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/CreateFieldAccessAdapter.java')
-rw-r--r--plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateFieldAccessAdapter.java130
1 files changed, 130 insertions, 0 deletions
diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateFieldAccessAdapter.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateFieldAccessAdapter.java
new file mode 100644
index 000000000..2b240e36f
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateFieldAccessAdapter.java
@@ -0,0 +1,130 @@
+/**********************************************************************
+ * 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.bytecode.Field;
+import org.eclipse.objectteams.otredyn.bytecode.Method;
+import org.eclipse.objectteams.otredyn.transformer.names.ConstantMembers;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.FieldInsnNode;
+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.MethodNode;
+import org.objectweb.asm.tree.TypeInsnNode;
+
+/**
+ * Creates and adds the instructions,
+ * that are needed to access a not visible field from the team
+ * in the method access or accessStatic as follows:<br/> <br/>
+ * case (memberId) { // generated by CreateSwitchForAccessAdapter <br/>
+ * if (opKind == 0) { <br/>
+ * return field; <br/>
+ * } else { <br/>
+ * field = args[0]; <br/>
+ * } <br/>
+ * break; <br/>
+ * }
+ *
+ * @author Oliver Frank
+ */
+public class CreateFieldAccessAdapter extends AbstractTransformableClassNode {
+
+ private Field field;
+ private int accessId;
+ private Method access;
+ private int firstArgIndex;
+
+ public CreateFieldAccessAdapter(Field field, int accessId) {
+ this.field = field;
+ this.accessId = accessId;
+ if (field.isStatic()) {
+ access = ConstantMembers.accessStatic;
+ firstArgIndex = 0;
+ } else {
+ access = ConstantMembers.access;
+ firstArgIndex = 1;
+ }
+ }
+
+ @Override
+ public void transform() {
+
+ InsnList instructions = new InsnList();
+ // put accessId on the stack
+ instructions.add(new IntInsnNode(Opcodes.ILOAD, firstArgIndex + 1));
+ // read or write access
+ LabelNode writeAccess = new LabelNode();
+ instructions.add(new JumpInsnNode(Opcodes.IFNE, writeAccess));
+ // read access
+ if (field.isStatic()) {
+ // get value of field
+ instructions.add(new FieldInsnNode(Opcodes.GETSTATIC, name, field
+ .getName(), field.getSignature()));
+ } else {
+ // put "this" on the stack
+ instructions.add(new IntInsnNode(Opcodes.ALOAD, 0));
+ // get value of field
+ instructions.add(new FieldInsnNode(Opcodes.GETFIELD, name, field
+ .getName(), field.getSignature()));
+ }
+
+ //box value as "Object"
+ Type type = Type.getType(field.getSignature());
+ instructions.add(AsmTypeHelper.getBoxingInstructionForType(type));
+ instructions.add(new InsnNode(Opcodes.ARETURN));
+
+ //write access
+ instructions.add(writeAccess);
+ //put "args" on the stack
+ instructions.add(new IntInsnNode(Opcodes.ALOAD, firstArgIndex + 2));
+ //get the first element of "args"
+ instructions.add(new InsnNode(Opcodes.ICONST_0));
+ instructions.add(new InsnNode(Opcodes.AALOAD));
+ //unbox it
+ if (type.getSort() != Type.ARRAY && type.getSort() != Type.OBJECT) {
+ String objectType = AsmTypeHelper.getObjectType(type);
+ instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, objectType));
+ instructions.add(AsmTypeHelper.getUnboxingInstructionForType(type, objectType));
+ } else {
+ instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, type.getInternalName()));
+ }
+
+ if (field.isStatic()) {
+ //save value in field
+ instructions.add(new FieldInsnNode(Opcodes.PUTSTATIC, name, field.getName(), field.getSignature()));
+ } else {
+ //put "this" on the stack
+ instructions.add(new IntInsnNode(Opcodes.ALOAD, 0));
+ instructions.add(new InsnNode(Opcodes.SWAP));
+ //save value in field
+ instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, name, field.getName(), field.getSignature()));
+ }
+
+ //dummy return
+ instructions.add(new InsnNode(Opcodes.ACONST_NULL));
+ instructions.add(new InsnNode(Opcodes.ARETURN));
+
+ //add the instructions to a new label in the existing switch
+ MethodNode method = getMethod(access);
+ addNewLabelToSwitch(method.instructions, instructions, accessId);
+ }
+
+}

Back to the top