Mercurial > hg > graal-jvmci-8
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 } |