Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [aspectj-dev] semantics of thisEnclosingJoinPointStaticPart

re:

  thisEnclosingJoinPointStaticPart is bound to the static part
  of the join point enclosing the current join point

Gregor Kiczales wrote:
My understanding is that what tEJPSP is about is that "enclosing" means
"lexically enclosing", And "static" just means the same as in joinPointStaticPart.

I'd love to just use "lexical" rather than hand-waving with
"staticly determinable":

  thisEnclosingJoinPointStaticPart is bound to the static part
  of the join point lexically enclosing the current join point
                    ^^^^^^^^^

But I want to write more to avoid some potential confusion:

(1) join points are not points in code as this suggests.
Indeed, since we consider join points to be points in the
dynamic execution of a program, then in the original,
"enclosing" would mean "the most recently initiated join
point, if any", as one might find using cflow().

(2) "lexically" might not help for readers thinking of this in
bytecode.  (PCD's within() and withincode() make some sense in
bytecode, except that some nested/anonymous classes lose
that characteristic in bytecode.)

(3) tEJPSP does not behave as one might expect when thinking
about lexically-enclosed source code.  e.g.,

- tEJSP for a method-call in a field-initializer is the
  instance initializer

- in the code below, tEJSP for constructor-execution D()
  is not method-execution m()

  class C {
    void m() {
      class D {
        D() { }
      }
      new D();
    }
  }

- in the code below, tEJSP for method-call n() is
  method-execution m(), not handler(Error):

  void m() {
    try { ... }
    catch (Error e) {
      n();
    }
  }

> Given that understanding, I don't think there should
> be implementation variability here.

We already saw differences in the move from 1.0 to 1.1
with respect to some nested/anonymous classes (no longer
determinable to be withincode(..)) and code for join points
enclosed in exception handlers.  But I agree that it is
important if not necessary to avoid variations in the
join points picked out by a pointcut for a given language
(and recommend below specifying our behavior).

So what can we say of AspectJ 1.1?  A particular join point
is inferred from more or less explicit Java {byte-}code
of various kinds:

-- expressions
constructor-call
method-call
field get
field set

-- blocks
constructor-execution
method-execution
advice-execution

-- assembled blocks
static initialization
initialization
pre-initialization

-- range-start
handler


Someone correct me if either of these isn't true:

(1) all join points from expressions or handlers
(and only those join points) will have a tEJSP
(different from themselves) bound.[1]

(2) only join points inferred from blocks or assembled
blocks can be bound as tEJSP


So, in the interest of both brevity and completeness, I plan

(a) to modify the semantics guide to say: [2]

  thisEnclosingJoinPointStaticPart is bound to the static part
  of the join point lexically enclosing the current join point code
                    ^^^^^^^^^                                  ^^^^

(b) to add tests for the behavior of tEJPSP described above; and

(c) to document our behavior either in the FAQ or in the
programming guide, depending on what you or Erik thinks.
I'd recommend just enumerating:

  One of these...         will be tEJSP for each of these:
  ---------------         --------------------------------
  constructor-execution   constructor-call
  method-execution        method-call
  advice execution        handler
  initialization          field-set
  pre-initialization      field-get
  static initialization

  (Expressions in the body of handlers have the same
  tEJPSP as the handler itself.)

I think it belongs in the programming guide since this
behavior is derived from Java bytecode (and should be
implementable for pre-processor-based implementations).

Thoughts?

Wes

[1] Note that while there are, e.g., class instance creation
expressions, they do not form the basis for the static
initialization join point.

[2] Rejected formulations for the code giving rise to a join point:

  "code giving rise to a join point"
  "code for the join point"
  "code basis for the join point"
  "static shadow of the join point" (v. pointcuts)
  "static join point"
  "join point source" (probably the most promising)

Note that this would also be used for the referents of the IDE
crosscutting structure.  E.g., "Expand the tree for the foo()
pointcut to list the source for each join point picked out
by the pointcut."



So its theStaticPartOf(theLexicallyEnclosingJoinPointOf(thisJoinPoint)).
Just as tJSP is theStaticPartOf(thisJoinPoint).



  Implementations may vary in the static analysis to
  deduce enclosing join points, and are not required
  to evaluate scopes beyond the currently enclosing


Given that understanding, I don't think there should be implementation variability
here.



-----Original Message-----
From: aspectj-dev-admin@xxxxxxxxxxx [mailto:aspectj-dev-admin@xxxxxxxxxxx] On Behalf Of Wes Isberg
Sent: Tuesday, October 07, 2003 3:22 PM
To: aspectj-dev@xxxxxxxxxxx
Subject: [aspectj-dev] semantics of thisEnclosingJoinPointStaticPart


The programming guide says,

  thisEnclosingJoinPointStaticPart is bound to the static
  part of the join point enclosing the current join point.

