001: /**
002: * Copyright (C) 2001-2005 France Telecom R&D
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: */package org.objectweb.speedo.generation.enhancer.pc;
018:
019: import org.objectweb.asm.ClassVisitor;
020: import org.objectweb.asm.CodeVisitor;
021: import org.objectweb.asm.Label;
022: import org.objectweb.asm.Type;
023: import org.objectweb.speedo.genclass.api.SpeedoGenClassCoherence;
024: import org.objectweb.speedo.genclass.api.SpeedoGenClassListener;
025: import org.objectweb.speedo.generation.api.SpeedoCompilerParameter;
026: import org.objectweb.speedo.generation.enhancer.common.Util;
027: import org.objectweb.speedo.generation.generator.lib.AbstractSpeedoGenerator.Field;
028: import org.objectweb.speedo.generation.lib.NamingRules;
029: import org.objectweb.speedo.lib.Personality;
030: import org.objectweb.speedo.metadata.SpeedoClass;
031: import org.objectweb.speedo.metadata.SpeedoField;
032: import org.objectweb.speedo.mim.api.DetachedLifeCycle;
033: import org.objectweb.util.monolog.api.Logger;
034:
035: import java.util.Iterator;
036: import java.util.List;
037: import java.util.Map;
038:
039: /**
040: * Generates the speedo accessors (static and normal) for each persistent field
041: * of the class. It generates also setter for coherency management of relation.
042: *
043: * @author S.Chassande-Barrioz
044: */
045: public class FieldAccessorsAdder extends AbstractPCModifier implements
046: POVariableNames {
047:
048: public FieldAccessorsAdder(ClassVisitor classVisitor,
049: Logger logger, SpeedoClass sc, SpeedoCompilerParameter cp,
050: Personality p) {
051: super (classVisitor, logger, sc, cp, p);
052: }
053:
054: public void visit(final int version, final int access,
055: final String name, final String super Name,
056: final String[] interfaces, final String sourceFile) {
057: Map ctx = getGenerationContext();
058: boolean needSpeedoGenClassListener = ((Boolean) ctx
059: .get("needSpeedoGenClassListener")).booleanValue();
060:
061: String[] itfs;
062: //indicate the number of new interface to add
063: if (needSpeedoGenClassListener) {
064: if (interfaces != null && interfaces.length > 0) {
065: itfs = new String[interfaces.length + 1];
066: System.arraycopy(interfaces, 0, itfs, 1,
067: interfaces.length);
068: } else {
069: itfs = new String[1];
070: }
071: itfs[0] = Type
072: .getInternalName(SpeedoGenClassListener.class);
073: } else {
074: itfs = interfaces;
075: }
076: cv.visit(version, access, name, super Name, itfs, sourceFile);
077: final List fields = (List) ctx.get("fields");
078: final int nbfields = fields.size();
079: for (Iterator iter = fields.iterator(); iter.hasNext();) {
080: Field f = (Field) iter.next();
081: final String ftd = f.jvmType;
082: Type ft = Type.getType(ftd);
083: generateStaticFieldGetter(f, ft);
084: generateStaticFieldSetter(f, ft);
085: generateFieldGetter(f, ft, ftd, nbfields);
086: generateFieldSetter(f, ft, ftd, nbfields);
087: if (f.getCoherentSetter() != null) {
088: generateCoherenceFieldSetter(f, ft, ftd, nbfields);
089: }
090: }
091: if (needSpeedoGenClassListener) {
092: generateSpeedoElementAddedMethod();
093: generateSpeedoElementRemovedMethod();
094: }
095: }
096:
097: private void generateStaticFieldGetter(Field f, Type ft) {
098: //public final static ${f.memoryType} ${f.getter}(${baseClassName} instance) {
099: CodeVisitor mv;
100: mv = cv.visitMethod(ACC_PUBLIC + ACC_FINAL + ACC_STATIC, f
101: .getGetter(), "(" + getJVMType(classToWrite) + ")"
102: + ft.getDescriptor(), null, null);
103: //return instance.${f.getter}();
104: mv.visitVarInsn(ALOAD, 0);
105: mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite, f.getGetter(),
106: "()" + ft.getDescriptor());
107: mv.visitInsn(ft.getOpcode(IRETURN));
108: mv.visitMaxs(0, 0);
109: }
110:
111: private void generateStaticFieldSetter(Field f, Type ft) {
112: //public final static void ${f.setter}(${baseClassName} instance, ${f.memoryType} val) {
113: CodeVisitor mv;
114: mv = cv.visitMethod(ACC_PUBLIC + ACC_FINAL + ACC_STATIC, f
115: .getSetter(), "(" + getJVMType(classToWrite)
116: + ft.getDescriptor() + ")V", null, null);
117: //instance.${f.setter}(val);
118: mv.visitVarInsn(ALOAD, 0); //Class instance
119: mv.visitVarInsn(ft.getOpcode(ILOAD), 1); //field
120: mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite, f.getSetter(),
121: "(" + ft.getDescriptor() + ")V");
122: mv.visitInsn(RETURN);
123: mv.visitMaxs(0, 0);
124: }
125:
126: private void generateFieldGetter(Field f, Type ft, String ftd,
127: int nbField) {
128: CodeVisitor mv;
129: mv = cv.visitMethod(ACC_PUBLIC, f.getGetter(), "()" + ftd,
130: null, null);
131: if (f.isReference) {
132: // if ( (speedoReferenceState != null)
133: generateGetRefState(mv, false);
134: Label l1 = new Label();
135: mv.visitJumpInsn(IFNULL, l1);
136: // && (speedoReferenceState.getDetachedStatus() != DetachedLifeCycle.DETACHED_NONE)
137: generateGetRefState(mv, false);
138: mv.visitMethodInsn(INVOKEVIRTUAL, xfieldsAncestorJCN,
139: "getDetachedStatus", "()B");
140: Util.visitIntConstant(mv, DetachedLifeCycle.DETACHED_NONE);
141: mv.visitInsn(I2B);
142: mv.visitJumpInsn(IF_ICMPEQ, l1);
143: // && !(($classNameFields) speedoReferenceState).${f.name}Loaded
144: generateGetRefState(mv, true);
145: mv.visitFieldInsn(GETFIELD, xfieldsJCN, f.getName()
146: + "Loaded", "Z");
147: mv.visitJumpInsn(IFNE, l1);
148: {
149: mv
150: .visitTypeInsn(
151: NEW,
152: personality
153: .getDetachedFieldAccessExceptionClassNameSlash());
154: mv.visitInsn(DUP);
155: mv
156: .visitLdcInsn("Field "
157: + f.getName()
158: + " cannot be accessed: not loaded when the object has been detached");
159: mv
160: .visitMethodInsn(
161: INVOKESPECIAL,
162: personality
163: .getDetachedFieldAccessExceptionClassNameSlash(),
164: "<init>", "(Ljava/lang/String;)V");
165: mv.visitInsn(ATHROW);
166: }
167: mv.visitLabel(l1);
168: }
169:
170: //StateItf sa = this.speedoReadIntention(new long[] { ... });
171: mv.visitVarInsn(ALOAD, 0);
172: generateFieldIdAsLongArray(f, nbField, mv);
173: mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite,
174: "speedoReadIntention", "([J)" + JT_STATE);
175: mv.visitTypeInsn(CHECKCAST, xfieldsJCN);
176: mv.visitVarInsn(ASTORE, 1);
177:
178: //return sa.f1;
179: mv.visitVarInsn(ALOAD, 1);
180: mv.visitFieldInsn(GETFIELD, xfieldsJCN, f.getName(), ftd);
181: mv.visitInsn(ft.getOpcode(IRETURN));
182: mv.visitMaxs(0, 0);
183: }
184:
185: private void generateFieldSetter(Field f, Type ft, String ftd,
186: int nbField) {
187: CodeVisitor mv;
188: int nextLocalVarIdx = 1 + ft.getSize();
189: mv = cv.visitMethod(ACC_PUBLIC, f.getSetter(),
190: "(" + ftd + ")V", null, null);
191:
192: //if (!speedoIsActive()) {
193: mv.visitVarInsn(ALOAD, 0);
194: mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite,
195: ISACTIVE_FIELD_NAME, "()Z");
196: Label l1 = new Label();
197: mv.visitJumpInsn(IFNE, l1);
198: {
199: //if(speedoReferenceState.getDetachedStatus() != DetachedLifeCycle.DETACHED_NONE) {
200: generateGetRefState(mv, false);
201: mv.visitMethodInsn(INVOKEVIRTUAL, xfieldsAncestorJCN,
202: "getDetachedStatus", "()B");
203: Util.visitIntConstant(mv, DetachedLifeCycle.DETACHED_NONE);
204: mv.visitInsn(I2B);
205: Label l3 = new Label();
206: mv.visitJumpInsn(IF_ICMPEQ, l3);
207: {
208: //if (!(($classNameFields) speedoReferenceState).${f.name}Loaded ) {
209: generateGetRefState(mv, true);
210: mv.visitFieldInsn(GETFIELD, xfieldsJCN, f.getName()
211: + "Loaded", "Z");
212: Label l5 = new Label();
213: mv.visitJumpInsn(IFNE, l5);
214: {
215: //throw new DetachedFieldAccessException("Field $f.name cannot be accessed: not loaded when the object has been detached");
216: mv
217: .visitTypeInsn(
218: NEW,
219: personality
220: .getDetachedFieldAccessExceptionClassNameSlash());
221: mv.visitInsn(DUP);
222: mv
223: .visitLdcInsn("Field "
224: + f.getName()
225: + " cannot be accessed: not loaded when the object has been detached");
226: mv
227: .visitMethodInsn(
228: INVOKESPECIAL,
229: personality
230: .getDetachedFieldAccessExceptionClassNameSlash(),
231: "<init>", "(Ljava/lang/String;)V");
232: mv.visitInsn(ATHROW);
233: }
234: mv.visitLabel(l5);
235: //mark the detached copy as dirty
236: //speedoReferenceState.setDetachedStatus(DetachedLifeCycle.DETACHED_DIRTY);
237: generateGetRefState(mv, false);
238: Util.visitIntConstant(mv,
239: DetachedLifeCycle.DETACHED_DIRTY);
240: mv.visitInsn(I2B);
241: mv.visitMethodInsn(INVOKEVIRTUAL, xfieldsAncestorJCN,
242: "setDetachedStatus", "(B)V");
243: }
244: mv.visitLabel(l3);
245: //(($classNameFields) speedoReferenceState).${f.name} = val;
246: generateGetRefState(mv, true);
247: mv.visitVarInsn(ft.getOpcode(ILOAD), 1);
248: mv.visitFieldInsn(PUTFIELD, xfieldsJCN, f.getName(), ftd);
249:
250: //return
251: mv.visitInsn(RETURN);
252: }
253:
254: mv.visitLabel(l1);
255: //The po is activated
256: //Logger logger = ((org.objectweb.jorm.util.api.Loggable) getPClassMapping()).getLogger();
257: mv.visitVarInsn(ALOAD, 0);
258: mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite,
259: "getPClassMapping",
260: "()Lorg/objectweb/jorm/api/PClassMapping;");
261: mv.visitTypeInsn(CHECKCAST,
262: "org/objectweb/jorm/util/api/Loggable");
263: mv.visitMethodInsn(INVOKEINTERFACE,
264: "org/objectweb/jorm/util/api/Loggable", "getLogger",
265: "()Lorg/objectweb/util/monolog/api/Logger;");
266: final int loggerIdx = nextLocalVarIdx;
267: nextLocalVarIdx++;
268: mv.visitVarInsn(ASTORE, loggerIdx);
269:
270: //$classNameFields state = ($classNameFields) speedoWriteIntention(${f.jormFielIdDecl});
271: mv.visitVarInsn(ALOAD, 0);
272: generateFieldIdAsLongArray(f, nbField, mv);
273: mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite,
274: "speedoWriteIntention", "([J)" + JT_STATE);
275: mv.visitTypeInsn(CHECKCAST, xfieldsJCN);
276: final int stateIdx = nextLocalVarIdx;
277: nextLocalVarIdx++;
278: mv.visitVarInsn(ASTORE, stateIdx);
279:
280: if (f.getIsReference()) {
281: generateReferenceSetter(f, ft, nbField, loggerIdx,
282: stateIdx, nextLocalVarIdx, mv);
283: } else {
284: mv.visitVarInsn(ALOAD, stateIdx);
285: mv.visitVarInsn(ft.getOpcode(ILOAD), 1);
286: mv.visitFieldInsn(PUTFIELD, xfieldsJCN, f.getName(), ftd);
287: }
288: mv.visitInsn(RETURN);
289: mv.visitMaxs(0, 0);
290: }
291:
292: /**
293: * Generate the part of the setter concerning reference (the field is a
294: * reference
295: * @param f is the Field descriptor
296: * @param ft is the field type
297: * @param nbField is the total number of field. This value permits to know
298: * the size of the long[] to pass on the speedoWriteIntention call
299: * @param loggerIdx is the register number of the logger local variable
300: * @param mv is the code vistor of the setter method where the code
301: * dedicated to the reference, has to be generated.
302: */
303: private void generateReferenceSetter(Field f, Type ft, int nbField,
304: int loggerIdx, int stateIdx, int nextLocalVarIdx,
305: CodeVisitor mv) {
306: //if (val == state.${f.name}) {
307: mv.visitVarInsn(ALOAD, 1);
308: mv.visitVarInsn(ALOAD, stateIdx);
309: mv.visitFieldInsn(GETFIELD, xfieldsJCN, f.getName(), ft
310: .getDescriptor());
311: Label l12 = new Label();
312: mv.visitJumpInsn(IF_ACMPNE, l12);
313: {
314: mv.visitInsn(RETURN);
315: }
316: mv.visitLabel(l12);
317: Label labelEnd = new Label();
318: //if (val == null) {
319: mv.visitVarInsn(ALOAD, 1);
320: Label labelElse = new Label();
321: mv.visitJumpInsn(IFNONNULL, labelElse);
322: nextLocalVarIdx = generateAssignNullInSetter(f, ft, stateIdx,
323: nextLocalVarIdx, mv);
324: mv.visitJumpInsn(GOTO, labelEnd);
325: mv.visitLabel(labelElse);
326: nextLocalVarIdx = generateAssignNotNullInSetter(f, ft,
327: loggerIdx, stateIdx, nextLocalVarIdx, mv);
328: mv.visitLabel(labelEnd);
329: }
330:
331: /**
332: * Generate the byte code corresponding to a part of the setter method.
333: * This part is the assignement to a null value to a reference field.
334: * #see generateReferenceSetter
335: * @param stateIdx is the number of the register where is stored the
336: * reference to the state (XXXFields instance).
337: * @param nextLocalVarIdx is the next register availlable for declaring a
338: * local variable
339: * @return the next register availlable for declaring a local variable.
340: */
341: private int generateAssignNullInSetter(Field f, Type ft,
342: int stateIdx, int nextLocalVarIdx, CodeVisitor mv) {
343: //state.${f.name}PName = null;
344: mv.visitVarInsn(ALOAD, stateIdx);
345: mv.visitInsn(ACONST_NULL);
346: mv.visitFieldInsn(PUTFIELD, xfieldsJCN, f.getName() + "PName",
347: "Lorg/objectweb/jorm/naming/api/PName;");
348: if (f.isMultiValued) {
349: Label l31 = new Label();
350: mv.visitVarInsn(ALOAD, stateIdx);
351: mv.visitFieldInsn(GETFIELD, xfieldsJCN, f.getName(), ft
352: .getDescriptor());
353: mv.visitJumpInsn(IFNULL, l31);
354: //if (state.${f.name} != null) {
355: {
356: //((SpeedoGenClassPO) state.${f.name}).setElements(null);
357: mv.visitVarInsn(ALOAD, stateIdx);
358: mv.visitFieldInsn(GETFIELD, xfieldsJCN, f.getName(), ft
359: .getDescriptor());
360: mv.visitTypeInsn(CHECKCAST, JCN_GCPO);
361: mv.visitInsn(ACONST_NULL);
362: mv.visitMethodInsn(INVOKEINTERFACE, JCN_GCPO,
363: "setElements", "(Ljava/lang/Object;)V");
364: } //else state.${f.name} is null then there is no generic class
365: mv.visitLabel(l31);
366: } else {
367: mv.visitVarInsn(ALOAD, stateIdx);
368: mv.visitInsn(ACONST_NULL);
369: mv.visitFieldInsn(PUTFIELD, xfieldsJCN, f.getName(), ft
370: .getDescriptor());
371: }
372: return nextLocalVarIdx;
373: }
374:
375: /**
376: * Generate the byte code corresponding to a part of the setter method.
377: * This part is the assignement to a non null value to a reference field.
378: * #see generateReferenceSetter
379: * @param loggerIdx is the number of the register where is stored the logger
380: * @param stateIdx is the number of the register where is stored the
381: * reference to the state (XXXFields instance).
382: * @param nextLocalVarIdx is the next register availlable for declaring a
383: * local variable
384: * @return the next register availlable for declaring a local variable.
385: */
386: private int generateAssignNotNullInSetter(Field f, Type ft,
387: int loggerIdx, int stateIdx, int nextLocalVarIdx,
388: CodeVisitor mv) {
389: if (f.isMultiValued) {
390: //The field '${f.name}' is a multivalued reference
391: //if (state.${f.name} == null) {
392: Label l32 = new Label();
393: mv.visitVarInsn(ALOAD, stateIdx);
394: mv.visitFieldInsn(GETFIELD, xfieldsJCN, f.getName(), ft
395: .getDescriptor());
396: mv.visitJumpInsn(IFNONNULL, l32);
397: {
398: //Allocate a new ${f.gc}
399: //state.initGC${f.name}(logger);
400: mv.visitVarInsn(ALOAD, stateIdx);
401: mv.visitVarInsn(ALOAD, loggerIdx);
402: mv.visitMethodInsn(INVOKEVIRTUAL, xfieldsJCN, "initGC"
403: + f.getName(),
404: "(Lorg/objectweb/util/monolog/api/Logger;)V");
405: }
406: mv.visitLabel(l32);
407: } else {
408: //The field '${f.name}' is a simple reference
409: //state.${f.name} = val;
410: mv.visitVarInsn(ALOAD, stateIdx);
411: mv.visitVarInsn(ALOAD, 1);
412: mv.visitFieldInsn(PUTFIELD, xfieldsJCN, f.getName(), ft
413: .getDescriptor());
414: }
415:
416: //PersistentObjectItf sp = (PersistentObjectItf) state.${f.name};
417: mv.visitVarInsn(ALOAD, stateIdx);
418: mv.visitFieldInsn(GETFIELD, xfieldsJCN, f.getName(), ft
419: .getDescriptor());
420: mv.visitTypeInsn(CHECKCAST, JCN_PO);
421: final int spIdx = nextLocalVarIdx;
422: nextLocalVarIdx++;
423: mv.visitVarInsn(ASTORE, spIdx);
424:
425: //if (!sp.speedoIsActive()) {
426: mv.visitVarInsn(ALOAD, spIdx);
427: mv.visitMethodInsn(INVOKEINTERFACE, JCN_PO,
428: ISACTIVE_FIELD_NAME, "()Z");
429: Label l20 = new Label();
430: mv.visitJumpInsn(IFNE, l20);
431: {
432: //speedoGetPOManager().speedoMakePersistent(sp, null);
433: mv.visitVarInsn(ALOAD, 0);
434: mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite,
435: "speedoGetPOManager", "()" + JT_POM);
436: mv.visitVarInsn(ALOAD, spIdx);
437: mv.visitInsn(ACONST_NULL);
438: mv.visitMethodInsn(INVOKEINTERFACE, JCN_POM,
439: "speedoMakePersistent", "(" + JT_PO
440: + "Ljava/util/Map;)Ljava/lang/Object;");
441: mv.visitInsn(POP);
442: }
443: mv.visitLabel(l20);
444: //state.${f.name}PName = sp.getPName();
445: mv.visitVarInsn(ALOAD, stateIdx);
446: mv.visitVarInsn(ALOAD, spIdx);
447: mv.visitMethodInsn(INVOKEINTERFACE, JCN_PO, "getPName",
448: "()Lorg/objectweb/jorm/naming/api/PName;");
449: mv.visitFieldInsn(PUTFIELD, xfieldsJCN, f.getName() + "PName",
450: "Lorg/objectweb/jorm/naming/api/PName;");
451: if (f.isMultiValued) {
452: //Assign values after the po initialization
453: //((SpeedoGenClassPO) state.${f.name}).setElements(val);
454: mv.visitVarInsn(ALOAD, stateIdx);
455: mv.visitFieldInsn(GETFIELD, xfieldsJCN, f.getName(), ft
456: .getDescriptor());
457: mv.visitTypeInsn(CHECKCAST, JCN_GCPO);
458: mv.visitVarInsn(ALOAD, 1);
459: mv.visitMethodInsn(INVOKEINTERFACE, JCN_GCPO,
460: "setElements", "(Ljava/lang/Object;)V");
461: }
462: return nextLocalVarIdx;
463: }
464:
465: private void generateCoherenceFieldSetter(Field f, Type ft,
466: String ftd, int nbField) {
467: CodeVisitor mv;
468: mv = cv.visitMethod(ACC_PUBLIC, f.getCoherentSetter(), "("
469: + ftd + ")V", null, null);
470: if (f.getIs11Relation()) {
471: generateCoherenceFieldSetter11(f, ft, ftd, nbField, mv);
472: } else if (f.getIsM1Relation()) {
473: generateCoherenceFieldSetterM1(f, ft, ftd, nbField, mv);
474: } else if (f.getIsxMRelation()) {
475: //The coherency management is done on the GenClass implementation
476: // by the setElements method (see the normal setter)
477:
478: //${f.setter}(val);
479: mv.visitVarInsn(ALOAD, 0);
480: mv.visitVarInsn(ft.getOpcode(ILOAD), 1);
481: mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite, f
482: .getSetter(), "(" + ftd + ")V");
483: }
484: mv.visitInsn(RETURN);
485: mv.visitMaxs(0, 0);
486: }
487:
488: private void generateCoherenceFieldSetter11(Field f, Type ft,
489: String ftd, int nbField, CodeVisitor mv) {
490: //${f.memoryType} oldVal = ${f.getter}();
491: mv.visitVarInsn(ALOAD, 0);
492: mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite, f.getGetter(),
493: "()" + ftd);
494: mv.visitVarInsn(ASTORE, 2);
495:
496: //if (oldVal != val) {
497: mv.visitVarInsn(ALOAD, 2);
498: mv.visitVarInsn(ALOAD, 1);
499: Label l2 = new Label();
500: mv.visitJumpInsn(IF_ACMPEQ, l2);
501: {
502: //The assigned value is different from the current
503: //if (oldVal != null) {
504: mv.visitVarInsn(ALOAD, 2);
505: Label l4 = new Label();
506: mv.visitJumpInsn(IFNULL, l4);
507: {
508: //The old value is not null ==> set the reverse field to because
509: // it does not reference anymore 'this' because this references
510: // another stuff.
511: //oldVal.${f.reverseSetter}(null);
512: mv.visitVarInsn(ALOAD, 2);
513: mv.visitInsn(ACONST_NULL);
514: mv.visitMethodInsn(INVOKEVIRTUAL, ft.getInternalName(),
515: f.getReverseSetter(), "("
516: + getJVMType(classToWrite) + ")V");
517: }
518: //if (val != null) {
519: mv.visitLabel(l4);
520: mv.visitVarInsn(ALOAD, 1);
521: Label l6 = new Label();
522: mv.visitJumpInsn(IFNULL, l6);
523: {
524: //The new value is not null ==> set the reverse field to this
525: // because this reference the new value
526: //${baseClassName} reverse = val.${f.reverseGetter}();
527: mv.visitVarInsn(ALOAD, 1);
528: mv.visitMethodInsn(INVOKEVIRTUAL, ft.getInternalName(),
529: f.getReverseGetter(), "()"
530: + getJVMType(classToWrite));
531: mv.visitVarInsn(ASTORE, 3);
532: //if (reverse != null) {
533: mv.visitVarInsn(ALOAD, 3);
534: Label l9 = new Label();
535: mv.visitJumpInsn(IFNULL, l9);
536: {
537: //reverse.${f.setter}(null);
538: mv.visitVarInsn(ALOAD, 3);
539: mv.visitInsn(ACONST_NULL);
540: mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite, f
541: .getSetter(), "(" + ftd + ")V");
542: }
543: //val.${f.reverseSetter}(this);
544: mv.visitLabel(l9);
545: mv.visitVarInsn(ALOAD, 1);
546: mv.visitVarInsn(ALOAD, 0);
547: mv.visitMethodInsn(INVOKEVIRTUAL, ft.getInternalName(),
548: f.getReverseSetter(), "("
549: + getJVMType(classToWrite) + ")V");
550: }
551: //Assign the value
552: //${f.setter}(val);
553: mv.visitLabel(l6);
554: mv.visitVarInsn(ALOAD, 0);
555: mv.visitVarInsn(ALOAD, 1);
556: mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite, f
557: .getSetter(), "(" + ftd + ")V");
558: }
559: mv.visitLabel(l2);
560: }
561:
562: private void generateCoherenceFieldSetterM1(Field f, Type ft,
563: String ftd, int nbField, CodeVisitor mv) {
564: //${f.memoryType} oldVal = ${f.getter}();
565: mv.visitVarInsn(ALOAD, 0);
566: mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite, f.getGetter(),
567: "()" + ftd);
568: mv.visitVarInsn(ASTORE, 2);
569:
570: //if (oldVal != val) {
571: mv.visitVarInsn(ALOAD, 2);
572: mv.visitVarInsn(ALOAD, 1);
573: Label l2 = new Label();
574: mv.visitJumpInsn(IF_ACMPEQ, l2);
575: {
576: //remove this from reverse collection
577: //if (oldVal != null) {
578: mv.visitVarInsn(ALOAD, 2);
579: Label labelOldValIsNull = new Label();
580: mv.visitJumpInsn(IFNULL, labelOldValIsNull);
581: {
582: //((SpeedoGenClassCoherence)oldVal.${f.reverseGetter}())
583: // .speedoRemove(this, ${f.reverseKeyField});
584: mv.visitVarInsn(ALOAD, 2);
585: mv.visitMethodInsn(INVOKEVIRTUAL, ft.getInternalName(),
586: f.getReverseGetter(), "()"
587: + f.reverseField.type);
588: mv.visitTypeInsn(CHECKCAST,
589: getJVMClassName(SpeedoGenClassCoherence.class));
590:
591: mv.visitVarInsn(ALOAD, 0);
592: if (f.getReverseIsMap()) {
593: SpeedoField sf = f.reverseKField;
594: mv.visitVarInsn(ALOAD, 0);
595: mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite,
596: NamingRules.getterName(sf), "()" + sf.type);
597: } else {
598: mv.visitInsn(ACONST_NULL);
599: }
600: mv.visitMethodInsn(INVOKEINTERFACE,
601: getJVMClassName(SpeedoGenClassCoherence.class),
602: "speedoRemove",
603: "(Ljava/lang/Object;Ljava/lang/Object;)Z");
604: mv.visitInsn(POP);
605: }
606: mv.visitLabel(labelOldValIsNull);
607:
608: //assign reference
609: //${f.setter}(val);
610: mv.visitVarInsn(ALOAD, 0);
611: mv.visitVarInsn(ALOAD, 1);
612: mv.visitMethodInsn(INVOKEVIRTUAL, classToWrite, f
613: .getSetter(), "(" + ftd + ")V");
614:
615: //add this from reverse collection
616: //if (val != null) {
617: mv.visitVarInsn(ALOAD, 1);
618: Label labelValIsNull = new Label();
619: mv.visitJumpInsn(IFNULL, labelValIsNull);
620: {
621: //${f.accessorClassName}.speedoAdd(this, ${f.reverseNumber}, (PersistentObjectItf) val);// ${f.reverse}
622: mv.visitVarInsn(ALOAD, 0);
623: Util.visitIntConstant(mv, f.reverseNumber);
624: mv.visitVarInsn(ALOAD, 1);
625: mv.visitTypeInsn(CHECKCAST, JCN_PO);
626: mv.visitMethodInsn(INVOKESTATIC,
627: getJVMClassName(f.accessorClassName),
628: "speedoAdd", "(Ljava/lang/Object;I" + JT_PO
629: + ")V");
630: }
631: mv.visitLabel(labelValIsNull);
632: }
633: mv.visitLabel(l2);
634: }
635:
636: private void generateSpeedoElementAddedMethod() {
637: CodeVisitor mv;
638: mv = cv.visitMethod(ACC_PUBLIC, "speedoElementAdded",
639: "(Ljava/lang/Object;I)V", null, null);
640: //${classNameFields}.speedoElementAdded(elem, gcid, this);
641: mv.visitVarInsn(ALOAD, 1);
642: mv.visitVarInsn(ILOAD, 2);
643: mv.visitVarInsn(ALOAD, 0);
644: mv.visitMethodInsn(INVOKESTATIC, xfieldsJCN,
645: "speedoElementAdded", "(Ljava/lang/Object;I" + JT_PO
646: + ")V");
647: mv.visitInsn(RETURN);
648: mv.visitMaxs(0, 0);
649: }
650:
651: private void generateSpeedoElementRemovedMethod() {
652: CodeVisitor mv;
653: mv = cv.visitMethod(ACC_PUBLIC, "speedoElementRemoved",
654: "(Ljava/lang/Object;I)V", null, null);
655: //${classNameFields}.speedoElementRemoved(elem, gcid, this);
656: mv.visitVarInsn(ALOAD, 1);
657: mv.visitVarInsn(ILOAD, 2);
658: mv.visitVarInsn(ALOAD, 0);
659: mv.visitMethodInsn(INVOKESTATIC, xfieldsJCN,
660: "speedoElementRemoved", "(Ljava/lang/Object;I" + JT_PO
661: + ")V");
662: mv.visitInsn(RETURN);
663: mv.visitMaxs(0, 0);
664: }
665: }
|