/** * Track methods that have a stack values. This is later used for deoptimization testing during * compilation. */ private void recordMethodsWithStackValues() { bigbang.getUniverse().getMethods().parallelStream().forEach(analysisMethod -> { if (analysisMethod.getTypeFlow() != null && analysisMethod.getTypeFlow().getGraph() != null && analysisMethod.getTypeFlow().getGraph().getNodes(StackValueNode.TYPE).isNotEmpty()) { hUniverse.recordMethodWithStackValues(analysisMethod); } }); }
public StaticAnalysisResults makeResults(AnalysisMethod method) { MethodFlowsGraph originalFlows = methodFlow.getOriginalMethodFlows(); JavaTypeProfile paramProfile = makeTypeProfile(methodFlow.foldTypeFlow(bb, originalFlows.getParameter(i))); if (paramProfile != null) { ensureSize(paramProfiles, i); JavaTypeProfile resultTypeProfile = makeTypeProfile(methodFlow.foldTypeFlow(bb, originalFlows.getResult())); TypeState instanceOfTypeState = methodFlow.foldTypeFlow(bb, originalInstanceOf); originalInstanceOf.setState(bb, instanceOfTypeState); invokeTypeState = methodFlow.foldTypeFlow(bb, originalInvoke.getReceiver()); originalInvoke.setState(bb, invokeTypeState); TypeState returnTypeState = null; if (originalReturn != null) { returnTypeState = methodFlow.foldTypeFlow(bb, originalReturn); originalReturn.setState(bb, returnTypeState);
@Override public void run(DebugContext ignore) { methodFlow.addContext(BigBang.this, BigBang.this.contextPolicy().emptyContext(), null); }
TypeFlowBuilder<MergeTypeFlow> newFlowBuilder = TypeFlowBuilder.create(bb, merge, MergeTypeFlow.class, () -> { MergeTypeFlow newFlow = new MergeTypeFlow(merge); methodFlow.addMiscEntry(newFlow); return newFlow; }); TypeFlow<?> input = ((AnalysisType) StampTool.typeOrNull(node)).getTypeFlow(bb, false); ExceptionObjectTypeFlow exceptionObjectFlow = new ExceptionObjectTypeFlow(node, input); methodFlow.addMiscEntry(exceptionObjectFlow); return exceptionObjectFlow; }); TypeFlowBuilder<DynamicNewInstanceTypeFlow> dynamicNewInstanceBuilder = TypeFlowBuilder.create(bb, node, DynamicNewInstanceTypeFlow.class, () -> { DynamicNewInstanceTypeFlow newInstanceTypeFlow = new DynamicNewInstanceTypeFlow(instanceTypeBuilder.get(), node, allocationLabel); methodFlow.addDynamicAllocation(newInstanceTypeFlow); return newInstanceTypeFlow; }); methodFlow.addDynamicAllocation(newArrayTypeFlow); return newArrayTypeFlow; }); TypeFlowBuilder<NewInstanceTypeFlow> newArrayBuilder = TypeFlowBuilder.create(bb, node, NewInstanceTypeFlow.class, () -> { NewInstanceTypeFlow newArray = new NewInstanceTypeFlow(node, type, allocationLabel); methodFlow.addAllocation(newArray); return newArray; }); FieldTypeFlow fieldFlow = field.getStaticFieldFlow();
TypeFlow<?> returnTypeFlow = methodFlow.getResultFlow().getDeclaredType().getTypeFlow(this.bb, true); returnTypeFlow = new ProxyTypeFlow(null, returnTypeFlow); FormalReturnTypeFlow resultFlow = new FormalReturnTypeFlow(null, returnType, method); returnTypeFlow.addOriginalUse(this.bb, resultFlow); methodFlow.addMiscEntry(returnTypeFlow); methodFlow.setResult(resultFlow); methodFlow.setParameter(index, parameter); return parameter; }); BoxNode node = (BoxNode) n; Object key = uniqueKey(node); BytecodeLocation boxSite = bb.analysisPolicy().createAllocationSite(bb, key, methodFlow.getMethod()); AnalysisType type = (AnalysisType) StampTool.typeOrNull(node); methodFlow.addAllocation(boxFlow); return boxFlow; }); TypeFlowBuilder<SourceTypeFlow> sourceBuilder = TypeFlowBuilder.create(bb, node, SourceTypeFlow.class, () -> { SourceTypeFlow constantSource = new SourceTypeFlow(node, TypeState.forNull()); methodFlow.addSource(constantSource); return constantSource; }); TypeFlowBuilder<SourceTypeFlow> sourceBuilder = TypeFlowBuilder.create(bb, node, SourceTypeFlow.class, () -> { SourceTypeFlow constantSource = new SourceTypeFlow(node, TypeState.forConstant(this.bb, node.asJavaConstant(), type)); methodFlow.addSource(constantSource);
MethodFlowsGraph calleeFlows = callee.addContext(bb, bb.contextPolicy().emptyContext(), this); assert callee.getContexts()[0] == bb.contextPolicy().emptyContext(); if (addCallee(callee.getMethod())) { linkCallee(bb, false, calleeFlows);
for (int i = 0; i < method.getTypeFlow().getOriginalMethodFlows().getParameters().length; i++) { TypeState state = method.getTypeFlow().getParameterTypeState(bigbang, i); if (state != null) { AnalysisType declaredType = method.getTypeFlow().getOriginalMethodFlows().getParameter(i).getDeclaredType(); if (declaredType.isInterface()) { state = TypeState.forSubtraction(bigbang, state, declaredType.getTypeFlow(bigbang, true).getState());
AnalysisMethod targetMethod = (AnalysisMethod) targetNode.targetMethod(); AnalysisMethod callerMethod = (AnalysisMethod) targetNode.invoke().stateAfter().getMethod(); InvokeTypeFlow invokeFlow = callerMethod.getTypeFlow().getOriginalMethodFlows().getInvoke(targetNode.invoke().bci());
protected void processNewInstance(NewInstanceNode node, TypeFlowsOfNodes state) { AnalysisType type = (AnalysisType) node.instanceClass(); assert type.isInstantiated(); Object key = uniqueKey(node); BytecodeLocation allocationLabel = bb.analysisPolicy().createAllocationSite(bb, key, method); TypeFlowBuilder<?> newInstanceBuilder = TypeFlowBuilder.create(bb, node, NewInstanceTypeFlow.class, () -> { NewInstanceTypeFlow newInstance = createNewInstanceTypeFlow(node, type, allocationLabel); /* Instance fields of a new object are initialized to null state in AnalysisField. */ methodFlow.addAllocation(newInstance); return newInstance; }); state.add(node, newInstanceBuilder); }
private TypeFlowBuilder<?> uniqueInstanceOfFlow(InstanceOfNode node, AnalysisType declaredType) { /* * This happens during method parsing, which is single threaded, so there is no need for * synchronization. */ Object key = uniqueKey(node); return instanceOfFlows.computeIfAbsent(key, (bciKey) -> { BytecodeLocation location = BytecodeLocation.create(bciKey, method); TypeFlowBuilder<?> instanceOfBuilder = TypeFlowBuilder.create(bb, node, InstanceOfTypeFlow.class, () -> { InstanceOfTypeFlow instanceOf = new InstanceOfTypeFlow(node, location, declaredType); methodFlow.addInstanceOf(key, instanceOf); return instanceOf; }); /* InstanceOf must not be removed as it is reported by the analysis results. */ typeFlowGraphBuilder.registerSinkBuilder(instanceOfBuilder); return instanceOfBuilder; }); }
typeFlow = new MethodTypeFlow(universe.hostVM().options(), this);
protected void processNewArray(NewArrayNode node, TypeFlowsOfNodes state) { AnalysisType type = ((AnalysisType) node.elementType()).getArrayClass(); assert type.isInstantiated(); Object key = uniqueKey(node); BytecodeLocation allocationLabel = bb.analysisPolicy().createAllocationSite(bb, key, method); TypeFlowBuilder<?> newArrayBuilder = TypeFlowBuilder.create(bb, node, NewInstanceTypeFlow.class, () -> { NewInstanceTypeFlow newArray = createNewArrayTypeFlow(node, type, allocationLabel); methodFlow.addAllocation(newArray); return newArray; }); state.add(node, newArrayBuilder); }
public void scanBootImageHeapRoots(Comparator<AnalysisField> fieldComparator, Comparator<AnalysisMethod> methodComparator) { // scan the original roots // the original roots are all the static fields, of object type, that were accessed bb.getUniverse().getFields().stream() .filter(field -> Modifier.isStatic(field.getModifiers()) && field.getJavaKind() == JavaKind.Object && field.isAccessed()) .sorted(fieldComparator) .forEach(field -> scanField(field, null, field)); // scan the constant nodes bb.getUniverse().getMethods().stream() .filter(method -> method.getTypeFlow().getGraph() != null) .sorted(methodComparator) .forEach(this::scanMethod); finish(); }
@Override public void update(BigBang bb) { assert this.isClone(); /* The static invokes should be updated only once and the callee should be null. */ guarantee(callee == null, "static invoke updated multiple times!"); /* * Initialize the callee lazily so that if the invoke flow is not reached in this context, * i.e. for this clone, there is no callee linked/ */ MethodCallTargetNode target = (MethodCallTargetNode) invoke.callTarget(); callee = ((AnalysisMethod) target.targetMethod()).getTypeFlow(); // set the callee in the original invoke too ((DirectInvokeTypeFlow) originalInvoke).callee = callee; calleeContext = bb.contextPolicy().staticCalleeContext(bb, location, callerContext, callee); MethodFlowsGraph calleeFlows = callee.addContext(bb, calleeContext, this); linkCallee(bb, true, calleeFlows); }
/** Visit the callees of this method. */ VisitResult walkCallees(AnalysisMethod method, CallPathVisitor visitor) { final StructuredGraph graph = method.getTypeFlow().getGraph(); if (graph != null) { for (Invoke invoke : graph.getInvokes()) { final CallTargetNode callTarget = invoke.callTarget(); final AnalysisMethod callee = (AnalysisMethod) callTarget.targetMethod(); walkMethodAndCallees(callee, method, invoke, visitor); } } return VisitResult.CONTINUE; }
@Override public void onObservedUpdate(BigBang bb) { assert this.isClone(); /* The receiver state has changed. Process the invoke. */ /* * Initialize the callee lazily so that if the invoke flow is not reached in this context, * i.e. for this clone, there is no callee linked. */ if (callee == null) { MethodCallTargetNode target = (MethodCallTargetNode) invoke.callTarget(); callee = ((AnalysisMethod) target.targetMethod()).getTypeFlow(); // set the callee in the original invoke too ((DirectInvokeTypeFlow) originalInvoke).callee = callee; } TypeState invokeState = getReceiver().getState(); for (AnalysisObject receiverObject : invokeState.objects()) { AnalysisContext calleeContext = bb.contextPolicy().calleeContext(bb, receiverObject, callerContext, callee); MethodFlowsGraph calleeFlows = callee.addContext(bb, calleeContext, this); if (calleesFlows.putIfAbsent(calleeFlows, Boolean.TRUE) == null) { linkCallee(bb, false, calleeFlows); } updateReceiver(bb, calleeFlows, receiverObject); } }
private void scanMethod(AnalysisMethod method) { try { StreamSupport.stream(method.getTypeFlow().getGraph().getNodes().spliterator(), false) .filter(n -> n instanceof ConstantNode).forEach(n -> { ConstantNode cn = (ConstantNode) n; JavaConstant c = (JavaConstant) cn.getValue(); if (c.getJavaKind() == JavaKind.Object) { scanConstant(c, method); } }); } catch (UnsupportedFeatureException ex) { bb.getUnsupportedFeatures().addMessage(method.format("%H.%n(%p)"), method, ex.getMessage(), null, ex); } }
MethodFlowsGraph calleeFlows = callee.addContext(bb, calleeContext, this);
@Override public InlineInfo shouldInlineInvoke(GraphBuilderContext builder, ResolvedJavaMethod original, ValueNode[] arguments) { if (original.getAnnotation(NeverInline.class) != null) { return InlineInfo.DO_NOT_INLINE_WITH_EXCEPTION; } else if (invocationPlugins.lookupInvocation(original) != null) { return InlineInfo.DO_NOT_INLINE_WITH_EXCEPTION; } else if (original.getAnnotation(ExplodeLoop.class) != null) { return InlineInfo.DO_NOT_INLINE_WITH_EXCEPTION; } else if (replacements.hasSubstitution(original, builder.bci())) { return InlineInfo.DO_NOT_INLINE_WITH_EXCEPTION; } for (ResolvedJavaMethod m : partialEvaluator.getNeverInlineMethods()) { if (original.equals(m)) { return InlineInfo.DO_NOT_INLINE_WITH_EXCEPTION; } } StructuredGraph graph = ((AnalysisMethod) original).getTypeFlow().getGraph(); if (graph != null && original.getCode() != null && includeMethodPredicate.test(original) && InliningUtilities.isTrivialMethod(graph) && builder.getDepth() < InlineDuringParsingMaxDepth.getValue(HostedOptionValues.singleton())) { return createStandardInlineInfo(original); } return null; } }