package org.mozartoz.truffle.nodes.local;

import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.ImportStatic;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.Frame;
import com.oracle.truffle.api.frame.FrameSlot;
import com.oracle.truffle.api.frame.FrameUtil;
import com.oracle.truffle.api.nodes.Node;

@ImportStatic(FrameUtil.class)
public abstract class CachingReadFrameSlotNode extends Node implements FrameSlotNode {

	@Child ReadFrameSlotNode readFrameSlotNode;

	public CachingReadFrameSlotNode(FrameSlot slot) {
		this.readFrameSlotNode = ReadFrameSlotNodeGen.create(slot);
	}

	public FrameSlot getSlot() {
		return readFrameSlotNode.getSlot();
	}

	public abstract Object executeRead(Frame frame);

	@Specialization(guards = "frame == cachedFrame", limit = "1")
	protected Object readConstant(Frame frame,
			@Cached("frame") Frame cachedFrame,
			@Cached("readFrameSlotNode.executeRead(cachedFrame)") Object cachedValue) {
		return cachedValue;
	}

	@Specialization(replaces = "readConstant")
	protected Object readNotConstant(Frame frame) {
		return readFrameSlotNode.executeRead(frame);
	}

	@Override
	public String toString() {
		return readFrameSlotNode.toString();
	}

}

@@ -36,16 +36,53 @@
 local;%0A%0A
+import java.lang.ref.WeakReference;%0A%0A
 import c
@@ -834,16 +834,25 @@
 rame == 
+getFrame(
 cachedFr
@@ -854,16 +854,17 @@
 hedFrame
+)
 %22, limit
@@ -931,21 +931,50 @@
 ed(%22
+newWeakFrame(
 frame
+)
 %22) 
+WeakReference%3C
 Frame
+%3E
  cac
@@ -995,16 +995,27 @@
 Cached(%22
+newWeakRef(
 readFram
@@ -1040,29 +1040,39 @@
 ead(
-cachedF
+f
 rame)
+)
 %22) 
+WeakReference%3C
 Object
+%3E
  cac
@@ -1089,22 +1089,172 @@
 %7B%0A%09%09
-return cachedV
+final Object value = cachedValue.get();%0A%09%09assert value != null; // If one can read a variable, then it has a strong ref to it via parent frame(s) + slots%0A%09%09return v
 alue
@@ -1485,10 +1485,319 @@
 ();%0A%09%7D%0A%0A
+%09protected static WeakReference%3CObject%3E newWeakRef(Object value) %7B%0A%09%09return new WeakReference%3C%3E(value);%0A%09%7D%0A%0A%09protected static WeakReference%3CFrame%3E newWeakFrame(Frame frame) %7B%0A%09%09return new WeakReference%3C%3E(frame);%0A%09%7D%0A%0A%09protected static Frame getFrame(WeakReference%3CFrame%3E weakRef) %7B%0A%09%09return weakRef.get();%0A%09%7D%0A%0A
 %7D%0A

Use WeakReference when caching variable reads so they do not prevent GC