1 /* 2 * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.lang.invoke; 27 28 import static java.lang.invoke.MethodHandleStatics.UNSAFE; 29 30 import java.lang.reflect.Method; 31 import java.util.Arrays; 32 import java.util.Collections; 33 import java.util.HashMap; 34 import java.util.List; 35 import java.util.Map; 36 import java.util.Objects; 37 38 import jdk.internal.vm.annotation.ForceInline; 39 40 // Android-changed: currently only 4 methods and the Holder class are needed, hence not importing 41 // entire file. 42 /** 43 * The flavor of method handle which implements a constant reference 44 * to a class member. 45 * @author jrose 46 */ 47 class DirectMethodHandle { 48 49 @ForceInline 50 /*non-public*/ fieldOffset(Object accessorObj)51 static long fieldOffset(Object accessorObj) { 52 // Note: We return a long because that is what Unsafe.getObject likes. 53 // We store a plain int because it is more compact. 54 // Android-changed: there is only MethodHandleImpl. 55 // return ((Accessor)accessorObj).fieldOffset; 56 return ((MethodHandleImpl) accessorObj).field.getOffset(); 57 } 58 59 @ForceInline 60 /*non-public*/ checkBase(Object obj)61 static Object checkBase(Object obj) { 62 // Note that the object's class has already been verified, 63 // since the parameter type of the Accessor method handle 64 // is either member.getDeclaringClass or a subclass. 65 // This was verified in DirectMethodHandle.make. 66 // Therefore, the only remaining check is for null. 67 // Since this check is *not* guaranteed by Unsafe.getInt 68 // and its siblings, we need to make an explicit one here. 69 return Objects.requireNonNull(obj); 70 } 71 72 73 @ForceInline 74 /*non-public*/ staticBase(Object accessorObj)75 static Object staticBase(Object accessorObj) { 76 // Android-changed: there is only MethodHandleImpl. 77 // return ((StaticAccessor)accessorObj).staticBase; 78 return ((MethodHandleImpl) accessorObj).field.getDeclaringClass(); 79 } 80 81 @ForceInline 82 /*non-public*/ staticOffset(Object accessorObj)83 static long staticOffset(Object accessorObj) { 84 // Android-changed: there is only MethodHandleImpl. 85 // return ((StaticAccessor)accessorObj).staticOffset; 86 return ((MethodHandleImpl) accessorObj).field.getOffset(); 87 } 88 89 // BEGIN Android-added: different mechanism to tie actual implementation to a MethodHandle. getImplementation(String name, List<Class<?>> parameters)90 static Method getImplementation(String name, List<Class<?>> parameters) { 91 return ACCESSOR_IMPLEMENTATIONS.get(new MethodKey(name, parameters)); 92 } 93 94 private static final Map<MethodKey, Method> ACCESSOR_IMPLEMENTATIONS; 95 96 static { 97 UNSAFE.ensureClassInitialized(Holder.class); 98 99 // 4 access kinds, 9 basic types and fields can be volatile or non-volatile. 100 HashMap<MethodKey, Method> accessorMethods = HashMap.newHashMap(4 * 9 * 2); 101 102 for (Method m : Holder.class.getDeclaredMethods()) { accessorMethods.put( new MethodKey(m.getName(), Arrays.asList(m.getParameterTypes())), m)103 accessorMethods.put( 104 new MethodKey(m.getName(), Arrays.asList(m.getParameterTypes())), m); 105 } 106 107 ACCESSOR_IMPLEMENTATIONS = Collections.unmodifiableMap(accessorMethods); 108 } 109 110 private static final class MethodKey { 111 private final String name; 112 private final List<Class<?>> arguments; 113 MethodKey(String name, List<Class<?>> arguments)114 MethodKey(String name, List<Class<?>> arguments) { 115 this.name = Objects.requireNonNull(name); 116 this.arguments = Objects.requireNonNull(arguments); 117 } 118 119 @Override hashCode()120 public int hashCode() { 121 return 31 * name.hashCode() + arguments.hashCode(); 122 } 123 124 @Override equals(Object obj)125 public boolean equals(Object obj) { 126 if (obj instanceof MethodKey methodKey) { 127 return name.equals(methodKey.name) && arguments.equals(methodKey.arguments); 128 } 129 130 return false; 131 } 132 } 133 // END Android-added: different mechanism to tie actual implementation to a MethodHandle. 134 135 // Android-changed: upstream inserts implementation at the link time (straight to bytecode, w/o 136 // compilation). 137 // Do not change this class manually: check AccessorMethodHandlesGenerator. 138 /* Placeholder class for DirectMethodHandles generated ahead of time */ 139 static final class Holder { putBoolean(Object base, boolean value, MethodHandleImpl mh)140 static void putBoolean(Object base, boolean value, MethodHandleImpl mh) { 141 checkBase(base); 142 long offset = fieldOffset(mh); 143 UNSAFE.putBoolean(base, offset, value); 144 } 145 putBooleanVolatile(Object base, boolean value, MethodHandleImpl mh)146 static void putBooleanVolatile(Object base, boolean value, MethodHandleImpl mh) { 147 checkBase(base); 148 long offset = fieldOffset(mh); 149 UNSAFE.putBooleanVolatile(base, offset, value); 150 } 151 putByte(Object base, byte value, MethodHandleImpl mh)152 static void putByte(Object base, byte value, MethodHandleImpl mh) { 153 checkBase(base); 154 long offset = fieldOffset(mh); 155 UNSAFE.putByte(base, offset, value); 156 } 157 putByteVolatile(Object base, byte value, MethodHandleImpl mh)158 static void putByteVolatile(Object base, byte value, MethodHandleImpl mh) { 159 checkBase(base); 160 long offset = fieldOffset(mh); 161 UNSAFE.putByteVolatile(base, offset, value); 162 } 163 putChar(Object base, char value, MethodHandleImpl mh)164 static void putChar(Object base, char value, MethodHandleImpl mh) { 165 checkBase(base); 166 long offset = fieldOffset(mh); 167 UNSAFE.putChar(base, offset, value); 168 } 169 putCharVolatile(Object base, char value, MethodHandleImpl mh)170 static void putCharVolatile(Object base, char value, MethodHandleImpl mh) { 171 checkBase(base); 172 long offset = fieldOffset(mh); 173 UNSAFE.putCharVolatile(base, offset, value); 174 } 175 putShort(Object base, short value, MethodHandleImpl mh)176 static void putShort(Object base, short value, MethodHandleImpl mh) { 177 checkBase(base); 178 long offset = fieldOffset(mh); 179 UNSAFE.putShort(base, offset, value); 180 } 181 putShortVolatile(Object base, short value, MethodHandleImpl mh)182 static void putShortVolatile(Object base, short value, MethodHandleImpl mh) { 183 checkBase(base); 184 long offset = fieldOffset(mh); 185 UNSAFE.putShortVolatile(base, offset, value); 186 } 187 putInt(Object base, int value, MethodHandleImpl mh)188 static void putInt(Object base, int value, MethodHandleImpl mh) { 189 checkBase(base); 190 long offset = fieldOffset(mh); 191 UNSAFE.putInt(base, offset, value); 192 } 193 putIntVolatile(Object base, int value, MethodHandleImpl mh)194 static void putIntVolatile(Object base, int value, MethodHandleImpl mh) { 195 checkBase(base); 196 long offset = fieldOffset(mh); 197 UNSAFE.putIntVolatile(base, offset, value); 198 } 199 putLong(Object base, long value, MethodHandleImpl mh)200 static void putLong(Object base, long value, MethodHandleImpl mh) { 201 checkBase(base); 202 long offset = fieldOffset(mh); 203 UNSAFE.putLong(base, offset, value); 204 } 205 putLongVolatile(Object base, long value, MethodHandleImpl mh)206 static void putLongVolatile(Object base, long value, MethodHandleImpl mh) { 207 checkBase(base); 208 long offset = fieldOffset(mh); 209 UNSAFE.putLongVolatile(base, offset, value); 210 } 211 putDouble(Object base, double value, MethodHandleImpl mh)212 static void putDouble(Object base, double value, MethodHandleImpl mh) { 213 checkBase(base); 214 long offset = fieldOffset(mh); 215 UNSAFE.putDouble(base, offset, value); 216 } 217 putDoubleVolatile(Object base, double value, MethodHandleImpl mh)218 static void putDoubleVolatile(Object base, double value, MethodHandleImpl mh) { 219 checkBase(base); 220 long offset = fieldOffset(mh); 221 UNSAFE.putDoubleVolatile(base, offset, value); 222 } 223 putFloat(Object base, float value, MethodHandleImpl mh)224 static void putFloat(Object base, float value, MethodHandleImpl mh) { 225 checkBase(base); 226 long offset = fieldOffset(mh); 227 UNSAFE.putFloat(base, offset, value); 228 } 229 putFloatVolatile(Object base, float value, MethodHandleImpl mh)230 static void putFloatVolatile(Object base, float value, MethodHandleImpl mh) { 231 checkBase(base); 232 long offset = fieldOffset(mh); 233 UNSAFE.putFloatVolatile(base, offset, value); 234 } 235 putReference(Object base, Object value, MethodHandleImpl mh)236 static void putReference(Object base, Object value, MethodHandleImpl mh) { 237 checkBase(base); 238 long offset = fieldOffset(mh); 239 UNSAFE.putReference(base, offset, value); 240 } 241 putReferenceVolatile(Object base, Object value, MethodHandleImpl mh)242 static void putReferenceVolatile(Object base, Object value, MethodHandleImpl mh) { 243 checkBase(base); 244 long offset = fieldOffset(mh); 245 UNSAFE.putReferenceVolatile(base, offset, value); 246 } 247 getBoolean(Object base, MethodHandleImpl mh)248 static boolean getBoolean(Object base, MethodHandleImpl mh) { 249 checkBase(base); 250 long offset = fieldOffset(mh); 251 return UNSAFE.getBoolean(base, offset); 252 } 253 getBooleanVolatile(Object base, MethodHandleImpl mh)254 static boolean getBooleanVolatile(Object base, MethodHandleImpl mh) { 255 checkBase(base); 256 long offset = fieldOffset(mh); 257 return UNSAFE.getBooleanVolatile(base, offset); 258 } 259 getByte(Object base, MethodHandleImpl mh)260 static byte getByte(Object base, MethodHandleImpl mh) { 261 checkBase(base); 262 long offset = fieldOffset(mh); 263 return UNSAFE.getByte(base, offset); 264 } 265 getByteVolatile(Object base, MethodHandleImpl mh)266 static byte getByteVolatile(Object base, MethodHandleImpl mh) { 267 checkBase(base); 268 long offset = fieldOffset(mh); 269 return UNSAFE.getByteVolatile(base, offset); 270 } 271 getChar(Object base, MethodHandleImpl mh)272 static char getChar(Object base, MethodHandleImpl mh) { 273 checkBase(base); 274 long offset = fieldOffset(mh); 275 return UNSAFE.getChar(base, offset); 276 } 277 getCharVolatile(Object base, MethodHandleImpl mh)278 static char getCharVolatile(Object base, MethodHandleImpl mh) { 279 checkBase(base); 280 long offset = fieldOffset(mh); 281 return UNSAFE.getCharVolatile(base, offset); 282 } 283 getShort(Object base, MethodHandleImpl mh)284 static short getShort(Object base, MethodHandleImpl mh) { 285 checkBase(base); 286 long offset = fieldOffset(mh); 287 return UNSAFE.getShort(base, offset); 288 } 289 getShortVolatile(Object base, MethodHandleImpl mh)290 static short getShortVolatile(Object base, MethodHandleImpl mh) { 291 checkBase(base); 292 long offset = fieldOffset(mh); 293 return UNSAFE.getShortVolatile(base, offset); 294 } 295 getInt(Object base, MethodHandleImpl mh)296 static int getInt(Object base, MethodHandleImpl mh) { 297 checkBase(base); 298 long offset = fieldOffset(mh); 299 return UNSAFE.getInt(base, offset); 300 } 301 getIntVolatile(Object base, MethodHandleImpl mh)302 static int getIntVolatile(Object base, MethodHandleImpl mh) { 303 checkBase(base); 304 long offset = fieldOffset(mh); 305 return UNSAFE.getIntVolatile(base, offset); 306 } 307 getLong(Object base, MethodHandleImpl mh)308 static long getLong(Object base, MethodHandleImpl mh) { 309 checkBase(base); 310 long offset = fieldOffset(mh); 311 return UNSAFE.getLong(base, offset); 312 } 313 getLongVolatile(Object base, MethodHandleImpl mh)314 static long getLongVolatile(Object base, MethodHandleImpl mh) { 315 checkBase(base); 316 long offset = fieldOffset(mh); 317 return UNSAFE.getLongVolatile(base, offset); 318 } 319 getDouble(Object base, MethodHandleImpl mh)320 static double getDouble(Object base, MethodHandleImpl mh) { 321 checkBase(base); 322 long offset = fieldOffset(mh); 323 return UNSAFE.getDouble(base, offset); 324 } 325 getDoubleVolatile(Object base, MethodHandleImpl mh)326 static double getDoubleVolatile(Object base, MethodHandleImpl mh) { 327 checkBase(base); 328 long offset = fieldOffset(mh); 329 return UNSAFE.getDoubleVolatile(base, offset); 330 } 331 getFloat(Object base, MethodHandleImpl mh)332 static float getFloat(Object base, MethodHandleImpl mh) { 333 checkBase(base); 334 long offset = fieldOffset(mh); 335 return UNSAFE.getFloat(base, offset); 336 } 337 getFloatVolatile(Object base, MethodHandleImpl mh)338 static float getFloatVolatile(Object base, MethodHandleImpl mh) { 339 checkBase(base); 340 long offset = fieldOffset(mh); 341 return UNSAFE.getFloatVolatile(base, offset); 342 } 343 getReference(Object base, MethodHandleImpl mh)344 static Object getReference(Object base, MethodHandleImpl mh) { 345 checkBase(base); 346 long offset = fieldOffset(mh); 347 return UNSAFE.getReference(base, offset); 348 } 349 getReferenceVolatile(Object base, MethodHandleImpl mh)350 static Object getReferenceVolatile(Object base, MethodHandleImpl mh) { 351 checkBase(base); 352 long offset = fieldOffset(mh); 353 return UNSAFE.getReferenceVolatile(base, offset); 354 } 355 putBoolean(boolean value, MethodHandleImpl mh)356 static void putBoolean(boolean value, MethodHandleImpl mh) { 357 Object base = staticBase(mh); 358 long offset = staticOffset(mh); 359 UNSAFE.putBoolean(base, offset, value); 360 } 361 putBooleanVolatile(boolean value, MethodHandleImpl mh)362 static void putBooleanVolatile(boolean value, MethodHandleImpl mh) { 363 Object base = staticBase(mh); 364 long offset = staticOffset(mh); 365 UNSAFE.putBooleanVolatile(base, offset, value); 366 } 367 putByte(byte value, MethodHandleImpl mh)368 static void putByte(byte value, MethodHandleImpl mh) { 369 Object base = staticBase(mh); 370 long offset = staticOffset(mh); 371 UNSAFE.putByte(base, offset, value); 372 } 373 putByteVolatile(byte value, MethodHandleImpl mh)374 static void putByteVolatile(byte value, MethodHandleImpl mh) { 375 Object base = staticBase(mh); 376 long offset = staticOffset(mh); 377 UNSAFE.putByteVolatile(base, offset, value); 378 } 379 putChar(char value, MethodHandleImpl mh)380 static void putChar(char value, MethodHandleImpl mh) { 381 Object base = staticBase(mh); 382 long offset = staticOffset(mh); 383 UNSAFE.putChar(base, offset, value); 384 } 385 putCharVolatile(char value, MethodHandleImpl mh)386 static void putCharVolatile(char value, MethodHandleImpl mh) { 387 Object base = staticBase(mh); 388 long offset = staticOffset(mh); 389 UNSAFE.putCharVolatile(base, offset, value); 390 } 391 putShort(short value, MethodHandleImpl mh)392 static void putShort(short value, MethodHandleImpl mh) { 393 Object base = staticBase(mh); 394 long offset = staticOffset(mh); 395 UNSAFE.putShort(base, offset, value); 396 } 397 putShortVolatile(short value, MethodHandleImpl mh)398 static void putShortVolatile(short value, MethodHandleImpl mh) { 399 Object base = staticBase(mh); 400 long offset = staticOffset(mh); 401 UNSAFE.putShortVolatile(base, offset, value); 402 } 403 putInt(int value, MethodHandleImpl mh)404 static void putInt(int value, MethodHandleImpl mh) { 405 Object base = staticBase(mh); 406 long offset = staticOffset(mh); 407 UNSAFE.putInt(base, offset, value); 408 } 409 putIntVolatile(int value, MethodHandleImpl mh)410 static void putIntVolatile(int value, MethodHandleImpl mh) { 411 Object base = staticBase(mh); 412 long offset = staticOffset(mh); 413 UNSAFE.putIntVolatile(base, offset, value); 414 } 415 putLong(long value, MethodHandleImpl mh)416 static void putLong(long value, MethodHandleImpl mh) { 417 Object base = staticBase(mh); 418 long offset = staticOffset(mh); 419 UNSAFE.putLong(base, offset, value); 420 } 421 putLongVolatile(long value, MethodHandleImpl mh)422 static void putLongVolatile(long value, MethodHandleImpl mh) { 423 Object base = staticBase(mh); 424 long offset = staticOffset(mh); 425 UNSAFE.putLongVolatile(base, offset, value); 426 } 427 putDouble(double value, MethodHandleImpl mh)428 static void putDouble(double value, MethodHandleImpl mh) { 429 Object base = staticBase(mh); 430 long offset = staticOffset(mh); 431 UNSAFE.putDouble(base, offset, value); 432 } 433 putDoubleVolatile(double value, MethodHandleImpl mh)434 static void putDoubleVolatile(double value, MethodHandleImpl mh) { 435 Object base = staticBase(mh); 436 long offset = staticOffset(mh); 437 UNSAFE.putDoubleVolatile(base, offset, value); 438 } 439 putFloat(float value, MethodHandleImpl mh)440 static void putFloat(float value, MethodHandleImpl mh) { 441 Object base = staticBase(mh); 442 long offset = staticOffset(mh); 443 UNSAFE.putFloat(base, offset, value); 444 } 445 putFloatVolatile(float value, MethodHandleImpl mh)446 static void putFloatVolatile(float value, MethodHandleImpl mh) { 447 Object base = staticBase(mh); 448 long offset = staticOffset(mh); 449 UNSAFE.putFloatVolatile(base, offset, value); 450 } 451 putReference(Object value, MethodHandleImpl mh)452 static void putReference(Object value, MethodHandleImpl mh) { 453 Object base = staticBase(mh); 454 long offset = staticOffset(mh); 455 UNSAFE.putReference(base, offset, value); 456 } 457 putReferenceVolatile(Object value, MethodHandleImpl mh)458 static void putReferenceVolatile(Object value, MethodHandleImpl mh) { 459 Object base = staticBase(mh); 460 long offset = staticOffset(mh); 461 UNSAFE.putReferenceVolatile(base, offset, value); 462 } 463 getBoolean(MethodHandleImpl mh)464 static boolean getBoolean(MethodHandleImpl mh) { 465 Object base = staticBase(mh); 466 long offset = staticOffset(mh); 467 return UNSAFE.getBoolean(base, offset); 468 } 469 getBooleanVolatile(MethodHandleImpl mh)470 static boolean getBooleanVolatile(MethodHandleImpl mh) { 471 Object base = staticBase(mh); 472 long offset = staticOffset(mh); 473 return UNSAFE.getBooleanVolatile(base, offset); 474 } 475 getByte(MethodHandleImpl mh)476 static byte getByte(MethodHandleImpl mh) { 477 Object base = staticBase(mh); 478 long offset = staticOffset(mh); 479 return UNSAFE.getByte(base, offset); 480 } 481 getByteVolatile(MethodHandleImpl mh)482 static byte getByteVolatile(MethodHandleImpl mh) { 483 Object base = staticBase(mh); 484 long offset = staticOffset(mh); 485 return UNSAFE.getByteVolatile(base, offset); 486 } 487 getChar(MethodHandleImpl mh)488 static char getChar(MethodHandleImpl mh) { 489 Object base = staticBase(mh); 490 long offset = staticOffset(mh); 491 return UNSAFE.getChar(base, offset); 492 } 493 getCharVolatile(MethodHandleImpl mh)494 static char getCharVolatile(MethodHandleImpl mh) { 495 Object base = staticBase(mh); 496 long offset = staticOffset(mh); 497 return UNSAFE.getCharVolatile(base, offset); 498 } 499 getShort(MethodHandleImpl mh)500 static short getShort(MethodHandleImpl mh) { 501 Object base = staticBase(mh); 502 long offset = staticOffset(mh); 503 return UNSAFE.getShort(base, offset); 504 } 505 getShortVolatile(MethodHandleImpl mh)506 static short getShortVolatile(MethodHandleImpl mh) { 507 Object base = staticBase(mh); 508 long offset = staticOffset(mh); 509 return UNSAFE.getShortVolatile(base, offset); 510 } 511 getInt(MethodHandleImpl mh)512 static int getInt(MethodHandleImpl mh) { 513 Object base = staticBase(mh); 514 long offset = staticOffset(mh); 515 return UNSAFE.getInt(base, offset); 516 } 517 getIntVolatile(MethodHandleImpl mh)518 static int getIntVolatile(MethodHandleImpl mh) { 519 Object base = staticBase(mh); 520 long offset = staticOffset(mh); 521 return UNSAFE.getIntVolatile(base, offset); 522 } 523 getLong(MethodHandleImpl mh)524 static long getLong(MethodHandleImpl mh) { 525 Object base = staticBase(mh); 526 long offset = staticOffset(mh); 527 return UNSAFE.getLong(base, offset); 528 } 529 getLongVolatile(MethodHandleImpl mh)530 static long getLongVolatile(MethodHandleImpl mh) { 531 Object base = staticBase(mh); 532 long offset = staticOffset(mh); 533 return UNSAFE.getLongVolatile(base, offset); 534 } 535 getDouble(MethodHandleImpl mh)536 static double getDouble(MethodHandleImpl mh) { 537 Object base = staticBase(mh); 538 long offset = staticOffset(mh); 539 return UNSAFE.getDouble(base, offset); 540 } 541 getDoubleVolatile(MethodHandleImpl mh)542 static double getDoubleVolatile(MethodHandleImpl mh) { 543 Object base = staticBase(mh); 544 long offset = staticOffset(mh); 545 return UNSAFE.getDoubleVolatile(base, offset); 546 } 547 getFloat(MethodHandleImpl mh)548 static float getFloat(MethodHandleImpl mh) { 549 Object base = staticBase(mh); 550 long offset = staticOffset(mh); 551 return UNSAFE.getFloat(base, offset); 552 } 553 getFloatVolatile(MethodHandleImpl mh)554 static float getFloatVolatile(MethodHandleImpl mh) { 555 Object base = staticBase(mh); 556 long offset = staticOffset(mh); 557 return UNSAFE.getFloatVolatile(base, offset); 558 } 559 getReference(MethodHandleImpl mh)560 static Object getReference(MethodHandleImpl mh) { 561 Object base = staticBase(mh); 562 long offset = staticOffset(mh); 563 return UNSAFE.getReference(base, offset); 564 } 565 getReferenceVolatile(MethodHandleImpl mh)566 static Object getReferenceVolatile(MethodHandleImpl mh) { 567 Object base = staticBase(mh); 568 long offset = staticOffset(mh); 569 return UNSAFE.getReferenceVolatile(base, offset); 570 } 571 } 572 } 573