11package trufflesom .interpreter .nodes ;
22
3- import com .oracle .truffle .api .CompilerAsserts ;
3+ import com .oracle .truffle .api .CallTarget ;
4+ import com .oracle .truffle .api .CompilerDirectives ;
5+ import com .oracle .truffle .api .CompilerDirectives .CompilationFinal ;
46import com .oracle .truffle .api .Truffle ;
57import com .oracle .truffle .api .frame .VirtualFrame ;
68import com .oracle .truffle .api .nodes .DirectCallNode ;
79import com .oracle .truffle .api .nodes .ExplodeLoop ;
10+ import com .oracle .truffle .api .nodes .InvalidAssumptionException ;
811import com .oracle .truffle .api .nodes .NodeCost ;
912import com .oracle .truffle .api .source .SourceSection ;
1013
1114import bd .primitives .Specializer ;
1215import bd .primitives .nodes .PreevaluatedExpression ;
1316import bd .tools .nodes .Invocation ;
14- import trufflesom .interpreter .TruffleCompiler ;
17+ import trufflesom .interpreter .Types ;
1518import trufflesom .interpreter .nodes .dispatch .AbstractDispatchNode ;
16- import trufflesom .interpreter .nodes .dispatch .DispatchChain .Cost ;
19+ import trufflesom .interpreter .nodes .dispatch .AbstractDispatchNode .CachedDispatchNode ;
20+ import trufflesom .interpreter .nodes .dispatch .AbstractDispatchNode .CachedExprNode ;
21+ import trufflesom .interpreter .nodes .dispatch .AbstractDispatchNode .GuardedDispatchNode ;
22+ import trufflesom .interpreter .nodes .dispatch .CachedDnuNode ;
23+ import trufflesom .interpreter .nodes .dispatch .DispatchGuard ;
1724import trufflesom .interpreter .nodes .dispatch .GenericDispatchNode ;
18- import trufflesom .interpreter .nodes .dispatch .UninitializedDispatchNode ;
1925import trufflesom .primitives .Primitives ;
2026import trufflesom .vm .NotYetImplementedException ;
2127import trufflesom .vm .Universe ;
2228import trufflesom .vmobjects .SClass ;
2329import trufflesom .vmobjects .SInvokable ;
30+ import trufflesom .vmobjects .SObject ;
2431import trufflesom .vmobjects .SSymbol ;
2532
2633
@@ -32,8 +39,7 @@ public static ExpressionNode create(final SSymbol selector,
3239 Specializer <Universe , ExpressionNode , SSymbol > specializer =
3340 prims .getParserSpecializer (selector , arguments );
3441 if (specializer == null ) {
35- return new UninitializedMessageSendNode (
36- selector , arguments , universe ).initialize (source );
42+ return new GenericMessageSendNode (selector , arguments , universe ).initialize (source );
3743 }
3844
3945 ExpressionNode newNode = specializer .create (null , arguments , source , universe );
@@ -44,14 +50,14 @@ public static ExpressionNode create(final SSymbol selector,
4450
4551 public static AbstractMessageSendNode createForPerformNodes (final SSymbol selector ,
4652 final SourceSection source , final Universe universe ) {
47- return new UninitializedMessageSendNode (selector , NO_ARGS , universe ).initialize (source );
53+ return new GenericMessageSendNode (selector , NO_ARGS , universe ).initialize (source );
4854 }
4955
5056 public static GenericMessageSendNode createGeneric (final SSymbol selector ,
5157 final ExpressionNode [] argumentNodes , final SourceSection source ,
5258 final Universe universe ) {
53- return new GenericMessageSendNode (selector , argumentNodes ,
54- new UninitializedDispatchNode ( selector , universe ) ).initialize (source );
59+ return new GenericMessageSendNode (
60+ selector , argumentNodes , universe , true ).initialize (source );
5561 }
5662
5763 public static AbstractMessageSendNode createSuperSend (final SClass superClass ,
@@ -102,109 +108,171 @@ private Object[] evaluateArguments(final VirtualFrame frame) {
102108 public abstract int getNumberOfArguments ();
103109 }
104110
105- public static final class UninitializedMessageSendNode extends AbstractMessageSendNode {
111+ public static final class GenericMessageSendNode
112+ extends AbstractMessageSendNode {
113+
114+ private final SSymbol selector ;
115+ private final Universe universe ;
116+
117+ private final int numberOfSignatureArguments ;
118+
119+ @ CompilationFinal private boolean triedEager ;
106120
107- protected final SSymbol selector ;
108- protected final Universe universe ;
121+ @ Child private GuardedDispatchNode dispatchCache ;
109122
110- protected UninitializedMessageSendNode (final SSymbol selector ,
111- final ExpressionNode [] arguments , final Universe universe ) {
123+ private GenericMessageSendNode (final SSymbol selector , final ExpressionNode [] arguments ,
124+ final Universe universe , final boolean triedEager ) {
112125 super (arguments );
113126 this .selector = selector ;
114127 this .universe = universe ;
128+ this .triedEager = triedEager ;
129+ this .numberOfSignatureArguments = selector .getNumberOfSignatureArguments ();
115130 }
116131
117- @ Override
118- public String toString ( ) {
119- return getClass (). getSimpleName () + "(" + selector . getString () + ")" ;
132+ private GenericMessageSendNode ( final SSymbol selector , final ExpressionNode [] arguments ,
133+ final Universe universe ) {
134+ this ( selector , arguments , universe , false ) ;
120135 }
121136
122137 @ Override
123- public Object doPreEvaluated (final VirtualFrame frame , final Object [] arguments ) {
124- return specialize (arguments ).doPreEvaluated (frame , arguments );
125- }
126-
127- private PreevaluatedExpression specialize (final Object [] arguments ) {
128- TruffleCompiler .transferToInterpreterAndInvalidate ("Specialize Message Node" );
129-
130- // We treat super sends separately for simplicity, might not be the
131- // optimal solution, especially in cases were the knowledge of the
132- // receiver class also allows us to do more specific things, but for the
133- // moment we will leave it at this.
134- // TODO: revisit, and also do more specific optimizations for super sends.
135-
136- Primitives prims = universe .getPrimitives ();
137-
138- Specializer <Universe , ExpressionNode , SSymbol > specializer =
139- prims .getEagerSpecializer (selector , arguments , argumentNodes );
140-
141- if (specializer != null ) {
142- PreevaluatedExpression newNode =
143- (PreevaluatedExpression ) specializer .create (arguments , argumentNodes ,
144- sourceSection , universe );
138+ @ ExplodeLoop
139+ public Object doPreEvaluated (final VirtualFrame frame ,
140+ final Object [] arguments ) {
145141
146- return (PreevaluatedExpression ) replace ((ExpressionNode ) newNode );
142+ GuardedDispatchNode cache = dispatchCache ;
143+
144+ Object rcvr = arguments [0 ];
145+
146+ while (cache != null ) {
147+ try {
148+ if (cache .entryMatches (rcvr )) {
149+ return cache .doPreEvaluated (frame , arguments );
150+ }
151+ } catch (InvalidAssumptionException e ) {
152+ // Remove invalid node from dispatch chain
153+ CompilerDirectives .transferToInterpreterAndInvalidate ();
154+ if (cache .getParent () == this ) {
155+ if (cache .next == null ) {
156+ dispatchCache = null ;
157+ cache = null ;
158+ } else {
159+ dispatchCache = insert (cache .next );
160+ cache = cache .next ;
161+ }
162+ } else {
163+ GuardedDispatchNode parent = (GuardedDispatchNode ) cache .getParent ();
164+ if (cache .next == null ) {
165+ parent .next = null ;
166+ cache = null ;
167+ } else {
168+ parent .next = insert (cache .next );
169+ cache = cache .next ;
170+ }
171+ }
172+ continue ;
173+ }
174+ // cache guard
175+ // --> apply cache
176+ cache = cache .next ;
147177 }
148178
149- return makeGenericSend ();
150- }
179+ CompilerDirectives .transferToInterpreterAndInvalidate ();
151180
152- private GenericMessageSendNode makeGenericSend () {
153- GenericMessageSendNode send = new GenericMessageSendNode (selector , argumentNodes ,
154- new UninitializedDispatchNode (selector , universe )).initialize (sourceSection );
155- return replace (send );
181+ return specialize (arguments ).doPreEvaluated (frame , arguments );
156182 }
157183
158184 @ Override
159- public SSymbol getInvocationIdentifier () {
160- return selector ;
185+ public String toString () {
186+ return "GMsgSend(" + selector . getString () + ")" ;
161187 }
162188
163189 @ Override
164- public int getNumberOfArguments () {
165- return selector . getNumberOfSignatureArguments () ;
190+ public NodeCost getCost () {
191+ return NodeCost . NONE ;
166192 }
167- }
168193
169- // TODO: currently, we do not only specialize the given stuff above, but also what has been
170- // classified as 'value' sends in the OMOP branch. Is that a problem?
194+ private PreevaluatedExpression specialize (final Object [] arguments ) {
195+ if (!triedEager ) {
196+ triedEager = true ;
197+ PreevaluatedExpression eager = attemptEagerSpecialization (arguments );
198+ if (eager != null ) {
199+ return eager ;
200+ }
201+ }
171202
172- public static final class GenericMessageSendNode
173- extends AbstractMessageSendNode {
203+ final GuardedDispatchNode first = dispatchCache ;
204+ GuardedDispatchNode cache = first ;
205+ int cacheSize = 0 ;
206+ while (cache != null ) {
207+ cache = cache .next ;
208+ cacheSize += 1 ;
209+ }
174210
175- private final SSymbol selector ;
176- private final int numberOfSignatureArguments ;
211+ Object rcvr = arguments [ 0 ] ;
212+ assert rcvr != null ;
177213
178- @ Child private AbstractDispatchNode dispatchNode ;
214+ if (rcvr instanceof SObject ) {
215+ SObject r = (SObject ) rcvr ;
216+ if (r .updateLayoutToMatchClass () && first != null ) {
217+ // if the dispatchCache is null, we end up here, so continue directly below instead
218+ // otherwise, let's retry the cache!
219+ return this ;
220+ }
221+ }
179222
180- private GenericMessageSendNode (final SSymbol selector , final ExpressionNode [] arguments ,
181- final AbstractDispatchNode dispatchNode ) {
182- super (arguments );
183- this .selector = selector ;
184- this .dispatchNode = dispatchNode ;
185- this .numberOfSignatureArguments = selector .getNumberOfSignatureArguments ();
186- }
223+ if (cacheSize < AbstractDispatchNode .INLINE_CACHE_SIZE ) {
224+ SClass rcvrClass = Types .getClassOf (rcvr , universe );
225+ SInvokable method = rcvrClass .lookupInvokable (selector );
226+ CallTarget callTarget = null ;
227+ PreevaluatedExpression expr = null ;
228+ if (method != null ) {
229+ if (method .isTrivial ()) {
230+ expr = method .copyTrivialNode ();
231+ assert expr != null ;
232+ } else {
233+ callTarget = method .getCallTarget ();
234+ }
235+ }
236+
237+ DispatchGuard guard = DispatchGuard .create (rcvr );
238+
239+ GuardedDispatchNode node ;
240+ if (expr != null ) {
241+ node = new CachedExprNode (guard , expr );
242+ } else if (method != null ) {
243+ node = new CachedDispatchNode (guard , callTarget );
244+ } else {
245+ node = new CachedDnuNode (rcvrClass , guard , selector );
246+ }
247+
248+ if (first != null ) {
249+ node .next = node .insertHere (first );
250+ }
251+ dispatchCache = insert (node );
252+ return node ;
253+ }
187254
188- @ Override
189- public Object doPreEvaluated (final VirtualFrame frame ,
190- final Object [] arguments ) {
191- return dispatchNode .executeDispatch (frame , arguments );
255+ // the chain is longer than the maximum defined by INLINE_CACHE_SIZE and
256+ // thus, this callsite is considered to be megaprophic, and we generalize it.
257+ GenericDispatchNode generic = new GenericDispatchNode (selector , universe );
258+ dispatchCache = insert (generic );
259+ return generic ;
192260 }
193261
194- public void replaceDispatchListHead (
195- final GenericDispatchNode replacement ) {
196- CompilerAsserts .neverPartOfCompilation ();
197- dispatchNode .replace (replacement );
198- }
262+ private PreevaluatedExpression attemptEagerSpecialization (final Object [] arguments ) {
263+ Primitives prims = universe .getPrimitives ();
199264
200- @ Override
201- public String toString () {
202- return "GMsgSend(" + selector .getString () + ")" ;
203- }
265+ Specializer <Universe , ExpressionNode , SSymbol > specializer =
266+ prims .getEagerSpecializer (selector , arguments , argumentNodes );
204267
205- @ Override
206- public NodeCost getCost () {
207- return Cost .getCost (dispatchNode );
268+ if (specializer != null ) {
269+ PreevaluatedExpression newNode =
270+ (PreevaluatedExpression ) specializer .create (arguments , argumentNodes ,
271+ sourceSection , universe );
272+
273+ return (PreevaluatedExpression ) replace ((ExpressionNode ) newNode );
274+ }
275+ return null ;
208276 }
209277
210278 @ Override
0 commit comments