1#!/usr/bin/python3 2# 3# Copyright (C) 2018 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17""" 18Generate java test files for 712-varhandle-invocations 19""" 20 21from enum import Enum 22from pathlib import Path 23from random import Random 24from string import Template 25 26import io 27import re 28import sys 29 30class JavaType(object): 31 def __init__(self, name, examples, supports_bitwise=False, supports_numeric=False): 32 self.name=name 33 self.examples=examples 34 self.supports_bitwise=supports_bitwise 35 self.supports_numeric=supports_numeric 36 37 def is_value_type(self): 38 return False 39 40 def __repr__(self): 41 return self.name 42 43 def __str__(self): 44 return self.name 45 46class ValueType(JavaType): 47 def __init__(self, name, boxed_type, examples, ordinal=-1, width=-1, supports_bitwise=True, supports_numeric=True): 48 JavaType.__init__(self, name, examples, supports_bitwise, supports_numeric) 49 self.ordinal=ordinal 50 self.width=width 51 self.boxed_type=boxed_type 52 53 def boxing_method(self): 54 return self.boxed_type + ".valueOf" 55 56 def unboxing_method(self): 57 return self.name + "Value" 58 59 def is_value_type(self): 60 return True 61 62 def __eq__(self, other): 63 return self.ordinal == other.ordinal 64 65 def __hash__(self): 66 return self.ordinal 67 68 def __le__(self, other): 69 return self.ordinal < other.ordinal 70 71 def __repr__(self): 72 return self.name 73 74 def __str__(self): 75 return self.name 76 77BOOLEAN_TYPE = ValueType("boolean", "Boolean", [ "true", "false" ], ordinal = 0, width = 1, supports_numeric=False) 78BYTE_TYPE=ValueType("byte", "Byte", [ "(byte) -128", "(byte) -61", "(byte) 7", "(byte) 127", "(byte) 33" ], ordinal=1, width=1) 79SHORT_TYPE=ValueType("short", "Short", [ "(short) -32768", "(short) -384", "(short) 32767", "(short) 0xaa55" ], ordinal=2, width=2) 80CHAR_TYPE=ValueType("char", "Character", [ r"'A'", r"'#'", r"'$'", r"'Z'", r"'t'", r"'c'", r"Character.MAX_VALUE", r"Character.MIN_LOW_SURROGATE"], ordinal=3, width=2) 81INT_TYPE=ValueType("int", "Integer", [ "-0x01234567", "0x7f6e5d4c", "0x12345678", "0x10215220", "42" ], ordinal=4, width=4) 82LONG_TYPE=ValueType("long", "Long", [ "-0x0123456789abcdefl", "0x789abcdef0123456l", "0xfedcba9876543210l" ], ordinal=5, width=8) 83FLOAT_TYPE=ValueType("float", "Float", [ "-7.77e23f", "1.234e-17f", "3.40e36f", "-8.888e3f", "4.442e11f" ], ordinal=6, width=4, supports_bitwise=False) 84DOUBLE_TYPE=ValueType("double", "Double", [ "-1.0e-200", "1.11e200", "3.141", "1.1111", "6.022e23", "6.626e-34" ], ordinal=7, width=4, supports_bitwise=False) 85 86VALUE_TYPES = { BOOLEAN_TYPE, BYTE_TYPE, SHORT_TYPE, CHAR_TYPE, INT_TYPE, LONG_TYPE, FLOAT_TYPE, DOUBLE_TYPE } 87VIEW_SUPPORTED_TYPES = list(filter(lambda x : x.width >= 2, VALUE_TYPES)) 88VIEW_SUPPORTED_NARROW_TYPES = list(filter(lambda x : x.width == 2, VALUE_TYPES)) 89 90WIDENING_CONVERSIONS = { 91 BOOLEAN_TYPE : set(), 92 BYTE_TYPE : { SHORT_TYPE, INT_TYPE, LONG_TYPE, FLOAT_TYPE, DOUBLE_TYPE }, 93 SHORT_TYPE : { INT_TYPE, LONG_TYPE, FLOAT_TYPE, DOUBLE_TYPE }, 94 CHAR_TYPE : { INT_TYPE, LONG_TYPE, FLOAT_TYPE, DOUBLE_TYPE }, 95 INT_TYPE : { LONG_TYPE, FLOAT_TYPE, DOUBLE_TYPE }, 96 LONG_TYPE : { FLOAT_TYPE, DOUBLE_TYPE }, 97 FLOAT_TYPE : { DOUBLE_TYPE }, 98 DOUBLE_TYPE : set() 99} 100 101def types_that_widen_to(var_type): 102 types_that_widen = { var_type } 103 for src_type in WIDENING_CONVERSIONS: 104 if var_type in WIDENING_CONVERSIONS[src_type]: 105 types_that_widen.add(src_type) 106 return types_that_widen 107 108class VarHandleKind(object): 109 def __init__(self, name, supported_types=[], imports=[], declarations=[], lookup='', coordinates=[], get_value='', may_throw_read_only=False): 110 self.name = name 111 self.supported_types = supported_types 112 self.imports = imports 113 self.declarations = declarations 114 self.lookup = lookup 115 self.coordinates = coordinates 116 self.get_value_ = get_value 117 self.may_throw_read_only = may_throw_read_only 118 119 def get_name(self): 120 return self.name 121 122 def get_coordinates(self): 123 return self.coordinates 124 125 def get_field_declarations(self, dictionary): 126 return list(map(lambda d: Template(d).safe_substitute(dictionary), self.declarations)) 127 128 def get_imports(self): 129 return self.imports 130 131 def get_lookup(self, dictionary): 132 return Template(self.lookup).safe_substitute(dictionary) 133 134 def get_supported_types(self): 135 return self.supported_types 136 137 def is_view(self): 138 return "View" in self.name 139 140 def get_value(self, dictionary): 141 return Template(self.get_value_).safe_substitute(dictionary) 142 143FIELD_VAR_HANDLE = VarHandleKind("Field", 144 VALUE_TYPES, 145 [ 146 'java.lang.invoke.MethodHandles', 147 'java.lang.invoke.VarHandle' 148 ], 149 [ 150 "${var_type} field = ${initial_value}" 151 ], 152 'MethodHandles.lookup().findVarHandle(${test_class}.class, "field", ${var_type}.class)', 153 [ 154 'this' 155 ], 156 'field', 157 may_throw_read_only = False) 158 159FINAL_FIELD_VAR_HANDLE = VarHandleKind("FinalField", 160 VALUE_TYPES, 161 [ 162 'java.lang.invoke.MethodHandles', 163 'java.lang.invoke.VarHandle' 164 ], 165 [ 166 "${var_type} field = ${initial_value}" 167 ], 168 'MethodHandles.lookup().findVarHandle(${test_class}.class, "field", ${var_type}.class)', 169 [ 170 'this' 171 ], 172 'field', 173 may_throw_read_only = False) 174 175STATIC_FIELD_VAR_HANDLE = VarHandleKind("StaticField", 176 VALUE_TYPES, 177 [ 178 'java.lang.invoke.MethodHandles', 179 'java.lang.invoke.VarHandle' 180 ], 181 [ 182 "static ${var_type} field = ${initial_value}" 183 ], 184 'MethodHandles.lookup().findStaticVarHandle(${test_class}.class, "field", ${var_type}.class)', 185 [], 186 'field', 187 may_throw_read_only = False) 188 189STATIC_FINAL_FIELD_VAR_HANDLE = VarHandleKind("StaticFinalField", 190 VALUE_TYPES, 191 [ 192 'java.lang.invoke.MethodHandles', 193 'java.lang.invoke.VarHandle' 194 ], 195 [ 196 "static ${var_type} field = ${initial_value}" 197 ], 198 'MethodHandles.lookup().findStaticVarHandle(${test_class}.class, "field", ${var_type}.class)', 199 [], 200 'field', 201 may_throw_read_only = False) 202 203ARRAY_ELEMENT_VAR_HANDLE = VarHandleKind("ArrayElement", 204 VALUE_TYPES, 205 [ 206 'java.lang.invoke.MethodHandles', 207 'java.lang.invoke.VarHandle' 208 ], 209 [ 210 "${var_type}[] array = new ${var_type}[11]", 211 "int index = 3", 212 "{ array[index] = ${initial_value}; }" 213 ], 214 'MethodHandles.arrayElementVarHandle(${var_type}[].class)', 215 [ 'array', 'index'], 216 'array[index]', 217 may_throw_read_only = False) 218 219BYTE_ARRAY_LE_VIEW_VAR_HANDLE = VarHandleKind("ByteArrayViewLE", 220 VIEW_SUPPORTED_TYPES, 221 [ 222 'java.lang.invoke.MethodHandles', 223 'java.lang.invoke.VarHandle', 224 'java.nio.ByteOrder' 225 ], 226 [ 227 "byte[] array = VarHandleUnitTestHelpers.createFilledByteArray(27)", 228 "int index = 8", 229 "{" 230 " index = VarHandleUnitTestHelpers.alignedOffset_${var_type}(array, index);" 231 " VarHandleUnitTestHelpers.setBytesAs_${var_type}(array, index, ${initial_value}, ByteOrder.LITTLE_ENDIAN);" 232 "}" 233 ], 234 'MethodHandles.byteArrayViewVarHandle(${var_type}[].class, ByteOrder.LITTLE_ENDIAN)', 235 [ 236 'array', 237 'index' 238 ], 239 'VarHandleUnitTestHelpers.getBytesAs_${var_type}(array, index, ByteOrder.LITTLE_ENDIAN)', 240 may_throw_read_only = False) 241 242NARROW_BYTE_ARRAY_LE_VIEW_VAR_HANDLE = VarHandleKind("NarrowByteArrayViewLE", 243 VIEW_SUPPORTED_NARROW_TYPES, 244 [ 245 'java.lang.invoke.MethodHandles', 246 'java.lang.invoke.VarHandle', 247 'java.nio.ByteOrder' 248 ], 249 [ 250 "byte[] array = VarHandleUnitTestHelpers.createFilledByteArray(27)", 251 "int index = 10", 252 "{" 253 " index = VarHandleUnitTestHelpers.alignedOffset_${var_type}(array, index);" 254 " VarHandleUnitTestHelpers.setBytesAs_${var_type}(array, index, ${initial_value}, ByteOrder.LITTLE_ENDIAN);" 255 "}" 256 ], 257 'MethodHandles.byteArrayViewVarHandle(${var_type}[].class, ByteOrder.LITTLE_ENDIAN)', 258 [ 259 'array', 260 'index' 261 ], 262 'VarHandleUnitTestHelpers.getBytesAs_${var_type}(array, index, ByteOrder.LITTLE_ENDIAN)', 263 may_throw_read_only = False) 264 265BYTE_ARRAY_BE_VIEW_VAR_HANDLE = VarHandleKind("ByteArrayViewBE", 266 VIEW_SUPPORTED_TYPES, 267 [ 268 'java.lang.invoke.MethodHandles', 269 'java.lang.invoke.VarHandle', 270 'java.nio.ByteOrder' 271 ], 272 [ 273 "byte[] array = VarHandleUnitTestHelpers.createFilledByteArray(27)", 274 "int index = 8", 275 "{" 276 " index = VarHandleUnitTestHelpers.alignedOffset_${var_type}(array, index);" 277 " VarHandleUnitTestHelpers.setBytesAs_${var_type}(array, index, ${initial_value}, ByteOrder.BIG_ENDIAN);" 278 "}" 279 ], 280 'MethodHandles.byteArrayViewVarHandle(${var_type}[].class, ByteOrder.BIG_ENDIAN)', 281 [ 282 'array', 283 'index' 284 ], 285 'VarHandleUnitTestHelpers.getBytesAs_${var_type}(array, index, ByteOrder.BIG_ENDIAN)', 286 may_throw_read_only = False) 287 288NARROW_BYTE_ARRAY_BE_VIEW_VAR_HANDLE = VarHandleKind("NarrowByteArrayViewBE", 289 VIEW_SUPPORTED_NARROW_TYPES, 290 [ 291 'java.lang.invoke.MethodHandles', 292 'java.lang.invoke.VarHandle', 293 'java.nio.ByteOrder' 294 ], 295 [ 296 "byte[] array = VarHandleUnitTestHelpers.createFilledByteArray(27)", 297 "int index = 10", 298 "{" 299 " index = VarHandleUnitTestHelpers.alignedOffset_${var_type}(array, index);" 300 " VarHandleUnitTestHelpers.setBytesAs_${var_type}(array, index, ${initial_value}, ByteOrder.BIG_ENDIAN);" 301 "}" 302 ], 303 'MethodHandles.byteArrayViewVarHandle(${var_type}[].class, ByteOrder.BIG_ENDIAN)', 304 [ 305 'array', 306 'index' 307 ], 308 'VarHandleUnitTestHelpers.getBytesAs_${var_type}(array, index, ByteOrder.BIG_ENDIAN)', 309 may_throw_read_only = False) 310 311DIRECT_BYTE_BUFFER_LE_VIEW_VAR_HANDLE = VarHandleKind("DirectByteBufferViewLE", 312 VIEW_SUPPORTED_TYPES, 313 [ 314 'java.lang.invoke.MethodHandles', 315 'java.lang.invoke.VarHandle', 316 'java.nio.ByteBuffer', 317 'java.nio.ByteOrder' 318 ], 319 [ 320 "ByteBuffer bb = ByteBuffer.allocateDirect(31)", 321 "int index = 8", 322 "{" 323 " index = VarHandleUnitTestHelpers.alignedOffset_${var_type}(bb, index);" 324 " VarHandleUnitTestHelpers.setBytesAs_${var_type}(bb, index, ${initial_value}, ByteOrder.LITTLE_ENDIAN);" 325 "}" 326 ], 327 'MethodHandles.byteBufferViewVarHandle(${var_type}[].class, ByteOrder.LITTLE_ENDIAN)', 328 [ 329 'bb', 330 'index' 331 ], 332 'VarHandleUnitTestHelpers.getBytesAs_${var_type}(bb, index, ByteOrder.LITTLE_ENDIAN)', 333 may_throw_read_only = False) 334 335NARROW_DIRECT_BYTE_BUFFER_LE_VIEW_VAR_HANDLE = VarHandleKind("NarrowDirectByteBufferViewLE", 336 VIEW_SUPPORTED_NARROW_TYPES, 337 [ 338 'java.lang.invoke.MethodHandles', 339 'java.lang.invoke.VarHandle', 340 'java.nio.ByteBuffer', 341 'java.nio.ByteOrder' 342 ], 343 [ 344 "ByteBuffer bb = ByteBuffer.allocateDirect(31)", 345 "int index = 10", 346 "{" 347 " index = VarHandleUnitTestHelpers.alignedOffset_${var_type}(bb, index);" 348 " VarHandleUnitTestHelpers.setBytesAs_${var_type}(bb, index, ${initial_value}, ByteOrder.LITTLE_ENDIAN);" 349 "}" 350 ], 351 'MethodHandles.byteBufferViewVarHandle(${var_type}[].class, ByteOrder.LITTLE_ENDIAN)', 352 [ 353 'bb', 354 'index' 355 ], 356 'VarHandleUnitTestHelpers.getBytesAs_${var_type}(bb, index, ByteOrder.LITTLE_ENDIAN)', 357 may_throw_read_only = False) 358 359DIRECT_BYTE_BUFFER_BE_VIEW_VAR_HANDLE = VarHandleKind("DirectByteBufferViewBE", 360 VIEW_SUPPORTED_TYPES, 361 [ 362 'java.lang.invoke.MethodHandles', 363 'java.lang.invoke.VarHandle', 364 'java.nio.ByteBuffer', 365 'java.nio.ByteOrder' 366 ], 367 [ 368 "ByteBuffer bb = ByteBuffer.allocateDirect(31)", 369 "int index = 8", 370 "{" 371 " index = VarHandleUnitTestHelpers.alignedOffset_${var_type}(bb, index);" 372 " VarHandleUnitTestHelpers.setBytesAs_${var_type}(bb, index, ${initial_value}, ByteOrder.BIG_ENDIAN);" 373 "}" 374 ], 375 'MethodHandles.byteBufferViewVarHandle(${var_type}[].class, ByteOrder.BIG_ENDIAN)', 376 [ 377 'bb', 378 'index' 379 ], 380 'VarHandleUnitTestHelpers.getBytesAs_${var_type}(bb, index, ByteOrder.BIG_ENDIAN)', 381 may_throw_read_only = False) 382 383NARROW_DIRECT_BYTE_BUFFER_BE_VIEW_VAR_HANDLE = VarHandleKind("NarrowDirectByteBufferViewBE", 384 VIEW_SUPPORTED_NARROW_TYPES, 385 [ 386 'java.lang.invoke.MethodHandles', 387 'java.lang.invoke.VarHandle', 388 'java.nio.ByteBuffer', 389 'java.nio.ByteOrder' 390 ], 391 [ 392 "ByteBuffer bb = ByteBuffer.allocateDirect(31)", 393 "int index = 10", 394 "{" 395 " index = VarHandleUnitTestHelpers.alignedOffset_${var_type}(bb, index);" 396 " VarHandleUnitTestHelpers.setBytesAs_${var_type}(bb, index, ${initial_value}, ByteOrder.BIG_ENDIAN);" 397 "}" 398 ], 399 'MethodHandles.byteBufferViewVarHandle(${var_type}[].class, ByteOrder.BIG_ENDIAN)', 400 [ 401 'bb', 402 'index' 403 ], 404 'VarHandleUnitTestHelpers.getBytesAs_${var_type}(bb, index, ByteOrder.BIG_ENDIAN)', 405 may_throw_read_only = False) 406 407HEAP_BYTE_BUFFER_LE_VIEW_VAR_HANDLE = VarHandleKind("HeapByteBufferViewLE", 408 VIEW_SUPPORTED_TYPES, 409 [ 410 'java.lang.invoke.MethodHandles', 411 'java.lang.invoke.VarHandle', 412 'java.nio.ByteBuffer', 413 'java.nio.ByteOrder' 414 ], 415 [ 416 "byte[] array = VarHandleUnitTestHelpers.createFilledByteArray(36)", 417 "int offset = 8", 418 "ByteBuffer bb = ByteBuffer.wrap(array, offset, array.length - offset)", 419 "int index = 8", 420 "{" 421 " index = VarHandleUnitTestHelpers.alignedOffset_${var_type}(bb, index);" 422 " VarHandleUnitTestHelpers.setBytesAs_${var_type}(bb, index, ${initial_value}, ByteOrder.LITTLE_ENDIAN);" 423 "}" 424 ], 425 'MethodHandles.byteBufferViewVarHandle(${var_type}[].class, ByteOrder.LITTLE_ENDIAN)', 426 [ 427 'bb', 428 'index' 429 ], 430 'VarHandleUnitTestHelpers.getBytesAs_${var_type}(bb, index, ByteOrder.LITTLE_ENDIAN)', 431 may_throw_read_only = False) 432 433NARROW_HEAP_BYTE_BUFFER_LE_VIEW_VAR_HANDLE = VarHandleKind("NarrowHeapByteBufferViewLE", 434 VIEW_SUPPORTED_NARROW_TYPES, 435 [ 436 'java.lang.invoke.MethodHandles', 437 'java.lang.invoke.VarHandle', 438 'java.nio.ByteBuffer', 439 'java.nio.ByteOrder' 440 ], 441 [ 442 "byte[] array = VarHandleUnitTestHelpers.createFilledByteArray(36)", 443 "int offset = 8", 444 "ByteBuffer bb = ByteBuffer.wrap(array, offset, array.length - offset)", 445 "int index = 10", 446 "{" 447 " index = VarHandleUnitTestHelpers.alignedOffset_${var_type}(bb, index);" 448 " VarHandleUnitTestHelpers.setBytesAs_${var_type}(bb, index, ${initial_value}, ByteOrder.LITTLE_ENDIAN);" 449 "}" 450 ], 451 'MethodHandles.byteBufferViewVarHandle(${var_type}[].class, ByteOrder.LITTLE_ENDIAN)', 452 [ 453 'bb', 454 'index' 455 ], 456 'VarHandleUnitTestHelpers.getBytesAs_${var_type}(bb, index, ByteOrder.LITTLE_ENDIAN)', 457 may_throw_read_only = False) 458 459HEAP_BYTE_BUFFER_BE_VIEW_VAR_HANDLE = VarHandleKind("HeapByteBufferViewBE", 460 VIEW_SUPPORTED_TYPES, 461 [ 462 'java.lang.invoke.MethodHandles', 463 'java.lang.invoke.VarHandle', 464 'java.nio.ByteBuffer', 465 'java.nio.ByteOrder' 466 ], 467 [ 468 "byte[] array = VarHandleUnitTestHelpers.createFilledByteArray(47)", 469 "int offset = 8", 470 "ByteBuffer bb = ByteBuffer.wrap(array, offset, array.length - offset)", 471 "int index = 8", 472 "{" 473 " index = VarHandleUnitTestHelpers.alignedOffset_${var_type}(bb, index);" 474 " VarHandleUnitTestHelpers.setBytesAs_${var_type}(bb, index, ${initial_value}, ByteOrder.BIG_ENDIAN);" 475 "}" 476 ], 477 'MethodHandles.byteBufferViewVarHandle(${var_type}[].class, ByteOrder.BIG_ENDIAN)', 478 [ 479 'bb', 480 'index' 481 ], 482 'VarHandleUnitTestHelpers.getBytesAs_${var_type}(bb, index, ByteOrder.BIG_ENDIAN)', 483 may_throw_read_only = False) 484 485NARROW_HEAP_BYTE_BUFFER_BE_VIEW_VAR_HANDLE = VarHandleKind("NarrowHeapByteBufferViewBE", 486 VIEW_SUPPORTED_NARROW_TYPES, 487 [ 488 'java.lang.invoke.MethodHandles', 489 'java.lang.invoke.VarHandle', 490 'java.nio.ByteBuffer', 491 'java.nio.ByteOrder' 492 ], 493 [ 494 "byte[] array = VarHandleUnitTestHelpers.createFilledByteArray(47)", 495 "int offset = 8", 496 "ByteBuffer bb = ByteBuffer.wrap(array, offset, array.length - offset)", 497 "int index = 10", 498 "{" 499 " index = VarHandleUnitTestHelpers.alignedOffset_${var_type}(bb, index);" 500 " VarHandleUnitTestHelpers.setBytesAs_${var_type}(bb, index, ${initial_value}, ByteOrder.BIG_ENDIAN);" 501 "}" 502 ], 503 'MethodHandles.byteBufferViewVarHandle(${var_type}[].class, ByteOrder.BIG_ENDIAN)', 504 [ 505 'bb', 506 'index' 507 ], 508 'VarHandleUnitTestHelpers.getBytesAs_${var_type}(bb, index, ByteOrder.BIG_ENDIAN)', 509 may_throw_read_only = False) 510 511HEAP_BYTE_BUFFER_RO_LE_VIEW_VAR_HANDLE = VarHandleKind("HeapByteBufferReadOnlyViewLE", 512 VIEW_SUPPORTED_TYPES, 513 [ 514 'java.lang.invoke.MethodHandles', 515 'java.lang.invoke.VarHandle', 516 'java.nio.ByteBuffer', 517 'java.nio.ByteOrder', 518 'java.nio.ReadOnlyBufferException' 519 ], 520 [ 521 "byte[] array = VarHandleUnitTestHelpers.createFilledByteArray(43)", 522 "int index = 8", 523 "ByteBuffer bb", 524 "{" 525 " bb = ByteBuffer.wrap(array).asReadOnlyBuffer();" 526 " index = VarHandleUnitTestHelpers.alignedOffset_${var_type}(bb, index);" 527 " VarHandleUnitTestHelpers.setBytesAs_${var_type}(array, index, ${initial_value}, ByteOrder.LITTLE_ENDIAN);" 528 " bb = bb.asReadOnlyBuffer();" 529 "}" 530 ], 531 'MethodHandles.byteBufferViewVarHandle(${var_type}[].class, ByteOrder.LITTLE_ENDIAN)', 532 [ 533 'bb', 534 'index' 535 ], 536 'VarHandleUnitTestHelpers.getBytesAs_${var_type}(bb, index, ByteOrder.LITTLE_ENDIAN)', 537 may_throw_read_only = True) 538 539NARROW_HEAP_BYTE_BUFFER_RO_LE_VIEW_VAR_HANDLE = VarHandleKind("NarrowHeapByteBufferReadOnlyViewLE", 540 VIEW_SUPPORTED_NARROW_TYPES, 541 [ 542 'java.lang.invoke.MethodHandles', 543 'java.lang.invoke.VarHandle', 544 'java.nio.ByteBuffer', 545 'java.nio.ByteOrder', 546 'java.nio.ReadOnlyBufferException' 547 ], 548 [ 549 "byte[] array = VarHandleUnitTestHelpers.createFilledByteArray(43)", 550 "int index = 10", 551 "ByteBuffer bb", 552 "{" 553 " bb = ByteBuffer.wrap(array).asReadOnlyBuffer();" 554 " index = VarHandleUnitTestHelpers.alignedOffset_${var_type}(bb, index);" 555 " VarHandleUnitTestHelpers.setBytesAs_${var_type}(array, index, ${initial_value}, ByteOrder.LITTLE_ENDIAN);" 556 " bb = bb.asReadOnlyBuffer();" 557 "}" 558 ], 559 'MethodHandles.byteBufferViewVarHandle(${var_type}[].class, ByteOrder.LITTLE_ENDIAN)', 560 [ 561 'bb', 562 'index' 563 ], 564 'VarHandleUnitTestHelpers.getBytesAs_${var_type}(bb, index, ByteOrder.LITTLE_ENDIAN)', 565 may_throw_read_only = True) 566 567HEAP_BYTE_BUFFER_RO_BE_VIEW_VAR_HANDLE = VarHandleKind("HeapByteBufferReadOnlyViewBE", 568 VIEW_SUPPORTED_TYPES, 569 [ 570 'java.lang.invoke.MethodHandles', 571 'java.lang.invoke.VarHandle', 572 'java.nio.ByteBuffer', 573 'java.nio.ByteOrder', 574 'java.nio.ReadOnlyBufferException' 575 ], 576 [ 577 "byte[] array = VarHandleUnitTestHelpers.createFilledByteArray(29)", 578 "int index = 8", 579 "ByteBuffer bb", 580 "{" 581 " bb = ByteBuffer.wrap(array);" 582 " index = VarHandleUnitTestHelpers.alignedOffset_${var_type}(bb, index);" 583 " VarHandleUnitTestHelpers.setBytesAs_${var_type}(array, index, ${initial_value}, ByteOrder.BIG_ENDIAN);" 584 " bb = bb.asReadOnlyBuffer();" 585 "}" 586 ], 587 'MethodHandles.byteBufferViewVarHandle(${var_type}[].class, ByteOrder.BIG_ENDIAN)', 588 [ 589 'bb', 590 'index' 591 ], 592 'VarHandleUnitTestHelpers.getBytesAs_${var_type}(bb, index, ByteOrder.BIG_ENDIAN)', 593 may_throw_read_only = True) 594 595NARROW_HEAP_BYTE_BUFFER_RO_BE_VIEW_VAR_HANDLE = VarHandleKind("NarrowHeapByteBufferReadOnlyViewBE", 596 VIEW_SUPPORTED_NARROW_TYPES, 597 [ 598 'java.lang.invoke.MethodHandles', 599 'java.lang.invoke.VarHandle', 600 'java.nio.ByteBuffer', 601 'java.nio.ByteOrder', 602 'java.nio.ReadOnlyBufferException' 603 ], 604 [ 605 "byte[] array = VarHandleUnitTestHelpers.createFilledByteArray(29)", 606 "int index = 10", 607 "ByteBuffer bb", 608 "{" 609 " bb = ByteBuffer.wrap(array);" 610 " index = VarHandleUnitTestHelpers.alignedOffset_${var_type}(bb, index);" 611 " VarHandleUnitTestHelpers.setBytesAs_${var_type}(array, index, ${initial_value}, ByteOrder.BIG_ENDIAN);" 612 " bb = bb.asReadOnlyBuffer();" 613 "}" 614 ], 615 'MethodHandles.byteBufferViewVarHandle(${var_type}[].class, ByteOrder.BIG_ENDIAN)', 616 [ 617 'bb', 618 'index' 619 ], 620 'VarHandleUnitTestHelpers.getBytesAs_${var_type}(bb, index, ByteOrder.BIG_ENDIAN)', 621 may_throw_read_only = True) 622 623ALL_FIELD_VAR_HANDLE_KINDS = [ 624 FIELD_VAR_HANDLE, 625 FINAL_FIELD_VAR_HANDLE, 626 STATIC_FIELD_VAR_HANDLE, 627 STATIC_FINAL_FIELD_VAR_HANDLE 628] 629 630ALL_BYTE_VIEW_VAR_HANDLE_KINDS = [ 631 BYTE_ARRAY_LE_VIEW_VAR_HANDLE, 632 NARROW_BYTE_ARRAY_LE_VIEW_VAR_HANDLE, 633 BYTE_ARRAY_BE_VIEW_VAR_HANDLE, 634 NARROW_BYTE_ARRAY_BE_VIEW_VAR_HANDLE, 635 DIRECT_BYTE_BUFFER_LE_VIEW_VAR_HANDLE, 636 NARROW_DIRECT_BYTE_BUFFER_LE_VIEW_VAR_HANDLE, 637 DIRECT_BYTE_BUFFER_BE_VIEW_VAR_HANDLE, 638 NARROW_DIRECT_BYTE_BUFFER_BE_VIEW_VAR_HANDLE, 639 HEAP_BYTE_BUFFER_LE_VIEW_VAR_HANDLE, 640 NARROW_HEAP_BYTE_BUFFER_LE_VIEW_VAR_HANDLE, 641 HEAP_BYTE_BUFFER_BE_VIEW_VAR_HANDLE, 642 NARROW_HEAP_BYTE_BUFFER_BE_VIEW_VAR_HANDLE, 643 HEAP_BYTE_BUFFER_RO_LE_VIEW_VAR_HANDLE, 644 NARROW_HEAP_BYTE_BUFFER_RO_LE_VIEW_VAR_HANDLE, 645 HEAP_BYTE_BUFFER_RO_BE_VIEW_VAR_HANDLE, 646 NARROW_HEAP_BYTE_BUFFER_RO_BE_VIEW_VAR_HANDLE 647] 648 649ALL_VAR_HANDLE_KINDS = ALL_FIELD_VAR_HANDLE_KINDS + [ ARRAY_ELEMENT_VAR_HANDLE ] + ALL_BYTE_VIEW_VAR_HANDLE_KINDS 650 651class AccessModeForm(Enum): 652 GET = 0 653 SET = 1 654 STRONG_COMPARE_AND_SET = 2 655 WEAK_COMPARE_AND_SET = 3 656 COMPARE_AND_EXCHANGE = 4 657 GET_AND_SET = 5 658 GET_AND_UPDATE_BITWISE = 6 659 GET_AND_UPDATE_NUMERIC = 7 660 661class VarHandleAccessor: 662 def __init__(self, method_name): 663 self.method_name = method_name 664 self.access_mode = self.get_access_mode(method_name) 665 self.access_mode_form = self.get_access_mode_form(method_name) 666 667 def get_return_type(self, var_type): 668 if self.access_mode_form == AccessModeForm.SET: 669 return None 670 elif (self.access_mode_form == AccessModeForm.STRONG_COMPARE_AND_SET or 671 self.access_mode_form == AccessModeForm.WEAK_COMPARE_AND_SET): 672 return BOOLEAN_TYPE 673 else: 674 return var_type 675 676 def get_number_of_var_type_arguments(self): 677 if self.access_mode_form == AccessModeForm.GET: 678 return 0 679 elif (self.access_mode_form == AccessModeForm.SET or 680 self.access_mode_form == AccessModeForm.GET_AND_SET or 681 self.access_mode_form == AccessModeForm.GET_AND_UPDATE_BITWISE or 682 self.access_mode_form == AccessModeForm.GET_AND_UPDATE_NUMERIC): 683 return 1 684 elif (self.access_mode_form == AccessModeForm.STRONG_COMPARE_AND_SET or 685 self.access_mode_form == AccessModeForm.WEAK_COMPARE_AND_SET or 686 self.access_mode_form == AccessModeForm.COMPARE_AND_EXCHANGE): 687 return 2 688 else: 689 raise ValueError(self.access_mode_form) 690 691 def is_read_only(self): 692 return self.access_mode_form == AccessModeForm.GET 693 694 def get_java_bitwise_operator(self): 695 if "BitwiseAnd" in self.method_name: 696 return "&" 697 elif "BitwiseOr" in self.method_name: 698 return "|" 699 elif "BitwiseXor" in self.method_name: 700 return "^" 701 raise ValueError(self.method_name) 702 703 def get_java_numeric_operator(self): 704 if "Add" in self.method_name: 705 return "+" 706 raise ValueError(self.method_name) 707 708 @staticmethod 709 def get_access_mode(accessor_method): 710 """Converts an access method name to AccessMode value. For example, getAndSet becomes GET_AND_SET""" 711 return re.sub('([A-Z])', r'_\1', accessor_method).upper() 712 713 @staticmethod 714 def get_access_mode_form(accessor_method): 715 prefix_mode_list = [ 716 ('getAndAdd', AccessModeForm.GET_AND_UPDATE_NUMERIC), 717 ('getAndBitwise', AccessModeForm.GET_AND_UPDATE_BITWISE), 718 ('getAndSet', AccessModeForm.GET_AND_SET), 719 ('get', AccessModeForm.GET), 720 ('set', AccessModeForm.SET), 721 ('compareAndSet', AccessModeForm.STRONG_COMPARE_AND_SET), 722 ('weakCompareAndSet', AccessModeForm.WEAK_COMPARE_AND_SET), 723 ('compareAndExchange', AccessModeForm.COMPARE_AND_EXCHANGE)] 724 for prefix, mode in prefix_mode_list: 725 if accessor_method.startswith(prefix): 726 return mode 727 raise ValueError(accessor_method) 728 729VAR_HANDLE_ACCESSORS = [ 730 VarHandleAccessor('get'), 731 VarHandleAccessor('set'), 732 VarHandleAccessor('getVolatile'), 733 VarHandleAccessor('setVolatile'), 734 VarHandleAccessor('getAcquire'), 735 VarHandleAccessor('setRelease'), 736 VarHandleAccessor('getOpaque'), 737 VarHandleAccessor('setOpaque'), 738 VarHandleAccessor('compareAndSet'), 739 VarHandleAccessor('compareAndExchange'), 740 VarHandleAccessor('compareAndExchangeAcquire'), 741 VarHandleAccessor('compareAndExchangeRelease'), 742 VarHandleAccessor('weakCompareAndSetPlain'), 743 VarHandleAccessor('weakCompareAndSet'), 744 VarHandleAccessor('weakCompareAndSetAcquire'), 745 VarHandleAccessor('weakCompareAndSetRelease'), 746 VarHandleAccessor('getAndSet'), 747 VarHandleAccessor('getAndSetAcquire'), 748 VarHandleAccessor('getAndSetRelease'), 749 VarHandleAccessor('getAndAdd'), 750 VarHandleAccessor('getAndAddAcquire'), 751 VarHandleAccessor('getAndAddRelease'), 752 VarHandleAccessor('getAndBitwiseOr'), 753 VarHandleAccessor('getAndBitwiseOrRelease'), 754 VarHandleAccessor('getAndBitwiseOrAcquire'), 755 VarHandleAccessor('getAndBitwiseAnd'), 756 VarHandleAccessor('getAndBitwiseAndRelease'), 757 VarHandleAccessor('getAndBitwiseAndAcquire'), 758 VarHandleAccessor('getAndBitwiseXor'), 759 VarHandleAccessor('getAndBitwiseXorRelease'), 760 VarHandleAccessor('getAndBitwiseXorAcquire') 761] 762 763# Pseudo-RNG used for arbitrary decisions 764RANDOM = Random(0) 765 766BANNER = '// This file is generated by util-src/generate_java.py do not directly modify!' 767 768# List of generated test classes 769GENERATED_TEST_CLASSES = [] 770 771def java_file_for_class(class_name): 772 return class_name + ".java" 773 774def capitalize_first(word): 775 return word[0].upper() + word[1:] 776 777def indent_code(code): 778 """Applies rudimentary indentation to code""" 779 return code 780 781def build_template_dictionary(test_class, var_handle_kind, accessor, var_type): 782 initial_value = RANDOM.choice(var_type.examples) 783 updated_value = RANDOM.choice(list(filter(lambda v : v != initial_value, var_type.examples))) 784 coordinates = ", ".join(var_handle_kind.get_coordinates()) 785 if accessor.get_number_of_var_type_arguments() != 0 and coordinates != "": 786 coordinates += ", " 787 dictionary = { 788 'accessor_method' : accessor.method_name, 789 'access_mode' : accessor.access_mode, 790 'banner' : BANNER, 791 'coordinates' : coordinates, 792 'initial_value' : initial_value, 793 'test_class' : test_class, 794 'updated_value' : updated_value, 795 'var_type' : var_type, 796 } 797 dictionary['imports'] = ";\n".join(list(map(lambda x: "import " + x, var_handle_kind.get_imports()))) 798 dictionary['lookup'] = var_handle_kind.get_lookup(dictionary) 799 dictionary['field_declarations'] = ";\n".join(var_handle_kind.get_field_declarations(dictionary)) 800 dictionary['read_value'] = var_handle_kind.get_value(dictionary) 801 802 # For indexable types we need to check out-of-bounds access at negative index. 803 # We always generate the check, but comment it out for non-indexable types. 804 dictionary['coordinates_negative_index'] = coordinates.replace('index', '-16') 805 dictionary['indexable_only'] = "//" if not re.search('Array|ByteBuffer', var_handle_kind.name) else "" 806 807 return dictionary 808 809def emit_accessor_test(var_handle_kind, accessor, var_type, output_path): 810 test_class = var_handle_kind.get_name() + capitalize_first(accessor.method_name) + capitalize_first(var_type.name) 811 GENERATED_TEST_CLASSES.append(test_class) 812 src_file_path = output_path / java_file_for_class(test_class) 813 expansions = build_template_dictionary(test_class, var_handle_kind, accessor, var_type) 814 # Compute test operation 815 if accessor.access_mode_form == AccessModeForm.GET: 816 test_template = Template(""" 817 ${var_type} value = (${var_type}) vh.${accessor_method}(${coordinates}); 818 assertEquals(${initial_value}, value); 819 // Check for out of bounds access (for indexable types only). 820 ${indexable_only} try { 821 ${indexable_only} value = (${var_type}) vh.${accessor_method}(${coordinates_negative_index}); 822 ${indexable_only} failUnreachable(); 823 ${indexable_only} } catch (IndexOutOfBoundsException ex) {}""") 824 elif accessor.access_mode_form == AccessModeForm.SET: 825 test_template = Template(""" 826 vh.${accessor_method}(${coordinates}${updated_value}); 827 assertEquals(${updated_value}, ${read_value}); 828 // Check for out of bounds access (for indexable types only). 829 ${indexable_only} try { 830 ${indexable_only} vh.${accessor_method}(${coordinates_negative_index}${updated_value}); 831 ${indexable_only} failUnreachable(); 832 ${indexable_only} } catch (IndexOutOfBoundsException ex) {}""") 833 elif accessor.access_mode_form == AccessModeForm.STRONG_COMPARE_AND_SET: 834 test_template = Template(""" 835 assertEquals(${initial_value}, ${read_value}); 836 // Test an update that should succeed. 837 boolean applied = (boolean) vh.${accessor_method}(${coordinates}${initial_value}, ${updated_value}); 838 assertEquals(${updated_value}, ${read_value}); 839 assertTrue(applied); 840 // Test an update that should fail. 841 applied = (boolean) vh.${accessor_method}(${coordinates}${initial_value}, ${initial_value}); 842 assertFalse(applied); 843 assertEquals(${updated_value}, ${read_value}); 844 // Check for out of bounds access (for indexable types only). 845 ${indexable_only} try { 846 ${indexable_only} applied = (boolean) vh.${accessor_method}(${coordinates_negative_index}${updated_value}, ${updated_value}); 847 ${indexable_only} failUnreachable(); 848 ${indexable_only} } catch (IndexOutOfBoundsException ex) {}""") 849 elif accessor.access_mode_form == AccessModeForm.WEAK_COMPARE_AND_SET: 850 test_template = Template(""" 851 assertEquals(${initial_value}, ${read_value}); 852 // Test an update that should succeed. 853 int attempts = 10000; 854 boolean applied; 855 do { 856 applied = (boolean) vh.${accessor_method}(${coordinates}${initial_value}, ${updated_value}); 857 } while (applied == false && attempts-- > 0); 858 assertEquals(${updated_value}, ${read_value}); 859 assertTrue(attempts > 0); 860 // Test an update that should fail. 861 applied = (boolean) vh.${accessor_method}(${coordinates}${initial_value}, ${initial_value}); 862 assertFalse(applied); 863 assertEquals(${updated_value}, ${read_value}); 864 // Check for out of bounds access (for indexable types only). 865 ${indexable_only} try { 866 ${indexable_only} applied = (boolean) vh.${accessor_method}(${coordinates_negative_index}${updated_value}, ${updated_value}); 867 ${indexable_only} failUnreachable(); 868 ${indexable_only} } catch (IndexOutOfBoundsException ex) {}""") 869 elif accessor.access_mode_form == AccessModeForm.COMPARE_AND_EXCHANGE: 870 test_template = Template(""" 871 // This update should succeed. 872 ${var_type} witness_value = (${var_type}) vh.${accessor_method}(${coordinates}${initial_value}, ${updated_value}); 873 assertEquals(${initial_value}, witness_value); 874 assertEquals(${updated_value}, ${read_value}); 875 // This update should fail. 876 witness_value = (${var_type}) vh.${accessor_method}(${coordinates}${initial_value}, ${initial_value}); 877 assertEquals(${updated_value}, witness_value); 878 assertEquals(${updated_value}, ${read_value}); 879 // Check for out of bounds access (for indexable types only). 880 ${indexable_only} try { 881 ${indexable_only} witness_value = (${var_type}) vh.${accessor_method}(${coordinates_negative_index}${updated_value}, ${updated_value}); 882 ${indexable_only} failUnreachable(); 883 ${indexable_only} } catch (IndexOutOfBoundsException ex) {}""") 884 elif accessor.access_mode_form == AccessModeForm.GET_AND_SET: 885 test_template = Template(""" 886 ${var_type} old_value = (${var_type}) vh.${accessor_method}(${coordinates}${updated_value}); 887 assertEquals(${initial_value}, old_value); 888 assertEquals(${updated_value}, ${read_value}); 889 // Check for out of bounds access (for indexable types only). 890 ${indexable_only} try { 891 ${indexable_only} old_value = (${var_type}) vh.${accessor_method}(${coordinates_negative_index}${updated_value}); 892 ${indexable_only} failUnreachable(); 893 ${indexable_only} } catch (IndexOutOfBoundsException ex) {}""") 894 elif accessor.access_mode_form == AccessModeForm.GET_AND_UPDATE_BITWISE: 895 if var_type.supports_bitwise == True: 896 expansions['binop'] = accessor.get_java_bitwise_operator() 897 test_template = Template(""" 898 ${var_type} old_value = (${var_type}) vh.${accessor_method}(${coordinates}${updated_value}); 899 assertEquals(${initial_value}, old_value); 900 assertEquals(${initial_value} ${binop} ${updated_value}, ${read_value}); 901 // Check for out of bounds access (for indexable types only). 902 ${indexable_only} try { 903 ${indexable_only} old_value = (${var_type}) vh.${accessor_method}(${coordinates_negative_index}${updated_value}); 904 ${indexable_only} failUnreachable(); 905 ${indexable_only} } catch (IndexOutOfBoundsException ex) {}""") 906 else: 907 test_template = Template(""" 908 vh.${accessor_method}(${coordinates}${initial_value}, ${updated_value}); 909 failUnreachable(); 910 // Check for out of bounds access (for indexable types only). 911 ${indexable_only} try { 912 ${indexable_only} vh.${accessor_method}(${coordinates_negative_index}${updated_value}, ${updated_value}); 913 ${indexable_only} failUnreachable(); 914 ${indexable_only} } catch (IndexOutOfBoundsException ex) {}""") 915 elif accessor.access_mode_form == AccessModeForm.GET_AND_UPDATE_NUMERIC: 916 if var_type.supports_numeric == True: 917 expansions['binop'] = accessor.get_java_numeric_operator() 918 test_template = Template(""" 919 ${var_type} unchanged = (${var_type}) vh.${accessor_method}(${coordinates}(${var_type}) 0); 920 assertEquals(${initial_value}, unchanged); 921 ${var_type} old_value = (${var_type}) vh.${accessor_method}(${coordinates}${updated_value}); 922 assertEquals(${initial_value}, old_value); 923 ${var_type} expected_value = (${var_type}) (${initial_value} ${binop} ${updated_value}); 924 assertEquals(expected_value, ${read_value}); 925 // Check for out of bounds access (for indexable types only). 926 ${indexable_only} try { 927 ${indexable_only} old_value = (${var_type}) vh.${accessor_method}(${coordinates_negative_index}${updated_value}); 928 ${indexable_only} failUnreachable(); 929 ${indexable_only} } catch (IndexOutOfBoundsException ex) {}""") 930 else: 931 test_template = Template(""" 932 vh.${accessor_method}(${coordinates}${initial_value}, ${updated_value}); 933 failUnreachable(); 934 // Check for out of bounds access (for indexable types only). 935 ${indexable_only} try { 936 ${indexable_only} vh.${accessor_method}(${coordinates_negative_index}${updated_value}, ${updated_value}); 937 ${indexable_only} failUnreachable(); 938 ${indexable_only} } catch (IndexOutOfBoundsException ex) {}""") 939 else: 940 raise ValueError(accessor.access_mode_form) 941 942 if var_handle_kind.may_throw_read_only and not accessor.is_read_only(): 943 # ByteBufferViews can be read-only and dynamically raise ReadOnlyBufferException. 944 expansions['try_statement'] = "try {" 945 expansions['catch_statement'] = "failUnreachable();\n} catch (ReadOnlyBufferException ex) {}" 946 else: 947 expansions['try_statement'] = "" 948 expansions['catch_statement'] = "" 949 950 expansions['test_body'] = test_template.safe_substitute(expansions) 951 952 s = Template("""${banner} 953 954${imports}; 955 956class ${test_class} extends VarHandleUnitTest { 957 ${field_declarations}; 958 static final VarHandle vh; 959 static { 960 try { 961 vh = ${lookup}; 962 } catch (Exception e) { 963 throw new RuntimeException("Unexpected initialization exception", e); 964 } 965 } 966 967 @Override 968 public void doTest() throws Exception { 969 if (!vh.isAccessModeSupported(VarHandle.AccessMode.${access_mode})) { 970 try { 971 ${test_body} 972 failUnreachable(); 973 } catch (UnsupportedOperationException ex) {} 974 } else { 975 ${try_statement} 976 ${test_body} 977 ${catch_statement} 978 } 979 } 980 981 public static void main(String[] args) { 982 new ${test_class}().run(); 983 } 984} 985""").safe_substitute(expansions) 986 with src_file_path.open("w") as src_file: 987 print(s, file=src_file) 988 989def emit_value_type_accessor_tests(output_path): 990 for var_handle_kind in ALL_VAR_HANDLE_KINDS: 991 for accessor in VAR_HANDLE_ACCESSORS: 992 for var_type in var_handle_kind.get_supported_types(): 993 emit_accessor_test(var_handle_kind, accessor, var_type, output_path) 994 995def emit_reference_accessor_tests(output_path): 996 ref_type = JavaType("Widget", [ "Widget.ONE", "Widget.TWO", "null" ]) 997 for var_handle_kind in ALL_VAR_HANDLE_KINDS: 998 if var_handle_kind.is_view(): 999 # Views as reference type arrays are not supported. They 1000 # fail instantiation. This is tested in 710-varhandle-creation. 1001 continue 1002 for accessor in VAR_HANDLE_ACCESSORS: 1003 emit_accessor_test(var_handle_kind, accessor, ref_type, output_path) 1004 1005def emit_interface_accessor_tests(output_path): 1006 ref_type = JavaType("WidgetInterface", [ "Widget.ONE", "Widget.TWO", "null" ]) 1007 for var_handle_kind in ALL_VAR_HANDLE_KINDS: 1008 if var_handle_kind.is_view(): 1009 # Views as reference type arrays are not supported. They 1010 # fail instantiation. This is tested in 710-varhandle-creation. 1011 continue 1012 for accessor in VAR_HANDLE_ACCESSORS: 1013 emit_accessor_test(var_handle_kind, accessor, ref_type, output_path) 1014 1015def emit_boxing_value_type_accessor_test(accessor, var_type, output_path): 1016 test_class = "Boxing" + capitalize_first(accessor.method_name) + capitalize_first(var_type.name) 1017 GENERATED_TEST_CLASSES.append(test_class) 1018 src_file_path = output_path / java_file_for_class(test_class) 1019 var_handle_kind = FIELD_VAR_HANDLE 1020 expansions = build_template_dictionary(test_class, var_handle_kind, accessor, var_type) 1021 template = Template(""" 1022${banner} 1023 1024${imports}; 1025import java.lang.invoke.WrongMethodTypeException; 1026 1027public class ${test_class} extends VarHandleUnitTest { 1028 ${field_declarations}; 1029 private static final VarHandle vh; 1030 static { 1031 try { 1032 vh = ${lookup}; 1033 } catch (Exception e) { 1034 throw new RuntimeException("Unexpected initialization exception", e); 1035 } 1036 } 1037 1038 @Override 1039 public void doTest() throws Exception { 1040 ${body} 1041 } 1042 1043 public static void main(String[] args) { 1044 new ${test_class}().run(); 1045 } 1046} 1047""") 1048 with io.StringIO() as body_text: 1049 compatible_types = types_that_widen_to(var_type) 1050 incompatible_types = { RANDOM.choice(list(VALUE_TYPES - compatible_types)) } 1051 test_types = compatible_types | incompatible_types 1052 for value_type in test_types: 1053 print("try {", file=body_text) 1054 return_type = accessor.get_return_type(var_type) 1055 if return_type: 1056 print("{0} result = ({0}) ".format(return_type), end="", file=body_text) 1057 print("vh.{0}(this".format(accessor.method_name), end="", file=body_text) 1058 num_args = accessor.get_number_of_var_type_arguments() 1059 for i in range(0, num_args): 1060 print(", SampleValues.get_{0}({1})".format(value_type.boxed_type, i), end="", file=body_text) 1061 print(");", file=body_text) 1062 if value_type in compatible_types: 1063 print(" assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.{0}));".format(accessor.access_mode), 1064 file=body_text) 1065 else: 1066 print("failUnreachable();", file=body_text) 1067 print("} catch (WrongMethodTypeException e) {", file=body_text) 1068 print("} catch (UnsupportedOperationException e) {", file=body_text) 1069 print(" assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.{0}));".format(accessor.access_mode), 1070 file=body_text) 1071 print("}", file=body_text) 1072 expansions['body'] = body_text.getvalue(); 1073 with src_file_path.open("w") as src_file: 1074 print(template.safe_substitute(expansions), file=src_file) 1075 1076def emit_boxing_return_value_type_test(accessor, var_type, output_path): 1077 test_class = "BoxingReturn" + capitalize_first(accessor.method_name) + capitalize_first(var_type.name) 1078 GENERATED_TEST_CLASSES.append(test_class) 1079 src_file_path = output_path / java_file_for_class(test_class) 1080 var_handle_kind = FIELD_VAR_HANDLE 1081 expansions = build_template_dictionary(test_class, var_handle_kind, accessor, var_type) 1082 template = Template(""" 1083${banner} 1084 1085${imports}; 1086import java.lang.invoke.WrongMethodTypeException; 1087 1088public class ${test_class} extends VarHandleUnitTest { 1089 ${field_declarations}; 1090 private static final VarHandle vh; 1091 static { 1092 try { 1093 vh = ${lookup}; 1094 } catch (Exception e) { 1095 throw new RuntimeException("Unexpected initialization exception", e); 1096 } 1097 } 1098 1099 @Override 1100 public void doTest() throws Exception { 1101 ${body} 1102 } 1103 1104 public static void main(String[] args) { 1105 new ${test_class}().run(); 1106 } 1107} 1108""") 1109 with io.StringIO() as body_text: 1110 return_type = accessor.get_return_type(var_type) 1111 compatible_types = { return_type } 1112 incompatible_types = { RANDOM.choice(list(VALUE_TYPES - compatible_types)) } 1113 test_types = compatible_types | incompatible_types 1114 for value_type in test_types: 1115 print("try {", file=body_text) 1116 print("{0} result = ({0}) ".format(value_type.boxed_type), end="", file=body_text) 1117 print("vh.{0}(this".format(accessor.method_name), end="", file=body_text) 1118 num_args = accessor.get_number_of_var_type_arguments() 1119 for i in range(0, num_args): 1120 print(", {0})".format(var_type.examples[i]), end="", file=body_text) 1121 print(");", file=body_text) 1122 if value_type in compatible_types: 1123 print(" assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.{0}));".format(accessor.access_mode), 1124 file=body_text) 1125 else: 1126 print("failUnreachable();", file=body_text) 1127 print("} catch (WrongMethodTypeException e) {", file=body_text) 1128 print("} catch (UnsupportedOperationException e) {", file=body_text) 1129 print(" assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.{0}));".format(accessor.access_mode), 1130 file=body_text) 1131 print("}", file=body_text) 1132 expansions['body'] = body_text.getvalue(); 1133 with src_file_path.open("w") as src_file: 1134 print(template.safe_substitute(expansions), file=src_file) 1135 1136def emit_boxing_value_type_accessor_tests(output_path): 1137 for var_type in VALUE_TYPES: 1138 for accessor in VAR_HANDLE_ACCESSORS: 1139 if accessor.get_number_of_var_type_arguments() > 0: 1140 emit_boxing_value_type_accessor_test(accessor, var_type, output_path) 1141 else: 1142 emit_boxing_return_value_type_test(accessor, var_type, output_path) 1143 1144def emit_main(output_path, manual_test_classes): 1145 main_file_path = output_path / "Main.java" 1146 all_test_classes = GENERATED_TEST_CLASSES + manual_test_classes 1147 with main_file_path.open("w") as main_file: 1148 print("// " + BANNER, file=main_file) 1149 print(""" 1150public class Main { 1151 public static void main(String[] args) { 1152""", file=main_file) 1153 for cls in all_test_classes: 1154 print(" " + cls + ".main(args);", file=main_file) 1155 print(" VarHandleUnitTest.DEFAULT_COLLECTOR.printSummary();", file=main_file) 1156 print(" System.exit(VarHandleUnitTest.DEFAULT_COLLECTOR.failuresOccurred() ? 1 : 0);", file=main_file) 1157 print(" }\n}", file=main_file) 1158 1159def main(argv): 1160 final_java_dir = Path(argv[1]) 1161 if not final_java_dir.exists() or not final_java_dir.is_dir(): 1162 print("{} is not a valid java dir".format(final_java_dir), file=sys.stderr) 1163 sys.exit(1) 1164 emit_value_type_accessor_tests(final_java_dir) 1165 emit_reference_accessor_tests(final_java_dir) 1166 emit_interface_accessor_tests(final_java_dir) 1167 emit_boxing_value_type_accessor_tests(final_java_dir) 1168 emit_main(final_java_dir, argv[2:]) 1169 1170if __name__ == '__main__': 1171 main(sys.argv) 1172