|
57 | 57 | import org.graalvm.collections.Pair; |
58 | 58 |
|
59 | 59 | import com.oracle.truffle.api.CompilerAsserts; |
60 | | -import com.oracle.truffle.api.CompilerDirectives; |
61 | 60 | import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; |
62 | 61 | import com.oracle.truffle.api.object.ExtLocations.ObjectLocation; |
63 | 62 | import com.oracle.truffle.api.object.Transition.AbstractReplacePropertyTransition; |
@@ -159,74 +158,53 @@ private static boolean assertLocationInRange(final Shape shape, final Location l |
159 | 158 | } |
160 | 159 |
|
161 | 160 | @TruffleBoundary |
162 | | - static boolean putGeneric(DynamicObject object, Object key, Object value, int newPropertyFlags, int putFlags) { |
163 | | - Shape shape = object.getShape(); |
164 | | - Property existingProperty = shape.getProperty(key); |
165 | | - return putGeneric(object, key, value, newPropertyFlags, putFlags, shape, existingProperty); |
| 161 | + static boolean putGeneric(DynamicObject object, Object key, Object value, int newPropertyFlags, int mode) { |
| 162 | + return putGeneric(object, key, value, newPropertyFlags, mode, null, null); |
166 | 163 | } |
167 | 164 |
|
168 | 165 | @TruffleBoundary |
169 | | - static boolean putGeneric(DynamicObject object, Object key, Object value, int newPropertyFlags, int putFlags, Shape s, Property existingProperty) { |
170 | | - if (existingProperty == null) { |
171 | | - if (Flags.isPutIfPresent(putFlags)) { |
172 | | - return false; |
173 | | - } |
174 | | - } else { |
175 | | - if (Flags.isPutIfAbsent(putFlags)) { |
176 | | - return false; |
177 | | - } else if (!Flags.isUpdateFlags(putFlags) && existingProperty.getLocation().canStore(value)) { |
178 | | - existingProperty.getLocation().setSafe(object, value, false, false); |
179 | | - return true; |
180 | | - } |
181 | | - } |
182 | | - return putGenericSlowPath(object, key, value, newPropertyFlags, putFlags, s, existingProperty); |
183 | | - } |
184 | | - |
185 | | - private static boolean putGenericSlowPath(DynamicObject object, Object key, Object value, int newPropertyFlags, int putFlags, |
186 | | - Shape initialShape, Property propertyOfInitialShape) { |
| 166 | + static boolean putGeneric(DynamicObject object, Object key, Object value, int newPropertyFlags, int mode, |
| 167 | + Shape cachedShape, Property propertyOfCachedShape) { |
187 | 168 | CompilerAsserts.neverPartOfCompilation(); |
188 | 169 | updateShape(object); |
189 | 170 | Shape oldShape; |
190 | 171 | Shape newShape; |
191 | 172 | Property property; |
192 | 173 | do { |
193 | 174 | oldShape = object.getShape(); |
194 | | - final Property existingProperty = reusePropertyLookup(key, initialShape, propertyOfInitialShape, oldShape); |
| 175 | + final Property existingProperty = reusePropertyLookup(key, cachedShape, propertyOfCachedShape, oldShape); |
195 | 176 | if (existingProperty == null) { |
196 | | - if (Flags.isPutIfPresent(putFlags)) { |
| 177 | + if (Flags.isPutIfPresent(mode)) { |
197 | 178 | return false; |
198 | 179 | } else { |
199 | | - newShape = defineProperty(oldShape, key, value, newPropertyFlags, existingProperty, putFlags); |
| 180 | + newShape = defineProperty(oldShape, key, value, newPropertyFlags, null, mode); |
200 | 181 | property = newShape.getProperty(key); |
201 | 182 | } |
202 | | - } else if (Flags.isPutIfAbsent(putFlags)) { |
| 183 | + } else if (Flags.isPutIfAbsent(mode)) { |
203 | 184 | return false; |
204 | | - } else if (Flags.isUpdateFlags(putFlags) && newPropertyFlags != existingProperty.getFlags()) { |
205 | | - newShape = defineProperty(oldShape, key, value, newPropertyFlags, existingProperty, putFlags); |
206 | | - property = newShape.getProperty(key); |
207 | | - } else { |
208 | | - if (existingProperty.getLocation().canStore(value)) { |
| 185 | + } else if (!Flags.isUpdateFlags(mode) || newPropertyFlags == existingProperty.getFlags()) { |
| 186 | + if (existingProperty.getLocation().canStoreValue(value)) { |
209 | 187 | newShape = oldShape; |
210 | 188 | property = existingProperty; |
211 | 189 | } else { |
212 | | - assert !Flags.isUpdateFlags(putFlags) || newPropertyFlags == existingProperty.getFlags(); |
213 | | - newShape = defineProperty(oldShape, key, value, existingProperty.getFlags(), existingProperty, putFlags); |
| 190 | + newShape = defineProperty(oldShape, key, value, existingProperty.getFlags(), existingProperty, mode); |
214 | 191 | property = newShape.getProperty(key); |
215 | 192 | } |
| 193 | + } else { |
| 194 | + newShape = defineProperty(oldShape, key, value, newPropertyFlags, existingProperty, mode); |
| 195 | + property = newShape.getProperty(key); |
216 | 196 | } |
217 | 197 | } while (updateShape(object)); |
218 | 198 |
|
219 | 199 | assert object.getShape() == oldShape; |
| 200 | + assert !Flags.isPutIfAbsent(mode) || oldShape != newShape; |
| 201 | + |
220 | 202 | Location location = property.getLocation(); |
| 203 | + location.setInternal(object, value, false, oldShape, newShape); |
| 204 | + |
221 | 205 | if (oldShape != newShape) { |
222 | | - DynamicObjectSupport.grow(object, oldShape, newShape); |
223 | | - location.setSafe(object, value, false, true); |
224 | 206 | DynamicObjectSupport.setShapeWithStoreFence(object, newShape); |
225 | 207 | updateShape(object); |
226 | | - } else if (Flags.isPutIfAbsent(putFlags)) { |
227 | | - return false; |
228 | | - } else { |
229 | | - location.setSafe(object, value, false, false); |
230 | 208 | } |
231 | 209 | return true; |
232 | 210 | } |
@@ -503,11 +481,15 @@ public String getMessage() { |
503 | 481 | } |
504 | 482 | } |
505 | 483 |
|
506 | | - @TruffleBoundary |
507 | 484 | static boolean updateShape(DynamicObject object) { |
508 | | - boolean changed = checkForObsoleteShapeAndMigrate(object); |
509 | | - // shape should be valid now, but we cannot assert this due to a possible race |
510 | | - return changed; |
| 485 | + return updateShape(object, object.getShape()); |
| 486 | + } |
| 487 | + |
| 488 | + static boolean updateShape(DynamicObject object, Shape currentShape) { |
| 489 | + if (currentShape.isValid()) { |
| 490 | + return false; |
| 491 | + } |
| 492 | + return migrateObsoleteShape(object, currentShape); |
511 | 493 | } |
512 | 494 |
|
513 | 495 | private static Shape ensureValid(Shape newShape) { |
@@ -800,21 +782,14 @@ private static void setPropertyInternal(Property toProperty, DynamicObject toObj |
800 | 782 | toProperty.getLocation().set(toObject, value, false, true); |
801 | 783 | } |
802 | 784 |
|
803 | | - private static boolean checkForObsoleteShapeAndMigrate(DynamicObject store) { |
804 | | - Shape currentShape = store.getShape(); |
805 | | - if (currentShape.isValid()) { |
806 | | - return false; |
807 | | - } |
808 | | - CompilerDirectives.transferToInterpreter(); |
809 | | - return migrateObsoleteShape(currentShape, store); |
810 | | - } |
811 | | - |
812 | | - private static boolean migrateObsoleteShape(Shape currentShape, DynamicObject store) { |
| 785 | + @TruffleBoundary |
| 786 | + private static boolean migrateObsoleteShape(DynamicObject store, Shape currentShape) { |
813 | 787 | CompilerAsserts.neverPartOfCompilation(); |
814 | 788 | synchronized (currentShape.getMutex()) { |
815 | 789 | if (!currentShape.isValid()) { |
816 | 790 | assert !currentShape.isShared(); |
817 | 791 | reshape(store); |
| 792 | + // shape should be valid now, but we cannot assert this due to a possible race |
818 | 793 | return true; |
819 | 794 | } |
820 | 795 | return false; |
|
0 commit comments