1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
package com.seaofnodes.simple.node;
import com.seaofnodes.print.ExprPrinter;
import com.seaofnodes.simple.type.*;
import com.seaofnodes.simple.util.*;
import java.util.HashMap;
import java.util.IdentityHashMap;
/**
* Merge public and private aliases.
* 0 - control
* 1 - private pointer
* 2 - private alias
* 3 - public alias
*/
public class EscapeNode extends TypeNode {
public EscapeNode(Field fld, Node self, Node priv, Node pub ) {
super(fld,null,self,priv,pub);
}
public EscapeNode(EscapeNode esc ) {
super(esc); // Copy constructor
// Except we do not want/need self ptr past Opto.
// *NOTE* the weird direct stomp; this is correct because this
// constructor does NOT set the backedges, because it is used to
// copy-construct an entire graph and ALL edges will get rewritten.
_inputs.set(1,null);
_con = esc._con;
}
// Pointer to some private (unescaped) memory from a NewNode
public Node self() { return in(1); }
public Node priv() { return in(2); }
public Node pub () { return in(3); }
public Field fld() { return (Field)_con; }
@Override public Tag serialTag() { return Tag.Escape; }
@Override public void packed( BAOS baos, HashMap<String,Integer> strs, HashMap<Type,Integer> types, IdentityHashMap<Node, Integer> anodes ) {
baos.packed2(types.get(_con));
}
static Node make( BAOS bais, Type[] types) {
return new EscapeNode((Field)types[bais.packed2()], null,null,null);
}
@Override
protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) {
p.p("Esc#").p(fld()._alias).p(" {");
if( self()==null ) p.p("---");
else p.n(self()).p(",");
p.n(priv()).p("}, ");
p.n(pub ());
return p;
}
@Override
public Type compute() {
if( priv()._type.isHigh() ) return TypeMem.TOP;
if( pub ()._type.isHigh() ) return TypeMem.TOP;
TypeMem mpriv = (TypeMem)priv()._type;
TypeMem mpub = (TypeMem)pub ()._type;
// Private memory comes from an allocation or other non-aliased source.
// Public memory comes from anywhere, might be bulk memory with a very weak mem type.
Field fld = fld();
assert mpriv._alias==1 || mpriv._alias==fld._alias;
assert mpub ._alias==1 || mpub ._alias==fld._alias;
Type tpriv = mpriv._t instanceof TypeStruct ts && ts.findAlias(fld._alias)!=-1
? ts.at(ts.findAlias(fld._alias))._t
: mpriv._t;
assert !(mpub._t instanceof TypeStruct); // Never expect this, but if it starts to happen, need to optimize
Type tpub = mpub._t;
// t is meet of pub & priv. Pub memory can be very weak (e.g. alias 1)
// and we're no worse than the declared field type
Type t = tpriv.meet(tpub).join(fld._t);
int[] fidxes = XInt.meet(mpriv._escFs, mpub._escFs);
int[] aliases = XInt.meet(mpriv._escAs, mpub._escAs);
return TypeMem.make(fld._alias, t, false, false, fld._final, fidxes, aliases).escapesFrom(t);
}
@Override public Node idealize() {
// Sharpen private memory input
if( priv() instanceof MemMergeNode mmm ) {
setDef(2,mmm.alias(fld()._alias));
return this;
}
// Sharpen public memory input
if( pub() instanceof MemMergeNode mmm ) {
setDef(3,mmm.alias(fld()._alias));
return this;
}
// New allocation is dead
if( self()._type.isHigh() )
if( pub()._type.isa(_type) ) return pub();
else addDep(pub());
return null;
}
// Upgrade the internal type
@Override boolean _upgradeType( HashMap<String,Type> TYPES) {
Type t = _con.upgradeType(TYPES);
if( t == _con ) return false;
unlock(); // Unlock before changing _con
_con = t;
return true;
}
@Override public boolean eq(Node n) {
if( fld()._alias!=((EscapeNode)n).fld()._alias )
return false;
assert _con == ((EscapeNode)n)._con;
return true;
}
@Override int hash() { return _con.hashCode(); }
}
|