Bug 473549 - [otdre] trouble with decapsulation in a base class
hierarchy
- WIP, regression in test1126_nestingAndLayering4pf
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IntLiteral.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IntLiteral.java
index 2fa4070..b1c7fb5 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IntLiteral.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IntLiteral.java
@@ -53,6 +53,9 @@
}
return new IntLiteral(token, intReducedToken != token ? intReducedToken : null, s, e);
}
+//{ObjectTeams:
+protected
+// SH}
IntLiteral(char[] token, char[] reducedForm, int start, int end) {
super(token, start, end);
this.reducedForm = reducedForm;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
index 1d7dbf4..d6a019b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
@@ -64,6 +64,7 @@
import static org.eclipse.jdt.internal.compiler.ast.ExpressionContext.*;
import static org.eclipse.objectteams.otdt.core.compiler.IOTConstants.CALLIN_FLAG_DEFINITELY_MISSING_BASECALL;
import static org.eclipse.objectteams.otdt.core.compiler.IOTConstants.CALLIN_FLAG_POTENTIALLY_MISSING_BASECALL;
+import static org.eclipse.objectteams.otdt.internal.core.compiler.lookup.SyntheticOTTargetMethod.OTDREMethodDecapsulation;
import java.util.HashMap;
@@ -117,7 +118,6 @@
import org.eclipse.objectteams.otdt.internal.core.compiler.control.ITranslationStates;
import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.AnchorMapping;
import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.DependentTypeBinding;
-import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.SyntheticOTTargetMethod;
import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.SyntheticRoleBridgeMethodBinding;
import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.WeakenedTypeBinding;
import org.eclipse.objectteams.otdt.internal.core.compiler.mappings.CalloutImplementor;
@@ -1074,7 +1074,11 @@
this.accessId = scope.enclosingSourceType().roleModel.addInaccessibleBaseMethod(this.binding);
if (weavingScheme == WeavingScheme.OTDRE) {
MethodBinding accessor = CalloutImplementorDyn.ensureAccessor(scope, this.binding.declaringClass, this.binding.isStatic());
- this.syntheticAccessor = new SyntheticOTTargetMethod.OTDREMethodDecapsulation(accessor, this.binding.parameters, this.binding.returnType, this.accessId, scope, this);
+ OTDREMethodDecapsulation updatableAccessor = new OTDREMethodDecapsulation(accessor, this.binding.parameters, this.binding.returnType, this.accessId, scope, this);
+ ReferenceBinding enclosingType = scope.enclosingSourceType().enclosingType();
+ if (enclosingType != null && enclosingType.isTeam())
+ enclosingType.getTeamModel().recordUpdatableAccessId(updatableAccessor);
+ this.syntheticAccessor = updatableAccessor;
} else {
this.binding = new MethodBinding(this.binding, this.binding.declaringClass.getRealClass());
this.binding.selector = CharOperation.concat(IOTConstants.OT_DECAPS, this.selector);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
index 64b95b4..7009d65 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
@@ -964,6 +964,7 @@
}
if (isTeam()) {
CopyInheritance.copySyntheticTeamMethods(this);
+ getTeamModel().updateDecapsAccessIds();
}
// value paramters:
this.binding.computeValueParameterSlotSizes();
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/BaseAllocationExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/BaseAllocationExpression.java
index 53958d7..b98f24d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/BaseAllocationExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/BaseAllocationExpression.java
@@ -67,6 +67,7 @@
import org.eclipse.objectteams.otdt.internal.core.compiler.mappings.CalloutImplementorDyn;
import org.eclipse.objectteams.otdt.internal.core.compiler.model.MethodModel;
import org.eclipse.objectteams.otdt.internal.core.compiler.model.RoleModel;
+import org.eclipse.objectteams.otdt.internal.core.compiler.model.TeamModel.UpdatableIntLiteral;
import org.eclipse.objectteams.otdt.internal.core.compiler.util.AstGenerator;
/**
@@ -262,11 +263,13 @@
int modifiers = ClassFileConstants.AccPublic|ClassFileConstants.AccStatic;
Expression[] arguments = expression.arguments;
Expression enclosingInstance = null;
+ ReferenceBinding enclosingTeam = null;
if (expression instanceof QualifiedAllocationExpression) {
enclosingInstance = ((QualifiedAllocationExpression) expression).enclosingInstance;
+ // TODO: enclosing team (for accessId-updating)?
} else if (baseclass.isMemberType()) {
// extract the enclosing base instance from an outer playedBy:
- ReferenceBinding enclosingTeam = scope.enclosingReceiverType().enclosingType();
+ enclosingTeam = scope.enclosingReceiverType().enclosingType();
if (enclosingTeam != null
&& TypeBinding.equalsEquals(baseclass.enclosingType(), enclosingTeam.baseclass)) {
enclosingInstance = gen.fieldReference(
@@ -301,7 +304,7 @@
allocSend.constant = Constant.NotAConstant;
allocSend.actualReceiverType = baseclass;
allocSend.accessId = accessId;
- allocSend.arguments = createResolvedAccessArguments(gen, accessId, arguments, scope);
+ allocSend.arguments = createResolvedAccessArguments(gen, accessId, arguments, enclosingTeam, scope);
allocSend.binding = new MethodBinding(modifiers, new TypeBinding[] {
TypeBinding.INT,
TypeBinding.INT,
@@ -315,9 +318,11 @@
return gen.resolvedCastExpression(allocSend, baseclass, CastExpression.RAW);
}
- private static Expression[] createResolvedAccessArguments(AstGenerator gen, int accessId, Expression[] arguments, BlockScope scope) {
- IntLiteral accessIdLiteral = gen.intLiteral(accessId);
+ private static Expression[] createResolvedAccessArguments(AstGenerator gen, int accessId, Expression[] arguments, ReferenceBinding enclosingTeam, BlockScope scope) {
+ UpdatableIntLiteral accessIdLiteral = gen.updatableIntLiteral(accessId);
accessIdLiteral.resolveType(scope);
+ if (enclosingTeam != null)
+ enclosingTeam.getTeamModel().recordUpdatableAccessId(accessIdLiteral);
IntLiteral opKindLiteral = gen.intLiteral(0);
opKindLiteral.resolveType(scope);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/bytecode/OTSpecialAccessAttribute.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/bytecode/OTSpecialAccessAttribute.java
index 9f1fbfb..0ebab2b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/bytecode/OTSpecialAccessAttribute.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/bytecode/OTSpecialAccessAttribute.java
@@ -61,9 +61,11 @@
private static final int DYN_CALLOUT_FIELD_ACCESS = 5;
private static final int DYN_SUPER_METHOD_ACCESS = 6;
- /*
+ /**
* For OTREDyn, each attribute of this type maintains a set of locally unique (per team) access IDs.
- * These IDs are consumed and translated by OTREDyn to obtain those IDs that uniquely identify the
+ * These IDs are later made unique per team-hierarchy by adding {@link #accessIdOffset}.
+ * This for of ids is then stored in the attribute.
+ * Stored ids are consumed and translated by OTREDyn to obtain those global IDs that uniquely identify the
* base feature within a generated _OT$access or _OT$accessStatic method.
*
* AccessIds are generated during resolve and stored in these AST nodes:
@@ -72,13 +74,18 @@
* the accessId as an argument for the generated _OT$access[Static] call.
* - MessageSend; accessId is preset for message sends implementing decapsulating BaseAllocationExpression
* - regular base class:
- * - detected during AllocationExpression.resolveType, throws ConstructorDecapsulationExpression
+ * - detected during AllocationExpression.resolveType, throws ConstructorDecapsulationException
* - allocation is then replaced by a MessageSend to the _OT$access method
* - base is role:
* - generated AST has accessId = -1 to be updated during MessageSend.resolveType() if decaps needed
+ * The UpdatableAccessId representing the accessId in any of these generated ASTs / synthetic binding
+ * is updated after disambiguation from TeamModel.updateDecapsAccessIds().
*/
- int nextAccessId = 0;
-
+ public int nextAccessId = 0;
+
+ /** Updated by {@link TeamModel#updateDecapsAccessIds()} to denote the space of ids used by super teams. */
+ public int accessIdOffset;
+
/** Descriptor for a decapsulated base-method. */
private class DecapsulatedMethodDesc {
ReferenceBinding boundBaseclass;
@@ -140,7 +147,7 @@
writeName(this.method.signature());
}
if (OTSpecialAccessAttribute.this._weavingScheme == WeavingScheme.OTDRE)
- writeUnsignedShort(this.accessId);
+ writeUnsignedShort(this.accessId + OTSpecialAccessAttribute.this.accessIdOffset);
}
public String toString() {
@@ -188,7 +195,7 @@
void write() {
if (OTSpecialAccessAttribute.this._weavingScheme == WeavingScheme.OTDRE) {
writeByte((byte)DYN_CALLOUT_FIELD_ACCESS);
- writeUnsignedShort(this.accessId);
+ writeUnsignedShort(this.accessId + OTSpecialAccessAttribute.this.accessIdOffset);
} else {
writeByte((byte)CALLOUT_FIELD_ACCESS);
}
@@ -452,5 +459,4 @@
}
return result.toString();
}
-
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lookup/SyntheticOTTargetMethod.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lookup/SyntheticOTTargetMethod.java
index cfbdca8..a9d2c47 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lookup/SyntheticOTTargetMethod.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lookup/SyntheticOTTargetMethod.java
@@ -27,6 +27,7 @@
import org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
+import org.eclipse.objectteams.otdt.internal.core.compiler.model.TeamModel;
/**
* A synthetic method binding, which used as an invocation target needs to
@@ -145,7 +146,7 @@
* Represents a decapsulating method access while targeting OTDRE (not an explicit callout).
* We need to generate a special sequence to call _OT$access(int,int,Object[],ITeam)
*/
- public static class OTDREMethodDecapsulation extends SyntheticOTTargetMethod {
+ public static class OTDREMethodDecapsulation extends SyntheticOTTargetMethod implements TeamModel.UpdatableAccessId {
private int accessId;
private ReferenceBinding enclosingTeam;
@@ -236,6 +237,11 @@
}
return 0; // signal we're done
}
+
+ @Override
+ public void update(int offset) {
+ this.accessId += offset;
+ }
}
static int size(TypeBinding type) {
switch (type.id) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CalloutImplementorDyn.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CalloutImplementorDyn.java
index 9dda280..3216538 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CalloutImplementorDyn.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CalloutImplementorDyn.java
@@ -50,7 +50,8 @@
{
char[] selector = ensureAccessor(scope, baseType, baseSpec.isStatic()).selector;
TeamModel teamModel = roleModel.getTeamModel();
- Expression accessIdArg = gen.intLiteral(baseSpec.accessId);
+ TeamModel.UpdatableIntLiteral accessIdArg = gen.updatableIntLiteral(baseSpec.accessId);
+ teamModel.recordUpdatableAccessId(accessIdArg); // may need updating before codeGen.
int opKind = 0;
if (baseSpec instanceof FieldAccessSpec)
if (((FieldAccessSpec) baseSpec).calloutModifier == TerminalTokens.TokenNameset)
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/model/TeamModel.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/model/TeamModel.java
index 21d4dd1..4ff7f5c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/model/TeamModel.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/model/TeamModel.java
@@ -30,8 +30,11 @@
import org.eclipse.jdt.internal.compiler.ClassFile;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.IntLiteral;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions.WeavingScheme;
+import org.eclipse.jdt.internal.compiler.impl.IntConstant;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
@@ -966,4 +969,58 @@
}
return 0;
}
+
+// =======================================================================================
+// = Support for ensuring uniqueness of accessIds among a team and all its super teams. =
+
+ public static interface UpdatableAccessId {
+ void update(int offset);
+ }
+
+ public static class UpdatableIntLiteral extends IntLiteral implements UpdatableAccessId {
+ int val;
+ public UpdatableIntLiteral(int val, int start, int end) {
+ super(String.valueOf(val).toCharArray(), null, start, end);
+ this.val = val;
+ }
+ @Override
+ public void update(int offset) {
+ this.constant = IntConstant.fromValue(this.val + offset);
+ }
+ }
+
+ /** Region of ids used by this team and its supers. */
+ int accessIdOffset = -1;
+ /** accessIds that may require updating. */
+ List<UpdatableAccessId> updatableAccessIds = null;
+
+ public void recordUpdatableAccessId(UpdatableAccessId updatableAccessId) {
+ if (this.updatableAccessIds == null)
+ this.updatableAccessIds = new ArrayList<>();
+ this.updatableAccessIds.add(updatableAccessId);
+ }
+
+ /** Update all recorded accessIds to stay clear of id ranges used by super teams. */
+ public int updateDecapsAccessIds() {
+ if (this.accessIdOffset > -1 || this.weavingScheme != WeavingScheme.OTDRE) return this.accessIdOffset;
+
+ this.accessIdOffset = 0;
+
+ TeamModel superTeam = getSuperTeam();
+ if (superTeam != null)
+ this.accessIdOffset += superTeam.updateDecapsAccessIds();
+
+ // update ASTs above super's id range if needed:
+ if (this.updatableAccessIds != null && this.accessIdOffset > 0)
+ for (UpdatableAccessId updater : this.updatableAccessIds)
+ updater.update(this.accessIdOffset);
+
+ if (this._specialAccess != null) {
+ // update attribute if needed:
+ this._specialAccess.accessIdOffset = this.accessIdOffset;
+ // include local value in the total offset:
+ this.accessIdOffset += this._specialAccess.nextAccessId;
+ }
+ return this.accessIdOffset;
+ }
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/model/TypeModel.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/model/TypeModel.java
index 4591c43..abf48e5 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/model/TypeModel.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/model/TypeModel.java
@@ -513,7 +513,7 @@
assert this._specialAccess == null;
this._specialAccess = attribute;
}
- protected OTSpecialAccessAttribute getSpecialAccessAttribute() {
+ public OTSpecialAccessAttribute getSpecialAccessAttribute() {
if (this._specialAccess == null) {
this._specialAccess = new OTSpecialAccessAttribute(this._binding, getWeavingScheme());
addAttribute(this._specialAccess);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/AstGenerator.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/AstGenerator.java
index 7f6b01c..71986b4 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/AstGenerator.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/AstGenerator.java
@@ -71,6 +71,7 @@
import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.ITeamAnchor;
import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.TThisBinding;
import org.eclipse.objectteams.otdt.internal.core.compiler.model.RoleModel;
+import org.eclipse.objectteams.otdt.internal.core.compiler.model.TeamModel;
/**
* This factory creates "generated" elements, ie., elements that have
@@ -334,6 +335,9 @@
IntLiteral result = IntLiteral.buildIntLiteral(String.valueOf(val).toCharArray(), this.sourceStart, this.sourceEnd);
return result;
}
+ public TeamModel.UpdatableIntLiteral updatableIntLiteral(int val) {
+ return new TeamModel.UpdatableIntLiteral(val, this.sourceStart, this.sourceEnd);
+ }
public Literal booleanLiteral(boolean val) {
MagicLiteral result = val
? new TrueLiteral(this.sourceStart, this.sourceEnd)
diff --git a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/DelegatingTransformer.java b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/DelegatingTransformer.java
index 1755f00..9996724 100644
--- a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/DelegatingTransformer.java
+++ b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/DelegatingTransformer.java
@@ -24,7 +24,6 @@
import java.net.URL;
import java.security.ProtectionDomain;
import java.util.Collection;
-import java.util.List;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.objectteams.internal.osgi.weaving.OTWeavingHook.WeavingReason;
@@ -134,14 +133,6 @@
return new IWeavingContext() {
@Override
public boolean isWeavable(String className) {
- // currently, we don't support implicit crossing of bundle boundaries,
- // so check if the requested class is provided by the current bundle:
- int lastDot = className.lastIndexOf('.');
- String path = className.substring(0, lastDot).replace('.', '/');
- String filePattern = className.substring(lastDot+1)+".class";
- List<URL> entry = bundleWiring.findEntries(path, filePattern, 0);
- if (entry == null || entry.isEmpty())
- return false;
return hook.requiresWeaving(bundleWiring, className, null) != WeavingReason.None;
}
};
diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AsmWritableBoundClass.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AsmWritableBoundClass.java
index b41ee8f..10246fe 100644
--- a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AsmWritableBoundClass.java
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AsmWritableBoundClass.java
@@ -460,10 +460,9 @@
@Override
protected void prepareForFirstMemberAccess() {
if (!isTransformedForMemberAccess && !isInterface()) {
- nodes.add(new CreateSwitchForAccessAdapter(ConstantMembers.access,
- getInternalSuperClassName(), this));
- nodes.add(new CreateSwitchForAccessAdapter(ConstantMembers.accessStatic,
- getInternalSuperClassName(), this));
+ String superClassName = this.weavingContext.isWeavable(getSuperClassName()) ? getInternalSuperClassName() : null;
+ nodes.add(new CreateSwitchForAccessAdapter(ConstantMembers.access, superClassName, this));
+ nodes.add(new CreateSwitchForAccessAdapter(ConstantMembers.accessStatic, superClassName, this));
isTransformedForMemberAccess = true;
}
diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateSwitchForAccessAdapter.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateSwitchForAccessAdapter.java
index 9d47646..ebeedfe 100644
--- a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateSwitchForAccessAdapter.java
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateSwitchForAccessAdapter.java
@@ -53,11 +53,9 @@
@Override
protected void addPreSwitchInstructions(MethodNode method) {
// put "accessId" on the stack
- method.instructions.add(new IntInsnNode(Opcodes.ILOAD,
- getFirstArgIndex()));
+ method.instructions.add(new IntInsnNode(Opcodes.ILOAD, getFirstArgIndex()));
// put "caller".getClass() on the stack
- method.instructions.add(new IntInsnNode(Opcodes.ALOAD,
- getFirstArgIndex() + 3));
+ method.instructions.add(new IntInsnNode(Opcodes.ALOAD, getFirstArgIndex() + 3));
method.instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false));
// call "getMemberId(accessId, callerClass)
method.instructions
@@ -70,7 +68,7 @@
@Override
protected void addInstructionForDefaultLabel(MethodNode method) {
- if (superClassName.equals("java/lang/Object")) {
+ if (superClassName == null || superClassName.equals("java/lang/Object")) {
method.instructions.add(new TypeInsnNode(Opcodes.NEW, "org/objectteams/NoSuchMethodError"));
method.instructions.add(new InsnNode(Opcodes.DUP));
method.instructions.add(new IntInsnNode(Opcodes.ILOAD, getFirstArgIndex())); // accessId
@@ -88,14 +86,14 @@
}
method.instructions.add(new MethodInsnNode(opcode,
superClassName, getMethod().getName(),
- getMethod().getSignature()));
+ getMethod().getSignature(), false));
method.instructions.add(new InsnNode(Opcodes.ARETURN));
}
}
@Override
protected int getMaxStack() {
- return 5;
+ return 6;
}
}
diff --git a/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otredyn/runtime/TeamManager.java b/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otredyn/runtime/TeamManager.java
index 4a088df..fb4cf2c 100644
--- a/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otredyn/runtime/TeamManager.java
+++ b/plugins/org.eclipse.objectteams.runtime/src/org/eclipse/objectteams/otredyn/runtime/TeamManager.java
@@ -41,7 +41,7 @@
private static List<List<ITeam>> _teams = new ArrayList<List<ITeam>>();
private static List<List<Integer>> _callinIds = new ArrayList<List<Integer>>();
private static Map<String, Integer> joinpointMap = new HashMap<String, Integer>();
- // key: Team class, value: list of global memberIds, indexed by local accessId
+ // key: Team class, value: list of global memberIds, indexed by local accessId, id of null means "not mapped in this team (try super)"
private static Map<Class<?>, List<Integer>> accessIdMap = new HashMap<Class<?>, List<Integer>>();
private static int currentJoinpointId = 0;
// map all original joinpoints to their inherited versions in subclasses
@@ -116,15 +116,14 @@
*/
public static int getMemberId(int accessId, Class<? extends ITeam> teamClass) {
List<Integer> teamMap = accessIdMap.get(teamClass);
- if (teamMap == null) {
- // TODO: is it safe to assume that the accessId is the same between sub & super teams?
+ Integer id = -1;
+ if (teamMap == null || (id = teamMap.get(accessId)) == null) {
Class<?> superClass = teamClass.getSuperclass();
if (ITeam.class.isAssignableFrom(superClass)) {
@SuppressWarnings("unchecked") Class<? extends ITeam> superTeam = (Class<? extends ITeam>) superClass;
return getMemberId(accessId, superTeam);
}
}
- Integer id = teamMap.get(accessId);
return id;
}
@@ -294,7 +293,7 @@
int highestAccessId = teem.getHighestAccessId() + 1;
accessIds = new ArrayList<Integer>(highestAccessId);
for (int i = 0; i <= highestAccessId; i++) {
- accessIds.add(0);
+ accessIds.add(null);
}
accessIdMap.put(teamClass, accessIds);
}