Mercurial > hg > truffle
comparison truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/ObjectAccessNode.java @ 22123:329fe954f6f2
Can compile Truffle API with following javac lints: -Xlint:all,-auxiliaryclass,-try,-processing
author | Jaroslav Tulach <jaroslav.tulach@oracle.com> |
---|---|
date | Wed, 02 Sep 2015 13:15:51 +0200 |
parents | 6203830a4f9a |
children | dc83cc1f94f2 |
comparison
equal
deleted
inserted
replaced
22122:ac017ff52c07 | 22123:329fe954f6f2 |
---|---|
22 * or visit www.oracle.com if you need additional information or have any | 22 * or visit www.oracle.com if you need additional information or have any |
23 * questions. | 23 * questions. |
24 */ | 24 */ |
25 package com.oracle.truffle.api.interop; | 25 package com.oracle.truffle.api.interop; |
26 | 26 |
27 import com.oracle.truffle.api.*; | |
28 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; | |
29 import com.oracle.truffle.api.frame.*; | 27 import com.oracle.truffle.api.frame.*; |
30 import com.oracle.truffle.api.nodes.*; | 28 import com.oracle.truffle.api.nodes.*; |
31 | 29 |
32 abstract class ObjectAccessNode extends Node { | 30 abstract class ObjectAccessNode extends Node { |
33 | 31 |
34 public abstract Object executeWith(VirtualFrame frame, TruffleObject receiver, Object[] arguments); | 32 public abstract Object executeWith(VirtualFrame frame, TruffleObject receiver, Object[] arguments); |
35 | 33 |
36 } | 34 } |
37 | |
38 class UnresolvedObjectAccessNode extends ObjectAccessNode { | |
39 | |
40 private static final int CACHE_SIZE = 8; | |
41 private int cacheLength = 1; | |
42 | |
43 @Override | |
44 public Object executeWith(VirtualFrame frame, TruffleObject receiver, Object[] arguments) { | |
45 CompilerDirectives.transferToInterpreterAndInvalidate(); | |
46 ForeignObjectAccessHeadNode nthParent = (ForeignObjectAccessHeadNode) NodeUtil.getNthParent(this, cacheLength); | |
47 ObjectAccessNode first = nthParent.getFirst(); | |
48 if (cacheLength < CACHE_SIZE) { | |
49 CachedObjectAccessNode createCachedAccess = createCachedAccess(receiver, nthParent.getAccessTree(), first); | |
50 cacheLength++; | |
51 return first.replace(createCachedAccess).executeWith(frame, receiver, arguments); | |
52 } else { | |
53 return first.replace(createGenericAccess(nthParent.getAccessTree())).executeWith(frame, receiver, arguments); | |
54 } | |
55 } | |
56 | |
57 private static CachedObjectAccessNode createCachedAccess(TruffleObject receiver, Message accessTree, ObjectAccessNode next) { | |
58 ForeignAccess fa = receiver.getForeignAccess(); | |
59 final CallTarget ct = fa.access(accessTree); | |
60 if (ct == null) { | |
61 throw new IllegalArgumentException("Message " + accessTree + " not recognized by " + fa); | |
62 } | |
63 return new CachedObjectAccessNode(Truffle.getRuntime().createDirectCallNode(ct), next, fa); | |
64 } | |
65 | |
66 private static GenericObjectAccessNode createGenericAccess(Message access) { | |
67 return new GenericObjectAccessNode(access); | |
68 } | |
69 } | |
70 | |
71 class GenericObjectAccessNode extends ObjectAccessNode { | |
72 | |
73 private final Message access; | |
74 @Child private IndirectCallNode indirectCallNode; | |
75 | |
76 public GenericObjectAccessNode(Message access) { | |
77 this.access = access; | |
78 indirectCallNode = Truffle.getRuntime().createIndirectCallNode(); | |
79 } | |
80 | |
81 public GenericObjectAccessNode(GenericObjectAccessNode prev) { | |
82 this(prev.access); | |
83 } | |
84 | |
85 @Override | |
86 public Object executeWith(VirtualFrame frame, TruffleObject truffleObject, Object[] arguments) { | |
87 final ForeignAccess fa = truffleObject.getForeignAccess(); | |
88 final CallTarget ct = fa.access(access); | |
89 if (ct == null) { | |
90 throw messageNotRecognizedException(fa); | |
91 } | |
92 return indirectCallNode.call(frame, ct, ForeignAccessArguments.create(truffleObject, arguments)); | |
93 } | |
94 | |
95 @TruffleBoundary | |
96 private RuntimeException messageNotRecognizedException(final ForeignAccess fa) { | |
97 throw new IllegalStateException("Message " + access + " not recognized by " + fa); | |
98 } | |
99 } | |
100 | |
101 class CachedObjectAccessNode extends ObjectAccessNode { | |
102 @Child private DirectCallNode callTarget; | |
103 @Child private ObjectAccessNode next; | |
104 | |
105 private final ForeignAccess languageCheck; | |
106 | |
107 protected CachedObjectAccessNode(DirectCallNode callTarget, ObjectAccessNode next, ForeignAccess languageCheck) { | |
108 this.callTarget = callTarget; | |
109 this.next = next; | |
110 this.languageCheck = languageCheck; | |
111 this.callTarget.forceInlining(); | |
112 } | |
113 | |
114 protected CachedObjectAccessNode(CachedObjectAccessNode prev) { | |
115 this(prev.callTarget, prev.next, prev.languageCheck); | |
116 } | |
117 | |
118 @Override | |
119 public Object executeWith(VirtualFrame frame, TruffleObject receiver, Object[] arguments) { | |
120 return doAccess(frame, receiver, arguments); | |
121 } | |
122 | |
123 private Object doAccess(VirtualFrame frame, TruffleObject receiver, Object[] arguments) { | |
124 if (languageCheck.canHandle(receiver)) { | |
125 return callTarget.call(frame, ForeignAccessArguments.create(receiver, arguments)); | |
126 } else { | |
127 return doNext(frame, receiver, arguments); | |
128 } | |
129 } | |
130 | |
131 private Object doNext(VirtualFrame frame, TruffleObject receiver, Object[] arguments) { | |
132 return next.executeWith(frame, receiver, arguments); | |
133 } | |
134 } |