Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephan Herrmann2010-04-02 18:34:32 -0400
committerStephan Herrmann2010-04-02 18:34:32 -0400
commit395d4f28ee096e35e73e1a775ee61f1d59d11f40 (patch)
tree18aebff615f2c2eb90acaf1d535e5f8693427341 /othersrc/OTRE
parentf7f058e77e8e7171439ca4ec28ead954c67043c5 (diff)
downloadorg.eclipse.objectteams-395d4f28ee096e35e73e1a775ee61f1d59d11f40.tar.gz
org.eclipse.objectteams-395d4f28ee096e35e73e1a775ee61f1d59d11f40.tar.xz
org.eclipse.objectteams-395d4f28ee096e35e73e1a775ee61f1d59d11f40.zip
Fix (patch v2) for Bug 302745 - [otre] ClassCastException in base call in role-of-role
Diffstat (limited to 'othersrc/OTRE')
-rw-r--r--othersrc/OTRE/src/org/eclipse/objectteams/otre/BaseCallRedirection.java20
-rw-r--r--othersrc/OTRE/src/org/eclipse/objectteams/otre/BaseMethodTransformation.java136
2 files changed, 105 insertions, 51 deletions
diff --git a/othersrc/OTRE/src/org/eclipse/objectteams/otre/BaseCallRedirection.java b/othersrc/OTRE/src/org/eclipse/objectteams/otre/BaseCallRedirection.java
index 65574f39b..5ac779604 100644
--- a/othersrc/OTRE/src/org/eclipse/objectteams/otre/BaseCallRedirection.java
+++ b/othersrc/OTRE/src/org/eclipse/objectteams/otre/BaseCallRedirection.java
@@ -875,6 +875,16 @@ public class BaseCallRedirection extends ObjectTeamsTransformation {
mb.getBaseMethodSignature());
InstructionHandle nextBranch = il.append(new NOP());
+ short invocationKind = isSuperAccess
+ ? Constants.INVOKESTATIC
+ : Constants.INVOKEVIRTUAL;
+
+ String boundBaseClassName = mb.getBaseClassName();
+ if (boundBaseClassName.indexOf(OTDT_PREFIX) != -1) {
+ // if base is a role class, switch now to the interface part to support base-side implicit inheritance:
+ boundBaseClassName = ObjectTeamsTransformation.genRoleInterfaceName(boundBaseClassName);
+ invocationKind = Constants.INVOKEINTERFACE;
+ }
String baseMethodName = mb.getBaseMethodName();
String baseMethodSignature = mb.getBaseMethodSignature();
Type[] baseMethodArgumentTypes = Type.getArgumentTypes(baseMethodSignature);
@@ -911,10 +921,10 @@ public class BaseCallRedirection extends ObjectTeamsTransformation {
InstructionHandle baseCallLine = il.append(InstructionFactory.createThis());
il.append(factory.createFieldAccess(className, BASE, baseClass, Constants.GETFIELD));
- if (!baseClass.getClassName().equals(mb.getBaseClassName())) {
+ if (!baseClass.getClassName().equals(boundBaseClassName)) {
// playedBy has been refined in the sub role;
// create a cast to the sub base class:
- il.append(factory.createCast(baseClass, new ObjectType(mb.getBaseClassName())));
+ il.append(factory.createCast(baseClass, new ObjectType(boundBaseClassName)));
}
// --- load arguments of the new method: ---
@@ -946,13 +956,11 @@ public class BaseCallRedirection extends ObjectTeamsTransformation {
// --- done loading ---
// invoke the chaining method of the base class (base-call!):
- il.append(factory.createInvoke(mb.getBaseClassName(),
+ il.append(factory.createInvoke(boundBaseClassName,
baseChainMethodName,
baseChainReturnType,
enhancedBaseArgumentTypes,
- isSuperAccess
- ? Constants.INVOKESTATIC
- : Constants.INVOKEVIRTUAL
+ invocationKind
));
boolean resultLiftingNecessary = ((mb.getTranslationFlags()&1)!=0);
diff --git a/othersrc/OTRE/src/org/eclipse/objectteams/otre/BaseMethodTransformation.java b/othersrc/OTRE/src/org/eclipse/objectteams/otre/BaseMethodTransformation.java
index a5984463b..1e2799d75 100644
--- a/othersrc/OTRE/src/org/eclipse/objectteams/otre/BaseMethodTransformation.java
+++ b/othersrc/OTRE/src/org/eclipse/objectteams/otre/BaseMethodTransformation.java
@@ -288,13 +288,6 @@ public class BaseMethodTransformation
}*/
//inheritedSigns.addAll(interfaceInheritedSigns);
- boolean haveDirectCallin =
- CallinBindingManager.isBoundBaseClass(class_name);
- // IMPLICIT_INHERITANCE
- if (inheritedBindings.size() == 0 && !haveDirectCallin /*&& interfaceInheritedSigns.size()==0*/) {
- if(logging) printLogMessage("\nCallins: nothing to do for class " + class_name); //$NON-NLS-1$
- return; // nothing to do
- }
// if class is already transformed by this transformer
/*
if (interfaceTransformedClasses.contains(class_name))
@@ -302,9 +295,42 @@ public class BaseMethodTransformation
*/
if(cg.isInterface()) {
+ // may need to add an interface version of the chaining wrapper, to be called for a base-call
+ int lastDollar = class_name.lastIndexOf('$');
+ if (lastDollar != -1) {
+ // try inserting __OT__ to last type name segment
+ String roleClassName = class_name.substring(0, lastDollar+1)+"__OT__"+class_name.substring(lastDollar+1);
+ if (CallinBindingManager.isBoundBaseClass(roleClassName)) {
+ Method[] methods = cg.getMethods();
+ for (int i=0; i<methods.length; i++) {
+ Method m = methods[i];
+ if (m.isVolatile()) // bridge method!
+ continue;
+ String method_name = m.getName();
+ String signature = m.getSignature();
+ Collection<MethodBinding> bindingsForMethod = CallinBindingManager .
+ getBindingForBaseMethod(roleClassName, method_name, signature);
+ if (bindingsForMethod!= null) {
+ MethodGen chainGen = generateChainingWrapper(class_name, cpg,
+ m.getAccessFlags()|Constants.ACC_ABSTRACT, method_name, signature, null/*argumentNames*/);
+ if (cg.containsMethod(chainGen.getName(), chainGen.getSignature()) == null)
+ ce.addMethod(chainGen.getMethod(), cg);
+ }
+ }
+ }
+ }
+
//CallinBindingManager.addBoundBaseInterface(class_name); // <- this is to late, implementing class may be loaded before!!
return; // No transfomations neccessary for interfaces.
}
+
+ boolean haveDirectCallin =
+ CallinBindingManager.isBoundBaseClass(class_name);
+ // IMPLICIT_INHERITANCE
+ if (inheritedBindings.size() == 0 && !haveDirectCallin /*&& interfaceInheritedSigns.size()==0*/) {
+ if(logging) printLogMessage("\nCallins: nothing to do for class " + class_name); //$NON-NLS-1$
+ return; // nothing to do
+ }
if(logging) printLogMessage("\nCallin bindings may be changing class " //$NON-NLS-1$
+ class_name + ':');
@@ -340,7 +366,6 @@ public class BaseMethodTransformation
MethodGen mg = null;
int firstLine = STEP_OVER_LINENUMBER;
- String original_signature = method_signature;
/*if (bindingsForMethod != null || containsSign(inheritedSigns, m)*/ /*|| containsSign(interfaceInheritedSigns, m)*/ //) {
MethodBinding inheritedBinding = matchingBinding(inheritedBindings, m, false);
String method_key = method_name+'.'+method_signature;
@@ -380,10 +405,11 @@ public class BaseMethodTransformation
//CH: changed 'inheritedCallinBindings' to 'inheritedSigns', because it was the same.
if (bindingsForMethod != null) {
//add method '_OT$<method_name>$chain' :
- Method chain;
mg = getConcretMethodGen(m, class_name, cpg);
- chain = generateChainingWrapper(mg, method_name,
- original_signature/*method_signature*/, class_name, cpg, cg, firstLine);
+ MethodGen chainGen = generateChainingWrapper(class_name, cpg,
+ mg.getAccessFlags(), method_name, method_signature, mg.getArgumentNames());
+ Method chain = generateChainingWrapperBody(class_name, cg, cpg,
+ mg, method_name, method_signature, chainGen, firstLine);
if (cg.containsMethod(chain.getName(), chain.getSignature()) == null)
ce.addMethod(chain, cg);
@@ -735,44 +761,64 @@ public class BaseMethodTransformation
/**
* Generate a chaining wrapper for the original method described by the passed arguments.
- * This includes dispatch code and the termination condition for the recursion.
- * @param mg the MethodGen of the original method
+ * @param class_name the name of the appropriate class
+ * @param cpg the ConstantPoolGen of the class
+ * @param accessFlags raw flags of the method to add, visibility will however be ignored/set to public inside
* @param method_name the name of the original method
- * @param method_signature the signature of the original method
- * @param class_name the name of the appropriate class
- * @param cpg the ConstantPoolGen of the class
- * @param cg the ClassGen of the class
- * @param firstLine the first real source line of this method
- * @return
+ * @param method_signature the signature of the original method
+ * @param argumentNames source level argument names, may be null
+ * @return an new method with an empty instruction list
*/
- Method generateChainingWrapper(MethodGen mg,
- String method_name,
- String method_signature,
- String class_name,
- ConstantPoolGen cpg,
- ClassGen cg,
- int firstLine)
+ MethodGen generateChainingWrapper(String class_name,
+ ConstantPoolGen cpg,
+ int accessFlags,
+ String method_name,
+ String method_signature,
+ String[] argumentNames)
{
- Type origReturnType = mg.getReturnType();
- Type[] argumentTypes = mg.getArgumentTypes();
- String[] argumentNames = mg.getArgumentNames();
- Type[] enhancedArgumentTypes = enhanceArgumentTypes(argumentTypes);
- String[] enhancedArgumentNames = enhanceArgumentNames(argumentNames);
- Type enhancedReturnType = object; // ALWAYS!
-
- InstructionList il = new InstructionList();
-
- // the chaining wrapper has to be 'public' because it will be called by base calls:
- int accessFlags = makePublicFlags(mg.getAccessFlags());
+ Type[] argumentTypes = Type.getArgumentTypes(method_signature);
+ if (argumentNames == null) {
+ argumentNames = new String[argumentTypes.length];
+ for (int i = 0; i < argumentNames.length; i++)
+ argumentNames[i] = "arg"+i;
+ }
+ return new MethodGen(makePublicFlags(accessFlags), // the chaining wrapper has to be 'public' because it will be called by base calls:
+ object, // ALWAYS!
+ enhanceArgumentTypes(argumentTypes),
+ enhanceArgumentNames(argumentNames),
+ genChainMethName(method_name),
+ class_name,
+ new InstructionList(),
+ cpg);
+ }
+
+ /**
+ * Create the instructions for the chaining wrapper, which includes dispatch code
+ * and the termination condition for the recursion.
+ * @param class_name
+ * @param cg
+ * @param cpg
+ * @param mg
+ * @param method_name
+ * @param method_signature
+ * @param chainMethod
+ * @param firstLine
+ * @return
+ */
+ Method generateChainingWrapperBody(String class_name,
+ ClassGen cg,
+ ConstantPoolGen cpg,
+ MethodGen mg,
+ String method_name,
+ String method_signature,
+ MethodGen chainMethod,
+ int firstLine)
+ {
+ Type origReturnType = mg.getReturnType();
+ Type[] argumentTypes = mg.getArgumentTypes();
+ Type enhancedReturnType = chainMethod.getReturnType();
+ InstructionList il = chainMethod.getInstructionList();
- MethodGen chainMethod = new MethodGen(accessFlags,
- enhancedReturnType,
- enhancedArgumentTypes,
- enhancedArgumentNames,
- genChainMethName(method_name),
- class_name,
- il, cpg);
-
// All chaining calls return an Object.
// Need to store this in a local variable to keep the stack
// balanced, because each section (before, replace, after)

Back to the top