Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AbstractCreateDispatchCodeAdapter.java')
-rw-r--r--plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AbstractCreateDispatchCodeAdapter.java154
1 files changed, 154 insertions, 0 deletions
diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AbstractCreateDispatchCodeAdapter.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AbstractCreateDispatchCodeAdapter.java
new file mode 100644
index 000000000..449222e98
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AbstractCreateDispatchCodeAdapter.java
@@ -0,0 +1,154 @@
+/**********************************************************************
+ * This file is part of "Object Teams Dynamic Runtime Environment"
+ *
+ * Copyright 2009, 2012 Oliver Frank and others.
+ *
+ * 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
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * Oliver Frank - Initial API and implementation
+ * Stephan Herrmann - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.objectteams.otredyn.bytecode.asm;
+
+import org.eclipse.objectteams.otredyn.transformer.names.ClassNames;
+import org.eclipse.objectteams.otredyn.transformer.names.ConstantMembers;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.InsnList;
+import org.objectweb.asm.tree.InsnNode;
+import org.objectweb.asm.tree.IntInsnNode;
+import org.objectweb.asm.tree.JumpInsnNode;
+import org.objectweb.asm.tree.LabelNode;
+import org.objectweb.asm.tree.MethodInsnNode;
+import org.objectweb.asm.tree.MethodNode;
+import org.objectweb.asm.tree.TypeInsnNode;
+
+/**
+ * Create the code for the dispatch from a base class to the teams. <br/> <br/>
+ * The code was generated as follows: <br/>
+ * <code>
+ * switch (boundMethodId) { // this was generated in CreateSwitchAdapter <br/>
+ * ... <br/>
+ * case (...): // this was generated in concrete implementations <br/>
+ * // of this abstract class <br/>
+ * Teams[] teams = TeamManager.getTeams(joinpointId) <br/><br/>
+ * if (teams == null) { <br/>
+ * break; <br/>
+ * } <br/>
+ * <br/>
+ * Team t = teams[0]; <br/>
+ * int[] callinIds = TeamManager.getCallinIds(joinpointId); <br/>
+ * Object[] args = {arg1, ... , argn};
+ * return team._OT$callAllBindings(this, teams, 0, callinIds, boundMethodId, args);
+ * } <br/>
+ * </code>
+ * @author Oliver Frank
+ */
+public abstract class AbstractCreateDispatchCodeAdapter extends
+ AbstractTransformableClassNode {
+
+ private boolean isStatic;
+
+ public AbstractCreateDispatchCodeAdapter(boolean isStatic) {
+ this.isStatic = isStatic;
+ }
+
+ private Type[] args;
+
+ protected InsnList getDispatchCode(MethodNode method, int joinPointId,
+ int boundMethodId) {
+ InsnList instructions = new InsnList();
+
+ // teams = TeamManager.getTeams(joinpointId)
+ instructions.add(createLoadIntConstant(joinPointId));
+
+ instructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC,
+ ClassNames.TEAM_MANAGER_SLASH, ConstantMembers.getTeams.getName(),
+ ConstantMembers.getTeams.getSignature()));
+
+ instructions.add(createInstructionsToCheackTeams(method));
+
+ // get the first team
+ instructions.add(new InsnNode(Opcodes.DUP));
+ instructions.add(new InsnNode(Opcodes.ICONST_0));
+ instructions.add(new InsnNode(Opcodes.AALOAD));
+ instructions.add(new InsnNode(Opcodes.SWAP));
+ if (isStatic) {
+ instructions.add(new InsnNode(Opcodes.ACONST_NULL));
+ } else {
+ // put "this" on the stack and cast it to IBoundBase
+ instructions.add(new IntInsnNode(Opcodes.ALOAD, 0));
+ instructions.add(new TypeInsnNode(Opcodes.CHECKCAST,
+ ClassNames.I_BOUND_BASE_SLASH));
+ }
+ instructions.add(new InsnNode(Opcodes.SWAP));
+ // start index
+ instructions.add(new InsnNode(Opcodes.ICONST_0));
+
+ // TeamManager.getCallinIds(joinpointId)
+ instructions.add(createLoadIntConstant(joinPointId));
+
+ instructions
+ .add(new MethodInsnNode(Opcodes.INVOKESTATIC,
+ ClassNames.TEAM_MANAGER_SLASH,
+ ConstantMembers.getCallinIds.getName(),
+ ConstantMembers.getCallinIds.getSignature()));
+
+ instructions.add(createLoadIntConstant(boundMethodId));
+ args = Type.getArgumentTypes(method.desc);
+
+ // box the arguments
+ instructions.add(getBoxedArguments(args));
+
+ instructions.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE,
+ ClassNames.ITEAM_SLASH, ConstantMembers.callAllBindingsTeam
+ .getName(), ConstantMembers.callAllBindingsTeam
+ .getSignature()));
+
+ Type returnType = Type.getReturnType(method.desc);
+ instructions.add(getUnboxingInstructionsForReturnValue(returnType));
+
+ return instructions;
+ }
+
+ protected InsnList createInstructionsToCheackTeams(MethodNode method) {
+ // if (teams == null) {
+ // break;
+ // }
+ InsnList instructions = new InsnList();
+ instructions.add(new InsnNode(Opcodes.DUP));
+ LabelNode label = new LabelNode();
+ instructions.add(new JumpInsnNode(Opcodes.IFNONNULL, label));
+ instructions.add(new InsnNode(Opcodes.POP));
+ instructions.add(new JumpInsnNode(Opcodes.GOTO, findBreakLabel(method.instructions)));
+ instructions.add(label);
+ return instructions;
+ }
+
+ private LabelNode findBreakLabel(InsnList instructions) {
+ for (int i = instructions.size() - 1; i >= 0; i--) {
+ AbstractInsnNode node = instructions.get(i);
+ if (node.getType() == AbstractInsnNode.LABEL) {
+ return (LabelNode) node;
+ }
+ }
+ throw new RuntimeException("Can't find break label to create dispatch code");
+ }
+
+ protected abstract InsnList getBoxedArguments(Type[] args);
+
+ protected int getMaxLocals() {
+ return args.length + 1;
+ }
+
+ protected int getMaxStack() {
+ return 10;
+ }
+}

Back to the top