comparison graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLWriteLocalVariableNode.java @ 13836:64c77f0577bb

More documentation and improvements of Simple Language
author Christian Wimmer <christian.wimmer@oracle.com>
date Thu, 30 Jan 2014 17:53:27 -0800
parents b16ec83edc73
children afd6fa5e8229
comparison
equal deleted inserted replaced
13835:67e4e7f56911 13836:64c77f0577bb
25 import com.oracle.truffle.api.*; 25 import com.oracle.truffle.api.*;
26 import com.oracle.truffle.api.dsl.*; 26 import com.oracle.truffle.api.dsl.*;
27 import com.oracle.truffle.api.frame.*; 27 import com.oracle.truffle.api.frame.*;
28 import com.oracle.truffle.sl.nodes.*; 28 import com.oracle.truffle.sl.nodes.*;
29 29
30 /**
31 * Node to write a local variable to a function's {@link VirtualFrame frame}. The Truffle frame API
32 * allows to store primitive values of all Java primitive types, and Object values.
33 */
30 @NodeChild(value = "valueNode") 34 @NodeChild(value = "valueNode")
31 @NodeField(name = "slot", type = FrameSlot.class) 35 @NodeField(name = "slot", type = FrameSlot.class)
32 public abstract class SLWriteLocalVariableNode extends SLExpressionNode { 36 public abstract class SLWriteLocalVariableNode extends SLExpressionNode {
33 37
38 /**
39 * Returns the descriptor of the accessed local variable. The implementation of this method is
40 * created by the Truffle DSL based on the {@link NodeField} annotation on the class.
41 */
34 protected abstract FrameSlot getSlot(); 42 protected abstract FrameSlot getSlot();
35 43
44 /**
45 * Specialized method to write a primitive {@code long} value}. This is only possible if the
46 * local variable also has currently the type {@code long}, therefore a Truffle DSL
47 * {@link #isLongKind() custom guard} is specified.
48 */
36 @Specialization(guards = "isLongKind") 49 @Specialization(guards = "isLongKind")
37 protected long write(VirtualFrame frame, long value) { 50 protected long write(VirtualFrame frame, long value) {
38 frame.setLong(getSlot(), value); 51 frame.setLong(getSlot(), value);
39 return value; 52 return value;
40 } 53 }
43 protected boolean write(VirtualFrame frame, boolean value) { 56 protected boolean write(VirtualFrame frame, boolean value) {
44 frame.setBoolean(getSlot(), value); 57 frame.setBoolean(getSlot(), value);
45 return value; 58 return value;
46 } 59 }
47 60
61 /**
62 * Generic write method that works for all possible types.
63 * <p>
64 * Why is this method annotated with {@link Specialization} and not {@link Generic}? For a
65 * {@link Generic} method, the Truffle DSL generated code would try all other specializations
66 * first before calling this method. We know that all these specializations would fail their
67 * guards, so there is no point in calling them. Since this method takes a value of type
68 * {@link Object}, it is guaranteed to never fail, i.e., once we are in this specialization the
69 * node will never be re-specialized.
70 */
48 @Specialization 71 @Specialization
49 protected Object write(VirtualFrame frame, Object value) { 72 protected Object write(VirtualFrame frame, Object value) {
50 if (getSlot().getKind() != FrameSlotKind.Object) { 73 if (getSlot().getKind() != FrameSlotKind.Object) {
74 /*
75 * The local variable has still a primitive type, we need to change it to Object. Since
76 * the variable type is important when the compiler optimizes a method, we also discard
77 * compiled code.
78 */
51 CompilerDirectives.transferToInterpreterAndInvalidate(); 79 CompilerDirectives.transferToInterpreterAndInvalidate();
52 getSlot().setKind(FrameSlotKind.Object); 80 getSlot().setKind(FrameSlotKind.Object);
53 } 81 }
54 frame.setObject(getSlot(), value); 82 frame.setObject(getSlot(), value);
55 return value; 83 return value;
56 } 84 }
57 85
86 /**
87 * Guard function that the local variable has the type {@code long}.
88 */
58 protected boolean isLongKind() { 89 protected boolean isLongKind() {
59 return isKind(FrameSlotKind.Long); 90 return isKind(FrameSlotKind.Long);
60 } 91 }
61 92
62 protected boolean isBooleanKind() { 93 protected boolean isBooleanKind() {
63 return isKind(FrameSlotKind.Boolean); 94 return isKind(FrameSlotKind.Boolean);
64 } 95 }
65 96
66 private boolean isKind(FrameSlotKind kind) { 97 private boolean isKind(FrameSlotKind kind) {
67 if (getSlot().getKind() == kind) { 98 if (getSlot().getKind() == kind) {
99 /* Success: the frame slot has the expected kind. */
68 return true; 100 return true;
69 } else if (getSlot().getKind() == FrameSlotKind.Illegal) { 101 } else if (getSlot().getKind() == FrameSlotKind.Illegal) {
102 /*
103 * This is the first write to this local variable. We can set the type to the one we
104 * expect. Since the variable type is important when the compiler optimizes a method, we
105 * also discard compiled code.
106 */
70 CompilerDirectives.transferToInterpreterAndInvalidate(); 107 CompilerDirectives.transferToInterpreterAndInvalidate();
71 getSlot().setKind(kind); 108 getSlot().setKind(kind);
72 return true; 109 return true;
73 } else { 110 } else {
111 /*
112 * Failure: the frame slot has the wrong kind, the Truffle DSL generated code will
113 * choose a different specialization.
114 */
74 return false; 115 return false;
75 } 116 }
76 } 117 }
77 } 118 }