1 /* |
1 /* |
2 * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
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 |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. Oracle designates this |
7 * published by the Free Software Foundation. Oracle designates this |
217 for (int i = 0; i < convSpecs.length-1; i++) { |
217 for (int i = 0; i < convSpecs.length-1; i++) { |
218 Object convSpec = convSpecs[i]; |
218 Object convSpec = convSpecs[i]; |
219 if (convSpec == null) continue; |
219 if (convSpec == null) continue; |
220 MethodHandle fn; |
220 MethodHandle fn; |
221 if (convSpec instanceof Class) { |
221 if (convSpec instanceof Class) { |
222 fn = Lazy.MH_castReference.bindTo(convSpec); |
222 fn = Lazy.MH_cast.bindTo(convSpec); |
223 } else { |
223 } else { |
224 fn = (MethodHandle) convSpec; |
224 fn = (MethodHandle) convSpec; |
225 } |
225 } |
226 Class<?> newType = basicSrcType.parameterType(i); |
226 Class<?> newType = basicSrcType.parameterType(i); |
227 if (--convCount == 0) |
227 if (--convCount == 0) |
237 MethodHandle fn; |
237 MethodHandle fn; |
238 if (convSpec instanceof Class) { |
238 if (convSpec instanceof Class) { |
239 if (convSpec == void.class) |
239 if (convSpec == void.class) |
240 fn = null; |
240 fn = null; |
241 else |
241 else |
242 fn = Lazy.MH_castReference.bindTo(convSpec); |
242 fn = Lazy.MH_cast.bindTo(convSpec); |
243 } else { |
243 } else { |
244 fn = (MethodHandle) convSpec; |
244 fn = (MethodHandle) convSpec; |
245 } |
245 } |
246 Class<?> newType = basicSrcType.returnType(); |
246 Class<?> newType = basicSrcType.returnType(); |
247 assert(--convCount == 0); |
247 assert(--convCount == 0); |
300 } |
300 } |
301 |
301 |
302 Name conv; |
302 Name conv; |
303 if (convSpec instanceof Class) { |
303 if (convSpec instanceof Class) { |
304 Class<?> convClass = (Class<?>) convSpec; |
304 Class<?> convClass = (Class<?>) convSpec; |
305 conv = new Name(Lazy.MH_castReference, convClass, names[INARG_BASE + i]); |
305 conv = new Name(Lazy.MH_cast, convClass, names[INARG_BASE + i]); |
306 } else { |
306 } else { |
307 MethodHandle fn = (MethodHandle) convSpec; |
307 MethodHandle fn = (MethodHandle) convSpec; |
308 conv = new Name(fn, names[INARG_BASE + i]); |
308 conv = new Name(fn, names[INARG_BASE + i]); |
309 } |
309 } |
310 assert(names[nameCursor] == null); |
310 assert(names[nameCursor] == null); |
324 Name conv; |
324 Name conv; |
325 if (convSpec == void.class) { |
325 if (convSpec == void.class) { |
326 conv = new Name(LambdaForm.constantZero(BasicType.basicType(srcType.returnType()))); |
326 conv = new Name(LambdaForm.constantZero(BasicType.basicType(srcType.returnType()))); |
327 } else if (convSpec instanceof Class) { |
327 } else if (convSpec instanceof Class) { |
328 Class<?> convClass = (Class<?>) convSpec; |
328 Class<?> convClass = (Class<?>) convSpec; |
329 conv = new Name(Lazy.MH_castReference, convClass, names[OUT_CALL]); |
329 conv = new Name(Lazy.MH_cast, convClass, names[OUT_CALL]); |
330 } else { |
330 } else { |
331 MethodHandle fn = (MethodHandle) convSpec; |
331 MethodHandle fn = (MethodHandle) convSpec; |
332 if (fn.type().parameterCount() == 0) |
332 if (fn.type().parameterCount() == 0) |
333 conv = new Name(fn); // don't pass retval to void conversion |
333 conv = new Name(fn); // don't pass retval to void conversion |
334 else |
334 else |
339 assert(RETURN_CONV == names.length-1); |
339 assert(RETURN_CONV == names.length-1); |
340 } |
340 } |
341 |
341 |
342 LambdaForm form = new LambdaForm("convert", lambdaType.parameterCount(), names, RESULT); |
342 LambdaForm form = new LambdaForm("convert", lambdaType.parameterCount(), names, RESULT); |
343 return SimpleMethodHandle.make(srcType, form); |
343 return SimpleMethodHandle.make(srcType, form); |
344 } |
|
345 |
|
346 /** |
|
347 * Identity function, with reference cast. |
|
348 * @param t an arbitrary reference type |
|
349 * @param x an arbitrary reference value |
|
350 * @return the same value x |
|
351 */ |
|
352 @ForceInline |
|
353 @SuppressWarnings("unchecked") |
|
354 static <T,U> T castReference(Class<? extends T> t, U x) { |
|
355 // inlined Class.cast because we can't ForceInline it |
|
356 if (x != null && !t.isInstance(x)) |
|
357 throw newClassCastException(t, x); |
|
358 return (T) x; |
|
359 } |
|
360 |
|
361 private static ClassCastException newClassCastException(Class<?> t, Object obj) { |
|
362 return new ClassCastException("Cannot cast " + obj.getClass().getName() + " to " + t.getName()); |
|
363 } |
344 } |
364 |
345 |
365 static Object[] computeValueConversions(MethodType srcType, MethodType dstType, |
346 static Object[] computeValueConversions(MethodType srcType, MethodType dstType, |
366 boolean strict, boolean monobox) { |
347 boolean strict, boolean monobox) { |
367 final int INARG_COUNT = srcType.parameterCount(); |
348 final int INARG_COUNT = srcType.parameterCount(); |
589 * Pre-initialized NamedFunctions for bootstrapping purposes. |
570 * Pre-initialized NamedFunctions for bootstrapping purposes. |
590 * Factored in an inner class to delay initialization until first usage. |
571 * Factored in an inner class to delay initialization until first usage. |
591 */ |
572 */ |
592 static class Lazy { |
573 static class Lazy { |
593 private static final Class<?> MHI = MethodHandleImpl.class; |
574 private static final Class<?> MHI = MethodHandleImpl.class; |
|
575 private static final Class<?> CLS = Class.class; |
594 |
576 |
595 private static final MethodHandle[] ARRAYS; |
577 private static final MethodHandle[] ARRAYS; |
596 private static final MethodHandle[] FILL_ARRAYS; |
578 private static final MethodHandle[] FILL_ARRAYS; |
597 |
579 |
598 static final NamedFunction NF_checkSpreadArgument; |
580 static final NamedFunction NF_checkSpreadArgument; |
599 static final NamedFunction NF_guardWithCatch; |
581 static final NamedFunction NF_guardWithCatch; |
600 static final NamedFunction NF_throwException; |
582 static final NamedFunction NF_throwException; |
601 static final NamedFunction NF_profileBoolean; |
583 static final NamedFunction NF_profileBoolean; |
602 |
584 |
603 static final MethodHandle MH_castReference; |
585 static final MethodHandle MH_cast; |
604 static final MethodHandle MH_selectAlternative; |
586 static final MethodHandle MH_selectAlternative; |
605 static final MethodHandle MH_copyAsPrimitiveArray; |
587 static final MethodHandle MH_copyAsPrimitiveArray; |
606 static final MethodHandle MH_fillNewTypedArray; |
588 static final MethodHandle MH_fillNewTypedArray; |
607 static final MethodHandle MH_fillNewArray; |
589 static final MethodHandle MH_fillNewArray; |
608 static final MethodHandle MH_arrayIdentity; |
590 static final MethodHandle MH_arrayIdentity; |
621 NF_checkSpreadArgument.resolve(); |
603 NF_checkSpreadArgument.resolve(); |
622 NF_guardWithCatch.resolve(); |
604 NF_guardWithCatch.resolve(); |
623 NF_throwException.resolve(); |
605 NF_throwException.resolve(); |
624 NF_profileBoolean.resolve(); |
606 NF_profileBoolean.resolve(); |
625 |
607 |
626 MH_castReference = IMPL_LOOKUP.findStatic(MHI, "castReference", |
608 MH_cast = IMPL_LOOKUP.findVirtual(CLS, "cast", |
627 MethodType.methodType(Object.class, Class.class, Object.class)); |
609 MethodType.methodType(Object.class, Object.class)); |
628 MH_copyAsPrimitiveArray = IMPL_LOOKUP.findStatic(MHI, "copyAsPrimitiveArray", |
610 MH_copyAsPrimitiveArray = IMPL_LOOKUP.findStatic(MHI, "copyAsPrimitiveArray", |
629 MethodType.methodType(Object.class, Wrapper.class, Object[].class)); |
611 MethodType.methodType(Object.class, Wrapper.class, Object[].class)); |
630 MH_arrayIdentity = IMPL_LOOKUP.findStatic(MHI, "identity", |
612 MH_arrayIdentity = IMPL_LOOKUP.findStatic(MHI, "identity", |
631 MethodType.methodType(Object[].class, Object[].class)); |
613 MethodType.methodType(Object[].class, Object[].class)); |
632 MH_fillNewArray = IMPL_LOOKUP.findStatic(MHI, "fillNewArray", |
614 MH_fillNewArray = IMPL_LOOKUP.findStatic(MHI, "fillNewArray", |