# HG changeset patch # User psandoz # Date 1520548437 28800 # Node ID 74518f9ca4b46597aba65bbe5540c4f6e52ab674 # Parent 2d1d0c66966b142ad229cc4a05017bcdc74dec9a 8199342: The constant pool forgets it has a Dynamic entry if there are overpass methods Reviewed-by: lfoltan, acorn diff -r 2d1d0c66966b -r 74518f9ca4b4 src/hotspot/share/classfile/bytecodeAssembler.cpp --- a/src/hotspot/share/classfile/bytecodeAssembler.cpp Mon Mar 12 14:11:54 2018 -0700 +++ b/src/hotspot/share/classfile/bytecodeAssembler.cpp Thu Mar 08 14:33:57 2018 -0800 @@ -56,6 +56,11 @@ cp->set_pool_holder(_orig->pool_holder()); _orig->copy_cp_to(1, _orig->length() - 1, cp, 1, CHECK_NULL); + // Preserve dynamic constant information from the original pool + if (_orig->has_dynamic_constant()) { + cp->set_has_dynamic_constant(); + } + for (int i = 0; i < _entries.length(); ++i) { BytecodeCPEntry entry = _entries.at(i); int idx = i + _orig->length(); diff -r 2d1d0c66966b -r 74518f9ca4b4 test/jdk/java/lang/invoke/condy/CondyInterfaceWithOverpassMethods.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/java/lang/invoke/condy/CondyInterfaceWithOverpassMethods.java Thu Mar 08 14:33:57 2018 -0800 @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2018, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8186046 + * @summary Test for an interface using condy with default overpass methods + * @library /lib/testlibrary/bytecode + * @build jdk.experimental.bytecode.BasicClassBuilder + * @run testng CondyInterfaceWithOverpassMethods + * @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:UseBootstrapCallInfo=3 CondyInterfaceWithOverpassMethods + */ + +import jdk.experimental.bytecode.BasicClassBuilder; +import jdk.experimental.bytecode.Flag; +import jdk.experimental.bytecode.TypedCodeBuilder; +import org.testng.Assert; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.FileOutputStream; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.reflect.Method; +import java.util.concurrent.atomic.AtomicInteger; + +@Test +public class CondyInterfaceWithOverpassMethods { + interface A { + int a(); + + default int x() { + return 1; + } + } + + + // Generated class with methods containing condy ldc + Class gc; + + public static Object bsm(MethodHandles.Lookup l, String name, Class type) { + return name; + } + + @BeforeClass + public void generateClass() throws Exception { +// interface B extends A { +// // Overpass for method A.a +// +// default void y() { +// // ldc to Dynamic +// } +// } + Class thisClass = CondyInterfaceWithOverpassMethods.class; + + String genClassName = thisClass.getSimpleName() + "$Code"; + String bsmClassName = thisClass.getCanonicalName().replace('.', '/'); + String bsmMethodName = "bsm"; + String bsmDescriptor = MethodType.methodType(Object.class, MethodHandles.Lookup.class, + String.class, Class.class).toMethodDescriptorString(); + + byte[] byteArray = new BasicClassBuilder(genClassName, 55, 0) + .withFlags(Flag.ACC_INTERFACE, Flag.ACC_ABSTRACT) + .withSuperclass("java/lang/Object") + .withSuperinterface(thisClass.getCanonicalName().replace('.', '/') + "$" + A.class.getSimpleName()) + .withMethod("y", "()Ljava/lang/String;", M -> + M.withFlags(Flag.ACC_PUBLIC) + .withCode(TypedCodeBuilder::new, C -> + C.ldc("String", "Ljava/lang/String;", bsmClassName, bsmMethodName, bsmDescriptor, + S -> {}) + .areturn() + )) + .build(); + + // For debugging purposes + new FileOutputStream(new File(genClassName + ".class")).write(byteArray); + + gc = MethodHandles.lookup().defineClass(byteArray); + } + + @Test + public void testClass() throws Exception { + // Trigger initialization + Class.forName(gc.getName()); + } +}