38
38
39
39
import com .oracle .graal .pointsto .BigBang ;
40
40
import com .oracle .graal .pointsto .meta .AnalysisField ;
41
+ import com .oracle .graal .pointsto .meta .AnalysisMetaAccess ;
41
42
import com .oracle .graal .pointsto .meta .AnalysisMethod ;
42
43
import com .oracle .graal .pointsto .meta .AnalysisType ;
43
44
import com .oracle .svm .core .ParsingReason ;
44
45
import com .oracle .svm .core .feature .AutomaticallyRegisteredFeature ;
45
46
import com .oracle .svm .core .feature .InternalFeature ;
47
+ import com .oracle .svm .core .nodes .SubstrateMethodCallTargetNode ;
46
48
import com .oracle .svm .hosted .FeatureImpl ;
47
49
import com .oracle .svm .hosted .ImageClassLoader ;
48
- import com .oracle .svm .hosted .webimage .JSObjectAccessFeature ;
49
50
import com .oracle .svm .hosted .webimage .codegen .node .InterceptJSInvokeNode ;
50
51
import com .oracle .svm .hosted .webimage .codegen .oop .ClassWithMirrorLowerer ;
52
+ import com .oracle .svm .hosted .webimage .js .JSObjectAccessMethodSupport ;
51
53
import com .oracle .svm .hosted .webimage .util .ReflectUtil ;
52
54
import com .oracle .svm .util .ReflectionUtil ;
53
55
import com .oracle .svm .webimage .api .Nothing ;
54
56
import com .oracle .svm .webimage .platform .WebImageJSPlatform ;
55
57
56
- import jdk .graal .compiler .core .common .spi .ForeignCallDescriptor ;
57
- import jdk .graal .compiler .core .common .type .Stamp ;
58
58
import jdk .graal .compiler .core .common .type .StampFactory ;
59
- import jdk .graal .compiler .nodes .ConstantNode ;
59
+ import jdk .graal .compiler .core .common .type .StampPair ;
60
+ import jdk .graal .compiler .nodes .CallTargetNode ;
60
61
import jdk .graal .compiler .nodes .Invoke ;
62
+ import jdk .graal .compiler .nodes .InvokeWithExceptionNode ;
61
63
import jdk .graal .compiler .nodes .ValueNode ;
62
- import jdk .graal .compiler .nodes .extended .ForeignCallNode ;
63
64
import jdk .graal .compiler .nodes .graphbuilderconf .GraphBuilderConfiguration ;
64
65
import jdk .graal .compiler .nodes .graphbuilderconf .GraphBuilderContext ;
65
66
import jdk .graal .compiler .nodes .graphbuilderconf .InlineInvokePlugin ;
@@ -124,7 +125,7 @@ private boolean canBeJavaScriptCall(AnalysisMethod method) {
124
125
125
126
@ Override
126
127
public boolean handleLoadField (GraphBuilderContext b , ValueNode object , ResolvedJavaField field ) {
127
- if (ClassWithMirrorLowerer .isJSObjectSubtype ((( AnalysisType ) field . getDeclaringClass ()). getJavaClass () )) {
128
+ if (ClassWithMirrorLowerer .isFieldRepresentedInJavaScript ( field )) {
128
129
genJSObjectFieldAccess (b , object , field , null );
129
130
return true ;
130
131
}
@@ -133,44 +134,55 @@ public boolean handleLoadField(GraphBuilderContext b, ValueNode object, Resolved
133
134
134
135
@ Override
135
136
public boolean handleStoreField (GraphBuilderContext b , ValueNode object , ResolvedJavaField field , ValueNode value ) {
136
- if (ClassWithMirrorLowerer .isJSObjectSubtype ((( AnalysisType ) field . getDeclaringClass ()). getJavaClass () )) {
137
+ if (ClassWithMirrorLowerer .isFieldRepresentedInJavaScript ( field )) {
137
138
genJSObjectFieldAccess (b , object , field , value );
138
139
return true ;
139
140
}
140
141
return false ;
141
142
}
142
143
143
- private void genJSObjectFieldAccess (GraphBuilderContext b , ValueNode object , ResolvedJavaField field , ValueNode valueForStore ) {
144
- ResolvedJavaType fieldType = field .getType ().resolve (null );
145
- JavaKind fieldKind = fieldType .getJavaKind ();
146
- ConstantNode fieldNameNode = ConstantNode .forConstant (b .getConstantReflection ().forString (field .getName ()), b .getMetaAccess (), b .getGraph ());
144
+ /**
145
+ * Replaces an access to {@link JSObject} fields with a call to an
146
+ * {@link com.oracle.svm.hosted.webimage.js.JSObjectAccessMethod accessor method} that
147
+ * performs the access on the underlying JavaScript object.
148
+ *
149
+ * @param valueForStore If {@code null} is this a load. Otherwise, the value to be
150
+ * written into the field.
151
+ * @see JSObjectAccessMethodSupport
152
+ */
153
+ private static void genJSObjectFieldAccess (GraphBuilderContext b , ValueNode object , ResolvedJavaField field , ValueNode valueForStore ) {
154
+ AnalysisMetaAccess metaAccess = (AnalysisMetaAccess ) b .getMetaAccess ();
155
+ AnalysisField analysisField = (AnalysisField ) field ;
147
156
148
157
boolean isLoad = valueForStore == null ;
149
158
150
- ForeignCallDescriptor bridgeMethod ;
159
+ AnalysisMethod accessMethod ;
151
160
ValueNode [] arguments ;
152
161
if (isLoad ) {
153
- // This is a load access.
154
- bridgeMethod = JSObjectAccessFeature .GETTERS .get (fieldKind );
155
- arguments = new ValueNode []{object , fieldNameNode };
162
+ accessMethod = JSObjectAccessMethodSupport .singleton ().lookupLoadMethod (metaAccess , analysisField );
163
+ arguments = new ValueNode []{object };
156
164
} else {
157
- // This is a store access.
158
- bridgeMethod = JSObjectAccessFeature .SETTERS .get (fieldKind );
159
- arguments = new ValueNode []{object , fieldNameNode , valueForStore };
165
+ accessMethod = JSObjectAccessMethodSupport .singleton ().lookupStoreMethod (metaAccess , analysisField );
166
+ arguments = new ValueNode []{object , valueForStore };
160
167
}
161
- ValueNode access = new ForeignCallNode (bridgeMethod , arguments );
168
+
169
+ JavaKind returnKind = accessMethod .getSignature ().getReturnType ().getJavaKind ();
170
+ StampPair returnStamp = StampPair .createSingle (StampFactory .forKind (returnKind ));
171
+
172
+ SubstrateMethodCallTargetNode callTarget = new SubstrateMethodCallTargetNode (CallTargetNode .InvokeKind .Static , accessMethod , arguments , returnStamp );
173
+ /*
174
+ * Just use a null exception edge. The GraphBuilderContext takes care of wiring it
175
+ * up correctly. The exception edge is needed because the access may produce an
176
+ * exception during conversions, especially loads, which can cause a
177
+ * ClassCastException if JavaScript code stored a value with the wrong type in the
178
+ * field.
179
+ */
180
+ InvokeWithExceptionNode invoke = new InvokeWithExceptionNode (callTarget , null , b .bci ());
181
+
162
182
if (isLoad ) {
163
- b .addPush (fieldKind , access );
164
- // A checkcast is necessary to guard against invalid assignments in JavaScript
165
- // code.
166
- if (fieldKind .isObject ()) {
167
- b .pop (fieldKind );
168
- Stamp classStamp = StampFactory .forDeclaredType (null , b .getMetaAccess ().lookupJavaType (Class .class ), true ).getTrustedStamp ();
169
- ConstantNode classConstant = b .add (new ConstantNode (b .getConstantReflection ().asObjectHub (fieldType .resolve (null )), classStamp ));
170
- b .genCheckcastDynamic (access , classConstant );
171
- }
183
+ b .addPush (returnKind , invoke );
172
184
} else {
173
- b .add (access );
185
+ b .add (invoke );
174
186
}
175
187
}
176
188
});
0 commit comments