6060import com .oracle .graal .pointsto .constraints .UnsupportedFeatures ;
6161import com .oracle .graal .pointsto .flow .AllSynchronizedTypeFlow ;
6262import com .oracle .graal .pointsto .flow .FieldTypeFlow ;
63+ import com .oracle .graal .pointsto .flow .FormalParamTypeFlow ;
64+ import com .oracle .graal .pointsto .flow .InvokeTypeFlow ;
65+ import com .oracle .graal .pointsto .flow .MethodFlowsGraph ;
6366import com .oracle .graal .pointsto .flow .MethodTypeFlow ;
6467import com .oracle .graal .pointsto .flow .MethodTypeFlowBuilder ;
6568import com .oracle .graal .pointsto .flow .OffsetLoadTypeFlow .AbstractUnsafeLoadTypeFlow ;
6669import com .oracle .graal .pointsto .flow .OffsetStoreTypeFlow .AbstractUnsafeStoreTypeFlow ;
6770import com .oracle .graal .pointsto .flow .TypeFlow ;
6871import com .oracle .graal .pointsto .flow .context .AnalysisContext ;
6972import com .oracle .graal .pointsto .flow .context .AnalysisContextPolicy ;
73+ import com .oracle .graal .pointsto .infrastructure .WrappedSignature ;
7074import com .oracle .graal .pointsto .meta .AnalysisField ;
7175import com .oracle .graal .pointsto .meta .AnalysisMetaAccess ;
7276import com .oracle .graal .pointsto .meta .AnalysisMethod ;
@@ -443,46 +447,29 @@ public AnalysisMethod addRootMethod(AnalysisMethod aMethod, boolean invokeSpecia
443447
444448 AnalysisType declaringClass = aMethod .getDeclaringClass ();
445449 boolean isStatic = aMethod .isStatic ();
446- int paramCount = aMethod .getSignature ().getParameterCount (!isStatic );
450+ WrappedSignature signature = aMethod .getSignature ();
451+ int paramCount = signature .getParameterCount (!isStatic );
447452 PointsToAnalysisMethod pointsToMethod = assertPointsToAnalysisMethod (aMethod );
448- final MethodTypeFlow methodFlow = pointsToMethod .getTypeFlow ();
449-
450- /*
451- * Add the initial parameter flows as uses to the type flow of their respective types.
452- * The initial parameter flows will be linked to the concrete parameter flows after the
453- * method is parsed and the method type flow is linked. This code is shared between
454- * static and non-static methods and the differentiation is made below when the methods
455- * are linked.
456- *
457- * The parameter iteration skips the primitive parameters, as these are not modeled, and
458- * the receiver for virtual invokes which will be linked below.
459- *
460- * Note: the Signature doesn't count the receiver of a virtual invoke as a parameter
461- * whereas the MethodTypeFlow does, hence when accessing the parameter type below we use
462- * idx-offset but when setting the initial parameter flow we simply use idx.
463- */
464- int offset = 0 ;
465- if (!isStatic ) {
466- methodFlow .setInitialReceiverFlow (this , aMethod .getDeclaringClass ());
467- offset = 1 ;
468- }
469- for (int idx = offset ; idx < paramCount ; idx ++) {
470- AnalysisType declaredParamType = (AnalysisType ) aMethod .getSignature ().getParameterType (idx - offset , declaringClass );
471- if (declaredParamType .getJavaKind () == JavaKind .Object ) {
472- methodFlow .setInitialParameterFlow (this , declaredParamType , idx );
473- }
474- }
475453
476454 if (isStatic ) {
477455 /*
478456 * For static methods trigger analysis in the empty context. This will trigger
479- * parsing and will add the actual parameter flows as uses to the initial parameter
480- * flows initialized above .
457+ * parsing and return the method flows graph. Then the method parameter type flows
458+ * are initialized with the corresponding parameter declared type .
481459 */
482460 postTask (() -> {
483461 pointsToMethod .registerAsDirectRootMethod ();
484462 pointsToMethod .registerAsImplementationInvoked (null );
485- methodFlow .addContext (PointsToAnalysis .this , PointsToAnalysis .this .contextPolicy ().emptyContext ());
463+ MethodTypeFlow methodFlow = pointsToMethod .getTypeFlow ();
464+ MethodFlowsGraph methodFlowsGraph = methodFlow .addContext (PointsToAnalysis .this , PointsToAnalysis .this .contextPolicy ().emptyContext ());
465+ for (int idx = 0 ; idx < paramCount ; idx ++) {
466+ AnalysisType declaredParamType = (AnalysisType ) signature .getParameterType (idx , declaringClass );
467+ FormalParamTypeFlow parameter = methodFlowsGraph .getParameter (idx );
468+ if (declaredParamType .getJavaKind () == JavaKind .Object && parameter != null ) {
469+ TypeFlow <?> initialParameterFlow = declaredParamType .getTypeFlow (this , true );
470+ initialParameterFlow .addUse (this , parameter );
471+ }
472+ }
486473 });
487474 } else {
488475 if (invokeSpecial && pointsToMethod .isAbstract ()) {
@@ -498,10 +485,10 @@ public AnalysisMethod addRootMethod(AnalysisMethod aMethod, boolean invokeSpecia
498485 * state it will get notified for any future reachable subtypes and will resolve the
499486 * method in each subtype.
500487 *
501- * In both cases when a callee is resolved the method is parsed and the
502- * corresponding actual parameter flows are added as uses to the initial parameter
503- * flows initialized above. Then the callee is linked and registered as
504- * implementation-invoked.
488+ * In both cases the context-insensitive invoke parameters are initialized with the
489+ * corresponding declared type state. When a callee is resolved the method is parsed
490+ * and the actual parameter type state is propagated to the formal parameters. Then
491+ * the callee is linked and registered as implementation-invoked.
505492 */
506493 postTask (() -> {
507494 BytecodePosition location = new BytecodePosition (null , pointsToMethod , 0 );
@@ -510,7 +497,30 @@ public AnalysisMethod addRootMethod(AnalysisMethod aMethod, boolean invokeSpecia
510497 } else {
511498 pointsToMethod .registerAsVirtualRootMethod ();
512499 }
513- pointsToMethod .initAndGetContextInsensitiveInvoke (PointsToAnalysis .this , location , invokeSpecial );
500+ InvokeTypeFlow invoke = pointsToMethod .initAndGetContextInsensitiveInvoke (PointsToAnalysis .this , location , invokeSpecial );
501+ /*
502+ * Initialize the type flow of the invoke's actual parameters with the
503+ * corresponding parameter declared type. Thus, when the invoke links callees it
504+ * will propagate the parameter types too.
505+ *
506+ * The parameter iteration skips the primitive parameters, as these are not
507+ * modeled. The type flow of the receiver is set to the receiver type already
508+ * when the invoke is created.
509+ */
510+ for (int idx = 1 ; idx < paramCount ; idx ++) {
511+ /*
512+ * Note: the Signature doesn't count the receiver of a virtual invoke as a
513+ * parameter whereas the MethodTypeFlow does, hence when accessing the
514+ * parameter type below we use idx-1 but when accessing the actual parameter
515+ * flow we simply use idx.
516+ */
517+ AnalysisType declaredParamType = (AnalysisType ) signature .getParameterType (idx - 1 , declaringClass );
518+ TypeFlow <?> actualParameterFlow = invoke .getActualParameter (idx );
519+ if (declaredParamType .getJavaKind () == JavaKind .Object && actualParameterFlow != null ) {
520+ TypeFlow <?> initialParameterFlow = declaredParamType .getTypeFlow (this , true );
521+ initialParameterFlow .addUse (this , actualParameterFlow );
522+ }
523+ }
514524 });
515525 }
516526 }
0 commit comments