Is it correct (and helpful) to say this?:

  thisEnclosingJoinPointStaticPart is bound to the static
  part of the join point which can be staticly determined
  to enclose the current join point.

If not also:

  For example, if a
  method call site is in the body of a constructor, then
  the method call join point will have as its enclosing
  join point the constructor execution join point.  If
  the enclosing join point cannot be staticly determined,
  then thisEnclosingJoinPointStaticPart will be the same
  as thisJoinPointStaticPart.

and in the limitations appendix:

  Implementations may vary in the static analysis to
  deduce enclosing join points, and are not required
  to evaluate scopes beyond the currently enclosing
  scope of the join point or to include implicit
  invocations resulting from instantiating instances
  or classes.

I guess this is supposed to work when the enclosing join point
is method or constructor execution or {static} initialization
and the join point is a handler, a method or constructor call,
or a field get or set?  Any other times?

If so, we might document e.g., that a method-call is
not necessarily the enclosing join point of a method-
execution.

Thanks -
Wes

---- output

     tjp: staticinitialization(AdviceExecution.<clinit>)
     ejp: staticinitialization(AdviceExecution.<clinit>)
     tjp: execution(void AdviceExecution.main(String[]))
     ejp: execution(void AdviceExecution.main(String[]))
       tjp: call(C())
       ejp: execution(void AdviceExecution.main(String[]))
         tjp: staticinitialization(C.<clinit>)
         ejp: staticinitialization(C.<clinit>)
         tjp: initialization(C())
         ejp: initialization(C())
         tjp: execution(C.<init>)
         ejp: execution(C.<init>)
         tjp: execution(C())
         ejp: execution(C())
       tjp: initialization(A())
       ejp: initialization(A())
       tjp: execution(A.<init>)
       ejp: execution(A.<init>)
       tjp: execution(A())
       ejp: execution(A())
       tjp: staticinitialization(A.<clinit>)
       ejp: staticinitialization(A.<clinit>)
       tjp: execution(ADVICE: void A.before())
       ejp: execution(ADVICE: void A.before())
         tjp: call(void A.m())
         ejp: execution(ADVICE: void A.before())
           tjp: execution(void A.m())
           ejp: execution(void A.m())
             tjp: call(java.lang.Error(String))
             ejp: execution(void A.m())
         tjp: handler(catch(Error))
         ejp: execution(ADVICE: void A.before())
         tjp: call(void A.log(Error))
         ejp: execution(ADVICE: void A.before())
           tjp: execution(void A.log(Error))
           ejp: execution(void A.log(Error))
             tjp: get(PrintStream java.lang.System.out)
             ejp: execution(void A.log(Error))
             tjp: call(String java.lang.Throwable.getMessage())
             ejp: execution(void A.log(Error))
             tjp: call(void java.io.PrintStream.println(String))
             ejp: execution(void A.log(Error))
Error: catch me if you can
       tjp: call(void C.run())
       ejp: execution(void AdviceExecution.main(String[]))
         tjp: execution(void C.run())
         ejp: execution(void C.run())

---- program

import java.io.PrintStream;
import org.aspectj.lang.JoinPoint;

public class AdviceExecution {
    public static void main(String[] args) {
        new C().run();
    }
}

class C { void run() {} }

aspect A {
    before() : call(* *(..))
        && !call(void A.m())
        && !call(void A.log(Error))
        && !withincode(void A.log(Error))
        && JoinPointLogger.safety() {
        try {
          m();
        } catch (Error e) {
            log(e);
        }
    }
    void  m() { throw new Error("catch me if you can");}
    void  log(Error e) {
            System.out.println("Error: " + e.getMessage());
    }
}

aspect JoinPointLogger {
    final String tab = "  ";
    final StringBuffer tabs = new StringBuffer();

    pointcut safety() : !within(JoinPointLogger);
    pointcut aroundsafety() : !(initialization(*.new(..))
        || handler(*)
        //|| preinitialization(*.new(..))
        );


    before() : within(*) && safety() {
        System.out.println(tab + tabs
            + "   tjp: "
            + thisJoinPoint.toString());
        System.out.println(tab + tabs
            + "   ejp: "
            + thisEnclosingJoinPointStaticPart.toString());
    }

    /** identify all join points */
    Object around() : within(*) && safety() && aroundsafety() {
        final int len = tabs.length();
        tabs.append(tab);
        try {
            return proceed();
        } finally {
            tabs.setLength(len);
        }
    }
}


_______________________________________________
aspectj-dev mailing list
aspectj-dev@xxxxxxxxxxx
http://dev.eclipse.org/mailman/listinfo/aspectj-dev




_______________________________________________
aspectj-dev mailing list
aspectj-dev@xxxxxxxxxxx
http://dev.eclipse.org/mailman/listinfo/aspectj-dev




Back to the top