DynamicNewInstanceNode.java revision 12651:6ef01bd40ce2
190075Sobrien/*
290075Sobrien * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
3169689Skan * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
490075Sobrien *
590075Sobrien * This code is free software; you can redistribute it and/or modify it
690075Sobrien * under the terms of the GNU General Public License version 2 only, as
790075Sobrien * published by the Free Software Foundation.
8132718Skan *
990075Sobrien * This code is distributed in the hope that it will be useful, but WITHOUT
10132718Skan * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11132718Skan * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12132718Skan * version 2 for more details (a copy is included in the LICENSE file that
13132718Skan * accompanied this code).
1490075Sobrien *
15132718Skan * You should have received a copy of the GNU General Public License version
16132718Skan * 2 along with this work; if not, write to the Free Software Foundation,
17132718Skan * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18132718Skan *
1990075Sobrien * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2090075Sobrien * or visit www.oracle.com if you need additional information or have any
21132718Skan * questions.
22169689Skan */
23169689Skanpackage org.graalvm.compiler.nodes.java;
2490075Sobrien
2590075Sobrienimport java.lang.reflect.Modifier;
2690075Sobrien
2790075Sobrienimport org.graalvm.compiler.core.common.type.StampFactory;
2890075Sobrienimport org.graalvm.compiler.graph.Node;
2990075Sobrienimport org.graalvm.compiler.graph.NodeClass;
3090075Sobrienimport org.graalvm.compiler.graph.spi.Canonicalizable;
3190075Sobrienimport org.graalvm.compiler.graph.spi.CanonicalizerTool;
3290075Sobrienimport org.graalvm.compiler.nodeinfo.NodeInfo;
33169689Skanimport org.graalvm.compiler.nodes.FrameState;
34169689Skanimport org.graalvm.compiler.nodes.ValueNode;
3590075Sobrien
3690075Sobrienimport jdk.vm.ci.meta.MetaAccessProvider;
3790075Sobrienimport jdk.vm.ci.meta.ResolvedJavaType;
3890075Sobrien
39169689Skan@NodeInfo
40169689Skanpublic class DynamicNewInstanceNode extends AbstractNewObjectNode implements Canonicalizable {
41169689Skan    public static final NodeClass<DynamicNewInstanceNode> TYPE = NodeClass.create(DynamicNewInstanceNode.class);
4290075Sobrien
4390075Sobrien    @Input ValueNode clazz;
44132718Skan
45132718Skan    /**
46132718Skan     * Class pointer to class.class needs to be exposed earlier than this node is lowered so that it
47132718Skan     * can be replaced by the AOT machinery. If it's not needed for lowering this input can be
48132718Skan     * ignored.
49132718Skan     */
50132718Skan    @OptionalInput ValueNode classClass;
5190075Sobrien
5290075Sobrien    public DynamicNewInstanceNode(ValueNode clazz, boolean fillContents) {
5390075Sobrien        this(TYPE, clazz, fillContents, null);
5490075Sobrien    }
5590075Sobrien
5690075Sobrien    protected DynamicNewInstanceNode(NodeClass<? extends DynamicNewInstanceNode> c, ValueNode clazz, boolean fillContents, FrameState stateBefore) {
5790075Sobrien        super(c, StampFactory.objectNonNull(), fillContents, stateBefore);
5890075Sobrien        this.clazz = clazz;
5990075Sobrien    }
6090075Sobrien
6190075Sobrien    public ValueNode getInstanceType() {
6290075Sobrien        return clazz;
6390075Sobrien    }
6490075Sobrien
6590075Sobrien    @Override
6690075Sobrien    public Node canonical(CanonicalizerTool tool) {
6790075Sobrien        if (clazz.isConstant()) {
6890075Sobrien            ResolvedJavaType type = tool.getConstantReflection().asJavaType(clazz.asConstant());
69117395Skan            if (type != null && type.isInitialized() && !throwsInstantiationException(type, tool.getMetaAccess())) {
70117395Skan                return createNewInstanceNode(type);
71117395Skan            }
72117395Skan        }
73117395Skan        return this;
7490075Sobrien    }
7590075Sobrien
7690075Sobrien    /** Hook for subclasses to instantiate a subclass of {@link NewInstanceNode}. */
7790075Sobrien    protected NewInstanceNode createNewInstanceNode(ResolvedJavaType type) {
7890075Sobrien        return new NewInstanceNode(type, fillContents(), stateBefore());
7990075Sobrien    }
80117395Skan
81132718Skan    public static boolean throwsInstantiationException(Class<?> type, Class<?> classClass) {
82132718Skan        return type.isPrimitive() || type.isArray() || type.isInterface() || Modifier.isAbstract(type.getModifiers()) || type == classClass;
83132718Skan    }
84132718Skan
85132718Skan    public static boolean throwsInstantiationException(ResolvedJavaType type, MetaAccessProvider metaAccess) {
86132718Skan        return type.isPrimitive() || type.isArray() || type.isInterface() || Modifier.isAbstract(type.getModifiers()) || type.equals(metaAccess.lookupJavaType(Class.class));
87132718Skan    }
88132718Skan
89132718Skan    public ValueNode getClassClass() {
90132718Skan        return classClass;
91132718Skan    }
92132718Skan
93169689Skan    public void setClassClass(ValueNode newClassClass) {
94169689Skan        updateUsages(classClass, newClassClass);
95169689Skan        classClass = newClassClass;
9690075Sobrien    }
9790075Sobrien}
9890075Sobrien