Browse Source

synchronization joinpoints: code dump...

tags/V1_5_2rc1
aclement 18 years ago
parent
commit
f1ad9e6c35

+ 15
- 0
weaver/src/org/aspectj/weaver/Advice.java View File

@@ -43,6 +43,8 @@ public abstract class Advice extends ShadowMunger {
protected UnresolvedType[] bindingParameterTypes;
protected List/*Lint.Kind*/ suppressedLintKinds = null; // based on annotations on this advice
ISourceLocation lastReportedMonitorExitJoinpointLocation = null;

public static Advice makeCflowEntry(World world, Pointcut entry, boolean isBelow, Member stackField, int nFreeVars, List innerCflowEntries, ResolvedType inAspect){
Advice ret = world.createAdviceMunger(isBelow ? AdviceKind.CflowBelowEntry : AdviceKind.CflowEntry,
@@ -115,6 +117,19 @@ public abstract class Advice extends ShadowMunger {
return false;
}
}
if (shadow.getKind()==Shadow.SynchronizationLock ||
shadow.getKind()==Shadow.SynchronizationUnlock) {
if (kind==AdviceKind.Around
// Don't work, see comments in SynchronizationTests
// && attribute.getProceedCallSignatures()!=null
// && attribute.getProceedCallSignatures().length!=0
) {
world.showMessage(IMessage.WARNING,
WeaverMessages.format(WeaverMessages.NO_AROUND_ON_SYNCHRONIZATION),
getSourceLocation(), shadow.getSourceLocation());
return false;
}
}

if (hasExtraParameter() && kind == AdviceKind.AfterReturning) {

+ 52
- 7
weaver/src/org/aspectj/weaver/Shadow.java View File

@@ -14,6 +14,7 @@
package org.aspectj.weaver;

import java.io.DataInputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
@@ -146,6 +147,10 @@ public abstract class Shadow {
return (getKind()==ConstructorCall && signature.getDeclaringType().isArray());
}
public boolean isShadowForMonitor() {
return (getKind()==SynchronizationLock || getKind()==SynchronizationUnlock);
}
// will return the right length array of ints depending on how many dimensions the array has
public ResolvedType[] getArgumentTypesForArrayConstructionShadow() {
String s = signature.getDeclaringType().getSignature();
@@ -165,6 +170,9 @@ public abstract class Shadow {
if (isShadowForArrayConstructionJoinpoint()) {
return getArgumentTypesForArrayConstructionShadow();
}
if (isShadowForMonitor()) {
return UnresolvedType.ARRAY_WITH_JUST_OBJECT;
}
if (getKind() == FieldSet) return new UnresolvedType[] { getResolvedSignature().getGenericReturnType() };
return getResolvedSignature().getGenericParameterTypes();
}
@@ -236,8 +244,9 @@ public abstract class Shadow {
public UnresolvedType getReturnType() {
if (kind == ConstructorCall) return getSignature().getDeclaringType();
else if (kind == FieldSet) return ResolvedType.VOID;
if (kind == ConstructorCall) return getSignature().getDeclaringType();
else if (kind == FieldSet) return ResolvedType.VOID;
else if (kind == SynchronizationLock || kind==SynchronizationUnlock) return ResolvedType.VOID;
return getResolvedSignature().getGenericReturnType();
}

@@ -257,6 +266,8 @@ public abstract class Shadow {
public static final Kind AdviceExecution = new Kind(JoinPoint.ADVICE_EXECUTION, 9, false);
public static final Kind Initialization = new Kind(JoinPoint.INITIALIZATION, 10, false);
public static final Kind ExceptionHandler = new Kind(JoinPoint.EXCEPTION_HANDLER, 11, true);
public static final Kind SynchronizationLock = new Kind(JoinPoint.SYNCHRONIZATION_LOCK, 12, true);
public static final Kind SynchronizationUnlock= new Kind(JoinPoint.SYNCHRONIZATION_UNLOCK, 13, true);
// Bits here are 1<<(Kind.getKey()) - and unfortunately keys didn't start at zero so bits here start at 2
public static final int MethodCallBit = 0x002;
@@ -270,20 +281,22 @@ public abstract class Shadow {
public static final int AdviceExecutionBit = 0x200;
public static final int InitializationBit = 0x400;
public static final int ExceptionHandlerBit = 0x800;
public static final int SynchronizationLockBit =0x1000;
public static final int SynchronizationUnlockBit=0x2000;
public static final int MAX_SHADOW_KIND = 11;
public static final int MAX_SHADOW_KIND = 13;
public static final Kind[] SHADOW_KINDS = new Kind[] {
MethodCall, ConstructorCall, MethodExecution, ConstructorExecution,
FieldGet, FieldSet, StaticInitialization, PreInitialization,
AdviceExecution, Initialization, ExceptionHandler,
AdviceExecution, Initialization, ExceptionHandler,SynchronizationLock,SynchronizationUnlock
};
public static final int ALL_SHADOW_KINDS_BITS;
public static final int NO_SHADOW_KINDS_BITS;
static {
ALL_SHADOW_KINDS_BITS = 0xffe;
NO_SHADOW_KINDS_BITS = 0x000;
ALL_SHADOW_KINDS_BITS = 0x3ffe;
NO_SHADOW_KINDS_BITS = 0x0000;
}
/**
@@ -363,7 +376,7 @@ public abstract class Shadow {
}
private final static int neverHasTargetFlag=
ConstructorCallBit | ExceptionHandlerBit | PreInitializationBit | StaticInitializationBit;
ConstructorCallBit | ExceptionHandlerBit | PreInitializationBit | StaticInitializationBit | SynchronizationLockBit | SynchronizationUnlockBit;
public boolean neverHasTarget() {
return (bit&neverHasTargetFlag)!=0;
}
@@ -395,6 +408,8 @@ public abstract class Shadow {
case 9: return AdviceExecution;
case 10: return Initialization;
case 11: return ExceptionHandler;
case 12: return SynchronizationLock;
case 13: return SynchronizationUnlock;
}
throw new BCException("unknown kind: " + key);
}
@@ -577,6 +592,25 @@ public abstract class Shadow {
aKind.equals(AdviceKind.Around) ||
aKind.equals(AdviceKind.Softener))) return;
// synchronized blocks are implemented with multiple monitor_exit instructions in the bytecode
// (one for normal exit from the method, one for abnormal exit), we only want to tell the user
// once we have advised the end of the sync block, even though under the covers we will have
// woven both exit points
if (this.kind==Shadow.SynchronizationUnlock) {
if (advice.lastReportedMonitorExitJoinpointLocation==null) {
// this is the first time through, let's continue...
advice.lastReportedMonitorExitJoinpointLocation = getSourceLocation();
} else {
if (areTheSame(getSourceLocation(),advice.lastReportedMonitorExitJoinpointLocation)) {
// Don't report it again!
advice.lastReportedMonitorExitJoinpointLocation=null;
return;
}
// hmmm, this means some kind of nesting is going on, urgh
advice.lastReportedMonitorExitJoinpointLocation=getSourceLocation();
}
}
String description = advice.getKind().toString();
String advisedType = this.getEnclosingType().getName();
String advisingType= advice.getConcreteAspect().getName();
@@ -604,6 +638,17 @@ public abstract class Shadow {
}


private boolean areTheSame(ISourceLocation locA, ISourceLocation locB) {
if (locA==null) return locB==null;
if (locB==null) return false;
if (locA.getLine()!=locB.getLine()) return false;
File fA = locA.getSourceFile();
File fB = locA.getSourceFile();
if (fA==null) return fB==null;
if (fB==null) return false;
return fA.getName().equals(fB.getName());
}

public IRelationship.Kind determineRelKind(ShadowMunger munger) {
AdviceKind ak = ((Advice)munger).getKind();
if (ak.getKey()==AdviceKind.Before.getKey())

+ 11
- 4
weaver/src/org/aspectj/weaver/World.java View File

@@ -96,13 +96,15 @@ public abstract class World implements Dump.INode {
private String targetAspectjRuntimeLevel = Constants.RUNTIME_LEVEL_DEFAULT;
/** Flags for the new joinpoints that are 'optional' */
private boolean optionalJoinpoint_ArrayConstruction = false; // Command line flag: "arrayconstruction"
private boolean optionalJoinpoint_ArrayConstruction = false; // Command line flag: "-Xjoinpoints:arrayconstruction"
private boolean optionalJoinpoint_Synchronization = false; // Command line flag: "-Xjoinpoints:synchronization"
private boolean addSerialVerUID = false;
private Properties extraConfiguration = null;
private boolean checkedAdvancedConfiguration=false;
private boolean synchronizationPointcutsInUse = false;
// Xset'table options
private boolean fastDelegateSupportEnabled = isASMAround;
private boolean runMinimalMemory = false;
@@ -762,14 +764,17 @@ public abstract class World implements Dump.INode {
public void setOptionalJoinpoints(String jps) {
if (jps==null) return;
if (jps.indexOf("arrayconstruction")!=-1) {
optionalJoinpoint_ArrayConstruction = true;
}
if (jps.indexOf("arrayconstruction")!=-1) optionalJoinpoint_ArrayConstruction = true;
if (jps.indexOf("trivial")!=-1) optionalJoinpoint_Trivial = true;
if (jps.indexOf("synchronization")!=-1) optionalJoinpoint_Synchronization = true;
}
public boolean isJoinpointArrayConstructionEnabled() {
return optionalJoinpoint_ArrayConstruction;
}
public boolean isJoinpointSynchronizationEnabled() {
return optionalJoinpoint_Synchronization;
}
public String getTargetAspectjRuntimeLevel() {
return targetAspectjRuntimeLevel;
@@ -1162,4 +1167,6 @@ public abstract class World implements Dump.INode {
public void setIncrementalCompileCouldFollow(boolean b) {incrementalCompileCouldFollow = b;}
public boolean couldIncrementalCompileFollow() {return incrementalCompileCouldFollow;}
public void setSynchronizationPointcutsInUse() {synchronizationPointcutsInUse =true;}
public boolean areSynchronizationPointcutsInUse() {return synchronizationPointcutsInUse;}
}

+ 27
- 1
weaver/src/org/aspectj/weaver/bcel/BcelShadow.java View File

@@ -814,6 +814,32 @@ public class BcelShadow extends Shadow {
retargetAllBranches(arrayInstruction, r.getStart());
return s;
}
public static BcelShadow makeMonitorEnter(BcelWorld world,LazyMethodGen enclosingMethod,InstructionHandle monitorInstruction,BcelShadow enclosingShadow) {
final InstructionList body = enclosingMethod.getBody();
Member sig = world.makeJoinPointSignatureForMonitorEnter(enclosingMethod.getEnclosingClass(),monitorInstruction);
BcelShadow s = new BcelShadow(world,SynchronizationLock,sig,enclosingMethod,enclosingShadow);
ShadowRange r = new ShadowRange(body);
r.associateWithShadow(s);
r.associateWithTargets(
Range.genStart(body, monitorInstruction),
Range.genEnd(body, monitorInstruction));
retargetAllBranches(monitorInstruction, r.getStart());
return s;
}
public static BcelShadow makeMonitorExit(BcelWorld world,LazyMethodGen enclosingMethod,InstructionHandle monitorInstruction,BcelShadow enclosingShadow) {
final InstructionList body = enclosingMethod.getBody();
Member sig = world.makeJoinPointSignatureForMonitorExit(enclosingMethod.getEnclosingClass(),monitorInstruction);
BcelShadow s = new BcelShadow(world,SynchronizationUnlock,sig,enclosingMethod,enclosingShadow);
ShadowRange r = new ShadowRange(body);
r.associateWithShadow(s);
r.associateWithTargets(
Range.genStart(body, monitorInstruction),
Range.genEnd(body, monitorInstruction));
retargetAllBranches(monitorInstruction, r.getStart());
return s;
}

// see pr77166
// public static BcelShadow makeArrayLoadCall(
@@ -3295,4 +3321,4 @@ public class BcelShadow extends Shadow {
public String getActualTargetType() {
return actualInstructionTargetType;
}
}
}

+ 89
- 0
weaver/src/org/aspectj/weaver/bcel/PoliceExtensionUse.java View File

@@ -0,0 +1,89 @@
/*******************************************************************************
* Copyright (c) 2006 IBM
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andy Clement - initial API and implementation
*******************************************************************************/
package org.aspectj.weaver.bcel;

import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.MessageUtil;
import org.aspectj.weaver.Shadow;
import org.aspectj.weaver.World;
import org.aspectj.weaver.patterns.AndPointcut;
import org.aspectj.weaver.patterns.IdentityPointcutVisitor;
import org.aspectj.weaver.patterns.KindedPointcut;
import org.aspectj.weaver.patterns.NotPointcut;
import org.aspectj.weaver.patterns.OrPointcut;
import org.aspectj.weaver.patterns.Pointcut;

/**
* Walks a pointcut and determines if the synchronization related designators have been
* used: lock() or unlock()
*/
public class PoliceExtensionUse extends IdentityPointcutVisitor {
private boolean synchronizationDesignatorEncountered;
private World world;
private Pointcut p;
public PoliceExtensionUse(World w,Pointcut p) {
this.world = w;
this.p = p;
this.synchronizationDesignatorEncountered = false;
}
public boolean synchronizationDesignatorEncountered() {
return synchronizationDesignatorEncountered;
}

public Object visit(KindedPointcut node, Object data) {
if (world==null) return super.visit(node,data); // error scenario can sometimes lead to this LazyClassGen.toLongString()
if (node.getKind()==Shadow.SynchronizationLock ||
node.getKind()==Shadow.SynchronizationUnlock)
synchronizationDesignatorEncountered=true;
// Check it!
if (!world.isJoinpointSynchronizationEnabled()) {
if (node.getKind()==Shadow.SynchronizationLock) {
IMessage m = MessageUtil.warn("lock() pointcut designator cannot be used without the option -Xjoinpoints:synchronization",
p.getSourceLocation());
world.getMessageHandler().handleMessage(m);
} else if (node.getKind()==Shadow.SynchronizationUnlock) {
IMessage m = MessageUtil.warn("unlock() pointcut designator cannot be used without the option -Xjoinpoints:synchronization",
p.getSourceLocation());
world.getMessageHandler().handleMessage(m);
}
}
if (node.getKind()==Shadow.MethodExecution) {
if (!world.isJoinpointTrivialEnabled() &&
node.getSignature().getModifiers().concernedWithTriviality()) {
IMessage m = MessageUtil.warn("Use of 'trivial' modifier in the execution() pointcut is not allowed without the option -Xjoinpoints:trivial",
p.getSourceLocation());
world.getMessageHandler().handleMessage(m);
}
}
return super.visit(node, data);
}
public Object visit(AndPointcut node, Object data) {
node.getLeft().accept(this, data);
node.getRight().accept(this, data);
return node;
}

public Object visit(NotPointcut node, Object data) {
node.getNegatedPointcut().accept(this, data);
return node;
}

public Object visit(OrPointcut node, Object data) {
node.getLeft().accept(this, data);
node.getRight().accept(this, data);
return node;
}
}

+ 3
- 0
weaver/src/org/aspectj/weaver/patterns/KindedPointcut.java View File

@@ -100,6 +100,9 @@ public class KindedPointcut extends Pointcut {
protected FuzzyBoolean matchInternal(Shadow shadow) {
if (shadow.getKind() != kind) return FuzzyBoolean.NO;

if (shadow.getKind() == Shadow.SynchronizationLock && kind == Shadow.SynchronizationLock) return FuzzyBoolean.YES;
if (shadow.getKind() == Shadow.SynchronizationUnlock && kind == Shadow.SynchronizationUnlock) return FuzzyBoolean.YES;
if (!signature.matches(shadow.getMatchingSignature(), shadow.getIWorld(),this.kind == Shadow.MethodCall)){

if(kind == Shadow.MethodCall) {

+ 9
- 0
weaver/src/org/aspectj/weaver/patterns/Pointcut.java View File

@@ -29,8 +29,10 @@ import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.Shadow;
import org.aspectj.weaver.ShadowMunger;
import org.aspectj.weaver.VersionedDataInputStream;
import org.aspectj.weaver.World;
import org.aspectj.weaver.ast.Literal;
import org.aspectj.weaver.ast.Test;
import org.aspectj.weaver.bcel.PoliceExtensionUse;

/**
* The lifecycle of Pointcuts is modeled by Pointcut.State. It has three things:
@@ -310,6 +312,13 @@ public abstract class Pointcut extends PatternNode {
}
public void check(ISourceContext ctx,World world) {
PoliceExtensionUse pointcutPolice = new PoliceExtensionUse(world,this);
this.accept(pointcutPolice, null);
if (pointcutPolice.synchronizationDesignatorEncountered())
world.setSynchronizationPointcutsInUse();
}

//public void prepare(Shadow shadow) {}

Loading…
Cancel
Save