diff --git a/.hgtags b/.hgtags deleted file mode 100644 index ef4ec35e2f27ed951ce5306b393547235e25a97f..0000000000000000000000000000000000000000 --- a/.hgtags +++ /dev/null @@ -1,664 +0,0 @@ -3cc80be736f24704e505ad8ddaa598dec3fa2ed3 jdk-9+181 -e2b70be325bd10dae4c06f74c46d70d480854916 jdk-9+179 -5b16a1c3ccffff2a82c88bb7ea894c4ff1c9ebde jdk-9+180 -43bf6f30fcba031ecf0cc7e511efe3a8179d0f77 jdk-9+176 -d9f6bc6ba599d0487dc18b2fbdb6c34eedf6f958 jdk-9+177 -bc9df7dd63ec76f50fafeb4acc44465044662f0a jdk-9+178 -994036e74ab805bcc09afa0646be17a725bec42f jdk-9+175 -94680c6d60ecd9ed3ffd1847706efde7eb947afc jdk-9+174 -6dd7fda42bab7ecf648cafb0a4e9b4ca11b3094f jdk-9+173 -dad6746278facbbea57dd462cb56fb743dc0a5f0 jdk-9+172 -643b5f18c2656fe91b69fea85b07b98d5fad394d jdk-9+171 -898cbe31fbdae2d25d141384fac746cc244a730c jdk-9+170 -c7efde2b60fc1ec04630be769d9ad60efb39c39c jdk-9+169 -8fd0a4569191f33c98ee90c2709174a342fefb0d jdk-9+167 -fcabc74bd44e56c7419d111d59b95669ecb33c55 jdk-9+168 -d3e973f1809606c67412361041ad197e50fe8cec jdk-9+166 -3965b747cfe1e6cbd66b8739da5a1ea6ec6985e9 jdk-9+165 -d16aebbb56d37f12e0c0b0a4fb427db65e1fb1a8 jdk-9+162 -18c41483a082e097ac2f5f983c1226ed94aa4215 jdk-9+163 -32db52c675e7d5bc413605d2e89b68b608b19be0 jdk-9+164 -fd1497902bbe3aa24b21f270ecdcb8de5f7aa9ac jdk-9+159 -6aa8be0c4e054fe8b3ab016ae00d16d680f92145 jdk-9+160 -f6883b1a5a6478437cd4181c4bd45328ab24feaf jdk-9+161 -fa3e76b477829afc4476f0b725cfaa440a6fd917 jdk-9+157 -b5015f742ba648184bb7fc547197bd33ebfde30d jdk-9+158 -1cc8dd79fd1cd13d36b385196271a29632c67c3b jdk7-b24 -bf2517e15f0c0f950e5b3143c4ca11e2df73dcc1 jdk7-b25 -5ae7db536e3fcf6be78e45b240a9058095e0ed38 jdk7-b26 -67052ac87fc927d048e62ec54ff42adb230d3f7c jdk7-b27 -18dc4ba4739a537fd146f77da51db16efce28da2 jdk7-b28 -bfe4572fd301a6fcd120373cdb2eff5d2da0c72c jdk7-b29 -bee4731164a06ddece1297ae58db24aca6a1c626 jdk7-b30 -cd8b8f500face60d1566d850857a7fccadbd383a jdk7-b31 -a9f1805e3ba9ca520cad199d522c84af5433e85a jdk7-b32 -6838c1a3296aaa3572364d2ce7d70826cee96286 jdk7-b33 -90cf935adb353bb0af4b46fb0677e841fd24c000 jdk7-b34 -6d909d5803e3a22850e6c4e5a75b888742ee7e20 jdk7-b35 -d718a441936196b93d8bc9f084933af9a4c2a350 jdk7-b36 -c2036bf76829c03b99108fffab52e20910a9be4f jdk7-b37 -a2879b2837f5a4c87e9542efe69ef138194af8ff jdk7-b38 -126f365cec6c3c2c72de934fa1c64b5f082b55b5 jdk7-b39 -3c53424bbe3bb77e01b468b4b0140deec33e11fc jdk7-b40 -3cb2a607c347934f8e7e86f840a094c28b08d9ea jdk7-b41 -caf58ffa084568990cbb3441f9ae188e36b31770 jdk7-b42 -41bd0a702bc8ec6feebd725a63e7c3227f82ab11 jdk7-b43 -5843778bda89b1d5ac8e1aa05e26930ac90b3145 jdk7-b44 -54dffad0bf066791a2793305875250c395011d5f jdk7-b45 -04b2620edc72de93671646e4720c5992c74ac8b5 jdk7-b46 -0c4657194eec95c08ba478aee9cfc3c295e41657 jdk7-b47 -1bf51a4c2627c2f0e0cbcc2cf0421bdb37f1f2b2 jdk7-b48 -6b84b04a80afe23262377c60913eebfc898f14c4 jdk7-b49 -5da0e6b9f4f18ef483c977337214b12ee0e1fc8f jdk7-b50 -a25c5ec5e40e07733d1ff9898a0abe36159288ff jdk7-b51 -7a90e89e36d103038f8667f6a7daae34ecfa1ad8 jdk7-b52 -d52186ee770dac57950536cd00ccbfdef360b04c jdk7-b53 -15096652c4d48dfb9fc0b2cb135304db94c65ba0 jdk7-b54 -c8b275d62d6b0a980c510e839b70292245863e85 jdk7-b55 -a8134c4ee2cf451cf9b5e1609f39d83ecd53acc5 jdk7-b56 -b44f05654c26fcd1f995e712992f9b07ffd7c0c6 jdk7-b57 -d60a9ce3c3eabf28f5d50ae839d18be04a551bc2 jdk7-b58 -c33e7d38c9210741dbc285507403a4b20bd802a0 jdk7-b59 -5a10e4d0b14d7beac53a7b2213ae6864afe1fd3e jdk7-b60 -dbb955b1ee59b876dd1f133952b557b48b1d7732 jdk7-b61 -6107cbff3130c747d243c25a7874cd59db5744a8 jdk7-b62 -dfd8506f74c3731bb169ce93c72612d78ee0413b jdk7-b63 -d22867c5f1b295a0a2b3b4bc8999a2676f6e20c3 jdk7-b64 -7d3bf00f3cc4f8125de1842521e7567f37dc84b8 jdk7-b65 -62109d1b9e7310f29ab51ca6f1d71b899c0ce6b0 jdk7-b66 -eb24af1404aec8aa140c4cd4d13d2839b150dd41 jdk7-b67 -bca2225b66d78c4bf4d9801f54cac7715a598650 jdk7-b68 -1b662b1ed14eb4ae31d5138a36c433b13d941dc5 jdk7-b69 -207f694795c448c17753eff1a2f50363106960c2 jdk7-b70 -c5d39b6be65cba0effb5f466ea48fe43764d0e0c jdk7-b71 -df4bcd06e1d0ab306efa5a44f24a409dc0c0c742 jdk7-b72 -ce74bd35ce948d629a356e168797f44b593b1578 jdk7-b73 -4e7661eaa211e186674f6cbefec4aef1144ac2a0 jdk7-b74 -946518568340c4e511549318f19f47f06b7f5f9b jdk7-b75 -09e0b33177af2b98a03c9ca19eedf61440bd1cf6 jdk7-b76 -1d0121b741f029dc4b828e4b36ba6fda92907dd7 jdk7-b77 -4061c66ba1af1a2e27c2c839ba887407dd3ce050 jdk7-b78 -e9c98378f6b9256c0595ef2985ca5899f0c0e274 jdk7-b79 -e6abd38682d237306d6c147c17538ec9e7f8e3a7 jdk7-b80 -dcc938ac40cc45f1ef454d76020b5db5d943001c jdk7-b81 -a30062be6d9ca1d48579826f870f85974300004e jdk7-b82 -34c8199936a1682aa8587857f44cfaf37c2b6381 jdk7-b83 -b1e55627a6980b9508854ed0c0f21d4f981b4494 jdk7-b84 -b6f633a93ae0ec4555ff4bf756f5e2150c9bdede jdk7-b85 -c94d9cc81f495d97817eba9d71b84fc45f7661a5 jdk7-b86 -b7456c473862048fa70ed8092313a4ef0a55d403 jdk7-b87 -7077b95d42f6b3942a8751bba033801ff50e5889 jdk7-b88 -44158f6d3b94c0fa020e33632532473d92d1ea96 jdk7-b89 -1d1927f9ec097b62c913921e2dfa5dbaf5dc325b jdk7-b90 -308ad8f68b8dd68e22d73dd490e110059b732422 jdk7-b91 -ff9031a745d9cc52318f2148e43ca3b07ee08098 jdk7-b92 -b5dab6a313fdff4c043250e4d9c8f66fd624d27e jdk7-b93 -8bb281f0f91582104d65d032be22522bfd2d8110 jdk7-b94 -654298d26561b76dfe3cfcffbbd7078080837300 jdk7-b95 -d260f892491e040ae385a8e6df59557a7d721abf jdk7-b96 -7e406ebed9a5968b584f3c3e6b60893b5d6d9741 jdk7-b97 -db6e660120446c407e2d908d52ec046592b21726 jdk7-b98 -c4c8a5bc54f66abc68cd185d9294042121922154 jdk7-b99 -2d6ba7a221915bdf0311acc5641c7f3875cb793e jdk7-b100 -2548ac036b8fca3326d058d758e6df8355a42469 jdk7-b101 -88db80c8e49cea352c2900f689600dc410761c1f jdk7-b102 -64770970865839b0443066370e7d476ef47e90cd jdk7-b103 -10bc903a228d3a8efdf46fb8c3fcf82a59b88bc5 jdk7-b104 -1ce7938efb03224ccc8b3cdd7803eb39e889539c jdk7-b105 -6bdae472f77205046703b685eff2ac4f7a0ecf4e jdk7-b106 -439de530aac531a360beedba6e2fe51e17292cc0 jdk7-b107 -044d31b99ef5609389fc771c422e722e5e224228 jdk7-b108 -e02b4d709e177d08d56130a4bc68061e4bbacc7d jdk7-b109 -a6442d6bc38a44152e0662688213ce4d2701f42a jdk7-b110 -69f3edf083477955b5bd2f754252c7504167d8e1 jdk7-b111 -f960f117f1623629f64203e2b09a92a8f6f14ff5 jdk7-b112 -1fee41c7ed2b3388970a756a85aa693c0de8407a jdk7-b113 -750c1ccb2f2d1ddfa95ab6c7f897fdab2f87f7e9 jdk7-b114 -9cb24917216bc68997154f6e9566c3de62acb2f4 jdk7-b115 -a4e6aa1f45ad23a6f083ed98d970b5006ea4d292 jdk7-b116 -228e73f288c543a8c34e2a54227103ae5649e6af jdk7-b117 -2e876e59938a853934aa738c811b26c452bd9fe8 jdk7-b118 -4951967a61b4dbbf514828879f57bd1a0d4b420b jdk7-b119 -8c840d3ab24f8d0f422b991638acb44b6ab1d98c jdk7-b120 -0ce0a2c3a6926677dc507839a820ab6625541e5a jdk7-b121 -6f09ea1c034f087916d2a8cf0d22be768400118f jdk7-b122 -142129d8599d1f56b29387e7f9a5fad53b6d61df jdk7-b123 -aa894c225b1a517b665ac2a58295217ea2245134 jdk7-b124 -f658ec2730fa29323c36d23c27e54c7219ef5e16 jdk7-b125 -f1df068076986679ea1105532a65529d63a89060 jdk7-b126 -f83cd8bd35c678f94e526990e03dc838d0ec2717 jdk7-b127 -7da3f5f30855dec6bf3a86529e87dee883b90c72 jdk7-b128 -6823ea7eb8eb6fab405d7edb7a5c2f690887a2fa jdk7-b129 -a36beda9b9de91231d92a2c529f21cc218fcf8d5 jdk7-b130 -d8af56da89bc0fc02a6b6ad78f51157a46d665ab jdk7-b131 -d61280d36755d1941fb487f554e8b7a6d0bca6a1 jdk7-b132 -fd444c61e7ed3d92b2a730da7c737b02191b682f jdk7-b133 -def8e16dd237a47fc067d66d4c616d7baaec6001 jdk7-b134 -f75a1efb141210901aabe00a834e0fc32bb8b337 jdk7-b135 -46acf76a533954cfd594bb88fdea79938abfbe20 jdk7-b136 -d1cf7d4ee16c341f5b8c7e7f1d68a8c412b6c693 jdk7-b137 -62b8e328f8c8c66c14b0713222116f2add473f3f jdk7-b138 -955488f34ca418f6cdab843d61c20d2c615637d9 jdk7-b139 -f4298bc3f4b6baa315643be06966f09684290068 jdk7-b140 -5d86d0c7692e8f4a58d430d68c03594e2d3403b3 jdk7-b141 -92bf0655022d4187e9b49c1400f98fb3392a4630 jdk7-b142 -4a05062d8c4dfa3edec3faf1052af28baba5adff jdk7-b143 -07a8728ad49ef6dfa469c3a8bf5ab1e9c80bed5c jdk7-b144 -8294c99e685a1f6d1d37c45cd97854cf74be771e jdk7-b145 -dca1e8a87e8f756f95b99bac8fe795750d42e1b0 jdk7-b146 -a2a589fc29543ed32919c78a1810ad93a6fcf5bc jdk7-b147 -de9223c94f9c710b3eebb599cd3586f36c8b94a9 jdk8-b01 -1b9d19620eb4606a25b1e28f86d66c8bfa867e06 jdk8-b02 -6815e85bf96d6d3875954f9777660372cd70d065 jdk8-b03 -31f5c34d78081572ad9a2401c0bb0c6b9711dd65 jdk8-b04 -c4f9ea1ecb55ff44e0dd21d2888ead308c86a3aa jdk8-b05 -429da7734bf491bccde2a752fae97e9f225896dc jdk8-b06 -bc5710332b294676661103bb20d47d2ea3ba8def jdk8-b07 -24ee504f80412770c6874836cd9e55b536427b1d jdk8-b08 -fbf3cabc9e3bb1fcf710941d777cb0400505fbe6 jdk8-b09 -f651ce87127980c58e3599daba964eba2f3b4026 jdk8-b10 -cc1f5ce8e504d350e0b0c28c5f84333f8d540132 jdk8-b11 -86db042b3385c338e17f7664447fdc7d406dd19e jdk8-b12 -4cc0ef72c812943743ef4765f1100e2fbe2b1a08 jdk8-b13 -9ffaa48dbfb0f5936c2b789867d0785faec7071d jdk8-b14 -b5060eae3b32fd9f884a09774338cd8186d7fafa jdk8-b15 -736a63b854f321c7824b7e47890135f80aee05e3 jdk8-b16 -f0eccb2946986fb9626efde7d8ed9c8192623f5c jdk8-b17 -885050364691ac1ac978305c63f3368a197fb04d jdk8-b18 -0ff7113a0882ec82d642cb9f0297b4e497807ced jdk8-b19 -6561530ea757c3f3a6fb171c9cc7b3885cdeca85 jdk8-b20 -b3a426170188f52981cf4573a2f14d487fddab0d jdk8-b21 -e8f03541af27e38aafb619b96863e17f65ffe53b jdk8-b22 -498124337041ad53cbaa7eb110f3d7acd6d4eac4 jdk8-b23 -7d3720d8c595d1519c31e9ff7366203fc2c61350 jdk8-b24 -0071a6d64113a35ba345bb1580c256de5ce17d3e jdk8-b25 -6c805d8ed4e5449ea5e4d158c7bdbd7b0b70efd1 jdk8-b26 -c51754cddc037b9609e202b9ed38363d8683e7a8 jdk8-b27 -16ba58282d117247f480aae7a79b88141ade52a3 jdk8-b28 -e070119aa56ee4dc5506c19d2c4d2eecab8ad429 jdk8-b29 -23da7804aca0c9c4e6e86532a1453125a76d95ee jdk8-b30 -bac81e9f7d57b75fba5ab31b571f3fe0dc08af69 jdk8-b31 -2c5208ccb863db936eab523f49450b3fcd230348 jdk8-b32 -a6e6d42203e6d35f9e8b31eac25b0021b4dd58ad jdk8-b33 -0ae89825c75c9492e44efb3aca3d9ee3d8a209df jdk8-b34 -f151d5833912a82cd4f203944da0305c3be83ecc jdk8-b35 -98ce9816ae089c959ba1e70fba98423a31c4e9fa jdk8-b36 -b3a91113026c99b0da010d41055719ab0d8938f0 jdk8-b37 -4cc5610a6dd6227da766ebf9742eb11ff5ded6c0 jdk8-b38 -35a5397278779a2f8f3013f81586dc8f30cb149d jdk8-b39 -6e4e654931b976304bf6e7b4d0d6db8f75bac5d9 jdk8-b40 -c029c972396cea042a0dc67c0f7ccf2fe68007d4 jdk8-b41 -5c5a64ec0839df5affe9394b99ff338c363acbca jdk8-b42 -69d8a827cdf9236be9694a46d75c710d71dac7d7 jdk8-b43 -7e981cb0ad6a194f1fa859f9ad47586db461f269 jdk8-b44 -9b19b2302c28f4da6d4078f66234abecfed5688a jdk8-b45 -600c9a1feb01633cbcf2341a43d1d21e6497ecd0 jdk8-b46 -b820143a6f1ce993c6e6f31db4d64de990f42654 jdk8-b47 -086271e35b0a419b38e8bda9bebd70693811df0a jdk8-b48 -cecd7026f30cbd83b0601925a7a5e059aec98138 jdk8-b49 -38fe5ab028908cf64dd73a43336ba3211577bfc3 jdk8-b50 -382651d28f2502d371eca751962232c0e535e57a jdk8-b51 -b67041a6cb508da18d2f5c7687e6a31e08bea4fc jdk8-b52 -c7aa5cca1c01689a7b1a92411daf83684af05a33 jdk8-b53 -7c6aa31ff1b2ae48c1c686ebe1aadf0c3da5be15 jdk8-b54 -319f583f66db47395fa86127dd3ddb729eb7c64f jdk8-b55 -ffe6bce5a521be40146af2ac03c509b7bac30595 jdk8-b56 -2c21c080b11b93efb3851e39e1363e45da805943 jdk8-b57 -479d3302a26d7607ba271d66973e59ebf58825b6 jdk8-b58 -3bd874584fc01aae92fbc8827e2bd04d8b6ace04 jdk8-b59 -5e3adc681779037a2d33b7be6f75680619085492 jdk8-b60 -cdaa6122185f9bf512dcd6600f56bfccc4824e8c jdk8-b61 -8d9d430b4244b95f5cf1ebe719f834a1ac5d6cd5 jdk8-b62 -21ee1dd7b809639284900a128b9b656a592ebc7a jdk8-b63 -70fa4b11f26522e69b51fd652215f60ce350bac3 jdk8-b64 -a2cf4d4a484378caea2e827ed604b2bbae58bdba jdk8-b65 -17820b958ae84f7c1cc6719319c8e2232f7a4f1d jdk8-b66 -76cc9bd3ece407d3a15d3bea537b57927973c5e7 jdk8-b67 -cb33628d4e8f11e879c371959e5948b66a53376f jdk8-b68 -adb5171c554e14cd86f618b5584f6e3d693d5889 jdk8-b69 -0d625373c69e2ad6f546fd88ab50c6c9aad01271 jdk8-b70 -a41ada2ed4ef735449531c6ebe6cec593d890a1c jdk8-b71 -6725b3961f987cf40f446d1c11cd324a3bec545f jdk8-b72 -fe94b40ffd9390f6cffcdf51c0389b0e6dde0c13 jdk8-b73 -f627eff819628822a0777af8062244352f2a29cf jdk8-b74 -f1478a6d25fddd311a84dcbfac50824cc1858bdd jdk8-b75 -f407160c280d1c5b00d314c535441ac26f195fee jdk8-b76 -d17eb2e13e362085e866d46235314c50cc4661cc jdk8-b77 -6d3dcd34b5b962ea1ef9eed0dafdee9e812401bc jdk8-b78 -a1313a8d90d17d363a3b2a645dc4030ec204b168 jdk8-b79 -3fa21fbf9be7e6b482af43aacb6a09acfa30bdb6 jdk8-b80 -e41d716405b209d3eddef8bd4240cec2bd34dcca jdk8-b81 -5e8c55025644730385a6f8fa029ecdb2d2c98a07 jdk8-b82 -bcebd3fdefc91abb9d7fa0c5af6211b3f8720da6 jdk8-b83 -d7ad0dfaa41151bd3a9ae46725b0aec3730a9cd0 jdk8-b84 -1872c12529090e1c1dbf567f02ad7ae6231b8f0c jdk8-b85 -da9a4c9312816451884aa6db6f18be51a07bff13 jdk8-b86 -5ebf6c63714de2c9dcf831074086d31daec819df jdk8-b87 -e517701a4d0e25ae9c7945bca6e1762a8c5d8aa6 jdk8-b88 -4dec41b3c5e3bb616f0c6f15830d940905aa5d16 jdk8-b89 -f09ab0c416185e3cba371e81bcb6a16060c90f44 jdk8-b90 -80b6c3172dc2cfceb022411292d290a967f9c728 jdk8-b91 -2fd6acba737b01e705e1f7c33588c922a3787f13 jdk8-b92 -b72ae39e1329fefae50d4690db4fde43f3841a95 jdk8-b93 -0d804e3b955dce406af6a79ac1cc35c696aff7fb jdk8-b94 -49fe9c8049132647ad38837a877dd473e6c9b0e5 jdk8-b95 -ea73f01b9053e7165e7ba80f242bafecbc6af712 jdk8-b96 -0a85476a0b9cb876d5666d45097dac68bef3fce1 jdk8-b97 -711eb4aa87de68de78250e0549980936bab53d54 jdk8-b98 -2d3875b0d18b3ad1c2bebf385a697e309e4005a4 jdk8-b99 -3d34036aae4ea90b2ca59712d5a69db3221f0875 jdk8-b100 -edb01c460d4cab21ff0ff13512df7b746efaa0e7 jdk8-b101 -bbe43d712fe08e650808d774861b256ccb34e500 jdk8-b102 -30a1d677a20c6a95f98043d8f20ce570304e3818 jdk8-b103 -b5ed503c26ad38869c247c5e32debec217fd056b jdk8-b104 -589f4fdc584e373a47cde0162e9eceec9165c381 jdk8-b105 -514b0b69fb9683ef52062fd962a3e0644431f64d jdk8-b106 -892889f445755790ae90e61775bfb59ddc6182b5 jdk8-b107 -74049f7a28b48c14910106a75d9f2504169c352e jdk8-b108 -af9a674e12a16da1a4bd53e4990ddb1121a21ef1 jdk8-b109 -b5d2bf482a3ea1cca08c994512804ffbc73de0a1 jdk8-b110 -b9a0f6c693f347a6f4b9bb994957f4eaa05bdedd jdk8-b111 -ad67c34f79c28a8e755f4a49f313868619d6702c jdk8-b112 -4a4dbcf7cb7d3e1a81beaa3b11cd909f69ebc79a jdk8-b113 -dfa34ab293faad9b543a24646dbb381bc3ab5586 jdk8-b114 -3dd9732b17034f45d111996d1d50287b05a3998c jdk8-b115 -aaf663f591aba43ec942263b15ba62759ce26a1e jdk8-b116 -31b0e03fcad73d7886b306b4c2e57ad270780d0d jdk8-b117 -f5b521ade7a35cea18df78ee86322207729f5611 jdk8-b118 -87b743b2263cc53955266411b7797b365a0fb050 jdk8-b119 -a1ee9743f4ee165eae59389a020f2552f895dac8 jdk8-b120 -13b877757b0b1c0d5813298df85364f41d7ba6fe jdk9-b00 -f130ca87de6637acae7d99fcd7a8573eea1cbaed jdk9-b01 -b32e2219736e42baaf45daf0ad67ed34f6033799 jdk9-b02 -7f655f31f9bcee618cf832f08176ad8c1ed3fdd3 jdk9-b03 -099891b1d86f3719e116ac717ffdafc90d037fb7 jdk9-b04 -dd311791ad6895a3989020dd6c6c46db87972ab8 jdk9-b05 -85dbdc227c5e11429b4fc4a8ba763f50107edd6e jdk9-b06 -c826d05f1fb0773f6a28caa763307dd30d90d36e jdk9-b07 -b47e021195757f8f45582124ea7cad48ccf5f872 jdk9-b08 -efe7dbc6088691757404e0c8745f894e3ca9c022 jdk9-b09 -8c0bdeecd7c0f9ce3f3762a51991f755cb3a972c jdk9-b10 -0809c9a4d36e6291f1c4384604c4bbf29e975722 jdk9-b11 -0d1f816217dce5e72187f167cc1816080cbeb453 jdk9-b12 -1a30593dcb9802faec3b6edb24d86ca088594e4e jdk9-b13 -97932f6ad950ae5a73a9da5c96e6e58503ff646b jdk9-b14 -74eb0778e4f2dbff6628e718378449fba27c4265 jdk9-b15 -4a09f5d30be844ac6f714bdb0f63d8c3c08b9a98 jdk9-b16 -410bccbded9e9cce80f1e13ad221e37ae97a3986 jdk9-b17 -c5495e25c7258ab5f96a1ae14610887d76d2be63 jdk9-b18 -2dcf544eb7ed5ac6a3f7813a32e33acea7442405 jdk9-b19 -89731ae72a761afdf4262e8b9513f302f6563f89 jdk9-b20 -28dd0c7beb3cad9cf95f17b4b5ad87eb447a4084 jdk9-b21 -9678e0db8ff6ed845d4c2ee4a3baf7f386a777e5 jdk9-b22 -39cfdc2dcaf3f195c55398e4e677ab053b07e3d2 jdk9-b23 -d9ce05f36ffec3e5e8af62a92455c1c66a63c320 jdk9-b24 -13a5c76976fe48e55c9727c25fae2d2ce7c05da0 jdk9-b25 -cd6f4557e7fea5799ff3762ed7a80a743e75d5fd jdk9-b26 -d06a6d3c66c08293b2a9650f3cc01fd55c620e65 jdk9-b27 -f4269e8f454eb77763ecee228a88ae102a9aef6e jdk9-b28 -c36c0092693707a8255561433647e8c3cd724ccd jdk9-b29 -b2287cac7813c70ed7f679d9a46fe774bd4005f8 jdk9-b30 -9d0e6639a4d71b63507dd94b1a028e963b27e798 jdk9-b31 -1b1ec4291abc0ba6da7bf79b754f08dd759a4a0c jdk9-b32 -f0c5e4b732da823bdaa4184133675f384e7cd68d jdk9-b33 -9618201c5df28a460631577fad1f61e96f775c34 jdk9-b34 -a137992d750c72f6f944f341aa19b0d0d96afe0c jdk9-b35 -41df50e7303daf73c0d661ef601c4fe250915de5 jdk9-b36 -b409bc51bc23cfd51f2bd04ea919ec83535af9d0 jdk9-b37 -948cceef81ba4cb34bc233e7cc5952951ff04e88 jdk9-b38 -4e7c4d692e934cb9023af8201e7c2b510e9c4ee1 jdk9-b39 -82f4cb44b2d7af2352f48568a64b7b6a5ae960cd jdk9-b40 -9fffb959eb4197ff806e4ac12244761815b4deee jdk9-b41 -3107be2ba9c6e208a0b86bc7100a141abbc5b5fb jdk9-b42 -6494b13f88a867026ee316b444d9a4fa589dd6bd jdk9-b43 -abbfccd659b91a7bb815d5e36fed635dcdd40f31 jdk9-b44 -bfc24ae2b900187585079bb11e66e459d1e525fe jdk9-b45 -722378bc599e38d9a1dd484de30f10dfd7b21438 jdk9-b46 -8327024a99559982b848e9c2191da9c0bf8838fd jdk9-b47 -b2f9702efbe95527ea3a991474fda23987ff1c5c jdk9-b48 -5b8db585a33c3cc48e70e688ceee57dd9271dc5d jdk9-b49 -1550b2f6b63d1411fa84dc7bbc6f04809aedb43f jdk9-b50 -6efe265424e3f1ea596408a1f71baf2de316c772 jdk9-b51 -d6224d6021459ac8b3832e822f5acc849fa944af jdk9-b52 -874d76e4699dfcd61ae1826c9fe0ddc1610ad598 jdk9-b53 -82cd31c5d6ca8d4c1653f4eb1c09eb2d9a3b2813 jdk9-b54 -c97e2d1bad9708d379793ba2a4c848eda14c741e jdk9-b55 -47544495db2d3d2edf0f85862d8715592fdb919f jdk9-b56 -ddb95d8f169b09544cc17e72a6baaff2400092f5 jdk9-b57 -f40752db7773ca0c737f2ad88371e35c57fdfed7 jdk9-b58 -da950f343762a856d69751570a4c07cfa68a415b jdk9-b59 -38f98cb6b33562a926ec3b79c7b34128be37647d jdk9-b60 -ac3f5a39d4ff14d70c365e12cf5ec8f2abd52a04 jdk9-b61 -e7dbbef69d12b6a74dfad331b7188e7f893e8d29 jdk9-b62 -989253a902c34dcb7564695161c9200a5fbb7412 jdk9-b63 -8ffdeabc7c2b9a8280bf46cae026ac46b4d31c26 jdk9-b64 -4915246064b2f89d5f00c96e758686b7fdad36a6 jdk9-b65 -ff3fc75f3214ad7e03595be1b0d0f38d887b6f0e jdk9-b66 -56166ce66037952fa21e9f680b31bf8eb47312c0 jdk9-b67 -5b500c93ce4822d47061cd518ff3f72d9d8cb5b5 jdk9-b68 -d69c968463f0ae5d0b45de3fc14fe65171b23948 jdk9-b69 -43d0179ee9de3bfffae3417f09e07eb6d8efc963 jdk9-b70 -f66c185284727f6e6ffd27e9c45ed2dd9da0a691 jdk9-b71 -61d2d0629b6dbf4c091dc86151ade1b3ef34fffe jdk9-b72 -9b3a9d72f07b40c648de79961679f42283af1bb5 jdk9-b73 -7c577fda1855d03c04546694d514678f596508c9 jdk9-b74 -f55df5cfe11c97e4b58998b76f5bd00a73cde12d jdk9-b75 -eeea9adfd1e3d075ef82148c00a4847a1aab4d26 jdk9-b76 -c25e882cee9622ec75c4e9d60633539a2f0a8809 jdk9-b77 -c8753d0be1778944dc512ec86a459941ea1ad2c3 jdk9-b78 -3966bd3b8167419aa05c6718a4af1cf54b1e3c58 jdk9-b79 -3c9f5bd909ae7187f24622ee4b69f8a5756a9271 jdk9-b80 -2050b3a0aadcb0e024bf798197421d58e54ec8bf jdk9-b81 -6521875cb63e1d0121b30af56ebbc36db078c4c6 jdk9-b82 -f61a63b7d1e52e307abc0bfc751203155d362ec4 jdk9-b83 -51b2db2fa04c16d767b66113dbf08c5349ce382a jdk9-b84 -8392405ab038b22e69a3728e17dbdd9e3d3a22ed jdk9-b85 -7db0663a5e968059fa7c772172187ebd60b6492d jdk9-b86 -1a52a30674cd28c24d4d388150336121f2e9ddf9 jdk9-b87 -16b4968f9bb8f34371b42c0ba483d76e91ba84d8 jdk9-b88 -4a0312f2894bcbe1fd20266c8fda8d983bd2fcf6 jdk9-b89 -d131f4b8433a79408f935eff9bf92a0664229b60 jdk9-b90 -8077fd2f055d31e50b46fcf62d9c035bc385a215 jdk9-b91 -f242d4332f563648426a1b0fa02d8741beba19ef jdk9-b92 -09206c6513b300e1ac8541f3be012e1a49312104 jdk9-b93 -25a2cab05cfbe6034b71d9e72d64c65b0572ce63 jdk9-b94 -5ac6287ec71aafe021cc839d8bc828108d23aaba jdk-9+95 -139f19d70350238e15e107945cea75082b6380b3 jdk-9+96 -4edcff1b9a8875eb6380a2165dfec599e8e3f7c0 jdk-9+97 -d00ad2d9049ac60815f70bff445e95df85648bd2 jdk-9+98 -f9bcdce2df26678c3fe468130b535c0342c69b89 jdk-9+99 -4379223f8806626852c46c52d4e7a27a584b406e jdk-9+100 -80f67512daa15cf37b4825c1c62a675d524d7c49 jdk-9+101 -2dc4c11fe48831854916d53c3913bdb7d49023ea jdk-9+102 -4a652e4ca9523422149958673033e0ac740d5e1e jdk-9+103 -086c682bd8c5f195c324f61e2c61fbcd0226d63b jdk-9+104 -db483b34fa7148d257a429acddbde9c13687dcae jdk-9+105 -6c644cca3f3fc2763e2ff7d669849a75d34543ba jdk-9+106 -1c076468bf7dad5b8f2ee5dcf66e2279caa3e208 jdk-9+107 -257b579d813201682931d6b42f0445ffe5b4210d jdk-9+108 -c870cb782aca71093d2584376f27f0cfbfec0e3a jdk-9+109 -4a95f4b1bd8bfce85dc02a593896749feab96c34 jdk-9+110 -a6614ff7bf09da74be1d0ef3d9755090d244697a jdk-9+111 -7359994942f8d8e723b584d66a3a92c2e9e95e5c jdk-9+112 -6072af7a98be3922f26bdce71b53bb3646cb2ac9 jdk-9+113 -c84d0cce090e161d736de69e941830adf8c2f87a jdk-9+114 -8d78fb40648dd221ce4ef19f9d5aa41ee1a3a884 jdk-9+115 -84aba7335005a3a47751dcf1f37935f97df9f99a jdk-9+116 -82b8d12a553f5617737c238cec060281d52e351c jdk-9+117 -7c04fcb12bd4a31570a238e663fa846dfa5ec3b8 jdk-9+118 -caf97b37ebec84288c112d21d3a60cb628cba1e8 jdk-9+119 -9330543436402b8f3bd070524846a464d8143557 jdk-9+120 -18e5cdecb37a2f03ba74f6c8f022858bcbaacf56 jdk-9+121 -7693aa00e131493ceb42b93305e2f014c9922a3b jdk-9+122 -d53037a90c441cb528dc41c30827985de0e67c62 jdk-9+123 -2a5697a98620c4f40e4a1a71478464399b8878de jdk-9+124 -3aa52182b3ad7c5b3a61cf05a59dd07e4c5884e5 jdk-9+125 -03e7b2c5ae345be3caf981d76ceb3efe5ff447f8 jdk-9+126 -8e45018bde9de4ad15b972ae62874bba52dba2d5 jdk-9+127 -5bf88dce615f6804f9e101a96ffa7c9dfb4fbbbe jdk-9+128 -e8373543a3f0f60589b7d72b1f9b172721124caf jdk-9+129 -e613affb88d178dc7c589f1679db113d589bddb4 jdk-9+130 -4d2a15091124488080d65848b704e25599b2aaeb jdk-9+131 -2e83d21d78cd9c1d52e6cd2599e9c8aa36ea1f52 jdk-9+132 -e17429a7e843c4a4ed3651458d0f950970edcbcc jdk-9+133 -a71210c0d9800eb6925b61ecd6198abd554f90ee jdk-9+134 -e384420383a5b79fa0012ebcb25d8f83cff7f777 jdk-9+135 -1b4b5d01aa11edf24b6fadbe3d2f3e411e3b02cd jdk-9+136 -9cb87c88ed851c0575b8ead753ea238ed5b544e9 jdk-9+137 -d273dfe9a126d3bffe92072547fef2cd1361b0eb jdk-9+138 -65477538bec32963dc41153d89c4417eb46c45fc jdk-9+139 -0875007901f7d364a08220b052f0c81003e9c8c5 jdk-9+140 -9aadd2163b568d76f8969ad2fb404a63733da359 jdk-9+141 -df0e03e3ca0ed1307793017dfc1a054c8726131c jdk-9+142 -d62173b931bf5b6bffc6e80a9060bb2e8b8efc75 jdk-9+143 -31f5023200d42185b70c4c00ba5672391e4642d0 jdk-9+144 -3ee4e7827413fa5c5c4fca58597b0ad89e921bfb jdk-9+145 -581331db696a62dd411926ba7fd437252252a71d jdk-9+146 -f4e854a77aa38749bd90f722b06974a56e7233d5 jdk-9+147 -5c71ea43933b6c7e8a85eb1a4eb2213011b95d82 jdk-9+148 -cf139f925da04c8bd7efd33270a0315d72b338d3 jdk-9+149 -17469f16fbb406ec9f0dd262ce776ab6efbc38f1 jdk-9+150 -37b95df0042ae0687324e1f7dc4a2519e230e704 jdk-9+151 -ab2c8b03c3284fcbdd157551a66f807e3a182d9b jdk-9+152 -d7034ff7f8e257e81c9f95c7785dd4eaaa3c2afc jdk-9+153 -8c70d170e62c0c58b5bc3ba666bd140399b98c9c jdk-10+0 -45b751afd11e6c05991cf4913c5a0ac3304fcc4e jdk-9+154 -f4aff695ffe05cfdb69d8af25a4ddc6a029754ea jdk-9+155 -06bce0388880b5ff8e040e4a9d72a3ea11dac321 jdk-9+156 -74116beae88a8f17a80301aa6c83865c82f10ece jdk-10+1 -4a79ad46e578112fce68f1af9dd931025cc235cb jdk-10+2 -d1cab6c7e608479be4ebfad48a25b0ed48600f62 jdk-10+3 -02253db2ace1422f576f58502fc7831ead77424b jdk-10+4 -f113ce12fe24fbd24acf02711372d9f1e1c12426 jdk-10+5 -1407b19a2ddf6baae162f5a1a5b96af473f4d7d1 jdk-10+6 -30e75693ae99fd8e47fd2f5116527aff1b59aff9 jdk-10+7 -c42dc7b58b4d4301ea676a76326fd9bbd403d595 jdk-10+8 -aa5b01f5e5620438fd39efdb2e2f6365a2c7d898 jdk-10+9 -b0f2b8ff25a2209b2c807785d75f20e5086bbfc2 jdk-10+10 -036dbf8b381798e5d31065109714d04d97bf98a4 jdk-10+11 -e6d70017f5b9adbb2ec82d826973d0251800a3c3 jdk-10+12 -9927a9f16738e240ab7014f0118f41e314ef8f99 jdk-10+13 -9ef5029b247b4d940080417a287440bbdbab995b jdk-10+14 -878e216039322cb3f0ecbd0944642a2b4e2593f3 jdk-10+15 -4bbea012e5676e8025ade2bcfab4d6581e6e9f4b jdk-10+16 -7db699468b4f84abbcc01647e5a964409737411a jdk-10+17 -3739654290616e533fc6f51bf9ad69ed47a6abba jdk-10+18 -14df107500cc3b8ab238c3e4ad2c74e12bfe6067 jdk-10+19 -4586bc5d28d13d3147b993e6237eaf29a7073bbb jdk-10+20 -a85884d55ce32799f5c7382b7ea4839052b362a2 jdk-10+21 -e5357aa85dadacc6562175ff74714fecfb4470cf jdk-10+22 -22850b3a55240253841b9a425ad60a7fcdb22d47 jdk-10+23 -3b201865d5c1f244f555cad58da599c9261286d8 jdk-10+24 -8eb5e3ccee560c28ac9b1df2670adac2b3d36fad jdk-10+25 -1129253d3bc728a2963ba411ab9dd1adf358fb6b jdk-10+26 -b87d7b5d5dedc1185e5929470f945b7378cdb3ad jdk-10+27 -92f08900cb3c0d694e5c529a676c1c9e5909193f jdk-10+28 -a6e591e12f122768f675428e1e5a838fd0e9c7ec jdk-10+29 -8fee80b92e65149f7414250fd5e34b6f35d417b4 jdk-10+30 -e6278add9ff28fab70fe1cc4c1d65f7363dc9445 jdk-10+31 -a2008587c13fa05fa2dbfcb09fe987576fbedfd1 jdk-10+32 -bbd692ad4fa300ecca7939ffbe3b1d5e52a28cc6 jdk-10+33 -89deac44e51517841491ba86ff44aa82a5ca96b3 jdk-10+34 -d8c634b016c628622c9abbdc6bf50509e5dedbec jdk-10+35 -0ee20aad71c4f33c426372b4c8bcc1235ce2ec08 jdk-11+0 -959f2f7cbaa6d2ee45d50029744efb219721576c jdk-10+36 -4f830b447edf04fb4a52151a5ad44d9bb60723cd jdk-10+37 -e569e83139fdfbecfeb3cd9014d560917787f158 jdk-10+38 -5b834ec962366e00d4445352a999a3ac14e26f64 jdk-10+39 -860326263d1f6a83996d7da0f4c66806ae4aa1eb jdk-10+40 -3eae36c6baa5f916a3024cf1513e22357e00185d jdk-10+41 -4b62b815b4f49970b91a952929cf50115c263cb3 jdk-10+42 -107413b070b92c88bde6230ceb4a19b579781068 jdk-10+43 -dfa46cfe56346884a61efdc30dc50f7505d66761 jdk-11+1 -03ae177c26b016353e5ea1cab6ffd051dfa086ca jdk-11+2 -663f20fc51091bd7f95d18448850ba091207b7bd jdk-10+44 -4f96cf952e71cb8a127334494faf28880c26181b jdk-10+45 -1fd4d6068f54561cfc67d54fc9ca84af7212c4f8 jdk-11+3 -e59941f7247d451fa7df9eaef3fce0f492f8420c jdk-11+4 -d5c43e9f08fb9a7c74aae0d48daf17f2ad2afaef jdk-11+5 -3acb379b86725c47e7f33358cb22efa8752ae532 jdk-11+6 -f7363de371c9a1f668bd0a01b7df3d1ddb9cc58b jdk-11+7 -755e1b55a4dff510f9639cdb5c5e82549a7e09b3 jdk-11+8 -0c3e252cea44f06aef570ef464950ab97c669970 jdk-11+9 -6fa770f9f8ab296e1ce255ec17ccf6d4e1051886 jdk-10+46 -69d7398038c54774d9395b6810e0cca335edc02c jdk-11+10 -e1e60f75cd39312a7f59d2a4f91d624e5aecc95e jdk-11+11 -3ab6ba9f94a9045a526d645af26c933235371d6f jdk-11+12 -758deedaae8406ae60147486107a54e9864aa7b0 jdk-11+13 -3595bd343b65f8c37818ebe6a4c343ddeb1a5f88 jdk-11+14 -a11c1cb542bbd1671d25b85efe7d09b983c48525 jdk-11+15 -02934b0d661b82b7fe1052a04998d2091352e08d jdk-11+16 -64e4b1686141e57a681936a8283983341484676e jdk-11+17 -e1b3def126240d5433902f3cb0e91a4c27f6db50 jdk-11+18 -36ca515343e00b021dcfc902e986d26ec994a2e5 jdk-11+19 -95aad0c785e497f1bade3955c4e4a677b629fa9d jdk-12+0 -9816d7cc655e53ba081f938b656e31971b8f097a jdk-11+20 -14708e1acdc3974f4539027cbbcfa6d69f83cf51 jdk-11+21 -00b16d0457e43d23f6ca5ade6b243edce62750a0 jdk-12+1 -9937ef7499dcd7673714517fd5e450410c14ba4e jdk-11+22 -69b438908512d3dfef5852c6a843a5778333a309 jdk-12+2 -1edcf36fe15f79d6228d1a63eb680878e2386480 jdk-11+23 -990db216e7199b2ba9989d8fa20b657e0ca7d969 jdk-12+3 -ea900a7dc7d77dee30865c60eabd87fc24b1037c jdk-11+24 -499b873761d8e8a1cc4aa649daf04cbe98cbce77 jdk-12+4 -331888ea4a788df801b1edf8836646cd25fc758b jdk-11+25 -f8696e0ab9b795030429fc3374ec03e378fd9ed7 jdk-12+5 -945ba9278a272a5477ffb1b3ea1b04174fed8036 jdk-11+26 -7939b3c4e4088bf4f70ec5bbd8030393b653372f jdk-12+6 -9d7d74c6f2cbe522e39fa22dc557fdd3f79b32ad jdk-11+27 -ef57958c7c511162da8d9a75f0b977f0f7ac464e jdk-12+7 -76072a077ee1d815152d45d1692c4b36c53c5c49 jdk-11+28 -492b366f8e5784cc4927c2c98f9b8a3f16c067eb jdk-12+8 -31b159f30fb281016c5f0c103552809aeda84063 jdk-12+9 -8f594f75e0547d4ca16649cb3501659e3155e81b jdk-12+10 -f0f5d23449d31f1b3580c8a73313918cafeaefd7 jdk-12+11 -15094d12a632f452a2064318a4e416d0c7a9ce0c jdk-12+12 -511a9946f83e3e3c7b9dbe1840367063fb39b4e1 jdk-12+13 -8897e41b327c0a5601c6ba2bba5d07f15a3ffc91 jdk-12+14 -8897e41b327c0a5601c6ba2bba5d07f15a3ffc91 jdk-12+14 -6f04692c7d5137ee34a6bd94c0c8a6c9219cb127 jdk-12+14 -f8626bcc169813a4b2a15880386b952719d1d6d1 jdk-12+15 -199658d1ef860cdc17055b4fd3e94b057f292fe9 jdk-12+16 -eefa65e142af305923d2adcd596fab9c639723a1 jdk-12+17 -e38473506688e0995e701fc7f77d5a91b438ef93 jdk-12+18 -dc1f9dec2018a37fedba47d8a2aedef99faaec64 jdk-12+19 -40098289d5804c3b5e7074bc75501a81e70d9b0d jdk-12+20 -f8fb0c86f2b3d24294d39c5685a628e1beb14ba7 jdk-12+21 -732bec44c89e8b93a38296bf690f97b7230c5b6d jdk-12+22 -eef755718cb24813031a842bbfc716a6cea18e9a jdk-12+23 -cc4098b3bc10d1c390384289025fea7b0d4b9e93 jdk-13+0 -7d4397b43fa305806160785a4c7210600d59581a jdk-12+24 -11033c4ada542f9c9a873314b6ecf60af19e8256 jdk-13+1 -7496df94b3b79f3da53925d2d137317715f11d97 jdk-12+25 -50677f43ac3df9a8684222b8893543c60f3aa0bd jdk-13+2 -de9fd809bb475401aad188eab2264226788aad81 jdk-12+26 -642346a11059b9f283110dc301a24ed43b76a94e jdk-13+3 -f15d443f97318e9b40e6f451e327ff69ed4ec361 jdk-12+27 -a47b8125b7cc9ef59619745c163975fe935b57ed jdk-13+4 -659b004b6a1bd8c31e766cbdf328d8f8473fd4d7 jdk-12+28 -e3ed960609927b5fdfd0a797159835cd83a81a31 jdk-13+5 -44f41693631f9b5ac78ff4d2bfabd6734fe46df2 jdk-12+29 -b5f05fe4a6f8b3996a000c20078b356d991ca8ec jdk-13+6 -6c377af36a5c4203f16aed8a5e4c2ecc08fcd8bd jdk-12+30 -021917019cda1c0c5853255322274f37693a2431 jdk-13+7 -b5f7bb57de2f797be34f6c75d45c3245ad37ab97 jdk-12+31 -a535ba736cabc6886acdff36de3a096c46e5ddc5 jdk-13+8 -4ce47bc1fb92cf94c6e3d1f49d582f02dcb851ab jdk-12+32 -c081f3ea6b9300265a4a34e38f970b1e3ddaae9f jdk-13+9 -b67884871b5fff79c5ef3eb8ac74dd48d71ea9b1 jdk-12+33 -8e069f7b4fabfe05d9f500783e6d56cb0196d25c jdk-13+10 -21ea4076a275a0f498afa517e9ee1b94a9cf0255 jdk-13+11 -1d7aec80147a6d92b101a76aef92f3ddc88bedf4 jdk-13+12 -b67884871b5fff79c5ef3eb8ac74dd48d71ea9b1 jdk-12-ga -83cace4142c8563b6a921787db02388e1bc48d01 jdk-13+13 -46cf212cdccaf4fb064d913b12004007d3322b67 jdk-13+14 -f855ec13aa2501ae184c8b3e0626a8cec9966116 jdk-13+15 -9d0ae9508d5337b0dc7cc4684be42888c4023755 jdk-13+16 -93b702d2a0cb9e32160208f6700aede1f8492773 jdk-13+17 -bebb82ef3434a25f8142edafec20165f07ac562d jdk-13+18 -a43d6467317d8f1e160f67aadec37919c9d64443 jdk-13+19 -6ccc7cd7931e34129f6b7e04988fc9a63958dde0 jdk-13+20 -f2f11d7f7f4e7128f8aba6ffa576cfa76fbf7d1a jdk-13+21 -181986c5476468bc2dd4532af49599003ee8af37 jdk-13+22 -b034d2dee5fc93d42a81b65e58ce3f91e42586ff jdk-13+23 -7e2238451585029680f126ccbb46d01f2ff5607f jdk-13+24 -22b3b7983adab54e318f75aeb94471f7a4429c1e jdk-14+0 -22b3b7983adab54e318f75aeb94471f7a4429c1e jdk-13+25 -2f4e214781a1d597ed36bf5a36f20928c6c82996 jdk-14+1 -0692b67f54621991ba7afbf23e55b788f3555e69 jdk-13+26 -43627549a488b7d0b4df8fad436e36233df89877 jdk-14+2 -b7f68ddec66f996ae3aad03291d129ca9f02482d jdk-13+27 -e64383344f144217c36196c3c8a2df8f588a2af3 jdk-14+3 -1e95931e7d8fa7e3899340a9c7cb28dbea50c10c jdk-13+28 -19d0b382f0869f72d4381b54fa129f1c74b6e766 jdk-14+4 -3081f39a3d30d63b112098386ac2bb027c2b7223 jdk-13+29 -0f1e29c77e50c7da11d83df410026392c4d1a28c jdk-14+5 -2e63fb0a885fa908a97bbb0da8d7c3de11536aca jdk-13+30 -443f7359b34d60e7821216ffc60f88b6ffe0ccdd jdk-14+6 -6a159c6c23ccd0029140ab91653442e412305ce5 jdk-13+31 -28ab01c067551ef158abaef08e154e1051ca0893 jdk-14+7 -929f37a9c35d530d4e866f6e832001aeb4cfb371 jdk-13+32 -c0023e364b6f130cb1e93747b796d8718d544db1 jdk-14+8 -9c250a7600e12bdb1e611835250af3204d4aa152 jdk-13+33 -18f189e69b29f8215a3500b875127ed4fb2d977a jdk-14+9 -ececb6dae777e622abda42c705fd984a42f46b5a jdk-14+10 -bf4c808a4488025a415f867e54c8b088417e08a0 jdk-14+11 -8570f22b9b6ac6bec673899b582150865696e425 jdk-14+12 -fbbe6672ae15deaf350a9e935290a36f57ba9c25 jdk-14+13 -cddef3bde924f3ff4f17f3d369280cf69d0450e5 jdk-14+14 -9c250a7600e12bdb1e611835250af3204d4aa152 jdk-13-ga -778fc2dcbdaa8981e07e929a2cacef979c72261e jdk-14+15 -d29f0181ba424a95d881aba5eabf2e393abcc70f jdk-14+16 -5c83830390baafb76a1fbe33443c57620bd45fb9 jdk-14+17 -e84d8379815ba0d3e50fb096d28c25894cb50b8c jdk-14+18 -9b67dd88a9313e982ec5f710a7747161bc8f0c23 jdk-14+19 -54ffb15c48399dd59922ee22bb592d815307e77c jdk-14+20 -c16ac7a2eba4e73cb4f7ee9294dd647860eebff0 jdk-14+21 -83810b7d12e7ff761ad3dd91f323a22dad96f108 jdk-14+22 -15936b142f86731afa4b1a2c0fe4a01e806c4944 jdk-14+23 -438337c846fb071900ddb6922bddf8b3e895a514 jdk-14+24 -17d242844fc9e7d18b3eac97426490a9c246119e jdk-14+25 -288777cf0702914e5266bc1e5d380eed9032ca41 jdk-14+26 -2c724dba4c3cf9516b2152e151c9aea66b21b30b jdk-15+0 -91a3f092682fc715d991a87eb6ec6f28886d2035 jdk-14+27 -63e17cf29bed191ea21020b4648c9cdf893f80f5 jdk-15+1 -2069b4bfd23b56b6fc659fba8b75aaaa23debbe0 jdk-14+28 -f33197adda9ad82fdef46ac0f7dc0126204f35b2 jdk-15+2 -563fa900fa17c290ae516c7a3a69e8c069dde304 jdk-14+29 -d05fcdf25717d85e80a3a39a6b719458b22be5fe jdk-15+3 -d54ce919da90dab361995bb4d87be9851f00537a jdk-14+30 -bb0a7975b31ded63d594ee8dbfc4d4ead587f79b jdk-15+4 -decd3d2953b640f1043ee76953ff89238bff92e8 jdk-14+31 -b97c1773ccafae4a8c16cc6aedb10b2a4f9a07ed jdk-15+5 -2776da28515e087cc8849acf1e131a65ea7e77b6 jdk-14+32 -ef7d53b4fccd4a0501b17d974e84f37aa99fa813 jdk-15+6 -f728b6c7f4910d6bd6070cb4dde8393f4ba95113 jdk-14+33 -e2bc57500c1b785837982f7ce8af6751387ed73b jdk-15+7 -a96bc204e3b31ddbf909b20088964112f052927e jdk-14+34 -c7d4f2849dbfb755fc5860b362a4044ea0c9e082 jdk-15+8 -4a87bb7ebfd7f6a25ec59a5982fe3607242777f8 jdk-14+35 -62b5bfef8d618e08e6f3a56cf1fb0e67e89e9cc2 jdk-15+9 -bc54620a3848c26cff9766e5e2a6e5ddab98ed18 jdk-14+36 -1bee69801aeea1a34261c93f35bc9de072a98704 jdk-15+10 -b2dd4028a6de4e40dda8b76109e4b5c6b294f980 jdk-15+11 -2ec0ff3042630ddbd3587e340fe0dd40391cb6c4 jdk-15+12 -1c06a8ee8acad4d93c782626a233693a73de0add jdk-15+13 -1d6ceb13e142665ea833fca01c8c8598e0ddd211 jdk-15+14 -bc54620a3848c26cff9766e5e2a6e5ddab98ed18 jdk-14-ga -82b7c62cf4cc56828a8fb724f57087967232a2a7 jdk-15+15 -5c7ec21f5d13f6eb5cd32288c69b8be2f9cac256 jdk-15+16 -dd5198db2e5b1ebcafe065d987c03ba9fcb50fc3 jdk-15+17 -44aef192b488a48cce12422394691a6b1d16b98e jdk-15+18 -7cc27caabe6e342151e8baf549beb07a9c755ec2 jdk-15+19 -46bca5e5e6fb26efd07245d26fe96a9c3260f51e jdk-15+20 -12b55fad80f30d24b1f8fdb3b947ea6465ef9518 jdk-15+21 -7223c6d610343fd8323af9d07d501e01fa1a7696 jdk-15+22 -f143729ca00ec14a98ea5c7f73acba88da97746e jdk-15+23 -497fd9f9129c4928fd5a876dd55e0daf6298b511 jdk-15+24 -90b266a84c06f1b3dc0ed8767856793e8c1c357e jdk-15+25 -0a32396f7a690015d22ca3328ac441a358295d90 jdk-15+26 -93813843680bbe1b7efbca56c03fd137f20a2c31 jdk-16+0 -93813843680bbe1b7efbca56c03fd137f20a2c31 jdk-15+27 -4a485c89d5a08b495961835f5308a96038678aeb jdk-16+1 -06c9f89459daba98395fad726100feb44f89ba71 jdk-15+28 -bcbe7b8a77b8971bc221c0be1bd2abb6fb68c2d0 jdk-16+2 -b58fc60580550a4a587cab729d8fd87223ad6932 jdk-15+29 -76810b3a88c8c641ae3850a8dfd7c40c984aea9d jdk-16+3 -6909e4a1f25bfe9a2727026f5845fc1fc44a36aa jdk-15+30 -e2622818f0bd30e736252eba101fe7d2c27f400b jdk-16+4 -a32f58c6b8be81877411767de7ba9c4cf087c1b5 jdk-15+31 -143e258f64af490010eb7e0bacc1cfaeceff0993 jdk-16+5 -2dad000726b8d5db9f3df647fb4949d88f269dd4 jdk-15+32 -4a8fd81d64bafa523cddb45f82805536edace106 jdk-16+6 -6b65f4e7a975628df51ef755b02642075390041d jdk-15+33 -c3a4a7ea7c304cabdacdc31741eb94c51351668d jdk-16+7 -b0817631d2f4395508cb10e81c3858a94d9ae4de jdk-15+34 -0a73d6f3aab48ff6d7e61e47f0bc2d87a054f217 jdk-16+8 -fd60c3146a024037cdd9be34c645bb793995a7cc jdk-15+35 -c075a286cc7df767cce28e8057d6ec5051786490 jdk-16+9 -b01985b4f88f554f97901e53e1ba314681dd9c19 jdk-16+10 -e3f940bd3c8fcdf4ca704c6eb1ac745d155859d5 jdk-15+36 -5c18d696c7ce724ca36df13933aa53f50e12b9e0 jdk-16+11 -fc8e62b399bd93d06e8d13dc3b384c450e853dcd jdk-16+12 -fd07cdb26fc70243ef23d688b545514f4ddf1c2b jdk-16+13 -36b29df125dc88f11657ce93b4998aa9ff5f5d41 jdk-16+14 diff --git a/doc/building.html b/doc/building.html index 1333a36771ab4c33577e093c6b289ff2848d51f6..97c9b2a4bb693d81a2a523047d65fbca18088497 100644 --- a/doc/building.html +++ b/doc/building.html @@ -891,7 +891,7 @@ spawn failed -

Add the flag --enable-reproducible-builds to your configure command line. This will turn on support for reproducible builds where it could otherwise be lacking.

+

Add the flag --enable-reproducible-build to your configure command line. This will turn on support for reproducible builds where it could otherwise be lacking.

diff --git a/doc/building.md b/doc/building.md index ac694ef84049b35238eb9494e54911cd55c302ae..033f99d3f5a8bc92970864728030e6c372984b02 100644 --- a/doc/building.md +++ b/doc/building.md @@ -1518,7 +1518,7 @@ non-determinism and make a larger part of the build reproducible: * Turn on build system support for reproducible builds -Add the flag `--enable-reproducible-builds` to your `configure` command line. +Add the flag `--enable-reproducible-build` to your `configure` command line. This will turn on support for reproducible builds where it could otherwise be lacking. diff --git a/doc/testing.html b/doc/testing.html index 1146400df805f5d5cc84536ea96b8b484c7dcf09..f647af91934b90e51739309a1bc9fb1729d2b87c 100644 --- a/doc/testing.html +++ b/doc/testing.html @@ -194,6 +194,8 @@ TEST FAILURE

Generate AOT modules before testing for the specified module, or set of modules. If multiple modules are specified, they should be separated by space (or, to help avoid quoting issues, the special value %20).

RETRY_COUNT

Retry failed tests up to a set number of times. Defaults to 0.

+

REPEAT_COUNT

+

Repeat the tests for a set number of times. Defaults to 0.

Gtest keywords

REPEAT

The number of times to repeat the tests (--gtest_repeat).

diff --git a/doc/testing.md b/doc/testing.md index 5dde4d11804d67a4450c7c2a1beb9227ccb8a221..bba5ae0941c7a808d9677045ba8f4434ae6a0d02 100644 --- a/doc/testing.md +++ b/doc/testing.md @@ -421,6 +421,10 @@ modules. If multiple modules are specified, they should be separated by space Retry failed tests up to a set number of times. Defaults to 0. +#### REPEAT_COUNT + +Repeat the tests for a set number of times. Defaults to 0. + ### Gtest keywords #### REPEAT diff --git a/make/CompileInterimLangtools.gmk b/make/CompileInterimLangtools.gmk index a6a42f6a9cd3c72e9b66c443d45ee27571bcde80..3fff64db1f81a4c26fe4988f58f2e0bf6acfc421 100644 --- a/make/CompileInterimLangtools.gmk +++ b/make/CompileInterimLangtools.gmk @@ -71,7 +71,7 @@ define SetupInterimModule SRC := $(BUILDTOOLS_OUTPUTDIR)/gensrc/$1.interim \ $$(wildcard $(SUPPORT_OUTPUTDIR)/gensrc/$1) \ $(TOPDIR)/src/$1/share/classes, \ - EXCLUDES := sun, \ + EXCLUDES := sun javax/tools/snippet-files, \ EXCLUDE_FILES := $(TOPDIR)/src/$1/share/classes/module-info.java \ Standard.java, \ EXTRA_FILES := $(BUILDTOOLS_OUTPUTDIR)/gensrc/$1.interim/module-info.java, \ diff --git a/make/Main.gmk b/make/Main.gmk index 75eee65ba84afddd1f787ddbac7d13c2fd205fd8..e5ea250bf5aad0dc77180792072e3e5bf2cce7f1 100644 --- a/make/Main.gmk +++ b/make/Main.gmk @@ -324,7 +324,7 @@ $(eval $(call SetupTarget, vscode-project-ccls, \ # aren't built until after libjava and libjvm are available to link to. $(eval $(call SetupTarget, demos-jdk, \ MAKEFILE := CompileDemos, \ - DEPS := java.base-libs exploded-image, \ + DEPS := java.base-libs exploded-image buildtools-jdk, \ )) $(eval $(call SetupTarget, test-image-demos-jdk, \ @@ -383,12 +383,12 @@ bootcycle-images: $(eval $(call SetupTarget, zip-security, \ MAKEFILE := ZipSecurity, \ - DEPS := java.base-java java.security.jgss-java java.security.jgss-libs, \ + DEPS := buildtools-jdk java.base-java java.security.jgss-java java.security.jgss-libs, \ )) $(eval $(call SetupTarget, zip-source, \ MAKEFILE := ZipSource, \ - DEPS := gensrc, \ + DEPS := buildtools-jdk gensrc, \ )) $(eval $(call SetupTarget, jrtfs-jar, \ @@ -508,13 +508,13 @@ $(eval $(call SetupTarget, docs-jdk-index, \ $(eval $(call SetupTarget, docs-zip, \ MAKEFILE := Docs, \ TARGET := docs-zip, \ - DEPS := docs-jdk, \ + DEPS := docs-jdk buildtools-jdk, \ )) $(eval $(call SetupTarget, docs-specs-zip, \ MAKEFILE := Docs, \ TARGET := docs-specs-zip, \ - DEPS := docs-jdk-specs, \ + DEPS := docs-jdk-specs buildtools-jdk, \ )) $(eval $(call SetupTarget, update-build-docs, \ diff --git a/make/RunTests.gmk b/make/RunTests.gmk index a2c8ea8101eac3fbdca236ec0a3f087acae94cc0..81540266ec0c68d8fd3f416dcc5a5fe9480cbf28 100644 --- a/make/RunTests.gmk +++ b/make/RunTests.gmk @@ -200,7 +200,7 @@ $(eval $(call SetTestOpt,FAILURE_HANDLER_TIMEOUT,JTREG)) $(eval $(call ParseKeywordVariable, JTREG, \ SINGLE_KEYWORDS := JOBS TIMEOUT_FACTOR FAILURE_HANDLER_TIMEOUT \ TEST_MODE ASSERT VERBOSE RETAIN MAX_MEM RUN_PROBLEM_LISTS \ - RETRY_COUNT MAX_OUTPUT $(CUSTOM_JTREG_SINGLE_KEYWORDS), \ + RETRY_COUNT REPEAT_COUNT MAX_OUTPUT $(CUSTOM_JTREG_SINGLE_KEYWORDS), \ STRING_KEYWORDS := OPTIONS JAVA_OPTIONS VM_OPTIONS KEYWORDS \ EXTRA_PROBLEM_LISTS LAUNCHER_OPTIONS \ $(CUSTOM_JTREG_STRING_KEYWORDS), \ @@ -745,6 +745,15 @@ define SetupRunJtregTestBody JTREG_RETAIN ?= fail,error JTREG_RUN_PROBLEM_LISTS ?= false JTREG_RETRY_COUNT ?= 0 + JTREG_REPEAT_COUNT ?= 0 + + ifneq ($$(JTREG_RETRY_COUNT), 0) + ifneq ($$(JTREG_REPEAT_COUNT), 0) + $$(info Error: Cannot use both JTREG_RETRY_COUNT and JTREG_REPEAT_COUNT together.) + $$(info Please choose one or the other.) + $$(error Cannot continue) + endif + endif ifneq ($$(JTREG_LAUNCHER_OPTIONS), ) $1_JTREG_LAUNCHER_OPTIONS += $$(JTREG_LAUNCHER_OPTIONS) @@ -869,6 +878,18 @@ define SetupRunJtregTestBody done endif + ifneq ($$(JTREG_REPEAT_COUNT), 0) + $1_COMMAND_LINE := \ + for i in {1..$$(JTREG_REPEAT_COUNT)}; do \ + $$(PRINTF) "\nRepeating Jtreg run: $$$$i out of $$(JTREG_REPEAT_COUNT)\n"; \ + $$($1_COMMAND_LINE); \ + if [ "`$$(CAT) $$($1_EXITCODE)`" != "0" ]; then \ + $$(PRINTF) "\nFailures detected, no more repeats.\n"; \ + break; \ + fi; \ + done + endif + run-test-$1: pre-run-test clean-workdir-$1 $$(call LogWarn) $$(call LogWarn, Running test '$$($1_TEST)') diff --git a/make/ToolsJdk.gmk b/make/ToolsJdk.gmk index 395a78602f626a83e7ecdd2fb45e980e6caf7119..af9def3a415ad5cf5b00ed12acca94cde7715d4c 100644 --- a/make/ToolsJdk.gmk +++ b/make/ToolsJdk.gmk @@ -82,6 +82,8 @@ TOOL_GENERATECACERTS = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_class TOOL_GENERATEEMOJIDATA = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \ build.tools.generateemojidata.GenerateEmojiData +TOOL_MAKEZIPREPRODUCIBLE = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \ + build.tools.makezipreproducible.MakeZipReproducible # TODO: There are references to the jdwpgen.jar in jdk/make/netbeans/jdwpgen/build.xml # and nbproject/project.properties in the same dir. Needs to be looked at. diff --git a/make/autoconf/basic.m4 b/make/autoconf/basic.m4 index 60b4097cba90e04cfb268a8367aab1acff26671a..e7fdab53050710b5ae499bab9fed5b720e6d62de 100644 --- a/make/autoconf/basic.m4 +++ b/make/autoconf/basic.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -94,11 +94,6 @@ AC_DEFUN_ONCE([BASIC_SETUP_PATHS], # Locate the directory of this script. AUTOCONF_DIR=$TOPDIR/make/autoconf - - # Setup username (for use in adhoc version strings etc) - # Outer [ ] to quote m4. - [ USERNAME=`$ECHO "$USER" | $TR -d -c '[a-z][A-Z][0-9]'` ] - AC_SUBST(USERNAME) ]) ############################################################################### diff --git a/make/autoconf/jdk-options.m4 b/make/autoconf/jdk-options.m4 index f8062d91b69a0735530850ad874f5d963f0844ce..cc4a44d39c96a872117af81095983daffc25f5ca 100644 --- a/make/autoconf/jdk-options.m4 +++ b/make/autoconf/jdk-options.m4 @@ -169,6 +169,23 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_JDK_OPTIONS], fi AC_SUBST(CACERTS_FILE) + # Choose cacerts source folder for user provided PEM files + AC_ARG_WITH(cacerts-src, [AS_HELP_STRING([--with-cacerts-src], + [specify alternative cacerts source folder containing certificates])]) + CACERTS_SRC="" + AC_MSG_CHECKING([for cacerts source]) + if test "x$with_cacerts_src" == x; then + AC_MSG_RESULT([default]) + else + CACERTS_SRC=$with_cacerts_src + if test ! -d "$CACERTS_SRC"; then + AC_MSG_RESULT([fail]) + AC_MSG_ERROR([Specified cacerts source folder "$CACERTS_SRC" does not exist]) + fi + AC_MSG_RESULT([$CACERTS_SRC]) + fi + AC_SUBST(CACERTS_SRC) + # Enable or disable unlimited crypto UTIL_ARG_ENABLE(NAME: unlimited-crypto, DEFAULT: true, RESULT: UNLIMITED_CRYPTO, DESC: [enable unlimited crypto policy]) @@ -702,7 +719,7 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_REPRODUCIBLE_BUILD], if test "x$OPENJDK_BUILD_OS" = xwindows && \ test "x$ALLOW_ABSOLUTE_PATHS_IN_OUTPUT" = xfalse && \ test "x$ENABLE_REPRODUCIBLE_BUILD" = xfalse; then - AC_MSG_NOTICE([On Windows it is not possible to combine --disable-reproducible-builds]) + AC_MSG_NOTICE([On Windows it is not possible to combine --disable-reproducible-build]) AC_MSG_NOTICE([with --disable-absolute-paths-in-output.]) AC_MSG_ERROR([Cannot continue]) fi diff --git a/make/autoconf/jdk-version.m4 b/make/autoconf/jdk-version.m4 index 60405d67bcb078779b7abacd6d69393fbd1dcb75..5312624d90c5f194d0aa8d553544be8e0fcd59bd 100644 --- a/make/autoconf/jdk-version.m4 +++ b/make/autoconf/jdk-version.m4 @@ -69,6 +69,17 @@ AC_DEFUN_ONCE([JDKVER_SETUP_JDK_VERSION_NUMBERS], AC_SUBST(JDK_RC_PLATFORM_NAME) AC_SUBST(HOTSPOT_VM_DISTRO) + # Setup username (for use in adhoc version strings etc) + AC_ARG_WITH([build-user], [AS_HELP_STRING([--with-build-user], + [build username to use in version strings])]) + if test "x$with_build_user" != x; then + USERNAME="$with_build_user" + else + # Outer [ ] to quote m4. + [ USERNAME=`$ECHO "$USER" | $TR -d -c '[a-z][A-Z][0-9]'` ] + fi + AC_SUBST(USERNAME) + # Set the JDK RC name AC_ARG_WITH(jdk-rc-name, [AS_HELP_STRING([--with-jdk-rc-name], [Set JDK RC name. This is used for FileDescription and ProductName properties diff --git a/make/autoconf/spec.gmk.in b/make/autoconf/spec.gmk.in index 72be922f1036f0b31ad6fc4ccd347f1e5eb69871..bc13f30e5f185b2df88cbddcce1e3ca13515a119 100644 --- a/make/autoconf/spec.gmk.in +++ b/make/autoconf/spec.gmk.in @@ -416,6 +416,8 @@ GTEST_FRAMEWORK_SRC := @GTEST_FRAMEWORK_SRC@ # Source file for cacerts CACERTS_FILE=@CACERTS_FILE@ +# Source folder for user provided cacerts PEM files +CACERTS_SRC=@CACERTS_SRC@ # Enable unlimited crypto policy UNLIMITED_CRYPTO=@UNLIMITED_CRYPTO@ diff --git a/make/common/TestFilesCompilation.gmk b/make/common/TestFilesCompilation.gmk index 01dc181d2c2ab2e3d89c93e18588b62c0cca929e..bb807ebf6b1761cd0bc94c0b517da4f8ca17ec26 100644 --- a/make/common/TestFilesCompilation.gmk +++ b/make/common/TestFilesCompilation.gmk @@ -62,11 +62,7 @@ define SetupTestFilesCompilationBody $1_OUTPUT_SUBDIR := lib $1_BASE_CFLAGS := $(CFLAGS_JDKLIB) $1_BASE_CXXFLAGS := $(CXXFLAGS_JDKLIB) - ifeq ($(call isTargetOs, windows), false) - $1_LDFLAGS := $(LDFLAGS_JDKLIB) $$(call SET_SHARED_LIBRARY_ORIGIN) -pthread - else - $1_LDFLAGS := $(LDFLAGS_JDKLIB) $$(call SET_SHARED_LIBRARY_ORIGIN) - endif + $1_LDFLAGS := $(LDFLAGS_JDKLIB) $$(call SET_SHARED_LIBRARY_ORIGIN) $1_COMPILATION_TYPE := LIBRARY else ifeq ($$($1_TYPE), PROGRAM) $1_PREFIX = exe diff --git a/make/common/ZipArchive.gmk b/make/common/ZipArchive.gmk index efa013f501ecf612c1f9bdf7c78476582471ad3d..592d1a60aa0f5c50cd63d1b3fa45afb4ee3e5db2 100644 --- a/make/common/ZipArchive.gmk +++ b/make/common/ZipArchive.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,9 @@ ifndef _ZIP_ARCHIVE_GMK _ZIP_ARCHIVE_GMK := 1 +# Depends on build tools for MakeZipReproducible +include ../ToolsJdk.gmk + ifeq (,$(_MAKEBASE_GMK)) $(error You must include MakeBase.gmk prior to including ZipArchive.gmk) endif @@ -51,6 +54,8 @@ endif # FOLLOW_SYMLINKS - Set to explicitly follow symlinks. Affects performance of # finding files. # ZIP_OPTIONS extra options to pass to zip +# REPRODUCIBLE override ENABLE_REPRODUCIBLE_BUILD (to make zip reproducible or not) + SetupZipArchive = $(NamedParamsMacroTemplate) define SetupZipArchiveBody @@ -124,6 +129,10 @@ define SetupZipArchiveBody ) \ ) + ifeq ($$($1_REPRODUCIBLE), ) + $1_REPRODUCIBLE := $$(ENABLE_REPRODUCIBLE_BUILD) + endif + # Use a slightly shorter name for logging, but with enough path to identify this zip. $1_NAME:=$$(subst $$(OUTPUTDIR)/,,$$($1_ZIP)) @@ -134,6 +143,8 @@ define SetupZipArchiveBody # dir is very small. # If zip has nothing to do, it returns 12 and would fail the build. Check for 12 # and only fail if it's not. + # For reproducible builds set the zip access & modify times to SOURCE_DATE_EPOCH + # by using a ziptmp folder to generate final zip from using MakeZipReproducible. $$($1_ZIP) : $$($1_ALL_SRCS) $$($1_EXTRA_DEPS) $$(call LogWarn, Updating $$($1_NAME)) $$(call MakeTargetDir) @@ -163,7 +174,18 @@ define SetupZipArchiveBody $$($1_ZIP_EXCLUDES_$$s) \ || test "$$$$?" = "12" \ ))$$(NEWLINE) \ - ) true \ + ) true + ifeq ($$($1_REPRODUCIBLE), true) + $$(call ExecuteWithLog, \ + $$(SUPPORT_OUTPUTDIR)/makezipreproducible/$$(patsubst $$(OUTPUTDIR)/%,%, $$@), \ + ($(RM) $$(SUPPORT_OUTPUTDIR)/ziptmp/$1/tmp.zip && \ + $(MKDIR) -p $$(SUPPORT_OUTPUTDIR)/ziptmp/$1 && \ + $(TOOL_MAKEZIPREPRODUCIBLE) -f $$(SUPPORT_OUTPUTDIR)/ziptmp/$1/tmp.zip \ + -t $(SOURCE_DATE_EPOCH) $$@ && \ + $(RM) $$@ && \ + $(MV) $$(SUPPORT_OUTPUTDIR)/ziptmp/$1/tmp.zip $$@ \ + )) + endif $(TOUCH) $$@ # Add zip to target list diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js index 80228aa718812bb2ac591341fe2973222bb3c585..24aeea9893df63d5dd918c5ad5eed3b6764881c8 100644 --- a/make/conf/jib-profiles.js +++ b/make/conf/jib-profiles.js @@ -450,7 +450,7 @@ var getJibProfilesProfiles = function (input, common, data) { "macosx-aarch64": { target_os: "macosx", target_cpu: "aarch64", - dependencies: ["devkit", "gtest"], + dependencies: ["devkit", "gtest", "pandoc"], configure_args: concat(common.configure_args_64bit, "--with-zlib=system", "--with-macosx-version-max=11.00.00"), }, @@ -1100,6 +1100,17 @@ var getJibProfilesDependencies = function (input, common) { environment_path: common.boot_jdk_home + "/bin" } + var pandoc_version; + if (input.build_cpu == "aarch64") { + if (input.build_os == "macosx") { + pandoc_version = "2.14.0.2+1.0"; + } else { + pandoc_version = "2.5+1.0"; + } + } else { + pandoc_version = "2.3.1+1.0"; + } + var makeBinDir = (input.build_os == "windows" ? input.get("gnumake", "install_path") + "/cygwin/bin" : input.get("gnumake", "install_path") + "/bin"); @@ -1212,7 +1223,7 @@ var getJibProfilesDependencies = function (input, common) { pandoc: { organization: common.organization, ext: "tar.gz", - revision: (input.build_cpu == 'aarch64' ? "2.5+1.0" : "2.3.1+1.0"), + revision: pandoc_version, module: "pandoc-" + input.build_platform, configure_args: "PANDOC=" + input.get("pandoc", "install_path") + "/pandoc/pandoc", environment_path: input.get("pandoc", "install_path") + "/pandoc" diff --git a/make/conf/version-numbers.conf b/make/conf/version-numbers.conf index 2d12d668a71051fad460bebc8a7a6027a2706e9f..3cb6b4341b52b0117a47495f6af8161df8a7c076 100644 --- a/make/conf/version-numbers.conf +++ b/make/conf/version-numbers.conf @@ -26,17 +26,17 @@ # Default version, product, and vendor information to use, # unless overridden by configure -DEFAULT_VERSION_FEATURE=18 +DEFAULT_VERSION_FEATURE=19 DEFAULT_VERSION_INTERIM=0 DEFAULT_VERSION_UPDATE=0 DEFAULT_VERSION_PATCH=0 DEFAULT_VERSION_EXTRA1=0 DEFAULT_VERSION_EXTRA2=0 DEFAULT_VERSION_EXTRA3=0 -DEFAULT_VERSION_DATE=2022-03-15 -DEFAULT_VERSION_CLASSFILE_MAJOR=62 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`" +DEFAULT_VERSION_DATE=2022-09-20 +DEFAULT_VERSION_CLASSFILE_MAJOR=63 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`" DEFAULT_VERSION_CLASSFILE_MINOR=0 DEFAULT_VERSION_DOCS_API_SINCE=11 -DEFAULT_ACCEPTABLE_BOOT_VERSIONS="17 18" -DEFAULT_JDK_SOURCE_TARGET_VERSION=18 +DEFAULT_ACCEPTABLE_BOOT_VERSIONS="17 18 19" +DEFAULT_JDK_SOURCE_TARGET_VERSION=19 DEFAULT_PROMOTED_VERSION_PRE=ea diff --git a/make/data/hotspot-symbols/symbols-unix b/make/data/hotspot-symbols/symbols-unix index d735f61b3a456bc9878949861043ebb995eceed7..9ec0c1ec7c7dc6b453052981336303ed1150872b 100644 --- a/make/data/hotspot-symbols/symbols-unix +++ b/make/data/hotspot-symbols/symbols-unix @@ -147,6 +147,7 @@ JVM_IsArrayClass JVM_IsCDSDumpingEnabled JVM_IsConstructorIx JVM_IsDumpingClassList +JVM_IsFinalizationEnabled JVM_IsHiddenClass JVM_IsInterface JVM_IsPrimitiveClass diff --git a/make/data/symbols/java.base-C.sym.txt b/make/data/symbols/java.base-C.sym.txt index 27896d9902f9ab2f9b99a45fc9e0f065d8bcf3a9..7a45fc1b49ed190a6f8fe14b9ba1138bbf8401e2 100644 --- a/make/data/symbols/java.base-C.sym.txt +++ b/make/data/symbols/java.base-C.sym.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ # ########################################################## # module name java.base -header exports java/io,java/lang,java/lang/annotation,java/lang/constant,java/lang/invoke,java/lang/module,java/lang/ref,java/lang/reflect,java/math,java/net,java/net/spi,java/nio,java/nio/channels,java/nio/channels/spi,java/nio/charset,java/nio/charset/spi,java/nio/file,java/nio/file/attribute,java/nio/file/spi,java/security,java/security/acl,java/security/cert,java/security/interfaces,java/security/spec,java/text,java/text/spi,java/time,java/time/chrono,java/time/format,java/time/temporal,java/time/zone,java/util,java/util/concurrent,java/util/concurrent/atomic,java/util/concurrent/locks,java/util/function,java/util/jar,java/util/regex,java/util/spi,java/util/stream,java/util/zip,javax/crypto,javax/crypto/interfaces,javax/crypto/spec,javax/net,javax/net/ssl,javax/security/auth,javax/security/auth/callback,javax/security/auth/login,javax/security/auth/spi,javax/security/auth/x500,javax/security/cert uses java/lang/System$LoggerFinder,java/net/ContentHandlerFactory,java/net/spi/URLStreamHandlerProvider,java/nio/channels/spi/AsynchronousChannelProvider,java/nio/channels/spi/SelectorProvider,java/nio/charset/spi/CharsetProvider,java/nio/file/spi/FileSystemProvider,java/nio/file/spi/FileTypeDetector,java/security/Provider,java/text/spi/BreakIteratorProvider,java/text/spi/CollatorProvider,java/text/spi/DateFormatProvider,java/text/spi/DateFormatSymbolsProvider,java/text/spi/DecimalFormatSymbolsProvider,java/text/spi/NumberFormatProvider,java/time/chrono/AbstractChronology,java/time/chrono/Chronology,java/time/zone/ZoneRulesProvider,java/util/spi/CalendarDataProvider,java/util/spi/CalendarNameProvider,java/util/spi/CurrencyNameProvider,java/util/spi/LocaleNameProvider,java/util/spi/ResourceBundleControlProvider,java/util/spi/ResourceBundleProvider,java/util/spi/TimeZoneNameProvider,java/util/spi/ToolProvider,javax/security/auth/spi/LoginModule,jdk/internal/logger/DefaultLoggerFinder,sun/text/spi/JavaTimeDateTimePatternProvider,sun/util/locale/provider/LocaleDataMetaInfo,sun/util/resources/LocaleData$CommonResourceBundleProvider,sun/util/resources/LocaleData$SupplementaryResourceBundleProvider,sun/util/spi/CalendarProvider provides interface\u0020;java/nio/file/spi/FileSystemProvider\u0020;impls\u0020;jdk/internal/jrtfs/JrtFileSystemProvider target linux-amd64 flags 8000 +header exports java/io,java/lang,java/lang/annotation,java/lang/constant,java/lang/invoke,java/lang/module,java/lang/ref,java/lang/reflect,java/math,java/net,java/net/spi,java/nio,java/nio/channels,java/nio/channels/spi,java/nio/charset,java/nio/charset/spi,java/nio/file,java/nio/file/attribute,java/nio/file/spi,java/security,java/security/acl,java/security/cert,java/security/interfaces,java/security/spec,java/text,java/text/spi,java/time,java/time/chrono,java/time/format,java/time/temporal,java/time/zone,java/util,java/util/concurrent,java/util/concurrent/atomic,java/util/concurrent/locks,java/util/function,java/util/jar,java/util/regex,java/util/spi,java/util/stream,java/util/zip,javax/crypto,javax/crypto/interfaces,javax/crypto/spec,javax/net,javax/net/ssl,javax/security/auth,javax/security/auth/callback,javax/security/auth/login,javax/security/auth/spi,javax/security/auth/x500,javax/security/cert,jdk/internal/event[jdk.jfr] uses java/lang/System$LoggerFinder,java/net/ContentHandlerFactory,java/net/spi/URLStreamHandlerProvider,java/nio/channels/spi/AsynchronousChannelProvider,java/nio/channels/spi/SelectorProvider,java/nio/charset/spi/CharsetProvider,java/nio/file/spi/FileSystemProvider,java/nio/file/spi/FileTypeDetector,java/security/Provider,java/text/spi/BreakIteratorProvider,java/text/spi/CollatorProvider,java/text/spi/DateFormatProvider,java/text/spi/DateFormatSymbolsProvider,java/text/spi/DecimalFormatSymbolsProvider,java/text/spi/NumberFormatProvider,java/time/chrono/AbstractChronology,java/time/chrono/Chronology,java/time/zone/ZoneRulesProvider,java/util/spi/CalendarDataProvider,java/util/spi/CalendarNameProvider,java/util/spi/CurrencyNameProvider,java/util/spi/LocaleNameProvider,java/util/spi/ResourceBundleControlProvider,java/util/spi/ResourceBundleProvider,java/util/spi/TimeZoneNameProvider,java/util/spi/ToolProvider,javax/security/auth/spi/LoginModule,jdk/internal/logger/DefaultLoggerFinder,sun/text/spi/JavaTimeDateTimePatternProvider,sun/util/locale/provider/LocaleDataMetaInfo,sun/util/resources/LocaleData$CommonResourceBundleProvider,sun/util/resources/LocaleData$SupplementaryResourceBundleProvider,sun/util/spi/CalendarProvider provides interface\u0020;java/nio/file/spi/FileSystemProvider\u0020;impls\u0020;jdk/internal/jrtfs/JrtFileSystemProvider target linux-amd64 flags 8000 class name java/io/FileInputStream -method name finalize descriptor ()V @@ -634,3 +634,13 @@ field name serialVersionUID descriptor J constantValue -1430015993304333921 flag class name javax/net/ssl/HttpsURLConnection method name getSSLSession descriptor ()Ljava/util/Optional; flags 1 signature ()Ljava/util/Optional; +class name jdk/internal/event/Event +header extends java/lang/Object flags 421 +method name descriptor ()V flags 4 +method name begin descriptor ()V flags 1 +method name end descriptor ()V flags 1 +method name commit descriptor ()V flags 1 +method name isEnabled descriptor ()Z flags 1 +method name shouldCommit descriptor ()Z flags 1 +method name set descriptor (ILjava/lang/Object;)V flags 1 + diff --git a/make/data/symbols/java.base-E.sym.txt b/make/data/symbols/java.base-E.sym.txt index 0aebcdd54d9e74e8177d879c0a2908a10dd7d66b..eaebf4b68f57c3e60f216b894691a36d6d1f4911 100644 --- a/make/data/symbols/java.base-E.sym.txt +++ b/make/data/symbols/java.base-E.sym.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ # ########################################################## # module name java.base -header exports java/io,java/lang,java/lang/annotation,java/lang/constant,java/lang/invoke,java/lang/module,java/lang/ref,java/lang/reflect,java/lang/runtime,java/math,java/net,java/net/spi,java/nio,java/nio/channels,java/nio/channels/spi,java/nio/charset,java/nio/charset/spi,java/nio/file,java/nio/file/attribute,java/nio/file/spi,java/security,java/security/cert,java/security/interfaces,java/security/spec,java/text,java/text/spi,java/time,java/time/chrono,java/time/format,java/time/temporal,java/time/zone,java/util,java/util/concurrent,java/util/concurrent/atomic,java/util/concurrent/locks,java/util/function,java/util/jar,java/util/regex,java/util/spi,java/util/stream,java/util/zip,javax/crypto,javax/crypto/interfaces,javax/crypto/spec,javax/net,javax/net/ssl,javax/security/auth,javax/security/auth/callback,javax/security/auth/login,javax/security/auth/spi,javax/security/auth/x500,javax/security/cert uses java/lang/System$LoggerFinder,java/net/ContentHandlerFactory,java/net/spi/URLStreamHandlerProvider,java/nio/channels/spi/AsynchronousChannelProvider,java/nio/channels/spi/SelectorProvider,java/nio/charset/spi/CharsetProvider,java/nio/file/spi/FileSystemProvider,java/nio/file/spi/FileTypeDetector,java/security/Provider,java/text/spi/BreakIteratorProvider,java/text/spi/CollatorProvider,java/text/spi/DateFormatProvider,java/text/spi/DateFormatSymbolsProvider,java/text/spi/DecimalFormatSymbolsProvider,java/text/spi/NumberFormatProvider,java/time/chrono/AbstractChronology,java/time/chrono/Chronology,java/time/zone/ZoneRulesProvider,java/util/spi/CalendarDataProvider,java/util/spi/CalendarNameProvider,java/util/spi/CurrencyNameProvider,java/util/spi/LocaleNameProvider,java/util/spi/ResourceBundleControlProvider,java/util/spi/ResourceBundleProvider,java/util/spi/TimeZoneNameProvider,java/util/spi/ToolProvider,javax/security/auth/spi/LoginModule,jdk/internal/logger/DefaultLoggerFinder,sun/text/spi/JavaTimeDateTimePatternProvider,sun/util/locale/provider/LocaleDataMetaInfo,sun/util/resources/LocaleData$CommonResourceBundleProvider,sun/util/resources/LocaleData$SupplementaryResourceBundleProvider,sun/util/spi/CalendarProvider provides interface\u0020;java/nio/file/spi/FileSystemProvider\u0020;impls\u0020;jdk/internal/jrtfs/JrtFileSystemProvider target linux-amd64 flags 8000 +header exports java/io,java/lang,java/lang/annotation,java/lang/constant,java/lang/invoke,java/lang/module,java/lang/ref,java/lang/reflect,java/lang/runtime,java/math,java/net,java/net/spi,java/nio,java/nio/channels,java/nio/channels/spi,java/nio/charset,java/nio/charset/spi,java/nio/file,java/nio/file/attribute,java/nio/file/spi,java/security,java/security/cert,java/security/interfaces,java/security/spec,java/text,java/text/spi,java/time,java/time/chrono,java/time/format,java/time/temporal,java/time/zone,java/util,java/util/concurrent,java/util/concurrent/atomic,java/util/concurrent/locks,java/util/function,java/util/jar,java/util/regex,java/util/spi,java/util/stream,java/util/zip,javax/crypto,javax/crypto/interfaces,javax/crypto/spec,javax/net,javax/net/ssl,javax/security/auth,javax/security/auth/callback,javax/security/auth/login,javax/security/auth/spi,javax/security/auth/x500,javax/security/cert,jdk/internal/event[jdk.jfr] uses java/lang/System$LoggerFinder,java/net/ContentHandlerFactory,java/net/spi/URLStreamHandlerProvider,java/nio/channels/spi/AsynchronousChannelProvider,java/nio/channels/spi/SelectorProvider,java/nio/charset/spi/CharsetProvider,java/nio/file/spi/FileSystemProvider,java/nio/file/spi/FileTypeDetector,java/security/Provider,java/text/spi/BreakIteratorProvider,java/text/spi/CollatorProvider,java/text/spi/DateFormatProvider,java/text/spi/DateFormatSymbolsProvider,java/text/spi/DecimalFormatSymbolsProvider,java/text/spi/NumberFormatProvider,java/time/chrono/AbstractChronology,java/time/chrono/Chronology,java/time/zone/ZoneRulesProvider,java/util/spi/CalendarDataProvider,java/util/spi/CalendarNameProvider,java/util/spi/CurrencyNameProvider,java/util/spi/LocaleNameProvider,java/util/spi/ResourceBundleControlProvider,java/util/spi/ResourceBundleProvider,java/util/spi/TimeZoneNameProvider,java/util/spi/ToolProvider,javax/security/auth/spi/LoginModule,jdk/internal/logger/DefaultLoggerFinder,sun/text/spi/JavaTimeDateTimePatternProvider,sun/util/locale/provider/LocaleDataMetaInfo,sun/util/resources/LocaleData$CommonResourceBundleProvider,sun/util/resources/LocaleData$SupplementaryResourceBundleProvider,sun/util/spi/CalendarProvider provides interface\u0020;java/nio/file/spi/FileSystemProvider\u0020;impls\u0020;jdk/internal/jrtfs/JrtFileSystemProvider target linux-amd64 flags 8000 class name java/io/PrintStream method name write descriptor ([B)V thrownTypes java/io/IOException flags 1 @@ -209,18 +209,18 @@ method name setCurrentBlocker descriptor (Ljava/lang/Object;)V flags 9 class name java/util/concurrent/locks/StampedLock header extends java/lang/Object implements java/io/Serializable flags 21 classAnnotations @Ljdk/Profile+Annotation;(value=I1) -method name tryWriteLock descriptor ()J flags 1 -method name writeLockInterruptibly descriptor ()J thrownTypes java/lang/InterruptedException flags 1 -method name tryReadLock descriptor ()J flags 1 -method name tryReadLock descriptor (JLjava/util/concurrent/TimeUnit;)J thrownTypes java/lang/InterruptedException flags 1 -method name readLockInterruptibly descriptor ()J thrownTypes java/lang/InterruptedException flags 1 -method name unlock descriptor (J)V flags 1 -method name tryWriteLock descriptor ()J -method name writeLockInterruptibly descriptor ()J -method name tryReadLock descriptor ()J -method name tryReadLock descriptor (JLjava/util/concurrent/TimeUnit;)J -method name readLockInterruptibly descriptor ()J -method name unlock descriptor (J)V +method name tryWriteLock descriptor ()J flags 1 +method name writeLockInterruptibly descriptor ()J thrownTypes java/lang/InterruptedException flags 1 +method name tryReadLock descriptor ()J flags 1 +method name tryReadLock descriptor (JLjava/util/concurrent/TimeUnit;)J thrownTypes java/lang/InterruptedException flags 1 +method name readLockInterruptibly descriptor ()J thrownTypes java/lang/InterruptedException flags 1 +method name unlock descriptor (J)V flags 1 -class name java/util/jar/Pack200 diff --git a/make/data/symbols/java.base-G.sym.txt b/make/data/symbols/java.base-G.sym.txt index 774c74459b4d6ea5cb74292161f98a904237306d..8196ef6be117ee881ef1031159b42677d8a23976 100644 --- a/make/data/symbols/java.base-G.sym.txt +++ b/make/data/symbols/java.base-G.sym.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,9 @@ # ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### # ########################################################## # +module name java.base +header exports java/io,java/lang,java/lang/annotation,java/lang/constant,java/lang/invoke,java/lang/module,java/lang/ref,java/lang/reflect,java/lang/runtime,java/math,java/net,java/net/spi,java/nio,java/nio/channels,java/nio/channels/spi,java/nio/charset,java/nio/charset/spi,java/nio/file,java/nio/file/attribute,java/nio/file/spi,java/security,java/security/cert,java/security/interfaces,java/security/spec,java/text,java/text/spi,java/time,java/time/chrono,java/time/format,java/time/temporal,java/time/zone,java/util,java/util/concurrent,java/util/concurrent/atomic,java/util/concurrent/locks,java/util/function,java/util/jar,java/util/regex,java/util/spi,java/util/stream,java/util/zip,javax/crypto,javax/crypto/interfaces,javax/crypto/spec,javax/net,javax/net/ssl,javax/security/auth,javax/security/auth/callback,javax/security/auth/login,javax/security/auth/spi,javax/security/auth/x500,javax/security/cert,jdk/internal/event[jdk.jfr],jdk/internal/vm/vector[jdk.incubator.vector] uses java/lang/System$LoggerFinder,java/net/ContentHandlerFactory,java/net/spi/URLStreamHandlerProvider,java/nio/channels/spi/AsynchronousChannelProvider,java/nio/channels/spi/SelectorProvider,java/nio/charset/spi/CharsetProvider,java/nio/file/spi/FileSystemProvider,java/nio/file/spi/FileTypeDetector,java/security/Provider,java/text/spi/BreakIteratorProvider,java/text/spi/CollatorProvider,java/text/spi/DateFormatProvider,java/text/spi/DateFormatSymbolsProvider,java/text/spi/DecimalFormatSymbolsProvider,java/text/spi/NumberFormatProvider,java/time/chrono/AbstractChronology,java/time/chrono/Chronology,java/time/zone/ZoneRulesProvider,java/util/spi/CalendarDataProvider,java/util/spi/CalendarNameProvider,java/util/spi/CurrencyNameProvider,java/util/spi/LocaleNameProvider,java/util/spi/ResourceBundleControlProvider,java/util/spi/ResourceBundleProvider,java/util/spi/TimeZoneNameProvider,java/util/spi/ToolProvider,javax/security/auth/spi/LoginModule,jdk/internal/logger/DefaultLoggerFinder,sun/text/spi/JavaTimeDateTimePatternProvider,sun/util/locale/provider/LocaleDataMetaInfo,sun/util/resources/LocaleData$CommonResourceBundleProvider,sun/util/resources/LocaleData$SupplementaryResourceBundleProvider,sun/util/spi/CalendarProvider provides interface\u0020;java/nio/file/spi/FileSystemProvider\u0020;impls\u0020;jdk/internal/jrtfs/JrtFileSystemProvider target linux-amd64 flags 8000 + class name java/io/PrintStream header extends java/io/FilterOutputStream implements java/lang/Appendable,java/io/Closeable flags 21 innerclass innerClass java/util/Locale$Category outerClass java/util/Locale innerClassName Category flags 4019 @@ -677,8 +680,8 @@ method name toString descriptor ()Ljava/lang/String; flags 1 class name java/security/spec/PSSParameterSpec -field name TRAILER_FIELD_BC descriptor I -field name TRAILER_FIELD_BC descriptor I constantValue 1 flags 19 -method name toString descriptor ()Ljava/lang/String; +field name TRAILER_FIELD_BC descriptor I constantValue 1 flags 19 method name toString descriptor ()Ljava/lang/String; flags 1 class name java/security/spec/RSAKeyGenParameterSpec @@ -1169,3 +1172,113 @@ header extends java/lang/Object implements java/security/spec/AlgorithmParameter class name javax/crypto/spec/SecretKeySpec header extends java/lang/Object implements java/security/spec/KeySpec,javax/crypto/SecretKey flags 21 +class name jdk/internal/event/Event +header extends java/lang/Object flags 421 +-method name descriptor ()V +-method name begin descriptor ()V +-method name end descriptor ()V +-method name commit descriptor ()V +-method name isEnabled descriptor ()Z +-method name shouldCommit descriptor ()Z +-method name set descriptor (ILjava/lang/Object;)V +method name descriptor ()V flags 4 +method name begin descriptor ()V flags 1 +method name end descriptor ()V flags 1 +method name commit descriptor ()V flags 1 +method name isEnabled descriptor ()Z flags 1 +method name shouldCommit descriptor ()Z flags 1 +method name set descriptor (ILjava/lang/Object;)V flags 1 + +class name jdk/internal/vm/vector/VectorSupport +header extends java/lang/Object nestMembers jdk/internal/vm/vector/VectorSupport$VectorMask,jdk/internal/vm/vector/VectorSupport$VectorShuffle,jdk/internal/vm/vector/VectorSupport$Vector,jdk/internal/vm/vector/VectorSupport$VectorPayload,jdk/internal/vm/vector/VectorSupport$VectorSpecies flags 21 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorShuffle outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorShuffle flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$Vector outerClass jdk/internal/vm/vector/VectorSupport innerClassName Vector flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorMask outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorMask flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorPayload outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorPayload flags 9 +field name VECTOR_OP_ABS descriptor I constantValue 0 flags 19 +field name VECTOR_OP_NEG descriptor I constantValue 1 flags 19 +field name VECTOR_OP_SQRT descriptor I constantValue 2 flags 19 +field name VECTOR_OP_ADD descriptor I constantValue 4 flags 19 +field name VECTOR_OP_SUB descriptor I constantValue 5 flags 19 +field name VECTOR_OP_MUL descriptor I constantValue 6 flags 19 +field name VECTOR_OP_DIV descriptor I constantValue 7 flags 19 +field name VECTOR_OP_MIN descriptor I constantValue 8 flags 19 +field name VECTOR_OP_MAX descriptor I constantValue 9 flags 19 +field name VECTOR_OP_AND descriptor I constantValue 10 flags 19 +field name VECTOR_OP_OR descriptor I constantValue 11 flags 19 +field name VECTOR_OP_XOR descriptor I constantValue 12 flags 19 +field name VECTOR_OP_FMA descriptor I constantValue 13 flags 19 +field name VECTOR_OP_LSHIFT descriptor I constantValue 14 flags 19 +field name VECTOR_OP_RSHIFT descriptor I constantValue 15 flags 19 +field name VECTOR_OP_URSHIFT descriptor I constantValue 16 flags 19 +field name VECTOR_OP_CAST descriptor I constantValue 17 flags 19 +field name VECTOR_OP_REINTERPRET descriptor I constantValue 18 flags 19 +field name BT_eq descriptor I constantValue 0 flags 19 +field name BT_ne descriptor I constantValue 4 flags 19 +field name BT_le descriptor I constantValue 5 flags 19 +field name BT_ge descriptor I constantValue 7 flags 19 +field name BT_lt descriptor I constantValue 3 flags 19 +field name BT_gt descriptor I constantValue 1 flags 19 +field name BT_overflow descriptor I constantValue 2 flags 19 +field name BT_no_overflow descriptor I constantValue 6 flags 19 +field name T_FLOAT descriptor I constantValue 6 flags 19 +field name T_DOUBLE descriptor I constantValue 7 flags 19 +field name T_BYTE descriptor I constantValue 8 flags 19 +field name T_SHORT descriptor I constantValue 9 flags 19 +field name T_INT descriptor I constantValue 10 flags 19 +field name T_LONG descriptor I constantValue 11 flags 19 +method name descriptor ()V flags 1 +method name broadcastCoerced descriptor (Ljava/lang/Class;Ljava/lang/Class;IJLjdk/internal/vm/vector/VectorSupport$VectorSpecies;Ljdk/internal/vm/vector/VectorSupport$BroadcastOperation;)Ljava/lang/Object; flags 9 signature ;>(Ljava/lang/Class<+TVM;>;Ljava/lang/Class;IJTS;Ljdk/internal/vm/vector/VectorSupport$BroadcastOperation;)TVM; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name shuffleIota descriptor (Ljava/lang/Class;Ljava/lang/Class;Ljdk/internal/vm/vector/VectorSupport$VectorSpecies;IIIILjdk/internal/vm/vector/VectorSupport$ShuffleIotaOperation;)Ljdk/internal/vm/vector/VectorSupport$VectorShuffle; flags 9 signature ;>(Ljava/lang/Class<*>;Ljava/lang/Class<*>;TS;IIIILjdk/internal/vm/vector/VectorSupport$ShuffleIotaOperation;)Ljdk/internal/vm/vector/VectorSupport$VectorShuffle; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name shuffleToVector descriptor (Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;Ljdk/internal/vm/vector/VectorSupport$VectorShuffle;ILjdk/internal/vm/vector/VectorSupport$ShuffleToVectorOperation;)Ljava/lang/Object; flags 9 signature ;E:Ljava/lang/Object;>(Ljava/lang/Class<*>;Ljava/lang/Class<*>;Ljava/lang/Class<*>;TSh;ILjdk/internal/vm/vector/VectorSupport$ShuffleToVectorOperation;)TVM; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name indexVector descriptor (Ljava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;ILjdk/internal/vm/vector/VectorSupport$VectorSpecies;Ljdk/internal/vm/vector/VectorSupport$IndexOperation;)Ljdk/internal/vm/vector/VectorSupport$Vector; flags 9 signature ;E:Ljava/lang/Object;S:Ljdk/internal/vm/vector/VectorSupport$VectorSpecies;>(Ljava/lang/Class<+TV;>;Ljava/lang/Class;ITV;ITS;Ljdk/internal/vm/vector/VectorSupport$IndexOperation;)TV; +method name reductionCoerced descriptor (ILjava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;Ljava/util/function/Function;)J flags 9 signature ;>(ILjava/lang/Class<*>;Ljava/lang/Class<*>;ITV;Ljava/util/function/Function;)J runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name extract descriptor (Ljava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;ILjdk/internal/vm/vector/VectorSupport$VecExtractOp;)J flags 9 signature ;>(Ljava/lang/Class<*>;Ljava/lang/Class<*>;ITV;ILjdk/internal/vm/vector/VectorSupport$VecExtractOp;)J runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name insert descriptor (Ljava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;IJLjdk/internal/vm/vector/VectorSupport$VecInsertOp;)Ljdk/internal/vm/vector/VectorSupport$Vector; flags 9 signature ;>(Ljava/lang/Class<+TV;>;Ljava/lang/Class<*>;ITV;IJLjdk/internal/vm/vector/VectorSupport$VecInsertOp;)TV; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name unaryOp descriptor (ILjava/lang/Class;Ljava/lang/Class;ILjava/lang/Object;Ljava/util/function/Function;)Ljava/lang/Object; flags 9 signature (ILjava/lang/Class<+TVM;>;Ljava/lang/Class<*>;ITVM;Ljava/util/function/Function;)TVM; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name binaryOp descriptor (ILjava/lang/Class;Ljava/lang/Class;ILjava/lang/Object;Ljava/lang/Object;Ljava/util/function/BiFunction;)Ljava/lang/Object; flags 9 signature (ILjava/lang/Class<+TVM;>;Ljava/lang/Class<*>;ITVM;TVM;Ljava/util/function/BiFunction;)TVM; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name ternaryOp descriptor (ILjava/lang/Class;Ljava/lang/Class;ILjava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljdk/internal/vm/vector/VectorSupport$TernaryOperation;)Ljava/lang/Object; flags 9 signature (ILjava/lang/Class<+TVM;>;Ljava/lang/Class<*>;ITVM;TVM;TVM;Ljdk/internal/vm/vector/VectorSupport$TernaryOperation;)TVM; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name load descriptor (Ljava/lang/Class;Ljava/lang/Class;ILjava/lang/Object;JLjava/lang/Object;ILjdk/internal/vm/vector/VectorSupport$VectorSpecies;Ljdk/internal/vm/vector/VectorSupport$LoadOperation;)Ljava/lang/Object; flags 9 signature ;>(Ljava/lang/Class<+TVM;>;Ljava/lang/Class;ILjava/lang/Object;JTC;ITS;Ljdk/internal/vm/vector/VectorSupport$LoadOperation;)TVM; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name loadWithMap descriptor (Ljava/lang/Class;Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/Object;JLjdk/internal/vm/vector/VectorSupport$Vector;Ljava/lang/Object;I[IILjdk/internal/vm/vector/VectorSupport$VectorSpecies;Ljdk/internal/vm/vector/VectorSupport$LoadVectorOperationWithMap;)Ljdk/internal/vm/vector/VectorSupport$Vector; flags 9 signature ;W:Ljdk/internal/vm/vector/VectorSupport$Vector;E:Ljava/lang/Object;S:Ljdk/internal/vm/vector/VectorSupport$VectorSpecies;>(Ljava/lang/Class<*>;Ljava/lang/Class;ILjava/lang/Class<*>;Ljava/lang/Object;JTW;TC;I[IITS;Ljdk/internal/vm/vector/VectorSupport$LoadVectorOperationWithMap;)TV; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name store descriptor (Ljava/lang/Class;Ljava/lang/Class;ILjava/lang/Object;JLjdk/internal/vm/vector/VectorSupport$Vector;Ljava/lang/Object;ILjdk/internal/vm/vector/VectorSupport$StoreVectorOperation;)V flags 9 signature ;>(Ljava/lang/Class<*>;Ljava/lang/Class<*>;ILjava/lang/Object;JTV;TC;ILjdk/internal/vm/vector/VectorSupport$StoreVectorOperation;)V runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name storeWithMap descriptor (Ljava/lang/Class;Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/Object;JLjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljava/lang/Object;I[IILjdk/internal/vm/vector/VectorSupport$StoreVectorOperationWithMap;)V flags 9 signature ;W:Ljdk/internal/vm/vector/VectorSupport$Vector;>(Ljava/lang/Class<*>;Ljava/lang/Class<*>;ILjava/lang/Class<*>;Ljava/lang/Object;JTW;TV;TC;I[IILjdk/internal/vm/vector/VectorSupport$StoreVectorOperationWithMap;)V runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name test descriptor (ILjava/lang/Class;Ljava/lang/Class;ILjava/lang/Object;Ljava/lang/Object;Ljava/util/function/BiFunction;)Z flags 9 signature (ILjava/lang/Class<*>;Ljava/lang/Class<*>;ITVM;TVM;Ljava/util/function/BiFunction;)Z runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name compare descriptor (ILjava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$VectorCompareOp;)Ljdk/internal/vm/vector/VectorSupport$VectorMask; flags 9 signature ;M:Ljdk/internal/vm/vector/VectorSupport$VectorMask;E:Ljava/lang/Object;>(ILjava/lang/Class<+TV;>;Ljava/lang/Class;Ljava/lang/Class<*>;ITV;TV;Ljdk/internal/vm/vector/VectorSupport$VectorCompareOp;)TM; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name rearrangeOp descriptor (Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$VectorShuffle;Ljdk/internal/vm/vector/VectorSupport$VectorRearrangeOp;)Ljdk/internal/vm/vector/VectorSupport$Vector; flags 9 signature ;Sh:Ljdk/internal/vm/vector/VectorSupport$VectorShuffle;E:Ljava/lang/Object;>(Ljava/lang/Class<+TV;>;Ljava/lang/Class;Ljava/lang/Class<*>;ITV;TSh;Ljdk/internal/vm/vector/VectorSupport$VectorRearrangeOp;)TV; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name blend descriptor (Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$VectorMask;Ljdk/internal/vm/vector/VectorSupport$VectorBlendOp;)Ljdk/internal/vm/vector/VectorSupport$Vector; flags 9 signature ;M:Ljdk/internal/vm/vector/VectorSupport$VectorMask;E:Ljava/lang/Object;>(Ljava/lang/Class<+TV;>;Ljava/lang/Class;Ljava/lang/Class<*>;ITV;TV;TM;Ljdk/internal/vm/vector/VectorSupport$VectorBlendOp;)TV; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name broadcastInt descriptor (ILjava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;ILjdk/internal/vm/vector/VectorSupport$VectorBroadcastIntOp;)Ljdk/internal/vm/vector/VectorSupport$Vector; flags 9 signature ;>(ILjava/lang/Class<+TV;>;Ljava/lang/Class<*>;ITV;ILjdk/internal/vm/vector/VectorSupport$VectorBroadcastIntOp;)TV; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name convert descriptor (ILjava/lang/Class;Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$VectorPayload;Ljdk/internal/vm/vector/VectorSupport$VectorSpecies;Ljdk/internal/vm/vector/VectorSupport$VectorConvertOp;)Ljdk/internal/vm/vector/VectorSupport$VectorPayload; flags 9 signature ;>(ILjava/lang/Class<*>;Ljava/lang/Class<*>;ILjava/lang/Class<*>;Ljava/lang/Class<*>;ITVIN;TS;Ljdk/internal/vm/vector/VectorSupport$VectorConvertOp;)TVOUT; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name maybeRebox descriptor (Ljava/lang/Object;)Ljava/lang/Object; flags 9 signature (TV;)TV; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name getMaxLaneCount descriptor (Ljava/lang/Class;)I flags 109 signature (Ljava/lang/Class<*>;)I +method name isNonCapturingLambda descriptor (Ljava/lang/Object;)Z flags 9 + +class name jdk/internal/vm/vector/VectorSupport$Vector +header extends jdk/internal/vm/vector/VectorSupport$VectorPayload nestHost jdk/internal/vm/vector/VectorSupport flags 21 signature Ljdk/internal/vm/vector/VectorSupport$VectorPayload; +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorPayload outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorPayload flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$Vector outerClass jdk/internal/vm/vector/VectorSupport innerClassName Vector flags 9 +method name descriptor (Ljava/lang/Object;)V flags 1 + +class name jdk/internal/vm/vector/VectorSupport$VectorMask +header extends jdk/internal/vm/vector/VectorSupport$VectorPayload nestHost jdk/internal/vm/vector/VectorSupport flags 21 signature Ljdk/internal/vm/vector/VectorSupport$VectorPayload; +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorPayload outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorPayload flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorMask outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorMask flags 9 +method name descriptor (Ljava/lang/Object;)V flags 1 + +class name jdk/internal/vm/vector/VectorSupport$VectorPayload +header extends java/lang/Object nestHost jdk/internal/vm/vector/VectorSupport flags 21 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorPayload outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorPayload flags 9 +method name descriptor (Ljava/lang/Object;)V flags 1 +method name getPayload descriptor ()Ljava/lang/Object; flags 14 + +class name jdk/internal/vm/vector/VectorSupport$VectorShuffle +header extends jdk/internal/vm/vector/VectorSupport$VectorPayload nestHost jdk/internal/vm/vector/VectorSupport flags 21 signature Ljdk/internal/vm/vector/VectorSupport$VectorPayload; +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorPayload outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorPayload flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorShuffle outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorShuffle flags 9 +method name descriptor (Ljava/lang/Object;)V flags 1 + +class name jdk/internal/vm/vector/VectorSupport$VectorSpecies +header extends java/lang/Object nestHost jdk/internal/vm/vector/VectorSupport flags 21 signature Ljava/lang/Object; +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 +method name descriptor ()V flags 1 + diff --git a/make/data/symbols/java.base-H.sym.txt b/make/data/symbols/java.base-H.sym.txt index 585d05063b31cc9d6102b42e7b45ca6fda279123..c6ef0d70aeb710f8fdd7a30c8cf1891715114844 100644 --- a/make/data/symbols/java.base-H.sym.txt +++ b/make/data/symbols/java.base-H.sym.txt @@ -27,7 +27,7 @@ # ########################################################## # module name java.base -header exports java/io,java/lang,java/lang/annotation,java/lang/constant,java/lang/invoke,java/lang/module,java/lang/ref,java/lang/reflect,java/lang/runtime,java/math,java/net,java/net/spi,java/nio,java/nio/channels,java/nio/channels/spi,java/nio/charset,java/nio/charset/spi,java/nio/file,java/nio/file/attribute,java/nio/file/spi,java/security,java/security/cert,java/security/interfaces,java/security/spec,java/text,java/text/spi,java/time,java/time/chrono,java/time/format,java/time/temporal,java/time/zone,java/util,java/util/concurrent,java/util/concurrent/atomic,java/util/concurrent/locks,java/util/function,java/util/jar,java/util/random,java/util/regex,java/util/spi,java/util/stream,java/util/zip,javax/crypto,javax/crypto/interfaces,javax/crypto/spec,javax/net,javax/net/ssl,javax/security/auth,javax/security/auth/callback,javax/security/auth/login,javax/security/auth/spi,javax/security/auth/x500,javax/security/cert uses java/lang/System$LoggerFinder,java/net/ContentHandlerFactory,java/net/spi/URLStreamHandlerProvider,java/nio/channels/spi/AsynchronousChannelProvider,java/nio/channels/spi/SelectorProvider,java/nio/charset/spi/CharsetProvider,java/nio/file/spi/FileSystemProvider,java/nio/file/spi/FileTypeDetector,java/security/Provider,java/text/spi/BreakIteratorProvider,java/text/spi/CollatorProvider,java/text/spi/DateFormatProvider,java/text/spi/DateFormatSymbolsProvider,java/text/spi/DecimalFormatSymbolsProvider,java/text/spi/NumberFormatProvider,java/time/chrono/AbstractChronology,java/time/chrono/Chronology,java/time/zone/ZoneRulesProvider,java/util/random/RandomGenerator,java/util/spi/CalendarDataProvider,java/util/spi/CalendarNameProvider,java/util/spi/CurrencyNameProvider,java/util/spi/LocaleNameProvider,java/util/spi/ResourceBundleControlProvider,java/util/spi/ResourceBundleProvider,java/util/spi/TimeZoneNameProvider,java/util/spi/ToolProvider,javax/security/auth/spi/LoginModule,jdk/internal/logger/DefaultLoggerFinder,sun/text/spi/JavaTimeDateTimePatternProvider,sun/util/locale/provider/LocaleDataMetaInfo,sun/util/resources/LocaleData$CommonResourceBundleProvider,sun/util/resources/LocaleData$SupplementaryResourceBundleProvider,sun/util/spi/CalendarProvider provides interface\u0020;java/nio/file/spi/FileSystemProvider\u0020;impls\u0020;jdk/internal/jrtfs/JrtFileSystemProvider,interface\u0020;java/util/random/RandomGenerator\u0020;impls\u0020;java/security/SecureRandom\u005C;u002C;java/util/Random\u005C;u002C;java/util/SplittableRandom target linux-amd64 flags 8000 +header exports java/io,java/lang,java/lang/annotation,java/lang/constant,java/lang/invoke,java/lang/module,java/lang/ref,java/lang/reflect,java/lang/runtime,java/math,java/net,java/net/spi,java/nio,java/nio/channels,java/nio/channels/spi,java/nio/charset,java/nio/charset/spi,java/nio/file,java/nio/file/attribute,java/nio/file/spi,java/security,java/security/cert,java/security/interfaces,java/security/spec,java/text,java/text/spi,java/time,java/time/chrono,java/time/format,java/time/temporal,java/time/zone,java/util,java/util/concurrent,java/util/concurrent/atomic,java/util/concurrent/locks,java/util/function,java/util/jar,java/util/random,java/util/regex,java/util/spi,java/util/stream,java/util/zip,javax/crypto,javax/crypto/interfaces,javax/crypto/spec,javax/net,javax/net/ssl,javax/security/auth,javax/security/auth/callback,javax/security/auth/login,javax/security/auth/spi,javax/security/auth/x500,javax/security/cert,jdk/internal/event[jdk.jfr],jdk/internal/vm/vector[jdk.incubator.vector] uses java/lang/System$LoggerFinder,java/net/ContentHandlerFactory,java/net/spi/URLStreamHandlerProvider,java/nio/channels/spi/AsynchronousChannelProvider,java/nio/channels/spi/SelectorProvider,java/nio/charset/spi/CharsetProvider,java/nio/file/spi/FileSystemProvider,java/nio/file/spi/FileTypeDetector,java/security/Provider,java/text/spi/BreakIteratorProvider,java/text/spi/CollatorProvider,java/text/spi/DateFormatProvider,java/text/spi/DateFormatSymbolsProvider,java/text/spi/DecimalFormatSymbolsProvider,java/text/spi/NumberFormatProvider,java/time/chrono/AbstractChronology,java/time/chrono/Chronology,java/time/zone/ZoneRulesProvider,java/util/random/RandomGenerator,java/util/spi/CalendarDataProvider,java/util/spi/CalendarNameProvider,java/util/spi/CurrencyNameProvider,java/util/spi/LocaleNameProvider,java/util/spi/ResourceBundleControlProvider,java/util/spi/ResourceBundleProvider,java/util/spi/TimeZoneNameProvider,java/util/spi/ToolProvider,javax/security/auth/spi/LoginModule,jdk/internal/logger/DefaultLoggerFinder,sun/text/spi/JavaTimeDateTimePatternProvider,sun/util/locale/provider/LocaleDataMetaInfo,sun/util/resources/LocaleData$CommonResourceBundleProvider,sun/util/resources/LocaleData$SupplementaryResourceBundleProvider,sun/util/spi/CalendarProvider provides interface\u0020;java/nio/file/spi/FileSystemProvider\u0020;impls\u0020;jdk/internal/jrtfs/JrtFileSystemProvider,interface\u0020;java/util/random/RandomGenerator\u0020;impls\u0020;java/security/SecureRandom\u005C;u002C;java/util/Random\u005C;u002C;java/util/SplittableRandom target linux-amd64 flags 8000 class name java/io/CharArrayReader method name read descriptor (Ljava/nio/CharBuffer;)I thrownTypes java/io/IOException flags 1 @@ -114,8 +114,8 @@ header extends java/lang/Object implements java/lang/annotation/Annotation flags class name java/lang/System -method name setSecurityManager descriptor (Ljava/lang/SecurityManager;)V -method name getSecurityManager descriptor ()Ljava/lang/SecurityManager; -method name getSecurityManager descriptor ()Ljava/lang/SecurityManager; flags 9 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="17") method name setSecurityManager descriptor (Ljava/lang/SecurityManager;)V flags 9 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="17")@Ljdk/internal/reflect/CallerSensitive; +method name getSecurityManager descriptor ()Ljava/lang/SecurityManager; flags 9 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="17") class name java/lang/Thread -method name checkAccess descriptor ()V @@ -313,8 +313,8 @@ field name SHA512_256 descriptor Ljava/security/spec/MGF1ParameterSpec; flags 19 class name java/security/spec/PSSParameterSpec -field name TRAILER_FIELD_BC descriptor I -field name TRAILER_FIELD_BC descriptor I constantValue 1 flags 19 -method name toString descriptor ()Ljava/lang/String; +field name TRAILER_FIELD_BC descriptor I constantValue 1 flags 19 method name toString descriptor ()Ljava/lang/String; flags 1 class name java/security/spec/RSAKeyGenParameterSpec @@ -470,8 +470,8 @@ method name splits descriptor ()Ljava/util/stream/Stream; flags 1 signature ()Lj method name splits descriptor (J)Ljava/util/stream/Stream; flags 1 signature (J)Ljava/util/stream/Stream; method name splits descriptor (Ljava/util/random/RandomGenerator$SplittableGenerator;)Ljava/util/stream/Stream; flags 1 signature (Ljava/util/random/RandomGenerator$SplittableGenerator;)Ljava/util/stream/Stream; method name splits descriptor (JLjava/util/random/RandomGenerator$SplittableGenerator;)Ljava/util/stream/Stream; flags 1 signature (JLjava/util/random/RandomGenerator$SplittableGenerator;)Ljava/util/stream/Stream; -method name split descriptor ()Ljava/util/random/RandomGenerator$SplittableGenerator; flags 1041 method name split descriptor (Ljava/util/random/RandomGenerator$SplittableGenerator;)Ljava/util/random/RandomGenerator$SplittableGenerator; flags 1041 +method name split descriptor ()Ljava/util/random/RandomGenerator$SplittableGenerator; flags 1041 class name java/util/TimeZone header extends java/lang/Object implements java/io/Serializable,java/lang/Cloneable flags 421 @@ -928,3 +928,32 @@ method name doAsPrivileged descriptor (Ljavax/security/auth/Subject;Ljava/securi class name javax/security/auth/SubjectDomainCombiner header extends java/lang/Object implements java/security/DomainCombiner flags 21 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="17") +class name jdk/internal/vm/vector/VectorSupport +field name VECTOR_OP_MASK_TRUECOUNT descriptor I constantValue 19 flags 19 +field name VECTOR_OP_MASK_FIRSTTRUE descriptor I constantValue 20 flags 19 +field name VECTOR_OP_MASK_LASTTRUE descriptor I constantValue 21 flags 19 +field name VECTOR_OP_TAN descriptor I constantValue 101 flags 19 +field name VECTOR_OP_TANH descriptor I constantValue 102 flags 19 +field name VECTOR_OP_SIN descriptor I constantValue 103 flags 19 +field name VECTOR_OP_SINH descriptor I constantValue 104 flags 19 +field name VECTOR_OP_COS descriptor I constantValue 105 flags 19 +field name VECTOR_OP_COSH descriptor I constantValue 106 flags 19 +field name VECTOR_OP_ASIN descriptor I constantValue 107 flags 19 +field name VECTOR_OP_ACOS descriptor I constantValue 108 flags 19 +field name VECTOR_OP_ATAN descriptor I constantValue 109 flags 19 +field name VECTOR_OP_ATAN2 descriptor I constantValue 110 flags 19 +field name VECTOR_OP_CBRT descriptor I constantValue 111 flags 19 +field name VECTOR_OP_LOG descriptor I constantValue 112 flags 19 +field name VECTOR_OP_LOG10 descriptor I constantValue 113 flags 19 +field name VECTOR_OP_LOG1P descriptor I constantValue 114 flags 19 +field name VECTOR_OP_POW descriptor I constantValue 115 flags 19 +field name VECTOR_OP_EXP descriptor I constantValue 116 flags 19 +field name VECTOR_OP_EXPM1 descriptor I constantValue 117 flags 19 +field name VECTOR_OP_HYPOT descriptor I constantValue 118 flags 19 +field name BT_unsigned_compare descriptor I constantValue 16 flags 19 +field name BT_ule descriptor I constantValue 21 flags 19 +field name BT_uge descriptor I constantValue 23 flags 19 +field name BT_ult descriptor I constantValue 19 flags 19 +field name BT_ugt descriptor I constantValue 17 flags 19 +method name maskReductionCoerced descriptor (ILjava/lang/Class;Ljava/lang/Class;ILjava/lang/Object;Ljdk/internal/vm/vector/VectorSupport$VectorMaskOp;)I flags 9 signature (ILjava/lang/Class<+TM;>;Ljava/lang/Class<*>;ITM;Ljdk/internal/vm/vector/VectorSupport$VectorMaskOp;)I runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; + diff --git a/make/data/symbols/java.base-I.sym.txt b/make/data/symbols/java.base-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..4657f5cfcfe5de77dda6bfd95159bf520300a05e --- /dev/null +++ b/make/data/symbols/java.base-I.sym.txt @@ -0,0 +1,742 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name java.base +header exports java/io,java/lang,java/lang/annotation,java/lang/constant,java/lang/invoke,java/lang/module,java/lang/ref,java/lang/reflect,java/lang/runtime,java/math,java/net,java/net/spi,java/nio,java/nio/channels,java/nio/channels/spi,java/nio/charset,java/nio/charset/spi,java/nio/file,java/nio/file/attribute,java/nio/file/spi,java/security,java/security/cert,java/security/interfaces,java/security/spec,java/text,java/text/spi,java/time,java/time/chrono,java/time/format,java/time/temporal,java/time/zone,java/util,java/util/concurrent,java/util/concurrent/atomic,java/util/concurrent/locks,java/util/function,java/util/jar,java/util/random,java/util/regex,java/util/spi,java/util/stream,java/util/zip,javax/crypto,javax/crypto/interfaces,javax/crypto/spec,javax/net,javax/net/ssl,javax/security/auth,javax/security/auth/callback,javax/security/auth/login,javax/security/auth/spi,javax/security/auth/x500,javax/security/cert,jdk/internal/event[jdk.jfr],jdk/internal/vm/vector[jdk.incubator.vector] uses java/lang/System$LoggerFinder,java/net/ContentHandlerFactory,java/net/spi/InetAddressResolverProvider,java/net/spi/URLStreamHandlerProvider,java/nio/channels/spi/AsynchronousChannelProvider,java/nio/channels/spi/SelectorProvider,java/nio/charset/spi/CharsetProvider,java/nio/file/spi/FileSystemProvider,java/nio/file/spi/FileTypeDetector,java/security/Provider,java/text/spi/BreakIteratorProvider,java/text/spi/CollatorProvider,java/text/spi/DateFormatProvider,java/text/spi/DateFormatSymbolsProvider,java/text/spi/DecimalFormatSymbolsProvider,java/text/spi/NumberFormatProvider,java/time/chrono/AbstractChronology,java/time/chrono/Chronology,java/time/zone/ZoneRulesProvider,java/util/random/RandomGenerator,java/util/spi/CalendarDataProvider,java/util/spi/CalendarNameProvider,java/util/spi/CurrencyNameProvider,java/util/spi/LocaleNameProvider,java/util/spi/ResourceBundleControlProvider,java/util/spi/ResourceBundleProvider,java/util/spi/TimeZoneNameProvider,java/util/spi/ToolProvider,javax/security/auth/spi/LoginModule,jdk/internal/logger/DefaultLoggerFinder,sun/text/spi/JavaTimeDateTimePatternProvider,sun/util/locale/provider/LocaleDataMetaInfo,sun/util/resources/LocaleData$CommonResourceBundleProvider,sun/util/resources/LocaleData$SupplementaryResourceBundleProvider,sun/util/spi/CalendarProvider provides interface\u0020;java/nio/file/spi/FileSystemProvider\u0020;impls\u0020;jdk/internal/jrtfs/JrtFileSystemProvider,interface\u0020;java/util/random/RandomGenerator\u0020;impls\u0020;java/security/SecureRandom\u005C;u002C;java/util/Random\u005C;u002C;java/util/SplittableRandom target linux-amd64 flags 8000 + +class name java/io/FileInputStream +method name transferTo descriptor (Ljava/io/OutputStream;)J thrownTypes java/io/IOException flags 1 + +class name java/io/ObjectInputStream$GetField +-method name get descriptor (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; +method name get descriptor (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; thrownTypes java/io/IOException,java/lang/ClassNotFoundException flags 401 + +class name java/io/PrintStream +header extends java/io/FilterOutputStream implements java/lang/Appendable,java/io/Closeable flags 21 +innerclass innerClass java/util/Locale$Category outerClass java/util/Locale innerClassName Category flags 4019 +method name charset descriptor ()Ljava/nio/charset/Charset; flags 1 + +class name java/lang/AbstractStringBuilder +header extends java/lang/Object implements java/lang/Appendable,java/lang/CharSequence flags 420 +innerclass innerClass java/util/Spliterator$OfInt outerClass java/util/Spliterator innerClassName OfInt flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/lang/Compiler +header extends java/lang/Object flags 31 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="9") + +class name java/lang/Deprecated +header extends java/lang/Object implements java/lang/annotation/Annotation flags 2601 runtimeAnnotations @Ljava/lang/annotation/Documented;@Ljava/lang/annotation/Retention;(value=eLjava/lang/annotation/RetentionPolicy;RUNTIME;)@Ljava/lang/annotation/Target;(value={eLjava/lang/annotation/ElementType;CONSTRUCTOR;eLjava/lang/annotation/ElementType;FIELD;eLjava/lang/annotation/ElementType;LOCAL_VARIABLE;eLjava/lang/annotation/ElementType;METHOD;eLjava/lang/annotation/ElementType;PACKAGE;eLjava/lang/annotation/ElementType;MODULE;eLjava/lang/annotation/ElementType;PARAMETER;eLjava/lang/annotation/ElementType;TYPE;}) + +class name java/lang/Enum +-method name finalize descriptor ()V +method name finalize descriptor ()V flags 14 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="18") + +class name java/lang/IllegalCallerException +header extends java/lang/RuntimeException flags 21 + +class name java/lang/LayerInstantiationException +header extends java/lang/RuntimeException flags 21 + +class name java/lang/Math +method name divideExact descriptor (II)I flags 9 +method name divideExact descriptor (JJ)J flags 9 +method name floorDivExact descriptor (II)I flags 9 +method name floorDivExact descriptor (JJ)J flags 9 +method name ceilDivExact descriptor (II)I flags 9 +method name ceilDivExact descriptor (JJ)J flags 9 +method name unsignedMultiplyHigh descriptor (JJ)J flags 9 runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name ceilDiv descriptor (II)I flags 9 +method name ceilDiv descriptor (JI)J flags 9 +method name ceilDiv descriptor (JJ)J flags 9 +method name ceilMod descriptor (II)I flags 9 +method name ceilMod descriptor (JI)I flags 9 +method name ceilMod descriptor (JJ)J flags 9 + +class name java/lang/NamedPackage +header extends java/lang/Object flags 20 + +class name java/lang/Object +-method name finalize descriptor ()V +method name finalize descriptor ()V thrownTypes java/lang/Throwable flags 4 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="9") + +class name java/lang/Runtime +-method name exec descriptor (Ljava/lang/String;)Ljava/lang/Process; +-method name exec descriptor (Ljava/lang/String;[Ljava/lang/String;)Ljava/lang/Process; +-method name exec descriptor (Ljava/lang/String;[Ljava/lang/String;Ljava/io/File;)Ljava/lang/Process; +-method name runFinalization descriptor ()V +method name exec descriptor (Ljava/lang/String;)Ljava/lang/Process; thrownTypes java/io/IOException flags 1 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="18") +method name exec descriptor (Ljava/lang/String;[Ljava/lang/String;)Ljava/lang/Process; thrownTypes java/io/IOException flags 1 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="18") +method name exec descriptor (Ljava/lang/String;[Ljava/lang/String;Ljava/io/File;)Ljava/lang/Process; thrownTypes java/io/IOException flags 1 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="18") +method name runFinalization descriptor ()V flags 1 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="18") + +class name java/lang/StrictMath +method name divideExact descriptor (II)I flags 9 +method name divideExact descriptor (JJ)J flags 9 +method name floorDivExact descriptor (II)I flags 9 +method name floorDivExact descriptor (JJ)J flags 9 +method name ceilDivExact descriptor (II)I flags 9 +method name ceilDivExact descriptor (JJ)J flags 9 +method name unsignedMultiplyHigh descriptor (JJ)J flags 9 +method name ceilDiv descriptor (II)I flags 9 +method name ceilDiv descriptor (JI)J flags 9 +method name ceilDiv descriptor (JJ)J flags 9 +method name ceilMod descriptor (II)I flags 9 +method name ceilMod descriptor (JI)I flags 9 +method name ceilMod descriptor (JJ)J flags 9 + +class name java/lang/SuppressWarnings +header extends java/lang/Object implements java/lang/annotation/Annotation flags 2601 runtimeAnnotations @Ljava/lang/annotation/Target;(value={eLjava/lang/annotation/ElementType;TYPE;eLjava/lang/annotation/ElementType;FIELD;eLjava/lang/annotation/ElementType;METHOD;eLjava/lang/annotation/ElementType;PARAMETER;eLjava/lang/annotation/ElementType;CONSTRUCTOR;eLjava/lang/annotation/ElementType;LOCAL_VARIABLE;eLjava/lang/annotation/ElementType;MODULE;})@Ljava/lang/annotation/Retention;(value=eLjava/lang/annotation/RetentionPolicy;SOURCE;) + +class name java/lang/System +-method name runFinalization descriptor ()V +method name runFinalization descriptor ()V flags 9 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="18") + +class name java/lang/Thread +-method name stop descriptor ()V +method name stop descriptor ()V flags 11 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="1.2") + +class name java/lang/constant/ClassDesc +header extends java/lang/Object implements java/lang/constant/ConstantDesc,java/lang/invoke/TypeDescriptor$OfField sealed true flags 601 signature Ljava/lang/Object;Ljava/lang/constant/ConstantDesc;Ljava/lang/invoke/TypeDescriptor$OfField; +innerclass innerClass java/lang/invoke/TypeDescriptor$OfField outerClass java/lang/invoke/TypeDescriptor innerClassName OfField flags 609 + +class name java/lang/constant/ConstantDesc +header extends java/lang/Object sealed true flags 601 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/lang/constant/DirectMethodHandleDesc +header extends java/lang/Object implements java/lang/constant/MethodHandleDesc nestMembers java/lang/constant/DirectMethodHandleDesc$Kind sealed true flags 601 +innerclass innerClass java/lang/constant/DirectMethodHandleDesc$Kind outerClass java/lang/constant/DirectMethodHandleDesc innerClassName Kind flags 4019 + +class name java/lang/constant/MethodHandleDesc +header extends java/lang/Object implements java/lang/constant/ConstantDesc sealed true flags 601 +innerclass innerClass java/lang/constant/DirectMethodHandleDesc$Kind outerClass java/lang/constant/DirectMethodHandleDesc innerClassName Kind flags 4019 + +class name java/lang/constant/MethodTypeDesc +header extends java/lang/Object implements java/lang/constant/ConstantDesc,java/lang/invoke/TypeDescriptor$OfMethod sealed true flags 601 signature Ljava/lang/Object;Ljava/lang/constant/ConstantDesc;Ljava/lang/invoke/TypeDescriptor$OfMethod; +innerclass innerClass java/lang/invoke/TypeDescriptor$OfMethod outerClass java/lang/invoke/TypeDescriptor innerClassName OfMethod flags 609 +innerclass innerClass java/lang/invoke/TypeDescriptor$OfField outerClass java/lang/invoke/TypeDescriptor innerClassName OfField flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/lang/invoke/CallSite +header extends java/lang/Object flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/lang/invoke/LambdaMetafactory +header extends java/lang/Object flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/lang/invoke/MethodHandle +-method name asType descriptor (Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; +method name asType descriptor (Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; flags 11 + +class name java/lang/invoke/StringConcatException +header extends java/lang/Exception flags 21 + +class name java/lang/module/Configuration +header extends java/lang/Object flags 31 +innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/lang/module/FindException +header extends java/lang/RuntimeException flags 21 + +class name java/lang/module/InvalidModuleDescriptorException +header extends java/lang/RuntimeException flags 21 + +class name java/lang/module/ModuleReader +header extends java/lang/Object implements java/io/Closeable flags 601 + +class name java/lang/module/ModuleReference +header extends java/lang/Object flags 421 + +class name java/lang/module/ResolutionException +header extends java/lang/RuntimeException flags 21 + +class name java/lang/module/ResolvedModule +header extends java/lang/Object flags 31 + +class name java/lang/reflect/AccessibleObject +header extends java/lang/Object implements java/lang/reflect/AnnotatedElement flags 21 classAnnotations @Ljdk/Profile+Annotation;(value=I1) + +class name java/lang/reflect/AnnotatedElement +header extends java/lang/Object flags 601 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/lang/reflect/Executable +header extends java/lang/reflect/AccessibleObject implements java/lang/reflect/Member,java/lang/reflect/GenericDeclaration sealed true flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/lang/reflect/InaccessibleObjectException +header extends java/lang/RuntimeException flags 21 + +class name java/lang/reflect/Method +-method name invoke descriptor (Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; +method name invoke descriptor (Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; thrownTypes java/lang/IllegalAccessException,java/lang/reflect/InvocationTargetException flags 81 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive;@Ljdk/internal/vm/annotation/ForceInline;@Ljdk/internal/vm/annotation/IntrinsicCandidate; + +class name java/net/DatagramSocket +header extends java/lang/Object implements java/io/Closeable flags 21 classAnnotations @Ljdk/Profile+Annotation;(value=I1) + +class name java/net/InetAddress +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/net/spi/InetAddressResolver$LookupPolicy outerClass java/net/spi/InetAddressResolver innerClassName LookupPolicy flags 19 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/io/ObjectOutputStream$PutField outerClass java/io/ObjectOutputStream innerClassName PutField flags 409 +innerclass innerClass java/net/spi/InetAddressResolverProvider$Configuration outerClass java/net/spi/InetAddressResolverProvider innerClassName Configuration flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/net/ServerSocket +-method name setSoTimeout descriptor (I)V +-method name getSoTimeout descriptor ()I +-method name setReceiveBufferSize descriptor (I)V +-method name getReceiveBufferSize descriptor ()I +method name setSoTimeout descriptor (I)V thrownTypes java/net/SocketException flags 1 +method name getSoTimeout descriptor ()I thrownTypes java/io/IOException flags 1 +method name setReceiveBufferSize descriptor (I)V thrownTypes java/net/SocketException flags 1 +method name getReceiveBufferSize descriptor ()I thrownTypes java/net/SocketException flags 1 + +class name java/net/SocketImpl +header extends java/lang/Object implements java/net/SocketOptions flags 421 + +class name java/net/spi/InetAddressResolver +header extends java/lang/Object nestMembers java/net/spi/InetAddressResolver$LookupPolicy flags 601 +innerclass innerClass java/net/spi/InetAddressResolver$LookupPolicy outerClass java/net/spi/InetAddressResolver innerClassName LookupPolicy flags 19 +method name lookupByName descriptor (Ljava/lang/String;Ljava/net/spi/InetAddressResolver$LookupPolicy;)Ljava/util/stream/Stream; thrownTypes java/net/UnknownHostException flags 401 signature (Ljava/lang/String;Ljava/net/spi/InetAddressResolver$LookupPolicy;)Ljava/util/stream/Stream; +method name lookupByAddress descriptor ([B)Ljava/lang/String; thrownTypes java/net/UnknownHostException flags 401 + +class name java/net/spi/InetAddressResolver$LookupPolicy +header extends java/lang/Object nestHost java/net/spi/InetAddressResolver flags 31 +innerclass innerClass java/net/spi/InetAddressResolver$LookupPolicy outerClass java/net/spi/InetAddressResolver innerClassName LookupPolicy flags 19 +field name IPV4 descriptor I constantValue 1 flags 19 +field name IPV6 descriptor I constantValue 2 flags 19 +field name IPV4_FIRST descriptor I constantValue 4 flags 19 +field name IPV6_FIRST descriptor I constantValue 8 flags 19 +method name of descriptor (I)Ljava/net/spi/InetAddressResolver$LookupPolicy; flags 9 +method name characteristics descriptor ()I flags 1 + +class name java/net/spi/InetAddressResolverProvider +header extends java/lang/Object nestMembers java/net/spi/InetAddressResolverProvider$Configuration flags 421 +innerclass innerClass java/net/spi/InetAddressResolverProvider$Configuration outerClass java/net/spi/InetAddressResolverProvider innerClassName Configuration flags 609 +method name get descriptor (Ljava/net/spi/InetAddressResolverProvider$Configuration;)Ljava/net/spi/InetAddressResolver; flags 401 +method name name descriptor ()Ljava/lang/String; flags 401 +method name descriptor ()V flags 4 + +class name java/net/spi/InetAddressResolverProvider$Configuration +header extends java/lang/Object nestHost java/net/spi/InetAddressResolverProvider sealed true flags 601 +innerclass innerClass java/net/spi/InetAddressResolverProvider$Configuration outerClass java/net/spi/InetAddressResolverProvider innerClassName Configuration flags 609 +method name builtinResolver descriptor ()Ljava/net/spi/InetAddressResolver; flags 401 +method name lookupLocalHostName descriptor ()Ljava/lang/String; flags 401 + +class name java/net/spi/URLStreamHandlerProvider +header extends java/lang/Object implements java/net/URLStreamHandlerFactory flags 421 + +class name java/nio/CharBuffer +header extends java/nio/Buffer implements java/lang/Comparable,java/lang/Appendable,java/lang/CharSequence,java/lang/Readable flags 421 signature Ljava/nio/Buffer;Ljava/lang/Comparable;Ljava/lang/Appendable;Ljava/lang/CharSequence;Ljava/lang/Readable; +innerclass innerClass java/util/Spliterator$OfInt outerClass java/util/Spliterator innerClassName OfInt flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/nio/charset/Charset +method name forName descriptor (Ljava/lang/String;Ljava/nio/charset/Charset;)Ljava/nio/charset/Charset; flags 9 + +class name java/security/Certificate +header extends java/lang/Object flags 601 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="1.2") + +class name java/security/Identity +header extends java/lang/Object implements java/security/Principal,java/io/Serializable flags 421 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="1.2") + +class name java/security/KeyStore +method name getAttributes descriptor (Ljava/lang/String;)Ljava/util/Set; thrownTypes java/security/KeyStoreException flags 11 signature (Ljava/lang/String;)Ljava/util/Set; + +class name java/security/KeyStoreSpi +header extends java/lang/Object flags 421 +innerclass innerClass java/security/KeyStore$LoadStoreParameter outerClass java/security/KeyStore innerClassName LoadStoreParameter flags 609 +innerclass innerClass java/security/KeyStore$ProtectionParameter outerClass java/security/KeyStore innerClassName ProtectionParameter flags 609 +innerclass innerClass java/security/KeyStore$PasswordProtection outerClass java/security/KeyStore innerClassName PasswordProtection flags 9 +innerclass innerClass java/security/KeyStore$CallbackHandlerProtection outerClass java/security/KeyStore innerClassName CallbackHandlerProtection flags 9 +innerclass innerClass java/security/KeyStore$TrustedCertificateEntry outerClass java/security/KeyStore innerClassName TrustedCertificateEntry flags 19 +innerclass innerClass java/security/KeyStore$PrivateKeyEntry outerClass java/security/KeyStore innerClassName PrivateKeyEntry flags 19 +innerclass innerClass java/security/KeyStore$SecretKeyEntry outerClass java/security/KeyStore innerClassName SecretKeyEntry flags 19 +innerclass innerClass java/security/KeyStore$Entry outerClass java/security/KeyStore innerClassName Entry flags 609 +innerclass innerClass java/security/KeyStore$Entry$Attribute outerClass java/security/KeyStore$Entry innerClassName Attribute flags 609 +method name engineGetAttributes descriptor (Ljava/lang/String;)Ljava/util/Set; flags 1 signature (Ljava/lang/String;)Ljava/util/Set; + +class name java/security/SecureRandomParameters +header extends java/lang/Object flags 601 + +class name java/security/SignedObject +header extends java/lang/Object implements java/io/Serializable flags 31 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 + +class name java/security/cert/CertificateRevokedException +header extends java/security/cert/CertificateException flags 21 +innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 + +class name java/security/cert/URICertStoreParameters +header extends java/lang/Object implements java/security/cert/CertStoreParameters flags 31 + +class name java/security/interfaces/RSAKey +-method name getParams descriptor ()Ljava/security/spec/AlgorithmParameterSpec; +method name getParams descriptor ()Ljava/security/spec/AlgorithmParameterSpec; flags 1 + +class name java/security/spec/MGF1ParameterSpec +-field name SHA512_224 descriptor Ljava/security/spec/MGF1ParameterSpec; +-field name SHA512_256 descriptor Ljava/security/spec/MGF1ParameterSpec; +field name SHA512_224 descriptor Ljava/security/spec/MGF1ParameterSpec; flags 19 +field name SHA512_256 descriptor Ljava/security/spec/MGF1ParameterSpec; flags 19 + +class name java/security/spec/PSSParameterSpec +-field name TRAILER_FIELD_BC descriptor I +-method name toString descriptor ()Ljava/lang/String; +field name TRAILER_FIELD_BC descriptor I constantValue 1 flags 19 +method name toString descriptor ()Ljava/lang/String; flags 1 + +class name java/security/spec/RSAKeyGenParameterSpec +-method name descriptor (ILjava/math/BigInteger;Ljava/security/spec/AlgorithmParameterSpec;)V +-method name getKeyParams descriptor ()Ljava/security/spec/AlgorithmParameterSpec; +method name descriptor (ILjava/math/BigInteger;Ljava/security/spec/AlgorithmParameterSpec;)V flags 1 +method name getKeyParams descriptor ()Ljava/security/spec/AlgorithmParameterSpec; flags 1 + +class name java/security/spec/RSAMultiPrimePrivateCrtKeySpec +-method name descriptor (Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;[Ljava/security/spec/RSAOtherPrimeInfo;Ljava/security/spec/AlgorithmParameterSpec;)V +method name descriptor (Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;[Ljava/security/spec/RSAOtherPrimeInfo;Ljava/security/spec/AlgorithmParameterSpec;)V flags 1 + +class name java/security/spec/RSAPrivateCrtKeySpec +-method name descriptor (Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/security/spec/AlgorithmParameterSpec;)V +method name descriptor (Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/security/spec/AlgorithmParameterSpec;)V flags 1 + +class name java/security/spec/RSAPrivateKeySpec +-method name descriptor (Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/security/spec/AlgorithmParameterSpec;)V +-method name getParams descriptor ()Ljava/security/spec/AlgorithmParameterSpec; +method name descriptor (Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/security/spec/AlgorithmParameterSpec;)V flags 1 +method name getParams descriptor ()Ljava/security/spec/AlgorithmParameterSpec; flags 1 + +class name java/security/spec/RSAPublicKeySpec +-method name descriptor (Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/security/spec/AlgorithmParameterSpec;)V +-method name getParams descriptor ()Ljava/security/spec/AlgorithmParameterSpec; +method name descriptor (Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/security/spec/AlgorithmParameterSpec;)V flags 1 +method name getParams descriptor ()Ljava/security/spec/AlgorithmParameterSpec; flags 1 + +class name java/text/DateFormatSymbols +header extends java/lang/Object implements java/io/Serializable,java/lang/Cloneable flags 21 +innerclass innerClass java/util/Locale$Category outerClass java/util/Locale innerClassName Category flags 4019 + +class name java/text/RuleBasedCollator +header extends java/text/Collator flags 21 +innerclass innerClass java/text/Normalizer$Form outerClass java/text/Normalizer innerClassName Form flags 4019 + +class name java/time/Duration +method name isPositive descriptor ()Z flags 1 + +class name java/time/chrono/ChronoLocalDate +header extends java/lang/Object implements java/time/temporal/Temporal,java/time/temporal/TemporalAdjuster,java/lang/Comparable flags 601 signature Ljava/lang/Object;Ljava/time/temporal/Temporal;Ljava/time/temporal/TemporalAdjuster;Ljava/lang/Comparable; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/time/chrono/ChronoLocalDateTime +header extends java/lang/Object implements java/time/temporal/Temporal,java/time/temporal/TemporalAdjuster,java/lang/Comparable flags 601 signature Ljava/lang/Object;Ljava/time/temporal/Temporal;Ljava/time/temporal/TemporalAdjuster;Ljava/lang/Comparable;>; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/time/format/DecimalStyle +header extends java/lang/Object flags 31 +innerclass innerClass java/util/Locale$Category outerClass java/util/Locale innerClassName Category flags 4019 + +class name java/time/temporal/TemporalAdjusters +header extends java/lang/Object flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/Comparator +header extends java/lang/Object flags 601 signature Ljava/lang/Object; runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/DoubleSummaryStatistics +header extends java/lang/Object implements java/util/function/DoubleConsumer flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/GregorianCalendar +header extends java/util/Calendar flags 21 +innerclass innerClass java/util/Locale$Category outerClass java/util/Locale innerClassName Category flags 4019 + +class name java/util/HashMap +header extends java/util/AbstractMap implements java/util/Map,java/lang/Cloneable,java/io/Serializable flags 21 signature Ljava/util/AbstractMap;Ljava/util/Map;Ljava/lang/Cloneable;Ljava/io/Serializable; +innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 + +class name java/util/HashSet +header extends java/util/AbstractSet implements java/util/Set,java/lang/Cloneable,java/io/Serializable flags 21 signature Ljava/util/AbstractSet;Ljava/util/Set;Ljava/lang/Cloneable;Ljava/io/Serializable; +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 + +class name java/util/Locale$IsoCountryCode +header extends java/lang/Enum nestHost java/util/Locale sealed true flags 4421 signature Ljava/lang/Enum; +innerclass innerClass java/util/Locale$IsoCountryCode outerClass java/util/Locale innerClassName IsoCountryCode flags 4409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/Observable +header extends java/lang/Object flags 21 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") + +class name java/util/Observer +header extends java/lang/Object flags 601 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") + +class name java/util/TimeZone +header extends java/lang/Object implements java/io/Serializable,java/lang/Cloneable flags 421 +innerclass innerClass java/util/Locale$Category outerClass java/util/Locale innerClassName Category flags 4019 + +class name java/util/TreeSet +header extends java/util/AbstractSet implements java/util/NavigableSet,java/lang/Cloneable,java/io/Serializable flags 21 signature Ljava/util/AbstractSet;Ljava/util/NavigableSet;Ljava/lang/Cloneable;Ljava/io/Serializable; +innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 + +class name java/util/concurrent/ConcurrentMap +header extends java/lang/Object implements java/util/Map flags 601 signature Ljava/lang/Object;Ljava/util/Map; +innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/concurrent/ConcurrentSkipListSet +header extends java/util/AbstractSet implements java/util/NavigableSet,java/lang/Cloneable,java/io/Serializable flags 21 signature Ljava/util/AbstractSet;Ljava/util/NavigableSet;Ljava/lang/Cloneable;Ljava/io/Serializable; +innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/concurrent/CountedCompleter +header extends java/util/concurrent/ForkJoinTask flags 421 signature Ljava/util/concurrent/ForkJoinTask; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/concurrent/ThreadPoolExecutor +-method name finalize descriptor ()V +method name finalize descriptor ()V flags 4 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="9") + +class name java/util/concurrent/atomic/AtomicBoolean +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/concurrent/atomic/AtomicReference +header extends java/lang/Object implements java/io/Serializable flags 21 signature Ljava/lang/Object;Ljava/io/Serializable; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/concurrent/atomic/AtomicReferenceArray +header extends java/lang/Object implements java/io/Serializable flags 21 signature Ljava/lang/Object;Ljava/io/Serializable; +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/concurrent/locks/StampedLock +header extends java/lang/Object implements java/io/Serializable flags 21 classAnnotations @Ljdk/Profile+Annotation;(value=I1) +-method name tryWriteLock descriptor ()J +-method name writeLockInterruptibly descriptor ()J +-method name tryReadLock descriptor ()J +-method name tryReadLock descriptor (JLjava/util/concurrent/TimeUnit;)J +-method name readLockInterruptibly descriptor ()J +-method name unlock descriptor (J)V +method name tryWriteLock descriptor ()J flags 1 +method name writeLockInterruptibly descriptor ()J thrownTypes java/lang/InterruptedException flags 1 +method name tryReadLock descriptor ()J flags 1 +method name tryReadLock descriptor (JLjava/util/concurrent/TimeUnit;)J thrownTypes java/lang/InterruptedException flags 1 +method name readLockInterruptibly descriptor ()J thrownTypes java/lang/InterruptedException flags 1 +method name unlock descriptor (J)V flags 1 + +class name java/util/function/BiConsumer +header extends java/lang/Object flags 601 signature Ljava/lang/Object; runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/function/BiFunction +header extends java/lang/Object flags 601 signature Ljava/lang/Object; runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/function/BiPredicate +header extends java/lang/Object flags 601 signature Ljava/lang/Object; runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/function/BinaryOperator +header extends java/lang/Object implements java/util/function/BiFunction flags 601 signature Ljava/lang/Object;Ljava/util/function/BiFunction; runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/function/Consumer +header extends java/lang/Object flags 601 signature Ljava/lang/Object; runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/function/DoubleConsumer +header extends java/lang/Object flags 601 runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/function/DoublePredicate +header extends java/lang/Object flags 601 runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/function/DoubleUnaryOperator +header extends java/lang/Object flags 601 runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/function/Function +header extends java/lang/Object flags 601 signature Ljava/lang/Object; runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/function/IntConsumer +header extends java/lang/Object flags 601 runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/function/IntPredicate +header extends java/lang/Object flags 601 runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/function/IntUnaryOperator +header extends java/lang/Object flags 601 runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/function/LongConsumer +header extends java/lang/Object flags 601 runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/function/LongPredicate +header extends java/lang/Object flags 601 runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/function/LongUnaryOperator +header extends java/lang/Object flags 601 runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/function/Predicate +header extends java/lang/Object flags 601 signature Ljava/lang/Object; runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/function/UnaryOperator +header extends java/lang/Object implements java/util/function/Function flags 601 signature Ljava/lang/Object;Ljava/util/function/Function; runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/spi/AbstractResourceBundleProvider +header extends java/lang/Object implements java/util/spi/ResourceBundleProvider flags 421 +innerclass innerClass java/util/ResourceBundle$Control outerClass java/util/ResourceBundle innerClassName Control flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/spi/CurrencyNameProvider +header extends java/util/spi/LocaleServiceProvider flags 421 +innerclass innerClass java/util/ResourceBundle$Control outerClass java/util/ResourceBundle innerClassName Control flags 9 + +class name java/util/spi/ResourceBundleProvider +header extends java/lang/Object flags 601 + +class name java/util/spi/ToolProvider +header extends java/lang/Object flags 601 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/zip/CRC32C +header extends java/lang/Object implements java/util/zip/Checksum flags 31 + +class name javax/crypto/AEADBadTagException +header extends javax/crypto/BadPaddingException flags 21 + +class name javax/crypto/BadPaddingException +header extends java/security/GeneralSecurityException flags 21 + +class name javax/crypto/CipherInputStream +header extends java/io/FilterInputStream flags 21 + +class name javax/crypto/CipherOutputStream +header extends java/io/FilterOutputStream flags 21 + +class name javax/crypto/CipherSpi +header extends java/lang/Object flags 421 + +class name javax/crypto/EncryptedPrivateKeyInfo +header extends java/lang/Object flags 21 + +class name javax/crypto/ExemptionMechanism +header extends java/lang/Object flags 21 + +class name javax/crypto/ExemptionMechanismException +header extends java/security/GeneralSecurityException flags 21 + +class name javax/crypto/ExemptionMechanismSpi +header extends java/lang/Object flags 421 + +class name javax/crypto/IllegalBlockSizeException +header extends java/security/GeneralSecurityException flags 21 + +class name javax/crypto/KeyAgreement +header extends java/lang/Object flags 21 +innerclass innerClass java/security/Provider$Service outerClass java/security/Provider innerClassName Service flags 9 + +class name javax/crypto/KeyAgreementSpi +header extends java/lang/Object flags 421 + +class name javax/crypto/KeyGenerator +header extends java/lang/Object flags 21 +innerclass innerClass java/security/Provider$Service outerClass java/security/Provider innerClassName Service flags 9 + +class name javax/crypto/KeyGeneratorSpi +header extends java/lang/Object flags 421 + +class name javax/crypto/Mac +header extends java/lang/Object implements java/lang/Cloneable flags 21 +innerclass innerClass java/security/Provider$Service outerClass java/security/Provider innerClassName Service flags 9 + +class name javax/crypto/MacSpi +header extends java/lang/Object flags 421 + +class name javax/crypto/NoSuchPaddingException +header extends java/security/GeneralSecurityException flags 21 + +class name javax/crypto/NullCipher +header extends javax/crypto/Cipher flags 21 + +class name javax/crypto/SealedObject +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/crypto/SecretKey +header extends java/lang/Object implements java/security/Key,javax/security/auth/Destroyable flags 601 + +class name javax/crypto/SecretKeyFactory +header extends java/lang/Object flags 21 +innerclass innerClass java/security/Provider$Service outerClass java/security/Provider innerClassName Service flags 9 + +class name javax/crypto/SecretKeyFactorySpi +header extends java/lang/Object flags 421 + +class name javax/crypto/ShortBufferException +header extends java/security/GeneralSecurityException flags 21 + +class name javax/crypto/interfaces/DHKey +header extends java/lang/Object flags 601 + +class name javax/crypto/interfaces/DHPrivateKey +header extends java/lang/Object implements javax/crypto/interfaces/DHKey,java/security/PrivateKey flags 601 + +class name javax/crypto/interfaces/DHPublicKey +header extends java/lang/Object implements javax/crypto/interfaces/DHKey,java/security/PublicKey flags 601 + +class name javax/crypto/interfaces/PBEKey +header extends java/lang/Object implements javax/crypto/SecretKey flags 601 + +class name javax/crypto/spec/DESKeySpec +header extends java/lang/Object implements java/security/spec/KeySpec flags 21 + +class name javax/crypto/spec/DESedeKeySpec +header extends java/lang/Object implements java/security/spec/KeySpec flags 21 + +class name javax/crypto/spec/DHGenParameterSpec +header extends java/lang/Object implements java/security/spec/AlgorithmParameterSpec flags 21 + +class name javax/crypto/spec/DHParameterSpec +header extends java/lang/Object implements java/security/spec/AlgorithmParameterSpec flags 21 + +class name javax/crypto/spec/DHPrivateKeySpec +header extends java/lang/Object implements java/security/spec/KeySpec flags 21 + +class name javax/crypto/spec/DHPublicKeySpec +header extends java/lang/Object implements java/security/spec/KeySpec flags 21 + +class name javax/crypto/spec/GCMParameterSpec +header extends java/lang/Object implements java/security/spec/AlgorithmParameterSpec flags 21 + +class name javax/crypto/spec/IvParameterSpec +header extends java/lang/Object implements java/security/spec/AlgorithmParameterSpec flags 21 + +class name javax/crypto/spec/OAEPParameterSpec +header extends java/lang/Object implements java/security/spec/AlgorithmParameterSpec flags 21 +innerclass innerClass javax/crypto/spec/PSource$PSpecified outerClass javax/crypto/spec/PSource innerClassName PSpecified flags 19 + +class name javax/crypto/spec/PBEKeySpec +header extends java/lang/Object implements java/security/spec/KeySpec flags 21 + +class name javax/crypto/spec/PBEParameterSpec +header extends java/lang/Object implements java/security/spec/AlgorithmParameterSpec flags 21 + +class name javax/crypto/spec/RC2ParameterSpec +header extends java/lang/Object implements java/security/spec/AlgorithmParameterSpec flags 21 + +class name javax/crypto/spec/RC5ParameterSpec +header extends java/lang/Object implements java/security/spec/AlgorithmParameterSpec flags 21 + +class name javax/crypto/spec/SecretKeySpec +header extends java/lang/Object implements java/security/spec/KeySpec,javax/crypto/SecretKey flags 21 + +class name javax/security/auth/Subject +header extends java/lang/Object implements java/io/Serializable flags 31 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +-method name doAs descriptor (Ljavax/security/auth/Subject;Ljava/security/PrivilegedAction;)Ljava/lang/Object; +-method name doAs descriptor (Ljavax/security/auth/Subject;Ljava/security/PrivilegedExceptionAction;)Ljava/lang/Object; +method name current descriptor ()Ljavax/security/auth/Subject; flags 9 +method name callAs descriptor (Ljavax/security/auth/Subject;Ljava/util/concurrent/Callable;)Ljava/lang/Object; thrownTypes java/util/concurrent/CompletionException flags 9 signature (Ljavax/security/auth/Subject;Ljava/util/concurrent/Callable;)TT; +method name doAs descriptor (Ljavax/security/auth/Subject;Ljava/security/PrivilegedAction;)Ljava/lang/Object; flags 9 deprecated true signature (Ljavax/security/auth/Subject;Ljava/security/PrivilegedAction;)TT; runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="18") +method name doAs descriptor (Ljavax/security/auth/Subject;Ljava/security/PrivilegedExceptionAction;)Ljava/lang/Object; thrownTypes java/security/PrivilegedActionException flags 9 deprecated true signature (Ljavax/security/auth/Subject;Ljava/security/PrivilegedExceptionAction;)TT; runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="18") + +class name javax/security/auth/login/LoginContext +header extends java/lang/Object flags 21 +innerclass innerClass javax/security/auth/login/AppConfigurationEntry$LoginModuleControlFlag outerClass javax/security/auth/login/AppConfigurationEntry innerClassName LoginModuleControlFlag flags 9 +innerclass innerClass java/util/ServiceLoader$Provider outerClass java/util/ServiceLoader innerClassName Provider flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/internal/vm/vector/VectorSupport +header extends java/lang/Object nestMembers jdk/internal/vm/vector/VectorSupport$VectorMask,jdk/internal/vm/vector/VectorSupport$VectorShuffle,jdk/internal/vm/vector/VectorSupport$Vector,jdk/internal/vm/vector/VectorSupport$VectorPayload,jdk/internal/vm/vector/VectorSupport$VectorSpecies flags 21 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorPayload outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorPayload flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorShuffle outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorShuffle flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$Vector outerClass jdk/internal/vm/vector/VectorSupport innerClassName Vector flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorMask outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorMask flags 9 +-method name broadcastCoerced descriptor (Ljava/lang/Class;Ljava/lang/Class;IJLjdk/internal/vm/vector/VectorSupport$VectorSpecies;Ljdk/internal/vm/vector/VectorSupport$BroadcastOperation;)Ljava/lang/Object; +-method name shuffleIota descriptor (Ljava/lang/Class;Ljava/lang/Class;Ljdk/internal/vm/vector/VectorSupport$VectorSpecies;IIIILjdk/internal/vm/vector/VectorSupport$ShuffleIotaOperation;)Ljdk/internal/vm/vector/VectorSupport$VectorShuffle; +-method name shuffleToVector descriptor (Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;Ljdk/internal/vm/vector/VectorSupport$VectorShuffle;ILjdk/internal/vm/vector/VectorSupport$ShuffleToVectorOperation;)Ljava/lang/Object; +-method name indexVector descriptor (Ljava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;ILjdk/internal/vm/vector/VectorSupport$VectorSpecies;Ljdk/internal/vm/vector/VectorSupport$IndexOperation;)Ljdk/internal/vm/vector/VectorSupport$Vector; +-method name reductionCoerced descriptor (ILjava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;Ljava/util/function/Function;)J +-method name extract descriptor (Ljava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;ILjdk/internal/vm/vector/VectorSupport$VecExtractOp;)J +-method name insert descriptor (Ljava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;IJLjdk/internal/vm/vector/VectorSupport$VecInsertOp;)Ljdk/internal/vm/vector/VectorSupport$Vector; +-method name unaryOp descriptor (ILjava/lang/Class;Ljava/lang/Class;ILjava/lang/Object;Ljava/util/function/Function;)Ljava/lang/Object; +-method name binaryOp descriptor (ILjava/lang/Class;Ljava/lang/Class;ILjava/lang/Object;Ljava/lang/Object;Ljava/util/function/BiFunction;)Ljava/lang/Object; +-method name ternaryOp descriptor (ILjava/lang/Class;Ljava/lang/Class;ILjava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljdk/internal/vm/vector/VectorSupport$TernaryOperation;)Ljava/lang/Object; +-method name load descriptor (Ljava/lang/Class;Ljava/lang/Class;ILjava/lang/Object;JLjava/lang/Object;ILjdk/internal/vm/vector/VectorSupport$VectorSpecies;Ljdk/internal/vm/vector/VectorSupport$LoadOperation;)Ljava/lang/Object; +-method name loadWithMap descriptor (Ljava/lang/Class;Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/Object;JLjdk/internal/vm/vector/VectorSupport$Vector;Ljava/lang/Object;I[IILjdk/internal/vm/vector/VectorSupport$VectorSpecies;Ljdk/internal/vm/vector/VectorSupport$LoadVectorOperationWithMap;)Ljdk/internal/vm/vector/VectorSupport$Vector; +-method name storeWithMap descriptor (Ljava/lang/Class;Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/Object;JLjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljava/lang/Object;I[IILjdk/internal/vm/vector/VectorSupport$StoreVectorOperationWithMap;)V +-method name test descriptor (ILjava/lang/Class;Ljava/lang/Class;ILjava/lang/Object;Ljava/lang/Object;Ljava/util/function/BiFunction;)Z +-method name compare descriptor (ILjava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$VectorCompareOp;)Ljdk/internal/vm/vector/VectorSupport$VectorMask; +-method name rearrangeOp descriptor (Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$VectorShuffle;Ljdk/internal/vm/vector/VectorSupport$VectorRearrangeOp;)Ljdk/internal/vm/vector/VectorSupport$Vector; +-method name blend descriptor (Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$VectorMask;Ljdk/internal/vm/vector/VectorSupport$VectorBlendOp;)Ljdk/internal/vm/vector/VectorSupport$Vector; +-method name broadcastInt descriptor (ILjava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;ILjdk/internal/vm/vector/VectorSupport$VectorBroadcastIntOp;)Ljdk/internal/vm/vector/VectorSupport$Vector; +-method name maybeRebox descriptor (Ljava/lang/Object;)Ljava/lang/Object; +-method name maskReductionCoerced descriptor (ILjava/lang/Class;Ljava/lang/Class;ILjava/lang/Object;Ljdk/internal/vm/vector/VectorSupport$VectorMaskOp;)I +field name VECTOR_OP_MASK_TOLONG descriptor I constantValue 22 flags 19 +field name VECTOR_OP_LROTATE descriptor I constantValue 23 flags 19 +field name VECTOR_OP_RROTATE descriptor I constantValue 24 flags 19 +method name broadcastCoerced descriptor (Ljava/lang/Class;Ljava/lang/Class;IJLjdk/internal/vm/vector/VectorSupport$VectorSpecies;Ljdk/internal/vm/vector/VectorSupport$BroadcastOperation;)Ljdk/internal/vm/vector/VectorSupport$VectorPayload; flags 9 signature ;E:Ljava/lang/Object;>(Ljava/lang/Class<+TVM;>;Ljava/lang/Class;IJTS;Ljdk/internal/vm/vector/VectorSupport$BroadcastOperation;)TVM; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name shuffleIota descriptor (Ljava/lang/Class;Ljava/lang/Class;Ljdk/internal/vm/vector/VectorSupport$VectorSpecies;IIIILjdk/internal/vm/vector/VectorSupport$ShuffleIotaOperation;)Ljdk/internal/vm/vector/VectorSupport$VectorShuffle; flags 9 signature ;SH:Ljdk/internal/vm/vector/VectorSupport$VectorShuffle;>(Ljava/lang/Class;Ljava/lang/Class<+TSH;>;TS;IIIILjdk/internal/vm/vector/VectorSupport$ShuffleIotaOperation;)TSH; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name shuffleToVector descriptor (Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;Ljdk/internal/vm/vector/VectorSupport$VectorShuffle;ILjdk/internal/vm/vector/VectorSupport$ShuffleToVectorOperation;)Ljdk/internal/vm/vector/VectorSupport$Vector; flags 9 signature ;SH:Ljdk/internal/vm/vector/VectorSupport$VectorShuffle;E:Ljava/lang/Object;>(Ljava/lang/Class<+Ljdk/internal/vm/vector/VectorSupport$Vector;>;Ljava/lang/Class;Ljava/lang/Class<+TSH;>;TSH;ILjdk/internal/vm/vector/VectorSupport$ShuffleToVectorOperation;)TV; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name indexVector descriptor (Ljava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;ILjdk/internal/vm/vector/VectorSupport$VectorSpecies;Ljdk/internal/vm/vector/VectorSupport$IndexOperation;)Ljdk/internal/vm/vector/VectorSupport$Vector; flags 9 signature ;E:Ljava/lang/Object;S:Ljdk/internal/vm/vector/VectorSupport$VectorSpecies;>(Ljava/lang/Class<+TV;>;Ljava/lang/Class;ITV;ITS;Ljdk/internal/vm/vector/VectorSupport$IndexOperation;)TV; +method name reductionCoerced descriptor (ILjava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$VectorMask;Ljdk/internal/vm/vector/VectorSupport$ReductionOperation;)J flags 9 signature ;M:Ljdk/internal/vm/vector/VectorSupport$VectorMask;E:Ljava/lang/Object;>(ILjava/lang/Class<+TV;>;Ljava/lang/Class<+TM;>;Ljava/lang/Class;ITV;TM;Ljdk/internal/vm/vector/VectorSupport$ReductionOperation;)J runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name extract descriptor (Ljava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;ILjdk/internal/vm/vector/VectorSupport$VecExtractOp;)J flags 9 signature ;E:Ljava/lang/Object;>(Ljava/lang/Class<+TV;>;Ljava/lang/Class;ITV;ILjdk/internal/vm/vector/VectorSupport$VecExtractOp;)J runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name insert descriptor (Ljava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;IJLjdk/internal/vm/vector/VectorSupport$VecInsertOp;)Ljdk/internal/vm/vector/VectorSupport$Vector; flags 9 signature ;E:Ljava/lang/Object;>(Ljava/lang/Class<+TV;>;Ljava/lang/Class;ITV;IJLjdk/internal/vm/vector/VectorSupport$VecInsertOp;)TV; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name unaryOp descriptor (ILjava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$VectorMask;Ljdk/internal/vm/vector/VectorSupport$UnaryOperation;)Ljdk/internal/vm/vector/VectorSupport$Vector; flags 9 signature ;M:Ljdk/internal/vm/vector/VectorSupport$VectorMask;E:Ljava/lang/Object;>(ILjava/lang/Class<+TV;>;Ljava/lang/Class<+TM;>;Ljava/lang/Class;ITV;TM;Ljdk/internal/vm/vector/VectorSupport$UnaryOperation;)TV; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name binaryOp descriptor (ILjava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$VectorPayload;Ljdk/internal/vm/vector/VectorSupport$VectorPayload;Ljdk/internal/vm/vector/VectorSupport$VectorMask;Ljdk/internal/vm/vector/VectorSupport$BinaryOperation;)Ljdk/internal/vm/vector/VectorSupport$VectorPayload; flags 9 signature ;E:Ljava/lang/Object;>(ILjava/lang/Class<+TVM;>;Ljava/lang/Class<+TM;>;Ljava/lang/Class;ITVM;TVM;TM;Ljdk/internal/vm/vector/VectorSupport$BinaryOperation;)TVM; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name ternaryOp descriptor (ILjava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$VectorMask;Ljdk/internal/vm/vector/VectorSupport$TernaryOperation;)Ljdk/internal/vm/vector/VectorSupport$Vector; flags 9 signature ;M:Ljdk/internal/vm/vector/VectorSupport$VectorMask;E:Ljava/lang/Object;>(ILjava/lang/Class<+TV;>;Ljava/lang/Class<+TM;>;Ljava/lang/Class;ITV;TV;TV;TM;Ljdk/internal/vm/vector/VectorSupport$TernaryOperation;)TV; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name load descriptor (Ljava/lang/Class;Ljava/lang/Class;ILjava/lang/Object;JLjava/lang/Object;ILjdk/internal/vm/vector/VectorSupport$VectorSpecies;Ljdk/internal/vm/vector/VectorSupport$LoadOperation;)Ljdk/internal/vm/vector/VectorSupport$VectorPayload; flags 9 signature ;>(Ljava/lang/Class<+TVM;>;Ljava/lang/Class;ILjava/lang/Object;JTC;ITS;Ljdk/internal/vm/vector/VectorSupport$LoadOperation;)TVM; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name loadMasked descriptor (Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;ILjava/lang/Object;JLjdk/internal/vm/vector/VectorSupport$VectorMask;Ljava/lang/Object;ILjdk/internal/vm/vector/VectorSupport$VectorSpecies;Ljdk/internal/vm/vector/VectorSupport$LoadVectorMaskedOperation;)Ljdk/internal/vm/vector/VectorSupport$Vector; flags 9 signature ;E:Ljava/lang/Object;S:Ljdk/internal/vm/vector/VectorSupport$VectorSpecies;M:Ljdk/internal/vm/vector/VectorSupport$VectorMask;>(Ljava/lang/Class<+TV;>;Ljava/lang/Class;Ljava/lang/Class;ILjava/lang/Object;JTM;TC;ITS;Ljdk/internal/vm/vector/VectorSupport$LoadVectorMaskedOperation;)TV; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name loadWithMap descriptor (Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/Object;JLjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$VectorMask;Ljava/lang/Object;I[IILjdk/internal/vm/vector/VectorSupport$VectorSpecies;Ljdk/internal/vm/vector/VectorSupport$LoadVectorOperationWithMap;)Ljdk/internal/vm/vector/VectorSupport$Vector; flags 9 signature ;W:Ljdk/internal/vm/vector/VectorSupport$Vector;S:Ljdk/internal/vm/vector/VectorSupport$VectorSpecies;M:Ljdk/internal/vm/vector/VectorSupport$VectorMask;E:Ljava/lang/Object;>(Ljava/lang/Class<+TV;>;Ljava/lang/Class;Ljava/lang/Class;ILjava/lang/Class<+Ljdk/internal/vm/vector/VectorSupport$Vector;>;Ljava/lang/Object;JTW;TM;TC;I[IITS;Ljdk/internal/vm/vector/VectorSupport$LoadVectorOperationWithMap;)TV; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name storeMasked descriptor (Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;ILjava/lang/Object;JLjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$VectorMask;Ljava/lang/Object;ILjdk/internal/vm/vector/VectorSupport$StoreVectorMaskedOperation;)V flags 9 signature ;M:Ljdk/internal/vm/vector/VectorSupport$VectorMask;E:Ljava/lang/Object;>(Ljava/lang/Class<+TV;>;Ljava/lang/Class;Ljava/lang/Class;ILjava/lang/Object;JTV;TM;TC;ILjdk/internal/vm/vector/VectorSupport$StoreVectorMaskedOperation;)V runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name storeWithMap descriptor (Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/Object;JLjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$VectorMask;Ljava/lang/Object;I[IILjdk/internal/vm/vector/VectorSupport$StoreVectorOperationWithMap;)V flags 9 signature ;W:Ljdk/internal/vm/vector/VectorSupport$Vector;M:Ljdk/internal/vm/vector/VectorSupport$VectorMask;E:Ljava/lang/Object;>(Ljava/lang/Class<+TV;>;Ljava/lang/Class;Ljava/lang/Class;ILjava/lang/Class<+Ljdk/internal/vm/vector/VectorSupport$Vector;>;Ljava/lang/Object;JTW;TV;TM;TC;I[IILjdk/internal/vm/vector/VectorSupport$StoreVectorOperationWithMap;)V runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name test descriptor (ILjava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$VectorMask;Ljdk/internal/vm/vector/VectorSupport$VectorMask;Ljava/util/function/BiFunction;)Z flags 9 signature ;E:Ljava/lang/Object;>(ILjava/lang/Class<*>;Ljava/lang/Class<*>;ITM;TM;Ljava/util/function/BiFunction;)Z runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name compare descriptor (ILjava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$VectorMask;Ljdk/internal/vm/vector/VectorSupport$VectorCompareOp;)Ljdk/internal/vm/vector/VectorSupport$VectorMask; flags 9 signature ;M:Ljdk/internal/vm/vector/VectorSupport$VectorMask;E:Ljava/lang/Object;>(ILjava/lang/Class<+TV;>;Ljava/lang/Class;Ljava/lang/Class;ITV;TV;TM;Ljdk/internal/vm/vector/VectorSupport$VectorCompareOp;)TM; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name rearrangeOp descriptor (Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$VectorShuffle;Ljdk/internal/vm/vector/VectorSupport$VectorMask;Ljdk/internal/vm/vector/VectorSupport$VectorRearrangeOp;)Ljdk/internal/vm/vector/VectorSupport$Vector; flags 9 signature ;SH:Ljdk/internal/vm/vector/VectorSupport$VectorShuffle;M:Ljdk/internal/vm/vector/VectorSupport$VectorMask;E:Ljava/lang/Object;>(Ljava/lang/Class<+TV;>;Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;ITV;TSH;TM;Ljdk/internal/vm/vector/VectorSupport$VectorRearrangeOp;)TV; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name blend descriptor (Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$VectorMask;Ljdk/internal/vm/vector/VectorSupport$VectorBlendOp;)Ljdk/internal/vm/vector/VectorSupport$Vector; flags 9 signature ;M:Ljdk/internal/vm/vector/VectorSupport$VectorMask;E:Ljava/lang/Object;>(Ljava/lang/Class<+TV;>;Ljava/lang/Class;Ljava/lang/Class;ITV;TV;TM;Ljdk/internal/vm/vector/VectorSupport$VectorBlendOp;)TV; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name broadcastInt descriptor (ILjava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;ILjdk/internal/vm/vector/VectorSupport$VectorMask;Ljdk/internal/vm/vector/VectorSupport$VectorBroadcastIntOp;)Ljdk/internal/vm/vector/VectorSupport$Vector; flags 9 signature ;M:Ljdk/internal/vm/vector/VectorSupport$VectorMask;E:Ljava/lang/Object;>(ILjava/lang/Class<+TV;>;Ljava/lang/Class<+TM;>;Ljava/lang/Class;ITV;ITM;Ljdk/internal/vm/vector/VectorSupport$VectorBroadcastIntOp;)TV; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name maybeRebox descriptor (Ljdk/internal/vm/vector/VectorSupport$VectorPayload;)Ljdk/internal/vm/vector/VectorSupport$VectorPayload; flags 9 signature (TVP;)TVP; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name maskReductionCoerced descriptor (ILjava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$VectorMask;Ljdk/internal/vm/vector/VectorSupport$VectorMaskOp;)J flags 9 signature ;E:Ljava/lang/Object;>(ILjava/lang/Class<+TM;>;Ljava/lang/Class<*>;ITM;Ljdk/internal/vm/vector/VectorSupport$VectorMaskOp;)J runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; + diff --git a/make/data/symbols/java.compiler-I.sym.txt b/make/data/symbols/java.compiler-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..6f3cdb0623ee5a6369fce63891d7c7989c08abbf --- /dev/null +++ b/make/data/symbols/java.compiler-I.sym.txt @@ -0,0 +1,140 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name javax/annotation/processing/AbstractProcessor +header extends java/lang/Object implements javax/annotation/processing/Processor flags 421 +innerclass innerClass javax/tools/Diagnostic$Kind outerClass javax/tools/Diagnostic innerClassName Kind flags 4019 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/annotation/processing/Generated +header extends java/lang/Object implements java/lang/annotation/Annotation flags 2601 runtimeAnnotations @Ljava/lang/annotation/Documented;@Ljava/lang/annotation/Retention;(value=eLjava/lang/annotation/RetentionPolicy;SOURCE;)@Ljava/lang/annotation/Target;(value={eLjava/lang/annotation/ElementType;PACKAGE;eLjava/lang/annotation/ElementType;TYPE;eLjava/lang/annotation/ElementType;METHOD;eLjava/lang/annotation/ElementType;CONSTRUCTOR;eLjava/lang/annotation/ElementType;FIELD;eLjava/lang/annotation/ElementType;LOCAL_VARIABLE;eLjava/lang/annotation/ElementType;PARAMETER;}) + +class name javax/annotation/processing/Messager +method name printError descriptor (Ljava/lang/CharSequence;)V flags 1 +method name printError descriptor (Ljava/lang/CharSequence;Ljavax/lang/model/element/Element;)V flags 1 +method name printWarning descriptor (Ljava/lang/CharSequence;)V flags 1 +method name printWarning descriptor (Ljava/lang/CharSequence;Ljavax/lang/model/element/Element;)V flags 1 +method name printNote descriptor (Ljava/lang/CharSequence;)V flags 1 +method name printNote descriptor (Ljava/lang/CharSequence;Ljavax/lang/model/element/Element;)V flags 1 + +class name javax/lang/model/SourceVersion +field name RELEASE_18 descriptor Ljavax/lang/model/SourceVersion; flags 4019 +method name valueOf descriptor (Ljava/lang/Runtime$Version;)Ljavax/lang/model/SourceVersion; flags 9 +method name runtimeVersion descriptor ()Ljava/lang/Runtime$Version; flags 1 + +class name javax/lang/model/element/ExecutableElement +method name getEnclosingElement descriptor ()Ljavax/lang/model/element/Element; flags 401 + +class name javax/lang/model/element/Modifier +header extends java/lang/Enum sealed true flags 4021 signature Ljava/lang/Enum; + +class name javax/lang/model/element/UnknownAnnotationValueException +header extends javax/lang/model/UnknownEntityException flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/lang/model/element/UnknownDirectiveException +header extends javax/lang/model/UnknownEntityException flags 21 +innerclass innerClass javax/lang/model/element/ModuleElement$Directive outerClass javax/lang/model/element/ModuleElement innerClassName Directive flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/lang/model/element/UnknownElementException +header extends javax/lang/model/UnknownEntityException flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/lang/model/type/MirroredTypeException +header extends javax/lang/model/type/MirroredTypesException flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/lang/model/type/MirroredTypesException +header extends java/lang/RuntimeException flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/lang/model/type/UnknownTypeException +header extends javax/lang/model/UnknownEntityException flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/lang/model/util/AbstractAnnotationValueVisitor14 +header extends javax/lang/model/util/AbstractAnnotationValueVisitor9 flags 421 signature Ljavax/lang/model/util/AbstractAnnotationValueVisitor9; runtimeAnnotations @Ljavax/annotation/processing/SupportedSourceVersion;(value=eLjavax/lang/model/SourceVersion;RELEASE_18;) + +class name javax/lang/model/util/AbstractElementVisitor14 +header extends javax/lang/model/util/AbstractElementVisitor9 flags 421 signature Ljavax/lang/model/util/AbstractElementVisitor9; runtimeAnnotations @Ljavax/annotation/processing/SupportedSourceVersion;(value=eLjavax/lang/model/SourceVersion;RELEASE_18;) + +class name javax/lang/model/util/AbstractTypeVisitor14 +header extends javax/lang/model/util/AbstractTypeVisitor9 flags 421 signature Ljavax/lang/model/util/AbstractTypeVisitor9; runtimeAnnotations @Ljavax/annotation/processing/SupportedSourceVersion;(value=eLjavax/lang/model/SourceVersion;RELEASE_18;) + +class name javax/lang/model/util/AbstractTypeVisitor6 +header extends java/lang/Object implements javax/lang/model/type/TypeVisitor flags 421 signature Ljava/lang/Object;Ljavax/lang/model/type/TypeVisitor; runtimeAnnotations @Ljavax/annotation/processing/SupportedSourceVersion;(value=eLjavax/lang/model/SourceVersion;RELEASE_6;) + +class name javax/lang/model/util/AbstractTypeVisitor7 +header extends javax/lang/model/util/AbstractTypeVisitor6 flags 421 signature Ljavax/lang/model/util/AbstractTypeVisitor6; runtimeAnnotations @Ljavax/annotation/processing/SupportedSourceVersion;(value=eLjavax/lang/model/SourceVersion;RELEASE_7;) + +class name javax/lang/model/util/AbstractTypeVisitor8 +header extends javax/lang/model/util/AbstractTypeVisitor7 flags 421 signature Ljavax/lang/model/util/AbstractTypeVisitor7; runtimeAnnotations @Ljavax/annotation/processing/SupportedSourceVersion;(value=eLjavax/lang/model/SourceVersion;RELEASE_8;) + +class name javax/lang/model/util/ElementKindVisitor14 +header extends javax/lang/model/util/ElementKindVisitor9 flags 21 signature Ljavax/lang/model/util/ElementKindVisitor9; runtimeAnnotations @Ljavax/annotation/processing/SupportedSourceVersion;(value=eLjavax/lang/model/SourceVersion;RELEASE_18;) + +class name javax/lang/model/util/ElementScanner14 +header extends javax/lang/model/util/ElementScanner9 flags 21 signature Ljavax/lang/model/util/ElementScanner9; runtimeAnnotations @Ljavax/annotation/processing/SupportedSourceVersion;(value=eLjavax/lang/model/SourceVersion;RELEASE_18;) + +class name javax/lang/model/util/Elements +method name getOutermostTypeElement descriptor (Ljavax/lang/model/element/Element;)Ljavax/lang/model/element/TypeElement; flags 1 +method name getFileObjectOf descriptor (Ljavax/lang/model/element/Element;)Ljavax/tools/JavaFileObject; flags 1 + +class name javax/lang/model/util/SimpleAnnotationValueVisitor14 +header extends javax/lang/model/util/SimpleAnnotationValueVisitor9 flags 21 signature Ljavax/lang/model/util/SimpleAnnotationValueVisitor9; runtimeAnnotations @Ljavax/annotation/processing/SupportedSourceVersion;(value=eLjavax/lang/model/SourceVersion;RELEASE_18;) + +class name javax/lang/model/util/SimpleElementVisitor14 +header extends javax/lang/model/util/SimpleElementVisitor9 flags 21 signature Ljavax/lang/model/util/SimpleElementVisitor9; runtimeAnnotations @Ljavax/annotation/processing/SupportedSourceVersion;(value=eLjavax/lang/model/SourceVersion;RELEASE_18;) + +class name javax/lang/model/util/SimpleTypeVisitor14 +header extends javax/lang/model/util/SimpleTypeVisitor9 flags 21 signature Ljavax/lang/model/util/SimpleTypeVisitor9; runtimeAnnotations @Ljavax/annotation/processing/SupportedSourceVersion;(value=eLjavax/lang/model/SourceVersion;RELEASE_18;) + +class name javax/lang/model/util/TypeKindVisitor14 +header extends javax/lang/model/util/TypeKindVisitor9 flags 21 signature Ljavax/lang/model/util/TypeKindVisitor9; runtimeAnnotations @Ljavax/annotation/processing/SupportedSourceVersion;(value=eLjavax/lang/model/SourceVersion;RELEASE_18;) + +class name javax/tools/DocumentationTool$Location +field name SNIPPET_PATH descriptor Ljavax/tools/DocumentationTool$Location; flags 4019 + +class name javax/tools/ForwardingJavaFileManager +method name getJavaFileForOutputForOriginatingFiles descriptor (Ljavax/tools/JavaFileManager$Location;Ljava/lang/String;Ljavax/tools/JavaFileObject$Kind;[Ljavax/tools/FileObject;)Ljavax/tools/JavaFileObject; thrownTypes java/io/IOException flags 81 +method name getFileForOutputForOriginatingFiles descriptor (Ljavax/tools/JavaFileManager$Location;Ljava/lang/String;Ljava/lang/String;[Ljavax/tools/FileObject;)Ljavax/tools/FileObject; thrownTypes java/io/IOException flags 81 + +class name javax/tools/JavaFileManager +method name getJavaFileForOutputForOriginatingFiles descriptor (Ljavax/tools/JavaFileManager$Location;Ljava/lang/String;Ljavax/tools/JavaFileObject$Kind;[Ljavax/tools/FileObject;)Ljavax/tools/JavaFileObject; thrownTypes java/io/IOException flags 81 +method name getFileForOutputForOriginatingFiles descriptor (Ljavax/tools/JavaFileManager$Location;Ljava/lang/String;Ljava/lang/String;[Ljavax/tools/FileObject;)Ljavax/tools/FileObject; thrownTypes java/io/IOException flags 81 + +class name javax/tools/SimpleJavaFileObject +header extends java/lang/Object implements javax/tools/JavaFileObject flags 21 +innerclass innerClass javax/tools/JavaFileObject$Kind outerClass javax/tools/JavaFileObject innerClassName Kind flags 4019 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/tools/ToolProvider +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + diff --git a/test/jdk/jdk/incubator/vector/build-tests.sh b/make/data/symbols/java.datatransfer-I.sym.txt similarity index 53% rename from test/jdk/jdk/incubator/vector/build-tests.sh rename to make/data/symbols/java.datatransfer-I.sym.txt index 69f0290ce26f8454f5d6b7e4cea2866498e8fe5a..748b21f2ef81b739b3160fd099c7a49240c61a79 100644 --- a/test/jdk/jdk/incubator/vector/build-tests.sh +++ b/make/data/symbols/java.datatransfer-I.sym.txt @@ -1,6 +1,5 @@ -#!/bin/bash # -# Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,35 +22,15 @@ # or visit www.oracle.com if you need additional information or have any # questions. # +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name java/awt/datatransfer/Clipboard +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 -. config.sh - -Log false "Building Vector API tests, $(date)\n" - -# For each type -for type in byte short int long float double -do - Type="$(tr '[:lower:]' '[:upper:]' <<< ${type:0:1})${type:1}" - - # For each size - for bits in 64 128 256 512 - do - vectorteststype=${typeprefix}${Type}${bits}VectorTests - # Compile - Log true "Compiling ${vectorteststype}... " - Log false "\n${JAVAC} -cp \"${VECTORTESTS_HOME_CP}$SEPARATOR${TESTNG_JAR}\" --add-modules=jdk.incubator.vector $vectorteststype.java 2>&1" - compilation=$(${JAVAC} -cp "${VECTORTESTS_HOME_CP}$SEPARATOR${TESTNG_JAR}" \ - --add-modules=jdk.incubator.vector $vectorteststype.java 2>&1) - if [[ $compilation == *"error"* ]]; then - Log true "$compilation\n" - exit -1 - else - Log false "$compilation\n" - fi - Log true "done\n" - done -done - -rm -fr build - +class name java/awt/datatransfer/DataFlavor +header extends java/lang/Object implements java/io/Externalizable,java/lang/Cloneable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 diff --git a/make/data/symbols/java.desktop-I.sym.txt b/make/data/symbols/java.desktop-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..348d9fd110ebbf775a09e5f8e067c1be4a6b9110 --- /dev/null +++ b/make/data/symbols/java.desktop-I.sym.txt @@ -0,0 +1,922 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name java/awt/AWTKeyStroke +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/AttributeValue +header extends java/lang/Object flags 420 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/BorderLayout +header extends java/lang/Object implements java/awt/LayoutManager2,java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/CheckboxGroup +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/Color +header extends java/lang/Object implements java/awt/Paint,java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/ContainerOrderFocusTraversalPolicy +header extends java/awt/FocusTraversalPolicy implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/Dimension +header extends java/awt/geom/Dimension2D implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/DisplayMode +header extends java/lang/Object flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/Event +header extends java/lang/Object implements java/io/Serializable flags 21 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/FlowLayout +header extends java/lang/Object implements java/awt/LayoutManager,java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/FontMetrics +header extends java/lang/Object implements java/io/Serializable flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/Graphics +header extends java/lang/Object flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +-method name finalize descriptor ()V +method name finalize descriptor ()V flags 1 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="9") + +class name java/awt/GridBagLayoutInfo +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/awt/Component$BaselineResizeBehavior outerClass java/awt/Component innerClassName BaselineResizeBehavior flags 4019 + +class name java/awt/GridLayout +header extends java/lang/Object implements java/awt/LayoutManager,java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/HeadlessException +header extends java/lang/UnsupportedOperationException flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/Insets +header extends java/lang/Object implements java/lang/Cloneable,java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/MenuShortcut +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/Point +header extends java/awt/geom/Point2D implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/PrintJob +-method name finalize descriptor ()V +method name finalize descriptor ()V flags 1 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="9") + +class name java/awt/Rectangle +header extends java/awt/geom/Rectangle2D implements java/awt/Shape,java/io/Serializable flags 21 +innerclass innerClass java/awt/geom/Rectangle2D$Double outerClass java/awt/geom/Rectangle2D innerClassName Double flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/SystemColor +header extends java/awt/Color implements java/io/Serializable flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/TexturePaint +header extends java/lang/Object implements java/awt/Paint flags 21 +innerclass innerClass java/awt/geom/Rectangle2D$Double outerClass java/awt/geom/Rectangle2D innerClassName Double flags 9 + +class name java/awt/color/ColorSpace +header extends java/lang/Object implements java/io/Serializable flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/color/ICC_ColorSpace +header extends java/awt/color/ColorSpace flags 21 classAnnotations @Ljdk/Profile+Annotation;(value=I4) + +class name java/awt/color/ICC_Profile +-method name finalize descriptor ()V + +class name java/awt/desktop/AboutEvent +header extends java/awt/desktop/AppEvent flags 31 + +class name java/awt/desktop/AboutHandler +header extends java/lang/Object flags 601 + +class name java/awt/desktop/AppEvent +header extends java/util/EventObject flags 21 + +class name java/awt/desktop/AppForegroundEvent +header extends java/awt/desktop/AppEvent flags 31 + +class name java/awt/desktop/AppForegroundListener +header extends java/lang/Object implements java/awt/desktop/SystemEventListener flags 601 + +class name java/awt/desktop/AppHiddenEvent +header extends java/awt/desktop/AppEvent flags 31 + +class name java/awt/desktop/AppHiddenListener +header extends java/lang/Object implements java/awt/desktop/SystemEventListener flags 601 + +class name java/awt/desktop/AppReopenedEvent +header extends java/awt/desktop/AppEvent flags 31 + +class name java/awt/desktop/AppReopenedListener +header extends java/lang/Object implements java/awt/desktop/SystemEventListener flags 601 + +class name java/awt/desktop/FilesEvent +header extends java/awt/desktop/AppEvent flags 21 + +class name java/awt/desktop/OpenFilesEvent +header extends java/awt/desktop/FilesEvent flags 31 + +class name java/awt/desktop/OpenFilesHandler +header extends java/lang/Object flags 601 + +class name java/awt/desktop/OpenURIEvent +header extends java/awt/desktop/AppEvent flags 31 + +class name java/awt/desktop/OpenURIHandler +header extends java/lang/Object flags 601 + +class name java/awt/desktop/PreferencesEvent +header extends java/awt/desktop/AppEvent flags 31 + +class name java/awt/desktop/PreferencesHandler +header extends java/lang/Object flags 601 + +class name java/awt/desktop/PrintFilesEvent +header extends java/awt/desktop/FilesEvent flags 31 + +class name java/awt/desktop/PrintFilesHandler +header extends java/lang/Object flags 601 + +class name java/awt/desktop/QuitEvent +header extends java/awt/desktop/AppEvent flags 31 + +class name java/awt/desktop/QuitHandler +header extends java/lang/Object flags 601 + +class name java/awt/desktop/QuitResponse +header extends java/lang/Object flags 601 + +class name java/awt/desktop/QuitStrategy +header extends java/lang/Enum flags 4031 signature Ljava/lang/Enum; + +class name java/awt/desktop/ScreenSleepEvent +header extends java/awt/desktop/AppEvent flags 31 + +class name java/awt/desktop/ScreenSleepListener +header extends java/lang/Object implements java/awt/desktop/SystemEventListener flags 601 + +class name java/awt/desktop/SystemEventListener +header extends java/lang/Object implements java/util/EventListener flags 601 + +class name java/awt/desktop/SystemSleepEvent +header extends java/awt/desktop/AppEvent flags 31 + +class name java/awt/desktop/SystemSleepListener +header extends java/lang/Object implements java/awt/desktop/SystemEventListener flags 601 + +class name java/awt/desktop/UserSessionListener +header extends java/lang/Object implements java/awt/desktop/SystemEventListener flags 601 + +class name java/awt/dnd/DragGestureEvent +header extends java/util/EventObject flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 + +class name java/awt/dnd/DragGestureRecognizer +header extends java/lang/Object implements java/io/Serializable flags 421 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 + +class name java/awt/dnd/DragSource +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/dnd/DropTargetDragEvent +header extends java/awt/dnd/DropTargetEvent flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/dnd/DropTargetDropEvent +header extends java/awt/dnd/DropTargetEvent flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/event/ActionEvent +header extends java/awt/AWTEvent flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/event/AdjustmentEvent +header extends java/awt/AWTEvent flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/event/ComponentEvent +header extends java/awt/AWTEvent flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/event/ContainerEvent +header extends java/awt/event/ComponentEvent flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/event/HierarchyEvent +header extends java/awt/AWTEvent flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/event/InputMethodEvent +header extends java/awt/AWTEvent flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/event/ItemEvent +header extends java/awt/AWTEvent flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/event/MouseWheelEvent +header extends java/awt/event/MouseEvent flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/event/PaintEvent +header extends java/awt/event/ComponentEvent flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/event/WindowEvent +header extends java/awt/event/ComponentEvent flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/font/FontRenderContext +header extends java/lang/Object flags 21 +innerclass innerClass java/awt/RenderingHints$Key outerClass java/awt/RenderingHints innerClassName Key flags 409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/font/GraphicAttribute +header extends java/lang/Object flags 421 +innerclass innerClass java/awt/geom/Rectangle2D$Float outerClass java/awt/geom/Rectangle2D innerClassName Float flags 9 + +class name java/awt/font/ImageGraphicAttribute +header extends java/awt/font/GraphicAttribute flags 31 +innerclass innerClass java/awt/geom/Rectangle2D$Float outerClass java/awt/geom/Rectangle2D innerClassName Float flags 9 + +class name java/awt/font/NumericShaper$Range +header extends java/lang/Enum nestHost java/awt/font/NumericShaper sealed true flags 4021 signature Ljava/lang/Enum; +innerclass innerClass java/awt/font/NumericShaper$Range outerClass java/awt/font/NumericShaper innerClassName Range flags 4009 + +class name java/awt/font/ShapeGraphicAttribute +header extends java/awt/font/GraphicAttribute flags 31 +innerclass innerClass java/awt/geom/Rectangle2D$Float outerClass java/awt/geom/Rectangle2D innerClassName Float flags 9 + +class name java/awt/font/TextHitInfo +header extends java/lang/Object flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/font/TextMeasurer +header extends java/lang/Object implements java/lang/Cloneable flags 31 +innerclass innerClass java/text/AttributedCharacterIterator$Attribute outerClass java/text/AttributedCharacterIterator innerClassName Attribute flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/geom/AffineTransform +header extends java/lang/Object implements java/lang/Cloneable,java/io/Serializable flags 21 +innerclass innerClass java/awt/geom/Point2D$Double outerClass java/awt/geom/Point2D innerClassName Double flags 9 +innerclass innerClass java/awt/geom/Point2D$Float outerClass java/awt/geom/Point2D innerClassName Float flags 9 +innerclass innerClass java/awt/geom/Path2D$Double outerClass java/awt/geom/Path2D innerClassName Double flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/geom/Area +header extends java/lang/Object implements java/awt/Shape,java/lang/Cloneable flags 21 +innerclass innerClass java/awt/geom/Rectangle2D$Double outerClass java/awt/geom/Rectangle2D innerClassName Double flags 9 + +class name java/awt/geom/RectangularShape +header extends java/lang/Object implements java/awt/Shape,java/lang/Cloneable flags 421 +innerclass innerClass java/awt/geom/Rectangle2D$Double outerClass java/awt/geom/Rectangle2D innerClassName Double flags 9 + +class name java/awt/image/AbstractMultiResolutionImage +header extends java/awt/Image implements java/awt/image/MultiResolutionImage flags 421 + +class name java/awt/image/BandCombineOp +header extends java/lang/Object implements java/awt/image/RasterOp flags 21 +innerclass innerClass java/awt/geom/Point2D$Float outerClass java/awt/geom/Point2D innerClassName Float flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/BandedSampleModel +header extends java/awt/image/ComponentSampleModel flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/BaseMultiResolutionImage +header extends java/awt/image/AbstractMultiResolutionImage flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/BufferedImageFilter +header extends java/awt/image/ImageFilter implements java/lang/Cloneable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/ByteLookupTable +header extends java/awt/image/LookupTable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/ColorConvertOp +header extends java/lang/Object implements java/awt/image/BufferedImageOp,java/awt/image/RasterOp flags 21 +innerclass innerClass java/awt/geom/Point2D$Float outerClass java/awt/geom/Point2D innerClassName Float flags 9 + +class name java/awt/image/ColorModel +-method name finalize descriptor ()V + +class name java/awt/image/ComponentColorModel +header extends java/awt/image/ColorModel flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/ComponentSampleModel +header extends java/awt/image/SampleModel flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/ConvolveOp +header extends java/lang/Object implements java/awt/image/BufferedImageOp,java/awt/image/RasterOp flags 21 +innerclass innerClass java/awt/geom/Point2D$Float outerClass java/awt/geom/Point2D innerClassName Float flags 9 + +class name java/awt/image/DataBufferUShort +header extends java/awt/image/DataBuffer flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/DirectColorModel +header extends java/awt/image/PackedColorModel flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/ImageFilter +header extends java/lang/Object implements java/awt/image/ImageConsumer,java/lang/Cloneable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/IndexColorModel +header extends java/awt/image/ColorModel flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +-method name finalize descriptor ()V + +class name java/awt/image/Kernel +header extends java/lang/Object implements java/lang/Cloneable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/LookupOp +header extends java/lang/Object implements java/awt/image/BufferedImageOp,java/awt/image/RasterOp flags 21 +innerclass innerClass java/awt/geom/Point2D$Float outerClass java/awt/geom/Point2D innerClassName Float flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/MultiPixelPackedSampleModel +header extends java/awt/image/SampleModel flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/MultiResolutionImage +header extends java/lang/Object flags 601 + +class name java/awt/image/PackedColorModel +header extends java/awt/image/ColorModel flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/Raster +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/ReplicateScaleFilter +header extends java/awt/image/ImageFilter flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/RescaleOp +header extends java/lang/Object implements java/awt/image/BufferedImageOp,java/awt/image/RasterOp flags 21 +innerclass innerClass java/awt/geom/Point2D$Float outerClass java/awt/geom/Point2D innerClassName Float flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/SampleModel +header extends java/lang/Object flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/ShortLookupTable +header extends java/awt/image/LookupTable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/SinglePixelPackedSampleModel +header extends java/awt/image/SampleModel flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/print/Paper +header extends java/lang/Object implements java/lang/Cloneable flags 21 +innerclass innerClass java/awt/geom/Rectangle2D$Double outerClass java/awt/geom/Rectangle2D innerClassName Double flags 9 + +class name java/beans/BeanProperty +header extends java/lang/Object implements java/lang/annotation/Annotation flags 2601 runtimeAnnotations @Ljava/lang/annotation/Documented;@Ljava/lang/annotation/Target;(value={eLjava/lang/annotation/ElementType;METHOD;})@Ljava/lang/annotation/Retention;(value=eLjava/lang/annotation/RetentionPolicy;RUNTIME;) + +class name java/beans/Beans +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/beans/DefaultPersistenceDelegate +header extends java/beans/PersistenceDelegate flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/beans/Encoder +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/beans/EventSetDescriptor +header extends java/beans/FeatureDescriptor flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/beans/Expression +header extends java/beans/Statement flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/beans/FeatureDescriptor +header extends java/lang/Object flags 21 +innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 + +class name java/beans/IndexedPropertyDescriptor +header extends java/beans/PropertyDescriptor flags 21 +innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/beans/JavaBean +header extends java/lang/Object implements java/lang/annotation/Annotation flags 2601 runtimeAnnotations @Ljava/lang/annotation/Documented;@Ljava/lang/annotation/Target;(value={eLjava/lang/annotation/ElementType;TYPE;})@Ljava/lang/annotation/Retention;(value=eLjava/lang/annotation/RetentionPolicy;RUNTIME;) + +class name java/beans/PropertyDescriptor +header extends java/beans/FeatureDescriptor flags 21 +innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/beans/SimpleBeanInfo +header extends java/lang/Object implements java/beans/BeanInfo flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/accessibility/AccessibilityProvider +header extends java/lang/Object flags 421 + +class name javax/accessibility/AccessibleBundle +header extends java/lang/Object flags 421 classAnnotations @Ljdk/Profile+Annotation;(value=I4) + +class name javax/accessibility/AccessibleRelationSet +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/accessibility/AccessibleStateSet +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/imageio/metadata/IIOMetadata +header extends java/lang/Object flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/imageio/plugins/jpeg/JPEGHuffmanTable +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/imageio/plugins/jpeg/JPEGQTable +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/imageio/plugins/tiff/TIFFDirectory +header extends java/lang/Object implements java/lang/Cloneable flags 21 + +class name javax/imageio/plugins/tiff/TIFFField +header extends java/lang/Object implements java/lang/Cloneable flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/imageio/plugins/tiff/TIFFImageReadParam +header extends javax/imageio/ImageReadParam flags 31 + +class name javax/imageio/plugins/tiff/TIFFTag +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/imageio/plugins/tiff/TIFFTagSet +header extends java/lang/Object flags 21 + +class name javax/imageio/spi/ImageReaderWriterSpi +header extends javax/imageio/spi/IIOServiceProvider flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/imageio/spi/ServiceRegistry +-method name finalize descriptor ()V +method name finalize descriptor ()V thrownTypes java/lang/Throwable flags 1 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="9") + +class name javax/imageio/stream/FileCacheImageInputStream +-method name finalize descriptor ()V +method name finalize descriptor ()V thrownTypes java/lang/Throwable flags 4 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="9") + +class name javax/imageio/stream/FileImageInputStream +-method name finalize descriptor ()V +method name finalize descriptor ()V thrownTypes java/lang/Throwable flags 4 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="9") + +class name javax/imageio/stream/FileImageOutputStream +-method name finalize descriptor ()V +method name finalize descriptor ()V thrownTypes java/lang/Throwable flags 4 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="9") + +class name javax/imageio/stream/ImageInputStreamImpl +-method name finalize descriptor ()V +method name finalize descriptor ()V thrownTypes java/lang/Throwable flags 4 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="9") + +class name javax/imageio/stream/MemoryCacheImageInputStream +-method name finalize descriptor ()V +method name finalize descriptor ()V thrownTypes java/lang/Throwable flags 4 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="9") + +class name javax/print/attribute/DateTimeSyntax +header extends java/lang/Object implements java/io/Serializable,java/lang/Cloneable flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/print/attribute/EnumSyntax +header extends java/lang/Object implements java/io/Serializable,java/lang/Cloneable flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/print/attribute/IntegerSyntax +header extends java/lang/Object implements java/io/Serializable,java/lang/Cloneable flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/print/attribute/standard/MediaPrintableArea +header extends java/lang/Object implements javax/print/attribute/DocAttribute,javax/print/attribute/PrintRequestAttribute,javax/print/attribute/PrintJobAttribute flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/print/event/PrintEvent +header extends java/util/EventObject flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/sound/midi/MetaMessage +header extends javax/sound/midi/MidiMessage flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/sound/midi/MidiMessage +header extends java/lang/Object implements java/lang/Cloneable flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/sound/midi/Sequence +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/sound/midi/ShortMessage +header extends javax/sound/midi/MidiMessage flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/sound/midi/SysexMessage +header extends javax/sound/midi/MidiMessage flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/sound/sampled/ReverbType +header extends java/lang/Object flags 21 classAnnotations @Ljdk/Profile+Annotation;(value=I4) + +class name javax/sound/sampled/spi/FormatConversionProvider +header extends java/lang/Object flags 421 +innerclass innerClass javax/sound/sampled/AudioFormat$Encoding outerClass javax/sound/sampled/AudioFormat innerClassName Encoding flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/BoxLayout +header extends java/lang/Object implements java/awt/LayoutManager2,java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/DebugGraphics +header extends java/awt/Graphics flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/DefaultBoundedRangeModel +header extends java/lang/Object implements javax/swing/BoundedRangeModel,java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/DefaultListSelectionModel +header extends java/lang/Object implements javax/swing/ListSelectionModel,java/lang/Cloneable,java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/GrayFilter +header extends java/awt/image/RGBImageFilter flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/GroupLayout +header extends java/lang/Object implements java/awt/LayoutManager2 nestMembers javax/swing/GroupLayout$ParallelGroup,javax/swing/GroupLayout$SequentialGroup,javax/swing/GroupLayout$Group,javax/swing/GroupLayout$Spring,javax/swing/GroupLayout$Alignment flags 21 +innerclass innerClass javax/swing/GroupLayout$Alignment outerClass javax/swing/GroupLayout innerClassName Alignment flags 4019 +innerclass innerClass javax/swing/GroupLayout$ParallelGroup outerClass javax/swing/GroupLayout innerClassName ParallelGroup flags 1 +innerclass innerClass javax/swing/GroupLayout$Group outerClass javax/swing/GroupLayout innerClassName Group flags 401 +innerclass innerClass javax/swing/GroupLayout$SequentialGroup outerClass javax/swing/GroupLayout innerClassName SequentialGroup flags 1 +innerclass innerClass javax/swing/GroupLayout$Spring outerClass javax/swing/GroupLayout innerClassName Spring flags 40a +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/GroupLayout$Group +header extends javax/swing/GroupLayout$Spring nestHost javax/swing/GroupLayout flags 421 +innerclass innerClass javax/swing/GroupLayout$Group outerClass javax/swing/GroupLayout innerClassName Group flags 401 +innerclass innerClass javax/swing/GroupLayout$Spring outerClass javax/swing/GroupLayout innerClassName Spring flags 40a + +class name javax/swing/GroupLayout$ParallelGroup +header extends javax/swing/GroupLayout$Group nestHost javax/swing/GroupLayout flags 21 +innerclass innerClass javax/swing/GroupLayout$ParallelGroup outerClass javax/swing/GroupLayout innerClassName ParallelGroup flags 1 +innerclass innerClass javax/swing/GroupLayout$Group outerClass javax/swing/GroupLayout innerClassName Group flags 401 +innerclass innerClass javax/swing/GroupLayout$Alignment outerClass javax/swing/GroupLayout innerClassName Alignment flags 4019 +innerclass innerClass javax/swing/GroupLayout$Spring outerClass javax/swing/GroupLayout innerClassName Spring flags 40a + +class name javax/swing/GroupLayout$SequentialGroup +header extends javax/swing/GroupLayout$Group nestHost javax/swing/GroupLayout flags 21 +innerclass innerClass javax/swing/GroupLayout$SequentialGroup outerClass javax/swing/GroupLayout innerClassName SequentialGroup flags 1 +innerclass innerClass javax/swing/GroupLayout$Group outerClass javax/swing/GroupLayout innerClassName Group flags 401 +innerclass innerClass javax/swing/GroupLayout$Spring outerClass javax/swing/GroupLayout innerClassName Spring flags 40a +innerclass innerClass javax/swing/LayoutStyle$ComponentPlacement outerClass javax/swing/LayoutStyle innerClassName ComponentPlacement flags 4019 +innerclass innerClass java/awt/Component$BaselineResizeBehavior outerClass java/awt/Component innerClassName BaselineResizeBehavior flags 4019 + +class name javax/swing/GroupLayout$Spring +header extends java/lang/Object nestHost javax/swing/GroupLayout flags 420 +innerclass innerClass javax/swing/GroupLayout$Spring outerClass javax/swing/GroupLayout innerClassName Spring flags 40a +innerclass innerClass javax/swing/GroupLayout$Alignment outerClass javax/swing/GroupLayout innerClassName Alignment flags 4019 +innerclass innerClass java/awt/Component$BaselineResizeBehavior outerClass java/awt/Component innerClassName BaselineResizeBehavior flags 4019 + +class name javax/swing/JList$AccessibleJList$AccessibleJListChild +-method name getAccessibleAction descriptor ()Ljavax/accessibility/AccessibleAction; +method name getAccessibleAction descriptor ()Ljavax/accessibility/AccessibleAction; flags 1 + +class name javax/swing/JTextPane +header extends javax/swing/JEditorPane flags 21 runtimeAnnotations @Ljava/beans/JavaBean;(description="A\u005C;u0020;text\u005C;u0020;component\u005C;u0020;that\u005C;u0020;can\u005C;u0020;be\u005C;u0020;marked\u005C;u0020;up\u005C;u0020;with\u005C;u0020;attributes\u005C;u0020;that\u005C;u0020;are\u005C;u0020;graphically\u005C;u0020;represented.")@Ljavax/swing/SwingContainer; + +class name javax/swing/LookAndFeel +header extends java/lang/Object flags 421 +innerclass innerClass javax/swing/text/JTextComponent$KeyBinding outerClass javax/swing/text/JTextComponent innerClassName KeyBinding flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/MenuSelectionManager +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/SizeRequirements +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/SortingFocusTraversalPolicy +header extends javax/swing/InternalFrameFocusTraversalPolicy flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/SwingContainer +header extends java/lang/Object implements java/lang/annotation/Annotation flags 2601 runtimeAnnotations @Ljava/lang/annotation/Target;(value={eLjava/lang/annotation/ElementType;TYPE;})@Ljava/lang/annotation/Retention;(value=eLjava/lang/annotation/RetentionPolicy;RUNTIME;) + +class name javax/swing/UIClientPropertyKey +header extends java/lang/Object flags 601 + +class name javax/swing/border/LineBorder +header extends javax/swing/border/AbstractBorder flags 21 +innerclass innerClass java/awt/geom/RoundRectangle2D$Float outerClass java/awt/geom/RoundRectangle2D innerClassName Float flags 9 +innerclass innerClass java/awt/geom/Rectangle2D$Float outerClass java/awt/geom/Rectangle2D innerClassName Float flags 9 +innerclass innerClass java/awt/geom/Path2D$Float outerClass java/awt/geom/Path2D innerClassName Float flags 9 + +class name javax/swing/event/EventListenerList +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/event/ListDataEvent +header extends java/util/EventObject flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/event/ListSelectionEvent +header extends java/util/EventObject flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/event/TreeModelEvent +header extends java/util/EventObject flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/filechooser/FileNameExtensionFilter +header extends javax/swing/filechooser/FileFilter flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/plaf/basic/BasicArrowButton +header extends javax/swing/JButton implements javax/swing/SwingConstants flags 21 +innerclass innerClass java/awt/geom/Path2D$Double outerClass java/awt/geom/Path2D innerClassName Double flags 9 + +class name javax/swing/plaf/basic/BasicButtonUI +header extends javax/swing/plaf/ButtonUI flags 21 +innerclass innerClass java/awt/Component$BaselineResizeBehavior outerClass java/awt/Component innerClassName BaselineResizeBehavior flags 4019 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/plaf/basic/BasicPasswordFieldUI +header extends javax/swing/plaf/basic/BasicTextFieldUI flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/plaf/basic/BasicSplitPaneUI$BasicVerticalLayoutManager +header extends javax/swing/plaf/basic/BasicSplitPaneUI$BasicHorizontalLayoutManager nestHost javax/swing/plaf/basic/BasicSplitPaneUI flags 21 +innerclass innerClass javax/swing/plaf/basic/BasicSplitPaneUI$BasicHorizontalLayoutManager outerClass javax/swing/plaf/basic/BasicSplitPaneUI innerClassName BasicHorizontalLayoutManager flags 1 +innerclass innerClass javax/swing/plaf/basic/BasicSplitPaneUI$BasicVerticalLayoutManager outerClass javax/swing/plaf/basic/BasicSplitPaneUI innerClassName BasicVerticalLayoutManager flags 1 + +class name javax/swing/plaf/basic/BasicToolBarSeparatorUI +header extends javax/swing/plaf/basic/BasicSeparatorUI flags 21 +innerclass innerClass javax/swing/JToolBar$Separator outerClass javax/swing/JToolBar innerClassName Separator flags 9 + +class name javax/swing/plaf/metal/MetalButtonUI +header extends javax/swing/plaf/basic/BasicButtonUI flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/plaf/metal/MetalCheckBoxUI +header extends javax/swing/plaf/metal/MetalRadioButtonUI flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/plaf/metal/MetalRadioButtonUI +header extends javax/swing/plaf/basic/BasicRadioButtonUI flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/plaf/metal/MetalTabbedPaneUI$TabbedPaneLayout +header extends javax/swing/plaf/basic/BasicTabbedPaneUI$TabbedPaneLayout nestHost javax/swing/plaf/metal/MetalTabbedPaneUI flags 21 +innerclass innerClass javax/swing/plaf/basic/BasicTabbedPaneUI$TabbedPaneLayout outerClass javax/swing/plaf/basic/BasicTabbedPaneUI innerClassName TabbedPaneLayout flags 1 +innerclass innerClass javax/swing/plaf/metal/MetalTabbedPaneUI$TabbedPaneLayout outerClass javax/swing/plaf/metal/MetalTabbedPaneUI innerClassName TabbedPaneLayout flags 1 + +class name javax/swing/plaf/metal/MetalToggleButtonUI +header extends javax/swing/plaf/basic/BasicToggleButtonUI flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/plaf/metal/MetalToolBarUI$MetalContainerListener +header extends javax/swing/plaf/basic/BasicToolBarUI$ToolBarContListener nestHost javax/swing/plaf/metal/MetalToolBarUI flags 21 +innerclass innerClass javax/swing/plaf/basic/BasicToolBarUI$ToolBarContListener outerClass javax/swing/plaf/basic/BasicToolBarUI innerClassName ToolBarContListener flags 4 +innerclass innerClass javax/swing/plaf/metal/MetalToolBarUI$MetalContainerListener outerClass javax/swing/plaf/metal/MetalToolBarUI innerClassName MetalContainerListener flags 4 + +class name javax/swing/plaf/metal/MetalToolBarUI$MetalRolloverListener +header extends javax/swing/plaf/basic/BasicToolBarUI$PropertyListener nestHost javax/swing/plaf/metal/MetalToolBarUI flags 21 +innerclass innerClass javax/swing/plaf/basic/BasicToolBarUI$PropertyListener outerClass javax/swing/plaf/basic/BasicToolBarUI innerClassName PropertyListener flags 4 +innerclass innerClass javax/swing/plaf/metal/MetalToolBarUI$MetalRolloverListener outerClass javax/swing/plaf/metal/MetalToolBarUI innerClassName MetalRolloverListener flags 4 + +class name javax/swing/plaf/metal/MetalToolTipUI +header extends javax/swing/plaf/basic/BasicToolTipUI flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/plaf/multi/MultiLookAndFeel +header extends javax/swing/LookAndFeel flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/plaf/synth/SynthButtonUI +header extends javax/swing/plaf/basic/BasicButtonUI implements java/beans/PropertyChangeListener,javax/swing/plaf/synth/SynthUI flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/plaf/synth/SynthIcon +header extends java/lang/Object implements javax/swing/Icon flags 601 + +class name javax/swing/plaf/synth/SynthMenuItemUI +header extends javax/swing/plaf/basic/BasicMenuItemUI implements java/beans/PropertyChangeListener,javax/swing/plaf/synth/SynthUI flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/plaf/synth/SynthMenuUI +header extends javax/swing/plaf/basic/BasicMenuUI implements java/beans/PropertyChangeListener,javax/swing/plaf/synth/SynthUI flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/plaf/synth/SynthSeparatorUI +header extends javax/swing/plaf/SeparatorUI implements java/beans/PropertyChangeListener,javax/swing/plaf/synth/SynthUI flags 21 +innerclass innerClass javax/swing/JToolBar$Separator outerClass javax/swing/JToolBar innerClassName Separator flags 9 + +class name javax/swing/plaf/synth/SynthStyle +header extends java/lang/Object flags 421 +innerclass innerClass javax/swing/UIDefaults$LazyInputMap outerClass javax/swing/UIDefaults innerClassName LazyInputMap flags 9 +innerclass innerClass javax/swing/UIDefaults$LazyValue outerClass javax/swing/UIDefaults innerClassName LazyValue flags 609 + +class name javax/swing/table/AbstractTableModel +header extends java/lang/Object implements javax/swing/table/TableModel,java/io/Serializable flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/text/AbstractWriter +header extends java/lang/Object flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/text/BoxView +header extends javax/swing/text/CompositeView flags 21 +innerclass innerClass javax/swing/event/DocumentEvent$ElementChange outerClass javax/swing/event/DocumentEvent innerClassName ElementChange flags 609 +innerclass innerClass javax/swing/text/Position$Bias outerClass javax/swing/text/Position innerClassName Bias flags 19 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/text/CompositeView +header extends javax/swing/text/View flags 421 +innerclass innerClass javax/swing/text/Position$Bias outerClass javax/swing/text/Position innerClassName Bias flags 19 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/text/DateFormatter +header extends javax/swing/text/InternationalFormatter flags 21 +innerclass innerClass java/text/DateFormat$Field outerClass java/text/DateFormat innerClassName Field flags 9 + +class name javax/swing/text/IconView +header extends javax/swing/text/View flags 21 +innerclass innerClass javax/swing/text/Position$Bias outerClass javax/swing/text/Position innerClassName Bias flags 19 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/text/LayoutQueue +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/text/NumberFormatter +header extends javax/swing/text/InternationalFormatter flags 21 +innerclass innerClass java/text/NumberFormat$Field outerClass java/text/NumberFormat innerClassName Field flags 9 +innerclass innerClass javax/swing/text/DocumentFilter$FilterBypass outerClass javax/swing/text/DocumentFilter innerClassName FilterBypass flags 409 +innerclass innerClass java/text/AttributedCharacterIterator$Attribute outerClass java/text/AttributedCharacterIterator innerClassName Attribute flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/text/Segment +header extends java/lang/Object implements java/lang/Cloneable,java/text/CharacterIterator,java/lang/CharSequence flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/text/TabSet +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/text/TabStop +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/text/View +header extends java/lang/Object implements javax/swing/SwingConstants flags 421 +innerclass innerClass javax/swing/text/Position$Bias outerClass javax/swing/text/Position innerClassName Bias flags 19 +innerclass innerClass javax/swing/event/DocumentEvent$ElementChange outerClass javax/swing/event/DocumentEvent innerClassName ElementChange flags 609 +innerclass innerClass javax/swing/event/DocumentEvent$EventType outerClass javax/swing/event/DocumentEvent innerClassName EventType flags 19 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/text/html/InlineView +header extends javax/swing/text/LabelView flags 21 +innerclass innerClass javax/swing/text/html/CSS$Attribute outerClass javax/swing/text/html/CSS innerClassName Attribute flags 19 + +class name javax/swing/text/html/ListView +header extends javax/swing/text/html/BlockView flags 21 +innerclass innerClass javax/swing/text/html/StyleSheet$ListPainter outerClass javax/swing/text/html/StyleSheet innerClassName ListPainter flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/text/html/MinimalHTMLWriter +header extends javax/swing/text/AbstractWriter flags 21 +innerclass innerClass javax/swing/text/StyleConstants$ParagraphConstants outerClass javax/swing/text/StyleConstants innerClassName ParagraphConstants flags 9 +innerclass innerClass javax/swing/text/StyleConstants$CharacterConstants outerClass javax/swing/text/StyleConstants innerClassName CharacterConstants flags 9 +innerclass innerClass javax/swing/text/StyleConstants$FontConstants outerClass javax/swing/text/StyleConstants innerClassName FontConstants flags 9 +innerclass innerClass javax/swing/text/StyleConstants$ColorConstants outerClass javax/swing/text/StyleConstants innerClassName ColorConstants flags 9 +innerclass innerClass javax/swing/text/AbstractDocument$BranchElement outerClass javax/swing/text/AbstractDocument innerClassName BranchElement flags 1 +innerclass innerClass javax/swing/text/StyleContext$NamedStyle outerClass javax/swing/text/StyleContext innerClassName NamedStyle flags 1 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/text/html/ObjectView +header extends javax/swing/text/ComponentView flags 21 +innerclass innerClass javax/swing/text/html/HTML$Attribute outerClass javax/swing/text/html/HTML innerClassName Attribute flags 19 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/text/html/Option +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass javax/swing/text/html/HTML$Attribute outerClass javax/swing/text/html/HTML innerClassName Attribute flags 19 + +class name javax/swing/text/html/ParagraphView +header extends javax/swing/text/ParagraphView flags 21 +innerclass innerClass javax/swing/text/html/StyleSheet$BoxPainter outerClass javax/swing/text/html/StyleSheet innerClassName BoxPainter flags 9 +innerclass innerClass javax/swing/text/html/CSS$Attribute outerClass javax/swing/text/html/CSS innerClassName Attribute flags 19 + +class name javax/swing/text/html/parser/ContentModel +header extends java/lang/Object implements java/io/Serializable flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/text/html/parser/DocumentParser +header extends javax/swing/text/html/parser/Parser flags 21 +innerclass innerClass javax/swing/text/html/HTMLEditorKit$ParserCallback outerClass javax/swing/text/html/HTMLEditorKit innerClassName ParserCallback flags 9 +innerclass innerClass javax/swing/text/html/HTML$Tag outerClass javax/swing/text/html/HTML innerClassName Tag flags 9 +innerclass innerClass javax/swing/text/html/HTML$Attribute outerClass javax/swing/text/html/HTML innerClassName Attribute flags 19 + +class name javax/swing/text/html/parser/Parser +header extends java/lang/Object implements javax/swing/text/html/parser/DTDConstants flags 21 +innerclass innerClass javax/swing/text/html/HTML$Attribute outerClass javax/swing/text/html/HTML innerClassName Attribute flags 19 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/text/html/parser/TagElement +header extends java/lang/Object flags 21 +innerclass innerClass javax/swing/text/html/HTML$Tag outerClass javax/swing/text/html/HTML innerClassName Tag flags 9 +innerclass innerClass javax/swing/text/html/HTML$UnknownTag outerClass javax/swing/text/html/HTML innerClassName UnknownTag flags 9 + +class name javax/swing/tree/DefaultTreeModel +header extends java/lang/Object implements java/io/Serializable,javax/swing/tree/TreeModel flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 + +class name javax/swing/tree/DefaultTreeSelectionModel +header extends java/lang/Object implements java/lang/Cloneable,java/io/Serializable,javax/swing/tree/TreeSelectionModel flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/tree/TreePath +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/undo/AbstractUndoableEdit +header extends java/lang/Object implements javax/swing/undo/UndoableEdit,java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/undo/CompoundEdit +header extends javax/swing/undo/AbstractUndoableEdit flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/undo/UndoableEditSupport +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + diff --git a/make/data/symbols/java.instrument-I.sym.txt b/make/data/symbols/java.instrument-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..9f7539e822613fcf2d4f82865bfa24fdbd5add3f --- /dev/null +++ b/make/data/symbols/java.instrument-I.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name java/lang/instrument/UnmodifiableModuleException +header extends java/lang/RuntimeException flags 21 + diff --git a/make/data/symbols/java.logging-I.sym.txt b/make/data/symbols/java.logging-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..0c5aabcc4bb913e7a9243924fb88f58bebf52876 --- /dev/null +++ b/make/data/symbols/java.logging-I.sym.txt @@ -0,0 +1,55 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name java/util/logging/ErrorManager +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/logging/LoggingMXBean +header extends java/lang/Object flags 601 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") + +class name java/util/logging/LoggingPermission +header extends java/security/BasicPermission flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/logging/MemoryHandler +header extends java/util/logging/Handler flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/logging/SimpleFormatter +header extends java/util/logging/Formatter flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/logging/SocketHandler +header extends java/util/logging/StreamHandler flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/logging/XMLFormatter +header extends java/util/logging/Formatter flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + diff --git a/make/data/symbols/java.management-I.sym.txt b/make/data/symbols/java.management-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..ae261e32e0c9f49286e1f3aff065ff916b0bc286 --- /dev/null +++ b/make/data/symbols/java.management-I.sym.txt @@ -0,0 +1,269 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name java/lang/management/LockInfo +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/lang/management/ManagementPermission +header extends java/security/BasicPermission flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/lang/management/MemoryMXBean +-method name getObjectPendingFinalizationCount descriptor ()I +method name getObjectPendingFinalizationCount descriptor ()I flags 401 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="18") + +class name java/lang/management/MemoryUsage +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/lang/management/MonitorInfo +header extends java/lang/management/LockInfo flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/lang/management/RuntimeMXBean +header extends java/lang/Object implements java/lang/management/PlatformManagedObject flags 601 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/Attribute +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/AttributeList +header extends java/util/ArrayList flags 21 signature Ljava/util/ArrayList; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/BadAttributeValueExpException +header extends java/lang/Exception flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/BadBinaryOpValueExpException +header extends java/lang/Exception flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/BadStringOperationException +header extends java/lang/Exception flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/ConstructorParameters +header extends java/lang/Object implements java/lang/annotation/Annotation flags 2601 runtimeAnnotations @Ljava/lang/annotation/Documented;@Ljava/lang/annotation/Target;(value={eLjava/lang/annotation/ElementType;CONSTRUCTOR;})@Ljava/lang/annotation/Retention;(value=eLjava/lang/annotation/RetentionPolicy;RUNTIME;) + +class name javax/management/ImmutableDescriptor +header extends java/lang/Object implements javax/management/Descriptor flags 21 +innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/MBeanAttributeInfo +header extends javax/management/MBeanFeatureInfo implements java/lang/Cloneable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/MBeanConstructorInfo +header extends javax/management/MBeanFeatureInfo implements java/lang/Cloneable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/MBeanNotificationInfo +header extends javax/management/MBeanFeatureInfo implements java/lang/Cloneable flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/MBeanOperationInfo +header extends javax/management/MBeanFeatureInfo implements java/lang/Cloneable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/MBeanParameterInfo +header extends javax/management/MBeanFeatureInfo implements java/lang/Cloneable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/MBeanPermission +header extends java/security/Permission flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/MBeanServerDelegate +header extends java/lang/Object implements javax/management/MBeanServerDelegateMBean,javax/management/NotificationEmitter flags 21 +innerclass innerClass java/lang/System$Logger outerClass java/lang/System innerClassName Logger flags 609 +innerclass innerClass java/lang/System$Logger$Level outerClass java/lang/System$Logger innerClassName Level flags 4019 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/MBeanServerFactory +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/System$Logger outerClass java/lang/System innerClassName Logger flags 609 +innerclass innerClass java/lang/System$Logger$Level outerClass java/lang/System$Logger innerClassName Level flags 4019 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/MBeanServerInvocationHandler +header extends java/lang/Object implements java/lang/reflect/InvocationHandler flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/MBeanServerNotification +header extends javax/management/Notification flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/MBeanServerPermission +header extends java/security/BasicPermission flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/MBeanTrustPermission +header extends java/security/BasicPermission flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/Notification +header extends java/util/EventObject flags 21 +innerclass innerClass java/io/ObjectOutputStream$PutField outerClass java/io/ObjectOutputStream innerClassName PutField flags 409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/ObjectInstance +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/Query +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/StandardEmitterMBean +header extends javax/management/StandardMBean implements javax/management/NotificationEmitter flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/StringValueExp +header extends java/lang/Object implements javax/management/ValueExp flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/loading/DefaultLoaderRepository +header extends java/lang/Object flags 21 deprecated true runtimeAnnotations @Ljava/lang/Deprecated; +innerclass innerClass java/lang/System$Logger outerClass java/lang/System innerClassName Logger flags 609 +innerclass innerClass java/lang/System$Logger$Level outerClass java/lang/System$Logger innerClassName Level flags 4019 + +class name javax/management/loading/MLetContent +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/modelmbean/InvalidTargetObjectTypeException +header extends java/lang/Exception flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/io/ObjectOutputStream$PutField outerClass java/io/ObjectOutputStream innerClassName PutField flags 409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/modelmbean/XMLParseException +header extends java/lang/Exception flags 21 +innerclass innerClass java/io/ObjectOutputStream$PutField outerClass java/io/ObjectOutputStream innerClassName PutField flags 409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/openmbean/ArrayType +header extends javax/management/openmbean/OpenType flags 21 signature Ljavax/management/openmbean/OpenType; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/openmbean/CompositeDataInvocationHandler +header extends java/lang/Object implements java/lang/reflect/InvocationHandler flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/openmbean/CompositeDataSupport +header extends java/lang/Object implements javax/management/openmbean/CompositeData,java/io/Serializable flags 21 +innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/openmbean/CompositeType +header extends javax/management/openmbean/OpenType flags 21 signature Ljavax/management/openmbean/OpenType; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/openmbean/OpenMBeanAttributeInfoSupport +header extends javax/management/MBeanAttributeInfo implements javax/management/openmbean/OpenMBeanAttributeInfo flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/openmbean/OpenMBeanOperationInfoSupport +header extends javax/management/MBeanOperationInfo implements javax/management/openmbean/OpenMBeanOperationInfo flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/openmbean/SimpleType +header extends javax/management/openmbean/OpenType flags 31 signature Ljavax/management/openmbean/OpenType; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/openmbean/TabularDataSupport +header extends java/lang/Object implements javax/management/openmbean/TabularData,java/util/Map,java/lang/Cloneable,java/io/Serializable flags 21 signature Ljava/lang/Object;Ljavax/management/openmbean/TabularData;Ljava/util/Map;Ljava/lang/Cloneable;Ljava/io/Serializable; +innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/openmbean/TabularType +header extends javax/management/openmbean/OpenType flags 21 signature Ljavax/management/openmbean/OpenType; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/relation/RelationNotification +header extends javax/management/Notification flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/io/ObjectOutputStream$PutField outerClass java/io/ObjectOutputStream innerClassName PutField flags 409 + +class name javax/management/relation/RelationSupport +header extends java/lang/Object implements javax/management/relation/RelationSupportMBean,javax/management/MBeanRegistration flags 21 +innerclass innerClass java/lang/System$Logger outerClass java/lang/System innerClassName Logger flags 609 +innerclass innerClass java/lang/System$Logger$Level outerClass java/lang/System$Logger innerClassName Level flags 4019 + +class name javax/management/relation/Role +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/io/ObjectOutputStream$PutField outerClass java/io/ObjectOutputStream innerClassName PutField flags 409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/relation/RoleInfo +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/io/ObjectOutputStream$PutField outerClass java/io/ObjectOutputStream innerClassName PutField flags 409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/relation/RoleResult +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/io/ObjectOutputStream$PutField outerClass java/io/ObjectOutputStream innerClassName PutField flags 409 + +class name javax/management/relation/RoleUnresolved +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/io/ObjectOutputStream$PutField outerClass java/io/ObjectOutputStream innerClassName PutField flags 409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/remote/JMXConnectorServerFactory +header extends java/lang/Object flags 21 +innerclass innerClass java/util/ServiceLoader$Provider outerClass java/util/ServiceLoader innerClassName Provider flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/remote/JMXPrincipal +header extends java/lang/Object implements java/security/Principal,java/io/Serializable flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/remote/JMXServiceURL +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/remote/NotificationResult +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/remote/TargetedNotification +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + diff --git a/make/data/symbols/java.management.rmi-I.sym.txt b/make/data/symbols/java.management.rmi-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..18477d6862fb9b090aa665edc321161a80ec44a0 --- /dev/null +++ b/make/data/symbols/java.management.rmi-I.sym.txt @@ -0,0 +1,39 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name javax/management/remote/rmi/RMIConnectorServer +header extends javax/management/remote/JMXConnectorServer flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/remote/rmi/RMIIIOPServerImpl +header extends javax/management/remote/rmi/RMIServerImpl flags 21 deprecated true runtimeAnnotations @Ljava/lang/Deprecated; + +class name javax/management/remote/rmi/RMIServerImpl +header extends java/lang/Object implements java/io/Closeable,javax/management/remote/rmi/RMIServer flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + diff --git a/make/data/symbols/java.naming-I.sym.txt b/make/data/symbols/java.naming-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..f913ec6f184bff2d13a5184d6b1f445ca38c21f9 --- /dev/null +++ b/make/data/symbols/java.naming-I.sym.txt @@ -0,0 +1,76 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name javax/naming/BinaryRefAddr +header extends javax/naming/RefAddr flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/naming/Binding +header extends javax/naming/NameClassPair flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/naming/CompositeName +header extends java/lang/Object implements javax/naming/Name flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/naming/CompoundName +header extends java/lang/Object implements javax/naming/Name flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/naming/LinkException +header extends javax/naming/NamingException flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/naming/NameClassPair +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/naming/NamingException +header extends java/lang/Exception flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/naming/RefAddr +header extends java/lang/Object implements java/io/Serializable flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/naming/Reference +header extends java/lang/Object implements java/lang/Cloneable,java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/naming/directory/AttributeModificationException +header extends javax/naming/NamingException flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/naming/directory/ModificationItem +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/naming/directory/SearchResult +header extends javax/naming/Binding flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + diff --git a/make/data/symbols/java.net.http-I.sym.txt b/make/data/symbols/java.net.http-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..718ae0a2c6f76482ce71f02b3c3edaff5b9f3985 --- /dev/null +++ b/make/data/symbols/java.net.http-I.sym.txt @@ -0,0 +1,36 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name java/net/http/HttpRequest$Builder +header extends java/lang/Object nestHost java/net/http/HttpRequest flags 601 +innerclass innerClass java/net/http/HttpRequest$BodyPublishers outerClass java/net/http/HttpRequest innerClassName BodyPublishers flags 9 +innerclass innerClass java/net/http/HttpRequest$BodyPublisher outerClass java/net/http/HttpRequest innerClassName BodyPublisher flags 609 +innerclass innerClass java/net/http/HttpRequest$Builder outerClass java/net/http/HttpRequest innerClassName Builder flags 609 +innerclass innerClass java/net/http/HttpClient$Version outerClass java/net/http/HttpClient innerClassName Version flags 4019 +method name HEAD descriptor ()Ljava/net/http/HttpRequest$Builder; flags 1 + diff --git a/make/data/symbols/java.rmi-I.sym.txt b/make/data/symbols/java.rmi-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..9e577bb975ca0af4c80ecef1dfe574adc436a551 --- /dev/null +++ b/make/data/symbols/java.rmi-I.sym.txt @@ -0,0 +1,52 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name java/rmi/RemoteException +header extends java/io/IOException flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/rmi/dgc/VMID +header extends java/lang/Object implements java/io/Serializable flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/rmi/server/ObjID +header extends java/lang/Object implements java/io/Serializable flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/rmi/server/RemoteObject +header extends java/lang/Object implements java/rmi/Remote,java/io/Serializable flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/rmi/server/ServerCloneException +header extends java/lang/CloneNotSupportedException flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/rmi/server/UID +header extends java/lang/Object implements java/io/Serializable flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + diff --git a/make/data/symbols/java.scripting-I.sym.txt b/make/data/symbols/java.scripting-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..661fc972e825f36a278c3e0187ba52bb7081d418 --- /dev/null +++ b/make/data/symbols/java.scripting-I.sym.txt @@ -0,0 +1,32 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name javax/script/ScriptException +header extends java/lang/Exception flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + diff --git a/make/data/symbols/java.security.jgss-I.sym.txt b/make/data/symbols/java.security.jgss-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..6af48bfea4aeade47ff8c10898c1e6fa0e175929 --- /dev/null +++ b/make/data/symbols/java.security.jgss-I.sym.txt @@ -0,0 +1,69 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name javax/security/auth/kerberos/DelegationPermission +header extends java/security/BasicPermission implements java/io/Serializable flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/security/auth/kerberos/EncryptionKey +header extends java/lang/Object implements javax/crypto/SecretKey flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/security/auth/kerberos/KerberosCredMessage +header extends java/lang/Object implements javax/security/auth/Destroyable flags 31 +innerclass innerClass java/util/Base64$Encoder outerClass java/util/Base64 innerClassName Encoder flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/security/auth/kerberos/KerberosKey +header extends java/lang/Object implements javax/crypto/SecretKey flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/security/auth/kerberos/KerberosPrincipal +header extends java/lang/Object implements java/security/Principal,java/io/Serializable flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/security/auth/kerberos/KerberosTicket +header extends java/lang/Object implements javax/security/auth/Destroyable,javax/security/auth/Refreshable,java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/security/auth/kerberos/KeyTab +header extends java/lang/Object flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/security/auth/kerberos/ServicePermission +header extends java/security/Permission implements java/io/Serializable flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name org/ietf/jgss/GSSException +header extends java/lang/Exception flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name org/ietf/jgss/Oid +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + diff --git a/make/data/symbols/java.security.sasl-I.sym.txt b/make/data/symbols/java.security.sasl-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..37bab20606abb562b3f564e30882c5359b873e18 --- /dev/null +++ b/make/data/symbols/java.security.sasl-I.sym.txt @@ -0,0 +1,32 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name javax/security/sasl/SaslException +header extends java/io/IOException flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + diff --git a/make/data/symbols/java.smartcardio-I.sym.txt b/make/data/symbols/java.smartcardio-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..63ca75a641ec247e8ab443d4c1d5faf1d5467e72 --- /dev/null +++ b/make/data/symbols/java.smartcardio-I.sym.txt @@ -0,0 +1,62 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name javax/smartcardio/ATR +header extends java/lang/Object implements java/io/Serializable flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/smartcardio/Card +header extends java/lang/Object flags 421 + +class name javax/smartcardio/CardChannel +header extends java/lang/Object flags 421 + +class name javax/smartcardio/CardException +header extends java/lang/Exception flags 21 + +class name javax/smartcardio/CardNotPresentException +header extends javax/smartcardio/CardException flags 21 + +class name javax/smartcardio/CardPermission +header extends java/security/Permission flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/smartcardio/CardTerminal +header extends java/lang/Object flags 421 + +class name javax/smartcardio/CommandAPDU +header extends java/lang/Object implements java/io/Serializable flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/smartcardio/ResponseAPDU +header extends java/lang/Object implements java/io/Serializable flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/smartcardio/TerminalFactorySpi +header extends java/lang/Object flags 421 + diff --git a/make/data/symbols/java.sql-I.sym.txt b/make/data/symbols/java.sql-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..16586cf28ca2f5c4ffe01573f07f48fe1e7c19c4 --- /dev/null +++ b/make/data/symbols/java.sql-I.sym.txt @@ -0,0 +1,60 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name java/sql/BatchUpdateException +header extends java/sql/SQLException flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/io/ObjectOutputStream$PutField outerClass java/io/ObjectOutputStream innerClassName PutField flags 409 + +class name java/sql/ConnectionBuilder +header extends java/lang/Object flags 601 + +class name java/sql/JDBCType +header extends java/lang/Enum implements java/sql/SQLType flags 4031 signature Ljava/lang/Enum;Ljava/sql/SQLType; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/sql/SQLWarning +header extends java/sql/SQLException flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/sql/ShardingKey +header extends java/lang/Object flags 601 + +class name java/sql/ShardingKeyBuilder +header extends java/lang/Object flags 601 + +class name java/sql/Statement +header extends java/lang/Object implements java/sql/Wrapper,java/lang/AutoCloseable flags 601 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/sql/PooledConnectionBuilder +header extends java/lang/Object flags 601 + +class name javax/sql/XAConnectionBuilder +header extends java/lang/Object flags 601 + diff --git a/make/data/symbols/java.sql.rowset-I.sym.txt b/make/data/symbols/java.sql.rowset-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..ea90b56bbc7363c76ad0b788b4b91bc1c0f69b41 --- /dev/null +++ b/make/data/symbols/java.sql.rowset-I.sym.txt @@ -0,0 +1,69 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name javax/sql/rowset/BaseRowSet +header extends java/lang/Object implements java/io/Serializable,java/lang/Cloneable flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/sql/rowset/serial/SerialArray +header extends java/lang/Object implements java/sql/Array,java/io/Serializable,java/lang/Cloneable flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/io/ObjectOutputStream$PutField outerClass java/io/ObjectOutputStream innerClassName PutField flags 409 + +class name javax/sql/rowset/serial/SerialBlob +header extends java/lang/Object implements java/sql/Blob,java/io/Serializable,java/lang/Cloneable flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/io/ObjectOutputStream$PutField outerClass java/io/ObjectOutputStream innerClassName PutField flags 409 + +class name javax/sql/rowset/serial/SerialClob +header extends java/lang/Object implements java/sql/Clob,java/io/Serializable,java/lang/Cloneable flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/io/ObjectOutputStream$PutField outerClass java/io/ObjectOutputStream innerClassName PutField flags 409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/sql/rowset/serial/SerialDatalink +header extends java/lang/Object implements java/io/Serializable,java/lang/Cloneable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/sql/rowset/serial/SerialJavaObject +header extends java/lang/Object implements java/io/Serializable,java/lang/Cloneable flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/io/ObjectOutputStream$PutField outerClass java/io/ObjectOutputStream innerClassName PutField flags 409 + +class name javax/sql/rowset/serial/SerialRef +header extends java/lang/Object implements java/sql/Ref,java/io/Serializable,java/lang/Cloneable flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/io/ObjectOutputStream$PutField outerClass java/io/ObjectOutputStream innerClassName PutField flags 409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/sql/rowset/serial/SerialStruct +header extends java/lang/Object implements java/sql/Struct,java/io/Serializable,java/lang/Cloneable flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/io/ObjectOutputStream$PutField outerClass java/io/ObjectOutputStream innerClassName PutField flags 409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + diff --git a/make/data/symbols/java.xml-B.sym.txt b/make/data/symbols/java.xml-B.sym.txt index 08675c9bf03cb30bef1c36be40ba5b50f4292aa6..3f256899258cebb963072b57e0a4f0504639035b 100644 --- a/make/data/symbols/java.xml-B.sym.txt +++ b/make/data/symbols/java.xml-B.sym.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -136,8 +136,8 @@ header extends java/lang/Object implements javax/xml/stream/util/XMLEventConsume class name javax/xml/stream/XMLInputFactory header extends java/lang/Object flags 421 -method name newFactory descriptor ()Ljavax/xml/stream/XMLInputFactory; thrownTypes javax/xml/stream/FactoryConfigurationError flags 9 -method name newFactory descriptor ()Ljavax/xml/stream/XMLInputFactory; +method name newFactory descriptor ()Ljavax/xml/stream/XMLInputFactory; thrownTypes javax/xml/stream/FactoryConfigurationError flags 9 class name javax/xml/stream/XMLOutputFactory header extends java/lang/Object flags 421 diff --git a/make/data/symbols/java.xml-C.sym.txt b/make/data/symbols/java.xml-C.sym.txt index 6023e7f147c9da0ff7d89269ce57a628e93012ad..56f91aac3dcb316ac47a9225de2e0bf6b1b806b0 100644 --- a/make/data/symbols/java.xml-C.sym.txt +++ b/make/data/symbols/java.xml-C.sym.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,6 @@ # ########################################################## # class name javax/xml/stream/XMLInputFactory -method name newFactory descriptor ()Ljavax/xml/stream/XMLInputFactory; thrownTypes javax/xml/stream/FactoryConfigurationError flags 9 -method name newFactory descriptor ()Ljavax/xml/stream/XMLInputFactory; +method name newFactory descriptor ()Ljavax/xml/stream/XMLInputFactory; thrownTypes javax/xml/stream/FactoryConfigurationError flags 9 diff --git a/make/data/symbols/java.xml-D.sym.txt b/make/data/symbols/java.xml-D.sym.txt index 29a4adb0d58dc4d268b49416e61ffc5f9755ddd6..a91b0cd8dd12ff3f0a4627609dfc9cb6a5322ef5 100644 --- a/make/data/symbols/java.xml-D.sym.txt +++ b/make/data/symbols/java.xml-D.sym.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -42,6 +42,6 @@ method name newNSInstance descriptor ()Ljavax/xml/parsers/SAXParserFactory; flag method name newNSInstance descriptor (Ljava/lang/String;Ljava/lang/ClassLoader;)Ljavax/xml/parsers/SAXParserFactory; flags 9 class name javax/xml/stream/XMLInputFactory -method name newFactory descriptor ()Ljavax/xml/stream/XMLInputFactory; thrownTypes javax/xml/stream/FactoryConfigurationError flags 9 -method name newFactory descriptor ()Ljavax/xml/stream/XMLInputFactory; +method name newFactory descriptor ()Ljavax/xml/stream/XMLInputFactory; thrownTypes javax/xml/stream/FactoryConfigurationError flags 9 diff --git a/make/data/symbols/java.xml-E.sym.txt b/make/data/symbols/java.xml-E.sym.txt index 3c5d6da6fc3df7bac5816bad97c1eb0789cfac7d..9c4ac9945e8b55e00620b5f22a6c676fb9e0f873 100644 --- a/make/data/symbols/java.xml-E.sym.txt +++ b/make/data/symbols/java.xml-E.sym.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -27,8 +27,8 @@ # ########################################################## # class name javax/xml/stream/XMLInputFactory -method name newFactory descriptor ()Ljavax/xml/stream/XMLInputFactory; thrownTypes javax/xml/stream/FactoryConfigurationError flags 9 -method name newFactory descriptor ()Ljavax/xml/stream/XMLInputFactory; +method name newFactory descriptor ()Ljavax/xml/stream/XMLInputFactory; thrownTypes javax/xml/stream/FactoryConfigurationError flags 9 class name org/xml/sax/ContentHandler method name declaration descriptor (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V thrownTypes org/xml/sax/SAXException flags 1 diff --git a/make/data/symbols/java.xml-I.sym.txt b/make/data/symbols/java.xml-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..ccadde9ba21875fc4d507911737bfeab3864f9aa --- /dev/null +++ b/make/data/symbols/java.xml-I.sym.txt @@ -0,0 +1,158 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name javax/xml/catalog/Catalog +header extends java/lang/Object flags 601 + +class name javax/xml/catalog/CatalogException +header extends java/lang/RuntimeException flags 21 + +class name javax/xml/catalog/CatalogFeatures +header extends java/lang/Object nestMembers javax/xml/catalog/CatalogFeatures$Builder,javax/xml/catalog/CatalogFeatures$Feature flags 21 +innerclass innerClass javax/xml/catalog/CatalogFeatures$Builder outerClass javax/xml/catalog/CatalogFeatures innerClassName Builder flags 9 +innerclass innerClass javax/xml/catalog/CatalogFeatures$Feature outerClass javax/xml/catalog/CatalogFeatures innerClassName Feature flags 4019 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/xml/catalog/CatalogManager +header extends java/lang/Object flags 31 + +class name javax/xml/catalog/CatalogResolver +header extends java/lang/Object implements org/xml/sax/EntityResolver,javax/xml/stream/XMLResolver,javax/xml/transform/URIResolver,org/w3c/dom/ls/LSResourceResolver flags 601 + +class name javax/xml/datatype/DatatypeFactory +header extends java/lang/Object flags 421 +innerclass innerClass javax/xml/datatype/DatatypeConstants$Field outerClass javax/xml/datatype/DatatypeConstants innerClassName Field flags 19 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/xml/datatype/Duration +header extends java/lang/Object flags 421 +innerclass innerClass javax/xml/datatype/DatatypeConstants$Field outerClass javax/xml/datatype/DatatypeConstants innerClassName Field flags 19 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/xml/namespace/QName +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/xml/parsers/DocumentBuilder +header extends java/lang/Object flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/xml/parsers/DocumentBuilderFactory +header extends java/lang/Object flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/xml/parsers/SAXParser +header extends java/lang/Object flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/xml/parsers/SAXParserFactory +header extends java/lang/Object flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/xml/stream/XMLEventReader +header extends java/lang/Object implements java/util/Iterator flags 601 signature Ljava/lang/Object;Ljava/util/Iterator; + +class name javax/xml/stream/XMLInputFactory +-method name newFactory descriptor ()Ljavax/xml/stream/XMLInputFactory; +method name newFactory descriptor ()Ljavax/xml/stream/XMLInputFactory; thrownTypes javax/xml/stream/FactoryConfigurationError flags 9 + +class name javax/xml/stream/XMLStreamException +header extends java/lang/Exception flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/xml/transform/Transformer +header extends java/lang/Object flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/xml/transform/TransformerException +header extends java/lang/Exception flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/xml/validation/SchemaFactory +header extends java/lang/Object flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/xml/xpath/XPath +header extends java/lang/Object flags 601 +innerclass innerClass javax/xml/xpath/XPathEvaluationResult$XPathResultType outerClass javax/xml/xpath/XPathEvaluationResult innerClassName XPathResultType flags 4019 + +class name javax/xml/xpath/XPathException +header extends java/lang/Exception flags 21 +innerclass innerClass java/io/ObjectOutputStream$PutField outerClass java/io/ObjectOutputStream innerClassName PutField flags 409 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 + +class name javax/xml/xpath/XPathExpression +header extends java/lang/Object flags 601 +innerclass innerClass javax/xml/xpath/XPathEvaluationResult$XPathResultType outerClass javax/xml/xpath/XPathEvaluationResult innerClassName XPathResultType flags 4019 + +class name javax/xml/xpath/XPathFactory +header extends java/lang/Object flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +method name setProperty descriptor (Ljava/lang/String;Ljava/lang/String;)V flags 1 +method name getProperty descriptor (Ljava/lang/String;)Ljava/lang/String; flags 1 + +class name javax/xml/xpath/XPathNodes +header extends java/lang/Object implements java/lang/Iterable flags 601 signature Ljava/lang/Object;Ljava/lang/Iterable; + +class name org/w3c/dom/ElementTraversal +header extends java/lang/Object flags 601 + +class name org/xml/sax/AttributeList +header extends java/lang/Object flags 601 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="1.5") + +class name org/xml/sax/DocumentHandler +header extends java/lang/Object flags 601 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="1.5") + +class name org/xml/sax/HandlerBase +header extends java/lang/Object implements org/xml/sax/EntityResolver,org/xml/sax/DTDHandler,org/xml/sax/DocumentHandler,org/xml/sax/ErrorHandler flags 21 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="1.5") + +class name org/xml/sax/Parser +header extends java/lang/Object flags 601 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="1.5") + +class name org/xml/sax/ext/Attributes2Impl +header extends org/xml/sax/helpers/AttributesImpl implements org/xml/sax/ext/Attributes2 flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name org/xml/sax/helpers/AttributeListImpl +header extends java/lang/Object implements org/xml/sax/AttributeList flags 21 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="1.5") + +class name org/xml/sax/helpers/AttributesImpl +header extends java/lang/Object implements org/xml/sax/Attributes flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name org/xml/sax/helpers/ParserFactory +header extends java/lang/Object flags 21 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="1.5") + +class name org/xml/sax/helpers/XMLFilterImpl +header extends java/lang/Object implements org/xml/sax/XMLFilter,org/xml/sax/EntityResolver,org/xml/sax/DTDHandler,org/xml/sax/ContentHandler,org/xml/sax/ErrorHandler flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name org/xml/sax/helpers/XMLReaderFactory +header extends java/lang/Object flags 31 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + diff --git a/make/data/symbols/java.xml.crypto-I.sym.txt b/make/data/symbols/java.xml.crypto-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..257909a317c7b7111508eebc2f150e8223c5a91a --- /dev/null +++ b/make/data/symbols/java.xml.crypto-I.sym.txt @@ -0,0 +1,46 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name javax/xml/crypto/NodeSetData +header extends java/lang/Object implements javax/xml/crypto/Data,java/lang/Iterable flags 601 signature Ljava/lang/Object;Ljavax/xml/crypto/Data;Ljava/lang/Iterable; + +class name javax/xml/crypto/dom/DOMCryptoContext +header extends java/lang/Object implements javax/xml/crypto/XMLCryptoContext flags 21 +innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/xml/crypto/dsig/XMLSignatureFactory +header extends java/lang/Object flags 421 +innerclass innerClass java/security/Provider$Service outerClass java/security/Provider innerClassName Service flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/xml/crypto/dsig/keyinfo/KeyInfoFactory +header extends java/lang/Object flags 421 +innerclass innerClass java/security/Provider$Service outerClass java/security/Provider innerClassName Service flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + diff --git a/make/data/symbols/jdk.accessibility-I.sym.txt b/make/data/symbols/jdk.accessibility-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..eee9c4105f30260169246c6ca5f22e2e62dca6a9 --- /dev/null +++ b/make/data/symbols/jdk.accessibility-I.sym.txt @@ -0,0 +1,58 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name com/sun/java/accessibility/util/AWTEventMonitor +-field name componentWithFocus descriptor Ljava/awt/Component; +-field name componentListener descriptor Ljava/awt/event/ComponentListener; +-field name containerListener descriptor Ljava/awt/event/ContainerListener; +-field name focusListener descriptor Ljava/awt/event/FocusListener; +-field name keyListener descriptor Ljava/awt/event/KeyListener; +-field name mouseListener descriptor Ljava/awt/event/MouseListener; +-field name mouseMotionListener descriptor Ljava/awt/event/MouseMotionListener; +-field name windowListener descriptor Ljava/awt/event/WindowListener; +-field name actionListener descriptor Ljava/awt/event/ActionListener; +-field name adjustmentListener descriptor Ljava/awt/event/AdjustmentListener; +-field name itemListener descriptor Ljava/awt/event/ItemListener; +-field name textListener descriptor Ljava/awt/event/TextListener; + +class name com/sun/java/accessibility/util/AccessibilityListenerList +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name com/sun/java/accessibility/util/EventID +header extends java/lang/Object flags 21 + +class name com/sun/java/accessibility/util/GUIInitializedListener +header extends java/lang/Object implements java/util/EventListener flags 601 + +class name com/sun/java/accessibility/util/TopLevelWindowListener +header extends java/lang/Object implements java/util/EventListener flags 601 + +class name com/sun/java/accessibility/util/Translator +header extends javax/accessibility/AccessibleContext implements javax/accessibility/Accessible,javax/accessibility/AccessibleComponent flags 21 + diff --git a/make/data/symbols/jdk.attach-I.sym.txt b/make/data/symbols/jdk.attach-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..bbe7de3e07f9363b49f7686cfea8cf05049b2c58 --- /dev/null +++ b/make/data/symbols/jdk.attach-I.sym.txt @@ -0,0 +1,55 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name com/sun/tools/attach/AgentInitializationException +header extends java/lang/Exception flags 21 + +class name com/sun/tools/attach/AgentLoadException +header extends java/lang/Exception flags 21 + +class name com/sun/tools/attach/AttachNotSupportedException +header extends java/lang/Exception flags 21 + +class name com/sun/tools/attach/AttachOperationFailedException +header extends java/io/IOException flags 21 + +class name com/sun/tools/attach/AttachPermission +header extends java/security/BasicPermission flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name com/sun/tools/attach/VirtualMachine +header extends java/lang/Object flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name com/sun/tools/attach/VirtualMachineDescriptor +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name com/sun/tools/attach/spi/AttachProvider +header extends java/lang/Object flags 421 + diff --git a/make/data/symbols/jdk.compiler-I.sym.txt b/make/data/symbols/jdk.compiler-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..7546b9fea27467f220f4480013a4d9939d84e350 --- /dev/null +++ b/make/data/symbols/jdk.compiler-I.sym.txt @@ -0,0 +1,373 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name com/sun/source/doctree/AuthorTree +header extends java/lang/Object implements com/sun/source/doctree/BlockTagTree flags 601 + +class name com/sun/source/doctree/BlockTagTree +header extends java/lang/Object implements com/sun/source/doctree/DocTree flags 601 + +class name com/sun/source/doctree/CommentTree +header extends java/lang/Object implements com/sun/source/doctree/DocTree flags 601 + +class name com/sun/source/doctree/DeprecatedTree +header extends java/lang/Object implements com/sun/source/doctree/BlockTagTree flags 601 + +class name com/sun/source/doctree/DocCommentTree +header extends java/lang/Object implements com/sun/source/doctree/DocTree flags 601 + +class name com/sun/source/doctree/DocRootTree +header extends java/lang/Object implements com/sun/source/doctree/InlineTagTree flags 601 + +class name com/sun/source/doctree/DocTree$Kind +field name SNIPPET descriptor Lcom/sun/source/doctree/DocTree$Kind; flags 4019 + +class name com/sun/source/doctree/DocTreeVisitor +header extends java/lang/Object flags 601 signature Ljava/lang/Object; +method name visitSnippet descriptor (Lcom/sun/source/doctree/SnippetTree;Ljava/lang/Object;)Ljava/lang/Object; flags 1 signature (Lcom/sun/source/doctree/SnippetTree;TP;)TR; + +class name com/sun/source/doctree/DocTypeTree +header extends java/lang/Object implements com/sun/source/doctree/DocTree flags 601 + +class name com/sun/source/doctree/EndElementTree +header extends java/lang/Object implements com/sun/source/doctree/DocTree flags 601 + +class name com/sun/source/doctree/EntityTree +header extends java/lang/Object implements com/sun/source/doctree/DocTree flags 601 + +class name com/sun/source/doctree/ErroneousTree +header extends java/lang/Object implements com/sun/source/doctree/TextTree flags 601 + +class name com/sun/source/doctree/HiddenTree +header extends java/lang/Object implements com/sun/source/doctree/BlockTagTree flags 601 + +class name com/sun/source/doctree/IdentifierTree +header extends java/lang/Object implements com/sun/source/doctree/DocTree flags 601 + +class name com/sun/source/doctree/IndexTree +header extends java/lang/Object implements com/sun/source/doctree/InlineTagTree flags 601 + +class name com/sun/source/doctree/InheritDocTree +header extends java/lang/Object implements com/sun/source/doctree/InlineTagTree flags 601 + +class name com/sun/source/doctree/InlineTagTree +header extends java/lang/Object implements com/sun/source/doctree/DocTree flags 601 + +class name com/sun/source/doctree/LinkTree +header extends java/lang/Object implements com/sun/source/doctree/InlineTagTree flags 601 + +class name com/sun/source/doctree/LiteralTree +header extends java/lang/Object implements com/sun/source/doctree/InlineTagTree flags 601 + +class name com/sun/source/doctree/ParamTree +header extends java/lang/Object implements com/sun/source/doctree/BlockTagTree flags 601 + +class name com/sun/source/doctree/ProvidesTree +header extends java/lang/Object implements com/sun/source/doctree/BlockTagTree flags 601 + +class name com/sun/source/doctree/ReferenceTree +header extends java/lang/Object implements com/sun/source/doctree/DocTree flags 601 + +class name com/sun/source/doctree/SeeTree +header extends java/lang/Object implements com/sun/source/doctree/BlockTagTree flags 601 + +class name com/sun/source/doctree/SerialDataTree +header extends java/lang/Object implements com/sun/source/doctree/BlockTagTree flags 601 + +class name com/sun/source/doctree/SerialFieldTree +header extends java/lang/Object implements com/sun/source/doctree/BlockTagTree flags 601 + +class name com/sun/source/doctree/SerialTree +header extends java/lang/Object implements com/sun/source/doctree/BlockTagTree flags 601 + +class name com/sun/source/doctree/SinceTree +header extends java/lang/Object implements com/sun/source/doctree/BlockTagTree flags 601 + +class name com/sun/source/doctree/SnippetTree +header extends java/lang/Object implements com/sun/source/doctree/InlineTagTree flags 601 +method name getAttributes descriptor ()Ljava/util/List; flags 401 signature ()Ljava/util/List<+Lcom/sun/source/doctree/DocTree;>; +method name getBody descriptor ()Lcom/sun/source/doctree/TextTree; flags 401 + +class name com/sun/source/doctree/StartElementTree +header extends java/lang/Object implements com/sun/source/doctree/DocTree flags 601 + +class name com/sun/source/doctree/SummaryTree +header extends java/lang/Object implements com/sun/source/doctree/InlineTagTree flags 601 + +class name com/sun/source/doctree/TextTree +header extends java/lang/Object implements com/sun/source/doctree/DocTree flags 601 + +class name com/sun/source/doctree/ThrowsTree +header extends java/lang/Object implements com/sun/source/doctree/BlockTagTree flags 601 + +class name com/sun/source/doctree/UnknownBlockTagTree +header extends java/lang/Object implements com/sun/source/doctree/BlockTagTree flags 601 + +class name com/sun/source/doctree/UnknownInlineTagTree +header extends java/lang/Object implements com/sun/source/doctree/InlineTagTree flags 601 + +class name com/sun/source/doctree/UsesTree +header extends java/lang/Object implements com/sun/source/doctree/BlockTagTree flags 601 + +class name com/sun/source/doctree/ValueTree +header extends java/lang/Object implements com/sun/source/doctree/InlineTagTree flags 601 + +class name com/sun/source/doctree/VersionTree +header extends java/lang/Object implements com/sun/source/doctree/BlockTagTree flags 601 + +class name com/sun/source/tree/AnnotatedTypeTree +header extends java/lang/Object implements com/sun/source/tree/ExpressionTree flags 601 + +class name com/sun/source/tree/AnnotationTree +header extends java/lang/Object implements com/sun/source/tree/ExpressionTree flags 601 + +class name com/sun/source/tree/ArrayAccessTree +header extends java/lang/Object implements com/sun/source/tree/ExpressionTree flags 601 + +class name com/sun/source/tree/ArrayTypeTree +header extends java/lang/Object implements com/sun/source/tree/Tree flags 601 + +class name com/sun/source/tree/AssertTree +header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 + +class name com/sun/source/tree/AssignmentTree +header extends java/lang/Object implements com/sun/source/tree/ExpressionTree flags 601 + +class name com/sun/source/tree/BinaryTree +header extends java/lang/Object implements com/sun/source/tree/ExpressionTree flags 601 + +class name com/sun/source/tree/BlockTree +header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 + +class name com/sun/source/tree/BreakTree +header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 + +class name com/sun/source/tree/CatchTree +header extends java/lang/Object implements com/sun/source/tree/Tree flags 601 + +class name com/sun/source/tree/ClassTree +header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 + +class name com/sun/source/tree/CompilationUnitTree +header extends java/lang/Object implements com/sun/source/tree/Tree flags 601 + +class name com/sun/source/tree/CompoundAssignmentTree +header extends java/lang/Object implements com/sun/source/tree/ExpressionTree flags 601 + +class name com/sun/source/tree/ConditionalExpressionTree +header extends java/lang/Object implements com/sun/source/tree/ExpressionTree flags 601 + +class name com/sun/source/tree/ContinueTree +header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 + +class name com/sun/source/tree/DirectiveTree +header extends java/lang/Object implements com/sun/source/tree/Tree flags 601 + +class name com/sun/source/tree/DoWhileLoopTree +header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 + +class name com/sun/source/tree/EmptyStatementTree +header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 + +class name com/sun/source/tree/EnhancedForLoopTree +header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 + +class name com/sun/source/tree/ErroneousTree +header extends java/lang/Object implements com/sun/source/tree/ExpressionTree flags 601 + +class name com/sun/source/tree/ExportsTree +header extends java/lang/Object implements com/sun/source/tree/DirectiveTree flags 601 + +class name com/sun/source/tree/ExpressionStatementTree +header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 + +class name com/sun/source/tree/ForLoopTree +header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 + +class name com/sun/source/tree/IdentifierTree +header extends java/lang/Object implements com/sun/source/tree/ExpressionTree flags 601 + +class name com/sun/source/tree/IfTree +header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 + +class name com/sun/source/tree/ImportTree +header extends java/lang/Object implements com/sun/source/tree/Tree flags 601 + +class name com/sun/source/tree/InstanceOfTree +header extends java/lang/Object implements com/sun/source/tree/ExpressionTree flags 601 + +class name com/sun/source/tree/IntersectionTypeTree +header extends java/lang/Object implements com/sun/source/tree/Tree flags 601 + +class name com/sun/source/tree/LabeledStatementTree +header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 + +class name com/sun/source/tree/LineMap +header extends java/lang/Object flags 601 + +class name com/sun/source/tree/LiteralTree +header extends java/lang/Object implements com/sun/source/tree/ExpressionTree flags 601 + +class name com/sun/source/tree/MemberSelectTree +header extends java/lang/Object implements com/sun/source/tree/ExpressionTree flags 601 + +class name com/sun/source/tree/MethodInvocationTree +header extends java/lang/Object implements com/sun/source/tree/ExpressionTree flags 601 + +class name com/sun/source/tree/MethodTree +header extends java/lang/Object implements com/sun/source/tree/Tree flags 601 + +class name com/sun/source/tree/ModifiersTree +header extends java/lang/Object implements com/sun/source/tree/Tree flags 601 + +class name com/sun/source/tree/NewArrayTree +header extends java/lang/Object implements com/sun/source/tree/ExpressionTree flags 601 + +class name com/sun/source/tree/NewClassTree +header extends java/lang/Object implements com/sun/source/tree/ExpressionTree flags 601 + +class name com/sun/source/tree/OpensTree +header extends java/lang/Object implements com/sun/source/tree/DirectiveTree flags 601 + +class name com/sun/source/tree/PackageTree +header extends java/lang/Object implements com/sun/source/tree/Tree flags 601 + +class name com/sun/source/tree/ParameterizedTypeTree +header extends java/lang/Object implements com/sun/source/tree/Tree flags 601 + +class name com/sun/source/tree/ParenthesizedTree +header extends java/lang/Object implements com/sun/source/tree/ExpressionTree flags 601 + +class name com/sun/source/tree/PrimitiveTypeTree +header extends java/lang/Object implements com/sun/source/tree/Tree flags 601 + +class name com/sun/source/tree/ProvidesTree +header extends java/lang/Object implements com/sun/source/tree/DirectiveTree flags 601 + +class name com/sun/source/tree/RequiresTree +header extends java/lang/Object implements com/sun/source/tree/DirectiveTree flags 601 + +class name com/sun/source/tree/ReturnTree +header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 + +class name com/sun/source/tree/Scope +header extends java/lang/Object flags 601 + +class name com/sun/source/tree/StatementTree +header extends java/lang/Object implements com/sun/source/tree/Tree flags 601 + +class name com/sun/source/tree/SwitchTree +header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 + +class name com/sun/source/tree/SynchronizedTree +header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 + +class name com/sun/source/tree/ThrowTree +header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 + +class name com/sun/source/tree/TreeVisitor +header extends java/lang/Object flags 601 signature Ljava/lang/Object; + +class name com/sun/source/tree/TryTree +header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 + +class name com/sun/source/tree/TypeCastTree +header extends java/lang/Object implements com/sun/source/tree/ExpressionTree flags 601 + +class name com/sun/source/tree/TypeParameterTree +header extends java/lang/Object implements com/sun/source/tree/Tree flags 601 + +class name com/sun/source/tree/UnaryTree +header extends java/lang/Object implements com/sun/source/tree/ExpressionTree flags 601 + +class name com/sun/source/tree/UnionTypeTree +header extends java/lang/Object implements com/sun/source/tree/Tree flags 601 + +class name com/sun/source/tree/UsesTree +header extends java/lang/Object implements com/sun/source/tree/DirectiveTree flags 601 + +class name com/sun/source/tree/VariableTree +header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 + +class name com/sun/source/tree/WhileLoopTree +header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 + +class name com/sun/source/tree/WildcardTree +header extends java/lang/Object implements com/sun/source/tree/Tree flags 601 + +class name com/sun/source/util/DocSourcePositions +header extends java/lang/Object implements com/sun/source/util/SourcePositions flags 601 + +class name com/sun/source/util/DocTreeFactory +header extends java/lang/Object flags 601 +innerclass innerClass com/sun/source/doctree/AttributeTree$ValueKind outerClass com/sun/source/doctree/AttributeTree innerClassName ValueKind flags 4019 +method name newSnippetTree descriptor (Ljava/util/List;Lcom/sun/source/doctree/TextTree;)Lcom/sun/source/doctree/SnippetTree; flags 401 signature (Ljava/util/List<+Lcom/sun/source/doctree/DocTree;>;Lcom/sun/source/doctree/TextTree;)Lcom/sun/source/doctree/SnippetTree; + +class name com/sun/source/util/DocTreePathScanner +header extends com/sun/source/util/DocTreeScanner flags 21 signature Lcom/sun/source/util/DocTreeScanner; + +class name com/sun/source/util/DocTreeScanner +header extends java/lang/Object implements com/sun/source/doctree/DocTreeVisitor flags 21 signature Ljava/lang/Object;Lcom/sun/source/doctree/DocTreeVisitor; +method name visitSnippet descriptor (Lcom/sun/source/doctree/SnippetTree;Ljava/lang/Object;)Ljava/lang/Object; flags 1 signature (Lcom/sun/source/doctree/SnippetTree;TP;)TR; + +class name com/sun/source/util/DocTrees +header extends com/sun/source/util/Trees flags 421 +innerclass innerClass javax/tools/JavaCompiler$CompilationTask outerClass javax/tools/JavaCompiler innerClassName CompilationTask flags 609 +innerclass innerClass javax/tools/Diagnostic$Kind outerClass javax/tools/Diagnostic innerClassName Kind flags 4019 + +class name com/sun/source/util/JavacTask +header extends java/lang/Object implements javax/tools/JavaCompiler$CompilationTask flags 421 +innerclass innerClass javax/tools/JavaCompiler$CompilationTask outerClass javax/tools/JavaCompiler innerClassName CompilationTask flags 609 + +class name com/sun/source/util/Plugin +header extends java/lang/Object flags 601 + +class name com/sun/source/util/SimpleDocTreeVisitor +header extends java/lang/Object implements com/sun/source/doctree/DocTreeVisitor flags 21 signature Ljava/lang/Object;Lcom/sun/source/doctree/DocTreeVisitor; +method name visitSnippet descriptor (Lcom/sun/source/doctree/SnippetTree;Ljava/lang/Object;)Ljava/lang/Object; flags 1 signature (Lcom/sun/source/doctree/SnippetTree;TP;)TR; + +class name com/sun/source/util/SimpleTreeVisitor +header extends java/lang/Object implements com/sun/source/tree/TreeVisitor flags 21 signature Ljava/lang/Object;Lcom/sun/source/tree/TreeVisitor; + +class name com/sun/source/util/SourcePositions +header extends java/lang/Object flags 601 + +class name com/sun/source/util/TaskListener +header extends java/lang/Object flags 601 + +class name com/sun/source/util/TreePathScanner +header extends com/sun/source/util/TreeScanner flags 21 signature Lcom/sun/source/util/TreeScanner; + +class name com/sun/source/util/Trees +header extends java/lang/Object flags 421 +innerclass innerClass javax/tools/JavaCompiler$CompilationTask outerClass javax/tools/JavaCompiler innerClassName CompilationTask flags 609 +innerclass innerClass javax/tools/Diagnostic$Kind outerClass javax/tools/Diagnostic innerClassName Kind flags 4019 + +class name com/sun/tools/javac/Main +header extends java/lang/Object flags 21 + diff --git a/make/data/symbols/jdk.dynalink-I.sym.txt b/make/data/symbols/jdk.dynalink-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..854dbd70888eb8241862fc6affba6420a06351dc --- /dev/null +++ b/make/data/symbols/jdk.dynalink-I.sym.txt @@ -0,0 +1,136 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name jdk/dynalink/CallSiteDescriptor +header extends jdk/dynalink/SecureLookupSupplier flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/dynalink/DynamicLinker +header extends java/lang/Object flags 31 +innerclass innerClass java/lang/StackWalker$StackFrame outerClass java/lang/StackWalker innerClassName StackFrame flags 609 +innerclass innerClass java/lang/StackWalker$Option outerClass java/lang/StackWalker innerClassName Option flags 4019 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/dynalink/NamedOperation +header extends java/lang/Object implements jdk/dynalink/Operation flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/dynalink/Namespace +header extends java/lang/Object flags 601 + +class name jdk/dynalink/NamespaceOperation +header extends java/lang/Object implements jdk/dynalink/Operation flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/dynalink/NoSuchDynamicMethodException +header extends java/lang/RuntimeException flags 21 + +class name jdk/dynalink/Operation +header extends java/lang/Object flags 601 + +class name jdk/dynalink/RelinkableCallSite +header extends java/lang/Object flags 601 + +class name jdk/dynalink/SecureLookupSupplier +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/dynalink/StandardNamespace +header extends java/lang/Enum implements jdk/dynalink/Namespace flags 4031 signature Ljava/lang/Enum;Ljdk/dynalink/Namespace; + +class name jdk/dynalink/StandardOperation +header extends java/lang/Enum implements jdk/dynalink/Operation flags 4031 signature Ljava/lang/Enum;Ljdk/dynalink/Operation; + +class name jdk/dynalink/beans/MissingMemberHandlerFactory +header extends java/lang/Object flags 601 runtimeAnnotations @Ljava/lang/FunctionalInterface; + +class name jdk/dynalink/linker/GuardedInvocation +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/dynalink/linker/GuardedInvocationTransformer +header extends java/lang/Object flags 601 runtimeAnnotations @Ljava/lang/FunctionalInterface; + +class name jdk/dynalink/linker/GuardingDynamicLinker +header extends java/lang/Object flags 601 + +class name jdk/dynalink/linker/GuardingDynamicLinkerExporter +header extends java/lang/Object implements java/util/function/Supplier flags 421 signature Ljava/lang/Object;Ljava/util/function/Supplier;>; + +class name jdk/dynalink/linker/GuardingTypeConverterFactory +header extends java/lang/Object flags 601 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/dynalink/linker/LinkRequest +header extends java/lang/Object flags 601 + +class name jdk/dynalink/linker/LinkerServices +header extends java/lang/Object flags 601 +innerclass innerClass jdk/dynalink/linker/ConversionComparator$Comparison outerClass jdk/dynalink/linker/ConversionComparator innerClassName Comparison flags 4019 + +class name jdk/dynalink/linker/MethodHandleTransformer +header extends java/lang/Object flags 601 runtimeAnnotations @Ljava/lang/FunctionalInterface; + +class name jdk/dynalink/linker/MethodTypeConversionStrategy +header extends java/lang/Object flags 601 runtimeAnnotations @Ljava/lang/FunctionalInterface; + +class name jdk/dynalink/linker/TypeBasedGuardingDynamicLinker +header extends java/lang/Object implements jdk/dynalink/linker/GuardingDynamicLinker flags 601 + +class name jdk/dynalink/linker/support/CompositeGuardingDynamicLinker +header extends java/lang/Object implements jdk/dynalink/linker/GuardingDynamicLinker flags 21 + +class name jdk/dynalink/linker/support/DefaultInternalObjectFilter +header extends java/lang/Object implements jdk/dynalink/linker/MethodHandleTransformer flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/dynalink/linker/support/Guards +header extends java/lang/Object flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/dynalink/linker/support/Lookup +header extends java/lang/Object flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/dynalink/linker/support/SimpleLinkRequest +header extends java/lang/Object implements jdk/dynalink/linker/LinkRequest flags 21 + +class name jdk/dynalink/linker/support/TypeUtilities +header extends java/lang/Object flags 31 +innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 + +class name jdk/dynalink/support/AbstractRelinkableCallSite +header extends java/lang/invoke/MutableCallSite implements jdk/dynalink/RelinkableCallSite flags 421 + +class name jdk/dynalink/support/ChainedCallSite +header extends jdk/dynalink/support/AbstractRelinkableCallSite flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/dynalink/support/SimpleRelinkableCallSite +header extends jdk/dynalink/support/AbstractRelinkableCallSite flags 21 + diff --git a/make/data/symbols/jdk.httpserver-I.sym.txt b/make/data/symbols/jdk.httpserver-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..5803e61c4ba94a11b799870501ee0f9bda09e023 --- /dev/null +++ b/make/data/symbols/jdk.httpserver-I.sym.txt @@ -0,0 +1,110 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.httpserver +header exports com/sun/net/httpserver,com/sun/net/httpserver/spi requires name\u0020;java.base\u0020;flags\u0020;8000 uses com/sun/net/httpserver/spi/HttpServerProvider target linux-amd64 moduleMainClass sun/net/httpserver/simpleserver/Main flags 8000 + +class name com/sun/net/httpserver/Filter +method name adaptRequest descriptor (Ljava/lang/String;Ljava/util/function/UnaryOperator;)Lcom/sun/net/httpserver/Filter; flags 9 signature (Ljava/lang/String;Ljava/util/function/UnaryOperator;)Lcom/sun/net/httpserver/Filter; + +class name com/sun/net/httpserver/Headers +header extends java/lang/Object implements java/util/Map flags 21 signature Ljava/lang/Object;Ljava/util/Map;>; +innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +method name descriptor (Ljava/util/Map;)V flags 1 signature (Ljava/util/Map;>;)V +method name replaceAll descriptor (Ljava/util/function/BiFunction;)V flags 1 signature (Ljava/util/function/BiFunction<-Ljava/lang/String;-Ljava/util/List;+Ljava/util/List;>;)V +method name toString descriptor ()Ljava/lang/String; flags 1 +method name of descriptor ([Ljava/lang/String;)Lcom/sun/net/httpserver/Headers; flags 89 +method name of descriptor (Ljava/util/Map;)Lcom/sun/net/httpserver/Headers; flags 9 signature (Ljava/util/Map;>;)Lcom/sun/net/httpserver/Headers; + +class name com/sun/net/httpserver/HttpContext +header extends java/lang/Object flags 421 + +class name com/sun/net/httpserver/HttpExchange +header extends java/lang/Object implements java/lang/AutoCloseable,com/sun/net/httpserver/Request flags 421 + +class name com/sun/net/httpserver/HttpHandler +header extends java/lang/Object flags 601 + +class name com/sun/net/httpserver/HttpHandlers +header extends java/lang/Object flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +method name handleOrElse descriptor (Ljava/util/function/Predicate;Lcom/sun/net/httpserver/HttpHandler;Lcom/sun/net/httpserver/HttpHandler;)Lcom/sun/net/httpserver/HttpHandler; flags 9 signature (Ljava/util/function/Predicate;Lcom/sun/net/httpserver/HttpHandler;Lcom/sun/net/httpserver/HttpHandler;)Lcom/sun/net/httpserver/HttpHandler; +method name of descriptor (ILcom/sun/net/httpserver/Headers;Ljava/lang/String;)Lcom/sun/net/httpserver/HttpHandler; flags 9 + +class name com/sun/net/httpserver/HttpPrincipal +header extends java/lang/Object implements java/security/Principal flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name com/sun/net/httpserver/HttpServer +header extends java/lang/Object flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +method name create descriptor (Ljava/net/InetSocketAddress;ILjava/lang/String;Lcom/sun/net/httpserver/HttpHandler;[Lcom/sun/net/httpserver/Filter;)Lcom/sun/net/httpserver/HttpServer; thrownTypes java/io/IOException flags 89 + +class name com/sun/net/httpserver/HttpsConfigurator +header extends java/lang/Object flags 21 + +class name com/sun/net/httpserver/HttpsExchange +header extends com/sun/net/httpserver/HttpExchange flags 421 + +class name com/sun/net/httpserver/HttpsParameters +header extends java/lang/Object flags 421 + +class name com/sun/net/httpserver/HttpsServer +header extends com/sun/net/httpserver/HttpServer flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +method name create descriptor (Ljava/net/InetSocketAddress;ILjava/lang/String;Lcom/sun/net/httpserver/HttpHandler;[Lcom/sun/net/httpserver/Filter;)Lcom/sun/net/httpserver/HttpsServer; thrownTypes java/io/IOException flags 89 + +class name com/sun/net/httpserver/Request +header extends java/lang/Object flags 601 +method name getRequestURI descriptor ()Ljava/net/URI; flags 401 +method name getRequestMethod descriptor ()Ljava/lang/String; flags 401 +method name getRequestHeaders descriptor ()Lcom/sun/net/httpserver/Headers; flags 401 +method name with descriptor (Ljava/lang/String;Ljava/util/List;)Lcom/sun/net/httpserver/Request; flags 1 signature (Ljava/lang/String;Ljava/util/List;)Lcom/sun/net/httpserver/Request; + +class name com/sun/net/httpserver/SimpleFileServer +header extends java/lang/Object nestMembers com/sun/net/httpserver/SimpleFileServer$OutputLevel flags 31 +innerclass innerClass com/sun/net/httpserver/SimpleFileServer$OutputLevel outerClass com/sun/net/httpserver/SimpleFileServer innerClassName OutputLevel flags 4019 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +method name createFileServer descriptor (Ljava/net/InetSocketAddress;Ljava/nio/file/Path;Lcom/sun/net/httpserver/SimpleFileServer$OutputLevel;)Lcom/sun/net/httpserver/HttpServer; flags 9 +method name createFileHandler descriptor (Ljava/nio/file/Path;)Lcom/sun/net/httpserver/HttpHandler; flags 9 +method name createOutputFilter descriptor (Ljava/io/OutputStream;Lcom/sun/net/httpserver/SimpleFileServer$OutputLevel;)Lcom/sun/net/httpserver/Filter; flags 9 + +class name com/sun/net/httpserver/SimpleFileServer$OutputLevel +header extends java/lang/Enum nestHost com/sun/net/httpserver/SimpleFileServer flags 4031 signature Ljava/lang/Enum; +innerclass innerClass com/sun/net/httpserver/SimpleFileServer$OutputLevel outerClass com/sun/net/httpserver/SimpleFileServer innerClassName OutputLevel flags 4019 +field name NONE descriptor Lcom/sun/net/httpserver/SimpleFileServer$OutputLevel; flags 4019 +field name INFO descriptor Lcom/sun/net/httpserver/SimpleFileServer$OutputLevel; flags 4019 +field name VERBOSE descriptor Lcom/sun/net/httpserver/SimpleFileServer$OutputLevel; flags 4019 +method name values descriptor ()[Lcom/sun/net/httpserver/SimpleFileServer$OutputLevel; flags 9 +method name valueOf descriptor (Ljava/lang/String;)Lcom/sun/net/httpserver/SimpleFileServer$OutputLevel; flags 9 + +class name com/sun/net/httpserver/spi/HttpServerProvider +header extends java/lang/Object flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + diff --git a/make/data/symbols/jdk.incubator.foreign-F.sym.txt b/make/data/symbols/jdk.incubator.foreign-F.sym.txt index 4a37cfad9b5cf0488ed26c56faf41f9dded05ccc..efb2d71b3344c2b5b3ce1effafa9b4f6d7421e07 100644 --- a/make/data/symbols/jdk.incubator.foreign-F.sym.txt +++ b/make/data/symbols/jdk.incubator.foreign-F.sym.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -59,9 +59,9 @@ method name asSlice descriptor (JJ)Ljdk/incubator/foreign/MemorySegment; flags 1 method name withAccessModes descriptor (I)Ljdk/incubator/foreign/MemorySegment; flags 1041 class name jdk/incubator/foreign/MemoryAddress -field name NULL descriptor Ljdk/incubator/foreign/MemoryAddress; flags 19 -method name offset descriptor ()J -method name copy descriptor (Ljdk/incubator/foreign/MemoryAddress;Ljdk/incubator/foreign/MemoryAddress;J)V +field name NULL descriptor Ljdk/incubator/foreign/MemoryAddress; flags 19 method name segmentOffset descriptor ()J flags 401 method name toRawLongValue descriptor ()J flags 401 method name rebase descriptor (Ljdk/incubator/foreign/MemorySegment;)Ljdk/incubator/foreign/MemoryAddress; flags 401 @@ -78,8 +78,8 @@ method name collectCoordinates descriptor (Ljava/lang/invoke/VarHandle;ILjava/la method name dropCoordinates descriptor (Ljava/lang/invoke/VarHandle;I[Ljava/lang/Class;)Ljava/lang/invoke/VarHandle; flags 89 signature (Ljava/lang/invoke/VarHandle;I[Ljava/lang/Class<*>;)Ljava/lang/invoke/VarHandle; class name jdk/incubator/foreign/MemoryLayout -field name LAYOUT_NAME descriptor Ljava/lang/String; constantValue layout/name flags 19 -method name offset descriptor ([Ljdk/incubator/foreign/MemoryLayout$PathElement;)J +field name LAYOUT_NAME descriptor Ljava/lang/String; constantValue layout/name flags 19 method name attribute descriptor (Ljava/lang/String;)Ljava/util/Optional; flags 401 signature (Ljava/lang/String;)Ljava/util/Optional; method name withAttribute descriptor (Ljava/lang/String;Ljava/lang/constant/Constable;)Ljdk/incubator/foreign/MemoryLayout; flags 401 method name attributes descriptor ()Ljava/util/stream/Stream; flags 401 signature ()Ljava/util/stream/Stream; @@ -88,16 +88,16 @@ method name byteOffset descriptor ([Ljdk/incubator/foreign/MemoryLayout$PathElem method name isPadding descriptor ()Z flags 401 class name jdk/incubator/foreign/MemorySegment +-method name acquire descriptor ()Ljdk/incubator/foreign/MemorySegment; +-method name asReadOnly descriptor ()Ljdk/incubator/foreign/MemorySegment; +-method name isReadOnly descriptor ()Z +-method name mapFromPath descriptor (Ljava/nio/file/Path;JLjava/nio/channels/FileChannel$MapMode;)Ljdk/incubator/foreign/MemorySegment; field name READ descriptor I constantValue 1 flags 19 field name WRITE descriptor I constantValue 2 flags 19 field name CLOSE descriptor I constantValue 4 flags 19 field name ACQUIRE descriptor I constantValue 8 flags 19 field name HANDOFF descriptor I constantValue 16 flags 19 field name ALL_ACCESS descriptor I constantValue 31 flags 19 --method name acquire descriptor ()Ljdk/incubator/foreign/MemorySegment; --method name asReadOnly descriptor ()Ljdk/incubator/foreign/MemorySegment; --method name isReadOnly descriptor ()Z --method name mapFromPath descriptor (Ljava/nio/file/Path;JLjava/nio/channels/FileChannel$MapMode;)Ljdk/incubator/foreign/MemorySegment; method name spliterator descriptor (Ljdk/incubator/foreign/MemorySegment;Ljdk/incubator/foreign/SequenceLayout;)Ljava/util/Spliterator; flags 9 signature (TS;Ljdk/incubator/foreign/SequenceLayout;)Ljava/util/Spliterator; method name withOwnerThread descriptor (Ljava/lang/Thread;)Ljdk/incubator/foreign/MemorySegment; flags 401 method name withAccessModes descriptor (I)Ljdk/incubator/foreign/MemorySegment; flags 401 diff --git a/make/data/symbols/jdk.incubator.foreign-G.sym.txt b/make/data/symbols/jdk.incubator.foreign-G.sym.txt index 5bb38702f4fa1a496f86e3ed98f3f38e10888f8f..3ea0960ea1e1761c471640498a3e72f598ccab23 100644 --- a/make/data/symbols/jdk.incubator.foreign-G.sym.txt +++ b/make/data/symbols/jdk.incubator.foreign-G.sym.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -264,12 +264,12 @@ header extends java/lang/Object implements jdk/incubator/foreign/Addressable,jav innerclass innerClass java/nio/channels/FileChannel$MapMode outerClass java/nio/channels/FileChannel innerClassName MapMode flags 9 innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 -field name ACQUIRE descriptor I -field name SHARE descriptor I constantValue 8 flags 19 -method name baseAddress descriptor ()Ljdk/incubator/foreign/MemoryAddress; -method name spliterator descriptor (Ljdk/incubator/foreign/MemorySegment;Ljdk/incubator/foreign/SequenceLayout;)Ljava/util/Spliterator; -method name withOwnerThread descriptor (Ljava/lang/Thread;)Ljdk/incubator/foreign/MemorySegment; -method name mapFromPath descriptor (Ljava/nio/file/Path;JJLjava/nio/channels/FileChannel$MapMode;)Ljdk/incubator/foreign/MappedMemorySegment; -method name ofNativeRestricted descriptor (Ljdk/incubator/foreign/MemoryAddress;JLjava/lang/Thread;Ljava/lang/Runnable;Ljava/lang/Object;)Ljdk/incubator/foreign/MemorySegment; +field name SHARE descriptor I constantValue 8 flags 19 method name address descriptor ()Ljdk/incubator/foreign/MemoryAddress; flags 401 method name spliterator descriptor (Ljdk/incubator/foreign/SequenceLayout;)Ljava/util/Spliterator; flags 401 signature (Ljdk/incubator/foreign/SequenceLayout;)Ljava/util/Spliterator; method name asSlice descriptor (Ljdk/incubator/foreign/MemoryAddress;J)Ljdk/incubator/foreign/MemorySegment; flags 1 diff --git a/make/data/symbols/jdk.incubator.foreign-H.sym.txt b/make/data/symbols/jdk.incubator.foreign-H.sym.txt index 376ba519f57b5fd270bb534406f45aa1feb316e7..d5349d378bfd7ddcbc57ccadefa20344e4f063fd 100644 --- a/make/data/symbols/jdk.incubator.foreign-H.sym.txt +++ b/make/data/symbols/jdk.incubator.foreign-H.sym.txt @@ -43,6 +43,7 @@ innerclass innerClass jdk/incubator/foreign/CLinker$VaList$Builder outerClass jd -method name allocateMemoryRestricted descriptor (J)Ljdk/incubator/foreign/MemoryAddress; -method name freeMemoryRestricted descriptor (Ljdk/incubator/foreign/MemoryAddress;)V method name getInstance descriptor ()Ljdk/incubator/foreign/CLinker; flags 9 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name systemLookup descriptor ()Ljdk/incubator/foreign/SymbolLookup; flags 9 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; method name downcallHandle descriptor (Ljdk/incubator/foreign/Addressable;Ljdk/incubator/foreign/SegmentAllocator;Ljava/lang/invoke/MethodType;Ljdk/incubator/foreign/FunctionDescriptor;)Ljava/lang/invoke/MethodHandle; flags 401 method name downcallHandle descriptor (Ljava/lang/invoke/MethodType;Ljdk/incubator/foreign/FunctionDescriptor;)Ljava/lang/invoke/MethodHandle; flags 401 method name upcallStub descriptor (Ljava/lang/invoke/MethodHandle;Ljdk/incubator/foreign/FunctionDescriptor;Ljdk/incubator/foreign/ResourceScope;)Ljdk/incubator/foreign/MemoryAddress; flags 401 @@ -51,7 +52,6 @@ method name toCString descriptor (Ljava/lang/String;Ljdk/incubator/foreign/Resou method name toJavaString descriptor (Ljdk/incubator/foreign/MemoryAddress;)Ljava/lang/String; flags 9 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; method name allocateMemory descriptor (J)Ljdk/incubator/foreign/MemoryAddress; flags 9 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; method name freeMemory descriptor (Ljdk/incubator/foreign/MemoryAddress;)V flags 9 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; -method name systemLookup descriptor ()Ljdk/incubator/foreign/SymbolLookup; flags 9 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; class name jdk/incubator/foreign/CLinker$VaList header extends java/lang/Object implements jdk/incubator/foreign/Addressable nestHost jdk/incubator/foreign/CLinker sealed true flags 601 diff --git a/make/data/symbols/jdk.incubator.foreign-I.sym.txt b/make/data/symbols/jdk.incubator.foreign-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..c8b457ba73374df773576d71cb98958841cceb0f --- /dev/null +++ b/make/data/symbols/jdk.incubator.foreign-I.sym.txt @@ -0,0 +1,582 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name jdk/incubator/foreign/AbstractLayout +header extends java/lang/Object implements jdk/incubator/foreign/MemoryLayout flags 420 +innerclass innerClass java/lang/constant/DirectMethodHandleDesc$Kind outerClass java/lang/constant/DirectMethodHandleDesc innerClassName Kind flags 4019 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +-method name descriptor (Ljava/util/OptionalLong;JLjava/util/Map;)V +-method name attribute descriptor (Ljava/lang/String;)Ljava/util/Optional; +-method name attributes descriptor ()Ljava/util/stream/Stream; +-method name withAttribute descriptor (Ljava/lang/String;Ljava/lang/constant/Constable;)Ljdk/incubator/foreign/AbstractLayout; +-method name withAttribute descriptor (Ljava/lang/String;Ljava/lang/constant/Constable;)Ljdk/incubator/foreign/MemoryLayout; +method name descriptor (Ljava/util/OptionalLong;JLjava/util/Optional;)V flags 1 signature (Ljava/util/OptionalLong;JLjava/util/Optional;)V +method name byteSize descriptor ()J flags 1 + +class name jdk/incubator/foreign/Addressable +header extends java/lang/Object sealed true flags 601 + +class name jdk/incubator/foreign/CLinker +header extends java/lang/Object implements jdk/incubator/foreign/SymbolLookup sealed true flags 601 +-field name C_CHAR descriptor Ljdk/incubator/foreign/ValueLayout; +-field name C_SHORT descriptor Ljdk/incubator/foreign/ValueLayout; +-field name C_INT descriptor Ljdk/incubator/foreign/ValueLayout; +-field name C_LONG descriptor Ljdk/incubator/foreign/ValueLayout; +-field name C_LONG_LONG descriptor Ljdk/incubator/foreign/ValueLayout; +-field name C_FLOAT descriptor Ljdk/incubator/foreign/ValueLayout; +-field name C_DOUBLE descriptor Ljdk/incubator/foreign/ValueLayout; +-field name C_POINTER descriptor Ljdk/incubator/foreign/ValueLayout; +-field name C_VA_LIST descriptor Ljdk/incubator/foreign/MemoryLayout; +-method name downcallHandle descriptor (Ljdk/incubator/foreign/Addressable;Ljava/lang/invoke/MethodType;Ljdk/incubator/foreign/FunctionDescriptor;)Ljava/lang/invoke/MethodHandle; +-method name asVarArg descriptor (Ljdk/incubator/foreign/MemoryLayout;)Ljdk/incubator/foreign/MemoryLayout; +-method name toJavaString descriptor (Ljdk/incubator/foreign/MemorySegment;)Ljava/lang/String; +-method name getInstance descriptor ()Ljdk/incubator/foreign/CLinker; +-method name systemLookup descriptor ()Ljdk/incubator/foreign/SymbolLookup; +-method name downcallHandle descriptor (Ljdk/incubator/foreign/Addressable;Ljdk/incubator/foreign/SegmentAllocator;Ljava/lang/invoke/MethodType;Ljdk/incubator/foreign/FunctionDescriptor;)Ljava/lang/invoke/MethodHandle; +-method name downcallHandle descriptor (Ljava/lang/invoke/MethodType;Ljdk/incubator/foreign/FunctionDescriptor;)Ljava/lang/invoke/MethodHandle; +-method name upcallStub descriptor (Ljava/lang/invoke/MethodHandle;Ljdk/incubator/foreign/FunctionDescriptor;Ljdk/incubator/foreign/ResourceScope;)Ljdk/incubator/foreign/MemoryAddress; +-method name toCString descriptor (Ljava/lang/String;Ljdk/incubator/foreign/SegmentAllocator;)Ljdk/incubator/foreign/MemorySegment; +-method name toCString descriptor (Ljava/lang/String;Ljdk/incubator/foreign/ResourceScope;)Ljdk/incubator/foreign/MemorySegment; +-method name toJavaString descriptor (Ljdk/incubator/foreign/MemoryAddress;)Ljava/lang/String; +-method name allocateMemory descriptor (J)Ljdk/incubator/foreign/MemoryAddress; +-method name freeMemory descriptor (Ljdk/incubator/foreign/MemoryAddress;)V +method name systemCLinker descriptor ()Ljdk/incubator/foreign/CLinker; flags 9 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name lookup descriptor (Ljava/lang/String;)Ljava/util/Optional; flags 1 signature (Ljava/lang/String;)Ljava/util/Optional; +method name downcallHandle descriptor (Ljdk/incubator/foreign/NativeSymbol;Ljdk/incubator/foreign/FunctionDescriptor;)Ljava/lang/invoke/MethodHandle; flags 1 +method name downcallHandle descriptor (Ljdk/incubator/foreign/FunctionDescriptor;)Ljava/lang/invoke/MethodHandle; flags 401 +method name upcallStub descriptor (Ljava/lang/invoke/MethodHandle;Ljdk/incubator/foreign/FunctionDescriptor;Ljdk/incubator/foreign/ResourceScope;)Ljdk/incubator/foreign/NativeSymbol; flags 401 +method name downcallType descriptor (Ljdk/incubator/foreign/FunctionDescriptor;)Ljava/lang/invoke/MethodType; flags 9 +method name upcallType descriptor (Ljdk/incubator/foreign/FunctionDescriptor;)Ljava/lang/invoke/MethodType; flags 9 + +-class name jdk/incubator/foreign/CLinker$TypeKind + +-class name jdk/incubator/foreign/CLinker$VaList + +-class name jdk/incubator/foreign/CLinker$VaList$Builder + +class name jdk/incubator/foreign/FunctionDescriptor +header extends java/lang/Object implements java/lang/constant/Constable sealed true flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +-field name TRIVIAL_ATTRIBUTE_NAME descriptor Ljava/lang/String; +-method name attribute descriptor (Ljava/lang/String;)Ljava/util/Optional; +-method name attributes descriptor ()Ljava/util/stream/Stream; +-method name withAttribute descriptor (Ljava/lang/String;Ljava/lang/constant/Constable;)Ljdk/incubator/foreign/FunctionDescriptor; +-method name withAppendedArgumentLayouts descriptor ([Ljdk/incubator/foreign/MemoryLayout;)Ljdk/incubator/foreign/FunctionDescriptor; +-method name withReturnLayout descriptor (Ljdk/incubator/foreign/MemoryLayout;)Ljdk/incubator/foreign/FunctionDescriptor; +-method name withVoidReturnLayout descriptor ()Ljdk/incubator/foreign/FunctionDescriptor; +method name asVariadic descriptor ([Ljdk/incubator/foreign/MemoryLayout;)Ljdk/incubator/foreign/FunctionDescriptor; flags 81 +method name firstVariadicArgumentIndex descriptor ()I flags 1 +method name appendArgumentLayouts descriptor ([Ljdk/incubator/foreign/MemoryLayout;)Ljdk/incubator/foreign/FunctionDescriptor; flags 81 +method name insertArgumentLayouts descriptor (I[Ljdk/incubator/foreign/MemoryLayout;)Ljdk/incubator/foreign/FunctionDescriptor; flags 81 +method name changeReturnLayout descriptor (Ljdk/incubator/foreign/MemoryLayout;)Ljdk/incubator/foreign/FunctionDescriptor; flags 1 +method name dropReturnLayout descriptor ()Ljdk/incubator/foreign/FunctionDescriptor; flags 1 + +class name jdk/incubator/foreign/GroupLayout +-method name withAttribute descriptor (Ljava/lang/String;Ljava/lang/constant/Constable;)Ljdk/incubator/foreign/GroupLayout; +-method name withAttribute descriptor (Ljava/lang/String;Ljava/lang/constant/Constable;)Ljdk/incubator/foreign/AbstractLayout; +-method name attributes descriptor ()Ljava/util/stream/Stream; +-method name attribute descriptor (Ljava/lang/String;)Ljava/util/Optional; +-method name withAttribute descriptor (Ljava/lang/String;Ljava/lang/constant/Constable;)Ljdk/incubator/foreign/MemoryLayout; +method name byteSize descriptor ()J flags 1041 + +-class name jdk/incubator/foreign/MemoryAccess + +class name jdk/incubator/foreign/MemoryAddress +header extends java/lang/Object implements jdk/incubator/foreign/Addressable sealed true flags 601 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfByte outerClass jdk/incubator/foreign/ValueLayout innerClassName OfByte flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfBoolean outerClass jdk/incubator/foreign/ValueLayout innerClassName OfBoolean flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfChar outerClass jdk/incubator/foreign/ValueLayout innerClassName OfChar flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfShort outerClass jdk/incubator/foreign/ValueLayout innerClassName OfShort flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfInt outerClass jdk/incubator/foreign/ValueLayout innerClassName OfInt flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfFloat outerClass jdk/incubator/foreign/ValueLayout innerClassName OfFloat flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfLong outerClass jdk/incubator/foreign/ValueLayout innerClassName OfLong flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfDouble outerClass jdk/incubator/foreign/ValueLayout innerClassName OfDouble flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfAddress outerClass jdk/incubator/foreign/ValueLayout innerClassName OfAddress flags 19 +-method name address descriptor ()Ljdk/incubator/foreign/MemoryAddress; +-method name segmentOffset descriptor (Ljdk/incubator/foreign/MemorySegment;)J +-method name scope descriptor ()Ljdk/incubator/foreign/ResourceScope; +-method name asSegment descriptor (JLjdk/incubator/foreign/ResourceScope;)Ljdk/incubator/foreign/MemorySegment; +-method name asSegment descriptor (JLjava/lang/Runnable;Ljdk/incubator/foreign/ResourceScope;)Ljdk/incubator/foreign/MemorySegment; +-method name isNative descriptor ()Z +method name getUtf8String descriptor (J)Ljava/lang/String; flags 401 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name setUtf8String descriptor (JLjava/lang/String;)V flags 401 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name get descriptor (Ljdk/incubator/foreign/ValueLayout$OfByte;J)B flags 401 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name set descriptor (Ljdk/incubator/foreign/ValueLayout$OfByte;JB)V flags 401 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name get descriptor (Ljdk/incubator/foreign/ValueLayout$OfBoolean;J)Z flags 401 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name set descriptor (Ljdk/incubator/foreign/ValueLayout$OfBoolean;JZ)V flags 401 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name get descriptor (Ljdk/incubator/foreign/ValueLayout$OfChar;J)C flags 401 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name set descriptor (Ljdk/incubator/foreign/ValueLayout$OfChar;JC)V flags 401 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name get descriptor (Ljdk/incubator/foreign/ValueLayout$OfShort;J)S flags 401 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name set descriptor (Ljdk/incubator/foreign/ValueLayout$OfShort;JS)V flags 401 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name get descriptor (Ljdk/incubator/foreign/ValueLayout$OfInt;J)I flags 401 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name set descriptor (Ljdk/incubator/foreign/ValueLayout$OfInt;JI)V flags 401 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name get descriptor (Ljdk/incubator/foreign/ValueLayout$OfFloat;J)F flags 401 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name set descriptor (Ljdk/incubator/foreign/ValueLayout$OfFloat;JF)V flags 401 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name get descriptor (Ljdk/incubator/foreign/ValueLayout$OfLong;J)J flags 401 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name set descriptor (Ljdk/incubator/foreign/ValueLayout$OfLong;JJ)V flags 401 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name get descriptor (Ljdk/incubator/foreign/ValueLayout$OfDouble;J)D flags 401 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name set descriptor (Ljdk/incubator/foreign/ValueLayout$OfDouble;JD)V flags 401 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name get descriptor (Ljdk/incubator/foreign/ValueLayout$OfAddress;J)Ljdk/incubator/foreign/MemoryAddress; flags 401 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name set descriptor (Ljdk/incubator/foreign/ValueLayout$OfAddress;JLjdk/incubator/foreign/Addressable;)V flags 401 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name getAtIndex descriptor (Ljdk/incubator/foreign/ValueLayout$OfChar;J)C flags 401 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name setAtIndex descriptor (Ljdk/incubator/foreign/ValueLayout$OfChar;JC)V flags 401 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name getAtIndex descriptor (Ljdk/incubator/foreign/ValueLayout$OfShort;J)S flags 401 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name setAtIndex descriptor (Ljdk/incubator/foreign/ValueLayout$OfShort;JS)V flags 401 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name getAtIndex descriptor (Ljdk/incubator/foreign/ValueLayout$OfInt;J)I flags 401 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name setAtIndex descriptor (Ljdk/incubator/foreign/ValueLayout$OfInt;JI)V flags 401 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name getAtIndex descriptor (Ljdk/incubator/foreign/ValueLayout$OfFloat;J)F flags 401 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name setAtIndex descriptor (Ljdk/incubator/foreign/ValueLayout$OfFloat;JF)V flags 401 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name getAtIndex descriptor (Ljdk/incubator/foreign/ValueLayout$OfLong;J)J flags 401 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name setAtIndex descriptor (Ljdk/incubator/foreign/ValueLayout$OfLong;JJ)V flags 401 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name getAtIndex descriptor (Ljdk/incubator/foreign/ValueLayout$OfDouble;J)D flags 401 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name setAtIndex descriptor (Ljdk/incubator/foreign/ValueLayout$OfDouble;JD)V flags 401 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name getAtIndex descriptor (Ljdk/incubator/foreign/ValueLayout$OfAddress;J)Ljdk/incubator/foreign/MemoryAddress; flags 401 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name setAtIndex descriptor (Ljdk/incubator/foreign/ValueLayout$OfAddress;JLjdk/incubator/foreign/Addressable;)V flags 401 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; + +class name jdk/incubator/foreign/MemoryHandles +-method name varHandle descriptor (Ljava/lang/Class;Ljava/nio/ByteOrder;)Ljava/lang/invoke/VarHandle; +-method name varHandle descriptor (Ljava/lang/Class;JLjava/nio/ByteOrder;)Ljava/lang/invoke/VarHandle; +-method name asAddressVarHandle descriptor (Ljava/lang/invoke/VarHandle;)Ljava/lang/invoke/VarHandle; +method name varHandle descriptor (Ljdk/incubator/foreign/ValueLayout;)Ljava/lang/invoke/VarHandle; flags 9 + +class name jdk/incubator/foreign/MemoryLayout +header extends java/lang/Object implements java/lang/constant/Constable nestMembers jdk/incubator/foreign/MemoryLayout$PathElement sealed true flags 601 +innerclass innerClass jdk/incubator/foreign/MemoryLayout$PathElement outerClass jdk/incubator/foreign/MemoryLayout innerClassName PathElement flags 609 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfBoolean outerClass jdk/incubator/foreign/ValueLayout innerClassName OfBoolean flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfChar outerClass jdk/incubator/foreign/ValueLayout innerClassName OfChar flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfByte outerClass jdk/incubator/foreign/ValueLayout innerClassName OfByte flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfShort outerClass jdk/incubator/foreign/ValueLayout innerClassName OfShort flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfInt outerClass jdk/incubator/foreign/ValueLayout innerClassName OfInt flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfFloat outerClass jdk/incubator/foreign/ValueLayout innerClassName OfFloat flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfLong outerClass jdk/incubator/foreign/ValueLayout innerClassName OfLong flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfDouble outerClass jdk/incubator/foreign/ValueLayout innerClassName OfDouble flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfAddress outerClass jdk/incubator/foreign/ValueLayout innerClassName OfAddress flags 19 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +-field name LAYOUT_NAME descriptor Ljava/lang/String; +-method name byteSize descriptor ()J +-method name varHandle descriptor (Ljava/lang/Class;[Ljdk/incubator/foreign/MemoryLayout$PathElement;)Ljava/lang/invoke/VarHandle; +-method name attribute descriptor (Ljava/lang/String;)Ljava/util/Optional; +-method name withAttribute descriptor (Ljava/lang/String;Ljava/lang/constant/Constable;)Ljdk/incubator/foreign/MemoryLayout; +-method name attributes descriptor ()Ljava/util/stream/Stream; +-method name valueLayout descriptor (JLjava/nio/ByteOrder;)Ljdk/incubator/foreign/ValueLayout; +method name byteSize descriptor ()J flags 401 +method name varHandle descriptor ([Ljdk/incubator/foreign/MemoryLayout$PathElement;)Ljava/lang/invoke/VarHandle; flags 81 +method name valueLayout descriptor (Ljava/lang/Class;Ljava/nio/ByteOrder;)Ljdk/incubator/foreign/ValueLayout; flags 9 signature (Ljava/lang/Class<*>;Ljava/nio/ByteOrder;)Ljdk/incubator/foreign/ValueLayout; + +class name jdk/incubator/foreign/MemoryLayout$PathElement +header extends java/lang/Object nestHost jdk/incubator/foreign/MemoryLayout sealed true flags 601 +innerclass innerClass jdk/incubator/foreign/MemoryLayout$PathElement outerClass jdk/incubator/foreign/MemoryLayout innerClassName PathElement flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +-class name jdk/incubator/foreign/MemoryLayouts + +class name jdk/incubator/foreign/MemorySegment +header extends java/lang/Object implements jdk/incubator/foreign/Addressable sealed true flags 601 +innerclass innerClass java/nio/channels/FileChannel$MapMode outerClass java/nio/channels/FileChannel innerClassName MapMode flags 9 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfByte outerClass jdk/incubator/foreign/ValueLayout innerClassName OfByte flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfBoolean outerClass jdk/incubator/foreign/ValueLayout innerClassName OfBoolean flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfChar outerClass jdk/incubator/foreign/ValueLayout innerClassName OfChar flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfShort outerClass jdk/incubator/foreign/ValueLayout innerClassName OfShort flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfInt outerClass jdk/incubator/foreign/ValueLayout innerClassName OfInt flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfFloat outerClass jdk/incubator/foreign/ValueLayout innerClassName OfFloat flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfLong outerClass jdk/incubator/foreign/ValueLayout innerClassName OfLong flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfDouble outerClass jdk/incubator/foreign/ValueLayout innerClassName OfDouble flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfAddress outerClass jdk/incubator/foreign/ValueLayout innerClassName OfAddress flags 19 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +-method name toByteArray descriptor ()[B +-method name copyFrom descriptor (Ljdk/incubator/foreign/MemorySegment;)V +-method name asSlice descriptor (Ljdk/incubator/foreign/MemoryAddress;J)Ljdk/incubator/foreign/MemorySegment; +-method name asSlice descriptor (Ljdk/incubator/foreign/MemoryAddress;)Ljdk/incubator/foreign/MemorySegment; +-method name toShortArray descriptor ()[S +-method name toCharArray descriptor ()[C +-method name toIntArray descriptor ()[I +-method name toFloatArray descriptor ()[F +-method name toLongArray descriptor ()[J +-method name toDoubleArray descriptor ()[D +-method name asReadOnly descriptor ()Ljdk/incubator/foreign/MemorySegment; +-method name isReadOnly descriptor ()Z +-method name globalNativeSegment descriptor ()Ljdk/incubator/foreign/MemorySegment; +method name asReadOnly descriptor ()Ljdk/incubator/foreign/MemorySegment; flags 401 +method name isReadOnly descriptor ()Z flags 401 +method name asOverlappingSlice descriptor (Ljdk/incubator/foreign/MemorySegment;)Ljdk/incubator/foreign/MemorySegment; flags 401 +method name segmentOffset descriptor (Ljdk/incubator/foreign/MemorySegment;)J flags 401 +method name copyFrom descriptor (Ljdk/incubator/foreign/MemorySegment;)Ljdk/incubator/foreign/MemorySegment; flags 1 +method name toArray descriptor (Ljdk/incubator/foreign/ValueLayout$OfByte;)[B flags 401 +method name toArray descriptor (Ljdk/incubator/foreign/ValueLayout$OfShort;)[S flags 401 +method name toArray descriptor (Ljdk/incubator/foreign/ValueLayout$OfChar;)[C flags 401 +method name toArray descriptor (Ljdk/incubator/foreign/ValueLayout$OfInt;)[I flags 401 +method name toArray descriptor (Ljdk/incubator/foreign/ValueLayout$OfFloat;)[F flags 401 +method name toArray descriptor (Ljdk/incubator/foreign/ValueLayout$OfLong;)[J flags 401 +method name toArray descriptor (Ljdk/incubator/foreign/ValueLayout$OfDouble;)[D flags 401 +method name getUtf8String descriptor (J)Ljava/lang/String; flags 1 +method name setUtf8String descriptor (JLjava/lang/String;)V flags 1 +method name ofAddress descriptor (Ljdk/incubator/foreign/MemoryAddress;JLjdk/incubator/foreign/ResourceScope;)Ljdk/incubator/foreign/MemorySegment; flags 9 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name copy descriptor (Ljdk/incubator/foreign/MemorySegment;JLjdk/incubator/foreign/MemorySegment;JJ)V flags 9 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name copy descriptor (Ljdk/incubator/foreign/MemorySegment;Ljdk/incubator/foreign/ValueLayout;JLjdk/incubator/foreign/MemorySegment;Ljdk/incubator/foreign/ValueLayout;JJ)V flags 9 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name get descriptor (Ljdk/incubator/foreign/ValueLayout$OfByte;J)B flags 1 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name set descriptor (Ljdk/incubator/foreign/ValueLayout$OfByte;JB)V flags 1 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name get descriptor (Ljdk/incubator/foreign/ValueLayout$OfBoolean;J)Z flags 1 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name set descriptor (Ljdk/incubator/foreign/ValueLayout$OfBoolean;JZ)V flags 1 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name get descriptor (Ljdk/incubator/foreign/ValueLayout$OfChar;J)C flags 1 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name set descriptor (Ljdk/incubator/foreign/ValueLayout$OfChar;JC)V flags 1 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name get descriptor (Ljdk/incubator/foreign/ValueLayout$OfShort;J)S flags 1 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name set descriptor (Ljdk/incubator/foreign/ValueLayout$OfShort;JS)V flags 1 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name get descriptor (Ljdk/incubator/foreign/ValueLayout$OfInt;J)I flags 1 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name set descriptor (Ljdk/incubator/foreign/ValueLayout$OfInt;JI)V flags 1 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name get descriptor (Ljdk/incubator/foreign/ValueLayout$OfFloat;J)F flags 1 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name set descriptor (Ljdk/incubator/foreign/ValueLayout$OfFloat;JF)V flags 1 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name get descriptor (Ljdk/incubator/foreign/ValueLayout$OfLong;J)J flags 1 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name set descriptor (Ljdk/incubator/foreign/ValueLayout$OfLong;JJ)V flags 1 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name get descriptor (Ljdk/incubator/foreign/ValueLayout$OfDouble;J)D flags 1 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name set descriptor (Ljdk/incubator/foreign/ValueLayout$OfDouble;JD)V flags 1 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name get descriptor (Ljdk/incubator/foreign/ValueLayout$OfAddress;J)Ljdk/incubator/foreign/MemoryAddress; flags 1 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name set descriptor (Ljdk/incubator/foreign/ValueLayout$OfAddress;JLjdk/incubator/foreign/Addressable;)V flags 1 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name getAtIndex descriptor (Ljdk/incubator/foreign/ValueLayout$OfChar;J)C flags 1 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name setAtIndex descriptor (Ljdk/incubator/foreign/ValueLayout$OfChar;JC)V flags 1 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name getAtIndex descriptor (Ljdk/incubator/foreign/ValueLayout$OfShort;J)S flags 1 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name setAtIndex descriptor (Ljdk/incubator/foreign/ValueLayout$OfShort;JS)V flags 1 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name getAtIndex descriptor (Ljdk/incubator/foreign/ValueLayout$OfInt;J)I flags 1 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name setAtIndex descriptor (Ljdk/incubator/foreign/ValueLayout$OfInt;JI)V flags 1 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name getAtIndex descriptor (Ljdk/incubator/foreign/ValueLayout$OfFloat;J)F flags 1 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name setAtIndex descriptor (Ljdk/incubator/foreign/ValueLayout$OfFloat;JF)V flags 1 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name getAtIndex descriptor (Ljdk/incubator/foreign/ValueLayout$OfLong;J)J flags 1 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name setAtIndex descriptor (Ljdk/incubator/foreign/ValueLayout$OfLong;JJ)V flags 1 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name getAtIndex descriptor (Ljdk/incubator/foreign/ValueLayout$OfDouble;J)D flags 1 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name setAtIndex descriptor (Ljdk/incubator/foreign/ValueLayout$OfDouble;JD)V flags 1 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name getAtIndex descriptor (Ljdk/incubator/foreign/ValueLayout$OfAddress;J)Ljdk/incubator/foreign/MemoryAddress; flags 1 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name setAtIndex descriptor (Ljdk/incubator/foreign/ValueLayout$OfAddress;JLjdk/incubator/foreign/Addressable;)V flags 1 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name copy descriptor (Ljdk/incubator/foreign/MemorySegment;Ljdk/incubator/foreign/ValueLayout;JLjava/lang/Object;II)V flags 9 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name copy descriptor (Ljava/lang/Object;ILjdk/incubator/foreign/MemorySegment;Ljdk/incubator/foreign/ValueLayout;JI)V flags 9 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; + +class name jdk/incubator/foreign/NativeSymbol +header extends java/lang/Object implements jdk/incubator/foreign/Addressable sealed true flags 601 +method name name descriptor ()Ljava/lang/String; flags 401 +method name scope descriptor ()Ljdk/incubator/foreign/ResourceScope; flags 401 +method name address descriptor ()Ljdk/incubator/foreign/MemoryAddress; flags 401 +method name ofAddress descriptor (Ljava/lang/String;Ljdk/incubator/foreign/MemoryAddress;Ljdk/incubator/foreign/ResourceScope;)Ljdk/incubator/foreign/NativeSymbol; flags 9 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; + +class name jdk/incubator/foreign/ResourceScope +header extends java/lang/Object implements java/lang/AutoCloseable sealed true flags 601 +-method name isImplicit descriptor ()Z +-method name acquire descriptor ()Ljdk/incubator/foreign/ResourceScope$Handle; +-method name release descriptor (Ljdk/incubator/foreign/ResourceScope$Handle;)V +method name keepAlive descriptor (Ljdk/incubator/foreign/ResourceScope;)V flags 401 + +-class name jdk/incubator/foreign/ResourceScope$Handle + +class name jdk/incubator/foreign/SegmentAllocator +header extends java/lang/Object flags 601 runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass jdk/incubator/foreign/MemoryLayout$PathElement outerClass jdk/incubator/foreign/MemoryLayout innerClassName PathElement flags 609 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfByte outerClass jdk/incubator/foreign/ValueLayout innerClassName OfByte flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfChar outerClass jdk/incubator/foreign/ValueLayout innerClassName OfChar flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfShort outerClass jdk/incubator/foreign/ValueLayout innerClassName OfShort flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfInt outerClass jdk/incubator/foreign/ValueLayout innerClassName OfInt flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfFloat outerClass jdk/incubator/foreign/ValueLayout innerClassName OfFloat flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfLong outerClass jdk/incubator/foreign/ValueLayout innerClassName OfLong flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfDouble outerClass jdk/incubator/foreign/ValueLayout innerClassName OfDouble flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfAddress outerClass jdk/incubator/foreign/ValueLayout innerClassName OfAddress flags 19 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +-method name allocate descriptor (Ljdk/incubator/foreign/ValueLayout;B)Ljdk/incubator/foreign/MemorySegment; +-method name allocate descriptor (Ljdk/incubator/foreign/ValueLayout;C)Ljdk/incubator/foreign/MemorySegment; +-method name allocate descriptor (Ljdk/incubator/foreign/ValueLayout;S)Ljdk/incubator/foreign/MemorySegment; +-method name allocate descriptor (Ljdk/incubator/foreign/ValueLayout;I)Ljdk/incubator/foreign/MemorySegment; +-method name allocate descriptor (Ljdk/incubator/foreign/ValueLayout;F)Ljdk/incubator/foreign/MemorySegment; +-method name allocate descriptor (Ljdk/incubator/foreign/ValueLayout;J)Ljdk/incubator/foreign/MemorySegment; +-method name allocate descriptor (Ljdk/incubator/foreign/ValueLayout;D)Ljdk/incubator/foreign/MemorySegment; +-method name allocate descriptor (Ljdk/incubator/foreign/ValueLayout;Ljdk/incubator/foreign/Addressable;)Ljdk/incubator/foreign/MemorySegment; +-method name allocateArray descriptor (Ljdk/incubator/foreign/ValueLayout;[B)Ljdk/incubator/foreign/MemorySegment; +-method name allocateArray descriptor (Ljdk/incubator/foreign/ValueLayout;[S)Ljdk/incubator/foreign/MemorySegment; +-method name allocateArray descriptor (Ljdk/incubator/foreign/ValueLayout;[C)Ljdk/incubator/foreign/MemorySegment; +-method name allocateArray descriptor (Ljdk/incubator/foreign/ValueLayout;[I)Ljdk/incubator/foreign/MemorySegment; +-method name allocateArray descriptor (Ljdk/incubator/foreign/ValueLayout;[F)Ljdk/incubator/foreign/MemorySegment; +-method name allocateArray descriptor (Ljdk/incubator/foreign/ValueLayout;[J)Ljdk/incubator/foreign/MemorySegment; +-method name allocateArray descriptor (Ljdk/incubator/foreign/ValueLayout;[D)Ljdk/incubator/foreign/MemorySegment; +-method name allocateArray descriptor (Ljdk/incubator/foreign/ValueLayout;[Ljdk/incubator/foreign/Addressable;)Ljdk/incubator/foreign/MemorySegment; +-method name arenaAllocator descriptor (JLjdk/incubator/foreign/ResourceScope;)Ljdk/incubator/foreign/SegmentAllocator; +-method name arenaAllocator descriptor (Ljdk/incubator/foreign/ResourceScope;)Ljdk/incubator/foreign/SegmentAllocator; +-method name ofSegment descriptor (Ljdk/incubator/foreign/MemorySegment;)Ljdk/incubator/foreign/SegmentAllocator; +-method name ofScope descriptor (Ljdk/incubator/foreign/ResourceScope;)Ljdk/incubator/foreign/SegmentAllocator; +method name allocateUtf8String descriptor (Ljava/lang/String;)Ljdk/incubator/foreign/MemorySegment; flags 1 +method name allocate descriptor (Ljdk/incubator/foreign/ValueLayout$OfByte;B)Ljdk/incubator/foreign/MemorySegment; flags 1 +method name allocate descriptor (Ljdk/incubator/foreign/ValueLayout$OfChar;C)Ljdk/incubator/foreign/MemorySegment; flags 1 +method name allocate descriptor (Ljdk/incubator/foreign/ValueLayout$OfShort;S)Ljdk/incubator/foreign/MemorySegment; flags 1 +method name allocate descriptor (Ljdk/incubator/foreign/ValueLayout$OfInt;I)Ljdk/incubator/foreign/MemorySegment; flags 1 +method name allocate descriptor (Ljdk/incubator/foreign/ValueLayout$OfFloat;F)Ljdk/incubator/foreign/MemorySegment; flags 1 +method name allocate descriptor (Ljdk/incubator/foreign/ValueLayout$OfLong;J)Ljdk/incubator/foreign/MemorySegment; flags 1 +method name allocate descriptor (Ljdk/incubator/foreign/ValueLayout$OfDouble;D)Ljdk/incubator/foreign/MemorySegment; flags 1 +method name allocate descriptor (Ljdk/incubator/foreign/ValueLayout$OfAddress;Ljdk/incubator/foreign/Addressable;)Ljdk/incubator/foreign/MemorySegment; flags 1 +method name allocateArray descriptor (Ljdk/incubator/foreign/ValueLayout$OfByte;[B)Ljdk/incubator/foreign/MemorySegment; flags 1 +method name allocateArray descriptor (Ljdk/incubator/foreign/ValueLayout$OfShort;[S)Ljdk/incubator/foreign/MemorySegment; flags 1 +method name allocateArray descriptor (Ljdk/incubator/foreign/ValueLayout$OfChar;[C)Ljdk/incubator/foreign/MemorySegment; flags 1 +method name allocateArray descriptor (Ljdk/incubator/foreign/ValueLayout$OfInt;[I)Ljdk/incubator/foreign/MemorySegment; flags 1 +method name allocateArray descriptor (Ljdk/incubator/foreign/ValueLayout$OfFloat;[F)Ljdk/incubator/foreign/MemorySegment; flags 1 +method name allocateArray descriptor (Ljdk/incubator/foreign/ValueLayout$OfLong;[J)Ljdk/incubator/foreign/MemorySegment; flags 1 +method name allocateArray descriptor (Ljdk/incubator/foreign/ValueLayout$OfDouble;[D)Ljdk/incubator/foreign/MemorySegment; flags 1 +method name newNativeArena descriptor (Ljdk/incubator/foreign/ResourceScope;)Ljdk/incubator/foreign/SegmentAllocator; flags 9 +method name newNativeArena descriptor (JLjdk/incubator/foreign/ResourceScope;)Ljdk/incubator/foreign/SegmentAllocator; flags 9 +method name newNativeArena descriptor (JJLjdk/incubator/foreign/ResourceScope;)Ljdk/incubator/foreign/SegmentAllocator; flags 9 +method name prefixAllocator descriptor (Ljdk/incubator/foreign/MemorySegment;)Ljdk/incubator/foreign/SegmentAllocator; flags 9 +method name nativeAllocator descriptor (Ljdk/incubator/foreign/ResourceScope;)Ljdk/incubator/foreign/SegmentAllocator; flags 9 +method name implicitAllocator descriptor ()Ljdk/incubator/foreign/SegmentAllocator; flags 9 + +class name jdk/incubator/foreign/SequenceLayout +-method name withAttribute descriptor (Ljava/lang/String;Ljava/lang/constant/Constable;)Ljdk/incubator/foreign/SequenceLayout; +-method name withAttribute descriptor (Ljava/lang/String;Ljava/lang/constant/Constable;)Ljdk/incubator/foreign/AbstractLayout; +-method name attributes descriptor ()Ljava/util/stream/Stream; +-method name attribute descriptor (Ljava/lang/String;)Ljava/util/Optional; +-method name withAttribute descriptor (Ljava/lang/String;Ljava/lang/constant/Constable;)Ljdk/incubator/foreign/MemoryLayout; +method name byteSize descriptor ()J flags 1041 + +class name jdk/incubator/foreign/SymbolLookup +-method name lookup descriptor (Ljava/lang/String;)Ljava/util/Optional; +method name lookup descriptor (Ljava/lang/String;)Ljava/util/Optional; flags 401 signature (Ljava/lang/String;)Ljava/util/Optional; + +class name jdk/incubator/foreign/VaList +header extends java/lang/Object implements jdk/incubator/foreign/Addressable nestMembers jdk/incubator/foreign/VaList$Builder sealed true flags 601 +innerclass innerClass jdk/incubator/foreign/VaList$Builder outerClass jdk/incubator/foreign/VaList innerClassName Builder flags 609 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfInt outerClass jdk/incubator/foreign/ValueLayout innerClassName OfInt flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfLong outerClass jdk/incubator/foreign/ValueLayout innerClassName OfLong flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfDouble outerClass jdk/incubator/foreign/ValueLayout innerClassName OfDouble flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfAddress outerClass jdk/incubator/foreign/ValueLayout innerClassName OfAddress flags 19 +method name nextVarg descriptor (Ljdk/incubator/foreign/ValueLayout$OfInt;)I flags 401 +method name nextVarg descriptor (Ljdk/incubator/foreign/ValueLayout$OfLong;)J flags 401 +method name nextVarg descriptor (Ljdk/incubator/foreign/ValueLayout$OfDouble;)D flags 401 +method name nextVarg descriptor (Ljdk/incubator/foreign/ValueLayout$OfAddress;)Ljdk/incubator/foreign/MemoryAddress; flags 401 +method name nextVarg descriptor (Ljdk/incubator/foreign/GroupLayout;Ljdk/incubator/foreign/SegmentAllocator;)Ljdk/incubator/foreign/MemorySegment; flags 401 +method name skip descriptor ([Ljdk/incubator/foreign/MemoryLayout;)V flags 481 +method name scope descriptor ()Ljdk/incubator/foreign/ResourceScope; flags 401 +method name copy descriptor ()Ljdk/incubator/foreign/VaList; flags 401 +method name address descriptor ()Ljdk/incubator/foreign/MemoryAddress; flags 401 +method name ofAddress descriptor (Ljdk/incubator/foreign/MemoryAddress;Ljdk/incubator/foreign/ResourceScope;)Ljdk/incubator/foreign/VaList; flags 9 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name make descriptor (Ljava/util/function/Consumer;Ljdk/incubator/foreign/ResourceScope;)Ljdk/incubator/foreign/VaList; flags 9 signature (Ljava/util/function/Consumer;Ljdk/incubator/foreign/ResourceScope;)Ljdk/incubator/foreign/VaList; +method name empty descriptor ()Ljdk/incubator/foreign/VaList; flags 9 + +class name jdk/incubator/foreign/VaList$Builder +header extends java/lang/Object nestHost jdk/incubator/foreign/VaList sealed true flags 601 +innerclass innerClass jdk/incubator/foreign/VaList$Builder outerClass jdk/incubator/foreign/VaList innerClassName Builder flags 609 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfInt outerClass jdk/incubator/foreign/ValueLayout innerClassName OfInt flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfLong outerClass jdk/incubator/foreign/ValueLayout innerClassName OfLong flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfDouble outerClass jdk/incubator/foreign/ValueLayout innerClassName OfDouble flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfAddress outerClass jdk/incubator/foreign/ValueLayout innerClassName OfAddress flags 19 +method name addVarg descriptor (Ljdk/incubator/foreign/ValueLayout$OfInt;I)Ljdk/incubator/foreign/VaList$Builder; flags 401 +method name addVarg descriptor (Ljdk/incubator/foreign/ValueLayout$OfLong;J)Ljdk/incubator/foreign/VaList$Builder; flags 401 +method name addVarg descriptor (Ljdk/incubator/foreign/ValueLayout$OfDouble;D)Ljdk/incubator/foreign/VaList$Builder; flags 401 +method name addVarg descriptor (Ljdk/incubator/foreign/ValueLayout$OfAddress;Ljdk/incubator/foreign/Addressable;)Ljdk/incubator/foreign/VaList$Builder; flags 401 +method name addVarg descriptor (Ljdk/incubator/foreign/GroupLayout;Ljdk/incubator/foreign/MemorySegment;)Ljdk/incubator/foreign/VaList$Builder; flags 401 + +class name jdk/incubator/foreign/ValueLayout +header extends jdk/incubator/foreign/AbstractLayout implements jdk/incubator/foreign/MemoryLayout nestMembers jdk/incubator/foreign/ValueLayout$OfAddress,jdk/incubator/foreign/ValueLayout$OfDouble,jdk/incubator/foreign/ValueLayout$OfLong,jdk/incubator/foreign/ValueLayout$OfFloat,jdk/incubator/foreign/ValueLayout$OfInt,jdk/incubator/foreign/ValueLayout$OfShort,jdk/incubator/foreign/ValueLayout$OfChar,jdk/incubator/foreign/ValueLayout$OfByte,jdk/incubator/foreign/ValueLayout$OfBoolean sealed true flags 21 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfAddress outerClass jdk/incubator/foreign/ValueLayout innerClassName OfAddress flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfByte outerClass jdk/incubator/foreign/ValueLayout innerClassName OfByte flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfBoolean outerClass jdk/incubator/foreign/ValueLayout innerClassName OfBoolean flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfChar outerClass jdk/incubator/foreign/ValueLayout innerClassName OfChar flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfShort outerClass jdk/incubator/foreign/ValueLayout innerClassName OfShort flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfInt outerClass jdk/incubator/foreign/ValueLayout innerClassName OfInt flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfLong outerClass jdk/incubator/foreign/ValueLayout innerClassName OfLong flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfFloat outerClass jdk/incubator/foreign/ValueLayout innerClassName OfFloat flags 19 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfDouble outerClass jdk/incubator/foreign/ValueLayout innerClassName OfDouble flags 19 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +-method name withAttribute descriptor (Ljava/lang/String;Ljava/lang/constant/Constable;)Ljdk/incubator/foreign/ValueLayout; +-method name withAttribute descriptor (Ljava/lang/String;Ljava/lang/constant/Constable;)Ljdk/incubator/foreign/AbstractLayout; +-method name attributes descriptor ()Ljava/util/stream/Stream; +-method name attribute descriptor (Ljava/lang/String;)Ljava/util/Optional; +-method name withAttribute descriptor (Ljava/lang/String;Ljava/lang/constant/Constable;)Ljdk/incubator/foreign/MemoryLayout; +field name ADDRESS descriptor Ljdk/incubator/foreign/ValueLayout$OfAddress; flags 19 +field name JAVA_BYTE descriptor Ljdk/incubator/foreign/ValueLayout$OfByte; flags 19 +field name JAVA_BOOLEAN descriptor Ljdk/incubator/foreign/ValueLayout$OfBoolean; flags 19 +field name JAVA_CHAR descriptor Ljdk/incubator/foreign/ValueLayout$OfChar; flags 19 +field name JAVA_SHORT descriptor Ljdk/incubator/foreign/ValueLayout$OfShort; flags 19 +field name JAVA_INT descriptor Ljdk/incubator/foreign/ValueLayout$OfInt; flags 19 +field name JAVA_LONG descriptor Ljdk/incubator/foreign/ValueLayout$OfLong; flags 19 +field name JAVA_FLOAT descriptor Ljdk/incubator/foreign/ValueLayout$OfFloat; flags 19 +field name JAVA_DOUBLE descriptor Ljdk/incubator/foreign/ValueLayout$OfDouble; flags 19 +method name carrier descriptor ()Ljava/lang/Class; flags 1 signature ()Ljava/lang/Class<*>; +method name byteSize descriptor ()J flags 1041 + +class name jdk/incubator/foreign/ValueLayout$OfAddress +header extends jdk/incubator/foreign/ValueLayout nestHost jdk/incubator/foreign/ValueLayout flags 31 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfAddress outerClass jdk/incubator/foreign/ValueLayout innerClassName OfAddress flags 19 +method name withName descriptor (Ljava/lang/String;)Ljdk/incubator/foreign/ValueLayout$OfAddress; flags 1 +method name withBitAlignment descriptor (J)Ljdk/incubator/foreign/ValueLayout$OfAddress; flags 1 +method name withOrder descriptor (Ljava/nio/ByteOrder;)Ljdk/incubator/foreign/ValueLayout$OfAddress; flags 1 +method name withBitAlignment descriptor (J)Ljdk/incubator/foreign/ValueLayout; flags 1041 +method name withName descriptor (Ljava/lang/String;)Ljdk/incubator/foreign/ValueLayout; flags 1041 +method name withOrder descriptor (Ljava/nio/ByteOrder;)Ljdk/incubator/foreign/ValueLayout; flags 1041 +method name withBitAlignment descriptor (J)Ljdk/incubator/foreign/MemoryLayout; flags 1041 +method name withName descriptor (Ljava/lang/String;)Ljdk/incubator/foreign/MemoryLayout; flags 1041 +method name isPadding descriptor ()Z flags 1041 +method name bitSize descriptor ()J flags 1041 +method name hasSize descriptor ()Z flags 1041 +method name byteSize descriptor ()J flags 1041 +method name withBitAlignment descriptor (J)Ljdk/incubator/foreign/AbstractLayout; flags 1041 +method name withName descriptor (Ljava/lang/String;)Ljdk/incubator/foreign/AbstractLayout; flags 1041 + +class name jdk/incubator/foreign/ValueLayout$OfBoolean +header extends jdk/incubator/foreign/ValueLayout nestHost jdk/incubator/foreign/ValueLayout flags 31 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfBoolean outerClass jdk/incubator/foreign/ValueLayout innerClassName OfBoolean flags 19 +method name withName descriptor (Ljava/lang/String;)Ljdk/incubator/foreign/ValueLayout$OfBoolean; flags 1 +method name withBitAlignment descriptor (J)Ljdk/incubator/foreign/ValueLayout$OfBoolean; flags 1 +method name withOrder descriptor (Ljava/nio/ByteOrder;)Ljdk/incubator/foreign/ValueLayout$OfBoolean; flags 1 +method name withBitAlignment descriptor (J)Ljdk/incubator/foreign/ValueLayout; flags 1041 +method name withName descriptor (Ljava/lang/String;)Ljdk/incubator/foreign/ValueLayout; flags 1041 +method name withOrder descriptor (Ljava/nio/ByteOrder;)Ljdk/incubator/foreign/ValueLayout; flags 1041 +method name withBitAlignment descriptor (J)Ljdk/incubator/foreign/MemoryLayout; flags 1041 +method name withName descriptor (Ljava/lang/String;)Ljdk/incubator/foreign/MemoryLayout; flags 1041 +method name isPadding descriptor ()Z flags 1041 +method name bitSize descriptor ()J flags 1041 +method name hasSize descriptor ()Z flags 1041 +method name byteSize descriptor ()J flags 1041 +method name withBitAlignment descriptor (J)Ljdk/incubator/foreign/AbstractLayout; flags 1041 +method name withName descriptor (Ljava/lang/String;)Ljdk/incubator/foreign/AbstractLayout; flags 1041 + +class name jdk/incubator/foreign/ValueLayout$OfByte +header extends jdk/incubator/foreign/ValueLayout nestHost jdk/incubator/foreign/ValueLayout flags 31 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfByte outerClass jdk/incubator/foreign/ValueLayout innerClassName OfByte flags 19 +method name withName descriptor (Ljava/lang/String;)Ljdk/incubator/foreign/ValueLayout$OfByte; flags 1 +method name withBitAlignment descriptor (J)Ljdk/incubator/foreign/ValueLayout$OfByte; flags 1 +method name withOrder descriptor (Ljava/nio/ByteOrder;)Ljdk/incubator/foreign/ValueLayout$OfByte; flags 1 +method name withBitAlignment descriptor (J)Ljdk/incubator/foreign/ValueLayout; flags 1041 +method name withName descriptor (Ljava/lang/String;)Ljdk/incubator/foreign/ValueLayout; flags 1041 +method name withOrder descriptor (Ljava/nio/ByteOrder;)Ljdk/incubator/foreign/ValueLayout; flags 1041 +method name withBitAlignment descriptor (J)Ljdk/incubator/foreign/MemoryLayout; flags 1041 +method name withName descriptor (Ljava/lang/String;)Ljdk/incubator/foreign/MemoryLayout; flags 1041 +method name isPadding descriptor ()Z flags 1041 +method name bitSize descriptor ()J flags 1041 +method name hasSize descriptor ()Z flags 1041 +method name byteSize descriptor ()J flags 1041 +method name withBitAlignment descriptor (J)Ljdk/incubator/foreign/AbstractLayout; flags 1041 +method name withName descriptor (Ljava/lang/String;)Ljdk/incubator/foreign/AbstractLayout; flags 1041 + +class name jdk/incubator/foreign/ValueLayout$OfChar +header extends jdk/incubator/foreign/ValueLayout nestHost jdk/incubator/foreign/ValueLayout flags 31 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfChar outerClass jdk/incubator/foreign/ValueLayout innerClassName OfChar flags 19 +method name withName descriptor (Ljava/lang/String;)Ljdk/incubator/foreign/ValueLayout$OfChar; flags 1 +method name withBitAlignment descriptor (J)Ljdk/incubator/foreign/ValueLayout$OfChar; flags 1 +method name withOrder descriptor (Ljava/nio/ByteOrder;)Ljdk/incubator/foreign/ValueLayout$OfChar; flags 1 +method name withBitAlignment descriptor (J)Ljdk/incubator/foreign/ValueLayout; flags 1041 +method name withName descriptor (Ljava/lang/String;)Ljdk/incubator/foreign/ValueLayout; flags 1041 +method name withOrder descriptor (Ljava/nio/ByteOrder;)Ljdk/incubator/foreign/ValueLayout; flags 1041 +method name withBitAlignment descriptor (J)Ljdk/incubator/foreign/MemoryLayout; flags 1041 +method name withName descriptor (Ljava/lang/String;)Ljdk/incubator/foreign/MemoryLayout; flags 1041 +method name isPadding descriptor ()Z flags 1041 +method name bitSize descriptor ()J flags 1041 +method name hasSize descriptor ()Z flags 1041 +method name byteSize descriptor ()J flags 1041 +method name withBitAlignment descriptor (J)Ljdk/incubator/foreign/AbstractLayout; flags 1041 +method name withName descriptor (Ljava/lang/String;)Ljdk/incubator/foreign/AbstractLayout; flags 1041 + +class name jdk/incubator/foreign/ValueLayout$OfDouble +header extends jdk/incubator/foreign/ValueLayout nestHost jdk/incubator/foreign/ValueLayout flags 31 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfDouble outerClass jdk/incubator/foreign/ValueLayout innerClassName OfDouble flags 19 +method name withName descriptor (Ljava/lang/String;)Ljdk/incubator/foreign/ValueLayout$OfDouble; flags 1 +method name withBitAlignment descriptor (J)Ljdk/incubator/foreign/ValueLayout$OfDouble; flags 1 +method name withOrder descriptor (Ljava/nio/ByteOrder;)Ljdk/incubator/foreign/ValueLayout$OfDouble; flags 1 +method name withBitAlignment descriptor (J)Ljdk/incubator/foreign/ValueLayout; flags 1041 +method name withName descriptor (Ljava/lang/String;)Ljdk/incubator/foreign/ValueLayout; flags 1041 +method name withOrder descriptor (Ljava/nio/ByteOrder;)Ljdk/incubator/foreign/ValueLayout; flags 1041 +method name withBitAlignment descriptor (J)Ljdk/incubator/foreign/MemoryLayout; flags 1041 +method name withName descriptor (Ljava/lang/String;)Ljdk/incubator/foreign/MemoryLayout; flags 1041 +method name isPadding descriptor ()Z flags 1041 +method name bitSize descriptor ()J flags 1041 +method name hasSize descriptor ()Z flags 1041 +method name byteSize descriptor ()J flags 1041 +method name withBitAlignment descriptor (J)Ljdk/incubator/foreign/AbstractLayout; flags 1041 +method name withName descriptor (Ljava/lang/String;)Ljdk/incubator/foreign/AbstractLayout; flags 1041 + +class name jdk/incubator/foreign/ValueLayout$OfFloat +header extends jdk/incubator/foreign/ValueLayout nestHost jdk/incubator/foreign/ValueLayout flags 31 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfFloat outerClass jdk/incubator/foreign/ValueLayout innerClassName OfFloat flags 19 +method name withName descriptor (Ljava/lang/String;)Ljdk/incubator/foreign/ValueLayout$OfFloat; flags 1 +method name withBitAlignment descriptor (J)Ljdk/incubator/foreign/ValueLayout$OfFloat; flags 1 +method name withOrder descriptor (Ljava/nio/ByteOrder;)Ljdk/incubator/foreign/ValueLayout$OfFloat; flags 1 +method name withBitAlignment descriptor (J)Ljdk/incubator/foreign/ValueLayout; flags 1041 +method name withName descriptor (Ljava/lang/String;)Ljdk/incubator/foreign/ValueLayout; flags 1041 +method name withOrder descriptor (Ljava/nio/ByteOrder;)Ljdk/incubator/foreign/ValueLayout; flags 1041 +method name withBitAlignment descriptor (J)Ljdk/incubator/foreign/MemoryLayout; flags 1041 +method name withName descriptor (Ljava/lang/String;)Ljdk/incubator/foreign/MemoryLayout; flags 1041 +method name isPadding descriptor ()Z flags 1041 +method name bitSize descriptor ()J flags 1041 +method name hasSize descriptor ()Z flags 1041 +method name byteSize descriptor ()J flags 1041 +method name withBitAlignment descriptor (J)Ljdk/incubator/foreign/AbstractLayout; flags 1041 +method name withName descriptor (Ljava/lang/String;)Ljdk/incubator/foreign/AbstractLayout; flags 1041 + +class name jdk/incubator/foreign/ValueLayout$OfInt +header extends jdk/incubator/foreign/ValueLayout nestHost jdk/incubator/foreign/ValueLayout flags 31 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfInt outerClass jdk/incubator/foreign/ValueLayout innerClassName OfInt flags 19 +method name withName descriptor (Ljava/lang/String;)Ljdk/incubator/foreign/ValueLayout$OfInt; flags 1 +method name withBitAlignment descriptor (J)Ljdk/incubator/foreign/ValueLayout$OfInt; flags 1 +method name withOrder descriptor (Ljava/nio/ByteOrder;)Ljdk/incubator/foreign/ValueLayout$OfInt; flags 1 +method name withBitAlignment descriptor (J)Ljdk/incubator/foreign/ValueLayout; flags 1041 +method name withName descriptor (Ljava/lang/String;)Ljdk/incubator/foreign/ValueLayout; flags 1041 +method name withOrder descriptor (Ljava/nio/ByteOrder;)Ljdk/incubator/foreign/ValueLayout; flags 1041 +method name withBitAlignment descriptor (J)Ljdk/incubator/foreign/MemoryLayout; flags 1041 +method name withName descriptor (Ljava/lang/String;)Ljdk/incubator/foreign/MemoryLayout; flags 1041 +method name isPadding descriptor ()Z flags 1041 +method name bitSize descriptor ()J flags 1041 +method name hasSize descriptor ()Z flags 1041 +method name byteSize descriptor ()J flags 1041 +method name withBitAlignment descriptor (J)Ljdk/incubator/foreign/AbstractLayout; flags 1041 +method name withName descriptor (Ljava/lang/String;)Ljdk/incubator/foreign/AbstractLayout; flags 1041 + +class name jdk/incubator/foreign/ValueLayout$OfLong +header extends jdk/incubator/foreign/ValueLayout nestHost jdk/incubator/foreign/ValueLayout flags 31 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfLong outerClass jdk/incubator/foreign/ValueLayout innerClassName OfLong flags 19 +method name withName descriptor (Ljava/lang/String;)Ljdk/incubator/foreign/ValueLayout$OfLong; flags 1 +method name withBitAlignment descriptor (J)Ljdk/incubator/foreign/ValueLayout$OfLong; flags 1 +method name withOrder descriptor (Ljava/nio/ByteOrder;)Ljdk/incubator/foreign/ValueLayout$OfLong; flags 1 +method name withBitAlignment descriptor (J)Ljdk/incubator/foreign/ValueLayout; flags 1041 +method name withName descriptor (Ljava/lang/String;)Ljdk/incubator/foreign/ValueLayout; flags 1041 +method name withOrder descriptor (Ljava/nio/ByteOrder;)Ljdk/incubator/foreign/ValueLayout; flags 1041 +method name withBitAlignment descriptor (J)Ljdk/incubator/foreign/MemoryLayout; flags 1041 +method name withName descriptor (Ljava/lang/String;)Ljdk/incubator/foreign/MemoryLayout; flags 1041 +method name isPadding descriptor ()Z flags 1041 +method name bitSize descriptor ()J flags 1041 +method name hasSize descriptor ()Z flags 1041 +method name byteSize descriptor ()J flags 1041 +method name withBitAlignment descriptor (J)Ljdk/incubator/foreign/AbstractLayout; flags 1041 +method name withName descriptor (Ljava/lang/String;)Ljdk/incubator/foreign/AbstractLayout; flags 1041 + +class name jdk/incubator/foreign/ValueLayout$OfShort +header extends jdk/incubator/foreign/ValueLayout nestHost jdk/incubator/foreign/ValueLayout flags 31 +innerclass innerClass jdk/incubator/foreign/ValueLayout$OfShort outerClass jdk/incubator/foreign/ValueLayout innerClassName OfShort flags 19 +method name withName descriptor (Ljava/lang/String;)Ljdk/incubator/foreign/ValueLayout$OfShort; flags 1 +method name withBitAlignment descriptor (J)Ljdk/incubator/foreign/ValueLayout$OfShort; flags 1 +method name withOrder descriptor (Ljava/nio/ByteOrder;)Ljdk/incubator/foreign/ValueLayout$OfShort; flags 1 +method name withBitAlignment descriptor (J)Ljdk/incubator/foreign/ValueLayout; flags 1041 +method name withName descriptor (Ljava/lang/String;)Ljdk/incubator/foreign/ValueLayout; flags 1041 +method name withOrder descriptor (Ljava/nio/ByteOrder;)Ljdk/incubator/foreign/ValueLayout; flags 1041 +method name withBitAlignment descriptor (J)Ljdk/incubator/foreign/MemoryLayout; flags 1041 +method name withName descriptor (Ljava/lang/String;)Ljdk/incubator/foreign/MemoryLayout; flags 1041 +method name isPadding descriptor ()Z flags 1041 +method name bitSize descriptor ()J flags 1041 +method name hasSize descriptor ()Z flags 1041 +method name byteSize descriptor ()J flags 1041 +method name withBitAlignment descriptor (J)Ljdk/incubator/foreign/AbstractLayout; flags 1041 +method name withName descriptor (Ljava/lang/String;)Ljdk/incubator/foreign/AbstractLayout; flags 1041 + diff --git a/make/data/symbols/jdk.incubator.vector-G.sym.txt b/make/data/symbols/jdk.incubator.vector-G.sym.txt index dec09658dc0d864278ee73557c011e410fca5ef9..35c8da2c622bb025f1a4250a6160029b57a87419 100644 --- a/make/data/symbols/jdk.incubator.vector-G.sym.txt +++ b/make/data/symbols/jdk.incubator.vector-G.sym.txt @@ -32,6 +32,8 @@ header exports jdk/incubator/vector requires name\u0020;java.base\u0020;flags\u0 class name jdk/incubator/vector/AbstractVector header extends jdk/incubator/vector/Vector flags 420 signature Ljdk/incubator/vector/Vector; innerclass innerClass jdk/incubator/vector/VectorOperators$Conversion outerClass jdk/incubator/vector/VectorOperators innerClassName Conversion flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorPayload outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorPayload flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 innerclass innerClass jdk/incubator/vector/VectorOperators$Associative outerClass jdk/incubator/vector/VectorOperators innerClassName Associative flags 609 innerclass innerClass jdk/incubator/vector/VectorOperators$Binary outerClass jdk/incubator/vector/VectorOperators innerClassName Binary flags 609 innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 @@ -55,6 +57,7 @@ method name slice descriptor (I)Ljdk/incubator/vector/Vector; flags 1041 class name jdk/incubator/vector/ByteVector header extends jdk/incubator/vector/AbstractVector flags 421 signature Ljdk/incubator/vector/AbstractVector; innerclass innerClass jdk/incubator/vector/VectorOperators$Operator outerClass jdk/incubator/vector/VectorOperators innerClassName Operator flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 innerclass innerClass jdk/incubator/vector/VectorOperators$Unary outerClass jdk/incubator/vector/VectorOperators innerClassName Unary flags 609 innerclass innerClass jdk/incubator/vector/VectorOperators$Comparison outerClass jdk/incubator/vector/VectorOperators innerClassName Comparison flags 609 innerclass innerClass jdk/incubator/vector/VectorOperators$Associative outerClass jdk/incubator/vector/VectorOperators innerClassName Associative flags 609 @@ -230,6 +233,7 @@ method name slice descriptor (I)Ljdk/incubator/vector/AbstractVector; flags 1041 class name jdk/incubator/vector/DoubleVector header extends jdk/incubator/vector/AbstractVector flags 421 signature Ljdk/incubator/vector/AbstractVector; innerclass innerClass jdk/incubator/vector/VectorOperators$Operator outerClass jdk/incubator/vector/VectorOperators innerClassName Operator flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 innerclass innerClass jdk/incubator/vector/VectorOperators$Unary outerClass jdk/incubator/vector/VectorOperators innerClassName Unary flags 609 innerclass innerClass jdk/incubator/vector/VectorOperators$Comparison outerClass jdk/incubator/vector/VectorOperators innerClassName Comparison flags 609 innerclass innerClass jdk/incubator/vector/VectorOperators$Associative outerClass jdk/incubator/vector/VectorOperators innerClassName Associative flags 609 @@ -402,6 +406,7 @@ method name slice descriptor (I)Ljdk/incubator/vector/AbstractVector; flags 1041 class name jdk/incubator/vector/FloatVector header extends jdk/incubator/vector/AbstractVector flags 421 signature Ljdk/incubator/vector/AbstractVector; innerclass innerClass jdk/incubator/vector/VectorOperators$Operator outerClass jdk/incubator/vector/VectorOperators innerClassName Operator flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 innerclass innerClass jdk/incubator/vector/VectorOperators$Unary outerClass jdk/incubator/vector/VectorOperators innerClassName Unary flags 609 innerclass innerClass jdk/incubator/vector/VectorOperators$Comparison outerClass jdk/incubator/vector/VectorOperators innerClassName Comparison flags 609 innerclass innerClass jdk/incubator/vector/VectorOperators$Associative outerClass jdk/incubator/vector/VectorOperators innerClassName Associative flags 609 @@ -574,6 +579,7 @@ method name slice descriptor (I)Ljdk/incubator/vector/AbstractVector; flags 1041 class name jdk/incubator/vector/IntVector header extends jdk/incubator/vector/AbstractVector flags 421 signature Ljdk/incubator/vector/AbstractVector; innerclass innerClass jdk/incubator/vector/VectorOperators$Operator outerClass jdk/incubator/vector/VectorOperators innerClassName Operator flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 innerclass innerClass jdk/incubator/vector/VectorOperators$Unary outerClass jdk/incubator/vector/VectorOperators innerClassName Unary flags 609 innerclass innerClass jdk/incubator/vector/VectorOperators$Comparison outerClass jdk/incubator/vector/VectorOperators innerClassName Comparison flags 609 innerclass innerClass jdk/incubator/vector/VectorOperators$Associative outerClass jdk/incubator/vector/VectorOperators innerClassName Associative flags 609 @@ -750,6 +756,7 @@ method name slice descriptor (I)Ljdk/incubator/vector/AbstractVector; flags 1041 class name jdk/incubator/vector/LongVector header extends jdk/incubator/vector/AbstractVector flags 421 signature Ljdk/incubator/vector/AbstractVector; innerclass innerClass jdk/incubator/vector/VectorOperators$Operator outerClass jdk/incubator/vector/VectorOperators innerClassName Operator flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 innerclass innerClass jdk/incubator/vector/VectorOperators$Unary outerClass jdk/incubator/vector/VectorOperators innerClassName Unary flags 609 innerclass innerClass jdk/incubator/vector/VectorOperators$Comparison outerClass jdk/incubator/vector/VectorOperators innerClassName Comparison flags 609 innerclass innerClass jdk/incubator/vector/VectorOperators$Associative outerClass jdk/incubator/vector/VectorOperators innerClassName Associative flags 609 @@ -919,6 +926,7 @@ method name slice descriptor (I)Ljdk/incubator/vector/AbstractVector; flags 1041 class name jdk/incubator/vector/ShortVector header extends jdk/incubator/vector/AbstractVector flags 421 signature Ljdk/incubator/vector/AbstractVector; innerclass innerClass jdk/incubator/vector/VectorOperators$Operator outerClass jdk/incubator/vector/VectorOperators innerClassName Operator flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 innerclass innerClass jdk/incubator/vector/VectorOperators$Unary outerClass jdk/incubator/vector/VectorOperators innerClassName Unary flags 609 innerclass innerClass jdk/incubator/vector/VectorOperators$Comparison outerClass jdk/incubator/vector/VectorOperators innerClassName Comparison flags 609 innerclass innerClass jdk/incubator/vector/VectorOperators$Associative outerClass jdk/incubator/vector/VectorOperators innerClassName Associative flags 609 @@ -1184,6 +1192,7 @@ method name hashCode descriptor ()I flags 401 class name jdk/incubator/vector/VectorMask header extends jdk/internal/vm/vector/VectorSupport$VectorMask flags 421 signature Ljdk/internal/vm/vector/VectorSupport$VectorMask; innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorMask outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorMask flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 method name vectorSpecies descriptor ()Ljdk/incubator/vector/VectorSpecies; flags 401 signature ()Ljdk/incubator/vector/VectorSpecies; method name length descriptor ()I flags 11 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; diff --git a/make/data/symbols/jdk.incubator.vector-H.sym.txt b/make/data/symbols/jdk.incubator.vector-H.sym.txt index a815726e54b3835248f19404d7ebd8971772591a..b83ff570747edecaee54d7782258e3d9c880e4a5 100644 --- a/make/data/symbols/jdk.incubator.vector-H.sym.txt +++ b/make/data/symbols/jdk.incubator.vector-H.sym.txt @@ -27,6 +27,20 @@ # ########################################################## # class name jdk/incubator/vector/ByteVector +header extends jdk/incubator/vector/AbstractVector flags 421 signature Ljdk/incubator/vector/AbstractVector; +innerclass innerClass jdk/incubator/vector/VectorOperators$Operator outerClass jdk/incubator/vector/VectorOperators innerClassName Operator flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Unary outerClass jdk/incubator/vector/VectorOperators innerClassName Unary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Comparison outerClass jdk/incubator/vector/VectorOperators innerClassName Comparison flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Associative outerClass jdk/incubator/vector/VectorOperators innerClassName Associative flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Binary outerClass jdk/incubator/vector/VectorOperators innerClassName Binary flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$Vector outerClass jdk/internal/vm/vector/VectorSupport innerClassName Vector flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Ternary outerClass jdk/incubator/vector/VectorOperators innerClassName Ternary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Test outerClass jdk/incubator/vector/VectorOperators innerClassName Test flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorMask outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorMask flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorShuffle outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorShuffle flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorPayload outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorPayload flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 method name fromBooleanArray descriptor (Ljdk/incubator/vector/VectorSpecies;[ZI)Ljdk/incubator/vector/ByteVector; flags 9 signature (Ljdk/incubator/vector/VectorSpecies;[ZI)Ljdk/incubator/vector/ByteVector; runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; method name fromBooleanArray descriptor (Ljdk/incubator/vector/VectorSpecies;[ZILjdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/ByteVector; flags 9 signature (Ljdk/incubator/vector/VectorSpecies;[ZILjdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/ByteVector; runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; method name fromBooleanArray descriptor (Ljdk/incubator/vector/VectorSpecies;[ZI[II)Ljdk/incubator/vector/ByteVector; flags 9 signature (Ljdk/incubator/vector/VectorSpecies;[ZI[II)Ljdk/incubator/vector/ByteVector; runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; @@ -36,7 +50,85 @@ method name intoBooleanArray descriptor ([ZILjdk/incubator/vector/VectorMask;)V method name intoBooleanArray descriptor ([ZI[II)V flags 11 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; method name intoBooleanArray descriptor ([ZI[IILjdk/incubator/vector/VectorMask;)V flags 11 signature ([ZI[IILjdk/incubator/vector/VectorMask;)V runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +class name jdk/incubator/vector/DoubleVector +header extends jdk/incubator/vector/AbstractVector flags 421 signature Ljdk/incubator/vector/AbstractVector; +innerclass innerClass jdk/incubator/vector/VectorOperators$Operator outerClass jdk/incubator/vector/VectorOperators innerClassName Operator flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Unary outerClass jdk/incubator/vector/VectorOperators innerClassName Unary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Comparison outerClass jdk/incubator/vector/VectorOperators innerClassName Comparison flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Associative outerClass jdk/incubator/vector/VectorOperators innerClassName Associative flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Binary outerClass jdk/incubator/vector/VectorOperators innerClassName Binary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Ternary outerClass jdk/incubator/vector/VectorOperators innerClassName Ternary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Test outerClass jdk/incubator/vector/VectorOperators innerClassName Test flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$Vector outerClass jdk/internal/vm/vector/VectorSupport innerClassName Vector flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorMask outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorMask flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorShuffle outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorShuffle flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorPayload outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorPayload flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/incubator/vector/FloatVector +header extends jdk/incubator/vector/AbstractVector flags 421 signature Ljdk/incubator/vector/AbstractVector; +innerclass innerClass jdk/incubator/vector/VectorOperators$Operator outerClass jdk/incubator/vector/VectorOperators innerClassName Operator flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Unary outerClass jdk/incubator/vector/VectorOperators innerClassName Unary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Comparison outerClass jdk/incubator/vector/VectorOperators innerClassName Comparison flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Associative outerClass jdk/incubator/vector/VectorOperators innerClassName Associative flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Binary outerClass jdk/incubator/vector/VectorOperators innerClassName Binary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Ternary outerClass jdk/incubator/vector/VectorOperators innerClassName Ternary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Test outerClass jdk/incubator/vector/VectorOperators innerClassName Test flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$Vector outerClass jdk/internal/vm/vector/VectorSupport innerClassName Vector flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorMask outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorMask flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorShuffle outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorShuffle flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorPayload outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorPayload flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/incubator/vector/IntVector +header extends jdk/incubator/vector/AbstractVector flags 421 signature Ljdk/incubator/vector/AbstractVector; +innerclass innerClass jdk/incubator/vector/VectorOperators$Operator outerClass jdk/incubator/vector/VectorOperators innerClassName Operator flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Unary outerClass jdk/incubator/vector/VectorOperators innerClassName Unary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Comparison outerClass jdk/incubator/vector/VectorOperators innerClassName Comparison flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Associative outerClass jdk/incubator/vector/VectorOperators innerClassName Associative flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Binary outerClass jdk/incubator/vector/VectorOperators innerClassName Binary flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$Vector outerClass jdk/internal/vm/vector/VectorSupport innerClassName Vector flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Ternary outerClass jdk/incubator/vector/VectorOperators innerClassName Ternary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Test outerClass jdk/incubator/vector/VectorOperators innerClassName Test flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorMask outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorMask flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorShuffle outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorShuffle flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorPayload outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorPayload flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/incubator/vector/LongVector +header extends jdk/incubator/vector/AbstractVector flags 421 signature Ljdk/incubator/vector/AbstractVector; +innerclass innerClass jdk/incubator/vector/VectorOperators$Operator outerClass jdk/incubator/vector/VectorOperators innerClassName Operator flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Unary outerClass jdk/incubator/vector/VectorOperators innerClassName Unary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Comparison outerClass jdk/incubator/vector/VectorOperators innerClassName Comparison flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Associative outerClass jdk/incubator/vector/VectorOperators innerClassName Associative flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Binary outerClass jdk/incubator/vector/VectorOperators innerClassName Binary flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$Vector outerClass jdk/internal/vm/vector/VectorSupport innerClassName Vector flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Ternary outerClass jdk/incubator/vector/VectorOperators innerClassName Ternary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Test outerClass jdk/incubator/vector/VectorOperators innerClassName Test flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorMask outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorMask flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorShuffle outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorShuffle flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorPayload outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorPayload flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + class name jdk/incubator/vector/ShortVector +header extends jdk/incubator/vector/AbstractVector flags 421 signature Ljdk/incubator/vector/AbstractVector; +innerclass innerClass jdk/incubator/vector/VectorOperators$Operator outerClass jdk/incubator/vector/VectorOperators innerClassName Operator flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Unary outerClass jdk/incubator/vector/VectorOperators innerClassName Unary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Comparison outerClass jdk/incubator/vector/VectorOperators innerClassName Comparison flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Associative outerClass jdk/incubator/vector/VectorOperators innerClassName Associative flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Binary outerClass jdk/incubator/vector/VectorOperators innerClassName Binary flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$Vector outerClass jdk/internal/vm/vector/VectorSupport innerClassName Vector flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Ternary outerClass jdk/incubator/vector/VectorOperators innerClassName Ternary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Test outerClass jdk/incubator/vector/VectorOperators innerClassName Test flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorMask outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorMask flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorShuffle outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorShuffle flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorPayload outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorPayload flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 method name fromCharArray descriptor (Ljdk/incubator/vector/VectorSpecies;[CI)Ljdk/incubator/vector/ShortVector; flags 9 signature (Ljdk/incubator/vector/VectorSpecies;[CI)Ljdk/incubator/vector/ShortVector; runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; method name fromCharArray descriptor (Ljdk/incubator/vector/VectorSpecies;[CILjdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/ShortVector; flags 9 signature (Ljdk/incubator/vector/VectorSpecies;[CILjdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/ShortVector; runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; method name fromCharArray descriptor (Ljdk/incubator/vector/VectorSpecies;[CI[II)Ljdk/incubator/vector/ShortVector; flags 9 signature (Ljdk/incubator/vector/VectorSpecies;[CI[II)Ljdk/incubator/vector/ShortVector; runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; diff --git a/make/data/symbols/jdk.incubator.vector-I.sym.txt b/make/data/symbols/jdk.incubator.vector-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..bb95434d8f92887d7d15fd189222a5235d27e220 --- /dev/null +++ b/make/data/symbols/jdk.incubator.vector-I.sym.txt @@ -0,0 +1,209 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name jdk/incubator/vector/ByteVector +header extends jdk/incubator/vector/AbstractVector flags 421 signature Ljdk/incubator/vector/AbstractVector; +innerclass innerClass jdk/incubator/vector/VectorOperators$Operator outerClass jdk/incubator/vector/VectorOperators innerClassName Operator flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorPayload outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorPayload flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Unary outerClass jdk/incubator/vector/VectorOperators innerClassName Unary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Comparison outerClass jdk/incubator/vector/VectorOperators innerClassName Comparison flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Associative outerClass jdk/incubator/vector/VectorOperators innerClassName Associative flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Binary outerClass jdk/incubator/vector/VectorOperators innerClassName Binary flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$Vector outerClass jdk/internal/vm/vector/VectorSupport innerClassName Vector flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorMask outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorMask flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Ternary outerClass jdk/incubator/vector/VectorOperators innerClassName Ternary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Test outerClass jdk/incubator/vector/VectorOperators innerClassName Test flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorShuffle outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorShuffle flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +-method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Unary;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/ByteVector; +-method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Binary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/ByteVector; +-method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Ternary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/ByteVector; +-method name compare descriptor (Ljdk/incubator/vector/VectorOperators$Comparison;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/VectorMask; +-method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Ternary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/Vector; +-method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Binary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/Vector; +-method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Unary;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/Vector; +method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Unary;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/ByteVector; flags 401 signature (Ljdk/incubator/vector/VectorOperators$Unary;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/ByteVector; +method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Binary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/ByteVector; flags 401 signature (Ljdk/incubator/vector/VectorOperators$Binary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/ByteVector; +method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Ternary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/ByteVector; flags 401 signature (Ljdk/incubator/vector/VectorOperators$Ternary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/ByteVector; +method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Ternary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/Vector; flags 1041 +method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Binary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/Vector; flags 1041 +method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Unary;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/Vector; flags 1041 + +class name jdk/incubator/vector/DoubleVector +header extends jdk/incubator/vector/AbstractVector flags 421 signature Ljdk/incubator/vector/AbstractVector; +innerclass innerClass jdk/incubator/vector/VectorOperators$Operator outerClass jdk/incubator/vector/VectorOperators innerClassName Operator flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorPayload outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorPayload flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Unary outerClass jdk/incubator/vector/VectorOperators innerClassName Unary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Comparison outerClass jdk/incubator/vector/VectorOperators innerClassName Comparison flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$Vector outerClass jdk/internal/vm/vector/VectorSupport innerClassName Vector flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorMask outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorMask flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Associative outerClass jdk/incubator/vector/VectorOperators innerClassName Associative flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Binary outerClass jdk/incubator/vector/VectorOperators innerClassName Binary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Ternary outerClass jdk/incubator/vector/VectorOperators innerClassName Ternary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Test outerClass jdk/incubator/vector/VectorOperators innerClassName Test flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorShuffle outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorShuffle flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +-method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Unary;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/DoubleVector; +-method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Binary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/DoubleVector; +-method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Ternary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/DoubleVector; +-method name compare descriptor (Ljdk/incubator/vector/VectorOperators$Comparison;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/VectorMask; +-method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Ternary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/Vector; +-method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Binary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/Vector; +-method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Unary;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/Vector; +method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Unary;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/DoubleVector; flags 401 signature (Ljdk/incubator/vector/VectorOperators$Unary;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/DoubleVector; +method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Binary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/DoubleVector; flags 401 signature (Ljdk/incubator/vector/VectorOperators$Binary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/DoubleVector; +method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Ternary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/DoubleVector; flags 401 signature (Ljdk/incubator/vector/VectorOperators$Ternary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/DoubleVector; +method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Ternary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/Vector; flags 1041 +method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Binary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/Vector; flags 1041 +method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Unary;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/Vector; flags 1041 + +class name jdk/incubator/vector/FloatVector +header extends jdk/incubator/vector/AbstractVector flags 421 signature Ljdk/incubator/vector/AbstractVector; +innerclass innerClass jdk/incubator/vector/VectorOperators$Operator outerClass jdk/incubator/vector/VectorOperators innerClassName Operator flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorPayload outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorPayload flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Unary outerClass jdk/incubator/vector/VectorOperators innerClassName Unary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Comparison outerClass jdk/incubator/vector/VectorOperators innerClassName Comparison flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$Vector outerClass jdk/internal/vm/vector/VectorSupport innerClassName Vector flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorMask outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorMask flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Associative outerClass jdk/incubator/vector/VectorOperators innerClassName Associative flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Binary outerClass jdk/incubator/vector/VectorOperators innerClassName Binary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Ternary outerClass jdk/incubator/vector/VectorOperators innerClassName Ternary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Test outerClass jdk/incubator/vector/VectorOperators innerClassName Test flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorShuffle outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorShuffle flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +-method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Unary;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/FloatVector; +-method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Binary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/FloatVector; +-method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Ternary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/FloatVector; +-method name compare descriptor (Ljdk/incubator/vector/VectorOperators$Comparison;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/VectorMask; +-method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Ternary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/Vector; +-method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Binary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/Vector; +-method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Unary;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/Vector; +method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Unary;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/FloatVector; flags 401 signature (Ljdk/incubator/vector/VectorOperators$Unary;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/FloatVector; +method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Binary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/FloatVector; flags 401 signature (Ljdk/incubator/vector/VectorOperators$Binary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/FloatVector; +method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Ternary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/FloatVector; flags 401 signature (Ljdk/incubator/vector/VectorOperators$Ternary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/FloatVector; +method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Ternary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/Vector; flags 1041 +method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Binary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/Vector; flags 1041 +method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Unary;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/Vector; flags 1041 + +class name jdk/incubator/vector/IntVector +header extends jdk/incubator/vector/AbstractVector flags 421 signature Ljdk/incubator/vector/AbstractVector; +innerclass innerClass jdk/incubator/vector/VectorOperators$Operator outerClass jdk/incubator/vector/VectorOperators innerClassName Operator flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorPayload outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorPayload flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Unary outerClass jdk/incubator/vector/VectorOperators innerClassName Unary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Comparison outerClass jdk/incubator/vector/VectorOperators innerClassName Comparison flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Associative outerClass jdk/incubator/vector/VectorOperators innerClassName Associative flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Binary outerClass jdk/incubator/vector/VectorOperators innerClassName Binary flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$Vector outerClass jdk/internal/vm/vector/VectorSupport innerClassName Vector flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorMask outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorMask flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Ternary outerClass jdk/incubator/vector/VectorOperators innerClassName Ternary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Test outerClass jdk/incubator/vector/VectorOperators innerClassName Test flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorShuffle outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorShuffle flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +-method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Unary;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/IntVector; +-method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Binary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/IntVector; +-method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Ternary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/IntVector; +-method name compare descriptor (Ljdk/incubator/vector/VectorOperators$Comparison;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/VectorMask; +-method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Ternary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/Vector; +-method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Binary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/Vector; +-method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Unary;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/Vector; +method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Unary;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/IntVector; flags 401 signature (Ljdk/incubator/vector/VectorOperators$Unary;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/IntVector; +method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Binary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/IntVector; flags 401 signature (Ljdk/incubator/vector/VectorOperators$Binary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/IntVector; +method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Ternary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/IntVector; flags 401 signature (Ljdk/incubator/vector/VectorOperators$Ternary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/IntVector; +method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Ternary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/Vector; flags 1041 +method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Binary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/Vector; flags 1041 +method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Unary;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/Vector; flags 1041 + +class name jdk/incubator/vector/LongVector +header extends jdk/incubator/vector/AbstractVector flags 421 signature Ljdk/incubator/vector/AbstractVector; +innerclass innerClass jdk/incubator/vector/VectorOperators$Operator outerClass jdk/incubator/vector/VectorOperators innerClassName Operator flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorPayload outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorPayload flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Unary outerClass jdk/incubator/vector/VectorOperators innerClassName Unary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Comparison outerClass jdk/incubator/vector/VectorOperators innerClassName Comparison flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Associative outerClass jdk/incubator/vector/VectorOperators innerClassName Associative flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Binary outerClass jdk/incubator/vector/VectorOperators innerClassName Binary flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$Vector outerClass jdk/internal/vm/vector/VectorSupport innerClassName Vector flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorMask outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorMask flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Ternary outerClass jdk/incubator/vector/VectorOperators innerClassName Ternary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Test outerClass jdk/incubator/vector/VectorOperators innerClassName Test flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorShuffle outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorShuffle flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +-method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Unary;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/LongVector; +-method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Binary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/LongVector; +-method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Ternary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/LongVector; +-method name compare descriptor (Ljdk/incubator/vector/VectorOperators$Comparison;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/VectorMask; +-method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Ternary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/Vector; +-method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Binary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/Vector; +-method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Unary;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/Vector; +method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Unary;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/LongVector; flags 401 signature (Ljdk/incubator/vector/VectorOperators$Unary;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/LongVector; +method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Binary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/LongVector; flags 401 signature (Ljdk/incubator/vector/VectorOperators$Binary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/LongVector; +method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Ternary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/LongVector; flags 401 signature (Ljdk/incubator/vector/VectorOperators$Ternary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/LongVector; +method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Ternary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/Vector; flags 1041 +method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Binary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/Vector; flags 1041 +method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Unary;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/Vector; flags 1041 + +class name jdk/incubator/vector/ShortVector +header extends jdk/incubator/vector/AbstractVector flags 421 signature Ljdk/incubator/vector/AbstractVector; +innerclass innerClass jdk/incubator/vector/VectorOperators$Operator outerClass jdk/incubator/vector/VectorOperators innerClassName Operator flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorPayload outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorPayload flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Unary outerClass jdk/incubator/vector/VectorOperators innerClassName Unary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Comparison outerClass jdk/incubator/vector/VectorOperators innerClassName Comparison flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Associative outerClass jdk/incubator/vector/VectorOperators innerClassName Associative flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Binary outerClass jdk/incubator/vector/VectorOperators innerClassName Binary flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$Vector outerClass jdk/internal/vm/vector/VectorSupport innerClassName Vector flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorMask outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorMask flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Ternary outerClass jdk/incubator/vector/VectorOperators innerClassName Ternary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Test outerClass jdk/incubator/vector/VectorOperators innerClassName Test flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorShuffle outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorShuffle flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +-method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Unary;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/ShortVector; +-method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Binary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/ShortVector; +-method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Ternary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/ShortVector; +-method name compare descriptor (Ljdk/incubator/vector/VectorOperators$Comparison;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/VectorMask; +-method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Ternary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/Vector; +-method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Binary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/Vector; +-method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Unary;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/Vector; +method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Unary;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/ShortVector; flags 401 signature (Ljdk/incubator/vector/VectorOperators$Unary;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/ShortVector; +method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Binary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/ShortVector; flags 401 signature (Ljdk/incubator/vector/VectorOperators$Binary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/ShortVector; +method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Ternary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/ShortVector; flags 401 signature (Ljdk/incubator/vector/VectorOperators$Ternary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/ShortVector; +method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Ternary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/Vector; flags 1041 +method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Binary;Ljdk/incubator/vector/Vector;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/Vector; flags 1041 +method name lanewise descriptor (Ljdk/incubator/vector/VectorOperators$Unary;Ljdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/Vector; flags 1041 + +class name jdk/incubator/vector/VectorMask +header extends jdk/internal/vm/vector/VectorSupport$VectorMask flags 421 signature Ljdk/internal/vm/vector/VectorSupport$VectorMask; +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorMask outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorMask flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorPayload outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorPayload flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + diff --git a/make/data/symbols/jdk.jartool-I.sym.txt b/make/data/symbols/jdk.jartool-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..9133449be101c8ec2bfb21b2236c7bebe56095ac --- /dev/null +++ b/make/data/symbols/jdk.jartool-I.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name jdk/security/jarsigner/JarSignerException +header extends java/lang/RuntimeException flags 21 + diff --git a/make/data/symbols/jdk.javadoc-H.sym.txt b/make/data/symbols/jdk.javadoc-H.sym.txt index b2ab2561f5c5a004ce9efdf761741c23bd46b948..d7d4a4c3779c29bf7e85113357d0a750c8fd831c 100644 --- a/make/data/symbols/jdk.javadoc-H.sym.txt +++ b/make/data/symbols/jdk.javadoc-H.sym.txt @@ -29,9 +29,9 @@ class name jdk/javadoc/doclet/Reporter header extends java/lang/Object flags 601 innerclass innerClass javax/tools/Diagnostic$Kind outerClass javax/tools/Diagnostic innerClassName Kind flags 4019 +method name print descriptor (Ljavax/tools/Diagnostic$Kind;Ljavax/tools/FileObject;IIILjava/lang/String;)V flags 1 method name getStandardWriter descriptor ()Ljava/io/PrintWriter; flags 1 method name getDiagnosticWriter descriptor ()Ljava/io/PrintWriter; flags 1 -method name print descriptor (Ljavax/tools/Diagnostic$Kind;Ljavax/tools/FileObject;IIILjava/lang/String;)V flags 1 class name jdk/javadoc/doclet/StandardDoclet header extends java/lang/Object implements jdk/javadoc/doclet/Doclet flags 21 diff --git a/make/data/symbols/jdk.javadoc-I.sym.txt b/make/data/symbols/jdk.javadoc-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..8c4ff94e5eb2f242688567b639bdb36837cb1600 --- /dev/null +++ b/make/data/symbols/jdk.javadoc-I.sym.txt @@ -0,0 +1,37 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name jdk/javadoc/doclet/Reporter +header extends java/lang/Object flags 601 +innerclass innerClass javax/tools/Diagnostic$Kind outerClass javax/tools/Diagnostic innerClassName Kind flags 4019 +method name print descriptor (Ljavax/tools/Diagnostic$Kind;Lcom/sun/source/util/DocTreePath;IIILjava/lang/String;)V flags 1 + +class name jdk/javadoc/doclet/StandardDoclet +header extends java/lang/Object implements jdk/javadoc/doclet/Doclet flags 21 +innerclass innerClass jdk/javadoc/doclet/Doclet$Option outerClass jdk/javadoc/doclet/Doclet innerClassName Option flags 609 + diff --git a/make/data/symbols/jdk.jconsole-I.sym.txt b/make/data/symbols/jdk.jconsole-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..79977a63ab9300c5dfcf72010f18b355296793cb --- /dev/null +++ b/make/data/symbols/jdk.jconsole-I.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name com/sun/tools/jconsole/JConsolePlugin +header extends java/lang/Object flags 421 + diff --git a/make/data/symbols/jdk.jdi-I.sym.txt b/make/data/symbols/jdk.jdi-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..55fc5be41abd4bc8a1a843169358988551e0410b --- /dev/null +++ b/make/data/symbols/jdk.jdi-I.sym.txt @@ -0,0 +1,395 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name com/sun/jdi/AbsentInformationException +header extends java/lang/Exception flags 21 + +class name com/sun/jdi/Accessible +header extends java/lang/Object flags 601 + +class name com/sun/jdi/ArrayReference +header extends java/lang/Object implements com/sun/jdi/ObjectReference flags 601 + +class name com/sun/jdi/ArrayType +header extends java/lang/Object implements com/sun/jdi/ReferenceType flags 601 + +class name com/sun/jdi/BooleanType +header extends java/lang/Object implements com/sun/jdi/PrimitiveType flags 601 + +class name com/sun/jdi/BooleanValue +header extends java/lang/Object implements com/sun/jdi/PrimitiveValue flags 601 + +class name com/sun/jdi/Bootstrap +header extends java/lang/Object flags 21 + +class name com/sun/jdi/ByteType +header extends java/lang/Object implements com/sun/jdi/PrimitiveType flags 601 + +class name com/sun/jdi/ByteValue +header extends java/lang/Object implements com/sun/jdi/PrimitiveValue,java/lang/Comparable flags 601 signature Ljava/lang/Object;Lcom/sun/jdi/PrimitiveValue;Ljava/lang/Comparable; + +class name com/sun/jdi/CharType +header extends java/lang/Object implements com/sun/jdi/PrimitiveType flags 601 + +class name com/sun/jdi/CharValue +header extends java/lang/Object implements com/sun/jdi/PrimitiveValue,java/lang/Comparable flags 601 signature Ljava/lang/Object;Lcom/sun/jdi/PrimitiveValue;Ljava/lang/Comparable; + +class name com/sun/jdi/ClassLoaderReference +header extends java/lang/Object implements com/sun/jdi/ObjectReference flags 601 + +class name com/sun/jdi/ClassNotLoadedException +header extends java/lang/Exception flags 21 + +class name com/sun/jdi/ClassNotPreparedException +header extends java/lang/RuntimeException flags 21 + +class name com/sun/jdi/ClassObjectReference +header extends java/lang/Object implements com/sun/jdi/ObjectReference flags 601 + +class name com/sun/jdi/ClassType +header extends java/lang/Object implements com/sun/jdi/ReferenceType flags 601 + +class name com/sun/jdi/DoubleType +header extends java/lang/Object implements com/sun/jdi/PrimitiveType flags 601 + +class name com/sun/jdi/DoubleValue +header extends java/lang/Object implements com/sun/jdi/PrimitiveValue,java/lang/Comparable flags 601 signature Ljava/lang/Object;Lcom/sun/jdi/PrimitiveValue;Ljava/lang/Comparable; + +class name com/sun/jdi/Field +header extends java/lang/Object implements com/sun/jdi/TypeComponent,java/lang/Comparable flags 601 signature Ljava/lang/Object;Lcom/sun/jdi/TypeComponent;Ljava/lang/Comparable; + +class name com/sun/jdi/FloatType +header extends java/lang/Object implements com/sun/jdi/PrimitiveType flags 601 + +class name com/sun/jdi/FloatValue +header extends java/lang/Object implements com/sun/jdi/PrimitiveValue,java/lang/Comparable flags 601 signature Ljava/lang/Object;Lcom/sun/jdi/PrimitiveValue;Ljava/lang/Comparable; + +class name com/sun/jdi/IncompatibleThreadStateException +header extends java/lang/Exception flags 21 + +class name com/sun/jdi/InconsistentDebugInfoException +header extends java/lang/RuntimeException flags 21 + +class name com/sun/jdi/IntegerType +header extends java/lang/Object implements com/sun/jdi/PrimitiveType flags 601 + +class name com/sun/jdi/IntegerValue +header extends java/lang/Object implements com/sun/jdi/PrimitiveValue,java/lang/Comparable flags 601 signature Ljava/lang/Object;Lcom/sun/jdi/PrimitiveValue;Ljava/lang/Comparable; + +class name com/sun/jdi/InterfaceType +header extends java/lang/Object implements com/sun/jdi/ReferenceType flags 601 + +class name com/sun/jdi/InternalException +header extends java/lang/RuntimeException flags 21 + +class name com/sun/jdi/InvalidCodeIndexException +header extends java/lang/RuntimeException flags 21 deprecated true runtimeAnnotations @Ljava/lang/Deprecated; + +class name com/sun/jdi/InvalidLineNumberException +header extends java/lang/RuntimeException flags 21 deprecated true runtimeAnnotations @Ljava/lang/Deprecated; + +class name com/sun/jdi/InvalidModuleException +header extends java/lang/RuntimeException flags 21 + +class name com/sun/jdi/InvalidStackFrameException +header extends java/lang/RuntimeException flags 21 + +class name com/sun/jdi/InvalidTypeException +header extends java/lang/Exception flags 21 + +class name com/sun/jdi/InvocationException +header extends java/lang/Exception flags 21 + +class name com/sun/jdi/JDIPermission +header extends java/security/BasicPermission flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name com/sun/jdi/LocalVariable +header extends java/lang/Object implements com/sun/jdi/Mirror,java/lang/Comparable flags 601 signature Ljava/lang/Object;Lcom/sun/jdi/Mirror;Ljava/lang/Comparable; + +class name com/sun/jdi/Locatable +header extends java/lang/Object flags 601 + +class name com/sun/jdi/Location +header extends java/lang/Object implements com/sun/jdi/Mirror,java/lang/Comparable flags 601 signature Ljava/lang/Object;Lcom/sun/jdi/Mirror;Ljava/lang/Comparable; + +class name com/sun/jdi/LongType +header extends java/lang/Object implements com/sun/jdi/PrimitiveType flags 601 + +class name com/sun/jdi/LongValue +header extends java/lang/Object implements com/sun/jdi/PrimitiveValue,java/lang/Comparable flags 601 signature Ljava/lang/Object;Lcom/sun/jdi/PrimitiveValue;Ljava/lang/Comparable; + +class name com/sun/jdi/Method +header extends java/lang/Object implements com/sun/jdi/TypeComponent,com/sun/jdi/Locatable,java/lang/Comparable flags 601 signature Ljava/lang/Object;Lcom/sun/jdi/TypeComponent;Lcom/sun/jdi/Locatable;Ljava/lang/Comparable; + +class name com/sun/jdi/Mirror +header extends java/lang/Object flags 601 + +class name com/sun/jdi/ModuleReference +header extends java/lang/Object implements com/sun/jdi/ObjectReference flags 601 + +class name com/sun/jdi/MonitorInfo +header extends java/lang/Object implements com/sun/jdi/Mirror flags 601 + +class name com/sun/jdi/NativeMethodException +header extends java/lang/RuntimeException flags 21 + +class name com/sun/jdi/ObjectCollectedException +header extends java/lang/RuntimeException flags 21 + +class name com/sun/jdi/ObjectReference +header extends java/lang/Object implements com/sun/jdi/Value flags 601 + +class name com/sun/jdi/PathSearchingVirtualMachine +header extends java/lang/Object implements com/sun/jdi/VirtualMachine flags 601 + +class name com/sun/jdi/PrimitiveType +header extends java/lang/Object implements com/sun/jdi/Type flags 601 + +class name com/sun/jdi/PrimitiveValue +header extends java/lang/Object implements com/sun/jdi/Value flags 601 + +class name com/sun/jdi/ReferenceType +header extends java/lang/Object implements com/sun/jdi/Type,java/lang/Comparable,com/sun/jdi/Accessible flags 601 signature Ljava/lang/Object;Lcom/sun/jdi/Type;Ljava/lang/Comparable;Lcom/sun/jdi/Accessible; + +class name com/sun/jdi/ShortType +header extends java/lang/Object implements com/sun/jdi/PrimitiveType flags 601 + +class name com/sun/jdi/ShortValue +header extends java/lang/Object implements com/sun/jdi/PrimitiveValue,java/lang/Comparable flags 601 signature Ljava/lang/Object;Lcom/sun/jdi/PrimitiveValue;Ljava/lang/Comparable; + +class name com/sun/jdi/StackFrame +header extends java/lang/Object implements com/sun/jdi/Mirror,com/sun/jdi/Locatable flags 601 + +class name com/sun/jdi/StringReference +header extends java/lang/Object implements com/sun/jdi/ObjectReference flags 601 + +class name com/sun/jdi/ThreadGroupReference +header extends java/lang/Object implements com/sun/jdi/ObjectReference flags 601 + +class name com/sun/jdi/ThreadReference +header extends java/lang/Object implements com/sun/jdi/ObjectReference flags 601 + +class name com/sun/jdi/Type +header extends java/lang/Object implements com/sun/jdi/Mirror flags 601 + +class name com/sun/jdi/TypeComponent +header extends java/lang/Object implements com/sun/jdi/Mirror,com/sun/jdi/Accessible flags 601 + +class name com/sun/jdi/VMCannotBeModifiedException +header extends java/lang/UnsupportedOperationException flags 21 + +class name com/sun/jdi/VMDisconnectedException +header extends java/lang/RuntimeException flags 21 + +class name com/sun/jdi/VMMismatchException +header extends java/lang/RuntimeException flags 21 + +class name com/sun/jdi/VMOutOfMemoryException +header extends java/lang/RuntimeException flags 21 + +class name com/sun/jdi/Value +header extends java/lang/Object implements com/sun/jdi/Mirror flags 601 + +class name com/sun/jdi/VirtualMachine +header extends java/lang/Object implements com/sun/jdi/Mirror flags 601 + +class name com/sun/jdi/VirtualMachineManager +header extends java/lang/Object flags 601 + +class name com/sun/jdi/VoidType +header extends java/lang/Object implements com/sun/jdi/Type flags 601 + +class name com/sun/jdi/VoidValue +header extends java/lang/Object implements com/sun/jdi/Value flags 601 + +class name com/sun/jdi/connect/AttachingConnector +header extends java/lang/Object implements com/sun/jdi/connect/Connector flags 601 +innerclass innerClass com/sun/jdi/connect/Connector$Argument outerClass com/sun/jdi/connect/Connector innerClassName Argument flags 609 + +class name com/sun/jdi/connect/IllegalConnectorArgumentsException +header extends java/lang/Exception flags 21 + +class name com/sun/jdi/connect/LaunchingConnector +header extends java/lang/Object implements com/sun/jdi/connect/Connector flags 601 +innerclass innerClass com/sun/jdi/connect/Connector$Argument outerClass com/sun/jdi/connect/Connector innerClassName Argument flags 609 + +class name com/sun/jdi/connect/ListeningConnector +header extends java/lang/Object implements com/sun/jdi/connect/Connector flags 601 +innerclass innerClass com/sun/jdi/connect/Connector$Argument outerClass com/sun/jdi/connect/Connector innerClassName Argument flags 609 + +class name com/sun/jdi/connect/Transport +header extends java/lang/Object flags 601 + +class name com/sun/jdi/connect/TransportTimeoutException +header extends java/io/IOException flags 21 + +class name com/sun/jdi/connect/VMStartException +header extends java/lang/Exception flags 21 + +class name com/sun/jdi/connect/spi/ClosedConnectionException +header extends java/io/IOException flags 21 + +class name com/sun/jdi/connect/spi/Connection +header extends java/lang/Object flags 421 + +class name com/sun/jdi/event/AccessWatchpointEvent +header extends java/lang/Object implements com/sun/jdi/event/WatchpointEvent flags 601 + +class name com/sun/jdi/event/BreakpointEvent +header extends java/lang/Object implements com/sun/jdi/event/LocatableEvent flags 601 + +class name com/sun/jdi/event/ClassPrepareEvent +header extends java/lang/Object implements com/sun/jdi/event/Event flags 601 + +class name com/sun/jdi/event/ClassUnloadEvent +header extends java/lang/Object implements com/sun/jdi/event/Event flags 601 + +class name com/sun/jdi/event/Event +header extends java/lang/Object implements com/sun/jdi/Mirror flags 601 + +class name com/sun/jdi/event/EventIterator +header extends java/lang/Object implements java/util/Iterator flags 601 signature Ljava/lang/Object;Ljava/util/Iterator; + +class name com/sun/jdi/event/EventQueue +header extends java/lang/Object implements com/sun/jdi/Mirror flags 601 + +class name com/sun/jdi/event/EventSet +header extends java/lang/Object implements com/sun/jdi/Mirror,java/util/Set flags 601 signature Ljava/lang/Object;Lcom/sun/jdi/Mirror;Ljava/util/Set; + +class name com/sun/jdi/event/ExceptionEvent +header extends java/lang/Object implements com/sun/jdi/event/LocatableEvent flags 601 + +class name com/sun/jdi/event/LocatableEvent +header extends java/lang/Object implements com/sun/jdi/event/Event,com/sun/jdi/Locatable flags 601 + +class name com/sun/jdi/event/MethodEntryEvent +header extends java/lang/Object implements com/sun/jdi/event/LocatableEvent flags 601 + +class name com/sun/jdi/event/MethodExitEvent +header extends java/lang/Object implements com/sun/jdi/event/LocatableEvent flags 601 + +class name com/sun/jdi/event/ModificationWatchpointEvent +header extends java/lang/Object implements com/sun/jdi/event/WatchpointEvent flags 601 + +class name com/sun/jdi/event/MonitorContendedEnterEvent +header extends java/lang/Object implements com/sun/jdi/event/LocatableEvent flags 601 + +class name com/sun/jdi/event/MonitorContendedEnteredEvent +header extends java/lang/Object implements com/sun/jdi/event/LocatableEvent flags 601 + +class name com/sun/jdi/event/MonitorWaitEvent +header extends java/lang/Object implements com/sun/jdi/event/LocatableEvent flags 601 + +class name com/sun/jdi/event/MonitorWaitedEvent +header extends java/lang/Object implements com/sun/jdi/event/LocatableEvent flags 601 + +class name com/sun/jdi/event/StepEvent +header extends java/lang/Object implements com/sun/jdi/event/LocatableEvent flags 601 + +class name com/sun/jdi/event/ThreadDeathEvent +header extends java/lang/Object implements com/sun/jdi/event/Event flags 601 + +class name com/sun/jdi/event/ThreadStartEvent +header extends java/lang/Object implements com/sun/jdi/event/Event flags 601 + +class name com/sun/jdi/event/VMDeathEvent +header extends java/lang/Object implements com/sun/jdi/event/Event flags 601 + +class name com/sun/jdi/event/VMDisconnectEvent +header extends java/lang/Object implements com/sun/jdi/event/Event flags 601 + +class name com/sun/jdi/event/VMStartEvent +header extends java/lang/Object implements com/sun/jdi/event/Event flags 601 + +class name com/sun/jdi/event/WatchpointEvent +header extends java/lang/Object implements com/sun/jdi/event/LocatableEvent flags 601 + +class name com/sun/jdi/request/AccessWatchpointRequest +header extends java/lang/Object implements com/sun/jdi/request/WatchpointRequest flags 601 + +class name com/sun/jdi/request/BreakpointRequest +header extends java/lang/Object implements com/sun/jdi/request/EventRequest,com/sun/jdi/Locatable flags 601 + +class name com/sun/jdi/request/ClassPrepareRequest +header extends java/lang/Object implements com/sun/jdi/request/EventRequest flags 601 + +class name com/sun/jdi/request/ClassUnloadRequest +header extends java/lang/Object implements com/sun/jdi/request/EventRequest flags 601 + +class name com/sun/jdi/request/DuplicateRequestException +header extends java/lang/RuntimeException flags 21 + +class name com/sun/jdi/request/EventRequest +header extends java/lang/Object implements com/sun/jdi/Mirror flags 601 + +class name com/sun/jdi/request/EventRequestManager +header extends java/lang/Object implements com/sun/jdi/Mirror flags 601 + +class name com/sun/jdi/request/ExceptionRequest +header extends java/lang/Object implements com/sun/jdi/request/EventRequest flags 601 + +class name com/sun/jdi/request/InvalidRequestStateException +header extends java/lang/RuntimeException flags 21 + +class name com/sun/jdi/request/MethodEntryRequest +header extends java/lang/Object implements com/sun/jdi/request/EventRequest flags 601 + +class name com/sun/jdi/request/MethodExitRequest +header extends java/lang/Object implements com/sun/jdi/request/EventRequest flags 601 + +class name com/sun/jdi/request/ModificationWatchpointRequest +header extends java/lang/Object implements com/sun/jdi/request/WatchpointRequest flags 601 + +class name com/sun/jdi/request/MonitorContendedEnterRequest +header extends java/lang/Object implements com/sun/jdi/request/EventRequest flags 601 + +class name com/sun/jdi/request/MonitorContendedEnteredRequest +header extends java/lang/Object implements com/sun/jdi/request/EventRequest flags 601 + +class name com/sun/jdi/request/MonitorWaitRequest +header extends java/lang/Object implements com/sun/jdi/request/EventRequest flags 601 + +class name com/sun/jdi/request/MonitorWaitedRequest +header extends java/lang/Object implements com/sun/jdi/request/EventRequest flags 601 + +class name com/sun/jdi/request/StepRequest +header extends java/lang/Object implements com/sun/jdi/request/EventRequest flags 601 + +class name com/sun/jdi/request/ThreadDeathRequest +header extends java/lang/Object implements com/sun/jdi/request/EventRequest flags 601 + +class name com/sun/jdi/request/ThreadStartRequest +header extends java/lang/Object implements com/sun/jdi/request/EventRequest flags 601 + +class name com/sun/jdi/request/VMDeathRequest +header extends java/lang/Object implements com/sun/jdi/request/EventRequest flags 601 + +class name com/sun/jdi/request/WatchpointRequest +header extends java/lang/Object implements com/sun/jdi/request/EventRequest flags 601 + diff --git a/make/data/symbols/jdk.jfr-B.sym.txt b/make/data/symbols/jdk.jfr-B.sym.txt index a42ce39defee3021814208120a6e5796f162ca88..be19cab9578fdaf7d8e1774607af8643ef2e805c 100644 --- a/make/data/symbols/jdk.jfr-B.sym.txt +++ b/make/data/symbols/jdk.jfr-B.sym.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ # ########################################################## # module name jdk.jfr -header exports jdk/jfr,jdk/jfr/consumer requires name\u0020;java.base\u0020;flags\u0020;8000 target linux-amd64 flags 8000 +header exports jdk/jfr,jdk/jfr/consumer extraModulePackages jdk/jfr/internal requires name\u0020;java.base\u0020;flags\u0020;8000 target linux-amd64 flags 8000 class name jdk/jfr/AnnotationElement header extends java/lang/Object flags 31 @@ -390,3 +390,12 @@ method name readEventTypes descriptor ()Ljava/util/List; thrownTypes java/io/IOE method name close descriptor ()V thrownTypes java/io/IOException flags 1 method name readAllEvents descriptor (Ljava/nio/file/Path;)Ljava/util/List; thrownTypes java/io/IOException flags 9 signature (Ljava/nio/file/Path;)Ljava/util/List; +class name jdk/jfr/internal/Control +header extends java/lang/Object flags 421 +method name descriptor (Ljava/security/AccessControlContext;)V flags 1 +method name descriptor (Ljava/lang/String;)V flags 1 +method name combine descriptor (Ljava/util/Set;)Ljava/lang/String; flags 401 signature (Ljava/util/Set;)Ljava/lang/String; +method name setValue descriptor (Ljava/lang/String;)V flags 401 +method name getValue descriptor ()Ljava/lang/String; flags 401 +method name clone descriptor ()Ljava/lang/Object; thrownTypes java/lang/CloneNotSupportedException flags 11 + diff --git a/make/data/symbols/jdk.jfr-G.sym.txt b/make/data/symbols/jdk.jfr-G.sym.txt index 397e082021a2fcfdde89d1b909b867524d2a5acf..ba5b7e3a74331e6f4d5ab0d129d62f5806a26ebe 100644 --- a/make/data/symbols/jdk.jfr-G.sym.txt +++ b/make/data/symbols/jdk.jfr-G.sym.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,9 @@ # ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### # ########################################################## # +module name jdk.jfr +header exports jdk/jfr,jdk/jfr/consumer requires name\u0020;java.base\u0020;flags\u0020;8000 target linux-amd64 flags 8000 + class name jdk/jfr/SettingControl header extends java/lang/Object flags 421 runtimeAnnotations @Ljdk/jfr/MetadataDefinition; @@ -48,3 +51,5 @@ class name jdk/jfr/consumer/RecordedObject class name jdk/jfr/consumer/RecordingStream method name onMetadata descriptor (Ljava/util/function/Consumer;)V flags 1 signature (Ljava/util/function/Consumer;)V +-class name jdk/jfr/internal/Control + diff --git a/make/data/symbols/jdk.jlink-I.sym.txt b/make/data/symbols/jdk.jlink-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..7cc29b0fc2c05c2674271b0918ed85a5f0f4d49b --- /dev/null +++ b/make/data/symbols/jdk.jlink-I.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.jlink +header requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;jdk.internal.opt\u0020;flags\u0020;0,name\u0020;jdk.jdeps\u0020;flags\u0020;0 uses jdk/tools/jlink/plugin/Plugin provides interface\u0020;java/util/spi/ToolProvider\u0020;impls\u0020;jdk/tools/jmod/Main$JmodToolProvider\u005C;u002C;jdk/tools/jlink/internal/Main$JlinkToolProvider,interface\u0020;jdk/tools/jlink/plugin/Plugin\u0020;impls\u0020;jdk/tools/jlink/internal/plugins/DefaultStripDebugPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/StripJavaDebugAttributesPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/ExcludePlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/ExcludeFilesPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/ExcludeJmodSectionPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/LegalNoticeFilePlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/SystemModulesPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/StripNativeCommandsPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/OrderResourcesPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/DefaultCompressPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/ExcludeVMPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/ReleaseInfoPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/AddOptionsPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/VendorBugURLPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/VendorVMBugURLPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/VendorVersionPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/CDSPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/StripNativeDebugSymbolsPlugin target linux-amd64 flags 8000 + diff --git a/make/data/symbols/jdk.jshell-I.sym.txt b/make/data/symbols/jdk.jshell-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..349690280cb7251d9e6aa1992b2709cca49cca8f --- /dev/null +++ b/make/data/symbols/jdk.jshell-I.sym.txt @@ -0,0 +1,108 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name jdk/jshell/DeclarationSnippet +header extends jdk/jshell/PersistentSnippet flags 421 +innerclass innerClass jdk/jshell/Snippet$SubKind outerClass jdk/jshell/Snippet innerClassName SubKind flags 4019 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/jshell/Diag +header extends java/lang/Object flags 421 + +class name jdk/jshell/EvalException +header extends jdk/jshell/JShellException flags 21 + +class name jdk/jshell/ExpressionSnippet +header extends jdk/jshell/Snippet flags 21 +innerclass innerClass jdk/jshell/Snippet$SubKind outerClass jdk/jshell/Snippet innerClassName SubKind flags 4019 + +class name jdk/jshell/ImportSnippet +header extends jdk/jshell/PersistentSnippet flags 21 +innerclass innerClass jdk/jshell/Snippet$SubKind outerClass jdk/jshell/Snippet innerClassName SubKind flags 4019 + +class name jdk/jshell/JShellException +header extends java/lang/Exception flags 21 + +class name jdk/jshell/MethodSnippet +header extends jdk/jshell/DeclarationSnippet flags 21 +innerclass innerClass jdk/jshell/Snippet$SubKind outerClass jdk/jshell/Snippet innerClassName SubKind flags 4019 + +class name jdk/jshell/PersistentSnippet +header extends jdk/jshell/Snippet flags 421 +innerclass innerClass jdk/jshell/Snippet$SubKind outerClass jdk/jshell/Snippet innerClassName SubKind flags 4019 + +class name jdk/jshell/SnippetEvent +header extends java/lang/Object flags 21 +innerclass innerClass jdk/jshell/Snippet$Status outerClass jdk/jshell/Snippet innerClassName Status flags 4019 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/jshell/StatementSnippet +header extends jdk/jshell/Snippet flags 21 +innerclass innerClass jdk/jshell/Snippet$SubKind outerClass jdk/jshell/Snippet innerClassName SubKind flags 4019 + +class name jdk/jshell/TypeDeclSnippet +header extends jdk/jshell/DeclarationSnippet flags 21 +innerclass innerClass jdk/jshell/Snippet$SubKind outerClass jdk/jshell/Snippet innerClassName SubKind flags 4019 + +class name jdk/jshell/execution/FailOverExecutionControlProvider +header extends java/lang/Object implements jdk/jshell/spi/ExecutionControlProvider flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/jshell/execution/JdiDefaultExecutionControl +header extends jdk/jshell/execution/JdiExecutionControl flags 21 +innerclass innerClass jdk/jshell/spi/ExecutionControl$InternalException outerClass jdk/jshell/spi/ExecutionControl innerClassName InternalException flags 9 +innerclass innerClass jdk/jshell/spi/ExecutionControl$EngineTerminationException outerClass jdk/jshell/spi/ExecutionControl innerClassName EngineTerminationException flags 9 +innerclass innerClass jdk/jshell/spi/ExecutionControl$RunException outerClass jdk/jshell/spi/ExecutionControl innerClassName RunException flags 409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/jshell/execution/JdiExecutionControlProvider +header extends java/lang/Object implements jdk/jshell/spi/ExecutionControlProvider flags 21 + +class name jdk/jshell/execution/LoaderDelegate +header extends java/lang/Object flags 601 +innerclass innerClass jdk/jshell/spi/ExecutionControl$ClassBytecodes outerClass jdk/jshell/spi/ExecutionControl innerClassName ClassBytecodes flags 19 +innerclass innerClass jdk/jshell/spi/ExecutionControl$ClassInstallException outerClass jdk/jshell/spi/ExecutionControl innerClassName ClassInstallException flags 9 +innerclass innerClass jdk/jshell/spi/ExecutionControl$NotImplementedException outerClass jdk/jshell/spi/ExecutionControl innerClassName NotImplementedException flags 9 +innerclass innerClass jdk/jshell/spi/ExecutionControl$EngineTerminationException outerClass jdk/jshell/spi/ExecutionControl innerClassName EngineTerminationException flags 9 +innerclass innerClass jdk/jshell/spi/ExecutionControl$InternalException outerClass jdk/jshell/spi/ExecutionControl innerClassName InternalException flags 9 + +class name jdk/jshell/execution/LocalExecutionControlProvider +header extends java/lang/Object implements jdk/jshell/spi/ExecutionControlProvider flags 21 + +class name jdk/jshell/spi/ExecutionControlProvider +header extends java/lang/Object flags 601 + +class name jdk/jshell/spi/ExecutionEnv +header extends java/lang/Object flags 601 + +class name jdk/jshell/spi/SPIResolutionException +header extends java/lang/RuntimeException flags 21 + +class name jdk/jshell/tool/JavaShellToolBuilder +header extends java/lang/Object flags 601 + diff --git a/make/data/symbols/jdk.jsobject-I.sym.txt b/make/data/symbols/jdk.jsobject-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..a955e4bfe94126dafbee412bf3fcc81fb63b13f3 --- /dev/null +++ b/make/data/symbols/jdk.jsobject-I.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name netscape/javascript/JSException +header extends java/lang/RuntimeException flags 21 + diff --git a/make/data/symbols/jdk.management-I.sym.txt b/make/data/symbols/jdk.management-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..a6b7d08c1b4d2e57a5dac7ac5f227661a085362b --- /dev/null +++ b/make/data/symbols/jdk.management-I.sym.txt @@ -0,0 +1,49 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name com/sun/management/GarbageCollectionNotificationInfo +header extends java/lang/Object implements javax/management/openmbean/CompositeDataView flags 21 + +class name com/sun/management/GarbageCollectorMXBean +header extends java/lang/Object implements java/lang/management/GarbageCollectorMXBean flags 601 + +class name com/sun/management/GcInfo +header extends java/lang/Object implements javax/management/openmbean/CompositeData,javax/management/openmbean/CompositeDataView flags 21 + +class name com/sun/management/HotSpotDiagnosticMXBean +header extends java/lang/Object implements java/lang/management/PlatformManagedObject flags 601 + +class name com/sun/management/OperatingSystemMXBean +header extends java/lang/Object implements java/lang/management/OperatingSystemMXBean flags 601 + +class name com/sun/management/ThreadMXBean +header extends java/lang/Object implements java/lang/management/ThreadMXBean flags 601 + +class name com/sun/management/UnixOperatingSystemMXBean +header extends java/lang/Object implements com/sun/management/OperatingSystemMXBean flags 601 + diff --git a/make/data/symbols/jdk.management.jfr-I.sym.txt b/make/data/symbols/jdk.management.jfr-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..e2ac7345ef96eca15b59e819c48addee47197cdd --- /dev/null +++ b/make/data/symbols/jdk.management.jfr-I.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.management.jfr +header exports jdk/management/jfr requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;jdk.management\u0020;flags\u0020;0,name\u0020;java.management\u0020;flags\u0020;20,name\u0020;jdk.jfr\u0020;flags\u0020;20 provides interface\u0020;sun/management/spi/PlatformMBeanProvider\u0020;impls\u0020;jdk/management/jfr/internal/FlightRecorderMXBeanProvider target linux-amd64 flags 8000 + diff --git a/make/data/symbols/jdk.net-I.sym.txt b/make/data/symbols/jdk.net-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..51aada714d6b309efb237af405dfc9f5638f618b --- /dev/null +++ b/make/data/symbols/jdk.net-I.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name jdk/net/NetworkPermission +header extends java/security/BasicPermission flags 31 + diff --git a/make/data/symbols/jdk.sctp-I.sym.txt b/make/data/symbols/jdk.sctp-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..1694db9490daa9f6e60636053bb464abdba8e033 --- /dev/null +++ b/make/data/symbols/jdk.sctp-I.sym.txt @@ -0,0 +1,73 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name com/sun/nio/sctp/AbstractNotificationHandler +header extends java/lang/Object implements com/sun/nio/sctp/NotificationHandler flags 21 signature Ljava/lang/Object;Lcom/sun/nio/sctp/NotificationHandler; + +class name com/sun/nio/sctp/Association +header extends java/lang/Object flags 21 + +class name com/sun/nio/sctp/HandlerResult +header extends java/lang/Enum flags 4031 signature Ljava/lang/Enum; + +class name com/sun/nio/sctp/IllegalReceiveException +header extends java/lang/IllegalStateException flags 21 + +class name com/sun/nio/sctp/IllegalUnbindException +header extends java/lang/IllegalStateException flags 21 + +class name com/sun/nio/sctp/InvalidStreamException +header extends java/lang/IllegalArgumentException flags 21 + +class name com/sun/nio/sctp/MessageInfo +header extends java/lang/Object flags 421 + +class name com/sun/nio/sctp/Notification +header extends java/lang/Object flags 601 + +class name com/sun/nio/sctp/NotificationHandler +header extends java/lang/Object flags 601 signature Ljava/lang/Object; + +class name com/sun/nio/sctp/SctpChannel +header extends java/nio/channels/spi/AbstractSelectableChannel flags 421 + +class name com/sun/nio/sctp/SctpMultiChannel +header extends java/nio/channels/spi/AbstractSelectableChannel flags 421 + +class name com/sun/nio/sctp/SctpServerChannel +header extends java/nio/channels/spi/AbstractSelectableChannel flags 421 + +class name com/sun/nio/sctp/SctpSocketOption +header extends java/lang/Object implements java/net/SocketOption flags 601 signature Ljava/lang/Object;Ljava/net/SocketOption; + +class name com/sun/nio/sctp/SendFailedNotification +header extends java/lang/Object implements com/sun/nio/sctp/Notification flags 421 + +class name com/sun/nio/sctp/ShutdownNotification +header extends java/lang/Object implements com/sun/nio/sctp/Notification flags 421 + diff --git a/make/data/symbols/jdk.security.auth-I.sym.txt b/make/data/symbols/jdk.security.auth-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..a144d3775a4e55487f31a86f3a9e73a984ad81a5 --- /dev/null +++ b/make/data/symbols/jdk.security.auth-I.sym.txt @@ -0,0 +1,106 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name com/sun/security/auth/LdapPrincipal +header extends java/lang/Object implements java/security/Principal,java/io/Serializable flags 31 + +class name com/sun/security/auth/NTDomainPrincipal +header extends java/lang/Object implements java/security/Principal,java/io/Serializable flags 21 + +class name com/sun/security/auth/NTNumericCredential +header extends java/lang/Object flags 21 + +class name com/sun/security/auth/NTSid +header extends java/lang/Object implements java/security/Principal,java/io/Serializable flags 21 + +class name com/sun/security/auth/NTSidDomainPrincipal +header extends com/sun/security/auth/NTSid flags 21 + +class name com/sun/security/auth/NTSidGroupPrincipal +header extends com/sun/security/auth/NTSid flags 21 + +class name com/sun/security/auth/NTSidPrimaryGroupPrincipal +header extends com/sun/security/auth/NTSid flags 21 + +class name com/sun/security/auth/NTSidUserPrincipal +header extends com/sun/security/auth/NTSid flags 21 + +class name com/sun/security/auth/NTUserPrincipal +header extends java/lang/Object implements java/security/Principal,java/io/Serializable flags 21 + +class name com/sun/security/auth/PrincipalComparator +header extends java/lang/Object flags 601 + +class name com/sun/security/auth/UnixNumericGroupPrincipal +header extends java/lang/Object implements java/security/Principal,java/io/Serializable flags 21 + +class name com/sun/security/auth/UnixNumericUserPrincipal +header extends java/lang/Object implements java/security/Principal,java/io/Serializable flags 21 + +class name com/sun/security/auth/UnixPrincipal +header extends java/lang/Object implements java/security/Principal,java/io/Serializable flags 21 + +class name com/sun/security/auth/UserPrincipal +header extends java/lang/Object implements java/security/Principal,java/io/Serializable flags 31 + +class name com/sun/security/auth/callback/TextCallbackHandler +header extends java/lang/Object implements javax/security/auth/callback/CallbackHandler flags 21 + +class name com/sun/security/auth/login/ConfigFile +header extends javax/security/auth/login/Configuration flags 21 + +class name com/sun/security/auth/module/JndiLoginModule +header extends java/lang/Object implements javax/security/auth/spi/LoginModule flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name com/sun/security/auth/module/KeyStoreLoginModule +header extends java/lang/Object implements javax/security/auth/spi/LoginModule flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name com/sun/security/auth/module/Krb5LoginModule +header extends java/lang/Object implements javax/security/auth/spi/LoginModule flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name com/sun/security/auth/module/LdapLoginModule +header extends java/lang/Object implements javax/security/auth/spi/LoginModule flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name com/sun/security/auth/module/NTLoginModule +header extends java/lang/Object implements javax/security/auth/spi/LoginModule flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name com/sun/security/auth/module/NTSystem +header extends java/lang/Object flags 21 + +class name com/sun/security/auth/module/UnixLoginModule +header extends java/lang/Object implements javax/security/auth/spi/LoginModule flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name com/sun/security/auth/module/UnixSystem +header extends java/lang/Object flags 21 + diff --git a/make/data/symbols/jdk.security.jgss-I.sym.txt b/make/data/symbols/jdk.security.jgss-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..a3fd927f93f800744d55d2f3a953ceb79d105fcc --- /dev/null +++ b/make/data/symbols/jdk.security.jgss-I.sym.txt @@ -0,0 +1,47 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name com/sun/security/jgss/AuthorizationDataEntry +header extends java/lang/Object flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name com/sun/security/jgss/ExtendedGSSContext +header extends java/lang/Object implements org/ietf/jgss/GSSContext flags 601 + +class name com/sun/security/jgss/ExtendedGSSCredential +header extends java/lang/Object implements org/ietf/jgss/GSSCredential flags 601 + +class name com/sun/security/jgss/GSSUtil +header extends java/lang/Object flags 21 + +class name com/sun/security/jgss/InquireSecContextPermission +header extends java/security/BasicPermission flags 31 + +class name com/sun/security/jgss/InquireType +header extends java/lang/Enum flags 4031 signature Ljava/lang/Enum; + diff --git a/make/data/symbols/jdk.unsupported-I.sym.txt b/make/data/symbols/jdk.unsupported-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..db2342c25e259d5415dcab0d052c0a1842f48bd9 --- /dev/null +++ b/make/data/symbols/jdk.unsupported-I.sym.txt @@ -0,0 +1,56 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name com/sun/nio/file/ExtendedCopyOption +header extends java/lang/Enum implements java/nio/file/CopyOption flags 4031 signature Ljava/lang/Enum;Ljava/nio/file/CopyOption; classAnnotations @Lsun/Proprietary+Annotation; + +class name com/sun/nio/file/ExtendedOpenOption +header extends java/lang/Enum implements java/nio/file/OpenOption flags 4031 signature Ljava/lang/Enum;Ljava/nio/file/OpenOption; classAnnotations @Lsun/Proprietary+Annotation; + +class name com/sun/nio/file/ExtendedWatchEventModifier +header extends java/lang/Enum implements java/nio/file/WatchEvent$Modifier flags 4031 signature Ljava/lang/Enum;Ljava/nio/file/WatchEvent$Modifier; classAnnotations @Lsun/Proprietary+Annotation; +innerclass innerClass java/nio/file/WatchEvent$Modifier outerClass java/nio/file/WatchEvent innerClassName Modifier flags 609 + +class name com/sun/nio/file/SensitivityWatchEventModifier +header extends java/lang/Enum implements java/nio/file/WatchEvent$Modifier flags 4031 signature Ljava/lang/Enum;Ljava/nio/file/WatchEvent$Modifier; classAnnotations @Lsun/Proprietary+Annotation; +innerclass innerClass java/nio/file/WatchEvent$Modifier outerClass java/nio/file/WatchEvent innerClassName Modifier flags 609 + +class name sun/misc/SignalHandler +header extends java/lang/Object flags 601 classAnnotations @Lsun/Proprietary+Annotation; + +class name sun/misc/Unsafe +-method name objectFieldOffset descriptor (Ljava/lang/reflect/Field;)J +-method name staticFieldOffset descriptor (Ljava/lang/reflect/Field;)J +-method name staticFieldBase descriptor (Ljava/lang/reflect/Field;)Ljava/lang/Object; +method name objectFieldOffset descriptor (Ljava/lang/reflect/Field;)J flags 1 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="18")@Ljdk/internal/vm/annotation/ForceInline; +method name staticFieldOffset descriptor (Ljava/lang/reflect/Field;)J flags 1 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="18")@Ljdk/internal/vm/annotation/ForceInline; +method name staticFieldBase descriptor (Ljava/lang/reflect/Field;)Ljava/lang/Object; flags 1 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="18")@Ljdk/internal/vm/annotation/ForceInline; + +class name sun/reflect/ReflectionFactory +header extends java/lang/Object flags 21 classAnnotations @Lsun/Proprietary+Annotation; + diff --git a/make/data/symbols/jdk.xml.dom-I.sym.txt b/make/data/symbols/jdk.xml.dom-I.sym.txt new file mode 100644 index 0000000000000000000000000000000000000000..24fc87498177232e04afc5ed40c8ac8cdca4995e --- /dev/null +++ b/make/data/symbols/jdk.xml.dom-I.sym.txt @@ -0,0 +1,295 @@ +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name org/w3c/dom/css/CSS2Properties +header extends java/lang/Object flags 601 + +class name org/w3c/dom/css/CSSCharsetRule +header extends java/lang/Object implements org/w3c/dom/css/CSSRule flags 601 + +class name org/w3c/dom/css/CSSFontFaceRule +header extends java/lang/Object implements org/w3c/dom/css/CSSRule flags 601 + +class name org/w3c/dom/css/CSSImportRule +header extends java/lang/Object implements org/w3c/dom/css/CSSRule flags 601 + +class name org/w3c/dom/css/CSSMediaRule +header extends java/lang/Object implements org/w3c/dom/css/CSSRule flags 601 + +class name org/w3c/dom/css/CSSPageRule +header extends java/lang/Object implements org/w3c/dom/css/CSSRule flags 601 + +class name org/w3c/dom/css/CSSPrimitiveValue +header extends java/lang/Object implements org/w3c/dom/css/CSSValue flags 601 + +class name org/w3c/dom/css/CSSRule +header extends java/lang/Object flags 601 + +class name org/w3c/dom/css/CSSRuleList +header extends java/lang/Object flags 601 + +class name org/w3c/dom/css/CSSStyleDeclaration +header extends java/lang/Object flags 601 + +class name org/w3c/dom/css/CSSStyleRule +header extends java/lang/Object implements org/w3c/dom/css/CSSRule flags 601 + +class name org/w3c/dom/css/CSSStyleSheet +header extends java/lang/Object implements org/w3c/dom/stylesheets/StyleSheet flags 601 + +class name org/w3c/dom/css/CSSUnknownRule +header extends java/lang/Object implements org/w3c/dom/css/CSSRule flags 601 + +class name org/w3c/dom/css/CSSValue +header extends java/lang/Object flags 601 + +class name org/w3c/dom/css/CSSValueList +header extends java/lang/Object implements org/w3c/dom/css/CSSValue flags 601 + +class name org/w3c/dom/css/Counter +header extends java/lang/Object flags 601 + +class name org/w3c/dom/css/DOMImplementationCSS +header extends java/lang/Object implements org/w3c/dom/DOMImplementation flags 601 + +class name org/w3c/dom/css/DocumentCSS +header extends java/lang/Object implements org/w3c/dom/stylesheets/DocumentStyle flags 601 + +class name org/w3c/dom/css/ElementCSSInlineStyle +header extends java/lang/Object flags 601 + +class name org/w3c/dom/css/RGBColor +header extends java/lang/Object flags 601 + +class name org/w3c/dom/css/Rect +header extends java/lang/Object flags 601 + +class name org/w3c/dom/css/ViewCSS +header extends java/lang/Object implements org/w3c/dom/views/AbstractView flags 601 + +class name org/w3c/dom/html/HTMLAnchorElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLAppletElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLAreaElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLBRElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLBaseElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLBaseFontElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLBodyElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLButtonElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLCollection +header extends java/lang/Object flags 601 + +class name org/w3c/dom/html/HTMLDListElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLDOMImplementation +header extends java/lang/Object implements org/w3c/dom/DOMImplementation flags 601 + +class name org/w3c/dom/html/HTMLDirectoryElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLDivElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLDocument +header extends java/lang/Object implements org/w3c/dom/Document flags 601 + +class name org/w3c/dom/html/HTMLElement +header extends java/lang/Object implements org/w3c/dom/Element flags 601 + +class name org/w3c/dom/html/HTMLFieldSetElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLFontElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLFormElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLFrameElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLFrameSetElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLHRElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLHeadElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLHeadingElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLHtmlElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLIFrameElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLImageElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLInputElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLIsIndexElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLLIElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLLabelElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLLegendElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLLinkElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLMapElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLMenuElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLMetaElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLModElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLOListElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLObjectElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLOptGroupElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLOptionElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLParagraphElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLParamElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLPreElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLQuoteElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLScriptElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLSelectElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLStyleElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLTableCaptionElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLTableCellElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLTableColElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLTableElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLTableRowElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLTableSectionElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLTextAreaElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLTitleElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLUListElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/stylesheets/DocumentStyle +header extends java/lang/Object flags 601 + +class name org/w3c/dom/stylesheets/LinkStyle +header extends java/lang/Object flags 601 + +class name org/w3c/dom/stylesheets/MediaList +header extends java/lang/Object flags 601 + +class name org/w3c/dom/stylesheets/StyleSheet +header extends java/lang/Object flags 601 + +class name org/w3c/dom/stylesheets/StyleSheetList +header extends java/lang/Object flags 601 + +class name org/w3c/dom/xpath/XPathEvaluator +header extends java/lang/Object flags 601 + +class name org/w3c/dom/xpath/XPathException +header extends java/lang/RuntimeException flags 21 + +class name org/w3c/dom/xpath/XPathExpression +header extends java/lang/Object flags 601 + +class name org/w3c/dom/xpath/XPathNSResolver +header extends java/lang/Object flags 601 + +class name org/w3c/dom/xpath/XPathNamespace +header extends java/lang/Object implements org/w3c/dom/Node flags 601 + +class name org/w3c/dom/xpath/XPathResult +header extends java/lang/Object flags 601 + diff --git a/make/data/symbols/symbols b/make/data/symbols/symbols index d05e92601ea7a4ce75e87e942097bf4efe47d614..691d1d85bf83068e3b058f1428408bddf64aecd7 100644 --- a/make/data/symbols/symbols +++ b/make/data/symbols/symbols @@ -29,7 +29,7 @@ #command used to generate this file: #build.tools.symbolgenerator.CreateSymbols build-description-incremental symbols include.list # -generate platforms 7:8:9:A:B:C:D:E:F:G:H +generate platforms 7:8:9:A:B:C:D:E:F:G:H:I platform version 8 files java.activation-8.sym.txt:java.base-8.sym.txt:java.compiler-8.sym.txt:java.corba-8.sym.txt:java.datatransfer-8.sym.txt:java.desktop-8.sym.txt:java.instrument-8.sym.txt:java.logging-8.sym.txt:java.management-8.sym.txt:java.management.rmi-8.sym.txt:java.naming-8.sym.txt:java.prefs-8.sym.txt:java.rmi-8.sym.txt:java.scripting-8.sym.txt:java.security.jgss-8.sym.txt:java.security.sasl-8.sym.txt:java.sql-8.sym.txt:java.sql.rowset-8.sym.txt:java.transaction-8.sym.txt:java.xml-8.sym.txt:java.xml.bind-8.sym.txt:java.xml.crypto-8.sym.txt:java.xml.ws-8.sym.txt:java.xml.ws.annotation-8.sym.txt:jdk.httpserver-8.sym.txt:jdk.management-8.sym.txt:jdk.scripting.nashorn-8.sym.txt:jdk.sctp-8.sym.txt:jdk.security.auth-8.sym.txt:jdk.security.jgss-8.sym.txt platform version 7 base 8 files java.base-7.sym.txt:java.compiler-7.sym.txt:java.datatransfer-7.sym.txt:java.desktop-7.sym.txt:java.logging-7.sym.txt:java.management-7.sym.txt:java.naming-7.sym.txt:java.prefs-7.sym.txt:java.rmi-7.sym.txt:java.scripting-7.sym.txt:java.security.jgss-7.sym.txt:java.security.sasl-7.sym.txt:java.sql-7.sym.txt:java.sql.rowset-7.sym.txt:java.xml-7.sym.txt:java.xml.bind-7.sym.txt:java.xml.ws.annotation-7.sym.txt:jdk.httpserver-7.sym.txt:jdk.management-7.sym.txt:jdk.scripting.nashorn-7.sym.txt:jdk.sctp-7.sym.txt:jdk.security.auth-7.sym.txt:jdk.security.jgss-7.sym.txt platform version 9 base 8 files java.activation-9.sym.txt:java.base-9.sym.txt:java.compiler-9.sym.txt:java.corba-9.sym.txt:java.datatransfer-9.sym.txt:java.desktop-9.sym.txt:java.instrument-9.sym.txt:java.logging-9.sym.txt:java.management-9.sym.txt:java.management.rmi-9.sym.txt:java.naming-9.sym.txt:java.prefs-9.sym.txt:java.rmi-9.sym.txt:java.scripting-9.sym.txt:java.se-9.sym.txt:java.se.ee-9.sym.txt:java.security.jgss-9.sym.txt:java.security.sasl-9.sym.txt:java.smartcardio-9.sym.txt:java.sql-9.sym.txt:java.sql.rowset-9.sym.txt:java.transaction-9.sym.txt:java.xml-9.sym.txt:java.xml.bind-9.sym.txt:java.xml.crypto-9.sym.txt:java.xml.ws-9.sym.txt:java.xml.ws.annotation-9.sym.txt:jdk.accessibility-9.sym.txt:jdk.attach-9.sym.txt:jdk.charsets-9.sym.txt:jdk.compiler-9.sym.txt:jdk.crypto.cryptoki-9.sym.txt:jdk.crypto.ec-9.sym.txt:jdk.dynalink-9.sym.txt:jdk.editpad-9.sym.txt:jdk.hotspot.agent-9.sym.txt:jdk.httpserver-9.sym.txt:jdk.incubator.httpclient-9.sym.txt:jdk.jartool-9.sym.txt:jdk.javadoc-9.sym.txt:jdk.jcmd-9.sym.txt:jdk.jconsole-9.sym.txt:jdk.jdeps-9.sym.txt:jdk.jdi-9.sym.txt:jdk.jdwp.agent-9.sym.txt:jdk.jlink-9.sym.txt:jdk.jshell-9.sym.txt:jdk.jsobject-9.sym.txt:jdk.jstatd-9.sym.txt:jdk.localedata-9.sym.txt:jdk.management-9.sym.txt:jdk.management.agent-9.sym.txt:jdk.naming.dns-9.sym.txt:jdk.naming.rmi-9.sym.txt:jdk.net-9.sym.txt:jdk.pack-9.sym.txt:jdk.policytool-9.sym.txt:jdk.rmic-9.sym.txt:jdk.scripting.nashorn-9.sym.txt:jdk.sctp-9.sym.txt:jdk.security.auth-9.sym.txt:jdk.security.jgss-9.sym.txt:jdk.unsupported-9.sym.txt:jdk.xml.dom-9.sym.txt:jdk.zipfs-9.sym.txt @@ -41,3 +41,4 @@ platform version E base D files java.base-E.sym.txt:java.compiler-E.sym.txt:java platform version F base E files java.base-F.sym.txt:java.compiler-F.sym.txt:java.desktop-F.sym.txt:java.management.rmi-F.sym.txt:java.naming-F.sym.txt:java.rmi-F.sym.txt:java.xml-F.sym.txt:jdk.compiler-F.sym.txt:jdk.incubator.foreign-F.sym.txt:jdk.jartool-F.sym.txt:jdk.javadoc-F.sym.txt:jdk.jdi-F.sym.txt:jdk.net-F.sym.txt:jdk.nio.mapmode-F.sym.txt:jdk.rmic-F.sym.txt:jdk.scripting.nashorn-F.sym.txt:jdk.unsupported-F.sym.txt platform version G base F files java.base-G.sym.txt:java.compiler-G.sym.txt:java.datatransfer-G.sym.txt:java.desktop-G.sym.txt:java.instrument-G.sym.txt:java.logging-G.sym.txt:java.management-G.sym.txt:java.management.rmi-G.sym.txt:java.naming-G.sym.txt:java.net.http-G.sym.txt:java.rmi-G.sym.txt:java.scripting-G.sym.txt:java.security.jgss-G.sym.txt:java.security.sasl-G.sym.txt:java.smartcardio-G.sym.txt:java.sql-G.sym.txt:java.sql.rowset-G.sym.txt:java.xml-G.sym.txt:java.xml.crypto-G.sym.txt:jdk.accessibility-G.sym.txt:jdk.attach-G.sym.txt:jdk.compiler-G.sym.txt:jdk.dynalink-G.sym.txt:jdk.httpserver-G.sym.txt:jdk.incubator.foreign-G.sym.txt:jdk.incubator.jpackage-G.sym.txt:jdk.incubator.vector-G.sym.txt:jdk.jartool-G.sym.txt:jdk.javadoc-G.sym.txt:jdk.jconsole-G.sym.txt:jdk.jdi-G.sym.txt:jdk.jfr-G.sym.txt:jdk.jpackage-G.sym.txt:jdk.jshell-G.sym.txt:jdk.jsobject-G.sym.txt:jdk.management-G.sym.txt:jdk.management.jfr-G.sym.txt:jdk.net-G.sym.txt:jdk.sctp-G.sym.txt:jdk.security.auth-G.sym.txt:jdk.security.jgss-G.sym.txt:jdk.unsupported-G.sym.txt:jdk.xml.dom-G.sym.txt platform version H base G files java.base-H.sym.txt:java.compiler-H.sym.txt:java.datatransfer-H.sym.txt:java.desktop-H.sym.txt:java.instrument-H.sym.txt:java.logging-H.sym.txt:java.management-H.sym.txt:java.management.rmi-H.sym.txt:java.naming-H.sym.txt:java.rmi-H.sym.txt:java.scripting-H.sym.txt:java.security.jgss-H.sym.txt:java.security.sasl-H.sym.txt:java.smartcardio-H.sym.txt:java.sql-H.sym.txt:java.sql.rowset-H.sym.txt:java.xml-H.sym.txt:java.xml.crypto-H.sym.txt:jdk.accessibility-H.sym.txt:jdk.attach-H.sym.txt:jdk.compiler-H.sym.txt:jdk.dynalink-H.sym.txt:jdk.httpserver-H.sym.txt:jdk.incubator.foreign-H.sym.txt:jdk.incubator.vector-H.sym.txt:jdk.jartool-H.sym.txt:jdk.javadoc-H.sym.txt:jdk.jconsole-H.sym.txt:jdk.jdi-H.sym.txt:jdk.jfr-H.sym.txt:jdk.jshell-H.sym.txt:jdk.jsobject-H.sym.txt:jdk.management-H.sym.txt:jdk.management.jfr-H.sym.txt:jdk.net-H.sym.txt:jdk.sctp-H.sym.txt:jdk.security.auth-H.sym.txt:jdk.security.jgss-H.sym.txt:jdk.unsupported-H.sym.txt:jdk.xml.dom-H.sym.txt +platform version I base H files java.base-I.sym.txt:java.compiler-I.sym.txt:java.datatransfer-I.sym.txt:java.desktop-I.sym.txt:java.instrument-I.sym.txt:java.logging-I.sym.txt:java.management-I.sym.txt:java.management.rmi-I.sym.txt:java.naming-I.sym.txt:java.net.http-I.sym.txt:java.rmi-I.sym.txt:java.scripting-I.sym.txt:java.security.jgss-I.sym.txt:java.security.sasl-I.sym.txt:java.smartcardio-I.sym.txt:java.sql-I.sym.txt:java.sql.rowset-I.sym.txt:java.xml-I.sym.txt:java.xml.crypto-I.sym.txt:jdk.accessibility-I.sym.txt:jdk.attach-I.sym.txt:jdk.compiler-I.sym.txt:jdk.dynalink-I.sym.txt:jdk.httpserver-I.sym.txt:jdk.incubator.foreign-I.sym.txt:jdk.incubator.vector-I.sym.txt:jdk.jartool-I.sym.txt:jdk.javadoc-I.sym.txt:jdk.jconsole-I.sym.txt:jdk.jdi-I.sym.txt:jdk.jlink-I.sym.txt:jdk.jshell-I.sym.txt:jdk.jsobject-I.sym.txt:jdk.management-I.sym.txt:jdk.management.jfr-I.sym.txt:jdk.net-I.sym.txt:jdk.sctp-I.sym.txt:jdk.security.auth-I.sym.txt:jdk.security.jgss-I.sym.txt:jdk.unsupported-I.sym.txt:jdk.xml.dom-I.sym.txt diff --git a/make/jdk/src/classes/build/tools/depend/Depend.java b/make/jdk/src/classes/build/tools/depend/Depend.java index 74df2af2d575f14551c57f7ceb3d7d1b449b2f16..71d1b378879b8ba5f17a9f9fb6349df78a2ad17f 100644 --- a/make/jdk/src/classes/build/tools/depend/Depend.java +++ b/make/jdk/src/classes/build/tools/depend/Depend.java @@ -37,6 +37,7 @@ import java.security.NoSuchAlgorithmException; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; +import java.util.HexFormat; import java.util.List; import java.util.Map; import java.util.Objects; @@ -156,13 +157,7 @@ public class Depend implements Plugin { } private String toString(byte[] digest) { - StringBuilder result = new StringBuilder(); - - for (byte b : digest) { - result.append(String.format("%X", b)); - } - - return result.toString(); + return HexFormat.of().withUpperCase().formatHex(digest); } private static final class APIVisitor implements ElementVisitor, diff --git a/make/jdk/src/classes/build/tools/makezipreproducible/MakeZipReproducible.java b/make/jdk/src/classes/build/tools/makezipreproducible/MakeZipReproducible.java new file mode 100644 index 0000000000000000000000000000000000000000..48f08541d6731253629ae550fd8eb5f88200ceb8 --- /dev/null +++ b/make/jdk/src/classes/build/tools/makezipreproducible/MakeZipReproducible.java @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package build.tools.makezipreproducible; + +import java.io.*; +import java.nio.file.*; +import java.nio.file.attribute.BasicFileAttributes; +import java.nio.channels.Channels; +import java.nio.channels.FileChannel; +import java.util.*; +import java.util.zip.ZipEntry; +import java.util.zip.ZipException; +import java.util.zip.ZipFile; +import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; + +/** + * Generate a zip file in a "reproducible" manner from the input zip file. + * Standard zip tools rely on OS file list querying whose ordering can vary + * by platform architecture, this class ensures the zip entries are ordered + * and also supports SOURCE_DATE_EPOCH timestamps. + */ +public class MakeZipReproducible { + String input_file = null; + String fname = null; + String zname = ""; + long timestamp = -1L; + boolean verbose = false; + + // Keep a sorted Set of ZipEntrys to be processed, so that the zip is reproducible + SortedMap entries = new TreeMap(); + + private boolean ok; + + public MakeZipReproducible() { + } + + public synchronized boolean run(String args[]) { + ok = true; + if (!parseArgs(args)) { + return false; + } + try { + zname = fname.replace(File.separatorChar, '/'); + if (zname.startsWith("./")) { + zname = zname.substring(2); + } + + if (verbose) System.out.println("Input zip file: " + input_file); + + File inFile = new File(input_file); + if (!inFile.exists()) { + error("Input zip file does not exist"); + ok = false; + } else { + File zipFile = new File(fname); + // Check archive to create does not exist + if (!zipFile.exists()) { + // Process input ZipEntries + ok = processInputEntries(inFile); + if (ok) { + try (FileOutputStream out = new FileOutputStream(fname)) { + ok = create(inFile, new BufferedOutputStream(out, 4096)); + } + } else { + } + } else { + error("Target zip file "+fname+" already exists."); + ok = false; + } + } + } catch (IOException e) { + fatalError(e); + ok = false; + } catch (Error ee) { + ee.printStackTrace(); + ok = false; + } catch (Throwable t) { + t.printStackTrace(); + ok = false; + } + return ok; + } + + boolean parseArgs(String args[]) { + try { + boolean parsingIncludes = false; + boolean parsingExcludes = false; + int count = 0; + while(count < args.length) { + if (args[count].startsWith("-")) { + String flag = args[count].substring(1); + switch (flag.charAt(0)) { + case 'f': + fname = args[++count]; + break; + case 't': + // SOURCE_DATE_EPOCH timestamp specified + timestamp = Long.parseLong(args[++count]) * 1000; + break; + case 'v': + verbose = true; + break; + default: + error(String.format("Illegal option -%s", String.valueOf(flag.charAt(0)))); + usageError(); + return false; + } + } else { + // input zip file + if (input_file != null) { + error("Input zip file already specified"); + usageError(); + return false; + } + input_file = args[count]; + } + count++; + } + } catch (ArrayIndexOutOfBoundsException e) { + usageError(); + return false; + } catch (NumberFormatException e) { + usageError(); + return false; + } + if (fname == null) { + error("-f must be specified"); + usageError(); + return false; + } + // If no files specified then default to current directory + if (input_file == null) { + error("No input zip file specified"); + usageError(); + return false; + } + + return true; + } + + // Process input zip file and add to sorted entries set + boolean processInputEntries(File inFile) throws IOException { + ZipFile zipFile = new ZipFile(inFile); + zipFile.stream().forEach(entry -> entries.put(entry.getName(), entry)); + + return true; + } + + // Create new zip from entries + boolean create(File inFile, OutputStream out) throws IOException + { + try (ZipFile zipFile = new ZipFile(inFile); + ZipOutputStream zos = new ZipOutputStream(out)) { + for (Map.Entry entry : entries.entrySet()) { + ZipEntry zipEntry = entry.getValue(); + if (zipEntry.getSize() > 0) { + try (InputStream eis = zipFile.getInputStream(zipEntry)) { + addEntry(zos, zipEntry, eis); + } + } else { + addEntry(zos, zipEntry, null); + } + } + } + return true; + } + + // Add Entry and data to Zip + void addEntry(ZipOutputStream zos, ZipEntry entry, InputStream entryInputStream) throws IOException { + if (verbose) { + System.out.println("Adding: "+entry.getName()); + } + + // Set to specified timestamp if set otherwise leave as original lastModified time + if (timestamp != -1L) { + entry.setTime(timestamp); + } + + zos.putNextEntry(entry); + if (entry.getSize() > 0 && entryInputStream != null) { + entryInputStream.transferTo(zos); + } + zos.closeEntry(); + } + + void usageError() { + error( + "Usage: MakeZipReproducible [-v] [-t ] -f \n" + + "Options:\n" + + " -v verbose output\n" + + " -f specify archive file name to create\n" + + " -t specific SOURCE_DATE_EPOCH value to use for timestamps\n" + + " input_zip_file re-written as a reproducible zip output_zip_file.\n"); + } + + void fatalError(Exception e) { + e.printStackTrace(); + } + + protected void error(String s) { + System.err.println(s); + } + + public static void main(String args[]) { + MakeZipReproducible z = new MakeZipReproducible(); + System.exit(z.run(args) ? 0 : 1); + } +} + diff --git a/make/jdk/src/classes/build/tools/taglet/ToolGuide.java b/make/jdk/src/classes/build/tools/taglet/ToolGuide.java index ae70d424222fda7099f8392b46939df041662268..f3ce80cf241da4c3465810a4887f832d3a69329b 100644 --- a/make/jdk/src/classes/build/tools/taglet/ToolGuide.java +++ b/make/jdk/src/classes/build/tools/taglet/ToolGuide.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,8 +31,8 @@ import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.lang.model.element.Element; -import javax.lang.model.element.ModuleElement; import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; import com.sun.source.doctree.DocTree; import com.sun.source.doctree.UnknownBlockTagTree; @@ -75,7 +75,7 @@ public class ToolGuide implements Taglet { */ @Override public Set getAllowedLocations() { - return EnumSet.of(MODULE, PACKAGE); + return EnumSet.of(MODULE, PACKAGE, TYPE); } @Override @@ -151,6 +151,12 @@ public class ToolGuide implements Taglet { return pe.getEnclosingElement() != null ? "../" + pkgPart : pkgPart; + case CLASS: + TypeElement te = (TypeElement)elem; + return te.getQualifiedName() + .toString() + .replace('.', '/') + .replaceAll("[^/]+", ".."); default: throw new IllegalArgumentException(elem.getKind().toString()); diff --git a/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java b/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java index 1f439e1c29e081bd23174c1a44f6cebb10c56841..ea700f0b660c6558c21e1dfd91d195d4eaaf0988 100644 --- a/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java +++ b/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java @@ -25,6 +25,7 @@ package build.tools.symbolgenerator; +import build.tools.symbolgenerator.CreateSymbols.ModuleHeaderDescription.ExportsDescription; import build.tools.symbolgenerator.CreateSymbols .ModuleHeaderDescription .ProvidesDescription; @@ -122,6 +123,7 @@ import com.sun.tools.classfile.Field; import com.sun.tools.classfile.InnerClasses_attribute; import com.sun.tools.classfile.InnerClasses_attribute.Info; import com.sun.tools.classfile.Method; +import com.sun.tools.classfile.ModulePackages_attribute; import com.sun.tools.classfile.MethodParameters_attribute; import com.sun.tools.classfile.ModuleMainClass_attribute; import com.sun.tools.classfile.ModuleResolution_attribute; @@ -244,7 +246,14 @@ public class CreateSymbols { md, mhd, versionsList); - mhd.exports.stream().forEach(pkg -> { + List packages = new ArrayList<>(); + mhd.exports.stream() + .map(ExportsDescription::packageName) + .forEach(packages::add); + if (mhd.extraModulePackages != null) { + packages.addAll(mhd.extraModulePackages); + } + packages.stream().forEach(pkg -> { for (char v : mhd.versions.toCharArray()) { package2Version2Module.computeIfAbsent(pkg, dummy -> new HashMap<>()).put(v, md.name); } @@ -974,13 +983,21 @@ public class CreateSymbols { return new RequiresEntry(idx, r.flags, r.version != null - ? addInt(cp, r.version) + ? addString(cp, r.version) : 0); } private static ExportsEntry createExportsEntry(List cp, - String e) { - return new ExportsEntry(addPackageName(cp, e), 0, new int[0]); + ExportsDescription export) { + int[] to; + if (export.isQualified()) { + to = export.to.stream() + .mapToInt(module -> addModuleName(cp, module)) + .toArray(); + } else { + to = new int[0]; + } + return new ExportsEntry(addPackageName(cp, export.packageName()), 0, to); } private static OpensEntry createOpensEntry(List cp, String e) { @@ -1405,7 +1422,7 @@ public class CreateSymbols { dumpDescriptions(classes, modules, platforms, Set.of(), descDest.resolve("symbols"), args); } //where: - private static final String DO_NO_MODIFY = + public static String DO_NOT_MODIFY = "#\n" + "# Copyright (c) {YEAR}, Oracle and/or its affiliates. All rights reserved.\n" + "# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n" + @@ -1477,14 +1494,19 @@ public class CreateSymbols { ExcludeIncludeList currentEIList = excludesIncludes; if (!currentVersionModules.isEmpty()) { + Set privateIncludes = + enhancedIncludesListBasedOnClassHeaders(classes, classData); Set includes = new HashSet<>(); for (ModuleDescription md : currentVersionModules.values()) { - md.header.get(0).exports.stream().map(e -> e + '/') + md.header.get(0).exports.stream() + .filter(e -> !e.isQualified()) + .map(e -> e.packageName + '/') .forEach(includes::add); } currentEIList = new ExcludeIncludeList(includes, + privateIncludes, Collections.emptySet()); } @@ -1507,7 +1529,9 @@ public class CreateSymbols { if (unsupported.header .get(0) .exports - .contains(cd.packge().replace('.', '/'))) { + .stream() + .map(ed -> ed.packageName) + .anyMatch(pack -> pack.equals(cd.packge().replace('.', '/')))) { ClassHeaderDescription ch = cd.header.get(0); if (ch.classAnnotations == null) { ch.classAnnotations = new ArrayList<>(); @@ -1529,7 +1553,7 @@ public class CreateSymbols { for (ClassDescription clazz : currentVersionClasses) { ClassHeaderDescription header = clazz.header.get(0); - if (includeEffectiveAccess(currentVersionClasses, clazz)) { + if (includeEffectiveAccess(currentVersionClasses, clazz) && currentEIList.accepts(clazz.name, false)) { modified |= include(includedClasses, currentVersionClasses, clazz.name); } @@ -1555,6 +1579,8 @@ public class CreateSymbols { } } while (modified); + Set allIncludedPackages = new HashSet<>(); + for (ClassDescription clazz : currentVersionClasses) { if (!includedClasses.contains(clazz.name)) { continue; @@ -1595,6 +1621,8 @@ public class CreateSymbols { } else { classes.add(clazz); } + + allIncludedPackages.add(clazz.packge().replace('.', '/')); } for (ModuleDescription module : currentVersionModules.values()) { @@ -1611,6 +1639,13 @@ public class CreateSymbols { } } + header.exports.removeIf(ed -> ed.isQualified() && + !allIncludedPackages.contains(ed.packageName())); + + if (header.extraModulePackages != null) { + header.extraModulePackages.retainAll(allIncludedPackages); + } + ModuleDescription existing = modules.get(module.name); if (existing != null) { @@ -1642,7 +1677,16 @@ public class CreateSymbols { md.header .stream() .filter(h -> h.versions.contains(v.version)) - .flatMap(h -> h.exports.stream()) + .flatMap(h -> { + List packages = new ArrayList<>(); + h.exports.stream() + .map(ExportsDescription::packageName) + .forEach(packages::add); + if (h.extraModulePackages != null) { + packages.addAll(h.extraModulePackages); + } + return packages.stream(); + }) .map(p -> p.replace('/', '.')) .forEach(p -> package2Modules.putIfAbsent(p, md.name)); } @@ -1718,11 +1762,11 @@ public class CreateSymbols { boolean hasChange = true; if (Files.isReadable(f)) { String oldContent = Files.readString(f, StandardCharsets.UTF_8); - int yearPos = DO_NO_MODIFY.indexOf("{YEAR}"); + int yearPos = DO_NOT_MODIFY.indexOf("{YEAR}"); String headerPattern = - Pattern.quote(DO_NO_MODIFY.substring(0, yearPos)) + + Pattern.quote(DO_NOT_MODIFY.substring(0, yearPos)) + "([0-9]+)(, [0-9]+)?" + - Pattern.quote(DO_NO_MODIFY.substring(yearPos + "{YEAR}".length())); + Pattern.quote(DO_NOT_MODIFY.substring(yearPos + "{YEAR}".length())); String pattern = headerPattern + Pattern.quote(dataString); Matcher m = Pattern.compile(pattern, Pattern.MULTILINE).matcher(oldContent); @@ -1739,7 +1783,7 @@ public class CreateSymbols { try (Writer out = Files.newBufferedWriter(f, StandardCharsets.UTF_8)) { String currentYear = String.valueOf(year); String yearSpec = (existingYear != null && !currentYear.equals(existingYear) ? existingYear + ", " : "") + currentYear; - out.append(DO_NO_MODIFY.replace("{YEAR}", yearSpec)); + out.append(DO_NOT_MODIFY.replace("{YEAR}", yearSpec)); out.write(dataString); } } @@ -1750,7 +1794,7 @@ public class CreateSymbols { outputFiles.put(desc, files); } - symbolsOut.append(DO_NO_MODIFY.replace("{YEAR}", "2015, " + year)); + symbolsOut.append(DO_NOT_MODIFY.replace("{YEAR}", "2015, " + year)); symbolsOut.append("#command used to generate this file:\n"); symbolsOut.append("#") .append(CreateSymbols.class.getName()) @@ -1923,7 +1967,7 @@ public class CreateSymbols { return ; } - if (!excludesIncludes.accepts(cf.getName())) { + if (!excludesIncludes.accepts(cf.getName(), true)) { return ; } @@ -2019,6 +2063,45 @@ public class CreateSymbols { addModuleHeader(moduleDesc, headerDesc, version); } + private Set enhancedIncludesListBasedOnClassHeaders(ClassList classes, + Iterable classData) { + Set additionalIncludes = new HashSet<>(); + + for (byte[] classFileData : classData) { + try (InputStream in = new ByteArrayInputStream(classFileData)) { + ClassFile cf = ClassFile.read(in); + + if (cf.access_flags.is(AccessFlags.ACC_MODULE)) { + continue; + } + + Set additionalClasses = new HashSet<>(); + + if (cf.super_class != 0) { + additionalClasses.add(cf.getSuperclassName()); + } + for (int i = 0; i < cf.interfaces.length; i++) { + additionalClasses.add(cf.getInterfaceName(i)); + } + + for (String additional : additionalClasses) { + int dollar; + + additionalIncludes.add(additional); + + while ((dollar = additional.lastIndexOf('$')) != (-1)) { + additional = additional.substring(0, dollar); + additionalIncludes.add(additional); + } + } + } catch (IOException | ConstantPoolException ex) { + throw new IllegalStateException(ex); + } + } + + return additionalIncludes; + } + private void addModuleHeader(ModuleDescription moduleDesc, ModuleHeaderDescription headerDesc, String version) { @@ -2204,9 +2287,11 @@ public class CreateSymbols { header.exports = Arrays.stream(mod.exports) - .filter(ee -> ee.exports_to_count == 0) - .map(ee -> getPackageName(cf, ee.exports_index)) + .map(ee -> ExportsDescription.create(cf, ee)) .collect(Collectors.toList()); + if (header.extraModulePackages != null) { + header.exports.forEach(ed -> header.extraModulePackages.remove(ed.packageName())); + } header.requires = Arrays.stream(mod.requires) .map(r -> RequiresDescription.create(cf, r)) @@ -2242,6 +2327,20 @@ public class CreateSymbols { break; } case Attribute.ModulePackages: + assert feature instanceof ModuleHeaderDescription; + ModuleHeaderDescription header = + (ModuleHeaderDescription) feature; + ModulePackages_attribute mod = + (ModulePackages_attribute) attr; + header.extraModulePackages = new ArrayList<>(); + for (int i = 0; i < mod.packages_count; i++) { + String packageName = getPackageName(cf, mod.packages_index[i]); + if (header.exports == null || + header.exports.stream().noneMatch(ed -> ed.packageName().equals(packageName))) { + header.extraModulePackages.add(packageName); + } + } + break; case Attribute.ModuleHashes: break; case Attribute.NestHost: { @@ -2352,11 +2451,16 @@ public class CreateSymbols { } } - private static Integer getVersion(ClassFile cf, int idx) { + public static String INJECTED_VERSION = null; + + private static String getVersion(ClassFile cf, int idx) { + if (INJECTED_VERSION != null) { + return INJECTED_VERSION; + } if (idx == 0) return null; try { - return ((CONSTANT_Integer_info) cf.constant_pool.get(idx)).value; + return ((CONSTANT_Utf8_info) cf.constant_pool.get(idx)).value; } catch (InvalidIndex ex) { throw new IllegalStateException(ex); } @@ -2470,9 +2574,15 @@ public class CreateSymbols { if (clazzName == null) return false; + ClassDescription desc = classes.find(clazzName, true); + + if (desc == null) { + return false; + } + boolean modified = includedClasses.add(clazzName); - for (ClassDescription outer : classes.enclosingClasses(classes.find(clazzName, true))) { + for (ClassDescription outer : classes.enclosingClasses(desc)) { modified |= includedClasses.add(outer.name); } @@ -2514,10 +2624,17 @@ public class CreateSymbols { public static class ExcludeIncludeList { public final Set includeList; + public final Set privateIncludeList; public final Set excludeList; protected ExcludeIncludeList(Set includeList, Set excludeList) { + this(includeList, Set.of(), excludeList); + } + + protected ExcludeIncludeList(Set includeList, Set privateIncludeList, + Set excludeList) { this.includeList = includeList; + this.privateIncludeList = privateIncludeList; this.excludeList = excludeList; } @@ -2537,8 +2654,10 @@ public class CreateSymbols { return new ExcludeIncludeList(includeList, excludeList); } - public boolean accepts(String className) { - return matches(includeList, className) && !matches(excludeList, className); + public boolean accepts(String className, boolean includePrivateClasses) { + return (matches(includeList, className) || + (includePrivateClasses && matches(privateIncludeList, className))) && + !matches(excludeList, className); } private static boolean matches(Set list, String className) { @@ -2738,8 +2857,9 @@ public class CreateSymbols { static class ModuleHeaderDescription extends HeaderDescription { String name; - List exports = new ArrayList<>(); + List exports = new ArrayList<>(); List opens = new ArrayList<>(); + List extraModulePackages = new ArrayList<>(); List requires = new ArrayList<>(); List uses = new ArrayList<>(); List provides = new ArrayList<>(); @@ -2753,6 +2873,7 @@ public class CreateSymbols { hash = 83 * hash + Objects.hashCode(this.name); hash = 83 * hash + Objects.hashCode(this.exports); hash = 83 * hash + Objects.hashCode(this.opens); + hash = 83 * hash + Objects.hashCode(this.extraModulePackages); hash = 83 * hash + Objects.hashCode(this.requires); hash = 83 * hash + Objects.hashCode(this.uses); hash = 83 * hash + Objects.hashCode(this.provides); @@ -2781,6 +2902,9 @@ public class CreateSymbols { if (!listEquals(this.opens, other.opens)) { return false; } + if (!listEquals(this.extraModulePackages, other.extraModulePackages)) { + return false; + } if (!listEquals(this.requires, other.requires)) { return false; } @@ -2812,10 +2936,17 @@ public class CreateSymbols { && versions.contains(version))) return ; output.append("header"); - if (exports != null && !exports.isEmpty()) - output.append(" exports " + serializeList(exports)); + if (exports != null && !exports.isEmpty()) { + List exportsList = + exports.stream() + .map(exp -> exp.serialize()) + .collect(Collectors.toList()); + output.append(" exports " + serializeList(exportsList)); + } if (opens != null && !opens.isEmpty()) output.append(" opens " + serializeList(opens)); + if (extraModulePackages != null && !extraModulePackages.isEmpty()) + output.append(" extraModulePackages " + serializeList(extraModulePackages)); if (requires != null && !requires.isEmpty()) { List requiresList = requires.stream() @@ -2862,8 +2993,12 @@ public class CreateSymbols { if (!"header".equals(reader.lineKey)) return false; - exports = deserializeList(reader.attributes.get("exports")); + List exportsList = deserializeList(reader.attributes.get("exports"), false); + exports = exportsList.stream() + .map(ExportsDescription::deserialize) + .collect(Collectors.toList()); opens = deserializeList(reader.attributes.get("opens")); + extraModulePackages = deserializeList(reader.attributes.get("extraModulePackages")); List requiresList = deserializeList(reader.attributes.get("requires")); requires = requiresList.stream() @@ -2893,13 +3028,53 @@ public class CreateSymbols { return true; } + record ExportsDescription(String packageName, List to) { + public String serialize() { + return packageName + + (isQualified() ? "[" + quote(serializeList(to), true, true) + "]" + : ""); + } + + public static ExportsDescription deserialize(String data) { + int bracket = data.indexOf("["); + String packageName; + List to; + if (bracket != (-1)) { + packageName = data.substring(0, bracket); + to = deserializeList(unquote(data.substring(bracket + 1, data.length() - 1))); + } else { + packageName = data; + to = null; + } + + return new ExportsDescription(packageName, to); + } + + public static ExportsDescription create(ClassFile cf, + ExportsEntry ee) { + String packageName = getPackageName(cf, ee.exports_index); + List to = null; + if (ee.exports_to_count > 0) { + to = new ArrayList<>(); + for (int moduleIndex : ee.exports_to_index) { + to.add(getModuleName(cf, moduleIndex)); + } + } + return new ExportsDescription(packageName, to); + } + + public boolean isQualified() { + return to != null && !to.isEmpty(); + } + } + static class RequiresDescription { final String moduleName; final int flags; - final Integer version; + final String version; public RequiresDescription(String moduleName, int flags, - Integer version) { + String version) { this.moduleName = moduleName; this.flags = flags; this.version = version; @@ -2907,7 +3082,7 @@ public class CreateSymbols { public String serialize() { String versionKeyValue = version != null - ? " version " + quote(String.valueOf(version), true) + ? " version " + quote(version, true) : ""; return "name " + quote(moduleName, true) + " flags " + quote(Integer.toHexString(flags), true) + @@ -2917,8 +3092,8 @@ public class CreateSymbols { public static RequiresDescription deserialize(String data) { Map attributes = splitAttributes(data); - Integer ver = attributes.containsKey("version") - ? Integer.parseInt(attributes.get("version")) + String ver = attributes.containsKey("version") + ? attributes.get("version") : null; int flags = Integer.parseInt(attributes.get("flags"), 16); return new RequiresDescription(attributes.get("name"), @@ -2929,7 +3104,7 @@ public class CreateSymbols { public static RequiresDescription create(ClassFile cf, RequiresEntry req) { String mod = getModuleName(cf, req.requires_index); - Integer ver = getVersion(cf, req.requires_version_index); + String ver = getVersion(cf, req.requires_version_index); return new RequiresDescription(mod, req.requires_flags, ver); @@ -3071,10 +3246,24 @@ public class CreateSymbols { header.write(output, baselineVersion, version); } for (FieldDescription field : fields) { - field.write(output, baselineVersion, version); + if (!field.versions.contains(version)) { + field.write(output, baselineVersion, version); + } + } + for (MethodDescription method : methods) { + if (!method.versions.contains(version)) { + method.write(output, baselineVersion, version); + } + } + for (FieldDescription field : fields) { + if (field.versions.contains(version)) { + field.write(output, baselineVersion, version); + } } for (MethodDescription method : methods) { - method.write(output, baselineVersion, version); + if (method.versions.contains(version)) { + method.write(output, baselineVersion, version); + } } output.append("\n"); } @@ -3157,6 +3346,12 @@ public class CreateSymbols { return pack; } + + @Override + public String toString() { + return name; + } + } static class ClassHeaderDescription extends HeaderDescription { @@ -3265,12 +3460,12 @@ public class CreateSymbols { readRecordComponents(reader); } readInnerClasses(reader); + isSealed = reader.attributes.containsKey("permittedSubclasses"); if (isSealed) { String subclassesList = reader.attributes.get("permittedSubclasses"); permittedSubclasses = deserializeList(subclassesList); } - return true; } @@ -4120,8 +4315,11 @@ public class CreateSymbols { } w.write("module:" + module.name); w.write("\n"); - for (String pack : header.get().exports) { - w.write(pack.replace('/', '.')); + for (ExportsDescription export : header.get().exports) { + if (export.isQualified()) { + continue; + } + w.write(export.packageName.replace('/', '.')); w.write("\n"); } } diff --git a/make/langtools/tools/compileproperties/CompileProperties.java b/make/langtools/tools/compileproperties/CompileProperties.java index 49cfc8a4a4b1445cd15a32d784c8204fe95587e0..7d69f9b47b2e9d37e06f2424054d85385d1571f7 100644 --- a/make/langtools/tools/compileproperties/CompileProperties.java +++ b/make/langtools/tools/compileproperties/CompileProperties.java @@ -183,7 +183,8 @@ public class CompileProperties { log.error("cannot close " + filename, e); } } - if ( ok = true && contents != null ) { + ok = true; + if ( contents != null ) { String tokens[] = (new String(contents)).split("\\s+"); if ( tokens.length > 0 ) { ok = parseOptions(tokens); diff --git a/make/modules/java.base/Gendata.gmk b/make/modules/java.base/Gendata.gmk index f9c25c8c53fcea1ffd4b490b7e27f3fbb3fad28e..4b894eeae4a6634b14f1491b323d03998856a77a 100644 --- a/make/modules/java.base/Gendata.gmk +++ b/make/modules/java.base/Gendata.gmk @@ -60,7 +60,11 @@ TARGETS += $(GENDATA_CURDATA) ################################################################################ -GENDATA_CACERTS_SRC := $(TOPDIR)/make/data/cacerts/ +ifneq ($(CACERTS_SRC), ) + GENDATA_CACERTS_SRC := $(CACERTS_SRC) +else + GENDATA_CACERTS_SRC := $(TOPDIR)/make/data/cacerts/ +endif GENDATA_CACERTS := $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/security/cacerts $(GENDATA_CACERTS): $(BUILD_TOOLS_JDK) $(wildcard $(GENDATA_CACERTS_SRC)/*) diff --git a/make/modules/java.base/Java.gmk b/make/modules/java.base/Java.gmk index 58d707e6148c55de800dd90b67d106de40ad6257..b5bd86ada54724c62bdbe7bc832292a191d9db76 100644 --- a/make/modules/java.base/Java.gmk +++ b/make/modules/java.base/Java.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ # questions. # -DOCLINT += -Xdoclint:all/protected,-reference,-accessibility \ +DOCLINT += -Xdoclint:all/protected,-reference \ '-Xdoclint/package:java.*,javax.*' JAVAC_FLAGS += -XDstringConcat=inline COPY += .icu .dat .spp .nrm content-types.properties \ diff --git a/make/modules/java.compiler/Java.gmk b/make/modules/java.compiler/Java.gmk index e124e8844d3b39179d97b509f66430fd05c9029f..e2d5ac264b8b6406cf5c928d40d9c018cf103d9e 100644 --- a/make/modules/java.compiler/Java.gmk +++ b/make/modules/java.compiler/Java.gmk @@ -25,3 +25,5 @@ DOCLINT += -Xdoclint:all/protected \ '-Xdoclint/package:java.*,javax.*' + +EXCLUDES += javax/tools/snippet-files diff --git a/make/modules/java.desktop/Java.gmk b/make/modules/java.desktop/Java.gmk index e9f0d1fa3184ef08fa19f64851534655cbdddb73..a6d6cf80c1d86b4ebbfaf292f196ad43ec0d7ff7 100644 --- a/make/modules/java.desktop/Java.gmk +++ b/make/modules/java.desktop/Java.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ # questions. # -DOCLINT += -Xdoclint:all/protected,-reference,-missing \ +DOCLINT += -Xdoclint:all/protected \ '-Xdoclint/package:java.*,javax.*' COPY += .gif .png .wav .txt .xml .css .pf CLEAN += iio-plugin.properties cursors.properties diff --git a/make/modules/java.instrument/Java.gmk b/make/modules/java.instrument/Java.gmk index 5f46b155e0cc22c61f8f9f898e81a8c681af14ee..f49e425718e7fc45c52e1f55c81e221145a781cf 100644 --- a/make/modules/java.instrument/Java.gmk +++ b/make/modules/java.instrument/Java.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,5 +23,5 @@ # questions. # -DOCLINT += -Xdoclint:all/protected,-accessibility \ +DOCLINT += -Xdoclint:all/protected \ '-Xdoclint/package:java.*,javax.*' diff --git a/make/modules/java.logging/Java.gmk b/make/modules/java.logging/Java.gmk index 40da53d432b1692f18278d1895fcdb705b38e30e..a6641fc1485d506aa3d11ce6e41512d1bf64720e 100644 --- a/make/modules/java.logging/Java.gmk +++ b/make/modules/java.logging/Java.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,5 +23,5 @@ # questions. # -DOCLINT += -Xdoclint:all/protected,-reference,-accessibility \ +DOCLINT += -Xdoclint:all/protected,-reference \ '-Xdoclint/package:java.*,javax.*' diff --git a/make/modules/java.management/Java.gmk b/make/modules/java.management/Java.gmk index 40da53d432b1692f18278d1895fcdb705b38e30e..a6641fc1485d506aa3d11ce6e41512d1bf64720e 100644 --- a/make/modules/java.management/Java.gmk +++ b/make/modules/java.management/Java.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,5 +23,5 @@ # questions. # -DOCLINT += -Xdoclint:all/protected,-reference,-accessibility \ +DOCLINT += -Xdoclint:all/protected,-reference \ '-Xdoclint/package:java.*,javax.*' diff --git a/make/modules/java.naming/Java.gmk b/make/modules/java.naming/Java.gmk index 32bb474385f2a86a12d5bbab4946cf98250d68fd..648853d6f532c204b61eb9f41e6c2ea314582356 100644 --- a/make/modules/java.naming/Java.gmk +++ b/make/modules/java.naming/Java.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,6 @@ # questions. # -DOCLINT += -Xdoclint:all/protected,-accessibility \ +DOCLINT += -Xdoclint:all/protected \ '-Xdoclint/package:java.*,javax.*' CLEAN += jndiprovider.properties diff --git a/make/modules/java.smartcardio/Java.gmk b/make/modules/java.smartcardio/Java.gmk index 5f46b155e0cc22c61f8f9f898e81a8c681af14ee..f49e425718e7fc45c52e1f55c81e221145a781cf 100644 --- a/make/modules/java.smartcardio/Java.gmk +++ b/make/modules/java.smartcardio/Java.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,5 +23,5 @@ # questions. # -DOCLINT += -Xdoclint:all/protected,-accessibility \ +DOCLINT += -Xdoclint:all/protected \ '-Xdoclint/package:java.*,javax.*' diff --git a/make/modules/java.sql.rowset/Java.gmk b/make/modules/java.sql.rowset/Java.gmk index 2ea5be28ed17dece0db11134a408d0cd8ddb68ff..63437c6113f5ea153c6d599ed8467b75040aa1ee 100644 --- a/make/modules/java.sql.rowset/Java.gmk +++ b/make/modules/java.sql.rowset/Java.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ # questions. # -DOCLINT += -Xdoclint:all/protected,-accessibility \ +DOCLINT += -Xdoclint:all/protected \ '-Xdoclint/package:java.*,javax.*' CLEAN_FILES += $(wildcard \ $(TOPDIR)/src/java.sql.rowset/share/classes/com/sun/rowset/*.properties \ diff --git a/make/modules/java.xml/Java.gmk b/make/modules/java.xml/Java.gmk index b7bf8b701650124702baf8e85d38ea2517a4e3aa..aa4b786020fea5a4c39bdba74e63636042a6eda9 100644 --- a/make/modules/java.xml/Java.gmk +++ b/make/modules/java.xml/Java.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ # questions. # -DOCLINT += -Xdoclint:all/protected,-accessibility \ +DOCLINT += -Xdoclint:all/protected \ '-Xdoclint/package:$(call CommaList, javax.xml.catalog javax.xml.datatype \ javax.xml.transform javax.xml.validation javax.xml.xpath)' CLEAN += .properties diff --git a/make/modules/jdk.unsupported.desktop/Java.gmk b/make/modules/jdk.httpserver/Launcher.gmk similarity index 84% rename from make/modules/jdk.unsupported.desktop/Java.gmk rename to make/modules/jdk.httpserver/Launcher.gmk index f892ebeb84c171d99d372a9203ace9abdbc16e5a..ead28ba1ca5ee7bdb460ded024029f487785eaeb 100644 --- a/make/modules/jdk.unsupported.desktop/Java.gmk +++ b/make/modules/jdk.httpserver/Launcher.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,4 +23,8 @@ # questions. # -DISABLED_WARNINGS_java += missing-explicit-ctor +include LauncherCommon.gmk + +$(eval $(call SetupBuildLauncher, jwebserver, \ + MAIN_CLASS := sun.net.httpserver.simpleserver.JWebServer, \ +)) diff --git a/make/src/classes/build/tools/jfr/GenerateJfrFiles.java b/make/src/classes/build/tools/jfr/GenerateJfrFiles.java index dbaa8db7f653df27eef191994f3e81d3e73972ac..a3b17cf8c3f5a8b76ccec07a5feda31624cea0b7 100644 --- a/make/src/classes/build/tools/jfr/GenerateJfrFiles.java +++ b/make/src/classes/build/tools/jfr/GenerateJfrFiles.java @@ -174,6 +174,7 @@ public class GenerateJfrFiles { boolean cutoff; boolean throttle; boolean experimental; + boolean internal; long id; boolean isEvent; boolean isRelation; @@ -197,6 +198,7 @@ public class GenerateJfrFiles { pos.writeBoolean(cutoff); pos.writeBoolean(throttle); pos.writeBoolean(experimental); + pos.writeBoolean(internal); pos.writeLong(id); pos.writeBoolean(isEvent); pos.writeBoolean(isRelation); @@ -487,6 +489,7 @@ public class GenerateJfrFiles { currentType.description = getString(attributes, "description"); currentType.category = getString(attributes, "category"); currentType.experimental = getBoolean(attributes, "experimental", false); + currentType.internal = getBoolean(attributes, "internal", false); currentType.thread = getBoolean(attributes, "thread", false); currentType.stackTrace = getBoolean(attributes, "stackTrace", false); currentType.startTime = getBoolean(attributes, "startTime", true); @@ -863,6 +866,9 @@ public class GenerateJfrFiles { private static void printWriteData(Printer out, TypeElement type) { out.write(" template "); out.write(" void writeData(Writer& w) {"); + if (type.isEvent && type.internal) { + out.write(" JfrEventSetting::unhide_internal_types();"); + } if (("_thread_in_native").equals(type.commitState)) { out.write(" // explicit epoch synchronization check"); out.write(" JfrEpochSynchronization sync;"); diff --git a/make/test/JtregNativeJdk.gmk b/make/test/JtregNativeJdk.gmk index 270ff93d1475da508de1968f3db4779d23f930b7..62c0fc809b33a85868c5ef5e791222ce6cec280f 100644 --- a/make/test/JtregNativeJdk.gmk +++ b/make/test/JtregNativeJdk.gmk @@ -53,8 +53,6 @@ BUILD_JDK_JTREG_EXECUTABLES_CFLAGS_exeJliLaunchTest := \ -I$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjli \ -I$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS)/native/libjli -BUILD_JDK_JTREG_LIBRARIES_LDFLAGS_libAsyncStackWalk := $(LIBCXX) - # Platform specific setup ifeq ($(call isTargetOs, windows), true) BUILD_JDK_JTREG_EXCLUDE += libDirectIO.c libInheritedChannel.c exelauncher.c @@ -66,9 +64,15 @@ ifeq ($(call isTargetOs, windows), true) BUILD_JDK_JTREG_EXECUTABLES_LIBS_exeCallerAccessTest := jvm.lib BUILD_JDK_JTREG_EXECUTABLES_LIBS_exerevokeall := advapi32.lib BUILD_JDK_JTREG_LIBRARIES_CFLAGS_libAsyncStackWalk := /EHsc + BUILD_JDK_JTREG_LIBRARIES_CFLAGS_libAsyncInvokers := /EHsc + BUILD_JDK_JTREG_LIBRARIES_LDFLAGS_libAsyncStackWalk := $(LIBCXX) + BUILD_JDK_JTREG_LIBRARIES_LDFLAGS_libAsyncInvokers := $(LIBCXX) else BUILD_JDK_JTREG_LIBRARIES_LIBS_libstringPlatformChars := -ljava BUILD_JDK_JTREG_LIBRARIES_LIBS_libDirectIO := -ljava + BUILD_JDK_JTREG_LIBRARIES_LDFLAGS_libNativeThread := -pthread + BUILD_JDK_JTREG_LIBRARIES_LDFLAGS_libAsyncStackWalk := $(LIBCXX) -pthread + BUILD_JDK_JTREG_LIBRARIES_LDFLAGS_libAsyncInvokers := $(LIBCXX) -pthread BUILD_JDK_JTREG_EXCLUDE += exerevokeall.c ifeq ($(call isTargetOs, linux), true) BUILD_JDK_JTREG_LIBRARIES_LIBS_libInheritedChannel := -ljava diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index f0dff9cf8bb4dd541c6caa3596f4bb83c3f42778..75af9ed04b217ec3aff1e6ec6c32b0ebf7fc3d99 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -2481,7 +2481,7 @@ const RegMask* Matcher::predicate_reg_mask(void) { return &_PR_REG_mask; } -const TypeVect* Matcher::predicate_reg_type(const Type* elemTy, int length) { +const TypeVectMask* Matcher::predicate_reg_type(const Type* elemTy, int length) { return new TypeVectMask(elemTy, length); } @@ -3906,37 +3906,40 @@ encode %{ // Check for existing monitor __ tbnz(disp_hdr, exact_log2(markWord::monitor_value), object_has_monitor); - // Set tmp to be (markWord of object | UNLOCK_VALUE). - __ orr(tmp, disp_hdr, markWord::unlocked_value); - - // Initialize the box. (Must happen before we update the object mark!) - __ str(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes())); - - // Compare object markWord with an unlocked value (tmp) and if - // equal exchange the stack address of our box with object markWord. - // On failure disp_hdr contains the possibly locked markWord. - __ cmpxchg(oop, tmp, box, Assembler::xword, /*acquire*/ true, - /*release*/ true, /*weak*/ false, disp_hdr); - __ br(Assembler::EQ, cont); - - assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0"); - - // If the compare-and-exchange succeeded, then we found an unlocked - // object, will have now locked it will continue at label cont - - __ bind(cas_failed); - // We did not see an unlocked object so try the fast recursive case. - - // Check if the owner is self by comparing the value in the - // markWord of object (disp_hdr) with the stack pointer. - __ mov(rscratch1, sp); - __ sub(disp_hdr, disp_hdr, rscratch1); - __ mov(tmp, (address) (~(os::vm_page_size()-1) | markWord::lock_mask_in_place)); - // If condition is true we are cont and hence we can store 0 as the - // displaced header in the box, which indicates that it is a recursive lock. - __ ands(tmp/*==0?*/, disp_hdr, tmp); // Sets flags for result - __ str(tmp/*==0, perhaps*/, Address(box, BasicLock::displaced_header_offset_in_bytes())); - + if (!UseHeavyMonitors) { + // Set tmp to be (markWord of object | UNLOCK_VALUE). + __ orr(tmp, disp_hdr, markWord::unlocked_value); + + // Initialize the box. (Must happen before we update the object mark!) + __ str(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes())); + + // Compare object markWord with an unlocked value (tmp) and if + // equal exchange the stack address of our box with object markWord. + // On failure disp_hdr contains the possibly locked markWord. + __ cmpxchg(oop, tmp, box, Assembler::xword, /*acquire*/ true, + /*release*/ true, /*weak*/ false, disp_hdr); + __ br(Assembler::EQ, cont); + + assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0"); + + // If the compare-and-exchange succeeded, then we found an unlocked + // object, will have now locked it will continue at label cont + + __ bind(cas_failed); + // We did not see an unlocked object so try the fast recursive case. + + // Check if the owner is self by comparing the value in the + // markWord of object (disp_hdr) with the stack pointer. + __ mov(rscratch1, sp); + __ sub(disp_hdr, disp_hdr, rscratch1); + __ mov(tmp, (address) (~(os::vm_page_size()-1) | markWord::lock_mask_in_place)); + // If condition is true we are cont and hence we can store 0 as the + // displaced header in the box, which indicates that it is a recursive lock. + __ ands(tmp/*==0?*/, disp_hdr, tmp); // Sets flags for result + __ str(tmp/*==0, perhaps*/, Address(box, BasicLock::displaced_header_offset_in_bytes())); + } else { + __ tst(oop, oop); // Set NE to indicate 'failure' -> take slow-path. We know that oop != 0. + } __ b(cont); // Handle existing monitor. @@ -3982,23 +3985,29 @@ encode %{ assert_different_registers(oop, box, tmp, disp_hdr); - // Find the lock address and load the displaced header from the stack. - __ ldr(disp_hdr, Address(box, BasicLock::displaced_header_offset_in_bytes())); + if (!UseHeavyMonitors) { + // Find the lock address and load the displaced header from the stack. + __ ldr(disp_hdr, Address(box, BasicLock::displaced_header_offset_in_bytes())); - // If the displaced header is 0, we have a recursive unlock. - __ cmp(disp_hdr, zr); - __ br(Assembler::EQ, cont); + // If the displaced header is 0, we have a recursive unlock. + __ cmp(disp_hdr, zr); + __ br(Assembler::EQ, cont); + } // Handle existing monitor. __ ldr(tmp, Address(oop, oopDesc::mark_offset_in_bytes())); __ tbnz(disp_hdr, exact_log2(markWord::monitor_value), object_has_monitor); - // Check if it is still a light weight lock, this is is true if we - // see the stack address of the basicLock in the markWord of the - // object. + if (!UseHeavyMonitors) { + // Check if it is still a light weight lock, this is is true if we + // see the stack address of the basicLock in the markWord of the + // object. - __ cmpxchg(oop, box, disp_hdr, Assembler::xword, /*acquire*/ false, - /*release*/ true, /*weak*/ false, tmp); + __ cmpxchg(oop, box, disp_hdr, Assembler::xword, /*acquire*/ false, + /*release*/ true, /*weak*/ false, tmp); + } else { + __ tst(oop, oop); // Set NE to indicate 'failure' -> take slow-path. We know that oop != 0. + } __ b(cont); assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0"); @@ -4007,19 +4016,15 @@ encode %{ __ bind(object_has_monitor); STATIC_ASSERT(markWord::monitor_value <= INT_MAX); __ add(tmp, tmp, -(int)markWord::monitor_value); // monitor - __ ldr(rscratch1, Address(tmp, ObjectMonitor::owner_offset_in_bytes())); __ ldr(disp_hdr, Address(tmp, ObjectMonitor::recursions_offset_in_bytes())); Label notRecursive; - __ cmp(rscratch1, rthread); - __ br(Assembler::NE, cont); - __ cbz(disp_hdr, notRecursive); // Recursive lock __ sub(disp_hdr, disp_hdr, 1u); __ str(disp_hdr, Address(tmp, ObjectMonitor::recursions_offset_in_bytes())); - // flag == EQ was set in the ownership check above + __ cmp(disp_hdr, disp_hdr); // Sets flags for result __ b(cont); __ bind(notRecursive); @@ -8560,10 +8565,10 @@ instruct popCountI(iRegINoSp dst, iRegIorL2I src, vRegF tmp) %{ "mov $dst, $tmp\t# vector (1D)" %} ins_encode %{ __ movw($src$$Register, $src$$Register); // ensure top 32 bits 0 - __ mov($tmp$$FloatRegister, __ T1D, 0, $src$$Register); + __ mov($tmp$$FloatRegister, __ D, 0, $src$$Register); __ cnt($tmp$$FloatRegister, __ T8B, $tmp$$FloatRegister); __ addv($tmp$$FloatRegister, __ T8B, $tmp$$FloatRegister); - __ mov($dst$$Register, $tmp$$FloatRegister, __ T1D, 0); + __ mov($dst$$Register, $tmp$$FloatRegister, __ D, 0); %} ins_pipe(pipe_class_default); @@ -8585,7 +8590,7 @@ instruct popCountI_mem(iRegINoSp dst, memory4 mem, vRegF tmp) %{ as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp, 4); __ cnt($tmp$$FloatRegister, __ T8B, $tmp$$FloatRegister); __ addv($tmp$$FloatRegister, __ T8B, $tmp$$FloatRegister); - __ mov($dst$$Register, $tmp$$FloatRegister, __ T1D, 0); + __ mov($dst$$Register, $tmp$$FloatRegister, __ D, 0); %} ins_pipe(pipe_class_default); @@ -8603,10 +8608,10 @@ instruct popCountL(iRegINoSp dst, iRegL src, vRegD tmp) %{ "addv $tmp, $tmp\t# vector (8B)\n\t" "mov $dst, $tmp\t# vector (1D)" %} ins_encode %{ - __ mov($tmp$$FloatRegister, __ T1D, 0, $src$$Register); + __ mov($tmp$$FloatRegister, __ D, 0, $src$$Register); __ cnt($tmp$$FloatRegister, __ T8B, $tmp$$FloatRegister); __ addv($tmp$$FloatRegister, __ T8B, $tmp$$FloatRegister); - __ mov($dst$$Register, $tmp$$FloatRegister, __ T1D, 0); + __ mov($dst$$Register, $tmp$$FloatRegister, __ D, 0); %} ins_pipe(pipe_class_default); @@ -8628,7 +8633,7 @@ instruct popCountL_mem(iRegINoSp dst, memory8 mem, vRegD tmp) %{ as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp, 8); __ cnt($tmp$$FloatRegister, __ T8B, $tmp$$FloatRegister); __ addv($tmp$$FloatRegister, __ T8B, $tmp$$FloatRegister); - __ mov($dst$$Register, $tmp$$FloatRegister, __ T1D, 0); + __ mov($dst$$Register, $tmp$$FloatRegister, __ D, 0); %} ins_pipe(pipe_class_default); diff --git a/src/hotspot/cpu/aarch64/aarch64_neon.ad b/src/hotspot/cpu/aarch64/aarch64_neon.ad index b3cb6f5f25516bfbcf6db920ce603b7df6baab69..7c84a93583b10a8e9ff5c4526c84970f3e02419f 100644 --- a/src/hotspot/cpu/aarch64/aarch64_neon.ad +++ b/src/hotspot/cpu/aarch64/aarch64_neon.ad @@ -511,7 +511,7 @@ instruct vcvt2Dto2I(vecD dst, vecX src) "fcvtzdw rscratch1, $src\n\t" "fcvtzdw rscratch2, $dst\n\t" "fmovs $dst, rscratch1\n\t" - "mov $dst, T2S, 1, rscratch2\t#convert 2D to 2I vector" + "mov $dst, S, 1, rscratch2\t#convert 2D to 2I vector" %} ins_encode %{ __ ins(as_FloatRegister($dst$$reg), __ D, as_FloatRegister($src$$reg), 0, 1); @@ -520,7 +520,7 @@ instruct vcvt2Dto2I(vecD dst, vecX src) __ fcvtzdw(rscratch1, as_FloatRegister($src$$reg)); __ fcvtzdw(rscratch2, as_FloatRegister($dst$$reg)); __ fmovs(as_FloatRegister($dst$$reg), rscratch1); - __ mov(as_FloatRegister($dst$$reg), __ T2S, 1, rscratch2); + __ mov(as_FloatRegister($dst$$reg), __ S, 1, rscratch2); %} ins_pipe(pipe_slow); %} @@ -1703,13 +1703,13 @@ instruct insert8B(vecD dst, vecD src, iRegIorL2I val, immI idx) match(Set dst (VectorInsert (Binary src val) idx)); ins_cost(INSN_COST); format %{ "orr $dst, T8B, $src, $src\n\t" - "mov $dst, T8B, $idx, $val\t# insert into vector(8B)" %} + "mov $dst, B, $idx, $val\t# insert into vector(8B)" %} ins_encode %{ if (as_FloatRegister($dst$$reg) != as_FloatRegister($src$$reg)) { __ orr(as_FloatRegister($dst$$reg), __ T8B, as_FloatRegister($src$$reg), as_FloatRegister($src$$reg)); } - __ mov(as_FloatRegister($dst$$reg), __ T8B, $idx$$constant, $val$$Register); + __ mov(as_FloatRegister($dst$$reg), __ B, $idx$$constant, $val$$Register); %} ins_pipe(pipe_slow); %} @@ -1720,13 +1720,13 @@ instruct insert16B(vecX dst, vecX src, iRegIorL2I val, immI idx) match(Set dst (VectorInsert (Binary src val) idx)); ins_cost(INSN_COST); format %{ "orr $dst, T16B, $src, $src\n\t" - "mov $dst, T16B, $idx, $val\t# insert into vector(16B)" %} + "mov $dst, B, $idx, $val\t# insert into vector(16B)" %} ins_encode %{ if (as_FloatRegister($dst$$reg) != as_FloatRegister($src$$reg)) { __ orr(as_FloatRegister($dst$$reg), __ T16B, as_FloatRegister($src$$reg), as_FloatRegister($src$$reg)); } - __ mov(as_FloatRegister($dst$$reg), __ T16B, $idx$$constant, $val$$Register); + __ mov(as_FloatRegister($dst$$reg), __ B, $idx$$constant, $val$$Register); %} ins_pipe(pipe_slow); %} @@ -1737,13 +1737,13 @@ instruct insert4S(vecD dst, vecD src, iRegIorL2I val, immI idx) match(Set dst (VectorInsert (Binary src val) idx)); ins_cost(INSN_COST); format %{ "orr $dst, T8B, $src, $src\n\t" - "mov $dst, T4H, $idx, $val\t# insert into vector(4S)" %} + "mov $dst, H, $idx, $val\t# insert into vector(4S)" %} ins_encode %{ if (as_FloatRegister($dst$$reg) != as_FloatRegister($src$$reg)) { __ orr(as_FloatRegister($dst$$reg), __ T8B, as_FloatRegister($src$$reg), as_FloatRegister($src$$reg)); } - __ mov(as_FloatRegister($dst$$reg), __ T4H, $idx$$constant, $val$$Register); + __ mov(as_FloatRegister($dst$$reg), __ H, $idx$$constant, $val$$Register); %} ins_pipe(pipe_slow); %} @@ -1754,13 +1754,13 @@ instruct insert8S(vecX dst, vecX src, iRegIorL2I val, immI idx) match(Set dst (VectorInsert (Binary src val) idx)); ins_cost(INSN_COST); format %{ "orr $dst, T16B, $src, $src\n\t" - "mov $dst, T8H, $idx, $val\t# insert into vector(8S)" %} + "mov $dst, H, $idx, $val\t# insert into vector(8S)" %} ins_encode %{ if (as_FloatRegister($dst$$reg) != as_FloatRegister($src$$reg)) { __ orr(as_FloatRegister($dst$$reg), __ T16B, as_FloatRegister($src$$reg), as_FloatRegister($src$$reg)); } - __ mov(as_FloatRegister($dst$$reg), __ T8H, $idx$$constant, $val$$Register); + __ mov(as_FloatRegister($dst$$reg), __ H, $idx$$constant, $val$$Register); %} ins_pipe(pipe_slow); %} @@ -1771,13 +1771,13 @@ instruct insert2I(vecD dst, vecD src, iRegIorL2I val, immI idx) match(Set dst (VectorInsert (Binary src val) idx)); ins_cost(INSN_COST); format %{ "orr $dst, T8B, $src, $src\n\t" - "mov $dst, T2S, $idx, $val\t# insert into vector(2I)" %} + "mov $dst, S, $idx, $val\t# insert into vector(2I)" %} ins_encode %{ if (as_FloatRegister($dst$$reg) != as_FloatRegister($src$$reg)) { __ orr(as_FloatRegister($dst$$reg), __ T8B, as_FloatRegister($src$$reg), as_FloatRegister($src$$reg)); } - __ mov(as_FloatRegister($dst$$reg), __ T2S, $idx$$constant, $val$$Register); + __ mov(as_FloatRegister($dst$$reg), __ S, $idx$$constant, $val$$Register); %} ins_pipe(pipe_slow); %} @@ -1788,13 +1788,13 @@ instruct insert4I(vecX dst, vecX src, iRegIorL2I val, immI idx) match(Set dst (VectorInsert (Binary src val) idx)); ins_cost(INSN_COST); format %{ "orr $dst, T16B, $src, $src\n\t" - "mov $dst, T4S, $idx, $val\t# insert into vector(4I)" %} + "mov $dst, S, $idx, $val\t# insert into vector(4I)" %} ins_encode %{ if (as_FloatRegister($dst$$reg) != as_FloatRegister($src$$reg)) { __ orr(as_FloatRegister($dst$$reg), __ T16B, as_FloatRegister($src$$reg), as_FloatRegister($src$$reg)); } - __ mov(as_FloatRegister($dst$$reg), __ T4S, $idx$$constant, $val$$Register); + __ mov(as_FloatRegister($dst$$reg), __ S, $idx$$constant, $val$$Register); %} ins_pipe(pipe_slow); %} @@ -1805,13 +1805,13 @@ instruct insert2L(vecX dst, vecX src, iRegL val, immI idx) match(Set dst (VectorInsert (Binary src val) idx)); ins_cost(INSN_COST); format %{ "orr $dst, T16B, $src, $src\n\t" - "mov $dst, T2D, $idx, $val\t# insert into vector(2L)" %} + "mov $dst, D, $idx, $val\t# insert into vector(2L)" %} ins_encode %{ if (as_FloatRegister($dst$$reg) != as_FloatRegister($src$$reg)) { __ orr(as_FloatRegister($dst$$reg), __ T16B, as_FloatRegister($src$$reg), as_FloatRegister($src$$reg)); } - __ mov(as_FloatRegister($dst$$reg), __ T2D, $idx$$constant, $val$$Register); + __ mov(as_FloatRegister($dst$$reg), __ D, $idx$$constant, $val$$Register); %} ins_pipe(pipe_slow); %} @@ -2044,11 +2044,11 @@ instruct vmul2L(vecX dst, vecX src1, vecX src2, iRegLNoSp tmp1, iRegLNoSp tmp2) __ umov($tmp1$$Register, as_FloatRegister($src1$$reg), __ D, 0); __ umov($tmp2$$Register, as_FloatRegister($src2$$reg), __ D, 0); __ mul(as_Register($tmp2$$reg), as_Register($tmp2$$reg), as_Register($tmp1$$reg)); - __ mov(as_FloatRegister($dst$$reg), __ T2D, 0, $tmp2$$Register); + __ mov(as_FloatRegister($dst$$reg), __ D, 0, $tmp2$$Register); __ umov($tmp1$$Register, as_FloatRegister($src1$$reg), __ D, 1); __ umov($tmp2$$Register, as_FloatRegister($src2$$reg), __ D, 1); __ mul(as_Register($tmp2$$reg), as_Register($tmp2$$reg), as_Register($tmp1$$reg)); - __ mov(as_FloatRegister($dst$$reg), __ T2D, 1, $tmp2$$Register); + __ mov(as_FloatRegister($dst$$reg), __ D, 1, $tmp2$$Register); %} ins_pipe(pipe_slow); %} @@ -5617,3 +5617,35 @@ instruct vmask_lasttrue16B(iRegINoSp dst, vecX src) %{ %} ins_pipe(pipe_slow); %} + +instruct vmask_tolong8B(iRegLNoSp dst, vecD src) %{ + match(Set dst (VectorMaskToLong src)); + ins_cost(5 * INSN_COST); + format %{ "vmask_tolong $dst, $src\t# convert mask to long (8B)" %} + ins_encode %{ + // Input "src" is a vector of boolean represented as + // bytes with 0x00/0x01 as element values. + + __ fmovd(as_Register($dst$$reg), as_FloatRegister($src$$reg)); + __ bytemask_compress(as_Register($dst$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vmask_tolong16B(iRegLNoSp dst, vecX src) %{ + match(Set dst (VectorMaskToLong src)); + ins_cost(11 * INSN_COST); + format %{ "vmask_tolong $dst, $src\t# convert mask to long (16B)" %} + ins_encode %{ + // Input "src" is a vector of boolean represented as + // bytes with 0x00/0x01 as element values. + + __ umov(as_Register($dst$$reg), as_FloatRegister($src$$reg), __ D, 0); + __ umov(rscratch1, as_FloatRegister($src$$reg), __ D, 1); + __ bytemask_compress(as_Register($dst$$reg)); + __ bytemask_compress(rscratch1); + __ orr(as_Register($dst$$reg), as_Register($dst$$reg), + rscratch1, Assembler::LSL, 8); + %} + ins_pipe(pipe_slow); +%} diff --git a/src/hotspot/cpu/aarch64/aarch64_neon_ad.m4 b/src/hotspot/cpu/aarch64/aarch64_neon_ad.m4 index ded6d0fd6d2eb961c88579e204d9cf2abec4d1b1..ff94bb002fafc0d6c831a9fea239a289dcec482d 100644 --- a/src/hotspot/cpu/aarch64/aarch64_neon_ad.m4 +++ b/src/hotspot/cpu/aarch64/aarch64_neon_ad.m4 @@ -296,7 +296,7 @@ instruct vcvt2Dto2I(vecD dst, vecX src) "fcvtzdw rscratch1, $src\n\t" "fcvtzdw rscratch2, $dst\n\t" "fmovs $dst, rscratch1\n\t" - "mov $dst, T2S, 1, rscratch2\t#convert 2D to 2I vector" + "mov $dst, S, 1, rscratch2\t#convert 2D to 2I vector" %} ins_encode %{ __ ins(as_FloatRegister($dst$$reg), __ D, as_FloatRegister($src$$reg), 0, 1); @@ -305,7 +305,7 @@ instruct vcvt2Dto2I(vecD dst, vecX src) __ fcvtzdw(rscratch1, as_FloatRegister($src$$reg)); __ fcvtzdw(rscratch2, as_FloatRegister($dst$$reg)); __ fmovs(as_FloatRegister($dst$$reg), rscratch1); - __ mov(as_FloatRegister($dst$$reg), __ T2S, 1, rscratch2); + __ mov(as_FloatRegister($dst$$reg), __ S, 1, rscratch2); %} ins_pipe(pipe_slow); %} @@ -868,13 +868,13 @@ instruct insert$1$2`'(vec$3 dst, vec$3 src, iReg$4`'ORL2I($4) val, immI idx) match(Set dst (VectorInsert (Binary src val) idx)); ins_cost(INSN_COST); format %{ "orr $dst, T$5, $src, $src\n\t" - "mov $dst, T$1`'iTYPE2SIMD($2), $idx, $val\t# insert into vector($1$2)" %} + "mov $dst, iTYPE2SIMD($2), $idx, $val\t# insert into vector($1$2)" %} ins_encode %{ if (as_FloatRegister($dst$$reg) != as_FloatRegister($src$$reg)) { __ orr(as_FloatRegister($dst$$reg), __ T$5, as_FloatRegister($src$$reg), as_FloatRegister($src$$reg)); } - __ mov(as_FloatRegister($dst$$reg), __ T$1`'iTYPE2SIMD($2), $idx$$constant, $val$$Register); + __ mov(as_FloatRegister($dst$$reg), __ iTYPE2SIMD($2), $idx$$constant, $val$$Register); %} ins_pipe(pipe_slow); %}')dnl @@ -1003,11 +1003,11 @@ instruct vmul2L(vecX dst, vecX src1, vecX src2, iRegLNoSp tmp1, iRegLNoSp tmp2) __ umov($tmp1$$Register, as_FloatRegister($src1$$reg), __ D, 0); __ umov($tmp2$$Register, as_FloatRegister($src2$$reg), __ D, 0); __ mul(as_Register($tmp2$$reg), as_Register($tmp2$$reg), as_Register($tmp1$$reg)); - __ mov(as_FloatRegister($dst$$reg), __ T2D, 0, $tmp2$$Register); + __ mov(as_FloatRegister($dst$$reg), __ D, 0, $tmp2$$Register); __ umov($tmp1$$Register, as_FloatRegister($src1$$reg), __ D, 1); __ umov($tmp2$$Register, as_FloatRegister($src2$$reg), __ D, 1); __ mul(as_Register($tmp2$$reg), as_Register($tmp2$$reg), as_Register($tmp1$$reg)); - __ mov(as_FloatRegister($dst$$reg), __ T2D, 1, $tmp2$$Register); + __ mov(as_FloatRegister($dst$$reg), __ D, 1, $tmp2$$Register); %} ins_pipe(pipe_slow); %} @@ -2481,3 +2481,35 @@ instruct vmask_lasttrue16B(iRegINoSp dst, vecX src) %{ %} ins_pipe(pipe_slow); %} + +instruct vmask_tolong8B(iRegLNoSp dst, vecD src) %{ + match(Set dst (VectorMaskToLong src)); + ins_cost(5 * INSN_COST); + format %{ "vmask_tolong $dst, $src\t# convert mask to long (8B)" %} + ins_encode %{ + // Input "src" is a vector of boolean represented as + // bytes with 0x00/0x01 as element values. + + __ fmovd(as_Register($dst$$reg), as_FloatRegister($src$$reg)); + __ bytemask_compress(as_Register($dst$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vmask_tolong16B(iRegLNoSp dst, vecX src) %{ + match(Set dst (VectorMaskToLong src)); + ins_cost(11 * INSN_COST); + format %{ "vmask_tolong $dst, $src\t# convert mask to long (16B)" %} + ins_encode %{ + // Input "src" is a vector of boolean represented as + // bytes with 0x00/0x01 as element values. + + __ umov(as_Register($dst$$reg), as_FloatRegister($src$$reg), __ D, 0); + __ umov(rscratch1, as_FloatRegister($src$$reg), __ D, 1); + __ bytemask_compress(as_Register($dst$$reg)); + __ bytemask_compress(rscratch1); + __ orr(as_Register($dst$$reg), as_Register($dst$$reg), + rscratch1, Assembler::LSL, 8); + %} + ins_pipe(pipe_slow); +%} diff --git a/src/hotspot/cpu/aarch64/aarch64_sve.ad b/src/hotspot/cpu/aarch64/aarch64_sve.ad index 6ad2d68526c8e175f4aad69a9fd7cbfc4dcf3184..fc3ece5ef3a2e196617779c12ab474e4e3c83155 100644 --- a/src/hotspot/cpu/aarch64/aarch64_sve.ad +++ b/src/hotspot/cpu/aarch64/aarch64_sve.ad @@ -5744,4 +5744,35 @@ instruct vmask_lasttrue_partial(iRegINoSp dst, pReg src, pReg ptmp, rFlagsReg cr __ sve_vmask_lasttrue($dst$$Register, bt, as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg)); %} ins_pipe(pipe_slow); -%} \ No newline at end of file +%} + +instruct vmask_tolong(iRegLNoSp dst, pReg src, vReg vtmp1, vReg vtmp2, pRegGov pgtmp, rFlagsReg cr) %{ + predicate(UseSVE > 0 && + n->in(1)->bottom_type()->is_vect()->length() <= 64); + match(Set dst (VectorMaskToLong src)); + effect(TEMP vtmp1, TEMP vtmp2, TEMP pgtmp, KILL cr); + ins_cost(13 * SVE_COST); + format %{ "vmask_tolong $dst, $src\t# vector mask tolong (sve)" %} + ins_encode %{ + __ sve_vmask_tolong(as_Register($dst$$reg), as_PRegister($src$$reg), + Matcher::vector_element_basic_type(this, $src), + Matcher::vector_length(this, $src), + as_FloatRegister($vtmp1$$reg), as_FloatRegister($vtmp2$$reg), + as_PRegister($pgtmp$$reg)); + %} + ins_pipe(pipe_slow); +%} +// ---------------------------- Vector mask generation --------------------------- +instruct vmask_gen(pRegGov pg, iRegL len, rFlagsReg cr) %{ + predicate(UseSVE > 0); + match(Set pg (VectorMaskGen len)); + effect(KILL cr); + ins_cost(SVE_COST); + format %{ "sve_whilelo $pg, zr, $len\t # sve" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + Assembler::SIMD_RegVariant size = __ elemType_to_regVariant(bt); + __ sve_whilelo(as_PRegister($pg$$reg), size, zr, as_Register($len$$reg)); + %} + ins_pipe(pipe_slow); +%} diff --git a/src/hotspot/cpu/aarch64/aarch64_sve_ad.m4 b/src/hotspot/cpu/aarch64/aarch64_sve_ad.m4 index 65de321a6e121407ae875b65482fe054cec2bfb6..fcc0a17a4a12bc1b614dbefe80e267119baa765e 100644 --- a/src/hotspot/cpu/aarch64/aarch64_sve_ad.m4 +++ b/src/hotspot/cpu/aarch64/aarch64_sve_ad.m4 @@ -3174,4 +3174,36 @@ instruct vmask_lasttrue_partial(iRegINoSp dst, pReg src, pReg ptmp, rFlagsReg cr __ sve_vmask_lasttrue($dst$$Register, bt, as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg)); %} ins_pipe(pipe_slow); +%} + +instruct vmask_tolong(iRegLNoSp dst, pReg src, vReg vtmp1, vReg vtmp2, pRegGov pgtmp, rFlagsReg cr) %{ + predicate(UseSVE > 0 && + n->in(1)->bottom_type()->is_vect()->length() <= 64); + match(Set dst (VectorMaskToLong src)); + effect(TEMP vtmp1, TEMP vtmp2, TEMP pgtmp, KILL cr); + ins_cost(13 * SVE_COST); + format %{ "vmask_tolong $dst, $src\t# vector mask tolong (sve)" %} + ins_encode %{ + __ sve_vmask_tolong(as_Register($dst$$reg), as_PRegister($src$$reg), + Matcher::vector_element_basic_type(this, $src), + Matcher::vector_length(this, $src), + as_FloatRegister($vtmp1$$reg), as_FloatRegister($vtmp2$$reg), + as_PRegister($pgtmp$$reg)); + %} + ins_pipe(pipe_slow); %}dnl + +// ---------------------------- Vector mask generation --------------------------- +instruct vmask_gen(pRegGov pg, iRegL len, rFlagsReg cr) %{ + predicate(UseSVE > 0); + match(Set pg (VectorMaskGen len)); + effect(KILL cr); + ins_cost(SVE_COST); + format %{ "sve_whilelo $pg, zr, $len\t # sve" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + Assembler::SIMD_RegVariant size = __ elemType_to_regVariant(bt); + __ sve_whilelo(as_PRegister($pg$$reg), size, zr, as_Register($len$$reg)); + %} + ins_pipe(pipe_slow); +%} diff --git a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp index 9eee231ec0fea3046f9c600e90d8673bc6b99c9a..95edeadbf187af9fc3593e416a9c34dab63f4104 100644 --- a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp @@ -478,16 +478,17 @@ class Address { assert(size == 0, "bad size"); size = 0b100; } + assert(offset_ok_for_immed(_offset, size), + "must be, was: " INT64_FORMAT ", %d", _offset, size); unsigned mask = (1 << size) - 1; - if (_offset < 0 || _offset & mask) - { - i->f(0b00, 25, 24); - i->f(0, 21), i->f(0b00, 11, 10); - i->sf(_offset, 20, 12); - } else { - i->f(0b01, 25, 24); - i->f(_offset >> size, 21, 10); - } + if (_offset < 0 || _offset & mask) { + i->f(0b00, 25, 24); + i->f(0, 21), i->f(0b00, 11, 10); + i->sf(_offset, 20, 12); + } else { + i->f(0b01, 25, 24); + i->f(_offset >> size, 21, 10); + } } break; @@ -2755,20 +2756,18 @@ public: // Move from general purpose register // mov Vd.T[index], Rn - void mov(FloatRegister Vd, SIMD_Arrangement T, int index, Register Xn) { + void mov(FloatRegister Vd, SIMD_RegVariant T, int index, Register Xn) { + guarantee(T != Q, "invalid register variant"); starti; - f(0b01001110000, 31, 21), f(((1 << (T >> 1)) | (index << ((T >> 1) + 1))), 20, 16); + f(0b01001110000, 31, 21), f(((1 << T) | (index << (T + 1))), 20, 16); f(0b000111, 15, 10), zrf(Xn, 5), rf(Vd, 0); } // Move to general purpose register // mov Rd, Vn.T[index] - void mov(Register Xd, FloatRegister Vn, SIMD_Arrangement T, int index) { - guarantee(T >= T2S && T < T1Q, "only D and S arrangements are supported"); - starti; - f(0, 31), f((T >= T1D) ? 1:0, 30), f(0b001110000, 29, 21); - f(((1 << (T >> 1)) | (index << ((T >> 1) + 1))), 20, 16); - f(0b001111, 15, 10), rf(Vn, 5), rf(Xd, 0); + void mov(Register Xd, FloatRegister Vn, SIMD_RegVariant T, int index) { + guarantee(T == S || T == D, "invalid register variant"); + umov(Xd, Vn, T, index); } private: diff --git a/src/hotspot/cpu/aarch64/assembler_aarch64.inline.hpp b/src/hotspot/cpu/aarch64/assembler_aarch64.inline.hpp index 9fabf1699c53121e63eeadf79f5de7a45b85b24c..e7efe472b829047a09ae79d63fc84a72ac76452c 100644 --- a/src/hotspot/cpu/aarch64/assembler_aarch64.inline.hpp +++ b/src/hotspot/cpu/aarch64/assembler_aarch64.inline.hpp @@ -30,8 +30,14 @@ #include "asm/codeBuffer.hpp" #include "code/codeCache.hpp" - +// Check if an offset is within the encoding range for LDR/STR instructions +// with an immediate offset, either using unscaled signed 9-bits or, scaled +// unsigned 12-bits. We favour the scaled unsigned encoding for all aligned +// offsets (only using the signed 9-bit encoding for negative and unaligned +// offsets). As a precondition, 0 <= shift <= 4 is the log2(size), for the +// supported data widths, {1, 2, 4, 8, 16} bytes. inline bool Address::offset_ok_for_immed(int64_t offset, uint shift) { + precond(shift < 5); uint mask = (1 << shift) - 1; if (offset < 0 || (offset & mask) != 0) { // Unscaled signed offset, encoded in a signed imm9 field. diff --git a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp index 1cae3a3f3b64d998640c8f3a94d12be42127df8f..6f91b1539a6df7e336f455970a23db93db446711 100644 --- a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp @@ -187,14 +187,13 @@ Address LIR_Assembler::as_Address(LIR_Address* addr, Register tmp) { default: ShouldNotReachHere(); } - } else { - intptr_t addr_offset = intptr_t(addr->disp()); - if (Address::offset_ok_for_immed(addr_offset, addr->scale())) - return Address(base, addr_offset, Address::lsl(addr->scale())); - else { - __ mov(tmp, addr_offset); - return Address(base, tmp, Address::lsl(addr->scale())); - } + } else { + assert(addr->scale() == 0, + "expected for immediate operand, was: %d", addr->scale()); + ptrdiff_t offset = ptrdiff_t(addr->disp()); + // NOTE: Does not handle any 16 byte vector access. + const uint type_size = type2aelembytes(addr->type(), true); + return __ legitimize_address(Address(base, offset), type_size, tmp); } return Address(); } @@ -439,7 +438,11 @@ int LIR_Assembler::emit_unwind_handler() { if (method()->is_synchronized()) { monitor_address(0, FrameMap::r0_opr); stub = new MonitorExitStub(FrameMap::r0_opr, true, 0); - __ unlock_object(r5, r4, r0, *stub->entry()); + if (UseHeavyMonitors) { + __ b(*stub->entry()); + } else { + __ unlock_object(r5, r4, r0, *stub->entry()); + } __ bind(*stub->continuation()); } @@ -986,14 +989,7 @@ void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_Patch __ ldr(dest->as_register(), as_Address(from_addr)); break; case T_ADDRESS: - // FIXME: OMG this is a horrible kludge. Any offset from an - // address that matches klass_offset_in_bytes() will be loaded - // as a word, not a long. - if (UseCompressedClassPointers && addr->disp() == oopDesc::klass_offset_in_bytes()) { - __ ldrw(dest->as_register(), as_Address(from_addr)); - } else { - __ ldr(dest->as_register(), as_Address(from_addr)); - } + __ ldr(dest->as_register(), as_Address(from_addr)); break; case T_INT: __ ldrw(dest->as_register(), as_Address(from_addr)); @@ -1032,10 +1028,6 @@ void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_Patch // Load barrier has not yet been applied, so ZGC can't verify the oop here __ verify_oop(dest->as_register()); } - } else if (type == T_ADDRESS && addr->disp() == oopDesc::klass_offset_in_bytes()) { - if (UseCompressedClassPointers) { - __ decode_klass_not_null(dest->as_register()); - } } } @@ -2574,7 +2566,7 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) { Register obj = op->obj_opr()->as_register(); // may not be an oop Register hdr = op->hdr_opr()->as_register(); Register lock = op->lock_opr()->as_register(); - if (!UseFastLocking) { + if (UseHeavyMonitors) { __ b(*op->stub()->entry()); } else if (op->code() == lir_lock) { assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header"); @@ -2593,6 +2585,22 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) { __ bind(*op->stub()->continuation()); } +void LIR_Assembler::emit_load_klass(LIR_OpLoadKlass* op) { + Register obj = op->obj()->as_pointer_register(); + Register result = op->result_opr()->as_pointer_register(); + + CodeEmitInfo* info = op->info(); + if (info != NULL) { + add_debug_info_for_null_check_here(info); + } + + if (UseCompressedClassPointers) { + __ ldrw(result, Address (obj, oopDesc::klass_offset_in_bytes())); + __ decode_klass_not_null(result); + } else { + __ ldr(result, Address (obj, oopDesc::klass_offset_in_bytes())); + } +} void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) { ciMethod* method = op->profiled_method(); diff --git a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp index f8289a4bda54615535e655158c1639d01f3ca7ca..6d44edec82a7294359245bbbab0ecde1d8f54c13 100644 --- a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp @@ -946,6 +946,48 @@ void C2_MacroAssembler::neon_compare(FloatRegister dst, BasicType bt, FloatRegis } } +// Compress the least significant bit of each byte to the rightmost and clear +// the higher garbage bits. +void C2_MacroAssembler::bytemask_compress(Register dst) { + // Example input, dst = 0x01 00 00 00 01 01 00 01 + // The "??" bytes are garbage. + orr(dst, dst, dst, Assembler::LSR, 7); // dst = 0x?? 02 ?? 00 ?? 03 ?? 01 + orr(dst, dst, dst, Assembler::LSR, 14); // dst = 0x????????08 ??????0D + orr(dst, dst, dst, Assembler::LSR, 28); // dst = 0x????????????????8D + andr(dst, dst, 0xff); // dst = 0x8D +} + +// Pack the lowest-numbered bit of each mask element in src into a long value +// in dst, at most the first 64 lane elements. +// Clobbers: rscratch1 +void C2_MacroAssembler::sve_vmask_tolong(Register dst, PRegister src, BasicType bt, int lane_cnt, + FloatRegister vtmp1, FloatRegister vtmp2, PRegister pgtmp) { + assert(pgtmp->is_governing(), "This register has to be a governing predicate register."); + assert(lane_cnt <= 64 && is_power_of_2(lane_cnt), "Unsupported lane count"); + assert_different_registers(dst, rscratch1); + + Assembler::SIMD_RegVariant size = elemType_to_regVariant(bt); + + // Pack the mask into vector with sequential bytes. + sve_cpy(vtmp1, size, src, 1, false); + if (bt != T_BYTE) { + sve_vector_narrow(vtmp1, B, vtmp1, size, vtmp2); + } + + // Compress the lowest 8 bytes. + fmovd(dst, vtmp1); + bytemask_compress(dst); + if (lane_cnt <= 8) return; + + // Repeat on higher bytes and join the results. + // Compress 8 bytes in each iteration. + for (int idx = 1; idx < (lane_cnt / 8); idx++) { + idx == 1 ? fmovhid(rscratch1, vtmp1) : sve_extract(rscratch1, D, pgtmp, vtmp1, idx); + bytemask_compress(rscratch1); + orr(dst, dst, rscratch1, Assembler::LSL, idx << 3); + } +} + void C2_MacroAssembler::sve_compare(PRegister pd, BasicType bt, PRegister pg, FloatRegister zn, FloatRegister zm, int cond) { assert(pg->is_governing(), "This register has to be a governing predicate register"); @@ -1021,6 +1063,7 @@ void C2_MacroAssembler::sve_vector_narrow(FloatRegister dst, SIMD_RegVariant dst FloatRegister src, SIMD_RegVariant src_size, FloatRegister tmp) { assert(dst_size < src_size && dst_size <= S && src_size <= D, "invalid element size"); + assert_different_registers(src, tmp); sve_dup(tmp, src_size, 0); if (src_size == D) { switch (dst_size) { diff --git a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp index 2c9d4b59ecee6da32b3121f65cc475a4a23759e6..5aa1ac3e8cb5a7e1c059058b492d52468b587d4a 100644 --- a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp @@ -55,6 +55,15 @@ FloatRegister ztmp1, FloatRegister ztmp2, PRegister pgtmp, PRegister ptmp, bool isL); + // Compress the least significant bit of each byte to the rightmost and clear + // the higher garbage bits. + void bytemask_compress(Register dst); + + // Pack the lowest-numbered bit of each mask element in src into a long value + // in dst, at most the first 64 lane elements. + void sve_vmask_tolong(Register dst, PRegister src, BasicType bt, int lane_cnt, + FloatRegister vtmp1, FloatRegister vtmp2, PRegister pgtmp); + // SIMD&FP comparison void neon_compare(FloatRegister dst, BasicType bt, FloatRegister src1, FloatRegister src2, int cond, bool isQ); diff --git a/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp index 77a6dc8b7396ff06d5524435c7a9c3c0b217f5e9..cd689b008e05ee143542d98e48c225600785892b 100644 --- a/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp @@ -222,7 +222,7 @@ void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, const Register card_addr = tmp; - __ lsr(card_addr, store_addr, CardTable::card_shift); + __ lsr(card_addr, store_addr, CardTable::card_shift()); // get the address of the card __ load_byte_map_base(tmp2); @@ -444,7 +444,7 @@ void G1BarrierSetAssembler::generate_c1_post_barrier_runtime_stub(StubAssembler* assert_different_registers(card_offset, byte_map_base, rscratch1); __ load_parameter(0, card_offset); - __ lsr(card_offset, card_offset, CardTable::card_shift); + __ lsr(card_offset, card_offset, CardTable::card_shift()); __ load_byte_map_base(byte_map_base); __ ldrb(rscratch1, Address(byte_map_base, card_offset)); __ cmpw(rscratch1, (int)G1CardTable::g1_young_card_val()); diff --git a/src/hotspot/cpu/aarch64/gc/shared/cardTableBarrierSetAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/shared/cardTableBarrierSetAssembler_aarch64.cpp index fb677828e20e640df27cc874e6183f7a59036eed..f94f2b9c902a018c583f0fe79e68ba988d3ec448 100644 --- a/src/hotspot/cpu/aarch64/gc/shared/cardTableBarrierSetAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/shared/cardTableBarrierSetAssembler_aarch64.cpp @@ -38,7 +38,7 @@ void CardTableBarrierSetAssembler::store_check(MacroAssembler* masm, Register ob BarrierSet* bs = BarrierSet::barrier_set(); assert(bs->kind() == BarrierSet::CardTableBarrierSet, "Wrong barrier set kind"); - __ lsr(obj, obj, CardTable::card_shift); + __ lsr(obj, obj, CardTable::card_shift()); assert(CardTable::dirty_card_val() == 0, "must be"); @@ -64,8 +64,8 @@ void CardTableBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembl __ lea(end, Address(start, count, Address::lsl(LogBytesPerHeapOop))); // end = start + count << LogBytesPerHeapOop __ sub(end, end, BytesPerHeapOop); // last element address to make inclusive - __ lsr(start, start, CardTable::card_shift); - __ lsr(end, end, CardTable::card_shift); + __ lsr(start, start, CardTable::card_shift()); + __ lsr(end, end, CardTable::card_shift()); __ sub(count, end, start); // number of bytes to copy __ load_byte_map_base(scratch); diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index 07e3fdad17b16ac2c7b0614358884651e92a2386..bcb5eb92a0bdbe679704095bf33a2e25339d1651 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -3367,7 +3367,7 @@ void MacroAssembler::kernel_crc32(Register crc, Register buf, Register len, ld1r(v5, T2D, post(tmp, 8)); ld1r(v6, T2D, post(tmp, 8)); ld1r(v7, T2D, post(tmp, 8)); - mov(v16, T4S, 0, crc); + mov(v16, S, 0, crc); eor(v0, T16B, v0, v16); sub(len, len, 64); @@ -3471,16 +3471,16 @@ void MacroAssembler::kernel_crc32(Register crc, Register buf, Register len, br(Assembler::GE, L_fold); mov(crc, 0); - mov(tmp, v0, T1D, 0); + mov(tmp, v0, D, 0); update_word_crc32(crc, tmp, tmp2, table0, table1, table2, table3, false); update_word_crc32(crc, tmp, tmp2, table0, table1, table2, table3, true); - mov(tmp, v0, T1D, 1); + mov(tmp, v0, D, 1); update_word_crc32(crc, tmp, tmp2, table0, table1, table2, table3, false); update_word_crc32(crc, tmp, tmp2, table0, table1, table2, table3, true); - mov(tmp, v1, T1D, 0); + mov(tmp, v1, D, 0); update_word_crc32(crc, tmp, tmp2, table0, table1, table2, table3, false); update_word_crc32(crc, tmp, tmp2, table0, table1, table2, table3, true); - mov(tmp, v1, T1D, 1); + mov(tmp, v1, D, 1); update_word_crc32(crc, tmp, tmp2, table0, table1, table2, table3, false); update_word_crc32(crc, tmp, tmp2, table0, table1, table2, table3, true); diff --git a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp index 5c80566aeadd7d3425a82cde23b7c51d558bfc10..254cde16e0922a4b3ebebe43b6f52ce51ee2ff67 100644 --- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp @@ -1642,39 +1642,42 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // Load the oop from the handle __ ldr(obj_reg, Address(oop_handle_reg, 0)); - // Load (object->mark() | 1) into swap_reg %r0 - __ ldr(rscratch1, Address(obj_reg, oopDesc::mark_offset_in_bytes())); - __ orr(swap_reg, rscratch1, 1); + if (!UseHeavyMonitors) { + // Load (object->mark() | 1) into swap_reg %r0 + __ ldr(rscratch1, Address(obj_reg, oopDesc::mark_offset_in_bytes())); + __ orr(swap_reg, rscratch1, 1); - // Save (object->mark() | 1) into BasicLock's displaced header - __ str(swap_reg, Address(lock_reg, mark_word_offset)); + // Save (object->mark() | 1) into BasicLock's displaced header + __ str(swap_reg, Address(lock_reg, mark_word_offset)); - // src -> dest iff dest == r0 else r0 <- dest - { Label here; - __ cmpxchg_obj_header(r0, lock_reg, obj_reg, rscratch1, lock_done, /*fallthrough*/NULL); - } + // src -> dest iff dest == r0 else r0 <- dest + { Label here; + __ cmpxchg_obj_header(r0, lock_reg, obj_reg, rscratch1, lock_done, /*fallthrough*/NULL); + } - // Hmm should this move to the slow path code area??? + // Hmm should this move to the slow path code area??? - // Test if the oopMark is an obvious stack pointer, i.e., - // 1) (mark & 3) == 0, and - // 2) sp <= mark < mark + os::pagesize() - // These 3 tests can be done by evaluating the following - // expression: ((mark - sp) & (3 - os::vm_page_size())), - // assuming both stack pointer and pagesize have their - // least significant 2 bits clear. - // NOTE: the oopMark is in swap_reg %r0 as the result of cmpxchg + // Test if the oopMark is an obvious stack pointer, i.e., + // 1) (mark & 3) == 0, and + // 2) sp <= mark < mark + os::pagesize() + // These 3 tests can be done by evaluating the following + // expression: ((mark - sp) & (3 - os::vm_page_size())), + // assuming both stack pointer and pagesize have their + // least significant 2 bits clear. + // NOTE: the oopMark is in swap_reg %r0 as the result of cmpxchg - __ sub(swap_reg, sp, swap_reg); - __ neg(swap_reg, swap_reg); - __ ands(swap_reg, swap_reg, 3 - os::vm_page_size()); + __ sub(swap_reg, sp, swap_reg); + __ neg(swap_reg, swap_reg); + __ ands(swap_reg, swap_reg, 3 - os::vm_page_size()); - // Save the test result, for recursive case, the result is zero - __ str(swap_reg, Address(lock_reg, mark_word_offset)); - __ br(Assembler::NE, slow_path_lock); + // Save the test result, for recursive case, the result is zero + __ str(swap_reg, Address(lock_reg, mark_word_offset)); + __ br(Assembler::NE, slow_path_lock); + } else { + __ b(slow_path_lock); + } // Slow path will re-enter here - __ bind(lock_done); } @@ -1775,26 +1778,30 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, __ ldr(obj_reg, Address(oop_handle_reg, 0)); Label done; - // Simple recursive lock? - __ ldr(rscratch1, Address(sp, lock_slot_offset * VMRegImpl::stack_slot_size)); - __ cbz(rscratch1, done); + if (!UseHeavyMonitors) { + // Simple recursive lock? + __ ldr(rscratch1, Address(sp, lock_slot_offset * VMRegImpl::stack_slot_size)); + __ cbz(rscratch1, done); - // Must save r0 if if it is live now because cmpxchg must use it - if (ret_type != T_FLOAT && ret_type != T_DOUBLE && ret_type != T_VOID) { - save_native_result(masm, ret_type, stack_slots); - } + // Must save r0 if if it is live now because cmpxchg must use it + if (ret_type != T_FLOAT && ret_type != T_DOUBLE && ret_type != T_VOID) { + save_native_result(masm, ret_type, stack_slots); + } - // get address of the stack lock - __ lea(r0, Address(sp, lock_slot_offset * VMRegImpl::stack_slot_size)); - // get old displaced header - __ ldr(old_hdr, Address(r0, 0)); + // get address of the stack lock + __ lea(r0, Address(sp, lock_slot_offset * VMRegImpl::stack_slot_size)); + // get old displaced header + __ ldr(old_hdr, Address(r0, 0)); - // Atomic swap old header if oop still contains the stack lock - Label succeed; - __ cmpxchg_obj_header(r0, old_hdr, obj_reg, rscratch1, succeed, &slow_path_unlock); - __ bind(succeed); + // Atomic swap old header if oop still contains the stack lock + Label succeed; + __ cmpxchg_obj_header(r0, old_hdr, obj_reg, rscratch1, succeed, &slow_path_unlock); + __ bind(succeed); + } else { + __ b(slow_path_unlock); + } // slow path re-enters here __ bind(unlock_done); diff --git a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp index b039208654294196b9202b49a43a81103c54db32..e946f3be9703d484da18c0eb0a2ef0b6103f07e8 100644 --- a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp @@ -3210,6 +3210,194 @@ class StubGenerator: public StubCodeGenerator { return start; } + // Arguments: + // + // Inputs: + // c_rarg0 - byte[] source+offset + // c_rarg1 - int[] SHA.state + // c_rarg2 - int offset + // c_rarg3 - int limit + // + address generate_md5_implCompress(bool multi_block, const char *name) { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", name); + address start = __ pc(); + + Register buf = c_rarg0; + Register state = c_rarg1; + Register ofs = c_rarg2; + Register limit = c_rarg3; + Register a = r4; + Register b = r5; + Register c = r6; + Register d = r7; + Register rscratch3 = r10; + Register rscratch4 = r11; + + Label keys; + Label md5_loop; + + __ BIND(md5_loop); + + // Save hash values for addition after rounds + __ ldrw(a, Address(state, 0)); + __ ldrw(b, Address(state, 4)); + __ ldrw(c, Address(state, 8)); + __ ldrw(d, Address(state, 12)); + +#define FF(r1, r2, r3, r4, k, s, t) \ + __ eorw(rscratch3, r3, r4); \ + __ movw(rscratch2, t); \ + __ andw(rscratch3, rscratch3, r2); \ + __ addw(rscratch4, r1, rscratch2); \ + __ ldrw(rscratch1, Address(buf, k*4)); \ + __ eorw(rscratch3, rscratch3, r4); \ + __ addw(rscratch3, rscratch3, rscratch1); \ + __ addw(rscratch3, rscratch3, rscratch4); \ + __ rorw(rscratch2, rscratch3, 32 - s); \ + __ addw(r1, rscratch2, r2); + +#define GG(r1, r2, r3, r4, k, s, t) \ + __ eorw(rscratch2, r2, r3); \ + __ ldrw(rscratch1, Address(buf, k*4)); \ + __ andw(rscratch3, rscratch2, r4); \ + __ movw(rscratch2, t); \ + __ eorw(rscratch3, rscratch3, r3); \ + __ addw(rscratch4, r1, rscratch2); \ + __ addw(rscratch3, rscratch3, rscratch1); \ + __ addw(rscratch3, rscratch3, rscratch4); \ + __ rorw(rscratch2, rscratch3, 32 - s); \ + __ addw(r1, rscratch2, r2); + +#define HH(r1, r2, r3, r4, k, s, t) \ + __ eorw(rscratch3, r3, r4); \ + __ movw(rscratch2, t); \ + __ addw(rscratch4, r1, rscratch2); \ + __ ldrw(rscratch1, Address(buf, k*4)); \ + __ eorw(rscratch3, rscratch3, r2); \ + __ addw(rscratch3, rscratch3, rscratch1); \ + __ addw(rscratch3, rscratch3, rscratch4); \ + __ rorw(rscratch2, rscratch3, 32 - s); \ + __ addw(r1, rscratch2, r2); + +#define II(r1, r2, r3, r4, k, s, t) \ + __ movw(rscratch3, t); \ + __ ornw(rscratch2, r2, r4); \ + __ addw(rscratch4, r1, rscratch3); \ + __ ldrw(rscratch1, Address(buf, k*4)); \ + __ eorw(rscratch3, rscratch2, r3); \ + __ addw(rscratch3, rscratch3, rscratch1); \ + __ addw(rscratch3, rscratch3, rscratch4); \ + __ rorw(rscratch2, rscratch3, 32 - s); \ + __ addw(r1, rscratch2, r2); + + // Round 1 + FF(a, b, c, d, 0, 7, 0xd76aa478) + FF(d, a, b, c, 1, 12, 0xe8c7b756) + FF(c, d, a, b, 2, 17, 0x242070db) + FF(b, c, d, a, 3, 22, 0xc1bdceee) + FF(a, b, c, d, 4, 7, 0xf57c0faf) + FF(d, a, b, c, 5, 12, 0x4787c62a) + FF(c, d, a, b, 6, 17, 0xa8304613) + FF(b, c, d, a, 7, 22, 0xfd469501) + FF(a, b, c, d, 8, 7, 0x698098d8) + FF(d, a, b, c, 9, 12, 0x8b44f7af) + FF(c, d, a, b, 10, 17, 0xffff5bb1) + FF(b, c, d, a, 11, 22, 0x895cd7be) + FF(a, b, c, d, 12, 7, 0x6b901122) + FF(d, a, b, c, 13, 12, 0xfd987193) + FF(c, d, a, b, 14, 17, 0xa679438e) + FF(b, c, d, a, 15, 22, 0x49b40821) + + // Round 2 + GG(a, b, c, d, 1, 5, 0xf61e2562) + GG(d, a, b, c, 6, 9, 0xc040b340) + GG(c, d, a, b, 11, 14, 0x265e5a51) + GG(b, c, d, a, 0, 20, 0xe9b6c7aa) + GG(a, b, c, d, 5, 5, 0xd62f105d) + GG(d, a, b, c, 10, 9, 0x02441453) + GG(c, d, a, b, 15, 14, 0xd8a1e681) + GG(b, c, d, a, 4, 20, 0xe7d3fbc8) + GG(a, b, c, d, 9, 5, 0x21e1cde6) + GG(d, a, b, c, 14, 9, 0xc33707d6) + GG(c, d, a, b, 3, 14, 0xf4d50d87) + GG(b, c, d, a, 8, 20, 0x455a14ed) + GG(a, b, c, d, 13, 5, 0xa9e3e905) + GG(d, a, b, c, 2, 9, 0xfcefa3f8) + GG(c, d, a, b, 7, 14, 0x676f02d9) + GG(b, c, d, a, 12, 20, 0x8d2a4c8a) + + // Round 3 + HH(a, b, c, d, 5, 4, 0xfffa3942) + HH(d, a, b, c, 8, 11, 0x8771f681) + HH(c, d, a, b, 11, 16, 0x6d9d6122) + HH(b, c, d, a, 14, 23, 0xfde5380c) + HH(a, b, c, d, 1, 4, 0xa4beea44) + HH(d, a, b, c, 4, 11, 0x4bdecfa9) + HH(c, d, a, b, 7, 16, 0xf6bb4b60) + HH(b, c, d, a, 10, 23, 0xbebfbc70) + HH(a, b, c, d, 13, 4, 0x289b7ec6) + HH(d, a, b, c, 0, 11, 0xeaa127fa) + HH(c, d, a, b, 3, 16, 0xd4ef3085) + HH(b, c, d, a, 6, 23, 0x04881d05) + HH(a, b, c, d, 9, 4, 0xd9d4d039) + HH(d, a, b, c, 12, 11, 0xe6db99e5) + HH(c, d, a, b, 15, 16, 0x1fa27cf8) + HH(b, c, d, a, 2, 23, 0xc4ac5665) + + // Round 4 + II(a, b, c, d, 0, 6, 0xf4292244) + II(d, a, b, c, 7, 10, 0x432aff97) + II(c, d, a, b, 14, 15, 0xab9423a7) + II(b, c, d, a, 5, 21, 0xfc93a039) + II(a, b, c, d, 12, 6, 0x655b59c3) + II(d, a, b, c, 3, 10, 0x8f0ccc92) + II(c, d, a, b, 10, 15, 0xffeff47d) + II(b, c, d, a, 1, 21, 0x85845dd1) + II(a, b, c, d, 8, 6, 0x6fa87e4f) + II(d, a, b, c, 15, 10, 0xfe2ce6e0) + II(c, d, a, b, 6, 15, 0xa3014314) + II(b, c, d, a, 13, 21, 0x4e0811a1) + II(a, b, c, d, 4, 6, 0xf7537e82) + II(d, a, b, c, 11, 10, 0xbd3af235) + II(c, d, a, b, 2, 15, 0x2ad7d2bb) + II(b, c, d, a, 9, 21, 0xeb86d391) + +#undef FF +#undef GG +#undef HH +#undef II + + // write hash values back in the correct order + __ ldrw(rscratch1, Address(state, 0)); + __ addw(rscratch1, rscratch1, a); + __ strw(rscratch1, Address(state, 0)); + + __ ldrw(rscratch2, Address(state, 4)); + __ addw(rscratch2, rscratch2, b); + __ strw(rscratch2, Address(state, 4)); + + __ ldrw(rscratch3, Address(state, 8)); + __ addw(rscratch3, rscratch3, c); + __ strw(rscratch3, Address(state, 8)); + + __ ldrw(rscratch4, Address(state, 12)); + __ addw(rscratch4, rscratch4, d); + __ strw(rscratch4, Address(state, 12)); + + if (multi_block) { + __ add(buf, buf, 64); + __ add(ofs, ofs, 64); + __ cmp(ofs, limit); + __ br(Assembler::LE, md5_loop); + __ mov(c_rarg0, ofs); // return ofs + } + + __ ret(lr); + + return start; + } + // Arguments: // // Inputs: @@ -6209,6 +6397,18 @@ class StubGenerator: public StubCodeGenerator { return start; } + // Support for spin waits. + address generate_spin_wait() { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", "spin_wait"); + address start = __ pc(); + + __ spin_wait(); + __ ret(lr); + + return start; + } + #ifdef LINUX // ARMv8.1 LSE versions of the atomic stubs used by Atomic::PlatformXX. @@ -7501,6 +7701,10 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_galoisCounterMode_AESCrypt = generate_galoisCounterMode_AESCrypt(); } + if (UseMD5Intrinsics) { + StubRoutines::_md5_implCompress = generate_md5_implCompress(false, "md5_implCompress"); + StubRoutines::_md5_implCompressMB = generate_md5_implCompress(true, "md5_implCompressMB"); + } if (UseSHA1Intrinsics) { StubRoutines::_sha1_implCompress = generate_sha1_implCompress(false, "sha1_implCompress"); StubRoutines::_sha1_implCompressMB = generate_sha1_implCompress(true, "sha1_implCompressMB"); @@ -7523,6 +7727,8 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_updateBytesAdler32 = generate_updateBytesAdler32(); } + StubRoutines::aarch64::_spin_wait = generate_spin_wait(); + #ifdef LINUX generate_atomic_entry_points(); diff --git a/src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp b/src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp index 1cbc3ed21d16f29037d4a2e0ec391f06a148e5e3..9e16a1f9f8812268779be2caad8e459c123816ae 100644 --- a/src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp @@ -57,6 +57,10 @@ address StubRoutines::aarch64::_string_indexof_linear_uu = NULL; address StubRoutines::aarch64::_string_indexof_linear_ul = NULL; address StubRoutines::aarch64::_large_byte_array_inflate = NULL; address StubRoutines::aarch64::_method_entry_barrier = NULL; + +static void empty_spin_wait() { } +address StubRoutines::aarch64::_spin_wait = CAST_FROM_FN_PTR(address, empty_spin_wait); + bool StubRoutines::aarch64::_completed = false; /** diff --git a/src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp b/src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp index e3ebc4484470120a4c445054414a638b326e9e92..295264b7aaf22067503fcbc7fb3db2cab7222870 100644 --- a/src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp @@ -36,7 +36,7 @@ static bool returns_to_call_stub(address return_pc) { enum platform_dependent_constants { code_size1 = 19000, // simply increase if too small (assembler will crash if too small) - code_size2 = 38000 // simply increase if too small (assembler will crash if too small) + code_size2 = 45000 // simply increase if too small (assembler will crash if too small) }; class aarch64 { @@ -72,6 +72,8 @@ class aarch64 { static address _method_entry_barrier; + static address _spin_wait; + static bool _completed; public: @@ -177,6 +179,10 @@ class aarch64 { return _method_entry_barrier; } + static address spin_wait() { + return _spin_wait; + } + static bool complete() { return _completed; } diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index b4e75f88d291774a95942310253d304b4b23a187..833a6ec9f6da32bd48cda2bd201faeeea3dd4e5a 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -301,9 +301,8 @@ void VM_Version::initialize() { FLAG_SET_DEFAULT(UseFMA, true); } - if (UseMD5Intrinsics) { - warning("MD5 intrinsics are not available on this CPU"); - FLAG_SET_DEFAULT(UseMD5Intrinsics, false); + if (FLAG_IS_DEFAULT(UseMD5Intrinsics)) { + UseMD5Intrinsics = true; } if (_features & (CPU_SHA1 | CPU_SHA2 | CPU_SHA3 | CPU_SHA512)) { @@ -470,6 +469,14 @@ void VM_Version::initialize() { } } + int inline_size = (UseSVE > 0 && MaxVectorSize >= 16) ? MaxVectorSize : 0; + if (FLAG_IS_DEFAULT(ArrayOperationPartialInlineSize)) { + FLAG_SET_DEFAULT(ArrayOperationPartialInlineSize, inline_size); + } else if (ArrayOperationPartialInlineSize != 0 && ArrayOperationPartialInlineSize != inline_size) { + warning("Setting ArrayOperationPartialInlineSize to %d", inline_size); + ArrayOperationPartialInlineSize = inline_size; + } + if (FLAG_IS_DEFAULT(OptoScheduling)) { OptoScheduling = true; } @@ -481,3 +488,22 @@ void VM_Version::initialize() { _spin_wait = get_spin_wait_desc(); } + +void VM_Version::initialize_cpu_information(void) { + // do nothing if cpu info has been initialized + if (_initialized) { + return; + } + + _no_of_cores = os::processor_count(); + _no_of_threads = _no_of_cores; + _no_of_sockets = _no_of_cores; + snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE - 1, "AArch64"); + + int desc_len = snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "AArch64 "); + get_compatible_board(_cpu_desc + desc_len, CPU_DETAILED_DESC_BUF_SIZE - desc_len); + desc_len = (int)strlen(_cpu_desc); + snprintf(_cpu_desc + desc_len, CPU_DETAILED_DESC_BUF_SIZE - desc_len, " %s", _features_string); + + _initialized = true; +} diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp index 61f422bd2d38b3348f0294c1a741c8ba059b95a5..b6aec7ed01f985c97b009fb2dde99b73df3b7af8 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp @@ -153,6 +153,9 @@ public: // Is the CPU running emulated (for example macOS Rosetta running x86_64 code on M1 ARM (aarch64) static bool is_cpu_emulated(); #endif + + static void initialize_cpu_information(void); + }; #endif // CPU_AARCH64_VM_VERSION_AARCH64_HPP diff --git a/src/hotspot/cpu/aarch64/vm_version_ext_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_ext_aarch64.cpp deleted file mode 100644 index a95171173e9318615c439ea1b31c7bd2648e9677..0000000000000000000000000000000000000000 --- a/src/hotspot/cpu/aarch64/vm_version_ext_aarch64.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "precompiled.hpp" -#include "memory/allocation.hpp" -#include "memory/allocation.inline.hpp" -#include "runtime/os.inline.hpp" -#include "vm_version_ext_aarch64.hpp" - -// VM_Version_Ext statics -int VM_Version_Ext::_no_of_threads = 0; -int VM_Version_Ext::_no_of_cores = 0; -int VM_Version_Ext::_no_of_sockets = 0; -bool VM_Version_Ext::_initialized = false; -char VM_Version_Ext::_cpu_name[CPU_TYPE_DESC_BUF_SIZE] = {0}; -char VM_Version_Ext::_cpu_desc[CPU_DETAILED_DESC_BUF_SIZE] = {0}; - -void VM_Version_Ext::initialize_cpu_information(void) { - // do nothing if cpu info has been initialized - if (_initialized) { - return; - } - - int core_id = -1; - int chip_id = -1; - int len = 0; - char* src_string = NULL; - - _no_of_cores = os::processor_count(); - _no_of_threads = _no_of_cores; - _no_of_sockets = _no_of_cores; - snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE - 1, "AArch64"); - - int desc_len = snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "AArch64 "); - VM_Version::get_compatible_board(_cpu_desc + desc_len, CPU_DETAILED_DESC_BUF_SIZE - desc_len); - desc_len = (int)strlen(_cpu_desc); - snprintf(_cpu_desc + desc_len, CPU_DETAILED_DESC_BUF_SIZE - desc_len, " %s", _features_string); - - _initialized = true; -} - -int VM_Version_Ext::number_of_threads(void) { - initialize_cpu_information(); - return _no_of_threads; -} - -int VM_Version_Ext::number_of_cores(void) { - initialize_cpu_information(); - return _no_of_cores; -} - -int VM_Version_Ext::number_of_sockets(void) { - initialize_cpu_information(); - return _no_of_sockets; -} - -const char* VM_Version_Ext::cpu_name(void) { - initialize_cpu_information(); - char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, CPU_TYPE_DESC_BUF_SIZE, mtTracing); - if (NULL == tmp) { - return NULL; - } - strncpy(tmp, _cpu_name, CPU_TYPE_DESC_BUF_SIZE); - return tmp; -} - -const char* VM_Version_Ext::cpu_description(void) { - initialize_cpu_information(); - char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, CPU_DETAILED_DESC_BUF_SIZE, mtTracing); - if (NULL == tmp) { - return NULL; - } - strncpy(tmp, _cpu_desc, CPU_DETAILED_DESC_BUF_SIZE); - return tmp; -} diff --git a/src/hotspot/cpu/aarch64/vm_version_ext_aarch64.hpp b/src/hotspot/cpu/aarch64/vm_version_ext_aarch64.hpp deleted file mode 100644 index 0eced8e65575af258c3783b71bd1479d68d9cb99..0000000000000000000000000000000000000000 --- a/src/hotspot/cpu/aarch64/vm_version_ext_aarch64.hpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef CPU_AARCH64_VM_VERSION_EXT_AARCH64_HPP -#define CPU_AARCH64_VM_VERSION_EXT_AARCH64_HPP - -#include "runtime/vm_version.hpp" -#include "utilities/macros.hpp" - -class VM_Version_Ext : public VM_Version { - private: - static const size_t CPU_TYPE_DESC_BUF_SIZE = 256; - static const size_t CPU_DETAILED_DESC_BUF_SIZE = 4096; - - static int _no_of_threads; - static int _no_of_cores; - static int _no_of_sockets; - static bool _initialized; - static char _cpu_name[CPU_TYPE_DESC_BUF_SIZE]; - static char _cpu_desc[CPU_DETAILED_DESC_BUF_SIZE]; - - public: - static int number_of_threads(void); - static int number_of_cores(void); - static int number_of_sockets(void); - - static const char* cpu_name(void); - static const char* cpu_description(void); - static void initialize_cpu_information(void); - -}; - -#endif // CPU_AARCH64_VM_VERSION_EXT_AARCH64_HPP diff --git a/src/hotspot/cpu/arm/arm.ad b/src/hotspot/cpu/arm/arm.ad index 9e76f430054ac8a1ccbe3a6324b77812d638d52c..42d6d4151b28669400511d4fb21b6537557792cb 100644 --- a/src/hotspot/cpu/arm/arm.ad +++ b/src/hotspot/cpu/arm/arm.ad @@ -991,7 +991,7 @@ const RegMask* Matcher::predicate_reg_mask(void) { return NULL; } -const TypeVect* Matcher::predicate_reg_type(const Type* elemTy, int length) { +const TypeVectMask* Matcher::predicate_reg_type(const Type* elemTy, int length) { return NULL; } @@ -8385,7 +8385,7 @@ instruct cmpL3_reg_reg(iRegI dst, iRegL src1, iRegL src2, flagsReg ccr ) %{ // Conditional move instruct cmovLL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegL dst, iRegL src) %{ match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); - predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); ins_cost(150); size(8); @@ -8398,9 +8398,9 @@ instruct cmovLL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegL dst, iRegL src) % ins_pipe(ialu_reg); %} -instruct cmovLL_reg_LTGE_U(cmpOpL cmp, flagsRegUL_LTGE xcc, iRegL dst, iRegL src) %{ +instruct cmovLL_reg_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegL dst, iRegL src) %{ match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); - predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); ins_cost(150); size(8); @@ -8415,7 +8415,7 @@ instruct cmovLL_reg_LTGE_U(cmpOpL cmp, flagsRegUL_LTGE xcc, iRegL dst, iRegL src instruct cmovLL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegL dst, iRegL src) %{ match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); - predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); ins_cost(150); size(8); @@ -8430,7 +8430,7 @@ instruct cmovLL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegL dst, iRegL src) % instruct cmovLL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegL dst, iRegL src) %{ match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); - predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt); ins_cost(150); size(8); @@ -8443,9 +8443,9 @@ instruct cmovLL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegL dst, iReg ins_pipe(ialu_reg); %} -instruct cmovLL_reg_LEGT_U(cmpOpL_commute cmp, flagsRegUL_LEGT xcc, iRegL dst, iRegL src) %{ +instruct cmovLL_reg_LEGT_U(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, iRegL dst, iRegL src) %{ match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); - predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt); ins_cost(150); size(8); @@ -8460,7 +8460,7 @@ instruct cmovLL_reg_LEGT_U(cmpOpL_commute cmp, flagsRegUL_LEGT xcc, iRegL dst, i instruct cmovLL_imm_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegL dst, immL0 src) %{ match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); - predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); ins_cost(140); size(8); format %{ "MOV$cmp $dst.lo,0\t! long\n\t" @@ -8472,9 +8472,9 @@ instruct cmovLL_imm_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegL dst, immL0 src) % ins_pipe(ialu_imm); %} -instruct cmovLL_imm_LTGE_U(cmpOpL cmp, flagsRegUL_LTGE xcc, iRegL dst, immL0 src) %{ +instruct cmovLL_imm_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegL dst, immL0 src) %{ match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); - predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); ins_cost(140); size(8); format %{ "MOV$cmp $dst.lo,0\t! long\n\t" @@ -8488,7 +8488,7 @@ instruct cmovLL_imm_LTGE_U(cmpOpL cmp, flagsRegUL_LTGE xcc, iRegL dst, immL0 src instruct cmovLL_imm_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegL dst, immL0 src) %{ match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); - predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); ins_cost(140); size(8); format %{ "MOV$cmp $dst.lo,0\t! long\n\t" @@ -8502,7 +8502,7 @@ instruct cmovLL_imm_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegL dst, immL0 src) % instruct cmovLL_imm_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegL dst, immL0 src) %{ match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); - predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt); ins_cost(140); size(8); format %{ "MOV$cmp $dst.lo,0\t! long\n\t" @@ -8516,7 +8516,20 @@ instruct cmovLL_imm_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegL dst, immL instruct cmovIL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegI dst, iRegI src) %{ match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); - predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); + + ins_cost(150); + size(4); + format %{ "MOV$cmp $dst,$src" %} + ins_encode %{ + __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); + %} + ins_pipe(ialu_reg); +%} + +instruct cmovIL_reg_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegI dst, iRegI src) %{ + match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); ins_cost(150); size(4); @@ -8529,7 +8542,7 @@ instruct cmovIL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegI dst, iRegI src) % instruct cmovIL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegI dst, iRegI src) %{ match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); - predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); ins_cost(150); size(4); @@ -8540,9 +8553,22 @@ instruct cmovIL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegI dst, iRegI src) % ins_pipe(ialu_reg); %} +instruct cmovIL_reg_EQNE_U(cmpOpUL cmp, flagsRegUL_EQNE xcc, iRegI dst, iRegI src) %{ + match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); + + ins_cost(150); + size(4); + format %{ "MOV$cmp $dst,$src" %} + ins_encode %{ + __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); + %} + ins_pipe(ialu_reg); +%} + instruct cmovIL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegI dst, iRegI src) %{ match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); - predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt); ins_cost(150); size(4); @@ -8553,11 +8579,64 @@ instruct cmovIL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegI dst, iReg ins_pipe(ialu_reg); %} -instruct cmovIL_imm_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegI dst, immI16 src) %{ +instruct cmovIL_reg_LEGT_U(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, iRegI dst, iRegI src) %{ + match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt); + + ins_cost(150); + size(4); + format %{ "MOV$cmp $dst,$src" %} + ins_encode %{ + __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); + %} + ins_pipe(ialu_reg); +%} + +instruct cmovIL_imm16_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegI dst, immI16 src) %{ + match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); + + ins_cost(140); + size(4); + format %{ "MOVW$cmp $dst,$src" %} + ins_encode %{ + __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); + %} + ins_pipe(ialu_imm); +%} + +instruct cmovIL_imm16_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegI dst, immI16 src) %{ + match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); + + ins_cost(140); + size(4); + format %{ "MOVW$cmp $dst,$src" %} + ins_encode %{ + __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); + %} + ins_pipe(ialu_imm); +%} + +instruct cmovIL_imm16_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegI dst, immI16 src) %{ + match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); + + ins_cost(140); + size(4); + format %{ "MOVW$cmp $dst,$src" %} + ins_encode %{ + __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); + %} + ins_pipe(ialu_imm); +%} + +instruct cmovIL_imm16_EQNE_U(cmpOpUL cmp, flagsRegUL_EQNE xcc, iRegI dst, immI16 src) %{ match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); - predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); ins_cost(140); + size(4); format %{ "MOVW$cmp $dst,$src" %} ins_encode %{ __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); @@ -8565,11 +8644,12 @@ instruct cmovIL_imm_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegI dst, immI16 src) ins_pipe(ialu_imm); %} -instruct cmovIL_imm_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegI dst, immI16 src) %{ +instruct cmovIL_imm16_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegI dst, immI16 src) %{ match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); - predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt); ins_cost(140); + size(4); format %{ "MOVW$cmp $dst,$src" %} ins_encode %{ __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); @@ -8577,11 +8657,12 @@ instruct cmovIL_imm_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegI dst, immI16 src) ins_pipe(ialu_imm); %} -instruct cmovIL_imm_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegI dst, immI16 src) %{ +instruct cmovIL_imm16_LEGT_U(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, iRegI dst, immI16 src) %{ match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); - predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt); ins_cost(140); + size(4); format %{ "MOVW$cmp $dst,$src" %} ins_encode %{ __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); @@ -8589,9 +8670,100 @@ instruct cmovIL_imm_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegI dst, immI ins_pipe(ialu_imm); %} +instruct cmovIL_immMov_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegI dst, immIMov src) %{ + match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); + + ins_cost(140); + size(4); + format %{ "MOV$cmp $dst,$src" %} + ins_encode %{ + __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); + %} + ins_pipe(ialu_imm); +%} + +instruct cmovIL_immMov_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegI dst, immIMov src) %{ + match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); + + ins_cost(140); + size(4); + format %{ "MOV$cmp $dst,$src" %} + ins_encode %{ + __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); + %} + ins_pipe(ialu_imm); +%} + +instruct cmovIL_immMov_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegI dst, immIMov src) %{ + match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); + + ins_cost(140); + size(4); + format %{ "MOV$cmp $dst,$src" %} + ins_encode %{ + __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); + %} + ins_pipe(ialu_imm); +%} + +instruct cmovIL_immMov_EQNE_U(cmpOpUL cmp, flagsRegUL_EQNE xcc, iRegI dst, immIMov src) %{ + match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); + + ins_cost(140); + size(4); + format %{ "MOV$cmp $dst,$src" %} + ins_encode %{ + __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); + %} + ins_pipe(ialu_imm); +%} + +instruct cmovIL_immMov_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegI dst, immIMov src) %{ + match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt); + + ins_cost(140); + size(4); + format %{ "MOV$cmp $dst,$src" %} + ins_encode %{ + __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); + %} + ins_pipe(ialu_imm); +%} + +instruct cmovIL_immMov_LEGT_U(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, iRegI dst, immIMov src) %{ + match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt); + + ins_cost(140); + size(4); + format %{ "MOV$cmp $dst,$src" %} + ins_encode %{ + __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); + %} + ins_pipe(ialu_imm); +%} + instruct cmovPL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegP dst, iRegP src) %{ match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); - predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); + + ins_cost(150); + size(4); + format %{ "MOV$cmp $dst,$src" %} + ins_encode %{ + __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); + %} + ins_pipe(ialu_reg); +%} + +instruct cmovPL_reg_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegP dst, iRegP src) %{ + match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); ins_cost(150); size(4); @@ -8604,7 +8776,20 @@ instruct cmovPL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegP dst, iRegP src) % instruct cmovPL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegP dst, iRegP src) %{ match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); - predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); + + ins_cost(150); + size(4); + format %{ "MOV$cmp $dst,$src" %} + ins_encode %{ + __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); + %} + ins_pipe(ialu_reg); +%} + +instruct cmovPL_reg_EQNE_U(cmpOpUL cmp, flagsRegUL_EQNE xcc, iRegP dst, iRegP src) %{ + match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); ins_cost(150); size(4); @@ -8617,7 +8802,20 @@ instruct cmovPL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegP dst, iRegP src) % instruct cmovPL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegP dst, iRegP src) %{ match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); - predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt); + + ins_cost(150); + size(4); + format %{ "MOV$cmp $dst,$src" %} + ins_encode %{ + __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); + %} + ins_pipe(ialu_reg); +%} + +instruct cmovPL_reg_LEGT_U(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, iRegP dst, iRegP src) %{ + match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt); ins_cost(150); size(4); @@ -8630,9 +8828,23 @@ instruct cmovPL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegP dst, iReg instruct cmovPL_imm_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegP dst, immP0 src) %{ match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); - predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); + + ins_cost(140); + size(4); + format %{ "MOVW$cmp $dst,$src" %} + ins_encode %{ + __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); + %} + ins_pipe(ialu_imm); +%} + +instruct cmovPL_imm_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegP dst, immP0 src) %{ + match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); ins_cost(140); + size(4); format %{ "MOVW$cmp $dst,$src" %} ins_encode %{ __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); @@ -8642,9 +8854,23 @@ instruct cmovPL_imm_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegP dst, immP0 src) % instruct cmovPL_imm_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegP dst, immP0 src) %{ match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); - predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); ins_cost(140); + size(4); + format %{ "MOVW$cmp $dst,$src" %} + ins_encode %{ + __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); + %} + ins_pipe(ialu_imm); +%} + +instruct cmovPL_imm_EQNE_U(cmpOpUL cmp, flagsRegUL_EQNE xcc, iRegP dst, immP0 src) %{ + match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); + + ins_cost(140); + size(4); format %{ "MOVW$cmp $dst,$src" %} ins_encode %{ __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); @@ -8654,9 +8880,23 @@ instruct cmovPL_imm_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegP dst, immP0 src) % instruct cmovPL_imm_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegP dst, immP0 src) %{ match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); - predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt); ins_cost(140); + size(4); + format %{ "MOVW$cmp $dst,$src" %} + ins_encode %{ + __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); + %} + ins_pipe(ialu_imm); +%} + +instruct cmovPL_imm_LEGT_U(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, iRegP dst, immP0 src) %{ + match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt); + + ins_cost(140); + size(4); format %{ "MOVW$cmp $dst,$src" %} ins_encode %{ __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); @@ -8666,7 +8906,7 @@ instruct cmovPL_imm_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegP dst, immP instruct cmovFL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, regF dst, regF src) %{ match(Set dst (CMoveF (Binary cmp xcc) (Binary dst src))); - predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); ins_cost(150); size(4); format %{ "FCPYS$cmp $dst,$src" %} @@ -8678,7 +8918,7 @@ instruct cmovFL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, regF dst, regF src) %{ instruct cmovFL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, regF dst, regF src) %{ match(Set dst (CMoveF (Binary cmp xcc) (Binary dst src))); - predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); ins_cost(150); size(4); format %{ "FCPYS$cmp $dst,$src" %} @@ -8690,7 +8930,7 @@ instruct cmovFL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, regF dst, regF src) %{ instruct cmovFL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, regF dst, regF src) %{ match(Set dst (CMoveF (Binary cmp xcc) (Binary dst src))); - predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt); ins_cost(150); size(4); format %{ "FCPYS$cmp $dst,$src" %} @@ -8702,7 +8942,7 @@ instruct cmovFL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, regF dst, regF instruct cmovDL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, regD dst, regD src) %{ match(Set dst (CMoveD (Binary cmp xcc) (Binary dst src))); - predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); ins_cost(150); size(4); @@ -8715,7 +8955,7 @@ instruct cmovDL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, regD dst, regD src) %{ instruct cmovDL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, regD dst, regD src) %{ match(Set dst (CMoveD (Binary cmp xcc) (Binary dst src))); - predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); ins_cost(150); size(4); @@ -8728,7 +8968,7 @@ instruct cmovDL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, regD dst, regD src) %{ instruct cmovDL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, regD dst, regD src) %{ match(Set dst (CMoveD (Binary cmp xcc) (Binary dst src))); - predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); + predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt); ins_cost(150); size(4); diff --git a/src/hotspot/cpu/arm/assembler_arm_32.cpp b/src/hotspot/cpu/arm/assembler_arm_32.cpp index 5dd9d39392a0e7d595e779c65af863d8eec0a3bf..6cb6e19cbd5b88d3ee9430496dcbded16ae06969 100644 --- a/src/hotspot/cpu/arm/assembler_arm_32.cpp +++ b/src/hotspot/cpu/arm/assembler_arm_32.cpp @@ -46,7 +46,7 @@ // Convert the raw encoding form into the form expected by the // constructor for Address. Address Address::make_raw(int base, int index, int scale, int disp, relocInfo::relocType disp_reloc) { - RelocationHolder rspec; + RelocationHolder rspec = RelocationHolder::none; if (disp_reloc != relocInfo::none) { rspec = Relocation::spec_simple(disp_reloc); } diff --git a/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp b/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp index 4d6ce557d0ab056e7946a1fbe4be896b65c5ba21..95fab38a5848a611bbfb0e2139c96e3aba88e9f8 100644 --- a/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp +++ b/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp @@ -720,11 +720,7 @@ void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, break; case T_ADDRESS: - if (UseCompressedClassPointers && addr->disp() == oopDesc::klass_offset_in_bytes()) { - __ ldr_u32(dest->as_pointer_register(), as_Address(addr)); - } else { - __ ldr(dest->as_pointer_register(), as_Address(addr)); - } + __ ldr(dest->as_pointer_register(), as_Address(addr)); break; case T_INT: @@ -2429,7 +2425,7 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) { Register hdr = op->hdr_opr()->as_pointer_register(); Register lock = op->lock_opr()->as_pointer_register(); - if (!UseFastLocking) { + if (UseHeavyMonitors) { __ b(*op->stub()->entry()); } else if (op->code() == lir_lock) { assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header"); @@ -2445,6 +2441,21 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) { __ bind(*op->stub()->continuation()); } +void LIR_Assembler::emit_load_klass(LIR_OpLoadKlass* op) { + Register obj = op->obj()->as_pointer_register(); + Register result = op->result_opr()->as_pointer_register(); + + CodeEmitInfo* info = op->info(); + if (info != NULL) { + add_debug_info_for_null_check_here(info); + } + + if (UseCompressedClassPointers) { // On 32 bit arm?? + __ ldr_u32(result, Address(obj, oopDesc::klass_offset_in_bytes())); + } else { + __ ldr(result, Address(obj, oopDesc::klass_offset_in_bytes())); + } +} void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) { ciMethod* method = op->profiled_method(); diff --git a/src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp b/src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp index 0a5b80b23b7659ac35ad4c2cd2fbed4335379503..69a76f4beb0d32882437d4a6227b66840e0fa227 100644 --- a/src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp +++ b/src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp @@ -377,7 +377,7 @@ void LIRGenerator::CardTableBarrierSet_post_barrier_helper(LIR_Opr addr, LIR_Con // Use unsigned type T_BOOLEAN here rather than (signed) T_BYTE since signed load // byte instruction does not support the addressing mode we need. - LIR_Address* card_addr = new LIR_Address(tmp, addr, (LIR_Address::Scale) -CardTable::card_shift, 0, T_BOOLEAN); + LIR_Address* card_addr = new LIR_Address(tmp, addr, (LIR_Address::Scale) -CardTable::card_shift(), 0, T_BOOLEAN); if (UseCondCardMark) { LIR_Opr cur_value = new_register(T_INT); __ move(card_addr, cur_value); diff --git a/src/hotspot/cpu/arm/gc/g1/g1BarrierSetAssembler_arm.cpp b/src/hotspot/cpu/arm/gc/g1/g1BarrierSetAssembler_arm.cpp index 63bf45b8db5d38e4e84f0028c4dcce73108032f9..765b05e779b9e5e2164b297884ace283f6a12c90 100644 --- a/src/hotspot/cpu/arm/gc/g1/g1BarrierSetAssembler_arm.cpp +++ b/src/hotspot/cpu/arm/gc/g1/g1BarrierSetAssembler_arm.cpp @@ -218,7 +218,7 @@ void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, const Register card_addr = tmp1; __ mov_address(tmp2, (address)ct->byte_map_base()); - __ add(card_addr, tmp2, AsmOperand(store_addr, lsr, CardTable::card_shift)); + __ add(card_addr, tmp2, AsmOperand(store_addr, lsr, CardTable::card_shift())); __ ldrb(tmp2, Address(card_addr)); __ cmp(tmp2, (int)G1CardTable::g1_young_card_val()); @@ -452,7 +452,7 @@ void G1BarrierSetAssembler::generate_c1_post_barrier_runtime_stub(StubAssembler* // explicitly specify that 'cardtable' has a relocInfo::none // type. __ lea(r_card_base_1, cardtable); - __ add(r_card_addr_0, r_card_base_1, AsmOperand(r_obj_0, lsr, CardTable::card_shift)); + __ add(r_card_addr_0, r_card_base_1, AsmOperand(r_obj_0, lsr, CardTable::card_shift())); // first quick check without barrier __ ldrb(r_tmp2, Address(r_card_addr_0)); diff --git a/src/hotspot/cpu/arm/gc/shared/cardTableBarrierSetAssembler_arm.cpp b/src/hotspot/cpu/arm/gc/shared/cardTableBarrierSetAssembler_arm.cpp index 86f43597e220bb1b7f302dc59422cf0320e36de1..11b2ca2ef1d8c4a7dbbac6396c0903d3ac2d131c 100644 --- a/src/hotspot/cpu/arm/gc/shared/cardTableBarrierSetAssembler_arm.cpp +++ b/src/hotspot/cpu/arm/gc/shared/cardTableBarrierSetAssembler_arm.cpp @@ -55,8 +55,8 @@ void CardTableBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembl __ add_ptr_scaled_int32(count, addr, count, LogBytesPerHeapOop); __ sub(count, count, BytesPerHeapOop); // last addr - __ logical_shift_right(addr, addr, CardTable::card_shift); - __ logical_shift_right(count, count, CardTable::card_shift); + __ logical_shift_right(addr, addr, CardTable::card_shift()); + __ logical_shift_right(count, count, CardTable::card_shift()); __ sub(count, count, addr); // nb of cards // warning: Rthread has not been preserved @@ -129,7 +129,7 @@ void CardTableBarrierSetAssembler::store_check_part2(MacroAssembler* masm, Regis "Wrong barrier set kind"); assert(CardTable::dirty_card_val() == 0, "Dirty card value must be 0 due to optimizations."); - Address card_table_addr(card_table_base, obj, lsr, CardTable::card_shift); + Address card_table_addr(card_table_base, obj, lsr, CardTable::card_shift()); if (UseCondCardMark) { Label already_dirty; diff --git a/src/hotspot/cpu/arm/vm_version_arm.hpp b/src/hotspot/cpu/arm/vm_version_arm.hpp index a6e2dc8b442198115b3f4ad62fa36aefa16c4053..bdc3df12eb9f4d0b7fc4166583ccab5639efac70 100644 --- a/src/hotspot/cpu/arm/vm_version_arm.hpp +++ b/src/hotspot/cpu/arm/vm_version_arm.hpp @@ -106,6 +106,7 @@ class VM_Version: public Abstract_VM_Version { friend class VM_Version_StubGenerator; + static void initialize_cpu_information(void); }; #endif // CPU_ARM_VM_VERSION_ARM_HPP diff --git a/src/hotspot/cpu/arm/vm_version_arm_32.cpp b/src/hotspot/cpu/arm/vm_version_arm_32.cpp index a31857d9a47227a228f9bd65e3e0e37fdee59d8a..9e228b3d75191f84870891dde5021cf0a0618ec7 100644 --- a/src/hotspot/cpu/arm/vm_version_arm_32.cpp +++ b/src/hotspot/cpu/arm/vm_version_arm_32.cpp @@ -347,3 +347,17 @@ void VM_Version::initialize() { _is_initialized = true; } + +void VM_Version::initialize_cpu_information(void) { + // do nothing if cpu info has been initialized + if (_initialized) { + return; + } + + _no_of_cores = os::processor_count(); + _no_of_threads = _no_of_cores; + _no_of_sockets = _no_of_cores; + snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE - 1, "ARM%d", _arm_arch); + snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "%s", _features_string); + _initialized = true; +} diff --git a/src/hotspot/cpu/arm/vm_version_ext_arm.cpp b/src/hotspot/cpu/arm/vm_version_ext_arm.cpp deleted file mode 100644 index 0e2a1ffa1369f9e13e66b0cfaa3811aeff6e0830..0000000000000000000000000000000000000000 --- a/src/hotspot/cpu/arm/vm_version_ext_arm.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "memory/allocation.hpp" -#include "memory/allocation.inline.hpp" -#include "runtime/os.inline.hpp" -#include "vm_version_ext_arm.hpp" - -// VM_Version_Ext statics -int VM_Version_Ext::_no_of_threads = 0; -int VM_Version_Ext::_no_of_cores = 0; -int VM_Version_Ext::_no_of_sockets = 0; -bool VM_Version_Ext::_initialized = false; -char VM_Version_Ext::_cpu_name[CPU_TYPE_DESC_BUF_SIZE] = {0}; -char VM_Version_Ext::_cpu_desc[CPU_DETAILED_DESC_BUF_SIZE] = {0}; - -void VM_Version_Ext::initialize_cpu_information(void) { - // do nothing if cpu info has been initialized - if (_initialized) { - return; - } - - int core_id = -1; - int chip_id = -1; - int len = 0; - char* src_string = NULL; - - _no_of_cores = os::processor_count(); - _no_of_threads = _no_of_cores; - _no_of_sockets = _no_of_cores; - snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE - 1, "ARM%d", _arm_arch); - snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "%s", _features_string); - _initialized = true; -} - -int VM_Version_Ext::number_of_threads(void) { - initialize_cpu_information(); - return _no_of_threads; -} - -int VM_Version_Ext::number_of_cores(void) { - initialize_cpu_information(); - return _no_of_cores; -} - -int VM_Version_Ext::number_of_sockets(void) { - initialize_cpu_information(); - return _no_of_sockets; -} - -const char* VM_Version_Ext::cpu_name(void) { - initialize_cpu_information(); - char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, CPU_TYPE_DESC_BUF_SIZE, mtTracing); - if (NULL == tmp) { - return NULL; - } - strncpy(tmp, _cpu_name, CPU_TYPE_DESC_BUF_SIZE); - return tmp; -} - -const char* VM_Version_Ext::cpu_description(void) { - initialize_cpu_information(); - char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, CPU_DETAILED_DESC_BUF_SIZE, mtTracing); - if (NULL == tmp) { - return NULL; - } - strncpy(tmp, _cpu_desc, CPU_DETAILED_DESC_BUF_SIZE); - return tmp; -} diff --git a/src/hotspot/cpu/arm/vm_version_ext_arm.hpp b/src/hotspot/cpu/arm/vm_version_ext_arm.hpp deleted file mode 100644 index 77fc4615e1b4450b02d42ebd0a6b80fd8c8d81f0..0000000000000000000000000000000000000000 --- a/src/hotspot/cpu/arm/vm_version_ext_arm.hpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef CPU_ARM_VM_VERSION_EXT_ARM_HPP -#define CPU_ARM_VM_VERSION_EXT_ARM_HPP - -#include "runtime/vm_version.hpp" -#include "utilities/macros.hpp" - -class VM_Version_Ext : public VM_Version { - private: - static const size_t CPU_TYPE_DESC_BUF_SIZE = 256; - static const size_t CPU_DETAILED_DESC_BUF_SIZE = 4096; - - static int _no_of_threads; - static int _no_of_cores; - static int _no_of_sockets; - static bool _initialized; - static char _cpu_name[CPU_TYPE_DESC_BUF_SIZE]; - static char _cpu_desc[CPU_DETAILED_DESC_BUF_SIZE]; - - public: - static int number_of_threads(void); - static int number_of_cores(void); - static int number_of_sockets(void); - - static const char* cpu_name(void); - static const char* cpu_description(void); - static void initialize_cpu_information(void); - -}; - -#endif // CPU_ARM_VM_VERSION_EXT_ARM_HPP diff --git a/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp index 831e2bdfe930df2de90bf2fdba5905dd9854780f..b04c49152f3fb81e72a721c61d6592549f208669 100644 --- a/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp @@ -812,12 +812,7 @@ int LIR_Assembler::load(Register base, int offset, LIR_Opr to_reg, BasicType typ case T_LONG : __ ld(to_reg->as_register_lo(), offset, base); break; case T_METADATA: __ ld(to_reg->as_register(), offset, base); break; case T_ADDRESS: - if (offset == oopDesc::klass_offset_in_bytes() && UseCompressedClassPointers) { - __ lwz(to_reg->as_register(), offset, base); - __ decode_klass_not_null(to_reg->as_register()); - } else { - __ ld(to_reg->as_register(), offset, base); - } + __ ld(to_reg->as_register(), offset, base); break; case T_ARRAY : // fall through case T_OBJECT: @@ -947,9 +942,10 @@ void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmi tmp = FrameMap::R0_opr; if (UseCompressedOops && !wide && c->as_jobject() != NULL) { AddressLiteral oop_addr = __ constant_oop_address(c->as_jobject()); - __ lis(R0, oop_addr.value() >> 16); // Don't care about sign extend (will use stw). + // Don't care about sign extend (will use stw). + __ lis(R0, 0); // Will get patched. __ relocate(oop_addr.rspec(), /*compressed format*/ 1); - __ ori(R0, R0, oop_addr.value() & 0xffff); + __ ori(R0, R0, 0); // Will get patched. } else { jobject2reg(c->as_jobject(), R0); } @@ -2694,7 +2690,7 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) { // Obj may not be an oop. if (op->code() == lir_lock) { MonitorEnterStub* stub = (MonitorEnterStub*)op->stub(); - if (UseFastLocking) { + if (!UseHeavyMonitors) { assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header"); // Add debug info for NullPointerException only if one is possible. if (op->info() != NULL) { @@ -2716,7 +2712,7 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) { } } else { assert (op->code() == lir_unlock, "Invalid code, expected lir_unlock"); - if (UseFastLocking) { + if (!UseHeavyMonitors) { assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header"); __ unlock_object(hdr, obj, lock, *op->stub()->entry()); } else { @@ -2732,6 +2728,26 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) { __ bind(*op->stub()->continuation()); } +void LIR_Assembler::emit_load_klass(LIR_OpLoadKlass* op) { + Register obj = op->obj()->as_pointer_register(); + Register result = op->result_opr()->as_pointer_register(); + + CodeEmitInfo* info = op->info(); + if (info != NULL) { + if (!os::zero_page_read_protected() || !ImplicitNullChecks) { + explicit_null_check(obj, info); + } else { + add_debug_info_for_null_check_here(info); + } + } + + if (UseCompressedClassPointers) { + __ lwz(result, oopDesc::klass_offset_in_bytes(), obj); + __ decode_klass_not_null(result); + } else { + __ ld(result, oopDesc::klass_offset_in_bytes(), obj); + } +} void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) { ciMethod* method = op->profiled_method(); diff --git a/src/hotspot/cpu/ppc/c2_MacroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/c2_MacroAssembler_ppc.cpp index 69a29c02654e484e2d2fe9357f923c0b7f5bcd3c..1ae5c13e62e97e0157ba8367b69369b7d3991ee0 100644 --- a/src/hotspot/cpu/ppc/c2_MacroAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/c2_MacroAssembler_ppc.cpp @@ -41,17 +41,18 @@ // Compress char[] to byte[] by compressing 16 bytes at once. void C2_MacroAssembler::string_compress_16(Register src, Register dst, Register cnt, Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5, - Label& Lfailure) { + Label& Lfailure, bool ascii) { const Register tmp0 = R0; + const int byte_mask = ascii ? 0x7F : 0xFF; assert_different_registers(src, dst, cnt, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5); Label Lloop, Lslow; // Check if cnt >= 8 (= 16 bytes) - lis(tmp1, 0xFF); // tmp1 = 0x00FF00FF00FF00FF + lis(tmp1, byte_mask); // tmp1 = 0x00FF00FF00FF00FF (non ascii case) srwi_(tmp2, cnt, 3); beq(CCR0, Lslow); - ori(tmp1, tmp1, 0xFF); + ori(tmp1, tmp1, byte_mask); rldimi(tmp1, tmp1, 32, 0); mtctr(tmp2); @@ -67,7 +68,7 @@ void C2_MacroAssembler::string_compress_16(Register src, Register dst, Register rldimi(tmp4, tmp4, 2*8, 2*8); // _4_6_7_7 andc_(tmp0, tmp0, tmp1); - bne(CCR0, Lfailure); // Not latin1. + bne(CCR0, Lfailure); // Not latin1/ascii. addi(src, src, 16); rlwimi(tmp3, tmp2, 0*8, 24, 31);// _____1_3 @@ -87,20 +88,49 @@ void C2_MacroAssembler::string_compress_16(Register src, Register dst, Register } // Compress char[] to byte[]. cnt must be positive int. -void C2_MacroAssembler::string_compress(Register src, Register dst, Register cnt, Register tmp, Label& Lfailure) { +void C2_MacroAssembler::string_compress(Register src, Register dst, Register cnt, Register tmp, + Label& Lfailure, bool ascii) { + const int byte_mask = ascii ? 0x7F : 0xFF; Label Lloop; mtctr(cnt); bind(Lloop); lhz(tmp, 0, src); - cmplwi(CCR0, tmp, 0xff); - bgt(CCR0, Lfailure); // Not latin1. + cmplwi(CCR0, tmp, byte_mask); + bgt(CCR0, Lfailure); // Not latin1/ascii. addi(src, src, 2); stb(tmp, 0, dst); addi(dst, dst, 1); bdnz(Lloop); } +void C2_MacroAssembler::encode_iso_array(Register src, Register dst, Register len, + Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5, + Register result, bool ascii) { + Label Lslow, Lfailure1, Lfailure2, Ldone; + + string_compress_16(src, dst, len, tmp1, tmp2, tmp3, tmp4, tmp5, Lfailure1, ascii); + rldicl_(result, len, 0, 64-3); // Remaining characters. + beq(CCR0, Ldone); + bind(Lslow); + string_compress(src, dst, result, tmp2, Lfailure2, ascii); + li(result, 0); + b(Ldone); + + bind(Lfailure1); + mr(result, len); + mfctr(tmp1); + rldimi_(result, tmp1, 3, 0); // Remaining characters. + beq(CCR0, Ldone); + b(Lslow); + + bind(Lfailure2); + mfctr(result); // Remaining characters. + + bind(Ldone); + subf(result, result, len); +} + // Inflate byte[] to char[] by inflating 16 bytes at once. void C2_MacroAssembler::string_inflate_16(Register src, Register dst, Register cnt, Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5) { diff --git a/src/hotspot/cpu/ppc/c2_MacroAssembler_ppc.hpp b/src/hotspot/cpu/ppc/c2_MacroAssembler_ppc.hpp index 9f363f2b962170c6d3c43a84fe2851d036668696..9c4576f2eaf043f0be28ef27f56c348cae1d5de7 100644 --- a/src/hotspot/cpu/ppc/c2_MacroAssembler_ppc.hpp +++ b/src/hotspot/cpu/ppc/c2_MacroAssembler_ppc.hpp @@ -32,10 +32,16 @@ // Compress char[] to byte[] by compressing 16 bytes at once. void string_compress_16(Register src, Register dst, Register cnt, Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5, - Label& Lfailure); + Label& Lfailure, bool ascii = false); // Compress char[] to byte[]. cnt must be positive int. - void string_compress(Register src, Register dst, Register cnt, Register tmp, Label& Lfailure); + void string_compress(Register src, Register dst, Register cnt, Register tmp, + Label& Lfailure, bool ascii = false); + + // Encode UTF16 to ISO_8859_1 or ASCII. Return len on success or position of first mismatch. + void encode_iso_array(Register src, Register dst, Register len, + Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5, + Register result, bool ascii); // Inflate byte[] to char[] by inflating 16 bytes at once. void string_inflate_16(Register src, Register dst, Register cnt, diff --git a/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp b/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp index a9328e8d616705b0e2caa8e40c254b5e46816a10..05c8374cfa4c8ca55d0c064308af9a4d45eb622c 100644 --- a/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp @@ -245,7 +245,7 @@ void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, Decorato Register Rbase = tmp2; __ load_const_optimized(Rbase, (address)(ct->card_table()->byte_map_base()), /*temp*/ tmp3); - __ srdi(Rcard_addr, store_addr, CardTable::card_shift); + __ srdi(Rcard_addr, store_addr, CardTable::card_shift()); // Get the address of the card. __ lbzx(/*card value*/ tmp3, Rbase, Rcard_addr); @@ -516,7 +516,7 @@ void G1BarrierSetAssembler::generate_c1_post_barrier_runtime_stub(StubAssembler* __ std(addr, -8, R1_SP); __ std(tmp2, -16, R1_SP); - __ srdi(addr, R0, CardTable::card_shift); // Addr is passed in R0. + __ srdi(addr, R0, CardTable::card_shift()); // Addr is passed in R0. __ load_const_optimized(/*cardtable*/ tmp2, byte_map_base, tmp); __ add(addr, tmp2, addr); __ lbz(tmp, 0, addr); // tmp := [addr + cardtable] diff --git a/src/hotspot/cpu/ppc/gc/shared/cardTableBarrierSetAssembler_ppc.cpp b/src/hotspot/cpu/ppc/gc/shared/cardTableBarrierSetAssembler_ppc.cpp index 8337317e3f2cc1a431aa8832d87005a72c222381..0d80f2fd95484922d76476d7fdcbe2c0c5c2d9cf 100644 --- a/src/hotspot/cpu/ppc/gc/shared/cardTableBarrierSetAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/gc/shared/cardTableBarrierSetAssembler_ppc.cpp @@ -54,8 +54,8 @@ void CardTableBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembl __ addi(count, count, -BytesPerHeapOop); __ add(count, addr, count); // Use two shifts to clear out those low order two bits! (Cannot opt. into 1.) - __ srdi(addr, addr, CardTable::card_shift); - __ srdi(count, count, CardTable::card_shift); + __ srdi(addr, addr, CardTable::card_shift()); + __ srdi(count, count, CardTable::card_shift()); __ subf(count, addr, count); __ add_const_optimized(addr, addr, (address)ct->byte_map_base(), R0); __ addi(count, count, 1); @@ -74,7 +74,7 @@ void CardTableBarrierSetAssembler::card_table_write(MacroAssembler* masm, Register tmp, Register obj) { assert_different_registers(obj, tmp, R0); __ load_const_optimized(tmp, (address)byte_map_base, R0); - __ srdi(obj, obj, CardTable::card_shift); + __ srdi(obj, obj, CardTable::card_shift()); __ li(R0, CardTable::dirty_card_val()); __ stbx(R0, tmp, obj); } diff --git a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp index 98565003691a45fd9c35ea0609d3c8ec2717cd60..57d65c3aa08b9a29816d27a46b9b7fe7c93ab6db 100644 --- a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp @@ -233,7 +233,7 @@ address MacroAssembler::patch_set_narrow_oop(address a, address bound, narrowOop return inst1_addr; } -// Get compressed oop or klass constant. +// Get compressed oop constant. narrowOop MacroAssembler::get_narrow_oop(address a, address bound) { assert(UseCompressedOops, "Should only patch compressed oops"); @@ -2660,27 +2660,32 @@ void MacroAssembler::compiler_fast_lock_object(ConditionRegister flag, Register andi_(temp, displaced_header, markWord::monitor_value); bne(CCR0, object_has_monitor); - // Set displaced_header to be (markWord of object | UNLOCK_VALUE). - ori(displaced_header, displaced_header, markWord::unlocked_value); - - // Load Compare Value application register. - - // Initialize the box. (Must happen before we update the object mark!) - std(displaced_header, BasicLock::displaced_header_offset_in_bytes(), box); - - // Must fence, otherwise, preceding store(s) may float below cmpxchg. - // Compare object markWord with mark and if equal exchange scratch1 with object markWord. - cmpxchgd(/*flag=*/flag, - /*current_value=*/current_header, - /*compare_value=*/displaced_header, - /*exchange_value=*/box, - /*where=*/oop, - MacroAssembler::MemBarRel | MacroAssembler::MemBarAcq, - MacroAssembler::cmpxchgx_hint_acquire_lock(), - noreg, - &cas_failed, - /*check without membar and ldarx first*/true); - assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0"); + if (!UseHeavyMonitors) { + // Set displaced_header to be (markWord of object | UNLOCK_VALUE). + ori(displaced_header, displaced_header, markWord::unlocked_value); + + // Load Compare Value application register. + + // Initialize the box. (Must happen before we update the object mark!) + std(displaced_header, BasicLock::displaced_header_offset_in_bytes(), box); + + // Must fence, otherwise, preceding store(s) may float below cmpxchg. + // Compare object markWord with mark and if equal exchange scratch1 with object markWord. + cmpxchgd(/*flag=*/flag, + /*current_value=*/current_header, + /*compare_value=*/displaced_header, + /*exchange_value=*/box, + /*where=*/oop, + MacroAssembler::MemBarRel | MacroAssembler::MemBarAcq, + MacroAssembler::cmpxchgx_hint_acquire_lock(), + noreg, + &cas_failed, + /*check without membar and ldarx first*/true); + assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0"); + } else { + // Set NE to indicate 'failure' -> take slow-path. + crandc(flag, Assembler::equal, flag, Assembler::equal); + } // If the compare-and-exchange succeeded, then we found an unlocked // object and we have now locked it. @@ -2768,12 +2773,14 @@ void MacroAssembler::compiler_fast_unlock_object(ConditionRegister flag, Registe } #endif - // Find the lock address and load the displaced header from the stack. - ld(displaced_header, BasicLock::displaced_header_offset_in_bytes(), box); + if (!UseHeavyMonitors) { + // Find the lock address and load the displaced header from the stack. + ld(displaced_header, BasicLock::displaced_header_offset_in_bytes(), box); - // If the displaced header is 0, we have a recursive unlock. - cmpdi(flag, displaced_header, 0); - beq(flag, cont); + // If the displaced header is 0, we have a recursive unlock. + cmpdi(flag, displaced_header, 0); + beq(flag, cont); + } // Handle existing monitor. // The object has an existing monitor iff (mark & monitor_value) != 0. @@ -2782,20 +2789,24 @@ void MacroAssembler::compiler_fast_unlock_object(ConditionRegister flag, Registe andi_(R0, current_header, markWord::monitor_value); bne(CCR0, object_has_monitor); - // Check if it is still a light weight lock, this is is true if we see - // the stack address of the basicLock in the markWord of the object. - // Cmpxchg sets flag to cmpd(current_header, box). - cmpxchgd(/*flag=*/flag, - /*current_value=*/current_header, - /*compare_value=*/box, - /*exchange_value=*/displaced_header, - /*where=*/oop, - MacroAssembler::MemBarRel, - MacroAssembler::cmpxchgx_hint_release_lock(), - noreg, - &cont); - - assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0"); + if (!UseHeavyMonitors) { + // Check if it is still a light weight lock, this is is true if we see + // the stack address of the basicLock in the markWord of the object. + // Cmpxchg sets flag to cmpd(current_header, box). + cmpxchgd(/*flag=*/flag, + /*current_value=*/current_header, + /*compare_value=*/box, + /*exchange_value=*/displaced_header, + /*where=*/oop, + MacroAssembler::MemBarRel, + MacroAssembler::cmpxchgx_hint_release_lock(), + noreg, + &cont); + assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0"); + } else { + // Set NE to indicate 'failure' -> take slow-path. + crandc(flag, Assembler::equal, flag, Assembler::equal); + } // Handle existing monitor. b(cont); diff --git a/src/hotspot/cpu/ppc/matcher_ppc.hpp b/src/hotspot/cpu/ppc/matcher_ppc.hpp index 877f0be33c4413b644f76aef049c5707d6c0ec04..c07525bf79e71ab8882e6ee851f73710ad312174 100644 --- a/src/hotspot/cpu/ppc/matcher_ppc.hpp +++ b/src/hotspot/cpu/ppc/matcher_ppc.hpp @@ -165,6 +165,6 @@ } // Implements a variant of EncodeISOArrayNode that encode ASCII only - static const bool supports_encode_ascii_array = false; + static const bool supports_encode_ascii_array = true; #endif // CPU_PPC_MATCHER_PPC_HPP diff --git a/src/hotspot/cpu/ppc/nativeInst_ppc.hpp b/src/hotspot/cpu/ppc/nativeInst_ppc.hpp index 03b03238b025bdbef7110f7bfc88ace304532e6b..e9cc46e868112e82c505c5029c289b32818c0c3a 100644 --- a/src/hotspot/cpu/ppc/nativeInst_ppc.hpp +++ b/src/hotspot/cpu/ppc/nativeInst_ppc.hpp @@ -257,7 +257,7 @@ class NativeMovConstReg: public NativeInstruction { // Patch the code stream and oop pool. void set_data(intptr_t x); - // Patch narrow oop constants. Use this also for narrow klass. + // Patch narrow oop constants. void set_narrow_oop(narrowOop data, CodeBlob *code = NULL); void verify() NOT_DEBUG_RETURN; diff --git a/src/hotspot/cpu/ppc/ppc.ad b/src/hotspot/cpu/ppc/ppc.ad index 958059e1ca254ad9218d7134b81eb6e517cf7c77..832982deb4552f1477017ba7ab174dacd72c1e47 100644 --- a/src/hotspot/cpu/ppc/ppc.ad +++ b/src/hotspot/cpu/ppc/ppc.ad @@ -2185,7 +2185,7 @@ const RegMask* Matcher::predicate_reg_mask(void) { return NULL; } -const TypeVect* Matcher::predicate_reg_type(const Type* elemTy, int length) { +const TypeVectMask* Matcher::predicate_reg_type(const Type* elemTy, int length) { return NULL; } @@ -5953,7 +5953,7 @@ instruct loadConN_hi(iRegNdst dst, immN src) %{ format %{ "LIS $dst, $src \t// narrow oop hi" %} size(4); ins_encode %{ - __ lis($dst$$Register, (int)(short)(($src$$constant >> 16) & 0xffff)); + __ lis($dst$$Register, 0); // Will get patched. %} ins_pipe(pipe_class_default); %} @@ -5966,11 +5966,9 @@ instruct loadConN_lo(iRegNdst dst, iRegNsrc src1, immN src2) %{ format %{ "ORI $dst, $src1, $src2 \t// narrow oop lo" %} size(4); ins_encode %{ - assert(__ oop_recorder() != NULL, "this assembler needs an OopRecorder"); - int oop_index = __ oop_recorder()->find_index((jobject)$src2$$constant); - RelocationHolder rspec = oop_Relocation::spec(oop_index); - __ relocate(rspec, 1); - __ ori($dst$$Register, $src1$$Register, $src2$$constant & 0xffff); + AddressLiteral addrlit = __ constant_oop_address((jobject)$src2$$constant); + __ relocate(addrlit.rspec(), /*compressed format*/ 1); + __ ori($dst$$Register, $src1$$Register, 0); // Will get patched. %} ins_pipe(pipe_class_default); %} @@ -6085,12 +6083,9 @@ instruct loadConNKlass_lo(iRegNdst dst, immNKlass_NM src1, iRegNsrc src2) %{ format %{ "ORI $dst, $src1, $src2 \t// narrow klass lo" %} size(4); ins_encode %{ - intptr_t Csrc = CompressedKlassPointers::encode((Klass *)$src1$$constant); - assert(__ oop_recorder() != NULL, "this assembler needs an OopRecorder"); - int klass_index = __ oop_recorder()->find_index((Klass *)$src1$$constant); - RelocationHolder rspec = metadata_Relocation::spec(klass_index); - - __ relocate(rspec, 1); + // Notify OOP recorder (don't need the relocation) + AddressLiteral md = __ constant_metadata_address((Klass*)$src1$$constant); + intptr_t Csrc = CompressedKlassPointers::encode((Klass*)md.value()); __ ori($dst$$Register, $src2$$Register, Csrc & 0xffff); %} ins_pipe(pipe_class_default); @@ -12806,30 +12801,26 @@ instruct encode_iso_array(rarg1RegP src, rarg2RegP dst, iRegIsrc len, iRegIdst r effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, USE_KILL src, USE_KILL dst, KILL ctr, KILL cr0); ins_cost(300); - format %{ "Encode array $src,$dst,$len -> $result \t// KILL $tmp1, $tmp2, $tmp3, $tmp4, $tmp5" %} + format %{ "Encode iso array $src,$dst,$len -> $result \t// KILL $tmp1, $tmp2, $tmp3, $tmp4, $tmp5" %} ins_encode %{ - Label Lslow, Lfailure1, Lfailure2, Ldone; - __ string_compress_16($src$$Register, $dst$$Register, $len$$Register, $tmp1$$Register, - $tmp2$$Register, $tmp3$$Register, $tmp4$$Register, $tmp5$$Register, Lfailure1); - __ rldicl_($result$$Register, $len$$Register, 0, 64-3); // Remaining characters. - __ beq(CCR0, Ldone); - __ bind(Lslow); - __ string_compress($src$$Register, $dst$$Register, $result$$Register, $tmp2$$Register, Lfailure2); - __ li($result$$Register, 0); - __ b(Ldone); - - __ bind(Lfailure1); - __ mr($result$$Register, $len$$Register); - __ mfctr($tmp1$$Register); - __ rldimi_($result$$Register, $tmp1$$Register, 3, 0); // Remaining characters. - __ beq(CCR0, Ldone); - __ b(Lslow); - - __ bind(Lfailure2); - __ mfctr($result$$Register); // Remaining characters. + __ encode_iso_array($src$$Register, $dst$$Register, $len$$Register, $tmp1$$Register, $tmp2$$Register, + $tmp3$$Register, $tmp4$$Register, $tmp5$$Register, $result$$Register, false); + %} + ins_pipe(pipe_class_default); +%} - __ bind(Ldone); - __ subf($result$$Register, $result$$Register, $len$$Register); +// encode char[] to byte[] in ASCII +instruct encode_ascii_array(rarg1RegP src, rarg2RegP dst, iRegIsrc len, iRegIdst result, iRegLdst tmp1, + iRegLdst tmp2, iRegLdst tmp3, iRegLdst tmp4, iRegLdst tmp5, regCTR ctr, flagsRegCR0 cr0) %{ + predicate(((EncodeISOArrayNode*)n)->is_ascii()); + match(Set result (EncodeISOArray src (Binary dst len))); + effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, + USE_KILL src, USE_KILL dst, KILL ctr, KILL cr0); + ins_cost(300); + format %{ "Encode ascii array $src,$dst,$len -> $result \t// KILL $tmp1, $tmp2, $tmp3, $tmp4, $tmp5" %} + ins_encode %{ + __ encode_iso_array($src$$Register, $dst$$Register, $len$$Register, $tmp1$$Register, $tmp2$$Register, + $tmp3$$Register, $tmp4$$Register, $tmp5$$Register, $result$$Register, true); %} ins_pipe(pipe_class_default); %} diff --git a/src/hotspot/cpu/ppc/relocInfo_ppc.cpp b/src/hotspot/cpu/ppc/relocInfo_ppc.cpp index 71ced03459f9e5914223e748f91b37746dae80bf..a3a63c6283faf1f0d554bd4df2056cefcb591192 100644 --- a/src/hotspot/cpu/ppc/relocInfo_ppc.cpp +++ b/src/hotspot/cpu/ppc/relocInfo_ppc.cpp @@ -33,34 +33,15 @@ #include "runtime/safepoint.hpp" void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) { - // The following comment is from the declaration of DataRelocation: - // - // "The "o" (displacement) argument is relevant only to split relocations - // on RISC machines. In some CPUs (SPARC), the set-hi and set-lo ins'ns - // can encode more than 32 bits between them. This allows compilers to - // share set-hi instructions between addresses that differ by a small - // offset (e.g., different static variables in the same class). - // On such machines, the "x" argument to set_value on all set-lo - // instructions must be the same as the "x" argument for the - // corresponding set-hi instructions. The "o" arguments for the - // set-hi instructions are ignored, and must not affect the high-half - // immediate constant. The "o" arguments for the set-lo instructions are - // added into the low-half immediate constant, and must not overflow it." - // - // Currently we don't support splitting of relocations, so o must be - // zero: + // Currently we don't support splitting of relocations. assert(o == 0, "tried to split relocations"); if (!verify_only) { if (format() != 1) { nativeMovConstReg_at(addr())->set_data_plain(((intptr_t)x), code()); } else { - assert(type() == relocInfo::oop_type || type() == relocInfo::metadata_type, - "how to encode else?"); - narrowOop no = (type() == relocInfo::oop_type) ? - CompressedOops::encode(cast_to_oop(x)) : - // Type punning compressed klass pointer as narrowOop. - CompressedOops::narrow_oop_cast(CompressedKlassPointers::encode((Klass*)x)); + assert(type() == relocInfo::oop_type, "how to encode else?"); + narrowOop no = CompressedOops::encode(cast_to_oop(x)); nativeMovConstReg_at(addr())->set_narrow_oop(no, code()); } } else { diff --git a/src/hotspot/cpu/ppc/vm_version_ext_ppc.cpp b/src/hotspot/cpu/ppc/vm_version_ext_ppc.cpp deleted file mode 100644 index 8840a762840338cb176361576afef18648814ae7..0000000000000000000000000000000000000000 --- a/src/hotspot/cpu/ppc/vm_version_ext_ppc.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "jvm.h" -#include "memory/allocation.hpp" -#include "memory/allocation.inline.hpp" -#include "runtime/vm_version.hpp" -#include "vm_version_ext_ppc.hpp" - -// VM_Version_Ext statics -int VM_Version_Ext::_no_of_threads = 0; -int VM_Version_Ext::_no_of_cores = 0; -int VM_Version_Ext::_no_of_sockets = 0; -bool VM_Version_Ext::_initialized = false; -char VM_Version_Ext::_cpu_name[CPU_TYPE_DESC_BUF_SIZE] = {0}; -char VM_Version_Ext::_cpu_desc[CPU_DETAILED_DESC_BUF_SIZE] = {0}; - -// get cpu information. -void VM_Version_Ext::initialize_cpu_information(void) { - // do nothing if cpu info has been initialized - if (_initialized) { - return; - } - - _no_of_cores = os::processor_count(); - _no_of_threads = _no_of_cores; - _no_of_sockets = _no_of_cores; - snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE, "PowerPC POWER%lu", PowerArchitecturePPC64); - snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "PPC %s", features_string()); - _initialized = true; -} - -int VM_Version_Ext::number_of_threads(void) { - initialize_cpu_information(); - return _no_of_threads; -} - -int VM_Version_Ext::number_of_cores(void) { - initialize_cpu_information(); - return _no_of_cores; -} - -int VM_Version_Ext::number_of_sockets(void) { - initialize_cpu_information(); - return _no_of_sockets; -} - -const char* VM_Version_Ext::cpu_name(void) { - initialize_cpu_information(); - char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, CPU_TYPE_DESC_BUF_SIZE, mtTracing); - if (NULL == tmp) { - return NULL; - } - strncpy(tmp, _cpu_name, CPU_TYPE_DESC_BUF_SIZE); - return tmp; -} - -const char* VM_Version_Ext::cpu_description(void) { - initialize_cpu_information(); - char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, CPU_DETAILED_DESC_BUF_SIZE, mtTracing); - if (NULL == tmp) { - return NULL; - } - strncpy(tmp, _cpu_desc, CPU_DETAILED_DESC_BUF_SIZE); - return tmp; -} diff --git a/src/hotspot/cpu/ppc/vm_version_ext_ppc.hpp b/src/hotspot/cpu/ppc/vm_version_ext_ppc.hpp deleted file mode 100644 index 36df6f19fd3739523891ce835aff201af87b5f24..0000000000000000000000000000000000000000 --- a/src/hotspot/cpu/ppc/vm_version_ext_ppc.hpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef CPU_PPC_VM_VERSION_EXT_PPC_HPP -#define CPU_PPC_VM_VERSION_EXT_PPC_HPP - -#include "runtime/vm_version.hpp" -#include "utilities/macros.hpp" - -#define CPU_INFO "cpu_info" -#define CPU_TYPE "fpu_type" -#define CPU_DESCRIPTION "implementation" -#define CHIP_ID "chip_id" -#define CORE_ID "core_id" - -class VM_Version_Ext : public VM_Version { - private: - - static const size_t CPU_TYPE_DESC_BUF_SIZE = 256; - static const size_t CPU_DETAILED_DESC_BUF_SIZE = 4096; - - static int _no_of_threads; - static int _no_of_cores; - static int _no_of_sockets; - static bool _initialized; - static char _cpu_name[CPU_TYPE_DESC_BUF_SIZE]; - static char _cpu_desc[CPU_DETAILED_DESC_BUF_SIZE]; - - static void initialize_cpu_information(void); - - public: - - static int number_of_threads(void); - static int number_of_cores(void); - static int number_of_sockets(void); - - static const char* cpu_name(void); - static const char* cpu_description(void); -}; - -#endif // CPU_PPC_VM_VERSION_EXT_PPC_HPP diff --git a/src/hotspot/cpu/ppc/vm_version_ppc.cpp b/src/hotspot/cpu/ppc/vm_version_ppc.cpp index 0b2aa63bceadcd833d1d992d53ceceba323ad683..96709b7196b732112a2200d8d202bb7e3a6fa2b3 100644 --- a/src/hotspot/cpu/ppc/vm_version_ppc.cpp +++ b/src/hotspot/cpu/ppc/vm_version_ppc.cpp @@ -767,3 +767,18 @@ void VM_Version::allow_all() { void VM_Version::revert() { _features = saved_features; } + +// get cpu information. +void VM_Version::initialize_cpu_information(void) { + // do nothing if cpu info has been initialized + if (_initialized) { + return; + } + + _no_of_cores = os::processor_count(); + _no_of_threads = _no_of_cores; + _no_of_sockets = _no_of_cores; + snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE, "PowerPC POWER%lu", PowerArchitecturePPC64); + snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "PPC %s", features_string()); + _initialized = true; +} diff --git a/src/hotspot/cpu/ppc/vm_version_ppc.hpp b/src/hotspot/cpu/ppc/vm_version_ppc.hpp index 89352192615c53b082d94802832ce213f35eeb3b..0a9d5ce081045d5e61aa91ded0457283640e85fd 100644 --- a/src/hotspot/cpu/ppc/vm_version_ppc.hpp +++ b/src/hotspot/cpu/ppc/vm_version_ppc.hpp @@ -128,6 +128,8 @@ public: // POWER 8: DSCR current value. static uint64_t _dscr_val; + + static void initialize_cpu_information(void); }; #endif // CPU_PPC_VM_VERSION_PPC_HPP diff --git a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp index 6971490e0681cacf8ae196ae7079ad3bbd5328da..1d1f163826e243de60c85a19890b5191a1140bee 100644 --- a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp @@ -950,12 +950,7 @@ void LIR_Assembler::mem2reg(LIR_Opr src_opr, LIR_Opr dest, BasicType type, LIR_P } break; case T_ADDRESS: - if (UseCompressedClassPointers && addr->disp() == oopDesc::klass_offset_in_bytes()) { - __ z_llgf(dest->as_register(), disp_value, disp_reg, src); - __ decode_klass_not_null(dest->as_register()); - } else { - __ z_lg(dest->as_register(), disp_value, disp_reg, src); - } + __ z_lg(dest->as_register(), disp_value, disp_reg, src); break; case T_ARRAY : // fall through case T_OBJECT: @@ -2735,7 +2730,7 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) { Register obj = op->obj_opr()->as_register(); // May not be an oop. Register hdr = op->hdr_opr()->as_register(); Register lock = op->lock_opr()->as_register(); - if (!UseFastLocking) { + if (UseHeavyMonitors) { __ branch_optimized(Assembler::bcondAlways, *op->stub()->entry()); } else if (op->code() == lir_lock) { assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header"); @@ -2754,6 +2749,22 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) { __ bind(*op->stub()->continuation()); } +void LIR_Assembler::emit_load_klass(LIR_OpLoadKlass* op) { + Register obj = op->obj()->as_pointer_register(); + Register result = op->result_opr()->as_pointer_register(); + + CodeEmitInfo* info = op->info(); + if (info != NULL) { + add_debug_info_for_null_check_here(info); + } + + if (UseCompressedClassPointers) { + __ z_llgf(result, Address(obj, oopDesc::klass_offset_in_bytes())); + __ decode_klass_not_null(result); + } else { + __ z_lg(result, Address(obj, oopDesc::klass_offset_in_bytes())); + } +} void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) { ciMethod* method = op->profiled_method(); int bci = op->profiled_bci(); diff --git a/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp b/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp index 7258630bb0b9d30dfbd4691d675ddd7c27449733..b6e3d9eb2c7b5ab59ed1a4a3a95356a2b8edac76 100644 --- a/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp @@ -305,7 +305,7 @@ void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, Decorato // calculate address of card __ load_const_optimized(Rbase, (address)ct->card_table()->byte_map_base()); // Card table base. - __ z_srlg(Rcard_addr, Rstore_addr, CardTable::card_shift); // Index into card table. + __ z_srlg(Rcard_addr, Rstore_addr, CardTable::card_shift()); // Index into card table. __ z_algr(Rcard_addr, Rbase); // Explicit calculation needed for cli. Rbase = noreg; // end of lifetime @@ -548,7 +548,7 @@ void G1BarrierSetAssembler::generate_c1_post_barrier_runtime_stub(StubAssembler* // Calculate address of card corresponding to the updated oop slot. AddressLiteral rs(byte_map_base); - __ z_srlg(addr_card, addr_oop, CardTable::card_shift); + __ z_srlg(addr_card, addr_oop, CardTable::card_shift()); addr_oop = noreg; // dead now __ load_const_optimized(cardtable, rs); // cardtable := __ z_agr(addr_card, cardtable); // addr_card := addr_oop>>card_shift + cardtable diff --git a/src/hotspot/cpu/s390/gc/shared/cardTableBarrierSetAssembler_s390.cpp b/src/hotspot/cpu/s390/gc/shared/cardTableBarrierSetAssembler_s390.cpp index d3f7bafd33ea3a82a2a0857e6605cecefffb79a9..0124868e46a6fe0b9b49115c146d646b56f59011 100644 --- a/src/hotspot/cpu/s390/gc/shared/cardTableBarrierSetAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/gc/shared/cardTableBarrierSetAssembler_s390.cpp @@ -70,8 +70,8 @@ void CardTableBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembl __ load_const_optimized(Z_R1, (address)ct->byte_map_base()); // count = (count>>shift) - (addr>>shift) - __ z_srlg(addr, addr, CardTable::card_shift); - __ z_srlg(count, count, CardTable::card_shift); + __ z_srlg(addr, addr, CardTable::card_shift()); + __ z_srlg(count, count, CardTable::card_shift()); // Prefetch first elements of card table for update. if (VM_Version::has_Prefetch()) { @@ -146,7 +146,7 @@ void CardTableBarrierSetAssembler::store_check(MacroAssembler* masm, Register st assert_different_registers(store_addr, tmp); - __ z_srlg(store_addr, store_addr, CardTable::card_shift); + __ z_srlg(store_addr, store_addr, CardTable::card_shift()); __ load_absolute_address(tmp, (address)ct->byte_map_base()); __ z_agr(store_addr, tmp); __ z_mvi(0, store_addr, CardTable::dirty_card_val()); diff --git a/src/hotspot/cpu/s390/s390.ad b/src/hotspot/cpu/s390/s390.ad index 60c27c61a514c4cdcb190b661dab10f4d27e4b5c..8a6e62a809b3efd8e6791dcfa4f36c65798f6e6c 100644 --- a/src/hotspot/cpu/s390/s390.ad +++ b/src/hotspot/cpu/s390/s390.ad @@ -1544,7 +1544,7 @@ const RegMask* Matcher::predicate_reg_mask(void) { return NULL; } -const TypeVect* Matcher::predicate_reg_type(const Type* elemTy, int length) { +const TypeVectMask* Matcher::predicate_reg_type(const Type* elemTy, int length) { return NULL; } diff --git a/src/hotspot/cpu/s390/vm_version_ext_s390.cpp b/src/hotspot/cpu/s390/vm_version_ext_s390.cpp deleted file mode 100644 index 2be9d1c5ede1937922dab2152a0f441b05e04d0d..0000000000000000000000000000000000000000 --- a/src/hotspot/cpu/s390/vm_version_ext_s390.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "jvm.h" -#include "memory/allocation.hpp" -#include "memory/allocation.inline.hpp" -#include "vm_version_ext_s390.hpp" - -// VM_Version_Ext statics -int VM_Version_Ext::_no_of_threads = 0; -int VM_Version_Ext::_no_of_cores = 0; -int VM_Version_Ext::_no_of_sockets = 0; -bool VM_Version_Ext::_initialized = false; -char VM_Version_Ext::_cpu_name[CPU_TYPE_DESC_BUF_SIZE] = {0}; -char VM_Version_Ext::_cpu_desc[CPU_DETAILED_DESC_BUF_SIZE] = {0}; - -// get cpu information. -void VM_Version_Ext::initialize_cpu_information(void) { - // do nothing if cpu info has been initialized - if (_initialized) { - return; - } - - _no_of_cores = os::processor_count(); - _no_of_threads = _no_of_cores; - _no_of_sockets = _no_of_cores; - snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE, "s390 %s", VM_Version::get_model_string()); - snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "s390 %s", features_string()); - _initialized = true; -} - -int VM_Version_Ext::number_of_threads(void) { - initialize_cpu_information(); - return _no_of_threads; -} - -int VM_Version_Ext::number_of_cores(void) { - initialize_cpu_information(); - return _no_of_cores; -} - -int VM_Version_Ext::number_of_sockets(void) { - initialize_cpu_information(); - return _no_of_sockets; -} - -const char* VM_Version_Ext::cpu_name(void) { - initialize_cpu_information(); - char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, CPU_TYPE_DESC_BUF_SIZE, mtTracing); - if (NULL == tmp) { - return NULL; - } - strncpy(tmp, _cpu_name, CPU_TYPE_DESC_BUF_SIZE); - return tmp; -} - -const char* VM_Version_Ext::cpu_description(void) { - initialize_cpu_information(); - char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, CPU_DETAILED_DESC_BUF_SIZE, mtTracing); - if (NULL == tmp) { - return NULL; - } - strncpy(tmp, _cpu_desc, CPU_DETAILED_DESC_BUF_SIZE); - return tmp; -} diff --git a/src/hotspot/cpu/s390/vm_version_ext_s390.hpp b/src/hotspot/cpu/s390/vm_version_ext_s390.hpp deleted file mode 100644 index 8e6bc62e52df835cf8c40c8100be60b5e11f95cb..0000000000000000000000000000000000000000 --- a/src/hotspot/cpu/s390/vm_version_ext_s390.hpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef CPU_S390_VM_VERSION_EXT_S390_HPP -#define CPU_S390_VM_VERSION_EXT_S390_HPP - -#include "runtime/vm_version.hpp" -#include "utilities/macros.hpp" - -#define CPU_INFO "cpu_info" -#define CPU_TYPE "fpu_type" -#define CPU_DESCRIPTION "implementation" -#define CHIP_ID "chip_id" -#define CORE_ID "core_id" - -class VM_Version_Ext : public VM_Version { - private: - - static const size_t CPU_TYPE_DESC_BUF_SIZE = 256; - static const size_t CPU_DETAILED_DESC_BUF_SIZE = 4096; - - static int _no_of_threads; - static int _no_of_cores; - static int _no_of_sockets; - static bool _initialized; - static char _cpu_name[CPU_TYPE_DESC_BUF_SIZE]; - static char _cpu_desc[CPU_DETAILED_DESC_BUF_SIZE]; - - static void initialize_cpu_information(void); - - public: - - static int number_of_threads(void); - static int number_of_cores(void); - static int number_of_sockets(void); - - static const char* cpu_name(void); - static const char* cpu_description(void); -}; - -#endif // CPU_S390_VM_VERSION_EXT_S390_HPP diff --git a/src/hotspot/cpu/s390/vm_version_s390.cpp b/src/hotspot/cpu/s390/vm_version_s390.cpp index d7b68f907c7e370aeb5c405a7c01fc4548f1b069..6c077943d3a5a8b128010e0dc42f2497b21297bb 100644 --- a/src/hotspot/cpu/s390/vm_version_s390.cpp +++ b/src/hotspot/cpu/s390/vm_version_s390.cpp @@ -1490,3 +1490,19 @@ unsigned long VM_Version::z_SIGSEGV() { ); return ZeroBuffer; } + + +// get cpu information. +void VM_Version::initialize_cpu_information(void) { + // do nothing if cpu info has been initialized + if (_initialized) { + return; + } + + _no_of_cores = os::processor_count(); + _no_of_threads = _no_of_cores; + _no_of_sockets = _no_of_cores; + snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE, "s390 %s", VM_Version::get_model_string()); + snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "s390 %s", features_string()); + _initialized = true; +} diff --git a/src/hotspot/cpu/s390/vm_version_s390.hpp b/src/hotspot/cpu/s390/vm_version_s390.hpp index 176aa7549c0c807cd73d83d9233d160e536d6522..a2fb7dd8e9a3fafe578dd8cd9468ff90436b4b07 100644 --- a/src/hotspot/cpu/s390/vm_version_s390.hpp +++ b/src/hotspot/cpu/s390/vm_version_s390.hpp @@ -533,6 +533,8 @@ class VM_Version: public Abstract_VM_Version { // Sometimes helpful for debugging. static unsigned long z_SIGILL(); static unsigned long z_SIGSEGV(); + + static void initialize_cpu_information(void); }; #endif // CPU_S390_VM_VERSION_S390_HPP diff --git a/src/hotspot/cpu/x86/assembler_x86.cpp b/src/hotspot/cpu/x86/assembler_x86.cpp index 2119c0797a63ea49f4ae85e93c3ce841b3c9a6ff..a8f826a5b7a2468cbc2cd2a2e797d35d3726fb10 100644 --- a/src/hotspot/cpu/x86/assembler_x86.cpp +++ b/src/hotspot/cpu/x86/assembler_x86.cpp @@ -186,7 +186,7 @@ Address::Address(address loc, RelocationHolder spec) { // Address. An index of 4 (rsp) corresponds to having no index, so convert // that to noreg for the Address constructor. Address Address::make_raw(int base, int index, int scale, int disp, relocInfo::relocType disp_reloc) { - RelocationHolder rspec; + RelocationHolder rspec = RelocationHolder::none; if (disp_reloc != relocInfo::none) { rspec = Relocation::spec_simple(disp_reloc); } @@ -2060,6 +2060,13 @@ void Assembler::vcvtpd2ps(XMMRegister dst, XMMRegister src, int vector_len) { emit_int16(0x5A, (0xC0 | encode)); } +void Assembler::vcvttps2dq(XMMRegister dst, XMMRegister src, int vector_len) { + assert(vector_len <= AVX_256bit ? VM_Version::supports_avx() : VM_Version::supports_evex(), ""); + InstructionAttr attributes(vector_len, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F, &attributes); + emit_int16(0x5B, (0xC0 | encode)); +} + void Assembler::evcvtqq2ps(XMMRegister dst, XMMRegister src, int vector_len) { assert(UseAVX > 2 && VM_Version::supports_avx512dq(), ""); InstructionAttr attributes(vector_len, /* rex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); @@ -2068,6 +2075,14 @@ void Assembler::evcvtqq2ps(XMMRegister dst, XMMRegister src, int vector_len) { emit_int16(0x5B, (0xC0 | encode)); } +void Assembler::evcvttpd2qq(XMMRegister dst, XMMRegister src, int vector_len) { + assert(UseAVX > 2 && VM_Version::supports_avx512dq(), ""); + InstructionAttr attributes(vector_len, /* rex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F, &attributes); + emit_int16(0x7A, (0xC0 | encode)); +} + void Assembler::evcvtqq2pd(XMMRegister dst, XMMRegister src, int vector_len) { assert(UseAVX > 2 && VM_Version::supports_avx512dq(), ""); InstructionAttr attributes(vector_len, /* rex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); @@ -4306,6 +4321,20 @@ void Assembler::vpmovmskb(Register dst, XMMRegister src, int vec_enc) { emit_int16((unsigned char)0xD7, (0xC0 | encode)); } +void Assembler::vmovmskps(Register dst, XMMRegister src, int vec_enc) { + assert(VM_Version::supports_avx(), ""); + InstructionAttr attributes(vec_enc, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); + int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F, &attributes); + emit_int16(0x50, (0xC0 | encode)); +} + +void Assembler::vmovmskpd(Register dst, XMMRegister src, int vec_enc) { + assert(VM_Version::supports_avx(), ""); + InstructionAttr attributes(vec_enc, /* rex_w */ true, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); + int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F, &attributes); + emit_int16(0x50, (0xC0 | encode)); +} + void Assembler::vpmaskmovd(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { assert((VM_Version::supports_avx2() && vector_len == AVX_256bit), ""); InstructionMark im(this); @@ -11072,6 +11101,10 @@ void Assembler::evpcmpw(KRegister kdst, KRegister mask, XMMRegister nds, Address emit_int8((unsigned char)comparison); } +// Register is a class, but it would be assigned numerical value. +// "0" is assigned for xmm0. Thus we need to ignore -Wnonnull. +PRAGMA_DIAG_PUSH +PRAGMA_NONNULL_IGNORED void Assembler::evprord(XMMRegister dst, KRegister mask, XMMRegister src, int shift, bool merge, int vector_len) { assert(vector_len == AVX_512bit || VM_Version::supports_avx512vl(), ""); InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true); @@ -11095,6 +11128,7 @@ void Assembler::evprorq(XMMRegister dst, KRegister mask, XMMRegister src, int sh int encode = vex_prefix_and_encode(xmm0->encoding(), dst->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F, &attributes); emit_int24(0x72, (0xC0 | encode), shift & 0xFF); } +PRAGMA_DIAG_POP void Assembler::evprorvd(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int vector_len) { assert(vector_len == AVX_512bit || VM_Version::supports_avx512vl(), ""); @@ -11263,6 +11297,20 @@ void Assembler::bzhiq(Register dst, Register src1, Register src2) { emit_int16((unsigned char)0xF5, (0xC0 | encode)); } +void Assembler::pext(Register dst, Register src1, Register src2) { + assert(VM_Version::supports_bmi2(), "bit manipulation instructions not supported"); + InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); + int encode = vex_prefix_and_encode(dst->encoding(), src1->encoding(), src2->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F_38, &attributes); + emit_int16((unsigned char)0xF5, (0xC0 | encode)); +} + +void Assembler::pdep(Register dst, Register src1, Register src2) { + assert(VM_Version::supports_bmi2(), "bit manipulation instructions not supported"); + InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); + int encode = vex_prefix_and_encode(dst->encoding(), src1->encoding(), src2->encoding(), VEX_SIMD_F2, VEX_OPCODE_0F_38, &attributes); + emit_int16((unsigned char)0xF5, (0xC0 | encode)); +} + void Assembler::shlxl(Register dst, Register src1, Register src2) { assert(VM_Version::supports_bmi2(), ""); InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ true); diff --git a/src/hotspot/cpu/x86/assembler_x86.hpp b/src/hotspot/cpu/x86/assembler_x86.hpp index 09b2a392d305801f990beb003460ae9e311accf0..000375f5479f97fb6ece7fa16d05282ecdda8190 100644 --- a/src/hotspot/cpu/x86/assembler_x86.hpp +++ b/src/hotspot/cpu/x86/assembler_x86.hpp @@ -1168,10 +1168,16 @@ private: void vcvtps2pd(XMMRegister dst, XMMRegister src, int vector_len); void vcvtpd2ps(XMMRegister dst, XMMRegister src, int vector_len); + // Convert vector float and int + void vcvttps2dq(XMMRegister dst, XMMRegister src, int vector_len); + // Convert vector long to vector FP void evcvtqq2ps(XMMRegister dst, XMMRegister src, int vector_len); void evcvtqq2pd(XMMRegister dst, XMMRegister src, int vector_len); + // Convert vector double to long + void evcvttpd2qq(XMMRegister dst, XMMRegister src, int vector_len); + // Evex casts with truncation void evpmovwb(XMMRegister dst, XMMRegister src, int vector_len); void evpmovdw(XMMRegister dst, XMMRegister src, int vector_len); @@ -1774,6 +1780,8 @@ private: void pmovmskb(Register dst, XMMRegister src); void vpmovmskb(Register dst, XMMRegister src, int vec_enc); + void vmovmskps(Register dst, XMMRegister src, int vec_enc); + void vmovmskpd(Register dst, XMMRegister src, int vec_enc); void vpmaskmovd(XMMRegister dst, XMMRegister nds, Address src, int vector_len); // SSE 4.1 extract @@ -2176,6 +2184,9 @@ private: void shrxq(Register dst, Register src1, Register src2); void bzhiq(Register dst, Register src1, Register src2); + void pdep(Register dst, Register src1, Register src2); + void pext(Register dst, Register src1, Register src2); + //====================VECTOR ARITHMETIC===================================== // Add Packed Floating-Point Values diff --git a/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp b/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp index 971c2515017df2c9d49d55713802729eb5037a33..eaeeae235f0d2be6ff8f2adface509258fa9e777 100644 --- a/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp @@ -461,7 +461,11 @@ int LIR_Assembler::emit_unwind_handler() { if (method()->is_synchronized()) { monitor_address(0, FrameMap::rax_opr); stub = new MonitorExitStub(FrameMap::rax_opr, true, 0); - __ unlock_object(rdi, rsi, rax, *stub->entry()); + if (UseHeavyMonitors) { + __ jmp(*stub->entry()); + } else { + __ unlock_object(rdi, rsi, rax, *stub->entry()); + } __ bind(*stub->continuation()); } @@ -1184,7 +1188,6 @@ void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_Patch LIR_Address* addr = src->as_address_ptr(); Address from_addr = as_Address(addr); - Register tmp_load_klass = LP64_ONLY(rscratch1) NOT_LP64(noreg); if (addr->base()->type() == T_OBJECT) { __ verify_oop(addr->base()->as_pointer_register()); @@ -1257,11 +1260,7 @@ void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_Patch break; case T_ADDRESS: - if (UseCompressedClassPointers && addr->disp() == oopDesc::klass_offset_in_bytes()) { - __ movl(dest->as_register(), from_addr); - } else { - __ movptr(dest->as_register(), from_addr); - } + __ movptr(dest->as_register(), from_addr); break; case T_INT: __ movl(dest->as_register(), from_addr); @@ -1367,12 +1366,6 @@ void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_Patch if (!UseZGC) { __ verify_oop(dest->as_register()); } - } else if (type == T_ADDRESS && addr->disp() == oopDesc::klass_offset_in_bytes()) { -#ifdef _LP64 - if (UseCompressedClassPointers) { - __ decode_klass_not_null(dest->as_register(), tmp_load_klass); - } -#endif } } @@ -3509,7 +3502,7 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) { Register obj = op->obj_opr()->as_register(); // may not be an oop Register hdr = op->hdr_opr()->as_register(); Register lock = op->lock_opr()->as_register(); - if (!UseFastLocking) { + if (UseHeavyMonitors) { __ jmp(*op->stub()->entry()); } else if (op->code() == lir_lock) { assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header"); @@ -3528,6 +3521,23 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) { __ bind(*op->stub()->continuation()); } +void LIR_Assembler::emit_load_klass(LIR_OpLoadKlass* op) { + Register obj = op->obj()->as_pointer_register(); + Register result = op->result_opr()->as_pointer_register(); + + CodeEmitInfo* info = op->info(); + if (info != NULL) { + add_debug_info_for_null_check_here(info); + } + +#ifdef _LP64 + if (UseCompressedClassPointers) { + __ movl(result, Address(obj, oopDesc::klass_offset_in_bytes())); + __ decode_klass_not_null(result, rscratch1); + } else +#endif + __ movptr(result, Address(obj, oopDesc::klass_offset_in_bytes())); +} void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) { ciMethod* method = op->profiled_method(); diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp index 5e4c8917612982827749f09cdbd6a787e47f40e4..60b0d9205371c321568ca109c26564d634fd6355 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp @@ -485,6 +485,7 @@ void C2_MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmp #if INCLUDE_RTM_OPT if (UseRTMForStackLocks && use_rtm) { + assert(!UseHeavyMonitors, "+UseHeavyMonitors and +UseRTMForStackLocks are mutually exclusive"); rtm_stack_locking(objReg, tmpReg, scrReg, cx2Reg, stack_rtm_counters, method_data, profile_rtm, DONE_LABEL, IsInflated); @@ -495,20 +496,25 @@ void C2_MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmp testptr(tmpReg, markWord::monitor_value); // inflated vs stack-locked|neutral jccb(Assembler::notZero, IsInflated); - // Attempt stack-locking ... - orptr (tmpReg, markWord::unlocked_value); - movptr(Address(boxReg, 0), tmpReg); // Anticipate successful CAS - lock(); - cmpxchgptr(boxReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // Updates tmpReg - jcc(Assembler::equal, DONE_LABEL); // Success - - // Recursive locking. - // The object is stack-locked: markword contains stack pointer to BasicLock. - // Locked by current thread if difference with current SP is less than one page. - subptr(tmpReg, rsp); - // Next instruction set ZFlag == 1 (Success) if difference is less then one page. - andptr(tmpReg, (int32_t) (NOT_LP64(0xFFFFF003) LP64_ONLY(7 - os::vm_page_size())) ); - movptr(Address(boxReg, 0), tmpReg); + if (!UseHeavyMonitors) { + // Attempt stack-locking ... + orptr (tmpReg, markWord::unlocked_value); + movptr(Address(boxReg, 0), tmpReg); // Anticipate successful CAS + lock(); + cmpxchgptr(boxReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // Updates tmpReg + jcc(Assembler::equal, DONE_LABEL); // Success + + // Recursive locking. + // The object is stack-locked: markword contains stack pointer to BasicLock. + // Locked by current thread if difference with current SP is less than one page. + subptr(tmpReg, rsp); + // Next instruction set ZFlag == 1 (Success) if difference is less then one page. + andptr(tmpReg, (int32_t) (NOT_LP64(0xFFFFF003) LP64_ONLY(7 - os::vm_page_size())) ); + movptr(Address(boxReg, 0), tmpReg); + } else { + // Clear ZF so that we take the slow path at the DONE label. objReg is known to be not 0. + testptr(objReg, objReg); + } jmp(DONE_LABEL); bind(IsInflated); @@ -638,6 +644,7 @@ void C2_MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register t #if INCLUDE_RTM_OPT if (UseRTMForStackLocks && use_rtm) { + assert(!UseHeavyMonitors, "+UseHeavyMonitors and +UseRTMForStackLocks are mutually exclusive"); Label L_regular_unlock; movptr(tmpReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // fetch markword andptr(tmpReg, markWord::lock_mask_in_place); // look at 2 lock bits @@ -649,11 +656,15 @@ void C2_MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register t } #endif - cmpptr(Address(boxReg, 0), (int32_t)NULL_WORD); // Examine the displaced header - jcc (Assembler::zero, DONE_LABEL); // 0 indicates recursive stack-lock + if (!UseHeavyMonitors) { + cmpptr(Address(boxReg, 0), (int32_t)NULL_WORD); // Examine the displaced header + jcc (Assembler::zero, DONE_LABEL); // 0 indicates recursive stack-lock + } movptr(tmpReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // Examine the object's markword - testptr(tmpReg, markWord::monitor_value); // Inflated? - jccb (Assembler::zero, Stacked); + if (!UseHeavyMonitors) { + testptr(tmpReg, markWord::monitor_value); // Inflated? + jccb (Assembler::zero, Stacked); + } // It's inflated. #if INCLUDE_RTM_OPT @@ -795,11 +806,12 @@ void C2_MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register t testl (boxReg, 0); // set ICC.ZF=1 to indicate success jmpb (DONE_LABEL); - bind (Stacked); - movptr(tmpReg, Address (boxReg, 0)); // re-fetch - lock(); - cmpxchgptr(tmpReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // Uses RAX which is box - + if (!UseHeavyMonitors) { + bind (Stacked); + movptr(tmpReg, Address (boxReg, 0)); // re-fetch + lock(); + cmpxchgptr(tmpReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // Uses RAX which is box + } #endif bind(DONE_LABEL); } @@ -4059,62 +4071,244 @@ void C2_MacroAssembler::masked_op(int ideal_opc, int mask_len, KRegister dst, } } +/* + * Algorithm for vector D2L and F2I conversions:- + * a) Perform vector D2L/F2I cast. + * b) Choose fast path if none of the result vector lane contains 0x80000000 value. + * It signifies that source value could be any of the special floating point + * values(NaN,-Inf,Inf,Max,-Min). + * c) Set destination to zero if source is NaN value. + * d) Replace 0x80000000 with MaxInt if source lane contains a +ve value. + */ + +void C2_MacroAssembler::vector_castD2L_evex(XMMRegister dst, XMMRegister src, XMMRegister xtmp1, XMMRegister xtmp2, + KRegister ktmp1, KRegister ktmp2, AddressLiteral double_sign_flip, + Register scratch, int vec_enc) { + Label done; + evcvttpd2qq(dst, src, vec_enc); + evmovdqul(xtmp1, k0, double_sign_flip, false, vec_enc, scratch); + evpcmpeqq(ktmp1, xtmp1, dst, vec_enc); + kortestwl(ktmp1, ktmp1); + jccb(Assembler::equal, done); + + vpxor(xtmp2, xtmp2, xtmp2, vec_enc); + evcmppd(ktmp2, k0, src, src, Assembler::UNORD_Q, vec_enc); + evmovdquq(dst, ktmp2, xtmp2, true, vec_enc); + + kxorwl(ktmp1, ktmp1, ktmp2); + evcmppd(ktmp1, ktmp1, src, xtmp2, Assembler::NLT_UQ, vec_enc); + vpternlogq(xtmp2, 0x11, xtmp1, xtmp1, vec_enc); + evmovdquq(dst, ktmp1, xtmp2, true, vec_enc); + bind(done); +} + +void C2_MacroAssembler::vector_castF2I_avx(XMMRegister dst, XMMRegister src, XMMRegister xtmp1, + XMMRegister xtmp2, XMMRegister xtmp3, XMMRegister xtmp4, + AddressLiteral float_sign_flip, Register scratch, int vec_enc) { + Label done; + vcvttps2dq(dst, src, vec_enc); + vmovdqu(xtmp1, float_sign_flip, scratch, vec_enc); + vpcmpeqd(xtmp2, dst, xtmp1, vec_enc); + vptest(xtmp2, xtmp2, vec_enc); + jccb(Assembler::equal, done); + + vpcmpeqd(xtmp4, xtmp4, xtmp4, vec_enc); + vpxor(xtmp1, xtmp1, xtmp4, vec_enc); + + vpxor(xtmp4, xtmp4, xtmp4, vec_enc); + vcmpps(xtmp3, src, src, Assembler::UNORD_Q, vec_enc); + vblendvps(dst, dst, xtmp4, xtmp3, vec_enc); + + // Recompute the mask for remaining special value. + vpxor(xtmp2, xtmp2, xtmp3, vec_enc); + // Extract SRC values corresponding to TRUE mask lanes. + vpand(xtmp4, xtmp2, src, vec_enc); + // Flip mask bits so that MSB bit of MASK lanes corresponding to +ve special + // values are set. + vpxor(xtmp3, xtmp2, xtmp4, vec_enc); + + vblendvps(dst, dst, xtmp1, xtmp3, vec_enc); + bind(done); +} + +void C2_MacroAssembler::vector_castF2I_evex(XMMRegister dst, XMMRegister src, XMMRegister xtmp1, XMMRegister xtmp2, + KRegister ktmp1, KRegister ktmp2, AddressLiteral float_sign_flip, + Register scratch, int vec_enc) { + Label done; + vcvttps2dq(dst, src, vec_enc); + evmovdqul(xtmp1, k0, float_sign_flip, false, vec_enc, scratch); + Assembler::evpcmpeqd(ktmp1, k0, xtmp1, dst, vec_enc); + kortestwl(ktmp1, ktmp1); + jccb(Assembler::equal, done); + + vpxor(xtmp2, xtmp2, xtmp2, vec_enc); + evcmpps(ktmp2, k0, src, src, Assembler::UNORD_Q, vec_enc); + evmovdqul(dst, ktmp2, xtmp2, true, vec_enc); + + kxorwl(ktmp1, ktmp1, ktmp2); + evcmpps(ktmp1, ktmp1, src, xtmp2, Assembler::NLT_UQ, vec_enc); + vpternlogd(xtmp2, 0x11, xtmp1, xtmp1, vec_enc); + evmovdqul(dst, ktmp1, xtmp2, true, vec_enc); + bind(done); +} + #ifdef _LP64 -void C2_MacroAssembler::vector_mask_operation(int opc, Register dst, KRegister mask, - Register tmp, int masklen, int masksize, - int vec_enc) { - if(VM_Version::supports_avx512bw()) { - kmovql(tmp, mask); - } else { - assert(masklen <= 16, ""); - kmovwl(tmp, mask); - } - if (masksize < 16) { - andq(tmp, (((jlong)1 << masklen) - 1)); +void C2_MacroAssembler::vector_long_to_maskvec(XMMRegister dst, Register src, Register rtmp1, + Register rtmp2, XMMRegister xtmp, int mask_len, + int vec_enc) { + int index = 0; + int vindex = 0; + mov64(rtmp1, 0x0101010101010101L); + pdep(rtmp1, src, rtmp1); + if (mask_len > 8) { + movq(rtmp2, src); + vpxor(xtmp, xtmp, xtmp, vec_enc); + movq(xtmp, rtmp1); + } + movq(dst, rtmp1); + + mask_len -= 8; + while (mask_len > 0) { + assert ((mask_len & 0x7) == 0, "mask must be multiple of 8"); + index++; + if ((index % 2) == 0) { + pxor(xtmp, xtmp); + } + mov64(rtmp1, 0x0101010101010101L); + shrq(rtmp2, 8); + pdep(rtmp1, rtmp2, rtmp1); + pinsrq(xtmp, rtmp1, index % 2); + vindex = index / 2; + if (vindex) { + // Write entire 16 byte vector when both 64 bit + // lanes are update to save redundant instructions. + if (index % 2) { + vinsertf128(dst, dst, xtmp, vindex); + } + } else { + vmovdqu(dst, xtmp); + } + mask_len -= 8; } +} + +void C2_MacroAssembler::vector_mask_operation_helper(int opc, Register dst, Register tmp, int masklen) { switch(opc) { case Op_VectorMaskTrueCount: popcntq(dst, tmp); break; case Op_VectorMaskLastTrue: - mov64(dst, -1); - bsrq(tmp, tmp); - cmov(Assembler::notZero, dst, tmp); + if (VM_Version::supports_lzcnt()) { + lzcntq(tmp, tmp); + movl(dst, 63); + subl(dst, tmp); + } else { + movl(dst, -1); + bsrq(tmp, tmp); + cmov32(Assembler::notZero, dst, tmp); + } break; case Op_VectorMaskFirstTrue: - mov64(dst, masklen); - bsfq(tmp, tmp); - cmov(Assembler::notZero, dst, tmp); + if (VM_Version::supports_bmi1()) { + if (masklen < 32) { + orl(tmp, 1 << masklen); + tzcntl(dst, tmp); + } else if (masklen == 32) { + tzcntl(dst, tmp); + } else { + assert(masklen == 64, ""); + tzcntq(dst, tmp); + } + } else { + if (masklen < 32) { + orl(tmp, 1 << masklen); + bsfl(dst, tmp); + } else { + assert(masklen == 32 || masklen == 64, ""); + movl(dst, masklen); + if (masklen == 32) { + bsfl(tmp, tmp); + } else { + bsfq(tmp, tmp); + } + cmov32(Assembler::notZero, dst, tmp); + } + } + break; + case Op_VectorMaskToLong: + assert(dst == tmp, "Dst and tmp should be the same for toLong operations"); break; default: assert(false, "Unhandled mask operation"); } } -void C2_MacroAssembler::vector_mask_operation(int opc, Register dst, XMMRegister mask, XMMRegister xtmp, - XMMRegister xtmp1, Register tmp, int masklen, int masksize, - int vec_enc) { - assert(VM_Version::supports_avx(), ""); - vpxor(xtmp, xtmp, xtmp, vec_enc); - vpsubb(xtmp, xtmp, mask, vec_enc); - vpmovmskb(tmp, xtmp, vec_enc); - if (masksize < 16) { - andq(tmp, (((jlong)1 << masklen) - 1)); +void C2_MacroAssembler::vector_mask_operation(int opc, Register dst, KRegister mask, Register tmp, + int masklen, int masksize, int vec_enc) { + assert(VM_Version::supports_popcnt(), ""); + + if(VM_Version::supports_avx512bw()) { + kmovql(tmp, mask); + } else { + assert(masklen <= 16, ""); + kmovwl(tmp, mask); } - switch(opc) { - case Op_VectorMaskTrueCount: - popcntq(dst, tmp); + + // Mask generated out of partial vector comparisons/replicate/mask manipulation + // operations needs to be clipped. + if (masksize < 16 && opc != Op_VectorMaskFirstTrue) { + andq(tmp, (1 << masklen) - 1); + } + + vector_mask_operation_helper(opc, dst, tmp, masklen); +} + +void C2_MacroAssembler::vector_mask_operation(int opc, Register dst, XMMRegister mask, XMMRegister xtmp, + Register tmp, int masklen, BasicType bt, int vec_enc) { + assert(vec_enc == AVX_128bit && VM_Version::supports_avx() || + vec_enc == AVX_256bit && (VM_Version::supports_avx2() || type2aelembytes(bt) >= 4), ""); + assert(VM_Version::supports_popcnt(), ""); + + bool need_clip = false; + switch(bt) { + case T_BOOLEAN: + // While masks of other types contain 0, -1; boolean masks contain lane values of 0, 1 + vpxor(xtmp, xtmp, xtmp, vec_enc); + vpsubb(xtmp, xtmp, mask, vec_enc); + vpmovmskb(tmp, xtmp, vec_enc); + need_clip = masklen < 16; break; - case Op_VectorMaskLastTrue: - mov64(dst, -1); - bsrq(tmp, tmp); - cmov(Assembler::notZero, dst, tmp); + case T_BYTE: + vpmovmskb(tmp, mask, vec_enc); + need_clip = masklen < 16; break; - case Op_VectorMaskFirstTrue: - mov64(dst, masklen); - bsfq(tmp, tmp); - cmov(Assembler::notZero, dst, tmp); + case T_SHORT: + vpacksswb(xtmp, mask, mask, vec_enc); + if (masklen >= 16) { + vpermpd(xtmp, xtmp, 8, vec_enc); + } + vpmovmskb(tmp, xtmp, Assembler::AVX_128bit); + need_clip = masklen < 16; break; - default: assert(false, "Unhandled mask operation"); + case T_INT: + case T_FLOAT: + vmovmskps(tmp, mask, vec_enc); + need_clip = masklen < 4; + break; + case T_LONG: + case T_DOUBLE: + vmovmskpd(tmp, mask, vec_enc); + need_clip = masklen < 2; + break; + default: assert(false, "Unhandled type, %s", type2name(bt)); + } + + // Mask generated out of partial vector comparisons/replicate/mask manipulation + // operations needs to be clipped. + if (need_clip && opc != Op_VectorMaskFirstTrue) { + // need_clip implies masklen < 32 + andq(tmp, (1 << masklen) - 1); } + + vector_mask_operation_helper(opc, dst, tmp, masklen); } #endif diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp index 8efa36a8101db5843323e66a00ffbbe1cf18433a..301a072938ba024cec1a4e980afb4a71660b5b7c 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp @@ -224,11 +224,16 @@ public: public: #ifdef _LP64 + void vector_mask_operation_helper(int opc, Register dst, Register tmp, int masklen); + void vector_mask_operation(int opc, Register dst, KRegister mask, Register tmp, int masklen, int masksize, int vec_enc); - void vector_mask_operation(int opc, Register dst, XMMRegister mask, XMMRegister xtmp, XMMRegister xtmp1, - Register tmp, int masklen, int masksize, int vec_enc); + void vector_mask_operation(int opc, Register dst, XMMRegister mask, XMMRegister xtmp, + Register tmp, int masklen, BasicType bt, int vec_enc); + void vector_long_to_maskvec(XMMRegister dst, Register src, Register rtmp1, + Register rtmp2, XMMRegister xtmp, int mask_len, int vec_enc); #endif + void string_indexof_char(Register str1, Register cnt1, Register ch, Register result, XMMRegister vec1, XMMRegister vec2, XMMRegister vec3, Register tmp); @@ -288,4 +293,16 @@ public: void masked_op(int ideal_opc, int mask_len, KRegister dst, KRegister src1, KRegister src2); + + void vector_castF2I_avx(XMMRegister dst, XMMRegister src, XMMRegister xtmp1, + XMMRegister xtmp2, XMMRegister xtmp3, XMMRegister xtmp4, + AddressLiteral float_sign_flip, Register scratch, int vec_enc); + + void vector_castF2I_evex(XMMRegister dst, XMMRegister src, XMMRegister xtmp1, XMMRegister xtmp2, + KRegister ktmp1, KRegister ktmp2, AddressLiteral float_sign_flip, + Register scratch, int vec_enc); + + void vector_castD2L_evex(XMMRegister dst, XMMRegister src, XMMRegister xtmp1, XMMRegister xtmp2, + KRegister ktmp1, KRegister ktmp2, AddressLiteral double_sign_flip, + Register scratch, int vec_enc); #endif // CPU_X86_C2_MACROASSEMBLER_X86_HPP diff --git a/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp index 645c2fec8bd9e9a49c7ae77293cf680ddf1ac8cd..6525b13c5c253e54b3b2a4bce288a506ed582304 100644 --- a/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp @@ -298,7 +298,7 @@ void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, const Register cardtable = tmp2; __ movptr(card_addr, store_addr); - __ shrptr(card_addr, CardTable::card_shift); + __ shrptr(card_addr, CardTable::card_shift()); // Do not use ExternalAddress to load 'byte_map_base', since 'byte_map_base' is NOT // a valid address and therefore is not properly handled by the relocation code. __ movptr(cardtable, (intptr_t)ct->card_table()->byte_map_base()); @@ -540,7 +540,7 @@ void G1BarrierSetAssembler::generate_c1_post_barrier_runtime_stub(StubAssembler* const Register card_addr = rcx; __ load_parameter(0, card_addr); - __ shrptr(card_addr, CardTable::card_shift); + __ shrptr(card_addr, CardTable::card_shift()); // Do not use ExternalAddress to load 'byte_map_base', since 'byte_map_base' is NOT // a valid address and therefore is not properly handled by the relocation code. __ movptr(cardtable, (intptr_t)ct->card_table()->byte_map_base()); diff --git a/src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.cpp index 9b2d2c5efedcee2eba8c4a90adfe02b7e054dd7c..7fc36ffae8f0ba32a025bbf2cf81aa71eb85c378 100644 --- a/src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.cpp @@ -60,8 +60,8 @@ void CardTableBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembl #ifdef _LP64 __ leaq(end, Address(addr, count, TIMES_OOP, 0)); // end == addr+count*oop_size __ subptr(end, BytesPerHeapOop); // end - 1 to make inclusive - __ shrptr(addr, CardTable::card_shift); - __ shrptr(end, CardTable::card_shift); + __ shrptr(addr, CardTable::card_shift()); + __ shrptr(end, CardTable::card_shift()); __ subptr(end, addr); // end --> cards count __ mov64(tmp, disp); @@ -72,8 +72,8 @@ __ BIND(L_loop); __ jcc(Assembler::greaterEqual, L_loop); #else __ lea(end, Address(addr, count, Address::times_ptr, -wordSize)); - __ shrptr(addr, CardTable::card_shift); - __ shrptr(end, CardTable::card_shift); + __ shrptr(addr, CardTable::card_shift()); + __ shrptr(end, CardTable::card_shift()); __ subptr(end, addr); // end --> count __ BIND(L_loop); Address cardtable(addr, count, Address::times_1, disp); @@ -93,7 +93,7 @@ void CardTableBarrierSetAssembler::store_check(MacroAssembler* masm, Register ob CardTableBarrierSet* ctbs = barrier_set_cast(bs); CardTable* ct = ctbs->card_table(); - __ shrptr(obj, CardTable::card_shift); + __ shrptr(obj, CardTable::card_shift()); Address card_addr; diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index b44e8ee15c84183d10ad003b74b0b6f2af91c9f8..36f480069749852497da30b6d6825d6e10f98a26 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -2546,6 +2546,15 @@ void MacroAssembler::vmovdqu(XMMRegister dst, AddressLiteral src, Register scrat } } +void MacroAssembler::vmovdqu(XMMRegister dst, AddressLiteral src, Register scratch_reg, int vector_len) { + assert(vector_len <= AVX_256bit, "AVX2 vector length"); + if (vector_len == AVX_256bit) { + vmovdqu(dst, src, scratch_reg); + } else { + movdqu(dst, src, scratch_reg); + } +} + void MacroAssembler::kmov(KRegister dst, Address src) { if (VM_Version::supports_avx512bw()) { kmovql(dst, src); @@ -5012,7 +5021,7 @@ void MacroAssembler::xmm_clear_mem(Register base, Register cnt, Register rtmp, X // cnt - number of qwords (8-byte words). // base - start address, qword aligned. Label L_zero_64_bytes, L_loop, L_sloop, L_tail, L_end; - bool use64byteVector = MaxVectorSize == 64 && AVX3Threshold == 0; + bool use64byteVector = (MaxVectorSize == 64) && (VM_Version::avx3_threshold() == 0); if (use64byteVector) { vpxor(xtmp, xtmp, xtmp, AVX_512bit); } else if (MaxVectorSize >= 32) { @@ -5076,7 +5085,7 @@ void MacroAssembler::xmm_clear_mem(Register base, Register cnt, Register rtmp, X // Clearing constant sized memory using YMM/ZMM registers. void MacroAssembler::clear_mem(Register base, int cnt, Register rtmp, XMMRegister xtmp, KRegister mask) { assert(UseAVX > 2 && VM_Version::supports_avx512vlbw(), ""); - bool use64byteVector = MaxVectorSize > 32 && AVX3Threshold == 0; + bool use64byteVector = (MaxVectorSize > 32) && (VM_Version::avx3_threshold() == 0); int vector64_count = (cnt & (~0x7)) >> 3; cnt = cnt & 0x7; @@ -5319,8 +5328,8 @@ void MacroAssembler::generate_fill(BasicType t, bool aligned, // Fill 64-byte chunks Label L_fill_64_bytes_loop_avx3, L_check_fill_64_bytes_avx2; - // If number of bytes to fill < AVX3Threshold, perform fill using AVX2 - cmpl(count, AVX3Threshold); + // If number of bytes to fill < VM_Version::avx3_threshold(), perform fill using AVX2 + cmpl(count, VM_Version::avx3_threshold()); jccb(Assembler::below, L_check_fill_64_bytes_avx2); vpbroadcastd(xtmp, xtmp, Assembler::AVX_512bit); @@ -7030,7 +7039,7 @@ void MacroAssembler::fold512bit_crc32_avx512(XMMRegister xcrc, XMMRegister xK, X // Helper function for AVX 512 CRC32 // Compute CRC32 for < 256B buffers -void MacroAssembler::kernel_crc32_avx512_256B(Register crc, Register buf, Register len, Register key, Register pos, +void MacroAssembler::kernel_crc32_avx512_256B(Register crc, Register buf, Register len, Register table, Register pos, Register tmp1, Register tmp2, Label& L_barrett, Label& L_16B_reduction_loop, Label& L_get_last_two_xmms, Label& L_128_done, Label& L_cleanup) { @@ -7043,7 +7052,7 @@ void MacroAssembler::kernel_crc32_avx512_256B(Register crc, Register buf, Regist jcc(Assembler::less, L_less_than_32); // if there is, load the constants - movdqu(xmm10, Address(key, 1 * 16)); //rk1 and rk2 in xmm10 + movdqu(xmm10, Address(table, 1 * 16)); //rk1 and rk2 in xmm10 movdl(xmm0, crc); // get the initial crc value movdqu(xmm7, Address(buf, pos, Address::times_1, 0 * 16)); //load the plaintext pxor(xmm7, xmm0); @@ -7070,7 +7079,7 @@ void MacroAssembler::kernel_crc32_avx512_256B(Register crc, Register buf, Regist pxor(xmm7, xmm0); //xor the initial crc value addl(pos, 16); subl(len, 16); - movdqu(xmm10, Address(key, 1 * 16)); // rk1 and rk2 in xmm10 + movdqu(xmm10, Address(table, 1 * 16)); // rk1 and rk2 in xmm10 jmp(L_get_last_two_xmms); bind(L_less_than_16_left); @@ -7190,12 +7199,17 @@ void MacroAssembler::kernel_crc32_avx512_256B(Register crc, Register buf, Regist * param crc register containing existing CRC (32-bit) * param buf register pointing to input byte buffer (byte*) * param len register containing number of bytes +* param table address of crc or crc32c table * param tmp1 scratch register * param tmp2 scratch register * return rax result register +* +* This routine is identical for crc32c with the exception of the precomputed constant +* table which will be passed as the table argument. The calculation steps are +* the same for both variants. */ -void MacroAssembler::kernel_crc32_avx512(Register crc, Register buf, Register len, Register key, Register tmp1, Register tmp2) { - assert_different_registers(crc, buf, len, key, tmp1, tmp2, rax); +void MacroAssembler::kernel_crc32_avx512(Register crc, Register buf, Register len, Register table, Register tmp1, Register tmp2) { + assert_different_registers(crc, buf, len, table, tmp1, tmp2, rax, r12); Label L_tail, L_tail_restore, L_tail_loop, L_exit, L_align_loop, L_aligned; Label L_fold_tail, L_fold_128b, L_fold_512b, L_fold_512b_loop, L_fold_tail_loop; @@ -7210,8 +7224,6 @@ void MacroAssembler::kernel_crc32_avx512(Register crc, Register buf, Register le // For EVEX with VL and BW, provide a standard mask, VL = 128 will guide the merge // context for the registers used, where all instructions below are using 128-bit mode // On EVEX without VL and BW, these instructions will all be AVX. - lea(key, ExternalAddress(StubRoutines::x86::crc_table_avx512_addr())); - notl(crc); movl(pos, 0); // check if smaller than 256B @@ -7225,7 +7237,7 @@ void MacroAssembler::kernel_crc32_avx512(Register crc, Register buf, Register le evmovdquq(xmm0, Address(buf, pos, Address::times_1, 0 * 64), Assembler::AVX_512bit); evmovdquq(xmm4, Address(buf, pos, Address::times_1, 1 * 64), Assembler::AVX_512bit); evpxorq(xmm0, xmm0, xmm10, Assembler::AVX_512bit); - evbroadcasti32x4(xmm10, Address(key, 2 * 16), Assembler::AVX_512bit); //zmm10 has rk3 and rk4 + evbroadcasti32x4(xmm10, Address(table, 2 * 16), Assembler::AVX_512bit); //zmm10 has rk3 and rk4 subl(len, 256); cmpl(len, 256); @@ -7233,7 +7245,7 @@ void MacroAssembler::kernel_crc32_avx512(Register crc, Register buf, Register le evmovdquq(xmm7, Address(buf, pos, Address::times_1, 2 * 64), Assembler::AVX_512bit); evmovdquq(xmm8, Address(buf, pos, Address::times_1, 3 * 64), Assembler::AVX_512bit); - evbroadcasti32x4(xmm16, Address(key, 0 * 16), Assembler::AVX_512bit); //zmm16 has rk-1 and rk-2 + evbroadcasti32x4(xmm16, Address(table, 0 * 16), Assembler::AVX_512bit); //zmm16 has rk-1 and rk-2 subl(len, 256); bind(L_fold_256_B_loop); @@ -7279,8 +7291,8 @@ void MacroAssembler::kernel_crc32_avx512(Register crc, Register buf, Register le // at this point, the buffer pointer is pointing at the last y Bytes of the buffer, where 0 <= y < 128 // the 128B of folded data is in 8 of the xmm registers : xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7 bind(L_fold_128_B_register); - evmovdquq(xmm16, Address(key, 5 * 16), Assembler::AVX_512bit); // multiply by rk9-rk16 - evmovdquq(xmm11, Address(key, 9 * 16), Assembler::AVX_512bit); // multiply by rk17-rk20, rk1,rk2, 0,0 + evmovdquq(xmm16, Address(table, 5 * 16), Assembler::AVX_512bit); // multiply by rk9-rk16 + evmovdquq(xmm11, Address(table, 9 * 16), Assembler::AVX_512bit); // multiply by rk17-rk20, rk1,rk2, 0,0 evpclmulqdq(xmm1, xmm0, xmm16, 0x01, Assembler::AVX_512bit); evpclmulqdq(xmm2, xmm0, xmm16, 0x10, Assembler::AVX_512bit); // save last that has no multiplicand @@ -7289,7 +7301,7 @@ void MacroAssembler::kernel_crc32_avx512(Register crc, Register buf, Register le evpclmulqdq(xmm5, xmm4, xmm11, 0x01, Assembler::AVX_512bit); evpclmulqdq(xmm6, xmm4, xmm11, 0x10, Assembler::AVX_512bit); // Needed later in reduction loop - movdqu(xmm10, Address(key, 1 * 16)); + movdqu(xmm10, Address(table, 1 * 16)); vpternlogq(xmm1, 0x96, xmm2, xmm5, Assembler::AVX_512bit); // xor ABC vpternlogq(xmm1, 0x96, xmm6, xmm7, Assembler::AVX_512bit); // xor ABC @@ -7305,7 +7317,7 @@ void MacroAssembler::kernel_crc32_avx512(Register crc, Register buf, Register le jcc(Assembler::less, L_final_reduction_for_128); bind(L_16B_reduction_loop); - vpclmulqdq(xmm8, xmm7, xmm10, 0x1); + vpclmulqdq(xmm8, xmm7, xmm10, 0x01); vpclmulqdq(xmm7, xmm7, xmm10, 0x10); vpxor(xmm7, xmm7, xmm8, Assembler::AVX_128bit); movdqu(xmm0, Address(buf, pos, Address::times_1, 0 * 16)); @@ -7336,14 +7348,14 @@ void MacroAssembler::kernel_crc32_avx512(Register crc, Register buf, Register le vpshufb(xmm2, xmm2, xmm0, Assembler::AVX_128bit); blendvpb(xmm2, xmm2, xmm1, xmm0, Assembler::AVX_128bit); - vpclmulqdq(xmm8, xmm7, xmm10, 0x1); + vpclmulqdq(xmm8, xmm7, xmm10, 0x01); vpclmulqdq(xmm7, xmm7, xmm10, 0x10); vpxor(xmm7, xmm7, xmm8, Assembler::AVX_128bit); vpxor(xmm7, xmm7, xmm2, Assembler::AVX_128bit); bind(L_128_done); // compute crc of a 128-bit value - movdqu(xmm10, Address(key, 3 * 16)); + movdqu(xmm10, Address(table, 3 * 16)); movdqu(xmm0, xmm7); // 64b fold @@ -7359,14 +7371,14 @@ void MacroAssembler::kernel_crc32_avx512(Register crc, Register buf, Register le jmp(L_barrett); bind(L_less_than_256); - kernel_crc32_avx512_256B(crc, buf, len, key, pos, tmp1, tmp2, L_barrett, L_16B_reduction_loop, L_get_last_two_xmms, L_128_done, L_cleanup); + kernel_crc32_avx512_256B(crc, buf, len, table, pos, tmp1, tmp2, L_barrett, L_16B_reduction_loop, L_get_last_two_xmms, L_128_done, L_cleanup); //barrett reduction bind(L_barrett); vpand(xmm7, xmm7, ExternalAddress(StubRoutines::x86::crc_by128_masks_avx512_addr() + 1 * 16), Assembler::AVX_128bit, tmp2); movdqu(xmm1, xmm7); movdqu(xmm2, xmm7); - movdqu(xmm10, Address(key, 4 * 16)); + movdqu(xmm10, Address(table, 4 * 16)); pclmulqdq(xmm7, xmm10, 0x0); pxor(xmm7, xmm2); @@ -7378,7 +7390,6 @@ void MacroAssembler::kernel_crc32_avx512(Register crc, Register buf, Register le pextrd(crc, xmm7, 2); bind(L_cleanup); - notl(crc); // ~c addptr(rsp, 16 * 2 + 8); pop(r12); } @@ -8706,6 +8717,7 @@ void MacroAssembler::generate_fill_avx3(BasicType type, Register to, Register va Label L_fill_zmm_sequence; int shift = -1; + int avx3threshold = VM_Version::avx3_threshold(); switch(type) { case T_BYTE: shift = 0; break; @@ -8721,10 +8733,10 @@ void MacroAssembler::generate_fill_avx3(BasicType type, Register to, Register va fatal("Unhandled type: %s\n", type2name(type)); } - if (AVX3Threshold != 0 || MaxVectorSize == 32) { + if ((avx3threshold != 0) || (MaxVectorSize == 32)) { if (MaxVectorSize == 64) { - cmpq(count, AVX3Threshold >> shift); + cmpq(count, avx3threshold >> shift); jcc(Assembler::greater, L_fill_zmm_sequence); } @@ -9035,4 +9047,5 @@ void MacroAssembler::get_thread(Register thread) { } } + #endif // !WIN32 || _LP64 diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.hpp b/src/hotspot/cpu/x86/macroAssembler_x86.hpp index 392ff61d87fd4351f90a300d16aca5fcc45cd762..5c101b496875eb22ac4f622db7dbbdf06e4299af 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp @@ -1117,6 +1117,8 @@ public: void vmovdqu(XMMRegister dst, Address src); void vmovdqu(XMMRegister dst, XMMRegister src); void vmovdqu(XMMRegister dst, AddressLiteral src, Register scratch_reg = rscratch1); + void vmovdqu(XMMRegister dst, AddressLiteral src, Register scratch_reg, int vector_len); + // AVX512 Unaligned void evmovdqu(BasicType type, KRegister kmask, Address dst, XMMRegister src, int vector_len); diff --git a/src/hotspot/cpu/x86/macroAssembler_x86_arrayCopy_avx3.cpp b/src/hotspot/cpu/x86/macroAssembler_x86_arrayCopy_avx3.cpp index cbf4db8966b643afea4d6881bdd54168eddcd9c4..79ff020a54d0ab7e559e5b8c7326d6d7ae3e0e99 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86_arrayCopy_avx3.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86_arrayCopy_avx3.cpp @@ -114,7 +114,7 @@ void MacroAssembler::arraycopy_avx3_special_cases_conjoint(XMMRegister xmm, KReg bool use64byteVector, Label& L_entry, Label& L_exit) { Label L_entry_64, L_entry_96, L_entry_128; Label L_entry_160, L_entry_192; - bool avx3 = MaxVectorSize > 32 && AVX3Threshold == 0; + bool avx3 = (MaxVectorSize > 32) && (VM_Version::avx3_threshold() == 0); int size_mat[][6] = { /* T_BYTE */ {32 , 64, 96 , 128 , 160 , 192 }, diff --git a/src/hotspot/cpu/x86/rdtsc_x86.cpp b/src/hotspot/cpu/x86/rdtsc_x86.cpp index a4e743cc2dfbfaf9ca2ebda349cbd2cad6d61091..c6109ccdefec75be712e06f15345e74cf4a3890b 100644 --- a/src/hotspot/cpu/x86/rdtsc_x86.cpp +++ b/src/hotspot/cpu/x86/rdtsc_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ #include "runtime/globals_extension.hpp" #include "runtime/orderAccess.hpp" #include "runtime/thread.inline.hpp" -#include "vm_version_ext_x86.hpp" +#include "vm_version_x86.hpp" // The following header contains the implementations of rdtsc() #include OS_CPU_HEADER_INLINE(os) @@ -101,9 +101,9 @@ static jlong initialize_frequency() { // if platform supports invariant tsc, // apply higher resolution and granularity for conversion calculations - if (VM_Version_Ext::supports_tscinv_ext()) { + if (VM_Version::supports_tscinv_ext()) { // for invariant tsc platforms, take the maximum qualified cpu frequency - tsc_freq = (double)VM_Version_Ext::maximum_qualified_cpu_frequency(); + tsc_freq = (double)VM_Version::maximum_qualified_cpu_frequency(); os_to_tsc_conv_factor = tsc_freq / os_freq; } else { // use measurements to estimate @@ -171,7 +171,7 @@ static bool ergonomics() { } bool Rdtsc::is_supported() { - return VM_Version_Ext::supports_tscinv_ext(); + return VM_Version::supports_tscinv_ext(); } bool Rdtsc::is_elapsed_counter_enabled() { @@ -198,7 +198,7 @@ bool Rdtsc::initialize() { static bool initialized = false; if (!initialized) { assert(!rdtsc_elapsed_counter_enabled, "invariant"); - VM_Version_Ext::initialize(); + VM_Version::initialize_tsc(); assert(0 == tsc_frequency, "invariant"); assert(0 == _epoch, "invariant"); bool result = initialize_elapsed_counter(); // init hw diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp index a00af0e4af0d61c1ccf64598a5ef314a3a2e2930..e139b3cf6eb7d33fa3872178b891e0eeaf83f88b 100644 --- a/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp +++ b/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp @@ -1705,36 +1705,41 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // Load the oop from the handle __ movptr(obj_reg, Address(oop_handle_reg, 0)); - // Load immediate 1 into swap_reg %rax, - __ movptr(swap_reg, 1); - - // Load (object->mark() | 1) into swap_reg %rax, - __ orptr(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); - - // Save (object->mark() | 1) into BasicLock's displaced header - __ movptr(Address(lock_reg, mark_word_offset), swap_reg); - - // src -> dest iff dest == rax, else rax, <- dest - // *obj_reg = lock_reg iff *obj_reg == rax, else rax, = *(obj_reg) - __ lock(); - __ cmpxchgptr(lock_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); - __ jcc(Assembler::equal, lock_done); - - // Test if the oopMark is an obvious stack pointer, i.e., - // 1) (mark & 3) == 0, and - // 2) rsp <= mark < mark + os::pagesize() - // These 3 tests can be done by evaluating the following - // expression: ((mark - rsp) & (3 - os::vm_page_size())), - // assuming both stack pointer and pagesize have their - // least significant 2 bits clear. - // NOTE: the oopMark is in swap_reg %rax, as the result of cmpxchg - - __ subptr(swap_reg, rsp); - __ andptr(swap_reg, 3 - os::vm_page_size()); - - // Save the test result, for recursive case, the result is zero - __ movptr(Address(lock_reg, mark_word_offset), swap_reg); - __ jcc(Assembler::notEqual, slow_path_lock); + if (!UseHeavyMonitors) { + // Load immediate 1 into swap_reg %rax, + __ movptr(swap_reg, 1); + + // Load (object->mark() | 1) into swap_reg %rax, + __ orptr(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); + + // Save (object->mark() | 1) into BasicLock's displaced header + __ movptr(Address(lock_reg, mark_word_offset), swap_reg); + + // src -> dest iff dest == rax, else rax, <- dest + // *obj_reg = lock_reg iff *obj_reg == rax, else rax, = *(obj_reg) + __ lock(); + __ cmpxchgptr(lock_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); + __ jcc(Assembler::equal, lock_done); + + // Test if the oopMark is an obvious stack pointer, i.e., + // 1) (mark & 3) == 0, and + // 2) rsp <= mark < mark + os::pagesize() + // These 3 tests can be done by evaluating the following + // expression: ((mark - rsp) & (3 - os::vm_page_size())), + // assuming both stack pointer and pagesize have their + // least significant 2 bits clear. + // NOTE: the oopMark is in swap_reg %rax, as the result of cmpxchg + + __ subptr(swap_reg, rsp); + __ andptr(swap_reg, 3 - os::vm_page_size()); + + // Save the test result, for recursive case, the result is zero + __ movptr(Address(lock_reg, mark_word_offset), swap_reg); + __ jcc(Assembler::notEqual, slow_path_lock); + } else { + __ jmp(slow_path_lock); + } + // Slow path will re-enter here __ bind(lock_done); } @@ -1852,28 +1857,32 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // Get locked oop from the handle we passed to jni __ movptr(obj_reg, Address(oop_handle_reg, 0)); - // Simple recursive lock? + if (!UseHeavyMonitors) { + // Simple recursive lock? - __ cmpptr(Address(rbp, lock_slot_rbp_offset), (int32_t)NULL_WORD); - __ jcc(Assembler::equal, done); + __ cmpptr(Address(rbp, lock_slot_rbp_offset), (int32_t)NULL_WORD); + __ jcc(Assembler::equal, done); - // Must save rax, if if it is live now because cmpxchg must use it - if (ret_type != T_FLOAT && ret_type != T_DOUBLE && ret_type != T_VOID) { - save_native_result(masm, ret_type, stack_slots); - } + // Must save rax, if if it is live now because cmpxchg must use it + if (ret_type != T_FLOAT && ret_type != T_DOUBLE && ret_type != T_VOID) { + save_native_result(masm, ret_type, stack_slots); + } - // get old displaced header - __ movptr(rbx, Address(rbp, lock_slot_rbp_offset)); + // get old displaced header + __ movptr(rbx, Address(rbp, lock_slot_rbp_offset)); - // get address of the stack lock - __ lea(rax, Address(rbp, lock_slot_rbp_offset)); + // get address of the stack lock + __ lea(rax, Address(rbp, lock_slot_rbp_offset)); - // Atomic swap old header if oop still contains the stack lock - // src -> dest iff dest == rax, else rax, <- dest - // *obj_reg = rbx, iff *obj_reg == rax, else rax, = *(obj_reg) - __ lock(); - __ cmpxchgptr(rbx, Address(obj_reg, oopDesc::mark_offset_in_bytes())); - __ jcc(Assembler::notEqual, slow_path_unlock); + // Atomic swap old header if oop still contains the stack lock + // src -> dest iff dest == rax, else rax, <- dest + // *obj_reg = rbx, iff *obj_reg == rax, else rax, = *(obj_reg) + __ lock(); + __ cmpxchgptr(rbx, Address(obj_reg, oopDesc::mark_offset_in_bytes())); + __ jcc(Assembler::notEqual, slow_path_unlock); + } else { + __ jmp(slow_path_unlock); + } // slow path re-enters here __ bind(unlock_done); diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp index f78ec39c25e42c7dc8a3c3d55e776546cec92091..9ff40e943ba6e4ec9c1a851323e38b6b98b24f53 100644 --- a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp +++ b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp @@ -1918,37 +1918,41 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // Load the oop from the handle __ movptr(obj_reg, Address(oop_handle_reg, 0)); - // Load immediate 1 into swap_reg %rax - __ movl(swap_reg, 1); - - // Load (object->mark() | 1) into swap_reg %rax - __ orptr(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); - - // Save (object->mark() | 1) into BasicLock's displaced header - __ movptr(Address(lock_reg, mark_word_offset), swap_reg); - - // src -> dest iff dest == rax else rax <- dest - __ lock(); - __ cmpxchgptr(lock_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); - __ jcc(Assembler::equal, lock_done); - - // Hmm should this move to the slow path code area??? - - // Test if the oopMark is an obvious stack pointer, i.e., - // 1) (mark & 3) == 0, and - // 2) rsp <= mark < mark + os::pagesize() - // These 3 tests can be done by evaluating the following - // expression: ((mark - rsp) & (3 - os::vm_page_size())), - // assuming both stack pointer and pagesize have their - // least significant 2 bits clear. - // NOTE: the oopMark is in swap_reg %rax as the result of cmpxchg - - __ subptr(swap_reg, rsp); - __ andptr(swap_reg, 3 - os::vm_page_size()); - - // Save the test result, for recursive case, the result is zero - __ movptr(Address(lock_reg, mark_word_offset), swap_reg); - __ jcc(Assembler::notEqual, slow_path_lock); + if (!UseHeavyMonitors) { + // Load immediate 1 into swap_reg %rax + __ movl(swap_reg, 1); + + // Load (object->mark() | 1) into swap_reg %rax + __ orptr(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); + + // Save (object->mark() | 1) into BasicLock's displaced header + __ movptr(Address(lock_reg, mark_word_offset), swap_reg); + + // src -> dest iff dest == rax else rax <- dest + __ lock(); + __ cmpxchgptr(lock_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); + __ jcc(Assembler::equal, lock_done); + + // Hmm should this move to the slow path code area??? + + // Test if the oopMark is an obvious stack pointer, i.e., + // 1) (mark & 3) == 0, and + // 2) rsp <= mark < mark + os::pagesize() + // These 3 tests can be done by evaluating the following + // expression: ((mark - rsp) & (3 - os::vm_page_size())), + // assuming both stack pointer and pagesize have their + // least significant 2 bits clear. + // NOTE: the oopMark is in swap_reg %rax as the result of cmpxchg + + __ subptr(swap_reg, rsp); + __ andptr(swap_reg, 3 - os::vm_page_size()); + + // Save the test result, for recursive case, the result is zero + __ movptr(Address(lock_reg, mark_word_offset), swap_reg); + __ jcc(Assembler::notEqual, slow_path_lock); + } else { + __ jmp(slow_path_lock); + } // Slow path will re-enter here @@ -2055,26 +2059,30 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, __ movptr(obj_reg, Address(oop_handle_reg, 0)); Label done; - // Simple recursive lock? - __ cmpptr(Address(rsp, lock_slot_offset * VMRegImpl::stack_slot_size), (int32_t)NULL_WORD); - __ jcc(Assembler::equal, done); + if (!UseHeavyMonitors) { + // Simple recursive lock? + __ cmpptr(Address(rsp, lock_slot_offset * VMRegImpl::stack_slot_size), (int32_t)NULL_WORD); + __ jcc(Assembler::equal, done); - // Must save rax if if it is live now because cmpxchg must use it - if (ret_type != T_FLOAT && ret_type != T_DOUBLE && ret_type != T_VOID) { - save_native_result(masm, ret_type, stack_slots); - } + // Must save rax if if it is live now because cmpxchg must use it + if (ret_type != T_FLOAT && ret_type != T_DOUBLE && ret_type != T_VOID) { + save_native_result(masm, ret_type, stack_slots); + } - // get address of the stack lock - __ lea(rax, Address(rsp, lock_slot_offset * VMRegImpl::stack_slot_size)); - // get old displaced header - __ movptr(old_hdr, Address(rax, 0)); + // get address of the stack lock + __ lea(rax, Address(rsp, lock_slot_offset * VMRegImpl::stack_slot_size)); + // get old displaced header + __ movptr(old_hdr, Address(rax, 0)); - // Atomic swap old header if oop still contains the stack lock - __ lock(); - __ cmpxchgptr(old_hdr, Address(obj_reg, oopDesc::mark_offset_in_bytes())); - __ jcc(Assembler::notEqual, slow_path_unlock); + // Atomic swap old header if oop still contains the stack lock + __ lock(); + __ cmpxchgptr(old_hdr, Address(obj_reg, oopDesc::mark_offset_in_bytes())); + __ jcc(Assembler::notEqual, slow_path_unlock); + } else { + __ jmp(slow_path_unlock); + } // slow path re-enters here __ bind(unlock_done); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp index f5ef24ddf4cecfc19794c57155364d4aa2a32cac..863089751169fdcc2be3306877aeb4adbf8ac87d 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp @@ -1384,8 +1384,8 @@ class StubGenerator: public StubCodeGenerator { __ align(CodeEntryAlignment); StubCodeMark mark(this, "StubRoutines", name); address start = __ pc(); - - bool use64byteVector = MaxVectorSize > 32 && AVX3Threshold == 0; + int avx3threshold = VM_Version::avx3_threshold(); + bool use64byteVector = (MaxVectorSize > 32) && (avx3threshold == 0); Label L_main_loop, L_main_loop_64bytes, L_tail, L_tail64, L_exit, L_entry; Label L_repmovs, L_main_pre_loop, L_main_pre_loop_64bytes, L_pre_main_post_64; const Register from = rdi; // source array address @@ -1448,7 +1448,7 @@ class StubGenerator: public StubCodeGenerator { // PRE-MAIN-POST loop for aligned copy. __ BIND(L_entry); - if (AVX3Threshold != 0) { + if (avx3threshold != 0) { __ cmpq(count, threshold[shift]); if (MaxVectorSize == 64) { // Copy using 64 byte vectors. @@ -1460,7 +1460,7 @@ class StubGenerator: public StubCodeGenerator { } } - if (MaxVectorSize < 64 || AVX3Threshold != 0) { + if ((MaxVectorSize < 64) || (avx3threshold != 0)) { // Partial copy to make dst address 32 byte aligned. __ movq(temp2, to); __ andq(temp2, 31); @@ -1603,7 +1603,8 @@ class StubGenerator: public StubCodeGenerator { StubCodeMark mark(this, "StubRoutines", name); address start = __ pc(); - bool use64byteVector = MaxVectorSize > 32 && AVX3Threshold == 0; + int avx3threshold = VM_Version::avx3_threshold(); + bool use64byteVector = (MaxVectorSize > 32) && (avx3threshold == 0); Label L_main_pre_loop, L_main_pre_loop_64bytes, L_pre_main_post_64; Label L_main_loop, L_main_loop_64bytes, L_tail, L_tail64, L_exit, L_entry; @@ -1668,12 +1669,12 @@ class StubGenerator: public StubCodeGenerator { // PRE-MAIN-POST loop for aligned copy. __ BIND(L_entry); - if (MaxVectorSize > 32 && AVX3Threshold != 0) { + if ((MaxVectorSize > 32) && (avx3threshold != 0)) { __ cmpq(temp1, threshold[shift]); __ jcc(Assembler::greaterEqual, L_pre_main_post_64); } - if (MaxVectorSize < 64 || AVX3Threshold != 0) { + if ((MaxVectorSize < 64) || (avx3threshold != 0)) { // Partial copy to make dst address 32 byte aligned. __ leaq(temp2, Address(to, temp1, (Address::ScaleFactor)(shift), 0)); __ andq(temp2, 31); @@ -6260,6 +6261,9 @@ address generate_avx_ghash_processBlocks() { __ cmpl(length, 63); __ jcc(Assembler::lessEqual, L_finalBit); + __ mov64(rax, 0x0000ffffffffffff); + __ kmovql(k2, rax); + __ align32(); __ BIND(L_process64Loop); @@ -6281,7 +6285,7 @@ address generate_avx_ghash_processBlocks() { __ vpmaddwd(merged0, merge_ab_bc0, pack32_op, Assembler::AVX_512bit); __ vpermb(merged0, pack24bits, merged0, Assembler::AVX_512bit); - __ evmovdquq(Address(dest, dp), merged0, Assembler::AVX_512bit); + __ evmovdqub(Address(dest, dp), k2, merged0, true, Assembler::AVX_512bit); __ subl(length, 64); __ addptr(source, 64); @@ -6528,7 +6532,13 @@ address generate_avx_ghash_processBlocks() { if (VM_Version::supports_sse4_1() && VM_Version::supports_avx512_vpclmulqdq() && VM_Version::supports_avx512bw() && VM_Version::supports_avx512vl()) { + // The constants used in the CRC32 algorithm requires the 1's compliment of the initial crc value. + // However, the constant table for CRC32-C assumes the original crc value. Account for this + // difference before calling and after returning. + __ lea(table, ExternalAddress(StubRoutines::x86::crc_table_avx512_addr())); + __ notl(crc); __ kernel_crc32_avx512(crc, buf, len, table, tmp1, tmp2); + __ notl(crc); } else { __ kernel_crc32(crc, buf, len, table, tmp1); } @@ -6580,20 +6590,27 @@ address generate_avx_ghash_processBlocks() { BLOCK_COMMENT("Entry:"); __ enter(); // required for proper stackwalking of RuntimeStub frame + if (VM_Version::supports_sse4_1() && VM_Version::supports_avx512_vpclmulqdq() && + VM_Version::supports_avx512bw() && + VM_Version::supports_avx512vl()) { + __ lea(j, ExternalAddress(StubRoutines::x86::crc32c_table_avx512_addr())); + __ kernel_crc32_avx512(crc, buf, len, j, l, k); + } else { #ifdef _WIN64 - __ push(y); - __ push(z); + __ push(y); + __ push(z); #endif - __ crc32c_ipl_alg2_alt2(crc, buf, len, - a, j, k, - l, y, z, - c_farg0, c_farg1, c_farg2, - is_pclmulqdq_supported); - __ movl(rax, crc); + __ crc32c_ipl_alg2_alt2(crc, buf, len, + a, j, k, + l, y, z, + c_farg0, c_farg1, c_farg2, + is_pclmulqdq_supported); #ifdef _WIN64 - __ pop(z); - __ pop(y); + __ pop(z); + __ pop(y); #endif + } + __ movl(rax, crc); __ vzeroupper(); __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); diff --git a/src/hotspot/cpu/x86/stubRoutines_x86.cpp b/src/hotspot/cpu/x86/stubRoutines_x86.cpp index ec5a5d0f1433b7fd3a395b40414e31cd15051d6f..81362c76bd69472828ffcac5040d3d8a5dd1fcd8 100644 --- a/src/hotspot/cpu/x86/stubRoutines_x86.cpp +++ b/src/hotspot/cpu/x86/stubRoutines_x86.cpp @@ -221,6 +221,23 @@ juint StubRoutines::x86::_crc_table_avx512[] = 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL }; +juint StubRoutines::x86::_crc32c_table_avx512[] = +{ + 0xb9e02b86UL, 0x00000000UL, 0xdcb17aa4UL, 0x00000000UL, + 0x493c7d27UL, 0x00000000UL, 0xc1068c50UL, 0x0000000eUL, + 0x06e38d70UL, 0x00000002UL, 0x6992cea2UL, 0x00000000UL, + 0x493c7d27UL, 0x00000000UL, 0xdd45aab8UL, 0x00000000UL, + 0xdea713f0UL, 0x00000000UL, 0x05ec76f0UL, 0x00000001UL, + 0x47db8317UL, 0x00000000UL, 0x2ad91c30UL, 0x00000000UL, + 0x0715ce53UL, 0x00000000UL, 0xc49f4f67UL, 0x00000000UL, + 0x39d3b296UL, 0x00000000UL, 0x083a6eecUL, 0x00000000UL, + 0x9e4addf8UL, 0x00000000UL, 0x740eef02UL, 0x00000000UL, + 0xddc0152bUL, 0x00000000UL, 0x1c291d04UL, 0x00000000UL, + 0xba4fc28eUL, 0x00000000UL, 0x3da6d0cbUL, 0x00000000UL, + 0x493c7d27UL, 0x00000000UL, 0xc1068c50UL, 0x0000000eUL, + 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL +}; + juint StubRoutines::x86::_crc_by128_masks_avx512[] = { 0xffffffffUL, 0xffffffffUL, 0x00000000UL, 0x00000000UL, diff --git a/src/hotspot/cpu/x86/stubRoutines_x86.hpp b/src/hotspot/cpu/x86/stubRoutines_x86.hpp index 1ef8377dfc2376b7f52901831673d44b2b8a39ee..e4dd9550ce28343e24917176eababb5913835137 100644 --- a/src/hotspot/cpu/x86/stubRoutines_x86.hpp +++ b/src/hotspot/cpu/x86/stubRoutines_x86.hpp @@ -137,6 +137,7 @@ class x86 { #ifdef _LP64 static juint _crc_by128_masks_avx512[]; static juint _crc_table_avx512[]; + static juint _crc32c_table_avx512[]; static juint _shuf_table_crc32_avx512[]; static juint _adler32_shuf0_table[]; static juint _adler32_shuf1_table[]; @@ -256,6 +257,7 @@ class x86 { static address crc_by128_masks_avx512_addr() { return (address)_crc_by128_masks_avx512; } static address shuf_table_crc32_avx512_addr() { return (address)_shuf_table_crc32_avx512; } static address crc_table_avx512_addr() { return (address)_crc_table_avx512; } + static address crc32c_table_avx512_addr() { return (address)_crc32c_table_avx512; } static address ghash_polynomial512_addr() { return _ghash_poly512_addr; } #endif // _LP64 static address ghash_long_swap_mask_addr() { return _ghash_long_swap_mask_addr; } diff --git a/src/hotspot/cpu/x86/universalUpcallHandler_x86_64.cpp b/src/hotspot/cpu/x86/universalUpcallHandler_x86_64.cpp index c54b907f9b5c5f0bb3713532c66b4f27039bca9f..da675bf0aa6484761b8abce99ee5879045f9c616 100644 --- a/src/hotspot/cpu/x86/universalUpcallHandler_x86_64.cpp +++ b/src/hotspot/cpu/x86/universalUpcallHandler_x86_64.cpp @@ -616,12 +616,9 @@ address ProgrammableUpcallHandler::generate_optimized_upcall_stub(jobject receiv int reg_save_area_size = compute_reg_save_area_size(abi); int arg_save_area_size = compute_arg_save_area_size(conv); int res_save_area_size = compute_res_save_area_size(conv); - // To spill receiver during deopt - int deopt_spill_size = 1 * BytesPerWord; int shuffle_area_offset = 0; - int deopt_spill_offset = shuffle_area_offset + out_arg_area; - int res_save_area_offset = deopt_spill_offset + deopt_spill_size; + int res_save_area_offset = shuffle_area_offset + out_arg_area; int arg_save_area_offset = res_save_area_offset + res_save_area_size; int reg_save_area_offset = arg_save_area_offset + arg_save_area_size; int frame_data_offset = reg_save_area_offset + reg_save_area_size; @@ -648,9 +645,6 @@ address ProgrammableUpcallHandler::generate_optimized_upcall_stub(jobject receiv // | res_save_area | // |---------------------| = res_save_are_offset // | | - // | deopt_spill | - // |---------------------| = deopt_spill_offset - // | | // SP-> | out_arg_area | needs to be at end for shadow space // // diff --git a/src/hotspot/cpu/x86/vm_version_ext_x86.cpp b/src/hotspot/cpu/x86/vm_version_ext_x86.cpp deleted file mode 100644 index 84e8c9fa819a87c9ca8ad779c671961b9a2e9b9c..0000000000000000000000000000000000000000 --- a/src/hotspot/cpu/x86/vm_version_ext_x86.cpp +++ /dev/null @@ -1,982 +0,0 @@ -/* - * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "precompiled.hpp" -#include "jvm.h" -#include "utilities/macros.hpp" -#include "asm/macroAssembler.hpp" -#include "asm/macroAssembler.inline.hpp" -#include "code/codeBlob.hpp" -#include "memory/allocation.inline.hpp" -#include "memory/resourceArea.hpp" -#include "runtime/java.hpp" -#include "runtime/stubCodeGenerator.hpp" -#include "vm_version_ext_x86.hpp" - -typedef enum { - CPU_FAMILY_8086_8088 = 0, - CPU_FAMILY_INTEL_286 = 2, - CPU_FAMILY_INTEL_386 = 3, - CPU_FAMILY_INTEL_486 = 4, - CPU_FAMILY_PENTIUM = 5, - CPU_FAMILY_PENTIUMPRO = 6, // Same family several models - CPU_FAMILY_PENTIUM_4 = 0xF -} FamilyFlag; - -typedef enum { - RDTSCP_FLAG = 0x08000000, // bit 27 - INTEL64_FLAG = 0x20000000 // bit 29 -} _featureExtendedEdxFlag; - -#define CPUID_STANDARD_FN 0x0 -#define CPUID_STANDARD_FN_1 0x1 -#define CPUID_STANDARD_FN_4 0x4 -#define CPUID_STANDARD_FN_B 0xb - -#define CPUID_EXTENDED_FN 0x80000000 -#define CPUID_EXTENDED_FN_1 0x80000001 -#define CPUID_EXTENDED_FN_2 0x80000002 -#define CPUID_EXTENDED_FN_3 0x80000003 -#define CPUID_EXTENDED_FN_4 0x80000004 -#define CPUID_EXTENDED_FN_7 0x80000007 -#define CPUID_EXTENDED_FN_8 0x80000008 - -typedef enum { - FPU_FLAG = 0x00000001, - VME_FLAG = 0x00000002, - DE_FLAG = 0x00000004, - PSE_FLAG = 0x00000008, - TSC_FLAG = 0x00000010, - MSR_FLAG = 0x00000020, - PAE_FLAG = 0x00000040, - MCE_FLAG = 0x00000080, - CX8_FLAG = 0x00000100, - APIC_FLAG = 0x00000200, - SEP_FLAG = 0x00000800, - MTRR_FLAG = 0x00001000, - PGE_FLAG = 0x00002000, - MCA_FLAG = 0x00004000, - CMOV_FLAG = 0x00008000, - PAT_FLAG = 0x00010000, - PSE36_FLAG = 0x00020000, - PSNUM_FLAG = 0x00040000, - CLFLUSH_FLAG = 0x00080000, - DTS_FLAG = 0x00200000, - ACPI_FLAG = 0x00400000, - MMX_FLAG = 0x00800000, - FXSR_FLAG = 0x01000000, - SSE_FLAG = 0x02000000, - SSE2_FLAG = 0x04000000, - SS_FLAG = 0x08000000, - HTT_FLAG = 0x10000000, - TM_FLAG = 0x20000000 -} FeatureEdxFlag; - -static BufferBlob* cpuid_brand_string_stub_blob; -static const int cpuid_brand_string_stub_size = 550; - -extern "C" { - typedef void (*getCPUIDBrandString_stub_t)(void*); -} - -static getCPUIDBrandString_stub_t getCPUIDBrandString_stub = NULL; - -class VM_Version_Ext_StubGenerator: public StubCodeGenerator { - public: - - VM_Version_Ext_StubGenerator(CodeBuffer *c) : StubCodeGenerator(c) {} - - address generate_getCPUIDBrandString(void) { - // Flags to test CPU type. - const uint32_t HS_EFL_AC = 0x40000; - const uint32_t HS_EFL_ID = 0x200000; - // Values for when we don't have a CPUID instruction. - const int CPU_FAMILY_SHIFT = 8; - const uint32_t CPU_FAMILY_386 = (3 << CPU_FAMILY_SHIFT); - const uint32_t CPU_FAMILY_486 = (4 << CPU_FAMILY_SHIFT); - - Label detect_486, cpu486, detect_586, done, ext_cpuid; - - StubCodeMark mark(this, "VM_Version_Ext", "getCPUIDNameInfo_stub"); -# define __ _masm-> - - address start = __ pc(); - - // - // void getCPUIDBrandString(VM_Version::CpuidInfo* cpuid_info); - // - // LP64: rcx and rdx are first and second argument registers on windows - - __ push(rbp); -#ifdef _LP64 - __ mov(rbp, c_rarg0); // cpuid_info address -#else - __ movptr(rbp, Address(rsp, 8)); // cpuid_info address -#endif - __ push(rbx); - __ push(rsi); - __ pushf(); // preserve rbx, and flags - __ pop(rax); - __ push(rax); - __ mov(rcx, rax); - // - // if we are unable to change the AC flag, we have a 386 - // - __ xorl(rax, HS_EFL_AC); - __ push(rax); - __ popf(); - __ pushf(); - __ pop(rax); - __ cmpptr(rax, rcx); - __ jccb(Assembler::notEqual, detect_486); - - __ movl(rax, CPU_FAMILY_386); - __ jmp(done); - - // - // If we are unable to change the ID flag, we have a 486 which does - // not support the "cpuid" instruction. - // - __ bind(detect_486); - __ mov(rax, rcx); - __ xorl(rax, HS_EFL_ID); - __ push(rax); - __ popf(); - __ pushf(); - __ pop(rax); - __ cmpptr(rcx, rax); - __ jccb(Assembler::notEqual, detect_586); - - __ bind(cpu486); - __ movl(rax, CPU_FAMILY_486); - __ jmp(done); - - // - // At this point, we have a chip which supports the "cpuid" instruction - // - __ bind(detect_586); - __ xorl(rax, rax); - __ cpuid(); - __ orl(rax, rax); - __ jcc(Assembler::equal, cpu486); // if cpuid doesn't support an input - // value of at least 1, we give up and - // assume a 486 - - // - // Extended cpuid(0x80000000) for processor brand string detection - // - __ bind(ext_cpuid); - __ movl(rax, CPUID_EXTENDED_FN); - __ cpuid(); - __ cmpl(rax, CPUID_EXTENDED_FN_4); - __ jcc(Assembler::below, done); - - // - // Extended cpuid(0x80000002) // first 16 bytes in brand string - // - __ movl(rax, CPUID_EXTENDED_FN_2); - __ cpuid(); - __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_0_offset()))); - __ movl(Address(rsi, 0), rax); - __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_1_offset()))); - __ movl(Address(rsi, 0), rbx); - __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_2_offset()))); - __ movl(Address(rsi, 0), rcx); - __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_3_offset()))); - __ movl(Address(rsi,0), rdx); - - // - // Extended cpuid(0x80000003) // next 16 bytes in brand string - // - __ movl(rax, CPUID_EXTENDED_FN_3); - __ cpuid(); - __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_4_offset()))); - __ movl(Address(rsi, 0), rax); - __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_5_offset()))); - __ movl(Address(rsi, 0), rbx); - __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_6_offset()))); - __ movl(Address(rsi, 0), rcx); - __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_7_offset()))); - __ movl(Address(rsi,0), rdx); - - // - // Extended cpuid(0x80000004) // last 16 bytes in brand string - // - __ movl(rax, CPUID_EXTENDED_FN_4); - __ cpuid(); - __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_8_offset()))); - __ movl(Address(rsi, 0), rax); - __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_9_offset()))); - __ movl(Address(rsi, 0), rbx); - __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_10_offset()))); - __ movl(Address(rsi, 0), rcx); - __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_11_offset()))); - __ movl(Address(rsi,0), rdx); - - // - // return - // - __ bind(done); - __ popf(); - __ pop(rsi); - __ pop(rbx); - __ pop(rbp); - __ ret(0); - -# undef __ - - return start; - }; -}; - - -// VM_Version_Ext statics -const size_t VM_Version_Ext::VENDOR_LENGTH = 13; -const size_t VM_Version_Ext::CPU_EBS_MAX_LENGTH = (3 * 4 * 4 + 1); -const size_t VM_Version_Ext::CPU_TYPE_DESC_BUF_SIZE = 256; -const size_t VM_Version_Ext::CPU_DETAILED_DESC_BUF_SIZE = 4096; -char* VM_Version_Ext::_cpu_brand_string = NULL; -int64_t VM_Version_Ext::_max_qualified_cpu_frequency = 0; - -int VM_Version_Ext::_no_of_threads = 0; -int VM_Version_Ext::_no_of_cores = 0; -int VM_Version_Ext::_no_of_packages = 0; - -void VM_Version_Ext::initialize(void) { - ResourceMark rm; - - cpuid_brand_string_stub_blob = BufferBlob::create("getCPUIDBrandString_stub", cpuid_brand_string_stub_size); - if (cpuid_brand_string_stub_blob == NULL) { - vm_exit_during_initialization("Unable to allocate getCPUIDBrandString_stub"); - } - CodeBuffer c(cpuid_brand_string_stub_blob); - VM_Version_Ext_StubGenerator g(&c); - getCPUIDBrandString_stub = CAST_TO_FN_PTR(getCPUIDBrandString_stub_t, - g.generate_getCPUIDBrandString()); -} - -const char* VM_Version_Ext::cpu_model_description(void) { - uint32_t cpu_family = extended_cpu_family(); - uint32_t cpu_model = extended_cpu_model(); - const char* model = NULL; - - if (cpu_family == CPU_FAMILY_PENTIUMPRO) { - for (uint32_t i = 0; i <= cpu_model; i++) { - model = _model_id_pentium_pro[i]; - if (model == NULL) { - break; - } - } - } - return model; -} - -const char* VM_Version_Ext::cpu_brand_string(void) { - if (_cpu_brand_string == NULL) { - _cpu_brand_string = NEW_C_HEAP_ARRAY_RETURN_NULL(char, CPU_EBS_MAX_LENGTH, mtInternal); - if (NULL == _cpu_brand_string) { - return NULL; - } - int ret_val = cpu_extended_brand_string(_cpu_brand_string, CPU_EBS_MAX_LENGTH); - if (ret_val != OS_OK) { - FREE_C_HEAP_ARRAY(char, _cpu_brand_string); - _cpu_brand_string = NULL; - } - } - return _cpu_brand_string; -} - -const char* VM_Version_Ext::cpu_brand(void) { - const char* brand = NULL; - - if ((_cpuid_info.std_cpuid1_ebx.value & 0xFF) > 0) { - int brand_num = _cpuid_info.std_cpuid1_ebx.value & 0xFF; - brand = _brand_id[0]; - for (int i = 0; brand != NULL && i <= brand_num; i += 1) { - brand = _brand_id[i]; - } - } - return brand; -} - -bool VM_Version_Ext::cpu_is_em64t(void) { - return ((_cpuid_info.ext_cpuid1_edx.value & INTEL64_FLAG) == INTEL64_FLAG); -} - -bool VM_Version_Ext::is_netburst(void) { - return (is_intel() && (extended_cpu_family() == CPU_FAMILY_PENTIUM_4)); -} - -bool VM_Version_Ext::supports_tscinv_ext(void) { - if (!supports_tscinv_bit()) { - return false; - } - - if (is_intel()) { - return true; - } - - if (is_amd()) { - return !is_amd_Barcelona(); - } - - if (is_hygon()) { - return true; - } - - return false; -} - -void VM_Version_Ext::resolve_cpu_information_details(void) { - - // in future we want to base this information on proper cpu - // and cache topology enumeration such as: - // Intel 64 Architecture Processor Topology Enumeration - // which supports system cpu and cache topology enumeration - // either using 2xAPICIDs or initial APICIDs - - // currently only rough cpu information estimates - // which will not necessarily reflect the exact configuration of the system - - // this is the number of logical hardware threads - // visible to the operating system - _no_of_threads = os::processor_count(); - - // find out number of threads per cpu package - int threads_per_package = threads_per_core() * cores_per_cpu(); - - // use amount of threads visible to the process in order to guess number of sockets - _no_of_packages = _no_of_threads / threads_per_package; - - // process might only see a subset of the total number of threads - // from a single processor package. Virtualization/resource management for example. - // If so then just write a hard 1 as num of pkgs. - if (0 == _no_of_packages) { - _no_of_packages = 1; - } - - // estimate the number of cores - _no_of_cores = cores_per_cpu() * _no_of_packages; -} - -int VM_Version_Ext::number_of_threads(void) { - if (_no_of_threads == 0) { - resolve_cpu_information_details(); - } - return _no_of_threads; -} - -int VM_Version_Ext::number_of_cores(void) { - if (_no_of_cores == 0) { - resolve_cpu_information_details(); - } - return _no_of_cores; -} - -int VM_Version_Ext::number_of_sockets(void) { - if (_no_of_packages == 0) { - resolve_cpu_information_details(); - } - return _no_of_packages; -} - -const char* VM_Version_Ext::cpu_family_description(void) { - int cpu_family_id = extended_cpu_family(); - if (is_amd()) { - if (cpu_family_id < ExtendedFamilyIdLength_AMD) { - return _family_id_amd[cpu_family_id]; - } - } - if (is_intel()) { - if (cpu_family_id == CPU_FAMILY_PENTIUMPRO) { - return cpu_model_description(); - } - if (cpu_family_id < ExtendedFamilyIdLength_INTEL) { - return _family_id_intel[cpu_family_id]; - } - } - if (is_hygon()) { - return "Dhyana"; - } - return "Unknown x86"; -} - -int VM_Version_Ext::cpu_type_description(char* const buf, size_t buf_len) { - assert(buf != NULL, "buffer is NULL!"); - assert(buf_len >= CPU_TYPE_DESC_BUF_SIZE, "buffer len should at least be == CPU_TYPE_DESC_BUF_SIZE!"); - - const char* cpu_type = NULL; - const char* x64 = NULL; - - if (is_intel()) { - cpu_type = "Intel"; - x64 = cpu_is_em64t() ? " Intel64" : ""; - } else if (is_amd()) { - cpu_type = "AMD"; - x64 = cpu_is_em64t() ? " AMD64" : ""; - } else if (is_hygon()) { - cpu_type = "Hygon"; - x64 = cpu_is_em64t() ? " AMD64" : ""; - } else { - cpu_type = "Unknown x86"; - x64 = cpu_is_em64t() ? " x86_64" : ""; - } - - jio_snprintf(buf, buf_len, "%s %s%s SSE SSE2%s%s%s%s%s%s%s%s", - cpu_type, - cpu_family_description(), - supports_ht() ? " (HT)" : "", - supports_sse3() ? " SSE3" : "", - supports_ssse3() ? " SSSE3" : "", - supports_sse4_1() ? " SSE4.1" : "", - supports_sse4_2() ? " SSE4.2" : "", - supports_sse4a() ? " SSE4A" : "", - is_netburst() ? " Netburst" : "", - is_intel_family_core() ? " Core" : "", - x64); - - return OS_OK; -} - -int VM_Version_Ext::cpu_extended_brand_string(char* const buf, size_t buf_len) { - assert(buf != NULL, "buffer is NULL!"); - assert(buf_len >= CPU_EBS_MAX_LENGTH, "buffer len should at least be == CPU_EBS_MAX_LENGTH!"); - assert(getCPUIDBrandString_stub != NULL, "not initialized"); - - // invoke newly generated asm code to fetch CPU Brand String - getCPUIDBrandString_stub(&_cpuid_info); - - // fetch results into buffer - *((uint32_t*) &buf[0]) = _cpuid_info.proc_name_0; - *((uint32_t*) &buf[4]) = _cpuid_info.proc_name_1; - *((uint32_t*) &buf[8]) = _cpuid_info.proc_name_2; - *((uint32_t*) &buf[12]) = _cpuid_info.proc_name_3; - *((uint32_t*) &buf[16]) = _cpuid_info.proc_name_4; - *((uint32_t*) &buf[20]) = _cpuid_info.proc_name_5; - *((uint32_t*) &buf[24]) = _cpuid_info.proc_name_6; - *((uint32_t*) &buf[28]) = _cpuid_info.proc_name_7; - *((uint32_t*) &buf[32]) = _cpuid_info.proc_name_8; - *((uint32_t*) &buf[36]) = _cpuid_info.proc_name_9; - *((uint32_t*) &buf[40]) = _cpuid_info.proc_name_10; - *((uint32_t*) &buf[44]) = _cpuid_info.proc_name_11; - - return OS_OK; -} - -size_t VM_Version_Ext::cpu_write_support_string(char* const buf, size_t buf_len) { - guarantee(buf != NULL, "buffer is NULL!"); - guarantee(buf_len > 0, "buffer len not enough!"); - - unsigned int flag = 0; - unsigned int fi = 0; - size_t written = 0; - const char* prefix = ""; - -#define WRITE_TO_BUF(string) \ - { \ - int res = jio_snprintf(&buf[written], buf_len - written, "%s%s", prefix, string); \ - if (res < 0) { \ - return buf_len - 1; \ - } \ - written += res; \ - if (prefix[0] == '\0') { \ - prefix = ", "; \ - } \ - } - - for (flag = 1, fi = 0; flag <= 0x20000000 ; flag <<= 1, fi++) { - if (flag == HTT_FLAG && (((_cpuid_info.std_cpuid1_ebx.value >> 16) & 0xff) <= 1)) { - continue; /* no hyperthreading */ - } else if (flag == SEP_FLAG && (cpu_family() == CPU_FAMILY_PENTIUMPRO && ((_cpuid_info.std_cpuid1_eax.value & 0xff) < 0x33))) { - continue; /* no fast system call */ - } - if ((_cpuid_info.std_cpuid1_edx.value & flag) && strlen(_feature_edx_id[fi]) > 0) { - WRITE_TO_BUF(_feature_edx_id[fi]); - } - } - - for (flag = 1, fi = 0; flag <= 0x20000000; flag <<= 1, fi++) { - if ((_cpuid_info.std_cpuid1_ecx.value & flag) && strlen(_feature_ecx_id[fi]) > 0) { - WRITE_TO_BUF(_feature_ecx_id[fi]); - } - } - - for (flag = 1, fi = 0; flag <= 0x20000000 ; flag <<= 1, fi++) { - if ((_cpuid_info.ext_cpuid1_ecx.value & flag) && strlen(_feature_extended_ecx_id[fi]) > 0) { - WRITE_TO_BUF(_feature_extended_ecx_id[fi]); - } - } - - for (flag = 1, fi = 0; flag <= 0x20000000; flag <<= 1, fi++) { - if ((_cpuid_info.ext_cpuid1_edx.value & flag) && strlen(_feature_extended_edx_id[fi]) > 0) { - WRITE_TO_BUF(_feature_extended_edx_id[fi]); - } - } - - if (supports_tscinv_bit()) { - WRITE_TO_BUF("Invariant TSC"); - } - - return written; -} - -/** - * Write a detailed description of the cpu to a given buffer, including - * feature set. - */ -int VM_Version_Ext::cpu_detailed_description(char* const buf, size_t buf_len) { - assert(buf != NULL, "buffer is NULL!"); - assert(buf_len >= CPU_DETAILED_DESC_BUF_SIZE, "buffer len should at least be == CPU_DETAILED_DESC_BUF_SIZE!"); - - static const char* unknown = ""; - char vendor_id[VENDOR_LENGTH]; - const char* family = NULL; - const char* model = NULL; - const char* brand = NULL; - int outputLen = 0; - - family = cpu_family_description(); - if (family == NULL) { - family = unknown; - } - - model = cpu_model_description(); - if (model == NULL) { - model = unknown; - } - - brand = cpu_brand_string(); - - if (brand == NULL) { - brand = cpu_brand(); - if (brand == NULL) { - brand = unknown; - } - } - - *((uint32_t*) &vendor_id[0]) = _cpuid_info.std_vendor_name_0; - *((uint32_t*) &vendor_id[4]) = _cpuid_info.std_vendor_name_2; - *((uint32_t*) &vendor_id[8]) = _cpuid_info.std_vendor_name_1; - vendor_id[VENDOR_LENGTH-1] = '\0'; - - outputLen = jio_snprintf(buf, buf_len, "Brand: %s, Vendor: %s\n" - "Family: %s (0x%x), Model: %s (0x%x), Stepping: 0x%x\n" - "Ext. family: 0x%x, Ext. model: 0x%x, Type: 0x%x, Signature: 0x%8.8x\n" - "Features: ebx: 0x%8.8x, ecx: 0x%8.8x, edx: 0x%8.8x\n" - "Ext. features: eax: 0x%8.8x, ebx: 0x%8.8x, ecx: 0x%8.8x, edx: 0x%8.8x\n" - "Supports: ", - brand, - vendor_id, - family, - extended_cpu_family(), - model, - extended_cpu_model(), - cpu_stepping(), - _cpuid_info.std_cpuid1_eax.bits.ext_family, - _cpuid_info.std_cpuid1_eax.bits.ext_model, - _cpuid_info.std_cpuid1_eax.bits.proc_type, - _cpuid_info.std_cpuid1_eax.value, - _cpuid_info.std_cpuid1_ebx.value, - _cpuid_info.std_cpuid1_ecx.value, - _cpuid_info.std_cpuid1_edx.value, - _cpuid_info.ext_cpuid1_eax, - _cpuid_info.ext_cpuid1_ebx, - _cpuid_info.ext_cpuid1_ecx, - _cpuid_info.ext_cpuid1_edx); - - if (outputLen < 0 || (size_t) outputLen >= buf_len - 1) { - if (buf_len > 0) { buf[buf_len-1] = '\0'; } - return OS_ERR; - } - - cpu_write_support_string(&buf[outputLen], buf_len - outputLen); - - return OS_OK; -} - -const char* VM_Version_Ext::cpu_name(void) { - char cpu_type_desc[CPU_TYPE_DESC_BUF_SIZE]; - size_t cpu_desc_len = sizeof(cpu_type_desc); - - cpu_type_description(cpu_type_desc, cpu_desc_len); - char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, cpu_desc_len, mtTracing); - if (NULL == tmp) { - return NULL; - } - strncpy(tmp, cpu_type_desc, cpu_desc_len); - return tmp; -} - -const char* VM_Version_Ext::cpu_description(void) { - char cpu_detailed_desc_buffer[CPU_DETAILED_DESC_BUF_SIZE]; - size_t cpu_detailed_desc_len = sizeof(cpu_detailed_desc_buffer); - - cpu_detailed_description(cpu_detailed_desc_buffer, cpu_detailed_desc_len); - - char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, cpu_detailed_desc_len, mtTracing); - - if (NULL == tmp) { - return NULL; - } - - strncpy(tmp, cpu_detailed_desc_buffer, cpu_detailed_desc_len); - return tmp; -} - -/** - * For information about extracting the frequency from the cpu brand string, please see: - * - * Intel Processor Identification and the CPUID Instruction - * Application Note 485 - * May 2012 - * - * The return value is the frequency in Hz. - */ -int64_t VM_Version_Ext::max_qualified_cpu_freq_from_brand_string(void) { - const char* const brand_string = cpu_brand_string(); - if (brand_string == NULL) { - return 0; - } - const int64_t MEGA = 1000000; - int64_t multiplier = 0; - int64_t frequency = 0; - uint8_t idx = 0; - // The brand string buffer is at most 48 bytes. - // -2 is to prevent buffer overrun when looking for y in yHz, as z is +2 from y. - for (; idx < 48-2; ++idx) { - // Format is either "x.xxyHz" or "xxxxyHz", where y=M, G, T and x are digits. - // Search brand string for "yHz" where y is M, G, or T. - if (brand_string[idx+1] == 'H' && brand_string[idx+2] == 'z') { - if (brand_string[idx] == 'M') { - multiplier = MEGA; - } else if (brand_string[idx] == 'G') { - multiplier = MEGA * 1000; - } else if (brand_string[idx] == 'T') { - multiplier = MEGA * MEGA; - } - break; - } - } - if (multiplier > 0) { - // Compute freqency (in Hz) from brand string. - if (brand_string[idx-3] == '.') { // if format is "x.xx" - frequency = (brand_string[idx-4] - '0') * multiplier; - frequency += (brand_string[idx-2] - '0') * multiplier / 10; - frequency += (brand_string[idx-1] - '0') * multiplier / 100; - } else { // format is "xxxx" - frequency = (brand_string[idx-4] - '0') * 1000; - frequency += (brand_string[idx-3] - '0') * 100; - frequency += (brand_string[idx-2] - '0') * 10; - frequency += (brand_string[idx-1] - '0'); - frequency *= multiplier; - } - } - return frequency; -} - - -int64_t VM_Version_Ext::maximum_qualified_cpu_frequency(void) { - if (_max_qualified_cpu_frequency == 0) { - _max_qualified_cpu_frequency = max_qualified_cpu_freq_from_brand_string(); - } - return _max_qualified_cpu_frequency; -} - -const char* const VM_Version_Ext::_family_id_intel[ExtendedFamilyIdLength_INTEL] = { - "8086/8088", - "", - "286", - "386", - "486", - "Pentium", - "Pentium Pro", //or Pentium-M/Woodcrest depeding on model - "", - "", - "", - "", - "", - "", - "", - "", - "Pentium 4" -}; - -const char* const VM_Version_Ext::_family_id_amd[ExtendedFamilyIdLength_AMD] = { - "", - "", - "", - "", - "5x86", - "K5/K6", - "Athlon/AthlonXP", - "", - "", - "", - "", - "", - "", - "", - "", - "Opteron/Athlon64", - "Opteron QC/Phenom", // Barcelona et.al. - "", - "", - "", - "", - "", - "", - "Zen" -}; -// Partially from Intel 64 and IA-32 Architecture Software Developer's Manual, -// September 2013, Vol 3C Table 35-1 -const char* const VM_Version_Ext::_model_id_pentium_pro[] = { - "", - "Pentium Pro", - "", - "Pentium II model 3", - "", - "Pentium II model 5/Xeon/Celeron", - "Celeron", - "Pentium III/Pentium III Xeon", - "Pentium III/Pentium III Xeon", - "Pentium M model 9", // Yonah - "Pentium III, model A", - "Pentium III, model B", - "", - "Pentium M model D", // Dothan - "", - "Core 2", // 0xf Woodcrest/Conroe/Merom/Kentsfield/Clovertown - "", - "", - "", - "", - "", - "", - "Celeron", // 0x16 Celeron 65nm - "Core 2", // 0x17 Penryn / Harpertown - "", - "", - "Core i7", // 0x1A CPU_MODEL_NEHALEM_EP - "Atom", // 0x1B Z5xx series Silverthorn - "", - "Core 2", // 0x1D Dunnington (6-core) - "Nehalem", // 0x1E CPU_MODEL_NEHALEM - "", - "", - "", - "", - "", - "", - "Westmere", // 0x25 CPU_MODEL_WESTMERE - "", - "", - "", // 0x28 - "", - "Sandy Bridge", // 0x2a "2nd Generation Intel Core i7, i5, i3" - "", - "Westmere-EP", // 0x2c CPU_MODEL_WESTMERE_EP - "Sandy Bridge-EP", // 0x2d CPU_MODEL_SANDYBRIDGE_EP - "Nehalem-EX", // 0x2e CPU_MODEL_NEHALEM_EX - "Westmere-EX", // 0x2f CPU_MODEL_WESTMERE_EX - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "Ivy Bridge", // 0x3a - "", - "Haswell", // 0x3c "4th Generation Intel Core Processor" - "", // 0x3d "Next Generation Intel Core Processor" - "Ivy Bridge-EP", // 0x3e "Next Generation Intel Xeon Processor E7 Family" - "", // 0x3f "Future Generation Intel Xeon Processor" - "", - "", - "", - "", - "", - "Haswell", // 0x45 "4th Generation Intel Core Processor" - "Haswell", // 0x46 "4th Generation Intel Core Processor" - NULL -}; - -/* Brand ID is for back compability - * Newer CPUs uses the extended brand string */ -const char* const VM_Version_Ext::_brand_id[] = { - "", - "Celeron processor", - "Pentium III processor", - "Intel Pentium III Xeon processor", - "", - "", - "", - "", - "Intel Pentium 4 processor", - NULL -}; - - -const char* const VM_Version_Ext::_feature_edx_id[] = { - "On-Chip FPU", - "Virtual Mode Extensions", - "Debugging Extensions", - "Page Size Extensions", - "Time Stamp Counter", - "Model Specific Registers", - "Physical Address Extension", - "Machine Check Exceptions", - "CMPXCHG8B Instruction", - "On-Chip APIC", - "", - "Fast System Call", - "Memory Type Range Registers", - "Page Global Enable", - "Machine Check Architecture", - "Conditional Mov Instruction", - "Page Attribute Table", - "36-bit Page Size Extension", - "Processor Serial Number", - "CLFLUSH Instruction", - "", - "Debug Trace Store feature", - "ACPI registers in MSR space", - "Intel Architecture MMX Technology", - "Fast Float Point Save and Restore", - "Streaming SIMD extensions", - "Streaming SIMD extensions 2", - "Self-Snoop", - "Hyper Threading", - "Thermal Monitor", - "", - "Pending Break Enable" -}; - -const char* const VM_Version_Ext::_feature_extended_edx_id[] = { - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "SYSCALL/SYSRET", - "", - "", - "", - "", - "", - "", - "", - "", - "Execute Disable Bit", - "", - "", - "", - "", - "", - "", - "RDTSCP", - "", - "Intel 64 Architecture", - "", - "" -}; - -const char* const VM_Version_Ext::_feature_ecx_id[] = { - "Streaming SIMD Extensions 3", - "PCLMULQDQ", - "64-bit DS Area", - "MONITOR/MWAIT instructions", - "CPL Qualified Debug Store", - "Virtual Machine Extensions", - "Safer Mode Extensions", - "Enhanced Intel SpeedStep technology", - "Thermal Monitor 2", - "Supplemental Streaming SIMD Extensions 3", - "L1 Context ID", - "", - "Fused Multiply-Add", - "CMPXCHG16B", - "xTPR Update Control", - "Perfmon and Debug Capability", - "", - "Process-context identifiers", - "Direct Cache Access", - "Streaming SIMD extensions 4.1", - "Streaming SIMD extensions 4.2", - "x2APIC", - "MOVBE", - "Popcount instruction", - "TSC-Deadline", - "AESNI", - "XSAVE", - "OSXSAVE", - "AVX", - "F16C", - "RDRAND", - "" -}; - -const char* const VM_Version_Ext::_feature_extended_ecx_id[] = { - "LAHF/SAHF instruction support", - "Core multi-processor legacy mode", - "", - "", - "", - "Advanced Bit Manipulations: LZCNT", - "SSE4A: MOVNTSS, MOVNTSD, EXTRQ, INSERTQ", - "Misaligned SSE mode", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "" -}; diff --git a/src/hotspot/cpu/x86/vm_version_ext_x86.hpp b/src/hotspot/cpu/x86/vm_version_ext_x86.hpp deleted file mode 100644 index c81ebead23ca52d0a4691529cccc898292fa4358..0000000000000000000000000000000000000000 --- a/src/hotspot/cpu/x86/vm_version_ext_x86.hpp +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef CPU_X86_VM_VERSION_EXT_X86_HPP -#define CPU_X86_VM_VERSION_EXT_X86_HPP - -#include "runtime/vm_version.hpp" -#include "utilities/macros.hpp" -#include "utilities/sizes.hpp" - -class VM_Version_Ext : public VM_Version { - - enum { - ExtendedFamilyIdLength_INTEL = 16, - ExtendedFamilyIdLength_AMD = 24 - }; - - private: - static const size_t VENDOR_LENGTH; - static const size_t CPU_EBS_MAX_LENGTH; - static const size_t CPU_TYPE_DESC_BUF_SIZE; - static const size_t CPU_DETAILED_DESC_BUF_SIZE; - - static const char* const _family_id_intel[ExtendedFamilyIdLength_INTEL]; - static const char* const _family_id_amd[ExtendedFamilyIdLength_AMD]; - static const char* const _brand_id[]; - static const char* const _model_id_pentium_pro[]; - - static const char* const _feature_edx_id[]; - static const char* const _feature_extended_edx_id[]; - static const char* const _feature_ecx_id[]; - static const char* const _feature_extended_ecx_id[]; - - static int _no_of_threads; - static int _no_of_cores; - static int _no_of_packages; - static char* _cpu_brand_string; - static int64_t _max_qualified_cpu_frequency; - - static const char* cpu_family_description(void); - static const char* cpu_model_description(void); - static const char* cpu_brand(void); - static const char* cpu_brand_string(void); - - static int cpu_type_description(char* const buf, size_t buf_len); - static int cpu_detailed_description(char* const buf, size_t buf_len); - static int cpu_extended_brand_string(char* const buf, size_t buf_len); - - static bool cpu_is_em64t(void); - static bool is_netburst(void); - - // Returns bytes written excluding termninating null byte. - static size_t cpu_write_support_string(char* const buf, size_t buf_len); - static void resolve_cpu_information_details(void); - static int64_t max_qualified_cpu_freq_from_brand_string(void); - - public: - // Offsets for cpuid asm stub brand string - static ByteSize proc_name_0_offset() { return byte_offset_of(CpuidInfo, proc_name_0); } - static ByteSize proc_name_1_offset() { return byte_offset_of(CpuidInfo, proc_name_1); } - static ByteSize proc_name_2_offset() { return byte_offset_of(CpuidInfo, proc_name_2); } - static ByteSize proc_name_3_offset() { return byte_offset_of(CpuidInfo, proc_name_3); } - static ByteSize proc_name_4_offset() { return byte_offset_of(CpuidInfo, proc_name_4); } - static ByteSize proc_name_5_offset() { return byte_offset_of(CpuidInfo, proc_name_5); } - static ByteSize proc_name_6_offset() { return byte_offset_of(CpuidInfo, proc_name_6); } - static ByteSize proc_name_7_offset() { return byte_offset_of(CpuidInfo, proc_name_7); } - static ByteSize proc_name_8_offset() { return byte_offset_of(CpuidInfo, proc_name_8); } - static ByteSize proc_name_9_offset() { return byte_offset_of(CpuidInfo, proc_name_9); } - static ByteSize proc_name_10_offset() { return byte_offset_of(CpuidInfo, proc_name_10); } - static ByteSize proc_name_11_offset() { return byte_offset_of(CpuidInfo, proc_name_11); } - - static int number_of_threads(void); - static int number_of_cores(void); - static int number_of_sockets(void); - - static int64_t maximum_qualified_cpu_frequency(void); - - static bool supports_tscinv_ext(void); - - static const char* cpu_name(void); - static const char* cpu_description(void); - - static void initialize(); -}; - -#endif // CPU_X86_VM_VERSION_EXT_X86_HPP diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp index 605faf89f196ab96362c3395ef84a695f5b2405d..93613850a5e299c819486e1b953bfba250a80961 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp @@ -83,6 +83,19 @@ bool VM_Version::supports_clflush() { } #endif +#define CPUID_STANDARD_FN 0x0 +#define CPUID_STANDARD_FN_1 0x1 +#define CPUID_STANDARD_FN_4 0x4 +#define CPUID_STANDARD_FN_B 0xb + +#define CPUID_EXTENDED_FN 0x80000000 +#define CPUID_EXTENDED_FN_1 0x80000001 +#define CPUID_EXTENDED_FN_2 0x80000002 +#define CPUID_EXTENDED_FN_3 0x80000003 +#define CPUID_EXTENDED_FN_4 0x80000004 +#define CPUID_EXTENDED_FN_7 0x80000007 +#define CPUID_EXTENDED_FN_8 0x80000008 + class VM_Version_StubGenerator: public StubCodeGenerator { public: @@ -626,6 +639,149 @@ class VM_Version_StubGenerator: public StubCodeGenerator { __ pop(rbp); __ ret(0); +# undef __ + + return start; + }; + + + address generate_getCPUIDBrandString(void) { + // Flags to test CPU type. + const uint32_t HS_EFL_AC = 0x40000; + const uint32_t HS_EFL_ID = 0x200000; + // Values for when we don't have a CPUID instruction. + const int CPU_FAMILY_SHIFT = 8; + const uint32_t CPU_FAMILY_386 = (3 << CPU_FAMILY_SHIFT); + const uint32_t CPU_FAMILY_486 = (4 << CPU_FAMILY_SHIFT); + + Label detect_486, cpu486, detect_586, done, ext_cpuid; + + StubCodeMark mark(this, "VM_Version", "getCPUIDNameInfo_stub"); +# define __ _masm-> + + address start = __ pc(); + + // + // void getCPUIDBrandString(VM_Version::CpuidInfo* cpuid_info); + // + // LP64: rcx and rdx are first and second argument registers on windows + + __ push(rbp); +#ifdef _LP64 + __ mov(rbp, c_rarg0); // cpuid_info address +#else + __ movptr(rbp, Address(rsp, 8)); // cpuid_info address +#endif + __ push(rbx); + __ push(rsi); + __ pushf(); // preserve rbx, and flags + __ pop(rax); + __ push(rax); + __ mov(rcx, rax); + // + // if we are unable to change the AC flag, we have a 386 + // + __ xorl(rax, HS_EFL_AC); + __ push(rax); + __ popf(); + __ pushf(); + __ pop(rax); + __ cmpptr(rax, rcx); + __ jccb(Assembler::notEqual, detect_486); + + __ movl(rax, CPU_FAMILY_386); + __ jmp(done); + + // + // If we are unable to change the ID flag, we have a 486 which does + // not support the "cpuid" instruction. + // + __ bind(detect_486); + __ mov(rax, rcx); + __ xorl(rax, HS_EFL_ID); + __ push(rax); + __ popf(); + __ pushf(); + __ pop(rax); + __ cmpptr(rcx, rax); + __ jccb(Assembler::notEqual, detect_586); + + __ bind(cpu486); + __ movl(rax, CPU_FAMILY_486); + __ jmp(done); + + // + // At this point, we have a chip which supports the "cpuid" instruction + // + __ bind(detect_586); + __ xorl(rax, rax); + __ cpuid(); + __ orl(rax, rax); + __ jcc(Assembler::equal, cpu486); // if cpuid doesn't support an input + // value of at least 1, we give up and + // assume a 486 + + // + // Extended cpuid(0x80000000) for processor brand string detection + // + __ bind(ext_cpuid); + __ movl(rax, CPUID_EXTENDED_FN); + __ cpuid(); + __ cmpl(rax, CPUID_EXTENDED_FN_4); + __ jcc(Assembler::below, done); + + // + // Extended cpuid(0x80000002) // first 16 bytes in brand string + // + __ movl(rax, CPUID_EXTENDED_FN_2); + __ cpuid(); + __ lea(rsi, Address(rbp, in_bytes(VM_Version::proc_name_0_offset()))); + __ movl(Address(rsi, 0), rax); + __ lea(rsi, Address(rbp, in_bytes(VM_Version::proc_name_1_offset()))); + __ movl(Address(rsi, 0), rbx); + __ lea(rsi, Address(rbp, in_bytes(VM_Version::proc_name_2_offset()))); + __ movl(Address(rsi, 0), rcx); + __ lea(rsi, Address(rbp, in_bytes(VM_Version::proc_name_3_offset()))); + __ movl(Address(rsi,0), rdx); + + // + // Extended cpuid(0x80000003) // next 16 bytes in brand string + // + __ movl(rax, CPUID_EXTENDED_FN_3); + __ cpuid(); + __ lea(rsi, Address(rbp, in_bytes(VM_Version::proc_name_4_offset()))); + __ movl(Address(rsi, 0), rax); + __ lea(rsi, Address(rbp, in_bytes(VM_Version::proc_name_5_offset()))); + __ movl(Address(rsi, 0), rbx); + __ lea(rsi, Address(rbp, in_bytes(VM_Version::proc_name_6_offset()))); + __ movl(Address(rsi, 0), rcx); + __ lea(rsi, Address(rbp, in_bytes(VM_Version::proc_name_7_offset()))); + __ movl(Address(rsi,0), rdx); + + // + // Extended cpuid(0x80000004) // last 16 bytes in brand string + // + __ movl(rax, CPUID_EXTENDED_FN_4); + __ cpuid(); + __ lea(rsi, Address(rbp, in_bytes(VM_Version::proc_name_8_offset()))); + __ movl(Address(rsi, 0), rax); + __ lea(rsi, Address(rbp, in_bytes(VM_Version::proc_name_9_offset()))); + __ movl(Address(rsi, 0), rbx); + __ lea(rsi, Address(rbp, in_bytes(VM_Version::proc_name_10_offset()))); + __ movl(Address(rsi, 0), rcx); + __ lea(rsi, Address(rbp, in_bytes(VM_Version::proc_name_11_offset()))); + __ movl(Address(rsi,0), rdx); + + // + // return + // + __ bind(done); + __ popf(); + __ pop(rsi); + __ pop(rbx); + __ pop(rbp); + __ ret(0); + # undef __ return start; @@ -1878,6 +2034,19 @@ void VM_Version::check_virtualizations() { } } +// avx3_threshold() sets the threshold at which 64-byte instructions are used +// for implementing the array copy and clear operations. +// The Intel platforms that supports the serialize instruction +// has improved implementation of 64-byte load/stores and so the default +// threshold is set to 0 for these platforms. +int VM_Version::avx3_threshold() { + return (is_intel_family_core() && + supports_serialize() && + FLAG_IS_DEFAULT(AVX3Threshold)) ? 0 : AVX3Threshold; +} + +static bool _vm_version_initialized = false; + void VM_Version::initialize() { ResourceMark rm; // Making this stub must be FIRST use of assembler @@ -1900,4 +2069,757 @@ void VM_Version::initialize() { if (VM_Version::supports_hv()) { // Supports hypervisor check_virtualizations(); } + _vm_version_initialized = true; +} + +typedef enum { + CPU_FAMILY_8086_8088 = 0, + CPU_FAMILY_INTEL_286 = 2, + CPU_FAMILY_INTEL_386 = 3, + CPU_FAMILY_INTEL_486 = 4, + CPU_FAMILY_PENTIUM = 5, + CPU_FAMILY_PENTIUMPRO = 6, // Same family several models + CPU_FAMILY_PENTIUM_4 = 0xF +} FamilyFlag; + +typedef enum { + RDTSCP_FLAG = 0x08000000, // bit 27 + INTEL64_FLAG = 0x20000000 // bit 29 +} _featureExtendedEdxFlag; + +typedef enum { + FPU_FLAG = 0x00000001, + VME_FLAG = 0x00000002, + DE_FLAG = 0x00000004, + PSE_FLAG = 0x00000008, + TSC_FLAG = 0x00000010, + MSR_FLAG = 0x00000020, + PAE_FLAG = 0x00000040, + MCE_FLAG = 0x00000080, + CX8_FLAG = 0x00000100, + APIC_FLAG = 0x00000200, + SEP_FLAG = 0x00000800, + MTRR_FLAG = 0x00001000, + PGE_FLAG = 0x00002000, + MCA_FLAG = 0x00004000, + CMOV_FLAG = 0x00008000, + PAT_FLAG = 0x00010000, + PSE36_FLAG = 0x00020000, + PSNUM_FLAG = 0x00040000, + CLFLUSH_FLAG = 0x00080000, + DTS_FLAG = 0x00200000, + ACPI_FLAG = 0x00400000, + MMX_FLAG = 0x00800000, + FXSR_FLAG = 0x01000000, + SSE_FLAG = 0x02000000, + SSE2_FLAG = 0x04000000, + SS_FLAG = 0x08000000, + HTT_FLAG = 0x10000000, + TM_FLAG = 0x20000000 +} FeatureEdxFlag; + +static BufferBlob* cpuid_brand_string_stub_blob; +static const int cpuid_brand_string_stub_size = 550; + +extern "C" { + typedef void (*getCPUIDBrandString_stub_t)(void*); +} + +static getCPUIDBrandString_stub_t getCPUIDBrandString_stub = NULL; + +// VM_Version statics +enum { + ExtendedFamilyIdLength_INTEL = 16, + ExtendedFamilyIdLength_AMD = 24 +}; + +const size_t VENDOR_LENGTH = 13; +const size_t CPU_EBS_MAX_LENGTH = (3 * 4 * 4 + 1); +static char* _cpu_brand_string = NULL; +static int64_t _max_qualified_cpu_frequency = 0; + +static int _no_of_threads = 0; +static int _no_of_cores = 0; + +const char* const _family_id_intel[ExtendedFamilyIdLength_INTEL] = { + "8086/8088", + "", + "286", + "386", + "486", + "Pentium", + "Pentium Pro", //or Pentium-M/Woodcrest depeding on model + "", + "", + "", + "", + "", + "", + "", + "", + "Pentium 4" +}; + +const char* const _family_id_amd[ExtendedFamilyIdLength_AMD] = { + "", + "", + "", + "", + "5x86", + "K5/K6", + "Athlon/AthlonXP", + "", + "", + "", + "", + "", + "", + "", + "", + "Opteron/Athlon64", + "Opteron QC/Phenom", // Barcelona et.al. + "", + "", + "", + "", + "", + "", + "Zen" +}; +// Partially from Intel 64 and IA-32 Architecture Software Developer's Manual, +// September 2013, Vol 3C Table 35-1 +const char* const _model_id_pentium_pro[] = { + "", + "Pentium Pro", + "", + "Pentium II model 3", + "", + "Pentium II model 5/Xeon/Celeron", + "Celeron", + "Pentium III/Pentium III Xeon", + "Pentium III/Pentium III Xeon", + "Pentium M model 9", // Yonah + "Pentium III, model A", + "Pentium III, model B", + "", + "Pentium M model D", // Dothan + "", + "Core 2", // 0xf Woodcrest/Conroe/Merom/Kentsfield/Clovertown + "", + "", + "", + "", + "", + "", + "Celeron", // 0x16 Celeron 65nm + "Core 2", // 0x17 Penryn / Harpertown + "", + "", + "Core i7", // 0x1A CPU_MODEL_NEHALEM_EP + "Atom", // 0x1B Z5xx series Silverthorn + "", + "Core 2", // 0x1D Dunnington (6-core) + "Nehalem", // 0x1E CPU_MODEL_NEHALEM + "", + "", + "", + "", + "", + "", + "Westmere", // 0x25 CPU_MODEL_WESTMERE + "", + "", + "", // 0x28 + "", + "Sandy Bridge", // 0x2a "2nd Generation Intel Core i7, i5, i3" + "", + "Westmere-EP", // 0x2c CPU_MODEL_WESTMERE_EP + "Sandy Bridge-EP", // 0x2d CPU_MODEL_SANDYBRIDGE_EP + "Nehalem-EX", // 0x2e CPU_MODEL_NEHALEM_EX + "Westmere-EX", // 0x2f CPU_MODEL_WESTMERE_EX + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Ivy Bridge", // 0x3a + "", + "Haswell", // 0x3c "4th Generation Intel Core Processor" + "", // 0x3d "Next Generation Intel Core Processor" + "Ivy Bridge-EP", // 0x3e "Next Generation Intel Xeon Processor E7 Family" + "", // 0x3f "Future Generation Intel Xeon Processor" + "", + "", + "", + "", + "", + "Haswell", // 0x45 "4th Generation Intel Core Processor" + "Haswell", // 0x46 "4th Generation Intel Core Processor" + NULL +}; + +/* Brand ID is for back compability + * Newer CPUs uses the extended brand string */ +const char* const _brand_id[] = { + "", + "Celeron processor", + "Pentium III processor", + "Intel Pentium III Xeon processor", + "", + "", + "", + "", + "Intel Pentium 4 processor", + NULL +}; + + +const char* const _feature_edx_id[] = { + "On-Chip FPU", + "Virtual Mode Extensions", + "Debugging Extensions", + "Page Size Extensions", + "Time Stamp Counter", + "Model Specific Registers", + "Physical Address Extension", + "Machine Check Exceptions", + "CMPXCHG8B Instruction", + "On-Chip APIC", + "", + "Fast System Call", + "Memory Type Range Registers", + "Page Global Enable", + "Machine Check Architecture", + "Conditional Mov Instruction", + "Page Attribute Table", + "36-bit Page Size Extension", + "Processor Serial Number", + "CLFLUSH Instruction", + "", + "Debug Trace Store feature", + "ACPI registers in MSR space", + "Intel Architecture MMX Technology", + "Fast Float Point Save and Restore", + "Streaming SIMD extensions", + "Streaming SIMD extensions 2", + "Self-Snoop", + "Hyper Threading", + "Thermal Monitor", + "", + "Pending Break Enable" +}; + +const char* const _feature_extended_edx_id[] = { + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "SYSCALL/SYSRET", + "", + "", + "", + "", + "", + "", + "", + "", + "Execute Disable Bit", + "", + "", + "", + "", + "", + "", + "RDTSCP", + "", + "Intel 64 Architecture", + "", + "" +}; + +const char* const _feature_ecx_id[] = { + "Streaming SIMD Extensions 3", + "PCLMULQDQ", + "64-bit DS Area", + "MONITOR/MWAIT instructions", + "CPL Qualified Debug Store", + "Virtual Machine Extensions", + "Safer Mode Extensions", + "Enhanced Intel SpeedStep technology", + "Thermal Monitor 2", + "Supplemental Streaming SIMD Extensions 3", + "L1 Context ID", + "", + "Fused Multiply-Add", + "CMPXCHG16B", + "xTPR Update Control", + "Perfmon and Debug Capability", + "", + "Process-context identifiers", + "Direct Cache Access", + "Streaming SIMD extensions 4.1", + "Streaming SIMD extensions 4.2", + "x2APIC", + "MOVBE", + "Popcount instruction", + "TSC-Deadline", + "AESNI", + "XSAVE", + "OSXSAVE", + "AVX", + "F16C", + "RDRAND", + "" +}; + +const char* const _feature_extended_ecx_id[] = { + "LAHF/SAHF instruction support", + "Core multi-processor legacy mode", + "", + "", + "", + "Advanced Bit Manipulations: LZCNT", + "SSE4A: MOVNTSS, MOVNTSD, EXTRQ, INSERTQ", + "Misaligned SSE mode", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" +}; + +void VM_Version::initialize_tsc(void) { + ResourceMark rm; + + cpuid_brand_string_stub_blob = BufferBlob::create("getCPUIDBrandString_stub", cpuid_brand_string_stub_size); + if (cpuid_brand_string_stub_blob == NULL) { + vm_exit_during_initialization("Unable to allocate getCPUIDBrandString_stub"); + } + CodeBuffer c(cpuid_brand_string_stub_blob); + VM_Version_StubGenerator g(&c); + getCPUIDBrandString_stub = CAST_TO_FN_PTR(getCPUIDBrandString_stub_t, + g.generate_getCPUIDBrandString()); +} + +const char* VM_Version::cpu_model_description(void) { + uint32_t cpu_family = extended_cpu_family(); + uint32_t cpu_model = extended_cpu_model(); + const char* model = NULL; + + if (cpu_family == CPU_FAMILY_PENTIUMPRO) { + for (uint32_t i = 0; i <= cpu_model; i++) { + model = _model_id_pentium_pro[i]; + if (model == NULL) { + break; + } + } + } + return model; +} + +const char* VM_Version::cpu_brand_string(void) { + if (_cpu_brand_string == NULL) { + _cpu_brand_string = NEW_C_HEAP_ARRAY_RETURN_NULL(char, CPU_EBS_MAX_LENGTH, mtInternal); + if (NULL == _cpu_brand_string) { + return NULL; + } + int ret_val = cpu_extended_brand_string(_cpu_brand_string, CPU_EBS_MAX_LENGTH); + if (ret_val != OS_OK) { + FREE_C_HEAP_ARRAY(char, _cpu_brand_string); + _cpu_brand_string = NULL; + } + } + return _cpu_brand_string; +} + +const char* VM_Version::cpu_brand(void) { + const char* brand = NULL; + + if ((_cpuid_info.std_cpuid1_ebx.value & 0xFF) > 0) { + int brand_num = _cpuid_info.std_cpuid1_ebx.value & 0xFF; + brand = _brand_id[0]; + for (int i = 0; brand != NULL && i <= brand_num; i += 1) { + brand = _brand_id[i]; + } + } + return brand; +} + +bool VM_Version::cpu_is_em64t(void) { + return ((_cpuid_info.ext_cpuid1_edx.value & INTEL64_FLAG) == INTEL64_FLAG); +} + +bool VM_Version::is_netburst(void) { + return (is_intel() && (extended_cpu_family() == CPU_FAMILY_PENTIUM_4)); +} + +bool VM_Version::supports_tscinv_ext(void) { + if (!supports_tscinv_bit()) { + return false; + } + + if (is_intel()) { + return true; + } + + if (is_amd()) { + return !is_amd_Barcelona(); + } + + if (is_hygon()) { + return true; + } + + return false; +} + +void VM_Version::resolve_cpu_information_details(void) { + + // in future we want to base this information on proper cpu + // and cache topology enumeration such as: + // Intel 64 Architecture Processor Topology Enumeration + // which supports system cpu and cache topology enumeration + // either using 2xAPICIDs or initial APICIDs + + // currently only rough cpu information estimates + // which will not necessarily reflect the exact configuration of the system + + // this is the number of logical hardware threads + // visible to the operating system + _no_of_threads = os::processor_count(); + + // find out number of threads per cpu package + int threads_per_package = threads_per_core() * cores_per_cpu(); + + // use amount of threads visible to the process in order to guess number of sockets + _no_of_sockets = _no_of_threads / threads_per_package; + + // process might only see a subset of the total number of threads + // from a single processor package. Virtualization/resource management for example. + // If so then just write a hard 1 as num of pkgs. + if (0 == _no_of_sockets) { + _no_of_sockets = 1; + } + + // estimate the number of cores + _no_of_cores = cores_per_cpu() * _no_of_sockets; +} + + +const char* VM_Version::cpu_family_description(void) { + int cpu_family_id = extended_cpu_family(); + if (is_amd()) { + if (cpu_family_id < ExtendedFamilyIdLength_AMD) { + return _family_id_amd[cpu_family_id]; + } + } + if (is_intel()) { + if (cpu_family_id == CPU_FAMILY_PENTIUMPRO) { + return cpu_model_description(); + } + if (cpu_family_id < ExtendedFamilyIdLength_INTEL) { + return _family_id_intel[cpu_family_id]; + } + } + if (is_hygon()) { + return "Dhyana"; + } + return "Unknown x86"; +} + +int VM_Version::cpu_type_description(char* const buf, size_t buf_len) { + assert(buf != NULL, "buffer is NULL!"); + assert(buf_len >= CPU_TYPE_DESC_BUF_SIZE, "buffer len should at least be == CPU_TYPE_DESC_BUF_SIZE!"); + + const char* cpu_type = NULL; + const char* x64 = NULL; + + if (is_intel()) { + cpu_type = "Intel"; + x64 = cpu_is_em64t() ? " Intel64" : ""; + } else if (is_amd()) { + cpu_type = "AMD"; + x64 = cpu_is_em64t() ? " AMD64" : ""; + } else if (is_hygon()) { + cpu_type = "Hygon"; + x64 = cpu_is_em64t() ? " AMD64" : ""; + } else { + cpu_type = "Unknown x86"; + x64 = cpu_is_em64t() ? " x86_64" : ""; + } + + jio_snprintf(buf, buf_len, "%s %s%s SSE SSE2%s%s%s%s%s%s%s%s", + cpu_type, + cpu_family_description(), + supports_ht() ? " (HT)" : "", + supports_sse3() ? " SSE3" : "", + supports_ssse3() ? " SSSE3" : "", + supports_sse4_1() ? " SSE4.1" : "", + supports_sse4_2() ? " SSE4.2" : "", + supports_sse4a() ? " SSE4A" : "", + is_netburst() ? " Netburst" : "", + is_intel_family_core() ? " Core" : "", + x64); + + return OS_OK; +} + +int VM_Version::cpu_extended_brand_string(char* const buf, size_t buf_len) { + assert(buf != NULL, "buffer is NULL!"); + assert(buf_len >= CPU_EBS_MAX_LENGTH, "buffer len should at least be == CPU_EBS_MAX_LENGTH!"); + assert(getCPUIDBrandString_stub != NULL, "not initialized"); + + // invoke newly generated asm code to fetch CPU Brand String + getCPUIDBrandString_stub(&_cpuid_info); + + // fetch results into buffer + *((uint32_t*) &buf[0]) = _cpuid_info.proc_name_0; + *((uint32_t*) &buf[4]) = _cpuid_info.proc_name_1; + *((uint32_t*) &buf[8]) = _cpuid_info.proc_name_2; + *((uint32_t*) &buf[12]) = _cpuid_info.proc_name_3; + *((uint32_t*) &buf[16]) = _cpuid_info.proc_name_4; + *((uint32_t*) &buf[20]) = _cpuid_info.proc_name_5; + *((uint32_t*) &buf[24]) = _cpuid_info.proc_name_6; + *((uint32_t*) &buf[28]) = _cpuid_info.proc_name_7; + *((uint32_t*) &buf[32]) = _cpuid_info.proc_name_8; + *((uint32_t*) &buf[36]) = _cpuid_info.proc_name_9; + *((uint32_t*) &buf[40]) = _cpuid_info.proc_name_10; + *((uint32_t*) &buf[44]) = _cpuid_info.proc_name_11; + + return OS_OK; } + +size_t VM_Version::cpu_write_support_string(char* const buf, size_t buf_len) { + guarantee(buf != NULL, "buffer is NULL!"); + guarantee(buf_len > 0, "buffer len not enough!"); + + unsigned int flag = 0; + unsigned int fi = 0; + size_t written = 0; + const char* prefix = ""; + +#define WRITE_TO_BUF(string) \ + { \ + int res = jio_snprintf(&buf[written], buf_len - written, "%s%s", prefix, string); \ + if (res < 0) { \ + return buf_len - 1; \ + } \ + written += res; \ + if (prefix[0] == '\0') { \ + prefix = ", "; \ + } \ + } + + for (flag = 1, fi = 0; flag <= 0x20000000 ; flag <<= 1, fi++) { + if (flag == HTT_FLAG && (((_cpuid_info.std_cpuid1_ebx.value >> 16) & 0xff) <= 1)) { + continue; /* no hyperthreading */ + } else if (flag == SEP_FLAG && (cpu_family() == CPU_FAMILY_PENTIUMPRO && ((_cpuid_info.std_cpuid1_eax.value & 0xff) < 0x33))) { + continue; /* no fast system call */ + } + if ((_cpuid_info.std_cpuid1_edx.value & flag) && strlen(_feature_edx_id[fi]) > 0) { + WRITE_TO_BUF(_feature_edx_id[fi]); + } + } + + for (flag = 1, fi = 0; flag <= 0x20000000; flag <<= 1, fi++) { + if ((_cpuid_info.std_cpuid1_ecx.value & flag) && strlen(_feature_ecx_id[fi]) > 0) { + WRITE_TO_BUF(_feature_ecx_id[fi]); + } + } + + for (flag = 1, fi = 0; flag <= 0x20000000 ; flag <<= 1, fi++) { + if ((_cpuid_info.ext_cpuid1_ecx.value & flag) && strlen(_feature_extended_ecx_id[fi]) > 0) { + WRITE_TO_BUF(_feature_extended_ecx_id[fi]); + } + } + + for (flag = 1, fi = 0; flag <= 0x20000000; flag <<= 1, fi++) { + if ((_cpuid_info.ext_cpuid1_edx.value & flag) && strlen(_feature_extended_edx_id[fi]) > 0) { + WRITE_TO_BUF(_feature_extended_edx_id[fi]); + } + } + + if (supports_tscinv_bit()) { + WRITE_TO_BUF("Invariant TSC"); + } + + return written; +} + +/** + * Write a detailed description of the cpu to a given buffer, including + * feature set. + */ +int VM_Version::cpu_detailed_description(char* const buf, size_t buf_len) { + assert(buf != NULL, "buffer is NULL!"); + assert(buf_len >= CPU_DETAILED_DESC_BUF_SIZE, "buffer len should at least be == CPU_DETAILED_DESC_BUF_SIZE!"); + + static const char* unknown = ""; + char vendor_id[VENDOR_LENGTH]; + const char* family = NULL; + const char* model = NULL; + const char* brand = NULL; + int outputLen = 0; + + family = cpu_family_description(); + if (family == NULL) { + family = unknown; + } + + model = cpu_model_description(); + if (model == NULL) { + model = unknown; + } + + brand = cpu_brand_string(); + + if (brand == NULL) { + brand = cpu_brand(); + if (brand == NULL) { + brand = unknown; + } + } + + *((uint32_t*) &vendor_id[0]) = _cpuid_info.std_vendor_name_0; + *((uint32_t*) &vendor_id[4]) = _cpuid_info.std_vendor_name_2; + *((uint32_t*) &vendor_id[8]) = _cpuid_info.std_vendor_name_1; + vendor_id[VENDOR_LENGTH-1] = '\0'; + + outputLen = jio_snprintf(buf, buf_len, "Brand: %s, Vendor: %s\n" + "Family: %s (0x%x), Model: %s (0x%x), Stepping: 0x%x\n" + "Ext. family: 0x%x, Ext. model: 0x%x, Type: 0x%x, Signature: 0x%8.8x\n" + "Features: ebx: 0x%8.8x, ecx: 0x%8.8x, edx: 0x%8.8x\n" + "Ext. features: eax: 0x%8.8x, ebx: 0x%8.8x, ecx: 0x%8.8x, edx: 0x%8.8x\n" + "Supports: ", + brand, + vendor_id, + family, + extended_cpu_family(), + model, + extended_cpu_model(), + cpu_stepping(), + _cpuid_info.std_cpuid1_eax.bits.ext_family, + _cpuid_info.std_cpuid1_eax.bits.ext_model, + _cpuid_info.std_cpuid1_eax.bits.proc_type, + _cpuid_info.std_cpuid1_eax.value, + _cpuid_info.std_cpuid1_ebx.value, + _cpuid_info.std_cpuid1_ecx.value, + _cpuid_info.std_cpuid1_edx.value, + _cpuid_info.ext_cpuid1_eax, + _cpuid_info.ext_cpuid1_ebx, + _cpuid_info.ext_cpuid1_ecx, + _cpuid_info.ext_cpuid1_edx); + + if (outputLen < 0 || (size_t) outputLen >= buf_len - 1) { + if (buf_len > 0) { buf[buf_len-1] = '\0'; } + return OS_ERR; + } + + cpu_write_support_string(&buf[outputLen], buf_len - outputLen); + + return OS_OK; +} + + +// Fill in Abstract_VM_Version statics +void VM_Version::initialize_cpu_information() { + assert(_vm_version_initialized, "should have initialized VM_Version long ago"); + assert(!_initialized, "shouldn't be initialized yet"); + resolve_cpu_information_details(); + + // initialize cpu_name and cpu_desc + cpu_type_description(_cpu_name, CPU_TYPE_DESC_BUF_SIZE); + cpu_detailed_description(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE); + _initialized = true; +} + +/** + * For information about extracting the frequency from the cpu brand string, please see: + * + * Intel Processor Identification and the CPUID Instruction + * Application Note 485 + * May 2012 + * + * The return value is the frequency in Hz. + */ +int64_t VM_Version::max_qualified_cpu_freq_from_brand_string(void) { + const char* const brand_string = cpu_brand_string(); + if (brand_string == NULL) { + return 0; + } + const int64_t MEGA = 1000000; + int64_t multiplier = 0; + int64_t frequency = 0; + uint8_t idx = 0; + // The brand string buffer is at most 48 bytes. + // -2 is to prevent buffer overrun when looking for y in yHz, as z is +2 from y. + for (; idx < 48-2; ++idx) { + // Format is either "x.xxyHz" or "xxxxyHz", where y=M, G, T and x are digits. + // Search brand string for "yHz" where y is M, G, or T. + if (brand_string[idx+1] == 'H' && brand_string[idx+2] == 'z') { + if (brand_string[idx] == 'M') { + multiplier = MEGA; + } else if (brand_string[idx] == 'G') { + multiplier = MEGA * 1000; + } else if (brand_string[idx] == 'T') { + multiplier = MEGA * MEGA; + } + break; + } + } + if (multiplier > 0) { + // Compute freqency (in Hz) from brand string. + if (brand_string[idx-3] == '.') { // if format is "x.xx" + frequency = (brand_string[idx-4] - '0') * multiplier; + frequency += (brand_string[idx-2] - '0') * multiplier / 10; + frequency += (brand_string[idx-1] - '0') * multiplier / 100; + } else { // format is "xxxx" + frequency = (brand_string[idx-4] - '0') * 1000; + frequency += (brand_string[idx-3] - '0') * 100; + frequency += (brand_string[idx-2] - '0') * 10; + frequency += (brand_string[idx-1] - '0'); + frequency *= multiplier; + } + } + return frequency; +} + + +int64_t VM_Version::maximum_qualified_cpu_frequency(void) { + if (_max_qualified_cpu_frequency == 0) { + _max_qualified_cpu_frequency = max_qualified_cpu_freq_from_brand_string(); + } + return _max_qualified_cpu_frequency; +} + diff --git a/src/hotspot/cpu/x86/vm_version_x86.hpp b/src/hotspot/cpu/x86/vm_version_x86.hpp index 6feb3b8c1a0a6ec18ce98ecb47d7f05250cd65e0..27342dbdc96823227bc85fb2b2e65e4d8185b5f1 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.hpp +++ b/src/hotspot/cpu/x86/vm_version_x86.hpp @@ -371,7 +371,7 @@ protected: static const char* _features_names[]; -enum Extended_Family { + enum Extended_Family { // AMD CPU_FAMILY_AMD_11H = 0x11, // ZX @@ -911,6 +911,8 @@ public: static bool is_intel_skylake() { return is_intel_family_core() && extended_cpu_model() == CPU_MODEL_SKYLAKE; } + static int avx3_threshold(); + static bool is_intel_tsc_synched_at_init() { if (is_intel_family_core()) { uint32_t ext_model = extended_cpu_model(); @@ -1051,6 +1053,45 @@ public: // support functions for virtualization detection private: static void check_virtualizations(); + + static const char* cpu_family_description(void); + static const char* cpu_model_description(void); + static const char* cpu_brand(void); + static const char* cpu_brand_string(void); + + static int cpu_type_description(char* const buf, size_t buf_len); + static int cpu_detailed_description(char* const buf, size_t buf_len); + static int cpu_extended_brand_string(char* const buf, size_t buf_len); + + static bool cpu_is_em64t(void); + static bool is_netburst(void); + + // Returns bytes written excluding termninating null byte. + static size_t cpu_write_support_string(char* const buf, size_t buf_len); + static void resolve_cpu_information_details(void); + static int64_t max_qualified_cpu_freq_from_brand_string(void); + + public: + // Offsets for cpuid asm stub brand string + static ByteSize proc_name_0_offset() { return byte_offset_of(CpuidInfo, proc_name_0); } + static ByteSize proc_name_1_offset() { return byte_offset_of(CpuidInfo, proc_name_1); } + static ByteSize proc_name_2_offset() { return byte_offset_of(CpuidInfo, proc_name_2); } + static ByteSize proc_name_3_offset() { return byte_offset_of(CpuidInfo, proc_name_3); } + static ByteSize proc_name_4_offset() { return byte_offset_of(CpuidInfo, proc_name_4); } + static ByteSize proc_name_5_offset() { return byte_offset_of(CpuidInfo, proc_name_5); } + static ByteSize proc_name_6_offset() { return byte_offset_of(CpuidInfo, proc_name_6); } + static ByteSize proc_name_7_offset() { return byte_offset_of(CpuidInfo, proc_name_7); } + static ByteSize proc_name_8_offset() { return byte_offset_of(CpuidInfo, proc_name_8); } + static ByteSize proc_name_9_offset() { return byte_offset_of(CpuidInfo, proc_name_9); } + static ByteSize proc_name_10_offset() { return byte_offset_of(CpuidInfo, proc_name_10); } + static ByteSize proc_name_11_offset() { return byte_offset_of(CpuidInfo, proc_name_11); } + + static int64_t maximum_qualified_cpu_frequency(void); + + static bool supports_tscinv_ext(void); + + static void initialize_tsc(); + static void initialize_cpu_information(void); }; #endif // CPU_X86_VM_VERSION_X86_HPP diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index 3f6d5a44b0dbaf15e3937226ee62bfeb924c200c..b37681eddacdd5f690cc23b25a7eda5b45805d94 100644 --- a/src/hotspot/cpu/x86/x86.ad +++ b/src/hotspot/cpu/x86/x86.ad @@ -1382,6 +1382,8 @@ Assembler::Width widthForType(BasicType bt) { static address vector_long_shufflemask() { return StubRoutines::x86::vector_long_shuffle_mask(); } static address vector_32_bit_mask() { return StubRoutines::x86::vector_32_bit_mask(); } static address vector_64_bit_mask() { return StubRoutines::x86::vector_64_bit_mask(); } + static address vector_float_signflip() { return StubRoutines::x86::vector_float_sign_flip();} + static address vector_double_signflip() { return StubRoutines::x86::vector_double_sign_flip();} //============================================================================= const bool Matcher::match_rule_supported(int opcode) { @@ -1792,13 +1794,19 @@ const bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType return false; } break; - case Op_VectorCastF2X: case Op_VectorCastD2X: - if (is_integral_type(bt)) { - // Casts from FP to integral types require special fixup logic not easily - // implementable with vectors. - return false; // Implementation limitation + if (is_subword_type(bt) || bt == T_INT) { + return false; } + if (bt == T_LONG && !VM_Version::supports_avx512dq()) { + return false; + } + break; + case Op_VectorCastF2X: + if (is_subword_type(bt) || bt == T_LONG) { + return false; + } + break; case Op_MulReductionVI: if (bt == T_BYTE && size_in_bits == 512 && !VM_Version::supports_avx512bw()) { return false; @@ -1834,6 +1842,14 @@ const bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType return false; } break; + case Op_VectorLongToMask: + if (UseAVX < 1 || !is_LP64) { + return false; + } + if (UseAVX < 3 && !VM_Version::supports_bmi2()) { + return false; + } + break; } return true; // Per default match rules are supported. } @@ -2043,7 +2059,7 @@ const RegMask* Matcher::predicate_reg_mask(void) { return &_VECTMASK_REG_mask; } -const TypeVect* Matcher::predicate_reg_type(const Type* elemTy, int length) { +const TypeVectMask* Matcher::predicate_reg_type(const Type* elemTy, int length) { return new TypeVectMask(elemTy, length); } @@ -7157,7 +7173,7 @@ instruct vcastLtoX_evex(vec dst, vec src) %{ instruct vcastFtoD_reg(vec dst, vec src) %{ predicate(Matcher::vector_element_basic_type(n) == T_DOUBLE); match(Set dst (VectorCastF2X src)); - format %{ "vector_cast_f2x $dst,$src\t!" %} + format %{ "vector_cast_f2d $dst,$src\t!" %} ins_encode %{ int vlen_enc = vector_length_encoding(this); __ vcvtps2pd($dst$$XMMRegister, $src$$XMMRegister, vlen_enc); @@ -7165,6 +7181,38 @@ instruct vcastFtoD_reg(vec dst, vec src) %{ ins_pipe( pipe_slow ); %} +instruct vcastFtoI_reg_avx(vec dst, vec src, vec xtmp1, vec xtmp2, vec xtmp3, vec xtmp4, rRegP scratch, rFlagsReg cr) %{ + predicate(!VM_Version::supports_avx512vl() && + Matcher::vector_length_in_bytes(n) < 64 && + Matcher::vector_element_basic_type(n) == T_INT); + match(Set dst (VectorCastF2X src)); + effect(TEMP dst, TEMP xtmp1, TEMP xtmp2, TEMP xtmp3, TEMP xtmp4, TEMP scratch, KILL cr); + format %{ "vector_cast_f2i $dst,$src\t! using $xtmp1, $xtmp2, $xtmp3 and $xtmp4 as TEMP" %} + ins_encode %{ + int vlen_enc = vector_length_encoding(this); + __ vector_castF2I_avx($dst$$XMMRegister, $src$$XMMRegister, $xtmp1$$XMMRegister, + $xtmp2$$XMMRegister, $xtmp3$$XMMRegister, $xtmp4$$XMMRegister, + ExternalAddress(vector_float_signflip()), $scratch$$Register, vlen_enc); + %} + ins_pipe( pipe_slow ); +%} + +instruct vcastFtoI_reg_evex(vec dst, vec src, vec xtmp1, vec xtmp2, kReg ktmp1, kReg ktmp2, rRegP scratch, rFlagsReg cr) %{ + predicate((VM_Version::supports_avx512vl() || + Matcher::vector_length_in_bytes(n) == 64) && + Matcher::vector_element_basic_type(n) == T_INT); + match(Set dst (VectorCastF2X src)); + effect(TEMP dst, TEMP xtmp1, TEMP xtmp2, TEMP ktmp1, TEMP ktmp2, TEMP scratch, KILL cr); + format %{ "vector_cast_f2i $dst,$src\t! using $xtmp1, $xtmp2, $ktmp1 and $ktmp2 as TEMP" %} + ins_encode %{ + int vlen_enc = vector_length_encoding(this); + __ vector_castF2I_evex($dst$$XMMRegister, $src$$XMMRegister, $xtmp1$$XMMRegister, + $xtmp2$$XMMRegister, $ktmp1$$KRegister, $ktmp2$$KRegister, + ExternalAddress(vector_float_signflip()), $scratch$$Register, vlen_enc); + %} + ins_pipe( pipe_slow ); +%} + instruct vcastDtoF_reg(vec dst, vec src) %{ predicate(Matcher::vector_element_basic_type(n) == T_FLOAT); match(Set dst (VectorCastD2X src)); @@ -7176,6 +7224,20 @@ instruct vcastDtoF_reg(vec dst, vec src) %{ ins_pipe( pipe_slow ); %} +instruct vcastDtoL_reg_evex(vec dst, vec src, vec xtmp1, vec xtmp2, kReg ktmp1, kReg ktmp2, rRegP scratch, rFlagsReg cr) %{ + predicate(Matcher::vector_element_basic_type(n) == T_LONG); + match(Set dst (VectorCastD2X src)); + effect(TEMP dst, TEMP xtmp1, TEMP xtmp2, TEMP ktmp1, TEMP ktmp2, TEMP scratch, KILL cr); + format %{ "vector_cast_d2l $dst,$src\t! using $xtmp1, $xtmp2, $ktmp1 and $ktmp2 as TEMP" %} + ins_encode %{ + int vlen_enc = vector_length_encoding(this); + __ vector_castD2L_evex($dst$$XMMRegister, $src$$XMMRegister, $xtmp1$$XMMRegister, + $xtmp2$$XMMRegister, $ktmp1$$KRegister, $ktmp2$$KRegister, + ExternalAddress(vector_double_signflip()), $scratch$$Register, vlen_enc); + %} + ins_pipe( pipe_slow ); +%} + // --------------------------------- VectorMaskCmp -------------------------------------- instruct vcmpFD(legVec dst, legVec src1, legVec src2, immI8 cond) %{ @@ -8647,43 +8709,45 @@ instruct vmask_tolong_evex(rRegL dst, kReg mask, rFlagsReg cr) %{ effect(TEMP dst, KILL cr); format %{ "vector_tolong_evex $dst, $mask \t! vector mask tolong" %} ins_encode %{ - int mask_len = Matcher::vector_length(this, $mask); + int opcode = this->ideal_Opcode(); BasicType mbt = Matcher::vector_element_basic_type(this, $mask); - if (VM_Version::supports_avx512vlbw()) { - __ kmovql($dst$$Register, $mask$$KRegister); - } else { - assert(mask_len <= 16, ""); - __ kmovwl($dst$$Register, $mask$$KRegister); - } - // Mask generated out of partial vector comparisons/replicate/mask manipulation - // operations needs to be clipped. + int mask_len = Matcher::vector_length(this, $mask); int mask_size = mask_len * type2aelembytes(mbt); - if (mask_size < 16) { - __ andq($dst$$Register, (((jlong)1 << mask_len) - 1)); - } + int vlen_enc = vector_length_encoding(this, $mask); + __ vector_mask_operation(opcode, $dst$$Register, $mask$$KRegister, + $dst$$Register, mask_len, mask_size, vlen_enc); %} ins_pipe( pipe_slow ); %} -instruct vmask_tolong_avx(rRegL dst, vec mask, vec xtmp, rFlagsReg cr) %{ - predicate(n->in(1)->bottom_type()->isa_vectmask() == NULL && - n->in(1)->bottom_type()->is_vect()->element_basic_type() == T_BOOLEAN); +instruct vmask_tolong_bool(rRegL dst, vec mask, vec xtmp, rFlagsReg cr) %{ + predicate(n->in(1)->bottom_type()->isa_vectmask() == NULL); match(Set dst (VectorMaskToLong mask)); - format %{ "vector_tolong_avx $dst, $mask \t! using $xtmp as TEMP" %} + format %{ "vector_tolong_bool $dst, $mask \t! using $xtmp as TEMP" %} effect(TEMP_DEF dst, TEMP xtmp, KILL cr); ins_encode %{ + int opcode = this->ideal_Opcode(); + BasicType mbt = Matcher::vector_element_basic_type(this, $mask); int mask_len = Matcher::vector_length(this, $mask); + int vlen_enc = vector_length_encoding(this, $mask); + __ vector_mask_operation(opcode, $dst$$Register, $mask$$XMMRegister, $xtmp$$XMMRegister, + $dst$$Register, mask_len, mbt, vlen_enc); + %} + ins_pipe( pipe_slow ); +%} + +instruct vmask_tolong_avx(rRegL dst, vec mask, immI size, vec xtmp, rFlagsReg cr) %{ + predicate(n->in(1)->in(1)->bottom_type()->isa_vectmask() == NULL); + match(Set dst (VectorMaskToLong (VectorStoreMask mask size))); + format %{ "vector_tolong_avx $dst, $mask \t! using $xtmp as TEMP" %} + effect(TEMP_DEF dst, TEMP xtmp, KILL cr); + ins_encode %{ + int opcode = this->ideal_Opcode(); BasicType mbt = Matcher::vector_element_basic_type(this, $mask); + int mask_len = Matcher::vector_length(this, $mask); int vlen_enc = vector_length_encoding(this, $mask); - __ vpxor($xtmp$$XMMRegister, $xtmp$$XMMRegister, $xtmp$$XMMRegister, vlen_enc); - __ vpsubb($xtmp$$XMMRegister, $xtmp$$XMMRegister, $mask$$XMMRegister, vlen_enc); - __ vpmovmskb($dst$$Register, $xtmp$$XMMRegister, vlen_enc); - // Mask generated out of partial vector comparisons/replicate/mask manipulation - // operations needs to be clipped. - int mask_size = mask_len * type2aelembytes(mbt); - if (mask_size < 16) { - __ andq($dst$$Register, (((jlong)1 << mask_len) - 1)); - } + __ vector_mask_operation(opcode, $dst$$Register, $mask$$XMMRegister, $xtmp$$XMMRegister, + $dst$$Register, mask_len, mbt, vlen_enc); %} ins_pipe( pipe_slow ); %} @@ -8699,25 +8763,40 @@ instruct vmask_truecount_evex(rRegI dst, kReg mask, rRegL tmp, rFlagsReg cr) %{ int mask_len = Matcher::vector_length(this, $mask); int mask_size = mask_len * type2aelembytes(mbt); int vlen_enc = vector_length_encoding(this, $mask); - __ vector_mask_operation(opcode, $dst$$Register, $mask$$KRegister, $tmp$$Register, - mask_len, mask_size, vlen_enc); + __ vector_mask_operation(opcode, $dst$$Register, $mask$$KRegister, + $tmp$$Register, mask_len, mask_size, vlen_enc); %} ins_pipe( pipe_slow ); %} -instruct vmask_truecount_avx(rRegI dst, vec mask, rRegL tmp, vec xtmp, vec xtmp1, rFlagsReg cr) %{ +instruct vmask_truecount_bool(rRegI dst, vec mask, rRegL tmp, vec xtmp, rFlagsReg cr) %{ predicate(n->in(1)->bottom_type()->isa_vectmask() == NULL); match(Set dst (VectorMaskTrueCount mask)); - effect(TEMP_DEF dst, TEMP tmp, TEMP xtmp, TEMP xtmp1, KILL cr); - format %{ "vector_truecount_avx $dst, $mask \t! using $tmp, $xtmp and $xtmp1 as TEMP" %} + effect(TEMP_DEF dst, TEMP tmp, TEMP xtmp, KILL cr); + format %{ "vector_truecount_bool $dst, $mask \t! using $tmp, $xtmp as TEMP" %} ins_encode %{ int opcode = this->ideal_Opcode(); BasicType mbt = Matcher::vector_element_basic_type(this, $mask); int mask_len = Matcher::vector_length(this, $mask); - int mask_size = mask_len * type2aelembytes(mbt); int vlen_enc = vector_length_encoding(this, $mask); __ vector_mask_operation(opcode, $dst$$Register, $mask$$XMMRegister, $xtmp$$XMMRegister, - $xtmp1$$XMMRegister, $tmp$$Register, mask_len, mask_size, vlen_enc); + $tmp$$Register, mask_len, mbt, vlen_enc); + %} + ins_pipe( pipe_slow ); +%} + +instruct vmask_truecount_avx(rRegI dst, vec mask, immI size, rRegL tmp, vec xtmp, rFlagsReg cr) %{ + predicate(n->in(1)->in(1)->bottom_type()->isa_vectmask() == NULL); + match(Set dst (VectorMaskTrueCount (VectorStoreMask mask size))); + effect(TEMP_DEF dst, TEMP tmp, TEMP xtmp, KILL cr); + format %{ "vector_truecount_avx $dst, $mask \t! using $tmp, $xtmp as TEMP" %} + ins_encode %{ + int opcode = this->ideal_Opcode(); + BasicType mbt = Matcher::vector_element_basic_type(this, $mask); + int mask_len = Matcher::vector_length(this, $mask); + int vlen_enc = vector_length_encoding(this, $mask); + __ vector_mask_operation(opcode, $dst$$Register, $mask$$XMMRegister, $xtmp$$XMMRegister, + $tmp$$Register, mask_len, mbt, vlen_enc); %} ins_pipe( pipe_slow ); %} @@ -8734,26 +8813,42 @@ instruct vmask_first_or_last_true_evex(rRegI dst, kReg mask, rRegL tmp, rFlagsRe int mask_len = Matcher::vector_length(this, $mask); int mask_size = mask_len * type2aelembytes(mbt); int vlen_enc = vector_length_encoding(this, $mask); - __ vector_mask_operation(opcode, $dst$$Register, $mask$$KRegister, $tmp$$Register, mask_len, - mask_size, vlen_enc); + __ vector_mask_operation(opcode, $dst$$Register, $mask$$KRegister, + $tmp$$Register, mask_len, mask_size, vlen_enc); %} ins_pipe( pipe_slow ); %} -instruct vmask_first_or_last_true_avx(rRegI dst, vec mask, rRegL tmp, vec xtmp, vec xtmp1, rFlagsReg cr) %{ +instruct vmask_first_or_last_true_bool(rRegI dst, vec mask, rRegL tmp, vec xtmp, rFlagsReg cr) %{ predicate(n->in(1)->bottom_type()->isa_vectmask() == NULL); match(Set dst (VectorMaskFirstTrue mask)); match(Set dst (VectorMaskLastTrue mask)); - effect(TEMP_DEF dst, TEMP tmp, TEMP xtmp, TEMP xtmp1, KILL cr); - format %{ "vector_mask_first_or_last_true_avx $dst, $mask \t! using $tmp, $xtmp and $xtmp1 as TEMP" %} + effect(TEMP_DEF dst, TEMP tmp, TEMP xtmp, KILL cr); + format %{ "vector_mask_first_or_last_true_bool $dst, $mask \t! using $tmp, $xtmp as TEMP" %} + ins_encode %{ + int opcode = this->ideal_Opcode(); + BasicType mbt = Matcher::vector_element_basic_type(this, $mask); + int mask_len = Matcher::vector_length(this, $mask); + int vlen_enc = vector_length_encoding(this, $mask); + __ vector_mask_operation(opcode, $dst$$Register, $mask$$XMMRegister, $xtmp$$XMMRegister, + $tmp$$Register, mask_len, mbt, vlen_enc); + %} + ins_pipe( pipe_slow ); +%} + +instruct vmask_first_or_last_true_avx(rRegI dst, vec mask, immI size, rRegL tmp, vec xtmp, rFlagsReg cr) %{ + predicate(n->in(1)->in(1)->bottom_type()->isa_vectmask() == NULL); + match(Set dst (VectorMaskFirstTrue (VectorStoreMask mask size))); + match(Set dst (VectorMaskLastTrue (VectorStoreMask mask size))); + effect(TEMP_DEF dst, TEMP tmp, TEMP xtmp, KILL cr); + format %{ "vector_mask_first_or_last_true_avx $dst, $mask \t! using $tmp, $xtmp as TEMP" %} ins_encode %{ int opcode = this->ideal_Opcode(); BasicType mbt = Matcher::vector_element_basic_type(this, $mask); int mask_len = Matcher::vector_length(this, $mask); - int mask_size = mask_len * type2aelembytes(mbt); int vlen_enc = vector_length_encoding(this, $mask); __ vector_mask_operation(opcode, $dst$$Register, $mask$$XMMRegister, $xtmp$$XMMRegister, - $xtmp1$$XMMRegister, $tmp$$Register, mask_len, mask_size, vlen_enc); + $tmp$$Register, mask_len, mbt, vlen_enc); %} ins_pipe( pipe_slow ); %} @@ -9446,6 +9541,46 @@ instruct mask_not_imm(kReg dst, kReg src, immI_M1 cnt) %{ %} ins_pipe( pipe_slow ); %} + +instruct long_to_maskLE8_avx(vec dst, rRegL src, rRegL rtmp1, rRegL rtmp2, vec xtmp) %{ + predicate(n->bottom_type()->isa_vectmask() == NULL && Matcher::vector_length(n) <= 8); + match(Set dst (VectorLongToMask src)); + effect(TEMP dst, TEMP rtmp1, TEMP rtmp2, TEMP xtmp); + format %{ "long_to_mask_avx $dst, $src\t! using $rtmp1, $rtmp2, $xtmp as TEMP" %} + ins_encode %{ + int mask_len = Matcher::vector_length(this); + int vec_enc = vector_length_encoding(mask_len); + __ vector_long_to_maskvec($dst$$XMMRegister, $src$$Register, $rtmp1$$Register, + $rtmp2$$Register, xnoreg, mask_len, vec_enc); + %} + ins_pipe( pipe_slow ); +%} + + +instruct long_to_maskGT8_avx(vec dst, rRegL src, rRegL rtmp1, rRegL rtmp2, vec xtmp1, rFlagsReg cr) %{ + predicate(n->bottom_type()->isa_vectmask() == NULL && Matcher::vector_length(n) > 8); + match(Set dst (VectorLongToMask src)); + effect(TEMP dst, TEMP rtmp1, TEMP rtmp2, TEMP xtmp1, KILL cr); + format %{ "long_to_mask_avx $dst, $src\t! using $rtmp1, $rtmp2, $xtmp1, as TEMP" %} + ins_encode %{ + int mask_len = Matcher::vector_length(this); + assert(mask_len <= 32, "invalid mask length"); + int vec_enc = vector_length_encoding(mask_len); + __ vector_long_to_maskvec($dst$$XMMRegister, $src$$Register, $rtmp1$$Register, + $rtmp2$$Register, $xtmp1$$XMMRegister, mask_len, vec_enc); + %} + ins_pipe( pipe_slow ); +%} + +instruct long_to_mask_evex(kReg dst, rRegL src) %{ + predicate(n->bottom_type()->isa_vectmask()); + match(Set dst (VectorLongToMask src)); + format %{ "long_to_mask_evex $dst, $src\t!" %} + ins_encode %{ + __ kmov($dst$$KRegister, $src$$Register); + %} + ins_pipe( pipe_slow ); +%} #endif instruct mask_opers_evex(kReg dst, kReg src1, kReg src2, kReg kscratch) %{ @@ -9465,6 +9600,7 @@ instruct mask_opers_evex(kReg dst, kReg src1, kReg src2, kReg kscratch) %{ ins_pipe( pipe_slow ); %} + instruct castMM(kReg dst) %{ match(Set dst (CastVV dst)); diff --git a/src/hotspot/cpu/x86/x86_32.ad b/src/hotspot/cpu/x86/x86_32.ad index 5f09f565d1814c3cfeec2d483fcc1d836dea43fe..896064720ffb377abb7a0a337430ca170f7d3189 100644 --- a/src/hotspot/cpu/x86/x86_32.ad +++ b/src/hotspot/cpu/x86/x86_32.ad @@ -755,6 +755,7 @@ static enum RC rc_class( OptoReg::Name reg ) { assert(UseSSE < 2, "shouldn't be used in SSE2+ mode"); return rc_float; } + if (r->is_KRegister()) return rc_kreg; assert(r->is_XMMRegister(), "must be"); return rc_xmm; } @@ -1249,26 +1250,6 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, PhaseRegAlloc *ra_, bo return size; } - assert( size > 0, "missed a case" ); - - // -------------------------------------------------------------------- - // Check for second bits still needing moving. - if( src_second == dst_second ) - return size; // Self copy; no move - assert( src_second_rc != rc_bad && dst_second_rc != rc_bad, "src_second & dst_second cannot be Bad" ); - - // Check for second word int-int move - if( src_second_rc == rc_int && dst_second_rc == rc_int ) - return impl_mov_helper(cbuf,do_size,src_second,dst_second,size, st); - - // Check for second word integer store - if( src_second_rc == rc_int && dst_second_rc == rc_stack ) - return impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_second),src_second,0x89,"MOV ",size, st); - - // Check for second word integer load - if( dst_second_rc == rc_int && src_second_rc == rc_stack ) - return impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_second),dst_second,0x8B,"MOV ",size, st); - // AVX-512 opmask specific spilling. if (src_first_rc == rc_stack && dst_first_rc == rc_kreg) { assert((src_first & 1) == 0 && src_first + 1 == src_second, "invalid register pair"); @@ -1306,6 +1287,26 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, PhaseRegAlloc *ra_, bo return 0; } + assert( size > 0, "missed a case" ); + + // -------------------------------------------------------------------- + // Check for second bits still needing moving. + if( src_second == dst_second ) + return size; // Self copy; no move + assert( src_second_rc != rc_bad && dst_second_rc != rc_bad, "src_second & dst_second cannot be Bad" ); + + // Check for second word int-int move + if( src_second_rc == rc_int && dst_second_rc == rc_int ) + return impl_mov_helper(cbuf,do_size,src_second,dst_second,size, st); + + // Check for second word integer store + if( src_second_rc == rc_int && dst_second_rc == rc_stack ) + return impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_second),src_second,0x89,"MOV ",size, st); + + // Check for second word integer load + if( dst_second_rc == rc_int && src_second_rc == rc_stack ) + return impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_second),dst_second,0x8B,"MOV ",size, st); + Unimplemented(); return 0; // Mute compiler } @@ -13129,6 +13130,24 @@ instruct cmovLL_mem_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, eRegL dst, load_lo ins_pipe( pipe_cmov_reg_long ); %} +instruct cmovLL_reg_LTGE_U(cmpOpU cmp, flagsReg_ulong_LTGE flags, eRegL dst, eRegL src) %{ + match(Set dst (CMoveL (Binary cmp flags) (Binary dst src))); + predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge )); + ins_cost(400); + expand %{ + cmovLL_reg_LTGE(cmp, flags, dst, src); + %} +%} + +instruct cmovLL_mem_LTGE_U(cmpOpU cmp, flagsReg_ulong_LTGE flags, eRegL dst, load_long_memory src) %{ + match(Set dst (CMoveL (Binary cmp flags) (Binary dst (LoadL src)))); + predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge )); + ins_cost(500); + expand %{ + cmovLL_mem_LTGE(cmp, flags, dst, src); + %} +%} + // Compare 2 longs and CMOVE ints. instruct cmovII_reg_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, rRegI dst, rRegI src) %{ predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge )); @@ -13179,6 +13198,16 @@ instruct cmovPP_reg_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, eRegP dst, eRegP s ins_pipe( pipe_cmov_reg ); %} +// Compare 2 unsigned longs and CMOVE ptrs. +instruct cmovPP_reg_LTGE_U(cmpOpU cmp, flagsReg_ulong_LTGE flags, eRegP dst, eRegP src) %{ + predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge )); + match(Set dst (CMoveP (Binary cmp flags) (Binary dst src))); + ins_cost(200); + expand %{ + cmovPP_reg_LTGE(cmp,flags,dst,src); + %} +%} + // Compare 2 longs and CMOVE doubles instruct cmovDDPR_reg_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, regDPR dst, regDPR src) %{ predicate( UseSSE<=1 && _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); @@ -13360,6 +13389,16 @@ instruct cmovPP_reg_EQNE(cmpOp cmp, flagsReg_long_EQNE flags, eRegP dst, eRegP s ins_pipe( pipe_cmov_reg ); %} +// Compare 2 unsigned longs and CMOVE ptrs. +instruct cmovPP_reg_EQNE_U(cmpOpU cmp, flagsReg_ulong_EQNE flags, eRegP dst, eRegP src) %{ + predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne )); + match(Set dst (CMoveP (Binary cmp flags) (Binary dst src))); + ins_cost(200); + expand %{ + cmovPP_reg_EQNE(cmp,flags,dst,src); + %} +%} + // Compare 2 longs and CMOVE doubles instruct cmovDDPR_reg_EQNE(cmpOp cmp, flagsReg_long_EQNE flags, regDPR dst, regDPR src) %{ predicate( UseSSE<=1 && _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); @@ -13569,6 +13608,16 @@ instruct cmovPP_reg_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, eRegP dst, ins_pipe( pipe_cmov_reg ); %} +// Compare 2 unsigned longs and CMOVE ptrs. +instruct cmovPP_reg_LEGT_U(cmpOpU_commute cmp, flagsReg_ulong_LEGT flags, eRegP dst, eRegP src) %{ + predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt )); + match(Set dst (CMoveP (Binary cmp flags) (Binary dst src))); + ins_cost(200); + expand %{ + cmovPP_reg_LEGT(cmp,flags,dst,src); + %} +%} + // Compare 2 longs and CMOVE doubles instruct cmovDDPR_reg_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, regDPR dst, regDPR src) %{ predicate( UseSSE<=1 && _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); diff --git a/src/hotspot/cpu/zero/frame_zero.cpp b/src/hotspot/cpu/zero/frame_zero.cpp index 19970cfb82bc20cc2e4b6729e080aaaa2f7d29e3..2e00d703377cc89597762cc9d5bd36c11f4d4edb 100644 --- a/src/hotspot/cpu/zero/frame_zero.cpp +++ b/src/hotspot/cpu/zero/frame_zero.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. - * Copyright 2007, 2008, 2009, 2010, 2011 Red Hat, Inc. + * Copyright (c) 2007, 2021, Red Hat, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -116,13 +116,67 @@ void frame::patch_pc(Thread* thread, address pc) { } bool frame::safe_for_sender(JavaThread *thread) { - ShouldNotCallThis(); - return false; + address sp = (address)_sp; + + // consider stack guards when trying to determine "safe" stack pointers + // sp must be within the usable part of the stack (not in guards) + if (!thread->is_in_usable_stack(sp)) { + return false; + } + + // an fp must be within the stack and above (but not equal) sp + if (!thread->is_in_stack_range_excl((address)fp(), sp)) { + return false; + } + + // All good. + return true; } bool frame::is_interpreted_frame_valid(JavaThread *thread) const { - ShouldNotCallThis(); - return false; + assert(is_interpreted_frame(), "Not an interpreted frame"); + // These are reasonable sanity checks + if (fp() == 0 || (intptr_t(fp()) & (wordSize-1)) != 0) { + return false; + } + if (sp() == 0 || (intptr_t(sp()) & (wordSize-1)) != 0) { + return false; + } + // These are hacks to keep us out of trouble. + // The problem with these is that they mask other problems + if (fp() <= sp()) { // this attempts to deal with unsigned comparison above + return false; + } + + // do some validation of frame elements + // first the method + + Method* m = *interpreter_frame_method_addr(); + + // validate the method we'd find in this potential sender + if (!Method::is_valid_method(m)) { + return false; + } + + // validate bci/bcp + address bcp = interpreter_frame_bcp(); + if (m->validate_bci_from_bcp(bcp) < 0) { + return false; + } + + // validate ConstantPoolCache* + ConstantPoolCache* cp = *interpreter_frame_cache_addr(); + if (MetaspaceObj::is_valid(cp) == false) { + return false; + } + + // validate locals + address locals = (address) *interpreter_frame_locals_addr(); + if (!thread->is_in_stack_range_incl(locals, (address)fp())) { + return false; + } + + return true; } BasicType frame::interpreter_frame_result(oop* oop_result, diff --git a/src/hotspot/cpu/zero/vm_version_ext_zero.cpp b/src/hotspot/cpu/zero/vm_version_ext_zero.cpp deleted file mode 100644 index 9e4f45fd679e49d89520be4da442eece8e254e4a..0000000000000000000000000000000000000000 --- a/src/hotspot/cpu/zero/vm_version_ext_zero.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "memory/allocation.hpp" -#include "memory/allocation.inline.hpp" -#include "runtime/os.hpp" -#include "vm_version_ext_zero.hpp" - -// VM_Version_Ext statics -int VM_Version_Ext::_no_of_threads = 0; -int VM_Version_Ext::_no_of_cores = 0; -int VM_Version_Ext::_no_of_sockets = 0; -bool VM_Version_Ext::_initialized = false; -char VM_Version_Ext::_cpu_name[CPU_TYPE_DESC_BUF_SIZE] = {0}; -char VM_Version_Ext::_cpu_desc[CPU_DETAILED_DESC_BUF_SIZE] = {0}; - -void VM_Version_Ext::initialize_cpu_information(void) { - // do nothing if cpu info has been initialized - if (_initialized) { - return; - } - - int core_id = -1; - int chip_id = -1; - int len = 0; - char* src_string = NULL; - - _no_of_cores = os::processor_count(); - _no_of_threads = _no_of_cores; - _no_of_sockets = _no_of_cores; - snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE - 1, "Zero VM"); - snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "%s", _features_string); - _initialized = true; -} - -int VM_Version_Ext::number_of_threads(void) { - initialize_cpu_information(); - return _no_of_threads; -} - -int VM_Version_Ext::number_of_cores(void) { - initialize_cpu_information(); - return _no_of_cores; -} - -int VM_Version_Ext::number_of_sockets(void) { - initialize_cpu_information(); - return _no_of_sockets; -} - -const char* VM_Version_Ext::cpu_name(void) { - initialize_cpu_information(); - char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, CPU_TYPE_DESC_BUF_SIZE, mtTracing); - if (NULL == tmp) { - return NULL; - } - strncpy(tmp, _cpu_name, CPU_TYPE_DESC_BUF_SIZE); - return tmp; -} - -const char* VM_Version_Ext::cpu_description(void) { - initialize_cpu_information(); - char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, CPU_DETAILED_DESC_BUF_SIZE, mtTracing); - if (NULL == tmp) { - return NULL; - } - strncpy(tmp, _cpu_desc, CPU_DETAILED_DESC_BUF_SIZE); - return tmp; -} diff --git a/src/hotspot/cpu/zero/vm_version_ext_zero.hpp b/src/hotspot/cpu/zero/vm_version_ext_zero.hpp deleted file mode 100644 index 2c6580d5f1f20cd60598ec2af7871b869410b3be..0000000000000000000000000000000000000000 --- a/src/hotspot/cpu/zero/vm_version_ext_zero.hpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef CPU_ZERO_VM_VERSION_EXT_ZERO_HPP -#define CPU_ZERO_VM_VERSION_EXT_ZERO_HPP - -#include "runtime/vm_version.hpp" -#include "utilities/macros.hpp" - -class VM_Version_Ext : public VM_Version { - private: - static const size_t CPU_TYPE_DESC_BUF_SIZE = 256; - static const size_t CPU_DETAILED_DESC_BUF_SIZE = 4096; - - static int _no_of_threads; - static int _no_of_cores; - static int _no_of_sockets; - static bool _initialized; - static char _cpu_name[CPU_TYPE_DESC_BUF_SIZE]; - static char _cpu_desc[CPU_DETAILED_DESC_BUF_SIZE]; - - public: - static int number_of_threads(void); - static int number_of_cores(void); - static int number_of_sockets(void); - - static const char* cpu_name(void); - static const char* cpu_description(void); - static void initialize_cpu_information(void); - -}; - -#endif // CPU_ZERO_VM_VERSION_EXT_ZERO_HPP diff --git a/src/hotspot/cpu/zero/vm_version_zero.cpp b/src/hotspot/cpu/zero/vm_version_zero.cpp index 6fa56c24cce14c265ab5324e97f3f00c1536d781..5c2a0a3d5d2304b798d992ab5ae03138c4d899a9 100644 --- a/src/hotspot/cpu/zero/vm_version_zero.cpp +++ b/src/hotspot/cpu/zero/vm_version_zero.cpp @@ -121,3 +121,17 @@ void VM_Version::initialize() { UNSUPPORTED_OPTION(CountCompiledCalls); #endif } + +void VM_Version::initialize_cpu_information(void) { + // do nothing if cpu info has been initialized + if (_initialized) { + return; + } + + _no_of_cores = os::processor_count(); + _no_of_threads = _no_of_cores; + _no_of_sockets = _no_of_cores; + snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE - 1, "Zero VM"); + snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "%s", _features_string); + _initialized = true; +} diff --git a/src/hotspot/cpu/zero/vm_version_zero.hpp b/src/hotspot/cpu/zero/vm_version_zero.hpp index c63a47719e50d592d7db088fa0f9c04a77e901d4..1cfe57b11c2463b45ad9507affadd6a203b9a4f6 100644 --- a/src/hotspot/cpu/zero/vm_version_zero.hpp +++ b/src/hotspot/cpu/zero/vm_version_zero.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright 2007 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -34,6 +34,8 @@ class VM_Version : public Abstract_VM_Version { static void initialize(); constexpr static bool supports_stack_watermark_barrier() { return true; } + + static void initialize_cpu_information(void); }; #endif // CPU_ZERO_VM_VERSION_ZERO_HPP diff --git a/src/hotspot/os/aix/osThread_aix.hpp b/src/hotspot/os/aix/osThread_aix.hpp index 0c8706d4add55aa6c4c5dfda0e30141bf675cb24..79e60b82e4cf6df2d3be7080426414cca3944714 100644 --- a/src/hotspot/os/aix/osThread_aix.hpp +++ b/src/hotspot/os/aix/osThread_aix.hpp @@ -63,13 +63,6 @@ // Used for debugging, return a unique integer for each thread. int thread_identifier() const { return _thread_id; } #endif -#ifdef ASSERT - // We expect no reposition failures so kill vm if we get one. - // - bool valid_reposition_failure() { - return false; - } -#endif // ASSERT tid_t kernel_thread_id() const { return _kernel_thread_id; } diff --git a/src/hotspot/os/aix/os_aix.cpp b/src/hotspot/os/aix/os_aix.cpp index df8563067e43e7d103d52a64e581b23e9e8bbec0..419e2ce92fd0be424f557c82832dd146edd1b91c 100644 --- a/src/hotspot/os/aix/os_aix.cpp +++ b/src/hotspot/os/aix/os_aix.cpp @@ -741,7 +741,7 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, assert(thread->osthread() == NULL, "caller responsible"); // Allocate the OSThread object. - OSThread* osthread = new OSThread(NULL, NULL); + OSThread* osthread = new OSThread(); if (osthread == NULL) { return false; } @@ -855,7 +855,7 @@ bool os::create_attached_thread(JavaThread* thread) { #endif // Allocate the OSThread object - OSThread* osthread = new OSThread(NULL, NULL); + OSThread* osthread = new OSThread(); if (osthread == NULL) { return false; diff --git a/src/hotspot/os/aix/os_perf_aix.cpp b/src/hotspot/os/aix/os_perf_aix.cpp index 15eca737fdf9ae8044cd7619f30c73c52bb41f43..ccdf013766e3acb9e390ff3ba86face0c72554b8 100644 --- a/src/hotspot/os/aix/os_perf_aix.cpp +++ b/src/hotspot/os/aix/os_perf_aix.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,10 +28,9 @@ #include "os_aix.inline.hpp" #include "runtime/os.hpp" #include "runtime/os_perf.hpp" +#include "runtime/vm_version.hpp" #include "utilities/globalDefinitions.hpp" -#include CPU_HEADER(vm_version_ext) - #include #include #include @@ -863,11 +862,12 @@ CPUInformationInterface::CPUInformationInterface() { bool CPUInformationInterface::initialize() { _cpu_info = new CPUInformation(); - _cpu_info->set_number_of_hardware_threads(VM_Version_Ext::number_of_threads()); - _cpu_info->set_number_of_cores(VM_Version_Ext::number_of_cores()); - _cpu_info->set_number_of_sockets(VM_Version_Ext::number_of_sockets()); - _cpu_info->set_cpu_name(VM_Version_Ext::cpu_name()); - _cpu_info->set_cpu_description(VM_Version_Ext::cpu_description()); + VM_Version::initialize_cpu_information(); + _cpu_info->set_number_of_hardware_threads(VM_Version::number_of_threads()); + _cpu_info->set_number_of_cores(VM_Version::number_of_cores()); + _cpu_info->set_number_of_sockets(VM_Version::number_of_sockets()); + _cpu_info->set_cpu_name(VM_Version::cpu_name()); + _cpu_info->set_cpu_description(VM_Version::cpu_description()); return true; } diff --git a/src/hotspot/os/bsd/osThread_bsd.hpp b/src/hotspot/os/bsd/osThread_bsd.hpp index 8e7375d714566628a9c813d5c941d20a97a51790..731e046e529917743ff2f8f45d6e3e0b772b825c 100644 --- a/src/hotspot/os/bsd/osThread_bsd.hpp +++ b/src/hotspot/os/bsd/osThread_bsd.hpp @@ -67,14 +67,6 @@ intptr_t thread_identifier() const { return (intptr_t)_pthread_id; } #endif -#ifdef ASSERT - // We expect no reposition failures so kill vm if we get one. - // - bool valid_reposition_failure() { - return false; - } -#endif // ASSERT - pthread_t pthread_id() const { return _pthread_id; } diff --git a/src/hotspot/os/bsd/os_bsd.cpp b/src/hotspot/os/bsd/os_bsd.cpp index ef7e6e3e3a1c24076b90200b1475424feba95915..89e6aed8ec828c49f319389b26bca239ada199c8 100644 --- a/src/hotspot/os/bsd/os_bsd.cpp +++ b/src/hotspot/os/bsd/os_bsd.cpp @@ -589,7 +589,7 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, assert(thread->osthread() == NULL, "caller responsible"); // Allocate the OSThread object - OSThread* osthread = new OSThread(NULL, NULL); + OSThread* osthread = new OSThread(); if (osthread == NULL) { return false; } @@ -682,7 +682,7 @@ bool os::create_attached_thread(JavaThread* thread) { #endif // Allocate the OSThread object - OSThread* osthread = new OSThread(NULL, NULL); + OSThread* osthread = new OSThread(); if (osthread == NULL) { return false; diff --git a/src/hotspot/os/bsd/os_perf_bsd.cpp b/src/hotspot/os/bsd/os_perf_bsd.cpp index e69bfc79558c3fb5cebf3a8451b98f1fd0ecad80..9b80e74954284ab602e538e9d6cfb1a812ab85f7 100644 --- a/src/hotspot/os/bsd/os_perf_bsd.cpp +++ b/src/hotspot/os/bsd/os_perf_bsd.cpp @@ -26,8 +26,8 @@ #include "memory/resourceArea.hpp" #include "runtime/os.hpp" #include "runtime/os_perf.hpp" +#include "runtime/vm_version.hpp" #include "utilities/globalDefinitions.hpp" -#include CPU_HEADER(vm_version_ext) #ifdef __APPLE__ #import @@ -371,11 +371,12 @@ CPUInformationInterface::CPUInformationInterface() { bool CPUInformationInterface::initialize() { _cpu_info = new CPUInformation(); - _cpu_info->set_number_of_hardware_threads(VM_Version_Ext::number_of_threads()); - _cpu_info->set_number_of_cores(VM_Version_Ext::number_of_cores()); - _cpu_info->set_number_of_sockets(VM_Version_Ext::number_of_sockets()); - _cpu_info->set_cpu_name(VM_Version_Ext::cpu_name()); - _cpu_info->set_cpu_description(VM_Version_Ext::cpu_description()); + VM_Version::initialize_cpu_information(); + _cpu_info->set_number_of_hardware_threads(VM_Version::number_of_threads()); + _cpu_info->set_number_of_cores(VM_Version::number_of_cores()); + _cpu_info->set_number_of_sockets(VM_Version::number_of_sockets()); + _cpu_info->set_cpu_name(VM_Version::cpu_name()); + _cpu_info->set_cpu_description(VM_Version::cpu_description()); return true; } diff --git a/src/hotspot/os/linux/osThread_linux.hpp b/src/hotspot/os/linux/osThread_linux.hpp index 01c93f6eb9a8df29443b35ea8e41c36129fe23e4..7dbe92b415eae840f2cc7b1139a46b25e565ff74 100644 --- a/src/hotspot/os/linux/osThread_linux.hpp +++ b/src/hotspot/os/linux/osThread_linux.hpp @@ -55,13 +55,7 @@ // Used for debugging, return a unique integer for each thread. int thread_identifier() const { return _thread_id; } #endif -#ifdef ASSERT - // We expect no reposition failures so kill vm if we get one. - // - bool valid_reposition_failure() { - return false; - } -#endif // ASSERT + pthread_t pthread_id() const { return _pthread_id; } diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index e75e2e51b0e467b99b16e4904e551185b933a22b..cd0fd06f4e14ba9b8bf955d73d27b4a04096f5bf 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -786,7 +786,7 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, assert(thread->osthread() == NULL, "caller responsible"); // Allocate the OSThread object - OSThread* osthread = new OSThread(NULL, NULL); + OSThread* osthread = new OSThread(); if (osthread == NULL) { return false; } @@ -915,7 +915,7 @@ bool os::create_attached_thread(JavaThread* thread) { #endif // Allocate the OSThread object - OSThread* osthread = new OSThread(NULL, NULL); + OSThread* osthread = new OSThread(); if (osthread == NULL) { return false; diff --git a/src/hotspot/os/linux/os_perf_linux.cpp b/src/hotspot/os/linux/os_perf_linux.cpp index 7c42379a0a710de20b2f2f53c82d2fab45434d85..4f8e411d47b1f80583b80342498ab1012518db4d 100644 --- a/src/hotspot/os/linux/os_perf_linux.cpp +++ b/src/hotspot/os/linux/os_perf_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,10 +28,9 @@ #include "os_linux.inline.hpp" #include "runtime/os.hpp" #include "runtime/os_perf.hpp" +#include "runtime/vm_version.hpp" #include "utilities/globalDefinitions.hpp" -#include CPU_HEADER(vm_version_ext) - #include #include #include @@ -927,11 +926,12 @@ CPUInformationInterface::CPUInformationInterface() { bool CPUInformationInterface::initialize() { _cpu_info = new CPUInformation(); - _cpu_info->set_number_of_hardware_threads(VM_Version_Ext::number_of_threads()); - _cpu_info->set_number_of_cores(VM_Version_Ext::number_of_cores()); - _cpu_info->set_number_of_sockets(VM_Version_Ext::number_of_sockets()); - _cpu_info->set_cpu_name(VM_Version_Ext::cpu_name()); - _cpu_info->set_cpu_description(VM_Version_Ext::cpu_description()); + VM_Version::initialize_cpu_information(); + _cpu_info->set_number_of_hardware_threads(VM_Version::number_of_threads()); + _cpu_info->set_number_of_cores(VM_Version::number_of_cores()); + _cpu_info->set_number_of_sockets(VM_Version::number_of_sockets()); + _cpu_info->set_cpu_name(VM_Version::cpu_name()); + _cpu_info->set_cpu_description(VM_Version::cpu_description()); return true; } diff --git a/src/hotspot/os/posix/perfMemory_posix.cpp b/src/hotspot/os/posix/perfMemory_posix.cpp index a89947f32edc1da75a7d9622b8163ae7b5151757..5d0448246bf1929943f47d6c8ec37614c65ee8fc 100644 --- a/src/hotspot/os/posix/perfMemory_posix.cpp +++ b/src/hotspot/os/posix/perfMemory_posix.cpp @@ -1028,7 +1028,7 @@ static char* mmap_create_shared(size_t size) { // static void unmap_shared(char* addr, size_t bytes) { int res; - if (MemTracker::tracking_level() > NMT_minimal) { + if (MemTracker::enabled()) { // Note: Tracker contains a ThreadCritical. Tracker tkr(Tracker::release); res = ::munmap(addr, bytes); diff --git a/src/hotspot/os/windows/osThread_windows.hpp b/src/hotspot/os/windows/osThread_windows.hpp index 74b50100663396c3a9b3b981914241617a48ef0b..5bd07646b1718b51e3f201c7ad938493d4cf33e8 100644 --- a/src/hotspot/os/windows/osThread_windows.hpp +++ b/src/hotspot/os/windows/osThread_windows.hpp @@ -49,13 +49,6 @@ // Used for debugging, return a unique integer for each thread. int thread_identifier() const { return _thread_id; } #endif -#ifdef ASSERT - // We expect no reposition failures so kill vm if we get one - // - bool valid_reposition_failure() { - return false; - } -#endif // ASSERT private: void pd_initialize(); diff --git a/src/hotspot/os/windows/os_perf_windows.cpp b/src/hotspot/os/windows/os_perf_windows.cpp index 3ce1137f37d780dab850841bef7de849bcd6acca..fc2a5631b706ec96ae25b2c729d13c01d5be9a09 100644 --- a/src/hotspot/os/windows/os_perf_windows.cpp +++ b/src/hotspot/os/windows/os_perf_windows.cpp @@ -32,9 +32,9 @@ #include "runtime/os_perf.hpp" #include "runtime/os.hpp" #include "runtime/semaphore.inline.hpp" +#include "runtime/vm_version.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" -#include CPU_HEADER(vm_version_ext) #include #include #include @@ -1434,11 +1434,12 @@ CPUInformationInterface::CPUInformationInterface() : _cpu_info(NULL) {} bool CPUInformationInterface::initialize() { _cpu_info = new CPUInformation(); - _cpu_info->set_number_of_hardware_threads(VM_Version_Ext::number_of_threads()); - _cpu_info->set_number_of_cores(VM_Version_Ext::number_of_cores()); - _cpu_info->set_number_of_sockets(VM_Version_Ext::number_of_sockets()); - _cpu_info->set_cpu_name(VM_Version_Ext::cpu_name()); - _cpu_info->set_cpu_description(VM_Version_Ext::cpu_description()); + VM_Version::initialize_cpu_information(); + _cpu_info->set_number_of_hardware_threads(VM_Version::number_of_threads()); + _cpu_info->set_number_of_cores(VM_Version::number_of_cores()); + _cpu_info->set_number_of_sockets(VM_Version::number_of_sockets()); + _cpu_info->set_cpu_name(VM_Version::cpu_name()); + _cpu_info->set_cpu_description(VM_Version::cpu_description()); return true; } diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 6f8c88d764da645dda82dcec3df6867efbcf4fcd..e129b447cfd3794aa306c10a48fe56f4e849ea08 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -568,7 +568,7 @@ static unsigned __stdcall thread_native_entry(Thread* thread) { static OSThread* create_os_thread(Thread* thread, HANDLE thread_handle, int thread_id) { // Allocate the OSThread object - OSThread* osthread = new OSThread(NULL, NULL); + OSThread* osthread = new OSThread(); if (osthread == NULL) return NULL; // Initialize the JDK library's interrupt event. @@ -671,11 +671,14 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, unsigned thread_id; // Allocate the OSThread object - OSThread* osthread = new OSThread(NULL, NULL); + OSThread* osthread = new OSThread(); if (osthread == NULL) { return false; } + // Initial state is ALLOCATED but not INITIALIZED + osthread->set_state(ALLOCATED); + // Initialize the JDK library's interrupt event. // This should really be done when OSThread is constructed, // but there is no way for a constructor to report failure to @@ -777,7 +780,7 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, osthread->set_thread_handle(thread_handle); osthread->set_thread_id(thread_id); - // Initial thread state is INITIALIZED, not SUSPENDED + // Thread state now is INITIALIZED, not SUSPENDED osthread->set_state(INITIALIZED); // The thread is returned suspended (in state INITIALIZED), and is started higher up in the call chain diff --git a/src/hotspot/os/windows/perfMemory_windows.cpp b/src/hotspot/os/windows/perfMemory_windows.cpp index 600eb8882f9e4a51be91aa440713f0ff3dd29f36..0a53a94957c3d6d98db7dbe76637ed526be759ff 100644 --- a/src/hotspot/os/windows/perfMemory_windows.cpp +++ b/src/hotspot/os/windows/perfMemory_windows.cpp @@ -1834,7 +1834,7 @@ void PerfMemory::detach(char* addr, size_t bytes) { return; } - if (MemTracker::tracking_level() > NMT_minimal) { + if (MemTracker::enabled()) { // it does not go through os api, the operation has to record from here Tracker tkr(Tracker::release); remove_file_mapping(addr); diff --git a/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp b/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp index b3c60b6e6248241b6321b3090ce4fe03622842d0..6b09069e09dd71a03002722f5a285d2f62ae1dbd 100644 --- a/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp +++ b/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp @@ -382,7 +382,20 @@ int os::extra_bang_size_in_bytes() { extern "C" { int SpinPause() { - return 0; + using spin_wait_func_ptr_t = void (*)(); + spin_wait_func_ptr_t func = CAST_TO_FN_PTR(spin_wait_func_ptr_t, StubRoutines::aarch64::spin_wait()); + assert(func != nullptr, "StubRoutines::aarch64::spin_wait must not be null."); + (*func)(); + // If StubRoutines::aarch64::spin_wait consists of only a RET, + // SpinPause can be considered as implemented. There will be a sequence + // of instructions for: + // - call of SpinPause + // - load of StubRoutines::aarch64::spin_wait stub pointer + // - indirect call of the stub + // - return from the stub + // - return from SpinPause + // So '1' always is returned. + return 1; } void _Copy_conjoint_jshorts_atomic(const jshort* from, jshort* to, size_t count) { diff --git a/src/hotspot/os_cpu/linux_zero/thread_linux_zero.cpp b/src/hotspot/os_cpu/linux_zero/thread_linux_zero.cpp index 816ca411430cc609615825747f055c2ac0b82935..e4313782613ddab3ed94a56b66553f5089051fa0 100644 --- a/src/hotspot/os_cpu/linux_zero/thread_linux_zero.cpp +++ b/src/hotspot/os_cpu/linux_zero/thread_linux_zero.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. - * Copyright 2009, 2010 Red Hat, Inc. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2021, Red Hat, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,3 +35,40 @@ frame JavaThread::pd_last_frame() { void JavaThread::cache_global_variables() { // nothing to do } + +bool JavaThread::pd_get_top_frame_for_signal_handler(frame* fr_addr, + void* ucontext, + bool isInJava) { + if (has_last_Java_frame()) { + *fr_addr = pd_last_frame(); + return true; + } + + if (isInJava) { + // We know we are in Java, but there is no frame? + // Try to find the top-most Java frame on Zero stack then. + intptr_t* sp = zero_stack()->sp(); + ZeroFrame* zf = top_zero_frame(); + while (zf != NULL) { + if (zf->is_interpreter_frame()) { + interpreterState istate = zf->as_interpreter_frame()->interpreter_state(); + if (istate->self_link() == istate) { + // Valid interpreter state found, this is our frame. + *fr_addr = frame(zf, sp); + return true; + } + } + sp = ((intptr_t *) zf) + 1; + zf = zf->next(); + } + } + + // No dice. + return false; +} + +bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr, + void* ucontext, + bool isInJava) { + return pd_get_top_frame_for_signal_handler(fr_addr, ucontext, isInJava); +} diff --git a/src/hotspot/os_cpu/linux_zero/thread_linux_zero.hpp b/src/hotspot/os_cpu/linux_zero/thread_linux_zero.hpp index b180611b2f9e2fcf7fdae9d721a2debe566af203..b915c40c04987a5c303a9ef5eeceeab8dd6542d6 100644 --- a/src/hotspot/os_cpu/linux_zero/thread_linux_zero.hpp +++ b/src/hotspot/os_cpu/linux_zero/thread_linux_zero.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. - * Copyright 2007, 2008, 2009, 2010 Red Hat, Inc. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2021, Red Hat, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -96,16 +96,10 @@ public: bool pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext, - bool isInJava) { - ShouldNotCallThis(); - return false; // silence compile warning - } + bool isInJava); bool pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, - bool isInJava) { - ShouldNotCallThis(); - return false; // silence compile warning - } + bool isInJava); #endif // OS_CPU_LINUX_ZERO_THREAD_LINUX_ZERO_HPP diff --git a/src/hotspot/share/adlc/formssel.cpp b/src/hotspot/share/adlc/formssel.cpp index 651511f375185feff85a4d5b0aee0bb25e2b12ef..ee528d97b5f36f24f52e3033c6b34ef5aaef0fb8 100644 --- a/src/hotspot/share/adlc/formssel.cpp +++ b/src/hotspot/share/adlc/formssel.cpp @@ -4234,8 +4234,8 @@ bool MatchRule::is_vector() const { "VectorRearrange","VectorLoadShuffle", "VectorLoadConst", "VectorCastB2X", "VectorCastS2X", "VectorCastI2X", "VectorCastL2X", "VectorCastF2X", "VectorCastD2X", - "VectorMaskWrapper", "VectorMaskCmp", "VectorReinterpret","LoadVectorMasked","StoreVectorMasked", - "FmaVD", "FmaVF","PopCountVI", + "VectorMaskWrapper","VectorMaskCmp","VectorReinterpret","LoadVectorMasked","StoreVectorMasked", + "FmaVD","FmaVF","PopCountVI","VectorLongToMask", // Next are vector mask ops. "MaskAll", "AndVMask", "OrVMask", "XorVMask", "VectorMaskCast", // Next are not supported currently. diff --git a/src/hotspot/share/c1/c1_CFGPrinter.cpp b/src/hotspot/share/c1/c1_CFGPrinter.cpp index 9cd617d542812194c1e46cee42f20dc153020557..73a1d2d649e8686330a3a4f7bab3b3d48c867f14 100644 --- a/src/hotspot/share/c1/c1_CFGPrinter.cpp +++ b/src/hotspot/share/c1/c1_CFGPrinter.cpp @@ -231,9 +231,7 @@ void CFGPrinterOutput::print_LIR(BlockBegin* block) { void CFGPrinterOutput::print_block(BlockBegin* block) { print_begin("block"); - print("name \"B%d\"", block->block_id()); - print("from_bci %d", block->bci()); print("to_bci %d", (block->end() == NULL ? -1 : block->end()->printable_bci())); @@ -246,9 +244,13 @@ void CFGPrinterOutput::print_block(BlockBegin* block) { output()->cr(); output()->indent(); - output()->print("successors "); - for (i = 0; i < block->number_of_sux(); i++) { - output()->print("\"B%d\" ", block->sux_at(i)->block_id()); + if (block->end() != NULL) { + output()->print("successors "); + for (i = 0; i < block->number_of_sux(); i++) { + output()->print("\"B%d\" ", block->sux_at(i)->block_id()); + } + } else { + output()->print("(block has no end, cannot print successors)"); } output()->cr(); diff --git a/src/hotspot/share/c1/c1_FrameMap.hpp b/src/hotspot/share/c1/c1_FrameMap.hpp index 5cbb37422dcbbee4b7c5f95f31b21af259853ad9..480a1082f686e7c9ca66e15eb536dff07b646fab 100644 --- a/src/hotspot/share/c1/c1_FrameMap.hpp +++ b/src/hotspot/share/c1/c1_FrameMap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,7 +43,7 @@ class CallingConvention; //-------------------------------------------------------- // This class is responsible of mapping items (locals, monitors, spill -// slots and registers to their frame location +// slots and registers) to their frame location // // The monitors are specified by a consecutive index, although each monitor entry // occupies two words. The monitor_index is 0.._num_monitors diff --git a/src/hotspot/share/c1/c1_GraphBuilder.cpp b/src/hotspot/share/c1/c1_GraphBuilder.cpp index 9afabb75060bd17cc3e7970c731f464fffc65e62..032c6ffb3e3e63a7af8f38069cb90eaa1a70fd4e 100644 --- a/src/hotspot/share/c1/c1_GraphBuilder.cpp +++ b/src/hotspot/share/c1/c1_GraphBuilder.cpp @@ -53,6 +53,7 @@ class BlockListBuilder { BlockList _blocks; // internal list of all blocks BlockList* _bci2block; // mapping from bci to blocks for GraphBuilder + GrowableArray _bci2block_successors; // Mapping bcis to their blocks successors while we dont have a blockend // fields used by mark_loops ResourceBitMap _active; // for iteration of control flow graph @@ -89,6 +90,11 @@ class BlockListBuilder { void print(); #endif + int number_of_successors(BlockBegin* block); + BlockBegin* successor_at(BlockBegin* block, int i); + void add_successor(BlockBegin* block, BlockBegin* sux); + bool is_successor(BlockBegin* block, BlockBegin* sux); + public: // creation BlockListBuilder(Compilation* compilation, IRScope* scope, int osr_bci); @@ -105,6 +111,7 @@ BlockListBuilder::BlockListBuilder(Compilation* compilation, IRScope* scope, int , _scope(scope) , _blocks(16) , _bci2block(new BlockList(scope->method()->code_size(), NULL)) + , _bci2block_successors(scope->method()->code_size()) , _active() // size not known yet , _visited() // size not known yet , _loop_map() // size not known yet @@ -118,6 +125,8 @@ BlockListBuilder::BlockListBuilder(Compilation* compilation, IRScope* scope, int mark_loops(); NOT_PRODUCT(if (PrintInitialBlockList) print()); + // _bci2block still contains blocks with _end == null and > 0 sux in _bci2block_successors. + #ifndef PRODUCT if (PrintCFGToFile) { stringStream title; @@ -160,6 +169,7 @@ BlockBegin* BlockListBuilder::make_block_at(int cur_bci, BlockBegin* predecessor block = new BlockBegin(cur_bci); block->init_stores_to_locals(method()->max_locals()); _bci2block->at_put(cur_bci, block); + _bci2block_successors.at_put_grow(cur_bci, BlockList()); _blocks.append(block); assert(predecessor == NULL || predecessor->bci() < cur_bci, "targets for backward branches must already exist"); @@ -170,7 +180,7 @@ BlockBegin* BlockListBuilder::make_block_at(int cur_bci, BlockBegin* predecessor BAILOUT_("Exception handler can be reached by both normal and exceptional control flow", block); } - predecessor->add_successor(block); + add_successor(predecessor, block); block->increment_total_preds(); } @@ -201,8 +211,8 @@ void BlockListBuilder::handle_exceptions(BlockBegin* current, int cur_bci) { assert(entry->is_set(BlockBegin::exception_entry_flag), "flag must be set"); // add each exception handler only once - if (!current->is_successor(entry)) { - current->add_successor(entry); + if(!is_successor(current, entry)) { + add_successor(current, entry); entry->increment_total_preds(); } @@ -418,9 +428,9 @@ int BlockListBuilder::mark_loops(BlockBegin* block, bool in_subroutine) { _active.set_bit(block_id); intptr_t loop_state = 0; - for (int i = block->number_of_sux() - 1; i >= 0; i--) { + for (int i = number_of_successors(block) - 1; i >= 0; i--) { // recursively process all successors - loop_state |= mark_loops(block->sux_at(i), in_subroutine); + loop_state |= mark_loops(successor_at(block, i), in_subroutine); } // clear active-bit after all successors are processed @@ -452,6 +462,28 @@ int BlockListBuilder::mark_loops(BlockBegin* block, bool in_subroutine) { return loop_state; } +inline int BlockListBuilder::number_of_successors(BlockBegin* block) +{ + assert(_bci2block_successors.length() > block->bci(), "sux must exist"); + return _bci2block_successors.at(block->bci()).length(); +} + +inline BlockBegin* BlockListBuilder::successor_at(BlockBegin* block, int i) +{ + assert(_bci2block_successors.length() > block->bci(), "sux must exist"); + return _bci2block_successors.at(block->bci()).at(i); +} + +inline void BlockListBuilder::add_successor(BlockBegin* block, BlockBegin* sux) +{ + assert(_bci2block_successors.length() > block->bci(), "sux must exist"); + _bci2block_successors.at(block->bci()).append(sux); +} + +inline bool BlockListBuilder::is_successor(BlockBegin* block, BlockBegin* sux) { + assert(_bci2block_successors.length() > block->bci(), "sux must exist"); + return _bci2block_successors.at(block->bci()).contains(sux); +} #ifndef PRODUCT @@ -477,10 +509,10 @@ void BlockListBuilder::print() { tty->print(cur->is_set(BlockBegin::subroutine_entry_flag) ? " sr" : " "); tty->print(cur->is_set(BlockBegin::parser_loop_header_flag) ? " lh" : " "); - if (cur->number_of_sux() > 0) { + if (number_of_successors(cur) > 0) { tty->print(" sux: "); - for (int j = 0; j < cur->number_of_sux(); j++) { - BlockBegin* sux = cur->sux_at(j); + for (int j = 0; j < number_of_successors(cur); j++) { + BlockBegin* sux = successor_at(cur, j); tty->print("B%d ", sux->block_id()); } } @@ -1865,22 +1897,17 @@ void GraphBuilder::invoke(Bytecodes::Code code) { log->identify(target), Bytecodes::name(code)); - // invoke-special-super - if (bc_raw == Bytecodes::_invokespecial && !target->is_object_initializer()) { - ciInstanceKlass* sender_klass = calling_klass; - if (sender_klass->is_interface()) { - int index = state()->stack_size() - (target->arg_size_no_receiver() + 1); - Value receiver = state()->stack_at(index); - CheckCast* c = new CheckCast(sender_klass, receiver, copy_state_before()); - c->set_invokespecial_receiver_check(); - state()->stack_at_put(index, append_split(c)); - } - } - // Some methods are obviously bindable without any type checks so // convert them directly to an invokespecial or invokestatic. if (target->is_loaded() && !target->is_abstract() && target->can_be_statically_bound()) { switch (bc_raw) { + case Bytecodes::_invokeinterface: + // convert to invokespecial if the target is the private interface method. + if (target->is_private()) { + assert(holder->is_interface(), "How did we get a non-interface method here!"); + code = Bytecodes::_invokespecial; + } + break; case Bytecodes::_invokevirtual: code = Bytecodes::_invokespecial; break; @@ -1897,6 +1924,26 @@ void GraphBuilder::invoke(Bytecodes::Code code) { } } + if (code == Bytecodes::_invokespecial) { + // Additional receiver subtype checks for interface calls via invokespecial or invokeinterface. + ciKlass* receiver_constraint = nullptr; + + if (bc_raw == Bytecodes::_invokeinterface) { + receiver_constraint = holder; + } else if (bc_raw == Bytecodes::_invokespecial && !target->is_object_initializer() && calling_klass->is_interface()) { + receiver_constraint = calling_klass; + } + + if (receiver_constraint != nullptr) { + int index = state()->stack_size() - (target->arg_size_no_receiver() + 1); + Value receiver = state()->stack_at(index); + CheckCast* c = new CheckCast(receiver_constraint, receiver, copy_state_before()); + // go to uncommon_trap when checkcast fails + c->set_invokespecial_receiver_check(); + state()->stack_at_put(index, append_split(c)); + } + } + // Push appendix argument (MethodType, CallSite, etc.), if one. bool patch_for_appendix = false; int patching_appendix_arg = 0; @@ -3044,7 +3091,7 @@ BlockBegin* GraphBuilder::setup_start_block(int osr_bci, BlockBegin* std_entry, // each method. Previously, each method started with the // start-block created below, and this block was followed by the // header block that was always empty. This header block is only - // necesary if std_entry is also a backward branch target because + // necessary if std_entry is also a backward branch target because // then phi functions may be necessary in the header block. It's // also necessary when profiling so that there's a single block that // can increment the the counters. @@ -3215,6 +3262,8 @@ GraphBuilder::GraphBuilder(Compilation* compilation, IRScope* scope) _initial_state = state_at_entry(); start_block->merge(_initial_state); + // End nulls still exist here + // complete graph _vmap = new ValueMap(); switch (scope->method()->intrinsic_id()) { @@ -3318,6 +3367,27 @@ GraphBuilder::GraphBuilder(Compilation* compilation, IRScope* scope) } CHECK_BAILOUT(); +# ifdef ASSERT + //All blocks reachable from start_block have _end != NULL + { + BlockList processed; + BlockList to_go; + to_go.append(start_block); + while(to_go.length() > 0) { + BlockBegin* current = to_go.pop(); + assert(current != NULL, "Should not happen."); + assert(current->end() != NULL, "All blocks reachable from start_block should have end() != NULL."); + processed.append(current); + for(int i = 0; i < current->number_of_sux(); i++) { + BlockBegin* s = current->sux_at(i); + if (!processed.contains(s)) { + to_go.append(s); + } + } + } + } +#endif // ASSERT + _start = setup_start_block(osr_bci, start_block, _osr_entry, _initial_state); eliminate_redundant_phis(_start); diff --git a/src/hotspot/share/c1/c1_IR.cpp b/src/hotspot/share/c1/c1_IR.cpp index e4b9d86dcc300b54334a478b1e7578a1a1d29d88..112089019803b3cab4ec394480196205c959662d 100644 --- a/src/hotspot/share/c1/c1_IR.cpp +++ b/src/hotspot/share/c1/c1_IR.cpp @@ -191,7 +191,8 @@ CodeEmitInfo::CodeEmitInfo(ValueStack* stack, XHandlers* exception_handlers, boo , _oop_map(NULL) , _stack(stack) , _is_method_handle_invoke(false) - , _deoptimize_on_exception(deoptimize_on_exception) { + , _deoptimize_on_exception(deoptimize_on_exception) + , _force_reexecute(false) { assert(_stack != NULL, "must be non null"); } @@ -203,7 +204,8 @@ CodeEmitInfo::CodeEmitInfo(CodeEmitInfo* info, ValueStack* stack) , _oop_map(NULL) , _stack(stack == NULL ? info->_stack : stack) , _is_method_handle_invoke(info->_is_method_handle_invoke) - , _deoptimize_on_exception(info->_deoptimize_on_exception) { + , _deoptimize_on_exception(info->_deoptimize_on_exception) + , _force_reexecute(info->_force_reexecute) { // deep copy of exception handlers if (info->_exception_handlers != NULL) { @@ -215,7 +217,8 @@ CodeEmitInfo::CodeEmitInfo(CodeEmitInfo* info, ValueStack* stack) void CodeEmitInfo::record_debug_info(DebugInformationRecorder* recorder, int pc_offset) { // record the safepoint before recording the debug info for enclosing scopes recorder->add_safepoint(pc_offset, _oop_map->deep_copy()); - _scope_debug_info->record_debug_info(recorder, pc_offset, true/*topmost*/, _is_method_handle_invoke); + bool reexecute = _force_reexecute || _scope_debug_info->should_reexecute(); + _scope_debug_info->record_debug_info(recorder, pc_offset, reexecute, _is_method_handle_invoke); recorder->end_safepoint(pc_offset); } @@ -1261,12 +1264,22 @@ void IR::print(bool cfg_only, bool live_only) { } } +class EndNotNullValidator : public BlockClosure { + public: + EndNotNullValidator(IR* hir) { + hir->start()->iterate_postorder(this); + } + + void block_do(BlockBegin* block) { + assert(block->end() != NULL, "Expect block end to exist."); + } +}; typedef GrowableArray BlockListList; class PredecessorValidator : public BlockClosure { private: - BlockListList* _predecessors; + BlockListList* _predecessors; // Each index i will hold predecessors of block with id i BlockList* _blocks; static int cmp(BlockBegin** a, BlockBegin** b) { @@ -1277,71 +1290,74 @@ class PredecessorValidator : public BlockClosure { PredecessorValidator(IR* hir) { ResourceMark rm; _predecessors = new BlockListList(BlockBegin::number_of_blocks(), BlockBegin::number_of_blocks(), NULL); - _blocks = new BlockList(); + _blocks = new BlockList(BlockBegin::number_of_blocks()); - int i; hir->start()->iterate_preorder(this); if (hir->code() != NULL) { assert(hir->code()->length() == _blocks->length(), "must match"); - for (i = 0; i < _blocks->length(); i++) { + for (int i = 0; i < _blocks->length(); i++) { assert(hir->code()->contains(_blocks->at(i)), "should be in both lists"); } } - for (i = 0; i < _blocks->length(); i++) { + for (int i = 0; i < _blocks->length(); i++) { BlockBegin* block = _blocks->at(i); - BlockList* preds = _predecessors->at(block->block_id()); - if (preds == NULL) { - assert(block->number_of_preds() == 0, "should be the same"); - continue; - } - - // clone the pred list so we can mutate it - BlockList* pred_copy = new BlockList(); - int j; - for (j = 0; j < block->number_of_preds(); j++) { - pred_copy->append(block->pred_at(j)); - } - // sort them in the same order - preds->sort(cmp); - pred_copy->sort(cmp); - int length = MIN2(preds->length(), block->number_of_preds()); - for (j = 0; j < block->number_of_preds(); j++) { - assert(preds->at(j) == pred_copy->at(j), "must match"); - } - - assert(preds->length() == block->number_of_preds(), "should be the same"); + verify_block_preds_against_collected_preds(block); } } virtual void block_do(BlockBegin* block) { _blocks->append(block); - BlockEnd* be = block->end(); - int n = be->number_of_sux(); - int i; - for (i = 0; i < n; i++) { - BlockBegin* sux = be->sux_at(i); - assert(!sux->is_set(BlockBegin::exception_entry_flag), "must not be xhandler"); - - BlockList* preds = _predecessors->at_grow(sux->block_id(), NULL); - if (preds == NULL) { - preds = new BlockList(); - _predecessors->at_put(sux->block_id(), preds); - } - preds->append(block); + verify_successor_xentry_flag(block); + collect_predecessors(block); + } + + private: + void verify_successor_xentry_flag(const BlockBegin* block) const { + for (int i = 0; i < block->end()->number_of_sux(); i++) { + assert(!block->end()->sux_at(i)->is_set(BlockBegin::exception_entry_flag), "must not be xhandler"); + } + for (int i = 0; i < block->number_of_exception_handlers(); i++) { + assert(block->exception_handler_at(i)->is_set(BlockBegin::exception_entry_flag), "must be xhandler"); } + } - n = block->number_of_exception_handlers(); - for (i = 0; i < n; i++) { - BlockBegin* sux = block->exception_handler_at(i); - assert(sux->is_set(BlockBegin::exception_entry_flag), "must be xhandler"); + void collect_predecessors(BlockBegin* block) { + for (int i = 0; i < block->end()->number_of_sux(); i++) { + collect_predecessor(block, block->end()->sux_at(i)); + } + for (int i = 0; i < block->number_of_exception_handlers(); i++) { + collect_predecessor(block, block->exception_handler_at(i)); + } + } - BlockList* preds = _predecessors->at_grow(sux->block_id(), NULL); - if (preds == NULL) { - preds = new BlockList(); - _predecessors->at_put(sux->block_id(), preds); - } - preds->append(block); + void collect_predecessor(BlockBegin* const pred, const BlockBegin* sux) { + BlockList* preds = _predecessors->at_grow(sux->block_id(), NULL); + if (preds == NULL) { + preds = new BlockList(); + _predecessors->at_put(sux->block_id(), preds); + } + preds->append(pred); + } + + void verify_block_preds_against_collected_preds(const BlockBegin* block) const { + BlockList* preds = _predecessors->at(block->block_id()); + if (preds == NULL) { + assert(block->number_of_preds() == 0, "should be the same"); + return; + } + assert(preds->length() == block->number_of_preds(), "should be the same"); + + // clone the pred list so we can mutate it + BlockList* pred_copy = new BlockList(); + for (int j = 0; j < block->number_of_preds(); j++) { + pred_copy->append(block->pred_at(j)); + } + // sort them in the same order + preds->sort(cmp); + pred_copy->sort(cmp); + for (int j = 0; j < block->number_of_preds(); j++) { + assert(preds->at(j) == pred_copy->at(j), "must match"); } } }; @@ -1360,6 +1376,7 @@ public: void IR::verify() { #ifdef ASSERT PredecessorValidator pv(this); + EndNotNullValidator(this); VerifyBlockBeginField verifier; this->iterate_postorder(&verifier); #endif diff --git a/src/hotspot/share/c1/c1_IR.hpp b/src/hotspot/share/c1/c1_IR.hpp index f7155c464137d5bafdb78d311a32a84c06a20fdb..31f44411280544c42d408fd83872d637a79cf790 100644 --- a/src/hotspot/share/c1/c1_IR.hpp +++ b/src/hotspot/share/c1/c1_IR.hpp @@ -232,16 +232,15 @@ class IRScopeDebugInfo: public CompilationResourceObj { //Whether we should reexecute this bytecode for deopt bool should_reexecute(); - void record_debug_info(DebugInformationRecorder* recorder, int pc_offset, bool topmost, bool is_method_handle_invoke = false) { + void record_debug_info(DebugInformationRecorder* recorder, int pc_offset, bool reexecute, bool is_method_handle_invoke = false) { if (caller() != NULL) { // Order is significant: Must record caller first. - caller()->record_debug_info(recorder, pc_offset, false/*topmost*/); + caller()->record_debug_info(recorder, pc_offset, false/*reexecute*/); } DebugToken* locvals = recorder->create_scope_values(locals()); DebugToken* expvals = recorder->create_scope_values(expressions()); DebugToken* monvals = recorder->create_monitor_values(monitors()); // reexecute allowed only for the topmost frame - bool reexecute = topmost ? should_reexecute() : false; bool return_oop = false; // This flag will be ignored since it used only for C2 with escape analysis. bool rethrow_exception = false; bool is_opt_native = false; @@ -264,6 +263,7 @@ class CodeEmitInfo: public CompilationResourceObj { ValueStack* _stack; // used by deoptimization (contains also monitors bool _is_method_handle_invoke; // true if the associated call site is a MethodHandle call site. bool _deoptimize_on_exception; + bool _force_reexecute; // force the reexecute flag on, used for patching stub FrameMap* frame_map() const { return scope()->compilation()->frame_map(); } Compilation* compilation() const { return scope()->compilation(); } @@ -290,7 +290,11 @@ class CodeEmitInfo: public CompilationResourceObj { bool is_method_handle_invoke() const { return _is_method_handle_invoke; } void set_is_method_handle_invoke(bool x) { _is_method_handle_invoke = x; } + bool force_reexecute() const { return _force_reexecute; } + void set_force_reexecute() { _force_reexecute = true; } + int interpreter_frame_size() const; + }; diff --git a/src/hotspot/share/c1/c1_Instruction.cpp b/src/hotspot/share/c1/c1_Instruction.cpp index 687d2dae707be2a50dce11a29416b8f31bd0a6e3..8dbca0667f11f65f9bb32097c6439a36d486634f 100644 --- a/src/hotspot/share/c1/c1_Instruction.cpp +++ b/src/hotspot/share/c1/c1_Instruction.cpp @@ -524,39 +524,21 @@ Constant::CompareResult Constant::compare(Instruction::Condition cond, Value rig // Implementation of BlockBegin -void BlockBegin::set_end(BlockEnd* end) { - assert(end != NULL, "should not reset block end to NULL"); - if (end == _end) { - return; - } - clear_end(); - - // Set the new end - _end = end; +void BlockBegin::set_end(BlockEnd* new_end) { // Assumes that no predecessor of new_end still has it as its successor + assert(new_end != NULL, "Should not reset block new_end to NULL"); + if (new_end == _end) return; - _successors.clear(); - // Now reset successors list based on BlockEnd - for (int i = 0; i < end->number_of_sux(); i++) { - BlockBegin* sux = end->sux_at(i); - _successors.append(sux); - sux->_predecessors.append(this); + // Remove this block as predecessor of its current successors + if (_end != NULL) + for (int i = 0; i < number_of_sux(); i++) { + sux_at(i)->remove_predecessor(this); } - _end->set_begin(this); -} + _end = new_end; -void BlockBegin::clear_end() { - // Must make the predecessors/successors match up with the - // BlockEnd's notion. - if (_end != NULL) { - // disconnect from the old end - _end->set_begin(NULL); - - // disconnect this block from it's current successors - for (int i = 0; i < _successors.length(); i++) { - _successors.at(i)->remove_predecessor(this); - } - _end = NULL; + // Add this block as predecessor of its new successors + for (int i = 0; i < number_of_sux(); i++) { + sux_at(i)->add_predecessor(this); } } @@ -575,7 +557,7 @@ void BlockBegin::disconnect_edge(BlockBegin* from, BlockBegin* to) { if (index >= 0) { sux->_predecessors.remove_at(index); } - from->_successors.remove_at(s); + from->end()->remove_sux_at(s); } else { s++; } @@ -583,16 +565,6 @@ void BlockBegin::disconnect_edge(BlockBegin* from, BlockBegin* to) { } -void BlockBegin::disconnect_from_graph() { - // disconnect this block from all other blocks - for (int p = 0; p < number_of_preds(); p++) { - pred_at(p)->remove_successor(this); - } - for (int s = 0; s < number_of_sux(); s++) { - sux_at(s)->remove_predecessor(this); - } -} - void BlockBegin::substitute_sux(BlockBegin* old_sux, BlockBegin* new_sux) { // modify predecessors before substituting successors for (int i = 0; i < number_of_sux(); i++) { @@ -669,14 +641,6 @@ BlockBegin* BlockBegin::insert_block_between(BlockBegin* sux) { } -void BlockBegin::remove_successor(BlockBegin* pred) { - int idx; - while ((idx = _successors.find(pred)) >= 0) { - _successors.remove_at(idx); - } -} - - void BlockBegin::add_predecessor(BlockBegin* pred) { _predecessors.append(pred); } @@ -926,11 +890,6 @@ void BlockList::iterate_backward(BlockClosure* closure) { } -void BlockList::blocks_do(void f(BlockBegin*)) { - for (int i = length() - 1; i >= 0; i--) f(at(i)); -} - - void BlockList::values_do(ValueVisitor* f) { for (int i = length() - 1; i >= 0; i--) at(i)->block_values_do(f); } @@ -953,26 +912,10 @@ void BlockList::print(bool cfg_only, bool live_only) { // Implementation of BlockEnd -void BlockEnd::set_begin(BlockBegin* begin) { - BlockList* sux = NULL; - if (begin != NULL) { - sux = begin->successors(); - } else if (this->begin() != NULL) { - // copy our sux list - BlockList* sux = new BlockList(this->begin()->number_of_sux()); - for (int i = 0; i < this->begin()->number_of_sux(); i++) { - sux->append(this->begin()->sux_at(i)); - } - } - _sux = sux; -} - - void BlockEnd::substitute_sux(BlockBegin* old_sux, BlockBegin* new_sux) { substitute(*_sux, old_sux, new_sux); } - // Implementation of Phi // Normal phi functions take their operands from the last instruction of the diff --git a/src/hotspot/share/c1/c1_Instruction.hpp b/src/hotspot/share/c1/c1_Instruction.hpp index 6adaae6f30f6869a7737166f9aa5a463e2635e5a..932b79792a5597639c6b7150a466a46e6e981820 100644 --- a/src/hotspot/share/c1/c1_Instruction.hpp +++ b/src/hotspot/share/c1/c1_Instruction.hpp @@ -137,7 +137,6 @@ class BlockList: public GrowableArray { void iterate_forward(BlockClosure* closure); void iterate_backward(BlockClosure* closure); - void blocks_do(void f(BlockBegin*)); void values_do(ValueVisitor* f); void print(bool cfg_only = false, bool live_only = false) PRODUCT_RETURN; }; @@ -1595,7 +1594,6 @@ LEAF(BlockBegin, StateSplit) ResourceBitMap _stores_to_locals; // bit is set when a local variable is stored in the block // SSA specific fields: (factor out later) - BlockList _successors; // the successors of this block BlockList _predecessors; // the predecessors of this block BlockList _dominates; // list of blocks that are dominated by this block BlockBegin* _dominator; // the dominator of this block @@ -1649,7 +1647,6 @@ LEAF(BlockBegin, StateSplit) , _flags(0) , _total_preds(0) , _stores_to_locals() - , _successors(2) , _predecessors(2) , _dominates(2) , _dominator(NULL) @@ -1676,7 +1673,6 @@ LEAF(BlockBegin, StateSplit) // accessors int block_id() const { return _block_id; } int bci() const { return _bci; } - BlockList* successors() { return &_successors; } BlockList* dominates() { return &_dominates; } BlockBegin* dominator() const { return _dominator; } int loop_depth() const { return _loop_depth; } @@ -1704,9 +1700,7 @@ LEAF(BlockBegin, StateSplit) void set_dominator_depth(int d) { _dominator_depth = d; } void set_depth_first_number(int dfn) { _depth_first_number = dfn; } void set_linear_scan_number(int lsn) { _linear_scan_number = lsn; } - void set_end(BlockEnd* end); - void clear_end(); - void disconnect_from_graph(); + void set_end(BlockEnd* new_end); static void disconnect_edge(BlockBegin* from, BlockBegin* to); BlockBegin* insert_block_between(BlockBegin* sux); void substitute_sux(BlockBegin* old_sux, BlockBegin* new_sux); @@ -1729,10 +1723,6 @@ LEAF(BlockBegin, StateSplit) // successors and predecessors int number_of_sux() const; BlockBegin* sux_at(int i) const; - void add_successor(BlockBegin* sux); - void remove_successor(BlockBegin* pred); - bool is_successor(BlockBegin* sux) const { return _successors.contains(sux); } - void add_predecessor(BlockBegin* pred); void remove_predecessor(BlockBegin* pred); bool is_predecessor(BlockBegin* pred) const { return _predecessors.contains(pred); } @@ -1792,6 +1782,7 @@ LEAF(BlockBegin, StateSplit) // debugging void print_block() PRODUCT_RETURN; void print_block(InstructionPrinter& ip, bool live_only = false) PRODUCT_RETURN; + }; @@ -1825,14 +1816,13 @@ BASE(BlockEnd, StateSplit) BlockBegin* begin() const { return _block; } // manipulation - void set_begin(BlockBegin* begin); + inline void remove_sux_at(int i) { _sux->remove_at(i);} + inline int find_sux(BlockBegin* sux) {return _sux->find(sux);} // successors int number_of_sux() const { return _sux != NULL ? _sux->length() : 0; } BlockBegin* sux_at(int i) const { return _sux->at(i); } BlockBegin* default_sux() const { return sux_at(number_of_sux() - 1); } - BlockBegin** addr_sux_at(int i) const { return _sux->adr_at(i); } - int sux_index(BlockBegin* sux) const { return _sux->find(sux); } void substitute_sux(BlockBegin* old_sux, BlockBegin* new_sux); }; @@ -1998,14 +1988,6 @@ LEAF(If, BlockEnd) _cond = mirror(_cond); } - void swap_sux() { - assert(number_of_sux() == 2, "wrong number of successors"); - BlockList* s = sux(); - BlockBegin* t = s->at(0); s->at_put(0, s->at(1)); s->at_put(1, t); - _cond = negate(_cond); - set_flag(UnorderedIsTrueFlag, !check_flag(UnorderedIsTrueFlag)); - } - void set_should_profile(bool value) { set_flag(ProfileMDOFlag, value); } void set_profiled_method(ciMethod* method) { _profiled_method = method; } void set_profiled_bci(int bci) { _profiled_bci = bci; } @@ -2447,9 +2429,8 @@ class BlockPair: public CompilationResourceObj { typedef GrowableArray BlockPairList; -inline int BlockBegin::number_of_sux() const { assert(_end == NULL || _end->number_of_sux() == _successors.length(), "mismatch"); return _successors.length(); } -inline BlockBegin* BlockBegin::sux_at(int i) const { assert(_end == NULL || _end->sux_at(i) == _successors.at(i), "mismatch"); return _successors.at(i); } -inline void BlockBegin::add_successor(BlockBegin* sux) { assert(_end == NULL, "Would create mismatch with successors of BlockEnd"); _successors.append(sux); } +inline int BlockBegin::number_of_sux() const { assert(_end != NULL, "need end"); return _end->number_of_sux(); } +inline BlockBegin* BlockBegin::sux_at(int i) const { assert(_end != NULL , "need end"); return _end->sux_at(i); } #undef ASSERT_VALUES diff --git a/src/hotspot/share/c1/c1_InstructionPrinter.cpp b/src/hotspot/share/c1/c1_InstructionPrinter.cpp index 3e0708351a6cbfd65653700b97995dbb7a3f0f35..1a074a98ff8d94fbd6a2bfacfcbf8bb9ccd77ca4 100644 --- a/src/hotspot/share/c1/c1_InstructionPrinter.cpp +++ b/src/hotspot/share/c1/c1_InstructionPrinter.cpp @@ -612,14 +612,7 @@ void InstructionPrinter::do_BlockBegin(BlockBegin* x) { output()->print(" dom B%d", x->dominator()->block_id()); } - // print predecessors and successors - if (x->successors()->length() > 0) { - output()->print(" sux:"); - for (int i = 0; i < x->successors()->length(); i ++) { - output()->print(" B%d", x->successors()->at(i)->block_id()); - } - } - + // print predecessors if (x->number_of_preds() > 0) { output()->print(" pred:"); for (int i = 0; i < x->number_of_preds(); i ++) { diff --git a/src/hotspot/share/c1/c1_LIR.cpp b/src/hotspot/share/c1/c1_LIR.cpp index 4ab1d887e3ffe2e00b8c1a1a653399105dbd64fb..d27b9175c9da514cfceffa758b7ded5d894188c9 100644 --- a/src/hotspot/share/c1/c1_LIR.cpp +++ b/src/hotspot/share/c1/c1_LIR.cpp @@ -132,17 +132,15 @@ void LIR_Opr::validate_type() const { size_field() == double_size, "must match"); break; case T_FLOAT: - // FP return values can be also in CPU registers on ARM and PPC32 (softfp ABI) + // FP return values can be also in CPU registers on ARM (softfp ABI) assert((kindfield == fpu_register || kindfield == stack_value - ARM_ONLY(|| kindfield == cpu_register) - PPC32_ONLY(|| kindfield == cpu_register) ) && + ARM_ONLY(|| kindfield == cpu_register) ) && size_field() == single_size, "must match"); break; case T_DOUBLE: - // FP return values can be also in CPU registers on ARM and PPC32 (softfp ABI) + // FP return values can be also in CPU registers on ARM (softfp ABI) assert((kindfield == fpu_register || kindfield == stack_value - ARM_ONLY(|| kindfield == cpu_register) - PPC32_ONLY(|| kindfield == cpu_register) ) && + ARM_ONLY(|| kindfield == cpu_register) ) && size_field() == double_size, "must match"); break; case T_BOOLEAN: @@ -497,10 +495,6 @@ void LIR_OpVisitState::visit(LIR_Op* op) { assert(opConvert->_info == NULL, "must be"); if (opConvert->_opr->is_valid()) do_input(opConvert->_opr); if (opConvert->_result->is_valid()) do_output(opConvert->_result); -#ifdef PPC32 - if (opConvert->_tmp1->is_valid()) do_temp(opConvert->_tmp1); - if (opConvert->_tmp2->is_valid()) do_temp(opConvert->_tmp2); -#endif do_stub(opConvert->_stub); break; @@ -880,6 +874,19 @@ void LIR_OpVisitState::visit(LIR_Op* op) { break; } +// LIR_OpLoadKlass + case lir_load_klass: + { + LIR_OpLoadKlass* opLoadKlass = op->as_OpLoadKlass(); + assert(opLoadKlass != NULL, "must be"); + + do_input(opLoadKlass->_obj); + do_output(opLoadKlass->_result); + if (opLoadKlass->_info) do_info(opLoadKlass->_info); + break; + } + + // LIR_OpProfileCall: case lir_profile_call: { assert(op->as_OpProfileCall() != NULL, "must be"); @@ -1049,6 +1056,10 @@ void LIR_OpLock::emit_code(LIR_Assembler* masm) { } } +void LIR_OpLoadKlass::emit_code(LIR_Assembler* masm) { + masm->emit_load_klass(this); +} + #ifdef ASSERT void LIR_OpAssert::emit_code(LIR_Assembler* masm) { masm->emit_assert(this); @@ -1569,7 +1580,7 @@ static void print_block(BlockBegin* x) { } } - if (x->number_of_sux() > 0) { + if (end != NULL && x->number_of_sux() > 0) { tty->print("sux: "); for (int i = 0; i < x->number_of_sux(); i ++) { tty->print("B%d ", x->sux_at(i)->block_id()); @@ -1857,12 +1868,6 @@ void LIR_OpConvert::print_instr(outputStream* out) const { print_bytecode(out, bytecode()); in_opr()->print(out); out->print(" "); result_opr()->print(out); out->print(" "); -#ifdef PPC32 - if(tmp1()->is_valid()) { - tmp1()->print(out); out->print(" "); - tmp2()->print(out); out->print(" "); - } -#endif } void LIR_OpConvert::print_bytecode(outputStream* out, Bytecodes::Code code) { @@ -1970,6 +1975,11 @@ void LIR_OpLock::print_instr(outputStream* out) const { out->print("[lbl:" INTPTR_FORMAT "]", p2i(stub()->entry())); } +void LIR_OpLoadKlass::print_instr(outputStream* out) const { + obj()->print(out); out->print(" "); + result_opr()->print(out); out->print(" "); +} + #ifdef ASSERT void LIR_OpAssert::print_instr(outputStream* out) const { print_condition(out, condition()); out->print(" "); diff --git a/src/hotspot/share/c1/c1_LIR.hpp b/src/hotspot/share/c1/c1_LIR.hpp index 9334ae273d009c2f369866cf3e7140bff891a96a..c4504b7b8b5cc39d18f37279eff13859faeabb87 100644 --- a/src/hotspot/share/c1/c1_LIR.hpp +++ b/src/hotspot/share/c1/c1_LIR.hpp @@ -895,6 +895,7 @@ class LIR_OpUpdateCRC32; class LIR_OpLock; class LIR_OpTypeCheck; class LIR_OpCompareAndSwap; +class LIR_OpLoadKlass; class LIR_OpProfileCall; class LIR_OpProfileType; #ifdef ASSERT @@ -939,6 +940,7 @@ enum LIR_Code { , lir_roundfp , lir_safepoint , lir_unwind + , lir_load_klass , end_op1 , begin_op2 , lir_cmp @@ -1148,6 +1150,7 @@ class LIR_Op: public CompilationResourceObj { virtual LIR_OpUpdateCRC32* as_OpUpdateCRC32() { return NULL; } virtual LIR_OpTypeCheck* as_OpTypeCheck() { return NULL; } virtual LIR_OpCompareAndSwap* as_OpCompareAndSwap() { return NULL; } + virtual LIR_OpLoadKlass* as_OpLoadKlass() { return NULL; } virtual LIR_OpProfileCall* as_OpProfileCall() { return NULL; } virtual LIR_OpProfileType* as_OpProfileType() { return NULL; } #ifdef ASSERT @@ -1820,6 +1823,23 @@ class LIR_OpLock: public LIR_Op { void print_instr(outputStream* out) const PRODUCT_RETURN; }; +class LIR_OpLoadKlass: public LIR_Op { + friend class LIR_OpVisitState; + + private: + LIR_Opr _obj; + public: + LIR_OpLoadKlass(LIR_Opr obj, LIR_Opr result, CodeEmitInfo* info) + : LIR_Op(lir_load_klass, result, info) + , _obj(obj) + {} + + LIR_Opr obj() const { return _obj; } + + virtual LIR_OpLoadKlass* as_OpLoadKlass() { return this; } + virtual void emit_code(LIR_Assembler* masm); + void print_instr(outputStream* out) const PRODUCT_RETURN; +}; class LIR_OpDelay: public LIR_Op { friend class LIR_OpVisitState; @@ -2262,6 +2282,9 @@ class LIR_List: public CompilationResourceObj { void xadd(LIR_Opr src, LIR_Opr add, LIR_Opr res, LIR_Opr tmp) { append(new LIR_Op2(lir_xadd, src, add, res, tmp)); } void xchg(LIR_Opr src, LIR_Opr set, LIR_Opr res, LIR_Opr tmp) { append(new LIR_Op2(lir_xchg, src, set, res, tmp)); } + + void load_klass(LIR_Opr obj, LIR_Opr result, CodeEmitInfo* info) { append(new LIR_OpLoadKlass(obj, result, info)); } + #ifdef ASSERT void lir_assert(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, const char* msg, bool halt) { append(new LIR_OpAssert(condition, opr1, opr2, msg, halt)); } #endif diff --git a/src/hotspot/share/c1/c1_LIRAssembler.cpp b/src/hotspot/share/c1/c1_LIRAssembler.cpp index 1dc3981ceaf073f0b816a0abb702d03c203bedbe..d158faa7c084056721266ac6970934bf3f06d583 100644 --- a/src/hotspot/share/c1/c1_LIRAssembler.cpp +++ b/src/hotspot/share/c1/c1_LIRAssembler.cpp @@ -43,6 +43,7 @@ void LIR_Assembler::patching_epilog(PatchingStub* patch, LIR_PatchCode patch_cod while ((intx) _masm->pc() - (intx) patch->pc_start() < NativeGeneralJump::instruction_size) { _masm->nop(); } + info->set_force_reexecute(); patch->install(_masm, patch_code, obj, info); append_code_stub(patch); diff --git a/src/hotspot/share/c1/c1_LIRAssembler.hpp b/src/hotspot/share/c1/c1_LIRAssembler.hpp index 683e921846242bb97a488334cabdf782fe3b97b1..f27ade60bae2869f06ae8a7d835a9f9ca8843ed1 100644 --- a/src/hotspot/share/c1/c1_LIRAssembler.hpp +++ b/src/hotspot/share/c1/c1_LIRAssembler.hpp @@ -197,6 +197,7 @@ class LIR_Assembler: public CompilationResourceObj { void emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, Label* failure, Label* obj_is_null); void emit_compare_and_swap(LIR_OpCompareAndSwap* op); void emit_lock(LIR_OpLock* op); + void emit_load_klass(LIR_OpLoadKlass* op); void emit_call(LIR_OpJavaCall* op); void emit_rtcall(LIR_OpRTCall* op); void emit_profile_call(LIR_OpProfileCall* op); diff --git a/src/hotspot/share/c1/c1_LIRGenerator.cpp b/src/hotspot/share/c1/c1_LIRGenerator.cpp index bca42cd7cf56e5b3fb5dfd9269f47e54b35d0094..c064558b4584d5c102ba2a249a459428263d7b11 100644 --- a/src/hotspot/share/c1/c1_LIRGenerator.cpp +++ b/src/hotspot/share/c1/c1_LIRGenerator.cpp @@ -620,7 +620,7 @@ void LIRGenerator::monitor_exit(LIR_Opr object, LIR_Opr lock, LIR_Opr new_hdr, L // setup registers LIR_Opr hdr = lock; lock = new_hdr; - CodeStub* slow_path = new MonitorExitStub(lock, UseFastLocking, monitor_no); + CodeStub* slow_path = new MonitorExitStub(lock, !UseHeavyMonitors, monitor_no); __ load_stack_address_monitor(monitor_no, lock); __ unlock_object(hdr, object, lock, scratch, slow_path); } @@ -1231,13 +1231,17 @@ void LIRGenerator::do_isInstance(Intrinsic* x) { __ move(call_result, result); } +void LIRGenerator::load_klass(LIR_Opr obj, LIR_Opr klass, CodeEmitInfo* null_check_info) { + __ load_klass(obj, klass, null_check_info); +} + // Example: object.getClass () void LIRGenerator::do_getClass(Intrinsic* x) { assert(x->number_of_arguments() == 1, "wrong type"); LIRItem rcvr(x->argument_at(0), this); rcvr.load_item(); - LIR_Opr temp = new_register(T_METADATA); + LIR_Opr temp = new_register(T_ADDRESS); LIR_Opr result = rlock_result(x); // need to perform the null check on the rcvr @@ -1246,10 +1250,9 @@ void LIRGenerator::do_getClass(Intrinsic* x) { info = state_for(x); } - // FIXME T_ADDRESS should actually be T_METADATA but it can't because the - // meaning of these two is mixed up (see JDK-8026837). - __ move(new LIR_Address(rcvr.result(), oopDesc::klass_offset_in_bytes(), T_ADDRESS), temp, info); - __ move_wide(new LIR_Address(temp, in_bytes(Klass::java_mirror_offset()), T_ADDRESS), temp); + LIR_Opr klass = new_register(T_METADATA); + load_klass(rcvr.result(), klass, info); + __ move_wide(new LIR_Address(klass, in_bytes(Klass::java_mirror_offset()), T_ADDRESS), temp); // mirror = ((OopHandle)mirror)->resolve(); access_load(IN_NATIVE, T_OBJECT, LIR_OprFact::address(new LIR_Address(temp, T_OBJECT)), result); @@ -1322,7 +1325,7 @@ void LIRGenerator::do_getObjectSize(Intrinsic* x) { value.load_item(); LIR_Opr klass = new_register(T_METADATA); - __ move(new LIR_Address(value.result(), oopDesc::klass_offset_in_bytes(), T_ADDRESS), klass, NULL); + load_klass(value.result(), klass, NULL); LIR_Opr layout = new_register(T_INT); __ move(new LIR_Address(klass, in_bytes(Klass::layout_helper_offset()), T_INT), layout); @@ -3572,7 +3575,7 @@ LIR_Opr LIRGenerator::mask_boolean(LIR_Opr array, LIR_Opr value, CodeEmitInfo*& __ logical_and(value, LIR_OprFact::intConst(1), value_fixed); } LIR_Opr klass = new_register(T_METADATA); - __ move(new LIR_Address(array, oopDesc::klass_offset_in_bytes(), T_ADDRESS), klass, null_check_info); + load_klass(array, klass, null_check_info); null_check_info = NULL; LIR_Opr layout = new_register(T_INT); __ move(new LIR_Address(klass, in_bytes(Klass::layout_helper_offset()), T_INT), layout); diff --git a/src/hotspot/share/c1/c1_LIRGenerator.hpp b/src/hotspot/share/c1/c1_LIRGenerator.hpp index ffe7108c34e572a1d2870527bc317d187162a0a1..2c26e7714fdafc60719598c79ad2ff4fa07c34f9 100644 --- a/src/hotspot/share/c1/c1_LIRGenerator.hpp +++ b/src/hotspot/share/c1/c1_LIRGenerator.hpp @@ -239,6 +239,8 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure { void move_to_phi(PhiResolver* resolver, Value cur_val, Value sux_val); void move_to_phi(ValueStack* cur_state); + void load_klass(LIR_Opr obj, LIR_Opr klass, CodeEmitInfo* null_check_info); + // platform dependent LIR_Opr getThreadPointer(); diff --git a/src/hotspot/share/c1/c1_LinearScan.cpp b/src/hotspot/share/c1/c1_LinearScan.cpp index 27b11d05c8b7e19ea521305fb6bf3c9f4d9904ff..d2386d7cbb6234a9587c432a300f397922751e42 100644 --- a/src/hotspot/share/c1/c1_LinearScan.cpp +++ b/src/hotspot/share/c1/c1_LinearScan.cpp @@ -2141,12 +2141,8 @@ LIR_Opr LinearScan::calc_operand_for_interval(const Interval* interval) { #ifdef _LP64 return LIR_OprFact::double_cpu(assigned_reg, assigned_reg); -#else -#if defined(PPC32) - return LIR_OprFact::double_cpu(assigned_regHi, assigned_reg); #else return LIR_OprFact::double_cpu(assigned_reg, assigned_regHi); -#endif // PPC32 #endif // LP64 } @@ -2789,9 +2785,6 @@ int LinearScan::append_scope_value_for_operand(LIR_Opr opr, GrowableArrayfpu_regnrHi() == opr->fpu_regnrLo() + 1, "assumed in calculation (only fpu_regnrLo is used)"); #endif -#ifdef PPC32 - assert(opr->fpu_regnrLo() == opr->fpu_regnrHi(), "assumed in calculation (only fpu_regnrHi is used)"); -#endif #ifdef VM_LITTLE_ENDIAN VMReg rname_first = frame_map()->fpu_regname(opr->fpu_regnrLo()); diff --git a/src/hotspot/share/c1/c1_Optimizer.cpp b/src/hotspot/share/c1/c1_Optimizer.cpp index e5c5061e334a7a21f7dc55bb36dca9d393e98021..e406a530b73a9531ea9ae785d771a98d97c3acbe 100644 --- a/src/hotspot/share/c1/c1_Optimizer.cpp +++ b/src/hotspot/share/c1/c1_Optimizer.cpp @@ -312,6 +312,19 @@ void Optimizer::eliminate_conditional_expressions() { CE_Eliminator ce(ir()); } +void disconnect_from_graph(BlockBegin* block) { + for (int p = 0; p < block->number_of_preds(); p++) { + BlockBegin* pred = block->pred_at(p); + int idx; + while ((idx = pred->end()->find_sux(block)) >= 0) { + pred->end()->remove_sux_at(idx); + } + } + for (int s = 0; s < block->number_of_sux(); s++) { + block->sux_at(s)->remove_predecessor(block); + } +} + class BlockMerger: public BlockClosure { private: IR* _hir; @@ -336,140 +349,139 @@ class BlockMerger: public BlockClosure { bool try_merge(BlockBegin* block) { BlockEnd* end = block->end(); - if (end->as_Goto() != NULL) { - assert(end->number_of_sux() == 1, "end must have exactly one successor"); - // Note: It would be sufficient to check for the number of successors (= 1) - // in order to decide if this block can be merged potentially. That - // would then also include switch statements w/ only a default case. - // However, in that case we would need to make sure the switch tag - // expression is executed if it can produce observable side effects. - // We should probably have the canonicalizer simplifying such switch - // statements and then we are sure we don't miss these merge opportunities - // here (was bug - gri 7/7/99). - BlockBegin* sux = end->default_sux(); - if (sux->number_of_preds() == 1 && !sux->is_entry_block() && !end->is_safepoint()) { - // merge the two blocks + if (end->as_Goto() == NULL) return false; + + assert(end->number_of_sux() == 1, "end must have exactly one successor"); + // Note: It would be sufficient to check for the number of successors (= 1) + // in order to decide if this block can be merged potentially. That + // would then also include switch statements w/ only a default case. + // However, in that case we would need to make sure the switch tag + // expression is executed if it can produce observable side effects. + // We should probably have the canonicalizer simplifying such switch + // statements and then we are sure we don't miss these merge opportunities + // here (was bug - gri 7/7/99). + BlockBegin* sux = end->default_sux(); + if (sux->number_of_preds() != 1 || sux->is_entry_block() || end->is_safepoint()) return false; + // merge the two blocks #ifdef ASSERT - // verify that state at the end of block and at the beginning of sux are equal - // no phi functions must be present at beginning of sux - ValueStack* sux_state = sux->state(); - ValueStack* end_state = end->state(); - - assert(end_state->scope() == sux_state->scope(), "scopes must match"); - assert(end_state->stack_size() == sux_state->stack_size(), "stack not equal"); - assert(end_state->locals_size() == sux_state->locals_size(), "locals not equal"); - - int index; - Value sux_value; - for_each_stack_value(sux_state, index, sux_value) { - assert(sux_value == end_state->stack_at(index), "stack not equal"); - } - for_each_local_value(sux_state, index, sux_value) { - Phi* sux_phi = sux_value->as_Phi(); - if (sux_phi != NULL && sux_phi->is_illegal()) continue; - assert(sux_value == end_state->local_at(index), "locals not equal"); - } - assert(sux_state->caller_state() == end_state->caller_state(), "caller not equal"); + // verify that state at the end of block and at the beginning of sux are equal + // no phi functions must be present at beginning of sux + ValueStack* sux_state = sux->state(); + ValueStack* end_state = end->state(); + + assert(end_state->scope() == sux_state->scope(), "scopes must match"); + assert(end_state->stack_size() == sux_state->stack_size(), "stack not equal"); + assert(end_state->locals_size() == sux_state->locals_size(), "locals not equal"); + + int index; + Value sux_value; + for_each_stack_value(sux_state, index, sux_value) { + assert(sux_value == end_state->stack_at(index), "stack not equal"); + } + for_each_local_value(sux_state, index, sux_value) { + Phi* sux_phi = sux_value->as_Phi(); + if (sux_phi != NULL && sux_phi->is_illegal()) continue; + assert(sux_value == end_state->local_at(index), "locals not equal"); + } + assert(sux_state->caller_state() == end_state->caller_state(), "caller not equal"); #endif - // find instruction before end & append first instruction of sux block - Instruction* prev = end->prev(); - Instruction* next = sux->next(); - assert(prev->as_BlockEnd() == NULL, "must not be a BlockEnd"); - prev->set_next(next); - prev->fixup_block_pointers(); - sux->disconnect_from_graph(); - block->set_end(sux->end()); - // add exception handlers of deleted block, if any - for (int k = 0; k < sux->number_of_exception_handlers(); k++) { - BlockBegin* xhandler = sux->exception_handler_at(k); - block->add_exception_handler(xhandler); - - // also substitute predecessor of exception handler - assert(xhandler->is_predecessor(sux), "missing predecessor"); - xhandler->remove_predecessor(sux); - if (!xhandler->is_predecessor(block)) { - xhandler->add_predecessor(block); - } - } + // find instruction before end & append first instruction of sux block + Instruction* prev = end->prev(); + Instruction* next = sux->next(); + assert(prev->as_BlockEnd() == NULL, "must not be a BlockEnd"); + prev->set_next(next); + prev->fixup_block_pointers(); + + // disconnect this block from all other blocks + disconnect_from_graph(sux); + block->set_end(sux->end()); + + // TODO Should this be done in set_end universally? + // add exception handlers of deleted block, if any + for (int k = 0; k < sux->number_of_exception_handlers(); k++) { + BlockBegin* xhandler = sux->exception_handler_at(k); + block->add_exception_handler(xhandler); - // debugging output - _merge_count++; - if (PrintBlockElimination) { - tty->print_cr("%d. merged B%d & B%d (stack size = %d)", - _merge_count, block->block_id(), sux->block_id(), sux->state()->stack_size()); - } + // also substitute predecessor of exception handler + assert(xhandler->is_predecessor(sux), "missing predecessor"); + xhandler->remove_predecessor(sux); + if (!xhandler->is_predecessor(block)) { + xhandler->add_predecessor(block); + } + } + + // debugging output + _merge_count++; + if (PrintBlockElimination) { + tty->print_cr("%d. merged B%d & B%d (stack size = %d)", + _merge_count, block->block_id(), sux->block_id(), sux->state()->stack_size()); + } - _hir->verify(); - - If* if_ = block->end()->as_If(); - if (if_) { - IfOp* ifop = if_->x()->as_IfOp(); - Constant* con = if_->y()->as_Constant(); - bool swapped = false; - if (!con || !ifop) { - ifop = if_->y()->as_IfOp(); - con = if_->x()->as_Constant(); - swapped = true; + _hir->verify(); + + If* if_ = block->end()->as_If(); + if (if_) { + IfOp* ifop = if_->x()->as_IfOp(); + Constant* con = if_->y()->as_Constant(); + bool swapped = false; + if (!con || !ifop) { + ifop = if_->y()->as_IfOp(); + con = if_->x()->as_Constant(); + swapped = true; + } + if (con && ifop) { + Constant* tval = ifop->tval()->as_Constant(); + Constant* fval = ifop->fval()->as_Constant(); + if (tval && fval) { + // Find the instruction before if_, starting with ifop. + // When if_ and ifop are not in the same block, prev + // becomes NULL In such (rare) cases it is not + // profitable to perform the optimization. + Value prev = ifop; + while (prev != NULL && prev->next() != if_) { + prev = prev->next(); } - if (con && ifop) { - Constant* tval = ifop->tval()->as_Constant(); - Constant* fval = ifop->fval()->as_Constant(); - if (tval && fval) { - // Find the instruction before if_, starting with ifop. - // When if_ and ifop are not in the same block, prev - // becomes NULL In such (rare) cases it is not - // profitable to perform the optimization. - Value prev = ifop; - while (prev != NULL && prev->next() != if_) { - prev = prev->next(); - } - if (prev != NULL) { - Instruction::Condition cond = if_->cond(); - BlockBegin* tsux = if_->tsux(); - BlockBegin* fsux = if_->fsux(); - if (swapped) { - cond = Instruction::mirror(cond); - } - - BlockBegin* tblock = tval->compare(cond, con, tsux, fsux); - BlockBegin* fblock = fval->compare(cond, con, tsux, fsux); - if (tblock != fblock && !if_->is_safepoint()) { - If* newif = new If(ifop->x(), ifop->cond(), false, ifop->y(), - tblock, fblock, if_->state_before(), if_->is_safepoint()); - newif->set_state(if_->state()->copy()); - - assert(prev->next() == if_, "must be guaranteed by above search"); - NOT_PRODUCT(newif->set_printable_bci(if_->printable_bci())); - prev->set_next(newif); - block->set_end(newif); - - _merge_count++; - if (PrintBlockElimination) { - tty->print_cr("%d. replaced If and IfOp at end of B%d with single If", _merge_count, block->block_id()); - } - - _hir->verify(); - } + if (prev != NULL) { + Instruction::Condition cond = if_->cond(); + BlockBegin* tsux = if_->tsux(); + BlockBegin* fsux = if_->fsux(); + if (swapped) { + cond = Instruction::mirror(cond); + } + + BlockBegin* tblock = tval->compare(cond, con, tsux, fsux); + BlockBegin* fblock = fval->compare(cond, con, tsux, fsux); + if (tblock != fblock && !if_->is_safepoint()) { + If* newif = new If(ifop->x(), ifop->cond(), false, ifop->y(), + tblock, fblock, if_->state_before(), if_->is_safepoint()); + newif->set_state(if_->state()->copy()); + + assert(prev->next() == if_, "must be guaranteed by above search"); + NOT_PRODUCT(newif->set_printable_bci(if_->printable_bci())); + prev->set_next(newif); + block->set_end(newif); + + _merge_count++; + if (PrintBlockElimination) { + tty->print_cr("%d. replaced If and IfOp at end of B%d with single If", _merge_count, block->block_id()); } + + _hir->verify(); } } } - - return true; } } - return false; + + return true; } virtual void block_do(BlockBegin* block) { - _hir->verify(); // repeat since the same block may merge again - while (try_merge(block)) { - _hir->verify(); - } + while (try_merge(block)) ; } }; diff --git a/src/hotspot/share/c1/c1_Runtime1.cpp b/src/hotspot/share/c1/c1_Runtime1.cpp index 072b3d3900a72b4b55252d782ccebf2a0c00697f..68e77c823c80630e93443363376597ff5663bd35 100644 --- a/src/hotspot/share/c1/c1_Runtime1.cpp +++ b/src/hotspot/share/c1/c1_Runtime1.cpp @@ -243,9 +243,6 @@ void Runtime1::generate_blob_for(BufferBlob* buffer_blob, StubID id) { case fpu2long_stub_id: case unwind_exception_id: case counter_overflow_id: -#if defined(PPC32) - case handle_exception_nofpu_id: -#endif expect_oop_map = false; break; default: @@ -739,7 +736,7 @@ JRT_BLOCK_ENTRY(void, Runtime1::monitorenter(JavaThread* current, oopDesc* obj, _monitorenter_slowcase_cnt++; } #endif - if (!UseFastLocking) { + if (UseHeavyMonitors) { lock->set_obj(obj); } assert(obj == lock->obj(), "must match"); @@ -1179,40 +1176,6 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* current, Runtime1::StubID stub_ ShouldNotReachHere(); } -#if defined(PPC32) - if (load_klass_or_mirror_patch_id || - stub_id == Runtime1::load_appendix_patching_id) { - // Update the location in the nmethod with the proper - // metadata. When the code was generated, a NULL was stuffed - // in the metadata table and that table needs to be update to - // have the right value. On intel the value is kept - // directly in the instruction instead of in the metadata - // table, so set_data above effectively updated the value. - nmethod* nm = CodeCache::find_nmethod(instr_pc); - assert(nm != NULL, "invalid nmethod_pc"); - RelocIterator mds(nm, copy_buff, copy_buff + 1); - bool found = false; - while (mds.next() && !found) { - if (mds.type() == relocInfo::oop_type) { - assert(stub_id == Runtime1::load_mirror_patching_id || - stub_id == Runtime1::load_appendix_patching_id, "wrong stub id"); - oop_Relocation* r = mds.oop_reloc(); - oop* oop_adr = r->oop_addr(); - *oop_adr = stub_id == Runtime1::load_mirror_patching_id ? mirror() : appendix(); - r->fix_oop_relocation(); - found = true; - } else if (mds.type() == relocInfo::metadata_type) { - assert(stub_id == Runtime1::load_klass_patching_id, "wrong stub id"); - metadata_Relocation* r = mds.metadata_reloc(); - Metadata** metadata_adr = r->metadata_addr(); - *metadata_adr = load_klass; - r->fix_metadata_relocation(); - found = true; - } - } - assert(found, "the metadata must exist!"); - } -#endif if (do_patch) { // replace instructions // first replace the tail, then the call @@ -1270,13 +1233,6 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* current, Runtime1::StubID stub_ RelocIterator iter(nm, (address)instr_pc, (address)(instr_pc + 1)); relocInfo::change_reloc_info_for_address(&iter, (address) instr_pc, relocInfo::none, rtype); -#ifdef PPC32 - { address instr_pc2 = instr_pc + NativeMovConstReg::lo_offset; - RelocIterator iter2(nm, instr_pc2, instr_pc2 + 1); - relocInfo::change_reloc_info_for_address(&iter2, (address) instr_pc2, - relocInfo::none, rtype); - } -#endif } } else { diff --git a/src/hotspot/share/c1/c1_ValueMap.cpp b/src/hotspot/share/c1/c1_ValueMap.cpp index f1961663179b547211a2b6389a36f7fe826d1624..2e2f883bae5a9b5491ddc6dde3bccbad2819ddaf 100644 --- a/src/hotspot/share/c1/c1_ValueMap.cpp +++ b/src/hotspot/share/c1/c1_ValueMap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -505,7 +505,7 @@ GlobalValueNumbering::GlobalValueNumbering(IR* ir) assert(start_block == ir->start() && start_block->number_of_preds() == 0 && start_block->dominator() == NULL, "must be start block"); assert(start_block->next()->as_Base() != NULL && start_block->next()->next() == NULL, "start block must not have instructions"); - // method parameters are not linked in instructions list, so process them separateley + // method parameters are not linked in instructions list, so process them separately for_each_state_value(start_block->state(), value, assert(value->as_Local() != NULL, "only method parameters allowed"); set_processed(value); diff --git a/src/hotspot/share/c1/c1_ValueMap.hpp b/src/hotspot/share/c1/c1_ValueMap.hpp index 00034c24ed16aa5c2886d6a596ca0866c873a95a..3ada748c67af3eb0808504c4d8b636c097ed843e 100644 --- a/src/hotspot/share/c1/c1_ValueMap.hpp +++ b/src/hotspot/share/c1/c1_ValueMap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -116,7 +116,6 @@ class ValueMap: public CompilationResourceObj { void kill_memory(); void kill_field(ciField* field, bool all_offsets); void kill_array(ValueType* type); - void kill_exception(); void kill_map(ValueMap* map); void kill_all(); diff --git a/src/hotspot/share/c1/c1_globals.hpp b/src/hotspot/share/c1/c1_globals.hpp index 2b5de079a0c9410e490dafb9d2bb9d60ad21c056..e90aaf6536d4470fb51b6422454ebcc51f03f1be 100644 --- a/src/hotspot/share/c1/c1_globals.hpp +++ b/src/hotspot/share/c1/c1_globals.hpp @@ -242,9 +242,6 @@ develop(bool, UseFastNewObjectArray, true, \ "Use fast inlined object array allocation") \ \ - develop(bool, UseFastLocking, true, \ - "Use fast inlined locking code") \ - \ develop(bool, UseSlowPath, false, \ "For debugging: test slow cases by always using them") \ \ diff --git a/src/hotspot/share/cds/archiveBuilder.hpp b/src/hotspot/share/cds/archiveBuilder.hpp index 1057d05b0836647cd1410df9996efc95d233e6fa..484f7271a7c70b271c1214a680c58fcdae4504ab 100644 --- a/src/hotspot/share/cds/archiveBuilder.hpp +++ b/src/hotspot/share/cds/archiveBuilder.hpp @@ -312,14 +312,14 @@ public: template u4 buffer_to_offset_u4(T p) const { uintx offset = buffer_to_offset((address)p); - guarantee(offset <= MAX_SHARED_DELTA, "must be 32-bit offset"); + guarantee(offset <= MAX_SHARED_DELTA, "must be 32-bit offset " INTPTR_FORMAT, offset); return (u4)offset; } template u4 any_to_offset_u4(T p) const { uintx offset = any_to_offset((address)p); - guarantee(offset <= MAX_SHARED_DELTA, "must be 32-bit offset"); + guarantee(offset <= MAX_SHARED_DELTA, "must be 32-bit offset " INTPTR_FORMAT, offset); return (u4)offset; } diff --git a/src/hotspot/share/cds/dynamicArchive.cpp b/src/hotspot/share/cds/dynamicArchive.cpp index c821d46d4d0de45461ee3265f2ba30a13316766d..64c95e0893309ce0b68c15f5c3d01bd64805c887 100644 --- a/src/hotspot/share/cds/dynamicArchive.cpp +++ b/src/hotspot/share/cds/dynamicArchive.cpp @@ -354,6 +354,9 @@ public: _builder.doit(); } + ~VM_PopulateDynamicDumpSharedSpace() { + LambdaFormInvokers::cleanup_regenerated_classes(); + } }; void DynamicArchive::check_for_dynamic_dump() { diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp index 14eaa8a6abbfe3ae05bde33234feb15c5347750d..89a4d90d2570e69a19ff5926144676d226756833 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -121,7 +121,6 @@ void FileMapInfo::fail_continue(const char *msg, ...) { fail_exit(msg, ap); } else { if (log_is_enabled(Info, cds)) { - ResourceMark rm; LogStream ls(Log(cds)::info()); ls.print("UseSharedSpaces: "); ls.vprint_cr(msg, ap); @@ -1042,15 +1041,20 @@ void FileMapInfo::validate_non_existent_class_paths() { } } -// a utility class for checking file header +// A utility class for reading/validating the GenericCDSFileMapHeader portion of +// a CDS archive's header. The file header of all CDS archives with versions from +// CDS_GENERIC_HEADER_SUPPORTED_MIN_VERSION (12) are guaranteed to always start +// with GenericCDSFileMapHeader. This makes it possible to read important information +// from a CDS archive created by a different version of HotSpot, so that we can +// automatically regenerate the archive as necessary (JDK-8261455). class FileHeaderHelper { int _fd; - GenericCDSFileMapHeader _header; + bool _is_valid; + GenericCDSFileMapHeader* _header; + const char* _base_archive_name; public: - FileHeaderHelper() { - _fd = -1; - } + FileHeaderHelper() : _fd(-1), _is_valid(false), _header(nullptr), _base_archive_name(nullptr) {} ~FileHeaderHelper() { if (_fd != -1) { @@ -1059,8 +1063,10 @@ public: } bool initialize(const char* archive_name) { + log_info(cds)("Opening shared archive: %s", archive_name); _fd = os::open(archive_name, O_RDONLY | O_BINARY, 0); if (_fd < 0) { + FileMapInfo::fail_continue("Specified shared archive not found (%s)", archive_name); return false; } return initialize(_fd); @@ -1069,117 +1075,185 @@ public: // for an already opened file, do not set _fd bool initialize(int fd) { assert(fd != -1, "Archive should be opened"); + + + // First read the generic header so we know the exact size of the actual header. + GenericCDSFileMapHeader gen_header; size_t size = sizeof(GenericCDSFileMapHeader); lseek(fd, 0, SEEK_SET); - size_t n = os::read(fd, (void*)&_header, (unsigned int)size); + size_t n = os::read(fd, (void*)&gen_header, (unsigned int)size); + if (n != size) { + FileMapInfo::fail_continue("Unable to read generic CDS file map header from shared archive"); + return false; + } + + if (gen_header._magic != CDS_ARCHIVE_MAGIC && + gen_header._magic != CDS_DYNAMIC_ARCHIVE_MAGIC) { + FileMapInfo::fail_continue("The shared archive file has a bad magic number: %#x", gen_header._magic); + return false; + } + + if (gen_header._version < CDS_GENERIC_HEADER_SUPPORTED_MIN_VERSION) { + FileMapInfo::fail_continue("Cannot handle shared archive file version %d. Must be at least %d", + gen_header._version, CDS_GENERIC_HEADER_SUPPORTED_MIN_VERSION); + return false; + } + + size_t filelen = os::lseek(fd, 0, SEEK_END); + if (gen_header._header_size >= filelen) { + FileMapInfo::fail_continue("Archive file header larger than archive file"); + return false; + } + + // Read the actual header and perform more checks + size = gen_header._header_size; + _header = (GenericCDSFileMapHeader*)NEW_C_HEAP_ARRAY(char, size, mtInternal); + lseek(fd, 0, SEEK_SET); + n = os::read(fd, (void*)_header, (unsigned int)size); if (n != size) { - vm_exit_during_initialization("Unable to read generic CDS file map header from shared archive"); + FileMapInfo::fail_continue("Unable to read actual CDS file map header from shared archive"); return false; } + + if (!check_crc()) { + return false; + } + + if (!check_and_init_base_archive_name()) { + return false; + } + + // All fields in the GenericCDSFileMapHeader has been validated. + _is_valid = true; return true; } GenericCDSFileMapHeader* get_generic_file_header() { - return &_header; - } - - char* read_base_archive_name() { - assert(_fd != -1, "Archive should be open"); - size_t name_size = _header._base_archive_name_size; - assert(name_size != 0, "For non-default base archive, name size should be non-zero!"); - char* base_name = NEW_C_HEAP_ARRAY(char, name_size, mtInternal); - lseek(_fd, _header._base_archive_name_offset, SEEK_SET); // position to correct offset. - size_t n = os::read(_fd, base_name, (unsigned int)name_size); - if (n != name_size) { - log_info(cds)("Unable to read base archive name from archive"); - FREE_C_HEAP_ARRAY(char, base_name); - return nullptr; + assert(_header != nullptr && _is_valid, "must be a valid archive file"); + return _header; + } + + const char* base_archive_name() { + assert(_header != nullptr && _is_valid, "must be a valid archive file"); + return _base_archive_name; + } + + private: + bool check_crc() { + if (VerifySharedSpaces) { + FileMapHeader* header = (FileMapHeader*)_header; + int actual_crc = header->compute_crc(); + if (actual_crc != header->crc()) { + log_info(cds)("_crc expected: %d", header->crc()); + log_info(cds)(" actual: %d", actual_crc); + FileMapInfo::fail_continue("Header checksum verification failed."); + return false; + } } - if (base_name[name_size - 1] != '\0' || strlen(base_name) != name_size - 1) { - log_info(cds)("Base archive name is damaged"); - FREE_C_HEAP_ARRAY(char, base_name); - return nullptr; + return true; + } + + bool check_and_init_base_archive_name() { + unsigned int name_offset = _header->_base_archive_name_offset; + unsigned int name_size = _header->_base_archive_name_size; + unsigned int header_size = _header->_header_size; + + if (name_offset + name_size < name_offset) { + FileMapInfo::fail_continue("base_archive_name offset/size overflow: " UINT32_FORMAT "/" UINT32_FORMAT, + name_offset, name_size); + return false; } - if (!os::file_exists(base_name)) { - log_info(cds)("Base archive %s does not exist", base_name); - FREE_C_HEAP_ARRAY(char, base_name); - return nullptr; + if (_header->_magic == CDS_ARCHIVE_MAGIC) { + if (name_offset != 0) { + FileMapInfo::fail_continue("static shared archive must have zero _base_archive_name_offset"); + return false; + } + if (name_size != 0) { + FileMapInfo::fail_continue("static shared archive must have zero _base_archive_name_size"); + return false; + } + } else { + assert(_header->_magic == CDS_DYNAMIC_ARCHIVE_MAGIC, "must be"); + if ((name_size == 0 && name_offset != 0) || + (name_size != 0 && name_offset == 0)) { + // If either is zero, both must be zero. This indicates that we are using the default base archive. + FileMapInfo::fail_continue("Invalid base_archive_name offset/size: " UINT32_FORMAT "/" UINT32_FORMAT, + name_offset, name_size); + return false; + } + if (name_size > 0) { + if (name_offset + name_size > header_size) { + FileMapInfo::fail_continue("Invalid base_archive_name offset/size (out of range): " + UINT32_FORMAT " + " UINT32_FORMAT " > " UINT32_FORMAT , + name_offset, name_size, header_size); + return false; + } + const char* name = ((const char*)_header) + _header->_base_archive_name_offset; + if (name[name_size - 1] != '\0' || strlen(name) != name_size - 1) { + FileMapInfo::fail_continue("Base archive name is damaged"); + return false; + } + if (!os::file_exists(name)) { + FileMapInfo::fail_continue("Base archive %s does not exist", name); + return false; + } + _base_archive_name = name; + } } - return base_name; + return true; } }; bool FileMapInfo::check_archive(const char* archive_name, bool is_static) { FileHeaderHelper file_helper; if (!file_helper.initialize(archive_name)) { - // do not vm_exit_during_initialization here because Arguments::init_shared_archive_paths() - // requires a shared archive name. The open_for_read() function will log a message regarding - // failure in opening a shared archive. + // Any errors are reported by fail_continue(). return false; } GenericCDSFileMapHeader* header = file_helper.get_generic_file_header(); if (is_static) { if (header->_magic != CDS_ARCHIVE_MAGIC) { - vm_exit_during_initialization("Not a base shared archive", archive_name); - return false; - } - if (header->_base_archive_name_offset != 0) { - log_info(cds)("_base_archive_name_offset should be 0"); - log_info(cds)("_base_archive_name_offset = " UINT32_FORMAT, header->_base_archive_name_offset); + fail_continue("Not a base shared archive: %s", archive_name); return false; } } else { if (header->_magic != CDS_DYNAMIC_ARCHIVE_MAGIC) { - vm_exit_during_initialization("Not a top shared archive", archive_name); - return false; - } - unsigned int name_size = header->_base_archive_name_size; - unsigned int name_offset = header->_base_archive_name_offset; - unsigned int header_size = header->_header_size; - if (name_offset + name_size != header_size) { - log_info(cds)("_header_size should be equal to _base_archive_name_offset plus _base_archive_name_size"); - log_info(cds)(" _base_archive_name_size = " UINT32_FORMAT, name_size); - log_info(cds)(" _base_archive_name_offset = " UINT32_FORMAT, name_offset); - log_info(cds)(" _header_size = " UINT32_FORMAT, header_size); - return false; - } - char* base_name = file_helper.read_base_archive_name(); - if (base_name == nullptr) { + fail_continue("Not a top shared archive: %s", archive_name); return false; } - FREE_C_HEAP_ARRAY(char, base_name); } return true; } +// Return value: +// false: +// is not a valid archive. *base_archive_name is set to null. +// true && (*base_archive_name) == NULL: +// is a valid static archive. +// true && (*base_archive_name) != NULL: +// is a valid dynamic archive. bool FileMapInfo::get_base_archive_name_from_header(const char* archive_name, char** base_archive_name) { FileHeaderHelper file_helper; + *base_archive_name = NULL; + if (!file_helper.initialize(archive_name)) { return false; } GenericCDSFileMapHeader* header = file_helper.get_generic_file_header(); if (header->_magic != CDS_DYNAMIC_ARCHIVE_MAGIC) { - // Not a dynamic header, no need to proceed further. - return false; + assert(header->_magic == CDS_ARCHIVE_MAGIC, "must be"); + return true; } - if ((header->_base_archive_name_size == 0 && header->_base_archive_name_offset != 0) || - (header->_base_archive_name_size != 0 && header->_base_archive_name_offset == 0)) { - fail_continue("Default base archive not set correct"); - return false; - } - if (header->_base_archive_name_size == 0 && - header->_base_archive_name_offset == 0) { + const char* base = file_helper.base_archive_name(); + if (base == nullptr) { *base_archive_name = Arguments::get_default_shared_archive_path(); } else { - // read the base archive name - *base_archive_name = file_helper.read_base_archive_name(); - if (*base_archive_name == nullptr) { - return false; - } + *base_archive_name = os::strdup_check_oom(base); } + return true; } @@ -1247,16 +1321,6 @@ bool FileMapInfo::init_from_file(int fd) { return false; } - if (VerifySharedSpaces) { - int expected_crc = header()->compute_crc(); - if (expected_crc != header()->crc()) { - log_info(cds)("_crc expected: %d", expected_crc); - log_info(cds)(" actual: %d", header()->crc()); - FileMapInfo::fail_continue("Header checksum verification failed."); - return false; - } - } - _file_offset = header()->header_size(); // accounts for the size of _base_archive_name if (is_static()) { @@ -1294,9 +1358,9 @@ bool FileMapInfo::open_for_read() { int fd = os::open(_full_path, O_RDONLY | O_BINARY, 0); if (fd < 0) { if (errno == ENOENT) { - fail_continue("Specified shared archive not found (%s).", _full_path); + fail_continue("Specified shared archive not found (%s)", _full_path); } else { - fail_continue("Failed to open shared archive file (%s).", + fail_continue("Failed to open shared archive file (%s)", os::strerror(errno)); } return false; @@ -2480,28 +2544,28 @@ void FileMapInfo::stop_sharing_and_unmap(const char* msg) { ClassPathEntry** FileMapInfo::_classpath_entries_for_jvmti = NULL; ClassPathEntry* FileMapInfo::get_classpath_entry_for_jvmti(int i, TRAPS) { + if (i == 0) { + // index 0 corresponds to the ClassPathImageEntry which is a globally shared object + // and should never be deleted. + return ClassLoader::get_jrt_entry(); + } ClassPathEntry* ent = _classpath_entries_for_jvmti[i]; if (ent == NULL) { - if (i == 0) { - ent = ClassLoader::get_jrt_entry(); - assert(ent != NULL, "must be"); + SharedClassPathEntry* scpe = shared_path(i); + assert(scpe->is_jar(), "must be"); // other types of scpe will not produce archived classes + + const char* path = scpe->name(); + struct stat st; + if (os::stat(path, &st) != 0) { + char *msg = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, strlen(path) + 128); + jio_snprintf(msg, strlen(path) + 127, "error in finding JAR file %s", path); + THROW_MSG_(vmSymbols::java_io_IOException(), msg, NULL); } else { - SharedClassPathEntry* scpe = shared_path(i); - assert(scpe->is_jar(), "must be"); // other types of scpe will not produce archived classes - - const char* path = scpe->name(); - struct stat st; - if (os::stat(path, &st) != 0) { + ent = ClassLoader::create_class_path_entry(THREAD, path, &st, false, false); + if (ent == NULL) { char *msg = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, strlen(path) + 128); - jio_snprintf(msg, strlen(path) + 127, "error in finding JAR file %s", path); + jio_snprintf(msg, strlen(path) + 127, "error in opening JAR file %s", path); THROW_MSG_(vmSymbols::java_io_IOException(), msg, NULL); - } else { - ent = ClassLoader::create_class_path_entry(THREAD, path, &st, false, false); - if (ent == NULL) { - char *msg = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, strlen(path) + 128); - jio_snprintf(msg, strlen(path) + 127, "error in opening JAR file %s", path); - THROW_MSG_(vmSymbols::java_io_IOException(), msg, NULL); - } } } diff --git a/src/hotspot/share/cds/heapShared.cpp b/src/hotspot/share/cds/heapShared.cpp index aa4694168c12e4ec25ce164670b5bf8d8be4d6a0..2ae72ffb5edf06a6d008410e39a4b36717623c00 100644 --- a/src/hotspot/share/cds/heapShared.cpp +++ b/src/hotspot/share/cds/heapShared.cpp @@ -71,6 +71,7 @@ bool HeapShared::_closed_regions_mapped = false; bool HeapShared::_open_regions_mapped = false; bool HeapShared::_is_loaded = false; +bool HeapShared::_disable_writing = false; address HeapShared::_narrow_oop_base; int HeapShared::_narrow_oop_shift; DumpedInternedStrings *HeapShared::_dumped_interned_strings = NULL; diff --git a/src/hotspot/share/cds/heapShared.hpp b/src/hotspot/share/cds/heapShared.hpp index 0a673c51e864f7cd3d668f6e65d4f8d154848a17..52a8de9ad4602a37169e290647ab2690e94a96ee 100644 --- a/src/hotspot/share/cds/heapShared.hpp +++ b/src/hotspot/share/cds/heapShared.hpp @@ -155,10 +155,18 @@ public: // Can this VM write heap regions into the CDS archive? Currently only G1+compressed{oops,cp} static bool can_write() { - CDS_JAVA_HEAP_ONLY(return (UseG1GC && UseCompressedOops && UseCompressedClassPointers);) + CDS_JAVA_HEAP_ONLY( + if (_disable_writing) { + return false; + } + return (UseG1GC && UseCompressedOops && UseCompressedClassPointers); + ) NOT_CDS_JAVA_HEAP(return false;) } + static void disable_writing() { + CDS_JAVA_HEAP_ONLY(_disable_writing = true;) + } // Can this VM map archived heap regions? Currently only G1+compressed{oops,cp} static bool can_map() { CDS_JAVA_HEAP_ONLY(return (UseG1GC && UseCompressedOops && UseCompressedClassPointers);) @@ -188,6 +196,7 @@ public: private: #if INCLUDE_CDS_JAVA_HEAP + static bool _disable_writing; static bool _closed_regions_mapped; static bool _open_regions_mapped; static bool _is_loaded; diff --git a/src/hotspot/share/cds/lambdaFormInvokers.cpp b/src/hotspot/share/cds/lambdaFormInvokers.cpp index 5c058dc43ac131746c1ccb919189b51a94f56776..59666085d0499c19e4ca2e2eece19c2841a1517a 100644 --- a/src/hotspot/share/cds/lambdaFormInvokers.cpp +++ b/src/hotspot/share/cds/lambdaFormInvokers.cpp @@ -39,10 +39,11 @@ #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" #include "oops/instanceKlass.hpp" -#include "oops/klass.hpp" +#include "oops/klass.inline.hpp" #include "oops/objArrayKlass.hpp" #include "oops/objArrayOop.hpp" #include "oops/oop.inline.hpp" +#include "oops/oopHandle.inline.hpp" #include "oops/typeArrayOop.inline.hpp" #include "runtime/handles.inline.hpp" #include "runtime/javaCalls.hpp" @@ -50,6 +51,7 @@ GrowableArrayCHeap* LambdaFormInvokers::_lambdaform_lines = nullptr; Array*>* LambdaFormInvokers::_static_archive_invokers = nullptr; +GrowableArrayCHeap* LambdaFormInvokers::_regenerated_mirrors = nullptr; #define NUM_FILTER 4 static const char* filter[NUM_FILTER] = {"java.lang.invoke.Invokers$Holder", @@ -81,6 +83,25 @@ void LambdaFormInvokers::append(char* line) { _lambdaform_lines->append(line); } +// The regenerated Klass is not added to any class loader, so we need +// to keep its java_mirror alive to avoid class unloading. +void LambdaFormInvokers::add_regenerated_class(oop regenerated_class) { + if (_regenerated_mirrors == nullptr) { + _regenerated_mirrors = new GrowableArrayCHeap(150); + } + _regenerated_mirrors->append(OopHandle(Universe::vm_global(), regenerated_class)); +} + +void LambdaFormInvokers::cleanup_regenerated_classes() { + if (_regenerated_mirrors == nullptr) return; + + for (int i = 0; i < _regenerated_mirrors->length(); i++) { + _regenerated_mirrors->at(i).release(Universe::vm_global()); + } + delete _regenerated_mirrors; + _regenerated_mirrors = nullptr; +} + // convenient output class PrintLambdaFormMessage { public: @@ -155,12 +176,11 @@ void LambdaFormInvokers::regenerate_holder_classes(TRAPS) { char *buf = NEW_RESOURCE_ARRAY(char, len); memcpy(buf, (char*)h_bytes->byte_at_addr(0), len); ClassFileStream st((u1*)buf, len, NULL, ClassFileStream::verify); - reload_class(class_name, st, CHECK); + regenerate_class(class_name, st, CHECK); } } -// class_handle - the class name, bytes_handle - the class bytes -void LambdaFormInvokers::reload_class(char* name, ClassFileStream& st, TRAPS) { +void LambdaFormInvokers::regenerate_class(char* name, ClassFileStream& st, TRAPS) { Symbol* class_name = SymbolTable::new_symbol((const char*)name); // the class must exist Klass* klass = SystemDictionary::resolve_or_null(class_name, THREAD); @@ -180,6 +200,9 @@ void LambdaFormInvokers::reload_class(char* name, ClassFileStream& st, TRAPS) { cl_info, CHECK); + assert(result->java_mirror() != nullptr, "must be"); + add_regenerated_class(result->java_mirror()); + { MutexLocker mu_r(THREAD, Compile_lock); // add_to_hierarchy asserts this. SystemDictionary::add_to_hierarchy(result); @@ -191,7 +214,7 @@ void LambdaFormInvokers::reload_class(char* name, ClassFileStream& st, TRAPS) { // exclude the existing class from dump SystemDictionaryShared::set_excluded(InstanceKlass::cast(klass)); SystemDictionaryShared::init_dumptime_info(result); - log_info(cds, lambda)("Replaced class %s, old: " INTPTR_FORMAT " new: " INTPTR_FORMAT, + log_info(cds, lambda)("Regenerated class %s, old: " INTPTR_FORMAT " new: " INTPTR_FORMAT, name, p2i(klass), p2i(result)); } diff --git a/src/hotspot/share/cds/lambdaFormInvokers.hpp b/src/hotspot/share/cds/lambdaFormInvokers.hpp index acb5eab4d8adeb989c5314e0b72672f71dc390a3..c3b151790f1c0acd677ee72cd64c0210ffb8fcae 100644 --- a/src/hotspot/share/cds/lambdaFormInvokers.hpp +++ b/src/hotspot/share/cds/lambdaFormInvokers.hpp @@ -25,6 +25,7 @@ #ifndef SHARE_CDS_LAMBDAFORMINVOKERS_HPP #define SHARE_CDS_LAMBDAFORMINVOKERS_HPP #include "memory/allStatic.hpp" +#include "oops/oopHandle.hpp" #include "runtime/handles.hpp" #include "utilities/growableArray.hpp" @@ -37,7 +38,9 @@ class LambdaFormInvokers : public AllStatic { static GrowableArrayCHeap* _lambdaform_lines; // For storing LF form lines (LF_RESOLVE only) in read only table. static Array*>* _static_archive_invokers; - static void reload_class(char* name, ClassFileStream& st, TRAPS); + static GrowableArrayCHeap* _regenerated_mirrors; + static void regenerate_class(char* name, ClassFileStream& st, TRAPS); + static void add_regenerated_class(oop regenerated_class); public: static void append(char* line); static void append_filtered(char* line); @@ -45,5 +48,6 @@ class LambdaFormInvokers : public AllStatic { static void read_static_archive_invokers(); static void regenerate_holder_classes(TRAPS); static void serialize(SerializeClosure* soc); + static void cleanup_regenerated_classes(); }; #endif // SHARE_CDS_LAMBDAFORMINVOKERS_HPP diff --git a/src/hotspot/share/cds/metaspaceShared.cpp b/src/hotspot/share/cds/metaspaceShared.cpp index 17e27a5372f6a65fced5c0f6a7af3a94c1c486af..f714ce790b240a2b13e80cd01e673eb510ca8702 100644 --- a/src/hotspot/share/cds/metaspaceShared.cpp +++ b/src/hotspot/share/cds/metaspaceShared.cpp @@ -596,7 +596,7 @@ public: void do_cld(ClassLoaderData* cld) { assert(cld->is_alive(), "must be"); _loaded_cld.append(cld); - _loaded_cld_handles.append(OopHandle(Universe::vm_global(), cld->holder_phantom())); + _loaded_cld_handles.append(OopHandle(Universe::vm_global(), cld->holder())); } int nof_cld() const { return _loaded_cld.length(); } diff --git a/src/hotspot/share/ci/ciMethod.cpp b/src/hotspot/share/ci/ciMethod.cpp index 862824c5b72f9bc75b0d42c01195c21fbf50780e..b2d9e14208dd57d826e8c30bf1548cfca47b8187 100644 --- a/src/hotspot/share/ci/ciMethod.cpp +++ b/src/hotspot/share/ci/ciMethod.cpp @@ -117,9 +117,11 @@ ciMethod::ciMethod(const methodHandle& h_m, ciInstanceKlass* holder) : if (h_m->method_holder()->is_linked()) { _can_be_statically_bound = h_m->can_be_statically_bound(); + _can_omit_stack_trace = h_m->can_omit_stack_trace(); } else { // Have to use a conservative value in this case. _can_be_statically_bound = false; + _can_omit_stack_trace = true; } // Adjust the definition of this condition to be more useful: @@ -176,6 +178,7 @@ ciMethod::ciMethod(ciInstanceKlass* holder, _intrinsic_id( vmIntrinsics::_none), _instructions_size(-1), _can_be_statically_bound(false), + _can_omit_stack_trace(true), _liveness( NULL) #if defined(COMPILER2) , @@ -766,6 +769,20 @@ bool ciMethod::can_be_statically_bound(ciInstanceKlass* context) const { return (holder() == context) && can_be_statically_bound(); } +// ------------------------------------------------------------------ +// ciMethod::can_omit_stack_trace +// +// Tries to determine whether a method can omit stack trace in throw in compiled code. +bool ciMethod::can_omit_stack_trace() const { + if (!StackTraceInThrowable) { + return true; // stack trace is switched off. + } + if (!OmitStackTraceInFastThrow) { + return false; // Have to provide stack trace. + } + return _can_omit_stack_trace; +} + // ------------------------------------------------------------------ // ciMethod::resolve_invoke // diff --git a/src/hotspot/share/ci/ciMethod.hpp b/src/hotspot/share/ci/ciMethod.hpp index 926badd2f381f44c041ac40da8ca6fe591c59e9d..5e0732dfeb72bf2d1f89ede4aa36321e1871082a 100644 --- a/src/hotspot/share/ci/ciMethod.hpp +++ b/src/hotspot/share/ci/ciMethod.hpp @@ -92,6 +92,7 @@ class ciMethod : public ciMetadata { bool _is_c2_compilable; bool _can_be_parsed; bool _can_be_statically_bound; + bool _can_omit_stack_trace; bool _has_reserved_stack_access; bool _is_overpass; @@ -364,6 +365,8 @@ class ciMethod : public ciMetadata { bool can_be_statically_bound(ciInstanceKlass* context) const; + bool can_omit_stack_trace() const; + // Replay data methods static void dump_name_as_ascii(outputStream* st, Method* method); void dump_name_as_ascii(outputStream* st); diff --git a/src/hotspot/share/classfile/classFileParser.cpp b/src/hotspot/share/classfile/classFileParser.cpp index a7ae7bef5c3d5e5dcbf6c3189846e0dc497db0ef..e9c813ce4fb4870006ceb273c67265df99085217 100644 --- a/src/hotspot/share/classfile/classFileParser.cpp +++ b/src/hotspot/share/classfile/classFileParser.cpp @@ -139,6 +139,8 @@ #define JAVA_18_VERSION 62 +#define JAVA_19_VERSION 63 + void ClassFileParser::set_class_bad_constant_seen(short bad_constant) { assert((bad_constant == JVM_CONSTANT_Module || bad_constant == JVM_CONSTANT_Package) && _major_version >= JAVA_9_VERSION, @@ -2835,7 +2837,8 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs, annotation_default_length, CHECK_NULL); - if (name == vmSymbols::finalize_method_name() && + if (InstanceKlass::is_finalization_enabled() && + name == vmSymbols::finalize_method_name() && signature == vmSymbols::void_method_signature()) { if (m->is_empty_method()) { _has_empty_finalizer = true; @@ -4171,7 +4174,8 @@ void ClassFileParser::set_precomputed_flags(InstanceKlass* ik) { bool f = false; const Method* const m = ik->lookup_method(vmSymbols::finalize_method_name(), vmSymbols::void_method_signature()); - if (m != NULL && !m->is_empty_method()) { + if (InstanceKlass::is_finalization_enabled() && + (m != NULL) && !m->is_empty_method()) { f = true; } @@ -4525,7 +4529,6 @@ void ClassFileParser::verify_legal_class_modifiers(jint flags, TRAPS) const { const bool is_enum = (flags & JVM_ACC_ENUM) != 0; const bool is_annotation = (flags & JVM_ACC_ANNOTATION) != 0; const bool major_gte_1_5 = _major_version >= JAVA_1_5_VERSION; - const bool major_gte_14 = _major_version >= JAVA_14_VERSION; if ((is_abstract && is_final) || (is_interface && !is_abstract) || @@ -4781,7 +4784,7 @@ bool ClassFileParser::verify_unqualified_name(const char* name, // Take pointer to a UTF8 byte string (not NUL-terminated). // Skip over the longest part of the string that could -// be taken as a fieldname. Allow '/' if slash_ok is true. +// be taken as a fieldname. Allow non-trailing '/'s if slash_ok is true. // Return a pointer to just past the fieldname. // Return NULL if no fieldname at all was found, or in the case of slash_ok // being true, we saw consecutive slashes (meaning we were looking for a @@ -4855,7 +4858,7 @@ static const char* skip_over_field_name(const char* const name, } return (not_first_ch) ? old_p : NULL; } - return (not_first_ch) ? p : NULL; + return (not_first_ch && !last_is_slash) ? p : NULL; } // Take pointer to a UTF8 byte string (not NUL-terminated). diff --git a/src/hotspot/share/classfile/classLoader.cpp b/src/hotspot/share/classfile/classLoader.cpp index cf5ede2415fbcb41bd25eb3b188fdd2c7b914606..d5ac1c308fdc4a50b5303f64665d3a16c4f1852e 100644 --- a/src/hotspot/share/classfile/classLoader.cpp +++ b/src/hotspot/share/classfile/classLoader.cpp @@ -1253,7 +1253,8 @@ char* ClassLoader::skip_uri_protocol(char* source) { // Record the shared classpath index and loader type for classes loaded // by the builtin loaders at dump time. -void ClassLoader::record_result(JavaThread* current, InstanceKlass* ik, const ClassFileStream* stream) { +void ClassLoader::record_result(JavaThread* current, InstanceKlass* ik, + const ClassFileStream* stream, bool redefined) { Arguments::assert_is_dumping_archive(); assert(stream != NULL, "sanity"); @@ -1337,10 +1338,10 @@ void ClassLoader::record_result(JavaThread* current, InstanceKlass* ik, const Cl } } - // No path entry found for this class. Must be a shared class loaded by the + // No path entry found for this class: most likely a shared class loaded by the // user defined classloader. - if (classpath_index < 0) { - assert(ik->shared_classpath_index() < 0, "Sanity"); + if (classpath_index < 0 && !SystemDictionaryShared::is_builtin_loader(ik->class_loader_data())) { + assert(ik->shared_classpath_index() < 0, "not assigned yet"); ik->set_shared_classpath_index(UNREGISTERED_INDEX); SystemDictionaryShared::set_shared_class_misc_info(ik, (ClassFileStream*)stream); return; @@ -1359,7 +1360,7 @@ void ClassLoader::record_result(JavaThread* current, InstanceKlass* ik, const Cl ik->name()->utf8_length()); assert(file_name != NULL, "invariant"); - ClassLoaderExt::record_result(classpath_index, ik); + ClassLoaderExt::record_result(classpath_index, ik, redefined); } #endif // INCLUDE_CDS diff --git a/src/hotspot/share/classfile/classLoader.hpp b/src/hotspot/share/classfile/classLoader.hpp index 9cafdd2a83e4f3b09217d26da134eebf23d98392..c454a503a2ed5d3a6af003d9326ba944cc96eb01 100644 --- a/src/hotspot/share/classfile/classLoader.hpp +++ b/src/hotspot/share/classfile/classLoader.hpp @@ -365,7 +365,8 @@ class ClassLoader: AllStatic { static int num_module_path_entries(); static void exit_with_path_failure(const char* error, const char* message); static char* skip_uri_protocol(char* source); - static void record_result(JavaThread* current, InstanceKlass* ik, const ClassFileStream* stream); + static void record_result(JavaThread* current, InstanceKlass* ik, + const ClassFileStream* stream, bool redefined); #endif static char* lookup_vm_options(); diff --git a/src/hotspot/share/classfile/classLoaderData.cpp b/src/hotspot/share/classfile/classLoaderData.cpp index 0f1840cc9a6c0f9537f0bb07a41320e99fbf8c20..252daee19695f2b29af8eed6aea57d5a2b2ea058 100644 --- a/src/hotspot/share/classfile/classLoaderData.cpp +++ b/src/hotspot/share/classfile/classLoaderData.cpp @@ -615,8 +615,9 @@ Dictionary* ClassLoaderData::create_dictionary() { return new Dictionary(this, size, resizable); } -// Tell the GC to keep this klass alive while iterating ClassLoaderDataGraph -oop ClassLoaderData::holder_phantom() const { +// Tell the GC to keep this klass alive. Needed while iterating ClassLoaderDataGraph, +// and any runtime code that uses klasses. +oop ClassLoaderData::holder() const { // A klass that was previously considered dead can be looked up in the // CLD/SD, and its _java_mirror or _class_loader can be stored in a root // or a reachable object making it alive again. The SATB part of G1 needs diff --git a/src/hotspot/share/classfile/classLoaderData.hpp b/src/hotspot/share/classfile/classLoaderData.hpp index bb4938750433eed17e860478dfd1f4e199a64393..0d6defae93515c9dd0bda709a59dce638deb0e99 100644 --- a/src/hotspot/share/classfile/classLoaderData.hpp +++ b/src/hotspot/share/classfile/classLoaderData.hpp @@ -174,7 +174,7 @@ class ClassLoaderData : public CHeapObj { bool has_modified_oops() { return _modified_oops; } oop holder_no_keepalive() const; - oop holder_phantom() const; + oop holder() const; private: void unload(); diff --git a/src/hotspot/share/classfile/classLoaderDataGraph.cpp b/src/hotspot/share/classfile/classLoaderDataGraph.cpp index c1e672a0c4343939cc0651f23075db1f842f25ba..4cbee3ec7d8ae6070e98942a6d3f0efee396cd0c 100644 --- a/src/hotspot/share/classfile/classLoaderDataGraph.cpp +++ b/src/hotspot/share/classfile/classLoaderDataGraph.cpp @@ -336,7 +336,7 @@ public: } if (cld != NULL) { // Keep cld that is being returned alive. - _holder = Handle(_thread, cld->holder_phantom()); + _holder = Handle(_thread, cld->holder()); _next = cld->next(); } else { _next = NULL; diff --git a/src/hotspot/share/classfile/classLoaderExt.cpp b/src/hotspot/share/classfile/classLoaderExt.cpp index e571f2deda8a84b1a65681c8235d5b3df976b4b0..b6da1fb52c041830ca91337c4de3e5173fd8da0d 100644 --- a/src/hotspot/share/classfile/classLoaderExt.cpp +++ b/src/hotspot/share/classfile/classLoaderExt.cpp @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "cds/filemap.hpp" +#include "cds/heapShared.hpp" #include "classfile/classFileParser.hpp" #include "classfile/classLoader.inline.hpp" #include "classfile/classLoaderExt.hpp" @@ -227,7 +228,7 @@ void ClassLoaderExt::setup_search_paths(JavaThread* current) { ClassLoaderExt::setup_app_search_path(current); } -void ClassLoaderExt::record_result(const s2 classpath_index, InstanceKlass* result) { +void ClassLoaderExt::record_result(const s2 classpath_index, InstanceKlass* result, bool redefined) { Arguments::assert_is_dumping_archive(); // We need to remember where the class comes from during dumping. @@ -245,4 +246,21 @@ void ClassLoaderExt::record_result(const s2 classpath_index, InstanceKlass* resu } result->set_shared_classpath_index(classpath_index); result->set_shared_class_loader_type(classloader_type); +#if INCLUDE_CDS_JAVA_HEAP + if (DumpSharedSpaces && AllowArchivingWithJavaAgent && classloader_type == ClassLoader::BOOT_LOADER && + classpath_index < 0 && HeapShared::can_write() && redefined) { + // During static dump, classes for the built-in loaders are always loaded from + // known locations (jimage, classpath or modulepath), so classpath_index should + // always be >= 0. + // The only exception is when a java agent is used during dump time (for testing + // purposes only). If a class is transformed by the agent, the CodeSource of + // this class may point to an unknown location. This may break heap object archiving, + // which requires all the boot classes to be from known locations. This is an + // uncommon scenario (even in test cases). Let's simply disable heap object archiving. + ResourceMark rm; + log_warning(cds)("CDS heap objects cannot be written because class %s maybe modified by ClassFileLoadHook.", + result->external_name()); + HeapShared::disable_writing(); + } +#endif // INCLUDE_CDS_JAVA_HEAP } diff --git a/src/hotspot/share/classfile/classLoaderExt.hpp b/src/hotspot/share/classfile/classLoaderExt.hpp index cbc5481db7872079c3b59721ee73d59784327a88..7e58bc6d1e3f70c05c7f17a577e35e017eff8b23 100644 --- a/src/hotspot/share/classfile/classLoaderExt.hpp +++ b/src/hotspot/share/classfile/classLoaderExt.hpp @@ -111,7 +111,7 @@ public: return _has_non_jar_in_classpath; } - static void record_result(const s2 classpath_index, InstanceKlass* result); + static void record_result(const s2 classpath_index, InstanceKlass* result, bool redefined); static void set_has_app_classes() { _has_app_classes = true; } diff --git a/src/hotspot/share/classfile/klassFactory.cpp b/src/hotspot/share/classfile/klassFactory.cpp index 7b5960ee36ef6d569f0ab9c34d3626467d8777b1..de3e176a464b75c94902e1fd3123bf5becb32d4f 100644 --- a/src/hotspot/share/classfile/klassFactory.cpp +++ b/src/hotspot/share/classfile/klassFactory.cpp @@ -211,7 +211,7 @@ InstanceKlass* KlassFactory::create_from_stream(ClassFileStream* stream, #if INCLUDE_CDS if (Arguments::is_dumping_archive()) { - ClassLoader::record_result(THREAD, result, stream); + ClassLoader::record_result(THREAD, result, stream, old_stream != stream); } #endif // INCLUDE_CDS diff --git a/src/hotspot/share/classfile/vmIntrinsics.hpp b/src/hotspot/share/classfile/vmIntrinsics.hpp index 08cc2bec0e697dcb5c767918dd89ce789ea36cfc..7c3cb1d3f10235bcbb23d3363b930f98953a647d 100644 --- a/src/hotspot/share/classfile/vmIntrinsics.hpp +++ b/src/hotspot/share/classfile/vmIntrinsics.hpp @@ -869,15 +869,16 @@ class methodHandle; "Ljdk/internal/vm/vector/VectorSupport$Vector;") \ do_name(vector_ternary_op_name, "ternaryOp") \ \ - do_intrinsic(_VectorBroadcastCoerced, jdk_internal_vm_vector_VectorSupport, vector_broadcast_coerced_name, vector_broadcast_coerced_sig, F_S)\ - do_signature(vector_broadcast_coerced_sig, "(Ljava/lang/Class;" \ + do_intrinsic(_VectorFromBitsCoerced, jdk_internal_vm_vector_VectorSupport, vector_frombits_coerced_name, vector_frombits_coerced_sig, F_S) \ + do_signature(vector_frombits_coerced_sig, "(Ljava/lang/Class;" \ "Ljava/lang/Class;" \ "I" \ "J" \ + "I" \ "Ljdk/internal/vm/vector/VectorSupport$VectorSpecies;" \ - "Ljdk/internal/vm/vector/VectorSupport$BroadcastOperation;)" \ + "Ljdk/internal/vm/vector/VectorSupport$FromBitsCoercedOperation;)" \ "Ljdk/internal/vm/vector/VectorSupport$VectorPayload;") \ - do_name(vector_broadcast_coerced_name, "broadcastCoerced") \ + do_name(vector_frombits_coerced_name, "fromBitsCoerced") \ \ do_intrinsic(_VectorShuffleIota, jdk_internal_vm_vector_VectorSupport, vector_shuffle_step_iota_name, vector_shuffle_step_iota_sig, F_S) \ do_signature(vector_shuffle_step_iota_sig, "(Ljava/lang/Class;" \ diff --git a/src/hotspot/share/classfile/vmSymbols.hpp b/src/hotspot/share/classfile/vmSymbols.hpp index 6357019adb7757d3d309559d2985bd114d2a2c18..65acd172f685ff9ad9dcd33e3f6331a6d74cbee2 100644 --- a/src/hotspot/share/classfile/vmSymbols.hpp +++ b/src/hotspot/share/classfile/vmSymbols.hpp @@ -142,6 +142,7 @@ template(java_util_Iterator, "java/util/Iterator") \ template(java_lang_Record, "java/lang/Record") \ template(sun_instrument_InstrumentationImpl, "sun/instrument/InstrumentationImpl") \ + template(sun_invoke_util_ValueConversions, "sun/invoke/util/ValueConversions") \ \ template(jdk_internal_loader_NativeLibraries, "jdk/internal/loader/NativeLibraries") \ template(jdk_internal_loader_BuiltinClassLoader, "jdk/internal/loader/BuiltinClassLoader") \ @@ -351,7 +352,6 @@ /* Foreign API Support */ \ template(jdk_internal_invoke_NativeEntryPoint, "jdk/internal/invoke/NativeEntryPoint") \ template(jdk_internal_invoke_NativeEntryPoint_signature, "Ljdk/internal/invoke/NativeEntryPoint;") \ - template(jdk_incubator_foreign_MemoryAccess, "jdk/incubator/foreign/MemoryAccess") \ \ /* Support for JVMCI */ \ JVMCI_VM_SYMBOLS_DO(template, do_alias) \ diff --git a/src/hotspot/share/compiler/methodLiveness.cpp b/src/hotspot/share/compiler/methodLiveness.cpp index 5f83eea6716e65406e2239906f7f724b2fd004f4..6bcabfe4ace5a1ca6aa6aa334acd7ed1e5d32057 100644 --- a/src/hotspot/share/compiler/methodLiveness.cpp +++ b/src/hotspot/share/compiler/methodLiveness.cpp @@ -97,8 +97,6 @@ void MethodLiveness::compute_liveness() { void MethodLiveness::init_basic_blocks() { - bool bailout = false; - int method_len = method()->code_size(); ciMethodBlocks *mblocks = method()->get_method_blocks(); @@ -255,10 +253,6 @@ void MethodLiveness::init_basic_blocks() { // We will patch up jsr/rets in a subsequent pass. ret_list->append(current_block); break; - case Bytecodes::_breakpoint: - // Bail out of there are breakpoints in here. - bailout = true; - break; default: // Do nothing. break; diff --git a/src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp b/src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp index d5c4c14f92e3fc168c2f4350b05840ba672e75ff..7d28f26e68edfd3d6fa560e42fa7d945b54173f1 100644 --- a/src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp +++ b/src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp @@ -442,7 +442,7 @@ void G1BarrierSetC2::post_barrier(GraphKit* kit, Node* cast = __ CastPX(__ ctrl(), adr); // Divide pointer by card size - Node* card_offset = __ URShiftX( cast, __ ConI(CardTable::card_shift) ); + Node* card_offset = __ URShiftX( cast, __ ConI(CardTable::card_shift()) ); // Combine card table base and card offset Node* card_adr = __ AddP(no_base, byte_map_base_node(kit), card_offset ); diff --git a/src/hotspot/share/gc/g1/g1AllocRegion.cpp b/src/hotspot/share/gc/g1/g1AllocRegion.cpp index 239822d6d1d9fbedef918942a172bacf47326879..915110e3ebb1f5c22bd837384972d7c541896d86 100644 --- a/src/hotspot/share/gc/g1/g1AllocRegion.cpp +++ b/src/hotspot/share/gc/g1/g1AllocRegion.cpp @@ -371,7 +371,7 @@ HeapRegion* OldGCAllocRegion::release() { // Determine how far we are from the next card boundary. If it is smaller than // the minimum object size we can allocate into, expand into the next card. HeapWord* top = cur->top(); - HeapWord* aligned_top = align_up(top, BOTConstants::N_bytes); + HeapWord* aligned_top = align_up(top, BOTConstants::card_size()); size_t to_allocate_words = pointer_delta(aligned_top, top, HeapWordSize); diff --git a/src/hotspot/share/gc/g1/g1Arguments.cpp b/src/hotspot/share/gc/g1/g1Arguments.cpp index 6750e61a312780d70cc8ee608338c1802eb2c4eb..348402cf95785697437d9bd064befb965fd466fe 100644 --- a/src/hotspot/share/gc/g1/g1Arguments.cpp +++ b/src/hotspot/share/gc/g1/g1Arguments.cpp @@ -135,15 +135,15 @@ void G1Arguments::initialize_card_set_configuration() { uint region_size_log_mb = (uint)MAX2(HeapRegion::LogOfHRGrainBytes - LOG_M, 0); if (FLAG_IS_DEFAULT(G1RemSetArrayOfCardsEntries)) { - uint num_cards_in_inline_ptr = G1CardSetConfiguration::num_cards_in_inline_ptr(HeapRegion::LogOfHRGrainBytes - CardTable::card_shift); - FLAG_SET_ERGO(G1RemSetArrayOfCardsEntries, MAX2(num_cards_in_inline_ptr * 2, + uint max_cards_in_inline_ptr = G1CardSetConfiguration::max_cards_in_inline_ptr(HeapRegion::LogOfHRGrainBytes - CardTable::card_shift()); + FLAG_SET_ERGO(G1RemSetArrayOfCardsEntries, MAX2(max_cards_in_inline_ptr * 2, G1RemSetArrayOfCardsEntriesBase * (1u << (region_size_log_mb + 1)))); } // Round to next 8 byte boundary for array to maximize space usage. size_t const cur_size = G1CardSetArray::size_in_bytes(G1RemSetArrayOfCardsEntries); FLAG_SET_ERGO(G1RemSetArrayOfCardsEntries, - G1RemSetArrayOfCardsEntries + (uint)(align_up(cur_size, G1CardSetAllocOptions::BufferAlignment) - cur_size) / sizeof(G1CardSetArray::EntryDataType)); + G1RemSetArrayOfCardsEntries + (uint)(align_up(cur_size, G1CardSetAllocOptions::SlotAlignment) - cur_size) / sizeof(G1CardSetArray::EntryDataType)); // Howl card set container globals. if (FLAG_IS_DEFAULT(G1RemSetHowlNumBuckets)) { @@ -243,7 +243,7 @@ void G1Arguments::initialize() { // the refcount in G1CardSetContainer. uint max_parallel_refinement_threads = G1ConcRefinementThreads + G1DirtyCardQueueSet::num_par_ids(); uint const divisor = 3; // Safe divisor; we increment by 2 for each claim, but there is a small initial value. - if (max_parallel_refinement_threads > UINTPTR_MAX / divisor) { + if (max_parallel_refinement_threads > UINT_MAX / divisor) { vm_exit_during_initialization("Too large parallelism for remembered sets."); } } diff --git a/src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp b/src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp index dfb5da1a7a477618c459e9c38049804039cc645e..1c4bc3d33328b322c7e60b9bcf789380ab79e5b0 100644 --- a/src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp +++ b/src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,14 +52,14 @@ G1BlockOffsetTable::G1BlockOffsetTable(MemRegion heap, G1RegionToSpaceMapper* st bool G1BlockOffsetTable::is_card_boundary(HeapWord* p) const { assert(p >= _reserved.start(), "just checking"); size_t delta = pointer_delta(p, _reserved.start()); - return (delta & right_n_bits((int)BOTConstants::LogN_words)) == (size_t)NoBits; + return (delta & right_n_bits((int)BOTConstants::log_card_size_in_words())) == (size_t)NoBits; } #ifdef ASSERT void G1BlockOffsetTable::check_index(size_t index, const char* msg) const { - assert((index) < (_reserved.word_size() >> BOTConstants::LogN_words), + assert((index) < (_reserved.word_size() >> BOTConstants::log_card_size_in_words()), "%s - index: " SIZE_FORMAT ", _vs.committed_size: " SIZE_FORMAT, - msg, (index), (_reserved.word_size() >> BOTConstants::LogN_words)); + msg, (index), (_reserved.word_size() >> BOTConstants::log_card_size_in_words())); assert(G1CollectedHeap::heap()->is_in(address_for_index_raw(index)), "Index " SIZE_FORMAT " corresponding to " PTR_FORMAT " (%u) is not in committed area.", @@ -75,7 +75,6 @@ void G1BlockOffsetTable::check_index(size_t index, const char* msg) const { G1BlockOffsetTablePart::G1BlockOffsetTablePart(G1BlockOffsetTable* array, HeapRegion* hr) : _next_offset_threshold(NULL), - DEBUG_ONLY(_object_can_span(false) COMMA) _bot(array), _hr(hr) { @@ -97,14 +96,7 @@ void G1BlockOffsetTablePart::update() { // The arguments follow the normal convention of denoting // a right-open interval: [start, end) void G1BlockOffsetTablePart:: set_remainder_to_point_to_start(HeapWord* start, HeapWord* end) { - - if (start >= end) { - // The start address is equal to the end address (or to - // the right of the end address) so there are not cards - // that need to be updated.. - return; - } - + assert(start < end, "precondition"); // Write the backskip value for each region. // // offset @@ -141,7 +133,7 @@ void G1BlockOffsetTablePart:: set_remainder_to_point_to_start(HeapWord* start, H size_t start_card = _bot->index_for(start); size_t end_card = _bot->index_for(end-1); assert(start ==_bot->address_for_index(start_card), "Precondition"); - assert(end ==_bot->address_for_index(end_card)+BOTConstants::N_words, "Precondition"); + assert(end ==_bot->address_for_index(end_card)+BOTConstants::card_size_in_words(), "Precondition"); set_remainder_to_point_to_start_incl(start_card, end_card); // closed interval } @@ -149,11 +141,9 @@ void G1BlockOffsetTablePart:: set_remainder_to_point_to_start(HeapWord* start, H // a closed, inclusive interval: [start_card, end_card], cf set_remainder_to_point_to_start() // above. void G1BlockOffsetTablePart::set_remainder_to_point_to_start_incl(size_t start_card, size_t end_card) { - if (start_card > end_card) { - return; - } + assert(start_card <= end_card, "precondition"); assert(start_card > _bot->index_for(_hr->bottom()), "Cannot be first card"); - assert(_bot->offset_array(start_card-1) <= BOTConstants::N_words, + assert(_bot->offset_array(start_card-1) <= BOTConstants::card_size_in_words(), "Offset card has an unexpected value"); size_t start_card_for_region = start_card; u_char offset = max_jubyte; @@ -162,7 +152,7 @@ void G1BlockOffsetTablePart::set_remainder_to_point_to_start_incl(size_t start_c // so that the reach ends in this region and not at the start // of the next. size_t reach = start_card - 1 + (BOTConstants::power_to_cards_back(i+1) - 1); - offset = BOTConstants::N_words + i; + offset = BOTConstants::card_size_in_words() + i; if (reach >= end_card) { _bot->set_offset_array(start_card_for_region, end_card, offset); start_card_for_region = reach + 1; @@ -183,16 +173,16 @@ void G1BlockOffsetTablePart::check_all_cards(size_t start_card, size_t end_card) if (end_card < start_card) { return; } - guarantee(_bot->offset_array(start_card) == BOTConstants::N_words, "Wrong value in second card"); + guarantee(_bot->offset_array(start_card) == BOTConstants::card_size_in_words(), "Wrong value in second card"); for (size_t c = start_card + 1; c <= end_card; c++ /* yeah! */) { u_char entry = _bot->offset_array(c); if (c - start_card > BOTConstants::power_to_cards_back(1)) { - guarantee(entry > BOTConstants::N_words, + guarantee(entry > BOTConstants::card_size_in_words(), "Should be in logarithmic region - " "entry: %u, " "_array->offset_array(c): %u, " "N_words: %u", - (uint)entry, (uint)_bot->offset_array(c), BOTConstants::N_words); + (uint)entry, (uint)_bot->offset_array(c), BOTConstants::card_size_in_words()); } size_t backskip = BOTConstants::entry_to_cards_back(entry); size_t landing_card = c - backskip; @@ -205,10 +195,10 @@ void G1BlockOffsetTablePart::check_all_cards(size_t start_card, size_t end_card) } else { guarantee(landing_card == start_card - 1, "Tautology"); // Note that N_words is the maximum offset value - guarantee(_bot->offset_array(landing_card) <= BOTConstants::N_words, + guarantee(_bot->offset_array(landing_card) <= BOTConstants::card_size_in_words(), "landing card offset: %u, " "N_words: %u", - (uint)_bot->offset_array(landing_card), (uint)BOTConstants::N_words); + (uint)_bot->offset_array(landing_card), (uint)BOTConstants::card_size_in_words()); } } } @@ -233,13 +223,13 @@ void G1BlockOffsetTablePart::alloc_block_work(HeapWord** threshold_, HeapWord* b "phantom block"); assert(blk_end > threshold, "should be past threshold"); assert(blk_start <= threshold, "blk_start should be at or before threshold"); - assert(pointer_delta(threshold, blk_start) <= BOTConstants::N_words, + assert(pointer_delta(threshold, blk_start) <= BOTConstants::card_size_in_words(), "offset should be <= BlockOffsetSharedArray::N"); assert(G1CollectedHeap::heap()->is_in_reserved(blk_start), "reference must be into the heap"); assert(G1CollectedHeap::heap()->is_in_reserved(blk_end-1), "limit must be within the heap"); - assert(threshold == _bot->_reserved.start() + index*BOTConstants::N_words, + assert(threshold == _bot->_reserved.start() + index*BOTConstants::card_size_in_words(), "index must agree with threshold"); DEBUG_ONLY(size_t orig_index = index;) @@ -259,14 +249,14 @@ void G1BlockOffsetTablePart::alloc_block_work(HeapWord** threshold_, HeapWord* b HeapWord* rem_st = _bot->address_for_index(index + 1); // Calculate rem_end this way because end_index // may be the last valid index in the covered region. - HeapWord* rem_end = _bot->address_for_index(end_index) + BOTConstants::N_words; + HeapWord* rem_end = _bot->address_for_index(end_index) + BOTConstants::card_size_in_words(); set_remainder_to_point_to_start(rem_st, rem_end); } index = end_index + 1; // Calculate threshold_ this way because end_index // may be the last valid index in the covered region. - threshold = _bot->address_for_index(end_index) + BOTConstants::N_words; + threshold = _bot->address_for_index(end_index) + BOTConstants::card_size_in_words(); assert(threshold >= blk_end, "Incorrect offset threshold"); *threshold_ = threshold; @@ -277,7 +267,7 @@ void G1BlockOffsetTablePart::alloc_block_work(HeapWord** threshold_, HeapWord* b size_t start_index = _bot->index_for(blk_start); HeapWord* boundary = _bot->address_for_index(start_index); assert((_bot->offset_array(orig_index) == 0 && blk_start == boundary) || - (_bot->offset_array(orig_index) > 0 && _bot->offset_array(orig_index) <= BOTConstants::N_words), + (_bot->offset_array(orig_index) > 0 && _bot->offset_array(orig_index) <= BOTConstants::card_size_in_words()), "offset array should have been set - " "orig_index offset: %u, " "blk_start: " PTR_FORMAT ", " @@ -287,12 +277,12 @@ void G1BlockOffsetTablePart::alloc_block_work(HeapWord** threshold_, HeapWord* b for (size_t j = orig_index + 1; j <= end_index; j++) { assert(_bot->offset_array(j) > 0 && _bot->offset_array(j) <= - (u_char) (BOTConstants::N_words+BOTConstants::N_powers-1), + (u_char) (BOTConstants::card_size_in_words()+BOTConstants::N_powers-1), "offset array should have been set - " "%u not > 0 OR %u not <= %u", (uint) _bot->offset_array(j), (uint) _bot->offset_array(j), - (uint) (BOTConstants::N_words+BOTConstants::N_powers-1)); + (uint) (BOTConstants::card_size_in_words() + BOTConstants::N_powers - 1)); } #endif } @@ -306,7 +296,7 @@ void G1BlockOffsetTablePart::verify() const { for (size_t current_card = start_card; current_card < end_card; current_card++) { u_char entry = _bot->offset_array(current_card); - if (entry < BOTConstants::N_words) { + if (entry < BOTConstants::card_size_in_words()) { // The entry should point to an object before the current card. Verify that // it is possible to walk from that object in to the current card by just // iterating over the objects following it. @@ -340,12 +330,6 @@ void G1BlockOffsetTablePart::verify() const { } } -#ifdef ASSERT -void G1BlockOffsetTablePart::set_object_can_span(bool can_span) { - _object_can_span = can_span; -} -#endif - #ifndef PRODUCT void G1BlockOffsetTablePart::print_on(outputStream* out) { size_t from_index = _bot->index_for(_hr->bottom()); @@ -370,7 +354,7 @@ void G1BlockOffsetTablePart::zero_bottom_entry_raw() { } void G1BlockOffsetTablePart::initialize_threshold() { - _next_offset_threshold = _hr->bottom() + BOTConstants::N_words; + _next_offset_threshold = _hr->bottom() + BOTConstants::card_size_in_words(); } void G1BlockOffsetTablePart::set_for_starts_humongous(HeapWord* obj_top, size_t fill_size) { diff --git a/src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp b/src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp index 128e9d105a2e6631e6218b4540de2e01ad73fba3..1a13ad68c07f66141b9888621696eb9bc4149fef 100644 --- a/src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp +++ b/src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp @@ -55,9 +55,9 @@ private: volatile u_char* _offset_array; // byte array keeping backwards offsets void check_offset(size_t offset, const char* msg) const { - assert(offset <= BOTConstants::N_words, + assert(offset <= BOTConstants::card_size_in_words(), "%s - offset: " SIZE_FORMAT ", N_words: %u", - msg, offset, BOTConstants::N_words); + msg, offset, BOTConstants::card_size_in_words()); } // Bounds checking accessors: @@ -80,13 +80,13 @@ public: // Return the number of slots needed for an offset array // that covers mem_region_words words. static size_t compute_size(size_t mem_region_words) { - size_t number_of_slots = (mem_region_words / BOTConstants::N_words); + size_t number_of_slots = (mem_region_words / BOTConstants::card_size_in_words()); return ReservedSpace::allocation_align_size_up(number_of_slots); } // Returns how many bytes of the heap a single byte of the BOT corresponds to. static size_t heap_map_factor() { - return BOTConstants::N_bytes; + return BOTConstants::card_size(); } // Initialize the Block Offset Table to cover the memory region passed @@ -102,7 +102,7 @@ public: inline HeapWord* address_for_index(size_t index) const; // Variant of address_for_index that does not check the index for validity. inline HeapWord* address_for_index_raw(size_t index) const { - return _reserved.start() + (index << BOTConstants::LogN_words); + return _reserved.start() + (index << BOTConstants::log_card_size_in_words()); } }; @@ -114,9 +114,6 @@ private: // allocation boundary at which offset array must be updated HeapWord* _next_offset_threshold; - // Indicates if an object can span into this G1BlockOffsetTablePart. - debug_only(bool _object_can_span;) - // This is the global BlockOffsetTable. G1BlockOffsetTable* _bot; @@ -212,7 +209,6 @@ public: } void set_for_starts_humongous(HeapWord* obj_top, size_t fill_size); - void set_object_can_span(bool can_span) NOT_DEBUG_RETURN; void print_on(outputStream* out) PRODUCT_RETURN; }; diff --git a/src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp b/src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp index e4e24c219de14efb3aa744a730fa5889933b4d7f..9652c600b8c48bde8818352d3e9aa68cd6a90a23 100644 --- a/src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp +++ b/src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp @@ -41,7 +41,7 @@ inline HeapWord* G1BlockOffsetTablePart::threshold_for_addr(const void* addr) { } // Calculate next threshold. - HeapWord* threshold = card_boundary + BOTConstants::N_words; + HeapWord* threshold = card_boundary + BOTConstants::card_size_in_words(); return threshold; } @@ -84,7 +84,7 @@ void G1BlockOffsetTable::set_offset_array(size_t left, size_t right, u_char offs // Variant of index_for that does not check the index for validity. inline size_t G1BlockOffsetTable::index_for_raw(const void* p) const { - return pointer_delta((char*)p, _reserved.start(), sizeof(char)) >> BOTConstants::LogN; + return pointer_delta((char*)p, _reserved.start(), sizeof(char)) >> BOTConstants::log_card_size(); } inline size_t G1BlockOffsetTable::index_for(const void* p) const { @@ -113,26 +113,29 @@ inline size_t G1BlockOffsetTablePart::block_size(const HeapWord* p) const { } inline HeapWord* G1BlockOffsetTablePart::block_at_or_preceding(const void* addr) const { - assert(_object_can_span || _bot->offset_array(_bot->index_for(_hr->bottom())) == 0, - "Object crossed region boundary, found offset %u instead of 0", - (uint) _bot->offset_array(_bot->index_for(_hr->bottom()))); +#ifdef ASSERT + if (!_hr->is_continues_humongous()) { + // For non-ContinuesHumongous regions, the first obj always starts from bottom. + u_char offset = _bot->offset_array(_bot->index_for(_hr->bottom())); + assert(offset == 0, "Found offset %u instead of 0 for region %u %s", + offset, _hr->hrm_index(), _hr->get_short_type_str()); + } +#endif size_t index = _bot->index_for(addr); - HeapWord* q = _bot->address_for_index(index); - uint offset = _bot->offset_array(index); // Extend u_char to uint. - while (offset >= BOTConstants::N_words) { + while (offset >= BOTConstants::card_size_in_words()) { // The excess of the offset from N_words indicates a power of Base // to go back by. size_t n_cards_back = BOTConstants::entry_to_cards_back(offset); - q -= (BOTConstants::N_words * n_cards_back); index -= n_cards_back; offset = _bot->offset_array(index); } - assert(offset < BOTConstants::N_words, "offset too large"); - q -= offset; - return q; + assert(offset < BOTConstants::card_size_in_words(), "offset too large"); + + HeapWord* q = _bot->address_for_index(index); + return q - offset; } inline HeapWord* G1BlockOffsetTablePart::forward_to_block_containing_addr(HeapWord* q, HeapWord* n, @@ -146,10 +149,8 @@ inline HeapWord* G1BlockOffsetTablePart::forward_to_block_containing_addr(HeapWo "BOT not precise. Index for n: " SIZE_FORMAT " must be equal to the index for addr: " SIZE_FORMAT, _bot->index_for(n), _bot->index_for(addr)); q = n; - oop obj = cast_to_oop(q); - if (obj->klass_or_null_acquire() == NULL) { - return q; - } + assert(cast_to_oop(q)->klass_or_null() != nullptr, + "start of block must be an initialized object"); n += block_size(q); } assert(q <= n, "wrong order for q and addr"); diff --git a/src/hotspot/share/gc/g1/g1CardCounts.cpp b/src/hotspot/share/gc/g1/g1CardCounts.cpp index 1607ec40b95b9a96b2f015bd2b2c5979167001d1..6e56eecafb9a2a4afd22974a13e361c0c1c0b87e 100644 --- a/src/hotspot/share/gc/g1/g1CardCounts.cpp +++ b/src/hotspot/share/gc/g1/g1CardCounts.cpp @@ -126,7 +126,7 @@ void G1CardCounts::clear_range(MemRegion mr) { HeapWord* start_addr = _ct->addr_for(from_card_ptr); assert(start_addr == mr.start(), "MemRegion start must be aligned to a card."); HeapWord* last_addr = _ct->addr_for(last_card_ptr); - assert((last_addr + G1CardTable::card_size_in_words) == mr.end(), "MemRegion end must be aligned to a card."); + assert((last_addr + G1CardTable::card_size_in_words()) == mr.end(), "MemRegion end must be aligned to a card."); #endif // ASSERT // Clear the counts for the (exclusive) card range. diff --git a/src/hotspot/share/gc/g1/g1CardSet.cpp b/src/hotspot/share/gc/g1/g1CardSet.cpp index e9c986ebc5315c42950308fcd5ef0e17028c5f35..ad886b1e7e6baa7c3016605dd19926336aeecb23 100644 --- a/src/hotspot/share/gc/g1/g1CardSet.cpp +++ b/src/hotspot/share/gc/g1/g1CardSet.cpp @@ -45,40 +45,40 @@ G1CardSet::CardSetPtr G1CardSet::FullCardSet = (G1CardSet::CardSetPtr)-1; static uint default_log2_card_region_per_region() { - uint log2_card_region_per_heap_region = 0; + uint log2_card_regions_per_heap_region = 0; const uint card_container_limit = G1CardSetContainer::LogCardsPerRegionLimit; if (card_container_limit < (uint)HeapRegion::LogCardsPerRegion) { - log2_card_region_per_heap_region = (uint)HeapRegion::LogCardsPerRegion - card_container_limit; + log2_card_regions_per_heap_region = (uint)HeapRegion::LogCardsPerRegion - card_container_limit; } - return log2_card_region_per_heap_region; + return log2_card_regions_per_heap_region; } G1CardSetConfiguration::G1CardSetConfiguration() : G1CardSetConfiguration(HeapRegion::LogCardsPerRegion, /* inline_ptr_bits_per_card */ - G1RemSetArrayOfCardsEntries, /* num_cards_in_array */ + G1RemSetArrayOfCardsEntries, /* max_cards_in_array */ (double)G1RemSetCoarsenHowlBitmapToHowlFullPercent / 100, /* cards_in_bitmap_threshold_percent */ G1RemSetHowlNumBuckets, /* num_buckets_in_howl */ (double)G1RemSetCoarsenHowlToFullPercent / 100, /* cards_in_howl_threshold_percent */ (uint)HeapRegion::CardsPerRegion, /* max_cards_in_cardset */ default_log2_card_region_per_region()) /* log2_card_region_per_region */ { - assert((_log2_card_region_per_heap_region + _log2_cards_per_card_region) == (uint)HeapRegion::LogCardsPerRegion, + assert((_log2_card_regions_per_heap_region + _log2_cards_per_card_region) == (uint)HeapRegion::LogCardsPerRegion, "inconsistent heap region virtualization setup"); } -G1CardSetConfiguration::G1CardSetConfiguration(uint num_cards_in_array, +G1CardSetConfiguration::G1CardSetConfiguration(uint max_cards_in_array, double cards_in_bitmap_threshold_percent, uint max_buckets_in_howl, double cards_in_howl_threshold_percent, uint max_cards_in_card_set, uint log2_card_region_per_region) : G1CardSetConfiguration(log2i_exact(max_cards_in_card_set), /* inline_ptr_bits_per_card */ - num_cards_in_array, /* num_cards_in_array */ + max_cards_in_array, /* max_cards_in_array */ cards_in_bitmap_threshold_percent, /* cards_in_bitmap_threshold_percent */ G1CardSetHowl::num_buckets(max_cards_in_card_set, /* num_buckets_in_howl */ - num_cards_in_array, + max_cards_in_array, max_buckets_in_howl), cards_in_howl_threshold_percent, /* cards_in_howl_threshold_percent */ max_cards_in_card_set, /* max_cards_in_cardset */ @@ -86,23 +86,23 @@ G1CardSetConfiguration::G1CardSetConfiguration(uint num_cards_in_array, { } G1CardSetConfiguration::G1CardSetConfiguration(uint inline_ptr_bits_per_card, - uint num_cards_in_array, + uint max_cards_in_array, double cards_in_bitmap_threshold_percent, uint num_buckets_in_howl, double cards_in_howl_threshold_percent, uint max_cards_in_card_set, - uint log2_card_region_per_heap_region) : + uint log2_card_regions_per_heap_region) : _inline_ptr_bits_per_card(inline_ptr_bits_per_card), - _num_cards_in_array(num_cards_in_array), + _max_cards_in_array(max_cards_in_array), _num_buckets_in_howl(num_buckets_in_howl), _max_cards_in_card_set(max_cards_in_card_set), _cards_in_howl_threshold(max_cards_in_card_set * cards_in_howl_threshold_percent), - _num_cards_in_howl_bitmap(G1CardSetHowl::bitmap_size(_max_cards_in_card_set, _num_buckets_in_howl)), - _cards_in_howl_bitmap_threshold(_num_cards_in_howl_bitmap * cards_in_bitmap_threshold_percent), - _log2_num_cards_in_howl_bitmap(log2i_exact(_num_cards_in_howl_bitmap)), - _bitmap_hash_mask(~(~(0) << _log2_num_cards_in_howl_bitmap)), - _log2_card_region_per_heap_region(log2_card_region_per_heap_region), - _log2_cards_per_card_region(log2i_exact(_max_cards_in_card_set) - _log2_card_region_per_heap_region) { + _max_cards_in_howl_bitmap(G1CardSetHowl::bitmap_size(_max_cards_in_card_set, _num_buckets_in_howl)), + _cards_in_howl_bitmap_threshold(_max_cards_in_howl_bitmap * cards_in_bitmap_threshold_percent), + _log2_max_cards_in_howl_bitmap(log2i_exact(_max_cards_in_howl_bitmap)), + _bitmap_hash_mask(~(~(0) << _log2_max_cards_in_howl_bitmap)), + _log2_card_regions_per_heap_region(log2_card_regions_per_heap_region), + _log2_cards_per_card_region(log2i_exact(_max_cards_in_card_set) - _log2_card_regions_per_heap_region) { assert(is_power_of_2(_max_cards_in_card_set), "max_cards_in_card_set must be a power of 2: %u", _max_cards_in_card_set); @@ -118,31 +118,31 @@ G1CardSetConfiguration::~G1CardSetConfiguration() { void G1CardSetConfiguration::init_card_set_alloc_options() { _card_set_alloc_options = NEW_C_HEAP_ARRAY(G1CardSetAllocOptions, num_mem_object_types(), mtGC); new (&_card_set_alloc_options[0]) G1CardSetAllocOptions((uint)CardSetHash::get_node_size()); - new (&_card_set_alloc_options[1]) G1CardSetAllocOptions((uint)G1CardSetArray::size_in_bytes(_num_cards_in_array), 2, 256); - new (&_card_set_alloc_options[2]) G1CardSetAllocOptions((uint)G1CardSetBitMap::size_in_bytes(_num_cards_in_howl_bitmap), 2, 256); + new (&_card_set_alloc_options[1]) G1CardSetAllocOptions((uint)G1CardSetArray::size_in_bytes(_max_cards_in_array), 2, 256); + new (&_card_set_alloc_options[2]) G1CardSetAllocOptions((uint)G1CardSetBitMap::size_in_bytes(_max_cards_in_howl_bitmap), 2, 256); new (&_card_set_alloc_options[3]) G1CardSetAllocOptions((uint)G1CardSetHowl::size_in_bytes(_num_buckets_in_howl), 2, 256); } void G1CardSetConfiguration::log_configuration() { log_debug_p(gc, remset)("Card Set container configuration: " - "InlinePtr #elems %u size %zu " - "Array Of Cards #elems %u size %zu " + "InlinePtr #cards %u size %zu " + "Array Of Cards #cards %u size %zu " "Howl #buckets %u coarsen threshold %u " - "Howl Bitmap #elems %u size %zu coarsen threshold %u " + "Howl Bitmap #cards %u size %zu coarsen threshold %u " "Card regions per heap region %u cards per card region %u", - num_cards_in_inline_ptr(), sizeof(void*), - num_cards_in_array(), G1CardSetArray::size_in_bytes(num_cards_in_array()), + max_cards_in_inline_ptr(), sizeof(void*), + max_cards_in_array(), G1CardSetArray::size_in_bytes(max_cards_in_array()), num_buckets_in_howl(), cards_in_howl_threshold(), - num_cards_in_howl_bitmap(), G1CardSetBitMap::size_in_bytes(num_cards_in_howl_bitmap()), cards_in_howl_bitmap_threshold(), - (uint)1 << log2_card_region_per_heap_region(), + max_cards_in_howl_bitmap(), G1CardSetBitMap::size_in_bytes(max_cards_in_howl_bitmap()), cards_in_howl_bitmap_threshold(), + (uint)1 << log2_card_regions_per_heap_region(), (uint)1 << log2_cards_per_card_region()); } -uint G1CardSetConfiguration::num_cards_in_inline_ptr() const { - return num_cards_in_inline_ptr(_inline_ptr_bits_per_card); +uint G1CardSetConfiguration::max_cards_in_inline_ptr() const { + return max_cards_in_inline_ptr(_inline_ptr_bits_per_card); } -uint G1CardSetConfiguration::num_cards_in_inline_ptr(uint bits_per_card) { +uint G1CardSetConfiguration::max_cards_in_inline_ptr(uint bits_per_card) { return G1CardSetInlinePtr::max_cards_in_inline_ptr(bits_per_card); } @@ -199,8 +199,8 @@ void G1CardSetCoarsenStats::print_on(outputStream* out) { class G1CardSetHashTable : public CHeapObj { using CardSetPtr = G1CardSet::CardSetPtr; - // Did we insert at least one element in the table? - bool volatile _inserted_elem; + // Did we insert at least one card in the table? + bool volatile _inserted_card; G1CardSetMemoryManager* _mm; CardSetHash _table; @@ -247,7 +247,7 @@ public: G1CardSetHashTable(G1CardSetMemoryManager* mm, size_t initial_log_table_size = InitialLogTableSize) : - _inserted_elem(false), + _inserted_card(false), _mm(mm), _table(mm, initial_log_table_size) { } @@ -267,10 +267,10 @@ public: G1CardSetHashTableValue value(region_idx, G1CardSetInlinePtr()); bool inserted = _table.insert_get(Thread::current(), lookup, value, found, should_grow); - if (!_inserted_elem && inserted) { + if (!_inserted_card && inserted) { // It does not matter to us who is setting the flag so a regular atomic store // is sufficient. - Atomic::store(&_inserted_elem, true); + Atomic::store(&_inserted_card, true); } return found.value(); @@ -295,9 +295,9 @@ public: } void reset() { - if (Atomic::load(&_inserted_elem)) { + if (Atomic::load(&_inserted_card)) { _table.unsafe_reset(InitialLogTableSize); - Atomic::store(&_inserted_elem, false); + Atomic::store(&_inserted_card, false); } } @@ -508,19 +508,19 @@ G1AddCardResult G1CardSet::add_to_howl(CardSetPtr parent_card_set, G1AddCardResult G1CardSet::add_to_bitmap(CardSetPtr card_set, uint card_in_region) { G1CardSetBitMap* bitmap = card_set_ptr(card_set); uint card_offset = _config->howl_bitmap_offset(card_in_region); - return bitmap->add(card_offset, _config->cards_in_howl_bitmap_threshold(), _config->num_cards_in_howl_bitmap()); + return bitmap->add(card_offset, _config->cards_in_howl_bitmap_threshold(), _config->max_cards_in_howl_bitmap()); } G1AddCardResult G1CardSet::add_to_inline_ptr(CardSetPtr volatile* card_set_addr, CardSetPtr card_set, uint card_in_region) { G1CardSetInlinePtr value(card_set_addr, card_set); - return value.add(card_in_region, _config->inline_ptr_bits_per_card(), _config->num_cards_in_inline_ptr()); + return value.add(card_in_region, _config->inline_ptr_bits_per_card(), _config->max_cards_in_inline_ptr()); } G1CardSet::CardSetPtr G1CardSet::create_coarsened_array_of_cards(uint card_in_region, bool within_howl) { uint8_t* data = nullptr; CardSetPtr new_card_set; if (within_howl) { - uint const size_in_bits = _config->num_cards_in_howl_bitmap(); + uint const size_in_bits = _config->max_cards_in_howl_bitmap(); uint card_offset = _config->howl_bitmap_offset(card_in_region); data = allocate_mem_object(CardSetBitMap); new (data) G1CardSetBitMap(card_offset, size_in_bits); @@ -549,7 +549,7 @@ bool G1CardSet::coarsen_card_set(volatile CardSetPtr* card_set_addr, break; } case CardSetInlinePtr: { - uint const size = _config->num_cards_in_array(); + uint const size = _config->max_cards_in_array(); uint8_t* data = allocate_mem_object(CardSetArrayOfCards); new (data) G1CardSetArray(card_in_region, size); new_card_set = make_card_set_ptr(data, CardSetArrayOfCards); @@ -626,11 +626,11 @@ void G1CardSet::transfer_cards_in_howl(CardSetPtr parent_card_set, G1TransferCard iter(this, card_region); iterate_cards_during_transfer(source_card_set, iter); } else { - uint diff = _config->num_cards_in_howl_bitmap() - card_set_ptr(source_card_set)->num_bits_set(); + uint diff = _config->max_cards_in_howl_bitmap() - card_set_ptr(source_card_set)->num_bits_set(); // Need to correct for that the Full remembered set occupies more cards than the // bitmap before. - // We add 1 element less because the values will be incremented + // We add 1 card less because the values will be incremented // in G1CardSet::add_card for the current addition or where already incremented in // G1CardSet::add_to_howl after coarsening. diff -= 1; @@ -755,7 +755,7 @@ bool G1CardSet::contains_card(uint card_region, uint card_in_region) { return ptr.contains(card_in_region, _config->inline_ptr_bits_per_card()); } case CardSetArrayOfCards : return card_set_ptr(card_set)->contains(card_in_region); - case CardSetBitMap: return card_set_ptr(card_set)->contains(card_in_region, _config->num_cards_in_howl_bitmap()); + case CardSetBitMap: return card_set_ptr(card_set)->contains(card_in_region, _config->max_cards_in_howl_bitmap()); case CardSetHowl: { G1CardSetHowl* howling_array = card_set_ptr(card_set); diff --git a/src/hotspot/share/gc/g1/g1CardSet.hpp b/src/hotspot/share/gc/g1/g1CardSet.hpp index c8e09cec1267871bdb94a693d169a9e5775786ca..465984d713873d76bb52e42928534b0c364eb39c 100644 --- a/src/hotspot/share/gc/g1/g1CardSet.hpp +++ b/src/hotspot/share/gc/g1/g1CardSet.hpp @@ -50,26 +50,26 @@ class G1CardSetConfiguration { // regions covered by this card set. uint _inline_ptr_bits_per_card; - uint _num_cards_in_array; + uint _max_cards_in_array; uint _num_buckets_in_howl; uint _max_cards_in_card_set; uint _cards_in_howl_threshold; - uint _num_cards_in_howl_bitmap; + uint _max_cards_in_howl_bitmap; uint _cards_in_howl_bitmap_threshold; - uint _log2_num_cards_in_howl_bitmap; + uint _log2_max_cards_in_howl_bitmap; size_t _bitmap_hash_mask; - uint _log2_card_region_per_heap_region; + uint _log2_card_regions_per_heap_region; uint _log2_cards_per_card_region; G1CardSetAllocOptions* _card_set_alloc_options; G1CardSetConfiguration(uint inline_ptr_bits_per_card, - uint num_cards_in_array, + uint max_cards_in_array, double cards_in_bitmap_threshold_percent, uint num_buckets_in_howl, double cards_in_howl_threshold_percent, uint max_cards_in_card_set, - uint log2_card_region_per_heap_region); + uint log2_card_regions_per_heap_region); void init_card_set_alloc_options(); void log_configuration(); @@ -79,7 +79,7 @@ public: G1CardSetConfiguration(); // Initialize card set configuration from parameters. // Testing only. - G1CardSetConfiguration(uint num_cards_in_array, + G1CardSetConfiguration(uint max_cards_in_array, double cards_in_bitmap_threshold_percent, uint max_buckets_in_howl, double cards_in_howl_threshold_percent, @@ -90,21 +90,19 @@ public: // Inline pointer configuration uint inline_ptr_bits_per_card() const { return _inline_ptr_bits_per_card; } - uint num_cards_in_inline_ptr() const; - static uint num_cards_in_inline_ptr(uint bits_per_card); + uint max_cards_in_inline_ptr() const; + static uint max_cards_in_inline_ptr(uint bits_per_card); // Array of Cards configuration - bool use_cards_in_array() const { return _num_cards_in_array != 0; } // Unused for now - // Number of cards in "Array of Cards" set; 0 to disable. + // Maximum number of cards in "Array of Cards" set; 0 to disable. // Always coarsen to next level if full, so no specific threshold. - uint num_cards_in_array() const { return _num_cards_in_array; } + uint max_cards_in_array() const { return _max_cards_in_array; } // Bitmap within Howl card set container configuration - bool use_cards_in_howl_bitmap() const { return _num_cards_in_howl_bitmap != 0; } // Unused for now - uint num_cards_in_howl_bitmap() const { return _num_cards_in_howl_bitmap; } + uint max_cards_in_howl_bitmap() const { return _max_cards_in_howl_bitmap; } // (Approximate) Number of cards in bitmap to coarsen Howl Bitmap to Howl Full. uint cards_in_howl_bitmap_threshold() const { return _cards_in_howl_bitmap_threshold; } - uint log2_num_cards_in_howl_bitmap() const {return _log2_num_cards_in_howl_bitmap;} + uint log2_max_cards_in_howl_bitmap() const {return _log2_max_cards_in_howl_bitmap;} // Howl card set container configuration uint num_buckets_in_howl() const { return _num_buckets_in_howl; } @@ -112,7 +110,7 @@ public: uint cards_in_howl_threshold() const { return _cards_in_howl_threshold; } uint howl_bitmap_offset(uint card_idx) const { return card_idx & _bitmap_hash_mask; } // Given a card index, return the bucket in the array of card sets. - uint howl_bucket_index(uint card_idx) { return card_idx >> _log2_num_cards_in_howl_bitmap; } + uint howl_bucket_index(uint card_idx) { return card_idx >> _log2_max_cards_in_howl_bitmap; } // Full card configuration // Maximum number of cards in a non-full card set for a single region. Card sets @@ -127,8 +125,8 @@ public: // The next two members give information about how many card regions are there // per area (heap region) and how many cards each card region has. - // The log2 of the amount of card regions per heap region configured. - uint log2_card_region_per_heap_region() const { return _log2_card_region_per_heap_region; } + // The log2 of the number of card regions per heap region configured. + uint log2_card_regions_per_heap_region() const { return _log2_card_regions_per_heap_region; } // The log2 of the number of cards per card region. This is calculated from max_cards_in_region() // and above. uint log2_cards_per_card_region() const { return _log2_cards_per_card_region; } diff --git a/src/hotspot/share/gc/g1/g1CardSetContainers.hpp b/src/hotspot/share/gc/g1/g1CardSetContainers.hpp index c273695aa638ba72c97563158ccd732eb74c5500..b74a68c84ae225644af4ee64f0b051843694cb0b 100644 --- a/src/hotspot/share/gc/g1/g1CardSetContainers.hpp +++ b/src/hotspot/share/gc/g1/g1CardSetContainers.hpp @@ -95,7 +95,7 @@ class G1CardSetInlinePtr : public StackObj { return result; } - uint find(uint const card_idx, uint const bits_per_card, uint start_at, uint num_elems); + uint find(uint const card_idx, uint const bits_per_card, uint start_at, uint num_cards); public: G1CardSetInlinePtr() : _value_addr(nullptr), _value((CardSetPtr)G1CardSet::CardSetInlinePtr) { } @@ -218,7 +218,7 @@ private: } public: - G1CardSetArray(uint const card_in_region, EntryCountType num_elems); + G1CardSetArray(uint const card_in_region, EntryCountType num_cards); G1AddCardResult add(uint card_idx); @@ -228,7 +228,6 @@ public: void iterate(CardVisitor& found); size_t num_entries() const { return _num_entries & EntryMask; } - size_t max_entries() const { return _size; } static size_t header_size_in_bytes() { return header_size_in_bytes_internal(); } diff --git a/src/hotspot/share/gc/g1/g1CardSetContainers.inline.hpp b/src/hotspot/share/gc/g1/g1CardSetContainers.inline.hpp index e23386d4040eb6110bfff3d114089658939e21d0..df0e43f0d84fc44bd211f22ebcfadb3117bb00fe 100644 --- a/src/hotspot/share/gc/g1/g1CardSetContainers.inline.hpp +++ b/src/hotspot/share/gc/g1/g1CardSetContainers.inline.hpp @@ -50,19 +50,19 @@ inline G1AddCardResult G1CardSetInlinePtr::add(uint card_idx, uint bits_per_card uint cur_idx = 0; while (true) { - uint num_elems = num_cards_in(_value); - if (num_elems > 0) { - cur_idx = find(card_idx, bits_per_card, cur_idx, num_elems); + uint num_cards = num_cards_in(_value); + if (num_cards > 0) { + cur_idx = find(card_idx, bits_per_card, cur_idx, num_cards); } // Check if the card is already stored in the pointer. - if (cur_idx < num_elems) { + if (cur_idx < num_cards) { return Found; } // Check if there is actually enough space. - if (num_elems >= max_cards_in_inline_ptr) { + if (num_cards >= max_cards_in_inline_ptr) { return Overflow; } - CardSetPtr new_value = merge(_value, card_idx, num_elems, bits_per_card); + CardSetPtr new_value = merge(_value, card_idx, num_cards, bits_per_card); CardSetPtr old_value = Atomic::cmpxchg(_value_addr, _value, new_value, memory_order_relaxed); if (_value == old_value) { return Added; @@ -77,38 +77,38 @@ inline G1AddCardResult G1CardSetInlinePtr::add(uint card_idx, uint bits_per_card } } -inline uint G1CardSetInlinePtr::find(uint card_idx, uint bits_per_card, uint start_at, uint num_elems) { - assert(start_at < num_elems, "Precondition!"); +inline uint G1CardSetInlinePtr::find(uint card_idx, uint bits_per_card, uint start_at, uint num_cards) { + assert(start_at < num_cards, "Precondition!"); uintptr_t const card_mask = (1 << bits_per_card) - 1; uintptr_t value = ((uintptr_t)_value) >> card_pos_for(start_at, bits_per_card); // Check if the card is already stored in the pointer. - for (uint cur_idx = start_at; cur_idx < num_elems; cur_idx++) { + for (uint cur_idx = start_at; cur_idx < num_cards; cur_idx++) { if ((value & card_mask) == card_idx) { return cur_idx; } value >>= bits_per_card; } - return num_elems; + return num_cards; } inline bool G1CardSetInlinePtr::contains(uint card_idx, uint bits_per_card) { - uint num_elems = num_cards_in(_value); - if (num_elems == 0) { + uint num_cards = num_cards_in(_value); + if (num_cards == 0) { return false; } - uint cur_idx = find(card_idx, bits_per_card, 0, num_elems); - return cur_idx < num_elems; + uint cur_idx = find(card_idx, bits_per_card, 0, num_cards); + return cur_idx < num_cards; } template inline void G1CardSetInlinePtr::iterate(CardVisitor& found, uint bits_per_card) { - uint const num_elems = num_cards_in(_value); + uint const num_cards = num_cards_in(_value); uintptr_t const card_mask = (1 << bits_per_card) - 1; uintptr_t value = ((uintptr_t)_value) >> card_pos_for(0, bits_per_card); - for (uint cur_idx = 0; cur_idx < num_elems; cur_idx++) { + for (uint cur_idx = 0; cur_idx < num_cards; cur_idx++) { found(value & card_mask); value >>= bits_per_card; } @@ -136,9 +136,9 @@ inline uintptr_t G1CardSetContainer::decrement_refcount() { return Atomic::sub(&_ref_count, 2u); } -inline G1CardSetArray::G1CardSetArray(uint card_in_region, EntryCountType num_elems) : +inline G1CardSetArray::G1CardSetArray(uint card_in_region, EntryCountType num_cards) : G1CardSetContainer(), - _size(num_elems), + _size(num_cards), _num_entries(1) { assert(_size > 0, "CardSetArray of size 0 not supported."); assert(_size < LockBitMask, "Only support CardSetArray of size %u or smaller.", LockBitMask - 1); @@ -166,7 +166,7 @@ inline G1CardSetArray::G1CardSetArrayLocker::G1CardSetArrayLocker(EntryCountType inline G1AddCardResult G1CardSetArray::add(uint card_idx) { assert(card_idx < (1u << (sizeof(_data[0]) * BitsPerByte)), - "Card index %u does not fit card element.", card_idx); + "Card index %u does not fit allowed card value range.", card_idx); EntryCountType num_entries = Atomic::load_acquire(&_num_entries) & EntryMask; EntryCountType idx = 0; for (; idx < num_entries; idx++) { @@ -181,7 +181,7 @@ inline G1AddCardResult G1CardSetArray::add(uint card_idx) { // Reload number of entries from the G1CardSetArrayLocker as it might have changed. // It already read the actual value with the necessary synchronization. num_entries = x.num_entries(); - // Look if the elements added while waiting for the lock are the same as our card. + // Look if the cards added while waiting for the lock are the same as our card. for (; idx < num_entries; idx++) { if (_data[idx] == card_idx) { return Found; @@ -252,14 +252,14 @@ inline void G1CardSetBitMap::iterate(CardVisitor& found, size_t size_in_bits, ui inline G1CardSetHowl::G1CardSetHowl(EntryCountType card_in_region, G1CardSetConfiguration* config) : G1CardSetContainer(), - _num_entries((config->num_cards_in_array() + 1)) /* Card Transfer will not increment _num_entries */ { + _num_entries((config->max_cards_in_array() + 1)) /* Card Transfer will not increment _num_entries */ { EntryCountType num_buckets = config->num_buckets_in_howl(); EntryCountType bucket = config->howl_bucket_index(card_in_region); for (uint i = 0; i < num_buckets; ++i) { _buckets[i] = G1CardSetInlinePtr(); if (i == bucket) { G1CardSetInlinePtr value(&_buckets[i], _buckets[i]); - value.add(card_in_region, config->inline_ptr_bits_per_card(), config->num_cards_in_inline_ptr()); + value.add(card_in_region, config->inline_ptr_bits_per_card(), config->max_cards_in_inline_ptr()); } } } @@ -275,7 +275,7 @@ inline bool G1CardSetHowl::contains(uint card_idx, G1CardSetConfiguration* confi } case G1CardSet::CardSetBitMap: { uint card_offset = config->howl_bitmap_offset(card_idx); - return G1CardSet::card_set_ptr(card_set)->contains(card_offset, config->num_cards_in_howl_bitmap()); + return G1CardSet::card_set_ptr(card_set)->contains(card_offset, config->max_cards_in_howl_bitmap()); } case G1CardSet::CardSetInlinePtr: { G1CardSetInlinePtr ptr(card_set); @@ -321,28 +321,28 @@ inline void G1CardSetHowl::iterate_cardset(CardSetPtr const card_set, uint index } case G1CardSet::CardSetBitMap: { if (found.start_iterate(G1GCPhaseTimes::MergeRSHowlBitmap)) { - uint offset = index << config->log2_num_cards_in_howl_bitmap(); - G1CardSet::card_set_ptr(card_set)->iterate(found, config->num_cards_in_howl_bitmap(), offset); + uint offset = index << config->log2_max_cards_in_howl_bitmap(); + G1CardSet::card_set_ptr(card_set)->iterate(found, config->max_cards_in_howl_bitmap(), offset); } return; } case G1CardSet::CardSetHowl: { // actually FullCardSet assert(card_set == G1CardSet::FullCardSet, "Must be"); if (found.start_iterate(G1GCPhaseTimes::MergeRSHowlFull)) { - uint offset = index << config->log2_num_cards_in_howl_bitmap(); - found(offset, config->num_cards_in_howl_bitmap()); + uint offset = index << config->log2_max_cards_in_howl_bitmap(); + found(offset, config->max_cards_in_howl_bitmap()); } return; } } } -inline G1CardSetHowl::EntryCountType G1CardSetHowl::num_buckets(size_t size_in_bits, size_t num_cards_in_array, size_t max_num_buckets) { +inline G1CardSetHowl::EntryCountType G1CardSetHowl::num_buckets(size_t size_in_bits, size_t max_cards_in_array, size_t max_num_buckets) { size_t size_bitmap_bytes = BitMap::calc_size_in_words(size_in_bits) * BytesPerWord; // Ensure that in the worst case arrays consume half the memory size // of storing the entire bitmap size_t max_size_arrays_bytes = size_bitmap_bytes / 2; - size_t size_array_bytes = num_cards_in_array * sizeof(G1CardSetArray::EntryDataType); + size_t size_array_bytes = max_cards_in_array * sizeof(G1CardSetArray::EntryDataType); size_t num_arrays = max_size_arrays_bytes / size_array_bytes; // We use shifts and masks for indexing the array. So round down to the next // power of two to not use more than expected memory. diff --git a/src/hotspot/share/gc/g1/g1CardSetMemory.cpp b/src/hotspot/share/gc/g1/g1CardSetMemory.cpp index aba70b1efcdfd5d2833389b5bfa466ac408e69ba..85b4250090af3f1c1d467915274460e355d0b996 100644 --- a/src/hotspot/share/gc/g1/g1CardSetMemory.cpp +++ b/src/hotspot/share/gc/g1/g1CardSetMemory.cpp @@ -30,29 +30,28 @@ #include "runtime/atomic.hpp" #include "utilities/ostream.hpp" - -template -G1CardSetAllocator::G1CardSetAllocator(const char* name, - const G1CardSetAllocOptions* buffer_options, - G1CardSetBufferList* free_buffer_list) : - _segmented_array(buffer_options, free_buffer_list), +template +G1CardSetAllocator::G1CardSetAllocator(const char* name, + const G1CardSetAllocOptions* alloc_options, + G1CardSetFreeList* free_segment_list) : + _segmented_array(alloc_options, free_segment_list), _transfer_lock(false), - _free_nodes_list(), - _pending_nodes_list(), - _num_pending_nodes(0), - _num_free_nodes(0) + _free_slots_list(), + _pending_slots_list(), + _num_pending_slots(0), + _num_free_slots(0) { - uint elem_size = _segmented_array.elem_size(); - assert(elem_size >= sizeof(G1CardSetContainer), "Element instance size %u for allocator %s too small", elem_size, name); + uint slot_size = _segmented_array.slot_size(); + assert(slot_size >= sizeof(G1CardSetContainer), "Slot instance size %u for allocator %s too small", slot_size, name); } -template -G1CardSetAllocator::~G1CardSetAllocator() { +template +G1CardSetAllocator::~G1CardSetAllocator() { drop_all(); } -template -bool G1CardSetAllocator::try_transfer_pending() { +template +bool G1CardSetAllocator::try_transfer_pending() { // Attempt to claim the lock. if (Atomic::load_acquire(&_transfer_lock) || // Skip CAS if likely to fail. Atomic::cmpxchg(&_transfer_lock, false, true)) { @@ -60,13 +59,13 @@ bool G1CardSetAllocator::try_transfer_pending() { } // Have the lock; perform the transfer. - // Claim all the pending nodes. - G1CardSetContainer* first = _pending_nodes_list.pop_all(); + // Claim all the pending slots. + G1CardSetContainer* first = _pending_slots_list.pop_all(); if (first != nullptr) { - // Prepare to add the claimed nodes, and update _num_pending_nodes. + // Prepare to add the claimed slots, and update _num_pending_slots. G1CardSetContainer* last = first; - Atomic::load_acquire(&_num_pending_nodes); + Atomic::load_acquire(&_num_pending_slots); uint count = 1; for (G1CardSetContainer* next = first->next(); next != nullptr; next = next->next()) { @@ -74,70 +73,70 @@ bool G1CardSetAllocator::try_transfer_pending() { ++count; } - Atomic::sub(&_num_pending_nodes, count); + Atomic::sub(&_num_pending_slots, count); // Wait for any in-progress pops to avoid ABA for them. GlobalCounter::write_synchronize(); - // Add synchronized nodes to _free_node_list. + // Add synchronized slots to _free_slots_list. // Update count first so there can be no underflow in allocate(). - Atomic::add(&_num_free_nodes, count); - _free_nodes_list.prepend(*first, *last); + Atomic::add(&_num_free_slots, count); + _free_slots_list.prepend(*first, *last); } Atomic::release_store(&_transfer_lock, false); return true; } -template -void G1CardSetAllocator::free(Elem* elem) { - assert(elem != nullptr, "precondition"); +template +void G1CardSetAllocator::free(Slot* slot) { + assert(slot != nullptr, "precondition"); // Desired minimum transfer batch size. There is relatively little // importance to the specific number. It shouldn't be too big, else // we're wasting space when the release rate is low. If the release // rate is high, we might accumulate more than this before being // able to start a new transfer, but that's okay. Also note that // the allocation rate and the release rate are going to be fairly - // similar, due to how the buffers are used. - kbarret + // similar, due to how the slots are used. - kbarret uint const trigger_transfer = 10; - uint pending_count = Atomic::add(&_num_pending_nodes, 1u, memory_order_relaxed); + uint pending_count = Atomic::add(&_num_pending_slots, 1u, memory_order_relaxed); - G1CardSetContainer* node = reinterpret_cast(reinterpret_cast(elem)); + G1CardSetContainer* container = reinterpret_cast(reinterpret_cast(slot)); - node->set_next(nullptr); - assert(node->next() == nullptr, "precondition"); + container->set_next(nullptr); + assert(container->next() == nullptr, "precondition"); - _pending_nodes_list.push(*node); + _pending_slots_list.push(*container); if (pending_count > trigger_transfer) { try_transfer_pending(); } } -template -void G1CardSetAllocator::drop_all() { - _free_nodes_list.pop_all(); - _pending_nodes_list.pop_all(); - _num_pending_nodes = 0; - _num_free_nodes = 0; +template +void G1CardSetAllocator::drop_all() { + _free_slots_list.pop_all(); + _pending_slots_list.pop_all(); + _num_pending_slots = 0; + _num_free_slots = 0; _segmented_array.drop_all(); } -template -void G1CardSetAllocator::print(outputStream* os) { - uint num_allocated_nodes = _segmented_array.num_allocated_nodes(); - uint num_available_nodes = _segmented_array.num_available_nodes(); - uint highest = _segmented_array.first_array_buffer() != nullptr - ? _segmented_array.first_array_buffer()->num_elems() +template +void G1CardSetAllocator::print(outputStream* os) { + uint num_allocated_slots = _segmented_array.num_allocated_slots(); + uint num_available_slots = _segmented_array.num_available_slots(); + uint highest = _segmented_array.first_array_segment() != nullptr + ? _segmented_array.first_array_segment()->num_slots() : 0; - uint num_buffers = _segmented_array.num_buffers(); - os->print("MA " PTR_FORMAT ": %u elems pending (allocated %u available %u) used %.3f highest %u buffers %u size %zu ", + uint num_segments = _segmented_array.num_segments(); + os->print("MA " PTR_FORMAT ": %u slots pending (allocated %u available %u) used %.3f highest %u segments %u size %zu ", p2i(this), - _num_pending_nodes, - num_allocated_nodes, - num_available_nodes, - percent_of(num_allocated_nodes - _num_pending_nodes, num_available_nodes), + _num_pending_slots, + num_allocated_slots, + num_available_slots, + percent_of(num_allocated_slots - _num_pending_slots, num_available_slots), highest, - num_buffers, + num_segments, mem_size()); } @@ -202,11 +201,11 @@ size_t G1CardSetMemoryManager::wasted_mem_size() const { return result; } -G1CardSetMemoryStats G1CardSetMemoryManager::memory_stats() const { - G1CardSetMemoryStats result; +G1SegmentedArrayMemoryStats G1CardSetMemoryManager::memory_stats() const { + G1SegmentedArrayMemoryStats result; for (uint i = 0; i < num_mem_object_types(); i++) { result._num_mem_sizes[i] += _allocators[i].mem_size(); - result._num_buffers[i] += _allocators[i].num_buffers(); + result._num_segments[i] += _allocators[i].num_segments(); } return result; } diff --git a/src/hotspot/share/gc/g1/g1CardSetMemory.hpp b/src/hotspot/share/gc/g1/g1CardSetMemory.hpp index 68b7b28354246b1ca74a8962f01e2d3f5af56b05..a9d235f39e5c509bf6b041876efe37f68faa923b 100644 --- a/src/hotspot/share/gc/g1/g1CardSetMemory.hpp +++ b/src/hotspot/share/gc/g1/g1CardSetMemory.hpp @@ -37,43 +37,43 @@ class G1CardSetConfiguration; class outputStream; // Collects G1CardSetAllocator options/heuristics. Called by G1CardSetAllocator -// to determine the next size of the allocated G1CardSetBuffer. +// to determine the next size of the allocated G1CardSetSegment. class G1CardSetAllocOptions : public G1SegmentedArrayAllocOptions { - static const uint MinimumBufferSize = 8; - static const uint MaximumBufferSize = UINT_MAX / 2; + static const uint MinimumNumSlots = 8; + static const uint MaximumNumSlots = UINT_MAX / 2; - uint exponential_expand(uint prev_num_elems) const { - return clamp(prev_num_elems * 2, _initial_num_elems, _max_num_elems); + uint exponential_expand(uint prev_num_slots) const { + return clamp(prev_num_slots * 2, _initial_num_slots, _max_num_slots); } public: - static const uint BufferAlignment = 8; + static const uint SlotAlignment = 8; - G1CardSetAllocOptions(uint elem_size, uint initial_num_elems = MinimumBufferSize, uint max_num_elems = MaximumBufferSize) : - G1SegmentedArrayAllocOptions(align_up(elem_size, BufferAlignment), initial_num_elems, max_num_elems, BufferAlignment) { + G1CardSetAllocOptions(uint slot_size, uint initial_num_slots = MinimumNumSlots, uint max_num_slots = MaximumNumSlots) : + G1SegmentedArrayAllocOptions(align_up(slot_size, SlotAlignment), initial_num_slots, max_num_slots, SlotAlignment) { } - virtual uint next_num_elems(uint prev_num_elems) const override { - return exponential_expand(prev_num_elems); + virtual uint next_num_slots(uint prev_num_slots) const override { + return exponential_expand(prev_num_slots); } }; -typedef G1SegmentedArrayBuffer G1CardSetBuffer; +typedef G1SegmentedArraySegment G1CardSetSegment; -typedef G1SegmentedArrayBufferList G1CardSetBufferList; +typedef G1SegmentedArrayFreeList G1CardSetFreeList; -// Arena-like allocator for (card set) heap memory objects (Elem elements). +// Arena-like allocator for (card set) heap memory objects (Slot slots). // // Allocation and deallocation in the first phase on G1CardSetContainer basis // may occur by multiple threads at once. // // Allocation occurs from an internal free list of G1CardSetContainers first, -// only then trying to bump-allocate from the current G1CardSetBuffer. If there is -// none, this class allocates a new G1CardSetBuffer (allocated from the C heap, +// only then trying to bump-allocate from the current G1CardSetSegment. If there is +// none, this class allocates a new G1CardSetSegment (allocated from the C heap, // asking the G1CardSetAllocOptions instance about sizes etc) and uses that one. // -// The NodeStack free list is a linked list of G1CardSetContainers -// within all G1CardSetBuffer instances allocated so far. It uses a separate +// The SegmentStack free list is a linked list of G1CardSetContainers +// within all G1CardSetSegment instances allocated so far. It uses a separate // pending list and global synchronization to avoid the ABA problem when the // user frees a memory object. // @@ -84,58 +84,62 @@ typedef G1SegmentedArrayBufferList G1CardSetBufferList; // Since it is expected that every CardSet (and in extension each region) has its // own set of allocators, there is intentionally no padding between them to save // memory. -template +template class G1CardSetAllocator { - // G1CardSetBuffer management. + // G1CardSetSegment management. - typedef G1SegmentedArray SegmentedArray; - // G1CardSetContainer node management within the G1CardSetBuffers allocated + typedef G1SegmentedArray SegmentedArray; + // G1CardSetContainer slot management within the G1CardSetSegments allocated // by this allocator. - static G1CardSetContainer* volatile* next_ptr(G1CardSetContainer& node); - typedef LockFreeStack NodeStack; + static G1CardSetContainer* volatile* next_ptr(G1CardSetContainer& slot); + typedef LockFreeStack SlotStack; SegmentedArray _segmented_array; volatile bool _transfer_lock; - NodeStack _free_nodes_list; - NodeStack _pending_nodes_list; + SlotStack _free_slots_list; + SlotStack _pending_slots_list; - volatile uint _num_pending_nodes; // Number of nodes in the pending list. - volatile uint _num_free_nodes; // Number of nodes in the free list. + volatile uint _num_pending_slots; // Number of slots in the pending list. + volatile uint _num_free_slots; // Number of slots in the free list. - // Try to transfer nodes from _pending_nodes_list to _free_nodes_list, with a - // synchronization delay for any in-progress pops from the _free_nodes_list + // Try to transfer slots from _pending_slots_list to _free_slots_list, with a + // synchronization delay for any in-progress pops from the _free_slots_list // to solve ABA here. bool try_transfer_pending(); - uint num_free_elems() const; + uint num_free_slots() const; public: G1CardSetAllocator(const char* name, - const G1CardSetAllocOptions* buffer_options, - G1CardSetBufferList* free_buffer_list); + const G1CardSetAllocOptions* alloc_options, + G1CardSetFreeList* free_segment_list); ~G1CardSetAllocator(); - Elem* allocate(); - void free(Elem* elem); + Slot* allocate(); + void free(Slot* slot); - // Deallocate all buffers to the free buffer list and reset this allocator. Must + // Deallocate all segments to the free segment list and reset this allocator. Must // be called in a globally synchronized area. void drop_all(); size_t mem_size() const { return sizeof(*this) + - _segmented_array.num_buffers() * sizeof(G1CardSetBuffer) + _segmented_array.num_available_nodes() * _segmented_array.elem_size(); + _segmented_array.num_segments() * sizeof(G1CardSetSegment) + _segmented_array.num_available_slots() * + _segmented_array.slot_size(); } size_t wasted_mem_size() const { - return (_segmented_array.num_available_nodes() - (_segmented_array.num_allocated_nodes() - _num_pending_nodes)) * _segmented_array.elem_size(); + return (_segmented_array.num_available_slots() - (_segmented_array.num_allocated_slots() - _num_pending_slots)) * + _segmented_array.slot_size(); } - inline uint num_buffers() { return _segmented_array.num_buffers(); } + inline uint num_segments() { return _segmented_array.num_segments(); } void print(outputStream* os); }; +typedef G1SegmentedArrayFreePool G1CardSetFreePool; + class G1CardSetMemoryManager : public CHeapObj { G1CardSetConfiguration* _config; @@ -163,7 +167,7 @@ public: size_t mem_size() const; size_t wasted_mem_size() const; - G1CardSetMemoryStats memory_stats() const; + G1SegmentedArrayMemoryStats memory_stats() const; }; #endif // SHARE_GC_G1_G1CARDSETMEMORY_HPP diff --git a/src/hotspot/share/gc/g1/g1CardSetMemory.inline.hpp b/src/hotspot/share/gc/g1/g1CardSetMemory.inline.hpp index 0eaac226b593e62c07f187abb27ab92d19f05df2..21a509f449d82d5c73f4d7844881d2180b8a35a1 100644 --- a/src/hotspot/share/gc/g1/g1CardSetMemory.inline.hpp +++ b/src/hotspot/share/gc/g1/g1CardSetMemory.inline.hpp @@ -33,32 +33,32 @@ #include "gc/g1/g1CardSetContainers.inline.hpp" #include "utilities/globalCounter.inline.hpp" -template -G1CardSetContainer* volatile* G1CardSetAllocator::next_ptr(G1CardSetContainer& node) { - return node.next_addr(); +template +G1CardSetContainer* volatile* G1CardSetAllocator::next_ptr(G1CardSetContainer& slot) { + return slot.next_addr(); } -template -Elem* G1CardSetAllocator::allocate() { - assert(_segmented_array.elem_size() > 0, "instance size not set."); +template +Slot* G1CardSetAllocator::allocate() { + assert(_segmented_array.slot_size() > 0, "instance size not set."); - if (num_free_elems() > 0) { + if (num_free_slots() > 0) { // Pop under critical section to deal with ABA problem // Other solutions to the same problem are more complicated (ref counting, HP) GlobalCounter::CriticalSection cs(Thread::current()); - G1CardSetContainer* node = _free_nodes_list.pop(); - if (node != nullptr) { - Elem* elem = reinterpret_cast(reinterpret_cast(node)); - Atomic::sub(&_num_free_nodes, 1u); - guarantee(is_aligned(elem, 8), "result " PTR_FORMAT " not aligned", p2i(elem)); - return elem; + G1CardSetContainer* container = _free_slots_list.pop(); + if (container != nullptr) { + Slot* slot = reinterpret_cast(reinterpret_cast(container)); + Atomic::sub(&_num_free_slots, 1u); + guarantee(is_aligned(slot, 8), "result " PTR_FORMAT " not aligned", p2i(slot)); + return slot; } } - Elem* elem = _segmented_array.allocate(); - assert(elem != nullptr, "must be"); - return elem; + Slot* slot = _segmented_array.allocate(); + assert(slot != nullptr, "must be"); + return slot; } inline uint8_t* G1CardSetMemoryManager::allocate(uint type) { @@ -74,9 +74,9 @@ inline void G1CardSetMemoryManager::free_node(void* value) { free(0, value); } -template -inline uint G1CardSetAllocator::num_free_elems() const { - return Atomic::load(&_num_free_nodes); +template +inline uint G1CardSetAllocator::num_free_slots() const { + return Atomic::load(&_num_free_slots); } #endif // SHARE_GC_G1_G1CARDSETMEMORY_INLINE_HPP diff --git a/src/hotspot/share/gc/g1/g1CardTable.cpp b/src/hotspot/share/gc/g1/g1CardTable.cpp index 9e565c1ba64a6b9b26ae09a66053d768f5a74497..4fc6db5bac10ea92d42130abb5808015269bbe77 100644 --- a/src/hotspot/share/gc/g1/g1CardTable.cpp +++ b/src/hotspot/share/gc/g1/g1CardTable.cpp @@ -62,7 +62,7 @@ void G1CardTable::initialize(G1RegionToSpaceMapper* mapper) { _covered[0] = _whole_heap; _byte_map = (CardValue*) mapper->reserved().start(); - _byte_map_base = _byte_map - (uintptr_t(low_bound) >> card_shift); + _byte_map_base = _byte_map - (uintptr_t(low_bound) >> _card_shift); assert(byte_for(low_bound) == &_byte_map[0], "Checking start of map"); assert(byte_for(high_bound-1) <= &_byte_map[_last_valid_index], "Checking end of map"); diff --git a/src/hotspot/share/gc/g1/g1CardTable.hpp b/src/hotspot/share/gc/g1/g1CardTable.hpp index fd150db39f8dfa9102f8a9cd884cf1f7365aeb2c..e73cbfaf86d2f100374198b560ef619eada15465 100644 --- a/src/hotspot/share/gc/g1/g1CardTable.hpp +++ b/src/hotspot/share/gc/g1/g1CardTable.hpp @@ -110,12 +110,12 @@ public: inline uint region_idx_for(CardValue* p); static size_t compute_size(size_t mem_region_size_in_words) { - size_t number_of_slots = (mem_region_size_in_words / card_size_in_words); + size_t number_of_slots = (mem_region_size_in_words / _card_size_in_words); return ReservedSpace::allocation_align_size_up(number_of_slots); } // Returns how many bytes of the heap a single byte of the Card Table corresponds to. - static size_t heap_map_factor() { return card_size; } + static size_t heap_map_factor() { return _card_size; } void initialize() {} void initialize(G1RegionToSpaceMapper* mapper); diff --git a/src/hotspot/share/gc/g1/g1CardTable.inline.hpp b/src/hotspot/share/gc/g1/g1CardTable.inline.hpp index 41ffdf5318e30c1fb37b1ab162fc2cc6102d2737..d2962cbad845526fceb36755fce7f83f9042711b 100644 --- a/src/hotspot/share/gc/g1/g1CardTable.inline.hpp +++ b/src/hotspot/share/gc/g1/g1CardTable.inline.hpp @@ -31,7 +31,7 @@ inline uint G1CardTable::region_idx_for(CardValue* p) { size_t const card_idx = pointer_delta(p, _byte_map, sizeof(CardValue)); - return (uint)(card_idx >> (HeapRegion::LogOfHRGrainBytes - card_shift)); + return (uint)(card_idx >> (HeapRegion::LogOfHRGrainBytes - _card_shift)); } inline bool G1CardTable::mark_clean_as_dirty(CardValue* card) { diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index 86b92a6206f2f3ce5eb00779677afa41681c41a9..58f4a34d344ab4ed97d4f59dad7e19b686b685a5 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -33,7 +33,6 @@ #include "gc/g1/g1Arguments.hpp" #include "gc/g1/g1BarrierSet.hpp" #include "gc/g1/g1BatchedTask.hpp" -#include "gc/g1/g1CardSetFreeMemoryTask.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1CollectionSet.hpp" #include "gc/g1/g1CollectionSetCandidates.hpp" @@ -65,13 +64,14 @@ #include "gc/g1/g1RootClosures.hpp" #include "gc/g1/g1RootProcessor.hpp" #include "gc/g1/g1SATBMarkQueueSet.hpp" +#include "gc/g1/g1SegmentedArrayFreeMemoryTask.hpp" +#include "gc/g1/g1ServiceThread.hpp" #include "gc/g1/g1ThreadLocalData.hpp" #include "gc/g1/g1Trace.hpp" -#include "gc/g1/g1ServiceThread.hpp" #include "gc/g1/g1UncommitRegionTask.hpp" #include "gc/g1/g1VMOperations.hpp" -#include "gc/g1/g1YoungGCEvacFailureInjector.hpp" #include "gc/g1/g1YoungCollector.hpp" +#include "gc/g1/g1YoungGCEvacFailureInjector.hpp" #include "gc/g1/heapRegion.inline.hpp" #include "gc/g1/heapRegionRemSet.inline.hpp" #include "gc/g1/heapRegionSet.inline.hpp" @@ -87,17 +87,17 @@ #include "gc/shared/locationPrinter.inline.hpp" #include "gc/shared/oopStorageParState.hpp" #include "gc/shared/preservedMarks.inline.hpp" -#include "gc/shared/suspendibleThreadSet.hpp" #include "gc/shared/referenceProcessor.inline.hpp" -#include "gc/shared/taskTerminator.hpp" +#include "gc/shared/suspendibleThreadSet.hpp" #include "gc/shared/taskqueue.inline.hpp" +#include "gc/shared/taskTerminator.hpp" #include "gc/shared/tlab_globals.hpp" -#include "gc/shared/weakProcessor.inline.hpp" #include "gc/shared/workerPolicy.hpp" +#include "gc/shared/weakProcessor.inline.hpp" #include "logging/log.hpp" #include "memory/allocation.hpp" -#include "memory/iterator.hpp" #include "memory/heapInspection.hpp" +#include "memory/iterator.hpp" #include "memory/metaspaceUtils.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" @@ -1431,7 +1431,7 @@ G1CollectedHeap::G1CollectedHeap() : CollectedHeap(), _service_thread(NULL), _periodic_gc_task(NULL), - _free_card_set_memory_task(NULL), + _free_segmented_array_memory_task(NULL), _workers(NULL), _card_table(NULL), _collection_pause_end(Ticks::now()), @@ -1660,7 +1660,7 @@ jint G1CollectedHeap::initialize() { // The G1FromCardCache reserves card with value 0 as "invalid", so the heap must not // start within the first card. - guarantee((uintptr_t)(heap_rs.base()) >= G1CardTable::card_size, "Java heap must not start within the first card."); + guarantee((uintptr_t)(heap_rs.base()) >= G1CardTable::card_size(), "Java heap must not start within the first card."); G1FromCardCache::initialize(max_reserved_regions()); // Also create a G1 rem set. _rem_set = new G1RemSet(this, _card_table, _hot_card_cache); @@ -1723,8 +1723,8 @@ jint G1CollectedHeap::initialize() { _periodic_gc_task = new G1PeriodicGCTask("Periodic GC Task"); _service_thread->register_task(_periodic_gc_task); - _free_card_set_memory_task = new G1CardSetFreeMemoryTask("Card Set Free Memory Task"); - _service_thread->register_task(_free_card_set_memory_task); + _free_segmented_array_memory_task = new G1SegmentedArrayFreeMemoryTask("Card Set Free Memory Task"); + _service_thread->register_task(_free_segmented_array_memory_task); { G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set(); @@ -2616,8 +2616,8 @@ void G1CollectedHeap::gc_epilogue(bool full) { _collection_pause_end = Ticks::now(); - _free_card_set_memory_task->notify_new_stats(&_young_gen_card_set_stats, - &_collection_set_candidates_card_set_stats); + _free_segmented_array_memory_task->notify_new_stats(&_young_gen_card_set_stats, + &_collection_set_candidates_card_set_stats); } uint G1CollectedHeap::uncommit_regions(uint region_limit) { @@ -2941,11 +2941,11 @@ bool G1CollectedHeap::should_sample_collection_set_candidates() const { return candidates != NULL && candidates->num_remaining() > 0; } -void G1CollectedHeap::set_collection_set_candidates_stats(G1CardSetMemoryStats& stats) { +void G1CollectedHeap::set_collection_set_candidates_stats(G1SegmentedArrayMemoryStats& stats) { _collection_set_candidates_card_set_stats = stats; } -void G1CollectedHeap::set_young_gen_card_set_stats(const G1CardSetMemoryStats& stats) { +void G1CollectedHeap::set_young_gen_card_set_stats(const G1SegmentedArrayMemoryStats& stats) { _young_gen_card_set_stats = stats; } diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp index 8f86e4d7abe3cdfd8a73066faed90b44a4c0ef40..30ff5d19bec92854fc5a1efd4e7192506b06c577 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp @@ -27,7 +27,6 @@ #include "gc/g1/g1BarrierSet.hpp" #include "gc/g1/g1BiasedArray.hpp" -#include "gc/g1/g1CardSetFreeMemoryTask.hpp" #include "gc/g1/g1CardTable.hpp" #include "gc/g1/g1CollectionSet.hpp" #include "gc/g1/g1CollectorState.hpp" @@ -35,12 +34,13 @@ #include "gc/g1/g1EdenRegions.hpp" #include "gc/g1/g1EvacStats.hpp" #include "gc/g1/g1GCPauseType.hpp" +#include "gc/g1/g1HeapRegionAttr.hpp" #include "gc/g1/g1HeapTransition.hpp" #include "gc/g1/g1HeapVerifier.hpp" #include "gc/g1/g1HRPrinter.hpp" -#include "gc/g1/g1HeapRegionAttr.hpp" #include "gc/g1/g1MonitoringSupport.hpp" #include "gc/g1/g1NUMA.hpp" +#include "gc/g1/g1SegmentedArrayFreeMemoryTask.hpp" #include "gc/g1/g1SurvivorRegions.hpp" #include "gc/g1/g1YoungGCEvacFailureInjector.hpp" #include "gc/g1/heapRegionManager.hpp" @@ -143,7 +143,7 @@ class G1CollectedHeap : public CollectedHeap { private: G1ServiceThread* _service_thread; G1ServiceTask* _periodic_gc_task; - G1CardSetFreeMemoryTask* _free_card_set_memory_task; + G1SegmentedArrayFreeMemoryTask* _free_segmented_array_memory_task; WorkerThreads* _workers; G1CardTable* _card_table; @@ -160,9 +160,9 @@ private: HeapRegionSet _humongous_set; // Young gen memory statistics before GC. - G1CardSetMemoryStats _young_gen_card_set_stats; + G1SegmentedArrayMemoryStats _young_gen_card_set_stats; // Collection set candidates memory statistics after GC. - G1CardSetMemoryStats _collection_set_candidates_card_set_stats; + G1SegmentedArrayMemoryStats _collection_set_candidates_card_set_stats; // The block offset table for the G1 heap. G1BlockOffsetTable* _bot; @@ -259,8 +259,8 @@ public: void set_humongous_stats(uint num_humongous_total, uint num_humongous_candidates); bool should_sample_collection_set_candidates() const; - void set_collection_set_candidates_stats(G1CardSetMemoryStats& stats); - void set_young_gen_card_set_stats(const G1CardSetMemoryStats& stats); + void set_collection_set_candidates_stats(G1SegmentedArrayMemoryStats& stats); + void set_young_gen_card_set_stats(const G1SegmentedArrayMemoryStats& stats); private: diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp index dea7a858cba3649a61615273dbd255468e17531c..ece2ac0452adedf33b7e7580b2ae737613302062 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp @@ -770,7 +770,7 @@ public: double worker_cost() const override { // The work done per region is very small, therefore we choose this magic number to cap the number // of threads used when there are few regions. - const uint regions_per_thread = 1000; + const double regions_per_thread = 1000; return _claimer.n_regions() / regions_per_thread; } diff --git a/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp b/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp index 7d8076f3cf3c6d80e8d3304de25f4caf86b67acb..3393d3b601242cb41e943b7d6814c07c3cc658ff 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -250,14 +250,21 @@ static size_t calc_min_yellow_zone_size() { } } +// An initial guess at the rate for pause-time card refinement for one +// thread, used when computing the default initial green zone value. +const double InitialPauseTimeCardRefinementRate = 200.0; + static size_t calc_init_green_zone() { - size_t green = G1ConcRefinementGreenZone; - const char* name = "G1ConcRefinementGreenZone"; + size_t green; if (FLAG_IS_DEFAULT(G1ConcRefinementGreenZone)) { - green = ParallelGCThreads; - name = "ParallelGCThreads"; + const double rate = InitialPauseTimeCardRefinementRate * ParallelGCThreads; + // The time budget for pause-time card refinement. + const double ms = MaxGCPauseMillis * (G1RSetUpdatingPauseTimePercent / 100.0); + green = rate * ms; + } else { + green = configuration_buffers_to_cards(G1ConcRefinementGreenZone, + "G1ConcRefinementGreenZone"); } - green = configuration_buffers_to_cards(green, name); return MIN2(green, max_green_zone); } diff --git a/src/hotspot/share/gc/g1/g1ConcurrentRefineStats.cpp b/src/hotspot/share/gc/g1/g1ConcurrentRefineStats.cpp index 055fd8b891df2e72dec66d3ed290cb786a5b06c5..3e8f83326b2708bc6252f5d9bd3cc4324cde4016 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentRefineStats.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentRefineStats.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,12 @@ G1ConcurrentRefineStats::G1ConcurrentRefineStats() : _dirtied_cards(0) {} +double G1ConcurrentRefineStats::refinement_rate_ms() const { + // Report 0 when no time recorded because no refinement performed. + double secs = refinement_time().seconds(); + return (secs > 0) ? (refined_cards() / (secs * MILLIUNITS)) : 0.0; +} + G1ConcurrentRefineStats& G1ConcurrentRefineStats::operator+=(const G1ConcurrentRefineStats& other) { _refinement_time += other._refinement_time; diff --git a/src/hotspot/share/gc/g1/g1ConcurrentRefineStats.hpp b/src/hotspot/share/gc/g1/g1ConcurrentRefineStats.hpp index d0e17301a5fa06fc7cc8784a2594a78b265e5bdf..ae576778a070243d3de0f1345b1e456319f85d73 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentRefineStats.hpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentRefineStats.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,6 +47,9 @@ public: // Number of refined cards. size_t refined_cards() const { return _refined_cards; } + // Refinement rate, in cards per ms. + double refinement_rate_ms() const; + // Number of cards for which refinement was skipped because some other // thread had already refined them. size_t precleaned_cards() const { return _precleaned_cards; } diff --git a/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.cpp b/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.cpp index e57617114d26761ec82d29040fa949c8fe8923f9..45defd5e713059694638c7fb4af21963ef3b7b43 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -104,10 +104,6 @@ void G1ConcurrentRefineThread::run_service() { break; } - log_debug(gc, refine)("Activated worker %d, on threshold: " SIZE_FORMAT ", current: " SIZE_FORMAT, - _worker_id, _cr->activation_threshold(_worker_id), - G1BarrierSet::dirty_card_queue_set().num_cards()); - // For logging. G1ConcurrentRefineStats start_stats = *_refinement_stats; G1ConcurrentRefineStats total_stats; // Accumulate over activation. @@ -115,6 +111,10 @@ void G1ConcurrentRefineThread::run_service() { { SuspendibleThreadSetJoiner sts_join; + log_debug(gc, refine)("Activated worker %d, on threshold: %zu, current: %zu", + _worker_id, _cr->activation_threshold(_worker_id), + G1BarrierSet::dirty_card_queue_set().num_cards()); + while (!should_terminate()) { if (sts_join.should_yield()) { // Accumulate changed stats before possible GC that resets stats. @@ -131,12 +131,12 @@ void G1ConcurrentRefineThread::run_service() { } total_stats += *_refinement_stats - start_stats; - log_debug(gc, refine)("Deactivated worker %d, off threshold: " SIZE_FORMAT - ", current: " SIZE_FORMAT - ", refined cards: " SIZE_FORMAT, + log_debug(gc, refine)("Deactivated worker %d, off threshold: %zu, " + "cards: %zu, refined %zu, rate %1.2fc/ms", _worker_id, _cr->deactivation_threshold(_worker_id), G1BarrierSet::dirty_card_queue_set().num_cards(), - total_stats.refined_cards()); + total_stats.refined_cards(), + total_stats.refinement_rate_ms()); if (os::supports_vtime()) { _vtime_accum = (os::elapsedVTime() - _vtime_start); diff --git a/src/hotspot/share/gc/g1/g1EvacFailureObjectsSet.cpp b/src/hotspot/share/gc/g1/g1EvacFailureObjectsSet.cpp index deabc897ed86371df948b6519d1e0aebf63c3e94..a15f8965bcbd1a25c541b218ad5421a96073a20b 100644 --- a/src/hotspot/share/gc/g1/g1EvacFailureObjectsSet.cpp +++ b/src/hotspot/share/gc/g1/g1EvacFailureObjectsSet.cpp @@ -31,9 +31,9 @@ const G1SegmentedArrayAllocOptions G1EvacFailureObjectsSet::_alloc_options = - G1SegmentedArrayAllocOptions((uint)sizeof(OffsetInRegion), BufferLength, UINT_MAX, Alignment); + G1SegmentedArrayAllocOptions((uint)sizeof(OffsetInRegion), SegmentLength, UINT_MAX, Alignment); -G1SegmentedArrayBufferList G1EvacFailureObjectsSet::_free_buffer_list; +G1SegmentedArrayFreeList G1EvacFailureObjectsSet::_free_segment_list; #ifdef ASSERT void G1EvacFailureObjectsSet::assert_is_valid_offset(size_t offset) const { @@ -57,7 +57,7 @@ G1EvacFailureObjectsSet::OffsetInRegion G1EvacFailureObjectsSet::to_offset(oop o G1EvacFailureObjectsSet::G1EvacFailureObjectsSet(uint region_idx, HeapWord* bottom) : DEBUG_ONLY(_region_idx(region_idx) COMMA) _bottom(bottom), - _offsets(&_alloc_options, &_free_buffer_list) { + _offsets(&_alloc_options, &_free_segment_list) { assert(HeapRegion::LogOfHRGrainBytes < 32, "must be"); } @@ -76,7 +76,7 @@ class G1EvacFailureObjectsIterationHelper { } void join_and_sort() { - _segments->iterate_nodes(*this); + _segments->iterate_segments(*this); QuickSort::sort(_offset_array, _array_length, order_oop, true); } @@ -96,7 +96,7 @@ public: _array_length(0) { } void process_and_drop(ObjectClosure* closure) { - uint num = _segments->num_allocated_nodes(); + uint num = _segments->num_allocated_slots(); _offset_array = NEW_C_HEAP_ARRAY(OffsetInRegion, num, mtGC); join_and_sort(); @@ -106,9 +106,9 @@ public: FREE_C_HEAP_ARRAY(OffsetInRegion, _offset_array); } - // Callback of G1SegmentedArray::iterate_nodes - void do_buffer(G1SegmentedArrayBuffer* node, uint length) { - node->copy_to(&_offset_array[_array_length]); + // Callback of G1SegmentedArray::iterate_segments + void do_segment(G1SegmentedArraySegment* segment, uint length) { + segment->copy_to(&_offset_array[_array_length]); _array_length += length; } }; diff --git a/src/hotspot/share/gc/g1/g1EvacFailureObjectsSet.hpp b/src/hotspot/share/gc/g1/g1EvacFailureObjectsSet.hpp index c8ec317f351ae60b1659924adab1b81365c114b0..a2628807ee1c921956e49184e0cd545d9237c567 100644 --- a/src/hotspot/share/gc/g1/g1EvacFailureObjectsSet.hpp +++ b/src/hotspot/share/gc/g1/g1EvacFailureObjectsSet.hpp @@ -33,7 +33,7 @@ class G1EvacFailureObjectsIterationHelper; // This class collects addresses of objects that failed evacuation in a specific // heap region. -// Provides sorted iteration of these elements for processing during the remove +// Provides sorted iteration of these objects for processing during the remove // self forwards phase. class G1EvacFailureObjectsSet { friend class G1EvacFailureObjectsIterationHelper; @@ -45,13 +45,13 @@ public: typedef uint OffsetInRegion; private: - static const uint BufferLength = 256; + static const uint SegmentLength = 256; static const uint Alignment = 4; static const G1SegmentedArrayAllocOptions _alloc_options; // This free list is shared among evacuation failure process in all regions. - static G1SegmentedArrayBufferList _free_buffer_list; + static G1SegmentedArrayFreeList _free_segment_list; DEBUG_ONLY(const uint _region_idx;) diff --git a/src/hotspot/share/gc/g1/g1GCParPhaseTimesTracker.hpp b/src/hotspot/share/gc/g1/g1GCParPhaseTimesTracker.hpp index 11a62b03825ee34b9e724287836d95ad6028a514..af626e99fd413566e70c5715b730e6e1842e6017 100644 --- a/src/hotspot/share/gc/g1/g1GCParPhaseTimesTracker.hpp +++ b/src/hotspot/share/gc/g1/g1GCParPhaseTimesTracker.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,10 +36,10 @@ protected: G1GCPhaseTimes* _phase_times; uint _worker_id; EventGCPhaseParallel _event; - bool _must_record; + bool _allow_multiple_record; public: - G1GCParPhaseTimesTracker(G1GCPhaseTimes* phase_times, G1GCPhaseTimes::GCParPhases phase, uint worker_id, bool must_record = true); + G1GCParPhaseTimesTracker(G1GCPhaseTimes* phase_times, G1GCPhaseTimes::GCParPhases phase, uint worker_id, bool allow_multiple_record = false); virtual ~G1GCParPhaseTimesTracker(); }; diff --git a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp index c77dd7196f5409022cc902bb4024496be489484a..3495c22f84135fd760d959af88279e3d33800d00 100644 --- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp +++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp @@ -116,10 +116,12 @@ G1GCPhaseTimes::G1GCPhaseTimes(STWGCTimer* gc_timer, uint max_gc_threads) : _gc_par_phases[ScanHR]->create_thread_work_items("Scanned Cards:", ScanHRScannedCards); _gc_par_phases[ScanHR]->create_thread_work_items("Scanned Blocks:", ScanHRScannedBlocks); _gc_par_phases[ScanHR]->create_thread_work_items("Claimed Chunks:", ScanHRClaimedChunks); + _gc_par_phases[ScanHR]->create_thread_work_items("Found Roots:", ScanHRFoundRoots); _gc_par_phases[OptScanHR]->create_thread_work_items("Scanned Cards:", ScanHRScannedCards); _gc_par_phases[OptScanHR]->create_thread_work_items("Scanned Blocks:", ScanHRScannedBlocks); _gc_par_phases[OptScanHR]->create_thread_work_items("Claimed Chunks:", ScanHRClaimedChunks); + _gc_par_phases[OptScanHR]->create_thread_work_items("Found Roots:", ScanHRFoundRoots); _gc_par_phases[OptScanHR]->create_thread_work_items("Scanned Refs:", ScanHRScannedOptRefs); _gc_par_phases[OptScanHR]->create_thread_work_items("Used Memory:", ScanHRUsedMemory); @@ -264,11 +266,7 @@ void G1GCPhaseTimes::add_time_secs(GCParPhases phase, uint worker_id, double sec } void G1GCPhaseTimes::record_or_add_time_secs(GCParPhases phase, uint worker_id, double secs) { - if (_gc_par_phases[phase]->get(worker_id) == _gc_par_phases[phase]->uninitialized()) { - record_time_secs(phase, worker_id, secs); - } else { - add_time_secs(phase, worker_id, secs); - } + _gc_par_phases[phase]->set_or_add(worker_id, secs); } double G1GCPhaseTimes::get_time_secs(GCParPhases phase, uint worker_id) { @@ -576,8 +574,8 @@ void G1EvacPhaseWithTrimTimeTracker::stop() { _stopped = true; } -G1GCParPhaseTimesTracker::G1GCParPhaseTimesTracker(G1GCPhaseTimes* phase_times, G1GCPhaseTimes::GCParPhases phase, uint worker_id, bool must_record) : - _start_time(), _phase(phase), _phase_times(phase_times), _worker_id(worker_id), _event(), _must_record(must_record) { +G1GCParPhaseTimesTracker::G1GCParPhaseTimesTracker(G1GCPhaseTimes* phase_times, G1GCPhaseTimes::GCParPhases phase, uint worker_id, bool allow_multiple_record) : + _start_time(), _phase(phase), _phase_times(phase_times), _worker_id(worker_id), _event(), _allow_multiple_record(allow_multiple_record) { if (_phase_times != NULL) { _start_time = Ticks::now(); } @@ -585,10 +583,10 @@ G1GCParPhaseTimesTracker::G1GCParPhaseTimesTracker(G1GCPhaseTimes* phase_times, G1GCParPhaseTimesTracker::~G1GCParPhaseTimesTracker() { if (_phase_times != NULL) { - if (_must_record) { - _phase_times->record_time_secs(_phase, _worker_id, (Ticks::now() - _start_time).seconds()); - } else { + if (_allow_multiple_record) { _phase_times->record_or_add_time_secs(_phase, _worker_id, (Ticks::now() - _start_time).seconds()); + } else { + _phase_times->record_time_secs(_phase, _worker_id, (Ticks::now() - _start_time).seconds()); } _event.commit(GCId::current(), _worker_id, G1GCPhaseTimes::phase_name(_phase)); } diff --git a/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp b/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp index 255aab6f96ee98b6501cff361023a02701dac303..9db7f18dd347469be15aacad9b0e47fac1fbdb65 100644 --- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp +++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp @@ -123,6 +123,7 @@ class G1GCPhaseTimes : public CHeapObj { ScanHRScannedCards, ScanHRScannedBlocks, ScanHRClaimedChunks, + ScanHRFoundRoots, ScanHRScannedOptRefs, ScanHRUsedMemory }; diff --git a/src/hotspot/share/gc/g1/g1OopClosures.hpp b/src/hotspot/share/gc/g1/g1OopClosures.hpp index 9f0c4a23a55d4299863d0e899515481ac52dfe54..0dbaabbf6396de6ad1895cad77a63b1c29306e2d 100644 --- a/src/hotspot/share/gc/g1/g1OopClosures.hpp +++ b/src/hotspot/share/gc/g1/g1OopClosures.hpp @@ -61,10 +61,12 @@ public: // Used to scan cards from the DCQS or the remembered sets during garbage collection. class G1ScanCardClosure : public G1ScanClosureBase { + size_t& _heap_roots_found; public: G1ScanCardClosure(G1CollectedHeap* g1h, - G1ParScanThreadState* pss) : - G1ScanClosureBase(g1h, pss) { } + G1ParScanThreadState* pss, + size_t& heap_roots_found) : + G1ScanClosureBase(g1h, pss), _heap_roots_found(heap_roots_found) { } template void do_oop_work(T* p); virtual void do_oop(narrowOop* p) { do_oop_work(p); } diff --git a/src/hotspot/share/gc/g1/g1OopClosures.inline.hpp b/src/hotspot/share/gc/g1/g1OopClosures.inline.hpp index ac8c370bfd082720419efc55a2d60c3c0b115379..2cd41d4255f2df5edba66b269bc37849e417281a 100644 --- a/src/hotspot/share/gc/g1/g1OopClosures.inline.hpp +++ b/src/hotspot/share/gc/g1/g1OopClosures.inline.hpp @@ -180,6 +180,7 @@ inline void G1ScanCardClosure::do_oop_work(T* p) { // Since the source is always from outside the collection set, here we implicitly know // that this is a cross-region reference too. prefetch_and_push(p, obj); + _heap_roots_found++; } else if (!HeapRegion::is_in_same_region(p, obj)) { handle_non_cset_obj_common(region_attr, p, obj); _par_scan_state->enqueue_card_if_tracked(region_attr, p, obj); diff --git a/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp b/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp index a8ffaa20ed509bcd096e84471a7318784b3ed914..da24578f9df691178f521522b5a031c1bab24b23 100644 --- a/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp +++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp @@ -421,8 +421,8 @@ HeapWord* G1ParScanThreadState::allocate_copy_slow(G1HeapRegionAttr* dest_attr, } #if EVAC_FAILURE_INJECTOR -bool G1ParScanThreadState::inject_evacuation_failure() { - return _g1h->evac_failure_injector()->evacuation_should_fail(_evac_failure_inject_counter); +bool G1ParScanThreadState::inject_evacuation_failure(uint region_idx) { + return _g1h->evac_failure_injector()->evacuation_should_fail(_evac_failure_inject_counter, region_idx); } #endif @@ -470,7 +470,7 @@ oop G1ParScanThreadState::do_copy_to_survivor_space(G1HeapRegionAttr const regio assert(_g1h->is_in_reserved(obj_ptr), "Allocated memory should be in the heap"); // Should this evacuation fail? - if (inject_evacuation_failure()) { + if (inject_evacuation_failure(from_region->hrm_index())) { // Doing this after all the allocation attempts also tests the // undo_allocation() method too. undo_allocation(dest_attr, obj_ptr, word_sz, node_index); @@ -482,6 +482,10 @@ oop G1ParScanThreadState::do_copy_to_survivor_space(G1HeapRegionAttr const regio Copy::aligned_disjoint_words(cast_from_oop(old), obj_ptr, word_sz); const oop obj = cast_to_oop(obj_ptr); + // Because the forwarding is done with memory_order_relaxed there is no + // ordering with the above copy. Clients that get the forwardee must not + // examine its contents without other synchronization, since the contents + // may not be up to date for them. const oop forward_ptr = old->forward_to_atomic(obj, old_mark, memory_order_relaxed); if (forward_ptr == NULL) { diff --git a/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp b/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp index 478b8745731cadaf1562fe7091ddd2221468b6e2..f40ca519268fb4f477cbfc9d00972af9f8dfee67 100644 --- a/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp +++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp @@ -107,7 +107,7 @@ class G1ParScanThreadState : public CHeapObj { EvacuationFailedInfo _evacuation_failed_info; G1EvacFailureRegions* _evac_failure_regions; - bool inject_evacuation_failure() EVAC_FAILURE_INJECTOR_RETURN_( return false; ); + bool inject_evacuation_failure(uint region_idx) EVAC_FAILURE_INJECTOR_RETURN_( return false; ); public: G1ParScanThreadState(G1CollectedHeap* g1h, diff --git a/src/hotspot/share/gc/g1/g1ParScanThreadState.inline.hpp b/src/hotspot/share/gc/g1/g1ParScanThreadState.inline.hpp index 46651307bc1c6b160ebcf5db65939abab7f9202b..c37f0f38e51c8cf749510fad0d5798a106ee3b54 100644 --- a/src/hotspot/share/gc/g1/g1ParScanThreadState.inline.hpp +++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.inline.hpp @@ -111,9 +111,9 @@ template void G1ParScanThreadState::write_ref_field_post(T* p, oop obj // References to the current collection set are references to objects that failed // evacuation. Currently these regions are always relabelled as old without // remembered sets, so skip them. - assert(dest_attr.is_in_cset() == (obj->is_forwarded() && obj->forwardee() == obj), - "Only evac-failed objects must be in the collection set here but " PTR_FORMAT " is not", p2i(obj)); if (dest_attr.is_in_cset()) { + assert(obj->is_forwarded(), "evac-failed but not forwarded: " PTR_FORMAT, p2i(obj)); + assert(obj->forwardee() == obj, "evac-failed but not self-forwarded: " PTR_FORMAT, p2i(obj)); return; } enqueue_card_if_tracked(dest_attr, p, obj); diff --git a/src/hotspot/share/gc/g1/g1RemSet.cpp b/src/hotspot/share/gc/g1/g1RemSet.cpp index b689e6497625564f9e1d0d3f8eda2a221fc0e6fa..26bb89f2dbbaed2ce19c35a8ab73c24f2cee85da 100644 --- a/src/hotspot/share/gc/g1/g1RemSet.cpp +++ b/src/hotspot/share/gc/g1/g1RemSet.cpp @@ -774,6 +774,7 @@ class G1ScanHRForRegionClosure : public HeapRegionClosure { size_t _cards_scanned; size_t _blocks_scanned; size_t _chunks_claimed; + size_t _heap_roots_found; Tickspan _rem_set_root_scan_time; Tickspan _rem_set_trim_partially_time; @@ -785,7 +786,7 @@ class G1ScanHRForRegionClosure : public HeapRegionClosure { HeapWord* scan_memregion(uint region_idx_for_card, MemRegion mr) { HeapRegion* const card_region = _g1h->region_at(region_idx_for_card); - G1ScanCardClosure card_cl(_g1h, _pss); + G1ScanCardClosure card_cl(_g1h, _pss, _heap_roots_found); HeapWord* const scanned_to = card_region->oops_on_memregion_seq_iterate_careful(mr, &card_cl); assert(scanned_to != NULL, "Should be able to scan range"); @@ -807,7 +808,7 @@ class G1ScanHRForRegionClosure : public HeapRegionClosure { return; } - HeapWord* scan_end = MIN2(card_start + (num_cards << BOTConstants::LogN_words), top); + HeapWord* scan_end = MIN2(card_start + (num_cards << BOTConstants::log_card_size_in_words()), top); if (_scanned_to >= scan_end) { return; } @@ -880,6 +881,7 @@ public: _cards_scanned(0), _blocks_scanned(0), _chunks_claimed(0), + _heap_roots_found(0), _rem_set_root_scan_time(), _rem_set_trim_partially_time(), _scanned_to(NULL), @@ -906,6 +908,7 @@ public: size_t cards_scanned() const { return _cards_scanned; } size_t blocks_scanned() const { return _blocks_scanned; } size_t chunks_claimed() const { return _chunks_claimed; } + size_t heap_roots_found() const { return _heap_roots_found; } }; void G1RemSet::scan_heap_roots(G1ParScanThreadState* pss, @@ -924,6 +927,7 @@ void G1RemSet::scan_heap_roots(G1ParScanThreadState* pss, p->record_or_add_thread_work_item(scan_phase, worker_id, cl.cards_scanned(), G1GCPhaseTimes::ScanHRScannedCards); p->record_or_add_thread_work_item(scan_phase, worker_id, cl.blocks_scanned(), G1GCPhaseTimes::ScanHRScannedBlocks); p->record_or_add_thread_work_item(scan_phase, worker_id, cl.chunks_claimed(), G1GCPhaseTimes::ScanHRClaimedChunks); + p->record_or_add_thread_work_item(scan_phase, worker_id, cl.heap_roots_found(), G1GCPhaseTimes::ScanHRFoundRoots); } // Heap region closure to be applied to all regions in the current collection set @@ -937,6 +941,7 @@ class G1ScanCollectionSetRegionClosure : public HeapRegionClosure { uint _worker_id; + size_t _opt_roots_scanned; size_t _opt_refs_scanned; size_t _opt_refs_memory_used; @@ -951,7 +956,7 @@ class G1ScanCollectionSetRegionClosure : public HeapRegionClosure { G1OopStarChunkedList* opt_rem_set_list = _pss->oops_into_optional_region(r); - G1ScanCardClosure scan_cl(G1CollectedHeap::heap(), _pss); + G1ScanCardClosure scan_cl(G1CollectedHeap::heap(), _pss, _opt_roots_scanned); G1ScanRSForOptionalClosure cl(G1CollectedHeap::heap(), &scan_cl); _opt_refs_scanned += opt_rem_set_list->oops_do(&cl, _pss->closures()->strong_oops()); _opt_refs_memory_used += opt_rem_set_list->used_memory(); @@ -970,6 +975,7 @@ public: _scan_phase(scan_phase), _code_roots_phase(code_roots_phase), _worker_id(worker_id), + _opt_roots_scanned(0), _opt_refs_scanned(0), _opt_refs_memory_used(0), _strong_code_root_scan_time(), @@ -1006,6 +1012,7 @@ public: Tickspan rem_set_opt_root_scan_time() const { return _rem_set_opt_root_scan_time; } Tickspan rem_set_opt_trim_partially_time() const { return _rem_set_opt_trim_partially_time; } + size_t opt_roots_scanned() const { return _opt_roots_scanned; } size_t opt_refs_scanned() const { return _opt_refs_scanned; } size_t opt_refs_memory_used() const { return _opt_refs_memory_used; } }; @@ -1028,6 +1035,7 @@ void G1RemSet::scan_collection_set_regions(G1ParScanThreadState* pss, // At this time we record some metrics only for the evacuations after the initial one. if (scan_phase == G1GCPhaseTimes::OptScanHR) { + p->record_or_add_thread_work_item(scan_phase, worker_id, cl.opt_roots_scanned(), G1GCPhaseTimes::ScanHRFoundRoots); p->record_or_add_thread_work_item(scan_phase, worker_id, cl.opt_refs_scanned(), G1GCPhaseTimes::ScanHRScannedOptRefs); p->record_or_add_thread_work_item(scan_phase, worker_id, cl.opt_refs_memory_used(), G1GCPhaseTimes::ScanHRUsedMemory); } @@ -1415,7 +1423,7 @@ public: // Merge remembered sets of current candidates. { - G1GCParPhaseTimesTracker x(p, merge_remset_phase, worker_id, _initial_evacuation /* must_record */); + G1GCParPhaseTimesTracker x(p, merge_remset_phase, worker_id, !_initial_evacuation /* allow_multiple_record */); G1MergeCardSetStats stats; { G1MergeCardSetClosure cl(_scan_state); @@ -1666,7 +1674,7 @@ void G1RemSet::refine_card_concurrently(CardValue* const card_ptr, // Don't use addr_for(card_ptr + 1) which can ask for // a card beyond the heap. - HeapWord* end = start + G1CardTable::card_size_in_words; + HeapWord* end = start + G1CardTable::card_size_in_words(); MemRegion dirty_region(start, MIN2(scan_limit, end)); assert(!dirty_region.is_empty(), "sanity"); diff --git a/src/hotspot/share/gc/g1/g1RemSetSummary.cpp b/src/hotspot/share/gc/g1/g1RemSetSummary.cpp index 473166ad5db699bac8159ee1fc4c3bc8dc1b6bd8..cae7df6f90285a03474d8812566bc227abebdad8 100644 --- a/src/hotspot/share/gc/g1/g1RemSetSummary.cpp +++ b/src/hotspot/share/gc/g1/g1RemSetSummary.cpp @@ -319,7 +319,7 @@ public: } out->print_cr(" Region with largest amount of code roots = " HR_FORMAT ", " - "size = " SIZE_FORMAT "%s, num_elems = " SIZE_FORMAT ".", + "size = " SIZE_FORMAT "%s, num_slots = " SIZE_FORMAT ".", HR_FORMAT_PARAMS(max_code_root_mem_sz_region()), byte_size_in_proper_unit(max_code_root_rem_set->strong_code_roots_mem_size()), proper_unit_for_byte_size(max_code_root_rem_set->strong_code_roots_mem_size()), diff --git a/src/hotspot/share/gc/g1/g1SegmentedArray.hpp b/src/hotspot/share/gc/g1/g1SegmentedArray.hpp index b1522ae68c1430d9c3cf9d01b6346c3de25edc52..8091b6b2c8b4206eaeee9f5fdf3c489e8610eb9b 100644 --- a/src/hotspot/share/gc/g1/g1SegmentedArray.hpp +++ b/src/hotspot/share/gc/g1/g1SegmentedArray.hpp @@ -29,147 +29,147 @@ #include "memory/allocation.hpp" #include "utilities/lockFreeStack.hpp" -// A single buffer/arena containing _num_elems blocks of memory of _elem_size. -// G1SegmentedArrayBuffers can be linked together using a singly linked list. +// A single segment/arena containing _num_slots blocks of memory of _slot_size. +// G1SegmentedArraySegments can be linked together using a singly linked list. template -class G1SegmentedArrayBuffer : public CHeapObj { - const uint _elem_size; - const uint _num_elems; +class G1SegmentedArraySegment : public CHeapObj { + const uint _slot_size; + const uint _num_slots; - G1SegmentedArrayBuffer* volatile _next; + G1SegmentedArraySegment* volatile _next; - char* _buffer; // Actual data. + char* _segment; // Actual data. - // Index into the next free block to allocate into. Full if equal (or larger) - // to _num_elems (can be larger because we atomically increment this value and + // Index into the next free slot to allocate into. Full if equal (or larger) + // to _num_slots (can be larger because we atomically increment this value and // check only afterwards if the allocation has been successful). uint volatile _next_allocate; public: - G1SegmentedArrayBuffer(uint elem_size, uint num_elems, G1SegmentedArrayBuffer* next); - ~G1SegmentedArrayBuffer(); + G1SegmentedArraySegment(uint slot_size, uint num_slots, G1SegmentedArraySegment* next); + ~G1SegmentedArraySegment(); - G1SegmentedArrayBuffer* volatile* next_addr() { return &_next; } + G1SegmentedArraySegment* volatile* next_addr() { return &_next; } - void* get_new_buffer_elem(); + void* get_new_slot(); - uint num_elems() const { return _num_elems; } + uint num_slots() const { return _num_slots; } - G1SegmentedArrayBuffer* next() const { return _next; } + G1SegmentedArraySegment* next() const { return _next; } - void set_next(G1SegmentedArrayBuffer* next) { + void set_next(G1SegmentedArraySegment* next) { assert(next != this, " loop condition"); _next = next; } - void reset(G1SegmentedArrayBuffer* next) { + void reset(G1SegmentedArraySegment* next) { _next_allocate = 0; assert(next != this, " loop condition"); set_next(next); - memset((void*)_buffer, 0, (size_t)_num_elems * _elem_size); + memset((void*)_segment, 0, (size_t)_num_slots * _slot_size); } - uint elem_size() const { return _elem_size; } + uint slot_size() const { return _slot_size; } - size_t mem_size() const { return sizeof(*this) + (size_t)_num_elems * _elem_size; } + size_t mem_size() const { return sizeof(*this) + (size_t)_num_slots * _slot_size; } uint length() const { - // _next_allocate might grow larger than _num_elems in multi-thread environments + // _next_allocate might grow larger than _num_slots in multi-thread environments // due to races. - return MIN2(_next_allocate, _num_elems); + return MIN2(_next_allocate, _num_slots); } - // Copies the (valid) contents of this buffer into the destination. + // Copies the (valid) contents of this segment into the destination. void copy_to(void* dest) const { - ::memcpy(dest, _buffer, length() * _elem_size); + ::memcpy(dest, _segment, length() * _slot_size); } - bool is_full() const { return _next_allocate >= _num_elems; } + bool is_full() const { return _next_allocate >= _num_slots; } }; -// Set of (free) G1SegmentedArrayBuffers. The assumed usage is that allocation -// to it and removal of elements is strictly separate, but every action may be +// Set of (free) G1SegmentedArraySegments. The assumed usage is that allocation +// to it and removal of segments is strictly separate, but every action may be // performed by multiple threads at the same time. // Counts and memory usage are current on a best-effort basis if accessed concurrently. template -class G1SegmentedArrayBufferList { - static G1SegmentedArrayBuffer* volatile* next_ptr(G1SegmentedArrayBuffer& node) { - return node.next_addr(); +class G1SegmentedArrayFreeList { + static G1SegmentedArraySegment* volatile* next_ptr(G1SegmentedArraySegment& segment) { + return segment.next_addr(); } - typedef LockFreeStack, &G1SegmentedArrayBufferList::next_ptr> NodeStack; + typedef LockFreeStack, &G1SegmentedArrayFreeList::next_ptr> SegmentStack; - NodeStack _list; + SegmentStack _list; - volatile size_t _num_buffers; + volatile size_t _num_segments; volatile size_t _mem_size; public: - G1SegmentedArrayBufferList() : _list(), _num_buffers(0), _mem_size(0) { } - ~G1SegmentedArrayBufferList() { free_all(); } + G1SegmentedArrayFreeList() : _list(), _num_segments(0), _mem_size(0) { } + ~G1SegmentedArrayFreeList() { free_all(); } - void bulk_add(G1SegmentedArrayBuffer& first, G1SegmentedArrayBuffer& last, size_t num, size_t mem_size); + void bulk_add(G1SegmentedArraySegment& first, G1SegmentedArraySegment& last, size_t num, size_t mem_size); - G1SegmentedArrayBuffer* get(); - G1SegmentedArrayBuffer* get_all(size_t& num_buffers, size_t& mem_size); + G1SegmentedArraySegment* get(); + G1SegmentedArraySegment* get_all(size_t& num_segments, size_t& mem_size); // Give back all memory to the OS. void free_all(); void print_on(outputStream* out, const char* prefix = ""); - size_t num_buffers() const { return Atomic::load(&_num_buffers); } + size_t num_segments() const { return Atomic::load(&_num_segments); } size_t mem_size() const { return Atomic::load(&_mem_size); } }; -// Configuration for G1SegmentedArray, e.g element size, element number of next G1SegmentedArrayBuffer. +// Configuration for G1SegmentedArray, e.g slot size, slot number of next G1SegmentedArraySegment. class G1SegmentedArrayAllocOptions { protected: - const uint _elem_size; - const uint _initial_num_elems; - // Defines a limit to the number of elements in the buffer - const uint _max_num_elems; - const uint _alignment; + const uint _slot_size; + const uint _initial_num_slots; + // Defines a limit to the number of slots in the segment + const uint _max_num_slots; + const uint _slot_alignment; public: - G1SegmentedArrayAllocOptions(uint elem_size, uint initial_num_elems, uint max_num_elems, uint alignment) : - _elem_size(elem_size), - _initial_num_elems(initial_num_elems), - _max_num_elems(max_num_elems), - _alignment(alignment) { - assert(_elem_size > 0, "Must be"); - assert(_initial_num_elems > 0, "Must be"); - assert(_max_num_elems > 0, "Must be"); - assert(_alignment > 0, "Must be"); + G1SegmentedArrayAllocOptions(uint slot_size, uint initial_num_slots, uint max_num_slots, uint alignment) : + _slot_size(slot_size), + _initial_num_slots(initial_num_slots), + _max_num_slots(max_num_slots), + _slot_alignment(alignment) { + assert(_slot_size > 0, "Must be"); + assert(_initial_num_slots > 0, "Must be"); + assert(_max_num_slots > 0, "Must be"); + assert(_slot_alignment > 0, "Must be"); } - virtual uint next_num_elems(uint prev_num_elems) const { - return _initial_num_elems; + virtual uint next_num_slots(uint prev_num_slots) const { + return _initial_num_slots; } - uint elem_size() const { return _elem_size; } + uint slot_size() const { return _slot_size; } - uint alignment() const { return _alignment; } + uint slot_alignment() const { return _slot_alignment; } }; -// A segmented array where G1SegmentedArrayBuffer is the segment, and -// G1SegmentedArrayBufferList is the free list to cache G1SegmentedArrayBuffer, +// A segmented array where G1SegmentedArraySegment is the segment, and +// G1SegmentedArrayFreeList is the free list to cache G1SegmentedArraySegments, // and G1SegmentedArrayAllocOptions is the configuration for G1SegmentedArray // attributes. // // Implementation details as below: // -// Arena-like allocator for (card set, or ...) heap memory objects (Elem elements). +// Arena-like allocator for (card set, or ...) heap memory objects (Slot slots). // -// Actual allocation from the C heap occurs on G1SegmentedArrayBuffer basis, i.e. segments -// of elements. The assumed allocation pattern for these G1SegmentedArrayBuffer elements +// Actual allocation from the C heap occurs on G1SegmentedArraySegment basis, i.e. segments +// of slots. The assumed allocation pattern for these G1SegmentedArraySegment slots // is assumed to be strictly two-phased: // -// - in the first phase, G1SegmentedArrayBuffers are allocated from the C heap (or a free +// - in the first phase, G1SegmentedArraySegments are allocated from the C heap (or a free // list given at initialization time). This allocation may occur in parallel. This // typically corresponds to a single mutator phase, but may extend over multiple. // -// - in the second phase, G1SegmentedArrayBuffers are given back in bulk to the free list. +// - in the second phase, G1SegmentedArraySegments are given back in bulk to the free list. // This is typically done during a GC pause. // // Some third party is responsible for giving back memory from the free list to @@ -180,54 +180,54 @@ public: // The class also manages a few counters for statistics using atomic operations. // Their values are only consistent within each other with extra global // synchronization. -template +template class G1SegmentedArray { - // G1SegmentedArrayAllocOptions provides parameters for allocation buffer + // G1SegmentedArrayAllocOptions provides parameters for allocation segment // sizing and expansion. const G1SegmentedArrayAllocOptions* _alloc_options; - G1SegmentedArrayBuffer* volatile _first; // The (start of the) list of all buffers. - G1SegmentedArrayBuffer* _last; // The last element of the list of all buffers. - volatile uint _num_buffers; // Number of assigned buffers to this allocator. - volatile size_t _mem_size; // Memory used by all buffers. + G1SegmentedArraySegment* volatile _first; // The (start of the) list of all segments. + G1SegmentedArraySegment* _last; // The last segment of the list of all segments. + volatile uint _num_segments; // Number of assigned segments to this allocator. + volatile size_t _mem_size; // Memory used by all segments. - G1SegmentedArrayBufferList* _free_buffer_list; // The global free buffer list to - // preferentially get new buffers from. + G1SegmentedArrayFreeList* _free_segment_list; // The global free segment list to + // preferentially get new segments from. - volatile uint _num_available_nodes; // Number of nodes available in all buffers (allocated + free + pending + not yet used). - volatile uint _num_allocated_nodes; // Number of total nodes allocated and in use. + volatile uint _num_available_slots; // Number of slots available in all segments (allocated + free + pending + not yet used). + volatile uint _num_allocated_slots; // Number of total slots allocated and in use. private: - inline G1SegmentedArrayBuffer* create_new_buffer(G1SegmentedArrayBuffer* const prev); + inline G1SegmentedArraySegment* create_new_segment(G1SegmentedArraySegment* const prev); DEBUG_ONLY(uint calculate_length() const;) public: - const G1SegmentedArrayBuffer* first_array_buffer() const { return Atomic::load(&_first); } + const G1SegmentedArraySegment* first_array_segment() const { return Atomic::load(&_first); } - uint num_available_nodes() const { return Atomic::load(&_num_available_nodes); } - uint num_allocated_nodes() const { - uint allocated = Atomic::load(&_num_allocated_nodes); + uint num_available_slots() const { return Atomic::load(&_num_available_slots); } + uint num_allocated_slots() const { + uint allocated = Atomic::load(&_num_allocated_slots); assert(calculate_length() == allocated, "Must be"); return allocated; } - inline uint elem_size() const; + inline uint slot_size() const; - G1SegmentedArray(const G1SegmentedArrayAllocOptions* buffer_options, - G1SegmentedArrayBufferList* free_buffer_list); + G1SegmentedArray(const G1SegmentedArrayAllocOptions* alloc_options, + G1SegmentedArrayFreeList* free_segment_list); ~G1SegmentedArray(); - // Deallocate all buffers to the free buffer list and reset this allocator. Must + // Deallocate all segments to the free segment list and reset this allocator. Must // be called in a globally synchronized area. void drop_all(); - inline Elem* allocate(); + inline Slot* allocate(); - inline uint num_buffers() const; + inline uint num_segments() const; - template - void iterate_nodes(BufferClosure& closure) const; + template + void iterate_segments(SegmentClosure& closure) const; }; #endif //SHARE_GC_G1_G1SEGMENTEDARRAY_HPP diff --git a/src/hotspot/share/gc/g1/g1SegmentedArray.inline.hpp b/src/hotspot/share/gc/g1/g1SegmentedArray.inline.hpp index 463085602be80df592ff60f92063c66e60fc9245..1829f47e2169df6c0a63ec12b21498a5e2240e5c 100644 --- a/src/hotspot/share/gc/g1/g1SegmentedArray.inline.hpp +++ b/src/hotspot/share/gc/g1/g1SegmentedArray.inline.hpp @@ -31,79 +31,79 @@ #include "utilities/globalCounter.inline.hpp" template -G1SegmentedArrayBuffer::G1SegmentedArrayBuffer(uint elem_size, uint num_instances, G1SegmentedArrayBuffer* next) : - _elem_size(elem_size), _num_elems(num_instances), _next(next), _next_allocate(0) { +G1SegmentedArraySegment::G1SegmentedArraySegment(uint slot_size, uint num_slots, G1SegmentedArraySegment* next) : + _slot_size(slot_size), _num_slots(num_slots), _next(next), _next_allocate(0) { - _buffer = NEW_C_HEAP_ARRAY(char, (size_t)_num_elems * elem_size, mtGCCardSet); + _segment = NEW_C_HEAP_ARRAY(char, (size_t)_num_slots * slot_size, mtGCCardSet); } template -G1SegmentedArrayBuffer::~G1SegmentedArrayBuffer() { - FREE_C_HEAP_ARRAY(mtGCCardSet, _buffer); +G1SegmentedArraySegment::~G1SegmentedArraySegment() { + FREE_C_HEAP_ARRAY(mtGCCardSet, _segment); } template -void* G1SegmentedArrayBuffer::get_new_buffer_elem() { - if (_next_allocate >= _num_elems) { +void* G1SegmentedArraySegment::get_new_slot() { + if (_next_allocate >= _num_slots) { return nullptr; } uint result = Atomic::fetch_and_add(&_next_allocate, 1u, memory_order_relaxed); - if (result >= _num_elems) { + if (result >= _num_slots) { return nullptr; } - void* r = _buffer + (uint)result * _elem_size; + void* r = _segment + (uint)result * _slot_size; return r; } template -void G1SegmentedArrayBufferList::bulk_add(G1SegmentedArrayBuffer& first, - G1SegmentedArrayBuffer& last, - size_t num, - size_t mem_size) { +void G1SegmentedArrayFreeList::bulk_add(G1SegmentedArraySegment& first, + G1SegmentedArraySegment& last, + size_t num, + size_t mem_size) { _list.prepend(first, last); - Atomic::add(&_num_buffers, num, memory_order_relaxed); + Atomic::add(&_num_segments, num, memory_order_relaxed); Atomic::add(&_mem_size, mem_size, memory_order_relaxed); } template -void G1SegmentedArrayBufferList::print_on(outputStream* out, const char* prefix) { - out->print_cr("%s: buffers %zu size %zu", - prefix, Atomic::load(&_num_buffers), Atomic::load(&_mem_size)); +void G1SegmentedArrayFreeList::print_on(outputStream* out, const char* prefix) { + out->print_cr("%s: segments %zu size %zu", + prefix, Atomic::load(&_num_segments), Atomic::load(&_mem_size)); } template -G1SegmentedArrayBuffer* G1SegmentedArrayBufferList::get() { +G1SegmentedArraySegment* G1SegmentedArrayFreeList::get() { GlobalCounter::CriticalSection cs(Thread::current()); - G1SegmentedArrayBuffer* result = _list.pop(); + G1SegmentedArraySegment* result = _list.pop(); if (result != nullptr) { - Atomic::dec(&_num_buffers, memory_order_relaxed); + Atomic::dec(&_num_segments, memory_order_relaxed); Atomic::sub(&_mem_size, result->mem_size(), memory_order_relaxed); } return result; } template -G1SegmentedArrayBuffer* G1SegmentedArrayBufferList::get_all(size_t& num_buffers, - size_t& mem_size) { +G1SegmentedArraySegment* G1SegmentedArrayFreeList::get_all(size_t& num_segments, + size_t& mem_size) { GlobalCounter::CriticalSection cs(Thread::current()); - G1SegmentedArrayBuffer* result = _list.pop_all(); - num_buffers = Atomic::load(&_num_buffers); + G1SegmentedArraySegment* result = _list.pop_all(); + num_segments = Atomic::load(&_num_segments); mem_size = Atomic::load(&_mem_size); if (result != nullptr) { - Atomic::sub(&_num_buffers, num_buffers, memory_order_relaxed); + Atomic::sub(&_num_segments, num_segments, memory_order_relaxed); Atomic::sub(&_mem_size, mem_size, memory_order_relaxed); } return result; } template -void G1SegmentedArrayBufferList::free_all() { +void G1SegmentedArrayFreeList::free_all() { size_t num_freed = 0; size_t mem_size_freed = 0; - G1SegmentedArrayBuffer* cur; + G1SegmentedArraySegment* cur; while ((cur = _list.pop()) != nullptr) { mem_size_freed += cur->mem_size(); @@ -111,130 +111,130 @@ void G1SegmentedArrayBufferList::free_all() { delete cur; } - Atomic::sub(&_num_buffers, num_freed, memory_order_relaxed); + Atomic::sub(&_num_segments, num_freed, memory_order_relaxed); Atomic::sub(&_mem_size, mem_size_freed, memory_order_relaxed); } -template -G1SegmentedArrayBuffer* G1SegmentedArray::create_new_buffer(G1SegmentedArrayBuffer* const prev) { - // Take an existing buffer if available. - G1SegmentedArrayBuffer* next = _free_buffer_list->get(); +template +G1SegmentedArraySegment* G1SegmentedArray::create_new_segment(G1SegmentedArraySegment* const prev) { + // Take an existing segment if available. + G1SegmentedArraySegment* next = _free_segment_list->get(); if (next == nullptr) { - uint prev_num_elems = (prev != nullptr) ? prev->num_elems() : 0; - uint num_elems = _alloc_options->next_num_elems(prev_num_elems); - next = new G1SegmentedArrayBuffer(elem_size(), num_elems, prev); + uint prev_num_slots = (prev != nullptr) ? prev->num_slots() : 0; + uint num_slots = _alloc_options->next_num_slots(prev_num_slots); + next = new G1SegmentedArraySegment(slot_size(), num_slots, prev); } else { - assert(elem_size() == next->elem_size() , - "Mismatch %d != %d Elem %zu", elem_size(), next->elem_size(), sizeof(Elem)); + assert(slot_size() == next->slot_size() , + "Mismatch %d != %d Slot %zu", slot_size(), next->slot_size(), sizeof(Slot)); next->reset(prev); } - // Install it as current allocation buffer. - G1SegmentedArrayBuffer* old = Atomic::cmpxchg(&_first, prev, next); + // Install it as current allocation segment. + G1SegmentedArraySegment* old = Atomic::cmpxchg(&_first, prev, next); if (old != prev) { - // Somebody else installed the buffer, use that one. + // Somebody else installed the segment, use that one. delete next; return old; } else { - // Did we install the first element in the list? If so, this is also the last. + // Did we install the first segment in the list? If so, this is also the last. if (prev == nullptr) { _last = next; } - // Successfully installed the buffer into the list. - Atomic::inc(&_num_buffers, memory_order_relaxed); + // Successfully installed the segment into the list. + Atomic::inc(&_num_segments, memory_order_relaxed); Atomic::add(&_mem_size, next->mem_size(), memory_order_relaxed); - Atomic::add(&_num_available_nodes, next->num_elems(), memory_order_relaxed); + Atomic::add(&_num_available_slots, next->num_slots(), memory_order_relaxed); return next; } } -template -uint G1SegmentedArray::elem_size() const { - return _alloc_options->elem_size(); +template +uint G1SegmentedArray::slot_size() const { + return _alloc_options->slot_size(); } -template -G1SegmentedArray::G1SegmentedArray(const G1SegmentedArrayAllocOptions* buffer_options, - G1SegmentedArrayBufferList* free_buffer_list) : - _alloc_options(buffer_options), +template +G1SegmentedArray::G1SegmentedArray(const G1SegmentedArrayAllocOptions* alloc_options, + G1SegmentedArrayFreeList* free_segment_list) : + _alloc_options(alloc_options), _first(nullptr), _last(nullptr), - _num_buffers(0), + _num_segments(0), _mem_size(0), - _free_buffer_list(free_buffer_list), - _num_available_nodes(0), - _num_allocated_nodes(0) { - assert(_free_buffer_list != nullptr, "precondition!"); + _free_segment_list(free_segment_list), + _num_available_slots(0), + _num_allocated_slots(0) { + assert(_free_segment_list != nullptr, "precondition!"); } -template -G1SegmentedArray::~G1SegmentedArray() { +template +G1SegmentedArray::~G1SegmentedArray() { drop_all(); } -template -void G1SegmentedArray::drop_all() { - G1SegmentedArrayBuffer* cur = Atomic::load_acquire(&_first); +template +void G1SegmentedArray::drop_all() { + G1SegmentedArraySegment* cur = Atomic::load_acquire(&_first); if (cur != nullptr) { - assert(_last != nullptr, "If there is at least one element, there must be a last one."); + assert(_last != nullptr, "If there is at least one segment, there must be a last one."); - G1SegmentedArrayBuffer* first = cur; + G1SegmentedArraySegment* first = cur; #ifdef ASSERT // Check list consistency. - G1SegmentedArrayBuffer* last = cur; - uint num_buffers = 0; + G1SegmentedArraySegment* last = cur; + uint num_segments = 0; size_t mem_size = 0; while (cur != nullptr) { mem_size += cur->mem_size(); - num_buffers++; + num_segments++; - G1SegmentedArrayBuffer* next = cur->next(); + G1SegmentedArraySegment* next = cur->next(); last = cur; cur = next; } #endif - assert(num_buffers == _num_buffers, "Buffer count inconsistent %u %u", num_buffers, _num_buffers); + assert(num_segments == _num_segments, "Segment count inconsistent %u %u", num_segments, _num_segments); assert(mem_size == _mem_size, "Memory size inconsistent"); - assert(last == _last, "Inconsistent last element"); + assert(last == _last, "Inconsistent last segment"); - _free_buffer_list->bulk_add(*first, *_last, _num_buffers, _mem_size); + _free_segment_list->bulk_add(*first, *_last, _num_segments, _mem_size); } _first = nullptr; _last = nullptr; - _num_buffers = 0; + _num_segments = 0; _mem_size = 0; - _num_available_nodes = 0; - _num_allocated_nodes = 0; + _num_available_slots = 0; + _num_allocated_slots = 0; } -template -Elem* G1SegmentedArray::allocate() { - assert(elem_size() > 0, "instance size not set."); +template +Slot* G1SegmentedArray::allocate() { + assert(slot_size() > 0, "instance size not set."); - G1SegmentedArrayBuffer* cur = Atomic::load_acquire(&_first); + G1SegmentedArraySegment* cur = Atomic::load_acquire(&_first); if (cur == nullptr) { - cur = create_new_buffer(cur); + cur = create_new_segment(cur); } while (true) { - Elem* elem = (Elem*)cur->get_new_buffer_elem(); - if (elem != nullptr) { - Atomic::inc(&_num_allocated_nodes, memory_order_relaxed); - guarantee(is_aligned(elem, _alloc_options->alignment()), - "result " PTR_FORMAT " not aligned at %u", p2i(elem), _alloc_options->alignment()); - return elem; + Slot* slot = (Slot*)cur->get_new_slot(); + if (slot != nullptr) { + Atomic::inc(&_num_allocated_slots, memory_order_relaxed); + guarantee(is_aligned(slot, _alloc_options->slot_alignment()), + "result " PTR_FORMAT " not aligned at %u", p2i(slot), _alloc_options->slot_alignment()); + return slot; } - // The buffer is full. Next round. + // The segment is full. Next round. assert(cur->is_full(), "must be"); - cur = create_new_buffer(cur); + cur = create_new_segment(cur); } } -template -inline uint G1SegmentedArray::num_buffers() const { - return Atomic::load(&_num_buffers); +template +inline uint G1SegmentedArray::num_segments() const { + return Atomic::load(&_num_segments); } #ifdef ASSERT @@ -243,7 +243,7 @@ class LengthClosure { uint _total; public: LengthClosure() : _total(0) {} - void do_buffer(G1SegmentedArrayBuffer* node, uint limit) { + void do_segment(G1SegmentedArraySegment* segment, uint limit) { _total += limit; } uint length() const { @@ -251,24 +251,24 @@ public: } }; -template -uint G1SegmentedArray::calculate_length() const { +template +uint G1SegmentedArray::calculate_length() const { LengthClosure closure; - iterate_nodes(closure); + iterate_segments(closure); return closure.length(); } #endif -template -template -void G1SegmentedArray::iterate_nodes(BufferClosure& closure) const { - G1SegmentedArrayBuffer* cur = Atomic::load_acquire(&_first); +template +template +void G1SegmentedArray::iterate_segments(SegmentClosure& closure) const { + G1SegmentedArraySegment* cur = Atomic::load_acquire(&_first); assert((cur != nullptr) == (_last != nullptr), - "If there is at least one element, there must be a last one"); + "If there is at least one segment, there must be a last one"); while (cur != nullptr) { - closure.do_buffer(cur, cur->length()); + closure.do_segment(cur, cur->length()); cur = cur->next(); } } diff --git a/src/hotspot/share/gc/g1/g1CardSetFreeMemoryTask.cpp b/src/hotspot/share/gc/g1/g1SegmentedArrayFreeMemoryTask.cpp similarity index 70% rename from src/hotspot/share/gc/g1/g1CardSetFreeMemoryTask.cpp rename to src/hotspot/share/gc/g1/g1SegmentedArrayFreeMemoryTask.cpp index 09a22728a89471c0d4145a858bb376eb19e58fff..4752adde74d2d3be284b9c951f64033b0d45dbb4 100644 --- a/src/hotspot/share/gc/g1/g1CardSetFreeMemoryTask.cpp +++ b/src/hotspot/share/gc/g1/g1SegmentedArrayFreeMemoryTask.cpp @@ -23,22 +23,23 @@ */ #include "precompiled.hpp" -#include "gc/g1/g1CardSetFreeMemoryTask.hpp" +#include "ci/ciUtilities.hpp" #include "gc/g1/g1CardSetMemory.inline.hpp" #include "gc/g1/g1CollectedHeap.hpp" +#include "gc/g1/g1SegmentedArrayFreeMemoryTask.hpp" #include "gc/g1/g1_globals.hpp" +#include "gc/g1/heapRegionRemSet.hpp" #include "gc/shared/gcTraceTime.inline.hpp" #include "gc/shared/suspendibleThreadSet.hpp" -#include "heapRegionRemSet.hpp" -#include "ci/ciUtilities.hpp" +#include "runtime/os.hpp" -constexpr const char* G1CardSetFreeMemoryTask::_state_names[]; +constexpr const char* G1SegmentedArrayFreeMemoryTask::_state_names[]; -const char* G1CardSetFreeMemoryTask::get_state_name(State value) const { +const char* G1SegmentedArrayFreeMemoryTask::get_state_name(State value) const { return _state_names[static_cast>(value)]; } -bool G1CardSetFreeMemoryTask::deadline_exceeded(jlong deadline) { +bool G1SegmentedArrayFreeMemoryTask::deadline_exceeded(jlong deadline) { return os::elapsed_counter() >= deadline; } @@ -47,31 +48,31 @@ static size_t keep_size(size_t free, size_t used, double percent) { return MIN2(free, to_keep); } -bool G1CardSetFreeMemoryTask::calculate_return_infos(jlong deadline) { +bool G1SegmentedArrayFreeMemoryTask::calculate_return_infos(jlong deadline) { // Ignore the deadline in this step as it is very short. - G1CardSetMemoryStats used = _total_used; - G1CardSetMemoryStats free = G1CardSetFreePool::free_list_sizes(); + G1SegmentedArrayMemoryStats used = _total_used; + G1SegmentedArrayMemoryStats free = G1SegmentedArrayFreePool::free_list_sizes(); _return_info = new G1ReturnMemoryProcessorSet(used.num_pools()); for (uint i = 0; i < used.num_pools(); i++) { size_t return_to_vm_size = keep_size(free._num_mem_sizes[i], used._num_mem_sizes[i], G1RemSetFreeMemoryKeepExcessRatio); - log_trace(gc, task)("Card Set Free Memory: Type %s: Free: %zu (%zu) " + log_trace(gc, task)("Segmented Array Free Memory: Type %s: Free: %zu (%zu) " "Used: %zu Keep: %zu", G1CardSetConfiguration::mem_object_type_name_str(i), - free._num_mem_sizes[i], free._num_buffers[i], + free._num_mem_sizes[i], free._num_segments[i], used._num_mem_sizes[i], return_to_vm_size); _return_info->append(new G1ReturnMemoryProcessor(return_to_vm_size)); } - G1CardSetFreePool::update_unlink_processors(_return_info); + G1SegmentedArrayFreePool::update_unlink_processors(_return_info); return false; } -bool G1CardSetFreeMemoryTask::return_memory_to_vm(jlong deadline) { +bool G1SegmentedArrayFreeMemoryTask::return_memory_to_vm(jlong deadline) { for (int i = 0; i < _return_info->length(); i++) { G1ReturnMemoryProcessor* info = _return_info->at(i); if (!info->finished_return_to_vm()) { @@ -83,7 +84,7 @@ bool G1CardSetFreeMemoryTask::return_memory_to_vm(jlong deadline) { return false; } -bool G1CardSetFreeMemoryTask::return_memory_to_os(jlong deadline) { +bool G1SegmentedArrayFreeMemoryTask::return_memory_to_os(jlong deadline) { for (int i = 0; i < _return_info->length(); i++) { G1ReturnMemoryProcessor* info = _return_info->at(i); if (!info->finished_return_to_os()) { @@ -95,7 +96,7 @@ bool G1CardSetFreeMemoryTask::return_memory_to_os(jlong deadline) { return false; } -bool G1CardSetFreeMemoryTask::cleanup_return_infos() { +bool G1SegmentedArrayFreeMemoryTask::cleanup_return_infos() { for (int i = 0; i < _return_info->length(); i++) { G1ReturnMemoryProcessor* info = _return_info->at(i); delete info; @@ -106,12 +107,12 @@ bool G1CardSetFreeMemoryTask::cleanup_return_infos() { return false; } -bool G1CardSetFreeMemoryTask::free_excess_card_set_memory() { +bool G1SegmentedArrayFreeMemoryTask::free_excess_segmented_array_memory() { jlong start = os::elapsed_counter(); jlong end = start + (os::elapsed_frequency() / 1000) * G1RemSetFreeMemoryStepDurationMillis; - log_trace(gc, task)("Card Set Free Memory: Step start %1.3f end %1.3f", + log_trace(gc, task)("Segmented Array Free Memory: Step start %1.3f end %1.3f", TimeHelper::counter_to_millis(start), TimeHelper::counter_to_millis(end)); State next_state; @@ -148,7 +149,7 @@ bool G1CardSetFreeMemoryTask::free_excess_card_set_memory() { break; } default: - log_error(gc, task)("Should not try to free excess card set memory in %s state", get_state_name(_state)); + log_error(gc, task)("Should not try to free excess segmented array memory in %s state", get_state_name(_state)); ShouldNotReachHere(); break; } @@ -156,41 +157,41 @@ bool G1CardSetFreeMemoryTask::free_excess_card_set_memory() { set_state(next_state); } while (_state != State::Inactive && !deadline_exceeded(end)); - log_trace(gc, task)("Card Set Free Memory: Step took %1.3fms, done %s", + log_trace(gc, task)("Segmented Array Free Memory: Step took %1.3fms, done %s", TimeHelper::counter_to_millis(os::elapsed_counter() - start), bool_to_str(_state == State::CalculateUsed)); return is_active(); } -void G1CardSetFreeMemoryTask::set_state(State new_state) { - log_trace(gc, task)("Card Set Free Memory: State change from %s to %s", +void G1SegmentedArrayFreeMemoryTask::set_state(State new_state) { + log_trace(gc, task)("Segmented Array Free Memory: State change from %s to %s", get_state_name(_state), get_state_name(new_state)); _state = new_state; } -bool G1CardSetFreeMemoryTask::is_active() const { +bool G1SegmentedArrayFreeMemoryTask::is_active() const { return _state != State::Inactive; } -jlong G1CardSetFreeMemoryTask::reschedule_delay_ms() const { +jlong G1SegmentedArrayFreeMemoryTask::reschedule_delay_ms() const { return G1RemSetFreeMemoryRescheduleDelayMillis; } -G1CardSetFreeMemoryTask::G1CardSetFreeMemoryTask(const char* name) : +G1SegmentedArrayFreeMemoryTask::G1SegmentedArrayFreeMemoryTask(const char* name) : G1ServiceTask(name), _state(State::CalculateUsed), _return_info(nullptr) { } -void G1CardSetFreeMemoryTask::execute() { +void G1SegmentedArrayFreeMemoryTask::execute() { SuspendibleThreadSetJoiner sts; - if (free_excess_card_set_memory()) { + if (free_excess_segmented_array_memory()) { schedule(reschedule_delay_ms()); } } -void G1CardSetFreeMemoryTask::notify_new_stats(G1CardSetMemoryStats* young_gen_stats, - G1CardSetMemoryStats* collection_set_candidate_stats) { +void G1SegmentedArrayFreeMemoryTask::notify_new_stats(G1SegmentedArrayMemoryStats* young_gen_stats, + G1SegmentedArrayMemoryStats* collection_set_candidate_stats) { assert_at_safepoint_on_vm_thread(); _total_used = *young_gen_stats; diff --git a/src/hotspot/share/gc/g1/g1CardSetFreeMemoryTask.hpp b/src/hotspot/share/gc/g1/g1SegmentedArrayFreeMemoryTask.hpp similarity index 72% rename from src/hotspot/share/gc/g1/g1CardSetFreeMemoryTask.hpp rename to src/hotspot/share/gc/g1/g1SegmentedArrayFreeMemoryTask.hpp index 3d617243aa4c3fbd5f0186ace6484e81157d4b4b..a4195cd424c669ef414237868b4a644313de9190 100644 --- a/src/hotspot/share/gc/g1/g1CardSetFreeMemoryTask.hpp +++ b/src/hotspot/share/gc/g1/g1SegmentedArrayFreeMemoryTask.hpp @@ -22,17 +22,18 @@ * */ -#ifndef SHARE_GC_G1_G1CARDSETFREEMEMORYTASK_HPP -#define SHARE_GC_G1_G1CARDSETFREEMEMORYTASK_HPP +#ifndef SHARE_GC_G1_G1SEGMENTEDARRAYFREEMEMORYTASK_HPP +#define SHARE_GC_G1_G1SEGMENTEDARRAYFREEMEMORYTASK_HPP -#include "gc/g1/g1ServiceThread.hpp" #include "gc/g1/g1CardSetMemory.hpp" +#include "gc/g1/g1SegmentedArrayFreePool.hpp" +#include "gc/g1/g1ServiceThread.hpp" #include "gc/g1/heapRegionRemSet.hpp" #include "utilities/growableArray.hpp" #include "utilities/ticks.hpp" -// Task handling deallocation of free card set memory. -class G1CardSetFreeMemoryTask : public G1ServiceTask { +// Task handling deallocation of free segmented array memory. +class G1SegmentedArrayFreeMemoryTask : public G1ServiceTask { enum class State : uint { Inactive, @@ -52,11 +53,11 @@ class G1CardSetFreeMemoryTask : public G1ServiceTask { State _state; - // Current total card set memory usage. - G1CardSetMemoryStats _total_used; + // Current total segmented array memory usage. + G1SegmentedArrayMemoryStats _total_used; - typedef G1CardSetFreePool::G1ReturnMemoryProcessor G1ReturnMemoryProcessor; - typedef G1CardSetFreePool::G1ReturnMemoryProcessorSet G1ReturnMemoryProcessorSet; + typedef G1SegmentedArrayFreePool::G1ReturnMemoryProcessor G1ReturnMemoryProcessor; + typedef G1SegmentedArrayFreePool::G1ReturnMemoryProcessorSet G1ReturnMemoryProcessorSet; G1ReturnMemoryProcessorSet* _return_info; @@ -70,9 +71,9 @@ class G1CardSetFreeMemoryTask : public G1ServiceTask { bool return_memory_to_os(jlong deadline); bool cleanup_return_infos(); - // Free excess card set memory, main method. Returns true if there is more work + // Free excess segmented array memory, main method. Returns true if there is more work // to do. - bool free_excess_card_set_memory(); + bool free_excess_segmented_array_memory(); void set_state(State new_state); // Returns whether we are currently processing a recent request. @@ -82,14 +83,14 @@ class G1CardSetFreeMemoryTask : public G1ServiceTask { jlong reschedule_delay_ms() const; public: - explicit G1CardSetFreeMemoryTask(const char* name); + explicit G1SegmentedArrayFreeMemoryTask(const char* name); void execute() override; // Notify the task of new used remembered set memory statistics for the young // generation and the collection set candidate sets. - void notify_new_stats(G1CardSetMemoryStats* young_gen_stats, - G1CardSetMemoryStats* collection_set_candidate_stats); + void notify_new_stats(G1SegmentedArrayMemoryStats* young_gen_stats, + G1SegmentedArrayMemoryStats* collection_set_candidate_stats); }; -#endif // SHARE_GC_G1_G1CARDSETFREEMEMORYTASK_HPP +#endif // SHARE_GC_G1_G1SEGMENTEDARRAYFREEMEMORYTASK_HPP diff --git a/src/hotspot/share/gc/g1/g1SegmentedArrayFreePool.cpp b/src/hotspot/share/gc/g1/g1SegmentedArrayFreePool.cpp index 48ce124f00fb58c9cb8a34669f1518fa936461a5..118638da75bee9887a455926039223e41b7c67a5 100644 --- a/src/hotspot/share/gc/g1/g1SegmentedArrayFreePool.cpp +++ b/src/hotspot/share/gc/g1/g1SegmentedArrayFreePool.cpp @@ -24,7 +24,6 @@ #include "precompiled.hpp" -#include "gc/g1/g1CardSetMemory.hpp" #include "gc/g1/g1SegmentedArrayFreePool.hpp" #include "gc/g1/g1SegmentedArray.inline.hpp" #include "logging/log.hpp" @@ -33,19 +32,19 @@ #include "utilities/formatBuffer.hpp" #include "utilities/ostream.hpp" - -G1CardSetMemoryStats::G1CardSetMemoryStats() { +G1SegmentedArrayMemoryStats::G1SegmentedArrayMemoryStats() { clear(); } -void G1CardSetMemoryStats::clear() { +void G1SegmentedArrayMemoryStats::clear() { for (uint i = 0; i < num_pools(); i++) { _num_mem_sizes[i] = 0; - _num_buffers[i] = 0; + _num_segments[i] = 0; } } -void G1CardSetFreePool::update_unlink_processors(G1ReturnMemoryProcessorSet* unlink_processor) { +template +void G1SegmentedArrayFreePool::update_unlink_processors(G1ReturnMemoryProcessorSet* unlink_processor) { uint num_free_lists = _freelist_pool.num_free_lists(); for (uint i = 0; i < num_free_lists; i++) { @@ -53,7 +52,8 @@ void G1CardSetFreePool::update_unlink_processors(G1ReturnMemoryProcessorSet* unl } } -void G1CardSetFreePool::G1ReturnMemoryProcessor::visit_free_list(G1CardSetBufferList* source) { +template +void G1SegmentedArrayFreePool::G1ReturnMemoryProcessor::visit_free_list(G1SegmentedArrayFreeList* source) { assert(_source == nullptr, "already visited"); if (_return_to_vm_size > 0) { _source = source; @@ -75,15 +75,16 @@ void G1CardSetFreePool::G1ReturnMemoryProcessor::visit_free_list(G1CardSetBuffer } } -bool G1CardSetFreePool::G1ReturnMemoryProcessor::return_to_vm(jlong deadline) { +template +bool G1SegmentedArrayFreePool::G1ReturnMemoryProcessor::return_to_vm(jlong deadline) { assert(!finished_return_to_vm(), "already returned everything to the VM"); - assert(_first != nullptr, "must have element to return"); + assert(_first != nullptr, "must have segment to return"); size_t keep_size = 0; size_t keep_num = 0; - G1CardSetBuffer* cur = _first; - G1CardSetBuffer* last = nullptr; + G1SegmentedArraySegment* cur = _first; + G1SegmentedArraySegment* last = nullptr; while (cur != nullptr && _return_to_vm_size > 0) { size_t cur_size = cur->mem_size(); @@ -110,7 +111,7 @@ bool G1CardSetFreePool::G1ReturnMemoryProcessor::return_to_vm(jlong deadline) { _source->bulk_add(*_first, *last, keep_num, keep_size); _first = cur; - log_trace(gc, task)("Card Set Free Memory: Returned to VM %zu buffers size %zu", keep_num, keep_size); + log_trace(gc, task)("Segmented Array Free Memory: Returned to VM %zu segments size %zu", keep_num, keep_size); // _return_to_vm_size may be larger than what is available in the list at the // time we actually get the list. I.e. the list and _return_to_vm_size may be @@ -124,7 +125,8 @@ bool G1CardSetFreePool::G1ReturnMemoryProcessor::return_to_vm(jlong deadline) { return _source != nullptr; } -bool G1CardSetFreePool::G1ReturnMemoryProcessor::return_to_os(jlong deadline) { +template +bool G1SegmentedArrayFreePool::G1ReturnMemoryProcessor::return_to_os(jlong deadline) { assert(finished_return_to_vm(), "not finished returning to VM"); assert(!finished_return_to_os(), "already returned everything to the OS"); @@ -133,7 +135,7 @@ bool G1CardSetFreePool::G1ReturnMemoryProcessor::return_to_os(jlong deadline) { size_t mem_size_deleted = 0; while (_first != nullptr) { - G1CardSetBuffer* next = _first->next(); + G1SegmentedArraySegment* next = _first->next(); num_delete++; mem_size_deleted += _first->mem_size(); delete _first; @@ -145,45 +147,45 @@ bool G1CardSetFreePool::G1ReturnMemoryProcessor::return_to_os(jlong deadline) { } } - log_trace(gc, task)("Card Set Free Memory: Return to OS %zu buffers size %zu", num_delete, mem_size_deleted); + log_trace(gc, task)("Segmented Array Free Memory: Return to OS %zu segments size %zu", num_delete, mem_size_deleted); return _first != nullptr; } -G1CardSetFreePool G1CardSetFreePool::_freelist_pool(G1CardSetConfiguration::num_mem_object_types()); +template +G1SegmentedArrayFreePool G1SegmentedArrayFreePool::_freelist_pool(G1CardSetConfiguration::num_mem_object_types()); -G1CardSetFreePool::G1CardSetFreePool(uint num_free_lists) : +template +G1SegmentedArrayFreePool::G1SegmentedArrayFreePool(uint num_free_lists) : _num_free_lists(num_free_lists) { - _free_lists = NEW_C_HEAP_ARRAY(G1CardSetBufferList, _num_free_lists, mtGC); + _free_lists = NEW_C_HEAP_ARRAY(G1SegmentedArrayFreeList < flag >, _num_free_lists, mtGC); for (uint i = 0; i < _num_free_lists; i++) { - new (&_free_lists[i]) G1CardSetBufferList(); + new (&_free_lists[i]) G1SegmentedArrayFreeList(); } } -G1CardSetFreePool::~G1CardSetFreePool() { +template +G1SegmentedArrayFreePool::~G1SegmentedArrayFreePool() { for (uint i = 0; i < _num_free_lists; i++) { - _free_lists[i].~G1CardSetBufferList(); + _free_lists[i].~G1SegmentedArrayFreeList(); } FREE_C_HEAP_ARRAY(mtGC, _free_lists); } -G1CardSetBufferList* G1CardSetFreePool::free_list(uint i) { - assert(i < _num_free_lists, "must be"); - return &_free_lists[i]; -} - -G1CardSetMemoryStats G1CardSetFreePool::memory_sizes() const { - G1CardSetMemoryStats free_list_stats; +template +G1SegmentedArrayMemoryStats G1SegmentedArrayFreePool::memory_sizes() const { + G1SegmentedArrayMemoryStats free_list_stats; assert(free_list_stats.num_pools() == num_free_lists(), "must be"); for (uint i = 0; i < num_free_lists(); i++) { free_list_stats._num_mem_sizes[i] = _free_lists[i].mem_size(); - free_list_stats._num_buffers[i] = _free_lists[i].num_buffers(); + free_list_stats._num_segments[i] = _free_lists[i].num_segments(); } return free_list_stats; } -size_t G1CardSetFreePool::mem_size() const { +template +size_t G1SegmentedArrayFreePool::mem_size() const { size_t result = 0; for (uint i = 0; i < _num_free_lists; i++) { result += _free_lists[i].mem_size(); @@ -191,10 +193,13 @@ size_t G1CardSetFreePool::mem_size() const { return result; } -void G1CardSetFreePool::print_on(outputStream* out) { +template +void G1SegmentedArrayFreePool::print_on(outputStream* out) { out->print_cr(" Free Pool: size %zu", free_list_pool()->mem_size()); for (uint i = 0; i < _num_free_lists; i++) { FormatBuffer<> fmt(" %s", G1CardSetConfiguration::mem_object_type_name_str(i)); _free_lists[i].print_on(out, fmt); } } + +template class G1SegmentedArrayFreePool; diff --git a/src/hotspot/share/gc/g1/g1SegmentedArrayFreePool.hpp b/src/hotspot/share/gc/g1/g1SegmentedArrayFreePool.hpp index 917b9475c0b021d63f5aef1f4b96f82f3b7e34a0..ba1b952875c5f3c6470c8c338570f29ffc1262d1 100644 --- a/src/hotspot/share/gc/g1/g1SegmentedArrayFreePool.hpp +++ b/src/hotspot/share/gc/g1/g1SegmentedArrayFreePool.hpp @@ -21,6 +21,7 @@ * questions. * */ + #ifndef SHARE_GC_G1_G1SEGMENTEDARRAYFREEPOOL_HPP #define SHARE_GC_G1_G1SEGMENTEDARRAYFREEPOOL_HPP @@ -28,23 +29,23 @@ #include "gc/g1/g1SegmentedArray.hpp" #include "utilities/growableArray.hpp" -// Statistics for a fixed set of buffer lists. Contains the number of buffers and memory +// Statistics for a segmented array. Contains the number of segments and memory // used for each. Note that statistics are typically not taken atomically so there // can be inconsistencies. The user must be prepared for them. -class G1CardSetMemoryStats { +class G1SegmentedArrayMemoryStats { public: size_t _num_mem_sizes[G1CardSetConfiguration::num_mem_object_types()]; - size_t _num_buffers[G1CardSetConfiguration::num_mem_object_types()]; + size_t _num_segments[G1CardSetConfiguration::num_mem_object_types()]; // Returns all-zero statistics. - G1CardSetMemoryStats(); + G1SegmentedArrayMemoryStats(); - void add(G1CardSetMemoryStats const other) { - STATIC_ASSERT(ARRAY_SIZE(_num_buffers) == ARRAY_SIZE(_num_mem_sizes)); + void add(G1SegmentedArrayMemoryStats const other) { + STATIC_ASSERT(ARRAY_SIZE(_num_segments) == ARRAY_SIZE(_num_mem_sizes)); for (uint i = 0; i < ARRAY_SIZE(_num_mem_sizes); i++) { _num_mem_sizes[i] += other._num_mem_sizes[i]; - _num_buffers[i] += other._num_buffers[i]; + _num_segments[i] += other._num_segments[i]; } } @@ -53,46 +54,49 @@ public: uint num_pools() const { return G1CardSetConfiguration::num_mem_object_types(); } }; -typedef G1SegmentedArrayBuffer G1CardSetBuffer; -typedef G1SegmentedArrayBufferList G1CardSetBufferList; - -// A set of free lists holding memory buffers for use by G1CardSetAllocators. -class G1CardSetFreePool { +// A set of free lists holding freed segments for use by G1SegmentedArray, +// e.g. G1CardSetAllocators::SegmentedArray +template +class G1SegmentedArrayFreePool { // The global free pool. - static G1CardSetFreePool _freelist_pool; + static G1SegmentedArrayFreePool _freelist_pool; const uint _num_free_lists; - G1CardSetBufferList* _free_lists; + G1SegmentedArrayFreeList* _free_lists; public: - static G1CardSetFreePool* free_list_pool() { return &_freelist_pool; } - static G1CardSetMemoryStats free_list_sizes() { return _freelist_pool.memory_sizes(); } + static G1SegmentedArrayFreePool* free_list_pool() { return &_freelist_pool; } + static G1SegmentedArrayMemoryStats free_list_sizes() { return _freelist_pool.memory_sizes(); } class G1ReturnMemoryProcessor; typedef GrowableArrayCHeap G1ReturnMemoryProcessorSet; static void update_unlink_processors(G1ReturnMemoryProcessorSet* unlink_processors); - explicit G1CardSetFreePool(uint num_free_lists); - ~G1CardSetFreePool(); + explicit G1SegmentedArrayFreePool(uint num_free_lists); + ~G1SegmentedArrayFreePool(); - G1CardSetBufferList* free_list(uint i); + G1SegmentedArrayFreeList* free_list(uint i) { + assert(i < _num_free_lists, "must be"); + return &_free_lists[i]; + } uint num_free_lists() const { return _num_free_lists; } - G1CardSetMemoryStats memory_sizes() const; + G1SegmentedArrayMemoryStats memory_sizes() const; size_t mem_size() const; void print_on(outputStream* out); }; // Data structure containing current in-progress state for returning memory to the -// operating system for a single G1CardSetBufferList. -class G1CardSetFreePool::G1ReturnMemoryProcessor : public CHeapObj { - G1CardSetBufferList* _source; +// operating system for a single G1SegmentedArrayFreeList. +template +class G1SegmentedArrayFreePool::G1ReturnMemoryProcessor : public CHeapObj { + G1SegmentedArrayFreeList* _source; size_t _return_to_vm_size; - G1CardSetBuffer* _first; + G1SegmentedArraySegment* _first; size_t _unlinked_bytes; size_t _num_unlinked; @@ -101,23 +105,23 @@ public: _source(nullptr), _return_to_vm_size(return_to_vm), _first(nullptr), _unlinked_bytes(0), _num_unlinked(0) { } - // Updates the instance members about the given card set buffer list for the purpose - // of giving back memory. Only necessary members are updated, e.g. if there is - // nothing to return to the VM, do not set the source list. - void visit_free_list(G1CardSetBufferList* source); + // Updates the instance members about the given free list for + // the purpose of giving back memory. Only necessary members are updated, + // e.g. if there is nothing to return to the VM, do not set the source list. + void visit_free_list(G1SegmentedArrayFreeList* source); bool finished_return_to_vm() const { return _return_to_vm_size == 0; } bool finished_return_to_os() const { return _first == nullptr; } // Returns memory to the VM until the given deadline expires. Returns true if - // there is no more work. Guarantees forward progress, i.e. at least one buffer + // there is no more work. Guarantees forward progress, i.e. at least one segment // has been processed after returning. - // return_to_vm() re-adds buffers to the respective free list. + // return_to_vm() re-adds segments to the respective free list. bool return_to_vm(jlong deadline); // Returns memory to the VM until the given deadline expires. Returns true if - // there is no more work. Guarantees forward progress, i.e. at least one buffer + // there is no more work. Guarantees forward progress, i.e. at least one segment // has been processed after returning. - // return_to_os() gives back buffers to the OS. + // return_to_os() gives back segments to the OS. bool return_to_os(jlong deadline); }; diff --git a/src/hotspot/share/gc/g1/g1YoungCollector.cpp b/src/hotspot/share/gc/g1/g1YoungCollector.cpp index 34985059de5878e645b41d8511b7d2b41d5e1e60..d476c981d7134782d1459bbc74bc6f52674e5712 100644 --- a/src/hotspot/share/gc/g1/g1YoungCollector.cpp +++ b/src/hotspot/share/gc/g1/g1YoungCollector.cpp @@ -330,7 +330,7 @@ class G1PrepareEvacuationTask : public WorkerTask { uint _worker_humongous_total; uint _worker_humongous_candidates; - G1CardSetMemoryStats _card_set_stats; + G1SegmentedArrayMemoryStats _card_set_stats; void sample_card_set_size(HeapRegion* hr) { // Sample card set sizes for young gen and humongous before GC: this makes @@ -446,7 +446,7 @@ class G1PrepareEvacuationTask : public WorkerTask { return false; } - G1CardSetMemoryStats card_set_stats() const { + G1SegmentedArrayMemoryStats card_set_stats() const { return _card_set_stats; } }; @@ -456,7 +456,7 @@ class G1PrepareEvacuationTask : public WorkerTask { volatile uint _humongous_total; volatile uint _humongous_candidates; - G1CardSetMemoryStats _all_card_set_stats; + G1SegmentedArrayMemoryStats _all_card_set_stats; public: G1PrepareEvacuationTask(G1CollectedHeap* g1h) : @@ -490,7 +490,7 @@ public: return _humongous_total; } - const G1CardSetMemoryStats all_card_set_stats() const { + const G1SegmentedArrayMemoryStats all_card_set_stats() const { return _all_card_set_stats; } }; diff --git a/src/hotspot/share/gc/g1/g1YoungCollector.hpp b/src/hotspot/share/gc/g1/g1YoungCollector.hpp index 4bc1eaf19421c90612613ba96a167ada2f2a6134..055803a3352289117fadd975fbffaee5145c714f 100644 --- a/src/hotspot/share/gc/g1/g1YoungCollector.hpp +++ b/src/hotspot/share/gc/g1/g1YoungCollector.hpp @@ -33,7 +33,6 @@ class WorkerTask; class G1Allocator; class G1BatchedTask; -class G1CardSetMemoryStats; class G1CollectedHeap; class G1CollectionSet; class G1CollectorState; @@ -49,6 +48,7 @@ class G1ParScanThreadStateSet; class G1Policy; class G1RedirtyCardsQueueSet; class G1RemSet; +class G1SegmentedArrayMemoryStats; class G1SurvivorRegions; class G1YoungGCEvacFailureInjector; class STWGCTimer; diff --git a/src/hotspot/share/gc/g1/g1YoungGCEvacFailureInjector.cpp b/src/hotspot/share/gc/g1/g1YoungGCEvacFailureInjector.cpp index 67b44263004d691654af6a62def2a390a4bfc8ac..c534d6f29c8e85cf10bdf6656a0945d36ea10cfb 100644 --- a/src/hotspot/share/gc/g1/g1YoungGCEvacFailureInjector.cpp +++ b/src/hotspot/share/gc/g1/g1YoungGCEvacFailureInjector.cpp @@ -30,6 +30,33 @@ #if EVAC_FAILURE_INJECTOR +class SelectEvacFailureRegionClosure : public HeapRegionClosure { + CHeapBitMap& _evac_failure_regions; + size_t _evac_failure_regions_num; + +public: + SelectEvacFailureRegionClosure(CHeapBitMap& evac_failure_regions, size_t cset_length) : + _evac_failure_regions(evac_failure_regions), + _evac_failure_regions_num(cset_length * G1EvacuationFailureALotCSetPercent / 100) { } + + bool do_heap_region(HeapRegion* r) override { + assert(r->in_collection_set(), "must be"); + if (_evac_failure_regions_num > 0) { + _evac_failure_regions.set_bit(r->hrm_index()); + --_evac_failure_regions_num; + return false; + } + return true; + } +}; + +void G1YoungGCEvacFailureInjector::select_evac_failure_regions() { + G1CollectedHeap* g1h = G1CollectedHeap::heap(); + _evac_failure_regions.reinitialize(g1h->max_reserved_regions()); + SelectEvacFailureRegionClosure closure(_evac_failure_regions, g1h->collection_set()->cur_length()); + g1h->collection_set_iterate_all(&closure); +} + bool G1YoungGCEvacFailureInjector::arm_if_needed_for_gc_type(bool for_young_gc, bool during_concurrent_start, bool mark_or_rebuild_in_progress) { @@ -68,6 +95,10 @@ void G1YoungGCEvacFailureInjector::arm_if_needed() { arm_if_needed_for_gc_type(in_young_only_phase, in_concurrent_start_gc, mark_or_rebuild_in_progress); + + if (_inject_evacuation_failure_for_current_gc) { + select_evac_failure_regions(); + } } } diff --git a/src/hotspot/share/gc/g1/g1YoungGCEvacFailureInjector.hpp b/src/hotspot/share/gc/g1/g1YoungGCEvacFailureInjector.hpp index eb0d4598c14fe49e3b401abcd048eab44bb11de4..aff61c4035d3e766f485718fe6bf51578e93fa86 100644 --- a/src/hotspot/share/gc/g1/g1YoungGCEvacFailureInjector.hpp +++ b/src/hotspot/share/gc/g1/g1YoungGCEvacFailureInjector.hpp @@ -56,11 +56,17 @@ class G1YoungGCEvacFailureInjector { // Used to determine whether evacuation failure injection should be in effect // for the current GC. size_t _last_collection_with_evacuation_failure; + + // Records the regions that will fail evacuation. + CHeapBitMap _evac_failure_regions; #endif bool arm_if_needed_for_gc_type(bool for_young_gc, bool during_concurrent_start, bool mark_or_rebuild_in_progress) EVAC_FAILURE_INJECTOR_RETURN_( return false; ); + + // Selects the regions that will fail evacuation by G1EvacuationFailureALotCSetPercent. + void select_evac_failure_regions() EVAC_FAILURE_INJECTOR_RETURN; public: // Arm the evacuation failure injector if needed for the current @@ -69,7 +75,7 @@ public: // Return true if it's time to cause an evacuation failure; the caller // provides the (preferably thread-local) counter to minimize performance impact. - bool evacuation_should_fail(size_t& counter) EVAC_FAILURE_INJECTOR_RETURN_( return false; ); + bool evacuation_should_fail(size_t& counter, uint region_idx) EVAC_FAILURE_INJECTOR_RETURN_( return false; ); // Reset the evacuation failure injection counters. Should be called at // the end of an evacuation pause in which an evacuation failure occurred. diff --git a/src/hotspot/share/gc/g1/g1YoungGCEvacFailureInjector.inline.hpp b/src/hotspot/share/gc/g1/g1YoungGCEvacFailureInjector.inline.hpp index e259fc6137650408729634b8b373ebeca9a80a60..90d64056b83e25f9e3549676765797a6eb144a5b 100644 --- a/src/hotspot/share/gc/g1/g1YoungGCEvacFailureInjector.inline.hpp +++ b/src/hotspot/share/gc/g1/g1YoungGCEvacFailureInjector.inline.hpp @@ -32,10 +32,13 @@ #if EVAC_FAILURE_INJECTOR -inline bool G1YoungGCEvacFailureInjector::evacuation_should_fail(size_t& counter) { +inline bool G1YoungGCEvacFailureInjector::evacuation_should_fail(size_t& counter, uint region_idx) { if (!_inject_evacuation_failure_for_current_gc) { return false; } + if (!_evac_failure_regions.at(region_idx)) { + return false; + } if (++counter < G1EvacuationFailureALotCount) { return false; } diff --git a/src/hotspot/share/gc/g1/g1YoungGCPostEvacuateTasks.cpp b/src/hotspot/share/gc/g1/g1YoungGCPostEvacuateTasks.cpp index 2df06a5e3246f5fe940f11b4f0058d8d931287f9..f8e260e21e69d3368c0c5b20949b6d59d9c859e3 100644 --- a/src/hotspot/share/gc/g1/g1YoungGCPostEvacuateTasks.cpp +++ b/src/hotspot/share/gc/g1/g1YoungGCPostEvacuateTasks.cpp @@ -82,7 +82,7 @@ public: class G1SampleCollectionSetCandidatesClosure : public HeapRegionClosure { public: - G1CardSetMemoryStats _total; + G1SegmentedArrayMemoryStats _total; bool do_heap_region(HeapRegion* r) override { _total.add(r->rem_set()->card_set_memory_stats()); diff --git a/src/hotspot/share/gc/g1/g1_globals.hpp b/src/hotspot/share/gc/g1/g1_globals.hpp index ed71b6d45b2802d8ef89105de103cb3d474cc812..40334fc5f1054be48ea70e6f51f588841fc97d1a 100644 --- a/src/hotspot/share/gc/g1/g1_globals.hpp +++ b/src/hotspot/share/gc/g1/g1_globals.hpp @@ -73,7 +73,13 @@ \ product(bool, G1EvacuationFailureALotDuringMixedGC, true, \ "Force use of evacuation failure handling during mixed " \ - "evacuation pauses") + "evacuation pauses") \ + \ + product(uint, G1EvacuationFailureALotCSetPercent, 100, \ + "The percentage of regions in the collection set starting " \ + "from the beginning where the forced evacuation failure " \ + "injection will be applied.") \ + range(1, 100) #else #define GC_G1_EVACUATION_FAILURE_FLAGS(develop, \ develop_pd, \ diff --git a/src/hotspot/share/gc/g1/heapRegion.cpp b/src/hotspot/share/gc/g1/heapRegion.cpp index 78ca4ad8bf97fcdea9536075b6bdb198539ba49f..ef48692c1e574ad3194f62763b9e77a3c580084a 100644 --- a/src/hotspot/share/gc/g1/heapRegion.cpp +++ b/src/hotspot/share/gc/g1/heapRegion.cpp @@ -91,7 +91,7 @@ void HeapRegion::setup_heap_region_size(size_t max_heap_size) { GrainWords = GrainBytes >> LogHeapWordSize; guarantee(CardsPerRegion == 0, "we should only set it once"); - CardsPerRegion = GrainBytes >> G1CardTable::card_shift; + CardsPerRegion = GrainBytes >> G1CardTable::card_shift(); LogCardsPerRegion = log2i(CardsPerRegion); @@ -214,8 +214,6 @@ void HeapRegion::set_continues_humongous(HeapRegion* first_hr) { report_region_type_change(G1HeapRegionTraceType::ContinuesHumongous); _type.set_continues_humongous(); _humongous_start_region = first_hr; - - _bot_part.set_object_can_span(true); } void HeapRegion::clear_humongous() { @@ -223,8 +221,6 @@ void HeapRegion::clear_humongous() { assert(capacity() == HeapRegion::GrainBytes, "pre-condition"); _humongous_start_region = NULL; - - _bot_part.set_object_can_span(false); } HeapRegion::HeapRegion(uint hrm_index, @@ -659,6 +655,8 @@ void HeapRegion::verify(VerifyOption vo, VerifyLiveClosure vl_cl(g1h, vo); VerifyRemSetClosure vr_cl(g1h, vo); bool is_region_humongous = is_humongous(); + // We cast p to an oop, so region-bottom must be an obj-start. + assert(!is_region_humongous || is_starts_humongous(), "invariant"); size_t object_num = 0; while (p < top()) { oop obj = cast_to_oop(p); @@ -740,11 +738,6 @@ void HeapRegion::verify(VerifyOption vo, verify_strong_code_roots(vo, failures); } -void HeapRegion::verify() const { - bool dummy = false; - verify(VerifyOption_G1UsePrevMarking, /* failures */ &dummy); -} - void HeapRegion::verify_rem_set(VerifyOption vo, bool* failures) const { G1CollectedHeap* g1h = G1CollectedHeap::heap(); *failures = false; diff --git a/src/hotspot/share/gc/g1/heapRegion.hpp b/src/hotspot/share/gc/g1/heapRegion.hpp index 2317861388a7f9e95333a38e4ebd2c865df88386..5c16fa57ff192a2c392b8839bbcf2db060ba5711 100644 --- a/src/hotspot/share/gc/g1/heapRegion.hpp +++ b/src/hotspot/share/gc/g1/heapRegion.hpp @@ -38,7 +38,6 @@ #include "utilities/macros.hpp" class G1CardSetConfiguration; -class G1CardSetMemoryManager; class G1CollectedHeap; class G1CMBitMap; class G1Predictions; @@ -619,9 +618,6 @@ public: // full GC. void verify(VerifyOption vo, bool *failures) const; - // Verify using the "prev" marking information - void verify() const; - void verify_rem_set(VerifyOption vo, bool *failures) const; void verify_rem_set() const; }; diff --git a/src/hotspot/share/gc/g1/heapRegion.inline.hpp b/src/hotspot/share/gc/g1/heapRegion.inline.hpp index 120715562ab6f4dee618faa8160e7de852c84294..5159a818debe3bc7a05876562b7924fab65ae8aa 100644 --- a/src/hotspot/share/gc/g1/heapRegion.inline.hpp +++ b/src/hotspot/share/gc/g1/heapRegion.inline.hpp @@ -104,12 +104,8 @@ inline bool HeapRegion::is_obj_dead_with_size(const oop obj, const G1CMBitMap* c } inline bool HeapRegion::block_is_obj(const HeapWord* p) const { - G1CollectedHeap* g1h = G1CollectedHeap::heap(); - - if (!this->is_in(p)) { - assert(is_continues_humongous(), "This case can only happen for humongous regions"); - return (p == humongous_start_region()->bottom()); - } + assert(p >= bottom() && p < top(), "precondition"); + assert(!is_continues_humongous(), "p must point to block-start"); // When class unloading is enabled it is not safe to only consider top() to conclude if the // given pointer is a valid object. The situation can occur both for class unloading in a // Full GC and during a concurrent cycle. @@ -118,9 +114,9 @@ inline bool HeapRegion::block_is_obj(const HeapWord* p) const { // During a concurrent cycle class unloading is done after marking is complete and objects // for the unloaded classes will be stale until the regions are collected. if (ClassUnloading) { - return !g1h->is_obj_dead(cast_to_oop(p), this); + return !G1CollectedHeap::heap()->is_obj_dead(cast_to_oop(p), this); } - return p < top(); + return true; } inline size_t HeapRegion::block_size_using_bitmap(const HeapWord* addr, const G1CMBitMap* const prev_bitmap) const { diff --git a/src/hotspot/share/gc/g1/heapRegionRemSet.cpp b/src/hotspot/share/gc/g1/heapRegionRemSet.cpp index a0e740ad26790864477f942051f232bb20df36d6..d4570173f0e733be32b87032e999940f92fcc00b 100644 --- a/src/hotspot/share/gc/g1/heapRegionRemSet.cpp +++ b/src/hotspot/share/gc/g1/heapRegionRemSet.cpp @@ -60,7 +60,7 @@ void HeapRegionRemSet::initialize(MemRegion reserved) { vm_exit_during_initialization("Can not represent all cards in a card region within uint."); } - _split_card_shift = CardBitsWithinCardRegion + CardTable::card_shift; + _split_card_shift = CardBitsWithinCardRegion + CardTable::card_shift(); _split_card_mask = ((size_t)1 << _split_card_shift) - 1; // Check if the card region/region within cards combination can cover the heap. @@ -81,7 +81,7 @@ HeapRegionRemSet::HeapRegionRemSet(HeapRegion* hr, G1CardSetConfiguration* config) : _m(Mutex::service - 1, FormatBuffer<128>("HeapRegionRemSet#%u_lock", hr->hrm_index())), _code_roots(), - _card_set_mm(config, G1CardSetFreePool::free_list_pool()), + _card_set_mm(config, G1SegmentedArrayFreePool::free_list_pool()), _card_set(config, &_card_set_mm), _hr(hr), _state(Untracked) { } @@ -105,6 +105,10 @@ void HeapRegionRemSet::clear_locked(bool only_cardset) { assert(occupied() == 0, "Should be clear."); } +G1SegmentedArrayMemoryStats HeapRegionRemSet::card_set_memory_stats() const { + return _card_set_mm.memory_stats(); +} + void HeapRegionRemSet::print_static_mem_size(outputStream* out) { out->print_cr(" Static structures = " SIZE_FORMAT, HeapRegionRemSet::static_mem_size()); } diff --git a/src/hotspot/share/gc/g1/heapRegionRemSet.hpp b/src/hotspot/share/gc/g1/heapRegionRemSet.hpp index 958d6fceaf18920700779d30429f1c62df79b4d5..2a1b3c5527be9ba4d073557ee41035fe0bcec228 100644 --- a/src/hotspot/share/gc/g1/heapRegionRemSet.hpp +++ b/src/hotspot/share/gc/g1/heapRegionRemSet.hpp @@ -33,6 +33,7 @@ #include "runtime/safepoint.hpp" #include "utilities/bitMap.hpp" +class G1CardSetMemoryManager; class outputStream; class HeapRegionRemSet : public CHeapObj { @@ -125,7 +126,7 @@ public: void clear(bool only_cardset = false); void clear_locked(bool only_cardset = false); - G1CardSetMemoryStats card_set_memory_stats() const { return _card_set_mm.memory_stats(); } + G1SegmentedArrayMemoryStats card_set_memory_stats() const; // The actual # of bytes this hr_remset takes up. Also includes the strong code // root set. diff --git a/src/hotspot/share/gc/g1/heapRegionRemSet.inline.hpp b/src/hotspot/share/gc/g1/heapRegionRemSet.inline.hpp index fc7da0994e48dfa41fb30f20cfef0cdaca8a78fe..cd48da2a5bfec71c3bcbae36eb815deced4a3172 100644 --- a/src/hotspot/share/gc/g1/heapRegionRemSet.inline.hpp +++ b/src/hotspot/share/gc/g1/heapRegionRemSet.inline.hpp @@ -110,7 +110,7 @@ template inline void HeapRegionRemSet::iterate_for_merge(CardOrRangeVisitor& cl) { G1HeapRegionRemSetMergeCardClosure cl2(&_card_set, cl, - _card_set.config()->log2_card_region_per_heap_region(), + _card_set.config()->log2_card_regions_per_heap_region(), _card_set.config()->log2_cards_per_card_region()); _card_set.iterate_containers(&cl2, true /* at_safepoint */); } @@ -118,7 +118,7 @@ inline void HeapRegionRemSet::iterate_for_merge(CardOrRangeVisitor& cl) { void HeapRegionRemSet::split_card(OopOrNarrowOopStar from, uint& card_region, uint& card_within_region) const { size_t offset = pointer_delta(from, _heap_base_address, 1); card_region = (uint)(offset >> _split_card_shift); - card_within_region = (uint)((offset & _split_card_mask) >> CardTable::card_shift); + card_within_region = (uint)((offset & _split_card_mask) >> CardTable::card_shift()); assert(card_within_region < ((uint)1 << G1CardSetContainer::LogCardsPerRegionLimit), "must be"); } @@ -129,7 +129,7 @@ void HeapRegionRemSet::add_reference(OopOrNarrowOopStar from, uint tid) { } uint cur_idx = _hr->hrm_index(); - uintptr_t from_card = uintptr_t(from) >> CardTable::card_shift; + uintptr_t from_card = uintptr_t(from) >> CardTable::card_shift(); if (G1FromCardCache::contains_or_replace(tid, cur_idx, from_card)) { // We can't check whether the card is in the remembered set - the card container diff --git a/src/hotspot/share/gc/parallel/objectStartArray.cpp b/src/hotspot/share/gc/parallel/objectStartArray.cpp index e75a1efa734370796fc031ce1c944ad0052b6ffb..827ff73fb58c0f57d4cb32376e93a5bcad3490e3 100644 --- a/src/hotspot/share/gc/parallel/objectStartArray.cpp +++ b/src/hotspot/share/gc/parallel/objectStartArray.cpp @@ -31,26 +31,26 @@ #include "services/memTracker.hpp" #include "utilities/align.hpp" -uint ObjectStartArray::block_shift = 0; -uint ObjectStartArray::block_size = 0; -uint ObjectStartArray::block_size_in_words = 0; +uint ObjectStartArray::_card_shift = 0; +uint ObjectStartArray::_card_size = 0; +uint ObjectStartArray::_card_size_in_words = 0; void ObjectStartArray::initialize_block_size(uint card_shift) { - block_shift = card_shift; - block_size = 1 << block_shift; - block_size_in_words = block_size / sizeof(HeapWord); + _card_shift = card_shift; + _card_size = 1 << _card_shift; + _card_size_in_words = _card_size / sizeof(HeapWord); } void ObjectStartArray::initialize(MemRegion reserved_region) { // We're based on the assumption that we use the same // size blocks as the card table. - assert((int)block_size == (int)CardTable::card_size, "Sanity"); - assert(block_size <= MaxBlockSize, "block_size must be less than or equal to " UINT32_FORMAT, MaxBlockSize); + assert(_card_size == CardTable::card_size(), "Sanity"); + assert(_card_size <= MaxBlockSize, "block_size must be less than or equal to " UINT32_FORMAT, MaxBlockSize); // Calculate how much space must be reserved _reserved_region = reserved_region; - size_t bytes_to_reserve = reserved_region.word_size() / block_size_in_words; + size_t bytes_to_reserve = reserved_region.word_size() / _card_size_in_words; assert(bytes_to_reserve > 0, "Sanity"); bytes_to_reserve = @@ -65,20 +65,12 @@ void ObjectStartArray::initialize(MemRegion reserved_region) { MemTracker::record_virtual_memory_type((address)backing_store.base(), mtGC); // We do not commit any memory initially - if (!_virtual_space.initialize(backing_store, 0)) { - vm_exit_during_initialization("Could not commit space for ObjectStartArray"); - } + _virtual_space.initialize(backing_store); _raw_base = (jbyte*)_virtual_space.low_boundary(); + assert(_raw_base != nullptr, "set from the backing_store"); - if (_raw_base == NULL) { - vm_exit_during_initialization("Could not get raw_base address"); - } - - MemTracker::record_virtual_memory_type((address)_raw_base, mtGC); - - - _offset_base = _raw_base - (size_t(reserved_region.start()) >> block_shift); + _offset_base = _raw_base - (size_t(reserved_region.start()) >> _card_shift); _covered_region.set_start(reserved_region.start()); _covered_region.set_word_size(0); @@ -93,10 +85,10 @@ void ObjectStartArray::set_covered_region(MemRegion mr) { HeapWord* low_bound = mr.start(); HeapWord* high_bound = mr.end(); - assert((uintptr_t(low_bound) & (block_size - 1)) == 0, "heap must start at block boundary"); - assert((uintptr_t(high_bound) & (block_size - 1)) == 0, "heap must end at block boundary"); + assert((uintptr_t(low_bound) & (_card_size - 1)) == 0, "heap must start at block boundary"); + assert((uintptr_t(high_bound) & (_card_size - 1)) == 0, "heap must end at block boundary"); - size_t requested_blocks_size_in_bytes = mr.word_size() / block_size_in_words; + size_t requested_blocks_size_in_bytes = mr.word_size() / _card_size_in_words; // Only commit memory in page sized chunks requested_blocks_size_in_bytes = diff --git a/src/hotspot/share/gc/parallel/objectStartArray.hpp b/src/hotspot/share/gc/parallel/objectStartArray.hpp index 02c91d20ded3c2b9bac53059c934a2b90d517ab9..be91b51cd9432c40b4f3681de8b0dfffe3c5578d 100644 --- a/src/hotspot/share/gc/parallel/objectStartArray.hpp +++ b/src/hotspot/share/gc/parallel/objectStartArray.hpp @@ -41,21 +41,22 @@ class ObjectStartArray : public CHeapObj { private: PSVirtualSpace _virtual_space; MemRegion _reserved_region; + // The committed (old-gen heap) virtual space this object-start-array covers. MemRegion _covered_region; MemRegion _blocks_region; jbyte* _raw_base; jbyte* _offset_base; + static uint _card_shift; + static uint _card_size; + static uint _card_size_in_words; + public: enum BlockValueConstants { clean_block = -1 }; - static uint block_shift; - static uint block_size; - static uint block_size_in_words; - // Maximum size an offset table entry can cover. This maximum is derived from that // we need an extra bit for possible offsets in the byte for backskip values, leaving 2^7 possible offsets. // Minimum object alignment is 8 bytes (2^3), so we can at most represent 2^10 offsets within a BOT value. @@ -64,13 +65,24 @@ class ObjectStartArray : public CHeapObj { // Initialize block size based on card size static void initialize_block_size(uint card_shift); + static uint card_shift() { + return _card_shift; + } + + static uint card_size() { + return _card_size; + } + static uint card_size_in_words() { + return _card_size_in_words; + } + protected: // Mapping from address to object start array entry jbyte* block_for_addr(void* p) const { assert(_covered_region.contains(p), "out of bounds access to object start array"); - jbyte* result = &_offset_base[uintptr_t(p) >> block_shift]; + jbyte* result = &_offset_base[uintptr_t(p) >> _card_shift]; assert(_blocks_region.contains(result), "out of bounds result in byte_for"); return result; @@ -81,7 +93,7 @@ class ObjectStartArray : public CHeapObj { assert(_blocks_region.contains(p), "out of bounds access to object start array"); size_t delta = pointer_delta(p, _offset_base, sizeof(jbyte)); - HeapWord* result = (HeapWord*) (delta << block_shift); + HeapWord* result = (HeapWord*) (delta << _card_shift); assert(_covered_region.contains(result), "out of bounds accessor from card marking array"); return result; @@ -104,7 +116,7 @@ class ObjectStartArray : public CHeapObj { } size_t delta = pointer_delta(p, _offset_base, sizeof(jbyte)); - HeapWord* result = (HeapWord*) (delta << block_shift); + HeapWord* result = (HeapWord*) (delta << _card_shift); result += *p; assert(_covered_region.contains(result), diff --git a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp index d0c1f29bd97bbca3221de369326753a201cb4a2e..3a4774d15ca5f523265c3bbbe1d23d27618ffc07 100644 --- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp +++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp @@ -645,8 +645,10 @@ void ParallelScavengeHeap::prepare_for_verify() { PSHeapSummary ParallelScavengeHeap::create_ps_heap_summary() { PSOldGen* old = old_gen(); HeapWord* old_committed_end = (HeapWord*)old->virtual_space()->committed_high_addr(); - VirtualSpaceSummary old_summary(old->reserved().start(), old_committed_end, old->reserved().end()); - SpaceSummary old_space(old->reserved().start(), old_committed_end, old->used_in_bytes()); + HeapWord* old_reserved_start = old->reserved().start(); + HeapWord* old_reserved_end = old->reserved().end(); + VirtualSpaceSummary old_summary(old_reserved_start, old_committed_end, old_reserved_end); + SpaceSummary old_space(old_reserved_start, old_committed_end, old->used_in_bytes()); PSYoungGen* young = young_gen(); VirtualSpaceSummary young_summary(young->reserved().start(), diff --git a/src/hotspot/share/gc/parallel/psOldGen.cpp b/src/hotspot/share/gc/parallel/psOldGen.cpp index 4f689ec72518bc156cbb9e8f3051cb6b80cda26f..591341af8619c515c3754d3c42f4d07bdd3c2789 100644 --- a/src/hotspot/share/gc/parallel/psOldGen.cpp +++ b/src/hotspot/share/gc/parallel/psOldGen.cpp @@ -50,10 +50,6 @@ void PSOldGen::initialize(ReservedSpace rs, size_t initial_size, size_t alignmen initialize_virtual_space(rs, initial_size, alignment); initialize_work(perf_data_name, level); - // The old gen can grow to max_gen_size(). _reserve reflects only - // the current maximum that can be committed. - assert(_reserved.byte_size() <= max_gen_size(), "Consistency check"); - initialize_performance_counters(perf_data_name, level); } @@ -69,66 +65,51 @@ void PSOldGen::initialize_virtual_space(ReservedSpace rs, } void PSOldGen::initialize_work(const char* perf_data_name, int level) { - // - // Basic memory initialization - // - - MemRegion limit_reserved((HeapWord*)virtual_space()->low_boundary(), - heap_word_size(max_gen_size())); - assert(limit_reserved.byte_size() == max_gen_size(), - "word vs bytes confusion"); - // - // Object start stuff - // + MemRegion const reserved_mr = reserved(); + assert(reserved_mr.byte_size() == max_gen_size(), "invariant"); - start_array()->initialize(limit_reserved); + // Object start stuff: for all reserved memory + start_array()->initialize(reserved_mr); - _reserved = MemRegion((HeapWord*)virtual_space()->low_boundary(), - (HeapWord*)virtual_space()->high_boundary()); + // Card table stuff: for all committed memory + MemRegion committed_mr((HeapWord*)virtual_space()->low(), + (HeapWord*)virtual_space()->high()); - // - // Card table stuff - // - - MemRegion cmr((HeapWord*)virtual_space()->low(), - (HeapWord*)virtual_space()->high()); if (ZapUnusedHeapArea) { // Mangle newly committed space immediately rather than // waiting for the initialization of the space even though // mangling is related to spaces. Doing it here eliminates // the need to carry along information that a complete mangling // (bottom to end) needs to be done. - SpaceMangler::mangle_region(cmr); + SpaceMangler::mangle_region(committed_mr); } ParallelScavengeHeap* heap = ParallelScavengeHeap::heap(); PSCardTable* ct = heap->card_table(); - ct->resize_covered_region(cmr); + ct->resize_covered_region(committed_mr); // Verify that the start and end of this generation is the start of a card. // If this wasn't true, a single card could span more than one generation, // which would cause problems when we commit/uncommit memory, and when we // clear and dirty cards. - guarantee(ct->is_card_aligned(_reserved.start()), "generation must be card aligned"); - if (_reserved.end() != heap->reserved_region().end()) { - // Don't check at the very end of the heap as we'll assert that we're probing off - // the end if we try. - guarantee(ct->is_card_aligned(_reserved.end()), "generation must be card aligned"); - } + guarantee(ct->is_card_aligned(reserved_mr.start()), "generation must be card aligned"); + // Check the heap layout documented at `class ParallelScavengeHeap`. + assert(reserved_mr.end() != heap->reserved_region().end(), "invariant"); + guarantee(ct->is_card_aligned(reserved_mr.end()), "generation must be card aligned"); // // ObjectSpace stuff // _object_space = new MutableSpace(virtual_space()->alignment()); - object_space()->initialize(cmr, + object_space()->initialize(committed_mr, SpaceDecorator::Clear, SpaceDecorator::Mangle, MutableSpace::SetupPages, &ParallelScavengeHeap::heap()->workers()); // Update the start_array - start_array()->set_covered_region(cmr); + start_array()->set_covered_region(committed_mr); } void PSOldGen::initialize_performance_counters(const char* perf_data_name, int level) { @@ -152,7 +133,7 @@ size_t PSOldGen::num_iterable_blocks() const { void PSOldGen::object_iterate_block(ObjectClosure* cl, size_t block_index) { size_t block_word_size = IterateBlockSize / HeapWordSize; - assert((block_word_size % (ObjectStartArray::block_size)) == 0, + assert((block_word_size % (ObjectStartArray::card_size())) == 0, "Block size not a multiple of start_array block"); MutableSpace *space = object_space(); @@ -314,7 +295,6 @@ void PSOldGen::resize(size_t desired_free_space) { // Adjust according to our min and max new_size = clamp(new_size, min_gen_size(), max_gen_size()); - assert(max_gen_size() >= reserved().byte_size(), "max new size problem?"); new_size = align_up(new_size, alignment); const size_t current_size = capacity_in_bytes(); @@ -400,12 +380,11 @@ void PSOldGen::verify() { } class VerifyObjectStartArrayClosure : public ObjectClosure { - PSOldGen* _old_gen; ObjectStartArray* _start_array; public: - VerifyObjectStartArrayClosure(PSOldGen* old_gen, ObjectStartArray* start_array) : - _old_gen(old_gen), _start_array(start_array) { } + VerifyObjectStartArrayClosure(ObjectStartArray* start_array) : + _start_array(start_array) { } virtual void do_object(oop obj) { HeapWord* test_addr = cast_from_oop(obj) + 1; @@ -415,7 +394,7 @@ class VerifyObjectStartArrayClosure : public ObjectClosure { }; void PSOldGen::verify_object_start_array() { - VerifyObjectStartArrayClosure check( this, &_start_array ); + VerifyObjectStartArrayClosure check(&_start_array); object_iterate(&check); } diff --git a/src/hotspot/share/gc/parallel/psOldGen.hpp b/src/hotspot/share/gc/parallel/psOldGen.hpp index 53947a948984caffa548ba7dfb3880599dc96d5f..713098056c6d9939d3a5ecfc9f5b903ee78c52cb 100644 --- a/src/hotspot/share/gc/parallel/psOldGen.hpp +++ b/src/hotspot/share/gc/parallel/psOldGen.hpp @@ -34,9 +34,7 @@ class PSOldGen : public CHeapObj { friend class VMStructs; - private: - MemRegion _reserved; // Used for simple containment tests PSVirtualSpace* _virtual_space; // Controls mapping and unmapping of virtual mem ObjectStartArray _start_array; // Keeps track of where objects start in a 512b block MutableSpace* _object_space; // Where all the objects live @@ -99,16 +97,20 @@ class PSOldGen : public CHeapObj { PSOldGen(ReservedSpace rs, size_t initial_size, size_t min_size, size_t max_size, const char* perf_data_name, int level); - MemRegion reserved() const { return _reserved; } + MemRegion reserved() const { + return MemRegion((HeapWord*)(_virtual_space->low_boundary()), + (HeapWord*)(_virtual_space->high_boundary())); + } + size_t max_gen_size() const { return _max_gen_size; } size_t min_gen_size() const { return _min_gen_size; } bool is_in(const void* p) const { - return _virtual_space->contains((void *)p); + return _virtual_space->is_in_committed((void *)p); } bool is_in_reserved(const void* p) const { - return reserved().contains(p); + return _virtual_space->is_in_reserved(p); } MutableSpace* object_space() const { return _object_space; } diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.cpp b/src/hotspot/share/gc/parallel/psParallelCompact.cpp index 2a3d95192b6df19b9bfe7d65ac60efa75194db89..a28ebbf1510f11e7b68b6bfcdf857d387cba6731 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp @@ -1041,9 +1041,9 @@ void PSParallelCompact::post_compact() PSCardTable* ct = heap->card_table(); MemRegion old_mr = heap->old_gen()->reserved(); if (young_gen_empty) { - ct->clear(MemRegion(old_mr.start(), old_mr.end())); + ct->clear(old_mr); } else { - ct->invalidate(MemRegion(old_mr.start(), old_mr.end())); + ct->invalidate(old_mr); } // Delete metaspaces for unloaded class loaders and clean up loader_data graph diff --git a/src/hotspot/share/gc/parallel/psPromotionLAB.hpp b/src/hotspot/share/gc/parallel/psPromotionLAB.hpp index e51852f8a6e962f10d7fc659625e4ea1300aba9e..eb2cad171e5f6d32808886f0d32f450f8ab6a36d 100644 --- a/src/hotspot/share/gc/parallel/psPromotionLAB.hpp +++ b/src/hotspot/share/gc/parallel/psPromotionLAB.hpp @@ -106,7 +106,6 @@ class PSOldPromotionLAB : public PSPromotionLAB { public: PSOldPromotionLAB() : _start_array(NULL) { } - PSOldPromotionLAB(ObjectStartArray* start_array) : _start_array(start_array) { } void set_start_array(ObjectStartArray* start_array) { _start_array = start_array; } diff --git a/src/hotspot/share/gc/parallel/psVirtualspace.cpp b/src/hotspot/share/gc/parallel/psVirtualspace.cpp index 473a1f268545196e82bfb64128ba6cd39b3fb9f4..07f278c068baab6b0c2fb026dc0fb2208f57772b 100644 --- a/src/hotspot/share/gc/parallel/psVirtualspace.cpp +++ b/src/hotspot/share/gc/parallel/psVirtualspace.cpp @@ -56,27 +56,16 @@ PSVirtualSpace::PSVirtualSpace(): } // Deprecated. -bool PSVirtualSpace::initialize(ReservedSpace rs, - size_t commit_size) { +void PSVirtualSpace::initialize(ReservedSpace rs) { set_reserved(rs); set_committed(reserved_low_addr(), reserved_low_addr()); - - // Commit to initial size. - assert(commit_size <= rs.size(), "commit_size too big"); - bool result = commit_size > 0 ? expand_by(commit_size) : true; DEBUG_ONLY(verify()); - return result; } PSVirtualSpace::~PSVirtualSpace() { release(); } -bool PSVirtualSpace::contains(void* p) const { - char* const cp = (char*)p; - return cp >= committed_low_addr() && cp < committed_high_addr(); -} - void PSVirtualSpace::release() { DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this)); // This may not release memory it didn't reserve. @@ -121,67 +110,6 @@ bool PSVirtualSpace::shrink_by(size_t bytes) { return result; } -size_t -PSVirtualSpace::expand_into(PSVirtualSpace* other_space, size_t bytes) { - assert(is_aligned(bytes), "arg not aligned"); - assert(grows_up(), "this space must grow up"); - assert(other_space->grows_down(), "other space must grow down"); - assert(reserved_high_addr() == other_space->reserved_low_addr(), - "spaces not contiguous"); - assert(special() == other_space->special(), "one space is special, the other is not"); - DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this)); - DEBUG_ONLY(PSVirtualSpaceVerifier other_verifier(other_space)); - - size_t bytes_needed = bytes; - - // First use the uncommitted region in this space. - size_t tmp_bytes = MIN2(uncommitted_size(), bytes_needed); - if (tmp_bytes > 0) { - if (expand_by(tmp_bytes)) { - bytes_needed -= tmp_bytes; - } else { - return 0; - } - } - - // Next take from the uncommitted region in the other space, and commit it. - tmp_bytes = MIN2(other_space->uncommitted_size(), bytes_needed); - if (tmp_bytes > 0) { - char* const commit_base = committed_high_addr(); - if (other_space->special() || - os::commit_memory(commit_base, tmp_bytes, alignment(), !ExecMem)) { - // Reduce the reserved region in the other space. - other_space->set_reserved(other_space->reserved_low_addr() + tmp_bytes, - other_space->reserved_high_addr(), - other_space->special()); - - // Grow both reserved and committed in this space. - _reserved_high_addr += tmp_bytes; - _committed_high_addr += tmp_bytes; - bytes_needed -= tmp_bytes; - } else { - return bytes - bytes_needed; - } - } - - // Finally take from the already committed region in the other space. - tmp_bytes = bytes_needed; - if (tmp_bytes > 0) { - // Reduce both committed and reserved in the other space. - other_space->set_committed(other_space->committed_low_addr() + tmp_bytes, - other_space->committed_high_addr()); - other_space->set_reserved(other_space->reserved_low_addr() + tmp_bytes, - other_space->reserved_high_addr(), - other_space->special()); - - // Grow both reserved and committed in this space. - _reserved_high_addr += tmp_bytes; - _committed_high_addr += tmp_bytes; - } - - return bytes; -} - #ifndef PRODUCT bool PSVirtualSpace::is_aligned(size_t value, size_t align) { const size_t tmp_value = value + align - 1; @@ -210,13 +138,9 @@ void PSVirtualSpace::verify() const { "bad reserved addrs"); assert(committed_low_addr() <= committed_high_addr(), "bad committed addrs"); - if (grows_up()) { - assert(reserved_low_addr() == committed_low_addr(), "bad low addrs"); - assert(reserved_high_addr() >= committed_high_addr(), "bad high addrs"); - } else { - assert(reserved_high_addr() == committed_high_addr(), "bad high addrs"); - assert(reserved_low_addr() <= committed_low_addr(), "bad low addrs"); - } + // committed addr grows up + assert(reserved_low_addr() == committed_low_addr(), "bad low addrs"); + assert(reserved_high_addr() >= committed_high_addr(), "bad high addrs"); } #endif // #ifndef PRODUCT diff --git a/src/hotspot/share/gc/parallel/psVirtualspace.hpp b/src/hotspot/share/gc/parallel/psVirtualspace.hpp index 853264ed62d7a23b702cb853ca5df88af7f329f2..6c2ffeed53a10343be7b73e10427651188bc1e14 100644 --- a/src/hotspot/share/gc/parallel/psVirtualspace.hpp +++ b/src/hotspot/share/gc/parallel/psVirtualspace.hpp @@ -73,9 +73,15 @@ class PSVirtualSpace : public CHeapObj { _special(false) { } PSVirtualSpace(); - bool initialize(ReservedSpace rs, size_t commit_size); + void initialize(ReservedSpace rs); - bool contains(void* p) const; + bool is_in_committed(const void* p) const { + return (p >= committed_low_addr()) && (p < committed_high_addr()); + } + + bool is_in_reserved(const void* p) const { + return (p >= reserved_low_addr()) && (p < reserved_high_addr()); + } // Accessors (all sizes are bytes). size_t alignment() const { return _alignment; } @@ -85,6 +91,7 @@ class PSVirtualSpace : public CHeapObj { char* committed_high_addr() const { return _committed_high_addr; } bool special() const { return _special; } + // Return size in bytes inline size_t committed_size() const; inline size_t reserved_size() const; inline size_t uncommitted_size() const; @@ -95,7 +102,6 @@ class PSVirtualSpace : public CHeapObj { inline void set_committed(char* low_addr, char* high_addr); virtual bool expand_by(size_t bytes); virtual bool shrink_by(size_t bytes); - virtual size_t expand_into(PSVirtualSpace* space, size_t bytes); void release(); #ifndef PRODUCT @@ -104,8 +110,6 @@ class PSVirtualSpace : public CHeapObj { bool is_aligned(size_t val) const; bool is_aligned(char* val) const; void verify() const; - virtual bool grows_up() const { return true; } - bool grows_down() const { return !grows_up(); } // Helper class to verify a space when entering/leaving a block. class PSVirtualSpaceVerifier: public StackObj { diff --git a/src/hotspot/share/gc/parallel/psYoungGen.hpp b/src/hotspot/share/gc/parallel/psYoungGen.hpp index 0da0592a98616c252cc09ee83cadfd59e45bbc8e..3babc311e95500622f95b74259e7e5ab6c7df7aa 100644 --- a/src/hotspot/share/gc/parallel/psYoungGen.hpp +++ b/src/hotspot/share/gc/parallel/psYoungGen.hpp @@ -90,7 +90,7 @@ class PSYoungGen : public CHeapObj { MemRegion reserved() const { return _reserved; } bool is_in(const void* p) const { - return _virtual_space->contains((void *)p); + return _virtual_space->is_in_committed(p); } bool is_in_reserved(const void* p) const { diff --git a/src/hotspot/share/gc/parallel/vmStructs_parallelgc.hpp b/src/hotspot/share/gc/parallel/vmStructs_parallelgc.hpp index 0f131687f5b18b92b14f74c88f78ffbcaef8c537..fa019aa5b429517615a58bb85385d157b826f0ef 100644 --- a/src/hotspot/share/gc/parallel/vmStructs_parallelgc.hpp +++ b/src/hotspot/share/gc/parallel/vmStructs_parallelgc.hpp @@ -57,7 +57,6 @@ nonstatic_field(PSYoungGen, _min_gen_size, const size_t) \ nonstatic_field(PSYoungGen, _max_gen_size, const size_t) \ \ - nonstatic_field(PSOldGen, _reserved, MemRegion) \ nonstatic_field(PSOldGen, _virtual_space, PSVirtualSpace*) \ nonstatic_field(PSOldGen, _object_space, MutableSpace*) \ nonstatic_field(PSOldGen, _min_gen_size, const size_t) \ diff --git a/src/hotspot/share/gc/shared/blockOffsetTable.cpp b/src/hotspot/share/gc/shared/blockOffsetTable.cpp index b7d5864920810b7498f34bd1d129c13933ec9057..e350e70ad5fd5867a0b736f74f11842f44aaf222 100644 --- a/src/hotspot/share/gc/shared/blockOffsetTable.cpp +++ b/src/hotspot/share/gc/shared/blockOffsetTable.cpp @@ -33,16 +33,16 @@ #include "runtime/java.hpp" #include "services/memTracker.hpp" -uint BOTConstants::LogN = 0; -uint BOTConstants::LogN_words = 0; -uint BOTConstants::N_bytes = 0; -uint BOTConstants::N_words = 0; +uint BOTConstants::_log_card_size = 0; +uint BOTConstants::_log_card_size_in_words = 0; +uint BOTConstants::_card_size = 0; +uint BOTConstants::_card_size_in_words = 0; void BOTConstants::initialize_bot_size(uint card_shift) { - LogN = card_shift; - LogN_words = LogN - LogHeapWordSize; - N_bytes = 1 << LogN; - N_words = 1 << LogN_words; + _log_card_size = card_shift; + _log_card_size_in_words = _log_card_size - LogHeapWordSize; + _card_size = 1 << _log_card_size; + _card_size_in_words = 1 << _log_card_size_in_words; } ////////////////////////////////////////////////////////////////////// @@ -99,7 +99,7 @@ void BlockOffsetSharedArray::resize(size_t new_word_size) { bool BlockOffsetSharedArray::is_card_boundary(HeapWord* p) const { assert(p >= _reserved.start(), "just checking"); size_t delta = pointer_delta(p, _reserved.start()); - return (delta & right_n_bits((int)BOTConstants::LogN_words)) == (size_t)NoBits; + return (delta & right_n_bits((int)BOTConstants::log_card_size_in_words())) == (size_t)NoBits; } @@ -116,7 +116,7 @@ BlockOffsetArray::BlockOffsetArray(BlockOffsetSharedArray* array, set_init_to_zero(init_to_zero_); if (!init_to_zero_) { // initialize cards to point back to mr.start() - set_remainder_to_point_to_start(mr.start() + BOTConstants::N_words, mr.end()); + set_remainder_to_point_to_start(mr.start() + BOTConstants::card_size_in_words(), mr.end()); _array->set_offset_array(0, 0); // set first card to 0 } } @@ -172,7 +172,7 @@ set_remainder_to_point_to_start(HeapWord* start, HeapWord* end, bool reducing) { size_t start_card = _array->index_for(start); size_t end_card = _array->index_for(end-1); assert(start ==_array->address_for_index(start_card), "Precondition"); - assert(end ==_array->address_for_index(end_card)+BOTConstants::N_words, "Precondition"); + assert(end ==_array->address_for_index(end_card)+BOTConstants::card_size_in_words(), "Precondition"); set_remainder_to_point_to_start_incl(start_card, end_card, reducing); // closed interval } @@ -188,7 +188,7 @@ BlockOffsetArray::set_remainder_to_point_to_start_incl(size_t start_card, size_t return; } assert(start_card > _array->index_for(_bottom), "Cannot be first card"); - assert(_array->offset_array(start_card-1) <= BOTConstants::N_words, + assert(_array->offset_array(start_card-1) <= BOTConstants::card_size_in_words(), "Offset card has an unexpected value"); size_t start_card_for_region = start_card; u_char offset = max_jubyte; @@ -197,7 +197,7 @@ BlockOffsetArray::set_remainder_to_point_to_start_incl(size_t start_card, size_t // so that the reach ends in this region and not at the start // of the next. size_t reach = start_card - 1 + (BOTConstants::power_to_cards_back(i+1) - 1); - offset = BOTConstants::N_words + i; + offset = BOTConstants::card_size_in_words() + i; if (reach >= end_card) { _array->set_offset_array(start_card_for_region, end_card, offset, reducing); start_card_for_region = reach + 1; @@ -218,13 +218,13 @@ void BlockOffsetArray::check_all_cards(size_t start_card, size_t end_card) const if (end_card < start_card) { return; } - guarantee(_array->offset_array(start_card) == BOTConstants::N_words, "Wrong value in second card"); - u_char last_entry = BOTConstants::N_words; + guarantee(_array->offset_array(start_card) == BOTConstants::card_size_in_words(), "Wrong value in second card"); + u_char last_entry = BOTConstants::card_size_in_words(); for (size_t c = start_card + 1; c <= end_card; c++ /* yeah! */) { u_char entry = _array->offset_array(c); guarantee(entry >= last_entry, "Monotonicity"); if (c - start_card > BOTConstants::power_to_cards_back(1)) { - guarantee(entry > BOTConstants::N_words, "Should be in logarithmic region"); + guarantee(entry > BOTConstants::card_size_in_words(), "Should be in logarithmic region"); } size_t backskip = BOTConstants::entry_to_cards_back(entry); size_t landing_card = c - backskip; @@ -234,7 +234,7 @@ void BlockOffsetArray::check_all_cards(size_t start_card, size_t end_card) const } else { guarantee(landing_card == (start_card - 1), "Tautology"); // Note that N_words is the maximum offset value - guarantee(_array->offset_array(landing_card) <= BOTConstants::N_words, "Offset value"); + guarantee(_array->offset_array(landing_card) <= BOTConstants::card_size_in_words(), "Offset value"); } last_entry = entry; // remember for monotonicity test } @@ -266,7 +266,7 @@ BlockOffsetArray::do_block_internal(HeapWord* blk_start, uintptr_t start_ui = (uintptr_t)blk_start; // Calculate the last card boundary preceding end of blk intptr_t boundary_before_end = (intptr_t)end_ui; - clear_bits(boundary_before_end, right_n_bits((int)BOTConstants::LogN)); + clear_bits(boundary_before_end, right_n_bits((int)BOTConstants::log_card_size())); if (start_ui <= (uintptr_t)boundary_before_end) { // blk starts at or crosses a boundary // Calculate index of card on which blk begins @@ -279,7 +279,7 @@ BlockOffsetArray::do_block_internal(HeapWord* blk_start, if (blk_start != boundary) { // blk starts strictly after boundary // adjust card boundary and start_index forward to next card - boundary += BOTConstants::N_words; + boundary += BOTConstants::card_size_in_words(); start_index++; } assert(start_index <= end_index, "monotonicity of index_for()"); @@ -296,8 +296,8 @@ BlockOffsetArray::do_block_internal(HeapWord* blk_start, // We have finished marking the "offset card". We need to now // mark the subsequent cards that this blk spans. if (start_index < end_index) { - HeapWord* rem_st = _array->address_for_index(start_index) + BOTConstants::N_words; - HeapWord* rem_end = _array->address_for_index(end_index) + BOTConstants::N_words; + HeapWord* rem_st = _array->address_for_index(start_index) + BOTConstants::card_size_in_words(); + HeapWord* rem_end = _array->address_for_index(end_index) + BOTConstants::card_size_in_words(); set_remainder_to_point_to_start(rem_st, rem_end, reducing); } break; @@ -380,22 +380,22 @@ HeapWord* BlockOffsetArrayContigSpace::block_start_unsafe(const void* addr) cons HeapWord* q = _array->address_for_index(index); uint offset = _array->offset_array(index); // Extend u_char to uint. - while (offset > BOTConstants::N_words) { + while (offset > BOTConstants::card_size_in_words()) { // The excess of the offset from N_words indicates a power of Base // to go back by. size_t n_cards_back = BOTConstants::entry_to_cards_back(offset); - q -= (BOTConstants::N_words * n_cards_back); + q -= (BOTConstants::card_size_in_words() * n_cards_back); assert(q >= _sp->bottom(), "Went below bottom!"); index -= n_cards_back; offset = _array->offset_array(index); } - while (offset == BOTConstants::N_words) { + while (offset == BOTConstants::card_size_in_words()) { assert(q >= _sp->bottom(), "Went below bottom!"); - q -= BOTConstants::N_words; + q -= BOTConstants::card_size_in_words(); index--; offset = _array->offset_array(index); } - assert(offset < BOTConstants::N_words, "offset too large"); + assert(offset < BOTConstants::card_size_in_words(), "offset too large"); q -= offset; HeapWord* n = q; @@ -428,14 +428,14 @@ void BlockOffsetArrayContigSpace::alloc_block_work(HeapWord* blk_start, "should be past threshold"); assert(blk_start <= _next_offset_threshold, "blk_start should be at or before threshold"); - assert(pointer_delta(_next_offset_threshold, blk_start) <= BOTConstants::N_words, + assert(pointer_delta(_next_offset_threshold, blk_start) <= BOTConstants::card_size_in_words(), "offset should be <= BlockOffsetSharedArray::N"); assert(_sp->is_in_reserved(blk_start), "reference must be into the space"); assert(_sp->is_in_reserved(blk_end-1), "limit must be within the space"); assert(_next_offset_threshold == - _array->_reserved.start() + _next_offset_index*BOTConstants::N_words, + _array->_reserved.start() + _next_offset_index*BOTConstants::card_size_in_words(), "index must agree with threshold"); debug_only(size_t orig_next_offset_index = _next_offset_index;) @@ -457,7 +457,7 @@ void BlockOffsetArrayContigSpace::alloc_block_work(HeapWord* blk_start, HeapWord* rem_st = _array->address_for_index(_next_offset_index + 1); // Calculate rem_end this way because end_index // may be the last valid index in the covered region. - HeapWord* rem_end = _array->address_for_index(end_index) + BOTConstants::N_words; + HeapWord* rem_end = _array->address_for_index(end_index) + BOTConstants::card_size_in_words(); set_remainder_to_point_to_start(rem_st, rem_end); } @@ -465,7 +465,7 @@ void BlockOffsetArrayContigSpace::alloc_block_work(HeapWord* blk_start, _next_offset_index = end_index + 1; // Calculate _next_offset_threshold this way because end_index // may be the last valid index in the covered region. - _next_offset_threshold = _array->address_for_index(end_index) + BOTConstants::N_words; + _next_offset_threshold = _array->address_for_index(end_index) + BOTConstants::card_size_in_words(); assert(_next_offset_threshold >= blk_end, "Incorrect offset threshold"); #ifdef ASSERT @@ -476,11 +476,11 @@ void BlockOffsetArrayContigSpace::alloc_block_work(HeapWord* blk_start, assert((_array->offset_array(orig_next_offset_index) == 0 && blk_start == boundary) || (_array->offset_array(orig_next_offset_index) > 0 && - _array->offset_array(orig_next_offset_index) <= BOTConstants::N_words), + _array->offset_array(orig_next_offset_index) <= BOTConstants::card_size_in_words()), "offset array should have been set"); for (size_t j = orig_next_offset_index + 1; j <= end_index; j++) { assert(_array->offset_array(j) > 0 && - _array->offset_array(j) <= (u_char) (BOTConstants::N_words+BOTConstants::N_powers-1), + _array->offset_array(j) <= (u_char) (BOTConstants::card_size_in_words()+BOTConstants::N_powers-1), "offset array should have been set"); } #endif diff --git a/src/hotspot/share/gc/shared/blockOffsetTable.hpp b/src/hotspot/share/gc/shared/blockOffsetTable.hpp index ff656823a6c22f294049f84618bdcafeef02aff6..7d6ddfdf79998f49a3bc40311ddb20acdac51013 100644 --- a/src/hotspot/share/gc/shared/blockOffsetTable.hpp +++ b/src/hotspot/share/gc/shared/blockOffsetTable.hpp @@ -49,12 +49,12 @@ class ContiguousSpace; class BOTConstants : public AllStatic { -public: - static uint LogN; - static uint LogN_words; - static uint N_bytes; - static uint N_words; + static uint _log_card_size; + static uint _log_card_size_in_words; + static uint _card_size; + static uint _card_size_in_words; +public: // entries "e" of at least N_words mean "go back by Base^(e-N_words)." // All entries are less than "N_words + N_powers". static const uint LogBase = 4; @@ -67,16 +67,22 @@ public: static size_t power_to_cards_back(uint i) { return (size_t)1 << (LogBase * i); } - static size_t power_to_words_back(uint i) { - return power_to_cards_back(i) * N_words; - } + static size_t entry_to_cards_back(u_char entry) { - assert(entry >= N_words, "Precondition"); - return power_to_cards_back(entry - N_words); + assert(entry >= _card_size_in_words, "Precondition"); + return power_to_cards_back(entry - _card_size_in_words); + } + static uint log_card_size() { + return _log_card_size; + } + static uint log_card_size_in_words() { + return _log_card_size_in_words; + } + static uint card_size() { + return _card_size; } - static size_t entry_to_words_back(u_char entry) { - assert(entry >= N_words, "Precondition"); - return power_to_words_back(entry - N_words); + static uint card_size_in_words() { + return _card_size_in_words; } }; @@ -98,7 +104,7 @@ public: BlockOffsetTable(HeapWord* bottom, HeapWord* end): _bottom(bottom), _end(end) { assert(_bottom <= _end, "arguments out of order"); - assert(BOTConstants::N_bytes == CardTable::card_size, "sanity"); + assert(BOTConstants::card_size() == CardTable::card_size(), "sanity"); } // Note that the committed size of the covered space may have changed, @@ -185,7 +191,7 @@ class BlockOffsetSharedArray: public CHeapObj { check_reducing_assertion(reducing); assert(index < _vs.committed_size(), "index out of range"); assert(high >= low, "addresses out of order"); - assert(pointer_delta(high, low) <= BOTConstants::N_words, "offset too large"); + assert(pointer_delta(high, low) <= BOTConstants::card_size_in_words(), "offset too large"); assert(!reducing || _offset_array[index] >= (u_char)pointer_delta(high, low), "Not reducing"); _offset_array[index] = (u_char)pointer_delta(high, low); @@ -196,7 +202,7 @@ class BlockOffsetSharedArray: public CHeapObj { assert(index_for(right - 1) < _vs.committed_size(), "right address out of range"); assert(left < right, "Heap addresses out of order"); - size_t num_cards = pointer_delta(right, left) >> BOTConstants::LogN_words; + size_t num_cards = pointer_delta(right, left) >> BOTConstants::log_card_size_in_words(); fill_range(index_for(left), num_cards, offset); } @@ -213,7 +219,7 @@ class BlockOffsetSharedArray: public CHeapObj { void check_offset_array(size_t index, HeapWord* high, HeapWord* low) const { assert(index < _vs.committed_size(), "index out of range"); assert(high >= low, "addresses out of order"); - assert(pointer_delta(high, low) <= BOTConstants::N_words, "offset too large"); + assert(pointer_delta(high, low) <= BOTConstants::card_size_in_words(), "offset too large"); assert(_offset_array[index] == pointer_delta(high, low), "Wrong offset"); } @@ -228,7 +234,7 @@ class BlockOffsetSharedArray: public CHeapObj { // to be reserved. size_t compute_size(size_t mem_region_words) { - size_t number_of_slots = (mem_region_words / BOTConstants::N_words) + 1; + size_t number_of_slots = (mem_region_words / BOTConstants::card_size_in_words()) + 1; return ReservedSpace::allocation_align_size_up(number_of_slots); } @@ -342,7 +348,7 @@ class BlockOffsetArray: public BlockOffsetTable { assert(_array->is_card_boundary(new_end), "new _end would not be a card boundary"); // set all the newly added cards - _array->set_offset_array(_end, new_end, BOTConstants::N_words); + _array->set_offset_array(_end, new_end, BOTConstants::card_size_in_words()); } _end = new_end; // update _end } diff --git a/src/hotspot/share/gc/shared/blockOffsetTable.inline.hpp b/src/hotspot/share/gc/shared/blockOffsetTable.inline.hpp index ceb852b4ffc4a5b21eb9e07e8a90dc450d908475..abaa0dade46e127723d4e3b2a916a7ab0c1ce0ef 100644 --- a/src/hotspot/share/gc/shared/blockOffsetTable.inline.hpp +++ b/src/hotspot/share/gc/shared/blockOffsetTable.inline.hpp @@ -50,14 +50,14 @@ inline size_t BlockOffsetSharedArray::index_for(const void* p) const { pc < (char*)_reserved.end(), "p not in range."); size_t delta = pointer_delta(pc, _reserved.start(), sizeof(char)); - size_t result = delta >> BOTConstants::LogN; + size_t result = delta >> BOTConstants::log_card_size(); assert(result < _vs.committed_size(), "bad index from address"); return result; } inline HeapWord* BlockOffsetSharedArray::address_for_index(size_t index) const { assert(index < _vs.committed_size(), "bad index"); - HeapWord* result = _reserved.start() + (index << BOTConstants::LogN_words); + HeapWord* result = _reserved.start() + (index << BOTConstants::log_card_size_in_words()); assert(result >= _reserved.start() && result < _reserved.end(), "bad address from index"); return result; diff --git a/src/hotspot/share/gc/shared/c1/barrierSetC1.cpp b/src/hotspot/share/gc/shared/c1/barrierSetC1.cpp index 663ff91372b5879c85ac8a326a32d6d23b934f57..b1828fcdb178a69e0187eb407e911ffcf7bc3582 100644 --- a/src/hotspot/share/gc/shared/c1/barrierSetC1.cpp +++ b/src/hotspot/share/gc/shared/c1/barrierSetC1.cpp @@ -334,7 +334,7 @@ void BarrierSetC1::generate_referent_check(LIRAccess& access, LabelObj* cont) { if (gen_type_check) { // We have determined that offset == referent_offset && src != null. // if (src->_klass->_reference_type == REF_NONE) -> continue - __ move(new LIR_Address(base_reg, oopDesc::klass_offset_in_bytes(), T_ADDRESS), src_klass); + gen->load_klass(base_reg, src_klass, NULL); LIR_Address* reference_type_addr = new LIR_Address(src_klass, in_bytes(InstanceKlass::reference_type_offset()), T_BYTE); LIR_Opr reference_type = gen->new_register(T_INT); __ move(reference_type_addr, reference_type); diff --git a/src/hotspot/share/gc/shared/c1/cardTableBarrierSetC1.cpp b/src/hotspot/share/gc/shared/c1/cardTableBarrierSetC1.cpp index b66e94836ed43bf661ccd6ff87425f5c2692d7a5..660c324aa99b3dcf70620387ec1c7693bed98b70 100644 --- a/src/hotspot/share/gc/shared/c1/cardTableBarrierSetC1.cpp +++ b/src/hotspot/share/gc/shared/c1/cardTableBarrierSetC1.cpp @@ -69,9 +69,9 @@ void CardTableBarrierSetC1::post_barrier(LIRAccess& access, LIR_Opr addr, LIR_Op if (TwoOperandLIRForm) { LIR_Opr addr_opr = LIR_OprFact::address(new LIR_Address(addr, addr->type())); __ leal(addr_opr, tmp); - __ unsigned_shift_right(tmp, CardTable::card_shift, tmp); + __ unsigned_shift_right(tmp, CardTable::card_shift(), tmp); } else { - __ unsigned_shift_right(addr, CardTable::card_shift, tmp); + __ unsigned_shift_right(addr, CardTable::card_shift(), tmp); } LIR_Address* card_addr; diff --git a/src/hotspot/share/gc/shared/c2/cardTableBarrierSetC2.cpp b/src/hotspot/share/gc/shared/c2/cardTableBarrierSetC2.cpp index 73ea620041b8672930cc13e98f555b8e36c971ea..0a7a032c117edb81203c33e777ce7f3690fe68b0 100644 --- a/src/hotspot/share/gc/shared/c2/cardTableBarrierSetC2.cpp +++ b/src/hotspot/share/gc/shared/c2/cardTableBarrierSetC2.cpp @@ -91,7 +91,7 @@ void CardTableBarrierSetC2::post_barrier(GraphKit* kit, Node* cast = __ CastPX(__ ctrl(), adr); // Divide by card size - Node* card_offset = __ URShiftX(cast, __ ConI(CardTable::card_shift)); + Node* card_offset = __ URShiftX(cast, __ ConI(CardTable::card_shift())); // Combine card table base and card offset Node* card_adr = __ AddP(__ top(), byte_map_base_node(kit), card_offset); diff --git a/src/hotspot/share/gc/shared/cardTable.cpp b/src/hotspot/share/gc/shared/cardTable.cpp index 10e4723934d0188110a05298190430ba7f06e7ce..2ff5f8d31c38f9b5ccca5ac867a6475f1af71574 100644 --- a/src/hotspot/share/gc/shared/cardTable.cpp +++ b/src/hotspot/share/gc/shared/cardTable.cpp @@ -38,27 +38,27 @@ #include "gc/parallel/objectStartArray.hpp" #endif -uint CardTable::card_shift = 0; -uint CardTable::card_size = 0; -uint CardTable::card_size_in_words = 0; +uint CardTable::_card_shift = 0; +uint CardTable::_card_size = 0; +uint CardTable::_card_size_in_words = 0; void CardTable::initialize_card_size() { assert(UseG1GC || UseParallelGC || UseSerialGC, "Initialize card size should only be called by card based collectors."); - card_size = GCCardSizeInBytes; - card_shift = log2i_exact(card_size); - card_size_in_words = card_size / sizeof(HeapWord); + _card_size = GCCardSizeInBytes; + _card_shift = log2i_exact(_card_size); + _card_size_in_words = _card_size / sizeof(HeapWord); // Set blockOffsetTable size based on card table entry size - BOTConstants::initialize_bot_size(card_shift); + BOTConstants::initialize_bot_size(_card_shift); #if INCLUDE_PARALLELGC // Set ObjectStartArray block size based on card table entry size - ObjectStartArray::initialize_block_size(card_shift); + ObjectStartArray::initialize_block_size(_card_shift); #endif - log_info_p(gc, init)("CardTable entry size: " UINT32_FORMAT, card_size); + log_info_p(gc, init)("CardTable entry size: " UINT32_FORMAT, _card_size); } size_t CardTable::compute_byte_map_size() { @@ -82,8 +82,8 @@ CardTable::CardTable(MemRegion whole_heap) : _committed(MemRegion::create_array(_max_covered_regions, mtGC)), _guard_region() { - assert((uintptr_t(_whole_heap.start()) & (card_size - 1)) == 0, "heap must start at card boundary"); - assert((uintptr_t(_whole_heap.end()) & (card_size - 1)) == 0, "heap must end at card boundary"); + assert((uintptr_t(_whole_heap.start()) & (_card_size - 1)) == 0, "heap must start at card boundary"); + assert((uintptr_t(_whole_heap.end()) & (_card_size - 1)) == 0, "heap must end at card boundary"); } CardTable::~CardTable() { @@ -120,7 +120,7 @@ void CardTable::initialize() { // // _byte_map = _byte_map_base + (uintptr_t(low_bound) >> card_shift) _byte_map = (CardValue*) heap_rs.base(); - _byte_map_base = _byte_map - (uintptr_t(low_bound) >> card_shift); + _byte_map_base = _byte_map - (uintptr_t(low_bound) >> _card_shift); assert(byte_for(low_bound) == &_byte_map[0], "Checking start of map"); assert(byte_for(high_bound-1) <= &_byte_map[_last_valid_index], "Checking end of map"); @@ -413,7 +413,7 @@ void CardTable::dirty_card_iterate(MemRegion mr, MemRegionClosure* cl) { next_entry <= limit && *next_entry == dirty_card; dirty_cards++, next_entry++); MemRegion cur_cards(addr_for(cur_entry), - dirty_cards*card_size_in_words); + dirty_cards*_card_size_in_words); cl->do_MemRegion(cur_cards); } } @@ -439,7 +439,7 @@ MemRegion CardTable::dirty_card_range_after_reset(MemRegion mr, next_entry <= limit && *next_entry == dirty_card; dirty_cards++, next_entry++); MemRegion cur_cards(addr_for(cur_entry), - dirty_cards*card_size_in_words); + dirty_cards * _card_size_in_words); if (reset) { for (size_t i = 0; i < dirty_cards; i++) { cur_entry[i] = reset_val; @@ -493,7 +493,7 @@ void CardTable::verify_region(MemRegion mr, CardValue val, bool val_equals) { } log_error(gc, verify)("== card " PTR_FORMAT " [" PTR_FORMAT "," PTR_FORMAT "], val: %d", p2i(curr), p2i(addr_for(curr)), - p2i((HeapWord*) (((size_t) addr_for(curr)) + card_size)), + p2i((HeapWord*) (((size_t) addr_for(curr)) + _card_size)), (int) curr_val); } } diff --git a/src/hotspot/share/gc/shared/cardTable.hpp b/src/hotspot/share/gc/shared/cardTable.hpp index bf116a1f1e73c7fc58c7fab7d2d3aab5a0c4c4fe..075b961b3cd388fd826111aff1e42b84bc61f7c2 100644 --- a/src/hotspot/share/gc/shared/cardTable.hpp +++ b/src/hotspot/share/gc/shared/cardTable.hpp @@ -111,6 +111,11 @@ protected: // a word's worth (row) of clean card values static const intptr_t clean_card_row = (intptr_t)(-1); + // CardTable entry size + static uint _card_shift; + static uint _card_size; + static uint _card_size_in_words; + public: CardTable(MemRegion whole_heap); virtual ~CardTable(); @@ -133,8 +138,8 @@ public: // in, um, words. inline size_t cards_required(size_t covered_words) { // Add one for a guard card, used to detect errors. - const size_t words = align_up(covered_words, card_size_in_words); - return words / card_size_in_words + 1; + const size_t words = align_up(covered_words, _card_size_in_words); + return words / _card_size_in_words + 1; } // Dirty the bytes corresponding to "mr" (not all of which must be @@ -157,7 +162,7 @@ public: "Attempt to access p = " PTR_FORMAT " out of bounds of " " card marking array's _whole_heap = [" PTR_FORMAT "," PTR_FORMAT ")", p2i(p), p2i(_whole_heap.start()), p2i(_whole_heap.end())); - CardValue* result = &_byte_map_base[uintptr_t(p) >> card_shift]; + CardValue* result = &_byte_map_base[uintptr_t(p) >> _card_shift]; assert(result >= _byte_map && result < _byte_map + _byte_map_size, "out of bounds accessor for card marking array"); return result; @@ -189,7 +194,7 @@ public: " _byte_map: " PTR_FORMAT " _byte_map + _byte_map_size: " PTR_FORMAT, p2i(p), p2i(_byte_map), p2i(_byte_map + _byte_map_size)); size_t delta = pointer_delta(p, _byte_map_base, sizeof(CardValue)); - HeapWord* result = (HeapWord*) (delta << card_shift); + HeapWord* result = (HeapWord*) (delta << _card_shift); assert(_whole_heap.contains(result), "Returning result = " PTR_FORMAT " out of bounds of " " card marking array's _whole_heap = [" PTR_FORMAT "," PTR_FORMAT ")", @@ -228,10 +233,17 @@ public: MemRegion dirty_card_range_after_reset(MemRegion mr, bool reset, int reset_val); - // CardTable entry size - static uint card_shift; - static uint card_size; - static uint card_size_in_words; + static uint card_shift() { + return _card_shift; + } + + static uint card_size() { + return _card_size; + } + + static uint card_size_in_words() { + return _card_size_in_words; + } static constexpr CardValue clean_card_val() { return clean_card; } static constexpr CardValue dirty_card_val() { return dirty_card; } diff --git a/src/hotspot/share/gc/shared/gc_globals.hpp b/src/hotspot/share/gc/shared/gc_globals.hpp index b57be5abf62304ee07a58ce2b267c3fec0c154cf..684357297d8c5fc852eceb1f23ceb420eee19e52 100644 --- a/src/hotspot/share/gc/shared/gc_globals.hpp +++ b/src/hotspot/share/gc/shared/gc_globals.hpp @@ -696,7 +696,7 @@ \ product(uint, GCCardSizeInBytes, 512, \ "Card table entry size (in bytes) for card based collectors") \ - range(128, 1024) \ + range(128, NOT_LP64(512) LP64_ONLY(1024)) \ constraint(GCCardSizeInBytesConstraintFunc,AtParse) // end of GC_FLAGS diff --git a/src/hotspot/share/gc/shared/referenceProcessor.cpp b/src/hotspot/share/gc/shared/referenceProcessor.cpp index b36d746486defe59cf2214af97d040f2d7ffc882..be8ea708ffa49ed1299d569175f48761bf0fd112 100644 --- a/src/hotspot/share/gc/shared/referenceProcessor.cpp +++ b/src/hotspot/share/gc/shared/referenceProcessor.cpp @@ -191,10 +191,10 @@ ReferenceProcessorStats ReferenceProcessor::process_discovered_references(RefPro // Stop treating discovered references specially. disable_discovery(); - ReferenceProcessorStats stats(total_count(_discoveredSoftRefs), - total_count(_discoveredWeakRefs), - total_count(_discoveredFinalRefs), - total_count(_discoveredPhantomRefs)); + phase_times.set_ref_discovered(REF_SOFT, total_count(_discoveredSoftRefs)); + phase_times.set_ref_discovered(REF_WEAK, total_count(_discoveredWeakRefs)); + phase_times.set_ref_discovered(REF_FINAL, total_count(_discoveredFinalRefs)); + phase_times.set_ref_discovered(REF_PHANTOM, total_count(_discoveredPhantomRefs)); update_soft_ref_master_clock(); @@ -220,6 +220,10 @@ ReferenceProcessorStats ReferenceProcessor::process_discovered_references(RefPro // Elements on discovered lists were pushed to the pending list. verify_no_references_recorded(); + ReferenceProcessorStats stats(phase_times.ref_discovered(REF_SOFT), + phase_times.ref_discovered(REF_WEAK), + phase_times.ref_discovered(REF_FINAL), + phase_times.ref_discovered(REF_PHANTOM)); return stats; } @@ -725,12 +729,10 @@ void ReferenceProcessor::run_task(RefProcTask& task, RefProcProxyTask& proxy_tas void ReferenceProcessor::process_soft_weak_final_refs(RefProcProxyTask& proxy_task, ReferenceProcessorPhaseTimes& phase_times) { - size_t const num_soft_refs = total_count(_discoveredSoftRefs); - size_t const num_weak_refs = total_count(_discoveredWeakRefs); - size_t const num_final_refs = total_count(_discoveredFinalRefs); + size_t const num_soft_refs = phase_times.ref_discovered(REF_SOFT); + size_t const num_weak_refs = phase_times.ref_discovered(REF_WEAK); + size_t const num_final_refs = phase_times.ref_discovered(REF_FINAL); size_t const num_total_refs = num_soft_refs + num_weak_refs + num_final_refs; - phase_times.set_ref_discovered(REF_WEAK, num_weak_refs); - phase_times.set_ref_discovered(REF_FINAL, num_final_refs); if (num_total_refs == 0) { log_debug(gc, ref)("Skipped SoftWeakFinalRefsPhase of Reference Processing: no references"); @@ -763,7 +765,7 @@ void ReferenceProcessor::process_soft_weak_final_refs(RefProcProxyTask& proxy_ta void ReferenceProcessor::process_final_keep_alive(RefProcProxyTask& proxy_task, ReferenceProcessorPhaseTimes& phase_times) { - size_t const num_final_refs = total_count(_discoveredFinalRefs); + size_t const num_final_refs = phase_times.ref_discovered(REF_FINAL); if (num_final_refs == 0) { log_debug(gc, ref)("Skipped KeepAliveFinalRefsPhase of Reference Processing: no references"); @@ -788,8 +790,7 @@ void ReferenceProcessor::process_final_keep_alive(RefProcProxyTask& proxy_task, void ReferenceProcessor::process_phantom_refs(RefProcProxyTask& proxy_task, ReferenceProcessorPhaseTimes& phase_times) { - size_t const num_phantom_refs = total_count(_discoveredPhantomRefs); - phase_times.set_ref_discovered(REF_PHANTOM, num_phantom_refs); + size_t const num_phantom_refs = phase_times.ref_discovered(REF_PHANTOM); if (num_phantom_refs == 0) { log_debug(gc, ref)("Skipped PhantomRefsPhase of Reference Processing: no references"); @@ -820,7 +821,7 @@ inline DiscoveredList* ReferenceProcessor::get_discovered_list(ReferenceType rt) if (_discovery_is_mt) { // During a multi-threaded discovery phase, // each thread saves to its "own" list. - id = WorkerThread::current()->id(); + id = WorkerThread::worker_id(); } else { // single-threaded discovery, we save in round-robin // fashion to each of the lists. diff --git a/src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.cpp b/src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.cpp index 87d60b1a6c0b75ec7497fa80740ee9cff85f3084..2c9df9f29650e1aa90d1afdaaacae0a5c9699a13 100644 --- a/src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.cpp +++ b/src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.cpp @@ -101,10 +101,7 @@ RefProcWorkerTimeTracker::~RefProcWorkerTimeTracker() { RefProcSubPhasesWorkerTimeTracker::RefProcSubPhasesWorkerTimeTracker(ReferenceProcessor::RefProcSubPhases phase, ReferenceProcessorPhaseTimes* phase_times, uint worker_id) : - RefProcWorkerTimeTracker(phase_times->sub_phase_worker_time_sec(phase), worker_id) { -} - -RefProcSubPhasesWorkerTimeTracker::~RefProcSubPhasesWorkerTimeTracker() { + _tracker(phase_times->sub_phase_worker_time_sec(phase), worker_id) { } RefProcPhaseTimeBaseTracker::RefProcPhaseTimeBaseTracker(const char* title, @@ -200,7 +197,6 @@ void ReferenceProcessorPhaseTimes::set_phase_time_ms(ReferenceProcessor::RefProc void ReferenceProcessorPhaseTimes::reset() { for (int i = 0; i < ReferenceProcessor::RefSubPhaseMax; i++) { _sub_phases_worker_time_sec[i]->reset(); - _sub_phases_total_time_ms[i] = uninitialized(); } for (int i = 0; i < ReferenceProcessor::RefPhaseMax; i++) { @@ -227,17 +223,6 @@ ReferenceProcessorPhaseTimes::~ReferenceProcessorPhaseTimes() { delete _soft_weak_final_refs_phase_worker_time_sec; } -double ReferenceProcessorPhaseTimes::sub_phase_total_time_ms(ReferenceProcessor::RefProcSubPhases sub_phase) const { - ASSERT_SUB_PHASE(sub_phase); - return _sub_phases_total_time_ms[sub_phase]; -} - -void ReferenceProcessorPhaseTimes::set_sub_phase_total_phase_time_ms(ReferenceProcessor::RefProcSubPhases sub_phase, - double time_ms) { - ASSERT_SUB_PHASE(sub_phase); - _sub_phases_total_time_ms[sub_phase] = time_ms; -} - void ReferenceProcessorPhaseTimes::add_ref_cleared(ReferenceType ref_type, size_t count) { ASSERT_REF_TYPE(ref_type); Atomic::add(&_ref_cleared[ref_type_2_index(ref_type)], count, memory_order_relaxed); @@ -248,6 +233,11 @@ void ReferenceProcessorPhaseTimes::set_ref_discovered(ReferenceType ref_type, si _ref_discovered[ref_type_2_index(ref_type)] = count; } +size_t ReferenceProcessorPhaseTimes::ref_discovered(ReferenceType ref_type) { + ASSERT_REF_TYPE(ref_type); + return _ref_discovered[ref_type_2_index(ref_type)]; +} + double ReferenceProcessorPhaseTimes::balance_queues_time_ms(ReferenceProcessor::RefProcPhases phase) const { ASSERT_PHASE(phase); return _balance_queues_time_ms[phase]; diff --git a/src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.hpp b/src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.hpp index 5d1f2d2eeb7c6ec83797612795caa6720ecfa2ad..5b2e9e7bc7b786fadab5588dfe596e492b3cfe73 100644 --- a/src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.hpp +++ b/src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.hpp @@ -41,8 +41,6 @@ class ReferenceProcessorPhaseTimes : public CHeapObj { // Records per thread time information of each sub phase. WorkerDataArray* _sub_phases_worker_time_sec[ReferenceProcessor::RefSubPhaseMax]; - // Total time of each sub phase. - double _sub_phases_total_time_ms[ReferenceProcessor::RefSubPhaseMax]; // Records total elapsed time for each phase. double _phases_time_ms[ReferenceProcessor::RefPhaseMax]; @@ -62,7 +60,6 @@ class ReferenceProcessorPhaseTimes : public CHeapObj { GCTimer* _gc_timer; double phase_time_ms(ReferenceProcessor::RefProcPhases phase) const; - double sub_phase_total_time_ms(ReferenceProcessor::RefProcSubPhases sub_phase) const; double total_time_ms() const { return _total_time_ms; } @@ -84,12 +81,11 @@ public: WorkerDataArray* sub_phase_worker_time_sec(ReferenceProcessor::RefProcSubPhases phase) const; void set_phase_time_ms(ReferenceProcessor::RefProcPhases phase, double par_phase_time_ms); - void set_sub_phase_total_phase_time_ms(ReferenceProcessor::RefProcSubPhases sub_phase, double ref_proc_time_ms); - void set_total_time_ms(double total_time_ms) { _total_time_ms = total_time_ms; } void add_ref_cleared(ReferenceType ref_type, size_t count); void set_ref_discovered(ReferenceType ref_type, size_t count); + size_t ref_discovered(ReferenceType ref_type); void set_balance_queues_time_ms(ReferenceProcessor::RefProcPhases phase, double time_ms); @@ -103,23 +99,23 @@ public: void print_all_references(uint base_indent = 0, bool print_total = true) const; }; -class RefProcWorkerTimeTracker : public CHeapObj { +class RefProcWorkerTimeTracker : public StackObj { protected: WorkerDataArray* _worker_time; double _start_time; uint _worker_id; public: RefProcWorkerTimeTracker(WorkerDataArray* worker_time, uint worker_id); - virtual ~RefProcWorkerTimeTracker(); + ~RefProcWorkerTimeTracker(); }; // Updates working time of each worker thread for a given sub phase. -class RefProcSubPhasesWorkerTimeTracker : public RefProcWorkerTimeTracker { +class RefProcSubPhasesWorkerTimeTracker : public StackObj { + RefProcWorkerTimeTracker _tracker; public: RefProcSubPhasesWorkerTimeTracker(ReferenceProcessor::RefProcSubPhases phase, ReferenceProcessorPhaseTimes* phase_times, uint worker_id); - ~RefProcSubPhasesWorkerTimeTracker(); }; class RefProcPhaseTimeBaseTracker : public StackObj { diff --git a/src/hotspot/share/gc/shared/stringdedup/stringDedupConfig.cpp b/src/hotspot/share/gc/shared/stringdedup/stringDedupConfig.cpp index a01548a72b08d3d5c69da9b9cb57abb98dd18beb..3fa3df12891ec84eb9757bd0e80d83704a03c464 100644 --- a/src/hotspot/share/gc/shared/stringdedup/stringDedupConfig.cpp +++ b/src/hotspot/share/gc/shared/stringdedup/stringDedupConfig.cpp @@ -161,6 +161,6 @@ void StringDedup::Config::initialize() { _load_factor_for_shrink = StringDeduplicationShrinkTableLoad; _load_factor_target = StringDeduplicationTargetTableLoad; _minimum_dead_for_cleanup = StringDeduplicationCleanupDeadMinimum; - _dead_factor_for_cleanup = percent_of(StringDeduplicationCleanupDeadPercent, 100); + _dead_factor_for_cleanup = StringDeduplicationCleanupDeadPercent / 100.0; _hash_seed = initial_hash_seed(); } diff --git a/src/hotspot/share/gc/shared/vmStructs_gc.hpp b/src/hotspot/share/gc/shared/vmStructs_gc.hpp index 2de1cc8c57cd279a43bb0b6fa4646099746ae81c..f9b1c631123fc47fc4b59e9cd5cffb93003f6dc4 100644 --- a/src/hotspot/share/gc/shared/vmStructs_gc.hpp +++ b/src/hotspot/share/gc/shared/vmStructs_gc.hpp @@ -261,10 +261,6 @@ declare_constant(BarrierSet::ModRef) \ declare_constant(BarrierSet::CardTableBarrierSet) \ \ - declare_constant(BOTConstants::LogN) \ - declare_constant(BOTConstants::LogN_words) \ - declare_constant(BOTConstants::N_bytes) \ - declare_constant(BOTConstants::N_words) \ declare_constant(BOTConstants::LogBase) \ declare_constant(BOTConstants::Base) \ declare_constant(BOTConstants::N_powers) \ @@ -274,9 +270,6 @@ declare_constant(CardTable::dirty_card) \ declare_constant(CardTable::Precise) \ declare_constant(CardTable::ObjHeadPreciseArray) \ - declare_constant(CardTable::card_shift) \ - declare_constant(CardTable::card_size) \ - declare_constant(CardTable::card_size_in_words) \ \ declare_constant(CollectedHeap::Serial) \ declare_constant(CollectedHeap::Parallel) \ diff --git a/src/hotspot/share/gc/shared/workerThread.cpp b/src/hotspot/share/gc/shared/workerThread.cpp index 183349ef245ef5d61e37a7eef1e6abc36cc10333..9d141464a394be58a10231e93ea890ebaeef2ecb 100644 --- a/src/hotspot/share/gc/shared/workerThread.cpp +++ b/src/hotspot/share/gc/shared/workerThread.cpp @@ -59,8 +59,9 @@ void WorkerTaskDispatcher::worker_run_task() { // Wait for the coordinator to dispatch a task. _start_semaphore.wait(); - // Get worker id. + // Get and set worker id. const uint worker_id = Atomic::fetch_and_add(&_started, 1u); + WorkerThread::set_worker_id(worker_id); // Run task. GCIdMark gc_id_mark(_task->gc_id()); @@ -91,18 +92,20 @@ void WorkerThreads::initialize_workers() { } } -WorkerThread* WorkerThreads::create_worker(uint id) { +WorkerThread* WorkerThreads::create_worker(uint name_suffix) { if (is_init_completed() && InjectGCWorkerCreationFailure) { return NULL; } - WorkerThread* const worker = new WorkerThread(_name, id, &_dispatcher); + WorkerThread* const worker = new WorkerThread(_name, name_suffix, &_dispatcher); if (!os::create_thread(worker, os::gc_thread)) { delete worker; return NULL; } + on_create_worker(worker); + os::start_thread(worker); return worker; @@ -146,10 +149,11 @@ void WorkerThreads::run_task(WorkerTask* task, uint num_workers) { run_task(task); } -WorkerThread::WorkerThread(const char* name_prefix, uint id, WorkerTaskDispatcher* dispatcher) : - _dispatcher(dispatcher), - _id(id) { - set_name("%s#%d", name_prefix, id); +THREAD_LOCAL uint WorkerThread::_worker_id = UINT_MAX; + +WorkerThread::WorkerThread(const char* name_prefix, uint name_suffix, WorkerTaskDispatcher* dispatcher) : + _dispatcher(dispatcher) { + set_name("%s#%u", name_prefix, name_suffix); } void WorkerThread::run() { diff --git a/src/hotspot/share/gc/shared/workerThread.hpp b/src/hotspot/share/gc/shared/workerThread.hpp index d4c16c246f06b52d88ae1ed6d23caace3c248e81..bdb61f34ed9d90163441bae2ae73eecb09fb3111 100644 --- a/src/hotspot/share/gc/shared/workerThread.hpp +++ b/src/hotspot/share/gc/shared/workerThread.hpp @@ -91,8 +91,10 @@ private: uint _active_workers; WorkerTaskDispatcher _dispatcher; + WorkerThread* create_worker(uint name_suffix); + protected: - virtual WorkerThread* create_worker(uint id); + virtual void on_create_worker(WorkerThread* worker) {} public: WorkerThreads(const char* name, uint max_workers); @@ -117,23 +119,19 @@ public: }; class WorkerThread : public NamedThread { + friend class WorkerTaskDispatcher; + private: - WorkerTaskDispatcher* const _dispatcher; - const uint _id; + static THREAD_LOCAL uint _worker_id; -public: - static WorkerThread* current() { - return WorkerThread::cast(Thread::current()); - } + WorkerTaskDispatcher* const _dispatcher; - static WorkerThread* cast(Thread* t) { - assert(t->is_Worker_thread(), "incorrect cast to WorkerThread"); - return static_cast(t); - } + static void set_worker_id(uint worker_id) { _worker_id = worker_id; } - WorkerThread(const char* name_prefix, uint id, WorkerTaskDispatcher* dispatcher); +public: + static uint worker_id() { return _worker_id; } - uint id() const { return _id; } + WorkerThread(const char* name_prefix, uint which, WorkerTaskDispatcher* dispatcher); bool is_Worker_thread() const override { return true; } const char* type_name() const override { return "WorkerThread"; } diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp index 5ba3828b2d3d7a81b1b874530e3592ba7cd920b2..f46d94363166e525ade2c572342d443b05a8265e 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp @@ -54,7 +54,6 @@ bool ShenandoahBarrierC2Support::expand(Compile* C, PhaseIterGVN& igvn) { PhaseIdealLoop::optimize(igvn, LoopOptsShenandoahExpand); if (C->failing()) return false; PhaseIdealLoop::verify(igvn); - DEBUG_ONLY(verify_raw_mem(C->root());) if (attempt_more_loopopts) { C->set_major_progress(); if (!C->optimize_loops(igvn, LoopOptsShenandoahPostExpand)) { @@ -964,18 +963,11 @@ void ShenandoahBarrierC2Support::test_in_cset(Node*& ctrl, Node*& not_cset_ctrl, phase->register_new_node(cset_bool, old_ctrl); } -void ShenandoahBarrierC2Support::call_lrb_stub(Node*& ctrl, Node*& val, Node* load_addr, Node*& result_mem, Node* raw_mem, +void ShenandoahBarrierC2Support::call_lrb_stub(Node*& ctrl, Node*& val, Node* load_addr, DecoratorSet decorators, PhaseIdealLoop* phase) { IdealLoopTree*loop = phase->get_loop(ctrl); const TypePtr* obj_type = phase->igvn().type(val)->is_oopptr(); - // The slow path stub consumes and produces raw memory in addition - // to the existing memory edges - Node* base = find_bottom_mem(ctrl, phase); - MergeMemNode* mm = MergeMemNode::make(base); - mm->set_memory_at(Compile::AliasIdxRaw, raw_mem); - phase->register_new_node(mm, ctrl); - address calladdr = NULL; const char* name = NULL; bool is_strong = ShenandoahBarrierSet::is_strong_access(decorators); @@ -1013,7 +1005,7 @@ void ShenandoahBarrierC2Support::call_lrb_stub(Node*& ctrl, Node*& val, Node* lo call->init_req(TypeFunc::Control, ctrl); call->init_req(TypeFunc::I_O, phase->C->top()); - call->init_req(TypeFunc::Memory, mm); + call->init_req(TypeFunc::Memory, phase->C->top()); call->init_req(TypeFunc::FramePtr, phase->C->top()); call->init_req(TypeFunc::ReturnAdr, phase->C->top()); call->init_req(TypeFunc::Parms, val); @@ -1021,8 +1013,6 @@ void ShenandoahBarrierC2Support::call_lrb_stub(Node*& ctrl, Node*& val, Node* lo phase->register_control(call, loop, ctrl); ctrl = new ProjNode(call, TypeFunc::Control); phase->register_control(ctrl, loop, call); - result_mem = new ProjNode(call, TypeFunc::Memory); - phase->register_new_node(result_mem, call); val = new ProjNode(call, TypeFunc::Parms); phase->register_new_node(val, call); val = new CheckCastPPNode(ctrl, val, obj_type); @@ -1341,12 +1331,9 @@ void ShenandoahBarrierC2Support::pin_and_expand(PhaseIdealLoop* phase) { Node* ctrl = phase->get_ctrl(lrb); Node* val = lrb->in(ShenandoahLoadReferenceBarrierNode::ValueIn); - Node* orig_ctrl = ctrl; Node* raw_mem = fixer.find_mem(ctrl, lrb); - Node* init_raw_mem = raw_mem; - Node* raw_mem_for_ctrl = fixer.find_mem(ctrl, NULL); IdealLoopTree *loop = phase->get_loop(ctrl); @@ -1359,7 +1346,6 @@ void ShenandoahBarrierC2Support::pin_and_expand(PhaseIdealLoop* phase) { enum { _heap_stable = 1, _evac_path, _not_cset, PATH_LIMIT }; Node* region = new RegionNode(PATH_LIMIT); Node* val_phi = new PhiNode(region, val->bottom_type()->is_oopptr()); - Node* raw_mem_phi = PhiNode::make(region, raw_mem, Type::MEMORY, TypeRawPtr::BOTTOM); // Stable path. int flags = ShenandoahHeap::HAS_FORWARDED; @@ -1372,7 +1358,6 @@ void ShenandoahBarrierC2Support::pin_and_expand(PhaseIdealLoop* phase) { // Heap stable case region->init_req(_heap_stable, heap_stable_ctrl); val_phi->init_req(_heap_stable, val); - raw_mem_phi->init_req(_heap_stable, raw_mem); // Test for in-cset, unless it's a native-LRB. Native LRBs need to return NULL // even for non-cset objects to prevent ressurrection of such objects. @@ -1384,11 +1369,9 @@ void ShenandoahBarrierC2Support::pin_and_expand(PhaseIdealLoop* phase) { if (not_cset_ctrl != NULL) { region->init_req(_not_cset, not_cset_ctrl); val_phi->init_req(_not_cset, val); - raw_mem_phi->init_req(_not_cset, raw_mem); } else { region->del_req(_not_cset); val_phi->del_req(_not_cset); - raw_mem_phi->del_req(_not_cset); } // Resolve object when orig-value is in cset. @@ -1429,15 +1412,13 @@ void ShenandoahBarrierC2Support::pin_and_expand(PhaseIdealLoop* phase) { } } } - call_lrb_stub(ctrl, val, addr, result_mem, raw_mem, lrb->decorators(), phase); + call_lrb_stub(ctrl, val, addr, lrb->decorators(), phase); region->init_req(_evac_path, ctrl); val_phi->init_req(_evac_path, val); - raw_mem_phi->init_req(_evac_path, result_mem); phase->register_control(region, loop, heap_stable_iff); Node* out_val = val_phi; phase->register_new_node(val_phi, region); - phase->register_new_node(raw_mem_phi, region); fix_ctrl(lrb, region, fixer, uses, uses_to_ignore, last, phase); @@ -1450,18 +1431,10 @@ void ShenandoahBarrierC2Support::pin_and_expand(PhaseIdealLoop* phase) { for(uint next = 0; next < uses.size(); next++ ) { Node *n = uses.at(next); assert(phase->get_ctrl(n) == ctrl, "bad control"); - assert(n != init_raw_mem, "should leave input raw mem above the barrier"); + assert(n != raw_mem, "should leave input raw mem above the barrier"); phase->set_ctrl(n, region); follow_barrier_uses(n, ctrl, uses, phase); } - - // The slow path call produces memory: hook the raw memory phi - // from the expanded load reference barrier with the rest of the graph - // which may require adding memory phis at every post dominated - // region and at enclosing loop heads. Use the memory state - // collected in memory_nodes to fix the memory graph. Update that - // memory state as we go. - fixer.fix_mem(ctrl, region, init_raw_mem, raw_mem_for_ctrl, raw_mem_phi, uses); } // Done expanding load-reference-barriers. assert(ShenandoahBarrierSetC2::bsc2()->state()->load_reference_barriers_count() == 0, "all load reference barrier nodes should have been replaced"); @@ -1902,105 +1875,6 @@ void ShenandoahBarrierC2Support::optimize_after_expansion(VectorSet &visited, No } } -#ifdef ASSERT -void ShenandoahBarrierC2Support::verify_raw_mem(RootNode* root) { - const bool trace = false; - ResourceMark rm; - Unique_Node_List nodes; - Unique_Node_List controls; - Unique_Node_List memories; - - nodes.push(root); - for (uint next = 0; next < nodes.size(); next++) { - Node *n = nodes.at(next); - if (ShenandoahBarrierSetC2::is_shenandoah_lrb_call(n)) { - controls.push(n); - if (trace) { tty->print("XXXXXX verifying"); n->dump(); } - for (uint next2 = 0; next2 < controls.size(); next2++) { - Node *m = controls.at(next2); - for (DUIterator_Fast imax, i = m->fast_outs(imax); i < imax; i++) { - Node* u = m->fast_out(i); - if (u->is_CFG() && !u->is_Root() && - !(u->Opcode() == Op_CProj && u->in(0)->Opcode() == Op_NeverBranch && u->as_Proj()->_con == 1) && - !(u->is_Region() && u->unique_ctrl_out()->Opcode() == Op_Halt)) { - if (trace) { tty->print("XXXXXX pushing control"); u->dump(); } - controls.push(u); - } - } - } - memories.push(n->as_Call()->proj_out(TypeFunc::Memory)); - for (uint next2 = 0; next2 < memories.size(); next2++) { - Node *m = memories.at(next2); - assert(m->bottom_type() == Type::MEMORY, ""); - for (DUIterator_Fast imax, i = m->fast_outs(imax); i < imax; i++) { - Node* u = m->fast_out(i); - if (u->bottom_type() == Type::MEMORY && (u->is_Mem() || u->is_ClearArray())) { - if (trace) { tty->print("XXXXXX pushing memory"); u->dump(); } - memories.push(u); - } else if (u->is_LoadStore()) { - if (trace) { tty->print("XXXXXX pushing memory"); u->find_out_with(Op_SCMemProj)->dump(); } - memories.push(u->find_out_with(Op_SCMemProj)); - } else if (u->is_MergeMem() && u->as_MergeMem()->memory_at(Compile::AliasIdxRaw) == m) { - if (trace) { tty->print("XXXXXX pushing memory"); u->dump(); } - memories.push(u); - } else if (u->is_Phi()) { - assert(u->bottom_type() == Type::MEMORY, ""); - if (u->adr_type() == TypeRawPtr::BOTTOM || u->adr_type() == TypePtr::BOTTOM) { - assert(controls.member(u->in(0)), ""); - if (trace) { tty->print("XXXXXX pushing memory"); u->dump(); } - memories.push(u); - } - } else if (u->is_SafePoint() || u->is_MemBar()) { - for (DUIterator_Fast jmax, j = u->fast_outs(jmax); j < jmax; j++) { - Node* uu = u->fast_out(j); - if (uu->bottom_type() == Type::MEMORY) { - if (trace) { tty->print("XXXXXX pushing memory"); uu->dump(); } - memories.push(uu); - } - } - } - } - } - for (uint next2 = 0; next2 < controls.size(); next2++) { - Node *m = controls.at(next2); - if (m->is_Region()) { - bool all_in = true; - for (uint i = 1; i < m->req(); i++) { - if (!controls.member(m->in(i))) { - all_in = false; - break; - } - } - if (trace) { tty->print("XXX verifying %s", all_in ? "all in" : ""); m->dump(); } - bool found_phi = false; - for (DUIterator_Fast jmax, j = m->fast_outs(jmax); j < jmax && !found_phi; j++) { - Node* u = m->fast_out(j); - if (u->is_Phi() && memories.member(u)) { - found_phi = true; - for (uint i = 1; i < u->req() && found_phi; i++) { - Node* k = u->in(i); - if (memories.member(k) != controls.member(m->in(i))) { - found_phi = false; - } - } - } - } - assert(found_phi || all_in, ""); - } - } - controls.clear(); - memories.clear(); - } - for( uint i = 0; i < n->len(); ++i ) { - Node *m = n->in(i); - if (m != NULL) { - nodes.push(m); - } - } - } -} -#endif - ShenandoahIUBarrierNode::ShenandoahIUBarrierNode(Node* val) : Node(NULL, val) { ShenandoahBarrierSetC2::bsc2()->state()->add_iu_barrier(this); } diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.hpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.hpp index 6632e42b36f073a561620e9a4d4c87b7956f742d..86a74011f5a56ed2e398bc28e4feec710266e67d 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.hpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.hpp @@ -50,7 +50,6 @@ private: static bool verify_helper(Node* in, Node_Stack& phis, VectorSet& visited, verify_type t, bool trace, Unique_Node_List& barriers_used); static void report_verify_failure(const char* msg, Node* n1 = NULL, Node* n2 = NULL); - static void verify_raw_mem(RootNode* root); #endif static Node* dom_mem(Node* mem, Node* ctrl, int alias, Node*& mem_ctrl, PhaseIdealLoop* phase); static Node* no_branches(Node* c, Node* dom, bool allow_one_proj, PhaseIdealLoop* phase); @@ -61,7 +60,7 @@ private: static void test_null(Node*& ctrl, Node* val, Node*& null_ctrl, PhaseIdealLoop* phase); static void test_gc_state(Node*& ctrl, Node* raw_mem, Node*& heap_stable_ctrl, PhaseIdealLoop* phase, int flags); - static void call_lrb_stub(Node*& ctrl, Node*& val, Node* load_addr, Node*& result_mem, Node* raw_mem, + static void call_lrb_stub(Node*& ctrl, Node*& val, Node* load_addr, DecoratorSet decorators, PhaseIdealLoop* phase); static void test_in_cset(Node*& ctrl, Node*& not_cset_ctrl, Node* val, Node* raw_mem, PhaseIdealLoop* phase); static void move_gc_state_test_out_of_loop(IfNode* iff, PhaseIdealLoop* phase); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahReferenceProcessor.cpp b/src/hotspot/share/gc/shenandoah/shenandoahReferenceProcessor.cpp index 72a87a9d3dee264403b17e373c9dfd08fbb32add..b828582336c47d021d649dfd94b7b7bd564365f4 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahReferenceProcessor.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahReferenceProcessor.cpp @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "classfile/javaClasses.hpp" +#include "gc/shared/workerThread.hpp" #include "gc/shenandoah/shenandoahOopClosures.inline.hpp" #include "gc/shenandoah/shenandoahReferenceProcessor.hpp" #include "gc/shenandoah/shenandoahThreadLocalData.hpp" @@ -337,7 +338,6 @@ bool ShenandoahReferenceProcessor::discover(oop reference, ReferenceType type, u } // Add reference to discovered list - assert(worker_id != ShenandoahThreadLocalData::INVALID_WORKER_ID, "need valid worker ID"); ShenandoahRefProcThreadLocal& refproc_data = _ref_proc_thread_locals[worker_id]; oop discovered_head = refproc_data.discovered_list_head(); if (discovered_head == NULL) { @@ -361,7 +361,7 @@ bool ShenandoahReferenceProcessor::discover_reference(oop reference, ReferenceTy } log_trace(gc, ref)("Encountered Reference: " PTR_FORMAT " (%s)", p2i(reference), reference_type_name(type)); - uint worker_id = ShenandoahThreadLocalData::worker_id(Thread::current()); + uint worker_id = WorkerThread::worker_id(); _ref_proc_thread_locals->inc_encountered(type); if (UseCompressedOops) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp index a87918ce8a1947c0bed8a4d97fbc3a2d1bd07426..d5cb312949630728ac678c90bf332b167f566ea8 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp @@ -97,29 +97,6 @@ ShenandoahRootProcessor::ShenandoahRootProcessor(ShenandoahPhaseTimings::Phase p _worker_phase(phase) { } -ShenandoahRootScanner::ShenandoahRootScanner(uint n_workers, ShenandoahPhaseTimings::Phase phase) : - ShenandoahRootProcessor(phase), - _thread_roots(phase, n_workers > 1) { - nmethod::oops_do_marking_prologue(); -} - -ShenandoahRootScanner::~ShenandoahRootScanner() { - nmethod::oops_do_marking_epilogue(); -} - -void ShenandoahRootScanner::roots_do(uint worker_id, OopClosure* oops) { - MarkingCodeBlobClosure blobs_cl(oops, !CodeBlobToOopClosure::FixRelocations); - roots_do(worker_id, oops, &blobs_cl); -} - -void ShenandoahRootScanner::roots_do(uint worker_id, OopClosure* oops, CodeBlobClosure* code, ThreadClosure *tc) { - assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Must be at a safepoint"); - - ShenandoahParallelOopsDoThreadClosure tc_cl(oops, code, tc); - ResourceMark rm; - _thread_roots.threads_do(&tc_cl, worker_id); -} - ShenandoahSTWRootScanner::ShenandoahSTWRootScanner(ShenandoahPhaseTimings::Phase phase) : ShenandoahRootProcessor(phase), _thread_roots(phase, ShenandoahHeap::heap()->workers()->active_workers() > 1), diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp index 1ecee9906a547f2cb66c79d811cded242cc4bf9c..8a66c3df475e1709fa000cb60ac3eb7a84cbfbaf 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp @@ -143,20 +143,6 @@ public: ShenandoahHeap* heap() const { return _heap; } }; -class ShenandoahRootScanner : public ShenandoahRootProcessor { -private: - ShenandoahThreadRoots _thread_roots; - -public: - ShenandoahRootScanner(uint n_workers, ShenandoahPhaseTimings::Phase phase); - ~ShenandoahRootScanner(); - - void roots_do(uint worker_id, OopClosure* cl); - -private: - void roots_do(uint worker_id, OopClosure* oops, CodeBlobClosure* code, ThreadClosure* tc = NULL); -}; - // STW root scanner class ShenandoahSTWRootScanner : public ShenandoahRootProcessor { private: diff --git a/src/hotspot/share/gc/shenandoah/shenandoahThreadLocalData.hpp b/src/hotspot/share/gc/shenandoah/shenandoahThreadLocalData.hpp index e34073f9b8ee76055d91e9810ee7382b641f0307..8d50bb35ee1d220fccd16b5972298902a218d1be 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahThreadLocalData.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahThreadLocalData.hpp @@ -36,9 +36,6 @@ #include "utilities/sizes.hpp" class ShenandoahThreadLocalData { -public: - static const uint INVALID_WORKER_ID = uint(-1); - private: char _gc_state; // Evacuation OOM state @@ -47,7 +44,6 @@ private: SATBMarkQueue _satb_mark_queue; PLAB* _gclab; size_t _gclab_size; - uint _worker_id; int _disarmed_value; double _paced_time; @@ -58,7 +54,6 @@ private: _satb_mark_queue(&ShenandoahBarrierSet::satb_mark_queue_set()), _gclab(NULL), _gclab_size(0), - _worker_id(INVALID_WORKER_ID), _disarmed_value(0), _paced_time(0) { @@ -103,16 +98,6 @@ public: return data(thread)->_gc_state; } - static void set_worker_id(Thread* thread, uint id) { - assert(thread->is_Worker_thread(), "Must be a worker thread"); - data(thread)->_worker_id = id; - } - - static uint worker_id(Thread* thread) { - assert(thread->is_Worker_thread(), "Must be a worker thread"); - return data(thread)->_worker_id; - } - static void initialize_gclab(Thread* thread) { assert (thread->is_Java_thread() || thread->is_Worker_thread(), "Only Java and GC worker threads are allowed to get GCLABs"); assert(data(thread)->_gclab == NULL, "Only initialize once"); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahUtils.cpp b/src/hotspot/share/gc/shenandoah/shenandoahUtils.cpp index 4881aff0bf1e46df7877ea21163a8ef222b6a7c1..89db25a80aa2a10d6ebf09e4b6a0df52081bae0a 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahUtils.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahUtils.cpp @@ -146,10 +146,8 @@ ShenandoahGCWorkerPhase::~ShenandoahGCWorkerPhase() { _timings->record_workers_end(_phase); } -ShenandoahWorkerSession::ShenandoahWorkerSession(uint worker_id) : _worker_id(worker_id) { - Thread* thr = Thread::current(); - assert(ShenandoahThreadLocalData::worker_id(thr) == ShenandoahThreadLocalData::INVALID_WORKER_ID, "Already set"); - ShenandoahThreadLocalData::set_worker_id(thr, worker_id); +ShenandoahWorkerSession::ShenandoahWorkerSession(uint worker_id) { + assert(worker_id == WorkerThread::worker_id(), "Wrong worker id"); } ShenandoahConcurrentWorkerSession::~ShenandoahConcurrentWorkerSession() { @@ -157,12 +155,5 @@ ShenandoahConcurrentWorkerSession::~ShenandoahConcurrentWorkerSession() { } ShenandoahParallelWorkerSession::~ShenandoahParallelWorkerSession() { - _event.commit(GCId::current(), _worker_id, ShenandoahPhaseTimings::phase_name(ShenandoahGCPhase::current_phase())); -} -ShenandoahWorkerSession::~ShenandoahWorkerSession() { -#ifdef ASSERT - Thread* thr = Thread::current(); - assert(ShenandoahThreadLocalData::worker_id(thr) != ShenandoahThreadLocalData::INVALID_WORKER_ID, "Must be set"); - ShenandoahThreadLocalData::set_worker_id(thr, ShenandoahThreadLocalData::INVALID_WORKER_ID); -#endif + _event.commit(GCId::current(), WorkerThread::worker_id(), ShenandoahPhaseTimings::phase_name(ShenandoahGCPhase::current_phase())); } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahUtils.hpp b/src/hotspot/share/gc/shenandoah/shenandoahUtils.hpp index 49ff6ca28649f8b729bc12861ef3ac4a02b6a5f5..5b593dbfd0cc99bc28e2c3297ef4157f7f792606 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahUtils.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahUtils.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Red Hat, Inc. All rights reserved. + * Copyright (c) 2017, 2021, Red Hat, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ #include "gc/shared/gcVMOperations.hpp" #include "gc/shared/isGCActiveMark.hpp" #include "gc/shared/suspendibleThreadSet.hpp" +#include "gc/shared/workerThread.hpp" #include "gc/shenandoah/shenandoahPhaseTimings.hpp" #include "gc/shenandoah/shenandoahThreadLocalData.hpp" #include "jfr/jfrEvents.hpp" @@ -173,16 +174,10 @@ public: class ShenandoahWorkerSession : public StackObj { protected: - uint _worker_id; - ShenandoahWorkerSession(uint worker_id); - ~ShenandoahWorkerSession(); public: static inline uint worker_id() { - Thread* thr = Thread::current(); - uint id = ShenandoahThreadLocalData::worker_id(thr); - assert(id != ShenandoahThreadLocalData::INVALID_WORKER_ID, "Worker session has not been created"); - return id; + return WorkerThread::worker_id(); } }; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahWorkGroup.cpp b/src/hotspot/share/gc/shenandoah/shenandoahWorkGroup.cpp index 34202dac6574b8345ce61a4d6d081d0d21770714..d842c87e405c4771ee2eb0e2f9cdea7be138eda0 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahWorkGroup.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahWorkGroup.cpp @@ -71,11 +71,9 @@ ShenandoahPushWorkerScope::~ShenandoahPushWorkerScope() { assert(nworkers == _old_workers, "Must be able to restore"); } -WorkerThread* ShenandoahWorkerThreads::create_worker(uint id) { - WorkerThread* worker = WorkerThreads::create_worker(id); +void ShenandoahWorkerThreads::on_create_worker(WorkerThread* worker) { ShenandoahThreadLocalData::create(worker); if (_initialize_gclab) { ShenandoahThreadLocalData::initialize_gclab(worker); } - return worker; } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahWorkGroup.hpp b/src/hotspot/share/gc/shenandoah/shenandoahWorkGroup.hpp index f5bd3ea0e481b760a7a37ec93f3ce7829476ea0d..a428f26216adebe478814066d77e02c08eb6bf93 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahWorkGroup.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahWorkGroup.hpp @@ -60,9 +60,8 @@ public: WorkerThreads(name, workers), _initialize_gclab(false) { } - // Create a GC worker. // We need to initialize gclab for dynamic allocated workers - WorkerThread* create_worker(uint id); + void on_create_worker(WorkerThread* worker); void set_initialize_gclab() { assert(!_initialize_gclab, "Can only enable once"); _initialize_gclab = true; } }; diff --git a/src/hotspot/share/gc/z/zPhysicalMemory.cpp b/src/hotspot/share/gc/z/zPhysicalMemory.cpp index abdf7df69b08090e2ab7566e63e4082dc01787e0..eb889f4e4f2c31090124948c368e2f80f03ac1a0 100644 --- a/src/hotspot/share/gc/z/zPhysicalMemory.cpp +++ b/src/hotspot/share/gc/z/zPhysicalMemory.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -282,7 +282,7 @@ void ZPhysicalMemoryManager::nmt_commit(uintptr_t offset, size_t size) const { } void ZPhysicalMemoryManager::nmt_uncommit(uintptr_t offset, size_t size) const { - if (MemTracker::tracking_level() > NMT_minimal) { + if (MemTracker::enabled()) { const uintptr_t addr = ZAddress::marked0(offset); Tracker tracker(Tracker::uncommit); tracker.record((address)addr, size); diff --git a/src/hotspot/share/gc/z/zStat.cpp b/src/hotspot/share/gc/z/zStat.cpp index 0df9d061087c7b2c939f474882205981d53fd2c2..540c171ae9f7fad001dff608bff985bfd045f21d 100644 --- a/src/hotspot/share/gc/z/zStat.cpp +++ b/src/hotspot/share/gc/z/zStat.cpp @@ -31,6 +31,7 @@ #include "gc/z/zPageAllocator.inline.hpp" #include "gc/z/zRelocationSetSelector.inline.hpp" #include "gc/z/zStat.hpp" +#include "gc/z/zThread.inline.hpp" #include "gc/z/zTracer.inline.hpp" #include "gc/z/zUtils.hpp" #include "memory/metaspaceUtils.hpp" @@ -736,8 +737,13 @@ ZStatSubPhase::ZStatSubPhase(const char* name) : ZStatPhase("Subphase", name) {} void ZStatSubPhase::register_start(const Ticks& start) const { - LogTarget(Debug, gc, phases, start) log; - log_start(log, true /* thread */); + if (ZThread::is_worker()) { + LogTarget(Trace, gc, phases, start) log; + log_start(log, true /* thread */); + } else { + LogTarget(Debug, gc, phases, start) log; + log_start(log, false /* thread */); + } } void ZStatSubPhase::register_end(const Ticks& start, const Ticks& end) const { @@ -750,8 +756,13 @@ void ZStatSubPhase::register_end(const Ticks& start, const Ticks& end) const { const Tickspan duration = end - start; ZStatSample(_sampler, duration.value()); - LogTarget(Debug, gc, phases) log; - log_end(log, duration, true /* thread */); + if (ZThread::is_worker()) { + LogTarget(Trace, gc, phases) log; + log_end(log, duration, true /* thread */); + } else { + LogTarget(Debug, gc, phases) log; + log_end(log, duration, false /* thread */); + } } ZStatCriticalPhase::ZStatCriticalPhase(const char* name, bool verbose) : diff --git a/src/hotspot/share/gc/z/zTracer.cpp b/src/hotspot/share/gc/z/zTracer.cpp index 2a0d3e11a793778801f4e4df8fdbfbf5f3635cbb..b7d0bc0a697e5c14a0bbf1be1f37523f30d71164 100644 --- a/src/hotspot/share/gc/z/zTracer.cpp +++ b/src/hotspot/share/gc/z/zTracer.cpp @@ -131,3 +131,16 @@ void ZTracer::send_thread_phase(const char* name, const Ticks& start, const Tick e.commit(); } } + +void ZTracer::send_thread_debug(const char* name, const Ticks& start, const Ticks& end) { + NoSafepointVerifier nsv; + + EventZThreadDebug e(UNTIMED); + if (e.should_commit()) { + e.set_gcId(GCId::current_or_undefined()); + e.set_name(name); + e.set_starttime(start); + e.set_endtime(end); + e.commit(); + } +} diff --git a/src/hotspot/share/gc/z/zTracer.hpp b/src/hotspot/share/gc/z/zTracer.hpp index c39a193168ba2d9039408a147cb0a3375396ffdc..3ec97dfa4cbcbde8437478b632321ad58c95826e 100644 --- a/src/hotspot/share/gc/z/zTracer.hpp +++ b/src/hotspot/share/gc/z/zTracer.hpp @@ -39,6 +39,7 @@ private: void send_stat_counter(const ZStatCounter& counter, uint64_t increment, uint64_t value); void send_stat_sampler(const ZStatSampler& sampler, uint64_t value); void send_thread_phase(const char* name, const Ticks& start, const Ticks& end); + void send_thread_debug(const char* name, const Ticks& start, const Ticks& end); public: static ZTracer* tracer(); @@ -47,16 +48,18 @@ public: void report_stat_counter(const ZStatCounter& counter, uint64_t increment, uint64_t value); void report_stat_sampler(const ZStatSampler& sampler, uint64_t value); void report_thread_phase(const char* name, const Ticks& start, const Ticks& end); + void report_thread_debug(const char* name, const Ticks& start, const Ticks& end); }; -class ZTraceThreadPhase : public StackObj { +// For temporary latency measurements during development and debugging +class ZTraceThreadDebug : public StackObj { private: const Ticks _start; const char* const _name; public: - ZTraceThreadPhase(const char* name); - ~ZTraceThreadPhase(); + ZTraceThreadDebug(const char* name); + ~ZTraceThreadDebug(); }; #endif // SHARE_GC_Z_ZTRACER_HPP diff --git a/src/hotspot/share/gc/z/zTracer.inline.hpp b/src/hotspot/share/gc/z/zTracer.inline.hpp index 143eebb4d3b6304b2b4a8a71524593effdf4b012..cfaf7b43f0c463f9fb6cd8903fc48d544d04100c 100644 --- a/src/hotspot/share/gc/z/zTracer.inline.hpp +++ b/src/hotspot/share/gc/z/zTracer.inline.hpp @@ -50,12 +50,18 @@ inline void ZTracer::report_thread_phase(const char* name, const Ticks& start, c } } -inline ZTraceThreadPhase::ZTraceThreadPhase(const char* name) : +inline void ZTracer::report_thread_debug(const char* name, const Ticks& start, const Ticks& end) { + if (EventZThreadDebug::is_enabled()) { + send_thread_debug(name, start, end); + } +} + +inline ZTraceThreadDebug::ZTraceThreadDebug(const char* name) : _start(Ticks::now()), _name(name) {} -inline ZTraceThreadPhase::~ZTraceThreadPhase() { - ZTracer::tracer()->report_thread_phase(_name, _start, Ticks::now()); +inline ZTraceThreadDebug::~ZTraceThreadDebug() { + ZTracer::tracer()->report_thread_debug(_name, _start, Ticks::now()); } #endif // SHARE_GC_Z_ZTRACER_INLINE_HPP diff --git a/src/hotspot/share/include/cds.h b/src/hotspot/share/include/cds.h index eeb45ba34c4d755996d34a081e60893363cc75d3..476f84c34dffbad3e4bcdb8153727805d893e14d 100644 --- a/src/hotspot/share/include/cds.h +++ b/src/hotspot/share/include/cds.h @@ -38,6 +38,7 @@ #define NUM_CDS_REGIONS 7 // this must be the same as MetaspaceShared::n_regions #define CDS_ARCHIVE_MAGIC 0xf00baba2 #define CDS_DYNAMIC_ARCHIVE_MAGIC 0xf00baba8 +#define CDS_GENERIC_HEADER_SUPPORTED_MIN_VERSION 12 #define CURRENT_CDS_ARCHIVE_VERSION 12 typedef struct CDSFileMapRegion { @@ -59,7 +60,8 @@ typedef struct CDSFileMapRegion { char* _mapped_base; // Actually mapped address (NULL if this region is not mapped). } CDSFileMapRegion; -// This portion of the archive file header must remain unchanged for _version >= 12. +// This portion of the archive file header must remain unchanged for +// _version >= CDS_GENERIC_HEADER_SUPPORTED_MIN_VERSION (12). // This makes it possible to read important information from a CDS archive created by // a different version of HotSpot, so that we can automatically regenerate the archive as necessary. typedef struct GenericCDSFileMapHeader { diff --git a/src/hotspot/share/include/jvm.h b/src/hotspot/share/include/jvm.h index 7783b00841d58d1a283501fd1208b0d1de8c0022..e4f56c552b7b45173c4f935daa9ef1ffc90eb8ee 100644 --- a/src/hotspot/share/include/jvm.h +++ b/src/hotspot/share/include/jvm.h @@ -759,6 +759,9 @@ JVM_SupportsCX8(void); JNIEXPORT void JNICALL JVM_ReportFinalizationComplete(JNIEnv *env, jobject finalizee); +JNIEXPORT jboolean JNICALL +JVM_IsFinalizationEnabled(JNIEnv *env); + /************************************************************************* PART 2: Support for the Verifier and Class File Format Checker ************************************************************************/ diff --git a/src/hotspot/share/interpreter/interpreterRuntime.cpp b/src/hotspot/share/interpreter/interpreterRuntime.cpp index 6b178d625602d8db4646967150bd1c292b7361ff..5e61410ddc204637107e30134ac2417f8db73d93 100644 --- a/src/hotspot/share/interpreter/interpreterRuntime.cpp +++ b/src/hotspot/share/interpreter/interpreterRuntime.cpp @@ -407,7 +407,11 @@ JRT_ENTRY(void, InterpreterRuntime::create_klass_exception(JavaThread* current, // lookup exception klass TempNewSymbol s = SymbolTable::new_symbol(name); if (ProfileTraps) { - note_trap(current, Deoptimization::Reason_class_check); + if (s == vmSymbols::java_lang_ArrayStoreException()) { + note_trap(current, Deoptimization::Reason_array_check); + } else { + note_trap(current, Deoptimization::Reason_class_check); + } } // create exception, with klass name as detail message Handle exception = Exceptions::new_exception(current, s, klass_name); @@ -825,7 +829,18 @@ void InterpreterRuntime::resolve_invoke(JavaThread* current, Bytecodes::Code byt JavaThread* THREAD = current; // For exception macros. LinkResolver::resolve_invoke(info, receiver, pool, last_frame.get_index_u2_cpcache(bytecode), bytecode, - CHECK); + THREAD); + + if (HAS_PENDING_EXCEPTION) { + if (ProfileTraps && PENDING_EXCEPTION->klass()->name() == vmSymbols::java_lang_NullPointerException()) { + // Preserve the original exception across the call to note_trap() + PreserveExceptionMark pm(current); + // Recording the trap will help the compiler to potentially recognize this exception as "hot" + note_trap(current, Deoptimization::Reason_null_check); + } + return; + } + if (JvmtiExport::can_hotswap_or_post_breakpoint() && info.resolved_method()->is_old()) { resolved_method = methodHandle(current, info.resolved_method()->get_new_method()); } else { diff --git a/src/hotspot/share/jfr/dcmd/jfrDcmds.cpp b/src/hotspot/share/jfr/dcmd/jfrDcmds.cpp index 9763ed62b76cc3c3e06bc2890b6fc405b9a4c248..319d1c1a4e88047675198413ceb489fda863715b 100644 --- a/src/hotspot/share/jfr/dcmd/jfrDcmds.cpp +++ b/src/hotspot/share/jfr/dcmd/jfrDcmds.cpp @@ -388,12 +388,12 @@ void JfrConfigureFlightRecorderDCmd::print_help(const char* name) const { out->print_cr(" been initalized. (STRING, default determined by the value for"); out->print_cr(" memorysize)"); out->print_cr(""); - out->print_cr(" maxchunksize (Optional) Maximum size of an individual data chunk in bytes if"); + out->print_cr(" maxchunksize (Optional) Maximum size of an individual data chunk in bytes if"); out->print_cr(" one of the following suffixes is not used: 'm' or 'M' for"); out->print_cr(" megabytes OR 'g' or 'G' for gigabytes. This value cannot be"); out->print_cr(" changed once JFR has been initialized. (STRING, 12M)"); out->print_cr(""); - out->print_cr(" memorysize (Optional) Overall memory size, in bytes if one of the following"); + out->print_cr(" memorysize (Optional) Overall memory size, in bytes if one of the following"); out->print_cr(" suffixes is not used: 'm' or 'M' for megabytes OR 'g' or 'G' for"); out->print_cr(" gigabytes. This value cannot be changed once JFR has been"); out->print_cr(" initialized. (STRING, 10M)"); @@ -403,7 +403,11 @@ void JfrConfigureFlightRecorderDCmd::print_help(const char* name) const { out->print_cr(" location is the temporary directory for the operating system. On"); out->print_cr(" Linux operating systems, the temporary directory is /tmp. On"); out->print_cr(" Windows, the temporary directory is specified by the TMP"); - out->print_cr(" environment variable.)"); + out->print_cr(" environment variable)"); + out->print_cr(""); + out->print_cr(" dumppath (Optional) Path to the location where a recording file is written"); + out->print_cr(" in case the VM runs into a critical error, such as a system"); + out->print_cr(" crash. (STRING, The default location is the current directory)"); out->print_cr(""); out->print_cr(" stackdepth (Optional) Stack depth for stack traces. Setting this value"); out->print_cr(" greater than the default of 64 may cause a performance"); @@ -416,7 +420,8 @@ void JfrConfigureFlightRecorderDCmd::print_help(const char* name) const { out->print_cr(" performance and is not recommended. This value cannot be changed"); out->print_cr(" once JFR has been initialized. (STRING, 8k)"); out->print_cr(""); - out->print_cr(" samplethreads (Optional) Flag for activating thread sampling. (BOOLEAN, true)"); + out->print_cr(" samplethreads (Optional) Flag for activating thread sampling. This value cannot"); + out->print_cr(" be changed once JFR has been initialized. (BOOLEAN, true)"); out->print_cr(""); out->print_cr("Options must be specified using the or = syntax."); out->print_cr(""); @@ -467,38 +472,35 @@ void JfrConfigureFlightRecorderDCmd::execute(DCmdSource source, TRAPS) { } jobject stack_depth = NULL; - if (_stack_depth.is_set()) { - stack_depth = JfrJavaSupport::new_java_lang_Integer((jint)_stack_depth.value(), CHECK); - } - jobject global_buffer_count = NULL; - if (_global_buffer_count.is_set()) { - global_buffer_count = JfrJavaSupport::new_java_lang_Long(_global_buffer_count.value(), CHECK); - } - jobject global_buffer_size = NULL; - if (_global_buffer_size.is_set()) { - global_buffer_size = JfrJavaSupport::new_java_lang_Long(_global_buffer_size.value()._size, CHECK); - } - jobject thread_buffer_size = NULL; - if (_thread_buffer_size.is_set()) { - thread_buffer_size = JfrJavaSupport::new_java_lang_Long(_thread_buffer_size.value()._size, CHECK); - } - jobject max_chunk_size = NULL; - if (_max_chunk_size.is_set()) { - max_chunk_size = JfrJavaSupport::new_java_lang_Long(_max_chunk_size.value()._size, CHECK); - } - jobject memory_size = NULL; - if (_memory_size.is_set()) { - memory_size = JfrJavaSupport::new_java_lang_Long(_memory_size.value()._size, CHECK); - } - jobject sample_threads = NULL; - if (_sample_threads.is_set()) { - sample_threads = JfrJavaSupport::new_java_lang_Boolean(_sample_threads.value(), CHECK); + + if (!JfrRecorder::is_created()) { + if (_stack_depth.is_set()) { + stack_depth = JfrJavaSupport::new_java_lang_Integer((jint)_stack_depth.value(), CHECK); + } + if (_global_buffer_count.is_set()) { + global_buffer_count = JfrJavaSupport::new_java_lang_Long(_global_buffer_count.value(), CHECK); + } + if (_global_buffer_size.is_set()) { + global_buffer_size = JfrJavaSupport::new_java_lang_Long(_global_buffer_size.value()._size, CHECK); + } + if (_thread_buffer_size.is_set()) { + thread_buffer_size = JfrJavaSupport::new_java_lang_Long(_thread_buffer_size.value()._size, CHECK); + } + if (_max_chunk_size.is_set()) { + max_chunk_size = JfrJavaSupport::new_java_lang_Long(_max_chunk_size.value()._size, CHECK); + } + if (_memory_size.is_set()) { + memory_size = JfrJavaSupport::new_java_lang_Long(_memory_size.value()._size, CHECK); + } + if (_sample_threads.is_set()) { + sample_threads = JfrJavaSupport::new_java_lang_Boolean(_sample_threads.value(), CHECK); + } } static const char klass[] = "jdk/jfr/internal/dcmd/DCmdConfigure"; diff --git a/src/hotspot/share/jfr/jni/jfrJniMethod.cpp b/src/hotspot/share/jfr/jni/jfrJniMethod.cpp index 54a4680ced84b0dbf67d8a4e8f67400f4ebed6ba..690b02ef36d632f25b214d073f8f45fd1b3f30c3 100644 --- a/src/hotspot/share/jfr/jni/jfrJniMethod.cpp +++ b/src/hotspot/share/jfr/jni/jfrJniMethod.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,6 +35,7 @@ #include "jfr/recorder/repository/jfrRepository.hpp" #include "jfr/recorder/repository/jfrChunkRotation.hpp" #include "jfr/recorder/repository/jfrChunkWriter.hpp" +#include "jfr/recorder/repository/jfrEmergencyDump.hpp" #include "jfr/recorder/service/jfrEventThrottler.hpp" #include "jfr/recorder/service/jfrOptionSet.hpp" #include "jfr/recorder/stacktrace/jfrStackTraceRepository.hpp" @@ -315,6 +316,20 @@ JVM_ENTRY_NO_ENV(void, jfr_set_repository_location(JNIEnv* env, jobject repo, js return JfrRepository::set_path(location, thread); JVM_END +NO_TRANSITION(void, jfr_set_dump_path(JNIEnv* env, jobject jvm, jstring dumppath)) + if (dumppath == NULL) { + JfrEmergencyDump::set_dump_path(NULL); + } else { + const char* dump_path = env->GetStringUTFChars(dumppath, NULL); + JfrEmergencyDump::set_dump_path(dump_path); + env->ReleaseStringUTFChars(dumppath, dump_path); + } +NO_TRANSITION_END + +NO_TRANSITION(jstring, jfr_get_dump_path(JNIEnv* env, jobject jvm)) + return env->NewStringUTF(JfrEmergencyDump::get_dump_path()); +NO_TRANSITION_END + JVM_ENTRY_NO_ENV(void, jfr_uncaught_exception(JNIEnv* env, jobject jvm, jobject t, jthrowable throwable)) JfrJavaSupport::uncaught_exception(throwable, thread); JVM_END diff --git a/src/hotspot/share/jfr/jni/jfrJniMethod.hpp b/src/hotspot/share/jfr/jni/jfrJniMethod.hpp index 19a676c4a22b91fd37f701c1a1803b9937cbe7d4..946ef04470d6ef1f31251e5f31f10ef1a83fda4e 100644 --- a/src/hotspot/share/jfr/jni/jfrJniMethod.hpp +++ b/src/hotspot/share/jfr/jni/jfrJniMethod.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -113,6 +113,10 @@ jlong JNICALL jfr_type_id(JNIEnv* env, jobject jvm, jclass jc); void JNICALL jfr_set_repository_location(JNIEnv* env, jobject repo, jstring location); +void JNICALL jfr_set_dump_path(JNIEnv* env, jobject jvm, jstring dumppath); + +jstring JNICALL jfr_get_dump_path(JNIEnv* env, jobject jvm); + jobject JNICALL jfr_get_event_writer(JNIEnv* env, jclass cls); jobject JNICALL jfr_new_event_writer(JNIEnv* env, jclass cls); diff --git a/src/hotspot/share/jfr/jni/jfrJniMethodRegistration.cpp b/src/hotspot/share/jfr/jni/jfrJniMethodRegistration.cpp index db137776f654429bc06524da936acb0ad0cc6b5c..5bc8a95a826060ce9793e5ee67add7834a090baa 100644 --- a/src/hotspot/share/jfr/jni/jfrJniMethodRegistration.cpp +++ b/src/hotspot/share/jfr/jni/jfrJniMethodRegistration.cpp @@ -75,6 +75,8 @@ JfrJniMethodRegistration::JfrJniMethodRegistration(JNIEnv* env) { (char*)"flush", (char*)"(Ljdk/jfr/internal/EventWriter;II)Z", (void*)jfr_event_writer_flush, (char*)"flush", (char*)"()V", (void*)jfr_flush, (char*)"setRepositoryLocation", (char*)"(Ljava/lang/String;)V", (void*)jfr_set_repository_location, + (char*)"setDumpPath", (char*)"(Ljava/lang/String;)V", (void*)jfr_set_dump_path, + (char*)"getDumpPath", (char*)"()Ljava/lang/String;", (void*)jfr_get_dump_path, (char*)"abort", (char*)"(Ljava/lang/String;)V", (void*)jfr_abort, (char*)"addStringConstant", (char*)"(JLjava/lang/String;)Z", (void*)jfr_add_string_constant, (char*)"uncaughtException", (char*)"(Ljava/lang/Thread;Ljava/lang/Throwable;)V", (void*)jfr_uncaught_exception, diff --git a/src/hotspot/share/jfr/jni/jfrUpcalls.cpp b/src/hotspot/share/jfr/jni/jfrUpcalls.cpp index e8b846d6021f25951b4288ba3f12e719fdc15d10..2040a34a6fae3eba707cbdfe0d9dde5cc19f7591 100644 --- a/src/hotspot/share/jfr/jni/jfrUpcalls.cpp +++ b/src/hotspot/share/jfr/jni/jfrUpcalls.cpp @@ -32,6 +32,7 @@ #include "jfr/support/jfrJdkJfrEvent.hpp" #include "logging/log.hpp" #include "memory/oopFactory.hpp" +#include "memory/resourceArea.hpp" #include "oops/oop.inline.hpp" #include "oops/typeArrayKlass.hpp" #include "oops/typeArrayOop.inline.hpp" @@ -45,6 +46,8 @@ static Symbol* on_retransform_method_sym = NULL; static Symbol* on_retransform_signature_sym = NULL; static Symbol* bytes_for_eager_instrumentation_sym = NULL; static Symbol* bytes_for_eager_instrumentation_sig_sym = NULL; +static Symbol* unhide_internal_types_sym = NULL; +static Symbol* unhide_internal_types_sig_sym = NULL; static bool initialize(TRAPS) { static bool initialized = false; @@ -55,7 +58,9 @@ static bool initialize(TRAPS) { on_retransform_signature_sym = SymbolTable::new_permanent_symbol("(JZLjava/lang/Class;[B)[B"); bytes_for_eager_instrumentation_sym = SymbolTable::new_permanent_symbol("bytesForEagerInstrumentation"); bytes_for_eager_instrumentation_sig_sym = SymbolTable::new_permanent_symbol("(JZLjava/lang/Class;[B)[B"); - initialized = bytes_for_eager_instrumentation_sig_sym != NULL; + unhide_internal_types_sym = SymbolTable::new_permanent_symbol("unhideInternalTypes"); + unhide_internal_types_sig_sym = SymbolTable::new_permanent_symbol("()V"); + initialized = unhide_internal_types_sig_sym != NULL; } return initialized; } @@ -82,7 +87,8 @@ static const typeArrayOop invoke(jlong trace_id, args.push_oop(old_byte_array); JfrJavaSupport::call_static(&args, THREAD); if (HAS_PENDING_EXCEPTION) { - log_error(jfr, system)("JfrUpcall failed"); + ResourceMark rm(THREAD); + log_error(jfr, system)("JfrUpcall failed for %s", method_sym->as_C_string()); return NULL; } // The result should be a [B @@ -179,3 +185,19 @@ void JfrUpcalls::new_bytes_eager_instrumentation(jlong trace_id, *new_class_data_len = new_bytes_length; *new_class_data = new_bytes; } + +bool JfrUpcalls::unhide_internal_types(TRAPS) { + DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD)); + JavaValue result(T_VOID); + const Klass* klass = SystemDictionary::resolve_or_fail(jvm_upcalls_class_sym, true, CHECK_false); + assert(klass != NULL, "invariant"); + JfrJavaArguments args(&result, klass, unhide_internal_types_sym, unhide_internal_types_sig_sym); + JfrJavaSupport::call_static(&args, THREAD); + if (HAS_PENDING_EXCEPTION) { + CLEAR_PENDING_EXCEPTION; + ResourceMark rm(THREAD); + log_error(jfr, system)("JfrUpcall failed for %s", unhide_internal_types_sym->as_C_string()); + return false; + } + return true; +} diff --git a/src/hotspot/share/jfr/jni/jfrUpcalls.hpp b/src/hotspot/share/jfr/jni/jfrUpcalls.hpp index 0bfe7074b4c4cdf7abf43d9d6f7a258dabaf2bd2..cefda39bf6b3b324877af713f7192089183a3b72 100644 --- a/src/hotspot/share/jfr/jni/jfrUpcalls.hpp +++ b/src/hotspot/share/jfr/jni/jfrUpcalls.hpp @@ -53,6 +53,8 @@ class JfrUpcalls : AllStatic { jint* new_class_data_len, unsigned char** new_class_data, TRAPS); + + static bool unhide_internal_types(TRAPS); }; #endif // SHARE_JFR_JNI_JFRUPCALLS_HPP diff --git a/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.cpp b/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.cpp index 8e2a1060528affa137acd154985430da4c2c4824..9325f386e9a57c63ccd2763dfab0e2548a5162c9 100644 --- a/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.cpp +++ b/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.cpp @@ -202,7 +202,7 @@ static void prepare_for_resolution() { static bool stack_trace_precondition(const ObjectSample* sample) { assert(sample != NULL, "invariant"); - return sample->has_stack_trace_id() && !sample->is_dead(); + return sample->has_stack_trace_id() && !sample->is_dead() && !sample->stacktrace().valid(); } class StackTraceBlobInstaller { @@ -249,7 +249,7 @@ void StackTraceBlobInstaller::install(ObjectSample* sample) { writer.write_type(TYPE_STACKTRACE); writer.write_count(1); ObjectSampleCheckpoint::write_stacktrace(stack_trace, writer); - blob = writer.copy(); + blob = writer.move(); _cache.put(sample, blob); sample->set_stacktrace(blob); } @@ -278,7 +278,7 @@ void ObjectSampleCheckpoint::on_rotation(const ObjectSampler* sampler) { } static bool is_klass_unloaded(traceid klass_id) { - assert(ClassLoaderDataGraph_lock->owned_by_self(), "invariant"); + assert_locked_or_safepoint(ClassLoaderDataGraph_lock); return JfrKlassUnloading::is_unloaded(klass_id); } @@ -381,6 +381,12 @@ void ObjectSampleCheckpoint::write(const ObjectSampler* sampler, EdgeStore* edge assert(sampler != NULL, "invariant"); assert(edge_store != NULL, "invariant"); assert(thread != NULL, "invariant"); + { + // First install stacktrace blobs for the most recently added candidates. + MutexLocker lock(SafepointSynchronize::is_at_safepoint() ? nullptr : ClassLoaderDataGraph_lock); + // the lock is needed to ensure the unload lists do not grow in the middle of inspection. + install_stack_traces(sampler); + } write_sample_blobs(sampler, emit_all, thread); // write reference chains if (!edge_store->is_empty()) { diff --git a/src/hotspot/share/jfr/metadata/metadata.xml b/src/hotspot/share/jfr/metadata/metadata.xml index 6a1f426785c9d692d132a89d0dc1d4e2e38f6aab..0b17b5da71548b89858225189b7cd57262824d4e 100644 --- a/src/hotspot/share/jfr/metadata/metadata.xml +++ b/src/hotspot/share/jfr/metadata/metadata.xml @@ -26,6 +26,55 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/hotspot/share/jfr/metadata/metadata.xsd b/src/hotspot/share/jfr/metadata/metadata.xsd index 017307e38473087562db1e2f327309adfa03d3f5..95aa2b94e8cc7d731686d23752f8c7f086239dbd 100644 --- a/src/hotspot/share/jfr/metadata/metadata.xsd +++ b/src/hotspot/share/jfr/metadata/metadata.xsd @@ -1,4 +1,4 @@ - + off -// | -// |--> summary -- -// | | -// |--> detail --+--> minimal -// // Please keep relation of numerical values! -// unknown < off < minimal < summary < detail +// unknown < off < summary < detail // enum NMT_TrackingLevel { - NMT_unknown = 0, - NMT_off = 1, - NMT_minimal = 2, - NMT_summary = 3, - NMT_detail = 4 + NMT_unknown, + NMT_off, + NMT_summary, + NMT_detail }; // Number of stack frames to capture. This is a diff --git a/src/hotspot/share/services/nmtDCmd.cpp b/src/hotspot/share/services/nmtDCmd.cpp index e89dd2c56e703b78e6abd6ce95c555f80a668965..dd8eb17c298bc264c7ec5a2badc552c5c94448cf 100644 --- a/src/hotspot/share/services/nmtDCmd.cpp +++ b/src/hotspot/share/services/nmtDCmd.cpp @@ -50,9 +50,6 @@ NMTDCmd::NMTDCmd(outputStream* output, "comparison against previous baseline, which shows the memory " \ "allocation activities at different callsites.", "BOOLEAN", false, "false"), - _shutdown("shutdown", "request runtime to shutdown itself and free the " \ - "memory used by runtime.", - "BOOLEAN", false, "false"), _statistics("statistics", "print tracker statistics for tuning purpose.", \ "BOOLEAN", false, "false"), _scale("scale", "Memory usage in which scale, KB, MB or GB", @@ -62,7 +59,6 @@ NMTDCmd::NMTDCmd(outputStream* output, _dcmdparser.add_dcmd_option(&_baseline); _dcmdparser.add_dcmd_option(&_summary_diff); _dcmdparser.add_dcmd_option(&_detail_diff); - _dcmdparser.add_dcmd_option(&_shutdown); _dcmdparser.add_dcmd_option(&_statistics); _dcmdparser.add_dcmd_option(&_scale); } @@ -79,9 +75,6 @@ void NMTDCmd::execute(DCmdSource source, TRAPS) { if (MemTracker::tracking_level() == NMT_off) { output()->print_cr("Native memory tracking is not enabled"); return; - } else if (MemTracker::tracking_level() == NMT_minimal) { - output()->print_cr("Native memory tracking has been shutdown"); - return; } const char* scale_value = _scale.value(); @@ -97,12 +90,11 @@ void NMTDCmd::execute(DCmdSource source, TRAPS) { if (_baseline.is_set() && _baseline.value()) { ++nopt; } if (_summary_diff.is_set() && _summary_diff.value()) { ++nopt; } if (_detail_diff.is_set() && _detail_diff.value()) { ++nopt; } - if (_shutdown.is_set() && _shutdown.value()) { ++nopt; } if (_statistics.is_set() && _statistics.value()) { ++nopt; } if (nopt > 1) { output()->print_cr("At most one of the following option can be specified: " \ - "summary, detail, metadata, baseline, summary.diff, detail.diff, shutdown"); + "summary, detail, metadata, baseline, summary.diff, detail.diff"); return; } else if (nopt == 0) { if (_summary.is_set()) { @@ -147,9 +139,6 @@ void NMTDCmd::execute(DCmdSource source, TRAPS) { } else { output()->print_cr("No detail baseline for comparison"); } - } else if (_shutdown.value()) { - MemTracker::shutdown(); - output()->print_cr("Native memory tracking has been turned off"); } else if (_statistics.value()) { if (check_detail_tracking_level(output())) { MemTracker::tuning_statistics(output()); diff --git a/src/hotspot/share/services/nmtDCmd.hpp b/src/hotspot/share/services/nmtDCmd.hpp index 1ea19735cdc41fdfc3127a6cd8a0d3eaa4835c30..52c61d34c0c138d8fc25151454ae70e3cfa76ed0 100644 --- a/src/hotspot/share/services/nmtDCmd.hpp +++ b/src/hotspot/share/services/nmtDCmd.hpp @@ -42,7 +42,6 @@ class NMTDCmd: public DCmdWithParser { DCmdArgument _baseline; DCmdArgument _summary_diff; DCmdArgument _detail_diff; - DCmdArgument _shutdown; DCmdArgument _statistics; DCmdArgument _scale; diff --git a/src/hotspot/share/services/threadStackTracker.cpp b/src/hotspot/share/services/threadStackTracker.cpp index b426e81613bf1a41361a0453a9202fa073e6c98a..5caad66bb89f5558b1d157e96af8da7d33ba50ea 100644 --- a/src/hotspot/share/services/threadStackTracker.cpp +++ b/src/hotspot/share/services/threadStackTracker.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Red Hat, Inc. All rights reserved. + * Copyright (c) 2019, 2021, Red Hat, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,19 +42,6 @@ bool ThreadStackTracker::initialize(NMT_TrackingLevel level) { return true; } -bool ThreadStackTracker::transition(NMT_TrackingLevel from, NMT_TrackingLevel to) { - assert (from != NMT_minimal, "cannot convert from the lowest tracking level to anything"); - if (to == NMT_minimal) { - assert(from == NMT_summary || from == NMT_detail, "Just check"); - ThreadCritical tc; - if (_simple_thread_stacks != NULL) { - delete _simple_thread_stacks; - _simple_thread_stacks = NULL; - } - } - return true; -} - int ThreadStackTracker::compare_thread_stack_base(const SimpleThreadStackSite& s1, const SimpleThreadStackSite& s2) { return s1.base() - s2.base(); } diff --git a/src/hotspot/share/services/threadStackTracker.hpp b/src/hotspot/share/services/threadStackTracker.hpp index 3eee93cd71c4e06b4b6753a1f51aa14b203f6a1c..74e2311b7633e7628a563c326d7a2a434d3000a8 100644 --- a/src/hotspot/share/services/threadStackTracker.hpp +++ b/src/hotspot/share/services/threadStackTracker.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Red Hat, Inc. All rights reserved. + * Copyright (c) 2019, 2021, Red Hat, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -72,7 +72,6 @@ private: static SortedLinkedList* _simple_thread_stacks; public: static bool initialize(NMT_TrackingLevel level); - static bool transition(NMT_TrackingLevel from, NMT_TrackingLevel to); static void new_thread_stack(void* base, size_t size, const NativeCallStack& stack); static void delete_thread_stack(void* base, size_t size); diff --git a/src/hotspot/share/services/virtualMemoryTracker.cpp b/src/hotspot/share/services/virtualMemoryTracker.cpp index f9909f9e5691443077a4c066d6f952771d4a4264..77fb24927f5fee383a934315a3b20c35c6db6947 100644 --- a/src/hotspot/share/services/virtualMemoryTracker.cpp +++ b/src/hotspot/share/services/virtualMemoryTracker.cpp @@ -671,20 +671,3 @@ bool VirtualMemoryTracker::walk_virtual_memory(VirtualMemoryWalker* walker) { } return true; } - -// Transition virtual memory tracking level. -bool VirtualMemoryTracker::transition(NMT_TrackingLevel from, NMT_TrackingLevel to) { - assert (from != NMT_minimal, "cannot convert from the lowest tracking level to anything"); - if (to == NMT_minimal) { - assert(from == NMT_summary || from == NMT_detail, "Just check"); - // Clean up virtual memory tracking data structures. - ThreadCritical tc; - // Check for potential race with other thread calling transition - if (_reserved_regions != NULL) { - delete _reserved_regions; - _reserved_regions = NULL; - } - } - - return true; -} diff --git a/src/hotspot/share/services/virtualMemoryTracker.hpp b/src/hotspot/share/services/virtualMemoryTracker.hpp index a7948f67447ead9d4d1f6933c1ea4740cc054bc7..c96af6b838792b7ec97ff7b27b6898d2fb58cb50 100644 --- a/src/hotspot/share/services/virtualMemoryTracker.hpp +++ b/src/hotspot/share/services/virtualMemoryTracker.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -387,8 +387,6 @@ class VirtualMemoryTracker : AllStatic { // Walk virtual memory data structure for creating baseline, etc. static bool walk_virtual_memory(VirtualMemoryWalker* walker); - static bool transition(NMT_TrackingLevel from, NMT_TrackingLevel to); - // Snapshot current thread stacks static void snapshot_thread_stacks(); diff --git a/src/hotspot/share/utilities/debug.cpp b/src/hotspot/share/utilities/debug.cpp index 778d1a1b4a4ef8759a3359111b8ba325ceffdabe..1a0c3a84647fe1b9c5136304d91da76ad29a74a5 100644 --- a/src/hotspot/share/utilities/debug.cpp +++ b/src/hotspot/share/utilities/debug.cpp @@ -237,7 +237,6 @@ void report_vm_error(const char* file, int line, const char* error_msg) static void print_error_for_unit_test(const char* message, const char* detail_fmt, va_list detail_args) { -#ifdef ASSERT if (ExecutingUnitTests) { char detail_msg[256]; if (detail_fmt != NULL) { @@ -262,7 +261,6 @@ static void print_error_for_unit_test(const char* message, const char* detail_fm va_end(detail_args_copy); } } -#endif // ASSERT } void report_vm_error(const char* file, int line, const char* error_msg, const char* detail_fmt, ...) diff --git a/src/hotspot/share/utilities/globalDefinitions.cpp b/src/hotspot/share/utilities/globalDefinitions.cpp index a1d3cd9ccf386123e35650da261e003fff464a6b..349d99f3311f8eda545d60f1a1f03dd35c57ef86 100644 --- a/src/hotspot/share/utilities/globalDefinitions.cpp +++ b/src/hotspot/share/utilities/globalDefinitions.cpp @@ -39,6 +39,14 @@ int LogBitsPerHeapOop = 0; int BytesPerHeapOop = 0; int BitsPerHeapOop = 0; +// Old CDS options +bool DumpSharedSpaces; +bool DynamicDumpSharedSpaces; +bool RequireSharedSpaces; +extern "C" { +JNIEXPORT jboolean UseSharedSpaces = true; +} + // Object alignment, in units of HeapWords. // Defaults are -1 so things will break badly if incorrectly initialized. int MinObjAlignment = -1; diff --git a/src/hotspot/share/utilities/globalDefinitions.hpp b/src/hotspot/share/utilities/globalDefinitions.hpp index 78a8ffa11bfa9623950c57a257e52509a26d3f2a..1b0b90e70fc00397e455b70644b54dd22141e7f4 100644 --- a/src/hotspot/share/utilities/globalDefinitions.hpp +++ b/src/hotspot/share/utilities/globalDefinitions.hpp @@ -508,6 +508,16 @@ const jfloat max_jfloat = jfloat_cast(max_jintFloat); const int max_method_code_size = 64*K - 1; // JVM spec, 2nd ed. section 4.8.1 (p.134) +//---------------------------------------------------------------------------------------------------- +// old CDS options +extern bool DumpSharedSpaces; +extern bool DynamicDumpSharedSpaces; +extern bool RequireSharedSpaces; +extern "C" { +// Make sure UseSharedSpaces is accessible to the serviceability agent. +extern JNIEXPORT jboolean UseSharedSpaces; +} + //---------------------------------------------------------------------------------------------------- // Object alignment, in units of HeapWords. // diff --git a/src/java.base/share/classes/java/io/ClassCache.java b/src/java.base/share/classes/java/io/ClassCache.java new file mode 100644 index 0000000000000000000000000000000000000000..a3901d479ef12e933ab6bcc1ae9f3a0d87b070be --- /dev/null +++ b/src/java.base/share/classes/java/io/ClassCache.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.io; + +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; +import java.lang.ref.SoftReference; + +// Maps Class instances to values of type T. Under memory pressure, the +// mapping is released (under soft references GC policy) and would be +// recomputed the next time it is queried. The mapping is bound to the +// lifetime of the class: when the class is unloaded, the mapping is +// removed too. +abstract class ClassCache { + + private static class CacheRef extends SoftReference { + private final Class type; + + CacheRef(T referent, ReferenceQueue queue, Class type) { + super(referent, queue); + this.type = type; + } + + Class getType() { + return type; + } + } + + private final ReferenceQueue queue; + private final ClassValue> map; + + protected abstract T computeValue(Class cl); + + protected ClassCache() { + queue = new ReferenceQueue<>(); + map = new ClassValue<>() { + @Override + protected SoftReference computeValue(Class type) { + return new CacheRef<>(ClassCache.this.computeValue(type), queue, type); + } + }; + } + + T get(Class cl) { + processQueue(); + T val; + do { + SoftReference ref = map.get(cl); + val = ref.get(); + if (val == null) { + map.remove(cl); + } + } while (val == null); + return val; + } + + private void processQueue() { + Reference ref; + while((ref = queue.poll()) != null) { + CacheRef cacheRef = (CacheRef)ref; + map.remove(cacheRef.getType()); + } + } +} diff --git a/src/java.base/share/classes/java/io/ObjectInputStream.java b/src/java.base/share/classes/java/io/ObjectInputStream.java index d58bf1d91c9460b02b8bb559c9867e913456f46e..1545db083853a68dcdb9bda662c1e4e445bf6486 100644 --- a/src/java.base/share/classes/java/io/ObjectInputStream.java +++ b/src/java.base/share/classes/java/io/ObjectInputStream.java @@ -297,6 +297,15 @@ public class ObjectInputStream static final boolean SET_FILTER_AFTER_READ = GetBooleanAction .privilegedGetProperty("jdk.serialSetFilterAfterRead"); + /** + * Property to control {@link GetField#get(String, Object)} conversion of + * {@link ClassNotFoundException} to {@code null}. If set to {@code true} + * {@link GetField#get(String, Object)} returns null otherwise + * throwing {@link ClassNotFoundException}. + */ + private static final boolean GETFIELD_CNFE_RETURNS_NULL = GetBooleanAction + .privilegedGetProperty("jdk.serialGetFieldCnfeReturnsNull"); + /** * Property to override the implementation limit on the number * of interfaces allowed for Proxies. The property value is clamped to 0..65535. @@ -1026,10 +1035,7 @@ public class ObjectInputStream if (buf == null) { throw new NullPointerException(); } - int endoff = off + len; - if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) { - throw new IndexOutOfBoundsException(); - } + Objects.checkFromIndexSize(off, len, buf.length); return bin.read(buf, off, len, false); } @@ -1198,10 +1204,7 @@ public class ObjectInputStream * @throws IOException If other I/O error has occurred. */ public void readFully(byte[] buf, int off, int len) throws IOException { - int endoff = off + len; - if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) { - throw new IndexOutOfBoundsException(); - } + Objects.checkFromIndexSize(off, len, buf.length); bin.readFully(buf, off, len, false); } @@ -1596,12 +1599,13 @@ public class ObjectInputStream * @param val the default value to use if {@code name} does not * have a value * @return the value of the named {@code Object} field + * @throws ClassNotFoundException Class of a serialized object cannot be found. * @throws IOException if there are I/O errors while reading from the * underlying {@code InputStream} * @throws IllegalArgumentException if type of {@code name} is * not serializable or if the field type is incorrect */ - public abstract Object get(String name, Object val) throws IOException; + public abstract Object get(String name, Object val) throws IOException, ClassNotFoundException; } /** @@ -2645,13 +2649,19 @@ public class ObjectInputStream return (off >= 0) ? Bits.getDouble(primValues, off) : val; } - public Object get(String name, Object val) { + public Object get(String name, Object val) throws ClassNotFoundException { int off = getFieldOffset(name, Object.class); if (off >= 0) { int objHandle = objHandles[off]; handles.markDependency(passHandle, objHandle); - return (handles.lookupException(objHandle) == null) ? - objValues[off] : null; + ClassNotFoundException ex = handles.lookupException(objHandle); + if (ex == null) + return objValues[off]; + if (Caches.GETFIELD_CNFE_RETURNS_NULL) { + // Revert to the prior behavior; return null instead of CNFE + return null; + } + throw ex; } else { return val; } diff --git a/src/java.base/share/classes/java/io/ObjectOutputStream.java b/src/java.base/share/classes/java/io/ObjectOutputStream.java index 8d34fcec48396aa50ec167c4a814cb524b6a1bac..2a4d455c3a042539fa322f984e49c40fb0ff0b79 100644 --- a/src/java.base/share/classes/java/io/ObjectOutputStream.java +++ b/src/java.base/share/classes/java/io/ObjectOutputStream.java @@ -32,6 +32,7 @@ import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Objects; import java.util.StringJoiner; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -718,10 +719,7 @@ public class ObjectOutputStream if (buf == null) { throw new NullPointerException(); } - int endoff = off + len; - if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) { - throw new IndexOutOfBoundsException(); - } + Objects.checkFromIndexSize(off, len, buf.length); bout.write(buf, off, len, false); } diff --git a/src/java.base/share/classes/java/io/ObjectStreamClass.java b/src/java.base/share/classes/java/io/ObjectStreamClass.java index ff8a934a887da31dadb46a7dd62aa7711127c3b1..343499863f05665f37dcf4b4531e1e77e6573922 100644 --- a/src/java.base/share/classes/java/io/ObjectStreamClass.java +++ b/src/java.base/share/classes/java/io/ObjectStreamClass.java @@ -30,7 +30,6 @@ import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; -import java.lang.ref.SoftReference; import java.lang.ref.WeakReference; import java.lang.reflect.Constructor; import java.lang.reflect.Field; @@ -108,19 +107,22 @@ public class ObjectStreamClass implements Serializable { private static class Caches { /** cache mapping local classes -> descriptors */ - static final ConcurrentMap> localDescs = - new ConcurrentHashMap<>(); + static final ClassCache localDescs = + new ClassCache<>() { + @Override + protected ObjectStreamClass computeValue(Class type) { + return new ObjectStreamClass(type); + } + }; /** cache mapping field group/local desc pairs -> field reflectors */ - static final ConcurrentMap> reflectors = - new ConcurrentHashMap<>(); - - /** queue for WeakReferences to local classes */ - private static final ReferenceQueue> localDescsQueue = - new ReferenceQueue<>(); - /** queue for WeakReferences to field reflectors keys */ - private static final ReferenceQueue> reflectorsQueue = - new ReferenceQueue<>(); + static final ClassCache> reflectors = + new ClassCache<>() { + @Override + protected Map computeValue(Class type) { + return new ConcurrentHashMap<>(); + } + }; } /** class associated with this descriptor (if any) */ @@ -362,136 +364,7 @@ public class ObjectStreamClass implements Serializable { if (!(all || Serializable.class.isAssignableFrom(cl))) { return null; } - processQueue(Caches.localDescsQueue, Caches.localDescs); - WeakClassKey key = new WeakClassKey(cl, Caches.localDescsQueue); - Reference ref = Caches.localDescs.get(key); - Object entry = null; - if (ref != null) { - entry = ref.get(); - } - EntryFuture future = null; - if (entry == null) { - EntryFuture newEntry = new EntryFuture(); - Reference newRef = new SoftReference<>(newEntry); - do { - if (ref != null) { - Caches.localDescs.remove(key, ref); - } - ref = Caches.localDescs.putIfAbsent(key, newRef); - if (ref != null) { - entry = ref.get(); - } - } while (ref != null && entry == null); - if (entry == null) { - future = newEntry; - } - } - - if (entry instanceof ObjectStreamClass) { // check common case first - return (ObjectStreamClass) entry; - } - if (entry instanceof EntryFuture) { - future = (EntryFuture) entry; - if (future.getOwner() == Thread.currentThread()) { - /* - * Handle nested call situation described by 4803747: waiting - * for future value to be set by a lookup() call further up the - * stack will result in deadlock, so calculate and set the - * future value here instead. - */ - entry = null; - } else { - entry = future.get(); - } - } - if (entry == null) { - try { - entry = new ObjectStreamClass(cl); - } catch (Throwable th) { - entry = th; - } - if (future.set(entry)) { - Caches.localDescs.put(key, new SoftReference<>(entry)); - } else { - // nested lookup call already set future - entry = future.get(); - } - } - - if (entry instanceof ObjectStreamClass) { - return (ObjectStreamClass) entry; - } else if (entry instanceof RuntimeException) { - throw (RuntimeException) entry; - } else if (entry instanceof Error) { - throw (Error) entry; - } else { - throw new InternalError("unexpected entry: " + entry); - } - } - - /** - * Placeholder used in class descriptor and field reflector lookup tables - * for an entry in the process of being initialized. (Internal) callers - * which receive an EntryFuture belonging to another thread as the result - * of a lookup should call the get() method of the EntryFuture; this will - * return the actual entry once it is ready for use and has been set(). To - * conserve objects, EntryFutures synchronize on themselves. - */ - private static class EntryFuture { - - private static final Object unset = new Object(); - private final Thread owner = Thread.currentThread(); - private Object entry = unset; - - /** - * Attempts to set the value contained by this EntryFuture. If the - * EntryFuture's value has not been set already, then the value is - * saved, any callers blocked in the get() method are notified, and - * true is returned. If the value has already been set, then no saving - * or notification occurs, and false is returned. - */ - synchronized boolean set(Object entry) { - if (this.entry != unset) { - return false; - } - this.entry = entry; - notifyAll(); - return true; - } - - /** - * Returns the value contained by this EntryFuture, blocking if - * necessary until a value is set. - */ - @SuppressWarnings("removal") - synchronized Object get() { - boolean interrupted = false; - while (entry == unset) { - try { - wait(); - } catch (InterruptedException ex) { - interrupted = true; - } - } - if (interrupted) { - AccessController.doPrivileged( - new PrivilegedAction<>() { - public Void run() { - Thread.currentThread().interrupt(); - return null; - } - } - ); - } - return entry; - } - - /** - * Returns the thread that created this EntryFuture. - */ - Thread getOwner() { - return owner; - } + return Caches.localDescs.get(cl); } /** @@ -2248,82 +2121,39 @@ public class ObjectStreamClass implements Serializable { { // class irrelevant if no fields Class cl = (localDesc != null && fields.length > 0) ? - localDesc.cl : null; - processQueue(Caches.reflectorsQueue, Caches.reflectors); - FieldReflectorKey key = new FieldReflectorKey(cl, fields, - Caches.reflectorsQueue); - Reference ref = Caches.reflectors.get(key); - Object entry = null; - if (ref != null) { - entry = ref.get(); - } - EntryFuture future = null; - if (entry == null) { - EntryFuture newEntry = new EntryFuture(); - Reference newRef = new SoftReference<>(newEntry); - do { - if (ref != null) { - Caches.reflectors.remove(key, ref); - } - ref = Caches.reflectors.putIfAbsent(key, newRef); - if (ref != null) { - entry = ref.get(); - } - } while (ref != null && entry == null); - if (entry == null) { - future = newEntry; - } - } + localDesc.cl : Void.class; - if (entry instanceof FieldReflector) { // check common case first - return (FieldReflector) entry; - } else if (entry instanceof EntryFuture) { - entry = ((EntryFuture) entry).get(); - } else if (entry == null) { - try { - entry = new FieldReflector(matchFields(fields, localDesc)); - } catch (Throwable th) { - entry = th; - } - future.set(entry); - Caches.reflectors.put(key, new SoftReference<>(entry)); - } - - if (entry instanceof FieldReflector) { - return (FieldReflector) entry; - } else if (entry instanceof InvalidClassException) { - throw (InvalidClassException) entry; - } else if (entry instanceof RuntimeException) { - throw (RuntimeException) entry; - } else if (entry instanceof Error) { - throw (Error) entry; - } else { - throw new InternalError("unexpected entry: " + entry); + var clReflectors = Caches.reflectors.get(cl); + var key = new FieldReflectorKey(fields); + var reflector = clReflectors.get(key); + if (reflector == null) { + reflector = new FieldReflector(matchFields(fields, localDesc)); + var oldReflector = clReflectors.putIfAbsent(key, reflector); + if (oldReflector != null) { + reflector = oldReflector; + } } + return reflector; } /** * FieldReflector cache lookup key. Keys are considered equal if they - * refer to the same class and equivalent field formats. + * refer to equivalent field formats. */ - private static class FieldReflectorKey extends WeakReference> { + private static class FieldReflectorKey { private final String[] sigs; private final int hash; - private final boolean nullClass; - FieldReflectorKey(Class cl, ObjectStreamField[] fields, - ReferenceQueue> queue) + FieldReflectorKey(ObjectStreamField[] fields) { - super(cl, queue); - nullClass = (cl == null); sigs = new String[2 * fields.length]; for (int i = 0, j = 0; i < fields.length; i++) { ObjectStreamField f = fields[i]; sigs[j++] = f.getName(); sigs[j++] = f.getSignature(); } - hash = System.identityHashCode(cl) + Arrays.hashCode(sigs); + hash = Arrays.hashCode(sigs); } public int hashCode() { @@ -2331,19 +2161,9 @@ public class ObjectStreamClass implements Serializable { } public boolean equals(Object obj) { - if (obj == this) { - return true; - } - - if (obj instanceof FieldReflectorKey other) { - Class referent; - return (nullClass ? other.nullClass - : ((referent = get()) != null) && - (other.refersTo(referent))) && - Arrays.equals(sigs, other.sigs); - } else { - return false; - } + return obj == this || + obj instanceof FieldReflectorKey other && + Arrays.equals(sigs, other.sigs); } } diff --git a/src/java.base/share/classes/java/io/PipedInputStream.java b/src/java.base/share/classes/java/io/PipedInputStream.java index 883751660295c2d60f5ba904990b76089cca8450..c6034e193cf0fd0abf674e6d4cfc37effcbc20cb 100644 --- a/src/java.base/share/classes/java/io/PipedInputStream.java +++ b/src/java.base/share/classes/java/io/PipedInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ package java.io; +import java.util.Objects; + /** * A piped input stream should be connected * to a piped output stream; the piped input @@ -367,9 +369,9 @@ public class PipedInputStream extends InputStream { public synchronized int read(byte[] b, int off, int len) throws IOException { if (b == null) { throw new NullPointerException(); - } else if (off < 0 || len < 0 || len > b.length - off) { - throw new IndexOutOfBoundsException(); - } else if (len == 0) { + } + Objects.checkFromIndexSize(off, len, b.length); + if (len == 0) { return 0; } diff --git a/src/java.base/share/classes/java/io/PushbackInputStream.java b/src/java.base/share/classes/java/io/PushbackInputStream.java index 398751cdca0ba58ab8a6bfbaaade4c45139d83e5..9076657db266bdf3da0deca2a8cd7fae4742d929 100644 --- a/src/java.base/share/classes/java/io/PushbackInputStream.java +++ b/src/java.base/share/classes/java/io/PushbackInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ package java.io; +import java.util.Objects; + /** * A {@code PushbackInputStream} adds * functionality to another input stream, namely @@ -162,9 +164,9 @@ public class PushbackInputStream extends FilterInputStream { ensureOpen(); if (b == null) { throw new NullPointerException(); - } else if (off < 0 || len < 0 || len > b.length - off) { - throw new IndexOutOfBoundsException(); - } else if (len == 0) { + } + Objects.checkFromIndexSize(off, len, b.length); + if (len == 0) { return 0; } diff --git a/src/java.base/share/classes/java/io/SequenceInputStream.java b/src/java.base/share/classes/java/io/SequenceInputStream.java index 89b0507a5520ac15e76fe246ac07bbaec82595d6..5f692ce6c44de3f855d944dccd688ad403069fd2 100644 --- a/src/java.base/share/classes/java/io/SequenceInputStream.java +++ b/src/java.base/share/classes/java/io/SequenceInputStream.java @@ -25,8 +25,8 @@ package java.io; -import java.io.InputStream; import java.util.Enumeration; +import java.util.Objects; import java.util.Vector; /** @@ -189,9 +189,9 @@ public class SequenceInputStream extends InputStream { return -1; } else if (b == null) { throw new NullPointerException(); - } else if (off < 0 || len < 0 || len > b.length - off) { - throw new IndexOutOfBoundsException(); - } else if (len == 0) { + } + Objects.checkFromIndexSize(off, len, b.length); + if (len == 0) { return 0; } do { diff --git a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java index fce54fcb3d1c6c47d6d293468311178ece75e17b..cf83c825d38f2761d09d6ad7ada7091d7273639c 100644 --- a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java +++ b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java @@ -430,9 +430,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { * {@code beginIndex} is larger than {@code endIndex}. */ public int codePointCount(int beginIndex, int endIndex) { - if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) { - throw new IndexOutOfBoundsException(); - } + Preconditions.checkFromToIndex(beginIndex, endIndex, length(), null); if (isLatin1()) { return endIndex - beginIndex; } diff --git a/src/java.base/share/classes/java/lang/Enum.java b/src/java.base/share/classes/java/lang/Enum.java index 636ad7c757e471c46c86a8ed4b524880b89387af..886461c3a91321fd4dbba1dbdf41a217da6a1380 100644 --- a/src/java.base/share/classes/java/lang/Enum.java +++ b/src/java.base/share/classes/java/lang/Enum.java @@ -275,8 +275,13 @@ public abstract class Enum> /** * enum classes cannot have finalize methods. + * + * @deprecated Finalization has been deprecated for removal. See + * {@link java.lang.Object#finalize} for background information and details + * about migration options. */ - @SuppressWarnings("deprecation") + @Deprecated(since="18", forRemoval=true) + @SuppressWarnings("removal") protected final void finalize() { } /** diff --git a/src/java.base/share/classes/java/lang/Module.java b/src/java.base/share/classes/java/lang/Module.java index ab7d21038507d1c0dc02aacf8f5c87d43311657a..e822c951420669d2cc8c0b2e343b6a385dfd1ca3 100644 --- a/src/java.base/share/classes/java/lang/Module.java +++ b/src/java.base/share/classes/java/lang/Module.java @@ -68,6 +68,7 @@ import jdk.internal.org.objectweb.asm.ModuleVisitor; import jdk.internal.org.objectweb.asm.Opcodes; import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.Reflection; +import jdk.internal.vm.annotation.Stable; import sun.security.util.SecurityConstants; /** @@ -110,7 +111,8 @@ public final class Module implements AnnotatedElement { private final ModuleDescriptor descriptor; // true, if this module allows restricted native access - private volatile boolean enableNativeAccess; + @Stable + private boolean enableNativeAccess; /** * Creates a new named Module. The resulting Module will be defined to the diff --git a/src/java.base/share/classes/java/lang/Object.java b/src/java.base/share/classes/java/lang/Object.java index b8085b230afb03ebf03ae8c6fbc3b1354deb655c..52028ba99a7c42f53659e9ee45a6b5d4b31357a4 100644 --- a/src/java.base/share/classes/java/lang/Object.java +++ b/src/java.base/share/classes/java/lang/Object.java @@ -478,6 +478,12 @@ public class Object { * A subclass overrides the {@code finalize} method to dispose of * system resources or to perform other cleanup. *

+ * When running in a Java virtual machine in which finalization has been + * disabled or removed, the garbage collector will never call + * {@code finalize()}. In a Java virtual machine in which finalization is + * enabled, the garbage collector might call {@code finalize} only after an + * indefinite delay. + *

* The general contract of {@code finalize} is that it is invoked * if and when the Java virtual * machine has determined that there is no longer any @@ -543,27 +549,29 @@ public class Object { * } * } * - * @deprecated The finalization mechanism is inherently problematic. - * Finalization can lead to performance issues, deadlocks, and hangs. - * Errors in finalizers can lead to resource leaks; there is no way to cancel - * finalization if it is no longer necessary; and no ordering is specified - * among calls to {@code finalize} methods of different objects. - * Furthermore, there are no guarantees regarding the timing of finalization. - * The {@code finalize} method might be called on a finalizable object - * only after an indefinite delay, if at all. - * - * Classes whose instances hold non-heap resources should provide a method - * to enable explicit release of those resources, and they should also - * implement {@link AutoCloseable} if appropriate. - * The {@link java.lang.ref.Cleaner} and {@link java.lang.ref.PhantomReference} - * provide more flexible and efficient ways to release resources when an object - * becomes unreachable. + * @deprecated Finalization is deprecated and subject to removal in a future + * release. The use of finalization can lead to problems with security, + * performance, and reliability. + * See JEP 421 for + * discussion and alternatives. + *

+ * Subclasses that override {@code finalize} to perform cleanup should use + * alternative cleanup mechanisms and remove the {@code finalize} method. + * Use {@link java.lang.ref.Cleaner} and + * {@link java.lang.ref.PhantomReference} as safer ways to release resources + * when an object becomes unreachable. Alternatively, add a {@code close} + * method to explicitly release resources, and implement + * {@code AutoCloseable} to enable use of the {@code try}-with-resources + * statement. + *

+ * This method will remain in place until finalizers have been removed from + * most existing code. * * @throws Throwable the {@code Exception} raised by this method * @see java.lang.ref.WeakReference * @see java.lang.ref.PhantomReference * @jls 12.6 Finalization of Class Instances */ - @Deprecated(since="9") + @Deprecated(since="9", forRemoval=true) protected void finalize() throws Throwable { } } diff --git a/src/java.base/share/classes/java/lang/Runtime.java b/src/java.base/share/classes/java/lang/Runtime.java index 2288aca4d1114e4c839dee525a5e995020885f49..c674880c636170f221a1b0f4c35706fa910e066d 100644 --- a/src/java.base/share/classes/java/lang/Runtime.java +++ b/src/java.base/share/classes/java/lang/Runtime.java @@ -707,8 +707,17 @@ public class Runtime { * The method {@link System#runFinalization()} is the conventional * and convenient means of invoking this method. * + * @deprecated Finalization has been deprecated for removal. See + * {@link java.lang.Object#finalize} for background information and details + * about migration options. + *

+ * When running in a JVM in which finalization has been disabled or removed, + * no objects will be pending finalization, so this method does nothing. + * * @see java.lang.Object#finalize() + * @jls 12.6 Finalization of Class Instances */ + @Deprecated(since="18", forRemoval=true) public void runFinalization() { SharedSecrets.getJavaLangRefAccess().runFinalization(); } diff --git a/src/java.base/share/classes/java/lang/String.java b/src/java.base/share/classes/java/lang/String.java index 50e5525bb3eff5341409575c99c5946a2e1a1995..abb35ebaeb16cc81bca8404eecfb0c9dd9ac571e 100644 --- a/src/java.base/share/classes/java/lang/String.java +++ b/src/java.base/share/classes/java/lang/String.java @@ -261,6 +261,7 @@ public final class String this.value = original.value; this.coder = original.coder; this.hash = original.hash; + this.hashIsZero = original.hashIsZero; } /** diff --git a/src/java.base/share/classes/java/lang/System.java b/src/java.base/share/classes/java/lang/System.java index 12a8281343319970c74df440dcaa136a34ef1d88..47b436847cb4ee742d782237d394efc975487a19 100644 --- a/src/java.base/share/classes/java/lang/System.java +++ b/src/java.base/share/classes/java/lang/System.java @@ -1922,8 +1922,18 @@ public final class System { * Runtime.getRuntime().runFinalization() * * + * @deprecated Finalization has been deprecated for removal. See + * {@link java.lang.Object#finalize} for background information and details + * about migration options. + *

+ * When running in a JVM in which finalization has been disabled or removed, + * no objects will be pending finalization, so this method does nothing. + * * @see java.lang.Runtime#runFinalization() + * @jls 12.6 Finalization of Class Instances */ + @Deprecated(since="18", forRemoval=true) + @SuppressWarnings("removal") public static void runFinalization() { Runtime.getRuntime().runFinalization(); } @@ -2321,7 +2331,7 @@ public final class System { public Thread newThreadWithAcc(Runnable target, @SuppressWarnings("removal") AccessControlContext acc) { return new Thread(target, acc); } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") public void invokeFinalize(Object o) throws Throwable { o.finalize(); } diff --git a/src/java.base/share/classes/java/lang/Thread.java b/src/java.base/share/classes/java/lang/Thread.java index 17580d2aa8441c08efae7574c6fee301627c439e..797a7f9f82ec26aa1e1ae87e852d223304ca5e30 100644 --- a/src/java.base/share/classes/java/lang/Thread.java +++ b/src/java.base/share/classes/java/lang/Thread.java @@ -922,7 +922,7 @@ public class Thread implements Runnable { * Why * are Thread.stop, Thread.suspend and Thread.resume Deprecated?. */ - @Deprecated(since="1.2") + @Deprecated(since="1.2", forRemoval=true) public final void stop() { @SuppressWarnings("removal") SecurityManager security = System.getSecurityManager(); diff --git a/src/java.base/share/classes/java/lang/ThreadGroup.java b/src/java.base/share/classes/java/lang/ThreadGroup.java index c6e532a74448925cf4892b9631cfe81b072c7de7..bd55ca1595e5b202fd414e9c84a490f89a126b9f 100644 --- a/src/java.base/share/classes/java/lang/ThreadGroup.java +++ b/src/java.base/share/classes/java/lang/ThreadGroup.java @@ -628,6 +628,7 @@ public class ThreadGroup implements Thread.UncaughtExceptionHandler { * {@link Thread#stop} for details. */ @Deprecated(since="1.2", forRemoval=true) + @SuppressWarnings("removal") public final void stop() { if (stopOrSuspend(false)) Thread.currentThread().stop(); diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java b/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java index a428380443ee650e211d05558add277ef0f07eb0..404782c047e2ae418d95bc2128022bc1b2748e1a 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java @@ -1667,6 +1667,10 @@ abstract class MethodHandleImpl { return caller.makeHiddenClassDefiner(name, bytes, Set.of()).defineClassAsLookup(initialize, classData); } + @Override + public Class[] exceptionTypes(MethodHandle handle) { + return VarHandles.exceptionTypes(handle); + } }); } @@ -2273,15 +2277,16 @@ abstract class MethodHandleImpl { // Indexes into constant method handles: static final int - MH_cast = 0, - MH_selectAlternative = 1, - MH_countedLoopPred = 2, - MH_countedLoopStep = 3, - MH_initIterator = 4, - MH_iteratePred = 5, - MH_iterateNext = 6, - MH_Array_newInstance = 7, - MH_LIMIT = 8; + MH_cast = 0, + MH_selectAlternative = 1, + MH_countedLoopPred = 2, + MH_countedLoopStep = 3, + MH_initIterator = 4, + MH_iteratePred = 5, + MH_iterateNext = 6, + MH_Array_newInstance = 7, + MH_VarHandles_handleCheckedExceptions = 8, + MH_LIMIT = 9; static MethodHandle getConstantHandle(int idx) { MethodHandle handle = HANDLES[idx]; @@ -2331,6 +2336,9 @@ abstract class MethodHandleImpl { case MH_Array_newInstance: return IMPL_LOOKUP.findStatic(Array.class, "newInstance", MethodType.methodType(Object.class, Class.class, int.class)); + case MH_VarHandles_handleCheckedExceptions: + return IMPL_LOOKUP.findStatic(VarHandles.class, "handleCheckedExceptions", + MethodType.methodType(void.class, Throwable.class)); } } catch (ReflectiveOperationException ex) { throw newInternalError(ex); diff --git a/src/java.base/share/classes/java/lang/invoke/VarHandles.java b/src/java.base/share/classes/java/lang/invoke/VarHandles.java index fb86bfab0e8c7deff098c42cc674ec463f2f8ac8..45cdb75b2ee3045549ea1574fcfd0048d052fa6d 100644 --- a/src/java.base/share/classes/java/lang/invoke/VarHandles.java +++ b/src/java.base/share/classes/java/lang/invoke/VarHandles.java @@ -31,12 +31,9 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.lang.reflect.Parameter; import java.nio.ByteOrder; import java.util.ArrayList; -import java.util.LinkedHashMap; import java.util.List; -import java.util.Map; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -45,8 +42,6 @@ import java.util.stream.Stream; import static java.lang.invoke.MethodHandleStatics.UNSAFE; import static java.lang.invoke.MethodHandleStatics.VAR_HANDLE_IDENTITY_ADAPT; import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException; -import static java.util.stream.Collectors.joining; -import static java.util.stream.Collectors.toList; final class VarHandles { @@ -359,13 +354,13 @@ final class VarHandles { return target; } - public static VarHandle filterValue(VarHandle target, MethodHandle filterToTarget, MethodHandle filterFromTarget) { + public static VarHandle filterValue(VarHandle target, MethodHandle pFilterToTarget, MethodHandle pFilterFromTarget) { Objects.requireNonNull(target); - Objects.requireNonNull(filterToTarget); - Objects.requireNonNull(filterFromTarget); + Objects.requireNonNull(pFilterToTarget); + Objects.requireNonNull(pFilterFromTarget); //check that from/to filters do not throw checked exceptions - noCheckedExceptions(filterToTarget); - noCheckedExceptions(filterFromTarget); + MethodHandle filterToTarget = adaptForCheckedExceptions(pFilterToTarget); + MethodHandle filterFromTarget = adaptForCheckedExceptions(pFilterFromTarget); List> newCoordinates = new ArrayList<>(); List> additionalCoordinates = new ArrayList<>(); @@ -473,8 +468,9 @@ final class VarHandles { List> newCoordinates = new ArrayList<>(targetCoordinates); for (int i = 0 ; i < filters.length ; i++) { - noCheckedExceptions(filters[i]); - MethodType filterType = filters[i].type(); + MethodHandle filter = Objects.requireNonNull(filters[i]); + filter = adaptForCheckedExceptions(filter); + MethodType filterType = filter.type(); if (filterType.parameterCount() != 1) { throw newIllegalArgumentException("Invalid filter type " + filterType); } else if (newCoordinates.get(pos + i) != filterType.returnType()) { @@ -564,10 +560,10 @@ final class VarHandles { return adjustedType; } - public static VarHandle collectCoordinates(VarHandle target, int pos, MethodHandle filter) { + public static VarHandle collectCoordinates(VarHandle target, int pos, MethodHandle pFilter) { Objects.requireNonNull(target); - Objects.requireNonNull(filter); - noCheckedExceptions(filter); + Objects.requireNonNull(pFilter); + MethodHandle filter = adaptForCheckedExceptions(pFilter); List> targetCoordinates = target.coordinateTypes(); if (pos < 0 || pos >= targetCoordinates.size()) { @@ -604,42 +600,55 @@ final class VarHandles { (mode, modeHandle) -> MethodHandles.dropArguments(modeHandle, 1 + pos, valueTypes)); } - private static void noCheckedExceptions(MethodHandle handle) { + private static MethodHandle adaptForCheckedExceptions(MethodHandle target) { + Class[] exceptionTypes = exceptionTypes(target); + if (exceptionTypes != null) { // exceptions known + if (Stream.of(exceptionTypes).anyMatch(VarHandles::isCheckedException)) { + throw newIllegalArgumentException("Cannot adapt a var handle with a method handle which throws checked exceptions"); + } + return target; // no adaptation needed + } else { + MethodHandle handler = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_VarHandles_handleCheckedExceptions); + MethodHandle zero = MethodHandles.zero(target.type().returnType()); // dead branch + handler = MethodHandles.collectArguments(zero, 0, handler); + return MethodHandles.catchException(target, Throwable.class, handler); + } + } + + static void handleCheckedExceptions(Throwable throwable) throws Throwable { + if (isCheckedException(throwable.getClass())) { + throw new IllegalStateException("Adapter handle threw checked exception", throwable); + } + throw throwable; + } + + static Class[] exceptionTypes(MethodHandle handle) { if (handle instanceof DirectMethodHandle directHandle) { byte refKind = directHandle.member.getReferenceKind(); MethodHandleInfo info = new InfoFromMemberName( MethodHandles.Lookup.IMPL_LOOKUP, directHandle.member, refKind); - final Class[] exceptionTypes; if (MethodHandleNatives.refKindIsMethod(refKind)) { - exceptionTypes = info.reflectAs(Method.class, MethodHandles.Lookup.IMPL_LOOKUP) + return info.reflectAs(Method.class, MethodHandles.Lookup.IMPL_LOOKUP) .getExceptionTypes(); } else if (MethodHandleNatives.refKindIsField(refKind)) { - exceptionTypes = null; + return new Class[0]; } else if (MethodHandleNatives.refKindIsConstructor(refKind)) { - exceptionTypes = info.reflectAs(Constructor.class, MethodHandles.Lookup.IMPL_LOOKUP) + return info.reflectAs(Constructor.class, MethodHandles.Lookup.IMPL_LOOKUP) .getExceptionTypes(); } else { throw new AssertionError("Cannot get here"); } - if (exceptionTypes != null) { - if (Stream.of(exceptionTypes).anyMatch(VarHandles::isCheckedException)) { - throw newIllegalArgumentException("Cannot adapt a var handle with a method handle which throws checked exceptions"); - } - } } else if (handle instanceof DelegatingMethodHandle) { - noCheckedExceptions(((DelegatingMethodHandle)handle).getTarget()); - } else { - //bound - BoundMethodHandle boundHandle = (BoundMethodHandle)handle; - for (int i = 0 ; i < boundHandle.fieldCount() ; i++) { - Object arg = boundHandle.arg(i); - if (arg instanceof MethodHandle){ - noCheckedExceptions((MethodHandle) arg); - } - } + return exceptionTypes(((DelegatingMethodHandle)handle).getTarget()); + } else if (handle instanceof NativeMethodHandle) { + return new Class[0]; } + + assert handle instanceof BoundMethodHandle : "Unexpected handle type: " + handle; + // unknown + return null; } private static boolean isCheckedException(Class clazz) { diff --git a/src/java.base/share/classes/java/lang/ref/Finalizer.java b/src/java.base/share/classes/java/lang/ref/Finalizer.java index d5838b7a6b1b461d7dff80b400895ffbf089e606..18aedf11bb316f1a7a301559f11c84eeb8c8efa6 100644 --- a/src/java.base/share/classes/java/lang/ref/Finalizer.java +++ b/src/java.base/share/classes/java/lang/ref/Finalizer.java @@ -61,9 +61,17 @@ final class Finalizer extends FinalReference { /* Package-private; must return queue; } + static final boolean ENABLED = isFinalizationEnabled(); + + private static native boolean isFinalizationEnabled(); + /* Invoked by VM */ static void register(Object finalizee) { - new Finalizer(finalizee); + if (ENABLED) { + new Finalizer(finalizee); + } else { + throw new InternalError("unexpected call to Finalizer::register when finalization is disabled"); + } } private void runFinalizer(JavaLangAccess jla) { @@ -130,7 +138,7 @@ final class Finalizer extends FinalReference { /* Package-private; must /* Called by Runtime.runFinalization() */ static void runFinalization() { - if (VM.initLevel() == 0) { + if (VM.initLevel() == 0 || ! ENABLED) { return; } @@ -182,14 +190,16 @@ final class Finalizer extends FinalReference { /* Package-private; must } static { - ThreadGroup tg = Thread.currentThread().getThreadGroup(); - for (ThreadGroup tgn = tg; - tgn != null; - tg = tgn, tgn = tg.getParent()); - Thread finalizer = new FinalizerThread(tg); - finalizer.setPriority(Thread.MAX_PRIORITY - 2); - finalizer.setDaemon(true); - finalizer.start(); + if (ENABLED) { + ThreadGroup tg = Thread.currentThread().getThreadGroup(); + for (ThreadGroup tgn = tg; + tgn != null; + tg = tgn, tgn = tg.getParent()); + Thread finalizer = new FinalizerThread(tg); + finalizer.setPriority(Thread.MAX_PRIORITY - 2); + finalizer.setDaemon(true); + finalizer.start(); + } } } diff --git a/src/java.base/share/classes/java/lang/runtime/ObjectMethods.java b/src/java.base/share/classes/java/lang/runtime/ObjectMethods.java index 5d092328f756e75c39052406b9eda4e5d94896e8..c2d388d01bac0ed9935571a2b130cf49bd256e4d 100644 --- a/src/java.base/share/classes/java/lang/runtime/ObjectMethods.java +++ b/src/java.base/share/classes/java/lang/runtime/ObjectMethods.java @@ -396,15 +396,15 @@ public class ObjectMethods { * if invoked by a condy * @throws IllegalArgumentException if the bootstrap arguments are invalid * or inconsistent - * @throws NullPointerException if any argument but {@code lookup} is {@code null}, - * in the case of the {@code getters} argument, its - * contents cannot be {@code null} either + * @throws NullPointerException if any argument is {@code null} or if any element + * in the {@code getters} array is {@code null} * @throws Throwable if any exception is thrown during call site construction */ public static Object bootstrap(MethodHandles.Lookup lookup, String methodName, TypeDescriptor type, Class recordClass, String names, MethodHandle... getters) throws Throwable { + requireNonNull(lookup); requireNonNull(methodName); requireNonNull(type); requireNonNull(recordClass); diff --git a/src/java.base/share/classes/java/net/ServerSocket.java b/src/java.base/share/classes/java/net/ServerSocket.java index 3d985f84df3cebf5e761d441a807714c56c49f3d..9441e6476e31967d88795e8667b966dd6749ee48 100644 --- a/src/java.base/share/classes/java/net/ServerSocket.java +++ b/src/java.base/share/classes/java/net/ServerSocket.java @@ -78,17 +78,17 @@ import sun.net.PlatformSocketImpl; */ public class ServerSocket implements java.io.Closeable { /** - * Various states of this socket. + * The underlying SocketImpl */ - private boolean created = false; - private boolean bound = false; - private boolean closed = false; - private Object closeLock = new Object(); + private final SocketImpl impl; /** - * The implementation of this Socket. + * Various states of this socket, need stateLock to change. */ - private SocketImpl impl; + private volatile boolean created; // impl.create(boolean) called + private volatile boolean bound; + private volatile boolean closed; + private final Object stateLock = new Object(); /** * Creates a server socket with a user-specified {@code SocketImpl}. @@ -124,7 +124,7 @@ public class ServerSocket implements java.io.Closeable { * @revised 1.4 */ public ServerSocket() throws IOException { - setImpl(); + this.impl = createImpl(); } /** @@ -264,18 +264,15 @@ public class ServerSocket implements java.io.Closeable { * @since 1.1 */ public ServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException { - setImpl(); if (port < 0 || port > 0xFFFF) - throw new IllegalArgumentException( - "Port value out of range: " + port); + throw new IllegalArgumentException("Port value out of range: " + port); if (backlog < 1) - backlog = 50; + backlog = 50; + + this.impl = createImpl(); try { bind(new InetSocketAddress(bindAddr, port), backlog); - } catch(SecurityException e) { - close(); - throw e; - } catch(IOException e) { + } catch (IOException | SecurityException e) { close(); throw e; } @@ -289,35 +286,36 @@ public class ServerSocket implements java.io.Closeable { * @throws SocketException if creation fails. * @since 1.4 */ - SocketImpl getImpl() throws SocketException { - if (!created) - createImpl(); + private SocketImpl getImpl() throws SocketException { + if (!created) { + synchronized (stateLock) { + if (!created) { + if (closed) { + throw new SocketException("Socket is closed"); + } + try { + impl.create(true); + } catch (SocketException e) { + throw e; + } catch (IOException e) { + throw new SocketException(e.getMessage()); + } + created = true; + } + } + } return impl; } - private void setImpl() { + /** + * Create a SocketImpl for a server socket. + */ + private static SocketImpl createImpl() { SocketImplFactory factory = ServerSocket.factory; if (factory != null) { - impl = factory.createSocketImpl(); + return factory.createSocketImpl(); } else { - impl = SocketImpl.createPlatformSocketImpl(true); - } - } - - /** - * Creates the socket implementation. - * - * @throws SocketException if creation fails - * @since 1.4 - */ - void createImpl() throws SocketException { - if (impl == null) - setImpl(); - try { - impl.create(true); - created = true; - } catch (IOException e) { - throw new SocketException(e.getMessage()); + return SocketImpl.createPlatformSocketImpl(true); } } @@ -379,21 +377,21 @@ public class ServerSocket implements java.io.Closeable { if (epoint.isUnresolved()) throw new SocketException("Unresolved address"); if (backlog < 1) - backlog = 50; - try { - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) - security.checkListen(epoint.getPort()); + backlog = 50; + + @SuppressWarnings("removal") + SecurityManager security = System.getSecurityManager(); + if (security != null) + security.checkListen(epoint.getPort()); + + synchronized (stateLock) { + if (closed) + throw new SocketException("Socket is closed"); + if (bound) + throw new SocketException("Already bound"); getImpl().bind(epoint.getAddress(), epoint.getPort()); getImpl().listen(backlog); bound = true; - } catch(SecurityException e) { - bound = false; - throw e; - } catch(IOException e) { - bound = false; - throw e; } } @@ -711,12 +709,15 @@ public class ServerSocket implements java.io.Closeable { * @revised 1.4 */ public void close() throws IOException { - synchronized(closeLock) { - if (isClosed()) - return; - if (created) - impl.close(); - closed = true; + synchronized (stateLock) { + if (!closed) { + closed = true; + + // close underlying socket if created + if (created) { + impl.close(); + } + } } } @@ -760,9 +761,7 @@ public class ServerSocket implements java.io.Closeable { * @since 1.4 */ public boolean isClosed() { - synchronized(closeLock) { - return closed; - } + return closed; } /** @@ -783,7 +782,7 @@ public class ServerSocket implements java.io.Closeable { * @since 1.1 * @see #getSoTimeout() */ - public synchronized void setSoTimeout(int timeout) throws SocketException { + public void setSoTimeout(int timeout) throws SocketException { if (isClosed()) throw new SocketException("Socket is closed"); if (timeout < 0) @@ -799,7 +798,7 @@ public class ServerSocket implements java.io.Closeable { * @since 1.1 * @see #setSoTimeout(int) */ - public synchronized int getSoTimeout() throws IOException { + public int getSoTimeout() throws IOException { if (isClosed()) throw new SocketException("Socket is closed"); Object o = getImpl().getOption(SocketOptions.SO_TIMEOUT); @@ -984,7 +983,7 @@ public class ServerSocket implements java.io.Closeable { * @since 1.4 * @see #getReceiveBufferSize */ - public synchronized void setReceiveBufferSize (int size) throws SocketException { + public void setReceiveBufferSize (int size) throws SocketException { if (!(size > 0)) { throw new IllegalArgumentException("negative receive size"); } @@ -1007,8 +1006,7 @@ public class ServerSocket implements java.io.Closeable { * @see #setReceiveBufferSize(int) * @since 1.4 */ - public synchronized int getReceiveBufferSize() - throws SocketException{ + public int getReceiveBufferSize() throws SocketException { if (isClosed()) throw new SocketException("Socket is closed"); int result = 0; diff --git a/src/java.base/share/classes/java/net/spi/InetAddressResolverProvider.java b/src/java.base/share/classes/java/net/spi/InetAddressResolverProvider.java index 30f1c4f5b3e7e33bc4bc441c3a8a45c883420349..6dff033ffc8897763324c7c18d126f4ea40a13aa 100644 --- a/src/java.base/share/classes/java/net/spi/InetAddressResolverProvider.java +++ b/src/java.base/share/classes/java/net/spi/InetAddressResolverProvider.java @@ -66,7 +66,8 @@ import java.util.ServiceLoader; * *

If instantiating a custom resolver from a provider discovered in * step 1 throws an error or exception, the system-wide resolver will not be - * set and the error or exception will be propagated to the calling thread. + * set and the error or exception will be propagated to the caller of the method + * that triggered the lookup operation. * Otherwise, any lookup operation will be performed using the * system-wide resolver. * @@ -85,7 +86,7 @@ public abstract class InetAddressResolverProvider { * *

Any error or exception thrown by this method is considered as * a failure of {@code InetAddressResolver} instantiation and will be propagated to - * the calling thread. + * the caller of the method that triggered the lookup operation. * @param configuration a {@link Configuration} instance containing platform built-in address * resolution configuration. * @return the resolver provided by this provider diff --git a/src/java.base/share/classes/java/nio/Buffer.java b/src/java.base/share/classes/java/nio/Buffer.java index 607d5d45183d7c25386cf86b425d9b756ad74e63..92c9f80dca8c439fc6e54e411b0b70265333d968 100644 --- a/src/java.base/share/classes/java/nio/Buffer.java +++ b/src/java.base/share/classes/java/nio/Buffer.java @@ -820,7 +820,7 @@ public abstract class Buffer { } @Override - public Scope.Handle acquireScope(Buffer buffer, boolean async) { + public Runnable acquireScope(Buffer buffer, boolean async) { var scope = buffer.scope(); if (scope == null) { return null; @@ -828,7 +828,8 @@ public abstract class Buffer { if (async && scope.ownerThread() != null) { throw new IllegalStateException("Confined scope not supported"); } - return scope.acquire(); + scope.acquire0(); + return scope::release0; } @Override diff --git a/src/java.base/share/classes/java/nio/channels/Channels.java b/src/java.base/share/classes/java/nio/channels/Channels.java index 2d1637c53694973f6b193fd337080198cc0ac118..3e68d49b2b7023f2890f25435067d6dc5a1f563a 100644 --- a/src/java.base/share/classes/java/nio/channels/Channels.java +++ b/src/java.base/share/classes/java/nio/channels/Channels.java @@ -69,9 +69,12 @@ public final class Channels { /** * Constructs a stream that reads bytes from the given channel. * - *

The {@code read} methods of the resulting stream will throw an - * {@link IllegalBlockingModeException} if invoked while the underlying - * channel is in non-blocking mode. The stream will not be buffered, and + *

The {@code read} and {@code transferTo} methods of the resulting stream + * will throw an {@link IllegalBlockingModeException} if invoked while the + * underlying channel is in non-blocking mode. The {@code transferTo} method + * will also throw an {@code IllegalBlockingModeException} if invoked to + * transfer bytes to an output stream that writes to an underlying channel in + * non-blocking mode. The stream will not be buffered, and * it will not support the {@link InputStream#mark mark} or {@link * InputStream#reset reset} methods. The stream will be safe for access by * multiple concurrent threads. Closing the stream will in turn cause the diff --git a/src/java.base/share/classes/java/nio/file/Files.java b/src/java.base/share/classes/java/nio/file/Files.java index 98efa051d11841d4cd00f2b0636dbc2db31d87b2..9c1f92614faef7fe68a4df2df2daf4237aa7c439 100644 --- a/src/java.base/share/classes/java/nio/file/Files.java +++ b/src/java.base/share/classes/java/nio/file/Files.java @@ -1552,7 +1552,7 @@ public final class Files { *

    *
  • The two paths locate the {@linkplain #isSameFile(Path, Path) same file}, * even if two {@linkplain Path#equals(Object) equal} paths locate a file - * does not exist, or
  • + * that does not exist, or *
  • The two files are the same size, and every byte in the first file * is identical to the corresponding byte in the second file.
  • *
@@ -1561,7 +1561,7 @@ public final class Files { * returned by this method is: *
    *
  • The position of the first mismatched byte, or
  • - *
  • The size of the smaller file (in bytes) when the files are different + *
  • The size of the smaller file (in bytes) when the files are of different * sizes and every byte of the smaller file is identical to the * corresponding byte of the larger file.
  • *
diff --git a/src/java.base/share/classes/java/security/KeyStore.java b/src/java.base/share/classes/java/security/KeyStore.java index 2edbe65d26d57b5f69dbf55253b8e04e9e2f0516..efc18f53d33ebfff80457961df2caa35c57e6a49 100644 --- a/src/java.base/share/classes/java/security/KeyStore.java +++ b/src/java.base/share/classes/java/security/KeyStore.java @@ -1020,6 +1020,34 @@ public class KeyStore { return this.type; } + /** + * Retrieves the attributes associated with the given alias. + * + * @param alias the alias name + * @return an unmodifiable {@code Set} of attributes. This set is + * empty if the {@code KeyStoreSpi} implementation has not overridden + * {@link KeyStoreSpi#engineGetAttributes(String)}, or the given + * alias does not exist, or there are no attributes associated + * with the alias. This set may also be empty for + * {@code PrivateKeyEntry} or {@code SecretKeyEntry} + * entries that contain protected attributes and are only available + * through the {@link Entry#getAttributes} method after the entry + * is extracted. + * + * @throws KeyStoreException if the keystore has not been initialized + * (loaded). + * @throws NullPointerException if {@code alias} is {@code null} + * + * @since 18 + */ + public final Set getAttributes(String alias) + throws KeyStoreException { + if (!initialized) { + throw new KeyStoreException("Uninitialized keystore"); + } + return keyStoreSpi.engineGetAttributes(Objects.requireNonNull(alias)); + } + /** * Returns the key associated with the given alias, using the given * password to recover it. The key must have been associated with @@ -1384,7 +1412,9 @@ public class KeyStore { * integrity with the given password. * * @param stream the output stream to which this keystore is written. - * @param password the password to generate the keystore integrity check + * @param password the password to generate the keystore integrity check. + * May be {@code null} if the keystore does not support + * or require an integrity check. * * @throws KeyStoreException if the keystore has not been initialized * (loaded). diff --git a/src/java.base/share/classes/java/security/KeyStoreSpi.java b/src/java.base/share/classes/java/security/KeyStoreSpi.java index 7db1f52042e890f6fe757f62a861f851d139a57b..7702c0c93b5a7d109dabc763f73a02a2ddb77000 100644 --- a/src/java.base/share/classes/java/security/KeyStoreSpi.java +++ b/src/java.base/share/classes/java/security/KeyStoreSpi.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -289,7 +289,9 @@ public abstract class KeyStoreSpi { * integrity with the given password. * * @param stream the output stream to which this keystore is written. - * @param password the password to generate the keystore integrity check + * @param password the password to generate the keystore integrity check. + * May be {@code null} if the keystore does not support + * or require an integrity check. * * @throws IOException if there was an I/O problem with data * @throws NoSuchAlgorithmException if the appropriate data integrity @@ -445,6 +447,30 @@ public abstract class KeyStoreSpi { return; } + /** + * Retrieves the attributes associated with the given alias. + * + * @implSpec + * The default implementation returns an empty {@code Set}. + * {@code KeyStoreSpi} implementations that support attributes + * should override this method. + * + * @param alias the alias name + * @return an unmodifiable {@code Set} of attributes. This set is + * empty if the given alias does not exist or there are no + * attributes associated with the alias. This set may also be + * empty for {@code PrivateKeyEntry} or {@code SecretKeyEntry} + * entries that contain protected attributes. These protected + * attributes should be populated into the result returned by + * {@link #engineGetEntry} and can be retrieved by calling + * the {@link Entry#getAttributes} method. + * + * @since 18 + */ + public Set engineGetAttributes(String alias) { + return Collections.emptySet(); + } + /** * Gets a {@code KeyStore.Entry} for the specified alias * with the specified protection parameter. diff --git a/src/java.base/share/classes/java/security/Provider.java b/src/java.base/share/classes/java/security/Provider.java index 11c8eb29ca70ebcd85dbe7e4047d0a1f19eeb5c4..c6c3d63c61fe26b95542172af29c8d747d7b0179 100644 --- a/src/java.base/share/classes/java/security/Provider.java +++ b/src/java.base/share/classes/java/security/Provider.java @@ -191,6 +191,8 @@ public abstract class Provider extends Properties { this.versionStr = Double.toString(version); this.info = info; this.serviceMap = new ConcurrentHashMap<>(); + this.legacyMap = new ConcurrentHashMap<>(); + this.prngAlgos = new LinkedHashSet(6); putId(); initialized = true; } @@ -229,6 +231,8 @@ public abstract class Provider extends Properties { this.version = parseVersionStr(versionStr); this.info = info; this.serviceMap = new ConcurrentHashMap<>(); + this.legacyMap = new ConcurrentHashMap<>(); + this.prngAlgos = new LinkedHashSet(6); putId(); initialized = true; } @@ -572,7 +576,6 @@ public abstract class Provider extends Properties { public synchronized boolean replace(Object key, Object oldValue, Object newValue) { check("putProviderProperty." + name); - if (debug != null) { debug.println("Replace " + name + " provider property " + key); } @@ -598,7 +601,6 @@ public abstract class Provider extends Properties { @Override public synchronized Object replace(Object key, Object value) { check("putProviderProperty." + name); - if (debug != null) { debug.println("Replace " + name + " provider property " + key); } @@ -627,7 +629,6 @@ public abstract class Provider extends Properties { public synchronized void replaceAll(BiFunction function) { check("putProviderProperty." + name); - if (debug != null) { debug.println("ReplaceAll " + name + " provider property "); } @@ -657,7 +658,6 @@ public abstract class Provider extends Properties { ? super Object, ? extends Object> remappingFunction) { check("putProviderProperty." + name); check("removeProviderProperty." + name); - if (debug != null) { debug.println("Compute " + name + " provider property " + key); } @@ -684,11 +684,10 @@ public abstract class Provider extends Properties { * @since 1.8 */ @Override - public synchronized Object computeIfAbsent(Object key, Function mappingFunction) { + public synchronized Object computeIfAbsent(Object key, + Function mappingFunction) { check("putProviderProperty." + name); check("removeProviderProperty." + name); - if (debug != null) { debug.println("ComputeIfAbsent " + name + " provider property " + key); @@ -714,11 +713,11 @@ public abstract class Provider extends Properties { * @since 1.8 */ @Override - public synchronized Object computeIfPresent(Object key, BiFunction remappingFunction) { + public synchronized Object computeIfPresent(Object key, + BiFunction + remappingFunction) { check("putProviderProperty." + name); check("removeProviderProperty." + name); - if (debug != null) { debug.println("ComputeIfPresent " + name + " provider property " + key); @@ -747,11 +746,11 @@ public abstract class Provider extends Properties { * @since 1.8 */ @Override - public synchronized Object merge(Object key, Object value, BiFunction remappingFunction) { + public synchronized Object merge(Object key, Object value, + BiFunction + remappingFunction) { check("putProviderProperty." + name); check("removeProviderProperty." + name); - if (debug != null) { debug.println("Merge " + name + " provider property " + key); } @@ -777,7 +776,8 @@ public abstract class Provider extends Properties { * @since 1.8 */ @Override - public synchronized void forEach(BiConsumer action) { + public synchronized void forEach(BiConsumer + action) { checkInitialized(); super.forEach(action); } @@ -817,14 +817,11 @@ public abstract class Provider extends Properties { } } - // legacy properties changed since last call to any services method? - private transient boolean legacyChanged; + // legacyMap changed since last call to getServices() + private transient volatile boolean legacyChanged; // serviceMap changed since last call to getServices() private transient volatile boolean servicesChanged; - // Map used to keep track of legacy registration - private transient Map legacyStrings; - // Map // used for services added via putService(), initialized on demand private transient Map serviceMap; @@ -832,6 +829,9 @@ public abstract class Provider extends Properties { // For backward compatibility, the registration ordering of // SecureRandom (RNG) algorithms needs to be preserved for // "new SecureRandom()" calls when this provider is used + // NOTE: may need extra mechanism for providers to indicate their + // preferred ordering of SecureRandom algorithms since registration + // ordering info is lost once serialized private transient Set prngAlgos; // Map @@ -840,7 +840,7 @@ public abstract class Provider extends Properties { // Set // Unmodifiable set of all services. Initialized on demand. - private transient Set serviceSet; + private transient volatile Set serviceSet; // register the id attributes for this provider // this is to ensure that equals() and hashCode() do not incorrectly @@ -872,6 +872,7 @@ public abstract class Provider extends Properties { for (Map.Entry entry : super.entrySet()) { copy.put(entry.getKey(), entry.getValue()); } + defaults = null; in.defaultReadObject(); if (this.versionStr == null) { @@ -882,23 +883,22 @@ public abstract class Provider extends Properties { this.version = parseVersionStr(this.versionStr); } this.serviceMap = new ConcurrentHashMap<>(); + this.legacyMap = new ConcurrentHashMap<>(); + this.prngAlgos = new LinkedHashSet(6); implClear(); initialized = true; putAll(copy); } - // check whether to update 'legacyString' with the specified key - private boolean checkLegacy(Object key) { - String keyString = (String)key; - if (keyString.startsWith("Provider.")) { + // returns false if no update necessary, i.e. key isn't String or + // is String but it's provider-related (name/version/info/className) + private static boolean checkLegacy(Object key) { + if (key instanceof String && ((String)key).startsWith("Provider.")) { + // ignore provider related updates return false; + } else { + return true; } - - legacyChanged = true; - if (legacyStrings == null) { - legacyStrings = new LinkedHashMap<>(); - } - return true; } /** @@ -913,149 +913,161 @@ public abstract class Provider extends Properties { } private Object implRemove(Object key) { - if (key instanceof String) { - if (!checkLegacy(key)) { - return null; - } - legacyStrings.remove((String)key); + if (!checkLegacy(key)) return null; + + Object o = super.remove(key); + if (o instanceof String so && key instanceof String sk) { + parseLegacy(sk, so, OPType.REMOVE); } - return super.remove(key); + return o; } private boolean implRemove(Object key, Object value) { - if (key instanceof String && value instanceof String) { - if (!checkLegacy(key)) { - return false; - } - legacyStrings.remove((String)key, (String)value); + if (!checkLegacy(key)) return false; + + boolean result = super.remove(key, value); + if (result && key instanceof String sk && value instanceof String sv) { + parseLegacy(sk, sv, OPType.REMOVE); } - return super.remove(key, value); + return result; } private boolean implReplace(Object key, Object oldValue, Object newValue) { - if ((key instanceof String) && (oldValue instanceof String) && - (newValue instanceof String)) { - if (!checkLegacy(key)) { - return false; + if (!checkLegacy(key)) return false; + + boolean result = super.replace(key, oldValue, newValue); + if (result && key instanceof String sk) { + if (newValue instanceof String sv) { + parseLegacy(sk, sv, OPType.ADD); + } else if (oldValue instanceof String sv) { + parseLegacy(sk, sv, OPType.REMOVE); } - legacyStrings.replace((String)key, (String)oldValue, - (String)newValue); } - return super.replace(key, oldValue, newValue); + return result; } private Object implReplace(Object key, Object value) { - if ((key instanceof String) && (value instanceof String)) { - if (!checkLegacy(key)) { - return null; + if (!checkLegacy(key)) return null; + + Object o = super.replace(key, value); + if (key instanceof String sk) { + if (o instanceof String so) { + if (value instanceof String sv) { + parseLegacy(sk, sv, OPType.ADD); + } else { + parseLegacy(sk, so, OPType.REMOVE); + } } - legacyStrings.replace((String)key, (String)value); } - return super.replace(key, value); + return o; } @SuppressWarnings("unchecked") // Function must actually operate over strings private void implReplaceAll(BiFunction function) { + + super.replaceAll(function); + // clear out all existing mappings and start fresh + legacyMap.clear(); legacyChanged = true; - if (legacyStrings == null) { - legacyStrings = new LinkedHashMap<>(); - } else { - legacyStrings.replaceAll((BiFunction) function); + for (Map.Entry entry : super.entrySet()) { + Object key = entry.getKey(); + Object value = entry.getValue(); + if ((key instanceof String sk) && (value instanceof String sv)) { + if (!checkLegacy(sk)) { + continue; + } + parseLegacy(sk, sv, OPType.ADD); + } } - super.replaceAll(function); } @SuppressWarnings("unchecked") // Function must actually operate over strings private Object implMerge(Object key, Object value, BiFunction remappingFunction) { - if ((key instanceof String) && (value instanceof String)) { - if (!checkLegacy(key)) { - return null; + if (!checkLegacy(key)) return null; + + Object o = super.merge(key, value, remappingFunction); + if (key instanceof String sk) { + if (o == null) { + parseLegacy(sk, null, OPType.REMOVE); + } else if (o instanceof String so) { + parseLegacy(sk, so, OPType.ADD); } - legacyStrings.merge((String)key, (String)value, - (BiFunction) remappingFunction); } - return super.merge(key, value, remappingFunction); + return o; } @SuppressWarnings("unchecked") // Function must actually operate over strings private Object implCompute(Object key, BiFunction remappingFunction) { - if (key instanceof String) { - if (!checkLegacy(key)) { - return null; + + if (!checkLegacy(key)) return null; + + Object o = super.compute(key, remappingFunction); + if (key instanceof String sk) { + if (o == null) { + parseLegacy(sk, null, OPType.REMOVE); + } else if (o instanceof String so) { + parseLegacy(sk, so, OPType.ADD); } - legacyStrings.compute((String) key, - (BiFunction) remappingFunction); } - return super.compute(key, remappingFunction); + return o; } @SuppressWarnings("unchecked") // Function must actually operate over strings private Object implComputeIfAbsent(Object key, Function mappingFunction) { - if (key instanceof String) { - if (!checkLegacy(key)) { - return null; - } - legacyStrings.computeIfAbsent((String) key, - (Function) - mappingFunction); + if (!checkLegacy(key)) return null; + + Object o = super.computeIfAbsent(key, mappingFunction); + if (o instanceof String so && key instanceof String sk) { + parseLegacy(sk, so, OPType.ADD); } - return super.computeIfAbsent(key, mappingFunction); + return o; } @SuppressWarnings("unchecked") // Function must actually operate over strings private Object implComputeIfPresent(Object key, BiFunction remappingFunction) { - if (key instanceof String) { - if (!checkLegacy(key)) { - return null; - } - legacyStrings.computeIfPresent((String) key, - (BiFunction) remappingFunction); + if (!checkLegacy(key)) return null; + + Object o = super.computeIfPresent(key, remappingFunction); + if (o instanceof String so && key instanceof String sk) { + parseLegacy(sk, so, OPType.ADD); } - return super.computeIfPresent(key, remappingFunction); + return o; } private Object implPut(Object key, Object value) { - if ((key instanceof String) && (value instanceof String)) { - if (!checkLegacy(key)) { - return null; - } - legacyStrings.put((String)key, (String)value); + if (!checkLegacy(key)) return null; + + Object o = super.put(key, value); + if (key instanceof String sk && value instanceof String sv) { + parseLegacy(sk, sv, OPType.ADD); } - return super.put(key, value); + return o; } private Object implPutIfAbsent(Object key, Object value) { - if ((key instanceof String) && (value instanceof String)) { - if (!checkLegacy(key)) { - return null; - } - legacyStrings.putIfAbsent((String)key, (String)value); + if (!checkLegacy(key)) return null; + + Object o = super.putIfAbsent(key, value); + if (o == null && key instanceof String sk && + value instanceof String sv) { + parseLegacy(sk, sv, OPType.ADD); } - return super.putIfAbsent(key, value); + return o; } private void implClear() { - if (legacyStrings != null) { - legacyStrings.clear(); - } - if (legacyMap != null) { - legacyMap.clear(); - } + legacyMap.clear(); serviceMap.clear(); legacyChanged = false; servicesChanged = false; serviceSet = null; - prngAlgos = null; + prngAlgos.clear(); super.clear(); putId(); } @@ -1085,40 +1097,8 @@ public abstract class Provider extends Properties { boolean matches(String type, String algorithm) { return (this.type == type) && (this.originalAlgorithm == algorithm); } - } - - /** - * Ensure all the legacy String properties are fully parsed into - * service objects. - */ - private void ensureLegacyParsed() { - if (legacyChanged == false || (legacyStrings == null)) { - return; - } - serviceSet = null; - if (legacyMap == null) { - legacyMap = new ConcurrentHashMap<>(); - } else { - legacyMap.clear(); - } - for (Map.Entry entry : legacyStrings.entrySet()) { - parseLegacyPut(entry.getKey(), entry.getValue()); - } - removeInvalidServices(legacyMap); - legacyChanged = false; - } - - /** - * Remove all invalid services from the Map. Invalid services can only - * occur if the legacy properties are inconsistent or incomplete. - */ - private void removeInvalidServices(Map map) { - for (Iterator> t = - map.entrySet().iterator(); t.hasNext(); ) { - Service s = t.next().getValue(); - if (s.isValid() == false) { - t.remove(); - } + public String toString() { + return type + "." + algorithm; } } @@ -1136,71 +1116,136 @@ public abstract class Provider extends Properties { return new String[] {type, alg}; } + // utility method for getting a String with service type and algorithm + private static String getKey(Service s) { + return s.getType() + "." + s.getAlgorithm(); + } + private static final String ALIAS_PREFIX = "Alg.Alias."; private static final String ALIAS_PREFIX_LOWER = "alg.alias."; private static final int ALIAS_LENGTH = ALIAS_PREFIX.length(); - private void parseLegacyPut(String name, String value) { + private static enum OPType { + ADD, REMOVE; + } + + private void parseLegacy(String name, String value, OPType opType) { + // alias if (name.toLowerCase(ENGLISH).startsWith(ALIAS_PREFIX_LOWER)) { // e.g. put("Alg.Alias.MessageDigest.SHA", "SHA-1"); // aliasKey ~ MessageDigest.SHA - String stdAlg = value; - String aliasKey = name.substring(ALIAS_LENGTH); - String[] typeAndAlg = getTypeAndAlgorithm(aliasKey); + String aliasKeyStr = name.substring(ALIAS_LENGTH); + String[] typeAndAlg = getTypeAndAlgorithm(aliasKeyStr); if (typeAndAlg == null) { return; } + legacyChanged = true; + Objects.requireNonNull(value, "alias value should map to an alg"); String type = getEngineName(typeAndAlg[0]); String aliasAlg = typeAndAlg[1].intern(); - ServiceKey key = new ServiceKey(type, stdAlg, true); - Service s = legacyMap.get(key); - if (s == null) { - s = new Service(this, type, stdAlg); - legacyMap.put(key, s); + ServiceKey stdKey = new ServiceKey(type, value, true); + Service stdService = legacyMap.get(stdKey); + ServiceKey aliasKey = new ServiceKey(type, aliasAlg, true); + switch (opType) { + case ADD: + // clean up old alias if present + Service prevAliasService = legacyMap.get(aliasAlg); + if (prevAliasService != null) { + prevAliasService.removeAlias(aliasAlg); + } + if (stdService == null) { + // add standard mapping in order to add alias + stdService = new Service(this, type, value); + legacyMap.put(stdKey, stdService); + } + stdService.addAlias(aliasAlg); + legacyMap.put(aliasKey, stdService); + break; + case REMOVE: + if (stdService != null) { + stdService.removeAlias(aliasAlg); + } + legacyMap.remove(aliasKey); + break; + default: + throw new AssertionError(); } - legacyMap.put(new ServiceKey(type, aliasAlg, true), s); - s.addAlias(aliasAlg); } else { String[] typeAndAlg = getTypeAndAlgorithm(name); if (typeAndAlg == null) { return; } + legacyChanged = true; int i = typeAndAlg[1].indexOf(' '); + // regular registration if (i == -1) { // e.g. put("MessageDigest.SHA-1", "sun.security.provider.SHA"); String type = getEngineName(typeAndAlg[0]); String stdAlg = typeAndAlg[1].intern(); - String className = value; - ServiceKey key = new ServiceKey(type, stdAlg, true); - Service s = legacyMap.get(key); - if (s == null) { - s = new Service(this, type, stdAlg); - legacyMap.put(key, s); - } - s.className = className; - - if (type.equals("SecureRandom")) { - updateSecureRandomEntries(true, s.algorithm); + ServiceKey stdKey = new ServiceKey(type, stdAlg, true); + Service stdService = legacyMap.get(stdKey); + switch (opType) { + case ADD: + Objects.requireNonNull(value, + "className can't be null"); + if (stdService == null) { + stdService = new Service(this, type, stdAlg); + legacyMap.put(stdKey, stdService); + } + stdService.className = value; + break; + case REMOVE: + // only remove if value also matches when non-null + if (stdService != null) { + if (value == null) { + legacyMap.remove(stdKey); + } else if (stdService.className.equals(value)) { + legacyMap.remove(stdKey, stdService); + } + // remove all corresponding alias mappings + for (String alias : stdService.getAliases()) { + legacyMap.remove(new ServiceKey(type, alias, + true), stdService); + } + } + break; + default: + throw new AssertionError(); } + checkAndUpdateSecureRandom(type, stdAlg, + (opType != OPType.REMOVE)); } else { // attribute // e.g. put("MessageDigest.SHA-1 ImplementedIn", "Software"); - String attributeValue = value; String type = getEngineName(typeAndAlg[0]); - String attributeString = typeAndAlg[1]; - String stdAlg = attributeString.substring(0, i).intern(); - String attributeName = attributeString.substring(i + 1); + String attrString = typeAndAlg[1]; + String stdAlg = attrString.substring(0, i).intern(); + String attrName = attrString.substring(i + 1); // kill additional spaces - while (attributeName.startsWith(" ")) { - attributeName = attributeName.substring(1); + while (attrName.startsWith(" ")) { + attrName = attrName.substring(1); } - attributeName = attributeName.intern(); - ServiceKey key = new ServiceKey(type, stdAlg, true); - Service s = legacyMap.get(key); - if (s == null) { - s = new Service(this, type, stdAlg); - legacyMap.put(key, s); + attrName = attrName.intern(); + ServiceKey stdKey = new ServiceKey(type, stdAlg, true); + Service stdService = legacyMap.get(stdKey); + switch (opType) { + case ADD: + Objects.requireNonNull(value, + "attribute value should not be null"); + + if (stdService == null) { + stdService = new Service(this, type, stdAlg); + legacyMap.put(stdKey, stdService); + } + stdService.addAttribute(attrName, value); + break; + case REMOVE: + if (stdService != null) { + stdService.removeAttribute(attrName, value); + } + break; + default: + throw new AssertionError(); } - s.addAttribute(attributeName, attributeValue); } } } @@ -1227,25 +1272,25 @@ public abstract class Provider extends Properties { */ public Service getService(String type, String algorithm) { checkInitialized(); - // avoid allocating a new ServiceKey object if possible ServiceKey key = previousKey; if (key.matches(type, algorithm) == false) { key = new ServiceKey(type, algorithm, false); previousKey = key; } - if (!serviceMap.isEmpty()) { - Service s = serviceMap.get(key); - if (s != null) { - return s; - } + + Service s = serviceMap.get(key); + if (s != null) { + return s; } - synchronized (this) { - ensureLegacyParsed(); - if (legacyMap != null && !legacyMap.isEmpty()) { - return legacyMap.get(key); - } + + s = legacyMap.get(key); + if (s != null && !s.isValid()) { + legacyMap.remove(key, s); + } else { + return s; } + return null; } @@ -1267,22 +1312,19 @@ public abstract class Provider extends Properties { * * @since 1.5 */ - public synchronized Set getServices() { + public Set getServices() { checkInitialized(); - if (legacyChanged || servicesChanged) { - serviceSet = null; - } - if (serviceSet == null) { - ensureLegacyParsed(); + if (serviceSet == null || legacyChanged || servicesChanged) { Set set = new LinkedHashSet<>(); if (!serviceMap.isEmpty()) { set.addAll(serviceMap.values()); } - if (legacyMap != null && !legacyMap.isEmpty()) { + if (!legacyMap.isEmpty()) { set.addAll(legacyMap.values()); } serviceSet = Collections.unmodifiableSet(set); servicesChanged = false; + legacyChanged = false; } return serviceSet; } @@ -1339,44 +1381,36 @@ public abstract class Provider extends Properties { servicesChanged = true; synchronized (this) { putPropertyStrings(s); - if (type.equals("SecureRandom")) { - updateSecureRandomEntries(true, s.algorithm); - } + checkAndUpdateSecureRandom(type, algorithm, true); } } - // keep tracks of the registered secure random algos and store them in order - private void updateSecureRandomEntries(boolean doAdd, String s) { - Objects.requireNonNull(s); - if (doAdd) { - if (prngAlgos == null) { - prngAlgos = new LinkedHashSet(); + private void checkAndUpdateSecureRandom(String type, String algo, + boolean doAdd) { + if (type.equalsIgnoreCase("SecureRandom")) { + if (doAdd) { + prngAlgos.add(algo); + } else { + prngAlgos.remove(algo); + } + if (debug != null) { + debug.println((doAdd? "Add":"Remove") + + " SecureRandom algo " + algo); } - prngAlgos.add(s); - } else { - prngAlgos.remove(s); - } - - if (debug != null) { - debug.println((doAdd? "Add":"Remove") + " SecureRandom algo " + s); } } // used by new SecureRandom() to find out the default SecureRandom // service for this provider - synchronized Service getDefaultSecureRandomService() { + Service getDefaultSecureRandomService() { checkInitialized(); - if (legacyChanged) { - prngAlgos = null; - ensureLegacyParsed(); - } - - if (prngAlgos != null && !prngAlgos.isEmpty()) { + if (!prngAlgos.isEmpty()) { + String algo = prngAlgos.iterator().next(); // IMPORTANT: use the Service obj returned by getService(...) call // as providers may override putService(...)/getService(...) and // return their own Service objects - return getService("SecureRandom", prngAlgos.iterator().next()); + return getService("SecureRandom", algo); } return null; @@ -1473,12 +1507,9 @@ public abstract class Provider extends Properties { for (String alias : s.getAliases()) { serviceMap.remove(new ServiceKey(type, alias, false)); } - synchronized (this) { - removePropertyStrings(s); - if (type.equals("SecureRandom")) { - updateSecureRandomEntries(false, s.algorithm); - } - } + + removePropertyStrings(s); + checkAndUpdateSecureRandom(type, algorithm, false); } // Wrapped String that behaves in a case insensitive way for equals/hashCode @@ -1686,6 +1717,13 @@ public abstract class Provider extends Properties { aliases.add(alias); } + private void removeAlias(String alias) { + if (aliases.isEmpty()) { + return; + } + aliases.remove(alias); + } + void addAttribute(String type, String value) { if (attributes.isEmpty()) { attributes = new HashMap<>(8); @@ -1693,6 +1731,17 @@ public abstract class Provider extends Properties { attributes.put(new UString(type), value); } + void removeAttribute(String type, String value) { + if (attributes.isEmpty()) { + return; + } + if (value == null) { + attributes.remove(new UString(type)); + } else { + attributes.remove(new UString(type), value); + } + } + /** * Construct a new service. * diff --git a/src/java.base/share/classes/java/time/format/DateTimeFormatter.java b/src/java.base/share/classes/java/time/format/DateTimeFormatter.java index c94b123b26c9d5a57e3e1793d4cbd9b189298a21..063b6e14a00f5d79a3927e5d787d812961b57b3b 100644 --- a/src/java.base/share/classes/java/time/format/DateTimeFormatter.java +++ b/src/java.base/share/classes/java/time/format/DateTimeFormatter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -81,6 +81,7 @@ import java.time.Period; import java.time.ZoneId; import java.time.ZoneOffset; import java.time.chrono.ChronoLocalDateTime; +import java.time.chrono.ChronoZonedDateTime; import java.time.chrono.Chronology; import java.time.chrono.IsoChronology; import java.time.format.DateTimeFormatterBuilder.CompositePrinterParser; @@ -373,15 +374,15 @@ import sun.util.locale.provider.TimeZoneNameUtility; * letters throws {@code IllegalArgumentException}. *

* Zone names: This outputs the display name of the time-zone ID. If the - * pattern letter is 'z' the output is the daylight savings aware zone name. + * pattern letter is 'z' the output is the daylight saving aware zone name. * If there is insufficient information to determine whether DST applies, - * the name ignoring daylight savings time will be used. + * the name ignoring daylight saving time will be used. * If the count of letters is one, two or three, then the short name is output. * If the count of letters is four, then the full name is output. * Five or more letters throws {@code IllegalArgumentException}. *

* If the pattern letter is 'v' the output provides the zone name ignoring - * daylight savings time. If the count of letters is one, then the short name is output. + * daylight saving time. If the count of letters is one, then the short name is output. * If the count of letters is four, then the full name is output. * Two, three and five or more letters throw {@code IllegalArgumentException}. *

@@ -502,7 +503,10 @@ import sun.util.locale.provider.TimeZoneNameUtility; * {@code LocalDateTime} to form the instant, with any zone ignored. * If a {@code ZoneId} was parsed without an offset then the zone will be * combined with the {@code LocalDateTime} to form the instant using the rules - * of {@link ChronoLocalDateTime#atZone(ZoneId)}. + * of {@link ChronoLocalDateTime#atZone(ZoneId)}. If the {@code ZoneId} was + * parsed from a zone name that indicates whether daylight saving time is in + * operation or not, then that fact will be used to select the correct offset + * at the local time-line overlap. * * * @implSpec diff --git a/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java b/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java index 7af964f106b8aef27047a10a5c72b72fcfd185c5..40c0de53d3f6770ad3e8e254dd03a57f478a2262 100644 --- a/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java +++ b/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java @@ -4324,9 +4324,10 @@ public final class DateTimeFormatterBuilder { } } - private static final int STD = 0; - private static final int DST = 1; - private static final int GENERIC = 2; + static final int UNDEFINED = -1; + static final int STD = 0; + static final int DST = 1; + static final int GENERIC = 2; private static final Map>> cache = new ConcurrentHashMap<>(); @@ -4433,11 +4434,11 @@ public final class DateTimeFormatterBuilder { nonRegionIds.add(zid); continue; } - tree.add(zid, zid); // don't convert zid -> metazone + tree.add(zid, zid, UNDEFINED); // don't convert zid -> metazone zid = ZoneName.toZid(zid, locale); int i = textStyle == TextStyle.FULL ? 1 : 2; for (; i < names.length; i += 2) { - tree.add(names[i], zid); + tree.add(names[i], zid, (i - 1) / 2); } } @@ -4450,7 +4451,7 @@ public final class DateTimeFormatterBuilder { int i = textStyle == TextStyle.FULL ? 1 : 2; for (; i < cidNames.length; i += 2) { if (cidNames[i] != null && !cidNames[i].isEmpty()) { - t.add(cidNames[i], cid); + t.add(cidNames[i], cid, (i - 1) / 2); } } }); @@ -4465,7 +4466,7 @@ public final class DateTimeFormatterBuilder { } int i = textStyle == TextStyle.FULL ? 1 : 2; for (; i < names.length; i += 2) { - tree.add(names[i], zid); + tree.add(names[i], zid, (i - 1) / 2); } } } @@ -4571,15 +4572,16 @@ public final class DateTimeFormatterBuilder { // parse PrefixTree tree = getTree(context); ParsePosition ppos = new ParsePosition(position); - String parsedZoneId = tree.match(text, ppos); - if (parsedZoneId == null) { + PrefixTree parsedZoneId = tree.match(text, ppos); + if (parsedZoneId.value == null) { if (context.charEquals(nextChar, 'Z')) { context.setParsed(ZoneOffset.UTC); return position + 1; } return ~position; } - context.setParsed(ZoneId.of(parsedZoneId)); + context.setParsed(ZoneId.of(parsedZoneId.value)); + context.setParsedZoneNameType(parsedZoneId.type); return ppos.getIndex(); } @@ -4641,14 +4643,16 @@ public final class DateTimeFormatterBuilder { static class PrefixTree { protected String key; protected String value; + protected int type; protected char c0; // performance optimization to avoid the // boundary check cost of key.charat(0) protected PrefixTree child; protected PrefixTree sibling; - private PrefixTree(String k, String v, PrefixTree child) { + private PrefixTree(String k, String v, int type, PrefixTree child) { this.key = k; this.value = v; + this.type = type; this.child = child; if (k.isEmpty()) { c0 = 0xffff; @@ -4664,13 +4668,10 @@ public final class DateTimeFormatterBuilder { * @return the tree, not null */ public static PrefixTree newTree(DateTimeParseContext context) { - //if (!context.isStrict()) { - // return new LENIENT("", null, null); - //} if (context.isCaseSensitive()) { - return new PrefixTree("", null, null); + return new PrefixTree("", null, ZoneTextPrinterParser.UNDEFINED, null); } - return new CI("", null, null); + return new CI("", null, ZoneTextPrinterParser.UNDEFINED, null); } /** @@ -4683,7 +4684,7 @@ public final class DateTimeFormatterBuilder { public static PrefixTree newTree(Set keys, DateTimeParseContext context) { PrefixTree tree = newTree(context); for (String k : keys) { - tree.add0(k, k); + tree.add0(k, k, ZoneTextPrinterParser.UNDEFINED); } return tree; } @@ -4692,7 +4693,7 @@ public final class DateTimeFormatterBuilder { * Clone a copy of this tree */ public PrefixTree copyTree() { - PrefixTree copy = new PrefixTree(key, value, null); + PrefixTree copy = new PrefixTree(key, value, type, null); if (child != null) { copy.child = child.copyTree(); } @@ -4710,11 +4711,11 @@ public final class DateTimeFormatterBuilder { * @param v the value, not null * @return true if the pair is added successfully */ - public boolean add(String k, String v) { - return add0(k, v); + public boolean add(String k, String v, int t) { + return add0(k, v, t); } - private boolean add0(String k, String v) { + private boolean add0(String k, String v, int t) { k = toKey(k); int prefixLen = prefixLength(k); if (prefixLen == key.length()) { @@ -4723,12 +4724,12 @@ public final class DateTimeFormatterBuilder { PrefixTree c = child; while (c != null) { if (isEqual(c.c0, subKey.charAt(0))) { - return c.add0(subKey, v); + return c.add0(subKey, v, t); } c = c.sibling; } // add the node as the child of the current node - c = newNode(subKey, v, null); + c = newNode(subKey, v, t, null); c.sibling = child; child = c; return true; @@ -4738,18 +4739,20 @@ public final class DateTimeFormatterBuilder { // return false; //} value = v; + type = t; return true; } // split the existing node - PrefixTree n1 = newNode(key.substring(prefixLen), value, child); + PrefixTree n1 = newNode(key.substring(prefixLen), value, type, child); key = k.substring(0, prefixLen); child = n1; if (prefixLen < k.length()) { - PrefixTree n2 = newNode(k.substring(prefixLen), v, null); + PrefixTree n2 = newNode(k.substring(prefixLen), v, t, null); child.sibling = n2; value = null; } else { value = v; + type = t; } return true; } @@ -4760,9 +4763,9 @@ public final class DateTimeFormatterBuilder { * @param text the input text to parse, not null * @param off the offset position to start parsing at * @param end the end position to stop parsing - * @return the resulting string, or null if no match found. + * @return the resulting tree, or null if no match found. */ - public String match(CharSequence text, int off, int end) { + public PrefixTree match(CharSequence text, int off, int end) { if (!prefixOf(text, off, end)){ return null; } @@ -4770,16 +4773,16 @@ public final class DateTimeFormatterBuilder { PrefixTree c = child; do { if (isEqual(c.c0, text.charAt(off))) { - String found = c.match(text, off, end); + PrefixTree found = c.match(text, off, end); if (found != null) { return found; } - return value; + return this; } c = c.sibling; } while (c != null); } - return value; + return this; } /** @@ -4789,9 +4792,9 @@ public final class DateTimeFormatterBuilder { * @param pos the position to start parsing at, from 0 to the text * length. Upon return, position will be updated to the new parse * position, or unchanged, if no match found. - * @return the resulting string, or null if no match found. + * @return the resulting tree, or null if no match found. */ - public String match(CharSequence text, ParsePosition pos) { + public PrefixTree match(CharSequence text, ParsePosition pos) { int off = pos.getIndex(); int end = text.length(); if (!prefixOf(text, off, end)){ @@ -4803,7 +4806,7 @@ public final class DateTimeFormatterBuilder { do { if (isEqual(c.c0, text.charAt(off))) { pos.setIndex(off); - String found = c.match(text, pos); + PrefixTree found = c.match(text, pos); if (found != null) { return found; } @@ -4813,15 +4816,15 @@ public final class DateTimeFormatterBuilder { } while (c != null); } pos.setIndex(off); - return value; + return this; } protected String toKey(String k) { return k; } - protected PrefixTree newNode(String k, String v, PrefixTree child) { - return new PrefixTree(k, v, child); + protected PrefixTree newNode(String k, String v, int t, PrefixTree child) { + return new PrefixTree(k, v, t, child); } protected boolean isEqual(char c1, char c2) { @@ -4861,13 +4864,13 @@ public final class DateTimeFormatterBuilder { */ private static class CI extends PrefixTree { - private CI(String k, String v, PrefixTree child) { - super(k, v, child); + private CI(String k, String v, int t, PrefixTree child) { + super(k, v, t, child); } @Override - protected CI newNode(String k, String v, PrefixTree child) { - return new CI(k, v, child); + protected CI newNode(String k, String v, int t, PrefixTree child) { + return new CI(k, v, t, child); } @Override @@ -4890,86 +4893,6 @@ public final class DateTimeFormatterBuilder { return true; } } - - /** - * Lenient prefix tree. Case insensitive and ignores characters - * like space, underscore and slash. - */ - private static class LENIENT extends CI { - - private LENIENT(String k, String v, PrefixTree child) { - super(k, v, child); - } - - @Override - protected CI newNode(String k, String v, PrefixTree child) { - return new LENIENT(k, v, child); - } - - private boolean isLenientChar(char c) { - return c == ' ' || c == '_' || c == '/'; - } - - protected String toKey(String k) { - for (int i = 0; i < k.length(); i++) { - if (isLenientChar(k.charAt(i))) { - StringBuilder sb = new StringBuilder(k.length()); - sb.append(k, 0, i); - i++; - while (i < k.length()) { - if (!isLenientChar(k.charAt(i))) { - sb.append(k.charAt(i)); - } - i++; - } - return sb.toString(); - } - } - return k; - } - - @Override - public String match(CharSequence text, ParsePosition pos) { - int off = pos.getIndex(); - int end = text.length(); - int len = key.length(); - int koff = 0; - while (koff < len && off < end) { - if (isLenientChar(text.charAt(off))) { - off++; - continue; - } - if (!isEqual(key.charAt(koff++), text.charAt(off++))) { - return null; - } - } - if (koff != len) { - return null; - } - if (child != null && off != end) { - int off0 = off; - while (off0 < end && isLenientChar(text.charAt(off0))) { - off0++; - } - if (off0 < end) { - PrefixTree c = child; - do { - if (isEqual(c.c0, text.charAt(off0))) { - pos.setIndex(off0); - String found = c.match(text, pos); - if (found != null) { - return found; - } - break; - } - c = c.sibling; - } while (c != null); - } - } - pos.setIndex(off); - return value; - } - } } //----------------------------------------------------------------------- diff --git a/src/java.base/share/classes/java/time/format/DateTimeParseContext.java b/src/java.base/share/classes/java/time/format/DateTimeParseContext.java index 32eefcecc3009263ba3ba6b068b60b23bb7750ca..0a4c7e825a3b60c4e05475281b696d2da923c11f 100644 --- a/src/java.base/share/classes/java/time/format/DateTimeParseContext.java +++ b/src/java.base/share/classes/java/time/format/DateTimeParseContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -417,6 +417,24 @@ final class DateTimeParseContext { currentParsed().zone = zone; } + /** + * Stores the parsed zone name type. + *

+ * This stores the zone name type that has been parsed. + * The parsed type should either be; + *

    + *
  • {@link DateTimeFormatterBuilder.ZoneTextPrinterParser#UNDEFINED}
  • + *
  • {@link DateTimeFormatterBuilder.ZoneTextPrinterParser#STD}
  • + *
  • {@link DateTimeFormatterBuilder.ZoneTextPrinterParser#DST}
  • + *
  • {@link DateTimeFormatterBuilder.ZoneTextPrinterParser#GENERIC}
  • + *
+ * + * @param type the parsed zone name type + */ + void setParsedZoneNameType(int type) { + currentParsed().zoneNameType = type; + } + /** * Stores the parsed leap second. */ diff --git a/src/java.base/share/classes/java/time/format/Parsed.java b/src/java.base/share/classes/java/time/format/Parsed.java index 567c2700a155855ae7e19a5d9087a849d6f4c68e..1ec956dfa2cd39ceb60023e5087ba415af876169 100644 --- a/src/java.base/share/classes/java/time/format/Parsed.java +++ b/src/java.base/share/classes/java/time/format/Parsed.java @@ -87,6 +87,7 @@ import java.time.LocalTime; import java.time.Period; import java.time.ZoneId; import java.time.ZoneOffset; +import java.time.ZonedDateTime; import java.time.chrono.ChronoLocalDate; import java.time.chrono.ChronoLocalDateTime; import java.time.chrono.ChronoZonedDateTime; @@ -132,6 +133,10 @@ final class Parsed implements TemporalAccessor { * The parsed zone. */ ZoneId zone; + /** + * The parsed zone name type. + */ + int zoneNameType = DateTimeFormatterBuilder.ZoneTextPrinterParser.UNDEFINED; /** * The parsed chronology. */ @@ -175,6 +180,7 @@ final class Parsed implements TemporalAccessor { Parsed cloned = new Parsed(); cloned.fieldValues.putAll(this.fieldValues); cloned.zone = this.zone; + cloned.zoneNameType = this.zoneNameType; cloned.chrono = this.chrono; cloned.leapSecond = this.leapSecond; cloned.dayPeriod = this.dayPeriod; @@ -652,8 +658,12 @@ final class Parsed implements TemporalAccessor { fieldValues.put(INSTANT_SECONDS, instant); } else { if (zone != null) { - long instant = date.atTime(time).atZone(zone).toEpochSecond(); - fieldValues.put(INSTANT_SECONDS, instant); + var czdt = date.atTime(time).atZone(zone); + if (zoneNameType == DateTimeFormatterBuilder.ZoneTextPrinterParser.STD || + zoneNameType == DateTimeFormatterBuilder.ZoneTextPrinterParser.GENERIC) { + czdt = czdt.withLaterOffsetAtOverlap(); + } + fieldValues.put(INSTANT_SECONDS, czdt.toEpochSecond()); } } } @@ -718,6 +728,7 @@ final class Parsed implements TemporalAccessor { buf.append(fieldValues).append(',').append(chrono); if (zone != null) { buf.append(',').append(zone); + buf.append(',').append(zoneNameType); } if (date != null || time != null) { buf.append(" resolved to "); diff --git a/src/java.base/share/classes/java/util/Formatter.java b/src/java.base/share/classes/java/util/Formatter.java index d3f2ecd977babfabe6a4d7c44c938ba9deef427f..65f67656087b7aa86652ed7b93ba5f19d2e82eae 100644 --- a/src/java.base/share/classes/java/util/Formatter.java +++ b/src/java.base/share/classes/java/util/Formatter.java @@ -2034,7 +2034,7 @@ public final class Formatter implements Closeable, Flushable { } } - private static final Appendable nonNullAppendable(Appendable a) { + private static Appendable nonNullAppendable(Appendable a) { if (a == null) return new StringBuilder(); @@ -2755,24 +2755,24 @@ public final class Formatter implements Closeable, Flushable { try { switch (index) { case -2 -> // fixed string, "%n", or "%%" - fs.print(null, l); + fs.print(this, null, l); case -1 -> { // relative index if (last < 0 || (args != null && last > args.length - 1)) throw new MissingFormatArgumentException(fs.toString()); - fs.print((args == null ? null : args[last]), l); + fs.print(this, (args == null ? null : args[last]), l); } case 0 -> { // ordinary index lasto++; last = lasto; if (args != null && lasto > args.length - 1) throw new MissingFormatArgumentException(fs.toString()); - fs.print((args == null ? null : args[lasto]), l); + fs.print(this, (args == null ? null : args[lasto]), l); } default -> { // explicit index last = index - 1; if (args != null && last > args.length - 1) throw new MissingFormatArgumentException(fs.toString()); - fs.print((args == null ? null : args[last]), l); + fs.print(this, (args == null ? null : args[last]), l); } } } catch (IOException x) { @@ -2836,11 +2836,11 @@ public final class Formatter implements Closeable, Flushable { private interface FormatString { int index(); - void print(Object arg, Locale l) throws IOException; + void print(Formatter fmt, Object arg, Locale l) throws IOException; String toString(); } - private class FixedString implements FormatString { + private static class FixedString implements FormatString { private final String s; private final int start; private final int end; @@ -2850,8 +2850,8 @@ public final class Formatter implements Closeable, Flushable { this.end = end; } public int index() { return -2; } - public void print(Object arg, Locale l) - throws IOException { a.append(s, start, end); } + public void print(Formatter fmt, Object arg, Locale l) + throws IOException { fmt.a.append(s, start, end); } public String toString() { return s.substring(start, end); } } @@ -2870,10 +2870,10 @@ public final class Formatter implements Closeable, Flushable { DECIMAL_FLOAT }; - private class FormatSpecifier implements FormatString { + private static class FormatSpecifier implements FormatString { private int index = 0; - private Flags f = Flags.NONE; + private int flags = Flags.NONE; private int width = -1; private int precision = -1; private boolean dt = false; @@ -2898,8 +2898,8 @@ public final class Formatter implements Closeable, Flushable { } private void flags(String s, int start, int end) { - f = Flags.parse(s, start, end); - if (f.contains(Flags.PREVIOUS)) + flags = Flags.parse(s, start, end); + if (Flags.contains(flags, Flags.PREVIOUS)) index = -1; } @@ -2935,7 +2935,7 @@ public final class Formatter implements Closeable, Flushable { throw new UnknownFormatConversionException(String.valueOf(c)); } if (Character.isUpperCase(c)) { - f.add(Flags.UPPERCASE); + flags = Flags.add(flags, Flags.UPPERCASE); c = Character.toLowerCase(c); } if (Conversion.isText(c)) { @@ -2947,7 +2947,7 @@ public final class Formatter implements Closeable, Flushable { FormatSpecifier(char conv) { c = conv; if (Character.isUpperCase(conv)) { - f = Flags.UPPERCASE; + flags = Flags.UPPERCASE; c = Character.toLowerCase(conv); } if (Conversion.isText(conv)) { @@ -2965,7 +2965,7 @@ public final class Formatter implements Closeable, Flushable { if (tTStart >= 0) { dt = true; if (s.charAt(tTStart) == 'T') { - f.add(Flags.UPPERCASE); + flags = Flags.add(flags, Flags.UPPERCASE); } } conversion(s.charAt(m.start(6))); @@ -2986,79 +2986,79 @@ public final class Formatter implements Closeable, Flushable { throw new UnknownFormatConversionException(String.valueOf(c)); } - public void print(Object arg, Locale l) throws IOException { + public void print(Formatter fmt, Object arg, Locale l) throws IOException { if (dt) { - printDateTime(arg, l); + printDateTime(fmt, arg, l); return; } switch(c) { case Conversion.DECIMAL_INTEGER: case Conversion.OCTAL_INTEGER: case Conversion.HEXADECIMAL_INTEGER: - printInteger(arg, l); + printInteger(fmt, arg, l); break; case Conversion.SCIENTIFIC: case Conversion.GENERAL: case Conversion.DECIMAL_FLOAT: case Conversion.HEXADECIMAL_FLOAT: - printFloat(arg, l); + printFloat(fmt, arg, l); break; case Conversion.CHARACTER: - printCharacter(arg, l); + printCharacter(fmt, arg, l); break; case Conversion.BOOLEAN: - printBoolean(arg, l); + printBoolean(fmt, arg, l); break; case Conversion.STRING: - printString(arg, l); + printString(fmt, arg, l); break; case Conversion.HASHCODE: - printHashCode(arg, l); + printHashCode(fmt, arg, l); break; case Conversion.LINE_SEPARATOR: - a.append(System.lineSeparator()); + fmt.a.append(System.lineSeparator()); break; case Conversion.PERCENT_SIGN: - print("%", l); + print(fmt, "%", l); break; default: assert false; } } - private void printInteger(Object arg, Locale l) throws IOException { + private void printInteger(Formatter fmt, Object arg, Locale l) throws IOException { if (arg == null) - print("null", l); + print(fmt, "null", l); else if (arg instanceof Byte) - print(((Byte)arg).byteValue(), l); + print(fmt, ((Byte)arg).byteValue(), l); else if (arg instanceof Short) - print(((Short)arg).shortValue(), l); + print(fmt, ((Short)arg).shortValue(), l); else if (arg instanceof Integer) - print(((Integer)arg).intValue(), l); + print(fmt, ((Integer)arg).intValue(), l); else if (arg instanceof Long) - print(((Long)arg).longValue(), l); + print(fmt, ((Long)arg).longValue(), l); else if (arg instanceof BigInteger) - print(((BigInteger)arg), l); + print(fmt, ((BigInteger)arg), l); else failConversion(c, arg); } - private void printFloat(Object arg, Locale l) throws IOException { + private void printFloat(Formatter fmt, Object arg, Locale l) throws IOException { if (arg == null) - print("null", l); + print(fmt, "null", l); else if (arg instanceof Float) - print(((Float)arg).floatValue(), l); + print(fmt, ((Float)arg).floatValue(), l); else if (arg instanceof Double) - print(((Double)arg).doubleValue(), l); + print(fmt, ((Double)arg).doubleValue(), l); else if (arg instanceof BigDecimal) - print(((BigDecimal)arg), l); + print(fmt, ((BigDecimal)arg), l); else failConversion(c, arg); } - private void printDateTime(Object arg, Locale l) throws IOException { + private void printDateTime(Formatter fmt, Object arg, Locale l) throws IOException { if (arg == null) { - print("null", l); + print(fmt, "null", l); return; } Calendar cal = null; @@ -3079,19 +3079,19 @@ public final class Formatter implements Closeable, Flushable { cal = (Calendar) ((Calendar) arg).clone(); cal.setLenient(true); } else if (arg instanceof TemporalAccessor) { - print((TemporalAccessor) arg, c, l); + print(fmt, (TemporalAccessor) arg, c, l); return; } else { failConversion(c, arg); } // Use the provided locale so that invocations of // localizedMagnitude() use optimizations for null. - print(cal, c, l); + print(fmt, cal, c, l); } - private void printCharacter(Object arg, Locale l) throws IOException { + private void printCharacter(Formatter fmt, Object arg, Locale l) throws IOException { if (arg == null) { - print("null", l); + print(fmt, "null", l); return; } String s = null; @@ -3118,26 +3118,25 @@ public final class Formatter implements Closeable, Flushable { } else { failConversion(c, arg); } - print(s, l); + print(fmt, s, l); } - private void printString(Object arg, Locale l) throws IOException { + private void printString(Formatter fmt, Object arg, Locale l) throws IOException { if (arg instanceof Formattable) { - Formatter fmt = Formatter.this; if (fmt.locale() != l) fmt = new Formatter(fmt.out(), l); - ((Formattable)arg).formatTo(fmt, f.valueOf(), width, precision); + ((Formattable)arg).formatTo(fmt, flags, width, precision); } else { - if (f.contains(Flags.ALTERNATE)) + if (Flags.contains(flags, Flags.ALTERNATE)) failMismatch(Flags.ALTERNATE, 's'); if (arg == null) - print("null", l); + print(fmt, "null", l); else - print(arg.toString(), l); + print(fmt, arg.toString(), l); } } - private void printBoolean(Object arg, Locale l) throws IOException { + private void printBoolean(Formatter fmt, Object arg, Locale l) throws IOException { String s; if (arg != null) s = ((arg instanceof Boolean) @@ -3145,22 +3144,22 @@ public final class Formatter implements Closeable, Flushable { : Boolean.toString(true)); else s = Boolean.toString(false); - print(s, l); + print(fmt, s, l); } - private void printHashCode(Object arg, Locale l) throws IOException { + private void printHashCode(Formatter fmt, Object arg, Locale l) throws IOException { String s = (arg == null ? "null" : Integer.toHexString(arg.hashCode())); - print(s, l); + print(fmt, s, l); } - private void print(String s, Locale l) throws IOException { + private void print(Formatter fmt, String s, Locale l) throws IOException { if (precision != -1 && precision < s.length()) s = s.substring(0, precision); - if (f.contains(Flags.UPPERCASE)) + if (Flags.contains(flags, Flags.UPPERCASE)) s = toUpperCaseWithLocale(s, l); - appendJustified(a, s); + appendJustified(fmt.a, s); } private String toUpperCaseWithLocale(String s, Locale l) { @@ -3173,7 +3172,7 @@ public final class Formatter implements Closeable, Flushable { a.append(cs); return; } - boolean padRight = f.contains(Flags.LEFT_JUSTIFY); + boolean padRight = Flags.contains(flags, Flags.LEFT_JUSTIFY); int sp = width - cs.length(); if (padRight) { a.append(cs); @@ -3189,8 +3188,7 @@ public final class Formatter implements Closeable, Flushable { public String toString() { StringBuilder sb = new StringBuilder("%"); // Flags.UPPERCASE is set internally for legal conversions. - Flags dupf = f.dup().remove(Flags.UPPERCASE); - sb.append(dupf.toString()); + sb.append(Flags.toString(Flags.remove(flags, Flags.UPPERCASE))); if (index > 0) sb.append(index).append('$'); if (width != -1) @@ -3198,21 +3196,21 @@ public final class Formatter implements Closeable, Flushable { if (precision != -1) sb.append('.').append(precision); if (dt) - sb.append(f.contains(Flags.UPPERCASE) ? 'T' : 't'); - sb.append(f.contains(Flags.UPPERCASE) + sb.append(Flags.contains(flags, Flags.UPPERCASE) ? 'T' : 't'); + sb.append(Flags.contains(flags, Flags.UPPERCASE) ? Character.toUpperCase(c) : c); return sb.toString(); } private void checkGeneral() { if ((c == Conversion.BOOLEAN || c == Conversion.HASHCODE) - && f.contains(Flags.ALTERNATE)) + && Flags.contains(flags, Flags.ALTERNATE)) failMismatch(Flags.ALTERNATE, c); // '-' requires a width - if (width == -1 && f.contains(Flags.LEFT_JUSTIFY)) + if (width == -1 && Flags.contains(flags, Flags.LEFT_JUSTIFY)) throw new MissingFormatWidthException(toString()); - checkBadFlags(Flags.PLUS, Flags.LEADING_SPACE, Flags.ZERO_PAD, - Flags.GROUP, Flags.PARENTHESES); + checkBadFlags(Flags.PLUS | Flags.LEADING_SPACE | Flags.ZERO_PAD | + Flags.GROUP | Flags.PARENTHESES); } private void checkDateTime() { @@ -3220,20 +3218,20 @@ public final class Formatter implements Closeable, Flushable { throw new IllegalFormatPrecisionException(precision); if (!DateTime.isValid(c)) throw new UnknownFormatConversionException("t" + c); - checkBadFlags(Flags.ALTERNATE, Flags.PLUS, Flags.LEADING_SPACE, - Flags.ZERO_PAD, Flags.GROUP, Flags.PARENTHESES); + checkBadFlags(Flags.ALTERNATE | Flags.PLUS | Flags.LEADING_SPACE | + Flags.ZERO_PAD | Flags.GROUP | Flags.PARENTHESES); // '-' requires a width - if (width == -1 && f.contains(Flags.LEFT_JUSTIFY)) + if (width == -1 && Flags.contains(flags, Flags.LEFT_JUSTIFY)) throw new MissingFormatWidthException(toString()); } private void checkCharacter() { if (precision != -1) throw new IllegalFormatPrecisionException(precision); - checkBadFlags(Flags.ALTERNATE, Flags.PLUS, Flags.LEADING_SPACE, - Flags.ZERO_PAD, Flags.GROUP, Flags.PARENTHESES); + checkBadFlags(Flags.ALTERNATE | Flags.PLUS | Flags.LEADING_SPACE | + Flags.ZERO_PAD | Flags.GROUP | Flags.PARENTHESES); // '-' requires a width - if (width == -1 && f.contains(Flags.LEFT_JUSTIFY)) + if (width == -1 && Flags.contains(flags, Flags.LEFT_JUSTIFY)) throw new MissingFormatWidthException(toString()); } @@ -3250,17 +3248,17 @@ public final class Formatter implements Closeable, Flushable { checkBadFlags(Flags.GROUP); } - private void checkBadFlags(Flags ... badFlags) { - for (Flags badFlag : badFlags) - if (f.contains(badFlag)) - failMismatch(badFlag, c); + private void checkBadFlags(int badFlags) { + if ((flags & badFlags) != 0) { + failMismatch(flags & badFlags, c); + } } private void checkFloat() { checkNumeric(); if (c == Conversion.DECIMAL_FLOAT) { } else if (c == Conversion.HEXADECIMAL_FLOAT) { - checkBadFlags(Flags.PARENTHESES, Flags.GROUP); + checkBadFlags(Flags.PARENTHESES | Flags.GROUP); } else if (c == Conversion.SCIENTIFIC) { checkBadFlags(Flags.GROUP); } else if (c == Conversion.GENERAL) { @@ -3277,13 +3275,13 @@ public final class Formatter implements Closeable, Flushable { // '-' and '0' require a width if (width == -1 - && (f.contains(Flags.LEFT_JUSTIFY) || f.contains(Flags.ZERO_PAD))) + && (Flags.containsAny(flags, Flags.LEFT_JUSTIFY | Flags.ZERO_PAD))) throw new MissingFormatWidthException(toString()); // bad combination - if ((f.contains(Flags.PLUS) && f.contains(Flags.LEADING_SPACE)) - || (f.contains(Flags.LEFT_JUSTIFY) && f.contains(Flags.ZERO_PAD))) - throw new IllegalFormatFlagsException(f.toString()); + if ((Flags.contains(flags, Flags.PLUS | Flags.LEADING_SPACE)) + || (Flags.contains(flags, Flags.LEFT_JUSTIFY | Flags.ZERO_PAD))) + throw new IllegalFormatFlagsException(Flags.toString(flags)); } private void checkText() { @@ -3291,35 +3289,35 @@ public final class Formatter implements Closeable, Flushable { throw new IllegalFormatPrecisionException(precision); switch (c) { case Conversion.PERCENT_SIGN: - if (f.valueOf() != Flags.LEFT_JUSTIFY.valueOf() - && f.valueOf() != Flags.NONE.valueOf()) - throw new IllegalFormatFlagsException(f.toString()); + if (flags != Flags.LEFT_JUSTIFY + && flags != Flags.NONE) + throw new IllegalFormatFlagsException(Flags.toString(flags)); // '-' requires a width - if (width == -1 && f.contains(Flags.LEFT_JUSTIFY)) + if (width == -1 && Flags.contains(flags, Flags.LEFT_JUSTIFY)) throw new MissingFormatWidthException(toString()); break; case Conversion.LINE_SEPARATOR: if (width != -1) throw new IllegalFormatWidthException(width); - if (f.valueOf() != Flags.NONE.valueOf()) - throw new IllegalFormatFlagsException(f.toString()); + if (flags != Flags.NONE) + throw new IllegalFormatFlagsException(Flags.toString(flags)); break; default: assert false; } } - private void print(byte value, Locale l) throws IOException { + private void print(Formatter fmt, byte value, Locale l) throws IOException { long v = value; if (value < 0 && (c == Conversion.OCTAL_INTEGER || c == Conversion.HEXADECIMAL_INTEGER)) { v += (1L << 8); } - print(v, l); + print(fmt, v, l); } - private void print(short value, Locale l) throws IOException { + private void print(Formatter fmt, short value, Locale l) throws IOException { long v = value; if (value < 0 && (c == Conversion.OCTAL_INTEGER @@ -3327,10 +3325,10 @@ public final class Formatter implements Closeable, Flushable { v += (1L << 16); assert v >= 0 : v; } - print(v, l); + print(fmt, v, l); } - private void print(int value, Locale l) throws IOException { + private void print(Formatter fmt, int value, Locale l) throws IOException { long v = value; if (value < 0 && (c == Conversion.OCTAL_INTEGER @@ -3338,10 +3336,10 @@ public final class Formatter implements Closeable, Flushable { v += (1L << 32); assert v >= 0 : v; } - print(v, l); + print(fmt, v, l); } - private void print(long value, Locale l) throws IOException { + private void print(Formatter fmt, long value, Locale l) throws IOException { StringBuilder sb = new StringBuilder(); @@ -3353,58 +3351,56 @@ public final class Formatter implements Closeable, Flushable { leadingSign(sb, neg); // the value - localizedMagnitude(sb, valueStr, neg ? 1 : 0, f, adjustWidth(width, f, neg), l); + localizedMagnitude(fmt, sb, valueStr, neg ? 1 : 0, flags, adjustWidth(width, flags, neg), l); // trailing sign indicator trailingSign(sb, neg); } else if (c == Conversion.OCTAL_INTEGER) { - checkBadFlags(Flags.PARENTHESES, Flags.LEADING_SPACE, - Flags.PLUS); + checkBadFlags(Flags.PARENTHESES | Flags.LEADING_SPACE | Flags.PLUS); String s = Long.toOctalString(value); - int len = (f.contains(Flags.ALTERNATE) + int len = (Flags.contains(flags, Flags.ALTERNATE) ? s.length() + 1 : s.length()); // apply ALTERNATE (radix indicator for octal) before ZERO_PAD - if (f.contains(Flags.ALTERNATE)) + if (Flags.contains(flags, Flags.ALTERNATE)) sb.append('0'); - if (f.contains(Flags.ZERO_PAD)) { + if (Flags.contains(flags, Flags.ZERO_PAD)) { trailingZeros(sb, width - len); } sb.append(s); } else if (c == Conversion.HEXADECIMAL_INTEGER) { - checkBadFlags(Flags.PARENTHESES, Flags.LEADING_SPACE, - Flags.PLUS); + checkBadFlags(Flags.PARENTHESES | Flags.LEADING_SPACE | Flags.PLUS); String s = Long.toHexString(value); - int len = (f.contains(Flags.ALTERNATE) + int len = (Flags.contains(flags, Flags.ALTERNATE) ? s.length() + 2 : s.length()); // apply ALTERNATE (radix indicator for hex) before ZERO_PAD - if (f.contains(Flags.ALTERNATE)) - sb.append(f.contains(Flags.UPPERCASE) ? "0X" : "0x"); - if (f.contains(Flags.ZERO_PAD)) { + if (Flags.contains(flags, Flags.ALTERNATE)) + sb.append(Flags.contains(flags, Flags.UPPERCASE) ? "0X" : "0x"); + if (Flags.contains(flags, Flags.ZERO_PAD)) { trailingZeros(sb, width - len); } - if (f.contains(Flags.UPPERCASE)) + if (Flags.contains(flags, Flags.UPPERCASE)) s = toUpperCaseWithLocale(s, l); sb.append(s); } // justify based on width - appendJustified(a, sb); + appendJustified(fmt.a, sb); } // neg := val < 0 private StringBuilder leadingSign(StringBuilder sb, boolean neg) { if (!neg) { - if (f.contains(Flags.PLUS)) { + if (Flags.contains(flags, Flags.PLUS)) { sb.append('+'); - } else if (f.contains(Flags.LEADING_SPACE)) { + } else if (Flags.contains(flags, Flags.LEADING_SPACE)) { sb.append(' '); } } else { - if (f.contains(Flags.PARENTHESES)) + if (Flags.contains(flags, Flags.PARENTHESES)) sb.append('('); else sb.append('-'); @@ -3414,12 +3410,12 @@ public final class Formatter implements Closeable, Flushable { // neg := val < 0 private StringBuilder trailingSign(StringBuilder sb, boolean neg) { - if (neg && f.contains(Flags.PARENTHESES)) + if (neg && Flags.contains(flags, Flags.PARENTHESES)) sb.append(')'); return sb; } - private void print(BigInteger value, Locale l) throws IOException { + private void print(Formatter fmt, BigInteger value, Locale l) throws IOException { StringBuilder sb = new StringBuilder(); boolean neg = value.signum() == -1; BigInteger v = value.abs(); @@ -3429,20 +3425,20 @@ public final class Formatter implements Closeable, Flushable { // the value if (c == Conversion.DECIMAL_INTEGER) { - localizedMagnitude(sb, v.toString(), 0, f, adjustWidth(width, f, neg), l); + localizedMagnitude(fmt, sb, v.toString(), 0, flags, adjustWidth(width, flags, neg), l); } else if (c == Conversion.OCTAL_INTEGER) { String s = v.toString(8); int len = s.length() + sb.length(); - if (neg && f.contains(Flags.PARENTHESES)) + if (neg && Flags.contains(flags, Flags.PARENTHESES)) len++; // apply ALTERNATE (radix indicator for octal) before ZERO_PAD - if (f.contains(Flags.ALTERNATE)) { + if (Flags.contains(flags, Flags.ALTERNATE)) { len++; sb.append('0'); } - if (f.contains(Flags.ZERO_PAD)) { + if (Flags.contains(flags, Flags.ZERO_PAD)) { trailingZeros(sb, width - len); } sb.append(s); @@ -3450,18 +3446,18 @@ public final class Formatter implements Closeable, Flushable { String s = v.toString(16); int len = s.length() + sb.length(); - if (neg && f.contains(Flags.PARENTHESES)) + if (neg && Flags.contains(flags, Flags.PARENTHESES)) len++; // apply ALTERNATE (radix indicator for hex) before ZERO_PAD - if (f.contains(Flags.ALTERNATE)) { + if (Flags.contains(flags, Flags.ALTERNATE)) { len += 2; - sb.append(f.contains(Flags.UPPERCASE) ? "0X" : "0x"); + sb.append(Flags.contains(flags, Flags.UPPERCASE) ? "0X" : "0x"); } - if (f.contains(Flags.ZERO_PAD)) { + if (Flags.contains(flags, Flags.ZERO_PAD)) { trailingZeros(sb, width - len); } - if (f.contains(Flags.UPPERCASE)) + if (Flags.contains(flags, Flags.UPPERCASE)) s = toUpperCaseWithLocale(s, l); sb.append(s); } @@ -3470,14 +3466,14 @@ public final class Formatter implements Closeable, Flushable { trailingSign(sb, (value.signum() == -1)); // justify based on width - appendJustified(a, sb); + appendJustified(fmt.a, sb); } - private void print(float value, Locale l) throws IOException { - print((double) value, l); + private void print(Formatter fmt, float value, Locale l) throws IOException { + print(fmt, (double) value, l); } - private void print(double value, Locale l) throws IOException { + private void print(Formatter fmt, double value, Locale l) throws IOException { StringBuilder sb = new StringBuilder(); boolean neg = Double.compare(value, 0.0) == -1; @@ -3489,24 +3485,24 @@ public final class Formatter implements Closeable, Flushable { // the value if (!Double.isInfinite(v)) - print(sb, v, l, f, c, precision, neg); + print(fmt, sb, v, l, flags, c, precision, neg); else - sb.append(f.contains(Flags.UPPERCASE) + sb.append(Flags.contains(flags, Flags.UPPERCASE) ? "INFINITY" : "Infinity"); // trailing sign indicator trailingSign(sb, neg); } else { - sb.append(f.contains(Flags.UPPERCASE) ? "NAN" : "NaN"); + sb.append(Flags.contains(flags, Flags.UPPERCASE) ? "NAN" : "NaN"); } // justify based on width - appendJustified(a, sb); + appendJustified(fmt.a, sb); } // !Double.isInfinite(value) && !Double.isNaN(value) - private void print(StringBuilder sb, double value, Locale l, - Flags f, char c, int precision, boolean neg) + private void print(Formatter fmt, StringBuilder sb, double value, Locale l, + int flags, char c, int precision, boolean neg) throws IOException { if (c == Conversion.SCIENTIFIC) { @@ -3523,7 +3519,7 @@ public final class Formatter implements Closeable, Flushable { // If the precision is zero and the '#' flag is set, add the // requested decimal point. - if (f.contains(Flags.ALTERNATE) && (prec == 0)) { + if (Flags.contains(flags, Flags.ALTERNATE) && (prec == 0)) { mant.append('.'); } @@ -3532,17 +3528,17 @@ public final class Formatter implements Closeable, Flushable { int newW = width; if (width != -1) { - newW = adjustWidth(width - exp.length - 1, f, neg); + newW = adjustWidth(width - exp.length - 1, flags, neg); } - localizedMagnitude(sb, mant, 0, f, newW, l); + localizedMagnitude(fmt, sb, mant, 0, flags, newW, l); - sb.append(f.contains(Flags.UPPERCASE) ? 'E' : 'e'); + sb.append(Flags.contains(flags, Flags.UPPERCASE) ? 'E' : 'e'); char sign = exp[0]; assert(sign == '+' || sign == '-'); sb.append(sign); - localizedMagnitudeExp(sb, exp, 1, l); + localizedMagnitudeExp(fmt, sb, exp, 1, l); } else if (c == Conversion.DECIMAL_FLOAT) { // Create a new FormattedFloatingDecimal with the desired // precision. @@ -3557,13 +3553,13 @@ public final class Formatter implements Closeable, Flushable { // If the precision is zero and the '#' flag is set, add the // requested decimal point. - if (f.contains(Flags.ALTERNATE) && (prec == 0)) + if (Flags.contains(flags, Flags.ALTERNATE) && (prec == 0)) mant.append('.'); int newW = width; if (width != -1) - newW = adjustWidth(width, f, neg); - localizedMagnitude(sb, mant, 0, f, newW, l); + newW = adjustWidth(width, flags, neg); + localizedMagnitude(fmt, sb, mant, 0, flags, newW, l); } else if (c == Conversion.GENERAL) { int prec = precision; if (precision == -1) @@ -3596,27 +3592,27 @@ public final class Formatter implements Closeable, Flushable { addZeros(mant, prec); // If the precision is zero and the '#' flag is set, add the // requested decimal point. - if (f.contains(Flags.ALTERNATE) && (prec == 0)) { + if (Flags.contains(flags, Flags.ALTERNATE) && (prec == 0)) { mant.append('.'); } int newW = width; if (width != -1) { if (exp != null) - newW = adjustWidth(width - exp.length - 1, f, neg); + newW = adjustWidth(width - exp.length - 1, flags, neg); else - newW = adjustWidth(width, f, neg); + newW = adjustWidth(width, flags, neg); } - localizedMagnitude(sb, mant, 0, f, newW, l); + localizedMagnitude(fmt, sb, mant, 0, flags, newW, l); if (exp != null) { - sb.append(f.contains(Flags.UPPERCASE) ? 'E' : 'e'); + sb.append(Flags.contains(flags, Flags.UPPERCASE) ? 'E' : 'e'); char sign = exp[0]; assert(sign == '+' || sign == '-'); sb.append(sign); - localizedMagnitudeExp(sb, exp, 1, l); + localizedMagnitudeExp(fmt, sb, exp, 1, l); } } else if (c == Conversion.HEXADECIMAL_FLOAT) { int prec = precision; @@ -3629,13 +3625,13 @@ public final class Formatter implements Closeable, Flushable { String s = hexDouble(value, prec); StringBuilder va = new StringBuilder(); - boolean upper = f.contains(Flags.UPPERCASE); + boolean upper = Flags.contains(flags, Flags.UPPERCASE); sb.append(upper ? "0X" : "0x"); - if (f.contains(Flags.ZERO_PAD)) { + if (Flags.contains(flags, Flags.ZERO_PAD)) { int leadingCharacters = 2; - if(f.contains(Flags.LEADING_SPACE) || - f.contains(Flags.PLUS) || neg) { + if(Flags.contains(flags, Flags.LEADING_SPACE) || + Flags.contains(flags, Flags.PLUS) || neg) { leadingCharacters = 3; } trailingZeros(sb, width - s.length() - leadingCharacters); @@ -3774,7 +3770,7 @@ public final class Formatter implements Closeable, Flushable { } } - private void print(BigDecimal value, Locale l) throws IOException { + private void print(Formatter fmt, BigDecimal value, Locale l) throws IOException { if (c == Conversion.HEXADECIMAL_FLOAT) failConversion(c, value); StringBuilder sb = new StringBuilder(); @@ -3784,18 +3780,18 @@ public final class Formatter implements Closeable, Flushable { leadingSign(sb, neg); // the value - print(sb, v, l, f, c, precision, neg); + print(fmt, sb, v, l, flags, c, precision, neg); // trailing sign indicator trailingSign(sb, neg); // justify based on width - appendJustified(a, sb); + appendJustified(fmt.a, sb); } // value > 0 - private void print(StringBuilder sb, BigDecimal value, Locale l, - Flags f, char c, int precision, boolean neg) + private void print(Formatter fmt, StringBuilder sb, BigDecimal value, Locale l, + int flags, char c, int precision, boolean neg) throws IOException { if (c == Conversion.SCIENTIFIC) { @@ -3829,7 +3825,7 @@ public final class Formatter implements Closeable, Flushable { // precision is one. Append a decimal point if '#' is set or if // we require zero padding to get to the requested precision. if ((origPrec == 1 || !bdl.hasDot()) - && (nzeros > 0 || (f.contains(Flags.ALTERNATE)))) { + && (nzeros > 0 || (Flags.contains(flags, Flags.ALTERNATE)))) { mant.append('.'); } @@ -3840,18 +3836,18 @@ public final class Formatter implements Closeable, Flushable { StringBuilder exp = bdl.exponent(); int newW = width; if (width != -1) { - newW = adjustWidth(width - exp.length() - 1, f, neg); + newW = adjustWidth(width - exp.length() - 1, flags, neg); } - localizedMagnitude(sb, mant, 0, f, newW, l); + localizedMagnitude(fmt, sb, mant, 0, flags, newW, l); - sb.append(f.contains(Flags.UPPERCASE) ? 'E' : 'e'); + sb.append(Flags.contains(flags, Flags.UPPERCASE) ? 'E' : 'e'); - Flags flags = f.dup().remove(Flags.GROUP); + int adaptedFlags = Flags.remove(flags, Flags.GROUP); char sign = exp.charAt(0); assert(sign == '+' || sign == '-'); sb.append(sign); - sb.append(localizedMagnitude(null, exp, 1, flags, -1, l)); + sb.append(localizedMagnitude(fmt, null, exp, 1, adaptedFlags, -1, l)); } else if (c == Conversion.DECIMAL_FLOAT) { // Create a new BigDecimal with the desired precision. int prec = (precision == -1 ? 6 : precision); @@ -3883,7 +3879,7 @@ public final class Formatter implements Closeable, Flushable { // representation has no fractional part). Append a decimal // point if '#' is set or we require zero padding to get to the // requested precision. - if (bdl.scale() == 0 && (f.contains(Flags.ALTERNATE) + if (bdl.scale() == 0 && (Flags.contains(flags, Flags.ALTERNATE) || nzeros > 0)) { mant.append('.'); } @@ -3892,7 +3888,7 @@ public final class Formatter implements Closeable, Flushable { // number of available digits after the decimal separator. trailingZeros(mant, nzeros); - localizedMagnitude(sb, mant, 0, f, adjustWidth(width, f, neg), l); + localizedMagnitude(fmt, sb, mant, 0, flags, adjustWidth(width, flags, neg), l); } else if (c == Conversion.GENERAL) { int prec = precision; if (precision == -1) @@ -3920,10 +3916,10 @@ public final class Formatter implements Closeable, Flushable { // => f precision = g precision - exponent - 1 prec = prec - e - 1; - print(sb, value, l, f, Conversion.DECIMAL_FLOAT, prec, + print(fmt, sb, value, l, flags, Conversion.DECIMAL_FLOAT, prec, neg); } else { - print(sb, value, l, f, Conversion.SCIENTIFIC, prec - 1, neg); + print(fmt, sb, value, l, flags, Conversion.SCIENTIFIC, prec - 1, neg); } } else if (c == Conversion.HEXADECIMAL_FLOAT) { // This conversion isn't supported. The error should be @@ -4045,9 +4041,9 @@ public final class Formatter implements Closeable, Flushable { } } - private int adjustWidth(int width, Flags f, boolean neg) { + private int adjustWidth(int width, int flags, boolean neg) { int newW = width; - if (newW != -1 && neg && f.contains(Flags.PARENTHESES)) + if (newW != -1 && neg && Flags.contains(flags, Flags.PARENTHESES)) newW--; return newW; } @@ -4059,19 +4055,19 @@ public final class Formatter implements Closeable, Flushable { } } - private void print(Calendar t, char c, Locale l) throws IOException { + private void print(Formatter fmt, Calendar t, char c, Locale l) throws IOException { StringBuilder sb = new StringBuilder(); - print(sb, t, c, l); + print(fmt, sb, t, c, l); // justify based on width - if (f.contains(Flags.UPPERCASE)) { - appendJustified(a, toUpperCaseWithLocale(sb.toString(), l)); + if (Flags.contains(flags, Flags.UPPERCASE)) { + appendJustified(fmt.a, toUpperCaseWithLocale(sb.toString(), l)); } else { - appendJustified(a, sb); + appendJustified(fmt.a, sb); } } - private Appendable print(StringBuilder sb, Calendar t, char c, Locale l) + private Appendable print(Formatter fmt, StringBuilder sb, Calendar t, char c, Locale l) throws IOException { if (sb == null) sb = new StringBuilder(); @@ -4083,35 +4079,31 @@ public final class Formatter implements Closeable, Flushable { int i = t.get(Calendar.HOUR_OF_DAY); if (c == DateTime.HOUR_0 || c == DateTime.HOUR) i = (i == 0 || i == 12 ? 12 : i % 12); - Flags flags = (c == DateTime.HOUR_OF_DAY_0 + int flags = (c == DateTime.HOUR_OF_DAY_0 || c == DateTime.HOUR_0 ? Flags.ZERO_PAD : Flags.NONE); - sb.append(localizedMagnitude(null, i, flags, 2, l)); + sb.append(localizedMagnitude(fmt, null, i, flags, 2, l)); break; } case DateTime.MINUTE: { // 'M' (00 - 59) int i = t.get(Calendar.MINUTE); - Flags flags = Flags.ZERO_PAD; - sb.append(localizedMagnitude(null, i, flags, 2, l)); + sb.append(localizedMagnitude(fmt, null, i, Flags.ZERO_PAD, 2, l)); break; } case DateTime.NANOSECOND: { // 'N' (000000000 - 999999999) int i = t.get(Calendar.MILLISECOND) * 1000000; - Flags flags = Flags.ZERO_PAD; - sb.append(localizedMagnitude(null, i, flags, 9, l)); + sb.append(localizedMagnitude(fmt, null, i, Flags.ZERO_PAD, 9, l)); break; } case DateTime.MILLISECOND: { // 'L' (000 - 999) int i = t.get(Calendar.MILLISECOND); - Flags flags = Flags.ZERO_PAD; - sb.append(localizedMagnitude(null, i, flags, 3, l)); + sb.append(localizedMagnitude(fmt, null, i, Flags.ZERO_PAD, 3, l)); break; } case DateTime.MILLISECOND_SINCE_EPOCH: { // 'Q' (0 - 99...?) long i = t.getTimeInMillis(); - Flags flags = Flags.NONE; - sb.append(localizedMagnitude(null, i, flags, width, l)); + sb.append(localizedMagnitude(fmt, null, i, Flags.NONE, width, l)); break; } case DateTime.AM_PM: { // 'p' (am or pm) @@ -4128,14 +4120,12 @@ public final class Formatter implements Closeable, Flushable { } case DateTime.SECONDS_SINCE_EPOCH: { // 's' (0 - 99...?) long i = t.getTimeInMillis() / 1000; - Flags flags = Flags.NONE; - sb.append(localizedMagnitude(null, i, flags, width, l)); + sb.append(localizedMagnitude(fmt, null, i, Flags.NONE, width, l)); break; } case DateTime.SECOND: { // 'S' (00 - 60 - leap second) int i = t.get(Calendar.SECOND); - Flags flags = Flags.ZERO_PAD; - sb.append(localizedMagnitude(null, i, flags, 2, l)); + sb.append(localizedMagnitude(fmt, null, i, Flags.ZERO_PAD, 2, l)); break; } case DateTime.ZONE_NUMERIC: { // 'z' ({-|+}####) - ls minus? @@ -4147,9 +4137,8 @@ public final class Formatter implements Closeable, Flushable { int min = i / 60000; // combine minute and hour into a single integer int offset = (min / 60) * 100 + (min % 60); - Flags flags = Flags.ZERO_PAD; - sb.append(localizedMagnitude(null, offset, flags, 4, l)); + sb.append(localizedMagnitude(fmt, null, offset, Flags.ZERO_PAD, 4, l)); break; } case DateTime.ZONE: { // 'Z' (symbol) @@ -4194,29 +4183,26 @@ public final class Formatter implements Closeable, Flushable { case DateTime.YEAR_2 -> i %= 100; case DateTime.YEAR_4 -> size = 4; } - Flags flags = Flags.ZERO_PAD; - sb.append(localizedMagnitude(null, i, flags, size, l)); + sb.append(localizedMagnitude(fmt, null, i, Flags.ZERO_PAD, size, l)); break; } case DateTime.DAY_OF_MONTH_0: // 'd' (01 - 31) case DateTime.DAY_OF_MONTH: { // 'e' (1 - 31) -- like d int i = t.get(Calendar.DATE); - Flags flags = (c == DateTime.DAY_OF_MONTH_0 + int flags = (c == DateTime.DAY_OF_MONTH_0 ? Flags.ZERO_PAD : Flags.NONE); - sb.append(localizedMagnitude(null, i, flags, 2, l)); + sb.append(localizedMagnitude(fmt, null, i, flags, 2, l)); break; } case DateTime.DAY_OF_YEAR: { // 'j' (001 - 366) int i = t.get(Calendar.DAY_OF_YEAR); - Flags flags = Flags.ZERO_PAD; - sb.append(localizedMagnitude(null, i, flags, 3, l)); + sb.append(localizedMagnitude(fmt, null, i, Flags.ZERO_PAD, 3, l)); break; } case DateTime.MONTH: { // 'm' (01 - 12) int i = t.get(Calendar.MONTH) + 1; - Flags flags = Flags.ZERO_PAD; - sb.append(localizedMagnitude(null, i, flags, 2, l)); + sb.append(localizedMagnitude(fmt, null, i, Flags.ZERO_PAD, 2, l)); break; } @@ -4224,48 +4210,48 @@ public final class Formatter implements Closeable, Flushable { case DateTime.TIME: // 'T' (24 hour hh:mm:ss - %tH:%tM:%tS) case DateTime.TIME_24_HOUR: { // 'R' (hh:mm same as %H:%M) char sep = ':'; - print(sb, t, DateTime.HOUR_OF_DAY_0, l).append(sep); - print(sb, t, DateTime.MINUTE, l); + print(fmt, sb, t, DateTime.HOUR_OF_DAY_0, l).append(sep); + print(fmt, sb, t, DateTime.MINUTE, l); if (c == DateTime.TIME) { sb.append(sep); - print(sb, t, DateTime.SECOND, l); + print(fmt, sb, t, DateTime.SECOND, l); } break; } case DateTime.TIME_12_HOUR: { // 'r' (hh:mm:ss [AP]M) char sep = ':'; - print(sb, t, DateTime.HOUR_0, l).append(sep); - print(sb, t, DateTime.MINUTE, l).append(sep); - print(sb, t, DateTime.SECOND, l).append(' '); + print(fmt, sb, t, DateTime.HOUR_0, l).append(sep); + print(fmt, sb, t, DateTime.MINUTE, l).append(sep); + print(fmt, sb, t, DateTime.SECOND, l).append(' '); // this may be in wrong place for some locales StringBuilder tsb = new StringBuilder(); - print(tsb, t, DateTime.AM_PM, l); + print(fmt, tsb, t, DateTime.AM_PM, l); sb.append(toUpperCaseWithLocale(tsb.toString(), l)); break; } case DateTime.DATE_TIME: { // 'c' (Sat Nov 04 12:02:33 EST 1999) char sep = ' '; - print(sb, t, DateTime.NAME_OF_DAY_ABBREV, l).append(sep); - print(sb, t, DateTime.NAME_OF_MONTH_ABBREV, l).append(sep); - print(sb, t, DateTime.DAY_OF_MONTH_0, l).append(sep); - print(sb, t, DateTime.TIME, l).append(sep); - print(sb, t, DateTime.ZONE, l).append(sep); - print(sb, t, DateTime.YEAR_4, l); + print(fmt, sb, t, DateTime.NAME_OF_DAY_ABBREV, l).append(sep); + print(fmt, sb, t, DateTime.NAME_OF_MONTH_ABBREV, l).append(sep); + print(fmt, sb, t, DateTime.DAY_OF_MONTH_0, l).append(sep); + print(fmt, sb, t, DateTime.TIME, l).append(sep); + print(fmt, sb, t, DateTime.ZONE, l).append(sep); + print(fmt, sb, t, DateTime.YEAR_4, l); break; } case DateTime.DATE: { // 'D' (mm/dd/yy) char sep = '/'; - print(sb, t, DateTime.MONTH, l).append(sep); - print(sb, t, DateTime.DAY_OF_MONTH_0, l).append(sep); - print(sb, t, DateTime.YEAR_2, l); + print(fmt, sb, t, DateTime.MONTH, l).append(sep); + print(fmt, sb, t, DateTime.DAY_OF_MONTH_0, l).append(sep); + print(fmt, sb, t, DateTime.YEAR_2, l); break; } case DateTime.ISO_STANDARD_DATE: { // 'F' (%Y-%m-%d) char sep = '-'; - print(sb, t, DateTime.YEAR_4, l).append(sep); - print(sb, t, DateTime.MONTH, l).append(sep); - print(sb, t, DateTime.DAY_OF_MONTH_0, l); + print(fmt, sb, t, DateTime.YEAR_4, l).append(sep); + print(fmt, sb, t, DateTime.MONTH, l).append(sep); + print(fmt, sb, t, DateTime.DAY_OF_MONTH_0, l); break; } default: @@ -4274,18 +4260,18 @@ public final class Formatter implements Closeable, Flushable { return sb; } - private void print(TemporalAccessor t, char c, Locale l) throws IOException { + private void print(Formatter fmt, TemporalAccessor t, char c, Locale l) throws IOException { StringBuilder sb = new StringBuilder(); - print(sb, t, c, l); + print(fmt, sb, t, c, l); // justify based on width - if (f.contains(Flags.UPPERCASE)) { - appendJustified(a, toUpperCaseWithLocale(sb.toString(), l)); + if (Flags.contains(flags, Flags.UPPERCASE)) { + appendJustified(fmt.a, toUpperCaseWithLocale(sb.toString(), l)); } else { - appendJustified(a, sb); + appendJustified(fmt.a, sb); } } - private Appendable print(StringBuilder sb, TemporalAccessor t, char c, + private Appendable print(Formatter fmt, StringBuilder sb, TemporalAccessor t, char c, Locale l) throws IOException { if (sb == null) sb = new StringBuilder(); @@ -4293,28 +4279,27 @@ public final class Formatter implements Closeable, Flushable { switch (c) { case DateTime.HOUR_OF_DAY_0: { // 'H' (00 - 23) int i = t.get(ChronoField.HOUR_OF_DAY); - sb.append(localizedMagnitude(null, i, Flags.ZERO_PAD, 2, l)); + sb.append(localizedMagnitude(fmt, null, i, Flags.ZERO_PAD, 2, l)); break; } case DateTime.HOUR_OF_DAY: { // 'k' (0 - 23) -- like H int i = t.get(ChronoField.HOUR_OF_DAY); - sb.append(localizedMagnitude(null, i, Flags.NONE, 2, l)); + sb.append(localizedMagnitude(fmt, null, i, Flags.NONE, 2, l)); break; } case DateTime.HOUR_0: { // 'I' (01 - 12) int i = t.get(ChronoField.CLOCK_HOUR_OF_AMPM); - sb.append(localizedMagnitude(null, i, Flags.ZERO_PAD, 2, l)); + sb.append(localizedMagnitude(fmt, null, i, Flags.ZERO_PAD, 2, l)); break; } case DateTime.HOUR: { // 'l' (1 - 12) -- like I int i = t.get(ChronoField.CLOCK_HOUR_OF_AMPM); - sb.append(localizedMagnitude(null, i, Flags.NONE, 2, l)); + sb.append(localizedMagnitude(fmt, null, i, Flags.NONE, 2, l)); break; } case DateTime.MINUTE: { // 'M' (00 - 59) int i = t.get(ChronoField.MINUTE_OF_HOUR); - Flags flags = Flags.ZERO_PAD; - sb.append(localizedMagnitude(null, i, flags, 2, l)); + sb.append(localizedMagnitude(fmt, null, i, Flags.ZERO_PAD, 2, l)); break; } case DateTime.NANOSECOND: { // 'N' (000000000 - 999999999) @@ -4324,21 +4309,18 @@ public final class Formatter implements Closeable, Flushable { } catch (UnsupportedTemporalTypeException u) { i = t.get(ChronoField.MILLI_OF_SECOND) * 1000000; } - Flags flags = Flags.ZERO_PAD; - sb.append(localizedMagnitude(null, i, flags, 9, l)); + sb.append(localizedMagnitude(fmt, null, i, Flags.ZERO_PAD, 9, l)); break; } case DateTime.MILLISECOND: { // 'L' (000 - 999) int i = t.get(ChronoField.MILLI_OF_SECOND); - Flags flags = Flags.ZERO_PAD; - sb.append(localizedMagnitude(null, i, flags, 3, l)); + sb.append(localizedMagnitude(fmt, null, i, Flags.ZERO_PAD, 3, l)); break; } case DateTime.MILLISECOND_SINCE_EPOCH: { // 'Q' (0 - 99...?) long i = t.getLong(ChronoField.INSTANT_SECONDS) * 1000L + t.getLong(ChronoField.MILLI_OF_SECOND); - Flags flags = Flags.NONE; - sb.append(localizedMagnitude(null, i, flags, width, l)); + sb.append(localizedMagnitude(fmt, null, i, Flags.NONE, width, l)); break; } case DateTime.AM_PM: { // 'p' (am or pm) @@ -4355,14 +4337,12 @@ public final class Formatter implements Closeable, Flushable { } case DateTime.SECONDS_SINCE_EPOCH: { // 's' (0 - 99...?) long i = t.getLong(ChronoField.INSTANT_SECONDS); - Flags flags = Flags.NONE; - sb.append(localizedMagnitude(null, i, flags, width, l)); + sb.append(localizedMagnitude(fmt, null, i, Flags.NONE, width, l)); break; } case DateTime.SECOND: { // 'S' (00 - 60 - leap second) int i = t.get(ChronoField.SECOND_OF_MINUTE); - Flags flags = Flags.ZERO_PAD; - sb.append(localizedMagnitude(null, i, flags, 2, l)); + sb.append(localizedMagnitude(fmt, null, i, Flags.ZERO_PAD, 2, l)); break; } case DateTime.ZONE_NUMERIC: { // 'z' ({-|+}####) - ls minus? @@ -4374,8 +4354,7 @@ public final class Formatter implements Closeable, Flushable { int min = i / 60; // combine minute and hour into a single integer int offset = (min / 60) * 100 + (min % 60); - Flags flags = Flags.ZERO_PAD; - sb.append(localizedMagnitude(null, offset, flags, 4, l)); + sb.append(localizedMagnitude(fmt, null, offset, Flags.ZERO_PAD, 4, l)); break; } case DateTime.ZONE: { // 'Z' (symbol) @@ -4429,29 +4408,26 @@ public final class Formatter implements Closeable, Flushable { case DateTime.YEAR_2 -> i %= 100; case DateTime.YEAR_4 -> size = 4; } - Flags flags = Flags.ZERO_PAD; - sb.append(localizedMagnitude(null, i, flags, size, l)); + sb.append(localizedMagnitude(fmt, null, i, Flags.ZERO_PAD, size, l)); break; } case DateTime.DAY_OF_MONTH_0: // 'd' (01 - 31) case DateTime.DAY_OF_MONTH: { // 'e' (1 - 31) -- like d int i = t.get(ChronoField.DAY_OF_MONTH); - Flags flags = (c == DateTime.DAY_OF_MONTH_0 + int flags = (c == DateTime.DAY_OF_MONTH_0 ? Flags.ZERO_PAD : Flags.NONE); - sb.append(localizedMagnitude(null, i, flags, 2, l)); + sb.append(localizedMagnitude(fmt, null, i, flags, 2, l)); break; } case DateTime.DAY_OF_YEAR: { // 'j' (001 - 366) int i = t.get(ChronoField.DAY_OF_YEAR); - Flags flags = Flags.ZERO_PAD; - sb.append(localizedMagnitude(null, i, flags, 3, l)); + sb.append(localizedMagnitude(fmt, null, i, Flags.ZERO_PAD, 3, l)); break; } case DateTime.MONTH: { // 'm' (01 - 12) int i = t.get(ChronoField.MONTH_OF_YEAR); - Flags flags = Flags.ZERO_PAD; - sb.append(localizedMagnitude(null, i, flags, 2, l)); + sb.append(localizedMagnitude(fmt, null, i, Flags.ZERO_PAD, 2, l)); break; } @@ -4459,47 +4435,47 @@ public final class Formatter implements Closeable, Flushable { case DateTime.TIME: // 'T' (24 hour hh:mm:ss - %tH:%tM:%tS) case DateTime.TIME_24_HOUR: { // 'R' (hh:mm same as %H:%M) char sep = ':'; - print(sb, t, DateTime.HOUR_OF_DAY_0, l).append(sep); - print(sb, t, DateTime.MINUTE, l); + print(fmt, sb, t, DateTime.HOUR_OF_DAY_0, l).append(sep); + print(fmt, sb, t, DateTime.MINUTE, l); if (c == DateTime.TIME) { sb.append(sep); - print(sb, t, DateTime.SECOND, l); + print(fmt, sb, t, DateTime.SECOND, l); } break; } case DateTime.TIME_12_HOUR: { // 'r' (hh:mm:ss [AP]M) char sep = ':'; - print(sb, t, DateTime.HOUR_0, l).append(sep); - print(sb, t, DateTime.MINUTE, l).append(sep); - print(sb, t, DateTime.SECOND, l).append(' '); + print(fmt, sb, t, DateTime.HOUR_0, l).append(sep); + print(fmt, sb, t, DateTime.MINUTE, l).append(sep); + print(fmt, sb, t, DateTime.SECOND, l).append(' '); // this may be in wrong place for some locales StringBuilder tsb = new StringBuilder(); - print(tsb, t, DateTime.AM_PM, l); + print(fmt, tsb, t, DateTime.AM_PM, l); sb.append(toUpperCaseWithLocale(tsb.toString(), l)); break; } case DateTime.DATE_TIME: { // 'c' (Sat Nov 04 12:02:33 EST 1999) char sep = ' '; - print(sb, t, DateTime.NAME_OF_DAY_ABBREV, l).append(sep); - print(sb, t, DateTime.NAME_OF_MONTH_ABBREV, l).append(sep); - print(sb, t, DateTime.DAY_OF_MONTH_0, l).append(sep); - print(sb, t, DateTime.TIME, l).append(sep); - print(sb, t, DateTime.ZONE, l).append(sep); - print(sb, t, DateTime.YEAR_4, l); + print(fmt, sb, t, DateTime.NAME_OF_DAY_ABBREV, l).append(sep); + print(fmt, sb, t, DateTime.NAME_OF_MONTH_ABBREV, l).append(sep); + print(fmt, sb, t, DateTime.DAY_OF_MONTH_0, l).append(sep); + print(fmt, sb, t, DateTime.TIME, l).append(sep); + print(fmt, sb, t, DateTime.ZONE, l).append(sep); + print(fmt, sb, t, DateTime.YEAR_4, l); break; } case DateTime.DATE: { // 'D' (mm/dd/yy) char sep = '/'; - print(sb, t, DateTime.MONTH, l).append(sep); - print(sb, t, DateTime.DAY_OF_MONTH_0, l).append(sep); - print(sb, t, DateTime.YEAR_2, l); + print(fmt, sb, t, DateTime.MONTH, l).append(sep); + print(fmt, sb, t, DateTime.DAY_OF_MONTH_0, l).append(sep); + print(fmt, sb, t, DateTime.YEAR_2, l); break; } case DateTime.ISO_STANDARD_DATE: { // 'F' (%Y-%m-%d) char sep = '-'; - print(sb, t, DateTime.YEAR_4, l).append(sep); - print(sb, t, DateTime.MONTH, l).append(sep); - print(sb, t, DateTime.DAY_OF_MONTH_0, l); + print(fmt, sb, t, DateTime.YEAR_4, l).append(sep); + print(fmt, sb, t, DateTime.MONTH, l).append(sep); + print(fmt, sb, t, DateTime.DAY_OF_MONTH_0, l); break; } default: @@ -4513,8 +4489,8 @@ public final class Formatter implements Closeable, Flushable { // -- Methods to support throwing exceptions -- - private void failMismatch(Flags f, char c) { - String fs = f.toString(); + private void failMismatch(int f, char c) { + String fs = Flags.toString(f); throw new FormatFlagsConversionMismatchException(fs, c); } @@ -4522,28 +4498,28 @@ public final class Formatter implements Closeable, Flushable { throw new IllegalFormatConversionException(c, arg.getClass()); } - private char getZero(Locale l) { - if ((l != null) && !l.equals(locale())) { + private char getZero(Formatter fmt, Locale l) { + if ((l != null) && !l.equals(fmt.locale())) { DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(l); return dfs.getZeroDigit(); } - return zero(); + return fmt.zero(); } - private StringBuilder localizedMagnitude(StringBuilder sb, - long value, Flags f, int width, Locale l) { - return localizedMagnitude(sb, Long.toString(value, 10), 0, f, width, l); + private StringBuilder localizedMagnitude(Formatter fmt, StringBuilder sb, + long value, int flags, int width, Locale l) { + return localizedMagnitude(fmt, sb, Long.toString(value, 10), 0, flags, width, l); } - private StringBuilder localizedMagnitude(StringBuilder sb, - CharSequence value, final int offset, Flags f, int width, + private StringBuilder localizedMagnitude(Formatter fmt, StringBuilder sb, + CharSequence value, final int offset, int f, int width, Locale l) { if (sb == null) { sb = new StringBuilder(); } int begin = sb.length(); - char zero = getZero(l); + char zero = getZero(fmt, l); // determine localized grouping separator and size char grpSep = '\0'; @@ -4568,7 +4544,7 @@ public final class Formatter implements Closeable, Flushable { } } - if (f.contains(Flags.GROUP)) { + if (Flags.contains(f, Flags.GROUP)) { if (l == null || l.equals(Locale.US)) { grpSep = ','; grpSize = 3; @@ -4622,7 +4598,7 @@ public final class Formatter implements Closeable, Flushable { } // apply zero padding - if (width != -1 && f.contains(Flags.ZERO_PAD)) { + if (width != -1 && Flags.contains(f, Flags.ZERO_PAD)) { for (int k = sb.length(); k < width; k++) { sb.insert(begin, zero); } @@ -4634,9 +4610,9 @@ public final class Formatter implements Closeable, Flushable { // Specialized localization of exponents, where the source value can only // contain characters '0' through '9', starting at index offset, and no // group separators is added for any locale. - private void localizedMagnitudeExp(StringBuilder sb, char[] value, + private void localizedMagnitudeExp(Formatter fmt, StringBuilder sb, char[] value, final int offset, Locale l) { - char zero = getZero(l); + char zero = getZero(fmt, l); int len = value.length; for (int j = offset; j < len; j++) { @@ -4647,65 +4623,54 @@ public final class Formatter implements Closeable, Flushable { } private static class Flags { - private int flags; - static final Flags NONE = new Flags(0); // '' + static final int NONE = 0; // '' // duplicate declarations from Formattable.java - static final Flags LEFT_JUSTIFY = new Flags(1<<0); // '-' - static final Flags UPPERCASE = new Flags(1<<1); // '^' - static final Flags ALTERNATE = new Flags(1<<2); // '#' + static final int LEFT_JUSTIFY = 1<<0; // '-' + static final int UPPERCASE = 1<<1; // '^' + static final int ALTERNATE = 1<<2; // '#' // numerics - static final Flags PLUS = new Flags(1<<3); // '+' - static final Flags LEADING_SPACE = new Flags(1<<4); // ' ' - static final Flags ZERO_PAD = new Flags(1<<5); // '0' - static final Flags GROUP = new Flags(1<<6); // ',' - static final Flags PARENTHESES = new Flags(1<<7); // '(' + static final int PLUS = 1<<3; // '+' + static final int LEADING_SPACE = 1<<4; // ' ' + static final int ZERO_PAD = 1<<5; // '0' + static final int GROUP = 1<<6; // ',' + static final int PARENTHESES = 1<<7; // '(' // indexing - static final Flags PREVIOUS = new Flags(1<<8); // '<' - - private Flags(int f) { - flags = f; - } - - public int valueOf() { - return flags; - } + static final int PREVIOUS = 1<<8; // '<' - public boolean contains(Flags f) { - return (flags & f.valueOf()) == f.valueOf(); + public static boolean contains(int flags, int f) { + return (flags & f) == f; } - public Flags dup() { - return new Flags(flags); + public static boolean containsAny(int flags, int f) { + return (flags & f) != 0; } - private Flags add(Flags f) { - flags |= f.valueOf(); - return this; + private static int add(int flags, int f) { + return flags | f; } - public Flags remove(Flags f) { - flags &= ~f.valueOf(); - return this; + public static int remove(int flags, int f) { + return flags & ~f; } - public static Flags parse(String s, int start, int end) { - Flags f = new Flags(0); + public static int parse(String s, int start, int end) { + int f = 0; for (int i = start; i < end; i++) { char c = s.charAt(i); - Flags v = parse(c); - if (f.contains(v)) - throw new DuplicateFormatFlagsException(v.toString()); - f.add(v); + int v = parse(c); + if (contains(f, v)) + throw new DuplicateFormatFlagsException(toString(v)); + f = add(f, v); } return f; } // parse those flags which may be provided by users - private static Flags parse(char c) { + private static int parse(char c) { return switch (c) { case '-' -> LEFT_JUSTIFY; case '#' -> ALTERNATE; @@ -4720,21 +4685,17 @@ public final class Formatter implements Closeable, Flushable { } // Returns a string representation of the current {@code Flags}. - public static String toString(Flags f) { - return f.toString(); - } - - public String toString() { + public static String toString(int f) { StringBuilder sb = new StringBuilder(); - if (contains(LEFT_JUSTIFY)) sb.append('-'); - if (contains(UPPERCASE)) sb.append('^'); - if (contains(ALTERNATE)) sb.append('#'); - if (contains(PLUS)) sb.append('+'); - if (contains(LEADING_SPACE)) sb.append(' '); - if (contains(ZERO_PAD)) sb.append('0'); - if (contains(GROUP)) sb.append(','); - if (contains(PARENTHESES)) sb.append('('); - if (contains(PREVIOUS)) sb.append('<'); + if (contains(f, LEFT_JUSTIFY)) sb.append('-'); + if (contains(f, UPPERCASE)) sb.append('^'); + if (contains(f, ALTERNATE)) sb.append('#'); + if (contains(f, PLUS)) sb.append('+'); + if (contains(f, LEADING_SPACE)) sb.append(' '); + if (contains(f, ZERO_PAD)) sb.append('0'); + if (contains(f, GROUP)) sb.append(','); + if (contains(f, PARENTHESES)) sb.append('('); + if (contains(f, PREVIOUS)) sb.append('<'); return sb.toString(); } } diff --git a/src/java.base/share/classes/java/util/Optional.java b/src/java.base/share/classes/java/util/Optional.java index 64647ee49d5c18f34d083e959c564d14fedff069..cd8b2b6048fb60a32445aef0f7d22e92eb31f329 100644 --- a/src/java.base/share/classes/java/util/Optional.java +++ b/src/java.base/share/classes/java/util/Optional.java @@ -454,7 +454,7 @@ public final class Optional { @Override public String toString() { return value != null - ? String.format("Optional[%s]", value) + ? ("Optional[" + value + "]") : "Optional.empty"; } } diff --git a/src/java.base/share/classes/java/util/OptionalDouble.java b/src/java.base/share/classes/java/util/OptionalDouble.java index 61e54cfec2992c66db501b139c5722ef3f3e0b67..752aaac1e547ed28f69cafa9fbd38106825316b1 100644 --- a/src/java.base/share/classes/java/util/OptionalDouble.java +++ b/src/java.base/share/classes/java/util/OptionalDouble.java @@ -328,7 +328,7 @@ public final class OptionalDouble { @Override public String toString() { return isPresent - ? String.format("OptionalDouble[%s]", value) + ? ("OptionalDouble[" + value + "]") : "OptionalDouble.empty"; } } diff --git a/src/java.base/share/classes/java/util/OptionalInt.java b/src/java.base/share/classes/java/util/OptionalInt.java index d693a3ddba2fd109ef6b8f00377205d8f8babe18..c1e62090c25c5e10bb635dc5066bd81598f37aa5 100644 --- a/src/java.base/share/classes/java/util/OptionalInt.java +++ b/src/java.base/share/classes/java/util/OptionalInt.java @@ -326,7 +326,7 @@ public final class OptionalInt { @Override public String toString() { return isPresent - ? String.format("OptionalInt[%s]", value) + ? ("OptionalInt[" + value + "]") : "OptionalInt.empty"; } } diff --git a/src/java.base/share/classes/java/util/OptionalLong.java b/src/java.base/share/classes/java/util/OptionalLong.java index f92c5bdff175c34402c93523a7b513366ebf73f8..2c1171f86e9b763c7f63186113282b9a139b68d6 100644 --- a/src/java.base/share/classes/java/util/OptionalLong.java +++ b/src/java.base/share/classes/java/util/OptionalLong.java @@ -326,7 +326,7 @@ public final class OptionalLong { @Override public String toString() { return isPresent - ? String.format("OptionalLong[%s]", value) + ? ("OptionalLong[" + value + "]") : "OptionalLong.empty"; } } diff --git a/src/java.base/share/classes/java/util/concurrent/Executors.java b/src/java.base/share/classes/java/util/concurrent/Executors.java index a9e7de32a002f60f887ea74c0bc37f545d7a4e99..3345153bd9777e5901519aa58162d24d8566aab9 100644 --- a/src/java.base/share/classes/java/util/concurrent/Executors.java +++ b/src/java.base/share/classes/java/util/concurrent/Executors.java @@ -791,7 +791,7 @@ public class Executors { FinalizableDelegatedExecutorService(ExecutorService executor) { super(executor); } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() { super.shutdown(); } diff --git a/src/java.base/share/classes/java/util/concurrent/ThreadPoolExecutor.java b/src/java.base/share/classes/java/util/concurrent/ThreadPoolExecutor.java index 49d2a29b2624bc078526b284b85c8371d7dbf359..f23e72a8f70c82f2bba7845c54f02f2d9d920de1 100644 --- a/src/java.base/share/classes/java/util/concurrent/ThreadPoolExecutor.java +++ b/src/java.base/share/classes/java/util/concurrent/ThreadPoolExecutor.java @@ -1477,8 +1477,13 @@ public class ThreadPoolExecutor extends AbstractExecutorService { * @implNote Previous versions of this class had a finalize method * that shut down this executor, but in this version, finalize * does nothing. + * + * @deprecated Finalization has been deprecated for removal. See + * {@link java.lang.Object#finalize} for background information and details + * about migration options. */ - @Deprecated(since="9") + @Deprecated(since="9", forRemoval=true) + @SuppressWarnings("removal") protected void finalize() {} /** diff --git a/src/java.base/share/classes/java/util/stream/AbstractTask.java b/src/java.base/share/classes/java/util/stream/AbstractTask.java index 44c2656157b4083df7dd29ca6b65860930437124..9a61729f68d6234a4fdea154eeb5192928368a6b 100644 --- a/src/java.base/share/classes/java/util/stream/AbstractTask.java +++ b/src/java.base/share/classes/java/util/stream/AbstractTask.java @@ -180,7 +180,7 @@ abstract class AbstractTask The type of input element diff --git a/src/java.base/share/classes/java/util/stream/Node.java b/src/java.base/share/classes/java/util/stream/Node.java index 131195944eeaa414177707294b07e7e02019b5ef..7c4dda8adaf901bc3aef156420563cddef5b7981 100644 --- a/src/java.base/share/classes/java/util/stream/Node.java +++ b/src/java.base/share/classes/java/util/stream/Node.java @@ -200,7 +200,7 @@ interface Node { Node build(); /** - * Specialized @{code Node.Builder} for int elements + * Specialized {@code Node.Builder} for int elements */ interface OfInt extends Node.Builder, Sink.OfInt { @Override @@ -208,7 +208,7 @@ interface Node { } /** - * Specialized @{code Node.Builder} for long elements + * Specialized {@code Node.Builder} for long elements */ interface OfLong extends Node.Builder, Sink.OfLong { @Override @@ -216,7 +216,7 @@ interface Node { } /** - * Specialized @{code Node.Builder} for double elements + * Specialized {@code Node.Builder} for double elements */ interface OfDouble extends Node.Builder, Sink.OfDouble { @Override diff --git a/src/java.base/share/classes/java/util/stream/Nodes.java b/src/java.base/share/classes/java/util/stream/Nodes.java index ae0c202e51499aa484773dc29e53d67d08861271..33e1d920c26c39db9e66512ce6db019350e44e12 100644 --- a/src/java.base/share/classes/java/util/stream/Nodes.java +++ b/src/java.base/share/classes/java/util/stream/Nodes.java @@ -170,7 +170,7 @@ final class Nodes { } /** - * Produces a variable size @{link Node.Builder}. + * Produces a variable size {@link Node.Builder}. * * @param the type of elements of the node builder * @return a {@code Node.Builder} @@ -208,7 +208,7 @@ final class Nodes { } /** - * Produces a variable size @{link Node.Builder.OfInt}. + * Produces a variable size {@link Node.Builder.OfInt}. * * @return a {@code Node.Builder.OfInt} */ @@ -245,7 +245,7 @@ final class Nodes { } /** - * Produces a variable size @{link Node.Builder.OfLong}. + * Produces a variable size {@link Node.Builder.OfLong}. * * @return a {@code Node.Builder.OfLong} */ @@ -282,7 +282,7 @@ final class Nodes { } /** - * Produces a variable size @{link Node.Builder.OfDouble}. + * Produces a variable size {@link Node.Builder.OfDouble}. * * @return a {@code Node.Builder.OfDouble} */ diff --git a/src/java.base/share/classes/java/util/stream/PipelineHelper.java b/src/java.base/share/classes/java/util/stream/PipelineHelper.java index 7503bb6bf56fbb26e46ae463427408c6f75aac74..9571311ac1ff91014600f7d9e68e46ea54769247 100644 --- a/src/java.base/share/classes/java/util/stream/PipelineHelper.java +++ b/src/java.base/share/classes/java/util/stream/PipelineHelper.java @@ -163,7 +163,7 @@ abstract class PipelineHelper { abstract Spliterator wrapSpliterator(Spliterator spliterator); /** - * Constructs a @{link Node.Builder} compatible with the output shape of + * Constructs a {@link Node.Builder} compatible with the output shape of * this {@code PipelineHelper}. * * @param exactSizeIfKnown if >=0 then a builder will be created that has a diff --git a/src/java.base/share/classes/java/util/zip/DeflaterInputStream.java b/src/java.base/share/classes/java/util/zip/DeflaterInputStream.java index e0ecba0fcad5649e35e33aa7849b513824db3132..84d2c888543525ad94bf23544232879e3b7cd02b 100644 --- a/src/java.base/share/classes/java/util/zip/DeflaterInputStream.java +++ b/src/java.base/share/classes/java/util/zip/DeflaterInputStream.java @@ -28,6 +28,7 @@ package java.util.zip; import java.io.FilterInputStream; import java.io.InputStream; import java.io.IOException; +import java.util.Objects; /** * Implements an input stream filter for compressing data in the "deflate" @@ -172,9 +173,9 @@ public class DeflaterInputStream extends FilterInputStream { ensureOpen(); if (b == null) { throw new NullPointerException("Null buffer for read"); - } else if (off < 0 || len < 0 || len > b.length - off) { - throw new IndexOutOfBoundsException(); - } else if (len == 0) { + } + Objects.checkFromIndexSize(off, len, b.length); + if (len == 0) { return 0; } diff --git a/src/java.base/share/classes/java/util/zip/DeflaterOutputStream.java b/src/java.base/share/classes/java/util/zip/DeflaterOutputStream.java index 365bc676b082e372b4bbe9fdc7c8b3c55cb73fc8..7dfbd7f9edb5b4ef8644fa9f4fbfd825e31e7332 100644 --- a/src/java.base/share/classes/java/util/zip/DeflaterOutputStream.java +++ b/src/java.base/share/classes/java/util/zip/DeflaterOutputStream.java @@ -234,9 +234,12 @@ public class DeflaterOutputStream extends FilterOutputStream { */ public void close() throws IOException { if (!closed) { - finish(); - if (usesDefaultDeflater) - def.end(); + try { + finish(); + } finally { + if (usesDefaultDeflater) + def.end(); + } out.close(); closed = true; } diff --git a/src/java.base/share/classes/java/util/zip/GZIPOutputStream.java b/src/java.base/share/classes/java/util/zip/GZIPOutputStream.java index 153af0959b18189086a05a838e38bc499ffc2ef0..cdfac329cfa83896f3eb69a14221ac2578baeba7 100644 --- a/src/java.base/share/classes/java/util/zip/GZIPOutputStream.java +++ b/src/java.base/share/classes/java/util/zip/GZIPOutputStream.java @@ -157,24 +157,30 @@ public class GZIPOutputStream extends DeflaterOutputStream { */ public void finish() throws IOException { if (!def.finished()) { - def.finish(); - while (!def.finished()) { - int len = def.deflate(buf, 0, buf.length); - if (def.finished() && len <= buf.length - TRAILER_SIZE) { - // last deflater buffer. Fit trailer at the end - writeTrailer(buf, len); - len = len + TRAILER_SIZE; - out.write(buf, 0, len); - return; + try { + def.finish(); + while (!def.finished()) { + int len = def.deflate(buf, 0, buf.length); + if (def.finished() && len <= buf.length - TRAILER_SIZE) { + // last deflater buffer. Fit trailer at the end + writeTrailer(buf, len); + len = len + TRAILER_SIZE; + out.write(buf, 0, len); + return; + } + if (len > 0) + out.write(buf, 0, len); } - if (len > 0) - out.write(buf, 0, len); + // if we can't fit the trailer at the end of the last + // deflater buffer, we write it separately + byte[] trailer = new byte[TRAILER_SIZE]; + writeTrailer(trailer, 0); + out.write(trailer); + } catch (IOException e) { + if (usesDefaultDeflater) + def.end(); + throw e; } - // if we can't fit the trailer at the end of the last - // deflater buffer, we write it separately - byte[] trailer = new byte[TRAILER_SIZE]; - writeTrailer(trailer, 0); - out.write(trailer); } } diff --git a/src/java.base/share/classes/java/util/zip/InflaterInputStream.java b/src/java.base/share/classes/java/util/zip/InflaterInputStream.java index 534241d3d0a59aca11471cfa6f9a3c80f4af7bd3..e8ab2a449732cf786695fb185f74ff49089c0477 100644 --- a/src/java.base/share/classes/java/util/zip/InflaterInputStream.java +++ b/src/java.base/share/classes/java/util/zip/InflaterInputStream.java @@ -29,6 +29,7 @@ import java.io.FilterInputStream; import java.io.InputStream; import java.io.IOException; import java.io.EOFException; +import java.util.Objects; /** * This class implements a stream filter for uncompressing data in the @@ -142,9 +143,9 @@ public class InflaterInputStream extends FilterInputStream { ensureOpen(); if (b == null) { throw new NullPointerException(); - } else if (off < 0 || len < 0 || len > b.length - off) { - throw new IndexOutOfBoundsException(); - } else if (len == 0) { + } + Objects.checkFromIndexSize(off, len, b.length); + if (len == 0) { return 0; } try { diff --git a/src/java.base/share/classes/java/util/zip/InflaterOutputStream.java b/src/java.base/share/classes/java/util/zip/InflaterOutputStream.java index aa306239224133f743e0aa7b7942432807f10611..7b08d5b45385caaecec8d14ceee6c3eb3ec3a4f9 100644 --- a/src/java.base/share/classes/java/util/zip/InflaterOutputStream.java +++ b/src/java.base/share/classes/java/util/zip/InflaterOutputStream.java @@ -28,6 +28,7 @@ package java.util.zip; import java.io.FilterOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.util.Objects; /** * Implements an output stream filter for uncompressing data stored in the @@ -223,9 +224,9 @@ public class InflaterOutputStream extends FilterOutputStream { ensureOpen(); if (b == null) { throw new NullPointerException("Null buffer for read"); - } else if (off < 0 || len < 0 || len > b.length - off) { - throw new IndexOutOfBoundsException(); - } else if (len == 0) { + } + Objects.checkFromIndexSize(off, len, b.length); + if (len == 0) { return; } diff --git a/src/java.base/share/classes/java/util/zip/ZipEntry.java b/src/java.base/share/classes/java/util/zip/ZipEntry.java index 9ff3533116c6fa980114443f6f9bde72fd50279a..5846d6cc3bb64ea820107f5fa7ff976db126e1e7 100644 --- a/src/java.base/share/classes/java/util/zip/ZipEntry.java +++ b/src/java.base/share/classes/java/util/zip/ZipEntry.java @@ -153,7 +153,7 @@ public class ZipEntry implements ZipConstants, Cloneable { * be stored into the {@code date and time fields} of the zip file * entry and encoded in standard {@code MS-DOS date and time format}. * The {@link java.util.TimeZone#getDefault() default TimeZone} is - * used to convert the epoch time to the MS-DOS data and time. + * used to convert the epoch time to the MS-DOS date and time. * * @param time * The last modification time of the entry in milliseconds diff --git a/src/java.base/share/classes/java/util/zip/ZipInputStream.java b/src/java.base/share/classes/java/util/zip/ZipInputStream.java index 4c1eac3204c0fe9153db69b69fbb9cdc93d7c504..5f740a76655b7d8f6f08d01bc34fac4cd2e6cf16 100644 --- a/src/java.base/share/classes/java/util/zip/ZipInputStream.java +++ b/src/java.base/share/classes/java/util/zip/ZipInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ import java.io.IOException; import java.io.EOFException; import java.io.PushbackInputStream; import java.nio.charset.Charset; +import java.util.Objects; import sun.nio.cs.UTF_8; @@ -182,9 +183,8 @@ public class ZipInputStream extends InflaterInputStream implements ZipConstants */ public int read(byte[] b, int off, int len) throws IOException { ensureOpen(); - if (off < 0 || len < 0 || off > b.length - len) { - throw new IndexOutOfBoundsException(); - } else if (len == 0) { + Objects.checkFromIndexSize(off, len, b.length); + if (len == 0) { return 0; } diff --git a/src/java.base/share/classes/java/util/zip/ZipOutputStream.java b/src/java.base/share/classes/java/util/zip/ZipOutputStream.java index c43bcd3810339773b9d026dad2297824921d643b..1b8ed562d9f7d0a5bd1f3f85a2acd37ab26695c1 100644 --- a/src/java.base/share/classes/java/util/zip/ZipOutputStream.java +++ b/src/java.base/share/classes/java/util/zip/ZipOutputStream.java @@ -28,6 +28,7 @@ package java.util.zip; import java.io.OutputStream; import java.io.IOException; import java.nio.charset.Charset; +import java.util.Objects; import java.util.Vector; import java.util.HashSet; import static java.util.zip.ZipConstants64.*; @@ -259,58 +260,64 @@ public class ZipOutputStream extends DeflaterOutputStream implements ZipConstant public void closeEntry() throws IOException { ensureOpen(); if (current != null) { - ZipEntry e = current.entry; - switch (e.method) { - case DEFLATED -> { - def.finish(); - while (!def.finished()) { - deflate(); - } - if ((e.flag & 8) == 0) { - // verify size, compressed size, and crc-32 settings - if (e.size != def.getBytesRead()) { - throw new ZipException( - "invalid entry size (expected " + e.size + - " but got " + def.getBytesRead() + " bytes)"); - } - if (e.csize != def.getBytesWritten()) { - throw new ZipException( - "invalid entry compressed size (expected " + - e.csize + " but got " + def.getBytesWritten() + " bytes)"); + try { + ZipEntry e = current.entry; + switch (e.method) { + case DEFLATED -> { + def.finish(); + while (!def.finished()) { + deflate(); + } + if ((e.flag & 8) == 0) { + // verify size, compressed size, and crc-32 settings + if (e.size != def.getBytesRead()) { + throw new ZipException( + "invalid entry size (expected " + e.size + + " but got " + def.getBytesRead() + " bytes)"); + } + if (e.csize != def.getBytesWritten()) { + throw new ZipException( + "invalid entry compressed size (expected " + + e.csize + " but got " + def.getBytesWritten() + " bytes)"); + } + if (e.crc != crc.getValue()) { + throw new ZipException( + "invalid entry CRC-32 (expected 0x" + + Long.toHexString(e.crc) + " but got 0x" + + Long.toHexString(crc.getValue()) + ")"); + } + } else { + e.size = def.getBytesRead(); + e.csize = def.getBytesWritten(); + e.crc = crc.getValue(); + writeEXT(e); + } + def.reset(); + written += e.csize; } - if (e.crc != crc.getValue()) { - throw new ZipException( - "invalid entry CRC-32 (expected 0x" + - Long.toHexString(e.crc) + " but got 0x" + - Long.toHexString(crc.getValue()) + ")"); + case STORED -> { + // we already know that both e.size and e.csize are the same + if (e.size != written - locoff) { + throw new ZipException( + "invalid entry size (expected " + e.size + + " but got " + (written - locoff) + " bytes)"); + } + if (e.crc != crc.getValue()) { + throw new ZipException( + "invalid entry crc-32 (expected 0x" + + Long.toHexString(e.crc) + " but got 0x" + + Long.toHexString(crc.getValue()) + ")"); + } } - } else { - e.size = def.getBytesRead(); - e.csize = def.getBytesWritten(); - e.crc = crc.getValue(); - writeEXT(e); + default -> throw new ZipException("invalid compression method"); } - def.reset(); - written += e.csize; - } - case STORED -> { - // we already know that both e.size and e.csize are the same - if (e.size != written - locoff) { - throw new ZipException( - "invalid entry size (expected " + e.size + - " but got " + (written - locoff) + " bytes)"); - } - if (e.crc != crc.getValue()) { - throw new ZipException( - "invalid entry crc-32 (expected 0x" + - Long.toHexString(e.crc) + " but got 0x" + - Long.toHexString(crc.getValue()) + ")"); - } - } - default -> throw new ZipException("invalid compression method"); + crc.reset(); + current = null; + } catch (IOException e) { + if (usesDefaultDeflater && !(e instanceof ZipException)) + def.end(); + throw e; } - crc.reset(); - current = null; } } @@ -327,9 +334,8 @@ public class ZipOutputStream extends DeflaterOutputStream implements ZipConstant throws IOException { ensureOpen(); - if (off < 0 || len < 0 || off > b.length - len) { - throw new IndexOutOfBoundsException(); - } else if (len == 0) { + Objects.checkFromIndexSize(off, len, b.length); + if (len == 0) { return; } diff --git a/src/java.base/share/classes/javax/security/auth/Subject.java b/src/java.base/share/classes/javax/security/auth/Subject.java index 8e30f84ff4467114ded80e4b21792b245eb03770..c1235bffd532f34d9f7dd02faf1c8a8271a9fc6a 100644 --- a/src/java.base/share/classes/javax/security/auth/Subject.java +++ b/src/java.base/share/classes/javax/security/auth/Subject.java @@ -402,6 +402,7 @@ public final class Subject implements java.io.Serializable { */ public static T callAs(final Subject subject, final Callable action) throws CompletionException { + Objects.requireNonNull(action); if (USE_TL) { Subject oldSubject = SUBJECT_THREAD_LOCAL.get(); SUBJECT_THREAD_LOCAL.set(subject); diff --git a/src/java.base/share/classes/jdk/internal/access/JavaLangInvokeAccess.java b/src/java.base/share/classes/jdk/internal/access/JavaLangInvokeAccess.java index ee655188c9d3e4dc9174c9f03dbecf053c862c23..20823fcfcad90f1f73385664450059211ead423c 100644 --- a/src/java.base/share/classes/jdk/internal/access/JavaLangInvokeAccess.java +++ b/src/java.base/share/classes/jdk/internal/access/JavaLangInvokeAccess.java @@ -181,4 +181,11 @@ public interface JavaLangInvokeAccess { * The given bytes is trusted. */ Lookup defineHiddenClassWithClassData(Lookup caller, String name, byte[] bytes, Object classData, boolean initialize); + + /** + * A best-effort method that tries to find any exceptions thrown by the given method handle. + * @param handle the handle to check + * @return an array of exceptions, or {@code null}. + */ + Class[] exceptionTypes(MethodHandle handle); } diff --git a/src/java.base/share/classes/jdk/internal/access/JavaNioAccess.java b/src/java.base/share/classes/jdk/internal/access/JavaNioAccess.java index c639e4ced83217cbbb5d36cd1c018e686d8f0f56..82739b9bf074ca56a53c491bfd5f6ae5a954e6c0 100644 --- a/src/java.base/share/classes/jdk/internal/access/JavaNioAccess.java +++ b/src/java.base/share/classes/jdk/internal/access/JavaNioAccess.java @@ -92,7 +92,7 @@ public interface JavaNioAccess { * scope handle. Null is returned if the buffer has no scope, or * acquiring is not required to guarantee safety. */ - Scope.Handle acquireScope(Buffer buffer, boolean async); + Runnable acquireScope(Buffer buffer, boolean async); /** * Used by {@code jdk.internal.foreign.MappedMemorySegmentImpl} and byte buffer var handle views. diff --git a/src/java.base/share/classes/jdk/internal/jimage/ImageStringsReader.java b/src/java.base/share/classes/jdk/internal/jimage/ImageStringsReader.java index f5773302004030b195109bc4195a0f8453725a03..c4601ef3e6cc62a17683b95c005d0a548fa33b07 100644 --- a/src/java.base/share/classes/jdk/internal/jimage/ImageStringsReader.java +++ b/src/java.base/share/classes/jdk/internal/jimage/ImageStringsReader.java @@ -309,7 +309,7 @@ public class ImageStringsReader implements ImageStrings { return -1; } } - return length; + return current - offset + length; } static int mutf8FromStringLength(String s) { diff --git a/src/java.base/share/classes/jdk/internal/misc/CDS.java b/src/java.base/share/classes/jdk/internal/misc/CDS.java index 43f6128cc0576f5e979b2b9682794c885cd9c9e2..370086612cd83b8ed4cdf23fc129ee31f5970d32 100644 --- a/src/java.base/share/classes/jdk/internal/misc/CDS.java +++ b/src/java.base/share/classes/jdk/internal/misc/CDS.java @@ -66,7 +66,7 @@ public class CDS { } /** - * Is sharing enabled via the UseSharedSpaces flag. + * Is sharing enabled. */ public static boolean isSharingEnabled() { return isSharingEnabled; @@ -232,15 +232,11 @@ public class CDS { private static String[] excludeFlags = { "-XX:DumpLoadedClassList=", - "-XX:+DumpSharedSpaces", - "-XX:+DynamicDumpSharedSpaces", "-XX:+RecordDynamicDumpInfo", "-Xshare:", "-XX:SharedClassListFile=", "-XX:SharedArchiveFile=", - "-XX:ArchiveClassesAtExit=", - "-XX:+UseSharedSpaces", - "-XX:+RequireSharedSpaces"}; + "-XX:ArchiveClassesAtExit="}; private static boolean containsExcludedFlags(String testStr) { for (String e : excludeFlags) { if (testStr.contains(e)) { diff --git a/src/java.base/share/classes/jdk/internal/misc/X-ScopedMemoryAccess.java.template b/src/java.base/share/classes/jdk/internal/misc/X-ScopedMemoryAccess.java.template index e4cf2f5b2ed984527d703ea4137797701b9aa7e4..be2e8cb24ffc74025a317a8bb7020a6c834b11f9 100644 --- a/src/java.base/share/classes/jdk/internal/misc/X-ScopedMemoryAccess.java.template +++ b/src/java.base/share/classes/jdk/internal/misc/X-ScopedMemoryAccess.java.template @@ -103,19 +103,13 @@ public class ScopedMemoryAccess { */ public interface Scope { - interface Handle { - Scope scope(); - } - void checkValidState(); Thread ownerThread(); - boolean isImplicit(); - - Handle acquire(); + void acquire0(); - void release(Handle handle); + void release0(); /** * Error thrown when memory access fails because the memory has already been released. diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java index 17575546518ee5a5b7b1aa007fedaab8e5f25abf..e306e60d45bf209990bd019099ecc8ed605cadcd 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java @@ -222,7 +222,7 @@ public class ClassReader { this.b = classFileBuffer; // Check the class' major_version. This field is after the magic and minor_version fields, which // use 4 and 2 bytes respectively. - if (checkClassVersion && readShort(classFileOffset + 6) > Opcodes.V18) { + if (checkClassVersion && readShort(classFileOffset + 6) > Opcodes.V19) { throw new IllegalArgumentException( "Unsupported class file major version " + readShort(classFileOffset + 6)); } diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java index e8be8c1935ccfb1e6f082bd04a4a0e6a2e874bc8..d1b6d52865cca24e5ed7d767f8789e1038b69c39 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java @@ -314,6 +314,7 @@ public interface Opcodes { int V16 = 0 << 16 | 60; int V17 = 0 << 16 | 61; int V18 = 0 << 16 | 62; + int V19 = 0 << 16 | 63; /** * Version flag indicating that the class is using 'preview' features. diff --git a/src/java.base/share/classes/jdk/internal/reflect/Reflection.java b/src/java.base/share/classes/jdk/internal/reflect/Reflection.java index ce9655f7a78358c1d7249fb0e4e86bab994cce11..76a4bf8fa4a643beeb647d193ae2610bc7d4f0fc 100644 --- a/src/java.base/share/classes/jdk/internal/reflect/Reflection.java +++ b/src/java.base/share/classes/jdk/internal/reflect/Reflection.java @@ -32,6 +32,7 @@ import java.util.Objects; import java.util.Set; import jdk.internal.access.SharedSecrets; import jdk.internal.misc.VM; +import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.annotation.IntrinsicCandidate; /** Common utility routines used by both java.lang and @@ -106,6 +107,7 @@ public class Reflection { } } + @ForceInline public static void ensureNativeAccess(Class currentClass) { Module module = currentClass.getModule(); if (!SharedSecrets.getJavaLangAccess().isEnableNativeAccess(module)) { diff --git a/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java b/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java index 1d64432979d907864d3ebb928e78fe4125b7d3af..d47043b89aa199a5dca72c44e28ca3876e09d7b8 100644 --- a/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java +++ b/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java @@ -1186,10 +1186,10 @@ public class RandomSupport { // For the exponential distribution, every overhang is convex. final double[] X = DoubleZigguratTables.exponentialX; final double[] Y = DoubleZigguratTables.exponentialY; - for (;; U1 = (rng.nextLong() >>> 1)) { + // At this point, the high-order bits of U1 have not been used yet, + // but we need the value in U1 to be positive. + for (U1 = (U1 >>> 1);; U1 = (rng.nextLong() >>> 1)) { long U2 = (rng.nextLong() >>> 1); - // Compute the actual x-coordinate of the randomly chosen point. - double x = (X[j] * 0x1.0p63) + ((X[j-1] - X[j]) * (double)U1); // Does the point lie below the curve? long Udiff = U2 - U1; if (Udiff < 0) { @@ -1200,11 +1200,13 @@ public class RandomSupport { U2 = U1; U1 -= Udiff; } + // Compute the actual x-coordinate of the randomly chosen point. + double x = (X[j] * 0x1.0p63) + ((X[j-1] - X[j]) * (double)U1); if (Udiff >= DoubleZigguratTables.exponentialConvexMargin) { return x + extra; // The chosen point is way below the curve; accept it. } // Compute the actual y-coordinate of the randomly chosen point. - double y = (Y[j] * 0x1.0p63) + ((Y[j] - Y[j-1]) * (double)U2); + double y = (Y[j] * 0x1.0p63) + ((Y[j-1] - Y[j]) * (double)U2); // Now see how that y-coordinate compares to the curve if (y <= Math.exp(-x)) { return x + extra; // The chosen point is below the curve; accept it. @@ -1323,7 +1325,7 @@ public class RandomSupport { continue; // The chosen point is way above the curve; reject it. } // Compute the actual y-coordinate of the randomly chosen point. - double y = (Y[j] * 0x1.0p63) + ((Y[j] - Y[j-1]) * (double)U2); + double y = (Y[j] * 0x1.0p63) + ((Y[j-1] - Y[j]) * (double)U2); // Now see how that y-coordinate compares to the curve if (y <= Math.exp(-0.5*x*x)) { break; // The chosen point is below the curve; accept it. @@ -1348,8 +1350,6 @@ public class RandomSupport { } else if (j < DoubleZigguratTables.normalInflectionIndex) { // Convex overhang for (;; U1 = (rng.nextLong() >>> 1)) { long U2 = (rng.nextLong() >>> 1); - // Compute the actual x-coordinate of the randomly chosen point. - x = (X[j] * 0x1.0p63) + ((X[j-1] - X[j]) * (double)U1); // Does the point lie below the curve? long Udiff = U2 - U1; if (Udiff < 0) { @@ -1360,11 +1360,13 @@ public class RandomSupport { U2 = U1; U1 -= Udiff; } + // Compute the actual x-coordinate of the randomly chosen point. + x = (X[j] * 0x1.0p63) + ((X[j-1] - X[j]) * (double)U1); if (Udiff >= DoubleZigguratTables.normalConvexMargin) { break; // The chosen point is way below the curve; accept it. } // Compute the actual y-coordinate of the randomly chosen point. - double y = (Y[j] * 0x1.0p63) + ((Y[j] - Y[j-1]) * (double)U2); + double y = (Y[j] * 0x1.0p63) + ((Y[j-1] - Y[j]) * (double)U2); // Now see how that y-coordinate compares to the curve if (y <= Math.exp(-0.5*x*x)) break; // The chosen point is below the curve; accept it. // Otherwise, we reject this sample and have to try again. @@ -1384,7 +1386,7 @@ public class RandomSupport { continue; // The chosen point is way above the curve; reject it. } // Compute the actual y-coordinate of the randomly chosen point. - double y = (Y[j] * 0x1.0p63) + ((Y[j] - Y[j-1]) * (double)U2); + double y = (Y[j] * 0x1.0p63) + ((Y[j-1] - Y[j]) * (double)U2); // Now see how that y-coordinate compares to the curve if (y <= Math.exp(-0.5*x*x)) { break; // The chosen point is below the curve; accept it. diff --git a/src/java.base/share/classes/jdk/internal/vm/vector/VectorSupport.java b/src/java.base/share/classes/jdk/internal/vm/vector/VectorSupport.java index 63e007657929b255c160724b8a99bc3f8eae98c8..d175e62abbf2d063d72d02fc47f9fd7b51e8e5b7 100644 --- a/src/java.base/share/classes/jdk/internal/vm/vector/VectorSupport.java +++ b/src/java.base/share/classes/jdk/internal/vm/vector/VectorSupport.java @@ -114,6 +114,10 @@ public class VectorSupport { public static final int BT_ult = BT_lt | BT_unsigned_compare; public static final int BT_ugt = BT_gt | BT_unsigned_compare; + // Various broadcasting modes. + public static final int MODE_BROADCAST = 0; + public static final int MODE_BITS_COERCED_LONG_TO_MASK = 1; + // BasicType codes, for primitives only: public static final int T_FLOAT = 6, @@ -157,9 +161,9 @@ public class VectorSupport { } /* ============================================================================ */ - public interface BroadcastOperation> { - VM broadcast(long l, S s); + public interface FromBitsCoercedOperation> { + VM fromBits(long l, S s); } @IntrinsicCandidate @@ -167,12 +171,12 @@ public class VectorSupport { , E> - VM broadcastCoerced(Class vmClass, Class eClass, - int length, - long bits, S s, - BroadcastOperation defaultImpl) { + VM fromBitsCoerced(Class vmClass, Class eClass, + int length, + long bits, int mode, S s, + FromBitsCoercedOperation defaultImpl) { assert isNonCapturingLambda(defaultImpl) : defaultImpl; - return defaultImpl.broadcast(bits, s); + return defaultImpl.fromBits(bits, s); } /* ============================================================================ */ diff --git a/src/java.base/share/classes/sun/launcher/resources/launcher.properties b/src/java.base/share/classes/sun/launcher/resources/launcher.properties index efcc4d69969431a35398d81a083ca035d810bb87..22fe4a35a5e68329fe6f073d72d5313e6cb4b82c 100644 --- a/src/java.base/share/classes/sun/launcher/resources/launcher.properties +++ b/src/java.base/share/classes/sun/launcher/resources/launcher.properties @@ -194,7 +194,10 @@ java.launcher.X.usage=\n\ \ override or augment a module with classes and resources\n\ \ in JAR files or directories.\n\ \ --source \n\ -\ set the version of the source in source-file mode.\n\n\ +\ set the version of the source in source-file mode.\n\ +\ --finalization=\n\ +\ controls finalization\n\ +\ is one of "enabled" or "disabled"\n\n\ These extra options are subject to change without notice.\n # Translators please note do not translate the options themselves diff --git a/src/java.base/share/classes/sun/net/www/MeteredStream.java b/src/java.base/share/classes/sun/net/www/MeteredStream.java index 049b16c03c6b90828ee8fdcb2e87eb17a81e98c8..fc0579a679e107c9325e4b63326e0f8f0db3b912 100644 --- a/src/java.base/share/classes/sun/net/www/MeteredStream.java +++ b/src/java.base/share/classes/sun/net/www/MeteredStream.java @@ -242,7 +242,7 @@ public class MeteredStream extends FilterInputStream { return readLock.isHeldByCurrentThread(); } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { try { close(); diff --git a/src/java.base/share/classes/sun/nio/ch/ChannelInputStream.java b/src/java.base/share/classes/sun/nio/ch/ChannelInputStream.java index 6f312cb9ed2e74bf7506ec2eb78689714b461ad7..4ddd30485af4a992dc5d9f2b91df638110b088f9 100644 --- a/src/java.base/share/classes/sun/nio/ch/ChannelInputStream.java +++ b/src/java.base/share/classes/sun/nio/ch/ChannelInputStream.java @@ -34,6 +34,7 @@ import java.nio.channels.IllegalBlockingModeException; import java.nio.channels.ReadableByteChannel; import java.nio.channels.SeekableByteChannel; import java.nio.channels.SelectableChannel; +import java.nio.channels.WritableByteChannel; import java.util.Arrays; import java.util.Objects; import jdk.internal.util.ArraysSupport; @@ -238,15 +239,28 @@ public class ChannelInputStream Objects.requireNonNull(out, "out"); if (out instanceof ChannelOutputStream cos - && ch instanceof FileChannel fc - && cos.channel() instanceof FileChannel dst) { - return transfer(fc, dst); + && ch instanceof FileChannel fc) { + WritableByteChannel wbc = cos.channel(); + + if (wbc instanceof FileChannel dst) { + return transfer(fc, dst); + } + + if (wbc instanceof SelectableChannel sc) { + synchronized (sc.blockingLock()) { + if (!sc.isBlocking()) + throw new IllegalBlockingModeException(); + return transfer(fc, wbc); + } + } + + return transfer(fc, wbc); } return super.transferTo(out); } - private static long transfer(FileChannel src, FileChannel dst) throws IOException { + private static long transfer(FileChannel src, WritableByteChannel dst) throws IOException { long initialPos = src.position(); long pos = initialPos; try { diff --git a/src/java.base/share/classes/sun/nio/ch/IOUtil.java b/src/java.base/share/classes/sun/nio/ch/IOUtil.java index 900bb4e40883dbde2efbae4b3be0a75502bc9479..bea092befaeff79759a3e3e8fd8fcb669c371f6c 100644 --- a/src/java.base/share/classes/sun/nio/ch/IOUtil.java +++ b/src/java.base/share/classes/sun/nio/ch/IOUtil.java @@ -475,15 +475,15 @@ public class IOUtil { private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess(); - static Scope.Handle acquireScope(ByteBuffer bb, boolean async) { + static Runnable acquireScope(ByteBuffer bb, boolean async) { return NIO_ACCESS.acquireScope(bb, async); } - private static void releaseScope(Scope.Handle handle) { + private static void releaseScope(Runnable handle) { if (handle == null) return; try { - handle.scope().release(handle); + handle.run(); } catch (Exception e) { throw new IllegalStateException(e); } @@ -535,11 +535,11 @@ public class IOUtil { } } - static record Releaser(Scope.Handle handle) implements Runnable { + static record Releaser(Runnable handle) implements Runnable { Releaser { Objects.requireNonNull(handle) ; } @Override public void run() { releaseScope(handle); } - static Runnable of(Scope.Handle handle) { return new Releaser(handle); } - static Runnable ofNullable(Scope.Handle handle) { + static Runnable of(Runnable handle) { return new Releaser(handle); } + static Runnable ofNullable(Runnable handle) { if (handle == null) return () -> { }; return new Releaser(handle); diff --git a/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java b/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java index 477fa1afca2384391734437f2d1d326a3c66ddf5..117c14d5711e55c45eaed7593587d75249367e7e 100644 --- a/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java @@ -700,11 +700,11 @@ class SocketChannelImpl private SocketAddress unixBind(SocketAddress local) throws IOException { UnixDomainSockets.checkPermission(); if (local == null) { - return UnixDomainSockets.UNNAMED; + return UnixDomainSockets.unnamed(); } else { Path path = UnixDomainSockets.checkAddress(local).getPath(); if (path.toString().isEmpty()) { - return UnixDomainSockets.UNNAMED; + return UnixDomainSockets.unnamed(); } else { // bind to non-empty path UnixDomainSockets.bind(fd, path); diff --git a/src/java.base/share/classes/sun/nio/ch/UnixDomainSockets.java b/src/java.base/share/classes/sun/nio/ch/UnixDomainSockets.java index ee7e1d9d51ab92801a89f9c64588c3908eccf752..251e79c6ecc694ad45f1a27865230486d38c42bf 100644 --- a/src/java.base/share/classes/sun/nio/ch/UnixDomainSockets.java +++ b/src/java.base/share/classes/sun/nio/ch/UnixDomainSockets.java @@ -44,7 +44,9 @@ import sun.nio.fs.AbstractFileSystemProvider; class UnixDomainSockets { private UnixDomainSockets() { } - static final UnixDomainSocketAddress UNNAMED = UnixDomainSocketAddress.of(""); + private static class UnnamedHolder { + static final UnixDomainSocketAddress UNNAMED = UnixDomainSocketAddress.of(""); + } private static final boolean supported; @@ -71,7 +73,7 @@ class UnixDomainSockets { // Security check passed } catch (SecurityException e) { // Return unnamed address only if security check fails - addr = UNNAMED; + addr = unnamed(); } return addr; } @@ -133,7 +135,11 @@ class UnixDomainSockets { throw new BindException("Could not locate temporary directory for sockets"); int rnd = random.nextInt(Integer.MAX_VALUE); try { - Path path = Path.of(dir, "socket_" + rnd); + final Path path = Path.of(dir, "socket_" + rnd); + if (path.getFileSystem().provider() != sun.nio.fs.DefaultFileSystemProvider.instance()) { + throw new UnsupportedOperationException( + "Unix Domain Sockets not supported on non-default file system"); + } return UnixDomainSocketAddress.of(path); } catch (InvalidPathException e) { throw new BindException("Invalid temporary directory"); @@ -160,6 +166,10 @@ class UnixDomainSockets { return n; } + static UnixDomainSocketAddress unnamed() { + return UnnamedHolder.UNNAMED; + } + private static native boolean init(); private static native int socket0() throws IOException; diff --git a/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java b/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java index db79e2fcb639ab05fd0aafde1e14e58ee64929c7..2967f0593f691812697fa9f97075098592bed56e 100644 --- a/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java +++ b/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java @@ -1259,14 +1259,20 @@ public final class PKCS12KeyStore extends KeyStoreSpi { " certificate(s) in a PKCS#7 encryptedData"); } - byte[] encrData = createEncryptedData(password); - if (!certProtectionAlgorithm.equalsIgnoreCase("NONE")) { + byte[] certsData = getCertificateData(); + if (password != null && !certProtectionAlgorithm.equalsIgnoreCase("NONE")) { + // -- SEQUENCE of EncryptedData + DerOutputStream encrData = new DerOutputStream(); + encrData.putInteger(0); + encrData.write(encryptContent(certsData, password)); + DerOutputStream encrDataContent = new DerOutputStream(); + encrDataContent.write(DerValue.tag_Sequence, encrData); ContentInfo encrContentInfo = new ContentInfo(ContentInfo.ENCRYPTED_DATA_OID, - new DerValue(encrData)); + new DerValue(encrDataContent.toByteArray())); encrContentInfo.encode(authSafeContentInfo); } else { - ContentInfo dataContentInfo = new ContentInfo(encrData); + ContentInfo dataContentInfo = new ContentInfo(certsData); dataContentInfo.encode(authSafeContentInfo); } } @@ -1289,7 +1295,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi { if (macIterationCount < 0) { macIterationCount = defaultMacIterationCount(); } - if (!macAlgorithm.equalsIgnoreCase("NONE")) { + if (password != null && !macAlgorithm.equalsIgnoreCase("NONE")) { byte[] macData = calculateMac(password, authenticatedSafe); pfx.write(macData); } @@ -1301,6 +1307,15 @@ public final class PKCS12KeyStore extends KeyStoreSpi { stream.flush(); } + @Override + public Set engineGetAttributes(String alias) { + if (!engineContainsAlias(alias)) { + return super.engineGetAttributes(alias); + } + Entry entry = entries.get(alias.toLowerCase(Locale.ENGLISH)); + return Collections.unmodifiableSet(new HashSet<>(getAttributes(entry))); + } + /** * Gets a KeyStore.Entry for the specified alias * with the specified protection parameter. @@ -1704,12 +1719,11 @@ public final class PKCS12KeyStore extends KeyStoreSpi { } /* - * Create EncryptedData content type, that contains EncryptedContentInfo. - * Includes certificates in individual SafeBags of type CertBag. - * Each CertBag may include pkcs12 attributes + * Create Data content type, includes certificates in individual + * SafeBags of type CertBag. Each CertBag may include pkcs12 attributes * (see comments in getBagAttributes) */ - private byte[] createEncryptedData(char[] password) + private byte[] getCertificateData() throws CertificateException, IOException { DerOutputStream out = new DerOutputStream(); @@ -1803,22 +1817,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi { // wrap as SequenceOf SafeBag DerOutputStream safeBagValue = new DerOutputStream(); safeBagValue.write(DerValue.tag_SequenceOf, out); - byte[] safeBagData = safeBagValue.toByteArray(); - - // encrypt the content (EncryptedContentInfo) - if (!certProtectionAlgorithm.equalsIgnoreCase("NONE")) { - byte[] encrContentInfo = encryptContent(safeBagData, password); - - // -- SEQUENCE of EncryptedData - DerOutputStream encrData = new DerOutputStream(); - DerOutputStream encrDataContent = new DerOutputStream(); - encrData.putInteger(0); - encrData.write(encrContentInfo); - encrDataContent.write(DerValue.tag_Sequence, encrData); - return encrDataContent.toByteArray(); - } else { - return safeBagData; - } + return safeBagValue.toByteArray(); } /* diff --git a/src/java.base/share/classes/sun/security/provider/DomainKeyStore.java b/src/java.base/share/classes/sun/security/provider/DomainKeyStore.java index a6ace711faa05c1cbeafb21c9b8aa6904abc9d93..be0e91a55a3d053dfb323d8ae5b510cec23bcbc0 100644 --- a/src/java.base/share/classes/sun/security/provider/DomainKeyStore.java +++ b/src/java.base/share/classes/sun/security/provider/DomainKeyStore.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -236,6 +236,28 @@ abstract class DomainKeyStore extends KeyStoreSpi { return date; } + @Override + public Set engineGetAttributes(String alias) { + + AbstractMap.SimpleEntry> pair = + getKeystoresForReading(alias); + Set result = Collections.emptySet(); + + try { + String entryAlias = pair.getKey(); + for (KeyStore keystore : pair.getValue()) { + result = keystore.getAttributes(entryAlias); + if (result != null) { + break; + } + } + } catch (KeyStoreException e) { + throw new IllegalStateException(e); + } + + return result; + } + /** * Assigns the given private key to the given alias, protecting * it with the given password as defined in PKCS8. diff --git a/src/java.base/share/classes/sun/security/ssl/BaseSSLSocketImpl.java b/src/java.base/share/classes/sun/security/ssl/BaseSSLSocketImpl.java index ba58741d759279b642c044745d36baafe29a1dd9..8923dee25c98a01a6c6a17d6bc8224f69a3b6169 100644 --- a/src/java.base/share/classes/sun/security/ssl/BaseSSLSocketImpl.java +++ b/src/java.base/share/classes/sun/security/ssl/BaseSSLSocketImpl.java @@ -270,7 +270,7 @@ abstract class BaseSSLSocketImpl extends SSLSocket { * the penalty of prematurly killing SSL sessions. */ @Override - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected final void finalize() throws Throwable { try { close(); diff --git a/src/java.base/share/classes/sun/security/util/KeyStoreDelegator.java b/src/java.base/share/classes/sun/security/util/KeyStoreDelegator.java index d3e3de0d9919d719d6d7f600415c7190cbb6baff..27cde4b205381c9ccc044bff6669bed4b3306238 100644 --- a/src/java.base/share/classes/sun/security/util/KeyStoreDelegator.java +++ b/src/java.base/share/classes/sun/security/util/KeyStoreDelegator.java @@ -129,6 +129,11 @@ public class KeyStoreDelegator extends KeyStoreSpi { keystore.engineDeleteEntry(alias); } + @Override + public Set engineGetAttributes(String alias) { + return keystore.engineGetAttributes(alias); + } + @Override public Enumeration engineAliases() { return keystore.engineAliases(); diff --git a/src/java.base/share/classes/sun/util/cldr/CLDRTimeZoneNameProviderImpl.java b/src/java.base/share/classes/sun/util/cldr/CLDRTimeZoneNameProviderImpl.java index 6d78d77f64d1d5669727318a92b05a5cfb70c57f..d03e753a0a4e8b1576d41c5328ff3061231cb82b 100644 --- a/src/java.base/share/classes/sun/util/cldr/CLDRTimeZoneNameProviderImpl.java +++ b/src/java.base/share/classes/sun/util/cldr/CLDRTimeZoneNameProviderImpl.java @@ -82,7 +82,7 @@ public class CLDRTimeZoneNameProviderImpl extends TimeZoneNameProviderImpl { } if (namesSuper != null) { - // CLDR's resource bundle has an translated entry for this id. + // CLDR's resource bundle has a translated entry for this id. // Fix up names if needed, either missing or no-inheritance namesSuper[INDEX_TZID] = id; @@ -91,7 +91,7 @@ public class CLDRTimeZoneNameProviderImpl extends TimeZoneNameProviderImpl { case "": // Fill in empty elements deriveFallbackName(namesSuper, i, locale, - !TimeZone.getTimeZone(id).useDaylightTime()); + TimeZone.getTimeZone(id).toZoneId().getRules().isFixedOffset()); break; case NO_INHERITANCE_MARKER: // CLDR's "no inheritance marker" @@ -129,7 +129,7 @@ public class CLDRTimeZoneNameProviderImpl extends TimeZoneNameProviderImpl { // Derive fallback time zone name according to LDML's logic private void deriveFallbackNames(String[] names, Locale locale) { - boolean noDST = !TimeZone.getTimeZone(names[0]).useDaylightTime(); + boolean noDST = TimeZone.getTimeZone(names[0]).toZoneId().getRules().isFixedOffset(); for (int i = INDEX_STD_LONG; i <= INDEX_GEN_SHORT; i++) { deriveFallbackName(names, i, locale, noDST); @@ -149,13 +149,12 @@ public class CLDRTimeZoneNameProviderImpl extends TimeZoneNameProviderImpl { return; } - // Check parent locale first + // Check parent locales first if (!exists(names, index)) { CLDRLocaleProviderAdapter clpa = (CLDRLocaleProviderAdapter)LocaleProviderAdapter.forType(Type.CLDR); var cands = clpa.getCandidateLocales("", locale); - if (cands.size() > 1) { - var parentLoc = cands.get(1); // immediate parent locale - String[] parentNames = super.getDisplayNameArray(id, parentLoc); + for (int i = 1; i < cands.size() ; i++) { + String[] parentNames = super.getDisplayNameArray(id, cands.get(i)); if (parentNames != null && !parentNames[index].isEmpty()) { names[index] = parentNames[index]; return; @@ -163,22 +162,6 @@ public class CLDRTimeZoneNameProviderImpl extends TimeZoneNameProviderImpl { } } - // Check if COMPAT can substitute the name - if (LocaleProviderAdapter.getAdapterPreference().contains(Type.JRE)) { - String[] compatNames = (String[])LocaleProviderAdapter.forJRE() - .getLocaleResources(mapChineseLocale(locale)) - .getTimeZoneNames(id); - if (compatNames != null) { - for (int i = INDEX_STD_LONG; i <= INDEX_GEN_SHORT; i++) { - // Assumes COMPAT has no empty slots - if (i == index || !exists(names, i)) { - names[i] = compatNames[i]; - } - } - return; - } - } - // Region Fallback if (regionFormatFallback(names, index, locale)) { return; @@ -189,6 +172,19 @@ public class CLDRTimeZoneNameProviderImpl extends TimeZoneNameProviderImpl { return; } + // Check if COMPAT can substitute the name + if (!exists(names, index) && + LocaleProviderAdapter.getAdapterPreference().contains(Type.JRE)) { + String[] compatNames = (String[])LocaleProviderAdapter.forJRE() + .getLocaleResources(mapChineseLocale(locale)) + .getTimeZoneNames(id); + if (compatNames != null) { + // Assumes COMPAT has no empty slots + names[index] = compatNames[index]; + return; + } + } + // last resort names[index] = toGMTFormat(id, index == INDEX_DST_LONG || index == INDEX_DST_SHORT, diff --git a/src/java.base/share/conf/security/java.security b/src/java.base/share/conf/security/java.security index 63be286686d035e4fee83fcb5f43f2fe08da7d05..91b3a01ee577f574ebbe060ee08042c289eca43b 100644 --- a/src/java.base/share/conf/security/java.security +++ b/src/java.base/share/conf/security/java.security @@ -1365,3 +1365,29 @@ jdk.tls.alpnCharset=ISO_8859_1 # The default pattern value allows any object factory class specified by the reference # instance to recreate the referenced object. #jdk.jndi.object.factoriesFilter=* + +# +# Policy for non-forwardable service ticket in a S4U2proxy request +# +# The Service for User to Proxy (S4U2proxy) Kerberos extension enables a middle service +# to obtain a service ticket to another service on behalf of a user. It requires that +# the user's service ticket to the first service has the forwardable flag set [1]. +# However, some KDC implementations ignore this requirement and accept service tickets +# with the flag unset. +# +# If this security property is set to "true", then +# +# 1) The user service ticket, when obtained by the middle service after a S4U2self +# impersonation, is not required to have the forwardable flag set; and, +# +# 2) If a S4U2proxy request receives a KRB_ERROR of the KDC_ERR_BADOPTION error code +# and the ticket to the middle service is not forwardable, OpenJDK will try the same +# request with another KDC instead of treating it as a fatal failure. +# +# The default value is "false". +# +# If a system property of the same name is also specified, it supersedes the +# security property value defined here. +# +# [1] https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-sfu/bde93b0e-f3c9-4ddf-9f44-e1453be7af5a +#jdk.security.krb5.s4u2proxy.acceptNonForwardableServiceTicket=false diff --git a/src/java.base/share/man/java.1 b/src/java.base/share/man/java.1 index b9ce956462c2b72d543b2587effbdcfe9d1a1e00..aabcce30ade9e6df8898146d04f044a535d6537c 100644 --- a/src/java.base/share/man/java.1 +++ b/src/java.base/share/man/java.1 @@ -22,7 +22,7 @@ .\"t .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JAVA" "1" "2021" "JDK 18\-ea" "JDK Commands" +.TH "JAVA" "1" "2022" "JDK 19\-ea" "JDK Commands" .hy .SH NAME .PP @@ -181,7 +181,7 @@ with new values added and old values removed. You\[aq]ll get an error message if you use a value of \f[I]N\f[R] that is no longer supported. The supported values of \f[I]N\f[R] are the current Java SE release -(\f[CB]18\f[R]) and a limited number of previous releases, detailed in the +(\f[CB]19\f[R]) and a limited number of previous releases, detailed in the command\-line help for \f[CB]javac\f[R], under the \f[CB]\-\-source\f[R] and \f[CB]\-\-release\f[R] options. .RE @@ -935,11 +935,11 @@ size of the heap for the young generation, you can use .RE .TP .B \f[CB]\-Xms\f[R] \f[I]size\f[R] -Sets the minimum and initial size (in bytes) of the heap. +Sets the minimum and the initial size (in bytes) of the heap. This value must be a multiple of 1024 and greater than 1 MB. Append the letter \f[CB]k\f[R] or \f[CB]K\f[R] to indicate kilobytes, -\f[CB]m\f[R] or \f[CB]M\f[R] to indicate megabytes, \f[CB]g\f[R] or \f[CB]G\f[R] -to indicate gigabytes. +\f[CB]m\f[R] or \f[CB]M\f[R] to indicate megabytes, or \f[CB]g\f[R] or +\f[CB]G\f[R] to indicate gigabytes. The following examples show how to set the size of allocated memory to 6 MB using various units: .RS @@ -952,14 +952,17 @@ MB using various units: \f[R] .fi .PP -Instead of the \f[CB]\-Xms\f[R] option to set both the minimum and initial -size of the heap, you can use \f[CB]\-XX:MinHeapSize\f[R] to set the -minimum size and \f[CB]\-XX:InitialHeapSize\f[R] to set the initial size. -.PP -If you don\[aq]t set this option, the initial size is set as the sum of -the sizes allocated for the old generation and the young generation. +If you do not set this option, then the initial size will be set as the +sum of the sizes allocated for the old generation and the young +generation. The initial size of the heap for the young generation can be set using the \f[CB]\-Xmn\f[R] option or the \f[CB]\-XX:NewSize\f[R] option. +.PP +Note that the \f[CB]\-XX:InitialHeapSize\f[R] option can also be used to +set the initial heap size. +If it appears after \f[CB]\-Xms\f[R] on the command line, then the initial +heap size gets set to the value specified with +\f[CB]\-XX:InitialHeapSize\f[R]. .RE .TP .B \f[CB]\-Xmx\f[R] \f[I]size\f[R] @@ -1366,7 +1369,7 @@ By default this option is disabled. .RS .RE .TP -.B \f[CB]\-XX:FlightRecorderOptions=\f[R]\f[I]parameter\f[R]\f[CB]=\f[R]\f[I]value\f[R] (or)\f[CB]\-XX:FlightRecorderOptions:\f[R]\f[I]parameter\f[R]\f[CB]=\f[R]\f[I]value\f[R] +.B \f[CB]\-XX:FlightRecorderOptions=\f[R]\f[I]parameter\f[R]\f[CB]=\f[R]\f[I]value\f[R] (or) \f[CB]\-XX:FlightRecorderOptions:\f[R]\f[I]parameter\f[R]\f[CB]=\f[R]\f[I]value\f[R] Sets the parameters that control the behavior of JFR. .RS .PP @@ -1640,7 +1643,7 @@ Specifies the path and name of the class data sharing (CDS) archive file See \f[B]Application Class Data Sharing\f[R]. .RE .TP -.B \f[CB]\-XX:SharedArchiveConfigFile\f[R]=\f[I]shared_config_file\f[R] +.B \f[CB]\-XX:SharedArchiveConfigFile=\f[R]\f[I]shared_config_file\f[R] Specifies additional shared data added to the archive file. .RS .RE @@ -1747,9 +1750,6 @@ written when the recording is stopped, for example: \f[CB]/home/user/recordings/recording.jfr\f[R] .IP \[bu] 2 \f[CB]c:\\recordings\\recording.jfr\f[R] -.PP -If \f[CB]%p\f[R] and/or \f[CB]%t\f[R] is specified in the filename, it expands to the JVM\[aq]s -PID and the current timestamp, respectively. .RE .TP .B \f[CB]name=\f[R]\f[I]identifier\f[R] @@ -1825,10 +1825,10 @@ To list available options, use the \f[CB]JAVA_HOME\f[R]/bin/jfr tool. .RS .RE .TP -.B \f[CB]event\-setting\f[R]=\f[I]value\f[R] +.B \f[CB]event\-setting=\f[R]\f[I]value\f[R] Specifies the event setting value to modify. -Use the form: #= To add a new event setting, prefix the event name with -\[aq]+\[aq]. +Use the form: \f[CB]#=\f[R]. +To add a new event setting, prefix the event name with \[aq]+\[aq]. .RS .RE .PP @@ -2591,23 +2591,19 @@ The \f[CB]\-XX:UseRTMLocking\f[R] option must be enabled. .RE .TP .B \f[CB]\-XX:+SegmentedCodeCache\f[R] -Enables segmentation of the code cache. -Without the \f[CB]\-XX:+SegmentedCodeCache\f[R], the code cache consists -of one large segment. -With \f[CB]\-XX:+SegmentedCodeCache\f[R], we have separate segments for -nonmethod, profiled method, and nonprofiled method code. -These segments aren\[aq]t resized at runtime. -The feature is enabled by default if tiered compilation is enabled -(\f[CB]\-XX:+TieredCompilation\f[R] ) and -\f[CB]\-XX:ReservedCodeCacheSize\f[R] >= 240 MB. +Enables segmentation of the code cache, without which the code cache +consists of one large segment. +With \f[CB]\-XX:+SegmentedCodeCache\f[R], separate segments will be used +for non\-method, profiled method, and non\-profiled method code. +The segments are not resized at runtime. The advantages are better control of the memory footprint, reduced code -fragmentation, and better iTLB/iCache behavior due to improved locality. -iTLB/iCache is a CPU\-specific term meaning Instruction Translation -Lookaside Buffer (ITLB). -ICache is an instruction cache in theCPU. -The implementation of the code cache can be found in the file: -\f[CB]/share/vm/code/codeCache.cpp\f[R]. +fragmentation, and better CPU iTLB (instruction translation lookaside +buffer) and instruction cache behavior due to improved locality. .RS +.PP +The feature is enabled by default if tiered compilation is enabled +(\f[CB]\-XX:+TieredCompilation\f[R] ) and the reserved code cache size +(\f[CB]\-XX:ReservedCodeCacheSize\f[R]) is at least 240 MB. .RE .TP .B \f[CB]\-XX:StartAggressiveSweepingAt=\f[R]\f[I]percent\f[R] @@ -2639,7 +2635,8 @@ Is set by default to the highest supported version available (x86 only). Enables hardware\-based AES intrinsics for hardware that supports it. This option is on by default on hardware that has the necessary instructions. -The \f[CB]\-XX:+UseAES\f[R] is used in conjunction with UseAESIntrinsics. +The \f[CB]\-XX:+UseAES\f[R] is used in conjunction with +\f[CB]UseAESIntrinsics\f[R]. Flags that control intrinsics now require the option \f[CB]\-XX:+UnlockDiagnosticVMOptions\f[R]. .RS @@ -2647,8 +2644,8 @@ Flags that control intrinsics now require the option .TP .B \f[CB]\-XX:+UseAESIntrinsics\f[R] Enables AES intrinsics. -Specifying\f[CB]\-XX:+UseAESIntrinsics\f[R] is equivalent to also enabling -\f[CB]\-XX:+UseAES\f[R]. +Specifying \f[CB]\-XX:+UseAESIntrinsics\f[R] is equivalent to also +enabling \f[CB]\-XX:+UseAES\f[R]. To disable hardware\-based AES intrinsics, specify \f[CB]\-XX:\-UseAES\ \-XX:\-UseAESIntrinsics\f[R]. For example, to enable hardware AES, use the following flags: @@ -2844,7 +2841,7 @@ The default value is 1,000. .RS .RE .TP -.B \f[CB]\-XX:LoopStripMiningIterShortLoop\f[R]=\f[I]number_of_iterations\f[R] +.B \f[CB]\-XX:LoopStripMiningIterShortLoop=\f[R]\f[I]number_of_iterations\f[R] Controls loop strip mining optimization. Loops with the number of iterations less than specified will not have safepoints in them. @@ -2971,7 +2968,7 @@ an \f[CB]OutOfMemoryError\f[R] exception is thrown. .RS .RE .TP -.B \f[CB]\-XX:HeapDumpPath=path\f[R] +.B \f[CB]\-XX:HeapDumpPath=\f[R]\f[I]path\f[R] Sets the path and file name for writing the heap dump provided by the heap profiler (HPROF) when the \f[CB]\-XX:+HeapDumpOnOutOfMemoryError\f[R] option is set. @@ -3165,7 +3162,7 @@ The default value is 3. .RS .RE .TP -.B \f[CB]\-XX:G1HeapRegionSize=size\f[R] +.B \f[CB]\-XX:G1HeapRegionSize=\f[R]\f[I]size\f[R] Sets the size of the regions into which the Java heap is subdivided when using the garbage\-first (G1) collector. The value is a power of 2 and can range from 1 MB to 32 MB. @@ -3294,6 +3291,11 @@ If you set this option to 0, then the initial size is set as the sum of the sizes allocated for the old generation and the young generation. The size of the heap for the young generation can be set using the \f[CB]\-XX:NewSize\f[R] option. +Note that the \f[CB]\-Xms\f[R] option sets both the minimum and the +initial heap size of the heap. +If \f[CB]\-Xms\f[R] appears after \f[CB]\-XX:InitialHeapSize\f[R] on the +command line, then the initial heap size gets set to the value specified +with \f[CB]\-Xms\f[R]. .RE .TP .B \f[CB]\-XX:InitialRAMPercentage=\f[R]\f[I]percent\f[R] @@ -3895,7 +3897,7 @@ Supports heap sizes from 8MB to 16TB. .RS .RE .TP -.B \f[CB]\-XX:ZAllocationSpikeTolerance\f[R]=\f[I]factor\f[R] +.B \f[CB]\-XX:ZAllocationSpikeTolerance=\f[R]\f[I]factor\f[R] Sets the allocation spike tolerance for ZGC. By default, this option is set to 2.0. This factor describes the level of allocation spikes to expect. @@ -3904,14 +3906,14 @@ be expected to triple at any time. .RS .RE .TP -.B \f[CB]\-XX:ZCollectionInterval\f[R]=\f[I]seconds\f[R] +.B \f[CB]\-XX:ZCollectionInterval=\f[R]\f[I]seconds\f[R] Sets the maximum interval (in seconds) between two GC cycles when using ZGC. By default, this option is set to 0 (disabled). .RS .RE .TP -.B \f[CB]\-XX:ZFragmentationLimit\f[R]=\f[I]percent\f[R] +.B \f[CB]\-XX:ZFragmentationLimit=\f[R]\f[I]percent\f[R] Sets the maximum acceptable heap fragmentation (in percent) for ZGC. By default, this option is set to 25. Using a lower value will cause the heap to be compacted more @@ -3939,7 +3941,7 @@ JVM, and make that memory available for other processes to use. .RS .RE .TP -.B \f[CB]\-XX:ZUncommitDelay\f[R]=\f[I]seconds\f[R] +.B \f[CB]\-XX:ZUncommitDelay=\f[R]\f[I]seconds\f[R] Sets the amount of time (in seconds) that heap memory must have been unused before being uncommitted. By default, this option is set to 300 (5 minutes). @@ -4231,7 +4233,7 @@ In the argument file, .nf \f[CB] \-cp\ "/lib/cool\\ -\\app/jars??? +\\app/jars" \f[R] .fi .PP diff --git a/src/java.base/share/man/keytool.1 b/src/java.base/share/man/keytool.1 index c5777f2db8b86206d91417cf457fd6caddc09831..09f8057a06605d4ca12b584bf9e612953f99d2d4 100644 --- a/src/java.base/share/man/keytool.1 +++ b/src/java.base/share/man/keytool.1 @@ -22,7 +22,7 @@ .\"t .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "KEYTOOL" "1" "2021" "JDK 18\-ea" "JDK Commands" +.TH "KEYTOOL" "1" "2022" "JDK 19\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/java.base/share/native/libjava/Finalizer.c b/src/java.base/share/native/libjava/Finalizer.c index d0b81f63d6e7f03290e2c680cef0ea7d5e8d73c2..063e330ac9b911670f5c3a2f0b2314685e7008e3 100644 --- a/src/java.base/share/native/libjava/Finalizer.c +++ b/src/java.base/share/native/libjava/Finalizer.c @@ -32,4 +32,7 @@ Java_java_lang_ref_Finalizer_reportComplete(JNIEnv* env, jclass cls, jobject fin JVM_ReportFinalizationComplete(env, finalizee); } - +JNIEXPORT jboolean JNICALL +Java_java_lang_ref_Finalizer_isFinalizationEnabled(JNIEnv* env, jclass cls) { + return JVM_IsFinalizationEnabled(env); +} diff --git a/src/java.base/windows/classes/sun/nio/fs/WindowsPath.java b/src/java.base/windows/classes/sun/nio/fs/WindowsPath.java index 8500646a96fae1b239da4b16a811328bfbd8a1ac..ac41eaefc6926766f15734b6dc92aaa43e79520c 100644 --- a/src/java.base/windows/classes/sun/nio/fs/WindowsPath.java +++ b/src/java.base/windows/classes/sun/nio/fs/WindowsPath.java @@ -174,38 +174,48 @@ class WindowsPath implements Path { // use this path for Win32 calls // This method will prefix long paths with \\?\ or \\?\UNC as required. String getPathForWin32Calls() throws WindowsException { - // short absolute paths can be used directly - if (isAbsolute() && path.length() <= MAX_PATH) - return path; + return getPathForWin32Calls(true); + } + + String getPathWithPrefixForWin32Calls() throws WindowsException { + return getPathForWin32Calls(false); + } - // return cached values if available - WeakReference ref = pathForWin32Calls; - String resolved = (ref != null) ? ref.get() : null; - if (resolved != null) { - // Win32 path already available - return resolved; + private String getPathForWin32Calls(boolean allowShortPath) throws WindowsException { + if (allowShortPath) { + // short absolute paths can be used directly + if (isAbsolute() && path.length() <= MAX_PATH) + return path; + + // returned cached value if possible + WeakReference ref = pathForWin32Calls; + String cached = (ref != null) ? ref.get() : null; + if (cached != null) { + // Win32 path already available + return cached; + } } // resolve against default directory - resolved = getAbsolutePath(); + String resolved = getAbsolutePath(); // Long paths need to have "." and ".." removed and be prefixed with // "\\?\". Note that it is okay to remove ".." even when it follows // a link - for example, it is okay for foo/link/../bar to be changed // to foo/bar. The reason is that Win32 APIs to access foo/link/../bar // will access foo/bar anyway (which differs to Unix systems) - if (resolved.length() > MAX_PATH) { + if (resolved.length() > MAX_PATH || !allowShortPath) { if (resolved.length() > MAX_LONG_PATH) { throw new WindowsException("Cannot access file with path exceeding " + MAX_LONG_PATH + " characters"); } - resolved = addPrefixIfNeeded(GetFullPathName(resolved)); + resolved = addPrefix(GetFullPathName(resolved)); } // cache the resolved path (except drive relative paths as the working // directory on removal media devices can change during the lifetime // of the VM) - if (type != WindowsPathType.DRIVE_RELATIVE) { + if (allowShortPath && type != WindowsPathType.DRIVE_RELATIVE) { synchronized (this) { pathForWin32Calls = new WeakReference(resolved); } @@ -279,14 +289,20 @@ class WindowsPath implements Path { Character.toUpperCase(root2.charAt(0)); } + // Add long path prefix to path + static String addPrefix(String path) { + if (path.startsWith("\\\\")) { + path = "\\\\?\\UNC" + path.substring(1, path.length()); + } else { + path = "\\\\?\\" + path; + } + return path; + } + // Add long path prefix to path if required static String addPrefixIfNeeded(String path) { if (path.length() > MAX_PATH) { - if (path.startsWith("\\\\")) { - path = "\\\\?\\UNC" + path.substring(1, path.length()); - } else { - path = "\\\\?\\" + path; - } + return addPrefix(path); } return path; } diff --git a/src/java.base/windows/classes/sun/nio/fs/WindowsUserDefinedFileAttributeView.java b/src/java.base/windows/classes/sun/nio/fs/WindowsUserDefinedFileAttributeView.java index 2fba50a383253aca8194a8324d2900164715d569..a96596af3cd7156fec1dd336b39b1b29cf91c007 100644 --- a/src/java.base/windows/classes/sun/nio/fs/WindowsUserDefinedFileAttributeView.java +++ b/src/java.base/windows/classes/sun/nio/fs/WindowsUserDefinedFileAttributeView.java @@ -61,9 +61,7 @@ class WindowsUserDefinedFileAttributeView throw new IllegalArgumentException("'name' has a root component"); if (namePath.getParent() != null) throw new IllegalArgumentException("'name' has more than one element"); - String path = join(file.getPathForWin32Calls(), name); - WindowsPath wp = WindowsPath.createFromNormalizedPath(wfs, path); - return wp.getPathForWin32Calls(); + return join(file.getPathWithPrefixForWin32Calls(), name); } private final WindowsPath file; diff --git a/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java b/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java index 0f315a3fe17b43bbfdbf6d8c2a364344d76d190a..7d29f9011bf0b392414268ba1211e022079d4a4a 100644 --- a/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java +++ b/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java @@ -252,7 +252,15 @@ public enum SourceVersion { * * @since 18 */ - RELEASE_18; + RELEASE_18, + + /** + * The version recognized by the Java Platform, Standard Edition + * 19. + * + * @since 19 + */ + RELEASE_19; // Note that when adding constants for newer releases, the // behavior of latest() and latestSupported() must be updated too. @@ -261,7 +269,7 @@ public enum SourceVersion { * {@return the latest source version that can be modeled} */ public static SourceVersion latest() { - return RELEASE_18; + return RELEASE_19; } private static final SourceVersion latestSupported = getLatestSupported(); @@ -276,7 +284,7 @@ public enum SourceVersion { private static SourceVersion getLatestSupported() { int intVersion = Runtime.version().feature(); return (intVersion >= 11) ? - valueOf("RELEASE_" + Math.min(18, intVersion)): + valueOf("RELEASE_" + Math.min(19, intVersion)): RELEASE_10; } diff --git a/src/java.compiler/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor14.java b/src/java.compiler/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor14.java index fa49170a7c621313a9b22d0b29ec652520a6cb97..004aa596b3a8004d5391961d95e7fd7db58565d0 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor14.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor14.java @@ -44,7 +44,7 @@ import javax.annotation.processing.SupportedSourceVersion; * @see AbstractAnnotationValueVisitor9 * @since 14 */ -@SupportedSourceVersion(RELEASE_18) +@SupportedSourceVersion(RELEASE_19) public abstract class AbstractAnnotationValueVisitor14 extends AbstractAnnotationValueVisitor9 { /** diff --git a/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor14.java b/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor14.java index 7c69778c89e765266205a02d0ee9c633eaf28b3f..8200e6c00deec0f3b93e5dd236f6686460ef3417 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor14.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor14.java @@ -49,7 +49,7 @@ import static javax.lang.model.SourceVersion.*; * @see AbstractElementVisitor9 * @since 16 */ -@SupportedSourceVersion(RELEASE_18) +@SupportedSourceVersion(RELEASE_19) public abstract class AbstractElementVisitor14 extends AbstractElementVisitor9 { /** * Constructor for concrete subclasses to call. diff --git a/src/java.compiler/share/classes/javax/lang/model/util/AbstractTypeVisitor14.java b/src/java.compiler/share/classes/javax/lang/model/util/AbstractTypeVisitor14.java index 9df8eef86f29525f2d1c5f34ce88d3bb23eba20e..a2a9d098e6b3806d27aef1819c44ab7fb9f6ca41 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/AbstractTypeVisitor14.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/AbstractTypeVisitor14.java @@ -47,7 +47,7 @@ import static javax.lang.model.SourceVersion.*; * @see AbstractTypeVisitor9 * @since 14 */ -@SupportedSourceVersion(RELEASE_18) +@SupportedSourceVersion(RELEASE_19) public abstract class AbstractTypeVisitor14 extends AbstractTypeVisitor9 { /** * Constructor for concrete subclasses to call. diff --git a/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor14.java b/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor14.java index ab71cdb9c9d9de29c77f080d7336a716ba555e72..93b035e17721cde0dab6d5a30082f9d8edd7a970 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor14.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor14.java @@ -61,7 +61,7 @@ import javax.lang.model.SourceVersion; * @see ElementKindVisitor9 * @since 16 */ -@SupportedSourceVersion(RELEASE_18) +@SupportedSourceVersion(RELEASE_19) public class ElementKindVisitor14 extends ElementKindVisitor9 { /** * Constructor for concrete subclasses; uses {@code null} for the diff --git a/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner14.java b/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner14.java index cdc86c1f63be64e32f5999453f139c7a4d4fccf6..ac1bc4976cac1ffdff4f543d04c1c18769c2d399 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner14.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner14.java @@ -76,7 +76,7 @@ import static javax.lang.model.SourceVersion.*; * @see ElementScanner9 * @since 16 */ -@SupportedSourceVersion(RELEASE_18) +@SupportedSourceVersion(RELEASE_19) public class ElementScanner14 extends ElementScanner9 { /** * Constructor for concrete subclasses; uses {@code null} for the diff --git a/src/java.compiler/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor14.java b/src/java.compiler/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor14.java index b9015109bb86ecc31c9bdc6e20c28081e1f467b4..9174602cde0f3299b222d87613caf7394503755b 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor14.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor14.java @@ -52,7 +52,7 @@ import static javax.lang.model.SourceVersion.*; * @see SimpleAnnotationValueVisitor9 * @since 14 */ -@SupportedSourceVersion(RELEASE_18) +@SupportedSourceVersion(RELEASE_19) public class SimpleAnnotationValueVisitor14 extends SimpleAnnotationValueVisitor9 { /** * Constructor for concrete subclasses; uses {@code null} for the diff --git a/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor14.java b/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor14.java index b90c2c97c96eb7d034c39f1f06b525a107f39a15..8e992025e4a8abe318b694c93b34986e6e16a5aa 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor14.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor14.java @@ -57,7 +57,7 @@ import static javax.lang.model.SourceVersion.*; * @see SimpleElementVisitor9 * @since 16 */ -@SupportedSourceVersion(RELEASE_18) +@SupportedSourceVersion(RELEASE_19) public class SimpleElementVisitor14 extends SimpleElementVisitor9 { /** * Constructor for concrete subclasses; uses {@code null} for the diff --git a/src/java.compiler/share/classes/javax/lang/model/util/SimpleTypeVisitor14.java b/src/java.compiler/share/classes/javax/lang/model/util/SimpleTypeVisitor14.java index 331297c8f2ee4573459627f9b3193688988a95eb..86e7cb1d981e398e82c7df10a4015a19c40e1329 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/SimpleTypeVisitor14.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/SimpleTypeVisitor14.java @@ -56,7 +56,7 @@ import static javax.lang.model.SourceVersion.*; * @see SimpleTypeVisitor9 * @since 14 */ -@SupportedSourceVersion(RELEASE_18) +@SupportedSourceVersion(RELEASE_19) public class SimpleTypeVisitor14 extends SimpleTypeVisitor9 { /** * Constructor for concrete subclasses; uses {@code null} for the diff --git a/src/java.compiler/share/classes/javax/lang/model/util/TypeKindVisitor14.java b/src/java.compiler/share/classes/javax/lang/model/util/TypeKindVisitor14.java index 66743281bb031dfd7b405c6482934f19fc22fa85..b83307c20959fc75edbbda45f2c2de036ebb7ca0 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/TypeKindVisitor14.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/TypeKindVisitor14.java @@ -61,7 +61,7 @@ import static javax.lang.model.SourceVersion.*; * @see TypeKindVisitor9 * @since 14 */ -@SupportedSourceVersion(RELEASE_18) +@SupportedSourceVersion(RELEASE_19) public class TypeKindVisitor14 extends TypeKindVisitor9 { /** * Constructor for concrete subclasses to call; uses {@code null} diff --git a/src/java.compiler/share/classes/javax/tools/ForwardingJavaFileManager.java b/src/java.compiler/share/classes/javax/tools/ForwardingJavaFileManager.java index 27b55f3603aa5a8d5b19f3f6395312d020ed48bc..9001b0ef38370b0f6f95b69de5624f2b199aad5d 100644 --- a/src/java.compiler/share/classes/javax/tools/ForwardingJavaFileManager.java +++ b/src/java.compiler/share/classes/javax/tools/ForwardingJavaFileManager.java @@ -26,6 +26,7 @@ package javax.tools; import java.io.IOException; +import java.lang.reflect.Method; import java.util.Iterator; import java.util.Objects; import java.util.ServiceLoader; @@ -144,6 +145,39 @@ public class ForwardingJavaFileManager implements Jav return fileManager.getJavaFileForOutput(location, className, kind, sibling); } + /**{@inheritDoc} + * + * @implSpec If the subclass of the {@code ForwardingJavaFileManager} overrides the + * {@link #getJavaFileForOutput} method, this method will delegate to it as per the + * general contract of {@link JavaFileManager#getJavaFileForOutputForOriginatingFiles}. + * If the subclass does not override the method, the call will be delegated to the + * {@code fileManager}. + * + * @throws IllegalArgumentException {@inheritDoc} + * @throws IllegalStateException {@inheritDoc} + */ + @Override + public JavaFileObject getJavaFileForOutputForOriginatingFiles(Location location, + String className, + Kind kind, + FileObject... originatingFiles) throws IOException { + try { + Method delegate = getClass().getMethod("getJavaFileForOutput", + Location.class, String.class, + Kind.class, FileObject.class); + if (delegate.getDeclaringClass() == ForwardingJavaFileManager.class) { + return fileManager.getJavaFileForOutputForOriginatingFiles(location, className, + kind, originatingFiles); + } else { + return JavaFileManager.super + .getJavaFileForOutputForOriginatingFiles(location, className, + kind, originatingFiles); + } + } catch (NoSuchMethodException ex) { + throw new InternalError("This should never happen.", ex); + } + } + /** * @throws IllegalArgumentException {@inheritDoc} * @throws IllegalStateException {@inheritDoc} @@ -171,6 +205,39 @@ public class ForwardingJavaFileManager implements Jav return fileManager.getFileForOutput(location, packageName, relativeName, sibling); } + /**{@inheritDoc} + * + * @implSpec If the subclass of the {@code ForwardingJavaFileManager} overrides the + * {@link #getFileForOutput} method, this method will delegate to it as per the + * general contract of {@link JavaFileManager#getFileForOutputForOriginatingFiles}. + * If the subclass does not override the method, the call will be delegated to the + * {@code fileManager}. + * + * @throws IllegalArgumentException {@inheritDoc} + * @throws IllegalStateException {@inheritDoc} + */ + @Override + public FileObject getFileForOutputForOriginatingFiles(Location location, + String packageName, + String relativeName, + FileObject... originatingFiles) throws IOException { + try { + Method delegate = getClass().getMethod("getFileForOutput", + Location.class, String.class, + String.class, FileObject.class); + if (delegate.getDeclaringClass() == ForwardingJavaFileManager.class) { + return fileManager.getFileForOutputForOriginatingFiles(location, packageName, + relativeName, originatingFiles); + } else { + return JavaFileManager.super + .getFileForOutputForOriginatingFiles(location, packageName, + relativeName, originatingFiles); + } + } catch (NoSuchMethodException ex) { + throw new InternalError("This should never happen.", ex); + } + } + @Override public void flush() throws IOException { fileManager.flush(); diff --git a/src/java.compiler/share/classes/javax/tools/JavaCompiler.java b/src/java.compiler/share/classes/javax/tools/JavaCompiler.java index f7c1c61a41bc9bcfa2b4667325ac433c257dbfe9..9039490524ba1f691252cb311d11502795a7b3e8 100644 --- a/src/java.compiler/share/classes/javax/tools/JavaCompiler.java +++ b/src/java.compiler/share/classes/javax/tools/JavaCompiler.java @@ -26,6 +26,7 @@ package javax.tools; import java.io.Writer; +import java.net.URI; import java.nio.charset.Charset; import java.util.Locale; import java.util.concurrent.Callable; @@ -106,42 +107,45 @@ import javax.annotation.processing.Processor; * work with multiple sequential compilations making the following * example a recommended coding pattern: * - *
- *       File[] files1 = ... ; // input for first compilation task
- *       File[] files2 = ... ; // input for second compilation task
+ *     {@snippet id="use-sjfm" lang=java :
+ *       File[] files1 = null ; // input for first compilation task     // @replace substring=null replacement="..."
+ *       File[] files2 = null ; // input for second compilation task    // @replace substring=null replacement="..."
  *
  *       JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
  *       StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
  *
- *       {@code Iterable} compilationUnits1 =
- *           fileManager.getJavaFileObjectsFromFiles({@linkplain java.util.Arrays#asList Arrays.asList}(files1));
+ *       Iterable compilationUnits1 =
+ *           fileManager.getJavaFileObjectsFromFiles(Arrays.asList(files1));  // @link substring=Arrays.asList target="java.util.Arrays#asList"
  *       compiler.getTask(null, fileManager, null, null, null, compilationUnits1).call();
  *
- *       {@code Iterable} compilationUnits2 =
+ *       Iterable compilationUnits2 =
  *           fileManager.getJavaFileObjects(files2); // use alternative method
  *       // reuse the same file manager to allow caching of jar files
  *       compiler.getTask(null, fileManager, null, null, null, compilationUnits2).call();
  *
- *       fileManager.close();
+ * fileManager.close(); + * } * * * *
{@link DiagnosticCollector}
*
* Used to collect diagnostics in a list, for example: - *
- *       {@code Iterable} compilationUnits = ...;
+ *     {@snippet id="use-diag-collector" lang=java :
+ *       Iterable compilationUnits = null;        // @replace substring=null replacement="..."
  *       JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
- *       {@code DiagnosticCollector diagnostics = new DiagnosticCollector();}
+ *       DiagnosticCollector diagnostics = new DiagnosticCollector();
  *       StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);
  *       compiler.getTask(null, fileManager, diagnostics, null, null, compilationUnits).call();
  *
- *       for ({@code Diagnostic} diagnostic : diagnostics.getDiagnostics())
+ *       for (Diagnostic diagnostic : diagnostics.getDiagnostics()) {
  *           System.out.format("Error on line %d in %s%n",
  *                             diagnostic.getLineNumber(),
  *                             diagnostic.getSource().toUri());
+ *       }
  *
- *       fileManager.close();
+ * fileManager.close(); + * } *
* *
@@ -158,9 +162,9 @@ import javax.annotation.processing.Processor; * allowing customizing behavior. For example, consider how to * log all calls to {@linkplain JavaFileManager#flush}: * - *
- *       final  Logger logger = ...;
- *       {@code Iterable} compilationUnits = ...;
+ *     {@snippet id="forward-fm" lang=java :
+ *       final  Logger logger = null;                                       // @replace substring=null replacement="..."
+ *       Iterable compilationUnits = null;        // @replace substring=null replacement="..."
  *       JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
  *       StandardJavaFileManager stdFileManager = compiler.getStandardFileManager(null, null, null);
  *       JavaFileManager fileManager = new ForwardingJavaFileManager(stdFileManager) {
@@ -170,7 +174,8 @@ import javax.annotation.processing.Processor;
  *               logger.exiting(StandardJavaFileManager.class.getName(), "flush");
  *           }
  *       };
- *       compiler.getTask(null, fileManager, null, null, null, compilationUnits).call();
+ * compiler.getTask(null, fileManager, null, null, null, compilationUnits).call(); + * } * * *
{@link SimpleJavaFileObject}
@@ -181,32 +186,7 @@ import javax.annotation.processing.Processor; * example, here is how to define a file object which represent * source code stored in a string: * - *
- *       /**
- *        * A file object used to represent source coming from a string.
- *        {@code *}/
- *       public class JavaSourceFromString extends SimpleJavaFileObject {
- *           /**
- *            * The source code of this "file".
- *            {@code *}/
- *           final String code;
- *
- *           /**
- *            * Constructs a new JavaSourceFromString.
- *            * {@code @}param name the name of the compilation unit represented by this file object
- *            * {@code @}param code the source code for the compilation unit represented by this file object
- *            {@code *}/
- *           JavaSourceFromString(String name, String code) {
- *               super({@linkplain java.net.URI#create URI.create}("string:///" + name.replace('.','/') + Kind.SOURCE.extension),
- *                     Kind.SOURCE);
- *               this.code = code;
- *           }
- *
- *           {@code @}Override
- *           public CharSequence getCharContent(boolean ignoreEncodingErrors) {
- *               return code;
- *           }
- *       }
+ * {@snippet id=fileObject class=JavaSourceFromString } * * * diff --git a/src/java.compiler/share/classes/javax/tools/JavaFileManager.java b/src/java.compiler/share/classes/javax/tools/JavaFileManager.java index 85cde42addc6ec7f9fe1105abc6eb8bf2dd7a6c6..1fe510e809d2c11f2bcc414b461a0c94a457c2f6 100644 --- a/src/java.compiler/share/classes/javax/tools/JavaFileManager.java +++ b/src/java.compiler/share/classes/javax/tools/JavaFileManager.java @@ -28,9 +28,12 @@ package javax.tools; import java.io.Closeable; import java.io.Flushable; import java.io.IOException; +import java.net.URI; import java.util.Iterator; import java.util.ServiceLoader; import java.util.Set; +import javax.annotation.processing.Filer; +import javax.lang.model.util.Elements; import static javax.tools.JavaFileObject.Kind; @@ -78,8 +81,10 @@ import static javax.tools.JavaFileObject.Kind; * href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986, * section 3.3. Informally, this should be true: * - * - *
  URI.{@linkplain java.net.URI#create create}(relativeName).{@linkplain java.net.URI#normalize() normalize}().{@linkplain java.net.URI#getPath getPath}().equals(relativeName)
+ * {@snippet id="valid-relative-name" lang=java : + * // @link substring="create" target="URI#create" @link substring=normalize target="URI#normalize" @link substring=getPath target="URI#getPath" : + * URI.create(relativeName).normalize().getPath().equals(relativeName) + * } * *

All methods in this interface might throw a SecurityException. * @@ -338,6 +343,51 @@ public interface JavaFileManager extends Closeable, Flushable, OptionChecker { FileObject sibling) throws IOException; + /** + * Returns a {@linkplain JavaFileObject file object} for output + * representing the specified class of the specified kind in the + * given package-oriented location. + * + *

The provided {@code originatingFiles} represent files that + * were, in an unspecified way, used to create the content of + * the file created by this method. See {@code originatingElements} + * in {@link Filer#createSourceFile}. {@link Elements#getFileObjectOf} + * may be used to convert the {@code Element}s to {@code FileObject}s. + * + * @implSpec The default implementation calls + * {@link #getJavaFileForOutput(javax.tools.JavaFileManager.Location, java.lang.String, javax.tools.JavaFileObject.Kind, javax.tools.FileObject) } + * with the first element of the {@code originatingFiles}, if any, as a {@code sibling}. + * + * @param location a package-oriented location + * @param className the name of a class + * @param kind the kind of file, must be one of {@link + * JavaFileObject.Kind#SOURCE SOURCE} or {@link + * JavaFileObject.Kind#CLASS CLASS} + * @param originatingFiles the files which are contributing to this newly created file; + * {@code null} is equivalent to empty {@code originatingFiles}, + * meaning no known originating files + * @return a file object for output + * @throws IllegalArgumentException if sibling is not known to + * this file manager, or if the location is not known to this file + * manager and the file manager does not support unknown + * locations, or if the kind is not valid, or if the location is + * not an output location + * @throws IOException if an I/O error occurred, or if {@link + * #close} has been called and this file manager cannot be + * reopened + * @throws IllegalStateException {@link #close} has been called + * and this file manager cannot be reopened + * @since 18 + * @see Filer#createSourceFile + */ + default JavaFileObject getJavaFileForOutputForOriginatingFiles(Location location, + String className, + Kind kind, + FileObject... originatingFiles) + throws IOException { + return getJavaFileForOutput(location, className, kind, siblingFrom(originatingFiles)); + } + /** * Returns a {@linkplain FileObject file object} for input * representing the specified relative @@ -356,7 +406,9 @@ public interface JavaFileManager extends Closeable, Flushable, OptionChecker { * StandardLocation#SOURCE_PATH SOURCE_PATH} location, this method * might be called like so: * - *

getFileForInput(SOURCE_PATH, "com.sun.tools.javac", "resources/compiler.properties");
+ * {@snippet id="call-getFileForInput" lang=java : + * getFileForInput(SOURCE_PATH, "com.sun.tools.javac", "resources/compiler.properties"); + * } * *

If the call was executed on Windows, with SOURCE_PATH set to * "C:\Documents and Settings\UncleBob\src\share\classes", @@ -430,6 +482,59 @@ public interface JavaFileManager extends Closeable, Flushable, OptionChecker { FileObject sibling) throws IOException; + /** + * Returns a {@linkplain FileObject file object} for output + * representing the specified relative + * name in the specified package in the given location. + * + *

The provided {@code originatingFiles} represent files that + * were, in an unspecified way, used to create the content of + * the file created by this method. See {@code originatingElements} + * in {@link Filer#createResource}. {@link Elements#getFileObjectOf} + * may be used to convert the {@code Element}s to {@code FileObject}s. + * + *

If the returned object represents a {@linkplain + * JavaFileObject.Kind#SOURCE source} or {@linkplain + * JavaFileObject.Kind#CLASS class} file, it must be an instance + * of {@link JavaFileObject}. + * + *

Informally, the file object returned by this method is + * located in the concatenation of the location, package name, and + * relative name or in a location inferred from the {@code originatingFiles}. + * See {@link #getFileForInput getFileForInput} for an example. + * + * @implSpec The default implementation calls + * {@link #getFileForOutput(javax.tools.JavaFileManager.Location, java.lang.String, java.lang.String, javax.tools.FileObject) } + * with the first element of the {@code originatingFiles}, if any, as a {@code sibling}. + * + * @param location an output location + * @param packageName a package name + * @param relativeName a relative name + * @param originatingFiles the files which are contributing to this newly created file; + * {@code null} is equivalent to empty {@code originatingFiles}, + * meaning no known originating files + * @return a file object + * @throws IllegalArgumentException if sibling is not known to + * this file manager, or if the location is not known to this file + * manager and the file manager does not support unknown + * locations, or if {@code relativeName} is not valid, + * or if the location is not an output location + * @throws IOException if an I/O error occurred, or if {@link + * #close} has been called and this file manager cannot be + * reopened + * @throws IllegalStateException if {@link #close} has been called + * and this file manager cannot be reopened + * @since 18 + * @see Filer#createResource + */ + default FileObject getFileForOutputForOriginatingFiles(Location location, + String packageName, + String relativeName, + FileObject... originatingFiles) + throws IOException { + return getFileForOutput(location, packageName, relativeName, siblingFrom(originatingFiles)); + } + /** * Flushes any resources opened for output by this file manager * directly or indirectly. Flushing a closed file manager has no @@ -566,16 +671,17 @@ public interface JavaFileManager extends Closeable, Flushable, OptionChecker { *

For a package-oriented location, a file object is contained in the location if there exist * values for packageName and relativeName such that either of the following * calls would return the {@link #isSameFile same} file object: - *

-     *     getFileForInput(location, packageName, relativeName)
-     *     getFileForOutput(location, packageName, relativeName, null)
-     * 
+ * {@snippet : + * // @highlight region substring=packageName type=italic @highlight region substring=relativeName type=italic : + * getFileForInput(location, packageName, relativeName) + * getFileForOutput(location, packageName, relativeName, null) // @end @end + * } * *

For a module-oriented location, a file object is contained in the location if there exists * a module that may be obtained by the call: - *

-     *     getLocationForModule(location, moduleName)
-     * 
+ * {@snippet id="call-getLocationForModule" lang=java : + * getLocationForModule(location, moduleName) // @highlight substring=moduleName type=italic + * } * such that the file object is contained in the (package-oriented) location for that module. * * @implSpec This implementation throws {@code UnsupportedOperationException}. @@ -594,4 +700,8 @@ public interface JavaFileManager extends Closeable, Flushable, OptionChecker { throw new UnsupportedOperationException(); } + private static FileObject siblingFrom(FileObject[] originatingFiles) { + return originatingFiles != null && originatingFiles.length > 0 ? originatingFiles[0] : null; + } + } diff --git a/src/java.compiler/share/classes/javax/tools/StandardJavaFileManager.java b/src/java.compiler/share/classes/javax/tools/StandardJavaFileManager.java index 5b6590bf926a524536f781e67c2edc4f5de33e92..bd36f64be6f879d6eaa31fc8236f0f2bdf3203cd 100644 --- a/src/java.compiler/share/classes/javax/tools/StandardJavaFileManager.java +++ b/src/java.compiler/share/classes/javax/tools/StandardJavaFileManager.java @@ -75,9 +75,10 @@ import java.util.List; * {@linkplain FileObject#openReader(boolean)} * must succeed if the following would succeed (ignoring * encoding issues): - *
- *
new {@linkplain java.io.FileInputStream#FileInputStream(File) FileInputStream}(new {@linkplain File#File(java.net.URI) File}({@linkplain FileObject fileObject}.{@linkplain FileObject#toUri() toUri}()))
- *
+ * {@snippet id="equiv-input" lang=java : + * // @link substring=FileInputStream target="java.io.FileInputStream#FileInputStream(File)" @link regex="File\b" target="File#File(java.net.URI)" @link substring=fileObject target=FileObject @link substring=toUri target="FileObject#toUri()" : + * new FileInputStream(new File(fileObject.toUri())) + * } * *
  • * and the methods @@ -85,9 +86,10 @@ import java.util.List; * {@linkplain FileObject#openWriter()} must * succeed if the following would succeed (ignoring encoding * issues): - *
    - *
    new {@linkplain java.io.FileOutputStream#FileOutputStream(File) FileOutputStream}(new {@linkplain File#File(java.net.URI) File}({@linkplain FileObject fileObject}.{@linkplain FileObject#toUri() toUri}()))
    - *
    + * {@snippet id="equiv-output" lang=java : + * // @link substring=FileOutputStream target="java.io.FileOutputStream#FileOutputStream(File)" @link regex="File\b" target="File#File(java.net.URI)" @link substring=fileObject target=FileObject @link substring=toUri target="FileObject#toUri()" : + * new FileOutputStream(new File(fileObject.toUri())) + * } *
  • * * @@ -241,9 +243,9 @@ public interface StandardJavaFileManager extends JavaFileManager { * Returns file objects representing the given files. * Convenience method equivalent to: * - *
    -     *     getJavaFileObjectsFromFiles({@linkplain java.util.Arrays#asList Arrays.asList}(files))
    -     * 
    + * {@snippet id="equiv-getJavaFileObjects" lang=java : + * getJavaFileObjectsFromFiles(Arrays.asList(files)) // @link substring="Arrays.asList" target="Arrays#asList" + * } * * @param files an array of files * @return a list of file objects @@ -259,9 +261,9 @@ public interface StandardJavaFileManager extends JavaFileManager { * Returns file objects representing the given paths. * Convenience method equivalent to: * - *
    -     *     getJavaFileObjectsFromPaths({@linkplain java.util.Arrays#asList Arrays.asList}(paths))
    -     * 
    + * {@snippet id="equiv-getJavaFileObjectsFromPaths" lang=java : + * getJavaFileObjectsFromPaths(Arrays.asList(paths)) // @link substring="Arrays.asList" target="Arrays#asList" + * } * * @implSpec * The default implementation will only throw {@code NullPointerException} @@ -296,9 +298,9 @@ public interface StandardJavaFileManager extends JavaFileManager { * Returns file objects representing the given file names. * Convenience method equivalent to: * - *
    -     *     getJavaFileObjectsFromStrings({@linkplain java.util.Arrays#asList Arrays.asList}(names))
    -     * 
    + * {@snippet id="equiv-getJavaFileObjectsFromStrings" lang=java : + * getJavaFileObjectsFromStrings(Arrays.asList(names)) // @link substring="Arrays.asList" target="Arrays#asList" + * } * * @param names a list of file names * @return a list of file objects diff --git a/src/java.compiler/share/classes/javax/tools/package-info.java b/src/java.compiler/share/classes/javax/tools/package-info.java index c5ec54e7871e0495204da9cc29df9996a20b2512..963e6f2261c43a32a4f83689f215ecb49eff714b 100644 --- a/src/java.compiler/share/classes/javax/tools/package-info.java +++ b/src/java.compiler/share/classes/javax/tools/package-info.java @@ -52,7 +52,9 @@ * a default compiler is provided, it can be located using the * {@link javax.tools.ToolProvider}, for example: * - *

    {@code JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();} + * {@snippet id="show-getSystemJavaCompiler" lang=java : + * JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + * } * *

    It is possible to provide alternative compilers or tools * through the {@linkplain java.util.ServiceLoader service provider @@ -64,12 +66,16 @@ * META-INF/services/javax.tools.JavaCompiler}. This file would * contain the single line: * - *

    {@code com.vendor.VendorJavaCompiler} + * {@snippet id="show-service" : + * com.vendor.VendorJavaCompiler + * } * - *

    If the jar file is on the class path, VendorJavaCompiler can be + *

    If the jar file is on the class path, {@code VendorJavaCompiler} can be * located using code like this: * - *

    {@code JavaCompiler compiler = ServiceLoader.load(JavaCompiler.class).iterator().next();} + * {@snippet id="show-serviceLoader" lang=java : + * JavaCompiler compiler = ServiceLoader.load(JavaCompiler.class).iterator().next(); + * } * * @author Peter von der Ahé * @author Jonathan Gibbons diff --git a/src/java.compiler/share/classes/javax/tools/snippet-files/JavaSourceFromString.java b/src/java.compiler/share/classes/javax/tools/snippet-files/JavaSourceFromString.java new file mode 100644 index 0000000000000000000000000000000000000000..f0555a02e9e3baf276857052c22659a1923d5bf1 --- /dev/null +++ b/src/java.compiler/share/classes/javax/tools/snippet-files/JavaSourceFromString.java @@ -0,0 +1,54 @@ +// @replace region replacement="" +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.tools.SimpleJavaFileObject; +import java.net.URI; +// @end +/** + * A file object used to represent source coming from a string. + */ +public class JavaSourceFromString extends SimpleJavaFileObject { + /** + * The source code of this "file". + */ + final String code; + + /** + * Constructs a new JavaSourceFromString. + * @param name the name of the compilation unit represented by this file object + * @param code the source code for the compilation unit represented by this file object + */ + JavaSourceFromString(String name, String code) { + super(URI.create("string:///" + name.replace('.','/') + Kind.SOURCE.extension), // @link substring="URI.create" target="URI#create(String)" + Kind.SOURCE); + this.code = code; + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return code; + } +} diff --git a/src/java.compiler/share/classes/module-info.java b/src/java.compiler/share/classes/module-info.java index 3d937e09f0cc88d558360becf9b7158f0199de09..0793855d1dc6efb9846d77c5219be91b8a25ce84 100644 --- a/src/java.compiler/share/classes/module-info.java +++ b/src/java.compiler/share/classes/module-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,9 @@ */ /** - * Defines the Language Model, Annotation Processing, and Java Compiler APIs. + * Defines the {@index "Language Model"}, {@index "Annotation Processing"}, and + * {@index "Java Compiler"} APIs. + * *

    * These APIs model declarations and types of the Java programming language, * and define interfaces for tools such as compilers which can be invoked diff --git a/src/java.desktop/macosx/classes/apple/laf/JRSUIControl.java b/src/java.desktop/macosx/classes/apple/laf/JRSUIControl.java index e3579449b7570396b7c0767272d2720ebfd27fe2..6e6c86ccf7ac33d8e1116a1c8bd4978cb7635e9a 100644 --- a/src/java.desktop/macosx/classes/apple/laf/JRSUIControl.java +++ b/src/java.desktop/macosx/classes/apple/laf/JRSUIControl.java @@ -114,7 +114,7 @@ public final class JRSUIControl { changes.putAll(other.changes); } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected synchronized void finalize() throws Throwable { if (cfDictionaryPtr == 0) return; disposeCFDictionary(cfDictionaryPtr); diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaBorder.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaBorder.java index f9e099fd4d48c3765f2013866ffab90954a6ea9c..cf75ab164bac54104e30e32113f9f401b7d51ae1 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaBorder.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaBorder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -128,7 +128,7 @@ public abstract class AquaBorder implements Border, UIResource { if (!((javax.swing.text.JTextComponent)focusable).isEditable()) return false; } - return (focusable != null && focusable instanceof JComponent && ((JComponent)focusable).hasFocus()); + return (focusable instanceof JComponent jComponent) && jComponent.hasFocus(); } @Override diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonBorder.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonBorder.java index f58c518d2d4179911e913f5f414c21268e8adc33..1d11a0a8d96f4e35ebe60d1b8bf66916a52f4508 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonBorder.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonBorder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -145,9 +145,9 @@ public abstract class AquaButtonBorder extends AquaBorder implements Border, UIR * @param c the component for which this border insets value applies */ public Insets getBorderInsets(final Component c) { - if (c == null || !(c instanceof AbstractButton)) return new Insets(0, 0, 0, 0); + if (!(c instanceof AbstractButton button)) return new Insets(0, 0, 0, 0); - Insets margin = ((AbstractButton)c).getMargin(); + Insets margin = button.getMargin(); margin = (margin == null) ? new InsetsUIResource(0, 0, 0, 0) : (Insets)margin.clone(); margin.top += sizeVariant.margins.top; diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxUI.java index 06f84d0eae12e5a27bb3cbde969891ce8ef39f87..c25d89559fc0c25e17a01ef01916761842e79502 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -598,8 +598,7 @@ public class AquaComboBoxUI extends BasicComboBoxUI implements Sizeable { final boolean editable = comboBox.isEditable(); final Dimension size; - if (!editable && arrowButton != null && arrowButton instanceof AquaComboBoxButton) { - final AquaComboBoxButton button = (AquaComboBoxButton)arrowButton; + if (!editable && arrowButton instanceof final AquaComboBoxButton button) { final Insets buttonInsets = button.getInsets(); // Insets insets = comboBox.getInsets(); final Insets insets = new Insets(0, 5, 0, 25);//comboBox.getInsets(); diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaFileChooserUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaFileChooserUI.java index 4160087be4ed080495f305657bf2ccfb48d93b71..d8bfca02fe75d9dd1063e98dbdf95734f85513c8 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaFileChooserUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaFileChooserUI.java @@ -519,14 +519,14 @@ public class AquaFileChooserUI extends FileChooserUI { void setPackageIsTraversable(final Object o) { int newProp = -1; - if (o != null && o instanceof String) newProp = parseTraversableProperty((String)o); + if (o instanceof String s) newProp = parseTraversableProperty(s); if (newProp != -1) fPackageIsTraversable = newProp; else fPackageIsTraversable = sGlobalPackageIsTraversable; } void setApplicationIsTraversable(final Object o) { int newProp = -1; - if (o != null && o instanceof String) newProp = parseTraversableProperty((String)o); + if (o instanceof String s) newProp = parseTraversableProperty(s); if (newProp != -1) fApplicationIsTraversable = newProp; else fApplicationIsTraversable = sGlobalApplicationIsTraversable; } @@ -1985,11 +1985,11 @@ public class AquaFileChooserUI extends FileChooserUI { static { Object o = UIManager.get(PACKAGE_TRAVERSABLE_PROPERTY); - if (o != null && o instanceof String) sGlobalPackageIsTraversable = parseTraversableProperty((String)o); + if (o instanceof String s) sGlobalPackageIsTraversable = parseTraversableProperty(s); else sGlobalPackageIsTraversable = kOpenConditional; o = UIManager.get(APPLICATION_TRAVERSABLE_PROPERTY); - if (o != null && o instanceof String) sGlobalApplicationIsTraversable = parseTraversableProperty((String)o); + if (o instanceof String s) sGlobalApplicationIsTraversable = parseTraversableProperty(s); else sGlobalApplicationIsTraversable = kOpenConditional; } static final String sDataPrefix = "FileChooser."; diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaLookAndFeel.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaLookAndFeel.java index 610b408c99b372cd8330543b75b088d8f8fc4c1a..dad0b2279ebeff20c6e653803205e7e5e2564575 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaLookAndFeel.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaLookAndFeel.java @@ -188,8 +188,8 @@ public class AquaLookAndFeel extends BasicLookAndFeel { KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventPostProcessor(AquaMnemonicHandler.getInstance()); final PopupFactory popupFactory = PopupFactory.getSharedInstance(); - if (popupFactory != null && popupFactory instanceof ScreenPopupFactory) { - ((ScreenPopupFactory)popupFactory).setActive(false); + if (popupFactory instanceof ScreenPopupFactory spf) { + spf.setActive(false); } super.uninitialize(); diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaRootPaneUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaRootPaneUI.java index a4e179645a958bd3d6e916845233b45d86e89e00..2b4e1bb0867f8e6a46483bffd26d75367940b884 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaRootPaneUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaRootPaneUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -75,8 +75,7 @@ public class AquaRootPaneUI extends BasicRootPaneUI implements AncestorListener, // it is not since we are going to grab the one that was set on the JFrame. :( final Component parent = c.getParent(); - if (parent != null && parent instanceof JFrame) { - final JFrame frameParent = (JFrame)parent; + if (parent instanceof JFrame frameParent) { final Color bg = frameParent.getBackground(); if (bg == null || bg instanceof UIResource) { frameParent.setBackground(UIManager.getColor("Panel.background")); @@ -126,8 +125,8 @@ public class AquaRootPaneUI extends BasicRootPaneUI implements AncestorListener, final Window owningWindow = SwingUtilities.getWindowAncestor(jmb); // Could be a JDialog, and may have been added to a JRootPane not yet in a window. - if (owningWindow != null && owningWindow instanceof JFrame) { - ((AquaMenuBarUI)mbui).setScreenMenuBar((JFrame)owningWindow); + if (owningWindow instanceof JFrame frame) { + ((AquaMenuBarUI)mbui).setScreenMenuBar(frame); } } } @@ -154,8 +153,8 @@ public class AquaRootPaneUI extends BasicRootPaneUI implements AncestorListener, final Window owningWindow = SwingUtilities.getWindowAncestor(jmb); // Could be a JDialog, and may have been added to a JRootPane not yet in a window. - if (owningWindow != null && owningWindow instanceof JFrame) { - ((AquaMenuBarUI)mbui).clearScreenMenuBar((JFrame)owningWindow); + if (owningWindow instanceof JFrame frame) { + ((AquaMenuBarUI)mbui).clearScreenMenuBar(frame); } } } diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaSliderUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaSliderUI.java index 3775fc859e44348111e479578bc190d68dd412ab..50da054c1f8dcb5b27830953a5e81b261de0bbe6 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaSliderUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaSliderUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -266,8 +266,8 @@ public class AquaSliderUI extends BasicSliderUI implements Sizeable { if (slider.getPaintTicks() || slider.getPaintLabels()) return true; final Object shouldPaintArrowThumbProperty = slider.getClientProperty("Slider.paintThumbArrowShape"); - if (shouldPaintArrowThumbProperty != null && shouldPaintArrowThumbProperty instanceof Boolean) { - return ((Boolean)shouldPaintArrowThumbProperty).booleanValue(); + if (shouldPaintArrowThumbProperty instanceof Boolean b) { + return b; } return false; diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaTableHeaderUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaTableHeaderUI.java index 85577ce46ca458377b1f0a31e4959fa1cdc84ccb..af5621657de1cd8fda58890ab3478376d51c713e 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaTableHeaderUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaTableHeaderUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -103,9 +103,8 @@ public class AquaTableHeaderUI extends BasicTableHeaderUI { } final TableHeaderUI headerUI = target.getUI(); - if (headerUI == null || !(headerUI instanceof AquaTableHeaderUI)) return; + if (!(headerUI instanceof AquaTableHeaderUI aquaHeaderUI)) return; - final AquaTableHeaderUI aquaHeaderUI = (AquaTableHeaderUI)headerUI; aquaHeaderUI.sortColumn = tableColumn.getModelIndex(); aquaHeaderUI.sortOrder = sortDirection; final AquaTableCellRenderer renderer = aquaHeaderUI.new AquaTableCellRenderer(); @@ -145,8 +144,7 @@ public class AquaTableHeaderUI extends BasicTableHeaderUI { } protected static TableColumn getTableColumn(final JTableHeader target, final Object value) { - if (value == null || !(value instanceof Integer)) return null; - final int columnIndex = ((Integer)value).intValue(); + if (!(value instanceof Integer columnIndex)) return null; final TableColumnModel columnModel = target.getColumnModel(); if (columnIndex < 0 || columnIndex >= columnModel.getColumnCount()) return null; diff --git a/src/java.desktop/macosx/classes/com/apple/laf/ScreenMenu.java b/src/java.desktop/macosx/classes/com/apple/laf/ScreenMenu.java index 4f6e006faf82825227cc311faa92f04a54074728..747e8ac137ecfc35cf6c939eecc0f4da4d374a5c 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/ScreenMenu.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/ScreenMenu.java @@ -351,11 +351,8 @@ final class ScreenMenu extends Menu // Tell our parent to add/remove us final MenuContainer parent = getParent(); - if (parent != null) { - if (parent instanceof ScreenMenu) { - final ScreenMenu sm = (ScreenMenu)parent; - sm.setChildVisible(fInvoker, b); - } + if (parent instanceof ScreenMenu sm) { + sm.setChildVisible(fInvoker, b); } } diff --git a/src/java.desktop/macosx/classes/sun/awt/CGraphicsEnvironment.java b/src/java.desktop/macosx/classes/sun/awt/CGraphicsEnvironment.java index e96ce7e18d79ac35bf2552e1ac6ef92b4278f7b0..fe4431e3091284a994bbc42e40f50330a41638dc 100644 --- a/src/java.desktop/macosx/classes/sun/awt/CGraphicsEnvironment.java +++ b/src/java.desktop/macosx/classes/sun/awt/CGraphicsEnvironment.java @@ -144,7 +144,7 @@ public final class CGraphicsEnvironment extends SunGraphicsEnvironment { } @Override - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { try { super.finalize(); diff --git a/src/java.desktop/macosx/classes/sun/font/CFont.java b/src/java.desktop/macosx/classes/sun/font/CFont.java index 885fc7fc471d2bb3241b9d06b138ea76fe31cb10..073364719f04d06ef5ea155ce6d38609dc5ad838 100644 --- a/src/java.desktop/macosx/classes/sun/font/CFont.java +++ b/src/java.desktop/macosx/classes/sun/font/CFont.java @@ -206,7 +206,7 @@ public final class CFont extends PhysicalFont implements FontSubstitution { // In some italic cases the standard Mac cascade list is missing Arabic. listOfString.add("GeezaPro"); - FontManager fm = FontManagerFactory.getInstance(); + CFontManager fm = (CFontManager) FontManagerFactory.getInstance(); int numFonts = 1 + listOfString.size(); PhysicalFont[] fonts = new PhysicalFont[numFonts]; fonts[0] = this; @@ -222,7 +222,7 @@ public final class CFont extends PhysicalFont implements FontSubstitution { // Don't know why we get the weird name above .. replace. s = "AppleSymbols"; } - Font2D f2d = fm.findFont2D(s, Font.PLAIN, FontManager.NO_FALLBACK); + Font2D f2d = fm.getOrCreateFallbackFont(s); if (f2d == null || f2d == this) { continue; } @@ -247,7 +247,7 @@ public final class CFont extends PhysicalFont implements FontSubstitution { return compFont; } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected synchronized void finalize() { if (nativeFontPtr != 0) { disposeNativeFont(nativeFontPtr); diff --git a/src/java.desktop/macosx/classes/sun/font/CFontManager.java b/src/java.desktop/macosx/classes/sun/font/CFontManager.java index 85182158ec152c3c130c7a8b6b087fd46d0b7b3a..5af2be3f60c97d158d7f8568f0b1478e92cec16d 100644 --- a/src/java.desktop/macosx/classes/sun/font/CFontManager.java +++ b/src/java.desktop/macosx/classes/sun/font/CFontManager.java @@ -33,8 +33,10 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.Hashtable; import java.util.Locale; +import java.util.Map; import java.util.TreeMap; import java.util.Vector; +import java.util.concurrent.ConcurrentHashMap; import javax.swing.plaf.FontUIResource; @@ -45,6 +47,7 @@ import sun.lwawt.macosx.*; public final class CFontManager extends SunFontManager { private static Hashtable genericFonts = new Hashtable(); + private final Map fallbackFonts = new ConcurrentHashMap<>(); @Override protected FontConfiguration createFontConfiguration() { @@ -283,9 +286,9 @@ public final class CFontManager extends SunFontManager { if (realFamily == null) return false; Font2D realFont = realFamily.getFontWithExactStyleMatch(style); - if (realFont == null || !(realFont instanceof CFont)) return false; + if (!(realFont instanceof CFont cFont)) return false; - CFont newFont = new CFont((CFont)realFont, logicalFamilyName); + CFont newFont = new CFont(cFont, logicalFamilyName); registerGenericFont(newFont, true); return true; @@ -321,4 +324,17 @@ public final class CFontManager extends SunFontManager { @Override protected void populateFontFileNameMap(HashMap fontToFileMap, HashMap fontToFamilyNameMap, HashMap> familyToFontListMap, Locale locale) {} + + Font2D getOrCreateFallbackFont(String fontName) { + Font2D font2D = findFont2D(fontName, Font.PLAIN, FontManager.NO_FALLBACK); + if (font2D != null || fontName.startsWith(".")) { + return font2D; + } else { + // macOS doesn't list some system fonts in [NSFontManager availableFontFamilies] output, + // so they are not registered in font manager as part of 'loadNativeFonts'. + // These fonts are present in [NSFontManager availableFonts] output though, + // and can be accessed in the same way as other system fonts. + return fallbackFonts.computeIfAbsent(fontName, name -> new CFont(name, null)); + } + } } diff --git a/src/java.desktop/macosx/classes/sun/font/CStrike.java b/src/java.desktop/macosx/classes/sun/font/CStrike.java index 088fb01591e2b83031bc59e6463c2e7e78c26a3d..eb049c3d449d4b1ffb975090ff7e2c9062244bc6 100644 --- a/src/java.desktop/macosx/classes/sun/font/CStrike.java +++ b/src/java.desktop/macosx/classes/sun/font/CStrike.java @@ -125,7 +125,7 @@ public final class CStrike extends PhysicalStrike { return nativeStrikePtr; } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected synchronized void finalize() throws Throwable { if (nativeStrikePtr != 0) { disposeNativeStrikePtr(nativeStrikePtr); diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java index 2f23d8d0fdf258dd956d0508ac628ff73e34a78c..f338f25f05ed8d4d6a75582b7e4aa60b93ed06cf 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java @@ -627,8 +627,8 @@ class CAccessibility implements PropertyChangeListener { return invokeAndWait(new Callable() { public Accessible call() throws Exception { Component c = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); - if (c == null || !(c instanceof Accessible)) return null; - return CAccessible.getCAccessible((Accessible)c); + if (!(c instanceof Accessible accessible)) return null; + return CAccessible.getCAccessible(accessible); } }, c); } diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFRetainedResource.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFRetainedResource.java index de0553501e6b400a06c0e807ac581ac8384a54c5..43d6c218b29686652edc52357254e76a875f421b 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFRetainedResource.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFRetainedResource.java @@ -163,7 +163,7 @@ public class CFRetainedResource { } @Override - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected final void finalize() throws Throwable { dispose(); } diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java index eb97221dc728893322ebd7b5d0d78580e105ba68..1aa4eae1e5d1b375663aed01382a9d61549fc304 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java @@ -244,12 +244,12 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo c.execute(ptr -> nativeRevalidateNSWindowShadow(ptr)); }}, new Property(WINDOW_DOCUMENT_FILE) { public void applyProperty(final CPlatformWindow c, final Object value) { - if (value == null || !(value instanceof java.io.File)) { + if (!(value instanceof java.io.File file)) { c.execute(ptr->nativeSetNSWindowRepresentedFilename(ptr, null)); return; } - final String filename = ((java.io.File)value).getAbsolutePath(); + final String filename = file.getAbsolutePath(); c.execute(ptr->nativeSetNSWindowRepresentedFilename(ptr, filename)); }}, new Property(WINDOW_FULL_CONTENT) { diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java index 4849c16b79f0ce303e8816d89872dabbcf32d158..8dd0246228437192f5d08799196fb925b527f87e 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java @@ -598,7 +598,7 @@ public final class CPrinterJob extends RasterPrinterJob { // The following methods are CPrinterJob specific. @Override - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() { synchronized (fNSPrintInfoLock) { if (fNSPrintInfo != -1) { @@ -845,10 +845,10 @@ public final class CPrinterJob extends RasterPrinterJob { @Override protected MediaSize getMediaSize(Media media, PrintService service, PageFormat page) { - if (media == null || !(media instanceof MediaSizeName)) { + if (!(media instanceof MediaSizeName msn)) { return getDefaultMediaSize(page); } - MediaSize size = MediaSize.getMediaSizeForName((MediaSizeName) media); + MediaSize size = MediaSize.getMediaSizeForName(msn); return size != null ? size : getDefaultMediaSize(page); } diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/EncoderManager.m b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/EncoderManager.m index 0fb18c3f4c314e29eeae50141aa885160a121398..95374d2c93e53f1d4af0bd960b70e9b7be584bee 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/EncoderManager.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/EncoderManager.m @@ -41,11 +41,9 @@ const SurfaceRasterFlags defaultRasterFlags = { JNI_FALSE, JNI_TRUE }; - (void)dealloc; - (void)reset:(id)destination - isDstOpaque:(jboolean)isDstOpaque - isDstPremultiplied:(jboolean)isDstPremultiplied - isAA:(jboolean)isAA - isText:(jboolean)isText - isLCD:(jboolean)isLCD; + isAA:(jboolean)isAA + isText:(jboolean)isText + isLCD:(jboolean)isLCD; - (void)updateEncoder:(id)encoder context:(MTLContext *)mtlc @@ -64,7 +62,6 @@ const SurfaceRasterFlags defaultRasterFlags = { JNI_FALSE, JNI_TRUE }; // Persistent encoder properties id _destination; - SurfaceRasterFlags _dstFlags; jboolean _isAA; jboolean _isText; @@ -123,14 +120,10 @@ const SurfaceRasterFlags defaultRasterFlags = { JNI_FALSE, JNI_TRUE }; } - (void)reset:(id)destination - isDstOpaque:(jboolean)isDstOpaque - isDstPremultiplied:(jboolean)isDstPremultiplied - isAA:(jboolean)isAA - isText:(jboolean)isText - isLCD:(jboolean)isLCD { + isAA:(jboolean)isAA + isText:(jboolean)isText + isLCD:(jboolean)isLCD { _destination = destination; - _dstFlags.isOpaque = isDstOpaque; - _dstFlags.isPremultiplied = isDstPremultiplied; _isAA = isAA; _isText = isText; _isLCD = isLCD; @@ -288,20 +281,20 @@ const SurfaceRasterFlags defaultRasterFlags = { JNI_FALSE, JNI_TRUE }; - (id _Nonnull)getAARenderEncoder:(const BMTLSDOps * _Nonnull)dstOps { id dstTxt = dstOps->pTexture; - RenderOptions roptions = {JNI_FALSE, JNI_TRUE, INTERPOLATION_NEAREST_NEIGHBOR, defaultRasterFlags, {dstOps->isOpaque, JNI_TRUE}, JNI_FALSE, JNI_FALSE, JNI_FALSE}; + RenderOptions roptions = {JNI_FALSE, JNI_TRUE, INTERPOLATION_NEAREST_NEIGHBOR, defaultRasterFlags, JNI_FALSE, JNI_FALSE, JNI_FALSE}; return [self getEncoder:dstTxt renderOptions:&roptions]; } - (id _Nonnull)getAAShaderRenderEncoder:(const BMTLSDOps * _Nonnull)dstOps { - RenderOptions roptions = {JNI_FALSE, JNI_FALSE, INTERPOLATION_NEAREST_NEIGHBOR, defaultRasterFlags, {dstOps->isOpaque, JNI_TRUE}, JNI_FALSE, JNI_FALSE, JNI_TRUE}; + RenderOptions roptions = {JNI_FALSE, JNI_FALSE, INTERPOLATION_NEAREST_NEIGHBOR, defaultRasterFlags, JNI_FALSE, JNI_FALSE, JNI_TRUE}; return [self getEncoder:dstOps->pTexture renderOptions:&roptions]; } - (id _Nonnull)getRenderEncoder:(id _Nonnull)dest isDstOpaque:(bool)isOpaque { - RenderOptions roptions = {JNI_FALSE, JNI_FALSE, INTERPOLATION_NEAREST_NEIGHBOR, defaultRasterFlags, {isOpaque, JNI_TRUE}, JNI_FALSE, JNI_FALSE, JNI_FALSE}; + RenderOptions roptions = {JNI_FALSE, JNI_FALSE, INTERPOLATION_NEAREST_NEIGHBOR, defaultRasterFlags, JNI_FALSE, JNI_FALSE, JNI_FALSE}; return [self getEncoder:dest renderOptions:&roptions]; } @@ -329,7 +322,7 @@ const SurfaceRasterFlags defaultRasterFlags = { JNI_FALSE, JNI_TRUE }; isSrcOpaque:(bool)isSrcOpaque isDstOpaque:(bool)isDstOpaque { - RenderOptions roptions = {JNI_TRUE, JNI_FALSE, INTERPOLATION_NEAREST_NEIGHBOR, {isSrcOpaque, JNI_TRUE }, {isDstOpaque, JNI_TRUE}, JNI_FALSE, JNI_TRUE, JNI_FALSE}; + RenderOptions roptions = {JNI_TRUE, JNI_FALSE, INTERPOLATION_NEAREST_NEIGHBOR, {isSrcOpaque, JNI_TRUE }, JNI_FALSE, JNI_TRUE, JNI_FALSE}; return [self getEncoder:dest renderOptions:&roptions]; } @@ -339,7 +332,7 @@ const SurfaceRasterFlags defaultRasterFlags = { JNI_FALSE, JNI_TRUE }; interpolation:(int)interpolation isAA:(jboolean)isAA { - RenderOptions roptions = {JNI_TRUE, isAA, interpolation, { isSrcOpaque, JNI_TRUE }, {isDstOpaque, JNI_TRUE}, JNI_FALSE, JNI_FALSE, JNI_FALSE}; + RenderOptions roptions = {JNI_TRUE, isAA, interpolation, { isSrcOpaque, JNI_TRUE }, JNI_FALSE, JNI_FALSE, JNI_FALSE}; return [self getEncoder:dest renderOptions:&roptions]; } @@ -354,7 +347,8 @@ const SurfaceRasterFlags defaultRasterFlags = { JNI_FALSE, JNI_TRUE }; - (id _Nonnull) getTextEncoder:(const BMTLSDOps * _Nonnull)dstOps isSrcOpaque:(bool)isSrcOpaque { - RenderOptions roptions = {JNI_TRUE, JNI_FALSE, INTERPOLATION_NEAREST_NEIGHBOR, { isSrcOpaque, JNI_TRUE }, {dstOps->isOpaque, JNI_TRUE}, JNI_TRUE, JNI_FALSE, JNI_FALSE}; + RenderOptions roptions = {JNI_TRUE, JNI_FALSE, INTERPOLATION_NEAREST_NEIGHBOR, { isSrcOpaque, JNI_TRUE }, + JNI_TRUE, JNI_FALSE, JNI_FALSE}; return [self getEncoder:dstOps->pTexture renderOptions:&roptions]; } @@ -437,11 +431,9 @@ const SurfaceRasterFlags defaultRasterFlags = { JNI_FALSE, JNI_TRUE }; _encoder = [[cbw getCommandBuffer] renderCommandEncoderWithDescriptor:rpd]; [_encoderStates reset:dest - isDstOpaque:renderOptions->dstFlags.isOpaque - isDstPremultiplied:YES - isAA:renderOptions->isAA - isText:renderOptions->isText - isLCD:renderOptions->isLCD]; + isAA:renderOptions->isAA + isText:renderOptions->isText + isLCD:renderOptions->isLCD]; } // diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLBlitLoops.m b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLBlitLoops.m index bf55d8c8976d0454cd1e1f43bf895b917ac72b45..47571a5e7ae4a98862c92d59fa8aa5de880efaa0 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLBlitLoops.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLBlitLoops.m @@ -595,8 +595,9 @@ MTLBlitLoops_Blit(JNIEnv *env, } #ifdef TRACE_BLIT - J2dTraceImpl(J2D_TRACE_VERBOSE, JNI_FALSE, - "MTLBlitLoops_Blit [tx=%d, xf=%d, AC=%s]: bdst=%s, src=%p (%dx%d) O=%d premul=%d | (%d, %d, %d, %d)->(%1.2f, %1.2f, %1.2f, %1.2f)", + J2dTraceImpl(J2D_TRACE_VERBOSE, JNI_TRUE, + "MTLBlitLoops_Blit srctype=%d [tx=%d, xf=%d, AC=%s]: bdst=%s, src=%p (%dx%d) O=%d premul=%d | (%d, " + "%d, %d, %d)->(%1.2f, %1.2f, %1.2f, %1.2f)", srctype, texture, xform, [mtlc getCompositeDescription].cString, getSurfaceDescription(dstOps).cString, srcOps, sx2 - sx1, sy2 - sy1, diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLClip.m b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLClip.m index 35d8ba624c9bd00f85a1e3bea6ea0a291b50c3de..effe7aebae6f89a71e2c5c98dea19ebac98bb18d 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLClip.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLClip.m @@ -58,7 +58,6 @@ static void initTemplatePipelineDescriptors() { BMTLSDOps* _dstOps; BOOL _stencilMaskGenerationInProgress; BOOL _stencilMaskGenerationStarted; - BOOL _clipReady; MTLOrigin _clipShapeOrigin; MTLSize _clipShapeSize; } @@ -73,7 +72,6 @@ static void initTemplatePipelineDescriptors() { _dstOps = NULL; _stencilMaskGenerationInProgress = NO; _stencilMaskGenerationStarted = NO; - _clipReady = NO; } return self; } @@ -189,7 +187,6 @@ static void initTemplatePipelineDescriptors() { _stencilMaskGenerationStarted = NO; _dstOps = dstOps; _clipType = SHAPE_CLIP; - _clipReady = NO; } - (void)setMaskGenerationPipelineState:(id)encoder diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLPaints.m b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLPaints.m index a3b1254bf13745882cac470186788b5ada3151a3..5686449a295602e900b46342ccdc819484475993 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLPaints.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLPaints.m @@ -56,7 +56,7 @@ static MTLRenderPipelineDescriptor * templateLCDPipelineDesc = nil; static MTLRenderPipelineDescriptor * templateAAPipelineDesc = nil; static void setTxtUniforms(MTLContext *mtlc, int color, id encoder, int interpolation, bool repeat, - jfloat extraAlpha, const SurfaceRasterFlags *srcFlags, const SurfaceRasterFlags *dstFlags, int mode); + jfloat extraAlpha, const SurfaceRasterFlags *srcFlags, int mode); static void initTemplatePipelineDescriptors() { if (templateRenderPipelineDesc != nil && templateTexturePipelineDesc != nil && @@ -228,8 +228,8 @@ jint _color; rpDesc = [[templateLCDPipelineDesc copy] autorelease]; } setTxtUniforms(mtlc, _color, encoder, - renderOptions->interpolation, NO, [mtlc.composite getExtraAlpha], &renderOptions->srcFlags, - &renderOptions->dstFlags, 1); + renderOptions->interpolation, NO, [mtlc.composite getExtraAlpha], + &renderOptions->srcFlags, 1); } else if (renderOptions->isAAShader) { vertShader = @"vert_col_aa"; fragShader = @"frag_col_aa"; @@ -270,7 +270,7 @@ jint _color; setTxtUniforms(mtlc, col, encoder, renderOptions->interpolation, NO, [mtlc.composite getExtraAlpha], - &renderOptions->srcFlags, &renderOptions->dstFlags, 1); + &renderOptions->srcFlags, 1); [encoder setFragmentBytes:&xorColor length:sizeof(xorColor) atIndex:0]; [encoder setFragmentTexture:dstOps->pTexture atIndex:1]; @@ -809,9 +809,8 @@ jint _color; [encoder setFragmentTexture:_paintTexture atIndex:0]; } const SurfaceRasterFlags srcFlags = {_isOpaque, renderOptions->srcFlags.isPremultiplied}; - setTxtUniforms(mtlc, 0, encoder, - renderOptions->interpolation, YES, [mtlc.composite getExtraAlpha], - &srcFlags, &renderOptions->dstFlags, 0); + setTxtUniforms(mtlc, 0, encoder, renderOptions->interpolation, YES, [mtlc.composite getExtraAlpha], + &srcFlags, 0); id pipelineState = [pipelineStateStorage getPipelineState:rpDesc vertexShaderId:vertShader @@ -893,8 +892,8 @@ jint _color; static void setTxtUniforms(MTLContext *mtlc, int color, id encoder, int interpolation, bool repeat, - jfloat extraAlpha, const SurfaceRasterFlags *srcFlags, const SurfaceRasterFlags *dstFlags, int mode) { - struct TxtFrameUniforms uf = {RGBA_TO_V4(color), mode, srcFlags->isOpaque, dstFlags->isOpaque, extraAlpha}; + jfloat extraAlpha, const SurfaceRasterFlags *srcFlags, int mode) { + struct TxtFrameUniforms uf = {RGBA_TO_V4(color), mode, srcFlags->isOpaque, extraAlpha}; [encoder setFragmentBytes:&uf length:sizeof(uf) atIndex:FrameUniformBuffer]; [mtlc.samplerManager setSamplerWithEncoder:encoder interpolation:interpolation repeat:repeat]; } @@ -956,8 +955,7 @@ setTxtUniforms(MTLContext *mtlc, int color, id encoder } else { setTxtUniforms(mtlc, 0, encoder, renderOptions->interpolation, NO, [mtlc.composite getExtraAlpha], - &renderOptions->srcFlags, - &renderOptions->dstFlags, 0); + &renderOptions->srcFlags, 0); } id pipelineState = [pipelineStateStorage getPipelineState:rpDesc @@ -998,7 +996,7 @@ setTxtUniforms(MTLContext *mtlc, int color, id encoder const int col = 0 ^ xorColor; setTxtUniforms(mtlc, col, encoder, renderOptions->interpolation, NO, [mtlc.composite getExtraAlpha], - &renderOptions->srcFlags, &renderOptions->dstFlags, 0); + &renderOptions->srcFlags, 0); [encoder setFragmentBytes:&xorColor length:sizeof(xorColor) atIndex: 0]; BMTLSDOps *dstOps = MTLRenderQueue_GetCurrentDestination(); @@ -1006,8 +1004,7 @@ setTxtUniforms(MTLContext *mtlc, int color, id encoder setTxtUniforms(mtlc, 0, encoder, renderOptions->interpolation, NO, [mtlc.composite getExtraAlpha], - &renderOptions->srcFlags, - &renderOptions->dstFlags, 0); + &renderOptions->srcFlags, 0); id pipelineState = [pipelineStateStorage getPipelineState:rpDesc vertexShaderId:vertShader diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLPipelineStatesStorage.m b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLPipelineStatesStorage.m index 0928f12d426958d74803eff3e1353a40ecad5b89..9a7862e8c263044cd1a1c9c8977add83640a3587 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLPipelineStatesStorage.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLPipelineStatesStorage.m @@ -84,7 +84,7 @@ static void setBlendingFactors( vertexShaderId:(NSString *)vertexShaderId fragmentShaderId:(NSString *)fragmentShaderId { - RenderOptions defaultOptions = {JNI_FALSE, JNI_FALSE, 0/*unused*/, {JNI_FALSE, JNI_TRUE}, {JNI_FALSE, JNI_TRUE}, JNI_FALSE, JNI_FALSE, JNI_FALSE}; + RenderOptions defaultOptions = {JNI_FALSE, JNI_FALSE, 0/*unused*/, {JNI_FALSE, JNI_TRUE}, JNI_FALSE, JNI_FALSE, JNI_FALSE}; return [self getPipelineState:pipelineDescriptor vertexShaderId:vertexShaderId fragmentShaderId:fragmentShaderId @@ -98,7 +98,7 @@ static void setBlendingFactors( fragmentShaderId:(NSString *)fragmentShaderId stencilNeeded:(bool)stencilNeeded { - RenderOptions defaultOptions = {JNI_FALSE, JNI_FALSE, 0/*unused*/, {JNI_FALSE, JNI_TRUE}, {JNI_FALSE, JNI_TRUE}, JNI_FALSE, JNI_FALSE, JNI_FALSE}; + RenderOptions defaultOptions = {JNI_FALSE, JNI_FALSE, 0/*unused*/, {JNI_FALSE, JNI_TRUE}, JNI_FALSE, JNI_FALSE, JNI_FALSE}; return [self getPipelineState:pipelineDescriptor vertexShaderId:vertexShaderId fragmentShaderId:fragmentShaderId @@ -107,6 +107,19 @@ static void setBlendingFactors( stencilNeeded:stencilNeeded]; } +// Pipeline state index +union StateIndex { + uint32_t value; + struct { + uint32_t srcPremultiplied : 1, + srcOpaque : 1, + stencil : 1, + aa : 1, + extAlpha : 1, + compositeRule : 27; + } bits; +}; + // Base method to obtain MTLRenderPipelineState. // NOTE: parameters compositeRule, srcFlags, dstFlags are used to set MTLRenderPipelineColorAttachmentDescriptor multipliers - (id) getPipelineState:(MTLRenderPipelineDescriptor *) pipelineDescriptor @@ -123,45 +136,31 @@ static void setBlendingFactors( // Calculate index by flags and compositeRule // TODO: reimplement, use map with convenient key (calculated by all arguments) - int subIndex = 0; + union StateIndex index; + index.value = 0; if (useXorComposite) { // compositeRule value is already XOR_COMPOSITE_RULE } else { if (useComposite) { - if (!renderOptions->srcFlags.isPremultiplied) - subIndex |= 1; - if (renderOptions->srcFlags.isOpaque) - subIndex |= 1 << 1; - if (!renderOptions->dstFlags.isPremultiplied) - subIndex |= 1 << 2; - if (renderOptions->dstFlags.isOpaque) - subIndex |= 1 << 3; + index.bits.srcPremultiplied = renderOptions->srcFlags.isPremultiplied; + index.bits.srcOpaque = renderOptions->srcFlags.isOpaque; } else compositeRule = RULE_Src; } - if (stencilNeeded) { - subIndex |= 1 << 4; - } - - if (renderOptions->isAA) { - subIndex |= 1 << 5; - } - - if ((composite != nil && FLT_LT([composite getExtraAlpha], 1.0f))) { - subIndex |= 1 << 6; - } - - int index = compositeRule*128 + subIndex; + index.bits.stencil = stencilNeeded; + index.bits.aa = renderOptions->isAA; + index.bits.extAlpha = composite != nil && FLT_LT([composite getExtraAlpha], 1.0f); + index.bits.compositeRule = compositeRule; NSPointerArray * subStates = [self getSubStates:vertexShaderId fragmentShader:fragmentShaderId]; - if (index >= subStates.count) { - subStates.count = (NSUInteger) (index + 1); + if (index.value >= subStates.count) { + subStates.count = index.value + 1; } - id result = [subStates pointerAtIndex:index]; + id result = [subStates pointerAtIndex:index.value]; if (result == nil) { @autoreleasepool { id vertexShader = [self getShader:vertexShaderId]; @@ -222,7 +221,7 @@ static void setBlendingFactors( exit(0); } - [subStates insertPointer:result atIndex:index]; + [subStates replacePointerAtIndex:index.value withPointer:result]; } } diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/RenderOptions.h b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/RenderOptions.h index 46521ca5b09a93d389cb96c6eb10d4131671d87f..f24f131631af88b6106e617a8032f2afa980172a 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/RenderOptions.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/RenderOptions.h @@ -35,7 +35,6 @@ typedef struct { jboolean isAA; int interpolation; SurfaceRasterFlags srcFlags; - SurfaceRasterFlags dstFlags; jboolean isText; jboolean isLCD; jboolean isAAShader; diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/common.h b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/common.h index 556bbf5d88ef4ded24a60900a1806f8baab6cf4a..70218f7e849c56a711d4771dd21278b20a40a263 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/common.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/common.h @@ -114,7 +114,6 @@ struct TxtFrameUniforms { vector_float4 color; int mode; // NOTE: consider to use bit fields int isSrcOpaque; - int isDstOpaque; float extraAlpha; }; diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageWriter.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageWriter.java index 6a020ae934354f4e8766b6f10e98122cdd9f7888..56c21e18548b539aec9b07fb908f58cc0b456eba 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageWriter.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -210,10 +210,8 @@ public class BMPImageWriter extends ImageWriter implements BMPConstants { IIOMetadata imageMetadata = image.getMetadata(); BMPMetadata bmpImageMetadata = null; - if (imageMetadata != null - && imageMetadata instanceof BMPMetadata) - { - bmpImageMetadata = (BMPMetadata)imageMetadata; + if (imageMetadata instanceof BMPMetadata bmp) { + bmpImageMetadata = bmp; } else { ImageTypeSpecifier imageType = new ImageTypeSpecifier(colorModel, sampleModel); diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/common/SimpleCMYKColorSpace.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/common/SimpleCMYKColorSpace.java index 95c4d9ec5970f045470e84ce1efbd5694ac0ef23..75586561598ad0cb7048647f6565df7867036640 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/common/SimpleCMYKColorSpace.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/common/SimpleCMYKColorSpace.java @@ -59,7 +59,7 @@ public final class SimpleCMYKColorSpace extends ColorSpace { } public boolean equals(Object o) { - return o != null && o instanceof SimpleCMYKColorSpace; + return o instanceof SimpleCMYKColorSpace; } public int hashCode() { diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/common/SubImageInputStream.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/common/SubImageInputStream.java index 8ddffc522f1873a8689e14a19ca0667d174d71e4..10211c6636c90bb572937f71794925fdbc21cff1 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/common/SubImageInputStream.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/common/SubImageInputStream.java @@ -72,7 +72,7 @@ public final class SubImageInputStream extends ImageInputStreamImpl { streamPos = pos; } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { // Empty finalizer (for improved performance; no need to call // super.finalize() in this case) diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFWritableImageMetadata.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFWritableImageMetadata.java index 8566d45f6a482dd62f64b6622f6d2905ea6d652a..a3e8a769490b7822efab8e63814930b01a1f8bce 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFWritableImageMetadata.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFWritableImageMetadata.java @@ -248,8 +248,7 @@ class GIFWritableImageMetadata extends GIFImageMetadata { Object applicationExtensionData = applicationExtension.getUserObject(); - if (applicationExtensionData == null || - !(applicationExtensionData instanceof byte[])) { + if (!(applicationExtensionData instanceof byte[])) { fatal(applicationExtension, "Bad user object in ApplicationExtension!"); } diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadata.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadata.java index ece1df86fcf50984241eab5c36666f7b67d498ae..a2fe287bc3dbef9dee20c63017d3873eddf07bad 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadata.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadata.java @@ -371,8 +371,8 @@ public class JPEGMetadata extends IIOMetadata implements Cloneable { JPEGImageWriteParam jparam = null; - if ((param != null) && (param instanceof JPEGImageWriteParam)) { - jparam = (JPEGImageWriteParam) param; + if (param instanceof JPEGImageWriteParam p) { + jparam = p; if (!jparam.areTablesSet()) { jparam = null; } diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java index 449661b8c91800b48d8c835dc52ff946a3a58866..ce6f771ecdceb539a4bc27562fbda1167cb429d0 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java @@ -147,7 +147,7 @@ final class ChunkStream extends ImageOutputStreamImpl { } @Override - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { // Empty finalizer (for improved performance; no need to call // super.finalize() in this case) @@ -284,7 +284,7 @@ final class IDATOutputStream extends ImageOutputStreamImpl { } @Override - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { // Empty finalizer (for improved performance; no need to call // super.finalize() in this case) diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFBaseJPEGCompressor.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFBaseJPEGCompressor.java index d78cb1cbdd9cc4c415cb89be01a7f9187c88e477..dba8d87816953a71c6cd094e663196dd9ffd65f2 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFBaseJPEGCompressor.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFBaseJPEGCompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -274,8 +274,8 @@ public abstract class TIFFBaseJPEGCompressor extends TIFFCompressor { // Initialize the ImageWriteParam. if(this.JPEGParam == null) { - if(param != null && param instanceof JPEGImageWriteParam) { - JPEGParam = (JPEGImageWriteParam)param; + if (param instanceof JPEGImageWriteParam p) { + JPEGParam = p; } else { JPEGParam = new JPEGImageWriteParam(writer != null ? @@ -435,7 +435,7 @@ public abstract class TIFFBaseJPEGCompressor extends TIFFCompressor { return compDataLength; } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { super.finalize(); if(JPEGWriter != null) { diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriter.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriter.java index 1d2cff4231105a04ed3239d8f604c54f6faeac22..07186c0deb5a24e33f837bf1e83ccdfab889424a 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriter.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriter.java @@ -2895,7 +2895,7 @@ public class TIFFImageWriter extends ImageWriter { int numThumbs = thumbnails.size(); for(int i = 0; i < numThumbs; i++) { Object thumb = thumbnails.get(i); - if(thumb == null || !(thumb instanceof BufferedImage)) { + if (!(thumb instanceof BufferedImage)) { throw new IllegalArgumentException ("thumbnails contains null references or objects other than BufferedImages!"); } diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFJPEGDecompressor.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFJPEGDecompressor.java index 384687f8344b104ac1d93287f7732f5927c77d8f..0b21835901b44621456e41188e3a2c8d256eb59e 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFJPEGDecompressor.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFJPEGDecompressor.java @@ -139,7 +139,7 @@ public class TIFFJPEGDecompressor extends TIFFDecompressor { JPEGReader.read(0, JPEGParam); } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { super.finalize(); JPEGReader.dispose(); diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFOldJPEGDecompressor.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFOldJPEGDecompressor.java index 67dd60f8a79a4480a8c4cf99b288f920e0cf0582..3cd89b396ccc007beec977d0db210194bc1ba53b 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFOldJPEGDecompressor.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFOldJPEGDecompressor.java @@ -610,7 +610,7 @@ public class TIFFOldJPEGDecompressor extends TIFFJPEGDecompressor { JPEGReader.read(0, JPEGParam); } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { super.finalize(); JPEGReader.dispose(); diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReader.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReader.java index 5676733e65f33fe13b0e342b15091ec09e512f82..ac62269b2d9b6456aeb8332a21d52fd4e6cdfb8d 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReader.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -244,8 +244,8 @@ public class WBMPImageReader extends ImageReader { } // If noTransform is necessary, read the data. - iis.read(((DataBufferByte)tile.getDataBuffer()).getData(), - 0, height*sm.getScanlineStride()); + iis.readFully(((DataBufferByte)tile.getDataBuffer()).getData(), + 0, height*sm.getScanlineStride()); processImageUpdate(bi, 0, 0, width, height, 1, 1, @@ -280,7 +280,7 @@ public class WBMPImageReader extends ImageReader { if (abortRequested()) break; - iis.read(buf, 0, len); + iis.readFully(buf, 0, len); for (int i = 0; i < destinationRegion.width; i++) { //get the bit and assign to the data buffer of the raster int v = (buf[srcPos[i]] >> srcOff[i]) & 1; diff --git a/src/java.desktop/share/classes/com/sun/imageio/stream/StreamFinalizer.java b/src/java.desktop/share/classes/com/sun/imageio/stream/StreamFinalizer.java index be1e659ee6e7784e1131d48f22a4d1846642c3c1..012d7e106459823b25b62310c06bd48296e370ea 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/stream/StreamFinalizer.java +++ b/src/java.desktop/share/classes/com/sun/imageio/stream/StreamFinalizer.java @@ -60,7 +60,7 @@ public class StreamFinalizer { this.stream = stream; } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { try { stream.close(); diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifFileChooserUI.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifFileChooserUI.java index fcb9e724febc603974d113416c3dee647af85d0a..847fbf4117d4cda0caa99fbc1f1f00660f1bd3e1 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifFileChooserUI.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifFileChooserUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -787,8 +787,8 @@ public class MotifFileChooserUI extends BasicFileChooserUI { super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); - if (value != null && value instanceof FileFilter) { - setText(((FileFilter)value).getDescription()); + if (value instanceof FileFilter fileFilter) { + setText(fileFilter.getDescription()); } return this; diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifMenuUI.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifMenuUI.java index eaeb5b2ab662e1aea28429a2b89bb618229a9aec..bcee2e666fa682df552602a44850b555003773bd 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifMenuUI.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifMenuUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -110,10 +110,10 @@ public class MotifMenuUI extends BasicMenuUI manager.clearSelectedPath(); } else { Container cnt = menu.getParent(); - if(cnt != null && cnt instanceof JMenuBar) { + if (cnt instanceof JMenuBar menuBar) { MenuElement[] me = new MenuElement[2]; - me[0]=(MenuElement)cnt; - me[1]=menu; + me[0] = menuBar; + me[1] = menu; manager.setSelectedPath(me); } } diff --git a/src/java.desktop/share/classes/com/sun/media/sound/AbstractMidiDevice.java b/src/java.desktop/share/classes/com/sun/media/sound/AbstractMidiDevice.java index 52588387a788120a248781a38bdeb23ab8ad5005..3ba4ce2ed366b13eb76709bcf4f8eb4bd707fd3e 100644 --- a/src/java.desktop/share/classes/com/sun/media/sound/AbstractMidiDevice.java +++ b/src/java.desktop/share/classes/com/sun/media/sound/AbstractMidiDevice.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -425,7 +425,7 @@ abstract class AbstractMidiDevice implements MidiDevice, ReferenceCountingDevice * close this device if discarded by the garbage collector. */ @Override - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected final void finalize() { close(); } @@ -576,11 +576,9 @@ abstract class AbstractMidiDevice implements MidiDevice, ReferenceCountingDevice if (midiOutReceiver == oldR) { midiOutReceiver = null; } - if (newR != null) { - if ((newR instanceof MidiOutDevice.MidiOutReceiver) + if ((newR instanceof MidiOutDevice.MidiOutReceiver newReceiver) && (midiOutReceiver == null)) { - midiOutReceiver = ((MidiOutDevice.MidiOutReceiver) newR); - } + midiOutReceiver = newReceiver; } optimizedReceiverCount = ((midiOutReceiver!=null)?1:0); diff --git a/src/java.desktop/share/classes/com/sun/media/sound/AudioFloatFormatConverter.java b/src/java.desktop/share/classes/com/sun/media/sound/AudioFloatFormatConverter.java index 6dbbb3384506580f36947d8de7e8c247f5a48ccc..cb0dcf9df7e0eca50f661358c4b302446d25dcca 100644 --- a/src/java.desktop/share/classes/com/sun/media/sound/AudioFloatFormatConverter.java +++ b/src/java.desktop/share/classes/com/sun/media/sound/AudioFloatFormatConverter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -293,8 +293,7 @@ public final class AudioFloatFormatConverter extends FormatConversionProvider { format.getSampleRate(), sourceFormat.isBigEndian()); nrofchannels = targetFormat.getChannels(); Object interpolation = format.getProperty("interpolation"); - if (interpolation != null && (interpolation instanceof String)) { - String resamplerType = (String) interpolation; + if (interpolation instanceof String resamplerType) { if (resamplerType.equalsIgnoreCase("point")) this.resampler = new SoftPointResampler(); if (resamplerType.equalsIgnoreCase("linear")) diff --git a/src/java.desktop/share/classes/com/sun/media/sound/JavaSoundAudioClip.java b/src/java.desktop/share/classes/com/sun/media/sound/JavaSoundAudioClip.java index bc2f87fe33f04797bbde82e52870dd0ea6e1d4dc..c804a0e49c225ff1a0b852c54479d9dd71d41df7 100644 --- a/src/java.desktop/share/classes/com/sun/media/sound/JavaSoundAudioClip.java +++ b/src/java.desktop/share/classes/com/sun/media/sound/JavaSoundAudioClip.java @@ -283,6 +283,7 @@ public final class JavaSoundAudioClip implements AudioClip, MetaEventListener, L } @Override + @SuppressWarnings("removal") protected void finalize() { if (clip != null) { diff --git a/src/java.desktop/share/classes/com/sun/media/sound/PortMixer.java b/src/java.desktop/share/classes/com/sun/media/sound/PortMixer.java index 5f2c24788d399a40953a3984248c506604ec3279..099067f3ad62ee9d54ce6ead5e42b67753e719fe 100644 --- a/src/java.desktop/share/classes/com/sun/media/sound/PortMixer.java +++ b/src/java.desktop/share/classes/com/sun/media/sound/PortMixer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -115,7 +115,7 @@ final class PortMixer extends AbstractMixer { public Line getLine(Line.Info info) throws LineUnavailableException { Line.Info fullInfo = getLineInfo(info); - if ((fullInfo != null) && (fullInfo instanceof Port.Info)) { + if (fullInfo instanceof Port.Info) { for (int i = 0; i < portInfos.length; i++) { if (fullInfo.equals(portInfos[i])) { return getPort(i); diff --git a/src/java.desktop/share/classes/com/sun/media/sound/SoftMixingDataLine.java b/src/java.desktop/share/classes/com/sun/media/sound/SoftMixingDataLine.java index 99962841c8fe117078ae628b8f9a4ee2b6e73b1d..4ba5e61487489a5de915cd97d43a95990d190fef 100644 --- a/src/java.desktop/share/classes/com/sun/media/sound/SoftMixingDataLine.java +++ b/src/java.desktop/share/classes/com/sun/media/sound/SoftMixingDataLine.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -102,8 +102,7 @@ public abstract class SoftMixingDataLine implements DataLine { format.getSampleRate(), sourceFormat.isBigEndian()); nrofchannels = targetFormat.getChannels(); Object interpolation = format.getProperty("interpolation"); - if (interpolation != null && (interpolation instanceof String)) { - String resamplerType = (String) interpolation; + if (interpolation instanceof String resamplerType) { if (resamplerType.equalsIgnoreCase("point")) this.resampler = new SoftPointResampler(); if (resamplerType.equalsIgnoreCase("linear")) diff --git a/src/java.desktop/share/classes/com/sun/media/sound/SoftSynthesizer.java b/src/java.desktop/share/classes/com/sun/media/sound/SoftSynthesizer.java index 9d73c68e6ade115101cbc63175f1f93d9cf3ad60..c2642436fe4d10947ecaef7f8715abb4c0870f55 100644 --- a/src/java.desktop/share/classes/com/sun/media/sound/SoftSynthesizer.java +++ b/src/java.desktop/share/classes/com/sun/media/sound/SoftSynthesizer.java @@ -574,25 +574,25 @@ public final class SoftSynthesizer implements AudioSynthesizer, @Override public boolean loadInstrument(Instrument instrument) { - if (instrument == null || (!(instrument instanceof ModelInstrument))) { + if (!(instrument instanceof ModelInstrument modelInstrument)) { throw new IllegalArgumentException("Unsupported instrument: " + instrument); } List instruments = new ArrayList<>(); - instruments.add((ModelInstrument)instrument); + instruments.add(modelInstrument); return loadInstruments(instruments); } @Override public void unloadInstrument(Instrument instrument) { - if (instrument == null || (!(instrument instanceof ModelInstrument))) { + if (!(instrument instanceof ModelInstrument modelInstrument)) { throw new IllegalArgumentException("Unsupported instrument: " + instrument); } if (!isOpen()) return; - String pat = patchToString(instrument.getPatch()); + String pat = patchToString(modelInstrument.getPatch()); synchronized (control_mutex) { for (SoftChannel c: channels) c.current_instrument = null; @@ -841,11 +841,11 @@ public final class SoftSynthesizer implements AudioSynthesizer, public boolean loadAllInstruments(Soundbank soundbank) { List instruments = new ArrayList<>(); for (Instrument ins: soundbank.getInstruments()) { - if (ins == null || !(ins instanceof ModelInstrument)) { + if (!(ins instanceof ModelInstrument modelInstrument)) { throw new IllegalArgumentException( "Unsupported instrument: " + ins); } - instruments.add((ModelInstrument)ins); + instruments.add(modelInstrument); } return loadInstruments(instruments); } @@ -870,11 +870,11 @@ public final class SoftSynthesizer implements AudioSynthesizer, List instruments = new ArrayList<>(); for (Patch patch: patchList) { Instrument ins = soundbank.getInstrument(patch); - if (ins == null || !(ins instanceof ModelInstrument)) { + if (!(ins instanceof ModelInstrument modelInstrument)) { throw new IllegalArgumentException( "Unsupported instrument: " + ins); } - instruments.add((ModelInstrument)ins); + instruments.add(modelInstrument); } return loadInstruments(instruments); } diff --git a/src/java.desktop/share/classes/java/awt/AWTEvent.java b/src/java.desktop/share/classes/java/awt/AWTEvent.java index 404a4fb221ba88d51c39ca2e77d76cddf461bdab..93def2fadc9fdf69cdb05bd762341f9e769424d4 100644 --- a/src/java.desktop/share/classes/java/awt/AWTEvent.java +++ b/src/java.desktop/share/classes/java/awt/AWTEvent.java @@ -355,8 +355,7 @@ public abstract class AWTEvent extends EventObject { Component comp = null; if (newSource instanceof Component) { comp = (Component)newSource; - while (comp != null && comp.peer != null && - (comp.peer instanceof LightweightPeer)) { + while (comp != null && (comp.peer instanceof LightweightPeer)) { comp = comp.parent; } } diff --git a/src/java.desktop/share/classes/java/awt/BufferCapabilities.java b/src/java.desktop/share/classes/java/awt/BufferCapabilities.java index 18c3d725b369eda5ab3c13ec54a254e8a6bc4466..8d2288023b54272084dd6072ce9ab134dfc187bd 100644 --- a/src/java.desktop/share/classes/java/awt/BufferCapabilities.java +++ b/src/java.desktop/share/classes/java/awt/BufferCapabilities.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,7 @@ package java.awt; * @author Michael Martak * @since 1.4 */ +@SuppressWarnings("doclint:missing") public class BufferCapabilities implements Cloneable { private ImageCapabilities frontCaps; diff --git a/src/java.desktop/share/classes/java/awt/Component.java b/src/java.desktop/share/classes/java/awt/Component.java index c8930123c0bb0c978cdd73efcf04fcb183650060..2378588b03385c21d568c613f44fa3d0aec4ccac 100644 --- a/src/java.desktop/share/classes/java/awt/Component.java +++ b/src/java.desktop/share/classes/java/awt/Component.java @@ -214,6 +214,7 @@ import static sun.java2d.pipe.hw.ExtendedBufferCapabilities.VSyncType.VSYNC_ON; * @author Arthur van Hoff * @author Sami Shaio */ +@SuppressWarnings("doclint:missing") public abstract class Component implements ImageObserver, MenuContainer, Serializable { @@ -4944,8 +4945,8 @@ public abstract class Component implements ImageObserver, MenuContainer, // the active/passive/peered clients loose focus. if (id == FocusEvent.FOCUS_GAINED) { InputContext inputContext = getInputContext(); - if (inputContext != null && inputContext instanceof sun.awt.im.InputContext) { - ((sun.awt.im.InputContext)inputContext).disableNativeIM(); + if (inputContext instanceof sun.awt.im.InputContext ctx) { + ctx.disableNativeIM(); } } } diff --git a/src/java.desktop/share/classes/java/awt/Container.java b/src/java.desktop/share/classes/java/awt/Container.java index 68270d35adae69e00ca9043e2d5fa06a86abdc38..5b4489f3cac037367281592b11af7f29702c7b2c 100644 --- a/src/java.desktop/share/classes/java/awt/Container.java +++ b/src/java.desktop/share/classes/java/awt/Container.java @@ -3891,18 +3891,18 @@ public class Container extends Component { public void componentAdded(ContainerEvent e) { Component c = e.getChild(); - if (c != null && c instanceof Accessible) { + if (c instanceof Accessible accessible) { AccessibleAWTContainer.this.firePropertyChange( AccessibleContext.ACCESSIBLE_CHILD_PROPERTY, - null, ((Accessible) c).getAccessibleContext()); + null, accessible.getAccessibleContext()); } } public void componentRemoved(ContainerEvent e) { Component c = e.getChild(); - if (c != null && c instanceof Accessible) { + if (c instanceof Accessible accessible) { AccessibleAWTContainer.this.firePropertyChange( AccessibleContext.ACCESSIBLE_CHILD_PROPERTY, - ((Accessible) c).getAccessibleContext(), null); + accessible.getAccessibleContext(), null); } } } diff --git a/src/java.desktop/share/classes/java/awt/Graphics.java b/src/java.desktop/share/classes/java/awt/Graphics.java index 51cdd6a88da30d1f732fb09f58d621897c5e8d28..5ed31aeadb0565e5d14cbf539843c07f0d4ac1d8 100644 --- a/src/java.desktop/share/classes/java/awt/Graphics.java +++ b/src/java.desktop/share/classes/java/awt/Graphics.java @@ -1162,17 +1162,14 @@ public abstract class Graphics { /** * Disposes of this graphics context once it is no longer referenced. * - * @deprecated The {@code finalize} method has been deprecated. - * Subclasses that override {@code finalize} in order to perform cleanup - * should be modified to use alternative cleanup mechanisms and - * to remove the overriding {@code finalize} method. - * When overriding the {@code finalize} method, its implementation must explicitly - * ensure that {@code super.finalize()} is invoked as described in {@link Object#finalize}. - * See the specification for {@link Object#finalize()} for further - * information about migration options. + * @deprecated Finalization has been deprecated for removal. See + * {@link java.lang.Object#finalize} for background information and details + * about migration options. + * * @see #dispose */ - @Deprecated(since="9") + @Deprecated(since="9", forRemoval=true) + @SuppressWarnings("removal") public void finalize() { dispose(); } diff --git a/src/java.desktop/share/classes/java/awt/MenuComponent.java b/src/java.desktop/share/classes/java/awt/MenuComponent.java index e66b5867b239825f45f8b788edbb223e9689aca9..0e7ab46cedf0391c0dfd0c1d77f4c673116db5d3 100644 --- a/src/java.desktop/share/classes/java/awt/MenuComponent.java +++ b/src/java.desktop/share/classes/java/awt/MenuComponent.java @@ -373,8 +373,7 @@ public abstract class MenuComponent implements java.io.Serializable { Toolkit.getDefaultToolkit().notifyAWTEventListeners(e); if (newEventsOnly || - (parent != null && parent instanceof MenuComponent && - ((MenuComponent)parent).newEventsOnly)) { + (parent instanceof MenuComponent mc && mc.newEventsOnly)) { if (eventEnabled(e)) { processEvent(e); } else if (e instanceof ActionEvent && parent != null) { diff --git a/src/java.desktop/share/classes/java/awt/PrintJob.java b/src/java.desktop/share/classes/java/awt/PrintJob.java index a9e2bd8bea29aa1fb9eabf8962117548349e17e8..f4ea24efd97b383dd3d054320c8db8de5259f5a4 100644 --- a/src/java.desktop/share/classes/java/awt/PrintJob.java +++ b/src/java.desktop/share/classes/java/awt/PrintJob.java @@ -85,17 +85,14 @@ public abstract class PrintJob { /** * Ends this print job once it is no longer referenced. * - * @deprecated The {@code finalize} method has been deprecated. - * Subclasses that override {@code finalize} in order to perform cleanup - * should be modified to use alternative cleanup mechanisms and - * to remove the overriding {@code finalize} method. - * When overriding the {@code finalize} method, its implementation must explicitly - * ensure that {@code super.finalize()} is invoked as described in {@link Object#finalize}. - * See the specification for {@link Object#finalize()} for further - * information about migration options. + * @deprecated Finalization has been deprecated for removal. See + * {@link java.lang.Object#finalize} for background information and details + * about migration options. + * * @see #end */ - @Deprecated(since="9") + @Deprecated(since="9", forRemoval=true) + @SuppressWarnings("removal") public void finalize() { end(); } diff --git a/src/java.desktop/share/classes/java/awt/dnd/DropTarget.java b/src/java.desktop/share/classes/java/awt/dnd/DropTarget.java index a05dbdebad26f72fb3d7aa2f0bed5fa9d2dd2fe8..7ba9c9711da065fa8a1950c3663d0fd71bdfa921 100644 --- a/src/java.desktop/share/classes/java/awt/dnd/DropTarget.java +++ b/src/java.desktop/share/classes/java/awt/dnd/DropTarget.java @@ -793,7 +793,7 @@ public class DropTarget implements DropTargetListener, Serializable { */ protected void initializeAutoscrolling(Point p) { - if (component == null || !(component instanceof Autoscroll)) return; + if (!(component instanceof Autoscroll)) return; autoScroller = createDropTargetAutoScroller(component, p); } diff --git a/src/java.desktop/share/classes/java/awt/event/KeyEvent.java b/src/java.desktop/share/classes/java/awt/event/KeyEvent.java index 53b3bf9c9f1838120fb930c7788ee470fee97fb4..f416719fd2ec9498c65658e83212d9299e83eb88 100644 --- a/src/java.desktop/share/classes/java/awt/event/KeyEvent.java +++ b/src/java.desktop/share/classes/java/awt/event/KeyEvent.java @@ -151,6 +151,7 @@ import sun.awt.AWTAccessor; * * @since 1.1 */ +@SuppressWarnings("doclint:missing") public class KeyEvent extends InputEvent { /** diff --git a/src/java.desktop/share/classes/java/awt/image/AreaAveragingScaleFilter.java b/src/java.desktop/share/classes/java/awt/image/AreaAveragingScaleFilter.java index decfeb33622fdddb2f332cae245a13753f76e5ba..9e3434d4eed06d4ba13f9983c47d97f905d0afe1 100644 --- a/src/java.desktop/share/classes/java/awt/image/AreaAveragingScaleFilter.java +++ b/src/java.desktop/share/classes/java/awt/image/AreaAveragingScaleFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -105,7 +105,7 @@ public class AreaAveragingScaleFilter extends ReplicateScaleFilter { private int[] calcRow() { float origmult = ((float) srcWidth) * srcHeight; - if (outpixbuf == null || !(outpixbuf instanceof int[])) { + if (!(outpixbuf instanceof int[])) { outpixbuf = new int[destWidth]; } int[] outpix = (int[]) outpixbuf; diff --git a/src/java.desktop/share/classes/java/awt/image/ComponentSampleModel.java b/src/java.desktop/share/classes/java/awt/image/ComponentSampleModel.java index f8f6ffff56ea945c2772996e43f9c85f68dfa89a..9e0a8548eb04e9715855fc1d5886f9bbdea56a71 100644 --- a/src/java.desktop/share/classes/java/awt/image/ComponentSampleModel.java +++ b/src/java.desktop/share/classes/java/awt/image/ComponentSampleModel.java @@ -1185,11 +1185,10 @@ public class ComponentSampleModel extends SampleModel } public boolean equals(Object o) { - if ((o == null) || !(o instanceof ComponentSampleModel)) { + if (!(o instanceof ComponentSampleModel that)) { return false; } - ComponentSampleModel that = (ComponentSampleModel)o; return this.width == that.width && this.height == that.height && this.numBands == that.numBands && diff --git a/src/java.desktop/share/classes/java/awt/image/MultiPixelPackedSampleModel.java b/src/java.desktop/share/classes/java/awt/image/MultiPixelPackedSampleModel.java index 6a4aff4a39bff252a8f1f5861edcda9072a73064..dcec78fb34833e0ff4c308c6c1487922ebf58227 100644 --- a/src/java.desktop/share/classes/java/awt/image/MultiPixelPackedSampleModel.java +++ b/src/java.desktop/share/classes/java/awt/image/MultiPixelPackedSampleModel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -655,11 +655,10 @@ public class MultiPixelPackedSampleModel extends SampleModel } public boolean equals(Object o) { - if ((o == null) || !(o instanceof MultiPixelPackedSampleModel)) { + if (!(o instanceof MultiPixelPackedSampleModel that)) { return false; } - MultiPixelPackedSampleModel that = (MultiPixelPackedSampleModel)o; return this.width == that.width && this.height == that.height && this.numBands == that.numBands && diff --git a/src/java.desktop/share/classes/java/awt/image/ReplicateScaleFilter.java b/src/java.desktop/share/classes/java/awt/image/ReplicateScaleFilter.java index 10ba0842772b36e36995f1b0eedcf5d2dc7db9df..a92a77e422ef2a4f6c89a1b398596c6f7f139790 100644 --- a/src/java.desktop/share/classes/java/awt/image/ReplicateScaleFilter.java +++ b/src/java.desktop/share/classes/java/awt/image/ReplicateScaleFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -126,8 +126,8 @@ public class ReplicateScaleFilter extends ImageFilter { String key = "rescale"; String val = destWidth + "x" + destHeight; Object o = p.get(key); - if (o != null && o instanceof String) { - val = ((String) o) + ", " + val; + if (o instanceof String s) { + val = s + ", " + val; } p.put(key, val); super.setProperties(p); @@ -194,8 +194,8 @@ public class ReplicateScaleFilter extends ImageFilter { int dx1 = (2 * x * destWidth + srcWidth - 1) / (2 * srcWidth); int dy1 = (2 * y * destHeight + srcHeight - 1) / (2 * srcHeight); byte[] outpix; - if (outpixbuf != null && outpixbuf instanceof byte[]) { - outpix = (byte[]) outpixbuf; + if (outpixbuf instanceof byte[] outbytes) { + outpix = outbytes; } else { outpix = new byte[destWidth]; outpixbuf = outpix; @@ -235,8 +235,8 @@ public class ReplicateScaleFilter extends ImageFilter { int dx1 = (2 * x * destWidth + srcWidth - 1) / (2 * srcWidth); int dy1 = (2 * y * destHeight + srcHeight - 1) / (2 * srcHeight); int[] outpix; - if (outpixbuf != null && outpixbuf instanceof int[]) { - outpix = (int[]) outpixbuf; + if (outpixbuf instanceof int[] outints) { + outpix = outints; } else { outpix = new int[destWidth]; outpixbuf = outpix; diff --git a/src/java.desktop/share/classes/java/awt/image/SinglePixelPackedSampleModel.java b/src/java.desktop/share/classes/java/awt/image/SinglePixelPackedSampleModel.java index dd9b898e46faab8fc08f4ef9a96d813fdcd6c718..864ed00cf7617590c71d9de8fc59c50c219d1b1e 100644 --- a/src/java.desktop/share/classes/java/awt/image/SinglePixelPackedSampleModel.java +++ b/src/java.desktop/share/classes/java/awt/image/SinglePixelPackedSampleModel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -754,11 +754,10 @@ public class SinglePixelPackedSampleModel extends SampleModel } public boolean equals(Object o) { - if ((o == null) || !(o instanceof SinglePixelPackedSampleModel)) { + if (!(o instanceof SinglePixelPackedSampleModel that)) { return false; } - SinglePixelPackedSampleModel that = (SinglePixelPackedSampleModel)o; return this.width == that.width && this.height == that.height && this.numBands == that.numBands && diff --git a/src/java.desktop/share/classes/java/beans/IndexedPropertyDescriptor.java b/src/java.desktop/share/classes/java/beans/IndexedPropertyDescriptor.java index ebeff6c443887a8c8322aae96e3f4b2666469ce2..b49b1cb07a950673185fe6fcfca011f347fa5a16 100644 --- a/src/java.desktop/share/classes/java/beans/IndexedPropertyDescriptor.java +++ b/src/java.desktop/share/classes/java/beans/IndexedPropertyDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -407,8 +407,7 @@ public class IndexedPropertyDescriptor extends PropertyDescriptor { return true; } - if (obj != null && obj instanceof IndexedPropertyDescriptor) { - IndexedPropertyDescriptor other = (IndexedPropertyDescriptor)obj; + if (obj instanceof IndexedPropertyDescriptor other) { Method otherIndexedReadMethod = other.getIndexedReadMethod(); Method otherIndexedWriteMethod = other.getIndexedWriteMethod(); diff --git a/src/java.desktop/share/classes/java/beans/PropertyDescriptor.java b/src/java.desktop/share/classes/java/beans/PropertyDescriptor.java index 373b7ad6fff44c428e054a82840421b1cc786957..d63c446f37375e8b9af3f28fc9167998cdc99290 100644 --- a/src/java.desktop/share/classes/java/beans/PropertyDescriptor.java +++ b/src/java.desktop/share/classes/java/beans/PropertyDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -503,8 +503,7 @@ public class PropertyDescriptor extends FeatureDescriptor { if (this == obj) { return true; } - if (obj != null && obj instanceof PropertyDescriptor) { - PropertyDescriptor other = (PropertyDescriptor)obj; + if (obj instanceof PropertyDescriptor other) { Method otherReadMethod = other.getReadMethod(); Method otherWriteMethod = other.getWriteMethod(); diff --git a/src/java.desktop/share/classes/java/beans/beancontext/BeanContextServicesSupport.java b/src/java.desktop/share/classes/java/beans/beancontext/BeanContextServicesSupport.java index 878c489e0f6fe0d84fdc55bccd4af7653466c491..d3e6c6ea87a485715b543b57846e4e0156d97290 100644 --- a/src/java.desktop/share/classes/java/beans/beancontext/BeanContextServicesSupport.java +++ b/src/java.desktop/share/classes/java/beans/beancontext/BeanContextServicesSupport.java @@ -54,7 +54,7 @@ import java.util.TooManyListenersException; * @author Laurence P. G. Cable * @since 1.2 */ - +@SuppressWarnings("doclint:missing") public class BeanContextServicesSupport extends BeanContextSupport implements BeanContextServices { diff --git a/src/java.desktop/share/classes/java/beans/beancontext/BeanContextSupport.java b/src/java.desktop/share/classes/java/beans/beancontext/BeanContextSupport.java index 58e05f7708410bd013ad9b83b6ee017065da87c9..e5e53db3dfe6edfd8de96fb43eb86afc15f0b511 100644 --- a/src/java.desktop/share/classes/java/beans/beancontext/BeanContextSupport.java +++ b/src/java.desktop/share/classes/java/beans/beancontext/BeanContextSupport.java @@ -59,6 +59,7 @@ import java.util.Map; * @author Laurence P. G. Cable * @since 1.2 */ +@SuppressWarnings("doclint:missing") public class BeanContextSupport extends BeanContextChildSupport implements BeanContext, Serializable, diff --git a/src/java.desktop/share/classes/javax/imageio/ImageTypeSpecifier.java b/src/java.desktop/share/classes/javax/imageio/ImageTypeSpecifier.java index e50958f17572f95658965e969fcdb18777290ccc..e328d7499bcd28be7794db995a9c1cfc5116a9d0 100644 --- a/src/java.desktop/share/classes/javax/imageio/ImageTypeSpecifier.java +++ b/src/java.desktop/share/classes/javax/imageio/ImageTypeSpecifier.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -328,14 +328,10 @@ public class ImageTypeSpecifier { } public boolean equals(Object o) { - if ((o == null) || - !(o instanceof ImageTypeSpecifier.Interleaved)) { + if (!(o instanceof Interleaved that)) { return false; } - ImageTypeSpecifier.Interleaved that = - (ImageTypeSpecifier.Interleaved)o; - if ((!(this.colorSpace.equals(that.colorSpace))) || (this.dataType != that.dataType) || (this.hasAlpha != that.hasAlpha) || @@ -472,14 +468,10 @@ public class ImageTypeSpecifier { } public boolean equals(Object o) { - if ((o == null) || - !(o instanceof ImageTypeSpecifier.Banded)) { + if (!(o instanceof Banded that)) { return false; } - ImageTypeSpecifier.Banded that = - (ImageTypeSpecifier.Banded)o; - if ((!(this.colorSpace.equals(that.colorSpace))) || (this.dataType != that.dataType) || (this.hasAlpha != that.hasAlpha) || @@ -1095,11 +1087,10 @@ public class ImageTypeSpecifier { * {@code ImageTypeSpecifier}. */ public boolean equals(Object o) { - if ((o == null) || !(o instanceof ImageTypeSpecifier)) { + if (!(o instanceof ImageTypeSpecifier that)) { return false; } - ImageTypeSpecifier that = (ImageTypeSpecifier)o; return (colorModel.equals(that.colorModel)) && (sampleModel.equals(that.sampleModel)); } diff --git a/src/java.desktop/share/classes/javax/imageio/spi/ServiceRegistry.java b/src/java.desktop/share/classes/javax/imageio/spi/ServiceRegistry.java index 741ca55c5010efa9dbae99e6ec7c6e7b19387a72..4a43ca8133a5b7d14f12d270021441896dca8c21 100644 --- a/src/java.desktop/share/classes/javax/imageio/spi/ServiceRegistry.java +++ b/src/java.desktop/share/classes/javax/imageio/spi/ServiceRegistry.java @@ -680,16 +680,12 @@ public class ServiceRegistry { * @exception Throwable if an error occurs during superclass * finalization. * - * @deprecated The {@code finalize} method has been deprecated. - * Subclasses that override {@code finalize} in order to perform cleanup - * should be modified to use alternative cleanup mechanisms and - * to remove the overriding {@code finalize} method. - * When overriding the {@code finalize} method, its implementation must explicitly - * ensure that {@code super.finalize()} is invoked as described in {@link Object#finalize}. - * See the specification for {@link Object#finalize()} for further - * information about migration options. + * @deprecated Finalization has been deprecated for removal. See + * {@link java.lang.Object#finalize} for background information and details + * about migration options. */ - @Deprecated(since="9") + @Deprecated(since="9", forRemoval=true) + @SuppressWarnings("removal") public void finalize() throws Throwable { deregisterAll(); super.finalize(); @@ -842,7 +838,7 @@ class SubRegistry { accMap.clear(); } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") public synchronized void finalize() { clear(); } diff --git a/src/java.desktop/share/classes/javax/imageio/stream/FileCacheImageInputStream.java b/src/java.desktop/share/classes/javax/imageio/stream/FileCacheImageInputStream.java index e597490016123cfb7de02b451ca375e131d96c9f..6bf14838b7fc42d0e4ee853e9ff9f710033ec228 100644 --- a/src/java.desktop/share/classes/javax/imageio/stream/FileCacheImageInputStream.java +++ b/src/java.desktop/share/classes/javax/imageio/stream/FileCacheImageInputStream.java @@ -261,16 +261,12 @@ public class FileCacheImageInputStream extends ImageInputStreamImpl { /** * {@inheritDoc} * - * @deprecated The {@code finalize} method has been deprecated. - * Subclasses that override {@code finalize} in order to perform cleanup - * should be modified to use alternative cleanup mechanisms and - * to remove the overriding {@code finalize} method. - * When overriding the {@code finalize} method, its implementation must explicitly - * ensure that {@code super.finalize()} is invoked as described in {@link Object#finalize}. - * See the specification for {@link Object#finalize()} for further - * information about migration options. + * @deprecated Finalization has been deprecated for removal. See + * {@link java.lang.Object#finalize} for background information and details + * about migration options. */ - @Deprecated(since="9") + @Deprecated(since="9", forRemoval=true) + @SuppressWarnings("removal") protected void finalize() throws Throwable { // Empty finalizer: for performance reasons we instead use the // Disposer mechanism for ensuring that the underlying diff --git a/src/java.desktop/share/classes/javax/imageio/stream/FileImageInputStream.java b/src/java.desktop/share/classes/javax/imageio/stream/FileImageInputStream.java index 7ecc28767a0284881d37335ea094e0548604ed61..b1cce6fae4cc64bd98db88d535e8cb088b9478f6 100644 --- a/src/java.desktop/share/classes/javax/imageio/stream/FileImageInputStream.java +++ b/src/java.desktop/share/classes/javax/imageio/stream/FileImageInputStream.java @@ -156,16 +156,12 @@ public class FileImageInputStream extends ImageInputStreamImpl { /** * {@inheritDoc} * - * @deprecated The {@code finalize} method has been deprecated. - * Subclasses that override {@code finalize} in order to perform cleanup - * should be modified to use alternative cleanup mechanisms and - * to remove the overriding {@code finalize} method. - * When overriding the {@code finalize} method, its implementation must explicitly - * ensure that {@code super.finalize()} is invoked as described in {@link Object#finalize}. - * See the specification for {@link Object#finalize()} for further - * information about migration options. + * @deprecated Finalization has been deprecated for removal. See + * {@link java.lang.Object#finalize} for background information and details + * about migration options. */ - @Deprecated(since="9") + @Deprecated(since="9", forRemoval=true) + @SuppressWarnings("removal") protected void finalize() throws Throwable { // Empty finalizer: for performance reasons we instead use the // Disposer mechanism for ensuring that the underlying diff --git a/src/java.desktop/share/classes/javax/imageio/stream/FileImageOutputStream.java b/src/java.desktop/share/classes/javax/imageio/stream/FileImageOutputStream.java index e75c40396d8157a1957f75e27ffd887f06c006a7..715b43f40fb764aa4b3df57941cef1959c7029d6 100644 --- a/src/java.desktop/share/classes/javax/imageio/stream/FileImageOutputStream.java +++ b/src/java.desktop/share/classes/javax/imageio/stream/FileImageOutputStream.java @@ -164,16 +164,12 @@ public class FileImageOutputStream extends ImageOutputStreamImpl { /** * {@inheritDoc} * - * @deprecated The {@code finalize} method has been deprecated. - * Subclasses that override {@code finalize} in order to perform cleanup - * should be modified to use alternative cleanup mechanisms and - * to remove the overriding {@code finalize} method. - * When overriding the {@code finalize} method, its implementation must explicitly - * ensure that {@code super.finalize()} is invoked as described in {@link Object#finalize}. - * See the specification for {@link Object#finalize()} for further - * information about migration options. + * @deprecated Finalization has been deprecated for removal. See + * {@link java.lang.Object#finalize} for background information and details + * about migration options. */ - @Deprecated(since="9") + @Deprecated(since="9", forRemoval=true) + @SuppressWarnings("removal") protected void finalize() throws Throwable { // Empty finalizer: for performance reasons we instead use the // Disposer mechanism for ensuring that the underlying diff --git a/src/java.desktop/share/classes/javax/imageio/stream/ImageInputStreamImpl.java b/src/java.desktop/share/classes/javax/imageio/stream/ImageInputStreamImpl.java index c7cdc47cdafc3698312db86ea154b65573f78a68..053bbf7491826e852d0b0f466f68edf37841e0f7 100644 --- a/src/java.desktop/share/classes/javax/imageio/stream/ImageInputStreamImpl.java +++ b/src/java.desktop/share/classes/javax/imageio/stream/ImageInputStreamImpl.java @@ -868,16 +868,12 @@ public abstract class ImageInputStreamImpl implements ImageInputStream { * @exception Throwable if an error occurs during superclass * finalization. * - * @deprecated The {@code finalize} method has been deprecated. - * Subclasses that override {@code finalize} in order to perform cleanup - * should be modified to use alternative cleanup mechanisms and - * to remove the overriding {@code finalize} method. - * When overriding the {@code finalize} method, its implementation must explicitly - * ensure that {@code super.finalize()} is invoked as described in {@link Object#finalize}. - * See the specification for {@link Object#finalize()} for further - * information about migration options. + * @deprecated Finalization has been deprecated for removal. See + * {@link java.lang.Object#finalize} for background information and details + * about migration options. */ - @Deprecated(since="9") + @Deprecated(since="9", forRemoval=true) + @SuppressWarnings("removal") protected void finalize() throws Throwable { if (!isClosed) { try { diff --git a/src/java.desktop/share/classes/javax/imageio/stream/MemoryCacheImageInputStream.java b/src/java.desktop/share/classes/javax/imageio/stream/MemoryCacheImageInputStream.java index 4fcb0f40b8171a3e136bc30bfe5fc6abf0670af8..44b9d8cd5fbf9c0b3ce2130da8ed12b1bb9dd9f8 100644 --- a/src/java.desktop/share/classes/javax/imageio/stream/MemoryCacheImageInputStream.java +++ b/src/java.desktop/share/classes/javax/imageio/stream/MemoryCacheImageInputStream.java @@ -179,16 +179,12 @@ public class MemoryCacheImageInputStream extends ImageInputStreamImpl { /** * {@inheritDoc} * - * @deprecated The {@code finalize} method has been deprecated. - * Subclasses that override {@code finalize} in order to perform cleanup - * should be modified to use alternative cleanup mechanisms and - * to remove the overriding {@code finalize} method. - * When overriding the {@code finalize} method, its implementation must explicitly - * ensure that {@code super.finalize()} is invoked as described in {@link Object#finalize}. - * See the specification for {@link Object#finalize()} for further - * information about migration options. + * @deprecated Finalization has been deprecated for removal. See + * {@link java.lang.Object#finalize} for background information and details + * about migration options. */ - @Deprecated(since="9") + @Deprecated(since="9", forRemoval=true) + @SuppressWarnings("removal") protected void finalize() throws Throwable { // Empty finalizer: for performance reasons we instead use the // Disposer mechanism for ensuring that the underlying diff --git a/src/java.desktop/share/classes/javax/print/DocFlavor.java b/src/java.desktop/share/classes/javax/print/DocFlavor.java index 557a1799a241fe64f9fc37f4bada5761b59945b1..0e04dfb471c86206dbd2550b879bf0d41dae4f91 100644 --- a/src/java.desktop/share/classes/javax/print/DocFlavor.java +++ b/src/java.desktop/share/classes/javax/print/DocFlavor.java @@ -537,10 +537,8 @@ public class DocFlavor implements Serializable, Cloneable { * {@code false} otherwise */ public boolean equals(Object obj) { - return - obj != null && - obj instanceof DocFlavor && - getStringValue().equals (((DocFlavor) obj).getStringValue()); + return obj instanceof DocFlavor other && + getStringValue().equals(other.getStringValue()); } /** diff --git a/src/java.desktop/share/classes/javax/print/MimeType.java b/src/java.desktop/share/classes/javax/print/MimeType.java index b2967428a2a6aebcfdc1799937ca124851f25cb4..4e3acdb99fa6c05b7c73ded164799428ae2a00ac 100644 --- a/src/java.desktop/share/classes/javax/print/MimeType.java +++ b/src/java.desktop/share/classes/javax/print/MimeType.java @@ -141,10 +141,9 @@ class MimeType implements Serializable, Cloneable { throw new UnsupportedOperationException(); } public boolean equals(Object o) { - return (o != null && - o instanceof Map.Entry && - getKey().equals (((Map.Entry) o).getKey()) && - getValue().equals(((Map.Entry) o).getValue())); + return o instanceof Map.Entry entry && + getKey().equals(entry.getKey()) && + getValue().equals(entry.getValue()); } public int hashCode() { return getKey().hashCode() ^ getValue().hashCode(); @@ -290,9 +289,8 @@ class MimeType implements Serializable, Cloneable { * {@code false} otherwise */ public boolean equals (Object obj) { - return(obj != null && - obj instanceof MimeType && - getStringValue().equals(((MimeType) obj).getStringValue())); + return obj instanceof MimeType mimeType && + getStringValue().equals(mimeType.getStringValue()); } /** diff --git a/src/java.desktop/share/classes/javax/print/attribute/DateTimeSyntax.java b/src/java.desktop/share/classes/javax/print/attribute/DateTimeSyntax.java index 769177ed82b0aa8828c50b295085ee496dfb7029..2f0eafb9f791899044c8c0e4f1f29c95bf6b67e8 100644 --- a/src/java.desktop/share/classes/javax/print/attribute/DateTimeSyntax.java +++ b/src/java.desktop/share/classes/javax/print/attribute/DateTimeSyntax.java @@ -115,9 +115,8 @@ public abstract class DateTimeSyntax implements Serializable, Cloneable { * attribute, {@code false} otherwise */ public boolean equals(Object object) { - return (object != null && - object instanceof DateTimeSyntax && - value.equals(((DateTimeSyntax) object).value)); + return object instanceof DateTimeSyntax other && + value.equals(other.value); } /** diff --git a/src/java.desktop/share/classes/javax/print/attribute/HashAttributeSet.java b/src/java.desktop/share/classes/javax/print/attribute/HashAttributeSet.java index aaeef91954c6437d2b55f8e774d48868f950434b..4ad4c8634aa0e6ad387865a8f74b41a54541d1c7 100644 --- a/src/java.desktop/share/classes/javax/print/attribute/HashAttributeSet.java +++ b/src/java.desktop/share/classes/javax/print/attribute/HashAttributeSet.java @@ -345,10 +345,8 @@ public class HashAttributeSet implements AttributeSet, Serializable { * value */ public boolean containsValue(Attribute attribute) { - return - attribute != null && - attribute instanceof Attribute && - attribute.equals(attrMap.get(attribute.getCategory())); + return attribute != null && + attribute.equals(attrMap.get(attribute.getCategory())); } /** @@ -441,11 +439,10 @@ public class HashAttributeSet implements AttributeSet, Serializable { * set */ public boolean equals(Object object) { - if (object == null || !(object instanceof AttributeSet)) { + if (!(object instanceof AttributeSet aset)) { return false; } - AttributeSet aset = (AttributeSet)object; if (aset.size() != size()) { return false; } diff --git a/src/java.desktop/share/classes/javax/print/attribute/IntegerSyntax.java b/src/java.desktop/share/classes/javax/print/attribute/IntegerSyntax.java index c67eff7ebb82bc1054504c91d4d75ddef0b524af..f6dbee3aa5a62aceecfc92cb36f9ec8d2d6f20d7 100644 --- a/src/java.desktop/share/classes/javax/print/attribute/IntegerSyntax.java +++ b/src/java.desktop/share/classes/javax/print/attribute/IntegerSyntax.java @@ -108,9 +108,8 @@ public abstract class IntegerSyntax implements Serializable, Cloneable { * attribute, {@code false} otherwise */ public boolean equals(Object object) { - - return (object != null && object instanceof IntegerSyntax && - value == ((IntegerSyntax) object).value); + return object instanceof IntegerSyntax other && + value == other.value; } /** diff --git a/src/java.desktop/share/classes/javax/print/attribute/ResolutionSyntax.java b/src/java.desktop/share/classes/javax/print/attribute/ResolutionSyntax.java index d3eb94956a9bd33d1905cd8b3cf784e317edf4c8..8ffae65a0d239a39743072bfaaa8cfab674a1e40 100644 --- a/src/java.desktop/share/classes/javax/print/attribute/ResolutionSyntax.java +++ b/src/java.desktop/share/classes/javax/print/attribute/ResolutionSyntax.java @@ -267,13 +267,9 @@ public abstract class ResolutionSyntax implements Serializable, Cloneable { * attribute, {@code false} otherwise */ public boolean equals(Object object) { - - return(object != null && - object instanceof ResolutionSyntax && - this.crossFeedResolution == - ((ResolutionSyntax) object).crossFeedResolution && - this.feedResolution == - ((ResolutionSyntax) object).feedResolution); + return object instanceof ResolutionSyntax other && + this.crossFeedResolution == other.crossFeedResolution && + this.feedResolution == other.feedResolution; } /** diff --git a/src/java.desktop/share/classes/javax/print/attribute/SetOfIntegerSyntax.java b/src/java.desktop/share/classes/javax/print/attribute/SetOfIntegerSyntax.java index 0fac430e29aa0d511443c236b2ffe6fb24b55aa8..6df67ef90ca4df25f13da6279054321c1a0ff800 100644 --- a/src/java.desktop/share/classes/javax/print/attribute/SetOfIntegerSyntax.java +++ b/src/java.desktop/share/classes/javax/print/attribute/SetOfIntegerSyntax.java @@ -483,9 +483,9 @@ public abstract class SetOfIntegerSyntax implements Serializable, Cloneable { * set-of-integer attribute, {@code false} otherwise */ public boolean equals(Object object) { - if (object != null && object instanceof SetOfIntegerSyntax) { + if (object instanceof SetOfIntegerSyntax other) { int[][] myMembers = this.members; - int[][] otherMembers = ((SetOfIntegerSyntax) object).members; + int[][] otherMembers = other.members; int m = myMembers.length; int n = otherMembers.length; if (m == n) { diff --git a/src/java.desktop/share/classes/javax/print/attribute/Size2DSyntax.java b/src/java.desktop/share/classes/javax/print/attribute/Size2DSyntax.java index 8adc51b8ff5faad4106b97564e2cc0e8a01e1f70..9ff772bc30d6925b73d75d92296c6b56e6055d4f 100644 --- a/src/java.desktop/share/classes/javax/print/attribute/Size2DSyntax.java +++ b/src/java.desktop/share/classes/javax/print/attribute/Size2DSyntax.java @@ -264,10 +264,9 @@ public abstract class Size2DSyntax implements Serializable, Cloneable { * two-dimensional size attribute, {@code false} otherwise */ public boolean equals(Object object) { - return(object != null && - object instanceof Size2DSyntax && - this.x == ((Size2DSyntax) object).x && - this.y == ((Size2DSyntax) object).y); + return object instanceof Size2DSyntax size2DSyntax && + this.x == size2DSyntax.x && + this.y == size2DSyntax.y; } /** diff --git a/src/java.desktop/share/classes/javax/print/attribute/TextSyntax.java b/src/java.desktop/share/classes/javax/print/attribute/TextSyntax.java index 40fd3171e7a7e4c295cce3543b6ef5b0eed11548..9a343bc8af2c7fa836c8b068247d2c68ec31f05f 100644 --- a/src/java.desktop/share/classes/javax/print/attribute/TextSyntax.java +++ b/src/java.desktop/share/classes/javax/print/attribute/TextSyntax.java @@ -132,10 +132,9 @@ public abstract class TextSyntax implements Serializable, Cloneable { * attribute, {@code false} otherwise */ public boolean equals(Object object) { - return(object != null && - object instanceof TextSyntax && - this.value.equals (((TextSyntax) object).value) && - this.locale.equals (((TextSyntax) object).locale)); + return object instanceof TextSyntax other && + this.value.equals(other.value) && + this.locale.equals(other.locale); } /** diff --git a/src/java.desktop/share/classes/javax/print/attribute/URISyntax.java b/src/java.desktop/share/classes/javax/print/attribute/URISyntax.java index e5f4f57f138c6a7ddc0c66780bb58d1d37cb3eba..10545df71fd4430ed320e0896582f75f0612da22 100644 --- a/src/java.desktop/share/classes/javax/print/attribute/URISyntax.java +++ b/src/java.desktop/share/classes/javax/print/attribute/URISyntax.java @@ -101,9 +101,8 @@ public abstract class URISyntax implements Serializable, Cloneable { * attribute, {@code false} otherwise */ public boolean equals(Object object) { - return(object != null && - object instanceof URISyntax && - this.uri.equals (((URISyntax) object).uri)); + return object instanceof URISyntax other && + this.uri.equals(other.uri); } /** diff --git a/src/java.desktop/share/classes/javax/print/attribute/standard/Media.java b/src/java.desktop/share/classes/javax/print/attribute/standard/Media.java index 6e42547d95525aabc0cd5e0ef0a11f22f82ea703..6b62f1dbecdc042690d3e673ef2975d05e8cf337 100644 --- a/src/java.desktop/share/classes/javax/print/attribute/standard/Media.java +++ b/src/java.desktop/share/classes/javax/print/attribute/standard/Media.java @@ -90,9 +90,9 @@ public abstract class Media extends EnumSyntax * attribute, {@code false} otherwise */ public boolean equals(Object object) { - return(object != null && object instanceof Media && - object.getClass() == this.getClass() && - ((Media)object).getValue() == this.getValue()); + return object instanceof Media other && + object.getClass() == this.getClass() && + other.getValue() == this.getValue(); } /** diff --git a/src/java.desktop/share/classes/javax/swing/AbstractAction.java b/src/java.desktop/share/classes/javax/swing/AbstractAction.java index d56821c0424d859cb06c45c1b938c500ea35399f..6a22a985d69b7e477ddc4e1b9524eff4f85d2318 100644 --- a/src/java.desktop/share/classes/javax/swing/AbstractAction.java +++ b/src/java.desktop/share/classes/javax/swing/AbstractAction.java @@ -193,7 +193,7 @@ public abstract class AbstractAction implements Action, Cloneable, Serializable // to change enabled, it would be possible for stack // overflow in the case where a developer implemented setEnabled // in terms of putValue. - if (newValue == null || !(newValue instanceof Boolean)) { + if (!(newValue instanceof Boolean)) { newValue = false; } oldValue = enabled; diff --git a/src/java.desktop/share/classes/javax/swing/AbstractButton.java b/src/java.desktop/share/classes/javax/swing/AbstractButton.java index 56ff09c2c4907beac8ea3489f281fe8e006f1bec..8a2936cd4990e1dc2965c2f729ccba751195937f 100644 --- a/src/java.desktop/share/classes/javax/swing/AbstractButton.java +++ b/src/java.desktop/share/classes/javax/swing/AbstractButton.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2394,8 +2394,8 @@ public abstract class AbstractButton extends JComponent implements ItemSelectabl if (defaultIcon instanceof Accessible) { AccessibleContext ac = ((Accessible)defaultIcon).getAccessibleContext(); - if (ac != null && ac instanceof AccessibleIcon) { - return new AccessibleIcon[] { (AccessibleIcon)ac }; + if (ac instanceof AccessibleIcon ai) { + return new AccessibleIcon[] { ai }; } } return null; @@ -2441,8 +2441,8 @@ public abstract class AbstractButton extends JComponent implements ItemSelectabl if (!relationSet.contains(AccessibleRelation.MEMBER_OF)) { // get the members of the button group if one exists ButtonModel model = getModel(); - if (model != null && model instanceof DefaultButtonModel) { - ButtonGroup group = ((DefaultButtonModel)model).getGroup(); + if (model instanceof DefaultButtonModel defaultModel) { + ButtonGroup group = defaultModel.getGroup(); if (group != null) { // set the target of the MEMBER_OF relation to be // the members of the button group. diff --git a/src/java.desktop/share/classes/javax/swing/DebugGraphics.java b/src/java.desktop/share/classes/javax/swing/DebugGraphics.java index 5cd8c69dfacf0c35517b11aaf26219a430d9f8b5..102f7e35dd5a2735999fb601db80578c93bb68f9 100644 --- a/src/java.desktop/share/classes/javax/swing/DebugGraphics.java +++ b/src/java.desktop/share/classes/javax/swing/DebugGraphics.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1417,8 +1417,8 @@ public class DebugGraphics extends Graphics { Container container = (Container)component; int debugOptions = 0; - while (container != null && (container instanceof JComponent)) { - debugOptions |= info.getDebugOptions((JComponent)container); + while (container instanceof JComponent jc) { + debugOptions |= info.getDebugOptions(jc); container = container.getParent(); } diff --git a/src/java.desktop/share/classes/javax/swing/DefaultListSelectionModel.java b/src/java.desktop/share/classes/javax/swing/DefaultListSelectionModel.java index 25e47c8b90b29fd23c8a41ed91534c97885a87ab..1924df3123e2ad703da27accfc6e230cbe0b4c74 100644 --- a/src/java.desktop/share/classes/javax/swing/DefaultListSelectionModel.java +++ b/src/java.desktop/share/classes/javax/swing/DefaultListSelectionModel.java @@ -50,7 +50,8 @@ import javax.swing.event.*; * @see ListSelectionModel * @since 1.2 */ -@SuppressWarnings("serial") // Same-version serialization only +@SuppressWarnings({"serial", // Same-version serialization only + "doclint:missing"}) public class DefaultListSelectionModel implements ListSelectionModel, Cloneable, Serializable { private static final int MIN = -1; diff --git a/src/java.desktop/share/classes/javax/swing/JApplet.java b/src/java.desktop/share/classes/javax/swing/JApplet.java index d15fac15f66ccabb6f0488aebc5367d13f54e68b..a1ba64dcf0dd76ef00a15e0583a0e9776baa427c 100644 --- a/src/java.desktop/share/classes/javax/swing/JApplet.java +++ b/src/java.desktop/share/classes/javax/swing/JApplet.java @@ -99,7 +99,8 @@ import javax.accessibility.AccessibleContext; @Deprecated(since = "9", forRemoval = true) @JavaBean(defaultProperty = "JMenuBar", description = "Swing's Applet subclass.") @SwingContainer(delegate = "getContentPane") -@SuppressWarnings({"serial", "removal"}) // Same-version serialization only +@SuppressWarnings({"serial", "removal", // Same-version serialization only + "doclint:missing"}) public class JApplet extends Applet implements Accessible, RootPaneContainer, TransferHandler.HasGetTransferHandler diff --git a/src/java.desktop/share/classes/javax/swing/JComboBox.java b/src/java.desktop/share/classes/javax/swing/JComboBox.java index 3eba525bc81a8a1c2fe25b7f47b4037103a0334b..fdbbdc686575f26e01f8e0cce1c4ab61071bf07b 100644 --- a/src/java.desktop/share/classes/javax/swing/JComboBox.java +++ b/src/java.desktop/share/classes/javax/swing/JComboBox.java @@ -2000,11 +2000,10 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible { // Get the popup Accessible a = JComboBox.this.getUI().getAccessibleChild(JComboBox.this, 0); - if (a != null && - a instanceof javax.swing.plaf.basic.ComboPopup) { + if (a instanceof javax.swing.plaf.basic.ComboPopup popup) { // get the popup list - JList list = ((javax.swing.plaf.basic.ComboPopup)a).getList(); + JList list = popup.getList(); // return the i-th selection in the popup list AccessibleContext ac = list.getAccessibleContext(); diff --git a/src/java.desktop/share/classes/javax/swing/JComponent.java b/src/java.desktop/share/classes/javax/swing/JComponent.java index 74fcfcd94d811923cf7b0e044a1b27c5badab43c..c572a12ebb465e801d948c43fea0a45cf050efa5 100644 --- a/src/java.desktop/share/classes/javax/swing/JComponent.java +++ b/src/java.desktop/share/classes/javax/swing/JComponent.java @@ -878,8 +878,7 @@ public abstract class JComponent extends Container implements Serializable, } // If we are only to paint to a specific child, determine // its index. - if (paintingChild != null && - (paintingChild instanceof JComponent) && + if ((paintingChild instanceof JComponent) && paintingChild.isOpaque()) { for (; i >= 0; i--) { if (getComponent(i) == paintingChild){ @@ -3636,20 +3635,18 @@ public abstract class JComponent extends Container implements Serializable, boolean temporary, boolean focusedWindowChangeAllowed, FocusEvent.Cause cause) { - if ((to == null) || !(to instanceof JComponent)) { + if (!(to instanceof JComponent target)) { return true; } - if ((from == null) || !(from instanceof JComponent)) { + if (!(from instanceof JComponent jFocusOwner)) { return true; } - JComponent target = (JComponent) to; if (!target.getVerifyInputWhenFocusTarget()) { return true; } - JComponent jFocusOwner = (JComponent)from; InputVerifier iv = jFocusOwner.getInputVerifier(); if (iv == null) { @@ -3774,7 +3771,7 @@ public abstract class JComponent extends Container implements Serializable, protected AccessibleContainerHandler() {} public void componentAdded(ContainerEvent e) { Component c = e.getChild(); - if (c != null && c instanceof Accessible) { + if (c instanceof Accessible) { AccessibleJComponent.this.firePropertyChange( AccessibleContext.ACCESSIBLE_CHILD_PROPERTY, null, c.getAccessibleContext()); @@ -3782,7 +3779,7 @@ public abstract class JComponent extends Container implements Serializable, } public void componentRemoved(ContainerEvent e) { Component c = e.getChild(); - if (c != null && c instanceof Accessible) { + if (c instanceof Accessible) { AccessibleJComponent.this.firePropertyChange( AccessibleContext.ACCESSIBLE_CHILD_PROPERTY, c.getAccessibleContext(), null); diff --git a/src/java.desktop/share/classes/javax/swing/JDialog.java b/src/java.desktop/share/classes/javax/swing/JDialog.java index 522c8dae0a005635d7c3c1c6c389d02a9775a1ac..97013e59a6b298e670a706fd26435cf4f039033b 100644 --- a/src/java.desktop/share/classes/javax/swing/JDialog.java +++ b/src/java.desktop/share/classes/javax/swing/JDialog.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -95,7 +95,8 @@ import javax.accessibility.*; */ @JavaBean(defaultProperty = "JMenuBar", description = "A toplevel window for creating dialog boxes.") @SwingContainer(delegate = "getContentPane") -@SuppressWarnings("serial") // Same-version serialization only +@SuppressWarnings({"serial", // Same-version serialization only + "doclint:missing"}) public class JDialog extends Dialog implements WindowConstants, Accessible, RootPaneContainer, diff --git a/src/java.desktop/share/classes/javax/swing/JInternalFrame.java b/src/java.desktop/share/classes/javax/swing/JInternalFrame.java index 17b0fecde0826c0456d8c4b2e64c8b377a9ac650..62efd03c0db844aad94f0065eab55a3c4330fba7 100644 --- a/src/java.desktop/share/classes/javax/swing/JInternalFrame.java +++ b/src/java.desktop/share/classes/javax/swing/JInternalFrame.java @@ -1233,10 +1233,9 @@ public class JInternalFrame extends JComponent implements @BeanProperty(bound = false, expert = true, description = "Specifies what desktop layer is used.") public void setLayer(Integer layer) { - if(getParent() != null && getParent() instanceof JLayeredPane) { + if (getParent() instanceof JLayeredPane p) { // Normally we want to do this, as it causes the LayeredPane // to draw properly. - JLayeredPane p = (JLayeredPane)getParent(); p.setLayer(this, layer.intValue(), p.getPosition(this)); } else { // Try to do the right thing diff --git a/src/java.desktop/share/classes/javax/swing/JLabel.java b/src/java.desktop/share/classes/javax/swing/JLabel.java index e7678d79374dc72d4468e22be0c7fcc6871ef788..8dff4a8fd25b3ba8eacd741730138d189071d537 100644 --- a/src/java.desktop/share/classes/javax/swing/JLabel.java +++ b/src/java.desktop/share/classes/javax/swing/JLabel.java @@ -1075,6 +1075,10 @@ public class JLabel extends JComponent implements SwingConstants, Accessible * @see AccessibleContext#setAccessibleName */ public String getAccessibleName() { + return getAccessibleNameCheckIcon(getAccessibleNameImpl()); + } + + private String getAccessibleNameImpl() { String name = accessibleName; if (name == null) { @@ -1089,6 +1093,19 @@ public class JLabel extends JComponent implements SwingConstants, Accessible return name; } + private String getAccessibleNameCheckIcon(String name) { + if (((name == null) || name.isEmpty()) && + (JLabel.this.getIcon() != null)) { + if (JLabel.this.getIcon() instanceof Accessible) { + AccessibleContext ac = ((Accessible) JLabel.this.getIcon()).getAccessibleContext(); + if (ac != null) { + name = ac.getAccessibleName(); + } + } + } + return name; + } + /** * Get the role of this object. * @@ -1097,6 +1114,11 @@ public class JLabel extends JComponent implements SwingConstants, Accessible * @see AccessibleRole */ public AccessibleRole getAccessibleRole() { + String name = getAccessibleNameImpl(); + if (((name == null) || name.isEmpty()) && + (JLabel.this.getIcon() != null)) { + return AccessibleRole.ICON; + } return AccessibleRole.LABEL; } @@ -1110,8 +1132,8 @@ public class JLabel extends JComponent implements SwingConstants, Accessible if (icon instanceof Accessible) { AccessibleContext ac = ((Accessible)icon).getAccessibleContext(); - if (ac != null && ac instanceof AccessibleIcon) { - return new AccessibleIcon[] { (AccessibleIcon)ac }; + if (ac instanceof AccessibleIcon ai) { + return new AccessibleIcon[] { ai }; } } return null; diff --git a/src/java.desktop/share/classes/javax/swing/JList.java b/src/java.desktop/share/classes/javax/swing/JList.java index 7932209974bcc4a32c3cd02fd56ccf24a96f36d8..ac4a1e3fe3a6ff67d6b3b0047c3cab8734502b77 100644 --- a/src/java.desktop/share/classes/javax/swing/JList.java +++ b/src/java.desktop/share/classes/javax/swing/JList.java @@ -2949,21 +2949,21 @@ public class JList extends JComponent implements Scrollable, Accessible // re-set listData listeners if (name.equals("model")) { - if (oldValue != null && oldValue instanceof ListModel) { - ((ListModel) oldValue).removeListDataListener(this); + if (oldValue instanceof ListModel oldModel) { + oldModel.removeListDataListener(this); } - if (newValue != null && newValue instanceof ListModel) { - ((ListModel) newValue).addListDataListener(this); + if (newValue instanceof ListModel newModel) { + newModel.addListDataListener(this); } // re-set listSelectionModel listeners } else if (name.equals("selectionModel")) { - if (oldValue != null && oldValue instanceof ListSelectionModel) { - ((ListSelectionModel) oldValue).removeListSelectionListener(this); + if (oldValue instanceof ListSelectionModel oldModel) { + oldModel.removeListSelectionListener(this); } - if (newValue != null && newValue instanceof ListSelectionModel) { - ((ListSelectionModel) newValue).addListSelectionListener(this); + if (newValue instanceof ListSelectionModel newModel) { + newModel.addListSelectionListener(this); } firePropertyChange( diff --git a/src/java.desktop/share/classes/javax/swing/JMenu.java b/src/java.desktop/share/classes/javax/swing/JMenu.java index 5e54131d3ed2bdcfa4413ac86d100090d1b05de7..dbac4812ca821e3470adee0ae7b829e45f69fe72 100644 --- a/src/java.desktop/share/classes/javax/swing/JMenu.java +++ b/src/java.desktop/share/classes/javax/swing/JMenu.java @@ -1598,7 +1598,7 @@ public class JMenu extends JMenuItem implements Accessible,MenuElement return; } JMenuItem mi = getItem(i); - if (mi != null && mi instanceof JMenu) { + if (mi instanceof JMenu) { if (mi.isSelected()) { MenuElement[] old = MenuSelectionManager.defaultManager().getSelectedPath(); diff --git a/src/java.desktop/share/classes/javax/swing/JMenuBar.java b/src/java.desktop/share/classes/javax/swing/JMenuBar.java index cedaf9d25adbc0b141f39505bfacc56068e2ebe5..b94585702788d92a38eac4842072205fd8b02409 100644 --- a/src/java.desktop/share/classes/javax/swing/JMenuBar.java +++ b/src/java.desktop/share/classes/javax/swing/JMenuBar.java @@ -706,9 +706,7 @@ public class JMenuBar extends JComponent implements Accessible,MenuElement return false; } - if (c != null && c instanceof JComponent && - ((JComponent)c).processKeyBinding(ks, e, condition, pressed)) { - + if (c instanceof JComponent jc && jc.processKeyBinding(ks, e, condition, pressed)) { return true; } diff --git a/src/java.desktop/share/classes/javax/swing/JOptionPane.java b/src/java.desktop/share/classes/javax/swing/JOptionPane.java index 51dcd81d146d2d3499222bcd6865153080f1aed3..99eee90347ba2e2b8ad21258e1e2dfb5bc3d13bd 100644 --- a/src/java.desktop/share/classes/javax/swing/JOptionPane.java +++ b/src/java.desktop/share/classes/javax/swing/JOptionPane.java @@ -2330,17 +2330,17 @@ public class JOptionPane extends JComponent implements Accessible Vector values = new Vector(); s.defaultWriteObject(); - // Save the icon, if its Serializable. - if(icon != null && icon instanceof Serializable) { + // Save the icon, if it's Serializable. + if (icon instanceof Serializable) { values.addElement("icon"); values.addElement(icon); } - // Save the message, if its Serializable. - if(message != null && message instanceof Serializable) { + // Save the message, if it's Serializable. + if (message instanceof Serializable) { values.addElement("message"); values.addElement(message); } - // Save the treeModel, if its Serializable. + // Save the treeModel, if it's Serializable. if(options != null) { ArrayList serOptions = new ArrayList(); @@ -2354,17 +2354,17 @@ public class JOptionPane extends JComponent implements Accessible values.addElement(arrayOptions); } } - // Save the initialValue, if its Serializable. - if(initialValue != null && initialValue instanceof Serializable) { + // Save the initialValue, if it's Serializable. + if (initialValue instanceof Serializable) { values.addElement("initialValue"); values.addElement(initialValue); } - // Save the value, if its Serializable. - if(value != null && value instanceof Serializable) { + // Save the value, if it's Serializable. + if (value instanceof Serializable) { values.addElement("value"); values.addElement(value); } - // Save the selectionValues, if its Serializable. + // Save the selectionValues, if it's Serializable. if(selectionValues != null) { boolean serialize = true; @@ -2381,14 +2381,13 @@ public class JOptionPane extends JComponent implements Accessible values.addElement(selectionValues); } } - // Save the inputValue, if its Serializable. - if(inputValue != null && inputValue instanceof Serializable) { + // Save the inputValue, if it's Serializable. + if (inputValue instanceof Serializable) { values.addElement("inputValue"); values.addElement(inputValue); } - // Save the initialSelectionValue, if its Serializable. - if(initialSelectionValue != null && - initialSelectionValue instanceof Serializable) { + // Save the initialSelectionValue, if it's Serializable. + if (initialSelectionValue instanceof Serializable) { values.addElement("initialSelectionValue"); values.addElement(initialSelectionValue); } diff --git a/src/java.desktop/share/classes/javax/swing/JPopupMenu.java b/src/java.desktop/share/classes/javax/swing/JPopupMenu.java index 17afba6ec4b1c7748c59450d13b1d46f41d2e246..ef9ad42ef81d1f1978b1b6c7dbf49fd430009e07 100644 --- a/src/java.desktop/share/classes/javax/swing/JPopupMenu.java +++ b/src/java.desktop/share/classes/javax/swing/JPopupMenu.java @@ -988,10 +988,9 @@ public class JPopupMenu extends JComponent implements Accessible,MenuElement { JPopupMenu mp = this; while((mp!=null) && (mp.isPopupMenu()!=true) && (mp.getInvoker() != null) && - (mp.getInvoker().getParent() != null) && - (mp.getInvoker().getParent() instanceof JPopupMenu) + (mp.getInvoker().getParent() instanceof JPopupMenu popupMenu) ) { - mp = (JPopupMenu) mp.getInvoker().getParent(); + mp = popupMenu; } return mp; } @@ -1330,13 +1329,13 @@ public class JPopupMenu extends JComponent implements Accessible,MenuElement { Vector values = new Vector(); s.defaultWriteObject(); - // Save the invoker, if its Serializable. - if(invoker != null && invoker instanceof Serializable) { + // Save the invoker if != null, (Component implements Serializable) + if (invoker != null) { values.addElement("invoker"); values.addElement(invoker); } - // Save the popup, if its Serializable. - if(popup != null && popup instanceof Serializable) { + // Save the popup, if it's Serializable. + if (popup instanceof Serializable) { values.addElement("popup"); values.addElement(popup); } diff --git a/src/java.desktop/share/classes/javax/swing/JScrollBar.java b/src/java.desktop/share/classes/javax/swing/JScrollBar.java index df6e3e23b68ea71f89890916ac4692972e2a8363..25cdb0886a9867236ba796712658a152de4f97d0 100644 --- a/src/java.desktop/share/classes/javax/swing/JScrollBar.java +++ b/src/java.desktop/share/classes/javax/swing/JScrollBar.java @@ -83,7 +83,8 @@ import javax.swing.plaf.ScrollBarUI; */ @JavaBean(defaultProperty = "UI", description = "A component that helps determine the visible content range of an area.") @SwingContainer(false) -@SuppressWarnings("serial") // Same-version serialization only +@SuppressWarnings({"serial", // Same-version serialization only + "doclint:missing"}) public class JScrollBar extends JComponent implements Adjustable, Accessible { /** diff --git a/src/java.desktop/share/classes/javax/swing/JSlider.java b/src/java.desktop/share/classes/javax/swing/JSlider.java index 6310e69fd4c79656f13c5116eddee9afd1fca2fa..0d826fe7e49e1f910d4a6c1a623a62c06b1df8c9 100644 --- a/src/java.desktop/share/classes/javax/swing/JSlider.java +++ b/src/java.desktop/share/classes/javax/swing/JSlider.java @@ -1018,8 +1018,8 @@ public class JSlider extends JComponent implements SwingConstants, Accessible { @SuppressWarnings("rawtypes") Dictionary labelTable = getLabelTable(); - if (labelTable != null && (labelTable instanceof PropertyChangeListener)) { - removePropertyChangeListener((PropertyChangeListener) labelTable); + if (labelTable instanceof PropertyChangeListener listener) { + removePropertyChangeListener(listener); } addPropertyChangeListener( table ); diff --git a/src/java.desktop/share/classes/javax/swing/JTable.java b/src/java.desktop/share/classes/javax/swing/JTable.java index 2506ed2cb7d55d68c2ab620e137394f3f34fabf0..9af6a1ba616415e08121bf8c8b418a1960cabc8e 100644 --- a/src/java.desktop/share/classes/javax/swing/JTable.java +++ b/src/java.desktop/share/classes/javax/swing/JTable.java @@ -6758,11 +6758,11 @@ public class JTable extends JComponent implements TableModelListener, Scrollable // re-set tableModel listeners if (name.equals("model")) { - if (oldValue != null && oldValue instanceof TableModel) { - ((TableModel) oldValue).removeTableModelListener(this); + if (oldValue instanceof TableModel oldModel) { + oldModel.removeTableModelListener(this); } - if (newValue != null && newValue instanceof TableModel) { - ((TableModel) newValue).addTableModelListener(this); + if (newValue instanceof TableModel newModel) { + newModel.addTableModelListener(this); } // re-set selectionModel listeners @@ -6771,24 +6771,20 @@ public class JTable extends JComponent implements TableModelListener, Scrollable Object source = e.getSource(); if (source == JTable.this) { // row selection model - if (oldValue != null && - oldValue instanceof ListSelectionModel) { - ((ListSelectionModel) oldValue).removeListSelectionListener(this); + if (oldValue instanceof ListSelectionModel oldModel) { + oldModel.removeListSelectionListener(this); } - if (newValue != null && - newValue instanceof ListSelectionModel) { - ((ListSelectionModel) newValue).addListSelectionListener(this); + if (newValue instanceof ListSelectionModel newModel) { + newModel.addListSelectionListener(this); } } else if (source == JTable.this.getColumnModel()) { - if (oldValue != null && - oldValue instanceof ListSelectionModel) { - ((ListSelectionModel) oldValue).removeListSelectionListener(this); + if (oldValue instanceof ListSelectionModel oldModel) { + oldModel.removeListSelectionListener(this); } - if (newValue != null && - newValue instanceof ListSelectionModel) { - ((ListSelectionModel) newValue).addListSelectionListener(this); + if (newValue instanceof ListSelectionModel newModel) { + newModel.addListSelectionListener(this); } } else { @@ -6799,13 +6795,11 @@ public class JTable extends JComponent implements TableModelListener, Scrollable // and column's selection property listener as well } else if (name.equals("columnModel")) { - if (oldValue != null && oldValue instanceof TableColumnModel) { - TableColumnModel tcm = (TableColumnModel) oldValue; + if (oldValue instanceof TableColumnModel tcm) { tcm.removeColumnModelListener(this); tcm.getSelectionModel().removeListSelectionListener(this); } - if (newValue != null && newValue instanceof TableColumnModel) { - TableColumnModel tcm = (TableColumnModel) newValue; + if (newValue instanceof TableColumnModel tcm) { tcm.addColumnModelListener(this); tcm.getSelectionModel().addListSelectionListener(this); } @@ -6813,11 +6807,11 @@ public class JTable extends JComponent implements TableModelListener, Scrollable // re-se cellEditor listeners } else if (name.equals("tableCellEditor")) { - if (oldValue != null && oldValue instanceof TableCellEditor) { - ((TableCellEditor) oldValue).removeCellEditorListener(this); + if (oldValue instanceof TableCellEditor oldEditor) { + oldEditor.removeCellEditorListener(this); } - if (newValue != null && newValue instanceof TableCellEditor) { - ((TableCellEditor) newValue).addCellEditorListener(this); + if (newValue instanceof TableCellEditor newEditor) { + newEditor.addCellEditorListener(this); } } } diff --git a/src/java.desktop/share/classes/javax/swing/JTree.java b/src/java.desktop/share/classes/javax/swing/JTree.java index 06b76b0d3da721bf88e6d6ea3aec9eec20a12b49..ae90ea8be8bec502faf56b15683af34a8d75a161 100644 --- a/src/java.desktop/share/classes/javax/swing/JTree.java +++ b/src/java.desktop/share/classes/javax/swing/JTree.java @@ -3127,23 +3127,23 @@ public class JTree extends JComponent implements Scrollable, Accessible Vector values = new Vector(); s.defaultWriteObject(); - // Save the cellRenderer, if its Serializable. - if(cellRenderer != null && cellRenderer instanceof Serializable) { + // Save the cellRenderer, if it's Serializable. + if (cellRenderer instanceof Serializable) { values.addElement("cellRenderer"); values.addElement(cellRenderer); } - // Save the cellEditor, if its Serializable. - if(cellEditor != null && cellEditor instanceof Serializable) { + // Save the cellEditor, if it's Serializable. + if (cellEditor instanceof Serializable) { values.addElement("cellEditor"); values.addElement(cellEditor); } - // Save the treeModel, if its Serializable. - if(treeModel != null && treeModel instanceof Serializable) { + // Save the treeModel, if it's Serializable. + if (treeModel instanceof Serializable) { values.addElement("treeModel"); values.addElement(treeModel); } - // Save the selectionModel, if its Serializable. - if(selectionModel != null && selectionModel instanceof Serializable) { + // Save the selectionModel, if it's Serializable. + if (selectionModel instanceof Serializable) { values.addElement("selectionModel"); values.addElement(selectionModel); } @@ -5414,14 +5414,12 @@ public class JTree extends JComponent implements Scrollable, Accessible public Rectangle getBounds() { Rectangle r = tree.getPathBounds(path); Accessible parent = getAccessibleParent(); - if (parent != null) { - if (parent instanceof AccessibleJTreeNode) { - Point parentLoc = ((AccessibleJTreeNode) parent).getLocationInJTree(); - if (parentLoc != null && r != null) { - r.translate(-parentLoc.x, -parentLoc.y); - } else { - return null; // not visible! - } + if (parent instanceof AccessibleJTreeNode treeNode) { + Point parentLoc = treeNode.getLocationInJTree(); + if (parentLoc != null && r != null) { + r.translate(-parentLoc.x, -parentLoc.y); + } else { + return null; // not visible! } } return r; diff --git a/src/java.desktop/share/classes/javax/swing/MenuSelectionManager.java b/src/java.desktop/share/classes/javax/swing/MenuSelectionManager.java index 25c525a20320d570f41940dffe1bbb4bc5c40b7e..c84a218b8776e4093282b84426fe7caf14470df2 100644 --- a/src/java.desktop/share/classes/javax/swing/MenuSelectionManager.java +++ b/src/java.desktop/share/classes/javax/swing/MenuSelectionManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -72,8 +72,8 @@ public class MenuSelectionManager { // installing additional listener if found in the AppContext Object o = context.get(SwingUtilities2.MENU_SELECTION_MANAGER_LISTENER_KEY); - if (o != null && o instanceof ChangeListener) { - msm.addChangeListener((ChangeListener) o); + if (o instanceof ChangeListener listener) { + msm.addChangeListener(listener); } } diff --git a/src/java.desktop/share/classes/javax/swing/RepaintManager.java b/src/java.desktop/share/classes/javax/swing/RepaintManager.java index 966e6e8489c69c5848c002cdc658ef04ffe92f44..fe414fc16afcd5f965ce676b985a691d82edac25 100644 --- a/src/java.desktop/share/classes/javax/swing/RepaintManager.java +++ b/src/java.desktop/share/classes/javax/swing/RepaintManager.java @@ -928,7 +928,7 @@ public class RepaintManager for (int i = roots.size() - 1; i >= index; i--) { Component c = roots.get(i); for(;;) { - if (c == root || c == null || !(c instanceof JComponent)) { + if (c == root || !(c instanceof JComponent)) { break; } c = c.getParent(); diff --git a/src/java.desktop/share/classes/javax/swing/SpinnerDateModel.java b/src/java.desktop/share/classes/javax/swing/SpinnerDateModel.java index 9117c93809f1a6456b96169b9a40efe7578400e8..c78bc150c1a1e96f9658ab53dccc8daf303d5585 100644 --- a/src/java.desktop/share/classes/javax/swing/SpinnerDateModel.java +++ b/src/java.desktop/share/classes/javax/swing/SpinnerDateModel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -454,11 +454,11 @@ public class SpinnerDateModel extends AbstractSpinnerModel implements Serializab * @see #addChangeListener */ public void setValue(Object value) { - if ((value == null) || !(value instanceof Date)) { + if (!(value instanceof Date date)) { throw new IllegalArgumentException("illegal value"); } - if (!value.equals(this.value.getTime())) { - this.value.setTime((Date)value); + if (!date.equals(this.value.getTime())) { + this.value.setTime(date); fireStateChanged(); } } diff --git a/src/java.desktop/share/classes/javax/swing/SpinnerNumberModel.java b/src/java.desktop/share/classes/javax/swing/SpinnerNumberModel.java index d8db7b3ae0f177f0989cff69d8ebea213e05d63e..d2dd0a9d5f61ec9f817c1d3eb8e8ccf0b1418916 100644 --- a/src/java.desktop/share/classes/javax/swing/SpinnerNumberModel.java +++ b/src/java.desktop/share/classes/javax/swing/SpinnerNumberModel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -452,11 +452,11 @@ public class SpinnerNumberModel extends AbstractSpinnerModel implements Serializ * @see SpinnerModel#addChangeListener */ public void setValue(Object value) { - if ((value == null) || !(value instanceof Number)) { + if (!(value instanceof Number number)) { throw new IllegalArgumentException("illegal value"); } - if (!value.equals(this.value)) { - this.value = (Number)value; + if (!number.equals(this.value)) { + this.value = number; fireStateChanged(); } } diff --git a/src/java.desktop/share/classes/javax/swing/SwingUtilities.java b/src/java.desktop/share/classes/javax/swing/SwingUtilities.java index e15347ec06a7fdf2315d1e1978ecc42609b3eed2..5e3965e69b8edf7601ec495dd0c1aaefe251352a 100644 --- a/src/java.desktop/share/classes/javax/swing/SwingUtilities.java +++ b/src/java.desktop/share/classes/javax/swing/SwingUtilities.java @@ -2054,8 +2054,8 @@ public class SwingUtilities implements SwingConstants * ImageIcon, and the image it contains is the same as image. */ static boolean doesIconReferenceImage(Icon icon, Image image) { - Image iconImage = (icon != null && (icon instanceof ImageIcon)) ? - ((ImageIcon)icon).getImage() : null; + Image iconImage = (icon instanceof ImageIcon i) ? + i.getImage() : null; return (iconImage == image); } diff --git a/src/java.desktop/share/classes/javax/swing/TransferHandler.java b/src/java.desktop/share/classes/javax/swing/TransferHandler.java index b366a283ffa184967be62e3984bef1f782a1f628..f2622880e7fa3e6576df41ee1f9bdc2e354f2444 100644 --- a/src/java.desktop/share/classes/javax/swing/TransferHandler.java +++ b/src/java.desktop/share/classes/javax/swing/TransferHandler.java @@ -1272,9 +1272,9 @@ public class TransferHandler implements Serializable { // If the Drop target is inactive the dragExit will not be dispatched to the dtListener, // so make sure that we clean up the dtListener anyway. DropTargetListener dtListener = getDropTargetListener(); - if (dtListener != null && dtListener instanceof DropHandler) { - ((DropHandler)dtListener).cleanup(false); - } + if (dtListener instanceof DropHandler dropHandler) { + dropHandler.cleanup(false); + } } } diff --git a/src/java.desktop/share/classes/javax/swing/event/EventListenerList.java b/src/java.desktop/share/classes/javax/swing/event/EventListenerList.java index 21dacb1d0df6146a50f269df8910ba0489f4880d..1be0228864c1e84410ef3138cbda74dc407aef99 100644 --- a/src/java.desktop/share/classes/javax/swing/event/EventListenerList.java +++ b/src/java.desktop/share/classes/javax/swing/event/EventListenerList.java @@ -283,7 +283,7 @@ public class EventListenerList implements Serializable { for (int i = 0; i < lList.length; i+=2) { Class t = (Class)lList[i]; EventListener l = (EventListener)lList[i+1]; - if ((l!=null) && (l instanceof Serializable)) { + if (l instanceof Serializable) { s.writeObject(t.getName()); s.writeObject(l); } diff --git a/src/java.desktop/share/classes/javax/swing/filechooser/FileSystemView.java b/src/java.desktop/share/classes/javax/swing/filechooser/FileSystemView.java index 17a3b196b07e40ce61a8a25e617fa22d062b0f86..0f30ef14d88c2de6e46c5ac0f86ebfc95714e9c2 100644 --- a/src/java.desktop/share/classes/javax/swing/filechooser/FileSystemView.java +++ b/src/java.desktop/share/classes/javax/swing/filechooser/FileSystemView.java @@ -65,7 +65,7 @@ import sun.awt.shell.ShellFolder; // PENDING(jeff) - need to provide a specification for // how Mac/OS2/BeOS/etc file systems can modify FileSystemView // to handle their particular type of file system. - +@SuppressWarnings("doclint:missing") public abstract class FileSystemView { static FileSystemView windowsFileSystemView = null; diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicDesktopPaneUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicDesktopPaneUI.java index c2fab4089026a61b696efe424b01bb77cd6995f6..772ea16c44ec73e5f1dbec4f0150403901205e4d 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicDesktopPaneUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicDesktopPaneUI.java @@ -569,10 +569,7 @@ public class BasicDesktopPaneUI extends DesktopPaneUI { if (cycleRoot != null) { FocusTraversalPolicy policy = cycleRoot.getFocusTraversalPolicy(); - if (policy != null && policy instanceof - SortingFocusTraversalPolicy) { - SortingFocusTraversalPolicy sPolicy = - (SortingFocusTraversalPolicy)policy; + if (policy instanceof SortingFocusTraversalPolicy sPolicy) { boolean idc = sPolicy.getImplicitDownCycleTraversal(); try { sPolicy.setImplicitDownCycleTraversal(false); diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicInternalFrameUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicInternalFrameUI.java index 603dd896fde66992938808aa3fcc1d33cba1e6de..4e2e0fac3052f4bf3c72516d490bcdd667ddb591 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicInternalFrameUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicInternalFrameUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -578,9 +578,8 @@ public class BasicInternalFrameUI extends InternalFrameUI * @param c the new north pane */ public void setNorthPane(JComponent c) { - if (northPane != null && - northPane instanceof BasicInternalFrameTitlePane) { - ((BasicInternalFrameTitlePane)northPane).uninstallListeners(); + if (northPane instanceof BasicInternalFrameTitlePane tp) { + tp.uninstallListeners(); } replacePane(northPane, c); northPane = c; @@ -1614,9 +1613,8 @@ public class BasicInternalFrameUI extends InternalFrameUI // account the title pane since you are allowed to resize // the frames to the point where just the title pane is visible. Dimension result = new Dimension(); - if (getNorthPane() != null && - getNorthPane() instanceof BasicInternalFrameTitlePane) { - result = new Dimension(getNorthPane().getMinimumSize()); + if (getNorthPane() instanceof BasicInternalFrameTitlePane tp) { + result = new Dimension(tp.getMinimumSize()); } Insets i = frame.getInsets(); result.width += i.left + i.right; diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java index e2103468ab81a157b8c407a4b465a4b37075abae..fa6a531276715b58591f6b1544670e847f83d5fe 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java @@ -45,6 +45,7 @@ import sun.swing.*; * @author Arnaud Weber * @author Fredrik Lagerblad */ +@SuppressWarnings("doclint:missing") public class BasicMenuItemUI extends MenuItemUI { /** diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuUI.java index 33699871a18c8ff59d8f60555f1c3c8891b9c95d..78727a729c4228066672f8b20c3e3a019aafcee5 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,6 +46,7 @@ import java.util.ArrayList; * @author David Karlton * @author Arnaud Weber */ +@SuppressWarnings("doclint:missing") public class BasicMenuUI extends BasicMenuItemUI { /** @@ -297,20 +298,20 @@ public class BasicMenuUI extends BasicMenuItemUI final MenuSelectionManager defaultManager = MenuSelectionManager.defaultManager(); if(force) { Container cnt = menu.getParent(); - if(cnt != null && cnt instanceof JMenuBar) { + if (cnt instanceof JMenuBar menuBar) { MenuElement[] me; MenuElement[] subElements; subElements = menu.getPopupMenu().getSubElements(); if(subElements.length > 0) { me = new MenuElement[4]; - me[0] = (MenuElement) cnt; + me[0] = menuBar; me[1] = menu; me[2] = menu.getPopupMenu(); me[3] = subElements[0]; } else { me = new MenuElement[3]; - me[0] = (MenuElement)cnt; + me[0] = menuBar; me[1] = menu; me[2] = menu.getPopupMenu(); } @@ -512,10 +513,10 @@ public class BasicMenuUI extends BasicMenuItemUI manager.clearSelectedPath(); } else { Container cnt = menu.getParent(); - if(cnt != null && cnt instanceof JMenuBar) { + if (cnt instanceof JMenuBar menuBar) { MenuElement[] me = new MenuElement[2]; - me[0]=(MenuElement)cnt; - me[1]=menu; + me[0] = menuBar; + me[1] = menu; manager.setSelectedPath(me); } } diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicOptionPaneUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicOptionPaneUI.java index 427823573a6dba054004eb7408041c59c9c744a9..935e028783a170e4d3cbb562b3d98a6cf9dd982c 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicOptionPaneUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicOptionPaneUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -964,13 +964,10 @@ public class BasicOptionPaneUI extends OptionPaneUI { * the look and feel for based on the value in the inputComponent. */ protected void resetInputValue() { - if(inputComponent != null && (inputComponent instanceof JTextField)) { - optionPane.setInputValue(((JTextField)inputComponent).getText()); - - } else if(inputComponent != null && - (inputComponent instanceof JComboBox)) { - optionPane.setInputValue(((JComboBox)inputComponent) - .getSelectedItem()); + if (inputComponent instanceof JTextField textField) { + optionPane.setInputValue(textField.getText()); + } else if (inputComponent instanceof JComboBox comboBox) { + optionPane.setInputValue(comboBox.getSelectedItem()); } else if(inputComponent != null) { optionPane.setInputValue(((JList)inputComponent) .getSelectedValue()); diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSpinnerUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSpinnerUI.java index 71d0e4b671775105a2b5910459decfd3923a893b..cc6c46318d7a157fb25a3858ed6a5ade41432e34 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSpinnerUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSpinnerUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -197,8 +197,8 @@ public class BasicSpinnerUI extends SpinnerUI spinner.addChangeListener(getHandler()); } JComponent editor = spinner.getEditor(); - if (editor != null && editor instanceof JSpinner.DefaultEditor) { - JTextField tf = ((JSpinner.DefaultEditor)editor).getTextField(); + if (editor instanceof JSpinner.DefaultEditor defaultEditor) { + JTextField tf = defaultEditor.getTextField(); if (tf != null) { tf.addFocusListener(nextButtonHandler); tf.addFocusListener(previousButtonHandler); diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSplitPaneUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSplitPaneUI.java index 24b2fa873f1c934f05e1fc97e4fda62365cd362f..5fa79a7fa4da7a7b8185142d0a722fb204eb88fa 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSplitPaneUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSplitPaneUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -344,7 +344,7 @@ public class BasicSplitPaneUI extends SplitPaneUI Border b = divider.getBorder(); - if (b == null || !(b instanceof UIResource)) { + if (!(b instanceof UIResource)) { divider.setBorder(UIManager.getBorder("SplitPaneDivider.border")); } @@ -2359,8 +2359,7 @@ public class BasicSplitPaneUI extends SplitPaneUI } private Component getFirstAvailableComponent(Component c) { - if (c!=null && c instanceof JSplitPane) { - JSplitPane sp = (JSplitPane)c; + if (c instanceof JSplitPane sp) { Component left = getFirstAvailableComponent(sp.getLeftComponent()); if (left != null) { c = left; diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTableHeaderUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTableHeaderUI.java index 721fcbda9b705f87494030a847383127ea6c0b42..924458ad2fab972a7881984a6a8def72197cc0e3 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTableHeaderUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTableHeaderUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -535,13 +535,11 @@ public class BasicTableHeaderUI extends TableHeaderUI { * to ensure that the newly selected column is visible. */ private void scrollToColumn(int col) { - Container container; JTable table; //Test whether the header is in a scroll pane and has a table. if ((header.getParent() == null) || - ((container = header.getParent().getParent()) == null) || - !(container instanceof JScrollPane) || + !(header.getParent().getParent() instanceof JScrollPane) || ((table = header.getTable()) == null)) { return; } diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTableUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTableUI.java index 2ee4f1fa26d9138434f45f301f8fd9f9380ac331..c4ec26c56325bcb43f707332243348eccc7d6919 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTableUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTableUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -933,24 +933,21 @@ public class BasicTableUI extends TableUI // the table, seems to have no effect. Component editorComp = table.getEditorComponent(); - if (table.isEditing() && editorComp != null) { - if (editorComp instanceof JComponent) { - JComponent component = (JComponent)editorComp; - map = component.getInputMap(JComponent.WHEN_FOCUSED); - Object binding = (map != null) ? map.get(keyStroke) : null; - if (binding == null) { - map = component.getInputMap(JComponent. - WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); - binding = (map != null) ? map.get(keyStroke) : null; - } - if (binding != null) { - ActionMap am = component.getActionMap(); - Action action = (am != null) ? am.get(binding) : null; - if (action != null && SwingUtilities. + if (table.isEditing() && editorComp instanceof JComponent component) { + map = component.getInputMap(JComponent.WHEN_FOCUSED); + Object binding = (map != null) ? map.get(keyStroke) : null; + if (binding == null) { + map = component.getInputMap(JComponent. + WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + binding = (map != null) ? map.get(keyStroke) : null; + } + if (binding != null) { + ActionMap am = component.getActionMap(); + Action action = (am != null) ? am.get(binding) : null; + if (action != null && SwingUtilities. notifyAction(action, keyStroke, e, component, - e.getModifiers())) { - e.consume(); - } + e.getModifiers())) { + e.consume(); } } } @@ -1485,8 +1482,8 @@ public class BasicTableUI extends TableUI Container parent = SwingUtilities.getUnwrappedParent(table); // should be viewport if (parent != null) { parent = parent.getParent(); // should be the scrollpane - if (parent != null && parent instanceof JScrollPane) { - LookAndFeel.installBorder((JScrollPane)parent, "Table.scrollPaneBorder"); + if (parent instanceof JScrollPane scrollPane) { + LookAndFeel.installBorder(scrollPane, "Table.scrollPaneBorder"); } } diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java index b6d4bc6412bb78f7b81fa718fc7f2ee64fc3cd2c..6e98a57e5c31d266480b29822fe60203cdf961fc 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java @@ -182,8 +182,7 @@ public abstract class BasicTextUI extends TextUI implements ViewFactory { String prefix = getPropertyPrefix(); Object o = DefaultLookup.get(editor, this, prefix + ".keyBindings"); - if ((o != null) && (o instanceof JTextComponent.KeyBinding[])) { - JTextComponent.KeyBinding[] bindings = (JTextComponent.KeyBinding[]) o; + if (o instanceof JTextComponent.KeyBinding[] bindings) { JTextComponent.loadKeymap(map, bindings, getComponent().getActions()); } } @@ -536,8 +535,7 @@ public abstract class BasicTextUI extends TextUI implements ViewFactory { * should allow Tab to keyboard - accessibility */ EditorKit editorKit = getEditorKit(editor); - if ( editorKit != null - && editorKit instanceof DefaultEditorKit) { + if (editorKit instanceof DefaultEditorKit) { Set storedForwardTraversalKeys = editor. getFocusTraversalKeys(KeyboardFocusManager. FORWARD_TRAVERSAL_KEYS); @@ -617,9 +615,8 @@ public abstract class BasicTextUI extends TextUI implements ViewFactory { if (getEditorKit(editor) instanceof DefaultEditorKit) { if (map != null) { Object obj = map.get(DefaultEditorKit.insertBreakAction); - if (obj != null - && obj instanceof DefaultEditorKit.InsertBreakAction) { - Action action = new TextActionWrapper((TextAction)obj); + if (obj instanceof DefaultEditorKit.InsertBreakAction breakAction) { + Action action = new TextActionWrapper(breakAction); componentMap.put(action.getValue(Action.NAME),action); } } diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicToolBarUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicToolBarUI.java index a1d47aa4408f1da3feb3e4761ab992a155e20f7b..8a13bf119a5d140ca04b99e518b9bf084784ee23 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicToolBarUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicToolBarUI.java @@ -654,8 +654,8 @@ public class BasicToolBarUI extends ToolBarUI implements SwingConstants Container p; for(p = toolBar.getParent() ; p != null && !(p instanceof Window) ; p = p.getParent()); - if(p != null && p instanceof Window) - frame = (Window) p; + if (p instanceof Window window) + frame = window; } if(floatingToolBar == null) { floatingToolBar = createFloatingWindow(toolBar); diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTreeUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTreeUI.java index 650048a99734d13b58ecf79de4da19c645cf38b0..2626b1c9585023f3bdc59d378b1d42d53d7afb26 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTreeUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTreeUI.java @@ -1131,10 +1131,8 @@ public class BasicTreeUI extends TreeUI * @return a default cell editor */ protected TreeCellEditor createDefaultCellEditor() { - if(currentCellRenderer != null && - (currentCellRenderer instanceof DefaultTreeCellRenderer)) { - DefaultTreeCellEditor editor = new DefaultTreeCellEditor - (tree, (DefaultTreeCellRenderer)currentCellRenderer); + if (currentCellRenderer instanceof DefaultTreeCellRenderer defaultRenderer) { + DefaultTreeCellEditor editor = new DefaultTreeCellEditor(tree, defaultRenderer); return editor; } diff --git a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalBorders.java b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalBorders.java index 56e7cf7a798238329e2701ebe36c462d0c561294..9513b723490f18a03c51cfd4b2272d06dacd0a29 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalBorders.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalBorders.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,7 +47,7 @@ import sun.swing.SwingUtilities2; * Factory object that can vend Borders appropriate for the metal L & F. * @author Steve Wilson */ - +@SuppressWarnings("doclint:missing") public class MetalBorders { /** diff --git a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalFileChooserUI.java b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalFileChooserUI.java index a17890806c3e8e6146a67031f02dcfc310409d02..997af4983a3a58ac8407eb98ec12b53ad0f731ae 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalFileChooserUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalFileChooserUI.java @@ -1142,8 +1142,8 @@ public class MetalFileChooserUI extends BasicFileChooserUI { super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); - if (value != null && value instanceof FileFilter) { - setText(((FileFilter)value).getDescription()); + if (value instanceof FileFilter fileFilter) { + setText(fileFilter.getDescription()); } return this; diff --git a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTextFieldUI.java b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTextFieldUI.java index 29aacf365f14a3e0d65fd2584e1d4b2ff67a837a..707c438180d5f1b69285776e417131a1e3dc6303 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTextFieldUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTextFieldUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -147,8 +147,7 @@ public class SynthTextFieldUI extends BasicTextFieldUI implements SynthUI { Caret caret = comp.getCaret(); if (caret instanceof UIResource) { Object o = style.get(context, prefix + ".caretBlinkRate"); - if (o != null && o instanceof Integer) { - Integer rate = (Integer)o; + if (o instanceof Integer rate) { caret.setBlinkRate(rate.intValue()); } } diff --git a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTreeUI.java b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTreeUI.java index d7cf0aa99f88389a83f05174460790427d2e7c8b..ce9ae2813e843aacbca32418d9d08620db40c822 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTreeUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTreeUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -203,9 +203,8 @@ public class SynthTreeUI extends BasicTreeUI TreeCellRenderer renderer = tree.getCellRenderer(); DefaultTreeCellEditor editor; - if(renderer != null && (renderer instanceof DefaultTreeCellRenderer)) { - editor = new SynthTreeCellEditor(tree, (DefaultTreeCellRenderer) - renderer); + if (renderer instanceof DefaultTreeCellRenderer defaultRenderer) { + editor = new SynthTreeCellEditor(tree, defaultRenderer); } else { editor = new SynthTreeCellEditor(tree, null); diff --git a/src/java.desktop/share/classes/javax/swing/text/BoxView.java b/src/java.desktop/share/classes/javax/swing/text/BoxView.java index 1988adcad344c2c1c27156997fc02c4baa280a39..afaefacccf5457dcf74c8cfdcf67a4c6e06cf99b 100644 --- a/src/java.desktop/share/classes/javax/swing/text/BoxView.java +++ b/src/java.desktop/share/classes/javax/swing/text/BoxView.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1150,9 +1150,9 @@ public class BoxView extends CompositeView { int index = getViewIndexAtPosition(testPos); if(index != -1) { View v = getView(index); - if(v != null && v instanceof CompositeView) { - return ((CompositeView)v).flipEastAndWestAtEnds(position, - bias); + if (v instanceof CompositeView compositeView) { + return compositeView.flipEastAndWestAtEnds(position, + bias); } } } diff --git a/src/java.desktop/share/classes/javax/swing/text/DefaultStyledDocument.java b/src/java.desktop/share/classes/javax/swing/text/DefaultStyledDocument.java index 721421f780c77d41db40c2c7f4b37b4a00c61fa1..f549f522ff2b7513449091c0a64ca8aebe4636ac 100644 --- a/src/java.desktop/share/classes/javax/swing/text/DefaultStyledDocument.java +++ b/src/java.desktop/share/classes/javax/swing/text/DefaultStyledDocument.java @@ -438,11 +438,11 @@ public class DefaultStyledDocument extends AbstractDocument implements StyledDoc */ public void setLogicalStyle(int pos, Style s) { Element paragraph = getParagraphElement(pos); - if ((paragraph != null) && (paragraph instanceof AbstractElement)) { + if (paragraph instanceof AbstractElement abstractElement) { try { writeLock(); - StyleChangeUndoableEdit edit = new StyleChangeUndoableEdit((AbstractElement)paragraph, s); - ((AbstractElement)paragraph).setResolveParent(s); + StyleChangeUndoableEdit edit = new StyleChangeUndoableEdit(abstractElement, s); + abstractElement.setResolveParent(s); int p0 = paragraph.getStartOffset(); int p1 = paragraph.getEndOffset(); DefaultDocumentEvent e = diff --git a/src/java.desktop/share/classes/javax/swing/text/JTextComponent.java b/src/java.desktop/share/classes/javax/swing/text/JTextComponent.java index 69c7e39d703eda6714f4937cc336184ce2e78ff4..cbdd308cc84b81dc0b516a9da0ad7d9d25e5105c 100644 --- a/src/java.desktop/share/classes/javax/swing/text/JTextComponent.java +++ b/src/java.desktop/share/classes/javax/swing/text/JTextComponent.java @@ -3302,8 +3302,7 @@ public abstract class JTextComponent extends JComponent implements Scrollable, A // Fixes bug 4487492 Document doc = JTextComponent.this.getDocument(); - if (doc != null && doc instanceof StyledDocument) { - StyledDocument sDoc = (StyledDocument)doc; + if (doc instanceof StyledDocument sDoc) { int offset = startIndex; int length = endIndex - startIndex; sDoc.setCharacterAttributes(offset, length, as, true); diff --git a/src/java.desktop/share/classes/javax/swing/text/LayeredHighlighter.java b/src/java.desktop/share/classes/javax/swing/text/LayeredHighlighter.java index 08291e7176933741969b52c3056d9c9ad9c5c517..c50710233fcc561cb0e22844c18e7f84148d3205 100644 --- a/src/java.desktop/share/classes/javax/swing/text/LayeredHighlighter.java +++ b/src/java.desktop/share/classes/javax/swing/text/LayeredHighlighter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,7 @@ import java.awt.Shape; * @author Timothy Prinzing * @see Highlighter */ +@SuppressWarnings("doclint:missing") public abstract class LayeredHighlighter implements Highlighter { /** * Constructor for subclasses to call. diff --git a/src/java.desktop/share/classes/javax/swing/text/StringContent.java b/src/java.desktop/share/classes/javax/swing/text/StringContent.java index c66156a39f202898a3a39734e94e0823aedc690e..7f154df38edffce7203667f93ff9980c0c6268ba 100644 --- a/src/java.desktop/share/classes/javax/swing/text/StringContent.java +++ b/src/java.desktop/share/classes/javax/swing/text/StringContent.java @@ -350,7 +350,7 @@ public final class StringContent implements AbstractDocument.Content, Serializab return rec.offset; } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { // schedule the record to be removed later // on another thread. diff --git a/src/java.desktop/share/classes/javax/swing/text/html/AccessibleHTML.java b/src/java.desktop/share/classes/javax/swing/text/html/AccessibleHTML.java index a756cb2a02fbfcf60e5a2d8f45d66ae9ae00be13..ba8465d45704185ab7a86a6afa6973cd6a8eed42 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/AccessibleHTML.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/AccessibleHTML.java @@ -370,8 +370,8 @@ class AccessibleHTML implements Accessible { */ public Accessible getAccessibleChild(int i) { ElementInfo childInfo = elementInfo.getChild(i); - if (childInfo != null && childInfo instanceof Accessible) { - return (Accessible)childInfo; + if (childInfo instanceof Accessible accessibleChild) { + return accessibleChild; } else { return null; } @@ -1212,9 +1212,8 @@ class AccessibleHTML implements Accessible { private String getText(int offset, int length) throws BadLocationException { - if (model != null && model instanceof StyledDocument) { - StyledDocument doc = (StyledDocument)model; - return model.getText(offset, length); + if (model instanceof StyledDocument doc) { + return doc.getText(offset, length); } else { return null; } diff --git a/src/java.desktop/share/classes/javax/swing/text/html/CSS.java b/src/java.desktop/share/classes/javax/swing/text/html/CSS.java index 76ce4ac815f270e5e62ac7668734d6f868e0fd9c..22fa96b615337548703e8e98bedf447b78c6b84b 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/CSS.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/CSS.java @@ -1608,8 +1608,8 @@ public class CSS implements Serializable { if (key instanceof HTML.Tag) { HTML.Tag tag = (HTML.Tag)key; Object o = htmlAttrSet.getAttribute(tag); - if (o != null && o instanceof AttributeSet) { - translateAttributes(tag, (AttributeSet)o, cssAttrSet); + if (o instanceof AttributeSet as) { + translateAttributes(tag, as, cssAttrSet); } } else if (key instanceof CSS.Attribute) { cssAttrSet.addAttribute(key, htmlAttrSet.getAttribute(key)); diff --git a/src/java.desktop/share/classes/javax/swing/text/html/HRuleView.java b/src/java.desktop/share/classes/javax/swing/text/html/HRuleView.java index bacd81d271c4b93f63e3936e6ccbcdeb8bf1bc9f..885f0b7f2c9d63411d4b0210a5d22c957531db11 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/HRuleView.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/HRuleView.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -72,16 +72,16 @@ class HRuleView extends View { noshade = (String)eAttr.getAttribute(HTML.Attribute.NOSHADE); Object value = eAttr.getAttribute(HTML.Attribute.SIZE); - if (value != null && (value instanceof String)) { + if (value instanceof String s) { try { - size = Integer.parseInt((String)value); + size = Integer.parseInt(s); } catch (NumberFormatException e) { size = 1; } } value = attr.getAttribute(CSS.Attribute.WIDTH); - if (value != null && (value instanceof CSS.LengthValue)) { - widthValue = (CSS.LengthValue)value; + if (value instanceof CSS.LengthValue lv) { + widthValue = lv; } topMargin = getLength(CSS.Attribute.MARGIN_TOP, attr); bottomMargin = getLength(CSS.Attribute.MARGIN_BOTTOM, attr); diff --git a/src/java.desktop/share/classes/javax/swing/text/html/HTML.java b/src/java.desktop/share/classes/javax/swing/text/html/HTML.java index d23b2753580e980855683174849683347188b1b1..a27893d9fccbc241289f82fa3ffd2a6d244e91e2 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/HTML.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/HTML.java @@ -43,6 +43,7 @@ import javax.swing.text.StyleContext; * @author Sunita Mani * */ +@SuppressWarnings("doclint:missing") public class HTML { /** diff --git a/src/java.desktop/share/classes/javax/swing/text/html/HTMLDocument.java b/src/java.desktop/share/classes/javax/swing/text/html/HTMLDocument.java index 00272bc1eaae2cf94b3f3eac527dc2ccb4bad9ce..46d84e3cadcc31da718c032f2d172a431dc3501a 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/HTMLDocument.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/HTMLDocument.java @@ -901,8 +901,8 @@ public class HTMLDocument extends DefaultStyledDocument { if (name != null) { Object maps = getProperty(MAP_PROPERTY); - if (maps != null && (maps instanceof Hashtable)) { - return (Map)((Hashtable)maps).get(name); + if (maps instanceof Hashtable hashtable) { + return (Map) hashtable.get(name); } } return null; diff --git a/src/java.desktop/share/classes/javax/swing/text/html/HTMLEditorKit.java b/src/java.desktop/share/classes/javax/swing/text/html/HTMLEditorKit.java index b6b0b789eefc387f92c982e84406c2fe14fa1395..c85989533f2b8fce1b5438a4e4bbd34b764d8d02 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/HTMLEditorKit.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/HTMLEditorKit.java @@ -216,7 +216,8 @@ import static java.nio.charset.StandardCharsets.ISO_8859_1; * * @author Timothy Prinzing */ -@SuppressWarnings("serial") // Same-version serialization only +@SuppressWarnings({"serial", // Same-version serialization only + "doclint:missing"}) public class HTMLEditorKit extends StyledEditorKit implements Accessible { private JEditorPane theEditor; @@ -841,8 +842,8 @@ public class HTMLEditorKit extends StyledEditorKit implements Accessible { Element elem, AttributeSet attr, int offset, int x, int y) { Object useMap = attr.getAttribute(HTML.Attribute.USEMAP); - if (useMap != null && (useMap instanceof String)) { - Map m = hdoc.getMap((String)useMap); + if (useMap instanceof String s) { + Map m = hdoc.getMap(s); if (m != null && offset < hdoc.getLength()) { Rectangle bounds; TextUI ui = html.getUI(); @@ -1467,12 +1468,8 @@ public class HTMLEditorKit extends StyledEditorKit implements Accessible { protected void layoutMinorAxis(int targetSpan, int axis, int[] offsets, int[] spans) { Container container = getContainer(); - Container parentContainer; - if (container != null - && (container instanceof javax.swing.JEditorPane) - && (parentContainer = container.getParent()) != null - && (parentContainer instanceof javax.swing.JViewport)) { - JViewport viewPort = (JViewport)parentContainer; + if ((container instanceof JEditorPane) + && (container.getParent() instanceof JViewport viewPort)) { if (cachedViewPort != null) { JViewport cachedObject = cachedViewPort.get(); if (cachedObject != null) { @@ -2387,9 +2384,9 @@ public class HTMLEditorKit extends StyledEditorKit implements Accessible { */ private void doObjectAction(JEditorPane editor, Element elem) { View view = getView(editor, elem); - if (view != null && view instanceof ObjectView) { - Component comp = ((ObjectView)view).getComponent(); - if (comp != null && comp instanceof Accessible) { + if (view instanceof ObjectView objectView) { + Component comp = objectView.getComponent(); + if (comp instanceof Accessible) { AccessibleContext ac = comp.getAccessibleContext(); if (ac != null) { AccessibleAction aa = ac.getAccessibleAction(); @@ -2473,10 +2470,9 @@ public class HTMLEditorKit extends StyledEditorKit implements Accessible { JEditorPane editor = (JEditorPane)c; Document d = editor.getDocument(); - if (d == null || !(d instanceof HTMLDocument)) { + if (!(d instanceof HTMLDocument doc)) { return; } - HTMLDocument doc = (HTMLDocument)d; ElementIterator ei = new ElementIterator(doc); int currentOffset = editor.getCaretPosition(); diff --git a/src/java.desktop/share/classes/javax/swing/text/html/HTMLWriter.java b/src/java.desktop/share/classes/javax/swing/text/html/HTMLWriter.java index a166235d4c205faff1cff053b67d5c352a6a8744..c11214d71e3bce696dcef6900888ad0eabf6ce92 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/HTMLWriter.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/HTMLWriter.java @@ -308,9 +308,7 @@ public class HTMLWriter extends AbstractWriter { // If an instance of an UNKNOWN Tag, or an instance of a // tag that is only visible during editing // - if (nameTag != null && endTag != null && - (endTag instanceof String) && - endTag.equals("true")) { + if (nameTag != null && "true".equals(endTag)) { outputEndTag = true; } @@ -732,8 +730,8 @@ public class HTMLWriter extends AbstractWriter { write('<'); write(tag.toString()); Object o = attr.getAttribute(tag); - if (o != null && o instanceof AttributeSet) { - writeAttributes((AttributeSet)o); + if (o instanceof AttributeSet as) { + writeAttributes(as); } write('>'); tags.addElement(tag); @@ -813,8 +811,8 @@ public class HTMLWriter extends AbstractWriter { write('<'); write(t.toString()); Object o = tagValues.elementAt(i); - if (o != null && o instanceof AttributeSet) { - writeAttributes((AttributeSet)o); + if (o instanceof AttributeSet as) { + writeAttributes(as); } write('>'); } diff --git a/src/java.desktop/share/classes/javax/swing/text/html/HiddenTagView.java b/src/java.desktop/share/classes/javax/swing/text/html/HiddenTagView.java index 325bec6b8d6da60d0fd38736af0db71e9cf10daf..25406848bf78b8d1a39d98a57bffa7ffd68f41bd 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/HiddenTagView.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/HiddenTagView.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -271,8 +271,7 @@ class HiddenTagView extends EditableView implements DocumentListener { AttributeSet as = getElement().getAttributes(); if (as != null) { Object end = as.getAttribute(HTML.Attribute.ENDTAG); - if (end != null && (end instanceof String) && - ((String)end).equals("true")) { + if ("true".equals(end)) { return true; } } diff --git a/src/java.desktop/share/classes/javax/swing/text/html/Map.java b/src/java.desktop/share/classes/javax/swing/text/html/Map.java index cc79b5aeb3bbbbfbeaf174888a1bd9b8fd14cf74..c88d4e7495bcfca1f12d63ecf7f3111010412a78 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/Map.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/Map.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -181,12 +181,11 @@ class Map implements Serializable { * from trying to parse one of the numbers null is returned. */ protected static int[] extractCoords(Object stringCoords) { - if (stringCoords == null || !(stringCoords instanceof String)) { + if (!(stringCoords instanceof String s)) { return null; } - StringTokenizer st = new StringTokenizer((String)stringCoords, - ", \t\n\r"); + StringTokenizer st = new StringTokenizer(s, ", \t\n\r"); int[] retValue = null; int numCoords = 0; diff --git a/src/java.desktop/share/classes/javax/swing/text/html/StyleSheet.java b/src/java.desktop/share/classes/javax/swing/text/html/StyleSheet.java index 3352e0e79f89b00437e0b2dc9548b4631ffb69cf..9fb2ff25d63923725ceb6b8bc1ecfb753bb1e333 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/StyleSheet.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/StyleSheet.java @@ -2211,10 +2211,9 @@ public class StyleSheet extends StyleContext { retIndex--; } else if (as.isDefined(HTML.Attribute.VALUE)) { Object value = as.getAttribute(HTML.Attribute.VALUE); - if (value != null && - (value instanceof String)) { + if (value instanceof String s) { try { - int iValue = Integer.parseInt((String)value); + int iValue = Integer.parseInt(s); return retIndex - counter + iValue; } catch (NumberFormatException nfe) {} @@ -2744,8 +2743,7 @@ public class StyleSheet extends StyleContext { kind of conditional behaviour in the stylesheet. **/ - if (o != null && o instanceof AttributeSet) { - AttributeSet attr = (AttributeSet)o; + if (o instanceof AttributeSet attr) { if (attr.getAttribute(HTML.Attribute.HREF) == null) { continue; } diff --git a/src/java.desktop/share/classes/javax/swing/text/html/parser/AttributeList.java b/src/java.desktop/share/classes/javax/swing/text/html/parser/AttributeList.java index 898e9367171889bb4ca7ba99d72d26f623105172..f57a7f2a9174a9c41fe3d1c9a4f3517c4fd5a41a 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/parser/AttributeList.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/parser/AttributeList.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,7 +44,8 @@ import java.io.*; * @author Arthur Van Hoff * */ -@SuppressWarnings("serial") // Same-version serialization only +@SuppressWarnings({"serial", // Same-version serialization only + "doclint:missing"}) public final class AttributeList implements DTDConstants, Serializable { diff --git a/src/java.desktop/share/classes/javax/swing/text/html/parser/Parser.java b/src/java.desktop/share/classes/javax/swing/text/html/parser/Parser.java index 2a59e3b2163431801dddedec3028676b9d159855..fc7cac3cdc17f79882e1ea1602c244a73fc24b75 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/parser/Parser.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/parser/Parser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -75,6 +75,7 @@ import java.net.URL; * @author Arthur van Hoff * @author Sunita Mani */ +@SuppressWarnings("doclint:missing") public class Parser implements DTDConstants { diff --git a/src/java.desktop/share/classes/javax/swing/text/rtf/RTFGenerator.java b/src/java.desktop/share/classes/javax/swing/text/rtf/RTFGenerator.java index 46a7ce7efb98603f1e83db806e9f91a15ca60b1e..82ee2fffb0bfba218301c135502c1bd076d86fb2 100644 --- a/src/java.desktop/share/classes/javax/swing/text/rtf/RTFGenerator.java +++ b/src/java.desktop/share/classes/javax/swing/text/rtf/RTFGenerator.java @@ -391,7 +391,7 @@ public void writeRTFHeader() updateCharacterAttributes(goat, style, false); basis = style.getResolveParent(); - if (basis != null && basis instanceof Style) { + if (basis instanceof Style) { Integer basedOn = styleTable.get(basis); if (basedOn != null) { writeControlWord("sbasedon", basedOn.intValue()); diff --git a/src/java.desktop/share/classes/javax/swing/tree/DefaultMutableTreeNode.java b/src/java.desktop/share/classes/javax/swing/tree/DefaultMutableTreeNode.java index 0b8b6679ded33099f6f159cce568dd7baaeb420e..7735895502ecce78574ffbbf314c928975b9ec26 100644 --- a/src/java.desktop/share/classes/javax/swing/tree/DefaultMutableTreeNode.java +++ b/src/java.desktop/share/classes/javax/swing/tree/DefaultMutableTreeNode.java @@ -1297,8 +1297,8 @@ public class DefaultMutableTreeNode implements Cloneable, Object[] tValues; s.defaultWriteObject(); - // Save the userObject, if its Serializable. - if(userObject != null && userObject instanceof Serializable) { + // Save the userObject, if it's Serializable. + if (userObject instanceof Serializable) { tValues = new Object[2]; tValues[0] = "userObject"; tValues[1] = userObject; diff --git a/src/java.desktop/share/classes/javax/swing/tree/DefaultTreeModel.java b/src/java.desktop/share/classes/javax/swing/tree/DefaultTreeModel.java index 6bc1478309862f4eea0cc848aebf28ebb80724ce..6d2a692c0436f1a28c4b3130d76b81e3f837dd88 100644 --- a/src/java.desktop/share/classes/javax/swing/tree/DefaultTreeModel.java +++ b/src/java.desktop/share/classes/javax/swing/tree/DefaultTreeModel.java @@ -690,8 +690,8 @@ public class DefaultTreeModel implements Serializable, TreeModel { Vector values = new Vector(); s.defaultWriteObject(); - // Save the root, if its Serializable. - if(root != null && root instanceof Serializable) { + // Save the root, if it's Serializable. + if (root instanceof Serializable) { values.addElement("root"); values.addElement(root); } diff --git a/src/java.desktop/share/classes/javax/swing/tree/DefaultTreeSelectionModel.java b/src/java.desktop/share/classes/javax/swing/tree/DefaultTreeSelectionModel.java index 2c592f24d2b51b6ff184ccc4ea3e66e040937400..e1bdc4fc94b3952bdf3856f43dc80d3979e1361c 100644 --- a/src/java.desktop/share/classes/javax/swing/tree/DefaultTreeSelectionModel.java +++ b/src/java.desktop/share/classes/javax/swing/tree/DefaultTreeSelectionModel.java @@ -1217,7 +1217,7 @@ public class DefaultTreeSelectionModel implements Cloneable, Serializable, TreeS s.defaultWriteObject(); // Save the rowMapper, if it implements Serializable - if(rowMapper != null && rowMapper instanceof Serializable) { + if (rowMapper instanceof Serializable) { tValues = new Object[2]; tValues[0] = "rowMapper"; tValues[1] = rowMapper; diff --git a/src/java.desktop/share/classes/javax/swing/undo/UndoableEditSupport.java b/src/java.desktop/share/classes/javax/swing/undo/UndoableEditSupport.java index decd6afb9a044bc5e9868202ce1411de1bba79c3..5646222ecb11f1ce7ba8b2df4c2075bab49bb94c 100644 --- a/src/java.desktop/share/classes/javax/swing/undo/UndoableEditSupport.java +++ b/src/java.desktop/share/classes/javax/swing/undo/UndoableEditSupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,7 @@ import java.util.*; * * @author Ray Ryan */ +@SuppressWarnings("doclint:missing") public class UndoableEditSupport { /** * The update level. diff --git a/src/java.desktop/share/classes/sun/awt/im/InputContext.java b/src/java.desktop/share/classes/sun/awt/im/InputContext.java index 3ca1f6cedb988d9e9caff5905e526c3c0e9531ce..c35d17bfae3611114bb36694888975065cce65c2 100644 --- a/src/java.desktop/share/classes/sun/awt/im/InputContext.java +++ b/src/java.desktop/share/classes/sun/awt/im/InputContext.java @@ -790,8 +790,8 @@ public class InputContext extends java.awt.im.InputContext */ public void disableNativeIM() { InputMethod inputMethod = getInputMethod(); - if (inputMethod != null && inputMethod instanceof InputMethodAdapter) { - ((InputMethodAdapter)inputMethod).stopListening(); + if (inputMethod instanceof InputMethodAdapter adapter) { + adapter.stopListening(); } } diff --git a/src/java.desktop/share/classes/sun/awt/shell/ShellFolder.java b/src/java.desktop/share/classes/sun/awt/shell/ShellFolder.java index dd0d43bcf460dc8e6988b6168b07323ce229d431..0c375a900a0aae852f1e1edbc5a5e60319b357ff 100644 --- a/src/java.desktop/share/classes/sun/awt/shell/ShellFolder.java +++ b/src/java.desktop/share/classes/sun/awt/shell/ShellFolder.java @@ -181,9 +181,7 @@ public abstract class ShellFolder extends File { * @see #compareTo(Object) */ public int compareTo(File file2) { - if (file2 == null || !(file2 instanceof ShellFolder) - || ((file2 instanceof ShellFolder) && ((ShellFolder)file2).isFileSystem())) { - + if (!(file2 instanceof ShellFolder sf) || sf.isFileSystem()) { if (isFileSystem()) { return super.compareTo(file2); } else { diff --git a/src/java.desktop/share/classes/sun/awt/util/IdentityArrayList.java b/src/java.desktop/share/classes/sun/awt/util/IdentityArrayList.java index 8f1bbdc4714d178fc47645d576c4f0502685be28..98f93cc3ec7027fa9942a230d7889addeb9ea0df 100644 --- a/src/java.desktop/share/classes/sun/awt/util/IdentityArrayList.java +++ b/src/java.desktop/share/classes/sun/awt/util/IdentityArrayList.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -203,7 +203,7 @@ public class IdentityArrayList extends AbstractList * Returns {@code true} if this list contains the specified element. * More formally, returns {@code true} if and only if this list contains * at least one element {@code e} such that - * {@code Objects.equals(o, e)}. + * {@code o == e}. * * @param o element whose presence in this list is to be tested * @return {@code true} if this list contains the specified element @@ -216,8 +216,12 @@ public class IdentityArrayList extends AbstractList * Returns the index of the first occurrence of the specified element * in this list, or -1 if this list does not contain the element. * More formally, returns the lowest index {@code i} such that - * {@code Objects.equals(o, get(i))}, + * {@code get(i) == o}, * or -1 if there is no such index. + * + * @param o element to search for + * @return the index of the first occurrence of the specified element in + * this list, or -1 if this list does not contain the element */ public int indexOf(Object o) { for (int i = 0; i < size; i++) { @@ -232,8 +236,12 @@ public class IdentityArrayList extends AbstractList * Returns the index of the last occurrence of the specified element * in this list, or -1 if this list does not contain the element. * More formally, returns the highest index {@code i} such that - * {@code Objects.equals(o, get(i))}, + * {@code get(i) == o}, * or -1 if there is no such index. + * + * @param o element to search for + * @return the index of the last occurrence of the specified element in + * this list, or -1 if this list does not contain the element */ public int lastIndexOf(Object o) { for (int i = size-1; i >= 0; i--) { @@ -390,9 +398,9 @@ public class IdentityArrayList extends AbstractList /** * Removes the first occurrence of the specified element from this list, - * if it is present. If the list does not contain the element, it is + * if it is present. If this list does not contain the element, the list is * unchanged. More formally, removes the element with the lowest index - * {@code i} such that {@code Objects.equals(o, get(i))} + * {@code i} such that {@code get(i) == o} * (if such an element exists). Returns {@code true} if this list * contained the specified element (or equivalently, if this list * changed as a result of the call). diff --git a/src/java.desktop/share/classes/sun/awt/util/IdentityLinkedList.java b/src/java.desktop/share/classes/sun/awt/util/IdentityLinkedList.java index 21474bafcfdb5aed89b172cb09f236180994d41a..fef09665bc0788650a1685a108042c3b8f50e539 100644 --- a/src/java.desktop/share/classes/sun/awt/util/IdentityLinkedList.java +++ b/src/java.desktop/share/classes/sun/awt/util/IdentityLinkedList.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -183,7 +183,7 @@ public class IdentityLinkedList * Returns {@code true} if this list contains the specified element. * More formally, returns {@code true} if and only if this list contains * at least one element {@code e} such that - * {@code Objects.equals(o, e)}. + * {@code o == e}. * * @param o element whose presence in this list is to be tested * @return {@code true} if this list contains the specified element @@ -218,7 +218,7 @@ public class IdentityLinkedList * Removes the first occurrence of the specified element from this list, * if it is present. If this list does not contain the element, it is * unchanged. More formally, removes the element with the lowest index - * {@code i} such that {@code get(i)==o} + * {@code i} such that {@code get(i) == o} * (if such an element exists). Returns {@code true} if this list * contained the specified element (or equivalently, if this list * changed as a result of the call). @@ -389,7 +389,7 @@ public class IdentityLinkedList * Returns the index of the first occurrence of the specified element * in this list, or -1 if this list does not contain the element. * More formally, returns the lowest index {@code i} such that - * {@code get(i)==o}, + * {@code get(i) == o}, * or -1 if there is no such index. * * @param o element to search for @@ -411,7 +411,7 @@ public class IdentityLinkedList * Returns the index of the last occurrence of the specified element * in this list, or -1 if this list does not contain the element. * More formally, returns the highest index {@code i} such that - * {@code get(i)==o}, + * {@code get(i) == o}, * or -1 if there is no such index. * * @param o element to search for diff --git a/src/java.desktop/share/classes/sun/font/AttributeValues.java b/src/java.desktop/share/classes/sun/font/AttributeValues.java index 910195a2a9eb41c70a7956e744850951e31b83e3..6b3c0aaf4e29b4be369900bd192f44f2f5903c48 100644 --- a/src/java.desktop/share/classes/sun/font/AttributeValues.java +++ b/src/java.desktop/share/classes/sun/font/AttributeValues.java @@ -764,8 +764,8 @@ public final class AttributeValues implements Cloneable { return ((AttributeMap)map).getValues().justification; } Object obj = map.get(TextAttribute.JUSTIFICATION); - if (obj != null && obj instanceof Number) { - return max(0, min(1, ((Number)obj).floatValue())); + if (obj instanceof Number number) { + return max(0, min(1, number.floatValue())); } } return DEFAULT.justification; @@ -778,8 +778,8 @@ public final class AttributeValues implements Cloneable { return ((AttributeMap)map).getValues().numericShaping; } Object obj = map.get(TextAttribute.NUMERIC_SHAPING); - if (obj != null && obj instanceof NumericShaper) { - return (NumericShaper)obj; + if (obj instanceof NumericShaper shaper) { + return shaper; } } return DEFAULT.numericShaping; diff --git a/src/java.desktop/share/classes/sun/font/FontUtilities.java b/src/java.desktop/share/classes/sun/font/FontUtilities.java index 550cdcce3cf3f38b5779477ae6819fb1027a025a..c4f8c317a92b8f3c813a58e331e3ef1c5098bceb 100644 --- a/src/java.desktop/share/classes/sun/font/FontUtilities.java +++ b/src/java.desktop/share/classes/sun/font/FontUtilities.java @@ -413,10 +413,9 @@ public final class FontUtilities { FontManager fm = FontManagerFactory.getInstance(); Font2D dialog = fm.findFont2D("dialog", font.getStyle(), FontManager.NO_FALLBACK); // Should never be null, but MACOSX fonts are not CompositeFonts - if (dialog == null || !(dialog instanceof CompositeFont)) { + if (!(dialog instanceof CompositeFont dialog2D)) { return fuir; } - CompositeFont dialog2D = (CompositeFont)dialog; PhysicalFont physicalFont = (PhysicalFont)font2D; ConcurrentHashMap compMap = compMapRef.get(); if (compMap == null) { // Its been collected. diff --git a/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java b/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java index 15db79d69d2f95219f648049ba5459949c55bef8..b5b5225938b3a441dd24f0b125751933f2963f41 100644 --- a/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java +++ b/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java @@ -3656,7 +3656,7 @@ public final class SunGraphics2D * enough to know that if our override is empty then it should not * mark us as finalizeable. */ - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") public void finalize() { // DO NOT REMOVE THIS METHOD } diff --git a/src/java.desktop/share/classes/sun/print/PSStreamPrintService.java b/src/java.desktop/share/classes/sun/print/PSStreamPrintService.java index d221522940593e66ad9d26fd8e72f40faf9b64d9..62a28e0505261c016118840db40be102a7838136 100644 --- a/src/java.desktop/share/classes/sun/print/PSStreamPrintService.java +++ b/src/java.desktop/share/classes/sun/print/PSStreamPrintService.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -320,8 +320,7 @@ public class PSStreamPrintService extends StreamPrintService MediaSize mediaSize = (MediaSize)attributes.get(MediaSize.class); if (mediaSize == null) { Media media = (Media)attributes.get(Media.class); - if (media != null && media instanceof MediaSizeName) { - MediaSizeName msn = (MediaSizeName)media; + if (media instanceof MediaSizeName msn) { mediaSize = MediaSize.getMediaSizeForName(msn); } } diff --git a/src/java.desktop/share/classes/sun/print/PathGraphics.java b/src/java.desktop/share/classes/sun/print/PathGraphics.java index 1fbd7fa68d6c232635f2730abef2a1835387e47d..2235f82aab595928375678e8950b302c73f4a78c 100644 --- a/src/java.desktop/share/classes/sun/print/PathGraphics.java +++ b/src/java.desktop/share/classes/sun/print/PathGraphics.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -895,8 +895,8 @@ public abstract class PathGraphics extends ProxyGraphics2D { */ Map map = font.getAttributes(); Object o = map.get(TextAttribute.TRACKING); - boolean tracking = o != null && (o instanceof Number) && - (((Number)o).floatValue() != 0f); + boolean tracking = (o instanceof Number n) && + (n.floatValue() != 0f); if (tracking) { noPositionAdjustments = false; diff --git a/src/java.desktop/share/classes/sun/print/PeekGraphics.java b/src/java.desktop/share/classes/sun/print/PeekGraphics.java index c400ad59ca2b59b3f8da2ca70b72f469b355ae5c..b5eabc847739d312604b46d002b96f97af76e925 100644 --- a/src/java.desktop/share/classes/sun/print/PeekGraphics.java +++ b/src/java.desktop/share/classes/sun/print/PeekGraphics.java @@ -1336,7 +1336,7 @@ public class PeekGraphics extends Graphics2D /** * Empty finalizer as no clean up needed here. */ - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") public void finalize() { } diff --git a/src/java.desktop/share/classes/sun/print/PrintJob2D.java b/src/java.desktop/share/classes/sun/print/PrintJob2D.java index 3ad1c488567c1e7cd6c7cc6b2e98864fa18dce05..9083bd3e26965be3ba66460049c4f645a5dc2b7b 100644 --- a/src/java.desktop/share/classes/sun/print/PrintJob2D.java +++ b/src/java.desktop/share/classes/sun/print/PrintJob2D.java @@ -450,8 +450,8 @@ public class PrintJob2D extends PrintJob implements Printable, Runnable { Media media = (Media)attributes.get(Media.class); MediaSize mediaSize = null; - if (media != null && media instanceof MediaSizeName) { - mediaSize = MediaSize.getMediaSizeForName((MediaSizeName)media); + if (media instanceof MediaSizeName msn) { + mediaSize = MediaSize.getMediaSizeForName(msn); } Paper p = pageFormat.getPaper(); @@ -590,9 +590,9 @@ public class PrintJob2D extends PrintJob implements Printable, Runnable { pageAttributes.setPrintQuality(PrintQualityType.NORMAL); } - Media msn = (Media)attributes.get(Media.class); - if (msn != null && msn instanceof MediaSizeName) { - MediaType mType = unMapMedia((MediaSizeName)msn); + Media media = (Media)attributes.get(Media.class); + if (media instanceof MediaSizeName msn) { + MediaType mType = unMapMedia(msn); if (mType != null) { pageAttributes.setMedia(mType); @@ -940,7 +940,7 @@ public class PrintJob2D extends PrintJob implements Printable, Runnable { * Ends this print job once it is no longer referenced. * @see #end */ - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") public void finalize() { end(); } diff --git a/src/java.desktop/share/classes/sun/print/ProxyGraphics.java b/src/java.desktop/share/classes/sun/print/ProxyGraphics.java index 124a7a487f62d1f789119376d24271526d732ea8..c6c0615c3439d8b6fed7d7aad8d00c997bac87e4 100644 --- a/src/java.desktop/share/classes/sun/print/ProxyGraphics.java +++ b/src/java.desktop/share/classes/sun/print/ProxyGraphics.java @@ -1099,7 +1099,7 @@ public class ProxyGraphics extends Graphics { /** * Empty finalizer as no clean up needed here. */ - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") public void finalize() { } diff --git a/src/java.desktop/share/classes/sun/print/ProxyGraphics2D.java b/src/java.desktop/share/classes/sun/print/ProxyGraphics2D.java index fc1c0e768108fc602ed53e27f58a997ac4d04373..c05ba9a6188e4bf2924b343a62882e2514956828 100644 --- a/src/java.desktop/share/classes/sun/print/ProxyGraphics2D.java +++ b/src/java.desktop/share/classes/sun/print/ProxyGraphics2D.java @@ -1264,7 +1264,7 @@ public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics { /** * Empty finalizer as no clean up needed here. */ - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") public void finalize() { } diff --git a/src/java.desktop/share/classes/sun/print/ServiceDialog.java b/src/java.desktop/share/classes/sun/print/ServiceDialog.java index 8db53d2d3768da971017938180b6afc415f223e4..7167ba1884f1656adbb004bab7c3dc6a5d37174f 100644 --- a/src/java.desktop/share/classes/sun/print/ServiceDialog.java +++ b/src/java.desktop/share/classes/sun/print/ServiceDialog.java @@ -1613,11 +1613,10 @@ public class ServiceDialog extends JDialog implements ActionListener { MediaSize mediaSize = null; Media media = (Media)asCurrent.get(Media.class); - if (media == null || !(media instanceof MediaSizeName)) { + if (!(media instanceof MediaSizeName)) { media = (Media)psCurrent.getDefaultAttributeValue(Media.class); } - if (media != null && (media instanceof MediaSizeName)) { - MediaSizeName msn = (MediaSizeName)media; + if (media instanceof MediaSizeName msn) { mediaSize = MediaSize.getMediaSizeForName(msn); } if (mediaSize == null) { @@ -1699,11 +1698,10 @@ public class ServiceDialog extends JDialog implements ActionListener { MediaSize mediaSize = null; Media media = (Media)asCurrent.get(Media.class); - if (media == null || !(media instanceof MediaSizeName)) { + if (!(media instanceof MediaSizeName)) { media = (Media)psCurrent.getDefaultAttributeValue(Media.class); } - if (media != null && (media instanceof MediaSizeName)) { - MediaSizeName msn = (MediaSizeName)media; + if (media instanceof MediaSizeName msn) { mediaSize = MediaSize.getMediaSizeForName(msn); } if (mediaSize == null) { diff --git a/src/java.desktop/share/classes/sun/swing/DefaultLookup.java b/src/java.desktop/share/classes/sun/swing/DefaultLookup.java index 51949f2c626e33f2722d0ee742467903fe5fb8dd..cf3919d9d97177fee317ac877cb3a29e74471af6 100644 --- a/src/java.desktop/share/classes/sun/swing/DefaultLookup.java +++ b/src/java.desktop/share/classes/sun/swing/DefaultLookup.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -132,10 +132,10 @@ public class DefaultLookup { int defaultValue) { Object iValue = get(c, ui, key); - if (iValue == null || !(iValue instanceof Number)) { - return defaultValue; + if (iValue instanceof Number number) { + return number.intValue(); } - return ((Number)iValue).intValue(); + return defaultValue; } public static int getInt(JComponent c, ComponentUI ui, String key) { @@ -146,10 +146,10 @@ public class DefaultLookup { Insets defaultValue) { Object iValue = get(c, ui, key); - if (iValue == null || !(iValue instanceof Insets)) { - return defaultValue; + if (iValue instanceof Insets insets) { + return insets; } - return (Insets)iValue; + return defaultValue; } public static Insets getInsets(JComponent c, ComponentUI ui, String key) { @@ -160,10 +160,10 @@ public class DefaultLookup { boolean defaultValue) { Object iValue = get(c, ui, key); - if (iValue == null || !(iValue instanceof Boolean)) { - return defaultValue; + if (iValue instanceof Boolean b) { + return b; } - return ((Boolean)iValue).booleanValue(); + return defaultValue; } public static boolean getBoolean(JComponent c, ComponentUI ui, String key) { @@ -174,10 +174,10 @@ public class DefaultLookup { Color defaultValue) { Object iValue = get(c, ui, key); - if (iValue == null || !(iValue instanceof Color)) { - return defaultValue; + if (iValue instanceof Color color) { + return color; } - return (Color)iValue; + return defaultValue; } public static Color getColor(JComponent c, ComponentUI ui, String key) { @@ -187,10 +187,10 @@ public class DefaultLookup { public static Icon getIcon(JComponent c, ComponentUI ui, String key, Icon defaultValue) { Object iValue = get(c, ui, key); - if (iValue == null || !(iValue instanceof Icon)) { - return defaultValue; + if (iValue instanceof Icon icon) { + return icon; } - return (Icon)iValue; + return defaultValue; } public static Icon getIcon(JComponent c, ComponentUI ui, String key) { @@ -200,10 +200,10 @@ public class DefaultLookup { public static Border getBorder(JComponent c, ComponentUI ui, String key, Border defaultValue) { Object iValue = get(c, ui, key); - if (iValue == null || !(iValue instanceof Border)) { - return defaultValue; + if (iValue instanceof Border border) { + return border; } - return (Border)iValue; + return defaultValue; } public static Border getBorder(JComponent c, ComponentUI ui, String key) { diff --git a/src/java.desktop/share/classes/sun/swing/MenuItemLayoutHelper.java b/src/java.desktop/share/classes/sun/swing/MenuItemLayoutHelper.java index ff2898d0f72ba297cb64042cd52df820895b8579..6859fb0bab5612c4eada0dd87c466edfd477e635 100644 --- a/src/java.desktop/share/classes/sun/swing/MenuItemLayoutHelper.java +++ b/src/java.desktop/share/classes/sun/swing/MenuItemLayoutHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -378,10 +378,10 @@ public class MenuItemLayoutHelper { if (miParent != null) { value = miParent.getClientProperty(propertyName); } - if ((value == null) || !(value instanceof Integer)) { - value = 0; + if (value instanceof Integer intValue) { + return intValue; } - return (Integer) value; + return 0; } public static boolean isColumnLayout(boolean isLeftToRight, diff --git a/src/java.desktop/share/classes/sun/swing/SwingUtilities2.java b/src/java.desktop/share/classes/sun/swing/SwingUtilities2.java index e746dad6e7ee07554c582b9a140f2d4d214039c6..5b8cf120e1389cf989934e6a679b1816931c518b 100644 --- a/src/java.desktop/share/classes/sun/swing/SwingUtilities2.java +++ b/src/java.desktop/share/classes/sun/swing/SwingUtilities2.java @@ -520,7 +520,7 @@ public class SwingUtilities2 { * it to fit in the screen width. This distributes the spacing * more evenly than directly laying out to the screen advances. */ - String trimmedText = trimTrailingSpaces(text); + String trimmedText = text.stripTrailing(); if (!trimmedText.isEmpty()) { float screenWidth = (float) g2d.getFont().getStringBounds (trimmedText, getFontRenderContext(c)).getWidth(); @@ -866,7 +866,7 @@ public class SwingUtilities2 { String text = new String(data, offset, length); TextLayout layout = new TextLayout(text, g2d.getFont(), deviceFontRenderContext); - String trimmedText = trimTrailingSpaces(text); + String trimmedText = text.stripTrailing(); if (!trimmedText.isEmpty()) { float screenWidth = (float)g2d.getFont(). getStringBounds(trimmedText, frc).getWidth(); @@ -1321,14 +1321,6 @@ public class SwingUtilities2 { return (g instanceof PrinterGraphics || g instanceof PrintGraphics); } - private static String trimTrailingSpaces(String s) { - int i = s.length() - 1; - while(i >= 0 && Character.isWhitespace(s.charAt(i))) { - i--; - } - return s.substring(0, i + 1); - } - private static AttributedCharacterIterator getTrimmedTrailingSpacesIterator (AttributedCharacterIterator iterator) { int curIdx = iterator.getIndex(); diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XComponentPeer.java b/src/java.desktop/unix/classes/sun/awt/X11/XComponentPeer.java index 8297bf738f87cefd500b7eb5ac9365fe626580e6..1f4b0a4d5c87eba5bf664c970a1098db026ce1a6 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11/XComponentPeer.java +++ b/src/java.desktop/unix/classes/sun/awt/X11/XComponentPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1365,8 +1365,8 @@ public class XComponentPeer extends XWindow implements ComponentPeer, DropTarget if (graphicsConfig != null) { oldVisual = graphicsConfig.getVisual(); } - if (gc != null && gc instanceof X11GraphicsConfig) { - newVisual = ((X11GraphicsConfig)gc).getVisual(); + if (gc instanceof X11GraphicsConfig x11Config) { + newVisual = x11Config.getVisual(); } // If the new visual differs from the old one, the peer must be diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XEmbedCanvasPeer.java b/src/java.desktop/unix/classes/sun/awt/X11/XEmbedCanvasPeer.java index fe2f5ffb7e48c246faeeb8e2c70092c6ea592154..4317136816c2a6e34cd4972c922adc54b7871413 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11/XEmbedCanvasPeer.java +++ b/src/java.desktop/unix/classes/sun/awt/X11/XEmbedCanvasPeer.java @@ -567,8 +567,7 @@ public class XEmbedCanvasPeer extends XCanvasPeer implements WindowFocusListener // Find the top-level and see if it is XEmbed client. If so, ask him to // register the accelerator XWindowPeer parent = getToplevelXWindow(); - if (parent != null && parent instanceof XEmbeddedFramePeer) { - XEmbeddedFramePeer embedded = (XEmbeddedFramePeer)parent; + if (parent instanceof XEmbeddedFramePeer embedded) { embedded.registerAccelerator(stroke); } } @@ -577,8 +576,7 @@ public class XEmbedCanvasPeer extends XCanvasPeer implements WindowFocusListener // Find the top-level and see if it is XEmbed client. If so, ask him to // register the accelerator XWindowPeer parent = getToplevelXWindow(); - if (parent != null && parent instanceof XEmbeddedFramePeer) { - XEmbeddedFramePeer embedded = (XEmbeddedFramePeer)parent; + if (parent instanceof XEmbeddedFramePeer embedded) { embedded.unregisterAccelerator(stroke); } } diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XWindow.java b/src/java.desktop/unix/classes/sun/awt/X11/XWindow.java index b047e688f79b1ff831e271ce6520db26dc238baa..8d2ba131cb7d55b6ad1cdb85a5e20e30160bdc5a 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11/XWindow.java +++ b/src/java.desktop/unix/classes/sun/awt/X11/XWindow.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -303,15 +303,13 @@ class XWindow extends XBaseWindow implements X11ComponentPeer { Component temp = target.getParent(); final ComponentAccessor acc = AWTAccessor.getComponentAccessor(); ComponentPeer peer = acc.getPeer(temp); - while (!(peer instanceof XWindow)) + while (!(peer instanceof XWindow window)) { temp = temp.getParent(); peer = acc.getPeer(temp); } - if (peer != null && peer instanceof XWindow) - return ((XWindow)peer).getContentWindow(); - else return 0; + return window.getContentWindow(); } @@ -327,8 +325,8 @@ class XWindow extends XBaseWindow implements X11ComponentPeer { temp = temp.getParent(); peer = acc.getPeer(temp); } - if (peer != null && peer instanceof XWindow) - return (XWindow) peer; + if (peer instanceof XWindow xWindow) + return xWindow; else return null; } @@ -927,9 +925,7 @@ class XWindow extends XBaseWindow implements X11ComponentPeer { long childWnd = xce.get_subwindow(); if (childWnd != XConstants.None) { XBaseWindow child = XToolkit.windowToXWindow(childWnd); - if (child != null && child instanceof XWindow && - !child.isEventDisabled(xev)) - { + if (child instanceof XWindow && !child.isEventDisabled(xev)) { return; } } @@ -1438,20 +1434,19 @@ class XWindow extends XBaseWindow implements X11ComponentPeer { XToolkit.awtLock(); try { Object wpeer = XToolkit.targetToPeer(comp); - if (wpeer == null - || !(wpeer instanceof XDecoratedPeer) - || ((XDecoratedPeer)wpeer).configure_seen) + if (!(wpeer instanceof XDecoratedPeer xDecoratedPeer) + || xDecoratedPeer.configure_seen) { return toGlobal(0, 0); } // wpeer is an XDecoratedPeer not yet fully adopted by WM Point pt = toOtherWindow(getContentWindow(), - ((XDecoratedPeer)wpeer).getContentWindow(), + xDecoratedPeer.getContentWindow(), 0, 0); if (pt == null) { - pt = new Point(((XBaseWindow)wpeer).getAbsoluteX(), ((XBaseWindow)wpeer).getAbsoluteY()); + pt = new Point(xDecoratedPeer.getAbsoluteX(), xDecoratedPeer.getAbsoluteY()); } pt.x += comp.getX(); pt.y += comp.getY(); diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XWindowPeer.java b/src/java.desktop/unix/classes/sun/awt/X11/XWindowPeer.java index 3a79e785be64bd41fd4f9eb833c6b276f3bec00c..94a1dfd519666f8b1a4a300631669defb4d3d8cc 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11/XWindowPeer.java +++ b/src/java.desktop/unix/classes/sun/awt/X11/XWindowPeer.java @@ -416,10 +416,10 @@ class XWindowPeer extends XPanelPeer implements WindowPeer, final ComponentAccessor acc = AWTAccessor.getComponentAccessor(); for (int i = 0; i < cnt; i++) { final ComponentPeer childPeer = acc.getPeer(children[i]); - if (childPeer != null && childPeer instanceof XWindowPeer) { - if (((XWindowPeer)childPeer).winAttr.iconsInherited) { - ((XWindowPeer)childPeer).winAttr.icons = icons; - ((XWindowPeer)childPeer).recursivelySetIcon(icons); + if (childPeer instanceof XWindowPeer xWindowPeer) { + if (xWindowPeer.winAttr.iconsInherited) { + xWindowPeer.winAttr.icons = icons; + xWindowPeer.recursivelySetIcon(icons); } } } diff --git a/src/java.desktop/unix/classes/sun/awt/X11InputMethodBase.java b/src/java.desktop/unix/classes/sun/awt/X11InputMethodBase.java index 671df20d1dbeb6a6bc62130e1c14d4e56cc5e53c..eb71b7a59729cc3939deecb3a341ff3ffe1797cc 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11InputMethodBase.java +++ b/src/java.desktop/unix/classes/sun/awt/X11InputMethodBase.java @@ -172,7 +172,7 @@ public abstract class X11InputMethodBase extends InputMethodAdapter { } } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { dispose(); super.finalize(); diff --git a/src/java.desktop/unix/classes/sun/java2d/xr/XRCompositeManager.java b/src/java.desktop/unix/classes/sun/java2d/xr/XRCompositeManager.java index f41f3778da46cb35f92963e6b123c5ab15d01785..b40d1d0ffa1a6ed334dbe7888ee5c018b2a89453 100644 --- a/src/java.desktop/unix/classes/sun/java2d/xr/XRCompositeManager.java +++ b/src/java.desktop/unix/classes/sun/java2d/xr/XRCompositeManager.java @@ -25,15 +25,18 @@ package sun.java2d.xr; -import java.awt.*; -import java.awt.geom.*; - +import java.awt.AlphaComposite; +import java.awt.Composite; +import java.awt.Paint; +import java.awt.geom.AffineTransform; +import java.awt.geom.NoninvertibleTransformException; import java.security.AccessController; import java.security.PrivilegedAction; -import sun.font.*; -import sun.java2d.*; -import sun.java2d.loops.*; +import sun.awt.image.PixelConverter; +import sun.font.XRTextRenderer; +import sun.java2d.SunGraphics2D; +import sun.java2d.loops.XORComposite; /** * Manages per-application resources, e.g. the 1x1 pixmap used for solid color @@ -68,6 +71,7 @@ public class XRCompositeManager { int gradCachePicture; boolean xorEnabled = false; + int eargb; int validatedPixel = 0; Composite validatedComp; Paint validatedPaint; @@ -170,8 +174,10 @@ public class XRCompositeManager { validatedComp = comp; } - if (sg2d != null && (validatedPixel != sg2d.pixel || updatePaint)) { - validatedPixel = sg2d.pixel; + if (sg2d != null && (eargb != sg2d.eargb || updatePaint)) { + eargb = sg2d.eargb; + validatedPixel = PixelConverter.ArgbPre.instance + .rgbToPixel(eargb, null); setForeground(validatedPixel); } diff --git a/src/java.desktop/unix/classes/sun/java2d/xr/XRGraphicsConfig.java b/src/java.desktop/unix/classes/sun/java2d/xr/XRGraphicsConfig.java index 680e634cce85ac65c0de165a2b80c22cc6f040c1..7483128bec6476024bb8b4a702e7500827963b7d 100644 --- a/src/java.desktop/unix/classes/sun/java2d/xr/XRGraphicsConfig.java +++ b/src/java.desktop/unix/classes/sun/java2d/xr/XRGraphicsConfig.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,14 +25,12 @@ package sun.java2d.xr; -import java.awt.Transparency; -import sun.awt.X11GraphicsConfig; import sun.awt.X11ComponentPeer; +import sun.awt.X11GraphicsConfig; import sun.awt.X11GraphicsDevice; import sun.awt.X11GraphicsEnvironment; import sun.awt.image.SurfaceManager; import sun.java2d.SurfaceData; -import sun.java2d.loops.SurfaceType; public class XRGraphicsConfig extends X11GraphicsConfig implements SurfaceManager.ProxiedGraphicsConfig { @@ -58,14 +56,4 @@ public class XRGraphicsConfig extends X11GraphicsConfig implements public Object getProxyKey() { return this; } - - public synchronized SurfaceType getSurfaceType() { - if (surfaceType != null) { - return surfaceType; - } - - surfaceType = XRSurfaceData.getSurfaceType(this, Transparency.OPAQUE); - return surfaceType; - } - } diff --git a/src/java.desktop/unix/classes/sun/java2d/xr/XRSurfaceData.java b/src/java.desktop/unix/classes/sun/java2d/xr/XRSurfaceData.java index 1b12b54b8f81f6d98266d52549fe9ecab411a6cd..7a0f8d1bb29d3ccf35b7237b66bbb04de138d6df 100644 --- a/src/java.desktop/unix/classes/sun/java2d/xr/XRSurfaceData.java +++ b/src/java.desktop/unix/classes/sun/java2d/xr/XRSurfaceData.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,10 +36,12 @@ import java.awt.geom.AffineTransform; import java.awt.image.ColorModel; import java.awt.image.DirectColorModel; import java.awt.image.Raster; + import sun.awt.SunHints; import sun.awt.SunToolkit; import sun.awt.X11ComponentPeer; import sun.awt.image.PixelConverter; +import sun.font.FontManagerNativeLibrary; import sun.java2d.InvalidPipeException; import sun.java2d.SunGraphics2D; import sun.java2d.SurfaceData; @@ -55,7 +57,6 @@ import sun.java2d.pipe.ShapeDrawPipe; import sun.java2d.pipe.TextPipe; import sun.java2d.pipe.ValidatePipe; import sun.java2d.x11.XSurfaceData; -import sun.font.FontManagerNativeLibrary; public abstract class XRSurfaceData extends XSurfaceData { X11ComponentPeer peer; @@ -207,9 +208,8 @@ public abstract class XRSurfaceData extends XSurfaceData { protected MaskFill getMaskFill(SunGraphics2D sg2d) { AlphaComposite aComp = null; - if(sg2d.composite != null - && sg2d.composite instanceof AlphaComposite) { - aComp = (AlphaComposite) sg2d.composite; + if (sg2d.composite instanceof AlphaComposite alphaComposite) { + aComp = alphaComposite; } boolean supportedPaint = sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR @@ -277,7 +277,7 @@ public abstract class XRSurfaceData extends XSurfaceData { } return new XRPixmapSurfaceData - (gc, width, height, image, getSurfaceType(gc, transparency), + (gc, width, height, image, getPixmapSurfaceType(transparency), cm, drawable, transparency, XRUtils.getPictureFormatForTransparency(transparency), depth, isTexture); } @@ -396,8 +396,7 @@ public abstract class XRSurfaceData extends XSurfaceData { * Returns the XRender SurfaceType which is able to fullfill the specified * transparency requirement. */ - public static SurfaceType getSurfaceType(XRGraphicsConfig gc, - int transparency) { + public static SurfaceType getPixmapSurfaceType(int transparency) { SurfaceType sType = null; switch (transparency) { diff --git a/src/java.desktop/unix/classes/sun/print/IPPPrintService.java b/src/java.desktop/unix/classes/sun/print/IPPPrintService.java index af890126efb87f46759a1358cf70aadeb573e87b..82cb84a14550e632d9561a986a492e54a20eee6b 100644 --- a/src/java.desktop/unix/classes/sun/print/IPPPrintService.java +++ b/src/java.desktop/unix/classes/sun/print/IPPPrintService.java @@ -671,8 +671,7 @@ public class IPPPrintService implements PrintService, SunPrinterJobService { int match = -1; Media media = (Media)attributes.get(Media.class); - if (media != null && media instanceof MediaSizeName) { - MediaSizeName msn = (MediaSizeName)media; + if (media instanceof MediaSizeName msn) { // case when no supported mediasizenames are reported // check given media against the default diff --git a/src/java.desktop/unix/classes/sun/print/UnixPrintJob.java b/src/java.desktop/unix/classes/sun/print/UnixPrintJob.java index 2184e8a3fcf4de3e8deadeadca36e735d3f422bf..eefef8a53539ba4930ae10ae10f2f584bcbdbb18 100644 --- a/src/java.desktop/unix/classes/sun/print/UnixPrintJob.java +++ b/src/java.desktop/unix/classes/sun/print/UnixPrintJob.java @@ -366,8 +366,7 @@ public class UnixPrintJob implements CancelablePrintJob { } } - if (customTray != null && - customTray instanceof CustomMediaTray) { + if (customTray != null) { String choice = customTray.getChoiceName(); if (choice != null) { mOptions += " InputSlot="+choice; diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/AnimationController.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/AnimationController.java index 05c2f5c0a40cb4b3d7115a29f80b3d5420522dc4..b50a5ad583ec59bc720ef16f10f81ab1891d3309 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/AnimationController.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/AnimationController.java @@ -59,7 +59,7 @@ import sun.awt.AppContext; *
  • It tracks the animation state for every UI component involved in the * animation and paints {@code Skin} in new {@code State} over the * {@code Skin} in last {@code State} using - * {@code AlphaComposite.SrcOver.derive(alpha)} where {code alpha} + * {@code AlphaComposite.SrcOver.derive(alpha)} where {@code alpha} * depends on the state of animation * * diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java index 21cc715b4942549a77b1eb0c8ab6186e57f8a394..92980c52a009d8e6eea7269451050b49cfa6da1b 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java @@ -1221,8 +1221,8 @@ public class WindowsFileChooserUI extends BasicFileChooserUI { super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); - if (value != null && value instanceof FileFilter) { - setText(((FileFilter)value).getDescription()); + if (value instanceof FileFilter fileFilter) { + setText(fileFilter.getDescription()); } return this; diff --git a/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolder2.java b/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolder2.java index f08f5337e2ebf04c8495af9e6943f6b280fa0e31..1564804cf843496d86c431b5d635672ae3b10041 100644 --- a/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolder2.java +++ b/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolder2.java @@ -540,14 +540,13 @@ final class Win32ShellFolder2 extends ShellFolder { * Check to see if two ShellFolder objects are the same */ public boolean equals(Object o) { - if (o == null || !(o instanceof Win32ShellFolder2)) { + if (!(o instanceof Win32ShellFolder2 rhs)) { // Short-circuit circuitous delegation path if (!(o instanceof File)) { return super.equals(o); } return pathsEqual(getPath(), ((File) o).getPath()); } - Win32ShellFolder2 rhs = (Win32ShellFolder2) o; if ((parent == null && rhs.parent != null) || (parent != null && rhs.parent == null)) { return false; diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WInputMethod.java b/src/java.desktop/windows/classes/sun/awt/windows/WInputMethod.java index 9ad52ba7111c0b697fc58a92ace475c54ffaed33..681662032e147799bc0ae20c38f703ed0da634e3 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WInputMethod.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WInputMethod.java @@ -133,7 +133,7 @@ final class WInputMethod extends InputMethodAdapter } @Override - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { // Release the resources used by the native input context. diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WPrinterJob.java b/src/java.desktop/windows/classes/sun/awt/windows/WPrinterJob.java index e9c9c709adbb579e9f8c54efc12485985b6f4e98..028cb36c2fcec95605a73e8c4b9b2e9ebbc3431f 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WPrinterJob.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WPrinterJob.java @@ -731,8 +731,7 @@ public final class WPrinterJob extends RasterPrinterJob */ if (attr.getCategory() == SunAlternateMedia.class) { Media media = (Media)attributes.get(Media.class); - if (media == null || - !(media instanceof MediaTray)) { + if (!(media instanceof MediaTray)) { attr = ((SunAlternateMedia)attr).getMedia(); } } diff --git a/src/java.desktop/windows/native/libawt/windows/ShellFolder2.cpp b/src/java.desktop/windows/native/libawt/windows/ShellFolder2.cpp index bc0c27d069a55478870da585b2c88c5a4faf1708..124efa09be148b08e457eee889c018b9ee1ec541 100644 --- a/src/java.desktop/windows/native/libawt/windows/ShellFolder2.cpp +++ b/src/java.desktop/windows/native/libawt/windows/ShellFolder2.cpp @@ -1056,38 +1056,57 @@ JNIEXPORT jintArray JNICALL Java_sun_awt_shell_Win32ShellFolder2_getIconBits bmi.bmiHeader.biCompression = BI_RGB; // Extract the color bitmap int nBits = iconSize * iconSize; - long colorBits[MAX_ICON_SIZE * MAX_ICON_SIZE]; - GetDIBits(dc, iconInfo.hbmColor, 0, iconSize, colorBits, &bmi, DIB_RGB_COLORS); - // XP supports alpha in some icons, and depending on device. - // This should take precedence over the icon mask bits. - BOOL hasAlpha = FALSE; - if (IS_WINXP) { - for (int i = 0; i < nBits; i++) { - if ((colorBits[i] & 0xff000000) != 0) { - hasAlpha = TRUE; - break; + + long *colorBits = NULL; + long *maskBits = NULL; + + try { + entry_point(); + colorBits = (long*)safe_Malloc(MAX_ICON_SIZE * MAX_ICON_SIZE * sizeof(long)); + GetDIBits(dc, iconInfo.hbmColor, 0, iconSize, colorBits, &bmi, DIB_RGB_COLORS); + // XP supports alpha in some icons, and depending on device. + // This should take precedence over the icon mask bits. + BOOL hasAlpha = FALSE; + if (IS_WINXP) { + for (int i = 0; i < nBits; i++) { + if ((colorBits[i] & 0xff000000) != 0) { + hasAlpha = TRUE; + break; + } } } - } - if (!hasAlpha) { - // Extract the mask bitmap - long maskBits[MAX_ICON_SIZE * MAX_ICON_SIZE]; - GetDIBits(dc, iconInfo.hbmMask, 0, iconSize, maskBits, &bmi, DIB_RGB_COLORS); - // Copy the mask alphas into the color bits - for (int i = 0; i < nBits; i++) { - if (maskBits[i] == 0) { - colorBits[i] |= 0xff000000; + if (!hasAlpha) { + // Extract the mask bitmap + maskBits = (long*)safe_Malloc(MAX_ICON_SIZE * MAX_ICON_SIZE * sizeof(long)); + GetDIBits(dc, iconInfo.hbmMask, 0, iconSize, maskBits, &bmi, DIB_RGB_COLORS); + // Copy the mask alphas into the color bits + for (int i = 0; i < nBits; i++) { + if (maskBits[i] == 0) { + colorBits[i] |= 0xff000000; + } } } + // Create java array + iconBits = env->NewIntArray(nBits); + if (!(env->ExceptionCheck())) { + // Copy values to java array + env->SetIntArrayRegion(iconBits, 0, nBits, colorBits); + } + } catch(std::bad_alloc&) { + handle_bad_alloc(); } + // Release DC ReleaseDC(NULL, dc); - // Create java array - iconBits = env->NewIntArray(nBits); - if (!(env->ExceptionCheck())) { - // Copy values to java array - env->SetIntArrayRegion(iconBits, 0, nBits, colorBits); - } + + // Free bitmap buffers if they were allocated + if (colorBits != NULL) { + free(colorBits); + } + + if (maskBits != NULL) { + free(maskBits); + } } // Fix 4745575 GDI Resource Leak // MSDN diff --git a/src/java.management/share/classes/java/lang/management/MemoryMXBean.java b/src/java.management/share/classes/java/lang/management/MemoryMXBean.java index 716d2bcefca02a4c752b0f622147625f7850b7ee..f17e5e8077a86c5c947ab6d55458701e6c938d00 100644 --- a/src/java.management/share/classes/java/lang/management/MemoryMXBean.java +++ b/src/java.management/share/classes/java/lang/management/MemoryMXBean.java @@ -207,9 +207,15 @@ public interface MemoryMXBean extends PlatformManagedObject { * Returns the approximate number of objects for which * finalization is pending. * + * @deprecated Finalization has been deprecated for removal. See + * {@link java.lang.Object#finalize} for details. + * * @return the approximate number objects for which finalization - * is pending. + * is pending. If this MemoryMXBean contains information about a JVM in + * which finalization has been disabled or removed, this method always + * returns zero. */ + @Deprecated(since="18") public int getObjectPendingFinalizationCount(); /** diff --git a/src/java.management/share/classes/javax/management/modelmbean/RequiredModelMBean.java b/src/java.management/share/classes/javax/management/modelmbean/RequiredModelMBean.java index bfa8d5bc79a8cb379ef49c0988b2e0df436f5d28..abace393e671fd4b90149249ba76796794e9e4bc 100644 --- a/src/java.management/share/classes/javax/management/modelmbean/RequiredModelMBean.java +++ b/src/java.management/share/classes/javax/management/modelmbean/RequiredModelMBean.java @@ -192,7 +192,7 @@ public class RequiredModelMBean * * @exception MBeanException Wraps a distributed communication Exception. * @exception RuntimeOperationsException Wraps an - * {link java.lang.IllegalArgumentException}: + * {@link java.lang.IllegalArgumentException}: * The MBeanInfo passed in parameter is null. * **/ diff --git a/src/java.management/share/classes/sun/management/MemoryImpl.java b/src/java.management/share/classes/sun/management/MemoryImpl.java index 7850b90e7838c5a98e85ba2614505835ea8ff6d5..5bdbe7b63499bd516fa6042b940feeec0f31bcff 100644 --- a/src/java.management/share/classes/sun/management/MemoryImpl.java +++ b/src/java.management/share/classes/sun/management/MemoryImpl.java @@ -58,6 +58,7 @@ class MemoryImpl extends NotificationEmitterSupport this.jvm = vm; } + @SuppressWarnings("deprecation") public int getObjectPendingFinalizationCount() { return jdk.internal.misc.VM.getFinalRefCount(); } diff --git a/src/java.naming/share/classes/com/sun/jndi/ldap/AbstractLdapNamingEnumeration.java b/src/java.naming/share/classes/com/sun/jndi/ldap/AbstractLdapNamingEnumeration.java index 94c15c09d11cd9ac9788a82656f1445c194432eb..5c7644212f979674ffc08774a0c8fcfdc5cb686a 100644 --- a/src/java.naming/share/classes/com/sun/jndi/ldap/AbstractLdapNamingEnumeration.java +++ b/src/java.naming/share/classes/com/sun/jndi/ldap/AbstractLdapNamingEnumeration.java @@ -383,7 +383,7 @@ abstract class AbstractLdapNamingEnumeration listArg = ne.listArg; } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected final void finalize() { cleanup(); } diff --git a/src/java.naming/share/classes/com/sun/jndi/ldap/LdapClient.java b/src/java.naming/share/classes/com/sun/jndi/ldap/LdapClient.java index d972766dc118c75a662d2a96a203e1eb63eefcfb..4834b6e530aec1bc71a22fcd2151c19a4766b5d5 100644 --- a/src/java.naming/share/classes/com/sun/jndi/ldap/LdapClient.java +++ b/src/java.naming/share/classes/com/sun/jndi/ldap/LdapClient.java @@ -477,7 +477,7 @@ public final class LdapClient implements PooledConnection { } } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() { if (debug > 0) System.err.println("LdapClient: finalize " + this); forceClose(pooled); diff --git a/src/java.naming/share/classes/com/sun/jndi/ldap/LdapCtx.java b/src/java.naming/share/classes/com/sun/jndi/ldap/LdapCtx.java index 059b654f5818f534ff5ca6037cc3d4a7b6db9093..9a918edf0c3dd5451a86c41d1ba1bf4e2355c7ee 100644 --- a/src/java.naming/share/classes/com/sun/jndi/ldap/LdapCtx.java +++ b/src/java.naming/share/classes/com/sun/jndi/ldap/LdapCtx.java @@ -2639,7 +2639,7 @@ public final class LdapCtx extends ComponentDirContext // ----------------- Connection --------------------- - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() { try { close(); diff --git a/src/java.naming/share/classes/com/sun/jndi/ldap/sasl/DefaultCallbackHandler.java b/src/java.naming/share/classes/com/sun/jndi/ldap/sasl/DefaultCallbackHandler.java index 2a782c0e9cc5442930c6193ceb4e00defe09e2e8..b6388915840b2d4df99c259f4b102b82acd67aa3 100644 --- a/src/java.naming/share/classes/com/sun/jndi/ldap/sasl/DefaultCallbackHandler.java +++ b/src/java.naming/share/classes/com/sun/jndi/ldap/sasl/DefaultCallbackHandler.java @@ -131,7 +131,7 @@ final class DefaultCallbackHandler implements CallbackHandler { } } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { clearPassword(); } diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/ResponseSubscribers.java b/src/java.net.http/share/classes/jdk/internal/net/http/ResponseSubscribers.java index ba9df1b4c9cadc19f891020c727994616f6bdb27..9506d1333240b0d78d6e49350c7262a35b4cec1d 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/ResponseSubscribers.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/ResponseSubscribers.java @@ -1086,7 +1086,7 @@ public class ResponseSubscribers { * Invokes bs::getBody using the provided executor. * If invoking bs::getBody requires an executor, and the given executor * is a {@link HttpClientImpl.DelegatingExecutor}, then the executor's - * delegate is used. If an error occurs anywhere then the given {code cf} + * delegate is used. If an error occurs anywhere then the given {@code cf} * is completed exceptionally (this method does not throw). * @param e The executor that should be used to call bs::getBody * @param bs The BodySubscriber diff --git a/src/java.prefs/macosx/classes/java/util/prefs/MacOSXPreferencesFile.java b/src/java.prefs/macosx/classes/java/util/prefs/MacOSXPreferencesFile.java index ab954513b81a0a19c1a2b3b603eb283f611f1eb9..61ee92cf6013a8af12ae88209bd38743d1d4c562 100644 --- a/src/java.prefs/macosx/classes/java/util/prefs/MacOSXPreferencesFile.java +++ b/src/java.prefs/macosx/classes/java/util/prefs/MacOSXPreferencesFile.java @@ -93,18 +93,12 @@ class MacOSXPreferencesFile { }); } - private class FlushTask extends TimerTask { + private static class FlushTask extends TimerTask { public void run() { MacOSXPreferencesFile.flushWorld(); } } - private class SyncTask extends TimerTask { - public void run() { - MacOSXPreferencesFile.syncWorld(); - } - } - // Maps string -> weak reference to MacOSXPreferencesFile private static HashMap> cachedFiles; diff --git a/src/java.prefs/share/classes/java/util/prefs/AbstractPreferences.java b/src/java.prefs/share/classes/java/util/prefs/AbstractPreferences.java index e0e2551bb690bb8217c2cc769dccb6d428cf95d7..b0844b2e7ca1eeab278b56fc61f0f0ee993f661e 100644 --- a/src/java.prefs/share/classes/java/util/prefs/AbstractPreferences.java +++ b/src/java.prefs/share/classes/java/util/prefs/AbstractPreferences.java @@ -29,11 +29,6 @@ import java.util.*; import java.io.*; import java.security.AccessController; import java.security.PrivilegedAction; -// These imports needed only as a workaround for a JavaDoc bug -import java.lang.Integer; -import java.lang.Long; -import java.lang.Float; -import java.lang.Double; /** * This class provides a skeletal implementation of the {@link Preferences} @@ -1498,13 +1493,13 @@ public abstract class AbstractPreferences extends Preferences { * eventQueue so the event dispatch thread knows whether to call * childAdded or childRemoved. */ - private class NodeAddedEvent extends NodeChangeEvent { + private static class NodeAddedEvent extends NodeChangeEvent { private static final long serialVersionUID = -6743557530157328528L; NodeAddedEvent(Preferences parent, Preferences child) { super(parent, child); } } - private class NodeRemovedEvent extends NodeChangeEvent { + private static class NodeRemovedEvent extends NodeChangeEvent { private static final long serialVersionUID = 8735497392918824837L; NodeRemovedEvent(Preferences parent, Preferences child) { super(parent, child); diff --git a/src/java.prefs/unix/classes/java/util/prefs/FileSystemPreferences.java b/src/java.prefs/unix/classes/java/util/prefs/FileSystemPreferences.java index 5aafccbc487464a750a6d1c3126db90a8081a033..2a8947146666c8515a5b029df61cb30541b6ad82 100644 --- a/src/java.prefs/unix/classes/java/util/prefs/FileSystemPreferences.java +++ b/src/java.prefs/unix/classes/java/util/prefs/FileSystemPreferences.java @@ -24,6 +24,7 @@ */ package java.util.prefs; + import java.util.*; import java.io.*; import java.security.AccessController; @@ -298,8 +299,8 @@ class FileSystemPreferences extends AbstractPreferences { * A temporary file used for saving changes to preferences. As part of * the sync operation, changes are first saved into this file, and then * atomically renamed to prefsFile. This results in an atomic state - * change from one valid set of preferences to another. The - * the file-lock is held for the duration of this transformation. + * change from one valid set of preferences to another. + * The file-lock is held for the duration of this transformation. */ private final File tmpFile; @@ -385,12 +386,12 @@ class FileSystemPreferences extends AbstractPreferences { /** * Represents a change to a preference. */ - private abstract class Change { + private abstract static class Change { /** * Reapplies the change to prefsCache. */ abstract void replay(); - }; + } /** * Represents a preference put. @@ -426,7 +427,7 @@ class FileSystemPreferences extends AbstractPreferences { /** * Represents the creation of this node. */ - private class NodeCreate extends Change { + private static class NodeCreate extends Change { /** * Performs no action, but the presence of this object in changeLog * will force the node and its ancestors to be made permanent at the diff --git a/src/java.rmi/share/classes/java/rmi/server/RemoteObject.java b/src/java.rmi/share/classes/java/rmi/server/RemoteObject.java index 55f4c8ca626b7fb83e3ea5a23ff2eb6e693e34bd..4245d362a2425b1943539fdb9d2811f060658758 100644 --- a/src/java.rmi/share/classes/java/rmi/server/RemoteObject.java +++ b/src/java.rmi/share/classes/java/rmi/server/RemoteObject.java @@ -251,7 +251,7 @@ public abstract class RemoteObject implements Remote, java.io.Serializable { * written by {@link java.io.ObjectOutput#writeInt(int)} * *
  • the data written as a result of calling - * {link java.rmi.server.ObjID#write(java.io.ObjectOutput)} + * {@link java.rmi.server.ObjID#write(java.io.ObjectOutput)} * on the ObjID instance contained in the reference * *
  • the boolean value false, @@ -275,7 +275,7 @@ public abstract class RemoteObject implements Remote, java.io.Serializable { * written by {@link java.io.ObjectOutput#writeInt(int)} * *
  • the data written as a result of calling - * {link java.rmi.server.ObjID#write(java.io.ObjectOutput)} + * {@link java.rmi.server.ObjID#write(java.io.ObjectOutput)} * on the ObjID instance contained in the reference * *
  • the boolean value false, @@ -304,7 +304,7 @@ public abstract class RemoteObject implements Remote, java.io.Serializable { * writeObject on the stream instance * *
  • the data written as a result of calling - * {link java.rmi.server.ObjID#write(java.io.ObjectOutput)} + * {@link java.rmi.server.ObjID#write(java.io.ObjectOutput)} * on the ObjID instance contained in the reference * *
  • the boolean value false, diff --git a/src/java.rmi/share/classes/sun/rmi/log/LogInputStream.java b/src/java.rmi/share/classes/sun/rmi/log/LogInputStream.java index 649fa22516d43c991c3ae459c11937d2243d9f07..1dbdd3064bcf4ae06a911bc4ad8a8b8da0c72f58 100644 --- a/src/java.rmi/share/classes/sun/rmi/log/LogInputStream.java +++ b/src/java.rmi/share/classes/sun/rmi/log/LogInputStream.java @@ -128,7 +128,7 @@ class LogInputStream extends InputStream { /** * Closes the stream when garbage is collected. */ - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws IOException { close(); } diff --git a/src/java.rmi/share/man/rmiregistry.1 b/src/java.rmi/share/man/rmiregistry.1 index d4c84ea58c2e10e29887d482b18a07253dd11da2..d6e27ceec1ca1bfda4031284e2ed76f9cfca7b0d 100644 --- a/src/java.rmi/share/man/rmiregistry.1 +++ b/src/java.rmi/share/man/rmiregistry.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "RMIREGISTRY" "1" "2021" "JDK 18\-ea" "JDK Commands" +.TH "RMIREGISTRY" "1" "2022" "JDK 19\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/java.scripting/share/man/jrunscript.1 b/src/java.scripting/share/man/jrunscript.1 index 2c7ac2d40bc8ac73e0a1043d71df7c36a0336d05..727f6d2cece36df01cf8c91d23b481ec9c110ac0 100644 --- a/src/java.scripting/share/man/jrunscript.1 +++ b/src/java.scripting/share/man/jrunscript.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JRUNSCRIPT" "1" "2021" "JDK 18\-ea" "JDK Commands" +.TH "JRUNSCRIPT" "1" "2022" "JDK 19\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5Context.java b/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5Context.java index 8a9ab5f84888d278d468067821e09db117805cd0..6e0286c5d5bd32553042ea5f10092ae17964c2bf 100644 --- a/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5Context.java +++ b/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5Context.java @@ -45,7 +45,6 @@ import javax.security.auth.kerberos.ServicePermission; import javax.security.auth.kerberos.KerberosCredMessage; import javax.security.auth.kerberos.KerberosPrincipal; import javax.security.auth.kerberos.KerberosTicket; -import sun.security.krb5.internal.Ticket; import sun.security.krb5.internal.AuthorizationData; /** @@ -120,9 +119,12 @@ class Krb5Context implements GSSContextSpi { // XXX See if the required info from these can be extracted and // stored elsewhere private Credentials tgt; + + // On the Initiator side, contains the final TGS to a service on both + // delegation and no-delegation scenarios. + // On the Acceptor side, contains a user TGS usable for delegation. private Credentials serviceCreds; private KrbApReq apReq; - Ticket serviceTicket; private final GSSCaller caller; private static final boolean DEBUG = Krb5Util.DEBUG; @@ -548,7 +550,7 @@ class Krb5Context implements GSSContextSpi { delegatedCred = new Krb5ProxyCredential( Krb5InitCredential.getInstance( GSSCaller.CALLER_ACCEPT, myName, lifetime), - peerName, serviceTicket); + peerName, serviceCreds); } catch (GSSException gsse) { // OK, delegatedCred is null then } @@ -623,13 +625,13 @@ class Krb5Context implements GSSContextSpi { "No TGT available"); } myName = (Krb5NameElement) myCred.getName(); - final Krb5ProxyCredential second; + final Krb5ProxyCredential proxyCreds; if (myCred instanceof Krb5InitCredential) { - second = null; + proxyCreds = null; tgt = ((Krb5InitCredential) myCred).getKrb5Credentials(); } else { - second = (Krb5ProxyCredential) myCred; - tgt = second.self.getKrb5Credentials(); + proxyCreds = (Krb5ProxyCredential) myCred; + tgt = proxyCreds.self.getKrb5Credentials(); } checkPermission(peerName.getKrb5PrincipalName().getName(), @@ -657,9 +659,9 @@ class Krb5Context implements GSSContextSpi { GSSCaller.CALLER_UNKNOWN, // since it's useSubjectCredsOnly here, // don't worry about the null - second == null ? + proxyCreds == null ? myName.getKrb5PrincipalName().getName(): - second.getName().getKrb5PrincipalName().getName(), + proxyCreds.getName().getKrb5PrincipalName().getName(), peerName.getKrb5PrincipalName().getName()); }}); kerbTicket = tmp; @@ -690,15 +692,15 @@ class Krb5Context implements GSSContextSpi { "the subject"); } // Get Service ticket using the Kerberos protocols - if (second == null) { + if (proxyCreds == null) { serviceCreds = Credentials.acquireServiceCreds( peerName.getKrb5PrincipalName().getName(), tgt); } else { serviceCreds = Credentials.acquireS4U2proxyCreds( peerName.getKrb5PrincipalName().getName(), - second.tkt, - second.getName().getKrb5PrincipalName(), + proxyCreds.userCreds, + proxyCreds.getName().getKrb5PrincipalName(), tgt); } if (GSSUtil.useSubjectCredsOnly(caller)) { @@ -844,7 +846,7 @@ class Krb5Context implements GSSContextSpi { retVal = new AcceptSecContextToken(this, token.getKrbApReq()).encode(); } - serviceTicket = token.getKrbApReq().getCreds().getTicket(); + serviceCreds = token.getKrbApReq().getCreds(); myCred = null; state = STATE_DONE; } else { diff --git a/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5InitCredential.java b/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5InitCredential.java index 5bd5652f6996cb38d83cd7f24f7cf8b92a7ddcc2..5ec6c30a676f12e4bdca03403b70b6e0969f9f9b 100644 --- a/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5InitCredential.java +++ b/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5InitCredential.java @@ -392,7 +392,7 @@ public class Krb5InitCredential Krb5NameElement kname = (Krb5NameElement)name; Credentials newCred = Credentials.acquireS4U2selfCreds( kname.getKrb5PrincipalName(), krb5Credentials); - return new Krb5ProxyCredential(this, kname, newCred.getTicket()); + return new Krb5ProxyCredential(this, kname, newCred); } catch (IOException | KrbException ke) { GSSException ge = new GSSException(GSSException.FAILURE, -1, diff --git a/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5ProxyCredential.java b/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5ProxyCredential.java index 8fbe93a57685dcd1b6aec5500b10e3e8fd920606..8859c759f13e37508968f848de29522d28c368cd 100644 --- a/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5ProxyCredential.java +++ b/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5ProxyCredential.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,7 +33,6 @@ import java.io.IOException; import sun.security.krb5.Credentials; import sun.security.krb5.KrbException; -import sun.security.krb5.internal.Ticket; import javax.security.auth.kerberos.KerberosTicket; @@ -50,23 +49,23 @@ public class Krb5ProxyCredential implements Krb5CredElement { public final Krb5InitCredential self; // the middle server - private final Krb5NameElement client; // the client + private final Krb5NameElement user; // the user - // The ticket with cname=client and sname=self. This can be a normal - // service ticket or an S4U2self ticket. - public final Ticket tkt; + // The creds with cname=user and sname=self. The ticket inside can + // be either a normal service ticket or an S4U2self ticket. + public final Credentials userCreds; - Krb5ProxyCredential(Krb5InitCredential self, Krb5NameElement client, - Ticket tkt) { + Krb5ProxyCredential(Krb5InitCredential self, Krb5NameElement user, + Credentials userCreds) { this.self = self; - this.tkt = tkt; - this.client = client; + this.userCreds = userCreds; + this.user = user; } - // The client name behind the proxy + // The user name behind the proxy @Override public final Krb5NameElement getName() throws GSSException { - return client; + return user; } @Override @@ -130,7 +129,7 @@ public class Krb5ProxyCredential Credentials proxyCreds = Krb5Util.ticketToCreds(proxy); return new Krb5ProxyCredential(initiator, Krb5NameElement.getInstance(proxyCreds.getClient()), - proxyCreds.getTicket()); + proxyCreds); } else { return initiator; } diff --git a/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/GSSCredElement.java b/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/GSSCredElement.java index bfe1807935a9ac556d5500b297d43f8fedf4c1df..447b6c947e9c73b4b0ae317e93e676c7d138502c 100644 --- a/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/GSSCredElement.java +++ b/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/GSSCredElement.java @@ -132,7 +132,7 @@ public class GSSCredElement implements GSSCredentialSpi { return "N/A"; } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { dispose(); } diff --git a/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/GSSNameElement.java b/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/GSSNameElement.java index 54641f2f6e6a7ac00066f40cfa30796d80fa1f9e..b449169c441600952c5cd2b105b91a8bae3093b6 100644 --- a/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/GSSNameElement.java +++ b/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/GSSNameElement.java @@ -290,7 +290,7 @@ public class GSSNameElement implements GSSNameSpi { } } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { dispose(); } diff --git a/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/NativeGSSContext.java b/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/NativeGSSContext.java index e89b109250e5ea9878d690c8d0d63a848a799fa3..61640be3507d91ccaa05d672e64457dd20a7610a 100644 --- a/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/NativeGSSContext.java +++ b/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/NativeGSSContext.java @@ -639,7 +639,7 @@ class NativeGSSContext implements GSSContextSpi { return isInitiator; } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { dispose(); } diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/Credentials.java b/src/java.security.jgss/share/classes/sun/security/krb5/Credentials.java index d84ccd2b631fead521b3731b5a8b3470e6583602..b4efc5f4db73f20bbd4e2dd0fb333f0d83d80a23 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/Credentials.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/Credentials.java @@ -35,6 +35,8 @@ import sun.security.action.GetPropertyAction; import sun.security.krb5.internal.*; import sun.security.krb5.internal.ccache.CredentialsCache; import sun.security.krb5.internal.crypto.EType; +import sun.security.util.SecurityProperties; + import java.io.IOException; import java.util.Date; import java.util.Locale; @@ -64,6 +66,10 @@ public class Credentials { static boolean alreadyLoaded = false; private static boolean alreadyTried = false; + public static final boolean S4U2PROXY_ACCEPT_NON_FORWARDABLE + = "true".equalsIgnoreCase(SecurityProperties.privilegedGetOverridable( + "jdk.security.krb5.s4u2proxy.acceptNonForwardableServiceTicket")); + private Credentials proxy = null; public Credentials getProxy() { @@ -97,7 +103,7 @@ public class Credentials { this.authzData = authzData; } - // Warning: called by NativeCreds.c and nativeccache.c + // Warning: also called by NativeCreds.c and nativeccache.c public Credentials(Ticket new_ticket, PrincipalName new_client, PrincipalName new_client_alias, @@ -478,7 +484,7 @@ public class Credentials { * * @param service the name of service principal using format * components@realm - * @param ccreds client's initial credential. + * @param initCreds client's initial credential. * @exception IOException if an error occurs in reading the credentials * cache * @exception KrbException if an error occurs specific to Kerberos @@ -486,21 +492,21 @@ public class Credentials { */ public static Credentials acquireServiceCreds(String service, - Credentials ccreds) + Credentials initCreds) throws KrbException, IOException { - return CredentialsUtil.acquireServiceCreds(service, ccreds); + return CredentialsUtil.acquireServiceCreds(service, initCreds); } public static Credentials acquireS4U2selfCreds(PrincipalName user, - Credentials ccreds) throws KrbException, IOException { - return CredentialsUtil.acquireS4U2selfCreds(user, ccreds); + Credentials middleTGT) throws KrbException, IOException { + return CredentialsUtil.acquireS4U2selfCreds(user, middleTGT); } public static Credentials acquireS4U2proxyCreds(String service, - Ticket second, PrincipalName client, Credentials ccreds) + Credentials userCreds, PrincipalName client, Credentials middleTGT) throws KrbException, IOException { return CredentialsUtil.acquireS4U2proxyCreds( - service, second, client, ccreds); + service, userCreds, client, middleTGT); } /* diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/KdcComm.java b/src/java.security.jgss/share/classes/sun/security/krb5/KdcComm.java index 25af49ea451dd364e75dfc7f8396bc869bd8fbfe..5790b06170b9586c139ed770ad2e17e92c5a68a5 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/KdcComm.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/KdcComm.java @@ -188,21 +188,22 @@ public final class KdcComm { this.realm = realm; } - public byte[] send(byte[] obuf) + public byte[] send(KrbKdcReq req) throws IOException, KrbException { int udpPrefLimit = getRealmSpecificValue( realm, "udp_preference_limit", defaultUdpPrefLimit); + byte[] obuf = req.encoding(); boolean useTCP = (udpPrefLimit > 0 && (obuf != null && obuf.length > udpPrefLimit)); - return send(obuf, useTCP); + return send(req, useTCP); } - private byte[] send(byte[] obuf, boolean useTCP) + private byte[] send(KrbKdcReq req, boolean useTCP) throws IOException, KrbException { - if (obuf == null) + if (req == null) return null; Config cfg = Config.getInstance(); @@ -225,12 +226,12 @@ public final class KdcComm { } byte[] ibuf = null; try { - ibuf = sendIfPossible(obuf, tempKdc.next(), useTCP); + ibuf = sendIfPossible(req, tempKdc.next(), useTCP); } catch(Exception first) { boolean ok = false; while(tempKdc.hasNext()) { try { - ibuf = sendIfPossible(obuf, tempKdc.next(), useTCP); + ibuf = sendIfPossible(req, tempKdc.next(), useTCP); ok = true; break; } catch(Exception ignore) {} @@ -243,13 +244,13 @@ public final class KdcComm { return ibuf; } - // send the AS Request to the specified KDC + // send the KDC Request to the specified KDC // failover to using TCP if useTCP is not set and response is too big - private byte[] sendIfPossible(byte[] obuf, String tempKdc, boolean useTCP) + private byte[] sendIfPossible(KrbKdcReq req, String tempKdc, boolean useTCP) throws IOException, KrbException { try { - byte[] ibuf = send(obuf, tempKdc, useTCP); + byte[] ibuf = send(req, tempKdc, useTCP); KRBError ke = null; try { ke = new KRBError(ibuf); @@ -259,10 +260,17 @@ public final class KdcComm { if (ke != null) { if (ke.getErrorCode() == Krb5.KRB_ERR_RESPONSE_TOO_BIG) { - ibuf = send(obuf, tempKdc, true); + ibuf = send(req, tempKdc, true); } else if (ke.getErrorCode() == Krb5.KDC_ERR_SVC_UNAVAILABLE) { throw new KrbException("A service is not available"); + } else if (ke.getErrorCode() == Krb5.KDC_ERR_BADOPTION + && Credentials.S4U2PROXY_ACCEPT_NON_FORWARDABLE + && req instanceof KrbTgsReq tgsReq) { + Credentials extra = tgsReq.getAdditionalCreds(); + if (extra != null && !extra.isForwardable()) { + throw new KrbException("S4U2Proxy with non-forwardable ticket"); + } } } KdcAccessibility.removeBad(tempKdc); @@ -278,12 +286,12 @@ public final class KdcComm { } } - // send the AS Request to the specified KDC + // send the KDC Request to the specified KDC - private byte[] send(byte[] obuf, String tempKdc, boolean useTCP) + private byte[] send(KrbKdcReq req, String tempKdc, boolean useTCP) throws IOException, KrbException { - if (obuf == null) + if (req == null) return null; int port = Krb5.KDC_INET_DEFAULT_PORT; @@ -336,6 +344,7 @@ public final class KdcComm { port = tempPort; } + byte[] obuf = req.encoding(); if (DEBUG) { System.out.println(">>> KrbKdcReq send: kdc=" + kdc + (useTCP ? " TCP:":" UDP:") diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/KrbAsReq.java b/src/java.security.jgss/share/classes/sun/security/krb5/KrbAsReq.java index 19e3ef61076237894fdb8e6e46791d8c363d1e3a..580beddf21bb9cd21491b603d12b03a0da6a08c7 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/KrbAsReq.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/KrbAsReq.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,7 +42,7 @@ import java.util.Arrays; * This class encapsulates the KRB-AS-REQ message that the client * sends to the KDC. */ -public class KrbAsReq { +public class KrbAsReq extends KrbKdcReq { private ASReq asReqMessg; private boolean DEBUG = Krb5.DEBUG; @@ -165,10 +165,7 @@ public class KrbAsReq { asReqMessg = new ASReq( paData, kdc_req_body); - } - - byte[] encoding() throws IOException, Asn1Exception { - return asReqMessg.asn1Encode(); + obuf = asReqMessg.asn1Encode(); } // Used by KrbAsRep to validate AS-REP diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/KrbAsReqBuilder.java b/src/java.security.jgss/share/classes/sun/security/krb5/KrbAsReqBuilder.java index bdd70d64911885b1b1956bbeaa96f7241c446251..177f714d1ea9ff5a5713a4d31795c782d4aa3f22 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/KrbAsReqBuilder.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/KrbAsReqBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -342,7 +342,7 @@ public final class KrbAsReqBuilder { } try { req = build(pakey, referralsState); - rep = new KrbAsRep(comm.send(req.encoding())); + rep = new KrbAsRep(comm.send(req)); return this; } catch (KrbException ke) { if (!preAuthFailedOnce && ( diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/KrbKdcReq.java b/src/java.security.jgss/share/classes/sun/security/krb5/KrbKdcReq.java new file mode 100644 index 0000000000000000000000000000000000000000..e64cc977b460bf3718f36a83d17a47cd99ccca63 --- /dev/null +++ b/src/java.security.jgss/share/classes/sun/security/krb5/KrbKdcReq.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.security.krb5; + +/** + * Parent class for KrbAsReq and KrbTgsReq. + */ +abstract class KrbKdcReq { + + protected byte[] obuf; + + public byte[] encoding() { + return obuf; + } +} diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/KrbTgsRep.java b/src/java.security.jgss/share/classes/sun/security/krb5/KrbTgsRep.java index 356bfe110f7916988dea0b7a21740a790c7bdd60..c9eb9eaf21fc0d9fbb1e9b3da3f2c5047fc0d31a 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/KrbTgsRep.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/KrbTgsRep.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,7 +43,7 @@ import java.io.IOException; public class KrbTgsRep extends KrbKdcRep { private TGSRep rep; private Credentials creds; - private Ticket secondTicket; + private Credentials additionalCreds; KrbTgsRep(byte[] ibuf, KrbTgsReq tgsReq) throws KrbException, IOException { @@ -115,7 +115,7 @@ public class KrbTgsRep extends KrbKdcRep { enc_part.caddr ); this.rep = rep; - this.secondTicket = tgsReq.getSecondTicket(); + this.additionalCreds = tgsReq.getAdditionalCreds(); } /** @@ -126,7 +126,8 @@ public class KrbTgsRep extends KrbKdcRep { } sun.security.krb5.internal.ccache.Credentials setCredentials() { - return new sun.security.krb5.internal.ccache.Credentials(rep, secondTicket); + return new sun.security.krb5.internal.ccache.Credentials( + rep, additionalCreds == null ? null : additionalCreds.ticket); } private static boolean isReferralSname(PrincipalName sname) { diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/KrbTgsReq.java b/src/java.security.jgss/share/classes/sun/security/krb5/KrbTgsReq.java index cedd612d2c9d481b5fa20ede2171a818c5b5e9e6..8c2b70681116b5165b833ff13cdd70073ad732f4 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/KrbTgsReq.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/KrbTgsReq.java @@ -42,7 +42,7 @@ import java.util.Arrays; * This class encapsulates a Kerberos TGS-REQ that is sent from the * client to the KDC. */ -public class KrbTgsReq { +public class KrbTgsReq extends KrbKdcReq { private PrincipalName princName; private PrincipalName clientAlias; @@ -50,34 +50,31 @@ public class KrbTgsReq { private PrincipalName serverAlias; private TGSReq tgsReqMessg; private KerberosTime ctime; - private Ticket secondTicket = null; + private Credentials additionalCreds = null; private boolean useSubkey = false; EncryptionKey tgsReqKey; - private byte[] obuf; - private byte[] ibuf; - // Used in CredentialsUtil public KrbTgsReq(KDCOptions options, Credentials asCreds, PrincipalName cname, PrincipalName clientAlias, PrincipalName sname, PrincipalName serverAlias, - Ticket[] additionalTickets, PAData[] extraPAs) - throws KrbException, IOException { + Credentials additionalCreds, PAData[] extraPAs) + throws KrbException, IOException { this(options, - asCreds, - cname, - clientAlias, - sname, - serverAlias, - null, // KerberosTime from - null, // KerberosTime till - null, // KerberosTime rtime - null, // int[] eTypes - null, // HostAddresses addresses - null, // AuthorizationData authorizationData - additionalTickets, - null, // EncryptionKey subKey - extraPAs); + asCreds, + cname, + clientAlias, + sname, + serverAlias, + null, // KerberosTime from + null, // KerberosTime till + null, // KerberosTime rtime + null, // int[] eTypes + null, // HostAddresses addresses + null, // AuthorizationData authorizationData + additionalCreds, + null, // EncryptionKey subKey + extraPAs); } // Called by Credentials, KrbCred @@ -92,11 +89,11 @@ public class KrbTgsReq { int[] eTypes, HostAddresses addresses, AuthorizationData authorizationData, - Ticket[] additionalTickets, + Credentials additionalCreds, EncryptionKey subKey) throws KrbException, IOException { this(options, asCreds, asCreds.getClient(), asCreds.getClientAlias(), sname, serverAlias, from, till, rtime, eTypes, - addresses, authorizationData, additionalTickets, subKey, null); + addresses, authorizationData, additionalCreds, subKey, null); } private KrbTgsReq( @@ -112,7 +109,7 @@ public class KrbTgsReq { int[] eTypes, HostAddresses addresses, AuthorizationData authorizationData, - Ticket[] additionalTickets, + Credentials additionalCreds, EncryptionKey subKey, PAData[] extraPAs) throws KrbException, IOException { @@ -154,24 +151,24 @@ public class KrbTgsReq { if (!(asCreds.flags.get(KDCOptions.POSTDATED))) throw new KrbException(Krb5.KRB_AP_ERR_REQ_OPTIONS); } else { - if (from != null) from = null; + if (from != null) from = null; } if (options.get(KDCOptions.RENEWABLE)) { if (!(asCreds.flags.get(KDCOptions.RENEWABLE))) throw new KrbException(Krb5.KRB_AP_ERR_REQ_OPTIONS); } else { - if (rtime != null) rtime = null; + if (rtime != null) rtime = null; } if (options.get(KDCOptions.ENC_TKT_IN_SKEY) || options.get(KDCOptions.CNAME_IN_ADDL_TKT)) { - if (additionalTickets == null) + if (additionalCreds == null) throw new KrbException(Krb5.KRB_AP_ERR_REQ_OPTIONS); // in TGS_REQ there could be more than one additional // tickets, but in file-based credential cache, // there is only one additional ticket field. - secondTicket = additionalTickets[0]; + this.additionalCreds = additionalCreds; } else { - if (additionalTickets != null) - additionalTickets = null; + if (additionalCreds != null) + additionalCreds = null; } tgsReqMessg = createRequest( @@ -187,7 +184,7 @@ public class KrbTgsReq { eTypes, addresses, authorizationData, - additionalTickets, + additionalCreds, subKey, extraPAs); obuf = tgsReqMessg.asn1Encode(); @@ -206,34 +203,16 @@ public class KrbTgsReq { } - /** - * Sends a TGS request to the realm of the target. - * @throws KrbException - * @throws IOException - */ - public void send() throws IOException, KrbException { - String realmStr = null; - if (servName != null) - realmStr = servName.getRealmString(); - KdcComm comm = new KdcComm(realmStr); - ibuf = comm.send(obuf); - } - - public KrbTgsRep getReply() - throws KrbException, IOException { - return new KrbTgsRep(ibuf, this); - } - /** * Sends the request, waits for a reply, and returns the Credentials. * Used in Credentials, KrbCred, and internal/CredentialsUtil. */ public Credentials sendAndGetCreds() throws IOException, KrbException { - KrbTgsRep tgs_rep = null; - String kdc = null; - send(); - tgs_rep = getReply(); - return tgs_rep.getCreds(); + String realmStr = servName != null + ? servName.getRealmString() + : null; + KdcComm comm = new KdcComm(realmStr); + return new KrbTgsRep(comm.send(this), this).getCreds(); } KerberosTime getCtime() { @@ -253,7 +232,7 @@ public class KrbTgsReq { int[] eTypes, HostAddresses addresses, AuthorizationData authorizationData, - Ticket[] additionalTickets, + Credentials additionalCreds, EncryptionKey subKey, PAData[] extraPAs) throws IOException, KrbException, UnknownHostException { @@ -302,6 +281,8 @@ public class KrbTgsReq { KeyUsage.KU_TGS_REQ_AUTH_DATA_SESSKEY); } + Ticket[] additionalTickets = additionalCreds == null ? null + : new Ticket[] { additionalCreds.getTicket() }; KDCReqBody reqBody = new KDCReqBody( kdc_options, cname, @@ -347,8 +328,8 @@ public class KrbTgsReq { return tgsReqMessg; } - Ticket getSecondTicket() { - return secondTicket; + Credentials getAdditionalCreds() { + return additionalCreds; } PrincipalName getClientAlias() { diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/internal/CredentialsUtil.java b/src/java.security.jgss/share/classes/sun/security/krb5/internal/CredentialsUtil.java index 1f5f033c58b1c9eefd5f70742bcdd6e62bfda3f7..223810f67b51a89dd7d0f1844640d28f10514506 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/internal/CredentialsUtil.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/CredentialsUtil.java @@ -32,7 +32,6 @@ package sun.security.krb5.internal; import sun.security.krb5.*; -import sun.security.util.DerValue; import java.io.IOException; import java.util.LinkedList; @@ -55,17 +54,14 @@ public class CredentialsUtil { * Used by a middle server to acquire credentials on behalf of a * user to itself using the S4U2self extension. * @param user the user to impersonate - * @param ccreds the TGT of the middle service + * @param middleTGT the TGT of the middle service * @return the new creds (cname=user, sname=middle) */ public static Credentials acquireS4U2selfCreds(PrincipalName user, - Credentials ccreds) throws KrbException, IOException { - if (!ccreds.isForwardable()) { - throw new KrbException("S4U2self needs a FORWARDABLE ticket"); - } - PrincipalName sname = ccreds.getClient(); + Credentials middleTGT) throws KrbException, IOException { + PrincipalName sname = middleTGT.getClient(); String uRealm = user.getRealmString(); - String localRealm = ccreds.getClient().getRealmString(); + String localRealm = sname.getRealmString(); if (!uRealm.equals(localRealm)) { // Referrals will be required because the middle service // and the user impersonated are on different realms. @@ -73,25 +69,25 @@ public class CredentialsUtil { throw new KrbException("Cross-realm S4U2Self request not" + " possible when referrals are disabled."); } - if (ccreds.getClientAlias() != null) { + if (middleTGT.getClientAlias() != null) { // If the name was canonicalized, the user pick // has preference. This gives the possibility of // using FQDNs that KDCs may use to return referrals. // I.e.: a SVC/host.realm-2.com@REALM-1.COM name // may be used by REALM-1.COM KDC to return a // referral to REALM-2.COM. - sname = ccreds.getClientAlias(); + sname = middleTGT.getClientAlias(); } sname = new PrincipalName(sname.getNameType(), sname.getNameStrings(), new Realm(uRealm)); } Credentials creds = serviceCreds( KDCOptions.with(KDCOptions.FORWARDABLE), - ccreds, ccreds.getClient(), sname, user, + middleTGT, middleTGT.getClient(), sname, user, null, new PAData[] { new PAData(Krb5.PA_FOR_USER, new PAForUserEnc(user, - ccreds.getSessionKey()).asn1Encode()), + middleTGT.getSessionKey()).asn1Encode()), new PAData(Krb5.PA_PAC_OPTIONS, new PaPacOptions() .setResourceBasedConstrainedDelegation(true) @@ -101,7 +97,7 @@ public class CredentialsUtil { if (!creds.getClient().equals(user)) { throw new KrbException("S4U2self request not honored by KDC"); } - if (!creds.isForwardable()) { + if (!creds.isForwardable() && !Credentials.S4U2PROXY_ACCEPT_NON_FORWARDABLE) { throw new KrbException("S4U2self ticket must be FORWARDABLE"); } return creds; @@ -111,17 +107,17 @@ public class CredentialsUtil { * Used by a middle server to acquire a service ticket to a backend * server using the S4U2proxy extension. * @param backend the name of the backend service - * @param second the client's service ticket to the middle server - * @param ccreds the TGT of the middle server - * @return the creds (cname=client, sname=backend) + * @param userCreds containing the user's service ticket to the middle server + * @param middleTGT the TGT of the middle server + * @return the creds (cname=user, sname=backend) */ public static Credentials acquireS4U2proxyCreds( - String backend, Ticket second, - PrincipalName client, Credentials ccreds) + String backend, Credentials userCreds, + PrincipalName client, Credentials middleTGT) throws KrbException, IOException { PrincipalName backendPrincipal = new PrincipalName(backend); String backendRealm = backendPrincipal.getRealmString(); - String localRealm = ccreds.getClient().getRealmString(); + String localRealm = middleTGT.getClient().getRealmString(); if (!backendRealm.equals(localRealm)) { // The middle service and the backend service are on // different realms, so referrals will be required. @@ -136,8 +132,8 @@ public class CredentialsUtil { } Credentials creds = serviceCreds(KDCOptions.with( KDCOptions.CNAME_IN_ADDL_TKT, KDCOptions.FORWARDABLE), - ccreds, ccreds.getClient(), backendPrincipal, null, - new Ticket[] {second}, new PAData[] { + middleTGT, middleTGT.getClient(), backendPrincipal, null, + userCreds, new PAData[] { new PAData(Krb5.PA_PAC_OPTIONS, new PaPacOptions() .setResourceBasedConstrainedDelegation(true) @@ -159,28 +155,30 @@ public class CredentialsUtil { * from the foreign KDC. * * @param service the name of service principal - * @param ccreds client's initial credential + * @param initCreds client's initial credential */ public static Credentials acquireServiceCreds( - String service, Credentials ccreds) + String service, Credentials initCreds) throws KrbException, IOException { - PrincipalName sname = new PrincipalName(service, - PrincipalName.KRB_NT_UNKNOWN); - return serviceCreds(sname, ccreds); + return serviceCreds(new KDCOptions(), initCreds, + initCreds.getClient(), + new PrincipalName(service, PrincipalName.KRB_NT_UNKNOWN), + null, null, + null, S4U2Type.NONE); } /** * Gets a TGT to another realm * @param localRealm this realm * @param serviceRealm the other realm, cannot equals to localRealm - * @param ccreds TGT in this realm + * @param localTGT TGT in this realm * @param okAsDelegate an [out] argument to receive the okAsDelegate * property. True only if all realms allow delegation. * @return the TGT for the other realm, null if cannot find a path * @throws KrbException if something goes wrong */ private static Credentials getTGTforRealm(String localRealm, - String serviceRealm, Credentials ccreds, boolean[] okAsDelegate) + String serviceRealm, Credentials localTGT, boolean[] okAsDelegate) throws KrbException { // Get a list of realms to traverse @@ -192,7 +190,7 @@ public class CredentialsUtil { String newTgtRealm = null; okAsDelegate[0] = true; - for (cTgt = ccreds, i = 0; i < realms.length;) { + for (cTgt = localTGT, i = 0; i < realms.length;) { tempService = PrincipalName.tgsService(serviceRealm, realms[i]); if (DEBUG) { @@ -309,10 +307,10 @@ public class CredentialsUtil { * This method does the real job to request the service credential. */ private static Credentials serviceCreds( - PrincipalName service, Credentials ccreds) + PrincipalName service, Credentials initCreds) throws KrbException, IOException { - return serviceCreds(new KDCOptions(), ccreds, - ccreds.getClient(), service, null, null, + return serviceCreds(new KDCOptions(), initCreds, + initCreds.getClient(), service, null, null, null, S4U2Type.NONE); } @@ -325,13 +323,13 @@ public class CredentialsUtil { private static Credentials serviceCreds( KDCOptions options, Credentials asCreds, PrincipalName cname, PrincipalName sname, - PrincipalName user, Ticket[] additionalTickets, + PrincipalName user, Credentials additionalCreds, PAData[] extraPAs, S4U2Type s4u2Type) throws KrbException, IOException { if (!Config.DISABLE_REFERRALS) { try { return serviceCredsReferrals(options, asCreds, cname, sname, - s4u2Type, user, additionalTickets, extraPAs); + s4u2Type, user, additionalCreds, extraPAs); } catch (KrbException e) { // Server may raise an error if CANONICALIZE is true. // Try CANONICALIZE false. @@ -339,7 +337,7 @@ public class CredentialsUtil { } return serviceCredsSingle(options, asCreds, cname, asCreds.getClientAlias(), sname, sname, s4u2Type, - user, additionalTickets, extraPAs); + user, additionalCreds, extraPAs); } /* @@ -350,7 +348,7 @@ public class CredentialsUtil { KDCOptions options, Credentials asCreds, PrincipalName cname, PrincipalName sname, S4U2Type s4u2Type, PrincipalName user, - Ticket[] additionalTickets, PAData[] extraPAs) + Credentials additionalCreds, PAData[] extraPAs) throws KrbException, IOException { options = new KDCOptions(options.toBooleanArray()); options.set(KDCOptions.CANONICALIZE, true); @@ -363,12 +361,12 @@ public class CredentialsUtil { while (referrals.size() <= Config.MAX_REFERRALS) { ReferralsCache.ReferralCacheEntry ref = ReferralsCache.get(cname, sname, user, - additionalTickets, refSname.getRealmString()); + additionalCreds, refSname.getRealmString()); String toRealm = null; if (ref == null) { creds = serviceCredsSingle(options, asCreds, cname, clientAlias, refSname, cSname, s4u2Type, - user, additionalTickets, extraPAs); + user, additionalCreds, extraPAs); PrincipalName server = creds.getServer(); if (!refSname.equals(server)) { String[] serverNameStrings = server.getNameStrings(); @@ -380,7 +378,7 @@ public class CredentialsUtil { // Server Name (sname) has the following format: // krbtgt/TO-REALM.COM@FROM-REALM.COM ReferralsCache.put(cname, sname, user, - additionalTickets, server.getRealmString(), + additionalCreds, server.getRealmString(), serverNameStrings[1], creds); toRealm = serverNameStrings[1]; isReferral = true; @@ -398,13 +396,11 @@ public class CredentialsUtil { toRealm = handleS4U2ProxyReferral(asCreds, credsInOut, sname); creds = credsInOut[0]; - if (additionalTickets == null || - additionalTickets.length == 0 || - credsInOut[1] == null) { + if (additionalCreds == null || credsInOut[1] == null) { throw new KrbException("Additional tickets expected" + " for S4U2Proxy."); } - additionalTickets[0] = credsInOut[1].getTicket(); + additionalCreds = credsInOut[1]; } else if (s4u2Type == S4U2Type.SELF) { handleS4U2SelfReferral(extraPAs, user, creds); } @@ -436,7 +432,7 @@ public class CredentialsUtil { PrincipalName cname, PrincipalName clientAlias, PrincipalName refSname, PrincipalName sname, S4U2Type s4u2Type, PrincipalName user, - Ticket[] additionalTickets, PAData[] extraPAs) + Credentials additionalCreds, PAData[] extraPAs) throws KrbException, IOException { Credentials theCreds = null; boolean[] okAsDelegate = new boolean[]{true}; @@ -473,7 +469,7 @@ public class CredentialsUtil { " same realm"); } KrbTgsReq req = new KrbTgsReq(options, asCreds, cname, clientAlias, - refSname, sname, additionalTickets, extraPAs); + refSname, sname, additionalCreds, extraPAs); theCreds = req.sendAndGetCreds(); if (theCreds != null) { if (DEBUG) { diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/internal/KDCReq.java b/src/java.security.jgss/share/classes/sun/security/krb5/internal/KDCReq.java index 39e226a8de2dee03e555a45f21f5c1d2500f7bad..fd37366d7b0c2320c9044aca7d4dff865a73495c 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/internal/KDCReq.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/KDCReq.java @@ -31,7 +31,6 @@ package sun.security.krb5.internal; import sun.security.krb5.*; -import java.util.Vector; import sun.security.util.*; import java.io.IOException; import java.math.BigInteger; @@ -192,8 +191,4 @@ public class KDCReq { true, (byte) msgType), bytes); return out.toByteArray(); } - - public byte[] asn1EncodeReqBody() throws Asn1Exception, IOException { - return reqBody.asn1Encode(msgType); - } } diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/internal/ReferralsCache.java b/src/java.security.jgss/share/classes/sun/security/krb5/internal/ReferralsCache.java index c8f7414877badee912635783e48852fea11b1b8e..fa68fc42b2e1673a48e41ec0dece6d56c110f572 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/internal/ReferralsCache.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/ReferralsCache.java @@ -112,10 +112,10 @@ final class ReferralsCache { * REALM-1.COM -> REALM-2.COM referral entry is removed from the cache. */ static synchronized void put(PrincipalName cname, PrincipalName service, - PrincipalName user, Ticket[] userSvcTickets, String fromRealm, + PrincipalName user, Credentials additionalCreds, String fromRealm, String toRealm, Credentials creds) { - Ticket userSvcTicket = (userSvcTickets != null ? - userSvcTickets[0] : null); + Ticket userSvcTicket = (additionalCreds != null ? + additionalCreds.getTicket() : null); ReferralCacheKey k = new ReferralCacheKey(cname, service, user, userSvcTicket); pruneExpired(k); @@ -152,9 +152,9 @@ final class ReferralsCache { */ static synchronized ReferralCacheEntry get(PrincipalName cname, PrincipalName service, PrincipalName user, - Ticket[] userSvcTickets, String fromRealm) { - Ticket userSvcTicket = (userSvcTickets != null ? - userSvcTickets[0] : null); + Credentials additionalCreds, String fromRealm) { + Ticket userSvcTicket = (additionalCreds != null ? + additionalCreds.getTicket() : null); ReferralCacheKey k = new ReferralCacheKey(cname, service, user, userSvcTicket); pruneExpired(k); diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/internal/Ticket.java b/src/java.security.jgss/share/classes/sun/security/krb5/internal/Ticket.java index e4253d9bcf1eaf2be675b07817d380c7d450f92c..b9268ce2b6c1442e2b87e3a554a220f1d3d11667 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/internal/Ticket.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/Ticket.java @@ -85,12 +85,12 @@ public class Ticket implements Cloneable { // Warning: called by NativeCreds.c and nativeccache.c public Ticket(byte[] data) throws Asn1Exception, - RealmException, KrbApErrException, IOException { + RealmException, KrbApErrException, IOException { init(new DerValue(data)); } public Ticket(DerValue encoding) throws Asn1Exception, - RealmException, KrbApErrException, IOException { + RealmException, KrbApErrException, IOException { init(encoding); } diff --git a/src/java.security.sasl/share/classes/com/sun/security/sasl/CramMD5Base.java b/src/java.security.sasl/share/classes/com/sun/security/sasl/CramMD5Base.java index bbbe88a71e4e1001bbd4bdd92682700600f30137..b59b449e3c5f3136555eab52f5b6dbb695d910e2 100644 --- a/src/java.security.sasl/share/classes/com/sun/security/sasl/CramMD5Base.java +++ b/src/java.security.sasl/share/classes/com/sun/security/sasl/CramMD5Base.java @@ -136,7 +136,7 @@ abstract class CramMD5Base { } } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() { clearPassword(); } diff --git a/src/java.security.sasl/share/classes/com/sun/security/sasl/PlainClient.java b/src/java.security.sasl/share/classes/com/sun/security/sasl/PlainClient.java index e365e772e6e0547df5f44c9eee4e8de9fe85dce3..04a8d9856c2c6611175621a43fa7570d5158cb85 100644 --- a/src/java.security.sasl/share/classes/com/sun/security/sasl/PlainClient.java +++ b/src/java.security.sasl/share/classes/com/sun/security/sasl/PlainClient.java @@ -195,7 +195,7 @@ final class PlainClient implements SaslClient { } } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() { clearPassword(); } diff --git a/src/java.smartcardio/share/classes/sun/security/smartcardio/CardImpl.java b/src/java.smartcardio/share/classes/sun/security/smartcardio/CardImpl.java index 576333a1421cacd83ba74fdb0980a805d6e6edda..b982df5dd07237b66d24b2b553558789213d4e65 100644 --- a/src/java.smartcardio/share/classes/sun/security/smartcardio/CardImpl.java +++ b/src/java.smartcardio/share/classes/sun/security/smartcardio/CardImpl.java @@ -276,7 +276,7 @@ final class CardImpl extends Card { + ", protocol " + getProtocol() + ", state " + state; } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { try { if (state == State.OK) { diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/Init.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/Init.java index 4c51e7b5e8397d771f6eda8ec826a6d415335cbe..a35a4699d82a4aee7da45a9882350a95abdf7fba 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/Init.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/Init.java @@ -84,7 +84,7 @@ public class Init { } @SuppressWarnings("removal") - InputStream is = + InputStream is = //NOPMD AccessController.doPrivileged( (PrivilegedAction) () -> { @@ -351,6 +351,9 @@ public class Init { * @param callingClass The Class object of the calling object */ public static URL getResource(String resourceName, Class callingClass) { + if (resourceName == null) { + throw new NullPointerException(); + } URL url = Thread.currentThread().getContextClassLoader().getResource(resourceName); if (url == null && resourceName.charAt(0) == '/') { //certain classloaders need it without the leading / @@ -404,6 +407,9 @@ public class Init { * @param callingClass The Class object of the calling object */ private static List getResources(String resourceName, Class callingClass) { + if (resourceName == null) { + throw new NullPointerException(); + } List ret = new ArrayList<>(); Enumeration urls = new Enumeration() { public boolean hasMoreElements() { @@ -479,7 +485,7 @@ public class Init { } - if (ret.isEmpty() && resourceName != null && resourceName.charAt(0) != '/') { + if (ret.isEmpty() && resourceName.charAt(0) != '/') { return getResources('/' + resourceName, callingClass); } return ret; diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/IntegrityHmac.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/IntegrityHmac.java index 90302d478446dc9cd6cdbc19bbfcf39418972b3d..fdaf8643279c8d57aa4684cef02007a0fc8dfb6c 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/IntegrityHmac.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/IntegrityHmac.java @@ -309,7 +309,7 @@ public abstract class IntegrityHmac extends SignatureAlgorithmSpi { Node n = XMLUtils.selectDsNode(element.getFirstChild(), Constants._TAG_HMACOUTPUTLENGTH, 0); if (n != null) { String hmacLength = XMLUtils.getFullTextChildrenFromNode(n); - if (hmacLength != null && !"".equals(hmacLength)) { + if (hmacLength != null && hmacLength.length() != 0) { this.hmacOutputLength = new HMACOutputLength(Integer.parseInt(hmacLength)); } } diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer20010315.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer20010315.java index 1ed26fea60bc84ef4a6a6372bd496efb3106a6a2..f0cd610b3209a06fa3aa83eb02844c94e867861f 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer20010315.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer20010315.java @@ -125,7 +125,7 @@ public abstract class Canonicalizer20010315 extends CanonicalizerBase { * Output the Attr[]s for the given element. *
    * The code of this method is a copy of - * {@link #outputAttributes(Element, NameSpaceSymbTable, Map)}, + * {@link #outputAttributes(Element, NameSpaceSymbTable, Map, OutputStream)}, * whereas it takes into account that subtree-c14n is -- well -- subtree-based. * So if the element in question isRoot of c14n, it's parent is not in the * node set, as well as all other ancestors. diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/CanonicalizerBase.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/CanonicalizerBase.java index d3b972c95f853ea3ac48db2e1447ca511ff126ba..ce971a45a98101196cd9112dfc4c041021cc64a2 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/CanonicalizerBase.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/CanonicalizerBase.java @@ -211,7 +211,7 @@ public abstract class CanonicalizerBase extends CanonicalizerSpi { Node sibling = null; Node parentNode = null; Map cache = new HashMap<>(); - do { + do { //NOPMD switch (currentNode.getNodeType()) { case Node.ENTITY_NODE : @@ -338,7 +338,7 @@ public abstract class CanonicalizerBase extends CanonicalizerSpi { Node parentNode = null; int documentLevel = NODE_BEFORE_DOCUMENT_ELEMENT; Map cache = new HashMap<>(); - do { + do { //NOPMD switch (currentNode.getNodeType()) { case Node.ENTITY_NODE : @@ -560,7 +560,7 @@ public abstract class CanonicalizerBase extends CanonicalizerSpi { } parents.clear(); Attr nsprefix = ns.getMappingWithoutRendered(XMLNS); - if (nsprefix != null && "".equals(nsprefix.getValue())) { + if (nsprefix != null && nsprefix.getValue().length() == 0) { ns.addMappingAndRender( XMLNS, "", getNullNode(nsprefix.getOwnerDocument())); } diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/CanonicalizerPhysical.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/CanonicalizerPhysical.java index 4b2333938f5cc7335735420f6da4d9955d136bbf..66ad12029fc0d29f78edff7254c759e711445dd3 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/CanonicalizerPhysical.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/CanonicalizerPhysical.java @@ -110,7 +110,7 @@ public class CanonicalizerPhysical extends CanonicalizerBase { * Output the Attr[]s for the given element. *
    * The code of this method is a copy of - * {@link #outputAttributes(Element, NameSpaceSymbTable, Map)}, + * {@link #outputAttributes(Element, NameSpaceSymbTable, Map, OutputStream)}, * whereas it takes into account that subtree-c14n is -- well -- subtree-based. * So if the element in question isRoot of c14n, it's parent is not in the * node set, as well as all other ancestors. diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/NameSpaceSymbTable.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/NameSpaceSymbTable.java index 2fc853fe6901806728b4ffdab78203b2abae77c1..f0b1903accdcdba0933aa17efb819007fb4bb1e0 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/NameSpaceSymbTable.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/NameSpaceSymbTable.java @@ -348,7 +348,7 @@ class SymbMap implements Cloneable { List entrySet() { List a = new ArrayList<>(); for (int i = 0;i < entries.length;i++) { - if (entries[i] != null && !"".equals(entries[i].uri)) { + if (entries[i] != null && entries[i].uri.length() != 0) { a.add(entries[i]); } } diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/exceptions/XMLSecurityRuntimeException.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/exceptions/XMLSecurityRuntimeException.java deleted file mode 100644 index 7d17fe867e1ac1d7380b20feae5e24055cb55085..0000000000000000000000000000000000000000 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/exceptions/XMLSecurityRuntimeException.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package com.sun.org.apache.xml.internal.security.exceptions; - -import java.text.MessageFormat; - -import com.sun.org.apache.xml.internal.security.utils.Constants; -import com.sun.org.apache.xml.internal.security.utils.I18n; - -/** - * The mother of all runtime Exceptions in this bundle. It allows exceptions to have - * their messages translated to the different locales. - * - * The {@code xmlsecurity_en.properties} file contains this line: - *
    - * xml.WrongElement = Can't create a {0} from a {1} element
    - * 
    - * - * Usage in the Java source is: - *
    - * {
    - *    Object[] exArgs = { Constants._TAG_TRANSFORMS, "BadElement" };
    - *
    - *    throw new XMLSecurityException("xml.WrongElement", exArgs);
    - * }
    - * 
    - * - * Additionally, if another Exception has been caught, we can supply it, too - *
    - * try {
    - *    ...
    - * } catch (Exception oldEx) {
    - *    Object[] exArgs = { Constants._TAG_TRANSFORMS, "BadElement" };
    - *
    - *    throw new XMLSecurityException("xml.WrongElement", exArgs, oldEx);
    - * }
    - * 
    - * - * - */ -public class XMLSecurityRuntimeException extends RuntimeException { - - private static final long serialVersionUID = 1L; - - /** Field msgID */ - protected String msgID; - - /** - * Constructor XMLSecurityRuntimeException - * - */ - public XMLSecurityRuntimeException() { - super("Missing message string"); - - this.msgID = null; - } - - /** - * Constructor XMLSecurityRuntimeException - * - * @param msgID - */ - public XMLSecurityRuntimeException(String msgID) { - super(I18n.getExceptionMessage(msgID)); - - this.msgID = msgID; - } - - /** - * Constructor XMLSecurityRuntimeException - * - * @param msgID - * @param exArgs - */ - public XMLSecurityRuntimeException(String msgID, Object[] exArgs) { - super(MessageFormat.format(I18n.getExceptionMessage(msgID), exArgs)); - - this.msgID = msgID; - } - - /** - * Constructor XMLSecurityRuntimeException - * - * @param originalException - */ - public XMLSecurityRuntimeException(Exception originalException) { - super("Missing message ID to locate message string in resource bundle \"" - + Constants.exceptionMessagesResourceBundleBase - + "\". Original Exception was a " - + originalException.getClass().getName() + " and message " - + originalException.getMessage(), originalException); - } - - /** - * Constructor XMLSecurityRuntimeException - * - * @param msgID - * @param originalException - */ - public XMLSecurityRuntimeException(String msgID, Exception originalException) { - super(I18n.getExceptionMessage(msgID, originalException), originalException); - - this.msgID = msgID; - } - - /** - * Constructor XMLSecurityRuntimeException - * - * @param msgID - * @param exArgs - * @param originalException - */ - public XMLSecurityRuntimeException(String msgID, Object[] exArgs, Exception originalException) { - super(MessageFormat.format(I18n.getExceptionMessage(msgID), exArgs), originalException); - - this.msgID = msgID; - } - - /** - * Method getMsgID - * - * @return the messageId - */ - public String getMsgID() { - if (msgID == null) { - return "Missing message ID"; - } - return msgID; - } - - /** {@inheritDoc} */ - public String toString() { - String s = this.getClass().getName(); - String message = super.getLocalizedMessage(); - - if (message != null) { - message = s + ": " + message; - } else { - message = s; - } - - if (this.getCause() != null) { - message = message + "\nOriginal Exception was " + this.getCause().toString(); - } - - return message; - } - - /** - * Method getOriginalException - * - * @return the original exception - */ - public Exception getOriginalException() { - if (this.getCause() instanceof Exception) { - return (Exception)this.getCause(); - } - return null; - } - -} diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java index 7aa9a30128ab7e08850e9faf60bbc2fe0239c9a4..7445013e9cbcc2d7080c123a63258dee02f7a14d 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java @@ -170,8 +170,8 @@ public class KeyResolver { ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException { JavaUtils.checkRegisterPermission(); - KeyResolverSpi keyResolverSpi = - (KeyResolverSpi) JavaUtils.newInstanceWithEmptyConstructor(ClassLoaderUtils.loadClass(className, KeyResolver.class)); + KeyResolverSpi keyResolverSpi = (KeyResolverSpi) + JavaUtils.newInstanceWithEmptyConstructor(ClassLoaderUtils.loadClass(className, KeyResolver.class)); register(keyResolverSpi, false); } @@ -193,8 +193,8 @@ public class KeyResolver { KeyResolverSpi keyResolverSpi = null; Exception ex = null; try { - keyResolverSpi = (KeyResolverSpi) JavaUtils.newInstanceWithEmptyConstructor( - ClassLoaderUtils.loadClass(className, KeyResolver.class)); + keyResolverSpi = (KeyResolverSpi) + JavaUtils.newInstanceWithEmptyConstructor(ClassLoaderUtils.loadClass(className, KeyResolver.class)); register(keyResolverSpi, true); } catch (ClassNotFoundException | IllegalAccessException | InstantiationException | InvocationTargetException e) { ex = e; @@ -253,8 +253,8 @@ public class KeyResolver { JavaUtils.checkRegisterPermission(); List keyResolverList = new ArrayList<>(classNames.size()); for (String className : classNames) { - KeyResolverSpi keyResolverSpi = (KeyResolverSpi)JavaUtils - .newInstanceWithEmptyConstructor(ClassLoaderUtils.loadClass(className, KeyResolver.class)); + KeyResolverSpi keyResolverSpi = (KeyResolverSpi) + JavaUtils.newInstanceWithEmptyConstructor(ClassLoaderUtils.loadClass(className, KeyResolver.class)); keyResolverList.add(keyResolverSpi); } resolverList.addAll(keyResolverList); diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/KeyInfoReferenceResolver.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/KeyInfoReferenceResolver.java index fb32875c1b15fcc607ee0180a59d8dddd7425965..101fd2d12a554529d993329d75ffbb9ee41488bb 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/KeyInfoReferenceResolver.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/KeyInfoReferenceResolver.java @@ -162,6 +162,7 @@ public class KeyInfoReferenceResolver extends KeyResolverSpi { validateReference(referentElement, secureValidation); KeyInfo referent = new KeyInfo(referentElement, baseURI); + referent.setSecureValidation(secureValidation); referent.addStorageResolver(storage); return referent; } @@ -181,7 +182,7 @@ public class KeyInfoReferenceResolver extends KeyResolverSpi { } KeyInfo referent = new KeyInfo(referentElement, ""); - if (referent.containsKeyInfoReference()) { + if (referent.containsKeyInfoReference() || referent.containsRetrievalMethod()) { if (secureValidation) { throw new XMLSecurityException("KeyInfoReferenceResolver.InvalidReferentElement.ReferenceWithSecure"); } else { diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/resource/config.xml b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/resource/config.xml index 603d49e0ad5a4229ec3414f234ce00e238c03bfe..bbd26a399ca5cda99bf767690201f0bfccc2b8ff 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/resource/config.xml +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/resource/config.xml @@ -96,8 +96,6 @@ - ith SignatureProperty. Valid {@code i} - * values are 0 to {@code {link@ getSize}-1}. + * values are 0 to {@code {@link getSize}-1}. * * @param i Index of the requested {@link SignatureProperty} * @return the ith SignatureProperty diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/XMLSignatureInput.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/XMLSignatureInput.java index a6b1c6cd1704b7b561646d18f0eef7af2630d6fe..165bc98721fb5059331b67a11cb283ccb269fdcf 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/XMLSignatureInput.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/XMLSignatureInput.java @@ -36,7 +36,6 @@ import com.sun.org.apache.xml.internal.security.c14n.CanonicalizationException; import com.sun.org.apache.xml.internal.security.c14n.implementations.Canonicalizer11_OmitComments; import com.sun.org.apache.xml.internal.security.c14n.implementations.Canonicalizer20010315OmitComments; import com.sun.org.apache.xml.internal.security.c14n.implementations.CanonicalizerBase; -import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityRuntimeException; import com.sun.org.apache.xml.internal.security.parser.XMLParserException; import com.sun.org.apache.xml.internal.security.utils.JavaUtils; import com.sun.org.apache.xml.internal.security.utils.XMLUtils; @@ -141,7 +140,7 @@ public class XMLSignatureInput { /** * Construct a XMLSignatureInput from a subtree rooted by rootNode. This - * method included the node and all his descendants in the output. + * method included the node and all its descendants in the output. * * @param rootNode */ @@ -528,7 +527,7 @@ public class XMLSignatureInput { if (inputOctetStreamProxy == null) { return null; } - try { + try { //NOPMD bytes = JavaUtils.getBytesFromStream(inputOctetStreamProxy); } finally { inputOctetStreamProxy.close(); @@ -539,15 +538,9 @@ public class XMLSignatureInput { /** * @param filter */ - public void addNodeFilter(NodeFilter filter) { + public void addNodeFilter(NodeFilter filter) throws XMLParserException, IOException { if (isOctetStream()) { - try { - convertToNodes(); - } catch (Exception e) { - throw new XMLSecurityRuntimeException( - "signature.XMLSignatureInput.nodesetReference", e - ); - } + convertToNodes(); } nodeFilters.add(filter); } diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformC14N.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformC14N.java index e0f9b4faa1e3535c088b37363b567abb8ba44d42..6337bc2c201dbe09b54d60a74caddfa9baa693f1 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformC14N.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformC14N.java @@ -60,7 +60,7 @@ public class TransformC14N extends TransformSpi { Canonicalizer20010315 c14n = getCanonicalizer(); - if (os == null) { + if (os == null && (input.isOctetStream() || input.isElement() || input.isNodeSet())) { try (ByteArrayOutputStream writer = new ByteArrayOutputStream()) { c14n.engineCanonicalize(input, writer, secureValidation); writer.flush(); diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformC14NExclusive.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformC14NExclusive.java index 5393fa99ac3024f2d67b50b4ce594be3a5802d83..eca648267e1e69ccfaba8c657932e2bfbd3c4e0f 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformC14NExclusive.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformC14NExclusive.java @@ -82,7 +82,7 @@ public class TransformC14NExclusive extends TransformSpi { Canonicalizer20010315Excl c14n = getCanonicalizer(); - if (os == null) { + if (os == null && (input.isOctetStream() || input.isElement() || input.isNodeSet())) { try (ByteArrayOutputStream writer = new ByteArrayOutputStream()) { c14n.engineCanonicalize(input, inclusiveNamespaces, writer, secureValidation); writer.flush(); diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformEnvelopedSignature.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformEnvelopedSignature.java index 539590cc84c742d3405598f128a1bd264bfb4efb..030d7063cc30073e8e67397397c305a48386329e 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformEnvelopedSignature.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformEnvelopedSignature.java @@ -22,8 +22,10 @@ */ package com.sun.org.apache.xml.internal.security.transforms.implementations; +import java.io.IOException; import java.io.OutputStream; +import com.sun.org.apache.xml.internal.security.parser.XMLParserException; import com.sun.org.apache.xml.internal.security.signature.NodeFilter; import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput; import com.sun.org.apache.xml.internal.security.transforms.TransformSpi; @@ -71,7 +73,11 @@ public class TransformEnvelopedSignature extends TransformSpi { Node signatureElement = searchSignatureElement(transformElement); input.setExcludeNode(signatureElement); - input.addNodeFilter(new EnvelopedNodeFilter(signatureElement)); + try { + input.addNodeFilter(new EnvelopedNodeFilter(signatureElement)); + } catch (XMLParserException | IOException ex) { + throw new TransformationException(ex); + } return input; } diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformXPath.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformXPath.java index cdde27c6834c1840286868733249185e21de0dfb..ca844c0068256d628eeeb56000e90d216a24156d 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformXPath.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformXPath.java @@ -22,11 +22,12 @@ */ package com.sun.org.apache.xml.internal.security.transforms.implementations; +import java.io.IOException; import java.io.OutputStream; import javax.xml.transform.TransformerException; -import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityRuntimeException; +import com.sun.org.apache.xml.internal.security.parser.XMLParserException; import com.sun.org.apache.xml.internal.security.signature.NodeFilter; import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput; import com.sun.org.apache.xml.internal.security.transforms.TransformSpi; @@ -51,6 +52,9 @@ import org.w3c.dom.Node; */ public class TransformXPath extends TransformSpi { + private static final com.sun.org.slf4j.internal.Logger LOG = + com.sun.org.slf4j.internal.LoggerFactory.getLogger(TransformXPath.class); + /** * {@inheritDoc} */ @@ -102,7 +106,7 @@ public class TransformXPath extends TransformSpi { input.addNodeFilter(new XPathNodeFilter(xpathElement, xpathnode, str, xpathAPIInstance)); input.setNodeSet(true); return input; - } catch (DOMException ex) { + } catch (XMLParserException | IOException | DOMException ex) { throw new TransformationException(ex); } } @@ -144,11 +148,8 @@ public class TransformXPath extends TransformSpi { } return 0; } catch (TransformerException e) { - Object[] eArgs = {currentNode}; - throw new XMLSecurityRuntimeException("signature.Transform.node", eArgs, e); - } catch (Exception e) { - Object[] eArgs = {currentNode, currentNode.getNodeType()}; - throw new XMLSecurityRuntimeException("signature.Transform.nodeAndType",eArgs, e); + LOG.debug("Error evaluating XPath expression", e); + return 0; } } diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/Base64.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/Base64.java index d9d0e761468f4f67f2b113bd8d82b7e3c8e85446..0534fff3844b90c882ae371df5d20b7a3058fd69 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/Base64.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/Base64.java @@ -43,6 +43,7 @@ import org.w3c.dom.Text; * @see com.sun.org.apache.xml.internal.security.transforms.implementations.TransformBase64Decode */ @Deprecated +@SuppressWarnings("PMD") public final class Base64 { /** Field BASE64DEFAULTLENGTH */ diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/DOMNamespaceContext.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/DOMNamespaceContext.java index 116e868834228a1980c8e759c81d520eb767300a..6a2f5d5af260e9cfe3d637a422eb01a50c021707 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/DOMNamespaceContext.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/DOMNamespaceContext.java @@ -127,11 +127,11 @@ public class DOMNamespaceContext implements NamespaceContext { return DEFAULT_NS_PREFIX; } } - if (namespaceURI == null) { + if (namespaceURI == null && context != null) { return context.lookupNamespaceURI(null) != null ? null : DEFAULT_NS_PREFIX; - } else if (namespaceURI.equals(XML_NS_URI)) { + } else if (XML_NS_URI.equals(namespaceURI)) { return XML_NS_PREFIX; - } else if (namespaceURI.equals(XMLNS_ATTRIBUTE_NS_URI)) { + } else if (XMLNS_ATTRIBUTE_NS_URI.equals(namespaceURI)) { return XMLNS_ATTRIBUTE; } return null; diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/RFC2253Parser.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/RFC2253Parser.java index 4574e35f76a5d9a193055765c405edadc5cb33d3..552d1330a3f22aa5d87c27b7108354fe3bd7e67b 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/RFC2253Parser.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/RFC2253Parser.java @@ -190,20 +190,21 @@ public class RFC2253Parser { if (value.startsWith("\"")) { StringBuilder sb = new StringBuilder(); - StringReader sr = new StringReader(value.substring(1, value.length() - 1)); - int i = 0; - char c; + try (StringReader sr = new StringReader(value.substring(1, value.length() - 1))) { + int i = 0; + char c; - while ((i = sr.read()) > -1) { - c = (char) i; + while ((i = sr.read()) > -1) { + c = (char) i; - //the following char is defined at 4.Relationship with RFC1779 and LDAPv2 inrfc2253 - if (c == ',' || c == '=' || c == '+' || c == '<' - || c == '>' || c == '#' || c == ';') { - sb.append('\\'); - } + //the following char is defined at 4.Relationship with RFC1779 and LDAPv2 inrfc2253 + if (c == ',' || c == '=' || c == '+' || c == '<' + || c == '>' || c == '#' || c == ';') { + sb.append('\\'); + } - sb.append(c); + sb.append(c); + } } value = trim(sb.toString()); @@ -263,37 +264,38 @@ public class RFC2253Parser { */ static String changeLess32toRFC(String string) throws IOException { StringBuilder sb = new StringBuilder(); - StringReader sr = new StringReader(string); int i = 0; char c; - while ((i = sr.read()) > -1) { - c = (char) i; - - if (c == '\\') { - sb.append(c); - - char c1 = (char) sr.read(); - char c2 = (char) sr.read(); - - //65 (A) 97 (a) - if ((c1 >= 48 && c1 <= 57 || c1 >= 65 && c1 <= 70 || c1 >= 97 && c1 <= 102) - && (c2 >= 48 && c2 <= 57 - || c2 >= 65 && c2 <= 70 - || c2 >= 97 && c2 <= 102)) { - try { - char ch = (char) Byte.parseByte("" + c1 + c2, 16); + try (StringReader sr = new StringReader(string)) { + while ((i = sr.read()) > -1) { + c = (char) i; - sb.append(ch); - } catch (NumberFormatException ex) { - throw new IOException(ex); + if (c == '\\') { + sb.append(c); + + char c1 = (char) sr.read(); + char c2 = (char) sr.read(); + + //65 (A) 97 (a) + if ((c1 >= 48 && c1 <= 57 || c1 >= 65 && c1 <= 70 || c1 >= 97 && c1 <= 102) + && (c2 >= 48 && c2 <= 57 + || c2 >= 65 && c2 <= 70 + || c2 >= 97 && c2 <= 102)) { + try { + char ch = (char) Byte.parseByte("" + c1 + c2, 16); + + sb.append(ch); + } catch (NumberFormatException ex) { + throw new IOException(ex); + } + } else { + sb.append(c1); + sb.append(c2); } } else { - sb.append(c1); - sb.append(c2); + sb.append(c); } - } else { - sb.append(c); } } @@ -309,15 +311,16 @@ public class RFC2253Parser { */ static String changeLess32toXML(String string) throws IOException { StringBuilder sb = new StringBuilder(); - StringReader sr = new StringReader(string); int i = 0; - while ((i = sr.read()) > -1) { - if (i < 32) { - sb.append('\\'); - sb.append(Integer.toHexString(i)); - } else { - sb.append((char) i); + try (StringReader sr = new StringReader(string)) { + while ((i = sr.read()) > -1) { + if (i < 32) { + sb.append('\\'); + sb.append(Integer.toHexString(i)); + } else { + sb.append((char) i); + } } } @@ -333,28 +336,29 @@ public class RFC2253Parser { */ static String changeWStoXML(String string) throws IOException { StringBuilder sb = new StringBuilder(); - StringReader sr = new StringReader(string); int i = 0; char c; - while ((i = sr.read()) > -1) { - c = (char) i; + try (StringReader sr = new StringReader(string)) { + while ((i = sr.read()) > -1) { + c = (char) i; - if (c == '\\') { - char c1 = (char) sr.read(); + if (c == '\\') { + char c1 = (char) sr.read(); - if (c1 == ' ') { - sb.append('\\'); + if (c1 == ' ') { + sb.append('\\'); - String s = "20"; + String s = "20"; - sb.append(s); + sb.append(s); + } else { + sb.append('\\'); + sb.append(c1); + } } else { - sb.append('\\'); - sb.append(c1); + sb.append(c); } - } else { - sb.append(c); } } diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/XMLUtils.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/XMLUtils.java index 5eaeda3b5f07d0b0dcebe5706c6615cdd6df60fd..446d640194e0969a147b13d2930e20a66eed8e69 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/XMLUtils.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/XMLUtils.java @@ -583,7 +583,7 @@ public final class XMLUtils { Node parent = null; Node sibling = null; final String namespaceNs = Constants.NamespaceSpecNS; - do { + do { //NOPMD switch (node.getNodeType()) { case Node.ELEMENT_NODE : Element element = (Element) node; diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolver.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolver.java index 1b3f2be87cb216790434c2a09075177b195ec181..42271aa0128951bab1955264353e1a3ed0e0c146 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolver.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolver.java @@ -122,8 +122,8 @@ public class ResourceResolver { List resourceResolversToAdd = new ArrayList<>(classNames.size()); for (String className : classNames) { - ResourceResolverSpi resourceResolverSpi = (ResourceResolverSpi)JavaUtils - .newInstanceWithEmptyConstructor(ClassLoaderUtils.loadClass(className, ResourceResolver.class)); + ResourceResolverSpi resourceResolverSpi = (ResourceResolverSpi) + JavaUtils.newInstanceWithEmptyConstructor(ClassLoaderUtils.loadClass(className, ResourceResolver.class)); resourceResolversToAdd.add(resourceResolverSpi); } resolverList.addAll(resourceResolversToAdd); @@ -159,15 +159,6 @@ public class ResourceResolver { LOG.debug("check resolvability by class {}", resolver.getClass().getName()); if (resolver.engineCanResolveURI(context)) { - // Check to see whether the Resolver is allowed - if (context.secureValidation - && (resolver instanceof ResolverLocalFilesystem - || resolver instanceof ResolverDirectHTTP)) { - Object[] exArgs = { resolver.getClass().getName() }; - throw new ResourceResolverException( - "signature.Reference.ForbiddenResolver", exArgs, context.uriToResolve, context.baseUri - ); - } return resolver.engineResolveURI(context); } } diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolverContext.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolverContext.java index 47d0dbb87a8e4438723c41b228828c3d47642ccf..ef56d435dde2a1a70060ce047651b756fc9e003d 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolverContext.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolverContext.java @@ -54,5 +54,4 @@ public class ResourceResolverContext { public Map getProperties() { return properties; } - } diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/implementations/ResolverDirectHTTP.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/implementations/ResolverDirectHTTP.java index 955a42a01cff16c674d151f700d926197d052a7c..c1f9e199fb2c8764b625143e51c36ce4d0c0e165 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/implementations/ResolverDirectHTTP.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/implementations/ResolverDirectHTTP.java @@ -219,7 +219,8 @@ public class ResolverDirectHTTP extends ResourceResolverSpi { LOG.debug("I was asked whether I can resolve {}", context.uriToResolve); if (context.uriToResolve.startsWith("http:") || - context.baseUri != null && context.baseUri.startsWith("http:")) { + context.uriToResolve.startsWith("https:") || + context.baseUri != null && (context.baseUri.startsWith("http:") || context.baseUri.startsWith("https:"))) { LOG.debug("I state that I can resolve {}", context.uriToResolve); return true; } @@ -231,7 +232,7 @@ public class ResolverDirectHTTP extends ResourceResolverSpi { private static URI getNewURI(String uri, String baseURI) throws URISyntaxException { URI newUri = null; - if (baseURI == null || "".equals(baseURI)) { + if (baseURI == null || baseURI.length() == 0) { newUri = new URI(uri); } else { newUri = new URI(baseURI).resolve(uri); diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/implementations/ResolverLocalFilesystem.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/implementations/ResolverLocalFilesystem.java index 7e73ace1b2acdb496b7f62e7b58b011ff11a56d5..9d7e00bdbd6bd5fe6002676933fe0b9fc66cf687 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/implementations/ResolverLocalFilesystem.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/implementations/ResolverLocalFilesystem.java @@ -38,8 +38,6 @@ import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverS */ public class ResolverLocalFilesystem extends ResourceResolverSpi { - private static final int FILE_URI_LENGTH = "file:/".length(); - private static final com.sun.org.slf4j.internal.Logger LOG = com.sun.org.slf4j.internal.LoggerFactory.getLogger(ResolverLocalFilesystem.class); @@ -53,9 +51,7 @@ public class ResolverLocalFilesystem extends ResourceResolverSpi { // calculate new URI URI uriNew = getNewURI(context.uriToResolve, context.baseUri); - String fileName = - ResolverLocalFilesystem.translateUriToFilename(uriNew.toString()); - InputStream inputStream = Files.newInputStream(Paths.get(fileName)); + InputStream inputStream = Files.newInputStream(Paths.get(uriNew)); //NOPMD XMLSignatureInput result = new XMLSignatureInput(inputStream); result.setSecureValidation(context.secureValidation); @@ -67,41 +63,6 @@ public class ResolverLocalFilesystem extends ResourceResolverSpi { } } - /** - * Method translateUriToFilename - * - * @param uri - * @return the string of the filename - */ - private static String translateUriToFilename(String uri) { - - String subStr = uri.substring(FILE_URI_LENGTH); - - if (subStr.indexOf("%20") > -1) { - int offset = 0; - int index = 0; - StringBuilder temp = new StringBuilder(subStr.length()); - do { - index = subStr.indexOf("%20",offset); - if (index == -1) { - temp.append(subStr.substring(offset)); - } else { - temp.append(subStr.substring(offset, index)); - temp.append(' '); - offset = index + 3; - } - } while(index != -1); - subStr = temp.toString(); - } - - if (subStr.charAt(1) == ':') { - // we're running M$ Windows, so this works fine - return subStr; - } - // we're running some UNIX, so we have to prepend a slash - return "/" + subStr; - } - /** * {@inheritDoc} */ @@ -111,7 +72,7 @@ public class ResolverLocalFilesystem extends ResourceResolverSpi { } if (context.uriToResolve.isEmpty() || context.uriToResolve.charAt(0) == '#' || - context.uriToResolve.startsWith("http:")) { + context.uriToResolve.startsWith("http:") || context.uriToResolve.startsWith("https:")) { return false; } @@ -133,7 +94,7 @@ public class ResolverLocalFilesystem extends ResourceResolverSpi { private static URI getNewURI(String uri, String baseURI) throws URISyntaxException { URI newUri = null; - if (baseURI == null || "".equals(baseURI)) { + if (baseURI == null || baseURI.length() == 0) { newUri = new URI(uri); } else { newUri = new URI(baseURI).resolve(uri); diff --git a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/ApacheCanonicalizer.java b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/ApacheCanonicalizer.java index bb279ecc728817bf6587f942f7029f6960965f71..7655866ad7402618fc11013c570fb79a3707e392 100644 --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/ApacheCanonicalizer.java +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/ApacheCanonicalizer.java @@ -239,9 +239,6 @@ public abstract class ApacheCanonicalizer extends TransformService { try { in = apacheTransform.performTransform(in, os, secVal); - if (!in.isNodeSet() && !in.isElement()) { - return null; - } if (in.isOctetStream()) { return new ApacheOctetStreamData(in); } else { diff --git a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMReference.java b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMReference.java index 0b63c5eba1615eaafde0fdf1a6ef79ac9703517a..d278808ea0572832352e188b6cf1417fc0c9583f 100644 --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMReference.java +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMReference.java @@ -447,7 +447,7 @@ public final class DOMReference extends DOMStructure } Data data = dereferencedData; XMLSignatureInput xi = null; - try (OutputStream os = new UnsyncBufferedOutputStream(dos)) { + try (OutputStream os = new UnsyncBufferedOutputStream(dos)) { //NOPMD for (int i = 0, size = transforms.size(); i < size; i++) { DOMTransform transform = (DOMTransform)transforms.get(i); if (i < size - 1) { diff --git a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMTransform.java b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMTransform.java index a18b76e81f65af2134d1c31a40f756062ab99add..fd6a89229c49dddea5d40c1aa013aa7e47a4d1b2 100644 --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMTransform.java +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMTransform.java @@ -116,7 +116,7 @@ public class DOMTransform extends DOMStructure implements Transform { Document ownerDoc = DOMUtils.getOwnerDocument(parent); Element transformElem = null; - if (parent.getLocalName().equals("Transforms")) { + if ("Transforms".equals(parent.getLocalName())) { transformElem = DOMUtils.createElement(ownerDoc, "Transform", XMLSignature.XMLNS, dsPrefix); diff --git a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java index 6b728e236cb91ed12d3e3f14ace09d2b2973bc3e..e72642bbff35570d09bb229e60e75dd86e20a886 100644 --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java @@ -21,7 +21,7 @@ * under the License. */ /* - * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. */ package org.jcp.xml.dsig.internal.dom; @@ -101,7 +101,9 @@ public final class DOMURIDereferencer implements URIDereferencer { if (id.startsWith("xpointer(id(")) { int i1 = id.indexOf('\''); int i2 = id.indexOf('\'', i1+1); - id = id.substring(i1+1, i2); + if (i1 >= 0 && i2 >= 0) { + id = id.substring(i1 + 1, i2); + } } // check if element is registered by Id @@ -138,7 +140,7 @@ public final class DOMURIDereferencer implements URIDereferencer { } try { - ResourceResolverContext resContext = new ResourceResolverContext(uriAttr, baseURI, false); + ResourceResolverContext resContext = new ResourceResolverContext(uriAttr, baseURI, secVal); XMLSignatureInput in = ResourceResolver.resolve(resContext); if (in.isOctetStream()) { return new ApacheOctetStreamData(in); diff --git a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/Policy.java b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/Policy.java index f32cf39fd6212cdcb869339b409b955c6af2ad3a..fffca6b38f5262286d7aaedab42c26be1fe7c32a 100644 --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/Policy.java +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/Policy.java @@ -43,14 +43,13 @@ import java.util.Set; */ public final class Policy { - // all restrictions are initialized to be unconstrained - private static Set disallowedAlgs = new HashSet<>(); - private static int maxTrans = Integer.MAX_VALUE; - private static int maxRefs = Integer.MAX_VALUE; - private static Set disallowedRefUriSchemes = new HashSet<>(); - private static Map minKeyMap = new HashMap<>(); - private static boolean noDuplicateIds = false; - private static boolean noRMLoops = false; + private static Set disallowedAlgs; + private static int maxTrans; + private static int maxRefs; + private static Set disallowedRefUriSchemes; + private static Map minKeyMap; + private static boolean noDuplicateIds; + private static boolean noRMLoops; static { try { @@ -64,6 +63,16 @@ public final class Policy { private Policy() {} private static void initialize() { + // First initialized to be unconstrained and then parse the + // security property "jdk.xml.dsig.secureValidationPolicy" + disallowedAlgs = new HashSet<>(); + maxTrans = Integer.MAX_VALUE; + maxRefs = Integer.MAX_VALUE; + disallowedRefUriSchemes = new HashSet<>(); + minKeyMap = new HashMap<>(); + noDuplicateIds = false; + noRMLoops = false; + @SuppressWarnings("removal") String prop = AccessController.doPrivileged((PrivilegedAction) () -> diff --git a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/Utils.java b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/Utils.java index 0edb5dd5aff7019b895101a1c889723561a3f058..bcf28d0afe209c934be92db1093b963c227bdb8c 100644 --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/Utils.java +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/Utils.java @@ -21,7 +21,7 @@ * under the License. */ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. */ package org.jcp.xml.dsig.internal.dom; @@ -94,7 +94,9 @@ public final class Utils { if (id.startsWith("xpointer(id(")) { int i1 = id.indexOf('\''); int i2 = id.indexOf('\'', i1+1); - id = id.substring(i1+1, i2); + if (i1 >= 0 && i2 >= 0) { + id = id.substring(i1 + 1, i2); + } } return id; } @@ -114,7 +116,7 @@ public final class Utils { } private static boolean getBoolean(XMLCryptoContext xc, String name) { - Boolean value = (Boolean)xc.getProperty(name); + Boolean value = (Boolean) xc.getProperty(name); return value != null && value; } } diff --git a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/XMLDSigRI.java b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/XMLDSigRI.java index f26b6d9940b0e45b898d96ea9c2abbaf69797e4a..65bb25f058ff261393bbf191432ec610a482aeca 100644 --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/XMLDSigRI.java +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/XMLDSigRI.java @@ -134,7 +134,7 @@ public final class XMLDSigRI extends Provider { @SuppressWarnings("removal") public XMLDSigRI() { // This is the JDK XMLDSig provider, synced from - // Apache Santuario XML Security for Java, version 2.2.1 + // Apache Santuario XML Security for Java, version 2.3.0 super("XMLDSig", VER, INFO); final Provider p = this; diff --git a/src/java.xml.crypto/share/legal/santuario.md b/src/java.xml.crypto/share/legal/santuario.md index eba3a79e3e9f909de31670820917548d691e9f57..fa87128126d19e089465db75c016bbde4e236e22 100644 --- a/src/java.xml.crypto/share/legal/santuario.md +++ b/src/java.xml.crypto/share/legal/santuario.md @@ -1,4 +1,4 @@ -## Apache Santuario v2.2.1 +## Apache Santuario v2.3.0 ### Apache Santuario Notice
    diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java
    index 99d3681c0e7bc26ad43515ecd6fd8a4538b6fe1d..a76dcaf7cdb70b97b0bd28efeb02354d519dc83b 100644
    --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java
    +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java
    @@ -58,7 +58,7 @@ import org.xml.sax.XMLReader;
      * @author G. Todd Miller
      * @author Morten Jorgensen
      * @author John Howard (johnh@schemasoft.com)
    - * @LastModified: May 2021
    + * @LastModified: Nov 2021
      */
     public final class XSLTC {
     
    @@ -460,8 +460,11 @@ public final class XSLTC {
                     if (name != null) {
                         setClassName(name);
                     }
    -                else if (systemId != null && !systemId.equals("")) {
    -                    setClassName(Util.baseName(systemId));
    +                else if (systemId != null && !systemId.isEmpty()) {
    +                    String clsName = Util.baseName(systemId);
    +                    if (clsName != null && !clsName.isEmpty()) {
    +                        setClassName(clsName);
    +                    }
                     }
     
                     // Ensure we have a non-empty class name at this point
    diff --git a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathFactoryImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathFactoryImpl.java
    index f5ad625ec17b54f07c968c454091c485df93d6cd..f41615fe6ab1276f7d7d0e38df426413f457cece 100644
    --- a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathFactoryImpl.java
    +++ b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathFactoryImpl.java
    @@ -36,7 +36,7 @@ import jdk.xml.internal.JdkXmlFeatures;
      *
      * @author  Ramesh Mandava
      *
    - * @LastModified: May 2021
    + * @LastModified: Nov 2021
      */
     public  class XPathFactoryImpl extends XPathFactory {
     
    @@ -310,4 +310,38 @@ public  class XPathFactoryImpl extends XPathFactory {
     
                     xPathVariableResolver = resolver;
             }
    +
    +    @Override
    +    public void setProperty(String name, String value) {
    +        // property name cannot be null
    +        if (name == null) {
    +            String fmsg = XSLMessages.createXPATHMessage(
    +                    XPATHErrorResources.ER_PROPERTY_NAME_NULL,
    +                    new Object[] {CLASS_NAME,  value} );
    +            throw new NullPointerException(fmsg);
    +         }
    +
    +        // property name not recognized
    +        String fmsg = XSLMessages.createXPATHMessage(
    +                XPATHErrorResources.ER_PROPERTY_UNKNOWN,
    +                new Object[] {name, CLASS_NAME, value} );
    +        throw new IllegalArgumentException(fmsg);
    +    }
    +
    +    @Override
    +    public String getProperty(String name) {
    +        // property name cannot be null
    +        if (name == null) {
    +            String fmsg = XSLMessages.createXPATHMessage(
    +                    XPATHErrorResources.ER_GETTING_NULL_PROPERTY,
    +                    new Object[] {CLASS_NAME} );
    +            throw new NullPointerException(fmsg);
    +        }
    +
    +        // unknown property
    +        String fmsg = XSLMessages.createXPATHMessage(
    +                XPATHErrorResources.ER_GETTING_UNKNOWN_PROPERTY,
    +                new Object[] {name, CLASS_NAME} );
    +        throw new IllegalArgumentException(fmsg);
    +    }
     }
    diff --git a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources.java b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources.java
    index 54e4fe7b64661c70b6fb9c55fb0a1c0511f16abc..2e5f86ee30e8b5fa7d53cfb143d83152ecb46736 100644
    --- a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources.java
    +++ b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
      */
     /*
      * Licensed to the Apache Software Foundation (ASF) under one or more
    @@ -31,7 +31,7 @@ import java.util.ListResourceBundle;
       * Also you need to  update the count of messages(MAX_CODE)or
      * the count of warnings(MAX_WARNING) [ Information purpose only]
      * @xsl.usage advanced
    - * @LastModified: May 2019
    + * @LastModified: Nov 2021
      */
     public class XPATHErrorResources extends ListResourceBundle
     {
    @@ -322,6 +322,10 @@ public static final String ER_IGNORABLE_WHITESPACE_NOT_HANDLED =
       public static final String ER_SECUREPROCESSING_FEATURE = "ER_SECUREPROCESSING_FEATURE";
       public static final String ER_NULL_XPATH_FUNCTION_RESOLVER = "ER_NULL_XPATH_FUNCTION_RESOLVER";
       public static final String ER_NULL_XPATH_VARIABLE_RESOLVER = "ER_NULL_XPATH_VARIABLE_RESOLVER";
    +  public static final String ER_PROPERTY_NAME_NULL = "ER_PROPERTY_NAME_NULL";
    +  public static final String ER_PROPERTY_UNKNOWN = "ER_PROPERTY_UNKNOWN";
    +  public static final String ER_GETTING_NULL_PROPERTY = "ER_GETTING_NULL_PROPERTY";
    +  public static final String ER_GETTING_UNKNOWN_PROPERTY = "ER_GETTING_UNKNOWN_PROPERTY";
       //END: Keys needed for exception messages of  JAXP 1.3 XPath API implementation
     
       public static final String WG_LOCALE_NAME_NOT_HANDLED =
    @@ -836,6 +840,26 @@ public static final String ER_IGNORABLE_WHITESPACE_NOT_HANDLED =
       { ER_NULL_XPATH_VARIABLE_RESOLVER,
            "Attempting to set a null XPathVariableResolver:{0}#setXPathVariableResolver(null)"},
     
    +  /** Field ER_PROPERTY_NAME_NULL                       */
    +
    +  { ER_PROPERTY_NAME_NULL,
    +       "Trying to set a property with a null name: {0}#setProperty( null, {1})"},
    +
    +  /** Field ER_PROPERTY_UNKNOWN                       */
    +
    +  { ER_PROPERTY_UNKNOWN,
    +       "Trying to set the unknown property \"{0}\":{1}#setProperty({0},{2})"},
    +
    +  /** Field ER_GETTING_NULL_PROPERTY                       */
    +
    +  { ER_GETTING_NULL_PROPERTY,
    +       "Trying to get a property with a null name: {0}#getProperty(null)"},
    +
    +  /** Field ER_GETTING_NULL_PROPERTY                       */
    +
    +  { ER_GETTING_UNKNOWN_PROPERTY,
    +       "Trying to get the unknown property \"{0}\":{1}#getProperty({0})"},
    +
       //END:  Definitions of error keys used  in exception messages of  JAXP 1.3 XPath API implementation
     
       // Warnings...
    diff --git a/src/java.xml/share/classes/javax/xml/xpath/XPathFactory.java b/src/java.xml/share/classes/javax/xml/xpath/XPathFactory.java
    index 3e6c7d1d554d1855933ce905957a2a270272dcc7..90004e3169184739185765a3d2c9dbc6a15c70eb 100644
    --- a/src/java.xml/share/classes/javax/xml/xpath/XPathFactory.java
    +++ b/src/java.xml/share/classes/javax/xml/xpath/XPathFactory.java
    @@ -275,8 +275,9 @@ public abstract class XPathFactory {
         public abstract boolean isObjectModelSupported(String objectModel);
     
         /**
    -     * 

    Set a feature for this {@code XPathFactory} and - * XPaths created by this factory.

    + * Sets a feature for this {@code XPathFactory}. The feature applies to + * {@code XPath} objects that the {@code XPathFactory} creates. It has no + * impact on {@code XPath} objects that are already created. * *

    * Feature names are fully qualified {@link java.net.URI}s. @@ -369,4 +370,60 @@ public abstract class XPathFactory { * @return New instance of an XPath. */ public abstract XPath newXPath(); + + /** + * Sets a property for this {@code XPathFactory}. The property applies to + * {@code XPath} objects that the {@code XPathFactory} creates. It has no + * impact on {@code XPath} objects that are already created. + *

    + * A property can either be defined in this {@code XPathFactory}, or by the + * underlying implementation. + * + * @implSpec + * The default implementation throws + * {@link java.lang.UnsupportedOperationException}. + * + * @param name the property name + * @param value the value for the property + * + * @throws IllegalArgumentException if the property name is not recognized, + * or the value can not be assigned + * @throws UnsupportedOperationException if the implementation does not + * support the method + * @throws NullPointerException if the {@code name} is {@code null} + * + * @since 18 + */ + public void setProperty(String name, String value) { + + if (name == null) { + throw new NullPointerException("the name parameter is null"); + } + throw new UnsupportedOperationException("not implemented"); + } + + /** + * Returns the value of the specified property. + * + * @implSpec + * The default implementation throws + * {@link java.lang.UnsupportedOperationException}. + * + * @param name the property name + * @return the value of the property. + * + * @throws IllegalArgumentException if the property name is not recognized + * @throws UnsupportedOperationException if the implementation does not + * support the method + * @throws NullPointerException if the {@code name} is {@code null} + * + * @since 18 + */ + public String getProperty(String name) { + + if (name == null) { + throw new NullPointerException("the name parameter is null"); + } + throw new UnsupportedOperationException("not implemented"); + } } diff --git a/src/jdk.compiler/share/classes/com/sun/source/doctree/DocTree.java b/src/jdk.compiler/share/classes/com/sun/source/doctree/DocTree.java index b0375d200c3f88c00529698a1b8676aa869a2d95..4dea3d09bf46de415cb38df714c6d7714766f044 100644 --- a/src/jdk.compiler/share/classes/com/sun/source/doctree/DocTree.java +++ b/src/jdk.compiler/share/classes/com/sun/source/doctree/DocTree.java @@ -80,6 +80,8 @@ public interface DocTree { /** * Used for instances of {@link DocTypeTree} * representing an HTML DocType declaration. + * + * @since 10 */ DOC_TYPE, @@ -122,6 +124,8 @@ public interface DocTree { /** * Used for instances of {@link IndexTree} * representing an {@code @index} tag. + * + * @since 9 */ INDEX("index"), @@ -158,6 +162,8 @@ public interface DocTree { /** * Used for instances of {@link ProvidesTree} * representing an {@code @provides} tag. + * + * @since 9 */ PROVIDES("provides"), @@ -207,6 +213,8 @@ public interface DocTree { /** * Used for instances of {@link SnippetTree} * representing an {@code @snippet} tag. + * + * @since 18 */ SNIPPET("snippet"), @@ -219,12 +227,16 @@ public interface DocTree { /** * Used for instances of {@link SystemPropertyTree} * representing an {@code @systemProperty} tag. + * + * @since 12 */ SYSTEM_PROPERTY("systemProperty"), /** * Used for instances of {@link SummaryTree} * representing an {@code @summary} tag. + * + * @since 10 */ SUMMARY("summary"), @@ -255,6 +267,8 @@ public interface DocTree { /** * Used for instances of {@link UsesTree} * representing an {@code @uses} tag. + * + * @since 9 */ USES("uses"), diff --git a/src/jdk.compiler/share/classes/com/sun/source/util/Trees.java b/src/jdk.compiler/share/classes/com/sun/source/util/Trees.java index b33117bc541af0f01beefbcec5104f8546ce3948..e4228d37bd5a7772eb393aeacb480365a7af4b08 100644 --- a/src/jdk.compiler/share/classes/com/sun/source/util/Trees.java +++ b/src/jdk.compiler/share/classes/com/sun/source/util/Trees.java @@ -72,7 +72,7 @@ public abstract class Trees { } /** - * Returns a {code Trees} object for a given {@code ProcessingEnvironment}. + * Returns a {@code Trees} object for a given {@code ProcessingEnvironment}. * @param env the processing environment for which to get the {@code Trees} object * @throws IllegalArgumentException if the env does not support the Tree API. * @return the {@code Trees} object diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java index a26345ead881e63390ac63b5919bfc2542ba4d46..643d5bbee1f22cd52bb29c8e7c3c264f8a318ed7 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java @@ -305,6 +305,17 @@ public class ClientCodeWrapper { } } + @Override @DefinedBy(Api.COMPILER) + public JavaFileObject getJavaFileForOutputForOriginatingFiles(Location location, String className, Kind kind, FileObject... originatingFiles) throws IOException { + try { + return wrap(clientJavaFileManager.getJavaFileForOutputForOriginatingFiles(location, className, kind, originatingFiles)); + } catch (ClientCodeException e) { + throw e; + } catch (RuntimeException | Error e) { + throw new ClientCodeException(e); + } + } + @Override @DefinedBy(Api.COMPILER) public FileObject getFileForOutput(Location location, String packageName, String relativeName, FileObject sibling) throws IOException { try { @@ -316,6 +327,17 @@ public class ClientCodeWrapper { } } + @Override @DefinedBy(Api.COMPILER) + public FileObject getFileForOutputForOriginatingFiles(Location location, String packageName, String relativeName, FileObject... originatingFiles) throws IOException { + try { + return wrap(clientJavaFileManager.getFileForOutputForOriginatingFiles(location, packageName, relativeName, originatingFiles)); + } catch (ClientCodeException e) { + throw e; + } catch (RuntimeException | Error e) { + throw new ClientCodeException(e); + } + } + @Override @DefinedBy(Api.COMPILER) public boolean contains(Location location, FileObject file) throws IOException { try { diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java index 617d891fb7ce496e264ece81e5c36c835796e664..a6dddba278c468cc634df5970cb441dbba5b7d20 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java @@ -117,7 +117,12 @@ public enum Source { /** * 18, tbd */ - JDK18("18"); + JDK18("18"), + + /** + * 19, tbd + */ + JDK19("19"); private static final Context.Key sourceKey = new Context.Key<>(); @@ -169,6 +174,7 @@ public enum Source { public Target requiredTarget() { return switch(this) { + case JDK19 -> Target.JDK1_19; case JDK18 -> Target.JDK1_18; case JDK17 -> Target.JDK1_17; case JDK16 -> Target.JDK1_16; @@ -313,6 +319,7 @@ public enum Source { case JDK16 -> RELEASE_16; case JDK17 -> RELEASE_17; case JDK18 -> RELEASE_18; + case JDK19 -> RELEASE_19; default -> null; }; } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java index a078fb6e22cd4287538e8632176dcd4d175adade..f72a943a2a2307dc3ae6df1a07f8bb371155ac33 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java @@ -2278,6 +2278,11 @@ public abstract class Symbol extends AnnoConstruct implements PoolConstant, Elem this.staticArgs = staticArgs; } + @Override + public Name name() { + return name; + } + @Override public boolean isDynamic() { return true; @@ -2316,6 +2321,11 @@ public abstract class Symbol extends AnnoConstruct implements PoolConstant, Elem this.staticArgs = staticArgs; } + @Override + public Name name() { + return name; + } + @Override public boolean isDynamic() { return true; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java index 2561ae38f291a4bf5ebe9e9de16f0d9e64247154..fdf91e6f423aead8eec0aa8cbaefde874ccf8680 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java @@ -345,7 +345,7 @@ public class Annotate { Assert.checkNonNull(c, "Failed to create annotation"); - if (a.type.tsym.isAnnotationType()) { + if (a.type.isErroneous() || a.type.tsym.isAnnotationType()) { if (annotated.containsKey(a.type.tsym)) { if (!allowRepeatedAnnos) { log.error(DiagnosticFlag.SOURCE_LEVEL, a.pos(), Feature.REPEATED_ANNOTATIONS.error(sourceName)); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java index 32975a193ec2f144a31b2bf28ee0c96ffbfe71d4..7bd813cddb73abb43d14c71051acfdaca111cb56 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java @@ -1680,7 +1680,8 @@ public class Attr extends JCTree.Visitor { // Attribute all cases and // check that there are no duplicate case labels or default clauses. Set labels = new HashSet<>(); // The set of case labels. - List coveredTypes = List.nil(); + List coveredTypesForPatterns = List.nil(); + List coveredTypesForConstants = List.nil(); boolean hasDefault = false; // Is there a default label? boolean hasTotalPattern = false; // Is there a total pattern? boolean hasNullPattern = false; // Is there a null pattern? @@ -1718,7 +1719,7 @@ public class Attr extends JCTree.Visitor { } else if (!labels.add(sym)) { log.error(pat.pos(), Errors.DuplicateCaseLabel); } else { - checkCaseLabelDominated(pat.pos(), coveredTypes, sym.type); + checkCaseLabelDominated(pat.pos(), coveredTypesForConstants, sym.type); } } else if (errorEnumSwitch) { //error recovery: the selector is erroneous, and all the case labels @@ -1751,7 +1752,7 @@ public class Attr extends JCTree.Visitor { } else if (!labels.add(pattype.constValue())) { log.error(c.pos(), Errors.DuplicateCaseLabel); } else { - checkCaseLabelDominated(pat.pos(), coveredTypes, types.boxedTypeOrType(pattype)); + checkCaseLabelDominated(pat.pos(), coveredTypesForConstants, types.boxedTypeOrType(pattype)); } } } @@ -1784,9 +1785,12 @@ public class Attr extends JCTree.Visitor { } hasTotalPattern = true; } - checkCaseLabelDominated(pat.pos(), coveredTypes, patternType); - if (primary.unconditional() && !patternType.isErroneous()) { - coveredTypes = coveredTypes.prepend(patternType); + checkCaseLabelDominated(pat.pos(), coveredTypesForPatterns, patternType); + if (!patternType.isErroneous()) { + coveredTypesForConstants = coveredTypesForConstants.prepend(patternType); + if (primary.unconditional()) { + coveredTypesForPatterns = coveredTypesForPatterns.prepend(patternType); + } } } currentBindings = matchBindingsComputer.switchCase(pat, currentBindings, matchBindings); @@ -3950,14 +3954,14 @@ public class Attr extends JCTree.Visitor { : chk.checkNonVoid(tree.arg.pos(), attribExpr(tree.arg, env)); // Find operator. - Symbol operator = tree.operator = operators.resolveUnary(tree, tree.getTag(), argtype); + OperatorSymbol operator = tree.operator = operators.resolveUnary(tree, tree.getTag(), argtype); Type owntype = types.createErrorType(tree.type); if (operator != operators.noOpSymbol && !argtype.isErroneous()) { owntype = (tree.getTag().isIncOrDecUnaryOp()) ? tree.arg.type : operator.type.getReturnType(); - int opc = ((OperatorSymbol)operator).opcode; + int opc = operator.opcode; // If the argument is constant, fold it. if (argtype.constValue() != null) { @@ -4004,13 +4008,13 @@ public class Attr extends JCTree.Visitor { matchBindings = matchBindingsComputer.binary(tree, lhsBindings, matchBindings); // Find operator. - Symbol operator = tree.operator = operators.resolveBinary(tree, tree.getTag(), left, right); + OperatorSymbol operator = tree.operator = operators.resolveBinary(tree, tree.getTag(), left, right); Type owntype = types.createErrorType(tree.type); if (operator != operators.noOpSymbol && !left.isErroneous() && !right.isErroneous()) { owntype = operator.type.getReturnType(); - int opc = ((OperatorSymbol)operator).opcode; + int opc = operator.opcode; // If both arguments are constants, fold them. if (left.constValue() != null && right.constValue() != null) { Type ctype = cfolder.fold2(opc, left, right); @@ -4344,7 +4348,8 @@ public class Attr extends JCTree.Visitor { if (env.info.isSelfCall && ((sym.name == names._this && site.tsym == env.enclClass.sym) || - sym.name == names._super && env.info.constructorArgs)) { + sym.name == names._super && env.info.constructorArgs && + (sitesym.isInterface() || site.tsym == env.enclClass.sym))) { chk.earlyRefError(tree.pos(), sym); } } else { @@ -5494,11 +5499,11 @@ public class Attr extends JCTree.Visitor { c.owner.kind != PCK && ((c.flags() & STATIC) == 0 || c.name == names.empty) && (TreeInfo.flags(l.head) & (STATIC | INTERFACE)) != 0) { - Symbol sym = null; + VarSymbol sym = null; if (l.head.hasTag(VARDEF)) sym = ((JCVariableDecl) l.head).sym; if (sym == null || sym.kind != VAR || - ((VarSymbol) sym).getConstValue() == null) + sym.getConstValue() == null) log.error(l.head.pos(), Errors.IclsCantHaveStaticDecl(c)); } } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java index f4ba0f9bb1735be780d5a2dc688c37afc440e1e4..1346d141bb76740e6d3b0be4712b061cfedf9ce5 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java @@ -207,7 +207,6 @@ public class Flow { private final JCDiagnostic.Factory diags; private Env attrEnv; private Lint lint; - private final DeferredCompletionFailureHandler dcfh; private final boolean allowEffectivelyFinalInInnerClasses; public static Flow instance(Context context) { @@ -332,7 +331,6 @@ public class Flow { lint = Lint.instance(context); rs = Resolve.instance(context); diags = JCDiagnostic.Factory.instance(context); - dcfh = DeferredCompletionFailureHandler.instance(context); Source source = Source.instance(context); allowEffectivelyFinalInInnerClasses = Feature.EFFECTIVELY_FINAL_IN_INNER_CLASSES.allowedInSource(source); } @@ -693,7 +691,7 @@ public class Flow { } if (!tree.hasTotalPattern && exhaustiveSwitch && !TreeInfo.isErrorEnumSwitch(tree.selector, tree.cases) && - (constants == null || !isExhaustive(tree.selector.type, constants))) { + (constants == null || !isExhaustive(tree.selector.pos(), tree.selector.type, constants))) { log.error(tree, Errors.NotExhaustiveStatement); } if (!tree.hasTotalPattern) { @@ -728,7 +726,7 @@ public class Flow { } } if (!tree.hasTotalPattern && !TreeInfo.isErrorEnumSwitch(tree.selector, tree.cases) && - !isExhaustive(tree.selector.type, constants)) { + !isExhaustive(tree.selector.pos(), tree.selector.type, constants)) { log.error(tree, Errors.NotExhaustive); } alive = prevAlive; @@ -751,7 +749,7 @@ public class Flow { } } - private void transitiveCovers(Set covered) { + private void transitiveCovers(DiagnosticPosition pos, Type seltype, Set covered) { List todo = List.from(covered); while (todo.nonEmpty()) { Symbol sym = todo.head; @@ -773,7 +771,7 @@ public class Flow { case TYP -> { for (Type sup : types.directSupertypes(sym.type)) { if (sup.tsym.kind == TYP) { - if (isTransitivelyCovered(sup.tsym, covered) && + if (isTransitivelyCovered(pos, seltype, sup.tsym, covered) && covered.add(sup.tsym)) { todo = todo.prepend(sup.tsym); } @@ -784,39 +782,41 @@ public class Flow { } } - private boolean isTransitivelyCovered(Symbol sealed, Set covered) { - DeferredCompletionFailureHandler.Handler prevHandler = - dcfh.setHandler(dcfh.speculativeCodeHandler); + private boolean isTransitivelyCovered(DiagnosticPosition pos, Type seltype, + Symbol sealed, Set covered) { try { if (covered.stream().anyMatch(c -> sealed.isSubClass(c, types))) return true; if (sealed.kind == TYP && sealed.isAbstract() && sealed.isSealed()) { return ((ClassSymbol) sealed).permitted .stream() - .allMatch(s -> isTransitivelyCovered(s, covered)); + .filter(s -> { + return types.isCastable(seltype, s.type/*, types.noWarnings*/); + }) + .allMatch(s -> isTransitivelyCovered(pos, seltype, s, covered)); } return false; } catch (CompletionFailure cf) { - //safe to ignore, the symbol will be un-completed when the speculative handler is removed. - return false; - } finally { - dcfh.setHandler(prevHandler); + chk.completionError(pos, cf); + return true; } } - private boolean isExhaustive(Type seltype, Set covered) { - transitiveCovers(covered); + private boolean isExhaustive(DiagnosticPosition pos, Type seltype, Set covered) { + transitiveCovers(pos, seltype, covered); return switch (seltype.getTag()) { case CLASS -> { if (seltype.isCompound()) { if (seltype.isIntersection()) { - yield ((Type.IntersectionClassType) seltype).getComponents().stream().anyMatch(t -> isExhaustive(t, covered)); + yield ((Type.IntersectionClassType) seltype).getComponents() + .stream() + .anyMatch(t -> isExhaustive(pos, t, covered)); } yield false; } yield covered.contains(seltype.tsym); } - case TYPEVAR -> isExhaustive(((TypeVar) seltype).getUpperBound(), covered); + case TYPEVAR -> isExhaustive(pos, ((TypeVar) seltype).getUpperBound(), covered); default -> false; }; } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java index c48ac804ac850c5ec34b53eaa4a19454cd25763e..0638da66a8969191b572a18375af6bee01790718 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java @@ -165,9 +165,14 @@ public class LambdaToMethod extends TreeTranslator { dumpLambdaToMethodStats = options.isSet("debug.dumpLambdaToMethodStats"); attr = Attr.instance(context); forceSerializable = options.isSet("forceSerializable"); - debugLinesOrVars = options.isSet(Option.G) - || options.isSet(Option.G_CUSTOM, "lines") - || options.isSet(Option.G_CUSTOM, "vars"); + boolean lineDebugInfo = + options.isUnset(Option.G_CUSTOM) || + options.isSet(Option.G_CUSTOM, "lines"); + boolean varDebugInfo = + options.isUnset(Option.G_CUSTOM) + ? options.isSet(Option.G) + : options.isSet(Option.G_CUSTOM, "vars"); + debugLinesOrVars = lineDebugInfo || varDebugInfo; verboseDeduplication = options.isSet("debug.dumpLambdaToMethodDeduplication"); deduplicateLambdas = options.getBoolean("deduplicateLambdas", true); nestmateLambdas = Target.instance(context).runtimeUseNestAccess(); @@ -424,14 +429,14 @@ public class LambdaToMethod extends TreeTranslator { //add captured locals for (Symbol fv : localContext.getSymbolMap(CAPTURED_VAR).keySet()) { if (fv != localContext.self) { - JCTree captured_local = make.Ident(fv).setType(fv.type); - syntheticInits.append((JCExpression) captured_local); + JCExpression captured_local = make.Ident(fv).setType(fv.type); + syntheticInits.append(captured_local); } } // add captured outer this instances (used only when `this' capture itself is illegal) for (Symbol fv : localContext.getSymbolMap(CAPTURED_OUTER_THIS).keySet()) { - JCTree captured_local = make.QualThis(fv.type); - syntheticInits.append((JCExpression) captured_local); + JCExpression captured_local = make.QualThis(fv.type); + syntheticInits.append(captured_local); } //then, determine the arguments to the indy call @@ -1184,13 +1189,13 @@ public class LambdaToMethod extends TreeTranslator { syms.stringType, syms.methodTypeType).appendList(staticArgs.map(types::constantType)); - Symbol bsm = rs.resolveInternalMethod(pos, attrEnv, site, + MethodSymbol bsm = rs.resolveInternalMethod(pos, attrEnv, site, bsmName, bsm_staticArgs, List.nil()); DynamicMethodSymbol dynSym = new DynamicMethodSymbol(methName, syms.noSymbol, - ((MethodSymbol)bsm).asHandle(), + bsm.asHandle(), indyType, staticArgs.toArray(new LoadableConstant[staticArgs.length()])); JCFieldAccess qualifier = make.Select(make.QualIdent(site.tsym), bsmName); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java index 475e50d22bc60087c669efb01e454fa41835daa7..7b2ccb7f426b5ca098b4db158b045d1474a0244f 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java @@ -2279,30 +2279,13 @@ public class Lower extends TreeTranslator { // Enclosing instance field is used return true; } - if (rs.isSerializable(sym.type) && !hasSerialVersionUID(sym)) { - // Class is serializable and does not have a stable serialVersionUID + if (rs.isSerializable(sym.type)) { + // Class is serializable return true; } return false; } - private boolean hasSerialVersionUID(ClassSymbol sym) { - VarSymbol svuid = (VarSymbol) sym.members().findFirst(names.serialVersionUID, f -> f.kind == VAR); - if (svuid == null) { - return false; - } - if ((svuid.flags() & (STATIC | FINAL)) != (STATIC | FINAL)) { - return false; - } - if (!svuid.type.hasTag(LONG)) { - return false; - } - if (svuid.getConstValue() == null) { - return false; - } - return true; - } - List generateMandatedAccessors(JCClassDecl tree) { List fields = TreeInfo.recordFields(tree); return tree.sym.getRecordComponents().stream() @@ -2369,7 +2352,7 @@ public class Lower extends TreeTranslator { enumDefs.append(make.VarDef(valuesVar, make.App(make.QualIdent(valuesMethod)))); tree.sym.members().enter(valuesVar); - Symbol valuesSym = lookupMethod(tree.pos(), names.values, + MethodSymbol valuesSym = lookupMethod(tree.pos(), names.values, tree.type, List.nil()); List valuesBody; if (useClone()) { @@ -2420,7 +2403,7 @@ public class Lower extends TreeTranslator { } JCMethodDecl valuesDef = - make.MethodDef((MethodSymbol)valuesSym, make.Block(0, valuesBody)); + make.MethodDef(valuesSym, make.Block(0, valuesBody)); enumDefs.append(valuesDef); @@ -2635,7 +2618,7 @@ public class Lower extends TreeTranslator { Name bootstrapName, Name argName, boolean isStatic) { - Symbol bsm = rs.resolveInternalMethod(tree.pos(), attrEnv, site, + MethodSymbol bsm = rs.resolveInternalMethod(tree.pos(), attrEnv, site, bootstrapName, staticArgTypes, List.nil()); MethodType indyType = msym.type.asMethodType(); @@ -2647,7 +2630,7 @@ public class Lower extends TreeTranslator { ); DynamicMethodSymbol dynSym = new DynamicMethodSymbol(argName, syms.noSymbol, - ((MethodSymbol)bsm).asHandle(), + bsm.asHandle(), indyType, staticArgValues); JCFieldAccess qualifier = make.Select(make.QualIdent(site.tsym), argName); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java index 1ba0ace43b4099f79b81288ad49e333789e7526a..7c912dcc877cd1f069c625d4211046bcef00748b 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java @@ -1301,7 +1301,7 @@ public class Resolve { @Override void skip(JCTree tree) { - result &= false; + result = false; } @Override @@ -1313,9 +1313,9 @@ public class Resolve { @Override public void visitReference(JCMemberReference tree) { if (sRet.hasTag(VOID)) { - result &= true; + // do nothing } else if (tRet.hasTag(VOID)) { - result &= false; + result = false; } else if (tRet.isPrimitive() != sRet.isPrimitive()) { boolean retValIsPrimitive = tree.refPolyKind == PolyKind.STANDALONE && @@ -1335,9 +1335,9 @@ public class Resolve { @Override public void visitLambda(JCLambda tree) { if (sRet.hasTag(VOID)) { - result &= true; + // do nothing } else if (tRet.hasTag(VOID)) { - result &= false; + result = false; } else { List lambdaResults = lambdaResults(tree); if (!lambdaResults.isEmpty() && unrelatedFunctionalInterfaces(tRet, sRet)) { @@ -2942,9 +2942,6 @@ public class Resolve { sym.kind != WRONG_MTHS) { sym = super.access(env, pos, location, sym); } else { - final JCDiagnostic details = sym.kind == WRONG_MTH ? - ((InapplicableSymbolError)sym.baseSymbol()).errCandidate().snd : - null; sym = new DiamondError(sym, currentResolutionContext); sym = accessMethod(sym, pos, site, names.init, true, argtypes, typeargtypes); env.info.pendingResolutionPhase = currentResolutionContext.step; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java index fda59d6ddaadfe5c6ffd0e505e9b339e10e1ed70..56fdc73e02e6da351dc1019a00b2f4c2cce06328 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java @@ -347,8 +347,9 @@ public class TransPatterns extends TreeTranslator { } } selector = translate(selector); - statements.append(make.at(tree.pos).VarDef(temp, !hasNullCase ? attr.makeNullCheck(selector) - : selector)); + boolean needsNullCheck = !hasNullCase && !seltype.isPrimitive(); + statements.append(make.at(tree.pos).VarDef(temp, needsNullCheck ? attr.makeNullCheck(selector) + : selector)); VarSymbol index = new VarSymbol(Flags.SYNTHETIC, names.fromString(tree.pos + target.syntheticNameChar() + "index"), syms.intType, @@ -371,7 +372,7 @@ public class TransPatterns extends TreeTranslator { boolean enumSelector = seltype.tsym.isEnum(); Name bootstrapName = enumSelector ? names.enumSwitch : names.typeSwitch; - Symbol bsm = rs.resolveInternalMethod(tree.pos(), env, syms.switchBootstrapsType, + MethodSymbol bsm = rs.resolveInternalMethod(tree.pos(), env, syms.switchBootstrapsType, bootstrapName, staticArgTypes, List.nil()); MethodType indyType = new MethodType( @@ -382,7 +383,7 @@ public class TransPatterns extends TreeTranslator { ); DynamicMethodSymbol dynSym = new DynamicMethodSymbol(bootstrapName, syms.noSymbol, - ((MethodSymbol)bsm).asHandle(), + bsm.asHandle(), indyType, staticArgValues); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/file/PathFileObject.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/file/PathFileObject.java index 5831f3c22bd2a52a7458402f421d9961ed5fdcb9..adc4f813c602f1188df4e9da66fc7516daab829a 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/file/PathFileObject.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/file/PathFileObject.java @@ -178,13 +178,6 @@ public abstract class PathFileObject implements JavaFileObject { return toBinaryName(root.relativize(path)); } - @Override @DefinedBy(Api.COMPILER) - public URI toUri() { - // Work around bug JDK-8134451: - // path.toUri() returns double-encoded URIs, that cannot be opened by URLConnection - return createJarUri(userJarPath, path.toString()); - } - @Override public String toString() { return "JarFileObject[" + userJarPath + ":" + path + "]"; @@ -197,17 +190,6 @@ public abstract class PathFileObject implements JavaFileObject { userJarPath ); } - - private static URI createJarUri(Path jarFile, String entryName) { - URI jarURI = jarFile.toUri().normalize(); - String separator = entryName.startsWith("/") ? "!" : "!/"; - try { - // The jar URI convention appears to be not to re-encode the jarURI - return new URI("jar:" + jarURI + separator + entryName); - } catch (URISyntaxException e) { - throw new CannotCreateUriError(jarURI + separator + entryName, e); - } - } } /** diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java index c9077db01fc694628302f8a288a44441163ee62f..9499827c3206c030a8429fb4357c402f9effbe21 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java @@ -119,7 +119,8 @@ public class ClassFile { V59(59, 0), // JDK 15 V60(60, 0), // JDK 16 V61(61, 0), // JDK 17 - V62(62, 0); // JDK 18 + V62(62, 0), // JDK 18 + V63(63, 0); // JDK 19 Version(int major, int minor) { this.major = major; this.minor = minor; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolConstant.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolConstant.java index 77fbec7a569f8e6f6acece414f4c959b311ae9c4..2077efc188826cfeb0b201e610be1046cd1dbe84 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolConstant.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolConstant.java @@ -134,6 +134,11 @@ public interface PoolConstant { */ PoolConstant dynamicType(); + /** + * The dynamic constant's name. + */ + Name name(); + /** * The dynamic constant's static argument list. */ @@ -150,7 +155,7 @@ public interface PoolConstant { @Override default Object poolKey(Types types) { - return new Pair<>(bsmKey(types), dynamicType().poolKey(types)); + return new PoolKey(name(), bsmKey(types), dynamicType().poolKey(types)); } /** @@ -192,6 +197,8 @@ public interface PoolConstant { && Objects.equals(staticArgKeys, key.staticArgKeys); } } + + record PoolKey(Name name, BsmKey bsmKey, Object dynamicType) {} } /** diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java index 2c17b6880e889cad993842e59a2131c6294f5c00..0dddb3e5868e4f776a9b17e165c3ba5483476420 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java @@ -371,7 +371,7 @@ public abstract class StringConcat { syms.stringType, syms.methodTypeType); - Symbol bsm = rs.resolveInternalMethod(pos, + MethodSymbol bsm = rs.resolveInternalMethod(pos, gen.getAttrEnv(), syms.stringConcatFactory, names.makeConcat, @@ -380,7 +380,7 @@ public abstract class StringConcat { Symbol.DynamicMethodSymbol dynSym = new Symbol.DynamicMethodSymbol(names.makeConcat, syms.noSymbol, - ((MethodSymbol)bsm).asHandle(), + bsm.asHandle(), indyType, List.nil().toArray(new LoadableConstant[0])); @@ -487,7 +487,7 @@ public abstract class StringConcat { .append(syms.stringType) .appendList(constTypes); - Symbol bsm = rs.resolveInternalMethod(pos, + MethodSymbol bsm = rs.resolveInternalMethod(pos, gen.getAttrEnv(), syms.stringConcatFactory, names.makeConcatWithConstants, @@ -496,7 +496,7 @@ public abstract class StringConcat { Symbol.DynamicMethodSymbol dynSym = new Symbol.DynamicMethodSymbol(names.makeConcatWithConstants, syms.noSymbol, - ((MethodSymbol)bsm).asHandle(), + bsm.asHandle(), indyType, List.of(LoadableConstant.String(recipe)) .appendList(constants).toArray(new LoadableConstant[constants.size()])); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java index fba0c2584c9abeb0cf158a37aaf1ad78867ee7c7..49a2135b9950733e8f18333847341787002db6ea 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java @@ -88,7 +88,10 @@ public enum Target { JDK1_17("17", 61, 0), /** JDK 18. */ - JDK1_18("18", 62, 0); + JDK1_18("18", 62, 0), + + /** JDK 19. */ + JDK1_19("19", 63, 0); private static final Context.Key targetKey = new Context.Key<>(); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/launcher/Main.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/launcher/Main.java index 428b3a4a51ec032f522e1eabeb50debf7f18f052..76de3372d038ca5ed94ea380ab5bcc69c2064f1d 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/launcher/Main.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/launcher/Main.java @@ -354,6 +354,7 @@ public class Main { javacOpts.add("-Xdiags:verbose"); javacOpts.add("-Xlint:deprecation"); javacOpts.add("-Xlint:unchecked"); + javacOpts.add("-Xlint:-options"); return javacOpts; } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/DelegatingJavaFileManager.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/DelegatingJavaFileManager.java index 6e242df30600deaf1ee8376c79fcc1f0049122ee..70b4d4da8c8bcbf68d4b952e66ae6eb4a99dec12 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/DelegatingJavaFileManager.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/DelegatingJavaFileManager.java @@ -115,6 +115,12 @@ public class DelegatingJavaFileManager implements JavaFileManager { return delegate(location).getJavaFileForOutput(location, className, kind, sibling); } + @Override + public JavaFileObject getJavaFileForOutputForOriginatingFiles(Location location, String className, Kind kind, + FileObject... originatingFiles) throws IOException { + return delegate(location).getJavaFileForOutputForOriginatingFiles(location, className, kind, originatingFiles); + } + @Override public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException { @@ -127,6 +133,12 @@ public class DelegatingJavaFileManager implements JavaFileManager { return delegate(location).getFileForOutput(location, packageName, relativeName, sibling); } + @Override + public FileObject getFileForOutputForOriginatingFiles(Location location, String packageName, String relativeName, + FileObject... originatingFiles) throws IOException { + return delegate(location).getFileForOutputForOriginatingFiles(location, packageName, relativeName, originatingFiles); + } + @Override public void flush() throws IOException { releaseFM.flush(); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java index 033539c2c16b10e2519f1341ebbc6f0bf955bb9b..d5f1efa566b4ab37ebec232579c0a857ab6cbac7 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java @@ -510,6 +510,11 @@ public enum Option { public void process(OptionHelper helper, String option) { throw new AssertionError("the -J flag should be caught by the launcher."); } + + @Override + public void process(OptionHelper helper, String option, String arg) throws InvalidValueException { + throw helper.newInvalidValueException(Errors.InvalidFlag(option + arg)); + } }, MOREINFO("-moreinfo", null, HIDDEN, BASIC) { diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java index a1ae6c543a946ea8d376fa01cb88c228bc3222f9..ed909c8b80f72cc68bf59cc5432203e00ad3310b 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java @@ -757,6 +757,12 @@ public class JavacElements implements Elements { */ private Pair getTreeAndTopLevel(Element e) { Symbol sym = cast(Symbol.class, e); + if (sym.kind == PCK) { + TypeSymbol pkgInfo = ((PackageSymbol) sym).package_info; + if (pkgInfo != null) { + pkgInfo.complete(); + } + } Env enterEnv = getEnterEnv(sym); if (enterEnv == null) return null; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacFiler.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacFiler.java index ebac3ceaa5ab866aa4a22e57632b97a13a9fd334..bef291869ab36da185f5877c9ec044a480333e4e 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacFiler.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacFiler.java @@ -36,6 +36,7 @@ import java.io.FilterWriter; import java.io.PrintWriter; import java.io.IOException; import java.util.*; +import java.util.stream.Stream; import static java.util.Collections.*; @@ -62,8 +63,10 @@ import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.DefinedBy.Api; import static com.sun.tools.javac.code.Lint.LintCategory.PROCESSING; +import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Symbol.PackageSymbol; import com.sun.tools.javac.main.Option; +import java.util.stream.Collectors; /** * The FilerImplementation class must maintain a number of @@ -432,14 +435,14 @@ public class JavacFiler implements Filer, Closeable { public JavaFileObject createSourceFile(CharSequence nameAndModule, Element... originatingElements) throws IOException { Pair moduleAndClass = checkOrInferModule(nameAndModule); - return createSourceOrClassFile(moduleAndClass.fst, true, moduleAndClass.snd); + return createSourceOrClassFile(moduleAndClass.fst, true, moduleAndClass.snd, originatingElements); } @Override @DefinedBy(Api.ANNOTATION_PROCESSING) public JavaFileObject createClassFile(CharSequence nameAndModule, Element... originatingElements) throws IOException { Pair moduleAndClass = checkOrInferModule(nameAndModule); - return createSourceOrClassFile(moduleAndClass.fst, false, moduleAndClass.snd); + return createSourceOrClassFile(moduleAndClass.fst, false, moduleAndClass.snd, originatingElements); } private Pair checkOrInferModule(CharSequence moduleAndPkg) throws FilerException { @@ -483,7 +486,7 @@ public class JavacFiler implements Filer, Closeable { return Pair.of(explicitModule, pkg); } - private JavaFileObject createSourceOrClassFile(ModuleSymbol mod, boolean isSourceFile, String name) throws IOException { + private JavaFileObject createSourceOrClassFile(ModuleSymbol mod, boolean isSourceFile, String name, Element... originatingElements) throws IOException { Assert.checkNonNull(mod); if (lint) { @@ -506,7 +509,7 @@ public class JavacFiler implements Filer, Closeable { JavaFileObject.Kind.CLASS); JavaFileObject fileObject = - fileManager.getJavaFileForOutput(loc, name, kind, null); + fileManager.getJavaFileForOutputForOriginatingFiles(loc, name, kind, originatingFiles(originatingElements)); checkFileReopening(fileObject, true); if (lastRound) @@ -521,6 +524,17 @@ public class JavacFiler implements Filer, Closeable { return new FilerOutputJavaFileObject(mod, name, fileObject); } + private JavaFileObject[] originatingFiles(Element[] originatingElements) { + if (originatingElements == null) { + return new JavaFileObject[0]; + } + JavaFileObject[] originatingFiles = Stream.of(originatingElements) + .map(elementUtils::getFileObjectOf) + .filter(fo -> fo != null) + .toArray(s -> new JavaFileObject[s]); + return originatingFiles; + } + @Override @DefinedBy(Api.ANNOTATION_PROCESSING) public FileObject createResource(JavaFileManager.Location location, CharSequence moduleAndPkg, @@ -538,8 +552,8 @@ public class JavacFiler implements Filer, Closeable { checkName(strPkg); FileObject fileObject = - fileManager.getFileForOutput(location, strPkg, - relativeName.toString(), null); + fileManager.getFileForOutputForOriginatingFiles(location, strPkg, + relativeName.toString(), originatingFiles(originatingElements)); checkFileReopening(fileObject, true); if (fileObject instanceof JavaFileObject javaFileObject) @@ -579,10 +593,9 @@ public class JavacFiler implements Filer, Closeable { // invocation. FileObject fileObject; if (location.isOutputLocation()) { - fileObject = fileManager.getFileForOutput(location, + fileObject = fileManager.getFileForOutputForOriginatingFiles(location, pkg, - relativeName.toString(), - null); + relativeName.toString()); } else { fileObject = fileManager.getFileForInput(location, pkg, diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/PrintingProcessor.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/PrintingProcessor.java index 5ea75340db284bfd9cc5a55547bc4fb20a319528..9838057f6a46e6e3eb98e2d26b3830835bab3243 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/PrintingProcessor.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/PrintingProcessor.java @@ -55,7 +55,7 @@ import com.sun.tools.javac.util.StringUtils; * deletion without notice. */ @SupportedAnnotationTypes("*") -@SupportedSourceVersion(SourceVersion.RELEASE_18) +@SupportedSourceVersion(SourceVersion.RELEASE_19) public class PrintingProcessor extends AbstractProcessor { PrintWriter writer; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/RawDiagnosticFormatter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/RawDiagnosticFormatter.java index 27312e021e04e33314d916b2fbf8d53454762632..818e2e4742754e00aa80b17978d0daefe0aee81c 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/RawDiagnosticFormatter.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/RawDiagnosticFormatter.java @@ -59,8 +59,8 @@ public final class RawDiagnosticFormatter extends AbstractDiagnosticFormatter { /** * Helper class to generate stable positions for AST nodes occurring in diagnostic arguments. - * If the AST node appears in the same line number as the main diagnostic, the line is information is omitted. - * Otherwise both line and column information is included, using the format @{code line:col}". + * If the AST node appears in the same line number as the main diagnostic, the line information is omitted. + * Otherwise, both line and column information is included, using the format {@code line:col}. * * Note: since subdiagnostics can be created without a diagnostic source, a position helper * should always refer to the toplevel diagnostic source. @@ -85,7 +85,7 @@ public final class RawDiagnosticFormatter extends AbstractDiagnosticFormatter { /** * Create a formatter based on the supplied options. - * @param options + * @param options the compiler options */ public RawDiagnosticFormatter(Options options) { super(null, new SimpleConfiguration(options, diff --git a/src/jdk.compiler/share/classes/module-info.java b/src/jdk.compiler/share/classes/module-info.java index 88066d3c36358fb8b5e3050a0b0b1d10a58ccceb..a417a2998dc63b393219009094f611cd1e857e0a 100644 --- a/src/jdk.compiler/share/classes/module-info.java +++ b/src/jdk.compiler/share/classes/module-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,10 @@ * {@linkplain javax.tools.ToolProvider#getSystemJavaCompiler system Java compiler} * and its command line equivalent, {@index javac javac tool}. * + *

    The {@code com.sun.source.*} packages provide the {@index "Compiler Tree API"}: + * an API for accessing the abstract trees (ASTs) representing Java source code + * and documentation comments, used by javac, javadoc and related tools. + * *

    javac

    * *

    diff --git a/src/jdk.compiler/share/man/javac.1 b/src/jdk.compiler/share/man/javac.1 index c2a3190193c1473dd21333f4944f8e6963179c2d..7cc5714aa6ec5818f2972f98075d5e57b310898a 100644 --- a/src/jdk.compiler/share/man/javac.1 +++ b/src/jdk.compiler/share/man/javac.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JAVAC" "1" "2021" "JDK 18\-ea" "JDK Commands" +.TH "JAVAC" "1" "2022" "JDK 19\-ea" "JDK Commands" .hy .SH NAME .PP @@ -681,43 +681,28 @@ Selects a diagnostic mode. .RE .TP .B \f[CB]\-Xdoclint\f[R] -Enables recommended checks for problems in \f[CB]javadoc\f[R] comments +Enables recommended checks for problems in documentation comments. .RS .RE .TP .B \f[CB]\-Xdoclint:\f[R](\f[CB]all\f[R]|\f[CB]none\f[R]|[\f[CB]\-\f[R]]\f[I]group\f[R])[\f[CB]/\f[R]\f[I]access\f[R]] -Enables or disables specific groups of checks, +Enables or disables specific groups of checks in documentation comments. .RS .PP \f[I]group\f[R] can have one of the following values: -.IP \[bu] 2 -\f[CB]accessibility\f[R] -.IP \[bu] 2 -\f[CB]html\f[R] -.IP \[bu] 2 -\f[CB]missing\f[R] -.IP \[bu] 2 -\f[CB]reference\f[R] -.IP \[bu] 2 -\f[CB]syntax\f[R] +\f[CB]accessibility\f[R], \f[CB]html\f[R], \f[CB]missing\f[R], +\f[CB]reference\f[R], \f[CB]syntax\f[R] .PP The variable \f[I]access\f[R] specifies the minimum visibility level of classes and members that the \f[CB]\-Xdoclint\f[R] option checks. It can have one of the following values (in order of most to least -visible): -.IP \[bu] 2 -\f[CB]public\f[R] -.IP \[bu] 2 -\f[CB]protected\f[R] -.IP \[bu] 2 -\f[CB]package\f[R] -.IP \[bu] 2 -\f[CB]private\f[R] +visible): \f[CB]public\f[R], \f[CB]protected\f[R], \f[CB]package\f[R], +\f[CB]private\f[R]. .PP The default \f[I]access\f[R] level is \f[CB]private\f[R]. .PP For more information about these groups of checks, see the -\f[CB]\-Xdoclint\f[R] option of the \f[CB]javadoc\f[R] command. +\f[B]DocLint\f[R] section of the \f[CB]javadoc\f[R] command documentation. The \f[CB]\-Xdoclint\f[R] option is disabled by default in the \f[CB]javac\f[R] command. .PP @@ -747,6 +732,9 @@ sub\-packages of the given package. Each \f[I]package\f[R] can be prefixed with a hyphen (\f[CB]\-\f[R]) to disable checks for a specified package or packages. .RS +.PP +For more information, see the \f[B]DocLint\f[R] section of the +\f[CB]javadoc\f[R] command documentation. .RE .TP .B \f[CB]\-Xlint\f[R] @@ -1047,7 +1035,7 @@ Create a file named \f[CB]options\f[R] that contains the following: \f[R] .fi .PP -Create a file named \f[CB]classes\f[R] that contains the following: +Create a file named \f[CB]sources\f[R] that contains the following: .IP .nf \f[CB] @@ -1060,7 +1048,7 @@ MyClass3.java Then, run the \f[CB]javac\f[R] command as follows: .RS .PP -\f[CB]javac\ \@options\ \@classes\f[R] +\f[CB]javac\ \@options\ \@sources\f[R] .RE .RE .TP @@ -1071,7 +1059,7 @@ are relative to the current working directory (not \f[CB]path1\f[R] or .RS .RS .PP -\f[CB]javac\ \@path1/options\ \@path2/classes\f[R] +\f[CB]javac\ \@path1/options\ \@path2/sources\f[R] .RE .RE .SH ARRANGEMENT OF SOURCE CODE diff --git a/src/jdk.compiler/share/man/serialver.1 b/src/jdk.compiler/share/man/serialver.1 index 7781a3cbb355b0735833771dd578243034bdacd0..844e4fbca76147f1ba917ea7298c7411fcc02706 100644 --- a/src/jdk.compiler/share/man/serialver.1 +++ b/src/jdk.compiler/share/man/serialver.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "SERIALVER" "1" "2021" "JDK 18\-ea" "JDK Commands" +.TH "SERIALVER" "1" "2022" "JDK 19\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java index 6939c7be6f81f3c409ff8714aa9a41c9556a7d0a..676c1fe50e3c7aad21bf8d0c0c41584f8444ed60 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java @@ -165,7 +165,7 @@ final class Config { // name of the C function that returns the PKCS#11 functionlist // This option primarily exists for the deprecated // Secmod.Module.getProvider() method. - private String functionList = "C_GetFunctionList"; + private String functionList = null; // whether to use NSS secmod mode. Implicitly set if nssLibraryDirectory, // nssSecmodDirectory, or nssModule is specified. @@ -311,6 +311,12 @@ final class Config { } String getFunctionList() { + if (functionList == null) { + // defaults to "C_GetFunctionList" for NSS secmod + if (nssUseSecmod || nssUseSecmodTrust) { + return "C_GetFunctionList"; + } + } return functionList; } @@ -408,67 +414,73 @@ final class Config { if (token != TT_WORD) { throw excToken("Unexpected token:"); } - String word = st.sval; - if (word.equals("name")) { - name = parseStringEntry(word); - } else if (word.equals("library")) { - library = parseLibrary(word); - } else if (word.equals("description")) { - parseDescription(word); - } else if (word.equals("slot")) { - parseSlotID(word); - } else if (word.equals("slotListIndex")) { - parseSlotListIndex(word); - } else if (word.equals("enabledMechanisms")) { - parseEnabledMechanisms(word); - } else if (word.equals("disabledMechanisms")) { - parseDisabledMechanisms(word); - } else if (word.equals("attributes")) { - parseAttributes(word); - } else if (word.equals("handleStartupErrors")) { - parseHandleStartupErrors(word); - } else if (word.endsWith("insertionCheckInterval")) { - insertionCheckInterval = parseIntegerEntry(word); + switch (st.sval) { + case "name"-> + name = parseStringEntry(st.sval); + case "library"-> + library = parseLibrary(st.sval); + case "description"-> + parseDescription(st.sval); + case "slot"-> + parseSlotID(st.sval); + case "slotListIndex"-> + parseSlotListIndex(st.sval); + case "enabledMechanisms"-> + parseEnabledMechanisms(st.sval); + case "disabledMechanisms"-> + parseDisabledMechanisms(st.sval); + case "attributes"-> + parseAttributes(st.sval); + case "handleStartupErrors"-> + parseHandleStartupErrors(st.sval); + case "insertionCheckInterval"-> { + insertionCheckInterval = parseIntegerEntry(st.sval); if (insertionCheckInterval < 100) { - throw excLine(word + " must be at least 100 ms"); + throw excLine(st.sval + " must be at least 100 ms"); } - } else if (word.equals("cleaner.shortInterval")) { - resourceCleanerShortInterval = parseIntegerEntry(word); + } + case "cleaner.shortInterval"-> { + resourceCleanerShortInterval = parseIntegerEntry(st.sval); if (resourceCleanerShortInterval < 1_000) { - throw excLine(word + " must be at least 1000 ms"); + throw excLine(st.sval + " must be at least 1000 ms"); } - } else if (word.equals("cleaner.longInterval")) { - resourceCleanerLongInterval = parseIntegerEntry(word); + } + case "cleaner.longInterval"-> { + resourceCleanerLongInterval = parseIntegerEntry(st.sval); if (resourceCleanerLongInterval < 1_000) { - throw excLine(word + " must be at least 1000 ms"); + throw excLine(st.sval + " must be at least 1000 ms"); } - } else if (word.equals("destroyTokenAfterLogout")) { - destroyTokenAfterLogout = parseBooleanEntry(word); - } else if (word.equals("showInfo")) { - showInfo = parseBooleanEntry(word); - } else if (word.equals("keyStoreCompatibilityMode")) { - keyStoreCompatibilityMode = parseBooleanEntry(word); - } else if (word.equals("explicitCancel")) { - explicitCancel = parseBooleanEntry(word); - } else if (word.equals("omitInitialize")) { - omitInitialize = parseBooleanEntry(word); - } else if (word.equals("allowSingleThreadedModules")) { - allowSingleThreadedModules = parseBooleanEntry(word); - } else if (word.equals("functionList")) { - functionList = parseStringEntry(word); - } else if (word.equals("nssUseSecmod")) { - nssUseSecmod = parseBooleanEntry(word); - } else if (word.equals("nssLibraryDirectory")) { - nssLibraryDirectory = parseLibrary(word); + } + case "destroyTokenAfterLogout"-> + destroyTokenAfterLogout = parseBooleanEntry(st.sval); + case "showInfo"-> + showInfo = parseBooleanEntry(st.sval); + case "keyStoreCompatibilityMode"-> + keyStoreCompatibilityMode = parseBooleanEntry(st.sval); + case "explicitCancel"-> + explicitCancel = parseBooleanEntry(st.sval); + case "omitInitialize"-> + omitInitialize = parseBooleanEntry(st.sval); + case "allowSingleThreadedModules"-> + allowSingleThreadedModules = parseBooleanEntry(st.sval); + case "functionList"-> + functionList = parseStringEntry(st.sval); + case "nssUseSecmod"-> + nssUseSecmod = parseBooleanEntry(st.sval); + case "nssLibraryDirectory"-> { + nssLibraryDirectory = parseLibrary(st.sval); nssUseSecmod = true; - } else if (word.equals("nssSecmodDirectory")) { - nssSecmodDirectory = expand(parseStringEntry(word)); + } + case "nssSecmodDirectory"-> { + nssSecmodDirectory = expand(parseStringEntry(st.sval)); nssUseSecmod = true; - } else if (word.equals("nssModule")) { - nssModule = parseStringEntry(word); + } + case "nssModule"-> { + nssModule = parseStringEntry(st.sval); nssUseSecmod = true; - } else if (word.equals("nssDbMode")) { - String mode = parseStringEntry(word); + } + case "nssDbMode"-> { + String mode = parseStringEntry(st.sval); if (mode.equals("readWrite")) { nssDbMode = Secmod.DbMode.READ_WRITE; } else if (mode.equals("readOnly")) { @@ -479,22 +491,25 @@ final class Config { throw excToken("nssDbMode must be one of readWrite, readOnly, and noDb:"); } nssUseSecmod = true; - } else if (word.equals("nssNetscapeDbWorkaround")) { - nssNetscapeDbWorkaround = parseBooleanEntry(word); + } + case "nssNetscapeDbWorkaround"-> { + nssNetscapeDbWorkaround = parseBooleanEntry(st.sval); nssUseSecmod = true; - } else if (word.equals("nssArgs")) { - parseNSSArgs(word); - } else if (word.equals("nssUseSecmodTrust")) { - nssUseSecmodTrust = parseBooleanEntry(word); - } else if (word.equals("useEcX963Encoding")) { - useEcX963Encoding = parseBooleanEntry(word); - } else if (word.equals("nssOptimizeSpace")) { - nssOptimizeSpace = parseBooleanEntry(word); - } else { + } + case "nssArgs"-> + parseNSSArgs(st.sval); + case "nssUseSecmodTrust"-> + nssUseSecmodTrust = parseBooleanEntry(st.sval); + case "useEcX963Encoding"-> + useEcX963Encoding = parseBooleanEntry(st.sval); + case "nssOptimizeSpace"-> + nssOptimizeSpace = parseBooleanEntry(st.sval); + default-> throw new ConfigurationException - ("Unknown keyword '" + word + "', line " + st.lineno()); + ("Unknown keyword '" + st.sval + "', line " + + st.lineno()); } - parsedKeywords.add(word); + parsedKeywords.add(st.sval); } reader.close(); reader = null; diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11AEADCipher.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11AEADCipher.java index 8a01705b76ff0a562563852406b62d78ed42acb3..fbabbf2a36c1e83a4f07294268d45f01191e2b47 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11AEADCipher.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11AEADCipher.java @@ -401,7 +401,13 @@ final class P11AEADCipher extends CipherSpi { } private void cancelOperation() { - // cancel operation by finishing it; avoid killSession as some + token.ensureValid(); + if (P11Util.trySessionCancel(token, session, + (encrypt ? CKF_ENCRYPT : CKF_DECRYPT))) { + return; + } + + // cancel by finishing operations; avoid killSession as some // hardware vendors may require re-login int bufLen = doFinalLength(0); byte[] buffer = new byte[bufLen]; @@ -453,7 +459,7 @@ final class P11AEADCipher extends CipherSpi { token.ensureValid(); - byte[] aad = (aadBuffer.size() > 0? aadBuffer.toByteArray() : null); + byte[] aad = (aadBuffer.size() > 0 ? aadBuffer.toByteArray() : null); long p11KeyID = p11Key.getKeyID(); try { @@ -507,7 +513,7 @@ final class P11AEADCipher extends CipherSpi { result -= tagLen; } } - return (result > 0? result : 0); + return (result > 0 ? result : 0); } // reset the states to the pre-initialized values diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Cipher.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Cipher.java index 5934299e10c7bc73f6b10e49f42d34aa0a05fd21..367c9b84832f5b1aeef229a63d73d9741dbc1402 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Cipher.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Cipher.java @@ -445,8 +445,14 @@ final class P11Cipher extends CipherSpi { private void cancelOperation() { token.ensureValid(); - // cancel operation by finishing it; avoid killSession as some - // hardware vendors may require re-login + + if (P11Util.trySessionCancel(token, session, + (encrypt ? CKF_ENCRYPT : CKF_DECRYPT))) { + return; + } + + // cancel by finishing operations; avoid killSession as + // some hardware vendors may require re-login try { int bufLen = doFinalLength(0); byte[] buffer = new byte[bufLen]; @@ -458,7 +464,7 @@ final class P11Cipher extends CipherSpi { } catch (PKCS11Exception e) { if (e.match(CKR_OPERATION_NOT_INITIALIZED)) { // Cancel Operation may be invoked after an error on a PKCS#11 - // call. If the operation inside the token was already cancelled, + // call. If the operation inside the token is already cancelled, // do not fail here. This is part of a defensive mechanism for // PKCS#11 libraries that do not strictly follow the standard. return; @@ -488,7 +494,7 @@ final class P11Cipher extends CipherSpi { if (session == null) { session = token.getOpSession(); } - CK_MECHANISM mechParams = (blockMode == MODE_CTR? + CK_MECHANISM mechParams = (blockMode == MODE_CTR ? new CK_MECHANISM(mechanism, new CK_AES_CTR_PARAMS(iv)) : new CK_MECHANISM(mechanism, iv)); if (encrypt) { diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java index 638bd208aa6132d65a9890f42d26b48d2bee2342..bf0c5f2ba846b2b3e3ce5b68d0b3b4b5e319ae09 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java @@ -115,7 +115,7 @@ abstract class P11Key implements Key, Length { } P11Key(String type, Session session, long keyID, String algorithm, - int keyLength, CK_ATTRIBUTE[] attributes) { + int keyLength, CK_ATTRIBUTE[] attrs) { this.type = type; this.token = session.token; this.algorithm = algorithm; @@ -123,15 +123,15 @@ abstract class P11Key implements Key, Length { boolean tokenObject = false; boolean sensitive = false; boolean extractable = true; - int n = (attributes == null) ? 0 : attributes.length; - for (int i = 0; i < n; i++) { - CK_ATTRIBUTE attr = attributes[i]; - if (attr.type == CKA_TOKEN) { - tokenObject = attr.getBoolean(); - } else if (attr.type == CKA_SENSITIVE) { - sensitive = attr.getBoolean(); - } else if (attr.type == CKA_EXTRACTABLE) { - extractable = attr.getBoolean(); + if (attrs != null) { + for (CK_ATTRIBUTE attr : attrs) { + if (attr.type == CKA_TOKEN) { + tokenObject = attr.getBoolean(); + } else if (attr.type == CKA_SENSITIVE) { + sensitive = attr.getBoolean(); + } else if (attr.type == CKA_EXTRACTABLE) { + extractable = attr.getBoolean(); + } } } this.tokenObject = tokenObject; @@ -247,7 +247,7 @@ abstract class P11Key implements Key, Length { public String toString() { token.ensureValid(); String s1 = token.provider.getName() + " " + algorithm + " " + type - + " key, " + keyLength + " bits"; + + " key, " + keyLength + " bits "; s1 += (tokenObject ? "token" : "session") + " object"; if (isPublic()) { s1 += ")"; @@ -278,19 +278,31 @@ abstract class P11Key implements Key, Length { return type == SECRET; } - void fetchAttributes(CK_ATTRIBUTE[] attributes) { + CK_ATTRIBUTE[] fetchAttributes(CK_ATTRIBUTE[] attrs) { + Objects.requireNonNull(attrs, "attrs must be non-null"); Session tempSession = null; long keyID = this.getKeyID(); try { tempSession = token.getOpSession(); token.p11.C_GetAttributeValue(tempSession.id(), keyID, - attributes); + attrs); } catch (PKCS11Exception e) { throw new ProviderException(e); } finally { this.releaseKeyID(); token.releaseSession(tempSession); } + return attrs; + } + + // convenience method which returns the attribute values as BigInteger[] + BigInteger[] fetchAttributesAsInts(CK_ATTRIBUTE[] attrs) { + attrs = fetchAttributes(attrs); + BigInteger[] res = new BigInteger[attrs.length]; + for (int i = 0; i < attrs.length; i++) { + res[i] = attrs[i].getBigInteger(); + } + return res; } private static final CK_ATTRIBUTE[] A0 = new CK_ATTRIBUTE[0]; @@ -329,44 +341,43 @@ abstract class P11Key implements Key, Length { } static SecretKey secretKey(Session session, long keyID, String algorithm, - int keyLength, CK_ATTRIBUTE[] attributes) { - attributes = getAttributes(session, keyID, attributes, new CK_ATTRIBUTE[] { - new CK_ATTRIBUTE(CKA_TOKEN), - new CK_ATTRIBUTE(CKA_SENSITIVE), - new CK_ATTRIBUTE(CKA_EXTRACTABLE), + int keyLength, CK_ATTRIBUTE[] attrs) { + attrs = getAttributes(session, keyID, attrs, new CK_ATTRIBUTE[] { + new CK_ATTRIBUTE(CKA_TOKEN), + new CK_ATTRIBUTE(CKA_SENSITIVE), + new CK_ATTRIBUTE(CKA_EXTRACTABLE), }); - return new P11SecretKey(session, keyID, algorithm, keyLength, - attributes); + return new P11SecretKey(session, keyID, algorithm, keyLength, attrs); } - static SecretKey masterSecretKey(Session session, long keyID, String algorithm, - int keyLength, CK_ATTRIBUTE[] attributes, int major, int minor) { - attributes = getAttributes(session, keyID, attributes, new CK_ATTRIBUTE[] { - new CK_ATTRIBUTE(CKA_TOKEN), - new CK_ATTRIBUTE(CKA_SENSITIVE), - new CK_ATTRIBUTE(CKA_EXTRACTABLE), + static SecretKey masterSecretKey(Session session, long keyID, + String algorithm, int keyLength, CK_ATTRIBUTE[] attrs, + int major, int minor) { + attrs = getAttributes(session, keyID, attrs, new CK_ATTRIBUTE[] { + new CK_ATTRIBUTE(CKA_TOKEN), + new CK_ATTRIBUTE(CKA_SENSITIVE), + new CK_ATTRIBUTE(CKA_EXTRACTABLE), }); - return new P11TlsMasterSecretKey( - session, keyID, algorithm, keyLength, attributes, major, - minor); + return new P11TlsMasterSecretKey(session, keyID, algorithm, keyLength, + attrs, major, minor); } // we assume that all components of public keys are always accessible static PublicKey publicKey(Session session, long keyID, String algorithm, - int keyLength, CK_ATTRIBUTE[] attributes) { + int keyLength, CK_ATTRIBUTE[] attrs) { switch (algorithm) { case "RSA": return new P11RSAPublicKey(session, keyID, algorithm, - keyLength, attributes); + keyLength, attrs); case "DSA": return new P11DSAPublicKey(session, keyID, algorithm, - keyLength, attributes); + keyLength, attrs); case "DH": return new P11DHPublicKey(session, keyID, algorithm, - keyLength, attributes); + keyLength, attrs); case "EC": return new P11ECPublicKey(session, keyID, algorithm, - keyLength, attributes); + keyLength, attrs); default: throw new ProviderException ("Unknown public key algorithm " + algorithm); @@ -374,73 +385,45 @@ abstract class P11Key implements Key, Length { } static PrivateKey privateKey(Session session, long keyID, String algorithm, - int keyLength, CK_ATTRIBUTE[] attributes) { - attributes = getAttributes(session, keyID, attributes, new CK_ATTRIBUTE[] { - new CK_ATTRIBUTE(CKA_TOKEN), - new CK_ATTRIBUTE(CKA_SENSITIVE), - new CK_ATTRIBUTE(CKA_EXTRACTABLE), + int keyLength, CK_ATTRIBUTE[] attrs) { + attrs = getAttributes(session, keyID, attrs, new CK_ATTRIBUTE[] { + new CK_ATTRIBUTE(CKA_TOKEN), + new CK_ATTRIBUTE(CKA_SENSITIVE), + new CK_ATTRIBUTE(CKA_EXTRACTABLE), }); - if (attributes[1].getBoolean() || (attributes[2].getBoolean() == false)) { - return new P11PrivateKey - (session, keyID, algorithm, keyLength, attributes); - } else { - switch (algorithm) { - case "RSA": - // In order to decide if this is RSA CRT key, we first query - // and see if all extra CRT attributes are available. - CK_ATTRIBUTE[] attrs2 = new CK_ATTRIBUTE[] { - new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT), - new CK_ATTRIBUTE(CKA_PRIME_1), - new CK_ATTRIBUTE(CKA_PRIME_2), - new CK_ATTRIBUTE(CKA_EXPONENT_1), - new CK_ATTRIBUTE(CKA_EXPONENT_2), - new CK_ATTRIBUTE(CKA_COEFFICIENT), - }; - boolean crtKey; - try { - session.token.p11.C_GetAttributeValue - (session.id(), keyID, attrs2); - crtKey = ((attrs2[0].pValue instanceof byte[]) && - (attrs2[1].pValue instanceof byte[]) && - (attrs2[2].pValue instanceof byte[]) && - (attrs2[3].pValue instanceof byte[]) && - (attrs2[4].pValue instanceof byte[]) && - (attrs2[5].pValue instanceof byte[])) ; - } catch (PKCS11Exception e) { - // ignore, assume not available - crtKey = false; - } - if (crtKey) { - return new P11RSAPrivateKey(session, keyID, algorithm, - keyLength, attributes, attrs2); - } else { - return new P11RSAPrivateNonCRTKey(session, keyID, - algorithm, keyLength, attributes); - } - case "DSA": - return new P11DSAPrivateKey(session, keyID, algorithm, - keyLength, attributes); - case "DH": - return new P11DHPrivateKey(session, keyID, algorithm, - keyLength, attributes); - case "EC": - return new P11ECPrivateKey(session, keyID, algorithm, - keyLength, attributes); - default: - throw new ProviderException - ("Unknown private key algorithm " + algorithm); - } + + boolean keySensitive = (attrs[0].getBoolean() || + attrs[1].getBoolean() || !attrs[2].getBoolean()); + + switch (algorithm) { + case "RSA": + return P11RSAPrivateKeyInternal.of(session, keyID, algorithm, + keyLength, attrs, keySensitive); + case "DSA": + return P11DSAPrivateKeyInternal.of(session, keyID, algorithm, + keyLength, attrs, keySensitive); + case "DH": + return P11DHPrivateKeyInternal.of(session, keyID, algorithm, + keyLength, attrs, keySensitive); + case "EC": + return P11ECPrivateKeyInternal.of(session, keyID, algorithm, + keyLength, attrs, keySensitive); + default: + throw new ProviderException + ("Unknown private key algorithm " + algorithm); } } - // class for sensitive and unextractable private keys - private static final class P11PrivateKey extends P11Key - implements PrivateKey { + // base class for all PKCS11 private keys + private static abstract class P11PrivateKey extends P11Key implements + PrivateKey { private static final long serialVersionUID = -2138581185214187615L; + protected byte[] encoded; // guard by synchronized + P11PrivateKey(Session session, long keyID, String algorithm, - int keyLength, CK_ATTRIBUTE[] attributes) { - super(PRIVATE, session, keyID, algorithm, keyLength, attributes); + int keyLength, CK_ATTRIBUTE[] attrs) { + super(PRIVATE, session, keyID, algorithm, keyLength, attrs); } // XXX temporary encoding for serialization purposes public String getFormat() { @@ -455,11 +438,14 @@ abstract class P11Key implements Key, Length { private static class P11SecretKey extends P11Key implements SecretKey { private static final long serialVersionUID = -7828241727014329084L; - private volatile byte[] encoded; + + private volatile byte[] encoded; // guard by double-checked locking + P11SecretKey(Session session, long keyID, String algorithm, - int keyLength, CK_ATTRIBUTE[] attributes) { - super(SECRET, session, keyID, algorithm, keyLength, attributes); + int keyLength, CK_ATTRIBUTE[] attrs) { + super(SECRET, session, keyID, algorithm, keyLength, attrs); } + public String getFormat() { token.ensureValid(); if (sensitive || (extractable == false)) { @@ -468,32 +454,21 @@ abstract class P11Key implements Key, Length { return "RAW"; } } + byte[] getEncodedInternal() { token.ensureValid(); if (getFormat() == null) { return null; } + byte[] b = encoded; if (b == null) { synchronized (this) { b = encoded; if (b == null) { - Session tempSession = null; - long keyID = this.getKeyID(); - try { - tempSession = token.getOpSession(); - CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] { + b = fetchAttributes(new CK_ATTRIBUTE[] { new CK_ATTRIBUTE(CKA_VALUE), - }; - token.p11.C_GetAttributeValue - (tempSession.id(), keyID, attributes); - b = attributes[0].getByteArray(); - } catch (PKCS11Exception e) { - throw new ProviderException(e); - } finally { - this.releaseKeyID(); - token.releaseSession(tempSession); - } + })[0].getByteArray(); encoded = b; } } @@ -502,6 +477,19 @@ abstract class P11Key implements Key, Length { } } + // base class for all PKCS11 public keys + private static abstract class P11PublicKey extends P11Key implements + PublicKey { + private static final long serialVersionUID = 1L; + + protected byte[] encoded; // guard by synchronized + + P11PublicKey(Session session, long keyID, String algorithm, + int keyLength, CK_ATTRIBUTE[] attrs) { + super(PUBLIC, session, keyID, algorithm, keyLength, attrs); + } + } + @SuppressWarnings("deprecation") private static class P11TlsMasterSecretKey extends P11SecretKey implements TlsMasterSecret { @@ -509,8 +497,8 @@ abstract class P11Key implements Key, Length { private final int majorVersion, minorVersion; P11TlsMasterSecretKey(Session session, long keyID, String algorithm, - int keyLength, CK_ATTRIBUTE[] attributes, int major, int minor) { - super(session, keyID, algorithm, keyLength, attributes); + int keyLength, CK_ATTRIBUTE[] attrs, int major, int minor) { + super(session, keyID, algorithm, keyLength, attrs); this.majorVersion = major; this.minorVersion = minor; } @@ -523,17 +511,92 @@ abstract class P11Key implements Key, Length { } } + // impl class for sensitive/unextractable RSA private keys + static class P11RSAPrivateKeyInternal extends P11PrivateKey { + private static final long serialVersionUID = -2138581185214187615L; + + static P11RSAPrivateKeyInternal of(Session session, long keyID, + String algorithm, int keyLength, CK_ATTRIBUTE[] attrs, + boolean keySensitive) { + if (keySensitive) { + return new P11RSAPrivateKeyInternal(session, keyID, algorithm, + keyLength, attrs); + } else { + CK_ATTRIBUTE[] rsaAttrs = new CK_ATTRIBUTE[] { + new CK_ATTRIBUTE(CKA_MODULUS), + new CK_ATTRIBUTE(CKA_PRIVATE_EXPONENT), + new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT), + new CK_ATTRIBUTE(CKA_PRIME_1), + new CK_ATTRIBUTE(CKA_PRIME_2), + new CK_ATTRIBUTE(CKA_EXPONENT_1), + new CK_ATTRIBUTE(CKA_EXPONENT_2), + new CK_ATTRIBUTE(CKA_COEFFICIENT), + }; + boolean isCRT = true; + Session tempSession = null; + try { + tempSession = session.token.getOpSession(); + session.token.p11.C_GetAttributeValue(tempSession.id(), + keyID, rsaAttrs); + for (CK_ATTRIBUTE attr : rsaAttrs) { + isCRT &= (attr.pValue instanceof byte[]); + if (!isCRT) break; + } + } catch (PKCS11Exception e) { + // ignore, assume not available + isCRT = false; + } finally { + session.token.releaseSession(tempSession); + } + BigInteger n = rsaAttrs[0].getBigInteger(); + BigInteger d = rsaAttrs[1].getBigInteger(); + if (isCRT) { + return new P11RSAPrivateKey(session, keyID, algorithm, + keyLength, attrs, n, d, + Arrays.copyOfRange(rsaAttrs, 2, rsaAttrs.length)); + } else { + return new P11RSAPrivateNonCRTKey(session, keyID, + algorithm, keyLength, attrs, n, d); + } + } + } + + protected transient BigInteger n; + + private P11RSAPrivateKeyInternal(Session session, long keyID, + String algorithm, int keyLength, CK_ATTRIBUTE[] attrs) { + super(session, keyID, algorithm, keyLength, attrs); + } + + private synchronized void fetchValues() { + token.ensureValid(); + if (n != null) return; + + n = fetchAttributesAsInts(new CK_ATTRIBUTE[] { + new CK_ATTRIBUTE(CKA_MODULUS) + })[0]; + } + + public BigInteger getModulus() { + fetchValues(); + return n; + } + } + // RSA CRT private key - private static final class P11RSAPrivateKey extends P11Key - implements RSAPrivateCrtKey { + private static final class P11RSAPrivateKey extends P11RSAPrivateKeyInternal + implements RSAPrivateCrtKey { private static final long serialVersionUID = 9215872438913515220L; - private BigInteger n, e, d, p, q, pe, qe, coeff; - private byte[] encoded; - P11RSAPrivateKey(Session session, long keyID, String algorithm, - int keyLength, CK_ATTRIBUTE[] attrs, CK_ATTRIBUTE[] crtAttrs) { - super(PRIVATE, session, keyID, algorithm, keyLength, attrs); + private transient BigInteger e, d, p, q, pe, qe, coeff; + + private P11RSAPrivateKey(Session session, long keyID, String algorithm, + int keyLength, CK_ATTRIBUTE[] attrs, BigInteger n, BigInteger d, + CK_ATTRIBUTE[] crtAttrs) { + super(session, keyID, algorithm, keyLength, attrs); + this.n = n; + this.d = d; for (CK_ATTRIBUTE a : crtAttrs) { if (a.type == CKA_PUBLIC_EXPONENT) { e = a.getBigInteger(); @@ -550,28 +613,15 @@ abstract class P11Key implements Key, Length { } } } - private synchronized void fetchValues() { - token.ensureValid(); - if (n != null) { - return; - } - CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] { - new CK_ATTRIBUTE(CKA_MODULUS), - new CK_ATTRIBUTE(CKA_PRIVATE_EXPONENT), - }; - fetchAttributes(attributes); - n = attributes[0].getBigInteger(); - d = attributes[1].getBigInteger(); - } public String getFormat() { token.ensureValid(); return "PKCS#8"; } + synchronized byte[] getEncodedInternal() { token.ensureValid(); if (encoded == null) { - fetchValues(); try { Key newKey = RSAPrivateCrtKeyImpl.newKey (KeyType.RSA, null, n, e, d, p, q, pe, qe, coeff); @@ -582,15 +632,15 @@ abstract class P11Key implements Key, Length { } return encoded; } + + @Override public BigInteger getModulus() { - fetchValues(); return n; } public BigInteger getPublicExponent() { return e; } public BigInteger getPrivateExponent() { - fetchValues(); return d; } public BigInteger getPrimeP() { @@ -611,37 +661,28 @@ abstract class P11Key implements Key, Length { } // RSA non-CRT private key - private static final class P11RSAPrivateNonCRTKey extends P11Key - implements RSAPrivateKey { + private static final class P11RSAPrivateNonCRTKey extends + P11RSAPrivateKeyInternal implements RSAPrivateKey { private static final long serialVersionUID = 1137764983777411481L; - private BigInteger n, d; - private byte[] encoded; + private transient BigInteger d; + P11RSAPrivateNonCRTKey(Session session, long keyID, String algorithm, - int keyLength, CK_ATTRIBUTE[] attributes) { - super(PRIVATE, session, keyID, algorithm, keyLength, attributes); - } - private synchronized void fetchValues() { - token.ensureValid(); - if (n != null) { - return; - } - CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] { - new CK_ATTRIBUTE(CKA_MODULUS), - new CK_ATTRIBUTE(CKA_PRIVATE_EXPONENT), - }; - fetchAttributes(attributes); - n = attributes[0].getBigInteger(); - d = attributes[1].getBigInteger(); + int keyLength, CK_ATTRIBUTE[] attrs, BigInteger n, + BigInteger d) { + super(session, keyID, algorithm, keyLength, attrs); + this.n = n; + this.d = d; } + public String getFormat() { token.ensureValid(); return "PKCS#8"; } + synchronized byte[] getEncodedInternal() { token.ensureValid(); if (encoded == null) { - fetchValues(); try { // XXX make constructor in SunRsaSign provider public // and call it directly @@ -655,42 +696,43 @@ abstract class P11Key implements Key, Length { } return encoded; } + + @Override public BigInteger getModulus() { - fetchValues(); return n; } public BigInteger getPrivateExponent() { - fetchValues(); return d; } } - private static final class P11RSAPublicKey extends P11Key + private static final class P11RSAPublicKey extends P11PublicKey implements RSAPublicKey { private static final long serialVersionUID = -826726289023854455L; - private BigInteger n, e; - private byte[] encoded; + private transient BigInteger n, e; + P11RSAPublicKey(Session session, long keyID, String algorithm, - int keyLength, CK_ATTRIBUTE[] attributes) { - super(PUBLIC, session, keyID, algorithm, keyLength, attributes); + int keyLength, CK_ATTRIBUTE[] attrs) { + super(session, keyID, algorithm, keyLength, attrs); } + private synchronized void fetchValues() { token.ensureValid(); - if (n != null) { - return; - } - CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] { + if (n != null) return; + + BigInteger[] res = fetchAttributesAsInts(new CK_ATTRIBUTE[] { new CK_ATTRIBUTE(CKA_MODULUS), - new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT), - }; - fetchAttributes(attributes); - n = attributes[0].getBigInteger(); - e = attributes[1].getBigInteger(); + new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT) + }); + n = res[0]; + e = res[1]; } + public String getFormat() { token.ensureValid(); return "X.509"; } + synchronized byte[] getEncodedInternal() { token.ensureValid(); if (encoded == null) { @@ -704,6 +746,7 @@ abstract class P11Key implements Key, Length { } return encoded; } + public BigInteger getModulus() { fetchValues(); return n; @@ -719,41 +762,37 @@ abstract class P11Key implements Key, Length { } } - private static final class P11DSAPublicKey extends P11Key + private static final class P11DSAPublicKey extends P11PublicKey implements DSAPublicKey { private static final long serialVersionUID = 5989753793316396637L; - private BigInteger y; - @SuppressWarnings("serial") // Type of field is not Serializable - private DSAParams params; - private byte[] encoded; + private transient BigInteger y; + private transient DSAParams params; + P11DSAPublicKey(Session session, long keyID, String algorithm, - int keyLength, CK_ATTRIBUTE[] attributes) { - super(PUBLIC, session, keyID, algorithm, keyLength, attributes); + int keyLength, CK_ATTRIBUTE[] attrs) { + super(session, keyID, algorithm, keyLength, attrs); } + private synchronized void fetchValues() { token.ensureValid(); - if (y != null) { - return; - } - CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] { + if (y != null) return; + + BigInteger[] res = fetchAttributesAsInts(new CK_ATTRIBUTE[] { new CK_ATTRIBUTE(CKA_VALUE), new CK_ATTRIBUTE(CKA_PRIME), new CK_ATTRIBUTE(CKA_SUBPRIME), - new CK_ATTRIBUTE(CKA_BASE), - }; - fetchAttributes(attributes); - y = attributes[0].getBigInteger(); - params = new DSAParameterSpec( - attributes[1].getBigInteger(), - attributes[2].getBigInteger(), - attributes[3].getBigInteger() - ); + new CK_ATTRIBUTE(CKA_BASE) + }); + y = res[0]; + params = new DSAParameterSpec(res[1], res[2], res[3]); } + public String getFormat() { token.ensureValid(); return "X.509"; } + synchronized byte[] getEncodedInternal() { token.ensureValid(); if (encoded == null) { @@ -783,41 +822,76 @@ abstract class P11Key implements Key, Length { } } - private static final class P11DSAPrivateKey extends P11Key - implements DSAPrivateKey { + static class P11DSAPrivateKeyInternal extends P11PrivateKey { private static final long serialVersionUID = 3119629997181999389L; - private BigInteger x; - @SuppressWarnings("serial") // Type of field is not Serializable - private DSAParams params; - private byte[] encoded; + protected transient DSAParams params; + + static P11DSAPrivateKeyInternal of(Session session, long keyID, + String algorithm, int keyLength, CK_ATTRIBUTE[] attrs, + boolean keySensitive) { + if (keySensitive) { + return new P11DSAPrivateKeyInternal(session, keyID, algorithm, + keyLength, attrs); + } else { + return new P11DSAPrivateKey(session, keyID, algorithm, + keyLength, attrs); + } + } + + private P11DSAPrivateKeyInternal(Session session, long keyID, + String algorithm, int keyLength, CK_ATTRIBUTE[] attrs) { + super(session, keyID, algorithm, keyLength, attrs); + } + + private synchronized void fetchValues() { + token.ensureValid(); + if (params != null) return; + + BigInteger[] res = fetchAttributesAsInts(new CK_ATTRIBUTE[] { + new CK_ATTRIBUTE(CKA_PRIME), + new CK_ATTRIBUTE(CKA_SUBPRIME), + new CK_ATTRIBUTE(CKA_BASE), + }); + params = new DSAParameterSpec(res[0], res[1], res[2]); + } + + protected DSAParams getParams() { + fetchValues(); + return params; + } + } + + private static final class P11DSAPrivateKey extends P11DSAPrivateKeyInternal + implements DSAPrivateKey { + private static final long serialVersionUID = 3119629997181999389L; + + private transient BigInteger x; // params inside P11DSAPrivateKeyInternal + P11DSAPrivateKey(Session session, long keyID, String algorithm, - int keyLength, CK_ATTRIBUTE[] attributes) { - super(PRIVATE, session, keyID, algorithm, keyLength, attributes); + int keyLength, CK_ATTRIBUTE[] attrs) { + super(session, keyID, algorithm, keyLength, attrs); } + private synchronized void fetchValues() { token.ensureValid(); - if (x != null) { - return; - } - CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] { - new CK_ATTRIBUTE(CKA_VALUE), - new CK_ATTRIBUTE(CKA_PRIME), - new CK_ATTRIBUTE(CKA_SUBPRIME), - new CK_ATTRIBUTE(CKA_BASE), - }; - fetchAttributes(attributes); - x = attributes[0].getBigInteger(); - params = new DSAParameterSpec( - attributes[1].getBigInteger(), - attributes[2].getBigInteger(), - attributes[3].getBigInteger() - ); + if (x != null) return; + + BigInteger[] res = fetchAttributesAsInts(new CK_ATTRIBUTE[] { + new CK_ATTRIBUTE(CKA_VALUE), + new CK_ATTRIBUTE(CKA_PRIME), + new CK_ATTRIBUTE(CKA_SUBPRIME), + new CK_ATTRIBUTE(CKA_BASE), + }); + x = res[0]; + params = new DSAParameterSpec(res[1], res[2], res[3]); } + public String getFormat() { token.ensureValid(); return "PKCS#8"; } + synchronized byte[] getEncodedInternal() { token.ensureValid(); if (encoded == null) { @@ -828,49 +902,87 @@ abstract class P11Key implements Key, Length { } return encoded; } + public BigInteger getX() { fetchValues(); return x; } + + @Override public DSAParams getParams() { fetchValues(); return params; } } - private static final class P11DHPrivateKey extends P11Key + static class P11DHPrivateKeyInternal extends P11PrivateKey { + private static final long serialVersionUID = 1L; + + protected transient DHParameterSpec params; + + static P11DHPrivateKeyInternal of(Session session, long keyID, + String algorithm, int keyLength, CK_ATTRIBUTE[] attrs, + boolean keySensitive) { + if (keySensitive) { + return new P11DHPrivateKeyInternal(session, keyID, algorithm, + keyLength, attrs); + } else { + return new P11DHPrivateKey(session, keyID, algorithm, + keyLength, attrs); + } + } + + private P11DHPrivateKeyInternal(Session session, long keyID, + String algorithm, int keyLength, CK_ATTRIBUTE[] attrs) { + super(session, keyID, algorithm, keyLength, attrs); + } + + private synchronized void fetchValues() { + token.ensureValid(); + if (params != null) return; + + BigInteger[] res = fetchAttributesAsInts(new CK_ATTRIBUTE[] { + new CK_ATTRIBUTE(CKA_PRIME), + new CK_ATTRIBUTE(CKA_BASE), + }); + params = new DHParameterSpec(res[0], res[1]); + } + + public DHParameterSpec getParams() { + fetchValues(); + return params; + } + } + + private static final class P11DHPrivateKey extends P11DHPrivateKeyInternal implements DHPrivateKey { private static final long serialVersionUID = -1698576167364928838L; - private BigInteger x; - @SuppressWarnings("serial") // Type of field is not Serializable - private DHParameterSpec params; - private byte[] encoded; + private transient BigInteger x; // params in P11DHPrivateKeyInternal + P11DHPrivateKey(Session session, long keyID, String algorithm, - int keyLength, CK_ATTRIBUTE[] attributes) { - super(PRIVATE, session, keyID, algorithm, keyLength, attributes); + int keyLength, CK_ATTRIBUTE[] attrs) { + super(session, keyID, algorithm, keyLength, attrs); } + private synchronized void fetchValues() { token.ensureValid(); - if (x != null) { - return; - } - CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] { - new CK_ATTRIBUTE(CKA_VALUE), - new CK_ATTRIBUTE(CKA_PRIME), - new CK_ATTRIBUTE(CKA_BASE), - }; - fetchAttributes(attributes); - x = attributes[0].getBigInteger(); - params = new DHParameterSpec( - attributes[1].getBigInteger(), - attributes[2].getBigInteger() - ); + if (x != null) return; + + BigInteger[] res = fetchAttributesAsInts(new CK_ATTRIBUTE[] { + new CK_ATTRIBUTE(CKA_VALUE), + new CK_ATTRIBUTE(CKA_PRIME), + new CK_ATTRIBUTE(CKA_BASE), + }); + x = res[0]; + params = new DHParameterSpec(res[1], res[2]); } + public String getFormat() { token.ensureValid(); return "PKCS#8"; } + synchronized byte[] getEncodedInternal() { token.ensureValid(); if (encoded == null) { @@ -897,10 +1009,10 @@ abstract class P11Key implements Key, Length { return params; } public int hashCode() { + fetchValues(); if (!token.isValid()) { return 0; } - fetchValues(); return Objects.hash(x, params.getP(), params.getG()); } public boolean equals(Object obj) { @@ -921,39 +1033,36 @@ abstract class P11Key implements Key, Length { } } - private static final class P11DHPublicKey extends P11Key + private static final class P11DHPublicKey extends P11PublicKey implements DHPublicKey { static final long serialVersionUID = -598383872153843657L; - private BigInteger y; - @SuppressWarnings("serial") // Type of field is not Serializable - private DHParameterSpec params; - private byte[] encoded; + private transient BigInteger y; + private transient DHParameterSpec params; + P11DHPublicKey(Session session, long keyID, String algorithm, - int keyLength, CK_ATTRIBUTE[] attributes) { - super(PUBLIC, session, keyID, algorithm, keyLength, attributes); + int keyLength, CK_ATTRIBUTE[] attrs) { + super(session, keyID, algorithm, keyLength, attrs); } + private synchronized void fetchValues() { token.ensureValid(); - if (y != null) { - return; - } - CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] { - new CK_ATTRIBUTE(CKA_VALUE), - new CK_ATTRIBUTE(CKA_PRIME), - new CK_ATTRIBUTE(CKA_BASE), - }; - fetchAttributes(attributes); - y = attributes[0].getBigInteger(); - params = new DHParameterSpec( - attributes[1].getBigInteger(), - attributes[2].getBigInteger() - ); + if (y != null) return; + + BigInteger[] res = fetchAttributesAsInts(new CK_ATTRIBUTE[] { + new CK_ATTRIBUTE(CKA_VALUE), + new CK_ATTRIBUTE(CKA_PRIME), + new CK_ATTRIBUTE(CKA_BASE), + }); + y = res[0]; + params = new DHParameterSpec(res[1], res[2]); } + public String getFormat() { token.ensureValid(); return "X.509"; } + synchronized byte[] getEncodedInternal() { token.ensureValid(); if (encoded == null) { @@ -1009,45 +1118,88 @@ abstract class P11Key implements Key, Length { } } - private static final class P11ECPrivateKey extends P11Key + static class P11ECPrivateKeyInternal extends P11PrivateKey { + + private static final long serialVersionUID = 1L; + + protected transient ECParameterSpec params; + + static P11ECPrivateKeyInternal of(Session session, long keyID, + String algorithm, int keyLength, CK_ATTRIBUTE[] attrs, + boolean keySensitive) { + if (keySensitive) { + return new P11ECPrivateKeyInternal(session, keyID, algorithm, + keyLength, attrs); + } else { + return new P11ECPrivateKey(session, keyID, algorithm, + keyLength, attrs); + } + } + + private P11ECPrivateKeyInternal(Session session, long keyID, + String algorithm, int keyLength, CK_ATTRIBUTE[] attrs) { + super(session, keyID, algorithm, keyLength, attrs); + } + + private synchronized void fetchValues() { + token.ensureValid(); + if (params != null) return; + + try { + byte[] paramBytes = fetchAttributes(new CK_ATTRIBUTE[] { + new CK_ATTRIBUTE(CKA_EC_PARAMS) + })[0].getByteArray(); + + params = P11ECKeyFactory.decodeParameters(paramBytes); + } catch (Exception e) { + throw new RuntimeException("Could not parse key values", e); + } + } + + protected ECParameterSpec getParams() { + fetchValues(); + return params; + } + } + + private static final class P11ECPrivateKey extends P11ECPrivateKeyInternal implements ECPrivateKey { private static final long serialVersionUID = -7786054399510515515L; - private BigInteger s; - @SuppressWarnings("serial") // Type of field is not Serializable - private ECParameterSpec params; - private byte[] encoded; + private transient BigInteger s; // params in P11ECPrivateKeyInternal + P11ECPrivateKey(Session session, long keyID, String algorithm, - int keyLength, CK_ATTRIBUTE[] attributes) { - super(PRIVATE, session, keyID, algorithm, keyLength, attributes); + int keyLength, CK_ATTRIBUTE[] attrs) { + super(session, keyID, algorithm, keyLength, attrs); } + private synchronized void fetchValues() { token.ensureValid(); - if (s != null) { - return; - } - CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] { + if (s != null) return; + + CK_ATTRIBUTE[] attrs = fetchAttributes(new CK_ATTRIBUTE[] { new CK_ATTRIBUTE(CKA_VALUE), - new CK_ATTRIBUTE(CKA_EC_PARAMS, params), - }; - fetchAttributes(attributes); - s = attributes[0].getBigInteger(); + new CK_ATTRIBUTE(CKA_EC_PARAMS), + }); + + s = attrs[0].getBigInteger(); try { params = P11ECKeyFactory.decodeParameters - (attributes[1].getByteArray()); + (attrs[1].getByteArray()); } catch (Exception e) { throw new RuntimeException("Could not parse key values", e); } } + public String getFormat() { token.ensureValid(); return "PKCS#8"; } + synchronized byte[] getEncodedInternal() { - token.ensureValid(); if (encoded == null) { - fetchValues(); try { + fetchValues(); Key key = ECUtil.generateECPrivateKey(s, params); encoded = key.getEncoded(); } catch (InvalidKeySpecException e) { @@ -1056,44 +1208,43 @@ abstract class P11Key implements Key, Length { } return encoded; } + public BigInteger getS() { fetchValues(); return s; } + public ECParameterSpec getParams() { fetchValues(); return params; } } - private static final class P11ECPublicKey extends P11Key + private static final class P11ECPublicKey extends P11PublicKey implements ECPublicKey { private static final long serialVersionUID = -6371481375154806089L; - @SuppressWarnings("serial") // Type of field is not Serializable - private ECPoint w; - @SuppressWarnings("serial") // Type of field is not Serializable - private ECParameterSpec params; - private byte[] encoded; + private transient ECPoint w; + private transient ECParameterSpec params; + P11ECPublicKey(Session session, long keyID, String algorithm, - int keyLength, CK_ATTRIBUTE[] attributes) { - super(PUBLIC, session, keyID, algorithm, keyLength, attributes); + int keyLength, CK_ATTRIBUTE[] attrs) { + super(session, keyID, algorithm, keyLength, attrs); } + private synchronized void fetchValues() { token.ensureValid(); - if (w != null) { - return; - } - CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] { + if (w != null) return; + + CK_ATTRIBUTE[] attrs = fetchAttributes(new CK_ATTRIBUTE[] { new CK_ATTRIBUTE(CKA_EC_POINT), new CK_ATTRIBUTE(CKA_EC_PARAMS), - }; - fetchAttributes(attributes); + }); try { params = P11ECKeyFactory.decodeParameters - (attributes[1].getByteArray()); - byte[] ecKey = attributes[0].getByteArray(); + (attrs[1].getByteArray()); + byte[] ecKey = attrs[0].getByteArray(); // Check whether the X9.63 encoding of an EC point is wrapped // in an ASN.1 OCTET STRING @@ -1115,10 +1266,12 @@ abstract class P11Key implements Key, Length { throw new RuntimeException("Could not parse key values", e); } } + public String getFormat() { token.ensureValid(); return "X.509"; } + synchronized byte[] getEncodedInternal() { token.ensureValid(); if (encoded == null) { @@ -1417,3 +1570,4 @@ final class SessionKeyRef extends PhantomReference { this.clear(); } } + diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyStore.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyStore.java index 0f7b97ebc87903556afb7c00462f75b241bef10d..585fb47ec5461492aa2fc7fdceb8ea538af6e5f2 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyStore.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyStore.java @@ -243,7 +243,7 @@ final class P11KeyStore extends KeyStoreSpi { pc.setPassword(password); // this clones the password if not null } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { if (password != null) { Arrays.fill(password, ' '); diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyWrapCipher.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyWrapCipher.java index 2385040d75c900ddbefbf8e8200a51c861c6c824..caf0bd298fe15611a99710ee3c47fe44968fbce7 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyWrapCipher.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyWrapCipher.java @@ -126,7 +126,7 @@ final class P11KeyWrapCipher extends CipherSpi { String[] algoParts = algorithm.split("/"); if (algoParts[0].startsWith("AES")) { int index = algoParts[0].indexOf('_'); - fixedKeySize = (index == -1? -1 : + fixedKeySize = (index == -1 ? -1 : // should be well-formed since we specify what we support Integer.parseInt(algoParts[0].substring(index+1)) >> 3); try { @@ -180,7 +180,7 @@ final class P11KeyWrapCipher extends CipherSpi { protected AlgorithmParameters engineGetParameters() { // KW and KWP uses but not require parameters, return the default // IV when no IV is supplied by caller - byte[] iv = (this.iv == null? type.defIv : this.iv); + byte[] iv = (this.iv == null ? type.defIv : this.iv); AlgorithmParameterSpec spec = new IvParameterSpec(iv); try { @@ -213,7 +213,7 @@ final class P11KeyWrapCipher extends CipherSpi { ("Only IvParameterSpec is supported"); } - byte[] ivValue = (params == null? null : + byte[] ivValue = (params == null ? null : ((IvParameterSpec)params).getIV()); implInit(opmode, key, ivValue, sr); @@ -285,7 +285,14 @@ final class P11KeyWrapCipher extends CipherSpi { } private void cancelOperation() { - // cancel operation by finishing it; avoid killSession as some + token.ensureValid(); + + if (P11Util.trySessionCancel(token, session, + (opmode == Cipher.ENCRYPT_MODE ? CKF_ENCRYPT : CKF_DECRYPT))) { + return; + } + + // cancel by finishing operations; avoid killSession as some // hardware vendors may require re-login byte[] in = dataBuffer.toByteArray(); int inLen = in.length; @@ -379,7 +386,7 @@ final class P11KeyWrapCipher extends CipherSpi { } else { result -= BLK_SIZE; // minus the leading block including the ICV } - return (result > 0? result : 0); + return (result > 0 ? result : 0); } // reset the states to the pre-initialized values @@ -654,7 +661,7 @@ final class P11KeyWrapCipher extends CipherSpi { P11Key tbwP11Key = null; if (!(tbwKey instanceof P11Key)) { try { - tbwP11Key = (tbwKey instanceof SecretKey? + tbwP11Key = (tbwKey instanceof SecretKey ? P11SecretKeyFactory.convertKey(token, tbwKey, tbwKey.getAlgorithm()) : P11KeyFactory.convertKey(token, tbwKey, diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Mac.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Mac.java index 0e86528bb5708ae4e1a6ebe355a9fc702ac824a3..97082eae850f61b76fc9166eabeb3ecb308ded5f 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Mac.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Mac.java @@ -147,7 +147,12 @@ final class P11Mac extends MacSpi { private void cancelOperation() { token.ensureValid(); - // cancel operation by finishing it; avoid killSession as some + + if (P11Util.trySessionCancel(token, session, CKF_SIGN)) { + return; + } + + // cancel by finishing operations; avoid killSession as some // hardware vendors may require re-login try { token.p11.C_SignFinal(session.id(), 0); diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11PSSSignature.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11PSSSignature.java index 88b7b9cd5e87eac329e562bbfae1d38408d49825..512bf521be79172b20aabaf17f04118cd436f1ac 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11PSSSignature.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11PSSSignature.java @@ -170,7 +170,7 @@ final class P11PSSSignature extends SignatureSpi { this.mechanism = new CK_MECHANISM(mechId); int idx = algorithm.indexOf("with"); // convert to stdName - this.mdAlg = (idx == -1? + this.mdAlg = (idx == -1 ? null : toStdName(algorithm.substring(0, idx))); switch ((int)mechId) { @@ -193,7 +193,7 @@ final class P11PSSSignature extends SignatureSpi { throw new NoSuchAlgorithmException("Unsupported algorithm: " + algorithm); } - this.md = (this.mdAlg == null? null : + this.md = (this.mdAlg == null ? null : MessageDigest.getInstance(this.mdAlg)); type = T_DIGEST; break; @@ -269,9 +269,16 @@ final class P11PSSSignature extends SignatureSpi { private void cancelOperation() { token.ensureValid(); + if (DEBUG) System.out.print("Cancelling operation"); - // cancel operation by finishing it; avoid killSession as some + if (P11Util.trySessionCancel(token, session, + (mode == M_SIGN ? CKF_SIGN : CKF_VERIFY))) { + if (DEBUG) System.out.println(" by C_SessionCancel"); + return; + } + + // cancel by finishing operations; avoid killSession call as some // hardware vendors may require re-login try { if (mode == M_SIGN) { @@ -280,7 +287,7 @@ final class P11PSSSignature extends SignatureSpi { token.p11.C_SignFinal(session.id(), 0); } else { byte[] digest = - (md == null? new byte[0] : md.digest()); + (md == null ? new byte[0] : md.digest()); if (DEBUG) System.out.println(" by C_Sign"); token.p11.C_Sign(session.id(), digest); } @@ -292,7 +299,7 @@ final class P11PSSSignature extends SignatureSpi { token.p11.C_VerifyFinal(session.id(), signature); } else { byte[] digest = - (md == null? new byte[0] : md.digest()); + (md == null ? new byte[0] : md.digest()); if (DEBUG) System.out.println(" by C_Verify"); token.p11.C_Verify(session.id(), digest, signature); } diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11RSACipher.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11RSACipher.java index 869b77d4a638238965d873c851f991d980fe2495..1506918da962033128cdc98136dadefce6062352 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11RSACipher.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11RSACipher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,7 @@ import javax.crypto.spec.*; import static sun.security.pkcs11.TemplateManager.*; import sun.security.pkcs11.wrapper.*; import static sun.security.pkcs11.wrapper.PKCS11Constants.*; +import static sun.security.pkcs11.wrapper.PKCS11Exception.RV.*; import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec; import sun.security.util.KeyUtil; @@ -266,7 +267,21 @@ final class P11RSACipher extends CipherSpi { // state variables such as "initialized" private void cancelOperation() { token.ensureValid(); - // cancel operation by finishing it; avoid killSession as some + + long flags = switch(mode) { + case MODE_ENCRYPT -> CKF_ENCRYPT; + case MODE_DECRYPT -> CKF_DECRYPT; + case MODE_SIGN -> CKF_SIGN; + case MODE_VERIFY -> CKF_VERIFY; + default -> { + throw new AssertionError("Unexpected value: " + mode); + } + }; + if (P11Util.trySessionCancel(token, session, flags)) { + return; + } + + // cancel by finishing operations; avoid killSession as some // hardware vendors may require re-login try { PKCS11 p11 = token.p11; diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Signature.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Signature.java index 7c1714356407e4b0162c4e3530ce1ffabd16a7cf..c27a3f4f02e77d5877a709176f546c9620308209 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Signature.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Signature.java @@ -119,6 +119,9 @@ final class P11Signature extends SignatureSpi { // key instance used, if init*() was called private P11Key p11Key; + // signature length expected or 0 for unknown + private int sigLen; + // message digest, if we do the digesting ourselves private final MessageDigest md; @@ -280,12 +283,18 @@ final class P11Signature extends SignatureSpi { private void cancelOperation() { token.ensureValid(); - // cancel operation by finishing it; avoid killSession as some + + if (P11Util.trySessionCancel(token, session, + (mode == M_SIGN ? CKF_SIGN : CKF_VERIFY))) { + return; + } + + // cancel by finishing operations; avoid killSession call as some // hardware vendors may require re-login try { if (mode == M_SIGN) { if (type == T_UPDATE) { - token.p11.C_SignFinal(session.id(), 0); + token.p11.C_SignFinal(session.id(), sigLen); } else { byte[] digest; if (type == T_DIGEST) { @@ -296,12 +305,7 @@ final class P11Signature extends SignatureSpi { token.p11.C_Sign(session.id(), digest); } } else { // M_VERIFY - byte[] signature; - if (mechanism == CKM_DSA) { - signature = new byte[64]; // assume N = 256 - } else { - signature = new byte[(p11Key.length() + 7) >> 3]; - } + byte[] signature = new byte[sigLen]; if (type == T_UPDATE) { token.p11.C_VerifyFinal(session.id(), signature); } else { @@ -317,9 +321,9 @@ final class P11Signature extends SignatureSpi { } catch (PKCS11Exception e) { if (e.match(CKR_OPERATION_NOT_INITIALIZED)) { // Cancel Operation may be invoked after an error on a PKCS#11 - // call. If the operation inside the token was already cancelled, - // do not fail here. This is part of a defensive mechanism for - // PKCS#11 libraries that do not strictly follow the standard. + // call. If the operation was already cancelled, do not fail + // here. This is part of a defensive mechanism for PKCS#11 + // libraries that do not strictly follow the standard. return; } if (mode == M_VERIFY) { @@ -372,6 +376,15 @@ final class P11Signature extends SignatureSpi { md.reset(); } } + sigLen = 0; + if ("DSA".equals(p11Key.getAlgorithm())) { + if (p11Key instanceof P11Key.P11DSAPrivateKeyInternal) { + sigLen = ((P11Key.P11DSAPrivateKeyInternal)p11Key).getParams() + .getQ().bitLength() >> 2; + } else if (p11Key instanceof DSAKey) { + sigLen = ((DSAKey)p11Key).getParams().getQ().bitLength() >> 2; + } + } initialized = true; } @@ -617,7 +630,7 @@ final class P11Signature extends SignatureSpi { try { byte[] signature; if (type == T_UPDATE) { - signature = token.p11.C_SignFinal(session.id(), 0); + signature = token.p11.C_SignFinal(session.id(), sigLen); } else { byte[] digest; if (type == T_DIGEST) { @@ -684,7 +697,7 @@ final class P11Signature extends SignatureSpi { try { if (!p1363Format) { if (keyAlgorithm.equals("DSA")) { - signature = asn1ToDSA(signature); + signature = asn1ToDSA(signature, sigLen); } else if (keyAlgorithm.equals("EC")) { signature = asn1ToECDSA(signature); } @@ -801,7 +814,8 @@ final class P11Signature extends SignatureSpi { } } - private static byte[] asn1ToDSA(byte[] sig) throws SignatureException { + private static byte[] asn1ToDSA(byte[] sig, int sigLen) + throws SignatureException { try { // Enforce strict DER checking for signatures DerInputStream in = new DerInputStream(sig, 0, sig.length, false); @@ -816,8 +830,8 @@ final class P11Signature extends SignatureSpi { BigInteger r = values[0].getPositiveBigInteger(); BigInteger s = values[1].getPositiveBigInteger(); - byte[] br = toByteArray(r, 20); - byte[] bs = toByteArray(s, 20); + byte[] br = toByteArray(r, sigLen/2); + byte[] bs = toByteArray(s, sigLen/2); if ((br == null) || (bs == null)) { throw new SignatureException("Out of range value for R or S"); } @@ -829,7 +843,7 @@ final class P11Signature extends SignatureSpi { } } - private byte[] asn1ToECDSA(byte[] sig) throws SignatureException { + private static byte[] asn1ToECDSA(byte[] sig) throws SignatureException { try { // Enforce strict DER checking for signatures DerInputStream in = new DerInputStream(sig, 0, sig.length, false); @@ -909,3 +923,4 @@ final class P11Signature extends SignatureSpi { return null; } } + diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Util.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Util.java index 262cfc062adae7b687e86ae3e2d9a58e95823798..256c2f965689809d20cc9ee34d34c71760502249 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Util.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Util.java @@ -28,6 +28,9 @@ package sun.security.pkcs11; import java.math.BigInteger; import java.security.*; +import sun.security.pkcs11.wrapper.PKCS11Exception; +import static sun.security.pkcs11.wrapper.PKCS11Exception.RV.*; + /** * Collection of static utility methods. * @@ -187,4 +190,22 @@ public final class P11Util { return sb.toString(); } + // returns true if successfully cancelled + static boolean trySessionCancel(Token token, Session session, long flags) + throws ProviderException { + if (token.p11.getVersion().major == 3) { + try { + token.p11.C_SessionCancel(session.id(), flags); + return true; + } catch (PKCS11Exception e) { + // return false for CKR_OPERATION_CANCEL_FAILED, so callers + // can cancel in the pre v3.0 way, i.e. by finishing off the + // current operation + if (!e.match(CKR_OPERATION_CANCEL_FAILED)) { + throw new ProviderException("cancel failed", e); + } + } + } + return false; + } } diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java index e86d54963d36c0a23c3f7a511bf24651a79cfadd..9cdbdfa9d6b920949e5a3b50367d9c5072293c8c 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java @@ -150,7 +150,7 @@ public final class SunPKCS11 extends AuthProvider { this.config = c; if (debug != null) { - System.out.println("SunPKCS11 loading " + config.getFileName()); + debug.println("SunPKCS11 loading " + config.getFileName()); } String library = config.getLibrary(); @@ -176,7 +176,6 @@ public final class SunPKCS11 extends AuthProvider { // switch to using the NSS trust attributes for trusted certs // (KeyStore). // - if (useSecmod) { // note: Config ensures library/slot/slotListIndex not specified // in secmod mode. @@ -328,8 +327,7 @@ public final class SunPKCS11 extends AuthProvider { initArgs.flags = CKF_OS_LOCKING_OK; PKCS11 tmpPKCS11; try { - tmpPKCS11 = PKCS11.getInstance( - library, functionList, initArgs, + tmpPKCS11 = PKCS11.getInstance(library, functionList, initArgs, config.getOmitInitialize()); } catch (PKCS11Exception e) { if (debug != null) { @@ -345,18 +343,18 @@ public final class SunPKCS11 extends AuthProvider { } else { initArgs.flags = 0; } - tmpPKCS11 = PKCS11.getInstance(library, - functionList, initArgs, config.getOmitInitialize()); + tmpPKCS11 = PKCS11.getInstance(library, functionList, initArgs, + config.getOmitInitialize()); } p11 = tmpPKCS11; - CK_INFO p11Info = p11.C_GetInfo(); - if (p11Info.cryptokiVersion.major < 2) { + if (p11.getVersion().major < 2) { throw new ProviderException("Only PKCS#11 v2.0 and later " - + "supported, library version is v" + p11Info.cryptokiVersion); + + "supported, library version is v" + p11.getVersion()); } boolean showInfo = config.getShowInfo(); if (showInfo) { + CK_INFO p11Info = p11.C_GetInfo(); System.out.println("Information for provider " + getName()); System.out.println("Library info:"); System.out.println(p11Info); @@ -1482,12 +1480,10 @@ public final class SunPKCS11 extends AuthProvider { } // get the pin if necessary - char[] pin = null; if ((token.tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) == 0) { // get password - CallbackHandler myHandler = getCallbackHandler(handler); if (myHandler == null) { throw new LoginException @@ -1503,6 +1499,7 @@ public final class SunPKCS11 extends AuthProvider { PasswordCallback pcall = new PasswordCallback(form.format(source), false); Callback[] callbacks = { pcall }; + try { myHandler.handle(callbacks); } catch (Exception e) { @@ -1522,13 +1519,12 @@ public final class SunPKCS11 extends AuthProvider { } // perform token login - Session session = null; try { session = token.getOpSession(); - // pin is NULL if using CKF_PROTECTED_AUTHENTICATION_PATH p11.C_Login(session.id(), CKU_USER, pin); + if (debug != null) { debug.println("login succeeded"); } diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_MECHANISM.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_MECHANISM.java index db5474fa888322d4d75adba74dd7689cc222b1cb..0c9ebb289c1590fdbaf4d40e1ce71de6a1a11e80 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_MECHANISM.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_MECHANISM.java @@ -164,7 +164,6 @@ public class CK_MECHANISM { // CK_MECHANISM(long) constructor and setParameter(CK_RSA_PKCS_PSS_PARAMS) // methods instead of creating yet another constructor public void setParameter(CK_RSA_PKCS_PSS_PARAMS params) { - assert(this.mechanism == CKM_RSA_PKCS_PSS); assert(params != null); if (this.pParameter != null && this.pParameter.equals(params)) { return; diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11.java index 2b2f3d0ebd41d1163ae81f6018823db08a32b27c..f87690bc24f96de870115022f843eee0cd74b35c 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11.java @@ -110,7 +110,7 @@ public class PKCS11 { * e.g. pk2priv.dll. */ private final String pkcs11ModulePath; - + private final CK_VERSION version; private long pNativeData; /** @@ -141,13 +141,30 @@ public class PKCS11 { * path, if the driver is not in the system's search path. * * @param pkcs11ModulePath the PKCS#11 library path + * @param functionList the method name for retrieving the PKCS#11 + * function list; may be null if not set in config file * @preconditions (pkcs11ModulePath <> null) * @postconditions */ - PKCS11(String pkcs11ModulePath, String functionListName) + PKCS11(String pkcs11ModulePath, String functionList) throws IOException { - connect(pkcs11ModulePath, functionListName); + this.version = connect(pkcs11ModulePath, functionList); this.pkcs11ModulePath = pkcs11ModulePath; + // bug in native PKCS#11 lib; workaround it by calling C_GetInfo() + // and get cryptoki version from there + if (this.version.major != 2 && this.version.major != 3) { + try { + CK_INFO p11Info = C_GetInfo(); + this.version.major = p11Info.cryptokiVersion.major; + this.version.minor = p11Info.cryptokiVersion.minor; + } catch (PKCS11Exception e) { + // give up; just use what is returned by connect() + } + } + } + + public CK_VERSION getVersion() { + return version; } public static synchronized PKCS11 getInstance(String pkcs11ModulePath, @@ -186,11 +203,14 @@ public class PKCS11 { * native part. * * @param pkcs11ModulePath The PKCS#11 library path. + * @param functionList the method name for retrieving the PKCS#11 + * function list; may be null if not set in config file + * @return the actual PKCS11 interface version * @preconditions (pkcs11ModulePath <> null) * @postconditions */ - private native void connect(String pkcs11ModulePath, String functionListName) - throws IOException; + private native CK_VERSION connect(String pkcs11ModulePath, + String functionList) throws IOException; /** * Disconnects the PKCS#11 library from this object. After calling this @@ -463,6 +483,20 @@ public class PKCS11 { public native CK_SESSION_INFO C_GetSessionInfo(long hSession) throws PKCS11Exception; + /** + * C_SessionCancel terminates active session based operations. + * (Session management) (New in PKCS#11 v3.0) + * + * @param hSession the session's handle + * (PKCS#11 param: CK_SESSION_HANDLE hSession) + * @param flags indicates the operations to cancel. + * (PKCS#11 param: CK_FLAGS flags) + * @exception PKCS11Exception If function returns other value than CKR_OK. + * @preconditions + * @postconditions + */ + public native void C_SessionCancel(long hSession, long flags) + throws PKCS11Exception; /** * C_GetOperationState obtains the state of the cryptographic operation @@ -521,6 +555,24 @@ public class PKCS11 { public native void C_Login(long hSession, long userType, char[] pPin) throws PKCS11Exception; + ///** + // * C_LoginUser logs a user into a token. (New in PKCS#11 v3.0) + // * (Session management) + // * + // * @param hSession the session's handle + // * (PKCS#11 param: CK_SESSION_HANDLE hSession) + // * @param userType the user type + // * (PKCS#11 param: CK_USER_TYPE userType) + // * @param pPin the user's PIN and the length of the PIN + // * (PKCS#11 param: CK_CHAR_PTR pPin, CK_ULONG ulPinLen) + // * @param pUsername the user name and the length of the user name + // * (PKCS#11 param: CK_CHAR_PTR pUsername, CK_ULONG ulUsernameLen) + // * @exception PKCS11Exception If function returns other value than CKR_OK. + // * @preconditions + // * @postconditions + // */ + //public native void C_LoginUser(long hSession, long userType, char[] pPin, + // String pUsername) throws PKCS11Exception; /** * C_Logout logs a user out from a token. @@ -807,7 +859,6 @@ public class PKCS11 { public native int C_EncryptFinal(long hSession, long directOut, byte[] out, int outOfs, int outLen) throws PKCS11Exception; - /** * C_DecryptInit initializes a decryption operation. * (Encryption and decryption) @@ -902,8 +953,6 @@ public class PKCS11 { public native int C_DecryptFinal(long hSession, long directOut, byte[] out, int outOfs, int outLen) throws PKCS11Exception; - - /* ***************************************************************************** * Message digesting ******************************************************************************/ @@ -1615,7 +1664,7 @@ public class PKCS11 { * * @exception Throwable If finalization fails. */ - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { disconnect(); } @@ -1624,9 +1673,9 @@ public class PKCS11 { // parent. Used for tokens that only support single threaded access static class SynchronizedPKCS11 extends PKCS11 { - SynchronizedPKCS11(String pkcs11ModulePath, String functionListName) + SynchronizedPKCS11(String pkcs11ModulePath, String functionList) throws IOException { - super(pkcs11ModulePath, functionListName); + super(pkcs11ModulePath, functionList); } synchronized void C_Initialize(Object pInitArgs) throws PKCS11Exception { @@ -1682,11 +1731,22 @@ static class SynchronizedPKCS11 extends PKCS11 { return super.C_GetSessionInfo(hSession); } - public synchronized void C_Login(long hSession, long userType, char[] pPin) + public synchronized void C_SessionCancel(long hSession, long flags) throws PKCS11Exception { + super.C_SessionCancel(hSession, flags); + } + + public synchronized void C_Login(long hSession, long userType, + char[] pPin) throws PKCS11Exception { super.C_Login(hSession, userType, pPin); } + //public synchronized void C_LoginUser(long hSession, long userType, + // char[] pPin, String pUsername) + // throws PKCS11Exception { + // super.C_LoginUser(hSession, userType, pPin, pUsername); + //} + public synchronized void C_Logout(long hSession) throws PKCS11Exception { super.C_Logout(hSession); } diff --git a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_sessmgmt.c b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_sessmgmt.c index b06d397b09e1b8c89e6f43e0f5b1e58f91b78487..5209c5bbf78bc3e966be36f367bbf97fd4d11471 100644 --- a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_sessmgmt.c +++ b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_sessmgmt.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. */ /* Copyright (c) 2002 Graz University of Technology. All rights reserved. @@ -272,6 +272,33 @@ JNIEXPORT jobject JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1GetSessionI } #endif +#ifdef P11_ENABLE_C_SESSIONCANCEL +/* + * Class: sun_security_pkcs11_wrapper_PKCS11 + * Method: C_SessionCancel + * Signature: (JJ)V + * Parametermapping: *PKCS11* + * @param jlong jSessionHandle CK_SESSION_HANDLE hSession + * @param jlong jFlags CK_FLAGS flags + */ +JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1SessionCancel + (JNIEnv *env, jobject obj, jlong jSessionHandle, jlong jFlags) +{ + CK_SESSION_HANDLE ckSessionHandle; + CK_RV rv; + + CK_FUNCTION_LIST_3_0_PTR ckpFunctions30 = getFunctionList30(env, obj); + if (ckpFunctions30 == NULL) { return; } + + ckSessionHandle = jLongToCKULong(jSessionHandle); + + rv = (*ckpFunctions30->C_SessionCancel)(ckSessionHandle, + jLongToCKULong(jFlags)); + + ckAssertReturnValueOK(env, rv); +} +#endif + #ifdef P11_ENABLE_C_GETOPERATIONSTATE /* * Class: sun_security_pkcs11_wrapper_PKCS11 @@ -351,7 +378,7 @@ JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1SetOperationSt free(ckpState); - if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; } + ckAssertReturnValueOK(env, rv); } #endif @@ -367,28 +394,83 @@ JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1SetOperationSt * CK_ULONG ulPinLen */ JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1Login - (JNIEnv *env, jobject obj, jlong jSessionHandle, jlong jUserType, jcharArray jPin) + (JNIEnv *env, jobject obj, jlong jSessionHandle, jlong jUserType, + jcharArray jPin) { CK_SESSION_HANDLE ckSessionHandle; CK_USER_TYPE ckUserType; CK_CHAR_PTR ckpPinArray = NULL_PTR; CK_ULONG ckPinLength; CK_RV rv; + CK_FUNCTION_LIST_PTR ckpFunctions; - CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj); - if (ckpFunctions == NULL) { return; } + ckpFunctions = getFunctionList(env, obj); + + if (ckpFunctions == NULL) { + return; + } ckSessionHandle = jLongToCKULong(jSessionHandle); ckUserType = jLongToCKULong(jUserType); jCharArrayToCKCharArray(env, jPin, &ckpPinArray, &ckPinLength); if ((*env)->ExceptionCheck(env)) { return; } - rv = (*ckpFunctions->C_Login)(ckSessionHandle, ckUserType, ckpPinArray, ckPinLength); + rv = (*ckpFunctions->C_Login)(ckSessionHandle, ckUserType, ckpPinArray, + ckPinLength); + free(ckpPinArray); + + ckAssertReturnValueOK(env, rv); +} +#endif + +#ifdef P11_ENABLE_C_LOGINUSER +/* + * Class: sun_security_pkcs11_wrapper_PKCS11 + * Method: C_LoginUser + * Signature: (JJ[C;Ljava/lang/String;)V + * Parametermapping: *PKCS11* + * @param jlong jSessionHandle CK_SESSION_HANDLE hSession + * @param jlong jUserType CK_USER_TYPE userType + * @param jcharArray jPin CK_CHAR_PTR pPin + * CK_ULONG ulPinLen + * @param jstring jUsername CK_CHAR_PTR pUsername + * CK_ULONG ulUsernameLen + */ +JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1LoginUser + (JNIEnv *env, jobject obj, jlong jSessionHandle, jlong jUserType, + jcharArray jPin, jstring jUsername) +{ + CK_SESSION_HANDLE ckSessionHandle; + CK_USER_TYPE ckUserType; + CK_CHAR_PTR ckpPinArray = NULL_PTR; + CK_ULONG ckPinLength; + CK_CHAR_PTR ckpUsername = NULL_PTR; + CK_ULONG ckUsernameLength; + CK_RV rv; + CK_FUNCTION_LIST_3_0_PTR ckpFunctions30; + + ckpFunctions30 = getFunctionList30(env, obj); + + ckSessionHandle = jLongToCKULong(jSessionHandle); + ckUserType = jLongToCKULong(jUserType); + jCharArrayToCKCharArray(env, jPin, &ckpPinArray, &ckPinLength); + if ((*env)->ExceptionCheck(env)) { return; } + jStringToCKUTF8CharArray(env, jUsername, &ckpUsername, + &ckUsernameLength); + if ((*env)->ExceptionCheck(env)) { return; } + + if (ckpFunctions30 == NULL) { + return; + } + rv = (*ckpFunctions30->C_LoginUser)(ckSessionHandle, ckUserType, + ckpPinArray, ckPinLength, ckpUsername, ckUsernameLength); free(ckpPinArray); + free(ckpUsername); - if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; } + ckAssertReturnValueOK(env, rv); } + #endif #ifdef P11_ENABLE_C_LOGOUT @@ -411,7 +493,7 @@ JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1Logout ckSessionHandle = jLongToCKULong(jSessionHandle); rv = (*ckpFunctions->C_Logout)(ckSessionHandle); - if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; } + ckAssertReturnValueOK(env, rv); } #endif diff --git a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_util.c b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_util.c index 520bd52a2cd6c1fda7290073b00b21f1810074a6..2920707a2542d710e4ee384714f31a9b2c5a59bb 100644 --- a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_util.c +++ b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_util.c @@ -136,6 +136,20 @@ CK_FUNCTION_LIST_PTR getFunctionList(JNIEnv *env, jobject pkcs11Implementation) return ckpFunctions; } +CK_FUNCTION_LIST_3_0_PTR getFunctionList30(JNIEnv *env, jobject + pkcs11Implementation) { + ModuleData *moduleData; + CK_FUNCTION_LIST_3_0_PTR ckpFunctions30; + + moduleData = getModuleEntry(env, pkcs11Implementation); + if (moduleData == NULL) { + throwDisconnectedRuntimeException(env); + return NULL; + } + ckpFunctions30 = moduleData->ckFunctionList30Ptr; + return ckpFunctions30; +} + /* * Returns 1, if the given pkcs11Implementation is in the list. diff --git a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11wrapper.h b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11wrapper.h index eb6d01b9e47c8a6bc265722c858833684eb54b9f..c2b6f3d94b5076b9e699802988e6a684c6d99e15 100644 --- a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11wrapper.h +++ b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11wrapper.h @@ -100,9 +100,11 @@ #define P11_ENABLE_C_CLOSESESSION #undef P11_ENABLE_C_CLOSEALLSESSIONS #define P11_ENABLE_C_GETSESSIONINFO +#define P11_ENABLE_C_SESSIONCANCEL #define P11_ENABLE_C_GETOPERATIONSTATE #define P11_ENABLE_C_SETOPERATIONSTATE #define P11_ENABLE_C_LOGIN +//#define P11_ENABLE_C_LOGINUSER #define P11_ENABLE_C_LOGOUT #define P11_ENABLE_C_CREATEOBJECT #define P11_ENABLE_C_COPYOBJECT @@ -209,17 +211,21 @@ //#define TRACE0d(s) { printf(s); fflush(stdout); } //#define TRACE1d(s, p1) { printf(s, p1); fflush(stdout); } //#define TRACE2d(s, p1, p2) { printf(s, p1, p2); fflush(stdout); } +//#define TRACE3d(s, p1, p2, p3) { printf(s, p1, p2, p3); fflush(stdout); } +//#define TRACE4d(s, p1, p2, p3, p4) { printf(s, p1, p2, p3, p4); fflush(stdout); } #ifdef P11_DEBUG #define TRACE0(s) { printf(s); fflush(stdout); } #define TRACE1(s, p1) { printf(s, p1); fflush(stdout); } #define TRACE2(s, p1, p2) { printf(s, p1, p2); fflush(stdout); } #define TRACE3(s, p1, p2, p3) { printf(s, p1, p2, p3); fflush(stdout); } +#define TRACE4(s, p1, p2, p3, p4) { printf(s, p1, p2, p3, p4); fflush(stdout); } #else #define TRACE0(s) #define TRACE1(s, p1) #define TRACE2(s, p1, p2) #define TRACE3(s, p1, p2, p3) +#define TRACE4(s, p1, p2, p3, p4) #define TRACE_INTEND #define TRACE_UNINTEND #endif @@ -412,6 +418,8 @@ CK_RV callJUnlockMutex(CK_VOID_PTR pMutex); void putModuleEntry(JNIEnv *env, jobject pkcs11Implementation, ModuleData *moduleData); ModuleData * removeModuleEntry(JNIEnv *env, jobject pkcs11Implementation); CK_FUNCTION_LIST_PTR getFunctionList(JNIEnv *env, jobject pkcs11Implementation); +CK_FUNCTION_LIST_3_0_PTR getFunctionList30(JNIEnv *env, jobject + pkcs11Implementation); /* A structure to encapsulate the required data for a Notify callback */ struct NotifyEncapsulation { diff --git a/src/jdk.crypto.cryptoki/unix/native/libj2pkcs11/p11_md.c b/src/jdk.crypto.cryptoki/unix/native/libj2pkcs11/p11_md.c index 0105a9873b56f25259c288ed5902b91e5be00500..6cae296e8d4dbd330a7ccec7b5270a69b8ae0e3b 100644 --- a/src/jdk.crypto.cryptoki/unix/native/libj2pkcs11/p11_md.c +++ b/src/jdk.crypto.cryptoki/unix/native/libj2pkcs11/p11_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. */ /* Copyright (c) 2002 Graz University of Technology. All rights reserved. @@ -72,26 +72,34 @@ /* * Class: sun_security_pkcs11_wrapper_PKCS11 * Method: connect - * Signature: (Ljava/lang/String;)V + * Signature: (Ljava/lang/String;)Lsun/security/pkcs11/wrapper/CK_VERSION; */ -JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_connect - (JNIEnv *env, jobject obj, jstring jPkcs11ModulePath, jstring jGetFunctionList) -{ +JNIEXPORT jobject JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_connect + (JNIEnv *env, jobject obj, jstring jPkcs11ModulePath, + jstring jGetFunctionList) { + void *hModule; char *error; - CK_C_GetFunctionList C_GetFunctionList=NULL; + int i; + CK_ULONG ulCount = 0; + CK_C_GetInterfaceList C_GetInterfaceList = NULL; + CK_INTERFACE_PTR iList = NULL; + CK_C_GetInterface C_GetInterface = NULL; + CK_INTERFACE_PTR interface = NULL; + CK_C_GetFunctionList C_GetFunctionList = NULL; CK_RV rv; - ModuleData *moduleData; + ModuleData *moduleData = NULL; jobject globalPKCS11ImplementationReference; char *systemErrorMessage; char *exceptionMessage; - const char *getFunctionListStr; + const char *getFunctionListStr = NULL; - const char *libraryNameStr = (*env)->GetStringUTFChars(env, jPkcs11ModulePath, 0); + const char *libraryNameStr = (*env)->GetStringUTFChars(env, + jPkcs11ModulePath, 0); if (libraryNameStr == NULL) { - return; + return NULL; } - TRACE1("DEBUG: connect to PKCS#11 module: %s ... ", libraryNameStr); + TRACE1("Connect: connect to PKCS#11 module: %s ... ", libraryNameStr); /* * Load the PKCS #11 DLL @@ -108,39 +116,92 @@ JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_connect exceptionMessage = (char *) malloc(sizeof(char) * (strlen(systemErrorMessage) + strlen(libraryNameStr) + 1)); if (exceptionMessage == NULL) { throwOutOfMemoryError(env, 0); - (*env)->ReleaseStringUTFChars(env, jPkcs11ModulePath, libraryNameStr); - return; + goto cleanup; } strcpy(exceptionMessage, systemErrorMessage); strcat(exceptionMessage, libraryNameStr); throwIOException(env, exceptionMessage); - (*env)->ReleaseStringUTFChars(env, jPkcs11ModulePath, libraryNameStr); free(exceptionMessage); - return; + goto cleanup; } - (*env)->ReleaseStringUTFChars(env, jPkcs11ModulePath, libraryNameStr); - /* - * Get function pointer to C_GetFunctionList - */ - dlerror(); /* clear any old error message not fetched */ - // with the old JAR file jGetFunctionList is null, temporarily check for that + // clear any old error message not fetched + dlerror(); + +#ifdef DEBUG + C_GetInterfaceList = (CK_C_GetInterfaceList) dlsym(hModule, + "C_GetInterfaceList"); + if (C_GetInterfaceList != NULL) { + TRACE0("Connect: Found C_GetInterfaceList func\n"); + rv = (C_GetInterfaceList)(NULL, &ulCount); + if (rv == CKR_OK) { + TRACE1("Connect: interface list size %ld \n", ulCount); + // retrieve available interfaces and report their info + iList = (CK_INTERFACE_PTR) + malloc(ulCount*sizeof(CK_INTERFACE)); + rv = C_GetInterfaceList(iList, &ulCount); + if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { + TRACE0("Connect: error polling interface list\n"); + goto cleanup; + } + for (i=0; i < (int)ulCount; i++) { + TRACE4("Connect: name %s, version %d.%d, flags 0x%lX\n", + iList[i].pInterfaceName, + ((CK_VERSION *)iList[i].pFunctionList)->major, + ((CK_VERSION *)iList[i].pFunctionList)->minor, + iList[i].flags); + } + } else { + TRACE0("Connect: error polling interface list size\n"); + } + } else { + TRACE0("Connect: No C_GetInterfaceList func\n"); + } +#endif + if (jGetFunctionList != NULL) { - getFunctionListStr = (*env)->GetStringUTFChars(env, jGetFunctionList, 0); + getFunctionListStr = (*env)->GetStringUTFChars(env, + jGetFunctionList, 0); if (getFunctionListStr == NULL) { - return; + goto cleanup; } - C_GetFunctionList = (CK_C_GetFunctionList) dlsym(hModule, getFunctionListStr); - (*env)->ReleaseStringUTFChars(env, jGetFunctionList, getFunctionListStr); - } - if (C_GetFunctionList == NULL) { - throwIOException(env, "ERROR: C_GetFunctionList == NULL"); - return; - } else if ( (systemErrorMessage = dlerror()) != NULL ){ - throwIOException(env, systemErrorMessage); - return; + C_GetFunctionList = (CK_C_GetFunctionList) dlsym(hModule, + getFunctionListStr); + if ((systemErrorMessage = dlerror()) != NULL){ + throwIOException(env, systemErrorMessage); + goto cleanup; + } + if (C_GetFunctionList == NULL) { + TRACE1("Connect: No %s func\n", getFunctionListStr); + throwIOException(env, "ERROR: C_GetFunctionList == NULL"); + goto cleanup; + } + TRACE1("Connect: Found %s func\n", getFunctionListStr); + } else { + // if none specified, then we try 3.0 API first before trying 2.40 + C_GetInterface = (CK_C_GetInterface) dlsym(hModule, "C_GetInterface"); + if ((C_GetInterface != NULL) && (dlerror() == NULL)) { + TRACE0("Connect: Found C_GetInterface func\n"); + rv = (C_GetInterface)(NULL, NULL, &interface, 0L); + if (ckAssertReturnValueOK(env, rv) == CK_ASSERT_OK) { + goto setModuleData; + } + } + C_GetFunctionList = (CK_C_GetFunctionList) dlsym(hModule, + "C_GetFunctionList"); + if ((systemErrorMessage = dlerror()) != NULL){ + throwIOException(env, systemErrorMessage); + goto cleanup; + } + if (C_GetFunctionList == NULL) { + TRACE0("Connect: No C_GetFunctionList func\n"); + throwIOException(env, "ERROR: C_GetFunctionList == NULL"); + goto cleanup; + } + TRACE0("Connect: Found C_GetFunctionList func\n"); } +setModuleData: /* * Get function pointers to all PKCS #11 functions */ @@ -148,19 +209,56 @@ JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_connect if (moduleData == NULL) { dlclose(hModule); throwOutOfMemoryError(env, 0); - return; + goto cleanup; } moduleData->hModule = hModule; moduleData->applicationMutexHandler = NULL; - rv = (C_GetFunctionList)(&(moduleData->ckFunctionListPtr)); + if (C_GetFunctionList != NULL) { + rv = (C_GetFunctionList)(&(moduleData->ckFunctionListPtr)); + if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { + goto cleanup; + } + } else if (interface != NULL) { + moduleData->ckFunctionListPtr = interface->pFunctionList; + if (((CK_VERSION *)moduleData->ckFunctionListPtr)->major == 3) { + moduleData->ckFunctionList30Ptr = interface->pFunctionList; + } + } else { + // should never happen + throwIOException(env, "ERROR: No function list ptr found"); + goto cleanup; + } + if (((CK_VERSION *)moduleData->ckFunctionListPtr)->major == 3) { + moduleData->ckFunctionList30Ptr = interface->pFunctionList; + } else { + moduleData->ckFunctionList30Ptr = NULL; + } + + TRACE2("Connect: FunctionListPtr version = %d.%d\n", + ((CK_VERSION *)moduleData->ckFunctionListPtr)->major, + ((CK_VERSION *)moduleData->ckFunctionListPtr)->minor); + globalPKCS11ImplementationReference = (*env)->NewGlobalRef(env, obj); putModuleEntry(env, globalPKCS11ImplementationReference, moduleData); - TRACE0("FINISHED\n"); - - if(ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; } +cleanup: + if (jPkcs11ModulePath != NULL && libraryNameStr != NULL) { + (*env)->ReleaseStringUTFChars(env, jPkcs11ModulePath, libraryNameStr); + } + if (jGetFunctionList != NULL && getFunctionListStr != NULL) { + (*env)->ReleaseStringUTFChars(env, jGetFunctionList, + getFunctionListStr); + } + TRACE0("Connect: FINISHED\n"); + if (moduleData != NULL) { + return ckVersionPtrToJVersion(env, + (CK_VERSION *)moduleData->ckFunctionListPtr); + } else { + return NULL; + } } + /* * Class: sun_security_pkcs11_wrapper_PKCS11 * Method: disconnect diff --git a/src/jdk.crypto.cryptoki/unix/native/libj2pkcs11/p11_md.h b/src/jdk.crypto.cryptoki/unix/native/libj2pkcs11/p11_md.h index 0d8cb36337495b634a8825cc1ed9300c1eb30a74..676e3ab5d4c6d4614a26ae44240b0ac28a9de5cc 100644 --- a/src/jdk.crypto.cryptoki/unix/native/libj2pkcs11/p11_md.h +++ b/src/jdk.crypto.cryptoki/unix/native/libj2pkcs11/p11_md.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. */ /* @@ -83,8 +83,9 @@ struct ModuleData { /* the module (DLL or shared library) handle */ void *hModule; - /* The pointer to the PKCS#11 functions of this module. */ + /* The pointers to the PKCS#11 functions of this module. */ CK_FUNCTION_LIST_PTR ckFunctionListPtr; + CK_FUNCTION_LIST_3_0_PTR ckFunctionList30Ptr; /* Reference to the object to use for mutex handling. NULL, if not used. */ jobject applicationMutexHandler; diff --git a/src/jdk.crypto.cryptoki/windows/native/libj2pkcs11/p11_md.c b/src/jdk.crypto.cryptoki/windows/native/libj2pkcs11/p11_md.c index 145ad7f5693127fede0c576c7f03b58f7492b322..ea005664dff91ef61c4ab32a6977de1a06312cc4 100644 --- a/src/jdk.crypto.cryptoki/windows/native/libj2pkcs11/p11_md.c +++ b/src/jdk.crypto.cryptoki/windows/native/libj2pkcs11/p11_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. */ /* Copyright (c) 2002 Graz University of Technology. All rights reserved. @@ -72,16 +72,22 @@ /* * Class: sun_security_pkcs11_wrapper_PKCS11 * Method: connect - * Signature: (Ljava/lang/String;)V + * Signature: (Ljava/lang/String;)Lsun/security/pkcs11/wrapper/CK_VERSION; */ -JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_connect +JNIEXPORT jobject JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_connect (JNIEnv *env, jobject obj, jstring jPkcs11ModulePath, - jstring jGetFunctionList) + jstring jGetFunctionList) { HINSTANCE hModule; - CK_C_GetFunctionList C_GetFunctionList; + int i = 0; + CK_ULONG ulCount = 0; + CK_C_GetInterfaceList C_GetInterfaceList = NULL; + CK_INTERFACE_PTR iList = NULL; + CK_C_GetInterface C_GetInterface = NULL; + CK_INTERFACE_PTR interface = NULL; + CK_C_GetFunctionList C_GetFunctionList = NULL; CK_RV rv = CK_ASSERT_OK; - ModuleData *moduleData; + ModuleData *moduleData = NULL; jobject globalPKCS11ImplementationReference; LPVOID lpMsgBuf = NULL; char *exceptionMessage = NULL; @@ -91,10 +97,9 @@ JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_connect jPkcs11ModulePath, 0); TRACE1("DEBUG: connect to PKCS#11 module: %s ... ", libraryNameStr); - - /* - * Load the PKCS #11 DLL - */ + /* + * Load the PKCS #11 DLL + */ hModule = LoadLibrary(libraryNameStr); if (hModule == NULL) { FormatMessage( @@ -120,29 +125,93 @@ JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_connect goto cleanup; } +#ifdef DEBUG /* - * Get function pointer to C_GetFunctionList + * Get function pointer to C_GetInterfaceList */ - getFunctionListStr = (*env)->GetStringUTFChars(env, jGetFunctionList, 0); - C_GetFunctionList = (CK_C_GetFunctionList) GetProcAddress(hModule, - getFunctionListStr); - (*env)->ReleaseStringUTFChars(env, jGetFunctionList, getFunctionListStr); - if (C_GetFunctionList == NULL) { - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - GetLastError(), - 0, /* Default language */ - (LPTSTR) &lpMsgBuf, - 0, - NULL - ); - throwIOException(env, (LPTSTR) lpMsgBuf); - goto cleanup; + C_GetInterfaceList = (CK_C_GetInterfaceList) GetProcAddress(hModule, + "C_GetInterfaceList"); + if (C_GetInterfaceList != NULL) { + TRACE0("Found C_GetInterfaceList func\n"); + rv = (C_GetInterfaceList)(NULL, &ulCount); + if (rv == CKR_OK) { + /* get copy of interfaces */ + iList = (CK_INTERFACE_PTR) + malloc(ulCount*sizeof(CK_INTERFACE)); + rv = C_GetInterfaceList(iList, &ulCount); + for (i=0; i < (int)ulCount; i++) { + printf("interface %s version %d.%d funcs %p flags 0x%lu\n", + iList[i].pInterfaceName, + ((CK_VERSION *)iList[i].pFunctionList)->major, + ((CK_VERSION *)iList[i].pFunctionList)->minor, + iList[i].pFunctionList, iList[i].flags); + } + } else { + TRACE0("Connect: error polling interface list size\n"); + } + } else { + TRACE0("Connect: No C_GetInterfaceList func\n"); + } +#endif + + if (jGetFunctionList != NULL) { + getFunctionListStr = (*env)->GetStringUTFChars(env, + jGetFunctionList, 0); + if (getFunctionListStr == NULL) { + goto cleanup; + } + C_GetFunctionList = (CK_C_GetFunctionList) GetProcAddress(hModule, + getFunctionListStr); + if (C_GetFunctionList == NULL) { + TRACE1("Connect: No %s func\n", getFunctionListStr); + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + 0, /* Default language */ + (LPTSTR) &lpMsgBuf, + 0, + NULL + ); + throwIOException(env, (LPTSTR) lpMsgBuf); + goto cleanup; + } + TRACE1("Connect: Found %s func\n", getFunctionListStr); + } else { + // if none specified, then we try 3.0 API first before trying 2.40 + C_GetInterface = (CK_C_GetInterface) GetProcAddress(hModule, + "C_GetInterface"); + if (C_GetInterface != NULL) { + TRACE0("Connect: Found C_GetInterface func\n"); + rv = (C_GetInterface)(NULL, NULL, &interface, 0); + if (ckAssertReturnValueOK(env, rv) == CK_ASSERT_OK) { + goto setModuleData; + } + } + C_GetFunctionList = (CK_C_GetFunctionList) GetProcAddress(hModule, + "C_GetFunctionList"); + if (C_GetFunctionList == NULL) { + TRACE0("Connect: No C_GetFunctionList func\n"); + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + 0, /* Default language */ + (LPTSTR) &lpMsgBuf, + 0, + NULL + ); + throwIOException(env, (LPTSTR) lpMsgBuf); + goto cleanup; + } + TRACE0("Connect: Found C_GetFunctionList func\n"); } +setModuleData: /* * Get function pointers to all PKCS #11 functions */ @@ -153,12 +222,31 @@ JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_connect } moduleData->hModule = hModule; moduleData->applicationMutexHandler = NULL; - rv = (C_GetFunctionList)(&(moduleData->ckFunctionListPtr)); + if (C_GetFunctionList != NULL) { + rv = (C_GetFunctionList)(&(moduleData->ckFunctionListPtr)); + if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { + goto cleanup; + } + } else if (interface != NULL) { + moduleData->ckFunctionListPtr = interface->pFunctionList; + } else { + // should never happen + throwIOException(env, "ERROR: No function list ptr found"); + goto cleanup; + } + if (((CK_VERSION *)moduleData->ckFunctionListPtr)->major == 3) { + moduleData->ckFunctionList30Ptr = interface->pFunctionList; + } else { + moduleData->ckFunctionList30Ptr = NULL; + } + + TRACE2("Connect: FunctionListPtr version = %d.%d\n", + ((CK_VERSION *)moduleData->ckFunctionListPtr)->major, + ((CK_VERSION *)moduleData->ckFunctionListPtr)->minor); + globalPKCS11ImplementationReference = (*env)->NewGlobalRef(env, obj); putModuleEntry(env, globalPKCS11ImplementationReference, moduleData); - TRACE0("FINISHED\n"); - cleanup: /* Free up allocated buffers we no longer need */ if (lpMsgBuf != NULL) { @@ -167,11 +255,21 @@ cleanup: if (libraryNameStr != NULL) { (*env)->ReleaseStringUTFChars(env, jPkcs11ModulePath, libraryNameStr); } + if (jGetFunctionList != NULL && getFunctionListStr != NULL) { + (*env)->ReleaseStringUTFChars(env, jGetFunctionList, + getFunctionListStr); + } if (exceptionMessage != NULL) { free(exceptionMessage); } + TRACE0("Connect: FINISHED\n"); + if (moduleData != NULL) { + return ckVersionPtrToJVersion(env, + (CK_VERSION *)moduleData->ckFunctionListPtr); + } else { + return NULL; + } - if(ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; } } /* diff --git a/src/jdk.crypto.cryptoki/windows/native/libj2pkcs11/p11_md.h b/src/jdk.crypto.cryptoki/windows/native/libj2pkcs11/p11_md.h index 7cff0c7c24907e0b799730410f96076c75e45ace..0a069d5bc977ff5ae71f7b1b73d7cdf07290e381 100644 --- a/src/jdk.crypto.cryptoki/windows/native/libj2pkcs11/p11_md.h +++ b/src/jdk.crypto.cryptoki/windows/native/libj2pkcs11/p11_md.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. */ /* @@ -93,8 +93,9 @@ struct ModuleData { HINSTANCE hModule; - /* The pointer to the PKCS#11 functions of this module. */ + /* The pointers to the PKCS#11 functions of this module. */ CK_FUNCTION_LIST_PTR ckFunctionListPtr; + CK_FUNCTION_LIST_3_0_PTR ckFunctionList30Ptr; /* Reference to the object to use for mutex handling. NULL, if not used. */ jobject applicationMutexHandler; diff --git a/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CKey.java b/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CKey.java index 019f0ccac5619c8f6bc9e23b8adfa28d5d023d4e..e010e9717876d50112437ed6bca6ea5831cef72b 100644 --- a/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CKey.java +++ b/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CKey.java @@ -55,7 +55,7 @@ abstract class CKey implements Key, Length { this.hCryptKey = hCryptKey; } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { try { synchronized(this) { diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java index 820ca17ec9743f80e0b36a9620920ad08e839040..677d6e4cedfad06974e8ca14e82c09faedf39174 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java @@ -943,9 +943,13 @@ public class VM { public boolean isSharingEnabled() { if (sharingEnabled == null) { - Flag flag = getCommandLineFlag("UseSharedSpaces"); - sharingEnabled = (flag == null)? Boolean.FALSE : - (flag.getBool()? Boolean.TRUE: Boolean.FALSE); + Address address = VM.getVM().getDebugger().lookup(null, "UseSharedSpaces"); + if (address == null && getOS().equals("win32")) { + // On Win32 symbols are prefixed with the dll name. So look for + // UseSharedSpaces as a symbol in jvm.dll. + address = VM.getVM().getDebugger().lookup(null, "jvm!UseSharedSpaces"); + } + sharingEnabled = address.getJBooleanAt(0); } return sharingEnabled.booleanValue(); } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/types/basic/BasicTypeDataBase.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/types/basic/BasicTypeDataBase.java index 0944d59fc7154fdc92fc421b34b8e7b51370d023..e544db9e767a64965d84f0ba4b22456f7193f3db 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/types/basic/BasicTypeDataBase.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/types/basic/BasicTypeDataBase.java @@ -175,7 +175,7 @@ public class BasicTypeDataBase implements TypeDataBase { } // This implementation should be suitably platform-independent; we - // search nearby memory for the vtbl value of the given type. + // search the first word for the vtbl value of the given type. Address vtblAddr = vtblForType(type); @@ -231,12 +231,9 @@ public class BasicTypeDataBase implements TypeDataBase { // switch to this logic but in the interests of stability it will // be separate for the moment. - // Assuming that the base type is truly the first polymorphic type - // then the vtbl for all subclasss should be at several defined - // locations so only those locations will be checked. It's also - // required that the caller knows that the static type is at least - // baseType. See the notes in guessTypeForAddress for the logic of - // the locations searched. + // Assuming that the base type is truly the first polymorphic type, + // then the vtbl for all subclassses should be in the first word of + // the object. Address loc1 = addr.getAddressAt(0); @@ -248,50 +245,25 @@ public class BasicTypeDataBase implements TypeDataBase { } } - Address loc2 = null; - Address loc3 = null; - long offset2 = baseType.getSize(); - // I don't think this should be misaligned under any - // circumstances, but I'm not sure (FIXME: also not sure which - // way to go here, up or down -- assuming down) - offset2 = offset2 - (offset2 % getAddressSize()) - getAddressSize(); - if (offset2 > 0) { - loc2 = addr.getAddressAt(offset2); - } - long offset3 = offset2 - getAddressSize(); - if (offset3 > 0) { - loc3 = addr.getAddressAt(offset3); - } - - Type loc2Match = null; - Type loc3Match = null; for (Iterator iter = getTypes(); iter.hasNext(); ) { Type type = (Type) iter.next(); Type superClass = type; while (superClass != baseType && superClass != null) { superClass = superClass.getSuperclass(); } - if (superClass == null) continue; + if (superClass == null) continue; // type is not a subclass of baseType Address vtblAddr = vtblForType(type); if (vtblAddr == null) { - // This occurs sometimes for intermediate types that are never - // instantiated. + // This occurs sometimes for intermediate types that are never instantiated. if (DEBUG) { System.err.println("null vtbl for " + type); } continue; } - // Prefer loc1 match - if (vtblAddr.equals(loc1)) return type; - if (loc2 != null && loc2Match == null && vtblAddr.equals(loc2)) { - loc2Match = type; - } - if (loc3 != null && loc3Match == null && vtblAddr.equals(loc3)) { - loc3Match = type; + if (vtblAddr.equals(loc1)) { + return type; } } - if (loc2Match != null) return loc2Match; - if (loc3Match != null) return loc3Match; return null; } diff --git a/src/jdk.hotspot.agent/share/man/jhsdb.1 b/src/jdk.hotspot.agent/share/man/jhsdb.1 index 920c92a0377aec2b8f234263947262aa01af6696..b26c41d876212a408665bee5191365313f4a7f67 100644 --- a/src/jdk.hotspot.agent/share/man/jhsdb.1 +++ b/src/jdk.hotspot.agent/share/man/jhsdb.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JHSDB" "1" "2021" "JDK 18\-ea" "JDK Commands" +.TH "JHSDB" "1" "2022" "JDK 19\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.hotspot.agent/share/native/libsaproc/ps_core_common.c b/src/jdk.hotspot.agent/share/native/libsaproc/ps_core_common.c index e821ec2f4938d149ad640737b33c00a57523db60..79394a424d5672077f116425d56da7012251abcf 100644 --- a/src/jdk.hotspot.agent/share/native/libsaproc/ps_core_common.c +++ b/src/jdk.hotspot.agent/share/native/libsaproc/ps_core_common.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -300,7 +300,7 @@ bool init_classsharing_workaround(struct ps_prochandle* ph) { jvm_name = lib->name; useSharedSpacesAddr = lookup_symbol(ph, jvm_name, USE_SHARED_SPACES_SYM); if (useSharedSpacesAddr == 0) { - print_debug("can't lookup 'UseSharedSpaces' flag\n"); + print_debug("can't lookup 'UseSharedSpaces' symbol\n"); return false; } @@ -308,7 +308,7 @@ bool init_classsharing_workaround(struct ps_prochandle* ph) { // using equivalent type jboolean to read the value of // UseSharedSpaces which is same as hotspot type "bool". if (read_jboolean(ph, useSharedSpacesAddr, &useSharedSpaces) != true) { - print_debug("can't read the value of 'UseSharedSpaces' flag\n"); + print_debug("can't read the value of 'UseSharedSpaces' symbol\n"); return false; } diff --git a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/SimpleFileServer.java b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/SimpleFileServer.java index bd81e8e5eacff8ddaabe3d07aa7bae02b7630f98..a08f48567c9420f47e8a80c528661e22ce15fbbc 100644 --- a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/SimpleFileServer.java +++ b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/SimpleFileServer.java @@ -104,12 +104,12 @@ import sun.net.httpserver.simpleserver.OutputFilter; * server.start(); * } * - *

    Main entry point

    + *

    jwebserver Tool

    * - *

    A simple HTTP file server implementation is - * provided via the - * main entry point - * of the {@code jdk.httpserver} module. + *

    A simple HTTP file server implementation is provided via the + * {@code jwebserver} tool. + * + * @toolGuide jwebserver * * @since 18 */ @@ -164,14 +164,15 @@ public final class SimpleFileServer { } /** - * Creates a file server the serves files from a given path. + * Creates a file server that serves files from a given path. * *

    The server is configured with an initial context that maps the * URI {@code path} to a file handler. The file handler is * created as if by an invocation of * {@link #createFileHandler(Path) createFileHandler(rootDirectory)}, and is * associated to a context created as if by an invocation of - * {@link HttpServer#createContext(String) createContext("/")}. + * {@link HttpServer#createContext(String) createContext("/")}. The returned + * server is not started. * *

    An output level can be given to print log messages relating to the * exchanges handled by the server. The log messages, if any, are printed to diff --git a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/package-info.java b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/package-info.java index ed3978e0eae5a4a93f5953472d48be146688f6a6..3b9de3520fb9f6e64068f06a3fbf5c25c8b3beea 100644 --- a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/package-info.java +++ b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/package-info.java @@ -31,6 +31,24 @@ Any HTTP functionality not provided by this API can be implemented by application code using the API.

    + * The main components are: + *

      + *
    • the {@link com.sun.net.httpserver.HttpExchange} class that describes a + * request and response pair,
    • + *
    • the {@link com.sun.net.httpserver.HttpHandler} interface to handle + * incoming requests, plus the {@link com.sun.net.httpserver.HttpHandlers} class + * that provides useful handler implementations,
    • + *
    • the {@link com.sun.net.httpserver.HttpContext} class that maps a URI path + * to a {@code HttpHandler},
    • + *
    • the {@link com.sun.net.httpserver.HttpServer} class to listen for + * connections and dispatch requests to handlers,
    • + *
    • the {@link com.sun.net.httpserver.Filter} class that allows pre- and post- + * processing of requests.
    + *

    + * The {@link com.sun.net.httpserver.SimpleFileServer} class offers a simple + * HTTP-only file server (intended for testing, development and debugging purposes + * only). A default implementation is provided via the {@code jwebserver} tool. +

    Programmers must implement the {@link com.sun.net.httpserver.HttpHandler} interface. This interface provides a callback which is invoked to handle incoming requests from clients. A HTTP request and its response is known as an exchange. HTTP exchanges are @@ -120,13 +138,6 @@ } }); -

    - The {@link com.sun.net.httpserver.SimpleFileServer} class offers a simple - HTTP file server (intended for testing, development and debugging purposes - only). A default implementation is provided via the - main entry point - of the {@code jdk.httpserver} module. - @since 1.6 */ package com.sun.net.httpserver; diff --git a/src/jdk.httpserver/share/classes/module-info.java b/src/jdk.httpserver/share/classes/module-info.java index 417854d2ee88e465ee41e54e2d97d00dc68ac640..d7ddf8eb3039becee5c7ea885ed213748fc20cf7 100644 --- a/src/jdk.httpserver/share/classes/module-info.java +++ b/src/jdk.httpserver/share/classes/module-info.java @@ -24,41 +24,21 @@ */ /** - * Defines the JDK-specific HTTP server API. - *

    - * A basic high-level API for building embedded servers. Both HTTP and - * HTTPS are supported. - *

    - * The main components are: - *

      - *
    • the {@link com.sun.net.httpserver.HttpExchange} class that describes a - * request and response pair,
    • - *
    • the {@link com.sun.net.httpserver.HttpHandler} interface to handle - * incoming requests, plus the {@link com.sun.net.httpserver.HttpHandlers} class - * that provides useful handler implementations,
    • - *
    • the {@link com.sun.net.httpserver.HttpContext} class that maps a URI path - * to a {@code HttpHandler},
    • - *
    • the {@link com.sun.net.httpserver.HttpServer} class to listen for - * connections and dispatch requests to handlers,
    • - *
    • the {@link com.sun.net.httpserver.Filter} class that allows pre- and post- - * processing of requests.
    - *

    - * The {@link com.sun.net.httpserver.SimpleFileServer} class offers a simple - * HTTP file server (intended for testing, development and debugging purposes - * only). A default implementation is provided via the - * main entry point of the {@code jdk.httpserver} module, which can be used on - * the command line as such: - *

    {@code
    - *    Usage: java -m jdk.httpserver [-b bind address] [-p port] [-d directory]
    - *                                  [-o none|info|verbose] [-h to show options]
    - *    Options:
    - *    -b, --bind-address    - Address to bind to. Default: 127.0.0.1 or ::1 (loopback).
    - *                            For all interfaces use "-b 0.0.0.0" or "-b ::".
    - *    -d, --directory       - Directory to serve. Default: current directory.
    - *    -o, --output          - Output format. none|info|verbose. Default: info.
    - *    -p, --port            - Port to listen on. Default: 8000.
    - *    -h, -?, --help        - Print this help message.
    - * }
    + * Defines the JDK-specific HTTP server API, and provides the jwebserver tool + * for running a minimal HTTP server. + * + *

    The {@link com.sun.net.httpserver} package defines a high-level API for + * building servers that support HTTP and HTTPS. The SimpleFileServer class + * implements a simple HTTP-only file server intended for testing, development + * and debugging purposes. A default implementation is provided via the + * {@code jwebserver} tool and the main entry point of the module, which can + * also be invoked with {@code java -m jdk.httpserver}. + * + *

    The {@link com.sun.net.httpserver.spi} package specifies a Service Provider + * Interface (SPI) for locating HTTP server implementations based on the + * {@code com.sun.net.httpserver} API. + * + * @toolGuide jwebserver * * @uses com.sun.net.httpserver.spi.HttpServerProvider * diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/JWebServer.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/JWebServer.java new file mode 100644 index 0000000000000000000000000000000000000000..59f77abbae8b2f4552ce242c5f7a09292ef2733c --- /dev/null +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/JWebServer.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.net.httpserver.simpleserver; + +import java.io.PrintWriter; +import static java.nio.charset.StandardCharsets.UTF_8; + +/** + * Programmatic entry point to start the jwebserver tool. + */ +public class JWebServer { + + /** + * This constructor should never be called. + */ + private JWebServer() { throw new AssertionError(); } + + /** + * The main entry point. + * + *

    The command line arguments are parsed and the server is started. If + * started successfully, the server will run on a new non-daemon thread, + * and this method will return. Otherwise, if the server is not started + * successfully, e.g. an error is encountered while parsing the arguments + * or an I/O error occurs, the server is not started and this method invokes + * System::exit with an appropriate exit code. + * + *

    If the system property "sun.net.httpserver.maxReqTime" has not been + * set by the user, it is set to a value of 5 seconds. This is to prevent + * the server from hanging indefinitely, for example in the case of an HTTPS + * request. + * + * @param args the command-line options + * @throws NullPointerException if {@code args} is {@code null}, or if there + * are any {@code null} values in the {@code args} array + */ + public static void main(String... args) { + setMaxReqTime(); + + int ec = SimpleFileServerImpl.start(new PrintWriter(System.out, true, UTF_8), "jwebserver", args); + if (ec != 0) { + System.exit(ec); + } // otherwise, the server has either been started successfully and + // runs in another non-daemon thread, or -h or -version have been + // passed and the main thread has exited normally. + } + + public static final String MAXREQTIME_KEY = "sun.net.httpserver.maxReqTime"; + public static final String MAXREQTIME_VAL = "5"; + + private static void setMaxReqTime() { + if (System.getProperty(MAXREQTIME_KEY) == null) { + System.setProperty(MAXREQTIME_KEY, MAXREQTIME_VAL); + } + } +} diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/Main.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/Main.java index c51140bf5e982297f5f1a5b7bf5307d53f616d8d..83441cdbc7f1d7c324a1e6407d6b38378c88ee26 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/Main.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/Main.java @@ -27,12 +27,7 @@ import java.io.PrintWriter; import static java.nio.charset.StandardCharsets.UTF_8; /** - * Programmatic entry point to start the simpleserver tool. - * - *

    This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interface are subject to change or deletion - * without notice. + * Programmatic entry point to start "java -m jdk.httpserver". */ public class Main { @@ -51,15 +46,32 @@ public class Main { * or an I/O error occurs, the server is not started and this method invokes * System::exit with an appropriate exit code. * + *

    If the system property "sun.net.httpserver.maxReqTime" has not been + * set by the user, it is set to a value of 5 seconds. This is to prevent + * the server from hanging indefinitely, for example in the case of an HTTPS + * request. + * * @param args the command-line options * @throws NullPointerException if {@code args} is {@code null}, or if there * are any {@code null} values in the {@code args} array */ public static void main(String... args) { - int ec = SimpleFileServerImpl.start(new PrintWriter(System.out, true, UTF_8), args); - if (ec != 0) + setMaxReqTime(); + + int ec = SimpleFileServerImpl.start(new PrintWriter(System.out, true, UTF_8), "java", args); + if (ec != 0) { System.exit(ec); - // otherwise the server has been started successfully and runs in - // another non-daemon thread. + } // otherwise, the server has either been started successfully and + // runs in another non-daemon thread, or -h or -version have been + // passed and the main thread has exited normally. + } + + public static final String MAXREQTIME_KEY = "sun.net.httpserver.maxReqTime"; + public static final String MAXREQTIME_VAL = "5"; + + private static void setMaxReqTime() { + if (System.getProperty(MAXREQTIME_KEY) == null) { + System.setProperty(MAXREQTIME_KEY, MAXREQTIME_VAL); + } } } diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/SimpleFileServerImpl.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/SimpleFileServerImpl.java index 57138018bb9f86c8675db49f705dcdaa4db5781b..852aae5a83832e3bcb12cf780bb1952c875ff5da 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/SimpleFileServerImpl.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/SimpleFileServerImpl.java @@ -71,11 +71,12 @@ final class SimpleFileServerImpl { * * @param writer the writer to which output should be written * @param args the command line options + * @param launcher the launcher the server is started from * @throws NullPointerException if any of the arguments are {@code null}, * or if there are any {@code null} values in the {@code args} array * @return startup status code */ - static int start(PrintWriter writer, String[] args) { + static int start(PrintWriter writer, String launcher, String[] args) { Objects.requireNonNull(args); for (var arg : args) { Objects.requireNonNull(arg); @@ -96,7 +97,11 @@ final class SimpleFileServerImpl { option = options.next(); switch (option) { case "-h", "-?", "--help" -> { - out.showHelp(); + out.showHelp(launcher); + return Startup.OK.statusCode; + } + case "-version", "--version" -> { + out.showVersion(launcher); return Startup.OK.statusCode; } case "-b", "--bind-address" -> { @@ -115,7 +120,7 @@ final class SimpleFileServerImpl { } } catch (AssertionError ae) { out.reportError(ResourceBundleHelper.getMessage("err.unknown.option", option)); - out.showUsage(); + out.showUsage(launcher); return Startup.CMDERR.statusCode; } catch (NoSuchElementException nsee) { out.reportError(ResourceBundleHelper.getMessage("err.missing.arg", option)); @@ -169,12 +174,16 @@ final class SimpleFileServerImpl { } } - void showUsage() { - writer.println(ResourceBundleHelper.getMessage("usage")); + void showUsage(String launcher) { + writer.println(ResourceBundleHelper.getMessage("usage." + launcher)); + } + + void showVersion(String launcher) { + writer.println(ResourceBundleHelper.getMessage("version", launcher, System.getProperty("java.version"))); } - void showHelp() { - writer.println(ResourceBundleHelper.getMessage("usage")); + void showHelp(String launcher) { + writer.println(ResourceBundleHelper.getMessage("usage." + launcher)); writer.println(ResourceBundleHelper.getMessage("options", LOOPBACK_ADDR.getHostAddress())); } diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/resources/simpleserver.properties b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/resources/simpleserver.properties index bf7572b02d638a9ae3cf4b58d096a977dc45de51..fc5a9ec6029aba3c91880583c92228ff9a182bda 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/resources/simpleserver.properties +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/resources/simpleserver.properties @@ -23,9 +23,18 @@ # questions. # -usage=\ +usage.java=\ Usage: java -m jdk.httpserver [-b bind address] [-p port] [-d directory]\n\ -\ [-o none|info|verbose] [-h to show options] +\ [-o none|info|verbose] [-h to show options]\n\ +\ [-version to show version information] + +usage.jwebserver=\ +Usage: jwebserver [-b bind address] [-p port] [-d directory]\n\ +\ [-o none|info|verbose] [-h to show options]\n\ +\ [-version to show version information] + +version=\ +{0} {1} options=\ Options:\n\ @@ -34,7 +43,8 @@ Options:\n\ -d, --directory - Directory to serve. Default: current directory.\n\ -o, --output - Output format. none|info|verbose. Default: info.\n\ -p, --port - Port to listen on. Default: 8000.\n\ --h, -?, --help - Print this help message.\n\ +-h, -?, --help - Prints this help message and exits.\n\ +-version, --version - Prints version information and exits.\n\ To stop the server, press Ctrl + C. opt.bindaddress=\ diff --git a/src/jdk.httpserver/share/man/jwebserver.1 b/src/jdk.httpserver/share/man/jwebserver.1 new file mode 100644 index 0000000000000000000000000000000000000000..4f255c2a74af3b4cd2ed80205ca768ac4137123b --- /dev/null +++ b/src/jdk.httpserver/share/man/jwebserver.1 @@ -0,0 +1,196 @@ +.\" Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +.\" DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +.\" +.\" This code is free software; you can redistribute it and/or modify it +.\" under the terms of the GNU General Public License version 2 only, as +.\" published by the Free Software Foundation. +.\" +.\" This code is distributed in the hope that it will be useful, but WITHOUT +.\" ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +.\" FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +.\" version 2 for more details (a copy is included in the LICENSE file that +.\" accompanied this code). +.\" +.\" You should have received a copy of the GNU General Public License version +.\" 2 along with this work; if not, write to the Free Software Foundation, +.\" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +.\" +.\" Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +.\" or visit www.oracle.com if you need additional information or have any +.\" questions. +.\" +.\" Automatically generated by Pandoc 2.3.1 +.\" +.TH "JWEBSERVER" "1" "2022" "JDK 19\-ea" "JDK Commands" +.hy +.SH NAME +.PP +jwebserver \- launch the Java Simple Web Server +.SH SYNOPSIS +.PP +\f[CB]jwebserver\f[R] [\f[I]options\f[R]] +.TP +.B \f[I]options\f[R] +Command\-line options. +For a detailed description of the options, see \f[B]Options\f[R]. +.RS +.RE +.SH DESCRIPTION +.PP +The \f[CB]jwebserver\f[R] tool provides a minimal HTTP server, designed to +be used for prototyping, testing, and debugging. +It serves a single directory hierarchy, and only serves static files. +Only HTTP/1.1 is supported; HTTP/2 and HTTPS are not supported. +.PP +Only idempotent HEAD and GET requests are served. +Any other requests receive a \f[CB]501\ \-\ Not\ Implemented\f[R] or a +\f[CB]405\ \-\ Not\ Allowed\f[R] response. +GET requests are mapped to the directory being served, as follows: +.IP \[bu] 2 +If the requested resource is a file, its content is served. +.IP \[bu] 2 +If the requested resource is a directory that contains an index file, +the content of the index file is served. +.IP \[bu] 2 +Otherwise, the names of all files and subdirectories of the directory +are listed. +Symbolic links and hidden files are not listed or served. +.PP +MIME types are configured automatically, using the built\-in table. +For example, \f[CB]\&.html\f[R] files are served as \f[CB]text/html\f[R] and +\f[CB]\&.java\f[R] files are served as \f[CB]text/plain\f[R]. +.PP +\f[CB]jwebserver\f[R] is located in the jdk.httpserver module, and can +alternatively be started with \f[CB]java\ \-m\ jdk.httpserver\f[R]. +It is based on the web server implementation in the +\f[CB]com.sun.net.httpserver\f[R] package. +The \f[CB]com.sun.net.httpserver.SimpleFileServer\f[R] class provides a +programmatic way to retrieve the server and its components for reuse and +extension. +.SH USAGE +.IP +.nf +\f[CB] +jwebserver\ [\-b\ bind\ address]\ [\-p\ port]\ [\-d\ directory] +\ \ \ \ \ \ \ \ \ \ \ [\-o\ none|info|verbose]\ [\-h\ to\ show\ options] +\ \ \ \ \ \ \ \ \ \ \ [\-version\ to\ show\ version\ information] +\f[R] +.fi +.SH OPTIONS +.TP +.B \f[CB]\-h\f[R] or \f[CB]\-?\f[R] or \f[CB]\-\-help\f[R] +Prints the help message and exits. +.RS +.RE +.TP +.B \f[CB]\-b\f[R] \f[I]addr\f[R] or \f[CB]\-\-bind\-address\f[R] \f[I]addr\f[R] +Specifies the address to bind to. +Default: 127.0.0.1 or ::1 (loopback). +For all interfaces use \f[CB]\-b\ 0.0.0.0\f[R] or \f[CB]\-b\ ::\f[R]. +.RS +.RE +.TP +.B \f[CB]\-d\f[R] \f[I]dir\f[R] or \f[CB]\-\-directory\f[R] \f[I]dir\f[R] +Specifies the directory to serve. +Default: current directory. +.RS +.RE +.TP +.B \f[CB]\-o\f[R] \f[I]level\f[R] or \f[CB]\-\-output\f[R] \f[I]level\f[R] +Specifies the output format. +\f[CB]none\f[R] | \f[CB]info\f[R] | \f[CB]verbose\f[R]. +Default: \f[CB]info\f[R]. +.RS +.RE +.TP +.B \f[CB]\-p\f[R] \f[I]port\f[R] or \f[CB]\-\-port\f[R] \f[I]port\f[R] +Specifies the port to listen on. +Default: 8000. +.RS +.RE +.TP +.B \f[CB]\-version\f[R] or \f[CB]\-\-version\f[R] +Prints the version information and exits. +.RS +.RE +.PP +To stop the server, press \f[CB]Ctrl\ +\ C\f[R]. +.SH STARTING THE SERVER +.PP +The following command starts the Simple Web Server: +.IP +.nf +\f[CB] +$\ jwebserver +\f[R] +.fi +.PP +If startup is successful, the server prints a message to +\f[CB]System.out\f[R] listing the local address and the absolute path of +the directory being served. +For example: +.IP +.nf +\f[CB] +$\ jwebserver +Binding\ to\ loopback\ by\ default.\ For\ all\ interfaces\ use\ "\-b\ 0.0.0.0"\ or\ "\-b\ ::". +Serving\ /cwd\ and\ subdirectories\ on\ 127.0.0.1\ port\ 8000 +URL\ http://127.0.0.1:8000/ +\f[R] +.fi +.SH CONFIGURATION +.PP +By default, the server runs in the foreground and binds to the loopback +address and port 8000. +This can be changed with the \f[CB]\-b\f[R] and \f[CB]\-p\f[R] options. +.PD 0 +.P +.PD +For example, to bind the Simple Web Server to all interfaces, use: +.IP +.nf +\f[CB] +$\ jwebserver\ \-b\ 0.0.0.0 +Serving\ /cwd\ and\ subdirectories\ on\ 0.0.0.0\ (all\ interfaces)\ port\ 8000 +URL\ http://123.456.7.891:8000/ +\f[R] +.fi +.PP +Note that this makes the web server accessible to all hosts on the +network. +\f[I]Do not do this unless you are sure the server cannot leak any +sensitive information.\f[R] +.PP +As another example, use the following command to run on port 9000: +.IP +.nf +\f[CB] +$\ jwebserver\ \-p\ 9000 +\f[R] +.fi +.PP +By default, the files of the current directory are served. +A different directory can be specified with the \f[CB]\-d\f[R] option. +.PP +By default, every request is logged on the console. +The output looks like this: +.IP +.nf +\f[CB] +127.0.0.1\ \-\ \-\ [10/Feb/2021:14:34:11\ +0000]\ "GET\ /some/subdirectory/\ HTTP/1.1"\ 200\ \- +\f[R] +.fi +.PP +Logging output can be changed with the \f[CB]\-o\f[R] option. +The default setting is \f[CB]info\f[R]. +The \f[CB]verbose\f[R] setting additionally includes the request and +response headers as well as the absolute path of the requested resource. +.SH STOPPING THE SERVER +.PP +Once started successfully, the server runs until it is stopped. +On Unix platforms, the server can be stopped by sending it a +\f[CB]SIGINT\f[R] signal (\f[CB]Ctrl+C\f[R] in a terminal window). +.SH HELP OPTION +.PP +The \f[CB]\-h\f[R] option displays a help message describing the usage and +the options of the \f[CB]jwebserver\f[R]. diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/AbstractLayout.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/AbstractLayout.java index 81a20241a7ab1e344f71b0014f3e59f9136da740..f33e4cc2c4b9662d62af640229ce12171cd9fce7 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/AbstractLayout.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/AbstractLayout.java @@ -25,26 +25,23 @@ */ package jdk.incubator.foreign; +import jdk.internal.foreign.Utils; +import jdk.internal.vm.annotation.Stable; + import java.lang.constant.ClassDesc; -import java.lang.constant.Constable; import java.lang.constant.ConstantDesc; -import java.lang.constant.ConstantDescs; import java.lang.constant.DirectMethodHandleDesc; import java.lang.constant.DynamicConstantDesc; import java.lang.constant.MethodHandleDesc; import java.lang.constant.MethodTypeDesc; import java.nio.ByteOrder; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.OptionalLong; -import java.util.stream.Collectors; -import java.util.stream.Stream; import static java.lang.constant.ConstantDescs.BSM_GET_STATIC_FINAL; import static java.lang.constant.ConstantDescs.BSM_INVOKE; +import static java.lang.constant.ConstantDescs.CD_Class; import static java.lang.constant.ConstantDescs.CD_String; import static java.lang.constant.ConstantDescs.CD_long; @@ -52,50 +49,33 @@ abstract non-sealed class AbstractLayout implements MemoryLayout { private final OptionalLong size; final long alignment; - final Map attributes; + private final Optional name; + @Stable + long cachedSize; - public AbstractLayout(OptionalLong size, long alignment, Map attributes) { + public AbstractLayout(OptionalLong size, long alignment, Optional name) { this.size = size; this.alignment = alignment; - this.attributes = Collections.unmodifiableMap(attributes); + this.name = name; } @Override public AbstractLayout withName(String name) { Objects.requireNonNull(name); - return withAttribute(LAYOUT_NAME, name); + return dup(alignment, Optional.of(name)); } @Override public final Optional name() { - return attribute(LAYOUT_NAME).map(String.class::cast); - } - - @Override - public Optional attribute(String name) { - Objects.requireNonNull(name); - return Optional.ofNullable(attributes.get(name)); - } - - @Override - public Stream attributes() { - return attributes.keySet().stream(); - } - - @Override - public AbstractLayout withAttribute(String name, Constable value) { - Objects.requireNonNull(name); - Map newAttributes = new HashMap<>(attributes); - newAttributes.put(name, value); - return dup(alignment, newAttributes); + return name; } - abstract AbstractLayout dup(long alignment, Map annos); + abstract AbstractLayout dup(long alignment, Optional name); @Override public AbstractLayout withBitAlignment(long alignmentBits) { checkAlignment(alignmentBits); - return dup(alignmentBits, attributes); + return dup(alignmentBits, name); } void checkAlignment(long alignmentBitCount) { @@ -120,6 +100,15 @@ abstract non-sealed class AbstractLayout implements MemoryLayout { return alignment; } + @Override + public long byteSize() { + if (cachedSize == 0) { + cachedSize = Utils.bitsToBytesOrThrow(bitSize(), + () -> new UnsupportedOperationException("Cannot compute byte size; bit size is not a multiple of 8")); + } + return cachedSize; + } + @Override public boolean hasSize() { return size.isPresent(); @@ -145,11 +134,6 @@ abstract non-sealed class AbstractLayout implements MemoryLayout { if (!hasNaturalAlignment()) { s = alignment + "%" + s; } - if (!attributes.isEmpty()) { - s += attributes.entrySet().stream() - .map(e -> e.getKey() + "=" + e.getValue()) - .collect(Collectors.joining(",", "[", "]")); - } return s; } @@ -158,9 +142,9 @@ abstract non-sealed class AbstractLayout implements MemoryLayout { desc = DynamicConstantDesc.ofNamed(BSM_INVOKE, "withBitAlignment", desc.constantType(), MH_WITH_BIT_ALIGNMENT, desc, bitAlignment()); } - for (var e : attributes.entrySet()) { - desc = DynamicConstantDesc.ofNamed(BSM_INVOKE, "withAttribute", desc.constantType(), MH_WITH_ATTRIBUTE, - desc, e.getKey(), e.getValue().describeConstable().orElseThrow()); + if (name().isPresent()) { + desc = DynamicConstantDesc.ofNamed(BSM_INVOKE, "withName", desc.constantType(), MH_WITH_NAME, + desc, name().get().describeConstable().orElseThrow()); } return desc; @@ -177,7 +161,7 @@ abstract non-sealed class AbstractLayout implements MemoryLayout { @Override public int hashCode() { - return attributes.hashCode() << Long.hashCode(alignment); + return name.hashCode() << Long.hashCode(alignment); } @Override @@ -190,7 +174,7 @@ abstract non-sealed class AbstractLayout implements MemoryLayout { return false; } - return Objects.equals(attributes, ((AbstractLayout) other).attributes) && + return Objects.equals(name, ((AbstractLayout) other).name) && Objects.equals(alignment, ((AbstractLayout) other).alignment); } @@ -208,8 +192,6 @@ abstract non-sealed class AbstractLayout implements MemoryLayout { static final ClassDesc CD_FUNCTION_DESC = FunctionDescriptor.class.describeConstable().get(); - static final ClassDesc CD_Constable = Constable.class.describeConstable().get(); - static final ConstantDesc BIG_ENDIAN = DynamicConstantDesc.ofNamed(BSM_GET_STATIC_FINAL, "BIG_ENDIAN", CD_BYTEORDER, CD_BYTEORDER); static final ConstantDesc LITTLE_ENDIAN = DynamicConstantDesc.ofNamed(BSM_GET_STATIC_FINAL, "LITTLE_ENDIAN", CD_BYTEORDER, CD_BYTEORDER); @@ -217,9 +199,6 @@ abstract non-sealed class AbstractLayout implements MemoryLayout { static final MethodHandleDesc MH_PADDING = MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.INTERFACE_STATIC, CD_MEMORY_LAYOUT, "paddingLayout", MethodTypeDesc.of(CD_MEMORY_LAYOUT, CD_long)); - static final MethodHandleDesc MH_VALUE = MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.INTERFACE_STATIC, CD_MEMORY_LAYOUT, "valueLayout", - MethodTypeDesc.of(CD_VALUE_LAYOUT, CD_long, CD_BYTEORDER)); - static final MethodHandleDesc MH_SIZED_SEQUENCE = MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.INTERFACE_STATIC, CD_MEMORY_LAYOUT, "sequenceLayout", MethodTypeDesc.of(CD_SEQUENCE_LAYOUT, CD_long, CD_MEMORY_LAYOUT)); @@ -232,6 +211,9 @@ abstract non-sealed class AbstractLayout implements MemoryLayout { static final MethodHandleDesc MH_UNION = MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.INTERFACE_STATIC, CD_MEMORY_LAYOUT, "unionLayout", MethodTypeDesc.of(CD_GROUP_LAYOUT, CD_MEMORY_LAYOUT.arrayType())); + static final MethodHandleDesc MH_VALUE = MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.INTERFACE_STATIC, CD_MEMORY_LAYOUT, "valueLayout", + MethodTypeDesc.of(CD_VALUE_LAYOUT, CD_Class, CD_BYTEORDER)); + static final MethodHandleDesc MH_VOID_FUNCTION = MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.STATIC, CD_FUNCTION_DESC, "ofVoid", MethodTypeDesc.of(CD_FUNCTION_DESC, CD_MEMORY_LAYOUT.arrayType())); @@ -241,6 +223,6 @@ abstract non-sealed class AbstractLayout implements MemoryLayout { static final MethodHandleDesc MH_WITH_BIT_ALIGNMENT = MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.INTERFACE_VIRTUAL, CD_MEMORY_LAYOUT, "withBitAlignment", MethodTypeDesc.of(CD_MEMORY_LAYOUT, CD_long)); - static final MethodHandleDesc MH_WITH_ATTRIBUTE = MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.INTERFACE_VIRTUAL, CD_MEMORY_LAYOUT, "withAttribute", - MethodTypeDesc.of(CD_MEMORY_LAYOUT, CD_String, CD_Constable)); + static final MethodHandleDesc MH_WITH_NAME = MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.INTERFACE_VIRTUAL, CD_MEMORY_LAYOUT, "withName", + MethodTypeDesc.of(CD_MEMORY_LAYOUT, CD_String)); } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/Addressable.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/Addressable.java index b5513c835db3d8ae990165368b5c6ad14ab14fbf..39f61e76122446b4b333b332e9176eba7dbcd035 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/Addressable.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/Addressable.java @@ -27,16 +27,21 @@ package jdk.incubator.foreign; /** * Represents a type which is addressable. An addressable type is one which can be projected down to - * a memory address instance (see {@link #address()}). Examples of addressable types are {@link MemorySegment}, - * {@link MemoryAddress} and {@link CLinker.VaList}. + * a {@linkplain #address() memory address}. Examples of addressable types are {@link MemorySegment}, + * {@link MemoryAddress}, {@link VaList} and {@link NativeSymbol}. + *

    + * The {@link Addressable} type is used by the {@link CLinker C linker} to model the types of + * {@link CLinker#downcallHandle(FunctionDescriptor) downcall handle} parameters that must be passed by reference + * (e.g. memory addresses, va lists and upcall stubs). * * @implSpec * Implementations of this interface are value-based. */ -public interface Addressable { +public sealed interface Addressable permits MemorySegment, MemoryAddress, NativeSymbol, VaList { + /** - * Map this object into a {@link MemoryAddress} instance. - * @return the {@link MemoryAddress} instance associated with this object. + * Returns the memory address associated with this addressable. + * @return The memory address associated with this addressable. */ MemoryAddress address(); } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/CLinker.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/CLinker.java index 5bd4ba57c1240203f405b029ce6300634b842734..4ba44bd2dc6d2e83d40fce7a6434e9bd22af7a61 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/CLinker.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/CLinker.java @@ -25,93 +25,124 @@ */ package jdk.incubator.foreign; -import jdk.internal.foreign.AbstractCLinker; -import jdk.internal.foreign.NativeMemorySegmentImpl; -import jdk.internal.foreign.PlatformLayouts; import jdk.internal.foreign.SystemLookup; import jdk.internal.foreign.abi.SharedUtils; -import jdk.internal.foreign.abi.aarch64.linux.LinuxAArch64VaList; -import jdk.internal.foreign.abi.aarch64.macos.MacOsAArch64VaList; -import jdk.internal.foreign.abi.x64.sysv.SysVVaList; -import jdk.internal.foreign.abi.x64.windows.WinVaList; +import jdk.internal.foreign.abi.aarch64.linux.LinuxAArch64Linker; +import jdk.internal.foreign.abi.aarch64.macos.MacOsAArch64Linker; +import jdk.internal.foreign.abi.x64.sysv.SysVx64Linker; +import jdk.internal.foreign.abi.x64.windows.Windowsx64Linker; import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.Reflection; -import java.lang.constant.Constable; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.util.Objects; -import java.util.function.Consumer; - -import static jdk.internal.foreign.PlatformLayouts.*; +import java.util.Optional; /** * A C linker implements the C Application Binary Interface (ABI) calling conventions. * Instances of this interface can be used to link foreign functions in native libraries that - * follow the JVM's target platform C ABI. + * follow the JVM's target platform C ABI. A C linker provides two main capabilities: first, it allows Java code + * to link foreign functions into a so called downcall method handle; secondly, it allows + * native code to call Java method handles via the generation of upcall stubs. *

    - * Linking a foreign function is a process which requires two components: a method type, and - * a function descriptor. The method type, consists of a set of carrier types, which, together, - * specify the Java signature which clients must adhere to when calling the underlying foreign function. - * The function descriptor contains a set of memory layouts which, together, specify the foreign function - * signature and classification information (via a custom layout attributes, see {@link TypeKind}), so that linking can take place. + * On unsupported platforms this class will fail to initialize with an {@link ExceptionInInitializerError}. *

    - * Clients of this API can build function descriptors using the predefined memory layout constants - * (based on a subset of the built-in types provided by the C language), found in this interface; alternatively, - * they can also decorate existing value layouts using the required {@link TypeKind} classification attribute - * (this can be done using the {@link MemoryLayout#withAttribute(String, Constable)} method). A failure to do so might - * result in linkage errors, given that linking requires additional classification information to determine, for instance, - * how arguments should be loaded into registers during a foreign function call. + * Unless otherwise specified, passing a {@code null} argument, or an array argument containing one or more {@code null} + * elements to a method in this class causes a {@link NullPointerException NullPointerException} to be thrown.

    + * + *

    Downcall method handles

    + *

    + * {@linkplain #downcallHandle(FunctionDescriptor) Linking a foreign function} is a process which requires a function descriptor, + * a set of memory layouts which, together, specify the signature of the foreign function to be linked, and returns, + * when complete, a downcall method handle, that is, a method handle that can be used to invoke the target native function. + * The Java {@linkplain java.lang.invoke.MethodType method type} associated with the returned method handle is + * {@linkplain #downcallType(FunctionDescriptor) derived} from the argument and return layouts in the function descriptor. + * More specifically, given each layout {@code L} in the function descriptor, a corresponding carrier {@code C} is inferred, + * as described below: + *

      + *
    • if {@code L} is a {@link ValueLayout} with carrier {@code E} then there are two cases: + *
        + *
      • if {@code L} occurs in a parameter position and {@code E} is {@code MemoryAddress.class}, + * then {@code C = Addressable.class};
      • + *
      • otherwise, {@code C = E}; + *
    • + *
    • or, if {@code L} is a {@link GroupLayout}, then {@code C} is set to {@code MemorySegment.class}
    • + *
    *

    - * Implementations of this interface support the following primitive carrier types: - * {@code byte}, {@code short}, {@code char}, {@code int}, {@code long}, {@code float}, - * and {@code double}, as well as {@link MemoryAddress} for passing pointers, and - * {@link MemorySegment} for passing structs and unions. Finally, the {@link VaList} - * carrier type can be used to match the native {@code va_list} type. + * The downcall method handle type, derived as above, might be decorated by additional leading parameters, + * in the given order if both are present: + *

      + *
    • If the downcall method handle is created {@linkplain #downcallHandle(FunctionDescriptor) without specifying a native symbol}, + * the downcall method handle type features a leading parameter of type {@link NativeSymbol}, from which the + * address of the target native function can be derived.
    • + *
    • If the function descriptor's return layout is a group layout, the resulting downcall method handle accepts + * an additional leading parameter of type {@link SegmentAllocator}, which is used by the linker runtime to allocate the + * memory region associated with the struct returned by the downcall method handle.
    • + *
    + *

    Variadic functions, declared in C either with a trailing ellipses ({@code ...}) at the end of the formal parameter + * list or with an empty formal parameter list, are not supported directly. However, it is possible to link a native + * variadic function by using a {@linkplain FunctionDescriptor#asVariadic(MemoryLayout...) variadic} function descriptor, + * in which the specialized signature of a given variable arity callsite is described in full. Alternatively, + * if the foreign library allows it, clients might also be able to interact with variable arity methods + * by passing a trailing parameter of type {@link VaList}. + * + *

    Upcall stubs

    + * + * {@linkplain #upcallStub(MethodHandle, FunctionDescriptor, ResourceScope) Creating an upcall stub} requires a method + * handle and a function descriptor; in this case, the set of memory layouts in the function descriptor + * specify the signature of the function pointer associated with the upcall stub. *

    - * For the linking process to be successful, some requirements must be satisfied; if {@code M} and {@code F} are - * the method type (obtained after dropping any prefix arguments) and the function descriptor, respectively, - * used during the linking process, then it must be that: + * The type of the provided method handle has to match the Java {@linkplain java.lang.invoke.MethodType method type} + * associated with the upcall stub, which is derived from the argument and return layouts in the function descriptor. + * More specifically, given each layout {@code L} in the function descriptor, a corresponding carrier {@code C} is inferred, as described below: *

      - *
    • The arity of {@code M} is the same as that of {@code F};
    • - *
    • If the return type of {@code M} is {@code void}, then {@code F} should have no return layout - * (see {@link FunctionDescriptor#ofVoid(MemoryLayout...)});
    • - *
    • for each pair of carrier type {@code C} and layout {@code L} in {@code M} and {@code F}, respectively, - * where {@code C} and {@code L} refer to the same argument, or to the return value, the following conditions must hold: + *
    • if {@code L} is a {@link ValueLayout} with carrier {@code E} then there are two cases: *
        - *
      • If {@code C} is a primitve type, then {@code L} must be a {@code ValueLayout}, and the size of the layout must match - * that of the carrier type (see {@link Integer#SIZE} and similar fields in other primitive wrapper classes);
      • - *
      • If {@code C} is {@code MemoryAddress.class}, then {@code L} must be a {@code ValueLayout}, and its size must match - * the platform's address size (see {@link MemoryLayouts#ADDRESS}). For this purpose, the {@link CLinker#C_POINTER} layout - * constant can be used;
      • - *
      • If {@code C} is {@code MemorySegment.class}, then {@code L} must be a {@code GroupLayout}
      • - *
      • If {@code C} is {@code VaList.class}, then {@code L} must be {@link CLinker#C_VA_LIST}
      • - *
      - *
    • + *
    • if {@code L} occurs in a return position and {@code E} is {@code MemoryAddress.class}, + * then {@code C = Addressable.class};
    • + *
    • otherwise, {@code C = E}; + *
    + *
  • or, if {@code L} is a {@link GroupLayout}, then {@code C} is set to {@code MemorySegment.class}
  • * + * Upcall stubs are modelled by instances of type {@link NativeSymbol}; upcall stubs can be passed by reference to other + * downcall method handles (as {@link NativeSymbol} implements the {@link Addressable} interface) and, + * when no longer required, they can be {@link ResourceScope#close() released}, via their {@linkplain NativeSymbol#scope() scope}. * - *

    Variadic functions, declared in C either with a trailing ellipses ({@code ...}) at the end of the formal parameter - * list or with an empty formal parameter list, are not supported directly. It is not possible to create a method handle - * that takes a variable number of arguments, and neither is it possible to create an upcall stub wrapping a method - * handle that accepts a variable number of arguments. However, for downcalls only, it is possible to link a native - * variadic function by using a specialized method type and function descriptor: for each argument that is to be - * passed as a variadic argument, an explicit, additional, carrier type and memory layout must be present in the method type and - * function descriptor objects passed to the linker. Furthermore, as memory layouts corresponding to variadic arguments in - * a function descriptor must contain additional classification information, it is required that - * {@link #asVarArg(MemoryLayout)} is used to create the memory layouts for each parameter corresponding to a variadic - * argument in a specialized function descriptor. + *

    System lookup

    * - *

    On unsupported platforms this class will fail to initialize with an {@link ExceptionInInitializerError}. + * This class implements the {@link SymbolLookup} interface; as such clients can {@linkplain #lookup(String) look up} symbols + * in the standard libraries associated with this linker. The set of symbols available for lookup is unspecified, + * as it depends on the platform and on the operating system. * - *

    Unless otherwise specified, passing a {@code null} argument, or an array argument containing one or more {@code null} - * elements to a method in this class causes a {@link NullPointerException NullPointerException} to be thrown.

    + *

    Safety considerations

    + * + * Obtaining downcall method handle is intrinsically unsafe. A symbol in a native library does not, in general, + * contain enough signature information (e.g. arity and types of native function parameters). As a consequence, + * the linker runtime cannot validate linkage requests. When a client interacts with a downcall method handle obtained + * through an invalid linkage request (e.g. by specifying a function descriptor featuring too many argument layouts), + * the result of such interaction is unspecified and can lead to JVM crashes. On downcall handle invocation, + * the linker runtime guarantees the following for any argument that is a memory resource {@code R} (of type {@link MemorySegment}, + * {@link NativeSymbol} or {@link VaList}): + *
      + *
    • The resource scope of {@code R} is {@linkplain ResourceScope#isAlive() alive}. Otherwise, the invocation throws + * {@link IllegalStateException};
    • + *
    • The invocation occurs in same thread as the one {@link ResourceScope#ownerThread() owning} the resource scope of {@code R}, + * if said scope is confined. Otherwise, the invocation throws {@link IllegalStateException}; and
    • + *
    • The scope of {@code R} is {@linkplain ResourceScope#keepAlive(ResourceScope) kept alive} (and cannot be closed) during the invocation. + *
    + *

    + * When creating upcall stubs the linker runtime validates the type of the target method handle against the provided + * function descriptor and report an error if any mismatch is detected. As for downcalls, JVM crashes might occur, + * if the native code casts the function pointer associated with an upcall stub to a type + * that is incompatible with the provided function descriptor. Moreover, if the target method + * handle associated with an upcall stub returns a {@linkplain MemoryAddress native address}, clients must ensure + * that this address cannot become invalid after the upcall completes. This can lead to unspecified behavior, + * and even JVM crashes, since an upcall is typically executed in the context of a downcall method handle invocation. * * @implSpec * Implementations of this interface are immutable, thread-safe and value-based. */ -public sealed interface CLinker permits AbstractCLinker { +public sealed interface CLinker extends SymbolLookup permits Windowsx64Linker, SysVx64Linker, LinuxAArch64Linker, MacOsAArch64Linker { /** * Returns the C linker for the current platform. @@ -127,96 +158,75 @@ public sealed interface CLinker permits AbstractCLinker { * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. */ @CallerSensitive - static CLinker getInstance() { + static CLinker systemCLinker() { Reflection.ensureNativeAccess(Reflection.getCallerClass()); return SharedUtils.getSystemLinker(); } /** - * Obtains a system lookup which is suitable to find symbols in the standard C libraries. The set of symbols - * available for lookup is unspecified, as it depends on the platform and on the operating system. - *

    - * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * @return a system-specific library lookup which is suitable to find symbols in the standard C libraries. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + * Look up a symbol in the standard libraries associated with this linker. + * The set of symbols available for lookup is unspecified, as it depends on the platform and on the operating system. + * @return a symbol in the standard libraries associated with this linker. */ - @CallerSensitive - static SymbolLookup systemLookup() { - Reflection.ensureNativeAccess(Reflection.getCallerClass()); - return SystemLookup.getInstance(); + @Override + default Optional lookup(String name) { + return SystemLookup.getInstance().lookup(name); } /** * Obtains a foreign method handle, with the given type and featuring the given function descriptor, - * which can be used to call a target foreign function at the given address. + * which can be used to call a target foreign function at the address in the given native symbol. *

    * If the provided method type's return type is {@code MemorySegment}, then the resulting method handle features * an additional prefix parameter, of type {@link SegmentAllocator}, which will be used by the linker runtime * to allocate structs returned by-value. + *

    + * Calling this method is equivalent to the following code: + * {@snippet lang=java : + * linker.downcallHandle(function).bindTo(symbol); + * } * * @param symbol downcall symbol. - * @param type the method type. * @param function the function descriptor. - * @return the downcall method handle. - * @throws IllegalArgumentException in the case of a method type and function descriptor mismatch, or if the symbol - * is {@link MemoryAddress#NULL} - * - * @see SymbolLookup - */ - MethodHandle downcallHandle(Addressable symbol, MethodType type, FunctionDescriptor function); - - /** - * Obtain a foreign method handle, with the given type and featuring the given function descriptor, - * which can be used to call a target foreign function at the given address. - *

    - * If the provided method type's return type is {@code MemorySegment}, then the provided allocator will be used by - * the linker runtime to allocate structs returned by-value. - * - * @param symbol downcall symbol. - * @param allocator the segment allocator. - * @param type the method type. - * @param function the function descriptor. - * @return the downcall method handle. - * @throws IllegalArgumentException in the case of a method type and function descriptor mismatch, or if the symbol - * is {@link MemoryAddress#NULL} + * @return the downcall method handle. The method handle type is inferred + * @throws IllegalArgumentException if the provided descriptor contains either a sequence or a padding layout, + * or if the symbol is {@link MemoryAddress#NULL} * * @see SymbolLookup */ - MethodHandle downcallHandle(Addressable symbol, SegmentAllocator allocator, MethodType type, FunctionDescriptor function); + default MethodHandle downcallHandle(NativeSymbol symbol, FunctionDescriptor function) { + SharedUtils.checkSymbol(symbol); + return downcallHandle(function).bindTo(symbol); + } /** * Obtains a foreign method handle, with the given type and featuring the given function descriptor, which can be - * used to call a target foreign function at an address. - * The resulting method handle features a prefix parameter (as the first parameter) corresponding to the address, of - * type {@link Addressable}. + * used to call a target foreign function at the address in a dynamically provided native symbol. + * The resulting method handle features a prefix parameter (as the first parameter) corresponding to the foreign function + * entry point, of type {@link NativeSymbol}. *

    - * If the provided method type's return type is {@code MemorySegment}, then the resulting method handle features an + * If the provided function descriptor's return layout is a {@link GroupLayout}, then the resulting method handle features an * additional prefix parameter (inserted immediately after the address parameter), of type {@link SegmentAllocator}), * which will be used by the linker runtime to allocate structs returned by-value. *

    - * The returned method handle will throw an {@link IllegalArgumentException} if the target address passed to it is - * {@link MemoryAddress#NULL}, or a {@link NullPointerException} if the target address is {@code null}. + * The returned method handle will throw an {@link IllegalArgumentException} if the native symbol passed to it is + * associated with the {@link MemoryAddress#NULL} address, or a {@link NullPointerException} if the native symbol is {@code null}. * - * @param type the method type. * @param function the function descriptor. - * @return the downcall method handle. - * @throws IllegalArgumentException in the case of a method type and function descriptor mismatch. + * @return the downcall method handle. The method handle type is inferred + * from the provided function descriptor. + * @throws IllegalArgumentException if the provided descriptor contains either a sequence or a padding layout. * * @see SymbolLookup */ - MethodHandle downcallHandle(MethodType type, FunctionDescriptor function); + MethodHandle downcallHandle(FunctionDescriptor function); /** * Allocates a native stub with given scope which can be passed to other foreign functions (as a function pointer); * calling such a function pointer from native code will result in the execution of the provided method handle. * *

    - * The returned memory address is associated with the provided scope. When such scope is closed, + * The returned function pointer is associated with the provided scope. When such scope is closed, * the corresponding native stub will be deallocated. *

    * The target method handle should not throw any exceptions. If the target method handle does throw an exception, @@ -228,563 +238,34 @@ public sealed interface CLinker permits AbstractCLinker { * @param target the target method handle. * @param function the function descriptor. * @param scope the upcall stub scope. - * @return the native stub segment. - * @throws IllegalArgumentException if the target's method type and the function descriptor mismatch. + * @return the native stub symbol. + * @throws IllegalArgumentException if the provided descriptor contains either a sequence or a padding layout, + * or if it is determined that the target method handle can throw an exception, or if the target method handle + * has a type that does not match the upcall stub inferred type. * @throws IllegalStateException if {@code scope} has been already closed, or if access occurs from a thread other * than the thread owning {@code scope}. */ - MemoryAddress upcallStub(MethodHandle target, FunctionDescriptor function, ResourceScope scope); - - /** - * The layout for the {@code char} C type - */ - ValueLayout C_CHAR = pick(SysV.C_CHAR, Win64.C_CHAR, AArch64.C_CHAR); - /** - * The layout for the {@code short} C type - */ - ValueLayout C_SHORT = pick(SysV.C_SHORT, Win64.C_SHORT, AArch64.C_SHORT); - /** - * The layout for the {@code int} C type - */ - ValueLayout C_INT = pick(SysV.C_INT, Win64.C_INT, AArch64.C_INT); - /** - * The layout for the {@code long} C type - */ - ValueLayout C_LONG = pick(SysV.C_LONG, Win64.C_LONG, AArch64.C_LONG); - /** - * The layout for the {@code long long} C type. - */ - ValueLayout C_LONG_LONG = pick(SysV.C_LONG_LONG, Win64.C_LONG_LONG, AArch64.C_LONG_LONG); - /** - * The layout for the {@code float} C type - */ - ValueLayout C_FLOAT = pick(SysV.C_FLOAT, Win64.C_FLOAT, AArch64.C_FLOAT); - /** - * The layout for the {@code double} C type - */ - ValueLayout C_DOUBLE = pick(SysV.C_DOUBLE, Win64.C_DOUBLE, AArch64.C_DOUBLE); - /** - * The {@code T*} native type. - */ - ValueLayout C_POINTER = pick(SysV.C_POINTER, Win64.C_POINTER, AArch64.C_POINTER); - /** - * The layout for the {@code va_list} C type - */ - MemoryLayout C_VA_LIST = pick(SysV.C_VA_LIST, Win64.C_VA_LIST, AArch64.C_VA_LIST); - - /** - * Returns a memory layout that is suitable to use as the layout for variadic arguments in a specialized - * function descriptor. - * @param the memory layout type - * @param layout the layout the adapt - * @return a potentially newly created layout with the right attributes - */ - @SuppressWarnings("unchecked") - static T asVarArg(T layout) { - Objects.requireNonNull(layout); - return (T) PlatformLayouts.asVarArg(layout); - } - - /** - * Converts a Java string into a UTF-8 encoded, null-terminated C string, - * storing the result into a native memory segment allocated using the provided allocator. - *

    - * This method always replaces malformed-input and unmappable-character - * sequences with this charset's default replacement byte array. The - * {@link java.nio.charset.CharsetEncoder} class should be used when more - * control over the encoding process is required. - * - * @param str the Java string to be converted into a C string. - * @param allocator the allocator to be used for the native segment allocation. - * @return a new native memory segment containing the converted C string. - */ - static MemorySegment toCString(String str, SegmentAllocator allocator) { - Objects.requireNonNull(str); - Objects.requireNonNull(allocator); - return toCString(str.getBytes(StandardCharsets.UTF_8), allocator); - } - - /** - * Converts a Java string into a UTF-8 encoded, null-terminated C string, - * storing the result into a native memory segment associated with the provided resource scope. - *

    - * This method always replaces malformed-input and unmappable-character - * sequences with this charset's default replacement byte array. The - * {@link java.nio.charset.CharsetEncoder} class should be used when more - * control over the encoding process is required. - * - * @param str the Java string to be converted into a C string. - * @param scope the resource scope to be associated with the returned segment. - * @return a new native memory segment containing the converted C string. - * @throws IllegalStateException if {@code scope} has been already closed, or if access occurs from a thread other - * than the thread owning {@code scope}. - */ - static MemorySegment toCString(String str, ResourceScope scope) { - return toCString(str, SegmentAllocator.ofScope(scope)); - } - - /** - * Converts a UTF-8 encoded, null-terminated C string stored at given address into a Java string. - *

    - * This method always replaces malformed-input and unmappable-character - * sequences with this charset's default replacement string. The {@link - * java.nio.charset.CharsetDecoder} class should be used when more control - * over the decoding process is required. - *

    - * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * - * @param addr the address at which the string is stored. - * @return a Java string with the contents of the null-terminated C string at given address. - * @throws IllegalArgumentException if the size of the native string is greater than the largest string supported by the platform, - * or if {@code addr == MemoryAddress.NULL}. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. - */ - @CallerSensitive - static String toJavaString(MemoryAddress addr) { - Reflection.ensureNativeAccess(Reflection.getCallerClass()); - SharedUtils.checkAddress(addr); - return SharedUtils.toJavaStringInternal(NativeMemorySegmentImpl.EVERYTHING, addr.toRawLongValue()); - } - - /** - * Converts a UTF-8 encoded, null-terminated C string stored at given address into a Java string. - *

    - * This method always replaces malformed-input and unmappable-character - * sequences with this charset's default replacement string. The {@link - * java.nio.charset.CharsetDecoder} class should be used when more control - * over the decoding process is required. - * @param addr the address at which the string is stored. - * @return a Java string with the contents of the null-terminated C string at given address. - * @throws IllegalArgumentException if the size of the native string is greater than the largest string supported by the platform. - * @throws IllegalStateException if the size of the native string is greater than the size of the segment - * associated with {@code addr}, or if {@code addr} is associated with a segment that is not alive. - */ - static String toJavaString(MemorySegment addr) { - Objects.requireNonNull(addr); - return SharedUtils.toJavaStringInternal(addr, 0L); - } - - private static void copy(MemorySegment addr, byte[] bytes) { - var heapSegment = MemorySegment.ofArray(bytes); - addr.copyFrom(heapSegment); - MemoryAccess.setByteAtOffset(addr, bytes.length, (byte)0); - } - - private static MemorySegment toCString(byte[] bytes, SegmentAllocator allocator) { - MemorySegment addr = allocator.allocate(bytes.length + 1, 1L); - copy(addr, bytes); - return addr; - } + NativeSymbol upcallStub(MethodHandle target, FunctionDescriptor function, ResourceScope scope); /** - * Allocates memory of given size using malloc. - *

    - * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * - * @param size memory size to be allocated - * @return addr memory address of the allocated memory - * @throws OutOfMemoryError if malloc could not allocate the required amount of native memory. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + * Obtains the downcall method handle {@linkplain MethodType type} associated with a given function descriptor. + * @param functionDescriptor a function descriptor. + * @return the downcall method handle {@linkplain MethodType type} associated with a given function descriptor. + * @throws IllegalArgumentException if one or more layouts in the function descriptor are not supported + * (e.g. if they are sequence layouts or padding layouts). */ - @CallerSensitive - static MemoryAddress allocateMemory(long size) { - Reflection.ensureNativeAccess(Reflection.getCallerClass()); - MemoryAddress addr = SharedUtils.allocateMemoryInternal(size); - if (addr.equals(MemoryAddress.NULL)) { - throw new OutOfMemoryError(); - } else { - return addr; - } + static MethodType downcallType(FunctionDescriptor functionDescriptor) { + return SharedUtils.inferMethodType(functionDescriptor, false); } /** - * Frees the memory pointed by the given memory address. - *

    - * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * - * @param addr memory address of the native memory to be freed - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * @throws IllegalArgumentException if {@code addr == MemoryAddress.NULL}. - * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + * Obtains the method handle {@linkplain MethodType type} associated with an upcall stub with given function descriptor. + * @param functionDescriptor a function descriptor. + * @return the method handle {@linkplain MethodType type} associated with an upcall stub with given function descriptor. + * @throws IllegalArgumentException if one or more layouts in the function descriptor are not supported + * (e.g. if they are sequence layouts or padding layouts). */ - @CallerSensitive - static void freeMemory(MemoryAddress addr) { - Reflection.ensureNativeAccess(Reflection.getCallerClass()); - SharedUtils.checkAddress(addr); - SharedUtils.freeMemoryInternal(addr); - } - - /** - * An interface that models a C {@code va_list}. - *

    - * A va list is a stateful cursor used to iterate over a set of variadic arguments. - *

    - * Per the C specification (see C standard 6.5.2.2 Function calls - item 6), - * arguments to variadic calls are erased by way of 'default argument promotions', - * which erases integral types by way of integer promotion (see C standard 6.3.1.1 - item 2), - * and which erases all {@code float} arguments to {@code double}. - *

    - * As such, this interface only supports reading {@code int}, {@code double}, - * and any other type that fits into a {@code long}. - * - *

    Unless otherwise specified, passing a {@code null} argument, or an array argument containing one or more {@code null} - * elements to a method in this class causes a {@link NullPointerException NullPointerException} to be thrown.

    - */ - sealed interface VaList extends Addressable permits WinVaList, SysVVaList, LinuxAArch64VaList, MacOsAArch64VaList, SharedUtils.EmptyVaList { - - /** - * Reads the next value as an {@code int} and advances this va list's position. - * - * @param layout the layout of the value - * @return the value read as an {@code int} - * @throws IllegalStateException if the resource scope associated with this instance has been closed - * (see {@link #scope()}). - * @throws IllegalArgumentException if the given memory layout is not compatible with {@code int} - */ - int vargAsInt(MemoryLayout layout); - - /** - * Reads the next value as a {@code long} and advances this va list's position. - * - * @param layout the layout of the value - * @return the value read as an {@code long} - * @throws IllegalStateException if the resource scope associated with this instance has been closed - * (see {@link #scope()}). - * @throws IllegalArgumentException if the given memory layout is not compatible with {@code long} - */ - long vargAsLong(MemoryLayout layout); - - /** - * Reads the next value as a {@code double} and advances this va list's position. - * - * @param layout the layout of the value - * @return the value read as an {@code double} - * @throws IllegalStateException if the resource scope associated with this instance has been closed - * (see {@link #scope()}). - * @throws IllegalArgumentException if the given memory layout is not compatible with {@code double} - */ - double vargAsDouble(MemoryLayout layout); - - /** - * Reads the next value as a {@code MemoryAddress} and advances this va list's position. - * - * @param layout the layout of the value - * @return the value read as an {@code MemoryAddress} - * @throws IllegalStateException if the resource scope associated with this instance has been closed - * (see {@link #scope()}). - * @throws IllegalArgumentException if the given memory layout is not compatible with {@code MemoryAddress} - */ - MemoryAddress vargAsAddress(MemoryLayout layout); - - /** - * Reads the next value as a {@code MemorySegment}, and advances this va list's position. - *

    - * The memory segment returned by this method will be allocated using the given {@link SegmentAllocator}. - * - * @param layout the layout of the value - * @param allocator the allocator to be used for the native segment allocation - * @return the value read as an {@code MemorySegment} - * @throws IllegalStateException if the resource scope associated with this instance has been closed - * (see {@link #scope()}). - * @throws IllegalArgumentException if the given memory layout is not compatible with {@code MemorySegment} - */ - MemorySegment vargAsSegment(MemoryLayout layout, SegmentAllocator allocator); - - /** - * Reads the next value as a {@code MemorySegment}, and advances this va list's position. - *

    - * The memory segment returned by this method will be associated with the given {@link ResourceScope}. - * - * @param layout the layout of the value - * @param scope the resource scope to be associated with the returned segment - * @return the value read as an {@code MemorySegment} - * @throws IllegalStateException if the resource scope associated with this instance has been closed - * (see {@link #scope()}). - * @throws IllegalArgumentException if the given memory layout is not compatible with {@code MemorySegment} - * @throws IllegalStateException if {@code scope} has been already closed, or if access occurs from a thread other - * than the thread owning {@code scope}. - */ - MemorySegment vargAsSegment(MemoryLayout layout, ResourceScope scope); - - /** - * Skips a number of elements with the given memory layouts, and advances this va list's position. - * - * @param layouts the layout of the value - * @throws IllegalStateException if the resource scope associated with this instance has been closed - * (see {@link #scope()}). - */ - void skip(MemoryLayout... layouts); - - /** - * Returns the resource scope associated with this instance. - * @return the resource scope associated with this instance. - */ - ResourceScope scope(); - - /** - * Copies this C {@code va_list} at its current position. Copying is useful to traverse the va list's elements - * starting from the current position, without affecting the state of the original va list, essentially - * allowing the elements to be traversed multiple times. - *

    - * Any native resource required by the execution of this method will be allocated in the resource scope - * associated with this instance (see {@link #scope()}). - *

    - * This method only copies the va list cursor itself and not the memory that may be attached to the - * va list which holds its elements. That means that if this va list was created with the - * {@link #make(Consumer, ResourceScope)} method, closing this va list will also release the native memory that holds its - * elements, making the copy unusable. - * - * @return a copy of this C {@code va_list}. - * @throws IllegalStateException if the resource scope associated with this instance has been closed - * (see {@link #scope()}). - */ - VaList copy(); - - /** - * Returns the memory address of the C {@code va_list} associated with this instance. - * The returned memory address is associated with same resource scope as that associated with this instance. - * - * @return the memory address of the C {@code va_list} associated with this instance. - */ - @Override - MemoryAddress address(); - - /** - * Constructs a new {@code VaList} instance out of a memory address pointing to an existing C {@code va_list}, - * backed by the {@linkplain ResourceScope#globalScope() global} resource scope. - *

    - * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * - * @param address a memory address pointing to an existing C {@code va_list}. - * @return a new {@code VaList} instance backed by the C {@code va_list} at {@code address}. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. - */ - @CallerSensitive - static VaList ofAddress(MemoryAddress address) { - Reflection.ensureNativeAccess(Reflection.getCallerClass()); - return SharedUtils.newVaListOfAddress(address, ResourceScope.globalScope()); - } - - /** - * Constructs a new {@code VaList} instance out of a memory address pointing to an existing C {@code va_list}, - * with given resource scope. - *

    - * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * - * @param address a memory address pointing to an existing C {@code va_list}. - * @param scope the resource scope to be associated with the returned {@code VaList} instance. - * @return a new {@code VaList} instance backed by the C {@code va_list} at {@code address}. - * @throws IllegalStateException if {@code scope} has been already closed, or if access occurs from a thread other - * than the thread owning {@code scope}. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. - */ - @CallerSensitive - static VaList ofAddress(MemoryAddress address, ResourceScope scope) { - Reflection.ensureNativeAccess(Reflection.getCallerClass()); - Objects.requireNonNull(address); - Objects.requireNonNull(scope); - return SharedUtils.newVaListOfAddress(address, scope); - } - - /** - * Constructs a new {@code VaList} using a builder (see {@link Builder}), associated with a given - * {@linkplain ResourceScope resource scope}. - *

    - * If this method needs to allocate native memory, such memory will be managed by the given - * {@linkplain ResourceScope resource scope}, and will be released when the resource scope is {@linkplain ResourceScope#close closed}. - *

    - * Note that when there are no elements added to the created va list, - * this method will return the same as {@link #empty()}. - * - * @param actions a consumer for a builder (see {@link Builder}) which can be used to specify the elements - * of the underlying C {@code va_list}. - * @param scope the scope to be used for the valist allocation. - * @return a new {@code VaList} instance backed by a fresh C {@code va_list}. - * @throws IllegalStateException if {@code scope} has been already closed, or if access occurs from a thread other - * than the thread owning {@code scope}. - */ - static VaList make(Consumer actions, ResourceScope scope) { - Objects.requireNonNull(actions); - Objects.requireNonNull(scope); - return SharedUtils.newVaList(actions, scope); - } - - /** - * Returns an empty C {@code va_list} constant. - *

    - * The returned {@code VaList} can not be closed. - * - * @return a {@code VaList} modelling an empty C {@code va_list}. - */ - static VaList empty() { - return SharedUtils.emptyVaList(); - } - - /** - * A builder interface used to construct a C {@code va_list}. - * - *

    Unless otherwise specified, passing a {@code null} argument, or an array argument containing one or more {@code null} - * elements to a method in this class causes a {@link NullPointerException NullPointerException} to be thrown.

    - */ - sealed interface Builder permits WinVaList.Builder, SysVVaList.Builder, LinuxAArch64VaList.Builder, MacOsAArch64VaList.Builder { - - /** - * Adds a native value represented as an {@code int} to the C {@code va_list} being constructed. - * - * @param layout the native layout of the value. - * @param value the value, represented as an {@code int}. - * @return this builder. - * @throws IllegalArgumentException if the given memory layout is not compatible with {@code int} - */ - Builder vargFromInt(ValueLayout layout, int value); - - /** - * Adds a native value represented as a {@code long} to the C {@code va_list} being constructed. - * - * @param layout the native layout of the value. - * @param value the value, represented as a {@code long}. - * @return this builder. - * @throws IllegalArgumentException if the given memory layout is not compatible with {@code long} - */ - Builder vargFromLong(ValueLayout layout, long value); - - /** - * Adds a native value represented as a {@code double} to the C {@code va_list} being constructed. - * - * @param layout the native layout of the value. - * @param value the value, represented as a {@code double}. - * @return this builder. - * @throws IllegalArgumentException if the given memory layout is not compatible with {@code double} - */ - Builder vargFromDouble(ValueLayout layout, double value); - - /** - * Adds a native value represented as a {@code MemoryAddress} to the C {@code va_list} being constructed. - * - * @param layout the native layout of the value. - * @param value the value, represented as a {@code Addressable}. - * @return this builder. - * @throws IllegalArgumentException if the given memory layout is not compatible with {@code MemoryAddress} - */ - Builder vargFromAddress(ValueLayout layout, Addressable value); - - /** - * Adds a native value represented as a {@code MemorySegment} to the C {@code va_list} being constructed. - * - * @param layout the native layout of the value. - * @param value the value, represented as a {@code MemorySegment}. - * @return this builder. - * @throws IllegalArgumentException if the given memory layout is not compatible with {@code MemorySegment} - */ - Builder vargFromSegment(GroupLayout layout, MemorySegment value); - } - } - - /** - * A C type kind. Each kind corresponds to a particular C language builtin type, and can be attached to - * {@link ValueLayout} instances using the {@link MemoryLayout#withAttribute(String, Constable)} in order - * to obtain a layout which can be classified accordingly by {@link CLinker#downcallHandle(Addressable, MethodType, FunctionDescriptor)} - * and {@link CLinker#upcallStub(MethodHandle, FunctionDescriptor, ResourceScope)}. - */ - enum TypeKind { - /** - * A kind corresponding to the integral C {@code char} type - */ - CHAR(true), - /** - * A kind corresponding to the integral C {@code short} type - */ - SHORT(true), - /** - * A kind corresponding to the integral C {@code int} type - */ - INT(true), - /** - * A kind corresponding to the integral C {@code long} type - */ - LONG(true), - /** - * A kind corresponding to the integral C {@code long long} type - */ - LONG_LONG(true), - /** - * A kind corresponding to the floating-point C {@code float} type - */ - FLOAT(false), - /** - * A kind corresponding to the floating-point C {@code double} type - */ - DOUBLE(false), - /** - * A kind corresponding to the an integral C pointer type - */ - POINTER(false); - - private final boolean isIntegral; - - TypeKind(boolean isIntegral) { - this.isIntegral = isIntegral; - } - - /** - * Is this kind integral? - * - * @return true if this kind is integral - */ - public boolean isIntegral() { - return isIntegral; - } - - /** - * Is this kind a floating point type? - * - * @return true if this kind is a floating point type - */ - public boolean isFloat() { - return !isIntegral() && !isPointer(); - } - - /** - * Is this kind a pointer kind? - * - * @return true if this kind is a pointer kind - */ - public boolean isPointer() { - return this == POINTER; - } - - /** - * The layout attribute name associated with this classification kind. Clients can retrieve the type kind - * of a layout using the following code: - *
    {@code
    -        ValueLayout layout = ...
    -        TypeKind = layout.attribute(TypeKind.ATTR_NAME).orElse(null);
    -         * }
    - */ - public static final String ATTR_NAME = "abi/kind"; + static MethodType upcallType(FunctionDescriptor functionDescriptor) { + return SharedUtils.inferMethodType(functionDescriptor, true); } } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/FunctionDescriptor.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/FunctionDescriptor.java index 2124eea6ccdecd90b2bdd48ab5b8ba027106fe6e..9c557ec9e9e90c49d045e4922d907b64ed851c0d 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/FunctionDescriptor.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/FunctionDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,10 +30,7 @@ import java.lang.constant.ConstantDescs; import java.lang.constant.DynamicConstantDesc; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; @@ -46,60 +43,16 @@ import java.util.stream.Stream; *

    Unless otherwise specified, passing a {@code null} argument, or an array argument containing one or more {@code null} * elements to a method in this class causes a {@link NullPointerException NullPointerException} to be thrown.

    */ -public final class FunctionDescriptor implements Constable { - - /** - * The name of the function descriptor attribute (see {@link #attributes()} used to mark trivial functions. The - * attribute value must be a boolean. - */ - public static final String TRIVIAL_ATTRIBUTE_NAME = "abi/trivial"; +public sealed class FunctionDescriptor implements Constable permits FunctionDescriptor.VariadicFunction { private final MemoryLayout resLayout; - private final MemoryLayout[] argLayouts; - private final Map attributes; + private final List argLayouts; - private FunctionDescriptor(MemoryLayout resLayout, Map attributes, MemoryLayout... argLayouts) { + private FunctionDescriptor(MemoryLayout resLayout, List argLayouts) { this.resLayout = resLayout; - this.attributes = attributes; this.argLayouts = argLayouts; } - /** - * Returns the attribute with the given name (if it exists). - * - * @param name the attribute name. - * @return the attribute with the given name (if it exists). - */ - public Optional attribute(String name) { - Objects.requireNonNull(name); - return Optional.ofNullable(attributes.get(name)); - } - - /** - * Returns a stream of the attribute names associated with this function descriptor. - * - * @return a stream of the attribute names associated with this function descriptor. - */ - public Stream attributes() { - return attributes.keySet().stream(); - } - - /** - * Returns a new function descriptor which features the same attributes as this descriptor, plus the newly specified attribute. - * If this descriptor already contains an attribute with the same name, the existing attribute value is overwritten in the returned - * descriptor. - * - * @param name the attribute name. - * @param value the attribute value. - * @return a new function descriptor which features the same attributes as this descriptor, plus the newly specified attribute. - */ - public FunctionDescriptor withAttribute(String name, Constable value) { - Objects.requireNonNull(name); - Map newAttributes = new HashMap<>(attributes); - newAttributes.put(name, value); - return new FunctionDescriptor(resLayout, newAttributes, argLayouts); - } - /** * Returns the return layout associated with this function. * @return the return layout. @@ -113,7 +66,7 @@ public final class FunctionDescriptor implements Constable { * @return the argument layouts. */ public List argumentLayouts() { - return Arrays.asList(argLayouts); + return argLayouts; } /** @@ -126,7 +79,7 @@ public final class FunctionDescriptor implements Constable { Objects.requireNonNull(resLayout); Objects.requireNonNull(argLayouts); Arrays.stream(argLayouts).forEach(Objects::requireNonNull); - return new FunctionDescriptor(resLayout, Map.of(), argLayouts); + return new FunctionDescriptor(resLayout, List.of(argLayouts)); } /** @@ -137,7 +90,31 @@ public final class FunctionDescriptor implements Constable { public static FunctionDescriptor ofVoid(MemoryLayout... argLayouts) { Objects.requireNonNull(argLayouts); Arrays.stream(argLayouts).forEach(Objects::requireNonNull); - return new FunctionDescriptor(null, Map.of(), argLayouts); + return new FunctionDescriptor(null, List.of(argLayouts)); + } + + /** + * Obtain a specialized variadic function descriptor, by appending given variadic layouts to this + * function descriptor argument layouts. The resulting function descriptor can report the position + * of the {@linkplain #firstVariadicArgumentIndex() first variadic argument}, and cannot be altered + * in any way: for instance, calling {@link #changeReturnLayout(MemoryLayout)} on the resulting descriptor + * will throw an {@link UnsupportedOperationException}. + * @param variadicLayouts the variadic argument layouts to be appended to this descriptor argument layouts. + * @return a new variadic function descriptor, or this descriptor if {@code variadicLayouts.length == 0}. + */ + public FunctionDescriptor asVariadic(MemoryLayout... variadicLayouts) { + Objects.requireNonNull(variadicLayouts); + Arrays.stream(variadicLayouts).forEach(Objects::requireNonNull); + return variadicLayouts.length == 0 ? this : new VariadicFunction(this, variadicLayouts); + } + + /** + * The index of the first variadic argument layout (where defined). + * @return The index of the first variadic argument layout, or {@code -1} if this is not a + * {@linkplain #asVariadic(MemoryLayout...) variadic} layout. + */ + public int firstVariadicArgumentIndex() { + return -1; } /** @@ -146,12 +123,27 @@ public final class FunctionDescriptor implements Constable { * @param addedLayouts the argument layouts to append. * @return the new function descriptor. */ - public FunctionDescriptor withAppendedArgumentLayouts(MemoryLayout... addedLayouts) { - Objects.requireNonNull(addedLayouts); - Arrays.stream(addedLayouts).forEach(Objects::requireNonNull); - MemoryLayout[] newLayouts = Arrays.copyOf(argLayouts, argLayouts.length + addedLayouts.length); - System.arraycopy(addedLayouts, 0, newLayouts, argLayouts.length, addedLayouts.length); - return new FunctionDescriptor(resLayout, attributes, newLayouts); + public FunctionDescriptor appendArgumentLayouts(MemoryLayout... addedLayouts) { + return insertArgumentLayouts(argLayouts.size(), addedLayouts); + } + + /** + * Create a new function descriptor with the given argument layouts inserted at the given index, into the argument + * layout array of this function descriptor. + * @param index the index at which to insert the arguments + * @param addedLayouts the argument layouts to insert at given index. + * @return the new function descriptor. + * @throws IllegalArgumentException if {@code index < 0 || index > argumentLayouts().size()}. + */ + public FunctionDescriptor insertArgumentLayouts(int index, MemoryLayout... addedLayouts) { + if (index < 0 || index > argLayouts.size()) + throw new IllegalArgumentException("Index out of bounds: " + index); + List added = List.of(addedLayouts); // null check on array and its elements + List newLayouts = new ArrayList<>(argLayouts.size() + addedLayouts.length); + newLayouts.addAll(argLayouts.subList(0, index)); + newLayouts.addAll(added); + newLayouts.addAll(argLayouts.subList(index, argLayouts.size())); + return new FunctionDescriptor(resLayout, newLayouts); } /** @@ -159,17 +151,18 @@ public final class FunctionDescriptor implements Constable { * @param newReturn the new return layout. * @return the new function descriptor. */ - public FunctionDescriptor withReturnLayout(MemoryLayout newReturn) { + public FunctionDescriptor changeReturnLayout(MemoryLayout newReturn) { Objects.requireNonNull(newReturn); - return new FunctionDescriptor(newReturn, attributes, argLayouts); + return new FunctionDescriptor(newReturn, argLayouts); } /** - * Create a new function descriptor with the return layout dropped. + * Create a new function descriptor with the return layout dropped. This is useful to model functions + * which return no values. * @return the new function descriptor. */ - public FunctionDescriptor withVoidReturnLayout() { - return new FunctionDescriptor(null, attributes, argLayouts); + public FunctionDescriptor dropReturnLayout() { + return new FunctionDescriptor(null, argLayouts); } /** @@ -187,7 +180,7 @@ public final class FunctionDescriptor implements Constable { /** * Compares the specified object with this function descriptor for equality. Returns {@code true} if and only if the specified - * object is also a function descriptor, and all of the following conditions are met: + * object is also a function descriptor, and all the following conditions are met: *
      *
    • the two function descriptors have equals return layouts (see {@link MemoryLayout#equals(Object)}), or both have no return layout
    • *
    • the two function descriptors have argument layouts that are pair-wise equal (see {@link MemoryLayout#equals(Object)}) @@ -201,11 +194,10 @@ public final class FunctionDescriptor implements Constable { if (this == other) { return true; } - if (!(other instanceof FunctionDescriptor)) { + if (!(other instanceof FunctionDescriptor f)) { return false; } - FunctionDescriptor f = (FunctionDescriptor) other; - return Objects.equals(resLayout, f.resLayout) && Arrays.equals(argLayouts, f.argLayouts); + return Objects.equals(resLayout, f.resLayout) && Objects.equals(argLayouts, f.argLayouts); } /** @@ -214,10 +206,18 @@ public final class FunctionDescriptor implements Constable { */ @Override public int hashCode() { - int hashCode = Arrays.hashCode(argLayouts); + int hashCode = Objects.hashCode(argLayouts); return resLayout == null ? hashCode : resLayout.hashCode() ^ hashCode; } + /** + * Returns an {@link Optional} containing the nominal descriptor for this + * function descriptor, if one can be constructed, or an empty {@link Optional} + * if one cannot be constructed. + * + * @return An {@link Optional} containing the resulting nominal descriptor, + * or an empty {@link Optional} if one cannot be constructed. + */ @Override public Optional> describeConstable() { List constants = new ArrayList<>(); @@ -229,6 +229,47 @@ public final class FunctionDescriptor implements Constable { constants.add(argLayout.describeConstable().get()); } return Optional.of(DynamicConstantDesc.ofNamed( - ConstantDescs.BSM_INVOKE, "function", AbstractLayout.CD_FUNCTION_DESC, constants.toArray(new ConstantDesc[0]))); + ConstantDescs.BSM_INVOKE, "function", AbstractLayout.CD_FUNCTION_DESC, constants.toArray(new ConstantDesc[0]))); + } + + static final class VariadicFunction extends FunctionDescriptor { + + private final int firstVariadicIndex; + + public VariadicFunction(FunctionDescriptor descriptor, MemoryLayout... argLayouts) { + super(descriptor.returnLayout().orElse(null), + Stream.concat(descriptor.argumentLayouts().stream(), Stream.of(argLayouts)).toList()); + this.firstVariadicIndex = descriptor.argumentLayouts().size(); + } + + @Override + public int firstVariadicArgumentIndex() { + return firstVariadicIndex; + } + + @Override + public FunctionDescriptor appendArgumentLayouts(MemoryLayout... addedLayouts) { + throw new UnsupportedOperationException(); + } + + @Override + public FunctionDescriptor insertArgumentLayouts(int index, MemoryLayout... addedLayouts) { + throw new UnsupportedOperationException(); + } + + @Override + public FunctionDescriptor changeReturnLayout(MemoryLayout newReturn) { + throw new UnsupportedOperationException(); + } + + @Override + public FunctionDescriptor dropReturnLayout() { + throw new UnsupportedOperationException(); + } + + @Override + public Optional> describeConstable() { + return Optional.empty(); + } } } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/GroupLayout.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/GroupLayout.java index bcb5605252701da73ae7aa9100ec339f526e602c..d08bb716ae893520e5ba7071c4ce0e9ed931f540 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/GroupLayout.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/GroupLayout.java @@ -25,14 +25,12 @@ */ package jdk.incubator.foreign; -import java.lang.constant.Constable; import java.lang.constant.ConstantDesc; import java.lang.constant.ConstantDescs; import java.lang.constant.DynamicConstantDesc; import java.lang.constant.MethodHandleDesc; import java.util.Collections; import java.util.List; -import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.OptionalLong; @@ -40,7 +38,7 @@ import java.util.function.LongBinaryOperator; import java.util.stream.Collectors; /** - * A group layout is used to combine together multiple member layouts. There are two ways in which member layouts + * A group layout is used to combine multiple member layouts. There are two ways in which member layouts * can be combined: if member layouts are laid out one after the other, the resulting group layout is said to be a struct * (see {@link MemoryLayout#structLayout(MemoryLayout...)}); conversely, if all member layouts are laid out at the same starting offset, * the resulting group layout is said to be a union (see {@link MemoryLayout#unionLayout(MemoryLayout...)}). @@ -105,11 +103,11 @@ public final class GroupLayout extends AbstractLayout implements MemoryLayout { private final List elements; GroupLayout(Kind kind, List elements) { - this(kind, elements, kind.alignof(elements), Map.of()); + this(kind, elements, kind.alignof(elements), Optional.empty()); } - GroupLayout(Kind kind, List elements, long alignment, Map attributes) { - super(kind.sizeof(elements), alignment, attributes); + GroupLayout(Kind kind, List elements, long alignment, Optional name) { + super(kind.sizeof(elements), alignment, name); this.kind = kind; this.elements = elements; } @@ -160,10 +158,9 @@ public final class GroupLayout extends AbstractLayout implements MemoryLayout { if (!super.equals(other)) { return false; } - if (!(other instanceof GroupLayout)) { + if (!(other instanceof GroupLayout g)) { return false; } - GroupLayout g = (GroupLayout)other; return kind.equals(g.kind) && elements.equals(g.elements); } @@ -173,8 +170,8 @@ public final class GroupLayout extends AbstractLayout implements MemoryLayout { } @Override - GroupLayout dup(long alignment, Map attributes) { - return new GroupLayout(kind, elements, alignment, attributes); + GroupLayout dup(long alignment, Optional name) { + return new GroupLayout(kind, elements, alignment, name); } @Override @@ -212,12 +209,4 @@ public final class GroupLayout extends AbstractLayout implements MemoryLayout { public GroupLayout withBitAlignment(long alignmentBits) { return (GroupLayout)super.withBitAlignment(alignmentBits); } - - /** - * {@inheritDoc} - */ - @Override - public GroupLayout withAttribute(String name, Constable value) { - return (GroupLayout)super.withAttribute(name, value); - } } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryAccess.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryAccess.java deleted file mode 100644 index 3e2182b5963871d0f6df45aee16f626a08329618..0000000000000000000000000000000000000000 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryAccess.java +++ /dev/null @@ -1,1455 +0,0 @@ -/* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.incubator.foreign; - -import jdk.internal.access.foreign.MemorySegmentProxy; -import jdk.internal.vm.annotation.ForceInline; - -import java.lang.invoke.VarHandle; -import java.nio.ByteOrder; -import java.util.Objects; - -/** - * This class defines ready-made static accessors which can be used to dereference memory segments in many ways. - *

      - * The most primitive accessors (see {@link #getIntAtOffset(MemorySegment, long, ByteOrder)}) take a segment, an offset - * (expressed in bytes) and a byte order. The final address at which the dereference will occur will be computed by offsetting - * the base address by the specified offset, as if by calling {@link MemoryAddress#addOffset(long)} on the specified base address. - *

      - * In cases where no offset is required, overloads are provided (see {@link #getInt(MemorySegment, ByteOrder)}) so that - * clients can omit the offset coordinate. - *

      - * To help dereferencing in array-like use cases (e.g. where the layout of a given memory segment is a sequence - * layout of given size an element count), higher-level overloads are also provided (see {@link #getIntAtIndex(MemorySegment, long, ByteOrder)}), - * which take a segment and a logical element index. The formula to obtain the byte offset {@code O} from an - * index {@code I} is given by {@code O = I * S} where {@code S} is the size (expressed in bytes) of the element to - * be dereferenced. - *

      - * In cases where native byte order is preferred, overloads are provided (see {@link #getIntAtOffset(MemorySegment, long)}) - * so that clients can omit the byte order parameter. - * - *

      Unless otherwise specified, passing a {@code null} argument, or an array argument containing one or more {@code null} - * elements to a method in this class causes a {@link NullPointerException NullPointerException} to be thrown.

      - */ -public final class MemoryAccess { - - private MemoryAccess() { - // just the one - } - - private static final VarHandle byte_handle = MemoryHandles.varHandle(byte.class, ByteOrder.nativeOrder()); - private static final VarHandle char_LE_handle = unalignedHandle(MemoryLayouts.BITS_16_LE, char.class); - private static final VarHandle short_LE_handle = unalignedHandle(MemoryLayouts.BITS_16_LE, short.class); - private static final VarHandle int_LE_handle = unalignedHandle(MemoryLayouts.BITS_32_LE, int.class); - private static final VarHandle float_LE_handle = unalignedHandle(MemoryLayouts.BITS_32_LE, float.class); - private static final VarHandle long_LE_handle = unalignedHandle(MemoryLayouts.BITS_64_LE, long.class); - private static final VarHandle double_LE_handle = unalignedHandle(MemoryLayouts.BITS_64_LE, double.class); - private static final VarHandle char_BE_handle = unalignedHandle(MemoryLayouts.BITS_16_BE, char.class); - private static final VarHandle short_BE_handle = unalignedHandle(MemoryLayouts.BITS_16_BE, short.class); - private static final VarHandle int_BE_handle = unalignedHandle(MemoryLayouts.BITS_32_BE, int.class); - private static final VarHandle float_BE_handle = unalignedHandle(MemoryLayouts.BITS_32_BE, float.class); - private static final VarHandle long_BE_handle = unalignedHandle(MemoryLayouts.BITS_64_BE, long.class); - private static final VarHandle double_BE_handle = unalignedHandle(MemoryLayouts.BITS_64_BE, double.class); - private static final VarHandle address_handle; - - static { - Class carrier = switch ((int) MemoryLayouts.ADDRESS.byteSize()) { - case 4 -> int.class; - case 8 -> long.class; - default -> throw new ExceptionInInitializerError("Unsupported pointer size: " + MemoryLayouts.ADDRESS.byteSize()); - }; - address_handle = MemoryHandles.asAddressVarHandle(unalignedHandle(MemoryLayouts.ADDRESS, carrier)); - } - - private static VarHandle unalignedHandle(ValueLayout elementLayout, Class carrier) { - return MemoryHandles.varHandle(carrier, 1, elementLayout.order()); - } - - // Note: all the accessor methods defined below take advantage of argument type profiling - // (see src/hotspot/share/oops/methodData.cpp) which greatly enhances performance when the same accessor - // method is used repeatedly with different segment kinds (e.g. on-heap vs. off-heap). - - /** - * Reads a byte from given segment and offset. - * - * @param segment the segment to be dereferenced. - * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}. - * @return a byte value read from {@code segment}. - */ - @ForceInline - public static byte getByteAtOffset(MemorySegment segment, long offset) { - Objects.requireNonNull(segment); - return (byte)byte_handle.get(segment, offset); - } - - /** - * Writes a byte at given segment and offset. - * - * @param segment the segment to be dereferenced. - * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}. - * @param value the byte value to be written. - */ - @ForceInline - public static void setByteAtOffset(MemorySegment segment, long offset, byte value) { - Objects.requireNonNull(segment); - byte_handle.set(segment, offset, value); - } - - /** - * Reads a char from given segment and offset, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    getCharAtOffset(segment, offset, ByteOrder.nativeOrder());
      -     * }
      - * @param segment the segment to be dereferenced. - * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}. - * @return a char value read from {@code segment}. - */ - @ForceInline - public static char getCharAtOffset(MemorySegment segment, long offset) { - return getCharAtOffset(segment, offset, ByteOrder.nativeOrder()); - } - - /** - * Writes a char at given segment and offset, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    setCharAtOffset(segment, offset, ByteOrder.nativeOrder(), value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}. - * @param value the char value to be written. - */ - @ForceInline - public static void setCharAtOffset(MemorySegment segment, long offset, char value) { - setCharAtOffset(segment, offset, ByteOrder.nativeOrder(), value); - } - - /** - * Reads a short from given segment and offset, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    getShortAtOffset(segment, offset, ByteOrder.nativeOrder());
      -     * }
      - * @param segment the segment to be dereferenced. - * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}. - * @return a short value read from {@code segment}. - */ - @ForceInline - public static short getShortAtOffset(MemorySegment segment, long offset) { - return getShortAtOffset(segment, offset, ByteOrder.nativeOrder()); - } - - /** - * Writes a short at given segment and offset, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    setShortAtOffset(segment, offset, ByteOrder.nativeOrder(), value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}. - * @param value the short value to be written. - */ - @ForceInline - public static void setShortAtOffset(MemorySegment segment, long offset, short value) { - setShortAtOffset(segment, offset, ByteOrder.nativeOrder(), value); - } - - /** - * Reads an int from given segment and offset, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    getIntAtOffset(segment, offset, ByteOrder.nativeOrder());
      -     * }
      - * @param segment the segment to be dereferenced. - * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}. - * @return an int value read from {@code segment}. - */ - @ForceInline - public static int getIntAtOffset(MemorySegment segment, long offset) { - return getIntAtOffset(segment, offset, ByteOrder.nativeOrder()); - } - - /** - * Writes an int at given segment and offset, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    setIntAtOffset(segment, offset, ByteOrder.nativeOrder(), value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}. - * @param value the int value to be written. - */ - @ForceInline - public static void setIntAtOffset(MemorySegment segment, long offset, int value) { - setIntAtOffset(segment, offset, ByteOrder.nativeOrder(), value); - } - - /** - * Reads a float from given segment and offset, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    getFloatAtOffset(segment, offset, ByteOrder.nativeOrder());
      -     * }
      - * @param segment the segment to be dereferenced. - * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}. - * @return a float value read from {@code segment}. - */ - @ForceInline - public static float getFloatAtOffset(MemorySegment segment, long offset) { - return getFloatAtOffset(segment, offset, ByteOrder.nativeOrder()); - } - - /** - * Writes a float at given segment and offset, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    setFloatAtOffset(segment, offset, ByteOrder.nativeOrder(), value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}. - * @param value the float value to be written. - */ - @ForceInline - public static void setFloatAtOffset(MemorySegment segment, long offset, float value) { - setFloatAtOffset(segment, offset, ByteOrder.nativeOrder(), value); - } - - /** - * Reads a long from given segment and offset, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    getLongAtOffset(segment, offset, ByteOrder.nativeOrder());
      -     * }
      - * @param segment the segment to be dereferenced. - * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}. - * @return a long value read from {@code segment}. - */ - @ForceInline - public static long getLongAtOffset(MemorySegment segment, long offset) { - return getLongAtOffset(segment, offset, ByteOrder.nativeOrder()); - } - - /** - * Writes a long at given segment and offset, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    setLongAtOffset(segment, offset, ByteOrder.nativeOrder(), value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}. - * @param value the long value to be written. - */ - @ForceInline - public static void setLongAtOffset(MemorySegment segment, long offset, long value) { - setLongAtOffset(segment, offset, ByteOrder.nativeOrder(), value); - } - - /** - * Reads a double from given segment and offset, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    getDoubleAtOffset(segment, offset, ByteOrder.nativeOrder());
      -     * }
      - * @param segment the segment to be dereferenced. - * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}. - * @return a double value read from {@code segment}. - */ - @ForceInline - public static double getDoubleAtOffset(MemorySegment segment, long offset) { - return getDoubleAtOffset(segment, offset, ByteOrder.nativeOrder()); - } - - /** - * Writes a double at given segment and offset, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    setDoubleAtOffset(segment, offset, ByteOrder.nativeOrder(), value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}. - * @param value the double value to be written. - */ - @ForceInline - public static void setDoubleAtOffset(MemorySegment segment, long offset, double value) { - setDoubleAtOffset(segment, offset, ByteOrder.nativeOrder(), value); - } - - /** - * Reads a memory address from given segment and offset, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent (e.g. on a 64-bit platform) to the following code: - *

      {@code
      -    VarHandle handle = MemoryHandles.asAddressHandle(MemoryHandles.varHandle(long.class, ByteOrder.nativeOrder()));
      -    MemoryAddress value = (MemoryAddress)handle.get(segment, offset);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}. - * @return a memory address read from {@code segment}. - */ - @ForceInline - public static MemoryAddress getAddressAtOffset(MemorySegment segment, long offset) { - Objects.requireNonNull(segment); - return (MemoryAddress)address_handle.get(segment, offset); - } - - /** - * Writes a memory address at given segment and offset, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent (e.g. on a 64-bit platform) to the following code: - *

      {@code
      -    VarHandle handle = MemoryHandles.asAddressHandle(MemoryHandles.varHandle(long.class, ByteOrder.nativeOrder()));
      -    handle.set(segment, offset, value.address());
      -     * }
      - * @param segment the segment to be dereferenced. - * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}. - * @param value the memory address to be written (expressed as an {@link Addressable} instance). - */ - @ForceInline - public static void setAddressAtOffset(MemorySegment segment, long offset, Addressable value) { - Objects.requireNonNull(segment); - Objects.requireNonNull(value); - address_handle.set(segment, offset, value.address()); - } - - /** - * Reads a char from given segment and offset with given byte order. - *

      - * This is equivalent to the following code: - *

      {@code
      -    VarHandle handle = MemoryHandles.varHandle(char.class, 1, order);
      -    char value = (char)handle.get(segment, offset);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}. - * @param order the specified byte order. - * @return a char value read from {@code segment}. - */ - @ForceInline - public static char getCharAtOffset(MemorySegment segment, long offset, ByteOrder order) { - Objects.requireNonNull(segment); - Objects.requireNonNull(order); - return (char)((order == ByteOrder.BIG_ENDIAN) ? char_BE_handle : char_LE_handle).get(segment, offset); - } - - /** - * Writes a char at given segment and offset with given byte order. - *

      - * This is equivalent to the following code: - *

      {@code
      -    VarHandle handle = MemoryHandles.varHandle(char.class, 1, order);
      -    handle.set(segment, offset, value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}. - * @param order the specified byte order. - * @param value the char value to be written. - */ - @ForceInline - public static void setCharAtOffset(MemorySegment segment, long offset, ByteOrder order, char value) { - Objects.requireNonNull(segment); - Objects.requireNonNull(order); - ((order == ByteOrder.BIG_ENDIAN) ? char_BE_handle : char_LE_handle).set(segment, offset, value); - } - - /** - * Reads a short from given segment and offset with given byte order. - *

      - * This is equivalent to the following code: - *

      {@code
      -    VarHandle handle = MemoryHandles.varHandle(short.class, 1, order);
      -    short value = (short)handle.get(segment, offset);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}. - * @param order the specified byte order. - * @return a short value read from {@code segment}. - */ - @ForceInline - public static short getShortAtOffset(MemorySegment segment, long offset, ByteOrder order) { - Objects.requireNonNull(segment); - Objects.requireNonNull(order); - return (short)((order == ByteOrder.BIG_ENDIAN) ? short_BE_handle : short_LE_handle).get(segment, offset); - } - - /** - * Writes a short at given segment and offset with given byte order. - *

      - * This is equivalent to the following code: - *

      {@code
      -    VarHandle handle = MemoryHandles.varHandle(short.class, 1, order);
      -    handle.set(segment, offset, value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}. - * @param order the specified byte order. - * @param value the short value to be written. - */ - @ForceInline - public static void setShortAtOffset(MemorySegment segment, long offset, ByteOrder order, short value) { - Objects.requireNonNull(segment); - Objects.requireNonNull(order); - ((order == ByteOrder.BIG_ENDIAN) ? short_BE_handle : short_LE_handle).set(segment, offset, value); - } - - /** - * Reads an int from given segment and offset with given byte order. - *

      - * This is equivalent to the following code: - *

      {@code
      -    VarHandle handle = MemoryHandles.varHandle(int.class, 1, order);
      -    int value = (int)handle.get(segment, offset);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}. - * @param order the specified byte order. - * @return an int value read from {@code segment}. - */ - @ForceInline - public static int getIntAtOffset(MemorySegment segment, long offset, ByteOrder order) { - Objects.requireNonNull(segment); - Objects.requireNonNull(order); - return (int)((order == ByteOrder.BIG_ENDIAN) ? int_BE_handle : int_LE_handle).get(segment, offset); - } - - /** - * Writes an int at given segment and offset with given byte order. - *

      - * This is equivalent to the following code: - *

      {@code
      -    VarHandle handle = MemoryHandles.varHandle(int.class, 1, order);
      -    handle.set(segment, offset, value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}. - * @param order the specified byte order. - * @param value the int value to be written. - */ - @ForceInline - public static void setIntAtOffset(MemorySegment segment, long offset, ByteOrder order, int value) { - Objects.requireNonNull(segment); - Objects.requireNonNull(order); - ((order == ByteOrder.BIG_ENDIAN) ? int_BE_handle : int_LE_handle).set(segment, offset, value); - } - - /** - * Reads a float from given segment and offset with given byte order. - *

      - * This is equivalent to the following code: - *

      {@code
      -    VarHandle handle = MemoryHandles.varHandle(float.class, 1, order);
      -    float value = (float)handle.get(segment, offset);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}. - * @param order the specified byte order. - * @return a float value read from {@code segment}. - */ - @ForceInline - public static float getFloatAtOffset(MemorySegment segment, long offset, ByteOrder order) { - Objects.requireNonNull(segment); - Objects.requireNonNull(order); - return (float)((order == ByteOrder.BIG_ENDIAN) ? float_BE_handle : float_LE_handle).get(segment, offset); - } - - /** - * Writes a float at given segment and offset with given byte order. - *

      - * This is equivalent to the following code: - *

      {@code
      -    VarHandle handle = MemoryHandles.varHandle(float.class, 1, order);
      -    handle.set(segment, offset, value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}. - * @param order the specified byte order. - * @param value the float value to be written. - */ - @ForceInline - public static void setFloatAtOffset(MemorySegment segment, long offset, ByteOrder order, float value) { - Objects.requireNonNull(segment); - Objects.requireNonNull(order); - ((order == ByteOrder.BIG_ENDIAN) ? float_BE_handle : float_LE_handle).set(segment, offset, value); - } - - /** - * Reads a long from given segment and offset with given byte order. - *

      - * This is equivalent to the following code: - *

      {@code
      -    VarHandle handle = MemoryHandles.varHandle(long.class, 1, order);
      -    long value = (long)handle.get(segment, offset);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}. - * @param order the specified byte order. - * @return a long value read from {@code segment}. - */ - @ForceInline - public static long getLongAtOffset(MemorySegment segment, long offset, ByteOrder order) { - Objects.requireNonNull(segment); - Objects.requireNonNull(order); - return (long)((order == ByteOrder.BIG_ENDIAN) ? long_BE_handle : long_LE_handle).get(segment, offset); - } - - /** - * Writes a long at given segment and offset with given byte order. - *

      - * This is equivalent to the following code: - *

      {@code
      -    VarHandle handle = MemoryHandles.varHandle(long.class, 1, order);
      -    handle.set(segment, offset, value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}. - * @param order the specified byte order. - * @param value the long value to be written. - */ - @ForceInline - public static void setLongAtOffset(MemorySegment segment, long offset, ByteOrder order, long value) { - Objects.requireNonNull(segment); - Objects.requireNonNull(order); - ((order == ByteOrder.BIG_ENDIAN) ? long_BE_handle : long_LE_handle).set(segment, offset, value); - } - - /** - * Reads a double from given segment and offset with given byte order. - *

      - * This is equivalent to the following code: - *

      {@code
      -    VarHandle handle = MemoryHandles.varHandle(double.class, 1, order);
      -    double value = (double)handle.get(segment, offset);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}. - * @param order the specified byte order. - * @return a double value read from {@code segment}. - */ - @ForceInline - public static double getDoubleAtOffset(MemorySegment segment, long offset, ByteOrder order) { - Objects.requireNonNull(segment); - Objects.requireNonNull(order); - return (double)((order == ByteOrder.BIG_ENDIAN) ? double_BE_handle : double_LE_handle).get(segment, offset); - } - - /** - * Writes a double at given segment and offset with given byte order. - *

      - * This is equivalent to the following code: - *

      {@code
      -    VarHandle handle = MemoryHandles.varHandle(double.class, 1, order);
      -    handle.set(segment, offset, value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}. - * @param order the specified byte order. - * @param value the double value to be written. - */ - @ForceInline - public static void setDoubleAtOffset(MemorySegment segment, long offset, ByteOrder order, double value) { - Objects.requireNonNull(segment); - Objects.requireNonNull(order); - ((order == ByteOrder.BIG_ENDIAN) ? double_BE_handle : double_LE_handle).set(segment, offset, value); - } - - /** - * Reads a byte from given segment. - *

      - * This is equivalent to the following code: - *

      {@code
      -    byte value = getByteAtOffset(segment, 0L);
      -     * }
      - * - * @param segment the segment to be dereferenced. - * @return a byte value read from {@code segment}. - */ - @ForceInline - public static byte getByte(MemorySegment segment) { - return getByteAtOffset(segment, 0L); - } - - /** - * Writes a byte at given segment. - *

      - * This is equivalent to the following code: - *

      {@code
      -    setByteAtOffset(segment, 0L, value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param value the byte value to be written. - */ - @ForceInline - public static void setByte(MemorySegment segment, byte value) { - setByteAtOffset(segment, 0L, value); - } - - /** - * Reads a char from given segment, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    char value = getCharAtOffset(segment, 0L);
      -     * }
      - * @param segment the segment to be dereferenced. - * @return a char value read from {@code segment}. - */ - @ForceInline - public static char getChar(MemorySegment segment) { - return getCharAtOffset(segment, 0L); - } - - /** - * Writes a char at given segment, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    setCharAtOffset(segment, 0L, value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param value the char value to be written. - */ - @ForceInline - public static void setChar(MemorySegment segment, char value) { - setCharAtOffset(segment, 0L, value); - } - - /** - * Reads a short from given segment, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    short value = getShortAtOffset(segment, 0L);
      -     * }
      - * @param segment the segment to be dereferenced. - * @return a short value read from {@code segment}. - */ - @ForceInline - public static short getShort(MemorySegment segment) { - return getShortAtOffset(segment, 0L); - } - - /** - * Writes a short at given segment, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    setShortAtOffset(segment, 0L, value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param value the short value to be written. - */ - @ForceInline - public static void setShort(MemorySegment segment, short value) { - setShortAtOffset(segment, 0L, value); - } - - /** - * Reads an int from given segment, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    int value = getIntAtOffset(segment, 0L);
      -     * }
      - * @param segment the segment to be dereferenced. - * @return an int value read from {@code segment}. - */ - @ForceInline - public static int getInt(MemorySegment segment) { - return getIntAtOffset(segment, 0L); - } - - /** - * Writes an int at given segment, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    setIntAtOffset(segment, 0L, value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param value the int value to be written. - */ - @ForceInline - public static void setInt(MemorySegment segment, int value) { - setIntAtOffset(segment, 0L, value); - } - - /** - * Reads a float from given segment, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    float value = getFloatAtOffset(segment, 0L);
      -     * }
      - * @param segment the segment to be dereferenced. - * @return a float value read from {@code segment}. - */ - @ForceInline - public static float getFloat(MemorySegment segment) { - return getFloatAtOffset(segment, 0L); - } - - /** - * Writes a float at given segment, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    setFloatAtOffset(segment, 0L, value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param value the float value to be written. - */ - @ForceInline - public static void setFloat(MemorySegment segment, float value) { - setFloatAtOffset(segment, 0L, value); - } - - /** - * Reads a long from given segment, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    long value = getLongAtOffset(segment, 0L);
      -     * }
      - * @param segment the segment to be dereferenced. - * @return a long value read from {@code segment}. - */ - @ForceInline - public static long getLong(MemorySegment segment) { - return getLongAtOffset(segment, 0L); - } - - /** - * Writes a long at given segment, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    setLongAtOffset(segment, 0L, value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param value the long value to be written. - */ - @ForceInline - public static void setLong(MemorySegment segment, long value) { - setLongAtOffset(segment, 0L, value); - } - - /** - * Reads a double from given segment, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    double value = getDoubleAtOffset(segment, 0L);
      -     * }
      - * @param segment the segment to be dereferenced. - * @return a double value read from {@code segment}. - */ - @ForceInline - public static double getDouble(MemorySegment segment) { - return getDoubleAtOffset(segment, 0L); - } - - /** - * Writes a double at given segment, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    setDoubleAtOffset(segment, 0L, value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param value the double value to be written. - */ - @ForceInline - public static void setDouble(MemorySegment segment, double value) { - setDoubleAtOffset(segment, 0L, value); - } - - /** - * Reads a memory address from given segment, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    MemoryAddress value = getAddressAtOffset(segment, 0L);
      -     * }
      - * @param segment the segment to be dereferenced. - * @return a memory address read from {@code segment}. - */ - @ForceInline - public static MemoryAddress getAddress(MemorySegment segment) { - return getAddressAtOffset(segment, 0L); - } - - /** - * Writes a memory address at given segment, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    setAddressAtOffset(segment, 0L, value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param value the memory address to be written (expressed as an {@link Addressable} instance). - */ - @ForceInline - public static void setAddress(MemorySegment segment, Addressable value) { - setAddressAtOffset(segment, 0L, value); - } - - /** - * Reads a char from given segment, with given byte order. - *

      - * This is equivalent to the following code: - *

      {@code
      -    char value = getCharAtOffset(segment, 0L, order);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param order the specified byte order. - * @return a char value read from {@code segment}. - */ - @ForceInline - public static char getChar(MemorySegment segment, ByteOrder order) { - return getCharAtOffset(segment, 0L, order); - } - - /** - * Writes a char at given segment, with given byte order. - *

      - * This is equivalent to the following code: - *

      {@code
      -    setCharAtOffset(segment, 0L, order, value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param order the specified byte order. - * @param value the char value to be written. - */ - @ForceInline - public static void setChar(MemorySegment segment, ByteOrder order, char value) { - setCharAtOffset(segment, 0L, order, value); - } - - /** - * Reads a short from given segment, with given byte order. - *

      - * This is equivalent to the following code: - *

      {@code
      -    short value = getShortAtOffset(segment, 0L, order);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param order the specified byte order. - * @return a short value read from {@code segment}. - */ - @ForceInline - public static short getShort(MemorySegment segment, ByteOrder order) { - return getShortAtOffset(segment, 0L, order); - } - - /** - * Writes a short at given segment, with given byte order. - *

      - * This is equivalent to the following code: - *

      {@code
      -    setShortAtOffset(segment, 0L, order, value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param order the specified byte order. - * @param value the short value to be written. - */ - @ForceInline - public static void setShort(MemorySegment segment, ByteOrder order, short value) { - setShortAtOffset(segment, 0L, order, value); - } - - /** - * Reads an int from given segment, with given byte order. - *

      - * This is equivalent to the following code: - *

      {@code
      -    int value = getIntAtOffset(segment, 0L, order);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param order the specified byte order. - * @return an int value read from {@code segment}. - */ - @ForceInline - public static int getInt(MemorySegment segment, ByteOrder order) { - return getIntAtOffset(segment, 0L, order); - } - - /** - * Writes an int at given segment, with given byte order. - *

      - * This is equivalent to the following code: - *

      {@code
      -    setIntAtOffset(segment, 0L, order, value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param order the specified byte order. - * @param value the int value to be written. - */ - @ForceInline - public static void setInt(MemorySegment segment, ByteOrder order, int value) { - setIntAtOffset(segment, 0L, order, value); - } - - /** - * Reads a float from given segment, with given byte order. - *

      - * This is equivalent to the following code: - *

      {@code
      -    float value = getFloatAtOffset(segment, 0L, order);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param order the specified byte order. - * @return a float value read from {@code segment}. - */ - @ForceInline - public static float getFloat(MemorySegment segment, ByteOrder order) { - return getFloatAtOffset(segment, 0L, order); - } - - /** - * Writes a float at given segment, with given byte order. - *

      - * This is equivalent to the following code: - *

      {@code
      -    setFloatAtOffset(segment, 0L, order, value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param order the specified byte order. - * @param value the float value to be written. - */ - @ForceInline - public static void setFloat(MemorySegment segment, ByteOrder order, float value) { - setFloatAtOffset(segment, 0L, order, value); - } - - /** - * Reads a long from given segment, with given byte order. - *

      - * This is equivalent to the following code: - *

      {@code
      -    long value = getLongAtOffset(segment, 0L, order);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param order the specified byte order. - * @return a long value read from {@code segment}. - */ - @ForceInline - public static long getLong(MemorySegment segment, ByteOrder order) { - return getLongAtOffset(segment, 0L, order); - } - - /** - * Writes a long at given segment, with given byte order. - *

      - * This is equivalent to the following code: - *

      {@code
      -    setLongAtOffset(segment, 0L, order, value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param order the specified byte order. - * @param value the long value to be written. - */ - @ForceInline - public static void setLong(MemorySegment segment, ByteOrder order, long value) { - setLongAtOffset(segment, 0L, order, value); - } - - /** - * Reads a double from given segment, with given byte order. - *

      - * This is equivalent to the following code: - *

      {@code
      -    double value = getDoubleAtOffset(segment, 0L, order);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param order the specified byte order. - * @return a double value read from {@code segment}. - */ - @ForceInline - public static double getDouble(MemorySegment segment, ByteOrder order) { - return getDoubleAtOffset(segment, 0L, order); - } - - /** - * Writes a double at given segment, with given byte order. - *

      - * This is equivalent to the following code: - *

      {@code
      -    setDoubleAtOffset(segment, 0L, order, value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param order the specified byte order. - * @param value the double value to be written. - */ - @ForceInline - public static void setDouble(MemorySegment segment, ByteOrder order, double value) { - setDoubleAtOffset(segment, 0L, order, value); - } - - /** - * Reads a char from given segment and element index, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    char value = getCharAtOffset(segment, 2 * index);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 2)}. - * @return a char value read from {@code segment} at the element index specified by {@code index}. - */ - @ForceInline - public static char getCharAtIndex(MemorySegment segment, long index) { - return getCharAtOffset(segment, scale(segment, index, 2)); - } - - /** - * Writes a char at given segment and element index, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    setCharAtOffset(segment, 2 * index, value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 2)}. - * @param value the char value to be written. - */ - @ForceInline - public static void setCharAtIndex(MemorySegment segment, long index, char value) { - setCharAtOffset(segment, scale(segment, index, 2), value); - } - - /** - * Reads a short from given segment and element index, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    short value = getShortAtOffset(segment, 2 * index);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 2)}. - * @return a short value read from {@code segment} at the element index specified by {@code index}. - */ - @ForceInline - public static short getShortAtIndex(MemorySegment segment, long index) { - return getShortAtOffset(segment, scale(segment, index, 2)); - } - - /** - * Writes a short at given segment and element index, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    setShortAtOffset(segment, 2 * index, value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 2)}. - * @param value the short value to be written. - */ - @ForceInline - public static void setShortAtIndex(MemorySegment segment, long index, short value) { - setShortAtOffset(segment, scale(segment, index, 2), value); - } - - /** - * Reads an int from given segment and element index, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    int value = getIntAtOffset(segment, 4 * index);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 4)}. - * @return an int value read from {@code segment} at the element index specified by {@code index}. - */ - @ForceInline - public static int getIntAtIndex(MemorySegment segment, long index) { - return getIntAtOffset(segment, scale(segment, index, 4)); - } - - /** - * Writes an int at given segment and element index, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    setIntAtOffset(segment, 4 * index, value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 4)}. - * @param value the int value to be written. - */ - @ForceInline - public static void setIntAtIndex(MemorySegment segment, long index, int value) { - setIntAtOffset(segment, scale(segment, index, 4), value); - } - - /** - * Reads a float from given segment and element index, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    float value = getFloatAtOffset(segment, 4 * index);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 4)}. - * @return a float value read from {@code segment} at the element index specified by {@code index}. - */ - @ForceInline - public static float getFloatAtIndex(MemorySegment segment, long index) { - return getFloatAtOffset(segment, scale(segment, index, 4)); - } - - /** - * Writes a float at given segment and element index, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    setFloatAtOffset(segment, 4 * index, value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 4)}. - * @param value the float value to be written. - */ - @ForceInline - public static void setFloatAtIndex(MemorySegment segment, long index, float value) { - setFloatAtOffset(segment, scale(segment, index, 4), value); - } - - /** - * Reads a long from given segment and element index, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    return getLongAtOffset(segment, 8 * index);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 8)}. - * @return a long value read from {@code segment} at the element index specified by {@code index}. - */ - @ForceInline - public static long getLongAtIndex(MemorySegment segment, long index) { - return getLongAtOffset(segment, scale(segment, index, 8)); - } - - /** - * Writes a long at given segment and element index, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    setLongAtOffset(segment, 8 * index, value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 8)}. - * @param value the long value to be written. - */ - @ForceInline - public static void setLongAtIndex(MemorySegment segment, long index, long value) { - setLongAtOffset(segment, scale(segment, index, 8), value); - } - - /** - * Reads a double from given segment and element index, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    return getDoubleAtOffset(segment, 8 * index);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 8)}. - * @return a double value read from {@code segment} at the element index specified by {@code index}. - */ - @ForceInline - public static double getDoubleAtIndex(MemorySegment segment, long index) { - return getDoubleAtOffset(segment, scale(segment, index, 8)); - } - - /** - * Writes a double at given segment and element index, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    setDoubleAtOffset(segment, 8 * index, value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 8)}. - * @param value the double value to be written. - */ - @ForceInline - public static void setDoubleAtIndex(MemorySegment segment, long index, double value) { - setDoubleAtOffset(segment, scale(segment, index, 8), value); - } - - /** - * Reads a memory address from given segment and element index, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    return getAddressAtOffset(segment, index * MemoryLayouts.ADDRESS.byteSize());
      -     * }
      - * @param segment the segment to be dereferenced. - * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 8)}. - * @return a memory address read from {@code segment} at the element index specified by {@code index}. - */ - @ForceInline - public static MemoryAddress getAddressAtIndex(MemorySegment segment, long index) { - return getAddressAtOffset(segment, scale(segment, index, (int)MemoryLayouts.ADDRESS.byteSize())); - } - - /** - * Writes a memory address at given segment and element index, with byte order set to {@link ByteOrder#nativeOrder()}. - *

      - * This is equivalent to the following code: - *

      {@code
      -    setAddressAtOffset(segment, index * MemoryLayouts.ADDRESS.byteSize(), value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 8)}. - * @param value the memory address to be written (expressed as an {@link Addressable} instance). - */ - @ForceInline - public static void setAddressAtIndex(MemorySegment segment, long index, Addressable value) { - setAddressAtOffset(segment, scale(segment, index, (int)MemoryLayouts.ADDRESS.byteSize()), value); - } - - /** - * Reads a char from given segment and element index, with given byte order. - *

      - * This is equivalent to the following code: - *

      {@code
      -    char value = getCharAtOffset(segment, 2 * index, order);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 2)}. - * @param order the specified byte order. - * @return a char value read from {@code segment} at the element index specified by {@code index}. - */ - @ForceInline - public static char getCharAtIndex(MemorySegment segment, long index, ByteOrder order) { - return getCharAtOffset(segment, scale(segment, index, 2), order); - } - - /** - * Writes a char at given segment and element index, with given byte order. - *

      - * This is equivalent to the following code: - *

      {@code
      -    setCharAtOffset(segment, 2 * index, order, value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 2)}. - * @param order the specified byte order. - * @param value the char value to be written. - */ - @ForceInline - public static void setCharAtIndex(MemorySegment segment, long index, ByteOrder order, char value) { - setCharAtOffset(segment, scale(segment, index, 2), order, value); - } - - /** - * Reads a short from given segment and element index, with given byte order. - *

      - * This is equivalent to the following code: - *

      {@code
      -    short value = getShortAtOffset(segment, 2 * index, order);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 2)}. - * @param order the specified byte order. - * @return a short value read from {@code segment} at the element index specified by {@code index}. - */ - @ForceInline - public static short getShortAtIndex(MemorySegment segment, long index, ByteOrder order) { - return getShortAtOffset(segment, scale(segment, index, 2), order); - } - - /** - * Writes a short at given segment and element index, with given byte order. - *

      - * This is equivalent to the following code: - *

      {@code
      -    setShortAtOffset(segment, 2 * index, order, value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 2)}. - * @param order the specified byte order. - * @param value the short value to be written. - */ - @ForceInline - public static void setShortAtIndex(MemorySegment segment, long index, ByteOrder order, short value) { - setShortAtOffset(segment, scale(segment, index, 2), order, value); - } - - /** - * Reads an int from given segment and element index, with given byte order. - *

      - * This is equivalent to the following code: - *

      {@code
      -    int value = getIntAtOffset(segment, 4 * index, order);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 4)}. - * @param order the specified byte order. - * @return an int value read from {@code segment} at the element index specified by {@code index}. - */ - @ForceInline - public static int getIntAtIndex(MemorySegment segment, long index, ByteOrder order) { - return getIntAtOffset(segment, scale(segment, index, 4), order); - } - - /** - * Writes an int at given segment and element index, with given byte order. - *

      - * This is equivalent to the following code: - *

      {@code
      -    setIntAtOffset(segment, 4 * index, order, value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 4)}. - * @param order the specified byte order. - * @param value the int value to be written. - */ - @ForceInline - public static void setIntAtIndex(MemorySegment segment, long index, ByteOrder order, int value) { - setIntAtOffset(segment, scale(segment, index, 4), order, value); - } - - /** - * Reads a float from given segment and element index, with given byte order. - *

      - * This is equivalent to the following code: - *

      {@code
      -    float value = getFloatAtOffset(segment, 4 * index, order);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 4)}. - * @param order the specified byte order. - * @return a float value read from {@code segment} at the element index specified by {@code index}. - */ - @ForceInline - public static float getFloatAtIndex(MemorySegment segment, long index, ByteOrder order) { - return getFloatAtOffset(segment, scale(segment, index, 4), order); - } - - /** - * Writes a float at given segment and element index, with given byte order. - *

      - * This is equivalent to the following code: - *

      {@code
      -    setFloatAtOffset(segment, 4 * index, order, value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 4)}. - * @param order the specified byte order. - * @param value the float value to be written. - */ - @ForceInline - public static void setFloatAtIndex(MemorySegment segment, long index, ByteOrder order, float value) { - setFloatAtOffset(segment, scale(segment, index, 4), order, value); - } - - /** - * Reads a long from given segment and element index, with given byte order. - *

      - * This is equivalent to the following code: - *

      {@code
      -    return getLongAtOffset(segment, 8 * index, order);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 8)}. - * @param order the specified byte order. - * @return a long value read from {@code segment} at the element index specified by {@code index}. - */ - @ForceInline - public static long getLongAtIndex(MemorySegment segment, long index, ByteOrder order) { - return getLongAtOffset(segment, scale(segment, index, 8), order); - } - - /** - * Writes a long at given segment and element index, with given byte order. - *

      - * This is equivalent to the following code: - *

      {@code
      -    setLongAtOffset(segment, 8 * index, order, value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 8)}. - * @param order the specified byte order. - * @param value the long value to be written. - */ - @ForceInline - public static void setLongAtIndex(MemorySegment segment, long index, ByteOrder order, long value) { - setLongAtOffset(segment, scale(segment, index, 8), order, value); - } - - /** - * Reads a double from given segment and element index, with given byte order. - *

      - * This is equivalent to the following code: - *

      {@code
      -    return getDoubleAtOffset(segment, 8 * index, order);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 8)}. - * @param order the specified byte order. - * @return a double value read from {@code segment} at the element index specified by {@code index}. - */ - @ForceInline - public static double getDoubleAtIndex(MemorySegment segment, long index, ByteOrder order) { - return getDoubleAtOffset(segment, scale(segment, index, 8), order); - } - - /** - * Writes a double at given segment and element index, with given byte order. - *

      - * This is equivalent to the following code: - *

      {@code
      -    setDoubleAtOffset(segment, 8 * index, order, value);
      -     * }
      - * @param segment the segment to be dereferenced. - * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 8)}. - * @param order the specified byte order. - * @param value the double value to be written. - */ - @ForceInline - public static void setDoubleAtIndex(MemorySegment segment, long index, ByteOrder order, double value) { - setDoubleAtOffset(segment, scale(segment, index, 8), order, value); - } - - @ForceInline - private static long scale(MemorySegment address, long index, int size) { - return MemorySegmentProxy.multiplyOffsets(index, size, (MemorySegmentProxy)address); - } -} diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryAddress.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryAddress.java index 08290fc911f0921b35a4a2c483abbbe035017bac..7e94d63014cff23abf221847d9dcb9ea65a45096 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryAddress.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryAddress.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,33 +27,47 @@ package jdk.incubator.foreign; import jdk.internal.foreign.MemoryAddressImpl; -import jdk.internal.ref.CleanerFactory; import jdk.internal.reflect.CallerSensitive; -import java.lang.ref.Cleaner; +import java.lang.invoke.MethodHandle; +import java.nio.ByteOrder; /** - * A memory address models a reference into a memory location. Memory addresses are typically obtained using the - * {@link MemorySegment#address()} method, and can refer to either off-heap or on-heap memory. Off-heap memory - * addresses are referred to as native memory addresses (see {@link #isNative()}). Native memory addresses - * allow clients to obtain a raw memory address (expressed as a long value) which can then be used e.g. when interacting - * with native code. - *

      - * Given an address, it is possible to compute its offset relative to a given segment, which can be useful - * when performing memory dereference operations using a memory access var handle (see {@link MemoryHandles}). - *

      - * A memory address is associated with a {@linkplain ResourceScope resource scope}; the resource scope determines the - * lifecycle of the memory address, and whether the address can be used from multiple threads. Memory addresses - * obtained from {@linkplain #ofLong(long) numeric values}, or from native code, are associated with the - * {@linkplain ResourceScope#globalScope() global resource scope}. Memory addresses obtained from segments - * are associated with the same scope as the segment from which they have been obtained. + * A memory address models a reference into a memory location. Memory addresses are typically obtained in one of the following ways: + *

        + *
      • By calling {@link Addressable#address()} on an instance of type {@link Addressable} (e.g. a memory segment);
      • + *
      • By invoking a {@linkplain CLinker#downcallHandle(FunctionDescriptor) downcall method handle} which returns a pointer;
      • + *
      • By reading an address from memory, e.g. via {@link MemorySegment#get(ValueLayout.OfAddress, long)}.
      • + *
      • By the invocation of an {@linkplain CLinker#upcallStub(MethodHandle, FunctionDescriptor, ResourceScope) upcall stub} which accepts a pointer. + *
      + * A memory address is backed by a raw machine pointer, expressed as a {@linkplain #toRawLongValue() long value}. + * + *

      Dereference

      + * + * A memory address can be read or written using various methods provided in this class (e.g. {@link #get(ValueLayout.OfInt, long)}). + * Each dereference method takes a {@linkplain jdk.incubator.foreign.ValueLayout value layout}, which specifies the size, + * alignment constraints, byte order as well as the Java type associated with the dereference operation, and an offset. + * For instance, to read an int from a segment, using {@link ByteOrder#nativeOrder() default endianness}, the following code can be used: + * {@snippet lang=java : + * MemoryAddress address = ... + * int value = address.get(ValueLayout.JAVA_INT, 0); + * } + * + * If the value to be read is stored in memory using {@link ByteOrder#BIG_ENDIAN big-endian} encoding, the dereference operation + * can be expressed as follows: + * {@snippet lang=java : + * MemoryAddress address = ... + * int value = address.get(ValueLayout.JAVA_INT.withOrder(BIG_ENDIAN), 0); + * } + * + * All the dereference methods in this class are restricted: since + * a memory address does not feature temporal nor spatial bounds, the runtime has no way to check the correctness + * of the memory dereference operation. *

      * All implementations of this interface must be value-based; * programmers should treat instances that are {@linkplain #equals(Object) equal} as interchangeable and should not * use instances for synchronization, or unpredictable behavior may occur. For example, in a future release, * synchronization may fail. The {@code equals} method should be used for comparisons. - *

      - * Non-platform classes should not implement {@linkplain MemoryAddress} directly. * *

      Unless otherwise specified, passing a {@code null} argument, or an array argument containing one or more {@code null} * elements to a method in this class causes a {@link NullPointerException NullPointerException} to be thrown.

      @@ -63,10 +77,11 @@ import java.lang.ref.Cleaner; */ public sealed interface MemoryAddress extends Addressable permits MemoryAddressImpl { - @Override - default MemoryAddress address() { - return this; - } + /** + * Returns the raw long value associated with this memory address. + * @return The raw long value associated with this memory address. + */ + long toRawLongValue(); /** * Creates a new memory address with given offset (in bytes), which might be negative, from current one. @@ -76,155 +91,651 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI MemoryAddress addOffset(long offset); /** - * Returns the resource scope associated with this memory address. - * @return the resource scope associated with this memory address. + * Reads a UTF-8 encoded, null-terminated string from this address and offset. + *

      + * This method always replaces malformed-input and unmappable-character + * sequences with this charset's default replacement string. The {@link + * java.nio.charset.CharsetDecoder} class should be used when more control + * over the decoding process is required. + *

      + * This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * restricted methods, and use safe and supported functionalities, where possible. + * + * @param offset offset in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + offset}. + * @return a Java string constructed from the bytes read from the given starting address ({@code toRowLongValue() + offset}) + * up to (but not including) the first {@code '\0'} terminator character (assuming one is found). + * @throws IllegalArgumentException if the size of the native string is greater than the largest string supported by the platform. + * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option + * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or + * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + */ + @CallerSensitive + String getUtf8String(long offset); + + /** + * Writes the given string to this address at given offset, converting it to a null-terminated byte sequence using UTF-8 encoding. + *

      + * This method always replaces malformed-input and unmappable-character + * sequences with this charset's default replacement string. The {@link + * java.nio.charset.CharsetDecoder} class should be used when more control + * over the decoding process is required. + * @param offset offset in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + offset}. + * @param str the Java string to be written at this address. + * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option + * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or + * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + */ + @CallerSensitive + void setUtf8String(long offset, String str); + + /** + * Compares the specified object with this address for equality. Returns {@code true} if and only if the specified + * object is also an address, and it refers to the same memory location as this address. + * + * @param that the object to be compared for equality with this address. + * @return {@code true} if the specified object is equal to this address. + */ + @Override + boolean equals(Object that); + + /** + * Returns the hash code value for this address. + * @return the hash code value for this address. + */ + @Override + int hashCode(); + + /** + * The native memory address instance modelling the {@code NULL} address. + */ + MemoryAddress NULL = new MemoryAddressImpl(0L); + + /** + * Obtain a native memory address instance from given long address. + * @param value the long address. + * @return the new memory address instance. + */ + static MemoryAddress ofLong(long value) { + return value == 0 ? + NULL : + new MemoryAddressImpl(value); + } + + /** + * Reads a byte from this address and offset with given layout. + *

      + * This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * restricted methods, and use safe and supported functionalities, where possible. + * + * @param layout the layout of the memory region to be read. + * @param offset offset in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + offset}. + * @return a byte value read from this address. + * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option + * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or + * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. */ - ResourceScope scope(); + @CallerSensitive + byte get(ValueLayout.OfByte layout, long offset); /** - * Returns the offset of this memory address into the given segment. More specifically, if both the segment's - * base address and this address are native addresses, the result is computed as - * {@code this.toRawLongValue() - segment.address().toRawLongValue()}. Otherwise, if both addresses in the form - * {@code (B, O1)}, {@code (B, O2)}, where {@code B} is the same base heap object and {@code O1}, {@code O2} - * are byte offsets (relative to the base object) associated with this address and the segment's base address, - * the result is computed as {@code O1 - O2}. + * Writes a byte to this address instance and offset with given layout. *

      - * If the segment's base address and this address are both heap addresses, but with different base objects, the result is undefined - * and an exception is thrown. Similarly, if the segment's base address is an heap address (resp. off-heap) and - * this address is an off-heap (resp. heap) address, the result is undefined and an exception is thrown. - * Otherwise, the result is a byte offset {@code SO}. If this address falls within the - * spatial bounds of the given segment, then {@code 0 <= SO < segment.byteSize()}; otherwise, {@code SO < 0 || SO > segment.byteSize()}. - * @return the offset of this memory address into the given segment. - * @param segment the segment relative to which this address offset should be computed - * @throws IllegalArgumentException if {@code segment} is not compatible with this address; this can happen, for instance, - * when {@code segment} models an heap memory region, while this address is a {@linkplain #isNative() native} address. + * This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * restricted methods, and use safe and supported functionalities, where possible. + * + * @param layout the layout of the memory region to be written. + * @param offset offset in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + offset}. + * @param value the byte value to be written. + * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option + * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or + * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. */ - long segmentOffset(MemorySegment segment); + @CallerSensitive + void set(ValueLayout.OfByte layout, long offset, byte value); /** - Returns a new native memory segment with given size and resource scope (replacing the scope already associated - * with this address), and whose base address is this address. This method can be useful when interacting with custom - * native memory sources (e.g. custom allocators), where an address to some - * underlying memory region is typically obtained from native code (often as a plain {@code long} value). - * The returned segment is not read-only (see {@link MemorySegment#isReadOnly()}), and is associated with the - * provided resource scope. + * Reads a boolean from this address and offset with given layout. *

      - * Clients should ensure that the address and bounds refers to a valid region of memory that is accessible for reading and, - * if appropriate, writing; an attempt to access an invalid memory location from Java code will either return an arbitrary value, - * have no visible effect, or cause an unspecified exception to be thrown. + * This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * restricted methods, and use safe and supported functionalities, where possible. + * + * @param layout the layout of the memory region to be read. + * @param offset offset in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + offset}. + * @return a boolean value read from this address. + * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option + * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or + * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + */ + @CallerSensitive + boolean get(ValueLayout.OfBoolean layout, long offset); + + /** + * Writes a boolean to this address instance and offset with given layout. *

      - * This method is equivalent to the following code: - *

      {@code
      -    asSegment(byteSize, null, scope);
      -     * }
      + * This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * restricted methods, and use safe and supported functionalities, where possible. + * + * @param layout the layout of the memory region to be written. + * @param offset offset in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + offset}. + * @param value the boolean value to be written. + * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option + * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or + * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + */ + @CallerSensitive + void set(ValueLayout.OfBoolean layout, long offset, boolean value); + + /** + * Reads a char from this address and offset with given layout. *

      * This method is restricted. * Restricted methods are unsafe, and, if used incorrectly, their use might crash * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on * restricted methods, and use safe and supported functionalities, where possible. * - * @param bytesSize the desired size. - * @param scope the native segment scope. - * @return a new native memory segment with given base address, size and scope. - * @throws IllegalArgumentException if {@code bytesSize <= 0}. - * @throws IllegalStateException if either the scope associated with this address or the provided scope - * have been already closed, or if access occurs from a thread other than the thread owning either - * scopes. - * @throws UnsupportedOperationException if this address is not a {@linkplain #isNative() native} address. + * @param layout the layout of the memory region to be read. + * @param offset offset in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + offset}. + * @return a char value read from this address. * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. */ @CallerSensitive - MemorySegment asSegment(long bytesSize, ResourceScope scope); + char get(ValueLayout.OfChar layout, long offset); /** - * Returns a new native memory segment with given size and resource scope (replacing the scope already associated - * with this address), and whose base address is this address. This method can be useful when interacting with custom - * native memory sources (e.g. custom allocators), where an address to some - * underlying memory region is typically obtained from native code (often as a plain {@code long} value). - * The returned segment is associated with the provided resource scope. + * Writes a char to this address instance and offset with given layout. *

      - * Clients should ensure that the address and bounds refers to a valid region of memory that is accessible for reading and, - * if appropriate, writing; an attempt to access an invalid memory location from Java code will either return an arbitrary value, - * have no visible effect, or cause an unspecified exception to be thrown. + * This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * restricted methods, and use safe and supported functionalities, where possible. + * + * @param layout the layout of the memory region to be written. + * @param offset offset in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + offset}. + * @param value the char value to be written. + * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option + * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or + * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + */ + @CallerSensitive + void set(ValueLayout.OfChar layout, long offset, char value); + + /** + * Reads a short from this address and offset with given layout. *

      - * Calling {@link ResourceScope#close()} on the scope associated with the returned segment will result in calling - * the provided cleanup action (if any). + * This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * restricted methods, and use safe and supported functionalities, where possible. + * + * @param layout the layout of the memory region to be read. + * @param offset offset in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + offset}. + * @return a short value read from this address. + * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option + * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or + * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + */ + @CallerSensitive + short get(ValueLayout.OfShort layout, long offset); + + /** + * Writes a short to this address instance and offset with given layout. *

      * This method is restricted. * Restricted methods are unsafe, and, if used incorrectly, their use might crash * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on * restricted methods, and use safe and supported functionalities, where possible. * - * @param bytesSize the desired size. - * @param cleanupAction the cleanup action; can be {@code null}. - * @param scope the native segment scope. - * @return a new native memory segment with given base address, size and scope. - * @throws IllegalArgumentException if {@code bytesSize <= 0}. - * @throws IllegalStateException if either the scope associated with this address or the provided scope - * have been already closed, or if access occurs from a thread other than the thread owning either - * scopes. - * @throws UnsupportedOperationException if this address is not a {@linkplain #isNative() native} address. + * @param layout the layout of the memory region to be written. + * @param offset offset in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + offset}. + * @param value the short value to be written. * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. */ @CallerSensitive - MemorySegment asSegment(long bytesSize, Runnable cleanupAction, ResourceScope scope); + void set(ValueLayout.OfShort layout, long offset, short value); /** - * Is this an off-heap memory address? - * @return true, if this is an off-heap memory address. + * Reads an int from this address and offset with given layout. + *

      + * This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * restricted methods, and use safe and supported functionalities, where possible. + * + * @param layout the layout of the memory region to be read. + * @param offset offset in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + offset}. + * @return an int value read from this address. + * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option + * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or + * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. */ - boolean isNative(); + @CallerSensitive + int get(ValueLayout.OfInt layout, long offset); /** - * Returns the raw long value associated with this native memory address. - * @return The raw long value associated with this native memory address. - * @throws UnsupportedOperationException if this memory address is not a {@linkplain #isNative() native} address. - * @throws IllegalStateException if the scope associated with this segment has been already closed, - * or if access occurs from a thread other than the thread owning either segment. + * Writes an int to this address instance and offset with given layout. + *

      + * This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * restricted methods, and use safe and supported functionalities, where possible. + * + * @param layout the layout of the memory region to be written. + * @param offset offset in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + offset}. + * @param value the int value to be written. + * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option + * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or + * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. */ - long toRawLongValue(); + @CallerSensitive + void set(ValueLayout.OfInt layout, long offset, int value); /** - * Compares the specified object with this address for equality. Returns {@code true} if and only if the specified - * object is also an address, and it refers to the same memory location as this address. + * Reads a float from this address and offset with given layout. + *

      + * This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * restricted methods, and use safe and supported functionalities, where possible. * - * @apiNote two addresses might be considered equal despite their associated resource scopes differ. This - * can happen, for instance, if the same memory address is used to create memory segments with different - * scopes (using {@link #asSegment(long, ResourceScope)}), and the base address of the resulting segments is - * then compared. + * @param layout the layout of the memory region to be read. + * @param offset offset in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + offset}. + * @return a float value read from this address. + * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option + * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or + * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + */ + @CallerSensitive + float get(ValueLayout.OfFloat layout, long offset); + + /** + * Writes a float to this address instance and offset with given layout. + *

      + * This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * restricted methods, and use safe and supported functionalities, where possible. * - * @param that the object to be compared for equality with this address. - * @return {@code true} if the specified object is equal to this address. + * @param layout the layout of the memory region to be written. + * @param offset offset in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + offset}. + * @param value the float value to be written. + * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option + * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or + * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. */ - @Override - boolean equals(Object that); + @CallerSensitive + void set(ValueLayout.OfFloat layout, long offset, float value); /** - * Returns the hash code value for this address. - * @return the hash code value for this address. + * Reads a long from this address and offset with given layout. + *

      + * This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * restricted methods, and use safe and supported functionalities, where possible. + * + * @param layout the layout of the memory region to be read. + * @param offset offset in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + offset}. + * @return a long value read from this address. + * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option + * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or + * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. */ - @Override - int hashCode(); + @CallerSensitive + long get(ValueLayout.OfLong layout, long offset); /** - * The native memory address instance modelling the {@code NULL} address, associated - * with the {@linkplain ResourceScope#globalScope() global} resource scope. + * Writes a long to this address instance and offset with given layout. + *

      + * This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * restricted methods, and use safe and supported functionalities, where possible. + * + * @param layout the layout of the memory region to be written. + * @param offset offset in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + offset}. + * @param value the long value to be written. + * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option + * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or + * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. */ - MemoryAddress NULL = new MemoryAddressImpl(null, 0L); + @CallerSensitive + void set(ValueLayout.OfLong layout, long offset, long value); /** - * Obtain a native memory address instance from given long address. The returned address is associated - * with the {@linkplain ResourceScope#globalScope() global} resource scope. - * @param value the long address. - * @return the new memory address instance. + * Reads a double from this address and offset with given layout. + *

      + * This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * restricted methods, and use safe and supported functionalities, where possible. + * + * @param layout the layout of the memory region to be read. + * @param offset offset in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + offset}. + * @return a double value read from this address. + * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option + * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or + * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. */ - static MemoryAddress ofLong(long value) { - return value == 0 ? - NULL : - new MemoryAddressImpl(null, value); - } + @CallerSensitive + double get(ValueLayout.OfDouble layout, long offset); + + /** + * Writes a double to this address instance and offset with given layout. + *

      + * This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * restricted methods, and use safe and supported functionalities, where possible. + * + * @param layout the layout of the memory region to be written. + * @param offset offset in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + offset}. + * @param value the double value to be written. + * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option + * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or + * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + */ + @CallerSensitive + void set(ValueLayout.OfDouble layout, long offset, double value); + + /** + * Reads an address from this address and offset with given layout. + *

      + * This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * restricted methods, and use safe and supported functionalities, where possible. + * + * @param layout the layout of the memory region to be read. + * @param offset offset in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + offset}. + * @return an address value read from this address. + * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option + * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or + * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + */ + @CallerSensitive + MemoryAddress get(ValueLayout.OfAddress layout, long offset); + + /** + * Writes an address to this address instance and offset with given layout. + *

      + * This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * restricted methods, and use safe and supported functionalities, where possible. + * + * @param layout the layout of the memory region to be written. + * @param offset offset in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + offset}. + * @param value the address value to be written. + * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option + * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or + * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + */ + @CallerSensitive + void set(ValueLayout.OfAddress layout, long offset, Addressable value); + + /** + * Reads a char from this address and index, scaled by given layout size. + *

      + * This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * restricted methods, and use safe and supported functionalities, where possible. + * + * @param layout the layout of the memory region to be read. + * @param index index in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}. + * @return a char value read from this address. + * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option + * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or + * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + */ + @CallerSensitive + char getAtIndex(ValueLayout.OfChar layout, long index); + + /** + * Writes a char to this address instance and index, scaled by given layout size. + *

      + * This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * restricted methods, and use safe and supported functionalities, where possible. + * + * @param layout the layout of the memory region to be written. + * @param index index in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}. + * @param value the char value to be written. + * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option + * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or + * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + */ + @CallerSensitive + void setAtIndex(ValueLayout.OfChar layout, long index, char value); + + /** + * Reads a short from this address and index, scaled by given layout size. + *

      + * This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * restricted methods, and use safe and supported functionalities, where possible. + * + * @param layout the layout of the memory region to be read. + * @param index index in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}. + * @return a short value read from this address. + * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option + * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or + * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + */ + @CallerSensitive + short getAtIndex(ValueLayout.OfShort layout, long index); + + /** + * Writes a short to this address instance and index, scaled by given layout size. + *

      + * This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * restricted methods, and use safe and supported functionalities, where possible. + * + * @param layout the layout of the memory region to be written. + * @param index index in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}. + * @param value the short value to be written. + * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option + * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or + * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + */ + @CallerSensitive + void setAtIndex(ValueLayout.OfShort layout, long index, short value); + + /** + * Reads an int from this address and index, scaled by given layout size. + *

      + * This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * restricted methods, and use safe and supported functionalities, where possible. + * + * @param layout the layout of the memory region to be read. + * @param index index in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}. + * @return an int value read from this address. + * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option + * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or + * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + */ + @CallerSensitive + int getAtIndex(ValueLayout.OfInt layout, long index); + + /** + * Writes an int to this address instance and index, scaled by given layout size. + *

      + * This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * restricted methods, and use safe and supported functionalities, where possible. + * + * @param layout the layout of the memory region to be written. + * @param index index in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}. + * @param value the int value to be written. + * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option + * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or + * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + */ + @CallerSensitive + void setAtIndex(ValueLayout.OfInt layout, long index, int value); + + /** + * Reads a float from this address and index, scaled by given layout size. + *

      + * This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * restricted methods, and use safe and supported functionalities, where possible. + * + * @param layout the layout of the memory region to be read. + * @param index index in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}. + * @return a float value read from this address. + * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option + * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or + * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + */ + @CallerSensitive + float getAtIndex(ValueLayout.OfFloat layout, long index); + + /** + * Writes a float to this address instance and index, scaled by given layout size. + *

      + * This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * restricted methods, and use safe and supported functionalities, where possible. + * + * @param layout the layout of the memory region to be written. + * @param index index in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}. + * @param value the float value to be written. + * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option + * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or + * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + */ + @CallerSensitive + void setAtIndex(ValueLayout.OfFloat layout, long index, float value); + + /** + * Reads a long from this address and index, scaled by given layout size. + *

      + * This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * restricted methods, and use safe and supported functionalities, where possible. + * + * @param layout the layout of the memory region to be read. + * @param index index in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}. + * @return a long value read from this address. + * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option + * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or + * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + */ + @CallerSensitive + long getAtIndex(ValueLayout.OfLong layout, long index); + + /** + * Writes a long to this address instance and index, scaled by given layout size. + *

      + * This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * restricted methods, and use safe and supported functionalities, where possible. + * + * @param layout the layout of the memory region to be written. + * @param index index in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}. + * @param value the long value to be written. + * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option + * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or + * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + */ + @CallerSensitive + void setAtIndex(ValueLayout.OfLong layout, long index, long value); + + /** + * Reads a double from this address and index, scaled by given layout size. + *

      + * This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * restricted methods, and use safe and supported functionalities, where possible. + * + * @param layout the layout of the memory region to be read. + * @param index index in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}. + * @return a double value read from this address. + * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option + * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or + * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + */ + @CallerSensitive + double getAtIndex(ValueLayout.OfDouble layout, long index); + + /** + * Writes a double to this address instance and index, scaled by given layout size. + *

      + * This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * restricted methods, and use safe and supported functionalities, where possible. + * + * @param layout the layout of the memory region to be written. + * @param index index in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}. + * @param value the double value to be written. + * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option + * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or + * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + */ + @CallerSensitive + void setAtIndex(ValueLayout.OfDouble layout, long index, double value); + + /** + * Reads an address from this address and index, scaled by given layout size. + *

      + * This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * restricted methods, and use safe and supported functionalities, where possible. + * + * @param layout the layout of the memory region to be read. + * @param index index in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}. + * @return an address value read from this address. + * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option + * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or + * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + */ + @CallerSensitive + MemoryAddress getAtIndex(ValueLayout.OfAddress layout, long index); + + /** + * Writes an address to this address instance and index, scaled by given layout size. + *

      + * This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * restricted methods, and use safe and supported functionalities, where possible. + * + * @param layout the layout of the memory region to be written. + * @param index index in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}. + * @param value the address value to be written. + * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option + * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or + * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + */ + @CallerSensitive + void setAtIndex(ValueLayout.OfAddress layout, long index, Addressable value); } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryHandles.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryHandles.java index 31dbc4e9ce582771ec45f29fe7faac5d9f91ffcd..f24f5c7bc6ea3b96169eaf6c3318e3690b6e4761 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryHandles.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryHandles.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,40 +27,37 @@ package jdk.incubator.foreign; import jdk.internal.access.JavaLangInvokeAccess; import jdk.internal.access.SharedSecrets; -import jdk.internal.foreign.Utils; import sun.invoke.util.Wrapper; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.lang.invoke.VarHandle; -import java.nio.ByteOrder; import java.util.List; import java.util.Objects; /** * This class defines several factory methods for constructing and combining memory access var handles. - * To obtain a memory access var handle, clients must start from one of the leaf methods - * (see {@link MemoryHandles#varHandle(Class, ByteOrder)}, - * {@link MemoryHandles#varHandle(Class, long, ByteOrder)}). This determines the variable type - * (all primitive types but {@code void} and {@code boolean} are supported), as well as the alignment constraint and the - * byte order associated with a memory access var handle. The resulting memory access var handle can then be combined in various ways + * Memory access var handles can be obtained using {@link MemoryHandles#varHandle(ValueLayout)}. The provided value layout + * determines the type, as well as the alignment constraint and the byte order associated with the memory access var handle. + *

      + * The resulting memory access var handle can then be combined in various ways * to emulate different addressing modes. The var handles created by this class feature a mandatory coordinate type * (of type {@link MemorySegment}), and one {@code long} coordinate type, which represents the offset, in bytes, relative * to the segment, at which dereference should occur. *

      * As an example, consider the memory layout expressed by a {@link GroupLayout} instance constructed as follows: - *

      {@code
      -GroupLayout seq = MemoryLayout.structLayout(
      -        MemoryLayout.paddingLayout(32),
      -        MemoryLayout.valueLayout(32, ByteOrder.BIG_ENDIAN).withName("value")
      -);
      - * }
      + * {@snippet lang=java : + * GroupLayout seq = MemoryLayout.structLayout( + * MemoryLayout.paddingLayout(32), + * ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN).withName("value") + * ); + * } * To access the member layout named {@code value}, we can construct a memory access var handle as follows: - *
      {@code
      -VarHandle handle = MemoryHandles.varHandle(int.class, ByteOrder.BIG_ENDIAN); //(MemorySegment, long) -> int
      -handle = MemoryHandles.insertCoordinates(handle, 1, 4); //(MemorySegment) -> int
      - * }
      + * {@snippet lang=java : + * VarHandle handle = MemoryHandles.varHandle(ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN)); //(MemorySegment, long) -> int + * handle = MemoryHandles.insertCoordinates(handle, 1, 4); //(MemorySegment) -> int + * } * *

      Unless otherwise specified, passing a {@code null} argument, or an array argument containing one or more {@code null} * elements to a method in this class causes a {@link NullPointerException NullPointerException} to be thrown.

      @@ -77,21 +74,21 @@ handle = MemoryHandles.insertCoordinates(handle, 1, 4); //(MemorySegment) -> int * access modes {@code get} and {@code set} for {@code long} and * {@code double} on 32-bit platforms. *
    • atomic update access modes for {@code int}, {@code long}, - * {@code float} or {@code double}. + * {@code float}, {@code double} or {@link MemoryAddress}. * (Future major platform releases of the JDK may support additional * types for certain currently unsupported access modes.) - *
    • numeric atomic update access modes for {@code int} and {@code long}. + *
    • numeric atomic update access modes for {@code int}, {@code long} and {@link MemoryAddress}. * (Future major platform releases of the JDK may support additional * numeric types for certain currently unsupported access modes.) - *
    • bitwise atomic update access modes for {@code int} and {@code long}. + *
    • bitwise atomic update access modes for {@code int}, {@code long} and {@link MemoryAddress}. * (Future major platform releases of the JDK may support additional * numeric types for certain currently unsupported access modes.) *
    * - * If {@code T} is {@code float} or {@code double} then atomic + * If {@code T} is {@code float}, {@code double} or {@link MemoryAddress} then atomic * update access modes compare values using their bitwise representation - * (see {@link Float#floatToRawIntBits} and - * {@link Double#doubleToRawLongBits}, respectively). + * (see {@link Float#floatToRawIntBits}, + * {@link Double#doubleToRawLongBits} and {@link MemoryAddress#toRawLongValue()}, respectively). *

    * Alternatively, a memory access operation is partially aligned if it occurs at a memory address {@code A} * which is only compatible with the alignment constraint {@code B}; in such cases, access for anything other than the @@ -109,8 +106,6 @@ public final class MemoryHandles { //sorry, just the one! } - private static final MethodHandle LONG_TO_ADDRESS; - private static final MethodHandle ADDRESS_TO_LONG; private static final MethodHandle INT_TO_BYTE; private static final MethodHandle BYTE_TO_UNSIGNED_INT; private static final MethodHandle INT_TO_SHORT; @@ -124,10 +119,6 @@ public final class MemoryHandles { static { try { - LONG_TO_ADDRESS = MethodHandles.lookup().findStatic(MemoryHandles.class, "longToAddress", - MethodType.methodType(MemoryAddress.class, long.class)); - ADDRESS_TO_LONG = MethodHandles.lookup().findStatic(MemoryHandles.class, "addressToLong", - MethodType.methodType(long.class, MemoryAddress.class)); INT_TO_BYTE = MethodHandles.explicitCastArguments(MethodHandles.identity(byte.class), MethodType.methodType(byte.class, int.class)); BYTE_TO_UNSIGNED_INT = MethodHandles.lookup().findStatic(Byte.class, "toUnsignedInt", @@ -154,34 +145,10 @@ public final class MemoryHandles { } /** - * Creates a memory access var handle with the given carrier type and byte order. - * - * The returned var handle's type is {@code carrier} and the list of coordinate types is - * {@code (MemorySegment, long)}, where the {@code long} coordinate type corresponds to byte offset into - * a given memory segment. The returned var handle accesses bytes at an offset in a given - * memory segment, composing bytes to or from a value of the type {@code carrier} according to the given endianness; - * the alignment constraint (in bytes) for the resulting memory access var handle is the same as the size (in bytes) of the - * carrier type {@code carrier}. - * - * @apiNote the resulting var handle features certain access mode restrictions, - * which are common to all memory access var handles. - * - * @param carrier the carrier type. Valid carriers are {@code byte}, {@code short}, {@code char}, {@code int}, - * {@code float}, {@code long}, and {@code double}. - * @param byteOrder the required byte order. - * @return the new memory access var handle. - * @throws IllegalArgumentException when an illegal carrier type is used - */ - public static VarHandle varHandle(Class carrier, ByteOrder byteOrder) { - Objects.requireNonNull(carrier); - Objects.requireNonNull(byteOrder); - return varHandle(carrier, - carrierSize(carrier), - byteOrder); - } - - /** - * Creates a memory access var handle with the given carrier type, alignment constraint, and byte order. + * Creates a memory access var handle from given value layout. The provided layout will specify the + * {@linkplain ValueLayout#carrier() carrier type}, the {@linkplain ValueLayout#byteSize() the byte size}, + * the {@linkplain ValueLayout#byteAlignment() byte alignment} and the {@linkplain ValueLayout#order() byte order} + * associated to the returned var handle. * * The returned var handle's type is {@code carrier} and the list of coordinate types is * {@code (MemorySegment, long)}, where the {@code long} coordinate type corresponds to byte offset into @@ -192,56 +159,13 @@ public final class MemoryHandles { * @apiNote the resulting var handle features certain access mode restrictions, * which are common to all memory access var handles. * - * @param carrier the carrier type. Valid carriers are {@code byte}, {@code short}, {@code char}, {@code int}, - * {@code float}, {@code long}, and {@code double}. - * @param alignmentBytes the alignment constraint (in bytes). Must be a power of two. - * @param byteOrder the required byte order. + * @param layout the value layout for which a memory access handle is to be obtained. * @return the new memory access var handle. * @throws IllegalArgumentException if an illegal carrier type is used, or if {@code alignmentBytes} is not a power of two. */ - public static VarHandle varHandle(Class carrier, long alignmentBytes, ByteOrder byteOrder) { - Objects.requireNonNull(carrier); - Objects.requireNonNull(byteOrder); - checkCarrier(carrier); - - if (alignmentBytes <= 0 - || (alignmentBytes & (alignmentBytes - 1)) != 0) { // is power of 2? - throw new IllegalArgumentException("Bad alignment: " + alignmentBytes); - } - - return Utils.fixUpVarHandle(JLI.memoryAccessVarHandle(carrier, false, alignmentBytes - 1, byteOrder)); - } - - /** - * Adapt an existing var handle into a new var handle whose carrier type is {@link MemorySegment}. - * That is, when calling {@link VarHandle#get(Object...)} on the returned var handle, - * the read numeric value will be turned into a memory address (as if by calling {@link MemoryAddress#ofLong(long)}); - * similarly, when calling {@link VarHandle#set(Object...)}, the memory address to be set will be converted - * into a numeric value, and then written into memory. The amount of bytes read (resp. written) from (resp. to) - * memory depends on the carrier of the original memory access var handle. - * - * @param target the memory access var handle to be adapted - * @return the adapted var handle. - * @throws IllegalArgumentException if the carrier type of {@code varHandle} is either {@code boolean}, - * {@code float}, or {@code double}, or is not a primitive type. - */ - public static VarHandle asAddressVarHandle(VarHandle target) { - Objects.requireNonNull(target); - Class carrier = target.varType(); - if (!carrier.isPrimitive() || carrier == boolean.class || - carrier == float.class || carrier == double.class) { - throw new IllegalArgumentException("Unsupported carrier type: " + carrier.getName()); - } - - if (carrier != long.class) { - // slow-path, we need to adapt - return filterValue(target, - MethodHandles.explicitCastArguments(ADDRESS_TO_LONG, MethodType.methodType(carrier, MemoryAddress.class)), - MethodHandles.explicitCastArguments(LONG_TO_ADDRESS, MethodType.methodType(MemoryAddress.class, carrier))); - } else { - // fast-path - return filterValue(target, ADDRESS_TO_LONG, LONG_TO_ADDRESS); - } + public static VarHandle varHandle(ValueLayout layout) { + Objects.requireNonNull(layout); + return layout.accessHandle(); } /** @@ -253,13 +177,13 @@ public final class MemoryHandles { * example, it is often convenient to model an unsigned short as a * Java {@code int} to avoid dealing with negative values, which would be * the case if modeled as a Java {@code short}. This is illustrated in the following example: - *

    {@code
    -    MemorySegment segment = MemorySegment.allocateNative(2, ResourceScope.newImplicitScope());
    -    VarHandle SHORT_VH = MemoryLayouts.JAVA_SHORT.varHandle(short.class);
    -    VarHandle INT_VH = MemoryHandles.asUnsigned(SHORT_VH, int.class);
    -    SHORT_VH.set(segment, (short)-1);
    -    INT_VH.get(segment); // returns 65535
    -     * }
    + * {@snippet lang=java : + * MemorySegment segment = MemorySegment.allocateNative(2, ResourceScope.newImplicitScope()); + * VarHandle SHORT_VH = ValueLayout.JAVA_SHORT.varHandle(); + * VarHandle INT_VH = MemoryHandles.asUnsigned(SHORT_VH, int.class); + * SHORT_VH.set(segment, (short)-1); + * INT_VH.get(segment); // returns 65535 + * } *

    * When calling e.g. {@link VarHandle#set(Object...)} on the resulting var * handle, the incoming value (of type {@code adaptedType}) is converted by a @@ -276,7 +200,7 @@ public final class MemoryHandles { *

    * The returned var handle will feature the variable type {@code adaptedType}, * and the same access coordinates, the same access modes (see {@link - * java.lang.invoke.VarHandle.AccessMode}, and the same atomic access + * java.lang.invoke.VarHandle.AccessMode}), and the same atomic access * guarantees, as those featured by the {@code target} var handle. * * @param target the memory access var handle to be adapted @@ -284,7 +208,7 @@ public final class MemoryHandles { * @return the adapted var handle. * @throws IllegalArgumentException if the carrier type of {@code target} * is not one of {@code byte}, {@code short}, or {@code int}; if {@code - * adaptedType} is not one of {@code int}, or {@code long}; if the bitwidth + * adaptedType} is not one of {@code int}, or {@code long}; if the bit width * of the {@code adaptedType} is not greater than that of the {@code target} * carrier type. * @@ -324,12 +248,15 @@ public final class MemoryHandles { * is processed using the second filter and returned to the caller. More advanced access mode types, such as * {@link java.lang.invoke.VarHandle.AccessMode#COMPARE_AND_EXCHANGE} might apply both filters at the same time. *

    - * For the boxing and unboxing filters to be well formed, their types must be of the form {@code (A... , S) -> T} and + * For the boxing and unboxing filters to be well-formed, their types must be of the form {@code (A... , S) -> T} and * {@code (A... , T) -> S}, respectively, where {@code T} is the type of the target var handle. If this is the case, * the resulting var handle will have type {@code S} and will feature the additional coordinates {@code A...} (which * will be appended to the coordinates of the target var handle). *

    - * The resulting var handle will feature the same access modes (see {@link java.lang.invoke.VarHandle.AccessMode} and + * If the boxing and unboxing filters throw any checked exceptions when invoked, the resulting var handle will + * throw an {@link IllegalStateException}. + *

    + * The resulting var handle will feature the same access modes (see {@link java.lang.invoke.VarHandle.AccessMode}) and * atomic access guarantees as those featured by the target var handle. * * @param target the target var handle @@ -338,7 +265,7 @@ public final class MemoryHandles { * @return an adapter var handle which accepts a new type, performing the provided boxing/unboxing conversions. * @throws IllegalArgumentException if {@code filterFromTarget} and {@code filterToTarget} are not well-formed, that is, they have types * other than {@code (A... , S) -> T} and {@code (A... , T) -> S}, respectively, where {@code T} is the type of the target var handle, - * or if either {@code filterFromTarget} or {@code filterToTarget} throws any checked exceptions. + * or if it's determined that either {@code filterFromTarget} or {@code filterToTarget} throws any checked exceptions. */ public static VarHandle filterValue(VarHandle target, MethodHandle filterToTarget, MethodHandle filterFromTarget) { return JLI.filterValue(target, filterToTarget, filterFromTarget); @@ -353,9 +280,12 @@ public final class MemoryHandles { * parameter types of the unary filter functions), and then passed (along with any coordinate that was left unaltered * by the adaptation) to the target var handle. *

    - * For the coordinate filters to be well formed, their types must be of the form {@code S1 -> T1, S2 -> T1 ... Sn -> Tn}, + * For the coordinate filters to be well-formed, their types must be of the form {@code S1 -> T1, S2 -> T1 ... Sn -> Tn}, * where {@code T1, T2 ... Tn} are the coordinate types starting at position {@code pos} of the target var handle. *

    + * If any of the filters throws a checked exception when invoked, the resulting var handle will + * throw an {@link IllegalStateException}. + *

    * The resulting var handle will feature the same access modes (see {@link java.lang.invoke.VarHandle.AccessMode}) and * atomic access guarantees as those featured by the target var handle. * @@ -368,7 +298,7 @@ public final class MemoryHandles { * other than {@code S1 -> T1, S2 -> T2, ... Sn -> Tn} where {@code T1, T2 ... Tn} are the coordinate types starting * at position {@code pos} of the target var handle, if {@code pos} is not between 0 and the target var handle coordinate arity, inclusive, * or if more filters are provided than the actual number of coordinate types available starting at {@code pos}, - * or if any of the filters throws any checked exceptions. + * or if it's determined that any of the filters throws any checked exceptions. */ public static VarHandle filterCoordinates(VarHandle target, int pos, MethodHandle... filters) { return JLI.filterCoordinates(target, pos, filters); @@ -382,7 +312,7 @@ public final class MemoryHandles { * When calling e.g. {@link VarHandle#get(Object...)} on the resulting var handle, incoming coordinate values * are joined with bound coordinate values, and then passed to the target var handle. *

    - * For the bound coordinates to be well formed, their types must be {@code T1, T2 ... Tn }, + * For the bound coordinates to be well-formed, their types must be {@code T1, T2 ... Tn }, * where {@code T1, T2 ... Tn} are the coordinate types starting at position {@code pos} of the target var handle. *

    * The resulting var handle will feature the same access modes (see {@link java.lang.invoke.VarHandle.AccessMode}) and @@ -409,7 +339,7 @@ public final class MemoryHandles { *

    * The given array controls the reordering. * Call {@code #I} the number of incoming coordinates (the value - * {@code newCoordinates.size()}, and call {@code #O} the number + * {@code newCoordinates.size()}), and call {@code #O} the number * of outgoing coordinates (the number of coordinates associated with the target var handle). * Then the length of the reordering array must be {@code #O}, * and each element must be a non-negative number less than {@code #I}. @@ -444,7 +374,7 @@ public final class MemoryHandles { } /** - * Adapts a target var handle handle by pre-processing + * Adapts a target var handle by pre-processing * a sub-sequence of its coordinate values with a filter (a method handle). * The pre-processed coordinates are replaced by the result (if any) of the * filter function and the target var handle is then called on the modified (usually shortened) @@ -464,6 +394,9 @@ public final class MemoryHandles { * coordinate type of the target var handle at position {@code pos}, and that target var handle * coordinate is supplied by the return value of the filter. *

    + * If any of the filters throws a checked exception when invoked, the resulting var handle will + * throw an {@link IllegalStateException}. + *

    * The resulting var handle will feature the same access modes (see {@link java.lang.invoke.VarHandle.AccessMode}) and * atomic access guarantees as those featured by the target var handle. * @@ -476,7 +409,7 @@ public final class MemoryHandles { * is void, or it is not the same as the {@code pos} coordinate of the target var handle, * if {@code pos} is not between 0 and the target var handle coordinate arity, inclusive, * if the resulting var handle's type would have too many coordinates, - * or if {@code filter} throws any checked exceptions. + * or if it's determined that {@code filter} throws any checked exceptions. */ public static VarHandle collectCoordinates(VarHandle target, int pos, MethodHandle filter) { return JLI.collectCoordinates(target, pos, filter); @@ -505,24 +438,6 @@ public final class MemoryHandles { return JLI.dropCoordinates(target, pos, valueTypes); } - private static void checkAddressFirstCoordinate(VarHandle handle) { - if (handle.coordinateTypes().size() < 1 || - handle.coordinateTypes().get(0) != MemorySegment.class) { - throw new IllegalArgumentException("Expected var handle with leading coordinate of type MemorySegment"); - } - } - - private static void checkCarrier(Class carrier) { - if (!carrier.isPrimitive() || carrier == void.class || carrier == boolean.class) { - throw new IllegalArgumentException("Illegal carrier: " + carrier.getSimpleName()); - } - } - - private static long carrierSize(Class carrier) { - long bitsAlignment = Math.max(8, Wrapper.forPrimitiveType(carrier).bitWidth()); - return Utils.bitsToBytesOrThrow(bitsAlignment, IllegalStateException::new); - } - private static void checkWidenable(Class carrier) { if (!(carrier == byte.class || carrier == short.class || carrier == int.class)) { throw new IllegalArgumentException("illegal carrier:" + carrier.getSimpleName()); @@ -541,12 +456,4 @@ public final class MemoryHandles { target.getSimpleName() + " is not wider than: " + carrier.getSimpleName()); } } - - private static MemoryAddress longToAddress(long value) { - return MemoryAddress.ofLong(value); - } - - private static long addressToLong(MemoryAddress value) { - return value.toRawLongValue(); - } } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryLayout.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryLayout.java index 44793be750f963504e7be6480566e726838b583c..fe0fb4e93f9ce140f4ac141ab96f5a604a32d2d1 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryLayout.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryLayout.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,11 +46,11 @@ import java.util.stream.Collectors; import java.util.stream.Stream; /** - * A memory layout can be used to describe the contents of a memory segment in a language neutral fashion. + * A memory layout can be used to describe the contents of a memory segment. * There are two leaves in the layout hierarchy, value layouts, which are used to represent values of given size and kind (see * {@link ValueLayout}) and padding layouts which are used, as the name suggests, to represent a portion of a memory * segment whose contents should be ignored, and which are primarily present for alignment reasons (see {@link MemoryLayout#paddingLayout(long)}). - * Some common value layout constants are defined in the {@link MemoryLayouts} class. + * Some common value layout constants are defined in the {@link ValueLayout} class. *

    * More complex layouts can be derived from simpler ones: a sequence layout denotes a repetition of one or more * element layout (see {@link SequenceLayout}); a group layout denotes an aggregation of (typically) heterogeneous @@ -58,31 +58,29 @@ import java.util.stream.Stream; *

    * For instance, consider the following struct declaration in C: * - *

    {@code
    - typedef struct {
    -     char kind;
    -     int value;
    - } TaggedValues[5];
    - * }
    + * {@snippet lang=c : + * typedef struct { + * char kind; + * int value; + * } TaggedValues[5]; + * } * * The above declaration can be modelled using a layout object, as follows: * - *
    {@code
    -SequenceLayout taggedValues = MemoryLayout.sequenceLayout(5,
    -    MemoryLayout.structLayout(
    -        MemoryLayout.valueLayout(8, ByteOrder.nativeOrder()).withName("kind"),
    -        MemoryLayout.paddingLayout(24),
    -        MemoryLayout.valueLayout(32, ByteOrder.nativeOrder()).withName("value")
    -    )
    -).withName("TaggedValues");
    - * }
    + * {@snippet lang=java : + * SequenceLayout taggedValues = MemoryLayout.sequenceLayout(5, + * MemoryLayout.structLayout( + * ValueLayout.JAVA_BYTE.withName("kind"), + * MemoryLayout.paddingLayout(24), + * ValueLayout.JAVA_INT.withName("value") + * ) + * ).withName("TaggedValues"); + * } *

    * All implementations of this interface must be value-based; * programmers should treat instances that are {@linkplain #equals(Object) equal} as interchangeable and should not * use instances for synchronization, or unpredictable behavior may occur. For example, in a future release, * synchronization may fail. The {@code equals} method should be used for comparisons. - *

    - * Non-platform classes should not implement {@linkplain MemoryLayout} directly. * *

    Unless otherwise specified, passing a {@code null} argument, or an array argument containing one or more {@code null} * elements to a method in this class causes a {@link NullPointerException NullPointerException} to be thrown.

    @@ -122,52 +120,51 @@ SequenceLayout taggedValues = MemoryLayout.sequenceLayout(5, * at a layout nested within the root layout - this is the layout selected by the layout path. * Layout paths are typically expressed as a sequence of one or more {@link PathElement} instances. *

    - * Layout paths are for example useful in order to obtain offsets of arbitrarily nested layouts inside another layout - * (see {@link MemoryLayout#bitOffset(PathElement...)}), to quickly obtain a memory access handle corresponding to the selected - * layout (see {@link MemoryLayout#varHandle(Class, PathElement...)}), to select an arbitrarily nested layout inside - * another layout (see {@link MemoryLayout#select(PathElement...)}, or to transform a nested layout element inside - * another layout (see {@link MemoryLayout#map(UnaryOperator, PathElement...)}). + * Layout paths are for example useful in order to obtain {@linkplain MemoryLayout#bitOffset(PathElement...) offsets} of + * arbitrarily nested layouts inside another layout, to quickly obtain a {@linkplain #varHandle(PathElement...) memory access handle} + * corresponding to the selected layout, to {@linkplain #select(PathElement...) select} an arbitrarily nested layout inside + * another layout, or to {@link #map(UnaryOperator, PathElement...) transform} a nested layout element inside + * another layout. *

    * Such layout paths can be constructed programmatically using the methods in this class. * For instance, given the {@code taggedValues} layout instance constructed as above, we can obtain the offset, * in bits, of the member layout named value in the first sequence element, as follows: - *

    {@code
    -long valueOffset = taggedValues.bitOffset(PathElement.sequenceElement(0),
    -                                          PathElement.groupElement("value")); // yields 32
    - * }
    + * {@snippet lang=java : + * long valueOffset = taggedValues.bitOffset(PathElement.sequenceElement(0), + * PathElement.groupElement("value")); // yields 32 + * } * * Similarly, we can select the member layout named {@code value}, as follows: - *
    {@code
    -MemoryLayout value = taggedValues.select(PathElement.sequenceElement(),
    -                                         PathElement.groupElement("value"));
    - * }
    + * {@snippet lang=java : + * MemoryLayout value = taggedValues.select(PathElement.sequenceElement(), + * PathElement.groupElement("value")); + * } * * And, we can also replace the layout named {@code value} with another layout, as follows: - *
    {@code
    -MemoryLayout taggedValuesWithHole = taggedValues.map(l -> MemoryLayout.paddingLayout(32),
    -                                            PathElement.sequenceElement(), PathElement.groupElement("value"));
    - * }
    + * {@snippet lang=java : + * MemoryLayout taggedValuesWithHole = taggedValues.map(l -> MemoryLayout.paddingLayout(32), + * PathElement.sequenceElement(), PathElement.groupElement("value")); + * } * * That is, the above declaration is identical to the following, more verbose one: - *
    {@code
    -MemoryLayout taggedValuesWithHole = MemoryLayout.sequenceLayout(5,
    -    MemoryLayout.structLayout(
    -        MemoryLayout.valueLayout(8, ByteOrder.nativeOrder()).withName("kind"),
    -        MemoryLayout.paddingLayout(32),
    -        MemoryLayout.paddingLayout(32)
    -));
    - * }
    + * {@snippet lang=java : + * MemoryLayout taggedValuesWithHole = MemoryLayout.sequenceLayout(5, + * MemoryLayout.structLayout( + * ValueLayout.JAVA_BYTE.withName("kind"), + * MemoryLayout.paddingLayout(32), + * MemoryLayout.paddingLayout(32) + * )); + * } * * Layout paths can feature one or more free dimensions. For instance, a layout path traversing * an unspecified sequence element (that is, where one of the path component was obtained with the * {@link PathElement#sequenceElement()} method) features an additional free dimension, which will have to be bound at runtime. * This is important when obtaining memory access var handle from layouts, as in the following code: * - *
    {@code
    -VarHandle valueHandle = taggedValues.varHandle(int.class,
    -                                               PathElement.sequenceElement(),
    -                                               PathElement.groupElement("value"));
    - * }
    + * {@snippet lang=java : + * VarHandle valueHandle = taggedValues.varHandle(PathElement.sequenceElement(), + * PathElement.groupElement("value")); + * } * * Since the layout path constructed in the above example features exactly one free dimension (as it doesn't specify * which member layout named {@code value} should be selected from the enclosing sequence layout), @@ -180,18 +177,16 @@ VarHandle valueHandle = taggedValues.varHandle(int.class, * offsets of elements of a sequence at different indices, by supplying these indices when invoking the method handle. * For instance: * - *
    {@code
    -MethodHandle offsetHandle = taggedValues.byteOffsetHandle(PathElement.sequenceElement(),
    -                                                          PathElement.groupElement("kind"));
    -long offset1 = (long) offsetHandle.invokeExact(1L); // 8
    -long offset2 = (long) offsetHandle.invokeExact(2L); // 16
    - * }
    + * {@snippet lang=java : + * MethodHandle offsetHandle = taggedValues.byteOffsetHandle(PathElement.sequenceElement(), + * PathElement.groupElement("kind")); + * long offset1 = (long) offsetHandle.invokeExact(1L); // 8 + * long offset2 = (long) offsetHandle.invokeExact(2L); // 16 + * } * *

    Layout attributes

    * - * Layouts can be optionally associated with one or more attributes. A layout attribute forms a name/value - * pair, where the name is a {@link String} and the value is a {@link Constable}. The most common form of layout attribute - * is the layout name (see {@link #LAYOUT_NAME}), a custom name that can be associated with memory layouts and that can be referred to when + * Layouts can be optionally associated with a name. A layout name can be referred to when * constructing layout paths. * * @implSpec @@ -236,18 +231,10 @@ public sealed interface MemoryLayout extends Constable permits AbstractLayout, S * @throws UnsupportedOperationException if the layout is, or contains, a sequence layout with unspecified size (see {@link SequenceLayout}), * or if {@code bitSize()} is not a multiple of 8. */ - default long byteSize() { - return Utils.bitsToBytesOrThrow(bitSize(), - () -> new UnsupportedOperationException("Cannot compute byte size; bit size is not a multiple of 8")); - } + long byteSize(); /** * Return the name (if any) associated with this layout. - *

    - * This is equivalent to the following code: - *

    {@code
    -    attribute(LAYOUT_NAME).map(String.class::cast);
    -     * }
    * * @return the layout name (if any). * @see MemoryLayout#withName(String) @@ -256,11 +243,6 @@ public sealed interface MemoryLayout extends Constable permits AbstractLayout, S /** * Creates a new layout which features the desired layout name. - *

    - * This is equivalent to the following code: - *

    {@code
    -    withAttribute(LAYOUT_NAME, name);
    -     * }
    * * @param name the layout name. * @return a new layout which is the same as this layout, except for the name associated with it. @@ -313,36 +295,10 @@ public sealed interface MemoryLayout extends Constable permits AbstractLayout, S * * @param bitAlignment the layout alignment constraint, expressed in bits. * @return a new layout which is the same as this layout, except for the alignment constraint associated with it. - * @throws IllegalArgumentException if {@code bitAlignment} is not a power of two, or if it's less than than 8. + * @throws IllegalArgumentException if {@code bitAlignment} is not a power of two, or if it's less than 8. */ MemoryLayout withBitAlignment(long bitAlignment); - /** - * Returns the attribute with the given name (if it exists). - * - * @param name the attribute name - * @return the attribute with the given name (if it exists). - */ - Optional attribute(String name); - - /** - * Returns a new memory layout which features the same attributes as this layout, plus the newly specified attribute. - * If this layout already contains an attribute with the same name, the existing attribute value is overwritten in the returned - * layout. - * - * @param name the attribute name. - * @param value the attribute value. - * @return a new memory layout which features the same attributes as this layout, plus the newly specified attribute. - */ - MemoryLayout withAttribute(String name, Constable value); - - /** - * Returns a stream of the attribute names associated with this layout. - * - * @return a stream of the attribute names associated with this layout. - */ - Stream attributes(); - /** * Computes the offset, in bits, of the layout selected by a given layout path, where the path is considered rooted in this * layout. @@ -366,7 +322,7 @@ public sealed interface MemoryLayout extends Constable permits AbstractLayout, S * by a given layout path, where the path is considered rooted in this layout. * *

    The returned method handle has a return type of {@code long}, and features as many {@code long} - * parameter types as there are free dimensions in the provided layout path (see {@link PathElement#sequenceElement()}, + * parameter types as there are free dimensions in the provided layout path (see {@link PathElement#sequenceElement()}), * where the order of the parameters corresponds to the order of the path elements. * The returned method handle can be used to compute a layout offset similar to {@link #bitOffset(PathElement...)}, * but where some sequence indices are specified only when invoking the method handle. @@ -374,7 +330,7 @@ public sealed interface MemoryLayout extends Constable permits AbstractLayout, S *

    The final offset returned by the method handle is computed as follows: * *

    {@code
    -    offset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
    +     * offset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
          * }
    * * where {@code x_1}, {@code x_2}, ... {@code x_n} are dynamic values provided as {@code long} @@ -417,7 +373,7 @@ public sealed interface MemoryLayout extends Constable permits AbstractLayout, S * by a given layout path, where the path is considered rooted in this layout. * *

    The returned method handle has a return type of {@code long}, and features as many {@code long} - * parameter types as there are free dimensions in the provided layout path (see {@link PathElement#sequenceElement()}, + * parameter types as there are free dimensions in the provided layout path (see {@link PathElement#sequenceElement()}), * where the order of the parameters corresponds to the order of the path elements. * The returned method handle can be used to compute a layout offset similar to {@link #byteOffset(PathElement...)}, * but where some sequence indices are specified only when invoking the method handle. @@ -425,8 +381,8 @@ public sealed interface MemoryLayout extends Constable permits AbstractLayout, S *

    The final offset returned by the method handle is computed as follows: * *

    {@code
    -    bitOffset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
    -    offset = bitOffset / 8
    +     * bitOffset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
    +     * offset = bitOffset / 8
          * }
    * * where {@code x_1}, {@code x_2}, ... {@code x_n} are dynamic values provided as {@code long} @@ -457,7 +413,7 @@ public sealed interface MemoryLayout extends Constable permits AbstractLayout, S * The final memory location accessed by the returned memory access var handle can be computed as follows: * *
    {@code
    -    address = base + offset
    +     * address = base + offset
          * }
    * * where {@code base} denotes the base address expressed by the {@link MemorySegment} access coordinate @@ -465,7 +421,7 @@ public sealed interface MemoryLayout extends Constable permits AbstractLayout, S * can be expressed in the following form: * *
    {@code
    -    offset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
    +     * offset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
          * }
    * * where {@code x_1}, {@code x_2}, ... {@code x_n} are dynamic values provided as {@code long} @@ -477,18 +433,14 @@ public sealed interface MemoryLayout extends Constable permits AbstractLayout, S * unspecified sequence access component contained in this layout path. Moreover, the resulting var handle * features certain access mode restrictions, which are common to all memory access var handles. * - * @param carrier the var handle carrier type. * @param elements the layout path elements. * @return a var handle which can be used to dereference memory at the (possibly nested) layout selected by the layout path in {@code elements}. * @throws UnsupportedOperationException if the layout path has one or more elements with incompatible alignment constraints, * or if one of the layouts traversed by the layout path has unspecified size. - * @throws IllegalArgumentException if the carrier does not represent a primitive type, if the carrier is {@code void}, - * {@code boolean}, or if the layout path in {@code elements} does not select a value layout (see {@link ValueLayout}), - * or if the selected value layout has a size that that does not match that of the specified carrier type. + * @throws IllegalArgumentException if the layout path in {@code elements} does not select a value layout (see {@link ValueLayout}). */ - default VarHandle varHandle(Class carrier, PathElement... elements) { - Objects.requireNonNull(carrier); - return computePathOp(LayoutPath.rootPath(this, MemoryLayout::bitSize), path -> path.dereferenceHandle(carrier), + default VarHandle varHandle(PathElement... elements) { + return computePathOp(LayoutPath.rootPath(this, MemoryLayout::bitSize), LayoutPath::dereferenceHandle, Set.of(), elements); } @@ -498,7 +450,7 @@ public sealed interface MemoryLayout extends Constable permits AbstractLayout, S * *

    The returned method handle has a return type of {@code MemorySegment}, features a {@code MemorySegment} * parameter as leading parameter representing the segment to be sliced, and features as many trailing {@code long} - * parameter types as there are free dimensions in the provided layout path (see {@link PathElement#sequenceElement()}, + * parameter types as there are free dimensions in the provided layout path (see {@link PathElement#sequenceElement()}), * where the order of the parameters corresponds to the order of the path elements. * The returned method handle can be used to create a slice similar to using {@link MemorySegment#asSlice(long, long)}, * but where the offset argument is dynamically compute based on indices specified when invoking the method handle. @@ -506,8 +458,8 @@ public sealed interface MemoryLayout extends Constable permits AbstractLayout, S *

    The offset of the returned segment is computed as follows: * *

    {@code
    -    bitOffset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
    -    offset = bitOffset / 8
    +     * bitOffset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
    +     * offset = bitOffset / 8
          * }
    * * where {@code x_1}, {@code x_2}, ... {@code x_n} are dynamic values provided as {@code long} @@ -515,10 +467,10 @@ public sealed interface MemoryLayout extends Constable permits AbstractLayout, S * and {@code s_0}, {@code s_1}, ... {@code s_n} are static stride constants which are derived from * the layout path. * - *

    After the offset is computed, the returned segment is create as if by calling: - *

    {@code
    -    segment.asSlice(offset, layout.byteSize());
    -     * }
    + *

    After the offset is computed, the returned segment is created as if by calling: + * {@snippet lang=java : + * segment.asSlice(offset, layout.byteSize()); + * } * * where {@code segment} is the segment to be sliced, and where {@code layout} is the layout selected by the given * layout path, as per {@link MemoryLayout#select(PathElement...)}. @@ -582,7 +534,7 @@ public sealed interface MemoryLayout extends Constable permits AbstractLayout, S } /** - * Is this a padding layout (e.g. a layout created from {@link #paddingLayout(long)}) ? + * Is this a {@linkplain #paddingLayout(long) padding layout} ? * @return true, if this layout is a padding layout. */ boolean isPadding(); @@ -595,8 +547,6 @@ public sealed interface MemoryLayout extends Constable permits AbstractLayout, S * of sequence element layout can be explicit (see {@link PathElement#sequenceElement(long)}) or * implicit (see {@link PathElement#sequenceElement()}). When a path uses one or more implicit * sequence path elements, it acquires additional free dimensions. - *

    - * Non-platform classes should not implement {@linkplain PathElement} directly. * *

    Unless otherwise specified, passing a {@code null} argument, or an array argument containing one or more {@code null} * elements to a method in this class causes a {@link NullPointerException NullPointerException} to be thrown.

    @@ -612,7 +562,7 @@ public sealed interface MemoryLayout extends Constable permits AbstractLayout, S * that is combined with such element. * * @implSpec in case multiple group elements with a matching name exist, the path element returned by this - * method will select the first one; that is, the group element with lowest offset from current path is selected. + * method will select the first one; that is, the group element with the lowest offset from current path is selected. * * @param name the name of the group element to be selected. * @return a path element which selects the group element with given name. @@ -649,7 +599,7 @@ public sealed interface MemoryLayout extends Constable permits AbstractLayout, S * with this path is bound by an index {@code I}, the resulting accessed offset can be obtained with the following * formula: *
    {@code
    -E * (S + I * F)
    +         * E * (S + I * F)
              * }
    * where {@code E} is the size (in bytes) of the sequence element layout. * @@ -728,17 +678,48 @@ E * (S + I * F) } /** - * Create a value layout of given byte order and size. - * - * @param size the value layout size. + * Creates a value layout of given Java carrier and byte order. The type of resulting value layout is determined + * by the carrier provided: + *
      + *
    • {@link ValueLayout.OfBoolean}, for {@code boolean.class}
    • + *
    • {@link ValueLayout.OfByte}, for {@code byte.class}
    • + *
    • {@link ValueLayout.OfShort}, for {@code short.class}
    • + *
    • {@link ValueLayout.OfChar}, for {@code char.class}
    • + *
    • {@link ValueLayout.OfInt}, for {@code int.class}
    • + *
    • {@link ValueLayout.OfFloat}, for {@code float.class}
    • + *
    • {@link ValueLayout.OfLong}, for {@code long.class}
    • + *
    • {@link ValueLayout.OfDouble}, for {@code double.class}
    • + *
    • {@link ValueLayout.OfAddress}, for {@code MemoryAddress.class}
    • + *
    + * @param carrier the value layout carrier. * @param order the value layout's byte order. * @return a new value layout. - * @throws IllegalArgumentException if {@code size <= 0}. + * @throws IllegalArgumentException if the carrier type is not supported. */ - static ValueLayout valueLayout(long size, ByteOrder order) { + static ValueLayout valueLayout(Class carrier, ByteOrder order) { + Objects.requireNonNull(carrier); Objects.requireNonNull(order); - AbstractLayout.checkSize(size); - return new ValueLayout(order, size); + if (carrier == boolean.class) { + return new ValueLayout.OfBoolean(order); + } else if (carrier == char.class) { + return new ValueLayout.OfChar(order); + } else if (carrier == byte.class) { + return new ValueLayout.OfByte(order); + } else if (carrier == short.class) { + return new ValueLayout.OfShort(order); + } else if (carrier == int.class) { + return new ValueLayout.OfInt(order); + } else if (carrier == float.class) { + return new ValueLayout.OfFloat(order); + } else if (carrier == long.class) { + return new ValueLayout.OfLong(order); + } else if (carrier == double.class) { + return new ValueLayout.OfDouble(order); + } else if (carrier == MemoryAddress.class) { + return new ValueLayout.OfAddress(order); + } else { + throw new IllegalArgumentException("Unsupported carrier: " + carrier.getName()); + } } /** @@ -792,9 +773,4 @@ E * (S + I * F) .map(Objects::requireNonNull) .collect(Collectors.toList())); } - - /** - * Attribute name used to specify the name property of a memory layout (see {@link #name()} and {@link #withName(String)}). - */ - String LAYOUT_NAME = "layout/name"; } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryLayouts.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryLayouts.java deleted file mode 100644 index 4aee085821f1c5053bf653d653ffd0f79539545d..0000000000000000000000000000000000000000 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryLayouts.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package jdk.incubator.foreign; - -import jdk.internal.misc.Unsafe; - -import java.nio.ByteOrder; - -/** - * This class defines useful layout constants. Some of the constants defined in this class are explicit in both - * size and byte order (see {@link #BITS_64_BE}), and can therefore be used to explicitly and unambiguously specify the - * contents of a memory segment. Other constants make implicit byte order assumptions (see - * {@link #JAVA_INT}); as such, these constants make it easy to work with other serialization-centric APIs, - * such as {@link java.nio.ByteBuffer}. - */ -public final class MemoryLayouts { - - private MemoryLayouts() { - //just the one, please - } - - /** - * A value layout constant with size of one byte, and byte order set to {@link ByteOrder#LITTLE_ENDIAN}. - */ - public static final ValueLayout BITS_8_LE = MemoryLayout.valueLayout(8, ByteOrder.LITTLE_ENDIAN); - - /** - * A value layout constant with size of two bytes, and byte order set to {@link ByteOrder#LITTLE_ENDIAN}. - */ - public static final ValueLayout BITS_16_LE = MemoryLayout.valueLayout(16, ByteOrder.LITTLE_ENDIAN); - - /** - * A value layout constant with size of four bytes, and byte order set to {@link ByteOrder#LITTLE_ENDIAN}. - */ - public static final ValueLayout BITS_32_LE = MemoryLayout.valueLayout(32, ByteOrder.LITTLE_ENDIAN); - - /** - * A value layout constant with size of eight bytes, and byte order set to {@link ByteOrder#LITTLE_ENDIAN}. - */ - public static final ValueLayout BITS_64_LE = MemoryLayout.valueLayout(64, ByteOrder.LITTLE_ENDIAN); - - /** - * A value layout constant with size of one byte, and byte order set to {@link ByteOrder#BIG_ENDIAN}. - */ - public static final ValueLayout BITS_8_BE = MemoryLayout.valueLayout(8, ByteOrder.BIG_ENDIAN); - - /** - * A value layout constant with size of two bytes, and byte order set to {@link ByteOrder#BIG_ENDIAN}. - */ - public static final ValueLayout BITS_16_BE = MemoryLayout.valueLayout(16, ByteOrder.BIG_ENDIAN); - - /** - * A value layout constant with size of four bytes, and byte order set to {@link ByteOrder#BIG_ENDIAN}. - */ - public static final ValueLayout BITS_32_BE = MemoryLayout.valueLayout(32, ByteOrder.BIG_ENDIAN); - - /** - * A value layout constant with size of eight bytes, and byte order set to {@link ByteOrder#BIG_ENDIAN}. - */ - public static final ValueLayout BITS_64_BE = MemoryLayout.valueLayout(64, ByteOrder.BIG_ENDIAN); - - /** - * A padding layout constant with size of one byte. - */ - public static final MemoryLayout PAD_8 = MemoryLayout.paddingLayout(8); - - /** - * A padding layout constant with size of two bytes. - */ - public static final MemoryLayout PAD_16 = MemoryLayout.paddingLayout(16); - - /** - * A padding layout constant with size of four bytes. - */ - public static final MemoryLayout PAD_32 = MemoryLayout.paddingLayout(32); - - /** - * A padding layout constant with size of eight bytes. - */ - public static final MemoryLayout PAD_64 = MemoryLayout.paddingLayout(64); - - /** - * A value layout constant whose size is the same as that of a machine address (e.g. {@code size_t}), and byte order set to {@link ByteOrder#nativeOrder()}. - */ - public static final ValueLayout ADDRESS = MemoryLayout.valueLayout(Unsafe.ADDRESS_SIZE * 8, ByteOrder.nativeOrder()); - - /** - * A value layout constant whose size is the same as that of a Java {@code byte}, and byte order set to {@link ByteOrder#nativeOrder()}. - */ - public static final ValueLayout JAVA_BYTE = MemoryLayout.valueLayout(8, ByteOrder.nativeOrder()); - - /** - * A value layout constant whose size is the same as that of a Java {@code char}, and byte order set to {@link ByteOrder#nativeOrder()}. - */ - public static final ValueLayout JAVA_CHAR = MemoryLayout.valueLayout(16, ByteOrder.nativeOrder()); - - /** - * A value layout constant whose size is the same as that of a Java {@code short}, and byte order set to {@link ByteOrder#nativeOrder()}. - */ - public static final ValueLayout JAVA_SHORT = MemoryLayout.valueLayout(16, ByteOrder.nativeOrder()); - - /** - * A value layout constant whose size is the same as that of a Java {@code int}, and byte order set to {@link ByteOrder#nativeOrder()}. - */ - public static final ValueLayout JAVA_INT = MemoryLayout.valueLayout(32, ByteOrder.nativeOrder()); - - /** - * A value layout constant whose size is the same as that of a Java {@code long}, and byte order set to {@link ByteOrder#nativeOrder()}. - * The alignment of this layout (see {@link MemoryLayout#byteAlignment()} is platform-dependent, so that the following - * invariant holds: - *
    {@code
    -    MemoryLayouts.JAVA_LONG.byteAlignment() == MemoryLayouts.ADDRESS.byteSize();
    -     * }
    - */ - public static final ValueLayout JAVA_LONG = MemoryLayout.valueLayout(64, ByteOrder.nativeOrder()) - .withBitAlignment(ADDRESS.bitSize()); - - /** - * A value layout constant whose size is the same as that of a Java {@code float}, and byte order set to {@link ByteOrder#nativeOrder()}. - */ - public static final ValueLayout JAVA_FLOAT = MemoryLayout.valueLayout(32, ByteOrder.nativeOrder()); - - /** - * A value layout constant whose size is the same as that of a Java {@code double}, and byte order set to {@link ByteOrder#nativeOrder()}. - * The alignment of this layout (see {@link MemoryLayout#byteAlignment()} is platform-dependent, so that the following - * invariant holds: - *
    {@code
    -    MemoryLayouts.JAVA_DOUBLE.byteAlignment() == MemoryLayouts.ADDRESS.byteSize();
    -     * }
    - */ - public static final ValueLayout JAVA_DOUBLE = MemoryLayout.valueLayout(64, ByteOrder.nativeOrder()) - .withBitAlignment(ADDRESS.bitSize()); -} diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemorySegment.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemorySegment.java index 09874cf6dd76f251f57f582a998a5f5ac70f33d2..de974fa2e8031d1551aa4e3d24c46a89159793ce 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemorySegment.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemorySegment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ package jdk.incubator.foreign; import java.io.UncheckedIOException; +import java.lang.reflect.Array; import java.nio.ByteBuffer; import jdk.internal.foreign.AbstractMemorySegmentImpl; @@ -34,11 +35,18 @@ import jdk.internal.foreign.HeapMemorySegmentImpl; import jdk.internal.foreign.MappedMemorySegmentImpl; import jdk.internal.foreign.ResourceScopeImpl; import jdk.internal.foreign.NativeMemorySegmentImpl; +import jdk.internal.foreign.Utils; +import jdk.internal.foreign.abi.SharedUtils; +import jdk.internal.misc.ScopedMemoryAccess; +import jdk.internal.misc.Unsafe; import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.Reflection; +import jdk.internal.vm.annotation.ForceInline; import java.io.IOException; +import java.nio.ByteOrder; import java.nio.channels.FileChannel; +import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.Objects; import java.util.Spliterator; @@ -48,7 +56,7 @@ import java.util.stream.Stream; * A memory segment models a contiguous region of memory. A memory segment is associated with both spatial * and temporal bounds (e.g. a {@link ResourceScope}). Spatial bounds ensure that memory access operations on a memory segment cannot affect a memory location * which falls outside the boundaries of the memory segment being accessed. Temporal bounds ensure that memory access - * operations on a segment cannot occur after the resource scope associated with a memory segment has been closed (see {@link ResourceScope#close()}). + * operations on a segment cannot occur after the resource scope associated with a memory segment has been closed (see {@link ResourceScope#close()}). *

    * All implementations of this interface must be value-based; * programmers should treat instances that are {@linkplain Object#equals(Object) equal} as interchangeable and should not @@ -86,7 +94,7 @@ import java.util.stream.Stream; * called mapped memory segments; mapped memory segments are associated with an underlying file descriptor. *

    * Contents of mapped memory segments can be {@linkplain #force() persisted} and {@linkplain #load() loaded} to and from the underlying file; - * these capabilities are suitable replacements for some of the functionality in the {@link java.nio.MappedByteBuffer} class. + * these capabilities are suitable replacements for some capabilities in the {@link java.nio.MappedByteBuffer} class. * Note that, while it is possible to map a segment into a byte buffer (see {@link MemorySegment#asByteBuffer()}), * and then call e.g. {@link java.nio.MappedByteBuffer#force()} that way, this can only be done when the source segment * is small enough, due to the size limitation inherent to the ByteBuffer API. @@ -94,7 +102,42 @@ import java.util.stream.Stream; * Clients requiring sophisticated, low-level control over mapped memory segments, should consider writing * custom mapped memory segment factories; using {@link CLinker}, e.g. on Linux, it is possible to call {@code mmap} * with the desired parameters; the returned address can be easily wrapped into a memory segment, using - * {@link MemoryAddress#ofLong(long)} and {@link MemoryAddress#asSegment(long, Runnable, ResourceScope)}. + * {@link MemoryAddress#ofLong(long)} and {@link MemorySegment#ofAddress(MemoryAddress, long, ResourceScope)}. + * + *

    Restricted native segments

    + * + * Sometimes it is necessary to turn a memory address obtained from native code into a memory segment with + * full spatial, temporal and confinement bounds. To do this, clients can {@link #ofAddress(MemoryAddress, long, ResourceScope) obtain} + * a native segment unsafely from a give memory address, by providing the segment size, as well as the segment {@linkplain ResourceScope scope}. + * This is a restricted operation and should be used with + * caution: for instance, an incorrect segment size could result in a VM crash when attempting to dereference + * the memory segment. + * + *

    Dereference

    + * + * A memory segment can be read or written using various methods provided in this class (e.g. {@link #get(ValueLayout.OfInt, long)}). + * Each dereference method takes a {@linkplain jdk.incubator.foreign.ValueLayout value layout}, which specifies the size, + * alignment constraints, byte order as well as the Java type associated with the dereference operation, and an offset. + * For instance, to read an int from a segment, using {@link ByteOrder#nativeOrder() default endianness}, the following code can be used: + * {@snippet lang=java : + * MemorySegment segment = ... + * int value = segment.get(ValueLayout.JAVA_INT, 0); + * } + * + * If the value to be read is stored in memory using {@link ByteOrder#BIG_ENDIAN big-endian} encoding, the dereference operation + * can be expressed as follows: + * {@snippet lang=java : + * MemorySegment segment = ... + * int value = segment.get(ValueLayout.JAVA_INT.withOrder(BIG_ENDIAN), 0); + * } + * + * For more complex dereference operations (e.g. structured memory access), clients can obtain a memory access var handle, + * that is, a var handle that accepts a segment and, optionally, one or more additional {@code long} coordinates. Memory + * access var handles can be obtained from {@linkplain MemoryLayout#varHandle(MemoryLayout.PathElement...) memory layouts} + * by providing a so called layout path. + * Alternatively, clients can obtain raw memory access var handles from a given + * {@linkplain MemoryHandles#varHandle(ValueLayout) value layout}, and then adapt it using the var handle combinator + * functions defined in the {@link MemoryHandles} class. * *

    Lifecycle and confinement

    * @@ -102,27 +145,27 @@ import java.util.stream.Stream; * the {@link #scope()} method. As for all resources associated with a resource scope, a segment cannot be * accessed after its corresponding scope has been closed. For instance, the following code will result in an * exception: - *
    {@code
    -MemorySegment segment = null;
    -try (ResourceScope scope = ResourceScope.newConfinedScope()) {
    -    segment = MemorySegment.allocateNative(8, 1, scope);
    -}
    -MemoryAccess.getLong(segment); // already closed!
    - * }
    + * {@snippet lang=java : + * MemorySegment segment = null; + * try (ResourceScope scope = ResourceScope.newConfinedScope()) { + * segment = MemorySegment.allocateNative(8, scope); + * } + * segment.get(ValueLayout.JAVA_LONG, 0); // already closed! + * } * Additionally, access to a memory segment is subject to the thread-confinement checks enforced by the owning scope; that is, * if the segment is associated with a shared scope, it can be accessed by multiple threads; if it is associated with a confined * scope, it can only be accessed by the thread which owns the scope. *

    * Heap and buffer segments are always associated with a global, shared scope. This scope cannot be closed, - * and can be considered as always alive. + * and segments associated with it can be considered as always alive. * *

    Memory segment views

    * * Memory segments support views. For instance, it is possible to create an immutable view of a memory segment, as follows: - *
    {@code
    -MemorySegment segment = ...
    -MemorySegment roSegment = segment.asReadOnly();
    - * }
    + * {@snippet lang=java : + * MemorySegment segment = ... + * MemorySegment roSegment = segment.asReadOnly(); + * } * It is also possible to create views whose spatial bounds are stricter than the ones of the original segment * (see {@link MemorySegment#asSlice(long, long)}). *

    @@ -141,16 +184,15 @@ MemorySegment roSegment = segment.asReadOnly(); * (to do this, the segment has to be associated with a shared scope). The following code can be used to sum all int * values in a memory segment in parallel: * - *

    {@code
    -try (ResourceScope scope = ResourceScope.newSharedScope()) {
    -    SequenceLayout SEQUENCE_LAYOUT = MemoryLayout.sequenceLayout(1024, MemoryLayouts.JAVA_INT);
    -    MemorySegment segment = MemorySegment.allocateNative(SEQUENCE_LAYOUT, scope);
    -    VarHandle VH_int = SEQUENCE_LAYOUT.elementLayout().varHandle(int.class);
    -    int sum = segment.elements(MemoryLayouts.JAVA_INT).parallel()
    -                           .mapToInt(s -> (int)VH_int.get(s.address()))
    -                           .sum();
    -}
    - * }
    + * {@snippet lang=java : + * try (ResourceScope scope = ResourceScope.newSharedScope()) { + * SequenceLayout SEQUENCE_LAYOUT = MemoryLayout.sequenceLayout(1024, ValueLayout.JAVA_INT); + * MemorySegment segment = MemorySegment.allocateNative(SEQUENCE_LAYOUT, scope); + * int sum = segment.elements(ValueLayout.JAVA_INT).parallel() + * .mapToInt(s -> s.get(ValueLayout.JAVA_INT, 0)) + * .sum(); + * } + * } * * @implSpec * Implementations of this interface are immutable, thread-safe and value-based. @@ -158,8 +200,10 @@ try (ResourceScope scope = ResourceScope.newSharedScope()) { public sealed interface MemorySegment extends Addressable permits AbstractMemorySegmentImpl { /** - * The base memory address associated with this memory segment. - * The returned memory address is associated with same resource scope as that associated with this segment. + * The base memory address associated with this native memory segment. + * @throws UnsupportedOperationException if this segment is not a {@linkplain #isNative() native} segment. + * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from + * a thread other than the thread owning that scope. * @return The base memory address. */ @Override @@ -173,11 +217,11 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * The returned spliterator splits this segment according to the specified element layout; that is, * if the supplied layout has size N, then calling {@link Spliterator#trySplit()} will result in a spliterator serving * approximately {@code S/N/2} elements (depending on whether N is even or not), where {@code S} is the size of - * this segment. As such, splitting is possible as long as {@code S/N >= 2}. The spliterator returns segments that feature the same - * scope as this given segment. + * this segment. As such, splitting is possible as long as {@code S/N >= 2}. The spliterator returns segments that + * are associated with the same scope as this segment. *

    - * The returned spliterator effectively allows to slice this segment into disjoint sub-segments, which can then - * be processed in parallel by multiple threads. + * The returned spliterator effectively allows to slice this segment into disjoint {@linkplain #asSlice(long, long) slices}, + * which can then be processed in parallel by multiple threads. * * @param elementLayout the layout to be used for splitting. * @return the element spliterator for this segment @@ -189,9 +233,9 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory /** * Returns a sequential {@code Stream} over disjoint slices (whose size matches that of the specified layout) * in this segment. Calling this method is equivalent to the following code: - *

    {@code
    -    StreamSupport.stream(segment.spliterator(elementLayout), false);
    -     * }
    + * {@snippet lang=java : + * StreamSupport.stream(segment.spliterator(elementLayout), false); + * } * * @param elementLayout the layout to be used for splitting. * @return a sequential {@code Stream} over disjoint slices in this segment. @@ -217,8 +261,6 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * and whose new size is specified by the given argument. * * @see #asSlice(long) - * @see #asSlice(MemoryAddress) - * @see #asSlice(MemoryAddress, long) * * @param offset The new segment base offset (relative to the current segment base address), specified in bytes. * @param newSize The new segment size, specified in bytes. @@ -227,39 +269,15 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory */ MemorySegment asSlice(long offset, long newSize); - /** - * Obtains a new memory segment view whose base address is the given address, and whose new size is specified by the given argument. - *

    - * Equivalent to the following code: - *

    {@code
    -    asSlice(newBase.segmentOffset(this), newSize);
    -     * }
    - * - * @see #asSlice(long) - * @see #asSlice(MemoryAddress) - * @see #asSlice(long, long) - * - * @param newBase The new segment base address. - * @param newSize The new segment size, specified in bytes. - * @return a new memory segment view with updated base/limit addresses. - * @throws IndexOutOfBoundsException if {@code offset < 0}, {@code offset > byteSize()}, {@code newSize < 0}, or {@code newSize > byteSize() - offset} - */ - default MemorySegment asSlice(MemoryAddress newBase, long newSize) { - Objects.requireNonNull(newBase); - return asSlice(newBase.segmentOffset(this), newSize); - } - /** * Obtains a new memory segment view whose base address is the same as the base address of this segment plus a given offset, * and whose new size is computed by subtracting the specified offset from this segment size. *

    * Equivalent to the following code: - *

    {@code
    -    asSlice(offset, byteSize() - offset);
    -     * }
    + * {@snippet lang=java : + * asSlice(offset, byteSize() - offset); + * } * - * @see #asSlice(MemoryAddress) - * @see #asSlice(MemoryAddress, long) * @see #asSlice(long, long) * * @param offset The new segment base offset (relative to the current segment base address), specified in bytes. @@ -270,28 +288,6 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory return asSlice(offset, byteSize() - offset); } - /** - * Obtains a new memory segment view whose base address is the given address, and whose new size is computed by subtracting - * the address offset relative to this segment (see {@link MemoryAddress#segmentOffset(MemorySegment)}) from this segment size. - *

    - * Equivalent to the following code: - *

    {@code
    -    asSlice(newBase.segmentOffset(this));
    -     * }
    - * - * @see #asSlice(long) - * @see #asSlice(MemoryAddress, long) - * @see #asSlice(long, long) - * - * @param newBase The new segment base offset (relative to the current segment base address), specified in bytes. - * @return a new memory segment view with updated base/limit addresses. - * @throws IndexOutOfBoundsException if {@code address.segmentOffset(this) < 0}, or {@code address.segmentOffset(this) > byteSize()}. - */ - default MemorySegment asSlice(MemoryAddress newBase) { - Objects.requireNonNull(newBase); - return asSlice(newBase.segmentOffset(this)); - } - /** * Is this segment read-only? * @return {@code true}, if this segment is read-only. @@ -324,19 +320,55 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory */ boolean isMapped(); + /** + * Returns a slice of this segment that is the overlap between this and + * the provided segment. + * + *

    Two segments {@code S1} and {@code S2} are said to overlap if it is possible to find + * at least two slices {@code L1} (from {@code S1}) and {@code L2} (from {@code S2}) that are backed by the + * same memory region. As such, it is not possible for a + * {@link #isNative() native} segment to overlap with a heap segment; in + * this case, or when no overlap occurs, {@code null} is returned. + * + * @param other the segment to test for an overlap with this segment. + * @return a slice of this segment, or {@code null} if no overlap occurs. + */ + MemorySegment asOverlappingSlice(MemorySegment other); + + /** + * Returns the offset, in bytes, of the provided segment, relative to this + * segment. + * + *

    The offset is relative to the base address of this segment and can be + * a negative or positive value. For instance, if both segments are native + * segments, the resulting offset can be computed as follows: + * + * {@snippet lang=java : + * other.baseAddress().toRawLongValue() - segment.baseAddress().toRawLongValue() + * } + * + * If the segments share the same base address, {@code 0} is returned. If + * {@code other} is a slice of this segment, the offset is always + * {@code 0 <= x < this.byteSize()}. + * + * @param other the segment to retrieve an offset to. + * @return the relative offset, in bytes, of the provided segment. + */ + long segmentOffset(MemorySegment other); + /** * Fills a value into this memory segment. *

    * More specifically, the given value is filled into each address of this * segment. Equivalent to (but likely more efficient than) the following code: * - *

    {@code
    -byteHandle = MemoryLayout.ofSequence(MemoryLayouts.JAVA_BYTE)
    -         .varHandle(byte.class, MemoryLayout.PathElement.sequenceElement());
    -for (long l = 0; l < segment.byteSize(); l++) {
    -     byteHandle.set(segment.address(), l, value);
    -}
    -     * }
    + * {@snippet lang=java : + * byteHandle = MemoryLayout.ofSequence(ValueLayout.JAVA_BYTE) + * .varHandle(byte.class, MemoryLayout.PathElement.sequenceElement()); + * for (long l = 0; l < segment.byteSize(); l++) { + * byteHandle.set(segment.address(), l, value); + * } + * } * * without any regard or guarantees on the ordering of particular memory * elements being set. @@ -346,7 +378,7 @@ for (long l = 0; l < segment.byteSize(); l++) { * @param value the value to fill into this segment * @return this memory segment * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from - * a thread other than the thread owning that scope, + * a thread other than the thread owning that scope. * @throws UnsupportedOperationException if this segment is read-only (see {@link #isReadOnly()}). */ MemorySegment fill(byte value); @@ -355,23 +387,23 @@ for (long l = 0; l < segment.byteSize(); l++) { * Performs a bulk copy from given source segment to this segment. More specifically, the bytes at * offset {@code 0} through {@code src.byteSize() - 1} in the source segment are copied into this segment * at offset {@code 0} through {@code src.byteSize() - 1}. - * If the source segment overlaps with this segment, then the copying is performed as if the bytes at - * offset {@code 0} through {@code src.byteSize() - 1} in the source segment were first copied into a - * temporary segment with size {@code bytes}, and then the contents of the temporary segment were copied into - * this segment at offset {@code 0} through {@code src.byteSize() - 1}. *

    - * The result of a bulk copy is unspecified if, in the uncommon case, the source segment and this segment - * do not overlap, but refer to overlapping regions of the same backing storage using different addresses. - * For example, this may occur if the same file is {@linkplain MemorySegment#mapFile mapped} to two segments. - * + * Calling this method is equivalent to the following code: + * {@snippet lang=java : + * MemorySegment.copy(src, 0, this, 0, src.byteSize); + * } * @param src the source segment. * @throws IndexOutOfBoundsException if {@code src.byteSize() > this.byteSize()}. * @throws IllegalStateException if either the scope associated with the source segment or the scope associated * with this segment have been already closed, or if access occurs from a thread other than the thread owning either * scopes. * @throws UnsupportedOperationException if this segment is read-only (see {@link #isReadOnly()}). + * @return this segment. */ - void copyFrom(MemorySegment src); + default MemorySegment copyFrom(MemorySegment src) { + MemorySegment.copy(src, 0, this, 0, src.byteSize()); + return this; + } /** * Finds and returns the offset, in bytes, of the first mismatch between @@ -381,10 +413,10 @@ for (long l = 0; l < segment.byteSize(); l++) { * the smaller memory segment (exclusive). *

    * If the two segments share a common prefix then the returned offset is - * the length of the common prefix and it follows that there is a mismatch + * the length of the common prefix, and it follows that there is a mismatch * between the two segments at that offset within the respective segments. - * If one segment is a proper prefix of the other then the returned offset is - * the smaller of the segment sizes, and it follows that the offset is only + * If one segment is a proper prefix of the other, then the returned offset is + * the smallest of the segment sizes, and it follows that the offset is only * valid for the larger segment. Otherwise, there is no mismatch and {@code * -1} is returned. * @@ -398,11 +430,11 @@ for (long l = 0; l < segment.byteSize(); l++) { long mismatch(MemorySegment other); /** - * Tells whether or not the contents of this mapped segment is resident in physical + * Tells whether the contents of this mapped segment is resident in physical * memory. * *

    A return value of {@code true} implies that it is highly likely - * that all of the data in this segment is resident in physical memory and + * that all the data in this segment is resident in physical memory and * may therefore be accessed without incurring any virtual-memory page * faults or I/O operations. A return value of {@code false} does not * necessarily imply that this segment's content is not resident in physical @@ -481,19 +513,19 @@ for (long l = 0; l < segment.byteSize(); l++) { void force(); /** - * Wraps this segment in a {@link ByteBuffer}. Some of the properties of the returned buffer are linked to + * Wraps this segment in a {@link ByteBuffer}. Some properties of the returned buffer are linked to * the properties of this segment. For instance, if this segment is immutable * (e.g. the segment is a read-only segment, see {@link #isReadOnly()}), then the resulting buffer is read-only - * (see {@link ByteBuffer#isReadOnly()}. Additionally, if this is a native memory segment, the resulting buffer is + * (see {@link ByteBuffer#isReadOnly()}). Additionally, if this is a native memory segment, the resulting buffer is * direct (see {@link ByteBuffer#isDirect()}). *

    - * The returned buffer's position (see {@link ByteBuffer#position()} is initially set to zero, while + * The returned buffer's position (see {@link ByteBuffer#position()}) is initially set to zero, while * the returned buffer's capacity and limit (see {@link ByteBuffer#capacity()} and {@link ByteBuffer#limit()}, respectively) * are set to this segment' size (see {@link MemorySegment#byteSize()}). For this reason, a byte buffer cannot be * returned if this segment' size is greater than {@link Integer#MAX_VALUE}. *

    * The life-cycle of the returned buffer will be tied to that of this segment. That is, accessing the returned buffer - * after the scope associated with this segment has been closed (see {@link ResourceScope#close()}, will throw an {@link IllegalStateException}. + * after the scope associated with this segment has been closed (see {@link ResourceScope#close()}), will throw an {@link IllegalStateException}. *

    * If this segment is associated with a confined scope, calling read/write I/O operations on the resulting buffer * might result in an unspecified exception being thrown. Examples of such problematic operations are @@ -505,83 +537,136 @@ for (long l = 0; l < segment.byteSize(); l++) { * * @return a {@link ByteBuffer} view of this memory segment. * @throws UnsupportedOperationException if this segment cannot be mapped onto a {@link ByteBuffer} instance, - * e.g. because it models an heap-based segment that is not based on a {@code byte[]}), or if its size is greater + * e.g. because it models a heap-based segment that is not based on a {@code byte[]}), or if its size is greater * than {@link Integer#MAX_VALUE}. */ ByteBuffer asByteBuffer(); /** * Copy the contents of this memory segment into a fresh byte array. + * @param elementLayout the source element layout. If the byte order associated with the layout is + * different from the native order, a byte swap operation will be performed on each array element. * @return a fresh byte array copy of this memory segment. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope, or if this segment's contents cannot be copied into a {@link byte[]} instance, * e.g. its size is greater than {@link Integer#MAX_VALUE}. */ - byte[] toByteArray(); + byte[] toArray(ValueLayout.OfByte elementLayout); /** * Copy the contents of this memory segment into a fresh short array. + * @param elementLayout the source element layout. If the byte order associated with the layout is + * different from the native order, a byte swap operation will be performed on each array element. * @return a fresh short array copy of this memory segment. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope, or if this segment's contents cannot be copied into a {@link short[]} instance, * e.g. because {@code byteSize() % 2 != 0}, or {@code byteSize() / 2 > Integer#MAX_VALUE} */ - short[] toShortArray(); + short[] toArray(ValueLayout.OfShort elementLayout); /** * Copy the contents of this memory segment into a fresh char array. + * @param elementLayout the source element layout. If the byte order associated with the layout is + * different from the native order, a byte swap operation will be performed on each array element. * @return a fresh char array copy of this memory segment. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope, or if this segment's contents cannot be copied into a {@link char[]} instance, * e.g. because {@code byteSize() % 2 != 0}, or {@code byteSize() / 2 > Integer#MAX_VALUE}. */ - char[] toCharArray(); + char[] toArray(ValueLayout.OfChar elementLayout); /** * Copy the contents of this memory segment into a fresh int array. + * @param elementLayout the source element layout. If the byte order associated with the layout is + * different from the native order, a byte swap operation will be performed on each array element. * @return a fresh int array copy of this memory segment. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope, or if this segment's contents cannot be copied into a {@link int[]} instance, * e.g. because {@code byteSize() % 4 != 0}, or {@code byteSize() / 4 > Integer#MAX_VALUE}. */ - int[] toIntArray(); + int[] toArray(ValueLayout.OfInt elementLayout); /** * Copy the contents of this memory segment into a fresh float array. + * @param elementLayout the source element layout. If the byte order associated with the layout is + * different from the native order, a byte swap operation will be performed on each array element. * @return a fresh float array copy of this memory segment. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope, or if this segment's contents cannot be copied into a {@link float[]} instance, * e.g. because {@code byteSize() % 4 != 0}, or {@code byteSize() / 4 > Integer#MAX_VALUE}. */ - float[] toFloatArray(); + float[] toArray(ValueLayout.OfFloat elementLayout); /** * Copy the contents of this memory segment into a fresh long array. + * @param elementLayout the source element layout. If the byte order associated with the layout is + * different from the native order, a byte swap operation will be performed on each array element. * @return a fresh long array copy of this memory segment. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope, or if this segment's contents cannot be copied into a {@link long[]} instance, * e.g. because {@code byteSize() % 8 != 0}, or {@code byteSize() / 8 > Integer#MAX_VALUE}. */ - long[] toLongArray(); + long[] toArray(ValueLayout.OfLong elementLayout); /** * Copy the contents of this memory segment into a fresh double array. + * @param elementLayout the source element layout. If the byte order associated with the layout is + * different from the native order, a byte swap operation will be performed on each array element. * @return a fresh double array copy of this memory segment. * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from * a thread other than the thread owning that scope, or if this segment's contents cannot be copied into a {@link double[]} instance, * e.g. because {@code byteSize() % 8 != 0}, or {@code byteSize() / 8 > Integer#MAX_VALUE}. */ - double[] toDoubleArray(); + double[] toArray(ValueLayout.OfDouble elementLayout); /** - * Creates a new confined buffer memory segment that models the memory associated with the given byte + * Reads a UTF-8 encoded, null-terminated string from this segment at given offset. + *

    + * This method always replaces malformed-input and unmappable-character + * sequences with this charset's default replacement string. The {@link + * java.nio.charset.CharsetDecoder} class should be used when more control + * over the decoding process is required. + * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, + * the final address of this read operation can be expressed as {@code address().toRowLongValue() + offset}. + * @return a Java string constructed from the bytes read from the given starting address up to (but not including) + * the first {@code '\0'} terminator character (assuming one is found). + * @throws IllegalArgumentException if the size of the native string is greater than the largest string supported by the platform. + * @throws IllegalStateException if the size of the native string is greater than the size of this segment, + * or if the scope associated with this segment has been closed, or if access occurs from a thread other than the thread owning that scope. + */ + default String getUtf8String(long offset) { + return SharedUtils.toJavaStringInternal(this, offset); + } + + /** + * Writes the given string into this segment at given offset, converting it to a null-terminated byte sequence using UTF-8 encoding. + *

    + * This method always replaces malformed-input and unmappable-character + * sequences with this charset's default replacement string. The {@link + * java.nio.charset.CharsetDecoder} class should be used when more control + * over the decoding process is required. + * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, + * the final address of this write operation can be expressed as {@code address().toRowLongValue() + offset}. + * @param str the Java string to be written into this segment. + * @throws IllegalArgumentException if the size of the native string is greater than the largest string supported by the platform. + * @throws IllegalStateException if the size of the native string is greater than the size of this segment, + * or if the scope associated with this segment has been closed, or if access occurs from a thread other than the thread owning that scope. + * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. + */ + default void setUtf8String(long offset, String str) { + Utils.toCString(str.getBytes(StandardCharsets.UTF_8), SegmentAllocator.prefixAllocator(asSlice(offset))); + } + + + /** + * Creates a new buffer memory segment that models the memory associated with the given byte * buffer. The segment starts relative to the buffer's position (inclusive) * and ends relative to the buffer's limit (exclusive). *

    * If the buffer is {@link ByteBuffer#isReadOnly() read-only}, the resulting segment will also be * {@link ByteBuffer#isReadOnly() read-only}. The scope associated with this segment can either be the * {@linkplain ResourceScope#globalScope() global} resource scope, in case the buffer has been created independently, - * or to some other (possibly closeable) resource scope, in case the buffer has been obtained using {@link #asByteBuffer()}. + * or some other resource scope, in case the buffer has been obtained using {@link #asByteBuffer()}. *

    * The resulting memory segment keeps a reference to the backing buffer, keeping it reachable. * @@ -593,8 +678,8 @@ for (long l = 0; l < segment.byteSize(); l++) { } /** - * Creates a new confined array memory segment that models the memory associated with a given heap-allocated byte array. - * The returned segment's resource scope is set to the {@linkplain ResourceScope#globalScope() global} resource scope. + * Creates a new array memory segment that models the memory associated with a given heap-allocated byte array. + * The returned segment is associated with the {@linkplain ResourceScope#globalScope() global} resource scope. * * @param arr the primitive array backing the array memory segment. * @return a new array memory segment. @@ -604,8 +689,8 @@ for (long l = 0; l < segment.byteSize(); l++) { } /** - * Creates a new confined array memory segment that models the memory associated with a given heap-allocated char array. - * The returned segment's resource scope is set to the {@linkplain ResourceScope#globalScope() global} resource scope. + * Creates a new array memory segment that models the memory associated with a given heap-allocated char array. + * The returned segment is associated with the {@linkplain ResourceScope#globalScope() global} resource scope. * * @param arr the primitive array backing the array memory segment. * @return a new array memory segment. @@ -615,8 +700,8 @@ for (long l = 0; l < segment.byteSize(); l++) { } /** - * Creates a new confined array memory segment that models the memory associated with a given heap-allocated short array. - * The returned segment's resource scope is set to the {@linkplain ResourceScope#globalScope() global} resource scope. + * Creates a new array memory segment that models the memory associated with a given heap-allocated short array. + * The returned segment is associated with the {@linkplain ResourceScope#globalScope() global} resource scope. * * @param arr the primitive array backing the array memory segment. * @return a new array memory segment. @@ -626,8 +711,8 @@ for (long l = 0; l < segment.byteSize(); l++) { } /** - * Creates a new confined array memory segment that models the memory associated with a given heap-allocated int array. - * The returned segment's resource scope is set to the {@linkplain ResourceScope#globalScope() global} resource scope. + * Creates a new array memory segment that models the memory associated with a given heap-allocated int array. + * The returned segment is associated with the {@linkplain ResourceScope#globalScope() global} resource scope. * * @param arr the primitive array backing the array memory segment. * @return a new array memory segment. @@ -637,8 +722,8 @@ for (long l = 0; l < segment.byteSize(); l++) { } /** - * Creates a new confined array memory segment that models the memory associated with a given heap-allocated float array. - * The returned segment's resource scope is set to the {@linkplain ResourceScope#globalScope() global} resource scope. + * Creates a new array memory segment that models the memory associated with a given heap-allocated float array. + * The returned segment is associated with the {@linkplain ResourceScope#globalScope() global} resource scope. * * @param arr the primitive array backing the array memory segment. * @return a new array memory segment. @@ -648,8 +733,8 @@ for (long l = 0; l < segment.byteSize(); l++) { } /** - * Creates a new confined array memory segment that models the memory associated with a given heap-allocated long array. - * The returned segment's resource scope is set to the {@linkplain ResourceScope#globalScope() global} resource scope. + * Creates a new array memory segment that models the memory associated with a given heap-allocated long array. + * The returned segment is associated with the {@linkplain ResourceScope#globalScope() global} resource scope. * * @param arr the primitive array backing the array memory segment. * @return a new array memory segment. @@ -659,8 +744,8 @@ for (long l = 0; l < segment.byteSize(); l++) { } /** - * Creates a new confined array memory segment that models the memory associated with a given heap-allocated double array. - * The returned segment's resource scope is set to the {@linkplain ResourceScope#globalScope() global} resource scope. + * Creates a new array memory segment that models the memory associated with a given heap-allocated double array. + * The returned segment is associated with the {@linkplain ResourceScope#globalScope() global} resource scope. * * @param arr the primitive array backing the array memory segment. * @return a new array memory segment. @@ -669,15 +754,56 @@ for (long l = 0; l < segment.byteSize(); l++) { return HeapMemorySegmentImpl.OfDouble.fromArray(arr); } + /** - * Creates a new confined native memory segment that models a newly allocated block of off-heap memory with given layout + * Creates a new native memory segment with given size and resource scope, and whose base address is the given address. + * This method can be useful when interacting with custom + * native memory sources (e.g. custom allocators), where an address to some + * underlying memory region is typically obtained from native code (often as a plain {@code long} value). + * The returned segment is not read-only (see {@link MemorySegment#isReadOnly()}), and is associated with the + * provided resource scope. + *

    + * Clients should ensure that the address and bounds refer to a valid region of memory that is accessible for reading and, + * if appropriate, writing; an attempt to access an invalid memory location from Java code will either return an arbitrary value, + * have no visible effect, or cause an unspecified exception to be thrown. + *

    + * This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * restricted methods, and use safe and supported functionalities, where possible. + * + * + * @param address the returned segment's base address. + * @param bytesSize the desired size. + * @param scope the native segment scope. + * @return a new native memory segment with given base address, size and scope. + * @throws IllegalArgumentException if {@code bytesSize <= 0}. + * @throws IllegalStateException if the provided scope has been already closed, + * or if access occurs from a thread other than the thread owning the scope. + * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option + * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or + * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + */ + @CallerSensitive + static MemorySegment ofAddress(MemoryAddress address, long bytesSize, ResourceScope scope) { + Reflection.ensureNativeAccess(Reflection.getCallerClass()); + Objects.requireNonNull(address); + Objects.requireNonNull(scope); + if (bytesSize <= 0) { + throw new IllegalArgumentException("Invalid size : " + bytesSize); + } + return NativeMemorySegmentImpl.makeNativeSegmentUnchecked(address, bytesSize, (ResourceScopeImpl)scope); + } + + /** + * Creates a new native memory segment that models a newly allocated block of off-heap memory with given layout * and resource scope. A client is responsible make sure that the resource scope associated with the returned segment is closed * when the segment is no longer in use. Failure to do so will result in off-heap memory leaks. *

    * This is equivalent to the following code: - *

    {@code
    -    allocateNative(layout.bytesSize(), layout.bytesAlignment(), scope);
    -     * }
    + * {@snippet lang=java : + * allocateNative(layout.bytesSize(), layout.bytesAlignment(), scope); + * } *

    * The block of off-heap memory associated with the returned native memory segment is initialized to zero. * @@ -695,14 +821,14 @@ for (long l = 0; l < segment.byteSize(); l++) { } /** - * Creates a new confined native memory segment that models a newly allocated block of off-heap memory with given size (in bytes) + * Creates a new native memory segment that models a newly allocated block of off-heap memory with given size (in bytes) * and resource scope. A client is responsible make sure that the resource scope associated with the returned segment is closed * when the segment is no longer in use. Failure to do so will result in off-heap memory leaks. *

    * This is equivalent to the following code: - *

    {@code
    -    allocateNative(bytesSize, 1, scope);
    -     * }
    + * {@snippet lang=java : + * allocateNative(bytesSize, 1, scope); + * } *

    * The block of off-heap memory associated with the returned native memory segment is initialized to zero. * @@ -718,7 +844,7 @@ for (long l = 0; l < segment.byteSize(); l++) { } /** - * Creates a new confined native memory segment that models a newly allocated block of off-heap memory with given size + * Creates a new native memory segment that models a newly allocated block of off-heap memory with given size * (in bytes), alignment constraint (in bytes) and resource scope. A client is responsible make sure that the resource * scope associated with the returned segment is closed when the segment is no longer in use. * Failure to do so will result in off-heap memory leaks. @@ -756,7 +882,7 @@ for (long l = 0; l < segment.byteSize(); l++) { *

    * The content of a mapped memory segment can change at any time, for example * if the content of the corresponding region of the mapped file is changed by - * this (or another) program. Whether or not such changes occur, and when they + * this (or another) program. Whether such changes occur, and when they * occur, is operating-system dependent and therefore unspecified. *

    * All or part of a mapped memory segment may become @@ -774,17 +900,17 @@ for (long l = 0; l < segment.byteSize(); l++) { * @param path the path to the file to memory map. * @param bytesOffset the offset (expressed in bytes) within the file at which the mapped segment is to start. * @param bytesSize the size (in bytes) of the mapped memory backing the memory segment. - * @param mapMode a file mapping mode, see {@link FileChannel#map(FileChannel.MapMode, long, long)}; the chosen mapping mode + * @param mapMode a file mapping mode, see {@link FileChannel#map(FileChannel.MapMode, long, long)}; the mapping mode * might affect the behavior of the returned memory mapped segment (see {@link #force()}). * @param scope the segment scope. - * @return a new confined mapped memory segment. + * @return a new mapped memory segment. * @throws IllegalArgumentException if {@code bytesOffset < 0}, {@code bytesSize < 0}, or if {@code path} is not associated * with the default file system. * @throws IllegalStateException if {@code scope} has been already closed, or if access occurs from a thread other * than the thread owning {@code scope}. * @throws UnsupportedOperationException if an unsupported map mode is specified. * @throws IOException if the specified path does not point to an existing file, or if some other I/O error occurs. - * @throws SecurityException If a security manager is installed and it denies an unspecified permission required by the implementation. + * @throws SecurityException If a security manager is installed, and it denies an unspecified permission required by the implementation. * In the case of the default provider, the {@link SecurityManager#checkRead(String)} method is invoked to check * read access if the file is opened for reading. The {@link SecurityManager#checkWrite(String)} method is invoked to check * write access if the file is opened for writing. @@ -795,27 +921,770 @@ for (long l = 0; l < segment.byteSize(); l++) { } /** - * Returns a native memory segment whose base address is {@link MemoryAddress#NULL} and whose size is {@link Long#MAX_VALUE}. - * This method can be very useful when dereferencing memory addresses obtained when interacting with native libraries. - * The returned segment is associated with the global resource scope (see {@link ResourceScope#globalScope()}). - * Equivalent to (but likely more efficient than) the following code: - *

    {@code
    -    MemoryAddress.NULL.asSegment(Long.MAX_VALUE)
    -     * }
    + * Performs a bulk copy from source segment to destination segment. More specifically, the bytes at offset + * {@code srcOffset} through {@code srcOffset + bytes - 1} in the source segment are copied into the destination + * segment at offset {@code dstOffset} through {@code dstOffset + bytes - 1}. *

    - * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. + * If the source segment overlaps with this segment, then the copying is performed as if the bytes at + * offset {@code srcOffset} through {@code srcOffset + bytes - 1} in the source segment were first copied into a + * temporary segment with size {@code bytes}, and then the contents of the temporary segment were copied into + * the destination segment at offset {@code dstOffset} through {@code dstOffset + bytes - 1}. + *

    + * The result of a bulk copy is unspecified if, in the uncommon case, the source segment and the destination segment + * do not overlap, but refer to overlapping regions of the same backing storage using different addresses. + * For example, this may occur if the same file is {@linkplain MemorySegment#mapFile mapped} to two segments. + *

    + * Calling this method is equivalent to the following code: + * {@snippet lang=java : + * MemorySegment.copy(srcSegment, ValueLayout.JAVA_BYTE, srcOffset, dstSegment, ValueLayout.JAVA_BYTE, dstOffset, bytes); + * } + * @param srcSegment the source segment. + * @param srcOffset the starting offset, in bytes, of the source segment. + * @param dstSegment the destination segment. + * @param dstOffset the starting offset, in bytes, of the destination segment. + * @param bytes the number of bytes to be copied. + * @throws IllegalStateException if either the scope associated with the source segment or the scope associated + * with the destination segment have been already closed, or if access occurs from a thread other than the thread + * owning either scopes. + * @throws IndexOutOfBoundsException if {@code srcOffset + bytes > srcSegment.byteSize()} or if + * {@code dstOffset + bytes > dstSegment.byteSize()}, or if either {@code srcOffset}, {@code dstOffset} + * or {@code bytes} are {@code < 0}. + * @throws UnsupportedOperationException if the destination segment is read-only (see {@link #isReadOnly()}). + */ + @ForceInline + static void copy(MemorySegment srcSegment, long srcOffset, MemorySegment dstSegment, long dstOffset, long bytes) { + copy(srcSegment, ValueLayout.JAVA_BYTE, srcOffset, dstSegment, ValueLayout.JAVA_BYTE, dstOffset, bytes); + } + + /** + * Performs a bulk copy from source segment to destination segment. More specifically, if {@code S} is the byte size + * of the element layouts, the bytes at offset {@code srcOffset} through {@code srcOffset + (elementCount * S) - 1} + * in the source segment are copied into the destination segment at offset {@code dstOffset} through {@code dstOffset + (elementCount * S) - 1}. + *

    + * The copy occurs in an element-wise fashion: the bytes in the source segment are interpreted as a sequence of elements + * whose layout is {@code srcElementLayout}, whereas the bytes in the destination segment are interpreted as a sequence of + * elements whose layout is {@code dstElementLayout}. Both element layouts must have same size {@code S}. + * If the byte order of the two element layouts differ, the bytes corresponding to each element to be copied + * are swapped accordingly during the copy operation. + *

    + * If the source segment overlaps with this segment, then the copying is performed as if the bytes at + * offset {@code srcOffset} through {@code srcOffset + (elementCount * S) - 1} in the source segment were first copied into a + * temporary segment with size {@code bytes}, and then the contents of the temporary segment were copied into + * the destination segment at offset {@code dstOffset} through {@code dstOffset + (elementCount * S) - 1}. + *

    + * The result of a bulk copy is unspecified if, in the uncommon case, the source segment and the destination segment + * do not overlap, but refer to overlapping regions of the same backing storage using different addresses. + * For example, this may occur if the same file is {@linkplain MemorySegment#mapFile mapped} to two segments. + * @param srcSegment the source segment. + * @param srcElementLayout the element layout associated with the source segment. + * @param srcOffset the starting offset, in bytes, of the source segment. + * @param dstSegment the destination segment. + * @param dstElementLayout the element layout associated with the destination segment. + * @param dstOffset the starting offset, in bytes, of the destination segment. + * @param elementCount the number of elements to be copied. + * @throws IllegalArgumentException if the element layouts have different sizes, if the source offset is incompatible + * with the alignment constraints in the source element layout, or if the destination offset is incompatible with the + * alignment constraints in the destination element layout. + * @throws IllegalStateException if either the scope associated with the source segment or the scope associated + * with the destination segment have been already closed, or if access occurs from a thread other than the thread + * owning either scopes. + * @throws IndexOutOfBoundsException if {@code srcOffset + (elementCount * S) > srcSegment.byteSize()} or if + * {@code dstOffset + (elementCount * S) > dstSegment.byteSize()}, where {@code S} is the byte size + * of the element layouts, or if either {@code srcOffset}, {@code dstOffset} or {@code elementCount} are {@code < 0}. + * @throws UnsupportedOperationException if the destination segment is read-only (see {@link #isReadOnly()}). + */ + @ForceInline + static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long srcOffset, MemorySegment dstSegment, + ValueLayout dstElementLayout, long dstOffset, long elementCount) { + Objects.requireNonNull(srcSegment); + Objects.requireNonNull(srcElementLayout); + Objects.requireNonNull(dstSegment); + Objects.requireNonNull(dstElementLayout); + AbstractMemorySegmentImpl srcImpl = (AbstractMemorySegmentImpl)srcSegment; + AbstractMemorySegmentImpl dstImpl = (AbstractMemorySegmentImpl)dstSegment; + if (srcElementLayout.byteSize() != dstElementLayout.byteSize()) { + throw new IllegalArgumentException("Source and destination layouts must have same sizes"); + } + if (srcOffset % srcElementLayout.byteAlignment() != 0) { + throw new IllegalArgumentException("Source segment incompatible with alignment constraints"); + } + if (dstOffset % dstElementLayout.byteAlignment() != 0) { + throw new IllegalArgumentException("Target segment incompatible with alignment constraints"); + } + long size = elementCount * srcElementLayout.byteSize(); + srcImpl.checkAccess(srcOffset, size, true); + dstImpl.checkAccess(dstOffset, size, false); + if (srcElementLayout.byteSize() == 1 || srcElementLayout.order() == dstElementLayout.order()) { + ScopedMemoryAccess.getScopedMemoryAccess().copyMemory(srcImpl.scope(), dstImpl.scope(), + srcImpl.unsafeGetBase(), srcImpl.unsafeGetOffset() + srcOffset, + dstImpl.unsafeGetBase(), dstImpl.unsafeGetOffset() + dstOffset, size); + } else { + ScopedMemoryAccess.getScopedMemoryAccess().copySwapMemory(srcImpl.scope(), dstImpl.scope(), + srcImpl.unsafeGetBase(), srcImpl.unsafeGetOffset() + srcOffset, + dstImpl.unsafeGetBase(), dstImpl.unsafeGetOffset() + dstOffset, size, srcElementLayout.byteSize()); + } + } + + /** + * Reads a byte from this segment and offset with given layout. * - * @return a memory segment whose base address is {@link MemoryAddress#NULL} and whose size is {@link Long#MAX_VALUE}. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + * @param layout the layout of the memory region to be read. + * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, + * the final address of this read operation can be expressed as {@code address().toRowLongValue() + offset}. + * @return a byte value read from this address. + * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from + * a thread other than the thread owning that scope. + * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * memory segment. */ - @CallerSensitive - static MemorySegment globalNativeSegment() { - Reflection.ensureNativeAccess(Reflection.getCallerClass()); - return NativeMemorySegmentImpl.EVERYTHING; + @ForceInline + default byte get(ValueLayout.OfByte layout, long offset) { + return (byte)layout.accessHandle().get(this, offset); + } + + /** + * Writes a byte to this segment and offset with given layout. + * + * @param layout the layout of the memory region to be written. + * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, + * the final address of this write operation can be expressed as {@code address().toRowLongValue() + offset}. + * @param value the byte value to be written. + * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from + * a thread other than the thread owning that scope. + * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * memory segment. + * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. + */ + @ForceInline + default void set(ValueLayout.OfByte layout, long offset, byte value) { + layout.accessHandle().set(this, offset, value); + } + + /** + * Reads a boolean from this segment and offset with given layout. + * + * @param layout the layout of the memory region to be read. + * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, + * the final address of this read operation can be expressed as {@code address().toRowLongValue() + offset}. + * @return a boolean value read from this address. + * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from + * a thread other than the thread owning that scope. + * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * memory segment. + */ + @ForceInline + default boolean get(ValueLayout.OfBoolean layout, long offset) { + return (boolean)layout.accessHandle().get(this, offset); + } + + /** + * Writes a boolean to this segment and offset with given layout. + * + * @param layout the layout of the memory region to be written. + * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, + * the final address of this write operation can be expressed as {@code address().toRowLongValue() + offset}. + * @param value the boolean value to be written. + * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from + * a thread other than the thread owning that scope. + * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * memory segment. + * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. + */ + @ForceInline + default void set(ValueLayout.OfBoolean layout, long offset, boolean value) { + layout.accessHandle().set(this, offset, value); + } + + /** + * Reads a char from this segment and offset with given layout. + * + * @param layout the layout of the memory region to be read. + * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, + * the final address of this read operation can be expressed as {@code address().toRowLongValue() + offset}. + * @return a char value read from this address. + * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from + * a thread other than the thread owning that scope. + * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * memory segment. + */ + @ForceInline + default char get(ValueLayout.OfChar layout, long offset) { + return (char)layout.accessHandle().get(this, offset); + } + + /** + * Writes a char to this segment and offset with given layout. + * + * @param layout the layout of the memory region to be written. + * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, + * the final address of this write operation can be expressed as {@code address().toRowLongValue() + offset}. + * @param value the char value to be written. + * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from + * a thread other than the thread owning that scope. + * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * memory segment. + * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. + */ + @ForceInline + default void set(ValueLayout.OfChar layout, long offset, char value) { + layout.accessHandle().set(this, offset, value); + } + + /** + * Reads a short from this segment and offset with given layout. + * + * @param layout the layout of the memory region to be read. + * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, + * the final address of this read operation can be expressed as {@code address().toRowLongValue() + offset}. + * @return a short value read from this address. + * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from + * a thread other than the thread owning that scope. + * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * memory segment. + */ + @ForceInline + default short get(ValueLayout.OfShort layout, long offset) { + return (short)layout.accessHandle().get(this, offset); + } + + /** + * Writes a short to this segment and offset with given layout. + * + * @param layout the layout of the memory region to be written. + * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, + * the final address of this write operation can be expressed as {@code address().toRowLongValue() + offset}. + * @param value the short value to be written. + * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from + * a thread other than the thread owning that scope. + * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * memory segment. + * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. + */ + @ForceInline + default void set(ValueLayout.OfShort layout, long offset, short value) { + layout.accessHandle().set(this, offset, value); + } + + /** + * Reads an int from this segment and offset with given layout. + * + * @param layout the layout of the memory region to be read. + * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, + * the final address of this read operation can be expressed as {@code address().toRowLongValue() + offset}. + * @return an int value read from this address. + * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from + * a thread other than the thread owning that scope. + * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * memory segment. + */ + @ForceInline + default int get(ValueLayout.OfInt layout, long offset) { + return (int)layout.accessHandle().get(this, offset); + } + + /** + * Writes an int to this segment and offset with given layout. + * + * @param layout the layout of the memory region to be written. + * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, + * the final address of this write operation can be expressed as {@code address().toRowLongValue() + offset}. + * @param value the int value to be written. + * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from + * a thread other than the thread owning that scope. + * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * memory segment. + * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. + */ + @ForceInline + default void set(ValueLayout.OfInt layout, long offset, int value) { + layout.accessHandle().set(this, offset, value); + } + + /** + * Reads a float from this segment and offset with given layout. + * + * @param layout the layout of the memory region to be read. + * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, + * the final address of this read operation can be expressed as {@code address().toRowLongValue() + offset}. + * @return a float value read from this address. + * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from + * a thread other than the thread owning that scope. + * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * memory segment. + */ + @ForceInline + default float get(ValueLayout.OfFloat layout, long offset) { + return (float)layout.accessHandle().get(this, offset); + } + + /** + * Writes a float to this segment and offset with given layout. + * + * @param layout the layout of the memory region to be written. + * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, + * the final address of this write operation can be expressed as {@code address().toRowLongValue() + offset}. + * @param value the float value to be written. + * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from + * a thread other than the thread owning that scope. + * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * memory segment. + * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. + */ + @ForceInline + default void set(ValueLayout.OfFloat layout, long offset, float value) { + layout.accessHandle().set(this, offset, value); + } + + /** + * Reads a long from this segment and offset with given layout. + * + * @param layout the layout of the memory region to be read. + * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, + * the final address of this read operation can be expressed as {@code address().toRowLongValue() + offset}. + * @return a long value read from this address. + * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from + * a thread other than the thread owning that scope. + * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * memory segment. + */ + @ForceInline + default long get(ValueLayout.OfLong layout, long offset) { + return (long)layout.accessHandle().get(this, offset); + } + + /** + * Writes a long to this segment and offset with given layout. + * + * @param layout the layout of the memory region to be written. + * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, + * the final address of this write operation can be expressed as {@code address().toRowLongValue() + offset}. + * @param value the long value to be written. + * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from + * a thread other than the thread owning that scope. + * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * memory segment. + * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. + */ + @ForceInline + default void set(ValueLayout.OfLong layout, long offset, long value) { + layout.accessHandle().set(this, offset, value); + } + + /** + * Reads a double from this segment and offset with given layout. + * + * @param layout the layout of the memory region to be read. + * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, + * the final address of this read operation can be expressed as {@code address().toRowLongValue() + offset}. + * @return a double value read from this address. + * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from + * a thread other than the thread owning that scope. + * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * memory segment. + */ + @ForceInline + default double get(ValueLayout.OfDouble layout, long offset) { + return (double)layout.accessHandle().get(this, offset); + } + + /** + * Writes a double to this segment and offset with given layout. + * + * @param layout the layout of the memory region to be written. + * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, + * the final address of this write operation can be expressed as {@code address().toRowLongValue() + offset}. + * @param value the double value to be written. + * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from + * a thread other than the thread owning that scope. + * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * memory segment. + * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. + */ + @ForceInline + default void set(ValueLayout.OfDouble layout, long offset, double value) { + layout.accessHandle().set(this, offset, value); + } + + /** + * Reads an address from this segment and offset with given layout. + * + * @param layout the layout of the memory region to be read. + * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, + * the final address of this read operation can be expressed as {@code address().toRowLongValue() + offset}. + * @return an address value read from this address. + * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from + * a thread other than the thread owning that scope. + * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * memory segment. + */ + @ForceInline + default MemoryAddress get(ValueLayout.OfAddress layout, long offset) { + return (MemoryAddress)layout.accessHandle().get(this, offset); + } + + /** + * Writes an address to this segment and offset with given layout. + * + * @param layout the layout of the memory region to be written. + * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, + * the final address of this write operation can be expressed as {@code address().toRowLongValue() + offset}. + * @param value the address value to be written. + * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from + * a thread other than the thread owning that scope. + * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * memory segment. + * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. + */ + @ForceInline + default void set(ValueLayout.OfAddress layout, long offset, Addressable value) { + layout.accessHandle().set(this, offset, value.address()); + } + + /** + * Reads a char from this segment and index, scaled by given layout size. + * + * @param layout the layout of the memory region to be read. + * @param index index (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, + * the final address of this read operation can be expressed as {@code address().toRowLongValue() + (index * layout.byteSize())}. + * @return a char value read from this address. + * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from + * a thread other than the thread owning that scope. + * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * memory segment. + */ + @ForceInline + default char getAtIndex(ValueLayout.OfChar layout, long index) { + return (char)layout.accessHandle().get(this, Utils.scaleOffset(this, index, layout.byteSize())); + } + + /** + * Writes a char to this segment and index, scaled by given layout size. + * + * @param layout the layout of the memory region to be written. + * @param index index (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, + * the final address of this write operation can be expressed as {@code address().toRowLongValue() + (index * layout.byteSize())}. + * @param value the char value to be written. + * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from + * a thread other than the thread owning that scope. + * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * memory segment. + * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. + */ + @ForceInline + default void setAtIndex(ValueLayout.OfChar layout, long index, char value) { + layout.accessHandle().set(this, Utils.scaleOffset(this, index, layout.byteSize()), value); + } + + /** + * Reads a short from this segment and index, scaled by given layout size. + * + * @param layout the layout of the memory region to be read. + * @param index index (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, + * the final address of this read operation can be expressed as {@code address().toRowLongValue() + (index * layout.byteSize())}. + * @return a short value read from this address. + * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from + * a thread other than the thread owning that scope. + * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * memory segment. + */ + @ForceInline + default short getAtIndex(ValueLayout.OfShort layout, long index) { + return (short)layout.accessHandle().get(this, Utils.scaleOffset(this, index, layout.byteSize())); + } + + /** + * Writes a short to this segment and index, scaled by given layout size. + * + * @param layout the layout of the memory region to be written. + * @param index index (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, + * the final address of this write operation can be expressed as {@code address().toRowLongValue() + (index * layout.byteSize())}. + * @param value the short value to be written. + * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from + * a thread other than the thread owning that scope. + * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * memory segment. + * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. + */ + @ForceInline + default void setAtIndex(ValueLayout.OfShort layout, long index, short value) { + layout.accessHandle().set(this, Utils.scaleOffset(this, index, layout.byteSize()), value); + } + + /** + * Reads an int from this segment and index, scaled by given layout size. + * + * @param layout the layout of the memory region to be read. + * @param index index (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, + * the final address of this read operation can be expressed as {@code address().toRowLongValue() + (index * layout.byteSize())}. + * @return an int value read from this address. + * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from + * a thread other than the thread owning that scope. + * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * memory segment. + */ + @ForceInline + default int getAtIndex(ValueLayout.OfInt layout, long index) { + return (int)layout.accessHandle().get(this, Utils.scaleOffset(this, index, layout.byteSize())); + } + + /** + * Writes an int to this segment and index, scaled by given layout size. + * + * @param layout the layout of the memory region to be written. + * @param index index (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, + * the final address of this write operation can be expressed as {@code address().toRowLongValue() + (index * layout.byteSize())}. + * @param value the int value to be written. + * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from + * a thread other than the thread owning that scope. + * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * memory segment. + * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. + */ + @ForceInline + default void setAtIndex(ValueLayout.OfInt layout, long index, int value) { + layout.accessHandle().set(this, Utils.scaleOffset(this, index, layout.byteSize()), value); + } + + /** + * Reads a float from this segment and index, scaled by given layout size. + * + * @param layout the layout of the memory region to be read. + * @param index index (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, + * the final address of this read operation can be expressed as {@code address().toRowLongValue() + (index * layout.byteSize())}. + * @return a float value read from this address. + * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from + * a thread other than the thread owning that scope. + * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * memory segment. + */ + @ForceInline + default float getAtIndex(ValueLayout.OfFloat layout, long index) { + return (float)layout.accessHandle().get(this, Utils.scaleOffset(this, index, layout.byteSize())); + } + + /** + * Writes a float to this segment and index, scaled by given layout size. + * + * @param layout the layout of the memory region to be written. + * @param index index (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, + * the final address of this write operation can be expressed as {@code address().toRowLongValue() + (index * layout.byteSize())}. + * @param value the float value to be written. + * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from + * a thread other than the thread owning that scope. + * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * memory segment. + * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. + */ + @ForceInline + default void setAtIndex(ValueLayout.OfFloat layout, long index, float value) { + layout.accessHandle().set(this, Utils.scaleOffset(this, index, layout.byteSize()), value); + } + + /** + * Reads a long from this segment and index, scaled by given layout size. + * + * @param layout the layout of the memory region to be read. + * @param index index (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, + * the final address of this read operation can be expressed as {@code address().toRowLongValue() + (index * layout.byteSize())}. + * @return a long value read from this address. + * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from + * a thread other than the thread owning that scope. + * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * memory segment. + */ + @ForceInline + default long getAtIndex(ValueLayout.OfLong layout, long index) { + return (long)layout.accessHandle().get(this, Utils.scaleOffset(this, index, layout.byteSize())); + } + + /** + * Writes a long to this segment and index, scaled by given layout size. + * + * @param layout the layout of the memory region to be written. + * @param index index (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, + * the final address of this write operation can be expressed as {@code address().toRowLongValue() + (index * layout.byteSize())}. + * @param value the long value to be written. + * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from + * a thread other than the thread owning that scope. + * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * memory segment. + * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. + */ + @ForceInline + default void setAtIndex(ValueLayout.OfLong layout, long index, long value) { + layout.accessHandle().set(this, Utils.scaleOffset(this, index, layout.byteSize()), value); + } + + /** + * Reads a double from this segment and index, scaled by given layout size. + * + * @param layout the layout of the memory region to be read. + * @param index index (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, + * the final address of this read operation can be expressed as {@code address().toRowLongValue() + (index * layout.byteSize())}. + * @return a double value read from this address. + * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from + * a thread other than the thread owning that scope. + * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * memory segment. + */ + @ForceInline + default double getAtIndex(ValueLayout.OfDouble layout, long index) { + return (double)layout.accessHandle().get(this, Utils.scaleOffset(this, index, layout.byteSize())); + } + + /** + * Writes a double to this segment and index, scaled by given layout size. + * + * @param layout the layout of the memory region to be written. + * @param index index (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, + * the final address of this write operation can be expressed as {@code address().toRowLongValue() + (index * layout.byteSize())}. + * @param value the double value to be written. + * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from + * a thread other than the thread owning that scope. + * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * memory segment. + * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. + */ + @ForceInline + default void setAtIndex(ValueLayout.OfDouble layout, long index, double value) { + layout.accessHandle().set(this, Utils.scaleOffset(this, index, layout.byteSize()), value); + } + + /** + * Reads an address from this segment and index, scaled by given layout size. + * + * @param layout the layout of the memory region to be read. + * @param index index (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, + * the final address of this read operation can be expressed as {@code address().toRowLongValue() + (index * layout.byteSize())}. + * @return an address value read from this address. + * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from + * a thread other than the thread owning that scope. + * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * memory segment. + */ + @ForceInline + default MemoryAddress getAtIndex(ValueLayout.OfAddress layout, long index) { + return (MemoryAddress)layout.accessHandle().get(this, Utils.scaleOffset(this, index, layout.byteSize())); + } + + /** + * Writes an address to this segment and index, scaled by given layout size. + * + * @param layout the layout of the memory region to be written. + * @param index index (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, + * the final address of this write operation can be expressed as {@code address().toRowLongValue() + (index * layout.byteSize())}. + * @param value the address value to be written. + * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from + * a thread other than the thread owning that scope. + * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * memory segment. + * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. + */ + @ForceInline + default void setAtIndex(ValueLayout.OfAddress layout, long index, Addressable value) { + layout.accessHandle().set(this, Utils.scaleOffset(this, index, layout.byteSize()), value.address()); + } + + + /** + * Copies a number of elements from a source segment to a destination array, + * starting at a given segment offset (expressed in bytes), and a given array index, using the given source element layout. + * Supported array types are {@code byte[]}, {@code char[]}, {@code short[]}, {@code int[]}, {@code float[]}, {@code long[]} and {@code double[]}. + * @param srcSegment the source segment. + * @param srcLayout the source element layout. If the byte order associated with the layout is + * different from the native order, a byte swap operation will be performed on each array element. + * @param srcOffset the starting offset, in bytes, of the source segment. + * @param dstArray the destination array. + * @param dstIndex the starting index of the destination array. + * @param elementCount the number of array elements to be copied. + * @throws IllegalArgumentException if {@code dstArray} is not an array, or if it is an array but whose type is not supported, + * or if the destination array component type does not match the carrier of the source element layout. + */ + @ForceInline + static void copy( + MemorySegment srcSegment, ValueLayout srcLayout, long srcOffset, + Object dstArray, int dstIndex, int elementCount) { + Objects.requireNonNull(srcSegment); + Objects.requireNonNull(dstArray); + Objects.requireNonNull(srcLayout); + long baseAndScale = getBaseAndScale(dstArray.getClass()); + if (dstArray.getClass().componentType() != srcLayout.carrier()) { + throw new IllegalArgumentException("Incompatible value layout: " + srcLayout); + } + int dstBase = (int)baseAndScale; + int dstWidth = (int)(baseAndScale >> 32); + AbstractMemorySegmentImpl srcImpl = (AbstractMemorySegmentImpl)srcSegment; + srcImpl.checkAccess(srcOffset, elementCount * dstWidth, true); + Objects.checkFromIndexSize(dstIndex, elementCount, Array.getLength(dstArray)); + if (dstWidth == 1 || srcLayout.order() == ByteOrder.nativeOrder()) { + ScopedMemoryAccess.getScopedMemoryAccess().copyMemory(srcImpl.scope(), null, + srcImpl.unsafeGetBase(), srcImpl.unsafeGetOffset() + srcOffset, + dstArray, dstBase + (dstIndex * dstWidth), elementCount * dstWidth); + } else { + ScopedMemoryAccess.getScopedMemoryAccess().copySwapMemory(srcImpl.scope(), null, + srcImpl.unsafeGetBase(), srcImpl.unsafeGetOffset() + srcOffset, + dstArray, dstBase + (dstIndex * dstWidth), elementCount * dstWidth, dstWidth); + } + } + + /** + * Copies a number of elements from a source array to a destination segment, + * starting at a given array index, and a given segment offset (expressed in bytes), using the given destination element layout. + * Supported array types are {@code byte[]}, {@code char[]}, {@code short[]}, {@code int[]}, {@code float[]}, {@code long[]} and {@code double[]}. + * @param srcArray the source array. + * @param srcIndex the starting index of the source array. + * @param dstSegment the destination segment. + * @param dstLayout the destination element layout. If the byte order associated with the layout is + * different from the native order, a byte swap operation will be performed on each array element. + * @param dstOffset the starting offset, in bytes, of the destination segment. + * @param elementCount the number of array elements to be copied. + * @throws IllegalArgumentException if {@code srcArray} is not an array, or if it is an array but whose type is not supported, + * or if the source array component type does not match the carrier of the destination element layout. + */ + @ForceInline + static void copy( + Object srcArray, int srcIndex, + MemorySegment dstSegment, ValueLayout dstLayout, long dstOffset, int elementCount) { + Objects.requireNonNull(srcArray); + Objects.requireNonNull(dstSegment); + Objects.requireNonNull(dstLayout); + long baseAndScale = getBaseAndScale(srcArray.getClass()); + if (srcArray.getClass().componentType() != dstLayout.carrier()) { + throw new IllegalArgumentException("Incompatible value layout: " + dstLayout); + } + int srcBase = (int)baseAndScale; + int srcWidth = (int)(baseAndScale >> 32); + Objects.checkFromIndexSize(srcIndex, elementCount, Array.getLength(srcArray)); + AbstractMemorySegmentImpl destImpl = (AbstractMemorySegmentImpl)dstSegment; + destImpl.checkAccess(dstOffset, elementCount * srcWidth, false); + if (srcWidth == 1 || dstLayout.order() == ByteOrder.nativeOrder()) { + ScopedMemoryAccess.getScopedMemoryAccess().copyMemory(null, destImpl.scope(), + srcArray, srcBase + (srcIndex * srcWidth), + destImpl.unsafeGetBase(), destImpl.unsafeGetOffset() + dstOffset, elementCount * srcWidth); + } else { + ScopedMemoryAccess.getScopedMemoryAccess().copySwapMemory(null, destImpl.scope(), + srcArray, srcBase + (srcIndex * srcWidth), + destImpl.unsafeGetBase(), destImpl.unsafeGetOffset() + dstOffset, elementCount * srcWidth, srcWidth); + } + } + + private static long getBaseAndScale(Class arrayType) { + if (arrayType.equals(byte[].class)) { + return (long)Unsafe.ARRAY_BYTE_BASE_OFFSET | ((long)Unsafe.ARRAY_BYTE_INDEX_SCALE << 32); + } else if (arrayType.equals(char[].class)) { + return (long)Unsafe.ARRAY_CHAR_BASE_OFFSET | ((long)Unsafe.ARRAY_CHAR_INDEX_SCALE << 32); + } else if (arrayType.equals(short[].class)) { + return (long)Unsafe.ARRAY_SHORT_BASE_OFFSET | ((long)Unsafe.ARRAY_SHORT_INDEX_SCALE << 32); + } else if (arrayType.equals(int[].class)) { + return (long)Unsafe.ARRAY_INT_BASE_OFFSET | ((long) Unsafe.ARRAY_INT_INDEX_SCALE << 32); + } else if (arrayType.equals(float[].class)) { + return (long)Unsafe.ARRAY_FLOAT_BASE_OFFSET | ((long)Unsafe.ARRAY_FLOAT_INDEX_SCALE << 32); + } else if (arrayType.equals(long[].class)) { + return (long)Unsafe.ARRAY_LONG_BASE_OFFSET | ((long)Unsafe.ARRAY_LONG_INDEX_SCALE << 32); + } else if (arrayType.equals(double[].class)) { + return (long)Unsafe.ARRAY_DOUBLE_BASE_OFFSET | ((long)Unsafe.ARRAY_DOUBLE_INDEX_SCALE << 32); + } else { + throw new IllegalArgumentException("Not a supported array class: " + arrayType.getSimpleName()); + } } } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/NativeSymbol.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/NativeSymbol.java new file mode 100644 index 0000000000000000000000000000000000000000..bf137e965d74c3e699c50b4bd6a8800474cf866f --- /dev/null +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/NativeSymbol.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +package jdk.incubator.foreign; + +import jdk.internal.foreign.NativeSymbolImpl; +import jdk.internal.reflect.CallerSensitive; +import jdk.internal.reflect.Reflection; + +import java.lang.invoke.MethodHandle; +import java.util.Objects; + +/** + * A native symbol models a reference to a location (typically the entry point of a function) in a native library. + * A native symbol has a name, and is associated with a scope, which governs the native symbol's lifecycle. + * This is useful, since the library a native symbol refers to can be unloaded, thus invalidating the native symbol. + * While native symbols are typically obtained using a {@link SymbolLookup#lookup(String) symbol lookup}, it is also possible to obtain an + * anonymous native symbol, in the form of an {@linkplain CLinker#upcallStub(MethodHandle, FunctionDescriptor, ResourceScope) upcall stub}, + * that is, a reference to a dynamically-generated native symbol which can be used to call back into Java code. + */ +sealed public interface NativeSymbol extends Addressable permits NativeSymbolImpl { + + /** + * Returns the name of this symbol. + * @return the name of this symbol. + */ + String name(); + + /** + * Returns the resource scope associated with this symbol. + * @return the resource scope associated with this symbol. + */ + ResourceScope scope(); + + /** + * Returns the memory address associated with this symbol. + * @throws IllegalStateException if the scope associated with this symbol has been closed, or if access occurs from + * a thread other than the thread owning that scope. + * @return The memory address associated with this symbol. + */ + @Override + MemoryAddress address(); + + /** + * Creates a new symbol from given name, address and scope. + *

    + * This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * restricted methods, and use safe and supported functionalities, where possible. + * @param name the symbol name. + * @param address the symbol address. + * @param scope the symbol scope. + * @return A new symbol from given name, address and scope. + * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option + * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or + * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + */ + @CallerSensitive + static NativeSymbol ofAddress(String name, MemoryAddress address, ResourceScope scope) { + Reflection.ensureNativeAccess(Reflection.getCallerClass()); + Objects.requireNonNull(name); + Objects.requireNonNull(address); + Objects.requireNonNull(scope); + return new NativeSymbolImpl(name, address, scope); + } +} diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/PaddingLayout.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/PaddingLayout.java index db65c48669b312d39c43eb8395f558cdf2653e35..0b90e9a1d1d842d25a60763bf10f795049ea1d8f 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/PaddingLayout.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/PaddingLayout.java @@ -25,10 +25,8 @@ */ package jdk.incubator.foreign; -import java.lang.constant.Constable; import java.lang.constant.ConstantDescs; import java.lang.constant.DynamicConstantDesc; -import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.OptionalLong; @@ -53,11 +51,11 @@ import java.util.OptionalLong; /* package-private */ final class PaddingLayout extends AbstractLayout implements MemoryLayout { PaddingLayout(long size) { - this(size, 1, Map.of()); + this(size, 1, Optional.empty()); } - PaddingLayout(long size, long alignment, Map attributes) { - super(OptionalLong.of(size), alignment, attributes); + PaddingLayout(long size, long alignment, Optional name) { + super(OptionalLong.of(size), alignment, name); } @Override @@ -73,10 +71,9 @@ import java.util.OptionalLong; if (!super.equals(other)) { return false; } - if (!(other instanceof PaddingLayout)) { + if (!(other instanceof PaddingLayout p)) { return false; } - PaddingLayout p = (PaddingLayout)other; return bitSize() == p.bitSize(); } @@ -86,8 +83,8 @@ import java.util.OptionalLong; } @Override - PaddingLayout dup(long alignment, Map attributes) { - return new PaddingLayout(bitSize(), alignment, attributes); + PaddingLayout dup(long alignment, Optional name) { + return new PaddingLayout(bitSize(), alignment, name); } @Override @@ -119,12 +116,4 @@ import java.util.OptionalLong; public PaddingLayout withBitAlignment(long alignmentBits) { return (PaddingLayout)super.withBitAlignment(alignmentBits); } - - /** - * {@inheritDoc} - */ - @Override - public PaddingLayout withAttribute(String name, Constable value) { - return (PaddingLayout)super.withAttribute(name, value); - } } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/ResourceScope.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/ResourceScope.java index 0a46ab705b361e865a6ca75c37ba84b7503b7f2a..24665c7dfe9fcbb588dfa5a291a3ffce9a9e29db 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/ResourceScope.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/ResourceScope.java @@ -26,9 +26,11 @@ package jdk.incubator.foreign; import jdk.internal.foreign.ResourceScopeImpl; +import jdk.internal.ref.CleanerFactory; import java.lang.invoke.MethodHandle; import java.lang.ref.Cleaner; +import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.file.Path; import java.util.Objects; @@ -36,109 +38,109 @@ import java.util.Spliterator; /** * A resource scope manages the lifecycle of one or more resources. Resources (e.g. {@link MemorySegment}) associated - * with a resource scope can only be accessed while the resource scope is alive (see {@link #isAlive()}), - * and by the thread associated with the resource scope (if any). + * with a resource scope can only be accessed while the resource scope is {@linkplain #isAlive() alive}, + * and by the {@linkplain #ownerThread() thread} associated with the resource scope (if any). * - *

    Explicit resource scopes

    + *

    Deterministic deallocation

    * - * Resource scopes obtained from {@link #newConfinedScope()}, {@link #newSharedScope()} support deterministic deallocation; - * We call these resource scopes explicit scopes. Explicit resource scopes can be closed explicitly (see {@link ResourceScope#close()}). - * When a resource scope is closed, it is no longer alive (see {@link #isAlive()}, and subsequent operations on - * resources associated with that scope (e.g. attempting to access a {@link MemorySegment} instance) will fail with {@link IllegalStateException}. + * Resource scopes support deterministic deallocation; that is, they can be {@linkplain ResourceScope#close() closed} + * explicitly. When a resource scope is closed, it is no longer {@link #isAlive() alive}, and subsequent + * operations on resources associated with that scope (e.g. attempting to access a {@link MemorySegment} instance) + * will fail with {@link IllegalStateException}. *

    - * Closing a resource scope will cause all the cleanup actions associated with that scope (see {@link #addCloseAction(Runnable)}) to be called. + * Closing a resource scope will cause all the {@linkplain #addCloseAction(Runnable) close actions} associated with that scope to be called. * Moreover, closing a resource scope might trigger the releasing of the underlying memory resources associated with said scope; for instance: *

      - *
    • closing the scope associated with a native memory segment results in freeing the native memory associated with it - * (see {@link MemorySegment#allocateNative(long, ResourceScope)}, or {@link SegmentAllocator#arenaAllocator(ResourceScope)})
    • - *
    • closing the scope associated with a mapped memory segment results in the backing memory-mapped file to be unmapped - * (see {@link MemorySegment#mapFile(Path, long, long, FileChannel.MapMode, ResourceScope)})
    • - *
    • closing the scope associated with an upcall stub results in releasing the stub - * (see {@link CLinker#upcallStub(MethodHandle, FunctionDescriptor, ResourceScope)}
    • + *
    • closing the scope associated with a {@linkplain MemorySegment#allocateNative(long, long, ResourceScope) native memory segment} + * results in freeing the native memory associated with it;
    • + *
    • closing the scope associated with a {@linkplain MemorySegment#mapFile(Path, long, long, FileChannel.MapMode, ResourceScope) mapped memory segment} + * results in the backing memory-mapped file to be unmapped;
    • + *
    • closing the scope associated with an {@linkplain CLinker#upcallStub(MethodHandle, FunctionDescriptor, ResourceScope) upcall stub} + * results in releasing the stub;
    • + *
    • closing the scope associated with a {@linkplain VaList variable arity list} results in releasing the memory + * associated with that variable arity list instance.
    • *
    - *

    - * Sometimes, explicit scopes can be associated with a {@link Cleaner} instance (see {@link #newConfinedScope(Cleaner)} and - * {@link #newSharedScope(Cleaner)}). We call these resource scopes managed resource scopes. A managed resource scope - * is closed automatically once the scope instance becomes unreachable. - *

    - * Managed scopes can be useful to allow for predictable, deterministic resource deallocation, while still prevent accidental native memory leaks. - * In case a managed resource scope is closed explicitly, no further action will be taken when the scope becomes unreachable; - * that is, cleanup actions (see {@link #addCloseAction(Runnable)}) associated with a resource scope, whether managed or not, - * are called exactly once. * - *

    Implicit resource scopes

    + *

    Implicit deallocation

    + * + * Resource scopes can be associated with a {@link Cleaner} instance, so that they are also closed automatically, + * once the scope instance becomes unreachable. + * This can be useful to allow for predictable, deterministic resource deallocation, while still preventing accidental + * native memory leaks. In case a managed resource scope is closed explicitly, no further action will be taken when + * the scope becomes unreachable; that is, {@linkplain #addCloseAction(Runnable) close actions} associated with a + * resource scope, whether managed or not, are called exactly once. + * + *

    Global scope

    * - * Resource scopes obtained from {@link #newImplicitScope()} cannot be closed explicitly. We call these resource scopes - * implicit scopes. Calling {@link #close()} on an implicit resource scope always results in an exception. - * Resources associated with implicit scopes are released once the scope instance becomes - * unreachable. - *

    * An important implicit resource scope is the so called {@linkplain #globalScope() global scope}; the global scope is - * an implicit scope that is guaranteed to never become unreachable. - * As a results, the global scope will never attempt to release resources associated with it. Such resources must, where + * a resource scope that cannot be closed, either explicitly or implicitly. As a result, the global scope will never + * attempt to release resources associated with it. Examples of resources associated with the global scope are: + *

      + *
    • heap segments created from {@linkplain MemorySegment#ofArray(int[]) arrays} or + * {@linkplain MemorySegment#ofByteBuffer(ByteBuffer) buffers};
    • + *
    • variable arity lists {@linkplain VaList#ofAddress(MemoryAddress, ResourceScope) obtained} from raw memory addresses; + *
    • native symbols {@linkplain SymbolLookup#lookup(String) obtained} from a {@linkplain SymbolLookup#loaderLookup() loader lookup}, + * or from the {@link CLinker}.
    • + *
    + * In other words, the global scope is used to indicate that the lifecycle of one or more resources must, where * needed, be managed independently by clients. * *

    Thread confinement

    * - * Resource scopes can be further divided into two categories: thread-confined resource scopes, and shared + * Resource scopes can be divided into two categories: thread-confined resource scopes, and shared * resource scopes. *

    - * Confined resource scopes (see {@link #newConfinedScope()}), support strong thread-confinement guarantees. Upon creation, - * they are assigned an owner thread, typically the thread which initiated the creation operation (see {@link #ownerThread()}). + * {@linkplain #newConfinedScope() Confined resource scopes}, support strong thread-confinement guarantees. Upon creation, + * they are assigned an {@linkplain #ownerThread() owner thread}, typically the thread which initiated the creation operation. * After creating a confined resource scope, only the owner thread will be allowed to directly manipulate the resources * associated with this resource scope. Any attempt to perform resource access from a thread other than the * owner thread will result in a runtime failure. *

    - * Shared resource scopes (see {@link #newSharedScope()} and {@link #newImplicitScope()}), on the other hand, have no owner thread; - * as such resources associated with this shared resource scopes can be accessed by multiple threads. + * {@linkplain #newSharedScope() Shared resource scopes}, on the other hand, have no owner thread; + * as such, resources associated with shared resource scopes can be accessed by multiple threads. * This might be useful when multiple threads need to access the same resource concurrently (e.g. in the case of parallel processing). - * For instance, a client might obtain a {@link Spliterator} from a shared segment, which can then be used to slice the + * For instance, a client might obtain a {@link Spliterator} from a segment backed by a shared scope, which can then be used to slice the * segment and allow multiple threads to work in parallel on disjoint segment slices. The following code can be used to sum * all int values in a memory segment in parallel: * - *

    {@code
    -SequenceLayout SEQUENCE_LAYOUT = MemoryLayout.sequenceLayout(1024, MemoryLayouts.JAVA_INT);
    -try (ResourceScope scope = ResourceScope.newSharedScope()) {
    -    MemorySegment segment = MemorySegment.allocateNative(SEQUENCE_LAYOUT, scope);
    -    VarHandle VH_int = SEQUENCE_LAYOUT.elementLayout().varHandle(int.class);
    -    int sum = StreamSupport.stream(segment.spliterator(SEQUENCE_LAYOUT), true)
    -        .mapToInt(s -> (int)VH_int.get(s.address()))
    -        .sum();
    -}
    - * }
    + * {@snippet lang=java : + * try (ResourceScope scope = ResourceScope.newSharedScope()) { + * SequenceLayout SEQUENCE_LAYOUT = MemoryLayout.sequenceLayout(1024, ValueLayout.JAVA_INT); + * MemorySegment segment = MemorySegment.allocateNative(SEQUENCE_LAYOUT, scope); + * int sum = segment.elements(ValueLayout.JAVA_INT).parallel() + * .mapToInt(s -> s.get(ValueLayout.JAVA_INT, 0)) + * .sum(); + * } + * } * *

    - * Explicit shared resource scopes, while powerful, must be used with caution: if one or more threads accesses + * Shared resource scopes, while powerful, must be used with caution: if one or more threads accesses * a resource associated with a shared scope while the scope is being closed from another thread, an exception might occur on both * the accessing and the closing threads. Clients should refrain from attempting to close a shared resource scope repeatedly * (e.g. keep calling {@link #close()} until no exception is thrown). Instead, clients of shared resource scopes - * should always ensure that proper synchronization mechanisms (e.g. using resource scope handles, see below) are put in place + * should always ensure that proper synchronization mechanisms (e.g. using temporal dependencies, see below) are put in place * so that threads closing shared resource scopes can never race against threads accessing resources managed by same scopes. * - *

    Resource scope handles

    + *

    Temporal dependencies

    * - * Resource scopes can be made non-closeable by acquiring one or more resource scope handles (see - * {@link #acquire()}. A resource scope handle can be used to make sure that resources associated with a given resource scope - * (either explicit or implicit) cannot be released for a certain period of time - e.g. during a critical region of code - * involving one or more resources associated with the scope. For instance, an explicit resource scope can only be closed - * after all the handles acquired against that scope have been closed (see {@link Handle#close()}). + * Resource scopes can depend on each other. More specifically, a scope can feature + * {@linkplain #keepAlive(ResourceScope) temporal dependencies} on one or more other resource scopes. + * Such a resource scope cannot be closed (either implicitly or explicitly) until all the scopes it depends on + * have also been closed. + *

    * This can be useful when clients need to perform a critical operation on a memory segment, during which they have - * to ensure that the segment will not be released; this can be done as follows: + * to ensure that the scope associated with that segment will not be closed; this can be done as follows: * - *

    {@code
    -MemorySegment segment = ...
    -ResourceScope.Handle segmentHandle = segment.scope().acquire()
    -try {
    -   
    -} finally {
    -   segment.scope().release(segmentHandle);
    -}
    - * }
    + * {@snippet lang=java : + * MemorySegment segment = ... + * try (ResourceScope criticalScope = ResourceScope.newConfinedScope()) { + * criticalScope.keepAlive(segment.scope()); + * + * } + * } * - * Acquiring implicit resource scopes is also possible, but it is often unnecessary: since resources associated with - * an implicit scope will only be released when the scope becomes unreachable, - * clients can use e.g. {@link java.lang.ref.Reference#reachabilityFence(Object)} to make sure that resources associated - * with implicit scopes are not released prematurely. That said, the above code snippet works (trivially) for implicit scopes too. + * Note that a resource scope does not become unreachable + * until all the scopes it depends on have been closed. * * @implSpec * Implementations of this interface are immutable, thread-safe and value-based. @@ -158,15 +160,7 @@ public sealed interface ResourceScope extends AutoCloseable permits ResourceScop Thread ownerThread(); /** - * Is this resource scope an implicit scope? - * @return true if this scope is an implicit scope. - * @see #newImplicitScope() - * @see #globalScope() - */ - boolean isImplicit(); - - /** - * Closes this resource scope. As a side-effect, if this operation completes without exceptions, this scope will be marked + * Closes this resource scope. As a side effect, if this operation completes without exceptions, this scope will be marked * as not alive, and subsequent operations on resources associated with this scope will fail with {@link IllegalStateException}. * Additionally, upon successful closure, all native resources associated with this resource scope will be released. * @@ -180,9 +174,9 @@ public sealed interface ResourceScope extends AutoCloseable permits ResourceScop *
  • this resource scope is not alive *
  • this resource scope is confined, and this method is called from a thread other than the thread owning this resource scope
  • *
  • this resource scope is shared and a resource associated with this scope is accessed while this method is called
  • - *
  • one or more handles (see {@link #acquire()}) associated with this resource scope have not been {@linkplain #release(Handle) released}
  • + *
  • one or more scopes which {@linkplain #keepAlive(ResourceScope) depend} on this resource scope have not been closed. * - * @throws UnsupportedOperationException if this resource scope is {@linkplain #isImplicit() implicit}. + * @throws UnsupportedOperationException if this resource scope is the {@linkplain #globalScope() global scope}. */ void close(); @@ -190,61 +184,42 @@ public sealed interface ResourceScope extends AutoCloseable permits ResourceScop * Add a custom cleanup action which will be executed when the resource scope is closed. * The order in which custom cleanup actions are invoked once the scope is closed is unspecified. * @param runnable the custom cleanup action to be associated with this scope. - * @throws IllegalStateException if this scope has already been closed. + * @throws IllegalStateException if this scope has been closed, or if access occurs from + * a thread other than the thread owning this scope. */ void addCloseAction(Runnable runnable); /** - * Acquires a resource scope handle associated with this resource scope. An explicit resource scope cannot be - * {@linkplain #close() closed} until all the resource scope handles acquired from it have been {@linkplain #release(Handle)} released}. - * @return a resource scope handle. - */ - Handle acquire(); - - /** - * Release the provided resource scope handle. This method is idempotent, that is, releasing the same handle - * multiple times has no effect. - * @param handle the resource scope handle to be released. - * @throws IllegalArgumentException if the provided handle is not associated with this scope. + * Creates a temporal dependency between this scope and the target scope. As a result, the target scope cannot + * be {@linkplain #close() closed} before this scope. + * @implNote A given scope can support up to {@link Integer#MAX_VALUE} pending keep alive requests. + * @param target the scope that needs to be kept alive. + * @throws IllegalArgumentException if {@code target == this}. + * @throws IllegalStateException if this scope or {@code target} have been closed, or if access occurs from + * a thread other than the thread owning this scope or {@code target}. */ - void release(Handle handle); + void keepAlive(ResourceScope target); /** - * An abstraction modelling a resource scope handle. A resource scope handle is typically {@linkplain #acquire() acquired} by clients - * in order to prevent an explicit resource scope from being closed while executing a certain operation. - * Once obtained, resource scope handles can be {@linkplain #release(Handle)} released}; an explicit resource scope can - * be closed only after all the resource scope handles acquired from it have been released. - */ - sealed interface Handle permits ResourceScopeImpl.HandleImpl { - - /** - * Returns the resource scope associated with this handle. - * @return the resource scope associated with this handle. - */ - ResourceScope scope(); - } - - /** - * Create a new confined scope. The resulting scope is closeable, and is not managed by a {@link Cleaner}. + * Creates a new confined scope. * @return a new confined scope. */ static ResourceScope newConfinedScope() { - return ResourceScopeImpl.createConfined( null); + return ResourceScopeImpl.createConfined(Thread.currentThread(), null); } /** - * Create a new confined scope managed by a {@link Cleaner}. + * Creates a new confined scope, managed by the provided cleaner instance. * @param cleaner the cleaner to be associated with the returned scope. * @return a new confined scope, managed by {@code cleaner}. - * @throws NullPointerException if {@code cleaner == null}. */ static ResourceScope newConfinedScope(Cleaner cleaner) { Objects.requireNonNull(cleaner); - return ResourceScopeImpl.createConfined( cleaner); + return ResourceScopeImpl.createConfined(Thread.currentThread(), cleaner); } /** - * Create a new shared scope. The resulting scope is closeable, and is not managed by a {@link Cleaner}. + * Creates a new shared scope. * @return a new shared scope. */ static ResourceScope newSharedScope() { @@ -252,10 +227,9 @@ public sealed interface ResourceScope extends AutoCloseable permits ResourceScop } /** - * Create a new shared scope managed by a {@link Cleaner}. + * Creates a new shared scope, managed by the provided cleaner instance. * @param cleaner the cleaner to be associated with the returned scope. * @return a new shared scope, managed by {@code cleaner}. - * @throws NullPointerException if {@code cleaner == null}. */ static ResourceScope newSharedScope(Cleaner cleaner) { Objects.requireNonNull(cleaner); @@ -263,21 +237,20 @@ public sealed interface ResourceScope extends AutoCloseable permits ResourceScop } /** - * Create a new implicit scope. The implicit scope is a managed, shared, and non-closeable scope which only features - * implicit closure. - * Since implicit scopes can only be closed implicitly by the garbage collector, it is recommended that implicit - * scopes are only used in cases where deallocation performance is not a critical concern, to avoid unnecessary - * memory pressure. - * - * @return a new implicit scope. + * Creates a new shared scope, managed by a private {@link Cleaner} instance. Equivalent to (but likely more efficient than) + * the following code: + * {@snippet lang=java : + * newSharedScope(Cleaner.create()); + * } + * @return a shared scope, managed by a private {@link Cleaner} instance. */ static ResourceScope newImplicitScope() { - return ResourceScopeImpl.createImplicitScope(); + return newSharedScope(CleanerFactory.cleaner()); } /** - * Returns an implicit scope which is assumed to be always alive. - * @return the global scope. + * Returns the global scope. + * @return the global scope. */ static ResourceScope globalScope() { return ResourceScopeImpl.GLOBAL; diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/SegmentAllocator.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/SegmentAllocator.java index f127dc7033087256d2f01539033a40134401e9d3..4e2ad3255200bd4dc4797823853a280c862aa71d 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/SegmentAllocator.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/SegmentAllocator.java @@ -25,306 +25,277 @@ package jdk.incubator.foreign; -import jdk.internal.foreign.ArenaAllocator; import jdk.internal.foreign.AbstractMemorySegmentImpl; +import jdk.internal.foreign.ArenaAllocator; import jdk.internal.foreign.ResourceScopeImpl; import jdk.internal.foreign.Utils; import java.lang.invoke.VarHandle; import java.lang.reflect.Array; import java.nio.ByteOrder; +import java.nio.charset.StandardCharsets; import java.util.Objects; import java.util.function.Function; -import java.util.stream.Stream; /** * This interface models a memory allocator. Clients implementing this interface * must implement the {@link #allocate(long, long)} method. This interface defines several default methods * which can be useful to create segments from several kinds of Java values such as primitives and arrays. - * This interface can be seen as a thin wrapper around the basic capabilities for creating native segments - * (e.g. {@link MemorySegment#allocateNative(long, long, ResourceScope)}); since {@link SegmentAllocator} is a functional interface, + * This interface can be seen as a thin wrapper around the basic capabilities for + * {@linkplain MemorySegment#allocateNative(long, long, ResourceScope) creating} native segments; + * since {@link SegmentAllocator} is a functional interface, * clients can easily obtain a native allocator by using either a lambda expression or a method reference. *

    - * This interface provides a factory, namely {@link SegmentAllocator#ofScope(ResourceScope)} which can be used to obtain - * a scoped allocator, that is, an allocator which creates segment bound by a given scope. This can be useful - * when working inside a try-with-resources construct: - * - *

    {@code
    -try (ResourceScope scope = ResourceScope.newConfinedScope()) {
    -   SegmentAllocator allocator = SegmentAllocator.ofScope(scope);
    -   ...
    -}
    - * }
    - * - * In addition, this interface also defines factories for commonly used allocators; for instance {@link #arenaAllocator(ResourceScope)} - * and {@link #arenaAllocator(long, ResourceScope)} are arena-style native allocators. Finally {@link #ofSegment(MemorySegment)} - * returns an allocator which wraps a segment (either on-heap or off-heap) and recycles its content upon each new allocation request. + * This interface also defines factories for commonly used allocators: + *
      + *
    • {@link #nativeAllocator(ResourceScope)} creates an allocator which + * {@linkplain MemorySegment#allocateNative(long, long, ResourceScope) allocates} native segments, backed by a given scope;
    • + *
    • {@link #newNativeArena(ResourceScope)} creates a more efficient arena-style native allocator, where memory + * is allocated in bigger blocks, which are then sliced accordingly to fit allocation requests;
    • + *
    • {@link #prefixAllocator(MemorySegment)} creates an allocator which wraps a segment (either on-heap or off-heap) + * and recycles its content upon each new allocation request.
    • + *
    + *

    + * Passing a segment allocator to an API can be especially useful in circumstances where a client wants to communicate where + * the results of a certain operation (performed by the API) should be stored, as a memory segment. For instance, + * {@linkplain CLinker#downcallHandle(FunctionDescriptor) downcall method handles} can accept an additional + * {@link SegmentAllocator} parameter if the underlying native function is known to return a struct by-value. Effectively, + * the allocator parameter tells the linker runtime where to store the return value of the native function. */ @FunctionalInterface public interface SegmentAllocator { /** - * Allocate a block of memory with given layout and initialize it with given byte value. + * Converts a Java string into a UTF-8 encoded, null-terminated C string, + * storing the result into a memory segment. + *

    + * This method always replaces malformed-input and unmappable-character + * sequences with this charset's default replacement byte array. The + * {@link java.nio.charset.CharsetEncoder} class should be used when more + * control over the encoding process is required. + * + * @implSpec the default implementation for this method copies the contents of the provided Java string + * into a new memory segment obtained by calling {@code this.allocate(str.length() + 1)}. + * @param str the Java string to be converted into a C string. + * @return a new native memory segment containing the converted C string. + */ + default MemorySegment allocateUtf8String(String str) { + Objects.requireNonNull(str); + return Utils.toCString(str.getBytes(StandardCharsets.UTF_8), this); + } + + /** + * Allocate a memory segment with given layout and initialize it with given byte value. * @implSpec the default implementation for this method calls {@code this.allocate(layout)}. * @param layout the layout of the block of memory to be allocated. * @param value the value to be set on the newly allocated memory block. * @return a segment for the newly allocated memory block. - * @throws IllegalArgumentException if {@code layout.byteSize()} does not conform to the size of a byte value. */ - default MemorySegment allocate(ValueLayout layout, byte value) { + default MemorySegment allocate(ValueLayout.OfByte layout, byte value) { Objects.requireNonNull(layout); - VarHandle handle = layout.varHandle(byte.class); + VarHandle handle = layout.varHandle(); MemorySegment addr = allocate(layout); handle.set(addr, value); return addr; } /** - * Allocate a block of memory with given layout and initialize it with given char value. + * Allocate a memory segment with given layout and initialize it with given char value. * @implSpec the default implementation for this method calls {@code this.allocate(layout)}. * @param layout the layout of the block of memory to be allocated. * @param value the value to be set on the newly allocated memory block. * @return a segment for the newly allocated memory block. - * @throws IllegalArgumentException if {@code layout.byteSize()} does not conform to the size of a char value. */ - default MemorySegment allocate(ValueLayout layout, char value) { + default MemorySegment allocate(ValueLayout.OfChar layout, char value) { Objects.requireNonNull(layout); - VarHandle handle = layout.varHandle(char.class); + VarHandle handle = layout.varHandle(); MemorySegment addr = allocate(layout); handle.set(addr, value); return addr; } /** - * Allocate a block of memory with given layout and initialize it with given short value. + * Allocate a memory segment with given layout and initialize it with given short value. * @implSpec the default implementation for this method calls {@code this.allocate(layout)}. * @param layout the layout of the block of memory to be allocated. * @param value the value to be set on the newly allocated memory block. * @return a segment for the newly allocated memory block. - * @throws IllegalArgumentException if {@code layout.byteSize()} does not conform to the size of a short value. */ - default MemorySegment allocate(ValueLayout layout, short value) { + default MemorySegment allocate(ValueLayout.OfShort layout, short value) { Objects.requireNonNull(layout); - VarHandle handle = layout.varHandle(short.class); + VarHandle handle = layout.varHandle(); MemorySegment addr = allocate(layout); handle.set(addr, value); return addr; } /** - * Allocate a block of memory with given layout and initialize it with given int value. + * Allocate a memory segment with given layout and initialize it with given int value. * @implSpec the default implementation for this method calls {@code this.allocate(layout)}. * @param layout the layout of the block of memory to be allocated. * @param value the value to be set on the newly allocated memory block. * @return a segment for the newly allocated memory block. - * @throws IllegalArgumentException if {@code layout.byteSize()} does not conform to the size of a int value. */ - default MemorySegment allocate(ValueLayout layout, int value) { + default MemorySegment allocate(ValueLayout.OfInt layout, int value) { Objects.requireNonNull(layout); - VarHandle handle = layout.varHandle(int.class); + VarHandle handle = layout.varHandle(); MemorySegment addr = allocate(layout); handle.set(addr, value); return addr; } /** - * Allocate a block of memory with given layout and initialize it with given float value. + * Allocate a memory segment with given layout and initialize it with given float value. * @implSpec the default implementation for this method calls {@code this.allocate(layout)}. * @param layout the layout of the block of memory to be allocated. * @param value the value to be set on the newly allocated memory block. * @return a segment for the newly allocated memory block. - * @throws IllegalArgumentException if {@code layout.byteSize()} does not conform to the size of a float value. */ - default MemorySegment allocate(ValueLayout layout, float value) { + default MemorySegment allocate(ValueLayout.OfFloat layout, float value) { Objects.requireNonNull(layout); - VarHandle handle = layout.varHandle(float.class); + VarHandle handle = layout.varHandle(); MemorySegment addr = allocate(layout); handle.set(addr, value); return addr; } /** - * Allocate a block of memory with given layout and initialize it with given long value. + * Allocate a memory segment with given layout and initialize it with given long value. * @implSpec the default implementation for this method calls {@code this.allocate(layout)}. * @param layout the layout of the block of memory to be allocated. * @param value the value to be set on the newly allocated memory block. * @return a segment for the newly allocated memory block. - * @throws IllegalArgumentException if {@code layout.byteSize()} does not conform to the size of a long value. */ - default MemorySegment allocate(ValueLayout layout, long value) { + default MemorySegment allocate(ValueLayout.OfLong layout, long value) { Objects.requireNonNull(layout); - VarHandle handle = layout.varHandle(long.class); + VarHandle handle = layout.varHandle(); MemorySegment addr = allocate(layout); handle.set(addr, value); return addr; } /** - * Allocate a block of memory with given layout and initialize it with given double value. + * Allocate a memory segment with given layout and initialize it with given double value. * @implSpec the default implementation for this method calls {@code this.allocate(layout)}. * @param layout the layout of the block of memory to be allocated. * @param value the value to be set on the newly allocated memory block. * @return a segment for the newly allocated memory block. - * @throws IllegalArgumentException if {@code layout.byteSize()} does not conform to the size of a double value. */ - default MemorySegment allocate(ValueLayout layout, double value) { + default MemorySegment allocate(ValueLayout.OfDouble layout, double value) { Objects.requireNonNull(layout); - VarHandle handle = layout.varHandle(double.class); + VarHandle handle = layout.varHandle(); MemorySegment addr = allocate(layout); handle.set(addr, value); return addr; } /** - * Allocate a block of memory with given layout and initialize it with given address value + * Allocate a memory segment with given layout and initialize it with given address value * (expressed as an {@link Addressable} instance). - * The address value might be narrowed according to the platform address size (see {@link MemoryLayouts#ADDRESS}). + * The address value might be narrowed according to the platform address size (see {@link ValueLayout#ADDRESS}). * @implSpec the default implementation for this method calls {@code this.allocate(layout)}. * @param layout the layout of the block of memory to be allocated. * @param value the value to be set on the newly allocated memory block. * @return a segment for the newly allocated memory block. - * @throws IllegalArgumentException if {@code layout.byteSize() != MemoryLayouts.ADDRESS.byteSize()}. */ - default MemorySegment allocate(ValueLayout layout, Addressable value) { + default MemorySegment allocate(ValueLayout.OfAddress layout, Addressable value) { Objects.requireNonNull(value); Objects.requireNonNull(layout); - if (MemoryLayouts.ADDRESS.byteSize() != layout.byteSize()) { - throw new IllegalArgumentException("Layout size mismatch - " + layout.byteSize() + " != " + MemoryLayouts.ADDRESS.byteSize()); - } - return switch ((int)layout.byteSize()) { - case 4 -> allocate(layout, (int)value.address().toRawLongValue()); - case 8 -> allocate(layout, value.address().toRawLongValue()); - default -> throw new UnsupportedOperationException("Unsupported pointer size"); // should not get here - }; + MemorySegment segment = allocate(layout); + layout.varHandle().set(segment, value.address()); + return segment; } /** - * Allocate a block of memory with given layout and initialize it with given byte array. + * Allocate a memory segment with given layout and initialize it with given byte array. * @implSpec the default implementation for this method calls {@code this.allocateArray(layout, array.length)}. * @param elementLayout the element layout of the array to be allocated. * @param array the array to be copied on the newly allocated memory block. * @return a segment for the newly allocated memory block. - * @throws IllegalArgumentException if {@code elementLayout.byteSize()} does not conform to the size of a byte value. */ - default MemorySegment allocateArray(ValueLayout elementLayout, byte[] array) { + default MemorySegment allocateArray(ValueLayout.OfByte elementLayout, byte[] array) { return copyArrayWithSwapIfNeeded(array, elementLayout, MemorySegment::ofArray); } /** - * Allocate a block of memory with given layout and initialize it with given short array. + * Allocate a memory segment with given layout and initialize it with given short array. * @implSpec the default implementation for this method calls {@code this.allocateArray(layout, array.length)}. * @param elementLayout the element layout of the array to be allocated. * @param array the array to be copied on the newly allocated memory block. * @return a segment for the newly allocated memory block. - * @throws IllegalArgumentException if {@code elementLayout.byteSize()} does not conform to the size of a short value. */ - default MemorySegment allocateArray(ValueLayout elementLayout, short[] array) { + default MemorySegment allocateArray(ValueLayout.OfShort elementLayout, short[] array) { return copyArrayWithSwapIfNeeded(array, elementLayout, MemorySegment::ofArray); } /** - * Allocate a block of memory with given layout and initialize it with given char array. + * Allocate a memory segment with given layout and initialize it with given char array. * @implSpec the default implementation for this method calls {@code this.allocateArray(layout, array.length)}. * @param elementLayout the element layout of the array to be allocated. * @param array the array to be copied on the newly allocated memory block. * @return a segment for the newly allocated memory block. - * @throws IllegalArgumentException if {@code elementLayout.byteSize()} does not conform to the size of a char value. */ - default MemorySegment allocateArray(ValueLayout elementLayout, char[] array) { + default MemorySegment allocateArray(ValueLayout.OfChar elementLayout, char[] array) { return copyArrayWithSwapIfNeeded(array, elementLayout, MemorySegment::ofArray); } /** - * Allocate a block of memory with given layout and initialize it with given int array. + * Allocate a memory segment with given layout and initialize it with given int array. * @implSpec the default implementation for this method calls {@code this.allocateArray(layout, array.length)}. * @param elementLayout the element layout of the array to be allocated. * @param array the array to be copied on the newly allocated memory block. * @return a segment for the newly allocated memory block. - * @throws IllegalArgumentException if {@code elementLayout.byteSize()} does not conform to the size of a int value. */ - default MemorySegment allocateArray(ValueLayout elementLayout, int[] array) { + default MemorySegment allocateArray(ValueLayout.OfInt elementLayout, int[] array) { return copyArrayWithSwapIfNeeded(array, elementLayout, MemorySegment::ofArray); } /** - * Allocate a block of memory with given layout and initialize it with given float array. + * Allocate a memory segment with given layout and initialize it with given float array. * @implSpec the default implementation for this method calls {@code this.allocateArray(layout, array.length)}. * @param elementLayout the element layout of the array to be allocated. * @param array the array to be copied on the newly allocated memory block. * @return a segment for the newly allocated memory block. - * @throws IllegalArgumentException if {@code elementLayout.byteSize()} does not conform to the size of a float value. */ - default MemorySegment allocateArray(ValueLayout elementLayout, float[] array) { + default MemorySegment allocateArray(ValueLayout.OfFloat elementLayout, float[] array) { return copyArrayWithSwapIfNeeded(array, elementLayout, MemorySegment::ofArray); } /** - * Allocate a block of memory with given layout and initialize it with given long array. + * Allocate a memory segment with given layout and initialize it with given long array. * @implSpec the default implementation for this method calls {@code this.allocateArray(layout, array.length)}. * @param elementLayout the element layout of the array to be allocated. * @param array the array to be copied on the newly allocated memory block. * @return a segment for the newly allocated memory block. - * @throws IllegalArgumentException if {@code elementLayout.byteSize()} does not conform to the size of a long value. */ - default MemorySegment allocateArray(ValueLayout elementLayout, long[] array) { + default MemorySegment allocateArray(ValueLayout.OfLong elementLayout, long[] array) { return copyArrayWithSwapIfNeeded(array, elementLayout, MemorySegment::ofArray); } /** - * Allocate a block of memory with given layout and initialize it with given double array. + * Allocate a memory segment with given layout and initialize it with given double array. * @implSpec the default implementation for this method calls {@code this.allocateArray(layout, array.length)}. * @param elementLayout the element layout of the array to be allocated. * @param array the array to be copied on the newly allocated memory block. * @return a segment for the newly allocated memory block. - * @throws IllegalArgumentException if {@code elementLayout.byteSize()} does not conform to the size of a double value. */ - default MemorySegment allocateArray(ValueLayout elementLayout, double[] array) { + default MemorySegment allocateArray(ValueLayout.OfDouble elementLayout, double[] array) { return copyArrayWithSwapIfNeeded(array, elementLayout, MemorySegment::ofArray); } - /** - * Allocate a block of memory with given layout and initialize it with given address array. - * The address value of each array element might be narrowed according to the platform address size (see {@link MemoryLayouts#ADDRESS}). - * @implSpec the default implementation for this method calls {@code this.allocateArray(layout, array.length)}. - * @param elementLayout the element layout of the array to be allocated. - * @param array the array to be copied on the newly allocated memory block. - * @return a segment for the newly allocated memory block. - * @throws IllegalArgumentException if {@code layout.byteSize() != MemoryLayouts.ADDRESS.byteSize()}. - */ - default MemorySegment allocateArray(ValueLayout elementLayout, Addressable[] array) { - Objects.requireNonNull(elementLayout); - Objects.requireNonNull(array); - Stream.of(array).forEach(Objects::requireNonNull); - if (MemoryLayouts.ADDRESS.byteSize() != elementLayout.byteSize()) { - throw new IllegalArgumentException("Layout size mismatch - " + elementLayout.byteSize() + " != " + MemoryLayouts.ADDRESS.byteSize()); - } - return switch ((int)elementLayout.byteSize()) { - case 4 -> copyArrayWithSwapIfNeeded(Stream.of(array) - .mapToInt(a -> (int)a.address().toRawLongValue()).toArray(), - elementLayout, MemorySegment::ofArray); - case 8 -> copyArrayWithSwapIfNeeded(Stream.of(array) - .mapToLong(a -> a.address().toRawLongValue()).toArray(), - elementLayout, MemorySegment::ofArray); - default -> throw new UnsupportedOperationException("Unsupported pointer size"); // should not get here - }; - } - private MemorySegment copyArrayWithSwapIfNeeded(Z array, ValueLayout elementLayout, Function heapSegmentFactory) { Objects.requireNonNull(array); Objects.requireNonNull(elementLayout); - Utils.checkPrimitiveCarrierCompat(array.getClass().componentType(), elementLayout); - MemorySegment addr = allocate(MemoryLayout.sequenceLayout(Array.getLength(array), elementLayout)); - if (elementLayout.byteSize() == 1 || (elementLayout.order() == ByteOrder.nativeOrder())) { - addr.copyFrom(heapSegmentFactory.apply(array)); - } else { - ((AbstractMemorySegmentImpl)addr).copyFromSwap(heapSegmentFactory.apply(array), elementLayout.byteSize()); - } + int size = Array.getLength(array); + MemorySegment addr = allocate(MemoryLayout.sequenceLayout(size, elementLayout)); + MemorySegment.copy(heapSegmentFactory.apply(array), elementLayout, 0, + addr, elementLayout.withOrder(ByteOrder.nativeOrder()), 0, size); return addr; } /** - * Allocate a block of memory with given layout. + * Allocate a memory segment with given layout. * @implSpec the default implementation for this method calls {@code this.allocate(layout.byteSize(), layout.byteAlignment())}. * @param layout the layout of the block of memory to be allocated. * @return a segment for the newly allocated memory block. @@ -335,7 +306,7 @@ public interface SegmentAllocator { } /** - * Allocate a block of memory corresponding to an array with given element layout and size. + * Allocate a memory segment with given element layout and size. * @implSpec the default implementation for this method calls {@code this.allocate(MemoryLayout.sequenceLayout(count, elementLayout))}. * @param elementLayout the array element layout. * @param count the array element count. @@ -347,7 +318,8 @@ public interface SegmentAllocator { } /** - * Allocate a block of memory with given size, with default alignment (1-byte aligned). + * Allocate a memory segment with given size + * and default alignment constraints (1-byte aligned). * @implSpec the default implementation for this method calls {@code this.allocate(bytesSize, 1)}. * @param bytesSize the size (in bytes) of the block of memory to be allocated. * @return a segment for the newly allocated memory block. @@ -357,7 +329,7 @@ public interface SegmentAllocator { } /** - * Allocate a block of memory with given size and alignment constraint. + * Allocate a memory segment with given size and alignment constraints. * @param bytesSize the size (in bytes) of the block of memory to be allocated. * @param bytesAlignment the alignment (in bytes) of the block of memory to be allocated. * @return a segment for the newly allocated memory block. @@ -365,74 +337,91 @@ public interface SegmentAllocator { MemorySegment allocate(long bytesSize, long bytesAlignment); /** - * Returns a native arena-based allocator which allocates a single memory segment, of given size (using malloc), - * and then responds to allocation request by returning different slices of that same segment - * (until no further allocation is possible). - * This can be useful when clients want to perform multiple allocation requests while avoiding the cost associated - * with allocating a new off-heap memory region upon each allocation request. - *

    - * An allocator associated with a shared resource scope is thread-safe and allocation requests may be - * performed concurrently; conversely, if the arena allocator is associated with a confined resource scope, - * allocation requests can only occur from the thread owning the allocator's resource scope. - *

    - * The returned allocator might throw an {@link OutOfMemoryError} if an incoming allocation request exceeds - * the allocator capacity. + * Returns a native unbounded arena-based allocator, with predefined block size and maximum arena size, + * associated with the provided scope. Equivalent to the following code: + * {@snippet lang=java : + * SegmentAllocator.newNativeArena(Long.MAX_VALUE, predefinedBlockSize, scope); + * } * - * @param size the size (in bytes) of the allocation arena. - * @param scope the scope associated with the segments returned by this allocator. - * @return a new bounded arena-based allocator - * @throws IllegalArgumentException if {@code size <= 0}. + * @param scope the scope associated with the segments returned by the arena-based allocator. + * @return a new unbounded arena-based allocator * @throws IllegalStateException if {@code scope} has been already closed, or if access occurs from a thread other * than the thread owning {@code scope}. */ - static SegmentAllocator arenaAllocator(long size, ResourceScope scope) { - Objects.requireNonNull(scope); - return scope.ownerThread() == null ? - new ArenaAllocator.BoundedSharedArenaAllocator(scope, size) : - new ArenaAllocator.BoundedArenaAllocator(scope, size); + static SegmentAllocator newNativeArena(ResourceScope scope) { + return newNativeArena(Long.MAX_VALUE, ArenaAllocator.DEFAULT_BLOCK_SIZE, scope); } /** - * Returns a native unbounded arena-based allocator. + * Returns a native unbounded arena-based allocator, with block size set to the specified arena size, associated with + * the provided scope, with given arena size. Equivalent to the following code: + * {@snippet lang=java : + * SegmentAllocator.newNativeArena(arenaSize, arenaSize, scope); + * } + * + * @param arenaSize the size (in bytes) of the allocation arena. + * @param scope the scope associated with the segments returned by the arena-based allocator. + * @return a new unbounded arena-based allocator + * @throws IllegalArgumentException if {@code arenaSize <= 0}. + * @throws IllegalStateException if {@code scope} has been already closed, or if access occurs from a thread other + * than the thread owning {@code scope}. + */ + static SegmentAllocator newNativeArena(long arenaSize, ResourceScope scope) { + return newNativeArena(arenaSize, arenaSize, scope); + } + + /** + * Returns a native arena-based allocator, associated with the provided scope, with given arena size and block size. *

    - * The returned allocator allocates a memory segment {@code S} of a certain fixed size (using malloc) and then - * responds to allocation requests in one of the following ways: + * The returned allocator {@linkplain MemorySegment#allocateNative(long, ResourceScope) allocates} a memory segment + * {@code S} of the specified block size and then responds to allocation requests in one of the following ways: *

      *
    • if the size of the allocation requests is smaller than the size of {@code S}, and {@code S} has a free * slice {@code S'} which fits that allocation request, return that {@code S'}. *
    • if the size of the allocation requests is smaller than the size of {@code S}, and {@code S} has no free - * slices which fits that allocation request, allocate a new segment {@code S'} (using malloc), which has same size as {@code S} + * slices which fits that allocation request, allocate a new segment {@code S'}, which has same size as {@code S} * and set {@code S = S'}; the allocator then tries to respond to the same allocation request again. - *
    • if the size of the allocation requests is bigger than the size of {@code S}, allocate a new segment {@code S'} - * (using malloc), which has a sufficient size to satisfy the allocation request, and return {@code S'}. + *
    • if the size of the allocation requests is bigger than the size of {@code S}, allocate a new segment {@code S'}, + * which has a sufficient size to satisfy the allocation request, and return {@code S'}. *
    *

    * This segment allocator can be useful when clients want to perform multiple allocation requests while avoiding the * cost associated with allocating a new off-heap memory region upon each allocation request. *

    - * An allocator associated with a shared resource scope is thread-safe and allocation requests may be - * performed concurrently; conversely, if the arena allocator is associated with a confined resource scope, - * allocation requests can only occur from the thread owning the allocator's resource scope. - *

    - * The returned allocator might throw an {@link OutOfMemoryError} if an incoming allocation request exceeds - * the system capacity. + * The returned allocator might throw an {@link OutOfMemoryError} if the total memory allocated with this allocator + * exceeds the arena size, or the system capacity. Furthermore, the returned allocator is not thread safe. + * Concurrent allocation needs to be guarded with synchronization primitives. * - * @param scope the scope associated with the segments returned by this allocator. + * @param arenaSize the size (in bytes) of the allocation arena. + * @param blockSize the block size associated with the arena-based allocator. + * @param scope the scope associated with the segments returned by the arena-based allocator. * @return a new unbounded arena-based allocator + * @throws IllegalArgumentException if {@code blockSize <= 0}, if {@code arenaSize <= 0} or if {@code arenaSize < blockSize}. * @throws IllegalStateException if {@code scope} has been already closed, or if access occurs from a thread other * than the thread owning {@code scope}. */ - static SegmentAllocator arenaAllocator(ResourceScope scope) { + static SegmentAllocator newNativeArena(long arenaSize, long blockSize, ResourceScope scope) { Objects.requireNonNull(scope); - return scope.ownerThread() == null ? - new ArenaAllocator.UnboundedSharedArenaAllocator(scope) : - new ArenaAllocator.UnboundedArenaAllocator(scope); + if (blockSize <= 0) { + throw new IllegalArgumentException("Invalid block size: " + blockSize); + } + if (arenaSize <= 0 || arenaSize < blockSize) { + throw new IllegalArgumentException("Invalid arena size: " + arenaSize); + } + return new ArenaAllocator(blockSize, arenaSize, scope); } /** * Returns a segment allocator which responds to allocation requests by recycling a single segment; that is, * each new allocation request will return a new slice starting at the segment offset {@code 0} (alignment - * constraints are ignored by this allocator). This can be useful to limit allocation requests in case a client + * constraints are ignored by this allocator), hence the name prefix allocator. + * Equivalent to (but likely more efficient than) the following code: + * {@snippet lang=java : + * MemorySegment segment = ... + * SegmentAllocator prefixAllocator = (size, align) -> segment.asSlice(0, size); + * } + *

    + * This allocator can be useful to limit allocation requests in case a client * knows that they have fully processed the contents of the allocated segment before the subsequent allocation request * takes place. *

    @@ -442,25 +431,41 @@ public interface SegmentAllocator { * @param segment the memory segment to be recycled by the returned allocator. * @return an allocator which recycles an existing segment upon each new allocation request. */ - static SegmentAllocator ofSegment(MemorySegment segment) { + static SegmentAllocator prefixAllocator(MemorySegment segment) { Objects.requireNonNull(segment); - return (size, align) -> segment.asSlice(0, size); + return (AbstractMemorySegmentImpl)segment; } /** - * Returns a native allocator which responds to allocation requests by allocating new segments - * bound by the given resource scope, using the {@link MemorySegment#allocateNative(long, long, ResourceScope)} - * factory. This code is equivalent (but likely more efficient) to the following: - *

    {@code
    -    Resource scope = ...
    -    SegmentAllocator scoped = (size, align) -> MemorySegment.allocateNative(size, align, scope);
    -     * }
    + * Returns a native allocator, associated with the provided scope. Equivalent to (but likely more efficient than) + * the following code: + * {@snippet lang=java : + * ResourceScope scope = ... + * SegmentAllocator nativeAllocator = (size, align) -> MemorySegment.allocateNative(size, align, scope); + * } * - * @param scope the resource scope associated with the segments created by the returned allocator. - * @return an allocator which allocates new memory segment bound by the provided resource scope. + * @param scope the scope associated with the returned allocator. + * @return a native allocator, associated with the provided scope. */ - static SegmentAllocator ofScope(ResourceScope scope) { + static SegmentAllocator nativeAllocator(ResourceScope scope) { Objects.requireNonNull(scope); return (ResourceScopeImpl)scope; } + + /** + * Returns a native allocator which allocates segments in independent {@linkplain ResourceScope#newImplicitScope() implicit scopes}. + * Equivalent to (but likely more efficient than) the following code: + * {@snippet lang=java : + * SegmentAllocator implicitAllocator = (size, align) -> MemorySegment.allocateNative(size, align, ResourceScope.newImplicitScope()); + * } + * + * @return a native allocator which allocates segments in independent {@linkplain ResourceScope#newImplicitScope() implicit scopes}. + */ + static SegmentAllocator implicitAllocator() { + class Holder { + static final SegmentAllocator IMPLICIT_ALLOCATOR = (size, align) -> + MemorySegment.allocateNative(size, align, ResourceScope.newImplicitScope()); + } + return Holder.IMPLICIT_ALLOCATOR; + } } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/SequenceLayout.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/SequenceLayout.java index 8b79cb2fb9f1bf954560bb1b13717f982c871bbb..13ac71927288931165273ba74dd008f5d1721af8 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/SequenceLayout.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/SequenceLayout.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,32 +25,30 @@ */ package jdk.incubator.foreign; -import java.lang.constant.Constable; import java.lang.constant.ConstantDescs; import java.lang.constant.DynamicConstantDesc; -import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.OptionalLong; /** * A sequence layout. A sequence layout is used to denote a repetition of a given layout, also called the sequence layout's element layout. - * The repetition count, where it exists (e.g. for finite sequence layouts) is said to be the the sequence layout's element count. + * The repetition count, where it exists (e.g. for finite sequence layouts) is said to be the sequence layout's element count. * A finite sequence layout can be thought of as a group layout where the sequence layout's element layout is repeated a number of times * that is equal to the sequence layout's element count. In other words this layout: * - *
    {@code
    -MemoryLayout.sequenceLayout(3, MemoryLayout.valueLayout(32, ByteOrder.BIG_ENDIAN));
    - * }
    + * {@snippet lang=java : + * MemoryLayout.sequenceLayout(3, ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN)); + * } * * is equivalent to the following layout: * - *
    {@code
    -MemoryLayout.structLayout(
    -    MemoryLayout.valueLayout(32, ByteOrder.BIG_ENDIAN),
    -    MemoryLayout.valueLayout(32, ByteOrder.BIG_ENDIAN),
    -    MemoryLayout.valueLayout(32, ByteOrder.BIG_ENDIAN));
    - * }
    + * {@snippet lang=java : + * MemoryLayout.structLayout( + * ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN), + * ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN), + * ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN)); + * } * *

    * This is a value-based @@ -72,13 +70,13 @@ public final class SequenceLayout extends AbstractLayout implements MemoryLayout private final MemoryLayout elementLayout; SequenceLayout(OptionalLong elemCount, MemoryLayout elementLayout) { - this(elemCount, elementLayout, elementLayout.bitAlignment(), Map.of()); + this(elemCount, elementLayout, elementLayout.bitAlignment(), Optional.empty()); } - SequenceLayout(OptionalLong elemCount, MemoryLayout elementLayout, long alignment, Map attributes) { + SequenceLayout(OptionalLong elemCount, MemoryLayout elementLayout, long alignment, Optional name) { super(elemCount.isPresent() && AbstractLayout.optSize(elementLayout).isPresent() ? OptionalLong.of(elemCount.getAsLong() * elementLayout.bitSize()) : - OptionalLong.empty(), alignment, attributes); + OptionalLong.empty(), alignment, name); this.elemCount = elemCount; this.elementLayout = elementLayout; } @@ -110,7 +108,7 @@ public final class SequenceLayout extends AbstractLayout implements MemoryLayout */ public SequenceLayout withElementCount(long elementCount) { AbstractLayout.checkSize(elementCount, true); - return new SequenceLayout(OptionalLong.of(elementCount), elementLayout, alignment, attributes); + return new SequenceLayout(OptionalLong.of(elementCount), elementLayout, alignment, name()); } /** @@ -121,22 +119,22 @@ public final class SequenceLayout extends AbstractLayout implements MemoryLayout * as the flattened projection of this sequence layout. *

    * For instance, given a sequence layout of the kind: - *

    {@code
    -    var seq = MemoryLayout.sequenceLayout(4, MemoryLayout.sequenceLayout(3, MemoryLayouts.JAVA_INT));
    -     * }
    + * {@snippet lang=java : + * var seq = MemoryLayout.sequenceLayout(4, MemoryLayout.sequenceLayout(3, ValueLayout.JAVA_INT)); + * } * calling {@code seq.reshape(2, 6)} will yield the following sequence layout: - *
    {@code
    -    var reshapeSeq = MemoryLayout.sequenceLayout(2, MemoryLayout.sequenceLayout(6, MemoryLayouts.JAVA_INT));
    -     * }
    + * {@snippet lang=java : + * var reshapeSeq = MemoryLayout.sequenceLayout(2, MemoryLayout.sequenceLayout(6, ValueLayout.JAVA_INT)); + * } *

    * If one of the provided element count is the special value {@code -1}, then the element * count in that position will be inferred from the remaining element counts and the * element count of the flattened projection of this layout. For instance, a layout equivalent to * the above {@code reshapeSeq} can also be computed in the following ways: - *

    {@code
    -    var reshapeSeqImplicit1 = seq.reshape(-1, 6);
    -    var reshapeSeqImplicit2 = seq.reshape(2, -1);
    -     * }
    + * {@snippet lang=java : + * var reshapeSeqImplicit1 = seq.reshape(-1, 6); + * var reshapeSeqImplicit2 = seq.reshape(2, -1); + * } * @param elementCounts an array of element counts, of which at most one can be {@code -1}. * @return a new sequence layout where element layouts in the flattened projection of this * sequence layout (see {@link #flatten()}) are re-arranged into one or more nested sequence layouts. @@ -151,7 +149,7 @@ public final class SequenceLayout extends AbstractLayout implements MemoryLayout if (elementCounts.length == 0) { throw new IllegalArgumentException(); } - if (!elementCount().isPresent()) { + if (elementCount().isEmpty()) { throw new UnsupportedOperationException("Cannot reshape a sequence layout whose element count is unspecified"); } SequenceLayout flat = flatten(); @@ -197,26 +195,25 @@ public final class SequenceLayout extends AbstractLayout implements MemoryLayout * This transformation preserves the layout size; nested sequence layout in this sequence layout will * be dropped and their element counts will be incorporated into that of the returned sequence layout. * For instance, given a sequence layout of the kind: - *
    {@code
    -    var seq = MemoryLayout.sequenceLayout(4, MemoryLayout.sequenceLayout(3, MemoryLayouts.JAVA_INT));
    -     * }
    + * {@snippet lang=java : + * var seq = MemoryLayout.sequenceLayout(4, MemoryLayout.sequenceLayout(3, ValueLayout.JAVA_INT)); + * } * calling {@code seq.flatten()} will yield the following sequence layout: - *
    {@code
    -    var flattenedSeq = MemoryLayout.sequenceLayout(12, MemoryLayouts.JAVA_INT);
    -     * }
    + * {@snippet lang=java : + * var flattenedSeq = MemoryLayout.sequenceLayout(12, ValueLayout.JAVA_INT); + * } * @return a new sequence layout with the same size as this layout (but, possibly, with different * element count), whose element layout is not a sequence layout. * @throws UnsupportedOperationException if this sequence layout, or one of the nested sequence layouts being * flattened, does not have an element count. */ public SequenceLayout flatten() { - if (!elementCount().isPresent()) { + if (elementCount().isEmpty()) { throw badUnboundSequenceLayout(); } long count = elementCount().getAsLong(); MemoryLayout elemLayout = elementLayout(); - while (elemLayout instanceof SequenceLayout) { - SequenceLayout elemSeq = (SequenceLayout)elemLayout; + while (elemLayout instanceof SequenceLayout elemSeq) { count = count * elemSeq.elementCount().orElseThrow(this::badUnboundSequenceLayout); elemLayout = elemSeq.elementLayout(); } @@ -241,10 +238,9 @@ public final class SequenceLayout extends AbstractLayout implements MemoryLayout if (!super.equals(other)) { return false; } - if (!(other instanceof SequenceLayout)) { + if (!(other instanceof SequenceLayout s)) { return false; } - SequenceLayout s = (SequenceLayout)other; return elemCount.equals(s.elemCount) && elementLayout.equals(s.elementLayout); } @@ -254,8 +250,8 @@ public final class SequenceLayout extends AbstractLayout implements MemoryLayout } @Override - SequenceLayout dup(long alignment, Map attributes) { - return new SequenceLayout(elementCount(), elementLayout, alignment, attributes); + SequenceLayout dup(long alignment, Optional name) { + return new SequenceLayout(elementCount(), elementLayout, alignment, name); } @Override @@ -290,12 +286,4 @@ public final class SequenceLayout extends AbstractLayout implements MemoryLayout public SequenceLayout withBitAlignment(long alignmentBits) { return (SequenceLayout)super.withBitAlignment(alignmentBits); } - - /** - * {@inheritDoc} - */ - @Override - public SequenceLayout withAttribute(String name, Constable value) { - return (SequenceLayout)super.withAttribute(name, value); - } } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/SymbolLookup.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/SymbolLookup.java index 7f6a3d8110c1150824f20017b56862f100c1868f..5010703ba151594b002735bcf7ab6fdc0a5ac83a 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/SymbolLookup.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/SymbolLookup.java @@ -26,6 +26,7 @@ package jdk.incubator.foreign; import jdk.internal.access.JavaLangAccess; import jdk.internal.access.SharedSecrets; +import jdk.internal.foreign.ResourceScopeImpl; import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.Reflection; @@ -34,11 +35,11 @@ import java.util.Optional; /** * A symbol lookup. Exposes a lookup operation for searching symbol addresses by name, see {@link SymbolLookup#lookup(String)}. - * A symbol lookup can be used to lookup a symbol in a loaded library. Clients can obtain a {@linkplain #loaderLookup() loader lookup}, + * A symbol lookup can be used to look up a symbol in a loaded library. Clients can obtain a {@linkplain #loaderLookup() loader lookup}, * which can be used to search symbols in libraries loaded by the current classloader (e.g. using {@link System#load(String)}, * or {@link System#loadLibrary(String)}). - * Alternatively, clients can obtain a {@linkplain CLinker#systemLookup() platform-dependent lookup}, to search symbols - * in the standard C library. + * Alternatively, clients can search symbols in the standard C library using a {@link CLinker}, which conveniently + * implements this interface. *

    Unless otherwise specified, passing a {@code null} argument, or an array argument containing one or more {@code null} * elements to a method in this class causes a {@link NullPointerException NullPointerException} to be thrown.

    */ @@ -49,13 +50,15 @@ public interface SymbolLookup { * Looks up a symbol with given name in this lookup. * * @param name the symbol name. - * @return the memory address associated with the symbol (if any). + * @return the lookup symbol (if any). */ - Optional lookup(String name); + Optional lookup(String name); /** * Obtains a symbol lookup suitable to find symbols in native libraries associated with the caller's classloader - * (that is, libraries loaded using {@link System#loadLibrary} or {@link System#load}). + * (that is, libraries loaded using {@link System#loadLibrary} or {@link System#load}). The returned lookup + * returns native symbols backed by a non-closeable, shared scope which keeps the caller's classloader + * reachable. *

    * This method is restricted. * Restricted methods are unsafe, and, if used incorrectly, their use might crash @@ -72,11 +75,13 @@ public interface SymbolLookup { Class caller = Reflection.getCallerClass(); Reflection.ensureNativeAccess(caller); ClassLoader loader = Objects.requireNonNull(caller.getClassLoader()); + ResourceScope loaderScope = ResourceScopeImpl.heapScope(loader); return name -> { Objects.requireNonNull(name); JavaLangAccess javaLangAccess = SharedSecrets.getJavaLangAccess(); MemoryAddress addr = MemoryAddress.ofLong(javaLangAccess.findNative(loader, name)); - return addr == MemoryAddress.NULL? Optional.empty() : Optional.of(addr); + return addr == MemoryAddress.NULL? Optional.empty() : Optional.of(NativeSymbol.ofAddress(name, addr, loaderScope)); }; } + } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/VaList.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/VaList.java new file mode 100644 index 0000000000000000000000000000000000000000..1bc449fa907c374c8d4b973dfc9bf017a6310da7 --- /dev/null +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/VaList.java @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +package jdk.incubator.foreign; + +import jdk.internal.foreign.abi.SharedUtils; +import jdk.internal.foreign.abi.aarch64.linux.LinuxAArch64VaList; +import jdk.internal.foreign.abi.aarch64.macos.MacOsAArch64VaList; +import jdk.internal.foreign.abi.x64.sysv.SysVVaList; +import jdk.internal.foreign.abi.x64.windows.WinVaList; +import jdk.internal.reflect.CallerSensitive; +import jdk.internal.reflect.Reflection; + +import java.util.Objects; +import java.util.function.Consumer; + +/** + * An interface that models a variable argument list, similar in functionality to a C {@code va_list}. + *

    + * A variable argument list is a stateful cursor used to iterate over a set of arguments. A variable argument list + * can be passed by reference e.g. to a {@linkplain CLinker#downcallHandle(FunctionDescriptor) downcall method handle}. + *

    + * Per the C specification (see C standard 6.5.2.2 Function calls - item 6), + * arguments to variadic calls are erased by way of 'default argument promotions', + * which erases integral types by way of integer promotion (see C standard 6.3.1.1 - item 2), + * and which erases all {@code float} arguments to {@code double}. + *

    + * As such, this interface only supports reading {@code int}, {@code double}, + * and any other type that fits into a {@code long}. + * + * This class is not thread safe, and all accesses should occur within a single thread + * (regardless of the scope associated with the variable arity list). + * + *

    Unless otherwise specified, passing a {@code null} argument, or an array argument containing one or more {@code null} + * elements to a method in this class causes a {@link NullPointerException NullPointerException} to be thrown.

    + */ +sealed public interface VaList extends Addressable permits WinVaList, SysVVaList, LinuxAArch64VaList, MacOsAArch64VaList, SharedUtils.EmptyVaList { + + /** + * Reads the next value as an {@code int} and advances this variable argument list's position. The behavior of this + * method is equivalent to the C {@code va_arg} function. + * + * @param layout the layout of the value to be read. + * @return the {@code int} value read from this variable argument list. + * @throws IllegalStateException if the scope associated with this variable argument list has been closed, or if access occurs from + * a thread other than the thread owning that scope. + */ + int nextVarg(ValueLayout.OfInt layout); + + /** + * Reads the next value as a {@code long} and advances this variable argument list's position. The behavior of this + * method is equivalent to the C {@code va_arg} function. + * + * @param layout the layout of the value to be read. + * @return the {@code long} value read from this variable argument list. + * @throws IllegalStateException if the scope associated with this variable argument list has been closed, or if access occurs from + * a thread other than the thread owning that scope. + */ + long nextVarg(ValueLayout.OfLong layout); + + /** + * Reads the next value as a {@code double} and advances this variable argument list's position. The behavior of this + * method is equivalent to the C {@code va_arg} function. + * + * @param layout the layout of the value + * @return the {@code double} value read from this variable argument list. + * @throws IllegalStateException if the scope associated with this variable argument list has been closed, or if access occurs from + * a thread other than the thread owning that scope. + */ + double nextVarg(ValueLayout.OfDouble layout); + + /** + * Reads the next value as a {@code MemoryAddress} and advances this variable argument list's position. The behavior of this + * method is equivalent to the C {@code va_arg} function. + * + * @param layout the layout of the value to be read. + * @return the {@code MemoryAddress} value read from this variable argument list. + * @throws IllegalStateException if the scope associated with this variable argument list has been closed, or if access occurs from + * a thread other than the thread owning that scope. + */ + MemoryAddress nextVarg(ValueLayout.OfAddress layout); + + /** + * Reads the next value as a {@code MemorySegment}, and advances this variable argument list's position. The behavior of this + * method is equivalent to the C {@code va_arg} function. The provided group layout must correspond to a C struct or union + * type. + *

    + * How the value is read in the returned segment is ABI-dependent: calling this method on a group layout + * with member layouts {@code L_1, L_2, ... L_n} is not guaranteed to be semantically equivalent to perform distinct + * calls to {@code nextVarg} for each of the layouts in {@code L_1, L_2, ... L_n}. + *

    + * The memory segment returned by this method will be allocated using the given {@link SegmentAllocator}. + * + * @param layout the layout of the value to be read. + * @param allocator the allocator to be used to create a segment where the contents of the variable argument list + * will be copied. + * @return the {@code MemorySegment} value read from this variable argument list. + * @throws IllegalStateException if the scope associated with this variable argument list has been closed, or if access occurs from + * a thread other than the thread owning that scope. + */ + MemorySegment nextVarg(GroupLayout layout, SegmentAllocator allocator); + + /** + * Skips a number of elements with the given memory layouts, and advances this variable argument list's position. + * + * @param layouts the layouts of the values to be skipped. + * @throws IllegalStateException if the scope associated with this variable argument list has been closed, or if access occurs from + * a thread other than the thread owning that scope. + */ + void skip(MemoryLayout... layouts); + + /** + * Returns the resource scope associated with this variable argument list. + * @return the resource scope associated with this variable argument list. + */ + ResourceScope scope(); + + /** + * Copies this variable argument list at its current position into a new variable argument list associated + * with the same scope as this variable argument list. The behavior of this method is equivalent to the C + * {@code va_copy} function. + *

    + * Copying is useful to traverse the variable argument list elements, starting from the current position, + * without affecting the state of the original variable argument list, essentially allowing the elements to be + * traversed multiple times. + * + * @return a copy of this variable argument list. + * @throws IllegalStateException if the scope associated with this variable argument list has been closed, or if access occurs from + * a thread other than the thread owning that scope. + */ + VaList copy(); + + /** + * Returns the memory address associated with this variable argument list. + * @throws IllegalStateException if the scope associated with this variable argument list has been closed, or if access occurs from + * a thread other than the thread owning that scope. + * @return The memory address associated with this variable argument list. + */ + @Override + MemoryAddress address(); + + /** + * Constructs a new variable argument list from a memory address pointing to an existing variable argument list, + * with given resource scope. + *

    + * This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * restricted methods, and use safe and supported functionalities, where possible. + * + * @param address a memory address pointing to an existing variable argument list. + * @param scope the resource scope to be associated with the returned variable argument list. + * @return a new variable argument list backed by the memory region at {@code address}. + * @throws IllegalStateException if {@code scope} has been already closed, or if access occurs from a thread other + * than the thread owning {@code scope}. + * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option + * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or + * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + */ + @CallerSensitive + static VaList ofAddress(MemoryAddress address, ResourceScope scope) { + Reflection.ensureNativeAccess(Reflection.getCallerClass()); + Objects.requireNonNull(address); + Objects.requireNonNull(scope); + return SharedUtils.newVaListOfAddress(address, scope); + } + + /** + * Constructs a new variable argument list using a builder (see {@link Builder}), with a given resource scope. + *

    + * If this method needs to allocate native memory, such memory will be managed by the given + * {@linkplain ResourceScope resource scope}, and will be released when the resource scope is {@linkplain ResourceScope#close closed}. + *

    + * Note that when there are no elements added to the created va list, + * this method will return the same as {@link #empty()}. + * + * @param actions a consumer for a builder (see {@link Builder}) which can be used to specify the elements + * of the underlying variable argument list. + * @param scope scope the scope to be associated with the new variable arity list. + * @return a new variable argument list. + * @throws IllegalStateException if {@code scope} has been already closed, or if access occurs from a thread other + * than the thread owning {@code scope}. + */ + static VaList make(Consumer actions, ResourceScope scope) { + Objects.requireNonNull(actions); + Objects.requireNonNull(scope); + return SharedUtils.newVaList(actions, scope); + } + + /** + * Returns an empty variable argument list, associated with the {@linkplain ResourceScope#globalScope() global} + * scope. The resulting variable argument list does not contain any argument, and throws {@link UnsupportedOperationException} + * on all operations, except for {@link #scope()}, {@link #copy()} and {@link #address()}. + * @return an empty variable argument list. + */ + static VaList empty() { + return SharedUtils.emptyVaList(); + } + + /** + * A builder interface used to construct a variable argument list. + * + *

    Unless otherwise specified, passing a {@code null} argument, or an array argument containing one or more {@code null} + * elements to a method in this class causes a {@link NullPointerException NullPointerException} to be thrown.

    + */ + sealed interface Builder permits WinVaList.Builder, SysVVaList.Builder, LinuxAArch64VaList.Builder, MacOsAArch64VaList.Builder { + + /** + * Writes an {@code int} value to the variable argument list being constructed. + * + * @param layout the layout of the value to be written. + * @param value the {@code int} value to be written. + * @return this builder. + */ + Builder addVarg(ValueLayout.OfInt layout, int value); + + /** + * Writes a {@code long} value to the variable argument list being constructed. + * + * @param layout the layout of the value to be written. + * @param value the {@code long} value to be written. + * @return this builder. + */ + Builder addVarg(ValueLayout.OfLong layout, long value); + + /** + * Writes a {@code double} value to the variable argument list being constructed. + * + * @param layout the layout of the value to be written. + * @param value the {@code double} value to be written. + * @return this builder. + */ + Builder addVarg(ValueLayout.OfDouble layout, double value); + + /** + * Writes an {@code Addressable} value to the variable argument list being constructed. + * + * @param layout the layout of the value to be written. + * @param value the {@code Addressable} value to be written. + * @return this builder. + */ + Builder addVarg(ValueLayout.OfAddress layout, Addressable value); + + /** + * Writes a {@code MemorySegment} value, with given layout, to the variable argument list being constructed. + * + * @param layout the layout of the value to be written. + * @param value the {@code MemorySegment} whose contents will be copied. + * @return this builder. + */ + Builder addVarg(GroupLayout layout, MemorySegment value); + } +} diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/ValueLayout.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/ValueLayout.java index 26271da07da6f64719e4fc2765124521e597a260..3ce22d8743f3a35d462741a13549cf64a79216dd 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/ValueLayout.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/ValueLayout.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,19 +25,30 @@ */ package jdk.incubator.foreign; -import java.lang.constant.Constable; +import jdk.internal.foreign.Utils; +import jdk.internal.misc.Unsafe; +import jdk.internal.vm.annotation.ForceInline; +import jdk.internal.vm.annotation.Stable; +import sun.invoke.util.Wrapper; + import java.lang.constant.ConstantDescs; import java.lang.constant.DynamicConstantDesc; +import java.lang.invoke.VarHandle; import java.nio.ByteOrder; -import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.OptionalLong; /** * A value layout. A value layout is used to model the memory layout associated with values of basic data types, such as integral types - * (either signed or unsigned) and floating-point types. Each value layout has a size and a byte order (see {@link ByteOrder}). - * + * (either signed or unsigned) and floating-point types. Each value layout has a size, an alignment, a {@linkplain ByteOrder byte order}) + * and a carrier, that is, the Java type that should be used when {@linkplain MemorySegment#get(OfInt, long) accessing} + * a memory region using the value layout. + *

    + * This class defines useful value layout constants for Java primitive types and addresses. + * The layout constants in this class make implicit alignment and byte-ordering assumption: all layout + * constants in this class are byte-aligned, and their byte order is set to the {@linkplain ByteOrder#nativeOrder() platform default}, + * thus making it easy to work with other APIs, such as arrays and {@link java.nio.ByteBuffer}. *

    * This is a value-based * class; programmers should treat instances that are @@ -52,17 +63,22 @@ import java.util.OptionalLong; * @implSpec * This class is immutable and thread-safe. */ -public final class ValueLayout extends AbstractLayout implements MemoryLayout { +public sealed class ValueLayout extends AbstractLayout implements MemoryLayout { + private final Class carrier; private final ByteOrder order; - ValueLayout(ByteOrder order, long size) { - this(order, size, size, Map.of()); + private static final int ADDRESS_SIZE_BITS = Unsafe.ADDRESS_SIZE * 8; + + ValueLayout(Class carrier, ByteOrder order, long size) { + this(carrier, order, size, size, Optional.empty()); } - ValueLayout(ByteOrder order, long size, long alignment, Map attributes) { - super(OptionalLong.of(size), alignment, attributes); + ValueLayout(Class carrier, ByteOrder order, long size, long alignment, Optional name) { + super(OptionalLong.of(size), alignment, name); + this.carrier = carrier; this.order = order; + checkCarrierSize(carrier, size); } /** @@ -81,7 +97,7 @@ public final class ValueLayout extends AbstractLayout implements MemoryLayout { * @return a new value layout with given byte order. */ public ValueLayout withOrder(ByteOrder order) { - return new ValueLayout(Objects.requireNonNull(order), bitSize(), alignment, attributes); + return new ValueLayout(carrier, Objects.requireNonNull(order), bitSize(), alignment, name()); } @Override @@ -99,29 +115,37 @@ public final class ValueLayout extends AbstractLayout implements MemoryLayout { if (!super.equals(other)) { return false; } - if (!(other instanceof ValueLayout)) { + if (!(other instanceof ValueLayout v)) { return false; } - ValueLayout v = (ValueLayout)other; - return order.equals(v.order) && + return carrier.equals(v.carrier) && + order.equals(v.order) && bitSize() == v.bitSize() && alignment == v.alignment; } + /** + * Returns the carrier associated with this value layout. + * @return the carrier associated with this value layout. + */ + public Class carrier() { + return carrier; + } + @Override public int hashCode() { return Objects.hash(super.hashCode(), order, bitSize(), alignment); } @Override - ValueLayout dup(long alignment, Map attributes) { - return new ValueLayout(order, bitSize(), alignment, attributes); + ValueLayout dup(long alignment, Optional name) { + return new ValueLayout(carrier, order, bitSize(), alignment, name()); } @Override public Optional> describeConstable() { return Optional.of(decorateLayoutConstant(DynamicConstantDesc.ofNamed(ConstantDescs.BSM_INVOKE, "value", - CD_VALUE_LAYOUT, MH_VALUE, bitSize(), order == ByteOrder.BIG_ENDIAN ? BIG_ENDIAN : LITTLE_ENDIAN))); + CD_VALUE_LAYOUT, MH_VALUE, carrier().describeConstable().get(), order == ByteOrder.BIG_ENDIAN ? BIG_ENDIAN : LITTLE_ENDIAN))); } //hack: the declarations below are to make javadoc happy; we could have used generics in AbstractLayout @@ -143,11 +167,439 @@ public final class ValueLayout extends AbstractLayout implements MemoryLayout { return (ValueLayout)super.withBitAlignment(alignmentBits); } + static void checkCarrierSize(Class carrier, long size) { + if (!isValidCarrier(carrier)) { + throw new IllegalArgumentException("Invalid carrier: " + carrier.getName()); + } + if (carrier == MemoryAddress.class && size != ADDRESS_SIZE_BITS) { + throw new IllegalArgumentException("Address size mismatch: " + ADDRESS_SIZE_BITS + " != " + size); + } + if (carrier.isPrimitive()) { + int expectedSize = carrier == boolean.class ? 8 : Wrapper.forPrimitiveType(carrier).bitWidth(); + if (size != expectedSize) { + throw new IllegalArgumentException("Carrier size mismatch: " + carrier.getName() + " != " + size); + } + } + } + + static boolean isValidCarrier(Class carrier) { + return carrier == boolean.class + || carrier == byte.class + || carrier == short.class + || carrier == char.class + || carrier == int.class + || carrier == long.class + || carrier == float.class + || carrier == double.class + || carrier == MemoryAddress.class; + } + + @Stable + private VarHandle handle; + + @ForceInline + VarHandle accessHandle() { + if (handle == null) { + // this store to stable field is safe, because return value of 'makeMemoryAccessVarHandle' has stable identity + handle = Utils.makeMemoryAccessVarHandle(this, false); + } + return handle; + } + /** - * {@inheritDoc} + * A value layout whose carrier is {@code boolean.class}. */ - @Override - public ValueLayout withAttribute(String name, Constable value) { - return (ValueLayout)super.withAttribute(name, value); + public static final class OfBoolean extends ValueLayout { + OfBoolean(ByteOrder order) { + super(boolean.class, order, 8); + } + + OfBoolean(ByteOrder order, long alignment, Optional name) { + super(boolean.class, order, 8, alignment, name); + } + + @Override + OfBoolean dup(long alignment, Optional name) { + return new OfBoolean(order(), alignment, name); + } + + @Override + public OfBoolean withName(String name) { + return (OfBoolean)super.withName(name); + } + + @Override + public OfBoolean withBitAlignment(long alignmentBits) { + return (OfBoolean)super.withBitAlignment(alignmentBits); + } + + @Override + public OfBoolean withOrder(ByteOrder order) { + Objects.requireNonNull(order); + return new OfBoolean(order, alignment, name()); + } + } + + /** + * A value layout whose carrier is {@code byte.class}. + */ + public static final class OfByte extends ValueLayout { + OfByte(ByteOrder order) { + super(byte.class, order, 8); + } + + OfByte(ByteOrder order, long alignment, Optional name) { + super(byte.class, order, 8, alignment, name); + } + + @Override + OfByte dup(long alignment, Optional name) { + return new OfByte(order(), alignment, name); + } + + @Override + public OfByte withName(String name) { + return (OfByte)super.withName(name); + } + + @Override + public OfByte withBitAlignment(long alignmentBits) { + return (OfByte)super.withBitAlignment(alignmentBits); + } + + @Override + public OfByte withOrder(ByteOrder order) { + Objects.requireNonNull(order); + return new OfByte(order, alignment, name()); + } } + + /** + * A value layout whose carrier is {@code char.class}. + */ + public static final class OfChar extends ValueLayout { + OfChar(ByteOrder order) { + super(char.class, order, 16); + } + + OfChar(ByteOrder order, long alignment, Optional name) { + super(char.class, order, 16, alignment, name); + } + + @Override + OfChar dup(long alignment, Optional name) { + return new OfChar(order(), alignment, name); + } + + @Override + public OfChar withName(String name) { + return (OfChar)super.withName(name); + } + + @Override + public OfChar withBitAlignment(long alignmentBits) { + return (OfChar)super.withBitAlignment(alignmentBits); + } + + @Override + public OfChar withOrder(ByteOrder order) { + Objects.requireNonNull(order); + return new OfChar(order, alignment, name()); + } + } + + /** + * A value layout whose carrier is {@code short.class}. + */ + public static final class OfShort extends ValueLayout { + OfShort(ByteOrder order) { + super(short.class, order, 16); + } + + OfShort(ByteOrder order, long alignment, Optional name) { + super(short.class, order, 16, alignment, name); + } + + @Override + OfShort dup(long alignment, Optional name) { + return new OfShort(order(), alignment, name); + } + + @Override + public OfShort withName(String name) { + return (OfShort)super.withName(name); + } + + @Override + public OfShort withBitAlignment(long alignmentBits) { + return (OfShort)super.withBitAlignment(alignmentBits); + } + + @Override + public OfShort withOrder(ByteOrder order) { + Objects.requireNonNull(order); + return new OfShort(order, alignment, name()); + } + } + + /** + * A value layout whose carrier is {@code int.class}. + */ + public static final class OfInt extends ValueLayout { + OfInt(ByteOrder order) { + super(int.class, order, 32); + } + + OfInt(ByteOrder order, long alignment, Optional name) { + super(int.class, order, 32, alignment, name); + } + + @Override + OfInt dup(long alignment, Optional name) { + return new OfInt(order(), alignment, name); + } + + @Override + public OfInt withName(String name) { + return (OfInt)super.withName(name); + } + + @Override + public OfInt withBitAlignment(long alignmentBits) { + return (OfInt)super.withBitAlignment(alignmentBits); + } + + @Override + public OfInt withOrder(ByteOrder order) { + Objects.requireNonNull(order); + return new OfInt(order, alignment, name()); + } + } + + /** + * A value layout whose carrier is {@code float.class}. + */ + public static final class OfFloat extends ValueLayout { + OfFloat(ByteOrder order) { + super(float.class, order, 32); + } + + OfFloat(ByteOrder order, long alignment, Optional name) { + super(float.class, order, 32, alignment, name); + } + + @Override + OfFloat dup(long alignment, Optional name) { + return new OfFloat(order(), alignment, name); + } + + @Override + public OfFloat withName(String name) { + return (OfFloat)super.withName(name); + } + + @Override + public OfFloat withBitAlignment(long alignmentBits) { + return (OfFloat)super.withBitAlignment(alignmentBits); + } + + @Override + public OfFloat withOrder(ByteOrder order) { + Objects.requireNonNull(order); + return new OfFloat(order, alignment, name()); + } + } + + /** + * A value layout whose carrier is {@code long.class}. + */ + public static final class OfLong extends ValueLayout { + OfLong(ByteOrder order) { + super(long.class, order, 64); + } + + OfLong(ByteOrder order, long alignment, Optional name) { + super(long.class, order, 64, alignment, name); + } + + @Override + OfLong dup(long alignment, Optional name) { + return new OfLong(order(), alignment, name); + } + + @Override + public OfLong withName(String name) { + return (OfLong)super.withName(name); + } + + @Override + public OfLong withBitAlignment(long alignmentBits) { + return (OfLong)super.withBitAlignment(alignmentBits); + } + + @Override + public OfLong withOrder(ByteOrder order) { + Objects.requireNonNull(order); + return new OfLong(order, alignment, name()); + } + } + + /** + * A value layout whose carrier is {@code double.class}. + */ + public static final class OfDouble extends ValueLayout { + OfDouble(ByteOrder order) { + super(double.class, order, 64); + } + + OfDouble(ByteOrder order, long alignment, Optional name) { + super(double.class, order, 64, alignment, name); + } + + @Override + OfDouble dup(long alignment, Optional name) { + return new OfDouble(order(), alignment, name); + } + + @Override + public OfDouble withName(String name) { + return (OfDouble)super.withName(name); + } + + @Override + public OfDouble withBitAlignment(long alignmentBits) { + return (OfDouble)super.withBitAlignment(alignmentBits); + } + + @Override + public OfDouble withOrder(ByteOrder order) { + Objects.requireNonNull(order); + return new OfDouble(order, alignment, name()); + } + } + + /** + * A value layout whose carrier is {@code MemoryAddress.class}. + */ + public static final class OfAddress extends ValueLayout { + OfAddress(ByteOrder order) { + super(MemoryAddress.class, order, ADDRESS_SIZE_BITS); + } + + OfAddress(ByteOrder order, long size, long alignment, Optional name) { + super(MemoryAddress.class, order, size, alignment, name); + } + + @Override + OfAddress dup(long alignment, Optional name) { + return new OfAddress(order(), bitSize(), alignment, name); + } + + @Override + public OfAddress withName(String name) { + return (OfAddress)super.withName(name); + } + + @Override + public OfAddress withBitAlignment(long alignmentBits) { + return (OfAddress)super.withBitAlignment(alignmentBits); + } + + @Override + public OfAddress withOrder(ByteOrder order) { + Objects.requireNonNull(order); + return new OfAddress(order, bitSize(), alignment, name()); + } + } + + /** + * A value layout constant whose size is the same as that of a machine address (e.g. {@code size_t}), + * bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}. + * Equivalent to the following code: + * {@snippet lang=java : + * MemoryLayout.valueLayout(MemoryAddress.class, ByteOrder.nativeOrder()).withBitAlignment(8); + * } + */ + public static final OfAddress ADDRESS = new OfAddress(ByteOrder.nativeOrder()).withBitAlignment(8); + + /** + * A value layout constant whose size is the same as that of a Java {@code byte}, + * bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}. + * Equivalent to the following code: + * {@snippet lang=java : + * MemoryLayout.valueLayout(byte.class, ByteOrder.nativeOrder()).withBitAlignment(8); + * } + */ + public static final OfByte JAVA_BYTE = new OfByte(ByteOrder.nativeOrder()).withBitAlignment(8); + + /** + * A value layout constant whose size is the same as that of a Java {@code boolean}, + * bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}. + * Equivalent to the following code: + * {@snippet lang=java : + * MemoryLayout.valueLayout(boolean.class, ByteOrder.nativeOrder()).withBitAlignment(8); + * } + */ + public static final OfBoolean JAVA_BOOLEAN = new OfBoolean(ByteOrder.nativeOrder()).withBitAlignment(8); + + /** + * A value layout constant whose size is the same as that of a Java {@code char}, + * bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}. + * Equivalent to the following code: + * {@snippet lang=java : + * MemoryLayout.valueLayout(char.class, ByteOrder.nativeOrder()).withBitAlignment(8); + * } + */ + public static final OfChar JAVA_CHAR = new OfChar(ByteOrder.nativeOrder()).withBitAlignment(8); + + /** + * A value layout constant whose size is the same as that of a Java {@code short}, + * bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}. + * Equivalent to the following code: + * {@snippet lang=java : + * MemoryLayout.valueLayout(short.class, ByteOrder.nativeOrder()).withBitAlignment(8); + * } + */ + public static final OfShort JAVA_SHORT = new OfShort(ByteOrder.nativeOrder()).withBitAlignment(8); + + /** + * A value layout constant whose size is the same as that of a Java {@code int}, + * bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}. + * Equivalent to the following code: + * {@snippet lang=java : + * MemoryLayout.valueLayout(int.class, ByteOrder.nativeOrder()).withBitAlignment(8); + * } + */ + public static final OfInt JAVA_INT = new OfInt(ByteOrder.nativeOrder()).withBitAlignment(8); + + /** + * A value layout constant whose size is the same as that of a Java {@code long}, + * bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}. + * Equivalent to the following code: + * {@snippet lang=java : + * MemoryLayout.valueLayout(long.class, ByteOrder.nativeOrder()).withBitAlignment(8); + * } + */ + public static final OfLong JAVA_LONG = new OfLong(ByteOrder.nativeOrder()) + .withBitAlignment(8); + + /** + * A value layout constant whose size is the same as that of a Java {@code float}, + * bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}. + * Equivalent to the following code: + * {@snippet lang=java : + * MemoryLayout.valueLayout(float.class, ByteOrder.nativeOrder()).withBitAlignment(8); + * } + */ + public static final OfFloat JAVA_FLOAT = new OfFloat(ByteOrder.nativeOrder()).withBitAlignment(8); + + /** + * A value layout constant whose size is the same as that of a Java {@code double}, + * bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}. + * Equivalent to the following code: + * {@snippet lang=java : + * MemoryLayout.valueLayout(double.class, ByteOrder.nativeOrder()).withBitAlignment(8); + * } + */ + public static final OfDouble JAVA_DOUBLE = new OfDouble(ByteOrder.nativeOrder()).withBitAlignment(8); } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/package-info.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/package-info.java index d4d9a9356cef0abb83aaef549cf91c97dc83d5b7..3621495d064732809b4c3e97be652ed8c6b2666f 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/package-info.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,12 +30,11 @@ *

    Foreign memory access

    * *

    - * The key abstractions introduced to support foreign memory access are {@link jdk.incubator.foreign.MemorySegment} and {@link jdk.incubator.foreign.MemoryAddress}. - * The first models a contiguous memory region, which can reside either inside or outside the Java heap; the latter models an address - which also can - * reside either inside or outside the Java heap (and can sometimes be expressed as an offset into a given segment). + * The main abstractions introduced to support foreign memory access is {@link jdk.incubator.foreign.MemorySegment}, which + * models a contiguous memory region, which can reside either inside or outside the Java heap. * A memory segment represents the main access coordinate of a memory access var handle, which can be obtained * using the combinator methods defined in the {@link jdk.incubator.foreign.MemoryHandles} class; a set of - * common dereference operations is provided also by the {@link jdk.incubator.foreign.MemoryAccess} class, which can + * common dereference and copy operations is provided also by the {@link jdk.incubator.foreign.MemorySegment} class, which can * be useful for simple, non-structured access. Finally, the {@link jdk.incubator.foreign.MemoryLayout} class * hierarchy enables description of memory layouts and basic operations such as computing the size in bytes of a given * layout, obtain its alignment requirements, and so on. Memory layouts also provide an alternate, more abstract way, to produce @@ -44,19 +43,21 @@ * For example, to allocate an off-heap memory region big enough to hold 10 values of the primitive type {@code int}, and fill it with values * ranging from {@code 0} to {@code 9}, we can use the following code: * - *

    {@code
    -MemorySegment segment = MemorySegment.allocateNative(10 * 4, ResourceScope.newImplicitScope());
    -for (int i = 0 ; i < 10 ; i++) {
    -   MemoryAccess.setIntAtIndex(segment, i, 42);
    -}
    - * }
    + * {@snippet lang=java : + * MemorySegment segment = MemorySegment.allocateNative(10 * 4, ResourceScope.newImplicitScope()); + * for (int i = 0 ; i < 10 ; i++) { + * segment.setAtIndex(ValueLayout.JAVA_INT, i, i); + * } + * } * - * Here create a native memory segment, that is, a memory segment backed by + * This code creates a native memory segment, that is, a memory segment backed by * off-heap memory; the size of the segment is 40 bytes, enough to store 10 values of the primitive type {@code int}. - * Inside a loop, we then initialize the contents of the memory segment using the - * {@link jdk.incubator.foreign.MemoryAccess#setIntAtIndex(jdk.incubator.foreign.MemorySegment, long, int)} helper method; - * more specifically, if we view the memory segment as a set of 10 adjacent slots, - * {@code s[i]}, where {@code 0 <= i < 10}, where the size of each slot is exactly 4 bytes, the initialization logic above will set each slot + * Inside a loop, we then initialize the contents of the memory segment; note how the + * {@linkplain jdk.incubator.foreign.MemorySegment#setAtIndex(ValueLayout.OfInt, long, int) dereference method} + * accepts a {@linkplain jdk.incubator.foreign.ValueLayout value layout}, which specifies the size, alignment constraints, + * byte order as well as the Java type ({@code int}, in this case) associated with the dereference operation. More specifically, + * if we view the memory segment as a set of 10 adjacent slots, {@code s[i]}, where {@code 0 <= i < 10}, + * where the size of each slot is exactly 4 bytes, the initialization logic above will set each slot * so that {@code s[i] = i}, again where {@code 0 <= i < 10}. * *

    Deterministic deallocation

    @@ -68,14 +69,14 @@ for (int i = 0 ; i < 10 ; i++) { * Clients that operate under these assumptions might want to programmatically release the memory associated * with a memory segment. This can be done, using the {@link jdk.incubator.foreign.ResourceScope} abstraction, as shown below: * - *
    {@code
    -try (ResourceScope scope = ResourceScope.newConfinedScope()) {
    -    MemorySegment segment = MemorySegment.allocateNative(10 * 4, scope);
    -    for (int i = 0 ; i < 10 ; i++) {
    -        MemoryAccess.setIntAtIndex(segment, i, 42);
    -    }
    -}
    - * }
    + * {@snippet lang=java : + * try (ResourceScope scope = ResourceScope.newConfinedScope()) { + * MemorySegment segment = MemorySegment.allocateNative(10 * 4, scope); + * for (int i = 0 ; i < 10 ; i++) { + * segment.setAtIndex(ValueLayout.JAVA_INT, i, i); + * } + * } + * } * * This example is almost identical to the prior one; this time we first create a so called resource scope, * which is used to bind the life-cycle of the segment created immediately afterwards. Note the use of the @@ -85,7 +86,7 @@ try (ResourceScope scope = ResourceScope.newConfinedScope()) { *

    Safety

    * * This API provides strong safety guarantees when it comes to memory access. First, when dereferencing a memory segment, - * the access coordinates are validated (upon access), to make sure that access does not occur at an address which resides + * the access coordinates are validated (upon access), to make sure that access does not occur at any address which resides * outside the boundaries of the memory segment used by the dereference operation. We call this guarantee spatial safety; * in other words, access to memory segments is bounds-checked, in the same way as array access is, as described in * Section {@jls 15.10.4} of The Java Language Specification. @@ -96,137 +97,132 @@ try (ResourceScope scope = ResourceScope.newConfinedScope()) { * operation either succeeds - and accesses a valid memory location - or fails. * *

    Foreign function access

    - * The key abstractions introduced to support foreign function access are {@link jdk.incubator.foreign.SymbolLookup} and {@link jdk.incubator.foreign.CLinker}. - * The former is used to lookup symbols inside native libraries; the latter - * provides linking capabilities which allow to model foreign functions as {@link java.lang.invoke.MethodHandle} instances, + * The key abstractions introduced to support foreign function access are {@link jdk.incubator.foreign.SymbolLookup}, + * {@link jdk.incubator.foreign.MemoryAddress} and {@link jdk.incubator.foreign.CLinker}. + * The first is used to look up symbols inside native libraries; the second is used to model native addresses (more on that later), + * while the third provides linking capabilities which allows modelling foreign functions as {@link java.lang.invoke.MethodHandle} instances, * so that clients can perform foreign function calls directly in Java, without the need for intermediate layers of native - * code (as it's the case with the Java Native Interface (JNI)). + * code (as is the case with the Java Native Interface (JNI)). *

    * For example, to compute the length of a string using the C standard library function {@code strlen} on a Linux x64 platform, * we can use the following code: * - *

    {@code
    -      MethodHandle strlen = CLinker.getInstance().downcallHandle(
    -        CLinker.systemLookup().lookup("strlen").get(),
    -        MethodType.methodType(long.class, MemoryAddress.class),
    -        FunctionDescriptor.of(CLinker.C_LONG, CLinker.C_POINTER)
    -      );
    -
    -      try (var scope = ResourceScope.newConfinedScope()) {
    -         var cString = CLinker.toCString("Hello", scope);
    -         long len = (long)strlen.invokeExact(cString.address()); // 5
    -      }
    - * }
    - * - * Here, we lookup the {@code strlen} symbol in the {@linkplain jdk.incubator.foreign.CLinker#systemLookup() system lookup}. - * Then, we obtain a linker instance (see {@link jdk.incubator.foreign.CLinker#getInstance()}) and we use it to - * obtain a method handle which targets the {@code strlen} library symbol. To complete the linking successfully, - * we must provide (i) a {@link java.lang.invoke.MethodType} instance, describing the type of the resulting method handle - * and (ii) a {@link jdk.incubator.foreign.FunctionDescriptor} instance, describing the signature of the {@code strlen} - * function. From this information, the linker will uniquely determine the sequence of steps which will turn - * the method handle invocation (here performed using {@link java.lang.invoke.MethodHandle#invokeExact(java.lang.Object...)}) - * into a foreign function call, according to the rules specified by the platform C ABI. The {@link jdk.incubator.foreign.CLinker} - * class also provides many useful methods for interacting with native code, such as converting Java strings into - * native strings and viceversa (see {@link jdk.incubator.foreign.CLinker#toCString(java.lang.String, ResourceScope)} and - * {@link jdk.incubator.foreign.CLinker#toJavaString(jdk.incubator.foreign.MemorySegment)}, respectively), as - * demonstrated in the above example. + * {@snippet lang=java : + * var linker = CLinker.systemCLinker(); + * MethodHandle strlen = linker.downcallHandle( + * linker.lookup("strlen").get(), + * FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.ADDRESS) + * ); + * + * try (var scope = ResourceScope.newConfinedScope()) { + * var cString = MemorySegment.allocateNative(5 + 1, scope); + * cString.setUtf8String("Hello"); + * long len = (long)strlen.invoke(cString); // 5 + * } + * } + * + * Here, we obtain a {@linkplain jdk.incubator.foreign.CLinker#systemCLinker() linker instance} and we use it + * to {@linkplain jdk.incubator.foreign.CLinker#lookup(java.lang.String) look up} the {@code strlen} symbol in the + * standard C library; a downcall method handle targeting said symbol is subsequently + * {@linkplain jdk.incubator.foreign.CLinker#downcallHandle(jdk.incubator.foreign.FunctionDescriptor) obtained}. + * To complete the linking successfully, we must provide a {@link jdk.incubator.foreign.FunctionDescriptor} instance, + * describing the signature of the {@code strlen} function. + * From this information, the linker will uniquely determine the sequence of steps which will turn + * the method handle invocation (here performed using {@link java.lang.invoke.MethodHandle#invoke(java.lang.Object...)}) + * into a foreign function call, according to the rules specified by the platform C ABI. + * The {@link jdk.incubator.foreign.MemorySegment} class also provides many useful methods for + * interacting with native code, such as converting Java strings + * {@linkplain jdk.incubator.foreign.MemorySegment#setUtf8String(long, java.lang.String) into} native strings and + * {@linkplain jdk.incubator.foreign.MemorySegment#getUtf8String(long) back}, as demonstrated in the above example. * *

    Foreign addresses

    * * When a memory segment is created from Java code, the segment properties (spatial bounds, temporal bounds and confinement) - * are fully known at segment creation. But when interacting with native libraries, clients will often receive raw pointers; - * such pointers have no spatial bounds (example: does the C type {@code char*} refer to a single {@code char} value, - * or an array of {@code char} values, of given size?), no notion of temporal bounds, nor thread-confinement. - *

    - * When clients receive a {@link jdk.incubator.foreign.MemoryAddress} instance from a foreign function call, it might be - * necessary to obtain a {@link jdk.incubator.foreign.MemorySegment} instance to dereference the memory pointed to by that address. - * To do that, clients can proceed in three different ways, described below. + * are fully known at segment creation. But when interacting with native libraries, clients will often receive raw pointers. + * Such pointers have no spatial bounds. For example, the C type {@code char*} can refer to a single {@code char} value, + * or an array of {@code char} values, of given size. Nor do said pointers have any notion of temporal bounds or thread-confinement. *

    - * First, if the memory address is known to belong to a segment the client already owns, a rebase operation can be performed; - * in other words, the client can ask the address what its offset relative to a given segment is, and, then, proceed to dereference - * the original segment accordingly, as follows: - * - *

    {@code
    -MemorySegment segment = MemorySegment.allocateNative(100, scope);
    -...
    -MemoryAddress addr = ... //obtain address from native code
    -int x = MemoryAccess.getIntAtOffset(segment, addr.segmentOffset(segment));
    - * }
    - * - * Secondly, if the client does not have a segment which contains a given memory address, it can create one unsafely, - * using the {@link jdk.incubator.foreign.MemoryAddress#asSegment(long, ResourceScope)} factory. This allows the client to - * inject extra knowledge about spatial bounds which might, for instance, be available in the documentation of the foreign function - * which produced the native address. Here is how an unsafe segment can be created from a native address: - * - *
    {@code
    -ResourceScope scope = ... // initialize a resource scope object
    -MemoryAddress addr = ... //obtain address from native code
    -MemorySegment segment = addr.asSegment(4, scope); // segment is 4 bytes long
    -int x = MemoryAccess.getInt(segment);
    - * }
    - * - * Alternatively, the client can fall back to use the so called everything segment - that is, a primordial segment - * which covers the entire native heap. This segment can be obtained by calling the {@link jdk.incubator.foreign.MemorySegment#globalNativeSegment()} - * method, so that dereference can happen without the need of creating any additional segment instances: - * - *
    {@code
    -MemoryAddress addr = ... //obtain address from native code
    -int x = MemoryAccess.getIntAtOffset(MemorySegment.globalNativeSegment(), addr.toRawLongValue());
    - * }
    + * Raw pointers are modelled using the {@link jdk.incubator.foreign.MemoryAddress} class. When clients receive a + * memory address instance from a foreign function call, they can perform memory dereference on it directly, + * using one of the many unsafe + * {@linkplain jdk.incubator.foreign.MemoryAddress#get(jdk.incubator.foreign.ValueLayout.OfInt, long) dereference methods} + * provided: + * + * {@snippet lang=java : + * MemoryAddress addr = ... //obtain address from native code + * int x = addr.get(ValueLayout.JAVA_INT, 0); + * } + * + * Alternatively, the client can + * {@linkplain jdk.incubator.foreign.MemorySegment#ofAddress(jdk.incubator.foreign.MemoryAddress, long, jdk.incubator.foreign.ResourceScope) create} + * a memory segment unsafely. This allows the client to inject extra knowledge about spatial bounds which might, + * for instance, be available in the documentation of the foreign function which produced the native address. + * Here is how an unsafe segment can be created from a native address: + * + * {@snippet lang=java : + * ResourceScope scope = ... // initialize a resource scope object + * MemoryAddress addr = ... //obtain address from native code + * MemorySegment segment = MemorySegment.ofAddress(addr, 4, scope); // segment is 4 bytes long + * int x = segment.get(ValueLayout.JAVA_INT, 0); + * } * *

    Upcalls

    - * The {@link jdk.incubator.foreign.CLinker} interface also allows to turn an existing method handle (which might point - * to a Java method) into a native memory address (see {@link jdk.incubator.foreign.MemoryAddress}), so that Java code - * can effectively be passed to other foreign functions. For instance, we can write a method that compares two - * integer values, as follows: - * - *
    {@code
    -class IntComparator {
    -    static int intCompare(MemoryAddress addr1, MemoryAddress addr2) {
    -        return MemoryAccess.getIntAtOffset(MemorySegment.globalNativeSegment(), addr1.toRawLongValue()) -
    -               MemoryAccess.getIntAtOffset(MemorySegment.globalNativeSegment(), addr2.toRawLongValue());
    -    }
    -}
    - * }
    + * The {@link jdk.incubator.foreign.CLinker} interface also allows clients to turn an existing method handle (which might point + * to a Java method) into a memory address, so that Java code can effectively be passed to other foreign functions. + * For instance, we can write a method that compares two integer values, as follows: + * + * {@snippet lang=java : + * class IntComparator { + * static int intCompare(MemoryAddress addr1, MemoryAddress addr2) { + * return addr1.get(ValueLayout.JAVA_INT, 0) - addr2.get(ValueLayout.JAVA_INT, 0); + * } + * } + * } * * The above method dereferences two memory addresses containing an integer value, and performs a simple comparison * by returning the difference between such values. We can then obtain a method handle which targets the above static * method, as follows: * - *
    {@code
    -MethodHandle intCompareHandle = MethodHandles.lookup().findStatic(IntComparator.class,
    -                                                   "intCompare",
    -                                                   MethodType.methodType(int.class, MemoryAddress.class, MemoryAddress.class));
    - * }
    - * - * Now that we have a method handle instance, we can link it into a fresh native memory address, using the {@link jdk.incubator.foreign.CLinker} interface, as follows: - * - *
    {@code
    -ResourceScope scope = ...
    -MemoryAddress comparFunc = CLinker.getInstance().upcallStub(
    -     intCompareHandle,
    -     FunctionDescriptor.of(C_INT, C_POINTER, C_POINTER),
    -     scope
    -);
    - * }
    - * - * As before, we need to provide a {@link jdk.incubator.foreign.FunctionDescriptor} instance describing the signature - * of the function pointer we want to create; as before, this, coupled with the method handle type, uniquely determines the - * sequence of steps which will allow foreign code to call {@code intCompareHandle} according to the rules specified - * by the platform C ABI. The lifecycle of the memory address returned by - * {@link jdk.incubator.foreign.CLinker#upcallStub(java.lang.invoke.MethodHandle, jdk.incubator.foreign.FunctionDescriptor, jdk.incubator.foreign.ResourceScope)} - * is tied to the {@linkplain jdk.incubator.foreign.ResourceScope resource scope} parameter passed to that method. + * {@snippet lang=java : + * FunctionDescriptor intCompareDescriptor = FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.ADDRESS, ValueLayout.ADDRESS); + * MethodHandle intCompareHandle = MethodHandles.lookup().findStatic(IntComparator.class, + * "intCompare", + * CLinker.upcallType(comparFunction)); + * } + * + * As before, we need to create a {@link jdk.incubator.foreign.FunctionDescriptor} instance, this time describing the signature + * of the function pointer we want to create. The descriptor can be used to + * {@linkplain jdk.incubator.foreign.CLinker#upcallType(jdk.incubator.foreign.FunctionDescriptor) derive} a method type + * that can be used to look up the method handle for {@code IntComparator.intCompare}. + *

    + * Now that we have a method handle instance, we can turn it into a fresh function pointer, + * using the {@link jdk.incubator.foreign.CLinker} interface, as follows: + * + * {@snippet lang=java : + * ResourceScope scope = ... + * Addressable comparFunc = CLinker.systemCLinker().upcallStub( + * intCompareHandle, intCompareDescriptor, scope); + * ); + * } + * + * The {@link jdk.incubator.foreign.FunctionDescriptor} instance created in the previous step is then used to + * {@linkplain jdk.incubator.foreign.CLinker#upcallStub(java.lang.invoke.MethodHandle, jdk.incubator.foreign.FunctionDescriptor, jdk.incubator.foreign.ResourceScope) create} + * a new upcall stub; the layouts in the function descriptors allow the linker to determine the sequence of steps which + * allow foreign code to call the stub for {@code intCompareHandle} according to the rules specified by the platform C ABI. + * The lifecycle of the upcall stub returned by is tied to the {@linkplain jdk.incubator.foreign.ResourceScope resource scope} + * provided when the upcall stub is created. This same scope is made available by the {@link jdk.incubator.foreign.NativeSymbol} + * instance returned by that method. * * *

    Restricted methods

    * Some methods in this package are considered restricted. Restricted methods are typically used to bind native * foreign data and/or functions to first-class Java API elements which can then be used directly by clients. For instance - * the restricted method {@link jdk.incubator.foreign.MemoryAddress#asSegment(long, ResourceScope)} can be used to create - * a fresh segment with given spatial bounds out of a native address. + * the restricted method {@link MemorySegment#ofAddress(MemoryAddress, long, ResourceScope)} + * can be used to create a fresh segment with given spatial bounds out of a native address. *

    * Binding foreign data and/or functions is generally unsafe and, if done incorrectly, can result in VM crashes, or memory corruption when the bound Java API element is accessed. - * For instance, in the case of {@link jdk.incubator.foreign.MemoryAddress#asSegment(long, ResourceScope)}, if the provided - * spatial bounds are incorrect, a client of the segment returned by that method might crash the VM, or corrupt + * For instance, in the case of {@link MemorySegment#ofAddress(MemoryAddress, long, ResourceScope)}, + * if the provided spatial bounds are incorrect, a client of the segment returned by that method might crash the VM, or corrupt * memory when attempting to dereference said segment. For these reasons, it is crucial for code that calls a restricted method * to never pass arguments that might cause incorrect binding of foreign data and/or functions to a Java API. *

    diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/AbstractCLinker.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/AbstractCLinker.java deleted file mode 100644 index 91a7cbff6c6161fb0dcdafafac2096a83ebb54e6..0000000000000000000000000000000000000000 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/AbstractCLinker.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package jdk.internal.foreign; - -import jdk.incubator.foreign.Addressable; -import jdk.incubator.foreign.CLinker; -import jdk.incubator.foreign.FunctionDescriptor; -import jdk.incubator.foreign.MemorySegment; -import jdk.incubator.foreign.SegmentAllocator; -import jdk.internal.foreign.abi.SharedUtils; - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; -import java.util.Objects; - -public abstract non-sealed class AbstractCLinker implements CLinker { - - public final MethodHandle downcallHandle(Addressable symbol, MethodType type, FunctionDescriptor function) { - SharedUtils.checkSymbol(symbol); - return MethodHandles.insertArguments(downcallHandle(type, function), 0, symbol); - } - - public final MethodHandle downcallHandle(Addressable symbol, SegmentAllocator allocator, MethodType type, FunctionDescriptor function) { - SharedUtils.checkSymbol(symbol); - Objects.requireNonNull(allocator); - MethodHandle downcall = MethodHandles.insertArguments(downcallHandle(type, function), 0, symbol); - if (type.returnType().equals(MemorySegment.class)) { - downcall = MethodHandles.insertArguments(downcall, 0, allocator); - } - return downcall; - } -} diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java index b54ba68f29f20e2dacce49c1ee0cc41ff966b6aa..eacbeb26a519282d878018cd55db213c47df531b 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,6 +36,7 @@ import jdk.internal.vm.annotation.ForceInline; import sun.security.action.GetPropertyAction; import java.nio.ByteBuffer; +import java.nio.ByteOrder; import java.util.*; import java.util.function.Consumer; import java.util.function.Function; @@ -43,6 +44,8 @@ import java.util.function.IntFunction; import java.util.stream.Stream; import java.util.stream.StreamSupport; +import static jdk.incubator.foreign.ValueLayout.JAVA_BYTE; + /** * This abstract class provides an immutable implementation for the {@code MemorySegment} interface. This class contains information * about the segment's spatial and temporal bounds; each memory segment implementation is associated with an owner thread which is set at creation time. @@ -52,7 +55,7 @@ import java.util.stream.StreamSupport; * are defined for each memory segment kind, see {@link NativeMemorySegmentImpl}, {@link HeapMemorySegmentImpl} and * {@link MappedMemorySegmentImpl}. */ -public abstract non-sealed class AbstractMemorySegmentImpl extends MemorySegmentProxy implements MemorySegment { +public abstract non-sealed class AbstractMemorySegmentImpl extends MemorySegmentProxy implements MemorySegment, SegmentAllocator, Scoped { private static final ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess(); @@ -140,24 +143,9 @@ public abstract non-sealed class AbstractMemorySegmentImpl extends MemorySegment return this; } - public void copyFrom(MemorySegment src) { - AbstractMemorySegmentImpl that = (AbstractMemorySegmentImpl)Objects.requireNonNull(src); - long size = that.byteSize(); - checkAccess(0, size, false); - that.checkAccess(0, size, true); - SCOPED_MEMORY_ACCESS.copyMemory(scope, that.scope, - that.base(), that.min(), - base(), min(), size); - } - - public void copyFromSwap(MemorySegment src, long elemSize) { - AbstractMemorySegmentImpl that = (AbstractMemorySegmentImpl)src; - long size = that.byteSize(); - checkAccess(0, size, false); - that.checkAccess(0, size, true); - SCOPED_MEMORY_ACCESS.copySwapMemory(scope, that.scope, - that.base(), that.min(), - base(), min(), size, elemSize); + @Override + public MemorySegment allocate(long bytesSize, long bytesAlignment) { + return asSlice(0, bytesSize); } @Override @@ -175,7 +163,7 @@ public abstract non-sealed class AbstractMemorySegmentImpl extends MemorySegment long i = 0; if (length > 7) { - if (MemoryAccess.getByte(this) != MemoryAccess.getByte(that)) { + if (get(JAVA_BYTE, 0) != that.get(JAVA_BYTE, 0)) { return 0; } i = vectorizedMismatchLargeForBytes(scope, that.scope, @@ -190,7 +178,7 @@ public abstract non-sealed class AbstractMemorySegmentImpl extends MemorySegment i = length - remaining; } for (; i < length; i++) { - if (MemoryAccess.getByteAtOffset(this, i) != MemoryAccess.getByteAtOffset(that, i)) { + if (get(JAVA_BYTE, i) != that.get(JAVA_BYTE, i)) { return i; } } @@ -230,9 +218,8 @@ public abstract non-sealed class AbstractMemorySegmentImpl extends MemorySegment } @Override - @ForceInline - public final MemoryAddress address() { - return new MemoryAddressImpl(this, 0L); + public MemoryAddress address() { + throw new UnsupportedOperationException("Cannot obtain address of on-heap segment"); } @Override @@ -269,6 +256,33 @@ public abstract non-sealed class AbstractMemorySegmentImpl extends MemorySegment return false; } + @Override + public final MemorySegment asOverlappingSlice(MemorySegment other) { + AbstractMemorySegmentImpl that = (AbstractMemorySegmentImpl)Objects.requireNonNull(other); + if (base() == that.base()) { // both either native or heap + final long thisStart = this.min(); + final long thatStart = that.min(); + final long thisEnd = thisStart + this.byteSize(); + final long thatEnd = thatStart + that.byteSize(); + + if (thisStart < thatEnd && thisEnd > thatStart) { //overlap occurs + long offsetToThat = this.segmentOffset(that); + long newOffset = offsetToThat >= 0 ? offsetToThat : 0; + return asSlice(newOffset, Math.min(this.byteSize() - newOffset, that.byteSize() + offsetToThat)); + } + } + return null; + } + + @Override + public final long segmentOffset(MemorySegment other) { + AbstractMemorySegmentImpl that = (AbstractMemorySegmentImpl) Objects.requireNonNull(other); + if (base() == that.base()) { + return that.min() - this.min(); + } + throw new UnsupportedOperationException("Cannot compute offset from native to heap (or vice versa)."); + } + @Override public void load() { throw new UnsupportedOperationException("Not a mapped segment"); @@ -290,45 +304,45 @@ public abstract non-sealed class AbstractMemorySegmentImpl extends MemorySegment } @Override - public final byte[] toByteArray() { - return toArray(byte[].class, 1, byte[]::new, MemorySegment::ofArray); + public final byte[] toArray(ValueLayout.OfByte elementLayout) { + return toArray(byte[].class, elementLayout, byte[]::new, MemorySegment::ofArray); } @Override - public final short[] toShortArray() { - return toArray(short[].class, 2, short[]::new, MemorySegment::ofArray); + public final short[] toArray(ValueLayout.OfShort elementLayout) { + return toArray(short[].class, elementLayout, short[]::new, MemorySegment::ofArray); } @Override - public final char[] toCharArray() { - return toArray(char[].class, 2, char[]::new, MemorySegment::ofArray); + public final char[] toArray(ValueLayout.OfChar elementLayout) { + return toArray(char[].class, elementLayout, char[]::new, MemorySegment::ofArray); } @Override - public final int[] toIntArray() { - return toArray(int[].class, 4, int[]::new, MemorySegment::ofArray); + public final int[] toArray(ValueLayout.OfInt elementLayout) { + return toArray(int[].class, elementLayout, int[]::new, MemorySegment::ofArray); } @Override - public final float[] toFloatArray() { - return toArray(float[].class, 4, float[]::new, MemorySegment::ofArray); + public final float[] toArray(ValueLayout.OfFloat elementLayout) { + return toArray(float[].class, elementLayout, float[]::new, MemorySegment::ofArray); } @Override - public final long[] toLongArray() { - return toArray(long[].class, 8, long[]::new, MemorySegment::ofArray); + public final long[] toArray(ValueLayout.OfLong elementLayout) { + return toArray(long[].class, elementLayout, long[]::new, MemorySegment::ofArray); } @Override - public final double[] toDoubleArray() { - return toArray(double[].class, 8, double[]::new, MemorySegment::ofArray); + public final double[] toArray(ValueLayout.OfDouble elementLayout) { + return toArray(double[].class, elementLayout, double[]::new, MemorySegment::ofArray); } - private Z toArray(Class arrayClass, int elemSize, IntFunction arrayFactory, Function segmentFactory) { - int size = checkArraySize(arrayClass.getSimpleName(), elemSize); + private Z toArray(Class arrayClass, ValueLayout elemLayout, IntFunction arrayFactory, Function segmentFactory) { + int size = checkArraySize(arrayClass.getSimpleName(), (int)elemLayout.byteSize()); Z arr = arrayFactory.apply(size); MemorySegment arrSegment = segmentFactory.apply(arr); - arrSegment.copyFrom(this); + MemorySegment.copy(this, elemLayout, 0, arrSegment, elemLayout.withOrder(ByteOrder.nativeOrder()), 0, size); return arr; } @@ -382,11 +396,12 @@ public abstract non-sealed class AbstractMemorySegmentImpl extends MemorySegment private void checkBounds(long offset, long length) { if (isSmall() && - offset < Integer.MAX_VALUE && length < Integer.MAX_VALUE && - offset > Integer.MIN_VALUE && length > Integer.MIN_VALUE) { + offset <= Integer.MAX_VALUE && length <= Integer.MAX_VALUE && + offset >= Integer.MIN_VALUE && length >= Integer.MIN_VALUE) { checkBoundsSmall((int)offset, (int)length); - } else { - if (length < 0 || + } else if (this != NativeMemorySegmentImpl.EVERYTHING) { // oob not possible for everything segment + if ( + length < 0 || offset < 0 || offset > this.length - length) { // careful of overflow throw outOfBoundException(offset, length); diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/ArenaAllocator.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/ArenaAllocator.java index 8a8474a3be547f2221532cd62084d79cdf4cb80d..009ea6c703d8ddadc49880dc12e17c678ab2bf45 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/ArenaAllocator.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/ArenaAllocator.java @@ -29,14 +29,23 @@ import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.SegmentAllocator; import jdk.incubator.foreign.ResourceScope; -public abstract class ArenaAllocator implements SegmentAllocator { +public final class ArenaAllocator implements SegmentAllocator { - protected MemorySegment segment; + public static final long DEFAULT_BLOCK_SIZE = 4 * 1024; - protected long sp = 0L; + private MemorySegment segment; - ArenaAllocator(MemorySegment segment) { - this.segment = segment; + private long sp = 0L; + private long size = 0; + private final long blockSize; + private final long arenaSize; + private final ResourceScope scope; + + public ArenaAllocator(long blockSize, long arenaSize, ResourceScope scope) { + this.blockSize = blockSize; + this.arenaSize = arenaSize; + this.scope = scope; + this.segment = newSegment(blockSize, 1); } MemorySegment trySlice(long bytesSize, long bytesAlignment) { @@ -51,99 +60,37 @@ public abstract class ArenaAllocator implements SegmentAllocator { } } - void checkConfinementIfNeeded() { - Thread ownerThread = scope().ownerThread(); - if (ownerThread != null && ownerThread != Thread.currentThread()) { - throw new IllegalStateException("Attempt to allocate outside confinement thread"); - } + public ResourceScope scope() { + return scope; } - ResourceScope scope() { - return segment.scope(); - } - - public static class UnboundedArenaAllocator extends ArenaAllocator { - - private static final long DEFAULT_BLOCK_SIZE = 4 * 1024; - - public UnboundedArenaAllocator(ResourceScope scope) { - super(MemorySegment.allocateNative(DEFAULT_BLOCK_SIZE, 1, scope)); - } - - private MemorySegment newSegment(long size, long align) { - return MemorySegment.allocateNative(size, align, segment.scope()); - } - - @Override - public MemorySegment allocate(long bytesSize, long bytesAlignment) { - checkConfinementIfNeeded(); - // try to slice from current segment first... - MemorySegment slice = trySlice(bytesSize, bytesAlignment); - if (slice != null) { - return slice; - } else { - long maxPossibleAllocationSize = bytesSize + bytesAlignment - 1; - if (maxPossibleAllocationSize > DEFAULT_BLOCK_SIZE) { - // too big - return newSegment(bytesSize, bytesAlignment); - } else { - // allocate a new segment and slice from there - sp = 0L; - segment = newSegment(DEFAULT_BLOCK_SIZE, 1L); - return trySlice(bytesSize, bytesAlignment); - } - } + private MemorySegment newSegment(long bytesSize, long bytesAlignment) { + long allocatedSize = Utils.alignUp(bytesSize, bytesAlignment); + if (size + allocatedSize > arenaSize) { + throw new OutOfMemoryError(); } + size += allocatedSize; + return MemorySegment.allocateNative(bytesSize, bytesAlignment, scope); } - public static class BoundedArenaAllocator extends ArenaAllocator { - - public BoundedArenaAllocator(ResourceScope scope, long size) { - super(MemorySegment.allocateNative(size, 1, scope)); - } - - @Override - public MemorySegment allocate(long bytesSize, long bytesAlignment) { - checkConfinementIfNeeded(); - // try to slice from current segment first... - MemorySegment slice = trySlice(bytesSize, bytesAlignment); - if (slice != null) { - return slice; + @Override + public MemorySegment allocate(long bytesSize, long bytesAlignment) { + // try to slice from current segment first... + MemorySegment slice = trySlice(bytesSize, bytesAlignment); + if (slice != null) { + return slice; + } else { + long maxPossibleAllocationSize = bytesSize + bytesAlignment - 1; + if (maxPossibleAllocationSize > blockSize) { + // too big + return newSegment(bytesSize, bytesAlignment); } else { - throw new OutOfMemoryError("Not enough space left to allocate"); - } - } - } - - public static class BoundedSharedArenaAllocator extends BoundedArenaAllocator { - public BoundedSharedArenaAllocator(ResourceScope scope, long size) { - super(scope, size); - } - - @Override - public synchronized MemorySegment allocate(long bytesSize, long bytesAlignment) { - return super.allocate(bytesSize, bytesAlignment); - } - } - - public static class UnboundedSharedArenaAllocator implements SegmentAllocator { - - final ResourceScope scope; - - final ThreadLocal allocators = new ThreadLocal<>() { - @Override - protected ArenaAllocator initialValue() { - return new UnboundedArenaAllocator(scope); + // allocate a new segment and slice from there + sp = 0L; + segment = newSegment(blockSize, 1L); + slice = trySlice(bytesSize, bytesAlignment); + return slice; } - }; - - public UnboundedSharedArenaAllocator(ResourceScope scope) { - this.scope = scope; - } - - @Override - public MemorySegment allocate(long bytesSize, long bytesAlignment) { - return allocators.get().allocate(bytesSize, bytesAlignment); } } } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/CABI.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/CABI.java index 977a875521088f6956ba533502a493194db2c30a..24abdede3be684fa7524b7a6110dc028be967b4f 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/CABI.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/CABI.java @@ -25,9 +25,7 @@ */ package jdk.internal.foreign; -import sun.security.action.GetPropertyAction; - -import static jdk.incubator.foreign.MemoryLayouts.ADDRESS; +import static jdk.incubator.foreign.ValueLayout.ADDRESS; import static sun.security.action.GetPropertyAction.privilegedGetProperty; public enum CABI { diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/ConfinedScope.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/ConfinedScope.java index 16749105bd1568955ec07413b8f0daa71d41e462..ac8850258c15cf4842cac7b9493eef284987040d 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/ConfinedScope.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/ConfinedScope.java @@ -25,11 +25,11 @@ package jdk.internal.foreign; -import jdk.incubator.foreign.ResourceScope; import jdk.internal.vm.annotation.ForceInline; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; import java.lang.ref.Cleaner; -import java.lang.ref.Reference; /** * A confined scope, which features an owner thread. The liveness check features an additional @@ -41,10 +41,21 @@ final class ConfinedScope extends ResourceScopeImpl { private boolean closed; // = false private int lockCount = 0; + private int asyncReleaseCount = 0; private final Thread owner; + static final VarHandle ASYNC_RELEASE_COUNT; + + static { + try { + ASYNC_RELEASE_COUNT = MethodHandles.lookup().findVarHandle(ConfinedScope.class, "asyncReleaseCount", int.class); + } catch (Throwable ex) { + throw new ExceptionInInitializerError(ex); + } + } + public ConfinedScope(Thread owner, Cleaner cleaner) { - super(cleaner, new ConfinedResourceList()); + super(new ConfinedResourceList(), cleaner); this.owner = owner; } @@ -64,18 +75,35 @@ final class ConfinedScope extends ResourceScopeImpl { } @Override - public HandleImpl acquire() { + @ForceInline + public void acquire0() { checkValidState(); + if (lockCount == MAX_FORKS) { + throw new IllegalStateException("Scope keep alive limit exceeded"); + } lockCount++; - return new ConfinedHandle(); + } + + @Override + @ForceInline + public void release0() { + if (Thread.currentThread() == owner) { + lockCount--; + } else { + // It is possible to end up here in two cases: this scope was kept alive by some other confined scope + // which is implicitly released (in which case the release call comes from the cleaner thread). Or, + // this scope might be kept alive by a shared scope, which means the release call can come from any + // thread. + ASYNC_RELEASE_COUNT.getAndAdd(this, 1); + } } void justClose() { this.checkValidState(); - if (lockCount == 0) { + if (lockCount == 0 || lockCount - ((int)ASYNC_RELEASE_COUNT.getVolatile(this)) == 0) { closed = true; } else { - throw new IllegalStateException("Scope is acquired by " + lockCount + " locks"); + throw new IllegalStateException("Scope is kept alive by " + lockCount + " scopes"); } } @@ -109,25 +137,4 @@ final class ConfinedScope extends ResourceScopeImpl { } } } - - /** - * A confined resource scope handle; no races are possible here. - */ - final class ConfinedHandle implements HandleImpl { - boolean released = false; - - @Override - public ResourceScopeImpl scope() { - return ConfinedScope.this; - } - - @Override - public void release() { - checkValidState(); // thread check - if (!released) { - released = true; - lockCount--; - } - } - } } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/LayoutPath.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/LayoutPath.java index 346e6882a45c7e7f076d5b98c5f24fadf07116cb..1d8bb265c839f13bd51505ed5b56fc943284ce63 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/LayoutPath.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/LayoutPath.java @@ -28,8 +28,6 @@ package jdk.internal.foreign; import jdk.incubator.foreign.MemoryHandles; import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.MemorySegment; -import jdk.internal.access.JavaLangInvokeAccess; -import jdk.internal.access.SharedSecrets; import jdk.internal.access.foreign.MemorySegmentProxy; import jdk.incubator.foreign.GroupLayout; @@ -53,12 +51,10 @@ import java.util.function.UnaryOperator; * (see {@link #sequenceElement()}, {@link #sequenceElement(long)}, {@link #sequenceElement(long, long)}, {@link #groupElement(String)}). * Once a path has been fully constructed, clients can ask for the offset associated with the layout element selected * by the path (see {@link #offset}), or obtain a memory access var handle to access the selected layout element - * given an address pointing to a segment associated with the root layout (see {@link #dereferenceHandle(Class)}). + * given an address pointing to a segment associated with the root layout (see {@link #dereferenceHandle()}). */ public class LayoutPath { - private static final JavaLangInvokeAccess JLI = SharedSecrets.getJavaLangInvokeAccess(); - private static final MethodHandle ADD_STRIDE; private static final MethodHandle MH_ADD_SCALED_OFFSET; private static final MethodHandle MH_SLICE; @@ -156,8 +152,10 @@ public class LayoutPath { return offset; } - public VarHandle dereferenceHandle(Class carrier) { - Utils.checkPrimitiveCarrierCompat(carrier, layout); + public VarHandle dereferenceHandle() { + if (!(layout instanceof ValueLayout valueLayout)) { + throw new IllegalArgumentException("Path does not select a value layout"); + } checkAlignment(this); List> expectedCoordinates = new ArrayList<>(); @@ -165,8 +163,7 @@ public class LayoutPath { perms.addFirst(0); expectedCoordinates.add(MemorySegment.class); - VarHandle handle = Utils.fixUpVarHandle(JLI.memoryAccessVarHandle(carrier, true, layout.byteAlignment() - 1, - ((ValueLayout)layout).order())); + VarHandle handle = Utils.makeMemoryAccessVarHandle(valueLayout, true); for (int i = 0 ; i < strides.length ; i++) { expectedCoordinates.add(long.class); @@ -226,15 +223,13 @@ public class LayoutPath { MemoryLayout newLayout = op.apply(layout); if (enclosing == null) { return newLayout; - } else if (enclosing.layout instanceof SequenceLayout) { - SequenceLayout seq = (SequenceLayout)enclosing.layout; + } else if (enclosing.layout instanceof SequenceLayout seq) { if (seq.elementCount().isPresent()) { return enclosing.map(l -> dup(l, MemoryLayout.sequenceLayout(seq.elementCount().getAsLong(), newLayout))); } else { return enclosing.map(l -> dup(l, MemoryLayout.sequenceLayout(newLayout))); } - } else if (enclosing.layout instanceof GroupLayout) { - GroupLayout g = (GroupLayout)enclosing.layout; + } else if (enclosing.layout instanceof GroupLayout g) { List newElements = new ArrayList<>(g.memberLayouts()); //if we selected a layout in a group we must have a valid index newElements.set((int)elementIndex, newLayout); diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/MemoryAddressImpl.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/MemoryAddressImpl.java index 2330feefd4e37a481e60392826e55e182f14a02a..59d7105082cfc8876b2f0daa2db592adef99ca13 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/MemoryAddressImpl.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/MemoryAddressImpl.java @@ -25,128 +25,352 @@ */ package jdk.internal.foreign; +import jdk.incubator.foreign.Addressable; import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.ResourceScope; +import jdk.incubator.foreign.ValueLayout; +import jdk.internal.foreign.abi.SharedUtils; import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.Reflection; -import jdk.incubator.foreign.ResourceScope; -import java.util.Objects; +import jdk.internal.vm.annotation.ForceInline; /** * This class provides an immutable implementation for the {@code MemoryAddress} interface. This class contains information * about the segment this address is associated with, as well as an offset into such segment. */ -public final class MemoryAddressImpl implements MemoryAddress { +public final class MemoryAddressImpl implements MemoryAddress, Scoped { - private final AbstractMemorySegmentImpl segment; private final long offset; - public MemoryAddressImpl(AbstractMemorySegmentImpl segment, long offset) { - this.segment = segment; + public MemoryAddressImpl(long offset) { this.offset = offset; } - Object base() { - return segment != null ? segment.base() : null; + // MemoryAddress methods + + @Override + public MemoryAddress addOffset(long offset) { + return new MemoryAddressImpl(this.offset + offset); } - long offset() { - return segment != null ? - segment.min() + offset : offset; + @Override + public long toRawLongValue() { + return offset; } - // MemoryAddress methods + @Override + public final MemoryAddress address() { + return this; + } + + // Object methods + + @Override + public int hashCode() { + return (int) toRawLongValue(); + } + + @Override + public boolean equals(Object that) { + return (that instanceof MemoryAddressImpl addressImpl && + offset == addressImpl.offset); + } + + @Override + public String toString() { + return "MemoryAddress{ offset=0x" + Long.toHexString(offset) + " }"; + } + + public static MemorySegment ofLongUnchecked(long value) { + return ofLongUnchecked(value, Long.MAX_VALUE); + } + + public static MemorySegment ofLongUnchecked(long value, long byteSize, ResourceScopeImpl resourceScope) { + return NativeMemorySegmentImpl.makeNativeSegmentUnchecked(MemoryAddress.ofLong(value), byteSize, resourceScope); + } + + public static MemorySegment ofLongUnchecked(long value, long byteSize) { + return NativeMemorySegmentImpl.makeNativeSegmentUnchecked(MemoryAddress.ofLong(value), byteSize, ResourceScopeImpl.GLOBAL); + } @Override public ResourceScope scope() { - return segment != null ? - segment.scope() : ResourceScope.globalScope(); + return ResourceScopeImpl.GLOBAL; } @Override - public MemoryAddress addOffset(long offset) { - return new MemoryAddressImpl(segment, this.offset + offset); + @CallerSensitive + @ForceInline + public String getUtf8String(long offset) { + Reflection.ensureNativeAccess(Reflection.getCallerClass()); + SharedUtils.checkAddress(this); + return NativeMemorySegmentImpl.EVERYTHING.getUtf8String(toRawLongValue() + offset); } @Override - public long segmentOffset(MemorySegment segment) { - Objects.requireNonNull(segment); - AbstractMemorySegmentImpl segmentImpl = (AbstractMemorySegmentImpl)segment; - if (segmentImpl.base() != base()) { - throw new IllegalArgumentException("Incompatible segment: " + segment); - } - return offset() - segmentImpl.min(); + @CallerSensitive + @ForceInline + public void setUtf8String(long offset, String str) { + Reflection.ensureNativeAccess(Reflection.getCallerClass()); + SharedUtils.checkAddress(this); + NativeMemorySegmentImpl.EVERYTHING.setUtf8String(toRawLongValue() + offset, str); } @Override - public boolean isNative() { - return base() == null; + @ForceInline + @CallerSensitive + public byte get(ValueLayout.OfByte layout, long offset) { + Reflection.ensureNativeAccess(Reflection.getCallerClass()); + return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + offset); } @Override - public long toRawLongValue() { - if (segment != null) { - if (segment.base() != null) { - throw new UnsupportedOperationException("Not a native address"); - } - segment.checkValidState(); - } - return offset(); + @ForceInline + @CallerSensitive + public void set(ValueLayout.OfByte layout, long offset, byte value) { + Reflection.ensureNativeAccess(Reflection.getCallerClass()); + NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + offset, value); } - // Object methods + @Override + @ForceInline + @CallerSensitive + public boolean get(ValueLayout.OfBoolean layout, long offset) { + Reflection.ensureNativeAccess(Reflection.getCallerClass()); + return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + offset); + } @Override - public int hashCode() { - return Objects.hash(base(), offset()); + @ForceInline + @CallerSensitive + public void set(ValueLayout.OfBoolean layout, long offset, boolean value) { + Reflection.ensureNativeAccess(Reflection.getCallerClass()); + NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + offset, value); } @Override - public boolean equals(Object that) { - if (that instanceof MemoryAddressImpl) { - MemoryAddressImpl addr = (MemoryAddressImpl)that; - return Objects.equals(base(), addr.base()) && - offset() == addr.offset(); - } else { - return false; - } + @ForceInline + @CallerSensitive + public char get(ValueLayout.OfChar layout, long offset) { + Reflection.ensureNativeAccess(Reflection.getCallerClass()); + return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + offset); } @Override - public String toString() { - return "MemoryAddress{ base: " + base() + " offset=0x" + Long.toHexString(offset()) + " }"; + @ForceInline + @CallerSensitive + public void set(ValueLayout.OfChar layout, long offset, char value) { + Reflection.ensureNativeAccess(Reflection.getCallerClass()); + NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + offset, value); } @Override + @ForceInline @CallerSensitive - public final MemorySegment asSegment(long bytesSize, ResourceScope scope) { + public short get(ValueLayout.OfShort layout, long offset) { Reflection.ensureNativeAccess(Reflection.getCallerClass()); - return asSegment(bytesSize, null, scope); + return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + offset); } @Override + @ForceInline @CallerSensitive - public final MemorySegment asSegment(long bytesSize, Runnable cleanupAction, ResourceScope scope) { + public void set(ValueLayout.OfShort layout, long offset, short value) { Reflection.ensureNativeAccess(Reflection.getCallerClass()); - Objects.requireNonNull(scope); - if (bytesSize <= 0) { - throw new IllegalArgumentException("Invalid size : " + bytesSize); - } - return NativeMemorySegmentImpl.makeNativeSegmentUnchecked(this, bytesSize, - cleanupAction, - (ResourceScopeImpl) scope); + NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + offset, value); } - public static MemorySegment ofLongUnchecked(long value) { - return ofLongUnchecked(value, Long.MAX_VALUE); + @Override + @ForceInline + @CallerSensitive + public int get(ValueLayout.OfInt layout, long offset) { + Reflection.ensureNativeAccess(Reflection.getCallerClass()); + return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + offset); } - public static MemorySegment ofLongUnchecked(long value, long byteSize, ResourceScopeImpl resourceScope) { - return NativeMemorySegmentImpl.makeNativeSegmentUnchecked(MemoryAddress.ofLong(value), byteSize, null, resourceScope); + @Override + @ForceInline + @CallerSensitive + public void set(ValueLayout.OfInt layout, long offset, int value) { + Reflection.ensureNativeAccess(Reflection.getCallerClass()); + NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + offset, value); } - public static MemorySegment ofLongUnchecked(long value, long byteSize) { - return NativeMemorySegmentImpl.makeNativeSegmentUnchecked(MemoryAddress.ofLong(value), byteSize, null, ResourceScopeImpl.GLOBAL); + @Override + @ForceInline + @CallerSensitive + public float get(ValueLayout.OfFloat layout, long offset) { + Reflection.ensureNativeAccess(Reflection.getCallerClass()); + return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + offset); + } + + @Override + @ForceInline + @CallerSensitive + public void set(ValueLayout.OfFloat layout, long offset, float value) { + Reflection.ensureNativeAccess(Reflection.getCallerClass()); + NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + offset, value); + } + + @Override + @ForceInline + @CallerSensitive + public long get(ValueLayout.OfLong layout, long offset) { + Reflection.ensureNativeAccess(Reflection.getCallerClass()); + return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + offset); + } + + @Override + @ForceInline + @CallerSensitive + public void set(ValueLayout.OfLong layout, long offset, long value) { + Reflection.ensureNativeAccess(Reflection.getCallerClass()); + NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + offset, value); + } + + @Override + @ForceInline + @CallerSensitive + public double get(ValueLayout.OfDouble layout, long offset) { + Reflection.ensureNativeAccess(Reflection.getCallerClass()); + return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + offset); + } + + @Override + @ForceInline + @CallerSensitive + public void set(ValueLayout.OfDouble layout, long offset, double value) { + Reflection.ensureNativeAccess(Reflection.getCallerClass()); + NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + offset, value); + } + + @Override + @ForceInline + @CallerSensitive + public MemoryAddress get(ValueLayout.OfAddress layout, long offset) { + Reflection.ensureNativeAccess(Reflection.getCallerClass()); + return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + offset); + } + + @Override + @ForceInline + @CallerSensitive + public void set(ValueLayout.OfAddress layout, long offset, Addressable value) { + Reflection.ensureNativeAccess(Reflection.getCallerClass()); + NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + offset, value.address()); + } + + @Override + @ForceInline + @CallerSensitive + public char getAtIndex(ValueLayout.OfChar layout, long index) { + Reflection.ensureNativeAccess(Reflection.getCallerClass()); + return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + (index * layout.byteSize())); + } + + @Override + @ForceInline + @CallerSensitive + public void setAtIndex(ValueLayout.OfChar layout, long index, char value) { + Reflection.ensureNativeAccess(Reflection.getCallerClass()); + NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + (index * layout.byteSize()), value); + } + + @Override + @ForceInline + @CallerSensitive + public short getAtIndex(ValueLayout.OfShort layout, long index) { + Reflection.ensureNativeAccess(Reflection.getCallerClass()); + return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + (index * layout.byteSize())); + } + + @Override + @ForceInline + @CallerSensitive + public void setAtIndex(ValueLayout.OfShort layout, long index, short value) { + Reflection.ensureNativeAccess(Reflection.getCallerClass()); + NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + (index * layout.byteSize()), value); + } + + @Override + @ForceInline + @CallerSensitive + public int getAtIndex(ValueLayout.OfInt layout, long index) { + Reflection.ensureNativeAccess(Reflection.getCallerClass()); + return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + (index * layout.byteSize())); + } + + @Override + @ForceInline + @CallerSensitive + public void setAtIndex(ValueLayout.OfInt layout, long index, int value) { + Reflection.ensureNativeAccess(Reflection.getCallerClass()); + NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + (index * layout.byteSize()), value); + } + + @Override + @ForceInline + @CallerSensitive + public float getAtIndex(ValueLayout.OfFloat layout, long index) { + Reflection.ensureNativeAccess(Reflection.getCallerClass()); + return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + (index * layout.byteSize())); + } + + @Override + @ForceInline + @CallerSensitive + public void setAtIndex(ValueLayout.OfFloat layout, long index, float value) { + Reflection.ensureNativeAccess(Reflection.getCallerClass()); + NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + (index * layout.byteSize()), value); + } + + @Override + @ForceInline + @CallerSensitive + public long getAtIndex(ValueLayout.OfLong layout, long index) { + Reflection.ensureNativeAccess(Reflection.getCallerClass()); + return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + (index * layout.byteSize())); + } + + @Override + @ForceInline + @CallerSensitive + public void setAtIndex(ValueLayout.OfLong layout, long index, long value) { + Reflection.ensureNativeAccess(Reflection.getCallerClass()); + NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + (index * layout.byteSize()), value); + } + + @Override + @ForceInline + @CallerSensitive + public double getAtIndex(ValueLayout.OfDouble layout, long index) { + Reflection.ensureNativeAccess(Reflection.getCallerClass()); + return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + (index * layout.byteSize())); + } + + @Override + @ForceInline + @CallerSensitive + public void setAtIndex(ValueLayout.OfDouble layout, long index, double value) { + Reflection.ensureNativeAccess(Reflection.getCallerClass()); + NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + (index * layout.byteSize()), value); + } + + @Override + @ForceInline + @CallerSensitive + public MemoryAddress getAtIndex(ValueLayout.OfAddress layout, long index) { + Reflection.ensureNativeAccess(Reflection.getCallerClass()); + return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + (index * layout.byteSize())); + } + + @Override + @ForceInline + @CallerSensitive + public void setAtIndex(ValueLayout.OfAddress layout, long index, Addressable value) { + Reflection.ensureNativeAccess(Reflection.getCallerClass()); + NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + (index * layout.byteSize()), value.address()); } } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/NativeMemorySegmentImpl.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/NativeMemorySegmentImpl.java index 8d61c9b79b550b45be84879514d7ce1c79a93beb..11f795a2f8434b936980bfb4f4c9dc0f980f4b71 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/NativeMemorySegmentImpl.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/NativeMemorySegmentImpl.java @@ -28,8 +28,6 @@ package jdk.internal.foreign; import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemorySegment; -import jdk.incubator.foreign.ResourceScope; -import jdk.incubator.foreign.SegmentAllocator; import jdk.internal.misc.Unsafe; import jdk.internal.misc.VM; import jdk.internal.vm.annotation.ForceInline; @@ -43,12 +41,10 @@ import java.nio.ByteBuffer; */ public class NativeMemorySegmentImpl extends AbstractMemorySegmentImpl { - public static final MemorySegment EVERYTHING = makeNativeSegmentUnchecked(MemoryAddress.NULL, Long.MAX_VALUE, null, ResourceScopeImpl.GLOBAL); + public static final MemorySegment EVERYTHING = makeNativeSegmentUnchecked(MemoryAddress.NULL, Long.MAX_VALUE, ResourceScopeImpl.GLOBAL); private static final Unsafe unsafe = Unsafe.getUnsafe(); - public static final SegmentAllocator IMPLICIT_ALLOCATOR = (size, align) -> MemorySegment.allocateNative(size, align, ResourceScope.newImplicitScope()); - // The maximum alignment supported by malloc - typically 16 on // 64-bit platforms and 8 on 32-bit platforms. private static final long MAX_MALLOC_ALIGN = Unsafe.ADDRESS_SIZE == 4 ? 8 : 16; @@ -63,6 +59,13 @@ public class NativeMemorySegmentImpl extends AbstractMemorySegmentImpl { this.min = min; } + @ForceInline + @Override + public MemoryAddress address() { + checkValidState(); + return MemoryAddress.ofLong(unsafeGetOffset()); + } + @Override NativeMemorySegmentImpl dup(long offset, long size, int mask, ResourceScopeImpl scope) { return new NativeMemorySegmentImpl(min + offset, size, mask, scope); @@ -123,12 +126,9 @@ public class NativeMemorySegmentImpl extends AbstractMemorySegmentImpl { return segment; } - public static MemorySegment makeNativeSegmentUnchecked(MemoryAddress min, long bytesSize, Runnable cleanupAction, ResourceScopeImpl scope) { + public static MemorySegment makeNativeSegmentUnchecked(MemoryAddress min, long bytesSize, ResourceScopeImpl scope) { scope.checkValidStateSlow(); AbstractMemorySegmentImpl segment = new NativeMemorySegmentImpl(min.toRawLongValue(), bytesSize, defaultAccessModes(bytesSize), scope); - if (cleanupAction != null) { - scope.addCloseAction(cleanupAction); - } return segment; } } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/UpcallHandler.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/NativeSymbolImpl.java similarity index 65% rename from src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/UpcallHandler.java rename to src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/NativeSymbolImpl.java index a2e9c3ea2b9c44293c3da4bc1967f6351218e77c..ede6a7ad5f8b3c6700d69bf55dd69b656d4d54d2 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/UpcallHandler.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/NativeSymbolImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -18,13 +18,21 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. + * */ +package jdk.internal.foreign; -package jdk.internal.foreign.abi; +import jdk.incubator.foreign.MemoryAddress; +import jdk.incubator.foreign.NativeSymbol; +import jdk.incubator.foreign.ResourceScope; -public interface UpcallHandler { - long entryPoint(); +public record NativeSymbolImpl(String name, MemoryAddress address, ResourceScope scope) implements NativeSymbol, Scoped { + @Override + public MemoryAddress address() { + ((ResourceScopeImpl)scope).checkValidState(); + return address; + } } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/PlatformLayouts.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/PlatformLayouts.java index c5626f92896912c34ea50932033842ee9a7801a4..c18de05c1a5f3719c23bf5b08798af06bcf138f9 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/PlatformLayouts.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/PlatformLayouts.java @@ -25,14 +25,9 @@ */ package jdk.internal.foreign; -import jdk.incubator.foreign.CLinker; import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.ValueLayout; -import java.nio.ByteOrder; - -import static java.nio.ByteOrder.LITTLE_ENDIAN; - public class PlatformLayouts { public static Z pick(Z sysv, Z win64, Z aarch64) { return switch (CABI.current()) { @@ -42,59 +37,6 @@ public class PlatformLayouts { }; } - public static MemoryLayout asVarArg(MemoryLayout ml) { - return switch (CABI.current()) { - case Win64 -> Win64.asVarArg(ml); - case MacOsAArch64 -> AArch64.asVarArg(ml); - default -> ml; - }; - } - - private static ValueLayout ofChar(ByteOrder order, long bitSize) { - return MemoryLayout.valueLayout(bitSize, order) - .withAttribute(CLinker.TypeKind.ATTR_NAME, CLinker.TypeKind.CHAR); - } - - private static ValueLayout ofShort(ByteOrder order, long bitSize) { - return MemoryLayout.valueLayout(bitSize, order) - .withAttribute(CLinker.TypeKind.ATTR_NAME, CLinker.TypeKind.SHORT); - } - - private static ValueLayout ofInt(ByteOrder order, long bitSize) { - return MemoryLayout.valueLayout(bitSize, order) - .withAttribute(CLinker.TypeKind.ATTR_NAME, CLinker.TypeKind.INT); - } - - private static ValueLayout ofLong(ByteOrder order, long bitSize) { - return MemoryLayout.valueLayout(bitSize, order) - .withAttribute(CLinker.TypeKind.ATTR_NAME, CLinker.TypeKind.LONG); - } - - private static ValueLayout ofLongLong(ByteOrder order, long bitSize) { - return MemoryLayout.valueLayout(bitSize, order) - .withAttribute(CLinker.TypeKind.ATTR_NAME, CLinker.TypeKind.LONG_LONG); - } - - private static ValueLayout ofFloat(ByteOrder order, long bitSize) { - return MemoryLayout.valueLayout(bitSize, order) - .withAttribute(CLinker.TypeKind.ATTR_NAME, CLinker.TypeKind.FLOAT); - } - - private static ValueLayout ofDouble(ByteOrder order, long bitSize) { - return MemoryLayout.valueLayout(bitSize, order) - .withAttribute(CLinker.TypeKind.ATTR_NAME, CLinker.TypeKind.DOUBLE); - } - - private static ValueLayout ofPointer(ByteOrder order, long bitSize) { - return MemoryLayout.valueLayout(bitSize, order) - .withAttribute(CLinker.TypeKind.ATTR_NAME, CLinker.TypeKind.POINTER); - } - - public static CLinker.TypeKind getKind(MemoryLayout layout) { - return (CLinker.TypeKind)layout.attribute(CLinker.TypeKind.ATTR_NAME).orElseThrow( - () -> new IllegalStateException("Unexpected value layout: could not determine ABI class")); - } - /** * This class defines layout constants modelling standard primitive types supported by the x64 SystemV ABI. */ @@ -103,50 +45,55 @@ public class PlatformLayouts { //just the one } + /** + * The {@code bool} native type. + */ + public static final ValueLayout.OfBoolean C_BOOL = ValueLayout.JAVA_BOOLEAN; + /** * The {@code char} native type. */ - public static final ValueLayout C_CHAR = ofChar(LITTLE_ENDIAN, 8); + public static final ValueLayout.OfByte C_CHAR = ValueLayout.JAVA_BYTE; /** * The {@code short} native type. */ - public static final ValueLayout C_SHORT = ofShort(LITTLE_ENDIAN, 16); + public static final ValueLayout.OfShort C_SHORT = ValueLayout.JAVA_SHORT.withBitAlignment(16); /** * The {@code int} native type. */ - public static final ValueLayout C_INT = ofInt(LITTLE_ENDIAN, 32); + public static final ValueLayout.OfInt C_INT = ValueLayout.JAVA_INT.withBitAlignment(32); /** * The {@code long} native type. */ - public static final ValueLayout C_LONG = ofLong(LITTLE_ENDIAN, 64); + public static final ValueLayout.OfLong C_LONG = ValueLayout.JAVA_LONG.withBitAlignment(64); /** * The {@code long long} native type. */ - public static final ValueLayout C_LONG_LONG = ofLongLong(LITTLE_ENDIAN, 64); + public static final ValueLayout.OfLong C_LONG_LONG = ValueLayout.JAVA_LONG.withBitAlignment(64); /** * The {@code float} native type. */ - public static final ValueLayout C_FLOAT = ofFloat(LITTLE_ENDIAN, 32); + public static final ValueLayout.OfFloat C_FLOAT = ValueLayout.JAVA_FLOAT.withBitAlignment(32); /** * The {@code double} native type. */ - public static final ValueLayout C_DOUBLE = ofDouble(LITTLE_ENDIAN, 64); + public static final ValueLayout.OfDouble C_DOUBLE = ValueLayout.JAVA_DOUBLE.withBitAlignment(64); /** * The {@code T*} native type. */ - public static final ValueLayout C_POINTER = ofPointer(LITTLE_ENDIAN, 64); + public static final ValueLayout.OfAddress C_POINTER = ValueLayout.ADDRESS.withBitAlignment(64); /** * The {@code va_list} native type, as it is passed to a function. */ - public static final MemoryLayout C_VA_LIST = SysV.C_POINTER; + public static final ValueLayout.OfAddress C_VA_LIST = SysV.C_POINTER; } /** @@ -159,64 +106,53 @@ public class PlatformLayouts { } /** - * The name of the layout attribute (see {@link MemoryLayout#attributes()}) used to mark variadic parameters. The - * attribute value must be a boolean. + * The {@code bool} native type. */ - public static final String VARARGS_ATTRIBUTE_NAME = "abi/windows/varargs"; + public static final ValueLayout.OfBoolean C_BOOL = ValueLayout.JAVA_BOOLEAN; /** * The {@code char} native type. */ - public static final ValueLayout C_CHAR = ofChar(LITTLE_ENDIAN, 8); + public static final ValueLayout.OfByte C_CHAR = ValueLayout.JAVA_BYTE; /** * The {@code short} native type. */ - public static final ValueLayout C_SHORT = ofShort(LITTLE_ENDIAN, 16); + public static final ValueLayout.OfShort C_SHORT = ValueLayout.JAVA_SHORT.withBitAlignment(16); /** * The {@code int} native type. */ - public static final ValueLayout C_INT = ofInt(LITTLE_ENDIAN, 32); + public static final ValueLayout.OfInt C_INT = ValueLayout.JAVA_INT.withBitAlignment(32); /** * The {@code long} native type. */ - public static final ValueLayout C_LONG = ofLong(LITTLE_ENDIAN, 32); + public static final ValueLayout.OfInt C_LONG = ValueLayout.JAVA_INT.withBitAlignment(32); /** * The {@code long long} native type. */ - public static final ValueLayout C_LONG_LONG = ofLongLong(LITTLE_ENDIAN, 64); + public static final ValueLayout.OfLong C_LONG_LONG = ValueLayout.JAVA_LONG.withBitAlignment(64); /** * The {@code float} native type. */ - public static final ValueLayout C_FLOAT = ofFloat(LITTLE_ENDIAN, 32); + public static final ValueLayout.OfFloat C_FLOAT = ValueLayout.JAVA_FLOAT.withBitAlignment(32); /** * The {@code double} native type. */ - public static final ValueLayout C_DOUBLE = ofDouble(LITTLE_ENDIAN, 64); + public static final ValueLayout.OfDouble C_DOUBLE = ValueLayout.JAVA_DOUBLE.withBitAlignment(64); /** * The {@code T*} native type. */ - public static final ValueLayout C_POINTER = ofPointer(LITTLE_ENDIAN, 64); + public static final ValueLayout.OfAddress C_POINTER = ValueLayout.ADDRESS.withBitAlignment(64); /** * The {@code va_list} native type, as it is passed to a function. */ - public static final MemoryLayout C_VA_LIST = Win64.C_POINTER; - - /** - * Return a new memory layout which describes a variadic parameter to be passed to a function. - * @param layout the original parameter layout. - * @return a layout which is the same as {@code layout}, except for the extra attribute {@link #VARARGS_ATTRIBUTE_NAME}, - * which is set to {@code true}. - */ - public static MemoryLayout asVarArg(MemoryLayout layout) { - return layout.withAttribute(VARARGS_ATTRIBUTE_NAME, true); - } + public static final ValueLayout.OfAddress C_VA_LIST = Win64.C_POINTER; } /** @@ -228,69 +164,54 @@ public class PlatformLayouts { //just the one } + /** + * The {@code bool} native type. + */ + public static final ValueLayout.OfBoolean C_BOOL = ValueLayout.JAVA_BOOLEAN; + /** * The {@code char} native type. */ - public static final ValueLayout C_CHAR = ofChar(LITTLE_ENDIAN, 8); + public static final ValueLayout.OfByte C_CHAR = ValueLayout.JAVA_BYTE; /** * The {@code short} native type. */ - public static final ValueLayout C_SHORT = ofShort(LITTLE_ENDIAN, 16); + public static final ValueLayout.OfShort C_SHORT = ValueLayout.JAVA_SHORT.withBitAlignment(16); /** * The {@code int} native type. */ - public static final ValueLayout C_INT = ofInt(LITTLE_ENDIAN, 32); + public static final ValueLayout.OfInt C_INT = ValueLayout.JAVA_INT.withBitAlignment(32); /** * The {@code long} native type. */ - public static final ValueLayout C_LONG = ofLong(LITTLE_ENDIAN, 64); + public static final ValueLayout.OfLong C_LONG = ValueLayout.JAVA_LONG.withBitAlignment(64); /** * The {@code long long} native type. */ - public static final ValueLayout C_LONG_LONG = ofLongLong(LITTLE_ENDIAN, 64); + public static final ValueLayout.OfLong C_LONG_LONG = ValueLayout.JAVA_LONG.withBitAlignment(64); /** * The {@code float} native type. */ - public static final ValueLayout C_FLOAT = ofFloat(LITTLE_ENDIAN, 32); + public static final ValueLayout.OfFloat C_FLOAT = ValueLayout.JAVA_FLOAT.withBitAlignment(32); /** * The {@code double} native type. */ - public static final ValueLayout C_DOUBLE = ofDouble(LITTLE_ENDIAN, 64); + public static final ValueLayout.OfDouble C_DOUBLE = ValueLayout.JAVA_DOUBLE.withBitAlignment(64); /** * The {@code T*} native type. */ - public static final ValueLayout C_POINTER = ofPointer(LITTLE_ENDIAN, 64); + public static final ValueLayout.OfAddress C_POINTER = ValueLayout.ADDRESS.withBitAlignment(64); /** * The {@code va_list} native type, as it is passed to a function. */ - public static final MemoryLayout C_VA_LIST = AArch64.C_POINTER; - - /** - * The name of the layout attribute (see {@link MemoryLayout#attributes()}) - * used to mark variadic parameters on systems such as macOS which pass these - * entirely on the stack. The attribute value must be a boolean. - */ - public final static String STACK_VARARGS_ATTRIBUTE_NAME = "abi/aarch64/stack_varargs"; - - /** - * Return a new memory layout which describes a variadic parameter to be - * passed to a function. This is only required on platforms such as macOS - * which pass variadic parameters entirely on the stack. - * @param layout the original parameter layout. - * @return a layout which is the same as {@code layout}, except for - * the extra attribute {@link #STACK_VARARGS_ATTRIBUTE_NAME}, which is set - * to {@code true}. - */ - public static MemoryLayout asVarArg(MemoryLayout layout) { - return layout.withAttribute(STACK_VARARGS_ATTRIBUTE_NAME, true); - } + public static final ValueLayout.OfAddress C_VA_LIST = AArch64.C_POINTER; } } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/ResourceScopeImpl.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/ResourceScopeImpl.java index ffd225a6b2626e67389afdd3e8ff151f331f0f5a..ab47db827e70a0661cbedeb2597b3563e509e30b 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/ResourceScopeImpl.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/ResourceScopeImpl.java @@ -30,7 +30,7 @@ import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; import jdk.incubator.foreign.SegmentAllocator; import jdk.internal.misc.ScopedMemoryAccess; -import jdk.internal.ref.CleanerFactory; +import jdk.internal.vm.annotation.ForceInline; import java.lang.ref.Cleaner; import java.lang.ref.Reference; @@ -49,9 +49,12 @@ import java.util.Objects; * shared scopes use a more sophisticated synchronization mechanism, which guarantees that no concurrent * access is possible when a scope is being closed (see {@link jdk.internal.misc.ScopedMemoryAccess}). */ -public abstract non-sealed class ResourceScopeImpl implements ResourceScope, ScopedMemoryAccess.Scope, SegmentAllocator { +public abstract non-sealed class ResourceScopeImpl implements ResourceScope, SegmentAllocator, ScopedMemoryAccess.Scope { final ResourceList resourceList; + final Cleaner.Cleanable cleanable; + + static final int MAX_FORKS = Integer.MAX_VALUE; @Override public void addCloseAction(Runnable runnable) { @@ -59,11 +62,6 @@ public abstract non-sealed class ResourceScopeImpl implements ResourceScope, Sco addInternal(ResourceList.ResourceCleanup.ofRunnable(runnable)); } - @Override - public boolean isImplicit() { - return false; - } - /** * Add a cleanup action. If a failure occurred (because of a add vs. close race), call the cleanup action. * This semantics is useful when allocating new memory segments, since we first do a malloc/mmap and _then_ @@ -91,72 +89,38 @@ public abstract non-sealed class ResourceScopeImpl implements ResourceScope, Sco } } - protected ResourceScopeImpl(Cleaner cleaner, ResourceList resourceList) { + protected ResourceScopeImpl(ResourceList resourceList, Cleaner cleaner) { this.resourceList = resourceList; - if (cleaner != null) { - cleaner.register(this, resourceList); - } - } - - public static ResourceScopeImpl createImplicitScope() { - return new ImplicitScopeImpl(CleanerFactory.cleaner()); + cleanable = (cleaner != null) ? + cleaner.register(this, resourceList) : null; } public static ResourceScopeImpl createConfined(Thread thread, Cleaner cleaner) { return new ConfinedScope(thread, cleaner); } - /** - * Creates a confined memory scope with given attachment and cleanup action. The returned scope - * is assumed to be confined on the current thread. - * @return a confined memory scope - */ - public static ResourceScopeImpl createConfined(Cleaner cleaner) { - return new ConfinedScope(Thread.currentThread(), cleaner); - } - - /** - * Creates a shared memory scope with given attachment and cleanup action. - * @return a shared memory scope - */ public static ResourceScopeImpl createShared(Cleaner cleaner) { return new SharedScope(cleaner); } - private final void release0(HandleImpl handle) { - try { - Objects.requireNonNull(handle); - if (handle.scope() != this) { - throw new IllegalArgumentException("Cannot release an handle acquired from another scope"); - } - handle.release(); - } finally { - Reference.reachabilityFence(this); - } - } - - @Override - public final void release(ResourceScope.Handle handle) { - release0((HandleImpl)handle); - } - @Override - public final void release(ScopedMemoryAccess.Scope.Handle handle) { - release0((HandleImpl)handle); + public MemorySegment allocate(long bytesSize, long bytesAlignment) { + return MemorySegment.allocateNative(bytesSize, bytesAlignment, this); } - @Override - public abstract HandleImpl acquire(); - - /** - * Internal interface used to implement resource scope handles. - */ - public non-sealed interface HandleImpl extends ResourceScope.Handle, ScopedMemoryAccess.Scope.Handle { + public abstract void release0(); - @Override - ResourceScopeImpl scope(); + public abstract void acquire0(); - void release(); + @Override + public void keepAlive(ResourceScope target) { + Objects.requireNonNull(target); + if (target == this) { + throw new IllegalArgumentException("Invalid target scope."); + } + ResourceScopeImpl targetImpl = (ResourceScopeImpl)target; + targetImpl.acquire0(); + addCloseAction(targetImpl::release0); } /** @@ -167,7 +131,11 @@ public abstract non-sealed class ResourceScopeImpl implements ResourceScope, Sco public void close() { try { justClose(); - resourceList.cleanup(); + if (cleanable != null) { + cleanable.clean(); + } else { + resourceList.cleanup(); + } } finally { Reference.reachabilityFence(this); } @@ -215,61 +183,52 @@ public abstract non-sealed class ResourceScopeImpl implements ResourceScope, Sco } /** - * Allocates a segment using this scope. Used by {@link SegmentAllocator#ofScope(ResourceScope)}. + * The global, always alive, non-closeable, shared scope. Similar to a shared scope, but its {@link #close()} method throws unconditionally. + * Adding new resources to the global scope, does nothing: as the scope can never become not-alive, there is nothing to track. + * Acquiring and or releasing a resource scope similarly does nothing. */ - @Override - public MemorySegment allocate(long bytesSize, long bytesAlignment) { - return MemorySegment.allocateNative(bytesSize, bytesAlignment, this); - } + static class GlobalScopeImpl extends SharedScope { - /** - * A non-closeable, shared scope. Similar to a shared scope, but its {@link #close()} method throws unconditionally. - * In addition, non-closeable scopes feature a much simpler scheme for generating resource scope handles, where - * the scope itself also acts as a resource scope handle and is returned by {@link #acquire()}. - */ - static class ImplicitScopeImpl extends SharedScope implements HandleImpl { + final Object ref; - public ImplicitScopeImpl(Cleaner cleaner) { - super(cleaner); + public GlobalScopeImpl(Object ref) { + super(null); + this.ref = ref; } @Override - public HandleImpl acquire() { - return this; + public void close() { + throw new UnsupportedOperationException("Scope cannot be closed"); } @Override - public boolean isImplicit() { - return true; + @ForceInline + public void release0() { + // do nothing } @Override - public void close() { - throw new UnsupportedOperationException("Scope cannot be closed"); + @ForceInline + public void acquire0() { + // do nothing } @Override - public void release() { + void addInternal(ResourceList.ResourceCleanup resource) { // do nothing } @Override - public ResourceScopeImpl scope() { - return this; + public boolean isAlive() { + return true; } } - /** - * The global, always alive, non-closeable, shared scope. This is like a {@link ImplicitScopeImpl non-closeable scope}, - * except that the operation which adds new resources to the global scope does nothing: as the scope can never - * become not-alive, there is nothing to track. - */ - public static final ResourceScopeImpl GLOBAL = new ImplicitScopeImpl( null) { - @Override - void addInternal(ResourceList.ResourceCleanup resource) { - // do nothing - } - }; + public static final ResourceScopeImpl GLOBAL = new GlobalScopeImpl(null); + + public static ResourceScopeImpl heapScope(Object ref) { + return new GlobalScopeImpl(ref); + } /** * A list of all cleanup actions associated with a resource scope. Cleanup actions are modelled as instances @@ -296,7 +255,7 @@ public abstract non-sealed class ResourceScopeImpl implements ResourceScope, Sco } } - public static abstract class ResourceCleanup { + public abstract static class ResourceCleanup { ResourceCleanup next; public abstract void cleanup(); diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/Scoped.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/Scoped.java new file mode 100644 index 0000000000000000000000000000000000000000..7051aacb527b61c50221e593f886bd1b93d33b00 --- /dev/null +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/Scoped.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.internal.foreign; + +import jdk.incubator.foreign.ResourceScope; + +public interface Scoped { + ResourceScope scope(); +} diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/SharedScope.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/SharedScope.java index 8bbeaaab82949b0b163bf4e06e76e03dc046be03..93ecf08d468503e5d64823866f6bb854be5d2b71 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/SharedScope.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/SharedScope.java @@ -25,14 +25,12 @@ package jdk.internal.foreign; -import jdk.incubator.foreign.ResourceScope; import jdk.internal.misc.ScopedMemoryAccess; +import jdk.internal.vm.annotation.ForceInline; import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; import java.lang.ref.Cleaner; -import java.lang.ref.Reference; -import java.util.concurrent.atomic.AtomicBoolean; /** * A shared scope, which can be shared across multiple threads. Closing a shared scope has to ensure that @@ -50,7 +48,6 @@ class SharedScope extends ResourceScopeImpl { private static final int ALIVE = 0; private static final int CLOSING = -1; private static final int CLOSED = -2; - private static final int MAX_FORKS = Integer.MAX_VALUE; private int state = ALIVE; @@ -65,7 +62,7 @@ class SharedScope extends ResourceScopeImpl { } SharedScope(Cleaner cleaner) { - super(cleaner, new SharedResourceList()); + super(new SharedResourceList(), cleaner); } @Override @@ -81,7 +78,8 @@ class SharedScope extends ResourceScopeImpl { } @Override - public HandleImpl acquire() { + @ForceInline + public void acquire0() { int value; do { value = (int) STATE.getVolatile(this); @@ -90,10 +88,22 @@ class SharedScope extends ResourceScopeImpl { throw new IllegalStateException("Already closed"); } else if (value == MAX_FORKS) { //overflow - throw new IllegalStateException("Segment acquire limit exceeded"); + throw new IllegalStateException("Scope keep alive limit exceeded"); } } while (!STATE.compareAndSet(this, value, value + 1)); - return new SharedHandle(); + } + + @Override + @ForceInline + public void release0() { + int value; + do { + value = (int) STATE.getVolatile(this); + if (value <= ALIVE) { + //cannot get here - we can't close segment twice + throw new IllegalStateException("Already closed"); + } + } while (!STATE.compareAndSet(this, value, value - 1)); } void justClose() { @@ -101,7 +111,7 @@ class SharedScope extends ResourceScopeImpl { if (prevState < 0) { throw new IllegalStateException("Already closed"); } else if (prevState != ALIVE) { - throw new IllegalStateException("Scope is acquired by " + prevState + " locks"); + throw new IllegalStateException("Scope is kept alive by " + prevState + " scopes"); } boolean success = SCOPED_MEMORY_ACCESS.closeScope(this); STATE.setVolatile(this, success ? CLOSED : ALIVE); @@ -133,13 +143,13 @@ class SharedScope extends ResourceScopeImpl { @Override void add(ResourceCleanup cleanup) { while (true) { - ResourceCleanup prev = (ResourceCleanup) FST.getAcquire(this); - cleanup.next = prev; - ResourceCleanup newSegment = (ResourceCleanup) FST.compareAndExchangeRelease(this, prev, cleanup); - if (newSegment == ResourceCleanup.CLOSED_LIST) { + ResourceCleanup prev = (ResourceCleanup) FST.getVolatile(this); + if (prev == ResourceCleanup.CLOSED_LIST) { // too late throw new IllegalStateException("Already closed"); - } else if (newSegment == prev) { + } + cleanup.next = prev; + if (FST.compareAndSet(this, prev, cleanup)) { return; //victory } // keep trying @@ -155,9 +165,9 @@ class SharedScope extends ResourceScopeImpl { //ok now we're really closing down ResourceCleanup prev = null; while (true) { - prev = (ResourceCleanup) FST.getAcquire(this); + prev = (ResourceCleanup) FST.getVolatile(this); // no need to check for DUMMY, since only one thread can get here! - if (FST.weakCompareAndSetRelease(this, prev, ResourceCleanup.CLOSED_LIST)) { + if (FST.compareAndSet(this, prev, ResourceCleanup.CLOSED_LIST)) { break; } } @@ -167,30 +177,4 @@ class SharedScope extends ResourceScopeImpl { } } } - - /** - * A shared resource scope handle; this implementation has to handle close vs. close races. - */ - class SharedHandle implements HandleImpl { - final AtomicBoolean released = new AtomicBoolean(false); - - @Override - public ResourceScopeImpl scope() { - return SharedScope.this; - } - - @Override - public void release() { - if (released.compareAndSet(false, true)) { - int value; - do { - value = (int) STATE.getVolatile(jdk.internal.foreign.SharedScope.this); - if (value <= ALIVE) { - //cannot get here - we can't close segment twice - throw new IllegalStateException("Already closed"); - } - } while (!STATE.compareAndSet(jdk.internal.foreign.SharedScope.this, value, value - 1)); - } - } - } } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/SystemLookup.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/SystemLookup.java index 24743c7deebbac0adbb59d56d76d18937c0aa383..45c637b06bfb2eecce1a0d8ab75378da1771d096 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/SystemLookup.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/SystemLookup.java @@ -25,8 +25,8 @@ package jdk.internal.foreign; -import jdk.incubator.foreign.MemoryAccess; import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.NativeSymbol; import jdk.incubator.foreign.ResourceScope; import jdk.incubator.foreign.SymbolLookup; import jdk.incubator.foreign.MemoryAddress; @@ -39,13 +39,13 @@ import java.util.Objects; import java.util.Optional; import java.util.function.Function; -import static jdk.incubator.foreign.CLinker.C_POINTER; +import static jdk.incubator.foreign.ValueLayout.ADDRESS; public class SystemLookup implements SymbolLookup { private SystemLookup() { } - final static SystemLookup INSTANCE = new SystemLookup(); + static final SystemLookup INSTANCE = new SystemLookup(); /* * On POSIX systems, dlsym will allow us to lookup symbol in library dependencies; the same trick doesn't work @@ -71,11 +71,11 @@ public class SystemLookup implements SymbolLookup { SymbolLookup fallbackLibLookup = libLookup(libs -> libs.loadLibrary("WinFallbackLookup")); int numSymbols = WindowsFallbackSymbols.values().length; - MemorySegment funcs = fallbackLibLookup.lookup("funcs").orElseThrow() - .asSegment(C_POINTER.byteSize() * numSymbols, ResourceScope.newImplicitScope()); + MemorySegment funcs = MemorySegment.ofAddress(fallbackLibLookup.lookup("funcs").orElseThrow().address(), + ADDRESS.byteSize() * numSymbols, ResourceScope.globalScope()); SymbolLookup fallbackLookup = name -> Optional.ofNullable(WindowsFallbackSymbols.valueOfOrNull(name)) - .map(symbol -> MemoryAccess.getAddressAtIndex(funcs, symbol.ordinal())); + .map(symbol -> NativeSymbol.ofAddress(symbol.name(), funcs.getAtIndex(ADDRESS, symbol.ordinal()), ResourceScope.globalScope())); final SymbolLookup finalLookup = lookup; lookup = name -> finalLookup.lookup(name).or(() -> fallbackLookup.lookup(name)); @@ -91,7 +91,8 @@ public class SystemLookup implements SymbolLookup { try { long addr = lib.lookup(name); return addr == 0 ? - Optional.empty() : Optional.of(MemoryAddress.ofLong(addr)); + Optional.empty() : + Optional.of(NativeSymbol.ofAddress(name, MemoryAddress.ofLong(addr), ResourceScope.globalScope())); } catch (NoSuchMethodException e) { return Optional.empty(); } @@ -99,7 +100,7 @@ public class SystemLookup implements SymbolLookup { } @Override - public Optional lookup(String name) { + public Optional lookup(String name) { return syslookup.lookup(name); } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/Utils.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/Utils.java index f3b0240d2d0ca37356edc81d1f0dd65457b7ea32..6272e6e31005de03b6610013e831dd7c5dccfae9 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/Utils.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/Utils.java @@ -27,17 +27,19 @@ package jdk.internal.foreign; import jdk.incubator.foreign.*; +import jdk.internal.access.SharedSecrets; import jdk.internal.access.foreign.MemorySegmentProxy; -import jdk.internal.misc.VM; -import sun.invoke.util.Wrapper; +import jdk.internal.vm.annotation.ForceInline; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.lang.invoke.VarHandle; -import java.util.Optional; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Supplier; +import static jdk.incubator.foreign.ValueLayout.JAVA_BYTE; import static sun.security.action.GetPropertyAction.*; /** @@ -49,6 +51,10 @@ public final class Utils { = Boolean.parseBoolean(privilegedGetProperty("jdk.internal.foreign.SHOULD_ADAPT_HANDLES", "true")); private static final MethodHandle SEGMENT_FILTER; + private static final MethodHandle BYTE_TO_BOOL; + private static final MethodHandle BOOL_TO_BYTE; + private static final MethodHandle ADDRESS_TO_LONG; + private static final MethodHandle LONG_TO_ADDRESS; public static final MethodHandle MH_bitsToBytesOrThrowForOffset; public static final Supplier bitsToBytesThrowOffset @@ -59,6 +65,14 @@ public final class Utils { MethodHandles.Lookup lookup = MethodHandles.lookup(); SEGMENT_FILTER = lookup.findStatic(Utils.class, "filterSegment", MethodType.methodType(MemorySegmentProxy.class, MemorySegment.class)); + BYTE_TO_BOOL = lookup.findStatic(Utils.class, "byteToBoolean", + MethodType.methodType(boolean.class, byte.class)); + BOOL_TO_BYTE = lookup.findStatic(Utils.class, "booleanToByte", + MethodType.methodType(byte.class, boolean.class)); + ADDRESS_TO_LONG = lookup.findVirtual(MemoryAddress.class, "toRawLongValue", + MethodType.methodType(long.class)); + LONG_TO_ADDRESS = lookup.findStatic(MemoryAddress.class, "ofLong", + MethodType.methodType(MemoryAddress.class, long.class)); MH_bitsToBytesOrThrowForOffset = MethodHandles.insertArguments( lookup.findStatic(Utils.class, "bitsToBytesOrThrow", MethodType.methodType(long.class, long.class, Supplier.class)), @@ -91,38 +105,72 @@ public final class Utils { } } - public static VarHandle fixUpVarHandle(VarHandle handle) { + public static VarHandle makeMemoryAccessVarHandle(ValueLayout layout, boolean skipAlignmentCheck) { + class VarHandleCache { + private static final Map handleMap = new ConcurrentHashMap<>(); + private static final Map handleMapNoAlignCheck = new ConcurrentHashMap<>(); + + static VarHandle put(ValueLayout layout, VarHandle handle, boolean skipAlignmentCheck) { + VarHandle prev = (skipAlignmentCheck ? handleMapNoAlignCheck : handleMap).putIfAbsent(layout, handle); + return prev != null ? prev : handle; + } + } + Class baseCarrier = layout.carrier(); + if (layout.carrier() == MemoryAddress.class) { + baseCarrier = switch ((int) ValueLayout.ADDRESS.byteSize()) { + case 8 -> long.class; + case 4 -> int.class; + default -> throw new UnsupportedOperationException("Unsupported address layout"); + }; + } else if (layout.carrier() == boolean.class) { + baseCarrier = byte.class; + } + + VarHandle handle = SharedSecrets.getJavaLangInvokeAccess().memoryAccessVarHandle(baseCarrier, skipAlignmentCheck, + layout.byteAlignment() - 1, layout.order()); + // This adaptation is required, otherwise the memory access var handle will have type MemorySegmentProxy, // and not MemorySegment (which the user expects), which causes performance issues with asType() adaptations. - return SHOULD_ADAPT_HANDLES + handle = SHOULD_ADAPT_HANDLES ? MemoryHandles.filterCoordinates(handle, 0, SEGMENT_FILTER) : handle; + if (layout.carrier() == boolean.class) { + handle = MemoryHandles.filterValue(handle, BOOL_TO_BYTE, BYTE_TO_BOOL); + } else if (layout.carrier() == MemoryAddress.class) { + handle = MemoryHandles.filterValue(handle, + MethodHandles.explicitCastArguments(ADDRESS_TO_LONG, MethodType.methodType(baseCarrier, MemoryAddress.class)), + MethodHandles.explicitCastArguments(LONG_TO_ADDRESS, MethodType.methodType(MemoryAddress.class, baseCarrier))); + } + return VarHandleCache.put(layout, handle, skipAlignmentCheck); } private static MemorySegmentProxy filterSegment(MemorySegment segment) { return (AbstractMemorySegmentImpl)segment; } - public static void checkPrimitiveCarrierCompat(Class carrier, MemoryLayout layout) { - checkLayoutType(layout, ValueLayout.class); - if (!isValidPrimitiveCarrier(carrier)) - throw new IllegalArgumentException("Unsupported carrier: " + carrier); - if (Wrapper.forPrimitiveType(carrier).bitWidth() != layout.bitSize()) - throw new IllegalArgumentException("Carrier size mismatch: " + carrier + " != " + layout); + private static boolean byteToBoolean(byte b) { + return b != 0; + } + + private static byte booleanToByte(boolean b) { + return b ? (byte)1 : (byte)0; + } + + public static void copy(MemorySegment addr, byte[] bytes) { + var heapSegment = MemorySegment.ofArray(bytes); + addr.copyFrom(heapSegment); + addr.set(JAVA_BYTE, bytes.length, (byte)0); } - public static boolean isValidPrimitiveCarrier(Class carrier) { - return carrier == byte.class - || carrier == short.class - || carrier == char.class - || carrier == int.class - || carrier == long.class - || carrier == float.class - || carrier == double.class; + public static MemorySegment toCString(byte[] bytes, SegmentAllocator allocator) { + MemorySegment addr = allocator.allocate(bytes.length + 1, 1L); + copy(addr, bytes); + return addr; } - public static void checkLayoutType(MemoryLayout layout, Class layoutType) { - if (!layoutType.isInstance(layout)) - throw new IllegalArgumentException("Expected a " + layoutType.getSimpleName() + ": " + layout); + @ForceInline + public static long scaleOffset(MemorySegment segment, long index, long size) { + // note: we know size is a small value (as it comes from ValueLayout::byteSize()) + return MemorySegmentProxy.multiplyOffsets(index, (int)size, (AbstractMemorySegmentImpl)segment); } } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/Binding.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/Binding.java index 5b8468eafd30f223ddedf208db268c4092d14e6e..30623223169852d6d581967aa0d6f813440ae664 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/Binding.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/Binding.java @@ -24,17 +24,20 @@ */ package jdk.internal.foreign.abi; +import jdk.incubator.foreign.Addressable; import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemoryHandles; import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; import jdk.incubator.foreign.SegmentAllocator; +import jdk.incubator.foreign.ValueLayout; import jdk.internal.foreign.MemoryAddressImpl; import jdk.internal.foreign.ResourceScopeImpl; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; import java.util.ArrayList; import java.util.Deque; import java.util.List; @@ -204,7 +207,6 @@ import static java.lang.invoke.MethodType.methodType; public abstract class Binding { private static final MethodHandle MH_UNBOX_ADDRESS; private static final MethodHandle MH_BOX_ADDRESS; - private static final MethodHandle MH_BASE_ADDRESS; private static final MethodHandle MH_COPY_BUFFER; private static final MethodHandle MH_ALLOCATE_BUFFER; private static final MethodHandle MH_TO_SEGMENT; @@ -216,8 +218,6 @@ public abstract class Binding { methodType(long.class)); MH_BOX_ADDRESS = lookup.findStatic(MemoryAddress.class, "ofLong", methodType(MemoryAddress.class, long.class)); - MH_BASE_ADDRESS = lookup.findVirtual(MemorySegment.class, "address", - methodType(MemoryAddress.class)); MH_COPY_BUFFER = lookup.findStatic(Binding.Copy.class, "copyBuffer", methodType(MemorySegment.class, MemorySegment.class, long.class, long.class, Context.class)); MH_ALLOCATE_BUFFER = lookup.findStatic(Binding.Allocate.class, "allocateBuffer", @@ -262,7 +262,7 @@ public abstract class Binding { */ public static Context ofBoundedAllocator(long size) { ResourceScope scope = ResourceScope.newConfinedScope(); - return new Context(SegmentAllocator.arenaAllocator(size, scope), scope); + return new Context(SegmentAllocator.newNativeArena(size, scope), scope); } /** @@ -321,7 +321,6 @@ public abstract class Binding { ALLOC_BUFFER, BOX_ADDRESS, UNBOX_ADDRESS, - BASE_ADDRESS, TO_SEGMENT, DUP } @@ -344,7 +343,7 @@ public abstract class Binding { public abstract MethodHandle specialize(MethodHandle specializedHandle, int insertPos, int allocatorPos); private static void checkType(Class type) { - if (!type.isPrimitive() || type == void.class || type == boolean.class) + if (!type.isPrimitive() || type == void.class) throw new IllegalArgumentException("Illegal type: " + type); } @@ -388,11 +387,11 @@ public abstract class Binding { } public static UnboxAddress unboxAddress() { - return UnboxAddress.INSTANCE; + return UnboxAddress.INSTANCE.get(MemoryAddress.class); } - public static BaseAddress baseAddress() { - return BaseAddress.INSTANCE; + public static UnboxAddress unboxAddress(Class carrier) { + return UnboxAddress.INSTANCE.get(carrier); } public static ToSegment toSegment(MemoryLayout layout) { @@ -467,8 +466,8 @@ public abstract class Binding { return this; } - public Binding.Builder baseAddress() { - bindings.add(Binding.baseAddress()); + public Binding.Builder unboxAddress(Class carrier) { + bindings.add(Binding.unboxAddress(carrier)); return this; } @@ -487,7 +486,7 @@ public abstract class Binding { } } - static abstract class Move extends Binding { + abstract static class Move extends Binding { private final VMStorage storage; private final Class type; @@ -593,7 +592,7 @@ public abstract class Binding { } } - private static abstract class Dereference extends Binding { + private abstract static class Dereference extends Binding { private final long offset; private final Class type; @@ -630,7 +629,8 @@ public abstract class Binding { // alignment is set to 1 byte here to avoid exceptions for cases where we do super word // copies of e.g. 2 int fields of a struct as a single long, while the struct is only // 4-byte-aligned (since it only contains ints) - return MemoryHandles.insertCoordinates(MemoryHandles.varHandle(type, 1, ByteOrder.nativeOrder()), 1, offset); + ValueLayout layout = MemoryLayout.valueLayout(type(), ByteOrder.nativeOrder()).withBitAlignment(8); + return MemoryHandles.insertCoordinates(MemoryHandles.varHandle(layout), 1, offset); } } @@ -740,9 +740,8 @@ public abstract class Binding { private static MemorySegment copyBuffer(MemorySegment operand, long size, long alignment, Context context) { - MemorySegment copy = context.allocator().allocate(size, alignment); - copy.copyFrom(operand.asSlice(0, size)); - return copy; + return context.allocator().allocate(size, alignment) + .copyFrom(operand.asSlice(0, size)); } public long size() { @@ -875,27 +874,44 @@ public abstract class Binding { * and pushes that onto the operand stack. */ public static class UnboxAddress extends Binding { - private static final UnboxAddress INSTANCE = new UnboxAddress(); - private UnboxAddress() { + + static final ClassValue INSTANCE = new ClassValue<>() { + @Override + protected UnboxAddress computeValue(Class type) { + return new UnboxAddress(type); + } + }; + + final Class carrier; + final MethodHandle toAddress; + + private UnboxAddress(Class carrier) { super(Tag.UNBOX_ADDRESS); + this.carrier = carrier; + try { + this.toAddress = MethodHandles.lookup().findVirtual(carrier, "address", MethodType.methodType(MemoryAddress.class)); + } catch (Throwable ex) { + throw new IllegalArgumentException(ex); + } } @Override public void verify(Deque> stack) { Class actualType = stack.pop(); - SharedUtils.checkType(actualType, MemoryAddress.class); + SharedUtils.checkType(actualType, carrier); stack.push(long.class); } @Override public void interpret(Deque stack, BindingInterpreter.StoreFunc storeFunc, BindingInterpreter.LoadFunc loadFunc, Context context) { - stack.push(((MemoryAddress)stack.pop()).toRawLongValue()); + stack.push(((Addressable)stack.pop()).address().toRawLongValue()); } @Override public MethodHandle specialize(MethodHandle specializedHandle, int insertPos, int allocatorPos) { - return filterArguments(specializedHandle, insertPos, MH_UNBOX_ADDRESS); + return filterArguments(specializedHandle, insertPos, + MethodHandles.filterReturnValue(toAddress, MH_UNBOX_ADDRESS)); } @Override @@ -939,41 +955,6 @@ public abstract class Binding { } } - /** - * BASE_ADDRESS() - * Pops a MemorySegment from the operand stack, and takes the base address of the segment - * (the MemoryAddress that points to the start), and pushes that onto the operand stack - */ - public static class BaseAddress extends Binding { - private static final BaseAddress INSTANCE = new BaseAddress(); - private BaseAddress() { - super(Tag.BASE_ADDRESS); - } - - @Override - public void verify(Deque> stack) { - Class actualType = stack.pop(); - SharedUtils.checkType(actualType, MemorySegment.class); - stack.push(MemoryAddress.class); - } - - @Override - public void interpret(Deque stack, BindingInterpreter.StoreFunc storeFunc, - BindingInterpreter.LoadFunc loadFunc, Context context) { - stack.push(((MemorySegment) stack.pop()).address()); - } - - @Override - public MethodHandle specialize(MethodHandle specializedHandle, int insertPos, int allocatorPos) { - return filterArguments(specializedHandle, insertPos, MH_BASE_ADDRESS); - } - - @Override - public String toString() { - return "BaseAddress{}"; - } - } - /** * TO_SEGMENT([size]) * Pops a MemoryAddress from the operand stack, and converts it to a MemorySegment diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/BufferLayout.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/BufferLayout.java index d290a36cc737ce7b63c7f5fc6bae9e7448355b03..5308533676f29cfed09911f212057f9d9acb2cfe 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/BufferLayout.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/BufferLayout.java @@ -24,8 +24,8 @@ */ package jdk.internal.foreign.abi; -import jdk.incubator.foreign.MemoryLayouts; import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.ValueLayout; import jdk.internal.foreign.MemoryAddressImpl; import java.io.PrintStream; @@ -34,7 +34,7 @@ import java.util.HashMap; import java.util.Map; class BufferLayout { - static final VarHandle VH_LONG = MemoryLayouts.JAVA_LONG.varHandle(long.class); + static final VarHandle VH_LONG = ValueLayout.JAVA_LONG.varHandle(); final long size; final long arguments_next_pc; diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/CallingSequence.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/CallingSequence.java index 1412304a4cb03e074bafc6e65f16f510f20ae31d..614166b83d1b2511e473d1b11d8d6013d9061dfe 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/CallingSequence.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/CallingSequence.java @@ -28,7 +28,6 @@ import jdk.incubator.foreign.FunctionDescriptor; import java.lang.invoke.MethodType; import java.util.List; -import java.util.stream.IntStream; import java.util.stream.Stream; public class CallingSequence { diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/CallingSequenceBuilder.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/CallingSequenceBuilder.java index bdc8474d2b9492e58d4429df6b46296ecce5da6e..3f36ec22f2f408d944cd6421a13adfe76911b05d 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/CallingSequenceBuilder.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/CallingSequenceBuilder.java @@ -59,7 +59,7 @@ public class CallingSequenceBuilder { verifyBindings(true, carrier, bindings); inputBindings.add(bindings); mt = mt.appendParameterTypes(carrier); - desc = desc.withAppendedArgumentLayouts(layout); + desc = desc.appendArgumentLayouts(layout); return this; } @@ -68,7 +68,7 @@ public class CallingSequenceBuilder { verifyBindings(false, carrier, bindings); this.outputBindings = bindings; mt = mt.changeReturnType(carrier); - desc = desc.withReturnLayout(layout); + desc = desc.changeReturnLayout(layout); return this; } @@ -100,7 +100,6 @@ public class CallingSequenceBuilder { //ALLOC_BUFFER, //BOX_ADDRESS, UNBOX_ADDRESS, - BASE_ADDRESS, //TO_SEGMENT, DUP ); @@ -129,7 +128,6 @@ public class CallingSequenceBuilder { ALLOC_BUFFER, BOX_ADDRESS, //UNBOX_ADDRESS, - //BASE_ADDRESS, TO_SEGMENT, DUP ); diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/ProgrammableInvoker.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/ProgrammableInvoker.java index 4e7b4b37ea6b6223be8c68d4ae90999ac809c774..304e028c5d7317c2205a705b7b3c89999d0f496a 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/ProgrammableInvoker.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/ProgrammableInvoker.java @@ -25,11 +25,11 @@ package jdk.internal.foreign.abi; import jdk.incubator.foreign.Addressable; -import jdk.incubator.foreign.MemoryAddress; -import jdk.incubator.foreign.MemoryLayouts; import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.NativeSymbol; import jdk.incubator.foreign.ResourceScope; import jdk.incubator.foreign.SegmentAllocator; +import jdk.incubator.foreign.ValueLayout; import jdk.internal.access.JavaLangInvokeAccess; import jdk.internal.access.SharedSecrets; import jdk.internal.invoke.NativeEntryPoint; @@ -40,7 +40,6 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.lang.invoke.VarHandle; -import java.lang.ref.Reference; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -70,7 +69,7 @@ public class ProgrammableInvoker { private static final JavaLangInvokeAccess JLIA = SharedSecrets.getJavaLangInvokeAccess(); - private static final VarHandle VH_LONG = MemoryLayouts.JAVA_LONG.varHandle(long.class); + private static final VarHandle VH_LONG = ValueLayout.JAVA_LONG.varHandle(); private static final MethodHandle MH_INVOKE_MOVES; private static final MethodHandle MH_INVOKE_INTERP_BINDINGS; @@ -87,10 +86,10 @@ public class ProgrammableInvoker { MH_INVOKE_MOVES = lookup.findVirtual(ProgrammableInvoker.class, "invokeMoves", methodType(Object.class, long.class, Object[].class, Binding.VMStore[].class, Binding.VMLoad[].class)); MH_INVOKE_INTERP_BINDINGS = lookup.findVirtual(ProgrammableInvoker.class, "invokeInterpBindings", - methodType(Object.class, Addressable.class, SegmentAllocator.class, Object[].class, MethodHandle.class, Map.class, Map.class)); + methodType(Object.class, NativeSymbol.class, SegmentAllocator.class, Object[].class, MethodHandle.class, Map.class, Map.class)); MH_WRAP_ALLOCATOR = lookup.findStatic(Binding.Context.class, "ofAllocator", methodType(Binding.Context.class, SegmentAllocator.class)); - MH_ADDR_TO_LONG = lookup.findStatic(ProgrammableInvoker.class, "unboxTargetAddress", methodType(long.class, Addressable.class)); + MH_ADDR_TO_LONG = lookup.findStatic(ProgrammableInvoker.class, "unboxTargetAddress", methodType(long.class, NativeSymbol.class)); } catch (ReflectiveOperationException e) { throw new RuntimeException(e); } @@ -172,9 +171,9 @@ public class ProgrammableInvoker { return handle; } - private static long unboxTargetAddress(Addressable addr) { - MemoryAddress ma = SharedUtils.checkSymbol(addr); - return ma.toRawLongValue(); + private static long unboxTargetAddress(NativeSymbol addr) { + SharedUtils.checkSymbol(addr); + return addr.address().toRawLongValue(); } // Funnel from type to Object[] @@ -312,7 +311,7 @@ public class ProgrammableInvoker { } } - Object invokeInterpBindings(Addressable address, SegmentAllocator allocator, Object[] args, MethodHandle leaf, + Object invokeInterpBindings(NativeSymbol symbol, SegmentAllocator allocator, Object[] args, MethodHandle leaf, Map argIndexMap, Map retIndexMap) throws Throwable { Binding.Context unboxContext = bufferCopySize != 0 @@ -321,21 +320,17 @@ public class ProgrammableInvoker { try (unboxContext) { // do argument processing, get Object[] as result Object[] leafArgs = new Object[leaf.type().parameterCount()]; - leafArgs[0] = address; // addr + leafArgs[0] = symbol; // symbol for (int i = 0; i < args.length; i++) { Object arg = args[i]; BindingInterpreter.unbox(arg, callingSequence.argumentBindings(i), (storage, type, value) -> { - leafArgs[argIndexMap.get(storage) + 1] = value; // +1 to skip addr + leafArgs[argIndexMap.get(storage) + 1] = value; // +1 to skip symbol }, unboxContext); } // call leaf Object o = leaf.invokeWithArguments(leafArgs); - // make sure arguments are reachable during the call - // technically we only need to do all Addressable parameters here - Reference.reachabilityFence(address); - Reference.reachabilityFence(args); // return value processing if (o == null) { diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/ProgrammableUpcallHandler.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/ProgrammableUpcallHandler.java index 0f1a04619f6a80bc5713e817cd9533d609146f5d..ba8090f669ced45a1d466f66ff6eba1a88387012 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/ProgrammableUpcallHandler.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/ProgrammableUpcallHandler.java @@ -26,10 +26,10 @@ package jdk.internal.foreign.abi; import jdk.incubator.foreign.MemoryAddress; -import jdk.incubator.foreign.MemoryLayouts; import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.NativeSymbol; import jdk.incubator.foreign.ResourceScope; -import jdk.incubator.foreign.SegmentAllocator; +import jdk.incubator.foreign.ValueLayout; import jdk.internal.access.JavaLangInvokeAccess; import jdk.internal.access.SharedSecrets; import jdk.internal.foreign.MemoryAddressImpl; @@ -46,6 +46,7 @@ import java.util.Objects; import java.util.stream.Stream; import static java.lang.invoke.MethodHandles.dropArguments; +import static java.lang.invoke.MethodHandles.exactInvoker; import static java.lang.invoke.MethodHandles.filterReturnValue; import static java.lang.invoke.MethodHandles.identity; import static java.lang.invoke.MethodHandles.insertArguments; @@ -69,7 +70,7 @@ public class ProgrammableUpcallHandler { private static final JavaLangInvokeAccess JLI = SharedSecrets.getJavaLangInvokeAccess(); - private static final VarHandle VH_LONG = MemoryLayouts.JAVA_LONG.varHandle(long.class); + private static final VarHandle VH_LONG = ValueLayout.JAVA_LONG.varHandle(); private static final MethodHandle MH_invokeMoves; private static final MethodHandle MH_invokeInterpBindings; @@ -88,7 +89,7 @@ public class ProgrammableUpcallHandler { } } - public static UpcallHandler make(ABIDescriptor abi, MethodHandle target, CallingSequence callingSequence) { + public static NativeSymbol make(ABIDescriptor abi, MethodHandle target, CallingSequence callingSequence, ResourceScope scope) { Binding.VMLoad[] argMoves = argMoveBindings(callingSequence); Binding.VMStore[] retMoves = retMoveBindings(callingSequence); @@ -134,7 +135,7 @@ public class ProgrammableUpcallHandler { MethodHandle invokeMoves = insertArguments(MH_invokeMoves, 1, doBindingsErased, argMoves, retMoves, abi, layout); entryPoint = allocateUpcallStub(invokeMoves, abi, layout); } - return () -> entryPoint; + return UpcallStubs.makeUpcall(entryPoint, scope); } private static void checkPrimitive(MethodType type) { diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/SharedUtils.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/SharedUtils.java index d080d1de1910f47de09a11bd18259e2ff72fb67a..967fd203e04b08968e0f44f6a3f910bd441b733a 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/SharedUtils.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/SharedUtils.java @@ -25,40 +25,45 @@ package jdk.internal.foreign.abi; import jdk.incubator.foreign.Addressable; +import jdk.incubator.foreign.CLinker; import jdk.incubator.foreign.FunctionDescriptor; import jdk.incubator.foreign.GroupLayout; -import jdk.incubator.foreign.MemoryAccess; import jdk.incubator.foreign.MemoryAddress; -import jdk.incubator.foreign.MemoryHandles; import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.NativeSymbol; import jdk.incubator.foreign.ResourceScope; import jdk.incubator.foreign.SegmentAllocator; import jdk.incubator.foreign.SequenceLayout; -import jdk.incubator.foreign.CLinker; +import jdk.incubator.foreign.VaList; import jdk.incubator.foreign.ValueLayout; import jdk.internal.access.JavaLangAccess; +import jdk.internal.access.JavaLangInvokeAccess; import jdk.internal.access.SharedSecrets; +import jdk.internal.foreign.Scoped; import jdk.internal.foreign.CABI; import jdk.internal.foreign.MemoryAddressImpl; +import jdk.internal.foreign.ResourceScopeImpl; import jdk.internal.foreign.Utils; import jdk.internal.foreign.abi.aarch64.linux.LinuxAArch64Linker; import jdk.internal.foreign.abi.aarch64.macos.MacOsAArch64Linker; import jdk.internal.foreign.abi.x64.sysv.SysVx64Linker; import jdk.internal.foreign.abi.x64.windows.Windowsx64Linker; +import jdk.internal.vm.annotation.ForceInline; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.lang.invoke.VarHandle; import java.lang.ref.Reference; -import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.function.Consumer; +import java.util.function.UnaryOperator; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -67,17 +72,26 @@ import static java.lang.invoke.MethodHandles.constant; import static java.lang.invoke.MethodHandles.dropArguments; import static java.lang.invoke.MethodHandles.dropReturn; import static java.lang.invoke.MethodHandles.empty; -import static java.lang.invoke.MethodHandles.filterArguments; +import static java.lang.invoke.MethodHandles.foldArguments; import static java.lang.invoke.MethodHandles.identity; import static java.lang.invoke.MethodHandles.insertArguments; import static java.lang.invoke.MethodHandles.permuteArguments; import static java.lang.invoke.MethodHandles.tryFinally; import static java.lang.invoke.MethodType.methodType; -import static jdk.incubator.foreign.CLinker.*; +import static jdk.incubator.foreign.ValueLayout.ADDRESS; +import static jdk.incubator.foreign.ValueLayout.JAVA_BOOLEAN; +import static jdk.incubator.foreign.ValueLayout.JAVA_BYTE; +import static jdk.incubator.foreign.ValueLayout.JAVA_CHAR; +import static jdk.incubator.foreign.ValueLayout.JAVA_DOUBLE; +import static jdk.incubator.foreign.ValueLayout.JAVA_FLOAT; +import static jdk.incubator.foreign.ValueLayout.JAVA_INT; +import static jdk.incubator.foreign.ValueLayout.JAVA_LONG; +import static jdk.incubator.foreign.ValueLayout.JAVA_SHORT; public class SharedUtils { private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess(); + private static final JavaLangInvokeAccess JLIA = SharedSecrets.getJavaLangInvokeAccess(); private static final MethodHandle MH_ALLOC_BUFFER; private static final MethodHandle MH_BASEADDRESS; @@ -87,6 +101,8 @@ public class SharedUtils { private static final MethodHandle MH_CLOSE_CONTEXT; private static final MethodHandle MH_REACHBILITY_FENCE; private static final MethodHandle MH_HANDLE_UNCAUGHT_EXCEPTION; + private static final MethodHandle ACQUIRE_MH; + private static final MethodHandle RELEASE_MH; static { try { @@ -107,13 +123,19 @@ public class SharedUtils { methodType(void.class, Object.class)); MH_HANDLE_UNCAUGHT_EXCEPTION = lookup.findStatic(SharedUtils.class, "handleUncaughtException", methodType(void.class, Throwable.class)); + ACQUIRE_MH = MethodHandles.lookup().findStatic(SharedUtils.class, "acquire", + MethodType.methodType(void.class, Scoped[].class)); + RELEASE_MH = MethodHandles.lookup().findStatic(SharedUtils.class, "release", + MethodType.methodType(void.class, Scoped[].class)); } catch (ReflectiveOperationException e) { throw new BootstrapMethodError(e); } } // this allocator should be used when no allocation is expected - public static final SegmentAllocator THROWING_ALLOCATOR = (size, align) -> { throw new IllegalStateException("Cannot get here"); }; + public static final SegmentAllocator THROWING_ALLOCATOR = (size, align) -> { + throw new IllegalStateException("Cannot get here"); + }; /** * Align the specified type from a given address @@ -225,34 +247,6 @@ public class SharedUtils { return dest; } - public static void checkCompatibleType(Class carrier, MemoryLayout layout, long addressSize) { - if (carrier.isPrimitive()) { - Utils.checkPrimitiveCarrierCompat(carrier, layout); - } else if (carrier == MemoryAddress.class) { - Utils.checkLayoutType(layout, ValueLayout.class); - if (layout.bitSize() != addressSize) - throw new IllegalArgumentException("Address size mismatch: " + addressSize + " != " + layout.bitSize()); - } else if (carrier == MemorySegment.class) { - Utils.checkLayoutType(layout, GroupLayout.class); - } else { - throw new IllegalArgumentException("Unsupported carrier: " + carrier); - } - } - - public static void checkFunctionTypes(MethodType mt, FunctionDescriptor cDesc, long addressSize) { - if (mt.returnType() == void.class != cDesc.returnLayout().isEmpty()) - throw new IllegalArgumentException("Return type mismatch: " + mt + " != " + cDesc); - List argLayouts = cDesc.argumentLayouts(); - if (mt.parameterCount() != argLayouts.size()) - throw new IllegalArgumentException("Arity mismatch: " + mt + " != " + cDesc); - - int paramCount = mt.parameterCount(); - for (int i = 0; i < paramCount; i++) { - checkCompatibleType(mt.parameterType(i), argLayouts.get(i), addressSize); - } - cDesc.returnLayout().ifPresent(rl -> checkCompatibleType(mt.returnType(), rl, addressSize)); - } - public static Class primitiveCarrierForSize(long size, boolean useFloat) { if (useFloat) { if (size == 4) { @@ -287,15 +281,14 @@ public class SharedUtils { public static String toJavaStringInternal(MemorySegment segment, long start) { int len = strlen(segment, start); byte[] bytes = new byte[len]; - MemorySegment.ofArray(bytes) - .copyFrom(segment.asSlice(start, len)); + MemorySegment.copy(segment, JAVA_BYTE, start, bytes, 0, len); return new String(bytes, StandardCharsets.UTF_8); } private static int strlen(MemorySegment segment, long start) { // iterate until overflow (String can only hold a byte[], whose length can be expressed as an int) for (int offset = 0; offset >= 0; offset++) { - byte curr = MemoryAccess.getByteAtOffset(segment, start + offset); + byte curr = segment.get(JAVA_BYTE, start + offset); if (curr == 0) { return offset; } @@ -392,31 +385,21 @@ public class SharedUtils { insertPos = 1; } else { closer = identity(specializedHandle.type().returnType()); // (V) -> V - closer = dropArguments(closer, 0, Throwable.class); // (Throwable, V) -> V + if (!upcall) { + closer = dropArguments(closer, 0, Throwable.class); // (Throwable, V) -> V + } else { + closer = collectArguments(closer, 0, MH_HANDLE_UNCAUGHT_EXCEPTION); // (Throwable, V) -> V + } insertPos = 2; } - // downcalls get the leading Addressable/SegmentAllocator param as well + // downcalls get the leading NativeSymbol/SegmentAllocator param as well if (!upcall) { - closer = collectArguments(closer, insertPos++, reachabilityFenceHandle(Addressable.class)); - closer = dropArguments(closer, insertPos++, SegmentAllocator.class); // (Throwable, V?, Addressable, SegmentAllocator) -> V/void + closer = collectArguments(closer, insertPos++, reachabilityFenceHandle(NativeSymbol.class)); + closer = dropArguments(closer, insertPos++, SegmentAllocator.class); // (Throwable, V?, NativeSymbol, SegmentAllocator) -> V/void } - closer = collectArguments(closer, insertPos++, MH_CLOSE_CONTEXT); // (Throwable, V?, Addressable?, BindingContext) -> V/void - - if (!upcall) { - // now for each Addressable parameter, add a reachability fence - MethodType specType = specializedHandle.type(); - // skip 3 for address, segment allocator, and binding context - for (int i = 3; i < specType.parameterCount(); i++) { - Class param = specType.parameterType(i); - if (Addressable.class.isAssignableFrom(param)) { - closer = collectArguments(closer, insertPos++, reachabilityFenceHandle(param)); - } else { - closer = dropArguments(closer, insertPos++, param); - } - } - } + closer = collectArguments(closer, insertPos++, MH_CLOSE_CONTEXT); // (Throwable, V?, NativeSymbol?, BindingContext) -> V/void MethodHandle contextFactory; @@ -434,34 +417,171 @@ public class SharedUtils { return specializedHandle; } + @ForceInline + @SuppressWarnings("fallthrough") + public static void acquire(Scoped[] args) { + ResourceScope scope4 = null; + ResourceScope scope3 = null; + ResourceScope scope2 = null; + ResourceScope scope1 = null; + ResourceScope scope0 = null; + switch (args.length) { + default: + // slow path, acquire all remaining addressable parameters in isolation + for (int i = 5 ; i < args.length ; i++) { + acquire(args[i].scope()); + } + // fast path, acquire only scopes not seen in other parameters + case 5: + scope4 = args[4].scope(); + acquire(scope4); + case 4: + scope3 = args[3].scope(); + if (scope3 != scope4) + acquire(scope3); + case 3: + scope2 = args[2].scope(); + if (scope2 != scope3 && scope2 != scope4) + acquire(scope2); + case 2: + scope1 = args[1].scope(); + if (scope1 != scope2 && scope1 != scope3 && scope1 != scope4) + acquire(scope1); + case 1: + scope0 = args[0].scope(); + if (scope0 != scope1 && scope0 != scope2 && scope0 != scope3 && scope0 != scope4) + acquire(scope0); + case 0: break; + } + } + + @ForceInline + @SuppressWarnings("fallthrough") + public static void release(Scoped[] args) { + ResourceScope scope4 = null; + ResourceScope scope3 = null; + ResourceScope scope2 = null; + ResourceScope scope1 = null; + ResourceScope scope0 = null; + switch (args.length) { + default: + // slow path, release all remaining addressable parameters in isolation + for (int i = 5 ; i < args.length ; i++) { + release(args[i].scope()); + } + // fast path, release only scopes not seen in other parameters + case 5: + scope4 = args[4].scope(); + release(scope4); + case 4: + scope3 = args[3].scope(); + if (scope3 != scope4) + release(scope3); + case 3: + scope2 = args[2].scope(); + if (scope2 != scope3 && scope2 != scope4) + release(scope2); + case 2: + scope1 = args[1].scope(); + if (scope1 != scope2 && scope1 != scope3 && scope1 != scope4) + release(scope1); + case 1: + scope0 = args[0].scope(); + if (scope0 != scope1 && scope0 != scope2 && scope0 != scope3 && scope0 != scope4) + release(scope0); + case 0: break; + } + } + + @ForceInline + private static void acquire(ResourceScope scope) { + ((ResourceScopeImpl)scope).acquire0(); + } + + @ForceInline + private static void release(ResourceScope scope) { + ((ResourceScopeImpl)scope).release0(); + } + + /* + * This method adds a try/finally block to a downcall method handle, to make sure that all by-reference + * parameters (including the target address of the native function) are kept alive for the duration of + * the downcall. + */ + public static MethodHandle wrapDowncall(MethodHandle downcallHandle, FunctionDescriptor descriptor) { + boolean hasReturn = descriptor.returnLayout().isPresent(); + MethodHandle tryBlock = downcallHandle; + MethodHandle cleanup = hasReturn ? + MethodHandles.identity(downcallHandle.type().returnType()) : + MethodHandles.empty(MethodType.methodType(void.class)); + int addressableCount = 0; + List> adapters = new ArrayList<>(); + for (int i = 0 ; i < downcallHandle.type().parameterCount() ; i++) { + Class ptype = downcallHandle.type().parameterType(i); + if (ptype == Addressable.class || ptype == NativeSymbol.class) { + addressableCount++; + } else { + int pos = i; + adapters.add(mh -> dropArguments(mh, pos, ptype)); + } + } + + if (addressableCount > 0) { + cleanup = dropArguments(cleanup, 0, Throwable.class); + + MethodType adapterType = MethodType.methodType(void.class); + for (int i = 0 ; i < addressableCount ; i++) { + adapterType = adapterType.appendParameterTypes(i == 0 ? NativeSymbol.class : Addressable.class); + } + + MethodHandle acquireHandle = ACQUIRE_MH.asCollector(Scoped[].class, addressableCount).asType(adapterType); + MethodHandle releaseHandle = RELEASE_MH.asCollector(Scoped[].class, addressableCount).asType(adapterType); + + for (UnaryOperator adapter : adapters) { + acquireHandle = adapter.apply(acquireHandle); + releaseHandle = adapter.apply(releaseHandle); + } + + tryBlock = foldArguments(tryBlock, acquireHandle); + cleanup = collectArguments(cleanup, hasReturn ? 2 : 1, releaseHandle); + + return tryFinally(tryBlock, cleanup); + } else { + return downcallHandle; + } + } + + public static void checkExceptions(MethodHandle target) { + Class[] exceptions = JLIA.exceptionTypes(target); + if (exceptions != null && exceptions.length != 0) { + throw new IllegalArgumentException("Target handle may throw exceptions: " + Arrays.toString(exceptions)); + } + } + // lazy init MH_ALLOC and MH_FREE handles private static class AllocHolder { private static final CLinker SYS_LINKER = getSystemLinker(); - static final MethodHandle MH_MALLOC = SYS_LINKER.downcallHandle(CLinker.systemLookup().lookup("malloc").get(), - MethodType.methodType(MemoryAddress.class, long.class), - FunctionDescriptor.of(C_POINTER, C_LONG_LONG)); + static final MethodHandle MH_MALLOC = SYS_LINKER.downcallHandle(CLinker.systemCLinker().lookup("malloc").get(), + FunctionDescriptor.of(ADDRESS, JAVA_LONG)); - static final MethodHandle MH_FREE = SYS_LINKER.downcallHandle(CLinker.systemLookup().lookup("free").get(), - MethodType.methodType(void.class, MemoryAddress.class), - FunctionDescriptor.ofVoid(C_POINTER)); + static final MethodHandle MH_FREE = SYS_LINKER.downcallHandle(CLinker.systemCLinker().lookup("free").get(), + FunctionDescriptor.ofVoid(ADDRESS)); } - public static MemoryAddress checkSymbol(Addressable symbol) { - return checkAddressable(symbol, "Symbol is NULL"); + public static void checkSymbol(NativeSymbol symbol) { + checkAddressable(symbol, "Symbol is NULL"); } - public static MemoryAddress checkAddress(MemoryAddress address) { - return checkAddressable(address, "Address is NULL"); + public static void checkAddress(MemoryAddress address) { + checkAddressable(address, "Address is NULL"); } - private static MemoryAddress checkAddressable(Addressable symbol, String msg) { + private static void checkAddressable(Addressable symbol, String msg) { Objects.requireNonNull(symbol); - MemoryAddress symbolAddr = symbol.address(); - if (symbolAddr.equals(MemoryAddress.NULL)) - throw new IllegalArgumentException("Symbol is NULL: " + symbolAddr); - return symbolAddr; + if (symbol.address().toRawLongValue() == 0) + throw new IllegalArgumentException("Symbol is NULL: " + symbol); } public static MemoryAddress allocateMemoryInternal(long size) { @@ -474,7 +594,7 @@ public class SharedUtils { public static void freeMemoryInternal(MemoryAddress addr) { try { - AllocHolder.MH_FREE.invokeExact(addr); + AllocHolder.MH_FREE.invokeExact((Addressable)addr); } catch (Throwable th) { throw new RuntimeException(th); } @@ -489,12 +609,6 @@ public class SharedUtils { }; } - public static VarHandle vhPrimitiveOrAddress(Class carrier, MemoryLayout layout) { - return carrier == MemoryAddress.class - ? MemoryHandles.asAddressVarHandle(layout.varHandle(primitiveCarrierForSize(layout.byteSize(), false))) - : layout.varHandle(carrier); - } - public static VaList newVaListOfAddress(MemoryAddress ma, ResourceScope scope) { return switch (CABI.current()) { case Win64 -> Windowsx64Linker.newVaListOfAddress(ma, scope); @@ -513,34 +627,6 @@ public class SharedUtils { }; } - public static MethodType convertVaListCarriers(MethodType mt, Class carrier) { - Class[] params = new Class[mt.parameterCount()]; - for (int i = 0; i < params.length; i++) { - Class pType = mt.parameterType(i); - params[i] = ((pType == VaList.class) ? carrier : pType); - } - return methodType(mt.returnType(), params); - } - - public static MethodHandle unboxVaLists(MethodType type, MethodHandle handle, MethodHandle unboxer) { - for (int i = 0; i < type.parameterCount(); i++) { - if (type.parameterType(i) == VaList.class) { - handle = filterArguments(handle, i + 1, unboxer); // +1 for leading address - } - } - return handle; - } - - public static MethodHandle boxVaLists(MethodHandle handle, MethodHandle boxer) { - MethodType type = handle.type(); - for (int i = 0; i < type.parameterCount(); i++) { - if (type.parameterType(i) == VaList.class) { - handle = filterArguments(handle, i, boxer); - } - } - return handle; - } - static void checkType(Class actualType, Class expectedType) { if (expectedType != actualType) { throw new IllegalArgumentException( @@ -549,9 +635,12 @@ public class SharedUtils { } public static boolean isTrivial(FunctionDescriptor cDesc) { - return cDesc.attribute(FunctionDescriptor.TRIVIAL_ATTRIBUTE_NAME) - .map(Boolean.class::cast) - .orElse(false); + return false; // FIXME: use system property? + } + + public static boolean isVarargsIndex(FunctionDescriptor descriptor, int argIndex) { + int firstPos = descriptor.firstVariadicArgumentIndex(); + return firstPos != -1 && argIndex >= firstPos; } public static class SimpleVaArg { @@ -566,13 +655,11 @@ public class SharedUtils { } public VarHandle varHandle() { - return carrier == MemoryAddress.class - ? MemoryHandles.asAddressVarHandle(layout.varHandle(primitiveCarrierForSize(layout.byteSize(), false))) - : layout.varHandle(carrier); + return layout.varHandle(); } } - public static non-sealed class EmptyVaList implements VaList { + public static non-sealed class EmptyVaList implements VaList, Scoped { private final MemoryAddress address; @@ -585,32 +672,27 @@ public class SharedUtils { } @Override - public int vargAsInt(MemoryLayout layout) { - throw uoe(); - } - - @Override - public long vargAsLong(MemoryLayout layout) { + public int nextVarg(ValueLayout.OfInt layout) { throw uoe(); } @Override - public double vargAsDouble(MemoryLayout layout) { + public long nextVarg(ValueLayout.OfLong layout) { throw uoe(); } @Override - public MemoryAddress vargAsAddress(MemoryLayout layout) { + public double nextVarg(ValueLayout.OfDouble layout) { throw uoe(); } @Override - public MemorySegment vargAsSegment(MemoryLayout layout, SegmentAllocator allocator) { + public MemoryAddress nextVarg(ValueLayout.OfAddress layout) { throw uoe(); } @Override - public MemorySegment vargAsSegment(MemoryLayout layout, ResourceScope scope) { + public MemorySegment nextVarg(GroupLayout layout, SegmentAllocator allocator) { throw uoe(); } @@ -638,19 +720,21 @@ public class SharedUtils { static void writeOverSized(MemorySegment ptr, Class type, Object o) { // use VH_LONG for integers to zero out the whole register in the process if (type == long.class) { - MemoryAccess.setLong(ptr, (long) o); + ptr.set(JAVA_LONG, 0, (long) o); } else if (type == int.class) { - MemoryAccess.setLong(ptr, (int) o); + ptr.set(JAVA_LONG, 0, (int) o); } else if (type == short.class) { - MemoryAccess.setLong(ptr, (short) o); + ptr.set(JAVA_LONG, 0, (short) o); } else if (type == char.class) { - MemoryAccess.setLong(ptr, (char) o); + ptr.set(JAVA_LONG, 0, (char) o); } else if (type == byte.class) { - MemoryAccess.setLong(ptr, (byte) o); + ptr.set(JAVA_LONG, 0, (byte) o); } else if (type == float.class) { - MemoryAccess.setFloat(ptr, (float) o); + ptr.set(JAVA_FLOAT, 0, (float) o); } else if (type == double.class) { - MemoryAccess.setDouble(ptr, (double) o); + ptr.set(JAVA_DOUBLE, 0, (double) o); + } else if (type == boolean.class) { + ptr.set(JAVA_BOOLEAN, 0, (boolean) o); } else { throw new IllegalArgumentException("Unsupported carrier: " + type); } @@ -658,19 +742,21 @@ public class SharedUtils { static void write(MemorySegment ptr, Class type, Object o) { if (type == long.class) { - MemoryAccess.setLong(ptr, (long) o); + ptr.set(JAVA_LONG, 0, (long) o); } else if (type == int.class) { - MemoryAccess.setInt(ptr, (int) o); + ptr.set(JAVA_INT, 0, (int) o); } else if (type == short.class) { - MemoryAccess.setShort(ptr, (short) o); + ptr.set(JAVA_SHORT, 0, (short) o); } else if (type == char.class) { - MemoryAccess.setChar(ptr, (char) o); + ptr.set(JAVA_CHAR, 0, (char) o); } else if (type == byte.class) { - MemoryAccess.setByte(ptr, (byte) o); + ptr.set(JAVA_BYTE, 0, (byte) o); } else if (type == float.class) { - MemoryAccess.setFloat(ptr, (float) o); + ptr.set(JAVA_FLOAT, 0, (float) o); } else if (type == double.class) { - MemoryAccess.setDouble(ptr, (double) o); + ptr.set(JAVA_DOUBLE, 0, (double) o); + } else if (type == boolean.class) { + ptr.set(JAVA_BOOLEAN, 0, (boolean) o); } else { throw new IllegalArgumentException("Unsupported carrier: " + type); } @@ -678,21 +764,43 @@ public class SharedUtils { static Object read(MemorySegment ptr, Class type) { if (type == long.class) { - return MemoryAccess.getLong(ptr); + return ptr.get(JAVA_LONG, 0); } else if (type == int.class) { - return MemoryAccess.getInt(ptr); + return ptr.get(JAVA_INT, 0); } else if (type == short.class) { - return MemoryAccess.getShort(ptr); + return ptr.get(JAVA_SHORT, 0); } else if (type == char.class) { - return MemoryAccess.getChar(ptr); + return ptr.get(JAVA_CHAR, 0); } else if (type == byte.class) { - return MemoryAccess.getByte(ptr); + return ptr.get(JAVA_BYTE, 0); } else if (type == float.class) { - return MemoryAccess.getFloat(ptr); + return ptr.get(JAVA_FLOAT, 0); } else if (type == double.class) { - return MemoryAccess.getDouble(ptr); + return ptr.get(JAVA_DOUBLE, 0); + } else if (type == boolean.class) { + return ptr.get(JAVA_BOOLEAN, 0); } else { throw new IllegalArgumentException("Unsupported carrier: " + type); } } + + public static MethodType inferMethodType(FunctionDescriptor descriptor, boolean upcall) { + MethodType type = MethodType.methodType(descriptor.returnLayout().isPresent() ? + carrierFor(descriptor.returnLayout().get(), upcall) : void.class); + for (MemoryLayout argLayout : descriptor.argumentLayouts()) { + type = type.appendParameterTypes(carrierFor(argLayout, !upcall)); + } + return type; + } + + static Class carrierFor(MemoryLayout layout, boolean forArg) { + if (layout instanceof ValueLayout valueLayout) { + return (forArg && valueLayout.carrier().equals(MemoryAddress.class)) ? + Addressable.class : valueLayout.carrier(); + } else if (layout instanceof GroupLayout) { + return MemorySegment.class; + } else { + throw new IllegalArgumentException("Unsupported layout: " + layout); + } + } } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/UpcallStubs.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/UpcallStubs.java index d417b8ad9abee8eb69aa18dbefd4196f42e996b2..9f528dfacd0f61960ce07d5b35c5870aeae246f4 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/UpcallStubs.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/UpcallStubs.java @@ -25,18 +25,13 @@ package jdk.internal.foreign.abi; import jdk.incubator.foreign.MemoryAddress; -import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.NativeSymbol; +import jdk.incubator.foreign.ResourceScope; +import jdk.internal.foreign.NativeSymbolImpl; import jdk.internal.foreign.ResourceScopeImpl; -import jdk.internal.foreign.NativeMemorySegmentImpl; public class UpcallStubs { - public static MemoryAddress upcallAddress(UpcallHandler handler, ResourceScopeImpl scope) { - long stubAddress = handler.entryPoint(); - return NativeMemorySegmentImpl.makeNativeSegmentUnchecked(MemoryAddress.ofLong(stubAddress), 0, - () -> freeUpcallStub(stubAddress), scope).address(); - } - private static void freeUpcallStub(long stubAddress) { if (!freeUpcallStub0(stubAddress)) { throw new IllegalStateException("Not a stub address: " + stubAddress); @@ -52,4 +47,14 @@ public class UpcallStubs { static { registerNatives(); } + + static NativeSymbol makeUpcall(long entry, ResourceScope scope) { + ((ResourceScopeImpl)scope).addOrCleanupIfFail(new ResourceScopeImpl.ResourceList.ResourceCleanup() { + @Override + public void cleanup() { + freeUpcallStub(entry); + } + }); + return new NativeSymbolImpl("upcall:" + Long.toHexString(entry), MemoryAddress.ofLong(entry), scope); + } } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/aarch64/CallArranger.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/aarch64/CallArranger.java index ef12d129bcb6c4d499c59ec2e34771b3ab2f6d94..abcef36500dd62e1220977bd087ceb87545b69dd 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/aarch64/CallArranger.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/aarch64/CallArranger.java @@ -30,9 +30,10 @@ import jdk.incubator.foreign.GroupLayout; import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.NativeSymbol; +import jdk.incubator.foreign.ResourceScope; import jdk.internal.foreign.Utils; import jdk.internal.foreign.abi.CallingSequenceBuilder; -import jdk.internal.foreign.abi.UpcallHandler; import jdk.internal.foreign.abi.ABIDescriptor; import jdk.internal.foreign.abi.Binding; import jdk.internal.foreign.abi.CallingSequence; @@ -40,6 +41,8 @@ import jdk.internal.foreign.abi.ProgrammableInvoker; import jdk.internal.foreign.abi.ProgrammableUpcallHandler; import jdk.internal.foreign.abi.VMStorage; import jdk.internal.foreign.abi.SharedUtils; +import jdk.internal.foreign.abi.aarch64.linux.LinuxAArch64CallArranger; +import jdk.internal.foreign.abi.aarch64.macos.MacOsAArch64CallArranger; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; @@ -54,8 +57,12 @@ import static jdk.internal.foreign.abi.aarch64.AArch64Architecture.*; * to translate a C FunctionDescriptor into a CallingSequence2, which can then be turned into a MethodHandle. * * This includes taking care of synthetic arguments like pointers to return buffers for 'in-memory' returns. + * + * There are minor differences between the ABIs implemented on Linux, macOS, and Windows + * which are handled in sub-classes. Clients should access these through the provided + * public constants CallArranger.LINUX and CallArranger.MACOS. */ -public class CallArranger { +public abstract class CallArranger { private static final int STACK_SLOT_SIZE = 8; public static final int MAX_REGISTER_ARGUMENTS = 8; @@ -95,9 +102,20 @@ public class CallArranger { } } - public static Bindings getBindings(MethodType mt, FunctionDescriptor cDesc, boolean forUpcall) { - SharedUtils.checkFunctionTypes(mt, cDesc, AArch64.C_POINTER.bitSize()); + public static final CallArranger LINUX = new LinuxAArch64CallArranger(); + public static final CallArranger MACOS = new MacOsAArch64CallArranger(); + + /** + * Are variadic arguments assigned to registers as in the standard calling + * convention, or always passed on the stack? + * + * @returns true if variadic arguments should be spilled to the stack. + */ + protected abstract boolean varArgsOnStack(); + + protected CallArranger() {} + public Bindings getBindings(MethodType mt, FunctionDescriptor cDesc, boolean forUpcall) { CallingSequenceBuilder csb = new CallingSequenceBuilder(forUpcall); BindingCalculator argCalc = forUpcall ? new BoxBindingCalculator(true) : new UnboxBindingCalculator(true); @@ -116,6 +134,9 @@ public class CallArranger { for (int i = 0; i < mt.parameterCount(); i++) { Class carrier = mt.parameterType(i); MemoryLayout layout = cDesc.argumentLayouts().get(i); + if (varArgsOnStack() && SharedUtils.isVarargsIndex(cDesc, i)) { + argCalc.storageCalculator.adjustForVarArgs(); + } csb.addArgumentBindings(carrier, layout, argCalc.getBindings(carrier, layout)); } @@ -124,7 +145,7 @@ public class CallArranger { return new Bindings(csb.build(), returnInMemory); } - public static MethodHandle arrangeDowncall(MethodType mt, FunctionDescriptor cDesc) { + public MethodHandle arrangeDowncall(MethodType mt, FunctionDescriptor cDesc) { Bindings bindings = getBindings(mt, cDesc, false); MethodHandle handle = new ProgrammableInvoker(C, bindings.callingSequence).getBoundMethodHandle(); @@ -136,14 +157,14 @@ public class CallArranger { return handle; } - public static UpcallHandler arrangeUpcall(MethodHandle target, MethodType mt, FunctionDescriptor cDesc) { + public NativeSymbol arrangeUpcall(MethodHandle target, MethodType mt, FunctionDescriptor cDesc, ResourceScope scope) { Bindings bindings = getBindings(mt, cDesc, true); if (bindings.isInMemoryReturn) { target = SharedUtils.adaptUpcallForIMR(target, true /* drop return, since we don't have bindings for it */); } - return ProgrammableUpcallHandler.make(C, target, bindings.callingSequence); + return ProgrammableUpcallHandler.make(C, target, bindings.callingSequence,scope); } private static boolean isInMemoryReturn(Optional returnLayout) { @@ -208,18 +229,15 @@ public class CallArranger { return storage[0]; } - void adjustForVarArgs(MemoryLayout layout) { - if (layout.attribute(AArch64.STACK_VARARGS_ATTRIBUTE_NAME) - .map(Boolean.class::cast).orElse(false)) { - // This system passes all variadic parameters on the stack. Ensure - // no further arguments are allocated to registers. - nRegs[StorageClasses.INTEGER] = MAX_REGISTER_ARGUMENTS; - nRegs[StorageClasses.VECTOR] = MAX_REGISTER_ARGUMENTS; - } + void adjustForVarArgs() { + // This system passes all variadic parameters on the stack. Ensure + // no further arguments are allocated to registers. + nRegs[StorageClasses.INTEGER] = MAX_REGISTER_ARGUMENTS; + nRegs[StorageClasses.VECTOR] = MAX_REGISTER_ARGUMENTS; } } - static abstract class BindingCalculator { + abstract static class BindingCalculator { protected final StorageCalculator storageCalculator; protected BindingCalculator(boolean forArguments) { @@ -288,7 +306,6 @@ public class CallArranger { List getBindings(Class carrier, MemoryLayout layout) { TypeClass argumentClass = TypeClass.classifyLayout(layout); Binding.Builder bindings = Binding.builder(); - storageCalculator.adjustForVarArgs(layout); switch (argumentClass) { case STRUCT_REGISTER: { assert carrier == MemorySegment.class; @@ -317,8 +334,7 @@ public class CallArranger { case STRUCT_REFERENCE: { assert carrier == MemorySegment.class; bindings.copy(layout) - .baseAddress() - .unboxAddress(); + .unboxAddress(MemorySegment.class); VMStorage storage = storageCalculator.nextStorage( StorageClasses.INTEGER, AArch64.C_POINTER); bindings.vmStore(storage, long.class); @@ -349,7 +365,7 @@ public class CallArranger { break; } case POINTER: { - bindings.unboxAddress(); + bindings.unboxAddress(carrier); VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER, layout); bindings.vmStore(storage, long.class); @@ -391,7 +407,6 @@ public class CallArranger { List getBindings(Class carrier, MemoryLayout layout) { TypeClass argumentClass = TypeClass.classifyLayout(layout); Binding.Builder bindings = Binding.builder(); - assert !layout.attribute(AArch64.STACK_VARARGS_ATTRIBUTE_NAME).isPresent() : "no variadic upcalls"; switch (argumentClass) { case STRUCT_REGISTER: { assert carrier == MemorySegment.class; diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/aarch64/TypeClass.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/aarch64/TypeClass.java index 781d6851b5bcb3d721e795e3193558f0a7d18522..5514d300daafa696d7a3d7d253f383f163efbadb 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/aarch64/TypeClass.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/aarch64/TypeClass.java @@ -26,10 +26,10 @@ package jdk.internal.foreign.abi.aarch64; import jdk.incubator.foreign.GroupLayout; +import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.SequenceLayout; import jdk.incubator.foreign.ValueLayout; -import jdk.internal.foreign.PlatformLayouts; public enum TypeClass { STRUCT_REGISTER, @@ -42,11 +42,17 @@ public enum TypeClass { private static final int MAX_AGGREGATE_REGS_SIZE = 2; private static TypeClass classifyValueType(ValueLayout type) { - return switch (PlatformLayouts.getKind(type)) { - case CHAR, SHORT, INT, LONG, LONG_LONG -> INTEGER; - case POINTER -> POINTER; - case FLOAT, DOUBLE -> FLOAT; - }; + Class carrier = type.carrier(); + if (carrier == boolean.class || carrier == byte.class || carrier == char.class || + carrier == short.class || carrier == int.class || carrier == long.class) { + return INTEGER; + } else if (carrier == float.class || carrier == double.class) { + return FLOAT; + } else if (carrier == MemoryAddress.class) { + return POINTER; + } else { + throw new IllegalStateException("Cannot get here: " + carrier.getName()); + } } static boolean isRegisterAggregate(MemoryLayout type) { diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/aarch64/linux/LinuxAArch64CallArranger.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/aarch64/linux/LinuxAArch64CallArranger.java new file mode 100644 index 0000000000000000000000000000000000000000..044f4a83266d41f8f7d7e40bab157c1f3df5dafc --- /dev/null +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/aarch64/linux/LinuxAArch64CallArranger.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, Arm Limited. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.internal.foreign.abi.aarch64.linux; + +import jdk.internal.foreign.abi.aarch64.*; + +/** + * AArch64 CallArranger specialized for Linux ABI. + */ +public class LinuxAArch64CallArranger extends CallArranger { + + @Override + protected boolean varArgsOnStack() { + // Variadic arguments are passed as normal arguments + return false; + } + +} diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/aarch64/linux/LinuxAArch64Linker.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/aarch64/linux/LinuxAArch64Linker.java index d2a0db203bfc1bbdc9ee5866f989a6295adfa852..aca622ab5baed6e7bd24177b06a15de97f8f0f3c 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/aarch64/linux/LinuxAArch64Linker.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/aarch64/linux/LinuxAArch64Linker.java @@ -25,14 +25,14 @@ */ package jdk.internal.foreign.abi.aarch64.linux; +import jdk.incubator.foreign.CLinker; import jdk.incubator.foreign.FunctionDescriptor; import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.NativeSymbol; import jdk.incubator.foreign.ResourceScope; -import jdk.internal.foreign.AbstractCLinker; -import jdk.internal.foreign.ResourceScopeImpl; +import jdk.incubator.foreign.VaList; import jdk.internal.foreign.abi.SharedUtils; -import jdk.internal.foreign.abi.UpcallStubs; import jdk.internal.foreign.abi.aarch64.CallArranger; import java.lang.invoke.MethodHandle; @@ -45,26 +45,11 @@ import java.util.function.Consumer; * ABI implementation based on ARM document "Procedure Call Standard for * the ARM 64-bit Architecture". */ -public final class LinuxAArch64Linker extends AbstractCLinker { +public final class LinuxAArch64Linker implements CLinker { private static LinuxAArch64Linker instance; static final long ADDRESS_SIZE = 64; // bits - private static final MethodHandle MH_unboxVaList; - private static final MethodHandle MH_boxVaList; - - static { - try { - MethodHandles.Lookup lookup = MethodHandles.lookup(); - MH_unboxVaList = lookup.findVirtual(VaList.class, "address", - MethodType.methodType(MemoryAddress.class)); - MH_boxVaList = MethodHandles.insertArguments(lookup.findStatic(LinuxAArch64Linker.class, "newVaListOfAddress", - MethodType.methodType(VaList.class, MemoryAddress.class, ResourceScope.class)), 1, ResourceScope.globalScope()); - } catch (ReflectiveOperationException e) { - throw new ExceptionInInitializerError(e); - } - } - public static LinuxAArch64Linker getInstance() { if (instance == null) { instance = new LinuxAArch64Linker(); @@ -73,26 +58,28 @@ public final class LinuxAArch64Linker extends AbstractCLinker { } @Override - public final MethodHandle downcallHandle(MethodType type, FunctionDescriptor function) { - Objects.requireNonNull(type); + public final MethodHandle downcallHandle(FunctionDescriptor function) { Objects.requireNonNull(function); - MethodType llMt = SharedUtils.convertVaListCarriers(type, LinuxAArch64VaList.CARRIER); - MethodHandle handle = CallArranger.arrangeDowncall(llMt, function); + MethodType type = SharedUtils.inferMethodType(function, false); + MethodHandle handle = CallArranger.LINUX.arrangeDowncall(type, function); if (!type.returnType().equals(MemorySegment.class)) { // not returning segment, just insert a throwing allocator handle = MethodHandles.insertArguments(handle, 1, SharedUtils.THROWING_ALLOCATOR); } - handle = SharedUtils.unboxVaLists(type, handle, MH_unboxVaList); - return handle; + return SharedUtils.wrapDowncall(handle, function); } @Override - public final MemoryAddress upcallStub(MethodHandle target, FunctionDescriptor function, ResourceScope scope) { + public final NativeSymbol upcallStub(MethodHandle target, FunctionDescriptor function, ResourceScope scope) { Objects.requireNonNull(scope); Objects.requireNonNull(target); Objects.requireNonNull(function); - target = SharedUtils.boxVaLists(target, MH_boxVaList); - return UpcallStubs.upcallAddress(CallArranger.arrangeUpcall(target, target.type(), function), (ResourceScopeImpl) scope); + SharedUtils.checkExceptions(target); + MethodType type = SharedUtils.inferMethodType(function, true); + if (!type.equals(target.type())) { + throw new IllegalArgumentException("Wrong method handle type: " + target.type()); + } + return CallArranger.LINUX.arrangeUpcall(target, target.type(), function, scope); } public static VaList newVaList(Consumer actions, ResourceScope scope) { diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/aarch64/linux/LinuxAArch64VaList.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/aarch64/linux/LinuxAArch64VaList.java index 567ec2d4bd52add5743563712e555a0ede9449d6..457b798274ffa86fa09605ad647339ec110c5058 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/aarch64/linux/LinuxAArch64VaList.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/aarch64/linux/LinuxAArch64VaList.java @@ -26,32 +26,30 @@ package jdk.internal.foreign.abi.aarch64.linux; import jdk.incubator.foreign.*; +import jdk.internal.foreign.ResourceScopeImpl; +import jdk.internal.foreign.Scoped; import jdk.internal.foreign.Utils; import jdk.internal.foreign.abi.SharedUtils; import jdk.internal.foreign.abi.aarch64.*; import jdk.internal.misc.Unsafe; import java.lang.invoke.VarHandle; -import java.lang.ref.Cleaner; -import java.nio.ByteOrder; import java.util.ArrayList; import java.util.List; import java.util.Objects; import static jdk.internal.foreign.PlatformLayouts.AArch64; -import static jdk.incubator.foreign.CLinker.VaList; + import static jdk.incubator.foreign.MemoryLayout.PathElement.groupElement; import static jdk.internal.foreign.abi.SharedUtils.SimpleVaArg; import static jdk.internal.foreign.abi.SharedUtils.THROWING_ALLOCATOR; -import static jdk.internal.foreign.abi.SharedUtils.checkCompatibleType; -import static jdk.internal.foreign.abi.SharedUtils.vhPrimitiveOrAddress; import static jdk.internal.foreign.abi.aarch64.CallArranger.MAX_REGISTER_ARGUMENTS; /** * Standard va_list implementation as defined by AAPCS document and used on * Linux. Variadic parameters may be passed in registers or on the stack. */ -public non-sealed class LinuxAArch64VaList implements VaList { +public non-sealed class LinuxAArch64VaList implements VaList, Scoped { private static final Unsafe U = Unsafe.getUnsafe(); static final Class CARRIER = MemoryAddress.class; @@ -76,9 +74,9 @@ public non-sealed class LinuxAArch64VaList implements VaList { ).withName("__va_list"); private static final MemoryLayout GP_REG - = MemoryLayout.valueLayout(64, ByteOrder.nativeOrder()); + = MemoryLayout.paddingLayout(64).withBitAlignment(64); private static final MemoryLayout FP_REG - = MemoryLayout.valueLayout(128, ByteOrder.nativeOrder()); + = MemoryLayout.paddingLayout(128).withBitAlignment(128); private static final MemoryLayout LAYOUT_GP_REGS = MemoryLayout.sequenceLayout(MAX_REGISTER_ARGUMENTS, GP_REG); @@ -91,18 +89,14 @@ public non-sealed class LinuxAArch64VaList implements VaList { private static final int MAX_GP_OFFSET = (int) LAYOUT_GP_REGS.byteSize(); private static final int MAX_FP_OFFSET = (int) LAYOUT_FP_REGS.byteSize(); - private static final VarHandle VH_stack - = MemoryHandles.asAddressVarHandle(LAYOUT.varHandle(long.class, groupElement("__stack"))); - private static final VarHandle VH_gr_top - = MemoryHandles.asAddressVarHandle(LAYOUT.varHandle(long.class, groupElement("__gr_top"))); - private static final VarHandle VH_vr_top - = MemoryHandles.asAddressVarHandle(LAYOUT.varHandle(long.class, groupElement("__vr_top"))); + private static final VarHandle VH_stack = LAYOUT.varHandle(groupElement("__stack")); + private static final VarHandle VH_gr_top = LAYOUT.varHandle(groupElement("__gr_top")); + private static final VarHandle VH_vr_top = LAYOUT.varHandle(groupElement("__vr_top")); private static final VarHandle VH_gr_offs - = LAYOUT.varHandle(int.class, groupElement("__gr_offs")); + = LAYOUT.varHandle(groupElement("__gr_offs")); private static final VarHandle VH_vr_offs - = LAYOUT.varHandle(int.class, groupElement("__vr_offs")); + = LAYOUT.varHandle(groupElement("__vr_offs")); - private static final Cleaner cleaner = Cleaner.create(); private static final VaList EMPTY = new SharedUtils.EmptyVaList(emptyListAddress()); @@ -117,19 +111,20 @@ public non-sealed class LinuxAArch64VaList implements VaList { } private static LinuxAArch64VaList readFromSegment(MemorySegment segment) { - MemorySegment gpRegsArea = grTop(segment).addOffset(-MAX_GP_OFFSET).asSegment( + MemorySegment gpRegsArea = MemorySegment.ofAddress(grTop(segment).addOffset(-MAX_GP_OFFSET), MAX_GP_OFFSET, segment.scope()); - MemorySegment fpRegsArea = vrTop(segment).addOffset(-MAX_FP_OFFSET).asSegment( + MemorySegment fpRegsArea = MemorySegment.ofAddress(vrTop(segment).addOffset(-MAX_FP_OFFSET), MAX_FP_OFFSET, segment.scope()); return new LinuxAArch64VaList(segment, gpRegsArea, fpRegsArea); } private static MemoryAddress emptyListAddress() { long ptr = U.allocateMemory(LAYOUT.byteSize()); - MemorySegment ms = MemoryAddress.ofLong(ptr).asSegment( - LAYOUT.byteSize(), () -> U.freeMemory(ptr), ResourceScope.newSharedScope()); - cleaner.register(LinuxAArch64VaList.class, () -> ms.scope().close()); + ResourceScope scope = ResourceScope.newImplicitScope(); + scope.addCloseAction(() -> U.freeMemory(ptr)); + MemorySegment ms = MemorySegment.ofAddress(MemoryAddress.ofLong(ptr), + LAYOUT.byteSize(), scope); VH_stack.set(ms, MemoryAddress.NULL); VH_gr_top.set(ms, MemoryAddress.NULL); VH_vr_top.set(ms, MemoryAddress.NULL); @@ -215,58 +210,51 @@ public non-sealed class LinuxAArch64VaList implements VaList { } @Override - public int vargAsInt(MemoryLayout layout) { + public int nextVarg(ValueLayout.OfInt layout) { return (int) read(int.class, layout); } @Override - public long vargAsLong(MemoryLayout layout) { + public long nextVarg(ValueLayout.OfLong layout) { return (long) read(long.class, layout); } @Override - public double vargAsDouble(MemoryLayout layout) { + public double nextVarg(ValueLayout.OfDouble layout) { return (double) read(double.class, layout); } @Override - public MemoryAddress vargAsAddress(MemoryLayout layout) { + public MemoryAddress nextVarg(ValueLayout.OfAddress layout) { return (MemoryAddress) read(MemoryAddress.class, layout); } @Override - public MemorySegment vargAsSegment(MemoryLayout layout, SegmentAllocator allocator) { + public MemorySegment nextVarg(GroupLayout layout, SegmentAllocator allocator) { Objects.requireNonNull(allocator); return (MemorySegment) read(MemorySegment.class, layout, allocator); } - @Override - public MemorySegment vargAsSegment(MemoryLayout layout, ResourceScope scope) { - return vargAsSegment(layout, SegmentAllocator.ofScope(scope)); - } - private Object read(Class carrier, MemoryLayout layout) { return read(carrier, layout, THROWING_ALLOCATOR); } private Object read(Class carrier, MemoryLayout layout, SegmentAllocator allocator) { Objects.requireNonNull(layout); - checkCompatibleType(carrier, layout, LinuxAArch64Linker.ADDRESS_SIZE); - TypeClass typeClass = TypeClass.classifyLayout(layout); if (isRegOverflow(currentGPOffset(), currentFPOffset(), typeClass, layout)) { preAlignStack(layout); return switch (typeClass) { case STRUCT_REGISTER, STRUCT_HFA, STRUCT_REFERENCE -> { - MemorySegment slice = stackPtr().asSegment(layout.byteSize(), scope()); + MemorySegment slice = MemorySegment.ofAddress(stackPtr(), layout.byteSize(), scope()); MemorySegment seg = allocator.allocate(layout); seg.copyFrom(slice); postAlignStack(layout); yield seg; } case POINTER, INTEGER, FLOAT -> { - VarHandle reader = vhPrimitiveOrAddress(carrier, layout); - MemorySegment slice = stackPtr().asSegment(layout.byteSize(), scope()); + VarHandle reader = layout.varHandle(); + MemorySegment slice = MemorySegment.ofAddress(stackPtr(), layout.byteSize(), scope()); Object res = reader.get(slice); postAlignStack(layout); yield res; @@ -280,8 +268,7 @@ public non-sealed class LinuxAArch64VaList implements VaList { long offset = 0; while (offset < layout.byteSize()) { final long copy = Math.min(layout.byteSize() - offset, 8); - MemorySegment slice = value.asSlice(offset, copy); - slice.copyFrom(gpRegsArea.asSlice(currentGPOffset(), copy)); + MemorySegment.copy(gpRegsArea, currentGPOffset(), value, offset, copy); consumeGPSlots(1); offset += copy; } @@ -296,8 +283,7 @@ public non-sealed class LinuxAArch64VaList implements VaList { for (MemoryLayout elem : group.memberLayouts()) { assert elem.byteSize() <= 8; final long copy = elem.byteSize(); - MemorySegment slice = value.asSlice(offset, copy); - slice.copyFrom(fpRegsArea.asSlice(currentFPOffset(), copy)); + MemorySegment.copy(fpRegsArea, currentFPOffset(), value, offset, copy); consumeFPSlots(1); offset += copy; } @@ -305,25 +291,24 @@ public non-sealed class LinuxAArch64VaList implements VaList { } case STRUCT_REFERENCE -> { // Struct is passed indirectly via a pointer in an integer register. - VarHandle ptrReader - = SharedUtils.vhPrimitiveOrAddress(MemoryAddress.class, AArch64.C_POINTER); + VarHandle ptrReader = AArch64.C_POINTER.varHandle(); MemoryAddress ptr = (MemoryAddress) ptrReader.get( gpRegsArea.asSlice(currentGPOffset())); consumeGPSlots(1); - MemorySegment slice = ptr.asSegment(layout.byteSize(), scope()); + MemorySegment slice = MemorySegment.ofAddress(ptr, layout.byteSize(), scope()); MemorySegment seg = allocator.allocate(layout); seg.copyFrom(slice); yield seg; } case POINTER, INTEGER -> { - VarHandle reader = SharedUtils.vhPrimitiveOrAddress(carrier, layout); + VarHandle reader = layout.varHandle(); Object res = reader.get(gpRegsArea.asSlice(currentGPOffset())); consumeGPSlots(1); yield res; } case FLOAT -> { - VarHandle reader = layout.varHandle(carrier); + VarHandle reader = layout.varHandle(); Object res = reader.get(fpRegsArea.asSlice(currentFPOffset())); consumeFPSlots(1); yield res; @@ -335,6 +320,7 @@ public non-sealed class LinuxAArch64VaList implements VaList { @Override public void skip(MemoryLayout... layouts) { Objects.requireNonNull(layouts); + ((ResourceScopeImpl)segment.scope()).checkValidStateSlow(); for (MemoryLayout layout : layouts) { Objects.requireNonNull(layout); TypeClass typeClass = TypeClass.classifyLayout(layout); @@ -356,7 +342,7 @@ public non-sealed class LinuxAArch64VaList implements VaList { } public static VaList ofAddress(MemoryAddress ma, ResourceScope scope) { - return readFromSegment(ma.asSegment(LAYOUT.byteSize(), scope)); + return readFromSegment(MemorySegment.ofAddress(ma, LAYOUT.byteSize(), scope)); } @Override @@ -418,35 +404,33 @@ public non-sealed class LinuxAArch64VaList implements VaList { } @Override - public Builder vargFromInt(ValueLayout layout, int value) { + public Builder addVarg(ValueLayout.OfInt layout, int value) { return arg(int.class, layout, value); } @Override - public Builder vargFromLong(ValueLayout layout, long value) { + public Builder addVarg(ValueLayout.OfLong layout, long value) { return arg(long.class, layout, value); } @Override - public Builder vargFromDouble(ValueLayout layout, double value) { + public Builder addVarg(ValueLayout.OfDouble layout, double value) { return arg(double.class, layout, value); } @Override - public Builder vargFromAddress(ValueLayout layout, Addressable value) { + public Builder addVarg(ValueLayout.OfAddress layout, Addressable value) { return arg(MemoryAddress.class, layout, value.address()); } @Override - public Builder vargFromSegment(GroupLayout layout, MemorySegment value) { + public Builder addVarg(GroupLayout layout, MemorySegment value) { return arg(MemorySegment.class, layout, value); } private Builder arg(Class carrier, MemoryLayout layout, Object value) { Objects.requireNonNull(layout); Objects.requireNonNull(value); - checkCompatibleType(carrier, layout, LinuxAArch64Linker.ADDRESS_SIZE); - TypeClass typeClass = TypeClass.classifyLayout(layout); if (isRegOverflow(currentGPOffset, currentFPOffset, typeClass, layout)) { stackArgs.add(new SimpleVaArg(carrier, layout, value)); @@ -458,8 +442,7 @@ public non-sealed class LinuxAArch64VaList implements VaList { long offset = 0; while (offset < layout.byteSize()) { final long copy = Math.min(layout.byteSize() - offset, 8); - MemorySegment slice = valueSegment.asSlice(offset, copy); - gpRegs.asSlice(currentGPOffset, copy).copyFrom(slice); + MemorySegment.copy(valueSegment, offset, gpRegs, currentGPOffset, copy); currentGPOffset += GP_SLOT_SIZE; offset += copy; } @@ -473,8 +456,7 @@ public non-sealed class LinuxAArch64VaList implements VaList { for (MemoryLayout elem : group.memberLayouts()) { assert elem.byteSize() <= 8; final long copy = elem.byteSize(); - MemorySegment slice = valueSegment.asSlice(offset, copy); - fpRegs.asSlice(currentFPOffset, copy).copyFrom(slice); + MemorySegment.copy(valueSegment, offset, fpRegs, currentFPOffset, copy); currentFPOffset += FP_SLOT_SIZE; offset += copy; } @@ -482,20 +464,18 @@ public non-sealed class LinuxAArch64VaList implements VaList { case STRUCT_REFERENCE -> { // Struct is passed indirectly via a pointer in an integer register. MemorySegment valueSegment = (MemorySegment) value; - VarHandle writer - = SharedUtils.vhPrimitiveOrAddress(MemoryAddress.class, - AArch64.C_POINTER); + VarHandle writer = AArch64.C_POINTER.varHandle(); writer.set(gpRegs.asSlice(currentGPOffset), valueSegment.address()); currentGPOffset += GP_SLOT_SIZE; } case POINTER, INTEGER -> { - VarHandle writer = SharedUtils.vhPrimitiveOrAddress(carrier, layout); + VarHandle writer = layout.varHandle(); writer.set(gpRegs.asSlice(currentGPOffset), value); currentGPOffset += GP_SLOT_SIZE; } case FLOAT -> { - VarHandle writer = layout.varHandle(carrier); + VarHandle writer = layout.varHandle(); writer.set(fpRegs.asSlice(currentFPOffset), value); currentFPOffset += FP_SLOT_SIZE; } @@ -513,7 +493,7 @@ public non-sealed class LinuxAArch64VaList implements VaList { return EMPTY; } - SegmentAllocator allocator = SegmentAllocator.arenaAllocator(scope); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(scope); MemorySegment vaListSegment = allocator.allocate(LAYOUT); MemoryAddress stackArgsPtr = MemoryAddress.NULL; if (!stackArgs.isEmpty()) { diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/aarch64/macos/MacOsAArch64CallArranger.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/aarch64/macos/MacOsAArch64CallArranger.java new file mode 100644 index 0000000000000000000000000000000000000000..8b35583e5c3c487a0353b56162e54a70c5115684 --- /dev/null +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/aarch64/macos/MacOsAArch64CallArranger.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, Arm Limited. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.internal.foreign.abi.aarch64.macos; + +import jdk.internal.foreign.abi.aarch64.*; + +/** + * AArch64 CallArranger specialized for macOS ABI. + */ +public class MacOsAArch64CallArranger extends CallArranger { + + @Override + protected boolean varArgsOnStack() { + // Variadic arguments are always passed on the stack + return true; + } + +} diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/aarch64/macos/MacOsAArch64Linker.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/aarch64/macos/MacOsAArch64Linker.java index 1e644bf8760273877593481b55c64a26948b12e2..13b30a0f68fdfa47875b668d8c58ab410078f70f 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/aarch64/macos/MacOsAArch64Linker.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/aarch64/macos/MacOsAArch64Linker.java @@ -25,16 +25,14 @@ */ package jdk.internal.foreign.abi.aarch64.macos; -import jdk.incubator.foreign.Addressable; +import jdk.incubator.foreign.CLinker; import jdk.incubator.foreign.FunctionDescriptor; import jdk.incubator.foreign.MemoryAddress; -import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.NativeSymbol; import jdk.incubator.foreign.ResourceScope; -import jdk.internal.foreign.AbstractCLinker; -import jdk.internal.foreign.ResourceScopeImpl; +import jdk.incubator.foreign.VaList; import jdk.internal.foreign.abi.SharedUtils; -import jdk.internal.foreign.abi.UpcallStubs; import jdk.internal.foreign.abi.aarch64.CallArranger; import java.lang.invoke.MethodHandle; @@ -43,32 +41,15 @@ import java.lang.invoke.MethodType; import java.util.Objects; import java.util.function.Consumer; -import static jdk.internal.foreign.PlatformLayouts.*; - /** * ABI implementation for macOS on Apple silicon. Based on AAPCS with * changes to va_list and passing arguments on the stack. */ -public final class MacOsAArch64Linker extends AbstractCLinker { +public final class MacOsAArch64Linker implements CLinker { private static MacOsAArch64Linker instance; static final long ADDRESS_SIZE = 64; // bits - private static final MethodHandle MH_unboxVaList; - private static final MethodHandle MH_boxVaList; - - static { - try { - MethodHandles.Lookup lookup = MethodHandles.lookup(); - MH_unboxVaList = lookup.findVirtual(VaList.class, "address", - MethodType.methodType(MemoryAddress.class)); - MH_boxVaList = MethodHandles.insertArguments(lookup.findStatic(MacOsAArch64Linker.class, "newVaListOfAddress", - MethodType.methodType(VaList.class, MemoryAddress.class, ResourceScope.class)), 1, ResourceScope.globalScope()); - } catch (ReflectiveOperationException e) { - throw new ExceptionInInitializerError(e); - } - } - public static MacOsAArch64Linker getInstance() { if (instance == null) { instance = new MacOsAArch64Linker(); @@ -77,26 +58,27 @@ public final class MacOsAArch64Linker extends AbstractCLinker { } @Override - public final MethodHandle downcallHandle(MethodType type, FunctionDescriptor function) { - Objects.requireNonNull(type); + public final MethodHandle downcallHandle(FunctionDescriptor function) { Objects.requireNonNull(function); - MethodType llMt = SharedUtils.convertVaListCarriers(type, MacOsAArch64VaList.CARRIER); - MethodHandle handle = CallArranger.arrangeDowncall(llMt, function); + MethodType type = SharedUtils.inferMethodType(function, false); + MethodHandle handle = CallArranger.MACOS.arrangeDowncall(type, function); if (!type.returnType().equals(MemorySegment.class)) { // not returning segment, just insert a throwing allocator handle = MethodHandles.insertArguments(handle, 1, SharedUtils.THROWING_ALLOCATOR); } - handle = SharedUtils.unboxVaLists(type, handle, MH_unboxVaList); - return handle; + return SharedUtils.wrapDowncall(handle, function); } @Override - public final MemoryAddress upcallStub(MethodHandle target, FunctionDescriptor function, ResourceScope scope) { + public final NativeSymbol upcallStub(MethodHandle target, FunctionDescriptor function, ResourceScope scope) { Objects.requireNonNull(scope); Objects.requireNonNull(target); Objects.requireNonNull(function); - target = SharedUtils.boxVaLists(target, MH_boxVaList); - return UpcallStubs.upcallAddress(CallArranger.arrangeUpcall(target, target.type(), function), (ResourceScopeImpl) scope); + MethodType type = SharedUtils.inferMethodType(function, true); + if (!type.equals(target.type())) { + throw new IllegalArgumentException("Wrong method handle type: " + target.type()); + } + return CallArranger.MACOS.arrangeUpcall(target, target.type(), function, scope); } public static VaList newVaList(Consumer actions, ResourceScope scope) { diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/aarch64/macos/MacOsAArch64VaList.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/aarch64/macos/MacOsAArch64VaList.java index e456983bb16c7a2cc8cb4eb433e45d42b384645f..022235eb776ecaabb98ca13e9a1b9bcccc337f88 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/aarch64/macos/MacOsAArch64VaList.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/aarch64/macos/MacOsAArch64VaList.java @@ -26,7 +26,7 @@ package jdk.internal.foreign.abi.aarch64.macos; import jdk.incubator.foreign.*; -import jdk.incubator.foreign.CLinker.VaList; +import jdk.internal.foreign.Scoped; import jdk.internal.foreign.ResourceScopeImpl; import jdk.internal.foreign.abi.SharedUtils; import jdk.internal.foreign.abi.SharedUtils.SimpleVaArg; @@ -45,10 +45,10 @@ import static jdk.internal.foreign.abi.SharedUtils.alignUp; * parameters are passed on the stack and the type of va_list decays to * char* instead of the structure defined in the AAPCS. */ -public non-sealed class MacOsAArch64VaList implements VaList { +public non-sealed class MacOsAArch64VaList implements VaList, Scoped { public static final Class CARRIER = MemoryAddress.class; private static final long VA_SLOT_SIZE_BYTES = 8; - private static final VarHandle VH_address = MemoryHandles.asAddressVarHandle(C_POINTER.varHandle(long.class)); + private static final VarHandle VH_address = C_POINTER.varHandle(); private static final VaList EMPTY = new SharedUtils.EmptyVaList(MemoryAddress.NULL); @@ -65,65 +65,59 @@ public non-sealed class MacOsAArch64VaList implements VaList { } @Override - public int vargAsInt(MemoryLayout layout) { + public int nextVarg(ValueLayout.OfInt layout) { return (int) read(int.class, layout); } @Override - public long vargAsLong(MemoryLayout layout) { + public long nextVarg(ValueLayout.OfLong layout) { return (long) read(long.class, layout); } @Override - public double vargAsDouble(MemoryLayout layout) { + public double nextVarg(ValueLayout.OfDouble layout) { return (double) read(double.class, layout); } @Override - public MemoryAddress vargAsAddress(MemoryLayout layout) { + public MemoryAddress nextVarg(ValueLayout.OfAddress layout) { return (MemoryAddress) read(MemoryAddress.class, layout); } @Override - public MemorySegment vargAsSegment(MemoryLayout layout, SegmentAllocator allocator) { + public MemorySegment nextVarg(GroupLayout layout, SegmentAllocator allocator) { Objects.requireNonNull(allocator); return (MemorySegment) read(MemorySegment.class, layout, allocator); } - @Override - public MemorySegment vargAsSegment(MemoryLayout layout, ResourceScope scope) { - return vargAsSegment(layout, SegmentAllocator.ofScope(scope)); - } - private Object read(Class carrier, MemoryLayout layout) { return read(carrier, layout, SharedUtils.THROWING_ALLOCATOR); } private Object read(Class carrier, MemoryLayout layout, SegmentAllocator allocator) { Objects.requireNonNull(layout); - SharedUtils.checkCompatibleType(carrier, layout, MacOsAArch64Linker.ADDRESS_SIZE); Object res; if (carrier == MemorySegment.class) { TypeClass typeClass = TypeClass.classifyLayout(layout); res = switch (typeClass) { case STRUCT_REFERENCE -> { MemoryAddress structAddr = (MemoryAddress) VH_address.get(segment); - MemorySegment struct = structAddr.asSegment(layout.byteSize(), scope()); + MemorySegment struct = MemorySegment.ofAddress(structAddr, layout.byteSize(), scope()); MemorySegment seg = allocator.allocate(layout); seg.copyFrom(struct); segment = segment.asSlice(VA_SLOT_SIZE_BYTES); yield seg; } case STRUCT_REGISTER, STRUCT_HFA -> { - MemorySegment struct = allocator.allocate(layout); - struct.copyFrom(segment.asSlice(0L, layout.byteSize())); + MemorySegment struct = allocator.allocate(layout) + .copyFrom(segment.asSlice(0, layout.byteSize())); segment = segment.asSlice(alignUp(layout.byteSize(), VA_SLOT_SIZE_BYTES)); yield struct; } default -> throw new IllegalStateException("Unexpected TypeClass: " + typeClass); }; } else { - VarHandle reader = SharedUtils.vhPrimitiveOrAddress(carrier, layout); + VarHandle reader = layout.varHandle(); res = reader.get(segment); segment = segment.asSlice(VA_SLOT_SIZE_BYTES); } @@ -133,6 +127,7 @@ public non-sealed class MacOsAArch64VaList implements VaList { @Override public void skip(MemoryLayout... layouts) { Objects.requireNonNull(layouts); + ((ResourceScopeImpl)scope).checkValidStateSlow(); for (MemoryLayout layout : layouts) { Objects.requireNonNull(layout); @@ -144,7 +139,7 @@ public non-sealed class MacOsAArch64VaList implements VaList { } static MacOsAArch64VaList ofAddress(MemoryAddress addr, ResourceScope scope) { - MemorySegment segment = addr.asSegment(Long.MAX_VALUE, scope); + MemorySegment segment = MemorySegment.ofAddress(addr, Long.MAX_VALUE, scope); return new MacOsAArch64VaList(segment, scope); } @@ -181,33 +176,32 @@ public non-sealed class MacOsAArch64VaList implements VaList { private Builder arg(Class carrier, MemoryLayout layout, Object value) { Objects.requireNonNull(layout); Objects.requireNonNull(value); - SharedUtils.checkCompatibleType(carrier, layout, MacOsAArch64Linker.ADDRESS_SIZE); args.add(new SimpleVaArg(carrier, layout, value)); return this; } @Override - public Builder vargFromInt(ValueLayout layout, int value) { + public Builder addVarg(ValueLayout.OfInt layout, int value) { return arg(int.class, layout, value); } @Override - public Builder vargFromLong(ValueLayout layout, long value) { + public Builder addVarg(ValueLayout.OfLong layout, long value) { return arg(long.class, layout, value); } @Override - public Builder vargFromDouble(ValueLayout layout, double value) { + public Builder addVarg(ValueLayout.OfDouble layout, double value) { return arg(double.class, layout, value); } @Override - public Builder vargFromAddress(ValueLayout layout, Addressable value) { + public Builder addVarg(ValueLayout.OfAddress layout, Addressable value) { return arg(MemoryAddress.class, layout, value.address()); } @Override - public Builder vargFromSegment(GroupLayout layout, MemorySegment value) { + public Builder addVarg(GroupLayout layout, MemorySegment value) { return arg(MemorySegment.class, layout, value); } @@ -216,7 +210,7 @@ public non-sealed class MacOsAArch64VaList implements VaList { return EMPTY; } - SegmentAllocator allocator = SegmentAllocator.arenaAllocator(scope); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(scope); // Each argument may occupy up to four slots MemorySegment segment = allocator.allocate(VA_SLOT_SIZE_BYTES * args.size() * 4); @@ -237,10 +231,9 @@ public non-sealed class MacOsAArch64VaList implements VaList { VH_address.set(cursor, copy.address()); cursor = cursor.asSlice(VA_SLOT_SIZE_BYTES); } - case STRUCT_REGISTER, STRUCT_HFA -> { - cursor.copyFrom(msArg.asSlice(0, arg.layout.byteSize())); - cursor = cursor.asSlice(alignUp(arg.layout.byteSize(), VA_SLOT_SIZE_BYTES)); - } + case STRUCT_REGISTER, STRUCT_HFA -> + cursor.copyFrom(msArg.asSlice(0, arg.layout.byteSize())) + .asSlice(alignUp(arg.layout.byteSize(), VA_SLOT_SIZE_BYTES)); default -> throw new IllegalStateException("Unexpected TypeClass: " + typeClass); } } else { diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/sysv/CallArranger.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/sysv/CallArranger.java index f7f2ddd813929a7e74318850449aecfdeac7667a..188106c2e6fbf8e31ca9064c4a78ccbbd3d9bd6c 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/sysv/CallArranger.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/sysv/CallArranger.java @@ -30,8 +30,9 @@ import jdk.incubator.foreign.GroupLayout; import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.NativeSymbol; +import jdk.incubator.foreign.ResourceScope; import jdk.internal.foreign.abi.CallingSequenceBuilder; -import jdk.internal.foreign.abi.UpcallHandler; import jdk.internal.foreign.abi.ABIDescriptor; import jdk.internal.foreign.abi.Binding; import jdk.internal.foreign.abi.CallingSequence; @@ -86,8 +87,6 @@ public class CallArranger { } public static Bindings getBindings(MethodType mt, FunctionDescriptor cDesc, boolean forUpcall) { - SharedUtils.checkFunctionTypes(mt, cDesc, SysVx64Linker.ADDRESS_SIZE); - CallingSequenceBuilder csb = new CallingSequenceBuilder(forUpcall); BindingCalculator argCalc = forUpcall ? new BoxBindingCalculator(true) : new UnboxBindingCalculator(true); @@ -134,14 +133,14 @@ public class CallArranger { return handle; } - public static UpcallHandler arrangeUpcall(MethodHandle target, MethodType mt, FunctionDescriptor cDesc) { + public static NativeSymbol arrangeUpcall(MethodHandle target, MethodType mt, FunctionDescriptor cDesc, ResourceScope scope) { Bindings bindings = getBindings(mt, cDesc, true); if (bindings.isInMemoryReturn) { target = SharedUtils.adaptUpcallForIMR(target, true /* drop return, since we don't have bindings for it */); } - return ProgrammableUpcallHandler.make(CSysV, target, bindings.callingSequence); + return ProgrammableUpcallHandler.make(CSysV, target, bindings.callingSequence, scope); } private static boolean isInMemoryReturn(Optional returnLayout) { @@ -239,7 +238,7 @@ public class CallArranger { } } - static abstract class BindingCalculator { + abstract static class BindingCalculator { protected final StorageCalculator storageCalculator; protected BindingCalculator(boolean forArguments) { @@ -280,7 +279,7 @@ public class CallArranger { break; } case POINTER: { - bindings.unboxAddress(); + bindings.unboxAddress(carrier); VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER); bindings.vmStore(storage, long.class); break; diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/sysv/SysVVaList.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/sysv/SysVVaList.java index 4a74ebfa0d5cb5be9e7e3f22fdae3b0e173ae234..66fe2b97c4d51cca790560165e4208db0c8a4b2c 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/sysv/SysVVaList.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/sysv/SysVVaList.java @@ -26,27 +26,25 @@ package jdk.internal.foreign.abi.x64.sysv; import jdk.incubator.foreign.*; +import jdk.internal.foreign.ResourceScopeImpl; +import jdk.internal.foreign.Scoped; import jdk.internal.foreign.Utils; import jdk.internal.foreign.abi.SharedUtils; import jdk.internal.misc.Unsafe; import java.lang.invoke.VarHandle; -import java.lang.ref.Cleaner; -import java.nio.ByteOrder; import java.util.ArrayList; import java.util.List; import java.util.Objects; import static jdk.internal.foreign.PlatformLayouts.SysV; -import static jdk.incubator.foreign.CLinker.VaList; + import static jdk.incubator.foreign.MemoryLayout.PathElement.groupElement; import static jdk.internal.foreign.abi.SharedUtils.SimpleVaArg; import static jdk.internal.foreign.abi.SharedUtils.THROWING_ALLOCATOR; -import static jdk.internal.foreign.abi.SharedUtils.checkCompatibleType; -import static jdk.internal.foreign.abi.SharedUtils.vhPrimitiveOrAddress; // See https://software.intel.com/sites/default/files/article/402129/mpx-linux64-abi.pdf "3.5.7 Variable Argument Lists" -public non-sealed class SysVVaList implements VaList { +public non-sealed class SysVVaList implements VaList, Scoped { private static final Unsafe U = Unsafe.getUnsafe(); static final Class CARRIER = MemoryAddress.class; @@ -67,8 +65,8 @@ public non-sealed class SysVVaList implements VaList { SysV.C_POINTER.withName("reg_save_area") ).withName("__va_list_tag"); - private static final MemoryLayout GP_REG = MemoryLayout.valueLayout(64, ByteOrder.nativeOrder()); - private static final MemoryLayout FP_REG = MemoryLayout.valueLayout(128, ByteOrder.nativeOrder()); + private static final MemoryLayout GP_REG = MemoryLayout.paddingLayout(64).withBitAlignment(64); + private static final MemoryLayout FP_REG = MemoryLayout.paddingLayout(128).withBitAlignment(128); private static final GroupLayout LAYOUT_REG_SAVE_AREA = MemoryLayout.structLayout( GP_REG.withName("%rdi"), @@ -105,14 +103,11 @@ public non-sealed class SysVVaList implements VaList { private static final int MAX_GP_OFFSET = (int) FP_OFFSET; // 6 regs used private static final int MAX_FP_OFFSET = (int) LAYOUT_REG_SAVE_AREA.byteSize(); // 8 16 byte regs - private static final VarHandle VH_fp_offset = LAYOUT.varHandle(int.class, groupElement("fp_offset")); - private static final VarHandle VH_gp_offset = LAYOUT.varHandle(int.class, groupElement("gp_offset")); - private static final VarHandle VH_overflow_arg_area - = MemoryHandles.asAddressVarHandle(LAYOUT.varHandle(long.class, groupElement("overflow_arg_area"))); - private static final VarHandle VH_reg_save_area - = MemoryHandles.asAddressVarHandle(LAYOUT.varHandle(long.class, groupElement("reg_save_area"))); + private static final VarHandle VH_fp_offset = LAYOUT.varHandle(groupElement("fp_offset")); + private static final VarHandle VH_gp_offset = LAYOUT.varHandle(groupElement("gp_offset")); + private static final VarHandle VH_overflow_arg_area = LAYOUT.varHandle(groupElement("overflow_arg_area")); + private static final VarHandle VH_reg_save_area = LAYOUT.varHandle(groupElement("reg_save_area")); - private static final Cleaner cleaner = Cleaner.create(); private static final VaList EMPTY = new SharedUtils.EmptyVaList(emptyListAddress()); private final MemorySegment segment; @@ -130,9 +125,10 @@ public non-sealed class SysVVaList implements VaList { private static MemoryAddress emptyListAddress() { long ptr = U.allocateMemory(LAYOUT.byteSize()); - MemorySegment base = MemoryAddress.ofLong(ptr).asSegment( - LAYOUT.byteSize(), () -> U.freeMemory(ptr), ResourceScope.newSharedScope()); - cleaner.register(SysVVaList.class, () -> base.scope().close()); + ResourceScope scope = ResourceScope.newImplicitScope(); + scope.addCloseAction(() -> U.freeMemory(ptr)); + MemorySegment base = MemorySegment.ofAddress(MemoryAddress.ofLong(ptr), + LAYOUT.byteSize(), scope); VH_gp_offset.set(base, MAX_GP_OFFSET); VH_fp_offset.set(base, MAX_FP_OFFSET); VH_overflow_arg_area.set(base, MemoryAddress.NULL); @@ -173,7 +169,7 @@ public non-sealed class SysVVaList implements VaList { } private static MemorySegment getRegSaveArea(MemorySegment segment) { - return ((MemoryAddress)VH_reg_save_area.get(segment)).asSegment( + return MemorySegment.ofAddress(((MemoryAddress)VH_reg_save_area.get(segment)), LAYOUT_REG_SAVE_AREA.byteSize(), segment.scope()); } @@ -188,59 +184,53 @@ public non-sealed class SysVVaList implements VaList { } @Override - public int vargAsInt(MemoryLayout layout) { + public int nextVarg(ValueLayout.OfInt layout) { return (int) read(int.class, layout); } @Override - public long vargAsLong(MemoryLayout layout) { + public long nextVarg(ValueLayout.OfLong layout) { return (long) read(long.class, layout); } @Override - public double vargAsDouble(MemoryLayout layout) { + public double nextVarg(ValueLayout.OfDouble layout) { return (double) read(double.class, layout); } @Override - public MemoryAddress vargAsAddress(MemoryLayout layout) { + public MemoryAddress nextVarg(ValueLayout.OfAddress layout) { return (MemoryAddress) read(MemoryAddress.class, layout); } @Override - public MemorySegment vargAsSegment(MemoryLayout layout, SegmentAllocator allocator) { + public MemorySegment nextVarg(GroupLayout layout, SegmentAllocator allocator) { Objects.requireNonNull(allocator); return (MemorySegment) read(MemorySegment.class, layout, allocator); } - @Override - public MemorySegment vargAsSegment(MemoryLayout layout, ResourceScope scope) { - return vargAsSegment(layout, SegmentAllocator.ofScope(scope)); - } - private Object read(Class carrier, MemoryLayout layout) { return read(carrier, layout, THROWING_ALLOCATOR); } private Object read(Class carrier, MemoryLayout layout, SegmentAllocator allocator) { Objects.requireNonNull(layout); - checkCompatibleType(carrier, layout, SysVx64Linker.ADDRESS_SIZE); TypeClass typeClass = TypeClass.classifyLayout(layout); if (isRegOverflow(currentGPOffset(), currentFPOffset(), typeClass) || typeClass.inMemory()) { preAlignStack(layout); return switch (typeClass.kind()) { case STRUCT -> { - MemorySegment slice = stackPtr().asSegment(layout.byteSize(), scope()); + MemorySegment slice = MemorySegment.ofAddress(stackPtr(), layout.byteSize(), scope()); MemorySegment seg = allocator.allocate(layout); seg.copyFrom(slice); postAlignStack(layout); yield seg; } case POINTER, INTEGER, FLOAT -> { - VarHandle reader = vhPrimitiveOrAddress(carrier, layout); + VarHandle reader = layout.varHandle(); try (ResourceScope localScope = ResourceScope.newConfinedScope()) { - MemorySegment slice = stackPtr().asSegment(layout.byteSize(), localScope); + MemorySegment slice = MemorySegment.ofAddress(stackPtr(), layout.byteSize(), localScope); Object res = reader.get(slice); postAlignStack(layout); yield res; @@ -256,12 +246,11 @@ public non-sealed class SysVVaList implements VaList { while (offset < layout.byteSize()) { final long copy = Math.min(layout.byteSize() - offset, 8); boolean isSSE = typeClass.classes.get(classIdx++) == ArgumentClassImpl.SSE; - MemorySegment slice = value.asSlice(offset, copy); if (isSSE) { - slice.copyFrom(regSaveArea.asSlice(currentFPOffset(), copy)); + MemorySegment.copy(regSaveArea, currentFPOffset(), value, offset, copy); currentFPOffset(currentFPOffset() + FP_SLOT_SIZE); } else { - slice.copyFrom(regSaveArea.asSlice(currentGPOffset(), copy)); + MemorySegment.copy(regSaveArea, currentGPOffset(), value, offset, copy); currentGPOffset(currentGPOffset() + GP_SLOT_SIZE); } offset += copy; @@ -269,13 +258,13 @@ public non-sealed class SysVVaList implements VaList { yield value; } case POINTER, INTEGER -> { - VarHandle reader = SharedUtils.vhPrimitiveOrAddress(carrier, layout); + VarHandle reader = layout.varHandle(); Object res = reader.get(regSaveArea.asSlice(currentGPOffset())); currentGPOffset(currentGPOffset() + GP_SLOT_SIZE); yield res; } case FLOAT -> { - VarHandle reader = layout.varHandle(carrier); + VarHandle reader = layout.varHandle(); Object res = reader.get(regSaveArea.asSlice(currentFPOffset())); currentFPOffset(currentFPOffset() + FP_SLOT_SIZE); yield res; @@ -287,6 +276,7 @@ public non-sealed class SysVVaList implements VaList { @Override public void skip(MemoryLayout... layouts) { Objects.requireNonNull(layouts); + ((ResourceScopeImpl)segment.scope()).checkValidStateSlow(); for (MemoryLayout layout : layouts) { Objects.requireNonNull(layout); TypeClass typeClass = TypeClass.classifyLayout(layout); @@ -305,7 +295,7 @@ public non-sealed class SysVVaList implements VaList { } public static VaList ofAddress(MemoryAddress ma, ResourceScope scope) { - return readFromSegment(ma.asSegment(LAYOUT.byteSize(), scope)); + return readFromSegment(MemorySegment.ofAddress(ma, LAYOUT.byteSize(), scope)); } @Override @@ -353,34 +343,33 @@ public non-sealed class SysVVaList implements VaList { } @Override - public Builder vargFromInt(ValueLayout layout, int value) { + public Builder addVarg(ValueLayout.OfInt layout, int value) { return arg(int.class, layout, value); } @Override - public Builder vargFromLong(ValueLayout layout, long value) { + public Builder addVarg(ValueLayout.OfLong layout, long value) { return arg(long.class, layout, value); } @Override - public Builder vargFromDouble(ValueLayout layout, double value) { + public Builder addVarg(ValueLayout.OfDouble layout, double value) { return arg(double.class, layout, value); } @Override - public Builder vargFromAddress(ValueLayout layout, Addressable value) { + public Builder addVarg(ValueLayout.OfAddress layout, Addressable value) { return arg(MemoryAddress.class, layout, value.address()); } @Override - public Builder vargFromSegment(GroupLayout layout, MemorySegment value) { + public Builder addVarg(GroupLayout layout, MemorySegment value) { return arg(MemorySegment.class, layout, value); } private Builder arg(Class carrier, MemoryLayout layout, Object value) { Objects.requireNonNull(layout); Objects.requireNonNull(value); - checkCompatibleType(carrier, layout, SysVx64Linker.ADDRESS_SIZE); TypeClass typeClass = TypeClass.classifyLayout(layout); if (isRegOverflow(currentGPOffset, currentFPOffset, typeClass) || typeClass.inMemory()) { @@ -395,24 +384,23 @@ public non-sealed class SysVVaList implements VaList { while (offset < layout.byteSize()) { final long copy = Math.min(layout.byteSize() - offset, 8); boolean isSSE = typeClass.classes.get(classIdx++) == ArgumentClassImpl.SSE; - MemorySegment slice = valueSegment.asSlice(offset, copy); if (isSSE) { - reg_save_area.asSlice(currentFPOffset, copy).copyFrom(slice); + MemorySegment.copy(valueSegment, offset, reg_save_area, currentFPOffset, copy); currentFPOffset += FP_SLOT_SIZE; } else { - reg_save_area.asSlice(currentGPOffset, copy).copyFrom(slice); + MemorySegment.copy(valueSegment, offset, reg_save_area, currentGPOffset, copy); currentGPOffset += GP_SLOT_SIZE; } offset += copy; } } case POINTER, INTEGER -> { - VarHandle writer = SharedUtils.vhPrimitiveOrAddress(carrier, layout); + VarHandle writer = layout.varHandle(); writer.set(reg_save_area.asSlice(currentGPOffset), value); currentGPOffset += GP_SLOT_SIZE; } case FLOAT -> { - VarHandle writer = layout.varHandle(carrier); + VarHandle writer = layout.varHandle(); writer.set(reg_save_area.asSlice(currentFPOffset), value); currentFPOffset += FP_SLOT_SIZE; } @@ -430,7 +418,7 @@ public non-sealed class SysVVaList implements VaList { return EMPTY; } - SegmentAllocator allocator = SegmentAllocator.arenaAllocator(scope); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(scope); MemorySegment vaListSegment = allocator.allocate(LAYOUT); MemoryAddress stackArgsPtr = MemoryAddress.NULL; if (!stackArgs.isEmpty()) { diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/sysv/SysVx64Linker.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/sysv/SysVx64Linker.java index 10d4a61c11ec96393a1bfa5e9132d93b1ff387ea..0192168378c20225160dec1c1eab783addb07334 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/sysv/SysVx64Linker.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/sysv/SysVx64Linker.java @@ -25,14 +25,14 @@ package jdk.internal.foreign.abi.x64.sysv; +import jdk.incubator.foreign.CLinker; import jdk.incubator.foreign.FunctionDescriptor; import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.NativeSymbol; import jdk.incubator.foreign.ResourceScope; -import jdk.internal.foreign.AbstractCLinker; -import jdk.internal.foreign.ResourceScopeImpl; +import jdk.incubator.foreign.VaList; import jdk.internal.foreign.abi.SharedUtils; -import jdk.internal.foreign.abi.UpcallStubs; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; @@ -43,7 +43,7 @@ import java.util.function.Consumer; /** * ABI implementation based on System V ABI AMD64 supplement v.0.99.6 */ -public final class SysVx64Linker extends AbstractCLinker { +public final class SysVx64Linker implements CLinker { public static final int MAX_INTEGER_ARGUMENT_REGISTERS = 6; public static final int MAX_INTEGER_RETURN_REGISTERS = 2; public static final int MAX_VECTOR_ARGUMENT_REGISTERS = 8; @@ -54,21 +54,6 @@ public final class SysVx64Linker extends AbstractCLinker { static final long ADDRESS_SIZE = 64; // bits - private static final MethodHandle MH_unboxVaList; - private static final MethodHandle MH_boxVaList; - - static { - try { - MethodHandles.Lookup lookup = MethodHandles.lookup(); - MH_unboxVaList = lookup.findVirtual(VaList.class, "address", - MethodType.methodType(MemoryAddress.class)); - MH_boxVaList = MethodHandles.insertArguments(lookup.findStatic(SysVx64Linker.class, "newVaListOfAddress", - MethodType.methodType(VaList.class, MemoryAddress.class, ResourceScope.class)), 1, ResourceScope.globalScope()); - } catch (ReflectiveOperationException e) { - throw new ExceptionInInitializerError(e); - } - } - public static SysVx64Linker getInstance() { if (instance == null) { instance = new SysVx64Linker(); @@ -83,26 +68,28 @@ public final class SysVx64Linker extends AbstractCLinker { } @Override - public final MethodHandle downcallHandle(MethodType type, FunctionDescriptor function) { - Objects.requireNonNull(type); + public final MethodHandle downcallHandle(FunctionDescriptor function) { Objects.requireNonNull(function); - MethodType llMt = SharedUtils.convertVaListCarriers(type, SysVVaList.CARRIER); - MethodHandle handle = CallArranger.arrangeDowncall(llMt, function); + MethodType type = SharedUtils.inferMethodType(function, false); + MethodHandle handle = CallArranger.arrangeDowncall(type, function); if (!type.returnType().equals(MemorySegment.class)) { // not returning segment, just insert a throwing allocator handle = MethodHandles.insertArguments(handle, 1, SharedUtils.THROWING_ALLOCATOR); } - handle = SharedUtils.unboxVaLists(type, handle, MH_unboxVaList); - return handle; + return SharedUtils.wrapDowncall(handle, function); } @Override - public final MemoryAddress upcallStub(MethodHandle target, FunctionDescriptor function, ResourceScope scope) { + public final NativeSymbol upcallStub(MethodHandle target, FunctionDescriptor function, ResourceScope scope) { Objects.requireNonNull(scope); Objects.requireNonNull(target); Objects.requireNonNull(function); - target = SharedUtils.boxVaLists(target, MH_boxVaList); - return UpcallStubs.upcallAddress(CallArranger.arrangeUpcall(target, target.type(), function), (ResourceScopeImpl) scope); + SharedUtils.checkExceptions(target); + MethodType type = SharedUtils.inferMethodType(function, true); + if (!type.equals(target.type())) { + throw new IllegalArgumentException("Wrong method handle type: " + target.type()); + } + return CallArranger.arrangeUpcall(target, target.type(), function, scope); } public static VaList newVaListOfAddress(MemoryAddress ma, ResourceScope scope) { diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/sysv/TypeClass.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/sysv/TypeClass.java index 568b3d6378a4dbaf8ddd7f6ee153f2b4243faf75..1421072d50164c619ef3442441cf1cbb8d87b75e 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/sysv/TypeClass.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/sysv/TypeClass.java @@ -25,10 +25,10 @@ package jdk.internal.foreign.abi.x64.sysv; import jdk.incubator.foreign.GroupLayout; +import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.SequenceLayout; import jdk.incubator.foreign.ValueLayout; -import jdk.internal.foreign.PlatformLayouts; import jdk.internal.foreign.Utils; import java.util.ArrayList; @@ -107,11 +107,17 @@ class TypeClass { } private static ArgumentClassImpl argumentClassFor(MemoryLayout layout) { - return switch (PlatformLayouts.getKind(layout)) { - case CHAR, SHORT, INT, LONG, LONG_LONG -> ArgumentClassImpl.INTEGER; - case FLOAT, DOUBLE -> ArgumentClassImpl.SSE; - case POINTER -> ArgumentClassImpl.POINTER; - }; + Class carrier = ((ValueLayout)layout).carrier(); + if (carrier == boolean.class || carrier == byte.class || carrier == char.class || + carrier == short.class || carrier == int.class || carrier == long.class) { + return ArgumentClassImpl.INTEGER; + } else if (carrier == float.class || carrier == double.class) { + return ArgumentClassImpl.SSE; + } else if (carrier == MemoryAddress.class) { + return ArgumentClassImpl.POINTER; + } else { + throw new IllegalStateException("Cannot get here: " + carrier.getName()); + } } // TODO: handle zero length arrays diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/windows/CallArranger.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/windows/CallArranger.java index 5ff77e3928a1af32bb4cd29061a07cc7c58f35cb..df5fa2b08a9a91a2e01cf406dd8a328910a1d4db 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/windows/CallArranger.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/windows/CallArranger.java @@ -29,9 +29,10 @@ import jdk.incubator.foreign.GroupLayout; import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.NativeSymbol; +import jdk.incubator.foreign.ResourceScope; import jdk.internal.foreign.Utils; import jdk.internal.foreign.abi.CallingSequenceBuilder; -import jdk.internal.foreign.abi.UpcallHandler; import jdk.internal.foreign.abi.ABIDescriptor; import jdk.internal.foreign.abi.Binding; import jdk.internal.foreign.abi.CallingSequence; @@ -82,8 +83,6 @@ public class CallArranger { } public static Bindings getBindings(MethodType mt, FunctionDescriptor cDesc, boolean forUpcall) { - SharedUtils.checkFunctionTypes(mt, cDesc, Windowsx64Linker.ADDRESS_SIZE); - class CallingSequenceBuilderHelper { final CallingSequenceBuilder csb = new CallingSequenceBuilder(forUpcall); final BindingCalculator argCalc = @@ -91,12 +90,12 @@ public class CallArranger { final BindingCalculator retCalc = forUpcall ? new UnboxBindingCalculator(false) : new BoxBindingCalculator(false); - void addArgumentBindings(Class carrier, MemoryLayout layout) { - csb.addArgumentBindings(carrier, layout, argCalc.getBindings(carrier, layout)); + void addArgumentBindings(Class carrier, MemoryLayout layout, boolean isVararg) { + csb.addArgumentBindings(carrier, layout, argCalc.getBindings(carrier, layout, isVararg)); } void setReturnBindings(Class carrier, MemoryLayout layout) { - csb.setReturnBindings(carrier, layout, retCalc.getBindings(carrier, layout)); + csb.setReturnBindings(carrier, layout, retCalc.getBindings(carrier, layout, false)); } } var csb = new CallingSequenceBuilderHelper(); @@ -105,7 +104,7 @@ public class CallArranger { if (returnInMemory) { Class carrier = MemoryAddress.class; MemoryLayout layout = Win64.C_POINTER; - csb.addArgumentBindings(carrier, layout); + csb.addArgumentBindings(carrier, layout, false); if (forUpcall) { csb.setReturnBindings(carrier, layout); } @@ -114,7 +113,7 @@ public class CallArranger { } for (int i = 0; i < mt.parameterCount(); i++) { - csb.addArgumentBindings(mt.parameterType(i), cDesc.argumentLayouts().get(i)); + csb.addArgumentBindings(mt.parameterType(i), cDesc.argumentLayouts().get(i), SharedUtils.isVarargsIndex(cDesc, i)); } csb.csb.setTrivial(SharedUtils.isTrivial(cDesc)); @@ -134,14 +133,14 @@ public class CallArranger { return handle; } - public static UpcallHandler arrangeUpcall(MethodHandle target, MethodType mt, FunctionDescriptor cDesc) { + public static NativeSymbol arrangeUpcall(MethodHandle target, MethodType mt, FunctionDescriptor cDesc, ResourceScope scope) { Bindings bindings = getBindings(mt, cDesc, true); if (bindings.isInMemoryReturn) { target = SharedUtils.adaptUpcallForIMR(target, false /* need the return value as well */); } - return ProgrammableUpcallHandler.make(CWindows, target, bindings.callingSequence); + return ProgrammableUpcallHandler.make(CWindows, target, bindings.callingSequence, scope); } private static boolean isInMemoryReturn(Optional returnLayout) { @@ -185,7 +184,7 @@ public class CallArranger { } private interface BindingCalculator { - List getBindings(Class carrier, MemoryLayout layout); + List getBindings(Class carrier, MemoryLayout layout, boolean isVararg); } static class UnboxBindingCalculator implements BindingCalculator { @@ -196,8 +195,8 @@ public class CallArranger { } @Override - public List getBindings(Class carrier, MemoryLayout layout) { - TypeClass argumentClass = TypeClass.typeClassFor(layout); + public List getBindings(Class carrier, MemoryLayout layout, boolean isVararg) { + TypeClass argumentClass = TypeClass.typeClassFor(layout, isVararg); Binding.Builder bindings = Binding.builder(); switch (argumentClass) { case STRUCT_REGISTER: { @@ -211,14 +210,13 @@ public class CallArranger { case STRUCT_REFERENCE: { assert carrier == MemorySegment.class; bindings.copy(layout) - .baseAddress() - .unboxAddress(); + .unboxAddress(MemorySegment.class); VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER, layout); bindings.vmStore(storage, long.class); break; } case POINTER: { - bindings.unboxAddress(); + bindings.unboxAddress(carrier); VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER, layout); bindings.vmStore(storage, long.class); break; @@ -259,8 +257,8 @@ public class CallArranger { } @Override - public List getBindings(Class carrier, MemoryLayout layout) { - TypeClass argumentClass = TypeClass.typeClassFor(layout); + public List getBindings(Class carrier, MemoryLayout layout, boolean isVararg) { + TypeClass argumentClass = TypeClass.typeClassFor(layout, isVararg); Binding.Builder bindings = Binding.builder(); switch (argumentClass) { case STRUCT_REGISTER: { diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/windows/TypeClass.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/windows/TypeClass.java index 5a96c1b008ef2749fe41969d4ba1c2e7877a4313..d24963fc564a9fefd74273e258f1eca67abdcd85 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/windows/TypeClass.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/windows/TypeClass.java @@ -25,11 +25,9 @@ package jdk.internal.foreign.abi.x64.windows; import jdk.incubator.foreign.GroupLayout; +import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.ValueLayout; -import jdk.internal.foreign.PlatformLayouts; - -import static jdk.internal.foreign.PlatformLayouts.Win64.VARARGS_ATTRIBUTE_NAME; enum TypeClass { STRUCT_REGISTER, @@ -39,7 +37,7 @@ enum TypeClass { FLOAT, VARARG_FLOAT; - private static TypeClass classifyValueType(ValueLayout type) { + private static TypeClass classifyValueType(ValueLayout type, boolean isVararg) { // No 128 bit integers in the Windows C ABI. There are __m128(i|d) intrinsic types but they act just // like a struct when passing as an argument (passed by pointer). // https://docs.microsoft.com/en-us/cpp/cpp/m128?view=vs-2019 @@ -49,17 +47,21 @@ enum TypeClass { // but must be considered volatile across function calls." // https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=vs-2019 - return switch (PlatformLayouts.getKind(type)) { - case CHAR, SHORT, INT, LONG, LONG_LONG -> INTEGER; - case POINTER -> POINTER; - case FLOAT, DOUBLE -> { - if (type.attribute(VARARGS_ATTRIBUTE_NAME) - .map(Boolean.class::cast).orElse(false)) { - yield VARARG_FLOAT; - } - yield FLOAT; + Class carrier = type.carrier(); + if (carrier == boolean.class || carrier == byte.class || carrier == char.class || + carrier == short.class || carrier == int.class || carrier == long.class) { + return INTEGER; + } else if (carrier == float.class || carrier == double.class) { + if (isVararg) { + return VARARG_FLOAT; + } else { + return FLOAT; } - }; + } else if (carrier == MemoryAddress.class) { + return POINTER; + } else { + throw new IllegalStateException("Cannot get here: " + carrier.getName()); + } } static boolean isRegisterAggregate(MemoryLayout type) { @@ -77,9 +79,9 @@ enum TypeClass { return STRUCT_REFERENCE; } - static TypeClass typeClassFor(MemoryLayout type) { + static TypeClass typeClassFor(MemoryLayout type, boolean isVararg) { if (type instanceof ValueLayout) { - return classifyValueType((ValueLayout) type); + return classifyValueType((ValueLayout) type, isVararg); } else if (type instanceof GroupLayout) { return classifyStructType(type); } else { diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/windows/WinVaList.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/windows/WinVaList.java index debdf9c6b5d6a04955a30e7fc49d62e0c42bbf5e..f74acf568b799036c84b3dd0842be3aeb16787a9 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/windows/WinVaList.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/windows/WinVaList.java @@ -26,7 +26,7 @@ package jdk.internal.foreign.abi.x64.windows; import jdk.incubator.foreign.*; -import jdk.incubator.foreign.CLinker.VaList; +import jdk.internal.foreign.Scoped; import jdk.internal.foreign.ResourceScopeImpl; import jdk.internal.foreign.abi.SharedUtils; import jdk.internal.foreign.abi.SharedUtils.SimpleVaArg; @@ -55,10 +55,10 @@ import static jdk.internal.foreign.PlatformLayouts.Win64.C_POINTER; // ? **(t**)((ap += sizeof(__int64)) - sizeof(__int64)) \ // : *(t* )((ap += sizeof(__int64)) - sizeof(__int64))) // -public non-sealed class WinVaList implements VaList { +public non-sealed class WinVaList implements VaList, Scoped { public static final Class CARRIER = MemoryAddress.class; private static final long VA_SLOT_SIZE_BYTES = 8; - private static final VarHandle VH_address = MemoryHandles.asAddressVarHandle(C_POINTER.varHandle(long.class)); + private static final VarHandle VH_address = C_POINTER.varHandle(); private static final VaList EMPTY = new SharedUtils.EmptyVaList(MemoryAddress.NULL); @@ -75,63 +75,54 @@ public non-sealed class WinVaList implements VaList { } @Override - public int vargAsInt(MemoryLayout layout) { + public int nextVarg(ValueLayout.OfInt layout) { return (int) read(int.class, layout); } @Override - public long vargAsLong(MemoryLayout layout) { + public long nextVarg(ValueLayout.OfLong layout) { return (long) read(long.class, layout); } @Override - public double vargAsDouble(MemoryLayout layout) { + public double nextVarg(ValueLayout.OfDouble layout) { return (double) read(double.class, layout); } @Override - public MemoryAddress vargAsAddress(MemoryLayout layout) { + public MemoryAddress nextVarg(ValueLayout.OfAddress layout) { return (MemoryAddress) read(MemoryAddress.class, layout); } @Override - public MemorySegment vargAsSegment(MemoryLayout layout, SegmentAllocator allocator) { + public MemorySegment nextVarg(GroupLayout layout, SegmentAllocator allocator) { Objects.requireNonNull(allocator); return (MemorySegment) read(MemorySegment.class, layout, allocator); } - @Override - public MemorySegment vargAsSegment(MemoryLayout layout, ResourceScope scope) { - return vargAsSegment(layout, SegmentAllocator.ofScope(scope)); - } - private Object read(Class carrier, MemoryLayout layout) { return read(carrier, layout, SharedUtils.THROWING_ALLOCATOR); } private Object read(Class carrier, MemoryLayout layout, SegmentAllocator allocator) { Objects.requireNonNull(layout); - SharedUtils.checkCompatibleType(carrier, layout, Windowsx64Linker.ADDRESS_SIZE); Object res; if (carrier == MemorySegment.class) { - TypeClass typeClass = TypeClass.typeClassFor(layout); + TypeClass typeClass = TypeClass.typeClassFor(layout, false); res = switch (typeClass) { case STRUCT_REFERENCE -> { MemoryAddress structAddr = (MemoryAddress) VH_address.get(segment); - MemorySegment struct = structAddr.asSegment(layout.byteSize(), scope()); + MemorySegment struct = MemorySegment.ofAddress(structAddr, layout.byteSize(), scope()); MemorySegment seg = allocator.allocate(layout); seg.copyFrom(struct); yield seg; } - case STRUCT_REGISTER -> { - MemorySegment struct = allocator.allocate(layout); - struct.copyFrom(segment.asSlice(0L, layout.byteSize())); - yield struct; - } + case STRUCT_REGISTER -> + allocator.allocate(layout).copyFrom(segment.asSlice(0, layout.byteSize())); default -> throw new IllegalStateException("Unexpected TypeClass: " + typeClass); }; } else { - VarHandle reader = SharedUtils.vhPrimitiveOrAddress(carrier, layout); + VarHandle reader = layout.varHandle(); res = reader.get(segment); } segment = segment.asSlice(VA_SLOT_SIZE_BYTES); @@ -141,12 +132,13 @@ public non-sealed class WinVaList implements VaList { @Override public void skip(MemoryLayout... layouts) { Objects.requireNonNull(layouts); + ((ResourceScopeImpl)scope).checkValidStateSlow(); Stream.of(layouts).forEach(Objects::requireNonNull); segment = segment.asSlice(layouts.length * VA_SLOT_SIZE_BYTES); } static WinVaList ofAddress(MemoryAddress addr, ResourceScope scope) { - MemorySegment segment = addr.asSegment(Long.MAX_VALUE, scope); + MemorySegment segment = MemorySegment.ofAddress(addr, Long.MAX_VALUE, scope); return new WinVaList(segment, scope); } @@ -183,33 +175,32 @@ public non-sealed class WinVaList implements VaList { private Builder arg(Class carrier, MemoryLayout layout, Object value) { Objects.requireNonNull(layout); Objects.requireNonNull(value); - SharedUtils.checkCompatibleType(carrier, layout, Windowsx64Linker.ADDRESS_SIZE); args.add(new SimpleVaArg(carrier, layout, value)); return this; } @Override - public Builder vargFromInt(ValueLayout layout, int value) { + public Builder addVarg(ValueLayout.OfInt layout, int value) { return arg(int.class, layout, value); } @Override - public Builder vargFromLong(ValueLayout layout, long value) { + public Builder addVarg(ValueLayout.OfLong layout, long value) { return arg(long.class, layout, value); } @Override - public Builder vargFromDouble(ValueLayout layout, double value) { + public Builder addVarg(ValueLayout.OfDouble layout, double value) { return arg(double.class, layout, value); } @Override - public Builder vargFromAddress(ValueLayout layout, Addressable value) { + public Builder addVarg(ValueLayout.OfAddress layout, Addressable value) { return arg(MemoryAddress.class, layout, value.address()); } @Override - public Builder vargFromSegment(GroupLayout layout, MemorySegment value) { + public Builder addVarg(GroupLayout layout, MemorySegment value) { return arg(MemorySegment.class, layout, value); } @@ -217,7 +208,7 @@ public non-sealed class WinVaList implements VaList { if (args.isEmpty()) { return EMPTY; } - SegmentAllocator allocator = SegmentAllocator.arenaAllocator(scope); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(scope); MemorySegment segment = allocator.allocate(VA_SLOT_SIZE_BYTES * args.size()); List attachedSegments = new ArrayList<>(); attachedSegments.add(segment); @@ -226,7 +217,7 @@ public non-sealed class WinVaList implements VaList { for (SimpleVaArg arg : args) { if (arg.carrier == MemorySegment.class) { MemorySegment msArg = ((MemorySegment) arg.value); - TypeClass typeClass = TypeClass.typeClassFor(arg.layout); + TypeClass typeClass = TypeClass.typeClassFor(arg.layout, false); switch (typeClass) { case STRUCT_REFERENCE -> { MemorySegment copy = allocator.allocate(arg.layout); @@ -234,10 +225,8 @@ public non-sealed class WinVaList implements VaList { attachedSegments.add(copy); VH_address.set(cursor, copy.address()); } - case STRUCT_REGISTER -> { - MemorySegment slice = cursor.asSlice(0, VA_SLOT_SIZE_BYTES); - slice.copyFrom(msArg); - } + case STRUCT_REGISTER -> + cursor.copyFrom(msArg.asSlice(0, VA_SLOT_SIZE_BYTES)); default -> throw new IllegalStateException("Unexpected TypeClass: " + typeClass); } } else { diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/windows/Windowsx64Linker.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/windows/Windowsx64Linker.java index d40aabd1e7d362a2527f21657cb8946ba15f8723..6d7c8b23cacd0097315d43d59c257426bc88874d 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/windows/Windowsx64Linker.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/windows/Windowsx64Linker.java @@ -24,14 +24,14 @@ */ package jdk.internal.foreign.abi.x64.windows; +import jdk.incubator.foreign.CLinker; import jdk.incubator.foreign.FunctionDescriptor; import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.NativeSymbol; import jdk.incubator.foreign.ResourceScope; -import jdk.internal.foreign.AbstractCLinker; -import jdk.internal.foreign.ResourceScopeImpl; +import jdk.incubator.foreign.VaList; import jdk.internal.foreign.abi.SharedUtils; -import jdk.internal.foreign.abi.UpcallStubs; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; @@ -42,7 +42,7 @@ import java.util.function.Consumer; /** * ABI implementation based on Windows ABI AMD64 supplement v.0.99.6 */ -public final class Windowsx64Linker extends AbstractCLinker { +public final class Windowsx64Linker implements CLinker { public static final int MAX_INTEGER_ARGUMENT_REGISTERS = 4; public static final int MAX_INTEGER_RETURN_REGISTERS = 1; @@ -55,21 +55,6 @@ public final class Windowsx64Linker extends AbstractCLinker { static final long ADDRESS_SIZE = 64; // bits - private static final MethodHandle MH_unboxVaList; - private static final MethodHandle MH_boxVaList; - - static { - try { - MethodHandles.Lookup lookup = MethodHandles.lookup(); - MH_unboxVaList = lookup.findVirtual(VaList.class, "address", - MethodType.methodType(MemoryAddress.class)); - MH_boxVaList = MethodHandles.insertArguments(lookup.findStatic(Windowsx64Linker.class, "newVaListOfAddress", - MethodType.methodType(VaList.class, MemoryAddress.class, ResourceScope.class)), 1, ResourceScope.globalScope()); - } catch (ReflectiveOperationException e) { - throw new ExceptionInInitializerError(e); - } - } - public static Windowsx64Linker getInstance() { if (instance == null) { instance = new Windowsx64Linker(); @@ -84,26 +69,28 @@ public final class Windowsx64Linker extends AbstractCLinker { } @Override - public final MethodHandle downcallHandle(MethodType type, FunctionDescriptor function) { - Objects.requireNonNull(type); + public final MethodHandle downcallHandle(FunctionDescriptor function) { Objects.requireNonNull(function); - MethodType llMt = SharedUtils.convertVaListCarriers(type, WinVaList.CARRIER); - MethodHandle handle = CallArranger.arrangeDowncall(llMt, function); + MethodType type = SharedUtils.inferMethodType(function, false); + MethodHandle handle = CallArranger.arrangeDowncall(type, function); if (!type.returnType().equals(MemorySegment.class)) { // not returning segment, just insert a throwing allocator handle = MethodHandles.insertArguments(handle, 1, SharedUtils.THROWING_ALLOCATOR); } - handle = SharedUtils.unboxVaLists(type, handle, MH_unboxVaList); - return handle; + return SharedUtils.wrapDowncall(handle, function); } @Override - public final MemoryAddress upcallStub(MethodHandle target, FunctionDescriptor function, ResourceScope scope) { + public final NativeSymbol upcallStub(MethodHandle target, FunctionDescriptor function, ResourceScope scope) { Objects.requireNonNull(scope); Objects.requireNonNull(target); Objects.requireNonNull(function); - target = SharedUtils.boxVaLists(target, MH_boxVaList); - return UpcallStubs.upcallAddress(CallArranger.arrangeUpcall(target, target.type(), function), (ResourceScopeImpl) scope); + SharedUtils.checkExceptions(target); + MethodType type = SharedUtils.inferMethodType(function, true); + if (!type.equals(target.type())) { + throw new IllegalArgumentException("Wrong method handle type: " + target.type()); + } + return CallArranger.arrangeUpcall(target, target.type(), function, scope); } public static VaList newVaListOfAddress(MemoryAddress ma, ResourceScope scope) { diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractVector.java index 1ffdb058a273c0d67e24f71c1d0dce36c69a961b..6acd4282edd518130293ac2ff92ce3cefec2d6f8 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractVector.java @@ -707,7 +707,7 @@ abstract class AbstractVector extends Vector { return v.convert0('C', rspi); } // extend in place, but remove unwanted sign extension - long mask = -1L >>> sizeChange; + long mask = -1L >>> -dsp.elementSize(); return (AbstractVector) v.convert0('C', rspi) .lanewise(AND, rspi.broadcast(mask)); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte128Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte128Vector.java index 3a2620583bfc4e336c55ea6845716398528bf342..e4fae8e0acfff259fe909123465055a6ca354adf 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte128Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte128Vector.java @@ -757,9 +757,9 @@ final class Byte128Vector extends ByteVector { @ForceInline /*package-private*/ static Byte128Mask maskAll(boolean bit) { - return VectorSupport.broadcastCoerced(Byte128Mask.class, byte.class, VLENGTH, - (bit ? -1 : 0), null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + return VectorSupport.fromBitsCoerced(Byte128Mask.class, byte.class, VLENGTH, + (bit ? -1 : 0), MODE_BROADCAST, null, + (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final Byte128Mask TRUE_MASK = new Byte128Mask(true); private static final Byte128Mask FALSE_MASK = new Byte128Mask(false); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte256Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte256Vector.java index 6fbe00dfdeac3213798401ac2b1b86cd59bf9430..7c123c893b4e8f8f8da0c3fbda772cc747621d57 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte256Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte256Vector.java @@ -789,9 +789,9 @@ final class Byte256Vector extends ByteVector { @ForceInline /*package-private*/ static Byte256Mask maskAll(boolean bit) { - return VectorSupport.broadcastCoerced(Byte256Mask.class, byte.class, VLENGTH, - (bit ? -1 : 0), null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + return VectorSupport.fromBitsCoerced(Byte256Mask.class, byte.class, VLENGTH, + (bit ? -1 : 0), MODE_BROADCAST, null, + (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final Byte256Mask TRUE_MASK = new Byte256Mask(true); private static final Byte256Mask FALSE_MASK = new Byte256Mask(false); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte512Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte512Vector.java index fd6117a7884b199afefb05e051088cfa821cf7eb..1b63838b14c8b2f57a0c397f0e1f495f133b4f84 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte512Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte512Vector.java @@ -853,9 +853,9 @@ final class Byte512Vector extends ByteVector { @ForceInline /*package-private*/ static Byte512Mask maskAll(boolean bit) { - return VectorSupport.broadcastCoerced(Byte512Mask.class, byte.class, VLENGTH, - (bit ? -1 : 0), null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + return VectorSupport.fromBitsCoerced(Byte512Mask.class, byte.class, VLENGTH, + (bit ? -1 : 0), MODE_BROADCAST, null, + (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final Byte512Mask TRUE_MASK = new Byte512Mask(true); private static final Byte512Mask FALSE_MASK = new Byte512Mask(false); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte64Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte64Vector.java index 309f54eaf7638a9f4b770a2aec99e80971676fb8..16010b7de0987ac2b4cab568a6b46e64cf7abfe5 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte64Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte64Vector.java @@ -741,9 +741,9 @@ final class Byte64Vector extends ByteVector { @ForceInline /*package-private*/ static Byte64Mask maskAll(boolean bit) { - return VectorSupport.broadcastCoerced(Byte64Mask.class, byte.class, VLENGTH, - (bit ? -1 : 0), null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + return VectorSupport.fromBitsCoerced(Byte64Mask.class, byte.class, VLENGTH, + (bit ? -1 : 0), MODE_BROADCAST, null, + (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final Byte64Mask TRUE_MASK = new Byte64Mask(true); private static final Byte64Mask FALSE_MASK = new Byte64Mask(false); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteMaxVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteMaxVector.java index e27775d61c3982b111e001068cb341701b566c1b..fb36dab860ce21400f499e0e861cf59a21bb9cf8 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteMaxVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteMaxVector.java @@ -727,9 +727,9 @@ final class ByteMaxVector extends ByteVector { @ForceInline /*package-private*/ static ByteMaxMask maskAll(boolean bit) { - return VectorSupport.broadcastCoerced(ByteMaxMask.class, byte.class, VLENGTH, - (bit ? -1 : 0), null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + return VectorSupport.fromBitsCoerced(ByteMaxMask.class, byte.class, VLENGTH, + (bit ? -1 : 0), MODE_BROADCAST, null, + (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final ByteMaxMask TRUE_MASK = new ByteMaxMask(true); private static final ByteMaxMask FALSE_MASK = new ByteMaxMask(false); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java index 32b84aef14b9a46d9b66834736dc6e2aa9ea8164..256e1a5700f4154b4dd5fcab841fd6715c436564 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java @@ -455,8 +455,8 @@ public abstract class ByteVector extends AbstractVector { @ForceInline public static ByteVector zero(VectorSpecies species) { ByteSpecies vsp = (ByteSpecies) species; - return VectorSupport.broadcastCoerced(vsp.vectorType(), byte.class, species.length(), - 0, vsp, + return VectorSupport.fromBitsCoerced(vsp.vectorType(), byte.class, species.length(), + 0, MODE_BROADCAST, vsp, ((bits_, s_) -> s_.rvOp(i -> bits_))); } @@ -4149,9 +4149,9 @@ public abstract class ByteVector extends AbstractVector { @ForceInline final ByteVector broadcastBits(long bits) { return (ByteVector) - VectorSupport.broadcastCoerced( + VectorSupport.fromBitsCoerced( vectorType, byte.class, laneCount, - bits, this, + bits, MODE_BROADCAST, this, (bits_, s_) -> s_.rvOp(i -> bits_)); } diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double128Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double128Vector.java index 62f2eb5eff586a3f8f64c315ab1baf5a930b6862..d4762fe779659e522abb67ca10c604639c7cecb5 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double128Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double128Vector.java @@ -718,9 +718,9 @@ final class Double128Vector extends DoubleVector { @ForceInline /*package-private*/ static Double128Mask maskAll(boolean bit) { - return VectorSupport.broadcastCoerced(Double128Mask.class, long.class, VLENGTH, - (bit ? -1 : 0), null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + return VectorSupport.fromBitsCoerced(Double128Mask.class, long.class, VLENGTH, + (bit ? -1 : 0), MODE_BROADCAST, null, + (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final Double128Mask TRUE_MASK = new Double128Mask(true); private static final Double128Mask FALSE_MASK = new Double128Mask(false); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double256Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double256Vector.java index 547684af87d29652d788386febe4e02e35a6f490..147d6b866d63a1bd827bc3fd035695e6c88bdc83 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double256Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double256Vector.java @@ -722,9 +722,9 @@ final class Double256Vector extends DoubleVector { @ForceInline /*package-private*/ static Double256Mask maskAll(boolean bit) { - return VectorSupport.broadcastCoerced(Double256Mask.class, long.class, VLENGTH, - (bit ? -1 : 0), null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + return VectorSupport.fromBitsCoerced(Double256Mask.class, long.class, VLENGTH, + (bit ? -1 : 0), MODE_BROADCAST, null, + (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final Double256Mask TRUE_MASK = new Double256Mask(true); private static final Double256Mask FALSE_MASK = new Double256Mask(false); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double512Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double512Vector.java index bacc0cde0881f2a5dc4e8c7fd9395b07fb52012b..e091ca9b63fd4407e36323ec029c59dc3821dad6 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double512Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double512Vector.java @@ -730,9 +730,9 @@ final class Double512Vector extends DoubleVector { @ForceInline /*package-private*/ static Double512Mask maskAll(boolean bit) { - return VectorSupport.broadcastCoerced(Double512Mask.class, long.class, VLENGTH, - (bit ? -1 : 0), null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + return VectorSupport.fromBitsCoerced(Double512Mask.class, long.class, VLENGTH, + (bit ? -1 : 0), MODE_BROADCAST, null, + (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final Double512Mask TRUE_MASK = new Double512Mask(true); private static final Double512Mask FALSE_MASK = new Double512Mask(false); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double64Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double64Vector.java index 29977c72c6aeaf271a2888cbc67df202db0e1aec..a90ff9c761ca89a4ccedb06c239050046dc6c7a4 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double64Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double64Vector.java @@ -716,9 +716,9 @@ final class Double64Vector extends DoubleVector { @ForceInline /*package-private*/ static Double64Mask maskAll(boolean bit) { - return VectorSupport.broadcastCoerced(Double64Mask.class, long.class, VLENGTH, - (bit ? -1 : 0), null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + return VectorSupport.fromBitsCoerced(Double64Mask.class, long.class, VLENGTH, + (bit ? -1 : 0), MODE_BROADCAST, null, + (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final Double64Mask TRUE_MASK = new Double64Mask(true); private static final Double64Mask FALSE_MASK = new Double64Mask(false); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleMaxVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleMaxVector.java index c9db9f93b40a9092288c6ba4e21ad5a6ff00d28f..bf4ce4e6422a8a4e5fadfba200a0be293e0e341b 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleMaxVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleMaxVector.java @@ -715,9 +715,9 @@ final class DoubleMaxVector extends DoubleVector { @ForceInline /*package-private*/ static DoubleMaxMask maskAll(boolean bit) { - return VectorSupport.broadcastCoerced(DoubleMaxMask.class, long.class, VLENGTH, - (bit ? -1 : 0), null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + return VectorSupport.fromBitsCoerced(DoubleMaxMask.class, long.class, VLENGTH, + (bit ? -1 : 0), MODE_BROADCAST, null, + (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final DoubleMaxMask TRUE_MASK = new DoubleMaxMask(true); private static final DoubleMaxMask FALSE_MASK = new DoubleMaxMask(false); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java index 691a4def745301984b2448f9e8527c8d2cc2b961..8455e35467890d85654b94123e8ac1b18c0c48d5 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java @@ -444,8 +444,8 @@ public abstract class DoubleVector extends AbstractVector { @ForceInline public static DoubleVector zero(VectorSpecies species) { DoubleSpecies vsp = (DoubleSpecies) species; - return VectorSupport.broadcastCoerced(vsp.vectorType(), double.class, species.length(), - toBits(0.0f), vsp, + return VectorSupport.fromBitsCoerced(vsp.vectorType(), double.class, species.length(), + toBits(0.0f), MODE_BROADCAST, vsp, ((bits_, s_) -> s_.rvOp(i -> bits_))); } @@ -3754,9 +3754,9 @@ public abstract class DoubleVector extends AbstractVector { @ForceInline final DoubleVector broadcastBits(long bits) { return (DoubleVector) - VectorSupport.broadcastCoerced( + VectorSupport.fromBitsCoerced( vectorType, double.class, laneCount, - bits, this, + bits, MODE_BROADCAST, this, (bits_, s_) -> s_.rvOp(i -> bits_)); } diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float128Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float128Vector.java index 4e0dd018d269986843332e216b4ddafe64b72000..88f6d76d0cb76d0d8649c1913e1981299aff18a5 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float128Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float128Vector.java @@ -722,9 +722,9 @@ final class Float128Vector extends FloatVector { @ForceInline /*package-private*/ static Float128Mask maskAll(boolean bit) { - return VectorSupport.broadcastCoerced(Float128Mask.class, int.class, VLENGTH, - (bit ? -1 : 0), null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + return VectorSupport.fromBitsCoerced(Float128Mask.class, int.class, VLENGTH, + (bit ? -1 : 0), MODE_BROADCAST, null, + (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final Float128Mask TRUE_MASK = new Float128Mask(true); private static final Float128Mask FALSE_MASK = new Float128Mask(false); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float256Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float256Vector.java index 7812876f4eb59f8874ed9c977d653e22230681cb..4b039df7984ce16b136c1aa9d4d34eca9a3132d9 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float256Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float256Vector.java @@ -730,9 +730,9 @@ final class Float256Vector extends FloatVector { @ForceInline /*package-private*/ static Float256Mask maskAll(boolean bit) { - return VectorSupport.broadcastCoerced(Float256Mask.class, int.class, VLENGTH, - (bit ? -1 : 0), null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + return VectorSupport.fromBitsCoerced(Float256Mask.class, int.class, VLENGTH, + (bit ? -1 : 0), MODE_BROADCAST, null, + (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final Float256Mask TRUE_MASK = new Float256Mask(true); private static final Float256Mask FALSE_MASK = new Float256Mask(false); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float512Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float512Vector.java index a8936709baadb9c7e3a379b59fa7bae36376fda6..7864af72205406da5201a035e34b0c4ad5e5914a 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float512Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float512Vector.java @@ -746,9 +746,9 @@ final class Float512Vector extends FloatVector { @ForceInline /*package-private*/ static Float512Mask maskAll(boolean bit) { - return VectorSupport.broadcastCoerced(Float512Mask.class, int.class, VLENGTH, - (bit ? -1 : 0), null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + return VectorSupport.fromBitsCoerced(Float512Mask.class, int.class, VLENGTH, + (bit ? -1 : 0), MODE_BROADCAST, null, + (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final Float512Mask TRUE_MASK = new Float512Mask(true); private static final Float512Mask FALSE_MASK = new Float512Mask(false); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float64Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float64Vector.java index 0c91d46e64e46788d840b52abbd186b2deb4f3bb..bbdbcee1c5fb38e85568c1ed3358040b7600a810 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float64Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float64Vector.java @@ -718,9 +718,9 @@ final class Float64Vector extends FloatVector { @ForceInline /*package-private*/ static Float64Mask maskAll(boolean bit) { - return VectorSupport.broadcastCoerced(Float64Mask.class, int.class, VLENGTH, - (bit ? -1 : 0), null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + return VectorSupport.fromBitsCoerced(Float64Mask.class, int.class, VLENGTH, + (bit ? -1 : 0), MODE_BROADCAST, null, + (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final Float64Mask TRUE_MASK = new Float64Mask(true); private static final Float64Mask FALSE_MASK = new Float64Mask(false); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatMaxVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatMaxVector.java index f2e1bd05c13d290677c414ae909b4597f2b43e88..bba093b3b762e3d99ef6e621a1281b988eda9b9c 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatMaxVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatMaxVector.java @@ -715,9 +715,9 @@ final class FloatMaxVector extends FloatVector { @ForceInline /*package-private*/ static FloatMaxMask maskAll(boolean bit) { - return VectorSupport.broadcastCoerced(FloatMaxMask.class, int.class, VLENGTH, - (bit ? -1 : 0), null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + return VectorSupport.fromBitsCoerced(FloatMaxMask.class, int.class, VLENGTH, + (bit ? -1 : 0), MODE_BROADCAST, null, + (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final FloatMaxMask TRUE_MASK = new FloatMaxMask(true); private static final FloatMaxMask FALSE_MASK = new FloatMaxMask(false); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java index d5dbc2f9efa36fd125f5c3cf7d812ca0b6c2ca20..1dc63aa1de34feda1853fb7b20af06ccf0ee7ca4 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java @@ -444,8 +444,8 @@ public abstract class FloatVector extends AbstractVector { @ForceInline public static FloatVector zero(VectorSpecies species) { FloatSpecies vsp = (FloatSpecies) species; - return VectorSupport.broadcastCoerced(vsp.vectorType(), float.class, species.length(), - toBits(0.0f), vsp, + return VectorSupport.fromBitsCoerced(vsp.vectorType(), float.class, species.length(), + toBits(0.0f), MODE_BROADCAST, vsp, ((bits_, s_) -> s_.rvOp(i -> bits_))); } @@ -3704,9 +3704,9 @@ public abstract class FloatVector extends AbstractVector { @ForceInline final FloatVector broadcastBits(long bits) { return (FloatVector) - VectorSupport.broadcastCoerced( + VectorSupport.fromBitsCoerced( vectorType, float.class, laneCount, - bits, this, + bits, MODE_BROADCAST, this, (bits_, s_) -> s_.rvOp(i -> bits_)); } diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Int128Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Int128Vector.java index f54042159699ce51d8bf954ec127399f501d6c8d..3a88ba76e8044a25ea1642b52d61fe375c4039a6 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Int128Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Int128Vector.java @@ -733,9 +733,9 @@ final class Int128Vector extends IntVector { @ForceInline /*package-private*/ static Int128Mask maskAll(boolean bit) { - return VectorSupport.broadcastCoerced(Int128Mask.class, int.class, VLENGTH, - (bit ? -1 : 0), null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + return VectorSupport.fromBitsCoerced(Int128Mask.class, int.class, VLENGTH, + (bit ? -1 : 0), MODE_BROADCAST, null, + (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final Int128Mask TRUE_MASK = new Int128Mask(true); private static final Int128Mask FALSE_MASK = new Int128Mask(false); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Int256Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Int256Vector.java index f5ed7ce09b87069317a722e64922e2e8c56bb7e5..ffc560e5f52ec6b0512886e12919fe141f719c3e 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Int256Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Int256Vector.java @@ -741,9 +741,9 @@ final class Int256Vector extends IntVector { @ForceInline /*package-private*/ static Int256Mask maskAll(boolean bit) { - return VectorSupport.broadcastCoerced(Int256Mask.class, int.class, VLENGTH, - (bit ? -1 : 0), null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + return VectorSupport.fromBitsCoerced(Int256Mask.class, int.class, VLENGTH, + (bit ? -1 : 0), MODE_BROADCAST, null, + (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final Int256Mask TRUE_MASK = new Int256Mask(true); private static final Int256Mask FALSE_MASK = new Int256Mask(false); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Int512Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Int512Vector.java index 6da5f59d602c040812e21ebd2053f88f66530e72..a2ff6d515e372a9bfa5164a9999b7b69f7bf6cf8 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Int512Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Int512Vector.java @@ -757,9 +757,9 @@ final class Int512Vector extends IntVector { @ForceInline /*package-private*/ static Int512Mask maskAll(boolean bit) { - return VectorSupport.broadcastCoerced(Int512Mask.class, int.class, VLENGTH, - (bit ? -1 : 0), null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + return VectorSupport.fromBitsCoerced(Int512Mask.class, int.class, VLENGTH, + (bit ? -1 : 0), MODE_BROADCAST, null, + (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final Int512Mask TRUE_MASK = new Int512Mask(true); private static final Int512Mask FALSE_MASK = new Int512Mask(false); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Int64Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Int64Vector.java index c9b1afb21b7a9c2e87f1696377aa09dc08b750fb..996f35ac15d480b07570c9ac01f6ccb9cc7feb76 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Int64Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Int64Vector.java @@ -729,9 +729,9 @@ final class Int64Vector extends IntVector { @ForceInline /*package-private*/ static Int64Mask maskAll(boolean bit) { - return VectorSupport.broadcastCoerced(Int64Mask.class, int.class, VLENGTH, - (bit ? -1 : 0), null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + return VectorSupport.fromBitsCoerced(Int64Mask.class, int.class, VLENGTH, + (bit ? -1 : 0), MODE_BROADCAST, null, + (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final Int64Mask TRUE_MASK = new Int64Mask(true); private static final Int64Mask FALSE_MASK = new Int64Mask(false); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntMaxVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntMaxVector.java index 7b28a5947b067896540e5f31b6b92e45744535ef..cfc645fcd6b76a53402fc682b9b85c8bc446ccd4 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntMaxVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntMaxVector.java @@ -727,9 +727,9 @@ final class IntMaxVector extends IntVector { @ForceInline /*package-private*/ static IntMaxMask maskAll(boolean bit) { - return VectorSupport.broadcastCoerced(IntMaxMask.class, int.class, VLENGTH, - (bit ? -1 : 0), null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + return VectorSupport.fromBitsCoerced(IntMaxMask.class, int.class, VLENGTH, + (bit ? -1 : 0), MODE_BROADCAST, null, + (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final IntMaxMask TRUE_MASK = new IntMaxMask(true); private static final IntMaxMask FALSE_MASK = new IntMaxMask(false); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector.java index 3deb61e990403ac289c3187820c50699f29fff21..29dbfe5a796ee1e304bd71b4bd048adff2afe1e3 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector.java @@ -455,8 +455,8 @@ public abstract class IntVector extends AbstractVector { @ForceInline public static IntVector zero(VectorSpecies species) { IntSpecies vsp = (IntSpecies) species; - return VectorSupport.broadcastCoerced(vsp.vectorType(), int.class, species.length(), - 0, vsp, + return VectorSupport.fromBitsCoerced(vsp.vectorType(), int.class, species.length(), + 0, MODE_BROADCAST, vsp, ((bits_, s_) -> s_.rvOp(i -> bits_))); } @@ -3874,9 +3874,9 @@ public abstract class IntVector extends AbstractVector { @ForceInline final IntVector broadcastBits(long bits) { return (IntVector) - VectorSupport.broadcastCoerced( + VectorSupport.fromBitsCoerced( vectorType, int.class, laneCount, - bits, this, + bits, MODE_BROADCAST, this, (bits_, s_) -> s_.rvOp(i -> bits_)); } diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Long128Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Long128Vector.java index 81dbb215f0df0bfe3443c657dfbe12d8601a3af7..aad676d8fcebd4623e6ae8074c802a9157707d1a 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Long128Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Long128Vector.java @@ -719,9 +719,9 @@ final class Long128Vector extends LongVector { @ForceInline /*package-private*/ static Long128Mask maskAll(boolean bit) { - return VectorSupport.broadcastCoerced(Long128Mask.class, long.class, VLENGTH, - (bit ? -1 : 0), null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + return VectorSupport.fromBitsCoerced(Long128Mask.class, long.class, VLENGTH, + (bit ? -1 : 0), MODE_BROADCAST, null, + (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final Long128Mask TRUE_MASK = new Long128Mask(true); private static final Long128Mask FALSE_MASK = new Long128Mask(false); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Long256Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Long256Vector.java index 569bd91eafa3a3845d72383b2224ae5267c65fa2..85f1e54f24290f5bdb38e1998ed9064b4526181d 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Long256Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Long256Vector.java @@ -723,9 +723,9 @@ final class Long256Vector extends LongVector { @ForceInline /*package-private*/ static Long256Mask maskAll(boolean bit) { - return VectorSupport.broadcastCoerced(Long256Mask.class, long.class, VLENGTH, - (bit ? -1 : 0), null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + return VectorSupport.fromBitsCoerced(Long256Mask.class, long.class, VLENGTH, + (bit ? -1 : 0), MODE_BROADCAST, null, + (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final Long256Mask TRUE_MASK = new Long256Mask(true); private static final Long256Mask FALSE_MASK = new Long256Mask(false); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Long512Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Long512Vector.java index 543baf97d47127ff11f06cdb9872f6e51695a884..1642b885f348a096bb9a3263d398abcceff97996 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Long512Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Long512Vector.java @@ -731,9 +731,9 @@ final class Long512Vector extends LongVector { @ForceInline /*package-private*/ static Long512Mask maskAll(boolean bit) { - return VectorSupport.broadcastCoerced(Long512Mask.class, long.class, VLENGTH, - (bit ? -1 : 0), null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + return VectorSupport.fromBitsCoerced(Long512Mask.class, long.class, VLENGTH, + (bit ? -1 : 0), MODE_BROADCAST, null, + (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final Long512Mask TRUE_MASK = new Long512Mask(true); private static final Long512Mask FALSE_MASK = new Long512Mask(false); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Long64Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Long64Vector.java index 328b399d59eb4c47b074427222f7e39a4c0ab5aa..3e67506c392157e666590640838cd45774343b66 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Long64Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Long64Vector.java @@ -717,9 +717,9 @@ final class Long64Vector extends LongVector { @ForceInline /*package-private*/ static Long64Mask maskAll(boolean bit) { - return VectorSupport.broadcastCoerced(Long64Mask.class, long.class, VLENGTH, - (bit ? -1 : 0), null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + return VectorSupport.fromBitsCoerced(Long64Mask.class, long.class, VLENGTH, + (bit ? -1 : 0), MODE_BROADCAST, null, + (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final Long64Mask TRUE_MASK = new Long64Mask(true); private static final Long64Mask FALSE_MASK = new Long64Mask(false); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongMaxVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongMaxVector.java index 23e9d9f3fb68eaec6ac2189d882314b6c0eb892f..2078dbec65b432adfb6dcb138dcf682180dcb0e9 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongMaxVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongMaxVector.java @@ -717,9 +717,9 @@ final class LongMaxVector extends LongVector { @ForceInline /*package-private*/ static LongMaxMask maskAll(boolean bit) { - return VectorSupport.broadcastCoerced(LongMaxMask.class, long.class, VLENGTH, - (bit ? -1 : 0), null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + return VectorSupport.fromBitsCoerced(LongMaxMask.class, long.class, VLENGTH, + (bit ? -1 : 0), MODE_BROADCAST, null, + (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final LongMaxMask TRUE_MASK = new LongMaxMask(true); private static final LongMaxMask FALSE_MASK = new LongMaxMask(false); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector.java index b48778f5ec3a3252302b3f27336fe36cd9166d08..365740c90c27878454bb8581432e33ff77f0e841 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector.java @@ -455,8 +455,8 @@ public abstract class LongVector extends AbstractVector { @ForceInline public static LongVector zero(VectorSpecies species) { LongSpecies vsp = (LongSpecies) species; - return VectorSupport.broadcastCoerced(vsp.vectorType(), long.class, species.length(), - 0, vsp, + return VectorSupport.fromBitsCoerced(vsp.vectorType(), long.class, species.length(), + 0, MODE_BROADCAST, vsp, ((bits_, s_) -> s_.rvOp(i -> bits_))); } @@ -3809,9 +3809,9 @@ public abstract class LongVector extends AbstractVector { @ForceInline final LongVector broadcastBits(long bits) { return (LongVector) - VectorSupport.broadcastCoerced( + VectorSupport.fromBitsCoerced( vectorType, long.class, laneCount, - bits, this, + bits, MODE_BROADCAST, this, (bits_, s_) -> s_.rvOp(i -> bits_)); } diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Short128Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Short128Vector.java index cd52dc003b6b8ab589785bf41769debbe6fc62d3..93bf40153a7e4cfc7110ba2fddc90c168b118956 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Short128Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Short128Vector.java @@ -741,9 +741,9 @@ final class Short128Vector extends ShortVector { @ForceInline /*package-private*/ static Short128Mask maskAll(boolean bit) { - return VectorSupport.broadcastCoerced(Short128Mask.class, short.class, VLENGTH, - (bit ? -1 : 0), null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + return VectorSupport.fromBitsCoerced(Short128Mask.class, short.class, VLENGTH, + (bit ? -1 : 0), MODE_BROADCAST, null, + (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final Short128Mask TRUE_MASK = new Short128Mask(true); private static final Short128Mask FALSE_MASK = new Short128Mask(false); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Short256Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Short256Vector.java index 66f6d409e6aed546271d27f5313c42220661209e..805f89bcdd932b1f52efe54ee879938e8f748483 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Short256Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Short256Vector.java @@ -757,9 +757,9 @@ final class Short256Vector extends ShortVector { @ForceInline /*package-private*/ static Short256Mask maskAll(boolean bit) { - return VectorSupport.broadcastCoerced(Short256Mask.class, short.class, VLENGTH, - (bit ? -1 : 0), null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + return VectorSupport.fromBitsCoerced(Short256Mask.class, short.class, VLENGTH, + (bit ? -1 : 0), MODE_BROADCAST, null, + (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final Short256Mask TRUE_MASK = new Short256Mask(true); private static final Short256Mask FALSE_MASK = new Short256Mask(false); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Short512Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Short512Vector.java index a2a8a07ddd3eddbe084fe6a8569c5645b12b941a..51d728529380e2b27013b09f889a64f776b7948e 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Short512Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Short512Vector.java @@ -789,9 +789,9 @@ final class Short512Vector extends ShortVector { @ForceInline /*package-private*/ static Short512Mask maskAll(boolean bit) { - return VectorSupport.broadcastCoerced(Short512Mask.class, short.class, VLENGTH, - (bit ? -1 : 0), null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + return VectorSupport.fromBitsCoerced(Short512Mask.class, short.class, VLENGTH, + (bit ? -1 : 0), MODE_BROADCAST, null, + (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final Short512Mask TRUE_MASK = new Short512Mask(true); private static final Short512Mask FALSE_MASK = new Short512Mask(false); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Short64Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Short64Vector.java index ff2b2d7e063f3736f9f6b674770f4ada350aa4d6..97ac8fe07cb91f51042cbcb317a4c5a4dcd86d1e 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Short64Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Short64Vector.java @@ -733,9 +733,9 @@ final class Short64Vector extends ShortVector { @ForceInline /*package-private*/ static Short64Mask maskAll(boolean bit) { - return VectorSupport.broadcastCoerced(Short64Mask.class, short.class, VLENGTH, - (bit ? -1 : 0), null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + return VectorSupport.fromBitsCoerced(Short64Mask.class, short.class, VLENGTH, + (bit ? -1 : 0), MODE_BROADCAST, null, + (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final Short64Mask TRUE_MASK = new Short64Mask(true); private static final Short64Mask FALSE_MASK = new Short64Mask(false); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortMaxVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortMaxVector.java index 7aa01264a738deb58b1137119745700289a8fcd6..c0ec9ee8b4ecccc5110ef2aa9710f20c9326e1a2 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortMaxVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortMaxVector.java @@ -727,9 +727,9 @@ final class ShortMaxVector extends ShortVector { @ForceInline /*package-private*/ static ShortMaxMask maskAll(boolean bit) { - return VectorSupport.broadcastCoerced(ShortMaxMask.class, short.class, VLENGTH, - (bit ? -1 : 0), null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + return VectorSupport.fromBitsCoerced(ShortMaxMask.class, short.class, VLENGTH, + (bit ? -1 : 0), MODE_BROADCAST, null, + (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final ShortMaxMask TRUE_MASK = new ShortMaxMask(true); private static final ShortMaxMask FALSE_MASK = new ShortMaxMask(false); diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java index e1cada48f17ac18350bd8e015133628a646a57d2..d527500bb1a48713eb2b91f57ce7a71870fffba2 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java @@ -455,8 +455,8 @@ public abstract class ShortVector extends AbstractVector { @ForceInline public static ShortVector zero(VectorSpecies species) { ShortSpecies vsp = (ShortSpecies) species; - return VectorSupport.broadcastCoerced(vsp.vectorType(), short.class, species.length(), - 0, vsp, + return VectorSupport.fromBitsCoerced(vsp.vectorType(), short.class, species.length(), + 0, MODE_BROADCAST, vsp, ((bits_, s_) -> s_.rvOp(i -> bits_))); } @@ -4143,9 +4143,9 @@ public abstract class ShortVector extends AbstractVector { @ForceInline final ShortVector broadcastBits(long bits) { return (ShortVector) - VectorSupport.broadcastCoerced( + VectorSupport.fromBitsCoerced( vectorType, short.class, laneCount, - bits, this, + bits, MODE_BROADCAST, this, (bits_, s_) -> s_.rvOp(i -> bits_)); } diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorMask.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorMask.java index b57a2abbb1f1600728cbcf4db048ab295ad2a447..506535d030f99b202dccd69475f32c7e99ae837a 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorMask.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorMask.java @@ -237,26 +237,25 @@ public abstract class VectorMask extends jdk.internal.vm.vector.VectorSupport */ @ForceInline public static VectorMask fromLong(VectorSpecies species, long bits) { - AbstractSpecies vspecies = (AbstractSpecies) species; - int laneCount = vspecies.laneCount(); - if (laneCount < Long.SIZE) { - int extraSignBits = Long.SIZE - laneCount; - bits <<= extraSignBits; - bits >>= extraSignBits; - } - if (bits == (bits >> 1)) { - // Special case. - assert(bits == 0 || bits == -1); - return vspecies.maskAll(bits != 0); - } - // FIXME: Intrinsify this. - long shifted = bits; - boolean[] a = new boolean[laneCount]; - for (int i = 0; i < a.length; i++) { - a[i] = ((shifted & 1) != 0); - shifted >>= 1; // replicate sign bit - } - return fromValues(vspecies, a); + AbstractSpecies vsp = (AbstractSpecies) species; + bits = bits & (0xFFFFFFFFFFFFFFFFL >>> (64 - vsp.laneCount())); + return VectorSupport.fromBitsCoerced(vsp.maskType(), vsp.elementType(), vsp.laneCount(), bits, + VectorSupport.MODE_BITS_COERCED_LONG_TO_MASK, vsp, + (m, s) -> { + if (m == (m >> 1)) { + // Special case. + assert(m == 0 || m == -1); + return s.maskAll(m != 0); + } + + long shifted = m; + boolean[] a = new boolean[s.laneCount()]; + for (int i = 0; i < a.length; i++) { + a[i] = ((shifted & 1) != 0); + shifted >>= 1; // replicate sign bit + } + return fromValues(s, a); + }); } /** diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template index 45c2cf9267c798f6a4f6d33b748ac7a0d8b33ce6..ae12e5fecffb767c8cf29f7c12604aafd0341d8d 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template @@ -470,12 +470,12 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { public static $abstractvectortype$ zero(VectorSpecies<$Boxtype$> species) { $Type$Species vsp = ($Type$Species) species; #if[FP] - return VectorSupport.broadcastCoerced(vsp.vectorType(), $type$.class, species.length(), - toBits(0.0f), vsp, + return VectorSupport.fromBitsCoerced(vsp.vectorType(), $type$.class, species.length(), + toBits(0.0f), MODE_BROADCAST, vsp, ((bits_, s_) -> s_.rvOp(i -> bits_))); #else[FP] - return VectorSupport.broadcastCoerced(vsp.vectorType(), $type$.class, species.length(), - 0, vsp, + return VectorSupport.fromBitsCoerced(vsp.vectorType(), $type$.class, species.length(), + 0, MODE_BROADCAST, vsp, ((bits_, s_) -> s_.rvOp(i -> bits_))); #end[FP] } @@ -5327,9 +5327,9 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { @ForceInline final $abstractvectortype$ broadcastBits(long bits) { return ($abstractvectortype$) - VectorSupport.broadcastCoerced( + VectorSupport.fromBitsCoerced( vectorType, $type$.class, laneCount, - bits, this, + bits, MODE_BROADCAST, this, (bits_, s_) -> s_.rvOp(i -> bits_)); } diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-VectorBits.java.template b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-VectorBits.java.template index df15c85fcccc301c668efa9d2dde61da4c11b6a3..2f1004f645039436642988e28d3b09b4da02044a 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-VectorBits.java.template +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-VectorBits.java.template @@ -1000,9 +1000,9 @@ final class $vectortype$ extends $abstractvectortype$ { @ForceInline /*package-private*/ static $masktype$ maskAll(boolean bit) { - return VectorSupport.broadcastCoerced($masktype$.class, $bitstype$.class, VLENGTH, - (bit ? -1 : 0), null, - (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); + return VectorSupport.fromBitsCoerced($masktype$.class, $bitstype$.class, VLENGTH, + (bit ? -1 : 0), MODE_BROADCAST, null, + (v, __) -> (v != 0 ? TRUE_MASK : FALSE_MASK)); } private static final $masktype$ TRUE_MASK = new $masktype$(true); private static final $masktype$ FALSE_MASK = new $masktype$(false); diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractTerminal.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractTerminal.java index e92233c7b4f47f38f9a62a44b0ef200a0019d3c3..8a464a6726565253e566669032766edcc0b0fd45 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractTerminal.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractTerminal.java @@ -55,7 +55,7 @@ public abstract class AbstractTerminal implements Terminal { public AbstractTerminal(String name, String type, Charset encoding, SignalHandler signalHandler) throws IOException { this.name = name; this.type = type != null ? type : "ansi"; - this.encoding = encoding != null ? encoding : Charset.defaultCharset(); + this.encoding = encoding != null ? encoding : System.out.charset(); for (Signal signal : Signal.values()) { handlers.put(signal, signalHandler); } diff --git a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java index e24d53425a8e99c2de0f48e16b67ff285b3a078b..8758b99e18e1403bfa3967c0ac099352f998cb16 100644 --- a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java +++ b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java @@ -834,9 +834,9 @@ public class Main { } // Only used when -verbose provided - StringBuffer sb = null; + StringBuilder sb = null; if (verbose != null) { - sb = new StringBuffer(); + sb = new StringBuilder(); boolean inManifest = ((man.getAttributes(name) != null) || (man.getAttributes("./"+name) != null) || diff --git a/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java b/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java index bcc4bb32f066af93b2951529842e234a37c4bddc..8686210b209bdc8c6ddb56d5633a76cd0c99076d 100644 --- a/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java +++ b/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java @@ -34,12 +34,21 @@ import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import jdk.internal.module.ModulePath; import jdk.internal.module.ModuleResolution; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; /** * Parser for GNU Style Options. */ class GNUStyleOptions { + // Valid --date range + static final ZonedDateTime DATE_MIN = ZonedDateTime.parse("1980-01-01T00:00:02Z"); + static final ZonedDateTime DATE_MAX = ZonedDateTime.parse("2099-12-31T23:59:59Z"); + static class BadArgs extends Exception { static final long serialVersionUID = 0L; @@ -188,6 +197,20 @@ class GNUStyleOptions { jartool.flag0 = true; } }, + new Option(true, OptionType.CREATE_UPDATE_INDEX, "--date") { + void process(Main jartool, String opt, String arg) throws BadArgs { + try { + ZonedDateTime date = ZonedDateTime.parse(arg, DateTimeFormatter.ISO_ZONED_DATE_TIME) + .withZoneSameInstant(ZoneOffset.UTC); + if (date.isBefore(DATE_MIN) || date.isAfter(DATE_MAX)) { + throw new BadArgs("error.date.out.of.range", arg); + } + jartool.date = date.toLocalDateTime(); + } catch (DateTimeParseException x) { + throw new BadArgs("error.date.notvalid", arg); + } + } + }, // Hidden options new Option(false, OptionType.OTHER, "-P") { diff --git a/src/jdk.jartool/share/classes/sun/tools/jar/Main.java b/src/jdk.jartool/share/classes/sun/tools/jar/Main.java index e79b858d9901795b34c30ad677041a20e5fc4c19..3436c01928b98c3957b99c29705c56b712eaefa2 100644 --- a/src/jdk.jartool/share/classes/sun/tools/jar/Main.java +++ b/src/jdk.jartool/share/classes/sun/tools/jar/Main.java @@ -44,6 +44,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; +import java.nio.file.attribute.FileTime; import java.text.MessageFormat; import java.util.*; import java.util.function.Consumer; @@ -59,6 +60,7 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; +import java.util.concurrent.TimeUnit; import jdk.internal.module.Checks; import jdk.internal.module.ModuleHashes; import jdk.internal.module.ModuleHashesBuilder; @@ -67,6 +69,8 @@ import jdk.internal.module.ModuleInfoExtender; import jdk.internal.module.ModuleResolution; import jdk.internal.module.ModuleTarget; import jdk.internal.util.jar.JarIndex; +import java.time.LocalDateTime; +import java.time.ZoneOffset; import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; import static java.util.jar.JarFile.MANIFEST_NAME; @@ -120,7 +124,7 @@ public class Main { Set entries = new LinkedHashSet<>(); // module-info.class entries need to be added/updated. - Map moduleInfos = new HashMap<>(); + Map moduleInfos = new HashMap<>(); // A paths Set for each version, where each Set contains directories // specified by the "-C" operation. @@ -173,6 +177,9 @@ public class Main { static final int VERSIONS_DIR_LENGTH = VERSIONS_DIR.length(); private static ResourceBundle rsrc; + /* Date option for entry timestamps resolved to UTC Local time */ + LocalDateTime date; + /** * If true, maintain compatibility with JDK releases prior to 6.0 by * timestamping extracted files with the time at which they are extracted. @@ -806,7 +813,10 @@ public class Main { if (f.isFile()) { Entry e = new Entry(f, name, false); if (isModuleInfoEntry(name)) { - moduleInfos.putIfAbsent(name, Files.readAllBytes(f.toPath())); + Path path = f.toPath(); + byte[] fileContent = Files.readAllBytes(path); + ModuleInfoEntry mie = new StreamedModuleInfoEntry(name, fileContent, Files.getLastModifiedTime(path)); + moduleInfos.putIfAbsent(name, mie); if (uflag) { entryMap.put(name, e); } @@ -858,12 +868,12 @@ public class Main { output(getMsg("out.added.manifest")); } ZipEntry e = new ZipEntry(MANIFEST_DIR); - e.setTime(System.currentTimeMillis()); + setZipEntryTime(e); e.setSize(0); e.setCrc(0); zos.putNextEntry(e); e = new ZipEntry(MANIFEST_NAME); - e.setTime(System.currentTimeMillis()); + setZipEntryTime(e); if (flag0) { crc32Manifest(e, manifest); } @@ -907,7 +917,7 @@ public class Main { */ boolean update(InputStream in, OutputStream out, InputStream newManifest, - Map moduleInfos, + Map moduleInfos, JarIndex jarIndex) throws IOException { ZipInputStream zis = new ZipInputStream(in); @@ -956,14 +966,14 @@ public class Main { return false; } } else if (moduleInfos != null && isModuleInfoEntry) { - moduleInfos.putIfAbsent(name, zis.readAllBytes()); + moduleInfos.putIfAbsent(name, new StreamedModuleInfoEntry(name, zis.readAllBytes(), e.getLastModifiedTime())); } else { boolean isDir = e.isDirectory(); if (!entryMap.containsKey(name)) { // copy the old stuff // do our own compression ZipEntry e2 = new ZipEntry(name); e2.setMethod(e.getMethod()); - e2.setTime(e.getTime()); + setZipEntryTime(e2, e.getTime()); e2.setComment(e.getComment()); e2.setExtra(e.getExtra()); if (e.getMethod() == ZipEntry.STORED) { @@ -1029,7 +1039,7 @@ public class Main { throws IOException { ZipEntry e = new ZipEntry(INDEX_NAME); - e.setTime(System.currentTimeMillis()); + setZipEntryTime(e); if (flag0) { CRC32OutputStream os = new CRC32OutputStream(); index.write(os); @@ -1040,15 +1050,21 @@ public class Main { zos.closeEntry(); } - private void updateModuleInfo(Map moduleInfos, ZipOutputStream zos) + private void updateModuleInfo(Map moduleInfos, ZipOutputStream zos) throws IOException { String fmt = uflag ? "out.update.module-info": "out.added.module-info"; - for (Map.Entry mi : moduleInfos.entrySet()) { + for (Map.Entry mi : moduleInfos.entrySet()) { String name = mi.getKey(); - byte[] bytes = mi.getValue(); + ModuleInfoEntry mie = mi.getValue(); + byte[] bytes = mie.readAllBytes(); ZipEntry e = new ZipEntry(name); - e.setTime(System.currentTimeMillis()); + FileTime lastModified = mie.getLastModifiedTime(); + if (lastModified != null) { + setZipEntryTime(e, lastModified.toMillis()); + } else { + setZipEntryTime(e); + } if (flag0) { crc32ModuleInfo(e, bytes); } @@ -1073,7 +1089,7 @@ public class Main { addMultiRelease(m); } ZipEntry e = new ZipEntry(MANIFEST_NAME); - e.setTime(System.currentTimeMillis()); + setZipEntryTime(e); if (flag0) { crc32Manifest(e, m); } @@ -1194,7 +1210,7 @@ public class Main { out.print(formatMsg("out.adding", name)); } ZipEntry e = new ZipEntry(name); - e.setTime(file.lastModified()); + setZipEntryTime(e, file.lastModified()); if (size == 0) { e.setMethod(ZipEntry.STORED); e.setSize(0); @@ -1743,12 +1759,23 @@ public class Main { /** * Associates a module descriptor's zip entry name along with its - * bytes and an optional URI. Used when describing modules. + * bytes and an optional URI. */ interface ModuleInfoEntry { - String name(); - Optional uriString(); - InputStream bytes() throws IOException; + String name(); + Optional uriString(); + InputStream bytes() throws IOException; + /** + * @return Returns the last modified time of the module-info.class. + * Returns null if the last modified time is unknown or cannot be + * determined. + */ + FileTime getLastModifiedTime(); + default byte[] readAllBytes() throws IOException { + try (InputStream is = bytes()) { + return is.readAllBytes(); + } + } } static class ZipFileModuleInfoEntry implements ModuleInfoEntry { @@ -1762,6 +1789,12 @@ public class Main { @Override public InputStream bytes() throws IOException { return zipFile.getInputStream(entry); } + + @Override + public FileTime getLastModifiedTime() { + return entry.getLastModifiedTime(); + } + /** Returns an optional containing the effective URI. */ @Override public Optional uriString() { String uri = (Paths.get(zipFile.getName())).toUri().toString(); @@ -1773,14 +1806,28 @@ public class Main { static class StreamedModuleInfoEntry implements ModuleInfoEntry { private final String name; private final byte[] bytes; - StreamedModuleInfoEntry(String name, byte[] bytes) { + private final FileTime lastModifiedTime; + + StreamedModuleInfoEntry(String name, byte[] bytes, FileTime lastModifiedTime) { this.name = name; this.bytes = bytes; + this.lastModifiedTime = lastModifiedTime; } @Override public String name() { return name; } @Override public InputStream bytes() throws IOException { return new ByteArrayInputStream(bytes); } + + @Override + public byte[] readAllBytes() throws IOException { + return bytes; + } + + @Override + public FileTime getLastModifiedTime() { + return lastModifiedTime; + } + /** Returns an empty optional. */ @Override public Optional uriString() { return Optional.empty(); // no URI can be derived @@ -1832,7 +1879,7 @@ public class Main { while ((e = zis.getNextEntry()) != null) { String ename = e.getName(); if (isModuleInfoEntry(ename)) { - infos.add(new StreamedModuleInfoEntry(ename, zis.readAllBytes())); + infos.add(new StreamedModuleInfoEntry(ename, zis.readAllBytes(), e.getLastModifiedTime())); } } } @@ -2045,14 +2092,14 @@ public class Main { return (classname.replace('.', '/')) + ".class"; } - private boolean checkModuleInfo(byte[] moduleInfoBytes, Set entries) + private boolean checkModuleInfo(ModuleInfoEntry moduleInfoEntry, Set entries) throws IOException { boolean ok = true; - if (moduleInfoBytes != null) { // no root module-info.class if null + if (moduleInfoEntry != null) { // no root module-info.class if null try { // ModuleDescriptor.read() checks open/exported pkgs vs packages - ModuleDescriptor md = ModuleDescriptor.read(ByteBuffer.wrap(moduleInfoBytes)); + ModuleDescriptor md = ModuleDescriptor.read(moduleInfoEntry.bytes()); // A module must have the implementation class of the services it 'provides'. if (md.provides().stream().map(Provides::providers).flatMap(List::stream) .filter(p -> !entries.contains(toBinaryName(p))) @@ -2070,15 +2117,19 @@ public class Main { /** * Adds extended modules attributes to the given module-info's. The given - * Map values are updated in-place. Returns false if an error occurs. + * Map values are updated in-place. */ - private void addExtendedModuleAttributes(Map moduleInfos, + private void addExtendedModuleAttributes(Map moduleInfos, Set packages) throws IOException { - for (Map.Entry e: moduleInfos.entrySet()) { - ModuleDescriptor md = ModuleDescriptor.read(ByteBuffer.wrap(e.getValue())); - e.setValue(extendedInfoBytes(md, e.getValue(), packages)); + for (Map.Entry e: moduleInfos.entrySet()) { + ModuleInfoEntry mie = e.getValue(); + byte[] bytes = mie.readAllBytes(); + ModuleDescriptor md = ModuleDescriptor.read(ByteBuffer.wrap(bytes)); + byte[] extended = extendedInfoBytes(md, bytes, packages); + // replace the entry value with the extended bytes + e.setValue(new StreamedModuleInfoEntry(mie.name(), extended, mie.getLastModifiedTime())); } } @@ -2273,4 +2324,18 @@ public class Main { static Comparator ENTRY_COMPARATOR = Comparator.comparing(ZipEntry::getName, ENTRYNAME_COMPARATOR); + // Set the ZipEntry dostime using date if specified otherwise the current time + private void setZipEntryTime(ZipEntry e) { + setZipEntryTime(e, System.currentTimeMillis()); + } + + // Set the ZipEntry dostime using the date if specified + // otherwise the original time + private void setZipEntryTime(ZipEntry e, long origTime) { + if (date != null) { + e.setTimeLocal(date); + } else { + e.setTime(origTime); + } + } } diff --git a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties index 61b9ecc241299d08ae9754982b142b4613ddeafa..87bff6891029f7f05293c15fafc6bd5e8c76b0b3 100644 --- a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties +++ b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -82,6 +82,10 @@ error.release.value.toosmall=\ release {0} not valid, must be >= 9 error.release.unexpected.versioned.entry=\ unexpected versioned entry {0} for release {1} +error.date.notvalid=\ + date {0} is not a valid ISO-8601 extended offset date-time with optional time-zone +error.date.out.of.range=\ + date {0} is not within the valid range 1980-01-01T00:00:02Z to 2099-12-31T23:59:59Z error.validator.jarfile.exception=\ can not validate {0}: {1} error.validator.jarfile.invalid=\ @@ -290,6 +294,10 @@ main.help.opt.create.update.index=\ \ Operation modifiers valid only in create, update, and generate-index mode:\n main.help.opt.create.update.index.no-compress=\ \ -0, --no-compress Store only; use no ZIP compression +main.help.opt.create.update.index.date=\ +\ --date=TIMESTAMP The timestamp in ISO-8601 extended offset date-time with\n\ +\ optional time-zone format, to use for the timestamps of\n\ +\ entries, e.g. "2022-02-12T12:30:00-05:00" main.help.opt.other=\ \ Other options:\n main.help.opt.other.help=\ diff --git a/src/jdk.jartool/share/man/jar.1 b/src/jdk.jartool/share/man/jar.1 index 4a8c8f4ae6697fdbd7dadafc2ad4ff685e389ea9..fd134fe1467b0498f596924f082999597e96bd55 100644 --- a/src/jdk.jartool/share/man/jar.1 +++ b/src/jdk.jartool/share/man/jar.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JAR" "1" "2021" "JDK 18\-ea" "JDK Commands" +.TH "JAR" "1" "2022" "JDK 19\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jartool/share/man/jarsigner.1 b/src/jdk.jartool/share/man/jarsigner.1 index 592a64ed8360dbcbedf35f801f8c518dec0b3f92..0d51b7040afa18f570c5d2921dfe4a3669f2d440 100644 --- a/src/jdk.jartool/share/man/jarsigner.1 +++ b/src/jdk.jartool/share/man/jarsigner.1 @@ -22,7 +22,7 @@ .\"t .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JARSIGNER" "1" "2021" "JDK 18\-ea" "JDK Commands" +.TH "JARSIGNER" "1" "2022" "JDK 19\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/doclet/package-info.java b/src/jdk.javadoc/share/classes/jdk/javadoc/doclet/package-info.java index 2e895024b93db50d4d35fbdef547fb987a4a5678..3658ed74d85febdcef6be556e1a0b49925ad7c3f 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/doclet/package-info.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/doclet/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,9 +51,9 @@ * The invocation is defined by the interface {@link jdk.javadoc.doclet.Doclet} * -- the {@link jdk.javadoc.doclet.Doclet#run(DocletEnvironment) run} interface * method, defines the entry point. - *
    - *    public boolean run(DocletEnvironment environment)
    - * 
    + * {@snippet id="entry-point" lang=java : + * public boolean run(DocletEnvironment environment) // @highlight substring="run" + * } * The {@link jdk.javadoc.doclet.DocletEnvironment} instance holds the * environment that the doclet will be initialized with. From this environment * all other information can be extracted, in the form of @@ -185,120 +185,147 @@ * * The following is an example doclet that displays information of a class * and its members, supporting an option. - *
    - * // note imports deleted for clarity
    + *
    + * {@snippet lang=java id="Example.java" :
    + * // @replace region=imports replacement=" // Note: imports deleted for clarity"
    + * import com.sun.source.doctree.DocCommentTree;
    + * import com.sun.source.util.DocTrees;
    + * import jdk.javadoc.doclet.Doclet;
    + * import jdk.javadoc.doclet.DocletEnvironment;
    + * import jdk.javadoc.doclet.Reporter;
    + *
    + * import javax.lang.model.SourceVersion;
    + * import javax.lang.model.element.Element;
    + * import javax.lang.model.element.TypeElement;
    + * import javax.lang.model.util.ElementFilter;
    + * import javax.tools.Diagnostic.Kind;
    + * import java.io.IOException;
    + * import java.io.PrintWriter;
    + * import java.util.List;
    + * import java.util.Locale;
    + * import java.util.Set;
    + * // @end
    + *
    + *
      * public class Example implements Doclet {
    - *    Reporter reporter;
    - *    @Override
    - *    public void init(Locale locale, Reporter reporter) {
    - *        reporter.print(Kind.NOTE, "Doclet using locale: " + locale);
    - *        this.reporter = reporter;
    - *    }
    - *
    - *    public void printElement(DocTrees trees, Element e) {
    - *        DocCommentTree docCommentTree = trees.getDocCommentTree(e);
    - *        if (docCommentTree != null) {
    - *            System.out.println("Element (" + e.getKind() + ": "
    - *                    + e + ") has the following comments:");
    - *            System.out.println("Entire body: " + docCommentTree.getFullBody());
    - *            System.out.println("Block tags: " + docCommentTree.getBlockTags());
    - *        }
    - *    }
    - *
    - *    @Override
    - *    public boolean run(DocletEnvironment docEnv) {
    - *        reporter.print(Kind.NOTE, "overviewfile: " + overviewfile);
    - *        // get the DocTrees utility class to access document comments
    - *        DocTrees docTrees = docEnv.getDocTrees();
    - *
    - *        // location of an element in the same directory as overview.html
    - *        try {
    - *            Element e = ElementFilter.typesIn(docEnv.getSpecifiedElements()).iterator().next();
    - *            DocCommentTree docCommentTree
    - *                    = docTrees.getDocCommentTree(e, overviewfile);
    - *            if (docCommentTree != null) {
    - *                System.out.println("Overview html: " + docCommentTree.getFullBody());
    - *            }
    - *        } catch (IOException missing) {
    - *            reporter.print(Kind.ERROR, "No overview.html found.");
    - *        }
    - *
    - *        for (TypeElement t : ElementFilter.typesIn(docEnv.getIncludedElements())) {
    - *            System.out.println(t.getKind() + ":" + t);
    - *            for (Element e : t.getEnclosedElements()) {
    - *                printElement(docTrees, e);
    - *            }
    - *        }
    - *        return true;
    - *    }
    - *
    - *    @Override
    - *    public String getName() {
    - *        return "Example";
    - *    }
    - *
    - *    private String overviewfile;
    - *
    - *    @Override
    - *    public Set<? extends Option> getSupportedOptions() {
    - *        Option[] options = {
    - *            new Option() {
    - *                private final List<String> someOption = Arrays.asList(
    - *                        "-overviewfile",
    - *                        "--overview-file",
    - *                        "-o"
    - *                );
    - *
    - *                @Override
    - *                public int getArgumentCount() {
    - *                    return 1;
    - *                }
    - *
    - *                @Override
    - *                public String getDescription() {
    - *                    return "an option with aliases";
    - *                }
    - *
    - *                @Override
    - *                public Option.Kind getKind() {
    - *                    return Option.Kind.STANDARD;
    - *                }
    - *
    - *                @Override
    - *                public List<String> getNames() {
    - *                    return someOption;
    - *                }
    - *
    - *                @Override
    - *                public String getParameters() {
    - *                    return "file";
    - *                }
    - *
    - *                @Override
    - *                public boolean process(String opt, List<String> arguments) {
    - *                    overviewfile = arguments.get(0);
    - *                    return true;
    - *                }
    - *            }
    - *        };
    - *        return new HashSet<>(Arrays.asList(options));
    - *    }
    - *
    - *    @Override
    - *    public SourceVersion getSupportedSourceVersion() {
    - *        // support the latest release
    - *        return SourceVersion.latest();
    - *    }
    + *     private Reporter reporter;
    + *     private PrintWriter stdout;
    + *
    + *     @Override
    + *     public void init(Locale locale, Reporter reporter) {
    + *         reporter.print(Kind.NOTE, "Doclet using locale: " + locale);
    + *         this.reporter = reporter;
    + *         stdout = reporter.getStandardWriter();
    + *     }
    + *
    + *     public void printElement(DocTrees trees, Element e) {
    + *         DocCommentTree docCommentTree = trees.getDocCommentTree(e);
    + *         if (docCommentTree != null) {
    + *             stdout.println("Element (" + e.getKind() + ": "
    + *                     + e + ") has the following comments:");
    + *             stdout.println("Entire body: " + docCommentTree.getFullBody());
    + *             stdout.println("Block tags: " + docCommentTree.getBlockTags());
    + *         }
    + *     }
    + *
    + *     @Override
    + *     public boolean run(DocletEnvironment docEnv) {
    + *         reporter.print(Kind.NOTE, "overviewFile: " + overviewFile);
    + *
    + *         // get the DocTrees utility class to access document comments
    + *         DocTrees docTrees = docEnv.getDocTrees();
    + *
    + *         // location of an element in the same directory as overview.html
    + *         try {
    + *             Element e = ElementFilter.typesIn(docEnv.getSpecifiedElements()).iterator().next();
    + *             DocCommentTree docCommentTree
    + *                     = docTrees.getDocCommentTree(e, overviewFile);
    + *             if (docCommentTree != null) {
    + *                 stdout.println("Overview html: " + docCommentTree.getFullBody());
    + *             }
    + *         } catch (IOException missing) {
    + *             reporter.print(Kind.ERROR, "No overview.html found.");
    + *         }
    + *
    + *         for (TypeElement t : ElementFilter.typesIn(docEnv.getIncludedElements())) {
    + *             stdout.println(t.getKind() + ":" + t);
    + *             for (Element e : t.getEnclosedElements()) {
    + *                 printElement(docTrees, e);
    + *             }
    + *         }
    + *         return true;
    + *     }
    + *
    + *     @Override
    + *     public String getName() {
    + *         return "Example";
    + *     }
    + *
    + *     private String overviewFile;
    + *
    + *     @Override
    + *     public Set getSupportedOptions() {
    + *         Option[] options = {
    + *             new Option() {
    + *                 private final List someOption = List.of(
    + *                         "--overview-file",
    + *                         "-overviewfile",
    + *                         "-o"
    + *                 );
    + *
    + *                 @Override
    + *                 public int getArgumentCount() {
    + *                     return 1;
    + *                 }
    + *
    + *                 @Override
    + *                 public String getDescription() {
    + *                     return "an option with aliases";
    + *                 }
    + *
    + *                 @Override
    + *                 public Option.Kind getKind() {
    + *                     return Option.Kind.STANDARD;
    + *                 }
    + *
    + *                 @Override
    + *                 public List getNames() {
    + *                     return someOption;
    + *                 }
    + *
    + *                 @Override
    + *                 public String getParameters() {
    + *                     return "file";
    + *                 }
    + *
    + *                 @Override
    + *                 public boolean process(String opt, List arguments) {
    + *                     overviewFile = arguments.get(0);
    + *                     return true;
    + *                 }
    + *             }
    + *         };
    + *
    + *         return Set.of(options);
    + *     }
    + *
    + *     @Override
    + *     public SourceVersion getSupportedSourceVersion() {
    + *         // support the latest release
    + *         return SourceVersion.latest();
    + *     }
    + * }
      * }
    - * 
    + * *

    * This doclet can be invoked with a command line, such as: - *

    - *     javadoc -doclet Example \
    - *       -overviewfile overview.html \
    - *       -sourcepath source-location \
    - *       source-location/Example.java
    - * 
    + * {@snippet id="run-doclet": + * javadoc -docletpath doclet-classes \ // @highlight substring="doclet-classes " type=italic + * -doclet Example \ + * --overview-file overview.html \ + * --source-path source-location \ // @highlight region substring="source-location" type=italic + * source-location/Example.java // @end + * } * *

    Migration Guide

    * diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java index 76709124ff2659d456136dbb14b46e71a3d30c30..1a73541288693b8cb75ec31d689e1e2652d1704f 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java @@ -36,6 +36,7 @@ import java.util.ListIterator; import java.util.Locale; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -896,7 +897,7 @@ public class HtmlDocletWriter { * Return the link for the given member. * * @param context the id of the context where the link will be printed. - * @param typeElement the typeElement that we should link to. This is not + * @param typeElement the typeElement that we should link to. This is * not necessarily the type containing element since we may be * inheriting comments. * @param element the member being linked to. @@ -912,7 +913,7 @@ public class HtmlDocletWriter { * Return the link for the given member. * * @param context the id of the context where the link will be printed. - * @param typeElement the typeElement that we should link to. This is not + * @param typeElement the typeElement that we should link to. This is * not necessarily the type containing element since we may be * inheriting comments. * @param element the member being linked to. @@ -929,7 +930,7 @@ public class HtmlDocletWriter { * Return the link for the given member. * * @param context the id of the context where the link will be printed. - * @param typeElement the typeElement that we should link to. This is not + * @param typeElement the typeElement that we should link to. This is * not necessarily the type containing element since we may be * inheriting comments. * @param element the member being linked to. @@ -945,7 +946,7 @@ public class HtmlDocletWriter { * Return the link for the given member. * * @param context the id of the context where the link will be printed. - * @param typeElement the typeElement that we should link to. This is not + * @param typeElement the typeElement that we should link to. This is * not necessarily the type containing element since we may be * inheriting comments. * @param element the member being linked to. @@ -1063,7 +1064,8 @@ public class HtmlDocletWriter { "doclet.see.class_or_package_not_found", "@" + tagName, seeText); - return (labelContent.isEmpty() ? text: labelContent); + return invalidTagOutput(resources.getText("doclet.tag.invalid", tagName), + Optional.of(labelContent.isEmpty() ? text: labelContent)); } } } else if (refMemName == null) { @@ -1407,14 +1409,6 @@ public class HtmlDocletWriter { return false; } - boolean isAllWhiteSpace(String body) { - for (int i = 0 ; i < body.length(); i++) { - if (!Character.isWhitespace(body.charAt(i))) - return false; - } - return true; - } - // Notify the next DocTree handler to take necessary action private boolean commentRemoved = false; @@ -1505,7 +1499,7 @@ public class HtmlDocletWriter { // Ignore any trailing whitespace OR whitespace after removed html comment if ((isLastNode || commentRemoved) && tag.getKind() == TEXT - && isAllWhiteSpace(ch.getText(tag))) + && ch.getText(tag).isBlank()) continue; // Ignore any leading html comments @@ -1622,13 +1616,18 @@ public class HtmlDocletWriter { DocTreePath dtp = ch.getDocTreePath(node); if (dtp != null) { String body = node.getBody(); - if (body.matches("(?i)\\{@[a-z]+.*")) { - messages.warning(dtp,"doclet.tag.invalid_usage", body); - } else { + Matcher m = Pattern.compile("(?i)\\{@([a-z]+).*").matcher(body); + String tagName = m.matches() ? m.group(1) : null; + if (tagName == null) { messages.warning(dtp, "doclet.tag.invalid_input", body); + result.add(invalidTagOutput(resources.getText("doclet.tag.invalid_input", body), + Optional.empty())); + } else { + messages.warning(dtp, "doclet.tag.invalid_usage", body); + result.add(invalidTagOutput(resources.getText("doclet.tag.invalid", tagName), + Optional.of(Text.of(body)))); } } - result.add(Text.of(node.toString())); return false; } @@ -1782,6 +1781,24 @@ public class HtmlDocletWriter { && currentPageElement != utils.getEnclosingTypeElement(element)); } + /** + * Returns the output for an invalid tag. The returned content uses special styling to + * highlight the problem. Depending on the presence of the {@code detail} string the method + * returns a plain text span or an expandable component. + * + * @param summary the single-line summary message + * @param detail the optional detail message which may contain preformatted text + * @return the output + */ + protected Content invalidTagOutput(String summary, Optional detail) { + if (detail.isEmpty() || detail.get().isEmpty()) { + return HtmlTree.SPAN(HtmlStyle.invalidTag, Text.of(summary)); + } + return new HtmlTree(TagName.DETAILS).addStyle(HtmlStyle.invalidTag) + .add(new HtmlTree(TagName.SUMMARY).add(Text.of(summary))) + .add(new HtmlTree(TagName.PRE).add(detail.get())); + } + /** * Returns true if element lives in the same package as the type or package * element of this writer. diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java index e2d96f0f693783524edb4412b736fa3b0f98e0ce..576597ae86e0c69fd65d59344d63b4728cfbe0c0 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java @@ -29,6 +29,7 @@ import java.util.ArrayList; import java.util.EnumSet; import java.util.HashSet; import java.util.List; +import java.util.Optional; import java.util.Set; import javax.lang.model.element.Element; @@ -401,6 +402,7 @@ public class TagletWriterImpl extends TagletWriter { Element e = null; String t = null; boolean linkEncountered = false; + boolean markupEncountered = false; Set classes = new HashSet<>(); for (Style s : styles) { if (s instanceof Style.Name n) { @@ -414,6 +416,8 @@ public class TagletWriterImpl extends TagletWriter { // TODO: diagnostic output } } else if (s instanceof Style.Markup) { + markupEncountered = true; + break; } else { // TODO: transform this if...else into an exhaustive // switch over the sealed Style hierarchy when "Pattern @@ -423,7 +427,9 @@ public class TagletWriterImpl extends TagletWriter { } } Content c; - if (linkEncountered) { + if (markupEncountered) { + return; + } else if (linkEncountered) { assert e != null; String line = sequence.toString(); String strippedLine = line.strip(); @@ -438,7 +444,7 @@ public class TagletWriterImpl extends TagletWriter { c = new ContentBuilder(whitespace, htmlWriter.linkToContent(element, e, t, strippedLine)); // We don't care about trailing whitespace. } else { - c = HtmlTree.SPAN(Text.of(utils.normalizeNewlines(sequence))); + c = HtmlTree.SPAN(Text.of(text)); classes.forEach(((HtmlTree) c)::addStyle); } code.add(c); @@ -531,6 +537,14 @@ public class TagletWriterImpl extends TagletWriter { : Text.of(constantVal); } + @Override + protected Content invalidTagOutput(String summary, Optional detail) { + return htmlWriter.invalidTagOutput(summary, + detail.isEmpty() || detail.get().isEmpty() + ? Optional.empty() + : Optional.of(Text.of(utils.normalizeNewlines(detail.get())))); + } + @Override public Content commentTagsToOutput(DocTree holder, List tags) { return commentTagsToOutput(null, holder, tags, false); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java index 1d22926b8162ef6009c34e4b70dc38a49386c768..ad74b81eee5af286d90228f5179dff267232f2cc 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java @@ -907,6 +907,11 @@ public enum HtmlStyle { */ inheritedList, + /** + * The class of an element that acts as a notification for an invalid tag. + */ + invalidTag, + /** * The class of a {@code p} element containing legal copy in the page footer. */ diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/TagName.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/TagName.java index 34655300b30b6dfbe154ac5c8568b91511b085c8..59aad16bf2d88f28fa15d0836466238f2d2255bf 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/TagName.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/TagName.java @@ -47,6 +47,7 @@ public enum TagName { CAPTION, CODE, DD, + DETAILS, DIV, DL, DT, @@ -83,6 +84,7 @@ public enum TagName { SPAN, STRONG, SUB, + SUMMARY, SUP, TABLE, TBODY, diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties index 130f3e55740a8b77c23a2dc56814352e984e3fa6..8a511b8ca4fa884adb72ee677af6d9e59d831629 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties @@ -106,6 +106,7 @@ doclet.see.class_or_package_not_accessible=Tag {0}: reference not accessible: {1 doclet.see.nested_link=Tag {0}: nested link doclet.tag.invalid_usage=invalid usage of tag {0} doclet.tag.invalid_input=invalid input: ''{0}'' +doclet.tag.invalid=invalid @{0} doclet.Deprecated_API=Deprecated API doclet.Deprecated_Elements=Deprecated {0} doclet.Deprecated_In_Release=Deprecated in {0} @@ -457,6 +458,14 @@ doclet.usage.linkoffline.parameters=\ doclet.usage.linkoffline.description=\ Link to docs at using package list at +# L10N: do not localize the option parameters: warn info +doclet.usage.link-modularity-mismatch.parameters=\ + (warn|info) +doclet.usage.link-modularity-mismatch.description=\ + Report external documentation with wrong modularity with either\n\ + a warning or informational message. The default behaviour is to\n\ + report a warning. + doclet.usage.link-platform-properties.parameters=\ doclet.usage.link-platform-properties.description=\ diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseOptions.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseOptions.java index 5fe0e514884306d47f5bf530a1a13dff0f25fe2c..6445f4fc6a088f4eaf0d52de680218f771f1bba3 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseOptions.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseOptions.java @@ -36,6 +36,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; +import java.util.Locale; import java.util.MissingResourceException; import java.util.Set; import java.util.StringTokenizer; @@ -165,6 +166,20 @@ public abstract class BaseOptions { // A list of pairs containing urls and package list private final List> linkOfflineList = new ArrayList<>(); + /** + * An enum of policies for handling modularity mismatches in external documentation. + */ + public enum ModularityMismatchPolicy { + INFO, + WARN + } + + /** + * Argument for command-line option {@code --link-modularity-mismatch}. + * Describes how to handle external documentation with non-matching modularity. + */ + private ModularityMismatchPolicy linkModularityMismatch = ModularityMismatchPolicy.WARN; + /** * Location of alternative platform link properties file. */ @@ -403,6 +418,23 @@ public abstract class BaseOptions { } }, + new Option(resources, "--link-modularity-mismatch", 1) { + @Override + public boolean process(String opt, List args) { + String s = args.get(0); + switch (s) { + case "warn", "info" -> + linkModularityMismatch = ModularityMismatchPolicy.valueOf(s.toUpperCase(Locale.ROOT)); + default -> { + reporter.print(ERROR, resources.getText( + "doclet.Option_invalid", s, "--link-modularity-mismatch")); + return false; + } + } + return true; + } + }, + new Option(resources, "--link-platform-properties", 1) { @Override public boolean process(String opt, List args) { @@ -464,16 +496,13 @@ public abstract class BaseOptions { public boolean process(String opt, List args) { String o = args.get(0); switch (o) { - case "summary": - summarizeOverriddenMethods = true; - break; - case "detail": - summarizeOverriddenMethods = false; - break; - default: + case "summary" -> summarizeOverriddenMethods = true; + case "detail" -> summarizeOverriddenMethods = false; + default -> { reporter.print(ERROR, resources.getText("doclet.Option_invalid",o, "--override-methods")); return false; + } } return true; } @@ -827,6 +856,14 @@ public abstract class BaseOptions { return linkOfflineList; } + /** + * Argument for command-line option {@code --link-modularity-mismatch}. + * Describes how to handle external documentation with non-matching modularity. + */ + public ModularityMismatchPolicy linkModularityMismatch() { + return linkModularityMismatch; + } + /** * Argument for command-line option {@code --link-platform-properties}. */ diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties index 8825d98f96de77da45348443317d65950e321f79..78fc21db8a21a07a0d044f0d87620cb5dc95e1e7 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties @@ -373,6 +373,8 @@ doclet.snippet.contents.mismatch=\ doclet.snippet.markup=\ snippet markup: {0} +doclet.snippet.markup.spurious=\ + spurious markup doclet.snippet.markup.attribute.absent=\ missing attribute "{0}" doclet.snippet.markup.attribute.simultaneous.use=\ diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css index d61caef2a0ebff9cd018180b9a968ad95efc9c19..69252eab283f2f5efd01df10943e84306e438613 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css @@ -555,6 +555,18 @@ div.block { div.block div.deprecation-comment { font-style:normal; } +details.invalid-tag, span.invalid-tag { + font-size:14px; + font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; + background: #ffe6e6; + border: thin solid #000000; + border-radius:2px; + padding: 2px 4px; + display:inline-block; +} +details.invalid-tag summary { + cursor: pointer; +} /* * Styles specific to HTML5 elements. */ @@ -991,11 +1003,9 @@ button.snippet-copy:active { pre.snippet .italic { font-style: italic; } - pre.snippet .bold { font-weight: bold; } - pre.snippet .highlighted { background-color: #f7c590; border-radius: 10%; diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/SnippetTaglet.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/SnippetTaglet.java index 754a5bf06182b08136fa83d6af27227fdd1bc424..3c13b194c226543e801e7110169379fa12aa9ee6 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/SnippetTaglet.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/SnippetTaglet.java @@ -30,6 +30,7 @@ import java.util.EnumSet; import java.util.HashMap; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.stream.Collectors; import javax.lang.model.element.Element; @@ -63,6 +64,38 @@ import jdk.javadoc.internal.doclets.toolkit.util.Utils; */ public class SnippetTaglet extends BaseTaglet { + public enum Language { + + JAVA("java"), + PROPERTIES("properties"); + + private static final Map languages; + + static { + Map tmp = new HashMap<>(); + for (var language : values()) { + String id = Objects.requireNonNull(language.identifier); + if (tmp.put(id, language) != null) + throw new IllegalStateException(); // 1-1 correspondence + } + languages = Map.copyOf(tmp); + } + + Language(String id) { + identifier = id; + } + + private final String identifier; + + public static Optional of(String identifier) { + if (identifier == null) + return Optional.empty(); + return Optional.ofNullable(languages.get(identifier)); + } + + public String getIdentifier() {return identifier;} + } + public SnippetTaglet() { super(DocTree.Kind.SNIPPET, true, EnumSet.allOf(Taglet.Location.class)); } @@ -87,7 +120,8 @@ public class SnippetTaglet extends BaseTaglet { return generateContent(holder, tag, writer); } catch (BadSnippetException e) { error(writer, holder, e.tag(), e.key(), e.args()); - return badSnippet(writer); + String details = writer.configuration().getDocResources().getText(e.key(), e.args()); + return badSnippet(writer, Optional.of(details)); } } @@ -217,14 +251,33 @@ public class SnippetTaglet extends BaseTaglet { } } + String lang = null; + AttributeTree langAttr = attributes.get("lang"); + if (langAttr != null) { + lang = stringValueOf(langAttr); + } else if (containsClass) { + lang = "java"; + } else if (containsFile) { + lang = languageFromFileName(fileObject.getName()); + } + + Optional language = Language.of(lang); + + // TODO cache parsed external snippet (WeakHashMap) StyledText inlineSnippet = null; StyledText externalSnippet = null; try { + Diags d = (text, pos) -> { + var path = writer.configuration().utils.getCommentHelper(holder) + .getDocTreePath(snippetTag.getBody()); + writer.configuration().getReporter().print(Diagnostic.Kind.WARNING, + path, pos, pos, pos, text); + }; if (inlineContent != null) { - inlineSnippet = parse(writer.configuration().getDocResources(), inlineContent); + inlineSnippet = parse(writer.configuration().getDocResources(), d, language, inlineContent); } } catch (ParseException e) { var path = writer.configuration().utils.getCommentHelper(holder) @@ -234,18 +287,20 @@ public class SnippetTaglet extends BaseTaglet { .getText("doclet.snippet.markup", e.getMessage()); writer.configuration().getReporter().print(Diagnostic.Kind.ERROR, path, e.getPosition(), e.getPosition(), e.getPosition(), msg); - return badSnippet(writer); + return badSnippet(writer, Optional.of(e.getMessage())); } try { + var finalFileObject = fileObject; + Diags d = (text, pos) -> writer.configuration().getMessages().warning(finalFileObject, pos, pos, pos, text); if (externalContent != null) { - externalSnippet = parse(writer.configuration().getDocResources(), externalContent); + externalSnippet = parse(writer.configuration().getDocResources(), d, language, externalContent); } } catch (ParseException e) { assert fileObject != null; writer.configuration().getMessages().error(fileObject, e.getPosition(), e.getPosition(), e.getPosition(), "doclet.snippet.markup", e.getMessage()); - return badSnippet(writer); + return badSnippet(writer, Optional.of(e.getMessage())); } // the region must be matched at least in one content: it can be matched @@ -289,15 +344,6 @@ public class SnippetTaglet extends BaseTaglet { assert inlineSnippet != null || externalSnippet != null; StyledText text = inlineSnippet != null ? inlineSnippet : externalSnippet; - String lang = null; - AttributeTree langAttr = attributes.get("lang"); - if (langAttr != null) { - lang = stringValueOf(langAttr); - } else if (containsClass) { - lang = "java"; - } else if (containsFile) { - lang = languageFromFileName(fileObject.getName()); - } AttributeTree idAttr = attributes.get("id"); String id = idAttr == null ? null @@ -326,12 +372,16 @@ public class SnippetTaglet extends BaseTaglet { """.formatted(inline, external); } - private StyledText parse(Resources resources, String content) throws ParseException { - Parser.Result result = new Parser(resources).parse(content); + private StyledText parse(Resources resources, Diags diags, Optional language, String content) throws ParseException { + Parser.Result result = new Parser(resources).parse(diags, language, content); result.actions().forEach(Action::perform); return result.text(); } + public interface Diags { + void warn(String text, int pos); + } + private static String stringValueOf(AttributeTree at) throws BadSnippetException { if (at.getValueKind() == AttributeTree.ValueKind.EMPTY) { throw new BadSnippetException(at, "doclet.tag.attribute.value.missing", @@ -359,8 +409,9 @@ public class SnippetTaglet extends BaseTaglet { writer.configuration().utils.getCommentHelper(holder).getDocTreePath(tag), key, args); } - private Content badSnippet(TagletWriter writer) { - return writer.getOutputInstance().add("bad snippet"); + private Content badSnippet(TagletWriter writer, Optional details) { + Resources resources = writer.configuration().getDocResources(); + return writer.invalidTagOutput(resources.getText("doclet.tag.invalid", "snippet"), details); } private String packageName(PackageElement pkg, Utils utils) { diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletWriter.java index a12c7b42ffd8045f17b6367db48c2df253708433..b9142d6721a3a2f7936c6a8b4db43bd7193f6f97 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletWriter.java @@ -27,6 +27,7 @@ package jdk.javadoc.internal.doclets.toolkit.taglets; import java.util.List; import java.util.Map; +import java.util.Optional; import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; import javax.lang.model.element.TypeElement; @@ -239,6 +240,17 @@ public abstract class TagletWriter { protected abstract Content valueTagOutput(VariableElement field, String constantVal, boolean includeLink); + /** + * Returns the output for an invalid tag. The returned content uses special styling to + * highlight the problem. Depending on the presence of the {@code detail} string the method + * returns a plain text span or an expandable component. + * + * @param summary the single-line summary message + * @param detail the optional detail message which may contain preformatted text + * @return the output + */ + protected abstract Content invalidTagOutput(String summary, Optional detail); + /** * Returns the main type element of the current page or null for pages that don't have one. * diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/snippet/MarkupParser.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/snippet/MarkupParser.java index 879ba7bf2e40e5843ef09dd297b4ce1bb3c46991..59d6b3f9fdb3381e5dab55d3c5255b80d06c50cd 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/snippet/MarkupParser.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/snippet/MarkupParser.java @@ -31,11 +31,8 @@ import java.util.List; import jdk.javadoc.internal.doclets.toolkit.Resources; // -// markup-comment = { markup-tag } ; -// markup-tag = "@" , tag-name , {attribute} [":"] ; -// -// If optional trailing ":" is present, the tag refers to the next line -// rather than to this line. +// markup-comment = { markup-tag } [":"] ; +// markup-tag = "@" , tag-name , {attribute} ; // /** @@ -76,15 +73,28 @@ public final class MarkupParser { } protected List parse() throws ParseException { + List tags = readTags(); + if (ch == ':') { + tags.forEach(t -> t.appliesToNextLine = true); + nextChar(); + } + skipWhitespace(); + if (ch != EOI) { + return List.of(); + } + return tags; + } + + protected List readTags() throws ParseException { List tags = new ArrayList<>(); - // TODO: what to do with leading and trailing unrecognized markup? + skipWhitespace(); while (bp < buflen) { - switch (ch) { - case '@' -> tags.add(readTag()); - default -> nextChar(); + if (ch == '@') { + tags.add(readTag()); + } else { + break; } } - return tags; } @@ -94,26 +104,13 @@ public final class MarkupParser { String name = readIdentifier(); skipWhitespace(); - boolean appliesToNextLine = false; - List attributes = List.of(); - - if (ch == ':') { - appliesToNextLine = true; - nextChar(); - } else { - attributes = attrs(); - skipWhitespace(); - if (ch == ':') { - appliesToNextLine = true; - nextChar(); - } - } + List attributes = attrs(); + skipWhitespace(); Parser.Tag i = new Parser.Tag(); i.nameLineOffset = nameBp; i.name = name; i.attributes = attributes; - i.appliesToNextLine = appliesToNextLine; return i; } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/snippet/Parser.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/snippet/Parser.java index 3a1fbaade375cdae6b8929ea87c30910e19b9997..3ed4ac03166d23b38922de2eb173e1cb18d3f7ce 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/snippet/Parser.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/snippet/Parser.java @@ -39,6 +39,7 @@ import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import jdk.javadoc.internal.doclets.toolkit.Resources; +import jdk.javadoc.internal.doclets.toolkit.taglets.SnippetTaglet; /* * Semantics of a EOL comment; plus @@ -76,10 +77,10 @@ import jdk.javadoc.internal.doclets.toolkit.Resources; */ public final class Parser { - // next-line tag behaves as if it were specified on the next line - - private String eolMarker; - private Matcher markedUpLine; + private static final Pattern JAVA_COMMENT = Pattern.compile( + "^(?.*)//(?\\s*@\\s*\\w+.+?)$"); + private static final Pattern PROPERTIES_COMMENT = Pattern.compile( + "^(?[ \t]*([#!].*)?)[#!](?\\s*@\\s*\\w+.+?)$"); private final Resources resources; private final MarkupParser markupParser; @@ -93,32 +94,23 @@ public final class Parser { this.markupParser = new MarkupParser(resources); } - public Result parse(String source) throws ParseException { - return parse("//", source); + public Result parse(SnippetTaglet.Diags diags, Optional language, String source) throws ParseException { + SnippetTaglet.Language lang = language.orElse(SnippetTaglet.Language.JAVA); + var p = switch (lang) { + case JAVA -> JAVA_COMMENT; + case PROPERTIES -> PROPERTIES_COMMENT; + }; + return parse(diags, p, source); } /* * Newline characters in the returned text are of the \n form. */ - public Result parse(String eolMarker, String source) throws ParseException { - Objects.requireNonNull(eolMarker); + private Result parse(SnippetTaglet.Diags diags, Pattern commentPattern, String source) throws ParseException { + Objects.requireNonNull(commentPattern); Objects.requireNonNull(source); - if (!Objects.equals(eolMarker, this.eolMarker)) { - if (eolMarker.length() < 1) { - throw new IllegalArgumentException(); - } - for (int i = 0; i < eolMarker.length(); i++) { - switch (eolMarker.charAt(i)) { - case '\f', '\n', '\r' -> throw new IllegalArgumentException(); - } - } - this.eolMarker = eolMarker; - // capture the rightmost eolMarker (e.g. "//") - // The below Pattern.compile should never throw PatternSyntaxException - Pattern pattern = Pattern.compile("^(.*)(" + Pattern.quote(eolMarker) - + "(\\s*@\\s*\\w+.+?))$"); - this.markedUpLine = pattern.matcher(""); // reusable matcher - } + + Matcher markedUpLine = commentPattern.matcher(""); // reusable matcher tags.clear(); regions.clear(); @@ -147,21 +139,22 @@ public final class Parser { String rawLine = next.line(); boolean addLineTerminator = iterator.hasNext() || trailingNewline; String line; + boolean hasMarkup = false; markedUpLine.reset(rawLine); if (!markedUpLine.matches()) { // (1) line = rawLine + (addLineTerminator ? "\n" : ""); } else { - String maybeMarkup = markedUpLine.group(3); + String maybeMarkup = rawLine.substring(markedUpLine.start("markup")); List parsedTags; try { parsedTags = markupParser.parse(maybeMarkup); } catch (ParseException e) { // translate error position from markup to file line - throw new ParseException(e::getMessage, markedUpLine.start(3) + e.getPosition()); + throw new ParseException(e::getMessage, next.offset() + markedUpLine.start("markup") + e.getPosition()); } for (Tag t : parsedTags) { t.lineSourceOffset = next.offset(); - t.markupLineOffset = markedUpLine.start(3); + t.markupLineOffset = markedUpLine.start("markup"); } thisLineTags.addAll(parsedTags); for (var tagIterator = thisLineTags.iterator(); tagIterator.hasNext(); ) { @@ -173,10 +166,11 @@ public final class Parser { } } if (parsedTags.isEmpty()) { // (2) - // TODO: log this with NOTICE; + diags.warn(resources.getText("doclet.snippet.markup.spurious"), next.offset() + markedUpLine.start("markup")); line = rawLine + (addLineTerminator ? "\n" : ""); } else { // (3) - String payload = markedUpLine.group(1); + hasMarkup = true; + String payload = rawLine.substring(0, markedUpLine.end("payload")); line = payload + (addLineTerminator ? "\n" : ""); } } @@ -193,7 +187,7 @@ public final class Parser { thisLineTags.clear(); - append(text, Set.of(), line); + append(text, line.isBlank() && hasMarkup ? Set.of(new Style.Markup()) : Set.of(), line); // TODO: mark up trailing whitespace! lineStart += line.length(); } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/snippet/Style.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/snippet/Style.java index 854899c794ea294e0ce467e5b622439a944a7064..f7fd6aab9cb7483f35bcbee1c4663524df9bfdec 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/snippet/Style.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/snippet/Style.java @@ -37,21 +37,21 @@ public sealed interface Style { /** * A style that describes a link. Characters of this style are typically - * processed by wrapping into an HTML {@code A} element pointing to the + * processed by being wrapped into an HTML {@code A} element pointing to the * provided target. */ record Link(String target) implements Style { } /** * A named style. Characters of this style are typically processed by - * wrapping into an HTML {@code SPAN} element with the {@code class} + * being wrapped into an HTML {@code SPAN} element with the {@code class} * attribute which is obtained from the provided name. */ record Name(String name) implements Style { } /** * A marker of belonging to markup. Characters of this style are typically - * processed by omitting from the output. + * processed by being omitted from the output. */ record Markup() implements Style { } } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/snippet/StyledText.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/snippet/StyledText.java index d7e51a4e9370c85598bf5460abca524f32d2ede6..2a64b87acfaf3236539364c258df0f9d0ab1003c 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/snippet/StyledText.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/snippet/StyledText.java @@ -74,8 +74,8 @@ public class StyledText { } /* - * For each character of this text adds the provided objects to a set of - * objects associated with that character. + * For each character of this text adds the provided styles to a set of + * styles associated with that character. */ public void addStyle(Set additionalStyles) { styles.add(0, length(), additionalStyles); @@ -87,7 +87,7 @@ public class StyledText { /* * Replaces all characters of this text with the provided sequence of - * characters, each of which is associated with all the provided objects. + * characters, each of which is associated with all the provided styles. */ public void replace(Set styles, CharSequence plaintext) { replace(0, length(), styles, plaintext); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Extern.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Extern.java index 052fe0eb13b10277c611baa96aa7fe94f8e1f26d..71ec19d270cb445040e5b63310194d399859dc28 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Extern.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Extern.java @@ -514,7 +514,7 @@ public class Extern { DocPath elempath; String moduleName = null; DocPath basePath = DocPath.create(path); - boolean issueWarning = true; + boolean showDiagnostic = true; while ((elemname = in.readLine()) != null) { if (elemname.length() > 0) { elempath = basePath; @@ -534,14 +534,14 @@ public class Extern { // For user provided libraries we check whether modularity matches the actual library. // We trust modularity to be correct for platform library element lists. if (platformVersion == 0) { - actualModuleName = checkLinkCompatibility(elemname, moduleName, path, issueWarning); + actualModuleName = checkLinkCompatibility(elemname, moduleName, path, showDiagnostic); } else { actualModuleName = moduleName == null ? DocletConstants.DEFAULT_ELEMENT_NAME : moduleName; } Item item = new Item(elemname, elempath, relative); packageItems.computeIfAbsent(actualModuleName, k -> new TreeMap<>()) .putIfAbsent(elemname, item); // first-one-wins semantics - issueWarning = false; + showDiagnostic = false; } } } @@ -556,25 +556,23 @@ public class Extern { * @param packageName the package name * @param moduleName the module name or null * @param path the documentation path - * @param issueWarning whether to print a warning in case of modularity mismatch + * @param showDiagnostic whether to print a diagnostic message in case of modularity mismatch * @return the module name to use according to actual modularity of the package */ - private String checkLinkCompatibility(String packageName, String moduleName, String path, boolean issueWarning) { + private String checkLinkCompatibility(String packageName, String moduleName, String path, boolean showDiagnostic) { PackageElement pe = utils.elementUtils.getPackageElement(packageName); if (pe != null) { ModuleElement me = (ModuleElement)pe.getEnclosingElement(); if (me == null || me.isUnnamed()) { - if (moduleName != null && issueWarning) { - configuration.getReporter().print(Kind.WARNING, - resources.getText("doclet.linkMismatch_PackagedLinkedtoModule", path)); + if (moduleName != null && showDiagnostic) { + printModularityMismatchDiagnostic("doclet.linkMismatch_PackagedLinkedtoModule", path); } // library is not modular, ignore module name even if documentation is modular return DocletConstants.DEFAULT_ELEMENT_NAME; } else if (moduleName == null) { - // suppress the warning message in the case of automatic modules - if (!utils.elementUtils.isAutomaticModule(me) && issueWarning) { - configuration.getReporter().print(Kind.WARNING, - resources.getText("doclet.linkMismatch_ModuleLinkedtoPackage", path)); + // suppress the diagnostic message in the case of automatic modules + if (!utils.elementUtils.isAutomaticModule(me) && showDiagnostic) { + printModularityMismatchDiagnostic("doclet.linkMismatch_ModuleLinkedtoPackage", path); } // library is modular, use module name for lookup even though documentation is not return utils.getModuleName(me); @@ -659,4 +657,11 @@ public class Extern { return in; } + + private void printModularityMismatchDiagnostic(String key, Object arg) { + switch (configuration.getOptions().linkModularityMismatch()) { + case INFO -> configuration.getMessages().notice(key, arg); + case WARN -> configuration.getMessages().warning(key, arg); + } + } } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java index 4d289797bcf1533a9d30e99f7194e4314887fb22..ec7b14c5b4f6385becd3a07d986f595e363fe459 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java @@ -2893,8 +2893,11 @@ public class Utils { } public PreviewSummary declaredUsingPreviewAPIs(Element el) { - List usedInDeclaration = new ArrayList<>(); - usedInDeclaration.addAll(annotations2Classes(el)); + if (el.asType().getKind() == ERROR) { + // Can happen with undocumented --ignore-source-errors option + return new PreviewSummary(Collections.emptySet(), Collections.emptySet(), Collections.emptySet()); + } + List usedInDeclaration = new ArrayList<>(annotations2Classes(el)); switch (el.getKind()) { case ANNOTATION_TYPE, CLASS, ENUM, INTERFACE, RECORD -> { TypeElement te = (TypeElement) el; diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Checker.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Checker.java index 0d73d233cc166af98273ec654db57c070abda3d8..abf8c698bbab039823dacd40ec764052ffde72de 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Checker.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Checker.java @@ -1236,13 +1236,7 @@ public class Checker extends DocTreePathScanner { } boolean hasNonWhitespace(TextTree tree) { - String s = tree.getBody(); - for (int i = 0; i < s.length(); i++) { - Character c = s.charAt(i); - if (!Character.isWhitespace(s.charAt(i))) - return true; - } - return false; + return !tree.getBody().isBlank(); } // diff --git a/src/jdk.javadoc/share/man/javadoc.1 b/src/jdk.javadoc/share/man/javadoc.1 index c052a4ca136f62e53b839b89cf8fd66def28a942..4f64deb532fa18c518da06803821b68436edf798 100644 --- a/src/jdk.javadoc/share/man/javadoc.1 +++ b/src/jdk.javadoc/share/man/javadoc.1 @@ -1,4 +1,4 @@ -.\" Copyright (c) 1994, 2020, Oracle and/or its affiliates. All rights reserved. +.\" Copyright (c) 1994, 2021, Oracle and/or its affiliates. All rights reserved. .\" DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. .\" .\" This code is free software; you can redistribute it and/or modify it @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JAVADOC" "1" "2021" "JDK 18\-ea" "JDK Commands" +.TH "JAVADOC" "1" "2022" "JDK 19\-ea" "JDK Commands" .hy .SH NAME .PP @@ -34,9 +34,9 @@ files .TP .B \f[I]options\f[R] Specifies command\-line options, separated by spaces. -See \f[B]Options for javadoc\f[R], \f[B]Extended Options\f[R], -\f[B]Standard doclet Options\f[R], and \f[B]Additional Options Provided -by the Standard doclet\f[R]. +See \f[B]Standard \f[BC]javadoc\f[B] Options\f[R], \f[B]Extra +\f[BC]javadoc\f[B] Options\f[R], \f[B]Standard Options for the Standard +Doclet\f[R], and \f[B]Extra Options for the Standard Doclet\f[R]. .RS .RE .TP @@ -88,19 +88,15 @@ option either to recursively traverse a directory and its subdirectories, or to pass in an explicit list of package names. When you document individual source files, pass in a list of Java source file names. -See \f[B]javadoc Overview\f[R] -[https://www.oracle.com/pls/topic/lookup?ctx=en/java/javase/13/tools&id=JSJAV\-GUID\-7A344353\-3BBF\-45C4\-8B28\-15025DDCC643] -in Java Platform, Standard Edition Javadoc Guide for information about -using the \f[CB]javadoc\f[R] tool. -.SH CONFORMANCE +.SS Conformance .PP -The standard doclet does not validate the content of documentation +The Standard Doclet does not validate the content of documentation comments for conformance, nor does it attempt to correct any errors in documentation comments. Anyone running javadoc is advised to be aware of the problems that may arise when generating non\-conformant output or output containing executable content, such as JavaScript. -The standard doclet does provide the \f[CB]doclint\f[R] feature to help +The Standard Doclet does provide the \f[B]DocLint\f[R] feature to help developers detect common problems in documentation comments; but it is also recommended to check the generated output with any appropriate conformance and other checking tools. @@ -112,7 +108,16 @@ in the HTML5 Specification. For more details on security issues related to web pages, see the \f[B]Open Web Application Security Project (OWASP)\f[R] [https://www.owasp.org] page. -.SH OPTIONS FOR JAVADOC +.SH OPTIONS +.PP +\f[CB]javadoc\f[R] supports command\-line options for both the main +\f[CB]javadoc\f[R] tool and the currently selected doclet. +The Standard Doclet is used if no other doclet is specified. +.PP +GNU\-style options (that is, those beginning with \f[CB]\-\-\f[R]) can use +an equal sign (\f[CB]=\f[R]) instead of whitespace characters to separate +the name of an option from its value. +.SS Standard \f[CB]javadoc\f[R] Options .PP The following core \f[CB]javadoc\f[R] options are equivalent to corresponding \f[CB]javac\f[R] options. @@ -151,12 +156,6 @@ descriptions of using these options: .PP The following options are the core \f[CB]javadoc\f[R] options that are not equivalent to a corresponding \f[CB]javac\f[R] option: -.PP -\f[B]Note:\f[R] -.PP -In tools that support \f[CB]\-\-\f[R] style options, the GNU\-style -options can use the equal sign (=) instead of a white space to separate -the name of an option from its value. .TP .B \f[CB]\-breakiterator\f[R] Computes the first sentence with \f[CB]BreakIterator\f[R]. @@ -222,20 +221,24 @@ exclude packages rooted at \f[CB]java.net\f[R] and \f[CB]java.lang\f[R]. Notice that these examples exclude \f[CB]java.lang.ref\f[R], which is a subpackage of \f[CB]java.lang\f[R]. .IP \[bu] 2 -\f[B]Linux and OS X:\f[R] +\f[B]Linux and macOS:\f[R] .RS 2 -.RS -.PP -\f[CB]javadoc\ \-sourcepath\ /home/user/src\ \-subpackages\ java\ \-exclude\ java.net:java.lang\f[R] -.RE +.IP +.nf +\f[CB] +javadoc\ \-sourcepath\ /home/user/src\ \-subpackages\ java\ \-exclude\ java.net:java.lang +\f[R] +.fi .RE .IP \[bu] 2 \f[B]Windows:\f[R] .RS 2 -.RS -.PP -\f[CB]javadoc\ \-sourcepath\ \\user\\src\ \-subpackages\ java\ \-exclude\ java.net:java.lang\f[R] -.RE +.IP +.nf +\f[CB] +javadoc\ \-sourcepath\ \\user\\src\ \-subpackages\ java\ \-exclude\ java.net:java.lang +\f[R] +.fi .RE .RE .TP @@ -283,9 +286,9 @@ used to run the \f[CB]javadoc\f[R] tool. .nf \f[CB] javadoc\ \-J\-version -java\ version\ "10\-ea"\ 2018\-03\-20 -Java(TM)\ SE\ Runtime\ Environment\ 18.3\ (build\ 10\-ea+36) -Java\ HotSpot(TM)\ 64\-Bit\ Server\ VM\ 18.3\ (build\ 10\-ea+36,\ mixed\ mode) +java\ version\ "17"\ 2021\-09\-14\ LTS +Java(TM)\ SE\ Runtime\ Environment\ (build\ 17+35\-LTS\-2724) +Java\ HotSpot(TM)\ 64\-Bit\ Server\ VM\ (build\ 17+35\-LTS\-2724,\ mixed\ mode,\ sharing) \f[R] .fi .RE @@ -298,13 +301,6 @@ The argument is the name of the locale, as described in (English, United States) or \f[CB]en_US_WIN\f[R] (Windows variant). .RS .PP -\f[B]Note:\f[R] -.PP -The \f[CB]\-locale\f[R] option must be placed ahead (to the left) of any -options provided by the standard doclet or any other doclet. -Otherwise, the navigation bars appear in English. -This is the only command\-line option that depends on order. -.PP Specifying a locale causes the \f[CB]javadoc\f[R] tool to choose the resource files of that locale for messages such as strings in the navigation bar, headings for lists and tables, help file contents, @@ -349,13 +345,14 @@ Specifies which members (fields or methods) are documented, where \f[I]value\f[R] can be any of the following: .RS .IP \[bu] 2 -\f[CB]protected\f[R]: The default value is protected. +\f[CB]public\f[R] \-\-\- shows only public members .IP \[bu] 2 -\f[CB]public\f[R]: Shows only public values. +\f[CB]protected\f[R] \-\-\- shows public and protected members; this is +the default .IP \[bu] 2 -\f[CB]package\f[R]: Shows public, protected, and package members. +\f[CB]package\f[R] \-\-\- shows public, protected, and package members .IP \[bu] 2 -\f[CB]private\f[R]: Shows all members. +\f[CB]private\f[R] \-\-\- shows all members .RE .TP .B \f[CB]\-\-show\-module\-contents\f[R] \f[I]value\f[R] @@ -375,14 +372,14 @@ Specifies which types (classes, interfaces, etc.) are documented, where \f[I]value\f[R] can be any of the following: .RS .IP \[bu] 2 -\f[CB]protected\f[R]: The default value. -Shows public and protected types. +\f[CB]public\f[R] \-\-\- shows only public types .IP \[bu] 2 -\f[CB]public\f[R]: Shows only public values. +\f[CB]protected\f[R] \-\-\- shows public and protected types; this is the +default .IP \[bu] 2 -\f[CB]package\f[R]: Shows public, protected, and package types. +\f[CB]package\f[R] \-\-\- shows public, protected, and package types .IP \[bu] 2 -\f[CB]private\f[R]: Shows all types. +\f[CB]private\f[R] \-\-\- shows all types .RE .TP .B \f[CB]\-subpackages\f[R] \f[I]subpkglist\f[R] @@ -404,20 +401,24 @@ For example, the following commands generates documentation for packages named \f[CB]java\f[R] and \f[CB]javax.swing\f[R] and all of their subpackages. .IP \[bu] 2 -\f[B]Linux and OS X:\f[R] +\f[B]Linux and macOS:\f[R] .RS 2 -.RS -.PP -\f[CB]javadoc\ \-d\ docs\ \-sourcepath\ /home/user/src\ \-subpackages\ java:javax.swing\f[R] -.RE +.IP +.nf +\f[CB] +javadoc\ \-d\ docs\ \-sourcepath\ /home/user/src\ \-subpackages\ java:javax.swing +\f[R] +.fi .RE .IP \[bu] 2 \f[B]Windows:\f[R] .RS 2 -.RS -.PP -\f[CB]javadoc\ \-d\ docs\ \-sourcepath\ \\user\\src\ \-subpackages\ java:javax.swing\f[R] -.RE +.IP +.nf +\f[CB] +javadoc\ \-d\ docs\ \-sourcepath\ \\user\\src\ \-subpackages\ java:javax.swing +\f[R] +.fi .RE .RE .TP @@ -440,14 +441,12 @@ Prints version information. Reports an error if any warnings occur. .RS .RE -.SH EXTENDED OPTIONS -.PP -\f[B]Note:\f[R] +.SS Extra \f[CB]javadoc\f[R] Options .PP -The extended options for \f[CB]javadoc\f[R] are subject to change without -notice. +\f[I]Note:\f[R] The additional options for \f[CB]javadoc\f[R] are subject +to change without notice. .PP -The following extended \f[CB]javadoc\f[R] options are equivalent to +The following additional \f[CB]javadoc\f[R] options are equivalent to corresponding \f[CB]javac\f[R] options. See \f[I]Extra Options\f[R] in \f[B]javac\f[R] for the detailed descriptions of using these options: @@ -461,25 +460,42 @@ descriptions of using these options: \f[CB]\-Xmaxerrs\f[R] .IP \[bu] 2 \f[CB]\-Xmaxwarns\f[R] -.SH STANDARD DOCLET OPTIONS +.SS Standard Options for the Standard Doclet .PP The following options are provided by the standard doclet. .TP -.B \f[CB]\-\-add\-stylesheet\f[R] \f[I]file\f[R] -Adds additional stylesheet file for the generated documentation. -This option can be used one or more times to specify additional -stylesheets included in the documentation. +.B \f[CB]\-\-add\-script\f[R] \f[I]file\f[R] +Adds \f[I]file\f[R] as an additional JavaScript file to the generated +documentation. +This option can be used one or more times to specify additional script +files. .RS .PP Command\-line example: .RS .PP -\f[CB]javadoc\ \-\-add\-stylesheet\ new_stylesheet_1.css\ \-\-add\-stylesheet\ new_stylesheet_2.css\ pkg_foo\f[R] +\f[CB]javadoc\ \-\-add\-script\ first_script.js\ \-\-add\-script\ second_script.js\ pkg_foo\f[R] .RE .RE .TP +.B \f[CB]\-\-add\-stylesheet\f[R] \f[I]file\f[R] +Adds \f[I]file\f[R] as an additional stylesheet file to the generated +documentation. +This option can be used one or more times to specify additional +stylesheets included in the documentation. +.RS +.PP +Command\-line example: +.IP +.nf +\f[CB] +javadoc\ \-\-add\-stylesheet\ new_stylesheet_1.css\ \-\-add\-stylesheet\ new_stylesheet_2.css\ pkg_foo +\f[R] +.fi +.RE +.TP .B \f[CB]\-\-allow\-script\-in\-comments\f[R] -Allow JavaScript in options and comments +Allow JavaScript in options and comments. .RS .RE .TP @@ -506,19 +522,23 @@ Registry, Character Sets\f[R] .RS .PP For example: -.RS -.PP -\f[CB]javadoc\ \-charset\ "iso\-8859\-1"\ mypackage\f[R] -.RE +.IP +.nf +\f[CB] +javadoc\ \-charset\ "iso\-8859\-1"\ mypackage +\f[R] +.fi .PP This command inserts the following line in the head of every generated page: -.RS -.PP -\f[CB]\f[R] -.RE +.IP +.nf +\f[CB] + +\f[R] +.fi .PP -The \f[CB]META\f[R] tag is described in the \f[B]HTML standard (4197265 +The \f[CB]meta\f[R] tag is described in the \f[B]HTML standard (4197265 and 4137321), HTML Document Representation\f[R] [http://www.w3.org/TR/REC\-html40/charset.html#h\-5.2.2]. .RE @@ -534,24 +554,28 @@ The destination directory is automatically created when the \f[CB]javadoc\f[R] tool runs. .RS .IP \[bu] 2 -\f[B]Linux and OS X:\f[R] For example, the following command generates +\f[B]Linux and macOS:\f[R] For example, the following command generates the documentation for the package \f[CB]com.mypackage\f[R] and saves the results in the \f[CB]/user/doc/\f[R] directory: .RS 2 -.RS -.PP -\f[CB]javadoc\ \-d\ /user/doc/\ com.mypackage\f[R] -.RE +.IP +.nf +\f[CB] +javadoc\ \-d\ /user/doc/\ com.mypackage +\f[R] +.fi .RE .IP \[bu] 2 \f[B]Windows:\f[R] For example, the following command generates the documentation for the package \f[CB]com.mypackage\f[R] and saves the results in the \f[CB]\\user\\doc\\\f[R] directory: .RS 2 -.RS -.PP -\f[CB]javadoc\ \-d\ \\user\\doc\\\ com.mypackage\f[R] -.RE +.IP +.nf +\f[CB] +javadoc\ \-d\ \\user\\doc\\\ com.mypackage +\f[R] +.fi .RE .RE .TP @@ -572,14 +596,15 @@ Of the three available options, at most, only the input and an output encoding option are used in a single encoding command. If you specify both input and output encoding options in a command, they must be the same value. -If you specify neither output option, it the tool defaults to the input -encoding. +If you specify neither output option, it defaults to the input encoding. .PP For example: -.RS -.PP -\f[CB]javadoc\ \-docencoding\ "iso\-8859\-1"\ mypackage\f[R] -.RE +.IP +.nf +\f[CB] +javadoc\ \-docencoding\ "iso\-8859\-1"\ mypackage +\f[R] +.fi .RE .TP .B \f[CB]\-docfilessubdirs\f[R] @@ -596,12 +621,12 @@ it does, you must enclose the title in quotation marks. Additional quotation marks within the \f[CB]title\f[R] tag must be escaped. For example, -\f[CB]javadoc\ \-doctitle\ "My\ Library
    v1.0"\ com.mypackage.\f[R] +\f[CB]javadoc\ \-doctitle\ "My\ Library
    v1.0"\ com.mypackage\f[R]. .RS .RE .TP .B \f[CB]\-excludedocfilessubdir\f[R] \f[I]name\f[R] -Excludes any doc files sub directories with the given name. +Excludes any doc files subdirectories with the given name. Enables deep copying of doc\-files directories. Subdirectories and all contents are recursively copied to the destination. @@ -635,7 +660,7 @@ The \f[CB]header\f[R] can contain HTML tags and white space, but when it does, the \f[CB]header\f[R] must be enclosed in quotation marks. Use escape characters for internal quotation marks within a header. For example, -\f[CB]javadoc\ \-header\ "My\ Library
    v1.0"\ com.mypackage.\f[R] +\f[CB]javadoc\ \-header\ "My\ Library
    v1.0"\ com.mypackage\f[R]. .RS .RE .TP @@ -653,20 +678,24 @@ accordingly. For example: .RS .IP \[bu] 2 -\f[B]Linux and OS X:\f[R] +\f[B]Linux and macOS:\f[R] .RS 2 -.RS -.PP -\f[CB]javadoc\ \-helpfile\ /home/user/myhelp.html\ java.awt.\f[R] -.RE +.IP +.nf +\f[CB] +javadoc\ \-helpfile\ /home/user/myhelp.html\ java.awt +\f[R] +.fi .RE .IP \[bu] 2 \f[B]Windows:\f[R] .RS 2 -.RS -.PP -\f[CB]javadoc\ \-helpfile\ C:\\user\\myhelp.html\ java.awt.\f[R] -.RE +.IP +.nf +\f[CB] +javadoc\ \-helpfile\ C:\\user\\myhelp.html\ java.awt +\f[R] +.fi .RE .RE .TP @@ -678,19 +707,21 @@ compatibility. .TP .B \f[CB]\-\-javafx\f[R] or \f[CB]\-javafx\f[R] Enables JavaFX functionality. +This option is enabled by default if the JavaFX library classes are +detected on the module path. .RS .RE .TP .B \f[CB]\-keywords\f[R] -Adds HTML keyword \f[CB]\f[R] tags to the generated file for each +Adds HTML keyword \f[CB]\f[R] tags to the generated file for each class. -These tags can help search engines that look for \f[CB]\f[R] tags +These tags can help search engines that look for \f[CB]\f[R] tags find the pages. Most search engines that search the entire Internet don\[aq]t look at -\f[CB]\f[R] tags, because pages can misuse them. +\f[CB]\f[R] tags, because pages can misuse them. Search engines offered by companies that confine their searches to their -own website can benefit by looking at \f[CB]\f[R] tags. -The \f[CB]\f[R] tags include the fully qualified name of the class +own website can benefit by looking at \f[CB]\f[R] tags. +The \f[CB]\f[R] tags include the fully qualified name of the class and the unqualified names of the fields and methods. Constructors aren\[aq]t included because they are identical to the class name. @@ -699,10 +730,10 @@ For example, the class \f[CB]String\f[R] starts with these keywords: .IP .nf \f[CB] - - - - + + + + \f[R] .fi .RE @@ -721,10 +752,8 @@ Either a \f[CB]package\-list\f[R] or an \f[CB]element\-list\f[R] file must be in this \f[I]url\f[R] directory (otherwise, use the \f[CB]\-linkoffline\f[R] option). .PP -\f[B]Note:\f[R] -.PP -The \f[CB]package\-list\f[R] and \f[CB]element\-list\f[R] files are -generated by the \f[CB]javadoc\f[R] tool when generating the API +\f[I]Note:\f[R] The \f[CB]package\-list\f[R] and \f[CB]element\-list\f[R] +files are generated by the \f[CB]javadoc\f[R] tool when generating the API documentation and should not be modified by the user. .PP When you use the \f[CB]javadoc\f[R] tool to document packages, it uses the @@ -769,6 +798,15 @@ Uniform Resource Locators\f[R] [http://www.ietf.org/rfc/rfc1738.txt]. .fi .RE .TP +.B \f[CB]\-\-link\-modularity\-mismatch\f[R] (\f[CB]warn\f[R]|\f[CB]info\f[R]) +Specifies whether external documentation with wrong modularity (e.g. +non\-modular documentation for a modular library, or the reverse case) +should be reported as a warning (\f[CB]warn\f[R]) or just a message +(\f[CB]info\f[R]). +The default behavior is to report a warning. +.RS +.RE +.TP .B \f[CB]\-linkoffline\f[R] \f[I]url1\f[R] \f[I]url2\f[R] This option is a variation of the \f[CB]\-link\f[R] option. They both create links to \f[CB]javadoc\f[R] generated documentation for @@ -788,10 +826,8 @@ the URL location, but does exist at a different location and can be specified by either the \f[CB]package\-list\f[R] or \f[CB]element\-list\f[R] file (typically local). .PP -\f[B]Note:\f[R] -.PP -The \f[CB]package\-list\f[R] and \f[CB]element\-list\f[R] files are -generated by the \f[CB]javadoc\f[R] tool when generating the API +\f[I]Note:\f[R] The \f[CB]package\-list\f[R] and \f[CB]element\-list\f[R] +files are generated by the \f[CB]javadoc\f[R] tool when generating the API documentation and should not be modified by the user. .PP If \f[I]url1\f[R] is accessible only on the World Wide Web, then the @@ -820,6 +856,38 @@ root of the packages being linked to. See \f[I]url\f[R] in the \f[CB]\-link\f[R] option. .RE .TP +.B \f[CB]\-\-link\-platform\-properties\f[R] \f[I]url\f[R] +Specifies a properties file used to configure links to platform +documentation. +.RS +.PP +The \f[I]url\f[R] argument is expected to point to a properties file +containing one or more entries with the following format, where +\f[CB]\f[R] is the platform version as passed to the +\f[CB]\-\-release\f[R] or \f[CB]\-\-source\f[R] option and \f[CB]\f[R] is +the base URL of the corresponding platform API documentation: +.IP +.nf +\f[CB] +doclet.platform.docs.= +\f[R] +.fi +.PP +For instance, a properties file containing URLs for releases 15 to 17 +might contain the following lines: +.IP +.nf +\f[CB] +doclet.platform.docs.15=https://example.com/api/15/ +doclet.platform.docs.16=https://example.com/api/16/ +doclet.platform.docs.17=https://example.com/api/17/ +\f[R] +.fi +.PP +If the properties file does not contain an entry for a particular +release no platform links are generated. +.RE +.TP .B \f[CB]\-linksource\f[R] Creates an HTML version of each source file (with line numbers) and adds links to them from the standard HTML documentation. @@ -840,17 +908,21 @@ classes or interfaces are accessible through links. Each link appears on the name of the identifier in its declaration. For example, the link to the source code of the \f[CB]Button\f[R] class would be on the word \f[CB]Button\f[R]: -.RS -.PP -\f[CB]public\ class\ Button\ extends\ Component\ implements\ Accessible\f[R] -.RE +.IP +.nf +\f[CB] +public\ class\ Button\ extends\ Component\ implements\ Accessible +\f[R] +.fi .PP The link to the source code of the \f[CB]getLabel\f[R] method in the \f[CB]Button\f[R] class is on the word \f[CB]getLabel\f[R]: -.RS -.PP -\f[CB]public\ String\ getLabel()\f[R] -.RE +.IP +.nf +\f[CB] +public\ String\ getLabel() +\f[R] +.fi .RE .TP .B \f[CB]\-\-main\-stylesheet\f[R] \f[I]file\f[R] or \f[CB]\-stylesheetfile\f[R] \f[I]file\f[R] @@ -865,10 +937,12 @@ The \f[CB]\-\-main\-stylesheet\f[R] option is the preferred form. .RS .PP Command\-line example: -.RS -.PP -\f[CB]javadoc\ \-\-main\-stylesheet\ main_stylesheet.css\ pkg_foo\f[R] -.RE +.IP +.nf +\f[CB] +javadoc\ \-\-main\-stylesheet\ main_stylesheet.css\ pkg_foo +\f[R] +.fi .RE .TP .B \f[CB]\-nocomment\f[R] @@ -901,15 +975,9 @@ you want to make the navigation bar cleaner. .RS .RE .TP -.B \f[CB]\-\-no\-frames\f[R] -This option is a no\-op and is just retained for backwards -compatibility. -.RS -.RE -.TP .B \f[CB]\-nohelp\f[R] -Omits the HELP link in the navigation bars at the top and bottom of each -page of output. +Omits the HELP link in the navigation bar at the top of each page of +output. .RS .RE .TP @@ -922,7 +990,7 @@ The index is produced by default. .B \f[CB]\-nonavbar\f[R] Prevents the generation of the navigation bar, header, and footer, that are usually found at the top and bottom of the generated pages. -The \f[CB]\-nonavbar\f[R] option has no affect on the \f[CB]\-bottom\f[R] +The \f[CB]\-nonavbar\f[R] option has no effect on the \f[CB]\-bottom\f[R] option. The \f[CB]\-nonavbar\f[R] option is useful when you are interested only in the content and have no need for navigation, such as when you are @@ -930,6 +998,12 @@ converting the files to PostScript or PDF for printing only. .RS .RE .TP +.B \f[CB]\-\-no\-platform\-links\f[R] +Prevents the generation of links to platform documentation. +These links are generated by default. +.RS +.RE +.TP .B \f[CB]\-noqualifier\f[R] \f[I]name1\f[R]\f[CB]:\f[R]\f[I]name2\f[R]... Excludes the list of qualifiers from the output. The package name is removed from places where class or interface names @@ -1000,14 +1074,14 @@ that contains the topmost package directories. In this location, no path is needed when documenting packages, because the \f[CB]\-sourcepath\f[R] option points to this file. .IP \[bu] 2 -\f[B]Linux and OS X:\f[R] For example, if the source tree for the -\f[CB]java.lang\f[R] package is \f[CB]/src/classes/java/lang/\f[R], then you -could place the overview file at /src/classes/overview.html. +\f[B]Linux and macOS:\f[R] For example, if the source tree for the +\f[CB]java.lang\f[R] package is \f[CB]src/classes/java/lang/\f[R], then you +could place the overview file at src/classes/overview.html. .IP \[bu] 2 \f[B]Windows:\f[R] For example, if the source tree for the -\f[CB]java.lang\f[R] package is \f[CB]\\src\\classes\\java\\lang\\\f[R], -then you could place the overview file at -\f[CB]\\src\\classes\\overview.html\f[R] +\f[CB]java.lang\f[R] package is \f[CB]src\\classes\\java\\lang\\\f[R], then +you could place the overview file at +\f[CB]src\\classes\\overview.html\f[R] .PP The overview page is created only when you pass two or more package names to the \f[CB]javadoc\f[R] tool. @@ -1022,6 +1096,43 @@ document default serializable fields and \f[CB]writeExternal\f[R] methods. .RS .RE .TP +.B \f[CB]\-\-since\f[R] \f[I]release\f[R](\f[CB],\f[R]\f[I]release\f[R])* +Generates documentation for APIs that were added or newly deprecated in +the specified \f[I]release\f[R]s. +.RS +.PP +If the \f[CB]\@since\f[R] tag in the \f[CB]javadoc\f[R] comment of an +element in the documented source code matches a \f[I]release\f[R] passed +as option argument, information about the element and the release it was +added in is included in a "New API" page. +.PP +If the "Deprecated API" page is generated and the \f[CB]since\f[R] element +of the \f[CB]java.lang.Deprecated\f[R] annotation of a documented element +matches a \f[I]release\f[R] in the option arguments, information about +the release the element was deprecated in is added to the "Deprecated +API" page. +.PP +Releases are compared using case\-sensitive string comparison. +.RE +.TP +.B \f[CB]\-\-since\-label\f[R] \f[I]text\f[R] +Specifies the \f[I]text\f[R] to use in the heading of the "New API" page. +This may contain information about the releases covered in the page, +e.g. +"New API in release 2.0", or "New API since release 1". +.RS +.RE +.TP +.B \f[CB]\-\-snippet\-path\f[R] \f[I]snippetpathlist\f[R] +Specifies the search paths for finding files for external snippets. +The \f[I]snippetpathlist\f[R] can contain multiple paths by separating +them with the platform path separator (\f[CB];\f[R] on Windows; \f[CB]:\f[R] +on other platforms.) The Standard Doclet first searches the +\f[CB]snippet\-files\f[R] subdirectory in the package containing the +snippet, and then searches all the directories in the given list. +.RS +.RE +.TP .B \f[CB]\-sourcetab\f[R] \f[I]tablength\f[R] Specifies the number of spaces each tab uses in the source. .RS @@ -1141,8 +1252,8 @@ Specifies the title to be placed in the HTML \f[CB]\f[R] tag. The text specified in the \f[CB]title\f[R] tag appears in the window title and in any browser bookmarks (favorite places) that someone creates for this page. -This title shouldn\[aq]t contain any HTML tags because the browser -doesn\[aq]t interpret them correctly. +This title should not contain any HTML tags because a browser will not +interpret them correctly. Use escape characters on any internal quotation marks within the \f[CB]title\f[R] tag. If the \f[CB]\-windowtitle\f[R] option is omitted, then the @@ -1152,131 +1263,276 @@ For example, \f[CB]javadoc\ \-windowtitle\ "My\ Library"\ com.mypackage\f[R]. .RS .RE -.SH ADDITIONAL OPTIONS PROVIDED BY THE STANDARD DOCLET +.SS Extra Options for the Standard Doclet .PP -The following are additional options provided by the standard doclet and +The following are additional options provided by the Standard Doclet and are subject to change without notice. Additional options are less commonly used or are otherwise regarded as advanced. .TP -.B \f[CB]\-Xdoclint\f[R] -Enables recommended checks for problems in documentation comments. +.B \f[CB]\-\-legal\-notices\f[R] (\f[CB]default\f[R]|\f[CB]none\f[R]|\f[I]directory\f[R]) +Specifies the location from which to copy legal files to the generated +documentation. +If the option is not specified or is used with the value +\f[CB]default\f[R], the files are copied from the default location. +If the argument is used with value \f[CB]none\f[R], no files are copied. +Every other argument is interpreted as directory from which to copy the +legal files. .RS .RE .TP -.B \f[CB]\-Xdoclint:\f[R](\f[CB]all\f[R]|\f[CB]none\f[R]|[\f[CB]\-\f[R]]\f[I]group\f[R]) -Enable or disable specific checks for bad references, accessibility -issues, missing documentation comments, errors in documentation comment -syntax and missing HTML tags. +.B \f[CB]\-\-no\-frames\f[R] +This option is a no\-op and is just retained for backwards +compatibility. +.RS +.RE +.TP +.B \f[CB]\-Xdoclint\f[R] +Enables recommended checks for problems in documentation comments. .RS -.PP -This option enables the \f[CB]javadoc\f[R] tool to check for all -documentation comments included in the generated output. -You can select which items to include in the generated output with the -standard options \f[CB]\-public\f[R], \f[CB]\-protected\f[R], -\f[CB]\-package\f[R] and \f[CB]\-private\f[R]. -.PP -When the \f[CB]\-Xdoclint\f[R] option is enabled, it reports issues with -messages similar to the \f[CB]javac\f[R] command. -The \f[CB]javadoc\f[R] tool prints a message, a copy of the source line, -and a caret pointing at the exact position where the error was detected. -Messages may be either warnings or errors, depending on their severity -and the likelihood to cause an error if the generated documentation were -to be run through a validator. -For example: missing documentation comments, duplicate information, and -extraneous comments do not cause the \f[CB]javadoc\f[R] tool to generate -invalid HTML, so these issues are reported as warnings; syntax errors, -missing required HTML end tags, and references to missing or misspelled -elements cause the \f[CB]javadoc\f[R] tool to generate invalid output, so -these issues are reported as errors. -.PP -\f[CB]\-Xdoclint\f[R] option validates input comments based upon the -requested markup. .PP By default, the \f[CB]\-Xdoclint\f[R] option is enabled. Disable it with the option \f[CB]\-Xdoclint:none\f[R]. .PP -The following options change what the \f[CB]\-Xdoclint\f[R] option -reports: -.IP \[bu] 2 -\f[CB]\-Xdoclint\ none\f[R]: Disables the \f[CB]\-Xdoclint\f[R] option -.IP \[bu] 2 -\f[CB]\-Xdoclint\f[R] \f[I]group\f[R]: Enables \f[I]group\f[R] checks -.IP \[bu] 2 -\f[CB]\-Xdoclint\ all\f[R]: Enables all groups of checks -.IP \[bu] 2 -\f[CB]\-Xdoclint\ all,\-\f[R]\f[I]group\f[R]: Enables all checks except -\f[I]group\f[R] checks -.PP -The \f[I]group\f[R] variable has one of the following values: -.IP \[bu] 2 -\f[CB]accessibility\f[R]: Checks for the issues to be detected by an -accessibility checker (for example, no caption or summary attributes -specified in a \f[CB]<table>\f[R] tag). -.IP \[bu] 2 -\f[CB]html\f[R]: Detects high\-level HTML issues, such as putting block -elements inside inline elements, or not closing elements that require an -end tag. -The rules are derived from the \f[B]HTML 4 Specification\f[R] -[https://www.w3.org/TR/html4/] or the \f[B]HTML 5 Specification\f[R] -[http://www.w3.org/TR/2014/REC\-html5\-20141028/] based on the standard -doclet \f[CB]html\f[R] output generation selected. -This type of check enables the \f[CB]javadoc\f[R] tool to detect HTML -issues that some browsers might not interpret as intended. -.IP \[bu] 2 -\f[CB]missing\f[R]: Checks for missing documentation comments or tags (for -example, a missing comment or class, or a missing \f[CB]\@return\f[R] tag -or similar tag on a method). -.IP \[bu] 2 -\f[CB]reference\f[R]: Checks for issues relating to the references to Java -API elements from documentation comment tags (for example, item not -found in \f[CB]\@see\f[R], or a bad name after \f[CB]\@param)\f[R]. -.IP \[bu] 2 -\f[CB]syntax\f[R]: Checks for low level issues like unescaped angle -brackets (\f[CB]<\f[R] and \f[CB]>\f[R]) and ampersands (\f[CB]&\f[R]) and -invalid documentation comment tags. -.PP -You can specify the \f[CB]\-Xdoclint\f[R] option multiple times to enable -the option to check errors and warnings in multiple categories. -Alternatively, you can specify multiple error and warning categories by -using the preceding options. -For example, use either of the following commands to check for the HTML, -syntax, and accessibility issues in the file \f[I]filename\f[R]. -.RS -.PP -\f[CB]javadoc\ \-Xdoclint:html\ \-Xdoclint:syntax\ \-Xdoclint:accessibility\f[R] -\f[I]filename\f[R] +For more details, see \f[B]DocLint\f[R]. .RE +.TP +.B \f[CB]\-Xdoclint:\f[R]\f[I]flag\f[R],\f[I]flag\f[R],... +Enable or disable specific checks for different kinds of issues in +documentation comments. .RS .PP -\f[CB]javadoc\ \-Xdoclint:html,syntax,accessibility\f[R] \f[I]filename\f[R] -.RE +Each \f[I]flag\f[R] can be one of \f[CB]all\f[R], \f[CB]none\f[R], or +\f[CB][\-]\f[R]\f[I]group\f[R] where \f[I]group\f[R] has one of the +following values: \f[CB]accessibility\f[R], \f[CB]html\f[R], +\f[CB]missing\f[R], \f[CB]reference\f[R], \f[CB]syntax\f[R]. +For more details on these values, see \f[B]DocLint Groups\f[R]. .PP -\f[B]Note:\f[R] +When specifying two or more flags, you can either use a single +\f[CB]\-Xdoclint:...\f[R] option, listing all the desired flags, or you +can use multiple options giving one or more flag in each option. +For example, use either of the following commands to check for the HTML, +syntax, and accessibility issues in the file \f[CB]MyFile.java\f[R]. +.IP +.nf +\f[CB] +javadoc\ \-Xdoclint:html\ \-Xdoclint:syntax\ \-Xdoclint:accessibility\ MyFile.java +javadoc\ \-Xdoclint:html,syntax,accessibility\ MyFile.java +\f[R] +.fi .PP -The \f[CB]javadoc\f[R] tool doesn\[aq]t guarantee the completeness of -these checks. -In particular, it isn\[aq]t a full HTML compliance checker. -The goal of the \-\f[CB]Xdoclint\f[R] option is to enable the -\f[CB]javadoc\f[R] tool to report majority of common errors. +The following examples illustrate how to change what DocLint reports: +.IP \[bu] 2 +\f[CB]\-Xdoclint:none\f[R] \-\-\- disables all checks +.IP \[bu] 2 +\f[CB]\-Xdoclint:\f[R]\f[I]group\f[R] \-\-\- enables \f[I]group\f[R] checks +.IP \[bu] 2 +\f[CB]\-Xdoclint:all\f[R] \-\-\- enables all groups of checks +.IP \[bu] 2 +\f[CB]\-Xdoclint:all,\-\f[R]\f[I]group\f[R] \-\-\- enables all checks +except \f[I]group\f[R] checks .PP -The \f[CB]javadoc\f[R] tool doesn\[aq]t attempt to fix invalid input, it -just reports it. +For more details, see \f[B]DocLint\f[R]. .RE .TP .B \f[CB]\-Xdoclint/package:\f[R][\f[CB]\-\f[R]]\f[I]packages\f[R] Enables or disables checks in specific packages. \f[I]packages\f[R] is a comma separated list of package specifiers. A package specifier is either a qualified name of a package or a package -name prefix followed by \f[CB]*\f[R], which expands to all sub packages of +name prefix followed by \f[CB]*\f[R], which expands to all subpackages of the given package. Prefix the package specifier with \f[CB]\-\f[R] to disable checks for the specified packages. .RS +.PP +For more details, see \f[B]DocLint\f[R]. .RE .TP .B \f[CB]\-Xdocrootparent\f[R] \f[I]url\f[R] -Replaces all \f[CB]\@docRoot\f[R] items followed by\f[CB]/..\f[R] in Javadoc -comments with the \f[I]url\f[R]. +Replaces all \f[CB]\@docRoot\f[R] items followed by \f[CB]/..\f[R] in +documentation comments with \f[I]url\f[R]. .RS .RE +.SH DOCLINT +.PP +DocLint provides the ability to check for possible problems in +documentation comments. +Problems may be reported as warnings or errors, depending on their +severity. +For example, a missing comment may be bad style that deserves a warning, +but a link to an unknown Java declaration is more serious and deserves +an error. +Problems are organized into \f[B]groups\f[R], and options can be used to +enable or disable messages in one or more groups. +Within the source code, messages in one or more groups can be +\f[B]suppressed\f[R] by using \f[CB]\@SuppressWarnings\f[R] annotations. +.PP +When invoked from \f[CB]javadoc\f[R], by default DocLint checks all +comments that are used in the generated documentation. +It thus relies on other command\-line options to determine which +declarations, and which corresponding documentation comments will be +included. +\f[I]Note:\f[R] this may mean that even comments on some private members +of serializable classes will also be checked, if the members need to be +documented in the generated \f[CB]Serialized\ Forms\f[R] page. +.PP +In contrast, when DocLint is invoked from \f[CB]javac\f[R], DocLint solely +relies on the various \f[CB]\-Xdoclint...\f[R] options to determine which +documentation comments to check. +.PP +DocLint doesn\[aq]t attempt to fix invalid input, it just reports it. +.PP +\f[I]Note:\f[R] DocLint doesn\[aq]t guarantee the completeness of these +checks. +In particular, it isn\[aq]t a full HTML compliance checker. +The goal is to just report common errors in a convenient manner. +.SS Groups +.PP +The checks performed by DocLint are organized into groups. +The warnings and errors in each group can be enabled or disabled with +command\-line options, or suppressed with \f[CB]\@SuppressWarnings\f[R] +annotations. +.PP +The groups are as follows: +.IP \[bu] 2 +\f[CB]accessibility\f[R] \-\-\- Checks for issues related to +accessibility. For example, no \f[CB]alt\f[R] attribute specified in an +\f[CB]<img>\f[R] element, or no caption or summary attributes specified in +a \f[CB]<table>\f[R] element. +.RS 2 +.PP +Issues are reported as errors if a downstream validation tool might be +expected to report an error in the files generated by \f[CB]javadoc\f[R]. +.PP +For reference, see the \f[B]Web Content Accessibility Guidelines\f[R] +[https://www.w3.org/WAI/standards\-guidelines/wcag/]. +.RE +.IP \[bu] 2 +\f[CB]html\f[R] \-\-\- Detects common high\-level HTML issues. For +example, putting block elements inside inline elements, or not closing +elements that require an end tag. +.RS 2 +.PP +Issues are reported as errors if a downstream validation tool might be +expected to report an error in the files generated by \f[CB]javadoc\f[R]. +.PP +For reference, see the \f[B]HTML Living Standard\f[R] +[https://html.spec.whatwg.org/multipage/]. +.RE +.IP \[bu] 2 +\f[CB]missing\f[R] \-\-\- Checks for missing documentation comments or +tags. For example, a missing comment on a class declaration, or a +missing \f[CB]\@param\f[R] or \f[CB]\@return\f[R] tag in the comment for a +method declaration. +.RS 2 +.PP +Issues related to missing items are typically reported as warnings +because they are unlikely to be reported as errors by downstream +validation tools that may be used to check the output generated by +\f[CB]javadoc\f[R]. +.RE +.IP \[bu] 2 +\f[CB]reference\f[R] \-\-\- Checks for issues relating to the references +to Java API elements from documentation comment tags. For example, the +reference in \f[CB]\@see\f[R] or \f[CB]{\@link\ ...}\f[R] cannot be found, +or a bad name is given for \f[CB]\@param\f[R] or \f[CB]\@throws\f[R]. +.RS 2 +.PP +Issues are typically reported as errors because while the issue may not +cause problems in the generated files, the author has likely made a +mistake that will lead to incorrect or unexpected documentation. +.RE +.IP \[bu] 2 +\f[CB]syntax\f[R] \-\-\- Checks for low\-level syntactic issues in +documentation comments. For example, unescaped angle brackets +(\f[CB]<\f[R] and \f[CB]>\f[R]) and ampersands (\f[CB]&\f[R]) and invalid +documentation comment tags. +.RS 2 +.PP +Issues are typically reported as errors because the issues may lead to +incorrect or unexpected documentation. +.RE +.SS Suppressing Messages +.PP +DocLint checks for and recognizes two strings that may be present in the +arguments for an \f[CB]\@SuppressWarnings\f[R] annotation. +.IP \[bu] 2 +\f[CB]doclint\f[R] +.IP \[bu] 2 +\f[CB]doclint:\f[R]\f[I]LIST\f[R] +.PP +where \f[I]LIST\f[R] is a comma\-separated list of one or more of +\f[CB]accessibility\f[R], \f[CB]html\f[R], \f[CB]missing\f[R], +\f[CB]syntax\f[R], \f[CB]reference\f[R]. +.PP +The names in \f[I]LIST\f[R] are the same \f[B]group\f[R] names supported +by the command\-line \f[CB]\-Xdoclint\f[R] option for \f[CB]javac\f[R] and +\f[CB]javadoc\f[R]. +(This is the same convention honored by the \f[CB]javac\f[R] +\f[CB]\-Xlint\f[R] option and the corresponding names supported by +\f[CB]\@SuppressWarnings\f[R].) +.PP +The names in \f[I]LIST\f[R] can equivalently be specified in separate +arguments of the annotation. +For example, the following are equivalent: +.IP \[bu] 2 +\f[CB]\@SuppressWarnings("doclint:accessibility,missing")\f[R] +.IP \[bu] 2 +\f[CB]\@SuppressWarnings("doclint:accessibility",\ "doclint:missing")\f[R] +.PP +When DocLint detects an issue in a documentation comment, it checks for +the presence of \f[CB]\@SuppressWarnings\f[R] on the associated +declaration and on all lexically enclosing declarations. +The issue will be ignored if any such annotation is found containing the +simple string \f[CB]doclint\f[R] or the longer form \f[CB]doclint:LIST\f[R] +where \f[I]LIST\f[R] contains the name of the group for the issue. +.PP +\f[I]Note:\f[R] as with other uses of \f[CB]\@SuppressWarnings\f[R], using +the annotation on a module or package declaration only affects that +declaration; it does not affect the contents of the module or package in +other source files. +.PP +All messages related to an issue are suppressed by the presence of an +appropriate \f[CB]\@SuppressWarnings\f[R] annotation: this includes errors +as well as warnings. +.PP +\f[I]Note:\f[R] It is only possible to \f[I]suppress\f[R] messages. +If an annotation of \f[CB]\@SuppressWarnings("doclint")\f[R] is given on a +top\-level declaration, all DocLint messages for that declaration and +any enclosed declarations will be suppressed; it is not possible to +selectively re\-enable messages for issues in enclosed declarations. +.SS Comparison with downstream validation tools +.PP +DocLint is a utility built into \f[CB]javac\f[R] and \f[CB]javadoc\f[R] that +checks the content of documentation comments, as found in source files. +In contrast, downstream validation tools can be used to validate the +output generated from those documentation comments by \f[CB]javadoc\f[R] +and the Standard Doclet. +.PP +Although there is some overlap in functionality, the two mechanisms are +different and each has its own strengths and weaknesses. +.IP \[bu] 2 +Downstream validation tools can check the end result of any generated +documentation, as it will be seen by the end user. +This includes content from all sources, including documentation +comments, the Standard Doclet itself, user\-provided taglets, and +content supplied via command\-line options. +Because such tools are analyzing complete HTML pages, they can do more +complete checks than can DocLint. +However, when a problem is found in the generated pages, it can be +harder to track down exactly where in the build pipeline the problem +needs to be fixed. +.IP \[bu] 2 +DocLint checks the content of documentation comments, in source files. +This makes it very easy to identify the exact position of any issues +that may be found. +DocLint can also detect some semantic errors in documentation comments +that downstream tools cannot detect, such as missing comments, using an +\f[CB]\@return\f[R] tag in a method returning \f[CB]void\f[R], or an +\f[CB]\@param\f[R] tag describing a non\-existent parameter. +But by its nature, DocLint cannot report on problems such as missing +links, or errors in user\-provided custom taglets, or problems in the +Standard Doclet itself. +It also cannot reliably detect errors in documentation comments at the +boundaries between content in a documentation comment and content +generated by a custom taglet. diff --git a/src/jdk.jcmd/share/man/jcmd.1 b/src/jdk.jcmd/share/man/jcmd.1 index a5f16e6a82d25b7939e56ab608d17a1a40ef3a7b..9d8288be42c98958a792a3b5012c19d426c75521 100644 --- a/src/jdk.jcmd/share/man/jcmd.1 +++ b/src/jdk.jcmd/share/man/jcmd.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JCMD" "1" "2021" "JDK 18\-ea" "JDK Commands" +.TH "JCMD" "1" "2022" "JDK 19\-ea" "JDK Commands" .hy .SH NAME .PP @@ -596,8 +596,8 @@ To list available options, use the \f[CB]JAVA_HOME\f[R]/bin/jfr tool. .IP \[bu] 2 \f[CB]event\-setting\f[R]: (Optional) Specifies the event setting value to modify. -Use the form: #= To add a new event setting, prefix the event name with -\[aq]+\[aq]. +Use the form: \f[CB]<event\-name>#<setting\-name>=<value>\f[R] To add a +new event setting, prefix the event name with \[aq]+\[aq]. .PP You can specify values for multiple event settings and .jfc options by separating them with a whitespace. @@ -1077,10 +1077,6 @@ detail comparison against previous baseline, which shows the memory allocation activities at different callsites. (BOOLEAN, false) .IP \[bu] 2 -\f[CB]shutdown\f[R]: (Optional) Requests runtime to shutdown itself and -free the memory used by runtime. -(BOOLEAN, false) -.IP \[bu] 2 \f[CB]statistics\f[R]: (Optional) Prints tracker statistics for tuning purpose. (BOOLEAN, false) diff --git a/src/jdk.jcmd/share/man/jinfo.1 b/src/jdk.jcmd/share/man/jinfo.1 index 30de6c169247c81e4017bd129ad35ed3b713fca3..40cf79d2b6ecd26de8b6ae740d83615232e872c2 100644 --- a/src/jdk.jcmd/share/man/jinfo.1 +++ b/src/jdk.jcmd/share/man/jinfo.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JINFO" "1" "2021" "JDK 18\-ea" "JDK Commands" +.TH "JINFO" "1" "2022" "JDK 19\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jcmd/share/man/jmap.1 b/src/jdk.jcmd/share/man/jmap.1 index 82e16d0ae2091bc1ec1fb5c3a5768fa0ac63a249..d29f8e84cfede203c73ef516b3039a26695ff1ba 100644 --- a/src/jdk.jcmd/share/man/jmap.1 +++ b/src/jdk.jcmd/share/man/jmap.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JMAP" "1" "2021" "JDK 18\-ea" "JDK Commands" +.TH "JMAP" "1" "2022" "JDK 19\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jcmd/share/man/jps.1 b/src/jdk.jcmd/share/man/jps.1 index a6d10fe911afe0b289b8cd83a1cdd2ee11fb7be5..a442c4665fbcc4d2862ab936a4b96ab21bdf855d 100644 --- a/src/jdk.jcmd/share/man/jps.1 +++ b/src/jdk.jcmd/share/man/jps.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JPS" "1" "2021" "JDK 18\-ea" "JDK Commands" +.TH "JPS" "1" "2022" "JDK 19\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jcmd/share/man/jstack.1 b/src/jdk.jcmd/share/man/jstack.1 index 302b9e5c24ab799cf56be7a33197231c2e159dc8..80674a67552c021ce8708acffe057695a61cf32b 100644 --- a/src/jdk.jcmd/share/man/jstack.1 +++ b/src/jdk.jcmd/share/man/jstack.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JSTACK" "1" "2021" "JDK 18\-ea" "JDK Commands" +.TH "JSTACK" "1" "2022" "JDK 19\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jcmd/share/man/jstat.1 b/src/jdk.jcmd/share/man/jstat.1 index 9996833ece9c06c6c54683e19f33bd7a79a023b4..f235acf0c116a8a90751d74037a285d4fb0215a8 100644 --- a/src/jdk.jcmd/share/man/jstat.1 +++ b/src/jdk.jcmd/share/man/jstat.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JSTAT" "1" "2021" "JDK 18\-ea" "JDK Commands" +.TH "JSTAT" "1" "2022" "JDK 19\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jconsole/share/classes/sun/tools/jconsole/SummaryTab.java b/src/jdk.jconsole/share/classes/sun/tools/jconsole/SummaryTab.java index f70f1b1f35895391c2eb76424df5350ab21464cd..3168665cfc0f99185ea98516f69746ac40f47e9c 100644 --- a/src/jdk.jconsole/share/classes/sun/tools/jconsole/SummaryTab.java +++ b/src/jdk.jconsole/share/classes/sun/tools/jconsole/SummaryTab.java @@ -113,6 +113,7 @@ class SummaryTab extends Tab { StringBuilder buf; + @SuppressWarnings("deprecation") synchronized Result formatSummary() { Result result = new Result(); ProxyClient proxyClient = vmPanel.getProxyClient(); diff --git a/src/jdk.jconsole/share/man/jconsole.1 b/src/jdk.jconsole/share/man/jconsole.1 index f9e29abb1acd76d171aea8ed68d7a1249a3e5203..a32e6d0d447de86c12479365b274869b0866f68b 100644 --- a/src/jdk.jconsole/share/man/jconsole.1 +++ b/src/jdk.jconsole/share/man/jconsole.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JCONSOLE" "1" "2021" "JDK 18\-ea" "JDK Commands" +.TH "JCONSOLE" "1" "2022" "JDK 19\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java index 1c4df796279f39f7c64e86360fbb37de45115996..b03c175da240f715188fbab10ad35413c23e8ce6 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java @@ -356,7 +356,8 @@ public class ClassFileReader implements Closeable { protected ClassFile readClassFile(JarFile jarfile, JarEntry e) throws IOException { try (InputStream is = jarfile.getInputStream(e)) { ClassFile cf = ClassFile.read(is); - if (jarfile.isMultiRelease()) { + // exclude module-info.class since this jarFile is on classpath + if (jarfile.isMultiRelease() && !cf.getName().equals("module-info")) { VersionHelper.add(jarfile, e, cf); } return cf; @@ -437,5 +438,4 @@ public class ClassFileReader implements Closeable { throw new UnsupportedOperationException("Not supported yet."); } } - private static final String MODULE_INFO = "module-info.class"; } diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/DependencyFinder.java b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/DependencyFinder.java index 514e2ef607a12b5f0e43c1b482aef8bd2534288a..d9a07700134adb5d06f4d5cd3d8910e5f32b91d7 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/DependencyFinder.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/DependencyFinder.java @@ -268,7 +268,14 @@ class DependencyFinder { } return targets; } catch (InterruptedException|ExecutionException e) { - throw new Error(e); + Throwable cause = e.getCause(); + if (cause instanceof RuntimeException x) { + throw x; + } else if (cause instanceof Error x) { + throw x; + } else { + throw new Error(e); + } } } diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/MultiReleaseException.java b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/MultiReleaseException.java index 0341923f926ef37432af4fdc3b1675050ae7f48a..0943287b93398807b67bcc9a8bc9f61f77aac0f3 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/MultiReleaseException.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/MultiReleaseException.java @@ -47,7 +47,7 @@ class MultiReleaseException extends RuntimeException { * The detail message array */ public MultiReleaseException(String key, Object... params) { - super(); + super(JdepsTask.getMessage(key, params)); this.key = key; this.params = params; } diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/VersionHelper.java b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/VersionHelper.java index 9ff358a63d38d873cfd879816566fc85894f3057..227c9ccd264db332f19f3f3eeedfbe5c0172d3a0 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/VersionHelper.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/VersionHelper.java @@ -55,15 +55,10 @@ public class VersionHelper { String version = realName.substring(len, n); assert (Integer.parseInt(version) > 8); String name = cf.getName().replace('/', '.'); - if (nameToVersion.containsKey(name)) { - if (!version.equals(nameToVersion.get(name))) { - throw new MultiReleaseException( - "err.multirelease.version.associated", - name, nameToVersion.get(name), version - ); - } - } else { - nameToVersion.put(name, version); + String v = nameToVersion.computeIfAbsent(name, _n -> version); + if (!version.equals(v)) { + throw new MultiReleaseException("err.multirelease.version.associated", + name, nameToVersion.get(name), version); } } else { throw new MultiReleaseException("err.multirelease.jar.malformed", diff --git a/src/jdk.jdeps/share/man/javap.1 b/src/jdk.jdeps/share/man/javap.1 index 02fc77a0e158b23979597fa133341159ef1f8c1e..c63d7a3a82dfd27f6113a58bf6250d12cd65b2b4 100644 --- a/src/jdk.jdeps/share/man/javap.1 +++ b/src/jdk.jdeps/share/man/javap.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JAVAP" "1" "2021" "JDK 18\-ea" "JDK Commands" +.TH "JAVAP" "1" "2022" "JDK 19\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jdeps/share/man/jdeprscan.1 b/src/jdk.jdeps/share/man/jdeprscan.1 index 109e97890ef8db3aa2763d620b2fb31b666b42be..d168901b5bcddb4546f1699136689698961232ae 100644 --- a/src/jdk.jdeps/share/man/jdeprscan.1 +++ b/src/jdk.jdeps/share/man/jdeprscan.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JDEPRSCAN" "1" "2021" "JDK 18\-ea" "JDK Commands" +.TH "JDEPRSCAN" "1" "2022" "JDK 19\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jdeps/share/man/jdeps.1 b/src/jdk.jdeps/share/man/jdeps.1 index 110a314af733229080239c34e5908860ebbe0fdd..e8cb14c460afc4290d0681938bb1e1633d1668e9 100644 --- a/src/jdk.jdeps/share/man/jdeps.1 +++ b/src/jdk.jdeps/share/man/jdeps.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JDEPS" "1" "2021" "JDK 18\-ea" "JDK Commands" +.TH "JDEPS" "1" "2022" "JDK 19\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jdi/share/man/jdb.1 b/src/jdk.jdi/share/man/jdb.1 index dfac04e3e275051c942a886236d5d05b0e2fd21d..fb6f04f5c12065f14d92967fff5cc1f6240836e3 100644 --- a/src/jdk.jdi/share/man/jdb.1 +++ b/src/jdk.jdi/share/man/jdb.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JDB" "1" "2021" "JDK 18\-ea" "JDK Commands" +.TH "JDB" "1" "2022" "JDK 19\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jdwp.agent/share/native/libjdwp/ArrayTypeImpl.c b/src/jdk.jdwp.agent/share/native/libjdwp/ArrayTypeImpl.c index c1631c2993827561caa50839896fdfbd53879afe..4176f0171d24228c7ee684a68ed099f6d49f18c9 100644 --- a/src/jdk.jdwp.agent/share/native/libjdwp/ArrayTypeImpl.c +++ b/src/jdk.jdwp.agent/share/native/libjdwp/ArrayTypeImpl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -227,7 +227,7 @@ newInstance(PacketInputStream *in, PacketOutputStream *out) error = classSignature(arrayClass, &signature, NULL); if ( error != JVMTI_ERROR_NONE ) { outStream_setError(out, map2jdwpError(error)); - return JNI_FALSE; + return JNI_TRUE; } componentSignature = componentTypeSignature(signature); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/EventType.java b/src/jdk.jfr/share/classes/jdk/jfr/EventType.java index 27bb9825abd6dfb8070b64e61597472e1feed478..46145ef2e8b60d370cf942f332f6dbb541a0d264 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/EventType.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/EventType.java @@ -241,4 +241,9 @@ public final class EventType { PlatformEventType getPlatformEventType() { return platformEventType; } + + // package private + boolean isVisible() { + return platformEventType.isVisible(); + } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorderPermission.java b/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorderPermission.java index 789fa18fdb3008e82fdc1082b569d711ff1a0700..7b89ddf02c8b547bea2c8f75fc1a1fe850bdb7fc 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorderPermission.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorderPermission.java @@ -203,6 +203,11 @@ public final class FlightRecorderPermission extends java.security.BasicPermissio public EventSettings newEventSettings(EventSettingsModifier esm) { return new EventSettings.DelegatedEventSettings(esm); } + + @Override + public boolean isVisible(EventType t) { + return t.isVisible(); + } } /** diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/ChunkInputStream.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/ChunkInputStream.java index a5e1d01783f2ae988db772f0eee6b4965ea3a3ed..5b192443980606cf7a2c70e110fa9f11fe29e16b 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/ChunkInputStream.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/ChunkInputStream.java @@ -112,7 +112,7 @@ final class ChunkInputStream extends InputStream { } @Override - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { super.finalize(); close(); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/ChunksChannel.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/ChunksChannel.java index 1139536c93876f8fa49ed46a625e2b07d057b49a..b606105d29e5506006508b0a6ce05b9712874795 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/ChunksChannel.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/ChunksChannel.java @@ -137,7 +137,7 @@ final class ChunksChannel implements ReadableByteChannel { } @Override - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { super.finalize(); close(); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventControl.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventControl.java index 6a89ce02d1e00ba0d21ac72d19b05113306b8a95..b0fdce2d6c92114d149835e58cd17e14598046af 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventControl.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventControl.java @@ -292,7 +292,7 @@ public final class EventControl { } ActiveSettingEvent event = ActiveSettingEvent.EVENT.get(); for (NamedControl nc : namedControls) { - if (Utils.isSettingVisible(nc.control, type.hasEventHook())) { + if (Utils.isSettingVisible(nc.control, type.hasEventHook()) && type.isVisible()) { String value = nc.control.getLastValue(); if (value == null) { value = nc.control.getDefaultValue(); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java index b5aff49cbe070aa3afb8a5fe5815e3dc50c8e3de..ff84b31b0cda7922fec0a6bfce783fe8efad4ad9 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java @@ -473,13 +473,26 @@ public final class JVM { public native void flush(); /** - * Sets the location of the disk repository, to be used at an emergency - * dump. + * Sets the location of the disk repository. * * @param dirText */ public native void setRepositoryLocation(String dirText); + /** + * Sets the path to emergency dump. + * + * @param dumpPathText + */ + public native void setDumpPath(String dumpPathText); + + /** + * Gets the path to emergency dump. + * + * @return The path to emergency dump. + */ + public native String getDumpPath(); + /** * Access to VM termination support. * diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/JVMUpcalls.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/JVMUpcalls.java index 2e4e4c95a3f30dff520c97cd8a1f4bfbc9bc3d53..be1dab301b785ad0f4b161fce1437942e328d06c 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/JVMUpcalls.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/JVMUpcalls.java @@ -125,14 +125,22 @@ final class JVMUpcalls { } } + /** + * Called by the JVM to ensure metadata for internal events/types become public. + * + * Must be called after metadata repository has been initialized (JFR created). + * + */ + static void unhideInternalTypes() { + MetadataRepository.unhideInternalTypes(); + } + /** * Called by the JVM to create the recorder thread. * - * @param systemThreadGroup - * the system thread group + * @param systemThreadGroup the system thread group * - * @param contextClassLoader - * the context class loader. + * @param contextClassLoader the context class loader. * * @return a new thread */ diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataLoader.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataLoader.java index ef9c22556f2410536044376306956e7143d89dfc..552b070527e84334a8caffa8cfa6de8f11545c6e 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataLoader.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataLoader.java @@ -53,7 +53,8 @@ public final class MetadataLoader { // Caching to reduce allocation pressure and heap usage private final AnnotationElement RELATIONAL = new AnnotationElement(Relational.class); - private final AnnotationElement ENABLED = new AnnotationElement(Enabled.class, false); + private final AnnotationElement ENABLED = new AnnotationElement(Enabled.class, true); + private final AnnotationElement DISABLED = new AnnotationElement(Enabled.class, false); private final AnnotationElement THRESHOLD = new AnnotationElement(Threshold.class, "0 ns"); private final AnnotationElement STACK_TRACE = new AnnotationElement(StackTrace.class, true); private final AnnotationElement TRANSITION_TO = new AnnotationElement(TransitionTo.class); @@ -82,6 +83,7 @@ public final class MetadataLoader { private final boolean isEvent; private final boolean isRelation; private final boolean experimental; + private final boolean internal; private final long id; public TypeElement(DataInputStream dis) throws IOException { @@ -101,6 +103,7 @@ public final class MetadataLoader { cutoff = dis.readBoolean(); throttle = dis.readBoolean(); experimental = dis.readBoolean(); + internal = dis.readBoolean(); id = dis.readLong(); isEvent = dis.readBoolean(); isRelation = dis.readBoolean(); @@ -315,7 +318,11 @@ public final class MetadataLoader { } Type type; if (t.isEvent) { - aes.add(ENABLED); + if (t.internal) { + aes.add(ENABLED); + } else { + aes.add(DISABLED); + } type = new PlatformEventType(t.name, t.id, false, true); } else { type = knownTypeMap.get(t.name); @@ -328,6 +335,15 @@ public final class MetadataLoader { } } } + if (t.internal) { + type.setInternal(true); + // Internal types are hidden by default + type.setVisible(false); + // Internal events are enabled by default + if (type instanceof PlatformEventType pe) { + pe.setEnabled(true); + } + } type.setAnnotations(aes); typeMap.put(t.name, type); } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataReader.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataReader.java index ca5c5c31ecd40ccf0363d311b47f49d665e2867f..91d243402aa35bd6b3766c1ec5f490624184120c 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataReader.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,7 @@ import static jdk.jfr.internal.MetadataDescriptor.ELEMENT_TYPE; import java.io.DataInput; import java.io.IOException; import java.util.ArrayList; -import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -84,7 +84,7 @@ final class MetadataReader { descriptor.root = root; if (Logger.shouldLog(LogTag.JFR_SYSTEM_PARSER, LogLevel.TRACE)) { List<Type> ts = new ArrayList<>(types.values()); - Collections.sort(ts, (x,y) -> x.getName().compareTo(y.getName())); + ts.sort(Comparator.comparing(Type::getName)); for (Type t : ts) { t.log("Found", LogTag.JFR_SYSTEM_PARSER, LogLevel.TRACE); } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java index 0c798b8b28eca3f1439661ede8f5be5e4d035de1..5a6e12989f903b59cd1860a174484f77b9438226 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java @@ -34,6 +34,7 @@ import java.io.IOException; import java.time.Instant; import java.util.ArrayList; import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -71,7 +72,7 @@ public final class MetadataRepository { private void initializeJVMEventTypes() { List<RequestHook> requestHooks = new ArrayList<>(); - for (Type type : typeLibrary.getTypes()) { + for (Type type : new ArrayList<>(typeLibrary.getTypes())) { if (type instanceof PlatformEventType pEventType) { EventType eventType = PrivateAccess.getInstance().newEventType(pEventType); pEventType.setHasDuration(eventType.getAnnotation(Threshold.class) != null); @@ -106,7 +107,11 @@ public final class MetadataRepository { eventTypes.add(h.getEventType()); } } - eventTypes.addAll(nativeEventTypes); + for (EventType t : nativeEventTypes) { + if (PrivateAccess.getInstance().isVisible(t)) { + eventTypes.add(t); + } + } return eventTypes; } @@ -243,7 +248,13 @@ public final class MetadataRepository { ByteArrayOutputStream baos = new ByteArrayOutputStream(40000); DataOutputStream daos = new DataOutputStream(baos); try { - List<Type> types = typeLibrary.getTypes(); + List<Type> types = typeLibrary.getVisibleTypes(); + if (Logger.shouldLog(LogTag.JFR_METADATA, LogLevel.DEBUG)) { + Collections.sort(types,Comparator.comparing(Type::getName)); + for (Type t: types) { + Logger.log(LogTag.JFR_METADATA, LogLevel.INFO, "Serialized type: " + t.getName() + " id=" + t.getId()); + } + } Collections.sort(types); MetadataDescriptor.write(types, daos); daos.flush(); @@ -349,4 +360,20 @@ public final class MetadataRepository { jvm.flush(); } + static void unhideInternalTypes() { + for (Type t : TypeLibrary.getInstance().getTypes()) { + if (t.isInternal()) { + t.setVisible(true); + Logger.log(LogTag.JFR_METADATA, LogLevel.DEBUG, "Unhiding internal type " + t.getName()); + } + } + // Singleton should have been initialized here. + // It's not possible to call MetadataRepository().getInstance(), + // because it will deadlock with Java thread calling flush() or setOutput(); + instance.storeDescriptorInJVM(); + } + + public synchronized List<Type> getVisibleTypes() { + return typeLibrary.getVisibleTypes(); + } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/Options.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/Options.java index 4d430bebba2c4e3c92b265eaf03182a01e6d1bf6..204badc4242ec74e7564c57a63920f73b9af352c 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/Options.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/Options.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,16 @@ package jdk.jfr.internal; +import java.io.IOException; + +import jdk.jfr.internal.LogLevel; +import jdk.jfr.internal.LogTag; +import jdk.jfr.internal.Logger; import jdk.jfr.internal.SecuritySupport.SafePath; import jdk.internal.misc.Unsafe; +import static java.nio.file.LinkOption.*; + /** * Options that control Flight Recorder. * @@ -48,7 +55,7 @@ public final class Options { private static final int DEFAULT_STACK_DEPTH = 64; private static final boolean DEFAULT_SAMPLE_THREADS = true; private static final long DEFAULT_MAX_CHUNK_SIZE = 12 * 1024 * 1024; - private static final SafePath DEFAULT_DUMP_PATH = SecuritySupport.USER_HOME; + private static final SafePath DEFAULT_DUMP_PATH = null; private static long memorySize; private static long globalBufferSize; @@ -57,7 +64,6 @@ public final class Options { private static int stackDepth; private static boolean sampleThreads; private static long maxChunkSize; - private static SafePath dumpPath; static { final long pageSize = Unsafe.getUnsafe().pageSize(); @@ -113,12 +119,19 @@ public final class Options { globalBufferSize = globalBufsize; } - public static synchronized void setDumpPath(SafePath path) { - dumpPath = path; + public static synchronized void setDumpPath(SafePath path) throws IOException { + if (path != null) { + if (SecuritySupport.isWritable(path)) { + path = SecuritySupport.toRealPath(path, NOFOLLOW_LINKS); + } else { + throw new IOException("Cannot write JFR emergency dump to " + path.toString()); + } + } + jvm.setDumpPath(path == null ? null : path.toString()); } public static synchronized SafePath getDumpPath() { - return dumpPath; + return new SafePath(jvm.getDumpPath()); } public static synchronized void setStackDepth(Integer stackTraceDepth) { @@ -144,7 +157,11 @@ public final class Options { setMemorySize(DEFAULT_MEMORY_SIZE); setGlobalBufferSize(DEFAULT_GLOBAL_BUFFER_SIZE); setGlobalBufferCount(DEFAULT_GLOBAL_BUFFER_COUNT); - setDumpPath(DEFAULT_DUMP_PATH); + try { + setDumpPath(DEFAULT_DUMP_PATH); + } catch (IOException e) { + // Ignore (depends on default value in JVM: it would be NULL) + } setSampleThreads(DEFAULT_SAMPLE_THREADS); setStackDepth(DEFAULT_STACK_DEPTH); setThreadBufferSize(DEFAULT_THREAD_BUFFER_SIZE); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java index ef1d51a06228e03d35edcfcf178c10dbdac4bc65..63a4840618faaa629b130d7baed90f77c5979be9 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java @@ -36,7 +36,6 @@ import java.security.AccessControlContext; import java.security.AccessController; import java.time.Duration; import java.time.Instant; -import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -437,7 +436,7 @@ public final class PlatformRecorder { } // n*log(n), should be able to do n*log(k) with a priority queue, // where k = number of recordings, n = number of chunks - Collections.sort(chunks, RepositoryChunk.END_TIME_COMPARATOR); + chunks.sort(RepositoryChunk.END_TIME_COMPARATOR); return chunks; } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/PrivateAccess.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/PrivateAccess.java index def05bba4c985843d3ff9e1dcc545e99605e2e08..09d53b4b5620b374376fed7c658956ac3deb30c6 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/PrivateAccess.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/PrivateAccess.java @@ -103,4 +103,6 @@ public abstract class PrivateAccess { public abstract AccessControlContext getContext(SettingControl sc); public abstract EventSettings newEventSettings(EventSettingsModifier esm); + + public abstract boolean isVisible(EventType t); } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/RepositoryChunk.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/RepositoryChunk.java index af5ff3e08e4e1a3bce09c5bfe43c4b8709da4e49..8cb8bd85c3791ebd9e7686b6c6151047607d4db2 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/RepositoryChunk.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/RepositoryChunk.java @@ -134,7 +134,7 @@ final class RepositoryChunk { } @Override - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() { boolean destroy = false; synchronized (this) { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/RequestEngine.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/RequestEngine.java index 49aa2bcd3f24676400ce81b27564f36ecb254c17..ff728fbf4f2a7d8eedf87047d4b8e8c097627054 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/RequestEngine.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/RequestEngine.java @@ -28,7 +28,6 @@ package jdk.jfr.internal; import java.security.AccessControlContext; import java.security.AccessController; import java.security.PrivilegedAction; -import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; @@ -162,10 +161,8 @@ public final class RequestEngine { // Only to be used for JVM events. No access control contest // or check if hook already exists static void addHooks(List<RequestHook> newEntries) { - List<RequestHook> addEntries = new ArrayList<>(); for (RequestHook rh : newEntries) { rh.type.setEventHook(true); - addEntries.add(rh); logHook("Added", rh.type); } entries.addAll(newEntries); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/SecuritySupport.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/SecuritySupport.java index d761eb98c58c548021ade6d1dfdd05613304b459..ae03bce313d85b1c99e26dba720ff8652ebd87cd 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/SecuritySupport.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/SecuritySupport.java @@ -41,6 +41,7 @@ import java.nio.channels.ReadableByteChannel; import java.nio.file.DirectoryStream; import java.nio.file.FileVisitResult; import java.nio.file.Files; +import java.nio.file.LinkOption; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; @@ -77,7 +78,6 @@ public final class SecuritySupport { private static final Module JFR_MODULE = Event.class.getModule(); public static final SafePath JFC_DIRECTORY = getPathInProperty("java.home", "lib/jfr"); public static final FileAccess PRIVILEGED = new Privileged(); - static final SafePath USER_HOME = getPathInProperty("user.home", null); static final SafePath JAVA_IO_TMPDIR = getPathInProperty("java.io.tmpdir", null); static { @@ -365,8 +365,8 @@ public final class SecuritySupport { doPriviligedIO(() -> Files.walkFileTree(safePath.toPath(), new DirectoryCleaner())); } - static SafePath toRealPath(SafePath safePath) throws IOException { - return new SafePath(doPrivilegedIOWithReturn(() -> safePath.toPath().toRealPath())); + static SafePath toRealPath(SafePath safePath, LinkOption... options) throws IOException { + return new SafePath(doPrivilegedIOWithReturn(() -> safePath.toPath().toRealPath(options))); } static boolean existDirectory(SafePath directory) throws IOException { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/SettingsManager.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/SettingsManager.java index db239b980e504b94ae55bfdc0e6dad37d70c3cee..d6078ef9f985e637580804bf852ef54ec18bfdd1 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/SettingsManager.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/SettingsManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ package jdk.jfr.internal; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; @@ -140,7 +140,7 @@ final class SettingsManager { } } else { if (Logger.shouldLog(LogTag.JFR_SETTING, LogLevel.INFO)) { - Collections.sort(eventControls, (x,y) -> x.getEventType().getName().compareTo(y.getEventType().getName())); + eventControls.sort(Comparator.comparing(x -> x.getEventType().getName())); } for (EventControl ec : eventControls) { setEventControl(ec); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/Type.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/Type.java index 9b6891bcdec515acb376d0bb14a6e0c08b61af4e..27938ed023c30678d5dd9a19449827481082e08e 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/Type.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/Type.java @@ -89,6 +89,8 @@ public class Type implements Comparable<Type> { private Boolean simpleType; // calculated lazy private boolean remove = true; private long id; + private boolean visible = true; + private boolean internal; /** * Creates a type @@ -337,4 +339,20 @@ public class Type implements Comparable<Type> { public void setId(long id) { this.id = id; } + + public void setVisible(boolean visible) { + this.visible = visible; + } + + public boolean isVisible() { + return visible; + } + + public void setInternal(boolean internal) { + this.internal = internal; + } + + public boolean isInternal() { + return internal; + } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/TypeLibrary.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/TypeLibrary.java index fb16c92f1716a1d9d8098fa9b16b09ba2ddbc769..1555bcc2aac660500288ecea18429f32defad535 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/TypeLibrary.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/TypeLibrary.java @@ -36,6 +36,7 @@ import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; @@ -108,7 +109,7 @@ public final class TypeLibrary { List<Type> jvmTypes; try { jvmTypes = MetadataLoader.createTypes(); - Collections.sort(jvmTypes, (a,b) -> Long.compare(a.getId(), b.getId())); + jvmTypes.sort(Comparator.comparingLong(Type::getId)); } catch (IOException e) { throw new Error("JFR: Could not read metadata"); } @@ -118,8 +119,19 @@ public final class TypeLibrary { } } - public List<Type> getTypes() { - return new ArrayList<>(types.values()); + public Collection<Type> getTypes() { + return types.values(); + } + + // Returned list should be mutable (for in-place sorting) + public List<Type> getVisibleTypes() { + List<Type> visible = new ArrayList<>(types.size()); + types.values().forEach(t -> { + if (t.isVisible()) { + visible.add(t); + } + }); + return visible; } public static Type createAnnotationType(Class<? extends Annotation> a) { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RepositoryFiles.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RepositoryFiles.java index 78bd18ddc7ad3beb8adcbd58d5b643f87da8981f..6ef88ecad375005f5dc99f0182dda52c64f8e0d3 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RepositoryFiles.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RepositoryFiles.java @@ -213,7 +213,7 @@ public final class RepositoryFiles { pathSet.remove(time); pathLookup.remove(remove); } - Collections.sort(added, (p1, p2) -> p1.compareTo(p2)); + Collections.sort(added); for (Path p : added) { // Only add files that have a complete header // as the JVM may be in progress writing the file diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/AbstractDCmd.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/AbstractDCmd.java index a6130b2ece704198453c49c51f475fc4f9bd19f5..b7fb23c940266639560d772f2bbbd1d735087d6b 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/AbstractDCmd.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/AbstractDCmd.java @@ -32,7 +32,6 @@ import java.nio.file.Paths; import java.time.Duration; import java.time.LocalDateTime; import java.util.ArrayList; -import java.util.Collections; import java.util.Comparator; import java.util.List; @@ -169,7 +168,7 @@ abstract class AbstractDCmd { protected final List<Recording> getRecordings() { List<Recording> list = new ArrayList<>(getFlightRecorder().getRecordings()); - Collections.sort(list, Comparator.comparing(Recording::getId)); + list.sort(Comparator.comparingLong(Recording::getId)); return list; } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdCheck.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdCheck.java index ef32321120ba87b95d3111fd1aa81af6c62fad65..888ca4eda2ab2b593ec3ddd7c8f7de4e8bc41dcd 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdCheck.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdCheck.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,6 @@ package jdk.jfr.internal.dcmd; import java.time.Duration; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; @@ -135,12 +134,7 @@ final class DCmdCheck extends AbstractDCmd { private static List<EventType> sortByEventPath(Collection<EventType> events) { List<EventType> sorted = new ArrayList<>(); sorted.addAll(events); - Collections.sort(sorted, new Comparator<EventType>() { - @Override - public int compare(EventType e1, EventType e2) { - return e1.getName().compareTo(e2.getName()); - } - }); + sorted.sort(Comparator.comparing(EventType::getName)); return sorted; } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdConfigure.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdConfigure.java index 4cfc9ae4800a81d1d7102323f1fa692526b421b8..edcb153047419449e5ba28b15240e6832302d954 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdConfigure.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdConfigure.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ package jdk.jfr.internal.dcmd; - +import java.io.IOException; import jdk.jfr.FlightRecorder; import jdk.jfr.internal.LogLevel; @@ -106,7 +106,11 @@ final class DCmdConfigure extends AbstractDCmd { } if (dumpPath != null) { - Options.setDumpPath(new SafePath(dumpPath)); + try { + Options.setDumpPath(new SafePath(dumpPath)); + } catch (IOException e) { + throw new DCmdException("Could not set " + dumpPath + " to emergency dump path. " + e.getMessage(), e); + } Logger.log(LogTag.JFR, LogLevel.INFO, "Emergency dump path set to " + dumpPath); if (verbose) { printDumpPath(); @@ -183,6 +187,7 @@ final class DCmdConfigure extends AbstractDCmd { println("Current configuration:"); println(); printRepositoryPath(); + printDumpPath(); printStackDepth(); printGlobalBufferCount(); printGlobalBufferSize(); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/EventPrintWriter.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/EventPrintWriter.java index 9a393f30ee8c5c2ac630599ae19f1823b613bb18..a6c92761a57047e6d6d04aa93a4da4ae06e351ac 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/EventPrintWriter.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/EventPrintWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,6 @@ import java.io.IOException; import java.io.PrintWriter; import java.nio.file.Path; import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -77,7 +76,7 @@ abstract class EventPrintWriter extends StructuredWriter { events.add(event); } if (PRIVATE_ACCESS.isLastEventInChunk(file)) { - Collections.sort(events, PRIVATE_ACCESS.eventComparator()); + events.sort(PRIVATE_ACCESS.eventComparator()); print(events); events.clear(); } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Metadata.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Metadata.java index c72a34edfd0b78efa164fec72bcf8ff331aabdb6..c27bf935a2a487fe6fc05744ee8945e787a6ce23 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Metadata.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Metadata.java @@ -31,7 +31,6 @@ import java.io.PrintWriter; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; -import java.util.Collections; import java.util.Comparator; import java.util.Deque; import java.util.List; @@ -43,7 +42,7 @@ import jdk.jfr.consumer.RecordingFile; import jdk.jfr.internal.PlatformEventType; import jdk.jfr.internal.PrivateAccess; import jdk.jfr.internal.Type; -import jdk.jfr.internal.TypeLibrary; +import jdk.jfr.internal.MetadataRepository; import jdk.jfr.internal.consumer.JdkJfrConsumer; import static java.nio.charset.StandardCharsets.UTF_8; @@ -206,7 +205,7 @@ final class Metadata extends Command { } List<Type> types = findTypes(file); - Collections.sort(types, new TypeComparator()); + types.sort(new TypeComparator()); for (Type type : types) { if (filter != null) { // If --events or --categories, only operate on events @@ -231,7 +230,7 @@ final class Metadata extends Command { if (file == null) { // Force initialization FlightRecorder.getFlightRecorder().getEventTypes(); - return TypeLibrary.getInstance().getTypes(); + return MetadataRepository.getInstance().getVisibleTypes(); } try (RecordingFile rf = new RecordingFile(file)) { return PRIVATE_ACCESS.readTypes(rf); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/PrettyWriter.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/PrettyWriter.java index 32178df920c41c3ac022b4372b24e0fbf19151c7..c13bdb2ae2735458acba4d87e16fa73c13794e57 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/PrettyWriter.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/PrettyWriter.java @@ -59,7 +59,7 @@ import jdk.jfr.internal.Utils; */ public final class PrettyWriter extends EventPrintWriter { private static final String TYPE_OLD_OBJECT = Type.TYPES_PREFIX + "OldObject"; - private static final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ofPattern("HH:mm:ss.SSS (YYYY-MM-dd)"); + private static final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ofPattern("HH:mm:ss.SSS (yyyy-MM-dd)"); private static final Long ZERO = 0L; private boolean showIds; private RecordedEvent currentEvent; diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Summary.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Summary.java index 3375ec3f7a6a41d53b1a2634ba5dcc3fa5761461..767ccf63507857404f7407418589ff6fa00a8dd6 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Summary.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Summary.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,6 @@ import java.time.Instant; import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; import java.util.ArrayList; -import java.util.Collections; import java.util.Deque; import java.util.HashMap; import java.util.List; @@ -143,7 +142,7 @@ final class Summary extends Command { println(" Start: " + DATE_FORMAT.format(Instant.ofEpochSecond(epochSeconds, adjustNanos)) + " (UTC)"); println(" Duration: " + (totalDuration + 500_000_000) / 1_000_000_000 + " s"); List<Statistics> statsList = new ArrayList<>(stats.values()); - Collections.sort(statsList, (u, v) -> Long.compare(v.count, u.count)); + statsList.sort((u, v) -> Long.compare(v.count, u.count)); println(); String header = " Count Size (bytes) "; String typeHeader = " Event Type"; diff --git a/src/jdk.jfr/share/man/jfr.1 b/src/jdk.jfr/share/man/jfr.1 index 27e4e630dc1374c8c66f1649dc4da859f65e1a0c..321562e90b81b6d0c5932161c68413509d156a2e 100644 --- a/src/jdk.jfr/share/man/jfr.1 +++ b/src/jdk.jfr/share/man/jfr.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JFR" "1" "2021" "JDK 18\-ea" "JDK Commands" +.TH "JFR" "1" "2022" "JDK 19\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java index d90e4cf38e45c563564d56fbc99adfa3313d1fbe..835294d26de0d69cf63093dcb131546c65ad85da 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java @@ -78,7 +78,7 @@ import jdk.internal.module.ModuleResolution; * ## Should use jdk.joptsimple some day. */ public class JlinkTask { - static final boolean DEBUG = Boolean.getBoolean("jlink.debug"); + public static final boolean DEBUG = Boolean.getBoolean("jlink.debug"); // jlink API ignores by default. Remove when signing is implemented. static final boolean IGNORE_SIGNING_DEFAULT = true; diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/AbstractPlugin.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/AbstractPlugin.java index fd4fdcd39dda98474db2b7113cc53ab102c0b5e8..758cb17e83e6803ff81f71b4fab1182bdffd8441 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/AbstractPlugin.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/AbstractPlugin.java @@ -26,10 +26,16 @@ package jdk.tools.jlink.internal.plugins; import jdk.tools.jlink.plugin.Plugin; +import jdk.tools.jlink.internal.JlinkTask; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; import java.util.Locale; import java.util.MissingResourceException; import java.util.ResourceBundle; +import jdk.internal.org.objectweb.asm.ClassReader; public abstract class AbstractPlugin implements Plugin { @@ -61,6 +67,35 @@ public abstract class AbstractPlugin implements Plugin { this.name = name; this.pluginsBundle = bundle; } + + private void dumpClassFile(String path, byte[] buf) { + try { + String fullPath = String.format("%d-%s%s%s", + ProcessHandle.current().pid(), + getName(), File.separator, + path.replace('/', File.separatorChar)); + System.err.printf("Dumping class file %s\n", fullPath); + new File(fullPath.substring(0, fullPath.lastIndexOf('/'))).mkdirs(); + Files.write(Paths.get(fullPath), buf); + } catch (IOException ioExp) { + System.err.println("writing " + path + " failed"); + ioExp.printStackTrace(); + } + } + + protected ClassReader newClassReader(String path, byte[] buf) { + try { + return new ClassReader(buf); + } catch (IllegalArgumentException iae) { + if (JlinkTask.DEBUG) { + System.err.printf("Failed to parse class file: %s\n", path); + iae.printStackTrace(); + dumpClassFile(path, buf); + } + throw iae; + } + } + @Override public String getName() { return name; diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java index 17062af55f35fd9ce91945d2f978ac1cba030493..623b7f2917b0e450eb924c7d0c3d2c5d0a19c605 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java @@ -158,7 +158,7 @@ public final class IncludeLocalesPlugin extends AbstractPlugin implements Resour if (resource != null && resource.type().equals(ResourcePoolEntry.Type.CLASS_OR_RESOURCE)) { byte[] bytes = resource.contentBytes(); - ClassReader cr = new ClassReader(bytes); + ClassReader cr = newClassReader(path, bytes); if (Arrays.stream(cr.getInterfaces()) .anyMatch(i -> i.contains(METAINFONAME)) && stripUnsupportedLocales(bytes, cr)) { diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripJavaDebugAttributesPlugin.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripJavaDebugAttributesPlugin.java index c7c3979992122bb40905b84a3d97da2680a5cb0f..8e212f649c834000b05a011c46864df870261c36 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripJavaDebugAttributesPlugin.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripJavaDebugAttributesPlugin.java @@ -59,7 +59,7 @@ public final class StripJavaDebugAttributesPlugin extends AbstractPlugin { if (path.endsWith("module-info.class")) { // XXX. Do we have debug info? Is Asm ready for module-info? } else { - ClassReader reader = new ClassReader(resource.contentBytes()); + ClassReader reader = newClassReader(path, resource.contentBytes()); ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS); reader.accept(writer, ClassReader.SKIP_DEBUG); byte[] content = writer.toByteArray(); diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/VersionPropsPlugin.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/VersionPropsPlugin.java index 8c1c8374faf0305fb905e0b82200ee4b3e7316c0..af241efcea7b80a5ee1495f7c20b5748035d696a 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/VersionPropsPlugin.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/VersionPropsPlugin.java @@ -96,9 +96,9 @@ abstract class VersionPropsPlugin extends AbstractPlugin { private boolean redefined = false; - private byte[] redefine(byte[] classFile) { + private byte[] redefine(String path, byte[] classFile) { - var cr = new ClassReader(classFile); + var cr = newClassReader(path, classFile); var cw = new ClassWriter(0); cr.accept(new ClassVisitor(Opcodes.ASM7, cw) { @@ -189,7 +189,7 @@ abstract class VersionPropsPlugin extends AbstractPlugin { in.transformAndCopy(res -> { if (res.type().equals(ResourcePoolEntry.Type.CLASS_OR_RESOURCE)) { if (res.path().equals(VERSION_PROPS_CLASS)) { - return res.copyWithContent(redefine(res.contentBytes())); + return res.copyWithContent(redefine(res.path(), res.contentBytes())); } } return res; diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties index 958c43c2ca4c7754f2c26094452f9020241cf0e2..017c46baab02df2c3318ad7447b10f5c31a355dc 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties @@ -142,7 +142,8 @@ generate-cds-archive.description=\ CDS plugin: generate cds archives if the runtime image supports CDS feature.\n\ generate-cds-archive.usage=\ -\ --generate-cds-archive Generate CDS archives if the runtime image supports CDS feature. +\ --generate-cds-archive Generate CDS archive if the runtime image supports\n\ +\ the CDS feature. generate-jli-classes.argument=@filename diff --git a/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodOutputStream.java b/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodOutputStream.java index 5fae838a59e050a31236d8da5b2acc5fb6690d8c..895500291f9e2fe71cd84b00295e1b2c94414811 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodOutputStream.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodOutputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,6 +41,7 @@ import java.util.Set; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import jdk.internal.jmod.JmodFile; +import java.time.LocalDateTime; import static jdk.internal.jmod.JmodFile.*; @@ -54,15 +55,17 @@ class JmodOutputStream extends OutputStream implements AutoCloseable { * This method creates (or overrides, if exists) the JMOD file, * returning the the output stream to write to the JMOD file. */ - static JmodOutputStream newOutputStream(Path file) throws IOException { + static JmodOutputStream newOutputStream(Path file, LocalDateTime date) throws IOException { OutputStream out = Files.newOutputStream(file); BufferedOutputStream bos = new BufferedOutputStream(out); - return new JmodOutputStream(bos); + return new JmodOutputStream(bos, date); } private final ZipOutputStream zos; - private JmodOutputStream(OutputStream out) { + private final LocalDateTime date; + private JmodOutputStream(OutputStream out, LocalDateTime date) { this.zos = new ZipOutputStream(out); + this.date = date; try { JmodFile.writeMagicNumber(out); } catch (IOException e) { @@ -104,7 +107,11 @@ class JmodOutputStream extends OutputStream implements AutoCloseable { // sun.tools.jar.Main.update() ZipEntry e2 = new ZipEntry(e1.getName()); e2.setMethod(e1.getMethod()); - e2.setTime(e1.getTime()); + if (date != null) { + e2.setTimeLocal(date); + } else { + e2.setTime(e1.getTime()); + } e2.setComment(e1.getComment()); e2.setExtra(e1.getExtra()); if (e1.getMethod() == ZipEntry.STORED) { @@ -124,7 +131,11 @@ class JmodOutputStream extends OutputStream implements AutoCloseable { String name = Paths.get(prefix, path).toString() .replace(File.separatorChar, '/'); entries.get(section).add(path); - return new ZipEntry(name); + ZipEntry zipEntry = new ZipEntry(name); + if (date != null) { + zipEntry.setTimeLocal(date); + } + return zipEntry; } public boolean contains(Section section, String path) { diff --git a/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java b/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java index f4248bd16cef3dda6ba04a30ce3966e89ca3db3f..b440e536235e995b3370763e7f61f72d9a3417d3 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java @@ -62,6 +62,11 @@ import java.util.stream.Collectors; import java.util.zip.ZipEntry; import java.util.zip.ZipException; import java.util.zip.ZipFile; +import java.time.LocalDateTime; +import java.time.ZonedDateTime; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; import jdk.internal.jmod.JmodFile; import jdk.internal.jmod.JmodFile.Section; @@ -160,8 +165,13 @@ public class JmodTask { boolean dryrun; List<PathMatcher> excludes; Path extractDir; + LocalDateTime date; } + // Valid --date range + static final ZonedDateTime DATE_MIN = ZonedDateTime.parse("1980-01-01T00:00:02Z"); + static final ZonedDateTime DATE_MAX = ZonedDateTime.parse("2099-12-31T23:59:59Z"); + public int run(String[] args) { try { @@ -427,7 +437,7 @@ public class JmodTask { Path target = options.jmodFile; Path tempTarget = jmodTempFilePath(target); try { - try (JmodOutputStream jos = JmodOutputStream.newOutputStream(tempTarget)) { + try (JmodOutputStream jos = JmodOutputStream.newOutputStream(tempTarget, options.date)) { jmod.write(jos); } Files.move(tempTarget, target); @@ -984,7 +994,11 @@ public class JmodTask { if (e.getName().equals(MODULE_INFO)) { // what about module-info.class in versioned entries? ZipEntry ze = new ZipEntry(e.getName()); - ze.setTime(System.currentTimeMillis()); + if (options.date != null) { + ze.setTimeLocal(options.date); + } else { + ze.setTime(System.currentTimeMillis()); + } jos.putNextEntry(ze); recordHashes(in, jos, moduleHashes); jos.closeEntry(); @@ -1012,7 +1026,7 @@ public class JmodTask { { try (JmodFile jf = new JmodFile(target); - JmodOutputStream jos = JmodOutputStream.newOutputStream(tempTarget)) + JmodOutputStream jos = JmodOutputStream.newOutputStream(tempTarget, options.date)) { jf.stream().forEach(e -> { try (InputStream in = jf.getInputStream(e.section(), e.name())) { @@ -1147,6 +1161,26 @@ public class JmodTask { @Override public String valuePattern() { return "module-version"; } } + static class DateConverter implements ValueConverter<LocalDateTime> { + @Override + public LocalDateTime convert(String value) { + try { + ZonedDateTime date = ZonedDateTime.parse(value, DateTimeFormatter.ISO_ZONED_DATE_TIME) + .withZoneSameInstant(ZoneOffset.UTC); + if (date.isBefore(DATE_MIN) || date.isAfter(DATE_MAX)) { + throw new CommandException("err.date.out.of.range", value); + } + return date.toLocalDateTime(); + } catch (DateTimeParseException x) { + throw new CommandException("err.invalid.date", value, x.getMessage()); + } + } + + @Override public Class<LocalDateTime> valueType() { return LocalDateTime.class; } + + @Override public String valuePattern() { return "date"; } + } + static class WarnIfResolvedReasonConverter implements ValueConverter<ModuleResolution> { @@ -1382,6 +1416,11 @@ public class JmodTask { OptionSpec<Void> version = parser.accepts("version", getMessage("main.opt.version")); + OptionSpec<LocalDateTime> date + = parser.accepts("date", getMessage("main.opt.date")) + .withRequiredArg() + .withValuesConvertedBy(new DateConverter()); + NonOptionArgumentSpec<String> nonOptions = parser.nonOptions(); @@ -1425,6 +1464,8 @@ public class JmodTask { options.manPages = getLastElement(opts.valuesOf(manPages)); if (opts.has(legalNotices)) options.legalNotices = getLastElement(opts.valuesOf(legalNotices)); + if (opts.has(date)) + options.date = opts.valueOf(date); if (opts.has(modulePath)) { Path[] dirs = getLastElement(opts.valuesOf(modulePath)).toArray(new Path[0]); options.moduleFinder = ModulePath.of(Runtime.version(), true, dirs); diff --git a/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod.properties b/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod.properties index 09aa5ae44b3175b274a1727708f1f0c5d0a8a70f..c1022b0fb5e8e89b0e3ea1eb9385e908bf7a5db2 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod.properties +++ b/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -74,6 +74,9 @@ main.opt.hash-modules=Compute and record hashes to tie a packaged module\ main.opt.do-not-resolve-by-default=Exclude from the default root set of modules main.opt.warn-if-resolved=Hint for a tool to issue a warning if the module \ is resolved. One of deprecated, deprecated-for-removal, or incubating +main.opt.date=Date and time for the timestamps of entries, specified in ISO-8601\ +\ extended offset date-time with optional time-zone format, e.g.\ +\ "2022-02-12T12:30:00-05:00" main.opt.cmdfile=Read options from the specified file @@ -106,6 +109,8 @@ err.module.descriptor.not.found=Module descriptor not found err.missing.export.or.open.packages=Packages that are exported or open in {0} are not present: {1} err.module.resolution.fail=Resolution failed: {0} err.no.moduleToHash=No hashes recorded: no module matching {0} found to record hashes +err.invalid.date=--date {0} is not a valid ISO-8601 extended offset date-time with optional time-zone format: {1} +err.date.out.of.range=--date {0} is out of the valid range 1980-01-01T00:00:02Z to 2099-12-31T23:59:59Z warn.invalid.arg=Invalid classname or pathname not exist: {0} warn.no.module.hashes=No hashes recorded: no module specified for hashing depends on {0} warn.ignore.entry=ignoring entry {0}, in section {1} diff --git a/src/jdk.jlink/share/man/jlink.1 b/src/jdk.jlink/share/man/jlink.1 index f5324309efcfd1f7e867ebedc5f7c80f85174cf2..fbe660189431b54d4a6d39214303e6850497d896 100644 --- a/src/jdk.jlink/share/man/jlink.1 +++ b/src/jdk.jlink/share/man/jlink.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JLINK" "1" "2021" "JDK 18\-ea" "JDK Commands" +.TH "JLINK" "1" "2022" "JDK 19\-ea" "JDK Commands" .hy .SH NAME .PP @@ -294,6 +294,17 @@ Example: Strips debug information from the output image. .RS .RE +.SS Plugin \f[CB]generate\-cds\-archive\f[R] +.TP +.B Options +\f[CB]\-\-generate\-cds\-archive\f[R] +.RS +.RE +.TP +.B Description +Generate CDS archive if the runtime image supports the CDS feature. +.RS +.RE .SH JLINK EXAMPLES .PP The following command creates a runtime image in the directory diff --git a/src/jdk.jlink/share/man/jmod.1 b/src/jdk.jlink/share/man/jmod.1 index 16f595782a5077791a3b8fda38aa5fdd15c975f4..a9c68e1a8dcab0d28ca12dab826dd735ad363227 100644 --- a/src/jdk.jlink/share/man/jmod.1 +++ b/src/jdk.jlink/share/man/jmod.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JMOD" "1" "2021" "JDK 18\-ea" "JDK Commands" +.TH "JMOD" "1" "2022" "JDK 19\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppImageBuilder.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppImageBuilder.java index f1eed5f5f1538e15138a3231b854ac0ad1f84403..fd33ffbb3db61e9c2eb4608c8ca0a3a15545257b 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppImageBuilder.java +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppImageBuilder.java @@ -593,7 +593,6 @@ public class MacAppImageBuilder extends AbstractAppImageBuilder { Log.error(I18N.getString("message.keychain.error")); return; } - boolean contains = keychainList.stream().anyMatch( str -> str.trim().equals("\""+keyChainPath.trim()+"\"")); if (contains) { @@ -608,7 +607,9 @@ public class MacAppImageBuilder extends AbstractAppImageBuilder { if (path.startsWith("\"") && path.endsWith("\"")) { path = path.substring(1, path.length()-1); } - keyChains.add(path); + if (!keyChains.contains(path)) { + keyChains.add(path); + } }); List<String> args = new ArrayList<>(); @@ -682,27 +683,23 @@ public class MacAppImageBuilder extends AbstractAppImageBuilder { Log.verbose(MessageFormat.format(I18N.getString( "message.ignoring.symlink"), p.toString())); } else { - List<String> args; - // runtime and Framework files will be signed below - // but they need to be unsigned first here - if ((p.toString().contains("/Contents/runtime")) || - (p.toString().contains("/Contents/Frameworks"))) { - - args = new ArrayList<>(); - args.addAll(Arrays.asList("/usr/bin/codesign", - "--remove-signature", p.toString())); - try { - Set<PosixFilePermission> oldPermissions = - Files.getPosixFilePermissions(p); - p.toFile().setWritable(true, true); - ProcessBuilder pb = new ProcessBuilder(args); - IOUtils.exec(pb); - Files.setPosixFilePermissions(p,oldPermissions); - } catch (IOException ioe) { - Log.verbose(ioe); - toThrow.set(ioe); - return; - } + // unsign everything before signing + List<String> args = new ArrayList<>(); + args.addAll(Arrays.asList("/usr/bin/codesign", + "--remove-signature", p.toString())); + try { + Set<PosixFilePermission> oldPermissions = + Files.getPosixFilePermissions(p); + p.toFile().setWritable(true, true); + ProcessBuilder pb = new ProcessBuilder(args); + // run quietly + IOUtils.exec(pb, false, null, false, + Executor.INFINITE_TIMEOUT, true); + Files.setPosixFilePermissions(p,oldPermissions); + } catch (IOException ioe) { + Log.verbose(ioe); + toThrow.set(ioe); + return; } args = new ArrayList<>(); args.addAll(Arrays.asList("/usr/bin/codesign", @@ -727,7 +724,9 @@ public class MacAppImageBuilder extends AbstractAppImageBuilder { Files.getPosixFilePermissions(p); p.toFile().setWritable(true, true); ProcessBuilder pb = new ProcessBuilder(args); - IOUtils.exec(pb); + // run quietly + IOUtils.exec(pb, false, null, false, + Executor.INFINITE_TIMEOUT, true); Files.setPosixFilePermissions(p, oldPermissions); } catch (IOException ioe) { toThrow.set(ioe); diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/IOUtils.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/IOUtils.java index bc32df6a9bae3cbe864c612134b0a7f7ddfcf379..c41d8ff3bbb68d34913e62c8948ee46acc9fc149 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/IOUtils.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/IOUtils.java @@ -190,14 +190,24 @@ public class IOUtils { static void exec(ProcessBuilder pb, boolean testForPresenceOnly, PrintStream consumer, boolean writeOutputToFile, long timeout) throws IOException { + exec(pb, testForPresenceOnly, consumer, writeOutputToFile, + timeout, false); + } + + static void exec(ProcessBuilder pb, boolean testForPresenceOnly, + PrintStream consumer, boolean writeOutputToFile, + long timeout, boolean quiet) throws IOException { List<String> output = new ArrayList<>(); - Executor exec = Executor.of(pb).setWriteOutputToFile(writeOutputToFile) - .setTimeout(timeout).setOutputConsumer(lines -> { - lines.forEach(output::add); - if (consumer != null) { - output.forEach(consumer::println); - } - }); + Executor exec = Executor.of(pb) + .setWriteOutputToFile(writeOutputToFile) + .setTimeout(timeout) + .setQuiet(quiet) + .setOutputConsumer(lines -> { + lines.forEach(output::add); + if (consumer != null) { + output.forEach(consumer::println); + } + }); if (testForPresenceOnly) { exec.execute(); diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/Log.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/Log.java index 22e43b4311f75f5db57be18331988adc56e90171..b14b4ab22caeb708e49e2a7cbe052eb6a68cf3ea 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/Log.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/Log.java @@ -108,7 +108,7 @@ public class Log { public void verbose(List<String> strings, List<String> output, int returnCode, long pid) { if (verbose) { - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); sb.append("Command [PID: "); sb.append(pid); sb.append("]:\n "); @@ -116,13 +116,13 @@ public class Log { for (String s : strings) { sb.append(" " + s); } - verbose(new String(sb)); + verbose(sb.toString()); if (output != null && !output.isEmpty()) { - sb = new StringBuffer("Output:"); + sb = new StringBuilder("Output:"); for (String s : output) { sb.append("\n " + s); } - verbose(new String(sb)); + verbose(sb.toString()); } verbose("Returned: " + returnCode + "\n"); } diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/OverridableResource.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/OverridableResource.java index 9680691bc5db94d2322ba72e0be54c90f8848510..c455ef7150034918bab35f2dcb7a030c6fc672c5 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/OverridableResource.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/OverridableResource.java @@ -36,6 +36,8 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -279,11 +281,35 @@ final class OverridableResource { private static Stream<String> substitute(Stream<String> lines, Map<String, String> substitutionData) { + // Order substitution data by the length of keys. + // Longer keys go first. + // This is needed to properly handle cases when one key is + // a subtring of another and try the later first. + var orderedEntries = substitutionData.entrySet().stream() + .sorted(Map.Entry.<String, String>comparingByKey( + Comparator.comparingInt(String::length)).reversed()) + .toList(); return lines.map(line -> { String result = line; - for (var entry : substitutionData.entrySet()) { - result = result.replace(entry.getKey(), Optional.ofNullable( - entry.getValue()).orElse("")); + var workEntries = orderedEntries; + var it = workEntries.listIterator(); + while (it.hasNext()) { + var entry = it.next(); + String newResult = result.replace(entry.getKey(), + Optional.ofNullable(entry.getValue()).orElse("")); + if (!newResult.equals(result)) { + // Substitution occured. + // Remove the matching substitution key from the list and + // go over the list of substitution entries again. + if (workEntries == orderedEntries) { + workEntries = new ArrayList<>(orderedEntries); + it = workEntries.listIterator(it.nextIndex() - 1); + it.next(); + } + it.remove(); + it = workEntries.listIterator(); + result = newResult; + } } return result; }); diff --git a/src/jdk.jpackage/share/man/jpackage.1 b/src/jdk.jpackage/share/man/jpackage.1 index 2b85c96cb468fd7d9021599a097dbe796ab32a7e..51b45f7bdfcb73c27fa10187c7422d8a9b4317d9 100644 --- a/src/jdk.jpackage/share/man/jpackage.1 +++ b/src/jdk.jpackage/share/man/jpackage.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JPACKAGE" "1" "2021" "JDK 18\-ea" "JDK Commands" +.TH "JPACKAGE" "1" "2022" "JDK 19\-ea" "JDK Commands" .hy .SH NAME .PP @@ -56,7 +56,7 @@ Read options from a file. This option can be used multiple times. .RE .TP -.B \f[CB]\-\-type\f[R] or \f[CB]\-t\f[R] <type string> +.B \f[CB]\-\-type\f[R] or \f[CB]\-t\f[R] \f[I]type\f[R] The type of package to create .RS .PP @@ -67,17 +67,17 @@ If this option is not specified a platform dependent default type will be created. .RE .TP -.B \f[CB]\-\-app\-version\f[R] <version> +.B \f[CB]\-\-app\-version\f[R] \f[I]version\f[R] Version of the application and/or package .RS .RE .TP -.B \f[CB]\-\-copyright\f[R] <copyright string> +.B \f[CB]\-\-copyright\f[R] \f[I]copyright\f[R] Copyright for the application .RS .RE .TP -.B \f[CB]\-\-description\f[R] <description string> +.B \f[CB]\-\-description\f[R] \f[I]description\f[R] Description of the application .RS .RE @@ -88,30 +88,33 @@ for the current platform to the output stream, and exit. .RS .RE .TP -.B \f[CB]\-\-icon\f[R] <icon file path> -Path of the icon of the application package (absolute path or relative -to the current directory) +.B \f[CB]\-\-icon\f[R] \f[I]path\f[R] +Path of the icon of the application package .RS +.PP +(absolute path or relative to the current directory) .RE .TP -.B \f[CB]\-\-name\f[R] or \f[CB]\-n\f[R] <name> +.B \f[CB]\-\-name\f[R] or \f[CB]\-n\f[R] \f[I]name\f[R] Name of the application and/or package .RS .RE .TP -.B \f[CB]\-\-dest\f[R] or \f[CB]\-d\f[R] <output path> +.B \f[CB]\-\-dest\f[R] or \f[CB]\-d\f[R] \f[I]destination\f[R] Path where generated output file is placed .RS .PP -Defaults to the current working directory. (absolute path or relative to the current directory). +.PP +Defaults to the current working directory. .RE .TP -.B \f[CB]\-\-temp\f[R] <directory path> +.B \f[CB]\-\-temp\f[R] \f[I]directory\f[R] Path of a new or empty directory used to create temporary files -(absolute path or relative to the current directory) .RS .PP +(absolute path or relative to the current directory) +.PP If specified, the temp dir will not be removed upon the task completion and must be removed manually. .PP @@ -119,7 +122,7 @@ If not specified, a temporary directory will be created and removed upon the task completion. .RE .TP -.B \f[CB]\-\-vendor\f[R] <vendor string> +.B \f[CB]\-\-vendor\f[R] \f[I]vendor\f[R] Vendor of the application .RS .RE @@ -135,7 +138,7 @@ Print the product version to the output stream and exit. .RE .SS Options for creating the runtime image: .TP -.B \f[CB]\-\-add\-modules\f[R] <module name> [\f[CB],\f[R]<module name>...] +.B \f[CB]\-\-add\-modules\f[R] \f[I]module\-name\f[R] [\f[CB],\f[R]\f[I]module\-name\f[R]...] A comma (",") separated list of modules to add .RS .PP @@ -148,7 +151,7 @@ specified) are used. This option can be used multiple times. .RE .TP -.B \f[CB]\-\-module\-path\f[R] or \f[CB]\-p\f[R] <module path>... +.B \f[CB]\-\-module\-path\f[R] or \f[CB]\-p\f[R] \f[I]module\-path\f[R] [\f[CB],\f[R]\f[I]module\-path\f[R]...] A File.pathSeparator separated list of paths .RS .PP @@ -158,7 +161,7 @@ and is absolute or relative to the current directory. This option can be used multiple times. .RE .TP -.B \f[CB]\-\-jlink\-options\f[R] <jlink options> +.B \f[CB]\-\-jlink\-options\f[R] \f[I]options\f[R] A space separated list of options to pass to jlink .RS .PP @@ -168,34 +171,48 @@ If not specified, defaults to "\-\-strip\-native\-commands This option can be used multiple times. .RE .TP -.B \f[CB]\-\-runtime\-image\f[R] <directory path> +.B \f[CB]\-\-runtime\-image\f[R] \f[I]directory\f[R] Path of the predefined runtime image that will be copied into the -application image (absolute path or relative to the current directory) +application image .RS .PP +(absolute path or relative to the current directory) +.PP If \-\-runtime\-image is not specified, jpackage will run jlink to create the runtime image using options specified by \-\-jlink\-options. .RE .SS Options for creating the application image: .TP -.B \f[CB]\-\-input\f[R] or \f[CB]\-i\f[R] <input path> +.B \f[CB]\-\-input\f[R] or \f[CB]\-i\f[R] \f[I]directory\f[R] Path of the input directory that contains the files to be packaged -(absolute path or relative to the current directory) .RS .PP +(absolute path or relative to the current directory) +.PP All files in the input directory will be packaged into the application image. .RE +.TP +.B `\-\-app\-content \f[I]additional\-content\f[R][,\f[I]additional\-content\f[R]...] +A comma separated list of paths to files and/or directories to add to +the application payload. +.RS +.PP +This option can be used more than once. +.RE .SS Options for creating the application launcher(s): .TP -.B \f[CB]\-\-add\-launcher\f[R] <launcher name>=<file path> +.B \f[CB]\-\-add\-launcher\f[R] \f[I]name\f[R]=\f[I]path\f[R] Name of launcher, and a path to a Properties file that contains a list -of key, value pairs (absolute path or relative to the current directory) +of key, value pairs .RS .PP +(absolute path or relative to the current directory) +.PP The keys "module", "main\-jar", "main\-class", "arguments", -"java\-options", "app\-version", "icon", "linux\-app\-category", -"linux\-app\-release", and "win\-console" can be used. +"java\-options", "app\-version", "icon", "win\-console", +"win\-shortcut", "win\-menu", "linux\-app\-category", and +"linux\-shortcut", can be used. .PP These options are added to, or used to overwrite, the original command line options to build an additional alternative launcher. @@ -206,7 +223,7 @@ this option can be used multiple times to build multiple additional launchers. .RE .TP -.B \f[CB]\-\-arguments\f[R] <main class arguments> +.B \f[CB]\-\-arguments\f[R] \f[I]arguments\f[R] Command line arguments to pass to the main class if no command line arguments are given to the launcher .RS @@ -214,21 +231,21 @@ arguments are given to the launcher This option can be used multiple times. .RE .TP -.B \f[CB]\-\-java\-options\f[R] <java options> +.B \f[CB]\-\-java\-options\f[R] \f[I]options\f[R] Options to pass to the Java runtime .RS .PP This option can be used multiple times. .RE .TP -.B \f[CB]\-\-main\-class\f[R] <class name> +.B \f[CB]\-\-main\-class\f[R] \f[I]class\-name\f[R] Qualified name of the application main class to execute .RS .PP This option can only be used if \-\-main\-jar is specified. .RE .TP -.B \f[CB]\-\-main\-jar\f[R] <main jar file> +.B \f[CB]\-\-main\-jar\f[R] \f[I]main\-jar\f[R] The main JAR of the application; containing the main class (specified as a path relative to the input path) .RS @@ -236,7 +253,7 @@ a path relative to the input path) Either \-\-module or \-\-main\-jar option can be specified but not both. .RE .TP -.B \f[CB]\-\-module\f[R] or \f[CB]\-m\f[R] <module name>/<main class>] +.B \f[CB]\-\-module\f[R] or \f[CB]\-m\f[R] \f[I]module\-name\f[R][/\f[I]main\-class\f[R]] The main module (and optionally main class) of the application .RS .PP @@ -256,7 +273,7 @@ application which requires console interactions .RE .SS macOS platform options (available only when running on macOS): .TP -.B \f[CB]\-\-mac\-package\-identifier\f[R] <ID string> +.B \f[CB]\-\-mac\-package\-identifier\f[R] \f[I]identifier\f[R] An identifier that uniquely identifies the application for macOS .RS .PP @@ -266,7 +283,7 @@ May only use alphanumeric (A\-Z,a\-z,0\-9), hyphen (\-), and period (.) characters. .RE .TP -.B \f[CB]\-\-mac\-package\-name\f[R] <name string> +.B \f[CB]\-\-mac\-package\-name\f[R] \f[I]name\f[R] Name of the application as it appears in the Menu Bar .RS .PP @@ -277,7 +294,7 @@ displaying in the menu bar and the application Info window. Defaults to the application name. .RE .TP -.B \f[CB]\-\-mac\-package\-signing\-prefix\f[R] <prefix string> +.B \f[CB]\-\-mac\-package\-signing\-prefix\f[R] \f[I]prefix\f[R] When signing the application package, this value is prefixed to all components that need to be signed that don\[aq]t have an existing package identifier. @@ -289,14 +306,14 @@ Request that the bundle be signed. .RS .RE .TP -.B \f[CB]\-\-mac\-signing\-keychain\f[R] <keychain name> +.B \f[CB]\-\-mac\-signing\-keychain\f[R] \f[I]keychain\-name\f[R] Name of the keychain to search for the signing identity .RS .PP If not specified, the standard keychains are used. .RE .TP -.B \f[CB]\-\-mac\-signing\-key\-user\-name\f[R] <team name> +.B \f[CB]\-\-mac\-signing\-key\-user\-name\f[R] \f[I]name\f[R] Team or user name portion in Apple signing identities .RS .RE @@ -306,13 +323,13 @@ Indicates that the jpackage output is intended for the Mac App Store. .RS .RE .TP -.B \f[CB]\-\-mac\-entitlements\f[R] <file path> +.B \f[CB]\-\-mac\-entitlements\f[R] \f[I]path\f[R] Path to file containing entitlements to use when signing executables and libraries in the bundle .RS .RE .TP -.B \f[CB]\-\-mac\-app\-category\f[R] <category string> +.B \f[CB]\-\-mac\-app\-category\f[R] \f[I]category\f[R] String used to construct LSApplicationCategoryType in application plist .RS .PP @@ -320,59 +337,63 @@ The default value is "utilities". .RE .SS Options for creating the application package: .TP -.B \f[CB]\-\-about\-url\f[R] <url> +.B \f[CB]\-\-about\-url\f[R] \f[I]url\f[R] URL of the application\[aq]s home page .RS .RE .TP -.B \f[CB]\-\-app\-image\f[R] <directory path> +.B \f[CB]\-\-app\-image\f[R] \f[I]directory\f[R] Location of the predefined application image that is used to build an installable package .RS .PP -(absolute path or relative to the current directory). +(absolute path or relative to the current directory) .PP See create\-app\-image mode options to create the application image. .RE .TP -.B \f[CB]\-\-file\-associations\f[R] <file path> +.B \f[CB]\-\-file\-associations\f[R] \f[I]path\f[R] Path to a Properties file that contains list of key, value pairs -(absolute path or relative to the current directory) .RS .PP +(absolute path or relative to the current directory) +.PP The keys "extension", "mime\-type", "icon", and "description" can be used to describe the association. .PP This option can be used multiple times. .RE .TP -.B \f[CB]\-\-install\-dir\f[R] <directory path> +.B \f[CB]\-\-install\-dir\f[R] \f[I]path\f[R] Absolute path of the installation directory of the application (on macos or linux), or relative sub\-path of the installation directory such as "Program Files" or "AppData" (on Windows) .RS .RE .TP -.B \f[CB]\-\-license\-file\f[R] <file path> -Path to the license file (absolute path or relative to the current -directory) +.B \f[CB]\-\-license\-file\f[R] \f[I]path\f[R] +Path to the license file .RS +.PP +(absolute path or relative to the current directory) .RE .TP -.B \f[CB]\-\-resource\-dir\f[R] <directory path> -Path to override jpackage resources (absolute path or relative to the -current directory) +.B \f[CB]\-\-resource\-dir\f[R] \f[I]path\f[R] +Path to override jpackage resources .RS .PP +(absolute path or relative to the current directory) +.PP Icons, template files, and other resources of jpackage can be over\-ridden by adding replacement resources to this directory. .RE .TP -.B \f[CB]\-\-runtime\-image\f[R] <directory path> -Path of the predefined runtime image to install (absolute path or -relative to the current directory) +.B \f[CB]\-\-runtime\-image\f[R] \f[I]path\f[R] +Path of the predefined runtime image to install .RS .PP +(absolute path or relative to the current directory) +.PP Option is required when creating a runtime installer. .RE .SS Platform dependent options for creating the application package: @@ -384,7 +405,7 @@ product is installed. .RS .RE .TP -.B \f[CB]\-\-win\-help\-url\f[R] <url> +.B \f[CB]\-\-win\-help\-url\f[R] \f[I]url\f[R] URL where user can obtain further information or technical support .RS .RE @@ -394,7 +415,7 @@ Request to add a Start Menu shortcut for this application .RS .RE .TP -.B \f[CB]\-\-win\-menu\-group\f[R] <menu group name> +.B \f[CB]\-\-win\-menu\-group\f[R] \f[I]menu\-group\-name\f[R] Start Menu group this application is placed in .RS .RE @@ -415,30 +436,30 @@ by installer .RS .RE .TP -.B \f[CB]\-\-win\-update\-url\f[R] <url> +.B \f[CB]\-\-win\-update\-url\f[R] \f[I]url\f[R] URL of available application update information .RS .RE .TP -.B \f[CB]\-\-win\-upgrade\-uuid\f[R] <id string> +.B \f[CB]\-\-win\-upgrade\-uuid\f[R] \f[I]id\f[R] UUID associated with upgrades for this package .RS .RE .SS Linux platform options (available only when running on Linux): .TP -.B \f[CB]\-\-linux\-package\-name\f[R] <package name> +.B \f[CB]\-\-linux\-package\-name\f[R] \f[I]name\f[R] Name for Linux package .RS .PP Defaults to the application name. .RE .TP -.B \f[CB]\-\-linux\-deb\-maintainer\f[R] <email address> +.B \f[CB]\-\-linux\-deb\-maintainer\f[R] \f[I]email\-address\f[R] Maintainer for .deb bundle .RS .RE .TP -.B \f[CB]\-\-linux\-menu\-group\f[R] <menu\-group\-name> +.B \f[CB]\-\-linux\-menu\-group\f[R] \f[I]menu\-group\-name\f[R] Menu group this application is placed in .RS .RE @@ -448,20 +469,19 @@ Required packages or capabilities for the application .RS .RE .TP -.B \f[CB]\-\-linux\-rpm\-license\-type\f[R] <type string> -Type of the license ("License: <value>" of the RPM .spec) +.B \f[CB]\-\-linux\-rpm\-license\-type\f[R] \f[I]type\f[R] +Type of the license ("License: \f[I]value\f[R]" of the RPM .spec) .RS .RE .TP -.B \f[CB]\-\-linux\-app\-release\f[R] <release string> +.B \f[CB]\-\-linux\-app\-release\f[R] \f[I]release\f[R] Release value of the RPM <name>.spec file or Debian revision value of the DEB control file .RS .RE .TP -.B \f[CB]\-\-linux\-app\-category\f[R] <category string> -Group value of the RPM <name>.spec file or Section value of DEB control -file +.B \f[CB]\-\-linux\-app\-category\f[R] \f[I]category\-value\f[R] +Group value of the RPM /.spec file or Section value of DEB control file .RS .RE .TP @@ -469,6 +489,14 @@ file Creates a shortcut for the application. .RS .RE +.SS macOS platform options (available only when running on macOS): +.TP +.B \[aq]\-\-mac\-dmg\-content \f[I]additional\-content\f[R][,\f[I]additional\-content\f[R]...] +Include all the referenced content in the dmg. +.RS +.PP +This option can be used more than once. +.RE .SH JPACKAGE EXAMPLES .IP .nf diff --git a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java index 60a14bddf099ed10eba976e7210edfc22652e570..a6c92b67e9678cc7aa5235cdfb3b09cf426b7571 100644 --- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java +++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -372,7 +372,7 @@ class Feedback { return ""; } Matcher m = FIELD_PATTERN.matcher(format); - StringBuffer sb = new StringBuffer(format.length()); + StringBuilder sb = new StringBuilder(format.length()); while (m.find()) { String fieldName = m.group(1); String sub = format(fieldName, selector); @@ -626,7 +626,7 @@ class Feedback { } /** - * Set mode. Create, changed, or delete a feedback mode. For @{code /set + * Set mode. Create, changed, or delete a feedback mode. For {@code /set * mode <mode> [<old-mode>] [-command|-quiet|-delete|-retain]}. * * @return true if successful diff --git a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java index b257b1323633033dd22c701c6181d12399e6218d..ac78e23eff6565d01c9f9dde51118df57ce4a123 100644 --- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java +++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java @@ -254,7 +254,7 @@ public class JShellTool implements MessageHandler { Pattern.compile(OPTION_PRE_PATTERN.pattern() + "(?<dd>-??)(?<flag>-([a-z][a-z\\-]*)?)"); // match an option flag and a (possibly missing or incomplete) value private static final Pattern OPTION_VALUE_PATTERN = - Pattern.compile(OPTION_PATTERN.pattern() + "\\s+(?<val>\\S*)"); + Pattern.compile(OPTION_PATTERN.pattern() + "\\s+(?<val>(\\S|\\\\ )*)"); // Tool id (tid) mapping: the three name spaces NameSpace mainNamespace; @@ -1561,13 +1561,13 @@ public class JShellTool implements MessageHandler { private static CompletionProvider fileCompletions(Predicate<Path> accept) { return (code, cursor, anchor) -> { int lastSlash = code.lastIndexOf('/'); - String path = code.substring(0, lastSlash + 1); - String prefix = lastSlash != (-1) ? code.substring(lastSlash + 1) : code; + String path = code.substring(0, lastSlash + 1).replace("\\ ", " "); + String prefix = (lastSlash != (-1) ? code.substring(lastSlash + 1) : code).replace("\\ ", " "); Path current = toPathResolvingUserHome(path); List<Suggestion> result = new ArrayList<>(); try (Stream<Path> dir = Files.list(current)) { dir.filter(f -> accept.test(f) && f.getFileName().toString().startsWith(prefix)) - .map(f -> new ArgSuggestion(f.getFileName() + (Files.isDirectory(f) ? "/" : ""))) + .map(f -> new ArgSuggestion(f.getFileName().toString().replace(" ", "\\ ") + (Files.isDirectory(f) ? "/" : ""))) .forEach(result::add); } catch (IOException ex) { //ignore... diff --git a/src/jdk.jshell/share/classes/jdk/jshell/execution/RemoteExecutionControl.java b/src/jdk.jshell/share/classes/jdk/jshell/execution/RemoteExecutionControl.java index 810e80acf47d9ee7857292050297b1ced90567b5..d8818dee5417e1f7b7d24e3f79c91f53663801f9 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/execution/RemoteExecutionControl.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/execution/RemoteExecutionControl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,8 +63,8 @@ public class RemoteExecutionControl extends DirectExecutionControl implements Ex InputStream inStream = socket.getInputStream(); OutputStream outStream = socket.getOutputStream(); Map<String, Consumer<OutputStream>> outputs = new HashMap<>(); - outputs.put("out", st -> System.setOut(new PrintStream(st, true))); - outputs.put("err", st -> System.setErr(new PrintStream(st, true))); + outputs.put("out", st -> System.setOut(new PrintStream(st, true, System.out.charset()))); + outputs.put("err", st -> System.setErr(new PrintStream(st, true, System.err.charset()))); Map<String, Consumer<InputStream>> input = new HashMap<>(); input.put("in", System::setIn); forwardExecutionControlAndIO(new RemoteExecutionControl(), inStream, outStream, outputs, input); diff --git a/src/jdk.jshell/share/man/jshell.1 b/src/jdk.jshell/share/man/jshell.1 index 1865d30f90ac95bde6a6abb759963336b4ecc48e..0eddce3469c645a5ba8d6b9ae7d8d31cb3803785 100644 --- a/src/jdk.jshell/share/man/jshell.1 +++ b/src/jdk.jshell/share/man/jshell.1 @@ -22,7 +22,7 @@ .\"t .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JSHELL" "1" "2021" "JDK 18\-ea" "JDK Commands" +.TH "JSHELL" "1" "2022" "JDK 19\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jstatd/share/man/jstatd.1 b/src/jdk.jstatd/share/man/jstatd.1 index ccfe6e000aa213fee8fcd06bd6fda180aedb017f..d13f06b59b17975f648007f16b538f4cd750f765 100644 --- a/src/jdk.jstatd/share/man/jstatd.1 +++ b/src/jdk.jstatd/share/man/jstatd.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JSTATD" "1" "2021" "JDK 18\-ea" "JDK Commands" +.TH "JSTATD" "1" "2022" "JDK 19\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.management.jfr/share/classes/jdk/management/jfr/RecordingInfo.java b/src/jdk.management.jfr/share/classes/jdk/management/jfr/RecordingInfo.java index 16a710ee14aec6ba1404406f3a7e244f5f439f8b..8d2f1e061ccdc34bbef21c419fd31762963962db 100644 --- a/src/jdk.management.jfr/share/classes/jdk/management/jfr/RecordingInfo.java +++ b/src/jdk.management.jfr/share/classes/jdk/management/jfr/RecordingInfo.java @@ -300,10 +300,10 @@ public final class RecordingInfo { /** * Returns the desired duration, measured in seconds, of the recording - * associated with this {@link RecordingInfo}, or {code 0} if no duration + * associated with this {@link RecordingInfo}, or {@code 0} if no duration * has been set. * - * @return the desired duration, or {code 0} if no duration has been set + * @return the desired duration, or {@code 0} if no duration has been set * * @see Recording#getDuration() */ diff --git a/src/jdk.naming.dns/share/classes/com/sun/jndi/dns/DnsClient.java b/src/jdk.naming.dns/share/classes/com/sun/jndi/dns/DnsClient.java index ed4f2d8a1054a101da37b7edd6a70d6786878ce5..a5508ec45dbcec8d19693d9cedd7d801b3c26d55 100644 --- a/src/jdk.naming.dns/share/classes/com/sun/jndi/dns/DnsClient.java +++ b/src/jdk.naming.dns/share/classes/com/sun/jndi/dns/DnsClient.java @@ -148,7 +148,7 @@ public class DnsClient { } } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() { close(); } diff --git a/src/jdk.naming.rmi/share/classes/com/sun/jndi/rmi/registry/RegistryContext.java b/src/jdk.naming.rmi/share/classes/com/sun/jndi/rmi/registry/RegistryContext.java index bea428a60680661ab181d889893ec67a3874d606..d77055d280876bcba0c42636b31bfd88b5ca3e3a 100644 --- a/src/jdk.naming.rmi/share/classes/com/sun/jndi/rmi/registry/RegistryContext.java +++ b/src/jdk.naming.rmi/share/classes/com/sun/jndi/rmi/registry/RegistryContext.java @@ -120,7 +120,7 @@ public class RegistryContext implements Context, Referenceable { reference = ctx.reference; } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() { close(); } @@ -596,7 +596,7 @@ class BindingEnumeration implements NamingEnumeration<Binding> { nextName = 0; } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() { ctx.close(); } diff --git a/src/jdk.random/share/classes/jdk/random/L128X1024MixRandom.java b/src/jdk.random/share/classes/jdk/random/L128X1024MixRandom.java index a612233f2ca63fe4eb7e7f91220293d4417bfc0a..46f8a642d54ad93765da2558ea1bcb8667320c6a 100644 --- a/src/jdk.random/share/classes/jdk/random/L128X1024MixRandom.java +++ b/src/jdk.random/share/classes/jdk/random/L128X1024MixRandom.java @@ -323,17 +323,7 @@ public final class L128X1024MixRandom extends AbstractSplittableWithBrineGenerat // Update the LCG subgenerator // The LCG is, in effect, s = ((1LL << 64) + ML) * s + a, if only we had 128-bit arithmetic. final long u = ML * sl; - - // Note that Math.multiplyHigh computes the high half of the product of signed values, - // but what we need is the high half of the product of unsigned values; for this we use the - // formula "unsignedMultiplyHigh(a, b) = multiplyHigh(a, b) + ((a >> 63) & b) + ((b >> 63) & a)"; - // in effect, each operand is added to the result iff the sign bit of the other operand is 1. - // (See Henry S. Warren, Jr., _Hacker's Delight_ (Second Edition), Addison-Wesley (2013), - // Section 8-3, p. 175; or see the First Edition, Addison-Wesley (2003), Section 8-3, p. 133.) - // If Math.unsignedMultiplyHigh(long, long) is ever implemented, the following line can become: - // sh = (ML * sh) + Math.unsignedMultiplyHigh(ML, sl) + sl + ah; - // and this entire comment can be deleted. - sh = (ML * sh) + (Math.multiplyHigh(ML, sl) + ((ML >> 63) & sl) + ((sl >> 63) & ML)) + sl + ah; + sh = (ML * sh) + Math.unsignedMultiplyHigh(ML, sl) + sl + ah; sl = u + al; if (Long.compareUnsigned(sl, u) < 0) ++sh; // Handle the carry propagation from low half to high half. diff --git a/src/jdk.random/share/classes/jdk/random/L128X128MixRandom.java b/src/jdk.random/share/classes/jdk/random/L128X128MixRandom.java index 1b7d25850a65c81a8cf5e66282025afd6fa5ae65..ac12b96b4d227a34c1ccb87f8247d8550c455386 100644 --- a/src/jdk.random/share/classes/jdk/random/L128X128MixRandom.java +++ b/src/jdk.random/share/classes/jdk/random/L128X128MixRandom.java @@ -248,16 +248,7 @@ public final class L128X128MixRandom extends AbstractSplittableWithBrineGenerato // Update the LCG subgenerator // The LCG is, in effect, s = ((1LL << 64) + ML) * s + a, if only we had 128-bit arithmetic. final long u = ML * sl; - // Note that Math.multiplyHigh computes the high half of the product of signed values, - // but what we need is the high half of the product of unsigned values; for this we use the - // formula "unsignedMultiplyHigh(a, b) = multiplyHigh(a, b) + ((a >> 63) & b) + ((b >> 63) & a)"; - // in effect, each operand is added to the result iff the sign bit of the other operand is 1. - // (See Henry S. Warren, Jr., _Hacker's Delight_ (Second Edition), Addison-Wesley (2013), - // Section 8-3, p. 175; or see the First Edition, Addison-Wesley (2003), Section 8-3, p. 133.) - // If Math.unsignedMultiplyHigh(long, long) is ever implemented, the following line can become: - // sh = (ML * sh) + Math.unsignedMultiplyHigh(ML, sl) + sl + ah; - // and this entire comment can be deleted. - sh = (ML * sh) + (Math.multiplyHigh(ML, sl) + ((ML >> 63) & sl) + ((sl >> 63) & ML)) + sl + ah; + sh = (ML * sh) + Math.unsignedMultiplyHigh(ML, sl) + sl + ah; sl = u + al; if (Long.compareUnsigned(sl, u) < 0) ++sh; // Handle the carry propagation from low half to high half. diff --git a/src/jdk.random/share/classes/jdk/random/L128X256MixRandom.java b/src/jdk.random/share/classes/jdk/random/L128X256MixRandom.java index dad792d8c94f6fb3a8331d2e09a9356e80ed9f68..024d8525b3f7a131eee47bab786f40c188a616dd 100644 --- a/src/jdk.random/share/classes/jdk/random/L128X256MixRandom.java +++ b/src/jdk.random/share/classes/jdk/random/L128X256MixRandom.java @@ -269,16 +269,7 @@ public final class L128X256MixRandom extends AbstractSplittableWithBrineGenerato // Update the LCG subgenerator // The LCG is, in effect, s = ((1LL << 64) + ML) * s + a, if only we had 128-bit arithmetic. final long u = ML * sl; - // Note that Math.multiplyHigh computes the high half of the product of signed values, - // but what we need is the high half of the product of unsigned values; for this we use the - // formula "unsignedMultiplyHigh(a, b) = multiplyHigh(a, b) + ((a >> 63) & b) + ((b >> 63) & a)"; - // in effect, each operand is added to the result iff the sign bit of the other operand is 1. - // (See Henry S. Warren, Jr., _Hacker's Delight_ (Second Edition), Addison-Wesley (2013), - // Section 8-3, p. 175; or see the First Edition, Addison-Wesley (2003), Section 8-3, p. 133.) - // If Math.unsignedMultiplyHigh(long, long) is ever implemented, the following line can become: - // sh = (ML * sh) + Math.unsignedMultiplyHigh(ML, sl) + sl + ah; - // and this entire comment can be deleted. - sh = (ML * sh) + (Math.multiplyHigh(ML, sl) + ((ML >> 63) & sl) + ((sl >> 63) & ML)) + sl + ah; + sh = (ML * sh) + Math.unsignedMultiplyHigh(ML, sl) + sl + ah; sl = u + al; if (Long.compareUnsigned(sl, u) < 0) ++sh; // Handle the carry propagation from low half to high half. diff --git a/src/jdk.security.jgss/share/classes/com/sun/security/sasl/gsskerb/GssKrb5Base.java b/src/jdk.security.jgss/share/classes/com/sun/security/sasl/gsskerb/GssKrb5Base.java index 04cc61a5d2e45e29c9eddf9bb4f2f9240f11ead3..afdb7279c170e158fe2f640dc88f2473ca915a3e 100644 --- a/src/jdk.security.jgss/share/classes/com/sun/security/sasl/gsskerb/GssKrb5Base.java +++ b/src/jdk.security.jgss/share/classes/com/sun/security/sasl/gsskerb/GssKrb5Base.java @@ -162,7 +162,7 @@ abstract class GssKrb5Base extends AbstractSaslImpl { } } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { dispose(); } diff --git a/src/jdk.unsupported/share/classes/sun/misc/Unsafe.java b/src/jdk.unsupported/share/classes/sun/misc/Unsafe.java index e0ab5f3dffad290fa3d0d94d39b35b08fc6067d8..2f8d397c6c99baba3aef8341a694491c0517303b 100644 --- a/src/jdk.unsupported/share/classes/sun/misc/Unsafe.java +++ b/src/jdk.unsupported/share/classes/sun/misc/Unsafe.java @@ -633,8 +633,15 @@ public final class Unsafe { * the field locations in a form usable by {@link #getInt(Object,long)}. * Therefore, code which will be ported to such JVMs on 64-bit platforms * must preserve all bits of static field offsets. + * + * @deprecated The guarantee that a field will always have the same offset + * and base may not be true in a future release. The ability to provide an + * offset and object reference to a heap memory accessor will be removed + * in a future release. Use {@link java.lang.invoke.VarHandle} instead. + * * @see #getInt(Object, long) */ + @Deprecated(since="18") @ForceInline public long objectFieldOffset(Field f) { if (f == null) { @@ -665,8 +672,15 @@ public final class Unsafe { * a few bits to encode an offset within a non-array object, * However, for consistency with other methods in this class, * this method reports its result as a long value. + * + * @deprecated The guarantee that a field will always have the same offset + * and base may not be true in a future release. The ability to provide an + * offset and object reference to a heap memory accessor will be removed + * in a future release. Use {@link java.lang.invoke.VarHandle} instead. + * * @see #getInt(Object, long) */ + @Deprecated(since="18") @ForceInline public long staticFieldOffset(Field f) { if (f == null) { @@ -691,7 +705,13 @@ public final class Unsafe { * which is a "cookie", not guaranteed to be a real Object, and it should * not be used in any way except as argument to the get and put routines in * this class. + * + * @deprecated The guarantee that a field will always have the same offset + * and base may not be true in a future release. The ability to provide an + * offset and object reference to a heap memory accessor will be removed + * in a future release. Use {@link java.lang.invoke.VarHandle} instead. */ + @Deprecated(since="18") @ForceInline public Object staticFieldBase(Field f) { if (f == null) { diff --git a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java index 4f9b4e427bc57a30b33b5e01c2dcadd49598b13a..dd85df4cc609e83c1a78c6cfaa41200f1d99a611 100644 --- a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java +++ b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java @@ -1219,7 +1219,7 @@ class ZipFileSystem extends FileSystem { return zc.toString(name); } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws IOException { close(); } @@ -1471,6 +1471,13 @@ class ZipFileSystem extends FileSystem { }; } + /** + * Package-private accessor to entry alias map used by ZipPath. + */ + byte[] lookupPath(byte[] resolvedPath) { + return entryLookup.apply(resolvedPath); + } + /** * Create a sorted version map of version -> inode, for inodes <= max version. * 9 -> META-INF/versions/9 diff --git a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipPath.java b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipPath.java index 5cccce8d113e3b017536bdaaa0807ef5481bb775..234c54f5d0287954f8f8d1be31ecdb998ed811c1 100644 --- a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipPath.java +++ b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipPath.java @@ -200,13 +200,19 @@ final class ZipPath implements Path { return new URI("jar", decodeUri(zfs.getZipFile().toUri().toString()) + "!" + - zfs.getString(toAbsolutePath().path), + getRealPath(), null); } catch (Exception ex) { throw new AssertionError(ex); } } + private String getRealPath() { + byte[] resolvedPath = getResolvedPath(); + byte[] realPath = zfs.lookupPath(resolvedPath); + return zfs.getString(realPath != null ? realPath : resolvedPath); + } + private boolean equalsNameAt(ZipPath other, int index) { int mbegin = offsets[index]; int mlen; diff --git a/src/utils/IdealGraphVisualizer/.java-version b/src/utils/IdealGraphVisualizer/.java-version new file mode 100644 index 0000000000000000000000000000000000000000..60d3b2f4a4cd5f1637eba020358bfe5ecb5edcf2 --- /dev/null +++ b/src/utils/IdealGraphVisualizer/.java-version @@ -0,0 +1 @@ +15 diff --git a/src/utils/IdealGraphVisualizer/BatikSVGProxy/pom.xml b/src/utils/IdealGraphVisualizer/BatikSVGProxy/pom.xml deleted file mode 100644 index dccb16b356b9564407a46d198bb45c6f8fdd8499..0000000000000000000000000000000000000000 --- a/src/utils/IdealGraphVisualizer/BatikSVGProxy/pom.xml +++ /dev/null @@ -1,85 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - - Neither the name of Oracle nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---> - -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - <modelVersion>4.0.0</modelVersion> - <parent> - <artifactId>IdealGraphVisualizer-parent</artifactId> - <groupId>com.sun.hotspot.igv</groupId> - <version>1.0-SNAPSHOT</version> - </parent> - <groupId>com.sun.hotspot.igv</groupId> - <artifactId>BatikSVGProxy</artifactId> - <version>1.0-SNAPSHOT</version> - <packaging>nbm</packaging> - <name>BatikSVGProxy</name> - <properties> - <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - </properties> - <dependencies> - </dependencies> - <build> - <plugins> - <plugin> - <groupId>org.apache.netbeans.utilities</groupId> - <artifactId>nbm-maven-plugin</artifactId> - <version>${nbmmvnplugin.version}</version> - <extensions>true</extensions> - <configuration> - <publicPackages> - <publicPackage>com.sun.hotspot.igv.svg</publicPackage> - </publicPackages> - </configuration> - </plugin> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-compiler-plugin</artifactId> - <version>${mvncompilerplugin.version}</version> - <configuration> - <source>1.8</source> - <target>1.8</target> - </configuration> - </plugin> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-jar-plugin</artifactId> - <version>${mvnjarplugin.version}</version> - <configuration> - <!-- to have the jar plugin pickup the nbm generated manifest --> - <archive> - <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile> - </archive> - </configuration> - </plugin> - </plugins> - </build> -</project> diff --git a/src/utils/IdealGraphVisualizer/BatikSVGProxy/src/main/java/com/sun/hotspot/igv/svg/BatikSVG.java b/src/utils/IdealGraphVisualizer/BatikSVGProxy/src/main/java/com/sun/hotspot/igv/svg/BatikSVG.java deleted file mode 100644 index 8c3d92dc0642ec5a8525338e298fe7cc3e4cb80a..0000000000000000000000000000000000000000 --- a/src/utils/IdealGraphVisualizer/BatikSVGProxy/src/main/java/com/sun/hotspot/igv/svg/BatikSVG.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.svg; - -import java.awt.Graphics2D; -import java.io.Writer; -import java.io.File; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLClassLoader; -import org.w3c.dom.DOMImplementation; - -/** - * Utility class - * @author Thomas Wuerthinger - */ -public class BatikSVG { - - private BatikSVG() { - } - - private static Constructor SVGGraphics2DConstructor; - private static Method streamMethod; - private static Method createDefaultMethod; - private static Method getDOMImplementationMethod; - private static Method setEmbeddedFontsOnMethod; - private static Class<?> classSVGGraphics2D; - - /** - * Creates a graphics object that allows to be exported to SVG data using the {@link #printToStream(Graphics2D, Writer, boolean) printToStream} method. - * @return the newly created Graphics2D object or null if the library does not exist - */ - public static Graphics2D createGraphicsObject() { - try { - if (SVGGraphics2DConstructor == null) { - String batikJar = System.getenv().get("IGV_BATIK_JAR"); - if (batikJar == null) { - return null; - } - // Load batik in it's own class loader since some it's support jars interfere with the JDK - URL url = new File(batikJar).toURI().toURL(); - ClassLoader cl = new URLClassLoader(new URL[] { url }); - Class<?> classGenericDOMImplementation = cl.loadClass("org.apache.batik.dom.GenericDOMImplementation"); - Class<?> classSVGGeneratorContext = cl.loadClass("org.apache.batik.svggen.SVGGeneratorContext"); - classSVGGraphics2D = cl.loadClass("org.apache.batik.svggen.SVGGraphics2D"); - getDOMImplementationMethod = classGenericDOMImplementation.getDeclaredMethod("getDOMImplementation", new Class[0]); - createDefaultMethod = classSVGGeneratorContext.getDeclaredMethod("createDefault", new Class[]{org.w3c.dom.Document.class}); - setEmbeddedFontsOnMethod = classSVGGeneratorContext.getDeclaredMethod("setEmbeddedFontsOn", new Class[]{boolean.class}); - streamMethod = classSVGGraphics2D.getDeclaredMethod("stream", Writer.class, boolean.class); - SVGGraphics2DConstructor = classSVGGraphics2D.getConstructor(classSVGGeneratorContext, boolean.class); - } - DOMImplementation dom = (DOMImplementation) getDOMImplementationMethod.invoke(null); - org.w3c.dom.Document document = dom.createDocument("http://www.w3.org/2000/svg", "svg", null); - Object ctx = createDefaultMethod.invoke(null, document); - setEmbeddedFontsOnMethod.invoke(ctx, true); - Graphics2D svgGenerator = (Graphics2D) SVGGraphics2DConstructor.newInstance(ctx, true); - return svgGenerator; - } catch (ClassNotFoundException e) { - return null; - } catch (NoSuchMethodException e) { - return null; - } catch (IllegalAccessException e) { - return null; - } catch (InvocationTargetException e) { - return null; - } catch (InstantiationException e) { - return null; - } catch (MalformedURLException e) { - return null; - } - } - - /** - * Serializes a graphics object to a stream in SVG format. - * @param svgGenerator the graphics object. Only graphics objects created by the {@link #createGraphicsObject() createGraphicsObject} method are valid. - * @param stream the stream to which the data is written - * @param useCSS whether to use CSS styles in the SVG output - */ - public static void printToStream(Graphics2D svgGenerator, Writer stream, boolean useCSS) { - assert classSVGGraphics2D != null; - assert classSVGGraphics2D.isInstance(svgGenerator); - try { - streamMethod.invoke(svgGenerator, stream, useCSS); - } catch (IllegalAccessException e) { - assert false; - } catch (InvocationTargetException e) { - assert false; - } - } -} diff --git a/src/utils/IdealGraphVisualizer/BatikSVGProxy/src/main/nbm/manifest.mf b/src/utils/IdealGraphVisualizer/BatikSVGProxy/src/main/nbm/manifest.mf deleted file mode 100644 index 175014d653e04296c592e979574aa9a6106b25a1..0000000000000000000000000000000000000000 --- a/src/utils/IdealGraphVisualizer/BatikSVGProxy/src/main/nbm/manifest.mf +++ /dev/null @@ -1,5 +0,0 @@ -Manifest-Version: 1.0 -OpenIDE-Module: com.sun.hotspot.igv.svg -OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/svg/Bundle.properties -OpenIDE-Module-Specification-Version: 1.0 - diff --git a/src/utils/IdealGraphVisualizer/BatikSVGProxy/src/main/resources/com/sun/hotspot/igv/svg/Bundle.properties b/src/utils/IdealGraphVisualizer/BatikSVGProxy/src/main/resources/com/sun/hotspot/igv/svg/Bundle.properties deleted file mode 100644 index e579912925b2e5fcefa7760785bcb5ad974985a5..0000000000000000000000000000000000000000 --- a/src/utils/IdealGraphVisualizer/BatikSVGProxy/src/main/resources/com/sun/hotspot/igv/svg/Bundle.properties +++ /dev/null @@ -1 +0,0 @@ -OpenIDE-Module-Name=BatikSVGProxy diff --git a/src/utils/IdealGraphVisualizer/View/pom.xml b/src/utils/IdealGraphVisualizer/View/pom.xml index 12b2a8678b41ccdc1c4b2530e7a9326cb3d29953..0b1b0d77f31b324c16f3858208508941f4577da8 100644 --- a/src/utils/IdealGraphVisualizer/View/pom.xml +++ b/src/utils/IdealGraphVisualizer/View/pom.xml @@ -81,11 +81,6 @@ <artifactId>SelectionCoordinator</artifactId> <version>${project.version}</version> </dependency> - <dependency> - <groupId>com.sun.hotspot.igv</groupId> - <artifactId>BatikSVGProxy</artifactId> - <version>${project.version}</version> - </dependency> <dependency> <groupId>com.sun.hotspot.igv</groupId> <artifactId>Settings</artifactId> @@ -151,6 +146,21 @@ <artifactId>org-netbeans-api-visual</artifactId> <version>${netbeans.version}</version> </dependency> + <dependency> + <groupId>org.apache.xmlgraphics</groupId> + <artifactId>batik-dom</artifactId> + <version>${batik.version}</version> + </dependency> + <dependency> + <groupId>org.apache.xmlgraphics</groupId> + <artifactId>batik-svggen</artifactId> + <version>${batik.version}</version> + </dependency> + <dependency> + <groupId>com.github.librepdf</groupId> + <artifactId>openpdf</artifactId> + <version>${openpdf.version}</version> + </dependency> </dependencies> <build> <plugins> diff --git a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/DiagramViewer.java b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/DiagramViewer.java index 42697d025fe9bb17a5487d8de2eb48d19f8e0d24..2c58ac4dd26adb4846ce05f6ca90bbce6e7f5186 100644 --- a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/DiagramViewer.java +++ b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/DiagramViewer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ package com.sun.hotspot.igv.view; import com.sun.hotspot.igv.graph.Figure; import java.awt.Component; import java.awt.Graphics2D; +import java.awt.Rectangle; import java.util.Collection; import java.util.List; import javax.swing.JComponent; @@ -44,7 +45,7 @@ interface DiagramViewer { PANNING, } - public void paint(Graphics2D svgGenerator); + public void paint(Graphics2D generator); public Lookup getLookup(); @@ -70,4 +71,6 @@ interface DiagramViewer { public void setInteractionMode(InteractionMode mode); + public Rectangle getBounds(); + } diff --git a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/EditorTopComponent.java b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/EditorTopComponent.java index 76a73b9706837d05ca6fd75681243b1fe9ac3c83..cf5e965de69b58206bca4a956e34b64612e3f321 100644 --- a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/EditorTopComponent.java +++ b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/EditorTopComponent.java @@ -36,7 +36,6 @@ import com.sun.hotspot.igv.filter.FilterChainProvider; import com.sun.hotspot.igv.graph.Diagram; import com.sun.hotspot.igv.graph.Figure; import com.sun.hotspot.igv.graph.services.DiagramProvider; -import com.sun.hotspot.igv.svg.BatikSVG; import com.sun.hotspot.igv.util.LookupHistory; import com.sun.hotspot.igv.util.RangeSlider; import com.sun.hotspot.igv.view.actions.*; @@ -48,10 +47,21 @@ import java.awt.event.KeyListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.*; +import java.nio.charset.StandardCharsets; import java.util.List; import java.util.*; import javax.swing.*; import javax.swing.border.Border; +import org.apache.batik.dom.GenericDOMImplementation; +import org.apache.batik.svggen.SVGGeneratorContext; +import org.apache.batik.svggen.SVGGraphics2D; +import com.lowagie.text.Document; +import com.lowagie.text.Rectangle; +import com.lowagie.text.pdf.PdfWriter; +import com.lowagie.text.pdf.PdfContentByte; +import com.lowagie.text.pdf.PdfTemplate; +import com.lowagie.text.pdf.PdfGraphics2D; +import org.w3c.dom.DOMImplementation; import org.openide.DialogDisplayer; import org.openide.NotifyDescriptor; import org.openide.actions.RedoAction; @@ -103,30 +113,14 @@ public final class EditorTopComponent extends TopComponent implements PropertyCh @Override public void export(File f) { - Graphics2D svgGenerator = BatikSVG.createGraphicsObject(); - - if (svgGenerator == null) { - NotifyDescriptor message = new NotifyDescriptor.Message("For export to SVG files the Batik SVG Toolkit must be intalled.", NotifyDescriptor.ERROR_MESSAGE); - DialogDisplayer.getDefault().notifyLater(message); + String lcFileName = f.getName().toLowerCase(); + if (lcFileName.endsWith(".pdf")) { + exportToPDF(scene, f); + } else if (lcFileName.endsWith(".svg")) { + exportToSVG(scene, f); } else { - scene.paint(svgGenerator); - FileOutputStream os = null; - try { - os = new FileOutputStream(f); - Writer out = new OutputStreamWriter(os, UTF_8); - BatikSVG.printToStream(svgGenerator, out, true); - } catch (FileNotFoundException e) { - NotifyDescriptor message = new NotifyDescriptor.Message("For export to SVG files the Batik SVG Toolkit must be intalled.", NotifyDescriptor.ERROR_MESSAGE); - DialogDisplayer.getDefault().notifyLater(message); - } finally { - if (os != null) { - try { - os.close(); - } catch (IOException e) { - } - } - } - + NotifyDescriptor message = new NotifyDescriptor.Message("Unknown image file extension: expected either '.pdf' or '.svg'", NotifyDescriptor.ERROR_MESSAGE); + DialogDisplayer.getDefault().notifyLater(message); } } }; @@ -639,5 +633,47 @@ public final class EditorTopComponent extends TopComponent implements PropertyCh @Override protected Object writeReplace() throws ObjectStreamException { throw new NotSerializableException(); -} + } + + private static void exportToPDF(DiagramViewer scene, File f) { + int width = scene.getBounds().width; + int height = scene.getBounds().height; + com.lowagie.text.Document document = new Document(new Rectangle(width, height)); + PdfWriter writer = null; + try { + writer = PdfWriter.getInstance(document, new FileOutputStream(f)); + writer.setCloseStream(true); + document.open(); + PdfContentByte contentByte = writer.getDirectContent(); + PdfTemplate template = contentByte.createTemplate(width, height); + PdfGraphics2D pdfGenerator = new PdfGraphics2D(contentByte, width, height); + scene.paint(pdfGenerator); + pdfGenerator.dispose(); + contentByte.addTemplate(template, 0, 0); + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (document.isOpen()) { + document.close(); + } + if (writer != null) { + writer.close(); + } + } + } + + private static void exportToSVG(DiagramViewer scene, File f) { + DOMImplementation dom = GenericDOMImplementation.getDOMImplementation(); + org.w3c.dom.Document document = dom.createDocument("http://www.w3.org/2000/svg", "svg", null); + SVGGeneratorContext ctx = SVGGeneratorContext.createDefault(document); + ctx.setEmbeddedFontsOn(true); + SVGGraphics2D svgGenerator = new SVGGraphics2D(ctx, true); + scene.paint(svgGenerator); + try (FileOutputStream os = new FileOutputStream(f)) { + Writer out = new OutputStreamWriter(os, StandardCharsets.UTF_8); + svgGenerator.stream(out, true); + } catch (IOException e) { + e.printStackTrace(); + } + } } diff --git a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/actions/ExportAction.java b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/actions/ExportAction.java index 8583a6fbf3503845496cff33b85688347b4f4fc4..e5ea4025c3364f7c5050cbc11e5a94c94dc23d50 100644 --- a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/actions/ExportAction.java +++ b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/actions/ExportAction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,7 +45,7 @@ public final class ExportAction extends CallableSystemAction implements LookupLi private final Lookup.Result<ExportCookie> result; public ExportAction() { - putValue(Action.SHORT_DESCRIPTION, "Export current graph as SVG file"); + putValue(Action.SHORT_DESCRIPTION, "Export current graph as image file"); putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_E, InputEvent.CTRL_MASK)); lookup = Utilities.actionsGlobalContext(); result = lookup.lookup(new Lookup.Template<>(ExportCookie.class)); @@ -66,12 +66,15 @@ public final class ExportAction extends CallableSystemAction implements LookupLi @Override public boolean accept(File f) { - return true; + String lcFileName = f.getName().toLowerCase(); + return lcFileName.endsWith(".pdf") || + lcFileName.endsWith(".svg") || + f.isDirectory(); } @Override public String getDescription() { - return "SVG files (*.svg)"; + return "Image files (*.pdf, *.svg)"; } }); fc.setCurrentDirectory(new File(Settings.get().get(Settings.DIRECTORY, Settings.DIRECTORY_DEFAULT))); @@ -80,7 +83,7 @@ public final class ExportAction extends CallableSystemAction implements LookupLi if (fc.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) { File file = fc.getSelectedFile(); if (!file.getName().contains(".")) { - file = new File(file.getAbsolutePath() + ".svg"); + file = new File(file.getAbsolutePath() + ".pdf"); } File dir = file; diff --git a/src/utils/IdealGraphVisualizer/application/pom.xml b/src/utils/IdealGraphVisualizer/application/pom.xml index b5422fecb52abc64f9683064b4c5ad98c4e29cfb..5fcb7252c5d0b170e5010a95849bc6608457ef6d 100644 --- a/src/utils/IdealGraphVisualizer/application/pom.xml +++ b/src/utils/IdealGraphVisualizer/application/pom.xml @@ -142,11 +142,6 @@ <artifactId>Graal</artifactId> <version>${project.version}</version> </dependency> - <dependency> - <groupId>${project.groupId}</groupId> - <artifactId>BatikSVGProxy</artifactId> - <version>${project.version}</version> - </dependency> <dependency> <groupId>${project.groupId}</groupId> <artifactId>View</artifactId> diff --git a/src/utils/IdealGraphVisualizer/pom.xml b/src/utils/IdealGraphVisualizer/pom.xml index c1b1896dde4eda03c1c8a5b42dbb757ca2f20769..daaae24a5fd14212b2b3814e658dec24542c7306 100644 --- a/src/utils/IdealGraphVisualizer/pom.xml +++ b/src/utils/IdealGraphVisualizer/pom.xml @@ -86,16 +86,17 @@ <module>ServerCompiler</module> <module>FilterWindow</module> <module>Graal</module> - <module>BatikSVGProxy</module> <module>View</module> </modules> <properties> <netbeans.version>RELEASE123</netbeans.version> <swinglayouts.version>1.0.2</swinglayouts.version> - <nbmmvnplugin.version>4.3</nbmmvnplugin.version> + <nbmmvnplugin.version>4.6</nbmmvnplugin.version> <mvncompilerplugin.version>3.8.1</mvncompilerplugin.version> - <mvnjarplugin.version>3.1.2</mvnjarplugin.version> + <mvnjarplugin.version>3.2.0</mvnjarplugin.version> <junit.version>4.13.2</junit.version> + <batik.version>1.14</batik.version> + <openpdf.version>1.3.26</openpdf.version> <brandingToken>idealgraphvisualizer</brandingToken> </properties> </project> diff --git a/test/hotspot/gtest/aarch64/aarch64-asmtest.py b/test/hotspot/gtest/aarch64/aarch64-asmtest.py index e79afecd3dcfbe3fc09e9183a8b31a2cec1a8663..37b5a6154b76ee8a1a582215defad335d72c0786 100644 --- a/test/hotspot/gtest/aarch64/aarch64-asmtest.py +++ b/test/hotspot/gtest/aarch64/aarch64-asmtest.py @@ -1571,10 +1571,10 @@ generate(SpecialCases, [["ccmn", "__ ccmn(zr, zr, 3u, Assembler::LE);", ["stxpw", "__ stxpw(r6, zr, zr, sp);", "stxp\tw6, wzr, wzr, [sp]"], ["dup", "__ dup(v0, __ T16B, zr);", "dup\tv0.16b, wzr"], ["dup", "__ dup(v0, __ S, v1);", "dup\ts0, v1.s[0]"], - ["mov", "__ mov(v1, __ T1D, 0, zr);", "mov\tv1.d[0], xzr"], - ["mov", "__ mov(v1, __ T2S, 1, zr);", "mov\tv1.s[1], wzr"], - ["mov", "__ mov(v1, __ T4H, 2, zr);", "mov\tv1.h[2], wzr"], - ["mov", "__ mov(v1, __ T8B, 3, zr);", "mov\tv1.b[3], wzr"], + ["mov", "__ mov(v1, __ D, 0, zr);", "mov\tv1.d[0], xzr"], + ["mov", "__ mov(v1, __ S, 1, zr);", "mov\tv1.s[1], wzr"], + ["mov", "__ mov(v1, __ H, 2, zr);", "mov\tv1.h[2], wzr"], + ["mov", "__ mov(v1, __ B, 3, zr);", "mov\tv1.b[3], wzr"], ["smov", "__ smov(r0, v1, __ S, 0);", "smov\tx0, v1.s[0]"], ["smov", "__ smov(r0, v1, __ H, 1);", "smov\tx0, v1.h[1]"], ["smov", "__ smov(r0, v1, __ B, 2);", "smov\tx0, v1.b[2]"], diff --git a/test/hotspot/gtest/aarch64/asmtest.out.h b/test/hotspot/gtest/aarch64/asmtest.out.h index 8bbbdc579f5da9a23a6a8bec798aeb2208320d48..17eead9961ec9ab67dd0ad37cfe3d7952d30bd49 100644 --- a/test/hotspot/gtest/aarch64/asmtest.out.h +++ b/test/hotspot/gtest/aarch64/asmtest.out.h @@ -713,10 +713,10 @@ __ stxpw(r6, zr, zr, sp); // stxp w6, wzr, wzr, [sp] __ dup(v0, __ T16B, zr); // dup v0.16b, wzr __ dup(v0, __ S, v1); // dup s0, v1.s[0] - __ mov(v1, __ T1D, 0, zr); // mov v1.d[0], xzr - __ mov(v1, __ T2S, 1, zr); // mov v1.s[1], wzr - __ mov(v1, __ T4H, 2, zr); // mov v1.h[2], wzr - __ mov(v1, __ T8B, 3, zr); // mov v1.b[3], wzr + __ mov(v1, __ D, 0, zr); // mov v1.d[0], xzr + __ mov(v1, __ S, 1, zr); // mov v1.s[1], wzr + __ mov(v1, __ H, 2, zr); // mov v1.h[2], wzr + __ mov(v1, __ B, 3, zr); // mov v1.b[3], wzr __ smov(r0, v1, __ S, 0); // smov x0, v1.s[0] __ smov(r0, v1, __ H, 1); // smov x0, v1.h[1] __ smov(r0, v1, __ B, 2); // smov x0, v1.b[2] diff --git a/test/hotspot/gtest/gc/g1/test_freeRegionList.cpp b/test/hotspot/gtest/gc/g1/test_freeRegionList.cpp index 9a69816558bb71a0416613676d3b6e4cc042d649..2cf82eb403774ae7359f8f9281e6c871c2dfa28f 100644 --- a/test/hotspot/gtest/gc/g1/test_freeRegionList.cpp +++ b/test/hotspot/gtest/gc/g1/test_freeRegionList.cpp @@ -57,7 +57,7 @@ TEST_VM(FreeRegionList, length) { bot_rs.size(), os::vm_page_size(), HeapRegion::GrainBytes, - BOTConstants::N_bytes, + BOTConstants::card_size(), mtGC); G1BlockOffsetTable bot(heap, bot_storage); bot_storage->commit_regions(0, num_regions_in_test); diff --git a/test/hotspot/gtest/gc/g1/test_g1CardSet.cpp b/test/hotspot/gtest/gc/g1/test_g1CardSet.cpp index f009fc4adea4e2161aa5bcf2f47e722ae67863cb..914c64aacc593ec67824da72cd67c05c5433feaa 100644 --- a/test/hotspot/gtest/gc/g1/test_g1CardSet.cpp +++ b/test/hotspot/gtest/gc/g1/test_g1CardSet.cpp @@ -25,10 +25,12 @@ #include "gc/g1/g1CardSet.inline.hpp" #include "gc/g1/g1CardSetContainers.hpp" #include "gc/g1/g1CardSetMemory.hpp" +#include "gc/g1/g1SegmentedArrayFreePool.hpp" #include "gc/g1/heapRegionRemSet.hpp" #include "gc/shared/gcTraceTime.inline.hpp" #include "gc/shared/workerThread.hpp" #include "logging/log.hpp" +#include "memory/allocation.hpp" #include "unittest.hpp" #include "utilities/powerOfTwo.hpp" @@ -343,17 +345,17 @@ void G1CardSetTest::cardset_basic_test() { ASSERT_TRUE(count == card_set.occupied()); } - G1AddCardResult res = card_set.add_card(99, config.num_cards_in_howl_bitmap() - 1); + G1AddCardResult res = card_set.add_card(99, config.max_cards_in_howl_bitmap() - 1); // Adding above card should have coarsened Bitmap -> Full. ASSERT_TRUE(res == Added); - ASSERT_TRUE(config.num_cards_in_howl_bitmap() == card_set.occupied()); + ASSERT_TRUE(config.max_cards_in_howl_bitmap() == card_set.occupied()); - res = card_set.add_card(99, config.num_cards_in_howl_bitmap() - 2); + res = card_set.add_card(99, config.max_cards_in_howl_bitmap() - 2); ASSERT_TRUE(res == Found); uint threshold = config.cards_in_howl_threshold(); uint adjusted_threshold = config.cards_in_howl_bitmap_threshold() * config.num_buckets_in_howl(); - i = config.num_cards_in_howl_bitmap(); + i = config.max_cards_in_howl_bitmap(); count = i; for (; i < threshold; i++) { G1AddCardResult res = card_set.add_card(99, i); diff --git a/test/hotspot/gtest/gc/g1/test_g1CardSetContainers.cpp b/test/hotspot/gtest/gc/g1/test_g1CardSetContainers.cpp index c2ebeadd4811979a52d0c783cd122bb9598bba1a..9283fc3303fe031a30a749fd30e7351510cfecee 100644 --- a/test/hotspot/gtest/gc/g1/test_g1CardSetContainers.cpp +++ b/test/hotspot/gtest/gc/g1/test_g1CardSetContainers.cpp @@ -240,7 +240,7 @@ TEST_VM_F(G1CardSetContainersTest, basic_cardset_inptr_test) { uint const max = (uint)log2i(HeapRegionBounds::max_size()); for (uint i = min; i <= max; i++) { - G1CardSetContainersTest::cardset_inlineptr_test(i - CardTable::card_shift); + G1CardSetContainersTest::cardset_inlineptr_test(i - CardTable::card_shift()); } } diff --git a/test/hotspot/gtest/nmt/test_nmt_buffer_overflow_detection.cpp b/test/hotspot/gtest/nmt/test_nmt_buffer_overflow_detection.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c1aeb3e845ced23769ca0eb17ccc5abd912225a3 --- /dev/null +++ b/test/hotspot/gtest/nmt/test_nmt_buffer_overflow_detection.cpp @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2021 SAP SE. All rights reserved. + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "precompiled.hpp" +#include "memory/allocation.hpp" +#include "runtime/os.hpp" +#include "services/memTracker.hpp" +#include "utilities/debug.hpp" +#include "utilities/ostream.hpp" +#include "unittest.hpp" +#include "testutils.hpp" + +#if INCLUDE_NMT + +// This prefix shows up on any c heap corruption NMT detects. If unsure which assert will +// come, just use this one. +#define COMMON_NMT_HEAP_CORRUPTION_MESSAGE_PREFIX "NMT corruption" + + + +#define DEFINE_TEST(test_function, expected_assertion_message) \ + TEST_VM_FATAL_ERROR_MSG(NMT, test_function, ".*" expected_assertion_message ".*") { \ + if (MemTracker::tracking_level() > NMT_off) { \ + tty->print_cr("NMT overwrite death test, please ignore subsequent error dump."); \ + test_function (); \ + } else { \ + /* overflow detection requires NMT to be on. If off, fake assert. */ \ + guarantee(false, \ + "fake message ignore this - " expected_assertion_message); \ + } \ + } + +/////// + +static void test_overwrite_front() { + address p = (address) os::malloc(1, mtTest); + *(p - 1) = 'a'; + os::free(p); +} + +DEFINE_TEST(test_overwrite_front, "header canary broken") + +/////// + +static void test_overwrite_back() { + address p = (address) os::malloc(1, mtTest); + *(p + 1) = 'a'; + os::free(p); +} + +DEFINE_TEST(test_overwrite_back, "footer canary broken") + +/////// + +// A overwrite farther away from the NMT header; the report should show the hex dump split up +// in two parts, containing both header and corruption site. +static void test_overwrite_back_long(size_t distance) { + address p = (address) os::malloc(distance, mtTest); + *(p + distance) = 'a'; + os::free(p); +} +static void test_overwrite_back_long_aligned_distance() { test_overwrite_back_long(0x2000); } +DEFINE_TEST(test_overwrite_back_long_aligned_distance, "footer canary broken") +static void test_overwrite_back_long_unaligned_distance() { test_overwrite_back_long(0x2001); } +DEFINE_TEST(test_overwrite_back_long_unaligned_distance, "footer canary broken") + +/////// + +static void test_double_free() { + address p = (address) os::malloc(1, mtTest); + os::free(p); + // Now a double free. Note that this is susceptible to concurrency issues should + // a concurrent thread have done a malloc and gotten the same address after the + // first free. To decrease chance of this happening, we repeat the double free + // several times. + for (int i = 0; i < 100; i ++) { + os::free(p); + } +} + +// What assertion message we will see depends on whether the VM wipes the memory-to-be-freed +// on the first free(), and whether the libc uses the freed memory to store bookkeeping information. +// If the death marker in the header is still intact after the first free, we will recognize this as +// double free; if it got wiped, we should at least see a broken header canary. +// The message would be either +// - "header canary broken" or +// - "header canary dead (double free?)". +// However, since gtest regex expressions do not support unions (a|b), I search for a reasonable +// subset here. +DEFINE_TEST(test_double_free, "header canary") + +/////// + +static void test_invalid_block_address() { + // very low, like the result of an overflow or of accessing a NULL this pointer + os::free((void*)0x100); +} +DEFINE_TEST(test_invalid_block_address, "invalid block address") + +/////// + +static void test_unaliged_block_address() { + address p = (address) os::malloc(1, mtTest); + os::free(p + 6); +} +DEFINE_TEST(test_unaliged_block_address, "block address is unaligned"); + +/////// + +// Test that we notice block corruption on realloc too +static void test_corruption_on_realloc(size_t s1, size_t s2) { + address p1 = (address) os::malloc(s1, mtTest); + *(p1 + s1) = 'a'; + address p2 = (address) os::realloc(p1, s2, mtTest); + + // Still here? + tty->print_cr("NMT did not detect corruption on os::realloc?"); + // Note: don't use ASSERT here, that does not work as expected in death tests. Just + // let the test run its course, it should notice something is amiss. +} +static void test_corruption_on_realloc_growing() { test_corruption_on_realloc(0x10, 0x11); } +DEFINE_TEST(test_corruption_on_realloc_growing, COMMON_NMT_HEAP_CORRUPTION_MESSAGE_PREFIX); +static void test_corruption_on_realloc_shrinking() { test_corruption_on_realloc(0x11, 0x10); } +DEFINE_TEST(test_corruption_on_realloc_shrinking, COMMON_NMT_HEAP_CORRUPTION_MESSAGE_PREFIX); + +/////// + +// realloc is the trickiest of the bunch. Test that realloc works and correctly takes over +// NMT header and footer to the resized block. We just test that nothing crashes - if the +// header/footer get corrupted, NMT heap corruption checker will trigger alert on os::free()). +TEST_VM(NMT, test_realloc) { + // We test both directions (growing and shrinking) and a small range for each to cover all + // size alignment variants. Should not matter, but this should be cheap. + for (size_t s1 = 0xF0; s1 < 0x110; s1 ++) { + for (size_t s2 = 0x100; s2 > 0xF0; s2 --) { + address p1 = (address) os::malloc(s1, mtTest); + ASSERT_NOT_NULL(p1); + GtestUtils::mark_range(p1, s1); // mark payload range... + address p2 = (address) os::realloc(p1, s2, mtTest); + ASSERT_NOT_NULL(p2); + ASSERT_RANGE_IS_MARKED(p2, MIN2(s1, s2)) // ... and check that it survived the resize + << s1 << "->" << s2 << std::endl; + os::free(p2); // <- if NMT headers/footers got corrupted this asserts + } + } +} + +#endif // INCLUDE_NMT diff --git a/test/hotspot/gtest/testutils.cpp b/test/hotspot/gtest/testutils.cpp index 47351f056affa96a4abcaeb53f693701c99ca2f9..eb2898a526dc87e1a7fd3d30724e8d209942b7ed 100644 --- a/test/hotspot/gtest/testutils.cpp +++ b/test/hotspot/gtest/testutils.cpp @@ -57,7 +57,8 @@ bool GtestUtils::check_range(const void* p, size_t s, uint8_t expected) { } if (first_wrong != NULL) { - tty->print_cr("wrong pattern around " PTR_FORMAT, p2i(first_wrong)); + tty->print_cr("check_range [" PTR_FORMAT ".." PTR_FORMAT "), 0x%X, : wrong pattern around " PTR_FORMAT, + p2i(p), p2i(p) + s, expected, p2i(first_wrong)); // Note: We deliberately print the surroundings too without bounds check. Might be interesting, // and os::print_hex_dump uses SafeFetch, so this is fine without bounds checks. os::print_hex_dump(tty, (address)(align_down(p2, 0x10) - 0x10), diff --git a/test/hotspot/gtest/testutils.hpp b/test/hotspot/gtest/testutils.hpp index 8ed72f4644fab778465d144ede8ac1122a210651..9852e87cadae22b18fbf7b70fa18024ddee75807 100644 --- a/test/hotspot/gtest/testutils.hpp +++ b/test/hotspot/gtest/testutils.hpp @@ -51,8 +51,8 @@ public: #define ASSERT_RANGE_IS_MARKED(p, size) ASSERT_TRUE(GtestUtils::check_range(p, size)) // Convenience asserts -#define ASSERT_NOT_NULL(p) ASSERT_NE(p, (char*)NULL) -#define ASSERT_NULL(p) ASSERT_EQ(p, (char*)NULL) +#define ASSERT_NOT_NULL(p) ASSERT_NE(p2i(p), 0) +#define ASSERT_NULL(p) ASSERT_EQ(p2i(p), 0) #define ASSERT_ALIGN(p, n) ASSERT_TRUE(is_aligned(p, n)) diff --git a/test/hotspot/gtest/unittest.hpp b/test/hotspot/gtest/unittest.hpp index b414b2fbdd97c811c254040f1ad3753e3a8b483b..fefcc8efc398541c313410337909e417c4698ec6 100644 --- a/test/hotspot/gtest/unittest.hpp +++ b/test/hotspot/gtest/unittest.hpp @@ -149,4 +149,21 @@ TEST_VM_ASSERT_MSG is only available in debug builds #endif +#define TEST_VM_FATAL_ERROR_MSG(category, name, msg) \ + static void test_ ## category ## _ ## name ## _(); \ + \ + static void child_ ## category ## _ ## name ## _() { \ + ::testing::GTEST_FLAG(throw_on_failure) = true; \ + test_ ## category ## _ ## name ## _(); \ + exit(0); \ + } \ + \ + TEST(category, CONCAT(name, _vm_assert)) { \ + ASSERT_EXIT(child_ ## category ## _ ## name ## _(), \ + ::testing::ExitedWithCode(1), \ + msg); \ + } \ + \ + void test_ ## category ## _ ## name ## _() + #endif // UNITTEST_HPP diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 77cfd0c78e35f3d5456e25bce6b9ff74a12d87b4..315522b09e488ebe465ffe4209f525c6dceba54f 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -74,6 +74,8 @@ compiler/whitebox/MakeMethodNotCompilableTest.java 8265360 macosx-aarch64 compiler/codecache/jmx/PoolsIndependenceTest.java 8264632 macosx-x64 compiler/codecache/TestStressCodeBuffers.java 8272094 generic-aarch64 +compiler/vectorapi/reshape/TestVectorCastAVX512.java 8278623 generic-x64 + ############################################################################# @@ -89,8 +91,6 @@ gc/stress/gclocker/TestGCLockerWithG1.java 8180622 generic-all gc/stress/TestJNIBlockFullGC/TestJNIBlockFullGC.java 8192647 generic-all gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java 8241293 macosx-x64 -applications/jcstress/acqrel.java 8277434 linux-aarch64 - ############################################################################# # :hotspot_runtime @@ -108,6 +108,8 @@ runtime/ErrorHandling/CreateCoredumpOnCrash.java 8267433 macosx-x64 applications/jcstress/copy.java 8229852 linux-all +containers/docker/TestJcmd.java 8278102 linux-aarch64 + ############################################################################# # :hotspot_serviceability @@ -159,7 +161,7 @@ vmTestbase/nsk/jvmti/AttachOnDemand/attach045/TestDescription.java 8202971 gener vmTestbase/nsk/jvmti/scenarios/jni_interception/JI05/ji05t001/TestDescription.java 8219652 aix-ppc64 vmTestbase/nsk/jvmti/scenarios/jni_interception/JI06/ji06t001/TestDescription.java 8219652 aix-ppc64 vmTestbase/nsk/jvmti/SetJNIFunctionTable/setjniftab001/TestDescription.java 8219652 aix-ppc64 -vmTestbase/nsk/jvmti/SuspendThread/suspendthrd003/TestDescription.java 8264605 generic-all +vmTestbase/nsk/jvmti/AttachOnDemand/attach002a/TestDescription.java 8277812 generic-all vmTestbase/gc/lock/jni/jnilock002/TestDescription.java 8192647 generic-all diff --git a/test/hotspot/jtreg/TEST.groups b/test/hotspot/jtreg/TEST.groups index 9578e55493ad7d03b151012ea009882b9eb9d070..c66e80a10c166ab381d023ef780fc7c568169c8d 100644 --- a/test/hotspot/jtreg/TEST.groups +++ b/test/hotspot/jtreg/TEST.groups @@ -71,6 +71,13 @@ hotspot_native_sanity = \ hotspot_containers = \ containers +# Test sets for running inside container environment +hotspot_containers_extended = \ + runtime \ + serviceability \ + vmTestbase/nsk/jvmti \ + vmTestbase/nsk/monitoring + hotspot_vector_1 = \ compiler/c2/cr6340864 \ compiler/codegen \ @@ -173,6 +180,50 @@ tier1_compiler_3 = \ -compiler/loopopts/Test7052494.java \ -compiler/runtime/Test6826736.java +tier2_compiler = \ + compiler/allocation/ \ + compiler/arguments/ \ + compiler/calls/ \ + compiler/cha/ \ + compiler/controldependency/ \ + compiler/conversions/ \ + compiler/codegen/ \ + compiler/linkage/ \ + compiler/loopstripmining/ \ + compiler/loopopts/Test7052494.java \ + compiler/longcountedloops/ \ + compiler/intrinsics/bmi \ + compiler/intrinsics/mathexact \ + compiler/intrinsics/sha \ + compiler/intrinsics/bigInteger/TestMultiplyToLen.java \ + compiler/intrinsics/zip/TestAdler32.java \ + compiler/membars/ \ + compiler/onSpinWait/ \ + compiler/parsing/ \ + compiler/rangechecks/ \ + compiler/reflection/ \ + compiler/rtm/ \ + compiler/runtime/Test6826736.java \ + compiler/stable/ \ + compiler/stringopts/ \ + -:tier1_compiler \ + -:hotspot_slow_compiler + +tier3_compiler = \ + compiler/c2/ \ + compiler/ciReplay/ \ + compiler/compilercontrol/ \ + compiler/debug/ \ + compiler/oracle/ \ + compiler/print/ \ + compiler/relocations/ \ + compiler/tiered/ \ + compiler/vectorapi/ \ + compiler/whitebox/ \ + :hotspot_slow_compiler \ + -:tier1_compiler \ + -:tier2_compiler + tier1_compiler_not_xcomp = \ compiler/profiling @@ -354,6 +405,7 @@ hotspot_appcds_dynamic = \ -runtime/cds/appcds/LambdaEagerInit.java \ -runtime/cds/appcds/LambdaProxyClasslist.java \ -runtime/cds/appcds/LambdaVerificationFailedDuringDump.java \ + -runtime/cds/appcds/LambdaWithJavaAgent.java \ -runtime/cds/appcds/LambdaWithOldClass.java \ -runtime/cds/appcds/LongClassListPath.java \ -runtime/cds/appcds/LotsOfClasses.java \ @@ -467,11 +519,13 @@ tier2 = \ :hotspot_tier2_runtime \ :hotspot_tier2_runtime_platform_agnostic \ :hotspot_tier2_serviceability \ + :tier2_compiler \ :tier2_gc_epsilon \ :tier2_gc_shenandoah tier3 = \ :hotspot_tier3_runtime \ + :tier3_compiler \ :tier3_gc_shenandoah # Everything that is not in other tiers, but not apps diff --git a/test/hotspot/jtreg/compiler/c2/TestSubIdealC0Minus_YPlusC1_.java b/test/hotspot/jtreg/compiler/c2/TestSubIdealC0Minus_YPlusC1_.java new file mode 100644 index 0000000000000000000000000000000000000000..b623e1a2393fcec932f023f9d223f5d071a34235 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/TestSubIdealC0Minus_YPlusC1_.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8277882 + * @summary New subnode ideal optimization: converting "c0 - (x + c1)" into "(c0 - c1) - x" + * @library /test/lib + * @run main/othervm -XX:-TieredCompilation -Xbatch + * -XX:CompileCommand=dontinline,compiler.c2.TestSubIdealC0Minus_YPlusC1_::test* + * -XX:CompileCommand=compileonly,compiler.c2.TestSubIdealC0Minus_YPlusC1_::test* + * compiler.c2.TestSubIdealC0Minus_YPlusC1_ + */ +package compiler.c2; + +import jdk.test.lib.Asserts; + +public class TestSubIdealC0Minus_YPlusC1_ { + + private static final int I_C0_0 = 1234; + private static final int I_C1 = 1234; + private static final int I_C0_1 = 4321; + + private static final long L_C0_0 = 123_456_789_123L; + private static final long L_C1 = 123_456_789_123L; + private static final long L_C0_1 = 654_321; + + public static int testIC0EqualsC1(int x) { + return I_C0_0 - (x + I_C1); + } + + public static long testLC0EqualsC1(long x) { + return L_C0_0 - (x + L_C1); + } + + public static int testIC0NotEqualsC1(int x) { + return I_C0_1 - (x + I_C1); + } + + public static long testLC0NotEqualsC1(long x) { + return L_C0_1 - (x + L_C1); + } + + public static int testIXPlusC1IsOverflow(int x) { + return Integer.MAX_VALUE - (x + Integer.MAX_VALUE); + } + + public static long testLXPlusC1IsOverflow(long x) { + return Long.MAX_VALUE - (x + Long.MAX_VALUE); + } + + public static int testIXPlusC1IsUnderflow(int x) { + return Integer.MIN_VALUE - (x + Integer.MIN_VALUE); + } + + public static long testLXPlusC1IsUnderflow(long x) { + return Long.MIN_VALUE - (x + Long.MIN_VALUE); + } + + public static int testIC0MinusC1IsOverflow(int x) { + return Integer.MAX_VALUE - (x + Integer.MIN_VALUE); + } + + public static long testLC0MinusC1IsOverflow(long x) { + return Long.MAX_VALUE - (x + Long.MIN_VALUE); + } + + public static int testIC0MinusC1IsUnderflow(int x) { + return Integer.MIN_VALUE - (x + Integer.MAX_VALUE); + } + + public static long testLC0MinusC1IsUnderflow(long x) { + return Long.MIN_VALUE - (x + Long.MAX_VALUE); + } + + public static int testIResultIsOverflow(int x) { + return 2147483637 - (x + 10); // Integer.MAX_VALUE == 2147483647 + } + + public static long testLResultIsOverflow(long x) { + return 9223372036854775797L - (x + 10); // Long.MAX_VALUE == 9223372036854775807 + } + + public static int testIResultIsUnderflow(int x) { + return -2147483637 - (x + 10); // Integer.MIN_VALUE == -2147483648 + } + + public static long testLResultIsUnderflow(long x) { + return -9223372036854775797L - (x + 10); // Long.MIN_VALUE == -9223372036854775808 + } + + public static void main(String... args) { + for (int i = 0; i < 50_000; i++) { + Asserts.assertTrue(testIC0EqualsC1(10) == -10); + Asserts.assertTrue(testIC0NotEqualsC1(100) == 2987); + Asserts.assertTrue(testIXPlusC1IsOverflow(10) == -10); + Asserts.assertTrue(testIXPlusC1IsUnderflow(-10) == 10); + Asserts.assertTrue(testIC0MinusC1IsOverflow(10) == -11); + Asserts.assertTrue(testIC0MinusC1IsUnderflow(10) == -9); + Asserts.assertTrue(testIResultIsOverflow(-21) == Integer.MIN_VALUE); + Asserts.assertTrue(testIResultIsUnderflow(2) == Integer.MAX_VALUE); + + Asserts.assertTrue(testLC0EqualsC1(10) == -10); + Asserts.assertTrue(testLC0NotEqualsC1(100) == -123456134902L); + Asserts.assertTrue(testLXPlusC1IsOverflow(10) == -10); + Asserts.assertTrue(testLXPlusC1IsUnderflow(-10) == 10); + Asserts.assertTrue(testLC0MinusC1IsOverflow(10) == -11); + Asserts.assertTrue(testLC0MinusC1IsUnderflow(10) == -9); + Asserts.assertTrue(testLResultIsOverflow(-21) == Long.MIN_VALUE); + Asserts.assertTrue(testLResultIsUnderflow(2) == Long.MAX_VALUE); + } + } +} diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestIterativeEA.java b/test/hotspot/jtreg/compiler/c2/irTests/TestIterativeEA.java new file mode 100644 index 0000000000000000000000000000000000000000..1bfaebabec84d299450871444ba9878a4d0c0849 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestIterativeEA.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.c2.irTests; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import jdk.test.lib.Asserts; +import compiler.lib.ir_framework.*; + +/* + * @test + * @bug 8276455 + * @summary Test C2 iterative Escape Analysis to remove all allocations in test + * @library /test/lib / + * @run driver compiler.c2.irTests.TestIterativeEA + */ +public class TestIterativeEA { + + public static void main(String[] args) { + TestFramework.run(); + } + + static class MyClass { + int val; + public MyClass(int val) { + this.val = val; + } + } + + static class AbstractClass { + final int unused; + public AbstractClass() { + unused = 42; + } + } + + static class HolderWithSuper extends AbstractClass { + final MyClass obj; + public HolderWithSuper(MyClass obj) { + this.obj = obj; + } + } + + static class Holder { + final MyClass obj; + public Holder(MyClass obj) { + this.obj = obj; + } + } + + static class GenericHolder { + final Object obj; + public GenericHolder(Object obj) { + this.obj = obj; + } + } + + @Test + @Arguments({ Argument.RANDOM_EACH }) + @IR(failOn = { IRNode.ALLOC }) + public static int testSlow(int val) { + MyClass obj = new MyClass(val); + HolderWithSuper h1 = new HolderWithSuper(obj); + GenericHolder h2 = new GenericHolder(h1); + return ((HolderWithSuper)h2.obj).obj.val; + } + + @Test + @Arguments({ Argument.RANDOM_EACH }) + @IR(failOn = { IRNode.ALLOC }) + public static int testFast(int val) { + MyClass obj = new MyClass(val); + Holder h1 = new Holder(obj); + GenericHolder h2 = new GenericHolder(h1); + return ((Holder)h2.obj).obj.val; + } + + static class A { + int i; + public A(int i) { + this.i = i; + } + } + + static class B { + A a; + public B(A a) { + this.a = a; + } + } + + static class C { + B b; + public C(B b) { + this.b = b; + } + } + + @Test + @Arguments({ Argument.RANDOM_EACH }) + @IR(failOn = { IRNode.ALLOC }) + static int testNested(int i) { + C c = new C(new B(new A(i))); + return c.b.a.i; + } +} diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestLongRangeChecks.java b/test/hotspot/jtreg/compiler/c2/irTests/TestLongRangeChecks.java index 298f00942011115c9fccd4228d27ffa57e0b5675..4fd677ab4c0ae52108b7a806491df1cc5b27528a 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/TestLongRangeChecks.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestLongRangeChecks.java @@ -28,7 +28,7 @@ import java.util.Objects; /* * @test - * @bug 8259609 + * @bug 8259609 8276116 * @summary C2: optimize long range checks in long counted loops * @library /test/lib / * @run driver compiler.c2.irTests.TestLongRangeChecks @@ -41,8 +41,8 @@ public class TestLongRangeChecks { @Test - @IR(counts = { IRNode.LOOP, "1"}) - @IR(failOn = { IRNode.COUNTEDLOOP}) + @IR(counts = { IRNode.LOOP, "1" }) + @IR(failOn = { IRNode.COUNTEDLOOP }) public static void testStridePosScalePos(long start, long stop, long length, long offset) { final long scale = 1; final long stride = 1; @@ -60,4 +60,40 @@ public class TestLongRangeChecks { private void testStridePosScalePos_runner() { testStridePosScalePos(0, 100, 100, 0); } + + @Test + @IR(counts = { IRNode.LOOP, "1" }) + @IR(failOn = { IRNode.COUNTEDLOOP }) + public static void testStridePosScalePosInIntLoop1(int start, int stop, long length, long offset) { + final long scale = 2; + final int stride = 1; + + // Same but with int loop + for (int i = start; i < stop; i += stride) { + Objects.checkIndex(scale * i + offset, length); + } + } + + @Run(test = "testStridePosScalePosInIntLoop1") + private void testStridePosScalePosInIntLoop1_runner() { + testStridePosScalePosInIntLoop1(0, 100, 200, 0); + } + + @Test + @IR(counts = { IRNode.LOOP, "1" }) + @IR(failOn = { IRNode.COUNTEDLOOP }) + public static void testStridePosScalePosInIntLoop2(int start, int stop, long length, long offset) { + final int scale = 2; + final int stride = 1; + + // Same but with int loop + for (int i = start; i < stop; i += stride) { + Objects.checkIndex(scale * i + offset, length); + } + } + + @Run(test = "testStridePosScalePosInIntLoop2") + private void testStridePosScalePosInIntLoop2_runner() { + testStridePosScalePosInIntLoop2(0, 100, 200, 0); + } } diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestShiftAndMask.java b/test/hotspot/jtreg/compiler/c2/irTests/TestShiftAndMask.java new file mode 100644 index 0000000000000000000000000000000000000000..ca6d59428a88aa82560e301521fa5202366bc227 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestShiftAndMask.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2021, Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.c2.irTests; + +import compiler.lib.ir_framework.*; + +/* + * @test + * @bug 8277850 + * @summary C2: optimize mask checks in counted loops + * @library /test/lib / + * @run driver compiler.c2.irTests.TestShiftAndMask + */ + +public class TestShiftAndMask { + public static void main(String[] args) { + TestFramework.run(); + } + + @Test + @Arguments(Argument.RANDOM_EACH) + @IR(failOn = { IRNode.AND_I, IRNode.LSHIFT_I }) + public static int shiftMaskInt(int i) { + return (i << 2) & 3; // transformed to: return 0; + } + + @Test + @Arguments(Argument.RANDOM_EACH) + @IR(failOn = { IRNode.AND_L, IRNode.LSHIFT_L }) + public static long shiftMaskLong(long i) { + return (i << 2) & 3; // transformed to: return 0; + } + + @Test + @Arguments({Argument.RANDOM_EACH, Argument.RANDOM_EACH}) + @IR(counts = { IRNode.AND_I, "1" }) + @IR(failOn = { IRNode.ADD_I, IRNode.LSHIFT_I }) + public static int addShiftMaskInt(int i, int j) { + return (j + (i << 2)) & 3; // transformed to: return j & 3; + } + + @Test + @Arguments({Argument.RANDOM_EACH, Argument.RANDOM_EACH}) + @IR(counts = { IRNode.AND_L, "1" }) + @IR(failOn = { IRNode.ADD_L, IRNode.LSHIFT_L }) + public static long addShiftMaskLong(long i, long j) { + return (j + (i << 2)) & 3; // transformed to: return j & 3; + } + + @Test + @Arguments({Argument.RANDOM_EACH, Argument.RANDOM_EACH}) + @IR(failOn = { IRNode.AND_I, IRNode.ADD_I, IRNode.LSHIFT_I }) + public static int addShiftMaskInt2(int i, int j) { + return ((j << 2) + (i << 2)) & 3; // transformed to: return 0; + } + + @Test + @Arguments({Argument.RANDOM_EACH, Argument.RANDOM_EACH}) + @IR(failOn = { IRNode.AND_L, IRNode.ADD_L, IRNode.LSHIFT_L }) + public static long addShiftMaskLong2(long i, long j) { + return ((j << 2) + (i << 2)) & 3; // transformed to: return 0; + } + + @Test + @Arguments(Argument.RANDOM_EACH) + @IR(failOn = { IRNode.AND_L, IRNode.LSHIFT_I }) + public static long shiftConvMask(int i) { + return ((long)(i << 2)) & 3; // transformed to: return 0; + } + + @Test + @Arguments({Argument.RANDOM_EACH, Argument.RANDOM_EACH}) + @IR(counts = { IRNode.AND_L, "1" }) + @IR(failOn = { IRNode.ADD_L, IRNode.LSHIFT_I, IRNode.CONV_I2L }) + public static long addShiftConvMask(int i, long j) { + return (j + (i << 2)) & 3; // transformed to: return j & 3; + } + + @Test + @Arguments({Argument.RANDOM_EACH, Argument.RANDOM_EACH}) + @IR(failOn = { IRNode.AND_L, IRNode.ADD_L, IRNode.LSHIFT_L }) + public static long addShiftConvMask2(int i, int j) { + return (((long)(j << 2)) + ((long)(i << 2))) & 3; // transformed to: return 0; + } + +} + diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestSpecialCasesOf_AMinusB_Plus_CMinusD_InAddIdeal.java b/test/hotspot/jtreg/compiler/c2/irTests/TestSpecialCasesOf_AMinusB_Plus_CMinusD_InAddIdeal.java new file mode 100644 index 0000000000000000000000000000000000000000..4cbbcd9330131dcd07e1aba68b146bba29121299 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestSpecialCasesOf_AMinusB_Plus_CMinusD_InAddIdeal.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.c2.irTests; + +import jdk.test.lib.Asserts; +import compiler.lib.ir_framework.*; + +/* + * @test + * @bug 8278471 + * @summary Remove unreached rules in AddNode::IdealIL + * @library /test/lib / + * @run driver compiler.c2.irTests.TestSpecialCasesOf_AMinusB_Plus_CMinusD_InAddIdeal + */ +/* Test conversion from (a - b) + (b - c) to (a - c) and conversion + * from (a - b) + (c - a) to (c - b) have really happened so we can + * safely remove both. */ +public class TestSpecialCasesOf_AMinusB_Plus_CMinusD_InAddIdeal { + + public static void main(String[] args) { + TestFramework.run(); + } + + @Test + @Arguments({Argument.RANDOM_ONCE, Argument.RANDOM_ONCE, Argument.RANDOM_ONCE}) + @IR(failOn = {IRNode.ADD_I}) + @IR(counts = {IRNode.SUB_I, "1"}) + public int test1Int(int a, int b, int c) { + return (a - b) + (b - c); // transformed to a - c rather than (a + b) - (b + c) + } + + @Test + @Arguments({Argument.RANDOM_ONCE, Argument.RANDOM_ONCE, Argument.RANDOM_ONCE}) + @IR(failOn = {IRNode.ADD_L}) + @IR(counts = {IRNode.SUB_L, "1"}) + public long test1Long(long a, long b, long c) { + return (a - b) + (b - c); // transformed to a - c rather than (a + b) - (b + c) + } + + @Test + @Arguments({Argument.RANDOM_ONCE, Argument.RANDOM_ONCE, Argument.RANDOM_ONCE}) + @IR(failOn = {IRNode.ADD_I}) + @IR(counts = {IRNode.SUB_I, "1"}) + public int test2Int(int b, int a, int c) { // make sure inputs sorted + return (a - b) + (c - a); // transformed to c - b rather than (a + c) - (b + a) + } + + @Test + @Arguments({Argument.RANDOM_ONCE, Argument.RANDOM_ONCE, Argument.RANDOM_ONCE}) + @IR(failOn = {IRNode.ADD_L}) + @IR(counts = {IRNode.SUB_L, "1"}) + public long test2Long(long b, long a, long c) { // make sure inputs sorted + return (a - b) + (c - a); // transformed to return c - b rather than (a + c) - (b + a) + } +} diff --git a/test/hotspot/jtreg/compiler/codecache/CodeCacheFullCountTest.java b/test/hotspot/jtreg/compiler/codecache/CodeCacheFullCountTest.java new file mode 100644 index 0000000000000000000000000000000000000000..1fee39144ff93f6cba9bc1ba42ecef6bd4b53f7a --- /dev/null +++ b/test/hotspot/jtreg/compiler/codecache/CodeCacheFullCountTest.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.net.URL; +import java.net.URLClassLoader; +import java.lang.reflect.Field; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +/* + * @test + * @bug 8276036 8277213 8277441 + * @summary test for the value of full_count in the message of insufficient codecache + * @library /test/lib + */ +public class CodeCacheFullCountTest { + public static void main(String args[]) throws Throwable { + if (args.length == 1) { + wasteCodeCache(); + } else { + runTest(); + } + } + + public static void wasteCodeCache() throws Exception { + URL url = CodeCacheFullCountTest.class.getProtectionDomain().getCodeSource().getLocation(); + + for (int i = 0; i < 500; i++) { + ClassLoader cl = new MyClassLoader(url); + refClass(cl.loadClass("SomeClass")); + } + } + + public static void runTest() throws Throwable { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:ReservedCodeCacheSize=2496k", "-XX:-UseCodeCacheFlushing", "CodeCacheFullCountTest", "WasteCodeCache"); + OutputAnalyzer oa = ProcessTools.executeProcess(pb); + oa.shouldHaveExitValue(0); + String stdout = oa.getStdout(); + + Pattern pattern = Pattern.compile("full_count=(\\d)"); + Matcher stdoutMatcher = pattern.matcher(stdout); + if (stdoutMatcher.find()) { + int fullCount = Integer.parseInt(stdoutMatcher.group(1)); + if (fullCount != 1) { + throw new RuntimeException("the value of full_count is wrong."); + } + } else { + throw new RuntimeException("codecache shortage did not occur."); + } + } + + private static void refClass(Class clazz) throws Exception { + Field name = clazz.getDeclaredField("NAME"); + name.setAccessible(true); + name.get(null); + } + + private static class MyClassLoader extends URLClassLoader { + public MyClassLoader(URL url) { + super(new URL[]{url}, null); + } + protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { + try { + return super.loadClass(name, resolve); + } catch (ClassNotFoundException e) { + return Class.forName(name, resolve, CodeCacheFullCountTest.class.getClassLoader()); + } + } + } +} + +abstract class Foo { + public abstract int foo(); +} + +class Foo1 extends Foo { + private int a; + public int foo() { return a; } +} + +class Foo2 extends Foo { + private int a; + public int foo() { return a; } +} + +class Foo3 extends Foo { + private int a; + public int foo() { return a; } +} + +class Foo4 extends Foo { + private int a; + public int foo() { return a; } +} + +class SomeClass { + static final String NAME = "name"; + + static { + int res =0; + Foo[] foos = new Foo[] { new Foo1(), new Foo2(), new Foo3(), new Foo4() }; + for (int i = 0; i < 100000; i++) { + res = foos[i % foos.length].foo(); + } + } +} diff --git a/test/hotspot/jtreg/compiler/escapeAnalysis/TestIterativeEA.java b/test/hotspot/jtreg/compiler/escapeAnalysis/TestIterativeEA.java new file mode 100644 index 0000000000000000000000000000000000000000..ef4db4635164f89216fd93babcf3ae23250126be --- /dev/null +++ b/test/hotspot/jtreg/compiler/escapeAnalysis/TestIterativeEA.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8276455 + * @summary Test C2 iterative Escape Analysis + * @library /test/lib / + * + * @requires vm.flagless + * @requires vm.compiler2.enabled & vm.debug == true + * + * @run driver TestIterativeEA + */ + +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; + +public class TestIterativeEA { + + public static void main(String[] args) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-server", "-XX:-TieredCompilation", "-Xbatch", "-XX:+PrintEliminateAllocations", + Launcher.class.getName()); + + OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); + + System.out.println(analyzer.getOutput()); + + analyzer.shouldHaveExitValue(0); + analyzer.shouldContain("++++ Eliminated: 26 Allocate"); + analyzer.shouldContain("++++ Eliminated: 48 Allocate"); + analyzer.shouldContain("++++ Eliminated: 78 Allocate"); + } + + static class A { + int i; + + public A(int i) { + this.i = i; + } + } + + static class B { + A a; + + public B(A a) { + this.a = a; + } + } + + static class C { + B b; + + public C(B b) { + this.b = b; + } + } + + static int test(int i) { + C c = new C(new B(new A(i))); + return c.b.a.i; + } + + static class Launcher { + public static void main(String[] args) { + for (int i = 0; i < 12000; ++i) { + int j = test(i); + } + } + } + +} diff --git a/test/hotspot/jtreg/compiler/exceptions/OptimizeImplicitExceptions.java b/test/hotspot/jtreg/compiler/exceptions/OptimizeImplicitExceptions.java new file mode 100644 index 0000000000000000000000000000000000000000..289353a38a240c992b95ab06f72c9d0b062a0d17 --- /dev/null +++ b/test/hotspot/jtreg/compiler/exceptions/OptimizeImplicitExceptions.java @@ -0,0 +1,275 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + /* + * @test + * @bug 8275908 + * @summary Record null_check traps for calls and array_check traps in the interpreter + * + * @requires vm.compiler2.enabled & vm.compMode != "Xcomp" + * + * @library /test/lib + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -Xbatch -XX:-UseOnStackReplacement -XX:-TieredCompilation + * -XX:CompileCommand=compileonly,compiler.exceptions.OptimizeImplicitExceptions::throwImplicitException + * compiler.exceptions.OptimizeImplicitExceptions + */ + +package compiler.exceptions; + +import java.lang.reflect.Method; +import java.util.HashMap; + +import jdk.test.lib.Asserts; +import jdk.test.whitebox.WhiteBox; + +public class OptimizeImplicitExceptions { + // ImplicitException represents the various implicit (aka. 'built-in') exceptions + // which can be thrown implicitely by the JVM when executing bytecodes. + public enum ImplicitException { + // NullPointerException during field access + NULL_POINTER_EXCEPTION("null_check"), + // NullPointerException during invoke + INVOKE_NULL_POINTER_EXCEPTION("null_check"), + ARITHMETIC_EXCEPTION("div0_check"), + ARRAY_INDEX_OUT_OF_BOUNDS_EXCEPTION("range_check"), + ARRAY_STORE_EXCEPTION("array_check"), + CLASS_CAST_EXCEPTION("class_check"); + private final String reason; + ImplicitException(String reason) { + this.reason = reason; + } + public String getReason() { + return reason; + } + } + // TestMode represents a specific combination of the OmitStackTraceInFastThrow command line options. + // They will be set up in 'setFlags(TestMode testMode)' before a new test run starts. + public enum TestMode { + OMIT_STACKTRACES_IN_FASTTHROW, + STACKTRACES_IN_FASTTHROW + } + + private static final WhiteBox WB = WhiteBox.getWhiteBox(); + // The number of deoptimizations after which a method will be made not-entrant + private static final int PerBytecodeTrapLimit = WB.getIntxVMFlag("PerBytecodeTrapLimit").intValue(); + // The number of interpreter invocations after which a decompiled method will be re-compiled. + private static final int Tier0InvokeNotifyFreq = (int)Math.pow(2, WB.getIntxVMFlag("Tier0InvokeNotifyFreqLog")); + // The following variables are used to track the value of the global deopt counters between the various test phases. + private static int oldDeoptCount = 0; + private static HashMap<String, Integer> oldDeoptCountReason = new HashMap<String, Integer>(ImplicitException.values().length); + // The following two objects are declared statically to simplify the test method. + private static String[] string_a = new String[1]; + private static final Object o = new Object(); + + // This is the main test method. It will repeatedly called with the same ImplicitException 'type' to + // JIT-compile it, deoptimized it, re-compile it again and do various checks on the way. + // This process will be repeated then for each kind of ImplicitException 'type'. + public static Object throwImplicitException(ImplicitException type, Object[] object_a) { + switch (type) { + case NULL_POINTER_EXCEPTION: { + return object_a.length; + } + case INVOKE_NULL_POINTER_EXCEPTION: { + return object_a.hashCode(); + } + case ARITHMETIC_EXCEPTION: { + return ((42 / (object_a.length - 1)) > 2) ? null : object_a[0]; + } + case ARRAY_INDEX_OUT_OF_BOUNDS_EXCEPTION: { + return object_a[5]; + } + case ARRAY_STORE_EXCEPTION: { + return (object_a[0] = o); + } + case CLASS_CAST_EXCEPTION: { + return (ImplicitException[])object_a; + } + } + return null; + } + + // Completely unload (i.e. make "not-entrant"->"zombie"->"unload/free") a JIT-compiled + // version of a method and clear the method's profiling counters. + private static void unloadAndClean(Method m) { + WB.deoptimizeMethod(m); // Makes the nmethod "not entrant". + WB.forceNMethodSweep(); // Makes all "not entrant" nmethods "zombie". This requires + WB.forceNMethodSweep(); // two sweeps, see 'nmethod::can_convert_to_zombie()' for why. + WB.forceNMethodSweep(); // Need third sweep to actually unload/free all "zombie" nmethods. + System.gc(); + WB.clearMethodState(m); + } + + // Set '-XX' flags according to 'TestMode' + private static void setFlags(TestMode testMode) { + if (testMode == TestMode.OMIT_STACKTRACES_IN_FASTTHROW) { + WB.setBooleanVMFlag("OmitStackTraceInFastThrow", true); + } else { + WB.setBooleanVMFlag("OmitStackTraceInFastThrow", false); + } + + System.out.println("=========================================================="); + System.out.println("testMode=" + testMode + + " OmitStackTraceInFastThrow=" + WB.getBooleanVMFlag("OmitStackTraceInFastThrow")); + System.out.println("=========================================================="); + } + + private static void printCounters(TestMode testMode, ImplicitException impExcp, Method throwImplicitException_m, int invocations) { + System.out.println("testMode=" + testMode + " exception=" + impExcp + " invocations=" + invocations + "\n" + + "decompilecount=" + WB.getMethodDecompileCount(throwImplicitException_m) + " " + + "trapCount=" + WB.getMethodTrapCount(throwImplicitException_m) + " " + + "trapCount(" + impExcp.getReason() + ")=" + + WB.getMethodTrapCount(throwImplicitException_m, impExcp.getReason()) + " " + + "globalDeoptCount=" + WB.getDeoptCount() + " " + + "globalDeoptCount(" + impExcp.getReason() + ")=" + WB.getDeoptCount(impExcp.getReason(), null)); + System.out.println("method compiled=" + WB.isMethodCompiled(throwImplicitException_m)); + } + + // Checks after the test method has been JIT-compiled but before the compiled version has been invoked. + private static void checkSimple(TestMode testMode, ImplicitException impExcp, Exception ex, Method throwImplicitException_m, int invocations) { + + printCounters(testMode, impExcp, throwImplicitException_m, invocations); + // At this point, throwImplicitException() has been compiled but the compiled version has not been invoked yet. + Asserts.assertEQ(WB.getMethodCompilationLevel(throwImplicitException_m), 4, "Method should be compiled at level 4."); + + int trapCount = WB.getMethodTrapCount(throwImplicitException_m); + int trapCountSpecific = WB.getMethodTrapCount(throwImplicitException_m, impExcp.getReason()); + Asserts.assertEQ(trapCount, invocations, "Trap count must much invocation count."); + Asserts.assertEQ(trapCountSpecific, invocations, "Trap count must much invocation count."); + Asserts.assertNotNull(ex.getMessage(), "Exceptions thrown in the interpreter should have a message."); + } + + // Checks after the JIT-compiled test method has been invoked 'invocations' times. + private static void check(TestMode testMode, ImplicitException impExcp, Exception ex, + Method throwImplicitException_m, int invocations, int totalInvocations) { + + printCounters(testMode, impExcp, throwImplicitException_m, totalInvocations); + // At this point, the compiled version of 'throwImplicitException()' has been invoked 'invocations' times. + Asserts.assertEQ(WB.getMethodCompilationLevel(throwImplicitException_m), 4, "Method should be compiled at level 4."); + int deoptCount = WB.getDeoptCount(); + int deoptCountReason = WB.getDeoptCount(impExcp.getReason(), null/*action*/); + if (testMode == TestMode.OMIT_STACKTRACES_IN_FASTTHROW) { + // No deoptimizations for '-XX:+OmitStackTraceInFastThrow' + Asserts.assertEQ(oldDeoptCount, deoptCount, "Wrong number of deoptimizations."); + Asserts.assertEQ(oldDeoptCountReason.get(impExcp.getReason()), deoptCountReason, "Wrong number of deoptimizations."); + // '-XX:+OmitStackTraceInFastThrow' never has message because it is using a global singleton exception. + Asserts.assertNull(ex.getMessage(), "Optimized exceptions have no message."); + } else if (testMode == TestMode.STACKTRACES_IN_FASTTHROW) { + // We always deoptimize for '-XX:-OmitStackTraceInFastThrow + Asserts.assertEQ(oldDeoptCount + invocations, deoptCount, "Wrong number of deoptimizations."); + Asserts.assertEQ(oldDeoptCountReason.get(impExcp.getReason()) + invocations, deoptCountReason, "Wrong number of deoptimizations."); + Asserts.assertNotNull(ex.getMessage(), "Exceptions thrown in the interpreter should have a message."); + } else { + Asserts.fail("Unknown test mode."); + } + oldDeoptCount = deoptCount; + oldDeoptCountReason.put(impExcp.getReason(), deoptCountReason); + } + + public static void main(String[] args) throws Exception { + + if (!WB.getBooleanVMFlag("ProfileTraps")) { + // The fast-throw optimzation only works if we're running with -XX:+ProfileTraps + return; + } + + // Initialize global deopt counts to zero. + for (ImplicitException impExcp : ImplicitException.values()) { + oldDeoptCountReason.put(impExcp.getReason(), 0); + } + // Get a handle of the test method for usage with the WhiteBox API. + Method throwImplicitException_m = OptimizeImplicitExceptions.class + .getDeclaredMethod("throwImplicitException", new Class[] { ImplicitException.class, Object[].class}); + + for (TestMode testMode : TestMode.values()) { + setFlags(testMode); + for (ImplicitException impExcp : ImplicitException.values()) { + int invocations = 0; + Exception lastException = null; + + // Warmup and compile, but don't invoke compiled code. + while(!WB.isMethodCompiled(throwImplicitException_m)) { + invocations++; + try { + throwImplicitException(impExcp, impExcp.getReason().equals("null_check") ? null : string_a); + } catch (Exception catchedExcp) { + lastException = catchedExcp; + continue; + } + throw new Exception("Should not happen"); + } + + checkSimple(testMode, impExcp, lastException, throwImplicitException_m, invocations); + + // Invoke compiled code 'PerBytecodeTrapLimit' times. + for (int i = 0; i < PerBytecodeTrapLimit; i++) { + invocations++; + try { + throwImplicitException(impExcp, impExcp.getReason().equals("null_check") ? null : string_a); + } catch (Exception catchedExcp) { + lastException = catchedExcp; + continue; + } + throw new Exception("Should not happen"); + } + + check(testMode, impExcp, lastException, throwImplicitException_m, PerBytecodeTrapLimit, invocations); + + // Invoke compiled code 'Tier0InvokeNotifyFreq' times. + // If the method was de-compiled before, this will re-compile it again. + for (int i = 0; i < Tier0InvokeNotifyFreq; i++) { + invocations++; + try { + throwImplicitException(impExcp, impExcp.getReason().equals("null_check") ? null : string_a); + } catch (Exception catchedExcp) { + lastException = catchedExcp; + continue; + } + throw new Exception("Should not happen"); + } + + check(testMode, impExcp, lastException, throwImplicitException_m, Tier0InvokeNotifyFreq, invocations); + + // Invoke compiled code 'PerBytecodeTrapLimit' times. + for (int i = 0; i < PerBytecodeTrapLimit; i++) { + invocations++; + try { + throwImplicitException(impExcp, impExcp.getReason().equals("null_check") ? null : string_a); + } catch (Exception catchedExcp) { + lastException = catchedExcp; + continue; + } + throw new Exception("Should not happen"); + } + + check(testMode, impExcp, lastException, throwImplicitException_m, PerBytecodeTrapLimit, invocations); + + System.out.println("------------------------------------------------------------------"); + + unloadAndClean(throwImplicitException_m); + } + } + } +} diff --git a/test/hotspot/jtreg/compiler/intrinsics/base64/TestBase64.java b/test/hotspot/jtreg/compiler/intrinsics/base64/TestBase64.java index 5c9d41cb794d55cef3a51c1651c4b95a5511e37b..16c6749900d37b4ef96f40d1c41d66a7ab7ff06b 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/base64/TestBase64.java +++ b/test/hotspot/jtreg/compiler/intrinsics/base64/TestBase64.java @@ -48,6 +48,7 @@ import java.util.Base64.Decoder; import java.util.Base64.Encoder; import java.util.Objects; import java.util.Random; +import java.util.Arrays; import compiler.whitebox.CompilerWhiteBoxTest; import sun.hotspot.code.Compiler; @@ -79,9 +80,9 @@ public class TestBase64 { private static void warmup() { final int warmupCount = 20_000; - final int bufSize = 60; + final int bufSize = 15308; byte[] srcBuf = new byte[bufSize]; - byte[] encBuf = new byte[(bufSize / 3) * 4]; + byte[] encBuf = new byte[((bufSize + 2) / 3) * 4]; byte[] decBuf = new byte[bufSize]; ran.nextBytes(srcBuf); @@ -163,10 +164,13 @@ public class TestBase64 { assertEqual(resEncodeStr, encodedStr); // test int decode(byte[], byte[]) - resArr = new byte[srcArr.length]; + // JDK-8273108: Test for output buffer overrun + resArr = new byte[srcArr.length + 2]; + resArr[srcArr.length + 1] = (byte) 167; len = decoder.decode(encodedArr, resArr); assertEqual(len, srcArr.length); - assertEqual(resArr, srcArr); + assertEqual(Arrays.copyOfRange(resArr, 0, srcArr.length), srcArr); + assertEqual(resArr[srcArr.length + 1], (byte) 167); // test byte[] decode(byte[]) resArr = decoder.decode(encodedArr); diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index a995cad3f2d49a68a65aa6d5487c28e4ed2bec44..331e00e53a4f141195b7ff96c4f11d68c5d16cc7 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -133,6 +133,24 @@ public class IRNode { public static final String SCOPE_OBJECT = "(.*# ScObj.*" + END; public static final String MEMBAR = START + "MemBar" + MID + END; + public static final String AND_I = START + "AndI" + MID + END; + public static final String AND_L = START + "AndL" + MID + END; + public static final String LSHIFT_I = START + "LShiftI" + MID + END; + public static final String LSHIFT_L = START + "LShiftL" + MID + END; + public static final String ADD_I = START + "AddI" + MID + END; + public static final String ADD_L = START + "AddL" + MID + END; + public static final String SUB_I = START + "SubI" + MID + END; + public static final String SUB_L = START + "SubL" + MID + END; + public static final String CONV_I2L = START + "ConvI2L" + MID + END; + + public static final String VECTOR_CAST_B2X = START + "VectorCastB2X" + MID + END; + public static final String VECTOR_CAST_S2X = START + "VectorCastS2X" + MID + END; + public static final String VECTOR_CAST_I2X = START + "VectorCastI2X" + MID + END; + public static final String VECTOR_CAST_L2X = START + "VectorCastL2X" + MID + END; + public static final String VECTOR_CAST_F2X = START + "VectorCastF2X" + MID + END; + public static final String VECTOR_CAST_D2X = START + "VectorCastD2X" + MID + END; + public static final String VECTOR_REINTERPRET = START + "VectorReinterpret" + MID + END; + /** * Called by {@link IRMatcher} to merge special composite nodes together with additional user-defined input. */ diff --git a/test/hotspot/jtreg/compiler/longcountedloops/TestIVPhiTypeIncorrectAfterCCP.java b/test/hotspot/jtreg/compiler/longcountedloops/TestIVPhiTypeIncorrectAfterCCP.java new file mode 100644 index 0000000000000000000000000000000000000000..0c22c12f06f6cf29c0441c787c863f974eddeba8 --- /dev/null +++ b/test/hotspot/jtreg/compiler/longcountedloops/TestIVPhiTypeIncorrectAfterCCP.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2021, Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8277906 + * @summary Incorrect type for IV phi of long counted loops after CCP + * + * @run main/othervm -XX:-TieredCompilation -XX:CompileCommand=compileonly,TestIVPhiTypeIncorrectAfterCCP::test -XX:-BackgroundCompilation TestIVPhiTypeIncorrectAfterCCP + * + */ + +public class TestIVPhiTypeIncorrectAfterCCP { + + static int test() { + int array[] = new int[50]; + + float f = 0; + for (int i = 3; i < 49; i++) { + for (long l = 1; l < i; l++) { + array[(int)l] = i; + f += l; + } + } + int sum = 0; + for (int i = 0; i < array.length; i++) { + sum += array[i]; + } + return sum; + } + + public static void main(String[] args) { + long expected = test(); + for (int i = 0; i < 10_000; i++) { + int res = test(); + if (res != expected) { + throw new RuntimeException("Unexpected result: " + res + " != " + expected); + } + } + } +} diff --git a/test/hotspot/jtreg/compiler/loopopts/TestDeadPostLoopBecausePredicate.java b/test/hotspot/jtreg/compiler/loopopts/TestDeadPostLoopBecausePredicate.java new file mode 100644 index 0000000000000000000000000000000000000000..719de54204f2c8eba27f73fa6ee03ec3bf358787 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestDeadPostLoopBecausePredicate.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2021, Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8275330 + * @summary C2: assert(n->is_Root() || n->is_Region() || n->is_Phi() || n->is_MachMerge() || def_block->dominates(block)) failed: uses must be dominated by definitions + * + * @run main/othervm -Xmx512m -XX:+UnlockDiagnosticVMOptions -Xcomp -XX:CompileOnly=TestDeadPostLoopBecausePredicate TestDeadPostLoopBecausePredicate + * + */ + + +public class TestDeadPostLoopBecausePredicate { + + public static final int N = 400; + + public static int iFld=54270; + public static int iFld1=-4; + public int iFld2=201; + + public int mainTest(String[] strArr1) { + + int i=0, i17=8052, i19=22380, i20=60894, iArr[]=new int[N]; + init(iArr, 4); + + i = 1; + do { + for (i17 = 5; i17 < 114; i17++) { + switch ((i17 % 7) + 126) { + case 126: + for (i19 = 2; i19 > i; i19 -= 3) { + try { + i20 = (iFld2 % TestDeadPostLoopBecausePredicate.iFld1); + i20 = (iArr[i19 - 1] % TestDeadPostLoopBecausePredicate.iFld); + TestDeadPostLoopBecausePredicate.iFld = (TestDeadPostLoopBecausePredicate.iFld1 % iArr[i19]); + } catch (ArithmeticException a_e) {} + } + break; + } + } + } while (++i < 220); + + return i20; + } + + public static void init(int[] a, int seed) { + for (int j = 0; j < a.length; j++) { + a[j] = (j % 2 == 0) ? seed + j : seed - j; + } + } + + public static void main(String[] strArr) { + TestDeadPostLoopBecausePredicate _instance = new TestDeadPostLoopBecausePredicate(); + for (int i = 0; i < 10; i++ ) { + _instance.mainTest(strArr); + } + } +} diff --git a/test/hotspot/jtreg/compiler/loopopts/TestDepBetweenLoopAndPredicate.java b/test/hotspot/jtreg/compiler/loopopts/TestDepBetweenLoopAndPredicate.java new file mode 100644 index 0000000000000000000000000000000000000000..674ae02f239d035c0c9419d3491c5993d9c73236 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestDepBetweenLoopAndPredicate.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8277529 + * @summary RangeCheck should not be moved out of a loop if a node on the data input chain for the bool is dependent + * on the projection into the loop (after the predicates). + * @run main/othervm -Xbatch -XX:CompileCommand=compileonly,compiler.loopopts.TestDepBetweenLoopAndPredicate::test* + * compiler.loopopts.TestDepBetweenLoopAndPredicate + */ + +package compiler.loopopts; + +public class TestDepBetweenLoopAndPredicate { + static int x, y, z; + static boolean flag; + static int[] iArrFld = new int[25]; + static int[] iArrFld2 = new int[5]; + static int limit = 5; + + public static void main(String[] args) { + for (int i = 0; i < 10000; i++) { + flag = !flag; + test(); + } + + for (int i = 0; i < 5000; i++) { + flag = !flag; + test2(); + test3(); + test4(); + test5(); + } + } + + public static void test() { + int[] iArr = new int[20]; + System.arraycopy(iArrFld, x, iArr, y, 18); + + if (flag) { + return; + } + + for (int i = 0; i < limit; i++) { + iArr[19]++; + } + } + + public static void test2() { + for (int i = 0; i < limit; i++) { + int[] iArr = new int[20]; + System.arraycopy(iArrFld, x, iArr, y, 18); + + if (flag) { + return; + } + + for (int j = i; j < limit; j++) { + x = iArrFld[iArr[19]]; // No new offset node created + iArr[19]++; + } + } + } + + public static void test3() { + for (int i = 0; i < limit; i++) { + int[] iArr = new int[20]; + System.arraycopy(iArrFld, x, iArr, y, 18); + + if (flag) { + return; + } + + for (int j = i + 1; j < limit; j++) { + x = iArrFld[iArr[19]]; // New offset node created + iArr[19]++; + } + } + } + + public static void test4() { + for (int i = 0; i < limit; i++) { + int[] iArr = new int[20]; + System.arraycopy(iArrFld, x, iArr, y, 18); + + if (flag) { + return; + } + + for (int j = i + 1 + z; j < limit; j++) { + x = iArrFld[iArr[19]]; // New offset node created + iArr[19]++; + } + } + } + + public static void test5() { + for (int i = 0; i < limit; i++) { + int[] iArr = new int[20]; + System.arraycopy(iArrFld, x, iArr, y, 18); + + if (flag) { + return; + } + + for (int j = i + 1 + z; j < limit; j++) { + x = iArrFld[iArr[19]]; // New offset node created + iArr[19]++; + y += iArrFld2[3]; // Range check removed because not dependent on projection into the loop + } + } + } +} diff --git a/test/hotspot/jtreg/compiler/loopopts/TestEliminateNullCheckWithSplitIf.java b/test/hotspot/jtreg/compiler/loopopts/TestEliminateNullCheckWithSplitIf.java new file mode 100644 index 0000000000000000000000000000000000000000..e83b23255b396f0d3b7538462a0a42f86b1e0e0b --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestEliminateNullCheckWithSplitIf.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test + * @key stress randomness + * @bug 8275610 + * @summary Null check for field access of object floats above null check resulting in a segfault. + * @requires vm.compiler2.enabled + * @run main/othervm -Xbatch -XX:CompileCommand=compileonly,compiler.loopopts.TestEliminateNullCheckWithSplitIf::test + * -XX:+UnlockDiagnosticVMOptions -XX:+StressGCM -XX:StressSeed=42 compiler.loopopts.TestEliminateNullCheckWithSplitIf + * @run main/othervm -Xbatch -XX:CompileCommand=compileonly,compiler.loopopts.TestEliminateNullCheckWithSplitIf::test + * -XX:+UnlockDiagnosticVMOptions -XX:+StressGCM -XX:+StressIGVN compiler.loopopts.TestEliminateNullCheckWithSplitIf + */ + +package compiler.loopopts; + +public class TestEliminateNullCheckWithSplitIf { + public static int[] iArrFld = new int[20]; + public static int[] iArrFld2 = new int[20]; + public static int iFld = 10; + public static MyClass obj; + + public static void main(String[] strArr) { + for (int i = 0; i < 10000; i++) { + obj = (i % 100 == 0 ? null : new MyClass()); + test(); + } + } + + // The field access obj.iFld requires a null check NC3 and adds a not-null CastPP node on the succeeded projection. + // In the first IGVN after parsing, the null check NC3 can be subsumed by the explicit null check NC2. + // (done in IfNode::simple_subsuming()). The Bool node of NC2 is also shared with the same null check NC1 earlier. + // However, C2 cannot remove the null check NC2, yet, because the IR in between the two checks are too complex + // (IfNode::search_identical() fails). + // Now, loopopts are applied: + // (1) First, the split if optimization is done. It recognizes that NC1 and NC2 are back to back null checks and removes + // the null check NC2 by splitting it through the region R which is removed afterwards. In this process, control dependent + // data nodes on the out projections of NC2 end up at the new regions R1/R2 created for each projection for R. They get + // the last nodes of the if and else block as input. For this example, R1 is a control input to the CastPP node which + // will merge both true projections. + // (2) Later in loop opts, the loop L is transformed into normal code and y will become a constant 1. + // After loopopts, another round of IGVN is done: + // (These steps also depend on the order in which they are applied in order to trigger the bug) + // (1) The region R is removed because one path is dead (a result of the split if optimization). + // (2) The new If node added by the above split if optimization is also folded. This rewires the CastPP node to + // the last control node in the If block which is the true projection of range check RC2. Up until now, the CastPP + // is still after the null check NC1. + // (3) The range check RC2 is removed because the range check RC1 already covers this range (see RangeCheck::Ideal()). + // All data nodes which are control dependent on RC2 will be rewired to the dominating range check RC1, including + // the non-null CastPP node - which now has a control input above the null check NC1. This also means that the field + // load obj.iFld now has the same early control as the CastPP (CastPP -> AddP -> LoadI). Using StressGCM can + // now schedule the obj.iFld load before the null check NC1 because the early control allows it which leads to a + // segmentation fault if obj is null. + public static void test() { + int x = iArrFld[17]; // Emits range check RC1 + if (obj != null) { // Null check NC1 + int y = 0; + for (int i = 0; i < 1; i++) { // Loop L + y++; + } + // Use additional loop to keep the rangecheck for iArrFld[y] in before loopopts. + // y will become constant 1 but only once the loop above is removed in loopopts. + x = iArrFld[y]; // Emits range check RC2 + } else { + x = iArrFld2[18]; + } + // Region R merging the if and else paths above. + if (obj != null) { // Null check NC2 + x = iArrFld2[obj.iFld]; // Emits Null check NC3 for obj.iFld + } + } +} + +class MyClass { + int iFld; +} + + + + diff --git a/test/hotspot/jtreg/compiler/rangechecks/TestLongRangeCheck.java b/test/hotspot/jtreg/compiler/rangechecks/TestLongRangeCheck.java index 63a649b886b0a969fa8eb81e1ef3661571418cc3..d56d19278cfb84e435f6a41933fc8cc7095a8c2a 100644 --- a/test/hotspot/jtreg/compiler/rangechecks/TestLongRangeCheck.java +++ b/test/hotspot/jtreg/compiler/rangechecks/TestLongRangeCheck.java @@ -23,7 +23,7 @@ /** * @test - * @bug 8259609 + * @bug 8259609 8276116 * @summary C2: optimize long range checks in long counted loops * @requires vm.compiler2.enabled * @requires vm.compMode != "Xcomp" @@ -32,7 +32,7 @@ * @build sun.hotspot.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox * - * @run main/othervm -ea -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-BackgroundCompilation TestLongRangeCheck + * @run main/othervm -ea -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestLongRangeCheck * */ @@ -193,6 +193,115 @@ public class TestLongRangeCheck { m.invoke(null, 0, 100, Long.MAX_VALUE, Long.MAX_VALUE - 50, 0, 50); assertIsCompiled(m); } + + test("testStridePosScalePosInIntLoop", 0, 100, 100, 0); + + test("testStrideNegScaleNegInIntLoop", 0, 100, 100, 100); + + test("testStrideNegScalePosInIntLoop", 0, 100, 100, 0); + + test("testStridePosScaleNegInIntLoop", 0, 100, 100, 99); + + test("testStridePosScalePosNotOneInIntLoop", 0, 100, 1090, 0); + + test("testStrideNegScaleNegNotOneInIntLoop", 0, 100, 1090, 1100); + + test("testStrideNegScalePosNotOneInIntLoop", 0, 100, 1090, 0); + + test("testStridePosScaleNegNotOneInIntLoop", 0, 100, 1090, 1089); + + v = ((long)Integer.MAX_VALUE / 10000) * 9999; + + test("testStridePosNotOneScalePosInIntLoop", -v, v, v * 4, 2 * v); + + test("testStrideNegNotOneScaleNegInIntLoop", -v, v, v * 4, 2 * v); + + test("testStrideNegNotOneScalePosInIntLoop", -v, v, v * 4, 2 * v); + + test("testStridePosNotOneScaleNegInIntLoop", -v, v, v * 4, 2 * v - 1); + + // offset causes overflow + { + Method m = newClassLoader().loadClass("TestLongRangeCheck").getDeclaredMethod("testStridePosScalePosInIntLoop", long.class, long.class, long.class, long.class); + m.invoke(null, 0, 100, 100, 0); + compile(m); + + m.invoke(null, 0, 100, 100, 0); + assertIsCompiled(m); + try { + m.invoke(null, 0, 100, 100, Long.MAX_VALUE - 50); + throw new RuntimeException("should have thrown"); + } catch(InvocationTargetException e) { + if (!(e.getCause() instanceof IndexOutOfBoundsException)) { + throw new RuntimeException("unexpected exception"); + } + } + assertIsNotCompiled(m); + } + // no spurious deopt if the range check doesn't fail because not executed + { + Method m = newClassLoader().loadClass("TestLongRangeCheck").getDeclaredMethod("testStridePosScalePosConditional", long.class, long.class, long.class, long.class, long.class, long.class); + m.invoke(null, 0, 100, 100, 0, 0, 100); + compile(m); + + m.invoke(null, 0, 100, 100, -50, 50, 100); + assertIsCompiled(m); + } + { + Method m = newClassLoader().loadClass("TestLongRangeCheck").getDeclaredMethod("testStridePosScalePosConditional", long.class, long.class, long.class, long.class, long.class, long.class); + m.invoke(null, 0, 100, 100, 0, 0, 100); + compile(m); + + m.invoke(null, 0, 100, Long.MAX_VALUE, Long.MAX_VALUE - 50, 0, 50); + assertIsCompiled(m); + } + + test("testStridePosScalePosNotOneInIntLoop2", 0, 100, 1090, 0); + + test("testStrideNegScaleNegNotOneInIntLoop2", 0, 100, 1090, 1100); + + test("testStrideNegScalePosNotOneInIntLoop2", 0, 100, 1090, 0); + + test("testStridePosScaleNegNotOneInIntLoop2", 0, 100, 1090, 1089); + + { + Method m = newClassLoader().loadClass("TestLongRangeCheck").getDeclaredMethod("testStridePosScalePosInIntLoopOverflow", long.class, long.class, long.class, long.class); + long stride = 1 << 14; + long scale = 1 << 15; + long offset = stride * scale * 4; + long length = offset + stride * scale * 3 + 1; + long stop = stride * 5; + + m.invoke(null, 0, stop, length, offset); + compile(m); + + m.invoke(null, 0, stop, length, offset); + // deoptimizes even though no range check fails + } + { + Method m = newClassLoader().loadClass("TestLongRangeCheck").getDeclaredMethod("testStridePosScalePosInIntLoopOverflow", long.class, long.class, long.class, long.class); + long stride = 1 << 14; + long scale = 1 << 15; + long offset = stride * scale * 4; + long length = offset + stride * scale * 3 + 1; + long stop = stride * 5; + + m.invoke(null, 0, stop, length, offset); + compile(m); + + offset = 0; + stop = stride * 5; + + try { + m.invoke(null, 0, stop, length, offset); + throw new RuntimeException("should have thrown"); + } catch(InvocationTargetException e) { + if (!(e.getCause() instanceof IndexOutOfBoundsException)) { + throw new RuntimeException("unexpected exception"); + } + } + assertIsNotCompiled(m); + } } public static void testStridePosScalePos(long start, long stop, long length, long offset) { @@ -301,4 +410,177 @@ public class TestLongRangeCheck { } } } + + private static void checkInputs(long... inputs) { + for (int i = 0; i < inputs.length; i++) { + if ((long)((int)inputs[i]) != inputs[i]) { + throw new RuntimeException("bad arguments"); + } + } + } + + public static void testStridePosScalePosInIntLoop(long start, long stop, long length, long offset) { + checkInputs(start, stop); + final long scale = 1; + final int stride = 1; + for (int i = (int)start; i < (int)stop; i += stride) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + + public static void testStrideNegScaleNegInIntLoop(long start, long stop, long length, long offset) { + checkInputs(start, stop); + final long scale = -1; + final int stride = 1; + for (int i = (int)stop; i > (int)start; i -= stride) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + + public static void testStrideNegScalePosInIntLoop(long start, long stop, long length, long offset) { + checkInputs(start, stop); + final long scale = 1; + final int stride = 1; + for (int i = (int)(stop-1); i >= (int)start; i -= stride) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + + public static void testStridePosScaleNegInIntLoop(long start, long stop, long length, long offset) { + checkInputs(start, stop); + final long scale = -1; + final int stride = 1; + for (int i = (int)start; i < (int)stop; i += stride) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + + public static void testStridePosScalePosNotOneInIntLoop(long start, long stop, long length, long offset) { + checkInputs(start, stop); + final long scale = 11; + final int stride = 1; + for (int i = (int)start; i < (int)stop; i += stride) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + + public static void testStrideNegScaleNegNotOneInIntLoop(long start, long stop, long length, long offset) { + checkInputs(start, stop); + final long scale = -11; + final int stride = 1; + for (int i = (int)stop; i > (int)start; i -= stride) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + + public static void testStrideNegScalePosNotOneInIntLoop(long start, long stop, long length, long offset) { + checkInputs(start, stop); + final long scale = 11; + final int stride = 1; + for (int i = (int)(stop-1); i >= (int)start; i -= stride) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + + public static void testStridePosScaleNegNotOneInIntLoop(long start, long stop, long length, long offset) { + checkInputs(start, stop); + final long scale = -11; + final int stride = 1; + for (int i = (int)start; i < (int)stop; i += stride) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + + public static void testStridePosNotOneScalePosInIntLoop(long start, long stop, long length, long offset) { + checkInputs(start, stop); + final long scale = 2; + final int stride = Integer.MAX_VALUE / 10000; + for (int i = (int)start; i < (int)stop; i += stride) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + + public static void testStrideNegNotOneScaleNegInIntLoop(long start, long stop, long length, long offset) { + checkInputs(start, stop); + final long scale = -2; + final int stride = Integer.MAX_VALUE / 10000; + for (int i = (int)stop; i > (int)start; i -= stride) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + + public static void testStrideNegNotOneScalePosInIntLoop(long start, long stop, long length, long offset) { + checkInputs(start, stop); + final long scale = 2; + final int stride = Integer.MAX_VALUE / 10000; + for (int i = (int)(stop-1); i >= (int)start; i -= stride) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + + public static void testStridePosNotOneScaleNegInIntLoop(long start, long stop, long length, long offset) { + checkInputs(start, stop); + final long scale = -2; + final int stride = Integer.MAX_VALUE / 10000; + for (int i = (int)start; i < (int)stop; i += stride) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + + public static void testStridePosScalePosConditionalInIntLoop(long start, long stop, long length, long offset, long start2, long stop2) { + checkInputs(start, stop, start2, stop2); + Preconditions.checkIndex(0, length, null); + final long scale = 1; + final int stride = 1; + for (int i = (int)start; i < (int)stop; i += stride) { + if (i >= (int)start2 && i < (int)stop2) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + } + + public static void testStridePosScalePosNotOneInIntLoop2(long start, long stop, long length, long offset) { + checkInputs(start, stop); + final int scale = 11; + final int stride = 1; + for (int i = (int)start; i < (int)stop; i += stride) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + + public static void testStrideNegScaleNegNotOneInIntLoop2(long start, long stop, long length, long offset) { + checkInputs(start, stop); + final int scale = -11; + final int stride = 1; + for (int i = (int)stop; i > (int)start; i -= stride) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + + public static void testStrideNegScalePosNotOneInIntLoop2(long start, long stop, long length, long offset) { + checkInputs(start, stop); + final int scale = 11; + final int stride = 1; + for (int i = (int)(stop-1); i >= (int)start; i -= stride) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + + public static void testStridePosScaleNegNotOneInIntLoop2(long start, long stop, long length, long offset) { + checkInputs(start, stop); + final int scale = -11; + final int stride = 1; + for (int i = (int)start; i < (int)stop; i += stride) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + + public static void testStridePosScalePosInIntLoopOverflow(long start, long stop, long length, long offset) { + checkInputs(start, stop); + final int scale = 1 << 15; + final int stride = 1 << 14; + for (int i = (int)start; i < (int)stop; i += stride) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } } diff --git a/test/hotspot/jtreg/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java b/test/hotspot/jtreg/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java index 00eb0e2d27234160408b12448ec55d50c5e9abc9..782ab6b9b46dcd773534a69e5449c23d15f90698 100644 --- a/test/hotspot/jtreg/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java +++ b/test/hotspot/jtreg/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java @@ -60,10 +60,11 @@ public class IntrinsicPredicates { }; public static final BooleanSupplier MD5_INSTRUCTION_AVAILABLE - = // x86 variants + = new OrPredicate(new CPUSpecificPredicate("aarch64.*", null, null), + // x86 variants new OrPredicate(new CPUSpecificPredicate("amd64.*", null, null), new OrPredicate(new CPUSpecificPredicate("i386.*", null, null), - new CPUSpecificPredicate("x86.*", null, null))); + new CPUSpecificPredicate("x86.*", null, null)))); public static final BooleanSupplier SHA1_INSTRUCTION_AVAILABLE = new OrPredicate(new CPUSpecificPredicate("aarch64.*", new String[] { "sha1" }, null), diff --git a/test/hotspot/jtreg/compiler/uncommontrap/Decompile.java b/test/hotspot/jtreg/compiler/uncommontrap/Decompile.java new file mode 100644 index 0000000000000000000000000000000000000000..3ea6bb5cb29da0910540bdb7abd0b4b19fedb93d --- /dev/null +++ b/test/hotspot/jtreg/compiler/uncommontrap/Decompile.java @@ -0,0 +1,167 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + /* + * @test + * @bug 8275908 + * @summary Quick test for the new WhiteBox methods of JDK-8275908 + * + * @requires vm.compiler2.enabled & vm.compMode != "Xcomp" + * + * @library /test/lib + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -Xbatch -XX:-UseOnStackReplacement -XX:-TieredCompilation + * -XX:CompileCommand=compileonly,compiler.uncommontrap.Decompile::uncommonTrap + * -XX:CompileCommand=inline,compiler.uncommontrap.Decompile*::foo + * compiler.uncommontrap.Decompile + */ + +package compiler.uncommontrap; + +import java.lang.reflect.Method; + +import jdk.test.lib.Asserts; +import jdk.test.whitebox.WhiteBox; + +public class Decompile { + + private static final WhiteBox WB = WhiteBox.getWhiteBox(); + // The number of deoptimizations after which a method will be made not-entrant + private static final int PerBytecodeTrapLimit = WB.getIntxVMFlag("PerBytecodeTrapLimit").intValue(); + // The number of interpreter invocations after which a decompiled method will be re-compiled. + private static final int Tier0InvokeNotifyFreq = (int)Math.pow(2, WB.getIntxVMFlag("Tier0InvokeNotifyFreqLog")); + // VM builds without JVMCI like x86_32 call the bimorphic inlining trap just 'bimorphic' + // while all the other builds with JVMCI call it 'bimorphic_or_optimized_type_check'. + // Only builds with JVMCI have the "EnableJVMCI" flag. + private static final boolean isJVMCISupported = (WB.getBooleanVMFlag("EnableJVMCI") != null); + private static final String bimorphicTrapName = isJVMCISupported ? "bimorphic_or_optimized_type_check" : "bimorphic"; + + static class Base { + void foo() {} + } + static class X extends Base { + void foo() {} + } + static class Y extends Base { + void foo() {} + } + + static void uncommonTrap(Base t) { + t.foo(); + } + + private static void printCounters(Method uncommonTrap_m, int invocations) { + System.out.println("-----------------------------------------------------------------"); + System.out.println("invocations=" + invocations + " " + + "method compiled=" + WB.isMethodCompiled(uncommonTrap_m) + " " + + "decompileCount=" + WB.getMethodDecompileCount(uncommonTrap_m) + "\n" + + "trapCount=" + WB.getMethodTrapCount(uncommonTrap_m) + " " + + "trapCount(class_check)=" + WB.getMethodTrapCount(uncommonTrap_m, "class_check") + " " + + "trapCount(" + bimorphicTrapName + ")=" + + WB.getMethodTrapCount(uncommonTrap_m, bimorphicTrapName) + "\n" + + "globalDeoptCount=" + WB.getDeoptCount() + " " + + "globalDeoptCount(class_check)=" + WB.getDeoptCount("class_check", null) + " " + + "globalDeoptCount(" + bimorphicTrapName + ")=" + + WB.getDeoptCount(bimorphicTrapName, null)); + System.out.println("-----------------------------------------------------------------"); + } + + private static void check(Method uncommonTrap_m, int invocations, boolean isCompiled, int decompileCount, + int trapCount, int trapCountClassCheck, int trapCountBimorphic, + int deoptCount, int deoptCountClassCheck, int deoptCountBimorphic) { + + printCounters(uncommonTrap_m, invocations); + + Asserts.assertEQ(isCompiled, WB.isMethodCompiled(uncommonTrap_m), + "Wrong compilation status."); + Asserts.assertEQ(decompileCount, WB.getMethodDecompileCount(uncommonTrap_m), + "Wrong number of decompilations."); + Asserts.assertEQ(trapCount, WB.getMethodTrapCount(uncommonTrap_m), + "Wrong number of traps."); + Asserts.assertEQ(trapCountClassCheck, WB.getMethodTrapCount(uncommonTrap_m, "class_check"), + "Wrong number of traps."); + Asserts.assertEQ(trapCountBimorphic, WB.getMethodTrapCount(uncommonTrap_m, bimorphicTrapName), + "Wrong number of traps."); + Asserts.assertEQ(deoptCount, WB.getDeoptCount(), + "Wrong number of deoptimizations."); + Asserts.assertEQ(deoptCountClassCheck, WB.getDeoptCount("class_check", null), + "Wrong number of class_check deoptimizations."); + Asserts.assertEQ(deoptCountBimorphic, WB.getDeoptCount(bimorphicTrapName, null), + "Wrong number of " + bimorphicTrapName + "deoptimizations."); + } + public static void main(String[] args) throws Exception { + + // Get a handle of the test method for usage with the WhiteBox API. + Method uncommonTrap_m = Decompile.class + .getDeclaredMethod("uncommonTrap", new Class[] { Base.class }); + + int invocations = 0; + Base b = new Base(); + // This is a little tricky :) We have to define 'x' already here otherwise + // the class 'X' won't be loaded and 'uncommonTrap()' will be compiled without + // a class check but a CHA dependency that class 'B' has no subtypes. + X x = new X(); + Y y = new Y(); + + // Warmup and compile with an object of type 'Base' as receiver, but don't invoke compiled code. + while(!WB.isMethodCompiled(uncommonTrap_m)) { + invocations++; + uncommonTrap(b); + } + check(uncommonTrap_m, invocations, true /* is_compiled */, 0 /* decompileCount */, + 0 /* trapCount */, 0 /* trapCountClassCheck */, 0 /* trapCountBimorphic */, + 0 /* deoptCount */, 0 /* deoptCountClassCheck */, 0 /* deoptCountBimorphic */); + + // Invoke compiled code 'PerBytecodeTrapLimit' times with an receiver object of type 'X'. + // This should deoptimize 'PerBytecodeTrapLimit' times and finally decompile the method. + for (int i = 0; i < PerBytecodeTrapLimit; i++) { + invocations++; + uncommonTrap(x); + } + check(uncommonTrap_m, invocations, false /* is_compiled */, 1 /* decompileCount */, + PerBytecodeTrapLimit /* trapCount */, PerBytecodeTrapLimit /* trapCountClassCheck */, 0 /* trapCountBimorphic */, + PerBytecodeTrapLimit /* deoptCount */, PerBytecodeTrapLimit /* deoptCountClassCheck */, 0 /* deoptCountBimorphic */); + + // Invoke the method 'Tier0InvokeNotifyFreq' more times with an receiver object of type 'X'. + // This should re-compile the method again with bimorphic inlining for receiver types 'Base' and 'X'. + for (int i = 0; i < Tier0InvokeNotifyFreq; i++) { + invocations++; + uncommonTrap(x); + } + check(uncommonTrap_m, invocations, true /* is_compiled */, 1 /* decompileCount */, + PerBytecodeTrapLimit /* trapCount */, PerBytecodeTrapLimit /* trapCountClassCheck */, 0 /* trapCountBimorphic */, + PerBytecodeTrapLimit /* deoptCount */, PerBytecodeTrapLimit /* deoptCountClassCheck */, 0 /* deoptCountBimorphic */); + + // Invoke compiled code 'PerBytecodeTrapLimit' times with an receiver object of type 'Y'. + // This should deoptimize 'PerBytecodeTrapLimit' times and finally decompile the method. + for (int i = 0; i < PerBytecodeTrapLimit; i++) { + invocations++; + uncommonTrap(y); + } + check(uncommonTrap_m, invocations, false /* is_compiled */, 2 /* decompileCount */, + 2*PerBytecodeTrapLimit /* trapCount */, PerBytecodeTrapLimit /* trapCountClassCheck */, PerBytecodeTrapLimit /* trapCountBimorphic */, + 2*PerBytecodeTrapLimit /* deoptCount */, PerBytecodeTrapLimit /* deoptCountClassCheck */, PerBytecodeTrapLimit /* deoptCountBimorphic */); + } +} \ No newline at end of file diff --git a/test/hotspot/jtreg/compiler/uncommontrap/TraceDeoptimizationNoRealloc.java b/test/hotspot/jtreg/compiler/uncommontrap/TraceDeoptimizationNoRealloc.java index 4a371a525b3889ce5bade9e0da2c087e70051f71..4cd10a1a63e9ede9950d16ed48f84eaac10d6d2e 100644 --- a/test/hotspot/jtreg/compiler/uncommontrap/TraceDeoptimizationNoRealloc.java +++ b/test/hotspot/jtreg/compiler/uncommontrap/TraceDeoptimizationNoRealloc.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ * @summary -XX:+TraceDeoptimization tries to print realloc'ed objects even when there are none * * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement - * -XX:+IgnoreUnrecognizedVMOptions -XX:+TraceDeoptimization + * -XX:+UnlockDiagnosticVMOptions -XX:+TraceDeoptimization * compiler.uncommontrap.TraceDeoptimizationNoRealloc */ diff --git a/test/hotspot/jtreg/compiler/vectorapi/VectorMaskLoadStoreTest.java b/test/hotspot/jtreg/compiler/vectorapi/VectorMaskLoadStoreTest.java index 669608b824b6a2aae78d7e519e2846bba14bd3e6..655681f87a83cfa5e5daae9ecb71d063d79ae227 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/VectorMaskLoadStoreTest.java +++ b/test/hotspot/jtreg/compiler/vectorapi/VectorMaskLoadStoreTest.java @@ -49,6 +49,18 @@ import org.testng.annotations.Test; * @run testng/othervm -XX:-TieredCompilation -XX:CompileThreshold=100 compiler.vectorapi.VectorMaskLoadStoreTest */ +/** + * @test + * @bug 8278584 + * @library /test/lib + * @summary Test the codegen for C2's VectorLongToMaskNode + * "-XX:DisableIntrinsic=_VectorMaskOp" is required to break "VectorMaskToLong (VectorLongToMask l) ==> l" opt. + * This is because when _VectorMaskOp is disabled, VectorMaskToLong won't be generated. + * @modules jdk.incubator.vector + * + * @run testng/othervm -XX:-TieredCompilation -XX:CompileThreshold=100 -XX:+UnlockDiagnosticVMOptions + * -XX:DisableIntrinsic=_VectorMaskOp compiler.vectorapi.VectorMaskLoadStoreTest + */ public class VectorMaskLoadStoreTest{ diff --git a/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastAVX1.java b/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastAVX1.java new file mode 100644 index 0000000000000000000000000000000000000000..a83364fa51cd8a029a80fdb2bad12089f28b5ab1 --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastAVX1.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.vectorapi.reshape; + +import compiler.vectorapi.reshape.tests.TestVectorCast; +import compiler.vectorapi.reshape.utils.TestCastMethods; +import compiler.vectorapi.reshape.utils.VectorReshapeHelper; + +/* + * @test + * @bug 8259610 + * @modules jdk.incubator.vector + * @modules java.base/jdk.internal.misc + * @summary Test that vector cast intrinsics work as intended on avx1. + * @requires vm.cpu.features ~= ".*avx.*" + * @library /test/lib / + * @run driver compiler.vectorapi.reshape.TestVectorCastAVX1 + */ +public class TestVectorCastAVX1 { + public static void main(String[] args) { + VectorReshapeHelper.runMainHelper( + TestVectorCast.class, + TestCastMethods.AVX1_CAST_TESTS.stream(), + "-XX:UseAVX=1"); + } +} diff --git a/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastAVX2.java b/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastAVX2.java new file mode 100644 index 0000000000000000000000000000000000000000..1b50613598b2669b12b7aa2c43311d7d4d48a69e --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastAVX2.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.vectorapi.reshape; + +import compiler.vectorapi.reshape.tests.TestVectorCast; +import compiler.vectorapi.reshape.utils.TestCastMethods; +import compiler.vectorapi.reshape.utils.VectorReshapeHelper; + +/* + * @test + * @bug 8259610 + * @modules jdk.incubator.vector + * @modules java.base/jdk.internal.misc + * @summary Test that vector cast intrinsics work as intended on avx2. + * @requires vm.cpu.features ~= ".*avx2.*" + * @library /test/lib / + * @run driver compiler.vectorapi.reshape.TestVectorCastAVX2 + */ +public class TestVectorCastAVX2 { + public static void main(String[] args) { + VectorReshapeHelper.runMainHelper( + TestVectorCast.class, + TestCastMethods.AVX2_CAST_TESTS.stream(), + "-XX:UseAVX=2"); + } +} + diff --git a/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastAVX512.java b/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastAVX512.java new file mode 100644 index 0000000000000000000000000000000000000000..749c6a21e06ef4c3d3f1bc01c59f644da12a134f --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastAVX512.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.vectorapi.reshape; + +import compiler.vectorapi.reshape.tests.TestVectorCast; +import compiler.vectorapi.reshape.utils.TestCastMethods; +import compiler.vectorapi.reshape.utils.VectorReshapeHelper; + +/* + * @test + * @bug 8259610 + * @modules jdk.incubator.vector + * @modules java.base/jdk.internal.misc + * @summary Test that vector cast intrinsics work as intended on avx512. + * @requires vm.cpu.features ~= ".*avx512.*" + * @library /test/lib / + * @run driver compiler.vectorapi.reshape.TestVectorCastAVX512 + */ +public class TestVectorCastAVX512 { + public static void main(String[] args) { + VectorReshapeHelper.runMainHelper( + TestVectorCast.class, + TestCastMethods.AVX512_CAST_TESTS.stream(), + "-XX:UseAVX=3"); + } +} + diff --git a/test/hotspot/jtreg/runtime/NMT/ChangeTrackingLevel.java b/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastAVX512DQ.java similarity index 52% rename from test/hotspot/jtreg/runtime/NMT/ChangeTrackingLevel.java rename to test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastAVX512DQ.java index 0cc059c13b93dec578f16e7c5ad2c98595b4b8dd..8799cccd918415912c378b4245bc680bbab0a280 100644 --- a/test/hotspot/jtreg/runtime/NMT/ChangeTrackingLevel.java +++ b/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastAVX512DQ.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,29 +21,28 @@ * questions. */ +package compiler.vectorapi.reshape; + +import compiler.vectorapi.reshape.tests.TestVectorCast; +import compiler.vectorapi.reshape.utils.TestCastMethods; +import compiler.vectorapi.reshape.utils.VectorReshapeHelper; + /* * @test - * @bug 8059100 - * @summary Test that you can decrease NMT tracking level but not increase it. + * @bug 8259610 + * @modules jdk.incubator.vector * @modules java.base/jdk.internal.misc - * @library /test/lib - * @build sun.hotspot.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail ChangeTrackingLevel + * @summary Test that vector cast intrinsics work as intended on avx512dq. + * @requires vm.cpu.features ~= ".*avx512dq.*" + * @library /test/lib / + * @run driver compiler.vectorapi.reshape.TestVectorCastAVX512DQ */ - -import sun.hotspot.WhiteBox; - -public class ChangeTrackingLevel { - - public static WhiteBox wb = WhiteBox.getWhiteBox(); - public static void main(String args[]) throws Exception { - boolean testChangeLevel = wb.NMTChangeTrackingLevel(); - if (testChangeLevel) { - System.out.println("NMT level change test passed."); - } else { - // it also fails if the VM asserts. - throw new RuntimeException("NMT level change test failed"); - } +public class TestVectorCastAVX512DQ { + public static void main(String[] args) { + VectorReshapeHelper.runMainHelper( + TestVectorCast.class, + TestCastMethods.AVX512DQ_CAST_TESTS.stream(), + "-XX:UseAVX=3"); } -}; +} + diff --git a/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastNeon.java b/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastNeon.java new file mode 100644 index 0000000000000000000000000000000000000000..11777a3ccfcf8b211021285017fcb0d4f3f75de5 --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastNeon.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.vectorapi.reshape; + +import compiler.vectorapi.reshape.tests.TestVectorCast; +import compiler.vectorapi.reshape.utils.TestCastMethods; +import compiler.vectorapi.reshape.utils.VectorReshapeHelper; + +/* + * @test + * @bug 8259610 + * @modules jdk.incubator.vector + * @modules java.base/jdk.internal.misc + * @summary Test that vector cast intrinsics work as intended on neon. + * @requires vm.cpu.features ~= ".*simd.*" + * @library /test/lib / + * @run driver compiler.vectorapi.reshape.TestVectorCastNeon + */ +public class TestVectorCastNeon { + public static void main(String[] args) { + VectorReshapeHelper.runMainHelper( + TestVectorCast.class, + TestCastMethods.NEON_CAST_TESTS.stream(), + "-XX:+UseNeon"); + } +} + + diff --git a/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastSVE.java b/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastSVE.java new file mode 100644 index 0000000000000000000000000000000000000000..614e8e870de43ae4a286258a6379f5f6f44bbde5 --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastSVE.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.vectorapi.reshape; + +import compiler.vectorapi.reshape.tests.TestVectorCast; +import compiler.vectorapi.reshape.utils.TestCastMethods; +import compiler.vectorapi.reshape.utils.VectorReshapeHelper; + +/* + * @test + * @bug 8259610 + * @modules jdk.incubator.vector + * @modules java.base/jdk.internal.misc + * @summary Test that vector cast intrinsics work as intended on sve. + * @requires vm.cpu.features ~= ".*sve.*" + * @library /test/lib / + * @run driver compiler.vectorapi.reshape.TestVectorCastSVE + */ +public class TestVectorCastSVE { + public static void main(String[] args) { + VectorReshapeHelper.runMainHelper( + TestVectorCast.class, + TestCastMethods.SVE_CAST_TESTS.stream(), + "-XX:UseSVE=1"); + } +} + + diff --git a/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorReinterpret.java b/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorReinterpret.java new file mode 100644 index 0000000000000000000000000000000000000000..10f67bc9668447970daace5d851ee1dbe4dc02b9 --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorReinterpret.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.vectorapi.reshape; + +import compiler.vectorapi.reshape.tests.TestVectorDoubleExpandShrink; +import compiler.vectorapi.reshape.tests.TestVectorExpandShrink; +import compiler.vectorapi.reshape.tests.TestVectorRebracket; +import compiler.vectorapi.reshape.utils.VectorReshapeHelper; +import compiler.vectorapi.reshape.utils.VectorSpeciesPair; +import java.util.List; +import jdk.incubator.vector.VectorShape; +import jdk.incubator.vector.VectorSpecies; + +/* + * @test + * @bug 8259610 + * @modules jdk.incubator.vector + * @modules java.base/jdk.internal.misc + * @summary Test that vector reinterpret intrinsics work as intended. + * @library /test/lib / + * @run driver compiler.vectorapi.reshape.TestVectorReinterpret + */ +public class TestVectorReinterpret { + private static final List<VectorShape> SHAPE_LIST = List.of(VectorShape.values()); + private static final List<Class<?>> ETYPE_LIST = List.of( + byte.class, short.class, int.class, long.class, float.class, double.class + ); + + public static void main(String[] args) { + VectorReshapeHelper.runMainHelper( + TestVectorExpandShrink.class, + SHAPE_LIST.stream() + .flatMap(s -> SHAPE_LIST.stream() + .filter(t -> t.vectorBitSize() != s.vectorBitSize()) + .map(t -> VectorSpeciesPair.makePair(VectorSpecies.of(byte.class, s), + VectorSpecies.of(byte.class, t)))) + ); + + VectorReshapeHelper.runMainHelper( + TestVectorDoubleExpandShrink.class, + SHAPE_LIST.stream() + .flatMap(s -> SHAPE_LIST.stream() + .filter(t -> t.vectorBitSize() != s.vectorBitSize()) + .map(t -> VectorSpeciesPair.makePair(VectorSpecies.of(byte.class, s), + VectorSpecies.of(byte.class, t)))) + ); + + VectorReshapeHelper.runMainHelper( + TestVectorRebracket.class, + SHAPE_LIST.stream() + .flatMap(shape -> ETYPE_LIST.stream() + .flatMap(etype -> ETYPE_LIST.stream() + .filter(ftype -> ftype != etype) + .map(ftype -> VectorSpeciesPair.makePair(VectorSpecies.of(etype, shape), + VectorSpecies.of(ftype, shape))))) + .filter(p -> p.isp().length() > 1 && p.osp().length() > 1), + "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED" + ); + } +} diff --git a/test/hotspot/jtreg/compiler/vectorapi/reshape/tests/TestVectorCast.java b/test/hotspot/jtreg/compiler/vectorapi/reshape/tests/TestVectorCast.java new file mode 100644 index 0000000000000000000000000000000000000000..c33cd924771bcbd16dd6d615593ce4d6565c9110 --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorapi/reshape/tests/TestVectorCast.java @@ -0,0 +1,1359 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.vectorapi.reshape.tests; + +import compiler.lib.ir_framework.IR; +import compiler.lib.ir_framework.Run; +import compiler.lib.ir_framework.Test; + +import static compiler.vectorapi.reshape.utils.VectorReshapeHelper.*; +import static jdk.incubator.vector.VectorOperators.*; + +/** + * This class contains all possible cast operations between different vector species. + * The methods only take into consideration the actual cast in C2, as the vectors are + * ofter shrunk or expanded before/after casting if the element numbers mismatch. + * In each cast, the VectorCastNode is expected to appear exactly once. + */ +public class TestVectorCast { + @Test + @IR(counts = {B2X_NODE, "1"}) + public static void testB64toS64(byte[] input, byte[] output) { + vectorCast(B2S, BSPEC64, SSPEC64, input, output); + } + + @Run(test = "testB64toS64") + public static void runB64toS64() throws Throwable { + runCastHelper(B2S, BSPEC64, SSPEC64); + } + + @Test + @IR(counts = {B2X_NODE, "1"}) + public static void testB64toS128(byte[] input, byte[] output) { + vectorCast(B2S, BSPEC64, SSPEC128, input, output); + } + + @Run(test = "testB64toS128") + public static void runB64toS128() throws Throwable { + runCastHelper(B2S, BSPEC64, SSPEC128); + } + + @Test + @IR(counts = {B2X_NODE, "1"}) + public static void testB128toS256(byte[] input, byte[] output) { + vectorCast(B2S, BSPEC128, SSPEC256, input, output); + } + + @Run(test = "testB128toS256") + public static void runB128toS256() throws Throwable { + runCastHelper(B2S, BSPEC128, SSPEC256); + } + + @Test + @IR(counts = {B2X_NODE, "1"}) + public static void testB256toS512(byte[] input, byte[] output) { + vectorCast(B2S, BSPEC256, SSPEC512, input, output); + } + + @Run(test = "testB256toS512") + public static void runB256toS512() throws Throwable { + runCastHelper(B2S, BSPEC256, SSPEC512); + } + + @Test + @IR(counts = {B2X_NODE, "1"}) + public static void testB64toI64(byte[] input, byte[] output) { + vectorCast(B2I, BSPEC64, ISPEC64, input, output); + } + + @Run(test = "testB64toI64") + public static void runB64toI64() throws Throwable { + runCastHelper(B2I, BSPEC64, ISPEC64); + } + + @Test + @IR(counts = {B2X_NODE, "1"}) + public static void testB64toI128(byte[] input, byte[] output) { + vectorCast(B2I, BSPEC64, ISPEC128, input, output); + } + + @Run(test = "testB64toI128") + public static void runB64toI128() throws Throwable { + runCastHelper(B2I, BSPEC64, ISPEC128); + } + + @Test + @IR(counts = {B2X_NODE, "1"}) + public static void testB64toI256(byte[] input, byte[] output) { + vectorCast(B2I, BSPEC64, ISPEC256, input, output); + } + + @Run(test = "testB64toI256") + public static void runB64toI256() throws Throwable { + runCastHelper(B2I, BSPEC64, ISPEC256); + } + + @Test + @IR(counts = {B2X_NODE, "1"}) + public static void testB128toI512(byte[] input, byte[] output) { + vectorCast(B2I, BSPEC128, ISPEC512, input, output); + } + + @Run(test = "testB128toI512") + public static void runB128toI512() throws Throwable { + runCastHelper(B2I, BSPEC128, ISPEC512); + } + + @Test + @IR(counts = {B2X_NODE, "1"}) + public static void testB64toL64(byte[] input, byte[] output) { + vectorCast(B2L, BSPEC64, LSPEC64, input, output); + } + + @Run(test = "testB64toL64") + public static void runB64toL64() throws Throwable { + runCastHelper(B2L, BSPEC64, LSPEC64); + } + + @Test + @IR(counts = {B2X_NODE, "1"}) + public static void testB64toL128(byte[] input, byte[] output) { + vectorCast(B2L, BSPEC64, LSPEC128, input, output); + } + + @Run(test = "testB64toL128") + public static void runB64toL128() throws Throwable { + runCastHelper(B2L, BSPEC64, LSPEC128); + } + + @Test + @IR(counts = {B2X_NODE, "1"}) + public static void testB64toL256(byte[] input, byte[] output) { + vectorCast(B2L, BSPEC64, LSPEC256, input, output); + } + + @Run(test = "testB64toL256") + public static void runB64toL256() throws Throwable { + runCastHelper(B2L, BSPEC64, LSPEC256); + } + + @Test + @IR(counts = {B2X_NODE, "1"}) + public static void testB64toL512(byte[] input, byte[] output) { + vectorCast(B2L, BSPEC64, LSPEC512, input, output); + } + + @Run(test = "testB64toL512") + public static void runB64toL512() throws Throwable { + runCastHelper(B2L, BSPEC64, LSPEC512); + } + + @Test + @IR(counts = {B2X_NODE, "1"}) + public static void testB64toF64(byte[] input, byte[] output) { + vectorCast(B2F, BSPEC64, FSPEC64, input, output); + } + + @Run(test = "testB64toF64") + public static void runB64toF64() throws Throwable { + runCastHelper(B2F, BSPEC64, FSPEC64); + } + + @Test + @IR(counts = {B2X_NODE, "1"}) + public static void testB64toF128(byte[] input, byte[] output) { + vectorCast(B2F, BSPEC64, FSPEC128, input, output); + } + + @Run(test = "testB64toF128") + public static void runB64toF128() throws Throwable { + runCastHelper(B2F, BSPEC64, FSPEC128); + } + + @Test + @IR(counts = {B2X_NODE, "1"}) + public static void testB64toF256(byte[] input, byte[] output) { + vectorCast(B2F, BSPEC64, FSPEC256, input, output); + } + + @Run(test = "testB64toF256") + public static void runB64toF256() throws Throwable { + runCastHelper(B2F, BSPEC64, FSPEC256); + } + + @Test + @IR(counts = {B2X_NODE, "1"}) + public static void testB128toF512(byte[] input, byte[] output) { + vectorCast(B2F, BSPEC128, FSPEC512, input, output); + } + + @Run(test = "testB128toF512") + public static void runB128toF512() throws Throwable { + runCastHelper(B2F, BSPEC128, FSPEC512); + } + + @Test + @IR(counts = {B2X_NODE, "1"}) + public static void testB64toD64(byte[] input, byte[] output) { + vectorCast(B2D, BSPEC64, DSPEC64, input, output); + } + + @Run(test = "testB64toD64") + public static void runB64toD64() throws Throwable { + runCastHelper(B2D, BSPEC64, DSPEC64); + } + + @Test + @IR(counts = {B2X_NODE, "1"}) + public static void testB64toD128(byte[] input, byte[] output) { + vectorCast(B2D, BSPEC64, DSPEC128, input, output); + } + + @Run(test = "testB64toD128") + public static void runB64toD128() throws Throwable { + runCastHelper(B2D, BSPEC64, DSPEC128); + } + + @Test + @IR(counts = {B2X_NODE, "1"}) + public static void testB64toD256(byte[] input, byte[] output) { + vectorCast(B2D, BSPEC64, DSPEC256, input, output); + } + + @Run(test = "testB64toD256") + public static void runB64toD256() throws Throwable { + runCastHelper(B2D, BSPEC64, DSPEC256); + } + + @Test + @IR(counts = {B2X_NODE, "1"}) + public static void testB64toD512(byte[] input, byte[] output) { + vectorCast(B2D, BSPEC64, DSPEC512, input, output); + } + + @Run(test = "testB64toD512") + public static void runB64toD512() throws Throwable { + runCastHelper(B2D, BSPEC64, DSPEC512); + } + + @Test + @IR(counts = {S2X_NODE, "1"}) + public static void testS64toB64(byte[] input, byte[] output) { + vectorCast(S2B, SSPEC64, BSPEC64, input, output); + } + + @Run(test = "testS64toB64") + public static void runS64toB64() throws Throwable { + runCastHelper(S2B, SSPEC64, BSPEC64); + } + + @Test + @IR(counts = {S2X_NODE, "1"}) + public static void testS128toB64(byte[] input, byte[] output) { + vectorCast(S2B, SSPEC128, BSPEC64, input, output); + } + + @Run(test = "testS128toB64") + public static void runS128toB64() throws Throwable { + runCastHelper(S2B, SSPEC128, BSPEC64); + } + + @Test + @IR(counts = {S2X_NODE, "1"}) + public static void testS256toB128(byte[] input, byte[] output) { + vectorCast(S2B, SSPEC256, BSPEC128, input, output); + } + + @Run(test = "testS256toB128") + public static void runS256toB128() throws Throwable { + runCastHelper(S2B, SSPEC256, BSPEC128); + } + + @Test + @IR(counts = {S2X_NODE, "1"}) + public static void testS512toB256(byte[] input, byte[] output) { + vectorCast(S2B, SSPEC512, BSPEC256, input, output); + } + + @Run(test = "testS512toB256") + public static void runS512toB256() throws Throwable { + runCastHelper(S2B, SSPEC512, BSPEC256); + } + + @Test + @IR(counts = {S2X_NODE, "1"}) + public static void testS64toI64(byte[] input, byte[] output) { + vectorCast(S2I, SSPEC64, ISPEC64, input, output); + } + + @Run(test = "testS64toI64") + public static void runS64toI64() throws Throwable { + runCastHelper(S2I, SSPEC64, ISPEC64); + } + + @Test + @IR(counts = {S2X_NODE, "1"}) + public static void testS64toI128(byte[] input, byte[] output) { + vectorCast(S2I, SSPEC64, ISPEC128, input, output); + } + + @Run(test = "testS64toI128") + public static void runS64toI128() throws Throwable { + runCastHelper(S2I, SSPEC64, ISPEC128); + } + + @Test + @IR(counts = {S2X_NODE, "1"}) + public static void testS128toI256(byte[] input, byte[] output) { + vectorCast(S2I, SSPEC128, ISPEC256, input, output); + } + + @Run(test = "testS128toI256") + public static void runS128toI256() throws Throwable { + runCastHelper(S2I, SSPEC128, ISPEC256); + } + + @Test + @IR(counts = {S2X_NODE, "1"}) + public static void testS256toI512(byte[] input, byte[] output) { + vectorCast(S2I, SSPEC256, ISPEC512, input, output); + } + + @Run(test = "testS256toI512") + public static void runS256toI512() throws Throwable { + runCastHelper(S2I, SSPEC256, ISPEC512); + } + + @Test + @IR(counts = {S2X_NODE, "1"}) + public static void testS64toL64(byte[] input, byte[] output) { + vectorCast(S2L, SSPEC64, LSPEC64, input, output); + } + + @Run(test = "testS64toL64") + public static void runS64toL64() throws Throwable { + runCastHelper(S2L, SSPEC64, LSPEC64); + } + + @Test + @IR(counts = {S2X_NODE, "1"}) + public static void testS64toL128(byte[] input, byte[] output) { + vectorCast(S2L, SSPEC64, LSPEC128, input, output); + } + + @Run(test = "testS64toL128") + public static void runS64toL128() throws Throwable { + runCastHelper(S2L, SSPEC64, LSPEC128); + } + + @Test + @IR(counts = {S2X_NODE, "1"}) + public static void testS64toL256(byte[] input, byte[] output) { + vectorCast(S2L, SSPEC64, LSPEC256, input, output); + } + + @Run(test = "testS64toL256") + public static void runS64toL256() throws Throwable { + runCastHelper(S2L, SSPEC64, LSPEC256); + } + + @Test + @IR(counts = {S2X_NODE, "1"}) + public static void testS128toL512(byte[] input, byte[] output) { + vectorCast(S2L, SSPEC128, LSPEC512, input, output); + } + + @Run(test = "testS128toL512") + public static void runS128toL512() throws Throwable { + runCastHelper(S2L, SSPEC128, LSPEC512); + } + + @Test + @IR(counts = {S2X_NODE, "1"}) + public static void testS64toF64(byte[] input, byte[] output) { + vectorCast(S2F, SSPEC64, FSPEC64, input, output); + } + + @Run(test = "testS64toF64") + public static void runS64toF64() throws Throwable { + runCastHelper(S2F, SSPEC64, FSPEC64); + } + + @Test + @IR(counts = {S2X_NODE, "1"}) + public static void testS64toF128(byte[] input, byte[] output) { + vectorCast(S2F, SSPEC64, FSPEC128, input, output); + } + + @Run(test = "testS64toF128") + public static void runS64toF128() throws Throwable { + runCastHelper(S2F, SSPEC64, FSPEC128); + } + + @Test + @IR(counts = {S2X_NODE, "1"}) + public static void testS128toF256(byte[] input, byte[] output) { + vectorCast(S2F, SSPEC128, FSPEC256, input, output); + } + + @Run(test = "testS128toF256") + public static void runS128toF256() throws Throwable { + runCastHelper(S2F, SSPEC128, FSPEC256); + } + + @Test + @IR(counts = {S2X_NODE, "1"}) + public static void testS256toF512(byte[] input, byte[] output) { + vectorCast(S2F, SSPEC256, FSPEC512, input, output); + } + + @Run(test = "testS256toF512") + public static void runS256toF512() throws Throwable { + runCastHelper(S2F, SSPEC256, FSPEC512); + } + + @Test + @IR(counts = {S2X_NODE, "1"}) + public static void testS64toD64(byte[] input, byte[] output) { + vectorCast(S2D, SSPEC64, DSPEC64, input, output); + } + + @Run(test = "testS64toD64") + public static void runS64toD64() throws Throwable { + runCastHelper(S2D, SSPEC64, DSPEC64); + } + + @Test + @IR(counts = {S2X_NODE, "1"}) + public static void testS64toD128(byte[] input, byte[] output) { + vectorCast(S2D, SSPEC64, DSPEC128, input, output); + } + + @Run(test = "testS64toD128") + public static void runS64toD128() throws Throwable { + runCastHelper(S2D, SSPEC64, DSPEC128); + } + + @Test + @IR(counts = {S2X_NODE, "1"}) + public static void testS64toD256(byte[] input, byte[] output) { + vectorCast(S2D, SSPEC64, DSPEC256, input, output); + } + + @Run(test = "testS64toD256") + public static void runS64toD256() throws Throwable { + runCastHelper(S2D, SSPEC64, DSPEC256); + } + + @Test + @IR(counts = {S2X_NODE, "1"}) + public static void testS128toD512(byte[] input, byte[] output) { + vectorCast(S2D, SSPEC128, DSPEC512, input, output); + } + + @Run(test = "testS128toD512") + public static void runS128toD512() throws Throwable { + runCastHelper(S2D, SSPEC128, DSPEC512); + } + + @Test + @IR(counts = {I2X_NODE, "1"}) + public static void testI64toB64(byte[] input, byte[] output) { + vectorCast(I2B, ISPEC64, BSPEC64, input, output); + } + + @Run(test = "testI64toB64") + public static void runI64toB64() throws Throwable { + runCastHelper(I2B, ISPEC64, BSPEC64); + } + + @Test + @IR(counts = {I2X_NODE, "1"}) + public static void testI128toB64(byte[] input, byte[] output) { + vectorCast(I2B, ISPEC128, BSPEC64, input, output); + } + + @Run(test = "testI128toB64") + public static void runI128toB64() throws Throwable { + runCastHelper(I2B, ISPEC128, BSPEC64); + } + + @Test + @IR(counts = {I2X_NODE, "1"}) + public static void testI256toB64(byte[] input, byte[] output) { + vectorCast(I2B, ISPEC256, BSPEC64, input, output); + } + + @Run(test = "testI256toB64") + public static void runI256toB64() throws Throwable { + runCastHelper(I2B, ISPEC256, BSPEC64); + } + + @Test + @IR(counts = {I2X_NODE, "1"}) + public static void testI512toB128(byte[] input, byte[] output) { + vectorCast(I2B, ISPEC512, BSPEC128, input, output); + } + + @Run(test = "testI512toB128") + public static void runI512toB128() throws Throwable { + runCastHelper(I2B, ISPEC512, BSPEC128); + } + + @Test + @IR(counts = {I2X_NODE, "1"}) + public static void testI64toS64(byte[] input, byte[] output) { + vectorCast(I2S, ISPEC64, SSPEC64, input, output); + } + + @Run(test = "testI64toS64") + public static void runI64toS64() throws Throwable { + runCastHelper(I2S, ISPEC64, SSPEC64); + } + + @Test + @IR(counts = {I2X_NODE, "1"}) + public static void testI128toS64(byte[] input, byte[] output) { + vectorCast(I2S, ISPEC128, SSPEC64, input, output); + } + + @Run(test = "testI128toS64") + public static void runI128toS64() throws Throwable { + runCastHelper(I2S, ISPEC128, SSPEC64); + } + + @Test + @IR(counts = {I2X_NODE, "1"}) + public static void testI256toS128(byte[] input, byte[] output) { + vectorCast(I2S, ISPEC256, SSPEC128, input, output); + } + + @Run(test = "testI256toS128") + public static void runI256toS128() throws Throwable { + runCastHelper(I2S, ISPEC256, SSPEC128); + } + + @Test + @IR(counts = {I2X_NODE, "1"}) + public static void testI512toS256(byte[] input, byte[] output) { + vectorCast(I2S, ISPEC512, SSPEC256, input, output); + } + + @Run(test = "testI512toS256") + public static void runI512toS256() throws Throwable { + runCastHelper(I2S, ISPEC512, SSPEC256); + } + + @Test + @IR(counts = {I2X_NODE, "1"}) + public static void testI64toL64(byte[] input, byte[] output) { + vectorCast(I2L, ISPEC64, LSPEC64, input, output); + } + + @Run(test = "testI64toL64") + public static void runI64toL64() throws Throwable { + runCastHelper(I2L, ISPEC64, LSPEC64); + } + + @Test + @IR(counts = {I2X_NODE, "1"}) + public static void testI64toL128(byte[] input, byte[] output) { + vectorCast(I2L, ISPEC64, LSPEC128, input, output); + } + + @Run(test = "testI64toL128") + public static void runI64toL128() throws Throwable { + runCastHelper(I2L, ISPEC64, LSPEC128); + } + + @Test + @IR(counts = {I2X_NODE, "1"}) + public static void testI128toL256(byte[] input, byte[] output) { + vectorCast(I2L, ISPEC128, LSPEC256, input, output); + } + + @Run(test = "testI128toL256") + public static void runI128toL256() throws Throwable { + runCastHelper(I2L, ISPEC128, LSPEC256); + } + + @Test + @IR(counts = {I2X_NODE, "1"}) + public static void testI256toL512(byte[] input, byte[] output) { + vectorCast(I2L, ISPEC256, LSPEC512, input, output); + } + + @Run(test = "testI256toL512") + public static void runI256toL512() throws Throwable { + runCastHelper(I2L, ISPEC256, LSPEC512); + } + + @Test + @IR(counts = {I2X_NODE, "1"}) + public static void testI64toF64(byte[] input, byte[] output) { + vectorCast(I2F, ISPEC64, FSPEC64, input, output); + } + + @Run(test = "testI64toF64") + public static void runI64toF64() throws Throwable { + runCastHelper(I2F, ISPEC64, FSPEC64); + } + + @Test + @IR(counts = {I2X_NODE, "1"}) + public static void testI128toF128(byte[] input, byte[] output) { + vectorCast(I2F, ISPEC128, FSPEC128, input, output); + } + + @Run(test = "testI128toF128") + public static void runI128toF128() throws Throwable { + runCastHelper(I2F, ISPEC128, FSPEC128); + } + + @Test + @IR(counts = {I2X_NODE, "1"}) + public static void testI256toF256(byte[] input, byte[] output) { + vectorCast(I2F, ISPEC256, FSPEC256, input, output); + } + + @Run(test = "testI256toF256") + public static void runI256toF256() throws Throwable { + runCastHelper(I2F, ISPEC256, FSPEC256); + } + + @Test + @IR(counts = {I2X_NODE, "1"}) + public static void testI512toF512(byte[] input, byte[] output) { + vectorCast(I2F, ISPEC512, FSPEC512, input, output); + } + + @Run(test = "testI512toF512") + public static void runI512toF512() throws Throwable { + runCastHelper(I2F, ISPEC512, FSPEC512); + } + + @Test + @IR(counts = {I2X_NODE, "1"}) + public static void testI64toD64(byte[] input, byte[] output) { + vectorCast(I2D, ISPEC64, DSPEC64, input, output); + } + + @Run(test = "testI64toD64") + public static void runI64toD64() throws Throwable { + runCastHelper(I2D, ISPEC64, DSPEC64); + } + + @Test + @IR(counts = {I2X_NODE, "1"}) + public static void testI64toD128(byte[] input, byte[] output) { + vectorCast(I2D, ISPEC64, DSPEC128, input, output); + } + + @Run(test = "testI64toD128") + public static void runI64toD128() throws Throwable { + runCastHelper(I2D, ISPEC64, DSPEC128); + } + + @Test + @IR(counts = {I2X_NODE, "1"}) + public static void testI128toD256(byte[] input, byte[] output) { + vectorCast(I2D, ISPEC128, DSPEC256, input, output); + } + + @Run(test = "testI128toD256") + public static void runI128toD256() throws Throwable { + runCastHelper(I2D, ISPEC128, DSPEC256); + } + + @Test + @IR(counts = {I2X_NODE, "1"}) + public static void testI256toD512(byte[] input, byte[] output) { + vectorCast(I2D, ISPEC256, DSPEC512, input, output); + } + + @Run(test = "testI256toD512") + public static void runI256toD512() throws Throwable { + runCastHelper(I2D, ISPEC256, DSPEC512); + } + + @Test + @IR(counts = {L2X_NODE, "1"}) + public static void testL64toB64(byte[] input, byte[] output) { + vectorCast(L2B, LSPEC64, BSPEC64, input, output); + } + + @Run(test = "testL64toB64") + public static void runL64toB64() throws Throwable { + runCastHelper(L2B, LSPEC64, BSPEC64); + } + + @Test + @IR(counts = {L2X_NODE, "1"}) + public static void testL128toB64(byte[] input, byte[] output) { + vectorCast(L2B, LSPEC128, BSPEC64, input, output); + } + + @Run(test = "testL128toB64") + public static void runL128toB64() throws Throwable { + runCastHelper(L2B, LSPEC128, BSPEC64); + } + + @Test + @IR(counts = {L2X_NODE, "1"}) + public static void testL256toB64(byte[] input, byte[] output) { + vectorCast(L2B, LSPEC256, BSPEC64, input, output); + } + + @Run(test = "testL256toB64") + public static void runL256toB64() throws Throwable { + runCastHelper(L2B, LSPEC256, BSPEC64); + } + + @Test + @IR(counts = {L2X_NODE, "1"}) + public static void testL512toB64(byte[] input, byte[] output) { + vectorCast(L2B, LSPEC512, BSPEC64, input, output); + } + + @Run(test = "testL512toB64") + public static void runL512toB64() throws Throwable { + runCastHelper(L2B, LSPEC512, BSPEC64); + } + + @Test + @IR(counts = {L2X_NODE, "1"}) + public static void testL64toS64(byte[] input, byte[] output) { + vectorCast(L2S, LSPEC64, SSPEC64, input, output); + } + + @Run(test = "testL64toS64") + public static void runL64toS64() throws Throwable { + runCastHelper(L2S, LSPEC64, SSPEC64); + } + + @Test + @IR(counts = {L2X_NODE, "1"}) + public static void testL128toS64(byte[] input, byte[] output) { + vectorCast(L2S, LSPEC128, SSPEC64, input, output); + } + + @Run(test = "testL128toS64") + public static void runL128toS64() throws Throwable { + runCastHelper(L2S, LSPEC128, SSPEC64); + } + + @Test + @IR(counts = {L2X_NODE, "1"}) + public static void testL256toS64(byte[] input, byte[] output) { + vectorCast(L2S, LSPEC256, SSPEC64, input, output); + } + + @Run(test = "testL256toS64") + public static void runL256toS64() throws Throwable { + runCastHelper(L2S, LSPEC256, SSPEC64); + } + + @Test + @IR(counts = {L2X_NODE, "1"}) + public static void testL512toS128(byte[] input, byte[] output) { + vectorCast(L2S, LSPEC512, SSPEC128, input, output); + } + + @Run(test = "testL512toS128") + public static void runL512toS128() throws Throwable { + runCastHelper(L2S, LSPEC512, SSPEC128); + } + + @Test + @IR(counts = {L2X_NODE, "1"}) + public static void testL64toI64(byte[] input, byte[] output) { + vectorCast(L2I, LSPEC64, ISPEC64, input, output); + } + + @Run(test = "testL64toI64") + public static void runL64toI64() throws Throwable { + runCastHelper(L2I, LSPEC64, ISPEC64); + } + + @Test + @IR(counts = {L2X_NODE, "1"}) + public static void testL128toI64(byte[] input, byte[] output) { + vectorCast(L2I, LSPEC128, ISPEC64, input, output); + } + + @Run(test = "testL128toI64") + public static void runL128toI64() throws Throwable { + runCastHelper(L2I, LSPEC128, ISPEC64); + } + + @Test + @IR(counts = {L2X_NODE, "1"}) + public static void testL256toI128(byte[] input, byte[] output) { + vectorCast(L2I, LSPEC256, ISPEC128, input, output); + } + + @Run(test = "testL256toI128") + public static void runL256toI128() throws Throwable { + runCastHelper(L2I, LSPEC256, ISPEC128); + } + + @Test + @IR(counts = {L2X_NODE, "1"}) + public static void testL512toI256(byte[] input, byte[] output) { + vectorCast(L2I, LSPEC512, ISPEC256, input, output); + } + + @Run(test = "testL512toI256") + public static void runL512toI256() throws Throwable { + runCastHelper(L2I, LSPEC512, ISPEC256); + } + + @Test + @IR(counts = {L2X_NODE, "1"}) + public static void testL64toF64(byte[] input, byte[] output) { + vectorCast(L2F, LSPEC64, FSPEC64, input, output); + } + + @Run(test = "testL64toF64") + public static void runL64toF64() throws Throwable { + runCastHelper(L2F, LSPEC64, FSPEC64); + } + + @Test + @IR(counts = {L2X_NODE, "1"}) + public static void testL128toF64(byte[] input, byte[] output) { + vectorCast(L2F, LSPEC128, FSPEC64, input, output); + } + + @Run(test = "testL128toF64") + public static void runL128toF64() throws Throwable { + runCastHelper(L2F, LSPEC128, FSPEC64); + } + + @Test + @IR(counts = {L2X_NODE, "1"}) + public static void testL256toF128(byte[] input, byte[] output) { + vectorCast(L2F, LSPEC256, FSPEC128, input, output); + } + + @Run(test = "testL256toF128") + public static void runL256toF128() throws Throwable { + runCastHelper(L2F, LSPEC256, FSPEC128); + } + + @Test + @IR(counts = {L2X_NODE, "1"}) + public static void testL512toF256(byte[] input, byte[] output) { + vectorCast(L2F, LSPEC512, FSPEC256, input, output); + } + + @Run(test = "testL512toF256") + public static void runL512toF256() throws Throwable { + runCastHelper(L2F, LSPEC512, FSPEC256); + } + + @Test + @IR(counts = {L2X_NODE, "1"}) + public static void testL64toD64(byte[] input, byte[] output) { + vectorCast(L2D, LSPEC64, DSPEC64, input, output); + } + + @Run(test = "testL64toD64") + public static void runL64toD64() throws Throwable { + runCastHelper(L2D, LSPEC64, DSPEC64); + } + + @Test + @IR(counts = {L2X_NODE, "1"}) + public static void testL128toD128(byte[] input, byte[] output) { + vectorCast(L2D, LSPEC128, DSPEC128, input, output); + } + + @Run(test = "testL128toD128") + public static void runL128toD128() throws Throwable { + runCastHelper(L2D, LSPEC128, DSPEC128); + } + + @Test + @IR(counts = {L2X_NODE, "1"}) + public static void testL256toD256(byte[] input, byte[] output) { + vectorCast(L2D, LSPEC256, DSPEC256, input, output); + } + + @Run(test = "testL256toD256") + public static void runL256toD256() throws Throwable { + runCastHelper(L2D, LSPEC256, DSPEC256); + } + + @Test + @IR(counts = {L2X_NODE, "1"}) + public static void testL512toD512(byte[] input, byte[] output) { + vectorCast(L2D, LSPEC512, DSPEC512, input, output); + } + + @Run(test = "testL512toD512") + public static void runL512toD512() throws Throwable { + runCastHelper(L2D, LSPEC512, DSPEC512); + } + + @Test + @IR(counts = {F2X_NODE, "1"}) + public static void testF64toB64(byte[] input, byte[] output) { + vectorCast(F2B, FSPEC64, BSPEC64, input, output); + } + + @Run(test = "testF64toB64") + public static void runF64toB64() throws Throwable { + runCastHelper(F2B, FSPEC64, BSPEC64); + } + + @Test + @IR(counts = {F2X_NODE, "1"}) + public static void testF128toB64(byte[] input, byte[] output) { + vectorCast(F2B, FSPEC128, BSPEC64, input, output); + } + + @Run(test = "testF128toB64") + public static void runF128toB64() throws Throwable { + runCastHelper(F2B, FSPEC128, BSPEC64); + } + + @Test + @IR(counts = {F2X_NODE, "1"}) + public static void testF256toB64(byte[] input, byte[] output) { + vectorCast(F2B, FSPEC256, BSPEC64, input, output); + } + + @Run(test = "testF256toB64") + public static void runF256toB64() throws Throwable { + runCastHelper(F2B, FSPEC256, BSPEC64); + } + + @Test + @IR(counts = {F2X_NODE, "1"}) + public static void testF512toB128(byte[] input, byte[] output) { + vectorCast(F2B, FSPEC512, BSPEC128, input, output); + } + + @Run(test = "testF512toB128") + public static void runF512toB128() throws Throwable { + runCastHelper(F2B, FSPEC512, BSPEC128); + } + + @Test + @IR(counts = {F2X_NODE, "1"}) + public static void testF64toS64(byte[] input, byte[] output) { + vectorCast(F2S, FSPEC64, SSPEC64, input, output); + } + + @Run(test = "testF64toS64") + public static void runF64toS64() throws Throwable { + runCastHelper(F2S, FSPEC64, SSPEC64); + } + + @Test + @IR(counts = {F2X_NODE, "1"}) + public static void testF128toS64(byte[] input, byte[] output) { + vectorCast(F2S, FSPEC128, SSPEC64, input, output); + } + + @Run(test = "testF128toS64") + public static void runF128toS64() throws Throwable { + runCastHelper(F2S, FSPEC128, SSPEC64); + } + + @Test + @IR(counts = {F2X_NODE, "1"}) + public static void testF256toS128(byte[] input, byte[] output) { + vectorCast(F2S, FSPEC256, SSPEC128, input, output); + } + + @Run(test = "testF256toS128") + public static void runF256toS128() throws Throwable { + runCastHelper(F2S, FSPEC256, SSPEC128); + } + + @Test + @IR(counts = {F2X_NODE, "1"}) + public static void testF512toS256(byte[] input, byte[] output) { + vectorCast(F2S, FSPEC512, SSPEC256, input, output); + } + + @Run(test = "testF512toS256") + public static void runF512toS256() throws Throwable { + runCastHelper(F2S, FSPEC512, SSPEC256); + } + + @Test + @IR(counts = {F2X_NODE, "1"}) + public static void testF64toL64(byte[] input, byte[] output) { + vectorCast(F2L, FSPEC64, LSPEC64, input, output); + } + + @Run(test = "testF64toL64") + public static void runF64toL64() throws Throwable { + runCastHelper(F2L, FSPEC64, LSPEC64); + } + + @Test + @IR(counts = {F2X_NODE, "1"}) + public static void testF64toL128(byte[] input, byte[] output) { + vectorCast(F2L, FSPEC64, LSPEC128, input, output); + } + + @Run(test = "testF64toL128") + public static void runF64toL128() throws Throwable { + runCastHelper(F2L, FSPEC64, LSPEC128); + } + + @Test + @IR(counts = {F2X_NODE, "1"}) + public static void testF128toL256(byte[] input, byte[] output) { + vectorCast(F2L, FSPEC128, LSPEC256, input, output); + } + + @Run(test = "testF128toL256") + public static void runF128toL256() throws Throwable { + runCastHelper(F2L, FSPEC128, LSPEC256); + } + + @Test + @IR(counts = {F2X_NODE, "1"}) + public static void testF256toL512(byte[] input, byte[] output) { + vectorCast(F2L, FSPEC256, LSPEC512, input, output); + } + + @Run(test = "testF256toL512") + public static void runF256toL512() throws Throwable { + runCastHelper(F2L, FSPEC256, LSPEC512); + } + + @Test + @IR(counts = {F2X_NODE, "1"}) + public static void testF64toI64(byte[] input, byte[] output) { + vectorCast(F2I, FSPEC64, ISPEC64, input, output); + } + + @Run(test = "testF64toI64") + public static void runF64toI64() throws Throwable { + runCastHelper(F2I, FSPEC64, ISPEC64); + } + + @Test + @IR(counts = {F2X_NODE, "1"}) + public static void testF128toI128(byte[] input, byte[] output) { + vectorCast(F2I, FSPEC128, ISPEC128, input, output); + } + + @Run(test = "testF128toI128") + public static void runF128toI128() throws Throwable { + runCastHelper(F2I, FSPEC128, ISPEC128); + } + + @Test + @IR(counts = {F2X_NODE, "1"}) + public static void testF256toI256(byte[] input, byte[] output) { + vectorCast(F2I, FSPEC256, ISPEC256, input, output); + } + + @Run(test = "testF256toI256") + public static void runF256toI256() throws Throwable { + runCastHelper(F2I, FSPEC256, ISPEC256); + } + + @Test + @IR(counts = {F2X_NODE, "1"}) + public static void testF512toI512(byte[] input, byte[] output) { + vectorCast(F2I, FSPEC512, ISPEC512, input, output); + } + + @Run(test = "testF512toI512") + public static void runF512toI512() throws Throwable { + runCastHelper(F2I, FSPEC512, ISPEC512); + } + + @Test + @IR(counts = {F2X_NODE, "1"}) + public static void testF64toD64(byte[] input, byte[] output) { + vectorCast(F2D, FSPEC64, DSPEC64, input, output); + } + + @Run(test = "testF64toD64") + public static void runF64toD64() throws Throwable { + runCastHelper(F2D, FSPEC64, DSPEC64); + } + + @Test + @IR(counts = {F2X_NODE, "1"}) + public static void testF64toD128(byte[] input, byte[] output) { + vectorCast(F2D, FSPEC64, DSPEC128, input, output); + } + + @Run(test = "testF64toD128") + public static void runF64toD128() throws Throwable { + runCastHelper(F2D, FSPEC64, DSPEC128); + } + + @Test + @IR(counts = {F2X_NODE, "1"}) + public static void testF128toD256(byte[] input, byte[] output) { + vectorCast(F2D, FSPEC128, DSPEC256, input, output); + } + + @Run(test = "testF128toD256") + public static void runF128toD256() throws Throwable { + runCastHelper(F2D, FSPEC128, DSPEC256); + } + + @Test + @IR(counts = {F2X_NODE, "1"}) + public static void testF256toD512(byte[] input, byte[] output) { + vectorCast(F2D, FSPEC256, DSPEC512, input, output); + } + + @Run(test = "testF256toD512") + public static void runF256toD512() throws Throwable { + runCastHelper(F2D, FSPEC256, DSPEC512); + } + + @Test + @IR(counts = {D2X_NODE, "1"}) + public static void testD64toB64(byte[] input, byte[] output) { + vectorCast(D2B, DSPEC64, BSPEC64, input, output); + } + + @Run(test = "testD64toB64") + public static void runD64toB64() throws Throwable { + runCastHelper(D2B, DSPEC64, BSPEC64); + } + + @Test + @IR(counts = {D2X_NODE, "1"}) + public static void testD128toB64(byte[] input, byte[] output) { + vectorCast(D2B, DSPEC128, BSPEC64, input, output); + } + + @Run(test = "testD128toB64") + public static void runD128toB64() throws Throwable { + runCastHelper(D2B, DSPEC128, BSPEC64); + } + + @Test + @IR(counts = {D2X_NODE, "1"}) + public static void testD256toB64(byte[] input, byte[] output) { + vectorCast(D2B, DSPEC256, BSPEC64, input, output); + } + + @Run(test = "testD256toB64") + public static void runD256toB64() throws Throwable { + runCastHelper(D2B, DSPEC256, BSPEC64); + } + + @Test + @IR(counts = {D2X_NODE, "1"}) + public static void testD512toB64(byte[] input, byte[] output) { + vectorCast(D2B, DSPEC512, BSPEC64, input, output); + } + + @Run(test = "testD512toB64") + public static void runD512toB64() throws Throwable { + runCastHelper(D2B, DSPEC512, BSPEC64); + } + + @Test + @IR(counts = {D2X_NODE, "1"}) + public static void testD64toS64(byte[] input, byte[] output) { + vectorCast(D2S, DSPEC64, SSPEC64, input, output); + } + + @Run(test = "testD64toS64") + public static void runD64toS64() throws Throwable { + runCastHelper(D2S, DSPEC64, SSPEC64); + } + + @Test + @IR(counts = {D2X_NODE, "1"}) + public static void testD128toS64(byte[] input, byte[] output) { + vectorCast(D2S, DSPEC128, SSPEC64, input, output); + } + + @Run(test = "testD128toS64") + public static void runD128toS64() throws Throwable { + runCastHelper(D2S, DSPEC128, SSPEC64); + } + + @Test + @IR(counts = {D2X_NODE, "1"}) + public static void testD256toS64(byte[] input, byte[] output) { + vectorCast(D2S, DSPEC256, SSPEC64, input, output); + } + + @Run(test = "testD256toS64") + public static void runD256toS64() throws Throwable { + runCastHelper(D2S, DSPEC256, SSPEC64); + } + + @Test + @IR(counts = {D2X_NODE, "1"}) + public static void testD512toS128(byte[] input, byte[] output) { + vectorCast(D2S, DSPEC512, SSPEC128, input, output); + } + + @Run(test = "testD512toS128") + public static void runD512toS128() throws Throwable { + runCastHelper(D2S, DSPEC512, SSPEC128); + } + + @Test + @IR(counts = {D2X_NODE, "1"}) + public static void testD64toI64(byte[] input, byte[] output) { + vectorCast(D2I, DSPEC64, ISPEC64, input, output); + } + + @Run(test = "testD64toI64") + public static void runD64toI64() throws Throwable { + runCastHelper(D2I, DSPEC64, ISPEC64); + } + + @Test + @IR(counts = {D2X_NODE, "1"}) + public static void testD128toI64(byte[] input, byte[] output) { + vectorCast(D2I, DSPEC128, ISPEC64, input, output); + } + + @Run(test = "testD128toI64") + public static void runD128toI64() throws Throwable { + runCastHelper(D2I, DSPEC128, ISPEC64); + } + + @Test + @IR(counts = {D2X_NODE, "1"}) + public static void testD256toI128(byte[] input, byte[] output) { + vectorCast(D2I, DSPEC256, ISPEC128, input, output); + } + + @Run(test = "testD256toI128") + public static void runD256toI128() throws Throwable { + runCastHelper(D2I, DSPEC256, ISPEC128); + } + + @Test + @IR(counts = {D2X_NODE, "1"}) + public static void testD512toI256(byte[] input, byte[] output) { + vectorCast(D2I, DSPEC512, ISPEC256, input, output); + } + + @Run(test = "testD512toI256") + public static void runD512toI256() throws Throwable { + runCastHelper(D2I, DSPEC512, ISPEC256); + } + + @Test + @IR(counts = {D2X_NODE, "1"}) + public static void testD64toF64(byte[] input, byte[] output) { + vectorCast(D2F, DSPEC64, FSPEC64, input, output); + } + + @Run(test = "testD64toF64") + public static void runD64toF64() throws Throwable { + runCastHelper(D2F, DSPEC64, FSPEC64); + } + + @Test + @IR(counts = {D2X_NODE, "1"}) + public static void testD128toF64(byte[] input, byte[] output) { + vectorCast(D2F, DSPEC128, FSPEC64, input, output); + } + + @Run(test = "testD128toF64") + public static void runD128toF64() throws Throwable { + runCastHelper(D2F, DSPEC128, FSPEC64); + } + + @Test + @IR(counts = {D2X_NODE, "1"}) + public static void testD256toF128(byte[] input, byte[] output) { + vectorCast(D2F, DSPEC256, FSPEC128, input, output); + } + + @Run(test = "testD256toF128") + public static void runD256toF128() throws Throwable { + runCastHelper(D2F, DSPEC256, FSPEC128); + } + + @Test + @IR(counts = {D2X_NODE, "1"}) + public static void testD512toF256(byte[] input, byte[] output) { + vectorCast(D2F, DSPEC512, FSPEC256, input, output); + } + + @Run(test = "testD512toF256") + public static void runD512toF256() throws Throwable { + runCastHelper(D2F, DSPEC512, FSPEC256); + } + + @Test + @IR(counts = {D2X_NODE, "1"}) + public static void testD64toL64(byte[] input, byte[] output) { + vectorCast(D2L, DSPEC64, LSPEC64, input, output); + } + + @Run(test = "testD64toL64") + public static void runD64toL64() throws Throwable { + runCastHelper(D2L, DSPEC64, LSPEC64); + } + + @Test + @IR(counts = {D2X_NODE, "1"}) + public static void testD128toL128(byte[] input, byte[] output) { + vectorCast(D2L, DSPEC128, LSPEC128, input, output); + } + + @Run(test = "testD128toL128") + public static void runD128toL128() throws Throwable { + runCastHelper(D2L, DSPEC128, LSPEC128); + } + + @Test + @IR(counts = {D2X_NODE, "1"}) + public static void testD256toL256(byte[] input, byte[] output) { + vectorCast(D2L, DSPEC256, LSPEC256, input, output); + } + + @Run(test = "testD256toL256") + public static void runD256toL256() throws Throwable { + runCastHelper(D2L, DSPEC256, LSPEC256); + } + + @Test + @IR(counts = {D2X_NODE, "1"}) + public static void testD512toL512(byte[] input, byte[] output) { + vectorCast(D2L, DSPEC512, LSPEC512, input, output); + } + + @Run(test = "testD512toL512") + public static void runD512toL512() throws Throwable { + runCastHelper(D2L, DSPEC512, LSPEC512); + } +} diff --git a/test/hotspot/jtreg/compiler/vectorapi/reshape/tests/TestVectorDoubleExpandShrink.java b/test/hotspot/jtreg/compiler/vectorapi/reshape/tests/TestVectorDoubleExpandShrink.java new file mode 100644 index 0000000000000000000000000000000000000000..5a20dea9c1b2b79a5dc494e70bf46444ecceac2a --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorapi/reshape/tests/TestVectorDoubleExpandShrink.java @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.vectorapi.reshape.tests; + +import compiler.lib.ir_framework.IR; +import compiler.lib.ir_framework.Run; +import compiler.lib.ir_framework.Test; + +import static compiler.vectorapi.reshape.utils.VectorReshapeHelper.*; + +/** + * As spot in 8259353. We need to do a shrink and an expand together to not accidentally + * zero out elements in the physical registers that may not be zero in general cases. + * In some methods, 2 consecutive ReinterpretNodes may be optimized out. + */ +public class TestVectorDoubleExpandShrink { + @Test + @IR(failOn = REINTERPRET_NODE) + public static void testB64toB128(byte[] input, byte[] output) { + vectorDoubleExpandShrink(BSPEC64, BSPEC128, input, output); + } + + @Run(test = "testB64toB128") + public static void runB64toB128() throws Throwable { + runDoubleExpandShrinkHelper(BSPEC64, BSPEC128); + } + + @Test + @IR(failOn = REINTERPRET_NODE) + public static void testB64toB256(byte[] input, byte[] output) { + vectorDoubleExpandShrink(BSPEC64, BSPEC256, input, output); + } + + @Run(test = "testB64toB256") + public static void runB64toB256() throws Throwable { + runDoubleExpandShrinkHelper(BSPEC64, BSPEC256); + } + + @Test + @IR(failOn = REINTERPRET_NODE) + public static void testB64toB512(byte[] input, byte[] output) { + vectorDoubleExpandShrink(BSPEC64, BSPEC512, input, output); + } + + @Run(test = "testB64toB512") + public static void runB64toB512() throws Throwable { + runDoubleExpandShrinkHelper(BSPEC64, BSPEC512); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "2"}) + public static void testB128toB64(byte[] input, byte[] output) { + vectorDoubleExpandShrink(BSPEC128, BSPEC64, input, output); + } + + @Run(test = "testB128toB64") + public static void runB128toB64() throws Throwable { + runDoubleExpandShrinkHelper(BSPEC128, BSPEC64); + } + + @Test + @IR(failOn = REINTERPRET_NODE) + public static void testB128toB256(byte[] input, byte[] output) { + vectorDoubleExpandShrink(BSPEC128, BSPEC256, input, output); + } + + @Run(test = "testB128toB256") + public static void runB128toB256() throws Throwable { + runDoubleExpandShrinkHelper(BSPEC128, BSPEC256); + } + + @Test + @IR(failOn = REINTERPRET_NODE) + public static void testB128toB512(byte[] input, byte[] output) { + vectorDoubleExpandShrink(BSPEC128, BSPEC512, input, output); + } + + @Run(test = "testB128toB512") + public static void runB128toB512() throws Throwable { + runDoubleExpandShrinkHelper(BSPEC128, BSPEC512); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "2"}) + public static void testB256toB64(byte[] input, byte[] output) { + vectorDoubleExpandShrink(BSPEC256, BSPEC64, input, output); + } + + @Run(test = "testB256toB64") + public static void runB256toB64() throws Throwable { + runDoubleExpandShrinkHelper(BSPEC256, BSPEC64); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "2"}) + public static void testB256toB128(byte[] input, byte[] output) { + vectorDoubleExpandShrink(BSPEC256, BSPEC128, input, output); + } + + @Run(test = "testB256toB128") + public static void runB256toB128() throws Throwable { + runDoubleExpandShrinkHelper(BSPEC256, BSPEC128); + } + + @Test + @IR(failOn = REINTERPRET_NODE) + public static void testB256toB512(byte[] input, byte[] output) { + vectorDoubleExpandShrink(BSPEC256, BSPEC512, input, output); + } + + @Run(test = "testB256toB512") + public static void runB256toB512() throws Throwable { + runDoubleExpandShrinkHelper(BSPEC256, BSPEC512); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "2"}) + public static void testB512toB64(byte[] input, byte[] output) { + vectorDoubleExpandShrink(BSPEC512, BSPEC64, input, output); + } + + @Run(test = "testB512toB64") + public static void runB512toB64() throws Throwable { + runDoubleExpandShrinkHelper(BSPEC512, BSPEC64); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "2"}) + public static void testB512toB128(byte[] input, byte[] output) { + vectorDoubleExpandShrink(BSPEC512, BSPEC128, input, output); + } + + @Run(test = "testB512toB128") + public static void runB512toB128() throws Throwable { + runDoubleExpandShrinkHelper(BSPEC512, BSPEC128); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "2"}) + public static void testB512toB256(byte[] input, byte[] output) { + vectorDoubleExpandShrink(BSPEC512, BSPEC256, input, output); + } + + @Run(test = "testB512toB256") + public static void runB512toB256() throws Throwable { + runDoubleExpandShrinkHelper(BSPEC512, BSPEC256); + } +} diff --git a/test/hotspot/jtreg/compiler/vectorapi/reshape/tests/TestVectorExpandShrink.java b/test/hotspot/jtreg/compiler/vectorapi/reshape/tests/TestVectorExpandShrink.java new file mode 100644 index 0000000000000000000000000000000000000000..7777ca3baad5104987c21860fae4ff90ee3dcedb --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorapi/reshape/tests/TestVectorExpandShrink.java @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.vectorapi.reshape.tests; + +import compiler.lib.ir_framework.IR; +import compiler.lib.ir_framework.Run; +import compiler.lib.ir_framework.Test; + +import static compiler.vectorapi.reshape.utils.VectorReshapeHelper.*; + +/** + * This class contains method to ensure a resizing reinterpretation operations work as + * intended. + * In each test, the ReinterpretNode is expected to appear exactly once. + */ +public class TestVectorExpandShrink { + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testB64toB128(byte[] input, byte[] output) { + vectorExpandShrink(BSPEC64, BSPEC128, input, output); + } + + @Run(test = "testB64toB128") + public static void runB64toB128() throws Throwable { + runExpandShrinkHelper(BSPEC64, BSPEC128); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testB64toB256(byte[] input, byte[] output) { + vectorExpandShrink(BSPEC64, BSPEC256, input, output); + } + + @Run(test = "testB64toB256") + public static void runB64toB256() throws Throwable { + runExpandShrinkHelper(BSPEC64, BSPEC256); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testB64toB512(byte[] input, byte[] output) { + vectorExpandShrink(BSPEC64, BSPEC512, input, output); + } + + @Run(test = "testB64toB512") + public static void runB64toB512() throws Throwable { + runExpandShrinkHelper(BSPEC64, BSPEC512); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testB128toB64(byte[] input, byte[] output) { + vectorExpandShrink(BSPEC128, BSPEC64, input, output); + } + + @Run(test = "testB128toB64") + public static void runB128toB64() throws Throwable { + runExpandShrinkHelper(BSPEC128, BSPEC64); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testB128toB256(byte[] input, byte[] output) { + vectorExpandShrink(BSPEC128, BSPEC256, input, output); + } + + @Run(test = "testB128toB256") + public static void runB128toB256() throws Throwable { + runExpandShrinkHelper(BSPEC128, BSPEC256); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testB128toB512(byte[] input, byte[] output) { + vectorExpandShrink(BSPEC128, BSPEC512, input, output); + } + + @Run(test = "testB128toB512") + public static void runB128toB512() throws Throwable { + runExpandShrinkHelper(BSPEC128, BSPEC512); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testB256toB64(byte[] input, byte[] output) { + vectorExpandShrink(BSPEC256, BSPEC64, input, output); + } + + @Run(test = "testB256toB64") + public static void runB256toB64() throws Throwable { + runExpandShrinkHelper(BSPEC256, BSPEC64); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testB256toB128(byte[] input, byte[] output) { + vectorExpandShrink(BSPEC256, BSPEC128, input, output); + } + + @Run(test = "testB256toB128") + public static void runB256toB128() throws Throwable { + runExpandShrinkHelper(BSPEC256, BSPEC128); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testB256toB512(byte[] input, byte[] output) { + vectorExpandShrink(BSPEC256, BSPEC512, input, output); + } + + @Run(test = "testB256toB512") + public static void runB256toB512() throws Throwable { + runExpandShrinkHelper(BSPEC256, BSPEC512); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testB512toB64(byte[] input, byte[] output) { + vectorExpandShrink(BSPEC512, BSPEC64, input, output); + } + + @Run(test = "testB512toB64") + public static void runB512toB64() throws Throwable { + runExpandShrinkHelper(BSPEC512, BSPEC64); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testB512toB128(byte[] input, byte[] output) { + vectorExpandShrink(BSPEC512, BSPEC128, input, output); + } + + @Run(test = "testB512toB128") + public static void runB512toB128() throws Throwable { + runExpandShrinkHelper(BSPEC512, BSPEC128); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testB512toB256(byte[] input, byte[] output) { + vectorExpandShrink(BSPEC512, BSPEC256, input, output); + } + + @Run(test = "testB512toB256") + public static void runB512toB256() throws Throwable { + runExpandShrinkHelper(BSPEC512, BSPEC256); + } +} diff --git a/test/hotspot/jtreg/compiler/vectorapi/reshape/tests/TestVectorRebracket.java b/test/hotspot/jtreg/compiler/vectorapi/reshape/tests/TestVectorRebracket.java new file mode 100644 index 0000000000000000000000000000000000000000..32b500aacdc10a6082b42ab169223d24900d9a2a --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorapi/reshape/tests/TestVectorRebracket.java @@ -0,0 +1,1360 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.vectorapi.reshape.tests; + +import compiler.lib.ir_framework.IR; +import compiler.lib.ir_framework.Run; +import compiler.lib.ir_framework.Test; + +import static compiler.vectorapi.reshape.utils.VectorReshapeHelper.*; + +/** + * This class contains methods to test for reinterpretation operations that reinterpret + * a vector as a similar vector with another element type. It is complicated to verify + * the IR in this case since a load/store with respect to byte array will result in + * additional ReinterpretNodes if the vector element type is not byte. As a result, + * arguments need to be arrays of the correct type. + * In each test, the ReinterpretNode is expected to appear exactly once. + */ +public class TestVectorRebracket { + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testB64toS64(byte[] input, short[] output) { + vectorRebracket(BSPEC64, SSPEC64, input, output); + } + + @Run(test = "testB64toS64") + public static void runB64toS64() throws Throwable { + runRebracketHelper(BSPEC64, SSPEC64); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testB64toI64(byte[] input, int[] output) { + vectorRebracket(BSPEC64, ISPEC64, input, output); + } + + @Run(test = "testB64toI64") + public static void runB64toI64() throws Throwable { + runRebracketHelper(BSPEC64, ISPEC64); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testB64toL64(byte[] input, long[] output) { + vectorRebracket(BSPEC64, LSPEC64, input, output); + } + + @Run(test = "testB64toL64") + public static void runB64toL64() throws Throwable { + runRebracketHelper(BSPEC64, LSPEC64); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testB64toF64(byte[] input, float[] output) { + vectorRebracket(BSPEC64, FSPEC64, input, output); + } + + @Run(test = "testB64toF64") + public static void runB64toF64() throws Throwable { + runRebracketHelper(BSPEC64, FSPEC64); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testB64toD64(byte[] input, double[] output) { + vectorRebracket(BSPEC64, DSPEC64, input, output); + } + + @Run(test = "testB64toD64") + public static void runB64toD64() throws Throwable { + runRebracketHelper(BSPEC64, DSPEC64); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testS64toB64(short[] input, byte[] output) { + vectorRebracket(SSPEC64, BSPEC64, input, output); + } + + @Run(test = "testS64toB64") + public static void runS64toB64() throws Throwable { + runRebracketHelper(SSPEC64, BSPEC64); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testS64toI64(short[] input, int[] output) { + vectorRebracket(SSPEC64, ISPEC64, input, output); + } + + @Run(test = "testS64toI64") + public static void runS64toI64() throws Throwable { + runRebracketHelper(SSPEC64, ISPEC64); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testS64toL64(short[] input, long[] output) { + vectorRebracket(SSPEC64, LSPEC64, input, output); + } + + @Run(test = "testS64toL64") + public static void runS64toL64() throws Throwable { + runRebracketHelper(SSPEC64, LSPEC64); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testS64toF64(short[] input, float[] output) { + vectorRebracket(SSPEC64, FSPEC64, input, output); + } + + @Run(test = "testS64toF64") + public static void runS64toF64() throws Throwable { + runRebracketHelper(SSPEC64, FSPEC64); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testS64toD64(short[] input, double[] output) { + vectorRebracket(SSPEC64, DSPEC64, input, output); + } + + @Run(test = "testS64toD64") + public static void runS64toD64() throws Throwable { + runRebracketHelper(SSPEC64, DSPEC64); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testI64toB64(int[] input, byte[] output) { + vectorRebracket(ISPEC64, BSPEC64, input, output); + } + + @Run(test = "testI64toB64") + public static void runI64toB64() throws Throwable { + runRebracketHelper(ISPEC64, BSPEC64); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testI64toS64(int[] input, short[] output) { + vectorRebracket(ISPEC64, SSPEC64, input, output); + } + + @Run(test = "testI64toS64") + public static void runI64toS64() throws Throwable { + runRebracketHelper(ISPEC64, SSPEC64); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testI64toL64(int[] input, long[] output) { + vectorRebracket(ISPEC64, LSPEC64, input, output); + } + + @Run(test = "testI64toL64") + public static void runI64toL64() throws Throwable { + runRebracketHelper(ISPEC64, LSPEC64); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testI64toF64(int[] input, float[] output) { + vectorRebracket(ISPEC64, FSPEC64, input, output); + } + + @Run(test = "testI64toF64") + public static void runI64toF64() throws Throwable { + runRebracketHelper(ISPEC64, FSPEC64); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testI64toD64(int[] input, double[] output) { + vectorRebracket(ISPEC64, DSPEC64, input, output); + } + + @Run(test = "testI64toD64") + public static void runI64toD64() throws Throwable { + runRebracketHelper(ISPEC64, DSPEC64); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testL64toB64(long[] input, byte[] output) { + vectorRebracket(LSPEC64, BSPEC64, input, output); + } + + @Run(test = "testL64toB64") + public static void runL64toB64() throws Throwable { + runRebracketHelper(LSPEC64, BSPEC64); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testL64toS64(long[] input, short[] output) { + vectorRebracket(LSPEC64, SSPEC64, input, output); + } + + @Run(test = "testL64toS64") + public static void runL64toS64() throws Throwable { + runRebracketHelper(LSPEC64, SSPEC64); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testL64toI64(long[] input, int[] output) { + vectorRebracket(LSPEC64, ISPEC64, input, output); + } + + @Run(test = "testL64toI64") + public static void runL64toI64() throws Throwable { + runRebracketHelper(LSPEC64, ISPEC64); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testL64toF64(long[] input, float[] output) { + vectorRebracket(LSPEC64, FSPEC64, input, output); + } + + @Run(test = "testL64toF64") + public static void runL64toF64() throws Throwable { + runRebracketHelper(LSPEC64, FSPEC64); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testL64toD64(long[] input, double[] output) { + vectorRebracket(LSPEC64, DSPEC64, input, output); + } + + @Run(test = "testL64toD64") + public static void runL64toD64() throws Throwable { + runRebracketHelper(LSPEC64, DSPEC64); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testF64toB64(float[] input, byte[] output) { + vectorRebracket(FSPEC64, BSPEC64, input, output); + } + + @Run(test = "testF64toB64") + public static void runF64toB64() throws Throwable { + runRebracketHelper(FSPEC64, BSPEC64); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testF64toS64(float[] input, short[] output) { + vectorRebracket(FSPEC64, SSPEC64, input, output); + } + + @Run(test = "testF64toS64") + public static void runF64toS64() throws Throwable { + runRebracketHelper(FSPEC64, SSPEC64); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testF64toI64(float[] input, int[] output) { + vectorRebracket(FSPEC64, ISPEC64, input, output); + } + + @Run(test = "testF64toI64") + public static void runF64toI64() throws Throwable { + runRebracketHelper(FSPEC64, ISPEC64); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testF64toL64(float[] input, long[] output) { + vectorRebracket(FSPEC64, LSPEC64, input, output); + } + + @Run(test = "testF64toL64") + public static void runF64toL64() throws Throwable { + runRebracketHelper(FSPEC64, LSPEC64); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testF64toD64(float[] input, double[] output) { + vectorRebracket(FSPEC64, DSPEC64, input, output); + } + + @Run(test = "testF64toD64") + public static void runF64toD64() throws Throwable { + runRebracketHelper(FSPEC64, DSPEC64); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testD64toB64(double[] input, byte[] output) { + vectorRebracket(DSPEC64, BSPEC64, input, output); + } + + @Run(test = "testD64toB64") + public static void runD64toB64() throws Throwable { + runRebracketHelper(DSPEC64, BSPEC64); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testD64toS64(double[] input, short[] output) { + vectorRebracket(DSPEC64, SSPEC64, input, output); + } + + @Run(test = "testD64toS64") + public static void runD64toS64() throws Throwable { + runRebracketHelper(DSPEC64, SSPEC64); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testD64toI64(double[] input, int[] output) { + vectorRebracket(DSPEC64, ISPEC64, input, output); + } + + @Run(test = "testD64toI64") + public static void runD64toI64() throws Throwable { + runRebracketHelper(DSPEC64, ISPEC64); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testD64toL64(double[] input, long[] output) { + vectorRebracket(DSPEC64, LSPEC64, input, output); + } + + @Run(test = "testD64toL64") + public static void runD64toL64() throws Throwable { + runRebracketHelper(DSPEC64, LSPEC64); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testD64toF64(double[] input, float[] output) { + vectorRebracket(DSPEC64, FSPEC64, input, output); + } + + @Run(test = "testD64toF64") + public static void runD64toF64() throws Throwable { + runRebracketHelper(DSPEC64, FSPEC64); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testB128toS128(byte[] input, short[] output) { + vectorRebracket(BSPEC128, SSPEC128, input, output); + } + + @Run(test = "testB128toS128") + public static void runB128toS128() throws Throwable { + runRebracketHelper(BSPEC128, SSPEC128); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testB128toI128(byte[] input, int[] output) { + vectorRebracket(BSPEC128, ISPEC128, input, output); + } + + @Run(test = "testB128toI128") + public static void runB128toI128() throws Throwable { + runRebracketHelper(BSPEC128, ISPEC128); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testB128toL128(byte[] input, long[] output) { + vectorRebracket(BSPEC128, LSPEC128, input, output); + } + + @Run(test = "testB128toL128") + public static void runB128toL128() throws Throwable { + runRebracketHelper(BSPEC128, LSPEC128); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testB128toF128(byte[] input, float[] output) { + vectorRebracket(BSPEC128, FSPEC128, input, output); + } + + @Run(test = "testB128toF128") + public static void runB128toF128() throws Throwable { + runRebracketHelper(BSPEC128, FSPEC128); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testB128toD128(byte[] input, double[] output) { + vectorRebracket(BSPEC128, DSPEC128, input, output); + } + + @Run(test = "testB128toD128") + public static void runB128toD128() throws Throwable { + runRebracketHelper(BSPEC128, DSPEC128); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testS128toB128(short[] input, byte[] output) { + vectorRebracket(SSPEC128, BSPEC128, input, output); + } + + @Run(test = "testS128toB128") + public static void runS128toB128() throws Throwable { + runRebracketHelper(SSPEC128, BSPEC128); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testS128toI128(short[] input, int[] output) { + vectorRebracket(SSPEC128, ISPEC128, input, output); + } + + @Run(test = "testS128toI128") + public static void runS128toI128() throws Throwable { + runRebracketHelper(SSPEC128, ISPEC128); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testS128toL128(short[] input, long[] output) { + vectorRebracket(SSPEC128, LSPEC128, input, output); + } + + @Run(test = "testS128toL128") + public static void runS128toL128() throws Throwable { + runRebracketHelper(SSPEC128, LSPEC128); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testS128toF128(short[] input, float[] output) { + vectorRebracket(SSPEC128, FSPEC128, input, output); + } + + @Run(test = "testS128toF128") + public static void runS128toF128() throws Throwable { + runRebracketHelper(SSPEC128, FSPEC128); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testS128toD128(short[] input, double[] output) { + vectorRebracket(SSPEC128, DSPEC128, input, output); + } + + @Run(test = "testS128toD128") + public static void runS128toD128() throws Throwable { + runRebracketHelper(SSPEC128, DSPEC128); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testI128toB128(int[] input, byte[] output) { + vectorRebracket(ISPEC128, BSPEC128, input, output); + } + + @Run(test = "testI128toB128") + public static void runI128toB128() throws Throwable { + runRebracketHelper(ISPEC128, BSPEC128); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testI128toS128(int[] input, short[] output) { + vectorRebracket(ISPEC128, SSPEC128, input, output); + } + + @Run(test = "testI128toS128") + public static void runI128toS128() throws Throwable { + runRebracketHelper(ISPEC128, SSPEC128); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testI128toL128(int[] input, long[] output) { + vectorRebracket(ISPEC128, LSPEC128, input, output); + } + + @Run(test = "testI128toL128") + public static void runI128toL128() throws Throwable { + runRebracketHelper(ISPEC128, LSPEC128); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testI128toF128(int[] input, float[] output) { + vectorRebracket(ISPEC128, FSPEC128, input, output); + } + + @Run(test = "testI128toF128") + public static void runI128toF128() throws Throwable { + runRebracketHelper(ISPEC128, FSPEC128); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testI128toD128(int[] input, double[] output) { + vectorRebracket(ISPEC128, DSPEC128, input, output); + } + + @Run(test = "testI128toD128") + public static void runI128toD128() throws Throwable { + runRebracketHelper(ISPEC128, DSPEC128); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testL128toB128(long[] input, byte[] output) { + vectorRebracket(LSPEC128, BSPEC128, input, output); + } + + @Run(test = "testL128toB128") + public static void runL128toB128() throws Throwable { + runRebracketHelper(LSPEC128, BSPEC128); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testL128toS128(long[] input, short[] output) { + vectorRebracket(LSPEC128, SSPEC128, input, output); + } + + @Run(test = "testL128toS128") + public static void runL128toS128() throws Throwable { + runRebracketHelper(LSPEC128, SSPEC128); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testL128toI128(long[] input, int[] output) { + vectorRebracket(LSPEC128, ISPEC128, input, output); + } + + @Run(test = "testL128toI128") + public static void runL128toI128() throws Throwable { + runRebracketHelper(LSPEC128, ISPEC128); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testL128toF128(long[] input, float[] output) { + vectorRebracket(LSPEC128, FSPEC128, input, output); + } + + @Run(test = "testL128toF128") + public static void runL128toF128() throws Throwable { + runRebracketHelper(LSPEC128, FSPEC128); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testL128toD128(long[] input, double[] output) { + vectorRebracket(LSPEC128, DSPEC128, input, output); + } + + @Run(test = "testL128toD128") + public static void runL128toD128() throws Throwable { + runRebracketHelper(LSPEC128, DSPEC128); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testF128toB128(float[] input, byte[] output) { + vectorRebracket(FSPEC128, BSPEC128, input, output); + } + + @Run(test = "testF128toB128") + public static void runF128toB128() throws Throwable { + runRebracketHelper(FSPEC128, BSPEC128); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testF128toS128(float[] input, short[] output) { + vectorRebracket(FSPEC128, SSPEC128, input, output); + } + + @Run(test = "testF128toS128") + public static void runF128toS128() throws Throwable { + runRebracketHelper(FSPEC128, SSPEC128); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testF128toI128(float[] input, int[] output) { + vectorRebracket(FSPEC128, ISPEC128, input, output); + } + + @Run(test = "testF128toI128") + public static void runF128toI128() throws Throwable { + runRebracketHelper(FSPEC128, ISPEC128); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testF128toL128(float[] input, long[] output) { + vectorRebracket(FSPEC128, LSPEC128, input, output); + } + + @Run(test = "testF128toL128") + public static void runF128toL128() throws Throwable { + runRebracketHelper(FSPEC128, LSPEC128); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testF128toD128(float[] input, double[] output) { + vectorRebracket(FSPEC128, DSPEC128, input, output); + } + + @Run(test = "testF128toD128") + public static void runF128toD128() throws Throwable { + runRebracketHelper(FSPEC128, DSPEC128); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testD128toB128(double[] input, byte[] output) { + vectorRebracket(DSPEC128, BSPEC128, input, output); + } + + @Run(test = "testD128toB128") + public static void runD128toB128() throws Throwable { + runRebracketHelper(DSPEC128, BSPEC128); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testD128toS128(double[] input, short[] output) { + vectorRebracket(DSPEC128, SSPEC128, input, output); + } + + @Run(test = "testD128toS128") + public static void runD128toS128() throws Throwable { + runRebracketHelper(DSPEC128, SSPEC128); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testD128toI128(double[] input, int[] output) { + vectorRebracket(DSPEC128, ISPEC128, input, output); + } + + @Run(test = "testD128toI128") + public static void runD128toI128() throws Throwable { + runRebracketHelper(DSPEC128, ISPEC128); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testD128toL128(double[] input, long[] output) { + vectorRebracket(DSPEC128, LSPEC128, input, output); + } + + @Run(test = "testD128toL128") + public static void runD128toL128() throws Throwable { + runRebracketHelper(DSPEC128, LSPEC128); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testD128toF128(double[] input, float[] output) { + vectorRebracket(DSPEC128, FSPEC128, input, output); + } + + @Run(test = "testD128toF128") + public static void runD128toF128() throws Throwable { + runRebracketHelper(DSPEC128, FSPEC128); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testB256toS256(byte[] input, short[] output) { + vectorRebracket(BSPEC256, SSPEC256, input, output); + } + + @Run(test = "testB256toS256") + public static void runB256toS256() throws Throwable { + runRebracketHelper(BSPEC256, SSPEC256); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testB256toI256(byte[] input, int[] output) { + vectorRebracket(BSPEC256, ISPEC256, input, output); + } + + @Run(test = "testB256toI256") + public static void runB256toI256() throws Throwable { + runRebracketHelper(BSPEC256, ISPEC256); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testB256toL256(byte[] input, long[] output) { + vectorRebracket(BSPEC256, LSPEC256, input, output); + } + + @Run(test = "testB256toL256") + public static void runB256toL256() throws Throwable { + runRebracketHelper(BSPEC256, LSPEC256); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testB256toF256(byte[] input, float[] output) { + vectorRebracket(BSPEC256, FSPEC256, input, output); + } + + @Run(test = "testB256toF256") + public static void runB256toF256() throws Throwable { + runRebracketHelper(BSPEC256, FSPEC256); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testB256toD256(byte[] input, double[] output) { + vectorRebracket(BSPEC256, DSPEC256, input, output); + } + + @Run(test = "testB256toD256") + public static void runB256toD256() throws Throwable { + runRebracketHelper(BSPEC256, DSPEC256); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testS256toB256(short[] input, byte[] output) { + vectorRebracket(SSPEC256, BSPEC256, input, output); + } + + @Run(test = "testS256toB256") + public static void runS256toB256() throws Throwable { + runRebracketHelper(SSPEC256, BSPEC256); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testS256toI256(short[] input, int[] output) { + vectorRebracket(SSPEC256, ISPEC256, input, output); + } + + @Run(test = "testS256toI256") + public static void runS256toI256() throws Throwable { + runRebracketHelper(SSPEC256, ISPEC256); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testS256toL256(short[] input, long[] output) { + vectorRebracket(SSPEC256, LSPEC256, input, output); + } + + @Run(test = "testS256toL256") + public static void runS256toL256() throws Throwable { + runRebracketHelper(SSPEC256, LSPEC256); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testS256toF256(short[] input, float[] output) { + vectorRebracket(SSPEC256, FSPEC256, input, output); + } + + @Run(test = "testS256toF256") + public static void runS256toF256() throws Throwable { + runRebracketHelper(SSPEC256, FSPEC256); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testS256toD256(short[] input, double[] output) { + vectorRebracket(SSPEC256, DSPEC256, input, output); + } + + @Run(test = "testS256toD256") + public static void runS256toD256() throws Throwable { + runRebracketHelper(SSPEC256, DSPEC256); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testI256toB256(int[] input, byte[] output) { + vectorRebracket(ISPEC256, BSPEC256, input, output); + } + + @Run(test = "testI256toB256") + public static void runI256toB256() throws Throwable { + runRebracketHelper(ISPEC256, BSPEC256); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testI256toS256(int[] input, short[] output) { + vectorRebracket(ISPEC256, SSPEC256, input, output); + } + + @Run(test = "testI256toS256") + public static void runI256toS256() throws Throwable { + runRebracketHelper(ISPEC256, SSPEC256); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testI256toL256(int[] input, long[] output) { + vectorRebracket(ISPEC256, LSPEC256, input, output); + } + + @Run(test = "testI256toL256") + public static void runI256toL256() throws Throwable { + runRebracketHelper(ISPEC256, LSPEC256); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testI256toF256(int[] input, float[] output) { + vectorRebracket(ISPEC256, FSPEC256, input, output); + } + + @Run(test = "testI256toF256") + public static void runI256toF256() throws Throwable { + runRebracketHelper(ISPEC256, FSPEC256); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testI256toD256(int[] input, double[] output) { + vectorRebracket(ISPEC256, DSPEC256, input, output); + } + + @Run(test = "testI256toD256") + public static void runI256toD256() throws Throwable { + runRebracketHelper(ISPEC256, DSPEC256); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testL256toB256(long[] input, byte[] output) { + vectorRebracket(LSPEC256, BSPEC256, input, output); + } + + @Run(test = "testL256toB256") + public static void runL256toB256() throws Throwable { + runRebracketHelper(LSPEC256, BSPEC256); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testL256toS256(long[] input, short[] output) { + vectorRebracket(LSPEC256, SSPEC256, input, output); + } + + @Run(test = "testL256toS256") + public static void runL256toS256() throws Throwable { + runRebracketHelper(LSPEC256, SSPEC256); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testL256toI256(long[] input, int[] output) { + vectorRebracket(LSPEC256, ISPEC256, input, output); + } + + @Run(test = "testL256toI256") + public static void runL256toI256() throws Throwable { + runRebracketHelper(LSPEC256, ISPEC256); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testL256toF256(long[] input, float[] output) { + vectorRebracket(LSPEC256, FSPEC256, input, output); + } + + @Run(test = "testL256toF256") + public static void runL256toF256() throws Throwable { + runRebracketHelper(LSPEC256, FSPEC256); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testL256toD256(long[] input, double[] output) { + vectorRebracket(LSPEC256, DSPEC256, input, output); + } + + @Run(test = "testL256toD256") + public static void runL256toD256() throws Throwable { + runRebracketHelper(LSPEC256, DSPEC256); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testF256toB256(float[] input, byte[] output) { + vectorRebracket(FSPEC256, BSPEC256, input, output); + } + + @Run(test = "testF256toB256") + public static void runF256toB256() throws Throwable { + runRebracketHelper(FSPEC256, BSPEC256); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testF256toS256(float[] input, short[] output) { + vectorRebracket(FSPEC256, SSPEC256, input, output); + } + + @Run(test = "testF256toS256") + public static void runF256toS256() throws Throwable { + runRebracketHelper(FSPEC256, SSPEC256); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testF256toI256(float[] input, int[] output) { + vectorRebracket(FSPEC256, ISPEC256, input, output); + } + + @Run(test = "testF256toI256") + public static void runF256toI256() throws Throwable { + runRebracketHelper(FSPEC256, ISPEC256); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testF256toL256(float[] input, long[] output) { + vectorRebracket(FSPEC256, LSPEC256, input, output); + } + + @Run(test = "testF256toL256") + public static void runF256toL256() throws Throwable { + runRebracketHelper(FSPEC256, LSPEC256); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testF256toD256(float[] input, double[] output) { + vectorRebracket(FSPEC256, DSPEC256, input, output); + } + + @Run(test = "testF256toD256") + public static void runF256toD256() throws Throwable { + runRebracketHelper(FSPEC256, DSPEC256); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testD256toB256(double[] input, byte[] output) { + vectorRebracket(DSPEC256, BSPEC256, input, output); + } + + @Run(test = "testD256toB256") + public static void runD256toB256() throws Throwable { + runRebracketHelper(DSPEC256, BSPEC256); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testD256toS256(double[] input, short[] output) { + vectorRebracket(DSPEC256, SSPEC256, input, output); + } + + @Run(test = "testD256toS256") + public static void runD256toS256() throws Throwable { + runRebracketHelper(DSPEC256, SSPEC256); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testD256toI256(double[] input, int[] output) { + vectorRebracket(DSPEC256, ISPEC256, input, output); + } + + @Run(test = "testD256toI256") + public static void runD256toI256() throws Throwable { + runRebracketHelper(DSPEC256, ISPEC256); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testD256toL256(double[] input, long[] output) { + vectorRebracket(DSPEC256, LSPEC256, input, output); + } + + @Run(test = "testD256toL256") + public static void runD256toL256() throws Throwable { + runRebracketHelper(DSPEC256, LSPEC256); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testD256toF256(double[] input, float[] output) { + vectorRebracket(DSPEC256, FSPEC256, input, output); + } + + @Run(test = "testD256toF256") + public static void runD256toF256() throws Throwable { + runRebracketHelper(DSPEC256, FSPEC256); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testB512toS512(byte[] input, short[] output) { + vectorRebracket(BSPEC512, SSPEC512, input, output); + } + + @Run(test = "testB512toS512") + public static void runB512toS512() throws Throwable { + runRebracketHelper(BSPEC512, SSPEC512); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testB512toI512(byte[] input, int[] output) { + vectorRebracket(BSPEC512, ISPEC512, input, output); + } + + @Run(test = "testB512toI512") + public static void runB512toI512() throws Throwable { + runRebracketHelper(BSPEC512, ISPEC512); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testB512toL512(byte[] input, long[] output) { + vectorRebracket(BSPEC512, LSPEC512, input, output); + } + + @Run(test = "testB512toL512") + public static void runB512toL512() throws Throwable { + runRebracketHelper(BSPEC512, LSPEC512); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testB512toF512(byte[] input, float[] output) { + vectorRebracket(BSPEC512, FSPEC512, input, output); + } + + @Run(test = "testB512toF512") + public static void runB512toF512() throws Throwable { + runRebracketHelper(BSPEC512, FSPEC512); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testB512toD512(byte[] input, double[] output) { + vectorRebracket(BSPEC512, DSPEC512, input, output); + } + + @Run(test = "testB512toD512") + public static void runB512toD512() throws Throwable { + runRebracketHelper(BSPEC512, DSPEC512); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testS512toB512(short[] input, byte[] output) { + vectorRebracket(SSPEC512, BSPEC512, input, output); + } + + @Run(test = "testS512toB512") + public static void runS512toB512() throws Throwable { + runRebracketHelper(SSPEC512, BSPEC512); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testS512toI512(short[] input, int[] output) { + vectorRebracket(SSPEC512, ISPEC512, input, output); + } + + @Run(test = "testS512toI512") + public static void runS512toI512() throws Throwable { + runRebracketHelper(SSPEC512, ISPEC512); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testS512toL512(short[] input, long[] output) { + vectorRebracket(SSPEC512, LSPEC512, input, output); + } + + @Run(test = "testS512toL512") + public static void runS512toL512() throws Throwable { + runRebracketHelper(SSPEC512, LSPEC512); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testS512toF512(short[] input, float[] output) { + vectorRebracket(SSPEC512, FSPEC512, input, output); + } + + @Run(test = "testS512toF512") + public static void runS512toF512() throws Throwable { + runRebracketHelper(SSPEC512, FSPEC512); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testS512toD512(short[] input, double[] output) { + vectorRebracket(SSPEC512, DSPEC512, input, output); + } + + @Run(test = "testS512toD512") + public static void runS512toD512() throws Throwable { + runRebracketHelper(SSPEC512, DSPEC512); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testI512toB512(int[] input, byte[] output) { + vectorRebracket(ISPEC512, BSPEC512, input, output); + } + + @Run(test = "testI512toB512") + public static void runI512toB512() throws Throwable { + runRebracketHelper(ISPEC512, BSPEC512); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testI512toS512(int[] input, short[] output) { + vectorRebracket(ISPEC512, SSPEC512, input, output); + } + + @Run(test = "testI512toS512") + public static void runI512toS512() throws Throwable { + runRebracketHelper(ISPEC512, SSPEC512); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testI512toL512(int[] input, long[] output) { + vectorRebracket(ISPEC512, LSPEC512, input, output); + } + + @Run(test = "testI512toL512") + public static void runI512toL512() throws Throwable { + runRebracketHelper(ISPEC512, LSPEC512); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testI512toF512(int[] input, float[] output) { + vectorRebracket(ISPEC512, FSPEC512, input, output); + } + + @Run(test = "testI512toF512") + public static void runI512toF512() throws Throwable { + runRebracketHelper(ISPEC512, FSPEC512); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testI512toD512(int[] input, double[] output) { + vectorRebracket(ISPEC512, DSPEC512, input, output); + } + + @Run(test = "testI512toD512") + public static void runI512toD512() throws Throwable { + runRebracketHelper(ISPEC512, DSPEC512); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testL512toB512(long[] input, byte[] output) { + vectorRebracket(LSPEC512, BSPEC512, input, output); + } + + @Run(test = "testL512toB512") + public static void runL512toB512() throws Throwable { + runRebracketHelper(LSPEC512, BSPEC512); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testL512toS512(long[] input, short[] output) { + vectorRebracket(LSPEC512, SSPEC512, input, output); + } + + @Run(test = "testL512toS512") + public static void runL512toS512() throws Throwable { + runRebracketHelper(LSPEC512, SSPEC512); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testL512toI512(long[] input, int[] output) { + vectorRebracket(LSPEC512, ISPEC512, input, output); + } + + @Run(test = "testL512toI512") + public static void runL512toI512() throws Throwable { + runRebracketHelper(LSPEC512, ISPEC512); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testL512toF512(long[] input, float[] output) { + vectorRebracket(LSPEC512, FSPEC512, input, output); + } + + @Run(test = "testL512toF512") + public static void runL512toF512() throws Throwable { + runRebracketHelper(LSPEC512, FSPEC512); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testL512toD512(long[] input, double[] output) { + vectorRebracket(LSPEC512, DSPEC512, input, output); + } + + @Run(test = "testL512toD512") + public static void runL512toD512() throws Throwable { + runRebracketHelper(LSPEC512, DSPEC512); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testF512toB512(float[] input, byte[] output) { + vectorRebracket(FSPEC512, BSPEC512, input, output); + } + + @Run(test = "testF512toB512") + public static void runF512toB512() throws Throwable { + runRebracketHelper(FSPEC512, BSPEC512); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testF512toS512(float[] input, short[] output) { + vectorRebracket(FSPEC512, SSPEC512, input, output); + } + + @Run(test = "testF512toS512") + public static void runF512toS512() throws Throwable { + runRebracketHelper(FSPEC512, SSPEC512); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testF512toI512(float[] input, int[] output) { + vectorRebracket(FSPEC512, ISPEC512, input, output); + } + + @Run(test = "testF512toI512") + public static void runF512toI512() throws Throwable { + runRebracketHelper(FSPEC512, ISPEC512); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testF512toL512(float[] input, long[] output) { + vectorRebracket(FSPEC512, LSPEC512, input, output); + } + + @Run(test = "testF512toL512") + public static void runF512toL512() throws Throwable { + runRebracketHelper(FSPEC512, LSPEC512); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testF512toD512(float[] input, double[] output) { + vectorRebracket(FSPEC512, DSPEC512, input, output); + } + + @Run(test = "testF512toD512") + public static void runF512toD512() throws Throwable { + runRebracketHelper(FSPEC512, DSPEC512); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testD512toB512(double[] input, byte[] output) { + vectorRebracket(DSPEC512, BSPEC512, input, output); + } + + @Run(test = "testD512toB512") + public static void runD512toB512() throws Throwable { + runRebracketHelper(DSPEC512, BSPEC512); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testD512toS512(double[] input, short[] output) { + vectorRebracket(DSPEC512, SSPEC512, input, output); + } + + @Run(test = "testD512toS512") + public static void runD512toS512() throws Throwable { + runRebracketHelper(DSPEC512, SSPEC512); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testD512toI512(double[] input, int[] output) { + vectorRebracket(DSPEC512, ISPEC512, input, output); + } + + @Run(test = "testD512toI512") + public static void runD512toI512() throws Throwable { + runRebracketHelper(DSPEC512, ISPEC512); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testD512toL512(double[] input, long[] output) { + vectorRebracket(DSPEC512, LSPEC512, input, output); + } + + @Run(test = "testD512toL512") + public static void runD512toL512() throws Throwable { + runRebracketHelper(DSPEC512, LSPEC512); + } + + @Test + @IR(counts = {REINTERPRET_NODE, "1"}) + public static void testD512toF512(double[] input, float[] output) { + vectorRebracket(DSPEC512, FSPEC512, input, output); + } + + @Run(test = "testD512toF512") + public static void runD512toF512() throws Throwable { + runRebracketHelper(DSPEC512, FSPEC512); + } +} diff --git a/test/hotspot/jtreg/compiler/vectorapi/reshape/utils/TestCastMethods.java b/test/hotspot/jtreg/compiler/vectorapi/reshape/utils/TestCastMethods.java new file mode 100644 index 0000000000000000000000000000000000000000..865daba9b05ee61bd07916ca933ab3d008bc71c7 --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorapi/reshape/utils/TestCastMethods.java @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.vectorapi.reshape.utils; + +import java.util.List; +import java.util.stream.Stream; + +import static compiler.vectorapi.reshape.utils.VectorReshapeHelper.*; +import static compiler.vectorapi.reshape.utils.VectorSpeciesPair.makePair; + +/** + * The cast intrinsics implemented on each platform, commented out tests are the ones that are + * supposed to work but currently don't. + */ +public class TestCastMethods { + public static final List<VectorSpeciesPair> AVX1_CAST_TESTS = List.of( + makePair(BSPEC64, SSPEC64), + makePair(BSPEC64, SSPEC128), + makePair(BSPEC64, ISPEC128), + makePair(BSPEC64, FSPEC128), + // makePair(BSPEC64, DSPEC256), + makePair(SSPEC64, BSPEC64), + makePair(SSPEC128, BSPEC64), + makePair(SSPEC64, ISPEC64), + makePair(SSPEC64, ISPEC128), + makePair(SSPEC64, LSPEC128), + makePair(SSPEC64, FSPEC64), + makePair(SSPEC64, FSPEC128), + makePair(SSPEC64, DSPEC128), + // makePair(SSPEC64, DSPEC256), + makePair(ISPEC128, BSPEC64), + makePair(ISPEC64, SSPEC64), + makePair(ISPEC128, SSPEC64), + makePair(ISPEC64, LSPEC128), + makePair(ISPEC64, FSPEC64), + makePair(ISPEC128, FSPEC128), + makePair(ISPEC64, DSPEC128), + makePair(ISPEC128, DSPEC256), + makePair(LSPEC128, SSPEC64), + makePair(LSPEC128, ISPEC64), + makePair(FSPEC64, ISPEC64), + makePair(FSPEC128, ISPEC128), + makePair(FSPEC64, DSPEC128), + makePair(FSPEC128, DSPEC256), + makePair(DSPEC128, FSPEC64) + // makePair(DSPEC256, FSPEC128) + ); + + public static final List<VectorSpeciesPair> AVX2_CAST_TESTS = Stream.concat(AVX1_CAST_TESTS.stream(), List.of( + makePair(BSPEC128, SSPEC256), + makePair(BSPEC64, ISPEC256), + makePair(BSPEC64, LSPEC256), + makePair(BSPEC64, FSPEC256), + makePair(SSPEC256, BSPEC128), + makePair(SSPEC128, ISPEC256), + makePair(SSPEC64, LSPEC256), + makePair(SSPEC128, FSPEC256), + makePair(ISPEC256, BSPEC64), + makePair(ISPEC256, SSPEC128), + makePair(ISPEC128, LSPEC256), + makePair(ISPEC256, FSPEC256), + makePair(LSPEC256, BSPEC64), + makePair(LSPEC256, SSPEC64), + makePair(LSPEC256, ISPEC128), + makePair(FSPEC256, ISPEC256) + ).stream()).toList(); + + public static final List<VectorSpeciesPair> AVX512_CAST_TESTS = Stream.concat(AVX2_CAST_TESTS.stream(), List.of( + makePair(BSPEC256, SSPEC512), + makePair(BSPEC128, ISPEC512), + makePair(BSPEC64, LSPEC512), + makePair(BSPEC128, FSPEC512), + makePair(BSPEC64, DSPEC512), + makePair(SSPEC512, BSPEC256), + makePair(SSPEC256, ISPEC512), + makePair(SSPEC128, LSPEC512), + makePair(SSPEC256, FSPEC512), + makePair(SSPEC128, DSPEC512), + makePair(ISPEC512, BSPEC128), + makePair(ISPEC512, SSPEC256), + makePair(ISPEC256, LSPEC512), + makePair(ISPEC512, FSPEC512), + makePair(ISPEC256, DSPEC512), + makePair(LSPEC512, BSPEC64), + makePair(LSPEC512, SSPEC128), + makePair(LSPEC512, ISPEC256), + makePair(FSPEC512, ISPEC512), + makePair(FSPEC256, DSPEC512), + makePair(DSPEC512, FSPEC256) + ).stream()).toList(); + + public static final List<VectorSpeciesPair> AVX512DQ_CAST_TESTS = Stream.concat(AVX512_CAST_TESTS.stream(), List.of( + makePair(LSPEC128, DSPEC128), + makePair(LSPEC256, DSPEC256), + makePair(LSPEC512, DSPEC512), + makePair(DSPEC128, LSPEC128), + makePair(DSPEC256, LSPEC256), + makePair(DSPEC512, LSPEC512) + ).stream()).toList(); + + public static final List<VectorSpeciesPair> SVE_CAST_TESTS = List.of( + makePair(BSPEC64, SSPEC128), + makePair(BSPEC128, SSPEC256), + makePair(BSPEC256, SSPEC512), + makePair(BSPEC64, ISPEC256), + makePair(BSPEC128, ISPEC512), + makePair(BSPEC64, LSPEC512), + makePair(BSPEC64, FSPEC256), + makePair(BSPEC128, FSPEC512), + makePair(BSPEC64, DSPEC512), + makePair(SSPEC128, BSPEC64), + makePair(SSPEC256, BSPEC128), + makePair(SSPEC512, BSPEC256), + makePair(SSPEC64, ISPEC128), + makePair(SSPEC128, ISPEC256), + makePair(SSPEC256, ISPEC512), + makePair(SSPEC64, LSPEC256), + makePair(SSPEC128, LSPEC512), + makePair(SSPEC64, FSPEC128), + makePair(SSPEC128, FSPEC256), + makePair(SSPEC256, FSPEC512), + makePair(SSPEC64, DSPEC256), + makePair(SSPEC128, DSPEC512), + makePair(ISPEC256, BSPEC64), + makePair(ISPEC512, BSPEC128), + makePair(ISPEC128, SSPEC64), + makePair(ISPEC256, SSPEC128), + makePair(ISPEC512, SSPEC256), + makePair(ISPEC64, LSPEC128), + makePair(ISPEC128, LSPEC256), + makePair(ISPEC256, LSPEC512), + makePair(ISPEC64, FSPEC64), + makePair(ISPEC128, FSPEC128), + makePair(ISPEC256, FSPEC256), + makePair(ISPEC512, FSPEC512), + makePair(ISPEC64, DSPEC128), + makePair(ISPEC128, DSPEC256), + makePair(ISPEC256, DSPEC512), + makePair(LSPEC512, BSPEC64), + makePair(LSPEC256, SSPEC64), + makePair(LSPEC512, SSPEC128), + makePair(LSPEC128, ISPEC64), + makePair(LSPEC256, ISPEC128), + makePair(LSPEC512, ISPEC256), + makePair(LSPEC128, FSPEC64), + makePair(LSPEC256, FSPEC128), + makePair(LSPEC512, FSPEC256), + makePair(LSPEC128, DSPEC128), + makePair(LSPEC256, DSPEC256), + makePair(LSPEC512, DSPEC512), + makePair(FSPEC256, BSPEC64), + makePair(FSPEC512, BSPEC128), + makePair(FSPEC128, SSPEC64), + makePair(FSPEC256, SSPEC128), + makePair(FSPEC512, SSPEC256), + makePair(FSPEC64, ISPEC64), + makePair(FSPEC128, ISPEC128), + makePair(FSPEC256, ISPEC256), + makePair(FSPEC512, ISPEC512), + makePair(FSPEC64, LSPEC128), + makePair(FSPEC128, LSPEC256), + makePair(FSPEC256, LSPEC512), + makePair(FSPEC64, DSPEC128), + makePair(FSPEC128, DSPEC256), + makePair(FSPEC256, DSPEC512), + makePair(DSPEC512, BSPEC64), + makePair(DSPEC256, SSPEC64), + makePair(DSPEC512, SSPEC128), + makePair(DSPEC128, ISPEC64), + makePair(DSPEC256, ISPEC128), + makePair(DSPEC512, ISPEC256), + makePair(DSPEC128, LSPEC128), + makePair(DSPEC256, LSPEC256), + makePair(DSPEC512, LSPEC512), + makePair(DSPEC128, FSPEC64), + makePair(DSPEC256, FSPEC128), + makePair(DSPEC512, FSPEC256) + ); + + public static final List<VectorSpeciesPair> NEON_CAST_TESTS = List.of( + makePair(BSPEC64, SSPEC64), + makePair(BSPEC64, SSPEC128), + makePair(BSPEC64, ISPEC128), + makePair(BSPEC64, FSPEC128), + makePair(SSPEC64, BSPEC64), + makePair(SSPEC128, BSPEC64), + makePair(SSPEC64, ISPEC128), + makePair(SSPEC64, FSPEC128), + makePair(ISPEC128, BSPEC64), + makePair(ISPEC128, SSPEC64), + makePair(ISPEC64, LSPEC128), + makePair(ISPEC64, FSPEC64), + makePair(ISPEC128, FSPEC128), + makePair(ISPEC64, DSPEC128), + makePair(LSPEC128, ISPEC64), + makePair(LSPEC128, FSPEC64), + makePair(LSPEC128, DSPEC128), + makePair(FSPEC128, BSPEC64), + makePair(FSPEC128, SSPEC64), + makePair(FSPEC64, ISPEC64), + makePair(FSPEC128, ISPEC128), + makePair(FSPEC64, LSPEC128), + makePair(FSPEC64, DSPEC128), + makePair(DSPEC128, ISPEC64), + makePair(DSPEC128, LSPEC128), + makePair(DSPEC128, FSPEC64) + ); +} diff --git a/test/hotspot/jtreg/compiler/vectorapi/reshape/utils/UnsafeUtils.java b/test/hotspot/jtreg/compiler/vectorapi/reshape/utils/UnsafeUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..4d244560b3facb4c5e837d7e71b770f4855bae0a --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorapi/reshape/utils/UnsafeUtils.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.vectorapi.reshape.utils; + +import jdk.internal.misc.Unsafe; + +/** + * Unsafe to check for correctness of reinterpret operations. May be replaced with foreign API later. + */ +public class UnsafeUtils { + private static final Unsafe UNSAFE = Unsafe.getUnsafe(); + + public static long arrayBase(Class<?> etype) { + return UNSAFE.arrayBaseOffset(etype.arrayType()); + } + + public static int getByte(Object o, long base, int i) { + // This is technically an UB, what we need is UNSAFE.getByteUnaligned but they seem to be equivalent + return UNSAFE.getByte(o, base + i); + } + + public static void putByte(Object o, long base, int i, int value) { + UNSAFE.putByte(o, base + i, (byte)value); + } +} diff --git a/test/hotspot/jtreg/compiler/vectorapi/reshape/utils/VectorReshapeHelper.java b/test/hotspot/jtreg/compiler/vectorapi/reshape/utils/VectorReshapeHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..848d4b38ee2ef166bf9083d5ba31bd549e8439e6 --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorapi/reshape/utils/VectorReshapeHelper.java @@ -0,0 +1,372 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.vectorapi.reshape.utils; + +import compiler.lib.ir_framework.ForceInline; +import compiler.lib.ir_framework.IRNode; +import compiler.lib.ir_framework.TestFramework; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.invoke.VarHandle; +import java.lang.reflect.Array; +import java.nio.ByteOrder; +import java.util.List; +import java.util.random.RandomGenerator; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import jdk.incubator.vector.*; +import jdk.test.lib.Asserts; + +public class VectorReshapeHelper { + public static final int INVOCATIONS = 10_000; + + public static final VectorSpecies<Byte> BSPEC64 = ByteVector.SPECIES_64; + public static final VectorSpecies<Short> SSPEC64 = ShortVector.SPECIES_64; + public static final VectorSpecies<Integer> ISPEC64 = IntVector.SPECIES_64; + public static final VectorSpecies<Long> LSPEC64 = LongVector.SPECIES_64; + public static final VectorSpecies<Float> FSPEC64 = FloatVector.SPECIES_64; + public static final VectorSpecies<Double> DSPEC64 = DoubleVector.SPECIES_64; + + public static final VectorSpecies<Byte> BSPEC128 = ByteVector.SPECIES_128; + public static final VectorSpecies<Short> SSPEC128 = ShortVector.SPECIES_128; + public static final VectorSpecies<Integer> ISPEC128 = IntVector.SPECIES_128; + public static final VectorSpecies<Long> LSPEC128 = LongVector.SPECIES_128; + public static final VectorSpecies<Float> FSPEC128 = FloatVector.SPECIES_128; + public static final VectorSpecies<Double> DSPEC128 = DoubleVector.SPECIES_128; + + public static final VectorSpecies<Byte> BSPEC256 = ByteVector.SPECIES_256; + public static final VectorSpecies<Short> SSPEC256 = ShortVector.SPECIES_256; + public static final VectorSpecies<Integer> ISPEC256 = IntVector.SPECIES_256; + public static final VectorSpecies<Long> LSPEC256 = LongVector.SPECIES_256; + public static final VectorSpecies<Float> FSPEC256 = FloatVector.SPECIES_256; + public static final VectorSpecies<Double> DSPEC256 = DoubleVector.SPECIES_256; + + public static final VectorSpecies<Byte> BSPEC512 = ByteVector.SPECIES_512; + public static final VectorSpecies<Short> SSPEC512 = ShortVector.SPECIES_512; + public static final VectorSpecies<Integer> ISPEC512 = IntVector.SPECIES_512; + public static final VectorSpecies<Long> LSPEC512 = LongVector.SPECIES_512; + public static final VectorSpecies<Float> FSPEC512 = FloatVector.SPECIES_512; + public static final VectorSpecies<Double> DSPEC512 = DoubleVector.SPECIES_512; + + public static final String B2X_NODE = IRNode.VECTOR_CAST_B2X; + public static final String S2X_NODE = IRNode.VECTOR_CAST_S2X; + public static final String I2X_NODE = IRNode.VECTOR_CAST_I2X; + public static final String L2X_NODE = IRNode.VECTOR_CAST_L2X; + public static final String F2X_NODE = IRNode.VECTOR_CAST_F2X; + public static final String D2X_NODE = IRNode.VECTOR_CAST_D2X; + public static final String REINTERPRET_NODE = IRNode.VECTOR_REINTERPRET; + + public static void runMainHelper(Class<?> testClass, Stream<VectorSpeciesPair> testMethods, String... flags) { + var test = new TestFramework(testClass); + test.setDefaultWarmup(1); + test.addHelperClasses(VectorReshapeHelper.class); + test.addFlags("--add-modules=jdk.incubator.vector"); + test.addFlags(flags); + String testMethodNames = testMethods + .filter(p -> p.isp().length() <= VectorSpecies.ofLargestShape(p.isp().elementType()).length()) + .filter(p -> p.osp().length() <= VectorSpecies.ofLargestShape(p.osp().elementType()).length()) + .map(VectorSpeciesPair::format) + .collect(Collectors.joining(",")); + test.addFlags("-DTest=" + testMethodNames); + test.start(); + } + + @ForceInline + public static <T, U> void vectorCast(VectorOperators.Conversion<T, U> cop, + VectorSpecies<T> isp, VectorSpecies<U> osp, byte[] input, byte[] output) { + isp.fromByteArray(input, 0, ByteOrder.nativeOrder()) + .convertShape(cop, osp, 0) + .intoByteArray(output, 0, ByteOrder.nativeOrder()); + } + + public static <T, U> void runCastHelper(VectorOperators.Conversion<T, U> castOp, + VectorSpecies<T> isp, VectorSpecies<U> osp) throws Throwable { + var random = RandomGenerator.getDefault(); + boolean isUnsignedCast = castOp.name().startsWith("ZERO"); + String testMethodName = VectorSpeciesPair.makePair(isp, osp).format(); + var caller = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE).getCallerClass(); + var testMethod = MethodHandles.lookup().findStatic(caller, + testMethodName, + MethodType.methodType(void.class, byte.class.arrayType(), byte.class.arrayType())); + byte[] input = new byte[isp.vectorByteSize()]; + byte[] output = new byte[osp.vectorByteSize()]; + for (int iter = 0; iter < INVOCATIONS; iter++) { + // We need to generate arrays with NaN or very large values occasionally + boolean normalArray = random.nextBoolean(); + var abnormalValue = List.of(Double.NaN, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, -1e30, 1e30); + for (int i = 0; i < isp.length(); i++) { + switch (isp.elementType().getName()) { + case "byte" -> setByte(input, i, (byte)random.nextInt()); + case "short" -> setShort(input, i, (short)random.nextInt()); + case "int" -> setInt(input, i, random.nextInt()); + case "long" -> setLong(input, i, random.nextLong()); + case "float" -> { + if (normalArray || random.nextBoolean()) { + setFloat(input, i, random.nextFloat(Byte.MIN_VALUE, Byte.MAX_VALUE)); + } else { + setFloat(input, i, abnormalValue.get(random.nextInt(abnormalValue.size())).floatValue()); + } + } + case "double" -> { + if (normalArray || random.nextBoolean()) { + setDouble(input, i, random.nextDouble(Byte.MIN_VALUE, Byte.MAX_VALUE)); + } else { + setDouble(input, i, abnormalValue.get(random.nextInt(abnormalValue.size()))); + } + } + default -> throw new AssertionError(); + } + } + + testMethod.invokeExact(input, output); + + for (int i = 0; i < osp.length(); i++) { + Number expected, actual; + if (i < isp.length()) { + Number initial = switch (isp.elementType().getName()) { + case "byte" -> getByte(input, i); + case "short" -> getShort(input, i); + case "int" -> getInt(input, i); + case "long" -> getLong(input, i); + case "float" -> getFloat(input, i); + case "double" -> getDouble(input, i); + default -> throw new AssertionError(); + }; + expected = switch (osp.elementType().getName()) { + case "byte" -> initial.byteValue(); + case "short" -> { + if (isUnsignedCast) { + yield (short) (initial.longValue() & ((1L << isp.elementSize()) - 1)); + } else { + yield initial.shortValue(); + } + } + case "int" -> { + if (isUnsignedCast) { + yield (int) (initial.longValue() & ((1L << isp.elementSize()) - 1)); + } else { + yield initial.intValue(); + } + } + case "long" -> { + if (isUnsignedCast) { + yield (long) (initial.longValue() & ((1L << isp.elementSize()) - 1)); + } else { + yield initial.longValue(); + } + } + case "float" -> initial.floatValue(); + case "double" -> initial.doubleValue(); + default -> throw new AssertionError(); + }; + } else { + expected = switch (osp.elementType().getName()) { + case "byte" -> (byte)0; + case "short" -> (short)0; + case "int" -> (int)0; + case "long" -> (long)0; + case "float" -> (float)0; + case "double" -> (double)0; + default -> throw new AssertionError(); + }; + } + actual = switch (osp.elementType().getName()) { + case "byte" -> getByte(output, i); + case "short" -> getShort(output, i); + case "int" -> getInt(output, i); + case "long" -> getLong(output, i); + case "float" -> getFloat(output, i); + case "double" -> getDouble(output, i); + default -> throw new AssertionError(); + }; + Asserts.assertEquals(expected, actual); + } + } + } + + @ForceInline + public static <T, U> void vectorExpandShrink(VectorSpecies<T> isp, VectorSpecies<U> osp, byte[] input, byte[] output) { + isp.fromByteArray(input, 0, ByteOrder.nativeOrder()) + .reinterpretShape(osp, 0) + .intoByteArray(output, 0, ByteOrder.nativeOrder()); + } + + public static <T, U> void runExpandShrinkHelper(VectorSpecies<T> isp, VectorSpecies<U> osp) throws Throwable { + var random = RandomGenerator.getDefault(); + String testMethodName = VectorSpeciesPair.makePair(isp, osp).format(); + var caller = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE).getCallerClass(); + var testMethod = MethodHandles.lookup().findStatic(caller, + testMethodName, + MethodType.methodType(void.class, byte.class.arrayType(), byte.class.arrayType())); + byte[] input = new byte[isp.vectorByteSize()]; + byte[] output = new byte[osp.vectorByteSize()]; + for (int iter = 0; iter < INVOCATIONS; iter++) { + random.nextBytes(input); + + testMethod.invokeExact(input, output); + + for (int i = 0; i < osp.vectorByteSize(); i++) { + int expected = i < isp.vectorByteSize() ? input[i] : 0; + int actual = output[i]; + Asserts.assertEquals(expected, actual); + } + } + } + + @ForceInline + public static <T, U> void vectorDoubleExpandShrink(VectorSpecies<T> isp, VectorSpecies<U> osp, byte[] input, byte[] output) { + isp.fromByteArray(input, 0, ByteOrder.nativeOrder()) + .reinterpretShape(osp, 0) + .reinterpretShape(isp, 0) + .intoByteArray(output, 0, ByteOrder.nativeOrder()); + } + + public static <T, U> void runDoubleExpandShrinkHelper(VectorSpecies<T> isp, VectorSpecies<U> osp) throws Throwable { + var random = RandomGenerator.getDefault(); + String testMethodName = VectorSpeciesPair.makePair(isp, osp).format(); + var caller = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE).getCallerClass(); + var testMethod = MethodHandles.lookup().findStatic(caller, + testMethodName, + MethodType.methodType(void.class, byte.class.arrayType(), byte.class.arrayType())); + byte[] input = new byte[isp.vectorByteSize()]; + byte[] output = new byte[isp.vectorByteSize()]; + for (int iter = 0; iter < INVOCATIONS; iter++) { + random.nextBytes(input); + + testMethod.invokeExact(input, output); + + for (int i = 0; i < isp.vectorByteSize(); i++) { + int expected = i < osp.vectorByteSize() ? input[i] : 0; + int actual = output[i]; + Asserts.assertEquals(expected, actual); + } + } + } + + // All this complication is due to the fact that vector load and store with respect to byte array introduce + // additional ReinterpretNodes, several ReinterpretNodes back to back being optimized make the number of + // nodes remaining in the IR becomes unpredictable. + @ForceInline + public static <T, U> void vectorRebracket(VectorSpecies<T> isp, VectorSpecies<U> osp, Object input, Object output) { + var outputVector = isp.fromArray(input, 0).reinterpretShape(osp, 0); + var otype = osp.elementType(); + if (otype == byte.class) { + ((ByteVector)outputVector).intoArray((byte[])output, 0); + } else if (otype == short.class) { + ((ShortVector)outputVector).intoArray((short[])output, 0); + } else if (otype == int.class) { + ((IntVector)outputVector).intoArray((int[])output, 0); + } else if (otype == long.class) { + ((LongVector)outputVector).intoArray((long[])output, 0); + } else if (otype == float.class) { + ((FloatVector)outputVector).intoArray((float[])output, 0); + } else if (otype == double.class) { + ((DoubleVector)outputVector).intoArray((double[])output, 0); + } else { + throw new AssertionError(); + } + } + + public static <T, U> void runRebracketHelper(VectorSpecies<T> isp, VectorSpecies<U> osp) throws Throwable { + var random = RandomGenerator.getDefault(); + String testMethodName = VectorSpeciesPair.makePair(isp, osp).format(); + var caller = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE).getCallerClass(); + var testMethod = MethodHandles.lookup().findStatic(caller, + testMethodName, + MethodType.methodType(void.class, isp.elementType().arrayType(), osp.elementType().arrayType())) + .asType(MethodType.methodType(void.class, Object.class, Object.class)); + Object input = Array.newInstance(isp.elementType(), isp.length()); + Object output = Array.newInstance(osp.elementType(), osp.length()); + long ibase = UnsafeUtils.arrayBase(isp.elementType()); + long obase = UnsafeUtils.arrayBase(osp.elementType()); + for (int iter = 0; iter < INVOCATIONS; iter++) { + for (int i = 0; i < isp.vectorByteSize(); i++) { + UnsafeUtils.putByte(input, ibase, i, random.nextInt()); + } + + testMethod.invokeExact(input, output); + + for (int i = 0; i < osp.vectorByteSize(); i++) { + int expected = i < isp.vectorByteSize() ? UnsafeUtils.getByte(input, ibase, i) : 0; + int actual = UnsafeUtils.getByte(output, obase, i); + Asserts.assertEquals(expected, actual); + } + } + } + + public static byte getByte(byte[] array, int index) { + return (byte)BYTE_ACCESS.get(array, index * Byte.BYTES); + } + + public static short getShort(byte[] array, int index) { + return (short)SHORT_ACCESS.get(array, index * Short.BYTES); + } + + public static int getInt(byte[] array, int index) { + return (int)INT_ACCESS.get(array, index * Integer.BYTES); + } + + public static long getLong(byte[] array, int index) { + return (long)LONG_ACCESS.get(array, index * Long.BYTES); + } + + public static float getFloat(byte[] array, int index) { + return (float)FLOAT_ACCESS.get(array, index * Float.BYTES); + } + + public static double getDouble(byte[] array, int index) { + return (double)DOUBLE_ACCESS.get(array, index * Double.BYTES); + } + + public static void setByte(byte[] array, int index, byte value) { + BYTE_ACCESS.set(array, index * Byte.BYTES, value); + } + + public static void setShort(byte[] array, int index, short value) { + SHORT_ACCESS.set(array, index * Short.BYTES, value); + } + + public static void setInt(byte[] array, int index, int value) { + INT_ACCESS.set(array, index * Integer.BYTES, value); + } + + public static void setLong(byte[] array, int index, long value) { + LONG_ACCESS.set(array, index * Long.BYTES, value); + } + + public static void setFloat(byte[] array, int index, float value) { + FLOAT_ACCESS.set(array, index * Float.BYTES, value); + } + + public static void setDouble(byte[] array, int index, double value) { + DOUBLE_ACCESS.set(array, index * Double.BYTES, value); + } + + private static final VarHandle BYTE_ACCESS = MethodHandles.arrayElementVarHandle(byte.class.arrayType()); + private static final VarHandle SHORT_ACCESS = MethodHandles.byteArrayViewVarHandle(short.class.arrayType(), ByteOrder.nativeOrder()); + private static final VarHandle INT_ACCESS = MethodHandles.byteArrayViewVarHandle(int.class.arrayType(), ByteOrder.nativeOrder()); + private static final VarHandle LONG_ACCESS = MethodHandles.byteArrayViewVarHandle(long.class.arrayType(), ByteOrder.nativeOrder()); + private static final VarHandle FLOAT_ACCESS = MethodHandles.byteArrayViewVarHandle(float.class.arrayType(), ByteOrder.nativeOrder()); + private static final VarHandle DOUBLE_ACCESS = MethodHandles.byteArrayViewVarHandle(double.class.arrayType(), ByteOrder.nativeOrder()); +} diff --git a/test/hotspot/jtreg/compiler/vectorapi/reshape/utils/VectorSpeciesPair.java b/test/hotspot/jtreg/compiler/vectorapi/reshape/utils/VectorSpeciesPair.java new file mode 100644 index 0000000000000000000000000000000000000000..74497f253abdc0bc84cb8518d20b9f78df6d7904 --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorapi/reshape/utils/VectorSpeciesPair.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.vectorapi.reshape.utils; + +import jdk.incubator.vector.VectorSpecies; + +public record VectorSpeciesPair(VectorSpecies<?> isp, VectorSpecies<?> osp, boolean unsignedCast) { + public static VectorSpeciesPair makePair(VectorSpecies<?> isp, VectorSpecies<?> osp, boolean unsignedCast) { + return new VectorSpeciesPair(isp, osp, unsignedCast); + } + + public static VectorSpeciesPair makePair(VectorSpecies<?> isp, VectorSpecies<?> osp) { + return new VectorSpeciesPair(isp, osp, false); + } + + public String format() { + return String.format("test%s%c%dto%c%d", + unsignedCast() ? "U" : "", + Character.toUpperCase(isp().elementType().getName().charAt(0)), + isp().vectorBitSize(), + Character.toUpperCase(osp().elementType().getName().charAt(0)), + osp().vectorBitSize()); + } +} diff --git a/test/hotspot/jtreg/gc/epsilon/TestMemoryMXBeans.java b/test/hotspot/jtreg/gc/epsilon/TestMemoryMXBeans.java index a9ff8d00ba09139d50ee3a502640f24d5efa3df1..1cb358e60dd896e9449261854318dc95ef0700d6 100644 --- a/test/hotspot/jtreg/gc/epsilon/TestMemoryMXBeans.java +++ b/test/hotspot/jtreg/gc/epsilon/TestMemoryMXBeans.java @@ -36,7 +36,7 @@ package gc.epsilon; * gc.epsilon.TestMemoryMXBeans * -1 256 * - * @run main/othervm -Xmx256m -Xmx256m + * @run main/othervm -Xms256m -Xmx256m * -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC * gc.epsilon.TestMemoryMXBeans * 256 256 diff --git a/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java b/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java index a9f347dbb073f0cd052002fae39615a12a26b982..3b997d74dc16f02f67ff3a044f863e71bd0830e3 100644 --- a/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java +++ b/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java @@ -142,6 +142,7 @@ public class TestGCLogMessages { new LogMessageWithLevel("Scanned Cards", Level.DEBUG), new LogMessageWithLevel("Scanned Blocks", Level.DEBUG), new LogMessageWithLevel("Claimed Chunks", Level.DEBUG), + new LogMessageWithLevel("Found Roots", Level.DEBUG), // Code Roots Scan new LogMessageWithLevel("Code Root Scan", Level.DEBUG), // Object Copy diff --git a/test/hotspot/jtreg/gc/shenandoah/compiler/TestLinkToNativeRBP.java b/test/hotspot/jtreg/gc/shenandoah/compiler/TestLinkToNativeRBP.java index 4d5203167d3df56ce847265ba3078fad93f5a840..a5ebe6f5de8a188238ebda319278aa0369bd557c 100644 --- a/test/hotspot/jtreg/gc/shenandoah/compiler/TestLinkToNativeRBP.java +++ b/test/hotspot/jtreg/gc/shenandoah/compiler/TestLinkToNativeRBP.java @@ -40,22 +40,19 @@ import jdk.incubator.foreign.CLinker; import jdk.incubator.foreign.FunctionDescriptor; import jdk.incubator.foreign.SymbolLookup; +import jdk.incubator.foreign.ValueLayout; import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodType; - -import static jdk.incubator.foreign.CLinker.C_INT; public class TestLinkToNativeRBP { static { System.loadLibrary("LinkToNativeRBP"); } - final static CLinker abi = CLinker.getInstance(); + final static CLinker abi = CLinker.systemCLinker(); static final SymbolLookup lookup = SymbolLookup.loaderLookup(); final static MethodHandle foo = abi.downcallHandle(lookup.lookup("foo").get(), - MethodType.methodType(int.class), - FunctionDescriptor.of(C_INT)); + FunctionDescriptor.of(ValueLayout.JAVA_INT)); static int foo() throws Throwable { return (int)foo.invokeExact(); diff --git a/test/hotspot/jtreg/gc/stress/gclocker/TestGCLockerWithSerial.java b/test/hotspot/jtreg/gc/stress/gclocker/TestGCLockerWithSerial.java index e81a762212bc8af07a70de980c3f300cde326bb4..9de8fa88ca70868098c7aba02f5dd6177229c827 100644 --- a/test/hotspot/jtreg/gc/stress/gclocker/TestGCLockerWithSerial.java +++ b/test/hotspot/jtreg/gc/stress/gclocker/TestGCLockerWithSerial.java @@ -30,7 +30,7 @@ package gc.stress.gclocker; * @requires vm.gc.Serial * @requires vm.flavor != "minimal" * @summary Stress Serial's GC locker by calling GetPrimitiveArrayCritical while concurrently filling up old gen. - * @run main/native/othervm/timeout=200 -Xlog:gc*=info -Xmx1500m -Xmx1500m -XX:+UseSerialGC gc.stress.gclocker.TestGCLockerWithSerial + * @run main/native/othervm/timeout=200 -Xlog:gc*=info -Xms1500m -Xmx1500m -XX:+UseSerialGC gc.stress.gclocker.TestGCLockerWithSerial */ public class TestGCLockerWithSerial { public static void main(String[] args) { diff --git a/test/hotspot/jtreg/runtime/BootstrapMethod/BSMCalledTwice.java b/test/hotspot/jtreg/runtime/BootstrapMethod/BSMCalledTwice.java index bad675a40ffcc4d7f4c98c8f9232a9c0b90bf6dd..a8a8aa060bf038295d045cc2b39778245e37224c 100644 --- a/test/hotspot/jtreg/runtime/BootstrapMethod/BSMCalledTwice.java +++ b/test/hotspot/jtreg/runtime/BootstrapMethod/BSMCalledTwice.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,16 @@ * @run main BSMCalledTwice */ +/* + * @test + * @bug 8262134 + * @library /test/lib + * @requires vm.debug + * @modules java.base/jdk.internal.org.objectweb.asm + * @compile -XDignore.symbol.file BSMCalledTwice.java + * @run main/othervm -Xcomp -XX:CompileCommand=compileonly,TestC::* -XX:+DeoptimizeALot -XX:+VerifyStack BSMCalledTwice + */ + import java.io.File; import java.io.FileOutputStream; import java.util.*; diff --git a/test/hotspot/jtreg/runtime/CommandLine/PrintTouchedMethodsJcmd.java b/test/hotspot/jtreg/runtime/CommandLine/PrintTouchedMethodsJcmd.java index f3188007941f385ba91c09c886ddf8152fda8633..26f0c3ca0dc2b221a9f403feac31e3ea0b43114c 100644 --- a/test/hotspot/jtreg/runtime/CommandLine/PrintTouchedMethodsJcmd.java +++ b/test/hotspot/jtreg/runtime/CommandLine/PrintTouchedMethodsJcmd.java @@ -41,10 +41,6 @@ public class PrintTouchedMethodsJcmd { var pb = new ProcessBuilder(); pb.command(new String[] {JDKToolFinder.getJDKTool("jcmd"), pid, "VM.print_touched_methods"}); var output = new OutputAnalyzer(pb.start()); - try { - output.shouldContain("PrintTouchedMethodsJcmd.main:([Ljava/lang/String;)V"); - } catch (RuntimeException e) { - output.shouldContain("Unknown diagnostic command"); - } - } + output.shouldContain("PrintTouchedMethodsJcmd.main:([Ljava/lang/String;)V"); + } } diff --git a/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java b/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java index b8e6c41c1ba00e152ad11319dead78f81d90d8c4..e9ccac0879314cdd8777824c7dcac8d320e8f0f3 100644 --- a/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java +++ b/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java @@ -21,6 +21,10 @@ * questions. */ +import java.util.Arrays; +import java.util.ArrayList; + +import jdk.test.lib.Platform; import jdk.test.lib.process.ProcessTools; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.cli.*; @@ -39,22 +43,24 @@ public class VMDeprecatedOptions { * each entry is {[0]: option name, [1]: value to set * (true/false/n/string)}. */ - public static final String[][] DEPRECATED_OPTIONS = { - // deprecated non-alias flags: - {"MaxGCMinorPauseMillis", "1032"}, - {"MaxRAMFraction", "8"}, - {"MinRAMFraction", "2"}, - {"InitialRAMFraction", "64"}, - {"TLABStats", "false"}, - {"AllowRedefinitionToAddDeleteMethods", "true"}, - {"UseSharedSpaces", "false"}, - {"RequireSharedSpaces", "false"}, - {"DumpSharedSpaces", "false"}, - {"DynamicDumpSharedSpaces", "false"}, + public static final String[][] DEPRECATED_OPTIONS; + static { + ArrayList<String[]> deprecated = new ArrayList( + Arrays.asList(new String[][] { + // deprecated non-alias flags: + {"MaxGCMinorPauseMillis", "1032"}, + {"MaxRAMFraction", "8"}, + {"MinRAMFraction", "2"}, + {"InitialRAMFraction", "64"}, + {"TLABStats", "false"}, + {"AllowRedefinitionToAddDeleteMethods", "true"}, - // deprecated alias flags (see also aliased_jvm_flags): - {"DefaultMaxRAMFraction", "4"}, - {"CreateMinidumpOnCrash", "false"} + // deprecated alias flags (see also aliased_jvm_flags): + {"DefaultMaxRAMFraction", "4"}, + {"CreateMinidumpOnCrash", "false"} + } + )); + DEPRECATED_OPTIONS = deprecated.toArray(new String[][]{}); }; static String getDeprecationString(String optionName) { diff --git a/test/hotspot/jtreg/runtime/HiddenClasses/InstantiateHiddenClass.java b/test/hotspot/jtreg/runtime/HiddenClasses/InstantiateHiddenClass.java index 773588b11f94311fb98f9777d249e10feb0734f8..cb8d59af2f7d4360a95ac64088384e82efb05b23 100644 --- a/test/hotspot/jtreg/runtime/HiddenClasses/InstantiateHiddenClass.java +++ b/test/hotspot/jtreg/runtime/HiddenClasses/InstantiateHiddenClass.java @@ -32,6 +32,7 @@ import java.lang.invoke.MethodType; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles.Lookup; +import java.lang.invoke.MethodHandles.Lookup.ClassOption; import static java.lang.invoke.MethodHandles.Lookup.ClassOption.*; import jdk.test.lib.compiler.InMemoryJavaCompiler; @@ -44,12 +45,19 @@ public class InstantiateHiddenClass { " } } "); public static void main(String[] args) throws Throwable { + // This class is also used by the appcds/dynamicArchive/RegularHiddenClass.java + // test which will pass the "keep-alive" argument during dynamic CDS dump + // for preventing from being GC'ed prior to the dumping operation. + boolean keepAlive = false; + if (args.length == 1 && args[0].equals("keep-alive")) { + keepAlive = true; + } // Test that a hidden class cannot be found through its name. try { Lookup lookup = MethodHandles.lookup(); - Class<?> cl = lookup.defineHiddenClass(klassbuf, false, NESTMATE).lookupClass(); - Class.forName(cl.getName()).newInstance(); + Class<?> c0 = lookup.defineHiddenClass(klassbuf, false, NESTMATE).lookupClass(); + Class.forName(c0.getName()).newInstance(); throw new RuntimeException("Expected ClassNotFoundException not thrown"); } catch (ClassNotFoundException e ) { // Test passed @@ -60,8 +68,9 @@ public class InstantiateHiddenClass { // Verify that the references to these objects are different and references // to their classes are not equal either. Lookup lookup = MethodHandles.lookup(); - Class<?> c1 = lookup.defineHiddenClass(klassbuf, false, NESTMATE).lookupClass(); - Class<?> c2 = lookup.defineHiddenClass(klassbuf, false, NESTMATE).lookupClass(); + ClassOption classOption = keepAlive ? STRONG : NESTMATE; + Class<?> c1 = lookup.defineHiddenClass(klassbuf, false, classOption).lookupClass(); + Class<?> c2 = lookup.defineHiddenClass(klassbuf, false, classOption).lookupClass(); Object o1 = c1.newInstance(); Object o2 = c2.newInstance(); if (o1 == o2) { diff --git a/test/hotspot/jtreg/runtime/Metaspace/PrintMetaspaceDcmd.java b/test/hotspot/jtreg/runtime/Metaspace/PrintMetaspaceDcmd.java index 413a911e700b10088d9778b042d53e3c0b6f8551..d90a49a0adbcdea6038809f9854cb06d7764e2fc 100644 --- a/test/hotspot/jtreg/runtime/Metaspace/PrintMetaspaceDcmd.java +++ b/test/hotspot/jtreg/runtime/Metaspace/PrintMetaspaceDcmd.java @@ -168,6 +168,29 @@ public class PrintMetaspaceDcmd { output.shouldContain("Virtual space list"); output.shouldMatch("node.*reserved.*committed.*used.*"); + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.metaspace", "chunkfreelist"}); + // Output should look somewhat like this... + // vvvvvvvvvvvvvvvv + // Chunk freelist details: + // Non-Class: + // cm non-class-space: 5 chunks, total word size: 402944. + // -- List[lv00]: empty + // -- List[lv01]: - <Chunk @0x00007f925c124090, state f, base 0x00007f9208600000, level lv01 (262144 words), used 0 words, committed 0 words.> - total : 1 chunks. + // -- List[lv02]: - <Chunk @0x00007f925c1240d8, state f, base 0x00007f9208500000, level lv02 (131072 words), used 0 words, committed 0 words.> - total : 1 chunks. + // -- List[lv03]: empty + // ..... + // + // total chunks: 5, total word size: 402944. + // ^^^^^^^^^^^^^^^^^ + // .... but the actual number of chunks in the freelist is difficult to predict and may be low or zero since + // no class unloading happened yet. + output = new OutputAnalyzer(pb.start()); + output.shouldHaveExitValue(0); + output.shouldContain("Chunk freelist details:"); + // ... but we should see at least one one chunk somewhere, the list should never be empty. + output.shouldMatch(".*-- List\\[lv00\\].*"); + output.shouldMatch(".*total chunks.*total word size.*"); + // Test with different scales pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.metaspace", "scale=G"}); output = new OutputAnalyzer(pb.start()); diff --git a/test/hotspot/jtreg/runtime/Monitor/MonitorUsedDeflationThresholdTest.java b/test/hotspot/jtreg/runtime/Monitor/MonitorUsedDeflationThresholdTest.java index 6bae009a84dafac02a3e9e783fb991df436e32a7..5dd01e4262bcdadc251d3fea0c6d9aae6aa46aab 100644 --- a/test/hotspot/jtreg/runtime/Monitor/MonitorUsedDeflationThresholdTest.java +++ b/test/hotspot/jtreg/runtime/Monitor/MonitorUsedDeflationThresholdTest.java @@ -81,6 +81,11 @@ public class MonitorUsedDeflationThresholdTest { // of monitors for threads that call Object.wait(). "-XX:+UnlockDiagnosticVMOptions", "-XX:AvgMonitorsPerThreadEstimate=1", + // MonitorUsedDeflationThreshold == 10 means we'll request + // deflations when 10% of monitors are used rather than the + // default 90%. This should allow the test to tolerate a burst + // of used monitors by threads not under this test's control. + "-XX:MonitorUsedDeflationThreshold=10", // Enable monitorinflation logging so we can see that // MonitorUsedDeflationThreshold and // NoAsyncDeflationProgressMaxoption are working. @@ -89,8 +94,9 @@ public class MonitorUsedDeflationThresholdTest { "-Xlog:safepoint+cleanup=info", "-Xlog:safepoint+stats=debug", // Run the test with inflate_count == 33 since that - // reproduced the bug with JDK13. Anything above the - // in_use_list_ceiling will do the trick. + // reproduced the bug with JDK13. With inflate_count == 33, an + // initial ceiling == 12 and MonitorUsedDeflationThreshold == 10, + // we should hit NoAsyncDeflationProgressMax at least 3 times. "MonitorUsedDeflationThresholdTest", "33"); OutputAnalyzer output_detail = new OutputAnalyzer(pb.start()); @@ -111,6 +117,8 @@ public class MonitorUsedDeflationThresholdTest { throw new RuntimeException("Did not find too_many string in output.\n"); } System.out.println("too_many='" + too_many + "'"); + // Uncomment the following line for dumping test output in passing runs: + // output_detail.reportDiagnosticSummary(); System.out.println("PASSED."); return; diff --git a/test/hotspot/jtreg/runtime/NMT/JcmdWithNMTDisabled.java b/test/hotspot/jtreg/runtime/NMT/JcmdWithNMTDisabled.java index 5567a57b517db59a31bedccd8a6c363cf4589bee..891f82be0bd9f6f7ae0f2c855c01a756c44cecb2 100644 --- a/test/hotspot/jtreg/runtime/NMT/JcmdWithNMTDisabled.java +++ b/test/hotspot/jtreg/runtime/NMT/JcmdWithNMTDisabled.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -69,7 +69,6 @@ public class JcmdWithNMTDisabled { jcmdCommand("summary.diff"); jcmdCommand("detail.diff"); jcmdCommand("scale=GB"); - jcmdCommand("shutdown"); } // Helper method for invoking different jcmd calls, all should fail with the same message saying NMT is not enabled diff --git a/test/hotspot/jtreg/runtime/NMT/SummaryAfterShutdown.java b/test/hotspot/jtreg/runtime/NMT/SummaryAfterShutdown.java deleted file mode 100644 index ab058fe8f0e7a06b5bf35056d7e27b0cb9dc1a6b..0000000000000000000000000000000000000000 --- a/test/hotspot/jtreg/runtime/NMT/SummaryAfterShutdown.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @summary Verify that jcmd correctly reports that NMT is not enabled after a shutdown - * @library /test/lib - * @modules java.base/jdk.internal.misc - * java.management - * @run main/othervm -XX:NativeMemoryTracking=detail SummaryAfterShutdown - */ - -import jdk.test.lib.process.ProcessTools; -import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.JDKToolFinder; - -public class SummaryAfterShutdown { - - public static void main(String args[]) throws Exception { - OutputAnalyzer output; - // Grab my own PID - String pid = Long.toString(ProcessTools.getProcessId()); - ProcessBuilder pb = new ProcessBuilder(); - - // Run 'jcmd <pid> VM.native_memory shutdown' - pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "shutdown"}); - output = new OutputAnalyzer(pb.start()); - - // Verify that jcmd reports that NMT is shutting down - output.shouldContain("Native memory tracking has been turned off"); - - // Run 'jcmd <pid> VM.native_memory summary' - pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary"}); - output = new OutputAnalyzer(pb.start()); - - // Verify that jcmd reports that NMT has been shutdown - output.shouldContain("Native memory tracking has been shutdown"); - } -} diff --git a/test/hotspot/jtreg/runtime/Thread/TestSpinPause.java b/test/hotspot/jtreg/runtime/Thread/TestSpinPause.java new file mode 100644 index 0000000000000000000000000000000000000000..7935d8a1a46141b5947551915bd76e8f76c34752 --- /dev/null +++ b/test/hotspot/jtreg/runtime/Thread/TestSpinPause.java @@ -0,0 +1,87 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test TestSpinPause + * @summary JVM runtime can use SpinPause function for synchronized statements. + * Check different implementations of JVM SpinPause don't crash JVM. + * @bug 8278241 + * @library /test/lib + * + * @requires os.arch=="aarch64" + * + * @run main/othervm TestSpinPause + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=none TestSpinPause + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=nop TestSpinPause + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=isb TestSpinPause + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=yield TestSpinPause + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=nop -XX:OnSpinWaitInstCount=10 TestSpinPause + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=isb -XX:OnSpinWaitInstCount=3 TestSpinPause + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=yield -XX:OnSpinWaitInstCount=3 TestSpinPause + * @run main/othervm -Xint TestSpinPause + * @run main/othervm -Xint -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=none TestSpinPause + * @run main/othervm -Xint -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=nop TestSpinPause + * @run main/othervm -Xint -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=isb TestSpinPause + * @run main/othervm -Xint -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=yield TestSpinPause + * @run main/othervm -Xint -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=nop -XX:OnSpinWaitInstCount=10 TestSpinPause + * @run main/othervm -Xint -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=isb -XX:OnSpinWaitInstCount=3 TestSpinPause + * @run main/othervm -Xint -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=yield -XX:OnSpinWaitInstCount=3 TestSpinPause + * @run main/othervm -Xcomp TestSpinPause + * @run main/othervm -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=none TestSpinPause + * @run main/othervm -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=nop TestSpinPause + * @run main/othervm -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=isb TestSpinPause + * @run main/othervm -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=yield TestSpinPause + * @run main/othervm -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=nop -XX:OnSpinWaitInstCount=10 TestSpinPause + * @run main/othervm -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=isb -XX:OnSpinWaitInstCount=3 TestSpinPause + * @run main/othervm -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=yield -XX:OnSpinWaitInstCount=3 TestSpinPause + */ + +public class TestSpinPause { + private Integer[] valueHolder; + + private TestSpinPause () { + valueHolder = new Integer[] {Integer.valueOf(101)}; + } + + private void getSet() { + final int iterCount = 100; + for (int i = 0; i < iterCount; ++i) { + synchronized (valueHolder) { + Integer v = valueHolder[0]; + valueHolder[0] = Integer.reverse(v); + } + } + } + + public static void main(String[] args) throws Exception { + TestSpinPause test = new TestSpinPause(); + Thread t1 = new Thread(test::getSet); + Thread t2 = new Thread(test::getSet); + t1.start(); + t2.start(); + t1.join(); + t2.join(); + System.out.println("Done: " + test.valueHolder[0]); + } +} + diff --git a/test/hotspot/jtreg/runtime/cds/SharedArchiveFile.java b/test/hotspot/jtreg/runtime/cds/SharedArchiveFile.java index d58bc0e888d0022605afb268311501b1f510ed91..83a1ce07bfcb1e7a669e5436f4ee5544d38c4add 100644 --- a/test/hotspot/jtreg/runtime/cds/SharedArchiveFile.java +++ b/test/hotspot/jtreg/runtime/cds/SharedArchiveFile.java @@ -45,12 +45,6 @@ public class SharedArchiveFile { .setArchiveName("./SharedArchiveFile.jsa"); CDSTestUtils.createArchiveAndCheck(opts); - // -XX:+DumpSharedSpaces should behave the same as -Xshare:dump - opts = (new CDSOptions()) - .addPrefix("-XX:+DumpSharedSpaces", "-Xlog:cds") - .setArchiveName("./SharedArchiveFile.jsa"); - CDSTestUtils.createArchiveAndCheck(opts); - opts = (new CDSOptions()) .setArchiveName("./SharedArchiveFile.jsa"); CDSTestUtils.run(opts) diff --git a/test/hotspot/jtreg/runtime/cds/appcds/DumpClassListWithLF.java b/test/hotspot/jtreg/runtime/cds/appcds/DumpClassListWithLF.java index a0a898989e1aad32d97bff58532b87e70ee6c300..b0851f46e9cbfa1e3940c8e8cfb7bb278a8f2f4b 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/DumpClassListWithLF.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/DumpClassListWithLF.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,7 +33,7 @@ */ public class DumpClassListWithLF extends ClassListFormatBase { - static final String REPLACE_OK = "Replaced class java/lang/invoke/DirectMethodHandle$Holder"; + static final String REPLACE_OK = "Regenerated class java/lang/invoke/DirectMethodHandle$Holder"; public static void main(String[] args) throws Throwable { String appJar = JarBuilder.getOrCreateHelloJar(); diff --git a/test/hotspot/jtreg/runtime/cds/appcds/LambdaWithJavaAgent.java b/test/hotspot/jtreg/runtime/cds/appcds/LambdaWithJavaAgent.java new file mode 100644 index 0000000000000000000000000000000000000000..955c07ac7a6c7ca0c235d3b2ff5083f2fa3b283a --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/LambdaWithJavaAgent.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test + * @bug 8276126 + * @summary Test static dumping with java agent transforming a class loaded + * by the boot class loader. + * @requires vm.cds.write.archived.java.heap + * @requires vm.jvmti + * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes + * @compile test-classes/Hello.java + * @compile test-classes/TransformBootClass.java + * @run driver LambdaWithJavaAgent + */ + +import jdk.test.lib.cds.CDSOptions; +import jdk.test.lib.cds.CDSTestUtils; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.helpers.ClassFileInstaller; + +public class LambdaWithJavaAgent { + + public static String agentClasses[] = { + TransformBootClass.class.getName(), + }; + + public static void main(String[] args) throws Exception { + String mainClass = Hello.class.getName(); + String namePrefix = "lambda-with-java-agent"; + JarBuilder.build(namePrefix, mainClass); + + String appJar = TestCommon.getTestJar(namePrefix + ".jar"); + String classList = namePrefix + ".list"; + String archiveName = namePrefix + ".jsa"; + + String agentJar = + ClassFileInstaller.writeJar("TransformBootClass.jar", + ClassFileInstaller.Manifest.fromSourceFile("test-classes/TransformBootClass.mf"), + agentClasses); + String useJavaAgent = "-javaagent:" + agentJar + "=jdk/internal/math/FDBigInteger"; + + // dump class list + CDSTestUtils.dumpClassList(classList, "-cp", appJar, mainClass); + + // create archive with the class list + CDSOptions opts = (new CDSOptions()) + .addPrefix("-XX:ExtraSharedClassListFile=" + classList, + "-cp", appJar, + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+AllowArchivingWithJavaAgent", + useJavaAgent, + "-Xlog:class+load,cds+class=debug,cds") + .setArchiveName(archiveName); + OutputAnalyzer output = CDSTestUtils.createArchiveAndCheck(opts); + output.shouldContain("CDS heap objects cannot be written because class jdk.internal.math.FDBigInteger maybe modified by ClassFileLoadHook") + .shouldContain("Skipping jdk/internal/math/FDBigInteger: Unsupported location") + .shouldMatch(".class.load.*jdk.internal.math.FDBigInteger.*source.*modules"); + + // run with archive + CDSOptions runOpts = (new CDSOptions()) + .addPrefix("-cp", appJar, "-Xlog:class+load,cds=debug", + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+AllowArchivingWithJavaAgent", + useJavaAgent) + .setArchiveName(archiveName) + .setUseVersion(false) + .addSuffix(mainClass); + output = CDSTestUtils.runWithArchive(runOpts); + TestCommon.checkExecReturn(output, 0, true, + "Hello source: shared objects file"); + } +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/SharedArchiveConsistency.java b/test/hotspot/jtreg/runtime/cds/appcds/SharedArchiveConsistency.java index 57086f343b375d14321bafde983d485c22060011..aee023198f5b0209f2fbc6bf4c4202561ed7d7ec 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/SharedArchiveConsistency.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/SharedArchiveConsistency.java @@ -112,7 +112,8 @@ public class SharedArchiveConsistency { // test, should pass System.out.println("1. Normal, should pass but may fail\n"); - String[] execArgs = {"-Xlog:cds=debug", "-cp", jarFile, "Hello"}; + // disable VerifySharedSpaces, it may be turned on by jtreg args + String[] execArgs = {"-Xlog:cds=debug", "-XX:-VerifySharedSpaces", "-cp", jarFile, "Hello"}; // tests that corrupt contents of the archive need to run with // VerifySharedSpaces enabled to detect inconsistencies String[] verifyExecArgs = {"-Xlog:cds", "-XX:+VerifySharedSpaces", "-cp", jarFile, "Hello"}; @@ -172,7 +173,7 @@ public class SharedArchiveConsistency { System.out.println("\n2d. Corrupt _version, should fail\n"); String modVersion = startNewArchive("modify-version"); copiedJsa = CDSArchiveUtils.copyArchiveFile(orgJsaFile, modVersion); - CDSArchiveUtils.modifyHeaderIntField(copiedJsa, CDSArchiveUtils.offsetVersion(), 0x00000000); + CDSArchiveUtils.modifyHeaderIntField(copiedJsa, CDSArchiveUtils.offsetVersion(), 0x3FFFFFFF); output = shareAuto ? TestCommon.execAuto(execArgs) : TestCommon.execCommon(execArgs); output.shouldContain("The shared archive file has the wrong version"); output.shouldNotContain("Checksum verification failed"); @@ -180,6 +181,17 @@ public class SharedArchiveConsistency { output.shouldContain(HELLO_WORLD); } + System.out.println("\n2e. Corrupt _version, should fail\n"); + String modVersion2 = startNewArchive("modify-version2"); + copiedJsa = CDSArchiveUtils.copyArchiveFile(orgJsaFile, modVersion2); + CDSArchiveUtils.modifyHeaderIntField(copiedJsa, CDSArchiveUtils.offsetVersion(), 0x00000000); + output = shareAuto ? TestCommon.execAuto(execArgs) : TestCommon.execCommon(execArgs); + output.shouldContain("Cannot handle shared archive file version 0. Must be at least 12"); + output.shouldNotContain("Checksum verification failed"); + if (shareAuto) { + output.shouldContain(HELLO_WORLD); + } + // modify content inside regions System.out.println("\n3. Corrupt Content, should fail\n"); for (int i=0; i<num_regions; i++) { diff --git a/test/hotspot/jtreg/runtime/cds/appcds/customLoader/test-classes/HelloUnload.java b/test/hotspot/jtreg/runtime/cds/appcds/customLoader/test-classes/HelloUnload.java index 0a6be28b10d7f9e58c44dd87ab0edc3376279314..5df55982f145141b9b2694740f2e7d4750e16e2c 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/customLoader/test-classes/HelloUnload.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/customLoader/test-classes/HelloUnload.java @@ -30,10 +30,12 @@ import jdk.test.lib.classloader.ClassUnloadCommon; public class HelloUnload { private static String className = "CustomLoadee"; + // Prevent the following class from being GC'ed too soon. + private static Class keptC = null; public static void main(String args[]) throws Exception { - if (args.length != 3) { - throw new RuntimeException("Unexpected number of arguments: expected 3, actual " + args.length); + if (args.length < 3) { + throw new RuntimeException("Unexpected number of arguments: expected at least 3, actual " + args.length); } String path = args[0]; @@ -62,9 +64,20 @@ public class HelloUnload { throw new RuntimeException("args[2] can only be either \"true\" or \"false\", actual " + args[1]); } + // The HelloDynamicCustom.java and PrintSharedArchiveAndExit.java tests + // under appcds/dynamicArchive pass the keep-alive argument for preventing + // the class from being GC'ed prior to dumping of the dynamic CDS archive. + boolean keepAlive = false; + if (args[args.length - 1].equals("keep-alive")) { + keepAlive = true; + } + URLClassLoader urlClassLoader = new URLClassLoader("HelloClassLoader", urls, null); Class c = Class.forName(className, true, urlClassLoader); + if (keepAlive) { + keptC = c; + } System.out.println(c); System.out.println(c.getClassLoader()); Object o = c.newInstance(); diff --git a/test/hotspot/jtreg/runtime/cds/appcds/customLoader/test-classes/OldClassApp.java b/test/hotspot/jtreg/runtime/cds/appcds/customLoader/test-classes/OldClassApp.java index a484018c90289d438fee19573d3dcf2c4d5fb100..51e21e1e82583f1df2aea13e7ff4ad22a58958fc 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/customLoader/test-classes/OldClassApp.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/customLoader/test-classes/OldClassApp.java @@ -25,9 +25,12 @@ import java.io.File; import java.net.URL; import java.net.URLClassLoader; +import java.util.HashMap; import sun.hotspot.WhiteBox; public class OldClassApp { + // Prevent the classes from being GC'ed too soon. + static HashMap<String, Class> clsMap = new HashMap<>(); public static void main(String args[]) throws Exception { String path = args[0]; URL url = new File(path).toURI().toURL(); @@ -44,13 +47,26 @@ public class OldClassApp { throw new RuntimeException("args[1] can only be either \"true\" or \"false\", actual " + args[1]); } + // The OldClassAndInf.java test under appcds/dynamicArchive passes the keep-alive + // argument for preventing the classes from being GC'ed prior to dumping of + // the dynamic CDS archive. + int startIdx = 2; + boolean keepAlive = false; + if (args[2].equals("keep-alive")) { + keepAlive = true; + startIdx = 3; + } + URLClassLoader urlClassLoader = new URLClassLoader("OldClassAppClassLoader", urls, null); - for (int i = 2; i < args.length; i++) { + for (int i = startIdx; i < args.length; i++) { Class c = urlClassLoader.loadClass(args[i]); System.out.println(c); System.out.println(c.getClassLoader()); + if (keepAlive) { + clsMap.put(args[i], c); + } // [1] Check that class is defined by the correct loader if (c.getClassLoader() != urlClassLoader) { diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/ArchiveConsistency.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/ArchiveConsistency.java index de723e6a13d37a0411b3b3fcd359b45ce0f9c36c..33bfc2ef99ebc4e38edeadb2bb229f1ed7a2504d 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/ArchiveConsistency.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/ArchiveConsistency.java @@ -30,7 +30,8 @@ * @build Hello sun.hotspot.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar hello.jar Hello * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ArchiveConsistency + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ArchiveConsistency on + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ArchiveConsistency auto */ import java.io.File; @@ -40,8 +41,15 @@ import jdk.test.lib.cds.CDSTestUtils; import jdk.test.lib.helpers.ClassFileInstaller; public class ArchiveConsistency extends DynamicArchiveTestBase { + private static final String HELLO_WORLD = "Hello World"; + private static boolean isAuto; public static void main(String[] args) throws Exception { + if (args.length != 1 || (!args[0].equals("on") && !args[0].equals("auto"))) { + throw new RuntimeException("Must have one arg either of \"on\" or \"auto\""); + } + isAuto = args[0].equals("auto"); + setAutoMode(isAuto); runTest(ArchiveConsistency::testCustomBase); } @@ -53,31 +61,39 @@ public class ArchiveConsistency extends DynamicArchiveTestBase { doTest(baseArchiveName, topArchiveName); } + static boolean VERIFY_CRC = false; + static void runTwo(String base, String top, - String jarName, String mainClassName, int exitValue, + String jarName, String mainClassName, int expectedExitValue, String ... checkMessages) throws Exception { CDSTestUtils.Result result = run2(base, top, "-Xlog:cds", "-Xlog:cds+dynamic=debug", - "-XX:+VerifySharedSpaces", + VERIFY_CRC ? "-XX:+VerifySharedSpaces" : "-XX:-VerifySharedSpaces", "-cp", jarName, mainClassName); - if (exitValue == 0) { + if (expectedExitValue == 0) { result.assertNormalExit( output -> { for (String s : checkMessages) { output.shouldContain(s); } + output.shouldContain(HELLO_WORLD); }); } else { result.assertAbnormalExit( output -> { for (String s : checkMessages) { output.shouldContain(s); } + output.shouldContain("Unable to use shared archive"); }); } } + private static void startTest(String str) { + System.out.println("\n" + str); + } + private static void doTest(String baseArchiveName, String topArchiveName) throws Exception { String appJar = ClassFileInstaller.getJarPath("hello.jar"); String mainClass = "Hello"; @@ -94,42 +110,36 @@ public class ArchiveConsistency extends DynamicArchiveTestBase { throw new IOException(jsa + " does not exist!"); } - // 1. Modify the CRC values in the header of the top archive. - System.out.println("\n1. Modify the CRC values in the header of the top archive"); + startTest("1. Modify the CRC values in the header of the top archive"); String modTop = getNewArchiveName("modTopRegionsCrc"); File copiedJsa = CDSArchiveUtils.copyArchiveFile(jsa, modTop); CDSArchiveUtils.modifyAllRegionsCrc(copiedJsa); + VERIFY_CRC = true; runTwo(baseArchiveName, modTop, - appJar, mainClass, 1, - new String[] {"Header checksum verification failed", - "Unable to use shared archive"}); + appJar, mainClass, isAuto ? 0 : 1, + "Header checksum verification failed"); + VERIFY_CRC = false; - // 2. Make header size larger than the archive size - System.out.println("\n2. Make header size larger than the archive size"); + startTest("2. Make header size larger than the archive size"); String largerHeaderSize = getNewArchiveName("largerHeaderSize"); copiedJsa = CDSArchiveUtils.copyArchiveFile(jsa, largerHeaderSize); CDSArchiveUtils.modifyHeaderIntField(copiedJsa, CDSArchiveUtils.offsetHeaderSize(), (int)copiedJsa.length() + 1024); runTwo(baseArchiveName, largerHeaderSize, - appJar, mainClass, 1, - new String[] {"_header_size should be equal to _base_archive_name_offset plus _base_archive_name_size", - "Unable to use shared archive"}); + appJar, mainClass, isAuto ? 0 : 1, + "Archive file header larger than archive file"); - // 3. Make base archive path offset beyond of header size - System.out.println("\n3. Make base archive path offset beyond of header size."); + startTest("3. Make base archive name offset beyond of header size."); String wrongBaseArchiveNameOffset = getNewArchiveName("wrongBaseArchiveNameOffset"); copiedJsa = CDSArchiveUtils.copyArchiveFile(jsa, wrongBaseArchiveNameOffset); int fileHeaderSize = (int)CDSArchiveUtils.fileHeaderSize(copiedJsa); int baseArchiveNameOffset = CDSArchiveUtils.baseArchiveNameOffset(copiedJsa); CDSArchiveUtils.modifyHeaderIntField(copiedJsa, CDSArchiveUtils.offsetBaseArchiveNameOffset(), baseArchiveNameOffset + 1024); runTwo(baseArchiveName, wrongBaseArchiveNameOffset, - appJar, mainClass, 1, - new String[] {"_header_size should be equal to _base_archive_name_offset plus _base_archive_name_size", - "The shared archive file has an incorrect header size", - "Unable to use shared archive"}); + appJar, mainClass, isAuto ? 0 : 1, + "Invalid base_archive_name offset/size (out of range)"); - // 4. Make base archive path offset points to middle of name size - System.out.println("\n4. Make base archive path offset points to middle of name size"); + startTest("4. Make base archive name offset points to middle of the base archive name"); String wrongBaseNameOffset = getNewArchiveName("wrongBaseNameOffset"); copiedJsa = CDSArchiveUtils.copyArchiveFile(jsa, wrongBaseNameOffset); int baseArchiveNameSize = CDSArchiveUtils.baseArchiveNameSize(copiedJsa); @@ -137,13 +147,10 @@ public class ArchiveConsistency extends DynamicArchiveTestBase { CDSArchiveUtils.modifyHeaderIntField(copiedJsa, baseArchiveNameOffset, baseArchiveNameOffset + baseArchiveNameSize/2); runTwo(baseArchiveName, wrongBaseNameOffset, - appJar, mainClass, 1, - new String[] {"An error has occurred while processing the shared archive file.", - "Header checksum verification failed", - "Unable to use shared archive"}); + appJar, mainClass, isAuto ? 0 : 1, + "Base archive name is damaged"); - // 5. Make base archive name not terminated with '\0' - System.out.println("\n5. Make base archive name not terminated with '\0'"); + startTest("5. Make base archive name not terminated with '\0'"); String wrongBaseName = getNewArchiveName("wrongBaseName"); copiedJsa = CDSArchiveUtils.copyArchiveFile(jsa, wrongBaseName); baseArchiveNameOffset = CDSArchiveUtils.baseArchiveNameOffset(copiedJsa); @@ -152,12 +159,10 @@ public class ArchiveConsistency extends DynamicArchiveTestBase { CDSArchiveUtils.writeData(copiedJsa, offset, new byte[] {(byte)'X'}); runTwo(baseArchiveName, wrongBaseName, - appJar, mainClass, 1, - new String[] {"Base archive name is damaged", - "Header checksum verification failed"}); + appJar, mainClass, isAuto ? 0 : 1, + "Base archive name is damaged"); - // 6. Modify base archive name to a file that doesn't exist. - System.out.println("\n6. Modify base archive name to a file that doesn't exist"); + startTest("6. Modify base archive name to a file that doesn't exist"); String wrongBaseName2 = getNewArchiveName("wrongBaseName2"); copiedJsa = CDSArchiveUtils.copyArchiveFile(jsa, wrongBaseName2); baseArchiveNameOffset = CDSArchiveUtils.baseArchiveNameOffset(copiedJsa); @@ -170,8 +175,32 @@ public class ArchiveConsistency extends DynamicArchiveTestBase { (new File(badName)).delete(); runTwo(baseArchiveName, wrongBaseName2, - appJar, mainClass, 1, - new String[] {"Base archive " + badName + " does not exist", - "Header checksum verification failed"}); + appJar, mainClass, isAuto ? 0 : 1, + "Base archive " + badName + " does not exist"); + + // Following three tests: + // -XX:SharedArchiveFile=non-exist-base.jsa:top.jsa + // -XX:SharedArchiveFile=base.jsa:non-exist-top.jsa + // -XX:SharedArchiveFile=non-exist-base.jsa:non-exist-top.jsa + startTest("7. Non-exist base archive"); + String nonExistBase = "non-exist-base.jsa"; + File nonExistBaseFile = new File(nonExistBase); + nonExistBaseFile.delete(); + runTwo(nonExistBase, topArchiveName, + appJar, mainClass, isAuto ? 0 : 1, + "Specified shared archive not found (" + nonExistBase + ")"); + + startTest("8. Non-exist top archive"); + String nonExistTop = "non-exist-top.jsa"; + File nonExistTopFile = new File(nonExistTop); + nonExistTopFile.delete(); + runTwo(baseArchiveName, nonExistTop, + appJar, mainClass, isAuto ? 0 : 1, + "Specified shared archive not found (" + nonExistTop + ")"); + + startTest("9. nost-exist-base and non-exist-top"); + runTwo(nonExistBase, nonExistTop, + appJar, mainClass, isAuto ? 0 : 1, + "Specified shared archive not found (" + nonExistBase + ")"); } } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicArchiveTestBase.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicArchiveTestBase.java index b61894c1b4bad2a422c67d38f6220b446e467fe8..050ccef88e258abfe9b2e4f6a4692c8439cd221b 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicArchiveTestBase.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicArchiveTestBase.java @@ -36,6 +36,7 @@ import sun.hotspot.WhiteBox; */ class DynamicArchiveTestBase { private static boolean executedIn_run = false; + private static boolean autoMode = false; // -Xshare:auto private static final WhiteBox WB = WhiteBox.getWhiteBox(); @@ -47,6 +48,7 @@ class DynamicArchiveTestBase { public void run(String args[]) throws Exception; } + public static void setAutoMode(boolean val) { autoMode = val; } /* * Tests for dynamic archives should be written using this pattern: @@ -183,7 +185,7 @@ class DynamicArchiveTestBase { (topArchiveName == null) ? baseArchiveName : baseArchiveName + File.pathSeparator + topArchiveName; String[] cmdLine = TestCommon.concat( - "-Xshare:on", + autoMode ? "-Xshare:auto" : "-Xshare:on", "-XX:SharedArchiveFile=" + archiveFiles); cmdLine = TestCommon.concat(cmdLine, cmdLineSuffix); return execProcess("exec", null, cmdLine); @@ -202,7 +204,7 @@ class DynamicArchiveTestBase { (topArchiveName == null) ? baseArchiveName : baseArchiveName + File.pathSeparator + topArchiveName; String[] cmdLine = TestCommon.concat( - "-Xshare:on", + autoMode ? "-Xshare:auto" : "-Xshare:on", "-XX:SharedArchiveFile=" + archiveFiles); cmdLine = TestCommon.concat(cmdLine, cmdLineSuffix); return execProcess("exec", jarDir, cmdLine); @@ -278,10 +280,10 @@ class DynamicArchiveTestBase { } /** - * Return true if the UseSharedSpaces flag has been disabled. + * Return true if sharing has been disabled. * By default, the VM will be started with -Xshare:auto. - * The UseSharedSpaces flag will be disabled by the VM if there's some - * problem in using the default CDS archive. It could happen under some + * Sharing will be disabled by the VM if there's some problem + * in using the default CDS archive. It could happen under some * situations such as follows: * - the default CDS archive wasn't generated during build time because * the JDK was built via cross-compilation on a different platform; @@ -292,6 +294,6 @@ class DynamicArchiveTestBase { * enabled when the default CDS archive was built. */ public static boolean isUseSharedSpacesDisabled() { - return (WB.getBooleanVMFlag("UseSharedSpaces") == false); + return !WB.isSharingEnabled(); } } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/HelloDynamicCustom.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/HelloDynamicCustom.java index 2c2c745027cd5c2993e6549cacc5bcb53be075e1..097162a17c14697645662085f999a3d03e17d9b9 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/HelloDynamicCustom.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/HelloDynamicCustom.java @@ -64,7 +64,7 @@ public class HelloDynamicCustom extends DynamicArchiveTestBase { "-Xlog:cds", "-Xlog:cds+dynamic=debug", "-cp", appJar, - mainAppClass, customJarPath, "false", "false") + mainAppClass, customJarPath, "false", "false", "keep-alive") .assertNormalExit(output -> { output.shouldContain("Written dynamic archive 0x") .shouldNotContain("klasses.*=.*CustomLoadee") diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/LambdaCustomLoader.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/LambdaCustomLoader.java index dc2c9f144d77379f1157fa38d6801a8191196ca1..df3122056e2299f48cfa98f2dfc1f9abb1510dec 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/LambdaCustomLoader.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/LambdaCustomLoader.java @@ -49,7 +49,7 @@ public class LambdaCustomLoader extends DynamicArchiveTestBase { // 1. Host class loaded by a custom loader is initialized during dump time. dump(topArchiveName, "-Xlog:class+load,cds=debug,cds+dynamic", - "-cp", appJar, mainClass, appJar, "init") + "-cp", appJar, mainClass, appJar, "init", "keep-alive") .assertNormalExit(output -> { output.shouldMatch("Skipping.LambHello[$][$]Lambda[$].*0x.*:.Hidden.class") .shouldHaveExitValue(0); @@ -67,7 +67,7 @@ public class LambdaCustomLoader extends DynamicArchiveTestBase { // 2. Host class loaded by a custom loader is NOT initialized during dump time. dump(topArchiveName, "-Xlog:class+load,cds=debug,cds+dynamic", - "-cp", appJar, mainClass, appJar) + "-cp", appJar, mainClass, appJar, "keep-alive") .assertNormalExit(output -> { output.shouldHaveExitValue(0); }); diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/OldClassAndInf.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/OldClassAndInf.java index 44b430eef6ab12e63f206541e57992e7035b883d..4508eefd82924e1c7adeb918e7600878ef775e55 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/OldClassAndInf.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/OldClassAndInf.java @@ -80,7 +80,7 @@ public class OldClassAndInf extends DynamicArchiveTestBase { "-Xlog:cds", "-Xlog:cds+dynamic=debug", "-cp", appJar, - mainAppClass, loadeesJar, inArchive), + mainAppClass, loadeesJar, inArchive, "keep-alive"), loadees)) .assertNormalExit(output -> { output.shouldContain("Written dynamic archive 0x") diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/PrintSharedArchiveAndExit.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/PrintSharedArchiveAndExit.java index 342aceff9372b9afa3357d8251613262e8b9f7fc..9ceb51c74b602db1aa3452e64ba147042b5f4c73 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/PrintSharedArchiveAndExit.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/PrintSharedArchiveAndExit.java @@ -64,7 +64,7 @@ public class PrintSharedArchiveAndExit extends DynamicArchiveTestBase { "-Xlog:cds", "-Xlog:cds+dynamic=debug", "-cp", appJar, - mainAppClass, customJarPath, "false", "false") + mainAppClass, customJarPath, "false", "false", "keep-alive") .assertNormalExit(output -> { output.shouldContain("Written dynamic archive 0x") .shouldNotContain("klasses.*=.*CustomLoadee") diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/RegularHiddenClass.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/RegularHiddenClass.java index 3729813e8fac011c17976bf5487d4954f2e57947..17c496bc14d6f6ef46cd89aee4de93df24b61d99 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/RegularHiddenClass.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/RegularHiddenClass.java @@ -54,7 +54,7 @@ public class RegularHiddenClass extends DynamicArchiveTestBase { dump(topArchiveName, "-Xlog:class+load=debug,cds+dynamic,cds=debug", - "-cp", appJar, mainClass) + "-cp", appJar, mainClass, "keep-alive") .assertNormalExit(output -> { output.shouldMatch("cds.*Skipping.TestClass.0x.*Hidden.class") .shouldNotMatch("cds.dynamic.*Archiving.hidden.TestClass.*") diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/CustomLoaderApp.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/CustomLoaderApp.java index ebc9350c57e8c3764bac3e245fec44ee48c6957f..37dcdbfdf1e31d41ccf55ce054dcf60148f871f9 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/CustomLoaderApp.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/CustomLoaderApp.java @@ -28,6 +28,8 @@ import java.net.URLClassLoader; public class CustomLoaderApp { private static String className = "LambHello"; + // Prevent the class from being GC'ed too soon. + private static Class keptC = null; public static void main(String args[]) throws Exception { String path = args[0]; @@ -37,13 +39,25 @@ public class CustomLoaderApp { System.out.println(url); boolean init = false; - if (args.length ==2 && args[1].equals("init")) { + if (args.length >= 2 && args[1].equals("init")) { init = true; } + // The dynamicArchive/LambdaCustomLoader.java test passes the keep-alive + // argument for preventing the class from being GC'ed prior to dumping of + // the dynamic CDS archive. + boolean keepAlive = false; + if (args[args.length - 1].equals("keep-alive")) { + keepAlive = true; + } + URLClassLoader urlClassLoader = new URLClassLoader("HelloClassLoader", urls, null); Class c = Class.forName(className, init, urlClassLoader); + if (keepAlive) { + keptC = c; + } + System.out.println(c); System.out.println(c.getClassLoader()); if (c.getClassLoader() != urlClassLoader) { diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jcmd/JCmdTestDumpBase.java b/test/hotspot/jtreg/runtime/cds/appcds/jcmd/JCmdTestDumpBase.java index 75103a50ed491a12c3b049491d3eb3597511d3a7..5e56d3a96e8d983fee61acda6b75603dc204fc7b 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/jcmd/JCmdTestDumpBase.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/jcmd/JCmdTestDumpBase.java @@ -96,7 +96,7 @@ public abstract class JCmdTestDumpBase { } private static void checkCDSEnabled() throws Exception { - boolean cdsEnabled = WhiteBox.getWhiteBox().getBooleanVMFlag("UseSharedSpaces"); + boolean cdsEnabled = WhiteBox.getWhiteBox().isSharingEnabled(); if (!cdsEnabled) { throw new SkippedException("CDS is not available for this JDK."); } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jcmd/JCmdTestDynamicDump.java b/test/hotspot/jtreg/runtime/cds/appcds/jcmd/JCmdTestDynamicDump.java index febc70aea0e6be81298522a7a57096cf6645a20e..72cb5c24d9a553b3dcd8b3906a1a501a89337800 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/jcmd/JCmdTestDynamicDump.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/jcmd/JCmdTestDynamicDump.java @@ -81,20 +81,13 @@ public class JCmdTestDynamicDump extends JCmdTestDumpBase { test(null, pid, noBoot, EXPECT_PASS, DYNAMIC_MESSAGES); app.stopApp(); - // Test dynamic dump with flags -XX:+RecordDynamicDumpInfo -XX:-DynamicDumpSharedSpaces. - print2ln(test_count++ + " Test dynamic dump with flags -XX:+RecordDynamicDumpInfo -XX:-DynamicDumpSharedSpaces."); - app = createLingeredApp("-cp", allJars, "-XX:+RecordDynamicDumpInfo", "-XX:-DynamicDumpSharedSpaces"); + // Test dynamic dump with flag -XX:+RecordDynamicDumpInfo + print2ln(test_count++ + " Test dynamic dump with flag -XX:+RecordDynamicDumpInfo."); + app = createLingeredApp("-cp", allJars, "-XX:+RecordDynamicDumpInfo"); pid = app.getPid(); test(null, pid, noBoot, EXPECT_PASS, DYNAMIC_MESSAGES); app.stopApp(); - // Test dynamic dump with flags -XX:-DynamicDumpSharedSpaces -XX:+RecordDynamicDumpInfo. - print2ln(test_count++ + " Test dynamic dump with flags -XX:-DynamicDumpSharedSpaces -XX:+RecordDynamicDumpInfo."); - app = createLingeredApp("-cp", allJars, "-XX:-DynamicDumpSharedSpaces", "-XX:+RecordDynamicDumpInfo"); - pid = app.getPid(); - test(null, pid, noBoot, EXPECT_PASS, DYNAMIC_MESSAGES); - app.stopApp(); - // Test dynamic with -Xbootclasspath/a:boot.jar print2ln(test_count++ + " Test dynamic with -Xbootclasspath/a:boot.jar"); app = createLingeredApp("-cp", testJar, "-Xbootclasspath/a:" + bootJar, "-XX:+RecordDynamicDumpInfo"); diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jcmd/JCmdTestStaticDump.java b/test/hotspot/jtreg/runtime/cds/appcds/jcmd/JCmdTestStaticDump.java index 2ac55b824a9f48d21c47f8668c6f47b44c214fb1..d232f936a0cf9a8f0c20d081ab99907dfadb8259 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/jcmd/JCmdTestStaticDump.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/jcmd/JCmdTestStaticDump.java @@ -45,25 +45,19 @@ public class JCmdTestStaticDump extends JCmdTestDumpBase { "LingeredApp source: shared objects file", "Hello source: shared objects file"}; - // Those two flags will not create a successful LingeredApp. + // This flag will not create a successful LingeredApp. private static String[] noDumpFlags = - {"-XX:+DumpSharedSpaces", - "-Xshare:dump"}; + {"-Xshare:dump"}; // Those flags will be excluded in static dumping, // See src/java.base/share/classes/jdk/internal/misc/CDS.java private static String[] excludeFlags = { "-XX:DumpLoadedClassList=AnyFileName.classlist", - // this flag just dump archive, won't run app normally. - // "-XX:+DumpSharedSpaces", - "-XX:+DynamicDumpSharedSpaces", "-XX:+RecordDynamicDumpInfo", "-Xshare:on", "-Xshare:auto", "-XX:SharedClassListFile=non-exist.classlist", "-XX:SharedArchiveFile=non-exist.jsa", - "-XX:ArchiveClassesAtExit=tmp.jsa", - "-XX:+UseSharedSpaces", - "-XX:+RequireSharedSpaces"}; + "-XX:ArchiveClassesAtExit=tmp.jsa"}; // Times to dump cds against same process. private static final int ITERATION_TIMES = 2; diff --git a/test/hotspot/jtreg/runtime/cds/appcds/loaderConstraints/DynamicLoaderConstraintsTest.java b/test/hotspot/jtreg/runtime/cds/appcds/loaderConstraints/DynamicLoaderConstraintsTest.java index 9d194c288a34942acb13afdaf654150ce381b37d..e983b5a7aecea943407b3e69a8ff349cd27f123e 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/loaderConstraints/DynamicLoaderConstraintsTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/loaderConstraints/DynamicLoaderConstraintsTest.java @@ -139,7 +139,7 @@ public class DynamicLoaderConstraintsTest extends DynamicArchiveTestBase { "java.base,jdk.httpserver", "--add-exports", "java.base/jdk.internal.misc=ALL-UNNAMED", - "-Xlog:class+load,class+loader+constraints", + "-Xlog:cds=debug,class+load,class+loader+constraints", }; if (useCustomLoader) { diff --git a/test/hotspot/jtreg/runtime/cds/appcds/test-classes/TransformBootClass.java b/test/hotspot/jtreg/runtime/cds/appcds/test-classes/TransformBootClass.java new file mode 100644 index 0000000000000000000000000000000000000000..e13c768cc99dfd246130fabf3149cdc6f3c76982 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/test-classes/TransformBootClass.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import java.lang.instrument.ClassFileTransformer; +import java.lang.instrument.Instrumentation; +import java.lang.instrument.IllegalClassFormatException; +import java.security.ProtectionDomain; + +public class TransformBootClass implements ClassFileTransformer { + + static String targetClass = null; + + public byte[] transform(ClassLoader loader, String name, Class<?> classBeingRedefined, + ProtectionDomain pd, byte[] buffer) throws IllegalClassFormatException { + + if (name.equals(targetClass)) { + System.out.println("Transforming class " + name); + return buffer; + } + return null; + } + + private static Instrumentation savedInstrumentation; + + public static void premain(String agentArguments, Instrumentation instrumentation) { + System.out.println("TransformBootClass.premain() is called"); + instrumentation.addTransformer(new TransformBootClass(), /*canRetransform=*/true); + savedInstrumentation = instrumentation; + if (agentArguments != null) { + targetClass = agentArguments; + } + } + + public static Instrumentation getInstrumentation() { + return savedInstrumentation; + } + + public static void agentmain(String args, Instrumentation inst) throws Exception { + premain(args, inst); + } +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/test-classes/TransformBootClass.mf b/test/hotspot/jtreg/runtime/cds/appcds/test-classes/TransformBootClass.mf new file mode 100644 index 0000000000000000000000000000000000000000..e9d472b02ba3f7b7d5451d0f65c20e02c64729cb --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/test-classes/TransformBootClass.mf @@ -0,0 +1,5 @@ +Manifest-Version: 1.0 +Premain-Class: TransformBootClass +Agent-Class: TransformBootClass +Can-Retransform-Classes: true +Can-Redefine-Classes: true diff --git a/test/hotspot/jtreg/runtime/classFileParserBug/TrailingSlashTest.java b/test/hotspot/jtreg/runtime/classFileParserBug/TrailingSlashTest.java new file mode 100644 index 0000000000000000000000000000000000000000..422b7357d2e6dadd5632ff1c2e7a320edeffbdf5 --- /dev/null +++ b/test/hotspot/jtreg/runtime/classFileParserBug/TrailingSlashTest.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8276241 + * @summary Throw ClassFormatError exception for an old class file whose name ends in a '/'. + * @run main/othervm -Xverify:remote TrailingSlashTest + */ + +public class TrailingSlashTest extends ClassLoader { + + @Override + public Class findClass(String fileName) throws ClassNotFoundException { + return defineClass(null, oldSlashClass, 0, oldSlashClass.length); + } + + public static void main(String args[]) throws Throwable { + try { + TrailingSlashTest cl = new TrailingSlashTest(); + cl.findClass("oldSlashClass"); + throw new RuntimeException("Expected exception not thrown"); + } catch (ClassFormatError e) { + if (!e.getMessage().contains("Illegal class name")) { + throw new RuntimeException("Wrong ClassFormatError exception: " + e.getMessage()); + } + } + } + + + // This byte array comprises the compiled bytes of the following class. Note that the class's + // name ends in a '/' and has a class file version of 45.3. + /* + package has; + public class slashe/ { } + */ + public static byte[] oldSlashClass = { + (byte) 0xca, (byte) 0xfe, (byte) 0xba, (byte) 0xbe, (byte) 0x0, (byte) 0x3, (byte) 0x0, (byte) 0x2d, + (byte) 0x0, (byte) 0xd, (byte) 0xa, (byte) 0x0, (byte) 0x2, (byte) 0x0, (byte) 0x3, (byte) 0x7, + (byte) 0x0, (byte) 0x4, (byte) 0xc, (byte) 0x0, (byte) 0x5, (byte) 0x0, (byte) 0x6, (byte) 0x1, + (byte) 0x0, (byte) 0x10, (byte) 0x6a, (byte) 0x61, (byte) 0x76, (byte) 0x61, (byte) 0x2f, (byte) 0x6c, + (byte) 0x61, (byte) 0x6e, (byte) 0x67, (byte) 0x2f, (byte) 0x4f, (byte) 0x62, (byte) 0x6a, (byte) 0x65, + (byte) 0x63, (byte) 0x74, (byte) 0x1, (byte) 0x0, (byte) 0x6, (byte) 0x3c, (byte) 0x69, (byte) 0x6e, + (byte) 0x69, (byte) 0x74, (byte) 0x3e, (byte) 0x1, (byte) 0x0, (byte) 0x3, (byte) 0x28, (byte) 0x29, + (byte) 0x56, (byte) 0x7, (byte) 0x0, (byte) 0x8, (byte) 0x1, (byte) 0x0, (byte) 0xb, (byte) 0x68, + (byte) 0x61, (byte) 0x73, (byte) 0x2f, (byte) 0x73, (byte) 0x6c, (byte) 0x61, (byte) 0x73, (byte) 0x68, + (byte) 0x65, (byte) 0x2f, (byte) 0x1, (byte) 0x0, (byte) 0x4, (byte) 0x43, (byte) 0x6f, (byte) 0x64, + (byte) 0x65, (byte) 0x1, (byte) 0x0, (byte) 0xf, (byte) 0x4c, (byte) 0x69, (byte) 0x6e, (byte) 0x65, + (byte) 0x4e, (byte) 0x75, (byte) 0x6d, (byte) 0x62, (byte) 0x65, (byte) 0x72, (byte) 0x54, (byte) 0x61, + (byte) 0x62, (byte) 0x6c, (byte) 0x65, (byte) 0x1, (byte) 0x0, (byte) 0xa, (byte) 0x53, (byte) 0x6f, + (byte) 0x75, (byte) 0x72, (byte) 0x63, (byte) 0x65, (byte) 0x46, (byte) 0x69, (byte) 0x6c, (byte) 0x65, + (byte) 0x1, (byte) 0x0, (byte) 0xc, (byte) 0x73, (byte) 0x6c, (byte) 0x61, (byte) 0x73, (byte) 0x68, + (byte) 0x65, (byte) 0x73, (byte) 0x2e, (byte) 0x6a, (byte) 0x61, (byte) 0x76, (byte) 0x61, (byte) 0x0, + (byte) 0x21, (byte) 0x0, (byte) 0x7, (byte) 0x0, (byte) 0x2, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x1, (byte) 0x0, (byte) 0x1, (byte) 0x0, (byte) 0x5, (byte) 0x0, + (byte) 0x6, (byte) 0x0, (byte) 0x1, (byte) 0x0, (byte) 0x9, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x1d, (byte) 0x0, (byte) 0x1, (byte) 0x0, (byte) 0x1, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x5, (byte) 0x2a, (byte) 0xb7, (byte) 0x0, (byte) 0x1, (byte) 0xb1, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x1, (byte) 0x0, (byte) 0xa, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x6, + (byte) 0x0, (byte) 0x1, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x3, (byte) 0x0, (byte) 0x1, + (byte) 0x0, (byte) 0xb, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x2, (byte) 0x0, (byte) 0xc, + }; + +} diff --git a/test/hotspot/jtreg/runtime/modules/LoadUnloadModuleStress.java b/test/hotspot/jtreg/runtime/modules/LoadUnloadModuleStress.java index 2d279856e523134b7f95e8e0b083a3ac560b82f4..0e1565cf6db6e0bb4b94f7863aea07887e3b2862 100644 --- a/test/hotspot/jtreg/runtime/modules/LoadUnloadModuleStress.java +++ b/test/hotspot/jtreg/runtime/modules/LoadUnloadModuleStress.java @@ -30,7 +30,7 @@ * @build sun.hotspot.WhiteBox * @compile/module=java.base java/lang/ModuleHelper.java * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xmx64m -Xmx64m LoadUnloadModuleStress 15000 + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xms64m -Xmx64m LoadUnloadModuleStress 15000 */ import java.lang.ref.WeakReference; diff --git a/test/hotspot/jtreg/serviceability/sa/LingeredAppWithLock.java b/test/hotspot/jtreg/serviceability/sa/LingeredAppWithLock.java index 9acf9d3bbb90c5c2e9f99db42300a7380a445417..4140a3e3381047ec954c970a25742acb8655c586 100644 --- a/test/hotspot/jtreg/serviceability/sa/LingeredAppWithLock.java +++ b/test/hotspot/jtreg/serviceability/sa/LingeredAppWithLock.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,6 +47,19 @@ public class LingeredAppWithLock extends LingeredApp { objectLock.start(); primitiveLock.start(); + // Wait until all threads have reached their blocked or timed wait state + while ((classLock1.getState() != Thread.State.BLOCKED && + classLock1.getState() != Thread.State.TIMED_WAITING) || + (classLock2.getState() != Thread.State.BLOCKED && + classLock2.getState() != Thread.State.TIMED_WAITING) || + (objectLock.getState() != Thread.State.TIMED_WAITING) || + (primitiveLock.getState() != Thread.State.TIMED_WAITING)) { + try { + Thread.sleep(100); + } catch (InterruptedException ex) { + } + } + LingeredApp.main(args); } } diff --git a/test/hotspot/jtreg/serviceability/sa/TestJmapCore.java b/test/hotspot/jtreg/serviceability/sa/TestJmapCore.java index 1c861f8c6015d4f379d89c0256978bc45a8975bb..1acb962c494802a6cb4f7b112957d93615132986 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestJmapCore.java +++ b/test/hotspot/jtreg/serviceability/sa/TestJmapCore.java @@ -26,7 +26,7 @@ * @summary Test verifies that jhsdb jmap could generate heap dump from core when heap is full * @requires vm.hasSA * @library /test/lib - * @run driver/timeout=240 TestJmapCore run heap + * @run driver/timeout=480 TestJmapCore run heap */ import java.io.File; diff --git a/test/hotspot/jtreg/vmTestbase/gc/gctests/LoadUnloadGC/LoadUnloadGC.java b/test/hotspot/jtreg/vmTestbase/gc/gctests/LoadUnloadGC/LoadUnloadGC.java index edd65b81145d6b93171b6d3ac8c221d3e1f87ba3..9b79865462d6fd6d2aef0e092c2613b89f08cb6c 100644 --- a/test/hotspot/jtreg/vmTestbase/gc/gctests/LoadUnloadGC/LoadUnloadGC.java +++ b/test/hotspot/jtreg/vmTestbase/gc/gctests/LoadUnloadGC/LoadUnloadGC.java @@ -28,11 +28,11 @@ * @summary converted from VM Testbase gc/gctests/LoadUnloadGC. * VM Testbase keywords: [gc, stress, stressopt, nonconcurrent, monitoring] * VM Testbase readme: - * In this test a 1000 classes are loaded and unloaded in a loop. + * In this test 1000 classes are loaded and unloaded in a loop. * Class0 gets loaded which results in Class1 getting loaded and so on all - * the way uptill class1000. The classes should be unloaded whenever a + * the way up to class1000. The classes should be unloaded whenever a * garbage collection takes place because their classloader is made unreachable - * at the end of the each loop iteration. The loop is repeated 1000 times. + * at the end of each loop iteration. The loop is repeated 1000 times. * * @requires vm.opt.final.ClassUnloading * @library /vmTestbase @@ -45,6 +45,30 @@ * gc.gctests.LoadUnloadGC.LoadUnloadGC */ +/* + * @test + * @key stress + * + * @summary converted from VM Testbase gc/gctests/LoadUnloadGC. + * VM Testbase keywords: [gc, stress, stressopt, nonconcurrent, monitoring] + * VM Testbase readme: + * In this test 1000 classes are loaded and unloaded in a loop. + * Class0 gets loaded which results in Class1 getting loaded and so on all + * the way up to class1000. The classes should be unloaded whenever a + * garbage collection takes place because their classloader is made unreachable + * at the end of each loop iteration. The loop is repeated 1000 times. + * + * @requires vm.opt.final.ClassUnloading + * @library /vmTestbase + * /test/lib + * @build nsk.share.gc.ClassChain + * @run main/othervm + * -XX:MaxMetaspaceSize=64M + * -XX:MetaspaceSize=64M + * -XX:CompressedClassSpaceSize=32M + * gc.gctests.LoadUnloadGC.LoadUnloadGC + */ + package gc.gctests.LoadUnloadGC; import nsk.share.test.*; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic001a.java index d65ae796b4e0410427e5aa27d76b215e47f7faca..0ccc8460a67388fb6eaa111927f3bf8fbe09a283 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic001a.java @@ -27,6 +27,7 @@ package nsk.jdi.TypeComponent.isSynthetic; import nsk.share.*; import nsk.share.jpda.*; import nsk.share.jdi.*; +import java.util.Objects; public class issynthetic001a { @@ -94,5 +95,10 @@ class ClassToCheck { protected Inter ER0, ER1[]={ER0}, ER2[][]={ER1}; transient Inter ET0, ET1[]={ET0}, ET2[][]={ET1}; volatile Inter EV0, EV1[]={EV0}, EV2[][]={EV1}; + + { + // access enclosing instance so this$0 field is generated + Objects.requireNonNull(ClassToCheck.this); + } } } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetThreadState/thrstat002/thrstat002.cpp b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetThreadState/thrstat002/thrstat002.cpp index 4840af81f3838f6dd59fd89f9d4ff67318320fc8..2b10a77c56caa8c3a616076733f7f9ce0f3b2623 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetThreadState/thrstat002/thrstat002.cpp +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetThreadState/thrstat002/thrstat002.cpp @@ -48,6 +48,107 @@ static jint state[] = { JVMTI_THREAD_STATE_IN_OBJECT_WAIT }; + +#if 1 // support for debug tracing + +#define LOG(...) \ + { \ + printf(__VA_ARGS__); \ + fflush(stdout); \ + } + +#define MAX_FRAME_COUNT_PRINT_STACK_TRACE 200 + +static void +check_jvmti_status(JNIEnv* jni, jvmtiError err, const char* msg) { + if (err != JVMTI_ERROR_NONE) { + LOG("check_jvmti_status: JVMTI function returned error: %s (%d)\n", TranslateError(err), err); + jni->FatalError(msg); + } +} + +static void +deallocate(jvmtiEnv *jvmti, JNIEnv* jni, void* ptr) { + jvmtiError err; + + err = jvmti->Deallocate((unsigned char*)ptr); + check_jvmti_status(jni, err, "deallocate: error in JVMTI Deallocate call"); +} + +static char* +get_method_class_name(jvmtiEnv *jvmti, JNIEnv* jni, jmethodID method) { + jclass klass = NULL; + char* cname = NULL; + char* result = NULL; + jvmtiError err; + + err = jvmti->GetMethodDeclaringClass(method, &klass); + check_jvmti_status(jni, err, "get_method_class_name: error in JVMTI GetMethodDeclaringClass"); + + err = jvmti->GetClassSignature(klass, &cname, NULL); + check_jvmti_status(jni, err, "get_method_class_name: error in JVMTI GetClassSignature"); + + size_t len = strlen(cname) - 2; // get rid of leading 'L' and trailing ';' + + err = jvmti->Allocate((jlong)(len + 1), (unsigned char**)&result); + check_jvmti_status(jni, err, "get_method_class_name: error in JVMTI Allocate"); + + strncpy(result, cname + 1, len); // skip leading 'L' + result[len] = '\0'; + deallocate(jvmti, jni, (void*)cname); + return result; +} + +static void +print_method(jvmtiEnv *jvmti, JNIEnv* jni, jmethodID method, jint depth) { + char* cname = NULL; + char* mname = NULL; + char* msign = NULL; + jvmtiError err; + + cname = get_method_class_name(jvmti, jni, method); + + err = jvmti->GetMethodName(method, &mname, &msign, NULL); + check_jvmti_status(jni, err, "print_method: error in JVMTI GetMethodName"); + + LOG("%2d: %s: %s%s\n", depth, cname, mname, msign); + fflush(0); + deallocate(jvmti, jni, (void*)cname); + deallocate(jvmti, jni, (void*)mname); + deallocate(jvmti, jni, (void*)msign); +} + +static char* +get_thread_name(jvmtiEnv *jvmti, JNIEnv* jni, jthread thread) { + jvmtiThreadInfo thr_info; + jvmtiError err; + + memset(&thr_info, 0, sizeof(thr_info)); + err = jvmti->GetThreadInfo(thread, &thr_info); + check_jvmti_status(jni, err, "get_thread_name: error in JVMTI GetThreadInfo call"); + + return thr_info.name == NULL ? (char*)"<Unnamed thread>" : thr_info.name; +} + +static void +print_stack_trace(jvmtiEnv *jvmti, JNIEnv* jni, jthread thread) { + jvmtiFrameInfo frames[MAX_FRAME_COUNT_PRINT_STACK_TRACE]; + char* tname = get_thread_name(jvmti, jni, thread); + jint count = 0; + jvmtiError err; + + err = jvmti->GetStackTrace(thread, 0, MAX_FRAME_COUNT_PRINT_STACK_TRACE, frames, &count); + check_jvmti_status(jni, err, "print_stack_trace: error in JVMTI GetStackTrace"); + + LOG("JVMTI Stack Trace for thread %s: frame count: %d\n", tname, count); + for (int depth = 0; depth < count; depth++) { + print_method(jvmti, jni, frames[depth].method, depth); + } + deallocate(jvmti, jni, (void*)tname); + LOG("\n"); +} +#endif // support for debug tracing + void printStateFlags(jint flags) { if (flags & JVMTI_THREAD_STATE_SUSPENDED) printf(" JVMTI_THREAD_STATE_SUSPENDED"); @@ -337,6 +438,9 @@ Java_nsk_jvmti_GetThreadState_thrstat002_checkStatus(JNIEnv *env, jclass cls, TranslateState(state[statInd]), state[statInd]); printf(" actual: %s (%d)\n", TranslateState(thrState), thrState); +#ifdef DBG + print_stack_trace(jvmti, env, thr_ptr); +#endif result = STATUS_FAILED; } if (suspState != JVMTI_THREAD_STATE_SUSPENDED) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/ClassFileFinder.java b/test/hotspot/jtreg/vmTestbase/nsk/share/ClassFileFinder.java index 3024ae1d7a5325779e46b05c25ed6deba6faa177..e79430044ca860fdc4222d02458748aa7e80e450 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/ClassFileFinder.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/ClassFileFinder.java @@ -36,7 +36,7 @@ public class ClassFileFinder { * classpath. * * @param name a classname - * @param classPath @{link File.pathSeparator} separated directories + * @param classPath {@link File.pathSeparator} separated directories * @return an absolute path to the found classfile, or null if it cannot be * found */ diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jvmti/agent_tools.cpp b/test/hotspot/jtreg/vmTestbase/nsk/share/jvmti/agent_tools.cpp index 660e2fc54e51bd8188077a4828e9c2bc2cb43d9e..2412bd630401ad267c298eb87f292a52c4d26632 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jvmti/agent_tools.cpp +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jvmti/agent_tools.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -138,34 +138,25 @@ jvmtiEnv* nsk_jvmti_getAgentJVMTIEnv() { return jvmti_env; } -/* ============================================================================= */ -static void set_agent_thread_state(thread_state_t value) { - rawMonitorEnter(jvmti_env, agent_data.monitor); - agent_data.thread_state = value; - rawMonitorNotify(jvmti_env, agent_data.monitor); - rawMonitorExit(jvmti_env, agent_data.monitor); -} - /** Wrapper for user agent thread. */ static void JNICALL agentThreadWrapper(jvmtiEnv* jvmti_env, JNIEnv* agentJNI, void* arg) { jni_env = agentJNI; - /* run user agent proc */ - { - set_agent_thread_state(RUNNABLE); + rawMonitorEnter(jvmti_env, agent_data.monitor); + agent_data.thread_state = RUNNABLE; + rawMonitorNotify(jvmti_env, agent_data.monitor); + rawMonitorExit(jvmti_env, agent_data.monitor); - NSK_TRACE((*agentThreadProc)(jvmti_env, agentJNI, agentThreadArg)); + NSK_TRACE((*agentThreadProc)(jvmti_env, agentJNI, agentThreadArg)); - set_agent_thread_state(TERMINATED); - } + rawMonitorEnter(jvmti_env, agent_data.monitor); + agent_data.thread_state = TERMINATED; + agentJNI->DeleteGlobalRef(agentThread); + agentThread = NULL; + rawMonitorNotify(jvmti_env, agent_data.monitor); + rawMonitorExit(jvmti_env, agent_data.monitor); - /* finalize agent thread */ - { - /* gelete global ref for agent thread */ - agentJNI->DeleteGlobalRef(agentThread); - agentThread = NULL; - } } /** Start wrapper for user agent thread. */ diff --git a/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack018.java b/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack018.java index 48fe41a67faa5b6efc6b702e1e94e9ca9d99258f..b60309cc98f94e44dd88e98ba617399c381c5fc2 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack018.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack018.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,7 @@ * invocations until stack overflow, and then tries to reproduce similar * stack overflows 10 times in each of 10 threads -- each time by trying * to invoke the same recursive method for the given fixed depth - * of invocations (which is 10 times that crucial depth just measured). + * of invocations (which is 100 times that crucial depth just measured). * The test is deemed passed, if VM have not crashed, and * if exception other than due to stack overflow was not * thrown. @@ -103,7 +103,7 @@ public class stack018 extends Thread { // Measure maximal recursion depth until stack overflow: // int maxDepth = 0; - for (depthToTry = 0; ; depthToTry += STEP) + for (depthToTry = 0; ; depthToTry += STEP) { try { invokeRecurse(depthToTry); maxDepth = depthToTry; @@ -117,6 +117,12 @@ public class stack018 extends Thread { throw (ThreadDeath) target; return 2; } + } + + if (maxDepth == 0) { + // The depth STEP was enough to cause StackOverflowError or OutOfMemoryError. + maxDepth = STEP; + } out.println("Maximal recursion depth: " + maxDepth); // diff --git a/test/jaxp/javax/xml/jaxp/unittest/xpath/XPathFactoryDummyImpl.java b/test/jaxp/javax/xml/jaxp/unittest/xpath/XPathFactoryDummyImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..8eb75c225cdb248d370e35db726d9c1c2fc430d9 --- /dev/null +++ b/test/jaxp/javax/xml/jaxp/unittest/xpath/XPathFactoryDummyImpl.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package xpath; + +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathFactory; +import javax.xml.xpath.XPathFactoryConfigurationException; +import javax.xml.xpath.XPathFunctionResolver; +import javax.xml.xpath.XPathVariableResolver; + +/** + * A dummy implementation of the XPathFactory without implementing + * the setProperty/getProperty methods + */ +public class XPathFactoryDummyImpl extends XPathFactory { + + @Override + public boolean isObjectModelSupported(String objectModel) { + // support the default object model, W3C DOM + if (objectModel.equals(XPathFactory.DEFAULT_OBJECT_MODEL_URI)) { + return true; + } + + // no support + return false; + } + + + @Override + public void setFeature(String name, boolean value) throws XPathFactoryConfigurationException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean getFeature(String name) throws XPathFactoryConfigurationException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void setXPathVariableResolver(XPathVariableResolver resolver) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void setXPathFunctionResolver(XPathFunctionResolver resolver) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public XPath newXPath() { + throw new UnsupportedOperationException("Not supported yet."); + } + +} diff --git a/test/jaxp/javax/xml/jaxp/unittest/xpath/XPathTest.java b/test/jaxp/javax/xml/jaxp/unittest/xpath/XPathTest.java index 7f5c45dc12b96327b2316383453c00a3251a1208..82c4cc5b1f3a6ec918d2d0632c67690ac4a0ed72 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/xpath/XPathTest.java +++ b/test/jaxp/javax/xml/jaxp/unittest/xpath/XPathTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,22 +30,77 @@ import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; +import org.testng.Assert; import org.testng.annotations.DataProvider; -import org.testng.annotations.Listeners; import org.testng.annotations.Test; import org.w3c.dom.Document; import org.w3c.dom.Node; /* * @test - * @bug 6376058 - * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest - * @run testng/othervm -DrunSecMngr=true -Djava.security.manager=allow xpath.XPathTest + * @bug 6376058 8276141 + * @build xpath.XPathTest xpath.XPathFactoryDummyImpl * @run testng/othervm xpath.XPathTest * @summary Test XPath functions. See details for each test. */ -@Listeners({jaxp.library.BasePolicy.class}) public class XPathTest { + /* + * DataProvider for testXPathFactory + */ + @DataProvider(name = "xpath") + public Object[][] getXPathFactory() throws Exception { + return new Object[][]{ + {null}, + {"xpath.XPathFactoryDummyImpl"}, + }; + } + + /* + * @bug 8276141 + * Tests the setProperty/getProperty method for the XPathFactory. + */ + @Test(dataProvider = "xpath") + public void testXPathFactory(String factoryName) + throws Exception { + + XPathFactory xpf; + if (factoryName == null) { + xpf = XPathFactory.newInstance(); + } else { + xpf = XPathFactory.newInstance( + XPathFactory.DEFAULT_OBJECT_MODEL_URI, factoryName, null); + } + + // NPE + Assert.assertThrows(NullPointerException.class, + () -> setProperty(xpf, null, "value")); + Assert.assertThrows(NullPointerException.class, + () -> getProperty(xpf, null)); + + if (factoryName == null) { + // default factory impl + Assert.assertThrows(IllegalArgumentException.class, + () -> setProperty(xpf, "unknown", "value")); + Assert.assertThrows(IllegalArgumentException.class, + () -> getProperty(xpf, "unknown")); + } else { + // the DummyImpl does not implement the method + Assert.assertThrows(UnsupportedOperationException.class, + () -> setProperty(xpf, "unknown", "value")); + Assert.assertThrows(UnsupportedOperationException.class, + () -> getProperty(xpf, "unknown")); + } + } + + private void setProperty(XPathFactory xpf, String name, String value) + throws Exception { + xpf.setProperty(name, value); + } + + private void getProperty(XPathFactory xpf, String name) + throws Exception { + xpf.getProperty(name); + } /* @bug 6211561 diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 15355aa04a01676eb1f0ba9d789343f013d6255d..2baa081bcb146f911e05347e2ac3e744dc6294b5 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -516,6 +516,7 @@ java/awt/KeyboardFocusmanager/TypeAhead/ButtonActionKeyTest/ButtonActionKeyTest. java/awt/Window/GetScreenLocation/GetScreenLocationTest.java 8225787 linux-x64 java/awt/Dialog/MakeWindowAlwaysOnTop/MakeWindowAlwaysOnTop.java 8266243 macosx-aarch64 +java/awt/dnd/BadSerializationTest/BadSerializationTest.java 8277817 linux-x64,windows-x64 ############################################################################ @@ -728,16 +729,26 @@ javax/swing/JRootPane/4670486/bug4670486.java 8042381 macosx-all javax/swing/JButton/8151303/PressedIconTest.java 8266246 macosx-aarch64 javax/swing/JMenuItem/ActionListenerCalledTwice/ActionListenerCalledTwiceTest.java 8273573 macosx-all -# Several tests which fail on some hidpi systems +# Several tests which fail on some hidpi systems/macosx12-aarch64 system java/awt/Window/8159168/SetShapeTest.java 8274106 macosx-aarch64 java/awt/image/multiresolution/MultiResolutionJOptionPaneIconTest.java 8274106 macosx-aarch64 javax/swing/JFrame/8175301/ScaledFrameBackgroundTest.java 8274106 macosx-aarch64 +javax/swing/text/html/StyleSheet/bug4936917.java 8277816 macosx-aarch64 +javax/swing/plaf/metal/MetalGradient/8163193/ButtonGradientTest.java 8277816 macosx-aarch64 +javax/swing/JInternalFrame/8160248/JInternalFrameDraggingTest.java 8277816 macosx-aarch64 +javax/swing/JInternalFrame/8069348/bug8069348.java 8277816 macosx-aarch64 +java/awt/Robot/HiDPIScreenCapture/ScreenCaptureTest.java 8277816 macosx-aarch64 +java/awt/Robot/CheckCommonColors/CheckCommonColors.java 8277816 macosx-aarch64 +java/awt/ColorClass/AlphaColorTest.java 8277816 macosx-aarch64 +java/awt/AlphaComposite/WindowAlphaCompositeTest.java 8277816 macosx-aarch64 + # macos12 failure javax/swing/JMenu/4515762/bug4515762.java 8276074 macosx-all sanity/client/SwingSet/src/ToolTipDemoTest.java 8225012 windows-all,macosx-all sanity/client/SwingSet/src/ScrollPaneDemoTest.java 8225013 linux-all sanity/client/SwingSet/src/ButtonDemoScreenshotTest.java 8265770 macosx-all +javax/swing/JTree/4908142/bug4908142.java 8278348 macosx-all ############################################################################ diff --git a/test/jdk/TEST.ROOT b/test/jdk/TEST.ROOT index 03552d41c15eef5725e907fe865c692ab716be5b..608facdf4b787c9dd03fa59e51e5f829041480cd 100644 --- a/test/jdk/TEST.ROOT +++ b/test/jdk/TEST.ROOT @@ -25,9 +25,7 @@ javax/management sun/awt sun/java2d javax/xml/jaxp/testng/validation java/lang/P # Tests that cannot run concurrently exclusiveAccess.dirs=java/math/BigInteger/largeMemory \ java/rmi/Naming java/util/prefs sun/management/jmxremote \ -sun/tools/jstatd sun/tools/jcmd \ -sun/tools/jinfo sun/tools/jmap sun/tools/jps sun/tools/jstack sun/tools/jstat \ -com/sun/tools/attach sun/security/mscapi java/util/Arrays/largeMemory \ +sun/tools/jstatd sun/security/mscapi java/util/Arrays/largeMemory \ java/util/BitSet/stream javax/rmi java/net/httpclient/websocket \ com/sun/net/httpserver/simpleserver diff --git a/test/jdk/TEST.groups b/test/jdk/TEST.groups index 37dafa2e73a27b50b0a57f39510770e7cf398ada..6092f604640b346318f9aeb42706b6c03d9fd7a9 100644 --- a/test/jdk/TEST.groups +++ b/test/jdk/TEST.groups @@ -74,7 +74,9 @@ tier3 = \ :build \ :jdk_vector \ :jdk_rmi \ - :jdk_jfr_tier3 + :jdk_svc \ + -:jdk_svc_sanity \ + -:svc_tools # Everything not in other tiers tier4 = \ @@ -283,9 +285,6 @@ jdk_tools = \ jdk_jfr = \ jdk/jfr -jdk_jfr_tier3 = \ - jdk/jfr/event/metadata/TestLookForUntestedEvents.java - # # Catch-all for other areas with a small number of tests # @@ -386,16 +385,33 @@ jdk_editpad = \ jdk/editpad jdk_desktop = \ - :jdk_awt \ - :jdk_2d \ - :jdk_beans \ + :jdk_desktop_part1 \ + :jdk_desktop_part2 \ + :jdk_desktop_part3 + +jdk_desktop_part1 = \ + :jdk_client_sanity \ :jdk_swing \ + :jdk_2d \ :jdk_sound \ :jdk_imageio \ - :jdk_accessibility \ + :jdk_editpad \ :jfc_demo \ - :jdk_client_sanity \ - :jdk_editpad + :jdk_accessibility \ + :jdk_beans + +jdk_desktop_part2 = \ + :jdk_awt \ + -java/awt/Component \ + -java/awt/Modal \ + -java/awt/datatransfer \ + -java/awt/Window + +jdk_desktop_part3 = \ + java/awt/Component \ + java/awt/Modal \ + java/awt/datatransfer \ + java/awt/Window # SwingSet3 tests. jdk_client_sanity = \ @@ -518,7 +534,23 @@ needs_g1gc = \ jdk/jfr/event/gc/objectcount/TestObjectCountAfterGCEventWithG1FullCollection.java \ jdk/jfr/event/gc/objectcount/TestObjectCountAfterGCEventWithG1ConcurrentMark.java \ jdk/jfr/event/gc/heapsummary/TestHeapSummaryEventG1.java - + +# This set of tests will be executed in an ipv6 only environment + +jdk_ipv6_only = \ + :jdk_net \ + :jdk_nio_networkchannel + +jdk_nio_networkchannel = \ + java/nio/channels/AsyncCloseAndInterrupt.java \ + java/nio/channels/AsynchronousServerSocketChannel \ + java/nio/channels/AsynchronousSocketChannel \ + java/nio/channels/DatagramChannel \ + java/nio/channels/ServerSocketChannel \ + java/nio/channels/SocketChannel \ + java/nio/channels/Selector \ + java/nio/channels/etc + jdk_core_manual = \ :jdk_core_manual_no_input \ :jdk_core_manual_no_input_security \ @@ -567,3 +599,8 @@ jdk_core_manual_requires_human_input = \ java/util/TimeZone/DefaultTimeZoneTest.java +# Test sets for running inside container environment +jdk_containers_extended = \ + :jdk_io \ + :jdk_nio \ + :jdk_svc diff --git a/test/jdk/com/sun/net/httpserver/SANTest.java b/test/jdk/com/sun/net/httpserver/SANTest.java new file mode 100644 index 0000000000000000000000000000000000000000..db0fc0542d6f55758a164343a24faa60e18ac569 --- /dev/null +++ b/test/jdk/com/sun/net/httpserver/SANTest.java @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8278312 + * @library /test/lib /test/jdk/java/net/httpclient /test/jdk/java/net/httpclient/http2/server + * @build jdk.test.lib.net.SimpleSSLContext HttpServerAdapters Http2Handler + * jdk.test.lib.net.IPSupport + * Http2TestExchange + * + * @modules java.net.http/jdk.internal.net.http.common + * java.net.http/jdk.internal.net.http.frame + * java.net.http/jdk.internal.net.http.hpack + * java.logging + * java.base/sun.net.www.http + * java.base/sun.net.www + * java.base/sun.net + * + * @run main/othervm SANTest + * @summary Update SimpleSSLContext keystore to use SANs for localhost IP addresses + */ + +import com.sun.net.httpserver.*; + +import java.util.concurrent.*; +import java.io.*; +import java.net.*; +import java.net.http.*; +import java.nio.charset.StandardCharsets; +import javax.net.ssl.*; +import jdk.test.lib.net.SimpleSSLContext; +import jdk.test.lib.net.URIBuilder; +import jdk.test.lib.net.IPSupport; + +/* + * Will fail if the testkeys file belonging to SimpleSSLContext + * does not have SAN entries for 127.0.0.1 or ::1 + */ +public class SANTest implements HttpServerAdapters { + + static SSLContext ctx; + + static HttpServer getHttpsServer(InetSocketAddress addr, Executor exec, SSLContext ctx) throws Exception { + HttpsServer server = HttpsServer.create(addr, 0); + server.setExecutor(exec); + server.setHttpsConfigurator(new HttpsConfigurator (ctx)); + return server; + } + + static final boolean hasIPv4 = IPSupport.hasIPv4(); + static final boolean hasIPv6 = IPSupport.hasIPv6(); + + static HttpTestServer initServer(boolean h2, InetAddress addr, SSLContext ctx, + String sni, ExecutorService e) throws Exception { + HttpTestServer s = null; + InetSocketAddress ia = new InetSocketAddress (addr, 0); + if ((addr instanceof Inet4Address) && !hasIPv4) + return null; + if ((addr instanceof Inet6Address) && !hasIPv6) + return null; + + if (!h2) { + s = HttpTestServer.of(getHttpsServer(ia, e, ctx)); + HttpTestHandler h = new HttpTestEchoHandler(); + s.addHandler(h, "/test1"); + s.start(); + return s; + } else { + s = HttpTestServer.of(new Http2TestServer(addr, sni, true, 0, e, + 10, null, ctx, false)); + HttpTestHandler h = new HttpTestEchoHandler(); + s.addHandler(h, "/test1"); + s.start(); + return s; + } + } + + public static void main (String[] args) throws Exception { + // Http/1.1 servers + HttpTestServer h1s1 = null; + HttpTestServer h1s2 = null; + + // Http/2 servers + HttpTestServer h2s1 = null; + HttpTestServer h2s2 = null; + + ExecutorService executor=null; + try { + System.out.print ("SANTest: "); + ctx = new SimpleSSLContext().get(); + executor = Executors.newCachedThreadPool(); + + InetAddress l1 = InetAddress.getByName("::1"); + InetAddress l2 = InetAddress.getByName("127.0.0.1"); + + h1s1 = initServer(false, l1, ctx, "::1", executor); + h1s2 = initServer(false, l2, ctx, "127.0.0.1", executor); + + h2s1 = initServer(true, l1, ctx, "::1", executor); + h2s2 = initServer(true, l2, ctx, "127.0.0.1", executor); + + test("127.0.0.1", h1s2); + test("::1", h1s1); + testNew("127.0.0.1", h2s2, executor); + testNew("::1", h2s1, executor); + System.out.println ("OK"); + } finally { + if (h1s1 != null) + h1s1.stop(); + if (h1s2 != null) + h1s2.stop(); + if (h2s1 != null) + h2s1.stop(); + if (h2s2 != null) + h2s2.stop(); + if (executor != null) + executor.shutdown (); + } + } + + static void test (String host, HttpTestServer server) throws Exception { + if (server == null) + return; + int port = server.getAddress().getPort(); + String body = "Yellow world"; + URL url = URIBuilder.newBuilder() + .scheme("https") + .host(host) + .port(port) + .path("/test1/foo.txt") + .toURL(); + System.out.println("URL = " + url); + HttpURLConnection urlc = (HttpURLConnection) url.openConnection(Proxy.NO_PROXY); + System.out.println("urlc = " + urlc); + if (urlc instanceof HttpsURLConnection) { + HttpsURLConnection urlcs = (HttpsURLConnection) urlc; + urlcs.setSSLSocketFactory (ctx.getSocketFactory()); + } + + urlc.setRequestMethod("POST"); + urlc.setDoOutput(true); + + OutputStream os = urlc.getOutputStream(); + os.write(body.getBytes(StandardCharsets.ISO_8859_1)); + os.close(); + InputStream is = urlc.getInputStream(); + byte[] vv = is.readAllBytes(); + String ff = new String(vv, StandardCharsets.ISO_8859_1); + System.out.println("resp = " + ff); + if (!ff.equals(body)) + throw new RuntimeException(); + is.close(); + } + + static void testNew (String host, HttpTestServer server, Executor exec) throws Exception { + if (server == null) + return; + int port = server.getAddress().getPort(); + String body = "Red and Yellow world"; + URI uri = URIBuilder.newBuilder() + .scheme("https") + .host(host) + .port(port) + .path("/test1/foo.txt") + .build(); + + HttpClient client = HttpClient.newBuilder() + .sslContext(ctx) + .executor(exec) + .build(); + HttpRequest req = HttpRequest.newBuilder(uri) + .version(HttpClient.Version.HTTP_2) + .POST(HttpRequest.BodyPublishers.ofString(body)) + .build(); + + HttpResponse<String> resp = client.send(req, HttpResponse.BodyHandlers.ofString()); + System.out.println("resp = " + resp.body()); + if (!resp.body().equals(body)) + throw new RuntimeException(); + } +} diff --git a/test/jdk/com/sun/net/httpserver/simpleserver/CommandLineNegativeTest.java b/test/jdk/com/sun/net/httpserver/simpleserver/CommandLineNegativeTest.java index a494d5961a31d10f8238139877bca4a2ca8522e9..3a22d54f36d046c07bea4bcb40b71a9f079f726c 100644 --- a/test/jdk/com/sun/net/httpserver/simpleserver/CommandLineNegativeTest.java +++ b/test/jdk/com/sun/net/httpserver/simpleserver/CommandLineNegativeTest.java @@ -23,7 +23,7 @@ /* * @test - * @summary Negative tests for simpleserver command-line tool + * @summary Negative tests for java -m jdk.httpserver command * @library /test/lib * @modules jdk.httpserver * @run testng/othervm CommandLineNegativeTest diff --git a/test/jdk/com/sun/net/httpserver/simpleserver/CommandLinePortNotSpecifiedTest.java b/test/jdk/com/sun/net/httpserver/simpleserver/CommandLinePortNotSpecifiedTest.java index 9e53d1008e4e34453eb020953c699ca011b2137f..ba414a9d0c1ac6f2fb2a8f9f42099ffeebe5a346 100644 --- a/test/jdk/com/sun/net/httpserver/simpleserver/CommandLinePortNotSpecifiedTest.java +++ b/test/jdk/com/sun/net/httpserver/simpleserver/CommandLinePortNotSpecifiedTest.java @@ -24,7 +24,7 @@ /* * @test * @bug 8276848 - * @summary Tests the command-line tool with port not specified + * @summary Tests the java -m jdk.httpserver command with port not specified * @modules jdk.httpserver * @library /test/lib * @run testng/othervm/manual CommandLinePortNotSpecifiedTest @@ -118,7 +118,8 @@ public class CommandLinePortNotSpecifiedTest { -d, --directory - Directory to serve. Default: current directory. -o, --output - Output format. none|info|verbose. Default: info. -p, --port - Port to listen on. Default: 8000. - -h, -?, --help - Print this help message. + -h, -?, --help - Prints this help message and exits. + -version, --version - Prints version information and exits. To stop the server, press Ctrl + C.""".formatted(LOOPBACK_ADDR); // The stdout/stderr output line to wait for when starting the simpleserver diff --git a/test/jdk/com/sun/net/httpserver/simpleserver/CommandLinePositiveTest.java b/test/jdk/com/sun/net/httpserver/simpleserver/CommandLinePositiveTest.java index c17b9e1b9732dbbad6d177799717ef0bfe733542..fce013460c1880358f46d8543c9b4e99f92b79ee 100644 --- a/test/jdk/com/sun/net/httpserver/simpleserver/CommandLinePositiveTest.java +++ b/test/jdk/com/sun/net/httpserver/simpleserver/CommandLinePositiveTest.java @@ -23,7 +23,7 @@ /* * @test - * @summary Positive tests for simpleserver command-line tool + * @summary Positive tests for java -m jdk.httpserver command * @library /test/lib * @modules jdk.httpserver * @run testng/othervm CommandLinePositiveTest @@ -46,6 +46,7 @@ import static java.lang.System.out; public class CommandLinePositiveTest { + static final String JAVA_VERSION = System.getProperty("java.version"); static final Path JAVA_HOME = Path.of(System.getProperty("java.home")); static final String JAVA = getJava(JAVA_HOME); static final Path CWD = Path.of(".").toAbsolutePath().normalize(); @@ -106,7 +107,8 @@ public class CommandLinePositiveTest { static final String USAGE_TEXT = """ Usage: java -m jdk.httpserver [-b bind address] [-p port] [-d directory] - [-o none|info|verbose] [-h to show options]"""; + [-o none|info|verbose] [-h to show options] + [-version to show version information]"""; static final String OPTIONS_TEXT = """ Options: @@ -115,7 +117,8 @@ public class CommandLinePositiveTest { -d, --directory - Directory to serve. Default: current directory. -o, --output - Output format. none|info|verbose. Default: info. -p, --port - Port to listen on. Default: 8000. - -h, -?, --help - Print this help message. + -h, -?, --help - Prints this help message and exits. + -version, --version - Prints version information and exits. To stop the server, press Ctrl + C.""".formatted(LOOPBACK_ADDR); @Test(dataProvider = "helpOptions") @@ -129,6 +132,18 @@ public class CommandLinePositiveTest { .shouldContain(OPTIONS_TEXT); } + @DataProvider + public Object[][] versionOptions() { return new Object[][] {{"-version"}, {"--version"}}; } + + @Test(dataProvider = "versionOptions") + public void testVersion(String opt) throws Throwable { + out.println("\n--- testVersion, opt=\"%s\" ".formatted(opt)); + simpleserver(WaitForLine.VERSION_STARTUP_LINE, + false, // do not explicitly destroy the process + JAVA, "-m", "jdk.httpserver", opt) + .shouldHaveExitValue(0); + } + @DataProvider public Object[][] bindOptions() { return new Object[][] {{"-b"}, {"--bind-address"}}; } @@ -207,11 +222,13 @@ public class CommandLinePositiveTest { static final String REGULAR_STARTUP_LINE1_STRING = "Serving"; static final String REGULAR_STARTUP_LINE2_STRING = "URL http://"; + static final String VERSION_STARTUP_LINE_STRING = "java " + JAVA_VERSION; // The stdout/stderr output line to wait for when starting the simpleserver enum WaitForLine { REGULAR_STARTUP_LINE (REGULAR_STARTUP_LINE2_STRING) , - HELP_STARTUP_LINE (OPTIONS_TEXT.lines().reduce((first, second) -> second).orElseThrow()); + HELP_STARTUP_LINE (OPTIONS_TEXT.lines().reduce((first, second) -> second).orElseThrow()), + VERSION_STARTUP_LINE (VERSION_STARTUP_LINE_STRING); final String value; WaitForLine(String value) { this.value = value; } diff --git a/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/CommandLineNegativeTest.java b/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/CommandLineNegativeTest.java new file mode 100644 index 0000000000000000000000000000000000000000..77671d1e82df6e7734f567c5f54ebad6b5bbb37a --- /dev/null +++ b/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/CommandLineNegativeTest.java @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Negative tests for the jwebserver command-line tool + * @library /test/lib + * @modules jdk.httpserver + * @run testng/othervm CommandLineNegativeTest + */ + +import java.io.IOException; +import java.net.InetAddress; +import java.nio.file.Files; +import java.nio.file.Path; +import jdk.test.lib.Platform; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.util.FileUtils; +import org.testng.SkipException; +import org.testng.annotations.AfterTest; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import static java.lang.System.out; +import static org.testng.Assert.assertFalse; + +public class CommandLineNegativeTest { + + static final Path JAVA_HOME = Path.of(System.getProperty("java.home")); + static final String JWEBSERVER = getJwebserver(JAVA_HOME); + static final Path CWD = Path.of(".").toAbsolutePath().normalize(); + static final Path TEST_DIR = CWD.resolve("CommandLineNegativeTest"); + static final Path TEST_FILE = TEST_DIR.resolve("file.txt"); + static final String LOOPBACK_ADDR = InetAddress.getLoopbackAddress().getHostAddress(); + + @BeforeTest + public void setup() throws IOException { + if (Files.exists(TEST_DIR)) { + FileUtils.deleteFileTreeWithRetry(TEST_DIR); + } + Files.createDirectories(TEST_DIR); + Files.createFile(TEST_FILE); + } + + @DataProvider + public Object[][] unknownOption() { + return new Object[][] { + {"--unknownOption"}, + {"null"} + }; + } + + @Test(dataProvider = "unknownOption") + public void testBadOption(String opt) throws Throwable { + out.println("\n--- testUnknownOption, opt=\"%s\" ".formatted(opt)); + simpleserver(JWEBSERVER, opt) + .shouldNotHaveExitValue(0) + .shouldContain("Error: unknown option: " + opt); + } + + @DataProvider + public Object[][] tooManyOptionArgs() { + return new Object[][] { + {"-b", "localhost"}, + {"-d", "/some/path"}, + {"-o", "none"}, + {"-p", "0"}, + {"--bind-address", "localhost"}, + {"--directory", "/some/path"}, + {"--output", "none"}, + {"--port", "0"} + // doesn't fail for -h option + }; + } + + @Test(dataProvider = "tooManyOptionArgs") + public void testTooManyOptionArgs(String opt, String arg) throws Throwable { + out.println("\n--- testTooManyOptionArgs, opt=\"%s\" ".formatted(opt)); + simpleserver(JWEBSERVER, opt, arg, arg) + .shouldNotHaveExitValue(0) + .shouldContain("Error: unknown option: " + arg); + } + + @DataProvider + public Object[][] noArg() { + return new Object[][] { + {"-b", """ + -b, --bind-address - Address to bind to. Default: %s (loopback). + For all interfaces use "-b 0.0.0.0" or "-b ::".""".formatted(LOOPBACK_ADDR)}, + {"-d", "-d, --directory - Directory to serve. Default: current directory."}, + {"-o", "-o, --output - Output format. none|info|verbose. Default: info."}, + {"-p", "-p, --port - Port to listen on. Default: 8000."}, + {"--bind-address", """ + -b, --bind-address - Address to bind to. Default: %s (loopback). + For all interfaces use "-b 0.0.0.0" or "-b ::".""".formatted(LOOPBACK_ADDR)}, + {"--directory", "-d, --directory - Directory to serve. Default: current directory."}, + {"--output", "-o, --output - Output format. none|info|verbose. Default: info."}, + {"--port", "-p, --port - Port to listen on. Default: 8000."} + // doesn't fail for -h option + }; + } + + @Test(dataProvider = "noArg") + public void testNoArg(String opt, String msg) throws Throwable { + out.println("\n--- testNoArg, opt=\"%s\" ".formatted(opt)); + simpleserver(JWEBSERVER, opt) + .shouldNotHaveExitValue(0) + .shouldContain("Error: no value given for " + opt) + .shouldContain(msg); + } + + @DataProvider + public Object[][] invalidValue() { + return new Object[][] { + {"-b", "[127.0.0.1]"}, + {"-b", "badhost"}, + {"--bind-address", "192.168.1.220..."}, + + {"-o", "bad-output-level"}, + {"--output", "bad-output-level"}, + + {"-p", "+-"}, + {"--port", "+-"} + }; + } + + @Test(dataProvider = "invalidValue") + public void testInvalidValue(String opt, String val) throws Throwable { + out.println("\n--- testInvalidValue, opt=\"%s\" ".formatted(opt)); + simpleserver(JWEBSERVER, opt, val) + .shouldNotHaveExitValue(0) + .shouldContain("Error: invalid value given for " + opt + ": " + val); + } + + @DataProvider + public Object[][] portOptions() { return new Object[][] {{"-p"}, {"--port"}}; } + + @Test(dataProvider = "portOptions") + public void testPortOutOfRange(String opt) throws Throwable { + out.println("\n--- testPortOutOfRange, opt=\"%s\" ".formatted(opt)); + simpleserver(JWEBSERVER, opt, "65536") // range 0 to 65535 + .shouldNotHaveExitValue(0) + .shouldContain("Error: server config failed: " + "port out of range:65536"); + } + + @DataProvider + public Object[][] directoryOptions() { return new Object[][] {{"-d"}, {"--directory"}}; } + + @Test(dataProvider = "directoryOptions") + public void testRootNotAbsolute(String opt) throws Throwable { + out.println("\n--- testRootNotAbsolute, opt=\"%s\" ".formatted(opt)); + var root = Path.of("."); + assertFalse(root.isAbsolute()); + simpleserver(JWEBSERVER, opt, root.toString()) + .shouldNotHaveExitValue(0) + .shouldContain("Error: server config failed: " + "Path is not absolute:"); + } + + @Test(dataProvider = "directoryOptions") + public void testRootNotADirectory(String opt) throws Throwable { + out.println("\n--- testRootNotADirectory, opt=\"%s\" ".formatted(opt)); + var file = TEST_FILE.toString(); + assertFalse(Files.isDirectory(TEST_FILE)); + simpleserver(JWEBSERVER, opt, file) + .shouldNotHaveExitValue(0) + .shouldContain("Error: server config failed: " + "Path is not a directory: " + file); + } + + @Test(dataProvider = "directoryOptions") + public void testRootDoesNotExist(String opt) throws Throwable { + out.println("\n--- testRootDoesNotExist, opt=\"%s\" ".formatted(opt)); + Path root = TEST_DIR.resolve("not/existent/dir"); + assertFalse(Files.exists(root)); + simpleserver(JWEBSERVER, opt, root.toString()) + .shouldNotHaveExitValue(0) + .shouldContain("Error: server config failed: " + "Path does not exist: " + root.toString()); + } + + @Test(dataProvider = "directoryOptions") + public void testRootNotReadable(String opt) throws Throwable { + out.println("\n--- testRootNotReadable, opt=\"%s\" ".formatted(opt)); + if (Platform.isWindows()) { + // Not applicable to Windows. Reason: cannot revoke an owner's read + // access to a directory that was created by that owner + throw new SkipException("cannot run on Windows"); + } + Path root = Files.createDirectories(TEST_DIR.resolve("not/readable/dir")); + try { + root.toFile().setReadable(false, false); + assertFalse(Files.isReadable(root)); + simpleserver(JWEBSERVER, opt, root.toString()) + .shouldNotHaveExitValue(0) + .shouldContain("Error: server config failed: " + "Path is not readable: " + root.toString()); + } finally { + root.toFile().setReadable(true, false); + } + } + + @AfterTest + public void teardown() throws IOException { + if (Files.exists(TEST_DIR)) { + FileUtils.deleteFileTreeWithRetry(TEST_DIR); + } + } + + // --- infra --- + + static String getJwebserver(Path image) { + boolean isWindows = System.getProperty("os.name").startsWith("Windows"); + Path jwebserver = image.resolve("bin").resolve(isWindows ? "jwebserver.exe" : "jwebserver"); + if (Files.notExists(jwebserver)) + throw new RuntimeException(jwebserver + " not found"); + return jwebserver.toAbsolutePath().toString(); + } + + static OutputAnalyzer simpleserver(String... args) throws Throwable { + var pb = new ProcessBuilder(args) + .directory(TEST_DIR.toFile()); + var outputAnalyser = ProcessTools.executeCommand(pb) + .outputTo(System.out) + .errorTo(System.out); + return outputAnalyser; + } +} diff --git a/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/CommandLinePortNotSpecifiedTest.java b/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/CommandLinePortNotSpecifiedTest.java new file mode 100644 index 0000000000000000000000000000000000000000..4d850442b25e4580919f68fa2d356f6a499b5af8 --- /dev/null +++ b/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/CommandLinePortNotSpecifiedTest.java @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8276848 + * @summary Tests the jwebserver tool with port not specified + * @modules jdk.httpserver + * @library /test/lib + * @run testng/othervm/manual CommandLinePortNotSpecifiedTest + */ + +import java.io.IOException; +import java.net.InetAddress; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.concurrent.TimeUnit; +import jdk.test.lib.Platform; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.util.FileUtils; +import org.testng.annotations.AfterTest; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; +import static java.lang.System.out; + +public class CommandLinePortNotSpecifiedTest { + + static final Path JAVA_HOME = Path.of(System.getProperty("java.home")); + static final String JWEBSERVER = getJwebserver(JAVA_HOME); + static final Path CWD = Path.of(".").toAbsolutePath().normalize(); + static final Path TEST_DIR = CWD.resolve("CommandLinePortNotSpecifiedTest"); + static final Path TEST_FILE = TEST_DIR.resolve("file.txt"); + static final String TEST_DIR_STR = TEST_DIR.toString(); + static final String LOOPBACK_ADDR = InetAddress.getLoopbackAddress().getHostAddress(); + + @BeforeTest + public void setup() throws IOException { + if (Files.exists(TEST_DIR)) { + FileUtils.deleteFileTreeWithRetry(TEST_DIR); + } + Files.createDirectories(TEST_DIR); + Files.createFile(TEST_FILE); + } + + static final int SIGTERM = 15; + static final int NORMAL_EXIT_CODE = normalExitCode(); + + static int normalExitCode() { + if (Platform.isWindows()) { + return 1; // expected process destroy exit code + } else { + // signal terminated exit code on Unix is 128 + signal value + return 128 + SIGTERM; + } + } + + /** + * This is a manual test to confirm the command-line tool starts successfully + * in the case where the port is not specified. In this case the server uses + * the default port 8000. The test is manual to avoid a BindException in the + * unlikely but not impossible case that the port is already in use. + */ + @Test + public void testPortNotSpecified() throws Throwable { + out.println("\n--- testPortNotSpecified"); + simpleserver(JWEBSERVER) + .shouldHaveExitValue(NORMAL_EXIT_CODE) + .shouldContain("Binding to loopback by default. For all interfaces use \"-b 0.0.0.0\" or \"-b ::\".") + .shouldContain("Serving " + TEST_DIR_STR + " and subdirectories on " + LOOPBACK_ADDR + " port") + .shouldContain("URL http://" + LOOPBACK_ADDR); + } + + @AfterTest + public void teardown() throws IOException { + if (Files.exists(TEST_DIR)) { + FileUtils.deleteFileTreeWithRetry(TEST_DIR); + } + } + + // --- infra --- + + static String getJwebserver(Path image) { + boolean isWindows = System.getProperty("os.name").startsWith("Windows"); + Path jwebserver = image.resolve("bin").resolve(isWindows ? "jwebserver.exe" : "jwebserver"); + if (Files.notExists(jwebserver)) + throw new RuntimeException(jwebserver + " not found"); + return jwebserver.toAbsolutePath().toString(); + } + + static final String REGULAR_STARTUP_LINE1_STRING = "Serving"; + static final String REGULAR_STARTUP_LINE2_STRING = "URL http://"; + + static final String OPTIONS_TEXT = """ + Options: + -b, --bind-address - Address to bind to. Default: %s (loopback). + For all interfaces use "-b 0.0.0.0" or "-b ::". + -d, --directory - Directory to serve. Default: current directory. + -o, --output - Output format. none|info|verbose. Default: info. + -p, --port - Port to listen on. Default: 8000. + -h, -?, --help - Prints this help message and exits. + -version, --version - Prints version information and exits. + To stop the server, press Ctrl + C.""".formatted(LOOPBACK_ADDR); + + // The stdout/stderr output line to wait for when starting the simpleserver + enum WaitForLine { + REGULAR_STARTUP_LINE (REGULAR_STARTUP_LINE2_STRING) , + HELP_STARTUP_LINE (OPTIONS_TEXT.lines().reduce((first, second) -> second).orElseThrow()); + + final String value; + WaitForLine(String value) { this.value = value; } + } + + static OutputAnalyzer simpleserver(String... args) throws Throwable { + return simpleserver(WaitForLine.REGULAR_STARTUP_LINE, true, args); + } + + static OutputAnalyzer simpleserver(WaitForLine waitForLine, boolean destroy, String... args) throws Throwable { + StringBuffer sb = new StringBuffer(); // stdout & stderr + // start the process and await the waitForLine before returning + var p = ProcessTools.startProcess("simpleserver", + new ProcessBuilder(args).directory(TEST_DIR.toFile()), + line -> sb.append(line + "\n"), + line -> line.startsWith(waitForLine.value), + 30, // suitably high default timeout, not expected to timeout + TimeUnit.SECONDS); + if (destroy) { + p.destroy(); // SIGTERM on Unix + } + int ec = p.waitFor(); + var outputAnalyser = new OutputAnalyzer(sb.toString(), "", ec); + return outputAnalyser; + } +} diff --git a/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/CommandLinePositiveTest.java b/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/CommandLinePositiveTest.java new file mode 100644 index 0000000000000000000000000000000000000000..c3a63371828d11a409e3c7d3d4edfd9a676258b1 --- /dev/null +++ b/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/CommandLinePositiveTest.java @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Positive tests for the jwebserver command-line tool + * @library /test/lib + * @modules jdk.httpserver + * @run testng/othervm CommandLinePositiveTest + */ + +import java.io.IOException; +import java.net.InetAddress; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.concurrent.TimeUnit; +import jdk.test.lib.Platform; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.util.FileUtils; +import org.testng.annotations.AfterTest; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import static java.lang.System.out; + +public class CommandLinePositiveTest { + + static final String JAVA_VERSION = System.getProperty("java.version"); + static final Path JAVA_HOME = Path.of(System.getProperty("java.home")); + static final String JWEBSERVER = getJwebserver(JAVA_HOME); + static final Path CWD = Path.of(".").toAbsolutePath().normalize(); + static final Path TEST_DIR = CWD.resolve("CommandLinePositiveTest"); + static final Path TEST_FILE = TEST_DIR.resolve("file.txt"); + static final String TEST_DIR_STR = TEST_DIR.toString(); + static final String LOOPBACK_ADDR = InetAddress.getLoopbackAddress().getHostAddress(); + + @BeforeTest + public void setup() throws IOException { + if (Files.exists(TEST_DIR)) { + FileUtils.deleteFileTreeWithRetry(TEST_DIR); + } + Files.createDirectories(TEST_DIR); + Files.createFile(TEST_FILE); + } + + static final int SIGTERM = 15; + static final int NORMAL_EXIT_CODE = normalExitCode(); + + static int normalExitCode() { + if (Platform.isWindows()) { + return 1; // expected process destroy exit code + } else { + // signal terminated exit code on Unix is 128 + signal value + return 128 + SIGTERM; + } + } + + @DataProvider + public Object[][] directoryOptions() { return new Object[][] {{"-d"}, {"--directory"}}; } + + @Test(dataProvider = "directoryOptions") + public void testDirectory(String opt) throws Throwable { + out.println("\n--- testDirectory, opt=\"%s\" ".formatted(opt)); + simpleserver(JWEBSERVER, "-p", "0", opt, TEST_DIR_STR) + .shouldHaveExitValue(NORMAL_EXIT_CODE) + .shouldContain("Binding to loopback by default. For all interfaces use \"-b 0.0.0.0\" or \"-b ::\".") + .shouldContain("Serving " + TEST_DIR_STR + " and subdirectories on " + LOOPBACK_ADDR + " port") + .shouldContain("URL http://" + LOOPBACK_ADDR); + } + + @DataProvider + public Object[][] portOptions() { return new Object[][] {{"-p"}, {"--port"}}; } + + @Test(dataProvider = "portOptions") + public void testPort(String opt) throws Throwable { + out.println("\n--- testPort, opt=\"%s\" ".formatted(opt)); + simpleserver(JWEBSERVER, opt, "0") + .shouldHaveExitValue(NORMAL_EXIT_CODE) + .shouldContain("Binding to loopback by default. For all interfaces use \"-b 0.0.0.0\" or \"-b ::\".") + .shouldContain("Serving " + TEST_DIR_STR + " and subdirectories on " + LOOPBACK_ADDR + " port") + .shouldContain("URL http://" + LOOPBACK_ADDR); + } + + @DataProvider + public Object[][] helpOptions() { return new Object[][] {{"-h"}, {"-?"}, {"--help"}}; } + + static final String USAGE_TEXT = """ + Usage: jwebserver [-b bind address] [-p port] [-d directory] + [-o none|info|verbose] [-h to show options] + [-version to show version information]"""; + + static final String OPTIONS_TEXT = """ + Options: + -b, --bind-address - Address to bind to. Default: %s (loopback). + For all interfaces use "-b 0.0.0.0" or "-b ::". + -d, --directory - Directory to serve. Default: current directory. + -o, --output - Output format. none|info|verbose. Default: info. + -p, --port - Port to listen on. Default: 8000. + -h, -?, --help - Prints this help message and exits. + -version, --version - Prints version information and exits. + To stop the server, press Ctrl + C.""".formatted(LOOPBACK_ADDR); + + @Test(dataProvider = "helpOptions") + public void testHelp(String opt) throws Throwable { + out.println("\n--- testHelp, opt=\"%s\" ".formatted(opt)); + simpleserver(WaitForLine.HELP_STARTUP_LINE, + false, // do not explicitly destroy the process + JWEBSERVER, opt) + .shouldHaveExitValue(0) + .shouldContain(USAGE_TEXT) + .shouldContain(OPTIONS_TEXT); + } + + @DataProvider + public Object[][] versionOptions() { return new Object[][] {{"-version"}, {"--version"}}; } + + @Test(dataProvider = "versionOptions") + public void testVersion(String opt) throws Throwable { + out.println("\n--- testVersion, opt=\"%s\" ".formatted(opt)); + simpleserver(WaitForLine.VERSION_STARTUP_LINE, + false, // do not explicitly destroy the process + JWEBSERVER, opt) + .shouldHaveExitValue(0); + } + + @DataProvider + public Object[][] bindOptions() { return new Object[][] {{"-b"}, {"--bind-address"}}; } + + @Test(dataProvider = "bindOptions") + public void testBindAllInterfaces(String opt) throws Throwable { + out.println("\n--- testBindAllInterfaces, opt=\"%s\" ".formatted(opt)); + simpleserver(JWEBSERVER, "-p", "0", opt, "0.0.0.0") + .shouldHaveExitValue(NORMAL_EXIT_CODE) + .shouldContain("Serving " + TEST_DIR_STR + " and subdirectories on 0.0.0.0 (all interfaces) port") + .shouldContain("URL http://" + InetAddress.getLocalHost().getHostAddress()); + simpleserver(JWEBSERVER, opt, "::0") + .shouldHaveExitValue(NORMAL_EXIT_CODE) + .shouldContain("Serving " + TEST_DIR_STR + " and subdirectories on 0.0.0.0 (all interfaces) port") + .shouldContain("URL http://" + InetAddress.getLocalHost().getHostAddress()); + } + + @Test(dataProvider = "bindOptions") + public void testLastOneWinsBindAddress(String opt) throws Throwable { + out.println("\n--- testLastOneWinsBindAddress, opt=\"%s\" ".formatted(opt)); + simpleserver(JWEBSERVER, "-p", "0", opt, "123.4.5.6", opt, LOOPBACK_ADDR) + .shouldHaveExitValue(NORMAL_EXIT_CODE) + .shouldContain("Serving " + TEST_DIR_STR + " and subdirectories on " + LOOPBACK_ADDR + " port") + .shouldContain("URL http://" + LOOPBACK_ADDR); + + } + + @Test(dataProvider = "directoryOptions") + public void testLastOneWinsDirectory(String opt) throws Throwable { + out.println("\n--- testLastOneWinsDirectory, opt=\"%s\" ".formatted(opt)); + simpleserver(JWEBSERVER, "-p", "0", opt, TEST_DIR_STR, opt, TEST_DIR_STR) + .shouldHaveExitValue(NORMAL_EXIT_CODE) + .shouldContain("Binding to loopback by default. For all interfaces use \"-b 0.0.0.0\" or \"-b ::\".") + .shouldContain("Serving " + TEST_DIR_STR + " and subdirectories on " + LOOPBACK_ADDR + " port") + .shouldContain("URL http://" + LOOPBACK_ADDR); + } + + @DataProvider + public Object[][] outputOptions() { return new Object[][] {{"-o"}, {"--output"}}; } + + @Test(dataProvider = "outputOptions") + public void testLastOneWinsOutput(String opt) throws Throwable { + out.println("\n--- testLastOneWinsOutput, opt=\"%s\" ".formatted(opt)); + simpleserver(JWEBSERVER, "-p", "0", opt, "none", opt, "verbose") + .shouldHaveExitValue(NORMAL_EXIT_CODE) + .shouldContain("Binding to loopback by default. For all interfaces use \"-b 0.0.0.0\" or \"-b ::\".") + .shouldContain("Serving " + TEST_DIR_STR + " and subdirectories on " + LOOPBACK_ADDR + " port") + .shouldContain("URL http://" + LOOPBACK_ADDR); + } + + @Test(dataProvider = "portOptions") + public void testLastOneWinsPort(String opt) throws Throwable { + out.println("\n--- testLastOneWinsPort, opt=\"%s\" ".formatted(opt)); + simpleserver(JWEBSERVER, opt, "-999", opt, "0") + .shouldHaveExitValue(NORMAL_EXIT_CODE) + .shouldContain("Binding to loopback by default. For all interfaces use \"-b 0.0.0.0\" or \"-b ::\".") + .shouldContain("Serving " + TEST_DIR_STR + " and subdirectories on " + LOOPBACK_ADDR + " port") + .shouldContain("URL http://" + LOOPBACK_ADDR); + } + + @AfterTest + public void teardown() throws IOException { + if (Files.exists(TEST_DIR)) { + FileUtils.deleteFileTreeWithRetry(TEST_DIR); + } + } + + // --- infra --- + + static String getJwebserver(Path image) { + boolean isWindows = System.getProperty("os.name").startsWith("Windows"); + Path jwebserver = image.resolve("bin").resolve(isWindows ? "jwebserver.exe" : "jwebserver"); + if (Files.notExists(jwebserver)) + throw new RuntimeException(jwebserver + " not found"); + return jwebserver.toAbsolutePath().toString(); + } + + static final String REGULAR_STARTUP_LINE1_STRING = "Serving"; + static final String REGULAR_STARTUP_LINE2_STRING = "URL http://"; + static final String VERSION_STARTUP_LINE_STRING = "jwebserver " + JAVA_VERSION; + + // The stdout/stderr output line to wait for when starting the simpleserver + enum WaitForLine { + REGULAR_STARTUP_LINE (REGULAR_STARTUP_LINE2_STRING) , + HELP_STARTUP_LINE (OPTIONS_TEXT.lines().reduce((first, second) -> second).orElseThrow()), + VERSION_STARTUP_LINE (VERSION_STARTUP_LINE_STRING); + + final String value; + WaitForLine(String value) { this.value = value; } + } + + static OutputAnalyzer simpleserver(String... args) throws Throwable { + return simpleserver(WaitForLine.REGULAR_STARTUP_LINE, true, args); + } + + static OutputAnalyzer simpleserver(WaitForLine waitForLine, boolean destroy, String... args) throws Throwable { + StringBuffer sb = new StringBuffer(); // stdout & stderr + // start the process and await the waitForLine before returning + var p = ProcessTools.startProcess("simpleserver", + new ProcessBuilder(args).directory(TEST_DIR.toFile()), + line -> sb.append(line + "\n"), + line -> line.startsWith(waitForLine.value), + 30, // suitably high default timeout, not expected to timeout + TimeUnit.SECONDS); + if (destroy) { + p.destroy(); // SIGTERM on Unix + } + int ec = p.waitFor(); + var outputAnalyser = new OutputAnalyzer(sb.toString(), "", ec); + return outputAnalyser; + } +} diff --git a/test/jdk/java/awt/ColorClass/AlphaColorTest.java b/test/jdk/java/awt/ColorClass/AlphaColorTest.java index e3478c961fc02fca6d2a65e864cebe443c14d3ee..62d5ca4da327e4d01876e829bd40a092e60e6f0c 100644 --- a/test/jdk/java/awt/ColorClass/AlphaColorTest.java +++ b/test/jdk/java/awt/ColorClass/AlphaColorTest.java @@ -24,7 +24,7 @@ /** * @test * @key headful - * @bug 8204931 8227392 8224825 8233910 + * @bug 8204931 8227392 8224825 8233910 8275843 * @summary test alpha colors are blended with background. */ diff --git a/test/jdk/java/awt/ColorClass/XRenderTranslucentColorDrawTest.java b/test/jdk/java/awt/ColorClass/XRenderTranslucentColorDrawTest.java index 7754c4125cb71b3e12ea042f03b87df920643277..eab4a91308d5568a5ad716febfecdfa3f8fcb069 100644 --- a/test/jdk/java/awt/ColorClass/XRenderTranslucentColorDrawTest.java +++ b/test/jdk/java/awt/ColorClass/XRenderTranslucentColorDrawTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,14 +21,15 @@ * questions. */ + /* * @test * @key headful - * @bug 8176795 + * @bug 8176795 8275843 * @summary Test verifies that we get proper color when we draw translucent * color over an opaque color using X Render extension in Linux. - * @requires (os.family == "linux") - * @run main XRenderTranslucentColorDrawTest -Dsun.java2d.xrender=true + * @run main/othervm XRenderTranslucentColorDrawTest + * @run main/othervm -Dsun.java2d.xrender=true XRenderTranslucentColorDrawTest */ import java.awt.Color; @@ -36,30 +37,28 @@ import java.awt.Graphics2D; import java.awt.GraphicsConfiguration; import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; +import java.awt.Transparency; import java.awt.image.BufferedImage; import java.awt.image.VolatileImage; public class XRenderTranslucentColorDrawTest { - public static void main(String[] args) throws Exception { - GraphicsEnvironment env = GraphicsEnvironment. - getLocalGraphicsEnvironment(); - GraphicsConfiguration translucentGC = null; - SCREENS: for (GraphicsDevice screen : env.getScreenDevices()) { + public static void main(String[] args) { + var env = GraphicsEnvironment.getLocalGraphicsEnvironment(); + for (GraphicsDevice screen : env.getScreenDevices()) { for (GraphicsConfiguration gc : screen.getConfigurations()) { - if (gc.isTranslucencyCapable()) { - translucentGC = gc; - break SCREENS; - } + test(gc, Transparency.OPAQUE); + test(gc, Transparency.BITMASK); + test(gc, Transparency.TRANSLUCENT); } } - if (translucentGC == null) { - throw new RuntimeException("No suitable gc found."); - } + } + + private static void test(GraphicsConfiguration gc, int transparency) { int width = 10; int height = 10; - VolatileImage image = translucentGC. - createCompatibleVolatileImage(width, height); + VolatileImage image = gc.createCompatibleVolatileImage(width, height, + transparency); Graphics2D g = image.createGraphics(); // draw opaque black color g.setColor(new Color(0xff000000, true)); @@ -72,10 +71,10 @@ public class XRenderTranslucentColorDrawTest { BufferedImage snapshot = image.getSnapshot(); int argb = snapshot.getRGB(width / 2, height / 2); // we expect the resultant rgb hex value to be ff808080 - if (!(Integer.toHexString(argb).equals("ff808080"))) { - throw new RuntimeException("Using X Render extension for drawing" - + " translucent color is not giving expected results."); + String actual = Integer.toHexString(argb); + if (!(actual.equals("ff808080"))) { + throw new RuntimeException("Drawing translucent color is not " + + "giving expected results: " + actual); } } -} - +} \ No newline at end of file diff --git a/test/jdk/java/awt/Desktop/DesktopEventsExceptions/DesktopEventsExceptions.java b/test/jdk/java/awt/Desktop/DesktopEventsExceptions/DesktopEventsExceptions.java index 2a1b88d7d73365dd327521ce6471e6f575d86699..83a35b71a120f33f5b3a727017a605e212dba499 100644 --- a/test/jdk/java/awt/Desktop/DesktopEventsExceptions/DesktopEventsExceptions.java +++ b/test/jdk/java/awt/Desktop/DesktopEventsExceptions/DesktopEventsExceptions.java @@ -45,7 +45,7 @@ import java.util.List; * @test * @bug 8203224 * @summary tests that the correct exceptions are thrown by the events classes - * in {code java.awt.desktop} package + * in {@code java.awt.desktop} package * @run main/othervm DesktopEventsExceptions * @run main/othervm -Djava.awt.headless=true DesktopEventsExceptions */ diff --git a/test/jdk/java/awt/image/ColorModel/DrawCustomColorModel.java b/test/jdk/java/awt/image/ColorModel/DrawCustomColorModel.java new file mode 100644 index 0000000000000000000000000000000000000000..a438048f1cee46b6ed052ceea39a4c6bdbd1b329 --- /dev/null +++ b/test/jdk/java/awt/image/ColorModel/DrawCustomColorModel.java @@ -0,0 +1,79 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.AlphaComposite; +import java.awt.Frame; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.Image; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.DataBufferInt; +import java.awt.image.DirectColorModel; +import java.awt.image.WritableRaster; +import java.util.Arrays; + +/** + * @test + * @bug 8275843 + * @key headful + * @summary No exception or errors should occur. + */ +public final class DrawCustomColorModel { + + public static void main(String[] args) { + var ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + for (GraphicsDevice gd : ge.getScreenDevices()) { + GraphicsConfiguration[] gcs = gd.getConfigurations(); + for (GraphicsConfiguration gc : gcs) { + test(gc); + } + } + } + + private static void test(GraphicsConfiguration gc) { + Frame frame = new Frame(gc); + frame.setUndecorated(true); + frame.pack(); + frame.setSize(15, 15); + ColorModel cm = new DirectColorModel(32, + 0xff000000, // Red + 0x00ff0000, // Green + 0x0000ff00, // Blue + 0x000000FF // Alpha + ); + WritableRaster wr = cm.createCompatibleWritableRaster(16, 16); + DataBufferInt buff = (DataBufferInt) wr.getDataBuffer(); + int[] data = buff.getData(); + Arrays.fill(data, -1); // more chance to reproduce + Image image = new BufferedImage(cm, wr, false, null); + + Graphics2D graphics = (Graphics2D) frame.getGraphics(); + graphics.setComposite(AlphaComposite.Src); + graphics.drawImage(image, 0, 0, null); + graphics.dispose(); + frame.dispose(); + } +} diff --git a/test/jdk/java/awt/regtesthelpers/process/ProcessCommunicator.java b/test/jdk/java/awt/regtesthelpers/process/ProcessCommunicator.java index 60a5952b32c03b12bc7217af83df0fa56c8451c0..474a23717ea91f8020602144b1d96aaafbd54686 100644 --- a/test/jdk/java/awt/regtesthelpers/process/ProcessCommunicator.java +++ b/test/jdk/java/awt/regtesthelpers/process/ProcessCommunicator.java @@ -76,7 +76,7 @@ public class ProcessCommunicator { } /** - * Executes child {code Process} + * Executes child {@code Process} * * @param classToExecute class to be executed as a child java process * @param args args to be passed in to the child process diff --git a/test/jdk/java/foreign/CallGeneratorHelper.java b/test/jdk/java/foreign/CallGeneratorHelper.java index 9a795525e1f323304e17bae4b8ed2aa2f6dc462b..a69fe1a5d81b99b71a65d6efbd5e1513e516a201 100644 --- a/test/jdk/java/foreign/CallGeneratorHelper.java +++ b/test/jdk/java/foreign/CallGeneratorHelper.java @@ -22,14 +22,19 @@ * */ +import jdk.incubator.foreign.Addressable; +import jdk.incubator.foreign.CLinker; +import jdk.incubator.foreign.FunctionDescriptor; import jdk.incubator.foreign.GroupLayout; import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.NativeSymbol; import jdk.incubator.foreign.ResourceScope; import jdk.incubator.foreign.SegmentAllocator; import jdk.incubator.foreign.ValueLayout; +import java.lang.invoke.MethodHandle; import java.lang.invoke.VarHandle; import java.util.ArrayList; import java.util.List; @@ -40,12 +45,13 @@ import java.util.stream.IntStream; import org.testng.annotations.*; -import static jdk.incubator.foreign.CLinker.*; import static org.testng.Assert.*; public class CallGeneratorHelper extends NativeTestHelper { - static SegmentAllocator IMPLICIT_ALLOCATOR = (size, align) -> MemorySegment.allocateNative(size, align, ResourceScope.newImplicitScope()); + static SegmentAllocator THROWING_ALLOCATOR = (size, align) -> { + throw new UnsupportedOperationException(); + }; static final int SAMPLE_FACTOR = Integer.parseInt((String)System.getProperties().getOrDefault("generator.sample.factor", "-1")); @@ -58,7 +64,7 @@ public class CallGeneratorHelper extends NativeTestHelper { GroupLayout g = (GroupLayout) layout; for (MemoryLayout field : g.memberLayouts()) { if (field instanceof ValueLayout) { - VarHandle vh = g.varHandle(vhCarrier(field), MemoryLayout.PathElement.groupElement(field.name().orElseThrow())); + VarHandle vh = g.varHandle(MemoryLayout.PathElement.groupElement(field.name().orElseThrow())); assertEquals(vh.get(actual), vh.get(expected)); } } @@ -410,12 +416,9 @@ public class CallGeneratorHelper extends NativeTestHelper { static void initStruct(MemorySegment str, GroupLayout g, List<Consumer<Object>> checks, boolean check) throws ReflectiveOperationException { for (MemoryLayout l : g.memberLayouts()) { if (l.isPadding()) continue; - VarHandle accessor = g.varHandle(structFieldCarrier(l), MemoryLayout.PathElement.groupElement(l.name().get())); + VarHandle accessor = g.varHandle(MemoryLayout.PathElement.groupElement(l.name().get())); List<Consumer<Object>> fieldsCheck = new ArrayList<>(); Object value = makeArg(l, fieldsCheck, check); - if (isPointer(l)) { - value = ((MemoryAddress)value).toRawLongValue(); - } //set value accessor.set(str, value); //add check @@ -424,11 +427,7 @@ public class CallGeneratorHelper extends NativeTestHelper { checks.add(o -> { MemorySegment actual = (MemorySegment)o; try { - if (isPointer(l)) { - fieldsCheck.get(0).accept(MemoryAddress.ofLong((long)accessor.get(actual))); - } else { - fieldsCheck.get(0).accept(accessor.get(actual)); - } + fieldsCheck.get(0).accept(accessor.get(actual)); } catch (Throwable ex) { throw new IllegalStateException(ex); } @@ -437,37 +436,23 @@ public class CallGeneratorHelper extends NativeTestHelper { } } - static Class<?> structFieldCarrier(MemoryLayout layout) { - if (isPointer(layout)) { - return long.class; - } else if (layout instanceof ValueLayout) { - if (isIntegral(layout)) { - return int.class; - } else if (layout.bitSize() == 32) { - return float.class; - } else { - return double.class; - } - } else { - throw new IllegalStateException("Unexpected layout: " + layout); - } - } - - static Class<?> paramCarrier(MemoryLayout layout) { + static Class<?> carrier(MemoryLayout layout, boolean param) { if (layout instanceof GroupLayout) { return MemorySegment.class; } if (isPointer(layout)) { - return MemoryAddress.class; - } else if (layout instanceof ValueLayout) { - if (isIntegral(layout)) { - return int.class; - } else if (layout.bitSize() == 32) { - return float.class; - } else { - return double.class; - } + return param ? Addressable.class : MemoryAddress.class; + } else if (layout instanceof ValueLayout valueLayout) { + return valueLayout.carrier(); } else { throw new IllegalStateException("Unexpected layout: " + layout); } } + + MethodHandle downcallHandle(CLinker abi, NativeSymbol symbol, SegmentAllocator allocator, FunctionDescriptor descriptor) { + MethodHandle mh = abi.downcallHandle(symbol, descriptor); + if (descriptor.returnLayout().isPresent() && descriptor.returnLayout().get() instanceof GroupLayout) { + mh = mh.bindTo(allocator); + } + return mh; + } } diff --git a/test/jdk/java/foreign/NativeTestHelper.java b/test/jdk/java/foreign/NativeTestHelper.java index 9b57beac732eef0dd5e0bc2a836fb79837078c73..ca789f984f8142ddb0afcd610b5d237ab9acc983 100644 --- a/test/jdk/java/foreign/NativeTestHelper.java +++ b/test/jdk/java/foreign/NativeTestHelper.java @@ -22,58 +22,90 @@ * */ +import jdk.incubator.foreign.Addressable; import jdk.incubator.foreign.CLinker; +import jdk.incubator.foreign.FunctionDescriptor; +import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; import jdk.incubator.foreign.SegmentAllocator; +import jdk.incubator.foreign.ValueLayout; + +import java.lang.invoke.MethodHandle; public class NativeTestHelper { - static CLinker.TypeKind kind(MemoryLayout layout) { - return (CLinker.TypeKind)layout.attribute(CLinker.TypeKind.ATTR_NAME).orElseThrow( - () -> new IllegalStateException("Unexpected value layout: could not determine ABI class")); + public static boolean isIntegral(MemoryLayout layout) { + return layout instanceof ValueLayout valueLayout && isIntegral(valueLayout.carrier()); } - public static boolean isIntegral(MemoryLayout layout) { - return kind(layout).isIntegral(); + static boolean isIntegral(Class<?> clazz) { + return clazz == byte.class || clazz == char.class || clazz == short.class + || clazz == int.class || clazz == long.class; } public static boolean isPointer(MemoryLayout layout) { - return kind(layout).isPointer(); + return layout instanceof ValueLayout valueLayout && valueLayout.carrier() == MemoryAddress.class; } - public static class NativeScope implements SegmentAllocator, AutoCloseable { - final ResourceScope resourceScope; - final ResourceScope.Handle scopeHandle; - final SegmentAllocator allocator; + // the constants below are useful aliases for C types. The type/carrier association is only valid for 64-bit platforms. - long allocatedBytes = 0; + /** + * The layout for the {@code bool} C type + */ + public static final ValueLayout.OfBoolean C_BOOL = ValueLayout.JAVA_BOOLEAN; + /** + * The layout for the {@code char} C type + */ + public static final ValueLayout.OfByte C_CHAR = ValueLayout.JAVA_BYTE; + /** + * The layout for the {@code short} C type + */ + public static final ValueLayout.OfShort C_SHORT = ValueLayout.JAVA_SHORT.withBitAlignment(16); + /** + * The layout for the {@code int} C type + */ + public static final ValueLayout.OfInt C_INT = ValueLayout.JAVA_INT.withBitAlignment(32); - public NativeScope() { - this.resourceScope = ResourceScope.newConfinedScope(); - this.scopeHandle = resourceScope.acquire(); - this.allocator = SegmentAllocator.arenaAllocator(resourceScope); - } + /** + * The layout for the {@code long long} C type. + */ + public static final ValueLayout.OfLong C_LONG_LONG = ValueLayout.JAVA_LONG.withBitAlignment(64); + /** + * The layout for the {@code float} C type + */ + public static final ValueLayout.OfFloat C_FLOAT = ValueLayout.JAVA_FLOAT.withBitAlignment(32); + /** + * The layout for the {@code double} C type + */ + public static final ValueLayout.OfDouble C_DOUBLE = ValueLayout.JAVA_DOUBLE.withBitAlignment(64); + /** + * The {@code T*} native type. + */ + public static final ValueLayout.OfAddress C_POINTER = ValueLayout.ADDRESS.withBitAlignment(64); - @Override - public MemorySegment allocate(long bytesSize, long bytesAlignment) { - allocatedBytes += bytesSize; - return allocator.allocate(bytesSize, bytesAlignment); - } + private static CLinker LINKER = CLinker.systemCLinker(); - public ResourceScope scope() { - return resourceScope; - } + private static final MethodHandle FREE = LINKER.downcallHandle( + LINKER.lookup("free").get(), FunctionDescriptor.ofVoid(ValueLayout.ADDRESS)); - public long allocatedBytes() { - return allocatedBytes; + private static final MethodHandle MALLOC = LINKER.downcallHandle( + LINKER.lookup("malloc").get(), FunctionDescriptor.of(ValueLayout.ADDRESS, ValueLayout.JAVA_LONG)); + + public static void freeMemory(Addressable address) { + try { + FREE.invokeExact(address); + } catch (Throwable ex) { + throw new IllegalStateException(ex); } + } - @Override - public void close() { - resourceScope.release(scopeHandle); - resourceScope.close(); + public static MemoryAddress allocateMemory(long size) { + try { + return (MemoryAddress)MALLOC.invokeExact(size); + } catch (Throwable ex) { + throw new IllegalStateException(ex); } } } diff --git a/test/jdk/java/foreign/SafeFunctionAccessTest.java b/test/jdk/java/foreign/SafeFunctionAccessTest.java index b6801ad8888072fba063f14d31a986e4bd88e930..5c45f42cc2635d49c7d451b42a7a941c0267b112 100644 --- a/test/jdk/java/foreign/SafeFunctionAccessTest.java +++ b/test/jdk/java/foreign/SafeFunctionAccessTest.java @@ -27,27 +27,31 @@ * @run testng/othervm --enable-native-access=ALL-UNNAMED SafeFunctionAccessTest */ +import jdk.incubator.foreign.Addressable; import jdk.incubator.foreign.CLinker; import jdk.incubator.foreign.FunctionDescriptor; +import jdk.incubator.foreign.NativeSymbol; import jdk.incubator.foreign.SymbolLookup; -import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; +import jdk.incubator.foreign.VaList; import org.testng.annotations.*; + import static org.testng.Assert.*; -public class SafeFunctionAccessTest { +public class SafeFunctionAccessTest extends NativeTestHelper { static { System.loadLibrary("SafeAccess"); } static MemoryLayout POINT = MemoryLayout.structLayout( - CLinker.C_INT, CLinker.C_INT + C_INT, C_INT ); static final SymbolLookup LOOKUP = SymbolLookup.loaderLookup(); @@ -59,26 +63,135 @@ public class SafeFunctionAccessTest { segment = MemorySegment.allocateNative(POINT, scope); } assertFalse(segment.scope().isAlive()); - MethodHandle handle = CLinker.getInstance().downcallHandle( + MethodHandle handle = CLinker.systemCLinker().downcallHandle( LOOKUP.lookup("struct_func").get(), - MethodType.methodType(void.class, MemorySegment.class), FunctionDescriptor.ofVoid(POINT)); handle.invokeExact(segment); } + @Test + public void testClosedStructAddr_6() throws Throwable { + MethodHandle handle = CLinker.systemCLinker().downcallHandle( + LOOKUP.lookup("addr_func_6").get(), + FunctionDescriptor.ofVoid(C_POINTER, C_POINTER, C_POINTER, C_POINTER, C_POINTER, C_POINTER)); + for (int i = 0 ; i < 6 ; i++) { + MemorySegment[] segments = new MemorySegment[]{ + MemorySegment.allocateNative(POINT, ResourceScope.newImplicitScope()), + MemorySegment.allocateNative(POINT, ResourceScope.newImplicitScope()), + MemorySegment.allocateNative(POINT, ResourceScope.newImplicitScope()), + MemorySegment.allocateNative(POINT, ResourceScope.newImplicitScope()), + MemorySegment.allocateNative(POINT, ResourceScope.newImplicitScope()), + MemorySegment.allocateNative(POINT, ResourceScope.newImplicitScope()) + }; + // check liveness + segments[i].scope().close(); + for (int j = 0 ; j < 6 ; j++) { + if (i == j) { + assertFalse(segments[j].scope().isAlive()); + } else { + assertTrue(segments[j].scope().isAlive()); + } + } + try { + handle.invokeWithArguments(segments); + fail(); + } catch (IllegalStateException ex) { + assertTrue(ex.getMessage().contains("Already closed")); + } + for (int j = 0 ; j < 6 ; j++) { + if (i != j) { + segments[j].scope().close(); // should succeed! + } + } + } + } + @Test(expectedExceptions = IllegalStateException.class) - public void testClosedPointer() throws Throwable { - MemoryAddress address; + public void testClosedVaList() throws Throwable { + VaList list; try (ResourceScope scope = ResourceScope.newConfinedScope()) { - address = MemorySegment.allocateNative(POINT, scope).address(); + list = VaList.make(b -> b.addVarg(C_INT, 42), scope); } - assertFalse(address.scope().isAlive()); - MethodHandle handle = CLinker.getInstance().downcallHandle( + assertFalse(list.scope().isAlive()); + MethodHandle handle = CLinker.systemCLinker().downcallHandle( LOOKUP.lookup("addr_func").get(), - MethodType.methodType(void.class, MemoryAddress.class), - FunctionDescriptor.ofVoid(CLinker.C_POINTER)); + FunctionDescriptor.ofVoid(C_POINTER)); - handle.invokeExact(address); + handle.invokeExact((Addressable)list); + } + + @Test(expectedExceptions = IllegalStateException.class) + public void testClosedUpcall() throws Throwable { + NativeSymbol upcall; + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MethodHandle dummy = MethodHandles.lookup().findStatic(SafeFunctionAccessTest.class, "dummy", MethodType.methodType(void.class)); + upcall = CLinker.systemCLinker().upcallStub(dummy, FunctionDescriptor.ofVoid(), scope); + } + assertFalse(upcall.scope().isAlive()); + MethodHandle handle = CLinker.systemCLinker().downcallHandle( + LOOKUP.lookup("addr_func").get(), + FunctionDescriptor.ofVoid(C_POINTER)); + + handle.invokeExact((Addressable)upcall); + } + + static void dummy() { } + + @Test + public void testClosedVaListCallback() throws Throwable { + MethodHandle handle = CLinker.systemCLinker().downcallHandle( + LOOKUP.lookup("addr_func_cb").get(), + FunctionDescriptor.ofVoid(C_POINTER, C_POINTER)); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + VaList list = VaList.make(b -> b.addVarg(C_INT, 42), scope); + handle.invoke(list, scopeChecker(scope)); + } + } + + @Test + public void testClosedStructCallback() throws Throwable { + MethodHandle handle = CLinker.systemCLinker().downcallHandle( + LOOKUP.lookup("addr_func_cb").get(), + FunctionDescriptor.ofVoid(C_POINTER, C_POINTER)); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemorySegment segment = MemorySegment.allocateNative(POINT, scope); + handle.invoke(segment, scopeChecker(scope)); + } + } + + @Test + public void testClosedUpcallCallback() throws Throwable { + MethodHandle handle = CLinker.systemCLinker().downcallHandle( + LOOKUP.lookup("addr_func_cb").get(), + FunctionDescriptor.ofVoid(C_POINTER, C_POINTER)); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MethodHandle dummy = MethodHandles.lookup().findStatic(SafeFunctionAccessTest.class, "dummy", MethodType.methodType(void.class)); + NativeSymbol upcall = CLinker.systemCLinker().upcallStub(dummy, FunctionDescriptor.ofVoid(), scope); + handle.invoke(upcall, scopeChecker(scope)); + } + } + + NativeSymbol scopeChecker(ResourceScope scope) { + try { + MethodHandle handle = MethodHandles.lookup().findStatic(SafeFunctionAccessTest.class, "checkScope", + MethodType.methodType(void.class, ResourceScope.class)); + handle = handle.bindTo(scope); + return CLinker.systemCLinker().upcallStub(handle, FunctionDescriptor.ofVoid(), ResourceScope.newImplicitScope()); + } catch (Throwable ex) { + throw new AssertionError(ex); + } + } + + static void checkScope(ResourceScope scope) { + try { + scope.close(); + fail("Scope closed unexpectedly!"); + } catch (IllegalStateException ex) { + assertTrue(ex.getMessage().contains("kept alive")); //if acquired, fine + } } } diff --git a/test/jdk/java/foreign/StdLibTest.java b/test/jdk/java/foreign/StdLibTest.java index 4495ed159211aaf9ef365b77f5864c5ce6631a66..1246a260b1d7299f3070f9e904452cf8b511fa2f 100644 --- a/test/jdk/java/foreign/StdLibTest.java +++ b/test/jdk/java/foreign/StdLibTest.java @@ -39,7 +39,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; -import java.util.Optional; import java.util.Set; import java.util.function.BiConsumer; import java.util.function.Function; @@ -48,17 +47,14 @@ import java.util.stream.Stream; import jdk.incubator.foreign.*; -import static jdk.incubator.foreign.MemoryAccess.*; - import org.testng.annotations.*; -import static jdk.incubator.foreign.CLinker.*; import static org.testng.Assert.*; @Test -public class StdLibTest { +public class StdLibTest extends NativeTestHelper { - final static CLinker abi = CLinker.getInstance(); + final static CLinker abi = CLinker.systemCLinker(); private StdLibHelper stdLibHelper = new StdLibHelper(); @@ -155,45 +151,36 @@ public class StdLibTest { static class StdLibHelper { - static final SymbolLookup LOOKUP = CLinker.systemLookup(); - - final static MethodHandle strcat = abi.downcallHandle(LOOKUP.lookup("strcat").get(), - MethodType.methodType(MemoryAddress.class, MemoryAddress.class, MemoryAddress.class), - FunctionDescriptor.of(C_POINTER, C_POINTER, C_POINTER)); + final static MethodHandle strcat = abi.downcallHandle(abi.lookup("strcat").get(), + FunctionDescriptor.of(C_POINTER, C_POINTER, C_POINTER)) + .asType(MethodType.methodType(MemoryAddress.class, MemorySegment.class, MemorySegment.class)); // exact signature match - final static MethodHandle strcmp = abi.downcallHandle(LOOKUP.lookup("strcmp").get(), - MethodType.methodType(int.class, MemoryAddress.class, MemoryAddress.class), + final static MethodHandle strcmp = abi.downcallHandle(abi.lookup("strcmp").get(), FunctionDescriptor.of(C_INT, C_POINTER, C_POINTER)); - final static MethodHandle puts = abi.downcallHandle(LOOKUP.lookup("puts").get(), - MethodType.methodType(int.class, MemoryAddress.class), + final static MethodHandle puts = abi.downcallHandle(abi.lookup("puts").get(), FunctionDescriptor.of(C_INT, C_POINTER)); - final static MethodHandle strlen = abi.downcallHandle(LOOKUP.lookup("strlen").get(), - MethodType.methodType(int.class, MemoryAddress.class), + final static MethodHandle strlen = abi.downcallHandle(abi.lookup("strlen").get(), FunctionDescriptor.of(C_INT, C_POINTER)); - final static MethodHandle gmtime = abi.downcallHandle(LOOKUP.lookup("gmtime").get(), - MethodType.methodType(MemoryAddress.class, MemoryAddress.class), + final static MethodHandle gmtime = abi.downcallHandle(abi.lookup("gmtime").get(), FunctionDescriptor.of(C_POINTER, C_POINTER)); - final static MethodHandle qsort = abi.downcallHandle(LOOKUP.lookup("qsort").get(), - MethodType.methodType(void.class, MemoryAddress.class, long.class, long.class, MemoryAddress.class), + final static MethodHandle qsort = abi.downcallHandle(abi.lookup("qsort").get(), FunctionDescriptor.ofVoid(C_POINTER, C_LONG_LONG, C_LONG_LONG, C_POINTER)); final static FunctionDescriptor qsortComparFunction = FunctionDescriptor.of(C_INT, C_POINTER, C_POINTER); final static MethodHandle qsortCompar; - final static MethodHandle rand = abi.downcallHandle(LOOKUP.lookup("rand").get(), - MethodType.methodType(int.class), + final static MethodHandle rand = abi.downcallHandle(abi.lookup("rand").get(), FunctionDescriptor.of(C_INT)); - final static MethodHandle vprintf = abi.downcallHandle(LOOKUP.lookup("vprintf").get(), - MethodType.methodType(int.class, MemoryAddress.class, VaList.class), - FunctionDescriptor.of(C_INT, C_POINTER, C_VA_LIST)); + final static MethodHandle vprintf = abi.downcallHandle(abi.lookup("vprintf").get(), + FunctionDescriptor.of(C_INT, C_POINTER, C_POINTER)); - final static MemoryAddress printfAddr = LOOKUP.lookup("printf").get(); + final static NativeSymbol printfAddr = abi.lookup("printf").get(); final static FunctionDescriptor printfBase = FunctionDescriptor.of(C_INT, C_POINTER); @@ -201,7 +188,7 @@ public class StdLibTest { try { //qsort upcall handle qsortCompar = MethodHandles.lookup().findStatic(StdLibTest.StdLibHelper.class, "qsortCompare", - MethodType.methodType(int.class, MemorySegment.class, MemoryAddress.class, MemoryAddress.class)); + CLinker.upcallType(qsortComparFunction)); } catch (ReflectiveOperationException ex) { throw new IllegalStateException(ex); } @@ -209,44 +196,44 @@ public class StdLibTest { String strcat(String s1, String s2) throws Throwable { try (ResourceScope scope = ResourceScope.newConfinedScope()) { - MemorySegment buf = MemorySegment.allocateNative(s1.length() + s2.length() + 1, scope); - MemorySegment other = toCString(s2, scope); - char[] chars = s1.toCharArray(); - for (long i = 0 ; i < chars.length ; i++) { - setByteAtOffset(buf, i, (byte)chars[(int)i]); - } - setByteAtOffset(buf, chars.length, (byte)'\0'); - return toJavaString(((MemoryAddress)strcat.invokeExact(buf.address(), other.address()))); + var malloc = SegmentAllocator.nativeAllocator(scope); + MemorySegment buf = malloc.allocate(s1.length() + s2.length() + 1); + buf.setUtf8String(0, s1); + MemorySegment other = malloc.allocateUtf8String(s2); + return ((MemoryAddress)strcat.invokeExact(buf, other)).getUtf8String(0); } } int strcmp(String s1, String s2) throws Throwable { try (ResourceScope scope = ResourceScope.newConfinedScope()) { - MemorySegment ns1 = toCString(s1, scope); - MemorySegment ns2 = toCString(s2, scope); - return (int)strcmp.invokeExact(ns1.address(), ns2.address()); + var malloc = SegmentAllocator.nativeAllocator(scope); + MemorySegment ns1 = malloc.allocateUtf8String(s1); + MemorySegment ns2 = malloc.allocateUtf8String(s2); + return (int)strcmp.invoke(ns1, ns2); } } int puts(String msg) throws Throwable { try (ResourceScope scope = ResourceScope.newConfinedScope()) { - MemorySegment s = toCString(msg, scope); - return (int)puts.invokeExact(s.address()); + var malloc = SegmentAllocator.nativeAllocator(scope); + MemorySegment s = malloc.allocateUtf8String(msg); + return (int)puts.invoke(s); } } int strlen(String msg) throws Throwable { try (ResourceScope scope = ResourceScope.newConfinedScope()) { - MemorySegment s = toCString(msg, scope); - return (int)strlen.invokeExact(s.address()); + var malloc = SegmentAllocator.nativeAllocator(scope); + MemorySegment s = malloc.allocateUtf8String(msg); + return (int)strlen.invoke(s); } } Tm gmtime(long arg) throws Throwable { try (ResourceScope scope = ResourceScope.newConfinedScope()) { MemorySegment time = MemorySegment.allocateNative(8, scope); - setLong(time, arg); - return new Tm((MemoryAddress)gmtime.invokeExact(time.address())); + time.set(C_LONG_LONG, 0, arg); + return new Tm((MemoryAddress)gmtime.invoke(time)); } } @@ -258,58 +245,57 @@ public class StdLibTest { static final long SIZE = 56; Tm(MemoryAddress addr) { - this.base = addr.asSegment(SIZE, ResourceScope.globalScope()); + this.base = MemorySegment.ofAddress(addr, SIZE, ResourceScope.globalScope()); } int sec() { - return getIntAtOffset(base, 0); + return base.get(C_INT, 0); } int min() { - return getIntAtOffset(base, 4); + return base.get(C_INT, 4); } int hour() { - return getIntAtOffset(base, 8); + return base.get(C_INT, 8); } int mday() { - return getIntAtOffset(base, 12); + return base.get(C_INT, 12); } int mon() { - return getIntAtOffset(base, 16); + return base.get(C_INT, 16); } int year() { - return getIntAtOffset(base, 20); + return base.get(C_INT, 20); } int wday() { - return getIntAtOffset(base, 24); + return base.get(C_INT, 24); } int yday() { - return getIntAtOffset(base, 28); + return base.get(C_INT, 28); } boolean isdst() { - byte b = getByteAtOffset(base, 32); - return b != 0; + return base.get(C_BOOL, 32); } } int[] qsort(int[] arr) throws Throwable { //init native array try (ResourceScope scope = ResourceScope.newConfinedScope()) { - SegmentAllocator allocator = SegmentAllocator.ofScope(scope); - MemorySegment nativeArr = allocator.allocateArray(C_INT, arr); + var malloc = SegmentAllocator.nativeAllocator(scope); + MemorySegment nativeArr = malloc.allocateArray(C_INT, arr); //call qsort - MemoryAddress qsortUpcallStub = abi.upcallStub(qsortCompar.bindTo(nativeArr), qsortComparFunction, scope); + NativeSymbol qsortUpcallStub = abi.upcallStub(qsortCompar, qsortComparFunction, scope); - qsort.invokeExact(nativeArr.address(), (long)arr.length, C_INT.byteSize(), qsortUpcallStub); + qsort.invoke(nativeArr, (long)arr.length, C_INT.byteSize(), qsortUpcallStub); //convert back to Java array - return nativeArr.toIntArray(); + return nativeArr.toArray(C_INT); } } - static int qsortCompare(MemorySegment base, MemoryAddress addr1, MemoryAddress addr2) { - return getIntAtOffset(base, addr1.segmentOffset(base)) - - getIntAtOffset(base, addr2.segmentOffset(base)); + static int qsortCompare(MemoryAddress addr1, MemoryAddress addr2) { + return addr1.get(C_INT, 0) - + addr2.get(C_INT, 0); } int rand() throws Throwable { @@ -318,17 +304,19 @@ public class StdLibTest { int printf(String format, List<PrintfArg> args) throws Throwable { try (ResourceScope scope = ResourceScope.newConfinedScope()) { - MemorySegment formatStr = toCString(format, scope); - return (int)specializedPrintf(args).invokeExact(formatStr.address(), + var malloc = SegmentAllocator.nativeAllocator(scope); + MemorySegment formatStr = malloc.allocateUtf8String(format); + return (int)specializedPrintf(args).invoke(formatStr, args.stream().map(a -> a.nativeValue(scope)).toArray()); } } int vprintf(String format, List<PrintfArg> args) throws Throwable { try (ResourceScope scope = ResourceScope.newConfinedScope()) { - MemorySegment formatStr = toCString(format, scope); + var malloc = SegmentAllocator.nativeAllocator(scope); + MemorySegment formatStr = malloc.allocateUtf8String(format); VaList vaList = VaList.make(b -> args.forEach(a -> a.accept(b, scope)), scope); - return (int)vprintf.invokeExact(formatStr.address(), vaList); + return (int)vprintf.invoke(formatStr, vaList); } } @@ -336,11 +324,13 @@ public class StdLibTest { //method type MethodType mt = MethodType.methodType(int.class, MemoryAddress.class); FunctionDescriptor fd = printfBase; + List<MemoryLayout> variadicLayouts = new ArrayList<>(args.size()); for (PrintfArg arg : args) { mt = mt.appendParameterTypes(arg.carrier); - fd = fd.withAppendedArgumentLayouts(arg.layout); + variadicLayouts.add(arg.layout); } - MethodHandle mh = abi.downcallHandle(printfAddr, mt, fd); + MethodHandle mh = abi.downcallHandle(printfAddr, + fd.asVariadic(variadicLayouts.toArray(new MemoryLayout[args.size()]))); return mh.asSpreader(1, Object[].class, args.size()); } } @@ -401,10 +391,14 @@ public class StdLibTest { enum PrintfArg implements BiConsumer<VaList.Builder, ResourceScope> { - INTEGRAL(int.class, asVarArg(C_INT), "%d", scope -> 42, 42, VaList.Builder::vargFromInt), - STRING(MemoryAddress.class, asVarArg(C_POINTER), "%s", scope -> toCString("str", scope).address(), "str", VaList.Builder::vargFromAddress), - CHAR(byte.class, asVarArg(C_CHAR), "%c", scope -> (byte) 'h', 'h', (builder, layout, value) -> builder.vargFromInt(C_INT, (int)value)), - DOUBLE(double.class, asVarArg(C_DOUBLE), "%.4f", scope ->1.2345d, 1.2345d, VaList.Builder::vargFromDouble); + INTEGRAL(int.class, C_INT, "%d", scope -> 42, 42, VaList.Builder::addVarg), + STRING(MemoryAddress.class, C_POINTER, "%s", scope -> { + var segment = MemorySegment.allocateNative(4, scope); + segment.setUtf8String(0, "str"); + return segment.address(); + }, "str", VaList.Builder::addVarg), + CHAR(byte.class, C_CHAR, "%c", scope -> (byte) 'h', 'h', (builder, layout, value) -> builder.addVarg(C_INT, (int)value)), + DOUBLE(double.class, C_DOUBLE, "%.4f", scope ->1.2345d, 1.2345d, VaList.Builder::addVarg); final Class<?> carrier; final ValueLayout layout; @@ -414,7 +408,7 @@ public class StdLibTest { @SuppressWarnings("rawtypes") final VaListBuilderCall builderCall; - <Z> PrintfArg(Class<?> carrier, ValueLayout layout, String format, Function<ResourceScope, Z> nativeValueFactory, Object javaValue, VaListBuilderCall<Z> builderCall) { + <Z, L extends ValueLayout> PrintfArg(Class<?> carrier, L layout, String format, Function<ResourceScope, Z> nativeValueFactory, Object javaValue, VaListBuilderCall<Z, L> builderCall) { this.carrier = carrier; this.layout = layout; this.format = format; @@ -429,8 +423,8 @@ public class StdLibTest { builderCall.build(builder, layout, nativeValueFactory.apply(scope)); } - interface VaListBuilderCall<V> { - void build(VaList.Builder builder, ValueLayout layout, V value); + interface VaListBuilderCall<V, L> { + void build(VaList.Builder builder, L layout, V value); } public Object nativeValue(ResourceScope scope) { diff --git a/test/jdk/java/foreign/TestAdaptVarHandles.java b/test/jdk/java/foreign/TestAdaptVarHandles.java index de88626948a6841cf7f2624f25fe37371f4b36f9..9c0e6c0e5543027a8a8b937c232d02266bcc8998 100644 --- a/test/jdk/java/foreign/TestAdaptVarHandles.java +++ b/test/jdk/java/foreign/TestAdaptVarHandles.java @@ -32,7 +32,6 @@ import jdk.incubator.foreign.MemoryHandles; import jdk.incubator.foreign.MemoryLayout; -import jdk.incubator.foreign.MemoryLayouts; import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; import jdk.incubator.foreign.ValueLayout; @@ -86,18 +85,18 @@ public class TestAdaptVarHandles { } } - static final VarHandle intHandleIndexed = MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_INT) - .varHandle(int.class, MemoryLayout.PathElement.sequenceElement()); + static final VarHandle intHandleIndexed = MemoryLayout.sequenceLayout(ValueLayout.JAVA_INT) + .varHandle(MemoryLayout.PathElement.sequenceElement()); - static final VarHandle intHandle = MemoryLayouts.JAVA_INT.varHandle(int.class); + static final VarHandle intHandle = ValueLayout.JAVA_INT.varHandle(); - static final VarHandle floatHandle = MemoryLayouts.JAVA_FLOAT.varHandle(float.class); + static final VarHandle floatHandle = ValueLayout.JAVA_FLOAT.varHandle(); @Test public void testFilterValue() throws Throwable { - ValueLayout layout = MemoryLayouts.JAVA_INT; + ValueLayout layout = ValueLayout.JAVA_INT; MemorySegment segment = MemorySegment.allocateNative(layout, ResourceScope.newImplicitScope()); - VarHandle intHandle = layout.varHandle(int.class); + VarHandle intHandle = layout.varHandle(); VarHandle i2SHandle = MemoryHandles.filterValue(intHandle, S2I, I2S); i2SHandle.set(segment, "1"); String oldValue = (String)i2SHandle.getAndAdd(segment, "42"); @@ -114,9 +113,9 @@ public class TestAdaptVarHandles { @Test public void testFilterValueComposite() throws Throwable { - ValueLayout layout = MemoryLayouts.JAVA_INT; + ValueLayout layout = ValueLayout.JAVA_INT; MemorySegment segment = MemorySegment.allocateNative(layout, ResourceScope.newImplicitScope()); - VarHandle intHandle = layout.varHandle(int.class); + VarHandle intHandle = layout.varHandle(); MethodHandle CTX_S2I = MethodHandles.dropArguments(S2I, 0, String.class, String.class); VarHandle i2SHandle = MemoryHandles.filterValue(intHandle, CTX_S2I, CTX_I2S); i2SHandle = MemoryHandles.insertCoordinates(i2SHandle, 1, "a", "b"); @@ -135,9 +134,9 @@ public class TestAdaptVarHandles { @Test public void testFilterValueLoose() throws Throwable { - ValueLayout layout = MemoryLayouts.JAVA_INT; + ValueLayout layout = ValueLayout.JAVA_INT; MemorySegment segment = MemorySegment.allocateNative(layout, ResourceScope.newImplicitScope()); - VarHandle intHandle = layout.varHandle(int.class); + VarHandle intHandle = layout.varHandle(); VarHandle i2SHandle = MemoryHandles.filterValue(intHandle, O2I, I2O); i2SHandle.set(segment, "1"); String oldValue = (String)i2SHandle.getAndAdd(segment, "42"); @@ -159,19 +158,19 @@ public class TestAdaptVarHandles { @Test(expectedExceptions = IllegalArgumentException.class) public void testBadFilterUnboxArity() { - VarHandle floatHandle = MemoryLayouts.JAVA_INT.varHandle(int.class); + VarHandle floatHandle = ValueLayout.JAVA_INT.varHandle(); MemoryHandles.filterValue(floatHandle, S2I.bindTo(""), I2S); } @Test(expectedExceptions = IllegalArgumentException.class) public void testBadFilterBoxArity() { - VarHandle intHandle = MemoryLayouts.JAVA_INT.varHandle(int.class); + VarHandle intHandle = ValueLayout.JAVA_INT.varHandle(); MemoryHandles.filterValue(intHandle, S2I, I2S.bindTo(42)); } @Test(expectedExceptions = IllegalArgumentException.class) public void testBadFilterBoxPrefixCoordinates() { - VarHandle intHandle = MemoryLayouts.JAVA_INT.varHandle(int.class); + VarHandle intHandle = ValueLayout.JAVA_INT.varHandle(); MemoryHandles.filterValue(intHandle, MethodHandles.dropArguments(S2I, 1, int.class), MethodHandles.dropArguments(I2S, 1, long.class)); @@ -179,31 +178,40 @@ public class TestAdaptVarHandles { @Test(expectedExceptions = IllegalArgumentException.class) public void testBadFilterBoxException() { - VarHandle intHandle = MemoryLayouts.JAVA_INT.varHandle(int.class); + VarHandle intHandle = ValueLayout.JAVA_INT.varHandle(); MemoryHandles.filterValue(intHandle, I2S, S2L_EX); } @Test(expectedExceptions = IllegalArgumentException.class) public void testBadFilterUnboxException() { - VarHandle intHandle = MemoryLayouts.JAVA_INT.varHandle(int.class); + VarHandle intHandle = ValueLayout.JAVA_INT.varHandle(); MemoryHandles.filterValue(intHandle, S2L_EX, I2S); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test(expectedExceptions = IllegalStateException.class) public void testBadFilterBoxHandleException() { - VarHandle intHandle = MemoryLayouts.JAVA_INT.varHandle(int.class); - MemoryHandles.filterValue(intHandle, S2I, I2S_EX); + VarHandle intHandle = ValueLayout.JAVA_INT.varHandle(); + VarHandle vh = MemoryHandles.filterValue(intHandle, S2I, I2S_EX); + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemorySegment seg = MemorySegment.allocateNative(ValueLayout.JAVA_INT, scope); + vh.set(seg, "42"); + String x = (String) vh.get(seg); // should throw + } } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test(expectedExceptions = IllegalStateException.class) public void testBadFilterUnboxHandleException() { - VarHandle intHandle = MemoryLayouts.JAVA_INT.varHandle(int.class); - MemoryHandles.filterValue(intHandle, S2I_EX, I2S); + VarHandle intHandle = ValueLayout.JAVA_INT.varHandle(); + VarHandle vh = MemoryHandles.filterValue(intHandle, S2I_EX, I2S); + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemorySegment seg = MemorySegment.allocateNative(ValueLayout.JAVA_INT, scope); + vh.set(seg, "42"); // should throw + } } @Test public void testFilterCoordinates() throws Throwable { - ValueLayout layout = MemoryLayouts.JAVA_INT; + ValueLayout layout = ValueLayout.JAVA_INT; MemorySegment segment = MemorySegment.allocateNative(layout, ResourceScope.newImplicitScope()); VarHandle intHandle_longIndex = MemoryHandles.filterCoordinates(intHandleIndexed, 0, BASE_ADDR, S2L); intHandle_longIndex.set(segment, "0", 1); @@ -246,7 +254,7 @@ public class TestAdaptVarHandles { @Test public void testInsertCoordinates() throws Throwable { - ValueLayout layout = MemoryLayouts.JAVA_INT; + ValueLayout layout = ValueLayout.JAVA_INT; MemorySegment segment = MemorySegment.allocateNative(layout, ResourceScope.newImplicitScope()); VarHandle intHandle_longIndex = MemoryHandles.insertCoordinates(intHandleIndexed, 0, segment, 0L); intHandle_longIndex.set(1); @@ -284,7 +292,7 @@ public class TestAdaptVarHandles { @Test public void testPermuteCoordinates() throws Throwable { - ValueLayout layout = MemoryLayouts.JAVA_INT; + ValueLayout layout = ValueLayout.JAVA_INT; MemorySegment segment = MemorySegment.allocateNative(layout, ResourceScope.newImplicitScope()); VarHandle intHandle_swap = MemoryHandles.permuteCoordinates(intHandleIndexed, List.of(long.class, MemorySegment.class), 1, 0); @@ -323,7 +331,7 @@ public class TestAdaptVarHandles { @Test public void testCollectCoordinates() throws Throwable { - ValueLayout layout = MemoryLayouts.JAVA_INT; + ValueLayout layout = ValueLayout.JAVA_INT; MemorySegment segment = MemorySegment.allocateNative(layout, ResourceScope.newImplicitScope()); VarHandle intHandle_sum = MemoryHandles.collectCoordinates(intHandleIndexed, 1, SUM_OFFSETS); intHandle_sum.set(segment, -2L, 2L, 1); @@ -366,7 +374,7 @@ public class TestAdaptVarHandles { @Test public void testDropCoordinates() throws Throwable { - ValueLayout layout = MemoryLayouts.JAVA_INT; + ValueLayout layout = ValueLayout.JAVA_INT; MemorySegment segment = MemorySegment.allocateNative(layout, ResourceScope.newImplicitScope()); VarHandle intHandle_dummy = MemoryHandles.dropCoordinates(intHandleIndexed, 1, float.class, String.class); intHandle_dummy.set(segment, 1f, "hello", 0L, 1); diff --git a/test/jdk/java/foreign/TestAddressHandle.java b/test/jdk/java/foreign/TestAddressHandle.java deleted file mode 100644 index de9bde07a5b26cdfb94fe181dc2733da07332154..0000000000000000000000000000000000000000 --- a/test/jdk/java/foreign/TestAddressHandle.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -/* - * @test - * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=true -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=false -Xverify:all TestAddressHandle - * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=true -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=true -Xverify:all TestAddressHandle - * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=false -Xverify:all TestAddressHandle - * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=true -Xverify:all TestAddressHandle - */ - -import java.lang.invoke.*; -import java.nio.ByteOrder; -import jdk.incubator.foreign.*; - -import org.testng.annotations.*; -import static org.testng.Assert.*; - -public class TestAddressHandle { - - static final MethodHandle INT_TO_BOOL; - static final MethodHandle BOOL_TO_INT; - static final MethodHandle INT_TO_STRING; - static final MethodHandle STRING_TO_INT; - - static { - try { - INT_TO_BOOL = MethodHandles.lookup().findStatic(TestAddressHandle.class, "intToBool", - MethodType.methodType(boolean.class, int.class)); - BOOL_TO_INT = MethodHandles.lookup().findStatic(TestAddressHandle.class, "boolToInt", - MethodType.methodType(int.class, boolean.class)); - INT_TO_STRING = MethodHandles.lookup().findStatic(TestAddressHandle.class, "intToString", - MethodType.methodType(String.class, int.class)); - STRING_TO_INT = MethodHandles.lookup().findStatic(TestAddressHandle.class, "stringToInt", - MethodType.methodType(int.class, String.class)); - } catch (Throwable ex) { - throw new ExceptionInInitializerError(ex); - } - } - - @Test(dataProvider = "addressHandles") - public void testAddressHandle(VarHandle addrHandle, int byteSize) { - VarHandle longHandle = MemoryLayouts.JAVA_LONG.varHandle(long.class); - try (ResourceScope scope = ResourceScope.newConfinedScope()) { - MemorySegment segment = MemorySegment.allocateNative(8, scope); - MemorySegment target = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN ? - segment.asSlice(8 - byteSize) : - segment; - longHandle.set(segment, 42L); - MemoryAddress address = (MemoryAddress)addrHandle.get(target); - assertEquals(address.toRawLongValue(), 42L); - addrHandle.set(target, address.addOffset(1)); - long result = (long)longHandle.get(segment); - assertEquals(43L, result); - } - } - - @Test(dataProvider = "addressHandles") - public void testNull(VarHandle addrHandle, int byteSize) { - VarHandle longHandle = MemoryLayouts.JAVA_LONG.varHandle(long.class); - try (ResourceScope scope = ResourceScope.newConfinedScope()) { - MemorySegment segment = MemorySegment.allocateNative(8, scope); - longHandle.set(segment, 0L); - MemoryAddress address = (MemoryAddress)addrHandle.get(segment); - assertTrue(address == MemoryAddress.NULL); - } - } - - @Test(expectedExceptions = IllegalArgumentException.class) - public void testBadAdaptFloat() { - VarHandle floatHandle = MemoryLayouts.JAVA_FLOAT.varHandle(float.class); - MemoryHandles.asAddressVarHandle(floatHandle); - } - - @Test(expectedExceptions = IllegalArgumentException.class) - public void testBadAdaptDouble() { - VarHandle doubleHandle = MemoryLayouts.JAVA_DOUBLE.varHandle(double.class); - MemoryHandles.asAddressVarHandle(doubleHandle); - } - - @Test(expectedExceptions = IllegalArgumentException.class) - public void testBadAdaptBoolean() { - VarHandle intHandle = MemoryLayouts.JAVA_INT.varHandle(int.class); - VarHandle boolHandle = MemoryHandles.filterValue(intHandle, BOOL_TO_INT, INT_TO_BOOL); - MemoryHandles.asAddressVarHandle(boolHandle); - } - - @Test(expectedExceptions = IllegalArgumentException.class) - public void testBadAdaptString() { - VarHandle intHandle = MemoryLayouts.JAVA_INT.varHandle(int.class); - VarHandle stringHandle = MemoryHandles.filterValue(intHandle, STRING_TO_INT, INT_TO_STRING); - MemoryHandles.asAddressVarHandle(stringHandle); - } - - @DataProvider(name = "addressHandles") - static Object[][] addressHandles() { - return new Object[][] { - // long - { MemoryHandles.asAddressVarHandle(at(MemoryHandles.varHandle(long.class, ByteOrder.nativeOrder()), 0)), 8 }, - { MemoryHandles.asAddressVarHandle(MemoryLayouts.JAVA_LONG.varHandle(long.class)), 8 }, - - // int - { MemoryHandles.asAddressVarHandle(at(MemoryHandles.varHandle(int.class, ByteOrder.nativeOrder()), 0)), 4 }, - { MemoryHandles.asAddressVarHandle(MemoryLayouts.JAVA_INT.varHandle(int.class)), 4 }, - - // short - { MemoryHandles.asAddressVarHandle(at(MemoryHandles.varHandle(short.class, ByteOrder.nativeOrder()), 0)), 2 }, - { MemoryHandles.asAddressVarHandle(MemoryLayouts.JAVA_SHORT.varHandle(short.class)), 2 }, - - // char - { MemoryHandles.asAddressVarHandle(at(MemoryHandles.varHandle(char.class, ByteOrder.nativeOrder()), 0)), 2 }, - { MemoryHandles.asAddressVarHandle(MemoryLayouts.JAVA_CHAR.varHandle(char.class)), 2 }, - - // byte - { MemoryHandles.asAddressVarHandle(at(MemoryHandles.varHandle(byte.class, ByteOrder.nativeOrder()), 0)), 1 }, - { MemoryHandles.asAddressVarHandle(MemoryLayouts.JAVA_BYTE.varHandle(byte.class)), 1 } - }; - } - - static VarHandle at(VarHandle handle, long offset) { - return MemoryHandles.insertCoordinates(handle, 1, offset); - } - - static int boolToInt(boolean value) { - return value ? 1 : 0; - } - - static boolean intToBool(int value) { - return value != 0; - } - - static int stringToInt(String value) { - return value.length(); - } - - static String intToString(int value) { - return String.valueOf(value); - } -} diff --git a/test/jdk/java/foreign/TestArrayCopy.java b/test/jdk/java/foreign/TestArrayCopy.java new file mode 100644 index 0000000000000000000000000000000000000000..b8a36307fdeec1040cc3b56690c791409cd6874f --- /dev/null +++ b/test/jdk/java/foreign/TestArrayCopy.java @@ -0,0 +1,542 @@ +/* + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @run testng TestArrayCopy + */ + +import static jdk.incubator.foreign.ValueLayout.JAVA_BYTE; +import static jdk.incubator.foreign.ValueLayout.JAVA_INT; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.fail; + +import java.lang.invoke.VarHandle; +import java.nio.ByteOrder; +import java.util.ArrayList; +import java.util.List; + +import jdk.incubator.foreign.MemoryLayout; +import jdk.incubator.foreign.MemorySegment; + +import jdk.incubator.foreign.ValueLayout; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +/** + * These tests exercise the MemoryCopy copyFromArray(...) and copyToArray(...). + * To make these tests more challenging the segment is a view of the given array, + * which makes the copy operations overlapping self-copies. Thus, this checks the claim: + * + * <p>If the source (destination) segment is actually a view of the destination (source) array, + * and if the copy region of the source overlaps with the copy region of the destination, + * the copy of the overlapping region is performed as if the data in the overlapping region + * were first copied into a temporary segment before being copied to the destination.</p> + */ +public class TestArrayCopy { + private static final ByteOrder NATIVE_ORDER = ByteOrder.nativeOrder(); + private static final ByteOrder NON_NATIVE_ORDER = NATIVE_ORDER == ByteOrder.LITTLE_ENDIAN + ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN; + + private static final int SEG_LENGTH_BYTES = 32; + private static final int SEG_OFFSET_BYTES = 8; + + @Test(dataProvider = "copyModesAndHelpers") + public void testSelfCopy(CopyMode mode, CopyHelper<Object, ValueLayout> helper, String helperDebugString) { + int bytesPerElement = (int)helper.elementLayout.byteSize(); + int indexShifts = SEG_OFFSET_BYTES / bytesPerElement; + MemorySegment base = srcSegment(SEG_LENGTH_BYTES); + MemorySegment truth = truthSegment(base, helper, indexShifts, mode); + ByteOrder bo = mode.swap ? NON_NATIVE_ORDER : NATIVE_ORDER; + //CopyFrom + Object srcArr = helper.toArray(base); + int srcIndex = mode.direction ? 0 : indexShifts; + int srcCopyLen = helper.length(srcArr) - indexShifts; + MemorySegment dstSeg = helper.fromArray(srcArr); + long dstOffsetBytes = mode.direction ? SEG_OFFSET_BYTES : 0; + helper.copyFromArray(srcArr, srcIndex, srcCopyLen, dstSeg, dstOffsetBytes, bo); + assertEquals(truth.mismatch(dstSeg), -1); + //CopyTo + long srcOffsetBytes = mode.direction ? 0 : SEG_OFFSET_BYTES; + Object dstArr = helper.toArray(base); + MemorySegment srcSeg = helper.fromArray(dstArr).asReadOnly(); + int dstIndex = mode.direction ? indexShifts : 0; + int dstCopyLen = helper.length(dstArr) - indexShifts; + helper.copyToArray(srcSeg, srcOffsetBytes, dstArr, dstIndex, dstCopyLen, bo); + MemorySegment result = helper.fromArray(dstArr); + assertEquals(truth.mismatch(result), -1); + } + + @Test(dataProvider = "copyModesAndHelpers") + public void testUnalignedCopy(CopyMode mode, CopyHelper<Object, ValueLayout> helper, String helperDebugString) { + int bytesPerElement = (int)helper.elementLayout.byteSize(); + int indexShifts = SEG_OFFSET_BYTES / bytesPerElement; + MemorySegment base = srcSegment(SEG_LENGTH_BYTES); + ByteOrder bo = mode.swap ? NON_NATIVE_ORDER : NATIVE_ORDER; + //CopyFrom + Object srcArr = helper.toArray(base); + int srcIndex = mode.direction ? 0 : indexShifts; + int srcCopyLen = helper.length(srcArr) - indexShifts; + MemorySegment dstSeg = helper.fromArray(srcArr); + long dstOffsetBytes = mode.direction ? (SEG_OFFSET_BYTES - 1) : 0; + helper.copyFromArray(srcArr, srcIndex, srcCopyLen, dstSeg, dstOffsetBytes, bo); + //CopyTo + long srcOffsetBytes = mode.direction ? 0 : (SEG_OFFSET_BYTES - 1); + Object dstArr = helper.toArray(base); + MemorySegment srcSeg = helper.fromArray(dstArr).asReadOnly(); + int dstIndex = mode.direction ? indexShifts : 0; + int dstCopyLen = helper.length(dstArr) - indexShifts; + helper.copyToArray(srcSeg, srcOffsetBytes, dstArr, dstIndex, dstCopyLen, bo); + } + + @Test(dataProvider = "copyModesAndHelpers") + public void testCopyOobLength(CopyMode mode, CopyHelper<Object, ValueLayout> helper, String helperDebugString) { + int bytesPerElement = (int)helper.elementLayout.byteSize(); + MemorySegment base = srcSegment(SEG_LENGTH_BYTES); + //CopyFrom + Object srcArr = helper.toArray(base); + MemorySegment dstSeg = helper.fromArray(srcArr); + try { + helper.copyFromArray(srcArr, 0, (SEG_LENGTH_BYTES / bytesPerElement) * 2, dstSeg, 0, ByteOrder.nativeOrder()); + fail(); + } catch (IndexOutOfBoundsException ex) { + //ok + } + //CopyTo + Object dstArr = helper.toArray(base); + MemorySegment srcSeg = helper.fromArray(dstArr).asReadOnly(); + try { + helper.copyToArray(srcSeg, 0, dstArr, 0, (SEG_LENGTH_BYTES / bytesPerElement) * 2, ByteOrder.nativeOrder()); + fail(); + } catch (IndexOutOfBoundsException ex) { + //ok + } + } + + @Test(dataProvider = "copyModesAndHelpers") + public void testCopyNegativeIndices(CopyMode mode, CopyHelper<Object, ValueLayout> helper, String helperDebugString) { + int bytesPerElement = (int)helper.elementLayout.byteSize(); + MemorySegment base = srcSegment(SEG_LENGTH_BYTES); + //CopyFrom + Object srcArr = helper.toArray(base); + MemorySegment dstSeg = helper.fromArray(srcArr); + try { + helper.copyFromArray(srcArr, -1, SEG_LENGTH_BYTES / bytesPerElement, dstSeg, 0, ByteOrder.nativeOrder()); + fail(); + } catch (IndexOutOfBoundsException ex) { + //ok + } + //CopyTo + Object dstArr = helper.toArray(base); + MemorySegment srcSeg = helper.fromArray(dstArr).asReadOnly(); + try { + helper.copyToArray(srcSeg, 0, dstArr, -1, SEG_LENGTH_BYTES / bytesPerElement, ByteOrder.nativeOrder()); + fail(); + } catch (IndexOutOfBoundsException ex) { + //ok + } + } + + @Test(dataProvider = "copyModesAndHelpers") + public void testCopyNegativeOffsets(CopyMode mode, CopyHelper<Object, ValueLayout> helper, String helperDebugString) { + int bytesPerElement = (int)helper.elementLayout.byteSize(); + MemorySegment base = srcSegment(SEG_LENGTH_BYTES); + //CopyFrom + Object srcArr = helper.toArray(base); + MemorySegment dstSeg = helper.fromArray(srcArr); + try { + helper.copyFromArray(srcArr, 0, SEG_LENGTH_BYTES / bytesPerElement, dstSeg, -1, ByteOrder.nativeOrder()); + fail(); + } catch (IndexOutOfBoundsException ex) { + //ok + } + //CopyTo + Object dstArr = helper.toArray(base); + MemorySegment srcSeg = helper.fromArray(dstArr).asReadOnly(); + try { + helper.copyToArray(srcSeg, -1, dstArr, 0, SEG_LENGTH_BYTES / bytesPerElement, ByteOrder.nativeOrder()); + fail(); + } catch (IndexOutOfBoundsException ex) { + //ok + } + } + + @Test(dataProvider = "copyModesAndHelpers") + public void testCopyOobIndices(CopyMode mode, CopyHelper<Object, ValueLayout> helper, String helperDebugString) { + int bytesPerElement = (int)helper.elementLayout.byteSize(); + MemorySegment base = srcSegment(SEG_LENGTH_BYTES); + //CopyFrom + Object srcArr = helper.toArray(base); + MemorySegment dstSeg = helper.fromArray(srcArr); + try { + helper.copyFromArray(srcArr, helper.length(srcArr) + 1, SEG_LENGTH_BYTES / bytesPerElement, dstSeg, 0, ByteOrder.nativeOrder()); + fail(); + } catch (IndexOutOfBoundsException ex) { + //ok + } + //CopyTo + Object dstArr = helper.toArray(base); + MemorySegment srcSeg = helper.fromArray(dstArr).asReadOnly(); + try { + helper.copyToArray(srcSeg, 0, dstArr, helper.length(dstArr) + 1, SEG_LENGTH_BYTES / bytesPerElement, ByteOrder.nativeOrder()); + fail(); + } catch (IndexOutOfBoundsException ex) { + //ok + } + } + + @Test(dataProvider = "copyModesAndHelpers") + public void testCopyOobOffsets(CopyMode mode, CopyHelper<Object, ValueLayout> helper, String helperDebugString) { + int bytesPerElement = (int)helper.elementLayout.byteSize(); + MemorySegment base = srcSegment(SEG_LENGTH_BYTES); + //CopyFrom + Object srcArr = helper.toArray(base); + MemorySegment dstSeg = helper.fromArray(srcArr); + try { + helper.copyFromArray(srcArr, 0, SEG_LENGTH_BYTES / bytesPerElement, dstSeg, SEG_LENGTH_BYTES + 1, ByteOrder.nativeOrder()); + fail(); + } catch (IndexOutOfBoundsException ex) { + //ok + } + //CopyTo + Object dstArr = helper.toArray(base); + MemorySegment srcSeg = helper.fromArray(dstArr).asReadOnly(); + try { + helper.copyToArray(srcSeg, SEG_OFFSET_BYTES + 1, dstArr, 0, SEG_LENGTH_BYTES / bytesPerElement, ByteOrder.nativeOrder()); + fail(); + } catch (IndexOutOfBoundsException ex) { + //ok + } + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testNotAnArraySrc() { + MemorySegment segment = MemorySegment.ofArray(new int[] {1, 2, 3, 4}); + MemorySegment.copy(segment, JAVA_BYTE, 0, new String[] { "hello" }, 0, 4); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testNotAnArrayDst() { + MemorySegment segment = MemorySegment.ofArray(new int[] {1, 2, 3, 4}); + MemorySegment.copy(new String[] { "hello" }, 0, segment, JAVA_BYTE, 0, 4); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testCarrierMismatchSrc() { + MemorySegment segment = MemorySegment.ofArray(new int[] {1, 2, 3, 4}); + MemorySegment.copy(segment, JAVA_INT, 0, new byte[] { 1, 2, 3, 4 }, 0, 4); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testCarrierMismatchDst() { + MemorySegment segment = MemorySegment.ofArray(new int[] {1, 2, 3, 4}); + MemorySegment.copy(new byte[] { 1, 2, 3, 4 }, 0, segment, JAVA_INT, 0, 4); + } + + /***** Utilities *****/ + + public static MemorySegment srcSegment(int bytesLength) { + byte[] arr = new byte[bytesLength]; + for (int i = 0; i < arr.length; i++) { + arr[i] = (byte)i; + } + return MemorySegment.ofArray(arr); + } + + public static MemorySegment truthSegment(MemorySegment srcSeg, CopyHelper<?, ?> helper, int indexShifts, CopyMode mode) { + VarHandle indexedHandleNO = MemoryLayout.sequenceLayout(helper.elementLayout.withOrder(NATIVE_ORDER)) + .varHandle(MemoryLayout.PathElement.sequenceElement()); + VarHandle indexedHandleNNO = MemoryLayout.sequenceLayout(helper.elementLayout.withOrder(NON_NATIVE_ORDER)) + .varHandle(MemoryLayout.PathElement.sequenceElement()); + MemorySegment dstSeg = MemorySegment.ofArray(srcSeg.toArray(JAVA_BYTE)); + int indexLength = (int) dstSeg.byteSize() / (int)helper.elementLayout.byteSize(); + if (mode.direction) { + if (mode.swap) { + for (int i = indexLength - 1; i >= indexShifts; i--) { + Object v = indexedHandleNNO.get(dstSeg, i - indexShifts); + indexedHandleNO.set(dstSeg, i, v); + } + } else { + for (int i = indexLength - 1; i >= indexShifts; i--) { + Object v = indexedHandleNO.get(dstSeg, i - indexShifts); + indexedHandleNO.set(dstSeg, i, v); + } + } + } else { //down + if (mode.swap) { + for (int i = indexShifts; i < indexLength; i++) { + Object v = indexedHandleNNO.get(dstSeg, i); + indexedHandleNO.set(dstSeg, i - indexShifts, v); + } + } else { + for (int i = indexShifts; i < indexLength; i++) { + Object v = indexedHandleNO.get(dstSeg, i); + indexedHandleNO.set(dstSeg, i - indexShifts, v); + } + } + } + return dstSeg; + } + + enum CopyMode { + UP_NO_SWAP(true, false), + UP_SWAP(true, true), + DOWN_NO_SWAP(false, false), + DOWN_SWAP(false, true); + + final boolean direction; + final boolean swap; + + CopyMode(boolean direction, boolean swap) { + this.direction = direction; + this.swap = swap; + } + } + + abstract static class CopyHelper<X, L extends ValueLayout> { + + final L elementLayout; + final Class<?> carrier; + + public CopyHelper(L elementLayout, Class<X> carrier) { + this.elementLayout = elementLayout; + this.carrier = carrier; + } + + abstract void copyFromArray(X srcArr, int srcIndex, int srcCopyLen, MemorySegment dstSeg, long dstOffsetBytes, ByteOrder bo); + abstract void copyToArray(MemorySegment srcSeg, long srcOffsetBytes, X dstArr, int dstIndex, int dstCopyLen, ByteOrder bo); + abstract X toArray(MemorySegment segment); + abstract MemorySegment fromArray(X array); + abstract int length(X arr); + + @Override + public String toString() { + return "CopyHelper{" + + "elementLayout=" + elementLayout + + ", carrier=" + carrier.getName() + + '}'; + } + + static final CopyHelper<byte[], ValueLayout.OfByte> BYTE = new CopyHelper<>(JAVA_BYTE, byte[].class) { + @Override + void copyFromArray(byte[] srcArr, int srcIndex, int srcCopyLen, MemorySegment dstSeg, long dstOffsetBytes, ByteOrder bo) { + MemorySegment.copy(srcArr, srcIndex, dstSeg, elementLayout.withOrder(bo), dstOffsetBytes, srcCopyLen); + } + + @Override + void copyToArray(MemorySegment srcSeg, long srcOffsetBytes, byte[] dstArr, int dstIndex, int dstCopyLen, ByteOrder bo) { + MemorySegment.copy(srcSeg, elementLayout.withOrder(bo), srcOffsetBytes, dstArr, dstIndex, dstCopyLen); + } + + @Override + byte[] toArray(MemorySegment segment) { + return segment.toArray(elementLayout); + } + + @Override + MemorySegment fromArray(byte[] array) { + return MemorySegment.ofArray(array); + } + + @Override + int length(byte[] arr) { + return arr.length; + } + }; + + static final CopyHelper<char[], ValueLayout.OfChar> CHAR = new CopyHelper<>(ValueLayout.JAVA_CHAR, char[].class) { + @Override + void copyFromArray(char[] srcArr, int srcIndex, int srcCopyLen, MemorySegment dstSeg, long dstOffsetBytes, ByteOrder bo) { + MemorySegment.copy(srcArr, srcIndex, dstSeg, elementLayout.withOrder(bo), dstOffsetBytes, srcCopyLen); + } + + @Override + void copyToArray(MemorySegment srcSeg, long srcOffsetBytes, char[] dstArr, int dstIndex, int dstCopyLen, ByteOrder bo) { + MemorySegment.copy(srcSeg, elementLayout.withOrder(bo), srcOffsetBytes, dstArr, dstIndex, dstCopyLen); + } + + @Override + char[] toArray(MemorySegment segment) { + return segment.toArray(elementLayout); + } + + @Override + MemorySegment fromArray(char[] array) { + return MemorySegment.ofArray(array); + } + + @Override + int length(char[] arr) { + return arr.length; + } + }; + + static final CopyHelper<short[], ValueLayout.OfShort> SHORT = new CopyHelper<>(ValueLayout.JAVA_SHORT, short[].class) { + @Override + void copyFromArray(short[] srcArr, int srcIndex, int srcCopyLen, MemorySegment dstSeg, long dstOffsetBytes, ByteOrder bo) { + MemorySegment.copy(srcArr, srcIndex, dstSeg, elementLayout.withOrder(bo), dstOffsetBytes, srcCopyLen); + } + + @Override + void copyToArray(MemorySegment srcSeg, long srcOffsetBytes, short[] dstArr, int dstIndex, int dstCopyLen, ByteOrder bo) { + MemorySegment.copy(srcSeg, elementLayout.withOrder(bo), srcOffsetBytes, dstArr, dstIndex, dstCopyLen); + } + + @Override + short[] toArray(MemorySegment segment) { + return segment.toArray(elementLayout); + } + + @Override + MemorySegment fromArray(short[] array) { + return MemorySegment.ofArray(array); + } + + @Override + int length(short[] arr) { + return arr.length; + } + }; + + static final CopyHelper<int[], ValueLayout.OfInt> INT = new CopyHelper<>(ValueLayout.JAVA_INT, int[].class) { + @Override + void copyFromArray(int[] srcArr, int srcIndex, int srcCopyLen, MemorySegment dstSeg, long dstOffsetBytes, ByteOrder bo) { + MemorySegment.copy(srcArr, srcIndex, dstSeg, elementLayout.withOrder(bo), dstOffsetBytes, srcCopyLen); + } + + @Override + void copyToArray(MemorySegment srcSeg, long srcOffsetBytes, int[] dstArr, int dstIndex, int dstCopyLen, ByteOrder bo) { + MemorySegment.copy(srcSeg, elementLayout.withOrder(bo), srcOffsetBytes, dstArr, dstIndex, dstCopyLen); + } + + @Override + int[] toArray(MemorySegment segment) { + return segment.toArray(elementLayout); + } + + @Override + MemorySegment fromArray(int[] array) { + return MemorySegment.ofArray(array); + } + + @Override + int length(int[] arr) { + return arr.length; + } + }; + + static final CopyHelper<float[], ValueLayout.OfFloat> FLOAT = new CopyHelper<>(ValueLayout.JAVA_FLOAT, float[].class) { + @Override + void copyFromArray(float[] srcArr, int srcIndex, int srcCopyLen, MemorySegment dstSeg, long dstOffsetBytes, ByteOrder bo) { + MemorySegment.copy(srcArr, srcIndex, dstSeg, elementLayout.withOrder(bo), dstOffsetBytes, srcCopyLen); + } + + @Override + void copyToArray(MemorySegment srcSeg, long srcOffsetBytes, float[] dstArr, int dstIndex, int dstCopyLen, ByteOrder bo) { + MemorySegment.copy(srcSeg, elementLayout.withOrder(bo), srcOffsetBytes, dstArr, dstIndex, dstCopyLen); + } + + @Override + float[] toArray(MemorySegment segment) { + return segment.toArray(elementLayout); + } + + @Override + MemorySegment fromArray(float[] array) { + return MemorySegment.ofArray(array); + } + + @Override + int length(float[] arr) { + return arr.length; + } + }; + + static final CopyHelper<long[], ValueLayout.OfLong> LONG = new CopyHelper<>(ValueLayout.JAVA_LONG, long[].class) { + @Override + void copyFromArray(long[] srcArr, int srcIndex, int srcCopyLen, MemorySegment dstSeg, long dstOffsetBytes, ByteOrder bo) { + MemorySegment.copy(srcArr, srcIndex, dstSeg, elementLayout.withOrder(bo), dstOffsetBytes, srcCopyLen); + } + + @Override + void copyToArray(MemorySegment srcSeg, long srcOffsetBytes, long[] dstArr, int dstIndex, int dstCopyLen, ByteOrder bo) { + MemorySegment.copy(srcSeg, elementLayout.withOrder(bo), srcOffsetBytes, dstArr, dstIndex, dstCopyLen); + } + + @Override + long[] toArray(MemorySegment segment) { + return segment.toArray(elementLayout); + } + + @Override + MemorySegment fromArray(long[] array) { + return MemorySegment.ofArray(array); + } + + @Override + int length(long[] arr) { + return arr.length; + } + }; + + static final CopyHelper<double[], ValueLayout.OfDouble> DOUBLE = new CopyHelper<>(ValueLayout.JAVA_DOUBLE, double[].class) { + @Override + void copyFromArray(double[] srcArr, int srcIndex, int srcCopyLen, MemorySegment dstSeg, long dstOffsetBytes, ByteOrder bo) { + MemorySegment.copy(srcArr, srcIndex, dstSeg, elementLayout.withOrder(bo), dstOffsetBytes, srcCopyLen); + } + + @Override + void copyToArray(MemorySegment srcSeg, long srcOffsetBytes, double[] dstArr, int dstIndex, int dstCopyLen, ByteOrder bo) { + MemorySegment.copy(srcSeg, elementLayout.withOrder(bo), srcOffsetBytes, dstArr, dstIndex, dstCopyLen); + } + + @Override + double[] toArray(MemorySegment segment) { + return segment.toArray(elementLayout); + } + + @Override + MemorySegment fromArray(double[] array) { + return MemorySegment.ofArray(array); + } + + @Override + int length(double[] arr) { + return arr.length; + } + }; + } + + @DataProvider + Object[][] copyModesAndHelpers() { + CopyHelper<?, ?>[] helpers = { CopyHelper.BYTE, CopyHelper.CHAR, CopyHelper.SHORT, CopyHelper.INT, + CopyHelper.FLOAT, CopyHelper.LONG, CopyHelper.DOUBLE }; + List<Object[]> results = new ArrayList<>(); + for (CopyHelper<?, ?> helper : helpers) { + for (CopyMode mode : CopyMode.values()) { + results.add(new Object[] { mode, helper, helper.toString() }); + } + } + return results.stream().toArray(Object[][]::new); + } +} diff --git a/test/jdk/java/foreign/TestArrays.java b/test/jdk/java/foreign/TestArrays.java index 451beeb4544dc89b3b609ad207e6082ab745e66e..ca412554cb4271347d3175972b28bfbf438693f2 100644 --- a/test/jdk/java/foreign/TestArrays.java +++ b/test/jdk/java/foreign/TestArrays.java @@ -30,7 +30,6 @@ import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.MemoryLayout.PathElement; -import jdk.incubator.foreign.MemoryLayouts; import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; import jdk.incubator.foreign.SequenceLayout; @@ -43,45 +42,52 @@ import java.util.function.Function; import org.testng.annotations.*; +import static jdk.incubator.foreign.ValueLayout.JAVA_BYTE; +import static jdk.incubator.foreign.ValueLayout.JAVA_CHAR; +import static jdk.incubator.foreign.ValueLayout.JAVA_DOUBLE; +import static jdk.incubator.foreign.ValueLayout.JAVA_FLOAT; +import static jdk.incubator.foreign.ValueLayout.JAVA_INT; +import static jdk.incubator.foreign.ValueLayout.JAVA_LONG; +import static jdk.incubator.foreign.ValueLayout.JAVA_SHORT; import static org.testng.Assert.*; public class TestArrays { static SequenceLayout bytes = MemoryLayout.sequenceLayout(100, - MemoryLayouts.JAVA_BYTE + JAVA_BYTE ); static SequenceLayout chars = MemoryLayout.sequenceLayout(100, - MemoryLayouts.JAVA_CHAR + JAVA_CHAR ); static SequenceLayout shorts = MemoryLayout.sequenceLayout(100, - MemoryLayouts.JAVA_SHORT + JAVA_SHORT ); static SequenceLayout ints = MemoryLayout.sequenceLayout(100, - MemoryLayouts.JAVA_INT + JAVA_INT ); static SequenceLayout floats = MemoryLayout.sequenceLayout(100, - MemoryLayouts.JAVA_FLOAT + JAVA_FLOAT ); static SequenceLayout longs = MemoryLayout.sequenceLayout(100, - MemoryLayouts.JAVA_LONG + JAVA_LONG ); static SequenceLayout doubles = MemoryLayout.sequenceLayout(100, - MemoryLayouts.JAVA_DOUBLE + JAVA_DOUBLE ); - static VarHandle byteHandle = bytes.varHandle(byte.class, PathElement.sequenceElement()); - static VarHandle charHandle = chars.varHandle(char.class, PathElement.sequenceElement()); - static VarHandle shortHandle = shorts.varHandle(short.class, PathElement.sequenceElement()); - static VarHandle intHandle = ints.varHandle(int.class, PathElement.sequenceElement()); - static VarHandle floatHandle = floats.varHandle(float.class, PathElement.sequenceElement()); - static VarHandle longHandle = longs.varHandle(long.class, PathElement.sequenceElement()); - static VarHandle doubleHandle = doubles.varHandle(double.class, PathElement.sequenceElement()); + static VarHandle byteHandle = bytes.varHandle(PathElement.sequenceElement()); + static VarHandle charHandle = chars.varHandle(PathElement.sequenceElement()); + static VarHandle shortHandle = shorts.varHandle(PathElement.sequenceElement()); + static VarHandle intHandle = ints.varHandle(PathElement.sequenceElement()); + static VarHandle floatHandle = floats.varHandle(PathElement.sequenceElement()); + static VarHandle longHandle = longs.varHandle(PathElement.sequenceElement()); + static VarHandle doubleHandle = doubles.varHandle(PathElement.sequenceElement()); static void initBytes(MemorySegment base, SequenceLayout seq, BiConsumer<MemorySegment, Long> handleSetter) { for (long i = 0; i < seq.elementCount().getAsLong() ; i++) { @@ -112,7 +118,7 @@ public class TestArrays { public void testTooBigForArray(MemoryLayout layout, Function<MemorySegment, Object> arrayFactory) { MemoryLayout seq = MemoryLayout.sequenceLayout((Integer.MAX_VALUE * layout.byteSize()) + 1, layout); //do not really allocate here, as it's way too much memory - MemorySegment segment = MemoryAddress.NULL.asSegment(seq.byteSize(), ResourceScope.globalScope()); + MemorySegment segment = MemorySegment.ofAddress(MemoryAddress.NULL, seq.byteSize(), ResourceScope.globalScope()); arrayFactory.apply(segment); } @@ -152,19 +158,19 @@ public class TestArrays { (base) -> initBytes(base, doubles, (addr, pos) -> doubleHandle.set(addr, pos, (double)(long)pos)); Consumer<MemorySegment> byteChecker = - (base) -> checkBytes(base, bytes, MemorySegment::toByteArray, (addr, pos) -> (byte)byteHandle.get(addr, pos)); + (base) -> checkBytes(base, bytes, s -> s.toArray(JAVA_BYTE), (addr, pos) -> (byte)byteHandle.get(addr, pos)); Consumer<MemorySegment> shortChecker = - (base) -> checkBytes(base, shorts, MemorySegment::toShortArray, (addr, pos) -> (short)shortHandle.get(addr, pos)); + (base) -> checkBytes(base, shorts, s -> s.toArray(JAVA_SHORT), (addr, pos) -> (short)shortHandle.get(addr, pos)); Consumer<MemorySegment> charChecker = - (base) -> checkBytes(base, chars, MemorySegment::toCharArray, (addr, pos) -> (char)charHandle.get(addr, pos)); + (base) -> checkBytes(base, chars, s -> s.toArray(JAVA_CHAR), (addr, pos) -> (char)charHandle.get(addr, pos)); Consumer<MemorySegment> intChecker = - (base) -> checkBytes(base, ints, MemorySegment::toIntArray, (addr, pos) -> (int)intHandle.get(addr, pos)); + (base) -> checkBytes(base, ints, s -> s.toArray(JAVA_INT), (addr, pos) -> (int)intHandle.get(addr, pos)); Consumer<MemorySegment> floatChecker = - (base) -> checkBytes(base, floats, MemorySegment::toFloatArray, (addr, pos) -> (float)floatHandle.get(addr, pos)); + (base) -> checkBytes(base, floats, s -> s.toArray(JAVA_FLOAT), (addr, pos) -> (float)floatHandle.get(addr, pos)); Consumer<MemorySegment> longChecker = - (base) -> checkBytes(base, longs, MemorySegment::toLongArray, (addr, pos) -> (long)longHandle.get(addr, pos)); + (base) -> checkBytes(base, longs, s -> s.toArray(JAVA_LONG), (addr, pos) -> (long)longHandle.get(addr, pos)); Consumer<MemorySegment> doubleChecker = - (base) -> checkBytes(base, doubles, MemorySegment::toDoubleArray, (addr, pos) -> (double)doubleHandle.get(addr, pos)); + (base) -> checkBytes(base, doubles, s -> s.toArray(JAVA_DOUBLE), (addr, pos) -> (double)doubleHandle.get(addr, pos)); return new Object[][]{ {byteInitializer, byteChecker, bytes}, @@ -180,13 +186,13 @@ public class TestArrays { @DataProvider(name = "elemLayouts") public Object[][] elemLayouts() { return new Object[][] { - { MemoryLayouts.JAVA_BYTE, (Function<MemorySegment, Object>) MemorySegment::toByteArray }, - { MemoryLayouts.JAVA_SHORT, (Function<MemorySegment, Object>) MemorySegment::toShortArray }, - { MemoryLayouts.JAVA_CHAR, (Function<MemorySegment, Object>) MemorySegment::toCharArray }, - { MemoryLayouts.JAVA_INT, (Function<MemorySegment, Object>) MemorySegment::toIntArray }, - { MemoryLayouts.JAVA_FLOAT, (Function<MemorySegment, Object>) MemorySegment::toFloatArray }, - { MemoryLayouts.JAVA_LONG, (Function<MemorySegment, Object>) MemorySegment::toLongArray }, - { MemoryLayouts.JAVA_DOUBLE, (Function<MemorySegment, Object>) MemorySegment::toDoubleArray } + { JAVA_BYTE, (Function<MemorySegment, Object>)s -> s.toArray(JAVA_BYTE)}, + { JAVA_SHORT, (Function<MemorySegment, Object>) s -> s.toArray(JAVA_SHORT)}, + { JAVA_CHAR, (Function<MemorySegment, Object>) s -> s.toArray(JAVA_CHAR)}, + { JAVA_INT, (Function<MemorySegment, Object>)s -> s.toArray(JAVA_INT)}, + { JAVA_FLOAT, (Function<MemorySegment, Object>)s -> s.toArray(JAVA_FLOAT)}, + { JAVA_LONG, (Function<MemorySegment, Object>)s -> s.toArray(JAVA_LONG)}, + { JAVA_DOUBLE, (Function<MemorySegment, Object>)s -> s.toArray(JAVA_DOUBLE)} }; } } diff --git a/test/jdk/java/foreign/TestByteBuffer.java b/test/jdk/java/foreign/TestByteBuffer.java index cdc9addb38132ba361e4d1939294a334c940d8ca..57d953f771d9acc525258a9e5f6199c90f8a289f 100644 --- a/test/jdk/java/foreign/TestByteBuffer.java +++ b/test/jdk/java/foreign/TestByteBuffer.java @@ -28,8 +28,6 @@ * @run testng/othervm --enable-native-access=ALL-UNNAMED TestByteBuffer */ -import jdk.incubator.foreign.MemoryAccess; -import jdk.incubator.foreign.MemoryLayouts; import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemorySegment; @@ -82,6 +80,13 @@ import org.testng.SkipException; import org.testng.annotations.*; import sun.nio.ch.DirectBuffer; +import static jdk.incubator.foreign.ValueLayout.JAVA_BYTE; +import static jdk.incubator.foreign.ValueLayout.JAVA_CHAR; +import static jdk.incubator.foreign.ValueLayout.JAVA_DOUBLE; +import static jdk.incubator.foreign.ValueLayout.JAVA_FLOAT; +import static jdk.incubator.foreign.ValueLayout.JAVA_INT; +import static jdk.incubator.foreign.ValueLayout.JAVA_LONG; +import static jdk.incubator.foreign.ValueLayout.JAVA_SHORT; import static org.testng.Assert.*; public class TestByteBuffer { @@ -102,40 +107,40 @@ public class TestByteBuffer { static SequenceLayout tuples = MemoryLayout.sequenceLayout(500, MemoryLayout.structLayout( - MemoryLayouts.BITS_32_BE.withName("index"), - MemoryLayouts.BITS_32_BE.withName("value") + JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN).withName("index"), + JAVA_FLOAT.withOrder(ByteOrder.BIG_ENDIAN).withName("value") )); static SequenceLayout bytes = MemoryLayout.sequenceLayout(100, - MemoryLayouts.BITS_8_BE + JAVA_BYTE ); static SequenceLayout chars = MemoryLayout.sequenceLayout(100, - MemoryLayouts.BITS_16_BE + JAVA_CHAR.withOrder(ByteOrder.BIG_ENDIAN) ); static SequenceLayout shorts = MemoryLayout.sequenceLayout(100, - MemoryLayouts.BITS_16_BE + JAVA_SHORT.withOrder(ByteOrder.BIG_ENDIAN) ); static SequenceLayout ints = MemoryLayout.sequenceLayout(100, - MemoryLayouts.BITS_32_BE + JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN) ); static SequenceLayout floats = MemoryLayout.sequenceLayout(100, - MemoryLayouts.BITS_32_BE + JAVA_FLOAT.withOrder(ByteOrder.BIG_ENDIAN) ); static SequenceLayout longs = MemoryLayout.sequenceLayout(100, - MemoryLayouts.BITS_64_BE + JAVA_LONG.withOrder(ByteOrder.BIG_ENDIAN) ); static SequenceLayout doubles = MemoryLayout.sequenceLayout(100, - MemoryLayouts.BITS_64_BE + JAVA_DOUBLE.withOrder(ByteOrder.BIG_ENDIAN) ); - static VarHandle indexHandle = tuples.varHandle(int.class, PathElement.sequenceElement(), PathElement.groupElement("index")); - static VarHandle valueHandle = tuples.varHandle(float.class, PathElement.sequenceElement(), PathElement.groupElement("value")); + static VarHandle indexHandle = tuples.varHandle(PathElement.sequenceElement(), PathElement.groupElement("index")); + static VarHandle valueHandle = tuples.varHandle(PathElement.sequenceElement(), PathElement.groupElement("value")); static void initTuples(MemorySegment base, long count) { for (long i = 0; i < count ; i++) { @@ -263,7 +268,7 @@ public class TestByteBuffer { } } - @Test(dataProvider = "mappedOps", expectedExceptions = UnsupportedOperationException.class) + @Test(dataProvider = "mappedOps", expectedExceptions = IllegalStateException.class) public void testMappedSegmentOperations(MappedSegmentOp mappedBufferOp) throws Throwable { File f = new File("test3.out"); f.createNewFile(); @@ -324,6 +329,9 @@ public class TestByteBuffer { segment.isLoaded(); segment.unload(); segment.isLoaded(); + } catch(IOException e) { + if (e.getMessage().equals("Function not implemented")) + throw new SkipException(e.getMessage(), e); } } @@ -480,7 +488,7 @@ public class TestByteBuffer { @Test(expectedExceptions = IllegalStateException.class) public void testTooBigForByteBuffer() { - MemorySegment segment = MemoryAddress.NULL.asSegment(Integer.MAX_VALUE + 10L, ResourceScope.globalScope()); + MemorySegment segment = MemorySegment.ofAddress(MemoryAddress.NULL, Integer.MAX_VALUE + 10L, ResourceScope.newImplicitScope()); segment.asByteBuffer(); } @@ -511,7 +519,7 @@ public class TestByteBuffer { try (ResourceScope scope = ResourceScope.newConfinedScope()) { MemorySegment segment = MemorySegment.mapFile(f.toPath(), 0, SIZE, FileChannel.MapMode.READ_WRITE, scope); for (byte offset = 0; offset < SIZE; offset++) { - MemoryAccess.setByteAtOffset(segment, offset, offset); + segment.set(JAVA_BYTE, offset, offset); } segment.force(); } @@ -519,7 +527,7 @@ public class TestByteBuffer { for (int offset = 0 ; offset < SIZE ; offset++) { try (ResourceScope scope = ResourceScope.newConfinedScope()) { MemorySegment segment = MemorySegment.mapFile(f.toPath(), offset, SIZE - offset, FileChannel.MapMode.READ_ONLY, scope); - assertEquals(MemoryAccess.getByte(segment), offset); + assertEquals(segment.get(JAVA_BYTE, 0), offset); } } } @@ -636,13 +644,13 @@ public class TestByteBuffer { @Test(expectedExceptions = IllegalStateException.class) public void testDeadAccessOnClosedBufferSegment() { - MemorySegment s1 = MemorySegment.allocateNative(MemoryLayouts.JAVA_INT, ResourceScope.newConfinedScope()); + MemorySegment s1 = MemorySegment.allocateNative(JAVA_INT, ResourceScope.newConfinedScope()); MemorySegment s2 = MemorySegment.ofByteBuffer(s1.asByteBuffer()); // memory freed s1.scope().close(); - MemoryAccess.setInt(s2, 10); // Dead access! + s2.set(JAVA_INT, 0, 10); // Dead access! } @Test(dataProvider = "allScopes") @@ -654,7 +662,7 @@ public class TestByteBuffer { ResourceScope scp = closeableScopeOrNull(scope = scopeSupplier.get())) { MemorySegment segment = MemorySegment.allocateNative(10, 1, scope); for (int i = 0; i < 10; i++) { - MemoryAccess.setByteAtOffset(segment, i, (byte) i); + segment.set(JAVA_BYTE, i, (byte) i); } ByteBuffer bb = segment.asByteBuffer(); assertEquals(channel.write(bb), 10); @@ -674,7 +682,7 @@ public class TestByteBuffer { try (FileChannel channel = FileChannel.open(tmp.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) { MemorySegment segment = MemorySegment.allocateNative(10, scopeSupplier.get()); for (int i = 0; i < 10; i++) { - MemoryAccess.setByteAtOffset(segment, i, (byte) i); + segment.set(JAVA_BYTE, i, (byte) i); } ByteBuffer bb = segment.asByteBuffer(); segment.scope().close(); @@ -694,7 +702,7 @@ public class TestByteBuffer { int newSize = 8; var slice = segment.asSlice(4, newSize); - var bytes = slice.toByteArray(); + var bytes = slice.toArray(JAVA_BYTE); assertEquals(newSize, bytes.length); var buffer = slice.asByteBuffer(); @@ -719,6 +727,7 @@ public class TestByteBuffer { public static Object[][] segments() throws Throwable { return new Object[][] { { (Supplier<MemorySegment>) () -> MemorySegment.allocateNative(16, ResourceScope.newImplicitScope()) }, + { (Supplier<MemorySegment>) () -> MemorySegment.allocateNative(16, ResourceScope.newConfinedScope()) }, { (Supplier<MemorySegment>) () -> MemorySegment.ofArray(new byte[16]) } }; } @@ -729,27 +738,20 @@ public class TestByteBuffer { { (Supplier<ResourceScope>) () -> ResourceScope.newSharedScope() }, { (Supplier<ResourceScope>) () -> ResourceScope.newConfinedScope() }, { (Supplier<ResourceScope>) () -> ResourceScope.newSharedScope(Cleaner.create()) }, - { (Supplier<ResourceScope>) () -> ResourceScope.newConfinedScope(Cleaner.create()) } - }; - } - - @DataProvider(name = "implicitScopes") - public static Object[][] implicitScopes() { - return new Object[][] { - { (Supplier<ResourceScope>) ResourceScope::newImplicitScope }, - { (Supplier<ResourceScope>) ResourceScope::globalScope }, + { (Supplier<ResourceScope>) () -> ResourceScope.newConfinedScope(Cleaner.create()) }, + { (Supplier<ResourceScope>) () -> ResourceScope.newImplicitScope() } }; } @DataProvider(name = "allScopes") public static Object[][] allScopes() { - return Stream.of(implicitScopes(), closeableScopes()) + return Stream.of(new Object[][] { { (Supplier<ResourceScope>)ResourceScope::globalScope } }, closeableScopes()) .flatMap(Arrays::stream) .toArray(Object[][]::new); } static ResourceScope closeableScopeOrNull(ResourceScope scope) { - if (scope.isImplicit()) + if (scope == ResourceScope.globalScope()) return null; return scope; } @@ -812,34 +814,34 @@ public class TestByteBuffer { @DataProvider(name = "resizeOps") public Object[][] resizeOps() { Consumer<MemorySegment> byteInitializer = - (base) -> initBytes(base, bytes, (addr, pos) -> MemoryAccess.setByteAtOffset(addr, pos, (byte)(long)pos)); + (base) -> initBytes(base, bytes, (addr, pos) -> addr.set(JAVA_BYTE, pos, (byte)(long)pos)); Consumer<MemorySegment> charInitializer = - (base) -> initBytes(base, chars, (addr, pos) -> MemoryAccess.setCharAtIndex(addr, pos, ByteOrder.BIG_ENDIAN, (char)(long)pos)); + (base) -> initBytes(base, chars, (addr, pos) -> addr.setAtIndex(JAVA_CHAR.withOrder(ByteOrder.BIG_ENDIAN), pos, (char)(long)pos)); Consumer<MemorySegment> shortInitializer = - (base) -> initBytes(base, shorts, (addr, pos) -> MemoryAccess.setShortAtIndex(addr, pos, ByteOrder.BIG_ENDIAN, (short)(long)pos)); + (base) -> initBytes(base, shorts, (addr, pos) -> addr.setAtIndex(JAVA_SHORT.withOrder(ByteOrder.BIG_ENDIAN), pos, (short)(long)pos)); Consumer<MemorySegment> intInitializer = - (base) -> initBytes(base, ints, (addr, pos) -> MemoryAccess.setIntAtIndex(addr, pos, ByteOrder.BIG_ENDIAN, (int)(long)pos)); + (base) -> initBytes(base, ints, (addr, pos) -> addr.setAtIndex(JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN), pos, (int)(long)pos)); Consumer<MemorySegment> floatInitializer = - (base) -> initBytes(base, floats, (addr, pos) -> MemoryAccess.setFloatAtIndex(addr, pos, ByteOrder.BIG_ENDIAN, (float)(long)pos)); + (base) -> initBytes(base, floats, (addr, pos) -> addr.setAtIndex(JAVA_FLOAT.withOrder(ByteOrder.BIG_ENDIAN), pos, (float)(long)pos)); Consumer<MemorySegment> longInitializer = - (base) -> initBytes(base, longs, (addr, pos) -> MemoryAccess.setLongAtIndex(addr, pos, ByteOrder.BIG_ENDIAN, (long)pos)); + (base) -> initBytes(base, longs, (addr, pos) -> addr.setAtIndex(JAVA_LONG.withOrder(ByteOrder.BIG_ENDIAN), pos, (long)pos)); Consumer<MemorySegment> doubleInitializer = - (base) -> initBytes(base, doubles, (addr, pos) -> MemoryAccess.setDoubleAtIndex(addr, pos, ByteOrder.BIG_ENDIAN, (double)(long)pos)); + (base) -> initBytes(base, doubles, (addr, pos) -> addr.setAtIndex(JAVA_DOUBLE.withOrder(ByteOrder.BIG_ENDIAN), pos, (double)(long)pos)); Consumer<MemorySegment> byteChecker = - (base) -> checkBytes(base, bytes, Function.identity(), (addr, pos) -> MemoryAccess.getByteAtOffset(addr, pos), ByteBuffer::get); + (base) -> checkBytes(base, bytes, Function.identity(), (addr, pos) -> addr.get(JAVA_BYTE, pos), ByteBuffer::get); Consumer<MemorySegment> charChecker = - (base) -> checkBytes(base, chars, ByteBuffer::asCharBuffer, (addr, pos) -> MemoryAccess.getCharAtIndex(addr, pos, ByteOrder.BIG_ENDIAN), CharBuffer::get); + (base) -> checkBytes(base, chars, ByteBuffer::asCharBuffer, (addr, pos) -> addr.getAtIndex(JAVA_CHAR.withOrder(ByteOrder.BIG_ENDIAN), pos), CharBuffer::get); Consumer<MemorySegment> shortChecker = - (base) -> checkBytes(base, shorts, ByteBuffer::asShortBuffer, (addr, pos) -> MemoryAccess.getShortAtIndex(addr, pos, ByteOrder.BIG_ENDIAN), ShortBuffer::get); + (base) -> checkBytes(base, shorts, ByteBuffer::asShortBuffer, (addr, pos) -> addr.getAtIndex(JAVA_SHORT.withOrder(ByteOrder.BIG_ENDIAN), pos), ShortBuffer::get); Consumer<MemorySegment> intChecker = - (base) -> checkBytes(base, ints, ByteBuffer::asIntBuffer, (addr, pos) -> MemoryAccess.getIntAtIndex(addr, pos, ByteOrder.BIG_ENDIAN), IntBuffer::get); + (base) -> checkBytes(base, ints, ByteBuffer::asIntBuffer, (addr, pos) -> addr.getAtIndex(JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN), pos), IntBuffer::get); Consumer<MemorySegment> floatChecker = - (base) -> checkBytes(base, floats, ByteBuffer::asFloatBuffer, (addr, pos) -> MemoryAccess.getFloatAtIndex(addr, pos, ByteOrder.BIG_ENDIAN), FloatBuffer::get); + (base) -> checkBytes(base, floats, ByteBuffer::asFloatBuffer, (addr, pos) -> addr.getAtIndex(JAVA_FLOAT.withOrder(ByteOrder.BIG_ENDIAN), pos), FloatBuffer::get); Consumer<MemorySegment> longChecker = - (base) -> checkBytes(base, longs, ByteBuffer::asLongBuffer, (addr, pos) -> MemoryAccess.getLongAtIndex(addr, pos, ByteOrder.BIG_ENDIAN), LongBuffer::get); + (base) -> checkBytes(base, longs, ByteBuffer::asLongBuffer, (addr, pos) -> addr.getAtIndex(JAVA_LONG.withOrder(ByteOrder.BIG_ENDIAN), pos), LongBuffer::get); Consumer<MemorySegment> doubleChecker = - (base) -> checkBytes(base, doubles, ByteBuffer::asDoubleBuffer, (addr, pos) -> MemoryAccess.getDoubleAtIndex(addr, pos, ByteOrder.BIG_ENDIAN), DoubleBuffer::get); + (base) -> checkBytes(base, doubles, ByteBuffer::asDoubleBuffer, (addr, pos) -> addr.getAtIndex(JAVA_DOUBLE.withOrder(ByteOrder.BIG_ENDIAN), pos), DoubleBuffer::get); return new Object[][]{ {byteChecker, byteInitializer, bytes}, diff --git a/test/jdk/java/foreign/TestCircularInit1.java b/test/jdk/java/foreign/TestCircularInit1.java deleted file mode 100644 index 46a98bd23f8d808104d1a22c7e7196de32507c6e..0000000000000000000000000000000000000000 --- a/test/jdk/java/foreign/TestCircularInit1.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64" - * @modules jdk.incubator.foreign/jdk.internal.foreign - * @run testng/othervm TestCircularInit1 - */ - -import jdk.incubator.foreign.CLinker; -import jdk.internal.foreign.PlatformLayouts; -import org.testng.annotations.Test; - -import static org.testng.Assert.assertNotNull; - -public class TestCircularInit1 { - - @Test - public void testCircularInit() { - System.out.println(PlatformLayouts.Win64.C_CHAR); // trigger clinit - assertNotNull(CLinker.C_CHAR); // should not be null - } - -} diff --git a/test/jdk/java/foreign/TestCircularInit2.java b/test/jdk/java/foreign/TestCircularInit2.java deleted file mode 100644 index 0eeed8184cf84d2eed124dfbaa2cffa05688d6cb..0000000000000000000000000000000000000000 --- a/test/jdk/java/foreign/TestCircularInit2.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64" - * @modules jdk.incubator.foreign/jdk.internal.foreign - * @run testng/othervm TestCircularInit2 - */ - -import jdk.incubator.foreign.CLinker; -import jdk.internal.foreign.PlatformLayouts; -import org.testng.annotations.Test; - -import static org.testng.Assert.assertNotNull; - -public class TestCircularInit2 { - - @Test - public void testCircularInit() { - System.out.println(CLinker.C_CHAR); // trigger clinit - assertNotNull(PlatformLayouts.Win64.C_CHAR); - assertNotNull(PlatformLayouts.SysV.C_CHAR); - assertNotNull(PlatformLayouts.AArch64.C_CHAR); - } - -} diff --git a/test/jdk/java/foreign/TestCondy.java b/test/jdk/java/foreign/TestCondy.java index 0f262214799d0d4298f1b7cb6efde318597b72f7..42191dd4a2491f508bd50d53bcfc542c726d2333 100644 --- a/test/jdk/java/foreign/TestCondy.java +++ b/test/jdk/java/foreign/TestCondy.java @@ -39,7 +39,15 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import static jdk.incubator.foreign.CLinker.*; +import static jdk.incubator.foreign.ValueLayout.ADDRESS; +import static jdk.incubator.foreign.ValueLayout.JAVA_BOOLEAN; +import static jdk.incubator.foreign.ValueLayout.JAVA_BYTE; +import static jdk.incubator.foreign.ValueLayout.JAVA_CHAR; +import static jdk.incubator.foreign.ValueLayout.JAVA_DOUBLE; +import static jdk.incubator.foreign.ValueLayout.JAVA_FLOAT; +import static jdk.incubator.foreign.ValueLayout.JAVA_INT; +import static jdk.incubator.foreign.ValueLayout.JAVA_LONG; +import static jdk.incubator.foreign.ValueLayout.JAVA_SHORT; import static org.testng.Assert.assertEquals; public class TestCondy { @@ -53,14 +61,15 @@ public class TestCondy { private static final MemoryLayout[] constants = { - C_CHAR, - C_SHORT, - C_INT, - C_LONG, - C_LONG_LONG, - C_FLOAT, - C_DOUBLE, - C_POINTER + JAVA_BOOLEAN, + JAVA_CHAR, + JAVA_BYTE, + JAVA_SHORT, + JAVA_INT, + JAVA_FLOAT, + JAVA_LONG, + JAVA_DOUBLE, + ADDRESS }; @DataProvider @@ -78,7 +87,7 @@ public class TestCondy { } testValues.add(FunctionDescriptor.ofVoid(constants)); - testValues.add(FunctionDescriptor.of(C_CHAR, constants)); + testValues.add(FunctionDescriptor.of(JAVA_BYTE, constants)); return testValues.stream().map(e -> new Object[] { e }).toArray(Object[][]::new); } diff --git a/test/jdk/java/foreign/TestDowncall.java b/test/jdk/java/foreign/TestDowncall.java index 8a78a20e1fbaad627781914b482136c32ebb4cda..252e14c69513df8e942302f988347161a795d310 100644 --- a/test/jdk/java/foreign/TestDowncall.java +++ b/test/jdk/java/foreign/TestDowncall.java @@ -33,8 +33,11 @@ * TestDowncall */ +import jdk.incubator.foreign.Addressable; import jdk.incubator.foreign.CLinker; import jdk.incubator.foreign.FunctionDescriptor; +import jdk.incubator.foreign.NativeSymbol; +import jdk.incubator.foreign.ResourceScope; import jdk.incubator.foreign.SymbolLookup; import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemoryLayout; @@ -52,7 +55,7 @@ import static org.testng.Assert.*; public class TestDowncall extends CallGeneratorHelper { - static CLinker abi = CLinker.getInstance(); + static CLinker abi = CLinker.systemCLinker(); static { System.loadLibrary("TestDowncall"); } @@ -62,64 +65,37 @@ public class TestDowncall extends CallGeneratorHelper { @Test(dataProvider="functions", dataProviderClass=CallGeneratorHelper.class) public void testDowncall(int count, String fName, Ret ret, List<ParamType> paramTypes, List<StructFieldType> fields) throws Throwable { List<Consumer<Object>> checks = new ArrayList<>(); - MemoryAddress addr = LOOKUP.lookup(fName).get(); + NativeSymbol addr = LOOKUP.lookup(fName).get(); MethodType mt = methodType(ret, paramTypes, fields); FunctionDescriptor descriptor = function(ret, paramTypes, fields); Object[] args = makeArgs(paramTypes, fields, checks); - try (NativeScope scope = new NativeScope()) { + try (ResourceScope scope = ResourceScope.newSharedScope()) { boolean needsScope = mt.returnType().equals(MemorySegment.class); - Object res = doCall(addr, scope, mt, descriptor, args); + SegmentAllocator allocator = needsScope ? + SegmentAllocator.newNativeArena(scope) : + THROWING_ALLOCATOR; + Object res = doCall(addr, allocator, descriptor, args); if (ret == Ret.NON_VOID) { checks.forEach(c -> c.accept(res)); if (needsScope) { // check that return struct has indeed been allocated in the native scope - assertEquals(((MemorySegment) res).scope(), scope.scope()); - assertEquals(scope.allocatedBytes(), descriptor.returnLayout().get().byteSize()); - } else { - // if here, there should be no allocation through the scope! - assertEquals(scope.allocatedBytes(), 0L); + assertEquals(((MemorySegment) res).scope(), scope); } - } else { - // if here, there should be no allocation through the scope! - assertEquals(scope.allocatedBytes(), 0L); } } } - @Test(dataProvider="functions", dataProviderClass=CallGeneratorHelper.class) - public void testDowncallNoScope(int count, String fName, Ret ret, List<ParamType> paramTypes, List<StructFieldType> fields) throws Throwable { - List<Consumer<Object>> checks = new ArrayList<>(); - MemoryAddress addr = LOOKUP.lookup(fName).get(); - MethodType mt = methodType(ret, paramTypes, fields); - FunctionDescriptor descriptor = function(ret, paramTypes, fields); - Object[] args = makeArgs(paramTypes, fields, checks); - boolean needsScope = mt.returnType().equals(MemorySegment.class); - Object res = doCall(addr, IMPLICIT_ALLOCATOR, mt, descriptor, args); - if (ret == Ret.NON_VOID) { - checks.forEach(c -> c.accept(res)); - if (needsScope) { - // check that return struct has indeed been allocated in the default scope - try { - ((MemorySegment)res).scope().close(); // should throw - fail("Expected exception!"); - } catch (UnsupportedOperationException ex) { - // ok - } - } - } - } - - Object doCall(MemoryAddress addr, SegmentAllocator allocator, MethodType type, FunctionDescriptor descriptor, Object[] args) throws Throwable { - MethodHandle mh = abi.downcallHandle(addr, allocator, type, descriptor); + Object doCall(NativeSymbol symbol, SegmentAllocator allocator, FunctionDescriptor descriptor, Object[] args) throws Throwable { + MethodHandle mh = downcallHandle(abi, symbol, allocator, descriptor); Object res = mh.invokeWithArguments(args); return res; } static MethodType methodType(Ret ret, List<ParamType> params, List<StructFieldType> fields) { MethodType mt = ret == Ret.VOID ? - MethodType.methodType(void.class) : MethodType.methodType(paramCarrier(params.get(0).layout(fields))); + MethodType.methodType(void.class) : MethodType.methodType(carrier(params.get(0).layout(fields), false)); for (ParamType p : params) { - mt = mt.appendParameterTypes(paramCarrier(p.layout(fields))); + mt = mt.appendParameterTypes(carrier(p.layout(fields), true)); } return mt; } diff --git a/test/jdk/java/foreign/TestFree.java b/test/jdk/java/foreign/TestFree.java index ad26e1eb5715bf630ca8408aa7f3dc682b2219bf..b009cee0ac4e57594982942bd3b2fe4a26b79b39 100644 --- a/test/jdk/java/foreign/TestFree.java +++ b/test/jdk/java/foreign/TestFree.java @@ -29,18 +29,16 @@ * @run testng/othervm --enable-native-access=ALL-UNNAMED TestFree */ -import jdk.incubator.foreign.MemoryAccess; import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; -import static jdk.incubator.foreign.CLinker.*; import static org.testng.Assert.assertEquals; -public class TestFree { +public class TestFree extends NativeTestHelper { private static MemorySegment asArray(MemoryAddress addr, MemoryLayout layout, int numElements) { - return addr.asSegment(numElements * layout.byteSize(), ResourceScope.globalScope()); + return MemorySegment.ofAddress(addr, numElements * layout.byteSize(), ResourceScope.globalScope()); } public void test() throws Throwable { @@ -48,8 +46,8 @@ public class TestFree { MemoryAddress addr = allocateMemory(str.length() + 1); MemorySegment seg = asArray(addr, C_CHAR, str.length() + 1); seg.copyFrom(MemorySegment.ofArray(str.getBytes())); - MemoryAccess.setByteAtOffset(seg, str.length(), (byte)0); - assertEquals(str, toJavaString(seg)); + seg.set(C_CHAR, str.length(), (byte)0); + assertEquals(str, seg.getUtf8String(0)); freeMemory(addr); } } diff --git a/test/jdk/java/foreign/TestFunctionDescriptor.java b/test/jdk/java/foreign/TestFunctionDescriptor.java index d8b82254dafcd34a37222ed2ea6b7420bf78532d..7f6eb908744f3ade366d87e0e77fb65ea115318b 100644 --- a/test/jdk/java/foreign/TestFunctionDescriptor.java +++ b/test/jdk/java/foreign/TestFunctionDescriptor.java @@ -25,27 +25,21 @@ /* * @test * @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64" - * @run testng TestFunctionDescriptor + * @run testng/othervm --enable-native-access=ALL-UNNAMED TestFunctionDescriptor */ import jdk.incubator.foreign.FunctionDescriptor; import jdk.incubator.foreign.MemoryLayout; import org.testng.annotations.Test; -import java.lang.constant.Constable; import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; -import static jdk.incubator.foreign.CLinker.C_DOUBLE; -import static jdk.incubator.foreign.CLinker.C_INT; -import static jdk.incubator.foreign.CLinker.C_LONG_LONG; -import static jdk.incubator.foreign.CLinker.C_POINTER; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; -public class TestFunctionDescriptor { +public class TestFunctionDescriptor extends NativeTestHelper { static final String DUMMY_ATTR = "dummy"; @@ -68,56 +62,35 @@ public class TestFunctionDescriptor { assertFalse(returnLayoutOp.isPresent()); } - @Test - public void testAttribute() { - FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_DOUBLE, C_LONG_LONG); - fd = fd.withAttribute(DUMMY_ATTR, true); - - assertEquals(fd.argumentLayouts(), List.of(C_DOUBLE, C_LONG_LONG)); - Optional<MemoryLayout> returnLayoutOp = fd.returnLayout(); - assertTrue(returnLayoutOp.isPresent()); - assertEquals(returnLayoutOp.get(), C_INT); - assertEquals(fd.attributes().collect(Collectors.toList()), List.of(DUMMY_ATTR)); - Optional<Constable> attr = fd.attribute(DUMMY_ATTR); - assertTrue(attr.isPresent()); - assertEquals(attr.get(), true); - } - @Test public void testAppendArgumentLayouts() { - FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_DOUBLE, C_LONG_LONG) - .withAttribute(DUMMY_ATTR, true); - fd = fd.withAppendedArgumentLayouts(C_POINTER); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_DOUBLE, C_LONG_LONG); + fd = fd.appendArgumentLayouts(C_POINTER); assertEquals(fd.argumentLayouts(), List.of(C_DOUBLE, C_LONG_LONG, C_POINTER)); Optional<MemoryLayout> returnLayoutOp = fd.returnLayout(); assertTrue(returnLayoutOp.isPresent()); assertEquals(returnLayoutOp.get(), C_INT); - assertEquals(fd.attributes().collect(Collectors.toList()), List.of(DUMMY_ATTR)); } @Test public void testChangeReturnLayout() { - FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_DOUBLE, C_LONG_LONG) - .withAttribute(DUMMY_ATTR, true); - fd = fd.withReturnLayout(C_INT); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_DOUBLE, C_LONG_LONG); + fd = fd.changeReturnLayout(C_INT); assertEquals(fd.argumentLayouts(), List.of(C_DOUBLE, C_LONG_LONG)); Optional<MemoryLayout> returnLayoutOp = fd.returnLayout(); assertTrue(returnLayoutOp.isPresent()); assertEquals(returnLayoutOp.get(), C_INT); - assertEquals(fd.attributes().collect(Collectors.toList()), List.of(DUMMY_ATTR)); } @Test public void testDropReturnLayout() { - FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_DOUBLE, C_LONG_LONG) - .withAttribute(DUMMY_ATTR, true); - fd = fd.withVoidReturnLayout(); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_DOUBLE, C_LONG_LONG); + fd = fd.dropReturnLayout(); assertEquals(fd.argumentLayouts(), List.of(C_DOUBLE, C_LONG_LONG)); Optional<MemoryLayout> returnLayoutOp = fd.returnLayout(); assertFalse(returnLayoutOp.isPresent()); - assertEquals(fd.attributes().collect(Collectors.toList()), List.of(DUMMY_ATTR)); } } diff --git a/test/jdk/java/foreign/TestHandshake.java b/test/jdk/java/foreign/TestHandshake.java index ee9b739459465ed1e65d9099c0ed1c2b0f1437ff..94fdd8cbf1828aacc2b4e2c262bdcd9de315836b 100644 --- a/test/jdk/java/foreign/TestHandshake.java +++ b/test/jdk/java/foreign/TestHandshake.java @@ -31,7 +31,6 @@ * @run testng/othervm -XX:-TieredCompilation TestHandshake */ -import jdk.incubator.foreign.MemoryAccess; import jdk.incubator.foreign.MemorySegment; import java.lang.invoke.MethodHandles; @@ -48,6 +47,8 @@ import java.util.concurrent.atomic.AtomicLong; import jdk.incubator.foreign.ResourceScope; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; + +import static jdk.incubator.foreign.ValueLayout.JAVA_BYTE; import static org.testng.Assert.*; public class TestHandshake { @@ -150,7 +151,7 @@ public class TestHandshake { void doAccess() { int sum = 0; for (int i = 0; i < segment.byteSize(); i++) { - sum += MemoryAccess.getByteAtOffset(segment, i); + sum += segment.get(JAVA_BYTE, i); } } } @@ -193,7 +194,7 @@ public class TestHandshake { super(id, segment); this.copy = MemorySegment.allocateNative(SEGMENT_SIZE, 1, segment.scope()); copy.copyFrom(segment); - MemoryAccess.setByteAtOffset(copy, ThreadLocalRandom.current().nextInt(SEGMENT_SIZE), (byte)42); + copy.set(JAVA_BYTE, ThreadLocalRandom.current().nextInt(SEGMENT_SIZE), (byte)42); } @Override diff --git a/test/jdk/java/foreign/TestIllegalLink.java b/test/jdk/java/foreign/TestIllegalLink.java index f63019bc4ffb99e301a8c7c2707af7962ba84386..7afa01689bc5a851eae1669c3aecb524a41c7ebe 100644 --- a/test/jdk/java/foreign/TestIllegalLink.java +++ b/test/jdk/java/foreign/TestIllegalLink.java @@ -32,26 +32,23 @@ import jdk.incubator.foreign.CLinker; import jdk.incubator.foreign.FunctionDescriptor; import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemoryLayout; -import jdk.incubator.foreign.MemoryLayouts; -import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.NativeSymbol; +import jdk.incubator.foreign.ResourceScope; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; -import java.lang.invoke.MethodType; - -import static jdk.incubator.foreign.CLinker.C_INT; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; -public class TestIllegalLink { +public class TestIllegalLink extends NativeTestHelper { - private static final MemoryAddress DUMMY_TARGET = MemoryAddress.ofLong(1); - private static final CLinker ABI = CLinker.getInstance(); + private static final NativeSymbol DUMMY_TARGET = NativeSymbol.ofAddress("dummy", MemoryAddress.ofLong(1), ResourceScope.globalScope()); + private static final CLinker ABI = CLinker.systemCLinker(); @Test(dataProvider = "types") - public void testTypeMismatch(MethodType mt, FunctionDescriptor desc, String expectedExceptionMessage) { + public void testTypeMismatch(FunctionDescriptor desc, String expectedExceptionMessage) { try { - ABI.downcallHandle(DUMMY_TARGET, mt, desc); + ABI.downcallHandle(DUMMY_TARGET, desc); fail("Expected IllegalArgumentException was not thrown"); } catch (IllegalArgumentException e) { assertTrue(e.getMessage().contains(expectedExceptionMessage)); @@ -62,49 +59,20 @@ public class TestIllegalLink { public static Object[][] types() { return new Object[][]{ { - MethodType.methodType(void.class), - FunctionDescriptor.of(C_INT), - "Return type mismatch" - }, - { - MethodType.methodType(void.class), - FunctionDescriptor.ofVoid(C_INT), - "Arity mismatch" + FunctionDescriptor.of(MemoryLayout.paddingLayout(64)), + "Unsupported layout: x64" }, { - MethodType.methodType(void.class, int.class), - FunctionDescriptor.ofVoid(MemoryLayout.paddingLayout(32)), - "Expected a ValueLayout" - }, - { - MethodType.methodType(void.class, boolean.class), - FunctionDescriptor.ofVoid(MemoryLayouts.BITS_8_LE), - "Unsupported carrier" - }, - { - MethodType.methodType(void.class, int.class), - FunctionDescriptor.ofVoid(MemoryLayouts.BITS_64_LE), - "Carrier size mismatch" - }, - { - MethodType.methodType(void.class, MemoryAddress.class), FunctionDescriptor.ofVoid(MemoryLayout.paddingLayout(64)), - "Expected a ValueLayout" - }, - { - MethodType.methodType(void.class, MemoryAddress.class), - FunctionDescriptor.ofVoid(MemoryLayouts.BITS_16_LE), - "Address size mismatch" + "Unsupported layout: x64" }, { - MethodType.methodType(void.class, MemorySegment.class), - FunctionDescriptor.ofVoid(MemoryLayouts.BITS_64_LE), - "Expected a GroupLayout" + FunctionDescriptor.of(MemoryLayout.sequenceLayout(C_INT)), + "Unsupported layout: [:b32]" }, { - MethodType.methodType(void.class, String.class), - FunctionDescriptor.ofVoid(MemoryLayouts.BITS_64_LE), - "Unsupported carrier" + FunctionDescriptor.ofVoid(MemoryLayout.sequenceLayout(C_INT)), + "Unsupported layout: [:b32]" }, }; } diff --git a/test/jdk/java/foreign/TestIntrinsics.java b/test/jdk/java/foreign/TestIntrinsics.java index 98e6829e4b2bef3f62a777d454834b56a7b78ac6..1d4afce2289898eec968075bf9e53fcd241ffecb 100644 --- a/test/jdk/java/foreign/TestIntrinsics.java +++ b/test/jdk/java/foreign/TestIntrinsics.java @@ -40,19 +40,18 @@ import java.lang.invoke.MethodType; import java.util.ArrayList; import java.util.List; -import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemoryLayout; +import jdk.incubator.foreign.NativeSymbol; import jdk.incubator.foreign.SymbolLookup; import org.testng.annotations.*; import static java.lang.invoke.MethodType.methodType; -import static jdk.incubator.foreign.CLinker.*; -import static jdk.incubator.foreign.FunctionDescriptor.TRIVIAL_ATTRIBUTE_NAME; +import static jdk.incubator.foreign.ValueLayout.JAVA_CHAR; import static org.testng.Assert.assertEquals; -public class TestIntrinsics { +public class TestIntrinsics extends NativeTestHelper { - static final CLinker abi = CLinker.getInstance(); + static final CLinker abi = CLinker.systemCLinker(); static { System.loadLibrary("Intrinsics"); } @@ -88,52 +87,48 @@ public class TestIntrinsics { } AddIdentity addIdentity = (name, carrier, layout, arg) -> { - MemoryAddress ma = LOOKUP.lookup(name).get(); + NativeSymbol ma = LOOKUP.lookup(name).get(); MethodType mt = methodType(carrier, carrier); FunctionDescriptor fd = FunctionDescriptor.of(layout, layout); - tests.add(abi.downcallHandle(ma, mt, fd), arg, arg); - tests.add(abi.downcallHandle(ma, mt, fd.withAttribute(TRIVIAL_ATTRIBUTE_NAME, true)), arg, arg); - tests.add(abi.downcallHandle(mt, fd), arg, ma, arg); + tests.add(abi.downcallHandle(ma, fd), arg, arg); + tests.add(abi.downcallHandle(fd), arg, ma, arg); }; { // empty - MemoryAddress ma = LOOKUP.lookup("empty").get(); + NativeSymbol ma = LOOKUP.lookup("empty").get(); MethodType mt = methodType(void.class); FunctionDescriptor fd = FunctionDescriptor.ofVoid(); - tests.add(abi.downcallHandle(ma, mt, fd), null); - tests.add(abi.downcallHandle(ma, mt, fd.withAttribute(TRIVIAL_ATTRIBUTE_NAME, true)), null); + tests.add(abi.downcallHandle(ma, fd), null); } - addIdentity.add("identity_char", byte.class, C_CHAR, (byte) 10); - addIdentity.add("identity_short", short.class, C_SHORT, (short) 10); - addIdentity.add("identity_int", int.class, C_INT, 10); - addIdentity.add("identity_long", long.class, C_LONG_LONG, 10L); - addIdentity.add("identity_float", float.class, C_FLOAT, 10F); - addIdentity.add("identity_double", double.class, C_DOUBLE, 10D); + addIdentity.add("identity_bool", boolean.class, C_BOOL, true); + addIdentity.add("identity_char", byte.class, C_CHAR, (byte) 10); + addIdentity.add("identity_short", short.class, C_SHORT, (short) 10); + addIdentity.add("identity_int", int.class, C_INT, 10); + addIdentity.add("identity_long", long.class, C_LONG_LONG, 10L); + addIdentity.add("identity_float", float.class, C_FLOAT, 10F); + addIdentity.add("identity_double", double.class, C_DOUBLE, 10D); { // identity_va - MemoryAddress ma = LOOKUP.lookup("identity_va").get(); + NativeSymbol ma = LOOKUP.lookup("identity_va").get(); MethodType mt = methodType(int.class, int.class, double.class, int.class, float.class, long.class); - FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, asVarArg(C_DOUBLE), - asVarArg(C_INT), asVarArg(C_FLOAT), asVarArg(C_LONG_LONG)); - tests.add(abi.downcallHandle(ma, mt, fd), 1, 1, 10D, 2, 3F, 4L); - tests.add(abi.downcallHandle(ma, mt, fd.withAttribute(TRIVIAL_ATTRIBUTE_NAME, true)), 1, 1, 10D, 2, 3F, 4L); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT).asVariadic(C_DOUBLE, C_INT, C_FLOAT, C_LONG_LONG); + tests.add(abi.downcallHandle(ma, fd), 1, 1, 10D, 2, 3F, 4L); } { // high_arity MethodType baseMT = methodType(void.class, int.class, double.class, long.class, float.class, byte.class, short.class, char.class); FunctionDescriptor baseFD = FunctionDescriptor.ofVoid(C_INT, C_DOUBLE, C_LONG_LONG, C_FLOAT, C_CHAR, - C_SHORT, C_SHORT); + C_SHORT, JAVA_CHAR); Object[] args = {1, 10D, 2L, 3F, (byte) 0, (short) 13, 'a'}; for (int i = 0; i < args.length; i++) { - MemoryAddress ma = LOOKUP.lookup("invoke_high_arity" + i).get(); + NativeSymbol ma = LOOKUP.lookup("invoke_high_arity" + i).get(); MethodType mt = baseMT.changeReturnType(baseMT.parameterType(i)); - FunctionDescriptor fd = baseFD.withReturnLayout(baseFD.argumentLayouts().get(i)); + FunctionDescriptor fd = baseFD.changeReturnLayout(baseFD.argumentLayouts().get(i)); Object expected = args[i]; - tests.add(abi.downcallHandle(ma, mt, fd), expected, args); - tests.add(abi.downcallHandle(ma, mt, fd.withAttribute(TRIVIAL_ATTRIBUTE_NAME, true)), expected, args); + tests.add(abi.downcallHandle(ma, fd), expected, args); } } diff --git a/test/jdk/java/foreign/TestLayoutAttributes.java b/test/jdk/java/foreign/TestLayoutAttributes.java deleted file mode 100644 index 9def5a3b8237f6a02379be8bf20f58f2e8388a5d..0000000000000000000000000000000000000000 --- a/test/jdk/java/foreign/TestLayoutAttributes.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @run testng TestLayoutAttributes - */ - -import jdk.incubator.foreign.MemoryLayout; -import jdk.incubator.foreign.MemoryLayouts; -import org.testng.annotations.Test; - -import java.util.List; -import java.util.stream.Collectors; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; - -public class TestLayoutAttributes { - - @Test - public void testAttribute() { - MemoryLayout ml = MemoryLayouts.BITS_32_LE - .withAttribute("MyAttribute", 10L); - assertEquals((long) ml.attribute("MyAttribute").orElseThrow(), 10L); - } - - @Test - public void testAttributeOverwrite() { - MemoryLayout ml = MemoryLayouts.BITS_32_LE - .withAttribute("MyAttribute", 10L); - assertEquals((long) ml.attribute("MyAttribute").orElseThrow(), 10L); - ml = ml.withAttribute("MyAttribute", 11L); - assertEquals((long) ml.attribute("MyAttribute").orElseThrow(), 11L); - } - - @Test - public void testAttributeNonExistent() { - MemoryLayout ml = MemoryLayouts.BITS_32_LE - .withAttribute("MyAttribute", 10L); - assertTrue(ml.attribute("Foo").isEmpty()); - } - - @Test - public void testNameAttribute() { - MemoryLayout ml = MemoryLayouts.BITS_32_LE - .withName("foo"); - assertEquals(ml.name().orElseThrow(), "foo"); - assertEquals(ml.attribute(MemoryLayout.LAYOUT_NAME).orElseThrow(), "foo"); - } - - @Test - public void testAttributesStream() { - MemoryLayout ml = MemoryLayouts.BITS_32_LE - .withName("foo") - .withAttribute("MyAttribute", 10L); - List<String> attribs = ml.attributes().collect(Collectors.toList()); - assertEquals(attribs.size(), 2); - assertTrue(attribs.contains("MyAttribute")); - assertTrue(attribs.contains(MemoryLayout.LAYOUT_NAME)); - } -} diff --git a/test/jdk/java/foreign/TestLayoutConstants.java b/test/jdk/java/foreign/TestLayoutConstants.java index 2ea2967923448e5d1a7e4e1c28faa69e433f0dd9..59d26ca2700b749435a9293c3fd780042e829a7c 100644 --- a/test/jdk/java/foreign/TestLayoutConstants.java +++ b/test/jdk/java/foreign/TestLayoutConstants.java @@ -27,11 +27,12 @@ */ import jdk.incubator.foreign.FunctionDescriptor; -import jdk.incubator.foreign.MemoryLayouts; import jdk.incubator.foreign.MemoryLayout; import java.lang.invoke.MethodHandles; +import java.nio.ByteOrder; +import jdk.incubator.foreign.ValueLayout; import org.testng.annotations.*; import static org.testng.Assert.*; @@ -66,49 +67,48 @@ public class TestLayoutConstants { public Object[][] createLayouts() { return new Object[][] { //padding - { MemoryLayouts.PAD_32 }, - { MemoryLayout.sequenceLayout(MemoryLayouts.PAD_32) }, - { MemoryLayout.sequenceLayout(5, MemoryLayouts.PAD_32) }, - { MemoryLayout.structLayout(MemoryLayouts.PAD_32, MemoryLayouts.PAD_32) }, - { MemoryLayout.unionLayout(MemoryLayouts.PAD_32, MemoryLayouts.PAD_32) }, + {MemoryLayout.paddingLayout(32)}, + { MemoryLayout.sequenceLayout(MemoryLayout.paddingLayout(32)) }, + { MemoryLayout.sequenceLayout(5, MemoryLayout.paddingLayout(32)) }, + { MemoryLayout.structLayout(MemoryLayout.paddingLayout(32), MemoryLayout.paddingLayout(32)) }, + { MemoryLayout.unionLayout(MemoryLayout.paddingLayout(32), MemoryLayout.paddingLayout(32)) }, //values, big endian - { MemoryLayouts.BITS_32_BE }, + { ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN) }, { MemoryLayout.structLayout( - MemoryLayouts.BITS_32_BE, - MemoryLayouts.BITS_32_BE) }, + ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN), + ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN)) }, { MemoryLayout.unionLayout( - MemoryLayouts.BITS_32_BE, - MemoryLayouts.BITS_32_BE) }, + ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN), + ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN)) }, //values, little endian - { MemoryLayouts.BITS_32_LE }, + { ValueLayout.JAVA_INT.withOrder(ByteOrder.LITTLE_ENDIAN) }, { MemoryLayout.structLayout( - MemoryLayouts.BITS_32_LE, - MemoryLayouts.BITS_32_LE) }, + ValueLayout.JAVA_INT.withOrder(ByteOrder.LITTLE_ENDIAN), + ValueLayout.JAVA_INT.withOrder(ByteOrder.LITTLE_ENDIAN)) }, { MemoryLayout.unionLayout( - MemoryLayouts.BITS_32_LE, - MemoryLayouts.BITS_32_LE) }, + ValueLayout.JAVA_INT.withOrder(ByteOrder.LITTLE_ENDIAN), + ValueLayout.JAVA_INT.withOrder(ByteOrder.LITTLE_ENDIAN)) }, //deeply nested { MemoryLayout.structLayout( - MemoryLayouts.PAD_16, + MemoryLayout.paddingLayout(16), MemoryLayout.structLayout( - MemoryLayouts.PAD_8, - MemoryLayouts.BITS_32_BE)) }, + MemoryLayout.paddingLayout(8), + ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN))) }, { MemoryLayout.unionLayout( - MemoryLayouts.PAD_16, + MemoryLayout.paddingLayout(16), MemoryLayout.structLayout( - MemoryLayouts.PAD_8, - MemoryLayouts.BITS_32_BE)) }, + MemoryLayout.paddingLayout(8), + ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN))) }, { MemoryLayout.sequenceLayout( MemoryLayout.structLayout( - MemoryLayouts.PAD_8, - MemoryLayouts.BITS_32_BE)) }, + MemoryLayout.paddingLayout(8), + ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN))) }, { MemoryLayout.sequenceLayout(5, MemoryLayout.structLayout( - MemoryLayouts.PAD_8, - MemoryLayouts.BITS_32_BE)) }, - { MemoryLayouts.BITS_32_LE.withName("myInt") }, - { MemoryLayouts.BITS_32_LE.withBitAlignment(8) }, - { MemoryLayouts.BITS_32_LE.withAttribute("xyz", "abc") }, + MemoryLayout.paddingLayout(8), + ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN))) }, + { ValueLayout.JAVA_INT.withOrder(ByteOrder.LITTLE_ENDIAN).withName("myInt") }, + { ValueLayout.JAVA_INT.withOrder(ByteOrder.LITTLE_ENDIAN).withBitAlignment(8) }, }; } diff --git a/test/jdk/java/foreign/TestLayoutEquality.java b/test/jdk/java/foreign/TestLayoutEquality.java index 8eb59ec340ee0d069a260bccb55dae930fc9e8a1..7a4d3124f0b865fb7c6da9d0d7f21953da057d29 100644 --- a/test/jdk/java/foreign/TestLayoutEquality.java +++ b/test/jdk/java/foreign/TestLayoutEquality.java @@ -29,7 +29,7 @@ * @run testng TestLayoutEquality */ -import jdk.incubator.foreign.MemoryLayout; +import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.ValueLayout; import jdk.internal.foreign.PlatformLayouts; import org.testng.annotations.DataProvider; @@ -39,23 +39,32 @@ import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; +import static jdk.incubator.foreign.ValueLayout.ADDRESS; +import static jdk.incubator.foreign.ValueLayout.JAVA_BOOLEAN; +import static jdk.incubator.foreign.ValueLayout.JAVA_BYTE; +import static jdk.incubator.foreign.ValueLayout.JAVA_CHAR; +import static jdk.incubator.foreign.ValueLayout.JAVA_DOUBLE; +import static jdk.incubator.foreign.ValueLayout.JAVA_FLOAT; +import static jdk.incubator.foreign.ValueLayout.JAVA_INT; +import static jdk.incubator.foreign.ValueLayout.JAVA_LONG; +import static jdk.incubator.foreign.ValueLayout.JAVA_SHORT; import static org.testng.Assert.*; public class TestLayoutEquality { @Test(dataProvider = "layoutConstants") public void testReconstructedEquality(ValueLayout layout) { - ValueLayout newLayout = MemoryLayout.valueLayout(layout.bitSize(), layout.order()); + ValueLayout newLayout = valueLayoutForCarrier(layout.carrier()); + newLayout = newLayout.withBitAlignment(layout.bitAlignment()); + newLayout = newLayout.withOrder(layout.order()); // properties should be equal assertEquals(newLayout.bitSize(), layout.bitSize()); assertEquals(newLayout.bitAlignment(), layout.bitAlignment()); assertEquals(newLayout.name(), layout.name()); - assertEquals(newLayout.attributes().toArray().length, 0); - assertEquals(layout.attributes().toArray().length, 1); - // but equals should return false, because one is a ValueLayout with a CLinker kind - assertNotEquals(newLayout, layout); + // layouts should be equals + assertEquals(newLayout, layout); } @DataProvider @@ -76,4 +85,27 @@ public class TestLayoutEquality { } } + static ValueLayout valueLayoutForCarrier(Class<?> carrier) { + if (carrier == boolean.class) { + return JAVA_BOOLEAN; + } else if (carrier == char.class) { + return JAVA_CHAR; + } else if (carrier == byte.class) { + return JAVA_BYTE; + } else if (carrier == short.class) { + return JAVA_SHORT; + } else if (carrier == int.class) { + return JAVA_INT; + } else if (carrier == long.class) { + return JAVA_LONG; + } else if (carrier == float.class) { + return JAVA_FLOAT; + } else if (carrier == double.class) { + return JAVA_DOUBLE; + } else if (carrier == MemoryAddress.class) { + return ADDRESS; + } else { + throw new UnsupportedOperationException(); + } + } } diff --git a/test/jdk/java/foreign/TestLayoutPaths.java b/test/jdk/java/foreign/TestLayoutPaths.java index 1cf3798c249f18d501140ff00d2fb337d4fd6179..438dc86ada6ae7cab6575127ae8cf375bf42cc79 100644 --- a/test/jdk/java/foreign/TestLayoutPaths.java +++ b/test/jdk/java/foreign/TestLayoutPaths.java @@ -28,24 +28,23 @@ */ import jdk.incubator.foreign.GroupLayout; -import jdk.incubator.foreign.MemoryLayouts; import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.MemoryLayout.PathElement; import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; import jdk.incubator.foreign.SequenceLayout; +import jdk.incubator.foreign.ValueLayout; import org.testng.SkipException; import org.testng.annotations.*; import java.lang.invoke.MethodHandle; -import java.nio.ByteOrder; import java.util.ArrayList; import java.util.List; import static jdk.incubator.foreign.MemoryLayout.PathElement.groupElement; import static jdk.incubator.foreign.MemoryLayout.PathElement.sequenceElement; -import static jdk.incubator.foreign.MemoryLayouts.JAVA_INT; +import static jdk.incubator.foreign.ValueLayout.JAVA_INT; import static org.testng.Assert.*; public class TestLayoutPaths { @@ -153,7 +152,7 @@ public class TestLayoutPaths { @Test(expectedExceptions = IllegalArgumentException.class) public void testIncompleteAccess() { SequenceLayout seq = MemoryLayout.sequenceLayout(5, MemoryLayout.structLayout(JAVA_INT)); - seq.varHandle(int.class, sequenceElement()); + seq.varHandle(sequenceElement()); } @Test(expectedExceptions = IllegalArgumentException.class) @@ -221,7 +220,7 @@ public class TestLayoutPaths { throw new AssertionError(ex); // should be ok! } try { - g.varHandle(int.class, groupElement("foo")); //ok + g.varHandle(groupElement("foo")); //ok assertTrue(false); //should fail! } catch (UnsupportedOperationException ex) { //ok @@ -232,7 +231,7 @@ public class TestLayoutPaths { @Test public void testBadAlignOffset() { - GroupLayout g = MemoryLayout.structLayout(MemoryLayouts.PAD_8, JAVA_INT.withBitAlignment(16).withName("foo")); + GroupLayout g = MemoryLayout.structLayout(MemoryLayout.paddingLayout(8), JAVA_INT.withBitAlignment(16).withName("foo")); try { g.bitOffset(groupElement("foo")); g.byteOffset(groupElement("foo")); @@ -240,7 +239,7 @@ public class TestLayoutPaths { throw new AssertionError(ex); // should be ok! } try { - g.varHandle(int.class, groupElement("foo")); //ok + g.varHandle(groupElement("foo")); //ok assertTrue(false); //should fail! } catch (UnsupportedOperationException ex) { //ok @@ -299,10 +298,10 @@ public class TestLayoutPaths { public void testStructPaths() { long[] offsets = { 0, 8, 24, 56 }; GroupLayout g = MemoryLayout.structLayout( - MemoryLayouts.JAVA_BYTE.withName("1"), - MemoryLayouts.JAVA_CHAR.withName("2"), - MemoryLayouts.JAVA_FLOAT.withName("3"), - MemoryLayouts.JAVA_LONG.withName("4") + ValueLayout.JAVA_BYTE.withName("1"), + ValueLayout.JAVA_CHAR.withName("2"), + ValueLayout.JAVA_FLOAT.withName("3"), + ValueLayout.JAVA_LONG.withName("4") ); // test select @@ -324,11 +323,11 @@ public class TestLayoutPaths { // test map for (int i = 1 ; i <= 4 ; i++) { - GroupLayout g2 = (GroupLayout)g.map(l -> MemoryLayouts.JAVA_DOUBLE, groupElement(String.valueOf(i))); + GroupLayout g2 = (GroupLayout)g.map(l -> ValueLayout.JAVA_DOUBLE, groupElement(String.valueOf(i))); assertTrue(g2.isStruct()); for (int j = 0 ; j < 4 ; j++) { if (j == i - 1) { - assertEquals(g2.memberLayouts().get(j), MemoryLayouts.JAVA_DOUBLE); + assertEquals(g2.memberLayouts().get(j), ValueLayout.JAVA_DOUBLE); } else { assertEquals(g2.memberLayouts().get(j), g.memberLayouts().get(j)); } @@ -340,10 +339,10 @@ public class TestLayoutPaths { public void testUnionPaths() { long[] offsets = { 0, 0, 0, 0 }; GroupLayout g = MemoryLayout.unionLayout( - MemoryLayouts.JAVA_BYTE.withName("1"), - MemoryLayouts.JAVA_CHAR.withName("2"), - MemoryLayouts.JAVA_FLOAT.withName("3"), - MemoryLayouts.JAVA_LONG.withName("4") + ValueLayout.JAVA_BYTE.withName("1"), + ValueLayout.JAVA_CHAR.withName("2"), + ValueLayout.JAVA_FLOAT.withName("3"), + ValueLayout.JAVA_LONG.withName("4") ); // test select @@ -365,11 +364,11 @@ public class TestLayoutPaths { // test map for (int i = 1 ; i <= 4 ; i++) { - GroupLayout g2 = (GroupLayout)g.map(l -> MemoryLayouts.JAVA_DOUBLE, groupElement(String.valueOf(i))); + GroupLayout g2 = (GroupLayout)g.map(l -> ValueLayout.JAVA_DOUBLE, groupElement(String.valueOf(i))); assertTrue(g2.isUnion()); for (int j = 0 ; j < 4 ; j++) { if (j == i - 1) { - assertEquals(g2.memberLayouts().get(j), MemoryLayouts.JAVA_DOUBLE); + assertEquals(g2.memberLayouts().get(j), ValueLayout.JAVA_DOUBLE); } else { assertEquals(g2.memberLayouts().get(j), g.memberLayouts().get(j)); } @@ -380,12 +379,12 @@ public class TestLayoutPaths { @Test public void testSequencePaths() { long[] offsets = { 0, 8, 16, 24 }; - SequenceLayout g = MemoryLayout.sequenceLayout(4, MemoryLayouts.JAVA_BYTE); + SequenceLayout g = MemoryLayout.sequenceLayout(4, ValueLayout.JAVA_BYTE); // test select MemoryLayout selected = g.select(sequenceElement()); - assertTrue(selected == MemoryLayouts.JAVA_BYTE); + assertTrue(selected == ValueLayout.JAVA_BYTE); // test offset @@ -398,8 +397,8 @@ public class TestLayoutPaths { // test map - SequenceLayout seq2 = (SequenceLayout)g.map(l -> MemoryLayouts.JAVA_DOUBLE, sequenceElement()); - assertTrue(seq2.elementLayout() == MemoryLayouts.JAVA_DOUBLE); + SequenceLayout seq2 = (SequenceLayout)g.map(l -> ValueLayout.JAVA_DOUBLE, sequenceElement()); + assertTrue(seq2.elementLayout() == ValueLayout.JAVA_DOUBLE); } @Test(dataProvider = "testLayouts") @@ -506,26 +505,16 @@ public class TestLayoutPaths { try (ResourceScope scope = ResourceScope.newConfinedScope()) { MemorySegment segment = MemorySegment.allocateNative(layout, scope); MemorySegment slice = (MemorySegment) sliceHandle.invokeExact(segment, indexes); - assertEquals(slice.address().segmentOffset(segment), expectedBitOffset / 8); + assertEquals(slice.address().toRawLongValue() - segment.address().toRawLongValue(), expectedBitOffset / 8); assertEquals(slice.byteSize(), selected.byteSize()); } } - @Test(expectedExceptions = UnsupportedOperationException.class) - public void testSliceHandleUOEInvalidSize() { - MemoryLayout layout = MemoryLayout.structLayout( - MemoryLayout.valueLayout(32, ByteOrder.nativeOrder()).withName("x"), - MemoryLayout.valueLayout(31, ByteOrder.nativeOrder()).withName("y") // size not a multiple of 8 - ); - - layout.sliceHandle(groupElement("y")); // should throw - } - @Test(expectedExceptions = UnsupportedOperationException.class) public void testSliceHandleUOEInvalidOffsetEager() throws Throwable { MemoryLayout layout = MemoryLayout.structLayout( MemoryLayout.paddingLayout(5), - MemoryLayout.valueLayout(32, ByteOrder.nativeOrder()).withName("y") // offset not a multiple of 8 + JAVA_INT.withName("y") // offset not a multiple of 8 ); layout.sliceHandle(groupElement("y")); // should throw @@ -536,7 +525,7 @@ public class TestLayoutPaths { MemoryLayout layout = MemoryLayout.sequenceLayout(3, MemoryLayout.structLayout( MemoryLayout.paddingLayout(4), - MemoryLayout.valueLayout(32, ByteOrder.nativeOrder()).withName("y") // offset not a multiple of 8 + JAVA_INT.withName("y") // offset not a multiple of 8 ) ); diff --git a/test/jdk/java/foreign/TestLayouts.java b/test/jdk/java/foreign/TestLayouts.java index 006163d3d503a2d44e160e927b2f2580ead9c660..6d54bef722d2b8ac2d9e25cc347dca3275e6dc88 100644 --- a/test/jdk/java/foreign/TestLayouts.java +++ b/test/jdk/java/foreign/TestLayouts.java @@ -34,15 +34,15 @@ import java.util.function.LongFunction; import java.util.stream.Stream; import org.testng.annotations.*; + +import static jdk.incubator.foreign.ValueLayout.JAVA_BYTE; +import static jdk.incubator.foreign.ValueLayout.JAVA_INT; +import static jdk.incubator.foreign.ValueLayout.JAVA_LONG; +import static jdk.incubator.foreign.ValueLayout.JAVA_SHORT; import static org.testng.Assert.*; public class TestLayouts { - @Test(dataProvider = "badLayoutSizes", expectedExceptions = IllegalArgumentException.class) - public void testBadLayoutSize(SizedLayoutFactory factory, long size) { - factory.make(size); - } - @Test(dataProvider = "badAlignments", expectedExceptions = IllegalArgumentException.class) public void testBadLayoutAlignment(MemoryLayout layout, long alignment) { layout.withBitAlignment(alignment); @@ -51,12 +51,12 @@ public class TestLayouts { @Test public void testVLAInStruct() { MemoryLayout layout = MemoryLayout.structLayout( - MemoryLayouts.JAVA_INT.withName("size"), + ValueLayout.JAVA_INT.withName("size"), MemoryLayout.paddingLayout(32), - MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_DOUBLE).withName("arr")); + MemoryLayout.sequenceLayout(ValueLayout.JAVA_DOUBLE).withName("arr")); assertFalse(layout.hasSize()); - VarHandle size_handle = layout.varHandle(int.class, MemoryLayout.PathElement.groupElement("size")); - VarHandle array_elem_handle = layout.varHandle(double.class, + VarHandle size_handle = layout.varHandle(MemoryLayout.PathElement.groupElement("size")); + VarHandle array_elem_handle = layout.varHandle( MemoryLayout.PathElement.groupElement("arr"), MemoryLayout.PathElement.sequenceElement()); try (ResourceScope scope = ResourceScope.newConfinedScope()) { @@ -77,12 +77,12 @@ public class TestLayouts { @Test public void testVLAInSequence() { MemoryLayout layout = MemoryLayout.structLayout( - MemoryLayouts.JAVA_INT.withName("size"), + ValueLayout.JAVA_INT.withName("size"), MemoryLayout.paddingLayout(32), - MemoryLayout.sequenceLayout(1, MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_DOUBLE)).withName("arr")); + MemoryLayout.sequenceLayout(1, MemoryLayout.sequenceLayout(ValueLayout.JAVA_DOUBLE)).withName("arr")); assertFalse(layout.hasSize()); - VarHandle size_handle = layout.varHandle(int.class, MemoryLayout.PathElement.groupElement("size")); - VarHandle array_elem_handle = layout.varHandle(double.class, + VarHandle size_handle = layout.varHandle(MemoryLayout.PathElement.groupElement("size")); + VarHandle array_elem_handle = layout.varHandle( MemoryLayout.PathElement.groupElement("arr"), MemoryLayout.PathElement.sequenceElement(0), MemoryLayout.PathElement.sequenceElement()); @@ -103,17 +103,17 @@ public class TestLayouts { @Test public void testIndexedSequencePath() { - MemoryLayout seq = MemoryLayout.sequenceLayout(10, MemoryLayouts.JAVA_INT); + MemoryLayout seq = MemoryLayout.sequenceLayout(10, ValueLayout.JAVA_INT); try (ResourceScope scope = ResourceScope.newConfinedScope()) { MemorySegment segment = MemorySegment.allocateNative(seq, scope); - VarHandle indexHandle = seq.varHandle(int.class, MemoryLayout.PathElement.sequenceElement()); + VarHandle indexHandle = seq.varHandle(MemoryLayout.PathElement.sequenceElement()); // init segment for (int i = 0 ; i < 10 ; i++) { indexHandle.set(segment, (long)i, i); } //check statically indexed handles for (int i = 0 ; i < 10 ; i++) { - VarHandle preindexHandle = seq.varHandle(int.class, MemoryLayout.PathElement.sequenceElement(i)); + VarHandle preindexHandle = seq.varHandle(MemoryLayout.PathElement.sequenceElement(i)); int expected = (int)indexHandle.get(segment, (long)i); int found = (int)preindexHandle.get(segment); assertEquals(expected, found); @@ -143,13 +143,13 @@ public class TestLayouts { @Test(expectedExceptions = IllegalArgumentException.class) public void testBadUnboundSequenceLayoutResize() { - SequenceLayout seq = MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_INT); + SequenceLayout seq = MemoryLayout.sequenceLayout(ValueLayout.JAVA_INT); seq.withElementCount(-1); } @Test(expectedExceptions = IllegalArgumentException.class) public void testBadBoundSequenceLayoutResize() { - SequenceLayout seq = MemoryLayout.sequenceLayout(10, MemoryLayouts.JAVA_INT); + SequenceLayout seq = MemoryLayout.sequenceLayout(10, ValueLayout.JAVA_INT); seq.withElementCount(-1); } @@ -168,13 +168,13 @@ public class TestLayouts { public void testStructSizeAndAlign() { MemoryLayout struct = MemoryLayout.structLayout( MemoryLayout.paddingLayout(8), - MemoryLayouts.JAVA_BYTE, - MemoryLayouts.JAVA_CHAR, - MemoryLayouts.JAVA_INT, - MemoryLayouts.JAVA_LONG + ValueLayout.JAVA_BYTE, + ValueLayout.JAVA_CHAR, + ValueLayout.JAVA_INT, + ValueLayout.JAVA_LONG ); assertEquals(struct.byteSize(), 1 + 1 + 2 + 4 + 8); - assertEquals(struct.byteAlignment(), MemoryLayouts.ADDRESS.byteAlignment()); + assertEquals(struct.byteAlignment(), ValueLayout.ADDRESS.byteAlignment()); } @Test(dataProvider="basicLayouts") @@ -199,13 +199,13 @@ public class TestLayouts { @Test public void testUnionSizeAndAlign() { MemoryLayout struct = MemoryLayout.unionLayout( - MemoryLayouts.JAVA_BYTE, - MemoryLayouts.JAVA_CHAR, - MemoryLayouts.JAVA_INT, - MemoryLayouts.JAVA_LONG + ValueLayout.JAVA_BYTE, + ValueLayout.JAVA_CHAR, + ValueLayout.JAVA_INT, + ValueLayout.JAVA_LONG ); assertEquals(struct.byteSize(), 8); - assertEquals(struct.byteAlignment(), MemoryLayouts.ADDRESS.byteAlignment()); + assertEquals(struct.byteAlignment(), ValueLayout.ADDRESS.byteAlignment()); } @Test(dataProvider = "layoutKinds") @@ -224,31 +224,19 @@ public class TestLayouts { } } - @DataProvider(name = "badLayoutSizes") - public Object[][] factoriesAndSizes() { - return new Object[][] { - { SizedLayoutFactory.VALUE_BE, 0 }, - { SizedLayoutFactory.VALUE_BE, -1 }, - { SizedLayoutFactory.VALUE_LE, 0 }, - { SizedLayoutFactory.VALUE_LE, -1 }, - { SizedLayoutFactory.PADDING, 0 }, - { SizedLayoutFactory.PADDING, -1 }, - { SizedLayoutFactory.SEQUENCE, -1 } - }; - } - @DataProvider(name = "unboundLayouts") public Object[][] unboundLayouts() { + ValueLayout alignedInt = JAVA_INT.withBitAlignment(32); return new Object[][] { - { MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_INT), 32 }, - { MemoryLayout.sequenceLayout(MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_INT)), 32 }, - { MemoryLayout.sequenceLayout(4, MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_INT)), 32 }, - { MemoryLayout.structLayout(MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_INT)), 32 }, - { MemoryLayout.structLayout(MemoryLayout.sequenceLayout(MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_INT))), 32 }, - { MemoryLayout.structLayout(MemoryLayout.sequenceLayout(4, MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_INT))), 32 }, - { MemoryLayout.unionLayout(MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_INT)), 32 }, - { MemoryLayout.unionLayout(MemoryLayout.sequenceLayout(MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_INT))), 32 }, - { MemoryLayout.unionLayout(MemoryLayout.sequenceLayout(4, MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_INT))), 32 }, + { MemoryLayout.sequenceLayout(alignedInt), 32 }, + { MemoryLayout.sequenceLayout(MemoryLayout.sequenceLayout(alignedInt)), 32 }, + { MemoryLayout.sequenceLayout(4, MemoryLayout.sequenceLayout(alignedInt)), 32 }, + { MemoryLayout.structLayout(MemoryLayout.sequenceLayout(alignedInt)), 32 }, + { MemoryLayout.structLayout(MemoryLayout.sequenceLayout(MemoryLayout.sequenceLayout(alignedInt))), 32 }, + { MemoryLayout.structLayout(MemoryLayout.sequenceLayout(4, MemoryLayout.sequenceLayout(alignedInt))), 32 }, + { MemoryLayout.unionLayout(MemoryLayout.sequenceLayout(alignedInt)), 32 }, + { MemoryLayout.unionLayout(MemoryLayout.sequenceLayout(MemoryLayout.sequenceLayout(alignedInt))), 32 }, + { MemoryLayout.unionLayout(MemoryLayout.sequenceLayout(4, MemoryLayout.sequenceLayout(alignedInt))), 32 }, }; } @@ -271,10 +259,10 @@ public class TestLayouts { } enum SizedLayoutFactory { - VALUE_LE(size -> MemoryLayout.valueLayout(size, ByteOrder.LITTLE_ENDIAN)), - VALUE_BE(size -> MemoryLayout.valueLayout(size, ByteOrder.BIG_ENDIAN)), + VALUE_LE(size -> valueLayoutForSize((int)size).withOrder(ByteOrder.LITTLE_ENDIAN)), + VALUE_BE(size -> valueLayoutForSize((int)size).withOrder(ByteOrder.BIG_ENDIAN)), PADDING(MemoryLayout::paddingLayout), - SEQUENCE(size -> MemoryLayout.sequenceLayout(size, MemoryLayouts.PAD_8)); + SEQUENCE(size -> MemoryLayout.sequenceLayout(size, MemoryLayout.paddingLayout(8))); private final LongFunction<MemoryLayout> factory; @@ -287,13 +275,22 @@ public class TestLayouts { } } + static ValueLayout valueLayoutForSize(int size) { + return switch (size) { + case 1 -> JAVA_BYTE; + case 2 -> JAVA_SHORT; + case 4 -> JAVA_INT; + case 8 -> JAVA_LONG; + default -> throw new UnsupportedOperationException(); + }; + } + enum LayoutKind { - VALUE_LE(MemoryLayouts.BITS_8_LE), - VALUE_BE(MemoryLayouts.BITS_8_BE), - PADDING(MemoryLayouts.PAD_8), - SEQUENCE(MemoryLayout.sequenceLayout(1, MemoryLayouts.PAD_8)), - STRUCT(MemoryLayout.structLayout(MemoryLayouts.PAD_8, MemoryLayouts.PAD_8)), - UNION(MemoryLayout.unionLayout(MemoryLayouts.PAD_8, MemoryLayouts.PAD_8)); + VALUE(ValueLayout.JAVA_BYTE), + PADDING(MemoryLayout.paddingLayout(8)), + SEQUENCE(MemoryLayout.sequenceLayout(1, MemoryLayout.paddingLayout(8))), + STRUCT(MemoryLayout.structLayout(MemoryLayout.paddingLayout(8), MemoryLayout.paddingLayout(8))), + UNION(MemoryLayout.unionLayout(MemoryLayout.paddingLayout(8), MemoryLayout.paddingLayout(8))); final MemoryLayout layout; @@ -333,12 +330,12 @@ public class TestLayouts { } static MemoryLayout[] basicLayouts = { - MemoryLayouts.JAVA_BYTE, - MemoryLayouts.JAVA_CHAR, - MemoryLayouts.JAVA_SHORT, - MemoryLayouts.JAVA_INT, - MemoryLayouts.JAVA_FLOAT, - MemoryLayouts.JAVA_LONG, - MemoryLayouts.JAVA_DOUBLE, + ValueLayout.JAVA_BYTE, + ValueLayout.JAVA_CHAR, + ValueLayout.JAVA_SHORT, + ValueLayout.JAVA_INT, + ValueLayout.JAVA_FLOAT, + ValueLayout.JAVA_LONG, + ValueLayout.JAVA_DOUBLE, }; } diff --git a/test/jdk/java/foreign/TestMemoryAccess.java b/test/jdk/java/foreign/TestMemoryAccess.java index d843c7b0b3921dbf023fd2a4b3fbfc66a519a8b2..7eade5f8147d4822292ba0e989d4b3c5e241f8d7 100644 --- a/test/jdk/java/foreign/TestMemoryAccess.java +++ b/test/jdk/java/foreign/TestMemoryAccess.java @@ -30,7 +30,7 @@ */ import jdk.incubator.foreign.GroupLayout; -import jdk.incubator.foreign.MemoryLayouts; +import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.MemoryLayout.PathElement; import jdk.incubator.foreign.MemorySegment; @@ -39,6 +39,7 @@ import jdk.incubator.foreign.SequenceLayout; import jdk.incubator.foreign.ValueLayout; import java.lang.invoke.VarHandle; +import java.nio.ByteOrder; import java.util.function.Function; import org.testng.annotations.*; @@ -47,39 +48,39 @@ import static org.testng.Assert.*; public class TestMemoryAccess { @Test(dataProvider = "elements") - public void testAccess(Function<MemorySegment, MemorySegment> viewFactory, ValueLayout elemLayout, Class<?> carrier, Checker checker) { + public void testAccess(Function<MemorySegment, MemorySegment> viewFactory, ValueLayout elemLayout, Checker checker) { ValueLayout layout = elemLayout.withName("elem"); - testAccessInternal(viewFactory, layout, layout.varHandle(carrier), checker); + testAccessInternal(viewFactory, layout, layout.varHandle(), checker); } @Test(dataProvider = "elements") - public void testPaddedAccessByName(Function<MemorySegment, MemorySegment> viewFactory, MemoryLayout elemLayout, Class<?> carrier, Checker checker) { + public void testPaddedAccessByName(Function<MemorySegment, MemorySegment> viewFactory, MemoryLayout elemLayout, Checker checker) { GroupLayout layout = MemoryLayout.structLayout(MemoryLayout.paddingLayout(elemLayout.bitSize()), elemLayout.withName("elem")); - testAccessInternal(viewFactory, layout, layout.varHandle(carrier, PathElement.groupElement("elem")), checker); + testAccessInternal(viewFactory, layout, layout.varHandle(PathElement.groupElement("elem")), checker); } @Test(dataProvider = "elements") - public void testPaddedAccessByIndexSeq(Function<MemorySegment, MemorySegment> viewFactory, MemoryLayout elemLayout, Class<?> carrier, Checker checker) { + public void testPaddedAccessByIndexSeq(Function<MemorySegment, MemorySegment> viewFactory, MemoryLayout elemLayout, Checker checker) { SequenceLayout layout = MemoryLayout.sequenceLayout(2, elemLayout); - testAccessInternal(viewFactory, layout, layout.varHandle(carrier, PathElement.sequenceElement(1)), checker); + testAccessInternal(viewFactory, layout, layout.varHandle(PathElement.sequenceElement(1)), checker); } @Test(dataProvider = "arrayElements") - public void testArrayAccess(Function<MemorySegment, MemorySegment> viewFactory, MemoryLayout elemLayout, Class<?> carrier, ArrayChecker checker) { + public void testArrayAccess(Function<MemorySegment, MemorySegment> viewFactory, MemoryLayout elemLayout, ArrayChecker checker) { SequenceLayout seq = MemoryLayout.sequenceLayout(10, elemLayout.withName("elem")); - testArrayAccessInternal(viewFactory, seq, seq.varHandle(carrier, PathElement.sequenceElement()), checker); + testArrayAccessInternal(viewFactory, seq, seq.varHandle(PathElement.sequenceElement()), checker); } @Test(dataProvider = "arrayElements") - public void testPaddedArrayAccessByName(Function<MemorySegment, MemorySegment> viewFactory, MemoryLayout elemLayout, Class<?> carrier, ArrayChecker checker) { + public void testPaddedArrayAccessByName(Function<MemorySegment, MemorySegment> viewFactory, MemoryLayout elemLayout, ArrayChecker checker) { SequenceLayout seq = MemoryLayout.sequenceLayout(10, MemoryLayout.structLayout(MemoryLayout.paddingLayout(elemLayout.bitSize()), elemLayout.withName("elem"))); - testArrayAccessInternal(viewFactory, seq, seq.varHandle(carrier, MemoryLayout.PathElement.sequenceElement(), MemoryLayout.PathElement.groupElement("elem")), checker); + testArrayAccessInternal(viewFactory, seq, seq.varHandle(MemoryLayout.PathElement.sequenceElement(), MemoryLayout.PathElement.groupElement("elem")), checker); } @Test(dataProvider = "arrayElements") - public void testPaddedArrayAccessByIndexSeq(Function<MemorySegment, MemorySegment> viewFactory, MemoryLayout elemLayout, Class<?> carrier, ArrayChecker checker) { + public void testPaddedArrayAccessByIndexSeq(Function<MemorySegment, MemorySegment> viewFactory, MemoryLayout elemLayout, ArrayChecker checker) { SequenceLayout seq = MemoryLayout.sequenceLayout(10, MemoryLayout.sequenceLayout(2, elemLayout)); - testArrayAccessInternal(viewFactory, seq, seq.varHandle(carrier, PathElement.sequenceElement(), MemoryLayout.PathElement.sequenceElement(1)), checker); + testArrayAccessInternal(viewFactory, seq, seq.varHandle(PathElement.sequenceElement(), MemoryLayout.PathElement.sequenceElement(1)), checker); } private void testAccessInternal(Function<MemorySegment, MemorySegment> viewFactory, MemoryLayout layout, VarHandle handle, Checker checker) { @@ -149,40 +150,33 @@ public class TestMemoryAccess { } @Test(dataProvider = "matrixElements") - public void testMatrixAccess(Function<MemorySegment, MemorySegment> viewFactory, MemoryLayout elemLayout, Class<?> carrier, MatrixChecker checker) { + public void testMatrixAccess(Function<MemorySegment, MemorySegment> viewFactory, MemoryLayout elemLayout, MatrixChecker checker) { SequenceLayout seq = MemoryLayout.sequenceLayout(20, MemoryLayout.sequenceLayout(10, elemLayout.withName("elem"))); - testMatrixAccessInternal(viewFactory, seq, seq.varHandle(carrier, + testMatrixAccessInternal(viewFactory, seq, seq.varHandle( PathElement.sequenceElement(), PathElement.sequenceElement()), checker); } @Test(dataProvider = "matrixElements") - public void testPaddedMatrixAccessByName(Function<MemorySegment, MemorySegment> viewFactory, MemoryLayout elemLayout, Class<?> carrier, MatrixChecker checker) { + public void testPaddedMatrixAccessByName(Function<MemorySegment, MemorySegment> viewFactory, MemoryLayout elemLayout, MatrixChecker checker) { SequenceLayout seq = MemoryLayout.sequenceLayout(20, MemoryLayout.sequenceLayout(10, MemoryLayout.structLayout(MemoryLayout.paddingLayout(elemLayout.bitSize()), elemLayout.withName("elem")))); testMatrixAccessInternal(viewFactory, seq, - seq.varHandle(carrier, + seq.varHandle( PathElement.sequenceElement(), PathElement.sequenceElement(), PathElement.groupElement("elem")), checker); } @Test(dataProvider = "matrixElements") - public void testPaddedMatrixAccessByIndexSeq(Function<MemorySegment, MemorySegment> viewFactory, MemoryLayout elemLayout, Class<?> carrier, MatrixChecker checker) { + public void testPaddedMatrixAccessByIndexSeq(Function<MemorySegment, MemorySegment> viewFactory, MemoryLayout elemLayout, MatrixChecker checker) { SequenceLayout seq = MemoryLayout.sequenceLayout(20, MemoryLayout.sequenceLayout(10, MemoryLayout.sequenceLayout(2, elemLayout))); testMatrixAccessInternal(viewFactory, seq, - seq.varHandle(carrier, + seq.varHandle( PathElement.sequenceElement(), PathElement.sequenceElement(), PathElement.sequenceElement(1)), checker); } - @Test(dataProvider = "badCarriers", - expectedExceptions = IllegalArgumentException.class) - public void testBadCarriers(Class<?> carrier) { - ValueLayout l = MemoryLayouts.BITS_32_LE.withName("elem"); - l.varHandle(carrier); - } - private void testMatrixAccessInternal(Function<MemorySegment, MemorySegment> viewFactory, SequenceLayout seq, VarHandle handle, MatrixChecker checker) { MemorySegment outer_segment; try (ResourceScope scope = ResourceScope.newConfinedScope()) { @@ -227,37 +221,37 @@ public class TestMemoryAccess { public Object[][] createData() { return new Object[][] { //BE, RW - { ID, MemoryLayouts.BITS_8_BE, byte.class, Checker.BYTE }, - { ID, MemoryLayouts.BITS_16_BE, short.class, Checker.SHORT }, - { ID, MemoryLayouts.BITS_16_BE, char.class, Checker.CHAR }, - { ID, MemoryLayouts.BITS_32_BE, int.class, Checker.INT }, - { ID, MemoryLayouts.BITS_64_BE, long.class, Checker.LONG }, - { ID, MemoryLayouts.BITS_32_BE, float.class, Checker.FLOAT }, - { ID, MemoryLayouts.BITS_64_BE, double.class, Checker.DOUBLE }, + { ID, ValueLayout.JAVA_BYTE, Checker.BYTE }, + { ID, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.BIG_ENDIAN), Checker.SHORT }, + { ID, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.BIG_ENDIAN), Checker.CHAR }, + { ID, ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN), Checker.INT }, + { ID, ValueLayout.JAVA_LONG.withOrder(ByteOrder.BIG_ENDIAN), Checker.LONG }, + { ID, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.BIG_ENDIAN), Checker.FLOAT }, + { ID, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.BIG_ENDIAN), Checker.DOUBLE }, //BE, RO - { IMMUTABLE, MemoryLayouts.BITS_8_BE, byte.class, Checker.BYTE }, - { IMMUTABLE, MemoryLayouts.BITS_16_BE, short.class, Checker.SHORT }, - { IMMUTABLE, MemoryLayouts.BITS_16_BE, char.class, Checker.CHAR }, - { IMMUTABLE, MemoryLayouts.BITS_32_BE, int.class, Checker.INT }, - { IMMUTABLE, MemoryLayouts.BITS_64_BE, long.class, Checker.LONG }, - { IMMUTABLE, MemoryLayouts.BITS_32_BE, float.class, Checker.FLOAT }, - { IMMUTABLE, MemoryLayouts.BITS_64_BE, double.class, Checker.DOUBLE }, + { IMMUTABLE, ValueLayout.JAVA_BYTE, Checker.BYTE }, + { IMMUTABLE, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.BIG_ENDIAN), Checker.SHORT }, + { IMMUTABLE, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.BIG_ENDIAN), Checker.CHAR }, + { IMMUTABLE, ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN), Checker.INT }, + { IMMUTABLE, ValueLayout.JAVA_LONG.withOrder(ByteOrder.BIG_ENDIAN), Checker.LONG }, + { IMMUTABLE, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.BIG_ENDIAN), Checker.FLOAT }, + { IMMUTABLE, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.BIG_ENDIAN), Checker.DOUBLE }, //LE, RW - { ID, MemoryLayouts.BITS_8_LE, byte.class, Checker.BYTE }, - { ID, MemoryLayouts.BITS_16_LE, short.class, Checker.SHORT }, - { ID, MemoryLayouts.BITS_16_LE, char.class, Checker.CHAR }, - { ID, MemoryLayouts.BITS_32_LE, int.class, Checker.INT }, - { ID, MemoryLayouts.BITS_64_LE, long.class, Checker.LONG }, - { ID, MemoryLayouts.BITS_32_LE, float.class, Checker.FLOAT }, - { ID, MemoryLayouts.BITS_64_LE, double.class, Checker.DOUBLE }, + { ID, ValueLayout.JAVA_BYTE, Checker.BYTE }, + { ID, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.LITTLE_ENDIAN), Checker.SHORT }, + { ID, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.LITTLE_ENDIAN), Checker.CHAR }, + { ID, ValueLayout.JAVA_INT.withOrder(ByteOrder.LITTLE_ENDIAN), Checker.INT }, + { ID, ValueLayout.JAVA_LONG.withOrder(ByteOrder.LITTLE_ENDIAN), Checker.LONG }, + { ID, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.LITTLE_ENDIAN), Checker.FLOAT }, + { ID, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.LITTLE_ENDIAN), Checker.DOUBLE }, //LE, RO - { IMMUTABLE, MemoryLayouts.BITS_8_LE, byte.class, Checker.BYTE }, - { IMMUTABLE, MemoryLayouts.BITS_16_LE, short.class, Checker.SHORT }, - { IMMUTABLE, MemoryLayouts.BITS_16_LE, char.class, Checker.CHAR }, - { IMMUTABLE, MemoryLayouts.BITS_32_LE, int.class, Checker.INT }, - { IMMUTABLE, MemoryLayouts.BITS_64_LE, long.class, Checker.LONG }, - { IMMUTABLE, MemoryLayouts.BITS_32_LE, float.class, Checker.FLOAT }, - { IMMUTABLE, MemoryLayouts.BITS_64_LE, double.class, Checker.DOUBLE }, + { IMMUTABLE, ValueLayout.JAVA_BYTE, Checker.BYTE }, + { IMMUTABLE, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.LITTLE_ENDIAN), Checker.SHORT }, + { IMMUTABLE, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.LITTLE_ENDIAN), Checker.CHAR }, + { IMMUTABLE, ValueLayout.JAVA_INT.withOrder(ByteOrder.LITTLE_ENDIAN), Checker.INT }, + { IMMUTABLE, ValueLayout.JAVA_LONG.withOrder(ByteOrder.LITTLE_ENDIAN), Checker.LONG }, + { IMMUTABLE, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.LITTLE_ENDIAN), Checker.FLOAT }, + { IMMUTABLE, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.LITTLE_ENDIAN), Checker.DOUBLE }, }; } @@ -304,37 +298,37 @@ public class TestMemoryAccess { public Object[][] createArrayData() { return new Object[][] { //BE, RW - { ID, MemoryLayouts.BITS_8_BE, byte.class, ArrayChecker.BYTE }, - { ID, MemoryLayouts.BITS_16_BE, short.class, ArrayChecker.SHORT }, - { ID, MemoryLayouts.BITS_16_BE, char.class, ArrayChecker.CHAR }, - { ID, MemoryLayouts.BITS_32_BE, int.class, ArrayChecker.INT }, - { ID, MemoryLayouts.BITS_64_BE, long.class, ArrayChecker.LONG }, - { ID, MemoryLayouts.BITS_32_BE, float.class, ArrayChecker.FLOAT }, - { ID, MemoryLayouts.BITS_64_BE, double.class, ArrayChecker.DOUBLE }, + { ID, ValueLayout.JAVA_BYTE, ArrayChecker.BYTE }, + { ID, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.BIG_ENDIAN), ArrayChecker.SHORT }, + { ID, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.BIG_ENDIAN), ArrayChecker.CHAR }, + { ID, ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN), ArrayChecker.INT }, + { ID, ValueLayout.JAVA_LONG.withOrder(ByteOrder.BIG_ENDIAN), ArrayChecker.LONG }, + { ID, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.BIG_ENDIAN), ArrayChecker.FLOAT }, + { ID, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.BIG_ENDIAN), ArrayChecker.DOUBLE }, //BE, RO - { IMMUTABLE, MemoryLayouts.BITS_8_BE, byte.class, ArrayChecker.BYTE }, - { IMMUTABLE, MemoryLayouts.BITS_16_BE, short.class, ArrayChecker.SHORT }, - { IMMUTABLE, MemoryLayouts.BITS_16_BE, char.class, ArrayChecker.CHAR }, - { IMMUTABLE, MemoryLayouts.BITS_32_BE, int.class, ArrayChecker.INT }, - { IMMUTABLE, MemoryLayouts.BITS_64_BE, long.class, ArrayChecker.LONG }, - { IMMUTABLE, MemoryLayouts.BITS_32_BE, float.class, ArrayChecker.FLOAT }, - { IMMUTABLE, MemoryLayouts.BITS_64_BE, double.class, ArrayChecker.DOUBLE }, + { IMMUTABLE, ValueLayout.JAVA_BYTE, ArrayChecker.BYTE }, + { IMMUTABLE, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.BIG_ENDIAN), ArrayChecker.SHORT }, + { IMMUTABLE, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.BIG_ENDIAN), ArrayChecker.CHAR }, + { IMMUTABLE, ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN), ArrayChecker.INT }, + { IMMUTABLE, ValueLayout.JAVA_LONG.withOrder(ByteOrder.BIG_ENDIAN), ArrayChecker.LONG }, + { IMMUTABLE, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.BIG_ENDIAN), ArrayChecker.FLOAT }, + { IMMUTABLE, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.BIG_ENDIAN), ArrayChecker.DOUBLE }, //LE, RW - { ID, MemoryLayouts.BITS_8_LE, byte.class, ArrayChecker.BYTE }, - { ID, MemoryLayouts.BITS_16_LE, short.class, ArrayChecker.SHORT }, - { ID, MemoryLayouts.BITS_16_LE, char.class, ArrayChecker.CHAR }, - { ID, MemoryLayouts.BITS_32_LE, int.class, ArrayChecker.INT }, - { ID, MemoryLayouts.BITS_64_LE, long.class, ArrayChecker.LONG }, - { ID, MemoryLayouts.BITS_32_LE, float.class, ArrayChecker.FLOAT }, - { ID, MemoryLayouts.BITS_64_LE, double.class, ArrayChecker.DOUBLE }, + { ID, ValueLayout.JAVA_BYTE, ArrayChecker.BYTE }, + { ID, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.LITTLE_ENDIAN), ArrayChecker.SHORT }, + { ID, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.LITTLE_ENDIAN), ArrayChecker.CHAR }, + { ID, ValueLayout.JAVA_INT.withOrder(ByteOrder.LITTLE_ENDIAN), ArrayChecker.INT }, + { ID, ValueLayout.JAVA_LONG.withOrder(ByteOrder.LITTLE_ENDIAN), ArrayChecker.LONG }, + { ID, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.LITTLE_ENDIAN), ArrayChecker.FLOAT }, + { ID, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.LITTLE_ENDIAN), ArrayChecker.DOUBLE }, //LE, RO - { IMMUTABLE, MemoryLayouts.BITS_8_LE, byte.class, ArrayChecker.BYTE }, - { IMMUTABLE, MemoryLayouts.BITS_16_LE, short.class, ArrayChecker.SHORT }, - { IMMUTABLE, MemoryLayouts.BITS_16_LE, char.class, ArrayChecker.CHAR }, - { IMMUTABLE, MemoryLayouts.BITS_32_LE, int.class, ArrayChecker.INT }, - { IMMUTABLE, MemoryLayouts.BITS_64_LE, long.class, ArrayChecker.LONG }, - { IMMUTABLE, MemoryLayouts.BITS_32_LE, float.class, ArrayChecker.FLOAT }, - { IMMUTABLE, MemoryLayouts.BITS_64_LE, double.class, ArrayChecker.DOUBLE }, + { IMMUTABLE, ValueLayout.JAVA_BYTE, ArrayChecker.BYTE }, + { IMMUTABLE, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.LITTLE_ENDIAN), ArrayChecker.SHORT }, + { IMMUTABLE, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.LITTLE_ENDIAN), ArrayChecker.CHAR }, + { IMMUTABLE, ValueLayout.JAVA_INT.withOrder(ByteOrder.LITTLE_ENDIAN), ArrayChecker.INT }, + { IMMUTABLE, ValueLayout.JAVA_LONG.withOrder(ByteOrder.LITTLE_ENDIAN), ArrayChecker.LONG }, + { IMMUTABLE, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.LITTLE_ENDIAN), ArrayChecker.FLOAT }, + { IMMUTABLE, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.LITTLE_ENDIAN), ArrayChecker.DOUBLE }, }; } @@ -381,37 +375,45 @@ public class TestMemoryAccess { public Object[][] createMatrixData() { return new Object[][] { //BE, RW - { ID, MemoryLayouts.BITS_8_BE, byte.class, MatrixChecker.BYTE }, - { ID, MemoryLayouts.BITS_16_BE, short.class, MatrixChecker.SHORT }, - { ID, MemoryLayouts.BITS_16_BE, char.class, MatrixChecker.CHAR }, - { ID, MemoryLayouts.BITS_32_BE, int.class, MatrixChecker.INT }, - { ID, MemoryLayouts.BITS_64_BE, long.class, MatrixChecker.LONG }, - { ID, MemoryLayouts.BITS_32_BE, float.class, MatrixChecker.FLOAT }, - { ID, MemoryLayouts.BITS_64_BE, double.class, MatrixChecker.DOUBLE }, + { ID, ValueLayout.JAVA_BYTE, MatrixChecker.BYTE }, + { ID, ValueLayout.JAVA_BOOLEAN, MatrixChecker.BOOLEAN }, + { ID, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.BIG_ENDIAN), MatrixChecker.SHORT }, + { ID, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.BIG_ENDIAN), MatrixChecker.CHAR }, + { ID, ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN), MatrixChecker.INT }, + { ID, ValueLayout.JAVA_LONG.withOrder(ByteOrder.BIG_ENDIAN), MatrixChecker.LONG }, + { ID, ValueLayout.ADDRESS.withOrder(ByteOrder.BIG_ENDIAN), MatrixChecker.ADDR }, + { ID, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.BIG_ENDIAN), MatrixChecker.FLOAT }, + { ID, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.BIG_ENDIAN), MatrixChecker.DOUBLE }, //BE, RO - { IMMUTABLE, MemoryLayouts.BITS_8_BE, byte.class, MatrixChecker.BYTE }, - { IMMUTABLE, MemoryLayouts.BITS_16_BE, short.class, MatrixChecker.SHORT }, - { IMMUTABLE, MemoryLayouts.BITS_16_BE, char.class, MatrixChecker.CHAR }, - { IMMUTABLE, MemoryLayouts.BITS_32_BE, int.class, MatrixChecker.INT }, - { IMMUTABLE, MemoryLayouts.BITS_64_BE, long.class, MatrixChecker.LONG }, - { IMMUTABLE, MemoryLayouts.BITS_32_BE, float.class, MatrixChecker.FLOAT }, - { IMMUTABLE, MemoryLayouts.BITS_64_BE, double.class, MatrixChecker.DOUBLE }, + { IMMUTABLE, ValueLayout.JAVA_BYTE, MatrixChecker.BYTE }, + { IMMUTABLE, ValueLayout.JAVA_BOOLEAN, MatrixChecker.BOOLEAN }, + { IMMUTABLE, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.BIG_ENDIAN), MatrixChecker.SHORT }, + { IMMUTABLE, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.BIG_ENDIAN), MatrixChecker.CHAR }, + { IMMUTABLE, ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN), MatrixChecker.INT }, + { IMMUTABLE, ValueLayout.JAVA_LONG.withOrder(ByteOrder.BIG_ENDIAN), MatrixChecker.LONG }, + { IMMUTABLE, ValueLayout.ADDRESS.withOrder(ByteOrder.BIG_ENDIAN), MatrixChecker.ADDR }, + { IMMUTABLE, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.BIG_ENDIAN), MatrixChecker.FLOAT }, + { IMMUTABLE, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.BIG_ENDIAN), MatrixChecker.DOUBLE }, //LE, RW - { ID, MemoryLayouts.BITS_8_LE, byte.class, MatrixChecker.BYTE }, - { ID, MemoryLayouts.BITS_16_LE, short.class, MatrixChecker.SHORT }, - { ID, MemoryLayouts.BITS_16_LE, char.class, MatrixChecker.CHAR }, - { ID, MemoryLayouts.BITS_32_LE, int.class, MatrixChecker.INT }, - { ID, MemoryLayouts.BITS_64_LE, long.class, MatrixChecker.LONG }, - { ID, MemoryLayouts.BITS_32_LE, float.class, MatrixChecker.FLOAT }, - { ID, MemoryLayouts.BITS_64_LE, double.class, MatrixChecker.DOUBLE }, + { ID, ValueLayout.JAVA_BYTE, MatrixChecker.BYTE }, + { ID, ValueLayout.JAVA_BOOLEAN, MatrixChecker.BOOLEAN }, + { ID, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.LITTLE_ENDIAN), MatrixChecker.SHORT }, + { ID, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.LITTLE_ENDIAN), MatrixChecker.CHAR }, + { ID, ValueLayout.JAVA_INT.withOrder(ByteOrder.LITTLE_ENDIAN), MatrixChecker.INT }, + { ID, ValueLayout.JAVA_LONG.withOrder(ByteOrder.LITTLE_ENDIAN), MatrixChecker.LONG }, + { ID, ValueLayout.ADDRESS.withOrder(ByteOrder.LITTLE_ENDIAN), MatrixChecker.ADDR }, + { ID, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.LITTLE_ENDIAN), MatrixChecker.FLOAT }, + { ID, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.LITTLE_ENDIAN), MatrixChecker.DOUBLE }, //LE, RO - { IMMUTABLE, MemoryLayouts.BITS_8_LE, byte.class, MatrixChecker.BYTE }, - { IMMUTABLE, MemoryLayouts.BITS_16_LE, short.class, MatrixChecker.SHORT }, - { IMMUTABLE, MemoryLayouts.BITS_16_LE, char.class, MatrixChecker.CHAR }, - { IMMUTABLE, MemoryLayouts.BITS_32_LE, int.class, MatrixChecker.INT }, - { IMMUTABLE, MemoryLayouts.BITS_64_LE, long.class, MatrixChecker.LONG }, - { IMMUTABLE, MemoryLayouts.BITS_32_LE, float.class, MatrixChecker.FLOAT }, - { IMMUTABLE, MemoryLayouts.BITS_64_LE, double.class, MatrixChecker.DOUBLE }, + { IMMUTABLE, ValueLayout.JAVA_BYTE, MatrixChecker.BYTE }, + { IMMUTABLE, ValueLayout.JAVA_BOOLEAN, MatrixChecker.BOOLEAN }, + { IMMUTABLE, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.LITTLE_ENDIAN), MatrixChecker.SHORT }, + { IMMUTABLE, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.LITTLE_ENDIAN), MatrixChecker.CHAR }, + { IMMUTABLE, ValueLayout.JAVA_INT.withOrder(ByteOrder.LITTLE_ENDIAN), MatrixChecker.INT }, + { IMMUTABLE, ValueLayout.JAVA_LONG.withOrder(ByteOrder.LITTLE_ENDIAN), MatrixChecker.LONG }, + { IMMUTABLE, ValueLayout.ADDRESS.withOrder(ByteOrder.LITTLE_ENDIAN), MatrixChecker.ADDR }, + { IMMUTABLE, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.LITTLE_ENDIAN), MatrixChecker.FLOAT }, + { IMMUTABLE, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.LITTLE_ENDIAN), MatrixChecker.DOUBLE }, }; } @@ -423,6 +425,11 @@ public class TestMemoryAccess { assertEquals(r + c, (byte)handle.get(segment, r, c)); }; + MatrixChecker BOOLEAN = (handle, segment, r, c) -> { + handle.set(segment, r, c, (r + c) != 0); + assertEquals((r + c) != 0, (boolean)handle.get(segment, r, c)); + }; + MatrixChecker SHORT = (handle, segment, r, c) -> { handle.set(segment, r, c, (short)(r + c)); assertEquals(r + c, (short)handle.get(segment, r, c)); @@ -443,6 +450,11 @@ public class TestMemoryAccess { assertEquals(r + c, (long)handle.get(segment, r, c)); }; + MatrixChecker ADDR = (handle, segment, r, c) -> { + handle.set(segment, r, c, MemoryAddress.ofLong(r + c)); + assertEquals(MemoryAddress.ofLong(r + c), (MemoryAddress)handle.get(segment, r, c)); + }; + MatrixChecker FLOAT = (handle, segment, r, c) -> { handle.set(segment, r, c, (float)(r + c)); assertEquals((float)(r + c), (float)handle.get(segment, r, c)); @@ -453,14 +465,4 @@ public class TestMemoryAccess { assertEquals((double)(r + c), (double)handle.get(segment, r, c)); }; } - - @DataProvider(name = "badCarriers") - public Object[][] createBadCarriers() { - return new Object[][] { - { void.class }, - { boolean.class }, - { Object.class }, - { int[].class } - }; - } } diff --git a/test/jdk/java/foreign/TestMemoryAccessInstance.java b/test/jdk/java/foreign/TestMemoryAccessInstance.java new file mode 100644 index 0000000000000000000000000000000000000000..702e95bf8da38c72ef5c25b314418c36cd9bdeff --- /dev/null +++ b/test/jdk/java/foreign/TestMemoryAccessInstance.java @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @run testng/othervm --enable-native-access=ALL-UNNAMED TestMemoryAccessInstance + */ + +import jdk.incubator.foreign.MemoryAddress; +import jdk.incubator.foreign.MemorySegment; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.function.Function; + +import jdk.incubator.foreign.ResourceScope; +import jdk.incubator.foreign.ValueLayout; +import org.testng.annotations.*; +import static org.testng.Assert.*; + +public class TestMemoryAccessInstance { + + static class Accessor<T, X, L> { + + interface SegmentGetter<T, X, L> { + X get(T buffer, L layout, long offset); + } + + interface SegmentSetter<T, X, L> { + void set(T buffer, L layout, long offset, X o); + } + + interface BufferGetter<X> { + X get(ByteBuffer segment, int offset); + } + + interface BufferSetter<X> { + void set(ByteBuffer buffer, int offset, X o); + } + + final X value; + final L layout; + final Function<MemorySegment, T> transform; + final SegmentGetter<T, X, L> segmentGetter; + final SegmentSetter<T, X, L> segmentSetter; + final BufferGetter<X> bufferGetter; + final BufferSetter<X> bufferSetter; + + Accessor(Function<MemorySegment, T> transform, L layout, X value, + SegmentGetter<T, X, L> segmentGetter, SegmentSetter<T, X, L> segmentSetter, + BufferGetter<X> bufferGetter, BufferSetter<X> bufferSetter) { + this.transform = transform; + this.layout = layout; + this.value = value; + this.segmentGetter = segmentGetter; + this.segmentSetter = segmentSetter; + this.bufferGetter = bufferGetter; + this.bufferSetter = bufferSetter; + } + + void test() { + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemorySegment segment = MemorySegment.allocateNative(64, scope); + ByteBuffer buffer = segment.asByteBuffer(); + T t = transform.apply(segment); + segmentSetter.set(t, layout, 4, value); + assertEquals(bufferGetter.get(buffer, 4), value); + bufferSetter.set(buffer, 4, value); + assertEquals(value, segmentGetter.get(t, layout, 4)); + } + } + + static <L, X> Accessor<MemorySegment, X, L> ofSegment(L layout, X value, + SegmentGetter<MemorySegment, X, L> segmentGetter, SegmentSetter<MemorySegment, X, L> segmentSetter, + BufferGetter<X> bufferGetter, BufferSetter<X> bufferSetter) { + return new Accessor<>(Function.identity(), layout, value, segmentGetter, segmentSetter, bufferGetter, bufferSetter); + } + + static <L, X> Accessor<MemoryAddress, X, L> ofAddress(L layout, X value, + SegmentGetter<MemoryAddress, X, L> segmentGetter, SegmentSetter<MemoryAddress, X, L> segmentSetter, + BufferGetter<X> bufferGetter, BufferSetter<X> bufferSetter) { + return new Accessor<>(MemorySegment::address, layout, value, segmentGetter, segmentSetter, bufferGetter, bufferSetter); + } + } + + @Test(dataProvider = "segmentAccessors") + public void testSegmentAccess(String testName, Accessor<?, ?, ?> accessor) { + accessor.test(); + } + + @Test(dataProvider = "addressAccessors") + public void testAddressAccess(String testName, Accessor<?, ?, ?> accessor) { + accessor.test(); + } + + static final ByteOrder NE = ByteOrder.nativeOrder(); + + @DataProvider(name = "segmentAccessors") + static Object[][] segmentAccessors() { + return new Object[][]{ + + {"byte", Accessor.ofSegment(ValueLayout.JAVA_BYTE, (byte) 42, + MemorySegment::get, MemorySegment::set, + ByteBuffer::get, ByteBuffer::put) + }, + {"bool", Accessor.ofSegment(ValueLayout.JAVA_BOOLEAN, false, + MemorySegment::get, MemorySegment::set, + (bb, pos) -> bb.get(pos) != 0, (bb, pos, v) -> bb.put(pos, v ? (byte)1 : (byte)0)) + }, + {"char", Accessor.ofSegment(ValueLayout.JAVA_CHAR, (char) 42, + MemorySegment::get, MemorySegment::set, + (bb, pos) -> bb.order(NE).getChar(pos), (bb, pos, v) -> bb.order(NE).putChar(pos, v)) + }, + {"int", Accessor.ofSegment(ValueLayout.JAVA_INT, 42, + MemorySegment::get, MemorySegment::set, + (bb, pos) -> bb.order(NE).getInt(pos), (bb, pos, v) -> bb.order(NE).putInt(pos, v)) + }, + {"float", Accessor.ofSegment(ValueLayout.JAVA_FLOAT, 42f, + MemorySegment::get, MemorySegment::set, + (bb, pos) -> bb.order(NE).getFloat(pos), (bb, pos, v) -> bb.order(NE).putFloat(pos, v)) + }, + {"long", Accessor.ofSegment(ValueLayout.JAVA_LONG, 42L, + MemorySegment::get, MemorySegment::set, + (bb, pos) -> bb.order(NE).getLong(pos), (bb, pos, v) -> bb.order(NE).putLong(pos, v)) + }, + {"double", Accessor.ofSegment(ValueLayout.JAVA_DOUBLE, 42d, + MemorySegment::get, MemorySegment::set, + (bb, pos) -> bb.order(NE).getDouble(pos), (bb, pos, v) -> bb.order(NE).putDouble(pos, v)) + }, + { "address", Accessor.ofSegment(ValueLayout.ADDRESS, MemoryAddress.ofLong(42), + MemorySegment::get, MemorySegment::set, + (bb, pos) -> { + ByteBuffer nb = bb.order(NE); + long addr = ValueLayout.ADDRESS.byteSize() == 8 ? + nb.getLong(pos) : nb.getInt(pos); + return MemoryAddress.ofLong(addr); + }, + (bb, pos, v) -> { + ByteBuffer nb = bb.order(NE); + if (ValueLayout.ADDRESS.byteSize() == 8) { + nb.putLong(pos, v.toRawLongValue()); + } else { + nb.putInt(pos, (int)v.toRawLongValue()); + } + }) + }, + + {"char/index", Accessor.ofSegment(ValueLayout.JAVA_CHAR, (char) 42, + MemorySegment::getAtIndex, MemorySegment::setAtIndex, + (bb, pos) -> bb.order(NE).getChar(pos * 2), (bb, pos, v) -> bb.order(NE).putChar(pos * 2, v)) + }, + {"int/index", Accessor.ofSegment(ValueLayout.JAVA_INT, 42, + MemorySegment::getAtIndex, MemorySegment::setAtIndex, + (bb, pos) -> bb.order(NE).getInt(pos * 4), (bb, pos, v) -> bb.order(NE).putInt(pos * 4, v)) + }, + {"float/index", Accessor.ofSegment(ValueLayout.JAVA_FLOAT, 42f, + MemorySegment::getAtIndex, MemorySegment::setAtIndex, + (bb, pos) -> bb.order(NE).getFloat(pos * 4), (bb, pos, v) -> bb.order(NE).putFloat(pos * 4, v)) + }, + {"long/index", Accessor.ofSegment(ValueLayout.JAVA_LONG, 42L, + MemorySegment::getAtIndex, MemorySegment::setAtIndex, + (bb, pos) -> bb.order(NE).getLong(pos * 8), (bb, pos, v) -> bb.order(NE).putLong(pos * 8, v)) + }, + {"double/index", Accessor.ofSegment(ValueLayout.JAVA_DOUBLE, 42d, + MemorySegment::getAtIndex, MemorySegment::setAtIndex, + (bb, pos) -> bb.order(NE).getDouble(pos * 8), (bb, pos, v) -> bb.order(NE).putDouble(pos * 8, v)) + }, + { "address/index", Accessor.ofSegment(ValueLayout.ADDRESS, MemoryAddress.ofLong(42), + MemorySegment::getAtIndex, MemorySegment::setAtIndex, + (bb, pos) -> { + ByteBuffer nb = bb.order(NE); + long addr = ValueLayout.ADDRESS.byteSize() == 8 ? + nb.getLong(pos * 8) : nb.getInt(pos * 4); + return MemoryAddress.ofLong(addr); + }, + (bb, pos, v) -> { + ByteBuffer nb = bb.order(NE); + if (ValueLayout.ADDRESS.byteSize() == 8) { + nb.putLong(pos * 8, v.toRawLongValue()); + } else { + nb.putInt(pos * 4, (int)v.toRawLongValue()); + } + }) + }, + }; + } + + @DataProvider(name = "addressAccessors") + static Object[][] addressAccessors() { + return new Object[][]{ + + {"byte", Accessor.ofAddress(ValueLayout.JAVA_BYTE, (byte) 42, + MemoryAddress::get, MemoryAddress::set, + ByteBuffer::get, ByteBuffer::put) + }, + {"bool", Accessor.ofAddress(ValueLayout.JAVA_BOOLEAN, false, + MemoryAddress::get, MemoryAddress::set, + (bb, pos) -> bb.get(pos) != 0, (bb, pos, v) -> bb.put(pos, v ? (byte)1 : (byte)0)) + }, + {"char", Accessor.ofAddress(ValueLayout.JAVA_CHAR, (char) 42, + MemoryAddress::get, MemoryAddress::set, + (bb, pos) -> bb.order(NE).getChar(pos), (bb, pos, v) -> bb.order(NE).putChar(pos, v)) + }, + {"int", Accessor.ofAddress(ValueLayout.JAVA_INT, 42, + MemoryAddress::get, MemoryAddress::set, + (bb, pos) -> bb.order(NE).getInt(pos), (bb, pos, v) -> bb.order(NE).putInt(pos, v)) + }, + {"float", Accessor.ofAddress(ValueLayout.JAVA_FLOAT, 42f, + MemoryAddress::get, MemoryAddress::set, + (bb, pos) -> bb.order(NE).getFloat(pos), (bb, pos, v) -> bb.order(NE).putFloat(pos, v)) + }, + {"long", Accessor.ofAddress(ValueLayout.JAVA_LONG, 42L, + MemoryAddress::get, MemoryAddress::set, + (bb, pos) -> bb.order(NE).getLong(pos), (bb, pos, v) -> bb.order(NE).putLong(pos, v)) + }, + {"double", Accessor.ofAddress(ValueLayout.JAVA_DOUBLE, 42d, + MemoryAddress::get, MemoryAddress::set, + (bb, pos) -> bb.order(NE).getDouble(pos), (bb, pos, v) -> bb.order(NE).putDouble(pos, v)) + }, + { "address", Accessor.ofAddress(ValueLayout.ADDRESS, MemoryAddress.ofLong(42), + MemoryAddress::get, MemoryAddress::set, + (bb, pos) -> { + ByteBuffer nb = bb.order(NE); + long addr = ValueLayout.ADDRESS.byteSize() == 8 ? + nb.getLong(pos) : nb.getInt(pos); + return MemoryAddress.ofLong(addr); + }, + (bb, pos, v) -> { + ByteBuffer nb = bb.order(NE); + if (ValueLayout.ADDRESS.byteSize() == 8) { + nb.putLong(pos, v.toRawLongValue()); + } else { + nb.putInt(pos, (int)v.toRawLongValue()); + } + }) + }, + {"char/index", Accessor.ofAddress(ValueLayout.JAVA_CHAR, (char) 42, + MemoryAddress::getAtIndex, MemoryAddress::setAtIndex, + (bb, pos) -> bb.order(NE).getChar(pos * 2), (bb, pos, v) -> bb.order(NE).putChar(pos * 2, v)) + }, + {"int/index", Accessor.ofAddress(ValueLayout.JAVA_INT, 42, + MemoryAddress::getAtIndex, MemoryAddress::setAtIndex, + (bb, pos) -> bb.order(NE).getInt(pos * 4), (bb, pos, v) -> bb.order(NE).putInt(pos * 4, v)) + }, + {"float/index", Accessor.ofAddress(ValueLayout.JAVA_FLOAT, 42f, + MemoryAddress::getAtIndex, MemoryAddress::setAtIndex, + (bb, pos) -> bb.order(NE).getFloat(pos * 4), (bb, pos, v) -> bb.order(NE).putFloat(pos * 4, v)) + }, + {"long/index", Accessor.ofAddress(ValueLayout.JAVA_LONG, 42L, + MemoryAddress::getAtIndex, MemoryAddress::setAtIndex, + (bb, pos) -> bb.order(NE).getLong(pos * 8), (bb, pos, v) -> bb.order(NE).putLong(pos * 8, v)) + }, + {"double/index", Accessor.ofAddress(ValueLayout.JAVA_DOUBLE, 42d, + MemoryAddress::getAtIndex, MemoryAddress::setAtIndex, + (bb, pos) -> bb.order(NE).getDouble(pos * 8), (bb, pos, v) -> bb.order(NE).putDouble(pos * 8, v)) + }, + { "address/index", Accessor.ofAddress(ValueLayout.ADDRESS, MemoryAddress.ofLong(42), + MemoryAddress::getAtIndex, MemoryAddress::setAtIndex, + (bb, pos) -> { + ByteBuffer nb = bb.order(NE); + long addr = ValueLayout.ADDRESS.byteSize() == 8 ? + nb.getLong(pos * 8) : nb.getInt(pos * 4); + return MemoryAddress.ofLong(addr); + }, + (bb, pos, v) -> { + ByteBuffer nb = bb.order(NE); + if (ValueLayout.ADDRESS.byteSize() == 8) { + nb.putLong(pos * 8, v.toRawLongValue()); + } else { + nb.putInt(pos * 4, (int)v.toRawLongValue()); + } + }) + } + }; + } +} diff --git a/test/jdk/java/foreign/TestMemoryAccessStatics.java b/test/jdk/java/foreign/TestMemoryAccessStatics.java deleted file mode 100644 index 4115bf58146a1c37e7392420d231d6481775b7d6..0000000000000000000000000000000000000000 --- a/test/jdk/java/foreign/TestMemoryAccessStatics.java +++ /dev/null @@ -1,364 +0,0 @@ -/* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @run testng TestMemoryAccessStatics - */ - -import jdk.incubator.foreign.MemoryAccess; -import jdk.incubator.foreign.MemoryAddress; -import jdk.incubator.foreign.MemoryLayouts; -import jdk.incubator.foreign.MemorySegment; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -import org.testng.annotations.*; -import static org.testng.Assert.*; - -public class TestMemoryAccessStatics { - - static class Accessor<X> { - - interface SegmentGetter<X> { - X get(MemorySegment segment); - } - - interface SegmentSetter<X> { - void set(MemorySegment segment, X o); - } - - interface BufferGetter<X> { - X get(ByteBuffer segment); - } - - interface BufferSetter<X> { - void set(ByteBuffer buffer, X o); - } - - final X value; - final SegmentGetter<X> segmentGetter; - final SegmentSetter<X> segmentSetter; - final BufferGetter<X> bufferGetter; - final BufferSetter<X> bufferSetter; - - Accessor(X value, - SegmentGetter<X> segmentGetter, SegmentSetter<X> segmentSetter, - BufferGetter<X> bufferGetter, BufferSetter<X> bufferSetter) { - this.value = value; - this.segmentGetter = segmentGetter; - this.segmentSetter = segmentSetter; - this.bufferGetter = bufferGetter; - this.bufferSetter = bufferSetter; - } - - void test() { - MemorySegment segment = MemorySegment.ofArray(new byte[32]); - ByteBuffer buffer = segment.asByteBuffer(); - segmentSetter.set(segment, value); - assertEquals(bufferGetter.get(buffer), value); - bufferSetter.set(buffer, value); - assertEquals(value, segmentGetter.get(segment)); - } - - <Z> Accessor<Z> of(Z value, - SegmentGetter<Z> segmentGetter, SegmentSetter<Z> segmentSetter, - BufferGetter<Z> bufferGetter, BufferSetter<Z> bufferSetter) { - return new Accessor<>(value, segmentGetter, segmentSetter, bufferGetter, bufferSetter); - } - } - - @Test(dataProvider = "accessors") - public void testMemoryAccess(String testName, Accessor<?> accessor) { - accessor.test(); - } - - static final ByteOrder BE = ByteOrder.BIG_ENDIAN; - static final ByteOrder LE = ByteOrder.LITTLE_ENDIAN; - static final ByteOrder NE = ByteOrder.nativeOrder(); - - @DataProvider(name = "accessors") - static Object[][] accessors() { - return new Object[][]{ - - {"byte", new Accessor<>((byte) 42, - MemoryAccess::getByte, MemoryAccess::setByte, - (bb) -> bb.get(0), (bb, v) -> bb.put(0, v)) - }, - {"char", new Accessor<>((char) 42, - MemoryAccess::getChar, MemoryAccess::setChar, - (bb) -> bb.order(NE).getChar(0), (bb, v) -> bb.order(NE).putChar(0, v)) - }, - {"char/LE", new Accessor<>((char) 42, - s -> MemoryAccess.getChar(s, LE), (s, x) -> MemoryAccess.setChar(s, LE, x), - (bb) -> bb.order(LE).getChar(0), (bb, v) -> bb.order(LE).putChar(0, v)) - }, - {"char/BE", new Accessor<>((char) 42, - s -> MemoryAccess.getChar(s, BE), (s, x) -> MemoryAccess.setChar(s, BE, x), - (bb) -> bb.order(BE).getChar(0), (bb, v) -> bb.order(BE).putChar(0, v)) - }, - {"short", new Accessor<>((short) 42, - MemoryAccess::getShort, MemoryAccess::setShort, - (bb) -> bb.order(NE).getShort(0), (bb, v) -> bb.order(NE).putShort(0, v)) - }, - {"short/LE", new Accessor<>((short) 42, - s -> MemoryAccess.getShort(s, LE), (s, x) -> MemoryAccess.setShort(s, LE, x), - (bb) -> bb.order(LE).getShort(0), (bb, v) -> bb.order(LE).putShort(0, v)) - }, - {"short/BE", new Accessor<>((short) 42, - s -> MemoryAccess.getShort(s, BE), (s, x) -> MemoryAccess.setShort(s, BE, x), - (bb) -> bb.order(BE).getShort(0), (bb, v) -> bb.order(BE).putShort(0, v)) - }, - {"int", new Accessor<>(42, - MemoryAccess::getInt, MemoryAccess::setInt, - (bb) -> bb.order(NE).getInt(0), (bb, v) -> bb.order(NE).putInt(0, v)) - }, - {"int/LE", new Accessor<>(42, - s -> MemoryAccess.getInt(s, LE), (s, x) -> MemoryAccess.setInt(s, LE, x), - (bb) -> bb.order(LE).getInt(0), (bb, v) -> bb.order(LE).putInt(0, v)) - }, - {"int/BE", new Accessor<>(42, - s -> MemoryAccess.getInt(s, BE), (s, x) -> MemoryAccess.setInt(s, BE, x), - (bb) -> bb.order(BE).getInt(0), (bb, v) -> bb.order(BE).putInt(0, v)) - }, - // float, no offset - {"float", new Accessor<>(42f, - MemoryAccess::getFloat, MemoryAccess::setFloat, - (bb) -> bb.order(NE).getFloat(0), (bb, v) -> bb.order(NE).putFloat(0, v)) - }, - {"float/LE", new Accessor<>(42f, - s -> MemoryAccess.getFloat(s, LE), (s, x) -> MemoryAccess.setFloat(s, LE, x), - (bb) -> bb.order(LE).getFloat(0), (bb, v) -> bb.order(LE).putFloat(0, v)) - }, - {"float/BE", new Accessor<>(42f, - s -> MemoryAccess.getFloat(s, BE), (s, x) -> MemoryAccess.setFloat(s, BE, x), - (bb) -> bb.order(BE).getFloat(0), (bb, v) -> bb.order(BE).putFloat(0, v)) - }, - // double, no offset - {"double", new Accessor<>(42d, - MemoryAccess::getDouble, MemoryAccess::setDouble, - (bb) -> bb.order(NE).getDouble(0), (bb, v) -> bb.order(NE).putDouble(0, v)) - }, - {"double/LE", new Accessor<>(42d, - s -> MemoryAccess.getDouble(s, LE), (s, x) -> MemoryAccess.setDouble(s, LE, x), - (bb) -> bb.order(LE).getDouble(0), (bb, v) -> bb.order(LE).putDouble(0, v)) - }, - {"double/BE", new Accessor<>(42d, - s -> MemoryAccess.getDouble(s, BE), (s, x) -> MemoryAccess.setDouble(s, BE, x), - (bb) -> bb.order(BE).getDouble(0), (bb, v) -> bb.order(BE).putDouble(0, v)) - }, - - - // byte, offset - {"byte/offset", new Accessor<>((byte) 42, - s -> MemoryAccess.getByteAtOffset(s, 4), (s, x) -> MemoryAccess.setByteAtOffset(s, 4, x), - (bb) -> bb.get(4), (bb, v) -> bb.put(4, v)) - }, - // char, offset - {"char/offset", new Accessor<>((char) 42, - s -> MemoryAccess.getCharAtOffset(s, 4), (s, x) -> MemoryAccess.setCharAtOffset(s, 4, x), - (bb) -> bb.order(NE).getChar(4), (bb, v) -> bb.order(NE).putChar(4, v)) - }, - {"char/offset/LE", new Accessor<>((char) 42, - s -> MemoryAccess.getCharAtOffset(s, 4, LE), (s, x) -> MemoryAccess.setCharAtOffset(s, 4, LE, x), - (bb) -> bb.order(LE).getChar(4), (bb, v) -> bb.order(LE).putChar(4, v)) - }, - {"char/offset/BE", new Accessor<>((char) 42, - s -> MemoryAccess.getCharAtOffset(s, 4, BE), (s, x) -> MemoryAccess.setCharAtOffset(s, 4, BE, x), - (bb) -> bb.order(BE).getChar(4), (bb, v) -> bb.order(BE).putChar(4, v)) - }, - // short, offset - {"short/offset", new Accessor<>((short) 42, - s -> MemoryAccess.getShortAtOffset(s, 4), (s, x) -> MemoryAccess.setShortAtOffset(s, 4, x), - (bb) -> bb.order(NE).getShort(4), (bb, v) -> bb.order(NE).putShort(4, v)) - }, - {"short/offset/LE", new Accessor<>((short) 42, - s -> MemoryAccess.getShortAtOffset(s, 4, LE), (s, x) -> MemoryAccess.setShortAtOffset(s, 4, LE, x), - (bb) -> bb.order(LE).getShort(4), (bb, v) -> bb.order(LE).putShort(4, v)) - }, - {"short/offset/BE", new Accessor<>((short) 42, - s -> MemoryAccess.getShortAtOffset(s, 4, BE), (s, x) -> MemoryAccess.setShortAtOffset(s, 4, BE, x), - (bb) -> bb.order(BE).getShort(4), (bb, v) -> bb.order(BE).putShort(4, v)) - }, - // int, offset - {"int/offset", new Accessor<>(42, - s -> MemoryAccess.getIntAtOffset(s, 4), (s, x) -> MemoryAccess.setIntAtOffset(s, 4, x), - (bb) -> bb.order(NE).getInt(4), (bb, v) -> bb.order(NE).putInt(4, v)) - }, - {"int/offset/LE", new Accessor<>(42, - s -> MemoryAccess.getIntAtOffset(s, 4, LE), (s, x) -> MemoryAccess.setIntAtOffset(s, 4, LE, x), - (bb) -> bb.order(LE).getInt(4), (bb, v) -> bb.order(LE).putInt(4, v)) - }, - {"int/offset/BE", new Accessor<>(42, - s -> MemoryAccess.getIntAtOffset(s, 4, BE), (s, x) -> MemoryAccess.setIntAtOffset(s, 4, BE, x), - (bb) -> bb.order(BE).getInt(4), (bb, v) -> bb.order(BE).putInt(4, v)) - }, - // float, offset - {"float/offset", new Accessor<>(42f, - s -> MemoryAccess.getFloatAtOffset(s, 4), (s, x) -> MemoryAccess.setFloatAtOffset(s, 4, x), - (bb) -> bb.order(NE).getFloat(4), (bb, v) -> bb.order(NE).putFloat(4, v)) - }, - {"float/offset/LE", new Accessor<>(42f, - s -> MemoryAccess.getFloatAtOffset(s, 4, LE), (s, x) -> MemoryAccess.setFloatAtOffset(s, 4, LE, x), - (bb) -> bb.order(LE).getFloat(4), (bb, v) -> bb.order(LE).putFloat(4, v)) - }, - {"float/offset/BE", new Accessor<>(42f, - s -> MemoryAccess.getFloatAtOffset(s, 4, BE), (s, x) -> MemoryAccess.setFloatAtOffset(s, 4, BE, x), - (bb) -> bb.order(BE).getFloat(4), (bb, v) -> bb.order(BE).putFloat(4, v)) - }, - // double, offset - {"double/offset", new Accessor<>(42d, - s -> MemoryAccess.getDoubleAtOffset(s, 4), (s, x) -> MemoryAccess.setDoubleAtOffset(s, 4, x), - (bb) -> bb.order(NE).getDouble(4), (bb, v) -> bb.order(NE).putDouble(4, v)) - }, - {"double/offset/LE", new Accessor<>(42d, - s -> MemoryAccess.getDoubleAtOffset(s, 4, LE), (s, x) -> MemoryAccess.setDoubleAtOffset(s, 4, LE, x), - (bb) -> bb.order(LE).getDouble(4), (bb, v) -> bb.order(LE).putDouble(4, v)) - }, - {"double/offset/BE", new Accessor<>(42d, - s -> MemoryAccess.getDoubleAtOffset(s, 4, BE), (s, x) -> MemoryAccess.setDoubleAtOffset(s, 4, BE, x), - (bb) -> bb.order(BE).getDouble(4), (bb, v) -> bb.order(BE).putDouble(4, v)) - }, - - - // char, index - {"char/index", new Accessor<>((char) 42, - s -> MemoryAccess.getCharAtIndex(s, 2), (s, x) -> MemoryAccess.setCharAtIndex(s, 2, x), - (bb) -> bb.order(NE).asCharBuffer().get(2), (bb, v) -> bb.order(NE).asCharBuffer().put(2, v)) - }, - {"char/index/LE", new Accessor<>((char) 42, - s -> MemoryAccess.getCharAtIndex(s, 2, LE), (s, x) -> MemoryAccess.setCharAtIndex(s, 2, LE, x), - (bb) -> bb.order(LE).asCharBuffer().get(2), (bb, v) -> bb.order(LE).asCharBuffer().put(2, v)) - }, - {"char/index/BE", new Accessor<>((char) 42, - s -> MemoryAccess.getCharAtIndex(s, 2, BE), (s, x) -> MemoryAccess.setCharAtIndex(s, 2, BE, x), - (bb) -> bb.order(BE).asCharBuffer().get(2), (bb, v) -> bb.order(BE).asCharBuffer().put(2, v)) - }, - // short, index - {"short/index", new Accessor<>((short) 42, - s -> MemoryAccess.getShortAtIndex(s, 2), (s, x) -> MemoryAccess.setShortAtIndex(s, 2, x), - (bb) -> bb.order(NE).asShortBuffer().get(2), (bb, v) -> bb.order(NE).asShortBuffer().put(2, v)) - }, - {"short/index/LE", new Accessor<>((short) 42, - s -> MemoryAccess.getShortAtIndex(s, 2, LE), (s, x) -> MemoryAccess.setShortAtIndex(s, 2, LE, x), - (bb) -> bb.order(LE).asShortBuffer().get(2), (bb, v) -> bb.order(LE).asShortBuffer().put(2, v)) - }, - {"short/index/BE", new Accessor<>((short) 42, - s -> MemoryAccess.getShortAtIndex(s, 2, BE), (s, x) -> MemoryAccess.setShortAtIndex(s, 2, BE, x), - (bb) -> bb.order(BE).asShortBuffer().get(2), (bb, v) -> bb.order(BE).asShortBuffer().put(2, v)) - }, - {"int/index", new Accessor<>(42, - s -> MemoryAccess.getIntAtIndex(s, 2), (s, x) -> MemoryAccess.setIntAtIndex(s, 2, x), - (bb) -> bb.order(NE).asIntBuffer().get(2), (bb, v) -> bb.order(NE).asIntBuffer().put(2, v)) - }, - {"int/index/LE", new Accessor<>(42, - s -> MemoryAccess.getIntAtIndex(s, 2, LE), (s, x) -> MemoryAccess.setIntAtIndex(s, 2, LE, x), - (bb) -> bb.order(LE).asIntBuffer().get(2), (bb, v) -> bb.order(LE).asIntBuffer().put(2, v)) - }, - {"int/index/BE", new Accessor<>(42, - s -> MemoryAccess.getIntAtIndex(s, 2, BE), (s, x) -> MemoryAccess.setIntAtIndex(s, 2, BE, x), - (bb) -> bb.order(BE).asIntBuffer().get(2), (bb, v) -> bb.order(BE).asIntBuffer().put(2, v)) - }, - {"float/index", new Accessor<>(42f, - s -> MemoryAccess.getFloatAtIndex(s, 2), (s, x) -> MemoryAccess.setFloatAtIndex(s, 2, x), - (bb) -> bb.order(NE).asFloatBuffer().get(2), (bb, v) -> bb.order(NE).asFloatBuffer().put(2, v)) - }, - {"float/index/LE", new Accessor<>(42f, - s -> MemoryAccess.getFloatAtIndex(s, 2, LE), (s, x) -> MemoryAccess.setFloatAtIndex(s, 2, LE, x), - (bb) -> bb.order(LE).asFloatBuffer().get(2), (bb, v) -> bb.order(LE).asFloatBuffer().put(2, v)) - }, - {"float/index/BE", new Accessor<>(42f, - s -> MemoryAccess.getFloatAtIndex(s, 2, BE), (s, x) -> MemoryAccess.setFloatAtIndex(s, 2, BE, x), - (bb) -> bb.order(BE).asFloatBuffer().get(2), (bb, v) -> bb.order(BE).asFloatBuffer().put(2, v)) - }, - {"double/index", new Accessor<>(42d, - s -> MemoryAccess.getDoubleAtIndex(s, 2), (s, x) -> MemoryAccess.setDoubleAtIndex(s, 2, x), - (bb) -> bb.order(NE).asDoubleBuffer().get(2), (bb, v) -> bb.order(NE).asDoubleBuffer().put(2, v)) - }, - {"double/index/LE", new Accessor<>(42d, - s -> MemoryAccess.getDoubleAtIndex(s, 2, LE), (s, x) -> MemoryAccess.setDoubleAtIndex(s, 2, LE, x), - (bb) -> bb.order(LE).asDoubleBuffer().get(2), (bb, v) -> bb.order(LE).asDoubleBuffer().put(2, v)) - }, - {"double/index/BE", new Accessor<>(42d, - s -> MemoryAccess.getDoubleAtIndex(s, 2, BE), (s, x) -> MemoryAccess.setDoubleAtIndex(s, 2, BE, x), - (bb) -> bb.order(BE).asDoubleBuffer().get(2), (bb, v) -> bb.order(BE).asDoubleBuffer().put(2, v)) - }, - - { "address", new Accessor<>(MemoryAddress.ofLong(42), - MemoryAccess::getAddress, MemoryAccess::setAddress, - (bb) -> { - ByteBuffer nb = bb.order(NE); - long addr = MemoryLayouts.ADDRESS.byteSize() == 8 ? - nb.getLong(0) : nb.getInt(0); - return MemoryAddress.ofLong(addr); - }, - (bb, v) -> { - ByteBuffer nb = bb.order(NE); - if (MemoryLayouts.ADDRESS.byteSize() == 8) { - nb.putLong(0, v.toRawLongValue()); - } else { - nb.putInt(0, (int)v.toRawLongValue()); - } - }) - }, - { "address/offset", new Accessor<>(MemoryAddress.ofLong(42), - s -> MemoryAccess.getAddressAtOffset(s, 4), (s, x) -> MemoryAccess.setAddressAtOffset(s, 4, x), - (bb) -> { - ByteBuffer nb = bb.order(NE); - long addr = MemoryLayouts.ADDRESS.byteSize() == 8 ? - nb.getLong(4) : nb.getInt(4); - return MemoryAddress.ofLong(addr); - }, - (bb, v) -> { - ByteBuffer nb = bb.order(NE); - if (MemoryLayouts.ADDRESS.byteSize() == 8) { - nb.putLong(4, v.toRawLongValue()); - } else { - nb.putInt(4, (int)v.toRawLongValue()); - } - }) - }, - { "address/index", new Accessor<>(MemoryAddress.ofLong(42), - s -> MemoryAccess.getAddressAtIndex(s, 2), (s, x) -> MemoryAccess.setAddressAtIndex(s, 2, x), - (bb) -> { - ByteBuffer nb = bb.order(NE); - long addr = MemoryLayouts.ADDRESS.byteSize() == 8 ? - nb.asLongBuffer().get(2) : nb.asIntBuffer().get(2); - return MemoryAddress.ofLong(addr); - }, - (bb, v) -> { - ByteBuffer nb = bb.order(NE); - if (MemoryLayouts.ADDRESS.byteSize() == 8) { - nb.asLongBuffer().put(2, v.toRawLongValue()); - } else { - nb.asIntBuffer().put(2, (int)v.toRawLongValue()); - } - }) - }, - }; - } -} diff --git a/test/jdk/java/foreign/TestMemoryAlignment.java b/test/jdk/java/foreign/TestMemoryAlignment.java index 93f218245c8d1ab080e70acc42dccf6759d1f3eb..d486581435a7efa70ac666b205df678830b5fd1f 100644 --- a/test/jdk/java/foreign/TestMemoryAlignment.java +++ b/test/jdk/java/foreign/TestMemoryAlignment.java @@ -26,7 +26,6 @@ * @run testng TestMemoryAlignment */ -import jdk.incubator.foreign.MemoryLayouts; import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.GroupLayout; @@ -36,6 +35,7 @@ import jdk.incubator.foreign.ResourceScope; import jdk.incubator.foreign.SequenceLayout; import jdk.incubator.foreign.ValueLayout; import java.lang.invoke.VarHandle; +import java.nio.ByteOrder; import java.util.stream.LongStream; import org.testng.annotations.*; @@ -45,11 +45,13 @@ public class TestMemoryAlignment { @Test(dataProvider = "alignments") public void testAlignedAccess(long align) { - ValueLayout layout = MemoryLayouts.BITS_32_BE; + ValueLayout layout = ValueLayout.JAVA_INT + .withBitAlignment(32) + .withOrder(ByteOrder.BIG_ENDIAN); assertEquals(layout.bitAlignment(), 32); ValueLayout aligned = layout.withBitAlignment(align); assertEquals(aligned.bitAlignment(), align); //unreasonable alignment here, to make sure access throws - VarHandle vh = aligned.varHandle(int.class); + VarHandle vh = aligned.varHandle(); try (ResourceScope scope = ResourceScope.newConfinedScope()) { MemorySegment segment = MemorySegment.allocateNative(aligned, scope); vh.set(segment, -42); @@ -60,12 +62,14 @@ public class TestMemoryAlignment { @Test(dataProvider = "alignments") public void testUnalignedAccess(long align) { - ValueLayout layout = MemoryLayouts.BITS_32_BE; + ValueLayout layout = ValueLayout.JAVA_INT + .withBitAlignment(32) + .withOrder(ByteOrder.BIG_ENDIAN); assertEquals(layout.bitAlignment(), 32); ValueLayout aligned = layout.withBitAlignment(align); - MemoryLayout alignedGroup = MemoryLayout.structLayout(MemoryLayouts.PAD_8, aligned); + MemoryLayout alignedGroup = MemoryLayout.structLayout(MemoryLayout.paddingLayout(8), aligned); assertEquals(alignedGroup.bitAlignment(), align); - VarHandle vh = aligned.varHandle(int.class); + VarHandle vh = aligned.varHandle(); try (ResourceScope scope = ResourceScope.newConfinedScope()) { MemorySegment segment = MemorySegment.allocateNative(alignedGroup, scope); vh.set(segment.asSlice(1L), -42); @@ -77,11 +81,11 @@ public class TestMemoryAlignment { @Test(dataProvider = "alignments") public void testUnalignedPath(long align) { - MemoryLayout layout = MemoryLayouts.BITS_32_BE; + MemoryLayout layout = ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN); MemoryLayout aligned = layout.withBitAlignment(align).withName("value"); - GroupLayout alignedGroup = MemoryLayout.structLayout(MemoryLayouts.PAD_8, aligned); + GroupLayout alignedGroup = MemoryLayout.structLayout(MemoryLayout.paddingLayout(8), aligned); try { - alignedGroup.varHandle(int.class, PathElement.groupElement("value")); + alignedGroup.varHandle(PathElement.groupElement("value")); assertEquals(align, 8); //this is the only case where path is aligned } catch (UnsupportedOperationException ex) { assertNotEquals(align, 8); //if align != 8, path is always unaligned @@ -90,9 +94,9 @@ public class TestMemoryAlignment { @Test(dataProvider = "alignments") public void testUnalignedSequence(long align) { - SequenceLayout layout = MemoryLayout.sequenceLayout(5, MemoryLayouts.BITS_32_BE.withBitAlignment(align)); + SequenceLayout layout = MemoryLayout.sequenceLayout(5, ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN).withBitAlignment(align)); try { - VarHandle vh = layout.varHandle(int.class, PathElement.sequenceElement()); + VarHandle vh = layout.varHandle(PathElement.sequenceElement()); try (ResourceScope scope = ResourceScope.newConfinedScope()) { MemorySegment segment = MemorySegment.allocateNative(layout, scope); for (long i = 0 ; i < 5 ; i++) { @@ -106,17 +110,17 @@ public class TestMemoryAlignment { @Test public void testPackedAccess() { - ValueLayout vChar = MemoryLayouts.BITS_8_BE; - ValueLayout vShort = MemoryLayouts.BITS_16_BE; - ValueLayout vInt = MemoryLayouts.BITS_32_BE; + ValueLayout vChar = ValueLayout.JAVA_BYTE; + ValueLayout vShort = ValueLayout.JAVA_SHORT.withOrder(ByteOrder.BIG_ENDIAN); + ValueLayout vInt = ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN); //mimic pragma pack(1) GroupLayout g = MemoryLayout.structLayout(vChar.withBitAlignment(8).withName("a"), vShort.withBitAlignment(8).withName("b"), vInt.withBitAlignment(8).withName("c")); assertEquals(g.bitAlignment(), 8); - VarHandle vh_c = g.varHandle(byte.class, PathElement.groupElement("a")); - VarHandle vh_s = g.varHandle(short.class, PathElement.groupElement("b")); - VarHandle vh_i = g.varHandle(int.class, PathElement.groupElement("c")); + VarHandle vh_c = g.varHandle(PathElement.groupElement("a")); + VarHandle vh_s = g.varHandle(PathElement.groupElement("b")); + VarHandle vh_i = g.varHandle(PathElement.groupElement("c")); try (ResourceScope scope = ResourceScope.newConfinedScope()) { MemorySegment segment = MemorySegment.allocateNative(g, scope); vh_c.set(segment, Byte.MIN_VALUE); diff --git a/test/jdk/java/foreign/TestMemoryCopy.java b/test/jdk/java/foreign/TestMemoryCopy.java deleted file mode 100644 index cba9186f124ac28e635ba64d175734fc25c5cd76..0000000000000000000000000000000000000000 --- a/test/jdk/java/foreign/TestMemoryCopy.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -/* - * @test - * @run testng TestMemoryCopy - */ - -import jdk.incubator.foreign.MemoryLayouts; -import jdk.incubator.foreign.MemorySegment; -import jdk.incubator.foreign.ResourceScope; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - -import java.lang.invoke.VarHandle; -import java.util.ArrayList; -import java.util.List; -import java.util.function.IntFunction; - -import static org.testng.Assert.*; - -public class TestMemoryCopy { - - final static VarHandle BYTE_HANDLE = MemoryLayouts.JAVA_BYTE.varHandle(byte.class); - - @Test(dataProvider = "slices") - public void testCopy(SegmentSlice s1, SegmentSlice s2) { - int size = Math.min(s1.size(), s2.size()); - //prepare source and target segments - for (int i = 0 ; i < size ; i++) { - BYTE_HANDLE.set(s2.segment.asSlice(i), (byte)0); - } - for (int i = 0 ; i < size ; i++) { - BYTE_HANDLE.set(s1.segment.asSlice(i), (byte) i); - } - //perform copy - s2.segment.copyFrom(s1.segment.asSlice(0, size)); - //check that copy actually worked - for (int i = 0 ; i < size ; i++) { - assertEquals((byte)i, BYTE_HANDLE.get(s2.segment.asSlice(i))); - } - } - - static class SegmentSlice { - - enum Kind { - NATIVE(i -> MemorySegment.allocateNative(i, ResourceScope.newImplicitScope())), - ARRAY(i -> MemorySegment.ofArray(new byte[i])); - - final IntFunction<MemorySegment> segmentFactory; - - Kind(IntFunction<MemorySegment> segmentFactory) { - this.segmentFactory = segmentFactory; - } - - MemorySegment makeSegment(int elems) { - return segmentFactory.apply(elems); - } - } - - final Kind kind; - final int first; - final int last; - final MemorySegment segment; - - public SegmentSlice(Kind kind, int first, int last, MemorySegment segment) { - this.kind = kind; - this.first = first; - this.last = last; - this.segment = segment; - } - - int size() { - return last - first + 1; - } - } - - @DataProvider(name = "slices") - static Object[][] slices() { - int[] sizes = { 16, 8, 4, 2, 1 }; - List<SegmentSlice> slices = new ArrayList<>(); - for (SegmentSlice.Kind kind : SegmentSlice.Kind.values()) { - MemorySegment segment = kind.makeSegment(16); - //compute all slices - for (int size : sizes) { - for (int index = 0 ; index < 16 ; index += size) { - MemorySegment slice = segment.asSlice(index, size); - slices.add(new SegmentSlice(kind, index, index + size - 1, slice)); - } - } - } - Object[][] sliceArray = new Object[slices.size() * slices.size()][]; - for (int i = 0 ; i < slices.size() ; i++) { - for (int j = 0 ; j < slices.size() ; j++) { - sliceArray[i * slices.size() + j] = new Object[] { slices.get(i), slices.get(j) }; - } - } - return sliceArray; - } -} diff --git a/test/jdk/java/foreign/TestMemoryDereference.java b/test/jdk/java/foreign/TestMemoryDereference.java new file mode 100644 index 0000000000000000000000000000000000000000..c62380cc355dcc7be599cfa5887cb80acff5a824 --- /dev/null +++ b/test/jdk/java/foreign/TestMemoryDereference.java @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @run testng TestMemoryDereference + */ + +import jdk.incubator.foreign.MemoryAddress; +import jdk.incubator.foreign.MemorySegment; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.incubator.foreign.ValueLayout; +import org.testng.annotations.*; + +import static jdk.incubator.foreign.ValueLayout.ADDRESS; +import static jdk.incubator.foreign.ValueLayout.JAVA_BOOLEAN; +import static jdk.incubator.foreign.ValueLayout.JAVA_BYTE; +import static jdk.incubator.foreign.ValueLayout.JAVA_CHAR; +import static jdk.incubator.foreign.ValueLayout.JAVA_DOUBLE; +import static jdk.incubator.foreign.ValueLayout.JAVA_FLOAT; +import static jdk.incubator.foreign.ValueLayout.JAVA_INT; +import static jdk.incubator.foreign.ValueLayout.JAVA_SHORT; +import static org.testng.Assert.*; + +public class TestMemoryDereference { + + static class Accessor<X> { + + interface SegmentGetter<X> { + X get(MemorySegment segment); + } + + interface SegmentSetter<X> { + void set(MemorySegment segment, X o); + } + + interface BufferGetter<X> { + X get(ByteBuffer segment); + } + + interface BufferSetter<X> { + void set(ByteBuffer buffer, X o); + } + + final X value; + final SegmentGetter<X> segmentGetter; + final SegmentSetter<X> segmentSetter; + final BufferGetter<X> bufferGetter; + final BufferSetter<X> bufferSetter; + + Accessor(X value, + SegmentGetter<X> segmentGetter, SegmentSetter<X> segmentSetter, + BufferGetter<X> bufferGetter, BufferSetter<X> bufferSetter) { + this.value = value; + this.segmentGetter = segmentGetter; + this.segmentSetter = segmentSetter; + this.bufferGetter = bufferGetter; + this.bufferSetter = bufferSetter; + } + + void test() { + MemorySegment segment = MemorySegment.ofArray(new byte[32]); + ByteBuffer buffer = segment.asByteBuffer(); + segmentSetter.set(segment, value); + assertEquals(bufferGetter.get(buffer), value); + bufferSetter.set(buffer, value); + assertEquals(value, segmentGetter.get(segment)); + } + + <Z> Accessor<Z> of(Z value, + SegmentGetter<Z> segmentGetter, SegmentSetter<Z> segmentSetter, + BufferGetter<Z> bufferGetter, BufferSetter<Z> bufferSetter) { + return new Accessor<>(value, segmentGetter, segmentSetter, bufferGetter, bufferSetter); + } + } + + @Test(dataProvider = "accessors") + public void testMemoryAccess(String testName, Accessor<?> accessor) { + accessor.test(); + } + + static final ByteOrder BE = ByteOrder.BIG_ENDIAN; + static final ByteOrder LE = ByteOrder.LITTLE_ENDIAN; + static final ByteOrder NE = ByteOrder.nativeOrder(); + + @DataProvider(name = "accessors") + static Object[][] accessors() { + return new Object[][]{ + + // byte, offset + {"byte/offset", new Accessor<>((byte) 42, + s -> s.get(JAVA_BYTE, 8), (s, x) -> s.set(JAVA_BYTE, 8, x), + (bb) -> bb.get(8), (bb, v) -> bb.put(8, v)) + }, + // bool, offset + {"bool", new Accessor<>(false, + s -> s.get(JAVA_BOOLEAN, 8), (s, x) -> s.set(JAVA_BOOLEAN, 8, x), + (bb) -> bb.get(8) != 0, (bb, v) -> bb.put(8, v ? (byte)1 : (byte)0)) + }, + // char, offset + {"char/offset", new Accessor<>((char) 42, + s -> s.get(JAVA_CHAR, 8), (s, x) -> s.set(JAVA_CHAR, 8, x), + (bb) -> bb.order(NE).getChar(8), (bb, v) -> bb.order(NE).putChar(8, v)) + }, + {"char/offset/LE", new Accessor<>((char) 42, + s -> s.get(JAVA_CHAR.withOrder(ByteOrder.LITTLE_ENDIAN), 8), + (s, x) -> s.set(JAVA_CHAR.withOrder(ByteOrder.LITTLE_ENDIAN), 8, x), + (bb) -> bb.order(LE).getChar(8), (bb, v) -> bb.order(LE).putChar(8, v)) + }, + {"char/offset/BE", new Accessor<>((char) 42, + s -> s.get(JAVA_CHAR.withOrder(ByteOrder.BIG_ENDIAN), 8), + (s, x) -> s.set(JAVA_CHAR.withOrder(ByteOrder.BIG_ENDIAN), 8, x), + (bb) -> bb.order(BE).getChar(8), (bb, v) -> bb.order(BE).putChar(8, v)) + }, + // short, offset + {"short/offset", new Accessor<>((short) 42, + s -> s.get(JAVA_SHORT, 8), (s, x) -> s.set(JAVA_SHORT, 8, x), + (bb) -> bb.order(NE).getShort(8), (bb, v) -> bb.order(NE).putShort(8, v)) + }, + {"short/offset/LE", new Accessor<>((short) 42, + s -> s.get(JAVA_SHORT.withOrder(ByteOrder.LITTLE_ENDIAN), 8), + (s, x) -> s.set(JAVA_SHORT.withOrder(ByteOrder.LITTLE_ENDIAN), 8, x), + (bb) -> bb.order(LE).getShort(8), (bb, v) -> bb.order(LE).putShort(8, v)) + }, + {"short/offset/BE", new Accessor<>((short) 42, + s -> s.get(JAVA_SHORT.withOrder(ByteOrder.BIG_ENDIAN), 8), + (s, x) -> s.set(JAVA_SHORT.withOrder(ByteOrder.BIG_ENDIAN), 8, x), + (bb) -> bb.order(BE).getShort(8), (bb, v) -> bb.order(BE).putShort(8, v)) + }, + // int, offset + {"int/offset", new Accessor<>(42, + s -> s.get(JAVA_INT, 8), (s, x) -> s.set(JAVA_INT, 8, x), + (bb) -> bb.order(NE).getInt(8), (bb, v) -> bb.order(NE).putInt(8, v)) + }, + {"int/offset/LE", new Accessor<>(42, + s -> s.get(JAVA_INT.withOrder(ByteOrder.LITTLE_ENDIAN), 8), + (s, x) -> s.set(JAVA_INT.withOrder(ByteOrder.LITTLE_ENDIAN), 8, x), + (bb) -> bb.order(LE).getInt(8), (bb, v) -> bb.order(LE).putInt(8, v)) + }, + {"int/offset/BE", new Accessor<>(42, + s -> s.get(JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN), 8), + (s, x) -> s.set(JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN), 8, x), + (bb) -> bb.order(BE).getInt(8), (bb, v) -> bb.order(BE).putInt(8, v)) + }, + // float, offset + {"float/offset", new Accessor<>(42f, + s -> s.get(JAVA_FLOAT, 8), (s, x) -> s.set(JAVA_FLOAT, 8, x), + (bb) -> bb.order(NE).getFloat(8), (bb, v) -> bb.order(NE).putFloat(8, v)) + }, + {"float/offset/LE", new Accessor<>(42f, + s -> s.get(ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.LITTLE_ENDIAN), 8), + (s, x) -> s.set(ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.LITTLE_ENDIAN), 8, x), + (bb) -> bb.order(LE).getFloat(8), (bb, v) -> bb.order(LE).putFloat(8, v)) + }, + {"float/offset/BE", new Accessor<>(42f, + s -> s.get(ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.BIG_ENDIAN), 8), + (s, x) -> s.set(ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.BIG_ENDIAN), 8, x), + (bb) -> bb.order(BE).getFloat(8), (bb, v) -> bb.order(BE).putFloat(8, v)) + }, + // double, offset + {"double/offset", new Accessor<>(42d, + s -> s.get(JAVA_DOUBLE, 8), (s, x) -> s.set(JAVA_DOUBLE, 8, x), + (bb) -> bb.order(NE).getDouble(8), (bb, v) -> bb.order(NE).putDouble(8, v)) + }, + {"double/offset/LE", new Accessor<>(42d, + s -> s.get(ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.LITTLE_ENDIAN), 8), + (s, x) -> s.set(ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.LITTLE_ENDIAN), 8, x), + (bb) -> bb.order(LE).getDouble(8), (bb, v) -> bb.order(LE).putDouble(8, v)) + }, + {"double/offset/BE", new Accessor<>(42d, + s -> s.get(ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.BIG_ENDIAN), 8), + (s, x) -> s.set(ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.BIG_ENDIAN), 8, x), + (bb) -> bb.order(BE).getDouble(8), (bb, v) -> bb.order(BE).putDouble(8, v)) + }, + { "address/offset", new Accessor<>(MemoryAddress.ofLong(42), + s -> s.get(ADDRESS, 8), (s, x) -> s.set(ADDRESS, 8, x), + (bb) -> { + ByteBuffer nb = bb.order(NE); + long addr = ValueLayout.ADDRESS.byteSize() == 8 ? + nb.getLong(8) : nb.getInt(8); + return MemoryAddress.ofLong(addr); + }, + (bb, v) -> { + ByteBuffer nb = bb.order(NE); + if (ValueLayout.ADDRESS.byteSize() == 8) { + nb.putLong(8, v.toRawLongValue()); + } else { + nb.putInt(8, (int)v.toRawLongValue()); + } + }) + }, + }; + } +} diff --git a/test/jdk/java/foreign/TestMemoryHandleAsUnsigned.java b/test/jdk/java/foreign/TestMemoryHandleAsUnsigned.java index d4a6e536234a87f8bdb72e0ba5fa3a828068683c..71ef6fe2999ecee5f0ef9b12a4fd10e88d45afee 100644 --- a/test/jdk/java/foreign/TestMemoryHandleAsUnsigned.java +++ b/test/jdk/java/foreign/TestMemoryHandleAsUnsigned.java @@ -25,14 +25,15 @@ import jdk.incubator.foreign.MemoryHandles; import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.MemoryLayout.PathElement; -import jdk.incubator.foreign.MemoryLayouts; import jdk.incubator.foreign.MemorySegment; import java.lang.invoke.VarHandle; +import java.nio.ByteOrder; import java.util.Arrays; import java.util.stream.IntStream; import java.util.stream.LongStream; import jdk.incubator.foreign.ResourceScope; +import jdk.incubator.foreign.ValueLayout; import org.testng.annotations.*; import static java.nio.ByteOrder.BIG_ENDIAN; import static org.testng.Assert.*; @@ -54,8 +55,8 @@ public class TestMemoryHandleAsUnsigned { public void testUnsignedIntToByte(int intValue) { byte byteValue = (byte) (intValue & 0xFF); - MemoryLayout layout = MemoryLayouts.BITS_8_BE; - VarHandle byteHandle = layout.varHandle(byte.class); + MemoryLayout layout = ValueLayout.JAVA_BYTE; + VarHandle byteHandle = layout.varHandle(); VarHandle intHandle = MemoryHandles.asUnsigned(byteHandle, int.class); try (ResourceScope scope = ResourceScope.newConfinedScope()) { @@ -77,8 +78,8 @@ public class TestMemoryHandleAsUnsigned { public void testUnsignedLongToByte(long longValue) { byte byteValue = (byte) (longValue & 0xFFL); - MemoryLayout layout = MemoryLayouts.BITS_8_BE; - VarHandle byteHandle = layout.varHandle(byte.class); + MemoryLayout layout = ValueLayout.JAVA_BYTE; + VarHandle byteHandle = layout.varHandle(); VarHandle longHandle = MemoryHandles.asUnsigned(byteHandle, long.class); try (ResourceScope scope = ResourceScope.newConfinedScope()) { @@ -100,8 +101,8 @@ public class TestMemoryHandleAsUnsigned { public void testUnsignedIntToShort(int intValue) { short shortValue = (short) (intValue & 0xFFFF); - MemoryLayout layout = MemoryLayouts.BITS_16_BE; - VarHandle shortHandle = layout.varHandle(short.class); + MemoryLayout layout = ValueLayout.JAVA_SHORT.withOrder(ByteOrder.BIG_ENDIAN); + VarHandle shortHandle = layout.varHandle(); VarHandle intHandle = MemoryHandles.asUnsigned(shortHandle, int.class); try (ResourceScope scope = ResourceScope.newConfinedScope()) { @@ -123,8 +124,8 @@ public class TestMemoryHandleAsUnsigned { public void testUnsignedLongToShort(long longValue) { short shortValue = (short) (longValue & 0xFFFFL); - MemoryLayout layout = MemoryLayouts.BITS_16_BE; - VarHandle shortHandle = layout.varHandle(short.class); + MemoryLayout layout = ValueLayout.JAVA_SHORT.withOrder(ByteOrder.BIG_ENDIAN); + VarHandle shortHandle = layout.varHandle(); VarHandle longHandle = MemoryHandles.asUnsigned(shortHandle, long.class); try (ResourceScope scope = ResourceScope.newConfinedScope()) { @@ -150,8 +151,8 @@ public class TestMemoryHandleAsUnsigned { public void testUnsignedLongToInt(long longValue) { int intValue = (int) (longValue & 0xFFFF_FFFFL); - MemoryLayout layout = MemoryLayouts.BITS_32_BE; - VarHandle intHandle = layout.varHandle(int.class); + MemoryLayout layout = ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN); + VarHandle intHandle = layout.varHandle(); VarHandle longHandle = MemoryHandles.asUnsigned(intHandle, long.class); try (ResourceScope scope = ResourceScope.newConfinedScope()) { @@ -165,8 +166,8 @@ public class TestMemoryHandleAsUnsigned { @Test public void testCoordinatesSequenceLayout() { - MemoryLayout layout = MemoryLayout.sequenceLayout(2, MemoryLayouts.BITS_8_BE); - VarHandle byteHandle = layout.varHandle(byte.class, PathElement.sequenceElement()); + MemoryLayout layout = MemoryLayout.sequenceLayout(2, ValueLayout.JAVA_BYTE); + VarHandle byteHandle = layout.varHandle(PathElement.sequenceElement()); VarHandle intHandle = MemoryHandles.asUnsigned(byteHandle, int.class); try (ResourceScope scope = ResourceScope.newConfinedScope()) { @@ -184,14 +185,14 @@ public class TestMemoryHandleAsUnsigned { MemorySegment segment = MemorySegment.ofArray(arr); { - VarHandle byteHandle = MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_BYTE) - .varHandle(byte.class, PathElement.sequenceElement()); + VarHandle byteHandle = MemoryLayout.sequenceLayout(ValueLayout.JAVA_BYTE) + .varHandle(PathElement.sequenceElement()); VarHandle intHandle = MemoryHandles.asUnsigned(byteHandle, int.class); assertEquals((int) intHandle.get(segment, 2L), 129); } { - VarHandle byteHandle = MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_BYTE) - .varHandle(byte.class, PathElement.sequenceElement()); + VarHandle byteHandle = MemoryLayout.sequenceLayout(ValueLayout.JAVA_BYTE) + .varHandle(PathElement.sequenceElement()); VarHandle intHandle = MemoryHandles.asUnsigned(byteHandle, int.class); assertEquals((int) intHandle.get(segment, 2L), 129); } @@ -201,7 +202,7 @@ public class TestMemoryHandleAsUnsigned { @Test public void testNull() { - VarHandle handle = MemoryHandles.varHandle(byte.class, BIG_ENDIAN); + VarHandle handle = MemoryHandles.varHandle(ValueLayout.JAVA_BYTE.withOrder(BIG_ENDIAN)); assertThrows(NPE, () -> MemoryHandles.asUnsigned(handle, null)); assertThrows(NPE, () -> MemoryHandles.asUnsigned(null, short.class)); assertThrows(NPE, () -> MemoryHandles.asUnsigned(null, null)); @@ -209,22 +210,22 @@ public class TestMemoryHandleAsUnsigned { static final Class<IllegalArgumentException> IAE = IllegalArgumentException.class; - static void assertIllegalArgumentExceptionIllegalCarrier(Class<?> carrier, Class<?> adaptedType) { - var vh = MemoryHandles.varHandle(carrier, BIG_ENDIAN); + static void assertIllegalArgumentExceptionIllegalCarrier(ValueLayout layout, Class<?> adaptedType) { + var vh = MemoryHandles.varHandle(layout.withOrder(BIG_ENDIAN)); var exception = expectThrows(IAE, () -> MemoryHandles.asUnsigned(vh, adaptedType)); var msg = exception.getMessage(); assertTrue(msg.contains("illegal carrier"), "Expected \"illegal carrier\" in:[" + msg +"]"); } - static void assertIllegalArgumentExceptionIllegalAdapter(Class<?> carrier, Class<?> adaptedType) { - var vh = MemoryHandles.varHandle(carrier, BIG_ENDIAN); + static void assertIllegalArgumentExceptionIllegalAdapter(ValueLayout layout, Class<?> adaptedType) { + var vh = MemoryHandles.varHandle(layout.withOrder(BIG_ENDIAN)); var exception = expectThrows(IAE, () -> MemoryHandles.asUnsigned(vh, adaptedType)); var msg = exception.getMessage(); assertTrue(msg.contains("illegal adapter type"), "Expected \"illegal adapter type\" in:[" + msg +"]"); } - static void assertIllegalArgumentExceptionIsNotWiderThan(Class<?> carrier, Class<?> adaptedType) { - var vh = MemoryHandles.varHandle(carrier, BIG_ENDIAN); + static void assertIllegalArgumentExceptionIsNotWiderThan(ValueLayout layout, Class<?> adaptedType) { + var vh = MemoryHandles.varHandle(layout.withOrder(BIG_ENDIAN)); var exception = expectThrows(IAE, () -> MemoryHandles.asUnsigned(vh, adaptedType)); var msg = exception.getMessage(); assertTrue(msg.contains("is not wider than"), "Expected \"is not wider than\" in:[" + msg +"]"); @@ -232,25 +233,25 @@ public class TestMemoryHandleAsUnsigned { @Test public void testIllegalArgumentException() { - assertIllegalArgumentExceptionIllegalCarrier(char.class, long.class); - assertIllegalArgumentExceptionIllegalCarrier(double.class, long.class); - assertIllegalArgumentExceptionIllegalCarrier(float.class, long.class); - assertIllegalArgumentExceptionIllegalCarrier(long.class, long.class); - - assertIllegalArgumentExceptionIllegalAdapter(byte.class, void.class); - assertIllegalArgumentExceptionIllegalAdapter(byte.class, byte.class); - assertIllegalArgumentExceptionIllegalAdapter(byte.class, short.class); - assertIllegalArgumentExceptionIllegalAdapter(byte.class, char.class); - assertIllegalArgumentExceptionIllegalAdapter(byte.class, double.class); - assertIllegalArgumentExceptionIllegalAdapter(byte.class, float.class); - assertIllegalArgumentExceptionIllegalAdapter(byte.class, Object.class); - assertIllegalArgumentExceptionIllegalAdapter(byte.class, Integer.class); - assertIllegalArgumentExceptionIllegalAdapter(byte.class, Long.class); - assertIllegalArgumentExceptionIllegalAdapter(byte.class, long[].class); - assertIllegalArgumentExceptionIllegalAdapter(byte.class, int[].class); - assertIllegalArgumentExceptionIllegalAdapter(byte.class, Integer[].class); - assertIllegalArgumentExceptionIllegalAdapter(byte.class, Long[].class); - - assertIllegalArgumentExceptionIsNotWiderThan(int.class, int.class); + assertIllegalArgumentExceptionIllegalCarrier(ValueLayout.JAVA_CHAR, long.class); + assertIllegalArgumentExceptionIllegalCarrier(ValueLayout.JAVA_DOUBLE, long.class); + assertIllegalArgumentExceptionIllegalCarrier(ValueLayout.JAVA_FLOAT, long.class); + assertIllegalArgumentExceptionIllegalCarrier(ValueLayout.JAVA_LONG, long.class); + + assertIllegalArgumentExceptionIllegalAdapter(ValueLayout.JAVA_BYTE, void.class); + assertIllegalArgumentExceptionIllegalAdapter(ValueLayout.JAVA_BYTE, byte.class); + assertIllegalArgumentExceptionIllegalAdapter(ValueLayout.JAVA_BYTE, short.class); + assertIllegalArgumentExceptionIllegalAdapter(ValueLayout.JAVA_BYTE, char.class); + assertIllegalArgumentExceptionIllegalAdapter(ValueLayout.JAVA_BYTE, double.class); + assertIllegalArgumentExceptionIllegalAdapter(ValueLayout.JAVA_BYTE, float.class); + assertIllegalArgumentExceptionIllegalAdapter(ValueLayout.JAVA_BYTE, Object.class); + assertIllegalArgumentExceptionIllegalAdapter(ValueLayout.JAVA_BYTE, Integer.class); + assertIllegalArgumentExceptionIllegalAdapter(ValueLayout.JAVA_BYTE, Long.class); + assertIllegalArgumentExceptionIllegalAdapter(ValueLayout.JAVA_BYTE, long[].class); + assertIllegalArgumentExceptionIllegalAdapter(ValueLayout.JAVA_BYTE, int[].class); + assertIllegalArgumentExceptionIllegalAdapter(ValueLayout.JAVA_BYTE, Integer[].class); + assertIllegalArgumentExceptionIllegalAdapter(ValueLayout.JAVA_BYTE, Long[].class); + + assertIllegalArgumentExceptionIsNotWiderThan(ValueLayout.JAVA_INT, int.class); } } diff --git a/test/jdk/java/foreign/TestMismatch.java b/test/jdk/java/foreign/TestMismatch.java index 5f4dd4c3195c31fed7df8abe96714dc6244b49aa..a399a20d9b82bb6a3a1ea66f7a3864798bd1336b 100644 --- a/test/jdk/java/foreign/TestMismatch.java +++ b/test/jdk/java/foreign/TestMismatch.java @@ -32,9 +32,9 @@ import java.util.List; import java.util.concurrent.atomic.AtomicReference; import java.util.function.IntFunction; -import jdk.incubator.foreign.MemoryLayouts; import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; +import jdk.incubator.foreign.ValueLayout; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import static java.lang.System.out; @@ -43,7 +43,7 @@ import static org.testng.Assert.assertThrows; public class TestMismatch { - final static VarHandle BYTE_HANDLE = MemoryLayouts.JAVA_BYTE.varHandle(byte.class); + final static VarHandle BYTE_HANDLE = ValueLayout.JAVA_BYTE.varHandle(); // stores a increasing sequence of values into the memory of the given segment static MemorySegment initializeSegment(MemorySegment segment) { @@ -112,7 +112,7 @@ public class TestMismatch { @Test public void testLarge() { // skip if not on 64 bits - if (MemoryLayouts.ADDRESS.byteSize() > 32) { + if (ValueLayout.ADDRESS.byteSize() > 32) { try (ResourceScope scope = ResourceScope.newConfinedScope()) { var s1 = MemorySegment.allocateNative((long) Integer.MAX_VALUE + 10L, 8, scope); var s2 = MemorySegment.allocateNative((long) Integer.MAX_VALUE + 10L, 8, scope); diff --git a/test/jdk/java/foreign/TestNULLAddress.java b/test/jdk/java/foreign/TestNULLAddress.java index 7ea4cbb974faa3cd59c7d7a467c5f6b8f298c47f..14aec5fb757665e3e88a5c855e6cb772481b1697 100644 --- a/test/jdk/java/foreign/TestNULLAddress.java +++ b/test/jdk/java/foreign/TestNULLAddress.java @@ -34,39 +34,37 @@ import jdk.incubator.foreign.Addressable; import jdk.incubator.foreign.CLinker; import jdk.incubator.foreign.FunctionDescriptor; import jdk.incubator.foreign.MemoryAddress; +import jdk.incubator.foreign.NativeSymbol; +import jdk.incubator.foreign.ResourceScope; import org.testng.annotations.Test; import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodType; -import java.nio.charset.Charset; public class TestNULLAddress { - static final CLinker LINKER = CLinker.getInstance(); + static final CLinker LINKER = CLinker.systemCLinker(); @Test(expectedExceptions = IllegalArgumentException.class) public void testNULLLinking() { LINKER.downcallHandle( - MemoryAddress.NULL, - MethodType.methodType(void.class), + NativeSymbol.ofAddress("nullAddress", MemoryAddress.NULL, ResourceScope.globalScope()), FunctionDescriptor.ofVoid()); } @Test(expectedExceptions = IllegalArgumentException.class) public void testNULLVirtual() throws Throwable { MethodHandle mh = LINKER.downcallHandle( - MethodType.methodType(void.class), FunctionDescriptor.ofVoid()); - mh.invokeExact((Addressable) MemoryAddress.NULL); + mh.invokeExact(NativeSymbol.ofAddress("null", MemoryAddress.NULL, ResourceScope.globalScope())); } @Test(expectedExceptions = IllegalArgumentException.class) - public void testNULLtoJavaString() { - CLinker.toJavaString(MemoryAddress.NULL); + public void testNULLgetString() { + MemoryAddress.NULL.getUtf8String(0); } @Test(expectedExceptions = IllegalArgumentException.class) - public void testNULLfreeMemory() { - CLinker.freeMemory(MemoryAddress.NULL); + public void testNULLsetString() { + MemoryAddress.NULL.setUtf8String(0, "hello"); } } diff --git a/test/jdk/java/foreign/TestNative.java b/test/jdk/java/foreign/TestNative.java index 443c13b11d5060e2e6a7568c0123f51193538249..0b6a6cdfb8d3719e280ef2e557bc2b6d37535bfc 100644 --- a/test/jdk/java/foreign/TestNative.java +++ b/test/jdk/java/foreign/TestNative.java @@ -29,15 +29,13 @@ * @run testng/othervm --enable-native-access=ALL-UNNAMED TestNative */ -import jdk.incubator.foreign.CLinker; -import jdk.incubator.foreign.MemoryAccess; import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.MemoryLayout.PathElement; -import jdk.incubator.foreign.MemoryLayouts; import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; import jdk.incubator.foreign.SequenceLayout; +import jdk.incubator.foreign.ValueLayout; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -56,45 +54,46 @@ import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Function; +import static jdk.incubator.foreign.ValueLayout.JAVA_INT; import static org.testng.Assert.*; -public class TestNative { +public class TestNative extends NativeTestHelper { static SequenceLayout bytes = MemoryLayout.sequenceLayout(100, - MemoryLayouts.JAVA_BYTE.withOrder(ByteOrder.nativeOrder()) + ValueLayout.JAVA_BYTE.withOrder(ByteOrder.nativeOrder()) ); static SequenceLayout chars = MemoryLayout.sequenceLayout(100, - MemoryLayouts.JAVA_CHAR.withOrder(ByteOrder.nativeOrder()) + ValueLayout.JAVA_CHAR.withOrder(ByteOrder.nativeOrder()) ); static SequenceLayout shorts = MemoryLayout.sequenceLayout(100, - MemoryLayouts.JAVA_SHORT.withOrder(ByteOrder.nativeOrder()) + ValueLayout.JAVA_SHORT.withOrder(ByteOrder.nativeOrder()) ); static SequenceLayout ints = MemoryLayout.sequenceLayout(100, - MemoryLayouts.JAVA_INT.withOrder(ByteOrder.nativeOrder()) + JAVA_INT.withOrder(ByteOrder.nativeOrder()) ); static SequenceLayout floats = MemoryLayout.sequenceLayout(100, - MemoryLayouts.JAVA_FLOAT.withOrder(ByteOrder.nativeOrder()) + ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.nativeOrder()) ); static SequenceLayout longs = MemoryLayout.sequenceLayout(100, - MemoryLayouts.JAVA_LONG.withOrder(ByteOrder.nativeOrder()) + ValueLayout.JAVA_LONG.withOrder(ByteOrder.nativeOrder()) ); static SequenceLayout doubles = MemoryLayout.sequenceLayout(100, - MemoryLayouts.JAVA_DOUBLE.withOrder(ByteOrder.nativeOrder()) + ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.nativeOrder()) ); - static VarHandle byteHandle = bytes.varHandle(byte.class, PathElement.sequenceElement()); - static VarHandle charHandle = chars.varHandle(char.class, PathElement.sequenceElement()); - static VarHandle shortHandle = shorts.varHandle(short.class, PathElement.sequenceElement()); - static VarHandle intHandle = ints.varHandle(int.class, PathElement.sequenceElement()); - static VarHandle floatHandle = floats.varHandle(float.class, PathElement.sequenceElement()); - static VarHandle longHandle = doubles.varHandle(long.class, PathElement.sequenceElement()); - static VarHandle doubleHandle = longs.varHandle(double.class, PathElement.sequenceElement()); + static VarHandle byteHandle = bytes.varHandle(PathElement.sequenceElement()); + static VarHandle charHandle = chars.varHandle(PathElement.sequenceElement()); + static VarHandle shortHandle = shorts.varHandle(PathElement.sequenceElement()); + static VarHandle intHandle = ints.varHandle(PathElement.sequenceElement()); + static VarHandle floatHandle = floats.varHandle(PathElement.sequenceElement()); + static VarHandle longHandle = longs.varHandle(PathElement.sequenceElement()); + static VarHandle doubleHandle = doubles.varHandle(PathElement.sequenceElement()); static void initBytes(MemorySegment base, SequenceLayout seq, BiConsumer<MemorySegment, Long> handleSetter) { for (long i = 0; i < seq.elementCount().getAsLong() ; i++) { @@ -144,14 +143,6 @@ public class TestNative { public static native long getCapacity(Buffer buffer); - public static MemoryAddress allocate(int size) { - return CLinker.allocateMemory(size); - } - - public static void free(MemoryAddress addr) { - CLinker.freeMemory(addr); - } - @Test(dataProvider="nativeAccessOps") public void testNativeAccess(Consumer<MemorySegment> checker, Consumer<MemorySegment> initializer, SequenceLayout seq) { try (ResourceScope scope = ResourceScope.newConfinedScope()) { @@ -176,25 +167,21 @@ public class TestNative { @Test public void testDefaultAccessModes() { - MemoryAddress addr = allocate(12); + MemoryAddress addr = allocateMemory(12); try (ResourceScope scope = ResourceScope.newConfinedScope()) { - MemorySegment mallocSegment = addr.asSegment(12, () -> free(addr), scope); + scope.addCloseAction(() -> freeMemory(addr)); + MemorySegment mallocSegment = MemorySegment.ofAddress(addr, 12, scope); assertFalse(mallocSegment.isReadOnly()); } } - @Test - public void testDefaultAccessModesEverthing() { - MemorySegment everything = MemorySegment.globalNativeSegment(); - assertFalse(everything.isReadOnly()); - } - @Test public void testMallocSegment() { - MemoryAddress addr = allocate(12); + MemoryAddress addr = allocateMemory(12); MemorySegment mallocSegment = null; try (ResourceScope scope = ResourceScope.newConfinedScope()) { - mallocSegment = addr.asSegment(12, () -> free(addr), scope); + scope.addCloseAction(() -> freeMemory(addr)); + mallocSegment = MemorySegment.ofAddress(addr, 12, scope); assertEquals(mallocSegment.byteSize(), 12); //free here } @@ -202,19 +189,18 @@ public class TestNative { } @Test - public void testEverythingSegment() { - MemoryAddress addr = allocate(4); - MemorySegment everything = MemorySegment.globalNativeSegment(); - MemoryAccess.setIntAtOffset(everything, addr.toRawLongValue(), 42); - assertEquals(MemoryAccess.getIntAtOffset(everything, addr.toRawLongValue()), 42); - free(addr); + public void testAddressAccess() { + MemoryAddress addr = allocateMemory(4); + addr.set(JAVA_INT, 0, 42); + assertEquals(addr.get(JAVA_INT, 0), 42); + freeMemory(addr); } @Test(expectedExceptions = IllegalArgumentException.class) public void testBadResize() { try (ResourceScope scope = ResourceScope.newConfinedScope()) { MemorySegment segment = MemorySegment.allocateNative(4, 1, scope); - segment.address().asSegment(0, ResourceScope.globalScope()); + MemorySegment.ofAddress(segment.address(), 0, ResourceScope.globalScope()); } } diff --git a/test/jdk/java/foreign/TestNoForeignUnsafeOverride.java b/test/jdk/java/foreign/TestNoForeignUnsafeOverride.java index ac47ea3113f051b50f575e6ca725e1e641eef7fe..d5aa76dc5413a73e1db1bb9200bd98d78f0f4178 100644 --- a/test/jdk/java/foreign/TestNoForeignUnsafeOverride.java +++ b/test/jdk/java/foreign/TestNoForeignUnsafeOverride.java @@ -28,7 +28,7 @@ import jdk.incubator.foreign.*; public class PanamaMain { public static void main(String[] args) { System.out.println("Trying to get CLinker"); - CLinker.getInstance(); + CLinker.systemCLinker(); System.out.println("Got CLinker"); } } diff --git a/test/jdk/java/foreign/TestNulls.java b/test/jdk/java/foreign/TestNulls.java index ccb27a61d35d5af741f977f642d96346bce0e2ca..7f57108b5d2a68078e241dc54d8d3687575c6a09 100644 --- a/test/jdk/java/foreign/TestNulls.java +++ b/test/jdk/java/foreign/TestNulls.java @@ -60,6 +60,8 @@ import java.util.function.UnaryOperator; import java.util.stream.Collectors; import java.util.stream.Stream; +import static jdk.incubator.foreign.ValueLayout.JAVA_INT; +import static jdk.incubator.foreign.ValueLayout.JAVA_LONG; import static org.testng.Assert.*; import static org.testng.Assert.fail; @@ -82,27 +84,43 @@ public class TestNulls { MemoryLayout.PathElement.class, SequenceLayout.class, ValueLayout.class, + ValueLayout.OfBoolean.class, + ValueLayout.OfByte.class, + ValueLayout.OfChar.class, + ValueLayout.OfShort.class, + ValueLayout.OfInt.class, + ValueLayout.OfFloat.class, + ValueLayout.OfLong.class, + ValueLayout.OfDouble.class, + ValueLayout.OfAddress.class, GroupLayout.class, Addressable.class, SymbolLookup.class, - MemoryAccess.class, - MemoryLayouts.class, MemoryHandles.class, CLinker.class, - CLinker.VaList.class, - CLinker.VaList.Builder.class, + VaList.class, + VaList.Builder.class, FunctionDescriptor.class, SegmentAllocator.class, - ResourceScope.class + ResourceScope.class, + NativeSymbol.class }; static final Set<String> EXCLUDE_LIST = Set.of( + "jdk.incubator.foreign.ResourceScope/newConfinedScope(java.lang.ref.Cleaner)/0/0", + "jdk.incubator.foreign.ResourceScope/newSharedScope(java.lang.ref.Cleaner)/0/0", "jdk.incubator.foreign.MemoryLayout/withAttribute(java.lang.String,java.lang.constant.Constable)/1/0", - "jdk.incubator.foreign.MemoryAddress/asSegment(long,java.lang.Runnable,java.lang.Object)/1/0", - "jdk.incubator.foreign.MemoryAddress/asSegment(long,java.lang.Runnable,java.lang.Object)/2/0", - "jdk.incubator.foreign.MemoryAddress/asSegment(long,java.lang.Runnable,jdk.incubator.foreign.ResourceScope)/1/0", "jdk.incubator.foreign.SequenceLayout/withAttribute(java.lang.String,java.lang.constant.Constable)/1/0", "jdk.incubator.foreign.ValueLayout/withAttribute(java.lang.String,java.lang.constant.Constable)/1/0", + "jdk.incubator.foreign.ValueLayout$OfAddress/withAttribute(java.lang.String,java.lang.constant.Constable)/1/0", + "jdk.incubator.foreign.ValueLayout$OfBoolean/withAttribute(java.lang.String,java.lang.constant.Constable)/1/0", + "jdk.incubator.foreign.ValueLayout$OfByte/withAttribute(java.lang.String,java.lang.constant.Constable)/1/0", + "jdk.incubator.foreign.ValueLayout$OfChar/withAttribute(java.lang.String,java.lang.constant.Constable)/1/0", + "jdk.incubator.foreign.ValueLayout$OfShort/withAttribute(java.lang.String,java.lang.constant.Constable)/1/0", + "jdk.incubator.foreign.ValueLayout$OfInt/withAttribute(java.lang.String,java.lang.constant.Constable)/1/0", + "jdk.incubator.foreign.ValueLayout$OfFloat/withAttribute(java.lang.String,java.lang.constant.Constable)/1/0", + "jdk.incubator.foreign.ValueLayout$OfLong/withAttribute(java.lang.String,java.lang.constant.Constable)/1/0", + "jdk.incubator.foreign.ValueLayout$OfDouble/withAttribute(java.lang.String,java.lang.constant.Constable)/1/0", "jdk.incubator.foreign.GroupLayout/withAttribute(java.lang.String,java.lang.constant.Constable)/1/0", "jdk.incubator.foreign.MemoryHandles/insertCoordinates(java.lang.invoke.VarHandle,int,java.lang.Object[])/2/1", "jdk.incubator.foreign.FunctionDescriptor/withAttribute(java.lang.String,java.lang.constant.Constable)/1/0" @@ -139,7 +157,7 @@ public class TestNulls { addDefaultMapping(Class.class, String.class); addDefaultMapping(Runnable.class, () -> {}); addDefaultMapping(Object.class, new Object()); - addDefaultMapping(VarHandle.class, MemoryHandles.varHandle(int.class, ByteOrder.nativeOrder())); + addDefaultMapping(VarHandle.class, MemoryHandles.varHandle(JAVA_INT)); addDefaultMapping(MethodHandle.class, MethodHandles.identity(int.class)); addDefaultMapping(List.class, List.of()); addDefaultMapping(Charset.class, Charset.defaultCharset()); @@ -147,32 +165,41 @@ public class TestNulls { addDefaultMapping(MethodType.class, MethodType.methodType(void.class)); addDefaultMapping(MemoryAddress.class, MemoryAddress.ofLong(1)); addDefaultMapping(Addressable.class, MemoryAddress.ofLong(1)); - addDefaultMapping(MemoryLayout.class, MemoryLayouts.JAVA_INT); - addDefaultMapping(ValueLayout.class, MemoryLayouts.JAVA_INT); - addDefaultMapping(GroupLayout.class, MemoryLayout.structLayout(MemoryLayouts.JAVA_INT)); - addDefaultMapping(SequenceLayout.class, MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_INT)); + addDefaultMapping(MemoryLayout.class, ValueLayout.JAVA_INT); + addDefaultMapping(ValueLayout.class, ValueLayout.JAVA_INT); + addDefaultMapping(ValueLayout.OfAddress.class, ValueLayout.ADDRESS); + addDefaultMapping(ValueLayout.OfByte.class, ValueLayout.JAVA_BYTE); + addDefaultMapping(ValueLayout.OfBoolean.class, ValueLayout.JAVA_BOOLEAN); + addDefaultMapping(ValueLayout.OfChar.class, ValueLayout.JAVA_CHAR); + addDefaultMapping(ValueLayout.OfShort.class, ValueLayout.JAVA_SHORT); + addDefaultMapping(ValueLayout.OfInt.class, ValueLayout.JAVA_INT); + addDefaultMapping(ValueLayout.OfFloat.class, ValueLayout.JAVA_FLOAT); + addDefaultMapping(ValueLayout.OfLong.class, JAVA_LONG); + addDefaultMapping(ValueLayout.OfDouble.class, ValueLayout.JAVA_DOUBLE); + addDefaultMapping(GroupLayout.class, MemoryLayout.structLayout(ValueLayout.JAVA_INT)); + addDefaultMapping(SequenceLayout.class, MemoryLayout.sequenceLayout(ValueLayout.JAVA_INT)); addDefaultMapping(MemorySegment.class, MemorySegment.ofArray(new byte[10])); addDefaultMapping(FunctionDescriptor.class, FunctionDescriptor.ofVoid()); - addDefaultMapping(CLinker.class, CLinker.getInstance()); - addDefaultMapping(CLinker.VaList.class, VaListHelper.vaList); - addDefaultMapping(CLinker.VaList.Builder.class, VaListHelper.vaListBuilder); - addDefaultMapping(ResourceScope.class, ResourceScope.newImplicitScope()); - addDefaultMapping(SegmentAllocator.class, (size, align) -> null); + addDefaultMapping(CLinker.class, CLinker.systemCLinker()); + addDefaultMapping(VaList.class, VaListHelper.vaList); + addDefaultMapping(VaList.Builder.class, VaListHelper.vaListBuilder); + addDefaultMapping(ResourceScope.class, ResourceScope.newSharedScope()); + addDefaultMapping(SegmentAllocator.class, SegmentAllocator.prefixAllocator(MemorySegment.ofArray(new byte[10]))); addDefaultMapping(Supplier.class, () -> null); - addDefaultMapping(ResourceScope.Handle.class, ResourceScope.globalScope().acquire()); addDefaultMapping(ClassLoader.class, TestNulls.class.getClassLoader()); - addDefaultMapping(SymbolLookup.class, CLinker.systemLookup()); + addDefaultMapping(SymbolLookup.class, CLinker.systemCLinker()); + addDefaultMapping(NativeSymbol.class, NativeSymbol.ofAddress("dummy", MemoryAddress.ofLong(1), ResourceScope.globalScope())); } static class VaListHelper { - static final CLinker.VaList vaList; - static final CLinker.VaList.Builder vaListBuilder; + static final VaList vaList; + static final VaList.Builder vaListBuilder; static { - AtomicReference<CLinker.VaList.Builder> builderRef = new AtomicReference<>(); - vaList = CLinker.VaList.make(b -> { + AtomicReference<VaList.Builder> builderRef = new AtomicReference<>(); + vaList = VaList.make(b -> { builderRef.set(b); - b.vargFromLong(CLinker.C_LONG_LONG, 42L); + b.addVarg(JAVA_LONG, 42L); }, ResourceScope.newImplicitScope()); vaListBuilder = builderRef.get(); } diff --git a/test/jdk/java/foreign/TestReshape.java b/test/jdk/java/foreign/TestReshape.java index dc53e83ee0f09d9dcaaf8af9f19096f186221a84..4fcfb5eb2103e0cf2c41b519522fe99781dadf63 100644 --- a/test/jdk/java/foreign/TestReshape.java +++ b/test/jdk/java/foreign/TestReshape.java @@ -27,7 +27,6 @@ */ import jdk.incubator.foreign.MemoryLayout; -import jdk.incubator.foreign.MemoryLayouts; import jdk.incubator.foreign.SequenceLayout; import java.util.ArrayList; @@ -35,6 +34,7 @@ import java.util.Iterator; import java.util.List; import java.util.stream.LongStream; +import jdk.incubator.foreign.ValueLayout; import org.testng.annotations.*; import static org.testng.Assert.*; @@ -54,43 +54,43 @@ public class TestReshape { @Test(expectedExceptions = IllegalArgumentException.class) public void testInvalidReshape() { - SequenceLayout seq = MemoryLayout.sequenceLayout(4, MemoryLayouts.JAVA_INT); + SequenceLayout seq = MemoryLayout.sequenceLayout(4, ValueLayout.JAVA_INT); seq.reshape(3, 2); } @Test(expectedExceptions = IllegalArgumentException.class) public void testBadReshapeInference() { - SequenceLayout seq = MemoryLayout.sequenceLayout(4, MemoryLayouts.JAVA_INT); + SequenceLayout seq = MemoryLayout.sequenceLayout(4, ValueLayout.JAVA_INT); seq.reshape(-1, -1); } @Test(expectedExceptions = IllegalArgumentException.class) public void testBadReshapeParameterZero() { - SequenceLayout seq = MemoryLayout.sequenceLayout(4, MemoryLayouts.JAVA_INT); + SequenceLayout seq = MemoryLayout.sequenceLayout(4, ValueLayout.JAVA_INT); seq.reshape(0, 4); } @Test(expectedExceptions = IllegalArgumentException.class) public void testBadReshapeParameterNegative() { - SequenceLayout seq = MemoryLayout.sequenceLayout(4, MemoryLayouts.JAVA_INT); + SequenceLayout seq = MemoryLayout.sequenceLayout(4, ValueLayout.JAVA_INT); seq.reshape(-2, 2); } @Test(expectedExceptions = UnsupportedOperationException.class) public void testReshapeOnUnboundSequence() { - SequenceLayout seq = MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_INT); + SequenceLayout seq = MemoryLayout.sequenceLayout(ValueLayout.JAVA_INT); seq.reshape(3, 2); } @Test(expectedExceptions = UnsupportedOperationException.class) public void testFlattenOnUnboundSequence() { - SequenceLayout seq = MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_INT); + SequenceLayout seq = MemoryLayout.sequenceLayout(ValueLayout.JAVA_INT); seq.flatten(); } @Test(expectedExceptions = UnsupportedOperationException.class) public void testFlattenOnUnboundNestedSequence() { - SequenceLayout seq = MemoryLayout.sequenceLayout(4, MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_INT)); + SequenceLayout seq = MemoryLayout.sequenceLayout(4, MemoryLayout.sequenceLayout(ValueLayout.JAVA_INT)); seq.flatten(); } @@ -125,61 +125,61 @@ public class TestReshape { } static MemoryLayout POINT = MemoryLayout.structLayout( - MemoryLayouts.JAVA_INT, - MemoryLayouts.JAVA_INT + ValueLayout.JAVA_INT, + ValueLayout.JAVA_INT ); @DataProvider(name = "shapes") Object[][] shapes() { return new Object[][] { - { MemoryLayouts.JAVA_BYTE, new long[] { 256 } }, - { MemoryLayouts.JAVA_BYTE, new long[] { 16, 16 } }, - { MemoryLayouts.JAVA_BYTE, new long[] { 4, 4, 4, 4 } }, - { MemoryLayouts.JAVA_BYTE, new long[] { 2, 8, 16 } }, - { MemoryLayouts.JAVA_BYTE, new long[] { 16, 8, 2 } }, - { MemoryLayouts.JAVA_BYTE, new long[] { 8, 16, 2 } }, - - { MemoryLayouts.JAVA_SHORT, new long[] { 256 } }, - { MemoryLayouts.JAVA_SHORT, new long[] { 16, 16 } }, - { MemoryLayouts.JAVA_SHORT, new long[] { 4, 4, 4, 4 } }, - { MemoryLayouts.JAVA_SHORT, new long[] { 2, 8, 16 } }, - { MemoryLayouts.JAVA_SHORT, new long[] { 16, 8, 2 } }, - { MemoryLayouts.JAVA_SHORT, new long[] { 8, 16, 2 } }, - - { MemoryLayouts.JAVA_CHAR, new long[] { 256 } }, - { MemoryLayouts.JAVA_CHAR, new long[] { 16, 16 } }, - { MemoryLayouts.JAVA_CHAR, new long[] { 4, 4, 4, 4 } }, - { MemoryLayouts.JAVA_CHAR, new long[] { 2, 8, 16 } }, - { MemoryLayouts.JAVA_CHAR, new long[] { 16, 8, 2 } }, - { MemoryLayouts.JAVA_CHAR, new long[] { 8, 16, 2 } }, - - { MemoryLayouts.JAVA_INT, new long[] { 256 } }, - { MemoryLayouts.JAVA_INT, new long[] { 16, 16 } }, - { MemoryLayouts.JAVA_INT, new long[] { 4, 4, 4, 4 } }, - { MemoryLayouts.JAVA_INT, new long[] { 2, 8, 16 } }, - { MemoryLayouts.JAVA_INT, new long[] { 16, 8, 2 } }, - { MemoryLayouts.JAVA_INT, new long[] { 8, 16, 2 } }, - - { MemoryLayouts.JAVA_LONG, new long[] { 256 } }, - { MemoryLayouts.JAVA_LONG, new long[] { 16, 16 } }, - { MemoryLayouts.JAVA_LONG, new long[] { 4, 4, 4, 4 } }, - { MemoryLayouts.JAVA_LONG, new long[] { 2, 8, 16 } }, - { MemoryLayouts.JAVA_LONG, new long[] { 16, 8, 2 } }, - { MemoryLayouts.JAVA_LONG, new long[] { 8, 16, 2 } }, - - { MemoryLayouts.JAVA_FLOAT, new long[] { 256 } }, - { MemoryLayouts.JAVA_FLOAT, new long[] { 16, 16 } }, - { MemoryLayouts.JAVA_FLOAT, new long[] { 4, 4, 4, 4 } }, - { MemoryLayouts.JAVA_FLOAT, new long[] { 2, 8, 16 } }, - { MemoryLayouts.JAVA_FLOAT, new long[] { 16, 8, 2 } }, - { MemoryLayouts.JAVA_FLOAT, new long[] { 8, 16, 2 } }, - - { MemoryLayouts.JAVA_DOUBLE, new long[] { 256 } }, - { MemoryLayouts.JAVA_DOUBLE, new long[] { 16, 16 } }, - { MemoryLayouts.JAVA_DOUBLE, new long[] { 4, 4, 4, 4 } }, - { MemoryLayouts.JAVA_DOUBLE, new long[] { 2, 8, 16 } }, - { MemoryLayouts.JAVA_DOUBLE, new long[] { 16, 8, 2 } }, - { MemoryLayouts.JAVA_DOUBLE, new long[] { 8, 16, 2 } }, + { ValueLayout.JAVA_BYTE, new long[] { 256 } }, + { ValueLayout.JAVA_BYTE, new long[] { 16, 16 } }, + { ValueLayout.JAVA_BYTE, new long[] { 4, 4, 4, 4 } }, + { ValueLayout.JAVA_BYTE, new long[] { 2, 8, 16 } }, + { ValueLayout.JAVA_BYTE, new long[] { 16, 8, 2 } }, + { ValueLayout.JAVA_BYTE, new long[] { 8, 16, 2 } }, + + { ValueLayout.JAVA_SHORT, new long[] { 256 } }, + { ValueLayout.JAVA_SHORT, new long[] { 16, 16 } }, + { ValueLayout.JAVA_SHORT, new long[] { 4, 4, 4, 4 } }, + { ValueLayout.JAVA_SHORT, new long[] { 2, 8, 16 } }, + { ValueLayout.JAVA_SHORT, new long[] { 16, 8, 2 } }, + { ValueLayout.JAVA_SHORT, new long[] { 8, 16, 2 } }, + + { ValueLayout.JAVA_CHAR, new long[] { 256 } }, + { ValueLayout.JAVA_CHAR, new long[] { 16, 16 } }, + { ValueLayout.JAVA_CHAR, new long[] { 4, 4, 4, 4 } }, + { ValueLayout.JAVA_CHAR, new long[] { 2, 8, 16 } }, + { ValueLayout.JAVA_CHAR, new long[] { 16, 8, 2 } }, + { ValueLayout.JAVA_CHAR, new long[] { 8, 16, 2 } }, + + { ValueLayout.JAVA_INT, new long[] { 256 } }, + { ValueLayout.JAVA_INT, new long[] { 16, 16 } }, + { ValueLayout.JAVA_INT, new long[] { 4, 4, 4, 4 } }, + { ValueLayout.JAVA_INT, new long[] { 2, 8, 16 } }, + { ValueLayout.JAVA_INT, new long[] { 16, 8, 2 } }, + { ValueLayout.JAVA_INT, new long[] { 8, 16, 2 } }, + + { ValueLayout.JAVA_LONG, new long[] { 256 } }, + { ValueLayout.JAVA_LONG, new long[] { 16, 16 } }, + { ValueLayout.JAVA_LONG, new long[] { 4, 4, 4, 4 } }, + { ValueLayout.JAVA_LONG, new long[] { 2, 8, 16 } }, + { ValueLayout.JAVA_LONG, new long[] { 16, 8, 2 } }, + { ValueLayout.JAVA_LONG, new long[] { 8, 16, 2 } }, + + { ValueLayout.JAVA_FLOAT, new long[] { 256 } }, + { ValueLayout.JAVA_FLOAT, new long[] { 16, 16 } }, + { ValueLayout.JAVA_FLOAT, new long[] { 4, 4, 4, 4 } }, + { ValueLayout.JAVA_FLOAT, new long[] { 2, 8, 16 } }, + { ValueLayout.JAVA_FLOAT, new long[] { 16, 8, 2 } }, + { ValueLayout.JAVA_FLOAT, new long[] { 8, 16, 2 } }, + + { ValueLayout.JAVA_DOUBLE, new long[] { 256 } }, + { ValueLayout.JAVA_DOUBLE, new long[] { 16, 16 } }, + { ValueLayout.JAVA_DOUBLE, new long[] { 4, 4, 4, 4 } }, + { ValueLayout.JAVA_DOUBLE, new long[] { 2, 8, 16 } }, + { ValueLayout.JAVA_DOUBLE, new long[] { 16, 8, 2 } }, + { ValueLayout.JAVA_DOUBLE, new long[] { 8, 16, 2 } }, { POINT, new long[] { 256 } }, { POINT, new long[] { 16, 16 } }, diff --git a/test/jdk/java/foreign/TestResourceScope.java b/test/jdk/java/foreign/TestResourceScope.java index bb126abbe8a6b27f540da8b4d0ca21e8b58dd7dc..77c436bca89912792bb7ac5fcf3816632f2bb6b0 100644 --- a/test/jdk/java/foreign/TestResourceScope.java +++ b/test/jdk/java/foreign/TestResourceScope.java @@ -39,6 +39,7 @@ import static org.testng.Assert.*; import java.util.ArrayList; import java.util.List; +import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Supplier; @@ -157,15 +158,14 @@ public class TestResourceScope { } } - @Test(dataProvider = "cleaners") - public void testLockSingleThread(Supplier<Cleaner> cleanerSupplier) { - Cleaner cleaner = cleanerSupplier.get(); - ResourceScope scope = cleaner != null ? - ResourceScope.newConfinedScope(cleaner) : - ResourceScope.newConfinedScope(); - List<ResourceScope.Handle> handles = new ArrayList<>(); + @Test + public void testLockSingleThread() { + ResourceScope scope = ResourceScope.newConfinedScope(); + List<ResourceScope> handles = new ArrayList<>(); for (int i = 0 ; i < N_THREADS ; i++) { - handles.add(scope.acquire()); + ResourceScope handle = ResourceScope.newConfinedScope(); + handle.keepAlive(scope); + handles.add(handle); } while (true) { @@ -175,31 +175,24 @@ public class TestResourceScope { break; } catch (IllegalStateException ex) { assertTrue(handles.size() > 0); - ResourceScope.Handle handle = handles.remove(0); - scope.release(handle); - scope.release(handle); // make sure it's idempotent - scope.release(handle); // make sure it's idempotent + ResourceScope handle = handles.remove(0); + handle.close(); } } } - @Test(dataProvider = "cleaners") - public void testLockSharedMultiThread(Supplier<Cleaner> cleanerSupplier) { - Cleaner cleaner = cleanerSupplier.get(); - ResourceScope scope = cleaner != null ? - ResourceScope.newSharedScope(cleaner) : - ResourceScope.newSharedScope(); + @Test + public void testLockSharedMultiThread() { + ResourceScope scope = ResourceScope.newSharedScope(); AtomicInteger lockCount = new AtomicInteger(); for (int i = 0 ; i < N_THREADS ; i++) { new Thread(() -> { - try { - ResourceScope.Handle handle = scope.acquire(); // this can throw if segment has been closed + try (ResourceScope handle = ResourceScope.newConfinedScope()) { + handle.keepAlive(scope); lockCount.incrementAndGet(); waitSomeTime(); lockCount.decrementAndGet(); - scope.release(handle); // cannot throw (acquired segments cannot be closed) - scope.release(handle); // cannot throw (idempotent) - scope.release(handle); // cannot throw (idempotent) + handle.close(); } catch (IllegalStateException ex) { // might be already closed - do nothing } @@ -230,13 +223,12 @@ public class TestResourceScope { @Test public void testCloseConfinedLock() { ResourceScope scope = ResourceScope.newConfinedScope(); - ResourceScope.Handle handle = scope.acquire(); + ResourceScope handle = ResourceScope.newConfinedScope(); + handle.keepAlive(scope); AtomicReference<Throwable> failure = new AtomicReference<>(); Thread t = new Thread(() -> { try { - scope.release(handle); - scope.release(handle); // make sure it's idempotent - scope.release(handle); // make sure it's idempotent + handle.close(); } catch (Throwable ex) { failure.set(ex); } @@ -255,24 +247,85 @@ public class TestResourceScope { public void testScopeHandles(Supplier<ResourceScope> scopeFactory) { ResourceScope scope = scopeFactory.get(); acquireRecursive(scope, 5); - if (!scope.isImplicit()) { + if (scope != ResourceScope.globalScope()) { scope.close(); } } + @Test(dataProvider = "scopes", expectedExceptions = IllegalArgumentException.class) + public void testAcquireSelf(Supplier<ResourceScope> scopeSupplier) { + ResourceScope scope = scopeSupplier.get(); + scope.keepAlive(scope); + } + private void acquireRecursive(ResourceScope scope, int acquireCount) { - ResourceScope.Handle handle = scope.acquire(); - assertEquals(handle.scope(), scope); - if (acquireCount > 0) { - // recursive acquire - acquireRecursive(scope, acquireCount - 1); + try (ResourceScope handle = ResourceScope.newConfinedScope()) { + handle.keepAlive(scope); + if (acquireCount > 0) { + // recursive acquire + acquireRecursive(scope, acquireCount - 1); + } + if (scope != ResourceScope.globalScope()) { + assertThrows(IllegalStateException.class, scope::close); + } } - if (!scope.isImplicit()) { - assertThrows(IllegalStateException.class, scope::close); + } + + @Test + public void testConfinedScopeWithImplicitDependency() { + ResourceScope root = ResourceScope.newConfinedScope(); + // Create many implicit scopes which depend on 'root', and let them become unreachable. + for (int i = 0; i < N_THREADS; i++) { + ResourceScope.newConfinedScope(Cleaner.create()).keepAlive(root); } - scope.release(handle); - scope.release(handle); // make sure it's idempotent - scope.release(handle); // make sure it's idempotent + // Now let's keep trying to close 'root' until we succeed. This is trickier than it seems: cleanup action + // might be called from another thread (the Cleaner thread), so that the confined scope lock count is updated racily. + // If that happens, the loop below never terminates. + while (true) { + try { + root.close(); + break; // success! + } catch (IllegalStateException ex) { + kickGC(); + for (int i = 0 ; i < N_THREADS ; i++) { // add more races from current thread + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + scope.keepAlive(root); + // dummy + } + } + // try again + } + } + } + + @Test + public void testConfinedScopeWithSharedDependency() { + ResourceScope root = ResourceScope.newConfinedScope(); + List<Thread> threads = new ArrayList<>(); + // Create many implicit scopes which depend on 'root', and let them become unreachable. + for (int i = 0; i < N_THREADS; i++) { + ResourceScope scope = ResourceScope.newSharedScope(); // create scope inside same thread! + scope.keepAlive(root); + Thread t = new Thread(scope::close); // close from another thread! + threads.add(t); + t.start(); + } + for (int i = 0 ; i < N_THREADS ; i++) { // add more races from current thread + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + scope.keepAlive(root); + // dummy + } + } + threads.forEach(t -> { + try { + t.join(); + } catch (InterruptedException ex) { + // ok + } + }); + // Now let's close 'root'. This is trickier than it seems: releases of the confined scope happen in different + // threads, so that the confined scope lock count is updated racily. If that happens, the following close will blow up. + root.close(); } private void waitSomeTime() { diff --git a/test/jdk/java/foreign/TestRestricted.java b/test/jdk/java/foreign/TestRestricted.java index 68d23b6eb237e34b01c7fadda1dbc17386a00ff0..8667ffe1f471008adb82abb994f9d927b194c92c 100644 --- a/test/jdk/java/foreign/TestRestricted.java +++ b/test/jdk/java/foreign/TestRestricted.java @@ -21,6 +21,7 @@ * questions. */ +import jdk.incubator.foreign.CLinker; import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; @@ -38,37 +39,37 @@ import java.lang.reflect.InvocationTargetException; public class TestRestricted { @Test(expectedExceptions = InvocationTargetException.class) public void testReflection() throws Throwable { - Method method = MemorySegment.class.getDeclaredMethod("globalNativeSegment"); + Method method = CLinker.class.getDeclaredMethod("systemCLinker"); method.invoke(null); } @Test(expectedExceptions = IllegalCallerException.class) public void testInvoke() throws Throwable { - var mh = MethodHandles.lookup().findStatic(MemorySegment.class, - "globalNativeSegment", MethodType.methodType(MemorySegment.class)); - var seg = (MemorySegment)mh.invokeExact(); + var mh = MethodHandles.lookup().findStatic(CLinker.class, + "systemCLinker", MethodType.methodType(CLinker.class)); + var seg = (CLinker)mh.invokeExact(); } @Test(expectedExceptions = IllegalCallerException.class) public void testDirectAccess() throws Throwable { - MemorySegment.globalNativeSegment(); + CLinker.systemCLinker(); } @Test(expectedExceptions = InvocationTargetException.class) public void testReflection2() throws Throwable { - Method method = MemoryAddress.class.getDeclaredMethod("asSegment", long.class, ResourceScope.class); - method.invoke(MemoryAddress.NULL, 4000L, ResourceScope.globalScope()); + Method method = MemorySegment.class.getDeclaredMethod("ofAddress", MemoryAddress.class, long.class, ResourceScope.class); + method.invoke(null, MemoryAddress.NULL, 4000L, ResourceScope.globalScope()); } @Test(expectedExceptions = IllegalCallerException.class) public void testInvoke2() throws Throwable { - var mh = MethodHandles.lookup().findVirtual(MemoryAddress.class, "asSegment", - MethodType.methodType(MemorySegment.class, long.class, ResourceScope.class)); + var mh = MethodHandles.lookup().findStatic(MemorySegment.class, "ofAddress", + MethodType.methodType(MemorySegment.class, MemoryAddress.class, long.class, ResourceScope.class)); var seg = (MemorySegment)mh.invokeExact(MemoryAddress.NULL, 4000L, ResourceScope.globalScope()); } @Test(expectedExceptions = IllegalCallerException.class) public void testDirectAccess2() throws Throwable { - MemoryAddress.NULL.asSegment(4000L, ResourceScope.globalScope()); + MemorySegment.ofAddress(MemoryAddress.NULL, 4000, ResourceScope.globalScope()); } } diff --git a/test/jdk/java/foreign/TestScopedOperations.java b/test/jdk/java/foreign/TestScopedOperations.java index 9254a9e5b3a79698aab7852fea7cca24f8bcf476..7384693481c20c246508f3b037c08ad3199b9149 100644 --- a/test/jdk/java/foreign/TestScopedOperations.java +++ b/test/jdk/java/foreign/TestScopedOperations.java @@ -27,13 +27,14 @@ * @run testng/othervm --enable-native-access=ALL-UNNAMED TestScopedOperations */ -import jdk.incubator.foreign.CLinker; import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemoryLayout; -import jdk.incubator.foreign.MemoryLayouts; import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.NativeSymbol; import jdk.incubator.foreign.ResourceScope; import jdk.incubator.foreign.SegmentAllocator; +import jdk.incubator.foreign.VaList; +import jdk.incubator.foreign.ValueLayout; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -47,6 +48,9 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; import java.util.function.Function; +import static jdk.incubator.foreign.ValueLayout.JAVA_BYTE; +import static jdk.incubator.foreign.ValueLayout.JAVA_INT; +import static jdk.incubator.foreign.ValueLayout.JAVA_LONG; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; @@ -67,11 +71,12 @@ public class TestScopedOperations { } @Test(dataProvider = "scopedOperations") - public void testOpAfterClose(String name, ScopedOperation scopedOperation) { + public <Z> void testOpAfterClose(String name, ScopedOperation<Z> scopedOperation) { ResourceScope scope = ResourceScope.newConfinedScope(); + Z obj = scopedOperation.apply(scope); scope.close(); try { - scopedOperation.accept(scope); + scopedOperation.accept(obj); fail(); } catch (IllegalStateException ex) { assertTrue(ex.getMessage().contains("closed")); @@ -79,12 +84,13 @@ public class TestScopedOperations { } @Test(dataProvider = "scopedOperations") - public void testOpOutsideConfinement(String name, ScopedOperation scopedOperation) { + public <Z> void testOpOutsideConfinement(String name, ScopedOperation<Z> scopedOperation) { try (ResourceScope scope = ResourceScope.newConfinedScope()) { + Z obj = scopedOperation.apply(scope); AtomicReference<Throwable> failed = new AtomicReference<>(); Thread t = new Thread(() -> { try { - scopedOperation.accept(scope); + scopedOperation.accept(obj); } catch (Throwable ex) { failed.set(ex); } @@ -106,9 +112,10 @@ public class TestScopedOperations { ScopedOperation.ofScope(scope -> scope.addCloseAction(() -> { }), "ResourceScope::addOnClose"); ScopedOperation.ofScope(scope -> { - ResourceScope.Handle handle = scope.acquire(); - scope.release(handle); - }, "ResourceScope::lock"); + ResourceScope scope2 = ResourceScope.newConfinedScope(); + scope2.keepAlive(scope); + scope2.close(); + }, "ResourceScope::keepAlive"); ScopedOperation.ofScope(scope -> MemorySegment.allocateNative(100, scope), "MemorySegment::allocateNative"); ScopedOperation.ofScope(scope -> { try { @@ -117,54 +124,46 @@ public class TestScopedOperations { fail(); } }, "MemorySegment::mapFromFile"); - ScopedOperation.ofScope(scope -> CLinker.VaList.make(b -> {}, scope), "VaList::make"); - ScopedOperation.ofScope(scope -> CLinker.VaList.ofAddress(MemoryAddress.ofLong(42), scope), "VaList::make"); - ScopedOperation.ofScope(scope -> CLinker.toCString("Hello", scope), "CLinker::toCString"); - ScopedOperation.ofScope(SegmentAllocator::arenaAllocator, "SegmentAllocator::arenaAllocator"); + ScopedOperation.ofScope(scope -> VaList.make(b -> b.addVarg(JAVA_INT, 42), scope), "VaList::make"); + ScopedOperation.ofScope(scope -> VaList.ofAddress(MemoryAddress.ofLong(42), scope), "VaList::make"); + ScopedOperation.ofScope(SegmentAllocator::newNativeArena, "SegmentAllocator::arenaAllocator"); // segment operations - ScopedOperation.ofSegment(MemorySegment::toByteArray, "MemorySegment::toByteArray"); - ScopedOperation.ofSegment(MemorySegment::toCharArray, "MemorySegment::toCharArray"); - ScopedOperation.ofSegment(MemorySegment::toShortArray, "MemorySegment::toShortArray"); - ScopedOperation.ofSegment(MemorySegment::toIntArray, "MemorySegment::toIntArray"); - ScopedOperation.ofSegment(MemorySegment::toFloatArray, "MemorySegment::toFloatArray"); - ScopedOperation.ofSegment(MemorySegment::toLongArray, "MemorySegment::toLongArray"); - ScopedOperation.ofSegment(MemorySegment::toDoubleArray, "MemorySegment::toDoubleArray"); + ScopedOperation.ofSegment(s -> s.toArray(JAVA_BYTE), "MemorySegment::toArray(BYTE)"); ScopedOperation.ofSegment(MemorySegment::address, "MemorySegment::address"); - ScopedOperation.ofSegment(s -> MemoryLayout.sequenceLayout(s.byteSize(), MemoryLayouts.JAVA_BYTE), "MemorySegment::spliterator"); ScopedOperation.ofSegment(s -> s.copyFrom(s), "MemorySegment::copyFrom"); ScopedOperation.ofSegment(s -> s.mismatch(s), "MemorySegment::mismatch"); ScopedOperation.ofSegment(s -> s.fill((byte) 0), "MemorySegment::fill"); - // address operations - ScopedOperation.ofAddress(a -> a.toRawLongValue(), "MemoryAddress::toRawLongValue"); - ScopedOperation.ofAddress(a -> a.asSegment(100, ResourceScope.globalScope()), "MemoryAddress::asSegment"); // valist operations - ScopedOperation.ofVaList(CLinker.VaList::address, "VaList::address"); - ScopedOperation.ofVaList(CLinker.VaList::copy, "VaList::copy"); - ScopedOperation.ofVaList(list -> list.vargAsAddress(MemoryLayouts.ADDRESS), "VaList::vargAsAddress"); - ScopedOperation.ofVaList(list -> list.vargAsInt(MemoryLayouts.JAVA_INT), "VaList::vargAsInt"); - ScopedOperation.ofVaList(list -> list.vargAsLong(MemoryLayouts.JAVA_LONG), "VaList::vargAsLong"); - ScopedOperation.ofVaList(list -> list.vargAsDouble(MemoryLayouts.JAVA_DOUBLE), "VaList::vargAsDouble"); - ScopedOperation.ofVaList(CLinker.VaList::skip, "VaList::skip"); - ScopedOperation.ofVaList(list -> list.vargAsSegment(MemoryLayout.structLayout(MemoryLayouts.JAVA_INT), ResourceScope.newImplicitScope()), "VaList::vargAsSegment/1"); + ScopedOperation.ofVaList(VaList::address, "VaList::address"); + ScopedOperation.ofVaList(VaList::copy, "VaList::copy"); + ScopedOperation.ofVaList(list -> list.nextVarg(ValueLayout.ADDRESS), "VaList::nextVarg/address"); + ScopedOperation.ofVaList(list -> list.nextVarg(ValueLayout.JAVA_INT), "VaList::nextVarg/int"); + ScopedOperation.ofVaList(list -> list.nextVarg(ValueLayout.JAVA_LONG), "VaList::nextVarg/long"); + ScopedOperation.ofVaList(list -> list.nextVarg(ValueLayout.JAVA_DOUBLE), "VaList::nextVarg/double"); + ScopedOperation.ofVaList(VaList::skip, "VaList::skip"); + ScopedOperation.ofVaList(list -> list.nextVarg(MemoryLayout.structLayout(ValueLayout.JAVA_INT), + SegmentAllocator.prefixAllocator(MemorySegment.ofArray(new byte[4]))), "VaList::nextVargs/segment"); // allocator operations ScopedOperation.ofAllocator(a -> a.allocate(1), "NativeAllocator::allocate/size"); ScopedOperation.ofAllocator(a -> a.allocate(1, 1), "NativeAllocator::allocate/size/align"); - ScopedOperation.ofAllocator(a -> a.allocate(MemoryLayouts.JAVA_BYTE), "NativeAllocator::allocate/layout"); - ScopedOperation.ofAllocator(a -> a.allocate(MemoryLayouts.JAVA_BYTE, (byte) 0), "NativeAllocator::allocate/byte"); - ScopedOperation.ofAllocator(a -> a.allocate(MemoryLayouts.JAVA_CHAR, (char) 0), "NativeAllocator::allocate/char"); - ScopedOperation.ofAllocator(a -> a.allocate(MemoryLayouts.JAVA_SHORT, (short) 0), "NativeAllocator::allocate/short"); - ScopedOperation.ofAllocator(a -> a.allocate(MemoryLayouts.JAVA_INT, 0), "NativeAllocator::allocate/int"); - ScopedOperation.ofAllocator(a -> a.allocate(MemoryLayouts.JAVA_FLOAT, 0f), "NativeAllocator::allocate/float"); - ScopedOperation.ofAllocator(a -> a.allocate(MemoryLayouts.JAVA_LONG, 0L), "NativeAllocator::allocate/long"); - ScopedOperation.ofAllocator(a -> a.allocate(MemoryLayouts.JAVA_DOUBLE, 0d), "NativeAllocator::allocate/double"); - ScopedOperation.ofAllocator(a -> a.allocateArray(MemoryLayouts.JAVA_BYTE, 1L), "NativeAllocator::allocateArray/size"); - ScopedOperation.ofAllocator(a -> a.allocateArray(MemoryLayouts.JAVA_BYTE, new byte[]{0}), "NativeAllocator::allocateArray/byte"); - ScopedOperation.ofAllocator(a -> a.allocateArray(MemoryLayouts.JAVA_CHAR, new char[]{0}), "NativeAllocator::allocateArray/char"); - ScopedOperation.ofAllocator(a -> a.allocateArray(MemoryLayouts.JAVA_SHORT, new short[]{0}), "NativeAllocator::allocateArray/short"); - ScopedOperation.ofAllocator(a -> a.allocateArray(MemoryLayouts.JAVA_INT, new int[]{0}), "NativeAllocator::allocateArray/int"); - ScopedOperation.ofAllocator(a -> a.allocateArray(MemoryLayouts.JAVA_FLOAT, new float[]{0}), "NativeAllocator::allocateArray/float"); - ScopedOperation.ofAllocator(a -> a.allocateArray(MemoryLayouts.JAVA_LONG, new long[]{0}), "NativeAllocator::allocateArray/long"); - ScopedOperation.ofAllocator(a -> a.allocateArray(MemoryLayouts.JAVA_DOUBLE, new double[]{0}), "NativeAllocator::allocateArray/double"); + ScopedOperation.ofAllocator(a -> a.allocate(JAVA_BYTE), "NativeAllocator::allocate/layout"); + ScopedOperation.ofAllocator(a -> a.allocate(JAVA_BYTE, (byte) 0), "NativeAllocator::allocate/byte"); + ScopedOperation.ofAllocator(a -> a.allocate(ValueLayout.JAVA_CHAR, (char) 0), "NativeAllocator::allocate/char"); + ScopedOperation.ofAllocator(a -> a.allocate(ValueLayout.JAVA_SHORT, (short) 0), "NativeAllocator::allocate/short"); + ScopedOperation.ofAllocator(a -> a.allocate(ValueLayout.JAVA_INT, 0), "NativeAllocator::allocate/int"); + ScopedOperation.ofAllocator(a -> a.allocate(ValueLayout.JAVA_FLOAT, 0f), "NativeAllocator::allocate/float"); + ScopedOperation.ofAllocator(a -> a.allocate(ValueLayout.JAVA_LONG, 0L), "NativeAllocator::allocate/long"); + ScopedOperation.ofAllocator(a -> a.allocate(ValueLayout.JAVA_DOUBLE, 0d), "NativeAllocator::allocate/double"); + ScopedOperation.ofAllocator(a -> a.allocateArray(JAVA_BYTE, 1L), "NativeAllocator::allocateArray/size"); + ScopedOperation.ofAllocator(a -> a.allocateArray(JAVA_BYTE, new byte[]{0}), "NativeAllocator::allocateArray/byte"); + ScopedOperation.ofAllocator(a -> a.allocateArray(ValueLayout.JAVA_CHAR, new char[]{0}), "NativeAllocator::allocateArray/char"); + ScopedOperation.ofAllocator(a -> a.allocateArray(ValueLayout.JAVA_SHORT, new short[]{0}), "NativeAllocator::allocateArray/short"); + ScopedOperation.ofAllocator(a -> a.allocateArray(ValueLayout.JAVA_INT, new int[]{0}), "NativeAllocator::allocateArray/int"); + ScopedOperation.ofAllocator(a -> a.allocateArray(ValueLayout.JAVA_FLOAT, new float[]{0}), "NativeAllocator::allocateArray/float"); + ScopedOperation.ofAllocator(a -> a.allocateArray(ValueLayout.JAVA_LONG, new long[]{0}), "NativeAllocator::allocateArray/long"); + ScopedOperation.ofAllocator(a -> a.allocateArray(ValueLayout.JAVA_DOUBLE, new double[]{0}), "NativeAllocator::allocateArray/double"); + // native symbol + ScopedOperation.of(scope -> NativeSymbol.ofAddress("", MemoryAddress.NULL, scope), NativeSymbol::address, "NativeSymbol::address"); }; @DataProvider(name = "scopedOperations") @@ -172,56 +171,56 @@ public class TestScopedOperations { return scopedOperations.stream().map(op -> new Object[] { op.name, op }).toArray(Object[][]::new); } - static class ScopedOperation implements Consumer<ResourceScope> { + static class ScopedOperation<X> implements Consumer<X>, Function<ResourceScope, X> { - final Consumer<ResourceScope> scopeConsumer; + final Function<ResourceScope, X> factory; + final Consumer<X> operation; final String name; - private ScopedOperation(Consumer<ResourceScope> scopeConsumer, String name) { - this.scopeConsumer = scopeConsumer; + private ScopedOperation(Function<ResourceScope, X> factory, Consumer<X> operation, String name) { + this.factory = factory; + this.operation = operation; this.name = name; } @Override - public void accept(ResourceScope scope) { - scopeConsumer.accept(scope); + public void accept(X obj) { + operation.accept(obj); } - static void ofScope(Consumer<ResourceScope> scopeConsumer, String name) { - scopedOperations.add(new ScopedOperation(scopeConsumer::accept, name)); + @Override + public X apply(ResourceScope scope) { + return factory.apply(scope); } - static void ofVaList(Consumer<CLinker.VaList> vaListConsumer, String name) { - scopedOperations.add(new ScopedOperation(scope -> { - CLinker.VaList vaList = CLinker.VaList.make((builder) -> {}, scope); - vaListConsumer.accept(vaList); - }, name)); + static <Z> void of(Function<ResourceScope, Z> factory, Consumer<Z> consumer, String name) { + scopedOperations.add(new ScopedOperation<>(factory, consumer, name)); } - static void ofSegment(Consumer<MemorySegment> segmentConsumer, String name) { - for (SegmentFactory segmentFactory : SegmentFactory.values()) { - scopedOperations.add(new ScopedOperation(scope -> { - MemorySegment segment = segmentFactory.segmentFactory.apply(scope); - segmentConsumer.accept(segment); - }, segmentFactory.name() + "/" + name)); - } + static void ofScope(Consumer<ResourceScope> scopeConsumer, String name) { + scopedOperations.add(new ScopedOperation<>(Function.identity(), scopeConsumer, name)); + } + + static void ofVaList(Consumer<VaList> vaListConsumer, String name) { + scopedOperations.add(new ScopedOperation<>(scope -> VaList.make(builder -> builder.addVarg(JAVA_LONG, 42), scope), + vaListConsumer, name)); } - static void ofAddress(Consumer<MemoryAddress> addressConsumer, String name) { + static void ofSegment(Consumer<MemorySegment> segmentConsumer, String name) { for (SegmentFactory segmentFactory : SegmentFactory.values()) { - scopedOperations.add(new ScopedOperation(scope -> { - MemoryAddress segment = segmentFactory.segmentFactory.apply(scope).address(); - addressConsumer.accept(segment); - }, segmentFactory.name() + "/" + name)); + scopedOperations.add(new ScopedOperation<>( + segmentFactory.segmentFactory, + segmentConsumer, + segmentFactory.name() + "/" + name)); } } static void ofAllocator(Consumer<SegmentAllocator> allocatorConsumer, String name) { for (AllocatorFactory allocatorFactory : AllocatorFactory.values()) { - scopedOperations.add(new ScopedOperation(scope -> { - SegmentAllocator allocator = allocatorFactory.allocatorFactory.apply(scope); - allocatorConsumer.accept(allocator); - }, allocatorFactory.name() + "/" + name)); + scopedOperations.add(new ScopedOperation<>( + allocatorFactory.allocatorFactory, + allocatorConsumer, + allocatorFactory.name() + "/" + name)); } } @@ -235,7 +234,7 @@ public class TestScopedOperations { throw new AssertionError(ex); } }), - UNSAFE(scope -> MemoryAddress.NULL.asSegment(10, scope)); + UNSAFE(scope -> MemorySegment.ofAddress(MemoryAddress.NULL, 10, scope)); static { try { @@ -255,13 +254,8 @@ public class TestScopedOperations { } enum AllocatorFactory { - ARENA_BOUNDED(scope -> SegmentAllocator.arenaAllocator(1000, scope)), - ARENA_UNBOUNDED(SegmentAllocator::arenaAllocator), - FROM_SEGMENT(scope -> { - MemorySegment segment = MemorySegment.allocateNative(10, scope); - return SegmentAllocator.ofSegment(segment); - }), - FROM_SCOPE(SegmentAllocator::ofScope); + ARENA_BOUNDED(scope -> SegmentAllocator.newNativeArena(1000, scope)), + ARENA_UNBOUNDED(SegmentAllocator::newNativeArena); final Function<ResourceScope, SegmentAllocator> allocatorFactory; diff --git a/test/jdk/java/foreign/TestSegmentAllocators.java b/test/jdk/java/foreign/TestSegmentAllocators.java index 3d2538ad897a21e42fc2a2b21da8f9a4bbe44285..aa269191a23312f9714ef089d1c4fe60576de63e 100644 --- a/test/jdk/java/foreign/TestSegmentAllocators.java +++ b/test/jdk/java/foreign/TestSegmentAllocators.java @@ -34,6 +34,7 @@ import org.testng.annotations.*; import java.lang.invoke.VarHandle; import java.nio.ByteBuffer; import java.nio.ByteOrder; +import java.nio.CharBuffer; import java.nio.DoubleBuffer; import java.nio.FloatBuffer; import java.nio.IntBuffer; @@ -51,17 +52,19 @@ import static org.testng.Assert.*; public class TestSegmentAllocators { final static int ELEMS = 128; - final static Class<?> ADDRESS_CARRIER = MemoryLayouts.ADDRESS.bitSize() == 64 ? long.class : int.class; + final static Class<?> ADDRESS_CARRIER = ValueLayout.ADDRESS.bitSize() == 64 ? long.class : int.class; @Test(dataProvider = "nativeScopes") - public <Z> void testAllocation(Z value, AllocationFactory allocationFactory, ValueLayout layout, AllocationFunction<Z> allocationFunction, Function<MemoryLayout, VarHandle> handleFactory) { - ValueLayout[] layouts = { + @SuppressWarnings("unchecked") + public <Z, L extends ValueLayout> void testAllocation(Z value, AllocationFactory allocationFactory, L layout, AllocationFunction<Z, L> allocationFunction, Function<MemoryLayout, VarHandle> handleFactory) { + layout = (L)layout.withBitAlignment(layout.bitSize()); + L[] layouts = (L[])new ValueLayout[] { layout, layout.withBitAlignment(layout.bitAlignment() * 2), layout.withBitAlignment(layout.bitAlignment() * 4), layout.withBitAlignment(layout.bitAlignment() * 8) }; - for (ValueLayout alignedLayout : layouts) { + for (L alignedLayout : layouts) { List<MemorySegment> addressList = new ArrayList<>(); int elems = ELEMS / ((int)alignedLayout.byteAlignment() / (int)layout.byteAlignment()); ResourceScope[] scopes = { @@ -80,16 +83,18 @@ public class TestSegmentAllocators { } boolean isBound = allocationFactory.isBound(); try { - allocationFunction.allocate(allocator, alignedLayout, value); //too much, should fail if bound + allocationFunction.allocate(allocator, alignedLayout, value); assertFalse(isBound); } catch (OutOfMemoryError ex) { //failure is expected if bound assertTrue(isBound); } } - // addresses should be invalid now - for (MemorySegment address : addressList) { - assertFalse(address.scope().isAlive()); + if (allocationFactory != AllocationFactory.IMPLICIT_ALLOCATOR) { + // addresses should be invalid now + for (MemorySegment address : addressList) { + assertFalse(address.scope().isAlive()); + } } } } @@ -100,7 +105,7 @@ public class TestSegmentAllocators { @Test public void testBigAllocationInUnboundedScope() { try (ResourceScope scope = ResourceScope.newConfinedScope()) { - SegmentAllocator allocator = SegmentAllocator.arenaAllocator(scope); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(scope); for (int i = 8 ; i < SIZE_256M ; i *= 8) { MemorySegment address = allocator.allocate(i, i); //check size @@ -111,24 +116,30 @@ public class TestSegmentAllocators { } } - @Test(expectedExceptions = OutOfMemoryError.class) + @Test public void testTooBigForBoundedArena() { try (ResourceScope scope = ResourceScope.newConfinedScope()) { - SegmentAllocator allocator = SegmentAllocator.arenaAllocator(10, scope); - allocator.allocate(12); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(10, scope); + assertThrows(OutOfMemoryError.class, () -> allocator.allocate(12)); + allocator.allocate(5); // ok } } @Test public void testBiggerThanBlockForBoundedArena() { try (ResourceScope scope = ResourceScope.newConfinedScope()) { - SegmentAllocator allocator = SegmentAllocator.arenaAllocator(4 * 1024 * 2, scope); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(4 * 1024 * 2, scope); allocator.allocate(4 * 1024 + 1); // should be ok } } + @Test(expectedExceptions = IllegalArgumentException.class) + public void testBadUnboundedArenaSize() { + SegmentAllocator.newNativeArena( -1, ResourceScope.globalScope()); + } + @Test(dataProvider = "arrayScopes") - public <Z> void testArray(AllocationFactory allocationFactory, ValueLayout layout, AllocationFunction<Object> allocationFunction, ToArrayHelper<Z> arrayHelper) { + public <Z> void testArray(AllocationFactory allocationFactory, ValueLayout layout, AllocationFunction<Object, ValueLayout> allocationFunction, ToArrayHelper<Z> arrayHelper) { Z arr = arrayHelper.array(); ResourceScope[] scopes = { ResourceScope.newConfinedScope(), @@ -146,221 +157,142 @@ public class TestSegmentAllocators { @DataProvider(name = "nativeScopes") static Object[][] nativeScopes() { - return new Object[][] { - { (byte)42, AllocationFactory.BOUNDED, MemoryLayouts.BITS_8_BE, - (AllocationFunction<Byte>) SegmentAllocator::allocate, - (Function<MemoryLayout, VarHandle>)l -> l.varHandle(byte.class) }, - { (short)42, AllocationFactory.BOUNDED, MemoryLayouts.BITS_16_BE, - (AllocationFunction<Short>) SegmentAllocator::allocate, - (Function<MemoryLayout, VarHandle>)l -> l.varHandle(short.class) }, - { (char)42, AllocationFactory.BOUNDED, MemoryLayouts.BITS_16_BE, - (AllocationFunction<Character>) SegmentAllocator::allocate, - (Function<MemoryLayout, VarHandle>)l -> l.varHandle(char.class) }, - { 42, AllocationFactory.BOUNDED, - MemoryLayouts.BITS_32_BE, - (AllocationFunction<Integer>) SegmentAllocator::allocate, - (Function<MemoryLayout, VarHandle>)l -> l.varHandle(int.class) }, - { 42f, AllocationFactory.BOUNDED, MemoryLayouts.BITS_32_BE, - (AllocationFunction<Float>) SegmentAllocator::allocate, - (Function<MemoryLayout, VarHandle>)l -> l.varHandle(float.class) }, - { 42L, AllocationFactory.BOUNDED, MemoryLayouts.BITS_64_BE, - (AllocationFunction<Long>) SegmentAllocator::allocate, - (Function<MemoryLayout, VarHandle>)l -> l.varHandle(long.class) }, - { 42d, AllocationFactory.BOUNDED, MemoryLayouts.BITS_64_BE, - (AllocationFunction<Double>) SegmentAllocator::allocate, - (Function<MemoryLayout, VarHandle>)l -> l.varHandle(double.class) }, - { MemoryAddress.ofLong(42), AllocationFactory.BOUNDED, MemoryLayouts.ADDRESS.withOrder(ByteOrder.BIG_ENDIAN), - (AllocationFunction<MemoryAddress>) SegmentAllocator::allocate, - (Function<MemoryLayout, VarHandle>)l -> MemoryHandles.asAddressVarHandle(l.varHandle(ADDRESS_CARRIER)) }, - - { (byte)42, AllocationFactory.BOUNDED, MemoryLayouts.BITS_8_LE, - (AllocationFunction<Byte>) SegmentAllocator::allocate, - (Function<MemoryLayout, VarHandle>)l -> l.varHandle(byte.class) }, - { (short)42, AllocationFactory.BOUNDED, MemoryLayouts.BITS_16_LE, - (AllocationFunction<Short>) SegmentAllocator::allocate, - (Function<MemoryLayout, VarHandle>)l -> l.varHandle(short.class) }, - { (char)42, AllocationFactory.BOUNDED, MemoryLayouts.BITS_16_LE, - (AllocationFunction<Character>) SegmentAllocator::allocate, - (Function<MemoryLayout, VarHandle>)l -> l.varHandle(char.class) }, - { 42, AllocationFactory.BOUNDED, - MemoryLayouts.BITS_32_LE, - (AllocationFunction<Integer>) SegmentAllocator::allocate, - (Function<MemoryLayout, VarHandle>)l -> l.varHandle(int.class) }, - { 42f, AllocationFactory.BOUNDED, MemoryLayouts.BITS_32_LE, - (AllocationFunction<Float>) SegmentAllocator::allocate, - (Function<MemoryLayout, VarHandle>)l -> l.varHandle(float.class) }, - { 42L, AllocationFactory.BOUNDED, MemoryLayouts.BITS_64_LE, - (AllocationFunction<Long>) SegmentAllocator::allocate, - (Function<MemoryLayout, VarHandle>)l -> l.varHandle(long.class) }, - { 42d, AllocationFactory.BOUNDED, MemoryLayouts.BITS_64_LE, - (AllocationFunction<Double>) SegmentAllocator::allocate, - (Function<MemoryLayout, VarHandle>)l -> l.varHandle(double.class) }, - { MemoryAddress.ofLong(42), AllocationFactory.BOUNDED, MemoryLayouts.ADDRESS.withOrder(ByteOrder.LITTLE_ENDIAN), - (AllocationFunction<MemoryAddress>) SegmentAllocator::allocate, - (Function<MemoryLayout, VarHandle>)l -> MemoryHandles.asAddressVarHandle(l.varHandle(ADDRESS_CARRIER)) }, - - { (byte)42, AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_8_BE, - (AllocationFunction<Byte>) SegmentAllocator::allocate, - (Function<MemoryLayout, VarHandle>)l -> l.varHandle(byte.class) }, - { (short)42, AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_16_BE, - (AllocationFunction<Short>) SegmentAllocator::allocate, - (Function<MemoryLayout, VarHandle>)l -> l.varHandle(short.class) }, - { (char)42, AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_16_BE, - (AllocationFunction<Character>) SegmentAllocator::allocate, - (Function<MemoryLayout, VarHandle>)l -> l.varHandle(char.class) }, - { 42, AllocationFactory.UNBOUNDED, - MemoryLayouts.BITS_32_BE, - (AllocationFunction<Integer>) SegmentAllocator::allocate, - (Function<MemoryLayout, VarHandle>)l -> l.varHandle(int.class) }, - { 42f, AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_32_BE, - (AllocationFunction<Float>) SegmentAllocator::allocate, - (Function<MemoryLayout, VarHandle>)l -> l.varHandle(float.class) }, - { 42L, AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_64_BE, - (AllocationFunction<Long>) SegmentAllocator::allocate, - (Function<MemoryLayout, VarHandle>)l -> l.varHandle(long.class) }, - { 42d, AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_64_BE, - (AllocationFunction<Double>) SegmentAllocator::allocate, - (Function<MemoryLayout, VarHandle>)l -> l.varHandle(double.class) }, - { MemoryAddress.ofLong(42), AllocationFactory.UNBOUNDED, MemoryLayouts.ADDRESS.withOrder(ByteOrder.BIG_ENDIAN), - (AllocationFunction<MemoryAddress>) SegmentAllocator::allocate, - (Function<MemoryLayout, VarHandle>)l -> MemoryHandles.asAddressVarHandle(l.varHandle(ADDRESS_CARRIER)) }, - - { (byte)42, AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_8_LE, - (AllocationFunction<Byte>) SegmentAllocator::allocate, - (Function<MemoryLayout, VarHandle>)l -> l.varHandle(byte.class) }, - { (short)42, AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_16_LE, - (AllocationFunction<Short>) SegmentAllocator::allocate, - (Function<MemoryLayout, VarHandle>)l -> l.varHandle(short.class) }, - { (char)42, AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_16_LE, - (AllocationFunction<Character>) SegmentAllocator::allocate, - (Function<MemoryLayout, VarHandle>)l -> l.varHandle(char.class) }, - { 42, AllocationFactory.UNBOUNDED, - MemoryLayouts.BITS_32_LE, - (AllocationFunction<Integer>) SegmentAllocator::allocate, - (Function<MemoryLayout, VarHandle>)l -> l.varHandle(int.class) }, - { 42f, AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_32_LE, - (AllocationFunction<Float>) SegmentAllocator::allocate, - (Function<MemoryLayout, VarHandle>)l -> l.varHandle(float.class) }, - { 42L, AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_64_LE, - (AllocationFunction<Long>) SegmentAllocator::allocate, - (Function<MemoryLayout, VarHandle>)l -> l.varHandle(long.class) }, - { 42d, AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_64_LE, - (AllocationFunction<Double>) SegmentAllocator::allocate, - (Function<MemoryLayout, VarHandle>)l -> l.varHandle(double.class) }, - { MemoryAddress.ofLong(42), AllocationFactory.UNBOUNDED, MemoryLayouts.ADDRESS.withOrder(ByteOrder.LITTLE_ENDIAN), - (AllocationFunction<MemoryAddress>) SegmentAllocator::allocate, - (Function<MemoryLayout, VarHandle>)l -> MemoryHandles.asAddressVarHandle(l.varHandle(ADDRESS_CARRIER)) }, - }; + List<Object[]> nativeScopes = new ArrayList<>(); + for (AllocationFactory factory : AllocationFactory.values()) { + nativeScopes.add(new Object[] { (byte)42, factory, ValueLayout.JAVA_BYTE, + (AllocationFunction.OfByte) SegmentAllocator::allocate, + (Function<MemoryLayout, VarHandle>)l -> l.varHandle() }); + nativeScopes.add(new Object[] { (short)42, factory, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.BIG_ENDIAN), + (AllocationFunction.OfShort) SegmentAllocator::allocate, + (Function<MemoryLayout, VarHandle>)l -> l.varHandle() }); + nativeScopes.add(new Object[] { (char)42, factory, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.BIG_ENDIAN), + (AllocationFunction.OfChar) SegmentAllocator::allocate, + (Function<MemoryLayout, VarHandle>)l -> l.varHandle() }); + nativeScopes.add(new Object[] { 42, factory, + ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN), + (AllocationFunction.OfInt) SegmentAllocator::allocate, + (Function<MemoryLayout, VarHandle>)l -> l.varHandle() }); + nativeScopes.add(new Object[] { 42f, factory, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.BIG_ENDIAN), + (AllocationFunction.OfFloat) SegmentAllocator::allocate, + (Function<MemoryLayout, VarHandle>)l -> l.varHandle() }); + nativeScopes.add(new Object[] { 42L, factory, ValueLayout.JAVA_LONG.withOrder(ByteOrder.BIG_ENDIAN), + (AllocationFunction.OfLong) SegmentAllocator::allocate, + (Function<MemoryLayout, VarHandle>)l -> l.varHandle() }); + nativeScopes.add(new Object[] { 42d, factory, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.BIG_ENDIAN), + (AllocationFunction.OfDouble) SegmentAllocator::allocate, + (Function<MemoryLayout, VarHandle>)l -> l.varHandle() }); + nativeScopes.add(new Object[] { MemoryAddress.ofLong(42), factory, ValueLayout.ADDRESS.withOrder(ByteOrder.BIG_ENDIAN), + (AllocationFunction.OfAddress) SegmentAllocator::allocate, + (Function<MemoryLayout, VarHandle>)l -> l.varHandle() }); + + nativeScopes.add(new Object[] { (short)42, factory, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.LITTLE_ENDIAN), + (AllocationFunction.OfShort) SegmentAllocator::allocate, + (Function<MemoryLayout, VarHandle>)l -> l.varHandle() }); + nativeScopes.add(new Object[] { (char)42, factory, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.LITTLE_ENDIAN), + (AllocationFunction.OfChar) SegmentAllocator::allocate, + (Function<MemoryLayout, VarHandle>)l -> l.varHandle() }); + nativeScopes.add(new Object[] { 42, factory, + ValueLayout.JAVA_INT.withOrder(ByteOrder.LITTLE_ENDIAN), + (AllocationFunction.OfInt) SegmentAllocator::allocate, + (Function<MemoryLayout, VarHandle>)l -> l.varHandle() }); + nativeScopes.add(new Object[] { 42f, factory, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.LITTLE_ENDIAN), + (AllocationFunction.OfFloat) SegmentAllocator::allocate, + (Function<MemoryLayout, VarHandle>)l -> l.varHandle() }); + nativeScopes.add(new Object[] { 42L, factory, ValueLayout.JAVA_LONG.withOrder(ByteOrder.LITTLE_ENDIAN), + (AllocationFunction.OfLong) SegmentAllocator::allocate, + (Function<MemoryLayout, VarHandle>)l -> l.varHandle() }); + nativeScopes.add(new Object[] { 42d, factory, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.LITTLE_ENDIAN), + (AllocationFunction.OfDouble) SegmentAllocator::allocate, + (Function<MemoryLayout, VarHandle>)l -> l.varHandle() }); + nativeScopes.add(new Object[] { MemoryAddress.ofLong(42), factory, ValueLayout.ADDRESS.withOrder(ByteOrder.BIG_ENDIAN), + (AllocationFunction.OfAddress) SegmentAllocator::allocate, + (Function<MemoryLayout, VarHandle>)l -> l.varHandle() }); + } + return nativeScopes.toArray(Object[][]::new); } @DataProvider(name = "arrayScopes") static Object[][] arrayScopes() { - return new Object[][] { - { AllocationFactory.BOUNDED, MemoryLayouts.BITS_8_LE, - (AllocationFunction<byte[]>) SegmentAllocator::allocateArray, - ToArrayHelper.toByteArray }, - { AllocationFactory.BOUNDED, MemoryLayouts.BITS_16_LE, - (AllocationFunction<short[]>) SegmentAllocator::allocateArray, - ToArrayHelper.toShortArray }, - { AllocationFactory.BOUNDED, - MemoryLayouts.BITS_32_LE, - (AllocationFunction<int[]>) SegmentAllocator::allocateArray, - ToArrayHelper.toIntArray }, - { AllocationFactory.BOUNDED, MemoryLayouts.BITS_32_LE, - (AllocationFunction<float[]>) SegmentAllocator::allocateArray, - ToArrayHelper.toFloatArray }, - { AllocationFactory.BOUNDED, MemoryLayouts.BITS_64_LE, - (AllocationFunction<long[]>) SegmentAllocator::allocateArray, - ToArrayHelper.toLongArray }, - { AllocationFactory.BOUNDED, MemoryLayouts.BITS_64_LE, - (AllocationFunction<double[]>) SegmentAllocator::allocateArray, - ToArrayHelper.toDoubleArray }, - { AllocationFactory.BOUNDED, MemoryLayouts.ADDRESS.withOrder(ByteOrder.LITTLE_ENDIAN), - (AllocationFunction<MemoryAddress[]>) SegmentAllocator::allocateArray, - ToArrayHelper.toAddressArray }, - - - { AllocationFactory.BOUNDED, MemoryLayouts.BITS_8_BE, - (AllocationFunction<byte[]>) SegmentAllocator::allocateArray, - ToArrayHelper.toByteArray }, - { AllocationFactory.BOUNDED, MemoryLayouts.BITS_16_BE, - (AllocationFunction<short[]>) SegmentAllocator::allocateArray, - ToArrayHelper.toShortArray }, - { AllocationFactory.BOUNDED, - MemoryLayouts.BITS_32_BE, - (AllocationFunction<int[]>) SegmentAllocator::allocateArray, - ToArrayHelper.toIntArray }, - { AllocationFactory.BOUNDED, MemoryLayouts.BITS_32_BE, - (AllocationFunction<float[]>) SegmentAllocator::allocateArray, - ToArrayHelper.toFloatArray }, - { AllocationFactory.BOUNDED, MemoryLayouts.BITS_64_BE, - (AllocationFunction<long[]>) SegmentAllocator::allocateArray, - ToArrayHelper.toLongArray }, - { AllocationFactory.BOUNDED, MemoryLayouts.BITS_64_BE, - (AllocationFunction<double[]>) SegmentAllocator::allocateArray, - ToArrayHelper.toDoubleArray }, - { AllocationFactory.BOUNDED, MemoryLayouts.ADDRESS.withOrder(ByteOrder.BIG_ENDIAN), - (AllocationFunction<MemoryAddress[]>) SegmentAllocator::allocateArray, - ToArrayHelper.toAddressArray }, - - { AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_8_LE, - (AllocationFunction<byte[]>) SegmentAllocator::allocateArray, - ToArrayHelper.toByteArray }, - { AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_16_LE, - (AllocationFunction<short[]>) SegmentAllocator::allocateArray, - ToArrayHelper.toShortArray }, - { AllocationFactory.UNBOUNDED, - MemoryLayouts.BITS_32_LE, - (AllocationFunction<int[]>) SegmentAllocator::allocateArray, - ToArrayHelper.toIntArray }, - { AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_32_LE, - (AllocationFunction<float[]>) SegmentAllocator::allocateArray, - ToArrayHelper.toFloatArray }, - { AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_64_LE, - (AllocationFunction<long[]>) SegmentAllocator::allocateArray, - ToArrayHelper.toLongArray }, - { AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_64_LE, - (AllocationFunction<double[]>) SegmentAllocator::allocateArray, - ToArrayHelper.toDoubleArray }, - { AllocationFactory.UNBOUNDED, MemoryLayouts.ADDRESS.withOrder(ByteOrder.LITTLE_ENDIAN), - (AllocationFunction<MemoryAddress[]>) SegmentAllocator::allocateArray, - ToArrayHelper.toAddressArray }, - - - { AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_8_BE, - (AllocationFunction<byte[]>) SegmentAllocator::allocateArray, - ToArrayHelper.toByteArray }, - { AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_16_BE, - (AllocationFunction<short[]>) SegmentAllocator::allocateArray, - ToArrayHelper.toShortArray }, - { AllocationFactory.UNBOUNDED, - MemoryLayouts.BITS_32_BE, - (AllocationFunction<int[]>) SegmentAllocator::allocateArray, - ToArrayHelper.toIntArray }, - { AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_32_BE, - (AllocationFunction<float[]>) SegmentAllocator::allocateArray, - ToArrayHelper.toFloatArray }, - { AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_64_BE, - (AllocationFunction<long[]>) SegmentAllocator::allocateArray, - ToArrayHelper.toLongArray }, - { AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_64_BE, - (AllocationFunction<double[]>) SegmentAllocator::allocateArray, - ToArrayHelper.toDoubleArray }, - { AllocationFactory.UNBOUNDED, MemoryLayouts.ADDRESS.withOrder(ByteOrder.BIG_ENDIAN), - (AllocationFunction<MemoryAddress[]>) SegmentAllocator::allocateArray, - ToArrayHelper.toAddressArray }, + List<Object[]> arrayScopes = new ArrayList<>(); + for (AllocationFactory factory : AllocationFactory.values()) { + arrayScopes.add(new Object[] { factory, ValueLayout.JAVA_BYTE, + (AllocationFunction.OfByteArray) SegmentAllocator::allocateArray, + ToArrayHelper.toByteArray }); + arrayScopes.add(new Object[] { factory, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.LITTLE_ENDIAN), + (AllocationFunction.OfCharArray) SegmentAllocator::allocateArray, + ToArrayHelper.toCharArray }); + arrayScopes.add(new Object[] { factory, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.LITTLE_ENDIAN), + (AllocationFunction.OfShortArray) SegmentAllocator::allocateArray, + ToArrayHelper.toShortArray }); + arrayScopes.add(new Object[] { factory, + ValueLayout.JAVA_INT.withOrder(ByteOrder.LITTLE_ENDIAN), + (AllocationFunction.OfIntArray) SegmentAllocator::allocateArray, + ToArrayHelper.toIntArray }); + arrayScopes.add(new Object[] { factory, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.LITTLE_ENDIAN), + (AllocationFunction.OfFloatArray) SegmentAllocator::allocateArray, + ToArrayHelper.toFloatArray }); + arrayScopes.add(new Object[] { factory, ValueLayout.JAVA_LONG.withOrder(ByteOrder.LITTLE_ENDIAN), + (AllocationFunction.OfLongArray) SegmentAllocator::allocateArray, + ToArrayHelper.toLongArray }); + arrayScopes.add(new Object[] { factory, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.LITTLE_ENDIAN), + (AllocationFunction.OfDoubleArray) SegmentAllocator::allocateArray, + ToArrayHelper.toDoubleArray }); + + arrayScopes.add(new Object[] { factory, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.BIG_ENDIAN), + (AllocationFunction.OfCharArray) SegmentAllocator::allocateArray, + ToArrayHelper.toCharArray }); + arrayScopes.add(new Object[] { factory, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.BIG_ENDIAN), + (AllocationFunction.OfShortArray) SegmentAllocator::allocateArray, + ToArrayHelper.toShortArray }); + arrayScopes.add(new Object[] { factory, + ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN), + (AllocationFunction.OfIntArray) SegmentAllocator::allocateArray, + ToArrayHelper.toIntArray }); + arrayScopes.add(new Object[] { factory, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.BIG_ENDIAN), + (AllocationFunction.OfFloatArray) SegmentAllocator::allocateArray, + ToArrayHelper.toFloatArray }); + arrayScopes.add(new Object[] { factory, ValueLayout.JAVA_LONG.withOrder(ByteOrder.BIG_ENDIAN), + (AllocationFunction.OfLongArray) SegmentAllocator::allocateArray, + ToArrayHelper.toLongArray }); + arrayScopes.add(new Object[] { factory, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.BIG_ENDIAN), + (AllocationFunction.OfDoubleArray) SegmentAllocator::allocateArray, + ToArrayHelper.toDoubleArray }); }; + return arrayScopes.toArray(Object[][]::new); } - interface AllocationFunction<X> { - MemorySegment allocate(SegmentAllocator allocator, ValueLayout layout, X value); + interface AllocationFunction<X, L extends ValueLayout> { + MemorySegment allocate(SegmentAllocator allocator, L layout, X value); + + interface OfByte extends AllocationFunction<Byte, ValueLayout.OfByte> { } + interface OfBoolean extends AllocationFunction<Boolean, ValueLayout.OfBoolean> { } + interface OfChar extends AllocationFunction<Character, ValueLayout.OfChar> { } + interface OfShort extends AllocationFunction<Short, ValueLayout.OfShort> { } + interface OfInt extends AllocationFunction<Integer, ValueLayout.OfInt> { } + interface OfFloat extends AllocationFunction<Float, ValueLayout.OfFloat> { } + interface OfLong extends AllocationFunction<Long, ValueLayout.OfLong> { } + interface OfDouble extends AllocationFunction<Double, ValueLayout.OfDouble> { } + interface OfAddress extends AllocationFunction<MemoryAddress, ValueLayout.OfAddress> { } + + interface OfByteArray extends AllocationFunction<byte[], ValueLayout.OfByte> { } + interface OfCharArray extends AllocationFunction<char[], ValueLayout.OfChar> { } + interface OfShortArray extends AllocationFunction<short[], ValueLayout.OfShort> { } + interface OfIntArray extends AllocationFunction<int[], ValueLayout.OfInt> { } + interface OfFloatArray extends AllocationFunction<float[], ValueLayout.OfFloat> { } + interface OfLongArray extends AllocationFunction<long[], ValueLayout.OfLong> { } + interface OfDoubleArray extends AllocationFunction<double[], ValueLayout.OfDouble> { } } - static class AllocationFactory { + enum AllocationFactory { + ARENA_BOUNDED(true, SegmentAllocator::newNativeArena), + ARENA_UNBOUNDED(false, (size, scope) -> SegmentAllocator.newNativeArena(scope)), + NATIVE_ALLOCATOR(false, (size, scope) -> SegmentAllocator.nativeAllocator(scope)), + IMPLICIT_ALLOCATOR(false, (size, scope) -> SegmentAllocator.implicitAllocator()); + private final boolean isBound; private final BiFunction<Long, ResourceScope, SegmentAllocator> factory; - private AllocationFactory(boolean isBound, BiFunction<Long, ResourceScope, SegmentAllocator> factory) { + AllocationFactory(boolean isBound, BiFunction<Long, ResourceScope, SegmentAllocator> factory) { this.isBound = isBound; this.factory = factory; } @@ -372,9 +304,6 @@ public class TestSegmentAllocators { public boolean isBound() { return isBound; } - - static AllocationFactory BOUNDED = new AllocationFactory(true, SegmentAllocator::arenaAllocator); - static AllocationFactory UNBOUNDED = new AllocationFactory(false, (size, scope) -> SegmentAllocator.arenaAllocator(scope)); } interface ToArrayHelper<T> { @@ -396,6 +325,21 @@ public class TestSegmentAllocators { } }; + ToArrayHelper<char[]> toCharArray = new ToArrayHelper<>() { + @Override + public char[] array() { + return new char[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + } + + @Override + public char[] toArray(MemorySegment segment, ValueLayout layout) { + CharBuffer buffer = segment.asByteBuffer().order(layout.order()).asCharBuffer(); + char[] found = new char[buffer.limit()]; + buffer.get(found); + return found; + } + }; + ToArrayHelper<short[]> toShortArray = new ToArrayHelper<>() { @Override public short[] array() { @@ -474,7 +418,7 @@ public class TestSegmentAllocators { ToArrayHelper<MemoryAddress[]> toAddressArray = new ToArrayHelper<>() { @Override public MemoryAddress[] array() { - return switch ((int)MemoryLayouts.ADDRESS.byteSize()) { + return switch ((int) ValueLayout.ADDRESS.byteSize()) { case 4 -> wrap(toIntArray.array()); case 8 -> wrap(toLongArray.array()); default -> throw new IllegalStateException("Cannot get here"); diff --git a/test/jdk/java/foreign/TestSegmentCopy.java b/test/jdk/java/foreign/TestSegmentCopy.java new file mode 100644 index 0000000000000000000000000000000000000000..de2dba0848341758a3969c19dca198cddc6ecbc3 --- /dev/null +++ b/test/jdk/java/foreign/TestSegmentCopy.java @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test + * @run testng TestSegmentCopy + */ + +import jdk.incubator.foreign.MemoryHandles; +import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.ResourceScope; +import jdk.incubator.foreign.ValueLayout; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.lang.invoke.VarHandle; +import java.nio.ByteOrder; +import java.util.ArrayList; +import java.util.List; +import java.util.function.IntFunction; + +import static org.testng.Assert.*; + +public class TestSegmentCopy { + + @Test(dataProvider = "slices") + public void testByteCopy(SegmentSlice s1, SegmentSlice s2) { + int size = Math.min(s1.byteSize(), s2.byteSize()); + //prepare source and target segments + for (int i = 0 ; i < size ; i++) { + Type.BYTE.set(s2, i, 0); + } + for (int i = 0 ; i < size ; i++) { + Type.BYTE.set(s1, i, i); + } + //perform copy + MemorySegment.copy(s1.segment, 0, s2.segment, 0, size); + //check that copy actually worked + for (int i = 0 ; i < size ; i++) { + Type.BYTE.check(s2, i, i); + } + } + + @Test(dataProvider = "slices") + public void testElementCopy(SegmentSlice s1, SegmentSlice s2) { + if (s1.type.carrier != s2.type.carrier) return; + int size = Math.min(s1.elementSize(), s2.elementSize()); + //prepare source and target segments + for (int i = 0 ; i < size ; i++) { + s2.set(i, 0); + } + for (int i = 0 ; i < size ; i++) { + s1.set(i, i); + } + //perform copy + MemorySegment.copy(s1.segment, s1.type.layout, 0, s2.segment, s2.type.layout, 0, size); + //check that copy actually worked + for (int i = 0; i < size; i++) { + s2.check(i, i); + } + } + + interface Getter<X> { + X get(MemorySegment segment, ValueLayout layout, long index); + } + + interface Setter<X> { + void set(MemorySegment segment, ValueLayout layout, long index, X val); + } + + enum Type { + // Byte + BYTE(byte.class, ValueLayout.JAVA_BYTE, i -> (byte)i), + //LE + SHORT_LE(short.class, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.LITTLE_ENDIAN), i -> (short)i), + CHAR_LE(char.class, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.LITTLE_ENDIAN), i -> (char)i), + INT_LE(int.class, ValueLayout.JAVA_INT.withOrder(ByteOrder.LITTLE_ENDIAN), i -> i), + FLOAT_LE(float.class, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.LITTLE_ENDIAN), i -> (float)i), + LONG_LE(long.class, ValueLayout.JAVA_LONG.withOrder(ByteOrder.LITTLE_ENDIAN), i -> (long)i), + DOUBLE_LE(double.class, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.LITTLE_ENDIAN), i -> (double)i), + //BE + SHORT_BE(short.class, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.BIG_ENDIAN), i -> (short)i), + CHAR_BE(char.class, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.BIG_ENDIAN), i -> (char)i), + INT_BE(int.class, ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN), i -> i), + FLOAT_BE(float.class, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.BIG_ENDIAN), i -> (float)i), + LONG_BE(long.class, ValueLayout.JAVA_LONG.withOrder(ByteOrder.BIG_ENDIAN), i -> (long)i), + DOUBLE_BE(double.class, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.BIG_ENDIAN), i -> (double)i); + + final ValueLayout layout; + final IntFunction<Object> valueConverter; + final Class<?> carrier; + + @SuppressWarnings("unchecked") + <Z> Type(Class<Z> carrier, ValueLayout layout, IntFunction<Z> valueConverter) { + this.carrier = carrier; + this.layout = layout; + this.valueConverter = (IntFunction<Object>)valueConverter; + } + + int size() { + return (int)layout.byteSize(); + } + + VarHandle handle() { + return MemoryHandles.varHandle(layout); + } + + void set(SegmentSlice slice, int index, int val) { + handle().set(slice.segment, index * size(), valueConverter.apply(val)); + } + + void check(SegmentSlice slice, int index, int val) { + assertEquals(handle().get(slice.segment, index * size()), valueConverter.apply(val)); + } + } + + static class SegmentSlice { + + enum Kind { + NATIVE(i -> MemorySegment.allocateNative(i, ResourceScope.newImplicitScope())), + ARRAY(i -> MemorySegment.ofArray(new byte[i])); + + final IntFunction<MemorySegment> segmentFactory; + + Kind(IntFunction<MemorySegment> segmentFactory) { + this.segmentFactory = segmentFactory; + } + + MemorySegment makeSegment(int elems) { + return segmentFactory.apply(elems); + } + } + + final Kind kind; + final Type type; + final int first; + final int last; + final MemorySegment segment; + + public SegmentSlice(Kind kind, Type type, int first, int last, MemorySegment segment) { + this.kind = kind; + this.type = type; + this.first = first; + this.last = last; + this.segment = segment; + } + + void set(int index, int val) { + type.set(this, index, val); + } + + void check(int index, int val) { + type.check(this, index, val); + } + + int byteSize() { + return last - first + 1; + } + + int elementSize() { + return byteSize() / type.size(); + } + + @Override + public String toString() { + return String.format("SegmentSlice{%s, %d, %d}", type, first, last); + } + } + + @DataProvider(name = "slices") + static Object[][] elementSlices() { + List<SegmentSlice> slices = new ArrayList<>(); + for (SegmentSlice.Kind kind : SegmentSlice.Kind.values()) { + MemorySegment segment = kind.makeSegment(16); + //compute all slices + for (Type type : Type.values()) { + for (int index = 0; index < 16; index += type.size()) { + MemorySegment first = segment.asSlice(0, index); + slices.add(new SegmentSlice(kind, type, 0, index - 1, first)); + MemorySegment second = segment.asSlice(index); + slices.add(new SegmentSlice(kind, type, index, 15, second)); + } + } + } + Object[][] sliceArray = new Object[slices.size() * slices.size()][]; + for (int i = 0 ; i < slices.size() ; i++) { + for (int j = 0 ; j < slices.size() ; j++) { + sliceArray[i * slices.size() + j] = new Object[] { slices.get(i), slices.get(j) }; + } + } + return sliceArray; + } +} diff --git a/test/jdk/java/foreign/TestRebase.java b/test/jdk/java/foreign/TestSegmentOffset.java similarity index 68% rename from test/jdk/java/foreign/TestRebase.java rename to test/jdk/java/foreign/TestSegmentOffset.java index 0396523c8a55882994166d85728bfcdf3acf2637..b9149f2471f43e69f31b90bef3d7e657fd32632f 100644 --- a/test/jdk/java/foreign/TestRebase.java +++ b/test/jdk/java/foreign/TestSegmentOffset.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -16,60 +16,58 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. - * */ /* * @test - * @run testng TestRebase + * @run testng TestSegmentOffset */ -import jdk.incubator.foreign.MemoryAccess; -import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; - import java.util.ArrayList; import java.util.List; import java.util.function.IntFunction; - +import static java.lang.System.out; +import static jdk.incubator.foreign.ValueLayout.JAVA_BYTE; import static org.testng.Assert.*; -public class TestRebase { +public class TestSegmentOffset { @Test(dataProvider = "slices") - public void testRebase(SegmentSlice s1, SegmentSlice s2) { + public void testOffset(SegmentSlice s1, SegmentSlice s2) { if (s1.contains(s2)) { - //check that an address and its rebased counterpart point to same element - MemoryAddress base = s2.segment.address(); - long offset = base.segmentOffset(s1.segment); + // check that a segment and its overlapping segment point to same elements + long offset = s1.segment.segmentOffset(s2.segment); for (int i = 0; i < s2.size(); i++) { - int expected = MemoryAccess.getByteAtOffset(s2.segment, i); - int found = (int)MemoryAccess.getByteAtOffset(s1.segment, i + offset); + out.format("testOffset s1:%s, s2:%s, offset:%d, i:%s\n", s1, s2, offset, i); + byte expected = s2.segment.get(JAVA_BYTE, i); + byte found = s1.segment.get(JAVA_BYTE, i + offset); assertEquals(found, expected); } } else if (s1.kind != s2.kind) { - // check that rebase s1 to s2 fails + // check that offset from s1 to s2 fails try { - s1.segment.address().segmentOffset(s2.segment); - fail("Rebase unexpectedly passed!"); - } catch (IllegalArgumentException ex) { - assertTrue(true); + long offset = s1.segment.segmentOffset(s2.segment); + out.format("testOffset s1:%s, s2:%s, offset:%d\n", s1, s2, offset); + fail("offset unexpectedly passed!"); + } catch (UnsupportedOperationException ex) { + assertTrue(ex.getMessage().contains("Cannot compute offset from native to heap (or vice versa).")); } } else if (!s2.contains(s1)) { - //disjoint segments - check that rebased address is out of bounds - MemoryAddress base = s2.segment.address(); - long offset = base.segmentOffset(s1.segment); + // disjoint segments - check that offset is out of bounds + long offset = s1.segment.segmentOffset(s2.segment); for (int i = 0; i < s2.size(); i++) { - MemoryAccess.getByteAtOffset(s2.segment, i); + out.format("testOffset s1:%s, s2:%s, offset:%d, i:%s\n", s1, s2, offset, i); + s2.segment.get(JAVA_BYTE, i); try { - MemoryAccess.getByteAtOffset(s1.segment, i + offset); - fail("Rebased address on a disjoint segment is not out of bounds!"); + s1.segment.get(JAVA_BYTE, i + offset); + fail("Offset on a disjoint segment is not out of bounds!"); } catch (IndexOutOfBoundsException ex) { assertTrue(true); } @@ -80,7 +78,7 @@ public class TestRebase { static class SegmentSlice { enum Kind { - NATIVE(i -> MemorySegment.allocateNative(i, ResourceScope.newImplicitScope())), + NATIVE(i -> MemorySegment.allocateNative(i, ResourceScope.newConfinedScope())), ARRAY(i -> MemorySegment.ofArray(new byte[i])); final IntFunction<MemorySegment> segmentFactory; @@ -122,12 +120,12 @@ public class TestRebase { int[] sizes = { 16, 8, 4, 2, 1 }; List<SegmentSlice> slices = new ArrayList<>(); for (SegmentSlice.Kind kind : SegmentSlice.Kind.values()) { - //init root segment + // init root segment MemorySegment segment = kind.makeSegment(16); for (int i = 0 ; i < 16 ; i++) { - MemoryAccess.setByteAtOffset(segment, i, (byte)i); + segment.set(JAVA_BYTE, i, (byte)i); } - //compute all slices + // compute all slices for (int size : sizes) { for (int index = 0 ; index < 16 ; index += size) { MemorySegment slice = segment.asSlice(index, size); diff --git a/test/jdk/java/foreign/TestSegmentOverlap.java b/test/jdk/java/foreign/TestSegmentOverlap.java new file mode 100644 index 0000000000000000000000000000000000000000..fb55e92dedb9046d8b743ec77fba9ea43af05cfd --- /dev/null +++ b/test/jdk/java/foreign/TestSegmentOverlap.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @run testng/othervm TestSegmentOverlap + */ + +import java.io.File; +import java.io.IOException; +import java.nio.channels.FileChannel; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.util.List; +import java.util.function.Supplier; +import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.ResourceScope; +import org.testng.annotations.Test; +import org.testng.annotations.DataProvider; +import static java.lang.System.out; +import static org.testng.Assert.*; + +public class TestSegmentOverlap { + + static Path tempPath; + + static { + try { + File file = File.createTempFile("buffer", "txt"); + file.deleteOnExit(); + tempPath = file.toPath(); + Files.write(file.toPath(), new byte[16], StandardOpenOption.WRITE); + + } catch (IOException ex) { + throw new ExceptionInInitializerError(ex); + } + } + + @DataProvider(name = "segmentFactories") + public Object[][] segmentFactories() { + List<Supplier<MemorySegment>> l = List.of( + () -> MemorySegment.allocateNative(16, ResourceScope.newConfinedScope()), + () -> { + try { + return MemorySegment.mapFile(tempPath, 0L, 16, FileChannel.MapMode.READ_WRITE, ResourceScope.newConfinedScope()); + } catch (IOException e) { + throw new RuntimeException(e); + } + }, + () -> MemorySegment.ofArray(new byte[] { 0x00, 0x01, 0x02, 0x03 } ), + () -> MemorySegment.ofArray(new char[] {'a', 'b', 'c', 'd' } ), + () -> MemorySegment.ofArray(new double[] { 1d, 2d, 3d, 4d} ), + () -> MemorySegment.ofArray(new float[] { 1.0f, 2.0f, 3.0f, 4.0f } ), + () -> MemorySegment.ofArray(new int[] { 1, 2, 3, 4 }), + () -> MemorySegment.ofArray(new long[] { 1L, 2L, 3L, 4L } ), + () -> MemorySegment.ofArray(new short[] { 1, 2, 3, 4 } ) + ); + return l.stream().map(s -> new Object[] { s }).toArray(Object[][]::new); + } + + @Test(dataProvider="segmentFactories") + public void testBasic(Supplier<MemorySegment> segmentSupplier) { + var s1 = segmentSupplier.get(); + var s2 = segmentSupplier.get(); + var sOther = s1.isNative() ? OtherSegmentFactory.HEAP.factory.get() + : OtherSegmentFactory.NATIVE.factory.get(); + out.format("testBasic s1:%s, s2:%s, sOther:%s\n", s1, s2, sOther); + assertNull(s1.asOverlappingSlice(s2)); + assertNull(s2.asOverlappingSlice(s1)); + assertNull(s1.asOverlappingSlice(sOther)); + } + + @Test(dataProvider="segmentFactories") + public void testIdentical(Supplier<MemorySegment> segmentSupplier) { + var s1 = segmentSupplier.get(); + var s2 = s1.asReadOnly(); + out.format("testIdentical s1:%s, s2:%s\n", s1, s2); + assertEquals(s1.asOverlappingSlice(s2).byteSize(), s1.byteSize()); + assertEquals(s1.asOverlappingSlice(s2).scope(), s1.scope()); + + assertEquals(s2.asOverlappingSlice(s1).byteSize(), s2.byteSize()); + assertEquals(s2.asOverlappingSlice(s1).scope(), s2.scope()); + + if (s1.isNative()) { + assertEquals(s1.asOverlappingSlice(s2).address(), s1.address()); + assertEquals(s2.asOverlappingSlice(s1).address(), s2.address()); + } + } + + @Test(dataProvider="segmentFactories") + public void testSlices(Supplier<MemorySegment> segmentSupplier) { + MemorySegment s1 = segmentSupplier.get(); + MemorySegment s2 = segmentSupplier.get(); + for (int offset = 0 ; offset < 4 ; offset++) { + MemorySegment slice = s1.asSlice(offset); + out.format("testSlices s1:%s, s2:%s, slice:%s, offset:%d\n", s1, s2, slice, offset); + assertEquals(s1.asOverlappingSlice(slice).byteSize(), s1.byteSize() - offset); + assertEquals(s1.asOverlappingSlice(slice).scope(), s1.scope()); + + assertEquals(slice.asOverlappingSlice(s1).byteSize(), slice.byteSize()); + assertEquals(slice.asOverlappingSlice(s1).scope(), slice.scope()); + + if (s1.isNative()) { + assertEquals(s1.asOverlappingSlice(slice).address(), s1.address().addOffset(offset)); + assertEquals(slice.asOverlappingSlice(s1).address(), slice.address()); + } + assertNull(s2.asOverlappingSlice(slice)); + } + } + + enum OtherSegmentFactory { + NATIVE(() -> MemorySegment.allocateNative(16, ResourceScope.newConfinedScope())), + HEAP(() -> MemorySegment.ofArray(new byte[]{16})); + + final Supplier<MemorySegment> factory; + + OtherSegmentFactory(Supplier<MemorySegment> segmentFactory) { + this.factory = segmentFactory; + } + } +} diff --git a/test/jdk/java/foreign/TestSegments.java b/test/jdk/java/foreign/TestSegments.java index beadf1618ac076e22c0c94f201bc8abe15bef7f2..fdf373448230ae6bfe7f508a77e8dd9a772c6b14 100644 --- a/test/jdk/java/foreign/TestSegments.java +++ b/test/jdk/java/foreign/TestSegments.java @@ -27,23 +27,21 @@ * @run testng/othervm -Xmx4G -XX:MaxDirectMemorySize=1M TestSegments */ -import jdk.incubator.foreign.MemoryAccess; import jdk.incubator.foreign.MemoryLayout; -import jdk.incubator.foreign.MemoryLayouts; import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; +import jdk.incubator.foreign.ValueLayout; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.lang.invoke.VarHandle; import java.nio.ByteBuffer; -import java.nio.ByteOrder; import java.util.List; import java.util.concurrent.atomic.AtomicReference; import java.util.function.IntFunction; -import java.util.function.LongFunction; import java.util.function.Supplier; +import static jdk.incubator.foreign.ValueLayout.JAVA_INT; import static org.testng.Assert.*; public class TestSegments { @@ -53,11 +51,6 @@ public class TestSegments { MemorySegment.allocateNative(size, align, ResourceScope.newImplicitScope()); } - @Test(dataProvider = "badLayouts", expectedExceptions = UnsupportedOperationException.class) - public void testBadAllocateLayout(MemoryLayout layout) { - MemorySegment.allocateNative(layout, ResourceScope.newImplicitScope()); - } - @Test(expectedExceptions = { OutOfMemoryError.class, IllegalArgumentException.class }) public void testAllocateTooBig() { @@ -71,8 +64,8 @@ public class TestSegments { @Test public void testNativeSegmentIsZeroed() { - VarHandle byteHandle = MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_BYTE) - .varHandle(byte.class, MemoryLayout.PathElement.sequenceElement()); + VarHandle byteHandle = MemoryLayout.sequenceLayout(ValueLayout.JAVA_BYTE) + .varHandle(MemoryLayout.PathElement.sequenceElement()); try (ResourceScope scope = ResourceScope.newConfinedScope()) { MemorySegment segment = MemorySegment.allocateNative(1000, 1, scope); for (long i = 0 ; i < segment.byteSize() ; i++) { @@ -83,8 +76,8 @@ public class TestSegments { @Test public void testSlices() { - VarHandle byteHandle = MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_BYTE) - .varHandle(byte.class, MemoryLayout.PathElement.sequenceElement()); + VarHandle byteHandle = MemoryLayout.sequenceLayout(ValueLayout.JAVA_BYTE) + .varHandle(MemoryLayout.PathElement.sequenceElement()); try (ResourceScope scope = ResourceScope.newConfinedScope()) { MemorySegment segment = MemorySegment.allocateNative(10, 1, scope); //init @@ -107,14 +100,14 @@ public class TestSegments { public void testSmallSegmentMax() { long offset = (long)Integer.MAX_VALUE + (long)Integer.MAX_VALUE + 2L + 6L; // overflows to 6 when casted to int MemorySegment memorySegment = MemorySegment.allocateNative(10, ResourceScope.newImplicitScope()); - MemoryAccess.getIntAtOffset(memorySegment, offset); + memorySegment.get(JAVA_INT, offset); } @Test(expectedExceptions = IndexOutOfBoundsException.class) public void testSmallSegmentMin() { long offset = ((long)Integer.MIN_VALUE * 2L) + 6L; // underflows to 6 when casted to int MemorySegment memorySegment = MemorySegment.allocateNative(10, ResourceScope.newImplicitScope()); - MemoryAccess.getIntAtOffset(memorySegment, offset); + memorySegment.get(JAVA_INT, offset); } @Test(dataProvider = "segmentFactories") @@ -125,7 +118,7 @@ public class TestSegments { } static void tryClose(MemorySegment segment) { - if (!segment.scope().isImplicit()) { + if (segment.scope() != ResourceScope.globalScope()) { segment.scope().close(); } } @@ -142,10 +135,10 @@ public class TestSegments { () -> MemorySegment.ofArray(new short[] { 1, 2, 3, 4 } ), () -> MemorySegment.allocateNative(4, ResourceScope.newImplicitScope()), () -> MemorySegment.allocateNative(4, 8, ResourceScope.newImplicitScope()), - () -> MemorySegment.allocateNative(MemoryLayout.valueLayout(32, ByteOrder.nativeOrder()), ResourceScope.newImplicitScope()), - () -> MemorySegment.allocateNative(4, ResourceScope.newConfinedScope()), - () -> MemorySegment.allocateNative(4, 8, ResourceScope.newConfinedScope()), - () -> MemorySegment.allocateNative(MemoryLayout.valueLayout(32, ByteOrder.nativeOrder()), ResourceScope.newConfinedScope()) + () -> MemorySegment.allocateNative(JAVA_INT, ResourceScope.newImplicitScope()), + () -> MemorySegment.allocateNative(4, ResourceScope.newImplicitScope()), + () -> MemorySegment.allocateNative(4, 8, ResourceScope.newImplicitScope()), + () -> MemorySegment.allocateNative(JAVA_INT, ResourceScope.newImplicitScope()) ); return l.stream().map(s -> new Object[] { s }).toArray(Object[][]::new); @@ -153,8 +146,8 @@ public class TestSegments { @Test(dataProvider = "segmentFactories") public void testFill(Supplier<MemorySegment> memorySegmentSupplier) { - VarHandle byteHandle = MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_BYTE) - .varHandle(byte.class, MemoryLayout.PathElement.sequenceElement()); + VarHandle byteHandle = MemoryLayout.sequenceLayout(ValueLayout.JAVA_BYTE) + .varHandle(MemoryLayout.PathElement.sequenceElement()); for (byte value : new byte[] {(byte) 0xFF, (byte) 0x00, (byte) 0x45}) { MemorySegment segment = memorySegmentSupplier.get(); @@ -193,15 +186,13 @@ public class TestSegments { } @Test(dataProvider = "segmentFactories") - public void testNativeSegments(Supplier<MemorySegment> memorySegmentSupplier) throws Exception { + public void testNativeSegments(Supplier<MemorySegment> memorySegmentSupplier) { MemorySegment segment = memorySegmentSupplier.get(); try { - segment.address().toRawLongValue(); + segment.address(); assertTrue(segment.isNative()); - assertTrue(segment.address().isNative()); } catch (UnsupportedOperationException exception) { assertFalse(segment.isNative()); - assertFalse(segment.address().isNative()); } tryClose(segment); } @@ -262,33 +253,6 @@ public class TestSegments { }; } - @DataProvider(name = "badLayouts") - public Object[][] layouts() { - SizedLayoutFactory[] layoutFactories = SizedLayoutFactory.values(); - Object[][] values = new Object[layoutFactories.length * 2][2]; - for (int i = 0; i < layoutFactories.length ; i++) { - values[i * 2] = new Object[] { MemoryLayout.structLayout(layoutFactories[i].make(7), MemoryLayout.paddingLayout(9)) }; // good size, bad align - values[(i * 2) + 1] = new Object[] { layoutFactories[i].make(15).withBitAlignment(16) }; // bad size, good align - } - return values; - } - - enum SizedLayoutFactory { - VALUE_BE(size -> MemoryLayout.valueLayout(size, ByteOrder.BIG_ENDIAN)), - VALUE_LE(size -> MemoryLayout.valueLayout(size, ByteOrder.LITTLE_ENDIAN)), - PADDING(MemoryLayout::paddingLayout); - - private final LongFunction<MemoryLayout> factory; - - SizedLayoutFactory(LongFunction<MemoryLayout> factory) { - this.factory = factory; - } - - MemoryLayout make(long size) { - return factory.apply(size); - } - } - @DataProvider(name = "heapFactories") public Object[][] heapFactories() { return new Object[][] { diff --git a/test/jdk/java/foreign/TestSharedAccess.java b/test/jdk/java/foreign/TestSharedAccess.java index b5b5f717b46e53b371c69e9e61be36338dc05ed1..346d92acef7cac6db97c5b4e82df92ca0b111067 100644 --- a/test/jdk/java/foreign/TestSharedAccess.java +++ b/test/jdk/java/foreign/TestSharedAccess.java @@ -43,11 +43,11 @@ import static org.testng.Assert.*; public class TestSharedAccess { - static final VarHandle intHandle = MemoryLayouts.JAVA_INT.varHandle(int.class); + static final VarHandle intHandle = ValueLayout.JAVA_INT.varHandle(); @Test public void testShared() throws Throwable { - SequenceLayout layout = MemoryLayout.sequenceLayout(1024, MemoryLayouts.JAVA_INT); + SequenceLayout layout = MemoryLayout.sequenceLayout(1024, ValueLayout.JAVA_INT); try (ResourceScope scope = ResourceScope.newSharedScope()) { MemorySegment s = MemorySegment.allocateNative(layout, scope); for (int i = 0 ; i < layout.elementCount().getAsLong() ; i++) { @@ -98,7 +98,7 @@ public class TestSharedAccess { setInt(s, 42); assertEquals(getInt(s), 42); List<Thread> threads = new ArrayList<>(); - MemorySegment sharedSegment = s.address().asSegment(s.byteSize(), scope); + MemorySegment sharedSegment = MemorySegment.ofAddress(s.address(), s.byteSize(), scope); for (int i = 0 ; i < 1000 ; i++) { threads.add(new Thread(() -> { assertEquals(getInt(sharedSegment), 42); @@ -121,7 +121,7 @@ public class TestSharedAccess { CountDownLatch b = new CountDownLatch(1); CompletableFuture<?> r; try (ResourceScope scope = ResourceScope.newConfinedScope()) { - MemorySegment s1 = MemorySegment.allocateNative(MemoryLayout.sequenceLayout(2, MemoryLayouts.JAVA_INT), scope); + MemorySegment s1 = MemorySegment.allocateNative(MemoryLayout.sequenceLayout(2, ValueLayout.JAVA_INT), scope); r = CompletableFuture.runAsync(() -> { try { ByteBuffer bb = s1.asByteBuffer(); diff --git a/test/jdk/java/foreign/TestSlices.java b/test/jdk/java/foreign/TestSlices.java index da9ad9135b1cadfae73fbbc2632dce1d416a2420..0cdc392cd93a9244493ab3b32ecdcdb8b703cdc0 100644 --- a/test/jdk/java/foreign/TestSlices.java +++ b/test/jdk/java/foreign/TestSlices.java @@ -23,12 +23,12 @@ */ import jdk.incubator.foreign.MemoryLayout; -import jdk.incubator.foreign.MemoryLayouts; import jdk.incubator.foreign.MemorySegment; import java.lang.invoke.VarHandle; import jdk.incubator.foreign.ResourceScope; +import jdk.incubator.foreign.ValueLayout; import org.testng.annotations.*; import static org.testng.Assert.*; @@ -39,9 +39,9 @@ import static org.testng.Assert.*; public class TestSlices { static MemoryLayout LAYOUT = MemoryLayout.sequenceLayout(2, - MemoryLayout.sequenceLayout(5, MemoryLayouts.JAVA_INT)); + MemoryLayout.sequenceLayout(5, ValueLayout.JAVA_INT)); - static VarHandle VH_ALL = LAYOUT.varHandle(int.class, + static VarHandle VH_ALL = LAYOUT.varHandle( MemoryLayout.PathElement.sequenceElement(), MemoryLayout.PathElement.sequenceElement()); @Test(dataProvider = "slices") @@ -76,16 +76,16 @@ public class TestSlices { // x { VH_ALL, 2, 5, new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 } }, // x[0::2] - { LAYOUT.varHandle(int.class, MemoryLayout.PathElement.sequenceElement(), + { LAYOUT.varHandle(MemoryLayout.PathElement.sequenceElement(), MemoryLayout.PathElement.sequenceElement(0, 2)), 2, 3, new int[] { 1, 3, 5, 6, 8, 10 } }, // x[1::2] - { LAYOUT.varHandle(int.class, MemoryLayout.PathElement.sequenceElement(), + { LAYOUT.varHandle(MemoryLayout.PathElement.sequenceElement(), MemoryLayout.PathElement.sequenceElement(1, 2)), 2, 2, new int[] { 2, 4, 7, 9 } }, // x[4::-2] - { LAYOUT.varHandle(int.class, MemoryLayout.PathElement.sequenceElement(), + { LAYOUT.varHandle(MemoryLayout.PathElement.sequenceElement(), MemoryLayout.PathElement.sequenceElement(4, -2)), 2, 3, new int[] { 5, 3, 1, 10, 8, 6 } }, // x[3::-2] - { LAYOUT.varHandle(int.class, MemoryLayout.PathElement.sequenceElement(), + { LAYOUT.varHandle(MemoryLayout.PathElement.sequenceElement(), MemoryLayout.PathElement.sequenceElement(3, -2)), 2, 2, new int[] { 4, 2, 9, 7 } }, }; } diff --git a/test/jdk/java/foreign/TestSpliterator.java b/test/jdk/java/foreign/TestSpliterator.java index d8c3fe24e0a9ac213f3ca5548af8a9cb6ba20171..17f4ef392590420b42337971f8fd3051df18ddcf 100644 --- a/test/jdk/java/foreign/TestSpliterator.java +++ b/test/jdk/java/foreign/TestSpliterator.java @@ -27,7 +27,6 @@ */ import jdk.incubator.foreign.MemoryLayout; -import jdk.incubator.foreign.MemoryLayouts; import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; import jdk.incubator.foreign.SequenceLayout; @@ -40,22 +39,22 @@ import java.util.concurrent.CountedCompleter; import java.util.concurrent.RecursiveTask; import java.util.concurrent.atomic.AtomicLong; import java.util.stream.LongStream; -import java.util.stream.StreamSupport; +import jdk.incubator.foreign.ValueLayout; import org.testng.annotations.*; import static org.testng.Assert.*; public class TestSpliterator { - static final VarHandle INT_HANDLE = MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_INT) - .varHandle(int.class, MemoryLayout.PathElement.sequenceElement()); + static final VarHandle INT_HANDLE = MemoryLayout.sequenceLayout(ValueLayout.JAVA_INT) + .varHandle(MemoryLayout.PathElement.sequenceElement()); final static int CARRIER_SIZE = 4; @Test(dataProvider = "splits") public void testSum(int size, int threshold) { - SequenceLayout layout = MemoryLayout.sequenceLayout(size, MemoryLayouts.JAVA_INT); + SequenceLayout layout = MemoryLayout.sequenceLayout(size, ValueLayout.JAVA_INT); //setup try (ResourceScope scope = ResourceScope.newSharedScope()) { @@ -82,7 +81,7 @@ public class TestSpliterator { @Test public void testSumSameThread() { - SequenceLayout layout = MemoryLayout.sequenceLayout(1024, MemoryLayouts.JAVA_INT); + SequenceLayout layout = MemoryLayout.sequenceLayout(1024, ValueLayout.JAVA_INT); //setup MemorySegment segment = MemorySegment.allocateNative(layout, ResourceScope.newImplicitScope()); @@ -100,32 +99,32 @@ public class TestSpliterator { @Test(expectedExceptions = IllegalArgumentException.class) public void testBadSpliteratorElementSizeTooBig() { - MemorySegment.ofArray(new byte[2]).spliterator(MemoryLayouts.JAVA_INT); + MemorySegment.ofArray(new byte[2]).spliterator(ValueLayout.JAVA_INT); } @Test(expectedExceptions = IllegalArgumentException.class) public void testBadStreamElementSizeTooBig() { - MemorySegment.ofArray(new byte[2]).elements(MemoryLayouts.JAVA_INT); + MemorySegment.ofArray(new byte[2]).elements(ValueLayout.JAVA_INT); } @Test(expectedExceptions = IllegalArgumentException.class) public void testBadSpliteratorElementSizeNotMultiple() { - MemorySegment.ofArray(new byte[7]).spliterator(MemoryLayouts.JAVA_INT); + MemorySegment.ofArray(new byte[7]).spliterator(ValueLayout.JAVA_INT); } @Test(expectedExceptions = IllegalArgumentException.class) public void testBadStreamElementSizeNotMultiple() { - MemorySegment.ofArray(new byte[7]).elements(MemoryLayouts.JAVA_INT); + MemorySegment.ofArray(new byte[7]).elements(ValueLayout.JAVA_INT); } @Test(expectedExceptions = IllegalArgumentException.class) public void testBadSpliteratorElementSizeZero() { - MemorySegment.ofArray(new byte[7]).spliterator(MemoryLayout.sequenceLayout(0, MemoryLayouts.JAVA_INT)); + MemorySegment.ofArray(new byte[7]).spliterator(MemoryLayout.sequenceLayout(0, ValueLayout.JAVA_INT)); } @Test(expectedExceptions = IllegalArgumentException.class) public void testBadStreamElementSizeZero() { - MemorySegment.ofArray(new byte[7]).elements(MemoryLayout.sequenceLayout(0, MemoryLayouts.JAVA_INT)); + MemorySegment.ofArray(new byte[7]).elements(MemoryLayout.sequenceLayout(0, ValueLayout.JAVA_INT)); } static long sumSingle(long acc, MemorySegment segment) { diff --git a/test/jdk/java/foreign/TestStringEncoding.java b/test/jdk/java/foreign/TestStringEncoding.java index 90fae756ada7fd17488f3650c28ca7b291d1d0f8..baa14db9d9bb475ef81e18e6724d4e0943511d2e 100644 --- a/test/jdk/java/foreign/TestStringEncoding.java +++ b/test/jdk/java/foreign/TestStringEncoding.java @@ -22,10 +22,10 @@ * */ -import jdk.incubator.foreign.CLinker; import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; +import jdk.incubator.foreign.SegmentAllocator; import org.testng.annotations.*; import static org.testng.Assert.*; @@ -40,11 +40,12 @@ public class TestStringEncoding { @Test(dataProvider = "strings") public void testStrings(String testString, int expectedByteLength) { try (ResourceScope scope = ResourceScope.newConfinedScope()) { - MemorySegment text = CLinker.toCString(testString, scope); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(expectedByteLength, scope); + MemorySegment text = allocator.allocateUtf8String(testString); assertEquals(text.byteSize(), expectedByteLength); - String roundTrip = CLinker.toJavaString(text); + String roundTrip = text.getUtf8String(0); assertEquals(roundTrip, testString); } } diff --git a/test/jdk/java/foreign/TestSymbolLookup.java b/test/jdk/java/foreign/TestSymbolLookup.java index 1cc537d5261e63fd8b9b01338767d31e95c0663c..fa76aa89ce3f78ba3193d2cc227698dfaaefb584 100644 --- a/test/jdk/java/foreign/TestSymbolLookup.java +++ b/test/jdk/java/foreign/TestSymbolLookup.java @@ -29,12 +29,12 @@ */ import jdk.incubator.foreign.SymbolLookup; -import jdk.incubator.foreign.MemoryAccess; -import jdk.incubator.foreign.MemoryLayouts; import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; +import jdk.incubator.foreign.ValueLayout; import org.testng.annotations.Test; +import static jdk.incubator.foreign.ValueLayout.JAVA_BYTE; import static org.testng.Assert.*; // FYI this test is run on 64-bit platforms only for now, @@ -61,7 +61,7 @@ public class TestSymbolLookup { @Test public void testVariableSymbolLookup() { - MemorySegment segment = LOOKUP.lookup("c").get().asSegment(MemoryLayouts.JAVA_INT.byteSize(), ResourceScope.globalScope()); - assertEquals(MemoryAccess.getInt(segment), 42); + MemorySegment segment = MemorySegment.ofAddress(LOOKUP.lookup("c").get().address(), ValueLayout.JAVA_INT.byteSize(), ResourceScope.globalScope()); + assertEquals(segment.get(JAVA_BYTE, 0), 42); } } diff --git a/test/jdk/java/foreign/TestTypeAccess.java b/test/jdk/java/foreign/TestTypeAccess.java index 9683f58987f4af25a19eb63005eb1b58d0896a2b..dc3ee8434bdc9d3065d6af475ebf91b412535a28 100644 --- a/test/jdk/java/foreign/TestTypeAccess.java +++ b/test/jdk/java/foreign/TestTypeAccess.java @@ -27,10 +27,9 @@ * @run testng TestTypeAccess */ -import jdk.incubator.foreign.MemoryHandles; import jdk.incubator.foreign.MemorySegment; -import jdk.incubator.foreign.MemoryLayouts; import jdk.incubator.foreign.ResourceScope; +import jdk.incubator.foreign.ValueLayout; import org.testng.annotations.*; import java.lang.invoke.VarHandle; @@ -38,24 +37,17 @@ import java.lang.invoke.WrongMethodTypeException; public class TestTypeAccess { - static final VarHandle INT_HANDLE = MemoryLayouts.JAVA_INT.varHandle(int.class); - - static final VarHandle ADDR_HANDLE = MemoryHandles.asAddressVarHandle(INT_HANDLE); + static final VarHandle INT_HANDLE = ValueLayout.JAVA_INT.varHandle(); + static final VarHandle ADDR_HANDLE = ValueLayout.ADDRESS.varHandle(); @Test(expectedExceptions=ClassCastException.class) public void testMemoryAddressCoordinateAsString() { - try (ResourceScope scope = ResourceScope.newConfinedScope()) { - MemorySegment s = MemorySegment.allocateNative(8, 8, scope); - int v = (int)INT_HANDLE.get("string"); - } + int v = (int)INT_HANDLE.get("string"); } @Test(expectedExceptions=WrongMethodTypeException.class) public void testMemoryCoordinatePrimitive() { - try (ResourceScope scope = ResourceScope.newConfinedScope()) { - MemorySegment s = MemorySegment.allocateNative(8, 8, scope); - int v = (int)INT_HANDLE.get(1); - } + int v = (int)INT_HANDLE.get(1); } @Test(expectedExceptions=ClassCastException.class) diff --git a/test/jdk/java/foreign/TestUnsupportedPlatform.java b/test/jdk/java/foreign/TestUnsupportedPlatform.java index 478cac72e33b88a7f2ae0a52c8bc798fa1a25441..eb1b5cf53a4154469bc0d4819faf133739827410 100644 --- a/test/jdk/java/foreign/TestUnsupportedPlatform.java +++ b/test/jdk/java/foreign/TestUnsupportedPlatform.java @@ -39,7 +39,7 @@ public class TestUnsupportedPlatform { @Test(expectedExceptions = ExceptionInInitializerError.class) public void testNoInitialization() { - CLinker.getInstance(); // trigger initialization + CLinker.systemCLinker(); // trigger initialization } } diff --git a/test/jdk/java/foreign/TestUpcall.java b/test/jdk/java/foreign/TestUpcall.java index 2b679e8539647f4c0e97e068698620ba0f4d8c38..c6959d7d131c2e0d4fe0f4e83496de6819e1acff 100644 --- a/test/jdk/java/foreign/TestUpcall.java +++ b/test/jdk/java/foreign/TestUpcall.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,24 +23,51 @@ */ /* - * @test + * @test id=scope * @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64" * @modules jdk.incubator.foreign/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcall * * @run testng/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies * --enable-native-access=ALL-UNNAMED -Dgenerator.sample.factor=17 + * -DUPCALL_TEST_TYPE=SCOPE + * TestUpcall + */ + +/* + * @test id=no_scope + * @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64" + * @modules jdk.incubator.foreign/jdk.internal.foreign + * @build NativeTestHelper CallGeneratorHelper TestUpcall + * + * @run testng/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies + * --enable-native-access=ALL-UNNAMED -Dgenerator.sample.factor=17 + * -DUPCALL_TEST_TYPE=NO_SCOPE + * TestUpcall + */ + +/* + * @test id=async + * @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64" + * @modules jdk.incubator.foreign/jdk.internal.foreign + * @build NativeTestHelper CallGeneratorHelper TestUpcall + * + * @run testng/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies + * --enable-native-access=ALL-UNNAMED -Dgenerator.sample.factor=17 + * -DUPCALL_TEST_TYPE=ASYNC * TestUpcall */ import jdk.incubator.foreign.CLinker; import jdk.incubator.foreign.FunctionDescriptor; +import jdk.incubator.foreign.NativeSymbol; +import jdk.incubator.foreign.SegmentAllocator; import jdk.incubator.foreign.SymbolLookup; -import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; +import org.testng.SkipException; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @@ -48,22 +75,32 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; import java.util.stream.Collectors; import static java.lang.invoke.MethodHandles.insertArguments; -import static jdk.incubator.foreign.CLinker.C_POINTER; import static org.testng.Assert.assertEquals; public class TestUpcall extends CallGeneratorHelper { + private enum TestType { + SCOPE, + NO_SCOPE, + ASYNC + } + + private static final TestType UPCALL_TEST_TYPE = TestType.valueOf(System.getProperty("UPCALL_TEST_TYPE")); + static { System.loadLibrary("TestUpcall"); + System.loadLibrary("AsyncInvokers"); } - static CLinker abi = CLinker.getInstance(); + static CLinker abi = CLinker.systemCLinker(); static final SymbolLookup LOOKUP = SymbolLookup.loaderLookup(); @@ -80,22 +117,29 @@ public class TestUpcall extends CallGeneratorHelper { } } - static MemoryAddress dummyStub; + static NativeSymbol dummyStub; @BeforeClass void setup() { dummyStub = abi.upcallStub(DUMMY, FunctionDescriptor.ofVoid(), ResourceScope.newImplicitScope()); } + private static void checkSelected(TestType type) { + if (UPCALL_TEST_TYPE != type) + throw new SkipException("Skipping tests that were not selected"); + } + @Test(dataProvider="functions", dataProviderClass=CallGeneratorHelper.class) public void testUpcalls(int count, String fName, Ret ret, List<ParamType> paramTypes, List<StructFieldType> fields) throws Throwable { + checkSelected(TestType.SCOPE); + List<Consumer<Object>> returnChecks = new ArrayList<>(); List<Consumer<Object[]>> argChecks = new ArrayList<>(); - MemoryAddress addr = LOOKUP.lookup(fName).get(); - MethodType mtype = methodType(ret, paramTypes, fields); - try (NativeScope scope = new NativeScope()) { - MethodHandle mh = abi.downcallHandle(addr, scope, mtype, function(ret, paramTypes, fields)); - Object[] args = makeArgs(scope.scope(), ret, paramTypes, fields, returnChecks, argChecks); + NativeSymbol addr = LOOKUP.lookup(fName).get(); + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(scope); + MethodHandle mh = downcallHandle(abi, addr, allocator, function(ret, paramTypes, fields)); + Object[] args = makeArgs(scope, ret, paramTypes, fields, returnChecks, argChecks); Object[] callArgs = args; Object res = mh.invokeWithArguments(callArgs); argChecks.forEach(c -> c.accept(args)); @@ -106,29 +150,57 @@ public class TestUpcall extends CallGeneratorHelper { } @Test(dataProvider="functions", dataProviderClass=CallGeneratorHelper.class) - public void testUpcallsNoScope(int count, String fName, Ret ret, List<ParamType> paramTypes, List<StructFieldType> fields) throws Throwable { + public void testUpcallsAsync(int count, String fName, Ret ret, List<ParamType> paramTypes, List<StructFieldType> fields) throws Throwable { + checkSelected(TestType.ASYNC); List<Consumer<Object>> returnChecks = new ArrayList<>(); List<Consumer<Object[]>> argChecks = new ArrayList<>(); - MemoryAddress addr = LOOKUP.lookup(fName).get(); - MethodType mtype = methodType(ret, paramTypes, fields); - MethodHandle mh = abi.downcallHandle(addr, IMPLICIT_ALLOCATOR, mtype, function(ret, paramTypes, fields)); - Object[] args = makeArgs(ResourceScope.newImplicitScope(), ret, paramTypes, fields, returnChecks, argChecks); - Object[] callArgs = args; - Object res = mh.invokeWithArguments(callArgs); - argChecks.forEach(c -> c.accept(args)); - if (ret == Ret.NON_VOID) { - returnChecks.forEach(c -> c.accept(res)); + NativeSymbol addr = LOOKUP.lookup(fName).get(); + try (ResourceScope scope = ResourceScope.newSharedScope()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(scope); + FunctionDescriptor descriptor = function(ret, paramTypes, fields); + MethodHandle mh = downcallHandle(abi, addr, allocator, descriptor); + Object[] args = makeArgs(ResourceScope.newImplicitScope(), ret, paramTypes, fields, returnChecks, argChecks); + + mh = mh.asSpreader(Object[].class, args.length); + mh = MethodHandles.insertArguments(mh, 0, (Object) args); + FunctionDescriptor callbackDesc = descriptor.returnLayout() + .map(FunctionDescriptor::of) + .orElse(FunctionDescriptor.ofVoid()); + NativeSymbol callback = abi.upcallStub(mh.asType(CLinker.upcallType(callbackDesc)), callbackDesc, scope); + + MethodHandle invoker = asyncInvoker(ret, ret == Ret.VOID ? null : paramTypes.get(0), fields); + + Object res = invoker.type().returnType() == MemorySegment.class + ? invoker.invoke(allocator, callback) + : invoker.invoke(callback); + argChecks.forEach(c -> c.accept(args)); + if (ret == Ret.NON_VOID) { + returnChecks.forEach(c -> c.accept(res)); + } } } - static MethodType methodType(Ret ret, List<ParamType> params, List<StructFieldType> fields) { - MethodType mt = ret == Ret.VOID ? - MethodType.methodType(void.class) : MethodType.methodType(paramCarrier(params.get(0).layout(fields))); - for (ParamType p : params) { - mt = mt.appendParameterTypes(paramCarrier(p.layout(fields))); + private static final Map<String, MethodHandle> INVOKERS = new HashMap<>(); + + private MethodHandle asyncInvoker(Ret ret, ParamType returnType, List<StructFieldType> fields) { + if (ret == Ret.VOID) { + String name = "call_async_V"; + return INVOKERS.computeIfAbsent(name, symbol -> + abi.downcallHandle( + LOOKUP.lookup(symbol).orElseThrow(), + FunctionDescriptor.ofVoid(C_POINTER))); } - mt = mt.appendParameterTypes(MemoryAddress.class); //the callback - return mt; + + String name = "call_async_" + returnType.name().charAt(0) + + (returnType == ParamType.STRUCT ? "_" + sigCode(fields) : ""); + + return INVOKERS.computeIfAbsent(name, symbol -> { + NativeSymbol invokerSymbol = LOOKUP.lookup(symbol).orElseThrow(); + MemoryLayout returnLayout = returnType.layout(fields); + FunctionDescriptor desc = FunctionDescriptor.of(returnLayout, C_POINTER); + + return abi.downcallHandle(invokerSymbol, desc); + }); } static FunctionDescriptor function(Ret ret, List<ParamType> params, List<StructFieldType> fields) { @@ -150,9 +222,9 @@ public class TestUpcall extends CallGeneratorHelper { } @SuppressWarnings("unchecked") - static MemoryAddress makeCallback(ResourceScope scope, Ret ret, List<ParamType> params, List<StructFieldType> fields, List<Consumer<Object>> checks, List<Consumer<Object[]>> argChecks) { + static NativeSymbol makeCallback(ResourceScope scope, Ret ret, List<ParamType> params, List<StructFieldType> fields, List<Consumer<Object>> checks, List<Consumer<Object[]>> argChecks) { if (params.isEmpty()) { - return dummyStub.address(); + return dummyStub; } AtomicReference<Object[]> box = new AtomicReference<>(); @@ -162,7 +234,7 @@ public class TestUpcall extends CallGeneratorHelper { for (int i = 0; i < params.size(); i++) { ParamType pt = params.get(i); MemoryLayout layout = pt.layout(fields); - Class<?> carrier = paramCarrier(layout); + Class<?> carrier = carrier(layout, false); mh = mh.asType(mh.type().changeParameterType(i, carrier)); final int finalI = i; @@ -175,7 +247,7 @@ public class TestUpcall extends CallGeneratorHelper { ParamType firstParam = params.get(0); MemoryLayout firstlayout = firstParam.layout(fields); - Class<?> firstCarrier = paramCarrier(firstlayout); + Class<?> firstCarrier = carrier(firstlayout, true); if (firstCarrier == MemorySegment.class) { checks.add(o -> assertStructEquals((MemorySegment) box.get()[0], (MemorySegment) o, firstlayout)); diff --git a/test/jdk/java/foreign/TestUpcallException.java b/test/jdk/java/foreign/TestUpcallException.java index d6630a74d77ce41a714760130a1d229cc509ef84..900b9c58513c3bc0f5050784d7d7589c371bf541 100644 --- a/test/jdk/java/foreign/TestUpcallException.java +++ b/test/jdk/java/foreign/TestUpcallException.java @@ -33,9 +33,6 @@ * TestUpcallException */ -import jdk.incubator.foreign.CLinker; -import jdk.incubator.foreign.FunctionDescriptor; -import jdk.incubator.foreign.ResourceScope; import jdk.test.lib.Utils; import org.testng.annotations.Test; @@ -54,17 +51,17 @@ public class TestUpcallException { @Test public void testExceptionInterpreted() throws InterruptedException, IOException { - boolean useSpec = false; - run(useSpec); + run(/* useSpec = */ false, /* isVoid = */ true); + run(/* useSpec = */ false, /* isVoid = */ false); } @Test public void testExceptionSpecialized() throws IOException, InterruptedException { - boolean useSpec = true; - run(useSpec); + run(/* useSpec = */ true, /* isVoid = */ true); + run(/* useSpec = */ true, /* isVoid = */ false); } - private void run(boolean useSpec) throws IOException, InterruptedException { + private void run(boolean useSpec, boolean isVoid) throws IOException, InterruptedException { Process process = new ProcessBuilder() .command( Paths.get(Utils.TEST_JDK) @@ -77,7 +74,8 @@ public class TestUpcallException { "-Djava.library.path=" + System.getProperty("java.library.path"), "-Djdk.internal.foreign.ProgrammableUpcallHandler.USE_SPEC=" + useSpec, "-cp", Utils.TEST_CLASS_PATH, - "ThrowingUpcall") + "ThrowingUpcall", + isVoid ? "void" : "non-void") .start(); int result = process.waitFor(); diff --git a/test/jdk/java/foreign/TestUpcallHighArity.java b/test/jdk/java/foreign/TestUpcallHighArity.java index dfe819c97e22fe385a9c6b7c7f0db6563539d28e..b025de9ed4ad4c5b311a89b47f1acbff9e75e9e9 100644 --- a/test/jdk/java/foreign/TestUpcallHighArity.java +++ b/test/jdk/java/foreign/TestUpcallHighArity.java @@ -33,8 +33,10 @@ * TestUpcallHighArity */ +import jdk.incubator.foreign.Addressable; import jdk.incubator.foreign.CLinker; import jdk.incubator.foreign.FunctionDescriptor; +import jdk.incubator.foreign.NativeSymbol; import jdk.incubator.foreign.SymbolLookup; import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemoryLayout; @@ -49,13 +51,12 @@ import java.lang.invoke.MethodType; import java.util.List; import java.util.concurrent.atomic.AtomicReference; -import static jdk.incubator.foreign.CLinker.*; import static org.testng.Assert.assertEquals; public class TestUpcallHighArity extends CallGeneratorHelper { static final MethodHandle MH_do_upcall; static final MethodHandle MH_passAndSave; - static final CLinker LINKER = CLinker.getInstance(); + static final CLinker LINKER = CLinker.systemCLinker(); // struct S_PDI { void* p0; double p1; int p2; }; static final MemoryLayout S_PDI_LAYOUT = MemoryLayout.structLayout( @@ -70,12 +71,7 @@ public class TestUpcallHighArity extends CallGeneratorHelper { SymbolLookup lookup = SymbolLookup.loaderLookup(); MH_do_upcall = LINKER.downcallHandle( lookup.lookup("do_upcall").get(), - MethodType.methodType(void.class, MemoryAddress.class, - MemorySegment.class, int.class, double.class, MemoryAddress.class, - MemorySegment.class, int.class, double.class, MemoryAddress.class, - MemorySegment.class, int.class, double.class, MemoryAddress.class, - MemorySegment.class, int.class, double.class, MemoryAddress.class), - FunctionDescriptor.ofVoid(C_POINTER, + FunctionDescriptor.ofVoid(C_POINTER, S_PDI_LAYOUT, C_INT, C_DOUBLE, C_POINTER, S_PDI_LAYOUT, C_INT, C_DOUBLE, C_POINTER, S_PDI_LAYOUT, C_INT, C_DOUBLE, C_POINTER, @@ -108,9 +104,9 @@ public class TestUpcallHighArity extends CallGeneratorHelper { .asCollector(Object[].class, upcallType.parameterCount()) .asType(upcallType); try (ResourceScope scope = ResourceScope.newConfinedScope()) { - MemoryAddress upcallStub = LINKER.upcallStub(target, upcallDescriptor, scope); + NativeSymbol upcallStub = LINKER.upcallStub(target, upcallDescriptor, scope); Object[] args = new Object[upcallType.parameterCount() + 1]; - args[0] = upcallStub.address(); + args[0] = upcallStub; List<MemoryLayout> argLayouts = upcallDescriptor.argumentLayouts(); for (int i = 1; i < args.length; i++) { args[i] = makeArg(argLayouts.get(i - 1), null, false); @@ -123,7 +119,7 @@ public class TestUpcallHighArity extends CallGeneratorHelper { if (upcallType.parameterType(i) == MemorySegment.class) { assertStructEquals((MemorySegment) capturedArgsArr[i], (MemorySegment) args[i + 1], argLayouts.get(i)); } else { - assertEquals(capturedArgsArr[i], args[i + 1]); + assertEquals(capturedArgsArr[i], args[i + 1], "For index " + i); } } } diff --git a/test/jdk/java/foreign/TestUpcallStructScope.java b/test/jdk/java/foreign/TestUpcallStructScope.java index 72bb1eafb9f09fb25bed6862e4098482bf995473..045d6191a9d50582d3cbaa441d08ad4640bac07f 100644 --- a/test/jdk/java/foreign/TestUpcallStructScope.java +++ b/test/jdk/java/foreign/TestUpcallStructScope.java @@ -37,8 +37,10 @@ * TestUpcallStructScope */ +import jdk.incubator.foreign.Addressable; import jdk.incubator.foreign.CLinker; import jdk.incubator.foreign.FunctionDescriptor; +import jdk.incubator.foreign.NativeSymbol; import jdk.incubator.foreign.SymbolLookup; import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemoryLayout; @@ -52,14 +54,11 @@ import java.lang.invoke.MethodType; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; -import static jdk.incubator.foreign.CLinker.C_DOUBLE; -import static jdk.incubator.foreign.CLinker.C_INT; -import static jdk.incubator.foreign.CLinker.C_POINTER; import static org.testng.Assert.assertFalse; -public class TestUpcallStructScope { +public class TestUpcallStructScope extends NativeTestHelper { static final MethodHandle MH_do_upcall; - static final CLinker LINKER = CLinker.getInstance(); + static final CLinker LINKER = CLinker.systemCLinker(); static final MethodHandle MH_Consumer_accept; // struct S_PDI { void* p0; double p1; int p2; }; @@ -74,8 +73,7 @@ public class TestUpcallStructScope { SymbolLookup lookup = SymbolLookup.loaderLookup(); MH_do_upcall = LINKER.downcallHandle( lookup.lookup("do_upcall").get(), - MethodType.methodType(void.class, MemoryAddress.class, MemorySegment.class), - FunctionDescriptor.ofVoid(C_POINTER, S_PDI_LAYOUT) + FunctionDescriptor.ofVoid(C_POINTER, S_PDI_LAYOUT) ); try { @@ -96,9 +94,9 @@ public class TestUpcallStructScope { MethodHandle target = methodHandle(capturedSegment::set); FunctionDescriptor upcallDesc = FunctionDescriptor.ofVoid(S_PDI_LAYOUT); try (ResourceScope scope = ResourceScope.newConfinedScope()) { - MemoryAddress upcallStub = LINKER.upcallStub(target, upcallDesc, scope); + NativeSymbol upcallStub = LINKER.upcallStub(target, upcallDesc, scope); MemorySegment argSegment = MemorySegment.allocateNative(S_PDI_LAYOUT, scope); - MH_do_upcall.invokeExact(upcallStub.address(), argSegment); + MH_do_upcall.invoke(upcallStub, argSegment); } MemorySegment captured = capturedSegment.get(); diff --git a/test/jdk/java/foreign/TestVarArgs.java b/test/jdk/java/foreign/TestVarArgs.java index 40ccea4e6845c828fbc0e405925fa15cc695c5ef..0efc22d7514601eaf78929bd8392b08ae065fea9 100644 --- a/test/jdk/java/foreign/TestVarArgs.java +++ b/test/jdk/java/foreign/TestVarArgs.java @@ -33,6 +33,7 @@ import jdk.incubator.foreign.FunctionDescriptor; import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.NativeSymbol; import jdk.incubator.foreign.ResourceScope; import jdk.incubator.foreign.SymbolLookup; import jdk.incubator.foreign.ValueLayout; @@ -45,27 +46,26 @@ import java.lang.invoke.VarHandle; import java.util.ArrayList; import java.util.List; -import static jdk.incubator.foreign.CLinker.*; import static jdk.incubator.foreign.MemoryLayout.PathElement.*; import static org.testng.Assert.assertEquals; -public class TestVarArgs { +public class TestVarArgs extends NativeTestHelper { static final MemoryLayout ML_CallInfo = MemoryLayout.structLayout( C_POINTER.withName("writeback"), // writeback C_POINTER.withName("argIDs")); // arg ids - static final VarHandle VH_CallInfo_writeback = ML_CallInfo.varHandle(long.class, groupElement("writeback")); - static final VarHandle VH_CallInfo_argIDs = ML_CallInfo.varHandle(long.class, groupElement("argIDs")); + static final VarHandle VH_CallInfo_writeback = ML_CallInfo.varHandle(groupElement("writeback")); + static final VarHandle VH_CallInfo_argIDs = ML_CallInfo.varHandle(groupElement("argIDs")); - static final VarHandle VH_IntArray = MemoryLayout.sequenceLayout(C_INT).varHandle(int.class, sequenceElement()); + static final VarHandle VH_IntArray = MemoryLayout.sequenceLayout(C_INT).varHandle(sequenceElement()); - static final CLinker abi = CLinker.getInstance(); + static final CLinker abi = CLinker.systemCLinker(); static { System.loadLibrary("VarArgs"); } - static final MemoryAddress VARARGS_ADDR = + static final NativeSymbol VARARGS_ADDR = SymbolLookup.loaderLookup() .lookup("varargs").get(); @@ -80,8 +80,8 @@ public class TestVarArgs { MemoryAddress callInfoPtr = callInfo.address(); - VH_CallInfo_writeback.set(callInfo, writeBack.address().toRawLongValue()); - VH_CallInfo_argIDs.set(callInfo, argIDs.address().toRawLongValue()); + VH_CallInfo_writeback.set(callInfo, writeBack.address()); + VH_CallInfo_argIDs.set(callInfo, argIDs.address()); for (int i = 0; i < args.size(); i++) { VH_IntArray.set(argIDs, (long) i, args.get(i).id.ordinal()); @@ -90,9 +90,9 @@ public class TestVarArgs { List<MemoryLayout> argLayouts = new ArrayList<>(); argLayouts.add(C_POINTER); // call info argLayouts.add(C_INT); // size - args.forEach(a -> argLayouts.add(asVarArg(a.layout))); - FunctionDescriptor desc = FunctionDescriptor.ofVoid(argLayouts.toArray(MemoryLayout[]::new)); + FunctionDescriptor desc = FunctionDescriptor.ofVoid(argLayouts.stream().toArray(MemoryLayout[]::new)) + .asVariadic(args.stream().map(a -> a.layout).toArray(MemoryLayout[]::new)); List<Class<?>> carriers = new ArrayList<>(); carriers.add(MemoryAddress.class); // call info @@ -101,7 +101,7 @@ public class TestVarArgs { MethodType mt = MethodType.methodType(void.class, carriers); - MethodHandle downcallHandle = abi.downcallHandle(VARARGS_ADDR, mt, desc); + MethodHandle downcallHandle = abi.downcallHandle(VARARGS_ADDR, desc); List<Object> argValues = new ArrayList<>(); argValues.add(callInfoPtr); // call info @@ -140,7 +140,7 @@ public class TestVarArgs { this.value = value; this.layout = layout; this.carrier = carrier; - this.vh = layout.varHandle(carrier); + this.vh = layout.varHandle(); } static VarArg intArg(int value) { diff --git a/test/jdk/java/foreign/TestVarHandleCombinators.java b/test/jdk/java/foreign/TestVarHandleCombinators.java index 2090c31fdd9add38cde22a4e460cf66dc3f369fc..e9beaebafa84c00377da2281a0e9fd209b1de9b7 100644 --- a/test/jdk/java/foreign/TestVarHandleCombinators.java +++ b/test/jdk/java/foreign/TestVarHandleCombinators.java @@ -29,6 +29,7 @@ import jdk.incubator.foreign.MemoryHandles; import jdk.incubator.foreign.ResourceScope; +import jdk.incubator.foreign.ValueLayout; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -43,7 +44,7 @@ public class TestVarHandleCombinators { @Test public void testElementAccess() { - VarHandle vh = MemoryHandles.varHandle(byte.class, ByteOrder.nativeOrder()); + VarHandle vh = MemoryHandles.varHandle(ValueLayout.JAVA_BYTE); byte[] arr = { 0, 0, -1, 0 }; MemorySegment segment = MemorySegment.ofArray(arr); @@ -52,7 +53,7 @@ public class TestVarHandleCombinators { @Test(expectedExceptions = IllegalStateException.class) public void testUnalignedElement() { - VarHandle vh = MemoryHandles.varHandle(byte.class, 4, ByteOrder.nativeOrder()); + VarHandle vh = MemoryHandles.varHandle(ValueLayout.JAVA_BYTE.withBitAlignment(32)); MemorySegment segment = MemorySegment.ofArray(new byte[4]); vh.get(segment, 2L); //should throw //FIXME: the VH only checks the alignment of the segment, which is fine if the VH is derived from layouts, @@ -60,19 +61,9 @@ public class TestVarHandleCombinators { //FIXME: at least until the VM is fixed } - @Test(expectedExceptions = IllegalArgumentException.class) - public void testAlignNotPowerOf2() { - VarHandle vh = MemoryHandles.varHandle(byte.class, 3, ByteOrder.nativeOrder()); - } - - @Test(expectedExceptions = IllegalArgumentException.class) - public void testAlignNegative() { - VarHandle vh = MemoryHandles.varHandle(byte.class, -1, ByteOrder.nativeOrder()); - } - @Test public void testAlign() { - VarHandle vh = MemoryHandles.varHandle(byte.class, 2, ByteOrder.nativeOrder()); + VarHandle vh = MemoryHandles.varHandle(ValueLayout.JAVA_BYTE.withBitAlignment(16)); MemorySegment segment = MemorySegment.allocateNative(1, 2, ResourceScope.newImplicitScope()); vh.set(segment, 0L, (byte) 10); // fine, memory region is aligned @@ -81,7 +72,7 @@ public class TestVarHandleCombinators { @Test public void testByteOrderLE() { - VarHandle vh = MemoryHandles.varHandle(short.class, 2, ByteOrder.LITTLE_ENDIAN); + VarHandle vh = MemoryHandles.varHandle(ValueLayout.JAVA_SHORT.withOrder(ByteOrder.LITTLE_ENDIAN)); byte[] arr = new byte[2]; MemorySegment segment = MemorySegment.ofArray(arr); vh.set(segment, 0L, (short) 0xFF); @@ -91,7 +82,7 @@ public class TestVarHandleCombinators { @Test public void testByteOrderBE() { - VarHandle vh = MemoryHandles.varHandle(short.class, 2, ByteOrder.BIG_ENDIAN); + VarHandle vh = MemoryHandles.varHandle(ValueLayout.JAVA_SHORT.withOrder(ByteOrder.BIG_ENDIAN)); byte[] arr = new byte[2]; MemorySegment segment = MemorySegment.ofArray(arr); vh.set(segment, 0L, (short) 0xFF); @@ -106,7 +97,7 @@ public class TestVarHandleCombinators { //[10 : [5 : [x32 i32]]] - VarHandle vh = MemoryHandles.varHandle(int.class, ByteOrder.nativeOrder()); + VarHandle vh = MemoryHandles.varHandle(ValueLayout.JAVA_INT.withBitAlignment(32)); int count = 0; try (ResourceScope scope = ResourceScope.newConfinedScope()) { MemorySegment segment = MemorySegment.allocateNative(inner_size * outer_size * 8, 4, scope); @@ -121,21 +112,4 @@ public class TestVarHandleCombinators { } } } - - @Test(dataProvider = "badCarriers", expectedExceptions = IllegalArgumentException.class) - public void testBadCarrier(Class<?> carrier) { - MemoryHandles.varHandle(carrier, ByteOrder.nativeOrder()); - } - - @DataProvider(name = "badCarriers") - public Object[][] createBadCarriers() { - return new Object[][] { - { void.class }, - { boolean.class }, - { Object.class }, - { int[].class }, - { MemorySegment.class } - }; - } - } diff --git a/test/jdk/java/foreign/ThrowingUpcall.java b/test/jdk/java/foreign/ThrowingUpcall.java index 405a89fc2f4c6e31a8189d1f8d0afd14856a6905..9efbf68565c35e9f840e159e0dacdc68dd09b679 100644 --- a/test/jdk/java/foreign/ThrowingUpcall.java +++ b/test/jdk/java/foreign/ThrowingUpcall.java @@ -23,29 +23,30 @@ import jdk.incubator.foreign.CLinker; import jdk.incubator.foreign.FunctionDescriptor; -import jdk.incubator.foreign.MemoryAddress; +import jdk.incubator.foreign.NativeSymbol; import jdk.incubator.foreign.ResourceScope; import jdk.incubator.foreign.SymbolLookup; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; -import java.security.Permission; -import static jdk.incubator.foreign.CLinker.C_POINTER; +public class ThrowingUpcall extends NativeTestHelper { -public class ThrowingUpcall { - - private static final MethodHandle downcall; + private static final MethodHandle downcallVoid; + private static final MethodHandle downcallNonVoid; public static final MethodHandle MH_throwException; static { System.loadLibrary("TestUpcall"); SymbolLookup lookup = SymbolLookup.loaderLookup(); - downcall = CLinker.getInstance().downcallHandle( + downcallVoid = CLinker.systemCLinker().downcallHandle( lookup.lookup("f0_V__").orElseThrow(), - MethodType.methodType(void.class, MemoryAddress.class), - FunctionDescriptor.ofVoid(C_POINTER) + FunctionDescriptor.ofVoid(C_POINTER) + ); + downcallNonVoid = CLinker.systemCLinker().downcallHandle( + lookup.lookup("f10_I_I_").orElseThrow(), + FunctionDescriptor.of(C_INT, C_INT, C_POINTER) ); try { @@ -61,18 +62,35 @@ public class ThrowingUpcall { } public static void main(String[] args) throws Throwable { - test(); + if (args[0].equals("void")) { + testVoid(); + } else { + testNonVoid(); + } } - public static void test() throws Throwable { + public static void testVoid() throws Throwable { MethodHandle handle = MH_throwException; MethodHandle invoker = MethodHandles.exactInvoker(MethodType.methodType(void.class)); handle = MethodHandles.insertArguments(invoker, 0, handle); try (ResourceScope scope = ResourceScope.newConfinedScope()) { - MemoryAddress stub = CLinker.getInstance().upcallStub(handle, FunctionDescriptor.ofVoid(), scope); + NativeSymbol stub = CLinker.systemCLinker().upcallStub(handle, FunctionDescriptor.ofVoid(), scope); + + downcallVoid.invoke(stub); // should call Shutdown.exit(1); + } + } + + public static void testNonVoid() throws Throwable { + MethodHandle handle = MethodHandles.identity(int.class); + handle = MethodHandles.collectArguments(handle, 0, MH_throwException); + MethodHandle invoker = MethodHandles.exactInvoker(MethodType.methodType(int.class, int.class)); + handle = MethodHandles.insertArguments(invoker, 0, handle); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol stub = CLinker.systemCLinker().upcallStub(handle, FunctionDescriptor.of(C_INT, C_INT), scope); - downcall.invokeExact(stub); // should call Shutdown.exit(1); + downcallNonVoid.invoke(42, stub); // should call Shutdown.exit(1); } } diff --git a/test/jdk/java/foreign/callarranger/TestAarch64CallArranger.java b/test/jdk/java/foreign/callarranger/TestAarch64CallArranger.java index eef17a4aad18d808b599338c1bd5443cc42c68a3..382b303f89b89c42b96742216dcba10d52c1e61f 100644 --- a/test/jdk/java/foreign/callarranger/TestAarch64CallArranger.java +++ b/test/jdk/java/foreign/callarranger/TestAarch64CallArranger.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,7 +56,7 @@ public class TestAarch64CallArranger extends CallArrangerTestBase { public void testEmpty() { MethodType mt = MethodType.methodType(void.class); FunctionDescriptor fd = FunctionDescriptor.ofVoid(); - CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); + CallArranger.Bindings bindings = CallArranger.LINUX.getBindings(mt, fd, false); assertFalse(bindings.isInMemoryReturn); CallingSequence callingSequence = bindings.callingSequence; @@ -78,7 +78,7 @@ public class TestAarch64CallArranger extends CallArrangerTestBase { C_INT, C_INT, C_INT, C_INT, C_INT, C_INT, C_INT, C_INT, C_INT, C_INT); - CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); + CallArranger.Bindings bindings = CallArranger.LINUX.getBindings(mt, fd, false); assertFalse(bindings.isInMemoryReturn); CallingSequence callingSequence = bindings.callingSequence; @@ -103,11 +103,11 @@ public class TestAarch64CallArranger extends CallArrangerTestBase { @Test public void testTwoIntTwoFloat() { - MethodType mt = MethodType.methodType(void.class, + MethodType mt = MethodType.methodType(void.class, int.class, int.class, float.class, float.class); FunctionDescriptor fd = FunctionDescriptor.ofVoid( C_INT, C_INT, C_FLOAT, C_FLOAT); - CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); + CallArranger.Bindings bindings = CallArranger.LINUX.getBindings(mt, fd, false); assertFalse(bindings.isInMemoryReturn); CallingSequence callingSequence = bindings.callingSequence; @@ -128,7 +128,7 @@ public class TestAarch64CallArranger extends CallArrangerTestBase { public void testStruct(MemoryLayout struct, Binding[] expectedBindings) { MethodType mt = MethodType.methodType(void.class, MemorySegment.class); FunctionDescriptor fd = FunctionDescriptor.ofVoid(struct); - CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); + CallArranger.Bindings bindings = CallArranger.LINUX.getBindings(mt, fd, false); assertFalse(bindings.isInMemoryReturn); CallingSequence callingSequence = bindings.callingSequence; @@ -157,8 +157,7 @@ public class TestAarch64CallArranger extends CallArrangerTestBase { // struct s { int32_t a, b; double c; int32_t d }; { struct2, new Binding[] { copy(struct2), - baseAddress(), - unboxAddress(), + unboxAddress(MemorySegment.class), vmStore(r0, long.class) }}, // struct s { int32_t a[2]; float b[2] }; @@ -188,7 +187,7 @@ public class TestAarch64CallArranger extends CallArrangerTestBase { MethodType mt = MethodType.methodType(void.class, MemorySegment.class, MemorySegment.class, int.class); FunctionDescriptor fd = FunctionDescriptor.ofVoid(struct1, struct2, C_INT); - CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); + CallArranger.Bindings bindings = CallArranger.LINUX.getBindings(mt, fd, false); assertFalse(bindings.isInMemoryReturn); CallingSequence callingSequence = bindings.callingSequence; @@ -198,14 +197,12 @@ public class TestAarch64CallArranger extends CallArrangerTestBase { checkArgumentBindings(callingSequence, new Binding[][]{ { copy(struct1), - baseAddress(), - unboxAddress(), + unboxAddress(MemorySegment.class), vmStore(r0, long.class) }, { copy(struct2), - baseAddress(), - unboxAddress(), + unboxAddress(MemorySegment.class), vmStore(r1, long.class) }, { vmStore(r2, int.class) } @@ -220,7 +217,7 @@ public class TestAarch64CallArranger extends CallArrangerTestBase { MethodType mt = MethodType.methodType(MemorySegment.class); FunctionDescriptor fd = FunctionDescriptor.of(struct); - CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); + CallArranger.Bindings bindings = CallArranger.LINUX.getBindings(mt, fd, false); assertTrue(bindings.isInMemoryReturn); CallingSequence callingSequence = bindings.callingSequence; @@ -243,7 +240,7 @@ public class TestAarch64CallArranger extends CallArrangerTestBase { MethodType mt = MethodType.methodType(MemorySegment.class); FunctionDescriptor fd = FunctionDescriptor.of(struct); - CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); + CallArranger.Bindings bindings = CallArranger.LINUX.getBindings(mt, fd, false); assertFalse(bindings.isInMemoryReturn); CallingSequence callingSequence = bindings.callingSequence; @@ -269,7 +266,7 @@ public class TestAarch64CallArranger extends CallArrangerTestBase { MethodType mt = MethodType.methodType(MemorySegment.class, float.class, int.class, MemorySegment.class); FunctionDescriptor fd = FunctionDescriptor.of(hfa, C_FLOAT, C_INT, hfa); - CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); + CallArranger.Bindings bindings = CallArranger.LINUX.getBindings(mt, fd, false); assertFalse(bindings.isInMemoryReturn); CallingSequence callingSequence = bindings.callingSequence; @@ -305,7 +302,7 @@ public class TestAarch64CallArranger extends CallArrangerTestBase { MethodType mt = MethodType.methodType(void.class, MemorySegment.class, MemorySegment.class, MemorySegment.class); FunctionDescriptor fd = FunctionDescriptor.ofVoid(struct, struct, struct); - CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); + CallArranger.Bindings bindings = CallArranger.LINUX.getBindings(mt, fd, false); assertFalse(bindings.isInMemoryReturn); CallingSequence callingSequence = bindings.callingSequence; @@ -358,7 +355,7 @@ public class TestAarch64CallArranger extends CallArrangerTestBase { int.class, int.class, int.class, int.class, MemorySegment.class, int.class); FunctionDescriptor fd = FunctionDescriptor.ofVoid( struct, struct, C_INT, C_INT, C_INT, C_INT, C_INT, C_INT, struct, C_INT); - CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); + CallArranger.Bindings bindings = CallArranger.LINUX.getBindings(mt, fd, false); assertFalse(bindings.isInMemoryReturn); CallingSequence callingSequence = bindings.callingSequence; @@ -366,18 +363,60 @@ public class TestAarch64CallArranger extends CallArrangerTestBase { assertEquals(callingSequence.functionDesc(), fd); checkArgumentBindings(callingSequence, new Binding[][]{ - { copy(struct), baseAddress(), unboxAddress(), vmStore(r0, long.class) }, - { copy(struct), baseAddress(), unboxAddress(), vmStore(r1, long.class) }, + { copy(struct), unboxAddress(MemorySegment.class), vmStore(r0, long.class) }, + { copy(struct), unboxAddress(MemorySegment.class), vmStore(r1, long.class) }, { vmStore(r2, int.class) }, { vmStore(r3, int.class) }, { vmStore(r4, int.class) }, { vmStore(r5, int.class) }, { vmStore(r6, int.class) }, { vmStore(r7, int.class) }, - { copy(struct), baseAddress(), unboxAddress(), vmStore(stackStorage(0), long.class) }, + { copy(struct), unboxAddress(MemorySegment.class), vmStore(stackStorage(0), long.class) }, { vmStore(stackStorage(1), int.class) }, }); checkReturnBindings(callingSequence, new Binding[]{}); } + + @Test + public void testVarArgsInRegs() { + MethodType mt = MethodType.methodType(void.class, int.class, int.class, float.class); + FunctionDescriptor fd = FunctionDescriptor.ofVoid(C_INT).asVariadic(C_INT, C_FLOAT); + CallArranger.Bindings bindings = CallArranger.LINUX.getBindings(mt, fd, false); + + assertFalse(bindings.isInMemoryReturn); + CallingSequence callingSequence = bindings.callingSequence; + assertEquals(callingSequence.methodType(), mt); + assertEquals(callingSequence.functionDesc(), fd); + + // This is identical to the non-variadic calling sequence + checkArgumentBindings(callingSequence, new Binding[][]{ + { vmStore(r0, int.class) }, + { vmStore(r1, int.class) }, + { vmStore(v0, float.class) }, + }); + + checkReturnBindings(callingSequence, new Binding[]{}); + } + + @Test + public void testVarArgsOnStack() { + MethodType mt = MethodType.methodType(void.class, int.class, int.class, float.class); + FunctionDescriptor fd = FunctionDescriptor.ofVoid(C_INT).asVariadic(C_INT, C_FLOAT); + CallArranger.Bindings bindings = CallArranger.MACOS.getBindings(mt, fd, false); + + assertFalse(bindings.isInMemoryReturn); + CallingSequence callingSequence = bindings.callingSequence; + assertEquals(callingSequence.methodType(), mt); + assertEquals(callingSequence.functionDesc(), fd); + + // The two variadic arguments should be allocated on the stack + checkArgumentBindings(callingSequence, new Binding[][]{ + { vmStore(r0, int.class) }, + { vmStore(stackStorage(0), int.class) }, + { vmStore(stackStorage(1), float.class) }, + }); + + checkReturnBindings(callingSequence, new Binding[]{}); + } } diff --git a/test/jdk/java/foreign/callarranger/TestSysVCallArranger.java b/test/jdk/java/foreign/callarranger/TestSysVCallArranger.java index 668132bc1defab4ce01ae801bfe29a76da25c4a5..ea1382e4a2e27c9abd63232ce8d91aac940a28cb 100644 --- a/test/jdk/java/foreign/callarranger/TestSysVCallArranger.java +++ b/test/jdk/java/foreign/callarranger/TestSysVCallArranger.java @@ -62,7 +62,7 @@ public class TestSysVCallArranger extends CallArrangerTestBase { assertFalse(bindings.isInMemoryReturn); CallingSequence callingSequence = bindings.callingSequence; assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class)); - assertEquals(callingSequence.functionDesc(), fd.withAppendedArgumentLayouts(C_LONG)); + assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG)); checkArgumentBindings(callingSequence, new Binding[][]{ { vmStore(rax, long.class) } @@ -89,7 +89,7 @@ public class TestSysVCallArranger extends CallArrangerTestBase { assertFalse(bindings.isInMemoryReturn); CallingSequence callingSequence = bindings.callingSequence; assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class)); - assertEquals(callingSequence.functionDesc(), fd.withAppendedArgumentLayouts(C_LONG)); + assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG)); checkArgumentBindings(callingSequence, new Binding[][]{ { dup(), bufferLoad(0, long.class), vmStore(rdi, long.class), @@ -119,7 +119,7 @@ public class TestSysVCallArranger extends CallArrangerTestBase { assertFalse(bindings.isInMemoryReturn); CallingSequence callingSequence = bindings.callingSequence; assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class)); - assertEquals(callingSequence.functionDesc(), fd.withAppendedArgumentLayouts(C_LONG)); + assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG)); checkArgumentBindings(callingSequence, new Binding[][]{ { dup(), bufferLoad(0, long.class), vmStore(rdi, long.class), @@ -148,7 +148,7 @@ public class TestSysVCallArranger extends CallArrangerTestBase { assertFalse(bindings.isInMemoryReturn); CallingSequence callingSequence = bindings.callingSequence; assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class)); - assertEquals(callingSequence.functionDesc(), fd.withAppendedArgumentLayouts(C_LONG)); + assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG)); checkArgumentBindings(callingSequence, new Binding[][]{ { dup(), bufferLoad(0, long.class), vmStore(stackStorage(0), long.class), @@ -177,7 +177,7 @@ public class TestSysVCallArranger extends CallArrangerTestBase { assertFalse(bindings.isInMemoryReturn); CallingSequence callingSequence = bindings.callingSequence; assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class)); - assertEquals(callingSequence.functionDesc(), fd.withAppendedArgumentLayouts(C_LONG)); + assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG)); checkArgumentBindings(callingSequence, new Binding[][]{ { dup(), bufferLoad(0, long.class), vmStore(stackStorage(0), long.class), @@ -201,7 +201,7 @@ public class TestSysVCallArranger extends CallArrangerTestBase { assertFalse(bindings.isInMemoryReturn); CallingSequence callingSequence = bindings.callingSequence; assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class)); - assertEquals(callingSequence.functionDesc(), fd.withAppendedArgumentLayouts(C_LONG)); + assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG)); checkArgumentBindings(callingSequence, new Binding[][]{ { vmStore(rdi, int.class) }, @@ -231,7 +231,7 @@ public class TestSysVCallArranger extends CallArrangerTestBase { assertFalse(bindings.isInMemoryReturn); CallingSequence callingSequence = bindings.callingSequence; assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class)); - assertEquals(callingSequence.functionDesc(), fd.withAppendedArgumentLayouts(C_LONG)); + assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG)); checkArgumentBindings(callingSequence, new Binding[][]{ { vmStore(xmm0, double.class) }, @@ -265,7 +265,7 @@ public class TestSysVCallArranger extends CallArrangerTestBase { assertFalse(bindings.isInMemoryReturn); CallingSequence callingSequence = bindings.callingSequence; assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class)); - assertEquals(callingSequence.functionDesc(), fd.withAppendedArgumentLayouts(C_LONG)); + assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG)); checkArgumentBindings(callingSequence, new Binding[][]{ { vmStore(rdi, long.class) }, @@ -321,7 +321,7 @@ public class TestSysVCallArranger extends CallArrangerTestBase { assertFalse(bindings.isInMemoryReturn); CallingSequence callingSequence = bindings.callingSequence; assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class)); - assertEquals(callingSequence.functionDesc(), fd.withAppendedArgumentLayouts(C_LONG)); + assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG)); checkArgumentBindings(callingSequence, new Binding[][]{ { vmStore(rdi, int.class) }, @@ -363,7 +363,7 @@ public class TestSysVCallArranger extends CallArrangerTestBase { assertFalse(bindings.isInMemoryReturn); CallingSequence callingSequence = bindings.callingSequence; assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class)); - assertEquals(callingSequence.functionDesc(), fd.withAppendedArgumentLayouts(C_LONG)); + assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG)); checkArgumentBindings(callingSequence, new Binding[][]{ { unboxAddress(), vmStore(rdi, long.class) }, @@ -384,7 +384,7 @@ public class TestSysVCallArranger extends CallArrangerTestBase { assertFalse(bindings.isInMemoryReturn); CallingSequence callingSequence = bindings.callingSequence; assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class)); - assertEquals(callingSequence.functionDesc(), fd.withAppendedArgumentLayouts(C_LONG)); + assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG)); checkArgumentBindings(callingSequence, new Binding[][]{ expectedBindings, @@ -442,7 +442,7 @@ public class TestSysVCallArranger extends CallArrangerTestBase { assertFalse(bindings.isInMemoryReturn); CallingSequence callingSequence = bindings.callingSequence; assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class)); - assertEquals(callingSequence.functionDesc(), fd.withAppendedArgumentLayouts(C_LONG)); + assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG)); checkArgumentBindings(callingSequence, new Binding[][]{ { vmStore(rax, long.class) } diff --git a/test/jdk/java/foreign/callarranger/TestWindowsCallArranger.java b/test/jdk/java/foreign/callarranger/TestWindowsCallArranger.java index cb85c6f55e8a5a38d8075133d4882b21b098f568..98ad5f4befbcc90fba7be0ac219dbd1476923522 100644 --- a/test/jdk/java/foreign/callarranger/TestWindowsCallArranger.java +++ b/test/jdk/java/foreign/callarranger/TestWindowsCallArranger.java @@ -156,8 +156,7 @@ public class TestWindowsCallArranger extends CallArrangerTestBase { { vmStore(rdx, int.class) }, { copy(structLayout), - baseAddress(), - unboxAddress(), + unboxAddress(MemorySegment.class), vmStore(r8, long.class) }, { vmStore(r9, int.class) }, @@ -178,7 +177,7 @@ public class TestWindowsCallArranger extends CallArrangerTestBase { MethodType mt = MethodType.methodType(void.class, int.class, double.class, int.class, double.class, double.class); FunctionDescriptor fd = FunctionDescriptor.ofVoid( - C_INT, C_DOUBLE, asVarArg(C_INT), asVarArg(C_DOUBLE), asVarArg(C_DOUBLE)); + C_INT, C_DOUBLE).asVariadic(C_INT, C_DOUBLE, C_DOUBLE); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); assertFalse(bindings.isInMemoryReturn); @@ -251,8 +250,7 @@ public class TestWindowsCallArranger extends CallArrangerTestBase { checkArgumentBindings(callingSequence, new Binding[][]{ { copy(struct), - baseAddress(), - unboxAddress(), + unboxAddress(MemorySegment.class), vmStore(rcx, long.class) } }); @@ -350,19 +348,19 @@ public class TestWindowsCallArranger extends CallArrangerTestBase { assertEquals(callingSequence.functionDesc(), fd); checkArgumentBindings(callingSequence, new Binding[][]{ - { copy(struct), baseAddress(), unboxAddress(), vmStore(rcx, long.class) }, + { copy(struct), unboxAddress(MemorySegment.class), vmStore(rcx, long.class) }, { vmStore(rdx, int.class) }, { vmStore(xmm2, double.class) }, { unboxAddress(), vmStore(r9, long.class) }, - { copy(struct), baseAddress(), unboxAddress(), vmStore(stackStorage(0), long.class) }, + { copy(struct), unboxAddress(MemorySegment.class), vmStore(stackStorage(0), long.class) }, { vmStore(stackStorage(1), int.class) }, { vmStore(stackStorage(2), double.class) }, { unboxAddress(), vmStore(stackStorage(3), long.class) }, - { copy(struct), baseAddress(), unboxAddress(), vmStore(stackStorage(4), long.class) }, + { copy(struct), unboxAddress(MemorySegment.class), vmStore(stackStorage(4), long.class) }, { vmStore(stackStorage(5), int.class) }, { vmStore(stackStorage(6), double.class) }, { unboxAddress(), vmStore(stackStorage(7), long.class) }, - { copy(struct), baseAddress(), unboxAddress(), vmStore(stackStorage(8), long.class) }, + { copy(struct), unboxAddress(MemorySegment.class), vmStore(stackStorage(8), long.class) }, { vmStore(stackStorage(9), int.class) }, { vmStore(stackStorage(10), double.class) }, { unboxAddress(), vmStore(stackStorage(11), long.class) }, diff --git a/test/jdk/java/foreign/channels/AbstractChannelsTest.java b/test/jdk/java/foreign/channels/AbstractChannelsTest.java index 81c6f0bf1932cb2ac74f7697bb45cee87ce95f8e..be0fb0afe8b2ee9409c797b7c2006ad44f49e369 100644 --- a/test/jdk/java/foreign/channels/AbstractChannelsTest.java +++ b/test/jdk/java/foreign/channels/AbstractChannelsTest.java @@ -22,18 +22,19 @@ */ import java.io.IOException; -import java.lang.ref.Cleaner; import java.nio.ByteBuffer; import java.util.Arrays; import java.util.Random; import java.util.concurrent.ExecutionException; import java.util.function.Supplier; import java.util.stream.Stream; -import jdk.incubator.foreign.MemoryAccess; + import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; import jdk.test.lib.RandomFactory; import org.testng.annotations.*; + +import static jdk.incubator.foreign.ValueLayout.JAVA_BYTE; import static org.testng.Assert.*; /** @@ -51,7 +52,7 @@ public class AbstractChannelsTest { } static ResourceScope closeableScopeOrNull(ResourceScope scope) { - if (scope.isImplicit()) + if (scope == ResourceScope.globalScope()) return null; return scope; } @@ -75,7 +76,7 @@ public class AbstractChannelsTest { static ByteBuffer segmentBufferOfSize(ResourceScope scope, int size) { var segment = MemorySegment.allocateNative(size, 1, scope); for (int i = 0; i < size; i++) { - MemoryAccess.setByteAtOffset(segment, i, ((byte)RANDOM.nextInt())); + segment.set(JAVA_BYTE, i, ((byte)RANDOM.nextInt())); } return segment.asByteBuffer(); } @@ -129,7 +130,6 @@ public class AbstractChannelsTest { public static Object[][] confinedScopes() { return new Object[][] { { ScopeSupplier.NEW_CONFINED }, - { ScopeSupplier.NEW_CONFINED_EXPLICIT }, }; } @@ -137,7 +137,6 @@ public class AbstractChannelsTest { public static Object[][] sharedScopes() { return new Object[][] { { ScopeSupplier.NEW_SHARED }, - { ScopeSupplier.NEW_SHARED_EXPLICIT }, }; } @@ -151,7 +150,6 @@ public class AbstractChannelsTest { @DataProvider(name = "implicitScopes") public static Object[][] implicitScopes() { return new Object[][] { - { ScopeSupplier.NEW_IMPLICIT }, { ScopeSupplier.GLOBAL }, }; } @@ -174,26 +172,20 @@ public class AbstractChannelsTest { public static Object[][] sharedScopesAndTimeouts() { return new Object[][] { { ScopeSupplier.NEW_SHARED , 0 }, - { ScopeSupplier.NEW_SHARED_EXPLICIT , 0 }, { ScopeSupplier.NEW_SHARED , 30 }, - { ScopeSupplier.NEW_SHARED_EXPLICIT , 30 }, }; } static class ScopeSupplier implements Supplier<ResourceScope> { static final Supplier<ResourceScope> NEW_CONFINED = - new ScopeSupplier(() -> ResourceScope.newConfinedScope(), "newConfinedScope()"); - static final Supplier<ResourceScope> NEW_CONFINED_EXPLICIT = - new ScopeSupplier(() -> ResourceScope.newConfinedScope(Cleaner.create()), "newConfinedScope(Cleaner)"); + new ScopeSupplier(ResourceScope::newConfinedScope, "newConfinedScope()"); static final Supplier<ResourceScope> NEW_SHARED = - new ScopeSupplier(() -> ResourceScope.newSharedScope(), "newSharedScope()"); - static final Supplier<ResourceScope> NEW_SHARED_EXPLICIT = - new ScopeSupplier(() -> ResourceScope.newSharedScope(Cleaner.create()), "newSharedScope(Cleaner)"); + new ScopeSupplier(ResourceScope::newSharedScope, "newSharedScope()"); static final Supplier<ResourceScope> NEW_IMPLICIT = - new ScopeSupplier(() -> ResourceScope.newImplicitScope(), "newImplicitScope()"); + new ScopeSupplier(ResourceScope::newImplicitScope, "newImplicitScope()"); static final Supplier<ResourceScope> GLOBAL = - new ScopeSupplier(() -> ResourceScope.globalScope(), "globalScope()"); + new ScopeSupplier(ResourceScope::globalScope, "globalScope()"); private final Supplier<ResourceScope> supplier; private final String str; diff --git a/test/jdk/java/foreign/channels/TestAsyncSocketChannels.java b/test/jdk/java/foreign/channels/TestAsyncSocketChannels.java index 1189600ddfe6de44c51e45965480c6b151c7d72d..f3d4a2cee4666e673167bc2d4eff5cf02d1129e6 100644 --- a/test/jdk/java/foreign/channels/TestAsyncSocketChannels.java +++ b/test/jdk/java/foreign/channels/TestAsyncSocketChannels.java @@ -48,12 +48,13 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import java.util.function.Supplier; -import jdk.incubator.foreign.MemoryAccess; + import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; import org.testng.annotations.*; import static java.lang.System.out; import static java.util.concurrent.TimeUnit.SECONDS; +import static jdk.incubator.foreign.ValueLayout.JAVA_BYTE; import static org.testng.Assert.*; /** @@ -162,7 +163,7 @@ public class TestAsyncSocketChannels extends AbstractChannelsTest { MemorySegment segment1 = MemorySegment.allocateNative(10, 1, scope); MemorySegment segment2 = MemorySegment.allocateNative(10, 1, scope); for (int i = 0; i < 10; i++) { - MemoryAccess.setByteAtOffset(segment1, i, (byte) i); + segment1.set(JAVA_BYTE, i, (byte) i); } { // Future variants ByteBuffer bb1 = segment1.asByteBuffer(); @@ -221,7 +222,7 @@ public class TestAsyncSocketChannels extends AbstractChannelsTest { ioOp.accept(handler); assertFalse(handler.isDone()); assertTrue(scope.isAlive()); - assertMessage(expectThrows(ISE, () -> scope.close()), "Scope is acquired by"); + assertMessage(expectThrows(ISE, () -> scope.close()), "Scope is kept alive by"); // write to allow the blocking read complete, which will // in turn unlock the scope and allow it to be closed. @@ -270,7 +271,7 @@ public class TestAsyncSocketChannels extends AbstractChannelsTest { // give time for socket buffer to fill up. awaitNoFurtherWrites(bytesWritten); - assertMessage(expectThrows(ISE, () -> scope.close()), "Scope is acquired by"); + assertMessage(expectThrows(ISE, () -> scope.close()), "Scope is kept alive by"); assertTrue(scope.isAlive()); // signal handler to stop further writing diff --git a/test/jdk/java/foreign/channels/TestSocketChannels.java b/test/jdk/java/foreign/channels/TestSocketChannels.java index 3ca3e2dc11aa7a8212ec76432a6244387bf75e97..7cbb624fd87522021ae648769c37d986f5af9840 100644 --- a/test/jdk/java/foreign/channels/TestSocketChannels.java +++ b/test/jdk/java/foreign/channels/TestSocketChannels.java @@ -40,10 +40,12 @@ import java.util.List; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Supplier; import java.util.stream.Stream; -import jdk.incubator.foreign.MemoryAccess; + import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; import org.testng.annotations.*; + +import static jdk.incubator.foreign.ValueLayout.JAVA_BYTE; import static org.testng.Assert.*; /** @@ -101,7 +103,7 @@ public class TestSocketChannels extends AbstractChannelsTest { MemorySegment segment1 = MemorySegment.allocateNative(10, 1, scope); MemorySegment segment2 = MemorySegment.allocateNative(10, 1, scope); for (int i = 0; i < 10; i++) { - MemoryAccess.setByteAtOffset(segment1, i, (byte) i); + segment1.set(JAVA_BYTE, i, (byte) i); } ByteBuffer bb1 = segment1.asByteBuffer(); ByteBuffer bb2 = segment2.asByteBuffer(); @@ -119,7 +121,7 @@ public class TestSocketChannels extends AbstractChannelsTest { var segment1 = MemorySegment.ofArray(new byte[10]); var segment2 = MemorySegment.ofArray(new byte[10]); for (int i = 0; i < 10; i++) { - MemoryAccess.setByteAtOffset(segment1, i, (byte) i); + segment1.set(JAVA_BYTE, i, (byte) i); } ByteBuffer bb1 = segment1.asByteBuffer(); ByteBuffer bb2 = segment2.asByteBuffer(); diff --git a/test/jdk/java/foreign/enablenativeaccess/org/openjdk/foreigntest/PanamaMainUnnamedModule.java b/test/jdk/java/foreign/enablenativeaccess/org/openjdk/foreigntest/PanamaMainUnnamedModule.java index bf32954eee3aea956deb9da736aa62f9e6aa1de7..789d70b139782d411f6d64419b75dc99042d33fd 100644 --- a/test/jdk/java/foreign/enablenativeaccess/org/openjdk/foreigntest/PanamaMainUnnamedModule.java +++ b/test/jdk/java/foreign/enablenativeaccess/org/openjdk/foreigntest/PanamaMainUnnamedModule.java @@ -32,26 +32,26 @@ import java.lang.reflect.Method; public class PanamaMainUnnamedModule { @Test public void testReflection() throws Throwable { - Method method = CLinker.class.getDeclaredMethod("getInstance"); + Method method = CLinker.class.getDeclaredMethod("systemCLinker"); method.invoke(null); } @Test public void testSetAccessible() throws Throwable { - Method method = CLinker.class.getDeclaredMethod("getInstance"); + Method method = CLinker.class.getDeclaredMethod("systemCLinker"); method.setAccessible(true); method.invoke(null); } @Test public void testInvoke() throws Throwable { - var mh = MethodHandles.lookup().findStatic(CLinker.class, "getInstance", + var mh = MethodHandles.lookup().findStatic(CLinker.class, "systemCLinker", MethodType.methodType(CLinker.class)); var linker = (CLinker)mh.invokeExact(); } @Test public void testDirectAccess() throws Throwable { - CLinker.getInstance(); + CLinker.systemCLinker(); } } diff --git a/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMain.java b/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMain.java index b4416f87808f0c204823ca36ce858fcf06351760..82c1e5008539914ea769b5570a01114cc42d4431 100644 --- a/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMain.java +++ b/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMain.java @@ -28,7 +28,7 @@ import jdk.incubator.foreign.*; public class PanamaMain { public static void main(String[] args) { System.out.println("Trying to get CLinker"); - CLinker.getInstance(); + CLinker.systemCLinker(); System.out.println("Got CLinker"); } } diff --git a/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMainInvoke.java b/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMainInvoke.java index 6a5a2bd4a92300cb44f3e5c402163ba45f561da3..46bf5a2c8d2ea1c7c42526ceb4225b6072308e01 100644 --- a/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMainInvoke.java +++ b/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMainInvoke.java @@ -28,7 +28,7 @@ import jdk.incubator.foreign.*; public class PanamaMainInvoke { public static void main(String[] args) throws Throwable { - var mh = MethodHandles.lookup().findStatic(CLinker.class, "getInstance", + var mh = MethodHandles.lookup().findStatic(CLinker.class, "systemCLinker", MethodType.methodType(CLinker.class)); var linker = (CLinker)mh.invokeExact(); } diff --git a/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMainReflection.java b/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMainReflection.java index 0ddd28b97ee1e51f402d2b095fc12f947838aa84..8206aab123bae670f74228164b5b814871944ff7 100644 --- a/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMainReflection.java +++ b/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMainReflection.java @@ -28,7 +28,7 @@ import java.lang.reflect.Method; public class PanamaMainReflection { public static void main(String[] args) throws Throwable { - Method method = CLinker.class.getDeclaredMethod("getInstance"); + Method method = CLinker.class.getDeclaredMethod("systemCLinker"); method.invoke(null); } } diff --git a/test/jdk/java/foreign/handles/invoker_module/handle/invoker/MethodHandleInvoker.java b/test/jdk/java/foreign/handles/invoker_module/handle/invoker/MethodHandleInvoker.java index bad4d441a48de1ec97911de05899560b0d94a3b3..c9ffe911be6d8ebc9481bbaa1d55c9e816d30034 100644 --- a/test/jdk/java/foreign/handles/invoker_module/handle/invoker/MethodHandleInvoker.java +++ b/test/jdk/java/foreign/handles/invoker_module/handle/invoker/MethodHandleInvoker.java @@ -28,10 +28,11 @@ import jdk.incubator.foreign.CLinker; import jdk.incubator.foreign.FunctionDescriptor; import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemoryLayout; -import jdk.incubator.foreign.MemoryLayouts; +import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; import jdk.incubator.foreign.SegmentAllocator; import jdk.incubator.foreign.SymbolLookup; +import jdk.incubator.foreign.ValueLayout; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; @@ -52,7 +53,7 @@ public class MethodHandleInvoker { throw new AssertionError("Caller module is not lookup_module!"); } } catch (Throwable ex) { - throw new AssertionError("Call to restricted method did not fail as expected!"); + throw new AssertionError("Call to restricted method did not fail as expected!", ex); } } @@ -63,8 +64,7 @@ public class MethodHandleInvoker { } static { - addDefaultMapping(CLinker.class, CLinker.getInstance()); - addDefaultMapping(long.class, 0L); + addDefaultMapping(CLinker.class, CLinker.systemCLinker()); addDefaultMapping(Path.class, Path.of("nonExistent")); addDefaultMapping(String.class, "Hello!"); addDefaultMapping(Runnable.class, () -> {}); @@ -73,11 +73,28 @@ public class MethodHandleInvoker { addDefaultMapping(MethodType.class, MethodType.methodType(void.class)); addDefaultMapping(MemoryAddress.class, MemoryAddress.NULL); addDefaultMapping(Addressable.class, MemoryAddress.NULL); - addDefaultMapping(MemoryLayout.class, MemoryLayouts.JAVA_INT); + addDefaultMapping(MemoryLayout.class, ValueLayout.JAVA_INT); addDefaultMapping(FunctionDescriptor.class, FunctionDescriptor.ofVoid()); addDefaultMapping(SymbolLookup.class, SymbolLookup.loaderLookup()); addDefaultMapping(ResourceScope.class, ResourceScope.newImplicitScope()); - addDefaultMapping(SegmentAllocator.class, (size, align) -> null); + addDefaultMapping(SegmentAllocator.class, SegmentAllocator.prefixAllocator(MemorySegment.ofArray(new byte[10]))); + addDefaultMapping(ValueLayout.OfByte.class, ValueLayout.JAVA_BYTE); + addDefaultMapping(ValueLayout.OfBoolean.class, ValueLayout.JAVA_BOOLEAN); + addDefaultMapping(ValueLayout.OfChar.class, ValueLayout.JAVA_CHAR); + addDefaultMapping(ValueLayout.OfShort.class, ValueLayout.JAVA_SHORT); + addDefaultMapping(ValueLayout.OfInt.class, ValueLayout.JAVA_INT); + addDefaultMapping(ValueLayout.OfFloat.class, ValueLayout.JAVA_FLOAT); + addDefaultMapping(ValueLayout.OfLong.class, ValueLayout.JAVA_LONG); + addDefaultMapping(ValueLayout.OfDouble.class, ValueLayout.JAVA_DOUBLE); + addDefaultMapping(ValueLayout.OfAddress.class, ValueLayout.ADDRESS); + addDefaultMapping(byte.class, (byte)0); + addDefaultMapping(boolean.class, true); + addDefaultMapping(char.class, (char)0); + addDefaultMapping(short.class, (short)0); + addDefaultMapping(int.class, 0); + addDefaultMapping(float.class, 0f); + addDefaultMapping(long.class, 0L); + addDefaultMapping(double.class, 0d); } static Object[] makeArgs(MethodType type) { diff --git a/test/jdk/java/foreign/handles/lookup_module/handle/lookup/MethodHandleLookup.java b/test/jdk/java/foreign/handles/lookup_module/handle/lookup/MethodHandleLookup.java index 20f092057c4e2ee5b0cf4f94516118d863da86f8..8755d40e6b173b2975c4ff52c241537e4a67287c 100644 --- a/test/jdk/java/foreign/handles/lookup_module/handle/lookup/MethodHandleLookup.java +++ b/test/jdk/java/foreign/handles/lookup_module/handle/lookup/MethodHandleLookup.java @@ -23,24 +23,20 @@ package handle.lookup; -import jdk.incubator.foreign.Addressable; import jdk.incubator.foreign.CLinker; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; -import java.nio.charset.Charset; -import java.nio.file.Path; -import java.util.Optional; -import jdk.incubator.foreign.FunctionDescriptor; +import jdk.incubator.foreign.Addressable; import jdk.incubator.foreign.SymbolLookup; import jdk.incubator.foreign.MemoryAddress; -import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; -import jdk.incubator.foreign.SegmentAllocator; +import jdk.incubator.foreign.VaList; +import jdk.incubator.foreign.ValueLayout; import org.testng.annotations.*; public class MethodHandleLookup { @@ -54,38 +50,77 @@ public class MethodHandleLookup { static Object[][] restrictedMethods() { try { return new Object[][]{ - { MethodHandles.lookup().findStatic(CLinker.class, "getInstance", - MethodType.methodType(CLinker.class)), "CLinker::getInstance" }, - { MethodHandles.lookup().findStatic(CLinker.class, "toJavaString", - MethodType.methodType(String.class, MemoryAddress.class)), - "CLinker::toJavaString" }, - { MethodHandles.lookup().findStatic(CLinker.class, "allocateMemory", - MethodType.methodType(MemoryAddress.class, long.class)), - "CLinker::allocateMemory" }, - { MethodHandles.lookup().findStatic(CLinker.class, "freeMemory", - MethodType.methodType(void.class, MemoryAddress.class)), - "CLinker::freeMemory" }, - { MethodHandles.lookup().findStatic(CLinker.VaList.class, "ofAddress", - MethodType.methodType(CLinker.VaList.class, MemoryAddress.class)), + { MethodHandles.lookup().findStatic(CLinker.class, "systemCLinker", + MethodType.methodType(CLinker.class)), "ForeignLinker::systemCLinker" }, + { MethodHandles.lookup().findStatic(VaList.class, "ofAddress", + MethodType.methodType(VaList.class, MemoryAddress.class, ResourceScope.class)), "VaList::ofAddress/1" }, - { MethodHandles.lookup().findStatic(CLinker.VaList.class, "ofAddress", - MethodType.methodType(CLinker.VaList.class, MemoryAddress.class, ResourceScope.class)), - "VaList::ofAddress/2" }, - { MethodHandles.lookup().findStatic(CLinker.class, "systemLookup", - MethodType.methodType(SymbolLookup.class)), - "CLinker::systemLookup" }, { MethodHandles.lookup().findStatic(SymbolLookup.class, "loaderLookup", MethodType.methodType(SymbolLookup.class)), "SymbolLookup::loaderLookup" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "asSegment", - MethodType.methodType(MemorySegment.class, long.class, ResourceScope.class)), - "MemoryAddress::asSegment/1" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "asSegment", - MethodType.methodType(MemorySegment.class, long.class, Runnable.class, ResourceScope.class)), - "MemoryAddress::asSegment/2" }, - { MethodHandles.lookup().findStatic(MemorySegment.class, "globalNativeSegment", - MethodType.methodType(MemorySegment.class)), - "MemoryAddress::globalNativeSegment" } + { MethodHandles.lookup().findStatic(MemorySegment.class, "ofAddress", + MethodType.methodType(MemorySegment.class, MemoryAddress.class, long.class, ResourceScope.class)), + "MemorySegment::ofAddress" }, + { MethodHandles.lookup().findVirtual(MemoryAddress.class, "getUtf8String", + MethodType.methodType(String.class, long.class)), + "MemoryAddress::getUtf8String" }, + { MethodHandles.lookup().findVirtual(MemoryAddress.class, "setUtf8String", + MethodType.methodType(void.class, long.class, String.class)), + "MemoryAddress::setUtf8String" }, + { MethodHandles.lookup().findVirtual(MemoryAddress.class, "get", + MethodType.methodType(byte.class, ValueLayout.OfByte.class, long.class)), + "MemoryAddress::get/byte" }, + { MethodHandles.lookup().findVirtual(MemoryAddress.class, "get", + MethodType.methodType(boolean.class, ValueLayout.OfBoolean.class, long.class)), + "MemoryAddress::get/boolean" }, + { MethodHandles.lookup().findVirtual(MemoryAddress.class, "get", + MethodType.methodType(char.class, ValueLayout.OfChar.class, long.class)), + "MemoryAddress::get/char" }, + { MethodHandles.lookup().findVirtual(MemoryAddress.class, "get", + MethodType.methodType(short.class, ValueLayout.OfShort.class, long.class)), + "MemoryAddress::get/short" }, + { MethodHandles.lookup().findVirtual(MemoryAddress.class, "get", + MethodType.methodType(int.class, ValueLayout.OfInt.class, long.class)), + "MemoryAddress::get/int" }, + { MethodHandles.lookup().findVirtual(MemoryAddress.class, "get", + MethodType.methodType(float.class, ValueLayout.OfFloat.class, long.class)), + "MemoryAddress::get/float" }, + { MethodHandles.lookup().findVirtual(MemoryAddress.class, "get", + MethodType.methodType(long.class, ValueLayout.OfLong.class, long.class)), + "MemoryAddress::get/long" }, + { MethodHandles.lookup().findVirtual(MemoryAddress.class, "get", + MethodType.methodType(double.class, ValueLayout.OfDouble.class, long.class)), + "MemoryAddress::get/double" }, + { MethodHandles.lookup().findVirtual(MemoryAddress.class, "get", + MethodType.methodType(MemoryAddress.class, ValueLayout.OfAddress.class, long.class)), + "MemoryAddress::get/address" }, + { MethodHandles.lookup().findVirtual(MemoryAddress.class, "set", + MethodType.methodType(void.class, ValueLayout.OfByte.class, long.class, byte.class)), + "MemoryAddress::set/byte" }, + { MethodHandles.lookup().findVirtual(MemoryAddress.class, "set", + MethodType.methodType(void.class, ValueLayout.OfBoolean.class, long.class, boolean.class)), + "MemoryAddress::set/boolean" }, + { MethodHandles.lookup().findVirtual(MemoryAddress.class, "set", + MethodType.methodType(void.class, ValueLayout.OfChar.class, long.class, char.class)), + "MemoryAddress::set/char" }, + { MethodHandles.lookup().findVirtual(MemoryAddress.class, "set", + MethodType.methodType(void.class, ValueLayout.OfShort.class, long.class, short.class)), + "MemoryAddress::set/short" }, + { MethodHandles.lookup().findVirtual(MemoryAddress.class, "set", + MethodType.methodType(void.class, ValueLayout.OfInt.class, long.class, int.class)), + "MemoryAddress::set/int" }, + { MethodHandles.lookup().findVirtual(MemoryAddress.class, "set", + MethodType.methodType(void.class, ValueLayout.OfFloat.class, long.class, float.class)), + "MemoryAddress::set/float" }, + { MethodHandles.lookup().findVirtual(MemoryAddress.class, "set", + MethodType.methodType(void.class, ValueLayout.OfLong.class, long.class, long.class)), + "MemoryAddress::set/long" }, + { MethodHandles.lookup().findVirtual(MemoryAddress.class, "set", + MethodType.methodType(void.class, ValueLayout.OfDouble.class, long.class, double.class)), + "MemoryAddress::set/double" }, + { MethodHandles.lookup().findVirtual(MemoryAddress.class, "set", + MethodType.methodType(void.class, ValueLayout.OfAddress.class, long.class, Addressable.class)), + "MemoryAddress::set/address" }, }; } catch (Throwable ex) { throw new ExceptionInInitializerError((ex)); diff --git a/test/jdk/java/foreign/libAsyncInvokers.cpp b/test/jdk/java/foreign/libAsyncInvokers.cpp new file mode 100644 index 0000000000000000000000000000000000000000..775e2c3c81439eb1c9a26f13d16c35ea4dff2e0f --- /dev/null +++ b/test/jdk/java/foreign/libAsyncInvokers.cpp @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include <thread> + +#include "libTestUpcall.h" +#ifdef __clang__ +#pragma clang optimize off +#elif defined __GNUC__ +#pragma GCC optimize ("O0") +#elif defined _MSC_BUILD +#pragma optimize( "", off ) +#endif + +template<typename CB> +void launch_v(CB cb) { + std::thread thrd(cb); + thrd.join(); +} + +template<typename O, typename CB> +void start(O& out, CB cb) { + out = cb(); +} + +template<typename O, typename CB> +O launch(CB cb) { + O result; + std::thread thrd(&start<O, CB>, std::ref(result), cb); + thrd.join(); + return result; +} + +extern "C" { +EXPORT void call_async_V(void (*cb)(void)) { launch_v(cb); } + +EXPORT int call_async_I(int (*cb)(void)) { return launch<int>(cb); } +EXPORT float call_async_F(float (*cb)(void)) { return launch<float>(cb); } +EXPORT double call_async_D(double (*cb)(void)) { return launch<double>(cb); } +EXPORT void* call_async_P(void* (*cb)(void)) { return launch<void*>(cb); } + +EXPORT struct S_I call_async_S_I(struct S_I (*cb)(void)) { return launch<struct S_I>(cb); } +EXPORT struct S_F call_async_S_F(struct S_F (*cb)(void)) { return launch<struct S_F>(cb); } +EXPORT struct S_D call_async_S_D(struct S_D (*cb)(void)) { return launch<struct S_D>(cb); } +EXPORT struct S_P call_async_S_P(struct S_P (*cb)(void)) { return launch<struct S_P>(cb); } +EXPORT struct S_II call_async_S_II(struct S_II (*cb)(void)) { return launch<struct S_II>(cb); } +EXPORT struct S_IF call_async_S_IF(struct S_IF (*cb)(void)) { return launch<struct S_IF>(cb); } +EXPORT struct S_ID call_async_S_ID(struct S_ID (*cb)(void)) { return launch<struct S_ID>(cb); } +EXPORT struct S_IP call_async_S_IP(struct S_IP (*cb)(void)) { return launch<struct S_IP>(cb); } +EXPORT struct S_FI call_async_S_FI(struct S_FI (*cb)(void)) { return launch<struct S_FI>(cb); } +EXPORT struct S_FF call_async_S_FF(struct S_FF (*cb)(void)) { return launch<struct S_FF>(cb); } +EXPORT struct S_FD call_async_S_FD(struct S_FD (*cb)(void)) { return launch<struct S_FD>(cb); } +EXPORT struct S_FP call_async_S_FP(struct S_FP (*cb)(void)) { return launch<struct S_FP>(cb); } +EXPORT struct S_DI call_async_S_DI(struct S_DI (*cb)(void)) { return launch<struct S_DI>(cb); } +EXPORT struct S_DF call_async_S_DF(struct S_DF (*cb)(void)) { return launch<struct S_DF>(cb); } +EXPORT struct S_DD call_async_S_DD(struct S_DD (*cb)(void)) { return launch<struct S_DD>(cb); } +EXPORT struct S_DP call_async_S_DP(struct S_DP (*cb)(void)) { return launch<struct S_DP>(cb); } +EXPORT struct S_PI call_async_S_PI(struct S_PI (*cb)(void)) { return launch<struct S_PI>(cb); } +EXPORT struct S_PF call_async_S_PF(struct S_PF (*cb)(void)) { return launch<struct S_PF>(cb); } +EXPORT struct S_PD call_async_S_PD(struct S_PD (*cb)(void)) { return launch<struct S_PD>(cb); } +EXPORT struct S_PP call_async_S_PP(struct S_PP (*cb)(void)) { return launch<struct S_PP>(cb); } +EXPORT struct S_III call_async_S_III(struct S_III (*cb)(void)) { return launch<struct S_III>(cb); } +EXPORT struct S_IIF call_async_S_IIF(struct S_IIF (*cb)(void)) { return launch<struct S_IIF>(cb); } +EXPORT struct S_IID call_async_S_IID(struct S_IID (*cb)(void)) { return launch<struct S_IID>(cb); } +EXPORT struct S_IIP call_async_S_IIP(struct S_IIP (*cb)(void)) { return launch<struct S_IIP>(cb); } +EXPORT struct S_IFI call_async_S_IFI(struct S_IFI (*cb)(void)) { return launch<struct S_IFI>(cb); } +EXPORT struct S_IFF call_async_S_IFF(struct S_IFF (*cb)(void)) { return launch<struct S_IFF>(cb); } +EXPORT struct S_IFD call_async_S_IFD(struct S_IFD (*cb)(void)) { return launch<struct S_IFD>(cb); } +EXPORT struct S_IFP call_async_S_IFP(struct S_IFP (*cb)(void)) { return launch<struct S_IFP>(cb); } +EXPORT struct S_IDI call_async_S_IDI(struct S_IDI (*cb)(void)) { return launch<struct S_IDI>(cb); } +EXPORT struct S_IDF call_async_S_IDF(struct S_IDF (*cb)(void)) { return launch<struct S_IDF>(cb); } +EXPORT struct S_IDD call_async_S_IDD(struct S_IDD (*cb)(void)) { return launch<struct S_IDD>(cb); } +EXPORT struct S_IDP call_async_S_IDP(struct S_IDP (*cb)(void)) { return launch<struct S_IDP>(cb); } +EXPORT struct S_IPI call_async_S_IPI(struct S_IPI (*cb)(void)) { return launch<struct S_IPI>(cb); } +EXPORT struct S_IPF call_async_S_IPF(struct S_IPF (*cb)(void)) { return launch<struct S_IPF>(cb); } +EXPORT struct S_IPD call_async_S_IPD(struct S_IPD (*cb)(void)) { return launch<struct S_IPD>(cb); } +EXPORT struct S_IPP call_async_S_IPP(struct S_IPP (*cb)(void)) { return launch<struct S_IPP>(cb); } +EXPORT struct S_FII call_async_S_FII(struct S_FII (*cb)(void)) { return launch<struct S_FII>(cb); } +EXPORT struct S_FIF call_async_S_FIF(struct S_FIF (*cb)(void)) { return launch<struct S_FIF>(cb); } +EXPORT struct S_FID call_async_S_FID(struct S_FID (*cb)(void)) { return launch<struct S_FID>(cb); } +EXPORT struct S_FIP call_async_S_FIP(struct S_FIP (*cb)(void)) { return launch<struct S_FIP>(cb); } +EXPORT struct S_FFI call_async_S_FFI(struct S_FFI (*cb)(void)) { return launch<struct S_FFI>(cb); } +EXPORT struct S_FFF call_async_S_FFF(struct S_FFF (*cb)(void)) { return launch<struct S_FFF>(cb); } +EXPORT struct S_FFD call_async_S_FFD(struct S_FFD (*cb)(void)) { return launch<struct S_FFD>(cb); } +EXPORT struct S_FFP call_async_S_FFP(struct S_FFP (*cb)(void)) { return launch<struct S_FFP>(cb); } +EXPORT struct S_FDI call_async_S_FDI(struct S_FDI (*cb)(void)) { return launch<struct S_FDI>(cb); } +EXPORT struct S_FDF call_async_S_FDF(struct S_FDF (*cb)(void)) { return launch<struct S_FDF>(cb); } +EXPORT struct S_FDD call_async_S_FDD(struct S_FDD (*cb)(void)) { return launch<struct S_FDD>(cb); } +EXPORT struct S_FDP call_async_S_FDP(struct S_FDP (*cb)(void)) { return launch<struct S_FDP>(cb); } +EXPORT struct S_FPI call_async_S_FPI(struct S_FPI (*cb)(void)) { return launch<struct S_FPI>(cb); } +EXPORT struct S_FPF call_async_S_FPF(struct S_FPF (*cb)(void)) { return launch<struct S_FPF>(cb); } +EXPORT struct S_FPD call_async_S_FPD(struct S_FPD (*cb)(void)) { return launch<struct S_FPD>(cb); } +EXPORT struct S_FPP call_async_S_FPP(struct S_FPP (*cb)(void)) { return launch<struct S_FPP>(cb); } +EXPORT struct S_DII call_async_S_DII(struct S_DII (*cb)(void)) { return launch<struct S_DII>(cb); } +EXPORT struct S_DIF call_async_S_DIF(struct S_DIF (*cb)(void)) { return launch<struct S_DIF>(cb); } +EXPORT struct S_DID call_async_S_DID(struct S_DID (*cb)(void)) { return launch<struct S_DID>(cb); } +EXPORT struct S_DIP call_async_S_DIP(struct S_DIP (*cb)(void)) { return launch<struct S_DIP>(cb); } +EXPORT struct S_DFI call_async_S_DFI(struct S_DFI (*cb)(void)) { return launch<struct S_DFI>(cb); } +EXPORT struct S_DFF call_async_S_DFF(struct S_DFF (*cb)(void)) { return launch<struct S_DFF>(cb); } +EXPORT struct S_DFD call_async_S_DFD(struct S_DFD (*cb)(void)) { return launch<struct S_DFD>(cb); } +EXPORT struct S_DFP call_async_S_DFP(struct S_DFP (*cb)(void)) { return launch<struct S_DFP>(cb); } +EXPORT struct S_DDI call_async_S_DDI(struct S_DDI (*cb)(void)) { return launch<struct S_DDI>(cb); } +EXPORT struct S_DDF call_async_S_DDF(struct S_DDF (*cb)(void)) { return launch<struct S_DDF>(cb); } +EXPORT struct S_DDD call_async_S_DDD(struct S_DDD (*cb)(void)) { return launch<struct S_DDD>(cb); } +EXPORT struct S_DDP call_async_S_DDP(struct S_DDP (*cb)(void)) { return launch<struct S_DDP>(cb); } +EXPORT struct S_DPI call_async_S_DPI(struct S_DPI (*cb)(void)) { return launch<struct S_DPI>(cb); } +EXPORT struct S_DPF call_async_S_DPF(struct S_DPF (*cb)(void)) { return launch<struct S_DPF>(cb); } +EXPORT struct S_DPD call_async_S_DPD(struct S_DPD (*cb)(void)) { return launch<struct S_DPD>(cb); } +EXPORT struct S_DPP call_async_S_DPP(struct S_DPP (*cb)(void)) { return launch<struct S_DPP>(cb); } +EXPORT struct S_PII call_async_S_PII(struct S_PII (*cb)(void)) { return launch<struct S_PII>(cb); } +EXPORT struct S_PIF call_async_S_PIF(struct S_PIF (*cb)(void)) { return launch<struct S_PIF>(cb); } +EXPORT struct S_PID call_async_S_PID(struct S_PID (*cb)(void)) { return launch<struct S_PID>(cb); } +EXPORT struct S_PIP call_async_S_PIP(struct S_PIP (*cb)(void)) { return launch<struct S_PIP>(cb); } +EXPORT struct S_PFI call_async_S_PFI(struct S_PFI (*cb)(void)) { return launch<struct S_PFI>(cb); } +EXPORT struct S_PFF call_async_S_PFF(struct S_PFF (*cb)(void)) { return launch<struct S_PFF>(cb); } +EXPORT struct S_PFD call_async_S_PFD(struct S_PFD (*cb)(void)) { return launch<struct S_PFD>(cb); } +EXPORT struct S_PFP call_async_S_PFP(struct S_PFP (*cb)(void)) { return launch<struct S_PFP>(cb); } +EXPORT struct S_PDI call_async_S_PDI(struct S_PDI (*cb)(void)) { return launch<struct S_PDI>(cb); } +EXPORT struct S_PDF call_async_S_PDF(struct S_PDF (*cb)(void)) { return launch<struct S_PDF>(cb); } +EXPORT struct S_PDD call_async_S_PDD(struct S_PDD (*cb)(void)) { return launch<struct S_PDD>(cb); } +EXPORT struct S_PDP call_async_S_PDP(struct S_PDP (*cb)(void)) { return launch<struct S_PDP>(cb); } +EXPORT struct S_PPI call_async_S_PPI(struct S_PPI (*cb)(void)) { return launch<struct S_PPI>(cb); } +EXPORT struct S_PPF call_async_S_PPF(struct S_PPF (*cb)(void)) { return launch<struct S_PPF>(cb); } +EXPORT struct S_PPD call_async_S_PPD(struct S_PPD (*cb)(void)) { return launch<struct S_PPD>(cb); } +EXPORT struct S_PPP call_async_S_PPP(struct S_PPP (*cb)(void)) { return launch<struct S_PPP>(cb); } +} diff --git a/test/jdk/java/foreign/libIntrinsics.c b/test/jdk/java/foreign/libIntrinsics.c index 5b6923cbbd780cff7c4974b71984270cb96900d6..89d0a09c7b608d7983ff565450214b3b3e7f888d 100644 --- a/test/jdk/java/foreign/libIntrinsics.c +++ b/test/jdk/java/foreign/libIntrinsics.c @@ -22,6 +22,8 @@ * */ +#include <stdbool.h> + #ifdef _WIN64 #define EXPORT __declspec(dllexport) #else @@ -31,6 +33,10 @@ EXPORT void empty() { } +EXPORT bool identity_bool(bool x) { + return x; +} + EXPORT char identity_char(char x) { return x; } diff --git a/test/jdk/java/foreign/libSafeAccess.c b/test/jdk/java/foreign/libSafeAccess.c index a5bcbe0e892dfc1e6b00d294940e0e28e700cff1..3a640329aa1264f4618d486b1f4ea2326920469e 100644 --- a/test/jdk/java/foreign/libSafeAccess.c +++ b/test/jdk/java/foreign/libSafeAccess.c @@ -36,3 +36,9 @@ struct Point { EXPORT void struct_func(struct Point p) { } EXPORT void addr_func(struct Point* p) { } + +EXPORT void addr_func_6(struct Point* p1, struct Point* p2, struct Point* p3, struct Point* p4, struct Point* p5, struct Point* p6) { } + +EXPORT void addr_func_cb(void* p, void (*callback)()) { + callback(); +} diff --git a/test/jdk/java/foreign/loaderLookup/TestLoaderLookup.java b/test/jdk/java/foreign/loaderLookup/TestLoaderLookup.java new file mode 100644 index 0000000000000000000000000000000000000000..3d83ba044edef321b8249d38d8562131fe7dc810 --- /dev/null +++ b/test/jdk/java/foreign/loaderLookup/TestLoaderLookup.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64" + * @compile --add-modules jdk.incubator.foreign lookup/Lookup.java + * @compile --add-modules jdk.incubator.foreign invoker/Invoker.java + * @run main/othervm --enable-native-access=ALL-UNNAMED TestLoaderLookup + */ + +import java.lang.reflect.*; +import jdk.incubator.foreign.*; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Paths; + +public class TestLoaderLookup { + public static void main(String[] args) throws ReflectiveOperationException { + ClassLoader loader1 = newClassLoader("lookup"); + Class<?> lookup = loader1.loadClass("lookup.Lookup"); + Method fooSymbol = lookup.getDeclaredMethod("fooSymbol"); + NativeSymbol foo = (NativeSymbol)fooSymbol.invoke(null); + + ClassLoader loader2 = newClassLoader("invoker"); + Class<?> invoker = loader2.loadClass("invoker.Invoker"); + Method invoke = invoker.getDeclaredMethod("invoke", NativeSymbol.class); + invoke.invoke(null, foo); + + loader1 = null; + lookup = null; + fooSymbol = null; + // Make sure that the loader is kept reachable + for (int i = 0 ; i < 1000 ; i++) { + invoke.invoke(null, foo); // might crash if loader1 is GC'ed + System.gc(); + } + } + + public static ClassLoader newClassLoader(String path) { + try { + return new URLClassLoader(new URL[] { + Paths.get(System.getProperty("test.classes", path)).toUri().toURL(), + }, null); + } catch (MalformedURLException e){ + throw new RuntimeException("Unexpected URL conversion failure", e); + } + } +} diff --git a/test/jdk/java/foreign/loaderLookup/invoker/Invoker.java b/test/jdk/java/foreign/loaderLookup/invoker/Invoker.java new file mode 100644 index 0000000000000000000000000000000000000000..fab39a25498137158e35ca7d716027ded22458d2 --- /dev/null +++ b/test/jdk/java/foreign/loaderLookup/invoker/Invoker.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package invoker; + +import jdk.incubator.foreign.*; + +public class Invoker { + public static void invoke(NativeSymbol symbol) throws Throwable { + var linker = CLinker.systemCLinker(); + var handle = linker.downcallHandle(symbol, FunctionDescriptor.ofVoid()); + handle.invokeExact(); + } +} \ No newline at end of file diff --git a/test/jdk/java/foreign/loaderLookup/lookup/Lookup.java b/test/jdk/java/foreign/loaderLookup/lookup/Lookup.java new file mode 100644 index 0000000000000000000000000000000000000000..087a91dcdc2b8c0e68fe4c4dcf6a5a84ba38bbd8 --- /dev/null +++ b/test/jdk/java/foreign/loaderLookup/lookup/Lookup.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package lookup; + +import jdk.incubator.foreign.*; + +public class Lookup { + static { + System.loadLibrary("Foo"); + } + + static SymbolLookup lookup = SymbolLookup.loaderLookup(); + + public static NativeSymbol fooSymbol() { + return lookup.lookup("foo").get(); + } +} \ No newline at end of file diff --git a/test/jdk/java/foreign/loaderLookup/lookup/libFoo.c b/test/jdk/java/foreign/loaderLookup/lookup/libFoo.c new file mode 100644 index 0000000000000000000000000000000000000000..68525215b9345254dc8bbdfcb286729749930c72 --- /dev/null +++ b/test/jdk/java/foreign/loaderLookup/lookup/libFoo.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include <stdio.h> + +#ifdef _WIN64 +#define EXPORT __declspec(dllexport) +#else +#define EXPORT +#endif + +EXPORT void foo(void) { + // do nothing +} diff --git a/test/jdk/java/foreign/malloc/TestMixedMallocFree.java b/test/jdk/java/foreign/malloc/TestMixedMallocFree.java index 41c7616c5f97f688091248db93305fc2c6c2932e..1603fd83ee392091224084d18859bdb01fff7aed 100644 --- a/test/jdk/java/foreign/malloc/TestMixedMallocFree.java +++ b/test/jdk/java/foreign/malloc/TestMixedMallocFree.java @@ -23,13 +23,13 @@ /* * @test + * @library ../ * @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64" * @run testng/othervm --enable-native-access=ALL-UNNAMED TestMixedMallocFree */ import jdk.incubator.foreign.CLinker; import jdk.incubator.foreign.FunctionDescriptor; -import jdk.incubator.foreign.MemoryAccess; import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; @@ -37,12 +37,11 @@ import jdk.incubator.foreign.SymbolLookup; import org.testng.annotations.Test; import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodType; -import static jdk.incubator.foreign.CLinker.*; +import static jdk.incubator.foreign.ValueLayout.JAVA_INT; import static org.testng.Assert.assertEquals; -public class TestMixedMallocFree { +public class TestMixedMallocFree extends NativeTestHelper { static final MethodHandle MH_my_malloc; @@ -50,21 +49,20 @@ public class TestMixedMallocFree { System.loadLibrary("Malloc"); SymbolLookup MALLOC = SymbolLookup.loaderLookup(); - MH_my_malloc = CLinker.getInstance().downcallHandle( + MH_my_malloc = CLinker.systemCLinker().downcallHandle( MALLOC.lookup("my_malloc").orElseThrow(), - MethodType.methodType(MemoryAddress.class, long.class), - FunctionDescriptor.of(C_POINTER, C_LONG_LONG)); + FunctionDescriptor.of(C_POINTER, C_LONG_LONG)); } @Test public void testMalloc() throws Throwable { MemoryAddress ma = (MemoryAddress) MH_my_malloc.invokeExact(4L); - MemorySegment seg = ma.asSegment(4L, ResourceScope.newImplicitScope()); - MemoryAccess.setInt(seg, 42); - assertEquals(MemoryAccess.getInt(seg), 42); + MemorySegment seg = MemorySegment.ofAddress(ma, 4L, ResourceScope.newImplicitScope()); + seg.set(JAVA_INT, 0, 42); + assertEquals(seg.get(JAVA_INT, 0), 42); // Test if this free crashes the VM, which might be the case if we load the wrong default library // and end up mixing two allocators together. - CLinker.freeMemory(ma); + freeMemory(ma); } } diff --git a/test/jdk/java/foreign/stackwalk/TestAsyncStackWalk.java b/test/jdk/java/foreign/stackwalk/TestAsyncStackWalk.java index b56231230fdf430580848809a0da23a8ebb07475..9c9de5e0305392a7095d2c555fe3779e638bb072 100644 --- a/test/jdk/java/foreign/stackwalk/TestAsyncStackWalk.java +++ b/test/jdk/java/foreign/stackwalk/TestAsyncStackWalk.java @@ -25,6 +25,7 @@ * @test id=default_gc * @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64" * @library /test/lib + * @library ../ * @build sun.hotspot.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox * @@ -52,6 +53,7 @@ * @requires (((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64") * @requires vm.gc.Z * @library /test/lib + * @library ../ * @build sun.hotspot.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox * @@ -80,6 +82,7 @@ * @requires (((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64") * @requires vm.gc.Shenandoah * @library /test/lib + * @library ../ * @build sun.hotspot.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox * @@ -106,6 +109,7 @@ import jdk.incubator.foreign.CLinker; import jdk.incubator.foreign.FunctionDescriptor; +import jdk.incubator.foreign.NativeSymbol; import jdk.incubator.foreign.SymbolLookup; import jdk.incubator.foreign.MemoryAddress; @@ -116,13 +120,12 @@ import jdk.incubator.foreign.ResourceScope; import sun.hotspot.WhiteBox; import static java.lang.invoke.MethodHandles.lookup; -import static jdk.incubator.foreign.CLinker.C_POINTER; import static jdk.test.lib.Asserts.assertTrue; -public class TestAsyncStackWalk { +public class TestAsyncStackWalk extends NativeTestHelper { static final WhiteBox WB = WhiteBox.getWhiteBox(); - static final CLinker linker = CLinker.getInstance(); + static final CLinker linker = CLinker.systemCLinker(); static final MethodHandle MH_asyncStackWalk; static final MethodHandle MH_m; @@ -133,7 +136,6 @@ public class TestAsyncStackWalk { SymbolLookup lookup = SymbolLookup.loaderLookup(); MH_asyncStackWalk = linker.downcallHandle( lookup.lookup("asyncStackWalk").get(), - MethodType.methodType(void.class, MemoryAddress.class), FunctionDescriptor.ofVoid(C_POINTER)); MH_m = lookup().findStatic(TestAsyncStackWalk.class, "m", MethodType.methodType(void.class)); } catch (ReflectiveOperationException e) { @@ -146,7 +148,7 @@ public class TestAsyncStackWalk { public static void main(String[] args) throws Throwable { try (ResourceScope scope = ResourceScope.newConfinedScope()) { - MemoryAddress stub = linker.upcallStub(MH_m, FunctionDescriptor.ofVoid(), scope); + NativeSymbol stub = linker.upcallStub(MH_m, FunctionDescriptor.ofVoid(), scope); MemoryAddress stubAddress = stub.address(); invocations = 0; didStackWalk = false; @@ -156,7 +158,7 @@ public class TestAsyncStackWalk { } static void payload(MemoryAddress cb) throws Throwable { - MH_asyncStackWalk.invokeExact(cb); + MH_asyncStackWalk.invoke(cb); } static void m() { diff --git a/test/jdk/java/foreign/stackwalk/TestStackWalk.java b/test/jdk/java/foreign/stackwalk/TestStackWalk.java index 5d220cce25c72deaa6e7e759424cbeb73837b02a..07cc0e83df66bba7a6e1ee3be9587a573a36ace5 100644 --- a/test/jdk/java/foreign/stackwalk/TestStackWalk.java +++ b/test/jdk/java/foreign/stackwalk/TestStackWalk.java @@ -25,6 +25,7 @@ * @test id=default_gc * @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64" * @library /test/lib + * @library ../ * @build sun.hotspot.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox * @@ -52,6 +53,7 @@ * @requires (((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64") * @requires vm.gc.Z * @library /test/lib + * @library ../ * @build sun.hotspot.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox * @@ -80,6 +82,7 @@ * @requires (((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64") * @requires vm.gc.Shenandoah * @library /test/lib + * @library ../ * @build sun.hotspot.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox * @@ -106,6 +109,7 @@ import jdk.incubator.foreign.CLinker; import jdk.incubator.foreign.FunctionDescriptor; +import jdk.incubator.foreign.NativeSymbol; import jdk.incubator.foreign.SymbolLookup; import jdk.incubator.foreign.MemoryAddress; @@ -117,12 +121,11 @@ import jdk.incubator.foreign.ResourceScope; import sun.hotspot.WhiteBox; import static java.lang.invoke.MethodHandles.lookup; -import static jdk.incubator.foreign.CLinker.C_POINTER; -public class TestStackWalk { +public class TestStackWalk extends NativeTestHelper { static final WhiteBox WB = WhiteBox.getWhiteBox(); - static final CLinker linker = CLinker.getInstance(); + static final CLinker linker = CLinker.systemCLinker(); static final MethodHandle MH_foo; static final MethodHandle MH_m; @@ -133,7 +136,6 @@ public class TestStackWalk { SymbolLookup lookup = SymbolLookup.loaderLookup(); MH_foo = linker.downcallHandle( lookup.lookup("foo").get(), - MethodType.methodType(void.class, MemoryAddress.class), FunctionDescriptor.ofVoid(C_POINTER)); MH_m = lookup().findStatic(TestStackWalk.class, "m", MethodType.methodType(void.class)); } catch (ReflectiveOperationException e) { @@ -145,7 +147,7 @@ public class TestStackWalk { public static void main(String[] args) throws Throwable { try (ResourceScope scope = ResourceScope.newConfinedScope()) { - MemoryAddress stub = linker.upcallStub(MH_m, FunctionDescriptor.ofVoid(), scope); + NativeSymbol stub = linker.upcallStub(MH_m, FunctionDescriptor.ofVoid(), scope); MemoryAddress stubAddress = stub.address(); armed = false; for (int i = 0; i < 20_000; i++) { @@ -158,7 +160,7 @@ public class TestStackWalk { } static void payload(MemoryAddress cb) throws Throwable { - MH_foo.invokeExact(cb); + MH_foo.invoke(cb); Reference.reachabilityFence(cb); // keep oop alive across call } diff --git a/test/jdk/java/foreign/upcalldeopt/TestUpcallDeopt.java b/test/jdk/java/foreign/upcalldeopt/TestUpcallDeopt.java new file mode 100644 index 0000000000000000000000000000000000000000..a8a09420344e6dfc61e1305dce9a0453d2e05087 --- /dev/null +++ b/test/jdk/java/foreign/upcalldeopt/TestUpcallDeopt.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test id=default_gc + * @bug 8277602 + * @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64" + * @library /test/lib + * @library ../ + * @build sun.hotspot.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox + * + * @run main/othervm + * -Xbootclasspath/a:. + * -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI + * --enable-native-access=ALL-UNNAMED + * -Xbatch + * TestUpcallDeopt + */ + +import jdk.incubator.foreign.Addressable; +import jdk.incubator.foreign.CLinker; +import jdk.incubator.foreign.FunctionDescriptor; +import jdk.incubator.foreign.NativeSymbol; +import jdk.incubator.foreign.SymbolLookup; +import jdk.incubator.foreign.MemoryAddress; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodType; +import java.lang.ref.Reference; + +import jdk.incubator.foreign.ResourceScope; +import sun.hotspot.WhiteBox; + +import static java.lang.invoke.MethodHandles.lookup; + +public class TestUpcallDeopt extends NativeTestHelper { + static final WhiteBox WB = WhiteBox.getWhiteBox(); + + static final CLinker linker = CLinker.systemCLinker(); + + static final MethodHandle MH_foo; + static final MethodHandle MH_m; + + static { + try { + System.loadLibrary("UpcallDeopt"); + SymbolLookup lookup = SymbolLookup.loaderLookup(); + MH_foo = linker.downcallHandle( + lookup.lookup("foo").orElseThrow(), + FunctionDescriptor.ofVoid(C_POINTER, C_INT, C_INT, C_INT, C_INT)); + MH_m = lookup().findStatic(TestUpcallDeopt.class, "m", + MethodType.methodType(void.class, int.class, int.class, int.class, int.class)); + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + } + + static boolean armed; + + // we need to deoptimize through an uncommon trap in the callee of the optimized upcall stub + // that is created when calling upcallStub below + public static void main(String[] args) throws Throwable { + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol stub = linker.upcallStub(MH_m, FunctionDescriptor.ofVoid(C_INT, C_INT, C_INT, C_INT), scope); + armed = false; + for (int i = 0; i < 20_000; i++) { + payload(stub); // warmup + } + + armed = true; + payload(stub); // test + } + } + + static void payload(NativeSymbol cb) throws Throwable { + MH_foo.invokeExact((Addressable) cb, 0, 1, 2, 3); + Reference.reachabilityFence(cb); // keep oop alive across call + } + + // Takes a bunch of arguments, even though unused, to test + // if the caller's frame is extended enough to spill these arguments. + static void m(int a0, int a1, int a2, int a3) { + if (armed) { + // Trigger uncommon trap from this frame + WB.verifyFrames(/*log=*/true, /*updateRegisterMap=*/true); + WB.verifyFrames(/*log=*/true, /*updateRegisterMap=*/false); // triggers different code paths + } + } + +} diff --git a/test/jdk/java/foreign/upcalldeopt/libUpcallDeopt.c b/test/jdk/java/foreign/upcalldeopt/libUpcallDeopt.c new file mode 100644 index 0000000000000000000000000000000000000000..ae2a8dc01731bd6a098bdaa8273eeef4165351ee --- /dev/null +++ b/test/jdk/java/foreign/upcalldeopt/libUpcallDeopt.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifdef _WIN64 +#define EXPORT __declspec(dllexport) +#else +#define EXPORT +#endif + +EXPORT void foo(void (*cb)(int, int, int, int), int a0, int a1, int a2, int a3) { + cb(a0, a1, a2, a3); +} diff --git a/test/jdk/java/foreign/valist/VaListTest.java b/test/jdk/java/foreign/valist/VaListTest.java index b2aac7d6dc8f6e4ab6c571ab95b446a6789448c2..9b48d361ed8f1b192d7cae0431b5002e5764a528 100644 --- a/test/jdk/java/foreign/valist/VaListTest.java +++ b/test/jdk/java/foreign/valist/VaListTest.java @@ -36,7 +36,7 @@ */ import jdk.incubator.foreign.*; -import jdk.incubator.foreign.CLinker.VaList; +import jdk.incubator.foreign.VaList; import jdk.internal.foreign.abi.aarch64.linux.LinuxAArch64Linker; import jdk.internal.foreign.abi.aarch64.macos.MacOsAArch64Linker; import jdk.internal.foreign.abi.x64.sysv.SysVx64Linker; @@ -55,59 +55,65 @@ import java.util.function.Function; import java.util.stream.DoubleStream; import java.util.stream.IntStream; -import static jdk.incubator.foreign.CLinker.C_DOUBLE; -import static jdk.incubator.foreign.CLinker.C_FLOAT; -import static jdk.incubator.foreign.CLinker.C_INT; -import static jdk.incubator.foreign.CLinker.C_LONG; -import static jdk.incubator.foreign.CLinker.C_LONG_LONG; -import static jdk.incubator.foreign.CLinker.C_POINTER; -import static jdk.incubator.foreign.CLinker.C_VA_LIST; import static jdk.incubator.foreign.MemoryLayout.PathElement.groupElement; -import static jdk.incubator.foreign.MemoryLayouts.JAVA_INT; +import static jdk.incubator.foreign.ValueLayout.JAVA_DOUBLE; +import static jdk.incubator.foreign.ValueLayout.JAVA_INT; +import static jdk.incubator.foreign.ValueLayout.JAVA_LONG; import static jdk.internal.foreign.PlatformLayouts.*; import static org.testng.Assert.*; public class VaListTest extends NativeTestHelper { - private static final CLinker abi = CLinker.getInstance(); + private static final CLinker abi = CLinker.systemCLinker(); static { System.loadLibrary("VaList"); } static final SymbolLookup LOOKUP = SymbolLookup.loaderLookup(); - private static final MethodHandle MH_sumInts = link("sumInts", - MethodType.methodType(int.class, int.class, VaList.class), - FunctionDescriptor.of(C_INT, C_INT, C_VA_LIST)); - private static final MethodHandle MH_sumDoubles = link("sumDoubles", - MethodType.methodType(double.class, int.class, VaList.class), - FunctionDescriptor.of(C_DOUBLE, C_INT, C_VA_LIST)); - private static final MethodHandle MH_getInt = link("getInt", - MethodType.methodType(int.class, VaList.class), - FunctionDescriptor.of(C_INT, C_VA_LIST)); - private static final MethodHandle MH_sumStruct = link("sumStruct", - MethodType.methodType(int.class, VaList.class), - FunctionDescriptor.of(C_INT, C_VA_LIST)); - private static final MethodHandle MH_sumBigStruct = link("sumBigStruct", - MethodType.methodType(long.class, VaList.class), - FunctionDescriptor.of(C_LONG_LONG, C_VA_LIST)); - private static final MethodHandle MH_sumHugeStruct = link("sumHugeStruct", - MethodType.methodType(long.class, VaList.class), - FunctionDescriptor.of(C_LONG_LONG, C_VA_LIST)); - private static final MethodHandle MH_sumFloatStruct = link("sumFloatStruct", - MethodType.methodType(float.class, VaList.class), - FunctionDescriptor.of(C_FLOAT, C_VA_LIST)); - private static final MethodHandle MH_sumStack = link("sumStack", - MethodType.methodType(void.class, MemoryAddress.class, MemoryAddress.class, VaList.class), - FunctionDescriptor.ofVoid(C_POINTER, C_POINTER, C_VA_LIST)); - - private static MethodHandle link(String symbol, MethodType mt, FunctionDescriptor fd) { - return abi.downcallHandle(LOOKUP.lookup(symbol).get(), mt, fd); + private static final MethodHandle ADDRESS_TO_VALIST; + + static { + try { + ADDRESS_TO_VALIST = MethodHandles.lookup().findStatic(VaList.class, "ofAddress", MethodType.methodType(VaList.class, MemoryAddress.class, ResourceScope.class)); + } catch (Throwable ex) { + throw new ExceptionInInitializerError(ex); + } + } + + + private static final MethodHandle MH_sumInts = linkVaList("sumInts", + FunctionDescriptor.of(C_INT, C_INT, C_POINTER)); + private static final MethodHandle MH_sumDoubles = linkVaList("sumDoubles", + FunctionDescriptor.of(C_DOUBLE, C_INT, C_POINTER)); + private static final MethodHandle MH_getInt = linkVaList("getInt", + FunctionDescriptor.of(C_INT, C_POINTER)); + private static final MethodHandle MH_sumStruct = linkVaList("sumStruct", + FunctionDescriptor.of(C_INT, C_POINTER)); + private static final MethodHandle MH_sumBigStruct = linkVaList("sumBigStruct", + FunctionDescriptor.of(C_LONG_LONG, C_POINTER)); + private static final MethodHandle MH_sumHugeStruct = linkVaList("sumHugeStruct", + FunctionDescriptor.of(C_LONG_LONG, C_POINTER)); + private static final MethodHandle MH_sumFloatStruct = linkVaList("sumFloatStruct", + FunctionDescriptor.of(C_FLOAT, C_POINTER)); + private static final MethodHandle MH_sumStack = linkVaList("sumStack", + FunctionDescriptor.ofVoid(C_POINTER, C_POINTER, C_POINTER)); + + private static MethodHandle link(String symbol, FunctionDescriptor fd) { + return linkInternal(symbol, fd); + } + + private static MethodHandle linkVaList(String symbol, FunctionDescriptor fd) { + return linkInternal(symbol, fd); + } + + + private static MethodHandle linkInternal(String symbol, FunctionDescriptor fd) { + return abi.downcallHandle(LOOKUP.lookup(symbol).get(), fd); } private static MethodHandle linkVaListCB(String symbol) { return link(symbol, - MethodType.methodType(void.class, MemoryAddress.class), FunctionDescriptor.ofVoid(C_POINTER)); } @@ -123,22 +129,22 @@ public class VaListTest extends NativeTestHelper { private static final Function<Consumer<VaList.Builder>, VaList> platformVaListFactory = (builder) -> VaList.make(builder, ResourceScope.newConfinedScope()); - private static final BiFunction<Consumer<VaList.Builder>, NativeScope, VaList> winVaListScopedFactory - = (builder, scope) -> Windowsx64Linker.newVaList(builder, scope.scope()); - private static final BiFunction<Consumer<VaList.Builder>, NativeScope, VaList> sysvVaListScopedFactory - = (builder, scope) -> SysVx64Linker.newVaList(builder, scope.scope()); - private static final BiFunction<Consumer<VaList.Builder>, NativeScope, VaList> linuxAArch64VaListScopedFactory - = (builder, scope) -> LinuxAArch64Linker.newVaList(builder, scope.scope()); - private static final BiFunction<Consumer<VaList.Builder>, NativeScope, VaList> macAArch64VaListScopedFactory - = (builder, scope) -> MacOsAArch64Linker.newVaList(builder, scope.scope()); - private static final BiFunction<Consumer<VaList.Builder>, NativeScope, VaList> platformVaListScopedFactory - = (builder, scope) -> VaList.make(builder, scope.scope()); + private static final BiFunction<Consumer<VaList.Builder>, ResourceScope, VaList> winVaListScopedFactory + = (builder, scope) -> Windowsx64Linker.newVaList(builder, scope); + private static final BiFunction<Consumer<VaList.Builder>, ResourceScope, VaList> sysvVaListScopedFactory + = (builder, scope) -> SysVx64Linker.newVaList(builder, scope); + private static final BiFunction<Consumer<VaList.Builder>, ResourceScope, VaList> linuxAArch64VaListScopedFactory + = (builder, scope) -> LinuxAArch64Linker.newVaList(builder, scope); + private static final BiFunction<Consumer<VaList.Builder>, ResourceScope, VaList> macAArch64VaListScopedFactory + = (builder, scope) -> MacOsAArch64Linker.newVaList(builder, scope); + private static final BiFunction<Consumer<VaList.Builder>, ResourceScope, VaList> platformVaListScopedFactory + = (builder, scope) -> VaList.make(builder, scope); @DataProvider @SuppressWarnings("unchecked") public static Object[][] sumInts() { - Function<MemoryLayout, BiFunction<Integer, VaList, Integer>> sumIntsJavaFact = layout -> - (num, list) -> IntStream.generate(() -> list.vargAsInt(layout)).limit(num).sum(); + Function<ValueLayout.OfInt, BiFunction<Integer, VaList, Integer>> sumIntsJavaFact = layout -> + (num, list) -> IntStream.generate(() -> list.nextVarg(layout)).limit(num).sum(); BiFunction<Integer, VaList, Integer> sumIntsNative = MethodHandleProxies.asInterfaceInstance(BiFunction.class, MH_sumInts); return new Object[][]{ @@ -153,11 +159,11 @@ public class VaListTest extends NativeTestHelper { @Test(dataProvider = "sumInts") public void testIntSum(Function<Consumer<VaList.Builder>, VaList> vaListFactory, BiFunction<Integer, VaList, Integer> sumInts, - ValueLayout intLayout) { + ValueLayout.OfInt intLayout) { VaList vaList = vaListFactory.apply(b -> - b.vargFromInt(intLayout, 10) - .vargFromInt(intLayout, 15) - .vargFromInt(intLayout, 20)); + b.addVarg(intLayout, 10) + .addVarg(intLayout, 15) + .addVarg(intLayout, 20)); int x = sumInts.apply(3, vaList); assertEquals(x, 45); vaList.scope().close(); @@ -166,8 +172,8 @@ public class VaListTest extends NativeTestHelper { @DataProvider @SuppressWarnings("unchecked") public static Object[][] sumDoubles() { - Function<MemoryLayout, BiFunction<Integer, VaList, Double>> sumDoublesJavaFact = layout -> - (num, list) -> DoubleStream.generate(() -> list.vargAsDouble(layout)).limit(num).sum(); + Function<ValueLayout.OfDouble, BiFunction<Integer, VaList, Double>> sumDoublesJavaFact = layout -> + (num, list) -> DoubleStream.generate(() -> list.nextVarg(layout)).limit(num).sum(); BiFunction<Integer, VaList, Double> sumDoublesNative = MethodHandleProxies.asInterfaceInstance(BiFunction.class, MH_sumDoubles); return new Object[][]{ @@ -182,11 +188,11 @@ public class VaListTest extends NativeTestHelper { @Test(dataProvider = "sumDoubles") public void testDoubleSum(Function<Consumer<VaList.Builder>, VaList> vaListFactory, BiFunction<Integer, VaList, Double> sumDoubles, - ValueLayout doubleLayout) { + ValueLayout.OfDouble doubleLayout) { VaList vaList = vaListFactory.apply(b -> - b.vargFromDouble(doubleLayout, 3.0D) - .vargFromDouble(doubleLayout, 4.0D) - .vargFromDouble(doubleLayout, 5.0D)); + b.addVarg(doubleLayout, 3.0D) + .addVarg(doubleLayout, 4.0D) + .addVarg(doubleLayout, 5.0D)); double x = sumDoubles.apply(3, vaList); assertEquals(x, 12.0D); vaList.scope().close(); @@ -195,10 +201,10 @@ public class VaListTest extends NativeTestHelper { @DataProvider @SuppressWarnings("unchecked") public static Object[][] pointers() { - Function<MemoryLayout, Function<VaList, Integer>> getIntJavaFact = layout -> + Function<ValueLayout.OfAddress, Function<VaList, Integer>> getIntJavaFact = layout -> list -> { - MemoryAddress ma = list.vargAsAddress(layout); - return MemoryAccess.getIntAtOffset(MemorySegment.globalNativeSegment(), ma.toRawLongValue()); + MemoryAddress ma = list.nextVarg(layout); + return ma.get(JAVA_INT, 0); }; Function<VaList, Integer> getIntNative = MethodHandleProxies.asInterfaceInstance(Function.class, MH_getInt); return new Object[][]{ @@ -213,11 +219,11 @@ public class VaListTest extends NativeTestHelper { @Test(dataProvider = "pointers") public void testVaListMemoryAddress(Function<Consumer<VaList.Builder>, VaList> vaListFactory, Function<VaList, Integer> getFromPointer, - ValueLayout pointerLayout) { + ValueLayout.OfAddress pointerLayout) { try (ResourceScope scope = ResourceScope.newConfinedScope()) { MemorySegment msInt = MemorySegment.allocateNative(JAVA_INT, scope); - MemoryAccess.setInt(msInt, 10); - VaList vaList = vaListFactory.apply(b -> b.vargFromAddress(pointerLayout, msInt.address())); + msInt.set(JAVA_INT, 0, 10); + VaList vaList = vaListFactory.apply(b -> b.addVarg(pointerLayout, msInt.address())); int x = getFromPointer.apply(vaList); assertEquals(x, 10); vaList.scope().close(); @@ -231,28 +237,29 @@ public class VaListTest extends NativeTestHelper { @DataProvider @SuppressWarnings("unchecked") public static Object[][] structs() { - TriFunction<MemoryLayout, VarHandle, VarHandle, Function<VaList, Integer>> sumStructJavaFact + TriFunction<GroupLayout, VarHandle, VarHandle, Function<VaList, Integer>> sumStructJavaFact = (pointLayout, VH_Point_x, VH_Point_y) -> list -> { - MemorySegment struct = list.vargAsSegment(pointLayout, ResourceScope.newImplicitScope()); + MemorySegment struct = MemorySegment.allocateNative(pointLayout, ResourceScope.newImplicitScope()); + list.nextVarg(pointLayout, SegmentAllocator.prefixAllocator(struct)); int x = (int) VH_Point_x.get(struct); int y = (int) VH_Point_y.get(struct); return x + y; }; - TriFunction<MemoryLayout, VarHandle, VarHandle, Function<VaList, Integer>> sumStructNativeFact + TriFunction<GroupLayout, VarHandle, VarHandle, Function<VaList, Integer>> sumStructNativeFact = (pointLayout, VH_Point_x, VH_Point_y) -> MethodHandleProxies.asInterfaceInstance(Function.class, MH_sumStruct); TriFunction<Function<Consumer<VaList.Builder>, VaList>, MemoryLayout, - TriFunction<MemoryLayout, VarHandle, VarHandle, Function<VaList, Integer>>, Object[]> argsFact + TriFunction<GroupLayout, VarHandle, VarHandle, Function<VaList, Integer>>, Object[]> argsFact = (vaListFact, intLayout, sumStructFact) -> { GroupLayout pointLayout = MemoryLayout.structLayout( intLayout.withName("x"), intLayout.withName("y") ); - VarHandle VH_Point_x = pointLayout.varHandle(int.class, groupElement("x")); - VarHandle VH_Point_y = pointLayout.varHandle(int.class, groupElement("y")); + VarHandle VH_Point_x = pointLayout.varHandle(groupElement("x")); + VarHandle VH_Point_y = pointLayout.varHandle(groupElement("y")); return new Object[] { vaListFact, sumStructFact.apply(pointLayout, VH_Point_x, VH_Point_y), pointLayout, VH_Point_x, VH_Point_y }; }; @@ -274,7 +281,7 @@ public class VaListTest extends NativeTestHelper { VH_Point_x.set(struct, 5); VH_Point_y.set(struct, 10); - VaList vaList = vaListFactory.apply(b -> b.vargFromSegment(Point_LAYOUT, struct)); + VaList vaList = vaListFactory.apply(b -> b.addVarg(Point_LAYOUT, struct)); int sum = sumStruct.apply(vaList); assertEquals(sum, 15); vaList.scope().close(); @@ -284,28 +291,29 @@ public class VaListTest extends NativeTestHelper { @DataProvider @SuppressWarnings("unchecked") public static Object[][] bigStructs() { - TriFunction<MemoryLayout, VarHandle, VarHandle, Function<VaList, Long>> sumStructJavaFact + TriFunction<GroupLayout, VarHandle, VarHandle, Function<VaList, Long>> sumStructJavaFact = (BigPoint_LAYOUT, VH_BigPoint_x, VH_BigPoint_y) -> list -> { - MemorySegment struct = list.vargAsSegment(BigPoint_LAYOUT, ResourceScope.newImplicitScope()); + MemorySegment struct = MemorySegment.allocateNative(BigPoint_LAYOUT, ResourceScope.newImplicitScope()); + list.nextVarg(BigPoint_LAYOUT, SegmentAllocator.prefixAllocator(struct)); long x = (long) VH_BigPoint_x.get(struct); long y = (long) VH_BigPoint_y.get(struct); return x + y; }; - TriFunction<MemoryLayout, VarHandle, VarHandle, Function<VaList, Long>> sumStructNativeFact + TriFunction<GroupLayout, VarHandle, VarHandle, Function<VaList, Long>> sumStructNativeFact = (pointLayout, VH_BigPoint_x, VH_BigPoint_y) -> MethodHandleProxies.asInterfaceInstance(Function.class, MH_sumBigStruct); TriFunction<Function<Consumer<VaList.Builder>, VaList>, MemoryLayout, - TriFunction<MemoryLayout, VarHandle, VarHandle, Function<VaList, Long>>, Object[]> argsFact + TriFunction<GroupLayout, VarHandle, VarHandle, Function<VaList, Long>>, Object[]> argsFact = (vaListFact, longLongLayout, sumBigStructFact) -> { GroupLayout BigPoint_LAYOUT = MemoryLayout.structLayout( longLongLayout.withName("x"), longLongLayout.withName("y") ); - VarHandle VH_BigPoint_x = BigPoint_LAYOUT.varHandle(long.class, groupElement("x")); - VarHandle VH_BigPoint_y = BigPoint_LAYOUT.varHandle(long.class, groupElement("y")); + VarHandle VH_BigPoint_x = BigPoint_LAYOUT.varHandle(groupElement("x")); + VarHandle VH_BigPoint_y = BigPoint_LAYOUT.varHandle(groupElement("y")); return new Object[] { vaListFact, sumBigStructFact.apply(BigPoint_LAYOUT, VH_BigPoint_x, VH_BigPoint_y), BigPoint_LAYOUT, VH_BigPoint_x, VH_BigPoint_y }; }; @@ -327,7 +335,7 @@ public class VaListTest extends NativeTestHelper { VH_BigPoint_x.set(struct, 5); VH_BigPoint_y.set(struct, 10); - VaList vaList = vaListFactory.apply(b -> b.vargFromSegment(BigPoint_LAYOUT, struct)); + VaList vaList = vaListFactory.apply(b -> b.addVarg(BigPoint_LAYOUT, struct)); long sum = sumBigStruct.apply(vaList); assertEquals(sum, 15); vaList.scope().close(); @@ -337,28 +345,29 @@ public class VaListTest extends NativeTestHelper { @DataProvider @SuppressWarnings("unchecked") public static Object[][] floatStructs() { - TriFunction<MemoryLayout, VarHandle, VarHandle, Function<VaList, Float>> sumStructJavaFact + TriFunction<GroupLayout, VarHandle, VarHandle, Function<VaList, Float>> sumStructJavaFact = (FloatPoint_LAYOUT, VH_FloatPoint_x, VH_FloatPoint_y) -> list -> { - MemorySegment struct = list.vargAsSegment(FloatPoint_LAYOUT, ResourceScope.newImplicitScope()); + MemorySegment struct = MemorySegment.allocateNative(FloatPoint_LAYOUT, ResourceScope.newImplicitScope()); + list.nextVarg(FloatPoint_LAYOUT, SegmentAllocator.prefixAllocator(struct)); float x = (float) VH_FloatPoint_x.get(struct); float y = (float) VH_FloatPoint_y.get(struct); return x + y; }; - TriFunction<MemoryLayout, VarHandle, VarHandle, Function<VaList, Float>> sumStructNativeFact + TriFunction<GroupLayout, VarHandle, VarHandle, Function<VaList, Float>> sumStructNativeFact = (pointLayout, VH_FloatPoint_x, VH_FloatPoint_y) -> MethodHandleProxies.asInterfaceInstance(Function.class, MH_sumFloatStruct); TriFunction<Function<Consumer<VaList.Builder>, VaList>, MemoryLayout, - TriFunction<MemoryLayout, VarHandle, VarHandle, Function<VaList, Float>>, Object[]> argsFact + TriFunction<GroupLayout, VarHandle, VarHandle, Function<VaList, Float>>, Object[]> argsFact = (vaListFact, floatLayout, sumFloatStructFact) -> { GroupLayout FloatPoint_LAYOUT = MemoryLayout.structLayout( floatLayout.withName("x"), floatLayout.withName("y") ); - VarHandle VH_FloatPoint_x = FloatPoint_LAYOUT.varHandle(float.class, groupElement("x")); - VarHandle VH_FloatPoint_y = FloatPoint_LAYOUT.varHandle(float.class, groupElement("y")); + VarHandle VH_FloatPoint_x = FloatPoint_LAYOUT.varHandle(groupElement("x")); + VarHandle VH_FloatPoint_y = FloatPoint_LAYOUT.varHandle(groupElement("y")); return new Object[] { vaListFact, sumFloatStructFact.apply(FloatPoint_LAYOUT, VH_FloatPoint_x, VH_FloatPoint_y), FloatPoint_LAYOUT, VH_FloatPoint_x, VH_FloatPoint_y }; }; @@ -381,7 +390,7 @@ public class VaListTest extends NativeTestHelper { VH_FloatPoint_x.set(struct, 1.234f); VH_FloatPoint_y.set(struct, 3.142f); - VaList vaList = vaListFactory.apply(b -> b.vargFromSegment(FloatPoint_LAYOUT, struct)); + VaList vaList = vaListFactory.apply(b -> b.addVarg(FloatPoint_LAYOUT, struct)); float sum = sumFloatStruct.apply(vaList); assertEquals(sum, 4.376f, 0.00001f); vaList.scope().close(); @@ -395,31 +404,32 @@ public class VaListTest extends NativeTestHelper { @DataProvider @SuppressWarnings("unchecked") public static Object[][] hugeStructs() { - QuadFunc<MemoryLayout, VarHandle, VarHandle, VarHandle, Function<VaList, Long>> sumStructJavaFact + QuadFunc<GroupLayout, VarHandle, VarHandle, VarHandle, Function<VaList, Long>> sumStructJavaFact = (HugePoint_LAYOUT, VH_HugePoint_x, VH_HugePoint_y, VH_HugePoint_z) -> list -> { - MemorySegment struct = list.vargAsSegment(HugePoint_LAYOUT, ResourceScope.newImplicitScope()); + MemorySegment struct = MemorySegment.allocateNative(HugePoint_LAYOUT, ResourceScope.newImplicitScope()); + list.nextVarg(HugePoint_LAYOUT, SegmentAllocator.prefixAllocator(struct)); long x = (long) VH_HugePoint_x.get(struct); long y = (long) VH_HugePoint_y.get(struct); long z = (long) VH_HugePoint_z.get(struct); return x + y + z; }; - QuadFunc<MemoryLayout, VarHandle, VarHandle, VarHandle, Function<VaList, Long>> sumStructNativeFact + QuadFunc<GroupLayout, VarHandle, VarHandle, VarHandle, Function<VaList, Long>> sumStructNativeFact = (pointLayout, VH_HugePoint_x, VH_HugePoint_y, VH_HugePoint_z) -> MethodHandleProxies.asInterfaceInstance(Function.class, MH_sumHugeStruct); TriFunction<Function<Consumer<VaList.Builder>, VaList>, MemoryLayout, - QuadFunc<MemoryLayout, VarHandle, VarHandle, VarHandle, Function<VaList, Long>>, Object[]> argsFact + QuadFunc<GroupLayout, VarHandle, VarHandle, VarHandle, Function<VaList, Long>>, Object[]> argsFact = (vaListFact, longLongLayout, sumBigStructFact) -> { GroupLayout HugePoint_LAYOUT = MemoryLayout.structLayout( longLongLayout.withName("x"), longLongLayout.withName("y"), longLongLayout.withName("z") ); - VarHandle VH_HugePoint_x = HugePoint_LAYOUT.varHandle(long.class, groupElement("x")); - VarHandle VH_HugePoint_y = HugePoint_LAYOUT.varHandle(long.class, groupElement("y")); - VarHandle VH_HugePoint_z = HugePoint_LAYOUT.varHandle(long.class, groupElement("z")); + VarHandle VH_HugePoint_x = HugePoint_LAYOUT.varHandle(groupElement("x")); + VarHandle VH_HugePoint_y = HugePoint_LAYOUT.varHandle(groupElement("y")); + VarHandle VH_HugePoint_z = HugePoint_LAYOUT.varHandle(groupElement("z")); return new Object[] { vaListFact, sumBigStructFact.apply(HugePoint_LAYOUT, VH_HugePoint_x, VH_HugePoint_y, VH_HugePoint_z), HugePoint_LAYOUT, VH_HugePoint_x, VH_HugePoint_y, VH_HugePoint_z }; @@ -446,7 +456,7 @@ public class VaListTest extends NativeTestHelper { VH_HugePoint_y.set(struct, 2); VH_HugePoint_z.set(struct, 3); - VaList vaList = vaListFactory.apply(b -> b.vargFromSegment(HugePoint_LAYOUT, struct)); + VaList vaList = vaListFactory.apply(b -> b.addVarg(HugePoint_LAYOUT, struct)); long sum = sumHugeStruct.apply(vaList); assertEquals(sum, 6); vaList.scope().close(); @@ -459,22 +469,22 @@ public class VaListTest extends NativeTestHelper { @DataProvider public static Object[][] sumStack() { - BiFunction<MemoryLayout, MemoryLayout, SumStackFunc> sumStackJavaFact = (longLayout, doubleLayout) -> + BiFunction<ValueLayout.OfLong, ValueLayout.OfDouble, SumStackFunc> sumStackJavaFact = (longLayout, doubleLayout) -> (longSum, doubleSum, list) -> { long lSum = 0L; for (int i = 0; i < 16; i++) { - lSum += list.vargAsLong(longLayout); + lSum += list.nextVarg(longLayout); } - MemoryAccess.setLong(longSum, lSum); + longSum.set(JAVA_LONG, 0, lSum); double dSum = 0D; for (int i = 0; i < 16; i++) { - dSum += list.vargAsDouble(doubleLayout); + dSum += list.nextVarg(doubleLayout); } - MemoryAccess.setDouble(doubleSum, dSum); + doubleSum.set(JAVA_DOUBLE, 0, dSum); }; SumStackFunc sumStackNative = (longSum, doubleSum, list) -> { try { - MH_sumStack.invokeExact(longSum.address(), doubleSum.address(), list); + MH_sumStack.invoke(longSum, doubleSum, list); } catch (Throwable ex) { throw new AssertionError(ex); } @@ -491,20 +501,20 @@ public class VaListTest extends NativeTestHelper { @Test(dataProvider = "sumStack") public void testStack(Function<Consumer<VaList.Builder>, VaList> vaListFactory, SumStackFunc sumStack, - ValueLayout longLayout, - ValueLayout doubleLayout) { + ValueLayout.OfLong longLayout, + ValueLayout.OfDouble doubleLayout) { try (ResourceScope scope = ResourceScope.newConfinedScope()) { MemorySegment longSum = MemorySegment.allocateNative(longLayout, scope); MemorySegment doubleSum = MemorySegment.allocateNative(doubleLayout, scope); - MemoryAccess.setLong(longSum, 0L); - MemoryAccess.setDouble(doubleSum, 0D); + longSum.set(JAVA_LONG, 0, 0L); + doubleSum.set(JAVA_DOUBLE, 0, 0D); VaList list = vaListFactory.apply(b -> { for (long l = 1; l <= 16L; l++) { - b.vargFromLong(longLayout, l); + b.addVarg(longLayout, l); } for (double d = 1; d <= 16D; d++) { - b.vargFromDouble(doubleLayout, d); + b.addVarg(doubleLayout, d); } }); @@ -514,8 +524,8 @@ public class VaListTest extends NativeTestHelper { list.scope().close(); } - long lSum = MemoryAccess.getLong(longSum); - double dSum = MemoryAccess.getDouble(doubleSum); + long lSum = longSum.get(JAVA_LONG, 0); + double dSum = doubleSum.get(JAVA_DOUBLE, 0); assertEquals(lSum, 136L); assertEquals(dSum, 136D); @@ -524,10 +534,10 @@ public class VaListTest extends NativeTestHelper { @Test(dataProvider = "upcalls") public void testUpcall(MethodHandle target, MethodHandle callback) throws Throwable { - FunctionDescriptor desc = FunctionDescriptor.ofVoid(C_VA_LIST); + FunctionDescriptor desc = FunctionDescriptor.ofVoid(C_POINTER); try (ResourceScope scope = ResourceScope.newConfinedScope()) { - MemoryAddress stub = abi.upcallStub(callback, desc, scope); - target.invokeExact(stub.address()); + NativeSymbol stub = abi.upcallStub(callback, desc, scope); + target.invoke(stub); } } @@ -555,8 +565,8 @@ public class VaListTest extends NativeTestHelper { @DataProvider @SuppressWarnings("unchecked") public static Object[][] sumIntsScoped() { - Function<MemoryLayout, BiFunction<Integer, VaList, Integer>> sumIntsJavaFact = layout -> - (num, list) -> IntStream.generate(() -> list.vargAsInt(layout)).limit(num).sum(); + Function<ValueLayout.OfInt, BiFunction<Integer, VaList, Integer>> sumIntsJavaFact = layout -> + (num, list) -> IntStream.generate(() -> list.nextVarg(layout)).limit(num).sum(); BiFunction<Integer, VaList, Integer> sumIntsNative = MethodHandleProxies.asInterfaceInstance(BiFunction.class, MH_sumInts); return new Object[][]{ @@ -569,14 +579,13 @@ public class VaListTest extends NativeTestHelper { } @Test(dataProvider = "sumIntsScoped") - public void testScopedVaList(BiFunction<Consumer<VaList.Builder>, NativeScope, VaList> vaListFactory, + public void testScopedVaList(BiFunction<Consumer<VaList.Builder>, ResourceScope, VaList> vaListFactory, BiFunction<Integer, VaList, Integer> sumInts, - ValueLayout intLayout) { + ValueLayout.OfInt intLayout) { VaList listLeaked; - try (NativeScope scope = new NativeScope()) { - VaList list = vaListFactory.apply(b -> b.vargFromInt(intLayout, 4) - .vargFromInt(intLayout, 8), - scope); + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + VaList list = vaListFactory.apply(b -> b.addVarg(intLayout, 4) + .addVarg(intLayout, 8), scope); int x = sumInts.apply(2, list); assertEquals(x, 12); listLeaked = list; @@ -589,13 +598,14 @@ public class VaListTest extends NativeTestHelper { Function<VaList, Integer> sumStruct, // ignored GroupLayout Point_LAYOUT, VarHandle VH_Point_x, VarHandle VH_Point_y) { MemorySegment pointOut; - try (NativeScope scope = new NativeScope()) { + try (ResourceScope scope = ResourceScope.newConfinedScope()) { try (ResourceScope innerScope = ResourceScope.newConfinedScope()) { MemorySegment pointIn = MemorySegment.allocateNative(Point_LAYOUT, innerScope); VH_Point_x.set(pointIn, 3); VH_Point_y.set(pointIn, 6); - VaList list = vaListFactory.apply(b -> b.vargFromSegment(Point_LAYOUT, pointIn)); - pointOut = list.vargAsSegment(Point_LAYOUT, scope); + VaList list = vaListFactory.apply(b -> b.addVarg(Point_LAYOUT, pointIn)); + pointOut = MemorySegment.allocateNative(Point_LAYOUT, scope); + list.nextVarg(Point_LAYOUT, SegmentAllocator.prefixAllocator(pointOut)); assertEquals((int) VH_Point_x.get(pointOut), 3); assertEquals((int) VH_Point_y.get(pointOut), 6); list.scope().close(); @@ -617,12 +627,12 @@ public class VaListTest extends NativeTestHelper { } @Test(dataProvider = "copy") - public void testCopy(Function<Consumer<VaList.Builder>, VaList> vaListFactory, ValueLayout intLayout) { - VaList list = vaListFactory.apply(b -> b.vargFromInt(intLayout, 4) - .vargFromInt(intLayout, 8)); + public void testCopy(Function<Consumer<VaList.Builder>, VaList> vaListFactory, ValueLayout.OfInt intLayout) { + VaList list = vaListFactory.apply(b -> b.addVarg(intLayout, 4) + .addVarg(intLayout, 8)); VaList copy = list.copy(); - assertEquals(copy.vargAsInt(intLayout), 4); - assertEquals(copy.vargAsInt(intLayout), 8); + assertEquals(copy.nextVarg(intLayout), 4); + assertEquals(copy.nextVarg(intLayout), 8); // try { // this logic only works on Windows! // int x = copy.vargAsInt(intLayout); @@ -631,21 +641,21 @@ public class VaListTest extends NativeTestHelper { // // ok - we exhausted the list // } - assertEquals(list.vargAsInt(intLayout), 4); - assertEquals(list.vargAsInt(intLayout), 8); + assertEquals(list.nextVarg(intLayout), 4); + assertEquals(list.nextVarg(intLayout), 8); list.scope().close(); } @Test(dataProvider = "copy", expectedExceptions = IllegalStateException.class) public void testCopyUnusableAfterOriginalClosed(Function<Consumer<VaList.Builder>, VaList> vaListFactory, - ValueLayout intLayout) { - VaList list = vaListFactory.apply(b -> b.vargFromInt(intLayout, 4) - .vargFromInt(intLayout, 8)); + ValueLayout.OfInt intLayout) { + VaList list = vaListFactory.apply(b -> b.addVarg(intLayout, 4) + .addVarg(intLayout, 8)); VaList copy = list.copy(); list.scope().close(); - copy.vargAsInt(intLayout); // should throw + copy.nextVarg(intLayout); // should throw } @DataProvider @@ -654,38 +664,40 @@ public class VaListTest extends NativeTestHelper { C_LONG_LONG.withName("x"), C_LONG_LONG.withName("y") ); - VarHandle VH_BigPoint_x = BigPoint_LAYOUT.varHandle(long.class, groupElement("x")); - VarHandle VH_BigPoint_y = BigPoint_LAYOUT.varHandle(long.class, groupElement("y")); + VarHandle VH_BigPoint_x = BigPoint_LAYOUT.varHandle(groupElement("x")); + VarHandle VH_BigPoint_y = BigPoint_LAYOUT.varHandle(groupElement("y")); GroupLayout Point_LAYOUT = MemoryLayout.structLayout( C_INT.withName("x"), C_INT.withName("y") ); - VarHandle VH_Point_x = Point_LAYOUT.varHandle(int.class, groupElement("x")); - VarHandle VH_Point_y = Point_LAYOUT.varHandle(int.class, groupElement("y")); + VarHandle VH_Point_x = Point_LAYOUT.varHandle(groupElement("x")); + VarHandle VH_Point_y = Point_LAYOUT.varHandle(groupElement("y")); GroupLayout FloatPoint_LAYOUT = MemoryLayout.structLayout( C_FLOAT.withName("x"), C_FLOAT.withName("y") ); - VarHandle VH_FloatPoint_x = FloatPoint_LAYOUT.varHandle(float.class, groupElement("x")); - VarHandle VH_FloatPoint_y = FloatPoint_LAYOUT.varHandle(float.class, groupElement("y")); + VarHandle VH_FloatPoint_x = FloatPoint_LAYOUT.varHandle(groupElement("x")); + VarHandle VH_FloatPoint_y = FloatPoint_LAYOUT.varHandle(groupElement("y")); GroupLayout HugePoint_LAYOUT = MemoryLayout.structLayout( C_LONG_LONG.withName("x"), C_LONG_LONG.withName("y"), C_LONG_LONG.withName("z") ); - VarHandle VH_HugePoint_x = HugePoint_LAYOUT.varHandle(long.class, groupElement("x")); - VarHandle VH_HugePoint_y = HugePoint_LAYOUT.varHandle(long.class, groupElement("y")); - VarHandle VH_HugePoint_z = HugePoint_LAYOUT.varHandle(long.class, groupElement("z")); + VarHandle VH_HugePoint_x = HugePoint_LAYOUT.varHandle(groupElement("x")); + VarHandle VH_HugePoint_y = HugePoint_LAYOUT.varHandle(groupElement("y")); + VarHandle VH_HugePoint_z = HugePoint_LAYOUT.varHandle(groupElement("z")); return new Object[][]{ { linkVaListCB("upcallBigStruct"), VaListConsumer.mh(vaList -> { - MemorySegment struct = vaList.vargAsSegment(BigPoint_LAYOUT, ResourceScope.newImplicitScope()); + MemorySegment struct = MemorySegment.allocateNative(BigPoint_LAYOUT, ResourceScope.newImplicitScope()); + vaList.nextVarg(BigPoint_LAYOUT, SegmentAllocator.prefixAllocator(struct)); assertEquals((long) VH_BigPoint_x.get(struct), 8); assertEquals((long) VH_BigPoint_y.get(struct), 16); })}, { linkVaListCB("upcallBigStruct"), VaListConsumer.mh(vaList -> { VaList copy = vaList.copy(); - MemorySegment struct = vaList.vargAsSegment(BigPoint_LAYOUT, ResourceScope.newImplicitScope()); + MemorySegment struct = MemorySegment.allocateNative(BigPoint_LAYOUT, ResourceScope.newImplicitScope()); + vaList.nextVarg(BigPoint_LAYOUT, SegmentAllocator.prefixAllocator(struct)); assertEquals((long) VH_BigPoint_x.get(struct), 8); assertEquals((long) VH_BigPoint_y.get(struct), 16); @@ -693,84 +705,91 @@ public class VaListTest extends NativeTestHelper { VH_BigPoint_y.set(struct, 0); // should be independent - struct = copy.vargAsSegment(BigPoint_LAYOUT, ResourceScope.newImplicitScope()); + copy.nextVarg(BigPoint_LAYOUT, SegmentAllocator.prefixAllocator(struct)); assertEquals((long) VH_BigPoint_x.get(struct), 8); assertEquals((long) VH_BigPoint_y.get(struct), 16); })}, { linkVaListCB("upcallBigStructPlusScalar"), VaListConsumer.mh(vaList -> { - MemorySegment struct = vaList.vargAsSegment(BigPoint_LAYOUT, ResourceScope.newImplicitScope()); + MemorySegment struct = MemorySegment.allocateNative(BigPoint_LAYOUT, ResourceScope.newImplicitScope()); + vaList.nextVarg(BigPoint_LAYOUT, SegmentAllocator.prefixAllocator(struct)); assertEquals((long) VH_BigPoint_x.get(struct), 8); assertEquals((long) VH_BigPoint_y.get(struct), 16); - assertEquals(vaList.vargAsLong(C_LONG_LONG), 42); + assertEquals(vaList.nextVarg(C_LONG_LONG), 42); })}, { linkVaListCB("upcallBigStructPlusScalar"), VaListConsumer.mh(vaList -> { vaList.skip(BigPoint_LAYOUT); - assertEquals(vaList.vargAsLong(C_LONG_LONG), 42); + assertEquals(vaList.nextVarg(C_LONG_LONG), 42); })}, { linkVaListCB("upcallStruct"), VaListConsumer.mh(vaList -> { - MemorySegment struct = vaList.vargAsSegment(Point_LAYOUT, ResourceScope.newImplicitScope()); + MemorySegment struct = MemorySegment.allocateNative(Point_LAYOUT, ResourceScope.newImplicitScope()); + vaList.nextVarg(Point_LAYOUT, SegmentAllocator.prefixAllocator(struct)); assertEquals((int) VH_Point_x.get(struct), 5); assertEquals((int) VH_Point_y.get(struct), 10); })}, { linkVaListCB("upcallHugeStruct"), VaListConsumer.mh(vaList -> { - MemorySegment struct = vaList.vargAsSegment(HugePoint_LAYOUT, ResourceScope.newImplicitScope()); + MemorySegment struct = MemorySegment.allocateNative(HugePoint_LAYOUT, ResourceScope.newImplicitScope()); + vaList.nextVarg(HugePoint_LAYOUT, SegmentAllocator.prefixAllocator(struct)); assertEquals((long) VH_HugePoint_x.get(struct), 1); assertEquals((long) VH_HugePoint_y.get(struct), 2); assertEquals((long) VH_HugePoint_z.get(struct), 3); })}, { linkVaListCB("upcallFloatStruct"), VaListConsumer.mh(vaList -> { - MemorySegment struct = vaList.vargAsSegment(FloatPoint_LAYOUT, ResourceScope.newImplicitScope()); + MemorySegment struct = MemorySegment.allocateNative(FloatPoint_LAYOUT, ResourceScope.newImplicitScope()); + vaList.nextVarg(FloatPoint_LAYOUT, SegmentAllocator.prefixAllocator(struct)); assertEquals((float) VH_FloatPoint_x.get(struct), 1.0f); assertEquals((float) VH_FloatPoint_y.get(struct), 2.0f); })}, { linkVaListCB("upcallMemoryAddress"), VaListConsumer.mh(vaList -> { - MemoryAddress intPtr = vaList.vargAsAddress(C_POINTER); - MemorySegment ms = intPtr.asSegment(C_INT.byteSize(), ResourceScope.globalScope()); - int x = MemoryAccess.getInt(ms); + MemoryAddress intPtr = vaList.nextVarg(C_POINTER); + MemorySegment ms = MemorySegment.ofAddress(intPtr, C_INT.byteSize(), ResourceScope.globalScope()); + int x = ms.get(JAVA_INT, 0); assertEquals(x, 10); })}, { linkVaListCB("upcallDoubles"), VaListConsumer.mh(vaList -> { - assertEquals(vaList.vargAsDouble(C_DOUBLE), 3.0); - assertEquals(vaList.vargAsDouble(C_DOUBLE), 4.0); - assertEquals(vaList.vargAsDouble(C_DOUBLE), 5.0); + assertEquals(vaList.nextVarg(C_DOUBLE), 3.0); + assertEquals(vaList.nextVarg(C_DOUBLE), 4.0); + assertEquals(vaList.nextVarg(C_DOUBLE), 5.0); })}, { linkVaListCB("upcallInts"), VaListConsumer.mh(vaList -> { - assertEquals(vaList.vargAsInt(C_INT), 10); - assertEquals(vaList.vargAsInt(C_INT), 15); - assertEquals(vaList.vargAsInt(C_INT), 20); + assertEquals(vaList.nextVarg(C_INT), 10); + assertEquals(vaList.nextVarg(C_INT), 15); + assertEquals(vaList.nextVarg(C_INT), 20); })}, { linkVaListCB("upcallStack"), VaListConsumer.mh(vaList -> { // skip all registers for (long l = 1; l <= 16; l++) { - assertEquals(vaList.vargAsLong(C_LONG_LONG), l); + assertEquals(vaList.nextVarg(C_LONG_LONG), l); } for (double d = 1; d <= 16; d++) { - assertEquals(vaList.vargAsDouble(C_DOUBLE), d); + assertEquals(vaList.nextVarg(C_DOUBLE), d); } // test some arbitrary values on the stack - assertEquals((byte) vaList.vargAsInt(C_INT), (byte) 1); - assertEquals((char) vaList.vargAsInt(C_INT), 'a'); - assertEquals((short) vaList.vargAsInt(C_INT), (short) 3); - assertEquals(vaList.vargAsInt(C_INT), 4); - assertEquals(vaList.vargAsLong(C_LONG_LONG), 5L); - assertEquals((float) vaList.vargAsDouble(C_DOUBLE), 6.0F); - assertEquals(vaList.vargAsDouble(C_DOUBLE), 7.0D); - assertEquals((byte) vaList.vargAsInt(C_INT), (byte) 8); - assertEquals((char) vaList.vargAsInt(C_INT), 'b'); - assertEquals((short) vaList.vargAsInt(C_INT), (short) 10); - assertEquals(vaList.vargAsInt(C_INT), 11); - assertEquals(vaList.vargAsLong(C_LONG_LONG), 12L); - assertEquals((float) vaList.vargAsDouble(C_DOUBLE), 13.0F); - assertEquals(vaList.vargAsDouble(C_DOUBLE), 14.0D); - - MemorySegment point = vaList.vargAsSegment(Point_LAYOUT, ResourceScope.newImplicitScope()); + assertEquals((byte) vaList.nextVarg(C_INT), (byte) 1); + assertEquals((char) vaList.nextVarg(C_INT), 'a'); + assertEquals((short) vaList.nextVarg(C_INT), (short) 3); + assertEquals(vaList.nextVarg(C_INT), 4); + assertEquals(vaList.nextVarg(C_LONG_LONG), 5L); + assertEquals((float) vaList.nextVarg(C_DOUBLE), 6.0F); + assertEquals(vaList.nextVarg(C_DOUBLE), 7.0D); + assertEquals((byte) vaList.nextVarg(C_INT), (byte) 8); + assertEquals((char) vaList.nextVarg(C_INT), 'b'); + assertEquals((short) vaList.nextVarg(C_INT), (short) 10); + assertEquals(vaList.nextVarg(C_INT), 11); + assertEquals(vaList.nextVarg(C_LONG_LONG), 12L); + assertEquals((float) vaList.nextVarg(C_DOUBLE), 13.0F); + assertEquals(vaList.nextVarg(C_DOUBLE), 14.0D); + + MemorySegment buffer = MemorySegment.allocateNative(BigPoint_LAYOUT, ResourceScope.newImplicitScope()); + SegmentAllocator bufferAllocator = SegmentAllocator.prefixAllocator(buffer); + + MemorySegment point = vaList.nextVarg(Point_LAYOUT, bufferAllocator); assertEquals((int) VH_Point_x.get(point), 5); assertEquals((int) VH_Point_y.get(point), 10); VaList copy = vaList.copy(); - MemorySegment bigPoint = vaList.vargAsSegment(BigPoint_LAYOUT, ResourceScope.newImplicitScope()); + MemorySegment bigPoint = vaList.nextVarg(BigPoint_LAYOUT, bufferAllocator); assertEquals((long) VH_BigPoint_x.get(bigPoint), 15); assertEquals((long) VH_BigPoint_y.get(bigPoint), 20); @@ -778,20 +797,20 @@ public class VaListTest extends NativeTestHelper { VH_BigPoint_y.set(bigPoint, 0); // should be independent - MemorySegment struct = copy.vargAsSegment(BigPoint_LAYOUT, ResourceScope.newImplicitScope()); + MemorySegment struct = copy.nextVarg(BigPoint_LAYOUT, bufferAllocator); assertEquals((long) VH_BigPoint_x.get(struct), 15); assertEquals((long) VH_BigPoint_y.get(struct), 20); })}, // test skip { linkVaListCB("upcallStack"), VaListConsumer.mh(vaList -> { vaList.skip(C_LONG_LONG, C_LONG_LONG, C_LONG_LONG, C_LONG_LONG); - assertEquals(vaList.vargAsLong(C_LONG_LONG), 5L); + assertEquals(vaList.nextVarg(C_LONG_LONG), 5L); vaList.skip(C_LONG_LONG, C_LONG_LONG, C_LONG_LONG, C_LONG_LONG); - assertEquals(vaList.vargAsLong(C_LONG_LONG), 10L); + assertEquals(vaList.nextVarg(C_LONG_LONG), 10L); vaList.skip(C_LONG_LONG, C_LONG_LONG, C_LONG_LONG, C_LONG_LONG, C_LONG_LONG, C_LONG_LONG); - assertEquals(vaList.vargAsDouble(C_DOUBLE), 1.0D); + assertEquals(vaList.nextVarg(C_DOUBLE), 1.0D); vaList.skip(C_DOUBLE, C_DOUBLE, C_DOUBLE, C_DOUBLE); - assertEquals(vaList.vargAsDouble(C_DOUBLE), 6.0D); + assertEquals(vaList.nextVarg(C_DOUBLE), 6.0D); })}, }; } @@ -801,8 +820,10 @@ public class VaListTest extends NativeTestHelper { static MethodHandle mh(VaListConsumer instance) { try { - return MethodHandles.lookup().findVirtual(VaListConsumer.class, "accept", + MethodHandle handle = MethodHandles.lookup().findVirtual(VaListConsumer.class, "accept", MethodType.methodType(void.class, VaList.class)).bindTo(instance); + return MethodHandles.filterArguments(handle, 0, + MethodHandles.insertArguments(ADDRESS_TO_VALIST, 1, ResourceScope.newConfinedScope())); } catch (ReflectiveOperationException e) { throw new InternalError(e); } diff --git a/test/jdk/java/foreign/virtual/TestVirtualCalls.java b/test/jdk/java/foreign/virtual/TestVirtualCalls.java index 39f80bdce1d0fdcb161fa27d53c785f338b9435f..70eecd151ceb4129863ed414d512ee2ddf16f574 100644 --- a/test/jdk/java/foreign/virtual/TestVirtualCalls.java +++ b/test/jdk/java/foreign/virtual/TestVirtualCalls.java @@ -24,6 +24,7 @@ /* * @test * @requires os.arch=="amd64" | os.arch=="x86_64" | os.arch=="aarch64" + * @library ../ * @run testng/othervm * --enable-native-access=ALL-UNNAMED * TestVirtualCalls @@ -34,28 +35,26 @@ import jdk.incubator.foreign.CLinker; import jdk.incubator.foreign.FunctionDescriptor; import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodType; +import jdk.incubator.foreign.NativeSymbol; import jdk.incubator.foreign.SymbolLookup; import jdk.incubator.foreign.MemoryAddress; import org.testng.annotations.*; -import static jdk.incubator.foreign.CLinker.*; import static org.testng.Assert.assertEquals; -public class TestVirtualCalls { +public class TestVirtualCalls extends NativeTestHelper { - static final CLinker abi = CLinker.getInstance(); + static final CLinker abi = CLinker.systemCLinker(); static final MethodHandle func; - static final MemoryAddress funcA; - static final MemoryAddress funcB; - static final MemoryAddress funcC; + static final NativeSymbol funcA; + static final NativeSymbol funcB; + static final NativeSymbol funcC; static { func = abi.downcallHandle( - MethodType.methodType(int.class), - FunctionDescriptor.of(C_INT)); + FunctionDescriptor.of(C_INT)); System.loadLibrary("Virtual"); SymbolLookup lookup = SymbolLookup.loaderLookup(); @@ -66,14 +65,14 @@ public class TestVirtualCalls { @Test public void testVirtualCalls() throws Throwable { - assertEquals((int) func.invokeExact((Addressable) funcA), 1); - assertEquals((int) func.invokeExact((Addressable) funcB), 2); - assertEquals((int) func.invokeExact((Addressable) funcC), 3); + assertEquals((int) func.invokeExact(funcA), 1); + assertEquals((int) func.invokeExact(funcB), 2); + assertEquals((int) func.invokeExact(funcC), 3); } @Test(expectedExceptions = NullPointerException.class) public void testNullTarget() throws Throwable { - int x = (int) func.invokeExact((Addressable) null); + int x = (int) func.invokeExact((NativeSymbol) null); } } diff --git a/test/jdk/java/io/ObjectStreamClass/ObjectStreamClassCaching.java b/test/jdk/java/io/ObjectStreamClass/ObjectStreamClassCaching.java new file mode 100644 index 0000000000000000000000000000000000000000..74c21c540d8649c84144af451a7096b06f7dddc0 --- /dev/null +++ b/test/jdk/java/io/ObjectStreamClass/ObjectStreamClassCaching.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.lang.ref.Reference; +import java.lang.ref.WeakReference; +import java.io.ObjectStreamClass; +import java.io.Serializable; +import java.util.ArrayList; +import org.testng.annotations.Test; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +/* @test + * @bug 8277072 + * @library /test/lib/ + * @summary ObjectStreamClass caches keep ClassLoaders alive + * @run testng/othervm -Xmx10m -XX:SoftRefLRUPolicyMSPerMB=1 ObjectStreamClassCaching + */ +public class ObjectStreamClassCaching { + + @Test + public void testCachingEffectiveness() throws Exception { + var ref = lookupObjectStreamClass(TestClass.class); + System.gc(); + Thread.sleep(100L); + // to trigger any ReferenceQueue processing... + lookupObjectStreamClass(AnotherTestClass.class); + assertFalse(ref.refersTo(null), + "Cache lost entry although memory was not under pressure"); + } + + @Test + public void testCacheReleaseUnderMemoryPressure() throws Exception { + var ref = lookupObjectStreamClass(TestClass.class); + pressMemoryHard(ref); + System.gc(); + Thread.sleep(100L); + assertTrue(ref.refersTo(null), + "Cache still has entry although memory was pressed hard"); + } + + // separate method so that the looked-up ObjectStreamClass is not kept on stack + private static WeakReference<?> lookupObjectStreamClass(Class<?> cl) { + return new WeakReference<>(ObjectStreamClass.lookup(cl)); + } + + private static void pressMemoryHard(Reference<?> ref) { + try { + var list = new ArrayList<>(); + while (!ref.refersTo(null)) { + list.add(new byte[1024 * 1024 * 64]); // 64 MiB chunks + } + } catch (OutOfMemoryError e) { + // release + } + } +} + +class TestClass implements Serializable { +} + +class AnotherTestClass implements Serializable { +} diff --git a/test/jdk/java/io/ObjectStreamClass/TestOSCClassLoaderLeak.java b/test/jdk/java/io/ObjectStreamClass/TestOSCClassLoaderLeak.java new file mode 100644 index 0000000000000000000000000000000000000000..3a99760bb6ebb6798feddeddf833e52663435ce3 --- /dev/null +++ b/test/jdk/java/io/ObjectStreamClass/TestOSCClassLoaderLeak.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.lang.ref.WeakReference; +import java.lang.reflect.Constructor; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.ObjectStreamClass; +import java.io.ObjectStreamField; +import java.io.Serializable; +import java.util.Arrays; +import org.testng.annotations.Test; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; + +import jdk.test.lib.util.ForceGC; + +/* @test + * @bug 8277072 + * @library /test/lib/ + * @build jdk.test.lib.util.ForceGC + * @summary ObjectStreamClass caches keep ClassLoaders alive + * @run testng TestOSCClassLoaderLeak + */ +public class TestOSCClassLoaderLeak { + + @Test + public void testClassLoaderLeak() throws Exception { + TestClassLoader myOwnClassLoader = new TestClassLoader(); + Class<?> loadClass = myOwnClassLoader.loadClass("ObjectStreamClass_MemoryLeakExample"); + Constructor con = loadClass.getConstructor(); + con.setAccessible(true); + Object objectStreamClass_MemoryLeakExample = con.newInstance(); + objectStreamClass_MemoryLeakExample.toString(); + + WeakReference<Object> myOwnClassLoaderWeakReference = new WeakReference<>(myOwnClassLoader); + assertNotNull(myOwnClassLoaderWeakReference.get()); + objectStreamClass_MemoryLeakExample = null; + myOwnClassLoader = null; + loadClass = null; + con = null; + assertNotNull(myOwnClassLoaderWeakReference.get()); + + ForceGC gc = new ForceGC(); + assertTrue(gc.await(() -> myOwnClassLoaderWeakReference.get() == null)); + } +} + +class ObjectStreamClass_MemoryLeakExample { + private static final ObjectStreamField[] fields = ObjectStreamClass.lookup(TestClass.class).getFields(); + public ObjectStreamClass_MemoryLeakExample() { + } + + @Override + public String toString() { + return Arrays.toString(fields); + } +} + +class TestClassLoader extends ClassLoader { + + @Override + public Class<?> loadClass(String name) throws ClassNotFoundException { + if (name.equals("TestClass") || name.equals("ObjectStreamClass_MemoryLeakExample")) { + byte[] bt = loadClassData(name); + return defineClass(name, bt, 0, bt.length); + } else { + return super.loadClass(name); + } + } + + private static byte[] loadClassData(String className) { + ByteArrayOutputStream byteSt = new ByteArrayOutputStream(); + try (InputStream is = TestClassLoader.class.getClassLoader().getResourceAsStream(className.replace(".", "/") + ".class")) { + int len = 0; + while ((len = is.read()) != -1) { + byteSt.write(len); + } + } catch (java.io.IOException e) { + e.printStackTrace(); + } + return byteSt.toByteArray(); + } +} + +class TestClass implements Serializable { + public String x; +} diff --git a/test/jdk/java/io/Serializable/GetField/ReadFieldsCNF.java b/test/jdk/java/io/Serializable/GetField/ReadFieldsCNF.java new file mode 100644 index 0000000000000000000000000000000000000000..7b91222d737e7e7b34ece765525f6f272a5677d4 --- /dev/null +++ b/test/jdk/java/io/Serializable/GetField/ReadFieldsCNF.java @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8273660 + * @summary Verify that ObjectInputStream ReadFields correctly reports ClassNotFoundException + * while getting the field value. The test uses Vector that calls ReadFields from its readObject. + * @library /test/lib + * @run testng ReadFieldsCNF + * @run testng/othervm -Djdk.serialGetFieldCnfeReturnsNull=true ReadFieldsCNF + */ + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.io.StreamCorruptedException; +import java.nio.charset.StandardCharsets; +import java.util.Vector; + +import org.testng.annotations.Test; +import org.testng.Assert; + +import jdk.test.lib.hexdump.HexPrinter; +import jdk.test.lib.hexdump.ObjectStreamPrinter; + +public class ReadFieldsCNF { + + private static final boolean GETFIELD_CNFE_RETURNS_NULL = + Boolean.getBoolean("jdk.serialGetFieldCnfeReturnsNull"); + + + /** + * Test a Vector holding a reference to a class instance that will not be found. + * @throws IOException If any other exception occurs + */ + @Test + private static void testVectorWithRole() throws IOException { + System.out.println("Property GETFIELD_CNFE_RETURNS_NULL: " + GETFIELD_CNFE_RETURNS_NULL); + + Role role = new Role(); + Vector<Role> vector = new Vector<>(); + vector.add(role); + + // Modify the byte stream to change the classname to be deserialized to + // XeadFieldsCNF$Role. + byte[] bytes = writeObject(vector); + + // Locate the name of the class to be deserialize + String s = new String(bytes, StandardCharsets.ISO_8859_1); // Map bytes to chars + int off = s.indexOf(Role.class.getName()); + System.out.printf("Role offset: %d (0x%x) : %s%n", off, off, Role.class.getName()); + if (off < 0) { + HexPrinter.simple().formatter(ObjectStreamPrinter.formatter()).format(bytes); + Assert.fail("classname not found"); + } + + bytes[off] = (byte) 'X'; // replace R with X -> Class not found + + // Deserialize the Vector expecting a ClassNotFoundException + ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes)); + try { + Object obj = in.readObject(); + System.out.println("Read: " + obj); + Assert.fail("Should not reach here, an exception should always occur"); + } catch (ClassNotFoundException cnfe) { + // Expected ClassNotFoundException + String expected = "XeadFieldsCNF$Role"; + Assert.assertEquals(expected, cnfe.getMessage(), "Wrong classname"); + if (GETFIELD_CNFE_RETURNS_NULL) { + Assert.fail("Expected IOException got ClassNotFoundException", cnfe); + } + System.out.println("Normal: OIS.readObject: " + cnfe); + } catch (StreamCorruptedException ioe) { + if (!GETFIELD_CNFE_RETURNS_NULL) { + Assert.fail("Expected ClassNotFoundException got StreamCorruptedException ", ioe); + } + System.out.println("Normal: " + ioe); + } + // Other exceptions cause the test to fail + } + + /** + * For an object holding a reference to a class that will not be found. + * @throws IOException If any other exception occurs + */ + @Test + private static void testHolderWithRole() throws IOException { + System.out.println("Property GETFIELD_CNFE_RETURNS_NULL: " + GETFIELD_CNFE_RETURNS_NULL); + Role role = new Role(); + Holder holder = new Holder(role); + + // Modify the byte stream to change the classname to be deserialized to + // XeadFieldsCNF$Role. + byte[] bytes = writeObject(holder); + + String s = new String(bytes, StandardCharsets.ISO_8859_1); // Map bytes to chars + int off = s.indexOf(Role.class.getName(), 0); + off = s.indexOf(Role.class.getName(), off + 1); // 2nd occurrence of classname + System.out.printf("Role offset: %d (0x%x)%n", off, off); + if (off < 0) { + HexPrinter.simple().formatter(ObjectStreamPrinter.formatter()).format(bytes); + Assert.fail("classname found at index: " + off + " (0x" + Integer.toHexString(off) + ")"); + } + + bytes[off] = (byte) 'X'; // replace R with X -> Class not found + + // Deserialize the Vector expecting a ClassNotFoundException + ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes)); + try { + Holder obj = (Holder)in.readObject(); + System.out.println("Read: " + obj); + Assert.fail("Should not reach here, an exception should always occur"); + } catch (ClassNotFoundException cnfe) { + // Expected ClassNotFoundException + String expected = "XeadFieldsCNF$Role"; + Assert.assertEquals(expected, cnfe.getMessage(), "Wrong classname"); + System.out.println("Normal: OIS.readObject: " + cnfe); + } catch (StreamCorruptedException ioe) { + if (!GETFIELD_CNFE_RETURNS_NULL) { + Assert.fail("Expected ClassNotFoundException got StreamCorruptedException ", ioe); + } + System.out.println("Normal: " + ioe); + } + // Other exceptions cause the test to fail + } + + private static byte[] writeObject(Object o) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try (ObjectOutputStream os = new ObjectOutputStream(baos)) { + os.writeObject(o); + } + return baos.toByteArray(); + } + + static class Role implements Serializable { + private static final long serialVersionUID = 0L; + + Role() {} + } + + static class Holder implements Serializable { + private static final long serialVersionUID = 1L; + + Role role; + + Holder(Role role) { + this.role = role; + } + + private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { + ObjectInputStream.GetField fields = ois.readFields(); + try { + Object repl = new Object(); + role = (Role)fields.get("role", repl); + System.out.println("Holder.readObject Role: " + role); + } catch (Exception ex) { + // Catch CNFE and ignore it; check elsewhere that CNFE is thrown from OIS.readObject + System.out.println("Normal: exception in Holder.readObject, ignoring: " + ex); + } + } + + public String toString() { + return "role: " + role; + } + } +} diff --git a/test/jdk/java/io/Serializable/oldTests/WritePrimitive.java b/test/jdk/java/io/Serializable/oldTests/WritePrimitive.java index f2bd28d75f73a06b3065cc8bf6d0a9732526c89f..e6b841e7a49751d02ebd6db06884c6fa11af63d1 100644 --- a/test/jdk/java/io/Serializable/oldTests/WritePrimitive.java +++ b/test/jdk/java/io/Serializable/oldTests/WritePrimitive.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,6 +22,7 @@ */ /* @test + * @bug 8276806 8278463 * @summary it is a new version of an old test which was * /src/share/test/serialization/piotest.java * Test of serialization/deserialization of @@ -32,28 +33,27 @@ */ import java.io.*; +import java.util.Arrays; public class WritePrimitive { public static void main (String argv[]) throws IOException { System.err.println("\nRegression test for testing of " + "serialization/deserialization of primitives \n"); + int i = 123456; + byte b = 12; + short s = 45; + char c = 'A'; + long l = 1234567890000L; + float f = 3.14159f; + double d = f * 2; + boolean z = true; + String string = "The String"; + PrimitivesTest prim = new PrimitivesTest(); + byte[] ba = {1, 2, 3, 4, 5, 6, 7}; // byte array to write - FileInputStream istream = null; - FileOutputStream ostream = null; - try { - int i = 123456; - byte b = 12; - short s = 45; - char c = 'A'; - long l = 1234567890000L; - float f = 3.14159f; - double d = f*2; - boolean z = true; - String string = "The String"; - PrimitivesTest prim = new PrimitivesTest(); - - ostream = new FileOutputStream("piotest1.tmp"); - ObjectOutputStream p = new ObjectOutputStream(ostream); + byte[] bytes; + try (ByteArrayOutputStream ostream = new ByteArrayOutputStream(); + ObjectOutputStream p = new ObjectOutputStream(ostream)) { p.writeInt(i); p.writeByte(b); @@ -63,14 +63,20 @@ public class WritePrimitive { p.writeFloat(f); p.writeDouble(d); p.writeBoolean(z); + p.write(ba); // for simple read(byte[]) + p.write(ba); // for readFully(byte[]) + p.write(ba, 0, ba.length - 2); // for readFully(byte[], 0, 7) p.writeUTF(string); p.writeObject(string); p.writeObject(prim); p.flush(); + bytes = ostream.toByteArray(); + + } - istream = new FileInputStream("piotest1.tmp"); - ObjectInputStream q = new ObjectInputStream(istream); + ByteArrayInputStream istream = new ByteArrayInputStream(bytes); + try (ObjectInputStream q = new ObjectInputStream(istream);) { int i_u = q.readInt(); byte b_u = q.readByte(); @@ -80,6 +86,12 @@ public class WritePrimitive { float f_u = q.readFloat(); double d_u = q.readDouble(); boolean z_u = q.readBoolean(); + byte[] ba_readBuf = new byte[ba.length]; + int ba_readLen = q.read(ba_readBuf); + byte[] ba_readFullyBuf = new byte[ba.length]; + int ba_readFullyLen = q.read(ba_readFullyBuf); + byte[] ba_readFullySizedBuf = new byte[ba.length]; + int ba_readFullySizedLen = q.read(ba_readFullySizedBuf, 0, ba.length - 2); String string_utf = q.readUTF(); String string_u = (String)q.readObject(); if (i != i_u) { @@ -120,6 +132,10 @@ public class WritePrimitive { z_u); throw new Error(); } + checkArray("read(byte[])", ba, ba.length, ba_readBuf, ba_readLen); + checkArray("readFully(byte[])", ba, ba.length, ba_readFullyBuf, ba_readFullyLen); + checkArray("readFully(byte[], off, len)", ba, ba.length - 2, ba_readFullySizedBuf, ba_readFullySizedLen); + if (!string.equals(string_utf)) { System.err.println("\nString: expected " + string + " actual " + string_utf); @@ -144,20 +160,26 @@ public class WritePrimitive { System.err.print("TEST FAILED: "); e.printStackTrace(); - System.err.println("\nInput remaining"); + System.err.println("\nBytes read: " + (bytes.length - istream.available()) + + ", Input remaining: " + istream.available()); int ch; try { while ((ch = istream.read()) != -1) { System.err.print("\n " + Integer.toString(ch, 16)+ " "); } System.out.println("\n "); - } catch (Exception f) { + } catch (Exception fex) { throw new Error(); } throw new Error(); - } finally { - if (istream != null) istream.close(); - if (ostream != null) ostream.close(); + } + } + + static void checkArray(String label, byte[] expected, int expectedLen, byte[] actual, int actualLen) { + int mismatch = Arrays.mismatch(expected, 0, expectedLen, actual, 0, actualLen); + if (actualLen != expectedLen || mismatch >= 0) { + System.err.println("\n" + label + ": expected " + expectedLen + " actual " + actualLen + ", mismatch: " + mismatch); + throw new Error(); } } } diff --git a/test/jdk/java/lang/Object/FinalizationOption.java b/test/jdk/java/lang/Object/FinalizationOption.java new file mode 100644 index 0000000000000000000000000000000000000000..7d50412e26f07a0d21b067ad7bf1b4e8dced9216 --- /dev/null +++ b/test/jdk/java/lang/Object/FinalizationOption.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8276422 + * @summary add command-line option to disable finalization + * @run main/othervm FinalizationOption yes + * @run main/othervm --finalization=enabled FinalizationOption yes + * @run main/othervm --finalization=disabled FinalizationOption no + */ +public class FinalizationOption { + static volatile boolean finalizerWasCalled = false; + + @SuppressWarnings("deprecation") + protected void finalize() { + finalizerWasCalled = true; + } + + static void create() { + new FinalizationOption(); + } + + /** + * Checks whether the finalizer thread is or is not running. The finalizer thread + * is a thread in the root thread group whose named is "Finalizer". + * @param expected boolean indicating whether a finalizer thread should exist + * @return boolean indicating whether the expectation was met + */ + static boolean checkFinalizerThread(boolean expected) { + ThreadGroup root = Thread.currentThread().getThreadGroup(); + for (ThreadGroup parent = root; + parent != null; + root = parent, parent = root.getParent()) + ; + + int nt = 100; + Thread[] threads; + while (true) { + threads = new Thread[nt]; + nt = root.enumerate(threads); + if (nt < threads.length) + break; + threads = new Thread[nt + 100]; + } + + Thread ft = null; + for (int i = 0; i < nt; i++) { + if ("Finalizer".equals(threads[i].getName())) { + ft = threads[i]; + break; + } + } + + String msg = (ft == null) ? "(none)" : ft.toString(); + boolean passed = (ft != null) == expected; + System.out.printf("Finalizer thread. Expected: %s Actual: %s %s%n", + expected, msg, passed ? "Passed." : "FAILED!"); + return passed; + } + + /** + * Checks whether there was a call to the finalize() method. + * @param expected boolean whether finalize() should be called + * @return boolean indicating whether the expecation was met + */ + static boolean checkFinalizerCalled(boolean expected) { + create(); + for (int i = 0; i < 100; i++) { + System.gc(); + try { + Thread.sleep(10L); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + } + if (finalizerWasCalled) { + break; + } + } + boolean passed = (expected == finalizerWasCalled); + System.out.printf("Call to finalize(). Expected: %s Actual: %s %s%n", + expected, finalizerWasCalled, + passed ? "Passed." : "FAILED!"); + return passed; + } + + public static void main(String[] args) { + boolean finalizationEnabled = switch (args[0]) { + case "yes" -> true; + case "no" -> false; + default -> { + throw new AssertionError("usage: FinalizationOption yes|no"); + } + }; + + boolean threadPass = checkFinalizerThread(finalizationEnabled); + boolean calledPass = checkFinalizerCalled(finalizationEnabled); + + if (!threadPass || !calledPass) + throw new AssertionError("Test failed."); + } +} diff --git a/test/hotspot/jtreg/runtime/NMT/ShutdownTwice.java b/test/jdk/java/lang/Object/InvalidFinalizationOption.java similarity index 50% rename from test/hotspot/jtreg/runtime/NMT/ShutdownTwice.java rename to test/jdk/java/lang/Object/InvalidFinalizationOption.java index 600d57cc91fa345d0b14813e35f96415ab5b6583..c5cca549ead095f62a251d65cfb80ae78799d201 100644 --- a/test/hotspot/jtreg/runtime/NMT/ShutdownTwice.java +++ b/test/jdk/java/lang/Object/InvalidFinalizationOption.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,37 +23,30 @@ /* * @test - * @summary Run shutdown twice + * @bug 8276422 + * @summary Invalid/missing values for the finalization option should be rejected * @library /test/lib - * @modules java.base/jdk.internal.misc - * java.management - * @run main/othervm -XX:NativeMemoryTracking=detail ShutdownTwice + * @run driver InvalidFinalizationOption */ import jdk.test.lib.process.ProcessTools; import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.JDKToolFinder; -public class ShutdownTwice { - - public static void main(String args[]) throws Exception { - // Grab my own PID - String pid = Long.toString(ProcessTools.getProcessId()); - OutputAnalyzer output; - - ProcessBuilder pb = new ProcessBuilder(); - - // Run 'jcmd <pid> VM.native_memory shutdown' - pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "shutdown"}); - output = new OutputAnalyzer(pb.start()); - - // Verify that jcmd reports that NMT is shutting down - output.shouldContain("Native memory tracking has been turned off"); - - // Run shutdown again - output = new OutputAnalyzer(pb.start()); - - // Verify that jcmd reports that NMT has been shutdown already - output.shouldContain("Native memory tracking has been shutdown"); - } +public class InvalidFinalizationOption { + public static void main(String[] args) throws Exception { + record TestData(String arg, String expected) { } + + TestData[] testData = { + new TestData("--finalization", "Unrecognized option"), + new TestData("--finalization=", "Invalid finalization value"), + new TestData("--finalization=azerty", "Invalid finalization value") + }; + + for (var data : testData) { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(data.arg); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain(data.expected); + output.shouldHaveExitValue(1); + } + } } diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestExact.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestExact.java index 6c14c885a2410e33b9b94f185365e190b4361faa..bd1d1b58b6f3f264c78f6ab1bf9add838adb8cdc 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestExact.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestExact.java @@ -47,6 +47,7 @@ */ import jdk.incubator.foreign.MemoryHandles; +import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; import jdk.internal.access.foreign.MemorySegmentProxy; @@ -170,7 +171,7 @@ public class VarHandleTestExact { @Test(dataProvider = "dataSetMemorySegment") public void testExactSegmentSet(Class<?> carrier, Object testValue, SetSegmentX setter) { - VarHandle vh = MemoryHandles.varHandle(carrier, ByteOrder.nativeOrder()); + VarHandle vh = MemoryHandles.varHandle(MemoryLayout.valueLayout(carrier, ByteOrder.nativeOrder())); try (ResourceScope scope = ResourceScope.newConfinedScope()) { MemorySegment seg = MemorySegment.allocateNative(8, scope); doTest(vh, diff --git a/test/jdk/java/lang/management/ThreadMXBean/ThreadLists.java b/test/jdk/java/lang/management/ThreadMXBean/ThreadLists.java index 433a3f54c0d158328562f09dc3280e388d502de6..cadfff1097cbc9dd7bcbefad9542dc6c12e04b78 100644 --- a/test/jdk/java/lang/management/ThreadMXBean/ThreadLists.java +++ b/test/jdk/java/lang/management/ThreadMXBean/ThreadLists.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,9 +23,11 @@ /* * @test - * @bug 5047639 + * @bug 5047639 8132785 * @summary Check that the "java-level" APIs provide a consistent view of * the thread list + * @comment Must run in othervm mode to avoid interference from other tests. + * @run main/othervm ThreadLists */ import java.lang.management.ManagementFactory; import java.lang.management.ThreadMXBean; @@ -50,6 +52,19 @@ public class ThreadLists { // get the thread count int activeCount = top.activeCount(); + // Now enumerate to see if we find any extras yet. + // Ensure the array is big enough for a few extras. + Thread[] threads = new Thread[activeCount * 2]; + int newCount = top.enumerate(threads); + if (newCount != activeCount) { + System.out.println("Found different threads after enumeration:"); + } else { + System.out.println("Initial set of enumerated threads:"); + } + for (int i = 0; i < newCount; i++) { + System.out.println(" - Thread: " + threads[i].getName()); + } + Map<Thread, StackTraceElement[]> stackTraces = Thread.getAllStackTraces(); ThreadMXBean threadBean = ManagementFactory.getThreadMXBean(); @@ -68,6 +83,11 @@ public class ThreadLists { if (activeCount != threadIds.length) failed = true; if (failed) { + System.out.println("Set of stack-traced threads:"); + for (Thread t : stackTraces.keySet()) { + System.out.println(" - Thread: " + + (t != null ? t.getName() : "null!")); + } throw new RuntimeException("inconsistent results"); } } diff --git a/test/jdk/java/lang/module/ClassFileVersionsTest.java b/test/jdk/java/lang/module/ClassFileVersionsTest.java index 6e9b19a09bca0957bb15ce86b4d39b30508398a7..9d723662b24ee00307af9f38b83d4df26a4218b6 100644 --- a/test/jdk/java/lang/module/ClassFileVersionsTest.java +++ b/test/jdk/java/lang/module/ClassFileVersionsTest.java @@ -43,74 +43,65 @@ import org.testng.annotations.Test; import static org.testng.Assert.*; public class ClassFileVersionsTest { + private static final int FEATURE; + static { + FEATURE = Runtime.version().feature(); + assert FEATURE >= 10; + } // major, minor, modifiers for requires java.base @DataProvider(name = "supported") public Object[][] supported() { - return new Object[][]{ - { 53, 0, Set.of() }, // JDK 9 - { 53, 0, Set.of(STATIC) }, - { 53, 0, Set.of(TRANSITIVE) }, - { 53, 0, Set.of(STATIC, TRANSITIVE) }, - - { 54, 0, Set.of() }, // JDK 10 - { 55, 0, Set.of() }, // JDK 11 - { 56, 0, Set.of() }, // JDK 12 - { 57, 0, Set.of() }, // JDK 13 - { 58, 0, Set.of() }, // JDK 14 - { 59, 0, Set.of() }, // JDK 15 - { 60, 0, Set.of() }, // JDK 16 - { 61, 0, Set.of() }, // JDK 17 - { 62, 0, Set.of() }, // JDK 18 - }; + /* + * There are four test cases for JDK 9 and then one test case + * for each subsequent JDK version from JDK 10 to the current + * feature release for a total of (4 + (FEATURE - 9) ) => + * (feature - 5) rows. + */ + Object[][] result = new Object[(FEATURE - 5)][]; + + // Class file version of JDK 9 is 53.0 + result[0] = new Object[]{ 53, 0, Set.of()}; + result[1] = new Object[]{ 53, 0, Set.of(STATIC) }; + result[2] = new Object[]{ 53, 0, Set.of(TRANSITIVE) }; + result[3] = new Object[]{ 53, 0, Set.of(STATIC, TRANSITIVE) }; + + // Major class file version of JDK N is 44 + n. Create rows + // for JDK 10 through FEATURE. + for (int i = 4; i < (FEATURE - 5) ; i++) { + result[i] = new Object[]{i + 50, 0, Set.of()}; + } + + return result; } // major, minor, modifiers for requires java.base @DataProvider(name = "unsupported") public Object[][] unsupported() { - return new Object[][]{ - { 50, 0, Set.of()}, // JDK 6 - { 51, 0, Set.of()}, // JDK 7 - { 52, 0, Set.of()}, // JDK 8 - - { 54, 0, Set.of(STATIC) }, // JDK 10 - { 54, 0, Set.of(TRANSITIVE) }, - { 54, 0, Set.of(STATIC, TRANSITIVE) }, - - { 55, 0, Set.of(STATIC) }, // JDK 11 - { 55, 0, Set.of(TRANSITIVE) }, - { 55, 0, Set.of(STATIC, TRANSITIVE) }, - - { 56, 0, Set.of(STATIC) }, // JDK 12 - { 56, 0, Set.of(TRANSITIVE) }, - { 56, 0, Set.of(STATIC, TRANSITIVE) }, - - { 57, 0, Set.of(STATIC) }, // JDK 13 - { 57, 0, Set.of(TRANSITIVE) }, - { 57, 0, Set.of(STATIC, TRANSITIVE) }, - - { 58, 0, Set.of(STATIC) }, // JDK 14 - { 58, 0, Set.of(TRANSITIVE) }, - { 58, 0, Set.of(STATIC, TRANSITIVE) }, - - { 59, 0, Set.of(STATIC) }, // JDK 15 - { 59, 0, Set.of(TRANSITIVE) }, - { 59, 0, Set.of(STATIC, TRANSITIVE) }, - - { 60, 0, Set.of(STATIC) }, // JDK 16 - { 60, 0, Set.of(TRANSITIVE) }, - { 60, 0, Set.of(STATIC, TRANSITIVE) }, - - { 61, 0, Set.of(STATIC) }, // JDK 17 - { 61, 0, Set.of(TRANSITIVE) }, - { 61, 0, Set.of(STATIC, TRANSITIVE) }, - - { 62, 0, Set.of(STATIC) }, // JDK 18 - { 62, 0, Set.of(TRANSITIVE) }, - { 62, 0, Set.of(STATIC, TRANSITIVE) }, - - { 63, 0, Set.of()}, // JDK 19 - }; + /* + * There are three test cases for releases prior to JDK 9, + * three test cases for each JDK version from JDK 10 to the + * current feature release, plus one addition test case for + * the next release for a total of (3 + (FEATURE - 9) * 3 + 1) + * rows. + */ + int unsupportedCount = 3 + (FEATURE - 9)*3 + 1; + Object[][] result = new Object[unsupportedCount][]; + + result[0] = new Object[]{50, 0, Set.of()}; // JDK 6 + result[1] = new Object[]{51, 0, Set.of()}; // JDK 7 + result[2] = new Object[]{52, 0, Set.of()}; // JDK 8 + + for (int i = 10; i <= FEATURE ; i++) { + int base = 3 + (i-10)*3; + // Major class file version of JDK N is 44+n + result[base] = new Object[]{i + 44, 0, Set.of(STATIC)}; + result[base + 1] = new Object[]{i + 44, 0, Set.of(TRANSITIVE)}; + result[base + 2] = new Object[]{i + 44, 0, Set.of(STATIC, TRANSITIVE)}; + } + + result[unsupportedCount - 1] = new Object[]{FEATURE+1+44, 0, Set.of()}; + return result; } @Test(dataProvider = "supported") diff --git a/test/jdk/java/lang/reflect/IllegalArgumentsTest.java b/test/jdk/java/lang/reflect/IllegalArgumentsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..0d699485f9103ad21711b9aeff195698c0f1c134 --- /dev/null +++ b/test/jdk/java/lang/reflect/IllegalArgumentsTest.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8277964 + * @summary Test IllegalArgumentException be thrown when an argument is invalid + * @run testng/othervm IllegalArgumentsTest + */ + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import org.testng.annotations.Test; + +public class IllegalArgumentsTest { + static class T { + public T(int i) {} + + public static void m(int i) {} + + public void m1(String s) {} + } + + @Test + public void wrongArgumentType() throws ReflectiveOperationException { + for (int i = 0; i < 100_000; ++i) { + try { + Constructor<T> ctor = T.class.getConstructor(int.class); + ctor.newInstance(int.class); // wrong argument type + throw new RuntimeException("Expected IAE not thrown"); + } catch (IllegalArgumentException e) {} + } + + for (int i = 0; i < 100_000; ++i) { + try { + Method method = T.class.getMethod("m", int.class); + method.invoke(null, int.class); // wrong argument type + throw new RuntimeException("Expected IAE not thrown"); + } catch (IllegalArgumentException e) {} + } + } + + @Test + public void nullArguments() throws ReflectiveOperationException { + for (int i = 0; i < 100_000; ++i) { + try { + Constructor<T> ctor = T.class.getConstructor(int.class); + ctor.newInstance(new Object[] {null}); + throw new RuntimeException("Expected IAE not thrown"); + } catch (IllegalArgumentException e) {} + } + + for (int i = 0; i < 100_000; ++i) { + try { + Method method = T.class.getMethod("m", int.class); + method.invoke(null, new Object[] {null}); + throw new RuntimeException("Expected IAE not thrown"); + } catch (IllegalArgumentException e) {} + } + } + + @Test + public void illegalArguments() throws ReflectiveOperationException { + for (int i = 0; i < 100_000; ++i) { + try { + Constructor<T> ctor = T.class.getConstructor(int.class); + ctor.newInstance(new Object[] { 10, 20}); + throw new RuntimeException("Expected IAE not thrown"); + } catch (IllegalArgumentException e) {} + } + + for (int i = 0; i < 100_000; ++i) { + try { + Method method = T.class.getMethod("m", int.class); + method.invoke(null, new Object[] { 10, 20}); + throw new RuntimeException("Expected IAE not thrown"); + } catch (IllegalArgumentException e) {} + } + } + + @Test + public void wrongReceiver() throws ReflectiveOperationException { + for (int i = 0; i < 100_000; ++i) { + try { + Method method = T.class.getMethod("m1", String.class); + method.invoke(this, "bad receiver"); + throw new RuntimeException("Expected IAE not thrown"); + } catch (IllegalArgumentException e) {} + } + } +} diff --git a/test/jdk/java/lang/runtime/ObjectMethodsTest.java b/test/jdk/java/lang/runtime/ObjectMethodsTest.java index dba92eb32ff77092053c52e542ef393eb865e4dd..0a7741c02e1788cd1ffb653bd90c727edbe88e2b 100644 --- a/test/jdk/java/lang/runtime/ObjectMethodsTest.java +++ b/test/jdk/java/lang/runtime/ObjectMethodsTest.java @@ -166,6 +166,7 @@ public class ObjectMethodsTest { assertThrows(NPE, () -> ObjectMethods.bootstrap(LOOKUP, npt.mn(), npt.mt(), null, "x;y", C.ACCESSORS)); assertThrows(NPE, () -> ObjectMethods.bootstrap(LOOKUP, npt.mn(), null, C.class, "x;y", C.ACCESSORS)); assertThrows(NPE, () -> ObjectMethods.bootstrap(LOOKUP, null, npt.mt(), C.class, "x;y", C.ACCESSORS)); + assertThrows(NPE, () -> ObjectMethods.bootstrap(null, npt.mn(), npt.mt(), C.class, "x;y", C.ACCESSORS)); } } diff --git a/test/jdk/java/net/ServerSocket/IsClosedAfterAsyncClose.java b/test/jdk/java/net/ServerSocket/IsClosedAfterAsyncClose.java new file mode 100644 index 0000000000000000000000000000000000000000..1b77793290091ff6b2f9967ef279e8ecbe52606b --- /dev/null +++ b/test/jdk/java/net/ServerSocket/IsClosedAfterAsyncClose.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8278339 + * @summary Test that ServerSocket::isClosed returns true after async close + */ + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.Socket; + +public class IsClosedAfterAsyncClose { + + private static final int ITERATIONS = 100; + + public static void main(String[] args) throws Exception { + for (int i = 0; i < ITERATIONS; i++) { + System.out.printf("Test %d...%n", i); + + // create listener bound to the loopback address + ServerSocket listener = new ServerSocket(); + InetAddress loopback = InetAddress.getLoopbackAddress(); + listener.bind(new InetSocketAddress(loopback, 0)); + + // task to close listener after a delay + Runnable closeListener = () -> { + try { + Thread.sleep(100); + listener.close(); + } catch (Exception e) { + e.printStackTrace(); + } + }; + + // main thread blocks in accept. When listener is closed then accept + // should wakeup with an IOException and isClosed should be true. + try (listener) { + Thread closer = new Thread(closeListener); + closer.start(); + try { + while (true) { + Socket s = listener.accept(); + // close spurious connection + s.close(); + } + } catch (IOException ioe) { + if (!listener.isClosed()) { + throw new RuntimeException("isClosed returned false!!"); + } + } finally { + closer.join(); + } + } + } + } +} + diff --git a/test/jdk/java/net/httpclient/ManyRequests.java b/test/jdk/java/net/httpclient/ManyRequests.java index f79d565162ad8e18730855e886c70d1d363406f6..296377441a73faa12e9ba10a5452c8602bda7169 100644 --- a/test/jdk/java/net/httpclient/ManyRequests.java +++ b/test/jdk/java/net/httpclient/ManyRequests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,13 +32,13 @@ * @compile ../../../com/sun/net/httpserver/LogFilter.java * @compile ../../../com/sun/net/httpserver/EchoHandler.java * @compile ../../../com/sun/net/httpserver/FileServerHandler.java - * @run main/othervm/timeout=40 -Djdk.httpclient.HttpClient.log=ssl ManyRequests - * @run main/othervm/timeout=40 -Dtest.insertDelay=true ManyRequests - * @run main/othervm/timeout=40 -Dtest.chunkSize=64 ManyRequests - * @run main/othervm/timeout=40 -Dtest.insertDelay=true -Dtest.chunkSize=64 ManyRequests + * @run main/othervm/timeout=40 -Djdk.httpclient.HttpClient.log=ssl,channel ManyRequests + * @run main/othervm/timeout=40 -Djdk.httpclient.HttpClient.log=channel -Dtest.insertDelay=true ManyRequests + * @run main/othervm/timeout=40 -Djdk.httpclient.HttpClient.log=channel -Dtest.chunkSize=64 ManyRequests + * @run main/othervm/timeout=40 -Djdk.httpclient.HttpClient.log=channel -Dtest.insertDelay=true -Dtest.chunkSize=64 ManyRequests * @summary Send a large number of requests asynchronously */ - // * @run main/othervm/timeout=40 -Djdk.httpclient.HttpClient.log=ssl ManyRequests + // * @run main/othervm/timeout=40 -Djdk.httpclient.HttpClient.log=ssl,channel ManyRequests import com.sun.net.httpserver.HttpsConfigurator; import com.sun.net.httpserver.HttpsParameters; @@ -47,6 +47,7 @@ import com.sun.net.httpserver.HttpExchange; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.net.ConnectException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.URI; @@ -54,13 +55,18 @@ import java.net.http.HttpClient; import java.net.http.HttpClient.Builder; import java.net.http.HttpRequest; import java.net.http.HttpRequest.BodyPublishers; +import java.net.http.HttpResponse; import java.net.http.HttpResponse.BodyHandlers; import java.time.Duration; import java.util.Arrays; import java.util.Formatter; import java.util.HashMap; import java.util.LinkedList; +import java.util.Map; import java.util.Random; +import java.util.concurrent.CompletionException; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; @@ -68,17 +74,27 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Logger; import java.util.logging.Level; import java.util.concurrent.CompletableFuture; +import java.util.stream.Stream; import javax.net.ssl.SSLContext; + +import jdk.test.lib.Platform; +import jdk.test.lib.RandomFactory; import jdk.test.lib.net.SimpleSSLContext; +import jdk.test.lib.net.URIBuilder; public class ManyRequests { - volatile static int counter = 0; + static final int MAX_COUNT = 20; + static final int MAX_LIMIT = 40; + static final AtomicInteger COUNT = new AtomicInteger(); + static final AtomicInteger LIMIT = new AtomicInteger(MAX_LIMIT); + static final Random RANDOM = RandomFactory.getRandom(); public static void main(String[] args) throws Exception { Logger logger = Logger.getLogger("com.sun.net.httpserver"); logger.setLevel(Level.ALL); logger.info("TEST"); + Stream.of(Logger.getLogger("").getHandlers()).forEach((h) -> h.setLevel(Level.ALL)); System.out.println("Sending " + REQUESTS + " requests; delay=" + INSERT_DELAY + ", chunks=" + CHUNK_SIZE @@ -106,14 +122,14 @@ public class ManyRequests { } //static final int REQUESTS = 1000; - static final int REQUESTS = 20; + static final int REQUESTS = MAX_COUNT; static final boolean INSERT_DELAY = Boolean.getBoolean("test.insertDelay"); static final int CHUNK_SIZE = Math.max(0, Integer.parseInt(System.getProperty("test.chunkSize", "0"))); static final boolean XFIXED = Boolean.getBoolean("test.XFixed"); static class TestEchoHandler extends EchoHandler { - final Random rand = jdk.test.lib.RandomFactory.getRandom(); + final Random rand = RANDOM; @Override public void handle(HttpExchange e) throws IOException { System.out.println("Server: received " + e.getRequestURI()); @@ -139,60 +155,126 @@ public class ManyRequests { } } + static String now(long start) { + long elapsed = System.nanoTime() - start; + long ms = elapsed / 1000_000L; + long s = ms / 1000L; + if (s == 0) return ms + "ms: "; + return s + "s, " + (ms - s * 1000L) + "ms: "; + } + + static String failure(Throwable t) { + String s = "\n\t failed: " + t; + for (t = t.getCause(); t != null ; t = t.getCause()) { + s = s + "\n\t\t Caused by: " + t; + } + return s; + } + static void test(HttpsServer server, HttpClient client) throws Exception { int port = server.getAddress().getPort(); - URI baseURI = new URI("https://localhost:" + port + "/foo/x"); + + URI baseURI = URIBuilder.newBuilder() + .scheme("https") + .host(InetAddress.getLoopbackAddress().getHostName()) + .port(port) + .path("/foo/x").build(); server.createContext("/foo", new TestEchoHandler()); server.start(); - RequestLimiter limiter = new RequestLimiter(40); - Random rand = new Random(); - CompletableFuture<?>[] results = new CompletableFuture<?>[REQUESTS]; - HashMap<HttpRequest,byte[]> bodies = new HashMap<>(); - - for (int i=0; i<REQUESTS; i++) { - byte[] buf = new byte[(i+1)*CHUNK_SIZE+i+1]; // different size bodies - rand.nextBytes(buf); - URI uri = new URI(baseURI.toString() + String.valueOf(i+1)); - HttpRequest r = HttpRequest.newBuilder(uri) - .header("XFixed", "true") - .POST(BodyPublishers.ofByteArray(buf)) - .build(); - bodies.put(r, buf); - - results[i] = - limiter.whenOkToSend() - .thenCompose((v) -> { - System.out.println("Client: sendAsync: " + r.uri()); - return client.sendAsync(r, BodyHandlers.ofByteArray()); - }) - .thenCompose((resp) -> { - limiter.requestComplete(); - if (resp.statusCode() != 200) { - String s = "Expected 200, got: " + resp.statusCode(); - System.out.println(s + " from " - + resp.request().uri().getPath()); - return completedWithIOException(s); - } else { - counter++; - System.out.println("Result (" + counter + ") from " - + resp.request().uri().getPath()); - } - return CompletableFuture.completedStage(resp.body()) - .thenApply((b) -> new Pair<>(resp, b)); - }) - .thenAccept((pair) -> { - HttpRequest request = pair.t.request(); - byte[] requestBody = bodies.get(request); - check(Arrays.equals(requestBody, pair.u), - "bodies not equal:[" + bytesToHexString(requestBody) - + "] [" + bytesToHexString(pair.u) + "]"); - - }); - } + // This loop implements a retry mechanism to work around an issue + // on some systems (observed on Windows 10) that seem to be trying to + // throttle the number of connections that can be made concurrently by + // rejecting connection attempts. + // On the first iteration of this loop, we will attempt 20 concurrent + // requests. If this fails with ConnectException, we will retry the + // 20 requests, but limiting the concurrency to 10 (LIMIT <- 10). + // If this fails again, the test will fail. + boolean done = false; + LOOP: do { + RequestLimiter limiter = new RequestLimiter(LIMIT.get()); + Random rand = RANDOM; + CompletableFuture<?>[] results = new CompletableFuture<?>[REQUESTS]; + Map<HttpRequest,byte[]> bodies = new ConcurrentHashMap<>(); + + long start = System.nanoTime(); + + for (int i = 0; i < REQUESTS; i++) { + byte[] buf = new byte[(i + 1) * CHUNK_SIZE + i + 1]; // different size bodies + rand.nextBytes(buf); + URI uri = new URI(baseURI.toString() + String.valueOf(i + 1)); + HttpRequest r = HttpRequest.newBuilder(uri) + .header("XFixed", "true") + .POST(BodyPublishers.ofByteArray(buf)) + .build(); + bodies.put(r, buf); + + results[i] = + limiter.whenOkToSend() + .thenCompose((v) -> { + System.out.println("Client: sendAsync: " + r.uri()); + return client.sendAsync(r, BodyHandlers.ofByteArray()); + }) + .handle((resp, t) -> { + limiter.requestComplete(); + CompletionStage<Pair<HttpResponse<byte[]>, byte[]>> res; + String now = now(start); + if (t == null) { + if (resp.statusCode() != 200) { + String s = "Expected 200, got: " + resp.statusCode(); + System.out.println(now + s + " from " + + resp.request().uri().getPath()); + res = completedWithIOException(s); + return res; + } else { + int counter = COUNT.incrementAndGet(); + System.out.println(now + "Result (" + counter + ") from " + + resp.request().uri().getPath()); + } + res = CompletableFuture.completedStage(resp.body()) + .thenApply((b) -> new Pair<>(resp, b)); + return res; + } else { + int counter = COUNT.incrementAndGet(); + System.out.println(now + "Result (" + counter + ") from " + + r.uri().getPath() + + failure(t)); + res = CompletableFuture.failedFuture(t); + return res; + } + }) + .thenCompose(c -> c) + .thenAccept((pair) -> { + HttpRequest request = pair.t.request(); + byte[] requestBody = bodies.get(request); + check(Arrays.equals(requestBody, pair.u), + "bodies not equal:[" + bytesToHexString(requestBody) + + "] [" + bytesToHexString(pair.u) + "]"); + + }); + } + + // wait for them all to complete and throw exception in case of err + try { + CompletableFuture.allOf(results).join(); + done = true; + } catch (CompletionException e) { + if (!Platform.isWindows()) throw e; + if (LIMIT.get() < REQUESTS) throw e; + Throwable cause = e; + while ((cause = cause.getCause()) != null) { + if (cause instanceof ConnectException) { + // try again, limit concurrency by half + COUNT.set(0); + LIMIT.set(REQUESTS/2); + System.out.println("*** Retrying due to " + cause); + continue LOOP; + } + } + throw e; + } + } while (!done); - // wait for them all to complete and throw exception in case of error - CompletableFuture.allOf(results).join(); } static <T> CompletableFuture<T> completedWithIOException(String message) { @@ -213,13 +295,7 @@ public class ManyRequests { return sb.toString(); } - static final class Pair<T,U> { - Pair(T t, U u) { - this.t = t; this.u = u; - } - T t; - U u; - } + record Pair<T,U>(T t, U u) { } /** * A simple limiter for controlling the number of requests to be run in diff --git a/test/jdk/java/net/httpclient/ManyRequests2.java b/test/jdk/java/net/httpclient/ManyRequests2.java index b0eee6e3be413b3be44dbf858635928958989009..49e7f758f7c14cee5916a8041df775bcdb33069e 100644 --- a/test/jdk/java/net/httpclient/ManyRequests2.java +++ b/test/jdk/java/net/httpclient/ManyRequests2.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,10 +33,14 @@ * @compile ../../../com/sun/net/httpserver/EchoHandler.java * @compile ../../../com/sun/net/httpserver/FileServerHandler.java * @build ManyRequests ManyRequests2 - * @run main/othervm/timeout=40 -Dtest.XFixed=true ManyRequests2 - * @run main/othervm/timeout=40 -Dtest.XFixed=true -Dtest.insertDelay=true ManyRequests2 - * @run main/othervm/timeout=40 -Dtest.XFixed=true -Dtest.chunkSize=64 ManyRequests2 + * @run main/othervm/timeout=40 -Dtest.XFixed=true + * -Djdk.httpclient.HttpClient.log=channel ManyRequests2 + * @run main/othervm/timeout=40 -Dtest.XFixed=true -Dtest.insertDelay=true + * -Djdk.httpclient.HttpClient.log=channel ManyRequests2 + * @run main/othervm/timeout=40 -Dtest.XFixed=true -Dtest.chunkSize=64 + * -Djdk.httpclient.HttpClient.log=channel ManyRequests2 * @run main/othervm/timeout=40 -Djdk.internal.httpclient.debug=true + * -Djdk.httpclient.HttpClient.log=channel * -Dtest.XFixed=true -Dtest.insertDelay=true * -Dtest.chunkSize=64 ManyRequests2 * @summary Send a large number of requests asynchronously. diff --git a/test/jdk/java/net/httpclient/ManyRequestsLegacy.java b/test/jdk/java/net/httpclient/ManyRequestsLegacy.java index b8d296087b9584cd37c1eb97c37e0487942f158a..0e9aba5deafa7df8dba718ae3db84ab184f7c7c7 100644 --- a/test/jdk/java/net/httpclient/ManyRequestsLegacy.java +++ b/test/jdk/java/net/httpclient/ManyRequestsLegacy.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,6 +43,7 @@ import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.HostnameVerifier; + import com.sun.net.httpserver.HttpsConfigurator; import com.sun.net.httpserver.HttpsParameters; import com.sun.net.httpserver.HttpsServer; @@ -50,12 +51,18 @@ import com.sun.net.httpserver.HttpExchange; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.net.ConnectException; import java.net.HttpURLConnection; import java.net.InetAddress; import java.net.URI; import java.net.URLConnection; +import java.util.Map; import java.util.Optional; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; @@ -73,12 +80,20 @@ import java.util.LinkedList; import java.util.Random; import java.util.logging.Logger; import java.util.logging.Level; + +import jdk.test.lib.Platform; +import jdk.test.lib.RandomFactory; import jdk.test.lib.net.SimpleSSLContext; import static java.net.Proxy.NO_PROXY; public class ManyRequestsLegacy { - volatile static int counter = 0; + static final int MAX_COUNT = 20; + static final int MAX_LIMIT = 40; + static final AtomicInteger COUNT = new AtomicInteger(); + static final AtomicInteger LIMIT = new AtomicInteger(MAX_LIMIT); + static final Random RANDOM = RandomFactory.getRandom(); + public static void main(String[] args) throws Exception { Logger logger = Logger.getLogger("com.sun.net.httpserver"); @@ -110,7 +125,7 @@ public class ManyRequestsLegacy { } //static final int REQUESTS = 1000; - static final int REQUESTS = 20; + static final int REQUESTS = MAX_COUNT; static final boolean INSERT_DELAY = Boolean.getBoolean("test.insertDelay"); static final int CHUNK_SIZE = Math.max(0, Integer.parseInt(System.getProperty("test.chunkSize", "0"))); @@ -194,7 +209,7 @@ public class ManyRequestsLegacy { } static class TestEchoHandler extends EchoHandler { - final Random rand = new Random(); + final Random rand = RANDOM; @Override public void handle(HttpExchange e) throws IOException { System.out.println("Server: received " + e.getRequestURI()); @@ -220,60 +235,119 @@ public class ManyRequestsLegacy { } } + static String now(long start) { + long elapsed = System.nanoTime() - start; + long ms = elapsed / 1000_000L; + long s = ms / 1000L; + if (s == 0) return ms + "ms: "; + return s + "s, " + (ms - s * 1000L) + "ms: "; + } + + static String failure(Throwable t) { + String s = "\n\t failed: " + t; + for (t = t.getCause(); t != null ; t = t.getCause()) { + s = s + "\n\t\t Caused by: " + t; + } + return s; + } + static void test(HttpsServer server, LegacyHttpClient client) throws Exception { int port = server.getAddress().getPort(); URI baseURI = new URI("https://localhost:" + port + "/foo/x"); server.createContext("/foo", new TestEchoHandler()); server.start(); - RequestLimiter limiter = new RequestLimiter(40); - Random rand = new Random(); - CompletableFuture<?>[] results = new CompletableFuture<?>[REQUESTS]; - HashMap<HttpRequest,byte[]> bodies = new HashMap<>(); - - for (int i=0; i<REQUESTS; i++) { - byte[] buf = new byte[(i+1)*CHUNK_SIZE+i+1]; // different size bodies - rand.nextBytes(buf); - URI uri = new URI(baseURI.toString() + String.valueOf(i+1)); - HttpRequest r = HttpRequest.newBuilder(uri) - .header("XFixed", "true") - .POST(BodyPublishers.ofByteArray(buf)) - .build(); - bodies.put(r, buf); - - results[i] = - limiter.whenOkToSend() - .thenCompose((v) -> { - System.out.println("Client: sendAsync: " + r.uri()); - return client.sendAsync(r, buf); - }) - .thenCompose((resp) -> { - limiter.requestComplete(); - if (resp.statusCode() != 200) { - String s = "Expected 200, got: " + resp.statusCode(); - System.out.println(s + " from " - + resp.request().uri().getPath()); - return completedWithIOException(s); - } else { - counter++; - System.out.println("Result (" + counter + ") from " - + resp.request().uri().getPath()); - } - return CompletableFuture.completedStage(resp.body()) - .thenApply((b) -> new Pair<>(resp, b)); - }) - .thenAccept((pair) -> { - HttpRequest request = pair.t.request(); - byte[] requestBody = bodies.get(request); - check(Arrays.equals(requestBody, pair.u), - "bodies not equal:[" + bytesToHexString(requestBody) - + "] [" + bytesToHexString(pair.u) + "]"); - - }); - } + // This loop implements a retry mechanism to work around an issue + // on some systems (observed on Windows 10) that seem to be trying to + // throttle the number of connections that can be made concurrently by + // rejecting connection attempts. + // On the first iteration of this loop, we will attempt 20 concurrent + // requests. If this fails with ConnectException, we will retry the + // 20 requests, but limiting the concurrency to 10 (LIMIT <- 10). + // If this fails again, the test will fail. + boolean done = false; + LOOP: do { + RequestLimiter limiter = new RequestLimiter(LIMIT.get()); + Random rand = RANDOM; + CompletableFuture<?>[] results = new CompletableFuture<?>[REQUESTS]; + Map<HttpRequest,byte[]> bodies = new ConcurrentHashMap<>(); + long start = System.nanoTime(); + + for (int i = 0; i < REQUESTS; i++) { + byte[] buf = new byte[(i + 1) * CHUNK_SIZE + i + 1]; // different size bodies + rand.nextBytes(buf); + URI uri = new URI(baseURI.toString() + String.valueOf(i + 1)); + HttpRequest r = HttpRequest.newBuilder(uri) + .header("XFixed", "true") + .POST(BodyPublishers.ofByteArray(buf)) + .build(); + bodies.put(r, buf); + + results[i] = + limiter.whenOkToSend() + .thenCompose((v) -> { + System.out.println("Client: sendAsync: " + r.uri()); + return client.sendAsync(r, buf); + }) + .handle((resp, t) -> { + limiter.requestComplete(); + CompletionStage<Pair<HttpResponse<byte[]>, byte[]>> res; + String now = now(start); + if (t == null) { + if (resp.statusCode() != 200) { + String s = "Expected 200, got: " + resp.statusCode(); + System.out.println(now + s + " from " + + resp.request().uri().getPath()); + res = completedWithIOException(s); + return res; + } else { + int counter = COUNT.incrementAndGet(); + System.out.println(now + "Result (" + counter + ") from " + + resp.request().uri().getPath()); + } + res = CompletableFuture.completedStage(resp.body()) + .thenApply((b) -> new Pair<>(resp, b)); + return res; + } else { + int counter = COUNT.incrementAndGet(); + System.out.println(now + "Result (" + counter + ") from " + + r.uri().getPath() + + failure(t)); + res = CompletableFuture.failedFuture(t); + return res; + } + }) + .thenCompose(c -> c) + .thenAccept((pair) -> { + HttpRequest request = pair.t.request(); + byte[] requestBody = bodies.get(request); + check(Arrays.equals(requestBody, pair.u), + "bodies not equal:[" + bytesToHexString(requestBody) + + "] [" + bytesToHexString(pair.u) + "]"); + + }); + } - // wait for them all to complete and throw exception in case of error - CompletableFuture.allOf(results).join(); + try { + // wait for them all to complete and throw exception in case of error + CompletableFuture.allOf(results).join(); + done = true; + } catch (CompletionException e) { + if (!Platform.isWindows()) throw e; + if (LIMIT.get() < REQUESTS) throw e; + Throwable cause = e; + while ((cause = cause.getCause()) != null) { + if (cause instanceof ConnectException) { + // try again, limit concurrency by half + COUNT.set(0); + LIMIT.set(REQUESTS/2); + System.out.println("*** Retrying due to " + cause); + continue LOOP; + } + } + throw e; + } + } while (!done); } static <T> CompletableFuture<T> completedWithIOException(String message) { @@ -294,13 +368,7 @@ public class ManyRequestsLegacy { return sb.toString(); } - static final class Pair<T,U> { - Pair(T t, U u) { - this.t = t; this.u = u; - } - T t; - U u; - } + record Pair<T,U>(T t, U u) { } /** * A simple limiter for controlling the number of requests to be run in diff --git a/test/jdk/java/net/httpclient/http2/server/Http2TestServer.java b/test/jdk/java/net/httpclient/http2/server/Http2TestServer.java index 33e5ade4f8340d89c7c5a81a278b0faef65b49cf..f8592272588781d37dac70a26600d8ac6f5b5239 100644 --- a/test/jdk/java/net/httpclient/http2/server/Http2TestServer.java +++ b/test/jdk/java/net/httpclient/http2/server/Http2TestServer.java @@ -124,6 +124,20 @@ public class Http2TestServer implements AutoCloseable { this(serverName, secure, port, exec, backlog, properties, context, false); } + public Http2TestServer(String serverName, + boolean secure, + int port, + ExecutorService exec, + int backlog, + Properties properties, + SSLContext context, + boolean supportsHTTP11) + throws Exception + { + this(InetAddress.getLoopbackAddress(), serverName, secure, port, exec, + backlog, properties, context, supportsHTTP11); + } + /** * Create a Http2Server listening on the given port. Currently needs * to know in advance whether incoming connections are plain TCP "h2c" @@ -134,6 +148,7 @@ public class Http2TestServer implements AutoCloseable { * "X-Magic", "HTTP/1.1 request received by HTTP/2 server", * "X-Received-Body", <the request body>); * + * @param localAddr local address to bind to * @param serverName SNI servername * @param secure https or http * @param port listen port @@ -146,7 +161,8 @@ public class Http2TestServer implements AutoCloseable { * connection without the h2 ALPN. Otherwise, false to operate in * HTTP/2 mode exclusively. */ - public Http2TestServer(String serverName, + public Http2TestServer(InetAddress localAddr, + String serverName, boolean secure, int port, ExecutorService exec, @@ -163,7 +179,7 @@ public class Http2TestServer implements AutoCloseable { this.sslContext = context; else this.sslContext = SSLContext.getDefault(); - server = initSecure(port, backlog); + server = initSecure(localAddr, port, backlog); } else { this.sslContext = context; server = initPlaintext(port, backlog); @@ -236,14 +252,14 @@ public class Http2TestServer implements AutoCloseable { } - final ServerSocket initSecure(int port, int backlog) throws Exception { + final ServerSocket initSecure(InetAddress localAddr, int port, int backlog) throws Exception { ServerSocketFactory fac; SSLParameters sslp = null; fac = sslContext.getServerSocketFactory(); sslp = sslContext.getSupportedSSLParameters(); SSLServerSocket se = (SSLServerSocket) fac.createServerSocket(); se.setReuseAddress(false); - se.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), backlog); + se.bind(new InetSocketAddress(localAddr, 0), backlog); if (supportsHTTP11) { sslp.setApplicationProtocols(new String[]{"h2", "http/1.1"}); } else { diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/PublisherVerificationRules.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/PublisherVerificationRules.java index 823a5174652c5fe03b6d232e658c70ea91037892..3af007cb9e1a190617ee5ecbf6a726ce6d008893 100644 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/PublisherVerificationRules.java +++ b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/PublisherVerificationRules.java @@ -126,7 +126,7 @@ public interface PublisherVerificationRules { * <p> * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 10. * <p> - * Note that this test is probabilistic, that is, may not capture any concurrent invocation in a {code Publisher} implementation. + * Note that this test is probabilistic, that is, may not capture any concurrent invocation in a {@code Publisher} implementation. * Note also that this test is sensitive to cases when a {@code request()} call in {@code onSubscribe()} triggers an asynchronous * call to the other {@code onXXX} methods. In contrast, the test allows synchronous call chain of * {@code onSubscribe -> request -> onNext}. diff --git a/test/jdk/java/nio/channels/Channels/ReadXBytes.java b/test/jdk/java/nio/channels/Channels/ReadXBytes.java index 1f36d4031fd09f9af4a490c9182a8f51efd8cad5..f146d629da189e4812d6e9212daaab99c82c66d1 100644 --- a/test/jdk/java/nio/channels/Channels/ReadXBytes.java +++ b/test/jdk/java/nio/channels/Channels/ReadXBytes.java @@ -25,12 +25,12 @@ * @test * @bug 8268435 8274780 * @summary Verify ChannelInputStream methods readAllBytes and readNBytes - * @requires vm.bits == 64 + * @requires (sun.arch.data.model == "64" & os.maxMemory >= 16g) * @library .. * @library /test/lib * @build jdk.test.lib.RandomFactory * @modules java.base/jdk.internal.util - * @run testng/othervm/timeout=900 -Xmx8G ReadXBytes + * @run testng/othervm/timeout=900 -Xmx12G ReadXBytes * @key randomness */ import java.io.File; @@ -38,7 +38,7 @@ import java.io.FileInputStream; import java.io.FilterInputStream; import java.io.InputStream; import java.io.IOException; -import java.io.RandomAccessFile; +import java.nio.ByteBuffer; import java.nio.channels.Channel; import java.nio.channels.Channels; import java.nio.channels.FileChannel; @@ -46,11 +46,12 @@ import java.nio.channels.ReadableByteChannel; import java.nio.channels.SeekableByteChannel; import java.nio.file.Files; import java.nio.file.Path; -import static java.nio.file.StandardOpenOption.READ; import java.util.List; import java.util.Random; import jdk.internal.util.ArraysSupport; +import static java.nio.file.StandardOpenOption.*; + import jdk.test.lib.RandomFactory; import org.testng.Assert; @@ -72,30 +73,51 @@ public class ReadXBytes { // A length greater than a 32-bit integer can accommodate private static final long HUGE_LENGTH = Integer.MAX_VALUE + 27L; + // Current directory + private static final Path DIR = Path.of(System.getProperty("test.dir", ".")); + // --- Framework --- + // Create a temporary file path + static Path createFilePath() { + String name = String.format("ReadXBytes%d.tmp", System.nanoTime()); + return DIR.resolve(name); + } + // Creates a temporary file of a specified length with undefined content static Path createFile(long length) throws IOException { - File file = File.createTempFile("foo", ".bar"); - file.deleteOnExit(); - try (RandomAccessFile raf = new RandomAccessFile(file, "rw")) { - raf.setLength(length); + Path path = createFilePath(); + path.toFile().deleteOnExit(); + try (FileChannel fc = FileChannel.open(path, CREATE_NEW, SPARSE, WRITE)) { + if (length > 0) { + fc.position(length - 1); + fc.write(ByteBuffer.wrap(new byte[] {27})); + } } - return file.toPath(); + return path; } // Creates a temporary file of a specified length with random content static Path createFileWithRandomContent(long length) throws IOException { Path file = createFile(length); - try (RandomAccessFile raf = new RandomAccessFile(file.toFile(), "rw")) { - long written = 0L; - int bufLength = Math.min(32768, (int)Math.min(length, BIG_LENGTH)); + try (FileChannel fc = FileChannel.open(file, WRITE);) { + long pos = 0L; + // if the length exceeds 2 GB, skip the first 2 GB - 1 MB bytes + if (length >= 2L*1024*1024*1024) { + // write the last (length - 2GB - 1MB) bytes + pos = 2047L*1024*1024; + } else if (length > 0) { + // write either the first or last bytes only + long p = Math.min(Math.abs(RAND.nextLong()), length - 1); + pos = RAND.nextBoolean() ? p : length - 1 - p; + } + fc.position(pos); + int bufLength = Math.min(32768, (int)Math.min(length - pos, BIG_LENGTH)); byte[] buf = new byte[bufLength]; - while (written < length) { + while (pos < length) { RAND.nextBytes(buf); - int len = (int)Math.min(bufLength, length - written); - raf.write(buf, 0, len); - written += len; + int len = (int)Math.min(bufLength, length - pos); + pos += fc.write(ByteBuffer.wrap(buf, 0, len)); } } return file; diff --git a/test/jdk/java/nio/channels/Channels/TransferTo.java b/test/jdk/java/nio/channels/Channels/TransferTo.java index 792419c2ff3ac762857d9c4ded819d8eff81ceb9..e7fa169788c3bb57847df5ea115b442d9b5b5d3e 100644 --- a/test/jdk/java/nio/channels/Channels/TransferTo.java +++ b/test/jdk/java/nio/channels/Channels/TransferTo.java @@ -23,16 +23,25 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; -import java.io.IOException; import java.io.InputStream; +import java.io.IOException; import java.io.OutputStream; +import java.nio.ByteBuffer; import java.nio.channels.Channels; import java.nio.channels.FileChannel; +import java.nio.channels.IllegalBlockingModeException; +import java.nio.channels.Pipe; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.SelectableChannel; +import java.nio.channels.WritableByteChannel; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardOpenOption; import java.util.Arrays; import java.util.Random; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; import java.util.function.Supplier; @@ -43,6 +52,7 @@ import org.testng.annotations.Test; import jdk.test.lib.RandomFactory; import static java.lang.String.format; +import static java.nio.file.StandardOpenOption.*; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertThrows; @@ -54,8 +64,8 @@ import static org.testng.Assert.assertTrue; * @build jdk.test.lib.RandomFactory * @run testng/othervm/timeout=180 TransferTo * @bug 8265891 - * @summary tests whether sun.nio.ChannelInputStream.transferTo conforms to the - * InputStream.transferTo contract defined in the javadoc + * @summary Tests whether sun.nio.ChannelInputStream.transferTo conforms to the + * InputStream.transferTo specification * @key randomness */ public class TransferTo { @@ -64,14 +74,17 @@ public class TransferTo { private static final int ITERATIONS = 10; - private static final int NUM_WRITES = 3 * 1024; - private static final int BYTES_PER_WRITE = 1024 * 1024; - private static final long BYTES_WRITTEN = (long) NUM_WRITES * BYTES_PER_WRITE; + private static final int NUM_WRITES = 3*1024; + private static final int BYTES_PER_WRITE = 1024*1024; + private static final long BYTES_WRITTEN = (long) NUM_WRITES*BYTES_PER_WRITE; private static final Random RND = RandomFactory.getRandom(); + private static final Path CWD = Path.of("."); + /* - * Provides test scenarios, i. e. combinations of input and output streams to be tested. + * Provides test scenarios, i.e., combinations of input and output streams + * to be tested. */ @DataProvider public static Object[][] streamCombinations() throws Exception { @@ -79,13 +92,22 @@ public class TransferTo { // tests FileChannel.transferTo(FileChannel) optimized case { fileChannelInput(), fileChannelOutput() }, + // tests FileChannel.transferTo(SelectableChannelOutput) + // optimized case + { fileChannelInput(), selectableChannelOutput() }, + + // tests FileChannel.transferTo(WritableChannelOutput) + // optimized case + { fileChannelInput(), writableByteChannelOutput() }, + // tests InputStream.transferTo(OutputStream) default case { readableByteChannelInput(), defaultOutput() } }; } /* - * Testing API compliance: Input stream must throw NullPointerException when parameter "out" is null. + * Testing API compliance: input stream must throw NullPointerException + * when parameter "out" is null. */ @Test(dataProvider = "streamCombinations") public void testNullPointerException(InputStreamProvider inputStreamProvider, @@ -101,7 +123,8 @@ public class TransferTo { } /* - * Testing API compliance: Complete content of input stream must be transferred to output stream. + * Testing API compliance: complete content of input stream must be + * transferred to output stream. */ @Test(dataProvider = "streamCombinations") public void testStreamContents(InputStreamProvider inputStreamProvider, @@ -112,10 +135,12 @@ public class TransferTo { // tests input stream with a length between 1k and 4k checkTransferredContents(inputStreamProvider, outputStreamProvider, createRandomBytes(1024, 4096)); - // tests input stream with several data chunks, as 16k is more than a single chunk can hold + // tests input stream with several data chunks, as 16k is more than a + // single chunk can hold checkTransferredContents(inputStreamProvider, outputStreamProvider, createRandomBytes(16384, 16384)); - // tests randomly chosen starting positions within source and target stream + // tests randomly chosen starting positions within source and + // target stream for (int i = 0; i < ITERATIONS; i++) { byte[] inBytes = createRandomBytes(MIN_SIZE, MAX_SIZE_INCR); int posIn = RND.nextInt(inBytes.length); @@ -131,34 +156,60 @@ public class TransferTo { } /* - * Special test for file-to-file transfer of more than two GB. - * This test covers multiple iterations of FileChannel.transerTo(FileChannel), - * which ChannelInputStream.transferTo() only applies in this particular case, - * and cannot get tested using a single byte[] due to size limitation of arrays. + * Special test for file-to-file transfer of more than 2 GB. This test + * covers multiple iterations of FileChannel.transerTo(FileChannel), + * which ChannelInputStream.transferTo() only applies in this particular + * case, and cannot get tested using a single byte[] due to size limitation + * of arrays. */ @Test public void testMoreThanTwoGB() throws IOException { - Path sourceFile = Files.createTempFile("test2GBSource", null); + // prepare two temporary files to be compared at the end of the test + // set the source file name + String sourceName = String.format("test3GBSource%s.tmp", + String.valueOf(RND.nextInt(Integer.MAX_VALUE))); + Path sourceFile = CWD.resolve(sourceName); + try { - // preparing two temporary files which will be compared at the end of the test - Path targetFile = Files.createTempFile("test2GBtarget", null); + // set the target file name + String targetName = String.format("test3GBTarget%s.tmp", + String.valueOf(RND.nextInt(Integer.MAX_VALUE))); + Path targetFile = CWD.resolve(targetName); + try { - // writing 3 GB of random bytes into source file - for (int i = 0; i < NUM_WRITES; i++) - Files.write(sourceFile, createRandomBytes(BYTES_PER_WRITE, 0), StandardOpenOption.APPEND); + // calculate initial position to be just short of 2GB + final long initPos = 2047*BYTES_PER_WRITE; + + // create the source file with a hint to be sparse + try (FileChannel fc = FileChannel.open(sourceFile, CREATE_NEW, SPARSE, WRITE, APPEND);) { + // set initial position to avoid writing nearly 2GB + fc.position(initPos); + + // fill the remainder of the file with random bytes + int nw = (int)(NUM_WRITES - initPos/BYTES_PER_WRITE); + for (int i = 0; i < nw; i++) { + byte[] rndBytes = createRandomBytes(BYTES_PER_WRITE, 0); + ByteBuffer src = ByteBuffer.wrap(rndBytes); + fc.write(src); + } + } - // performing actual transfer, effectively by multiple invocations of Filechannel.transferTo(FileChannel) - long count; - try (InputStream inputStream = Channels.newInputStream(FileChannel.open(sourceFile)); - OutputStream outputStream = Channels - .newOutputStream(FileChannel.open(targetFile, StandardOpenOption.WRITE))) { - count = inputStream.transferTo(outputStream); + // create the target file with a hint to be sparse + try (FileChannel fc = FileChannel.open(targetFile, CREATE_NEW, WRITE, SPARSE);) { } - // comparing reported transferred bytes, must be 3 GB - assertEquals(count, BYTES_WRITTEN); + // perform actual transfer, effectively by multiple invocations + // of Filechannel.transferTo(FileChannel) + try (InputStream inputStream = Channels.newInputStream(FileChannel.open(sourceFile)); + OutputStream outputStream = Channels.newOutputStream(FileChannel.open(targetFile, WRITE))) { + long count = inputStream.transferTo(outputStream); - // comparing content of both files, failing in case of any difference + // compare reported transferred bytes, must be 3 GB + // less the value of the initial position + assertEquals(count, BYTES_WRITTEN - initPos); + } + + // compare content of both files, failing if different assertEquals(Files.mismatch(sourceFile, targetFile), -1); } finally { @@ -170,9 +221,45 @@ public class TransferTo { } /* - * Asserts that the transferred content is correct, i. e. compares the actually transferred bytes - * to the expected assumption. The position of the input and output stream before the transfer is - * the start of stream (BOF). + * Special test of whether selectable channel based transfer throws blocking + * mode exception. + */ + @Test + public void testIllegalBlockingMode() throws IOException { + Pipe pipe = Pipe.open(); + try { + // testing arbitrary input (here: empty file) to non-blocking + // selectable output + try (FileChannel fc = FileChannel.open(Files.createTempFile(CWD, "testIllegalBlockingMode", null)); + InputStream is = Channels.newInputStream(fc); + SelectableChannel sc = pipe.sink().configureBlocking(false); + OutputStream os = Channels.newOutputStream((WritableByteChannel) sc)) { + + // IllegalBlockingMode must be thrown when trying to perform + // a transfer + assertThrows(IllegalBlockingModeException.class, () -> is.transferTo(os)); + } + + // testing non-blocking selectable input to arbitrary output + // (here: byte array) + try (SelectableChannel sc = pipe.source().configureBlocking(false); + InputStream is = Channels.newInputStream((ReadableByteChannel) sc); + OutputStream os = new ByteArrayOutputStream()) { + + // IllegalBlockingMode must be thrown when trying to perform + // a transfer + assertThrows(IllegalBlockingModeException.class, () -> is.transferTo(os)); + } + } finally { + pipe.source().close(); + pipe.sink().close(); + } + } + + /* + * Asserts that the transferred content is correct, i.e., compares the bytes + * actually transferred to those expected. The position of the input and + * output streams before the transfer are zero (BOF). */ private static void checkTransferredContents(InputStreamProvider inputStreamProvider, OutputStreamProvider outputStreamProvider, byte[] inBytes) throws Exception { @@ -180,16 +267,16 @@ public class TransferTo { } /* - * Asserts that the transferred content is correct, i. e. compares the actually transferred bytes - * to the expected assumption. The position of the input and output stream before the transfer is - * provided by the caller. + * Asserts that the transferred content is correct, i. e. compares the bytes + * actually transferred to those expected. The positions of the input and + * output streams before the transfer are provided by the caller. */ private static void checkTransferredContents(InputStreamProvider inputStreamProvider, OutputStreamProvider outputStreamProvider, byte[] inBytes, int posIn, int posOut) throws Exception { AtomicReference<Supplier<byte[]>> recorder = new AtomicReference<>(); try (InputStream in = inputStreamProvider.input(inBytes); - OutputStream out = outputStreamProvider.output(recorder::set)) { - // skip bytes till starting position + OutputStream out = outputStreamProvider.output(recorder::set)) { + // skip bytes until starting position in.skipNBytes(posIn); out.write(new byte[posOut]); @@ -205,7 +292,8 @@ public class TransferTo { } /* - * Creates an array of random size (between min and min + maxRandomAdditive) filled with random bytes + * Creates an array of random size (between min and min + maxRandomAdditive) + * filled with random bytes */ private static byte[] createRandomBytes(int min, int maxRandomAdditive) { byte[] bytes = new byte[min + (maxRandomAdditive == 0 ? 0 : RND.nextInt(maxRandomAdditive))]; @@ -242,7 +330,7 @@ public class TransferTo { return new InputStreamProvider() { @Override public InputStream input(byte... bytes) throws Exception { - Path path = Files.createTempFile(null, null); + Path path = Files.createTempFile(CWD, "fileChannelInput", null); Files.write(path, bytes); FileChannel fileChannel = FileChannel.open(path); return Channels.newInputStream(fileChannel); @@ -251,7 +339,8 @@ public class TransferTo { } /* - * Creates a provider for an input stream which wraps a readable byte channel but is not a file channel + * Creates a provider for an input stream which wraps a readable byte + * channel but is not a file channel */ private static InputStreamProvider readableByteChannelInput() { return new InputStreamProvider() { @@ -268,8 +357,8 @@ public class TransferTo { private static OutputStreamProvider fileChannelOutput() { return new OutputStreamProvider() { public OutputStream output(Consumer<Supplier<byte[]>> spy) throws Exception { - Path path = Files.createTempFile(null, null); - FileChannel fileChannel = FileChannel.open(path, StandardOpenOption.WRITE); + Path path = Files.createTempFile(CWD, "fileChannelOutput", null); + FileChannel fileChannel = FileChannel.open(path, WRITE); spy.accept(() -> { try { return Files.readAllBytes(path); @@ -282,4 +371,39 @@ public class TransferTo { }; } + private static OutputStreamProvider selectableChannelOutput() throws IOException { + return new OutputStreamProvider() { + public OutputStream output(Consumer<Supplier<byte[]>> spy) throws Exception { + Pipe pipe = Pipe.open(); + Future<byte[]> bytes = CompletableFuture.supplyAsync(() -> { + try { + InputStream is = Channels.newInputStream(pipe.source()); + return is.readAllBytes(); + } catch (IOException e) { + throw new AssertionError("Exception while asserting content", e); + } + }); + final OutputStream os = Channels.newOutputStream(pipe.sink()); + spy.accept(() -> { + try { + os.close(); + return bytes.get(); + } catch (IOException | InterruptedException | ExecutionException e) { + throw new AssertionError("Exception while asserting content", e); + } + }); + return os; + } + }; + } + + private static OutputStreamProvider writableByteChannelOutput() { + return new OutputStreamProvider() { + public OutputStream output(Consumer<Supplier<byte[]>> spy) throws Exception { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + spy.accept(outputStream::toByteArray); + return Channels.newOutputStream(Channels.newChannel(outputStream)); + } + }; + } } diff --git a/test/jdk/java/nio/channels/FileChannel/BlockDeviceSize.java b/test/jdk/java/nio/channels/FileChannel/BlockDeviceSize.java index aafe4192d3241b93f7a54c1660813f85ff1d6036..496312256beb5632ecb76710a75616403321be40 100644 --- a/test/jdk/java/nio/channels/FileChannel/BlockDeviceSize.java +++ b/test/jdk/java/nio/channels/FileChannel/BlockDeviceSize.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ /* @test * @bug 8054029 + * @requires (os.family == "linux") * @summary Block devices should not report size=0 on Linux */ diff --git a/test/jdk/java/nio/channels/Selector/CustomFileSystem.java b/test/jdk/java/nio/channels/Selector/CustomFileSystem.java new file mode 100644 index 0000000000000000000000000000000000000000..8113a7169105af14a1dcc2adb3a2b83c30233760 --- /dev/null +++ b/test/jdk/java/nio/channels/Selector/CustomFileSystem.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, JetBrains s.r.o.. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @summary Verifies that an attempt to call Selector.open() on a non-default + * file system succeeds. + * @build CustomFileSystem CustomFileSystemProvider + * @run main/othervm -Djava.nio.file.spi.DefaultFileSystemProvider=CustomFileSystemProvider CustomFileSystem + */ + +public class CustomFileSystem { + public static void main(String args[]) throws java.io.IOException { + java.nio.channels.Selector.open(); + } +} diff --git a/test/jdk/java/nio/channels/Selector/CustomFileSystemProvider.java b/test/jdk/java/nio/channels/Selector/CustomFileSystemProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..f3e876e08a7447ccc061ac6cc1985f5fc89f5408 --- /dev/null +++ b/test/jdk/java/nio/channels/Selector/CustomFileSystemProvider.java @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, JetBrains s.r.o.. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.nio.channels.FileChannel; +import java.nio.channels.SeekableByteChannel; +import java.nio.file.AccessMode; +import java.nio.file.CopyOption; +import java.nio.file.DirectoryStream; +import java.nio.file.FileStore; +import java.nio.file.FileSystem; +import java.nio.file.LinkOption; +import java.nio.file.OpenOption; +import java.nio.file.Path; +import java.nio.file.ReadOnlyFileSystemException; +import java.nio.file.attribute.BasicFileAttributes; +import java.nio.file.attribute.FileAttribute; +import java.nio.file.attribute.FileAttributeView; +import java.nio.file.attribute.UserPrincipalLookupService; +import java.nio.file.spi.FileSystemProvider; +import java.util.Collections; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +public class CustomFileSystemProvider extends FileSystemProvider { + + private final FileSystemProvider defaultProvider; + + public CustomFileSystemProvider(FileSystemProvider defaultProvider) { + this.defaultProvider = defaultProvider; + } + + FileSystemProvider defaultProvider() { + return defaultProvider; + } + + @Override + public String getScheme() { + return "file"; + } + + @Override + public FileSystem newFileSystem(URI uri, Map<String,?> env) throws IOException { + return defaultProvider.newFileSystem(uri, env); + } + + @Override + public FileSystem getFileSystem(URI uri) { + return defaultProvider.getFileSystem(uri); + } + + @Override + public Path getPath(URI uri) { + return defaultProvider.getPath(uri); + } + + @Override + public void setAttribute(Path file, String attribute, Object value, + LinkOption... options) + throws IOException + { + throw new RuntimeException("not implemented"); + } + + @Override + public Map<String,Object> readAttributes(Path file, String attributes, + LinkOption... options) + throws IOException + { + throw new RuntimeException("not implemented"); + } + + @Override + public <A extends BasicFileAttributes> A readAttributes(Path file, + Class<A> type, + LinkOption... options) + throws IOException + { + throw new RuntimeException("not implemented"); + } + + @Override + public <V extends FileAttributeView> V getFileAttributeView(Path file, + Class<V> type, + LinkOption... options) + { + throw new RuntimeException("not implemented"); + } + + @Override + public boolean isHidden(Path file) throws IOException { + throw new ReadOnlyFileSystemException(); + } + + @Override + public boolean isSameFile(Path file, Path other) throws IOException { + throw new RuntimeException("not implemented"); + } + + @Override + public void checkAccess(Path file, AccessMode... modes) + throws IOException + { + throw new RuntimeException("not implemented"); + } + + @Override + public void copy(Path source, Path target, CopyOption... options) + throws IOException + { + throw new RuntimeException("not implemented"); + } + + @Override + public void move(Path source, Path target, CopyOption... options) + throws IOException + { + throw new RuntimeException("not implemented"); + } + + @Override + public void delete(Path file) throws IOException { + throw new RuntimeException("not implemented"); + } + + @Override + public void createSymbolicLink(Path link, Path target, FileAttribute<?>... attrs) + throws IOException + { + throw new RuntimeException("not implemented"); + } + + @Override + public void createLink(Path link, Path existing) throws IOException { + throw new RuntimeException("not implemented"); + } + + @Override + public Path readSymbolicLink(Path link) throws IOException { + throw new RuntimeException("not implemented"); + } + + @Override + public void createDirectory(Path dir, FileAttribute<?>... attrs) + throws IOException + { + throw new RuntimeException("not implemented"); + } + + @Override + public DirectoryStream<Path> newDirectoryStream(Path dir, + DirectoryStream.Filter<? super Path> filter) + throws IOException + { + throw new RuntimeException("not implemented"); + } + + @Override + public SeekableByteChannel newByteChannel(Path file, + Set<? extends OpenOption> options, + FileAttribute<?>... attrs) + throws IOException + { + throw new RuntimeException("not implemented"); + } + + @Override + public FileChannel newFileChannel(Path file, + Set<? extends OpenOption> options, + FileAttribute<?>... attrs) + throws IOException + { + throw new RuntimeException("not implemented"); + } + + @Override + public FileStore getFileStore(Path file) throws IOException { + throw new RuntimeException("not implemented"); + } +} diff --git a/test/jdk/java/nio/file/Files/probeContentType/Basic.java b/test/jdk/java/nio/file/Files/probeContentType/Basic.java index 0812f886c30bcb4b8b14bb7082fb231ea8d662d3..b404673b2f4ff081f3963d1314a2bfbfb06067b6 100644 --- a/test/jdk/java/nio/file/Files/probeContentType/Basic.java +++ b/test/jdk/java/nio/file/Files/probeContentType/Basic.java @@ -110,8 +110,8 @@ public class Basic { + " cannot be determined"); failures++; } else if (!expectedTypes.contains(type)) { - System.err.printf("Content type: %s; expected: %s%n", - type, expectedTypes); + System.err.printf("For extension %s we got content type: %s; expected: %s%n", + extension, type, expectedTypes); failures++; } } finally { @@ -155,7 +155,7 @@ public class Basic { // Verify that certain extensions are mapped to the correct type. var exTypes = new ExType[] { new ExType("adoc", List.of("text/plain")), - new ExType("bz2", List.of("application/bz2", "application/x-bzip2")), + new ExType("bz2", List.of("application/bz2", "application/x-bzip2", "application/x-bzip")), new ExType("css", List.of("text/css")), new ExType("csv", List.of("text/csv")), new ExType("doc", List.of("application/msword")), @@ -166,19 +166,19 @@ public class Basic { new ExType("js", List.of("text/javascript", "application/javascript")), new ExType("json", List.of("application/json")), new ExType("markdown", List.of("text/markdown")), - new ExType("md", List.of("text/markdown")), + new ExType("md", List.of("text/markdown", "application/x-genesis-rom")), new ExType("mp3", List.of("audio/mpeg")), new ExType("mp4", List.of("video/mp4")), new ExType("odp", List.of("application/vnd.oasis.opendocument.presentation")), new ExType("ods", List.of("application/vnd.oasis.opendocument.spreadsheet")), new ExType("odt", List.of("application/vnd.oasis.opendocument.text")), new ExType("pdf", List.of("application/pdf")), - new ExType("php", List.of("text/plain", "text/php")), + new ExType("php", List.of("text/plain", "text/php", "application/x-php")), new ExType("png", List.of("image/png")), new ExType("ppt", List.of("application/vnd.ms-powerpoint")), new ExType("pptx",List.of("application/vnd.openxmlformats-officedocument.presentationml.presentation")), new ExType("py", List.of("text/plain", "text/x-python", "text/x-python-script")), - new ExType("rar", List.of("application/rar", "application/vnd.rar")), + new ExType("rar", List.of("application/rar", "application/vnd.rar", "application/x-rar")), new ExType("rtf", List.of("application/rtf", "text/rtf")), new ExType("webm", List.of("video/webm")), new ExType("webp", List.of("image/webp")), diff --git a/test/jdk/java/nio/file/attribute/UserDefinedFileAttributeView/Basic.java b/test/jdk/java/nio/file/attribute/UserDefinedFileAttributeView/Basic.java index bc47b8719f28ccd984698f0d00eb6dc6abbfb67d..00ab4670ba6d6d9b34a0a07c4bc9721639da6eb1 100644 --- a/test/jdk/java/nio/file/attribute/UserDefinedFileAttributeView/Basic.java +++ b/test/jdk/java/nio/file/attribute/UserDefinedFileAttributeView/Basic.java @@ -242,7 +242,7 @@ public class Basic { // We need to run up to MAX_PATH for directories, // but not quite go over it. - int MAX_PATH = 247; + int MAX_PATH = 250; int requiredLen = MAX_PATH - len - 2; // Create a really long directory name. @@ -252,11 +252,15 @@ public class Basic { Files.createDirectory(longPath); try { - // Try to set absolute path as extended attribute; expect IAE + System.out.println("Testing " + longPath); + + // Try to set absolute path as extended attribute; + // expect IAE tryCatch(IllegalArgumentException.class, new Task() { public void run() throws IOException { setEA(longPath, "user:C:\\"); - }}); + } + }); // Try to set an extended attribute on it. setEA(longPath, "user:short"); diff --git a/test/jdk/java/security/KeyStore/PKCS12/UnmodifiableAttributes.java b/test/jdk/java/security/KeyStore/PKCS12/UnmodifiableAttributes.java new file mode 100644 index 0000000000000000000000000000000000000000..ae38a6af71ec578970d1107aa405d5ca7115ae80 --- /dev/null +++ b/test/jdk/java/security/KeyStore/PKCS12/UnmodifiableAttributes.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8278744 + * @summary KeyStore:getAttributes() not returning unmodifiable Set + * @library /test/lib + */ + +import jdk.test.lib.SecurityTools; +import jdk.test.lib.Utils; + +import java.io.File; +import java.security.KeyStore; + +public class UnmodifiableAttributes { + public static final void main(String[] args) throws Exception { + + var oneAttr = new KeyStore.Entry.Attribute() { + @Override + public String getName() { + return "1.2.3"; + } + + @Override + public String getValue() { + return "testVal"; + } + }; + char[] pass = "changeit".toCharArray(); + + SecurityTools.keytool("-keystore ks -storepass changeit -genkeypair -alias a -dname CN=A -keyalg EC") + .shouldHaveExitValue(0); + + KeyStore ks = KeyStore.getInstance(new File("ks"), pass); + + var attrs = ks.getAttributes("a"); + Utils.runAndCheckException(() -> attrs.add(oneAttr), UnsupportedOperationException.class); + + var attrs2 = ks.getEntry("a", new KeyStore.PasswordProtection(pass)).getAttributes(); + Utils.runAndCheckException(() -> attrs2.add(oneAttr), UnsupportedOperationException.class); + } +} diff --git a/test/jdk/java/security/MessageDigest/ThreadSafetyTest.java b/test/jdk/java/security/MessageDigest/ThreadSafetyTest.java index 41ecbca2677b5188f05d0ce15ad771ae5859ca38..594e9926eabbf7ea83b8c03d48bd6324eb187ff9 100644 --- a/test/jdk/java/security/MessageDigest/ThreadSafetyTest.java +++ b/test/jdk/java/security/MessageDigest/ThreadSafetyTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Azul Systems, Inc. All rights reserved. + * Copyright (c) 2020, 2021, Azul Systems, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,9 +23,9 @@ /* * @test - * @bug 8241960 + * @bug 8241960 8277353 * @summary Confirm that java.security.MessageDigest is thread-safe after clone. - * @run main/othervm ThreadSafetyTest 5 4 + * @run main ThreadSafetyTest 4 2 */ import java.security.MessageDigest; @@ -56,7 +56,7 @@ public class ThreadSafetyTest { duration = Integer.parseInt(args[1]); } int nProcessors = Runtime.getRuntime().availableProcessors(); - int nTasks = nProcessors * threadsFactor; + int nTasks = Math.min(nProcessors, 4) * threadsFactor; System.out.println("Testing with " + nTasks + " threads on " + nProcessors + " processors for " + duration + diff --git a/test/jdk/java/text/Format/DateFormat/DateFormatTest.java b/test/jdk/java/text/Format/DateFormat/DateFormatTest.java index 43c73ac37786c9766ddfd661ef66e602ecfae1c2..5be792d1cd798a192d2dac6f87745ff0df6b9972 100644 --- a/test/jdk/java/text/Format/DateFormat/DateFormatTest.java +++ b/test/jdk/java/text/Format/DateFormat/DateFormatTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /** * @test * @bug 4052223 4089987 4469904 4326988 4486735 8008577 8045998 8140571 - * 8216969 + * 8190748 8216969 * @summary test DateFormat and SimpleDateFormat. * @library /java/text/testlib * @modules jdk.localedata @@ -342,7 +342,7 @@ public class DateFormatTest extends IntlTest // Test pattern with runs things together public void TestRunTogetherPattern985() { - String format = "yyyyMMddHHmmssSSS"; + String format = "yyyyMMddHHmmssSSSzzzz"; String now, then; SimpleDateFormat formatter = new SimpleDateFormat(format); diff --git a/test/jdk/java/text/Format/DateFormat/NonGregorianFormatTest.java b/test/jdk/java/text/Format/DateFormat/NonGregorianFormatTest.java index 93e2a9ffeee4ca3abc5ebf27b5db2b3a68111d9f..613687eb910f48b4f37be2f0b13dd7d89531c03a 100644 --- a/test/jdk/java/text/Format/DateFormat/NonGregorianFormatTest.java +++ b/test/jdk/java/text/Format/DateFormat/NonGregorianFormatTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,12 +23,13 @@ /* * @test - * @bug 4833268 6253991 8008577 + * @bug 4833268 6253991 8008577 8190748 * @summary Test formatting and parsing with non-Gregorian calendars * @modules jdk.localedata * @run main/othervm -Djava.locale.providers=COMPAT,SPI NonGregorianFormatTest */ +import java.time.ZoneId; import java.util.*; import java.text.*; import static java.util.Calendar.*; @@ -160,10 +161,15 @@ public class NonGregorianFormatTest { private static void testRoundTrip(DateFormat df, Date orig) { try { + var defZone = ZoneId.systemDefault(); + if (defZone.getRules().getTransition(orig.toInstant().atZone(defZone).toLocalDateTime()) != null) { + System.out.println("At the offset transition. Round trip test skipped."); + return; + } String s = df.format(orig); Date parsed = df.parse(s); if (!orig.equals(parsed)) { - error("testRoundTrip: bad date: origianl: '%s', parsed '%s'%n", orig, parsed); + error("testRoundTrip: bad date: original: '%s', parsed '%s'%n", orig, parsed); } } catch (Exception e) { error("Unexpected exception: %s%n", e); diff --git a/test/jdk/java/time/test/java/time/format/TestZoneTextPrinterParser.java b/test/jdk/java/time/test/java/time/format/TestZoneTextPrinterParser.java index 77ccf37ad5673fd02ee18ad509e1d1ee961d2595..7981d7699077b153f2306184694ec2181b929600 100644 --- a/test/jdk/java/time/test/java/time/format/TestZoneTextPrinterParser.java +++ b/test/jdk/java/time/test/java/time/format/TestZoneTextPrinterParser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,10 +24,12 @@ package test.java.time.format; import static org.testng.Assert.assertEquals; +import static org.testng.Assert.fail; import java.text.DateFormatSymbols; import java.time.ZoneId; import java.time.ZonedDateTime; +import java.time.format.DateTimeParseException; import java.time.format.DecimalStyle; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; @@ -49,7 +51,7 @@ import org.testng.annotations.Test; /* * @test - * @bug 8081022 8151876 8166875 8189784 8206980 + * @bug 8081022 8151876 8166875 8177819 8189784 8206980 8277049 * @key randomness */ @@ -236,4 +238,37 @@ public class TestZoneTextPrinterParser extends AbstractTestPrinterParser { .withDecimalStyle(DecimalStyle.of(locale)); } + @DataProvider(name="roundTripAtOverlap") + Object[][] data_roundTripAtOverlap() { + return new Object[][] { + {"yyyy-MM-dd HH:mm:ss.SSS z", "2021-10-31 02:30:00.000 CET"}, + {"yyyy-MM-dd HH:mm:ss.SSS z", "2021-10-31 02:30:00.000 CEST"}, + {"yyyy-MM-dd HH:mm:ss.SSS z", "2021-11-07 01:30:00.000 EST"}, + {"yyyy-MM-dd HH:mm:ss.SSS z", "2021-11-07 01:30:00.000 EDT"}, + {"yyyy-MM-dd HH:mm:ss.SSS zzzz", "2021-10-31 02:30:00.000 Central European Standard Time"}, + {"yyyy-MM-dd HH:mm:ss.SSS zzzz", "2021-10-31 02:30:00.000 Central European Summer Time"}, + {"yyyy-MM-dd HH:mm:ss.SSS zzzz", "2021-11-07 01:30:00.000 Eastern Standard Time"}, + {"yyyy-MM-dd HH:mm:ss.SSS zzzz", "2021-11-07 01:30:00.000 Eastern Daylight Time"}, + + {"yyyy-MM-dd HH:mm:ss.SSS v", "2021-10-31 02:30:00.000 CET"}, + {"yyyy-MM-dd HH:mm:ss.SSS v", "2021-11-07 01:30:00.000 ET"}, + {"yyyy-MM-dd HH:mm:ss.SSS vvvv", "2021-10-31 02:30:00.000 Central European Time"}, + {"yyyy-MM-dd HH:mm:ss.SSS vvvv", "2021-11-07 01:30:00.000 Eastern Time"}, + }; + } + + @Test(dataProvider="roundTripAtOverlap") + public void test_roundTripAtOverlap(String pattern, String input) { + var dtf = DateTimeFormatter.ofPattern(pattern); + assertEquals(dtf.format(ZonedDateTime.parse(input, dtf)), input); + var lc = input.toLowerCase(Locale.ROOT); + try { + ZonedDateTime.parse(lc, dtf); + fail("Should throw DateTimeParseException"); + } catch (DateTimeParseException ignore) {} + + dtf = new DateTimeFormatterBuilder().parseCaseInsensitive().appendPattern(pattern).toFormatter(); + assertEquals(dtf.format(ZonedDateTime.parse(input, dtf)), input); + assertEquals(dtf.format(ZonedDateTime.parse(lc, dtf)), input); + } } diff --git a/test/jdk/java/util/concurrent/ConcurrentHashMap/MapLoops.java b/test/jdk/java/util/concurrent/ConcurrentHashMap/MapLoops.java index 0f52bc67f085a115d4c4d3ffdddab360fc4e9816..922b18836dd877a36090f4cc0a601c2bec6b4a1b 100644 --- a/test/jdk/java/util/concurrent/ConcurrentHashMap/MapLoops.java +++ b/test/jdk/java/util/concurrent/ConcurrentHashMap/MapLoops.java @@ -45,6 +45,14 @@ * @run main/timeout=1600 MapLoops */ +/* + * @test + * @summary Exercise multithreaded maps, using only heavy monitors. + * @requires os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64" | os.arch=="aarch64" | os.arch == "ppc64" | os.arch == "ppc64le" + * @library /test/lib + * @run main/othervm/timeout=1600 -XX:+IgnoreUnrecognizedVMOptions -XX:+UseHeavyMonitors -XX:+VerifyHeavyMonitors MapLoops + */ + import static java.util.concurrent.TimeUnit.MILLISECONDS; import java.util.List; diff --git a/test/jdk/java/util/stream/test/org/openjdk/tests/java/util/stream/SegmentTestDataProvider.java b/test/jdk/java/util/stream/test/org/openjdk/tests/java/util/stream/SegmentTestDataProvider.java index 772e112b23d87f04488e3801b06637452c5a0ec5..7a4d16dff13efef836e441a141e75190dda5312c 100644 --- a/test/jdk/java/util/stream/test/org/openjdk/tests/java/util/stream/SegmentTestDataProvider.java +++ b/test/jdk/java/util/stream/test/org/openjdk/tests/java/util/stream/SegmentTestDataProvider.java @@ -23,9 +23,7 @@ package org.openjdk.tests.java.util.stream; -import jdk.incubator.foreign.MemoryAccess; import jdk.incubator.foreign.MemoryLayout; -import jdk.incubator.foreign.MemoryLayouts; import jdk.incubator.foreign.MemorySegment; import java.lang.invoke.VarHandle; @@ -36,12 +34,13 @@ import java.util.function.Consumer; import java.util.function.Function; import java.util.stream.Collectors; +import jdk.incubator.foreign.ValueLayout; import org.testng.annotations.DataProvider; public class SegmentTestDataProvider { static boolean compareSegmentsByte(Collection<MemorySegment> segments1, Collection<MemorySegment> segments2, boolean isOrdered) { - Function<MemorySegment, Byte> mapper = MemoryAccess::getByte; + Function<MemorySegment, Byte> mapper = s -> s.get(ValueLayout.JAVA_BYTE, 0); List<Byte> list1 = segments1.stream() .map(mapper) .collect(Collectors.toList()); @@ -52,7 +51,7 @@ public class SegmentTestDataProvider { } static boolean compareSegmentsChar(Collection<MemorySegment> segments1, Collection<MemorySegment> segments2, boolean isOrdered) { - Function<MemorySegment, Character> mapper = MemoryAccess::getChar; + Function<MemorySegment, Character> mapper = s -> s.get(ValueLayout.JAVA_CHAR, 0); List<Character> list1 = segments1.stream() .map(mapper) .collect(Collectors.toList()); @@ -63,7 +62,7 @@ public class SegmentTestDataProvider { } static boolean compareSegmentsShort(Collection<MemorySegment> segments1, Collection<MemorySegment> segments2, boolean isOrdered) { - Function<MemorySegment, Short> mapper = MemoryAccess::getShort; + Function<MemorySegment, Short> mapper = s -> s.get(ValueLayout.JAVA_SHORT, 0); List<Short> list1 = segments1.stream() .map(mapper) .collect(Collectors.toList()); @@ -74,7 +73,7 @@ public class SegmentTestDataProvider { } static boolean compareSegmentsInt(Collection<MemorySegment> segments1, Collection<MemorySegment> segments2, boolean isOrdered) { - Function<MemorySegment, Integer> mapper = MemoryAccess::getInt; + Function<MemorySegment, Integer> mapper = s -> s.get(ValueLayout.JAVA_INT, 0); List<Integer> list1 = segments1.stream() .map(mapper) .collect(Collectors.toList()); @@ -85,7 +84,7 @@ public class SegmentTestDataProvider { } static boolean compareSegmentsLong(Collection<MemorySegment> segments1, Collection<MemorySegment> segments2, boolean isOrdered) { - Function<MemorySegment, Long> mapper = MemoryAccess::getLong; + Function<MemorySegment, Long> mapper = s-> s.get(ValueLayout.JAVA_LONG, 0); List<Long> list1 = segments1.stream() .map(mapper) .collect(Collectors.toList()); @@ -96,7 +95,7 @@ public class SegmentTestDataProvider { } static boolean compareSegmentsFloat(Collection<MemorySegment> segments1, Collection<MemorySegment> segments2, boolean isOrdered) { - Function<MemorySegment, Float> mapper = MemoryAccess::getFloat; + Function<MemorySegment, Float> mapper = s -> s.get(ValueLayout.JAVA_FLOAT, 0); List<Float> list1 = segments1.stream() .map(mapper) .collect(Collectors.toList()); @@ -115,7 +114,7 @@ public class SegmentTestDataProvider { } static boolean compareSegmentsDouble(Collection<MemorySegment> segments1, Collection<MemorySegment> segments2, boolean isOrdered) { - Function<MemorySegment, Double> mapper = MemoryAccess::getDouble; + Function<MemorySegment, Double> mapper = s -> s.get(ValueLayout.JAVA_DOUBLE, 0); List<Double> list1 = segments1.stream() .map(mapper) .collect(Collectors.toList()); @@ -127,18 +126,18 @@ public class SegmentTestDataProvider { static void initSegment(MemorySegment segment) { for (int i = 0 ; i < segment.byteSize() ; i++) { - MemoryAccess.setByte(segment, (byte)i); + segment.set(ValueLayout.JAVA_BYTE, 0, (byte)i); } } static Object[][] spliteratorTestData = { - { "bytes", MemoryLayout.sequenceLayout(1024, MemoryLayouts.JAVA_BYTE), (SpliteratorTestHelper.ContentAsserter<MemorySegment>)SegmentTestDataProvider::compareSegmentsByte }, - { "chars", MemoryLayout.sequenceLayout(1024, MemoryLayouts.JAVA_CHAR), (SpliteratorTestHelper.ContentAsserter<MemorySegment>)SegmentTestDataProvider::compareSegmentsChar }, - { "shorts", MemoryLayout.sequenceLayout(1024, MemoryLayouts.JAVA_SHORT), (SpliteratorTestHelper.ContentAsserter<MemorySegment>)SegmentTestDataProvider::compareSegmentsShort }, - { "ints", MemoryLayout.sequenceLayout(1024, MemoryLayouts.JAVA_INT), (SpliteratorTestHelper.ContentAsserter<MemorySegment>)SegmentTestDataProvider::compareSegmentsInt }, - { "longs", MemoryLayout.sequenceLayout(1024, MemoryLayouts.JAVA_LONG), (SpliteratorTestHelper.ContentAsserter<MemorySegment>)SegmentTestDataProvider::compareSegmentsLong }, - { "floats", MemoryLayout.sequenceLayout(1024, MemoryLayouts.JAVA_FLOAT), (SpliteratorTestHelper.ContentAsserter<MemorySegment>)SegmentTestDataProvider::compareSegmentsFloat }, - { "doubles", MemoryLayout.sequenceLayout(1024, MemoryLayouts.JAVA_DOUBLE), (SpliteratorTestHelper.ContentAsserter<MemorySegment>)SegmentTestDataProvider::compareSegmentsDouble }, + { "bytes", MemoryLayout.sequenceLayout(1024, ValueLayout.JAVA_BYTE), (SpliteratorTestHelper.ContentAsserter<MemorySegment>)SegmentTestDataProvider::compareSegmentsByte }, + { "chars", MemoryLayout.sequenceLayout(1024, ValueLayout.JAVA_CHAR), (SpliteratorTestHelper.ContentAsserter<MemorySegment>)SegmentTestDataProvider::compareSegmentsChar }, + { "shorts", MemoryLayout.sequenceLayout(1024, ValueLayout.JAVA_SHORT), (SpliteratorTestHelper.ContentAsserter<MemorySegment>)SegmentTestDataProvider::compareSegmentsShort }, + { "ints", MemoryLayout.sequenceLayout(1024, ValueLayout.JAVA_INT), (SpliteratorTestHelper.ContentAsserter<MemorySegment>)SegmentTestDataProvider::compareSegmentsInt }, + { "longs", MemoryLayout.sequenceLayout(1024, ValueLayout.JAVA_LONG), (SpliteratorTestHelper.ContentAsserter<MemorySegment>)SegmentTestDataProvider::compareSegmentsLong }, + { "floats", MemoryLayout.sequenceLayout(1024, ValueLayout.JAVA_FLOAT), (SpliteratorTestHelper.ContentAsserter<MemorySegment>)SegmentTestDataProvider::compareSegmentsFloat }, + { "doubles", MemoryLayout.sequenceLayout(1024, ValueLayout.JAVA_DOUBLE), (SpliteratorTestHelper.ContentAsserter<MemorySegment>)SegmentTestDataProvider::compareSegmentsDouble }, }; // returns an array of (String name, Supplier<Spliterator<MemorySegment>>, ContentAsserter<MemorySegment>) diff --git a/test/jdk/java/util/zip/CloseDeflaterTest.java b/test/jdk/java/util/zip/CloseDeflaterTest.java new file mode 100644 index 0000000000000000000000000000000000000000..8aa4960f543628edc887c61a10a897373f38657f --- /dev/null +++ b/test/jdk/java/util/zip/CloseDeflaterTest.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8193682 + * @summary Test Infinite loop while writing on closed GZipOutputStream , ZipOutputStream and JarOutputStream. + * @run testng CloseDeflaterTest + */ +import java.io.*; +import java.util.Random; +import java.util.jar.JarOutputStream; +import java.util.zip.GZIPOutputStream; +import java.util.zip.ZipOutputStream; +import java.util.zip.ZipEntry; + +import org.testng.annotations.BeforeTest; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import static org.testng.Assert.fail; + + +public class CloseDeflaterTest { + + //number of bytes to write + private static final int INPUT_LENGTH= 512; + //OutputStream that will throw an exception during a write operation + private static OutputStream outStream = new OutputStream() { + @Override + public void write(byte[] b, int off, int len) throws IOException { + //throw exception during write + throw new IOException(); + } + @Override + public void write(byte b[]) throws IOException {} + @Override + public void write(int b) throws IOException {} + }; + private static byte[] inputBytes = new byte[INPUT_LENGTH]; + private static Random rand = new Random(); + + @DataProvider(name = "testgzipinput") + public Object[][] testGZipInput() { + //testGZip will close the GZipOutputStream using close() method when the boolean + //useCloseMethod is set to true and finish() method if the value is set to false + return new Object[][] { + { GZIPOutputStream.class, true }, + { GZIPOutputStream.class, false }, + }; + } + + @DataProvider(name = "testzipjarinput") + public Object[][] testZipAndJarInput() { + //testZipAndJarInput will perfrom write/closeEntry operations on JarOutputStream when the boolean + //useJar is set to true and on ZipOutputStream if the value is set to false + return new Object[][] { + { JarOutputStream.class, true }, + { ZipOutputStream.class, false }, + }; + } + + @BeforeTest + public void before_test() + { + //add inputBytes array with random bytes to write into Zip + rand.nextBytes(inputBytes); + } + + //Test for infinite loop by writing bytes to closed GZIPOutputStream + @Test(dataProvider = "testgzipinput") + public void testGZip(Class<?> type, boolean useCloseMethod) throws IOException { + GZIPOutputStream zip = new GZIPOutputStream(outStream); + try { + zip.write(inputBytes, 0, INPUT_LENGTH); + //close zip + if(useCloseMethod) { + zip.close(); + } else { + zip.finish(); + } + } catch (IOException e) { + //expected + } + for (int i = 0; i < 3; i++) { + try { + //write on a closed GZIPOutputStream + zip.write(inputBytes, 0, INPUT_LENGTH); + fail("Deflater closed exception not thrown"); + } catch (NullPointerException e) { + //expected , Deflater has been closed exception + } + } + } + + //Test for infinite loop by writing bytes to closed ZipOutputStream/JarOutputStream + @Test(dataProvider = "testzipjarinput") + public void testZipCloseEntry(Class<?> type,boolean useJar) throws IOException { + ZipOutputStream zip = null; + if(useJar) { + zip = new JarOutputStream(outStream); + } else { + zip = new ZipOutputStream(outStream); + } + try { + zip.putNextEntry(new ZipEntry("")); + } catch (IOException e) { + //expected to throw IOException since putNextEntry calls write method + } + try { + zip.write(inputBytes, 0, INPUT_LENGTH); + //close zip entry + zip.closeEntry(); + } catch (IOException e) { + //expected + } + for (int i = 0; i < 3; i++) { + try { + //write on a closed ZipOutputStream + zip.write(inputBytes, 0, INPUT_LENGTH); + fail("Deflater closed exception not thrown"); + } catch (NullPointerException e) { + //expected , Deflater has been closed exception + } + } + } + +} diff --git a/test/jdk/javax/imageio/plugins/wbmp/WBMPStreamTruncateTest.java b/test/jdk/javax/imageio/plugins/wbmp/WBMPStreamTruncateTest.java new file mode 100644 index 0000000000000000000000000000000000000000..36b8d4a72e0fd992d08fad2d0008109e7f8494a8 --- /dev/null +++ b/test/jdk/javax/imageio/plugins/wbmp/WBMPStreamTruncateTest.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8266435 + * @summary Test verifies that WBMPImageReader doesnt truncate + * the stream and reads it fully + * @run main WBMPStreamTruncateTest + */ + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.RandomAccessFile; +import javax.imageio.ImageIO; +import javax.imageio.stream.ImageInputStreamImpl; + +public class WBMPStreamTruncateTest +{ + static final int LIMIT = 100; + static final int width = 100; + static final int height = 100; + public static void main(String[] args) throws IOException + { + String sep = System.getProperty("file.separator"); + String dir = System.getProperty("test.src", "."); + String filePath = dir+sep; + BufferedImage srcImage = new + BufferedImage(width, height, BufferedImage.TYPE_BYTE_BINARY); + Graphics2D g = (Graphics2D) srcImage.getGraphics(); + g.setBackground(Color.WHITE); + g.fillRect(0, 0, srcImage.getWidth(), srcImage.getHeight()); + g.dispose(); + // create WBMP image + File imageFile = File. + createTempFile("test", ".wbmp", new File(filePath)); + imageFile.deleteOnExit(); + ImageIO.write(srcImage, "wbmp", imageFile); + BufferedImage testImg = + ImageIO.read(new LimitedImageInputStream(imageFile, LIMIT)); + for (int x = 0; x < testImg.getWidth(); ++x) + { + for (int y = 0; y < testImg.getHeight(); ++y) + { + int i1 = testImg.getRGB(x, y); + int i2 = srcImage.getRGB(x, y); + if (i1 != i2) + { + throw new RuntimeException("Stream is decoded only until " + + "the limit specified"); + } + } + } + } + + static class LimitedImageInputStream extends ImageInputStreamImpl + { + private final RandomAccessFile raf; + private final int limit; + + public LimitedImageInputStream(File file, int limit) + throws FileNotFoundException + { + raf = new RandomAccessFile(file, "r"); + this.limit = limit; + } + + @Override + public int read() throws IOException + { + return raf.read(); + } + + @Override + public int read(byte[] b, int off, int len) throws IOException + { + return raf.read(b, off, Math.min(limit, len)); + } + + @Override + public void close() throws IOException + { + super.close(); + raf.close(); + } + + @Override + public void seek(long pos) throws IOException + { + super.seek(pos); + raf.seek(pos); + } + } +} diff --git a/test/jdk/javax/print/PrintServiceLookup/FlushCustomClassLoader.java b/test/jdk/javax/print/PrintServiceLookup/FlushCustomClassLoader.java index 6e0a25a69d0a56beb09b5edb5186f50475b1e29f..4ec95fb75354e0e83651a5ec089e90d67e0be58b 100644 --- a/test/jdk/javax/print/PrintServiceLookup/FlushCustomClassLoader.java +++ b/test/jdk/javax/print/PrintServiceLookup/FlushCustomClassLoader.java @@ -34,6 +34,9 @@ import javax.print.PrintServiceLookup; * @test * @bug 8273831 * @summary Tests custom class loader cleanup + * @library /javax/swing/regtesthelpers + * @build Util + * @run main/timeout=60/othervm -mx32m FlushCustomClassLoader */ public final class FlushCustomClassLoader { @@ -42,12 +45,8 @@ public final class FlushCustomClassLoader { int attempt = 0; while (loader.get() != null) { - if (++attempt > 10) { - throw new RuntimeException("Too many attempts: " + attempt); - } - System.gc(); - Thread.sleep(1000); - System.out.println("Not freed, attempt: " + attempt); + Util.generateOOME(); + System.out.println("Not freed, attempt: " + attempt++); } } diff --git a/test/jdk/javax/swing/DefaultButtonModel/DefaultButtonModelCrashTest.java b/test/jdk/javax/swing/DefaultButtonModel/DefaultButtonModelCrashTest.java index efcf335a54d0cdbdbf8e85f79b4952f00ecd4d40..14190ce65d304f65da3bb0582f4dfe7b8853a700 100644 --- a/test/jdk/javax/swing/DefaultButtonModel/DefaultButtonModelCrashTest.java +++ b/test/jdk/javax/swing/DefaultButtonModel/DefaultButtonModelCrashTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,23 +21,21 @@ * questions. */ -/** +/* * @test * @bug 8182577 - * @summary Verifies if moving focus via custom ButtonModel causes crash + * @summary Verifies if moving focus to JToggleButton with DefaultButtonModel + * that is added to a ButtonGroup doesn't throw ClassCastException * @key headful * @run main DefaultButtonModelCrashTest */ import java.awt.BorderLayout; -import java.awt.Container; -import java.awt.Point; import java.awt.Robot; import java.awt.event.KeyEvent; import javax.swing.ButtonModel; import javax.swing.DefaultButtonModel; import javax.swing.JCheckBox; -import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JTextField; @@ -45,8 +43,6 @@ import javax.swing.SwingUtilities; public class DefaultButtonModelCrashTest { private JFrame frame = null; - private JPanel panel; - private volatile Point p = null; public static void main(String[] args) throws Exception { new DefaultButtonModelCrashTest(); @@ -58,29 +54,34 @@ public class DefaultButtonModelCrashTest { robot.setAutoDelay(200); SwingUtilities.invokeAndWait(() -> go()); robot.waitForIdle(); + robot.delay(1000); robot.keyPress(KeyEvent.VK_TAB); robot.keyRelease(KeyEvent.VK_TAB); robot.delay(100); robot.keyPress(KeyEvent.VK_TAB); robot.keyRelease(KeyEvent.VK_TAB); } finally { - if (frame != null) { SwingUtilities.invokeAndWait(()->frame.dispose()); } + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); } } private void go() { - frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - Container contentPane = frame.getContentPane(); - ButtonModel model = new DefaultButtonModel(); + ButtonModel model = new DefaultButtonModel(); JCheckBox check = new JCheckBox("a bit broken"); check.setModel(model); - panel = new JPanel(new BorderLayout()); + + JPanel panel = new JPanel(new BorderLayout()); panel.add(new JTextField("Press Tab (twice?)"), BorderLayout.NORTH); panel.add(check); - contentPane.add(panel); + + frame.getContentPane().add(panel); frame.setLocationRelativeTo(null); frame.pack(); frame.setVisible(true); diff --git a/test/jdk/javax/swing/JFileChooser/FileSystemView/ShellFolderStackOverflow.java b/test/jdk/javax/swing/JFileChooser/FileSystemView/ShellFolderStackOverflow.java new file mode 100644 index 0000000000000000000000000000000000000000..52bc51bd3f6d1242005ca456d64d76dcd6a39da3 --- /dev/null +++ b/test/jdk/javax/swing/JFileChooser/FileSystemView/ShellFolderStackOverflow.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8277299 + * @requires (os.family == "windows") + * @summary STACK_OVERFLOW in Java_sun_awt_shell_Win32ShellFolder2_getIconBits + * @run main/othervm -Xss320k ShellFolderStackOverflow + */ +import javax.swing.UIManager; + +public class ShellFolderStackOverflow { + public static void main(final String... args) throws Exception { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); + // With default stack size for 32-bit VM next call will cause VM crash + UIManager.getIcon("Tree.openIcon"); + } +} diff --git a/test/jdk/javax/swing/JTree/4908142/bug4908142.java b/test/jdk/javax/swing/JTree/4908142/bug4908142.java index 671af8abd2db5f4af0522edbc1068c03876aef77..784feda153d676a6083193ee5529bb90638ebb3f 100644 --- a/test/jdk/javax/swing/JTree/4908142/bug4908142.java +++ b/test/jdk/javax/swing/JTree/4908142/bug4908142.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,6 +60,7 @@ public class bug4908142 { }); robot.waitForIdle(); + robot.delay(1000); SwingUtilities.invokeAndWait(new Runnable() { @@ -70,12 +71,14 @@ public class bug4908142 { }); robot.waitForIdle(); - + robot.delay(500); robot.keyPress(KeyEvent.VK_A); robot.keyRelease(KeyEvent.VK_A); + robot.waitForIdle(); robot.keyPress(KeyEvent.VK_A); robot.keyRelease(KeyEvent.VK_A); + robot.waitForIdle(); robot.keyPress(KeyEvent.VK_D); robot.keyRelease(KeyEvent.VK_D); robot.waitForIdle(); @@ -114,6 +117,7 @@ public class bug4908142 { JScrollPane sp = new JScrollPane(tree); fr.getContentPane().add(sp); + fr.setLocationRelativeTo(null); fr.setSize(200, 200); fr.setVisible(true); } diff --git a/test/jdk/javax/xml/crypto/dsig/BadXPointer.java b/test/jdk/javax/xml/crypto/dsig/BadXPointer.java new file mode 100644 index 0000000000000000000000000000000000000000..ba985b6c568893e9bcdfc5728751efa535c6dc21 --- /dev/null +++ b/test/jdk/javax/xml/crypto/dsig/BadXPointer.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import jdk.test.lib.Asserts; +import jdk.test.lib.Utils; +import jdk.test.lib.security.XMLUtils; + +import javax.xml.crypto.URIReferenceException; +import javax.xml.crypto.dsig.XMLSignatureException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.spec.ECGenParameterSpec; + +/** + * @test + * @bug 8278186 + * @summary reject malformed xpointer(id('a')) gracefully + * @library /test/lib + * @modules java.xml.crypto + */ +public class BadXPointer { + + public static void main(String[] args) throws Exception { + + KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC"); + kpg.initialize(new ECGenParameterSpec("secp256r1")); + KeyPair kp = kpg.generateKeyPair(); + + var signer = XMLUtils.signer(kp.getPrivate(), kp.getPublic()); + var doc = XMLUtils.string2doc("<root/>"); + + // No enclosing ' for id + Utils.runAndCheckException( + () -> signer.signEnveloping(doc, "a", "#xpointer(id('a))"), + ex -> Asserts.assertTrue(ex instanceof XMLSignatureException + && ex.getCause() instanceof URIReferenceException + && ex.getMessage().contains("Could not find a resolver"), + ex.toString())); + } +} diff --git a/test/jdk/jdk/incubator/vector/Byte128VectorTests.java b/test/jdk/jdk/incubator/vector/Byte128VectorTests.java index db2140d223ef0bffc29d821fa1db26eb04a26cdb..8dae27c6179e62e49ab803f1818bae9402d748e1 100644 --- a/test/jdk/jdk/incubator/vector/Byte128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Byte128VectorTests.java @@ -5512,7 +5512,7 @@ public class Byte128VectorTests extends AbstractVectorTest { static void maskFromToLongByte128VectorTestsSmokeTest(long inputLong) { var vmask = VectorMask.fromLong(SPECIES, inputLong); long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, inputLong & (((1L << (SPECIES.length() - 1)) << 1) - 1)); + Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); } @DataProvider diff --git a/test/jdk/jdk/incubator/vector/Byte256VectorTests.java b/test/jdk/jdk/incubator/vector/Byte256VectorTests.java index b980f61df8c4e77218188b19b048b8881f834c36..554ca26fab09580ea369365d83295f38abc2f654 100644 --- a/test/jdk/jdk/incubator/vector/Byte256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Byte256VectorTests.java @@ -5512,7 +5512,7 @@ public class Byte256VectorTests extends AbstractVectorTest { static void maskFromToLongByte256VectorTestsSmokeTest(long inputLong) { var vmask = VectorMask.fromLong(SPECIES, inputLong); long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, inputLong & (((1L << (SPECIES.length() - 1)) << 1) - 1)); + Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); } @DataProvider diff --git a/test/jdk/jdk/incubator/vector/Byte512VectorTests.java b/test/jdk/jdk/incubator/vector/Byte512VectorTests.java index 2ec4e8b2c539ec20c13edef959c1164406756337..8eacafc20f7e46ff8e9adb2c1b94c60b6ecca8d9 100644 --- a/test/jdk/jdk/incubator/vector/Byte512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Byte512VectorTests.java @@ -5512,7 +5512,7 @@ public class Byte512VectorTests extends AbstractVectorTest { static void maskFromToLongByte512VectorTestsSmokeTest(long inputLong) { var vmask = VectorMask.fromLong(SPECIES, inputLong); long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, inputLong & (((1L << (SPECIES.length() - 1)) << 1) - 1)); + Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); } @DataProvider diff --git a/test/jdk/jdk/incubator/vector/Byte64VectorTests.java b/test/jdk/jdk/incubator/vector/Byte64VectorTests.java index 7ca7543a992a4701f8986694cfc712cc09006ee5..5fb5abe9c8cf1a8a7a8d363031750ae3ceaacaa9 100644 --- a/test/jdk/jdk/incubator/vector/Byte64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Byte64VectorTests.java @@ -5512,7 +5512,7 @@ public class Byte64VectorTests extends AbstractVectorTest { static void maskFromToLongByte64VectorTestsSmokeTest(long inputLong) { var vmask = VectorMask.fromLong(SPECIES, inputLong); long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, inputLong & (((1L << (SPECIES.length() - 1)) << 1) - 1)); + Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); } @DataProvider diff --git a/test/jdk/jdk/incubator/vector/Double128VectorTests.java b/test/jdk/jdk/incubator/vector/Double128VectorTests.java index a2dd0d44720a91bd5f24a1fe3748af3030df1a6b..4f5b7977ab71aca15eba81e81ad0e8acca140e15 100644 --- a/test/jdk/jdk/incubator/vector/Double128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Double128VectorTests.java @@ -4891,7 +4891,7 @@ public class Double128VectorTests extends AbstractVectorTest { static void maskFromToLongDouble128VectorTestsSmokeTest(long inputLong) { var vmask = VectorMask.fromLong(SPECIES, inputLong); long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, inputLong & (((1L << (SPECIES.length() - 1)) << 1) - 1)); + Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); } @DataProvider diff --git a/test/jdk/jdk/incubator/vector/Double256VectorTests.java b/test/jdk/jdk/incubator/vector/Double256VectorTests.java index c7be717ef5f72851f3055b43038904b53deb1fbc..67722eaac1d24ede802770736aa6b6ebe7dae613 100644 --- a/test/jdk/jdk/incubator/vector/Double256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Double256VectorTests.java @@ -4891,7 +4891,7 @@ public class Double256VectorTests extends AbstractVectorTest { static void maskFromToLongDouble256VectorTestsSmokeTest(long inputLong) { var vmask = VectorMask.fromLong(SPECIES, inputLong); long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, inputLong & (((1L << (SPECIES.length() - 1)) << 1) - 1)); + Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); } @DataProvider diff --git a/test/jdk/jdk/incubator/vector/Double512VectorTests.java b/test/jdk/jdk/incubator/vector/Double512VectorTests.java index ed7a2e470cb5660fbbafdfa4d9700bb7a32a69a1..445766aa3111fc51e7e24fa8c89d63d8f0ad2997 100644 --- a/test/jdk/jdk/incubator/vector/Double512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Double512VectorTests.java @@ -4891,7 +4891,7 @@ public class Double512VectorTests extends AbstractVectorTest { static void maskFromToLongDouble512VectorTestsSmokeTest(long inputLong) { var vmask = VectorMask.fromLong(SPECIES, inputLong); long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, inputLong & (((1L << (SPECIES.length() - 1)) << 1) - 1)); + Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); } @DataProvider diff --git a/test/jdk/jdk/incubator/vector/Double64VectorTests.java b/test/jdk/jdk/incubator/vector/Double64VectorTests.java index 20e70d70cc0ed35495cd85a7189c98623a596aaf..4d214ba1e6cb1a7642e06645b95b62520fdb46c5 100644 --- a/test/jdk/jdk/incubator/vector/Double64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Double64VectorTests.java @@ -4891,7 +4891,7 @@ public class Double64VectorTests extends AbstractVectorTest { static void maskFromToLongDouble64VectorTestsSmokeTest(long inputLong) { var vmask = VectorMask.fromLong(SPECIES, inputLong); long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, inputLong & (((1L << (SPECIES.length() - 1)) << 1) - 1)); + Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); } @DataProvider diff --git a/test/jdk/jdk/incubator/vector/Float128VectorTests.java b/test/jdk/jdk/incubator/vector/Float128VectorTests.java index 7e01f848864c754af9e486744ba0b87d64066dde..f8c23bd387d65da088d887e717959f38612ac9ff 100644 --- a/test/jdk/jdk/incubator/vector/Float128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Float128VectorTests.java @@ -4869,7 +4869,7 @@ public class Float128VectorTests extends AbstractVectorTest { static void maskFromToLongFloat128VectorTestsSmokeTest(long inputLong) { var vmask = VectorMask.fromLong(SPECIES, inputLong); long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, inputLong & (((1L << (SPECIES.length() - 1)) << 1) - 1)); + Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); } @DataProvider diff --git a/test/jdk/jdk/incubator/vector/Float256VectorTests.java b/test/jdk/jdk/incubator/vector/Float256VectorTests.java index 3ff38daa0a8c671f4ff4ea6ec00c0178aa607b1f..11d2e9cf5ca593333b6b3fdff2818ddc6b08bf6b 100644 --- a/test/jdk/jdk/incubator/vector/Float256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Float256VectorTests.java @@ -4869,7 +4869,7 @@ public class Float256VectorTests extends AbstractVectorTest { static void maskFromToLongFloat256VectorTestsSmokeTest(long inputLong) { var vmask = VectorMask.fromLong(SPECIES, inputLong); long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, inputLong & (((1L << (SPECIES.length() - 1)) << 1) - 1)); + Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); } @DataProvider diff --git a/test/jdk/jdk/incubator/vector/Float512VectorTests.java b/test/jdk/jdk/incubator/vector/Float512VectorTests.java index e7d9e3fa53212c58083c63e686d188a6f66dbd4c..5b88d81bab77e914ab35a9f64cb2b1aa1125231b 100644 --- a/test/jdk/jdk/incubator/vector/Float512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Float512VectorTests.java @@ -4869,7 +4869,7 @@ public class Float512VectorTests extends AbstractVectorTest { static void maskFromToLongFloat512VectorTestsSmokeTest(long inputLong) { var vmask = VectorMask.fromLong(SPECIES, inputLong); long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, inputLong & (((1L << (SPECIES.length() - 1)) << 1) - 1)); + Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); } @DataProvider diff --git a/test/jdk/jdk/incubator/vector/Float64VectorTests.java b/test/jdk/jdk/incubator/vector/Float64VectorTests.java index e4c646623bb93b219abde2ece7c25f7da218acb1..4eadb366b57dddf3a77a85f8c1ab3cbfbceb7a86 100644 --- a/test/jdk/jdk/incubator/vector/Float64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Float64VectorTests.java @@ -4869,7 +4869,7 @@ public class Float64VectorTests extends AbstractVectorTest { static void maskFromToLongFloat64VectorTestsSmokeTest(long inputLong) { var vmask = VectorMask.fromLong(SPECIES, inputLong); long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, inputLong & (((1L << (SPECIES.length() - 1)) << 1) - 1)); + Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); } @DataProvider diff --git a/test/jdk/jdk/incubator/vector/Int128VectorTests.java b/test/jdk/jdk/incubator/vector/Int128VectorTests.java index 0493494d1c02f2b25fce70cdd62fae6b297a87d8..c89854ac074e53a43b9202485247b2d3ee56027e 100644 --- a/test/jdk/jdk/incubator/vector/Int128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Int128VectorTests.java @@ -5466,7 +5466,7 @@ public class Int128VectorTests extends AbstractVectorTest { static void maskFromToLongInt128VectorTestsSmokeTest(long inputLong) { var vmask = VectorMask.fromLong(SPECIES, inputLong); long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, inputLong & (((1L << (SPECIES.length() - 1)) << 1) - 1)); + Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); } @DataProvider diff --git a/test/jdk/jdk/incubator/vector/Int256VectorTests.java b/test/jdk/jdk/incubator/vector/Int256VectorTests.java index 9b1872f33d1e09a731afd5ce033e5095016147a4..e6e969daefbbd8e41c397e1d2b83d26249c2e43c 100644 --- a/test/jdk/jdk/incubator/vector/Int256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Int256VectorTests.java @@ -5466,7 +5466,7 @@ public class Int256VectorTests extends AbstractVectorTest { static void maskFromToLongInt256VectorTestsSmokeTest(long inputLong) { var vmask = VectorMask.fromLong(SPECIES, inputLong); long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, inputLong & (((1L << (SPECIES.length() - 1)) << 1) - 1)); + Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); } @DataProvider diff --git a/test/jdk/jdk/incubator/vector/Int512VectorTests.java b/test/jdk/jdk/incubator/vector/Int512VectorTests.java index 52dcf43e31b5411a967be4c7d89c30fe6eb6e9e7..68be363a4677e882399ce935eac0d745d4f2150a 100644 --- a/test/jdk/jdk/incubator/vector/Int512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Int512VectorTests.java @@ -5466,7 +5466,7 @@ public class Int512VectorTests extends AbstractVectorTest { static void maskFromToLongInt512VectorTestsSmokeTest(long inputLong) { var vmask = VectorMask.fromLong(SPECIES, inputLong); long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, inputLong & (((1L << (SPECIES.length() - 1)) << 1) - 1)); + Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); } @DataProvider diff --git a/test/jdk/jdk/incubator/vector/Int64VectorTests.java b/test/jdk/jdk/incubator/vector/Int64VectorTests.java index 9d9fffcf246e8d29eaae382ce379c5ad3a10c86c..c284fd16816b7e2800754f422610e84366de295b 100644 --- a/test/jdk/jdk/incubator/vector/Int64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Int64VectorTests.java @@ -5466,7 +5466,7 @@ public class Int64VectorTests extends AbstractVectorTest { static void maskFromToLongInt64VectorTestsSmokeTest(long inputLong) { var vmask = VectorMask.fromLong(SPECIES, inputLong); long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, inputLong & (((1L << (SPECIES.length() - 1)) << 1) - 1)); + Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); } @DataProvider diff --git a/test/jdk/jdk/incubator/vector/Long128VectorTests.java b/test/jdk/jdk/incubator/vector/Long128VectorTests.java index 03d163a8a4c607fc752e0d51cb23c774c9d84b9e..0163736063bf2b648af5ab48b4d478b59c8eb182 100644 --- a/test/jdk/jdk/incubator/vector/Long128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Long128VectorTests.java @@ -5350,7 +5350,7 @@ public class Long128VectorTests extends AbstractVectorTest { static void maskFromToLongLong128VectorTestsSmokeTest(long inputLong) { var vmask = VectorMask.fromLong(SPECIES, inputLong); long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, inputLong & (((1L << (SPECIES.length() - 1)) << 1) - 1)); + Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); } @DataProvider diff --git a/test/jdk/jdk/incubator/vector/Long256VectorTests.java b/test/jdk/jdk/incubator/vector/Long256VectorTests.java index 91a41519bb43610d527da5b8b6bdf802be6e16d6..c443f757772ad754c15924df60be9dd316eb3ec6 100644 --- a/test/jdk/jdk/incubator/vector/Long256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Long256VectorTests.java @@ -5350,7 +5350,7 @@ public class Long256VectorTests extends AbstractVectorTest { static void maskFromToLongLong256VectorTestsSmokeTest(long inputLong) { var vmask = VectorMask.fromLong(SPECIES, inputLong); long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, inputLong & (((1L << (SPECIES.length() - 1)) << 1) - 1)); + Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); } @DataProvider diff --git a/test/jdk/jdk/incubator/vector/Long512VectorTests.java b/test/jdk/jdk/incubator/vector/Long512VectorTests.java index 53fa4592fc64baac7da7628fd71f57a4e6a14545..2af97735504a59ac5cd8661367f3de5030eedb57 100644 --- a/test/jdk/jdk/incubator/vector/Long512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Long512VectorTests.java @@ -5350,7 +5350,7 @@ public class Long512VectorTests extends AbstractVectorTest { static void maskFromToLongLong512VectorTestsSmokeTest(long inputLong) { var vmask = VectorMask.fromLong(SPECIES, inputLong); long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, inputLong & (((1L << (SPECIES.length() - 1)) << 1) - 1)); + Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); } @DataProvider diff --git a/test/jdk/jdk/incubator/vector/Long64VectorTests.java b/test/jdk/jdk/incubator/vector/Long64VectorTests.java index c8f9c31e4994e537091dbd7042f8abed9a398fee..1ec1bdc483f7177586caa33661db8fb870de7f12 100644 --- a/test/jdk/jdk/incubator/vector/Long64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Long64VectorTests.java @@ -5350,7 +5350,7 @@ public class Long64VectorTests extends AbstractVectorTest { static void maskFromToLongLong64VectorTestsSmokeTest(long inputLong) { var vmask = VectorMask.fromLong(SPECIES, inputLong); long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, inputLong & (((1L << (SPECIES.length() - 1)) << 1) - 1)); + Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); } @DataProvider diff --git a/test/jdk/jdk/incubator/vector/Short128VectorTests.java b/test/jdk/jdk/incubator/vector/Short128VectorTests.java index 88eca9e1d9a0fe31357661d7150a5a9a7557655a..ac31cc6e9fdc85583dbafd42cc5f3266a28af3a8 100644 --- a/test/jdk/jdk/incubator/vector/Short128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Short128VectorTests.java @@ -5491,7 +5491,7 @@ public class Short128VectorTests extends AbstractVectorTest { static void maskFromToLongShort128VectorTestsSmokeTest(long inputLong) { var vmask = VectorMask.fromLong(SPECIES, inputLong); long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, inputLong & (((1L << (SPECIES.length() - 1)) << 1) - 1)); + Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); } @DataProvider diff --git a/test/jdk/jdk/incubator/vector/Short256VectorTests.java b/test/jdk/jdk/incubator/vector/Short256VectorTests.java index bc33a302cec9357d5df243c3bb4dbf750482a18d..9fb8e7fbf1ebde712c95225ec5800d8a0439dabb 100644 --- a/test/jdk/jdk/incubator/vector/Short256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Short256VectorTests.java @@ -5491,7 +5491,7 @@ public class Short256VectorTests extends AbstractVectorTest { static void maskFromToLongShort256VectorTestsSmokeTest(long inputLong) { var vmask = VectorMask.fromLong(SPECIES, inputLong); long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, inputLong & (((1L << (SPECIES.length() - 1)) << 1) - 1)); + Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); } @DataProvider diff --git a/test/jdk/jdk/incubator/vector/Short512VectorTests.java b/test/jdk/jdk/incubator/vector/Short512VectorTests.java index b33134d622534369d61eea65111ec7cbbce048b6..b4f25ece2e871a016feb38a6ea09f73795193382 100644 --- a/test/jdk/jdk/incubator/vector/Short512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Short512VectorTests.java @@ -5491,7 +5491,7 @@ public class Short512VectorTests extends AbstractVectorTest { static void maskFromToLongShort512VectorTestsSmokeTest(long inputLong) { var vmask = VectorMask.fromLong(SPECIES, inputLong); long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, inputLong & (((1L << (SPECIES.length() - 1)) << 1) - 1)); + Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); } @DataProvider diff --git a/test/jdk/jdk/incubator/vector/Short64VectorTests.java b/test/jdk/jdk/incubator/vector/Short64VectorTests.java index af7dd74ac0e39d78f5d4383cdc8b550071a814be..564c89d639a92a036e7591ea68fb1f20b9cf8b01 100644 --- a/test/jdk/jdk/incubator/vector/Short64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Short64VectorTests.java @@ -5491,7 +5491,7 @@ public class Short64VectorTests extends AbstractVectorTest { static void maskFromToLongShort64VectorTestsSmokeTest(long inputLong) { var vmask = VectorMask.fromLong(SPECIES, inputLong); long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, inputLong & (((1L << (SPECIES.length() - 1)) << 1) - 1)); + Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); } @DataProvider diff --git a/test/jdk/jdk/incubator/vector/VectorReshapeTests.java b/test/jdk/jdk/incubator/vector/VectorReshapeTests.java index 01dcc4caf85a0858a533934143150b403d5fd82f..5db3577f36e5bf2b4966126e0e55e4ebbdae9f15 100644 --- a/test/jdk/jdk/incubator/vector/VectorReshapeTests.java +++ b/test/jdk/jdk/incubator/vector/VectorReshapeTests.java @@ -3334,6 +3334,327 @@ public class VectorReshapeTests { } } + @ForceInline + static + void testVectorUCastByteToShort(VectorSpecies<Byte> a, VectorSpecies<Short> b, byte[] input, short[] output) { + assert(input.length == a.length()); + assert(output.length == b.length()); + + ByteVector av = ByteVector.fromArray(a, input, 0); + ShortVector bv = (ShortVector) av.convertShape(VectorOperators.ZERO_EXTEND_B2S, b, 0); + bv.intoArray(output, 0); + + for (int i = 0; i < Math.min(input.length, output.length); i++) { + Assert.assertEquals(output[i], Byte.toUnsignedLong(input[i])); + } + for(int i = input.length; i < output.length; i++) { + Assert.assertEquals(output[i], (short)0); + } + } + + @ForceInline + static + void testVectorUCastByteToInt(VectorSpecies<Byte> a, VectorSpecies<Integer> b, byte[] input, int[] output) { + assert(input.length == a.length()); + assert(output.length == b.length()); + + ByteVector av = ByteVector.fromArray(a, input, 0); + IntVector bv = (IntVector) av.convertShape(VectorOperators.ZERO_EXTEND_B2I, b, 0); + bv.intoArray(output, 0); + + for (int i = 0; i < Math.min(input.length, output.length); i++) { + Assert.assertEquals(output[i], Byte.toUnsignedLong(input[i])); + } + for(int i = input.length; i < output.length; i++) { + Assert.assertEquals(output[i], (int)0); + } + } + + @ForceInline + static + void testVectorUCastByteToLong(VectorSpecies<Byte> a, VectorSpecies<Long> b, byte[] input, long[] output) { + assert(input.length == a.length()); + assert(output.length == b.length()); + + ByteVector av = ByteVector.fromArray(a, input, 0); + LongVector bv = (LongVector) av.convertShape(VectorOperators.ZERO_EXTEND_B2L, b, 0); + bv.intoArray(output, 0); + + for (int i = 0; i < Math.min(input.length, output.length); i++) { + Assert.assertEquals(output[i], Byte.toUnsignedLong(input[i])); + } + for(int i = input.length; i < output.length; i++) { + Assert.assertEquals(output[i], (long)0); + } + } + + @ForceInline + static + void testVectorUCastShortToInt(VectorSpecies<Short> a, VectorSpecies<Integer> b, short[] input, int[] output) { + assert(input.length == a.length()); + assert(output.length == b.length()); + + ShortVector av = ShortVector.fromArray(a, input, 0); + IntVector bv = (IntVector) av.convertShape(VectorOperators.ZERO_EXTEND_S2I, b, 0); + bv.intoArray(output, 0); + + for (int i = 0; i < Math.min(input.length, output.length); i++) { + Assert.assertEquals(output[i], Short.toUnsignedLong(input[i])); + } + for(int i = input.length; i < output.length; i++) { + Assert.assertEquals(output[i], (int)0); + } + } + + @ForceInline + static + void testVectorUCastShortToLong(VectorSpecies<Short> a, VectorSpecies<Long> b, short[] input, long[] output) { + assert(input.length == a.length()); + assert(output.length == b.length()); + + ShortVector av = ShortVector.fromArray(a, input, 0); + LongVector bv = (LongVector) av.convertShape(VectorOperators.ZERO_EXTEND_S2L, b, 0); + bv.intoArray(output, 0); + + for (int i = 0; i < Math.min(input.length, output.length); i++) { + Assert.assertEquals(output[i], Short.toUnsignedLong(input[i])); + } + for(int i = input.length; i < output.length; i++) { + Assert.assertEquals(output[i], (long)0); + } + } + + @ForceInline + static + void testVectorUCastIntToLong(VectorSpecies<Integer> a, VectorSpecies<Long> b, int[] input, long[] output) { + assert(input.length == a.length()); + assert(output.length == b.length()); + + IntVector av = IntVector.fromArray(a, input, 0); + LongVector bv = (LongVector) av.convertShape(VectorOperators.ZERO_EXTEND_I2L, b, 0); + bv.intoArray(output, 0); + + for (int i = 0; i < Math.min(input.length, output.length); i++) { + Assert.assertEquals(output[i], Integer.toUnsignedLong(input[i])); + } + for(int i = input.length; i < output.length; i++) { + Assert.assertEquals(output[i], (long)0); + } + } + + @Test(dataProvider = "byteUnaryOpProvider") + static void testUCastFromByte(IntFunction<byte[]> fa) { + byte[] bin64 = fa.apply(bspec64.length()); + byte[] bin128 = fa.apply(bspec128.length()); + byte[] bin256 = fa.apply(bspec256.length()); + byte[] bin512 = fa.apply(bspec512.length()); + + short[] sout64 = new short[sspec64.length()]; + short[] sout128 = new short[sspec128.length()]; + short[] sout256 = new short[sspec256.length()]; + short[] sout512 = new short[sspec512.length()]; + + int[] iout64 = new int[ispec64.length()]; + int[] iout128 = new int[ispec128.length()]; + int[] iout256 = new int[ispec256.length()]; + int[] iout512 = new int[ispec512.length()]; + + long[] lout64 = new long[lspec64.length()]; + long[] lout128 = new long[lspec128.length()]; + long[] lout256 = new long[lspec256.length()]; + long[] lout512 = new long[lspec512.length()]; + + for (int i = 0; i < NUM_ITER; i++) { + // B2S exact fit + testVectorUCastByteToShort(bspec64, sspec128, bin64, sout128); + testVectorUCastByteToShort(bspec128, sspec256, bin128, sout256); + testVectorUCastByteToShort(bspec256, sspec512, bin256, sout512); + + // B2S expansion + testVectorUCastByteToShort(bspec64, sspec64, bin64, sout64); + testVectorUCastByteToShort(bspec128, sspec128, bin128, sout128); + testVectorUCastByteToShort(bspec256, sspec256, bin256, sout256); + testVectorUCastByteToShort(bspec512, sspec512, bin512, sout512); + + testVectorUCastByteToShort(bspec128, sspec64, bin128, sout64); + testVectorUCastByteToShort(bspec256, sspec128, bin256, sout128); + testVectorUCastByteToShort(bspec512, sspec256, bin512, sout256); + + testVectorUCastByteToShort(bspec256, sspec64, bin256, sout64); + testVectorUCastByteToShort(bspec512, sspec128, bin512, sout128); + + testVectorUCastByteToShort(bspec512, sspec64, bin512, sout64); + + // B2S contraction + testVectorUCastByteToShort(bspec64, sspec256, bin64, sout256); + testVectorUCastByteToShort(bspec128, sspec512, bin128, sout512); + + testVectorUCastByteToShort(bspec64, sspec512, bin64, sout512); + + // B2I exact fit + testVectorUCastByteToInt(bspec64, ispec256, bin64, iout256); + testVectorUCastByteToInt(bspec128, ispec512, bin128, iout512); + + // B2I expansion + testVectorUCastByteToInt(bspec64, ispec128, bin64, iout128); + testVectorUCastByteToInt(bspec128, ispec256, bin128, iout256); + testVectorUCastByteToInt(bspec256, ispec512, bin256, iout512); + + testVectorUCastByteToInt(bspec64, ispec64, bin64, iout64); + testVectorUCastByteToInt(bspec128, ispec128, bin128, iout128); + testVectorUCastByteToInt(bspec256, ispec256, bin256, iout256); + testVectorUCastByteToInt(bspec512, ispec512, bin512, iout512); + + testVectorUCastByteToInt(bspec128, ispec64, bin128, iout64); + testVectorUCastByteToInt(bspec256, ispec128, bin256, iout128); + testVectorUCastByteToInt(bspec512, ispec256, bin512, iout256); + + testVectorUCastByteToInt(bspec256, ispec64, bin256, iout64); + testVectorUCastByteToInt(bspec512, ispec128, bin512, iout128); + + testVectorUCastByteToInt(bspec512, ispec64, bin512, iout64); + + // B2I contraction + testVectorUCastByteToInt(bspec64, ispec512, bin64, iout512); + + // B2L exact fit + testVectorUCastByteToLong(bspec64, lspec512, bin64, lout512); + + // B2L expansion + testVectorUCastByteToLong(bspec64, lspec256, bin64, lout256); + testVectorUCastByteToLong(bspec128, lspec512, bin128, lout512); + + testVectorUCastByteToLong(bspec64, lspec128, bin64, lout128); + testVectorUCastByteToLong(bspec128, lspec256, bin128, lout256); + testVectorUCastByteToLong(bspec256, lspec512, bin256, lout512); + + testVectorUCastByteToLong(bspec64, lspec64, bin64, lout64); + testVectorUCastByteToLong(bspec128, lspec128, bin128, lout128); + testVectorUCastByteToLong(bspec256, lspec256, bin256, lout256); + testVectorUCastByteToLong(bspec512, lspec512, bin512, lout512); + + testVectorUCastByteToLong(bspec128, lspec64, bin128, lout64); + testVectorUCastByteToLong(bspec256, lspec128, bin256, lout128); + testVectorUCastByteToLong(bspec512, lspec256, bin512, lout256); + + testVectorUCastByteToLong(bspec256, lspec64, bin256, lout64); + testVectorUCastByteToLong(bspec512, lspec128, bin512, lout128); + + testVectorUCastByteToLong(bspec512, lspec64, bin512, lout64); + } + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void testUCastFromShort(IntFunction<short[]> fa) { + short[] sin64 = fa.apply(sspec64.length()); + short[] sin128 = fa.apply(sspec128.length()); + short[] sin256 = fa.apply(sspec256.length()); + short[] sin512 = fa.apply(sspec512.length()); + + int[] iout64 = new int[ispec64.length()]; + int[] iout128 = new int[ispec128.length()]; + int[] iout256 = new int[ispec256.length()]; + int[] iout512 = new int[ispec512.length()]; + + long[] lout64 = new long[lspec64.length()]; + long[] lout128 = new long[lspec128.length()]; + long[] lout256 = new long[lspec256.length()]; + long[] lout512 = new long[lspec512.length()]; + + for (int i = 0; i < NUM_ITER; i++) { + // S2I exact fit + testVectorUCastShortToInt(sspec64, ispec128, sin64, iout128); + testVectorUCastShortToInt(sspec128, ispec256, sin128, iout256); + testVectorUCastShortToInt(sspec256, ispec512, sin256, iout512); + + // S2I expansion + testVectorUCastShortToInt(sspec64, ispec64, sin64, iout64); + testVectorUCastShortToInt(sspec128, ispec128, sin128, iout128); + testVectorUCastShortToInt(sspec256, ispec256, sin256, iout256); + testVectorUCastShortToInt(sspec512, ispec512, sin512, iout512); + + testVectorUCastShortToInt(sspec128, ispec64, sin128, iout64); + testVectorUCastShortToInt(sspec256, ispec128, sin256, iout128); + testVectorUCastShortToInt(sspec512, ispec256, sin512, iout256); + + testVectorUCastShortToInt(sspec256, ispec64, sin256, iout64); + testVectorUCastShortToInt(sspec512, ispec128, sin512, iout128); + + testVectorUCastShortToInt(sspec512, ispec64, sin512, iout64); + + // S2I contraction + testVectorUCastShortToInt(sspec64, ispec256, sin64, iout256); + testVectorUCastShortToInt(sspec128, ispec512, sin128, iout512); + + testVectorUCastShortToInt(sspec64, ispec512, sin64, iout512); + + // S2L exact fit + testVectorUCastShortToLong(sspec64, lspec256, sin64, lout256); + testVectorUCastShortToLong(sspec128, lspec512, sin128, lout512); + + // S2L expansion + testVectorUCastShortToLong(sspec64, lspec128, sin64, lout128); + testVectorUCastShortToLong(sspec128, lspec256, sin128, lout256); + testVectorUCastShortToLong(sspec256, lspec512, sin256, lout512); + + testVectorUCastShortToLong(sspec64, lspec64, sin64, lout64); + testVectorUCastShortToLong(sspec128, lspec128, sin128, lout128); + testVectorUCastShortToLong(sspec256, lspec256, sin256, lout256); + testVectorUCastShortToLong(sspec512, lspec512, sin512, lout512); + + testVectorUCastShortToLong(sspec128, lspec64, sin128, lout64); + testVectorUCastShortToLong(sspec256, lspec128, sin256, lout128); + testVectorUCastShortToLong(sspec512, lspec256, sin512, lout256); + + testVectorUCastShortToLong(sspec256, lspec64, sin256, lout64); + testVectorUCastShortToLong(sspec512, lspec128, sin512, lout128); + + testVectorUCastShortToLong(sspec512, lspec64, sin512, lout64); + + // S2L contraction + testVectorUCastShortToLong(sspec64, lspec512, sin64, lout512); + } + } + + @Test(dataProvider = "intUnaryOpProvider") + static void testUCastFromInt(IntFunction<int[]> fa) { + int[] iin64 = fa.apply(ispec64.length()); + int[] iin128 = fa.apply(ispec128.length()); + int[] iin256 = fa.apply(ispec256.length()); + int[] iin512 = fa.apply(ispec512.length()); + + long[] lout64 = new long[lspec64.length()]; + long[] lout128 = new long[lspec128.length()]; + long[] lout256 = new long[lspec256.length()]; + long[] lout512 = new long[lspec512.length()]; + + // I2L exact fit + testVectorUCastIntToLong(ispec64, lspec128, iin64, lout128); + testVectorUCastIntToLong(ispec128, lspec256, iin128, lout256); + testVectorUCastIntToLong(ispec256, lspec512, iin256, lout512); + + // I2L expansion + testVectorUCastIntToLong(ispec64, lspec64, iin64, lout64); + testVectorUCastIntToLong(ispec128, lspec128, iin128, lout128); + testVectorUCastIntToLong(ispec256, lspec256, iin256, lout256); + testVectorUCastIntToLong(ispec512, lspec512, iin512, lout512); + + testVectorUCastIntToLong(ispec128, lspec64, iin128, lout64); + testVectorUCastIntToLong(ispec256, lspec128, iin256, lout128); + testVectorUCastIntToLong(ispec512, lspec256, iin512, lout256); + + testVectorUCastIntToLong(ispec256, lspec64, iin256, lout64); + testVectorUCastIntToLong(ispec512, lspec128, iin512, lout128); + + testVectorUCastIntToLong(ispec512, lspec64, iin512, lout64); + + // I2L contraction + testVectorUCastIntToLong(ispec64, lspec256, iin64, lout256); + testVectorUCastIntToLong(ispec128, lspec512, iin128, lout512); + + testVectorUCastIntToLong(ispec64, lspec512, iin64, lout512); + } + static void testVectorCastByteMaxToByte(VectorSpecies<Byte> a, VectorSpecies<Byte> b, byte[] input, byte[] output) { diff --git a/test/jdk/jdk/incubator/vector/clean.sh b/test/jdk/jdk/incubator/vector/clean.sh index f889a9136238330a6b43263f707e802717a75b88..7c177d800164b7df1372eac7793ab09e4f1c73de 100644 --- a/test/jdk/jdk/incubator/vector/clean.sh +++ b/test/jdk/jdk/incubator/vector/clean.sh @@ -1,6 +1,6 @@ #!/bin/bash # -# Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -24,4 +24,4 @@ # questions. # -rm -rf *.class build.log test-output +rm -rf build.log diff --git a/test/jdk/jdk/incubator/vector/config.sh b/test/jdk/jdk/incubator/vector/config.sh index c1447b2e9fdc13f08b0301c435f17542451812cc..15bfe647c3a441b1b88b29c13b6fdf9b0d500a80 100644 --- a/test/jdk/jdk/incubator/vector/config.sh +++ b/test/jdk/jdk/incubator/vector/config.sh @@ -1,6 +1,6 @@ #!/bin/bash # -# Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -35,9 +35,6 @@ SPP_CLASSNAME="build.tools.spp.Spp" SEPARATOR=":" TYPEPREFIX="" TEMPLATE_FILE="unit_tests.template" -TESTNG_JAR="${TESTNG_PLUGIN}/plugins/org.testng.source_6.13.1.r201712040515.jar" -TESTNG_RUN_JAR="${TESTNG_PLUGIN}/plugins/org.testng_6.13.1.r201712040515.jar" -JCOMMANDER_JAR="${TESTNG_PLUGIN}/plugins/com.beust.jcommander_1.72.0.jar" TEST_ITER_COUNT=100 PERF_TEMPLATE_FILE="perf_tests.template" diff --git a/test/jdk/jdk/incubator/vector/gen-tests.sh b/test/jdk/jdk/incubator/vector/gen-tests.sh index 0056f54868d6913e67dd2d0813b43373c4874553..d02f0c519fe8fe593635b35e617bf2da4b0c6b61 100644 --- a/test/jdk/jdk/incubator/vector/gen-tests.sh +++ b/test/jdk/jdk/incubator/vector/gen-tests.sh @@ -1,6 +1,6 @@ #!/bin/bash # -# Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -28,20 +28,10 @@ # You can regenerate the source files, # and you can clean them up. # FIXME: Move this script under $REPO/make/gensrc/ -list_mech_gen() { - ( # List MG files physically present - grep -il 'mechanically generated.*do not edit' $(find * -name \*.java -print) - # List MG files currently deleted (via --clean) - hg status -nd . - ) | egrep '(^|/)(Byte|Short|Int|Long|Float|Double)(Scalar|([0-9Max]+Vector)).*\.java$' -} case $* in '') CLASS_FILTER='*';; --generate*) CLASS_FILTER=${2-'*'};; ---clean) MG=$(list_mech_gen); set -x; rm -f $MG; exit;; ---revert) MG=$(list_mech_gen); set -x; hg revert $MG; exit;; ---list) list_mech_gen; exit;; ---help|*) echo "Usage: $0 [--generate [file] | --clean | --revert | --list]"; exit 1;; +--help|*) echo "Usage: $0 [--generate [file]]"; exit 1;; esac . config.sh diff --git a/test/jdk/jdk/incubator/vector/run-tests.sh b/test/jdk/jdk/incubator/vector/run-tests.sh deleted file mode 100644 index 0669a97c2e6bbe63c3690ba95b864e10b7b802fb..0000000000000000000000000000000000000000 --- a/test/jdk/jdk/incubator/vector/run-tests.sh +++ /dev/null @@ -1,86 +0,0 @@ -#!/bin/bash -# -# Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -. config.sh - -POSITIONAL=() -while [[ $# -gt 0 ]] -do -key="$1" - -TESTS="" -DISABLE_VECTOR_INTRINSICS=false -case $key in - -t|--tests) - TESTS="$2" - echo "Tests set to $TESTS" - shift # past argument - shift # past value - ;; - -d|--disable-vector-intrinsics) - DISABLE_VECTOR_INTRINSICS=true - echo "Warning: Disabling Vector intrinsics..." - shift # past argument - ;; - *) # unknown option - POSITIONAL+=("$1") # save it in an array for later - shift # past argument - ;; -esac -done -set -- "${POSITIONAL[@]}" # restore positional parameters - - -if [ "$TESTS" == "" ]; then - # Run all the tests by default. - TESTS="Byte64VectorTests,Byte128VectorTests,Byte256VectorTests,Byte512VectorTests," - TESTS+="Int64VectorTests,Int128VectorTests,Int256VectorTests,Int512VectorTests," - TESTS+="Long64VectorTests,Long128VectorTests,Long256VectorTests,Long512VectorTests," - TESTS+="Short64VectorTests,Short128VectorTests,Short256VectorTests,Short512VectorTests," - TESTS+="Double64VectorTests,Double128VectorTests,Double256VectorTests,Double512VectorTests," - TESTS+="Float64VectorTests,Float128VectorTests,Float256VectorTests,Float512VectorTests" -fi - -# Get Java flags. -JAVA_FLAGS="-XX:-TieredCompilation" -if [ "$DISABLE_VECTOR_INTRINSICS" == "true" ]; then - JAVA_FLAGS+=" -XX:-UseVectorApiIntrinsics" -fi - -LogRun false "Running tests $(date)\n" -LogRun true "Running the following tests:\n" -LogRun true "${TESTS}\n" -LogRun false "${JAVA} -cp \"${VECTORTESTS_HOME_CP}${SEPARATOR}${TESTNG_RUN_JAR}${SEPARATOR}${JCOMMANDER_JAR}\" ${JAVA_FLAGS} --add-modules jdk.incubator.vector --add-opens jdk.incubator.vector/jdk.incubator.vector=ALL-UNNAMED org.testng.TestNG -testclass $TESTS" - -# Actual TestNG run. -time ${JAVA} -cp "${VECTORTESTS_HOME_CP}${SEPARATOR}${TESTNG_RUN_JAR}${SEPARATOR}${JCOMMANDER_JAR}" \ - ${JAVA_FLAGS} \ - --add-modules jdk.incubator.vector \ - --add-opens jdk.incubator.vector/jdk.incubator.vector=ALL-UNNAMED \ - -Djdk.incubator.vector.test.loop-iterations=${TEST_ITER_COUNT} \ - org.testng.TestNG -testclass $TESTS -LogRun true "Tests run complete. Please look at test-output/index.html to visualize the results.\n" - diff --git a/test/jdk/jdk/incubator/vector/templates/Unit-Miscellaneous.template b/test/jdk/jdk/incubator/vector/templates/Unit-Miscellaneous.template index a75a6842bd316fe558854d1fe6dda651453c5a06..59c133936f7a8e86134524638ffa7657a4123f11 100644 --- a/test/jdk/jdk/incubator/vector/templates/Unit-Miscellaneous.template +++ b/test/jdk/jdk/incubator/vector/templates/Unit-Miscellaneous.template @@ -499,7 +499,7 @@ static void maskFromToLong$vectorteststype$SmokeTest(long inputLong) { var vmask = VectorMask.fromLong(SPECIES, inputLong); long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, inputLong & (((1L << (SPECIES.length() - 1)) << 1) - 1)); + Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); } #end[!MaxBit] diff --git a/test/jdk/jdk/jfr/api/consumer/TestHiddenMethod.java b/test/jdk/jdk/jfr/api/consumer/TestHiddenMethod.java index 7a5bf1e42c42f6c38577a3e17dc4161501dc1acc..f1eeac58362d12f12fc01516bd8382ac1a3e929a 100644 --- a/test/jdk/jdk/jfr/api/consumer/TestHiddenMethod.java +++ b/test/jdk/jdk/jfr/api/consumer/TestHiddenMethod.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,10 +51,10 @@ import jdk.test.lib.jfr.Events; */ public final class TestHiddenMethod { - public static void main(String[] args) throws Throwable { - try (Recording recording = new Recording()) { - recording.enable(MyEvent.class).withThreshold(Duration.ofMillis(0)); - recording.start(); + // Must call in separate thread because JTREG uses reflection + // to invoke main method, which uses hidden methods. + public static class TestThread extends Thread { + public void run() { // doPrivileged calls a method that has the @Hidden // annotation AccessController.doPrivileged(new PrivilegedAction<Void>() { @@ -65,8 +65,19 @@ public final class TestHiddenMethod { return null; } }); + MyEvent event = new MyEvent(); event.commit(); + } + } + + public static void main(String[] args) throws Throwable { + try (Recording recording = new Recording()) { + recording.enable(MyEvent.class).withThreshold(Duration.ofMillis(0)); + recording.start(); + Thread t = new TestThread(); + t.start(); + t.join(); recording.stop(); List<RecordedEvent> events = Events.fromRecording(recording); @@ -78,9 +89,7 @@ public final class TestHiddenMethod { System.out.println("visibleEvent:" + visibleEvent); assertTrue(hasHiddenStackFrame(hiddenEvent), "No hidden frame in hidden event: " + hiddenEvent); - - // Temporary disable this test until JDK-8272064 is resolved. - // assertFalse(hasHiddenStackFrame(visibleEvent), "Hidden frame in visible event: " + visibleEvent); + assertFalse(hasHiddenStackFrame(visibleEvent), "Hidden frame in visible event: " + visibleEvent); } } diff --git a/test/jdk/jdk/jfr/event/runtime/TestFinalizerStatisticsEvent.java b/test/jdk/jdk/jfr/event/runtime/TestFinalizerStatisticsEvent.java index ecec7c383fb7bc46fa9dc6bf9c3f9f420dce7030..8256a62b5712b62dce068da4ae9742003990ec12 100644 --- a/test/jdk/jdk/jfr/event/runtime/TestFinalizerStatisticsEvent.java +++ b/test/jdk/jdk/jfr/event/runtime/TestFinalizerStatisticsEvent.java @@ -34,17 +34,20 @@ import jdk.test.lib.jfr.TestClassLoader; /** * @test + * @bug 8266936 8276422 * @summary The test verifies that classes overriding finalize() are represented as events. * @key jfr * @requires vm.hasJFR * @library /test/lib /test/jdk * @run main/othervm -Xlog:class+unload,finalizer -Xmx16m jdk.jfr.event.runtime.TestFinalizerStatisticsEvent + * @run main/othervm -Xlog:class+unload,finalizer -Xmx16m --finalization=disabled jdk.jfr.event.runtime.TestFinalizerStatisticsEvent disabled */ public final class TestFinalizerStatisticsEvent { private final static String TEST_CLASS_NAME = "jdk.jfr.event.runtime.TestFinalizerStatisticsEvent$TestClassOverridingFinalize"; private final static String TEST_CLASS_UNLOAD_NAME = "jdk.jfr.event.runtime.TestFinalizerStatisticsEvent$TestClassUnloadOverridingFinalize"; private final static String EVENT_PATH = EventNames.FinalizerStatistics; + private static boolean disabled = false; // Declare as public static to prevent the compiler from optimizing away all unread writes public static TestClassLoader unloadableClassLoader; @@ -52,6 +55,10 @@ public final class TestFinalizerStatisticsEvent { public static Object overridingInstance; public static void main(String[] args) throws Throwable { + if (args.length > 0 && "disabled".equals(args[0])) { + disabled = true; + System.out.println("Testing with finalization disabled"); + } Recording recording1 = new Recording(); recording1.enable(EVENT_PATH); Recording recording2 = new Recording(); @@ -69,8 +76,12 @@ public final class TestFinalizerStatisticsEvent { recording1.stop(); // rotation writes an event for TEST_CLASS_NAME into recording1 which now has 4 events reflecting this test case (3 chunks + 1 unload) try { - verify(recording2); - verify(recording1); + if (disabled) { + verifyDisabled(recording1); + } else { + verifyEnabled(recording2); + verifyEnabled(recording1); + } } finally { recording2.close(); @@ -84,7 +95,8 @@ public final class TestFinalizerStatisticsEvent { System.gc(); } - private static void verify(Recording recording) throws Throwable { + /* Verify correct operation with finalization enabled */ + private static void verifyEnabled(Recording recording) throws Throwable { boolean foundTestClassName = false; boolean foundTestClassUnloadName = false; List<RecordedEvent> events = Events.fromRecording(recording); @@ -108,6 +120,19 @@ public final class TestFinalizerStatisticsEvent { Asserts.assertTrue(foundTestClassUnloadName, "The class: " + TEST_CLASS_UNLOAD_NAME + " overriding finalize() is not found"); } + /* Verify no jdk.FinalizerStatistics events with finalization disabled */ + private static void verifyDisabled(Recording recording) throws Throwable { + int f10nEvents = 0; + List<RecordedEvent> events = Events.fromRecording(recording); + for (RecordedEvent event : events) { + System.out.println("Event:" + event); + if ("jdk.FinalizerStatistics".equals(event.getEventType().getName())) { + f10nEvents++; + } + } + Asserts.assertEquals(f10nEvents, 0, "Finalization disabled, but recorded " + f10nEvents + " jdk.FinalizerStatistics events"); + } + static public class TestClassOverridingFinalize { public boolean finalized = false; diff --git a/test/jdk/jdk/jfr/jcmd/TestJcmdConfigureReadOnly.java b/test/jdk/jdk/jfr/jcmd/TestJcmdConfigureReadOnly.java new file mode 100644 index 0000000000000000000000000000000000000000..6ddf3a752342d04952ffda1df0933f226a2a88b4 --- /dev/null +++ b/test/jdk/jdk/jfr/jcmd/TestJcmdConfigureReadOnly.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.jfr.jcmd; + +import jdk.test.lib.process.OutputAnalyzer; + +/** + * @test + * @summary The test verifies JFR.configure command can only set certain options before JFR is started. + * @key jfr + * @requires vm.hasJFR + * @library /test/lib /test/jdk + * @run main/othervm jdk.jfr.jcmd.TestJcmdConfigureReadOnly + */ +public class TestJcmdConfigureReadOnly { + public static void main(String[] args) throws Exception { + // Set an option before initializing JFR. + OutputAnalyzer output = JcmdHelper.jcmd("JFR.configure", "stackdepth=" + 128); + output.shouldContain("Stack depth: 128"); + // JFR.start will initialize JFR. + output = JcmdHelper.jcmd("JFR.start"); + JcmdAsserts.assertRecordingHasStarted(output); + // Attempt to set a new value after JFR initialization. + output = JcmdHelper.jcmd("JFR.configure", "stackdepth=" + 256); + // After initialization, the option is considered read-only. + output.shouldContain("Stack depth: 128"); + } +} diff --git a/test/jdk/jdk/jfr/jvm/TestDumpOnCrash.java b/test/jdk/jdk/jfr/jvm/TestDumpOnCrash.java index 3869509b2426ec6233eacd34f592453776f55b5d..5cd1f435bfd7e496eb9b96204ee3d3f0868c5797 100644 --- a/test/jdk/jdk/jfr/jvm/TestDumpOnCrash.java +++ b/test/jdk/jdk/jfr/jvm/TestDumpOnCrash.java @@ -26,6 +26,7 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.ArrayList; import java.util.List; import jdk.internal.misc.Unsafe; @@ -74,22 +75,42 @@ public class TestDumpOnCrash { } public static void main(String[] args) throws Exception { + // Test without dumppath test(CrasherIllegalAccess.class, "", true); test(CrasherIllegalAccess.class, "", false); test(CrasherHalt.class, "", true); test(CrasherHalt.class, "", false); + // Test with dumppath + Path dumppath = Files.createTempDirectory(null); + try { + test(CrasherIllegalAccess.class, "", true, dumppath.toString()); + test(CrasherIllegalAccess.class, "", false, dumppath.toString()); + test(CrasherHalt.class, "", true, dumppath.toString()); + test(CrasherHalt.class, "", false, dumppath.toString()); + } finally { + dumppath.toFile().delete(); + } + // Test is excluded until 8219680 is fixed // @ignore 8219680 // test(CrasherSig.class, "FPE", true); } private static void test(Class<?> crasher, String signal, boolean disk) throws Exception { + test(crasher, signal, disk, null); + } + + private static void test(Class<?> crasher, String signal, boolean disk, String dumppath) throws Exception { + test(crasher, signal, disk, dumppath, dumppath); + } + + private static void test(Class<?> crasher, String signal, boolean disk, String dumppath, String expectedPath) throws Exception { // The JVM may be in a state it can't recover from, so try three times // before concluding functionality is not working. for (int attempt = 0; attempt < ATTEMPTS; attempt++) { try { - verify(runProcess(crasher, signal, disk)); + verify(runProcess(crasher, signal, disk, dumppath), expectedPath); return; } catch (Exception e) { System.out.println("Attempt " + attempt + ". Verification failed:"); @@ -105,17 +126,19 @@ public class TestDumpOnCrash { throw new Exception(ATTEMPTS + " attempts with failure!"); } - private static long runProcess(Class<?> crasher, String signal, boolean disk) throws Exception { + private static long runProcess(Class<?> crasher, String signal, boolean disk, String dumppath) throws Exception { System.out.println("Test case for crasher " + crasher.getName()); - final String flightRecordingOptions = "dumponexit=true,disk=" + Boolean.toString(disk); - Process p = ProcessTools.createTestJvm( - "-Xmx64m", - "-XX:-CreateCoredumpOnCrash", - "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED", - "-XX:StartFlightRecording:" + flightRecordingOptions, - crasher.getName(), - signal) - .start(); + List<String> options = new ArrayList<>(); + options.add("-Xmx64m"); + options.add("-XX:-CreateCoredumpOnCrash"); + options.add("--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED"); + options.add("-XX:StartFlightRecording:dumponexit=true,disk=" + Boolean.toString(disk)); + if (dumppath != null) { + options.add("-XX:FlightRecorderOptions=dumppath=" + dumppath); + } + options.add(crasher.getName()); + options.add(signal); + Process p = ProcessTools.createTestJvm(options).start(); OutputAnalyzer output = new OutputAnalyzer(p); System.out.println("========== Crasher process output:"); @@ -125,9 +148,10 @@ public class TestDumpOnCrash { return p.pid(); } - private static void verify(long pid) throws IOException { + private static void verify(long pid, String dumppath) throws IOException { String fileName = "hs_err_pid" + pid + ".jfr"; - Path file = Paths.get(fileName).toAbsolutePath().normalize(); + Path file = (dumppath == null) ? Paths.get(fileName) : Paths.get(dumppath, fileName); + file = file.toAbsolutePath().normalize(); Asserts.assertTrue(Files.exists(file), "No emergency jfr recording file " + file + " exists"); Asserts.assertNotEquals(Files.size(file), 0L, "File length 0. Should at least be some bytes"); diff --git a/test/jdk/jdk/nio/zipfs/ZipFSTester.java b/test/jdk/jdk/nio/zipfs/ZipFSTester.java index 48244bfc46b06e824ca1cdb5e178a4e59f5f8a93..08c998ca221854bf84c51abe12bce026594857ea 100644 --- a/test/jdk/jdk/nio/zipfs/ZipFSTester.java +++ b/test/jdk/jdk/nio/zipfs/ZipFSTester.java @@ -73,7 +73,7 @@ import static java.nio.file.StandardCopyOption.*; * @test * @bug 6990846 7009092 7009085 7015391 7014948 7005986 7017840 7007596 * 7157656 8002390 7012868 7012856 8015728 8038500 8040059 8069211 - * 8131067 8034802 8210899 8273961 + * 8131067 8034802 8210899 8273961 8271079 * @summary Test Zip filesystem provider * @modules jdk.zipfs * @run main ZipFSTester diff --git a/test/jdk/jdk/nio/zipfs/jarfs/JFSTester.java b/test/jdk/jdk/nio/zipfs/jarfs/JFSTester.java index 5b912c239bd0104eaa6f6b385499af73432a2493..82505e24e6cfc7304743368ebb51cf1c00e70ec7 100644 --- a/test/jdk/jdk/nio/zipfs/jarfs/JFSTester.java +++ b/test/jdk/jdk/nio/zipfs/jarfs/JFSTester.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8164389 8222440 + * @bug 8164389 8222440 8271079 * @summary walk entries in a multi-release jar file via jdk.zipfs * @modules jdk.jartool * jdk.zipfs @@ -146,4 +146,58 @@ public class JFSTester { throw new UncheckedIOException(x); } } + + @Test + public void testToUri() throws IOException { + // treat multi-release jar as unversioned + Map<String, String> env = new HashMap<>(); + Set<String> contents = doTestUri(env); + Set<String> expectedContents = Set.of( + "!/root/dir1/leaf1.txt", + "!/root/dir1/leaf2.txt", + "!/root/dir2/leaf3.txt", + "!/root/dir2/leaf4.txt" + ); + Assert.assertEquals(contents, expectedContents); + + // open file as multi-release for version 9 + env.put("multi-release", "9"); + contents = doTestUri(env); + expectedContents = Set.of( + "!/root/dir1/leaf1.txt", + "!/root/dir1/leaf2.txt", + "!/META-INF/versions/9/root/dir2/leaf3.txt", + "!/META-INF/versions/9/root/dir2/leaf4.txt", + "!/META-INF/versions/9/root/dir3/leaf5.txt", + "!/META-INF/versions/9/root/dir3/leaf6.txt" + ); + Assert.assertEquals(contents, expectedContents); + + // open file as multi-release for version 10 + env.put("multi-release", "10"); + contents = doTestUri(env); + expectedContents = Set.of( + "!/root/dir1/leaf1.txt", + "!/root/dir1/leaf2.txt", + "!/META-INF/versions/9/root/dir2/leaf3.txt", + "!/META-INF/versions/9/root/dir2/leaf4.txt", + "!/META-INF/versions/10/root/dir3/leaf5.txt", + "!/META-INF/versions/10/root/dir3/leaf6.txt" + ); + Assert.assertEquals(contents, expectedContents); + } + + private Set<String> doTestUri(Map<String,String> env) throws IOException { + Set<String> contents; + try (FileSystem fs = FileSystems.newFileSystem(jarURI, env)) { + Path root = fs.getPath("root"); + int prefix = root.toUri().toString().indexOf('!'); + contents = Files.walk(root) + .filter(p -> !Files.isDirectory(p)) + .map(p -> p.toUri().toString().substring(prefix)) + .sorted() + .collect(Collectors.toSet()); + } + return contents; + } } diff --git a/test/jdk/sun/security/krb5/auto/KDC.java b/test/jdk/sun/security/krb5/auto/KDC.java index aeab113995f93f661f60050b51575091fff5c02b..6e4bfba61f4a843bdb33103723a3ba0ee9b6b3b1 100644 --- a/test/jdk/sun/security/krb5/auto/KDC.java +++ b/test/jdk/sun/security/krb5/auto/KDC.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,8 +29,11 @@ import java.lang.reflect.InvocationTargetException; import java.net.*; import java.io.*; import java.lang.reflect.Method; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.util.*; import java.util.concurrent.*; import java.util.stream.Collectors; @@ -249,6 +252,14 @@ public class KDC { * If true, will check if TGS-REQ contains a non-null addresses field. */ CHECK_ADDRESSES, + /** + * If true, S4U2self ticket is not set forwardable. + */ + S4U2SELF_NOT_FORWARDABLE, + /** + * If true, allow S4U2self ticket not forwardable. + */ + S4U2SELF_ALLOW_NOT_FORWARDABLE, }; /** @@ -441,12 +452,12 @@ public class KDC { } /** - * Adds a new principal to this realm with a random password + * Adds a new principal to this realm with a generated password * @param user the principal's name. For a service principal, use the * form of host/f.q.d.n */ public void addPrincipalRandKey(String user) { - addPrincipal(user, randomPassword()); + addPrincipal(user, randomPassword(user + "@" + realm)); } /** @@ -607,14 +618,29 @@ public class KDC { startServer(port, asDaemon); } /** - * Generates a 32-char random password + * Generates a 32-char password + * @param user the string to generate from, random is null * @return the password */ - private static char[] randomPassword() { - char[] pass = new char[32]; - Random r = new Random(); - for (int i=0; i<31; i++) - pass[i] = (char)('a' + r.nextInt(26)); + private static char[] randomPassword(String user) { + char[] pass; + if (user == null) { + pass = new char[32]; + Random r = new Random(); + for (int i = 0; i < 31; i++) { + pass[i] = (char) ('a' + r.nextInt(26)); + } + } else { + try { + pass = Base64.getEncoder().encodeToString( + MessageDigest.getInstance("SHA-256").digest((user) + .getBytes(StandardCharsets.UTF_8))) + .substring(0, 32) + .toCharArray(); + } catch (NoSuchAlgorithmException e) { + throw new AssertionError(e); + } + } // The last char cannot be a number, otherwise, keyForUser() // believes it's a sign of kvno pass[31] = 'Z'; @@ -629,7 +655,7 @@ public class KDC { */ private static EncryptionKey generateRandomKey(int eType) throws KrbException { - return genKey0(randomPassword(), "NOTHING", null, eType, null); + return genKey0(randomPassword(null), "NOTHING", null, eType, null); } /** @@ -790,7 +816,7 @@ public class KDC { service.getNameStrings(), service.getRealm()); } try { - System.out.println(realm + "> " + tgsReq.reqBody.cname + + log(tgsReq.reqBody.cname + " sends TGS-REQ for " + service + ", " + tgsReq.reqBody.kdcOptions); KDCReqBody body = tgsReq.reqBody; @@ -810,7 +836,7 @@ public class KDC { boolean allowForwardable = true; boolean isReferral = false; if (body.kdcOptions.get(KDCOptions.CANONICALIZE)) { - System.out.println(realm + "> verifying referral for " + + log("verifying referral for " + body.sname.getNameString()); KDC referral = aliasReferrals.get(body.sname.getNameString()); if (referral != null) { @@ -819,7 +845,7 @@ public class KDC { PrincipalName.NAME_COMPONENT_SEPARATOR_STR + referral.getRealm(), PrincipalName.KRB_NT_SRV_INST, this.getRealm()); - System.out.println(realm + "> referral to " + + log("referral to " + referral.getRealm()); isReferral = true; } @@ -842,14 +868,14 @@ public class KDC { // Finally, cname will be overwritten by PA-FOR-USER // if it exists. cname = etp.cname; - System.out.println(realm + "> presenting a ticket of " + log("presenting a ticket of " + etp.cname + " to " + tkt.sname); } else if (pa.getType() == Krb5.PA_FOR_USER) { if (options.containsKey(Option.ALLOW_S4U2SELF)) { PAForUserEnc p4u = new PAForUserEnc( new DerValue(pa.getValue()), null); forUserCName = p4u.name; - System.out.println(realm + "> See PA_FOR_USER " + log("See PA_FOR_USER " + " in the name of " + p4u.name); } } @@ -862,6 +888,9 @@ public class KDC { // allowed to send S4U2self, do not send an error. // Instead, send a ticket which is useless later. allowForwardable = false; + } else if (options.get(Option.S4U2SELF_NOT_FORWARDABLE) == Boolean.TRUE) { + // Requsted not forwardable + allowForwardable = false; } cname = forUserCName; } @@ -936,15 +965,16 @@ public class KDC { DerInputStream derIn = new DerInputStream(bb); DerValue der = derIn.getDerValue(); EncTicketPart tktEncPart = new EncTicketPart(der.toByteArray()); - if (!tktEncPart.flags.get(Krb5.TKT_OPTS_FORWARDABLE)) { - //throw new KrbException(Krb5.KDC_ERR_BADOPTION); + if (!tktEncPart.flags.get(Krb5.TKT_OPTS_FORWARDABLE) + && options.get(Option.S4U2SELF_ALLOW_NOT_FORWARDABLE) != Boolean.TRUE) { + throw new KrbException(Krb5.KDC_ERR_BADOPTION); } PrincipalName client = tktEncPart.cname; - System.out.println(realm + "> and an additional ticket of " + log("and an additional ticket of " + client + " to " + second.sname); if (map.containsKey(cname.toString())) { if (map.get(cname.toString()).contains(service.toString())) { - System.out.println(realm + "> S4U2proxy OK"); + log("S4U2proxy OK"); } else { throw new KrbException(Krb5.KDC_ERR_BADOPTION); } @@ -1066,7 +1096,7 @@ public class KDC { Realm.getDefault()); } try { - System.out.println(realm + "> " + asReq.reqBody.cname + + log(asReq.reqBody.cname + " sends AS-REQ for " + service + ", " + asReq.reqBody.kdcOptions); @@ -1601,6 +1631,10 @@ public class KDC { return udpConsumerReady && tcpConsumerReady && dispatcherReady; } + void log(String s) { + System.out.println(realm + ":" + port + "> " + s); + } + public void terminate() { if (nativeKdc != null) { System.out.println("Killing kdc..."); diff --git a/test/jdk/sun/security/krb5/auto/S4U2selfNotF.java b/test/jdk/sun/security/krb5/auto/S4U2selfNotF.java new file mode 100644 index 0000000000000000000000000000000000000000..44cf1dd5eddb7f2e9ee2752aebf3c51b940c600a --- /dev/null +++ b/test/jdk/sun/security/krb5/auto/S4U2selfNotF.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8272162 + * @summary S4U2Self ticket without forwardable flag + * @library /test/lib + * @compile -XDignore.symbol.file S4U2selfNotF.java + * @run main jdk.test.lib.FileInstaller TestHosts TestHosts + * @run main/othervm -Djdk.net.hosts.file=TestHosts + * -Djdk.security.krb5.s4u2proxy.acceptNonForwardableServiceTicket=true + * S4U2selfNotF + */ + +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.Map; + +import jdk.test.lib.Asserts; +import sun.security.jgss.GSSUtil; +import sun.security.krb5.Config; + +public class S4U2selfNotF { + + public static void main(String[] args) throws Exception { + + // Create 2 KDCs that has almost the same settings + OneKDC[] kdcs = new OneKDC[2]; + boolean[] touched = new boolean[2]; + for (int i = 0; i < 2; i++) { + final int pos = i; + kdcs[i] = new OneKDC(null) { + protected byte[] processTgsReq(byte[] in) throws Exception { + touched[pos] = true; + return super.processTgsReq(in); + } + }; + kdcs[i].setOption(KDC.Option.ALLOW_S4U2SELF, + List.of(OneKDC.USER + "@" + OneKDC.REALM)); + kdcs[i].setOption(KDC.Option.ALLOW_S4U2PROXY, Map.of( + OneKDC.USER + "@" + OneKDC.REALM, + List.of(OneKDC.BACKEND + "@" + OneKDC.REALM))); + } + kdcs[0].writeJAASConf(); + + // except that the 1st issues a non-forwardable S4U2self + // ticket and only the 2nd accepts it + kdcs[0].setOption(KDC.Option.S4U2SELF_NOT_FORWARDABLE, true); + kdcs[1].setOption(KDC.Option.S4U2SELF_ALLOW_NOT_FORWARDABLE, true); + + Files.write(Path.of(OneKDC.KRB5_CONF), String.format(""" + [libdefaults] + default_realm = RABBIT.HOLE + forwardable = true + default_keytab_name = localkdc.ktab + + [realms] + RABBIT.HOLE = { + kdc = kdc.rabbit.hole:%d kdc.rabbit.hole:%d + } + """, kdcs[0].getPort(), kdcs[1].getPort()) + .getBytes(StandardCharsets.UTF_8)); + Config.refresh(); + + Context c = Context.fromJAAS("client"); + c = c.impersonate(OneKDC.USER2); + c.startAsClient(OneKDC.BACKEND, GSSUtil.GSS_KRB5_MECH_OID); + c.take(new byte[0]); + + Asserts.assertTrue(touched[0]); // get S4U2self from 1st one + Asserts.assertTrue(touched[1]); // get S4U2proxy from 2nd one + } +} diff --git a/test/jdk/sun/security/pkcs11/Signature/LargeDSAKey.java b/test/jdk/sun/security/pkcs11/Signature/LargeDSAKey.java new file mode 100644 index 0000000000000000000000000000000000000000..a45a5ca47f544fefe11de334e9dede5dd2575c96 --- /dev/null +++ b/test/jdk/sun/security/pkcs11/Signature/LargeDSAKey.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2021, Red Hat, Inc. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.security.AlgorithmParameterGenerator; +import java.security.AlgorithmParameters; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.PrivateKey; +import java.security.Provider; +import java.security.PublicKey; +import java.security.SecureRandom; +import java.security.Signature; +import java.security.spec.DSAGenParameterSpec; +import java.security.spec.DSAParameterSpec; + +/* + * @test + * @bug 8271566 + * @library /test/lib .. + * @modules jdk.crypto.cryptoki + * @run main/othervm/timeout=30 LargeDSAKey + */ + +public final class LargeDSAKey extends PKCS11Test { + + private static final boolean enableDebug = false; + + private static final String knownText = + "Known text known text known text"; + + @Override + public void main(Provider p) throws Exception { + KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA", p); + AlgorithmParameterGenerator dsaParGen = + AlgorithmParameterGenerator.getInstance("DSA"); + DSAGenParameterSpec dsaParGenSpec = + new DSAGenParameterSpec(2048, 256); + dsaParGen.init(dsaParGenSpec, new SecureRandom()); + AlgorithmParameters params = dsaParGen.generateParameters(); + DSAParameterSpec dsaParams = + params.getParameterSpec(DSAParameterSpec.class); + kpg.initialize(dsaParams); + KeyPair kp = kpg.generateKeyPair(); + doTestSignature(kp, p); + } + + private static void doTestSignature(KeyPair kp, Provider p) + throws Exception { + byte[] knownTextSig = null; + Signature s = Signature.getInstance("SHA1withDSA", p); + PrivateKey privKey = kp.getPrivate(); + PublicKey pubKey = kp.getPublic(); + if (enableDebug) { + System.out.println("Signature algorithm: " + s.getAlgorithm()); + System.out.println("Signature Provider: " + s.getProvider()); + System.out.println("Private key for signature: " + privKey); + System.out.println("Public key for signature: " + pubKey); + } + s.initSign(privKey); + s.update(knownText.getBytes()); + knownTextSig = s.sign(); + s.initVerify(pubKey); + s.update(knownText.getBytes()); + if (s.verify(knownTextSig) == false) { + throw new Exception("Could not verify signature"); + } + if (enableDebug) { + System.out.println("Signature verified"); + } + } + + public static void main(String[] args) throws Throwable { + main(new LargeDSAKey()); + System.out.println("TEST PASS - OK"); + } + +} diff --git a/test/jdk/sun/security/pkcs12/EmptyPassword.java b/test/jdk/sun/security/pkcs12/EmptyPassword.java index 1f5e7ad457e84ac26cbb72b0f258cfa9eb8f943b..5e78003a4850f238bd9dfa4ed7c419be5bdcc1a9 100644 --- a/test/jdk/sun/security/pkcs12/EmptyPassword.java +++ b/test/jdk/sun/security/pkcs12/EmptyPassword.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,11 +23,11 @@ /* * @test - * @bug 8202299 + * @bug 8202299 8231107 * @modules java.base/sun.security.tools.keytool * java.base/sun.security.x509 * @library /test/lib - * @summary Java Keystore fails to load PKCS12/PFX certificates created in WindowsServer2016 + * @summary Testing empty (any of null, "", "\0") password behaviors */ import jdk.test.lib.Asserts; @@ -38,6 +38,7 @@ import java.io.File; import java.io.FileOutputStream; import java.security.KeyStore; import java.security.cert.Certificate; +import java.util.Arrays; public class EmptyPassword { @@ -52,13 +53,39 @@ public class EmptyPassword { new Certificate[] { gen.getSelfCertificate(new X500Name("CN=Me"), 100) }); - try (FileOutputStream fos = new FileOutputStream("p12")) { - ks.store(fos, new char[1]); - } + + // 8202299: interop between new char[0] and new char[1] + store(ks, "p12", new char[1]); // It can be loaded with password "". ks = KeyStore.getInstance(new File("p12"), new char[0]); Asserts.assertTrue(ks.getKey("a", new char[0]) != null); Asserts.assertTrue(ks.getCertificate("a") != null); + + ks = KeyStore.getInstance(new File("p12"), new char[1]); + Asserts.assertTrue(ks.getKey("a", new char[1]) != null); + Asserts.assertTrue(ks.getCertificate("a") != null); + + // 8231107: Store with null password makes it password-less + store(ks, "p00", null); + + // Can read cert and key with any password + for (char[] pass: new char[][] { + new char[0], // password actually used before 8202299 + new char[1], // the interoperability before 8202299 + null, // password-less after 8202299 + "whatever".toCharArray() + }) { + System.out.println("with password " + Arrays.toString(pass)); + ks = KeyStore.getInstance(new File("p00"), pass); + Asserts.assertTrue(ks.getKey("a", new char[1]) != null); + Asserts.assertTrue(ks.getCertificate("a") != null); + } + } + + static void store(KeyStore ks, String file, char[] pass) throws Exception { + try (FileOutputStream fos = new FileOutputStream(file)) { + ks.store(fos, pass); + } } } diff --git a/test/jdk/sun/security/pkcs12/GetAttributes.java b/test/jdk/sun/security/pkcs12/GetAttributes.java new file mode 100644 index 0000000000000000000000000000000000000000..6a4f37c97872086a84b9b78503ea13a742c717dc --- /dev/null +++ b/test/jdk/sun/security/pkcs12/GetAttributes.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8225181 + * @summary KeyStore should have a getAttributes method + * @library /test/lib + * @modules java.base/sun.security.tools.keytool + * java.base/sun.security.x509 + */ + +import jdk.test.lib.Asserts; +import sun.security.tools.keytool.CertAndKeyGen; +import sun.security.x509.X500Name; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.security.KeyStore; +import java.security.cert.Certificate; + +public class GetAttributes { + + static char[] pass = "changeit".toCharArray(); + + public static void main(String[] args) throws Exception { + + // Create a keystore with one private key entry and one cert entry + CertAndKeyGen cag = new CertAndKeyGen("EC", "SHA256withECDSA"); + KeyStore ks = KeyStore.getInstance("pkcs12"); + ks.load(null, null); + cag.generate("secp256r1"); + ks.setKeyEntry("a", cag.getPrivateKey(), pass, new Certificate[] { + cag.getSelfCertificate(new X500Name("CN=a"), 1000)} ); + cag.generate("secp256r1"); + ks.setCertificateEntry("b", + cag.getSelfCertificate(new X500Name("CN=b"), 1000)); + + // Test + check(ks); + + // Test newly loaded + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ks.store(bos, pass); + KeyStore ks2 = KeyStore.getInstance("pkcs12"); + ks2.load(new ByteArrayInputStream(bos.toByteArray()), pass); + check(ks2); + } + + static void check(KeyStore ks) throws Exception { + var entry = ks.getEntry("a", new KeyStore.PasswordProtection(pass)); + Asserts.assertEQ(ks.getAttributes("a"), entry.getAttributes()); + entry = ks.getEntry("b", null); + Asserts.assertEQ(ks.getAttributes("b"), entry.getAttributes()); + } +} diff --git a/test/jdk/sun/security/pkcs12/KeytoolOpensslInteropTest.java b/test/jdk/sun/security/pkcs12/KeytoolOpensslInteropTest.java index da655c90a49ac07cb582548da42f864ce56972ed..7fcbd95ca7d5bd5443cc38c5e4d1be52641a2c36 100644 --- a/test/jdk/sun/security/pkcs12/KeytoolOpensslInteropTest.java +++ b/test/jdk/sun/security/pkcs12/KeytoolOpensslInteropTest.java @@ -462,7 +462,7 @@ public class KeytoolOpensslInteropTest { "pkcs12", "-in", "ksnormal", "-passin", "pass:changeit", "-info", "-nokeys", "-nocerts"); output1.shouldHaveExitValue(0) - .shouldContain("MAC: sha256, Iteration 10000") + .shouldContain("MAC:").shouldContain("sha256").shouldContain("Iteration 10000") .shouldContain("Shrouded Keybag: PBES2, PBKDF2, AES-256-CBC," + " Iteration 10000, PRF hmacWithSHA256") .shouldContain("PKCS7 Encrypted data: PBES2, PBKDF2, AES-256-CBC," @@ -505,7 +505,7 @@ public class KeytoolOpensslInteropTest { "ksnewic", "-passin", "pass:changeit", "-info", "-nokeys", "-nocerts"); output1.shouldHaveExitValue(0) - .shouldContain("MAC: sha256, Iteration 5555") + .shouldContain("MAC:").shouldContain("sha256").shouldContain("Iteration 5555") .shouldContain("Shrouded Keybag: PBES2, PBKDF2, AES-256-CBC," + " Iteration 7777, PRF hmacWithSHA256") .shouldContain("Shrouded Keybag: pbeWithSHA1And128BitRC4," diff --git a/test/jdk/sun/tools/jhsdb/JShellHeapDumpTest.java b/test/jdk/sun/tools/jhsdb/JShellHeapDumpTest.java index 6c16ec2d29369caf9c5de71afaba1b1b2c96c3dd..5dee1b863dc70fc2ddad99e3694f17ad6667b0d8 100644 --- a/test/jdk/sun/tools/jhsdb/JShellHeapDumpTest.java +++ b/test/jdk/sun/tools/jhsdb/JShellHeapDumpTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -97,21 +97,33 @@ public class JShellHeapDumpTest { launch(expectedMessage, Arrays.asList(toolArgs)); } - public static void printStackTraces(String file) throws IOException { + /* Returns false if the attempt should be retried. */ + public static boolean printStackTraces(String file, boolean allowRetry) throws IOException { try { String output = HprofReader.getStack(file, 0); // We only require JShellToolProvider to be in the output if we did the // short sleep. If we did not, the java process may not have executed far // enough along to even start the main thread. if (doSleep && !output.contains("JShellToolProvider")) { - throw new RuntimeException("'JShellToolProvider' missing from stdout/stderr"); + // This check will very rarely fail due to not be able to get the stack trace + // of the main thread do to it actively executing. See JDK-8269556. We retry once + // if that happens. This failure is so rare that this should be enough to make it + // extremely unlikely that we ever see this test fail again for this reason. + if (!allowRetry) { + throw new RuntimeException("'JShellToolProvider' missing from stdout/stderr"); + } else { + System.out.println("'JShellToolProvider' missing. Allow one retry."); + return true; // Allow one retry + } } } catch (Exception ex) { throw new RuntimeException("Test ERROR " + ex, ex); } + return false; } - public static void testHeapDump() throws IOException { + /* Returns false if the attempt should be retried. */ + public static boolean testHeapDump(boolean allowRetry) throws IOException { File hprofFile = new File("jhsdb.jmap.heap." + System.currentTimeMillis() + ".hprof"); if (hprofFile.exists()) { @@ -124,10 +136,12 @@ public class JShellHeapDumpTest { assertTrue(hprofFile.exists() && hprofFile.isFile(), "Could not create dump file " + hprofFile.getAbsolutePath()); - printStackTraces(hprofFile.getAbsolutePath()); + boolean retry = printStackTraces(hprofFile.getAbsolutePath(), allowRetry); System.out.println("hprof file size: " + hprofFile.length()); hprofFile.delete(); + + return retry; } public static void launchJshell() throws IOException { @@ -149,7 +163,7 @@ public class JShellHeapDumpTest { // Give jshell a chance to fully start up. This makes SA more stable for the jmap dump. try { if (doSleep) { - Thread.sleep(2000); + Thread.sleep(4000); } } catch (Exception e) { } @@ -166,7 +180,12 @@ public class JShellHeapDumpTest { } else if (args.length != 0) { throw new RuntimeException("Too many args: " + args.length); } - testHeapDump(); + + boolean retry = testHeapDump(true); + // In case of rare failure to find 'JShellToolProvider' in the output, allow one retry. + if (retry) { + testHeapDump(false); + } // The test throws RuntimeException on error. // IOException is thrown if Jshell can't start because of some bad diff --git a/test/jdk/sun/util/resources/TimeZone/ChineseTimeZoneNameTest.java b/test/jdk/sun/util/resources/TimeZone/ChineseTimeZoneNameTest.java new file mode 100644 index 0000000000000000000000000000000000000000..c752ec4d63c2591263a2937f1b0d14fed2283553 --- /dev/null +++ b/test/jdk/sun/util/resources/TimeZone/ChineseTimeZoneNameTest.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + /* + * @test + * @bug 8275721 + * @modules jdk.localedata + * @summary Checks Chinese time zone names for `UTC` using CLDR are consistent + * @run testng/othervm -Djava.locale.providers=CLDR,COMPAT ChineseTimeZoneNameTest + * @run testng/othervm -Djava.locale.providers=CLDR ChineseTimeZoneNameTest + */ + +import java.time.Instant; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Locale; + +import static org.testng.Assert.assertEquals; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +@Test +public class ChineseTimeZoneNameTest { + + private static final Locale SIMPLIFIED_CHINESE = Locale.forLanguageTag("zh-Hans"); + private static final Locale TRADITIONAL_CHINESE = Locale.forLanguageTag("zh-Hant"); + private static final ZonedDateTime EPOCH_UTC = + ZonedDateTime.ofInstant(Instant.ofEpochSecond (0), ZoneId.of ("UTC")); + + @DataProvider(name="locales") + Object[][] data() { + return new Object[][] { + {Locale.CHINESE, SIMPLIFIED_CHINESE}, + {Locale.SIMPLIFIED_CHINESE, SIMPLIFIED_CHINESE}, + {Locale.forLanguageTag("zh-SG"), SIMPLIFIED_CHINESE}, + {Locale.forLanguageTag("zh-Hans-TW"), SIMPLIFIED_CHINESE}, + {Locale.forLanguageTag("zh-HK"), TRADITIONAL_CHINESE}, + {Locale.forLanguageTag("zh-MO"), TRADITIONAL_CHINESE}, + {Locale.TRADITIONAL_CHINESE, TRADITIONAL_CHINESE}, + {Locale.forLanguageTag("zh-Hant-CN"), TRADITIONAL_CHINESE}, + }; + } + + @Test(dataProvider="locales") + public void test_ChineseTimeZoneNames(Locale testLoc, Locale resourceLoc) { + assertEquals(DateTimeFormatter.ofPattern("z", testLoc).format(EPOCH_UTC), + DateTimeFormatter.ofPattern("z", resourceLoc).format(EPOCH_UTC)); + assertEquals(DateTimeFormatter.ofPattern("zzzz", testLoc).format(EPOCH_UTC), + DateTimeFormatter.ofPattern("zzzz", resourceLoc).format(EPOCH_UTC)); + } +} diff --git a/test/jdk/tools/jar/JarEntryTime.java b/test/jdk/tools/jar/JarEntryTime.java index 80fd65fba5c572cd9a2626f891f8782f9c377a7c..4d84547d07478c0f76daaa659eeb906b36b26e8e 100644 --- a/test/jdk/tools/jar/JarEntryTime.java +++ b/test/jdk/tools/jar/JarEntryTime.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /** * @test - * @bug 4225317 6969651 + * @bug 4225317 6969651 8277422 * @modules jdk.jartool * @summary Check extracted files have date as per those in the .jar file */ @@ -31,6 +31,7 @@ import java.io.File; import java.io.PrintWriter; import java.nio.file.attribute.FileTime; +import java.time.ZoneId; import java.util.Date; import java.util.TimeZone; import java.util.spi.ToolProvider; @@ -93,6 +94,14 @@ public class JarEntryTime { jarFile.delete(); testFile.delete(); + var date = new Date(); + var defZone = ZoneId.systemDefault(); + if (defZone.getRules().getTransition( + date.toInstant().atZone(defZone).toLocalDateTime()) != null) { + System.out.println("At the offset transition. JarEntryTime test skipped."); + return; + } + /* Create a directory structure * outer/ * inner/ diff --git a/test/jdk/tools/jar/ReproducibleJar.java b/test/jdk/tools/jar/ReproducibleJar.java new file mode 100644 index 0000000000000000000000000000000000000000..5fb46def40d94914d3a0879e3a3bc7e1b067d48e --- /dev/null +++ b/test/jdk/tools/jar/ReproducibleJar.java @@ -0,0 +1,290 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8276766 + * @summary Test jar --date source date of entries and that jars are + * reproducible + * @modules jdk.jartool + * @run testng/othervm ReproducibleJar + */ + +import org.testng.Assert; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; +import org.testng.annotations.DataProvider; + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.nio.file.Files; +import java.nio.file.attribute.FileTime; +import java.util.Date; +import java.util.TimeZone; +import java.util.spi.ToolProvider; +import java.time.LocalDateTime; +import java.time.ZonedDateTime; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; +import java.time.Instant; +import java.util.concurrent.TimeUnit; + +public class ReproducibleJar { + private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar") + .orElseThrow(() -> + new RuntimeException("jar tool not found") + ); + + // ZipEntry's mod date has 2 seconds precision: give extra time to + // allow for e.g. rounding/truncation and networked/samba drives. + private static final long PRECISION = 10000L; + + private static final TimeZone TZ = TimeZone.getDefault(); + private static final boolean DST = TZ.inDaylightTime(new Date()); + private static final String UNIX_2038_ROLLOVER_TIME = "2038-01-19T03:14:07Z"; + private static final Instant UNIX_2038_ROLLOVER = Instant.parse(UNIX_2038_ROLLOVER_TIME); + private static final File DIR_OUTER = new File("outer"); + private static final File DIR_INNER = new File(DIR_OUTER, "inner"); + private static final File FILE_INNER = new File(DIR_INNER, "foo.txt"); + private static final File JAR_FILE_SOURCE_DATE1 = new File("JarEntryTimeSourceDate1.jar"); + private static final File JAR_FILE_SOURCE_DATE2 = new File("JarEntryTimeSourceDate2.jar"); + + // Valid --date values for jar + @DataProvider + private Object[][] validSourceDates() { + return new Object[][]{ + {"1980-01-01T00:00:02+00:00"}, + {"1986-06-24T01:02:03+00:00"}, + {"2022-03-15T00:00:00+00:00"}, + {"2022-03-15T00:00:00+06:00"}, + {"2021-12-25T09:30:00-08:00[America/Los_Angeles]"}, + {"2021-12-31T23:59:59Z"}, + {"2024-06-08T14:24Z"}, + {"2026-09-24T16:26-05:00"}, + {"2038-11-26T06:06:06+00:00"}, + {"2098-02-18T00:00:00-08:00"}, + {"2099-12-31T23:59:59+00:00"} + }; + } + + // Invalid --date values for jar + @DataProvider + private Object[][] invalidSourceDates() { + return new Object[][]{ + {"1976-06-24T01:02:03+00:00"}, + {"1980-01-01T00:00:01+00:00"}, + {"2100-01-01T00:00:00+00:00"}, + {"2138-02-18T00:00:00-11:00"}, + {"2006-04-06T12:38:00"}, + {"2012-08-24T16"} + }; + } + + @BeforeMethod + public void runBefore() throws IOException { + runAfter(); + createOuterInnerDirs(); + } + + @AfterMethod + public void runAfter() { + cleanup(DIR_INNER); + cleanup(DIR_OUTER); + JAR_FILE_SOURCE_DATE1.delete(); + JAR_FILE_SOURCE_DATE2.delete(); + TimeZone.setDefault(TZ); + } + + /** + * Test jar tool with various valid --date <timestamps> + */ + @Test(dataProvider = "validSourceDates") + public void testValidSourceDate(String sourceDate) { + if (isInTransition()) return; + + // Test --date source date + Assert.assertEquals(JAR_TOOL.run(System.out, System.err, + "--create", + "--file", JAR_FILE_SOURCE_DATE1.getName(), + "--date", sourceDate, + DIR_OUTER.getName()), 0); + Assert.assertTrue(JAR_FILE_SOURCE_DATE1.exists()); + + // Extract JAR_FILE_SOURCE_DATE1 and check last modified values + Assert.assertEquals(JAR_TOOL.run(System.out, System.err, + "--extract", + "--file", JAR_FILE_SOURCE_DATE1.getName()), 0); + Assert.assertTrue(DIR_OUTER.exists()); + Assert.assertTrue(DIR_INNER.exists()); + Assert.assertTrue(FILE_INNER.exists()); + LocalDateTime expectedLdt = ZonedDateTime.parse(sourceDate, + DateTimeFormatter.ISO_DATE_TIME) + .withZoneSameInstant(ZoneOffset.UTC) + .toLocalDateTime(); + System.out.format("Checking jar entries local date time for --date %s, is %s%n", + sourceDate, expectedLdt); + long sourceDateEpochMillis = TimeUnit.MILLISECONDS.convert( + expectedLdt.toEpochSecond(ZoneId.systemDefault().getRules() + .getOffset(expectedLdt)), TimeUnit.SECONDS); + checkFileTime(DIR_OUTER.lastModified(), sourceDateEpochMillis); + checkFileTime(DIR_INNER.lastModified(), sourceDateEpochMillis); + checkFileTime(FILE_INNER.lastModified(), sourceDateEpochMillis); + } + + /** + * Test jar tool with various invalid --date <timestamps> + */ + @Test(dataProvider = "invalidSourceDates") + public void testInvalidSourceDate(String sourceDate) { + // Negative Tests --date out of range or wrong format source date + Assert.assertNotEquals(JAR_TOOL.run(System.out, System.err, + "--create", + "--file", JAR_FILE_SOURCE_DATE1.getName(), + "--date", sourceDate, + DIR_OUTER.getName()), 0); + } + + /** + * Test jar produces deterministic reproducible output + */ + @Test(dataProvider = "validSourceDates") + public void testJarsReproducible(String sourceDate) throws IOException { + // Test jars are reproducible across timezones + TimeZone tzAsia = TimeZone.getTimeZone("Asia/Shanghai"); + TimeZone tzLA = TimeZone.getTimeZone("America/Los_Angeles"); + TimeZone.setDefault(tzAsia); + Assert.assertEquals(JAR_TOOL.run(System.out, System.err, + "--create", + "--file", JAR_FILE_SOURCE_DATE1.getName(), + "--date", sourceDate, + DIR_OUTER.getName()), 0); + Assert.assertTrue(JAR_FILE_SOURCE_DATE1.exists()); + + try { + // Sleep 5 seconds to ensure jar timestamps might be different if they could be + Thread.sleep(5000); + } catch (InterruptedException ex) { + } + + TimeZone.setDefault(tzLA); + Assert.assertEquals(JAR_TOOL.run(System.out, System.err, + "--create", + "--file", JAR_FILE_SOURCE_DATE2.getName(), + "--date", sourceDate, + DIR_OUTER.getName()), 0); + Assert.assertTrue(JAR_FILE_SOURCE_DATE2.exists()); + + // Check jars are identical + Assert.assertEquals(Files.readAllBytes(JAR_FILE_SOURCE_DATE1.toPath()), + Files.readAllBytes(JAR_FILE_SOURCE_DATE2.toPath())); + } + + /** + * Create the standard directory structure used by the test: + * outer/ + * inner/ + * foo.txt + */ + static void createOuterInnerDirs() throws IOException { + Assert.assertTrue(DIR_OUTER.mkdir()); + Assert.assertTrue(DIR_INNER.mkdir()); + try (PrintWriter pw = new PrintWriter(FILE_INNER)) { + pw.println("hello, world"); + } + Assert.assertTrue(DIR_OUTER.exists()); + Assert.assertTrue(DIR_INNER.exists()); + Assert.assertTrue(FILE_INNER.exists()); + } + + /** + * Check the extracted and original millis since Epoch file times are + * within the zip precision time period. + */ + static void checkFileTime(long now, long original) { + if (isTimeSettingChanged()) { + return; + } + + if (Math.abs(now - original) > PRECISION) { + // If original time is after UNIX 2038 32bit rollover + // and the now time is exactly the rollover time, then assume + // running on a file system that only supports to 2038 (e.g.XFS) and pass test + if (FileTime.fromMillis(original).toInstant().isAfter(UNIX_2038_ROLLOVER) && + FileTime.fromMillis(now).toInstant().equals(UNIX_2038_ROLLOVER)) { + System.out.println("Checking file time after Unix 2038 rollover," + + " and extracted file time is " + UNIX_2038_ROLLOVER_TIME + ", " + + " Assuming restricted file system, pass file time check."); + } else { + throw new AssertionError("checkFileTime failed," + + " extracted to " + FileTime.fromMillis(now) + + ", expected to be close to " + FileTime.fromMillis(original)); + } + } + } + + /** + * Has the timezone or DST changed during the test? + */ + private static boolean isTimeSettingChanged() { + TimeZone currentTZ = TimeZone.getDefault(); + boolean currentDST = currentTZ.inDaylightTime(new Date()); + if (!currentTZ.equals(TZ) || currentDST != DST) { + System.out.println("Timezone or DST has changed during " + + "ReproducibleJar testcase execution. Test skipped"); + return true; + } else { + return false; + } + } + + /** + * Is the Zone currently within the transition change period? + */ + private static boolean isInTransition() { + var inTransition = false; + var date = new Date(); + var defZone = ZoneId.systemDefault(); + if (defZone.getRules().getTransition( + date.toInstant().atZone(defZone).toLocalDateTime()) != null) { + System.out.println("ReproducibleJar testcase being run during Zone offset transition. Test skipped."); + inTransition = true; + } + return inTransition; + } + + /** + * Remove the directory and its contents + */ + static void cleanup(File dir) { + File[] x = dir.listFiles(); + if (x != null) { + for (File f : x) { + f.delete(); + } + } + dir.delete(); + } +} diff --git a/test/jdk/tools/jar/modularJar/Basic.java b/test/jdk/tools/jar/modularJar/Basic.java index f6f95b632079797dcdd0d34e07b096c48ac7e584..26e9b835a496d1d38a50bfcf54ab4fce17f00c7b 100644 --- a/test/jdk/tools/jar/modularJar/Basic.java +++ b/test/jdk/tools/jar/modularJar/Basic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1093,9 +1093,6 @@ public class Basic { { List<String> commands = new ArrayList<>(); - if (!TOOL_VM_OPTIONS.isEmpty()) { - commands.addAll(Arrays.asList(TOOL_VM_OPTIONS.split("\\s+", -1))); - } commands.add("-d"); commands.add(dest.toString()); if (dest.toString().contains("bar")) { diff --git a/test/jdk/tools/jar/modularJar/JarToolModuleDescriptorReproducibilityTest.java b/test/jdk/tools/jar/modularJar/JarToolModuleDescriptorReproducibilityTest.java new file mode 100644 index 0000000000000000000000000000000000000000..376b261799854bfce96686d63add93db790617a3 --- /dev/null +++ b/test/jdk/tools/jar/modularJar/JarToolModuleDescriptorReproducibilityTest.java @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.lang.module.ModuleDescriptor; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.jar.JarEntry; +import java.util.jar.JarInputStream; +import java.util.spi.ToolProvider; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertNotNull; + +/** + * @test + * @bug 8258117 + * @summary Tests that the content generated for module-info.class, using the jar command, is reproducible + * @run testng JarToolModuleDescriptorReproducibilityTest + */ +public class JarToolModuleDescriptorReproducibilityTest { + + private static final String MODULE_NAME = "foo"; + private static final String MODULE_VERSION = "1.2.3"; + private static final String UPDATED_MODULE_VERSION = "1.2.4"; + private static final String MAIN_CLASS = "jdk.test.foo.Foo"; + private static final Path MODULE_CLASSES_DIR = Path.of("8258117-module-classes", MODULE_NAME).toAbsolutePath(); + + private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar") + .orElseThrow(() + -> new RuntimeException("jar tool not found") + ); + private static final ToolProvider JAVAC_TOOL = ToolProvider.findFirst("javac") + .orElseThrow(() + -> new RuntimeException("javac tool not found") + ); + + + @BeforeClass + public static void setup() throws Exception { + compileModuleClasses(); + } + + /** + * Launches a "jar --create" command multiple times with a module-info.class. The module-info.class + * is internally updated by the jar tool to add additional data. Expects that each such generated + * jar has the exact same bytes. + */ + @Test + public void testJarCreate() throws Exception { + List<Path> jarFiles = new ArrayList<>(); + for (int i = 0; i < 3; i++) { + Path targetJar = Files.createTempFile(Path.of("."), "8258117-jar-create", ".jar"); + jarFiles.add(targetJar); + if (i > 0) { + // the timestamp that gets embedded in (Zip/Jar)Entry gets narrowed + // down to SECONDS unit. So we make sure that there's at least a second + // gap between the jar file creations, to be sure that the jar file + // was indeed generated at "different times" + Thread.sleep(1000); + } + // create a modular jar + runJarCommand("--create", + "--file=" + targetJar, + "--main-class=" + MAIN_CLASS, + "--module-version=" + MODULE_VERSION, + "--no-manifest", + "-C", MODULE_CLASSES_DIR.toString(), "."); + // verify the module descriptor in the jar + assertExpectedModuleInfo(targetJar, MODULE_VERSION); + } + assertAllFileContentsAreSame(jarFiles); + } + + /** + * Launches a "jar --update" process multiple times to update the module-info.class + * descriptor with the same content and then expects that the modular jar created by + * each of these processes has the exact same bytes. + */ + @Test + public void testJarUpdate() throws Exception { + List<Path> jarFiles = new ArrayList<>(); + for (int i = 0; i < 3; i++) { + Path targetJar = Files.createTempFile(Path.of("."), "8258117-jar-update", ".jar"); + jarFiles.add(targetJar); + if (i > 0) { + // the timestamp that gets embedded in (Zip/Jar)Entry gets narrowed + // down to SECONDS unit. So we make sure that there's at least a second + // gap between the jar file creations, to be sure that the jar file + // was indeed generated at "different times" + Thread.sleep(1000); + } + // first create the modular jar + runJarCommand("--create", + "--file=" + targetJar, + "--module-version=" + MODULE_VERSION, + "--no-manifest", + "-C", MODULE_CLASSES_DIR.toString(), "."); + assertExpectedModuleInfo(targetJar, MODULE_VERSION); + // now update the same modular jar + runJarCommand("--update", + "--file=" + targetJar, + "--module-version=" + UPDATED_MODULE_VERSION, + "--no-manifest", + "-C", MODULE_CLASSES_DIR.toString(), "module-info.class"); + // verify the module descriptor in the jar + assertExpectedModuleInfo(targetJar, UPDATED_MODULE_VERSION); + } + assertAllFileContentsAreSame(jarFiles); + } + + // compiles using javac tool the classes used in the test module + private static void compileModuleClasses() throws Exception { + Path sourcePath = Path.of(System.getProperty("test.src", "."), + "src", MODULE_NAME); + List<String> sourceFiles = new ArrayList<>(); + Files.walkFileTree(sourcePath, new SimpleFileVisitor<>() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + if (file.toString().endsWith(".java")) { + sourceFiles.add(file.toString()); + } + return FileVisitResult.CONTINUE; + } + }); + Path classesDir = Files.createDirectories(MODULE_CLASSES_DIR); + List<String> javacArgs = new ArrayList<>(); + javacArgs.add("-d"); + javacArgs.add(classesDir.toString()); + sourceFiles.forEach((f) -> javacArgs.add(f)); + System.out.println("Launching javac command with args: " + javacArgs); + StringWriter sw = new StringWriter(); + try (PrintWriter pw = new PrintWriter(sw)) { + int exitCode = JAVAC_TOOL.run(pw, pw, javacArgs.toArray(new String[0])); + assertEquals(exitCode, 0, "Module compilation failed: " + sw.toString()); + } + System.out.println("Module classes successfully compiled to directory " + classesDir); + } + + // runs the "jar" command passing it the "jarArgs" and verifying that the command + // execution didn't fail + private static void runJarCommand(String... jarArgs) { + StringWriter sw = new StringWriter(); + System.out.println("Launching jar command with args: " + Arrays.toString(jarArgs)); + try (PrintWriter pw = new PrintWriter(sw)) { + int exitCode = JAR_TOOL.run(pw, pw, jarArgs); + assertEquals(exitCode, 0, "jar command execution failed: " + sw.toString()); + } + } + + // verifies the byte equality of the contents in each of the files + private static void assertAllFileContentsAreSame(List<Path> files) throws Exception { + Path firstFile = files.get(0); + for (int i = 1; i < files.size(); i++) { + assertEquals(Files.mismatch(firstFile, files.get(i)), -1, + "Content in file " + files.get(i) + " isn't the same as in file " + firstFile); + } + } + + // verifies that a module-info.class is present in the jar and the module name and version are the expected + // ones + private static void assertExpectedModuleInfo(Path jar, String expectedModuleVersion) throws Exception { + try (JarInputStream jaris = new JarInputStream(Files.newInputStream(jar))) { + JarEntry moduleInfoEntry = null; + JarEntry entry = null; + while ((entry = jaris.getNextJarEntry()) != null) { + if (entry.getName().equals("module-info.class")) { + moduleInfoEntry = entry; + break; + } + } + assertNotNull(moduleInfoEntry, "module-info.class is missing from jar " + jar); + + ModuleDescriptor md = ModuleDescriptor.read(jaris); + assertEquals(md.name(), MODULE_NAME, "Unexpected module name"); + assertFalse(md.rawVersion().isEmpty(), "Module version missing from descriptor"); + + String actualVersion = md.rawVersion().get(); + assertEquals(actualVersion, expectedModuleVersion, "Unexpected module version"); + + System.out.println(moduleInfoEntry.getName() + " has a timestamp of " + + moduleInfoEntry.getTime() + " for version " + actualVersion); + } + } +} + diff --git a/test/jdk/tools/jar/multiRelease/MRTestBase.java b/test/jdk/tools/jar/multiRelease/MRTestBase.java index 8447b20b368be3d13be0b6dbba5ec7f49b8dcf55..abd5782fdcde204653576a6744b649eb73753c28 100644 --- a/test/jdk/tools/jar/multiRelease/MRTestBase.java +++ b/test/jdk/tools/jar/multiRelease/MRTestBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -108,7 +108,6 @@ public class MRTestBase { if (!opts.isEmpty()) { commands.addAll(Arrays.asList(opts.split(" +"))); } - commands.addAll(Utils.getForwardVmOptions()); commands.add("-d"); commands.add(dest.toString()); Stream.of(sourceFiles) diff --git a/test/jdk/tools/jimage/JImageNonAsciiNameTest.java b/test/jdk/tools/jimage/JImageNonAsciiNameTest.java new file mode 100644 index 0000000000000000000000000000000000000000..4d1e5ba94ad82532e4b4c2cf291bf26ffe48eb1a --- /dev/null +++ b/test/jdk/tools/jimage/JImageNonAsciiNameTest.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.nio.file.Path; +import jdk.internal.jimage.BasicImageReader; +import jdk.internal.jimage.ImageLocation; +import jdk.test.lib.compiler.InMemoryJavaCompiler; +import jdk.test.lib.util.JarBuilder; + +import tests.Helper; +import tests.JImageGenerator; +import tests.Result; + +/* + * @test + * @bug 8278185 + * @summary Test non-ASCII path in custom JRE + * @library ../lib + * /test/lib + * @modules java.base/jdk.internal.jimage + * jdk.jdeps/com.sun.tools.classfile + * jdk.jlink/jdk.tools.jimage + * @build tests.* + * @run main/othervm JImageNonAsciiNameTest + */ + +public class JImageNonAsciiNameTest { + private final static String moduleName = "A_module"; + private final static String packageName = "test.\u3042"; //non-ASCII + private final static String className = "A"; + private final static String fullName = packageName + "." + className; + private static Helper helper; + + public static void main(String[] args) throws Exception { + helper = Helper.newHelper(); + if (helper == null) { + System.err.println("Test not run"); + return; + } + + String source = + "package "+packageName+";" + + "public class "+className+" {" + + " public static void main(String[] args) {}" + + "}"; + String moduleInfo = "module " + moduleName + " {}"; + + // Using InMemory features to avoid generating non-ASCII name file + byte[] byteA = InMemoryJavaCompiler.compile(fullName, source); + byte[] byteModule = InMemoryJavaCompiler.compile( + "module-info", moduleInfo); + + Path jarDir = helper.getJarDir(); + JarBuilder jb = new JarBuilder( + jarDir.resolve(moduleName + ".jar").toString()); + jb.addEntry(fullName.replace(".","/") + ".class", byteA); + jb.addEntry("module-info.class", byteModule); + jb.build(); + + Path outDir = helper.createNewImageDir(moduleName); + + Result result = JImageGenerator.getJLinkTask() + .modulePath(helper.defaultModulePath()) + .output(outDir) + .addMods(moduleName) + .call(); + Path testImage = result.assertSuccess(); + + BasicImageReader bir = BasicImageReader.open( + testImage.resolve("lib").resolve("modules")); + ImageLocation loc = bir.findLocation(moduleName, + fullName.replace(".","/") + ".class"); + if (loc == null) { + throw new RuntimeException("Failed to find " + + fullName + " in module " +moduleName); + } + } +} diff --git a/test/jdk/tools/jmod/JmodTest.java b/test/jdk/tools/jmod/JmodTest.java index bfec68b748beb213766098842047d5aec8092401..78f1a89a759ccbd02bd4d3a089c6d4df86545b27 100644 --- a/test/jdk/tools/jmod/JmodTest.java +++ b/test/jdk/tools/jmod/JmodTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8142968 8166568 8166286 8170618 8168149 8240910 8276764 + * @bug 8142968 8166568 8166286 8170618 8168149 8240910 8276764 8276766 * @summary Basic test for jmod * @library /test/lib * @modules jdk.compiler @@ -183,13 +183,15 @@ public class JmodTest { @Test public void testList() throws IOException { String cp = EXPLODED_DIR.resolve("foo").resolve("classes").toString(); + Path jmod = MODS_DIR.resolve("foo.jmod"); + FileUtils.deleteFileIfExistsWithRetry(jmod); jmod("create", "--class-path", cp, - MODS_DIR.resolve("foo.jmod").toString()) + jmod.toString()) .assertSuccess(); jmod("list", - MODS_DIR.resolve("foo.jmod").toString()) + jmod.toString()) .assertSuccess() .resultChecker(r -> { // asserts dependent on the exact contents of foo @@ -211,6 +213,64 @@ public class JmodTest { }); } + @Test + public void testSourceDateReproducible() throws IOException { + String cp = EXPLODED_DIR.resolve("foo").resolve("classes").toString(); + Path jmod1 = MODS_DIR.resolve("foo1.jmod"); + Path jmod2 = MODS_DIR.resolve("foo2.jmod"); + Path jmod3 = MODS_DIR.resolve("foo3.jmod"); + FileUtils.deleteFileIfExistsWithRetry(jmod1); + FileUtils.deleteFileIfExistsWithRetry(jmod2); + FileUtils.deleteFileIfExistsWithRetry(jmod3); + + // Use source date of 15/03/2022 + String sourceDate = "2022-03-15T00:00:00+00:00"; + + jmod("create", + "--class-path", cp, + "--date", sourceDate, + jmod1.toString()) + .assertSuccess(); + + try { + // Sleep 5 seconds to ensure zip timestamps might be different if they could be + Thread.sleep(5000); + } catch(InterruptedException ex) {} + + jmod("create", + "--class-path", cp, + "--date", sourceDate, + jmod2.toString()) + .assertSuccess(); + + // Compare file byte content to see if they are identical + assertSameContent(jmod1, jmod2); + + // Use a date before 1980 and assert failure error + sourceDate = "1976-03-15T00:00:00+00:00"; + + jmod("create", + "--class-path", cp, + "--date", sourceDate, + jmod3.toString()) + .assertFailure() + .resultChecker(r -> { + assertContains(r.output, "is out of the valid range"); + }); + + // Use a date after 2099 and assert failure error + sourceDate = "2100-03-15T00:00:00+00:00"; + + jmod("create", + "--class-path", cp, + "--date", sourceDate, + jmod3.toString()) + .assertFailure() + .resultChecker(r -> { + assertContains(r.output, "is out of the valid range"); + }); + } + @Test public void testExtractCWD() throws IOException { Path cp = EXPLODED_DIR.resolve("foo").resolve("classes"); diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java index 3315de374c3888cd3f179bcecbc033c1527f6990..b68fe08bd1e7940b98e40066c6ffd6a9edc6e8e0 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java @@ -768,6 +768,11 @@ public final class JPackageCommand extends CommandArguments<JPackageCommand> { } private JPackageCommand adjustArgumentsBeforeExecution() { + if (!isWithToolProvider()) { + // if jpackage is launched as a process then set the jlink.debug system property + // to allow the jlink process to print exception stacktraces on any failure + addArgument("-J-Djlink.debug=true"); + } if (!hasArgument("--runtime-image") && !hasArgument("--app-image") && DEFAULT_RUNTIME_IMAGE != null && !ignoreDefaultRuntime) { addArguments("--runtime-image", DEFAULT_RUNTIME_IMAGE); } diff --git a/test/jdk/tools/jpackage/junit/jdk/jpackage/internal/OverridableResourceTest.java b/test/jdk/tools/jpackage/junit/jdk/jpackage/internal/OverridableResourceTest.java index 55a3c22dc9a83a759fd5e13099550abd41989e78..7b00a60acf06ff1cbf35b9ff2b4c92b251ca45e4 100644 --- a/test/jdk/tools/jpackage/junit/jdk/jpackage/internal/OverridableResourceTest.java +++ b/test/jdk/tools/jpackage/junit/jdk/jpackage/internal/OverridableResourceTest.java @@ -136,16 +136,16 @@ public class OverridableResourceTest { } private void testCustomtWithSubstitution(String defaultName) throws IOException { - final List<String> resourceData = List.of("A", "[BB]", "C", "Foo", - "GoodbyeHello"); + final List<String> resourceData = List.of("A", "[BB]", "C", "Foo", "Foo", + "GoodbyeHello", "_B"); final Path customFile = createCustomFile("foo", resourceData); final Map<String, String> substitutionData = new HashMap(Map.of("B", - "Bar", "Foo", "B")); + "Bar", "Foo", "B", "_B", "JJ")); substitutionData.put("Hello", null); final List<String> expectedResourceData = List.of("A", "[BarBar]", "C", - "B", "Goodbye"); + "Bar", "Bar", "Goodbye", "JJ"); final List<String> actualResourceData = convertToStringList(saveToFile( new OverridableResource(defaultName) diff --git a/test/jdk/tools/jpackage/macosx/SigningAppImageTest.java b/test/jdk/tools/jpackage/macosx/SigningAppImageTest.java index cd30b24f350a361a7b8d9cce933e49dc15dbde1e..1ebef43dad8e3ebd04b93b21835f64ed9f334ab2 100644 --- a/test/jdk/tools/jpackage/macosx/SigningAppImageTest.java +++ b/test/jdk/tools/jpackage/macosx/SigningAppImageTest.java @@ -24,6 +24,7 @@ import java.nio.file.Path; import jdk.jpackage.test.JPackageCommand; import jdk.jpackage.test.Annotations.Test; +import jdk.jpackage.test.AdditionalLauncher; /** * Tests generation of app image with --mac-sign and related arguments. Test will @@ -65,11 +66,17 @@ public class SigningAppImageTest { cmd.addArguments("--mac-sign", "--mac-signing-key-user-name", SigningBase.DEV_NAME, "--mac-signing-keychain", SigningBase.KEYCHAIN); + + AdditionalLauncher testAL = new AdditionalLauncher("testAL"); + testAL.applyTo(cmd); cmd.executeAndAssertHelloAppImageCreated(); Path launcherPath = cmd.appLauncherPath(); SigningBase.verifyCodesign(launcherPath, true); + Path testALPath = launcherPath.getParent().resolve("testAL"); + SigningBase.verifyCodesign(testALPath, true); + Path appImage = cmd.outputBundle(); SigningBase.verifyCodesign(appImage, true); SigningBase.verifySpctl(appImage, "exec"); diff --git a/test/jdk/tools/launcher/HelpFlagsTest.java b/test/jdk/tools/launcher/HelpFlagsTest.java index 173074ab9055f2ca9b351675cb62f05f1bab91c6..dda649b9f41ba2bc0178dbd5edb98a5286a3116f 100644 --- a/test/jdk/tools/launcher/HelpFlagsTest.java +++ b/test/jdk/tools/launcher/HelpFlagsTest.java @@ -151,6 +151,7 @@ public class HelpFlagsTest extends TestHelper { new ToolHelpSpec("rmiregistry", 0, 0, 0, 0, 0, 0, 1), // none, prints help message anyways. new ToolHelpSpec("serialver", 0, 0, 0, 0, 0, 0, 1), // none, prints help message anyways. new ToolHelpSpec("jpackage", 0, 1, 1, 0, 0, 1, 1), // -h, --help, + new ToolHelpSpec("jwebserver", 1, 1, 1, 0, 0, 1, 1), // -?, -h, --help }; // Returns corresponding object from jdkTools array. diff --git a/test/jdk/tools/launcher/VersionCheck.java b/test/jdk/tools/launcher/VersionCheck.java index 38a61b54198524af8282c490503570ef12089112..32d8db799ead208a1547055b4de833b5273f5ba3 100644 --- a/test/jdk/tools/launcher/VersionCheck.java +++ b/test/jdk/tools/launcher/VersionCheck.java @@ -61,7 +61,8 @@ public class VersionCheck extends TestHelper { "jmc.ini", "jweblauncher", "jpackage", - "ssvagent" + "ssvagent", + "jwebserver" }; // tools that do not accept -version diff --git a/test/langtools/jdk/javadoc/doclet/testGenericTypeLink/TestGenericTypeLink.java b/test/langtools/jdk/javadoc/doclet/testGenericTypeLink/TestGenericTypeLink.java index fbfbb5f39782849d97592a3e38e2a48d9379128c..1f0ea233288abb63f76f0b043cb51ba1aa71db61 100644 --- a/test/langtools/jdk/javadoc/doclet/testGenericTypeLink/TestGenericTypeLink.java +++ b/test/langtools/jdk/javadoc/doclet/testGenericTypeLink/TestGenericTypeLink.java @@ -166,18 +166,48 @@ public class TestGenericTypeLink extends JavadocTester { checkExit(Exit.ERROR); checkOutput("pkg2/B.html", true, """ - <div class="block"><code>java.util.Foo<String></code> - Baz<Object> - <code>#b(List<Integer>)</code></div>""", + <div class="block"> + <details class="invalid-tag"> + <summary>invalid @link</summary> + <pre><code>java.util.Foo<String></code></pre> + </details> + + \s + <details class="invalid-tag"> + <summary>invalid @linkplain</summary> + <pre>Baz<Object></pre> + </details> + + \s + <details class="invalid-tag"> + <summary>invalid @link</summary> + <pre><code>#b(List<Integer>)</code></pre> + </details> + </div>""", """ <dl class="notes"> <dt>See Also:</dt> <dd> <ul class="see-list-long"> - <li><code>java.util.List<Bar></code></li> - <li><code>Baz<Object, String></code></li> - <li><code>B#b(List<Baz>)</code></li> + <li> + <details class="invalid-tag"> + <summary>invalid @see</summary> + <pre><code>java.util.List<Bar></code></pre> + </details> + </li> + <li> + <details class="invalid-tag"> + <summary>invalid @see</summary> + <pre><code>Baz<Object, String></code></pre> + </details> + </li> + <li> + <details class="invalid-tag"> + <summary>invalid @see</summary> + <pre><code>B#b(List<Baz>)</code></pre> + </details> + </li> </ul> </dd> </dl>"""); diff --git a/test/langtools/jdk/javadoc/doclet/testInherited/TestInherited.java b/test/langtools/jdk/javadoc/doclet/testInherited/TestInherited.java index 21391201a032c6ab86792bfe0b1338c43e294a9e..0806278b43d28d18951255915aa3189f52671191 100644 --- a/test/langtools/jdk/javadoc/doclet/testInherited/TestInherited.java +++ b/test/langtools/jdk/javadoc/doclet/testInherited/TestInherited.java @@ -69,11 +69,11 @@ public class TestInherited extends JavadocTester { checkExit(Exit.OK); checkOutput("BadParam.Base.html", true, """ <dt>Parameters:</dt> - <dd><code>i</code> - a < b</dd> + <dd><code>i</code> - a <span class="invalid-tag">invalid input: '<'</span> b</dd> """); checkOutput("BadParam.Sub.html", true, """ <dt>Parameters:</dt> - <dd><code>i</code> - a < b</dd> + <dd><code>i</code> - a <span class="invalid-tag">invalid input: '<'</span> b</dd> """); } @@ -101,11 +101,11 @@ public class TestInherited extends JavadocTester { checkExit(Exit.OK); checkOutput("BadReturn.Base.html", true, """ <dt>Returns:</dt> - <dd>a < b</dd> + <dd>a <span class="invalid-tag">invalid input: '<'</span> b</dd> """); checkOutput("BadReturn.Sub.html", true, """ <dt>Returns:</dt> - <dd>a < b</dd> + <dd>a <span class="invalid-tag">invalid input: '<'</span> b</dd> """); } @@ -147,16 +147,36 @@ public class TestInherited extends JavadocTester { src.resolve("BadReference.java").toString()); checkExit(Exit.OK); checkOutput("BadReference.Intf.html", true, """ - <div class="block"><code>NonExistingClass</code></div> + <div class="block"> + <details class="invalid-tag"> + <summary>invalid @link</summary> + <pre><code>NonExistingClass</code></pre> + </details> + </div> """); checkOutput("BadReference.Impl1.html", true, """ - <div class="block"><code>NonExistingClass</code></div> + <div class="block"> + <details class="invalid-tag"> + <summary>invalid @link</summary> + <pre><code>NonExistingClass</code></pre> + </details> + </div> """); checkOutput("BadReference.Impl2.html", true, """ - <div class="block"><code>NonExistingClass</code></div> + <div class="block"> + <details class="invalid-tag"> + <summary>invalid @link</summary> + <pre><code>NonExistingClass</code></pre> + </details> + </div> """); checkOutput("BadReference.Impl3.html", true, """ - <div class="block"><code>NonExistingClass</code></div> + <div class="block"> + <details class="invalid-tag"> + <summary>invalid @link</summary> + <pre><code>NonExistingClass</code></pre> + </details> + </div> """); } } diff --git a/test/langtools/jdk/javadoc/doclet/testLinkOption/TestLinkOptionWithModule.java b/test/langtools/jdk/javadoc/doclet/testLinkOption/TestLinkOptionWithModule.java index c12432322ff908277d46ff0b455b8a7e7d412baa..4f7602251d8e14cbf0b461ff5f496a297222f914 100644 --- a/test/langtools/jdk/javadoc/doclet/testLinkOption/TestLinkOptionWithModule.java +++ b/test/langtools/jdk/javadoc/doclet/testLinkOption/TestLinkOptionWithModule.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 8205593 8240169 + * @bug 8205593 8240169 8274639 * @summary Javadoc -link makes broken links if module name matches package name * @library /tools/lib ../../lib * @modules @@ -71,6 +71,7 @@ public class TestLinkOptionWithModule extends JavadocTester { "--module", "com.ex1"); javadoc("-d", out2.toString(), + "-Werror", "-Xdoclint:-missing", "--module-source-path", moduleSrc.toString(), "--module", "com.ex2", "-link", "../" + out1.getFileName()); @@ -109,13 +110,14 @@ public class TestLinkOptionWithModule extends JavadocTester { "-subpackages", "com.ex1"); javadoc("-d", out2.toString(), + "--link-modularity-mismatch", "warn", "--module-source-path", moduleSrc.toString(), "--module", "com.ex2", "-link", "../" + out1.getFileName()); checkExit(Exit.OK); checkOutput(Output.OUT, true, - "The code being documented uses modules but the packages defined " + "warning: The code being documented uses modules but the packages defined " + "in ../out3a/ are in the unnamed module"); checkOutput("com.ex2/com/ex2/B.html", true, """ @@ -137,13 +139,62 @@ public class TestLinkOptionWithModule extends JavadocTester { checkExit(Exit.OK); checkOutput(Output.OUT, true, - "The code being documented uses packages in the unnamed module, but the packages defined " + "warning: The code being documented uses packages in the unnamed module, but the packages defined " + "in ../out4a/ are in named modules"); checkOutput("com/ex2/B.html", true, """ <a href="../../../out4a/com.ex1/com/ex1/A.html" title="class or interface in com.ex1" class="external-link">A</a>"""); } + @Test + public void testModuleLinkedToPackageNoWarning(Path base) throws Exception { + Path out1 = base.resolve("out5a"), out2 = base.resolve("out5b"); + + javadoc("-d", out1.toString(), + "-sourcepath", packageSrc.toString(), + "-subpackages", "com.ex1"); + + javadoc("-d", out2.toString(), + "--link-modularity-mismatch", "info", + "-Werror", "-Xdoclint:-missing", + "--module-source-path", moduleSrc.toString(), + "--module", "com.ex2", + "-link", "../" + out1.getFileName()); + + checkExit(Exit.OK); + checkOutput(Output.OUT, true, + "The code being documented uses modules but the packages defined " + + "in ../out5a/ are in the unnamed module"); + checkOutput("com.ex2/com/ex2/B.html", true, + """ + <a href="../../../../out5a/com/ex1/A.html" title="class or interface in com.ex1" class="external-link">A</a>"""); + } + + @Test + public void testPackageLinkedToModuleNoWarning(Path base) throws Exception { + Path out1 = base.resolve("out6a"), out2 = base.resolve("out6b"); + + javadoc("-d", out1.toString(), + "--module-source-path", moduleSrc.toString(), + "--module", "com.ex1"); + + javadoc("-d", out2.toString(), + "--link-modularity-mismatch", "info", + "-quiet", // should not print modularity mismatch info + "-Werror", "-Xdoclint:-missing", + "-sourcepath", packageSrc.toString(), + "-subpackages", "com.ex2", + "-link", "../" + out1.getFileName()); + + checkExit(Exit.OK); + // Modularity mismatch diagnostic should not be printed because we're runnning with -quiet option + checkOutput(Output.OUT, false, + "The code being documented uses packages in the unnamed module, but the packages defined " + + "in ../out6a/ are in named modules"); + checkOutput("com/ex2/B.html", true, + """ + <a href="../../../out6a/com.ex1/com/ex1/A.html" title="class or interface in com.ex1" class="external-link">A</a>"""); + } void initModulesAndPackages() throws Exception{ new ModuleBuilder(tb, "com.ex1") diff --git a/test/langtools/jdk/javadoc/doclet/testNonInlineHtmlTagRemoval/TestNonInlineHtmlTagRemoval.java b/test/langtools/jdk/javadoc/doclet/testNonInlineHtmlTagRemoval/TestNonInlineHtmlTagRemoval.java index 35a25e29bf26310e930c68274e9521ffbf55dbf9..b0b54bbdd6c2e11d638f59ba83221199bd46ecb9 100644 --- a/test/langtools/jdk/javadoc/doclet/testNonInlineHtmlTagRemoval/TestNonInlineHtmlTagRemoval.java +++ b/test/langtools/jdk/javadoc/doclet/testNonInlineHtmlTagRemoval/TestNonInlineHtmlTagRemoval.java @@ -85,6 +85,6 @@ public class TestNonInlineHtmlTagRemoval extends JavadocTester { checkOutput("Negative.html", true, """ - <div class="block">case1: A hanging < : xx<</div>"""); + <div class="block">case1: A hanging < : xx<span class="invalid-tag">invalid input: '<'</span></div>"""); } } diff --git a/test/langtools/jdk/javadoc/doclet/testSeeTag/TestSeeTag.java b/test/langtools/jdk/javadoc/doclet/testSeeTag/TestSeeTag.java index f364cd47ef7c1ea33161bf393c2d1df3f848ea0a..b6661acae52b5d1275023d7aa408af9cceeb2cbd 100644 --- a/test/langtools/jdk/javadoc/doclet/testSeeTag/TestSeeTag.java +++ b/test/langtools/jdk/javadoc/doclet/testSeeTag/TestSeeTag.java @@ -100,7 +100,12 @@ public class TestSeeTag extends JavadocTester { <dd> <ul class="see-list"> <li><code>Object</code></li> - <li><code>Foo<String></code></li> + <li> + <details class="invalid-tag"> + <summary>invalid @see</summary> + <pre><code>Foo<String></code></pre> + </details> + </li> </ul> </dd> </dl>"""); diff --git a/test/langtools/jdk/javadoc/doclet/testSnippetTag/SnippetTester.java b/test/langtools/jdk/javadoc/doclet/testSnippetTag/SnippetTester.java index a220a4a0db95cdbbd1a2b0471812cff76aa942a3..23d653be00f82f1b5f151170ce8225719f2d1ae9 100644 --- a/test/langtools/jdk/javadoc/doclet/testSnippetTag/SnippetTester.java +++ b/test/langtools/jdk/javadoc/doclet/testSnippetTag/SnippetTester.java @@ -26,9 +26,11 @@ import java.io.UncheckedIOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardOpenOption; +import java.nio.file.attribute.BasicFileAttributes; import java.util.Arrays; import java.util.List; import java.util.Optional; +import java.util.function.BiPredicate; import java.util.function.ObjIntConsumer; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -101,6 +103,12 @@ public class SnippetTester extends JavadocTester { return getSnippetHtmlRepresentation(pathToHtmlFile, content, Optional.empty(), Optional.empty()); } + protected String getSnippetHtmlRepresentation(String pathToHtmlFile, + String content, + Optional<String> lang) { + return getSnippetHtmlRepresentation(pathToHtmlFile, content, lang, Optional.empty()); + } + protected String getSnippetHtmlRepresentation(String pathToHtmlFile, String content, Optional<String> lang, @@ -116,4 +124,46 @@ public class SnippetTester extends JavadocTester { <pre class="snippet"%s><code%s>%s</code></pre> </div>""".formatted(svgString, idString, langString, content); } + + // There's JavadocTester.diff(), but its semantics is different; hence we + // use this method. + protected void match(Path path1, Path path2, BiPredicate<Path, BasicFileAttributes> filter) throws IOException { + checking("diff " + path1 + ", " + path2); + try (var paths1 = Files.find(path1, Integer.MAX_VALUE, filter).sorted(); + var paths2 = Files.find(path2, Integer.MAX_VALUE, filter).sorted()) { + var it1 = paths1.iterator(); + var it2 = paths2.iterator(); + while (true) { + if (it1.hasNext() != it2.hasNext()) { + failed(it1.hasNext() ? it1.next() : it2.next(), "missing"); + return; + } + if (!it1.hasNext()) { + passed("match"); + return; + } + Path next1 = it1.next(); + Path next2 = it2.next(); + if (!path1.relativize(next1).equals(path2.relativize(next2))) { + // compare directory tree to see the difference + failed("mismatching names %s %s".formatted(next1, next2)); + return; + } + if (Files.isDirectory(next1) != Files.isDirectory(next2)) { + // it'd be surprising to ever see this + failed("mismatching types %s %s".formatted(next1, next2)); + return; + } + if (Files.isDirectory(next1)) { + continue; + } + if (Files.size(next1) != Files.size(next2) + || Files.mismatch(next1, next2) != -1L) { + failed("mismatching contents: diff %s %s".formatted(next1.toAbsolutePath(), + next2.toAbsolutePath())); + return; + } + } + } + } } diff --git a/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestLangProperties.java b/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestLangProperties.java new file mode 100644 index 0000000000000000000000000000000000000000..de8ea1b3490766f5ef66d13fbd79ddeb23d2455e --- /dev/null +++ b/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestLangProperties.java @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8266666 + * @summary Implementation for snippets + * @library /tools/lib ../../lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * jdk.javadoc/jdk.javadoc.internal.tool + * @build javadoc.tester.* toolbox.ToolBox toolbox.ModuleBuilder builder.ClassBuilder + * @run main TestLangProperties + */ + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +public class TestLangProperties extends SnippetTester { + + public static void main(String... args) throws Exception { + new TestLangProperties().runTests(m -> new Object[]{Paths.get(m.getName())}); + } + + @Test + public void testPositiveOuterMarkup(Path base) throws Exception { + var testCases = new ArrayList<TestSnippetMarkup.TestCase>(); + for (String whitespace1 : List.of("", " ", "\t")) + for (String commentIndicator1 : List.of("#", "!")) + for (String whitespace2 : List.of("", " ", "\t")) { + String markup = whitespace1 + commentIndicator1 + + whitespace2 + "@highlight :"; + var t = new TestSnippetMarkup.TestCase( + """ + %s + coffee=espresso + tea=black + """.formatted(markup), + """ + <span class="bold">coffee=espresso + </span>tea=black + """); + testCases.add(t); + } + testPositive(base, testCases); + } + + @Test + public void testPositiveInnerMarkup(Path base) throws Exception { + var testCases = new ArrayList<TestSnippetMarkup.TestCase>(); + for (String whitespace1 : List.of("", " ", "\t")) + for (String commentIndicator1 : List.of("#", "!")) + for (String whitespace2 : List.of("", " ", "\t")) + for (String unrelatedComment : List.of("a comment")) + for (String whitespace3 : List.of("", " ")) + for (String commentIndicator2 : List.of("#", "!")) { + String payload = whitespace1 + commentIndicator1 + whitespace2 + unrelatedComment; + String markup = payload + whitespace3 + commentIndicator2 + "@highlight :"; + var t = new TestSnippetMarkup.TestCase( + """ + %s + coffee=espresso + tea=black + """.formatted(markup), + """ + %s + <span class="bold">coffee=espresso + </span>tea=black + """.formatted(payload)); + testCases.add(t); + } + testPositive(base, testCases); + } + + @Test + public void testPositiveIneffectiveOuterMarkup(Path base) throws Exception { + var testCases = new ArrayList<TestSnippetMarkup.TestCase>(); + for (String whitespace1 : List.of("", " ", "\t")) + for (String commentIndicator1 : List.of("#", "!")) + for (String whitespace2 : List.of("", " ", "\t")) { + String ineffectiveMarkup = whitespace1 + + commentIndicator1 + whitespace2 + + "@highlight :"; + var t = new TestSnippetMarkup.TestCase( + """ + coffee=espresso%s + tea=black + """.formatted(ineffectiveMarkup), + """ + coffee=espresso%s + tea=black + """.formatted(ineffectiveMarkup)); + testCases.add(t); + } + testPositive(base, testCases); + } + + @Test + public void testPositiveIneffectiveInnerMarkup(Path base) throws Exception { + var testCases = new ArrayList<TestSnippetMarkup.TestCase>(); + for (String whitespace1 : List.of("", " ", "\t")) + for (String commentIndicator1 : List.of("#", "!")) + for (String whitespace2 : List.of("", " ", "\t")) + for (String unrelatedComment : List.of("a comment")) + for (String whitespace3 : List.of("", " ")) + for (String commentIndicator2 : List.of("#", "!")) { + String ineffectiveMarkup = whitespace1 + + commentIndicator1 + whitespace2 + + unrelatedComment + whitespace3 + + commentIndicator2 + "@highlight :"; + var t = new TestSnippetMarkup.TestCase( + """ + coffee=espresso%s + tea=black + """.formatted(ineffectiveMarkup), + """ + coffee=espresso%s + tea=black + """.formatted(ineffectiveMarkup)); + testCases.add(t); + } + testPositive(base, testCases); + } + + private void testPositive(Path base, List<TestSnippetMarkup.TestCase> testCases) + throws IOException { + StringBuilder methods = new StringBuilder(); + forEachNumbered(testCases, (i, n) -> { + String r = i.region().isBlank() ? "" : "region=" + i.region(); + var methodDef = """ + + /** + {@snippet lang="properties" %s: + %s}*/ + public void case%s() {} + """.formatted(r, i.input(), n); + methods.append(methodDef); + }); + var classDef = """ + public class A { + %s + } + """.formatted(methods.toString()); + Path src = Files.createDirectories(base.resolve("src")); + tb.writeJavaFiles(src, classDef); + javadoc("-d", base.resolve("out").toString(), + "-sourcepath", src.toString(), + src.resolve("A.java").toString()); + checkExit(Exit.OK); + checkNoCrashes(); + forEachNumbered(testCases, (t, index) -> { + String html = """ + <span class="element-name">case%s</span>()</div> + <div class="block"> + %s + </div>""".formatted(index, getSnippetHtmlRepresentation("A.html", + t.expectedOutput(), Optional.of("properties"))); + checkOutput("A.html", true, html); + }); + } +} diff --git a/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetMarkup.java b/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetMarkup.java index 16ec33212903faa6bea036ce3f510072ee5efd64..8b5e6b4438dc01c1994094f0cbea193f83c6e683 100644 --- a/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetMarkup.java +++ b/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetMarkup.java @@ -370,6 +370,348 @@ First line // @highlight : testPositive(base, testCases); } + /* + * These are corner cases. As such they are expected to rarely happen in + * practise. These tests merely capture what the results looked when + * the feature was integrated. This might help when refactoring + * and refreshing the feature, to better understand the impact of + * the proposed changes. + */ + @Test + public void testPositiveInlineTagMarkup_ReplaceOnBlankLine(Path base) throws Exception { + var testCases = List.of( + // the complete line is being replaced + new TestCase("one", + """ + // @start region=one @replace regex=".*" replacement="-----" + one + // @end + """, + """ + -----one + """ + ), + // the contents of the line, but not the line terminator is being replaced + new TestCase("two", + """ + // @start region=two @replace regex=".+" replacement="*****" + two + // @end + """, + """ + *****two + """ + ), + new TestCase( + """ + // @replace regex="duke" replacement="duchess" + """, + """ + """ + ) + ); + testPositive(base, testCases); + } + + @Test + public void testPositiveInlineTagMarkup_BlankLinesRegionEquivalence(Path base) throws Exception { + var testCases = List.of( + new TestCase("example1", + """ + // @start region="example1" + if (v.isPresent()) { + System.out.println("v: " + v.get()); + } // @end + """, + """ + if (v.isPresent()) { + System.out.println("v: " + v.get()); + }"""), + new TestCase("example2", + """ + if (v.isPresent()) { // @start region="example2" + System.out.println("v: " + v.get()); + } // @end + """, + """ + if (v.isPresent()) { + System.out.println("v: " + v.get()); + }"""), + new TestCase("example3", + """ + // @start region="example3" : + if (v.isPresent()) { + System.out.println("v: " + v.get()); + // @end : + } + """, + """ + if (v.isPresent()) { + System.out.println("v: " + v.get()); + }""") + ); + testPositive(base, testCases); + } + + @Test + public void testPositiveInlineTagMarkup_BlankLinesEquivalence(Path base) throws Exception { + var testCases = List.of( + new TestCase( + """ + // @start region="example" + if (v.isPresent()) { + System.out.println("v: " + v.get()); + } + // @end + """, + """ + if (v.isPresent()) { + System.out.println("v: " + v.get()); + } + """), + new TestCase( + """ + if (v.isPresent()) { // @start region="example" + System.out.println("v: " + v.get()); + } // @end + """, + """ + if (v.isPresent()) { + System.out.println("v: " + v.get()); + } + """), + new TestCase( + """ + // @start region="example" : + if (v.isPresent()) { + System.out.println("v: " + v.get()); + // @end : + } + """, + """ + if (v.isPresent()) { + System.out.println("v: " + v.get()); + } + """) + ); + testPositive(base, testCases); + } + + @Test + public void testPositiveInlineTagMarkup_BlankLinesFromStartEnd(Path base) throws Exception { + // A markup line that contains either @start or @end is removed. + var testCases = List.of( + new TestCase(""" + First line + // @start region="a" + Third line + // @end + Fifth line + """, + """ + First line + Third line + Fifth line + """), + new TestCase(""" + First line + // @start region="a" + // @start region="b" + Third line + // @end + Fifth line + // @end + """, + """ + First line + Third line + Fifth line + """), + // note incidental whitespace removal in test cases below + new TestCase("a", """ + First line + // @start region="a" + Third line + // @end + Fifth line + """, + + """ + Third line + """), + new TestCase("b", """ + First line + // @start region="a" + // @start region="b" + Third line + // @end + Fifth line + // @end + """, + """ + Third line + """) + ); + testPositive(base, testCases); + } + + @Test + public void testPositiveInlineTagMarkup_BlankLinesFromNextLineMarkup(Path base) throws Exception { + // A markup line that refers to the next line is removed. + var testCases = List.of( + new TestCase(""" + First line + // @highlight: + Third line + """, + """ + First line + <span class="bold"> Third line + </span>"""), + new TestCase(""" + First line + // @link target="Object#equals(Object)": + Third line + """, + replace(""" + First line + link(Third line) + """, "link\\((.+?)\\)", r -> link(true, "java.lang.Object#equals(Object)", r.group(1))) + ), + new TestCase(""" + First line + // @replace regex=.+ replacement="x": + Third line + """, + """ + First line + x + """), + new TestCase(""" + First line + // @start region=a: + Third line + // @end: + Fifth line + """, + """ + First line + Third line + Fifth line + """) + ); + testPositive(base, testCases); + } + + @Test + public void testPositiveInlineTagMarkup_FalseMarkup(Path base) throws Exception { + var testCases = List.of( + new TestCase( + """ + First line + // @formatter:off + Second Line + Third line + // @formatter:on + Fourth line + """, + """ + First line + // @formatter:off + Second Line + Third line + // @formatter:on + Fourth line + """), + new TestCase("showThis", + """ + First line + // @formatter:off + // @start region=showThis + Second Line + Third line + // @end region + // @formatter:on + Fourth line + """, + """ + Second Line + Third line + """) + ); + testPositive(base, testCases); + } + + @Test + public void testPositiveInlineTagMarkup_NextLineTwoTags(Path base) throws Exception { + var firstTag = new String[]{ + "@highlight string=firstWord", + "@replace string=secondWord replacement=replacedSecondWord", + "@link substring=firstWord target=java.lang.Object"}; + var secondTag = new String[]{ + "@highlight string=secondWord", + "@replace string=firstWord replacement=replacedFirstWord", + "@link substring=secondWord target=java.lang.Thread"}; + List<TestCase> testCases = new ArrayList<>(); + for (var f : firstTag) { + for (var s : secondTag) + for (var separator : List.of("", " ")) { + var t = new TestCase( + """ + first-line // %s %s%s: + firstWord secondWord thirdWord + """.formatted(f, s, separator), + """ + first-line + firstWord secondWord thirdWord // %s %s + """.formatted(f, s)); + testCases.add(t); + } + } + testEquivalence(base, testCases); + } + + record Snippet(String region, String snippet) { } + + private void testEquivalence(Path base, List<TestCase> testCases) throws IOException { + // group all the testcases in just two runs + Path out1 = base.resolve("out1"); + Path out2 = base.resolve("out2"); + run(base.resolve("src1"), out1, testCases.stream().map(t -> new Snippet(t.region(), t.input())).toList()); + run(base.resolve("src2"), out2, testCases.stream().map(t -> new Snippet(t.region(), t.expectedOutput())).toList()); + match(out1, out2, (p, a) -> /* p.toString().endsWith(".html") */ true); + } + + private void run(Path source, Path target, List<Snippet> snippets) throws IOException { + StringBuilder methods = new StringBuilder(); + forEachNumbered(snippets, (i, n) -> { + String r = i.region.isBlank() ? "" : "region=" + i.region; + var methodDef = """ + + /** + {@snippet %s: + %s}*/ + public void case%s() {} + """.formatted(r, i.snippet(), n); + methods.append(methodDef); + }); + var classDef = """ + public class A { + %s + } + """.formatted(methods.toString()); + Path src = Files.createDirectories(source); + tb.writeJavaFiles(src, classDef); + javadoc("-d", target.toString(), + "--limit-modules", "java.base", + "-quiet", "-nohelp", "-noindex", "-nonavbar", "-nosince", + "-notimestamp", "-notree", "-Xdoclint:none", + "-sourcepath", src.toString(), + src.resolve("A.java").toString()); + checkExit(Exit.OK); + checkNoCrashes(); + } + private static String link(boolean linkPlain, String targetReference, String content) diff --git a/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetTag.java b/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetTag.java index 269869ba4b532efe65c137a1ec95503712e21bd8..4b0dd06a2a246adc35c34432829beaf02cea552f 100644 --- a/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetTag.java +++ b/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetTag.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8266666 8275788 + * @bug 8266666 8275788 8276964 * @summary Implementation for snippets * @library /tools/lib ../../lib * @modules jdk.compiler/com.sun.tools.javac.api @@ -278,7 +278,6 @@ public class TestSnippetTag extends SnippetTester { checkExit(Exit.OK); checkLinks(); final var javaContent = """ - System.out.println(msg); """; final var propertiesContent = """ @@ -1081,6 +1080,12 @@ public class TestSnippetTag extends SnippetTester { checkOutput(Output.OUT, true, """ A.java:4: error: File not found: %s""".formatted(fileName)); + checkOutput("pkg/A.html", true, """ + <details class="invalid-tag"> + <summary>invalid @snippet</summary> + <pre>File not found: text.txt</pre> + </details> + """); checkNoCrashes(); } @@ -1156,6 +1161,12 @@ public class TestSnippetTag extends SnippetTester { checkOutput(Output.OUT, true, """ A.java:3: error: @snippet does not specify contents"""); + checkOutput("pkg/A.html", true, """ + <details class="invalid-tag"> + <summary>invalid @snippet</summary> + <pre>@snippet does not specify contents</pre> + </details> + """); checkNoCrashes(); } @@ -1212,6 +1223,12 @@ public class TestSnippetTag extends SnippetTester { checkOutput(Output.OUT, true, """ A.java:3: error: @snippet specifies multiple external contents, which is ambiguous"""); + checkOutput("pkg/A.html", true, """ + <details class="invalid-tag"> + <summary>invalid @snippet</summary> + <pre>@snippet specifies multiple external contents, which is ambiguous</pre> + </details> + """); checkNoCrashes(); } @@ -1864,15 +1881,15 @@ public class TestSnippetTag extends SnippetTester { for (String attrName : List.of("class", "file", "id", "lang", "region")) { // special case: valueless region attribute TestCase t = new TestCase(""" -{@snippet %s: - First line - Second line -} -""".formatted(attrName), -""" -: error: missing value for attribute "%s" -{@snippet %s: - ^""".formatted(attrName, attrName)); + {@snippet %s: + First line + Second line + } + """.formatted(attrName), + """ + : error: missing value for attribute "%s" + {@snippet %s: + ^""".formatted(attrName, attrName)); testCases.add(t); } @@ -1916,15 +1933,18 @@ public class TestSnippetTag extends SnippetTester { for (String quote : List.of("", "'", "\"")) for (String value : List.of("", " ")) { var t = new TestCase(""" -{@snippet region=%s%s%s: - First line - Second line -} -""".formatted(quote, value, quote), - """ -: error: illegal value for attribute "region": "%s" -{@snippet region=%s%s%s: - ^""".formatted(quote.isEmpty() ? "" : value, quote, value, quote)); // unquoted whitespace translates to empty string + {@snippet region=%s%s%s: + First line + Second line + } + """.formatted(quote, value, quote), + """ + : error: illegal value for attribute "region": "%s" + {@snippet region=%s%s%s: + ^ + """.formatted( + quote.isEmpty() ? "" : value, // unquoted whitespace translates to empty string + quote, value, quote)); testCases.add(t); } @@ -2016,6 +2036,17 @@ public class TestSnippetTag extends SnippetTester { checkOutput(Output.OUT, true, """ A.java:4: error: contents mismatch"""); + checkOutput("pkg/A.html", true, """ + <details class="invalid-tag"> + <summary>invalid @snippet</summary> + <pre>contents mismatch: + ----------------- inline ------------------- + Hello, Snippet! + ----------------- external ----------------- + Hello, Snippet!...more + </pre> + </details> + """); checkNoCrashes(); } @@ -2056,6 +2087,19 @@ public class TestSnippetTag extends SnippetTester { checkOutput(Output.OUT, true, """ A.java:4: error: contents mismatch"""); + checkOutput("pkg/A.html", true, """ + <details class="invalid-tag"> + <summary>invalid @snippet</summary> + <pre>contents mismatch: + ----------------- inline ------------------- + Hello, Snippet! ...more + + ----------------- external ----------------- + Hello, Snippet! + + </pre> + </details> + """); checkNoCrashes(); } @@ -2279,41 +2323,41 @@ public class TestSnippetTag extends SnippetTester { final var testCases = List.of( new TestCase(""" -{@snippet : -hello there // @highlight regex ="\t**" -}""", + {@snippet : + hello there // @highlight regex ="\t**" + }""", """ -error: snippet markup: invalid regex -hello there // @highlight regex ="\t**" - \t ^ -"""), + error: snippet markup: invalid regex + hello there // @highlight regex ="\t**" + \t ^ + """), new TestCase(""" -{@snippet : -hello there // @highlight regex ="\\t**" -}""", + {@snippet : + hello there // @highlight regex ="\\t**" + }""", """ -error: snippet markup: invalid regex -hello there // @highlight regex ="\\t**" - ^ -"""), + error: snippet markup: invalid regex + hello there // @highlight regex ="\\t**" + ^ + """), new TestCase(""" -{@snippet : -hello there // @highlight regex="\\.\\*\\+\\E" -}""", + {@snippet : + hello there // @highlight regex="\\.\\*\\+\\E" + }""", """ -error: snippet markup: invalid regex -hello there // @highlight regex="\\.\\*\\+\\E" - \s\s\s\s ^ -"""), // use \s to counteract shift introduced by \\ so as to visually align ^ right below E + error: snippet markup: invalid regex + hello there // @highlight regex="\\.\\*\\+\\E" + \s\s\s\s ^ + """), // use \s to counteract shift introduced by \\ so as to visually align ^ right below E new TestCase(""" -{@snippet : -hello there // @highlight type="italics" regex =" [" -}""", + {@snippet : + hello there // @highlight type="italics" regex =" [" + }""", """ -error: snippet markup: invalid regex -hello there // @highlight type="italics" regex =" [" - ^ -""") + error: snippet markup: invalid regex + hello there // @highlight type="italics" regex =" [" + ^ + """) ); List<String> inputs = testCases.stream().map(s -> s.input).toList(); @@ -2343,6 +2387,12 @@ hello there // @highlight type="italics" regex =" [" src.resolve("A.java").toString()); checkExit(Exit.ERROR); checkOrder(Output.OUT, testCases.stream().map(TestCase::expectedError).toArray(String[]::new)); + checkOutput("A.html", true, """ + <details class="invalid-tag"> + <summary>invalid @snippet</summary> + <pre>invalid regex</pre> + </details> + """); checkNoCrashes(); } @@ -2353,117 +2403,118 @@ hello there // @highlight type="italics" regex =" [" final var testCases = List.of( new TestCase(""" -{@snippet : - hello // @link -}""", + {@snippet : + hello // @link + }""", """ -error: snippet markup: missing attribute "target" - hello // @link - ^ + error: snippet markup: missing attribute "target" + hello // @link + ^ """), new TestCase(""" -{@snippet : - hello // @start -}""", + {@snippet : + hello // @start + }""", """ -error: snippet markup: missing attribute "region" - hello // @start - ^ + error: snippet markup: missing attribute "region" + hello // @start + ^ """), new TestCase(""" -{@snippet : - hello // @replace -}""", + {@snippet : + hello // @replace + }""", """ -error: snippet markup: missing attribute "replacement" - hello // @replace - ^ + error: snippet markup: missing attribute "replacement" + hello // @replace + ^ """), /* ---------------------- */ new TestCase(""" -{@snippet : - hello // @highlight regex=\\w+ substring=hello -}""", + {@snippet : + hello // @highlight regex=\\w+ substring=hello + }""", """ -error: snippet markup: attributes "substring" and "regex" used simultaneously - hello // @highlight regex=\\w+ substring=hello - ^ + error: snippet markup: attributes "substring" and "regex" used simultaneously + hello // @highlight regex=\\w+ substring=hello + ^ """), new TestCase(""" -{@snippet : - hello // @start region="x" name="here" -}""", + {@snippet : + hello // @start region="x" name="here" + }""", """ -error: snippet markup: unexpected attribute - hello // @start region="x" name="here" - ^ + error: snippet markup: unexpected attribute + hello // @start region="x" name="here" + ^ """), new TestCase(""" -{@snippet : - hello // @start region="" -}""", + {@snippet : + hello // @start region="" + }""", """ -error: snippet markup: invalid attribute value - hello // @start region="" - ^ + error: snippet markup: invalid attribute value + hello // @start region="" + ^ """), new TestCase(""" -{@snippet : - hello // @link target="Object#equals()" type=fluffy -}""", + {@snippet : + hello // @link target="Object#equals()" type=fluffy + }""", """ -error: snippet markup: invalid attribute value - hello // @link target="Object#equals()" type=fluffy - ^ + error: snippet markup: invalid attribute value + hello // @link target="Object#equals()" type=fluffy + ^ """), /* ---------------------- */ new TestCase(""" -{@snippet : - hello // @highlight substring=" -}""", + {@snippet : + hello + there // @highlight substring=" + }""", """ -error: snippet markup: unterminated attribute value - hello // @highlight substring=" - ^ + error: snippet markup: unterminated attribute value + there // @highlight substring=" + ^ """), new TestCase(""" -{@snippet : - hello // @start region="this" - world // @start region="this" - ! // @end -}""", + {@snippet : + hello // @start region="this" + world // @start region="this" + ! // @end + }""", """ -error: snippet markup: duplicated region - world // @start region="this" - ^ + error: snippet markup: duplicated region + world // @start region="this" + ^ """), new TestCase(""" -{@snippet : - hello // @end -}""", + {@snippet : + hello // @end + }""", """ -error: snippet markup: no region to end - hello // @end - ^ + error: snippet markup: no region to end + hello // @end + ^ """), new TestCase(""" -{@snippet : - hello // @start region=this -}""", + {@snippet : + hello // @start region=this + }""", """ -error: snippet markup: unpaired region - hello // @start region=this - ^ + error: snippet markup: unpaired region + hello // @start region=this + ^ """), new TestCase(""" -{@snippet : - hello // @highlight substring="hello" : -}""", + {@snippet : + hello // @highlight substring="hello" : + }""", """ -error: snippet markup: tag refers to non-existent lines - hello // @highlight substring="hello" : - ^ - """) + error: snippet markup: tag refers to non-existent lines + hello // @highlight substring="hello" : + ^ + """) ); List<String> inputs = testCases.stream().map(s -> s.input).toList(); StringBuilder methods = new StringBuilder(); @@ -2493,6 +2544,12 @@ error: snippet markup: tag refers to non-existent lines checkExit(Exit.ERROR); // use the facility from JDK-8273154 when it becomes available checkOutput(Output.OUT, true, testCases.stream().map(TestCase::expectedError).toArray(String[]::new)); + checkOutput("A.html", true, """ + <details class="invalid-tag"> + <summary>invalid @snippet</summary> + <pre>missing attribute "target"</pre> + </details> + """); checkNoCrashes(); } } diff --git a/test/langtools/jdk/javadoc/tool/CheckManPageOptions.java b/test/langtools/jdk/javadoc/tool/CheckManPageOptions.java index 437b55da677f4fd05e2e46cc42960b9b3e1f978d..5a0d83926c8ed954550c43314e8244da0008b994 100644 --- a/test/langtools/jdk/javadoc/tool/CheckManPageOptions.java +++ b/test/langtools/jdk/javadoc/tool/CheckManPageOptions.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8274211 + * @bug 8274211 8278538 * @summary Test man page that options are documented * @modules jdk.javadoc/jdk.javadoc.internal.tool:+open * @run main CheckManPageOptions @@ -60,15 +60,7 @@ public class CheckManPageOptions { static final PrintStream out = System.err; - // FIXME: JDK-8274295, JDK-8266666 - List<String> MISSING_IN_MAN_PAGE = List.of( - "--add-script", - "--legal-notices", - "--link-platform-properties", - "--no-platform-links", - "--since", - "--since-label", - "--snippet-path"); + List<String> MISSING_IN_MAN_PAGE = List.of(); void run(String... args) throws Exception { var file = args.length == 0 ? findDefaultFile() : Path.of(args[0]); diff --git a/test/langtools/jdk/javadoc/tool/IgnoreSourceErrors.java b/test/langtools/jdk/javadoc/tool/IgnoreSourceErrors.java index 6c79492db053b124156dbfc1a99028f93bf9a1dd..44e698d7a885e8944fe7d489f3124c8065df86c1 100644 --- a/test/langtools/jdk/javadoc/tool/IgnoreSourceErrors.java +++ b/test/langtools/jdk/javadoc/tool/IgnoreSourceErrors.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 8175219 + * @bug 8175219 8268582 * @summary test --ignore-errors works correctly * @modules * jdk.javadoc/jdk.javadoc.internal.api @@ -73,6 +73,12 @@ public class IgnoreSourceErrors extends TestRunner { if (!out.contains("modifier static not allowed here")) { throw new Exception("expected string not found \'modifier static not allowed here\'"); } + if (!out.contains("package invalid.example does not exist")) { + throw new Exception("expected string not found \'package invalid.example does not exist\'"); + } + if (!out.contains("cannot find symbol")) { + throw new Exception("expected string not found \'cannot find symbol\'"); + } } @Test @@ -84,12 +90,19 @@ public class IgnoreSourceErrors extends TestRunner { if (!out.contains("modifier static not allowed here")) { throw new Exception("expected string not found \'modifier static not allowed here\'"); } + if (!out.contains("package invalid.example does not exist")) { + throw new Exception("expected string not found \'package invalid.example does not exist\'"); + } + if (!out.contains("cannot find symbol")) { + throw new Exception("expected string not found \'cannot find symbol\'"); + } } void emitSample(Path file) throws IOException { String[] contents = { "/** A java file with errors */", - "public static class Foo {}" + "import invalid.example.OtherClass;", + "public static class Foo<T> extends OtherClass<T> {}" }; Files.write(file, Arrays.asList(contents), StandardOpenOption.CREATE); } diff --git a/test/langtools/jdk/jshell/CommandCompletionTest.java b/test/langtools/jdk/jshell/CommandCompletionTest.java index 27746a748b9dff441b9f893726c6c66ead04e007..3a5eb1a46a7ce46d258315ce60b69b9e08793bfe 100644 --- a/test/langtools/jdk/jshell/CommandCompletionTest.java +++ b/test/langtools/jdk/jshell/CommandCompletionTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8144095 8164825 8169818 8153402 8165405 8177079 8178013 8167554 8166232 + * @bug 8144095 8164825 8169818 8153402 8165405 8177079 8178013 8167554 8166232 8277328 * @summary Test Command Completion * @modules jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.main @@ -331,6 +331,22 @@ public class CommandCompletionTest extends ReplToolTesting { ); } + @Test + public void testClassPathWithSpace() throws IOException { + Compiler compiler = new Compiler(); + Path outDir = compiler.getPath("testClassPathWithSpace"); + Path dirWithSpace = Files.createDirectories(outDir.resolve("dir with space")); + Files.createDirectories(dirWithSpace.resolve("nested with space")); + String[] pathArray = new String[] {"dir\\ with\\ space/"}; + String[] pathArray2 = new String[] {"nested\\ with\\ space/"}; + testNoStartUp( + a -> assertCompletion(a, "/env -class-path " + outDir + "/|", false, pathArray), + a -> assertCompletion(a, "/env -class-path " + outDir + "/dir|", false, pathArray), + a -> assertCompletion(a, "/env -class-path " + outDir + "/dir\\ with|", false, pathArray), + a -> assertCompletion(a, "/env -class-path " + outDir + "/dir\\ with\\ space/|", false, pathArray2) + ); + } + @Test public void testUserHome() throws IOException { List<String> completions; @@ -338,8 +354,9 @@ public class CommandCompletionTest extends ReplToolTesting { String selectedFile; try (Stream<Path> content = Files.list(home)) { selectedFile = content.filter(CLASSPATH_FILTER) + .filter(file -> file.getFileName().toString().contains(" ")) .findAny() - .map(file -> file.getFileName().toString()) + .map(file -> file.getFileName().toString().replace(" ", "\\ ")) .orElse(null); } if (selectedFile == null) { @@ -347,8 +364,8 @@ public class CommandCompletionTest extends ReplToolTesting { } try (Stream<Path> content = Files.list(home)) { completions = content.filter(CLASSPATH_FILTER) - .filter(file -> file.getFileName().toString().startsWith(selectedFile)) - .map(file -> file.getFileName().toString() + (Files.isDirectory(file) ? "/" : "")) + .filter(file -> file.getFileName().toString().startsWith(selectedFile.replace("\\ ", " "))) + .map(file -> file.getFileName().toString().replace(" ", "\\ ") + (Files.isDirectory(file) ? "/" : "")) .sorted() .collect(Collectors.toList()); } diff --git a/test/langtools/tools/javac/8278078/InvalidThisAndSuperInConstructorArgTest.java b/test/langtools/tools/javac/8278078/InvalidThisAndSuperInConstructorArgTest.java new file mode 100644 index 0000000000000000000000000000000000000000..eee79e2d5e9895e29db9939d2fe2d7c48052d8df --- /dev/null +++ b/test/langtools/tools/javac/8278078/InvalidThisAndSuperInConstructorArgTest.java @@ -0,0 +1,68 @@ + +import java.util.function.Supplier; + +/** + * @test /nodynamiccopyright/ + * @bug 8278078 + * @summary error: cannot reference super before supertype constructor has been called + * @compile/fail/ref=InvalidThisAndSuperInConstructorArgTest.out -XDrawDiagnostics InvalidThisAndSuperInConstructorArgTest.java + */ +public class InvalidThisAndSuperInConstructorArgTest { + + interface InterfaceWithDefault { + default String get() { + return ""; + } + } + + InvalidThisAndSuperInConstructorArgTest(String s) { + } + + class InnerClass extends AssertionError implements InterfaceWithDefault { + InnerClass() { + super(InnerClass.super.toString()); + } + InnerClass(int i) { + this(InnerClass.super.toString()); + } + InnerClass(boolean b) { + super(InnerClass.this.toString()); + } + InnerClass(double d) { + this(InnerClass.this.toString()); + } + InnerClass(float f) { + super(AssertionError.super.toString()); + } + InnerClass(char ch) { + this(AssertionError.super.toString()); + } + InnerClass(byte b) { + super(AssertionError.this.toString()); + } + InnerClass(Object o) { + this(AssertionError.this.toString()); + } + InnerClass(int[] ii) { + this(InterfaceWithDefault.super.get()); + } + InnerClass(boolean[] bb) { + super(InterfaceWithDefault.this.get()); + } + InnerClass(double[] dd) { + this(InterfaceWithDefault.this.get()); + } + InnerClass(float[] ff) { + super(InterfaceWithDefault.super.get()); + } + InnerClass(char[] chch) { + this(InnerClass.this::toString); + } + InnerClass(String s) { + super(s); + } + InnerClass(Supplier<String> sup) { + super(sup); + } + } +} diff --git a/test/langtools/tools/javac/8278078/InvalidThisAndSuperInConstructorArgTest.out b/test/langtools/tools/javac/8278078/InvalidThisAndSuperInConstructorArgTest.out new file mode 100644 index 0000000000000000000000000000000000000000..1109eb0fdc46bb72be692c2ce7344a5ddc372f75 --- /dev/null +++ b/test/langtools/tools/javac/8278078/InvalidThisAndSuperInConstructorArgTest.out @@ -0,0 +1,14 @@ +InvalidThisAndSuperInConstructorArgTest.java:23:29: compiler.err.cant.ref.before.ctor.called: super +InvalidThisAndSuperInConstructorArgTest.java:26:28: compiler.err.cant.ref.before.ctor.called: super +InvalidThisAndSuperInConstructorArgTest.java:29:29: compiler.err.cant.ref.before.ctor.called: this +InvalidThisAndSuperInConstructorArgTest.java:32:28: compiler.err.cant.ref.before.ctor.called: this +InvalidThisAndSuperInConstructorArgTest.java:35:33: compiler.err.not.encl.class: java.lang.AssertionError +InvalidThisAndSuperInConstructorArgTest.java:38:32: compiler.err.not.encl.class: java.lang.AssertionError +InvalidThisAndSuperInConstructorArgTest.java:41:33: compiler.err.not.encl.class: java.lang.AssertionError +InvalidThisAndSuperInConstructorArgTest.java:44:32: compiler.err.not.encl.class: java.lang.AssertionError +InvalidThisAndSuperInConstructorArgTest.java:47:38: compiler.err.cant.ref.before.ctor.called: super +InvalidThisAndSuperInConstructorArgTest.java:50:39: compiler.err.not.encl.class: InvalidThisAndSuperInConstructorArgTest.InterfaceWithDefault +InvalidThisAndSuperInConstructorArgTest.java:53:38: compiler.err.not.encl.class: InvalidThisAndSuperInConstructorArgTest.InterfaceWithDefault +InvalidThisAndSuperInConstructorArgTest.java:56:39: compiler.err.cant.ref.before.ctor.called: super +InvalidThisAndSuperInConstructorArgTest.java:59:28: compiler.err.cant.ref.before.ctor.called: this +13 errors diff --git a/test/langtools/tools/javac/8278078/ValidThisAndSuperInConstructorArgTest.java b/test/langtools/tools/javac/8278078/ValidThisAndSuperInConstructorArgTest.java new file mode 100644 index 0000000000000000000000000000000000000000..2fe1388420c2690532d31107a993e5cbdaa20a46 --- /dev/null +++ b/test/langtools/tools/javac/8278078/ValidThisAndSuperInConstructorArgTest.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8278078 + * @summary error: cannot reference super before supertype constructor has been called + * @compile ValidThisAndSuperInConstructorArgTest.java + * @run main ValidThisAndSuperInConstructorArgTest + */ +public class ValidThisAndSuperInConstructorArgTest { + + static final String SUPER = "unexpected super call"; + static final String THIS = "unexpected this call"; + + public String get() { + return SUPER; + } + + static class StaticSubClass extends ValidThisAndSuperInConstructorArgTest { + @Override + public String get() { + return THIS; + } + + class InnerClass extends AssertionError { + InnerClass() { + super(StaticSubClass.super.get()); + } + InnerClass(int i) { + this(StaticSubClass.super.get()); + } + InnerClass(boolean b) { + super(StaticSubClass.this.get()); + } + InnerClass(double d) { + this(StaticSubClass.this.get()); + } + InnerClass(String s) { + super(s); + } + void assertThis() { + if (!THIS.equals(getMessage())) throw this; + } + void assertSuper() { + if (!SUPER.equals(getMessage())) throw this; + } + } + } + + public static void main(String...args) { + var test = new StaticSubClass(); + test.new InnerClass().assertSuper(); + test.new InnerClass(1).assertSuper(); + test.new InnerClass(true).assertThis(); + test.new InnerClass(1.0).assertThis(); + } +} diff --git a/test/langtools/tools/javac/T8271079.java b/test/langtools/tools/javac/T8271079.java new file mode 100644 index 0000000000000000000000000000000000000000..9b866f618a771c1058fa7d2fbf58fa95192d12dd --- /dev/null +++ b/test/langtools/tools/javac/T8271079.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8271079 + * @summary JavaFileObject#toUri in MR-JAR returns real path + * @modules java.compiler + * jdk.compiler + * @run main T8271079 + */ + +import java.io.*; +import java.net.*; +import java.nio.charset.StandardCharsets; +import java.nio.file.*; +import java.util.*; +import java.util.jar.JarEntry; +import javax.tools.*; + +public class T8271079 { + + public static void main(String[] args) throws Exception { + new T8271079().run(); + } + + final PrintStream out; + + T8271079() { + this.out = System.out; + } + + void run() throws Exception { + Path mr = generateMultiReleaseJar(); + try { + testT8271079(mr); + } finally { + Files.deleteIfExists(mr); + } + } + + // $ echo 'module hello {}' > module-info.java + // $ javac -d classes --release 9 module-info.java + // $ jar --create --file mr.jar --release 9 -C classes . + Path generateMultiReleaseJar() throws Exception { + Files.writeString(Path.of("module-info.java"), "module hello {}"); + java.util.spi.ToolProvider.findFirst("javac").orElseThrow() + .run(out, System.err, "-d", "classes", "--release", "9", "module-info.java"); + Path mr = Path.of("mr.jar"); + java.util.spi.ToolProvider.findFirst("jar").orElseThrow() + .run(out, System.err, "--create", "--file", mr.toString(), "--release", "9", "-C", "classes", "."); + out.println("Created: " + mr.toUri()); + out.println(" Exists: " + Files.exists(mr)); + return mr; + } + + void testT8271079(Path path) throws Exception { + StandardJavaFileManager fileManager = + ToolProvider.getSystemJavaCompiler() + .getStandardFileManager(null, Locale.ENGLISH, StandardCharsets.UTF_8); + fileManager.setLocationFromPaths(StandardLocation.CLASS_PATH, List.of(path)); + Iterator<String> options = Arrays.asList("--multi-release", "9").iterator(); + fileManager.handleOption(options.next(), options); + + Iterable<JavaFileObject> list = + fileManager.list( + StandardLocation.CLASS_PATH, "", EnumSet.allOf(JavaFileObject.Kind.class), false); + + for (JavaFileObject f : list) { + out.println("JavaFileObject#getName: " + f.getName()); + out.println("JavaFileObject#toUri: " + f.toUri()); + openUsingUri(f.toUri()); + } + System.gc(); // JDK-8224794 + } + + void openUsingUri(URI uri) throws IOException { + URLConnection connection = uri.toURL().openConnection(); + connection.setUseCaches(false); // JDK-8224794 + if (connection instanceof JarURLConnection jar) { + try { + JarEntry entry = jar.getJarEntry(); + out.println("JarEntry#getName: " + entry.getName()); + connection.getInputStream().close(); // JDK-8224794 + } catch (FileNotFoundException e) { + throw e; + } + } + } +} diff --git a/test/langtools/tools/javac/api/TestClientCodeWrapper.java b/test/langtools/tools/javac/api/TestClientCodeWrapper.java index c7f595a451285bba46a8b0f820d10cae22f6c2e0..7c96f29fe5bb91104bde3480457873629233afd7 100644 --- a/test/langtools/tools/javac/api/TestClientCodeWrapper.java +++ b/test/langtools/tools/javac/api/TestClientCodeWrapper.java @@ -62,7 +62,8 @@ public class TestClientCodeWrapper extends JavacTestingAbstractProcessor { defaultFileManager = fm; for (Method m: getMethodsExcept(JavaFileManager.class, - "close", "getJavaFileForInput", "getLocationForModule", "getServiceLoader", "contains")) { + "close", "getJavaFileForInput", "getLocationForModule", "getServiceLoader", + "contains", "getFileForOutput", "siblingFrom")) { test(m); } @@ -370,6 +371,12 @@ public class TestClientCodeWrapper extends JavacTestingAbstractProcessor { return wrap(super.getJavaFileForOutput(location, className, kind, sibling)); } + @Override + public JavaFileObject getJavaFileForOutputForOriginatingFiles(Location location, String className, Kind kind, FileObject... originatingFiles) throws IOException { + throwUserExceptionIfNeeded(fileManagerMethod, "getJavaFileForOutputForOriginatingFiles"); + return wrap(super.getJavaFileForOutputForOriginatingFiles(location, className, kind, originatingFiles)); + } + @Override public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException { throwUserExceptionIfNeeded(fileManagerMethod, "getFileForInput"); @@ -382,6 +389,12 @@ public class TestClientCodeWrapper extends JavacTestingAbstractProcessor { return wrap(super.getFileForOutput(location, packageName, relativeName, sibling)); } + @Override + public FileObject getFileForOutputForOriginatingFiles(Location location, String packageName, String relativeName, FileObject... originatingFiles) throws IOException { + throwUserExceptionIfNeeded(fileManagerMethod, "getFileForOutputForOriginatingFiles"); + return wrap(super.getFileForOutputForOriginatingFiles(location, packageName, relativeName, originatingFiles)); + } + @Override public void flush() throws IOException { throwUserExceptionIfNeeded(fileManagerMethod, "flush"); diff --git a/test/langtools/tools/javac/api/TestGetSourceVersions.java b/test/langtools/tools/javac/api/TestGetSourceVersions.java index 9b0ddb9d6733c4eefa5d21b4e815d61d9a659a87..472c4fe97eda00f54ac642cf1199852fe9479fad 100644 --- a/test/langtools/tools/javac/api/TestGetSourceVersions.java +++ b/test/langtools/tools/javac/api/TestGetSourceVersions.java @@ -35,7 +35,7 @@ * @run main TestGetSourceVersions RELEASE_3 RELEASE_4 RELEASE_5 RELEASE_6 RELEASE_7 * RELEASE_8 RELEASE_9 RELEASE_10 RELEASE_11 RELEASE_12 * RELEASE_13 RELEASE_14 RELEASE_15 RELEASE_16 RELEASE_17 - * RELEASE_18 + * RELEASE_18 RELEASE_19 */ import java.util.EnumSet; diff --git a/test/langtools/tools/javac/classfiles/ClassVersionChecker.java b/test/langtools/tools/javac/classfiles/ClassVersionChecker.java index 4fcc73031966ac41bf6581899e7ee05410f68a90..4e586c32dcb5b61695a254a284eff0434bd03d33 100644 --- a/test/langtools/tools/javac/classfiles/ClassVersionChecker.java +++ b/test/langtools/tools/javac/classfiles/ClassVersionChecker.java @@ -53,7 +53,8 @@ public class ClassVersionChecker { FIFTEEN("15", 59), SIXTEEN("16", 60), SEVENTEEN("17", 61), - EIGHTEEN("18", 62); + EIGHTEEN("18", 62), + NINETEEN("19", 63); private Version(String release, int classFileVer) { this.release = release; diff --git a/test/langtools/tools/javac/classfiles/attributes/lib/TestResult.java b/test/langtools/tools/javac/classfiles/attributes/lib/TestResult.java index 39b727cecea849f142ee8e98ff86ed49d56ac2d9..4c9662f110ff22a7c544f805f4f617c9915ef794 100644 --- a/test/langtools/tools/javac/classfiles/attributes/lib/TestResult.java +++ b/test/langtools/tools/javac/classfiles/attributes/lib/TestResult.java @@ -26,7 +26,7 @@ import java.io.StringWriter; import java.util.*; /** - * This class accumulates test results. Test results can be checked with method @{code checkStatus}. + * This class accumulates test results. Test results can be checked with method {@code checkStatus}. */ public class TestResult extends TestBase { diff --git a/test/langtools/tools/javac/classwriter/IndyCorrectInvocationName.java b/test/langtools/tools/javac/classwriter/IndyCorrectInvocationName.java new file mode 100644 index 0000000000000000000000000000000000000000..36d7b8c2759852adb93c533a56bf15ed3a491fba --- /dev/null +++ b/test/langtools/tools/javac/classwriter/IndyCorrectInvocationName.java @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8277634 + * @summary Verify the correct constantpool entries are created for invokedynamic instructions using + * the same bootstrap and type, but different name. + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.code + * jdk.compiler/com.sun.tools.javac.comp + * jdk.compiler/com.sun.tools.javac.jvm + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.tree + * jdk.compiler/com.sun.tools.javac.util + * jdk.jdeps/com.sun.tools.classfile + * jdk.jdeps/com.sun.tools.javap + * @build toolbox.JarTask toolbox.JavacTask toolbox.JavapTask toolbox.ToolBox + * @run main IndyCorrectInvocationName + */ + +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +import com.sun.source.util.JavacTask; +import com.sun.source.util.Plugin; +import com.sun.source.util.TaskEvent; +import com.sun.source.util.TaskListener; + +import com.sun.tools.classfile.Attribute; +import com.sun.tools.classfile.BootstrapMethods_attribute; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.Code_attribute; +import com.sun.tools.classfile.ConstantPool.CONSTANT_InvokeDynamic_info; +import com.sun.tools.classfile.ConstantPool.CONSTANT_NameAndType_info; +import com.sun.tools.classfile.Instruction; + +import com.sun.tools.javac.api.BasicJavacTask; +import com.sun.tools.javac.code.Symbol; +import com.sun.tools.javac.code.Symbol.MethodSymbol; +import com.sun.tools.javac.code.Symtab; +import com.sun.tools.javac.code.Type; +import com.sun.tools.javac.jvm.PoolConstant; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.JCTree.JCClassDecl; +import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; +import com.sun.tools.javac.tree.JCTree.JCLiteral; +import com.sun.tools.javac.tree.JCTree.JCMethodInvocation; +import com.sun.tools.javac.tree.JCTree.Tag; +import com.sun.tools.javac.tree.TreeMaker; +import com.sun.tools.javac.tree.TreeScanner; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.Names; + +import toolbox.JarTask; +import toolbox.ToolBox; + + +public class IndyCorrectInvocationName implements Plugin { + private static final String NL = System.lineSeparator(); + + public static void main(String... args) throws Exception { + new IndyCorrectInvocationName().run(); + } + + void run() throws Exception { + ToolBox tb = new ToolBox(); + Path pluginClasses = Path.of("plugin-classes"); + tb.writeFile(pluginClasses.resolve("META-INF").resolve("services").resolve(Plugin.class.getName()), + IndyCorrectInvocationName.class.getName() + System.lineSeparator()); + try (DirectoryStream<Path> ds = Files.newDirectoryStream(Path.of(ToolBox.testClasses))) { + for (Path p : ds) { + if (p.getFileName().toString().startsWith("IndyCorrectInvocationName") || + p.getFileName().toString().endsWith(".class")) { + Files.copy(p, pluginClasses.resolve(p.getFileName())); + } + } + } + + Path pluginJar = Path.of("plugin.jar"); + new JarTask(tb, pluginJar) + .baseDir(pluginClasses) + .files(".") + .run(); + + Path src = Path.of("src"); + tb.writeJavaFiles(src, + """ + import java.lang.invoke.CallSite; + import java.lang.invoke.ConstantCallSite; + import java.lang.invoke.MethodHandles; + import java.lang.invoke.MethodHandles.Lookup; + import java.lang.invoke.MethodType; + public class Test{ + private static final String NL = System.lineSeparator(); + private static StringBuilder output = new StringBuilder(); + public static void doRun() { + method("a"); + method("b"); + method("a"); + method("b"); + } + public static String run() { + doRun(); + return output.toString(); + } + public static void method(String name) {} + public static void actualMethod(String name) { + output.append(name).append(NL); + } + public static CallSite bootstrap(Lookup lookup, String name, MethodType type) throws Exception { + return new ConstantCallSite(MethodHandles.lookup() + .findStatic(Test.class, + "actualMethod", + MethodType.methodType(void.class, + String.class)) + .bindTo(name)); + } + } + """); + Path classes = Files.createDirectories(Path.of("classes")); + + new toolbox.JavacTask(tb) + .classpath(pluginJar) + .options("-XDaccessInternalAPI") + .outdir(classes) + .files(tb.findJavaFiles(src)) + .run() + .writeAll(); + + URLClassLoader cl = new URLClassLoader(new URL[] {classes.toUri().toURL()}); + + String actual = (String) cl.loadClass("Test") + .getMethod("run") + .invoke(null); + String expected = "a" + NL + "b" + NL + "a" + NL +"b" + NL; + if (!Objects.equals(actual, expected)) { + throw new AssertionError("expected: " + expected + "; but got: " + actual); + } + + Path testClass = classes.resolve("Test.class"); + ClassFile cf = ClassFile.read(testClass); + BootstrapMethods_attribute bootAttr = + (BootstrapMethods_attribute) cf.attributes.get(Attribute.BootstrapMethods); + if (bootAttr.bootstrap_method_specifiers.length != 1) { + throw new AssertionError("Incorrect number of bootstrap methods: " + + bootAttr.bootstrap_method_specifiers.length); + } + Code_attribute codeAttr = + (Code_attribute) cf.methods[1].attributes.get(Attribute.Code); + Set<Integer> seenBootstraps = new HashSet<>(); + Set<Integer> seenNameAndTypes = new HashSet<>(); + Set<String> seenNames = new HashSet<>(); + for (Instruction i : codeAttr.getInstructions()) { + switch (i.getOpcode()) { + case INVOKEDYNAMIC -> { + int idx = i.getUnsignedShort(1); + CONSTANT_InvokeDynamic_info dynamicInfo = + (CONSTANT_InvokeDynamic_info) cf.constant_pool.get(idx); + seenBootstraps.add(dynamicInfo.bootstrap_method_attr_index); + seenNameAndTypes.add(dynamicInfo.name_and_type_index); + CONSTANT_NameAndType_info nameAndTypeInfo = + cf.constant_pool.getNameAndTypeInfo(dynamicInfo.name_and_type_index); + seenNames.add(nameAndTypeInfo.getName()); + } + case RETURN -> {} + default -> throw new AssertionError("Unexpected instruction: " + i.getOpcode()); + } + } + if (seenBootstraps.size() != 1) { + throw new AssertionError("Unexpected bootstraps: " + seenBootstraps); + } + if (seenNameAndTypes.size() != 2) { + throw new AssertionError("Unexpected names and types: " + seenNameAndTypes); + } + if (!seenNames.equals(Set.of("a", "b"))) { + throw new AssertionError("Unexpected names and types: " + seenNames); + } + } + + // Plugin impl... + + @Override + public String getName() { return "IndyCorrectInvocationName"; } + + @Override + public void init(JavacTask task, String... args) { + Context c = ((BasicJavacTask) task).getContext(); + task.addTaskListener(new TaskListener() { + @Override + public void started(TaskEvent e) { + if (e.getKind() == TaskEvent.Kind.GENERATE) { + convert(c, (JCCompilationUnit) e.getCompilationUnit()); + } + } + }); + } + + @Override + public boolean autoStart() { + return true; + } + + private void convert(Context context, JCCompilationUnit toplevel) { + TreeMaker make = TreeMaker.instance(context); + Names names = Names.instance(context); + Symtab syms = Symtab.instance(context); + new TreeScanner() { + MethodSymbol bootstrap; + @Override + public void visitClassDef(JCClassDecl tree) { + bootstrap = (MethodSymbol) tree.sym.members().getSymbolsByName(names.fromString("bootstrap")).iterator().next(); + super.visitClassDef(tree); + } + @Override + public void visitApply(JCMethodInvocation tree) { + if (tree.args.size() == 1 && tree.args.head.hasTag(Tag.LITERAL)) { + String name = (String) ((JCLiteral) tree.args.head).value; + Type.MethodType indyType = new Type.MethodType( + com.sun.tools.javac.util.List.nil(), + syms.voidType, + com.sun.tools.javac.util.List.nil(), + syms.methodClass + ); + Symbol.DynamicMethodSymbol dynSym = new Symbol.DynamicMethodSymbol(names.fromString(name), + syms.noSymbol, + bootstrap.asHandle(), + indyType, + new PoolConstant.LoadableConstant[0]); + + JCTree.JCFieldAccess qualifier = make.Select(make.QualIdent(bootstrap.owner), dynSym.name); + qualifier.sym = dynSym; + qualifier.type = syms.voidType; + tree.meth = qualifier; + tree.args = com.sun.tools.javac.util.List.nil(); + tree.type = syms.voidType; + } + super.visitApply(tree); + } + + }.scan(toplevel); + } + +} diff --git a/test/langtools/tools/javac/diags/examples/LambdaDeduplicate.java b/test/langtools/tools/javac/diags/examples/LambdaDeduplicate.java index 8dda7bb2dd9d93e28a5d89211d977db891cbb979..cf39f9ffb758c2e01e5c596bfde12a1bd6943717 100644 --- a/test/langtools/tools/javac/diags/examples/LambdaDeduplicate.java +++ b/test/langtools/tools/javac/diags/examples/LambdaDeduplicate.java @@ -23,7 +23,7 @@ // key: compiler.note.verbose.l2m.deduplicate -// options: --debug=dumpLambdaToMethodDeduplication +// options: -g:none --debug=dumpLambdaToMethodDeduplication import java.util.function.Function; diff --git a/test/langtools/tools/javac/lambda/deduplication/DeduplicationDebugInfo.java b/test/langtools/tools/javac/lambda/deduplication/DeduplicationDebugInfo.java new file mode 100644 index 0000000000000000000000000000000000000000..2302b8f431d3b57d214b6a672016722e4e047b8e --- /dev/null +++ b/test/langtools/tools/javac/lambda/deduplication/DeduplicationDebugInfo.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021, Google LLC. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test 8275233 + * @summary Incorrect line number reported in exception stack trace thrown from a lambda expression + * @compile/ref=DeduplicationDebugInfo.out -XDrawDiagnostics -XDdebug.dumpLambdaToMethodDeduplication -g:none DeduplicationDebugInfo.java + * @compile/ref=DeduplicationDebugInfo_none.out -XDrawDiagnostics -XDdebug.dumpLambdaToMethodDeduplication DeduplicationDebugInfo.java + * @compile/ref=DeduplicationDebugInfo_none.out -XDrawDiagnostics -XDdebug.dumpLambdaToMethodDeduplication -g:lines DeduplicationDebugInfo.java + * @compile/ref=DeduplicationDebugInfo_none.out -XDrawDiagnostics -XDdebug.dumpLambdaToMethodDeduplication -g:vars DeduplicationDebugInfo.java + * @compile/ref=DeduplicationDebugInfo_none.out -XDrawDiagnostics -XDdebug.dumpLambdaToMethodDeduplication -g:lines,vars DeduplicationDebugInfo.java + */ + +import java.util.function.Function; + +class DeduplicationDebugInfoTest { + void f() { + Function<Object, Integer> f = x -> x.hashCode(); + Function<Object, Integer> g = x -> x.hashCode(); + } +} diff --git a/test/langtools/tools/javac/lambda/deduplication/DeduplicationDebugInfo.out b/test/langtools/tools/javac/lambda/deduplication/DeduplicationDebugInfo.out new file mode 100644 index 0000000000000000000000000000000000000000..f428fe28846675bad558eda19e0f18e3d15ca8fd --- /dev/null +++ b/test/langtools/tools/javac/lambda/deduplication/DeduplicationDebugInfo.out @@ -0,0 +1 @@ +DeduplicationDebugInfo.java:39:39: compiler.note.verbose.l2m.deduplicate: lambda$f$0(java.lang.Object) diff --git a/test/langtools/tools/javac/lambda/deduplication/DeduplicationDebugInfo_none.out b/test/langtools/tools/javac/lambda/deduplication/DeduplicationDebugInfo_none.out new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/test/langtools/tools/javac/lambda/deduplication/DeduplicationTest.java b/test/langtools/tools/javac/lambda/deduplication/DeduplicationTest.java index 14d0b88f09e40b525a492ee77f8741ba4ccfc0be..44c200e62261e3cb4069d882d69ba1b1ec4a6e54 100644 --- a/test/langtools/tools/javac/lambda/deduplication/DeduplicationTest.java +++ b/test/langtools/tools/javac/lambda/deduplication/DeduplicationTest.java @@ -93,6 +93,7 @@ public class DeduplicationTest { Arrays.asList( "-d", ".", + "-g:none", "-XDdebug.dumpLambdaToMethodDeduplication", "-XDdebug.dumpLambdaToMethodStats"), null, diff --git a/test/langtools/tools/javac/launcher/SourceLauncherTest.java b/test/langtools/tools/javac/launcher/SourceLauncherTest.java index 7507a6d9c276bf472dd8f9e0d1c4a807bf050b40..1b8fc23e67979e9228852680992cc7e689e0fe7e 100644 --- a/test/langtools/tools/javac/launcher/SourceLauncherTest.java +++ b/test/langtools/tools/javac/launcher/SourceLauncherTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8192920 8204588 8246774 8248843 8268869 + * @bug 8192920 8204588 8246774 8248843 8268869 8235876 * @summary Test source launcher * @library /tools/lib * @modules jdk.compiler/com.sun.tools.javac.api @@ -630,6 +630,20 @@ public class SourceLauncherTest extends TestRunner { } } + @Test + public void testNoOptionsWarnings(Path base) throws IOException { + tb.writeJavaFiles(base, "public class Main { public static void main(String... args) {}}"); + String log = new JavaTask(tb) + .vmOptions("--source", "7") + .className(base.resolve("Main.java").toString()) + .run(Task.Expect.SUCCESS) + .getOutput(Task.OutputKind.STDERR); + + if (log.contains("warning: [options]")) { + error("Unexpected options warning in error output: " + log); + } + } + void testError(Path file, String expectStdErr, String expectFault) throws IOException { Result r = run(file, Collections.emptyList(), List.of("1", "2", "3")); checkEmpty("stdout", r.stdOut); diff --git a/test/langtools/tools/javac/lib/JavacTestingAbstractProcessor.java b/test/langtools/tools/javac/lib/JavacTestingAbstractProcessor.java index 634a468d5591e29dee8487685035babc857edd31..03e065828961cb412239ce6fd48067ceb7e21d10 100644 --- a/test/langtools/tools/javac/lib/JavacTestingAbstractProcessor.java +++ b/test/langtools/tools/javac/lib/JavacTestingAbstractProcessor.java @@ -112,7 +112,7 @@ public abstract class JavacTestingAbstractProcessor extends AbstractProcessor { * corresponding platform visitor type. */ - @SupportedSourceVersion(RELEASE_18) + @SupportedSourceVersion(RELEASE_19) public static abstract class AbstractAnnotationValueVisitor<R, P> extends AbstractAnnotationValueVisitor14<R, P> { /** @@ -123,7 +123,7 @@ public abstract class JavacTestingAbstractProcessor extends AbstractProcessor { } } - @SupportedSourceVersion(RELEASE_18) + @SupportedSourceVersion(RELEASE_19) public static abstract class AbstractElementVisitor<R, P> extends AbstractElementVisitor14<R, P> { /** * Constructor for concrete subclasses to call. @@ -133,7 +133,7 @@ public abstract class JavacTestingAbstractProcessor extends AbstractProcessor { } } - @SupportedSourceVersion(RELEASE_18) + @SupportedSourceVersion(RELEASE_19) public static abstract class AbstractTypeVisitor<R, P> extends AbstractTypeVisitor14<R, P> { /** * Constructor for concrete subclasses to call. @@ -143,7 +143,7 @@ public abstract class JavacTestingAbstractProcessor extends AbstractProcessor { } } - @SupportedSourceVersion(RELEASE_18) + @SupportedSourceVersion(RELEASE_19) public static class ElementKindVisitor<R, P> extends ElementKindVisitor14<R, P> { /** * Constructor for concrete subclasses; uses {@code null} for the @@ -164,7 +164,7 @@ public abstract class JavacTestingAbstractProcessor extends AbstractProcessor { } } - @SupportedSourceVersion(RELEASE_18) + @SupportedSourceVersion(RELEASE_19) public static class ElementScanner<R, P> extends ElementScanner14<R, P> { /** * Constructor for concrete subclasses; uses {@code null} for the @@ -183,7 +183,7 @@ public abstract class JavacTestingAbstractProcessor extends AbstractProcessor { } } - @SupportedSourceVersion(RELEASE_18) + @SupportedSourceVersion(RELEASE_19) public static class SimpleAnnotationValueVisitor<R, P> extends SimpleAnnotationValueVisitor14<R, P> { /** * Constructor for concrete subclasses; uses {@code null} for the @@ -204,7 +204,7 @@ public abstract class JavacTestingAbstractProcessor extends AbstractProcessor { } } - @SupportedSourceVersion(RELEASE_18) + @SupportedSourceVersion(RELEASE_19) public static class SimpleElementVisitor<R, P> extends SimpleElementVisitor14<R, P> { /** * Constructor for concrete subclasses; uses {@code null} for the @@ -225,7 +225,7 @@ public abstract class JavacTestingAbstractProcessor extends AbstractProcessor { } } - @SupportedSourceVersion(RELEASE_18) + @SupportedSourceVersion(RELEASE_19) public static class SimpleTypeVisitor<R, P> extends SimpleTypeVisitor14<R, P> { /** * Constructor for concrete subclasses; uses {@code null} for the @@ -246,7 +246,7 @@ public abstract class JavacTestingAbstractProcessor extends AbstractProcessor { } } - @SupportedSourceVersion(RELEASE_18) + @SupportedSourceVersion(RELEASE_19) public static class TypeKindVisitor<R, P> extends TypeKindVisitor14<R, P> { /** * Constructor for concrete subclasses to call; uses {@code null} diff --git a/test/langtools/tools/javac/optimizeOuterThis/OptimizeOuterThis.java b/test/langtools/tools/javac/optimizeOuterThis/OptimizeOuterThis.java index 1a01d61f94ec8c52c2bb67ae05ab40085b31b77c..a42508e2a0a0d39adf5d7274dd96e76a79761400 100644 --- a/test/langtools/tools/javac/optimizeOuterThis/OptimizeOuterThis.java +++ b/test/langtools/tools/javac/optimizeOuterThis/OptimizeOuterThis.java @@ -64,7 +64,7 @@ public class OptimizeOuterThis extends InnerClasses { checkInner(N0.N1.N2.N3.N4.N5.class, false); checkInner(SerializableCapture.class, true); - checkInner(SerializableWithSerialVersionUID.class, false); + checkInner(SerializableWithSerialVersionUID.class, true); checkInner(SerializableWithInvalidSerialVersionUIDType.class, true); checkInner(SerializableWithInvalidSerialVersionUIDNonFinal.class, true); checkInner(SerializableWithInvalidSerialVersionUIDNonStatic.class, true); diff --git a/test/langtools/tools/javac/options/modes/AtFilesTest.java b/test/langtools/tools/javac/options/modes/AtFilesTest.java index 761e20b53021e6f74c468a6465195cccd7272349..5cf5c2acbaf79ddc8a5a4d8982b0c1f1f13d50ab 100644 --- a/test/langtools/tools/javac/options/modes/AtFilesTest.java +++ b/test/langtools/tools/javac/options/modes/AtFilesTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 8044859 + * @bug 8044859 8272728 * @summary test support for at-files * @modules jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.file @@ -33,6 +33,7 @@ * @run main AtFilesTest */ +import com.sun.tools.javac.main.Main; import java.io.IOException; public class AtFilesTest extends OptionModesTester { @@ -60,4 +61,16 @@ public class AtFilesTest extends OptionModesTester { runParse(opts, files) .checkIllegalArgumentException(); } + + @Test + void testAtFilesMustNotContainOptionJ() throws IOException { + writeFile("args", "-J-verbose"); + + String[] opts = { "@args", "-version" }; + String[] files = { }; + + runMain(opts, files) + .checkResult(Main.Result.CMDERR.exitCode) + .checkLog(Log.DIRECT, "-J-verbose"); + } } diff --git a/test/langtools/tools/javac/patterns/Domination.java b/test/langtools/tools/javac/patterns/Domination.java index b5283fe31a7ae31aa38bdf7b1ee9a26ef3a563f9..683758c297caf416318c807cdd609af6f25329f3 100644 --- a/test/langtools/tools/javac/patterns/Domination.java +++ b/test/langtools/tools/javac/patterns/Domination.java @@ -68,6 +68,20 @@ public class Domination { } } + int testDominatesStringConstant2(String str) { + switch (str) { + case (String s && s.isEmpty()): return 1; + case "": return -1; + } + } + + int testDominatesStringConstant3(String str) { + switch (str) { + case (String s && !s.isEmpty()): return 1; + case "": return -1; + } + } + int testDominatesIntegerConstant(Integer i) { switch (i) { case Integer j: return 1; @@ -75,6 +89,20 @@ public class Domination { } } + int testDominatesIntegerConstant2(Integer i) { + switch (i) { + case (Integer j && j == 0): return 1; + case 0: return -1; + } + } + + int testDominatesIntegerConstant3(Integer i) { + switch (i) { + case (Integer j && j == 1): return 1; + case 0: return -1; + } + } + int testDominatesEnumConstant() { enum E { A, B; @@ -86,4 +114,26 @@ public class Domination { } } + int testDominatesEnumConstant2() { + enum E { + A, B; + } + E e = E.A; + switch (e) { + case (E d && d == E.A): return 1; + case A: return -1; + } + } + + int testDominatesEnumConstant3() { + enum E { + A, B; + } + E e = E.A; + switch (e) { + case (E d && d == E.B): return 1; + case A: return -1; + } + } + } diff --git a/test/langtools/tools/javac/patterns/Domination.out b/test/langtools/tools/javac/patterns/Domination.out index 3d1aa46bab0fcf060edd8d64312a36c767253756..80b95b8527d84b41cb5cf953da9cf3f717760048 100644 --- a/test/langtools/tools/javac/patterns/Domination.out +++ b/test/langtools/tools/javac/patterns/Domination.out @@ -3,7 +3,13 @@ Domination.java:43:18: compiler.err.pattern.dominated Domination.java:51:18: compiler.err.pattern.dominated Domination.java:67:18: compiler.err.pattern.dominated Domination.java:74:18: compiler.err.pattern.dominated -Domination.java:85:18: compiler.err.pattern.dominated +Domination.java:81:18: compiler.err.pattern.dominated +Domination.java:88:18: compiler.err.pattern.dominated +Domination.java:95:18: compiler.err.pattern.dominated +Domination.java:102:18: compiler.err.pattern.dominated +Domination.java:113:18: compiler.err.pattern.dominated +Domination.java:124:18: compiler.err.pattern.dominated +Domination.java:135:18: compiler.err.pattern.dominated - compiler.note.preview.filename: Domination.java, DEFAULT - compiler.note.preview.recompile -6 errors +12 errors diff --git a/test/langtools/tools/javac/patterns/EnumTypeChanges.java b/test/langtools/tools/javac/patterns/EnumTypeChanges.java index f6a0aafe6e7ef6468ab0ce0f35b72d9027bb3421..8d16efd796551eb01d29e2b538344cf67835d4c6 100644 --- a/test/langtools/tools/javac/patterns/EnumTypeChanges.java +++ b/test/langtools/tools/javac/patterns/EnumTypeChanges.java @@ -52,8 +52,8 @@ public class EnumTypeChanges { String statementEnum(EnumTypeChangesEnum e) { switch (e) { case A -> { return "A"; } - case EnumTypeChangesEnum e1 && false -> throw new AssertionError(); case B -> { return "B"; } + case EnumTypeChangesEnum e1 && false -> throw new AssertionError(); default -> { return "D"; } } } @@ -61,8 +61,8 @@ public class EnumTypeChanges { String expressionEnum(EnumTypeChangesEnum e) { return switch (e) { case A -> "A"; - case EnumTypeChangesEnum e1 && false -> throw new AssertionError(); case B -> "B"; + case EnumTypeChangesEnum e1 && false -> throw new AssertionError(); default -> "D"; }; } diff --git a/test/langtools/tools/javac/patterns/Exhaustiveness.java b/test/langtools/tools/javac/patterns/Exhaustiveness.java index 9728fd83f48b0e2aa677d0d6f79a7a1b2e4ba787..b7db66c3231a256351acfecb3b5fbc11ee22fbc9 100644 --- a/test/langtools/tools/javac/patterns/Exhaustiveness.java +++ b/test/langtools/tools/javac/patterns/Exhaustiveness.java @@ -369,102 +369,6 @@ public class Exhaustiveness extends TestRunner { """); } - @Test - public void testInaccessiblePermitted(Path base) throws IOException { - Path current = base.resolve("."); - Path libSrc = current.resolve("lib-src"); - - tb.writeJavaFiles(libSrc, - """ - package lib; - public sealed interface S permits A, B {} - """, - """ - package lib; - public final class A implements S {} - """, - """ - package lib; - final class B implements S {} - """); - - Path libClasses = current.resolve("libClasses"); - - Files.createDirectories(libClasses); - - new JavacTask(tb) - .options("--enable-preview", - "-source", JAVA_VERSION) - .outdir(libClasses) - .files(tb.findJavaFiles(libSrc)) - .run(); - - Path src = current.resolve("src"); - tb.writeJavaFiles(src, - """ - package test; - import lib.*; - public class Test { - private int test(S obj) { - return switch (obj) { - case A a -> 0; - }; - } - } - """); - - Path classes = current.resolve("libClasses"); - - Files.createDirectories(libClasses); - - var log = - new JavacTask(tb) - .options("--enable-preview", - "-source", JAVA_VERSION, - "-XDrawDiagnostics", - "-Xlint:-preview", - "--class-path", libClasses.toString()) - .outdir(classes) - .files(tb.findJavaFiles(src)) - .run(Task.Expect.FAIL) - .writeAll() - .getOutputLines(Task.OutputKind.DIRECT); - - List<String> expectedErrors = List.of( - "Test.java:5:16: compiler.err.not.exhaustive", - "- compiler.note.preview.filename: Test.java, DEFAULT", - "- compiler.note.preview.recompile", - "1 error"); - - if (!expectedErrors.equals(log)) { - throw new AssertionError("Incorrect errors, expected: " + expectedErrors + - ", actual: " + log); - } - - Path bClass = libClasses.resolve("lib").resolve("B.class"); - - Files.delete(bClass); - - var log2 = - new JavacTask(tb) - .options("--enable-preview", - "-source", JAVA_VERSION, - "-XDrawDiagnostics", - "-Xlint:-preview", - "--class-path", libClasses.toString()) - .outdir(classes) - .files(tb.findJavaFiles(src)) - .run(Task.Expect.FAIL) - .writeAll() - .getOutputLines(Task.OutputKind.DIRECT); - - if (!expectedErrors.equals(log2)) { - throw new AssertionError("Incorrect errors, expected: " + expectedErrors + - ", actual: " + log2); - } - - } - @Test public void testExhaustiveStatement1(Path base) throws Exception { doTest(base, @@ -799,6 +703,94 @@ public class Exhaustiveness extends TestRunner { """); } + @Test + public void testOnlyApplicable(Path base) throws Exception { + record TestCase(String cases, String... errors) {} + TestCase[] subCases = new TestCase[] { + new TestCase(""" + case C3<Integer> c -> {} + case C5<Integer, ?> c -> {} + case C6<?, Integer> c -> {} + """), //OK + new TestCase(""" + case C5<Integer, ?> c -> {} + case C6<?, Integer> c -> {} + """, + "Test.java:11:9: compiler.err.not.exhaustive.statement", + "- compiler.note.preview.filename: Test.java, DEFAULT", + "- compiler.note.preview.recompile", + "1 error"), + new TestCase(""" + case C3<Integer> c -> {} + case C6<?, Integer> c -> {} + """, + "Test.java:11:9: compiler.err.not.exhaustive.statement", + "- compiler.note.preview.filename: Test.java, DEFAULT", + "- compiler.note.preview.recompile", + "1 error"), + new TestCase(""" + case C3<Integer> c -> {} + case C5<Integer, ?> c -> {} + """, + "Test.java:11:9: compiler.err.not.exhaustive.statement", + "- compiler.note.preview.filename: Test.java, DEFAULT", + "- compiler.note.preview.recompile", + "1 error"), + new TestCase(""" + case C1 c -> {} + case C3<Integer> c -> {} + case C5<Integer, ?> c -> {} + case C6<?, Integer> c -> {} + """, + "Test.java:12:18: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: test.Test.I<java.lang.Integer>, test.Test.C1)", + "- compiler.note.preview.filename: Test.java, DEFAULT", + "- compiler.note.preview.recompile", + "1 error"), + new TestCase(""" + case C2<?> c -> {} + case C3<Integer> c -> {} + case C5<Integer, ?> c -> {} + case C6<?, Integer> c -> {} + """, + "Test.java:12:18: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: test.Test.I<java.lang.Integer>, test.Test.C2<?>)", + "- compiler.note.preview.filename: Test.java, DEFAULT", + "- compiler.note.preview.recompile", + "1 error"), + new TestCase(""" + case C4<?, ?> c -> {} + case C3<Integer> c -> {} + case C5<Integer, ?> c -> {} + case C6<?, Integer> c -> {} + """, + "Test.java:12:18: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: test.Test.I<java.lang.Integer>, test.Test.C4<?,?>)", + "- compiler.note.preview.filename: Test.java, DEFAULT", + "- compiler.note.preview.recompile", + "1 error"), + }; + for (TestCase tc : subCases) { + doTest(base, + new String[0], + """ + package test; + public class Test { + sealed interface I<T> {} + final class C1 implements I<String> {} + final class C2<T> implements I<String> {} + final class C3<T> implements I<T> {} + final class C4<T, E> implements I<String> {} + final class C5<T, E> implements I<T> {} + final class C6<T, E> implements I<E> {} + void t(I<Integer> i) { + switch (i) { + ${cases} + } + } + } + """.replace("${cases}", tc.cases), + tc.errors); + } + } + private void doTest(Path base, String[] libraryCode, String testCode, String... expectedErrors) throws IOException { Path current = base.resolve("."); Path libClasses = current.resolve("libClasses"); diff --git a/test/langtools/tools/javac/patterns/SwitchErrors.java b/test/langtools/tools/javac/patterns/SwitchErrors.java index ddeca570d3aa1a09dda89aec49bcd672bb7d2507..61f544a52c0433c06ba6691131581d4e1837ab15 100644 --- a/test/langtools/tools/javac/patterns/SwitchErrors.java +++ b/test/langtools/tools/javac/patterns/SwitchErrors.java @@ -185,7 +185,16 @@ public class SwitchErrors { default -> null; }; } - void test8269146a(Integer i) { + void test8269146a1(Integer i) { + switch (i) { + //error - illegal combination of pattern and constant: + case 1, Integer o && o != null: + break; + default: + break; + } + } + void test8269146a2(Integer i) { switch (i) { //error - illegal combination of pattern and constant: case Integer o && o != null, 1: @@ -210,7 +219,14 @@ public class SwitchErrors { break; } } - void test8269301(Integer i) { + void test8269301a(Integer i) { + switch (i) { + //error - illegal combination of pattern, constant and default + case 1, Integer o && o != null, default: + break; + } + } + void test8269301b(Integer i) { switch (i) { //error - illegal combination of pattern, constant and default case Integer o && o != null, 1, default: diff --git a/test/langtools/tools/javac/patterns/SwitchErrors.out b/test/langtools/tools/javac/patterns/SwitchErrors.out index 9c4a8ff677f4f5a8888de4723e42dd3e47469506..4679651c800c64e07da8844bb02d9b782c377029 100644 --- a/test/langtools/tools/javac/patterns/SwitchErrors.out +++ b/test/langtools/tools/javac/patterns/SwitchErrors.out @@ -31,12 +31,15 @@ SwitchErrors.java:160:18: compiler.err.pattern.dominated SwitchErrors.java:172:18: compiler.err.pattern.expected SwitchErrors.java:178:76: compiler.err.cant.resolve.location: kindname.variable, n, , , (compiler.misc.location: kindname.class, SwitchErrors, null) SwitchErrors.java:184:71: compiler.err.cant.resolve.location: kindname.variable, n, , , (compiler.misc.location: kindname.class, SwitchErrors, null) -SwitchErrors.java:191:42: compiler.err.flows.through.from.pattern -SwitchErrors.java:200:24: compiler.err.flows.through.to.pattern -SwitchErrors.java:209:29: compiler.err.total.pattern.and.default -SwitchErrors.java:216:42: compiler.err.flows.through.from.pattern -SwitchErrors.java:216:45: compiler.err.flows.through.from.pattern -SwitchErrors.java:228:18: compiler.err.duplicate.total.pattern +SwitchErrors.java:191:21: compiler.err.flows.through.to.pattern +SwitchErrors.java:200:42: compiler.err.pattern.dominated +SwitchErrors.java:209:24: compiler.err.flows.through.to.pattern +SwitchErrors.java:218:29: compiler.err.total.pattern.and.default +SwitchErrors.java:225:21: compiler.err.flows.through.to.pattern +SwitchErrors.java:225:45: compiler.err.flows.through.from.pattern +SwitchErrors.java:232:42: compiler.err.pattern.dominated +SwitchErrors.java:232:45: compiler.err.flows.through.from.pattern +SwitchErrors.java:244:18: compiler.err.duplicate.total.pattern SwitchErrors.java:9:9: compiler.err.not.exhaustive.statement SwitchErrors.java:15:9: compiler.err.not.exhaustive.statement SwitchErrors.java:21:9: compiler.err.not.exhaustive.statement @@ -48,7 +51,7 @@ SwitchErrors.java:91:9: compiler.err.not.exhaustive.statement SwitchErrors.java:97:9: compiler.err.not.exhaustive.statement SwitchErrors.java:104:9: compiler.err.not.exhaustive.statement SwitchErrors.java:164:9: compiler.err.not.exhaustive.statement -SwitchErrors.java:221:9: compiler.err.not.exhaustive.statement +SwitchErrors.java:237:9: compiler.err.not.exhaustive.statement - compiler.note.preview.filename: SwitchErrors.java, DEFAULT - compiler.note.preview.recompile -51 errors +54 errors diff --git a/test/langtools/tools/javac/patterns/Switches.java b/test/langtools/tools/javac/patterns/Switches.java index cf9858e7d0a07ea73db8bd1b9b8412c7b6d8d4c5..e4c1bd6edb452b934e5ac684c248405b9820fe8e 100644 --- a/test/langtools/tools/javac/patterns/Switches.java +++ b/test/langtools/tools/javac/patterns/Switches.java @@ -28,7 +28,7 @@ import java.util.function.Function; /* * @test - * @bug 8262891 8268333 8268896 8269802 8269808 8270151 8269113 + * @bug 8262891 8268333 8268896 8269802 8269808 8270151 8269113 8277864 * @summary Check behavior of pattern switches. * @compile --enable-preview -source ${jdk.version} Switches.java * @run main/othervm --enable-preview Switches @@ -85,6 +85,9 @@ public class Switches { assertEquals(2, switchOverNull1()); assertEquals(2, switchOverNull2()); assertEquals(2, switchOverNull3()); + assertEquals(5, switchOverPrimitiveInt(0)); + assertEquals(7, switchOverPrimitiveInt(1)); + assertEquals(9, switchOverPrimitiveInt(2)); } void run(Function<Object, Integer> mapper) { @@ -265,8 +268,8 @@ public class Switches { switch (e) { case A: return "a"; case B: return "b"; - case E x && "A".equals(x.name()): return "broken"; case C: return String.valueOf(e); + case E x && "A".equals(x.name()): return "broken"; case null, E x: return String.valueOf(x); } } @@ -275,8 +278,8 @@ public class Switches { return switch (e) { case A -> "a"; case B -> "b"; - case E x && "A".equals(x.name()) -> "broken"; case C -> String.valueOf(e); + case E x && "A".equals(x.name()) -> "broken"; case null, E x -> String.valueOf(x); }; } @@ -286,8 +289,7 @@ public class Switches { case A: return "a"; case B: return "b"; case E x && "C".equals(x.name()): return "C"; - case C: return "broken"; - case null, E x: return String.valueOf(x); + case null, E x: return e == E.C ? "broken" : String.valueOf(x); } } @@ -296,8 +298,7 @@ public class Switches { case A -> "a"; case B -> "b"; case E x && "C".equals(x.name()) -> "C"; - case C -> "broken"; - case null, E x -> String.valueOf(x); + case null, E x -> e == E.C ? "broken" : String.valueOf(x); }; } @@ -306,8 +307,7 @@ public class Switches { case A: return "a"; case B: return "b"; case Object x && "C".equals(x.toString()): return "C"; - case C: return "broken"; - case null, E x: return String.valueOf(x); + case null, E x: return e == E.C ? "broken" : String.valueOf(x); } } @@ -316,8 +316,7 @@ public class Switches { case A -> "a"; case B -> "b"; case Object x && "C".equals(x.toString()) -> "C"; - case C -> "broken"; - case null, E x -> String.valueOf(x); + case null, E x -> e == E.C ? "broken" : String.valueOf(x); }; } @@ -326,8 +325,7 @@ public class Switches { case A: return "a"; case B: return "b"; case Runnable x && "C".equals(x.toString()): return "C"; - case C: return "broken"; - case null, E x: return String.valueOf(x); + case null, E x: return e == E.C ? "broken" : String.valueOf(x); } } @@ -336,8 +334,7 @@ public class Switches { case A -> "a"; case B -> "b"; case Runnable x && "C".equals(x.toString()) -> "C"; - case C -> "broken"; - case null, E x -> String.valueOf(x); + case null, E x -> e == E.C ? "broken" : String.valueOf(x); }; } @@ -346,8 +343,7 @@ public class Switches { case "A": return "a"; case Switches.ConstantClassClash: return "b"; case String x && "C".equals(x): return "C"; - case "C": return "broken"; - case null, String x: return String.valueOf(x); + case null, String x: return "C".equals(x) ? "broken" : String.valueOf(x); } } @@ -356,8 +352,7 @@ public class Switches { case "A" -> "a"; case ConstantClassClash -> "b"; case String x && "C".equals(x) -> "C"; - case "C" -> "broken"; - case null, String x -> String.valueOf(x); + case null, String x -> e == E.C ? "broken" : String.valueOf(x); }; } @@ -366,8 +361,7 @@ public class Switches { case 0: return "a"; case 1: return "b"; case Integer x && x.equals(2): return "C"; - case 2: return "broken"; - case null, Integer x: return String.valueOf(x); + case null, Integer x: return Objects.equals(x, 2) ? "broken" : String.valueOf(x); } } @@ -376,8 +370,7 @@ public class Switches { case 0 -> "a"; case 1 -> "b"; case Integer x && x.equals(2) -> "C"; - case 2 -> "broken"; - case null, Integer x -> String.valueOf(x); + case null, Integer x -> Objects.equals(x, 2) ? "broken" : String.valueOf(x); }; } @@ -412,7 +405,6 @@ public class Switches { switch (i) { case Integer o && o != null: r = 1; - case -1: r = 1; case null, default: r = 2; } @@ -424,7 +416,6 @@ public class Switches { int r = switch (i) { case Integer o && o != null: r = 1; - case -1: r = 1; case null, default: r = 2; yield r; @@ -603,6 +594,14 @@ public class Switches { }; } + private int switchOverPrimitiveInt(Integer i) { + return switch (i) { + case 0 -> 5 + 0; + case Integer j && j == 1 -> 6 + j; + case Integer j -> 7 + j; + }; + } + //verify that for cases like: //case ConstantClassClash -> //ConstantClassClash is interpreted as a field, not as a class diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicFlag.java b/test/langtools/tools/javac/platform/NonExportedSuperTypes.java similarity index 64% rename from test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicFlag.java rename to test/langtools/tools/javac/platform/NonExportedSuperTypes.java index d505ddbbb9a70af2ec93711fe53ec9e7dfdbe525..b3f17fd6e3c45df11a61ac388ee7f0b635b4dfaf 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicFlag.java +++ b/test/langtools/tools/javac/platform/NonExportedSuperTypes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -19,21 +19,23 @@ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. - * */ /* * @test - * @summary The DynamicDumpShareSpaces flag is internal, setting it at the command line should have no effect. - * @requires vm.cds - * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds - * @compile ../test-classes/Hello.java - * @run driver DynamicFlag + * @bug 8277106 + * @summary Verify no error is when compiling a class whose supertype is not exported. + * @modules jdk.compiler + * jdk.jfr + * @compile --release 17 NonExportedSuperTypes.java */ -public class DynamicFlag { - public static void main(String[] args) throws Exception { - TestCommon.test(JarBuilder.getOrCreateHelloJar(), - TestCommon.list("Hello"), "-XX:+DynamicDumpSharedSpaces", "Hello"); - } +import jdk.jfr.Event; + +public class NonExportedSuperTypes { + + public void evt(Event evt) { + evt.toString(); + } + } diff --git a/test/langtools/tools/javac/platform/createsymbols/CreateSymbolsTest.java b/test/langtools/tools/javac/platform/createsymbols/CreateSymbolsTest.java index 2f201fd0067da1d483c0a095ed42ceaf791f44d5..c54c21bfc0d7ad330cddec0cd7b1fd0ef3d110ce 100644 --- a/test/langtools/tools/javac/platform/createsymbols/CreateSymbolsTest.java +++ b/test/langtools/tools/javac/platform/createsymbols/CreateSymbolsTest.java @@ -23,7 +23,7 @@ /** * @test - * @bug 8072480 + * @bug 8072480 8277106 * @summary Unit test for CreateSymbols * @modules java.compiler * jdk.compiler/com.sun.tools.javac.api diff --git a/test/langtools/tools/javac/platform/createsymbols/CreateSymbolsTestImpl.java b/test/langtools/tools/javac/platform/createsymbols/CreateSymbolsTestImpl.java index 42b9649311adebe6caffc6c943bf916842729e44..307c53135a774751778b1594fc6383834bdcb1b3 100644 --- a/test/langtools/tools/javac/platform/createsymbols/CreateSymbolsTestImpl.java +++ b/test/langtools/tools/javac/platform/createsymbols/CreateSymbolsTestImpl.java @@ -28,8 +28,14 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.reflect.Method; import java.util.Arrays; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.DirectoryStream; import java.nio.file.FileVisitResult; import java.nio.file.FileVisitor; import java.nio.file.Files; @@ -52,6 +58,14 @@ import build.tools.symbolgenerator.CreateSymbols.ClassDescription; import build.tools.symbolgenerator.CreateSymbols.ClassList; import build.tools.symbolgenerator.CreateSymbols.ExcludeIncludeList; import build.tools.symbolgenerator.CreateSymbols.VersionDescription; +import com.sun.tools.classfile.Attribute; +import com.sun.tools.classfile.Attributes; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.ClassWriter; +import com.sun.tools.classfile.ConstantPool; +import com.sun.tools.classfile.ConstantPool.CPInfo; +import com.sun.tools.classfile.ConstantPool.CONSTANT_Utf8_info; +import com.sun.tools.classfile.ModulePackages_attribute; public class CreateSymbolsTestImpl { @@ -641,6 +655,306 @@ public class CreateSymbolsTestImpl { """); } + @Test + void testNonExportedSuperclass() throws Exception { + doTestComplex("api.Api", + """ + package api; + + public class Api extends nonapi.Impl.Nested.Exp { + + public Api(); + } + """, + """ + import api.Api; + public class Test { + private void t(Api api) { + api.run(); + } + } + """, + """ + import api.Api; + public class Test { + private void t(Api api) { + fail + } + } + """, + """ + module m { + exports api; + } + """, + """ + package api; + import nonapi.Impl; + public class Api extends Impl.Nested.Exp { + } + """, + """ + package api; + public @interface Ann { + } + """, + """ + package nonapi; + import api.Ann; + public class Impl { + public static final String C = ""; + public void test() {} + @Ann + public static class Nested { + public static class Exp extends Nested implements Runnable { + public void run() {} + public OtherNested get() { return null; } + } + } + public static class OtherNested {} + } + """); + } + + void doTestComplex(String printClass, + String expected, + String depSuccess, + String depFailure, + String... code) throws Exception { + ToolBox tb = new ToolBox(); + String testClasses = System.getProperty("test.classes"); + Path output = Paths.get(testClasses, "test-data" + i++); + deleteRecursively(output); + Files.createDirectories(output); + Path ver9Jar = output.resolve("9.jar"); + compileAndPack(output, + ver9Jar, + code); + + + Path ctSym = output.resolve("ct.sym"); + + deleteRecursively(ctSym); + + CreateSymbols.ALLOW_NON_EXISTING_CLASSES = true; + CreateSymbols.EXTENSION = ".class"; + + deleteRecursively(ctSym); + + List<VersionDescription> versions = + Arrays.asList(new VersionDescription(ver9Jar.toAbsolutePath().toString(), "9", null)); + + ExcludeIncludeList acceptAll = new ExcludeIncludeList(null, null) { + @Override public boolean accepts(String className, boolean includePrivateClasses) { + return true; + } + }; + new CreateSymbols().createBaseLine(versions, acceptAll, ctSym, new String[0]); + Path symbolsDesc = ctSym.resolve("symbols"); + Path systemModules = ctSym.resolve("systemModules"); + + Files.newBufferedWriter(systemModules).close(); + + Path classesZip = output.resolve("classes.zip"); + Path classesDir = output.resolve("classes"); + + new CreateSymbols().createSymbols(null, symbolsDesc.toAbsolutePath().toString(), classesZip.toAbsolutePath().toString(), 0, "9", systemModules.toString()); + + try (JarFile jf = new JarFile(classesZip.toFile())) { + Enumeration<JarEntry> en = jf.entries(); + + while (en.hasMoreElements()) { + JarEntry je = en.nextElement(); + if (je.isDirectory()) continue; + Path target = classesDir.resolve(je.getName()); + Files.createDirectories(target.getParent()); + Files.copy(jf.getInputStream(je), target); + } + } + + Path classes = classesDir; + Path scratch = output.resolve("scratch"); + + Files.createDirectories(scratch); + + String modulePath; + + try (Stream<Path> elements = Files.list(classes)) { + modulePath = elements.filter(el -> el.getFileName().toString().contains("9")) + .map(el -> el.resolve("m")) + .map(el -> el.toAbsolutePath().toString()) + .collect(Collectors.joining(File.pathSeparator)); + } + + { + String out = new JavacTask(tb, Task.Mode.CMDLINE) + .options("-d", scratch.toAbsolutePath().toString(), "--module-path", modulePath, + "--add-modules", "m", "-Xprint", "api.Api") + .run(Expect.SUCCESS) + .getOutput(Task.OutputKind.STDOUT) + .replaceAll("\\R", "\n"); + + if (!out.equals(expected)) { + throw new AssertionError("out=" + out + "; expected=" + expected); + } + } + + { + new JavacTask(tb) + .options("-d", scratch.toAbsolutePath().toString(), "--module-path", modulePath, + "--add-modules", "m") + .sources(depSuccess) + .run(Expect.SUCCESS) + .writeAll(); + } + + { + String expectedFailure = new JavacTask(tb) + .options("-d", scratch.toAbsolutePath().toString(), "--module-path", output.resolve("temp").toString(), + "--add-modules", "m", "-XDrawDiagnostics") + .sources(depFailure) + .run(Expect.FAIL) + .getOutput(Task.OutputKind.DIRECT) + .replaceAll("\\R", "\n"); + + String out = new JavacTask(tb) + .options("-d", scratch.toAbsolutePath().toString(), "--module-path", modulePath, + "--add-modules", "m", "-XDrawDiagnostics") + .sources(depFailure) + .run(Expect.FAIL) + .getOutput(Task.OutputKind.DIRECT) + .replaceAll("\\R", "\n"); + + if (!out.equals(expectedFailure)) { + throw new AssertionError("out=" + out + "; expected=" + expectedFailure); + } + } + } + + @Test + void testExtendsInternalData1() throws Exception { + doTestData(""" + module name m + header exports api,nonapi[java.base] requires name\\u0020;java.base\\u0020;flags\\u0020;8000\\u0020;version\\u0020;0 flags 8000 + + class name api/Ann + header extends java/lang/Object implements java/lang/annotation/Annotation flags 2601 + + class name api/Api + header extends nonapi/Impl$Nested$Exp flags 21 + innerclass innerClass nonapi/Impl$Nested outerClass nonapi/Impl innerClassName Nested flags 9 + innerclass innerClass nonapi/Impl$Nested$Exp outerClass nonapi/Impl$Nested innerClassName Exp flags 9 + method name <init> descriptor ()V flags 1 + + class name nonapi/Impl + header extends java/lang/Object nestMembers nonapi/Impl$Nested,nonapi/Impl$Nested$Exp flags 21 + innerclass innerClass nonapi/Impl$Nested outerClass nonapi/Impl innerClassName Nested flags 9 + innerclass innerClass nonapi/Impl$Nested$Exp outerClass nonapi/Impl$Nested innerClassName Exp flags 9 + field name C descriptor Ljava/lang/String; constantValue flags 19 + method name <init> descriptor ()V flags 1 + method name test descriptor ()V flags 1 + + class name nonapi/Impl$Nested + header extends java/lang/Object nestHost nonapi/Impl flags 21 classAnnotations @Lapi/Ann; + innerclass innerClass nonapi/Impl$Nested outerClass nonapi/Impl innerClassName Nested flags 9 + innerclass innerClass nonapi/Impl$Nested$Exp outerClass nonapi/Impl$Nested innerClassName Exp flags 9 + method name <init> descriptor ()V flags 1 + + class name nonapi/Impl$Nested$Exp + header extends nonapi/Impl$Nested implements java/lang/Runnable nestHost nonapi/Impl flags 21 + innerclass innerClass nonapi/Impl$Nested outerClass nonapi/Impl innerClassName Nested flags 9 + innerclass innerClass nonapi/Impl$Nested$Exp outerClass nonapi/Impl$Nested innerClassName Exp flags 9 + method name <init> descriptor ()V flags 1 + method name run descriptor ()V flags 1 + method name get descriptor ()Lnonapi/Impl$OtherNested; flags 1 + + """, + """ + module m { + exports api; + exports nonapi to java.base; + } + """, + """ + package api; + import nonapi.Impl; + public class Api extends Impl.Nested.Exp { + } + """, + """ + package api; + public @interface Ann { + } + """, + """ + package nonapi; + import api.Ann; + public class Impl { + public static final String C = ""; + public void test() {} + @Ann + public static class Nested { + public static class Exp extends Nested implements Runnable { + public void run() {} + public OtherNested get() { return null; } + } + } + public static class OtherNested {} + } + """); + } + + void doTestData(String data, + String... code) throws Exception { + String testClasses = System.getProperty("test.classes"); + Path output = Paths.get(testClasses, "test-data" + i++); + deleteRecursively(output); + Files.createDirectories(output); + Path ver9Jar = output.resolve("9.jar"); + compileAndPack(output, + ver9Jar, + code); + + Path ctSym = output.resolve("ct.sym"); + + deleteRecursively(ctSym); + + CreateSymbols.ALLOW_NON_EXISTING_CLASSES = true; + CreateSymbols.DO_NOT_MODIFY = ""; + CreateSymbols.EXTENSION = ".class"; + CreateSymbols.INJECTED_VERSION = "0"; + + deleteRecursively(ctSym); + + List<VersionDescription> versions = + Arrays.asList(new VersionDescription(ver9Jar.toAbsolutePath().toString(), "9", null)); + + ExcludeIncludeList acceptAll = new ExcludeIncludeList(null, null) { + @Override public boolean accepts(String className, boolean includePrivateClasses) { + return true; + } + }; + new CreateSymbols().createBaseLine(versions, acceptAll, ctSym, new String[0]); + + Path symFile = null; + + try (DirectoryStream<Path> ds = Files.newDirectoryStream(ctSym)) { + for (Path p : ds) { + if (p.toString().endsWith(".sym.txt")) { + if (symFile != null) { + throw new IllegalStateException("Multiple sym files!"); + } else { + symFile = p; + } + } + } + } + String acutalContent = new String(Files.readAllBytes(symFile), StandardCharsets.UTF_8); + if (!acutalContent.equals(data)) { + throw new AssertionError("out=" + acutalContent + "; expected=" + data); + } + } + void doTestIncluded(String code, String... includedClasses) throws Exception { boolean oldIncludeAll = includeAll; try { @@ -712,7 +1026,7 @@ public class CreateSymbolsTestImpl { new VersionDescription(jar8.toAbsolutePath().toString(), "8", "7")); ExcludeIncludeList acceptAll = new ExcludeIncludeList(null, null) { - @Override public boolean accepts(String className) { + @Override public boolean accepts(String className, boolean includePrivateClasses) { return true; } }; @@ -743,6 +1057,36 @@ public class CreateSymbolsTestImpl { System.err.println(Arrays.asList(code)); new JavacTask(tb).sources(code).options("-d", scratch.toAbsolutePath().toString()).run(Expect.SUCCESS); List<String> classFiles = collectClassFile(scratch); + Path moduleInfo = scratch.resolve("module-info.class"); + if (Files.exists(moduleInfo)) { + Set<String> packages = new HashSet<>(); + for (String cf : classFiles) { + int sep = cf.lastIndexOf(scratch.getFileSystem().getSeparator()); + if (sep != (-1)) { + packages.add(cf.substring(0, sep)); + } + } + ClassFile cf = ClassFile.read(moduleInfo); + List<CPInfo> cp = new ArrayList<>(); + cp.add(null); + cf.constant_pool.entries().forEach(cp::add); + Map<String, Attribute> attrs = new HashMap<>(cf.attributes.map); + int[] encodedPackages = new int[packages.size()]; + int i = 0; + for (String p : packages) { + int nameIndex = cp.size(); + cp.add(new CONSTANT_Utf8_info(p)); + encodedPackages[i++] = cp.size(); + cp.add(new ConstantPool.CONSTANT_Package_info(null, nameIndex)); + } + int attrName = cp.size(); + cp.add(new CONSTANT_Utf8_info(Attribute.ModulePackages)); + attrs.put(Attribute.ModulePackages, new ModulePackages_attribute(attrName, encodedPackages)); + ClassFile newFile = new ClassFile(cf.magic, cf.minor_version, cf.major_version, new ConstantPool(cp.toArray(new CPInfo[0])), cf.access_flags, cf.this_class, cf.super_class, cf.interfaces, cf.fields, cf.methods, new Attributes(attrs)); + try (OutputStream out = Files.newOutputStream(moduleInfo)) { + new ClassWriter().write(newFile, out); + } + } try (Writer out = Files.newBufferedWriter(outputFile)) { for (String classFile : classFiles) { try (InputStream in = Files.newInputStream(scratch.resolve(classFile))) { diff --git a/test/langtools/tools/javac/preview/classReaderTest/Client.nopreview.out b/test/langtools/tools/javac/preview/classReaderTest/Client.nopreview.out index 7c9e532800b01e458680f132a62688e5b9e50ba6..b80a19b27b4865838ae73d13a9c2e4d0cc4b36b0 100644 --- a/test/langtools/tools/javac/preview/classReaderTest/Client.nopreview.out +++ b/test/langtools/tools/javac/preview/classReaderTest/Client.nopreview.out @@ -1,2 +1,2 @@ -- compiler.err.preview.feature.disabled.classfile: Bar.class, 18 +- compiler.err.preview.feature.disabled.classfile: Bar.class, 19 1 error diff --git a/test/langtools/tools/javac/preview/classReaderTest/Client.preview.out b/test/langtools/tools/javac/preview/classReaderTest/Client.preview.out index 6a8ffbd85841acb47d790f6bcae1fdae09e0a367..df31f431c153ac96f4653a0ed6c8da5788fb016a 100644 --- a/test/langtools/tools/javac/preview/classReaderTest/Client.preview.out +++ b/test/langtools/tools/javac/preview/classReaderTest/Client.preview.out @@ -1,4 +1,4 @@ -- compiler.warn.preview.feature.use.classfile: Bar.class, 18 +- compiler.warn.preview.feature.use.classfile: Bar.class, 19 - compiler.err.warnings.and.werror 1 error 1 warning diff --git a/test/langtools/tools/javac/processing/8268575/Processor.java b/test/langtools/tools/javac/processing/8268575/Processor.java new file mode 100644 index 0000000000000000000000000000000000000000..8640c292303f6e912c5934c66daa037897b90a78 --- /dev/null +++ b/test/langtools/tools/javac/processing/8268575/Processor.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.io.Writer; +import java.util.Set; +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.tools.Diagnostic.Kind; +import javax.tools.JavaFileObject; +import java.util.List; + +@SupportedAnnotationTypes("*") +public class Processor extends AbstractProcessor { + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latestSupported(); + } + + int round = 1; + + @Override + public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { + processingEnv.getMessager().printMessage(Kind.NOTE, "round " + round); + Element t = processingEnv.getElementUtils().getTypeElement("T8268575"); + for (Element e : t.getEnclosedElements()) { + if (e instanceof ExecutableElement) { + for (VariableElement p : ((ExecutableElement) e).getParameters()) { + List<? extends AnnotationMirror> annos = p.getAnnotationMirrors(); + if (annos.size() != 1) { + throw new RuntimeException("Missing annotation in round " + round); + } + } + } + } + if (round == 1) { + String name = "A"; + try { + JavaFileObject jfo = processingEnv.getFiler().createSourceFile(name); + try (Writer w = jfo.openWriter()) { + w.write("@interface " + name + " {}"); + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + round++; + return false; + } +} diff --git a/src/utils/IdealGraphVisualizer/BatikSVGProxy/src/main/java/com/sun/hotspot/igv/svg/package-info.java b/test/langtools/tools/javac/processing/8268575/T8268575.java similarity index 76% rename from src/utils/IdealGraphVisualizer/BatikSVGProxy/src/main/java/com/sun/hotspot/igv/svg/package-info.java rename to test/langtools/tools/javac/processing/8268575/T8268575.java index 272fc48e96f03d735cc94bd5ab76205e5a2b7644..9233dbe55d1ad7980ea29fbfbe343c9e0bf50b30 100644 --- a/src/utils/IdealGraphVisualizer/BatikSVGProxy/src/main/java/com/sun/hotspot/igv/svg/package-info.java +++ b/test/langtools/tools/javac/processing/8268575/T8268575.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -19,11 +19,16 @@ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. - * */ + /** - * This package is used to proxy the SVG export functionality of the BatikSVG library. Reflection is used such that the - * library is optional and need not be present at build time. + * @test + * @bug 8268575 + * @summary Annotations not visible on model elements before they are generated + * @build Processor + * @compile -processor Processor T8268575.java */ -package com.sun.hotspot.igv.svg; +class T8268575 { + void f(@A int x) {} +} diff --git a/test/langtools/tools/javac/processing/filer/TestOriginatingElements.java b/test/langtools/tools/javac/processing/filer/TestOriginatingElements.java new file mode 100644 index 0000000000000000000000000000000000000000..a936c0bb554220eea92129709158a81957e23a52 --- /dev/null +++ b/test/langtools/tools/javac/processing/filer/TestOriginatingElements.java @@ -0,0 +1,486 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8272234 + * @summary Verify proper handling of originating elements in javac's Filer. + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * @build toolbox.TestRunner toolbox.ToolBox TestOriginatingElements + * @run main TestOriginatingElements + */ + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.Set; + +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.TypeElement; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.ToolProvider; + +import java.io.IOException; +import java.io.OutputStream; +import java.net.URI; +import java.util.ArrayList; +import java.util.Base64; +import java.util.Iterator; +import javax.annotation.processing.Filer; +import javax.annotation.processing.SupportedOptions; +import javax.lang.model.element.Element; +import javax.lang.model.element.ModuleElement; +import javax.lang.model.element.PackageElement; +import javax.lang.model.util.Elements; +import javax.tools.FileObject; +import javax.tools.ForwardingJavaFileManager; +import javax.tools.JavaFileManager; +import javax.tools.SimpleJavaFileObject; +import javax.tools.StandardLocation; +import toolbox.JavacTask; +import toolbox.TestRunner; +import toolbox.TestRunner.Test; +import toolbox.ToolBox; +import toolbox.ToolBox.MemoryFileManager; + +public class TestOriginatingElements extends TestRunner { + + public static void main(String... args) throws Exception { + new TestOriginatingElements().runTests(m -> new Object[] { Paths.get(m.getName()) }); + } + + private static final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + private final ToolBox tb = new ToolBox(); + + public TestOriginatingElements() { + super(System.err); + } + + @Test + public void testOriginatingElements(Path outerBase) throws Exception { + Path libSrc = outerBase.resolve("lib-src"); + tb.writeJavaFiles(libSrc, + """ + module lib { exports lib1; exports lib2; } + """, + """ + package lib1; + public @interface A { + } + """, + """ + package lib2; + public class Lib { + } + """); + tb.writeFile(libSrc.resolve("lib1/package-info.java"), "@A package lib1;"); + Path libClasses = outerBase.resolve("lib-classes"); + Path libClassesModule = libClasses.resolve("lib"); + Files.createDirectories(libClassesModule); + + new JavacTask(tb) + .files(tb.findJavaFiles(libSrc)) + .outdir(libClassesModule) + .run(); + + Path src = outerBase.resolve("src"); + tb.writeJavaFiles(src, + """ + module m {} + """, + """ + package t; + public class T1 { + } + """, + """ + package t; + public class T2 { + } + """, + """ + package t; + public class T3 { + } + """); + tb.writeFile(src.resolve("p/package-info.java"), "package p;"); + Path classes = outerBase.resolve("classes"); + Files.createDirectories(classes); + try (StandardJavaFileManager sjfm = compiler.getStandardFileManager(null, null, null)) { + List<String> testOutput = new ArrayList<>(); + JavaFileManager fm = new ForwardingJavaFileManager<JavaFileManager>(sjfm) { + @Override + public JavaFileObject getJavaFileForOutputForOriginatingFiles(Location location, + String className, + JavaFileObject.Kind kind, + FileObject... originatingFiles) throws IOException { + List.of(originatingFiles) + .stream() + .map(fo -> getInfo(fo)) + .forEach(testOutput::add); + return super.getJavaFileForOutputForOriginatingFiles(location, className, kind, originatingFiles); + } + @Override + public FileObject getFileForOutputForOriginatingFiles(Location location, + String packageName, + String relativeName, + FileObject... originatingFiles) throws IOException { + List.of(originatingFiles) + .stream() + .map(fo -> getInfo(fo)) + .forEach(testOutput::add); + return super.getFileForOutputForOriginatingFiles(location, packageName, relativeName, originatingFiles); + } + private String getInfo(FileObject fo) { + try { + JavaFileObject jfo = (JavaFileObject) fo; //the test only expects JavaFileObjects here: + JavaFileManager.Location location = jfo.getKind() == JavaFileObject.Kind.SOURCE + ? StandardLocation.SOURCE_PATH + : sjfm.getLocationForModule(StandardLocation.SYSTEM_MODULES, "java.base"); + String binaryName = inferBinaryName(location, jfo); + return binaryName + "(" + jfo.getKind() + ")"; + } catch (IOException ex) { + throw new AssertionError(ex); + } + } + }; + try { + String generatedData; + try (MemoryFileManager mfm = new MemoryFileManager(sjfm)) { + compiler.getTask(null, mfm, null, null, null, + List.of(new ToolBox.JavaSource("package test; public class Generated2 {}"))) + .call(); + generatedData = + Base64.getEncoder().encodeToString(mfm.getFileBytes(StandardLocation.CLASS_OUTPUT, "test.Generated2")); + } + List<String> options = List.of("-sourcepath", src.toString(), + "-processor", "TestOriginatingElements$P", + "-processorpath", System.getProperty("test.class.path"), + "--module-path", libClasses.toString(), + "--add-modules", "lib", + "-d", classes.toString(), + "-AgeneratedData=" + generatedData); + ToolProvider.getSystemJavaCompiler() + .getTask(null, fm, null, options, null, sjfm.getJavaFileObjects(tb.findJavaFiles(src))) + .call(); + List<String> expectedOriginatingFiles = List.of("t.T1(SOURCE)", + "java.lang.String(CLASS)", + "p.package-info(SOURCE)", + "lib1.package-info(CLASS)", + "module-info(SOURCE)", + "module-info(CLASS)", + "t.T2(SOURCE)", + "java.lang.CharSequence(CLASS)", + "p.package-info(SOURCE)", + "lib1.package-info(CLASS)", + "module-info(SOURCE)", + "module-info(CLASS)", + "t.T3(SOURCE)", + "java.lang.Exception(CLASS)", + "p.package-info(SOURCE)", + "lib1.package-info(CLASS)", + "module-info(SOURCE)", + "module-info(CLASS)"); + assertEquals(expectedOriginatingFiles, testOutput); + } catch (IOException ex) { + throw new IllegalStateException(ex); + } + } + } + + @SupportedAnnotationTypes("*") + @SupportedOptions("generatedData") + public static class P extends AbstractProcessor { + int round; + @Override + public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { + if (round++ == 0) { + Elements elems = processingEnv.getElementUtils(); + ModuleElement mdl = elems.getModuleElement("m"); + ModuleElement java_base = elems.getModuleElement("java.base"); + PackageElement pack = elems.getPackageElement("p"); + PackageElement lib1Pack = elems.getPackageElement("lib1"); + PackageElement lib2Pack = elems.getPackageElement("lib2"); + Filer filer = processingEnv.getFiler(); + try { + filer.createSourceFile("test.Generated1", + element("t.T1"), + element("java.lang.String"), + pack, + lib1Pack, + lib2Pack, + mdl, + java_base).openOutputStream().close(); + try (OutputStream out = filer.createClassFile("test.Generated2", + element("t.T2"), + element("java.lang.CharSequence"), + pack, + lib1Pack, + lib2Pack, + mdl, + java_base).openOutputStream()) { + out.write(Base64.getDecoder().decode(processingEnv.getOptions().get("generatedData"))); + } + filer.createResource(StandardLocation.CLASS_OUTPUT, + "test", + "Generated3.txt", + element("t.T3"), + element("java.lang.Exception"), + pack, + lib1Pack, + lib2Pack, + mdl, + java_base).openOutputStream().close(); + } catch (IOException ex) { + throw new AssertionError(ex); + } + } + return false; + } + + private Element element(String type) { + return processingEnv.getElementUtils().getTypeElement(type); + } + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } + } + + @Test + public void testVacuousJavaFileManager(Path outerBase) throws Exception { + List<String> log = new ArrayList<>(); + JavaFileObject expectedOut = new SimpleJavaFileObject(new URI("Out.java"), JavaFileObject.Kind.SOURCE) {}; + JavaFileManager fm = new MinimalJavaFileManager() { + @Override + public JavaFileObject getJavaFileForOutput(JavaFileManager.Location location, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException { + log.add("getJavaFileForOutput(" + location + ", " + className + ", " + kind + ", " + sibling); + return expectedOut; + } + @Override + public FileObject getFileForOutput(JavaFileManager.Location location, String packageName, String relativeName, FileObject sibling) throws IOException { + log.add("getFileForOutput(" + location + ", " + packageName + ", " + relativeName + ", " + sibling); + return expectedOut; + } + }; + + FileObject fo1 = new SimpleJavaFileObject(new URI("Test1.java"), JavaFileObject.Kind.SOURCE) { + @Override + public String toString() { + return "Test1 - FO"; + } + }; + FileObject fo2 = new SimpleJavaFileObject(new URI("Test2.java"), JavaFileObject.Kind.SOURCE) { + @Override + public String toString() { + return "Test2 - FO"; + } + }; + + assertEquals(expectedOut, + fm.getJavaFileForOutputForOriginatingFiles(StandardLocation.CLASS_OUTPUT, "test.Test", JavaFileObject.Kind.SOURCE, fo1, fo2)); + assertEquals(List.of("getJavaFileForOutput(CLASS_OUTPUT, test.Test, SOURCE, Test1 - FO"), log); log.clear(); + + assertEquals(expectedOut, + fm.getJavaFileForOutputForOriginatingFiles(StandardLocation.CLASS_OUTPUT, "test.Test", JavaFileObject.Kind.SOURCE)); + assertEquals(List.of("getJavaFileForOutput(CLASS_OUTPUT, test.Test, SOURCE, null"), log); log.clear(); + + assertEquals(expectedOut, + fm.getFileForOutputForOriginatingFiles(StandardLocation.CLASS_OUTPUT, "test", "Test.java", fo1, fo2)); + assertEquals(List.of("getFileForOutput(CLASS_OUTPUT, test, Test.java, Test1 - FO"), log); log.clear(); + assertEquals(expectedOut, + fm.getFileForOutputForOriginatingFiles(StandardLocation.CLASS_OUTPUT, "test", "Test.java")); + assertEquals(List.of("getFileForOutput(CLASS_OUTPUT, test, Test.java, null"), log); log.clear(); + } + + @Test + public void testForwardingJavaFileManager(Path outerBase) throws Exception { + List<String> log = new ArrayList<>(); + JavaFileObject expectedOut = new SimpleJavaFileObject(new URI("Out.java"), JavaFileObject.Kind.SOURCE) {}; + + FileObject fo1 = new SimpleJavaFileObject(new URI("Test1.java"), JavaFileObject.Kind.SOURCE) { + @Override + public String toString() { + return "Test1 - FO"; + } + }; + FileObject fo2 = new SimpleJavaFileObject(new URI("Test2.java"), JavaFileObject.Kind.SOURCE) { + @Override + public String toString() { + return "Test2 - FO"; + } + }; + + JavaFileManager forwardingWithOverride = new ForwardingJavaFileManager<>(new MinimalJavaFileManager() { + @Override + public JavaFileObject getJavaFileForOutput(JavaFileManager.Location location, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException { + log.add("getJavaFileForOutput(" + location + ", " + className + ", " + kind + ", " + sibling); + return expectedOut; + } + @Override + public JavaFileObject getJavaFileForOutputForOriginatingFiles(JavaFileManager.Location location, String className, JavaFileObject.Kind kind, FileObject... originatingFiles) throws IOException { + throw new AssertionError("Should not be called."); + } + @Override + public FileObject getFileForOutput(JavaFileManager.Location location, String packageName, String relativeName, FileObject sibling) throws IOException { + log.add("getFileForOutput(" + location + ", " + packageName + ", " + relativeName + ", " + sibling); + return expectedOut; + } + @Override + public FileObject getFileForOutputForOriginatingFiles(JavaFileManager.Location location, String packageName, String relativeName, FileObject... originatingFiles) throws IOException { + throw new AssertionError("Should not be called."); + } + }) { + @Override + public JavaFileObject getJavaFileForOutput(JavaFileManager.Location location, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException { + return super.getJavaFileForOutput(location, className, kind, sibling); + } + @Override + public FileObject getFileForOutput(JavaFileManager.Location location, String packageName, String relativeName, FileObject sibling) throws IOException { + return super.getFileForOutput(location, packageName, relativeName, sibling); + } + }; + + assertEquals(expectedOut, + forwardingWithOverride.getJavaFileForOutputForOriginatingFiles(StandardLocation.CLASS_OUTPUT, "test.Test", JavaFileObject.Kind.SOURCE, fo1, fo2)); + assertEquals(List.of("getJavaFileForOutput(CLASS_OUTPUT, test.Test, SOURCE, Test1 - FO"), log); log.clear(); + + assertEquals(expectedOut, + forwardingWithOverride.getJavaFileForOutputForOriginatingFiles(StandardLocation.CLASS_OUTPUT, "test.Test", JavaFileObject.Kind.SOURCE)); + assertEquals(List.of("getJavaFileForOutput(CLASS_OUTPUT, test.Test, SOURCE, null"), log); log.clear(); + + assertEquals(expectedOut, + forwardingWithOverride.getFileForOutputForOriginatingFiles(StandardLocation.CLASS_OUTPUT, "test", "Test.java", fo1, fo2)); + assertEquals(List.of("getFileForOutput(CLASS_OUTPUT, test, Test.java, Test1 - FO"), log); log.clear(); + assertEquals(expectedOut, + forwardingWithOverride.getFileForOutputForOriginatingFiles(StandardLocation.CLASS_OUTPUT, "test", "Test.java")); + assertEquals(List.of("getFileForOutput(CLASS_OUTPUT, test, Test.java, null"), log); log.clear(); + + JavaFileManager forwardingWithOutOverride = new ForwardingJavaFileManager<>(new MinimalJavaFileManager() { + @Override + public JavaFileObject getJavaFileForOutput(JavaFileManager.Location location, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException { + throw new AssertionError("Should not be called."); + } + @Override + public JavaFileObject getJavaFileForOutputForOriginatingFiles(JavaFileManager.Location location, String className, JavaFileObject.Kind kind, FileObject... originatingFiles) throws IOException { + log.add("getJavaFileForOutputForOriginatingFiles(" + location + ", " + className + ", " + kind + ", " + List.of(originatingFiles)); + return expectedOut; + } + @Override + public FileObject getFileForOutput(JavaFileManager.Location location, String packageName, String relativeName, FileObject sibling) throws IOException { + throw new AssertionError("Should not be called."); + } + @Override + public FileObject getFileForOutputForOriginatingFiles(JavaFileManager.Location location, String packageName, String relativeName, FileObject... originatingFiles) throws IOException { + log.add("getFileForOutputForOriginatingFiles(" + location + ", " + packageName + ", " + relativeName + ", " + List.of(originatingFiles)); + return expectedOut; + } + }) {}; + + assertEquals(expectedOut, + forwardingWithOutOverride.getJavaFileForOutputForOriginatingFiles(StandardLocation.CLASS_OUTPUT, "test.Test", JavaFileObject.Kind.SOURCE, fo1, fo2)); + assertEquals(List.of("getJavaFileForOutputForOriginatingFiles(CLASS_OUTPUT, test.Test, SOURCE, [Test1 - FO, Test2 - FO]"), log); log.clear(); + + assertEquals(expectedOut, + forwardingWithOutOverride.getJavaFileForOutputForOriginatingFiles(StandardLocation.CLASS_OUTPUT, "test.Test", JavaFileObject.Kind.SOURCE)); + assertEquals(List.of("getJavaFileForOutputForOriginatingFiles(CLASS_OUTPUT, test.Test, SOURCE, []"), log); log.clear(); + + assertEquals(expectedOut, + forwardingWithOutOverride.getFileForOutputForOriginatingFiles(StandardLocation.CLASS_OUTPUT, "test", "Test.java", fo1, fo2)); + assertEquals(List.of("getFileForOutputForOriginatingFiles(CLASS_OUTPUT, test, Test.java, [Test1 - FO, Test2 - FO]"), log); log.clear(); + assertEquals(expectedOut, + forwardingWithOutOverride.getFileForOutputForOriginatingFiles(StandardLocation.CLASS_OUTPUT, "test", "Test.java")); + assertEquals(List.of("getFileForOutputForOriginatingFiles(CLASS_OUTPUT, test, Test.java, []"), log); log.clear(); + } + + class MinimalJavaFileManager implements JavaFileManager { + @Override + public ClassLoader getClassLoader(JavaFileManager.Location location) { + throw new UnsupportedOperationException("Not supported."); + } + @Override + public Iterable<JavaFileObject> list(JavaFileManager.Location location, String packageName, Set<JavaFileObject.Kind> kinds, boolean recurse) throws IOException { + throw new UnsupportedOperationException("Not supported."); + } + @Override + public String inferBinaryName(JavaFileManager.Location location, JavaFileObject file) { + throw new UnsupportedOperationException("Not supported."); + } + @Override + public boolean isSameFile(FileObject a, FileObject b) { + throw new UnsupportedOperationException("Not supported."); + } + @Override + public boolean handleOption(String current, Iterator<String> remaining) { + throw new UnsupportedOperationException("Not supported."); + } + @Override + public boolean hasLocation(JavaFileManager.Location location) { + throw new UnsupportedOperationException("Not supported."); + } + @Override + public JavaFileObject getJavaFileForInput(JavaFileManager.Location location, String className, JavaFileObject.Kind kind) throws IOException { + throw new UnsupportedOperationException("Not supported."); + } + @Override + public JavaFileObject getJavaFileForOutput(JavaFileManager.Location location, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException { + throw new UnsupportedOperationException("Not supported."); + } + @Override + public FileObject getFileForInput(JavaFileManager.Location location, String packageName, String relativeName) throws IOException { + throw new UnsupportedOperationException("Not supported."); + } + @Override + public FileObject getFileForOutput(JavaFileManager.Location location, String packageName, String relativeName, FileObject sibling) throws IOException { + throw new UnsupportedOperationException("Not supported."); + } + @Override + public void flush() throws IOException { + throw new UnsupportedOperationException("Not supported."); + } + @Override + public void close() throws IOException { + throw new UnsupportedOperationException("Not supported."); + } + @Override + public int isSupportedOption(String option) { + throw new UnsupportedOperationException("Not supported."); + } + }; + + private void assertEquals(Object expected, Object actual) throws AssertionError { + if (!expected.equals(actual)) { + throw new AssertionError("Unexpected output: " + actual + ", expected: " + expected); + } + } + +} diff --git a/test/langtools/tools/javac/sealed/MissingPermittedSubtypes.java b/test/langtools/tools/javac/sealed/MissingPermittedSubtypes.java new file mode 100644 index 0000000000000000000000000000000000000000..ba75407099a7f0c08d9d2864f0e1be426c090279 --- /dev/null +++ b/test/langtools/tools/javac/sealed/MissingPermittedSubtypes.java @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8277105 + * @summary Verify missing permitted subtype is handled properly for both casts and pattern switches. + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.util + * @build toolbox.ToolBox toolbox.JavacTask + * @run main MissingPermittedSubtypes +*/ + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; + +import toolbox.TestRunner; +import toolbox.JavacTask; +import toolbox.Task; +import toolbox.ToolBox; + +public class MissingPermittedSubtypes extends TestRunner { + + private static final String JAVA_VERSION = System.getProperty("java.specification.version"); + + ToolBox tb; + + public static void main(String... args) throws Exception { + new MissingPermittedSubtypes().runTests(); + } + + MissingPermittedSubtypes() { + super(System.err); + tb = new ToolBox(); + } + + public void runTests() throws Exception { + runTests(m -> new Object[] { Paths.get(m.getName()) }); + } + + @Test + public void testInaccessiblePermitted(Path base) throws IOException { + Path current = base.resolve("."); + Path libSrc = current.resolve("lib-src"); + + tb.writeJavaFiles(libSrc, + """ + package lib; + public sealed interface S permits A, B1, B2 {} + """, + """ + package lib; + public final class A implements S {} + """, + """ + package lib; + final class B1 implements S {} + """, + """ + package lib; + final class B2 implements S, Runnable { + public void run() {} + } + """); + + Path libClasses = current.resolve("libClasses"); + + Files.createDirectories(libClasses); + + new JavacTask(tb) + .options("--enable-preview", + "-source", JAVA_VERSION) + .outdir(libClasses) + .files(tb.findJavaFiles(libSrc)) + .run(); + + Path b1Class = libClasses.resolve("lib").resolve("B1.class"); + + Files.delete(b1Class); + + Path b2Class = libClasses.resolve("lib").resolve("B2.class"); + + Files.delete(b2Class); + + { + Path src1 = current.resolve("src1"); + tb.writeJavaFiles(src1, + """ + package test; + import lib.*; + public class Test1 { + private void test(S obj) { + int i = switch (obj) { + case A a -> 0; + }; + Runnable r = () -> {obj = null;}; + } + } + """); + + Path classes1 = current.resolve("classes1"); + + Files.createDirectories(classes1); + + var log = + new JavacTask(tb) + .options("--enable-preview", + "-source", JAVA_VERSION, + "-XDrawDiagnostics", + "-Xlint:-preview", + "--class-path", libClasses.toString()) + .outdir(classes1) + .files(tb.findJavaFiles(src1)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + List<String> expectedErrors = List.of( + "Test1.java:5:24: compiler.err.cant.access: lib.B1, (compiler.misc.class.file.not.found: lib.B1)", + "Test1.java:8:29: compiler.err.cant.ref.non.effectively.final.var: obj, (compiler.misc.lambda)", + "- compiler.note.preview.filename: Test1.java, DEFAULT", + "- compiler.note.preview.recompile", + "2 errors"); + + if (!expectedErrors.equals(log)) { + throw new AssertionError("Incorrect errors, expected: " + expectedErrors + + ", actual: " + log); + } + } + + { + Path src2 = current.resolve("src2"); + tb.writeJavaFiles(src2, + """ + package test; + import lib.*; + public class Test1 { + private void test(S obj) { + Runnable r = (Runnable) obj; + String s = (String) obj; + } + } + """); + + Path classes2 = current.resolve("classes2"); + + Files.createDirectories(classes2); + + var log = + new JavacTask(tb) + .options("--enable-preview", + "-source", JAVA_VERSION, + "-XDrawDiagnostics", + "-Xlint:-preview", + "--class-path", libClasses.toString()) + .outdir(classes2) + .files(tb.findJavaFiles(src2)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + List<String> expectedErrors = List.of( + "Test1.java:5:19: compiler.err.cant.access: lib.B1, (compiler.misc.class.file.not.found: lib.B1)", + "Test1.java:6:26: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: lib.S, java.lang.String)", + "2 errors"); + + if (!expectedErrors.equals(log)) { + throw new AssertionError("Incorrect errors, expected: " + expectedErrors + + ", actual: " + log); + } + } + } + +} diff --git a/test/langtools/tools/javac/versions/Versions.java b/test/langtools/tools/javac/versions/Versions.java index 7b75896bab75ee6a77f9b1b1d23f0eccbe30c216..78185eba484b786c0a393ffd6fa0ab3e2bb065fc 100644 --- a/test/langtools/tools/javac/versions/Versions.java +++ b/test/langtools/tools/javac/versions/Versions.java @@ -71,9 +71,9 @@ public class Versions { public static final Set<String> VALID_SOURCES = Set.of("1.7", "1.8", "1.9", "1.10", "11", "12", "13", "14", - "15", "16", "17", "18"); + "15", "16", "17", "18", "19"); - public static final String LATEST_MAJOR_VERSION = "62.0"; + public static final String LATEST_MAJOR_VERSION = "63.0"; static enum SourceTarget { SEVEN(true, "51.0", "7", Versions::checksrc7), @@ -87,7 +87,8 @@ public class Versions { FIFTEEN(false, "59.0", "15", Versions::checksrc15), SIXTEEN(false, "60.0", "16", Versions::checksrc16), SEVENTEEN(false, "61.0", "17", Versions::checksrc17), - EIGHTEEN(false, "62.0", "18", Versions::checksrc18); + EIGHTEEN(false, "62.0", "18", Versions::checksrc18), + NINETEEN(false, "63.0", "19", Versions::checksrc19); private final boolean dotOne; private final String classFileVer; @@ -320,6 +321,13 @@ public class Versions { // Add expectedFail after new language features added in a later release. } + protected void checksrc19(List<String> args) { + printargs("checksrc19", args); + expectedPass(args, List.of("New7.java", "New8.java", "New10.java", "New11.java", + "New14.java", "New15.java", "New16.java", "New17.java")); + // Add expectedFail after new language features added in a later release. + } + protected void expected(List<String> args, List<String> fileNames, Consumer<List<String>> passOrFail) { ArrayList<String> fullArguments = new ArrayList<>(args); diff --git a/test/langtools/tools/jdeps/multiVersion/MultiVersionError.java b/test/langtools/tools/jdeps/multiVersion/MultiVersionError.java new file mode 100644 index 0000000000000000000000000000000000000000..62513406b7139da9c0bce340ba94c7973a896969 --- /dev/null +++ b/test/langtools/tools/jdeps/multiVersion/MultiVersionError.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8277165 + * @library ../lib + * @build CompilerUtils + * @run testng MultiVersionError + * @summary Tests multiple versions of the same class file + */ + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Set; +import java.util.spi.ToolProvider; + +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertTrue; + +public class MultiVersionError { + private static final String TEST_SRC = System.getProperty("test.src"); + private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); + + private static final Path MODS_DIR = Paths.get("mods"); + + private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar").orElseThrow(); + private static final Set<String> modules = Set.of("m1", "m2"); + + /** + * Compiles classes used by the test + */ + @BeforeTest + public void compileAll() throws Exception { + CompilerUtils.cleanDir(MODS_DIR); + modules.forEach(mn -> + assertTrue(CompilerUtils.compileModule(SRC_DIR, MODS_DIR, mn))); + + // create a modular multi-release m1.jar + Path m1 = MODS_DIR.resolve("m1"); + Path m2 = MODS_DIR.resolve("m2"); + jar("cf", "m1.jar", "-C", m1.toString(), "p/Test.class", + "--release", "9", "-C", m1.toString(), "module-info.class", + "--release", "11", "-C", m1.toString(), "p/internal/P.class"); + jar("cf", "m2.jar", "-C", m2.toString(), "q/Q.class", + "--release", "10", "-C", m2.toString(), "module-info.class"); + + // package private p/internal/P.class in m1 instead + jar("cf", "m3.jar", "-C", m2.toString(), "q/Q.class", + "--release", "12", "-C", m2.toString(), "module-info.class", + "-C", m1.toString(), "p/internal/P.class"); + } + + /* + * multiple module-info.class from different versions should be excluded + * from multiple version check. + */ + @Test + public void noMultiVersionClass() { + // skip parsing p.internal.P to workaround JDK-8277681 + JdepsRunner jdepsRunner = new JdepsRunner("--print-module-deps", "--multi-release", "10", + "--ignore-missing-deps", + "--module-path", "m1.jar", "m2.jar"); + int rc = jdepsRunner.run(true); + assertTrue(rc == 0); + assertTrue(jdepsRunner.outputContains("java.base,m1")); + } + + /* + * Detect multiple versions of p.internal.P class + */ + @Test + public void classInMultiVersions() { + JdepsRunner jdepsRunner = new JdepsRunner("--print-module-deps", "--multi-release", "13", + "--module-path", "m1.jar", "m3.jar"); + int rc = jdepsRunner.run(true); + assertTrue(rc != 0); + assertTrue(jdepsRunner.outputContains("class p.internal.P already associated with version")); + } + + private static void jar(String... options) { + int rc = JAR_TOOL.run(System.out, System.err, options); + assertTrue(rc == 0); + } +} diff --git a/test/langtools/tools/jdeps/multiVersion/src/m1/module-info.java b/test/langtools/tools/jdeps/multiVersion/src/m1/module-info.java new file mode 100644 index 0000000000000000000000000000000000000000..316803466ca7d225332b7329970b95cffa721cb1 --- /dev/null +++ b/test/langtools/tools/jdeps/multiVersion/src/m1/module-info.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +module m1 { + requires java.management; + exports p; +} diff --git a/test/langtools/tools/jdeps/multiVersion/src/m1/p/Test.java b/test/langtools/tools/jdeps/multiVersion/src/m1/p/Test.java new file mode 100644 index 0000000000000000000000000000000000000000..e3d9139bbddb67e136f29555cc0090757f043121 --- /dev/null +++ b/test/langtools/tools/jdeps/multiVersion/src/m1/p/Test.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package p; + +public class Test { +} diff --git a/test/langtools/tools/jdeps/multiVersion/src/m1/p/internal/P.java b/test/langtools/tools/jdeps/multiVersion/src/m1/p/internal/P.java new file mode 100644 index 0000000000000000000000000000000000000000..3a14badd1d07fce83e6b9d08877c222df487f145 --- /dev/null +++ b/test/langtools/tools/jdeps/multiVersion/src/m1/p/internal/P.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package p.internal; + +import java.lang.management.*; + +class P { + private static RuntimeMXBean mxbean = ManagementFactory.getRuntimeMXBean(); +} diff --git a/test/langtools/tools/jdeps/multiVersion/src/m2/module-info.java b/test/langtools/tools/jdeps/multiVersion/src/m2/module-info.java new file mode 100644 index 0000000000000000000000000000000000000000..5404ca478674ca3f3c71b7c1cf96968a05a7e11e --- /dev/null +++ b/test/langtools/tools/jdeps/multiVersion/src/m2/module-info.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +module m2 { + requires m1; + requires java.logging; +} diff --git a/test/langtools/tools/jdeps/multiVersion/src/m2/p/internal/P.java b/test/langtools/tools/jdeps/multiVersion/src/m2/p/internal/P.java new file mode 100644 index 0000000000000000000000000000000000000000..d68265798bda3a774a9ce96b4a3706c671a7768d --- /dev/null +++ b/test/langtools/tools/jdeps/multiVersion/src/m2/p/internal/P.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package p.internal; + +import java.util.logging.Logger; + +public class P { + private static final Logger LOGGER = Logger.getLogger("p"); +} diff --git a/test/langtools/tools/jdeps/multiVersion/src/m2/q/Q.java b/test/langtools/tools/jdeps/multiVersion/src/m2/q/Q.java new file mode 100644 index 0000000000000000000000000000000000000000..46cad1cc9d137b522b3c9ac9e06b51828a88db17 --- /dev/null +++ b/test/langtools/tools/jdeps/multiVersion/src/m2/q/Q.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package q; + +public class Q { + static p.Test t = new p.Test(); + + public Q() { + Object o = new p.internal.P(); + } +} diff --git a/test/lib-test/jdk/test/lib/AssertsTest.java b/test/lib-test/jdk/test/lib/AssertsTest.java index 86b1a7fb8c7d5a12864bd027d14067dd1a1524a3..a4c739d64bae8250f587a5b25abd207e46726980 100644 --- a/test/lib-test/jdk/test/lib/AssertsTest.java +++ b/test/lib-test/jdk/test/lib/AssertsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,7 +38,7 @@ public class AssertsTest { } public int compareTo(Foo f) { - return new Integer(id).compareTo(new Integer(f.id)); + return Integer.valueOf(id).compareTo(Integer.valueOf(f.id)); } public String toString() { return "Foo(" + Integer.toString(id) + ")"; diff --git a/test/lib-test/jdk/test/lib/TestPlatformIsTieredSupported.java b/test/lib-test/jdk/test/lib/TestPlatformIsTieredSupported.java index 8f57ab64eaf5b5960eb442a24f35fccfbee627df..8c0c8ea3c189cf807dc973778a128bc838996faf 100644 --- a/test/lib-test/jdk/test/lib/TestPlatformIsTieredSupported.java +++ b/test/lib-test/jdk/test/lib/TestPlatformIsTieredSupported.java @@ -39,6 +39,7 @@ import sun.hotspot.WhiteBox; */ public class TestPlatformIsTieredSupported { public static void main(String args[]) { + @SuppressWarnings("deprecation") WhiteBox whiteBox = WhiteBox.getWhiteBox(); boolean tieredCompilation = whiteBox.getBooleanVMFlag( "TieredCompilation"); diff --git a/test/lib-test/jdk/test/lib/format/ArrayDiffTest.java b/test/lib-test/jdk/test/lib/format/ArrayDiffTest.java index 7b7dfc086f18b033d57d1266146e8d445fbdb6b8..c52fcd78f9324d03daac00fd287cdd6c780e971a 100644 --- a/test/lib-test/jdk/test/lib/format/ArrayDiffTest.java +++ b/test/lib-test/jdk/test/lib/format/ArrayDiffTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -274,6 +274,7 @@ public class ArrayDiffTest { class StrObj { private final String value; public boolean equals(Object another) { return ((StrObj)another).value.equals(value); } + public int hashCode() { return value.hashCode(); } public StrObj(String value) { this.value = value; } public String toString() { return value; } } @@ -363,7 +364,7 @@ public class ArrayDiffTest { } public void assertTwoWay() { - ArrayDiff diff; + ArrayDiff<?> diff; // Direct if (defaultParameters) { diff --git a/test/lib-test/jdk/test/whitebox/OldWhiteBox.java b/test/lib-test/jdk/test/whitebox/OldWhiteBox.java index 677ed210f692bbecf15f63c4cecfc85a8ae18282..41af4698e9843bbd12c8a169d41240b70eab4c9b 100644 --- a/test/lib-test/jdk/test/whitebox/OldWhiteBox.java +++ b/test/lib-test/jdk/test/whitebox/OldWhiteBox.java @@ -43,6 +43,7 @@ import sun.hotspot.WhiteBox; public class OldWhiteBox { public static void main(String[] args) { + @SuppressWarnings("deprecation") WhiteBox wb = WhiteBox.getWhiteBox(); if (wb.getHeapOopSize() < 0) { throw new Error("wb.getHeapOopSize() < 0"); diff --git a/test/lib-test/jdk/test/whitebox/vm_flags/VmFlagTest.java b/test/lib-test/jdk/test/whitebox/vm_flags/VmFlagTest.java index d48aab6cf26f10b59eba71635b817f8aef8bd545..7290cd1096c1534652d55e47cea75322c923f8ee 100644 --- a/test/lib-test/jdk/test/whitebox/vm_flags/VmFlagTest.java +++ b/test/lib-test/jdk/test/whitebox/vm_flags/VmFlagTest.java @@ -72,9 +72,9 @@ public final class VmFlagTest<T> { protected static <T> void runTest(String existentFlag, T[] tests, T[] results, BiConsumer<String, T> set, Function<String, T> get) { if (existentFlag != null) { - new VmFlagTest(existentFlag, set, get, true).test(tests, results); + new VmFlagTest<T>(existentFlag, set, get, true).test(tests, results); } - new VmFlagTest(NONEXISTENT_FLAG, set, get, false).test(tests, results); + new VmFlagTest<T>(NONEXISTENT_FLAG, set, get, false).test(tests, results); } public final void test(T[] tests, T[] results) { diff --git a/test/lib/RedefineClassHelper.java b/test/lib/RedefineClassHelper.java index 0fcfc52f0c1b436fde6997a61a9033181ed1ca74..91b255828739f5dd2a1d6d06ca38dcd4277f3569 100644 --- a/test/lib/RedefineClassHelper.java +++ b/test/lib/RedefineClassHelper.java @@ -47,7 +47,7 @@ public class RedefineClassHelper { * @param clazz Class to redefine * @param javacode String with the new java code for the class to be redefined */ - public static void redefineClass(Class clazz, String javacode) throws Exception { + public static void redefineClass(Class<?> clazz, String javacode) throws Exception { byte[] bytecode = InMemoryJavaCompiler.compile(clazz.getName(), javacode); redefineClass(clazz, bytecode); } @@ -58,7 +58,7 @@ public class RedefineClassHelper { * @param clazz Class to redefine * @param bytecode byte[] with the new class */ - public static void redefineClass(Class clazz, byte[] bytecode) throws Exception { + public static void redefineClass(Class<?> clazz, byte[] bytecode) throws Exception { instrumentation.redefineClasses(new ClassDefinition(clazz, bytecode)); } diff --git a/test/lib/jdk/test/lib/NetworkConfiguration.java b/test/lib/jdk/test/lib/NetworkConfiguration.java index 716e2aed3d59bbfd1b3b14041b3dfd932cffa3eb..386a2bf0a6f084ca46ff90e40c9f35fdd5f621d8 100644 --- a/test/lib/jdk/test/lib/NetworkConfiguration.java +++ b/test/lib/jdk/test/lib/NetworkConfiguration.java @@ -451,6 +451,7 @@ public class NetworkConfiguration { } /** Prints all the system interface information to the give stream. */ + @SuppressWarnings("removal") public static void printSystemConfiguration(PrintStream out) { PrivilegedAction<Void> pa = () -> { try { diff --git a/test/lib/jdk/test/lib/compiler/InMemoryJavaCompiler.java b/test/lib/jdk/test/lib/compiler/InMemoryJavaCompiler.java index 9444e4cc97b50f70889f8e9b231e158c7917d12b..3fe7b43a82402ce9374d90b8066b5246fc209975 100644 --- a/test/lib/jdk/test/lib/compiler/InMemoryJavaCompiler.java +++ b/test/lib/jdk/test/lib/compiler/InMemoryJavaCompiler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,6 +36,7 @@ import javax.tools.ForwardingJavaFileManager; import javax.tools.FileObject; import javax.tools.JavaCompiler; import javax.tools.JavaCompiler.CompilationTask; +import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; import javax.tools.JavaFileObject.Kind; import javax.tools.SimpleJavaFileObject; @@ -106,7 +107,7 @@ public class InMemoryJavaCompiler { } } - private static class FileManagerWrapper extends ForwardingJavaFileManager { + private static class FileManagerWrapper extends ForwardingJavaFileManager<JavaFileManager> { private static final Location PATCH_LOCATION = new Location() { @Override public String getName() { diff --git a/test/lib/jdk/test/lib/format/ArrayCodec.java b/test/lib/jdk/test/lib/format/ArrayCodec.java index 0e34e7cd811226da3ff0e3754c2cd097932fe9df..8c2b1013204116062fa266baa4f7250f1dc96d3d 100644 --- a/test/lib/jdk/test/lib/format/ArrayCodec.java +++ b/test/lib/jdk/test/lib/format/ArrayCodec.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -141,7 +141,7 @@ public class ArrayCodec<E> { * @throws IllegalArgumentException if {@code array}'s component type is not supported * @return an ArrayCodec for the provided array */ - public static ArrayCodec of(Object array) { + public static ArrayCodec<?> of(Object array) { var type = array.getClass().getComponentType(); if (type == byte.class) { return ArrayCodec.of((byte[])array); diff --git a/test/lib/jdk/test/lib/format/ArrayDiff.java b/test/lib/jdk/test/lib/format/ArrayDiff.java index 6755a693b7c8340c01477b7dd9bcd3c98e332182..1b86e4d7578983f8fc906a8933c51981563f4de4 100644 --- a/test/lib/jdk/test/lib/format/ArrayDiff.java +++ b/test/lib/jdk/test/lib/format/ArrayDiff.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -93,7 +93,7 @@ public class ArrayDiff<E> implements Diff { * @param second the second array * @return an ArrayDiff instance for the two arrays */ - public static ArrayDiff of(Object first, Object second) { + public static ArrayDiff<?> of(Object first, Object second) { return ArrayDiff.of(first, second, Diff.Defaults.WIDTH, Diff.Defaults.CONTEXT_BEFORE); } @@ -109,7 +109,8 @@ public class ArrayDiff<E> implements Diff { * @throws NullPointerException if at least one of the arrays is null * @return an ArrayDiff instance for the two arrays and formatting parameters provided */ - public static ArrayDiff of(Object first, Object second, int width, int contextBefore) { + @SuppressWarnings("rawtypes") + public static ArrayDiff<?> of(Object first, Object second, int width, int contextBefore) { Objects.requireNonNull(first); Objects.requireNonNull(second); @@ -204,4 +205,3 @@ public class ArrayDiff<E> implements Diff { } } - diff --git a/test/lib/jdk/test/lib/hexdump/ASN1Formatter.java b/test/lib/jdk/test/lib/hexdump/ASN1Formatter.java index 5001978b8603c33dc87e004e13983a7baf1f8b77..ad96466d75f9977da4bcacc83715d5e90f415655 100644 --- a/test/lib/jdk/test/lib/hexdump/ASN1Formatter.java +++ b/test/lib/jdk/test/lib/hexdump/ASN1Formatter.java @@ -626,6 +626,7 @@ public class ASN1Formatter implements HexPrinter.Formatter { * @return the InputStream or the wrapped decoder of Base64Mime. * @throws IOException if an I/O error occurs */ + @SuppressWarnings("deprecation") private static InputStream wrapIfBase64Mime(BufferedInputStream bis) throws IOException { bis.mark(256); DataInputStream dis = new DataInputStream(bis); diff --git a/test/lib/jdk/test/lib/hexdump/StreamDump.java b/test/lib/jdk/test/lib/hexdump/StreamDump.java index 21ad296bca8c413e4bf78d7c395b798b16279f5c..cbdef1f61dc4d6f60fa51edfbb2cf18091242217 100644 --- a/test/lib/jdk/test/lib/hexdump/StreamDump.java +++ b/test/lib/jdk/test/lib/hexdump/StreamDump.java @@ -165,6 +165,7 @@ public class StreamDump { * @return an InputStream, unchanged unless it is Base64 Mime * @throws IOException if an I/O Error occurs */ + @SuppressWarnings("deprecation") static InputStream decodeMaybe(InputStream is) throws IOException { DataInputStream dis = new DataInputStream(is); is.mark(1024); diff --git a/test/lib/jdk/test/lib/net/testkeys b/test/lib/jdk/test/lib/net/testkeys index 4673898e0ae15936ac8b83357b802dc425f0c64c..d2818ec9b6c6dd5386a2cabe53b923bf6046e577 100644 Binary files a/test/lib/jdk/test/lib/net/testkeys and b/test/lib/jdk/test/lib/net/testkeys differ diff --git a/test/lib/jdk/test/lib/process/Proc.java b/test/lib/jdk/test/lib/process/Proc.java index def8796fce86a23349b56a7486b16b890d74eaba..3541f34144fe0c09d1331615aece1ee75566a3b6 100644 --- a/test/lib/jdk/test/lib/process/Proc.java +++ b/test/lib/jdk/test/lib/process/Proc.java @@ -113,8 +113,8 @@ public class Proc { private List<String> args = new ArrayList<>(); private Map<String,String> env = new HashMap<>(); - private Map<String,String> prop = new HashMap(); - private Map<String,String> secprop = new HashMap(); + private Map<String,String> prop = new HashMap<>(); + private Map<String,String> secprop = new HashMap<>(); private boolean inheritIO = false; private boolean noDump = false; diff --git a/test/lib/jdk/test/lib/process/ProcessTools.java b/test/lib/jdk/test/lib/process/ProcessTools.java index 7998bbbbe8248ef328a1b4d3709313550f3e10a2..19e3bb54785fc66bad837a152e00a4aa20021d80 100644 --- a/test/lib/jdk/test/lib/process/ProcessTools.java +++ b/test/lib/jdk/test/lib/process/ProcessTools.java @@ -432,6 +432,7 @@ public final class ProcessTools { * the default charset. * @return The {@linkplain OutputAnalyzer} instance wrapping the process. */ + @SuppressWarnings("removal") public static OutputAnalyzer executeProcess(ProcessBuilder pb, String input, Charset cs) throws Exception { OutputAnalyzer output = null; @@ -604,6 +605,7 @@ public final class ProcessTools { return pb; } + @SuppressWarnings("removal") private static Process privilegedStart(ProcessBuilder pb) throws IOException { try { return AccessController.doPrivileged( diff --git a/test/lib/jdk/test/lib/security/XMLUtils.java b/test/lib/jdk/test/lib/security/XMLUtils.java index bffab4be405797e4aa142a2c1a6ed71241df95d6..fa93e3f6b003207302f64c8032ddd1035d0be5f5 100644 --- a/test/lib/jdk/test/lib/security/XMLUtils.java +++ b/test/lib/jdk/test/lib/security/XMLUtils.java @@ -92,9 +92,11 @@ public class XMLUtils { Asserts.assertTrue(v2.validate(s3.sign(d))); // can read KeyInfo Asserts.assertTrue(v2.secureValidation(false).validate(s3.sign(p.toUri()))); // can read KeyInfo Asserts.assertTrue(v2.secureValidation(false).baseURI(b).validate( - s3.sign(p.getParent().toUri(), p.getFileName().toUri()))); // can read KeyInfo + s3.sign(p.toAbsolutePath().getParent().toUri(), p.getFileName().toUri()))); // can read KeyInfo Asserts.assertTrue(v1.validate(s1.sign("text"))); // plain text Asserts.assertTrue(v1.validate(s1.sign("binary".getBytes()))); // raw data + Asserts.assertTrue(v1.validate(s1.signEnveloping(d, "x", "#x"))); + Asserts.assertTrue(v1.validate(s1.signEnveloping(d, "x", "#xpointer(id('x'))"))); } //////////// CONVERT //////////// @@ -347,14 +349,14 @@ public class XMLUtils { } // Signs a document in enveloping mode - public Document signEnveloping(Document document) throws Exception { + public Document signEnveloping(Document document, String id, String ref) throws Exception { Document newDocument = DocumentBuilderFactory.newInstance() .newDocumentBuilder().newDocument(); FAC.newXMLSignature( - buildSignedInfo(FAC.newReference("#object", dm)), + buildSignedInfo(FAC.newReference(ref, dm)), buildKeyInfo(), List.of(FAC.newXMLObject(List.of(new DOMStructure(document.getDocumentElement())), - "object", null, null)), + id, null, null)), null, null) .sign(new DOMSignContext(privateKey, newDocument)); @@ -474,7 +476,7 @@ public class XMLUtils { // If key is not null, any key from the signature will be ignored public boolean validate(Document document, PublicKey key) throws Exception { - NodeList nodeList = document.getElementsByTagName("Signature"); + NodeList nodeList = document.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature"); if (nodeList.getLength() == 1) { Node signatureNode = nodeList.item(0); if (signatureNode != null) { diff --git a/test/lib/jdk/test/lib/util/CoreUtils.java b/test/lib/jdk/test/lib/util/CoreUtils.java index d7e68e82f427e4819596fbe2d5f2ed2fd01a4e1d..15de012534bba7e95758e50d61c4695c05c8d0b7 100644 --- a/test/lib/jdk/test/lib/util/CoreUtils.java +++ b/test/lib/jdk/test/lib/util/CoreUtils.java @@ -107,8 +107,10 @@ public class CoreUtils { // Find the core file String coreFileLocation = parseCoreFileLocationFromOutput(crashOutputString); if (coreFileLocation != null) { - System.out.println("Found core file: " + coreFileLocation); - Asserts.assertGT(new File(coreFileLocation).length(), 0L, "Unexpected core size"); + long coreFileSize = new File(coreFileLocation).length(); + System.out.println("Found core file " + coreFileLocation + + ", size = " + coreFileSize / 1024 / 1024 + "mb"); + Asserts.assertGT(coreFileSize, 0L, "Unexpected core size"); // Make sure the core file is moved into the cwd if not already there. Path corePath = Paths.get(coreFileLocation); diff --git a/test/lib/jdk/test/whitebox/WhiteBox.java b/test/lib/jdk/test/whitebox/WhiteBox.java index 4488559c4709701ecc4fbc9fdad0d8bcd35da4e9..e1e137f3b89598d5ad6f63433d97a12a1272016d 100644 --- a/test/lib/jdk/test/whitebox/WhiteBox.java +++ b/test/lib/jdk/test/whitebox/WhiteBox.java @@ -225,7 +225,6 @@ public class WhiteBox { public native void NMTReleaseMemory(long addr, long size); public native long NMTMallocWithPseudoStack(long size, int index); public native long NMTMallocWithPseudoStackAndType(long size, int index, int type); - public native boolean NMTChangeTrackingLevel(); public native int NMTGetHashSize(); public native long NMTNewArena(long initSize); public native void NMTFreeArena(long arena); @@ -317,6 +316,36 @@ public class WhiteBox { Objects.requireNonNull(method); return getMethodCompilationLevel0(method, isOsr); } + public int getMethodDecompileCount(Executable method) { + Objects.requireNonNull(method); + return getMethodDecompileCount0(method); + } + private native int getMethodDecompileCount0(Executable method); + // Get the total trap count of a method. If the trap count for a specific reason + // did overflow, this includes the overflow trap count of the method. + public int getMethodTrapCount(Executable method) { + Objects.requireNonNull(method); + return getMethodTrapCount0(method, null); + } + // Get the trap count of a method for a specific reason. If the trap count for + // that reason did overflow, this includes the overflow trap count of the method. + public int getMethodTrapCount(Executable method, String reason) { + Objects.requireNonNull(method); + return getMethodTrapCount0(method, reason); + } + private native int getMethodTrapCount0(Executable method, String reason); + // Get the total deopt count. + public int getDeoptCount() { + return getDeoptCount0(null, null); + } + // Get the deopt count for a specific reason and a specific action. If either + // one of 'reason' or 'action' is null, the method returns the sum of all + // deoptimizations with the specific 'action' or 'reason' respectively. + // If both arguments are null, the method returns the total deopt count. + public int getDeoptCount(String reason, String action) { + return getDeoptCount0(reason, action); + } + private native int getDeoptCount0(String reason, String action); private native boolean testSetDontInlineMethod0(Executable method, boolean value); public boolean testSetDontInlineMethod(Executable method, boolean value) { Objects.requireNonNull(method); diff --git a/test/lib/sun/hotspot/WhiteBox.java b/test/lib/sun/hotspot/WhiteBox.java index 8db7ec3baafc25825f8dacf9351be9b217f88112..1729545b0bb85d48f61c06e7445d80aa910a14ca 100644 --- a/test/lib/sun/hotspot/WhiteBox.java +++ b/test/lib/sun/hotspot/WhiteBox.java @@ -226,7 +226,6 @@ public class WhiteBox { public native void NMTReleaseMemory(long addr, long size); public native long NMTMallocWithPseudoStack(long size, int index); public native long NMTMallocWithPseudoStackAndType(long size, int index, int type); - public native boolean NMTChangeTrackingLevel(); public native int NMTGetHashSize(); public native long NMTNewArena(long initSize); public native void NMTFreeArena(long arena); @@ -318,6 +317,36 @@ public class WhiteBox { Objects.requireNonNull(method); return getMethodCompilationLevel0(method, isOsr); } + public int getMethodDecompileCount(Executable method) { + Objects.requireNonNull(method); + return getMethodDecompileCount0(method); + } + private native int getMethodDecompileCount0(Executable method); + // Get the total trap count of a method. If the trap count for a specific reason + // did overflow, this includes the overflow trap count of the method. + public int getMethodTrapCount(Executable method) { + Objects.requireNonNull(method); + return getMethodTrapCount0(method, null); + } + // Get the trap count of a method for a specific reason. If the trap count for + // that reason did overflow, this includes the overflow trap count of the method. + public int getMethodTrapCount(Executable method, String reason) { + Objects.requireNonNull(method); + return getMethodTrapCount0(method, reason); + } + private native int getMethodTrapCount0(Executable method, String reason); + // Get the total deopt count. + public int getDeoptCount() { + return getDeoptCount0(null, null); + } + // Get the deopt count for a specific reason and a specific action. If either + // one of 'reason' or 'action' is null, the method returns the sum of all + // deoptimizations with the specific 'action' or 'reason' respectively. + // If both arguments are null, the method returns the total deopt count. + public int getDeoptCount(String reason, String action) { + return getDeoptCount0(reason, action); + } + private native int getDeoptCount0(String reason, String action); private native boolean testSetDontInlineMethod0(Executable method, boolean value); public boolean testSetDontInlineMethod(Executable method, boolean value) { Objects.requireNonNull(method); diff --git a/test/micro/org/openjdk/bench/java/lang/ThreadOnSpinWaitProducerConsumer.java b/test/micro/org/openjdk/bench/java/lang/ThreadOnSpinWaitProducerConsumer.java index e111b77ab5171fc95f5afafcdc563b84fb99c49d..a4778838a84446c0aefc4c1aa446cb8d001f605c 100644 --- a/test/micro/org/openjdk/bench/java/lang/ThreadOnSpinWaitProducerConsumer.java +++ b/test/micro/org/openjdk/bench/java/lang/ThreadOnSpinWaitProducerConsumer.java @@ -193,6 +193,7 @@ public class ThreadOnSpinWaitProducerConsumer { } } threadConsumer.interrupt(); + threadConsumer.join(); if (producedDataCount != maxNum) { throw new RuntimeException("Produced: " + producedDataCount + ". Expected: " + maxNum); diff --git a/test/micro/org/openjdk/bench/java/util/RandomGeneratorNext.java b/test/micro/org/openjdk/bench/java/util/RandomGeneratorNext.java new file mode 100644 index 0000000000000000000000000000000000000000..adb70e195e4233cb0500c44cfc5aae45eb89e178 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/RandomGeneratorNext.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Param; +import java.util.random.RandomGenerator; +import java.util.random.RandomGeneratorFactory; +import java.util.concurrent.TimeUnit; + +/** + * Tests java.util.random.RandomGenerator's different random number generators which use Math.unsignedMultiplyHigh(). + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class RandomGeneratorNext { + + RandomGenerator randomGenerator; + + @Param({"L128X128MixRandom", "L128X256MixRandom", "L128X1024MixRandom"}) + String randomGeneratorName; + + long[] buffer; + + @Param("1024") + int size; + + @Setup + public void setup() { + buffer = new long[size]; + randomGenerator = RandomGeneratorFactory.of(randomGeneratorName).create(randomGeneratorName.hashCode()); + } + + @Benchmark + public long testNextLong() { + return randomGenerator.nextLong(); + } + + @Benchmark + public long[] testFillBufferWithNextLong() { + for (int i = 0; i < size; i++) buffer[i] = randomGenerator.nextLong(); + return buffer; + } + +} diff --git a/test/micro/org/openjdk/bench/java/util/TestCRC32C.java b/test/micro/org/openjdk/bench/java/util/TestCRC32C.java new file mode 100644 index 0000000000000000000000000000000000000000..0c3b39fc59a67dd3570ede9f9d27c3b5b0c72498 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/TestCRC32C.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util; + +import java.util.Random; +import java.util.concurrent.TimeUnit; +import java.util.zip.CRC32C; +import org.openjdk.jmh.annotations.*; + +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Benchmark) +@Fork(value = 2) + +public class TestCRC32C { + + private CRC32C crc32c; + private Random random; + private byte[] bytes; + + @Param({"64", "128", "256", "512", "1024", "2048", "4096", "8192", "16384", "32768", "65536"}) + private int count; + + public TestCRC32C() { + crc32c = new CRC32C(); + random = new Random(2147483648L); + bytes = new byte[1000000]; + random.nextBytes(bytes); + } + + @Setup(Level.Iteration) + public void setupBytes() { + crc32c.reset(); + } + + @Benchmark + public void testCRC32CUpdate() { + crc32c.update(bytes, 0, count); + } +} diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/BulkMismatchAcquire.java b/test/micro/org/openjdk/bench/jdk/incubator/foreign/BulkMismatchAcquire.java index 5d962ee39796e986df28531dc205c6cc67e51dec..c9fc3abd33a5c7748f5d509c0adcf831da944ac9 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/foreign/BulkMismatchAcquire.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/BulkMismatchAcquire.java @@ -26,7 +26,6 @@ package org.openjdk.bench.jdk.incubator.foreign; import jdk.incubator.foreign.ResourceScope; -import jdk.incubator.foreign.SegmentAllocator; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -38,15 +37,12 @@ import org.openjdk.jmh.annotations.Setup; import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.annotations.TearDown; import org.openjdk.jmh.annotations.Warmup; -import sun.misc.Unsafe; import jdk.incubator.foreign.MemorySegment; import java.nio.ByteBuffer; import java.util.concurrent.TimeUnit; import java.util.function.Supplier; -import static jdk.incubator.foreign.MemoryLayouts.JAVA_INT; - @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @@ -71,7 +67,7 @@ public class BulkMismatchAcquire { } } - @Param({"CONFINED", "SHARED", "IMPLICIT"}) + @Param({"CONFINED", "SHARED"}) public ScopeKind scopeKind; // large(ish) segments/buffers with same content, 0, for mismatch, non-multiple-of-8 sized @@ -121,8 +117,7 @@ public class BulkMismatchAcquire { @TearDown public void tearDown() { - if (!scope.isImplicit()) - scope.close(); + scope.close(); } @Benchmark @@ -134,11 +129,9 @@ public class BulkMismatchAcquire { @Benchmark @OutputTimeUnit(TimeUnit.NANOSECONDS) public long mismatch_large_segment_acquire() { - var handle = mismatchSegmentLarge1.scope().acquire(); - try { + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + scope.keepAlive(mismatchSegmentLarge1.scope()); return mismatchSegmentLarge1.mismatch(mismatchSegmentLarge2); - } finally { - mismatchSegmentLarge1.scope().release(handle); } } @@ -157,11 +150,9 @@ public class BulkMismatchAcquire { @Benchmark @OutputTimeUnit(TimeUnit.NANOSECONDS) public long mismatch_small_segment_acquire() { - var handle = mismatchSegmentLarge1.scope().acquire(); - try { + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + scope.keepAlive(mismatchSegmentLarge1.scope()); return mismatchSegmentSmall1.mismatch(mismatchSegmentSmall2); - } finally { - mismatchSegmentLarge1.scope().release(handle); } } diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/BulkOps.java b/test/micro/org/openjdk/bench/jdk/incubator/foreign/BulkOps.java index ac92e9429cae1382dfc49c7dc8f40cdffe1d13f8..25d6cf557b0398c5f0b311acc98baf5bd227bc0b 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/foreign/BulkOps.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/BulkOps.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,19 +27,23 @@ package org.openjdk.bench.jdk.incubator.foreign; import jdk.incubator.foreign.ResourceScope; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.CompilerControl; import org.openjdk.jmh.annotations.Fork; import org.openjdk.jmh.annotations.Measurement; import org.openjdk.jmh.annotations.Mode; import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Setup; import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; import org.openjdk.jmh.annotations.Warmup; import sun.misc.Unsafe; import jdk.incubator.foreign.MemorySegment; import java.nio.ByteBuffer; +import java.nio.IntBuffer; import java.util.concurrent.TimeUnit; -import static jdk.incubator.foreign.MemoryLayouts.JAVA_INT; +import static jdk.incubator.foreign.ValueLayout.JAVA_INT; @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) @@ -55,26 +59,31 @@ public class BulkOps { static final int CARRIER_SIZE = (int)JAVA_INT.byteSize(); static final int ALLOC_SIZE = ELEM_SIZE * CARRIER_SIZE; - static final long unsafe_addr = unsafe.allocateMemory(ALLOC_SIZE); - static final MemorySegment segment = MemorySegment.allocateNative(ALLOC_SIZE, ResourceScope.newConfinedScope()); + final ResourceScope scope = ResourceScope.newConfinedScope(); - static final int[] bytes = new int[ELEM_SIZE]; - static final MemorySegment bytesSegment = MemorySegment.ofArray(bytes); - static final int UNSAFE_INT_OFFSET = unsafe.arrayBaseOffset(int[].class); + final long unsafe_addr = unsafe.allocateMemory(ALLOC_SIZE); + final MemorySegment segment = MemorySegment.allocateNative(ALLOC_SIZE, ResourceScope.newConfinedScope()); + final IntBuffer buffer = IntBuffer.allocate(ELEM_SIZE); + + final int[] bytes = new int[ELEM_SIZE]; + final MemorySegment bytesSegment = MemorySegment.ofArray(bytes); + final int UNSAFE_INT_OFFSET = unsafe.arrayBaseOffset(int[].class); // large(ish) segments/buffers with same content, 0, for mismatch, non-multiple-of-8 sized static final int SIZE_WITH_TAIL = (1024 * 1024) + 7; - static final MemorySegment mismatchSegmentLarge1 = MemorySegment.allocateNative(SIZE_WITH_TAIL, ResourceScope.newConfinedScope()); - static final MemorySegment mismatchSegmentLarge2 = MemorySegment.allocateNative(SIZE_WITH_TAIL, ResourceScope.newConfinedScope()); - static final ByteBuffer mismatchBufferLarge1 = ByteBuffer.allocateDirect(SIZE_WITH_TAIL); - static final ByteBuffer mismatchBufferLarge2 = ByteBuffer.allocateDirect(SIZE_WITH_TAIL); + final MemorySegment mismatchSegmentLarge1 = MemorySegment.allocateNative(SIZE_WITH_TAIL, scope); + final MemorySegment mismatchSegmentLarge2 = MemorySegment.allocateNative(SIZE_WITH_TAIL, scope); + final ByteBuffer mismatchBufferLarge1 = ByteBuffer.allocateDirect(SIZE_WITH_TAIL); + final ByteBuffer mismatchBufferLarge2 = ByteBuffer.allocateDirect(SIZE_WITH_TAIL); // mismatch at first byte - static final MemorySegment mismatchSegmentSmall1 = MemorySegment.allocateNative(7, ResourceScope.newConfinedScope()); - static final MemorySegment mismatchSegmentSmall2 = MemorySegment.allocateNative(7, ResourceScope.newConfinedScope()); - static final ByteBuffer mismatchBufferSmall1 = ByteBuffer.allocateDirect(7); - static final ByteBuffer mismatchBufferSmall2 = ByteBuffer.allocateDirect(7); - static { + final MemorySegment mismatchSegmentSmall1 = MemorySegment.allocateNative(7, scope); + final MemorySegment mismatchSegmentSmall2 = MemorySegment.allocateNative(7, scope); + final ByteBuffer mismatchBufferSmall1 = ByteBuffer.allocateDirect(7); + final ByteBuffer mismatchBufferSmall2 = ByteBuffer.allocateDirect(7); + + @Setup + public void setup() { mismatchSegmentSmall1.fill((byte) 0xFF); mismatchBufferSmall1.put((byte) 0xFF).clear(); // verify expected mismatch indices @@ -90,14 +99,17 @@ public class BulkOps { bi = mismatchBufferSmall1.mismatch(mismatchBufferSmall2); if (bi != 0) throw new AssertionError("Unexpected mismatch index:" + bi); - } - static { for (int i = 0 ; i < bytes.length ; i++) { bytes[i] = i; } } + @TearDown + public void tearDown() { + scope.close(); + } + @Benchmark @OutputTimeUnit(TimeUnit.NANOSECONDS) public void unsafe_fill() { @@ -122,6 +134,50 @@ public class BulkOps { segment.copyFrom(bytesSegment); } + @Benchmark + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public void segment_copy_static() { + MemorySegment.copy(bytes, 0, segment, JAVA_INT, 0, bytes.length); + } + + @Benchmark + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public void segment_copy_static_small() { + MemorySegment.copy(bytes, 0, segment, JAVA_INT, 0, 10); + } + + @Benchmark + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public void segment_copy_static_small_dontinline() { + MemorySegment.copy(bytes, 0, segment, JAVA_INT, 0, 10); + } + + @Benchmark + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public void unsafe_copy_small() { + unsafe.copyMemory(bytes, UNSAFE_INT_OFFSET, null, unsafe_addr, 10 * CARRIER_SIZE); + } + + @Benchmark + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public void buffer_copy_small() { + buffer.put(0, bytes, 0, 10); + } + + @Benchmark + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public void buffer_copy() { + buffer.put(0, bytes, 0, bytes.length); + } + + @Benchmark + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public void segment_copy_static_dontinline() { + MemorySegment.copy(bytes, 0, segment, JAVA_INT, 0, bytes.length); + } + @Benchmark @OutputTimeUnit(TimeUnit.NANOSECONDS) public long mismatch_large_segment() { diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/CLayouts.java b/test/micro/org/openjdk/bench/jdk/incubator/foreign/CLayouts.java new file mode 100644 index 0000000000000000000000000000000000000000..530731e34bfc6221adba5376f490790105d4224c --- /dev/null +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/CLayouts.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.openjdk.bench.jdk.incubator.foreign; + +import jdk.incubator.foreign.Addressable; +import jdk.incubator.foreign.CLinker; +import jdk.incubator.foreign.FunctionDescriptor; +import jdk.incubator.foreign.MemoryAddress; +import jdk.incubator.foreign.ValueLayout; + +import java.lang.invoke.MethodHandle; + +public class CLayouts { + + // the constants below are useful aliases for C types. The type/carrier association is only valid for 64-bit platforms. + + /** + * The layout for the {@code bool} C type + */ + public static final ValueLayout.OfBoolean C_BOOL = ValueLayout.JAVA_BOOLEAN; + /** + * The layout for the {@code char} C type + */ + public static final ValueLayout.OfByte C_CHAR = ValueLayout.JAVA_BYTE; + /** + * The layout for the {@code short} C type + */ + public static final ValueLayout.OfShort C_SHORT = ValueLayout.JAVA_SHORT; + /** + * The layout for the {@code int} C type + */ + public static final ValueLayout.OfInt C_INT = ValueLayout.JAVA_INT; + + /** + * The layout for the {@code long long} C type. + */ + public static final ValueLayout.OfLong C_LONG_LONG = ValueLayout.JAVA_LONG; + /** + * The layout for the {@code float} C type + */ + public static final ValueLayout.OfFloat C_FLOAT = ValueLayout.JAVA_FLOAT; + /** + * The layout for the {@code double} C type + */ + public static final ValueLayout.OfDouble C_DOUBLE = ValueLayout.JAVA_DOUBLE; + /** + * The {@code T*} native type. + */ + public static final ValueLayout.OfAddress C_POINTER = ValueLayout.ADDRESS; + + private static CLinker LINKER = CLinker.systemCLinker(); + + private static final MethodHandle FREE = LINKER.downcallHandle( + LINKER.lookup("free").get(), FunctionDescriptor.ofVoid(ValueLayout.ADDRESS)); + + private static final MethodHandle MALLOC = LINKER.downcallHandle( + LINKER.lookup("malloc").get(), FunctionDescriptor.of(ValueLayout.ADDRESS, ValueLayout.JAVA_LONG)); + + public static void freeMemory(Addressable address) { + try { + FREE.invokeExact(address); + } catch (Throwable ex) { + throw new IllegalStateException(ex); + } + } + + public static MemoryAddress allocateMemory(long size) { + try { + return (MemoryAddress)MALLOC.invokeExact(size); + } catch (Throwable ex) { + throw new IllegalStateException(ex); + } + } +} diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/CallOverheadConstant.java b/test/micro/org/openjdk/bench/jdk/incubator/foreign/CallOverheadConstant.java index bd627646770b9cd2e442569e72c9a7898057bb36..8fe3d1b1ea472d461e61d7517686d42d12839a81 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/foreign/CallOverheadConstant.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/CallOverheadConstant.java @@ -22,6 +22,7 @@ */ package org.openjdk.bench.jdk.incubator.foreign; +import jdk.incubator.foreign.Addressable; import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemorySegment; import org.openjdk.jmh.annotations.Benchmark; @@ -55,11 +56,6 @@ public class CallOverheadConstant { func.invokeExact(); } - @Benchmark - public void panama_blank_trivial() throws Throwable { - func_trivial.invokeExact(); - } - @Benchmark public int jni_identity() throws Throwable { return identity(10); @@ -71,18 +67,73 @@ public class CallOverheadConstant { } @Benchmark - public int panama_identity_trivial() throws Throwable { - return (int) identity_trivial.invokeExact(10); + public MemorySegment panama_identity_struct_confined() throws Throwable { + return (MemorySegment) identity_struct.invokeExact(recycling_allocator, confinedPoint); + } + + @Benchmark + public MemorySegment panama_identity_struct_shared() throws Throwable { + return (MemorySegment) identity_struct.invokeExact(recycling_allocator, sharedPoint); + } + + @Benchmark + public MemorySegment panama_identity_struct_confined_3() throws Throwable { + return (MemorySegment) identity_struct_3.invokeExact(recycling_allocator, confinedPoint, confinedPoint, confinedPoint); + } + + @Benchmark + public MemorySegment panama_identity_struct_shared_3() throws Throwable { + return (MemorySegment) identity_struct_3.invokeExact(recycling_allocator, sharedPoint, sharedPoint, sharedPoint); + } + + @Benchmark + public MemoryAddress panama_identity_memory_address_shared() throws Throwable { + return (MemoryAddress) identity_memory_address.invokeExact((Addressable)sharedPoint.address()); + } + + @Benchmark + public MemoryAddress panama_identity_memory_address_confined() throws Throwable { + return (MemoryAddress) identity_memory_address.invokeExact((Addressable)confinedPoint.address()); + } + + @Benchmark + public MemoryAddress panama_identity_memory_address_shared_3() throws Throwable { + return (MemoryAddress) identity_memory_address_3.invokeExact((Addressable)sharedPoint.address(), (Addressable)sharedPoint.address(), (Addressable)sharedPoint.address()); + } + + @Benchmark + public MemoryAddress panama_identity_memory_address_confined_3() throws Throwable { + return (MemoryAddress) identity_memory_address_3.invokeExact((Addressable)confinedPoint.address(), (Addressable)confinedPoint.address(), (Addressable)confinedPoint.address()); + } + + @Benchmark + public MemoryAddress panama_identity_struct_ref_shared() throws Throwable { + return (MemoryAddress) identity_memory_address.invokeExact((Addressable)sharedPoint); + } + + @Benchmark + public MemoryAddress panama_identity_struct_ref_confined() throws Throwable { + return (MemoryAddress) identity_memory_address.invokeExact((Addressable)confinedPoint); + } + + @Benchmark + public MemoryAddress panama_identity_struct_ref_shared_3() throws Throwable { + return (MemoryAddress) identity_memory_address_3.invokeExact((Addressable)sharedPoint, (Addressable)sharedPoint, (Addressable)sharedPoint); + } + + @Benchmark + public MemoryAddress panama_identity_struct_ref_confined_3() throws Throwable { + return (MemoryAddress) identity_memory_address_3.invokeExact((Addressable)confinedPoint, (Addressable)confinedPoint, (Addressable)confinedPoint); } @Benchmark - public MemorySegment panama_identity_struct() throws Throwable { - return (MemorySegment) identity_struct.invokeExact(recycling_allocator, point); + public MemoryAddress panama_identity_memory_address_null() throws Throwable { + return (MemoryAddress) identity_memory_address.invokeExact((Addressable)MemoryAddress.NULL); } @Benchmark - public MemoryAddress panama_identity_memory_address() throws Throwable { - return (MemoryAddress) identity_memory_address.invokeExact(MemoryAddress.NULL); + public MemoryAddress panama_identity_memory_address_null_non_exact() throws Throwable { + return (MemoryAddress) identity_memory_address.invoke(MemoryAddress.NULL); } @Benchmark diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/CallOverheadHelper.java b/test/micro/org/openjdk/bench/jdk/incubator/foreign/CallOverheadHelper.java index 4989f5fa47e5f644f927756d41455c29443d6684..259c4b26bdd6ad2c5fd21f8827fca322a696fe83 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/foreign/CallOverheadHelper.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/CallOverheadHelper.java @@ -22,12 +22,11 @@ */ package org.openjdk.bench.jdk.incubator.foreign; -import jdk.incubator.foreign.Addressable; import jdk.incubator.foreign.CLinker; import jdk.incubator.foreign.FunctionDescriptor; -import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.NativeSymbol; import jdk.incubator.foreign.ResourceScope; import jdk.incubator.foreign.SegmentAllocator; import jdk.incubator.foreign.SymbolLookup; @@ -36,57 +35,58 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; import static java.lang.invoke.MethodHandles.insertArguments; -import static jdk.incubator.foreign.CLinker.C_DOUBLE; -import static jdk.incubator.foreign.CLinker.C_INT; -import static jdk.incubator.foreign.CLinker.C_LONG_LONG; -import static jdk.incubator.foreign.CLinker.C_POINTER; -public class CallOverheadHelper { +public class CallOverheadHelper extends CLayouts { - static final CLinker abi = CLinker.getInstance(); + static final CLinker abi = CLinker.systemCLinker(); static final MethodHandle func; static final MethodHandle func_v; - static Addressable func_addr; + static NativeSymbol func_addr; static final MethodHandle identity; static final MethodHandle identity_v; - static Addressable identity_addr; + static NativeSymbol identity_addr; static final MethodHandle identity_struct; static final MethodHandle identity_struct_v; - static Addressable identity_struct_addr; + static NativeSymbol identity_struct_addr; + static final MethodHandle identity_struct_3; + static final MethodHandle identity_struct_3_v; + static NativeSymbol identity_struct_3_addr; static final MethodHandle identity_memory_address; static final MethodHandle identity_memory_address_v; - static Addressable identity_memory_address_addr; + static NativeSymbol identity_memory_address_addr; + static final MethodHandle identity_memory_address_3; + static final MethodHandle identity_memory_address_3_v; + static NativeSymbol identity_memory_address_3_addr; static final MethodHandle args1; static final MethodHandle args1_v; - static Addressable args1_addr; + static NativeSymbol args1_addr; static final MethodHandle args2; static final MethodHandle args2_v; - static Addressable args2_addr; + static NativeSymbol args2_addr; static final MethodHandle args3; static final MethodHandle args3_v; - static Addressable args3_addr; + static NativeSymbol args3_addr; static final MethodHandle args4; static final MethodHandle args4_v; - static Addressable args4_addr; + static NativeSymbol args4_addr; static final MethodHandle args5; static final MethodHandle args5_v; - static Addressable args5_addr; + static NativeSymbol args5_addr; static final MethodHandle args10; static final MethodHandle args10_v; - static Addressable args10_addr; - static final MethodHandle func_trivial; - static final MethodHandle func_trivial_v; - static final MethodHandle identity_trivial; - static final MethodHandle identity_trivial_v; + static NativeSymbol args10_addr; static final MemoryLayout POINT_LAYOUT = MemoryLayout.structLayout( - C_LONG_LONG, C_LONG_LONG + C_INT, C_INT ); + static final MemorySegment sharedPoint = MemorySegment.allocateNative(POINT_LAYOUT, ResourceScope.newSharedScope()); + static final MemorySegment confinedPoint = MemorySegment.allocateNative(POINT_LAYOUT, ResourceScope.newConfinedScope()); + static final MemorySegment point = MemorySegment.allocateNative(POINT_LAYOUT, ResourceScope.newImplicitScope()); - static final SegmentAllocator recycling_allocator = SegmentAllocator.ofSegment(MemorySegment.allocateNative(POINT_LAYOUT, ResourceScope.newImplicitScope())); + static final SegmentAllocator recycling_allocator = SegmentAllocator.prefixAllocator(MemorySegment.allocateNative(POINT_LAYOUT, ResourceScope.newImplicitScope())); static { System.loadLibrary("CallOverheadJNI"); @@ -97,66 +97,62 @@ public class CallOverheadHelper { func_addr = lookup.lookup("func").orElseThrow(); MethodType mt = MethodType.methodType(void.class); FunctionDescriptor fd = FunctionDescriptor.ofVoid(); - func_v = abi.downcallHandle(mt, fd); + func_v = abi.downcallHandle(fd); func = insertArguments(func_v, 0, func_addr); - func_trivial_v = abi.downcallHandle(mt, fd.withAttribute(FunctionDescriptor.TRIVIAL_ATTRIBUTE_NAME, true)); - func_trivial = insertArguments(func_trivial_v, 0, func_addr); } { identity_addr = lookup.lookup("identity").orElseThrow(); - MethodType mt = MethodType.methodType(int.class, int.class); FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT); - identity_v = abi.downcallHandle(mt, fd); + identity_v = abi.downcallHandle(fd); identity = insertArguments(identity_v, 0, identity_addr); - identity_trivial_v = abi.downcallHandle(mt, fd.withAttribute(FunctionDescriptor.TRIVIAL_ATTRIBUTE_NAME, true)); - identity_trivial = insertArguments(identity_trivial_v, 0, identity_addr); } identity_struct_addr = lookup.lookup("identity_struct").orElseThrow(); identity_struct_v = abi.downcallHandle( - MethodType.methodType(MemorySegment.class, MemorySegment.class), FunctionDescriptor.of(POINT_LAYOUT, POINT_LAYOUT)); identity_struct = insertArguments(identity_struct_v, 0, identity_struct_addr); + identity_struct_3_addr = lookup.lookup("identity_struct_3").orElseThrow(); + identity_struct_3_v = abi.downcallHandle( + FunctionDescriptor.of(POINT_LAYOUT, POINT_LAYOUT, POINT_LAYOUT, POINT_LAYOUT)); + identity_struct_3 = insertArguments(identity_struct_3_v, 0, identity_struct_3_addr); + identity_memory_address_addr = lookup.lookup("identity_memory_address").orElseThrow(); identity_memory_address_v = abi.downcallHandle( - MethodType.methodType(MemoryAddress.class, MemoryAddress.class), FunctionDescriptor.of(C_POINTER, C_POINTER)); identity_memory_address = insertArguments(identity_memory_address_v, 0, identity_memory_address_addr); + identity_memory_address_3_addr = lookup.lookup("identity_memory_address_3").orElseThrow(); + identity_memory_address_3_v = abi.downcallHandle( + FunctionDescriptor.of(C_POINTER, C_POINTER, C_POINTER, C_POINTER)); + identity_memory_address_3 = insertArguments(identity_memory_address_3_v, 0, identity_memory_address_3_addr); + args1_addr = lookup.lookup("args1").orElseThrow(); args1_v = abi.downcallHandle( - MethodType.methodType(void.class, long.class), FunctionDescriptor.ofVoid(C_LONG_LONG)); args1 = insertArguments(args1_v, 0, args1_addr); args2_addr = lookup.lookup("args2").orElseThrow(); args2_v = abi.downcallHandle( - MethodType.methodType(void.class, long.class, double.class), FunctionDescriptor.ofVoid(C_LONG_LONG, C_DOUBLE)); args2 = insertArguments(args2_v, 0, args2_addr); args3_addr = lookup.lookup("args3").orElseThrow(); args3_v = abi.downcallHandle( - MethodType.methodType(void.class, long.class, double.class, long.class), FunctionDescriptor.ofVoid(C_LONG_LONG, C_DOUBLE, C_LONG_LONG)); args3 = insertArguments(args3_v, 0, args3_addr); args4_addr = lookup.lookup("args4").orElseThrow(); args4_v = abi.downcallHandle( - MethodType.methodType(void.class, long.class, double.class, long.class, double.class), FunctionDescriptor.ofVoid(C_LONG_LONG, C_DOUBLE, C_LONG_LONG, C_DOUBLE)); args4 = insertArguments(args4_v, 0, args4_addr); args5_addr = lookup.lookup("args5").orElseThrow(); args5_v = abi.downcallHandle( - MethodType.methodType(void.class, long.class, double.class, long.class, double.class, long.class), FunctionDescriptor.ofVoid(C_LONG_LONG, C_DOUBLE, C_LONG_LONG, C_DOUBLE, C_LONG_LONG)); args5 = insertArguments(args5_v, 0, args5_addr); args10_addr = lookup.lookup("args10").orElseThrow(); args10_v = abi.downcallHandle( - MethodType.methodType(void.class, long.class, double.class, long.class, double.class, long.class, - double.class, long.class, double.class, long.class, double.class), FunctionDescriptor.ofVoid(C_LONG_LONG, C_DOUBLE, C_LONG_LONG, C_DOUBLE, C_LONG_LONG, C_DOUBLE, C_LONG_LONG, C_DOUBLE, C_LONG_LONG, C_DOUBLE)); args10 = insertArguments(args10_v, 0, args10_addr); diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/CallOverheadVirtual.java b/test/micro/org/openjdk/bench/jdk/incubator/foreign/CallOverheadVirtual.java index e1e557bad237866ea82116b488f115787fe01ec7..11152bdd04414acee7c9c1d811f58252f6caf2dd 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/foreign/CallOverheadVirtual.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/CallOverheadVirtual.java @@ -22,6 +22,7 @@ */ package org.openjdk.bench.jdk.incubator.foreign; +import jdk.incubator.foreign.Addressable; import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemorySegment; import org.openjdk.jmh.annotations.Benchmark; @@ -56,23 +57,72 @@ public class CallOverheadVirtual { } @Benchmark - public void panama_blank_trivial() throws Throwable { - func_trivial_v.invokeExact(func_addr); + public int jni_identity() throws Throwable { + return identity(10); + } + + public MemorySegment panama_identity_struct_confined() throws Throwable { + return (MemorySegment) identity_struct_v.invokeExact(identity_struct_addr, recycling_allocator, confinedPoint); } @Benchmark - public int jni_identity() throws Throwable { - return identity(10); + public MemorySegment panama_identity_struct_shared() throws Throwable { + return (MemorySegment) identity_struct_v.invokeExact(identity_struct_addr, recycling_allocator, sharedPoint); } @Benchmark - public int panama_identity() throws Throwable { - return (int) identity_v.invokeExact(identity_addr, 10); + public MemorySegment panama_identity_struct_confined_3() throws Throwable { + return (MemorySegment) identity_struct_3_v.invokeExact(identity_struct_3_addr, recycling_allocator, confinedPoint, confinedPoint, confinedPoint); } @Benchmark - public int panama_identity_trivial() throws Throwable { - return (int) identity_trivial_v.invokeExact(identity_addr, 10); + public MemorySegment panama_identity_struct_shared_3() throws Throwable { + return (MemorySegment) identity_struct_3_v.invokeExact(identity_struct_3_addr, recycling_allocator, sharedPoint, sharedPoint, sharedPoint); + } + + @Benchmark + public MemoryAddress panama_identity_memory_address_shared() throws Throwable { + return (MemoryAddress) identity_memory_address_v.invokeExact(identity_memory_address_addr, (Addressable)sharedPoint.address()); + } + + @Benchmark + public MemoryAddress panama_identity_memory_address_confined() throws Throwable { + return (MemoryAddress) identity_memory_address_v.invokeExact(identity_memory_address_addr, (Addressable)confinedPoint.address()); + } + + @Benchmark + public MemoryAddress panama_identity_memory_address_shared_3() throws Throwable { + return (MemoryAddress) identity_memory_address_3_v.invokeExact(identity_memory_address_3_addr, (Addressable)sharedPoint.address(), (Addressable)sharedPoint.address(), (Addressable)sharedPoint.address()); + } + + @Benchmark + public MemoryAddress panama_identity_memory_address_confined_3() throws Throwable { + return (MemoryAddress) identity_memory_address_3_v.invokeExact(identity_memory_address_3_addr, (Addressable)confinedPoint.address(), (Addressable)confinedPoint.address(), (Addressable)confinedPoint.address()); + } + + @Benchmark + public MemoryAddress panama_identity_struct_ref_shared() throws Throwable { + return (MemoryAddress) identity_memory_address_v.invokeExact(identity_struct_addr, (Addressable)sharedPoint); + } + + @Benchmark + public MemoryAddress panama_identity_struct_ref_confined() throws Throwable { + return (MemoryAddress) identity_memory_address_v.invokeExact(identity_struct_addr, (Addressable)confinedPoint); + } + + @Benchmark + public MemoryAddress panama_identity_struct_ref_shared_3() throws Throwable { + return (MemoryAddress) identity_memory_address_3_v.invokeExact(identity_struct_3_addr, (Addressable)sharedPoint, (Addressable)sharedPoint, (Addressable)sharedPoint); + } + + @Benchmark + public MemoryAddress panama_identity_struct_ref_confined_3() throws Throwable { + return (MemoryAddress) identity_memory_address_3_v.invokeExact(identity_struct_3_addr, (Addressable)confinedPoint, (Addressable)confinedPoint, (Addressable)confinedPoint); + } + + @Benchmark + public int panama_identity() throws Throwable { + return (int) identity_v.invokeExact(identity_addr, 10); } @Benchmark @@ -81,8 +131,8 @@ public class CallOverheadVirtual { } @Benchmark - public MemoryAddress panama_identity_memory_address() throws Throwable { - return (MemoryAddress) identity_memory_address_v.invokeExact(identity_memory_address_addr, MemoryAddress.NULL); + public MemoryAddress panama_identity_memory_address_null() throws Throwable { + return (MemoryAddress) identity_memory_address_v.invokeExact(identity_memory_address_addr, (Addressable)MemoryAddress.NULL); } @Benchmark diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/JNICB.h b/test/micro/org/openjdk/bench/jdk/incubator/foreign/JNICB.h new file mode 100644 index 0000000000000000000000000000000000000000..9af5383ead7f4ee5732d47ef9088bf14ce20e99a --- /dev/null +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/JNICB.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include <jni.h> + +typedef struct { + jclass holder; + jmethodID mid; +} *JNICB; diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/JNICB.java b/test/micro/org/openjdk/bench/jdk/incubator/foreign/JNICB.java new file mode 100644 index 0000000000000000000000000000000000000000..89ead66025e35c16d948a3be89a94cd75d1376aa --- /dev/null +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/JNICB.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.openjdk.bench.jdk.incubator.foreign; + +public class JNICB { + + static { + System.loadLibrary("JNICB"); + } + + public static native long makeCB(String holder, String name, String signature); +} diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverConstant.java b/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverConstant.java index 64cc3697687e0628170b71669686bfba3237db14..e1b1b86b61ab7cfe19598b9e88e3600a4bc4ba31 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverConstant.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverConstant.java @@ -44,7 +44,7 @@ import java.nio.ByteOrder; import java.util.concurrent.TimeUnit; import static jdk.incubator.foreign.MemoryLayout.PathElement.sequenceElement; -import static jdk.incubator.foreign.MemoryLayouts.JAVA_INT; +import static jdk.incubator.foreign.ValueLayout.JAVA_INT; @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) @@ -73,7 +73,7 @@ public class LoopOverConstant { //setup native memory segment static final MemorySegment segment = MemorySegment.allocateNative(ALLOC_SIZE, ResourceScope.newImplicitScope()); - static final VarHandle VH_int = MemoryLayout.sequenceLayout(JAVA_INT).varHandle(int.class, sequenceElement()); + static final VarHandle VH_int = MemoryLayout.sequenceLayout(JAVA_INT).varHandle(sequenceElement()); static { for (int i = 0; i < ELEM_SIZE; i++) { diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverNew.java b/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverNew.java index 0d59d83488fa6e3f44e67f635d0521d1078b7511..c50148e46e682e631079abe778f0e9d06a99b3d0 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverNew.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverNew.java @@ -44,7 +44,7 @@ import java.nio.ByteOrder; import java.util.concurrent.TimeUnit; import static jdk.incubator.foreign.MemoryLayout.PathElement.sequenceElement; -import static jdk.incubator.foreign.MemoryLayouts.JAVA_INT; +import static jdk.incubator.foreign.ValueLayout.JAVA_INT; @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) @@ -61,10 +61,10 @@ public class LoopOverNew { static final int ALLOC_SIZE = ELEM_SIZE * CARRIER_SIZE; static final MemoryLayout ALLOC_LAYOUT = MemoryLayout.sequenceLayout(ELEM_SIZE, JAVA_INT); - static final VarHandle VH_int = MemoryLayout.sequenceLayout(JAVA_INT).varHandle(int.class, sequenceElement()); + static final VarHandle VH_int = MemoryLayout.sequenceLayout(JAVA_INT).varHandle(sequenceElement()); final ResourceScope scope = ResourceScope.newConfinedScope(); - final SegmentAllocator recyclingAlloc = SegmentAllocator.ofSegment(MemorySegment.allocateNative(ALLOC_LAYOUT, scope)); + final SegmentAllocator recyclingAlloc = SegmentAllocator.prefixAllocator(MemorySegment.allocateNative(ALLOC_LAYOUT, scope)); @TearDown public void tearDown() throws Throwable { diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverNewHeap.java b/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverNewHeap.java new file mode 100644 index 0000000000000000000000000000000000000000..62677639f2f400f48142a172d8d9ce8bccf2db21 --- /dev/null +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverNewHeap.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.jdk.incubator.foreign; + +import jdk.incubator.foreign.MemoryLayout; +import jdk.incubator.foreign.MemorySegment; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.annotations.Warmup; +import sun.misc.Unsafe; + +import java.lang.invoke.VarHandle; +import java.nio.IntBuffer; +import java.util.concurrent.TimeUnit; + +import static jdk.incubator.foreign.MemoryLayout.PathElement.sequenceElement; +import static jdk.incubator.foreign.ValueLayout.JAVA_INT; + +@BenchmarkMode(Mode.AverageTime) +@Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@State(org.openjdk.jmh.annotations.Scope.Thread) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@Fork(value = 3, jvmArgsAppend = { "--add-modules=jdk.incubator.foreign" }) +public class LoopOverNewHeap { + + static final Unsafe unsafe = Utils.unsafe; + + static final int ELEM_SIZE = 1_000_000; + static final int CARRIER_SIZE = (int)JAVA_INT.byteSize(); + + static final VarHandle VH_int = MemoryLayout.sequenceLayout(JAVA_INT).varHandle(sequenceElement()); + + @Param(value = {"false", "true"}) + boolean polluteProfile; + + @Setup + public void setup() { + if (polluteProfile) { + for (int i = 0 ; i < 10000 ; i++) { + MemorySegment intB = MemorySegment.ofArray(new byte[ELEM_SIZE]); + MemorySegment intI = MemorySegment.ofArray(new int[ELEM_SIZE]); + MemorySegment intD = MemorySegment.ofArray(new double[ELEM_SIZE]); + MemorySegment intF = MemorySegment.ofArray(new float[ELEM_SIZE]); + } + } + } + + @Benchmark + public void unsafe_loop() { + int[] elems = new int[ELEM_SIZE]; + for (int i = 0; i < ELEM_SIZE; i++) { + unsafe.putInt(elems, Unsafe.ARRAY_INT_BASE_OFFSET + (i * CARRIER_SIZE) , i); + } + } + + + @Benchmark + public void segment_loop() { + MemorySegment segment = MemorySegment.ofArray(new int[ELEM_SIZE]); + for (int i = 0; i < ELEM_SIZE; i++) { + VH_int.set(segment, (long) i, i); + } + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + @Benchmark + public void segment_loop_dontinline() { + MemorySegment segment = MemorySegment.ofArray(new int[ELEM_SIZE]); + for (int i = 0; i < ELEM_SIZE; i++) { + VH_int.set(segment, (long) i, i); + } + } + + @Benchmark + public void buffer_loop() { + IntBuffer buffer = IntBuffer.wrap(new int[ELEM_SIZE]); + for (int i = 0; i < ELEM_SIZE; i++) { + buffer.put(i , i); + } + } + +} diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverNonConstant.java b/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverNonConstant.java index c4af846b6850b7087d8e47db114d089cdfd278ea..ada578b09ba24c757be68490f59e4883c5b33c87 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverNonConstant.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverNonConstant.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,7 +22,7 @@ */ package org.openjdk.bench.jdk.incubator.foreign; -import jdk.incubator.foreign.MemoryAccess; +import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; @@ -44,14 +44,14 @@ import java.nio.ByteOrder; import java.util.concurrent.TimeUnit; import static jdk.incubator.foreign.MemoryLayout.PathElement.sequenceElement; -import static jdk.incubator.foreign.MemoryLayouts.JAVA_INT; +import static jdk.incubator.foreign.ValueLayout.JAVA_INT; @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(value = 3, jvmArgsAppend = { "--add-modules=jdk.incubator.foreign" }) +@Fork(value = 3, jvmArgsAppend = { "--add-modules=jdk.incubator.foreign", "--enable-native-access=ALL-UNNAMED" }) public class LoopOverNonConstant { static final Unsafe unsafe = Utils.unsafe; @@ -60,7 +60,7 @@ public class LoopOverNonConstant { static final int CARRIER_SIZE = (int)JAVA_INT.byteSize(); static final int ALLOC_SIZE = ELEM_SIZE * CARRIER_SIZE; - static final VarHandle VH_int = MemoryLayout.sequenceLayout(JAVA_INT).varHandle(int.class, sequenceElement()); + static final VarHandle VH_int = MemoryLayout.sequenceLayout(JAVA_INT).varHandle(sequenceElement()); MemorySegment segment; long unsafe_addr; @@ -117,19 +117,48 @@ public class LoopOverNonConstant { } @Benchmark - public int segment_loop_static() { - int res = 0; - for (int i = 0; i < ELEM_SIZE; i ++) { - res += MemoryAccess.getIntAtIndex(segment, i); + public int segment_loop() { + int sum = 0; + for (int i = 0; i < ELEM_SIZE; i++) { + sum += (int) VH_int.get(segment, (long) i); } - return res; + return sum; } @Benchmark - public int segment_loop() { + public int segment_loop_instance() { int sum = 0; for (int i = 0; i < ELEM_SIZE; i++) { - sum += (int) VH_int.get(segment, (long) i); + sum += segment.get(JAVA_INT, i * CARRIER_SIZE); + + } + return sum; + } + + @Benchmark + public int segment_loop_instance_index() { + int sum = 0; + for (int i = 0; i < ELEM_SIZE; i++) { + sum += segment.getAtIndex(JAVA_INT, i); + + } + return sum; + } + + @Benchmark + public int segment_loop_instance_address() { + int sum = 0; + for (int i = 0; i < ELEM_SIZE; i++) { + sum += segment.address().get(JAVA_INT, i * CARRIER_SIZE); + } + return sum; + } + + @Benchmark + public int segment_loop_instance_address_index() { + int sum = 0; + for (int i = 0; i < ELEM_SIZE; i++) { + sum += segment.address().getAtIndex(JAVA_INT, i); } return sum; } diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverNonConstantFP.java b/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverNonConstantFP.java index 17c8cd6b341d20acafea909200182c4b1f78b446..180c12240fa024c607841d0406a5a6abd56fe526 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverNonConstantFP.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverNonConstantFP.java @@ -22,7 +22,6 @@ */ package org.openjdk.bench.jdk.incubator.foreign; -import jdk.incubator.foreign.MemoryAccess; import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; import org.openjdk.jmh.annotations.Benchmark; @@ -42,7 +41,7 @@ import java.nio.ByteOrder; import java.util.concurrent.TimeUnit; import static jdk.incubator.foreign.MemoryLayout.PathElement.sequenceElement; -import static jdk.incubator.foreign.MemoryLayouts.JAVA_DOUBLE; +import static jdk.incubator.foreign.ValueLayout.JAVA_DOUBLE; @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) @@ -75,10 +74,10 @@ public class LoopOverNonConstantFP { segmentIn = MemorySegment.allocateNative(ALLOC_SIZE, ResourceScope.newConfinedScope()); segmentOut = MemorySegment.allocateNative(ALLOC_SIZE, ResourceScope.newConfinedScope()); for (int i = 0; i < ELEM_SIZE; i++) { - MemoryAccess.setDoubleAtIndex(segmentIn, i, i); + segmentIn.setAtIndex(JAVA_DOUBLE, i, i); } for (int i = 0; i < ELEM_SIZE; i++) { - MemoryAccess.setDoubleAtIndex(segmentOut, i, i); + segmentOut.setAtIndex(JAVA_DOUBLE, i, i); } byteBufferIn = ByteBuffer.allocateDirect(ALLOC_SIZE).order(ByteOrder.nativeOrder()); byteBufferOut = ByteBuffer.allocateDirect(ALLOC_SIZE).order(ByteOrder.nativeOrder()); @@ -112,9 +111,9 @@ public class LoopOverNonConstantFP { @Benchmark public void segment_loop() { for (int i = 0; i < ELEM_SIZE; i ++) { - MemoryAccess.setDoubleAtIndex(segmentOut, i, - MemoryAccess.getDoubleAtIndex(segmentIn, i) + - MemoryAccess.getDoubleAtIndex(segmentOut, i)); + segmentOut.setAtIndex(JAVA_DOUBLE, i, + segmentIn.getAtIndex(JAVA_DOUBLE, i) + + segmentOut.getAtIndex(JAVA_DOUBLE, i)); } } diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverNonConstantHeap.java b/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverNonConstantHeap.java index 2b2be067fdcdec08104c65a8f5dc621737c5c448..5b51db08c00b2563aff61961a10bf7cd4607c1e1 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverNonConstantHeap.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverNonConstantHeap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,7 +22,6 @@ */ package org.openjdk.bench.jdk.incubator.foreign; -import jdk.incubator.foreign.MemoryAccess; import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; @@ -46,7 +45,10 @@ import java.nio.ByteOrder; import java.util.concurrent.TimeUnit; import static jdk.incubator.foreign.MemoryLayout.PathElement.sequenceElement; -import static jdk.incubator.foreign.MemoryLayouts.JAVA_INT; +import static jdk.incubator.foreign.ValueLayout.JAVA_BYTE; +import static jdk.incubator.foreign.ValueLayout.JAVA_DOUBLE; +import static jdk.incubator.foreign.ValueLayout.JAVA_FLOAT; +import static jdk.incubator.foreign.ValueLayout.JAVA_INT; @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) @@ -63,7 +65,7 @@ public class LoopOverNonConstantHeap { static final int ALLOC_SIZE = ELEM_SIZE * CARRIER_SIZE; static final int UNSAFE_BYTE_BASE = unsafe.arrayBaseOffset(byte[].class); - static final VarHandle VH_int = MemoryLayout.sequenceLayout(JAVA_INT).varHandle(int.class, sequenceElement()); + static final VarHandle VH_int = MemoryLayout.sequenceLayout(JAVA_INT).varHandle(sequenceElement()); MemorySegment segment; byte[] base; @@ -79,13 +81,13 @@ public class LoopOverNonConstantHeap { MemorySegment intI = MemorySegment.ofArray(new int[ALLOC_SIZE]); MemorySegment intD = MemorySegment.ofArray(new double[ALLOC_SIZE]); MemorySegment intF = MemorySegment.ofArray(new float[ALLOC_SIZE]); - MemorySegment s = MemorySegment.allocateNative(ALLOC_SIZE, 1, ResourceScope.newConfinedScope(Cleaner.create())); + MemorySegment s = MemorySegment.allocateNative(ALLOC_SIZE, 1, ResourceScope.newConfinedScope()); for (int i = 0; i < ALLOC_SIZE; i++) { - MemoryAccess.setByteAtOffset(intB, i, (byte)i); - MemoryAccess.setIntAtIndex(intI, i, i); - MemoryAccess.setDoubleAtIndex(intD, i, i); - MemoryAccess.setFloatAtIndex(intF, i, i); - MemoryAccess.setByteAtOffset(s, i, (byte) i); + intB.set(JAVA_BYTE, i, (byte)i); + intI.setAtIndex(JAVA_INT, i, i); + intD.setAtIndex(JAVA_DOUBLE, i, i); + intF.setAtIndex(JAVA_FLOAT, i, i); + s.set(JAVA_BYTE, i, (byte) i); } } @@ -134,10 +136,10 @@ public class LoopOverNonConstantHeap { } @Benchmark - public int segment_loop_static() { + public int segment_loop_instance() { int res = 0; for (int i = 0; i < ELEM_SIZE; i ++) { - res += MemoryAccess.getIntAtIndex(segment, i); + res += segment.get(JAVA_INT, i * CARRIER_SIZE); } return res; } diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverNonConstantMapped.java b/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverNonConstantMapped.java index 11f1c1f061eb246b6c0cdddf537e5b9b3667d809..5e4e22916bf23f06876b69367b09e7c1408511c2 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverNonConstantMapped.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverNonConstantMapped.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,7 +22,6 @@ */ package org.openjdk.bench.jdk.incubator.foreign; -import jdk.incubator.foreign.MemoryAccess; import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; @@ -51,14 +50,14 @@ import java.nio.file.StandardOpenOption; import java.util.concurrent.TimeUnit; import static jdk.incubator.foreign.MemoryLayout.PathElement.sequenceElement; -import static jdk.incubator.foreign.MemoryLayouts.JAVA_INT; +import static jdk.incubator.foreign.ValueLayout.JAVA_INT; @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(value = 3, jvmArgsAppend = { "--add-modules=jdk.incubator.foreign" }) +@Fork(value = 3, jvmArgsAppend = { "--add-modules=jdk.incubator.foreign", "--enable-native-access=ALL-UNNAMED" }) public class LoopOverNonConstantMapped { static final Unsafe unsafe = Utils.unsafe; @@ -81,7 +80,7 @@ public class LoopOverNonConstantMapped { } } - static final VarHandle VH_int = MemoryLayout.sequenceLayout(JAVA_INT).varHandle(int.class, sequenceElement()); + static final VarHandle VH_int = MemoryLayout.sequenceLayout(JAVA_INT).varHandle(sequenceElement()); MemorySegment segment; long unsafe_addr; @@ -143,10 +142,19 @@ public class LoopOverNonConstantMapped { } @Benchmark - public int segment_loop_static() { + public int segment_loop_instance() { int res = 0; for (int i = 0; i < ELEM_SIZE; i ++) { - res += MemoryAccess.getIntAtIndex(segment, i); + res += segment.get(JAVA_INT, i * CARRIER_SIZE); + } + return res; + } + + @Benchmark + public int segment_loop_instance_address() { + int res = 0; + for (int i = 0; i < ELEM_SIZE; i ++) { + res += segment.address().get(JAVA_INT, i * CARRIER_SIZE); } return res; } diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverNonConstantShared.java b/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverNonConstantShared.java index 06c6310845a728d1916e191b529ae6092006ffc2..75c64a024f9c8aa4e9ff160c1397101aa46cf95d 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverNonConstantShared.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverNonConstantShared.java @@ -22,7 +22,6 @@ */ package org.openjdk.bench.jdk.incubator.foreign; -import jdk.incubator.foreign.MemoryAccess; import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; @@ -44,7 +43,7 @@ import java.nio.ByteOrder; import java.util.concurrent.TimeUnit; import static jdk.incubator.foreign.MemoryLayout.PathElement.sequenceElement; -import static jdk.incubator.foreign.MemoryLayouts.JAVA_INT; +import static jdk.incubator.foreign.ValueLayout.JAVA_INT; @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) @@ -60,7 +59,7 @@ public class LoopOverNonConstantShared { static final int CARRIER_SIZE = (int)JAVA_INT.byteSize(); static final int ALLOC_SIZE = ELEM_SIZE * CARRIER_SIZE; - static final VarHandle VH_int = MemoryLayout.sequenceLayout(JAVA_INT).varHandle(int.class, sequenceElement()); + static final VarHandle VH_int = MemoryLayout.sequenceLayout(JAVA_INT).varHandle(sequenceElement()); MemorySegment segment; long unsafe_addr; @@ -72,7 +71,7 @@ public class LoopOverNonConstantShared { for (int i = 0; i < ELEM_SIZE; i++) { unsafe.putInt(unsafe_addr + (i * CARRIER_SIZE) , i); } - segment = MemorySegment.allocateNative(ALLOC_SIZE, CARRIER_SIZE, ResourceScope.newSharedScope()); + segment = MemorySegment.allocateNative(ALLOC_SIZE, CARRIER_SIZE, ResourceScope.newConfinedScope()); for (int i = 0; i < ELEM_SIZE; i++) { VH_int.set(segment, (long) i, i); } @@ -117,10 +116,19 @@ public class LoopOverNonConstantShared { } @Benchmark - public int segment_loop_static() { + public int segment_loop_instance() { int res = 0; for (int i = 0; i < ELEM_SIZE; i ++) { - res += MemoryAccess.getIntAtIndex(segment, i); + res += segment.get(JAVA_INT, i * CARRIER_SIZE); + } + return res; + } + + @Benchmark + public int segment_loop_instance_address() { + int res = 0; + for (int i = 0; i < ELEM_SIZE; i ++) { + res += segment.get(JAVA_INT, i * CARRIER_SIZE); } return res; } diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverPollutedBuffer.java b/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverPollutedBuffer.java index 3903159c4073f8ff785256ef9187d05281bf2be9..0d1c90cb987fabdf3315de5ee916e019a8110644 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverPollutedBuffer.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverPollutedBuffer.java @@ -42,7 +42,7 @@ import java.nio.ByteOrder; import java.nio.FloatBuffer; import java.util.concurrent.TimeUnit; -import static jdk.incubator.foreign.MemoryLayouts.JAVA_INT; +import static jdk.incubator.foreign.ValueLayout.JAVA_INT; @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverPollutedSegments.java b/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverPollutedSegments.java index 65ae252ee322d538ba2176c064c736c333e2f40c..4cb01f091f1cc85de3ee1bc74d2d3083fe23c58c 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverPollutedSegments.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/LoopOverPollutedSegments.java @@ -22,7 +22,6 @@ */ package org.openjdk.bench.jdk.incubator.foreign; -import jdk.incubator.foreign.MemoryAccess; import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; @@ -42,7 +41,8 @@ import java.lang.invoke.VarHandle; import java.util.concurrent.TimeUnit; import static jdk.incubator.foreign.MemoryLayout.PathElement.sequenceElement; -import static jdk.incubator.foreign.MemoryLayouts.JAVA_INT; +import static jdk.incubator.foreign.ValueLayout.JAVA_FLOAT; +import static jdk.incubator.foreign.ValueLayout.JAVA_INT; @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) @@ -62,7 +62,7 @@ public class LoopOverPollutedSegments { byte[] arr; long addr; - static final VarHandle intHandle = MemoryLayout.sequenceLayout(JAVA_INT).varHandle(int.class, MemoryLayout.PathElement.sequenceElement()); + static final VarHandle intHandle = MemoryLayout.sequenceLayout(JAVA_INT).varHandle(MemoryLayout.PathElement.sequenceElement()); @Setup @@ -79,14 +79,14 @@ public class LoopOverPollutedSegments { for (int rep = 0 ; rep < 5 ; rep++) { for (int i = 0; i < ELEM_SIZE; i++) { unsafe.putInt(arr, Unsafe.ARRAY_BYTE_BASE_OFFSET + (i * 4), i); - MemoryAccess.setIntAtIndex(nativeSegment, i, i); - MemoryAccess.setFloatAtIndex(nativeSegment, i, i); + nativeSegment.setAtIndex(JAVA_INT, i, i); + nativeSegment.setAtIndex(JAVA_FLOAT, i, i); intHandle.set(nativeSegment, (long)i, i); - MemoryAccess.setIntAtIndex(heapSegmentBytes, i, i); - MemoryAccess.setFloatAtIndex(heapSegmentBytes, i, i); + heapSegmentBytes.setAtIndex(JAVA_INT, i, i); + heapSegmentBytes.setAtIndex(JAVA_FLOAT, i, i); intHandle.set(heapSegmentBytes, (long)i, i); - MemoryAccess.setIntAtIndex(heapSegmentFloats, i, i); - MemoryAccess.setFloatAtIndex(heapSegmentFloats, i, i); + heapSegmentFloats.setAtIndex(JAVA_INT, i, i); + heapSegmentFloats.setAtIndex(JAVA_FLOAT, i, i); intHandle.set(heapSegmentFloats, (long)i, i); } } @@ -113,11 +113,11 @@ public class LoopOverPollutedSegments { } @Benchmark - public int native_segment_static() { + public int native_segment_instance() { int sum = 0; for (int k = 0; k < ELEM_SIZE; k++) { - MemoryAccess.setIntAtOffset(nativeSegment, k, k + 1); - int v = MemoryAccess.getIntAtOffset(nativeSegment, k); + nativeSegment.setAtIndex(JAVA_INT, k, k + 1); + int v = nativeSegment.getAtIndex(JAVA_INT, k); sum += v; } return sum; @@ -135,11 +135,11 @@ public class LoopOverPollutedSegments { } @Benchmark - public int heap_segment_ints_static() { + public int heap_segment_ints_instance() { int sum = 0; for (int k = 0; k < ELEM_SIZE; k++) { - MemoryAccess.setIntAtOffset(heapSegmentBytes, k, k + 1); - int v = MemoryAccess.getIntAtOffset(heapSegmentBytes, k); + heapSegmentBytes.setAtIndex(JAVA_INT, k, k + 1); + int v = heapSegmentBytes.getAtIndex(JAVA_INT, k); sum += v; } return sum; @@ -157,11 +157,11 @@ public class LoopOverPollutedSegments { } @Benchmark - public int heap_segment_floats_static() { + public int heap_segment_floats_instance() { int sum = 0; for (int k = 0; k < ELEM_SIZE; k++) { - MemoryAccess.setIntAtOffset(heapSegmentFloats, k, k + 1); - int v = MemoryAccess.getIntAtOffset(heapSegmentFloats, k); + heapSegmentFloats.setAtIndex(JAVA_INT, k, k + 1); + int v = heapSegmentFloats.getAtIndex(JAVA_INT, k); sum += v; } return sum; diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/ParallelSum.java b/test/micro/org/openjdk/bench/jdk/incubator/foreign/ParallelSum.java index 231c606103bc0c894c5416a1c46178aff5e99fed..6ec449a1ec0364e9c01606932deb4bddf3cbc761 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/foreign/ParallelSum.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/ParallelSum.java @@ -24,9 +24,9 @@ package org.openjdk.bench.jdk.incubator.foreign; import jdk.incubator.foreign.MemoryLayout; -import jdk.incubator.foreign.MemoryLayouts; import jdk.incubator.foreign.ResourceScope; import jdk.incubator.foreign.SequenceLayout; +import jdk.incubator.foreign.ValueLayout; import sun.misc.Unsafe; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; @@ -52,7 +52,7 @@ import java.util.function.Predicate; import java.util.function.ToIntFunction; import static jdk.incubator.foreign.MemoryLayout.PathElement.sequenceElement; -import static jdk.incubator.foreign.MemoryLayouts.JAVA_INT; +import static jdk.incubator.foreign.ValueLayout.JAVA_INT; @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) @@ -65,9 +65,9 @@ public class ParallelSum { final static int CARRIER_SIZE = 4; final static int ALLOC_SIZE = CARRIER_SIZE * 1024 * 1024 * 256; final static int ELEM_SIZE = ALLOC_SIZE / CARRIER_SIZE; - static final VarHandle VH_int = MemoryLayout.sequenceLayout(JAVA_INT).varHandle(int.class, sequenceElement()); + static final VarHandle VH_int = MemoryLayout.sequenceLayout(JAVA_INT).varHandle(sequenceElement()); - final static MemoryLayout ELEM_LAYOUT = MemoryLayouts.JAVA_INT; + final static MemoryLayout ELEM_LAYOUT = ValueLayout.JAVA_INT; final static int BULK_FACTOR = 512; final static SequenceLayout ELEM_LAYOUT_BULK = MemoryLayout.sequenceLayout(BULK_FACTOR, ELEM_LAYOUT); diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/QSort.java b/test/micro/org/openjdk/bench/jdk/incubator/foreign/QSort.java new file mode 100644 index 0000000000000000000000000000000000000000..04a10f8ed4e5456f1c5da44fb4066d513f913019 --- /dev/null +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/QSort.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.jdk.incubator.foreign; + +import jdk.incubator.foreign.Addressable; +import jdk.incubator.foreign.CLinker; +import jdk.incubator.foreign.FunctionDescriptor; +import jdk.incubator.foreign.MemoryAddress; +import jdk.incubator.foreign.MemoryLayout; +import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.NativeSymbol; +import jdk.incubator.foreign.ResourceScope; +import jdk.incubator.foreign.SymbolLookup; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodType; +import java.util.concurrent.TimeUnit; + +import static java.lang.invoke.MethodHandles.lookup; +import static jdk.incubator.foreign.ValueLayout.JAVA_INT; + +@BenchmarkMode(Mode.AverageTime) +@Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@State(org.openjdk.jmh.annotations.Scope.Thread) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@Fork(value = 3, jvmArgsAppend = { "--add-modules=jdk.incubator.foreign", "--enable-native-access=ALL-UNNAMED" }) +public class QSort extends CLayouts { + + static final CLinker abi = CLinker.systemCLinker(); + static final MethodHandle clib_qsort; + static final NativeSymbol native_compar; + static final NativeSymbol panama_upcall_compar; + static final long jni_upcall_compar; + + static final int[] INPUT = { 5, 3, 2, 7, 8, 12, 1, 7 }; + static final MemorySegment INPUT_SEGMENT; + + static NativeSymbol qsort_addr = abi.lookup("qsort").get(); + + static { + INPUT_SEGMENT = MemorySegment.allocateNative(MemoryLayout.sequenceLayout(INPUT.length, JAVA_INT), ResourceScope.globalScope()); + INPUT_SEGMENT.copyFrom(MemorySegment.ofArray(INPUT)); + + System.loadLibrary("QSortJNI"); + jni_upcall_compar = JNICB.makeCB("org/openjdk/bench/jdk/incubator/foreign/QSort", "jni_upcall_compar", "(II)I"); + + try { + clib_qsort = abi.downcallHandle( + qsort_addr, + FunctionDescriptor.ofVoid(C_POINTER, C_LONG_LONG, C_LONG_LONG, C_POINTER) + ); + System.loadLibrary("QSort"); + native_compar = SymbolLookup.loaderLookup().lookup("compar").orElseThrow(); + panama_upcall_compar = abi.upcallStub( + lookup().findStatic(QSort.class, + "panama_upcall_compar", + MethodType.methodType(int.class, MemoryAddress.class, MemoryAddress.class)), + FunctionDescriptor.of(C_INT, C_POINTER, C_POINTER), + ResourceScope.globalScope() + ); + } catch (ReflectiveOperationException e) { + throw new BootstrapMethodError(e); + } + } + + static native void jni_qsort_optimized(int[] array, long cb); + static native void jni_qsort_naive(int[] array); + + @FunctionalInterface + interface JNIComparator { + int cmp(int e0, int e1); + } + + static final JNIComparator COMP = QSort::jni_upcall_compar; + + @Benchmark + public void native_qsort() throws Throwable { + clib_qsort.invokeExact((Addressable)INPUT_SEGMENT, (long) INPUT.length, JAVA_INT.byteSize(), (Addressable)native_compar); + } + + @Benchmark + public void jni_upcall_qsort_optimized() { + jni_qsort_optimized(INPUT, jni_upcall_compar); + } + + @Benchmark + public void jni_upcall_qsort_naive() { + jni_qsort_naive(INPUT); + } + + @Benchmark + public void panama_upcall_qsort() throws Throwable { + clib_qsort.invokeExact((Addressable)INPUT_SEGMENT, (long) INPUT.length, JAVA_INT.byteSize(), (Addressable)panama_upcall_compar); + } + + private static int getIntAbsolute(MemoryAddress addr) { + return addr.get(JAVA_INT, 0); + } + + static int panama_upcall_compar(MemoryAddress e0, MemoryAddress e1) { + return Integer.compare(getIntAbsolute(e0), getIntAbsolute(e1)); + } + + static int jni_upcall_compar(int j0, int j1) { + return Integer.compare(j0, j1); + } +} diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/StrLenTest.java b/test/micro/org/openjdk/bench/jdk/incubator/foreign/StrLenTest.java index ec4da5ffc8875d21a611906786aa16f0ca44f763..ec7d58cf823df27b8b706af1ab2e9b0482bcefe9 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/foreign/StrLenTest.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/StrLenTest.java @@ -25,9 +25,9 @@ package org.openjdk.bench.jdk.incubator.foreign; +import jdk.incubator.foreign.Addressable; import jdk.incubator.foreign.CLinker; import jdk.incubator.foreign.FunctionDescriptor; -import jdk.incubator.foreign.MemoryAccess; import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; @@ -45,10 +45,9 @@ import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.annotations.Warmup; import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodType; import java.util.concurrent.TimeUnit; -import static jdk.incubator.foreign.CLinker.*; +import static jdk.incubator.foreign.ValueLayout.JAVA_BYTE; @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) @@ -56,12 +55,12 @@ import static jdk.incubator.foreign.CLinker.*; @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.NANOSECONDS) @Fork(value = 3, jvmArgsAppend = { "--add-modules=jdk.incubator.foreign", "--enable-native-access=ALL-UNNAMED" }) -public class StrLenTest { +public class StrLenTest extends CLayouts { - ResourceScope scope = ResourceScope.newConfinedScope(); + ResourceScope scope = ResourceScope.newImplicitScope(); SegmentAllocator segmentAllocator; - SegmentAllocator arenaAllocator = SegmentAllocator.arenaAllocator(scope); + SegmentAllocator arenaAllocator = SegmentAllocator.newNativeArena(scope); @Param({"5", "20", "100"}) public int size; @@ -72,31 +71,17 @@ public class StrLenTest { } static final MethodHandle STRLEN; - static final MethodHandle STRLEN_TRIVIAL; - static final MethodHandle MALLOC_TRIVIAL; - static final MethodHandle FREE_TRIVIAL; static { - CLinker abi = CLinker.getInstance(); - STRLEN = abi.downcallHandle(CLinker.systemLookup().lookup("strlen").get(), - MethodType.methodType(int.class, MemoryAddress.class), + CLinker abi = CLinker.systemCLinker(); + STRLEN = abi.downcallHandle(abi.lookup("strlen").get(), FunctionDescriptor.of(C_INT, C_POINTER)); - STRLEN_TRIVIAL = abi.downcallHandle(CLinker.systemLookup().lookup("strlen").get(), - MethodType.methodType(int.class, MemoryAddress.class), - FunctionDescriptor.of(C_INT, C_POINTER).withAttribute(FunctionDescriptor.TRIVIAL_ATTRIBUTE_NAME, true)); - MALLOC_TRIVIAL = abi.downcallHandle(CLinker.systemLookup().lookup("malloc").get(), - MethodType.methodType(MemoryAddress.class, long.class), - FunctionDescriptor.of(C_POINTER, C_LONG_LONG).withAttribute(FunctionDescriptor.TRIVIAL_ATTRIBUTE_NAME, true)); - - FREE_TRIVIAL = abi.downcallHandle(CLinker.systemLookup().lookup("free").get(), - MethodType.methodType(void.class, MemoryAddress.class), - FunctionDescriptor.ofVoid(C_POINTER).withAttribute(FunctionDescriptor.TRIVIAL_ATTRIBUTE_NAME, true)); } @Setup public void setup() { str = makeString(size); - segmentAllocator = SegmentAllocator.ofSegment(MemorySegment.allocateNative(size + 1, ResourceScope.newImplicitScope())); + segmentAllocator = SegmentAllocator.prefixAllocator(MemorySegment.allocateNative(size + 1, ResourceScope.newConfinedScope())); } @TearDown @@ -112,54 +97,37 @@ public class StrLenTest { @Benchmark public int panama_strlen() throws Throwable { try (ResourceScope scope = ResourceScope.newConfinedScope()) { - MemorySegment segment = CLinker.toCString(str, scope); - return (int)STRLEN.invokeExact(segment.address()); + MemorySegment segment = MemorySegment.allocateNative(str.length() + 1, scope); + segment.setUtf8String(0, str); + return (int)STRLEN.invokeExact((Addressable)segment); } } @Benchmark public int panama_strlen_arena() throws Throwable { - return (int)STRLEN.invokeExact(CLinker.toCString(str, arenaAllocator).address()); + return (int)STRLEN.invokeExact((Addressable)arenaAllocator.allocateUtf8String(str)); } @Benchmark public int panama_strlen_prefix() throws Throwable { - return (int)STRLEN.invokeExact(CLinker.toCString(str, segmentAllocator).address()); + return (int)STRLEN.invokeExact((Addressable)segmentAllocator.allocateUtf8String(str)); } @Benchmark public int panama_strlen_unsafe() throws Throwable { MemoryAddress address = makeStringUnsafe(str); - int res = (int) STRLEN.invokeExact(address); - CLinker.freeMemory(address); - return res; - } - - @Benchmark - public int panama_strlen_unsafe_trivial() throws Throwable { - MemoryAddress address = makeStringUnsafeTrivial(str); - int res = (int) STRLEN_TRIVIAL.invokeExact(address); - FREE_TRIVIAL.invokeExact(address); + int res = (int) STRLEN.invokeExact((Addressable)address); + freeMemory(address); return res; } static MemoryAddress makeStringUnsafe(String s) { byte[] bytes = s.getBytes(); int len = bytes.length; - MemoryAddress address = CLinker.allocateMemory(len + 1); - MemorySegment str = address.asSegment(len + 1, ResourceScope.globalScope()); - str.copyFrom(MemorySegment.ofArray(bytes)); - MemoryAccess.setByteAtOffset(str, len, (byte)0); - return address; - } - - static MemoryAddress makeStringUnsafeTrivial(String s) throws Throwable { - byte[] bytes = s.getBytes(); - int len = bytes.length; - MemoryAddress address = (MemoryAddress)MALLOC_TRIVIAL.invokeExact((long)len + 1); - MemorySegment str = address.asSegment(len + 1, ResourceScope.globalScope()); + MemoryAddress address = allocateMemory(len + 1); + MemorySegment str = MemorySegment.ofAddress(address, len + 1, ResourceScope.globalScope()); str.copyFrom(MemorySegment.ofArray(bytes)); - MemoryAccess.setByteAtOffset(str, len, (byte)0); + str.set(JAVA_BYTE, len, (byte)0); return address; } diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/TestAdaptVarHandles.java b/test/micro/org/openjdk/bench/jdk/incubator/foreign/TestAdaptVarHandles.java index f8f482b3a284879ac2c6bd80dbb82b33be34cd75..4540b5907826b749731774cd691b275aada8165c 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/foreign/TestAdaptVarHandles.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/TestAdaptVarHandles.java @@ -26,8 +26,8 @@ package org.openjdk.bench.jdk.incubator.foreign; import jdk.incubator.foreign.MemoryHandles; import jdk.incubator.foreign.MemoryLayout; -import jdk.incubator.foreign.MemoryLayouts; import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.ValueLayout; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -85,8 +85,8 @@ public class TestAdaptVarHandles { static final VarHandle VH_box_int = MemoryHandles.filterValue(VH_int, INTBOX_TO_INT, INT_TO_INTBOX); - static final VarHandle VH_addr_int = MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_INT) - .varHandle(int.class, MemoryLayout.PathElement.sequenceElement()); + static final VarHandle VH_addr_int = MemoryLayout.sequenceLayout(ValueLayout.JAVA_INT) + .varHandle(MemoryLayout.PathElement.sequenceElement()); static final VarHandle VH_addr_box_int = MemoryHandles.filterValue(VH_addr_int, INTBOX_TO_INT, INT_TO_INTBOX); diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/TestLoadBytes.java b/test/micro/org/openjdk/bench/jdk/incubator/foreign/TestLoadBytes.java index 45c170b8dd359309488df69088482f3b52b17e09..6288c49cf92af34b925b78b1f93c5d0cd882ed5e 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/foreign/TestLoadBytes.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/TestLoadBytes.java @@ -23,14 +23,8 @@ package org.openjdk.bench.jdk.incubator.foreign; -import jdk.incubator.foreign.CLinker; -import jdk.incubator.foreign.MemoryAccess; -import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; -import jdk.incubator.vector.ByteVector; -import jdk.incubator.vector.IntVector; -import jdk.incubator.vector.VectorSpecies; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.CompilerControl; @@ -44,9 +38,10 @@ import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.annotations.Warmup; import java.nio.ByteBuffer; -import java.nio.ByteOrder; import java.util.concurrent.TimeUnit; +import static jdk.incubator.foreign.ValueLayout.JAVA_BYTE; + @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @@ -119,7 +114,7 @@ public class TestLoadBytes { public int segmentNativeScalar() { int size = 0; for (int i = 0; i < srcArray.length; i++) { - var v = MemoryAccess.getByteAtOffset(srcSegmentImplicit, i); + var v = srcSegmentImplicit.get(JAVA_BYTE, i); size += v; } return size; @@ -129,7 +124,7 @@ public class TestLoadBytes { public int segmentNativeScalarConst() { int size = 0; for (int i = 0; i < 1024; i++) { - var v = MemoryAccess.getByteAtOffset(srcSegmentImplicit, i); + var v = srcSegmentImplicit.get(JAVA_BYTE, i); size += v; } return size; diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/UnrolledAccess.java b/test/micro/org/openjdk/bench/jdk/incubator/foreign/UnrolledAccess.java index 614ff42b8f474d2f0305b68e71ce4db3d5f4e2c5..ea72c01f7b941b1fb11d7f0e9009c0fe230e8764 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/foreign/UnrolledAccess.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/UnrolledAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,6 @@ package org.openjdk.bench.jdk.incubator.foreign; -import static jdk.incubator.foreign.MemoryAccess.*; import jdk.incubator.foreign.*; import org.openjdk.jmh.annotations.*; import org.openjdk.jmh.runner.Runner; @@ -34,20 +33,22 @@ import java.util.concurrent.TimeUnit; import java.lang.invoke.VarHandle; +import static jdk.incubator.foreign.ValueLayout.JAVA_LONG; + @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MICROSECONDS) -@Fork(3) +@Fork(value = 3, jvmArgsAppend = { "--enable-native-access=ALL-UNNAMED" }) public class UnrolledAccess { static final Unsafe U = Utils.unsafe; final static int SIZE = 1024; - static final VarHandle LONG_HANDLE = MemoryLayout.sequenceLayout(SIZE, MemoryLayouts.JAVA_LONG) - .varHandle(long.class, MemoryLayout.PathElement.sequenceElement()); + static final VarHandle LONG_HANDLE = MemoryLayout.sequenceLayout(SIZE, JAVA_LONG) + .varHandle(MemoryLayout.PathElement.sequenceElement()); @State(Scope.Benchmark) public static class Data { @@ -65,8 +66,8 @@ public class UnrolledAccess { this.outputArray = new double[SIZE]; this.inputAddress = U.allocateMemory(8 * SIZE); this.outputAddress = U.allocateMemory(8 * SIZE); - this.inputSegment = MemoryAddress.ofLong(inputAddress).asSegment(8*SIZE, ResourceScope.globalScope()); - this.outputSegment = MemoryAddress.ofLong(outputAddress).asSegment(8*SIZE, ResourceScope.globalScope()); + this.inputSegment = MemorySegment.ofAddress(MemoryAddress.ofLong(inputAddress), 8*SIZE, ResourceScope.globalScope()); + this.outputSegment = MemorySegment.ofAddress(MemoryAddress.ofLong(outputAddress), 8*SIZE, ResourceScope.globalScope()); } } @@ -96,15 +97,15 @@ public class UnrolledAccess { } @Benchmark - public void static_handle_loop(Data state) { + public void handle_loop_instance(Data state) { final MemorySegment is = state.inputSegment; final MemorySegment os = state.outputSegment; for(int i = 0; i < SIZE; i+=4) { - setLongAtIndex(os, i,getLongAtIndex(is, i) + MemoryAccess.getLongAtIndex(os, i)); - setLongAtIndex(os, i+1,getLongAtIndex(is, i+1) + getLongAtIndex(os, i+1)); - setLongAtIndex(os, i+2,getLongAtIndex(is, i+2) + getLongAtIndex(os, i+2)); - setLongAtIndex(os, i+3,getLongAtIndex(is, i+3) + getLongAtIndex(os, i+3)); + os.setAtIndex(JAVA_LONG, i, is.getAtIndex(JAVA_LONG, i) + os.get(JAVA_LONG, i)); + os.setAtIndex(JAVA_LONG, i+1, is.getAtIndex(JAVA_LONG, i+1) + os.get(JAVA_LONG, i+1)); + os.setAtIndex(JAVA_LONG, i+2, is.getAtIndex(JAVA_LONG, i+2) + os.get(JAVA_LONG, i+2)); + os.setAtIndex(JAVA_LONG, i+3, is.getAtIndex(JAVA_LONG, i+3) + os.get(JAVA_LONG, i+3)); } } } diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/Upcalls.java b/test/micro/org/openjdk/bench/jdk/incubator/foreign/Upcalls.java index a25f4f9ae9fed4ade885a7f4ad62f5543bf4829f..06a25c4ab3a0bffc0608906aa578d310bcb14455 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/foreign/Upcalls.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/Upcalls.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,9 +22,10 @@ */ package org.openjdk.bench.jdk.incubator.foreign; -import jdk.incubator.foreign.FunctionDescriptor; -import jdk.incubator.foreign.MemoryAddress; +import jdk.incubator.foreign.Addressable; import jdk.incubator.foreign.CLinker; +import jdk.incubator.foreign.FunctionDescriptor; +import jdk.incubator.foreign.NativeSymbol; import jdk.incubator.foreign.ResourceScope; import jdk.incubator.foreign.SymbolLookup; import org.openjdk.jmh.annotations.Benchmark; @@ -41,10 +42,6 @@ import java.lang.invoke.MethodType; import java.util.concurrent.TimeUnit; import static java.lang.invoke.MethodHandles.lookup; -import static jdk.incubator.foreign.CLinker.C_DOUBLE; -import static jdk.incubator.foreign.CLinker.C_INT; -import static jdk.incubator.foreign.CLinker.C_LONG_LONG; -import static jdk.incubator.foreign.CLinker.C_POINTER; @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) @@ -52,18 +49,18 @@ import static jdk.incubator.foreign.CLinker.C_POINTER; @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.NANOSECONDS) @Fork(value = 3, jvmArgsAppend = { "--add-modules=jdk.incubator.foreign", "--enable-native-access=ALL-UNNAMED" }) -public class Upcalls { +public class Upcalls extends CLayouts { - static final CLinker abi = CLinker.getInstance(); + static final CLinker abi = CLinker.systemCLinker(); static final MethodHandle blank; static final MethodHandle identity; static final MethodHandle args5; static final MethodHandle args10; - static final MemoryAddress cb_blank; - static final MemoryAddress cb_identity; - static final MemoryAddress cb_args5; - static final MemoryAddress cb_args10; + static final NativeSymbol cb_blank; + static final NativeSymbol cb_identity; + static final NativeSymbol cb_args5; + static final NativeSymbol cb_args10; static final long cb_blank_jni; static final long cb_identity_jni; @@ -74,10 +71,10 @@ public class Upcalls { System.loadLibrary("UpcallsJNI"); String className = "org/openjdk/bench/jdk/incubator/foreign/Upcalls"; - cb_blank_jni = makeCB(className, "blank", "()V"); - cb_identity_jni = makeCB(className, "identity", "(I)I"); - cb_args5_jni = makeCB(className, "args5", "(JDJDJ)V"); - cb_args10_jni = makeCB(className, "args10", "(JDJDJDJDJD)V"); + cb_blank_jni = JNICB.makeCB(className, "blank", "()V"); + cb_identity_jni = JNICB.makeCB(className, "identity", "(I)I"); + cb_args5_jni = JNICB.makeCB(className, "args5", "(JDJDJ)V"); + cb_args10_jni = JNICB.makeCB(className, "args10", "(JDJDJDJDJD)V"); try { System.loadLibrary("Upcalls"); @@ -86,7 +83,7 @@ public class Upcalls { MethodType mt = MethodType.methodType(void.class); FunctionDescriptor fd = FunctionDescriptor.ofVoid(); - blank = linkFunc(name, mt, fd); + blank = linkFunc(name, fd); cb_blank = makeCB(name, mt, fd); } { @@ -94,7 +91,7 @@ public class Upcalls { MethodType mt = MethodType.methodType(int.class, int.class); FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT); - identity = linkFunc(name, mt, fd); + identity = linkFunc(name, fd); cb_identity = makeCB(name, mt, fd); } { @@ -104,7 +101,7 @@ public class Upcalls { FunctionDescriptor fd = FunctionDescriptor.ofVoid( C_LONG_LONG, C_DOUBLE, C_LONG_LONG, C_DOUBLE, C_LONG_LONG); - args5 = linkFunc(name, mt, fd); + args5 = linkFunc(name, fd); cb_args5 = makeCB(name, mt, fd); } { @@ -116,7 +113,7 @@ public class Upcalls { C_LONG_LONG, C_DOUBLE, C_LONG_LONG, C_DOUBLE, C_LONG_LONG, C_DOUBLE, C_LONG_LONG, C_DOUBLE, C_LONG_LONG, C_DOUBLE); - args10 = linkFunc(name, mt, fd); + args10 = linkFunc(name, fd); cb_args10 = makeCB(name, mt, fd); } } catch (ReflectiveOperationException e) { @@ -124,19 +121,18 @@ public class Upcalls { } } - static MethodHandle linkFunc(String name, MethodType baseType, FunctionDescriptor baseDesc) { + static MethodHandle linkFunc(String name, FunctionDescriptor baseDesc) { return abi.downcallHandle( SymbolLookup.loaderLookup().lookup(name).orElseThrow(), - baseType.insertParameterTypes(baseType.parameterCount(), MemoryAddress.class), - baseDesc.withAppendedArgumentLayouts(C_POINTER) + baseDesc.appendArgumentLayouts(C_POINTER) ); } - static MemoryAddress makeCB(String name, MethodType mt, FunctionDescriptor fd) throws ReflectiveOperationException { + static NativeSymbol makeCB(String name, MethodType mt, FunctionDescriptor fd) throws ReflectiveOperationException { return abi.upcallStub( lookup().findStatic(Upcalls.class, name, mt), fd, ResourceScope.globalScope() - ).address(); + ); } static native void blank(long cb); @@ -144,7 +140,6 @@ public class Upcalls { static native void args5(long a0, double a1, long a2, double a3, long a4, long cb); static native void args10(long a0, double a1, long a2, double a3, long a4, double a5, long a6, double a7, long a8, double a9, long cb); - static native long makeCB(String holder, String name, String signature); @Benchmark public void jni_blank() throws Throwable { @@ -153,7 +148,7 @@ public class Upcalls { @Benchmark public void panama_blank() throws Throwable { - blank.invokeExact(cb_blank); + blank.invokeExact((Addressable)cb_blank); } @Benchmark @@ -173,17 +168,17 @@ public class Upcalls { @Benchmark public int panama_identity() throws Throwable { - return (int) identity.invokeExact(10, cb_identity); + return (int) identity.invokeExact(10, (Addressable)cb_identity); } @Benchmark public void panama_args5() throws Throwable { - args5.invokeExact(1L, 2D, 3L, 4D, 5L, cb_args5); + args5.invokeExact(1L, 2D, 3L, 4D, 5L, (Addressable)cb_args5); } @Benchmark public void panama_args10() throws Throwable { - args10.invokeExact(1L, 2D, 3L, 4D, 5L, 6D, 7L, 8D, 9L, 10D, cb_args10); + args10.invokeExact(1L, 2D, 3L, 4D, 5L, 6D, 7L, 8D, 9L, 10D, (Addressable)cb_args10); } static void blank() {} diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/VaList.java b/test/micro/org/openjdk/bench/jdk/incubator/foreign/VaList.java index 34d74652cadd68cca0e16c31328cc5214c7b5421..d904c79a73401eb393ded730a9c65329ba3b67ed 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/foreign/VaList.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/VaList.java @@ -22,8 +22,10 @@ */ package org.openjdk.bench.jdk.incubator.foreign; -import jdk.incubator.foreign.FunctionDescriptor; +import jdk.incubator.foreign.Addressable; import jdk.incubator.foreign.CLinker; +import jdk.incubator.foreign.FunctionDescriptor; +import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.SymbolLookup; import jdk.incubator.foreign.ResourceScope; import org.openjdk.jmh.annotations.Benchmark; @@ -36,24 +38,17 @@ import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.annotations.Warmup; import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodType; import java.util.concurrent.TimeUnit; -import static jdk.incubator.foreign.CLinker.C_DOUBLE; -import static jdk.incubator.foreign.CLinker.C_INT; -import static jdk.incubator.foreign.CLinker.C_LONG_LONG; -import static jdk.incubator.foreign.CLinker.C_VA_LIST; -import static jdk.incubator.foreign.CLinker.asVarArg; - @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.NANOSECONDS) @Fork(value = 3, jvmArgsAppend = { "--add-modules=jdk.incubator.foreign", "--enable-native-access=ALL-UNNAMED" }) -public class VaList { +public class VaList extends CLayouts { - static final CLinker linker = CLinker.getInstance(); + static final CLinker linker = CLinker.systemCLinker(); static { System.loadLibrary("VaList"); } @@ -64,11 +59,9 @@ public class VaList { static { SymbolLookup lookup = SymbolLookup.loaderLookup(); MH_ellipsis = linker.downcallHandle(lookup.lookup("ellipsis").get(), - MethodType.methodType(void.class, int.class, int.class, double.class, long.class), - FunctionDescriptor.ofVoid(C_INT, asVarArg(C_INT), asVarArg(C_DOUBLE), asVarArg(C_LONG_LONG))); + FunctionDescriptor.ofVoid(C_INT).asVariadic(C_INT, C_DOUBLE, C_LONG_LONG)); MH_vaList = linker.downcallHandle(lookup.lookup("vaList").get(), - MethodType.methodType(void.class, int.class, CLinker.VaList.class), - FunctionDescriptor.ofVoid(C_INT, C_VA_LIST)); + FunctionDescriptor.ofVoid(C_INT, C_POINTER)); } @Benchmark @@ -80,12 +73,12 @@ public class VaList { @Benchmark public void vaList() throws Throwable { try (ResourceScope scope = ResourceScope.newConfinedScope()) { - CLinker.VaList vaList = CLinker.VaList.make(b -> - b.vargFromInt(C_INT, 1) - .vargFromDouble(C_DOUBLE, 2D) - .vargFromLong(C_LONG_LONG, 3L), scope); + jdk.incubator.foreign.VaList vaList = jdk.incubator.foreign.VaList.make(b -> + b.addVarg(C_INT, 1) + .addVarg(C_DOUBLE, 2D) + .addVarg(C_LONG_LONG, 3L), scope); MH_vaList.invokeExact(3, - vaList); + (Addressable)vaList); } } } diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/VarHandleExact.java b/test/micro/org/openjdk/bench/jdk/incubator/foreign/VarHandleExact.java index d560765c48c1e5f804c7e848714261f920674f88..0cb783473df67ab6e5ae206fc29ec3fcde7fefa9 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/foreign/VarHandleExact.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/VarHandleExact.java @@ -40,7 +40,7 @@ import java.lang.invoke.VarHandle; import java.nio.ByteOrder; import java.util.concurrent.TimeUnit; -import static jdk.incubator.foreign.MemoryLayouts.JAVA_INT; +import static jdk.incubator.foreign.ValueLayout.JAVA_INT; @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) @@ -54,7 +54,7 @@ public class VarHandleExact { static final VarHandle generic; static { - generic = MemoryHandles.varHandle(int.class, ByteOrder.nativeOrder()); + generic = MemoryHandles.varHandle(JAVA_INT); exact = generic.withInvokeExactBehavior(); } diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/libCallOverhead.c b/test/micro/org/openjdk/bench/jdk/incubator/foreign/libCallOverhead.c index f42aec0172c4e602e6a12d24ad489f34064826bb..8ad44f58cec4937617ca70f813959af9959d1ea2 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/foreign/libCallOverhead.c +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/libCallOverhead.c @@ -34,18 +34,26 @@ EXPORT int identity(int x) { } typedef struct { - long long x; - long long y; + int x; + int y; } Point; EXPORT Point identity_struct(Point p) { return p; } +EXPORT Point identity_struct_3(Point p1, Point p2, Point p3) { + return p1; +} + EXPORT void* identity_memory_address(void* p) { return p; } +EXPORT void* identity_memory_address_3(void* p1, void* p2, void* p3) { + return p1; +} + EXPORT void args1(long long a0) {} EXPORT void args2(long long a0, double a1) {} EXPORT void args3(long long a0, double a1, long long a2) {} diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/libJNICB.c b/test/micro/org/openjdk/bench/jdk/incubator/foreign/libJNICB.c new file mode 100644 index 0000000000000000000000000000000000000000..617d16d29dd96d62c820c661d20400e2a23f3712 --- /dev/null +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/libJNICB.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include <jni.h> +#include <stdlib.h> + +#include "JNICB.h" +#include "jlong.h" + +#define CHECK_NULL(thing, message) \ + if (thing == NULL) { \ + jclass cls = (*env)->FindClass(env, "java/lang/Exception"); \ + (*env)->ThrowNew(env, cls, message); \ + return 0; \ + } + +JNIEXPORT jlong JNICALL Java_org_openjdk_bench_jdk_incubator_foreign_JNICB_makeCB + (JNIEnv *env, jclass cls, jstring holderName, jstring methodName, jstring descriptor) { + + const char* holderNameC = (*env)->GetStringUTFChars(env, holderName, NULL); + const char* methodNameC = (*env)->GetStringUTFChars(env, methodName, NULL); + const char* descriptorC = (*env)->GetStringUTFChars(env, descriptor, NULL); + + JNICB cb = malloc(sizeof *cb); + CHECK_NULL(cb, "Can not allocate cb"); + + jclass holder = (*env)->FindClass(env, holderNameC); + CHECK_NULL(holder, "Can not find class"); + holder = (jclass) (*env)->NewGlobalRef(env, holder); + cb->holder = holder; + + jmethodID methodID = (*env)->GetStaticMethodID(env, holder, methodNameC, descriptorC); + CHECK_NULL(methodID, "Can not find method"); + //methodID = (jmethodID) (*env)->NewGlobalRef(env, methodID); // DON'T DO THIS! -> Crashes GC + cb->mid = methodID; + + (*env)->ReleaseStringUTFChars(env, holderName, holderNameC); + (*env)->ReleaseStringUTFChars(env, methodName, methodNameC); + (*env)->ReleaseStringUTFChars(env, descriptor, descriptorC); + + return ptr_to_jlong(cb); +} diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/libQSort.c b/test/micro/org/openjdk/bench/jdk/incubator/foreign/libQSort.c new file mode 100644 index 0000000000000000000000000000000000000000..cafb83d8708c85fb83f6896aae4bc754afc2211d --- /dev/null +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/libQSort.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifdef _WIN64 +#define EXPORT __declspec(dllexport) +#else +#define EXPORT +#endif + + +EXPORT int compar(const void* e0, const void* e1) { + int i0 = *((int*) e0); + int i1 = *((int*) e1); + return i0 - i1; +} diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/libQSortJNI.c b/test/micro/org/openjdk/bench/jdk/incubator/foreign/libQSortJNI.c new file mode 100644 index 0000000000000000000000000000000000000000..f6fe1b0c5d1a3f02f2a8aba2a49a1c99b3f28850 --- /dev/null +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/libQSortJNI.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include <jni.h> + +#include <stdlib.h> + +#include "jlong.h" +#include "JNICB.h" + +#ifdef _WIN64 +#define THREAD_LOCAL __declspec(thread) +#else +#define THREAD_LOCAL __thread +#endif + +THREAD_LOCAL struct { + JNICB cb; + JNIEnv* env; +} ctx_opt; + +static int comparator(const void* e0, const void* e1) { + JNICB jniCb = ctx_opt.cb; + JNIEnv* env = ctx_opt.env; + jint j0 = *((jint*) e0); + jint j1 = *((jint*) e1); + return (*env)->CallStaticIntMethod(env, jniCb->holder, jniCb->mid, j0, j1); +} + +JNIEXPORT void JNICALL Java_org_openjdk_bench_jdk_incubator_foreign_QSort_jni_1qsort_1optimized + (JNIEnv *env, jclass cls, jintArray arr, jlong cb) { + + ctx_opt.cb = jlong_to_ptr(cb); + ctx_opt.env = env; + + jint* ints = (*env)->GetIntArrayElements(env, arr, NULL); + jsize length = (*env)->GetArrayLength(env, arr); + + qsort(ints, length, sizeof(jint), &comparator); + + (*env)->ReleaseIntArrayElements(env, arr, ints, 0); +} + +JavaVM* VM = NULL; + +int java_cmp(const void *a, const void *b) { + int v1 = *((int*)a); + int v2 = *((int*)b); + + JNIEnv* env; + (*VM)->GetEnv(VM, (void**) &env, JNI_VERSION_10); + + jclass qsortClass = (*env)->FindClass(env, "org/openjdk/bench/jdk/incubator/foreign/QSort"); + jmethodID methodId = (*env)->GetStaticMethodID(env, qsortClass, "jni_upcall_compar", "(II)I"); + + return (*env)->CallStaticIntMethod(env, qsortClass, methodId, v1, v2); +} + +JNIEXPORT void JNICALL Java_org_openjdk_bench_jdk_incubator_foreign_QSort_jni_1qsort_1naive + (JNIEnv *env, jclass cls, jintArray arr) { + if (VM == NULL) { + (*env)->GetJavaVM(env, &VM); + } + + jint* carr = (*env)->GetIntArrayElements(env, arr, 0); + jsize length = (*env)->GetArrayLength(env, arr); + qsort(carr, length, sizeof(jint), java_cmp); + (*env)->ReleaseIntArrayElements(env, arr, carr, 0); +} diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/libUpcallsJNI.c b/test/micro/org/openjdk/bench/jdk/incubator/foreign/libUpcallsJNI.c index c44979e3e62f10025b4230f660e70a86bbcf4949..4e8926376213ebe1631a3199c87ca830ded2851e 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/foreign/libUpcallsJNI.c +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/libUpcallsJNI.c @@ -22,46 +22,9 @@ */ #include <jni.h> #include <stdlib.h> -#include "jlong.h" - -typedef struct { - jclass holder; - jmethodID mid; -} *JNICB; - -#define CHECK_NULL(thing, message) \ - if (thing == NULL) { \ - jclass cls = (*env)->FindClass(env, "java/lang/Exception"); \ - (*env)->ThrowNew(env, cls, message); \ - return 0; \ - } - -JNIEXPORT jlong JNICALL Java_org_openjdk_bench_jdk_incubator_foreign_Upcalls_makeCB - (JNIEnv *env, jclass cls, jstring holderName, jstring methodName, jstring descriptor) { - - const char* holderNameC = (*env)->GetStringUTFChars(env, holderName, NULL); - const char* methodNameC = (*env)->GetStringUTFChars(env, methodName, NULL); - const char* descriptorC = (*env)->GetStringUTFChars(env, descriptor, NULL); - - JNICB cb = malloc(sizeof *cb); - CHECK_NULL(cb, "Can not allocate cb"); - jclass holder = (*env)->FindClass(env, holderNameC); - CHECK_NULL(holder, "Can not find class"); - holder = (jclass) (*env)->NewGlobalRef(env, holder); - cb->holder = holder; - - jmethodID methodID = (*env)->GetStaticMethodID(env, holder, methodNameC, descriptorC); - CHECK_NULL(methodID, "Can not find method"); - //methodID = (jmethodID) (*env)->NewGlobalRef(env, methodID); // DON'T DO THIS! -> Crashes GC - cb->mid = methodID; - - (*env)->ReleaseStringUTFChars(env, holderName, holderNameC); - (*env)->ReleaseStringUTFChars(env, methodName, methodNameC); - (*env)->ReleaseStringUTFChars(env, descriptor, descriptorC); - - return ptr_to_jlong(cb); -} +#include "jlong.h" +#include "JNICB.h" JNIEXPORT void JNICALL Java_org_openjdk_bench_jdk_incubator_foreign_Upcalls_blank (JNIEnv *env, jclass cls, jlong cb) { diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/points/support/PanamaPoint.java b/test/micro/org/openjdk/bench/jdk/incubator/foreign/points/support/PanamaPoint.java index b12d57b20beaddfa5dfcb7284021fddec18e62b0..87c4855771bd4cefb9d92ad1c8f3d9634958bb01 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/foreign/points/support/PanamaPoint.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/points/support/PanamaPoint.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,46 +22,45 @@ */ package org.openjdk.bench.jdk.incubator.foreign.points.support; +import jdk.incubator.foreign.Addressable; +import jdk.incubator.foreign.CLinker; import jdk.incubator.foreign.FunctionDescriptor; -import jdk.incubator.foreign.SymbolLookup; import jdk.incubator.foreign.MemoryAddress; +import jdk.incubator.foreign.SymbolLookup; import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.MemorySegment; -import jdk.incubator.foreign.CLinker; import jdk.incubator.foreign.ResourceScope; +import org.openjdk.bench.jdk.incubator.foreign.CLayouts; import java.lang.invoke.MethodHandle; import java.lang.invoke.VarHandle; import static java.lang.invoke.MethodType.methodType; import static jdk.incubator.foreign.MemoryLayout.PathElement.groupElement; -import static jdk.incubator.foreign.CLinker.*; -public class PanamaPoint implements AutoCloseable { +public class PanamaPoint extends CLayouts implements AutoCloseable { public static final MemoryLayout LAYOUT = MemoryLayout.structLayout( C_INT.withName("x"), C_INT.withName("y") ); - private static final VarHandle VH_x = LAYOUT.varHandle(int.class, groupElement("x")); - private static final VarHandle VH_y = LAYOUT.varHandle(int.class, groupElement("y")); + private static final VarHandle VH_x = LAYOUT.varHandle(groupElement("x")); + private static final VarHandle VH_y = LAYOUT.varHandle(groupElement("y")); private static final MethodHandle MH_distance; private static final MethodHandle MH_distance_ptrs; static { - CLinker abi = CLinker.getInstance(); + CLinker abi = CLinker.systemCLinker(); System.loadLibrary("Point"); SymbolLookup lookup = SymbolLookup.loaderLookup(); MH_distance = abi.downcallHandle( lookup.lookup("distance").get(), - methodType(double.class, MemorySegment.class, MemorySegment.class), - FunctionDescriptor.of(C_DOUBLE, LAYOUT, LAYOUT) + FunctionDescriptor.of(C_DOUBLE, LAYOUT, LAYOUT) ); MH_distance_ptrs = abi.downcallHandle( - lookup.lookup("distance_ptrs").get(), - methodType(double.class, MemoryAddress.class, MemoryAddress.class), - FunctionDescriptor.of(C_DOUBLE, C_POINTER, C_POINTER) + lookup.lookup("distance_ptrs").get(), + FunctionDescriptor.of(C_DOUBLE, C_POINTER, C_POINTER) ); } @@ -107,7 +106,7 @@ public class PanamaPoint implements AutoCloseable { public double distanceToPtrs(PanamaPoint other) { try { - return (double) MH_distance_ptrs.invokeExact(segment.address(), other.segment.address()); + return (double) MH_distance_ptrs.invokeExact((Addressable)segment, (Addressable)other.segment); } catch (Throwable throwable) { throw new InternalError(throwable); } diff --git a/test/micro/org/openjdk/bench/jdk/incubator/vector/MaskFromLongBenchmark.java b/test/micro/org/openjdk/bench/jdk/incubator/vector/MaskFromLongBenchmark.java new file mode 100644 index 0000000000000000000000000000000000000000..e929697b57fba1e6b8663a7d0e002c1c906067e7 --- /dev/null +++ b/test/micro/org/openjdk/bench/jdk/incubator/vector/MaskFromLongBenchmark.java @@ -0,0 +1,138 @@ +// +// Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +// +// This code is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License version 2 only, as +// published by the Free Software Foundation. +// +// This code is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// version 2 for more details (a copy is included in the LICENSE file that +// accompanied this code). +// +// You should have received a copy of the GNU General Public License version +// 2 along with this work; if not, write to the Free Software Foundation, +// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +// or visit www.oracle.com if you need additional information or have any +// questions. +// +// +package org.openjdk.bench.jdk.incubator.vector; + +import jdk.incubator.vector.*; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.Blackhole; + +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Thread) +@Fork(jvmArgsPrepend = {"--add-modules=jdk.incubator.vector"}) +public class MaskFromLongBenchmark { + static long val = 0; + + @Setup(Level.Invocation) + public void BmSetup() { + val++; + } + + @Benchmark + public int microMaskFromLong_Byte64() { + VectorMask mask = VectorMask.fromLong(ByteVector.SPECIES_64, val); + return mask.laneIsSet(1) ? 1 : 0; + } + + @Benchmark + public int microMaskFromLong_Byte128() { + VectorMask mask = VectorMask.fromLong(ByteVector.SPECIES_128, val); + return mask.laneIsSet(1) ? 1 : 0; + } + + @Benchmark + public int microMaskFromLong_Byte256() { + VectorMask mask = VectorMask.fromLong(ByteVector.SPECIES_256, val); + return mask.laneIsSet(1) ? 1 : 0; + } + + @Benchmark + public int microMaskFromLong_Byte512() { + VectorMask mask = VectorMask.fromLong(ByteVector.SPECIES_512, val); + return mask.laneIsSet(1) ? 1 : 0; + } + + @Benchmark + public int microMaskFromLong_Short64() { + VectorMask mask = VectorMask.fromLong(ShortVector.SPECIES_64, val); + return mask.laneIsSet(1) ? 1 : 0; + } + + @Benchmark + public int microMaskFromLong_Short128() { + VectorMask mask = VectorMask.fromLong(ShortVector.SPECIES_128, val); + return mask.laneIsSet(1) ? 1 : 0; + } + + @Benchmark + public int microMaskFromLong_Short256() { + VectorMask mask = VectorMask.fromLong(ShortVector.SPECIES_256, val); + return mask.laneIsSet(1) ? 1 : 0; + } + + @Benchmark + public int microMaskFromLong_Short512() { + VectorMask mask = VectorMask.fromLong(ShortVector.SPECIES_512, val); + return mask.laneIsSet(1) ? 1 : 0; + } + + @Benchmark + public int microMaskFromLong_Integer64() { + VectorMask mask = VectorMask.fromLong(IntVector.SPECIES_64, val); + return mask.laneIsSet(1) ? 1 : 0; + } + + @Benchmark + public int microMaskFromLong_Integer128() { + VectorMask mask = VectorMask.fromLong(IntVector.SPECIES_128, val); + return mask.laneIsSet(1) ? 1 : 0; + } + + @Benchmark + public int microMaskFromLong_Integer256() { + VectorMask mask = VectorMask.fromLong(IntVector.SPECIES_256, val); + return mask.laneIsSet(1) ? 1 : 0; + } + + @Benchmark + public int microMaskFromLong_Integer512() { + VectorMask mask = VectorMask.fromLong(IntVector.SPECIES_512, val); + return mask.laneIsSet(1) ? 1 : 0; + } + + @Benchmark + public int microMaskFromLong_Long64() { + VectorMask mask = VectorMask.fromLong(LongVector.SPECIES_64, val); + return mask.laneIsSet(0) ? 1 : 0; + } + + @Benchmark + public int microMaskFromLong_Long128() { + VectorMask mask = VectorMask.fromLong(LongVector.SPECIES_128, val); + return mask.laneIsSet(1) ? 1 : 0; + } + + @Benchmark + public int microMaskFromLong_Long256() { + VectorMask mask = VectorMask.fromLong(LongVector.SPECIES_256, val); + return mask.laneIsSet(1) ? 1 : 0; + } + + @Benchmark + public int microMaskFromLong_Long512() { + VectorMask mask = VectorMask.fromLong(LongVector.SPECIES_512, val); + return mask.laneIsSet(1) ? 1 : 0; + } + +} diff --git a/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadStoreBytes.java b/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadStoreBytes.java index 582a7b4665a0131c8d73e5c07e6f48ccfd86909e..ce0386cb028aec203c6aeedf598a2779ee74833c 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadStoreBytes.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadStoreBytes.java @@ -26,8 +26,6 @@ package org.openjdk.bench.jdk.incubator.vector; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.concurrent.TimeUnit; -import jdk.incubator.foreign.CLinker; -import jdk.incubator.foreign.MemoryAccess; import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; @@ -46,6 +44,8 @@ import org.openjdk.jmh.annotations.Setup; import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.annotations.Warmup; +import static jdk.incubator.foreign.ValueLayout.JAVA_BYTE; + @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @@ -116,8 +116,8 @@ public class TestLoadStoreBytes { dstBufferSegmentImplicit = dstSegmentImplicit.asByteBuffer(); - srcAddress = CLinker.allocateMemory(size); - dstAddress = CLinker.allocateMemory(size); + srcAddress = MemorySegment.allocateNative(size, implicitScope).address(); + dstAddress = MemorySegment.allocateNative(size, implicitScope).address(); a = new byte[size]; b = new byte[size]; @@ -232,16 +232,16 @@ public class TestLoadStoreBytes { @CompilerControl(CompilerControl.Mode.PRINT) public void segmentImplicitScalar() { for (int i = 0; i < SPECIES.loopBound(srcArray.length); i++) { - var v = MemoryAccess.getByteAtOffset(srcSegmentImplicit, i); - MemoryAccess.setByteAtOffset(dstSegmentImplicit, i, v); + var v = srcSegmentImplicit.get(JAVA_BYTE, i); + dstSegmentImplicit.set(JAVA_BYTE, i, v); } } @Benchmark public void bufferSegmentConfined() { try (final var scope = ResourceScope.newConfinedScope()) { - final var srcBufferSegmentConfined = srcAddress.asSegment(size, scope).asByteBuffer(); - final var dstBufferSegmentConfined = dstAddress.asSegment(size, scope).asByteBuffer(); + final var srcBufferSegmentConfined = MemorySegment.ofAddress(srcAddress, size, scope).asByteBuffer(); + final var dstBufferSegmentConfined = MemorySegment.ofAddress(dstAddress, size, scope).asByteBuffer(); for (int i = 0; i < SPECIES.loopBound(srcArray.length); i += SPECIES.length()) { var v = ByteVector.fromByteBuffer(SPECIES, srcBufferSegmentConfined, i, ByteOrder.nativeOrder()); diff --git a/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadStoreShort.java b/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadStoreShort.java index 6bd9a85143fdf7dd8256c13ed7a3ea4fb3b734f8..881cfad9aa6d54290a8093f835a26cd3644d2da1 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadStoreShort.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadStoreShort.java @@ -26,7 +26,7 @@ package org.openjdk.bench.jdk.incubator.vector; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.concurrent.TimeUnit; -import jdk.incubator.foreign.CLinker; + import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; @@ -112,15 +112,15 @@ public class TestLoadStoreShort { dstBufferNative = ByteBuffer.allocateDirect(size); - implicitScope = ResourceScope.newImplicitScope(); + implicitScope = ResourceScope.newSharedScope(); srcSegmentImplicit = MemorySegment.allocateNative(size, SPECIES.vectorByteSize(), implicitScope); srcBufferSegmentImplicit = srcSegmentImplicit.asByteBuffer(); dstSegmentImplicit = MemorySegment.allocateNative(size, SPECIES.vectorByteSize(), implicitScope); dstBufferSegmentImplicit = dstSegmentImplicit.asByteBuffer(); - srcAddress = CLinker.allocateMemory(size); - dstAddress = CLinker.allocateMemory(size); + srcAddress = MemorySegment.allocateNative(size, implicitScope).address(); + dstAddress = MemorySegment.allocateNative(size, implicitScope).address(); this.longSize = longSize; @@ -130,12 +130,6 @@ public class TestLoadStoreShort { } - @TearDown - public void tearDown() { - CLinker.freeMemory(srcAddress); - CLinker.freeMemory(dstAddress); - } - @Benchmark @CompilerControl(CompilerControl.Mode.PRINT) public void array() { @@ -216,8 +210,8 @@ public class TestLoadStoreShort { @Benchmark public void bufferSegmentConfined() { try (final var scope = ResourceScope.newConfinedScope()) { - final var srcBufferSegmentConfined = srcAddress.asSegment(size, scope).asByteBuffer(); - final var dstBufferSegmentConfined = dstAddress.asSegment(size, scope).asByteBuffer(); + final var srcBufferSegmentConfined = MemorySegment.ofAddress(srcAddress, size, scope).asByteBuffer(); + final var dstBufferSegmentConfined = MemorySegment.ofAddress(dstAddress, size, scope).asByteBuffer(); for (int i = 0; i < SPECIES.loopBound(srcArray.length); i += SPECIES.length()) { var v = ShortVector.fromByteBuffer(SPECIES, srcBufferSegmentConfined, i, ByteOrder.nativeOrder()); diff --git a/test/micro/org/openjdk/bench/vm/compiler/InterfacePrivateCalls.java b/test/micro/org/openjdk/bench/vm/compiler/InterfacePrivateCalls.java new file mode 100644 index 0000000000000000000000000000000000000000..620b885db366f20049d3a8866dcbb21d27ce3f09 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/InterfacePrivateCalls.java @@ -0,0 +1,80 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.compiler; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; + +@State(Scope.Benchmark) +public class InterfacePrivateCalls { + interface I { + private int bar() { return 0; } + default int foo() { + return bar(); + } + } + + static class C1 implements I {} + static class C2 implements I {} + static class C3 implements I {} + + private I[] objs; + + @Setup(Level.Trial) + public void setupTrial() { + objs = new I[3]; + objs[0] = new C1(); + objs[1] = new C2(); + objs[2] = new C3(); + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + @Fork(value=1, jvmArgsAppend={"-XX:TieredStopAtLevel=1"}) + public void invokePrivateInterfaceMethodC1() { + for (int i = 0; i < objs.length; ++i) { + objs[i].foo(); + } + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + @Fork(value=1) + public void invokePrivateInterfaceMethodC2() { + for (int i = 0; i < objs.length; ++i) { + objs[i].foo(); + } + } +} diff --git a/test/micro/org/openjdk/bench/vm/compiler/IterativeEA.java b/test/micro/org/openjdk/bench/vm/compiler/IterativeEA.java new file mode 100644 index 0000000000000000000000000000000000000000..26e75f0e05270783bcc677cf7ba7ae2b8b262809 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/IterativeEA.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.openjdk.bench.vm.compiler; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +@Fork(1) + +public class IterativeEA { + + public static int ii = 1; + + static class A { + int i; + + public A(int i) { + this.i = i; + } + } + + static class B { + A a; + + public B(A a) { + this.a = a; + } + } + + static class C { + B b; + + public C(B b) { + this.b = b; + } + } + + @Benchmark + public int test1() { + C c = new C(new B(new A(ii))); + return c.b.a.i; + } + + static class Point { + int x; + int y; + int ax[]; + int ay[]; + } + + @Benchmark + public int test2() { + Point p = new Point(); + p.ax = new int[2]; + p.ay = new int[2]; + int x = 3; + p.ax[0] = x; + p.ay[1] = 3 * x + ii; + return p.ax[0] * p.ay[1]; + } + + public static final Double dbc = Double.valueOf(1.); + + @Benchmark + public double test3() { + Double j1 = Double.valueOf(1.); + Double j2 = Double.valueOf(1.); + for (int i = 0; i< 1000; i++) { + j1 = j1 + 1.; + j2 = j2 + 2.; + } + return j1 + j2; + } +} diff --git a/test/micro/org/openjdk/bench/vm/compiler/PointerBenchmarkFlat.java b/test/micro/org/openjdk/bench/vm/compiler/PointerBenchmarkFlat.java new file mode 100644 index 0000000000000000000000000000000000000000..f83e494b2c96df54c4975a5eab9ec32e75ae3dd3 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/PointerBenchmarkFlat.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.openjdk.bench.vm.compiler; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.util.concurrent.TimeUnit; + +@Fork(value = 3) +@BenchmarkMode(Mode.AverageTime) +@Warmup(iterations = 3, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Benchmark) +public class PointerBenchmarkFlat { + + static final int ELEM_SIZE = 1_000_000; + + PointerImpl ptr_ptr; + PointerImplFlat ptr_ptr_flat; + + @Setup + public void setup() { + ptr_ptr = new PointerImpl(new FakeSegment(MemoryAddress.NULL, Long.MAX_VALUE)); + ptr_ptr_flat = new PointerImplFlat(new FakeSegmentFlat(MemoryAddress.NULL, Long.MAX_VALUE)); + } + + static class MemoryAddress { + private long addr; + + public MemoryAddress(long addr) { + this.addr = addr; + } + + long toRawLongValue() { + return addr; + } + + private static final MemoryAddress NULL = new MemoryAddress(0); + + static MemoryAddress ofLong(long val) { + return new MemoryAddress(val); + } + } + + static class PointerImpl { + final FakeSegment segment; + + public PointerImpl(FakeSegment segment) { + this.segment = segment; + } + + MemoryAddress address() { + return segment.address(); + } + + PointerImpl get(long index) { + MemoryAddress address = MemoryAddress.ofLong(index); + FakeSegment holder = new FakeSegment(address, Long.MAX_VALUE); + return new PointerImpl(holder); + } + } + + static class PointerImplFlat { + final FakeSegmentFlat segment; + + public PointerImplFlat(FakeSegmentFlat segment) { + this.segment = segment; + } + + MemoryAddress address() { + return segment.address(); + } + + PointerImplFlat get(long index) { + MemoryAddress address = MemoryAddress.ofLong(index); + FakeSegmentFlat holder = new FakeSegmentFlat(address, Long.MAX_VALUE); + return new PointerImplFlat(holder); + } + } + + static class AbstractFakeSegment { + final long size; + + public AbstractFakeSegment(long size) { + this.size = size; + } + } + + static class FakeSegment extends AbstractFakeSegment { + final MemoryAddress address; + + public FakeSegment(MemoryAddress address, long size) { + super(size); + this.address = address; + } + + MemoryAddress address() { + return address; + } + } + + static class FakeSegmentFlat { + final MemoryAddress address; + final long size; + + public FakeSegmentFlat(MemoryAddress address, long size) { + this.size = size; + this.address = address; + } + + MemoryAddress address() { + return address; + } + } + + @Benchmark + public int test() { + int sum = 0; + for (int i = 0 ; i < ELEM_SIZE ; i++) { + sum += ptr_ptr.get(i).address().toRawLongValue(); + } + return sum; + } + + @Benchmark + public int testFlat() { + int sum = 0; + for (int i = 0 ; i < ELEM_SIZE ; i++) { + sum += ptr_ptr_flat.get(i).address().toRawLongValue(); + } + return sum; + } +} diff --git a/test/micro/org/openjdk/bench/vm/compiler/SubIdealC0Minus_YPlusC1_.java b/test/micro/org/openjdk/bench/vm/compiler/SubIdealC0Minus_YPlusC1_.java new file mode 100644 index 0000000000000000000000000000000000000000..17728f6bc2589decdacbbe4dead337f4022b40c9 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/SubIdealC0Minus_YPlusC1_.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.openjdk.bench.vm.compiler; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.concurrent.TimeUnit; + +/** + * Tests transformation that converts "c0 - (x + c1)" into "(c0 - c1) + * - x" in SubINode::Ideal and SubLNode::Ideal. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Thread) +@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) +@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) +@Fork(value = 3 , jvmArgsAppend = {"-XX:-TieredCompilation", "-Xbatch", "-Xcomp"}) +public class SubIdealC0Minus_YPlusC1_ { + + private static final int I_C0 = 1234567; + + private static final int I_C1 = 1234567; + + private static final long L_C0 = 123_456_789_123_456L; + + private static final long L_C1 = 123_456_789_123_456L; + + private final int size = 100_000_000; + + private int[] ints_a; + + private long[] longs_a; + + @Setup + public void init() { + ints_a = new int[size]; + longs_a = new long[size]; + for (int i = 0; i < size; i++) { + ints_a[i] = i; + longs_a[i] = i * i; + } + } + + @Benchmark + public void baseline() { + for (int i = 0; i < size; i++) { + sink(ints_a[i]); + sink(longs_a[i]); + } + } + + @Benchmark + public void test() { + for (int i = 0; i < size; i++) { + sink(helper(ints_a[i])); + sink(helper(longs_a[i])); + } + } + + // Convert "c0 - (x + c1)" into "(c0 - c1) - x" for int. + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static int helper(int x) { + return I_C0 - (x + I_C1); + } + + // Convert "c0 - (x + c1)" into "(c0 - c1) - x" for long. + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static long helper(long x) { + return L_C0 - (x + L_C1); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static void sink(int v) {} + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static void sink(long v) {} +}