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