Mercurial > hg > graal-compiler
diff graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/SpecializationNode.java @ 18761:a665483c3881
Truffle-DSL: new node layout implementation.
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Mon, 29 Dec 2014 23:38:54 +0100 |
parents | |
children | a720bf2e2f43 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/SpecializationNode.java Mon Dec 29 23:38:54 2014 +0100 @@ -0,0 +1,445 @@ +/* + * Copyright (c) 2014, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ +package com.oracle.truffle.api.dsl.internal; + +import java.lang.reflect.*; +import java.util.concurrent.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.dsl.internal.RewriteEvent.RewriteEvent0; +import com.oracle.truffle.api.dsl.internal.RewriteEvent.RewriteEvent1; +import com.oracle.truffle.api.dsl.internal.RewriteEvent.RewriteEvent2; +import com.oracle.truffle.api.dsl.internal.RewriteEvent.RewriteEvent3; +import com.oracle.truffle.api.dsl.internal.RewriteEvent.RewriteEvent4; +import com.oracle.truffle.api.dsl.internal.RewriteEvent.RewriteEventN; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.nodes.NodeUtil.NodeClass; +import com.oracle.truffle.api.nodes.NodeUtil.NodeField; + +/** + * Internal implementation dependent base class for generated specialized nodes. + */ +@SuppressWarnings("unused") +@NodeInfo(cost = NodeCost.NONE) +public abstract class SpecializationNode extends Node { + + @Child protected SpecializationNode next; + + private final int index; + + public SpecializationNode() { + this(-1); + } + + public SpecializationNode(int index) { + this.index = index; + } + + @Override + public final NodeCost getCost() { + return NodeCost.NONE; + } + + public static Node updateRoot(Node node) { + updateRootImpl(((SpecializedNode) node).getSpecializationNode(), node); + return node; + } + + private static void updateRootImpl(SpecializationNode start, Node node) { + NodeField[] fields = NodeClass.get(start.getClass()).getFields(); + for (int i = fields.length - 1; i >= 0; i--) { + NodeField f = fields[i]; + if (f.getName().equals("root")) { + f.putObject(start, node); + break; + } + } + if (start.next != null) { + updateRootImpl(start.next, node); + } + } + + protected final SpecializationNode polymorphicMerge(SpecializationNode newNode) { + SpecializationNode merged = next.merge(newNode); + if (merged == newNode && !isSame(newNode) && count() <= 2) { + return removeSame(new RewriteEvent0(findParentNode(), "merged polymorphic to monomorphic")); + } + return merged; + } + + public final NodeCost getNodeCost() { + switch (count()) { + case 0: + case 1: + return NodeCost.UNINITIALIZED; + case 2: + return NodeCost.MONOMORPHIC; + default: + return NodeCost.POLYMORPHIC; + } + } + + protected abstract Node[] getSuppliedChildren(); + + protected SpecializationNode merge(SpecializationNode newNode) { + if (this.isSame(newNode)) { + return this; + } + return next != null ? next.merge(newNode) : newNode; + } + + @Override + public final boolean equals(Object obj) { + if (obj instanceof SpecializationNode) { + return ((SpecializationNode) obj).isSame(this); + } + return super.equals(obj); + } + + @Override + public final int hashCode() { + return index; + } + + protected boolean isSame(SpecializationNode other) { + return getClass() == other.getClass(); + } + + private final int count() { + return next != null ? next.count() + 1 : 1; + } + + protected final SpecializationNode removeSame(final CharSequence reason) { + return atomic(new Callable<SpecializationNode>() { + public SpecializationNode call() throws Exception { + return removeImpl(SpecializationNode.this, reason); + } + }); + } + + /** Find the topmost of the specialization chain. */ + private final SpecializationNode findStart() { + SpecializationNode node = this; + Node parent = this.getParent(); + while (parent instanceof SpecializationNode) { + SpecializationNode parentCast = ((SpecializationNode) parent); + if (parentCast.next != node) { + break; + } + node = parentCast; + parent = node.getParent(); + } + return node; + } + + private final Node findParentNode() { + return findStart().getParent(); + } + + private SpecializationNode removeImpl(SpecializationNode toRemove, CharSequence reason) { + SpecializationNode start = findStart(); + SpecializationNode current = start; + while (current != null) { + if (current.isSame(toRemove)) { + current.replace(current.next, reason); + if (current == start) { + start = start.next; + } + } + current = current.next; + } + return start; + } + + public Object acceptAndExecute(VirtualFrame frame) { + throw new UnsupportedOperationException(); + } + + public Object acceptAndExecute(VirtualFrame frame, Object o1) { + throw new UnsupportedOperationException(); + } + + public Object acceptAndExecute(VirtualFrame frame, Object o1, Object o2) { + throw new UnsupportedOperationException(); + } + + public Object acceptAndExecute(VirtualFrame frame, Object o1, Object o2, Object o3) { + throw new UnsupportedOperationException(); + } + + public Object acceptAndExecute(VirtualFrame frame, Object o1, Object o2, Object o3, Object o4) { + throw new UnsupportedOperationException(); + } + + public Object acceptAndExecute(VirtualFrame frame, Object... args) { + throw new UnsupportedOperationException(); + } + + protected SpecializationNode createFallback() { + return null; + } + + protected SpecializationNode createPolymorphic() { + return null; + } + + protected SpecializationNode createNext(VirtualFrame frame) { + throw new UnsupportedOperationException(); + } + + protected SpecializationNode createNext(VirtualFrame frame, Object o1) { + throw new UnsupportedOperationException(); + } + + protected SpecializationNode createNext(VirtualFrame frame, Object o1, Object o2) { + throw new UnsupportedOperationException(); + } + + protected SpecializationNode createNext(VirtualFrame frame, Object o1, Object o2, Object o3) { + throw new UnsupportedOperationException(); + } + + protected SpecializationNode createNext(VirtualFrame frame, Object o1, Object o2, Object o3, Object o4) { + throw new UnsupportedOperationException(); + } + + protected SpecializationNode createNext(VirtualFrame frame, Object... args) { + throw new UnsupportedOperationException(); + } + + protected final Object uninitialized(VirtualFrame frame) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + SpecializationNode nextSpecialization = createNext(frame); + if (nextSpecialization == null) { + nextSpecialization = createFallback(); + } + if (nextSpecialization == null) { + return unsupported(frame); + } + return insertSpecialization(nextSpecialization, new RewriteEvent0(findParentNode(), "inserted new specialization")).acceptAndExecute(frame); + } + + protected final Object uninitialized(VirtualFrame frame, Object o1) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + SpecializationNode nextSpecialization = createNext(frame, o1); + if (nextSpecialization == null) { + nextSpecialization = createFallback(); + } + if (nextSpecialization == null) { + return unsupported(frame, o1); + } + return insertSpecialization(nextSpecialization, new RewriteEvent1(findParentNode(), "inserted new specialization", o1)).acceptAndExecute(frame, o1); + } + + protected final Object uninitialized(VirtualFrame frame, Object o1, Object o2) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + SpecializationNode nextSpecialization = createNext(frame, o1, o2); + if (nextSpecialization == null) { + nextSpecialization = createFallback(); + } + if (nextSpecialization == null) { + return unsupported(frame, o1, o2); + } + return insertSpecialization(nextSpecialization, new RewriteEvent2(findParentNode(), "inserted new specialization", o1, o2)).acceptAndExecute(frame, o1, o2); + } + + protected final Object uninitialized(VirtualFrame frame, Object o1, Object o2, Object o3) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + SpecializationNode nextSpecialization = createNext(frame, o1, o2, o3); + if (nextSpecialization == null) { + nextSpecialization = createFallback(); + } + if (nextSpecialization == null) { + return unsupported(frame, o1, o2, o3); + } + return insertSpecialization(nextSpecialization, new RewriteEvent3(findParentNode(), "inserted new specialization", o1, o2, o3)).acceptAndExecute(frame, o1, o2, o3); + } + + protected final Object uninitialized(VirtualFrame frame, Object o1, Object o2, Object o3, Object o4) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + SpecializationNode nextSpecialization = createNext(frame, o1, o2, o3, o4); + if (nextSpecialization == null) { + nextSpecialization = createFallback(); + } + if (nextSpecialization == null) { + return unsupported(frame, o1, o2, o3, o4); + } + return insertSpecialization(nextSpecialization, new RewriteEvent4(findParentNode(), "inserts new specialization", o1, o2, o3, o4)).acceptAndExecute(frame, o1, o2, o3, o4); + } + + protected final Object uninitialized(VirtualFrame frame, Object... args) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + SpecializationNode nextSpecialization = createNext(frame, args); + if (nextSpecialization == null) { + nextSpecialization = createFallback(); + } + if (nextSpecialization == null) { + unsupported(frame, args); + } + return insertSpecialization(nextSpecialization, new RewriteEventN(findParentNode(), "inserts new specialization", args)).acceptAndExecute(frame, args); + } + + private boolean needsPolymorphic() { + return findStart().count() == 2; + } + + protected final Object remove(String reason, VirtualFrame frame) { + return removeSame(new RewriteEvent0(findParentNode(), reason)).acceptAndExecute(frame); + } + + protected final Object remove(String reason, VirtualFrame frame, Object o1) { + return removeSame(new RewriteEvent1(findParentNode(), reason, o1)).acceptAndExecute(frame, o1); + } + + protected final Object remove(String reason, VirtualFrame frame, Object o1, Object o2) { + return removeSame(new RewriteEvent2(findParentNode(), reason, o1, o2)).acceptAndExecute(frame, o1, o2); + } + + protected final Object remove(String reason, VirtualFrame frame, Object o1, Object o2, Object o3) { + return removeSame(new RewriteEvent3(findParentNode(), reason, o1, o2, o3)).acceptAndExecute(frame, o1, o2, o3); + } + + protected final Object remove(String reason, VirtualFrame frame, Object o1, Object o2, Object o3, Object o4) { + return removeSame(new RewriteEvent4(findParentNode(), reason, o1, o2, o3, o4)).acceptAndExecute(frame, o1, o2, o3, o4); + } + + protected final Object remove(String reason, VirtualFrame frame, Object... args) { + return removeSame(new RewriteEventN(findParentNode(), reason, args)).acceptAndExecute(frame, args); + } + + protected Object unsupported(VirtualFrame frame) { + throw new UnsupportedSpecializationException(findParentNode(), getSuppliedChildren()); + } + + protected Object unsupported(VirtualFrame frame, Object o1) { + throw new UnsupportedSpecializationException(findParentNode(), getSuppliedChildren(), o1); + } + + protected Object unsupported(VirtualFrame frame, Object o1, Object o2) { + throw new UnsupportedSpecializationException(findParentNode(), getSuppliedChildren(), o1, o2); + } + + protected Object unsupported(VirtualFrame frame, Object o1, Object o2, Object o3) { + throw new UnsupportedSpecializationException(findParentNode(), getSuppliedChildren(), o1, o2, o3); + } + + protected Object unsupported(VirtualFrame frame, Object o1, Object o2, Object o3, Object o4) { + throw new UnsupportedSpecializationException(findParentNode(), getSuppliedChildren(), o1, o2, o3, o4); + } + + protected Object unsupported(VirtualFrame frame, Object... args) { + throw new UnsupportedSpecializationException(findParentNode(), getSuppliedChildren(), args); + } + + private SpecializationNode insertSpecialization(final SpecializationNode generated, final CharSequence message) { + return atomic(new Callable<SpecializationNode>() { + public SpecializationNode call() { + return insert(generated, message); + } + }); + } + + private final SpecializationNode insert(final SpecializationNode generated, CharSequence message) { + SpecializationNode start = findStart(); + if (start == this) { + // fast path for first insert + return insertBefore(this, generated, message); + } else { + return slowSortedInsert(start, generated, message); + } + } + + private static <T> SpecializationNode slowSortedInsert(SpecializationNode start, final SpecializationNode generated, final CharSequence message) { + final SpecializationNode merged = start.merge(generated); + if (merged == generated) { + // new node + if (start.count() == 2) { + insertBefore(start, start.createPolymorphic(), "insert polymorphic"); + } + SpecializationNode insertBefore = findInsertBeforeNode(generated.index, start); + return insertBefore(insertBefore, generated, message); + } else { + // existing node + merged.replace(merged, new RewriteEvent0(merged.findParentNode(), "merged specialization")); + return merged; + } + } + + private static SpecializationNode findInsertBeforeNode(int generatedIndex, SpecializationNode start) { + SpecializationNode current = start; + while (current != null && current.index < generatedIndex) { + current = current.next; + } + return current; + } + + private static <T> SpecializationNode insertBefore(SpecializationNode node, SpecializationNode insertBefore, CharSequence message) { + insertBefore.next = node; + return node.replace(insertBefore, message); + } + + @Override + public final String toString() { + Class<?> clazz = getClass(); + StringBuilder b = new StringBuilder(); + b.append(clazz.getSimpleName()); + + appendFields(b, clazz); + if (next != null) { + b.append(" -> ").append(next.toString()); + } + return b.toString(); + } + + private void appendFields(StringBuilder b, Class<?> clazz) { + Field[] fields = clazz.getDeclaredFields(); + if (fields.length == 0) { + return; + } + b.append("("); + for (Field field : fields) { + if (Modifier.isStatic(field.getModifiers())) { + continue; + } + String name = field.getName(); + if (name.equals("root")) { + continue; + } + b.append(field.getName()); + try { + field.setAccessible(true); + b.append(field.get(this)); + } catch (IllegalArgumentException e) { + b.append(e.toString()); + } catch (IllegalAccessException e) { + b.append(e.toString()); + } + } + b.append(")"); + } + +}