UninitializedWriteObjectFieldNode.java

  1. /*
  2.  * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This
  3.  * code is released under a tri EPL/GPL/LGPL license. You can use it,
  4.  * redistribute it and/or modify it under the terms of the:
  5.  *
  6.  * Eclipse Public License version 1.0
  7.  * GNU General Public License version 2
  8.  * GNU Lesser General Public License version 2.1
  9.  */
  10. package org.jruby.truffle.nodes.objectstorage;

  11. import com.oracle.truffle.api.CompilerDirectives;
  12. import com.oracle.truffle.api.nodes.NodeCost;
  13. import com.oracle.truffle.api.nodes.NodeInfo;
  14. import com.oracle.truffle.api.object.*;
  15. import org.jruby.truffle.runtime.core.RubyBasicObject;

  16. @NodeInfo(cost = NodeCost.UNINITIALIZED)
  17. public class UninitializedWriteObjectFieldNode extends WriteObjectFieldNode {

  18.     private final Object name;
  19.     public UninitializedWriteObjectFieldNode(Object name) {
  20.         this.name = name;

  21.     }

  22.     @Override
  23.     public void execute(RubyBasicObject object, Object value) {
  24.         CompilerDirectives.transferToInterpreterAndInvalidate();

  25.         final Shape currentShape = object.getDynamicObject().getShape();

  26.         // If the current shape is obsolete, add a node to migrate
  27.         if (object.getDynamicObject().updateShape()) {
  28.             final MigrateNode migrateNode = new MigrateNode(currentShape, this);
  29.             replace(migrateNode);
  30.             migrateNode.execute(object, value);
  31.             return;
  32.         }

  33.         final Shape newShape;
  34.         Location location;

  35.         final Property currentProperty = currentShape.getProperty(name);
  36.         final Property newProperty;

  37.         if (currentProperty != null && currentProperty.getLocation().canSet(object.getDynamicObject(), value)) {
  38.             newShape = currentShape;
  39.             newProperty = currentProperty;
  40.             newProperty.setSafe(object.getDynamicObject(), value, null);
  41.         } else {
  42.             object.getOperations().setInstanceVariable(object, name, value);
  43.             newShape = object.getDynamicObject().getShape();
  44.             newProperty = newShape.getProperty(name);

  45.             if (newProperty == null) {
  46.                 throw new IllegalStateException("Property missing from object's shape even after setting it");
  47.             }
  48.         }

  49.         location = newProperty.getLocation();
  50.         assert location.canSet(object.getDynamicObject(), value);

  51.         final WriteObjectFieldChainNode writeNode;

  52.         if (location instanceof BooleanLocation) {
  53.             writeNode = new WriteBooleanObjectFieldNode(currentShape, newShape, (BooleanLocation) location, this);
  54.         } else if (location instanceof IntLocation) {
  55.             writeNode = new WriteIntegerObjectFieldNode(currentShape, newShape, (IntLocation) location, this);
  56.         } else if (location instanceof LongLocation) {
  57.             writeNode = new WriteLongObjectFieldNode(currentShape, newShape, (LongLocation) location, this);
  58.         } else if (location instanceof DoubleLocation) {
  59.             writeNode = new WriteDoubleObjectFieldNode(currentShape, newShape, (DoubleLocation) location, this);
  60.         } else {
  61.             writeNode = new WriteObjectObjectFieldNode(currentShape, newShape, location, this);
  62.         }

  63.         replace(writeNode, "adding new write object field node to chain");
  64.         // not executing, value is already set
  65.     }

  66. }