1 /*
2 * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
257 }
258
259 @Override
260 public String getLanguage() {
261 throw new IllegalStateException(getClass().getSimpleName() + " should not be reachable.");
262 }
263 }
264
265 protected class PENonAppendGraphBuilderContext implements GraphBuilderContext {
266 protected final PEMethodScope methodScope;
267 protected final Invoke invoke;
268
269 @Override
270 public ExternalInliningContext getExternalInliningContext() {
271 return new ExternalInliningContext() {
272 @Override
273 public int getInlinedDepth() {
274 int count = 0;
275 PEGraphDecoder.PEMethodScope scope = methodScope;
276 while (scope != null) {
277 if (scope.method.equals(callInlinedMethod)) {
278 count++;
279 }
280 scope = scope.caller;
281 }
282 return count;
283 }
284 };
285 }
286
287 public PENonAppendGraphBuilderContext(PEMethodScope methodScope, Invoke invoke) {
288 this.methodScope = methodScope;
289 this.invoke = invoke;
290 }
291
292 /**
293 * {@link Fold} and {@link NodeIntrinsic} can be deferred during parsing/decoding. Only by
294 * the end of {@linkplain SnippetTemplate#instantiate Snippet instantiation} do they need to
295 * have been processed.
296 *
297 * This is how SVM handles snippets. They are parsed with plugins disabled and then encoded
298 * and stored in the image. When the snippet is needed at runtime the graph is decoded and
299 * the plugins are run during the decoding process. If they aren't handled at this point
300 * then they will never be handled.
301 */
302 @Override
303 public boolean canDeferPlugin(GeneratedInvocationPlugin plugin) {
304 return plugin.getSource().equals(Fold.class) || plugin.getSource().equals(Node.NodeIntrinsic.class);
305 }
306
307 @Override
308 public BailoutException bailout(String string) {
309 BailoutException bailout = new PermanentBailoutException(string);
310 throw GraphUtil.createBailoutException(string, bailout, GraphUtil.approxSourceStackTraceElement(methodScope.getCallerBytecodePosition()));
311 }
312
313 @Override
314 public StampProvider getStampProvider() {
315 return providers.getStampProvider();
316 }
317
318 @Override
319 public MetaAccessProvider getMetaAccess() {
320 return providers.getMetaAccess();
321 }
322
323 @Override
324 public ConstantReflectionProvider getConstantReflection() {
568 }
569
570 @Override
571 public boolean equals(Object obj) {
572 if (obj instanceof SpecialCallTargetCacheKey) {
573 SpecialCallTargetCacheKey key = (SpecialCallTargetCacheKey) obj;
574 return key.invokeKind.equals(this.invokeKind) && key.targetMethod.equals(this.targetMethod) && key.contextType.equals(this.contextType) && key.receiverStamp.equals(this.receiverStamp);
575 }
576 return false;
577 }
578 }
579
580 private final LoopExplosionPlugin loopExplosionPlugin;
581 private final InvocationPlugins invocationPlugins;
582 private final InlineInvokePlugin[] inlineInvokePlugins;
583 private final ParameterPlugin parameterPlugin;
584 private final NodePlugin[] nodePlugins;
585 private final EconomicMap<SpecialCallTargetCacheKey, Object> specialCallTargetCache;
586 private final EconomicMap<ResolvedJavaMethod, Object> invocationPluginCache;
587 private final ResolvedJavaMethod callInlinedMethod;
588 protected final SourceLanguagePositionProvider sourceLanguagePositionProvider;
589
590 public PEGraphDecoder(Architecture architecture, StructuredGraph graph, CoreProviders providers, LoopExplosionPlugin loopExplosionPlugin, InvocationPlugins invocationPlugins,
591 InlineInvokePlugin[] inlineInvokePlugins,
592 ParameterPlugin parameterPlugin,
593 NodePlugin[] nodePlugins, ResolvedJavaMethod callInlinedMethod, SourceLanguagePositionProvider sourceLanguagePositionProvider) {
594 super(architecture, graph, providers, true);
595 this.loopExplosionPlugin = loopExplosionPlugin;
596 this.invocationPlugins = invocationPlugins;
597 this.inlineInvokePlugins = inlineInvokePlugins;
598 this.parameterPlugin = parameterPlugin;
599 this.nodePlugins = nodePlugins;
600 this.specialCallTargetCache = EconomicMap.create(Equivalence.DEFAULT);
601 this.invocationPluginCache = EconomicMap.create(Equivalence.DEFAULT);
602 this.callInlinedMethod = callInlinedMethod;
603 this.sourceLanguagePositionProvider = sourceLanguagePositionProvider;
604 }
605
606 protected static LoopExplosionKind loopExplosionKind(ResolvedJavaMethod method, LoopExplosionPlugin loopExplosionPlugin) {
607 if (loopExplosionPlugin == null) {
608 return LoopExplosionKind.NONE;
609 } else {
610 return loopExplosionPlugin.loopExplosionKind(method);
611 }
612 }
613
614 @SuppressWarnings("try")
615 public void decode(ResolvedJavaMethod method, boolean isSubstitution, boolean trackNodeSourcePosition) {
616 try (DebugContext.Scope scope = debug.scope("PEGraphDecode", graph)) {
617 EncodedGraph encodedGraph = lookupEncodedGraph(method, null, null, isSubstitution, trackNodeSourcePosition);
618 PEMethodScope methodScope = new PEMethodScope(graph, null, null, encodedGraph, method, null, 0, loopExplosionPlugin, null);
619 decode(createInitialLoopScope(methodScope, null));
|
1 /*
2 * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
257 }
258
259 @Override
260 public String getLanguage() {
261 throw new IllegalStateException(getClass().getSimpleName() + " should not be reachable.");
262 }
263 }
264
265 protected class PENonAppendGraphBuilderContext implements GraphBuilderContext {
266 protected final PEMethodScope methodScope;
267 protected final Invoke invoke;
268
269 @Override
270 public ExternalInliningContext getExternalInliningContext() {
271 return new ExternalInliningContext() {
272 @Override
273 public int getInlinedDepth() {
274 int count = 0;
275 PEGraphDecoder.PEMethodScope scope = methodScope;
276 while (scope != null) {
277 if (scope.method.equals(callInlinedMethod) || scope.method.equals(callInlinedAgnosticMethod)) {
278 count++;
279 }
280 scope = scope.caller;
281 }
282 return count;
283 }
284 };
285 }
286
287 public PENonAppendGraphBuilderContext(PEMethodScope methodScope, Invoke invoke) {
288 this.methodScope = methodScope;
289 this.invoke = invoke;
290 }
291
292 /**
293 * {@link Fold} and {@link NodeIntrinsic} can be deferred during parsing/decoding. Only by
294 * the end of {@linkplain SnippetTemplate#instantiate Snippet instantiation} do they need to
295 * have been processed.
296 *
297 * This is how SVM handles snippets. They are parsed with plugins disabled and then encoded
298 * and stored in the image. When the snippet is needed at runtime the graph is decoded and
299 * the plugins are run during the decoding process. If they aren't handled at this point
300 * then they will never be handled.
301 */
302 @Override
303 public boolean canDeferPlugin(GeneratedInvocationPlugin plugin) {
304 return plugin.isGeneratedFromFoldOrNodeIntrinsic();
305 }
306
307 @Override
308 public BailoutException bailout(String string) {
309 BailoutException bailout = new PermanentBailoutException(string);
310 throw GraphUtil.createBailoutException(string, bailout, GraphUtil.approxSourceStackTraceElement(methodScope.getCallerBytecodePosition()));
311 }
312
313 @Override
314 public StampProvider getStampProvider() {
315 return providers.getStampProvider();
316 }
317
318 @Override
319 public MetaAccessProvider getMetaAccess() {
320 return providers.getMetaAccess();
321 }
322
323 @Override
324 public ConstantReflectionProvider getConstantReflection() {
568 }
569
570 @Override
571 public boolean equals(Object obj) {
572 if (obj instanceof SpecialCallTargetCacheKey) {
573 SpecialCallTargetCacheKey key = (SpecialCallTargetCacheKey) obj;
574 return key.invokeKind.equals(this.invokeKind) && key.targetMethod.equals(this.targetMethod) && key.contextType.equals(this.contextType) && key.receiverStamp.equals(this.receiverStamp);
575 }
576 return false;
577 }
578 }
579
580 private final LoopExplosionPlugin loopExplosionPlugin;
581 private final InvocationPlugins invocationPlugins;
582 private final InlineInvokePlugin[] inlineInvokePlugins;
583 private final ParameterPlugin parameterPlugin;
584 private final NodePlugin[] nodePlugins;
585 private final EconomicMap<SpecialCallTargetCacheKey, Object> specialCallTargetCache;
586 private final EconomicMap<ResolvedJavaMethod, Object> invocationPluginCache;
587 private final ResolvedJavaMethod callInlinedMethod;
588 private final ResolvedJavaMethod callInlinedAgnosticMethod;
589 protected final SourceLanguagePositionProvider sourceLanguagePositionProvider;
590
591 public PEGraphDecoder(Architecture architecture, StructuredGraph graph, CoreProviders providers, LoopExplosionPlugin loopExplosionPlugin, InvocationPlugins invocationPlugins,
592 InlineInvokePlugin[] inlineInvokePlugins,
593 ParameterPlugin parameterPlugin,
594 NodePlugin[] nodePlugins, ResolvedJavaMethod callInlinedMethod, ResolvedJavaMethod callInlinedAgnosticMethod, SourceLanguagePositionProvider sourceLanguagePositionProvider) {
595 super(architecture, graph, providers, true);
596 this.loopExplosionPlugin = loopExplosionPlugin;
597 this.invocationPlugins = invocationPlugins;
598 this.inlineInvokePlugins = inlineInvokePlugins;
599 this.parameterPlugin = parameterPlugin;
600 this.nodePlugins = nodePlugins;
601 this.callInlinedAgnosticMethod = callInlinedAgnosticMethod;
602 this.specialCallTargetCache = EconomicMap.create(Equivalence.DEFAULT);
603 this.invocationPluginCache = EconomicMap.create(Equivalence.DEFAULT);
604 this.callInlinedMethod = callInlinedMethod;
605 this.sourceLanguagePositionProvider = sourceLanguagePositionProvider;
606 }
607
608 protected static LoopExplosionKind loopExplosionKind(ResolvedJavaMethod method, LoopExplosionPlugin loopExplosionPlugin) {
609 if (loopExplosionPlugin == null) {
610 return LoopExplosionKind.NONE;
611 } else {
612 return loopExplosionPlugin.loopExplosionKind(method);
613 }
614 }
615
616 @SuppressWarnings("try")
617 public void decode(ResolvedJavaMethod method, boolean isSubstitution, boolean trackNodeSourcePosition) {
618 try (DebugContext.Scope scope = debug.scope("PEGraphDecode", graph)) {
619 EncodedGraph encodedGraph = lookupEncodedGraph(method, null, null, isSubstitution, trackNodeSourcePosition);
620 PEMethodScope methodScope = new PEMethodScope(graph, null, null, encodedGraph, method, null, 0, loopExplosionPlugin, null);
621 decode(createInitialLoopScope(methodScope, null));
|