Mercurial > hg > truffle
comparison graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java @ 18905:c46e268fd091
Truffle: add (and switch to) safe node field access implementation using reflection
author | Andreas Woess <andreas.woess@jku.at> |
---|---|
date | Thu, 22 Jan 2015 01:01:29 +0100 |
parents | 6ba170cb6f53 |
children | 0f462015296f |
comparison
equal
deleted
inserted
replaced
18904:6ba170cb6f53 | 18905:c46e268fd091 |
---|---|
41 | 41 |
42 /** | 42 /** |
43 * Utility class that manages the special access methods for node instances. | 43 * Utility class that manages the special access methods for node instances. |
44 */ | 44 */ |
45 public final class NodeUtil { | 45 public final class NodeUtil { |
46 private static final boolean USE_UNSAFE = Boolean.getBoolean("truffle.unsafe"); | |
46 | 47 |
47 /** | 48 /** |
48 * Interface that allows the customization of field offsets used for {@link Unsafe} field | 49 * Interface that allows the customization of field offsets used for {@link Unsafe} field |
49 * accesses. | 50 * accesses. |
50 */ | 51 */ |
86 } | 87 } |
87 | 88 |
88 /** | 89 /** |
89 * Information about a field in a {@link Node} class. | 90 * Information about a field in a {@link Node} class. |
90 */ | 91 */ |
91 public static final class NodeField { | 92 public abstract static class NodeField { |
92 | 93 |
93 private final NodeFieldKind kind; | 94 private final NodeFieldKind kind; |
94 private final Class<?> type; | |
95 private final String name; | 95 private final String name; |
96 private long offset; | 96 protected final Class<?> type; |
97 | 97 protected final long offset; |
98 private NodeField(NodeFieldKind kind, Field field) { | 98 |
99 protected NodeField(NodeFieldKind kind, Field field) { | |
99 this.kind = kind; | 100 this.kind = kind; |
100 this.type = field.getType(); | 101 this.type = field.getType(); |
101 this.name = field.getName(); | 102 this.name = field.getName(); |
102 this.offset = unsafeFieldOffsetProvider.objectFieldOffset(field); | 103 this.offset = unsafeFieldOffsetProvider.objectFieldOffset(field); |
103 } | 104 } |
104 | 105 |
105 protected static NodeField create(NodeFieldKind kind, Field field) { | 106 protected static NodeField create(NodeFieldKind kind, Field field) { |
106 return new NodeField(kind, field); | 107 if (USE_UNSAFE) { |
108 return new UnsafeNodeField(kind, field); | |
109 } else { | |
110 return new ReflectionNodeField(kind, field); | |
111 } | |
107 } | 112 } |
108 | 113 |
109 public NodeFieldKind getKind() { | 114 public NodeFieldKind getKind() { |
110 return kind; | 115 return kind; |
111 } | 116 } |
120 | 125 |
121 public long getOffset() { | 126 public long getOffset() { |
122 return offset; | 127 return offset; |
123 } | 128 } |
124 | 129 |
125 public void putObject(Object receiver, Object value) { | 130 public abstract void putObject(Node receiver, Object value); |
131 | |
132 public abstract Object getObject(Node receiver); | |
133 | |
134 public abstract Object loadValue(Node node); | |
135 | |
136 @Override | |
137 public int hashCode() { | |
138 return kind.hashCode() | type.hashCode() | name.hashCode() | ((Long) offset).hashCode(); | |
139 } | |
140 | |
141 @Override | |
142 public boolean equals(Object obj) { | |
143 if (obj instanceof NodeField) { | |
144 NodeField other = (NodeField) obj; | |
145 return offset == other.offset && name.equals(other.name) && type.equals(other.type) && kind.equals(other.kind); | |
146 } | |
147 return false; | |
148 } | |
149 } | |
150 | |
151 private static final class UnsafeNodeField extends NodeField { | |
152 protected UnsafeNodeField(NodeFieldKind kind, Field field) { | |
153 super(kind, field); | |
154 } | |
155 | |
156 @Override | |
157 public void putObject(Node receiver, Object value) { | |
126 assert !type.isPrimitive() && value == null || type.isInstance(value); | 158 assert !type.isPrimitive() && value == null || type.isInstance(value); |
127 unsafe.putObject(receiver, offset, value); | 159 unsafe.putObject(receiver, offset, value); |
128 } | 160 } |
129 | 161 |
130 public Object getObject(Object receiver) { | 162 @Override |
163 public Object getObject(Node receiver) { | |
131 assert !type.isPrimitive(); | 164 assert !type.isPrimitive(); |
132 return unsafe.getObject(receiver, offset); | 165 return unsafe.getObject(receiver, offset); |
133 } | 166 } |
134 | 167 |
168 @Override | |
135 public Object loadValue(Node node) { | 169 public Object loadValue(Node node) { |
136 if (type == boolean.class) { | 170 if (type == boolean.class) { |
137 return unsafe.getBoolean(node, offset); | 171 return unsafe.getBoolean(node, offset); |
138 } else if (type == byte.class) { | 172 } else if (type == byte.class) { |
139 return unsafe.getByte(node, offset); | 173 return unsafe.getByte(node, offset); |
151 return unsafe.getDouble(node, offset); | 185 return unsafe.getDouble(node, offset); |
152 } else { | 186 } else { |
153 return unsafe.getObject(node, offset); | 187 return unsafe.getObject(node, offset); |
154 } | 188 } |
155 } | 189 } |
190 } | |
191 | |
192 private static final class ReflectionNodeField extends NodeField { | |
193 private final Field field; | |
194 | |
195 protected ReflectionNodeField(NodeFieldKind kind, Field field) { | |
196 super(kind, field); | |
197 this.field = field; | |
198 field.setAccessible(true); | |
199 } | |
156 | 200 |
157 @Override | 201 @Override |
158 public int hashCode() { | 202 public void putObject(Node receiver, Object value) { |
159 return kind.hashCode() | type.hashCode() | name.hashCode() | ((Long) offset).hashCode(); | 203 assert !type.isPrimitive() && value == null || type.isInstance(value); |
204 try { | |
205 field.set(receiver, value); | |
206 } catch (IllegalAccessException e) { | |
207 throw new AssertionError(e); | |
208 } | |
160 } | 209 } |
161 | 210 |
162 @Override | 211 @Override |
163 public boolean equals(Object obj) { | 212 public Object getObject(Node receiver) { |
164 if (obj instanceof NodeField) { | 213 assert !type.isPrimitive(); |
165 NodeField other = (NodeField) obj; | 214 try { |
166 return offset == other.offset && name.equals(other.name) && type.equals(other.type) && kind.equals(other.kind); | 215 return field.get(receiver); |
167 } | 216 } catch (IllegalAccessException e) { |
168 return false; | 217 throw new AssertionError(e); |
218 } | |
219 } | |
220 | |
221 @Override | |
222 public Object loadValue(Node node) { | |
223 try { | |
224 if (type == boolean.class) { | |
225 return field.getBoolean(node); | |
226 } else if (type == byte.class) { | |
227 return field.getByte(node); | |
228 } else if (type == short.class) { | |
229 return field.getShort(node); | |
230 } else if (type == char.class) { | |
231 return field.getChar(node); | |
232 } else if (type == int.class) { | |
233 return field.getInt(node); | |
234 } else if (type == long.class) { | |
235 return field.getLong(node); | |
236 } else if (type == float.class) { | |
237 return field.getFloat(node); | |
238 } else if (type == double.class) { | |
239 return field.getDouble(node); | |
240 } else { | |
241 return field.get(node); | |
242 } | |
243 } catch (IllegalAccessException e) { | |
244 throw new AssertionError(e); | |
245 } | |
169 } | 246 } |
170 } | 247 } |
171 | 248 |
172 /** | 249 /** |
173 * Information about a {@link Node} class. A single instance of this class is allocated for | 250 * Information about a {@link Node} class. A single instance of this class is allocated for |