001/*
002 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.
008 *
009 * This code is distributed in the hope that it will be useful, but WITHOUT
010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
011 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
012 * version 2 for more details (a copy is included in the LICENSE file that
013 * accompanied this code).
014 *
015 * You should have received a copy of the GNU General Public License version
016 * 2 along with this work; if not, write to the Free Software Foundation,
017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
018 *
019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
020 * or visit www.oracle.com if you need additional information or have any
021 * questions.
022 */
023package com.oracle.graal.jtt.backend;
024
025import static jdk.internal.org.objectweb.asm.Opcodes.*;
026import jdk.internal.jvmci.options.*;
027import jdk.internal.jvmci.options.OptionValue.OverrideScope;
028import jdk.internal.org.objectweb.asm.*;
029
030import org.junit.*;
031
032import com.oracle.graal.api.directives.*;
033import com.oracle.graal.compiler.common.*;
034import com.oracle.graal.jtt.*;
035
036public class LargeConstantSectionTest extends JTTTest {
037    private static final String NAME = "LargeConstantSection";
038    private static final long LARGE_CONSTANT = 0xF0F0F0F0F0L;
039    private static LargeConstantClassLoader LOADER;
040
041    @BeforeClass
042    public static void before() {
043        LOADER = new LargeConstantClassLoader(LargeConstantSectionTest.class.getClassLoader());
044    }
045
046    public abstract static class LargeConstantAbstract {
047        public abstract long run(long i);
048    }
049
050    public static long test(LargeConstantAbstract a, long i) throws Exception {
051        return a.run(GraalDirectives.opaque(i));
052    }
053
054    public static class LargeConstantClassLoader extends ClassLoader {
055        public LargeConstantClassLoader(ClassLoader parent) {
056            super(parent);
057        }
058
059        @Override
060        protected Class<?> findClass(String name) throws ClassNotFoundException {
061            if (name.equals(NAME)) {
062                int numberIfBlocks = 1100; // Each if block contains three constants
063                ClassWriter cw = new ClassWriter(0);
064                MethodVisitor mv;
065                String abstractClassName = Type.getInternalName(LargeConstantAbstract.class);
066                cw.visit(52, ACC_PUBLIC + ACC_SUPER, NAME, null, abstractClassName, null);
067
068                mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
069                mv.visitCode();
070                Label l0 = new Label();
071                mv.visitLabel(l0);
072                mv.visitVarInsn(ALOAD, 0);
073                mv.visitMethodInsn(INVOKESPECIAL, abstractClassName, "<init>", "()V", false);
074                mv.visitInsn(RETURN);
075                Label l1 = new Label();
076                mv.visitLabel(l1);
077                mv.visitMaxs(1, 1);
078                mv.visitEnd();
079
080                mv = cw.visitMethod(ACC_PUBLIC, "run", "(J)J", null, null);
081                mv.visitCode();
082                Label nextIf = new Label();
083                for (int i = 0; i < numberIfBlocks; i++) {
084                    mv.visitLabel(nextIf);
085                    mv.visitFrame(Opcodes.F_NEW, 2, new Object[]{abstractClassName, Opcodes.LONG}, 0, new Object[]{});
086                    mv.visitVarInsn(LLOAD, 1);
087                    mv.visitLdcInsn(new Long(LARGE_CONSTANT + i));
088                    mv.visitInsn(LCMP);
089                    nextIf = new Label();
090                    mv.visitJumpInsn(IFNE, nextIf);
091                    mv.visitLdcInsn(new Long(LARGE_CONSTANT + i + numberIfBlocks));
092                    mv.visitMethodInsn(INVOKESTATIC, "com/oracle/graal/api/directives/GraalDirectives", "opaque", "(J)J", false);
093                    mv.visitLdcInsn(new Long(LARGE_CONSTANT + i + numberIfBlocks * 2));
094                    mv.visitMethodInsn(INVOKESTATIC, "com/oracle/graal/api/directives/GraalDirectives", "opaque", "(J)J", false);
095                    mv.visitInsn(LADD);
096                    mv.visitInsn(LRETURN);
097                }
098                mv.visitLabel(nextIf);
099                mv.visitFrame(Opcodes.F_NEW, 2, new Object[]{abstractClassName, Opcodes.LONG}, 0, new Object[]{});
100                mv.visitInsn(LCONST_0);
101                mv.visitInsn(LRETURN);
102                Label l9 = new Label();
103                mv.visitLabel(l9);
104                mv.visitMaxs(4, 6);
105                mv.visitEnd();
106
107                cw.visitEnd();
108
109                byte[] bytes = cw.toByteArray();
110                return defineClass(name, bytes, 0, bytes.length);
111            } else {
112                return super.findClass(name);
113            }
114        }
115    }
116
117    @Test
118    public void run0() throws Exception {
119        try (OverrideScope os = OptionValue.override(GraalOptions.InlineEverything, true)) {
120            runTest("test", LOADER.findClass(NAME).newInstance(), 0L);
121        }
122    }
123}