--- a/jdk/src/share/classes/sun/dyn/AdapterMethodHandle.java Thu Feb 10 16:24:40 2011 -0800
+++ b/jdk/src/share/classes/sun/dyn/AdapterMethodHandle.java Fri Feb 11 01:26:24 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -478,37 +478,60 @@
return new AdapterMethodHandle(target, newType, makeConv(raw ? OP_RETYPE_RAW : OP_RETYPE_ONLY));
}
- static MethodHandle makeTypeHandler(Access token,
- MethodHandle target, MethodHandle typeHandler) {
+ static MethodHandle makeVarargsCollector(Access token,
+ MethodHandle target, Class<?> arrayType) {
Access.check(token);
- return new WithTypeHandler(target, typeHandler);
+ return new AsVarargsCollector(target, arrayType);
}
- static class WithTypeHandler extends AdapterMethodHandle {
- final MethodHandle target, typeHandler;
- WithTypeHandler(MethodHandle target, MethodHandle typeHandler) {
+ static class AsVarargsCollector extends AdapterMethodHandle {
+ final MethodHandle target;
+ final Class<?> arrayType;
+ MethodHandle cache;
+
+ AsVarargsCollector(MethodHandle target, Class<?> arrayType) {
super(target, target.type(), makeConv(OP_RETYPE_ONLY));
this.target = target;
- this.typeHandler = typeHandler.asType(TYPE_HANDLER_TYPE);
+ this.arrayType = arrayType;
+ this.cache = target.asCollector(arrayType, 0);
+ }
+
+ @Override
+ public boolean isVarargsCollector() {
+ return true;
}
+ @Override
public MethodHandle asType(MethodType newType) {
- if (this.type() == newType)
- return this;
+ MethodType type = this.type();
+ int collectArg = type.parameterCount() - 1;
+ int newArity = newType.parameterCount();
+ if (newArity == collectArg+1 &&
+ type.parameterType(collectArg).isAssignableFrom(newType.parameterType(collectArg))) {
+ // if arity and trailing parameter are compatible, do normal thing
+ return super.asType(newType);
+ }
+ // check cache
+ if (cache.type().parameterCount() == newArity)
+ return cache.asType(newType);
+ // build and cache a collector
+ int arrayLength = newArity - collectArg;
+ MethodHandle collector;
try {
- MethodHandle retyped = (MethodHandle) typeHandler.invokeExact(target, newType);
- // Contract: Must return the desired type, or throw WMT
- if (retyped.type() != newType)
- throw new WrongMethodTypeException(retyped.toString());
- return retyped;
- } catch (Throwable ex) {
- if (ex instanceof Error) throw (Error)ex;
- if (ex instanceof RuntimeException) throw (RuntimeException)ex;
- throw new RuntimeException(ex);
+ collector = target.asCollector(arrayType, arrayLength);
+ } catch (IllegalArgumentException ex) {
+ throw new WrongMethodTypeException("cannot build collector");
}
+ cache = collector;
+ return collector.asType(newType);
}
- private static final MethodType TYPE_HANDLER_TYPE
- = MethodType.methodType(MethodHandle.class, MethodHandle.class, MethodType.class);
+
+ public MethodHandle asVarargsCollector(Class<?> arrayType) {
+ MethodType type = this.type();
+ if (type.parameterType(type.parameterCount()-1) == arrayType)
+ return this;
+ return super.asVarargsCollector(arrayType);
+ }
}
/** Can a checkcast adapter validly convert the target to newType?