comparison graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/access/SLWritePropertyCacheNode.java @ 18412:997bc9764a9a

SL: use the truffle object storage model to represent SL objects
author Andreas Woess <andreas.woess@jku.at>
date Tue, 18 Nov 2014 12:08:51 +0100
parents
children f7bc60c3a8f6
comparison
equal deleted inserted replaced
18411:dc2e000bed40 18412:997bc9764a9a
1 /*
2 * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23 package com.oracle.truffle.sl.nodes.access;
24
25 import com.oracle.truffle.api.*;
26 import com.oracle.truffle.api.nodes.*;
27 import com.oracle.truffle.api.object.*;
28
29 /**
30 * The node for accessing a property of an object. When executed, this node first evaluates the
31 * object expression on the left side of the dot operator and then reads the named property.
32 */
33 public abstract class SLWritePropertyCacheNode extends Node {
34
35 public static SLWritePropertyCacheNode create(String propertyName) {
36 return new SLUninitializedWritePropertyNode(propertyName);
37 }
38
39 public abstract void executeObject(DynamicObject receiver, Object value);
40
41 public abstract void executeLong(DynamicObject receiver, long value);
42
43 public abstract void executeBoolean(DynamicObject receiver, boolean value);
44
45 protected abstract static class SLWritePropertyCacheChainNode extends SLWritePropertyCacheNode {
46 protected final Shape oldShape;
47 protected final Shape newShape;
48 @Child protected SLWritePropertyCacheNode next;
49
50 public SLWritePropertyCacheChainNode(Shape oldShape, Shape newShape, SLWritePropertyCacheNode next) {
51 this.oldShape = oldShape;
52 this.newShape = newShape;
53 this.next = next;
54 }
55
56 @Override
57 public final void executeObject(DynamicObject receiver, Object value) {
58 try {
59 // if this assumption fails, the object needs to be updated to a valid shape
60 oldShape.getValidAssumption().check();
61 newShape.getValidAssumption().check();
62 } catch (InvalidAssumptionException e) {
63 this.replace(next).executeObject(receiver, value);
64 return;
65 }
66
67 boolean condition = oldShape.check(receiver) && checkValue(receiver, value);
68
69 if (condition) {
70 executeObjectUnchecked(receiver, value);
71 } else {
72 next.executeObject(receiver, value);
73 }
74 }
75
76 @Override
77 public final void executeLong(DynamicObject receiver, long value) {
78 try {
79 // if this assumption fails, the object needs to be updated to a valid shape
80 oldShape.getValidAssumption().check();
81 newShape.getValidAssumption().check();
82 } catch (InvalidAssumptionException e) {
83 this.replace(next).executeLong(receiver, value);
84 return;
85 }
86
87 boolean condition = oldShape.check(receiver) && checkValue(receiver, value);
88
89 if (condition) {
90 executeLongUnchecked(receiver, value);
91 } else {
92 next.executeLong(receiver, value);
93 }
94 }
95
96 @Override
97 public final void executeBoolean(DynamicObject receiver, boolean value) {
98 try {
99 // if this assumption fails, the object needs to be updated to a valid shape
100 oldShape.getValidAssumption().check();
101 newShape.getValidAssumption().check();
102 } catch (InvalidAssumptionException e) {
103 this.replace(next).executeBoolean(receiver, value);
104 return;
105 }
106
107 boolean condition = oldShape.check(receiver) && checkValue(receiver, value);
108
109 if (condition) {
110 executeBooleanUnchecked(receiver, value);
111 } else {
112 next.executeBoolean(receiver, value);
113 }
114 }
115
116 @SuppressWarnings("unused")
117 protected boolean checkValue(DynamicObject receiver, Object value) {
118 return true;
119 }
120
121 protected abstract void executeObjectUnchecked(DynamicObject receiver, Object value);
122
123 protected void executeLongUnchecked(DynamicObject receiver, long value) {
124 executeObjectUnchecked(receiver, value);
125 }
126
127 protected void executeBooleanUnchecked(DynamicObject receiver, boolean value) {
128 executeObjectUnchecked(receiver, value);
129 }
130 }
131
132 protected static class SLWriteObjectPropertyNode extends SLWritePropertyCacheChainNode {
133 private final Location location;
134
135 protected SLWriteObjectPropertyNode(Shape oldShape, Shape newShape, Location location, SLWritePropertyCacheNode next) {
136 super(oldShape, newShape, next);
137 this.location = location;
138 }
139
140 @Override
141 protected void executeObjectUnchecked(DynamicObject receiver, Object value) {
142 try {
143 if (oldShape == newShape) {
144 location.set(receiver, value, oldShape);
145 } else {
146 location.set(receiver, value, oldShape, newShape);
147 }
148 } catch (IncompatibleLocationException | FinalLocationException e) {
149 replace(next).executeObject(receiver, value);
150 }
151 }
152
153 @Override
154 protected boolean checkValue(DynamicObject receiver, Object value) {
155 return location.canSet(receiver, value);
156 }
157 }
158
159 protected static class SLWriteBooleanPropertyNode extends SLWritePropertyCacheChainNode {
160 private final BooleanLocation location;
161
162 protected SLWriteBooleanPropertyNode(Shape oldShape, Shape newShape, BooleanLocation location, SLWritePropertyCacheNode next) {
163 super(oldShape, newShape, next);
164 this.location = location;
165 }
166
167 @Override
168 protected void executeObjectUnchecked(DynamicObject receiver, Object value) {
169 try {
170 if (oldShape == newShape) {
171 location.set(receiver, value, oldShape);
172 } else {
173 location.set(receiver, value, oldShape, newShape);
174 }
175 } catch (IncompatibleLocationException | FinalLocationException e) {
176 replace(next).executeObject(receiver, value);
177 }
178 }
179
180 @Override
181 protected void executeBooleanUnchecked(DynamicObject receiver, boolean value) {
182 try {
183 if (oldShape == newShape) {
184 location.setBoolean(receiver, value, oldShape);
185 } else {
186 location.setBoolean(receiver, value, oldShape, newShape);
187 }
188 } catch (FinalLocationException e) {
189 replace(next).executeBoolean(receiver, value);
190 }
191 }
192
193 @Override
194 protected boolean checkValue(DynamicObject receiver, Object value) {
195 return value instanceof Boolean;
196 }
197 }
198
199 protected static class SLWriteLongPropertyNode extends SLWritePropertyCacheChainNode {
200 private final LongLocation location;
201
202 protected SLWriteLongPropertyNode(Shape oldShape, Shape newShape, LongLocation location, SLWritePropertyCacheNode next) {
203 super(oldShape, newShape, next);
204 this.location = location;
205 }
206
207 @Override
208 protected void executeObjectUnchecked(DynamicObject receiver, Object value) {
209 try {
210 if (oldShape == newShape) {
211 location.set(receiver, value, oldShape);
212 } else {
213 location.set(receiver, value, oldShape, newShape);
214 }
215 } catch (IncompatibleLocationException | FinalLocationException e) {
216 replace(next).executeObject(receiver, value);
217 }
218 }
219
220 @Override
221 protected void executeLongUnchecked(DynamicObject receiver, long value) {
222 try {
223 if (oldShape == newShape) {
224 location.setLong(receiver, value, oldShape);
225 } else {
226 location.setLong(receiver, value, oldShape, newShape);
227 }
228 } catch (FinalLocationException e) {
229 replace(next).executeLong(receiver, value);
230 }
231 }
232
233 @Override
234 protected boolean checkValue(DynamicObject receiver, Object value) {
235 return value instanceof Long;
236 }
237 }
238
239 protected static class SLUninitializedWritePropertyNode extends SLWritePropertyCacheNode {
240 protected final String propertyName;
241
242 protected SLUninitializedWritePropertyNode(String propertyName) {
243 this.propertyName = propertyName;
244 }
245
246 @Override
247 public void executeObject(DynamicObject receiver, Object value) {
248 CompilerDirectives.transferToInterpreterAndInvalidate();
249
250 if (receiver.updateShape()) {
251 // shape changed, retry cache again
252 getTopNode().executeObject(receiver, value);
253 return;
254 }
255
256 Shape oldShape = receiver.getShape();
257 Shape newShape;
258 Property property = oldShape.getProperty(propertyName);
259
260 final SLWritePropertyCacheNode resolvedNode;
261 if (property != null && property.getLocation().canSet(receiver, value)) {
262 newShape = oldShape;
263 } else {
264 receiver.define(propertyName, value, 0);
265 newShape = receiver.getShape();
266 property = newShape.getProperty(propertyName);
267 }
268
269 if (property.getLocation() instanceof LongLocation) {
270 resolvedNode = new SLWriteLongPropertyNode(oldShape, newShape, (LongLocation) property.getLocation(), this);
271 } else if (property.getLocation() instanceof BooleanLocation) {
272 resolvedNode = new SLWriteBooleanPropertyNode(oldShape, newShape, (BooleanLocation) property.getLocation(), this);
273 } else {
274 resolvedNode = new SLWriteObjectPropertyNode(oldShape, newShape, property.getLocation(), this);
275 }
276
277 this.replace(resolvedNode, "resolved '" + propertyName + "'").executeObject(receiver, value);
278 }
279
280 private SLWritePropertyCacheNode getTopNode() {
281 SLWritePropertyCacheNode top = this;
282 while (top.getParent() instanceof SLWritePropertyCacheNode) {
283 top = (SLWritePropertyCacheNode) top.getParent();
284 }
285 return top;
286 }
287
288 @Override
289 public void executeLong(DynamicObject receiver, long value) {
290 executeObject(receiver, value);
291 }
292
293 @Override
294 public void executeBoolean(DynamicObject receiver, boolean value) {
295 executeObject(receiver, value);
296 }
297 }
298 }