|
20 | 20 | import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; |
21 | 21 | import com.oracle.truffle.api.dsl.Cached; |
22 | 22 | import com.oracle.truffle.api.dsl.Fallback; |
| 23 | +import com.oracle.truffle.api.dsl.ImportStatic; |
23 | 24 | import com.oracle.truffle.api.dsl.Specialization; |
24 | 25 | import com.oracle.truffle.api.frame.Frame; |
25 | 26 | import com.oracle.truffle.api.frame.FrameDescriptor; |
@@ -2057,6 +2058,81 @@ protected boolean isParametric() { |
2057 | 2058 | } |
2058 | 2059 | } |
2059 | 2060 |
|
| 2061 | + @ImportStatic(BaseModule.class) |
| 2062 | + public abstract static class ReferenceTypeNode extends ObjectSlotTypeNode { |
| 2063 | + private TypeNode referentTypeNode; |
| 2064 | + @Child private ExpressionNode getModuleNode; |
| 2065 | + |
| 2066 | + public ReferenceTypeNode(SourceSection sourceSection, TypeNode referentTypeNode) { |
| 2067 | + super(sourceSection); |
| 2068 | + this.referentTypeNode = referentTypeNode; |
| 2069 | + this.getModuleNode = new GetModuleNode(sourceSection); |
| 2070 | + } |
| 2071 | + |
| 2072 | + @SuppressWarnings("unused") |
| 2073 | + @Specialization(guards = "value.getVmClass() == getReferenceClass()") |
| 2074 | + protected Object eval(VirtualFrame frame, VmReference value) { |
| 2075 | + if (referentTypeNode.isNoopTypeCheck()) { |
| 2076 | + return value; |
| 2077 | + } |
| 2078 | + |
| 2079 | + var module = (VmTyped) getModuleNode.executeGeneric(frame); |
| 2080 | + if (value.checkType(TypeNode.export(referentTypeNode), module.getVmClass().export())) { |
| 2081 | + return value; |
| 2082 | + } |
| 2083 | + // TODO better exceptions? |
| 2084 | + throw new VmExceptionBuilder() |
| 2085 | + .adhocEvalError( |
| 2086 | + "reference type mismatch Reference<%s> and %s", |
| 2087 | + value.getCandidateTypes(), TypeNode.export(referentTypeNode)) |
| 2088 | + .build(); |
| 2089 | + } |
| 2090 | + |
| 2091 | + @Fallback |
| 2092 | + protected Object fallback(Object value) { |
| 2093 | + throw typeMismatch(value, BaseModule.getReferenceClass()); |
| 2094 | + } |
| 2095 | + |
| 2096 | + @Override |
| 2097 | + protected boolean acceptTypeNode(boolean visitTypeArguments, TypeNodeConsumer consumer) { |
| 2098 | + if (visitTypeArguments) return consumer.accept(this) && consumer.accept(referentTypeNode); |
| 2099 | + return consumer.accept(this); |
| 2100 | + } |
| 2101 | + |
| 2102 | + @Override |
| 2103 | + public VmClass getVmClass() { |
| 2104 | + return BaseModule.getReferenceClass(); |
| 2105 | + } |
| 2106 | + |
| 2107 | + @Override |
| 2108 | + public VmList getTypeArgumentMirrors() { |
| 2109 | + return VmList.of(referentTypeNode.getMirror()); |
| 2110 | + } |
| 2111 | + |
| 2112 | + @Override |
| 2113 | + protected boolean doIsEquivalentTo(TypeNode other) { |
| 2114 | + if (!(other instanceof ReferenceTypeNode referenceTypeNode)) { |
| 2115 | + return false; |
| 2116 | + } |
| 2117 | + return referentTypeNode.isEquivalentTo(referenceTypeNode.referentTypeNode); |
| 2118 | + } |
| 2119 | + |
| 2120 | + @Override |
| 2121 | + public boolean isNoopTypeCheck() { |
| 2122 | + return referentTypeNode.isNoopTypeCheck(); |
| 2123 | + } |
| 2124 | + |
| 2125 | + @Override |
| 2126 | + protected PType doExport() { |
| 2127 | + return new PType.Class(BaseModule.getReferenceClass().export(), referentTypeNode.doExport()); |
| 2128 | + } |
| 2129 | + |
| 2130 | + @Override |
| 2131 | + protected boolean isParametric() { |
| 2132 | + return true; |
| 2133 | + } |
| 2134 | + } |
| 2135 | + |
2060 | 2136 | public static final class PairTypeNode extends ObjectSlotTypeNode { |
2061 | 2137 | @Child private TypeNode firstTypeNode; |
2062 | 2138 | @Child private TypeNode secondTypeNode; |
|
0 commit comments