### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core Index: compiler/org/eclipse/jdt/internal/compiler/ast/NameReference.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NameReference.java,v retrieving revision 1.19 diff -u -r1.19 NameReference.java --- compiler/org/eclipse/jdt/internal/compiler/ast/NameReference.java 27 Jun 2008 16:03:55 -0000 1.19 +++ compiler/org/eclipse/jdt/internal/compiler/ast/NameReference.java 24 Sep 2008 12:36:50 -0000 @@ -14,7 +14,7 @@ public abstract class NameReference extends Reference implements InvocationSite { - public Binding binding, codegenBinding; //may be aTypeBinding-aFieldBinding-aLocalVariableBinding + public Binding binding; //may be aTypeBinding-aFieldBinding-aLocalVariableBinding public TypeBinding actualReceiverType; // modified receiver type - actual one according to namelookup Index: compiler/org/eclipse/jdt/internal/compiler/ast/Clinit.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Clinit.java,v retrieving revision 1.53 diff -u -r1.53 Clinit.java --- compiler/org/eclipse/jdt/internal/compiler/ast/Clinit.java 7 Jul 2008 17:08:07 -0000 1.53 +++ compiler/org/eclipse/jdt/internal/compiler/ast/Clinit.java 24 Sep 2008 12:36:50 -0000 @@ -16,6 +16,7 @@ import org.eclipse.jdt.internal.compiler.codegen.BranchLabel; import org.eclipse.jdt.internal.compiler.codegen.CodeStream; import org.eclipse.jdt.internal.compiler.codegen.ConstantPool; +import org.eclipse.jdt.internal.compiler.codegen.Opcodes; import org.eclipse.jdt.internal.compiler.flow.ExceptionHandlingFlowContext; import org.eclipse.jdt.internal.compiler.flow.FlowInfo; import org.eclipse.jdt.internal.compiler.flow.InitializationFlowContext; @@ -173,7 +174,7 @@ falseLabel.place(); codeStream.iconst_0(); jumpLabel.place(); - codeStream.putstatic(this.assertionSyntheticFieldBinding); + codeStream.fieldAccess0(Opcodes.OPC_putstatic, this.assertionSyntheticFieldBinding, null /* default declaringClass */); } // generate static fields/initializers/enum constants final FieldDeclaration[] fieldDeclarations = declaringType.fields; @@ -206,13 +207,13 @@ if (fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) { codeStream.dup(); codeStream.generateInlinedValue(fieldDecl.binding.id); - codeStream.getstatic(fieldDecl.binding); + codeStream.fieldAccess0(Opcodes.OPC_getstatic, fieldDecl.binding, null /* default declaringClass */); codeStream.aastore(); } } } } - codeStream.putstatic(declaringType.enumValuesSyntheticfield); + codeStream.fieldAccess0(Opcodes.OPC_putstatic, declaringType.enumValuesSyntheticfield, null /* default declaringClass */); if (remainingFieldCount != 0) { // if fields that are not enum constants need to be generated (static initializer/static field) for (int i = 0, max = fieldDeclarations.length; i < max; i++) { Index: compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java,v retrieving revision 1.95 diff -u -r1.95 ConstructorDeclaration.java --- compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java 8 Jul 2008 02:01:42 -0000 1.95 +++ compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java 24 Sep 2008 12:36:50 -0000 @@ -228,7 +228,7 @@ if ((syntheticArg = syntheticArgs[i]).matchingField != null) { codeStream.aload_0(); codeStream.load(syntheticArg); - codeStream.putfield(syntheticArg.matchingField); + codeStream.fieldAccess0(Opcodes.OPC_putfield, syntheticArg.matchingField, null /* default declaringClass */); } } syntheticArgs = nestedType.syntheticOuterLocalVariables(); @@ -237,7 +237,7 @@ if ((syntheticArg = syntheticArgs[i]).matchingField != null) { codeStream.aload_0(); codeStream.load(syntheticArg); - codeStream.putfield(syntheticArg.matchingField); + codeStream.fieldAccess0(Opcodes.OPC_putfield, syntheticArg.matchingField, null /* default declaringClass */); } } } Index: compiler/org/eclipse/jdt/internal/compiler/ast/AssertStatement.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AssertStatement.java,v retrieving revision 1.55 diff -u -r1.55 AssertStatement.java --- compiler/org/eclipse/jdt/internal/compiler/ast/AssertStatement.java 12 Sep 2008 19:24:48 -0000 1.55 +++ compiler/org/eclipse/jdt/internal/compiler/ast/AssertStatement.java 24 Sep 2008 12:36:50 -0000 @@ -101,7 +101,7 @@ if (this.assertionSyntheticFieldBinding != null) { BranchLabel assertionActivationLabel = new BranchLabel(codeStream); - codeStream.getstatic(this.assertionSyntheticFieldBinding); + codeStream.fieldAccess0(Opcodes.OPC_getstatic, this.assertionSyntheticFieldBinding, null /* default declaringClass */); codeStream.ifne(assertionActivationLabel); BranchLabel falseLabel; Index: compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java,v retrieving revision 1.120 diff -u -r1.120 FieldReference.java --- compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java 17 Sep 2008 09:08:38 -0000 1.120 +++ compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java 24 Sep 2008 12:36:50 -0000 @@ -17,7 +17,6 @@ import org.eclipse.jdt.internal.compiler.codegen.Opcodes; import org.eclipse.jdt.internal.compiler.flow.FlowContext; import org.eclipse.jdt.internal.compiler.flow.FlowInfo; -import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.Binding; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; @@ -41,11 +40,10 @@ public Expression receiver; public char[] token; public FieldBinding binding; // exact binding resulting from lookup - protected FieldBinding codegenBinding; // actual binding used for code generation (if no synthetic accessor) public MethodBinding[] syntheticAccessors; // [0]=read accessor [1]=write accessor public long nameSourcePosition; //(start<<32)+end - public TypeBinding receiverType; + public TypeBinding actualReceiverType; public TypeBinding genericCast; public FieldReference(char[] source, long pos) { @@ -162,15 +160,16 @@ public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) { int pc = codeStream.position; + FieldBinding codegenBinding = this.binding.original(); this.receiver.generateCode( currentScope, codeStream, - !this.codegenBinding.isStatic()); + !codegenBinding.isStatic()); codeStream.recordPositionsFrom(pc, this.sourceStart); assignment.expression.generateCode(currentScope, codeStream, true); fieldStore( codeStream, - this.codegenBinding, + codegenBinding, this.syntheticAccessors == null ? null : this.syntheticAccessors[FieldReference.WRITE], valueRequired); if (valueRequired) { @@ -195,9 +194,10 @@ codeStream.recordPositionsFrom(pc, this.sourceStart); return; } - boolean isStatic = this.codegenBinding.isStatic(); + FieldBinding codegenBinding = this.binding.original(); + boolean isStatic = codegenBinding.isStatic(); boolean isThisReceiver = this.receiver instanceof ThisReference; - Constant fieldConstant = this.codegenBinding.constant(); + Constant fieldConstant = codegenBinding.constant(); if (fieldConstant != Constant.NotAConstant) { if (!isThisReceiver) { this.receiver.generateCode(currentScope, codeStream, !isStatic); @@ -218,7 +218,7 @@ || (this.genericCast != null)) { this.receiver.generateCode(currentScope, codeStream, !isStatic); pc = codeStream.position; - if (this.codegenBinding.declaringClass == null) { // array length + if (codegenBinding.declaringClass == null) { // array length codeStream.arraylength(); if (valueRequired) { codeStream.generateImplicitConversion(this.implicitConversion); @@ -228,10 +228,11 @@ } } else { if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) { + TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis()); if (isStatic) { - codeStream.getstatic(this.codegenBinding); + codeStream.fieldAccess0(Opcodes.OPC_getstatic, codegenBinding, constantPoolDeclaringClass); } else { - codeStream.getfield(this.codegenBinding); + codeStream.fieldAccess0(Opcodes.OPC_getfield, codegenBinding, constantPoolDeclaringClass); } } else { codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[FieldReference.READ], null /* default declaringClass */); @@ -244,7 +245,7 @@ boolean isUnboxing = (this.implicitConversion & TypeIds.UNBOXING) != 0; // conversion only generated if unboxing if (isUnboxing) codeStream.generateImplicitConversion(this.implicitConversion); - switch (isUnboxing ? postConversionType(currentScope).id : this.codegenBinding.type.id) { + switch (isUnboxing ? postConversionType(currentScope).id : codegenBinding.type.id) { case T_long : case T_double : codeStream.pop2(); @@ -258,14 +259,15 @@ if (isThisReceiver) { if (isStatic){ // if no valueRequired, still need possible side-effects of invocation, if field belongs to different class - if (this.binding.original().declaringClass != this.receiverType.erasure()) { + if (this.binding.original().declaringClass != this.actualReceiverType.erasure()) { MethodBinding accessor = this.syntheticAccessors == null ? null : this.syntheticAccessors[FieldReference.READ]; if (accessor == null) { - codeStream.getstatic(this.codegenBinding); + TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis()); + codeStream.fieldAccess0(Opcodes.OPC_getstatic, codegenBinding, constantPoolDeclaringClass); } else { codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */); } - switch (this.codegenBinding.type.id) { + switch (codegenBinding.type.id) { case T_long : case T_double : codeStream.pop2(); @@ -288,20 +290,20 @@ public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) { boolean isStatic; - this.receiver.generateCode( - currentScope, - codeStream, - !(isStatic = this.codegenBinding.isStatic())); + FieldBinding codegenBinding = this.binding.original(); + this.receiver.generateCode(currentScope, codeStream, !(isStatic = codegenBinding.isStatic())); if (isStatic) { if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) { - codeStream.getstatic(this.codegenBinding); + TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis()); + codeStream.fieldAccess0(Opcodes.OPC_getstatic, codegenBinding, constantPoolDeclaringClass); } else { codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[FieldReference.READ], null /* default declaringClass */); } } else { codeStream.dup(); if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) { - codeStream.getfield(this.codegenBinding); + TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis()); + codeStream.fieldAccess0(Opcodes.OPC_getfield, codegenBinding, constantPoolDeclaringClass); } else { codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[FieldReference.READ], null /* default declaringClass */); } @@ -329,30 +331,26 @@ // cast the value back to the array reference type codeStream.generateImplicitConversion(assignmentImplicitConversion); } - fieldStore( - codeStream, - this.codegenBinding, - this.syntheticAccessors == null ? null : this.syntheticAccessors[FieldReference.WRITE], - valueRequired); + fieldStore(codeStream, codegenBinding, this.syntheticAccessors == null ? null : this.syntheticAccessors[FieldReference.WRITE], valueRequired); // no need for generic cast as value got dupped } public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) { boolean isStatic; - this.receiver.generateCode( - currentScope, - codeStream, - !(isStatic = this.codegenBinding.isStatic())); + FieldBinding codegenBinding = this.binding.original(); + this.receiver.generateCode(currentScope, codeStream, !(isStatic = codegenBinding.isStatic())); if (isStatic) { if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) { - codeStream.getstatic(this.codegenBinding); + TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis()); + codeStream.fieldAccess0(Opcodes.OPC_getstatic, codegenBinding, constantPoolDeclaringClass); } else { codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[FieldReference.READ], null /* default declaringClass */); } } else { codeStream.dup(); if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) { - codeStream.getfield(this.codegenBinding); + TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis()); + codeStream.fieldAccess0(Opcodes.OPC_getfield, codegenBinding, constantPoolDeclaringClass); } else { codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[FieldReference.READ], null /* default declaringClass */); } @@ -362,23 +360,29 @@ codeStream.checkcast(this.genericCast); operandType = this.genericCast; } else { - operandType = this.codegenBinding.type; + operandType = codegenBinding.type; } if (valueRequired) { if (isStatic) { - if ((operandType == TypeBinding.LONG) - || (operandType == TypeBinding.DOUBLE)) { - codeStream.dup2(); - } else { - codeStream.dup(); - } + switch (operandType.id) { + case TypeIds.T_long : + case TypeIds.T_double : + codeStream.dup2(); + break; + default : + codeStream.dup(); + break; + } } else { // Stack: [owner][old field value] ---> [old field value][owner][old field value] - if ((operandType == TypeBinding.LONG) - || (operandType == TypeBinding.DOUBLE)) { - codeStream.dup2_x1(); - } else { - codeStream.dup_x1(); - } + switch (operandType.id) { + case TypeIds.T_long : + case TypeIds.T_double : + codeStream.dup2_x1(); + break; + default : + codeStream.dup_x1(); + break; + } } } codeStream.generateImplicitConversion(this.implicitConversion); @@ -388,7 +392,7 @@ codeStream.sendOperator(postIncrement.operator, this.implicitConversion & TypeIds.COMPILE_TYPE_MASK); codeStream.generateImplicitConversion( postIncrement.preAssignImplicitConversion); - fieldStore(codeStream, this.codegenBinding, this.syntheticAccessors == null ? null : this.syntheticAccessors[FieldReference.WRITE], false); + fieldStore(codeStream, codegenBinding, this.syntheticAccessors == null ? null : this.syntheticAccessors[FieldReference.WRITE], false); } /** @@ -412,16 +416,16 @@ if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0) return; // if field from parameterized type got found, use the original field at codegen time - this.codegenBinding = this.binding.original(); + FieldBinding codegenBinding = this.binding.original(); if (this.binding.isPrivate()) { - if ((currentScope.enclosingSourceType() != this.codegenBinding.declaringClass) + if ((currentScope.enclosingSourceType() != codegenBinding.declaringClass) && this.binding.constant() == Constant.NotAConstant) { if (this.syntheticAccessors == null) this.syntheticAccessors = new MethodBinding[2]; this.syntheticAccessors[isReadAccess ? FieldReference.READ : FieldReference.WRITE] = - ((SourceTypeBinding) this.codegenBinding.declaringClass).addSyntheticMethod(this.codegenBinding, isReadAccess); - currentScope.problemReporter().needToEmulateFieldAccess(this.codegenBinding, this, isReadAccess); + ((SourceTypeBinding) codegenBinding.declaringClass).addSyntheticMethod(codegenBinding, isReadAccess); + currentScope.problemReporter().needToEmulateFieldAccess(codegenBinding, this, isReadAccess); return; } @@ -433,8 +437,8 @@ .currentCompatibleType); if (this.syntheticAccessors == null) this.syntheticAccessors = new MethodBinding[2]; - this.syntheticAccessors[isReadAccess ? FieldReference.READ : FieldReference.WRITE] = destinationType.addSyntheticMethod(this.codegenBinding, isReadAccess); - currentScope.problemReporter().needToEmulateFieldAccess(this.codegenBinding, this, isReadAccess); + this.syntheticAccessors[isReadAccess ? FieldReference.READ : FieldReference.WRITE] = destinationType.addSyntheticMethod(codegenBinding, isReadAccess); + currentScope.problemReporter().needToEmulateFieldAccess(codegenBinding, this, isReadAccess); return; } else if (this.binding.isProtected()) { @@ -449,31 +453,11 @@ (this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT); if (this.syntheticAccessors == null) this.syntheticAccessors = new MethodBinding[2]; - this.syntheticAccessors[isReadAccess ? FieldReference.READ : FieldReference.WRITE] = currentCompatibleType.addSyntheticMethod(this.codegenBinding, isReadAccess); - currentScope.problemReporter().needToEmulateFieldAccess(this.codegenBinding, this, isReadAccess); + this.syntheticAccessors[isReadAccess ? FieldReference.READ : FieldReference.WRITE] = currentCompatibleType.addSyntheticMethod(codegenBinding, isReadAccess); + currentScope.problemReporter().needToEmulateFieldAccess(codegenBinding, this, isReadAccess); return; } } - // if the binding declaring class is not visible, need special action - // for runtime compatibility on 1.2 VMs : change the declaring class of the binding - // NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type - // and not from Object or implicit static field access. - if (this.binding.declaringClass != this.receiverType - && !this.receiverType.isArrayType() - && this.binding.declaringClass != null // array.length - && this.binding.constant() == Constant.NotAConstant) { - CompilerOptions options = currentScope.compilerOptions(); - if ((options.targetJDK >= ClassFileConstants.JDK1_2 - && (options.complianceLevel >= ClassFileConstants.JDK1_4 || !(this.receiver.isImplicitThis() && this.codegenBinding.isStatic())) - && this.binding.declaringClass.id != TypeIds.T_JavaLangObject) // no change for Object fields - || !this.binding.declaringClass.canBeSeenBy(currentScope)) { - - this.codegenBinding = - currentScope.enclosingSourceType().getUpdatedFieldBinding( - this.codegenBinding, - (ReferenceBinding) this.receiverType.erasure()); - } - } } public int nullStatus(FlowInfo flowInfo) { @@ -546,35 +530,35 @@ this.receiver.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on receiverCast = true; } - this.receiverType = this.receiver.resolveType(scope); - if (this.receiverType == null) { + this.actualReceiverType = this.receiver.resolveType(scope); + if (this.actualReceiverType == null) { this.constant = Constant.NotAConstant; return null; } if (receiverCast) { // due to change of declaring class with receiver type, only identity cast should be notified - if (((CastExpression)this.receiver).expression.resolvedType == this.receiverType) { + if (((CastExpression)this.receiver).expression.resolvedType == this.actualReceiverType) { scope.problemReporter().unnecessaryCast((CastExpression)this.receiver); } } // the case receiverType.isArrayType and token = 'length' is handled by the scope API - FieldBinding fieldBinding = this.codegenBinding = this.binding = scope.getField(this.receiverType, this.token, this); + FieldBinding fieldBinding = this.binding = scope.getField(this.actualReceiverType, this.token, this); if (!fieldBinding.isValidBinding()) { this.constant = Constant.NotAConstant; if (this.receiver.resolvedType instanceof ProblemReferenceBinding) { // problem already got signaled on receiver, do not report secondary problem return null; } - scope.problemReporter().invalidField(this, this.receiverType); + scope.problemReporter().invalidField(this, this.actualReceiverType); return null; } - TypeBinding receiverErasure = this.receiverType.erasure(); + TypeBinding receiverErasure = this.actualReceiverType.erasure(); if (receiverErasure instanceof ReferenceBinding) { if (receiverErasure.findSuperTypeOriginatingFrom(fieldBinding.declaringClass) == null) { - this.receiverType = fieldBinding.declaringClass; // handle indirect inheritance thru variable secondary bound + this.actualReceiverType = fieldBinding.declaringClass; // handle indirect inheritance thru variable secondary bound } } - this.receiver.computeConversion(scope, this.receiverType, this.receiverType); + this.receiver.computeConversion(scope, this.actualReceiverType, this.actualReceiverType); if (isFieldUseDeprecated(fieldBinding, scope, (this.bits & ASTNode.IsStrictlyAssigned) !=0)) { scope.problemReporter().deprecatedField(fieldBinding, this); } @@ -589,7 +573,7 @@ } ReferenceBinding declaringClass = this.binding.declaringClass; if (!isImplicitThisRcv - && declaringClass != this.receiverType + && declaringClass != this.actualReceiverType && declaringClass.canBeSeenBy(scope)) { scope.problemReporter().indirectAccessToStaticField(this, fieldBinding); } @@ -620,7 +604,7 @@ } public void setActualReceiverType(ReferenceBinding receiverType) { - // ignored + this.actualReceiverType = receiverType; } public void setDepth(int depth) { Index: compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java,v retrieving revision 1.110 diff -u -r1.110 SingleNameReference.java --- compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java 17 Sep 2008 09:08:38 -0000 1.110 +++ compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java 24 Sep 2008 12:36:51 -0000 @@ -278,9 +278,9 @@ } switch (this.bits & ASTNode.RestrictiveFlagMASK) { case Binding.FIELD : // assigning to a field - FieldBinding fieldBinding; int pc = codeStream.position; - if (!(fieldBinding = (FieldBinding) this.codegenBinding).isStatic()) { // need a receiver? + FieldBinding codegenBinding = ((FieldBinding) this.binding).original(); + if (!codegenBinding.isStatic()) { // need a receiver? if ((this.bits & ASTNode.DepthMASK) != 0) { ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT); Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/); @@ -291,14 +291,14 @@ } codeStream.recordPositionsFrom(pc, this.sourceStart); assignment.expression.generateCode(currentScope, codeStream, true); - fieldStore(codeStream, fieldBinding, this.syntheticAccessors == null ? null : this.syntheticAccessors[SingleNameReference.WRITE], valueRequired); + fieldStore(codeStream, codegenBinding, this.syntheticAccessors == null ? null : this.syntheticAccessors[SingleNameReference.WRITE], valueRequired); if (valueRequired) { codeStream.generateImplicitConversion(assignment.implicitConversion); } // no need for generic cast as value got dupped return; case Binding.LOCAL : // assigning to a local variable - LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding; + LocalVariableBinding localBinding = (LocalVariableBinding) this.binding; if (localBinding.resolvedPosition != -1) { assignment.expression.generateCode(currentScope, codeStream, true); } else { @@ -354,8 +354,8 @@ } else { switch (this.bits & ASTNode.RestrictiveFlagMASK) { case Binding.FIELD : // reading a field - FieldBinding fieldBinding = (FieldBinding) this.codegenBinding; - Constant fieldConstant = fieldBinding.constant(); + FieldBinding codegenField = ((FieldBinding) this.binding).original(); + Constant fieldConstant = codegenField.constant(); if (fieldConstant != Constant.NotAConstant) { // directly use inlined value for constant fields if (valueRequired) { @@ -364,7 +364,7 @@ codeStream.recordPositionsFrom(pc, this.sourceStart); return; } - if (fieldBinding.isStatic()) { + if (codegenField.isStatic()) { if (!valueRequired // if no valueRequired, still need possible side-effects of invocation, if field belongs to different class && ((FieldBinding)this.binding).original().declaringClass == this.actualReceiverType.erasure() @@ -376,7 +376,8 @@ } // managing private access if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) { - codeStream.getstatic(fieldBinding); + TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, this.actualReceiverType, true /* implicit this */); + codeStream.fieldAccess0(Opcodes.OPC_getstatic, codegenField, constantPoolDeclaringClass); } else { codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */); } @@ -398,14 +399,15 @@ } // managing private access if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) { - codeStream.getfield(fieldBinding); + TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, this.actualReceiverType, true /* implicit this */); + codeStream.fieldAccess0(Opcodes.OPC_getfield, codegenField, constantPoolDeclaringClass); } else { codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */); } } break; case Binding.LOCAL : // reading a local - LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding; + LocalVariableBinding localBinding = (LocalVariableBinding) this.binding; if (!valueRequired && (this.implicitConversion & TypeIds.UNBOXING) == 0) { // if no valueRequired, optimize out entire gen codeStream.recordPositionsFrom(pc, this.sourceStart); @@ -470,10 +472,11 @@ public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, MethodBinding writeAccessor, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) { switch (this.bits & ASTNode.RestrictiveFlagMASK) { case Binding.FIELD : // assigning to a field - FieldBinding fieldBinding; - if ((fieldBinding = (FieldBinding) this.codegenBinding).isStatic()) { + FieldBinding codegenField = ((FieldBinding) this.binding).original(); + if (codegenField.isStatic()) { if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) { - codeStream.getstatic(fieldBinding); + TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, this.actualReceiverType, true /* implicit this */); + codeStream.fieldAccess0(Opcodes.OPC_getstatic, codegenField, constantPoolDeclaringClass); } else { codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */); } @@ -487,14 +490,15 @@ } codeStream.dup(); if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) { - codeStream.getfield(fieldBinding); + TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, this.actualReceiverType, true /* implicit this */); + codeStream.fieldAccess0(Opcodes.OPC_getfield, codegenField, constantPoolDeclaringClass); } else { codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */); } } break; case Binding.LOCAL : // assigning to a local variable (cannot assign to outer local) - LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding; + LocalVariableBinding localBinding = (LocalVariableBinding) this.binding; // using incr bytecode if possible switch (localBinding.type.id) { case T_JavaLangString : @@ -564,16 +568,21 @@ // store the result back into the variable switch (this.bits & ASTNode.RestrictiveFlagMASK) { case Binding.FIELD : // assigning to a field - fieldStore(codeStream, (FieldBinding) this.codegenBinding, writeAccessor, valueRequired); + FieldBinding codegenField = ((FieldBinding) this.binding).original(); + fieldStore(codeStream, codegenField, writeAccessor, valueRequired); // no need for generic cast as value got dupped return; case Binding.LOCAL : // assigning to a local variable - LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding; + LocalVariableBinding localBinding = (LocalVariableBinding) this.binding; if (valueRequired) { - if ((localBinding.type == TypeBinding.LONG) || (localBinding.type == TypeBinding.DOUBLE)) { - codeStream.dup2(); - } else { - codeStream.dup(); + switch (localBinding.type.id) { + case TypeIds.T_long : + case TypeIds.T_double : + codeStream.dup2(); + break; + default: + codeStream.dup(); + break; } } codeStream.store(localBinding, false); @@ -583,10 +592,11 @@ public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) { switch (this.bits & ASTNode.RestrictiveFlagMASK) { case Binding.FIELD : // assigning to a field - FieldBinding fieldBinding; - if ((fieldBinding = (FieldBinding) this.codegenBinding).isStatic()) { + FieldBinding codegenField = (((FieldBinding)this.binding).original()); + if (codegenField.isStatic()) { if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) { - codeStream.getstatic(fieldBinding); + TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, this.actualReceiverType, true /* implicit this */); + codeStream.fieldAccess0(Opcodes.OPC_getstatic, codegenField, constantPoolDeclaringClass); } else { codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */); } @@ -600,7 +610,8 @@ } codeStream.dup(); if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) { - codeStream.getfield(fieldBinding); + TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, this.actualReceiverType, true /* implicit this */); + codeStream.fieldAccess0(Opcodes.OPC_getfield, codegenField, constantPoolDeclaringClass); } else { codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */); } @@ -610,20 +621,28 @@ codeStream.checkcast(this.genericCast); operandType = this.genericCast; } else { - operandType = fieldBinding.type; + operandType = codegenField.type; } if (valueRequired) { - if (fieldBinding.isStatic()) { - if ((operandType == TypeBinding.LONG) || (operandType == TypeBinding.DOUBLE)) { - codeStream.dup2(); - } else { - codeStream.dup(); - } + if (codegenField.isStatic()) { + switch (operandType.id) { + case TypeIds.T_long : + case TypeIds.T_double : + codeStream.dup2(); + break; + default: + codeStream.dup(); + break; + } } else { // Stack: [owner][old field value] ---> [old field value][owner][old field value] - if ((operandType == TypeBinding.LONG) || (operandType == TypeBinding.DOUBLE)) { - codeStream.dup2_x1(); - } else { - codeStream.dup_x1(); + switch (operandType.id) { + case TypeIds.T_long : + case TypeIds.T_double : + codeStream.dup2_x1(); + break; + default: + codeStream.dup_x1(); + break; } } } @@ -631,11 +650,11 @@ codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion); codeStream.sendOperator(postIncrement.operator, this.implicitConversion & TypeIds.COMPILE_TYPE_MASK); codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion); - fieldStore(codeStream, fieldBinding, this.syntheticAccessors == null ? null : this.syntheticAccessors[SingleNameReference.WRITE], false); + fieldStore(codeStream, codegenField, this.syntheticAccessors == null ? null : this.syntheticAccessors[SingleNameReference.WRITE], false); // no need for generic cast return; case Binding.LOCAL : // assigning to a local variable - LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding; + LocalVariableBinding localBinding = (LocalVariableBinding) this.binding; // using incr bytecode if possible if (localBinding.type == TypeBinding.INT) { if (valueRequired) { @@ -649,11 +668,15 @@ } else { codeStream.load(localBinding); if (valueRequired){ - if ((localBinding.type == TypeBinding.LONG) || (localBinding.type == TypeBinding.DOUBLE)) { - codeStream.dup2(); - } else { - codeStream.dup(); - } + switch (localBinding.type.id) { + case TypeIds.T_long : + case TypeIds.T_double : + codeStream.dup2(); + break; + default: + codeStream.dup(); + break; + } } codeStream.generateImplicitConversion(this.implicitConversion); codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion); @@ -710,7 +733,6 @@ if ((this.bits & Binding.FIELD) != 0) { FieldBinding fieldBinding = (FieldBinding) this.binding; FieldBinding codegenField = fieldBinding.original(); - this.codegenBinding = codegenField; if (((this.bits & ASTNode.DepthMASK) != 0) && (codegenField.isPrivate() // private access || (codegenField.isProtected() // implicit protected access @@ -723,26 +745,6 @@ currentScope.problemReporter().needToEmulateFieldAccess(codegenField, this, isReadAccess); return; } - // if the binding declaring class is not visible, need special action - // for runtime compatibility on 1.2 VMs : change the declaring class of the binding - // NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type - // and not from Object or implicit static field access. - if (fieldBinding.declaringClass != this.actualReceiverType - && !this.actualReceiverType.isArrayType() - && fieldBinding.declaringClass != null // array.length - && fieldBinding.constant() == Constant.NotAConstant) { - CompilerOptions options = currentScope.compilerOptions(); - if ((options.targetJDK >= ClassFileConstants.JDK1_2 - && (options.complianceLevel >= ClassFileConstants.JDK1_4 || !fieldBinding.isStatic()) - && fieldBinding.declaringClass.id != TypeIds.T_JavaLangObject) // no change for Object fields - || !fieldBinding.declaringClass.canBeSeenBy(currentScope)) { - - this.codegenBinding = - currentScope.enclosingSourceType().getUpdatedFieldBinding( - codegenField, - (ReferenceBinding)this.actualReceiverType.erasure()); - } - } } } @@ -832,7 +834,6 @@ this.actualReceiverType = scope.enclosingSourceType(); this.binding = scope.getBinding(this.token, this.bits & ASTNode.RestrictiveFlagMASK, this, true /*resolve*/); } - this.codegenBinding = this.binding; if (this.binding.isValidBinding()) { switch (this.bits & ASTNode.RestrictiveFlagMASK) { case Binding.VARIABLE : // =========only variable============ Index: compiler/org/eclipse/jdt/internal/compiler/ast/Reference.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Reference.java,v retrieving revision 1.29 diff -u -r1.29 Reference.java --- compiler/org/eclipse/jdt/internal/compiler/ast/Reference.java 17 Sep 2008 09:08:38 -0000 1.29 +++ compiler/org/eclipse/jdt/internal/compiler/ast/Reference.java 24 Sep 2008 12:36:51 -0000 @@ -10,9 +10,14 @@ *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; -import org.eclipse.jdt.internal.compiler.codegen.*; -import org.eclipse.jdt.internal.compiler.flow.*; -import org.eclipse.jdt.internal.compiler.lookup.*; +import org.eclipse.jdt.internal.compiler.codegen.CodeStream; +import org.eclipse.jdt.internal.compiler.codegen.Opcodes; +import org.eclipse.jdt.internal.compiler.flow.FlowContext; +import org.eclipse.jdt.internal.compiler.flow.FlowInfo; +import org.eclipse.jdt.internal.compiler.lookup.BlockScope; +import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; +import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; +import org.eclipse.jdt.internal.compiler.lookup.TypeIds; public abstract class Reference extends Expression { /** @@ -26,42 +31,53 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { return flowInfo; } + public FieldBinding fieldBinding() { //this method should be sent one FIELD-tagged references // (ref.bits & BindingIds.FIELD != 0)() return null ; } + public void fieldStore(CodeStream codeStream, FieldBinding fieldBinding, MethodBinding syntheticWriteAccessor, boolean valueRequired) { int pc = codeStream.position; if (fieldBinding.isStatic()) { if (valueRequired) { - if ((fieldBinding.type == TypeBinding.LONG) || (fieldBinding.type == TypeBinding.DOUBLE)) { - codeStream.dup2(); - } else { - codeStream.dup(); + switch (fieldBinding.type.id) { + case TypeIds.T_long : + case TypeIds.T_double : + codeStream.dup2(); + break; + default : + codeStream.dup(); + break; } } if (syntheticWriteAccessor == null) { - codeStream.putstatic(fieldBinding); + codeStream.fieldAccess0(Opcodes.OPC_putstatic, fieldBinding, null /* default declaringClass */); } else { codeStream.invoke(Opcodes.OPC_invokestatic, syntheticWriteAccessor, null /* default declaringClass */); } } else { // Stack: [owner][new field value] ---> [new field value][owner][new field value] if (valueRequired) { - if ((fieldBinding.type == TypeBinding.LONG) || (fieldBinding.type == TypeBinding.DOUBLE)) { - codeStream.dup2_x1(); - } else { - codeStream.dup_x1(); + switch (fieldBinding.type.id) { + case TypeIds.T_long : + case TypeIds.T_double : + codeStream.dup2_x1(); + break; + default : + codeStream.dup_x1(); + break; } } if (syntheticWriteAccessor == null) { - codeStream.putfield(fieldBinding); + codeStream.fieldAccess0(Opcodes.OPC_putfield, fieldBinding, null /* default declaringClass */); } else { codeStream.invoke(Opcodes.OPC_invokestatic, syntheticWriteAccessor, null /* default declaringClass */); } } codeStream.recordPositionsFrom(pc, this.sourceStart); } + public abstract void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired); public abstract void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired); Index: compiler/org/eclipse/jdt/internal/compiler/ast/Javadoc.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Javadoc.java,v retrieving revision 1.60 diff -u -r1.60 Javadoc.java --- compiler/org/eclipse/jdt/internal/compiler/ast/Javadoc.java 27 Jun 2008 16:03:55 -0000 1.60 +++ compiler/org/eclipse/jdt/internal/compiler/ast/Javadoc.java 24 Sep 2008 12:36:50 -0000 @@ -373,11 +373,11 @@ if (scopeModifiers == -1) scopeModifiers = scope.getDeclarationModifiers(); scope.problemReporter().javadocInvalidValueReference(fieldRef.sourceStart, fieldRef.sourceEnd, scopeModifiers); } - else if (fieldRef.receiverType != null) { - if (scope.enclosingSourceType().isCompatibleWith(fieldRef.receiverType)) { + else if (fieldRef.actualReceiverType != null) { + if (scope.enclosingSourceType().isCompatibleWith(fieldRef.actualReceiverType)) { fieldRef.bits |= ASTNode.SuperAccess; } - fieldRef.methodBinding = scope.findMethod((ReferenceBinding)fieldRef.receiverType, fieldRef.token, new TypeBinding[0], fieldRef); + fieldRef.methodBinding = scope.findMethod((ReferenceBinding)fieldRef.actualReceiverType, fieldRef.token, new TypeBinding[0], fieldRef); } } @@ -390,8 +390,8 @@ } // Verify type references - if (!hasProblems && fieldRef.binding != null && fieldRef.binding.isValidBinding() && fieldRef.receiverType instanceof ReferenceBinding) { - ReferenceBinding resolvedType = (ReferenceBinding) fieldRef.receiverType; + if (!hasProblems && fieldRef.binding != null && fieldRef.binding.isValidBinding() && fieldRef.actualReceiverType instanceof ReferenceBinding) { + ReferenceBinding resolvedType = (ReferenceBinding) fieldRef.actualReceiverType; verifyTypeReference(fieldRef, fieldRef.receiver, scope, source15, resolvedType, fieldRef.binding.modifiers); } Index: compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java,v retrieving revision 1.134 diff -u -r1.134 MessageSend.java --- compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java 17 Sep 2008 11:11:09 -0000 1.134 +++ compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java 24 Sep 2008 12:36:50 -0000 @@ -149,7 +149,7 @@ // actual message invocation if (this.syntheticAccessor == null){ - TypeBinding constantPoolDeclaringClass = getConstantPoolDeclaringClass(currentScope); + TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis(), this.receiverGenericCast != null); if (isStatic){ codeStream.invoke(Opcodes.OPC_invokestatic, codegenBinding, constantPoolDeclaringClass); } else if( (this.receiver.isSuper()) || codegenBinding.isPrivate()){ @@ -193,35 +193,6 @@ return this.genericTypeArguments; } -protected TypeBinding getConstantPoolDeclaringClass(BlockScope currentScope) { - // constantpool declaringClass - MethodBinding codegenBinding = this.binding.original(); - TypeBinding constantPoolDeclaringClass = codegenBinding.declaringClass; - // Post 1.4.0 target, array clone() invocations are qualified with array type - // This is handled in array type #clone method binding resolution (see Scope and UpdatedMethodBinding) - if (codegenBinding == currentScope.environment().arrayClone) { - CompilerOptions options = currentScope.compilerOptions(); - if (options.sourceLevel > ClassFileConstants.JDK1_4 ) { - constantPoolDeclaringClass = this.actualReceiverType.erasure(); - } - } else { - // if the binding declaring class is not visible, need special action - // for runtime compatibility on 1.2 VMs : change the declaring class of the binding - // NOTE: from target 1.2 on, method's declaring class is touched if any different from receiver type - // and not from Object or implicit static method call. - if (constantPoolDeclaringClass != this.actualReceiverType && this.receiverGenericCast == null && !this.actualReceiverType.isArrayType()) { - CompilerOptions options = currentScope.compilerOptions(); - if ((options.targetJDK >= ClassFileConstants.JDK1_2 - && (options.complianceLevel >= ClassFileConstants.JDK1_4 || !(this.receiver.isImplicitThis() && codegenBinding.isStatic())) - && this.binding.declaringClass.id != TypeIds.T_JavaLangObject) // no change for Object methods - || !this.binding.declaringClass.canBeSeenBy(currentScope)) { - constantPoolDeclaringClass = this.actualReceiverType.erasure(); - } - } - } - return constantPoolDeclaringClass; -} - public boolean isSuperAccess() { return this.receiver.isSuper(); } Index: compiler/org/eclipse/jdt/internal/compiler/ast/JavadocFieldReference.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocFieldReference.java,v retrieving revision 1.29 diff -u -r1.29 JavadocFieldReference.java --- compiler/org/eclipse/jdt/internal/compiler/ast/JavadocFieldReference.java 27 Jun 2008 16:03:56 -0000 1.29 +++ compiler/org/eclipse/jdt/internal/compiler/ast/JavadocFieldReference.java 24 Sep 2008 12:36:50 -0000 @@ -41,19 +41,19 @@ this.constant = Constant.NotAConstant; if (this.receiver == null) { - this.receiverType = scope.enclosingReceiverType(); + this.actualReceiverType = scope.enclosingReceiverType(); } else if (scope.kind == Scope.CLASS_SCOPE) { - this.receiverType = this.receiver.resolveType((ClassScope) scope); + this.actualReceiverType = this.receiver.resolveType((ClassScope) scope); } else { - this.receiverType = this.receiver.resolveType((BlockScope)scope); + this.actualReceiverType = this.receiver.resolveType((BlockScope)scope); } - if (this.receiverType == null) { + if (this.actualReceiverType == null) { return null; } Binding fieldBinding = (this.receiver != null && this.receiver.isThis()) ? scope.classScope().getBinding(this.token, this.bits & RestrictiveFlagMASK, this, true /*resolve*/) - : scope.getField(this.receiverType, this.token, this); + : scope.getField(this.actualReceiverType, this.token, this); if (!fieldBinding.isValidBinding()) { // implicit lookup may discover issues due to static/constructor contexts. javadoc must be resilient switch (fieldBinding.problemId()) { @@ -72,8 +72,8 @@ // problem already got signaled on receiver, do not report secondary problem return null; } - if (this.receiverType instanceof ReferenceBinding) { - ReferenceBinding refBinding = (ReferenceBinding) this.receiverType; + if (this.actualReceiverType instanceof ReferenceBinding) { + ReferenceBinding refBinding = (ReferenceBinding) this.actualReceiverType; MethodBinding possibleMethod = this.receiver.isThis() ? scope.getImplicitMethod(this.token, Binding.NO_TYPES, this) : scope.getMethod(refBinding, this.token, Binding.NO_TYPES, this); @@ -82,7 +82,7 @@ } else { ProblemMethodBinding problemMethodBinding = (ProblemMethodBinding) possibleMethod; if (problemMethodBinding.closestMatch == null) { - scope.problemReporter().javadocInvalidField(this, fieldBinding, this.receiverType, scope.getDeclarationModifiers()); + scope.problemReporter().javadocInvalidField(this, fieldBinding, this.actualReceiverType, scope.getDeclarationModifiers()); } else { this.methodBinding = problemMethodBinding.closestMatch; } Index: compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java,v retrieving revision 1.131 diff -u -r1.131 QualifiedNameReference.java --- compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java 17 Sep 2008 09:08:38 -0000 1.131 +++ compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java 24 Sep 2008 12:36:51 -0000 @@ -44,7 +44,7 @@ public char[][] tokens; public long[] sourcePositions; - public FieldBinding[] otherBindings, otherCodegenBindings; + public FieldBinding[] otherBindings; int[] otherDepths; public int indexOfFirstFieldBinding;//points (into tokens) for the first token that corresponds to first FieldBinding public SyntheticMethodBinding syntheticWriteAccessor; @@ -69,7 +69,7 @@ case Binding.FIELD : // reading a field lastFieldBinding = (FieldBinding) this.binding; if (needValue || complyTo14) { - manageSyntheticAccessIfNecessary(currentScope, lastFieldBinding, this.actualReceiverType, 0, flowInfo); + manageSyntheticAccessIfNecessary(currentScope, lastFieldBinding, 0, flowInfo); } // check if final blank field if (lastFieldBinding.isBlankFinal() @@ -107,14 +107,7 @@ lastFieldBinding = this.otherBindings[i]; needValue = !this.otherBindings[i+1].isStatic(); if (needValue || complyTo14) { - manageSyntheticAccessIfNecessary( - currentScope, - lastFieldBinding, - i == 0 - ? ((VariableBinding)this.binding).type - : this.otherBindings[i-1].type, - i + 1, - flowInfo); + manageSyntheticAccessIfNecessary(currentScope, lastFieldBinding, i + 1, flowInfo); } } lastFieldBinding = this.otherBindings[otherBindingsCount-1]; @@ -127,24 +120,7 @@ && (!flowInfo.isDefinitelyAssigned(lastFieldBinding))) { currentScope.problemReporter().uninitializedBlankFinalField(lastFieldBinding, this); } - TypeBinding lastReceiverType; - switch (otherBindingsCount) { - case 0 : - lastReceiverType = this.actualReceiverType; - break; - case 1 : - lastReceiverType = ((VariableBinding)this.binding).type; - break; - default: - lastReceiverType = this.otherBindings[otherBindingsCount-2].type; - break; - } - manageSyntheticAccessIfNecessary( - currentScope, - lastFieldBinding, - lastReceiverType, - otherBindingsCount, - flowInfo); + manageSyntheticAccessIfNecessary(currentScope, lastFieldBinding, otherBindingsCount, flowInfo); } if (assignment.expression != null) { @@ -176,20 +152,7 @@ } } } - // equivalent to valuesRequired[maxOtherBindings] - TypeBinding lastReceiverType; - switch (otherBindingsCount) { - case 0 : - lastReceiverType = this.actualReceiverType; - break; - case 1 : - lastReceiverType = ((VariableBinding)this.binding).type; - break; - default : - lastReceiverType = this.otherBindings[otherBindingsCount-2].type; - break; - } - manageSyntheticAccessIfNecessary(currentScope, lastFieldBinding, lastReceiverType, -1 /*write-access*/, flowInfo); + manageSyntheticAccessIfNecessary(currentScope, lastFieldBinding, -1 /*write-access*/, flowInfo); return flowInfo; } @@ -207,7 +170,7 @@ switch (this.bits & ASTNode.RestrictiveFlagMASK) { case Binding.FIELD : // reading a field if (needValue || complyTo14) { - manageSyntheticAccessIfNecessary(currentScope, (FieldBinding) this.binding, this.actualReceiverType, 0, flowInfo); + manageSyntheticAccessIfNecessary(currentScope, (FieldBinding) this.binding, 0, flowInfo); } if (this.indexOfFirstFieldBinding == 1) { // was an implicit reference to the first field binding FieldBinding fieldBinding = (FieldBinding) this.binding; @@ -221,8 +184,7 @@ break; case Binding.LOCAL : // reading a local variable LocalVariableBinding localBinding; - if (!flowInfo - .isDefinitelyAssigned(localBinding = (LocalVariableBinding) this.binding)) { + if (!flowInfo.isDefinitelyAssigned(localBinding = (LocalVariableBinding) this.binding)) { currentScope.problemReporter().uninitializedLocalVariable(localBinding, this); } if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) { @@ -240,20 +202,7 @@ for (int i = 0; i < otherBindingsCount; i++) { needValue = i < otherBindingsCount-1 ? !this.otherBindings[i+1].isStatic() : valueRequired; if (needValue || complyTo14) { - TypeBinding lastReceiverType = getGenericCast(i); - if (lastReceiverType == null) { - if (i == 0) { - lastReceiverType = ((VariableBinding)this.binding).type; - } else { - lastReceiverType = this.otherBindings[i-1].type; - } - } - manageSyntheticAccessIfNecessary( - currentScope, - this.otherBindings[i], - lastReceiverType, - i + 1, - flowInfo); + manageSyntheticAccessIfNecessary(currentScope, this.otherBindings[i], i + 1, flowInfo); } } } @@ -376,7 +325,7 @@ boolean isFirst = lastFieldBinding == this.binding && (this.indexOfFirstFieldBinding == 1 || lastFieldBinding.declaringClass == currentScope.enclosingReceiverType()) && this.otherBindings == null; // could be dup: next.next.next - TypeBinding requiredGenericCast = getGenericCast(this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length); + TypeBinding requiredGenericCast = getGenericCast(this.otherBindings == null ? 0 : this.otherBindings.length); if (valueRequired || (!isFirst && currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) || ((this.implicitConversion & TypeIds.UNBOXING) != 0) @@ -391,15 +340,13 @@ codeStream.pop(); } } else { - SyntheticMethodBinding accessor = - this.syntheticReadAccessors == null - ? null - : this.syntheticReadAccessors[this.syntheticReadAccessors.length - 1]; + SyntheticMethodBinding accessor = this.syntheticReadAccessors == null ? null : this.syntheticReadAccessors[this.syntheticReadAccessors.length - 1]; if (accessor == null) { + TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, lastFieldBinding, getFinalReceiverType(), isFirst); if (isStatic) { - codeStream.getstatic(lastFieldBinding); + codeStream.fieldAccess0(Opcodes.OPC_getstatic, lastFieldBinding, constantPoolDeclaringClass); } else { - codeStream.getfield(lastFieldBinding); + codeStream.fieldAccess0(Opcodes.OPC_getfield, lastFieldBinding, constantPoolDeclaringClass); } } else { codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */); @@ -436,29 +383,23 @@ codeStream.recordPositionsFrom(pc, this.sourceStart); } -public void generateCompoundAssignment( - BlockScope currentScope, - CodeStream codeStream, - Expression expression, - int operator, - int assignmentImplicitConversion, - boolean valueRequired) { - +public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) { FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream); - SyntheticMethodBinding accessor = - this.syntheticReadAccessors == null - ? null - : this.syntheticReadAccessors[this.syntheticReadAccessors.length - 1]; + boolean isFirst = lastFieldBinding == this.binding + && (this.indexOfFirstFieldBinding == 1 || lastFieldBinding.declaringClass == currentScope.enclosingReceiverType()) + && this.otherBindings == null; // could be dup: next.next.next + TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, lastFieldBinding, getFinalReceiverType(), isFirst); + SyntheticMethodBinding accessor = this.syntheticReadAccessors == null ? null : this.syntheticReadAccessors[this.syntheticReadAccessors.length - 1]; if (lastFieldBinding.isStatic()) { if (accessor == null) { - codeStream.getstatic(lastFieldBinding); + codeStream.fieldAccess0(Opcodes.OPC_getstatic, lastFieldBinding, constantPoolDeclaringClass); } else { codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */); } } else { codeStream.dup(); if (accessor == null) { - codeStream.getfield(lastFieldBinding); + codeStream.fieldAccess0(Opcodes.OPC_getfield, lastFieldBinding, constantPoolDeclaringClass); } else { codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */); } @@ -473,7 +414,7 @@ codeStream.generateStringConcatenationAppend(currentScope, null, expression); break; default : - TypeBinding requiredGenericCast = getGenericCast(this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length); + TypeBinding requiredGenericCast = getGenericCast(this.otherBindings == null ? 0 : this.otherBindings.length); if (requiredGenericCast != null) codeStream.checkcast(requiredGenericCast); // promote the array reference to the suitable operation type codeStream.generateImplicitConversion(this.implicitConversion); @@ -495,24 +436,28 @@ public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) { FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream); + boolean isFirst = lastFieldBinding == this.binding + && (this.indexOfFirstFieldBinding == 1 || lastFieldBinding.declaringClass == currentScope.enclosingReceiverType()) + && this.otherBindings == null; // could be dup: next.next.next + TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, lastFieldBinding, getFinalReceiverType(), isFirst); SyntheticMethodBinding accessor = this.syntheticReadAccessors == null ? null : this.syntheticReadAccessors[this.syntheticReadAccessors.length - 1]; if (lastFieldBinding.isStatic()) { if (accessor == null) { - codeStream.getstatic(lastFieldBinding); + codeStream.fieldAccess0(Opcodes.OPC_getstatic, lastFieldBinding, constantPoolDeclaringClass); } else { - codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */); + codeStream.invoke(Opcodes.OPC_invokestatic, accessor, constantPoolDeclaringClass); } } else { codeStream.dup(); if (accessor == null) { - codeStream.getfield(lastFieldBinding); + codeStream.fieldAccess0(Opcodes.OPC_getfield, lastFieldBinding, null /* default declaringClass */); } else { codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */); } } - TypeBinding requiredGenericCast = getGenericCast(this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length); + TypeBinding requiredGenericCast = getGenericCast(this.otherBindings == null ? 0 : this.otherBindings.length); TypeBinding operandType; if (requiredGenericCast != null) { codeStream.checkcast(requiredGenericCast); @@ -523,19 +468,25 @@ // duplicate the old field value if (valueRequired) { if (lastFieldBinding.isStatic()) { - if ((operandType == TypeBinding.LONG) - || (operandType == TypeBinding.DOUBLE)) { - codeStream.dup2(); - } else { - codeStream.dup(); - } + switch (operandType.id) { + case TypeIds.T_long : + case TypeIds.T_double : + codeStream.dup2(); + break; + default: + codeStream.dup(); + break; + } } else { // Stack: [owner][old field value] ---> [old field value][owner][old field value] - if ((operandType == TypeBinding.LONG) - || (operandType == TypeBinding.DOUBLE)) { - codeStream.dup2_x1(); - } else { - codeStream.dup_x1(); - } + switch (operandType.id) { + case TypeIds.T_long : + case TypeIds.T_double : + codeStream.dup2_x1(); + break; + default: + codeStream.dup_x1(); + break; + } } } codeStream.generateImplicitConversion(this.implicitConversion); @@ -554,16 +505,18 @@ */ public FieldBinding generateReadSequence(BlockScope currentScope, CodeStream codeStream) { // determine the rank until which we now we do not need any actual value for the field access - int otherBindingsCount = this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length; + int otherBindingsCount = this.otherBindings == null ? 0 : this.otherBindings.length; boolean needValue = otherBindingsCount == 0 || !this.otherBindings[0].isStatic(); - FieldBinding lastFieldBinding = null; - TypeBinding lastGenericCast = null; + FieldBinding lastFieldBinding; + TypeBinding lastGenericCast; + TypeBinding lastReceiverType; boolean complyTo14 = currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4; switch (this.bits & ASTNode.RestrictiveFlagMASK) { case Binding.FIELD : - lastFieldBinding = (FieldBinding) this.codegenBinding; + lastFieldBinding = ((FieldBinding) this.binding).original(); lastGenericCast = this.genericCast; + lastReceiverType = this.actualReceiverType; // if first field is actually constant, we can inline it if (lastFieldBinding.constant() != Constant.NotAConstant) { break; @@ -581,8 +534,11 @@ } break; case Binding.LOCAL : // reading the first local variable + lastFieldBinding = null; + lastGenericCast = null; + lastReceiverType = null; if (!needValue) break; // no value needed - LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding; + LocalVariableBinding localBinding = (LocalVariableBinding) this.binding; // regular local variable read Constant localConstant = localBinding.constant(); if (localConstant != Constant.NotAConstant) { @@ -598,15 +554,19 @@ codeStream.load(localBinding); } } + break; + default : // should not occur + return null; } // all intermediate field accesses are read accesses // only the last field binding is a write access int positionsLength = this.sourcePositions.length; - if (this.otherCodegenBindings != null) { + FieldBinding initialFieldBinding = lastFieldBinding; // can be null if initial was a local binding + if (this.otherBindings != null) { for (int i = 0; i < otherBindingsCount; i++) { int pc = codeStream.position; - FieldBinding nextField = this.otherCodegenBindings[i]; + FieldBinding nextField = this.otherBindings[i].original(); TypeBinding nextGenericCast = this.otherGenericCasts == null ? null : this.otherGenericCasts[i]; if (lastFieldBinding != null) { needValue = !nextField.isStatic(); @@ -623,10 +583,11 @@ if (needValue || (i > 0 && complyTo14) || lastGenericCast != null) { MethodBinding accessor = this.syntheticReadAccessors == null ? null : this.syntheticReadAccessors[i]; if (accessor == null) { + TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, lastFieldBinding, lastReceiverType, i == 0 && this.indexOfFirstFieldBinding == 1); if (lastFieldBinding.isStatic()) { - codeStream.getstatic(lastFieldBinding); + codeStream.fieldAccess0(Opcodes.OPC_getstatic, lastFieldBinding, constantPoolDeclaringClass); } else { - codeStream.getfield(lastFieldBinding); + codeStream.fieldAccess0(Opcodes.OPC_getfield, lastFieldBinding, constantPoolDeclaringClass); } } else { codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */); @@ -634,13 +595,14 @@ if (lastGenericCast != null) codeStream.checkcast(lastGenericCast); if (!needValue) codeStream.pop(); } else { - if (this.codegenBinding == lastFieldBinding) { + if (lastFieldBinding == initialFieldBinding) { if (lastFieldBinding.isStatic()){ // if no valueRequired, still need possible side-effects of invocation, if field belongs to different class - if (((FieldBinding)this.binding).original().declaringClass != this.actualReceiverType.erasure()) { + if (initialFieldBinding.declaringClass != this.actualReceiverType.erasure()) { MethodBinding accessor = this.syntheticReadAccessors == null ? null : this.syntheticReadAccessors[i]; if (accessor == null) { - codeStream.getstatic(lastFieldBinding); + TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, lastFieldBinding, lastReceiverType, i == 0 && this.indexOfFirstFieldBinding == 1); + codeStream.fieldAccess0(Opcodes.OPC_getstatic, lastFieldBinding, constantPoolDeclaringClass); } else { codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */); } @@ -658,6 +620,7 @@ } } } + lastReceiverType = lastFieldBinding.type; lastFieldBinding = nextField; lastGenericCast = nextGenericCast; } @@ -676,15 +639,30 @@ return null; } -// get the matching codegenBinding protected FieldBinding getCodegenBinding(int index) { if (index == 0){ - return (FieldBinding)this.codegenBinding; + return ((FieldBinding)this.binding).original(); } else { - return this.otherCodegenBindings[index-1]; + return this.otherBindings[index-1].original(); } } +/** + * Returns the receiver type for the final field in sequence (i.e. the return type of the previous binding) + * @return receiver type for the final field in sequence + */ +protected TypeBinding getFinalReceiverType() { + int otherBindingsCount = this.otherBindings == null ? 0 : this.otherBindings.length; + switch (otherBindingsCount) { + case 0 : + return this.actualReceiverType; + case 1 : + return ((VariableBinding)this.binding).type; + default: + return this.otherBindings[otherBindingsCount-2].type; + } +} + // get the matching generic cast protected TypeBinding getGenericCast(int index) { if (index == 0){ @@ -694,7 +672,6 @@ return this.otherGenericCasts[index-1]; } } - public TypeBinding getOtherFieldBindings(BlockScope scope) { // At this point restrictiveFlag may ONLY have two potential value : FIELD LOCAL (i.e cast <<(VariableBinding) binding>> is valid) int length = this.tokens.length; @@ -730,7 +707,6 @@ } // allocation of the fieldBindings array and its respective constants int otherBindingsLength = length - index; - this.otherCodegenBindings = this.otherBindings = new FieldBinding[otherBindingsLength]; this.otherDepths = new int[otherBindingsLength]; // fill the first constant (the one of the binding) @@ -825,18 +801,12 @@ /** * index is <0 to denote write access emulation */ -public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FieldBinding fieldBinding, TypeBinding lastReceiverType, int index, FlowInfo flowInfo) { +public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FieldBinding fieldBinding, int index, FlowInfo flowInfo) { if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0) return; // index == 0 denotes the first fieldBinding, index > 0 denotes one of the 'otherBindings', index < 0 denotes a write access (to last binding) if (fieldBinding.constant() != Constant.NotAConstant) return; - // if field from parameterized type got found, use the original field at codegen time - FieldBinding originalField = fieldBinding.original(); - if (originalField != fieldBinding) { - setCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index, originalField); - } - if (fieldBinding.isPrivate()) { // private access FieldBinding someCodegenBinding = getCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index); if (someCodegenBinding.declaringClass != currentScope.enclosingSourceType()) { @@ -852,34 +822,13 @@ // implicit protected access if (depth > 0 && (fieldBinding.declaringClass.getPackage() != currentScope.enclosingSourceType().getPackage())) { - FieldBinding someCodegenBinding = getCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index); + FieldBinding codegenField = getCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index); setSyntheticAccessor(fieldBinding, index, - ((SourceTypeBinding) currentScope.enclosingSourceType().enclosingTypeAt(depth)).addSyntheticMethod(someCodegenBinding, index >= 0 /*read-access?*/)); - currentScope.problemReporter().needToEmulateFieldAccess(someCodegenBinding, this, index >= 0 /*read-access?*/); + ((SourceTypeBinding) currentScope.enclosingSourceType().enclosingTypeAt(depth)).addSyntheticMethod(codegenField, index >= 0 /*read-access?*/)); + currentScope.problemReporter().needToEmulateFieldAccess(codegenField, this, index >= 0 /*read-access?*/); return; } } - // if the binding declaring class is not visible, need special action - // for runtime compatibility on 1.2 VMs : change the declaring class of the binding - // NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type - // and not from Object or implicit static field access. - if (fieldBinding.declaringClass != lastReceiverType - && !lastReceiverType.isArrayType() - && fieldBinding.declaringClass != null // array.length - && fieldBinding.constant() == Constant.NotAConstant) { - CompilerOptions options = currentScope.compilerOptions(); - if ((options.targetJDK >= ClassFileConstants.JDK1_2 - && (options.complianceLevel >= ClassFileConstants.JDK1_4 || !(index <= 1 && this.indexOfFirstFieldBinding == 1 && fieldBinding.isStatic())) - && fieldBinding.declaringClass.id != TypeIds.T_JavaLangObject) // no change for Object fields - || !fieldBinding.declaringClass.canBeSeenBy(currentScope)) { - - setCodegenBinding( - index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index, - currentScope.enclosingSourceType().getUpdatedFieldBinding( - getCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index), - (ReferenceBinding)lastReceiverType.erasure())); - } - } } public int nullStatus(FlowInfo flowInfo) { @@ -908,7 +857,7 @@ */ public TypeBinding postConversionType(Scope scope) { TypeBinding convertedType = this.resolvedType; - TypeBinding requiredGenericCast = getGenericCast(this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length); + TypeBinding requiredGenericCast = getGenericCast(this.otherBindings == null ? 0 : this.otherBindings.length); if (requiredGenericCast != null) convertedType = requiredGenericCast; int runtimeType = (this.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4; @@ -973,7 +922,7 @@ // the TC is Flag_Type Flag_LocalField and Flag_TypeLocalField this.actualReceiverType = scope.enclosingReceiverType(); this.constant = Constant.NotAConstant; - if ((this.codegenBinding = this.binding = scope.getBinding(this.tokens, this.bits & ASTNode.RestrictiveFlagMASK, this, true /*resolve*/)).isValidBinding()) { + if ((this.binding = scope.getBinding(this.tokens, this.bits & ASTNode.RestrictiveFlagMASK, this, true /*resolve*/)).isValidBinding()) { switch (this.bits & ASTNode.RestrictiveFlagMASK) { case Binding.VARIABLE : //============only variable=========== case Binding.TYPE | Binding.VARIABLE : @@ -1056,19 +1005,6 @@ return this.resolvedType = reportError(scope); } -// set the matching codegenBinding and generic cast -protected void setCodegenBinding(int index, FieldBinding someCodegenBinding) { - if (index == 0){ - this.codegenBinding = someCodegenBinding; - } else { - int length = this.otherBindings.length; - if (this.otherCodegenBindings == this.otherBindings){ - System.arraycopy(this.otherBindings, 0, this.otherCodegenBindings = new FieldBinding[length], 0, length); - } - this.otherCodegenBindings[index-1] = someCodegenBinding; - } -} - public void setFieldIndex(int index) { this.indexOfFirstFieldBinding = index; } Index: compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java,v retrieving revision 1.92 diff -u -r1.92 FieldDeclaration.java --- compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java 11 Sep 2008 10:04:25 -0000 1.92 +++ compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java 24 Sep 2008 12:36:50 -0000 @@ -104,9 +104,9 @@ this.initialization.generateCode(currentScope, codeStream, true); // store into field if (isStatic) { - codeStream.putstatic(this.binding); + codeStream.fieldAccess0(Opcodes.OPC_putstatic, this.binding, null /* default declaringClass */); } else { - codeStream.putfield(this.binding); + codeStream.fieldAccess0(Opcodes.OPC_putfield, this.binding, null /* default declaringClass */); } } codeStream.recordPositionsFrom(pc, this.sourceStart); Index: compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java,v retrieving revision 1.161 diff -u -r1.161 SourceTypeBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java 17 Sep 2008 09:33:00 -0000 1.161 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java 24 Sep 2008 12:36:52 -0000 @@ -1065,7 +1065,7 @@ public ReferenceBinding[] memberTypes() { return this.memberTypes; } -///** @deprecated */ +/** @deprecated */ public FieldBinding getUpdatedFieldBinding(FieldBinding targetField, ReferenceBinding newDeclaringClass) { if (this.synthetics == null) this.synthetics = new HashMap[MAX_SYNTHETICS]; Index: compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java,v retrieving revision 1.166 diff -u -r1.166 CodeStream.java --- compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java 17 Sep 2008 09:28:33 -0000 1.166 +++ compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java 24 Sep 2008 12:36:52 -0000 @@ -21,6 +21,7 @@ import org.eclipse.jdt.internal.compiler.ast.OperatorIds; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.flow.UnconditionalFlowInfo; +import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.*; import org.eclipse.jdt.internal.compiler.problem.AbortMethod; @@ -1214,6 +1215,65 @@ this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_fdiv; } +public void fieldAccess0(byte opcode, FieldBinding fieldBinding, TypeBinding declaringClass) { + if (declaringClass == null) declaringClass = fieldBinding.declaringClass; + if (declaringClass.leafComponentType().isNestedType()) { + this.classFile.recordInnerClasses(declaringClass); + } + TypeBinding returnType = fieldBinding.type; + int returnTypeSize; + switch (returnType.id) { + case TypeIds.T_long : + case TypeIds.T_double : + returnTypeSize = 2; + break; + default : + returnTypeSize = 1; + break; + } + this.fieldAccess(opcode, returnTypeSize, declaringClass.constantPoolName(), fieldBinding.name, returnType.signature()); +} + +private void fieldAccess(byte opcode, int returnTypeSize, char[] declaringClass, char[] fieldName, char[] signature) { + this.countLabels = 0; + switch(opcode) { + case Opcodes.OPC_getfield : + if (returnTypeSize == 2) { + this.stackDepth++; + } + break; + case Opcodes.OPC_getstatic : + if (returnTypeSize == 2) { + this.stackDepth += 2; + } else { + this.stackDepth++; + } + break; + case Opcodes.OPC_putfield : + if (returnTypeSize == 2) { + this.stackDepth -= 3; + } else { + this.stackDepth -= 2; + } + break; + case Opcodes.OPC_putstatic : + if (returnTypeSize == 2) { + this.stackDepth -= 2; + } else { + this.stackDepth--; + } + } + if (this.stackDepth > this.stackMax) { + this.stackMax = this.stackDepth; + } + if (this.classFileOffset + 2 >= this.bCodeStream.length) { + resizeByteArray(); + } + this.position++; + this.bCodeStream[this.classFileOffset++] = opcode; + writeUnsignedShort(this.constantPool.literalIndexForField(declaringClass, fieldName, signature)); +} + public void fload(int iArg) { this.countLabels = 0; this.stackDepth++; @@ -1641,7 +1701,7 @@ } else { BranchLabel endLabel = new BranchLabel(this); if (syntheticFieldBinding != null) { // non interface case - getstatic(syntheticFieldBinding); + fieldAccess0(Opcodes.OPC_getstatic, syntheticFieldBinding, null /* default declaringClass */); dup(); ifnonnull(endLabel); pop(); @@ -1684,7 +1744,7 @@ if (syntheticFieldBinding != null) { // non interface case dup(); - putstatic(syntheticFieldBinding); + fieldAccess0(Opcodes.OPC_putstatic, syntheticFieldBinding, null /* default declaringClass */); } goto_(endLabel); @@ -1877,57 +1937,6 @@ invokeAccessibleObjectSetAccessible(); } -private void generateFieldAccess(byte opcode, int returnTypeSize, char[] declaringClass, char[] name, char[] signature) { - this.countLabels = 0; - switch(opcode) { - case Opcodes.OPC_getfield : - if (returnTypeSize == 2) { - this.stackDepth++; - } - break; - case Opcodes.OPC_getstatic : - if (returnTypeSize == 2) { - this.stackDepth += 2; - } else { - this.stackDepth++; - } - break; - case Opcodes.OPC_putfield : - if (returnTypeSize == 2) { - this.stackDepth -= 3; - } else { - this.stackDepth -= 2; - } - break; - case Opcodes.OPC_putstatic : - if (returnTypeSize == 2) { - this.stackDepth -= 2; - } else { - this.stackDepth--; - } - } - if (this.stackDepth > this.stackMax) { - this.stackMax = this.stackDepth; - } - if (this.classFileOffset + 2 >= this.bCodeStream.length) { - resizeByteArray(); - } - this.position++; - this.bCodeStream[this.classFileOffset++] = opcode; - writeUnsignedShort(this.constantPool.literalIndexForField(declaringClass, name, signature)); -} - -private void generateFieldAccess(byte opcode, int returnTypeSize, ReferenceBinding binding, char[] name, TypeBinding type) { - if (binding.isNestedType()) { - this.classFile.recordInnerClasses(binding); - } - TypeBinding leafComponentType = type.leafComponentType(); - if (leafComponentType.isNestedType()) { - this.classFile.recordInnerClasses(leafComponentType); - } - this.generateFieldAccess(opcode, returnTypeSize, binding.constantPoolName(), name, type.signature()); -} - /** * Generates the sequence of instructions which will perform the conversion of the expression * on the stack into a different type (e.g. long l = someInt; --> i2l must be inserted). @@ -2251,14 +2260,14 @@ } else if (mappingSequence[0] instanceof FieldBinding) { FieldBinding fieldBinding = (FieldBinding) mappingSequence[0]; aload_0(); - getfield(fieldBinding); + fieldAccess0(Opcodes.OPC_getfield, fieldBinding, null /* default declaringClass */); } else { load((LocalVariableBinding) mappingSequence[0]); } for (int i = 1, length = mappingSequence.length; i < length; i++) { if (mappingSequence[i] instanceof FieldBinding) { FieldBinding fieldBinding = (FieldBinding) mappingSequence[i]; - getfield(fieldBinding); + fieldAccess0(Opcodes.OPC_getfield, fieldBinding, null /* default declaringClass */); } else { invoke(Opcodes.OPC_invokestatic, (MethodBinding) mappingSequence[i], null /* default declaringClass */); } @@ -2400,11 +2409,9 @@ //} public void generateSyntheticBodyForEnumValues(SyntheticMethodBinding methodBinding) { ClassScope scope = ((SourceTypeBinding)methodBinding.declaringClass).scope; - FieldBinding enumValuesSyntheticfield = scope.referenceContext.enumValuesSyntheticfield; initializeMaxLocals(methodBinding); TypeBinding enumArray = methodBinding.returnType; - - getstatic(enumValuesSyntheticfield); + fieldAccess0(Opcodes.OPC_getstatic, scope.referenceContext.enumValuesSyntheticfield, null /* default declaringClass */); dup(); astore_0(); iconst_0(); @@ -2425,11 +2432,11 @@ public void generateSyntheticBodyForFieldReadAccess(SyntheticMethodBinding accessBinding) { initializeMaxLocals(accessBinding); FieldBinding fieldBinding = accessBinding.targetReadField; - if (fieldBinding.isStatic()) - getstatic(fieldBinding); - else { + if (fieldBinding.isStatic()) { + fieldAccess0(Opcodes.OPC_getstatic, fieldBinding, null /* default declaringClass */); + } else { aload_0(); - getfield(fieldBinding); + fieldAccess0(Opcodes.OPC_getfield, fieldBinding, null /* default declaringClass */); } switch (fieldBinding.type.id) { // case T_void : @@ -2461,11 +2468,11 @@ FieldBinding fieldBinding = accessBinding.targetWriteField; if (fieldBinding.isStatic()) { load(fieldBinding.type, 0); - putstatic(fieldBinding); + fieldAccess0(Opcodes.OPC_putstatic, fieldBinding, null /* default declaringClass */); } else { aload_0(); load(fieldBinding.type, 1); - putfield(fieldBinding); + fieldAccess0(Opcodes.OPC_putfield, fieldBinding, null /* default declaringClass */); } return_(); } @@ -2551,7 +2558,7 @@ initializeMaxLocals(methodBinding); final BranchLabel nullLabel = new BranchLabel(this); FieldBinding syntheticFieldBinding = methodBinding.targetReadField; - getstatic(syntheticFieldBinding); + fieldAccess0(Opcodes.OPC_getstatic, syntheticFieldBinding, null /* default declaringClass */); dup(); ifnull(nullLabel); areturn(); @@ -2575,7 +2582,7 @@ final ExceptionLabel anyExceptionHandler = new ExceptionLabel(this, TypeBinding.LONG /* represents NoSuchFieldError*/); anyExceptionHandler.placeStart(); aload_0(); - getstatic(fieldBinding); + fieldAccess0(Opcodes.OPC_getstatic, fieldBinding, null /* default declaringClass */); invokeEnumOrdinal(enumBinding.constantPoolName()); this.generateInlinedValue(fieldBinding.id + 1); // zero should not be returned see bug 141810 iastore(); @@ -2591,7 +2598,7 @@ } aload_0(); dup(); - putstatic(syntheticFieldBinding); + fieldAccess0(Opcodes.OPC_putstatic, syntheticFieldBinding, null /* default declaringClass */); areturn(); removeVariable(localVariableBinding); } @@ -2868,116 +2875,155 @@ return contents; } -public void getfield(FieldBinding fieldBinding) { - int returnTypeSize = 1; - if ((fieldBinding.type.id == TypeIds.T_double) || (fieldBinding.type.id == TypeIds.T_long)) { - returnTypeSize = 2; - } - generateFieldAccess( - Opcodes.OPC_getfield, - returnTypeSize, - fieldBinding.declaringClass, - fieldBinding.name, - fieldBinding.type); +/** + * Returns the type that should be substituted to original binding declaring class as the proper receiver type + * @param currentScope + * @param codegenBinding + * @param actualReceiverType + * @param isImplicitThisReceiver + * @return the receiver type to use in constant pool + */ +public static TypeBinding getConstantPoolDeclaringClass(BlockScope currentScope, FieldBinding codegenBinding, TypeBinding actualReceiverType, boolean isImplicitThisReceiver) { + ReferenceBinding constantPoolDeclaringClass = codegenBinding.declaringClass; + // if the binding declaring class is not visible, need special action + // for runtime compatibility on 1.2 VMs : change the declaring class of the binding + // NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type + // and not from Object or implicit static field access. + if (constantPoolDeclaringClass != actualReceiverType.erasure() + && !actualReceiverType.isArrayType() + && constantPoolDeclaringClass != null // array.length + && codegenBinding.constant() == Constant.NotAConstant) { + CompilerOptions options = currentScope.compilerOptions(); + if ((options.targetJDK >= ClassFileConstants.JDK1_2 + && (options.complianceLevel >= ClassFileConstants.JDK1_4 || !(isImplicitThisReceiver && codegenBinding.isStatic())) + && constantPoolDeclaringClass.id != TypeIds.T_JavaLangObject) // no change for Object fields + || !constantPoolDeclaringClass.canBeSeenBy(currentScope)) { + + return actualReceiverType.erasure(); + } + } + return constantPoolDeclaringClass; } +/** + * Returns the type that should be substituted to original binding declaring class as the proper receiver type + * @param currentScope + * @param codegenBinding + * @param actualReceiverType + * @param isImplicitThisReceiver + * @param hasGenericCast + * @return the receiver type to use in constant pool + */ +public static TypeBinding getConstantPoolDeclaringClass(BlockScope currentScope, MethodBinding codegenBinding, TypeBinding actualReceiverType, boolean isImplicitThisReceiver, boolean hasGenericCast) { + TypeBinding constantPoolDeclaringClass = codegenBinding.declaringClass; + // Post 1.4.0 target, array clone() invocations are qualified with array type + // This is handled in array type #clone method binding resolution (see Scope and UpdatedMethodBinding) + if (codegenBinding == currentScope.environment().arrayClone) { + CompilerOptions options = currentScope.compilerOptions(); + if (options.sourceLevel > ClassFileConstants.JDK1_4 ) { + constantPoolDeclaringClass = actualReceiverType.erasure(); + } + } else { + // if the binding declaring class is not visible, need special action + // for runtime compatibility on 1.2 VMs : change the declaring class of the binding + // NOTE: from target 1.2 on, method's declaring class is touched if any different from receiver type + // and not from Object or implicit static method call. + if (constantPoolDeclaringClass != actualReceiverType.erasure() && !hasGenericCast && !actualReceiverType.isArrayType()) { + CompilerOptions options = currentScope.compilerOptions(); + if ((options.targetJDK >= ClassFileConstants.JDK1_2 + && (options.complianceLevel >= ClassFileConstants.JDK1_4 || !(isImplicitThisReceiver && codegenBinding.isStatic())) + && codegenBinding.declaringClass.id != TypeIds.T_JavaLangObject) // no change for Object methods + || !codegenBinding.declaringClass.canBeSeenBy(currentScope)) { + constantPoolDeclaringClass = actualReceiverType.erasure(); + } + } + } + return constantPoolDeclaringClass; +} protected int getPosition() { return this.position; } -public void getstatic(FieldBinding fieldBinding) { - int returnTypeSize = 1; - if ((fieldBinding.type.id == TypeIds.T_double) || (fieldBinding.type.id == TypeIds.T_long)) { - returnTypeSize = 2; - } - generateFieldAccess( - Opcodes.OPC_getstatic, - returnTypeSize, - fieldBinding.declaringClass, - fieldBinding.name, - fieldBinding.type); -} - public void getTYPE(int baseTypeID) { this.countLabels = 0; switch (baseTypeID) { case TypeIds.T_byte : // getstatic: java.lang.Byte.TYPE - generateFieldAccess( + fieldAccess( Opcodes.OPC_getstatic, - 1, + 1, // return type size ConstantPool.JavaLangByteConstantPoolName, ConstantPool.TYPE, ConstantPool.JavaLangClassSignature); break; case TypeIds.T_short : // getstatic: java.lang.Short.TYPE - generateFieldAccess( + fieldAccess( Opcodes.OPC_getstatic, - 1, + 1, // return type size ConstantPool.JavaLangShortConstantPoolName, ConstantPool.TYPE, ConstantPool.JavaLangClassSignature); break; case TypeIds.T_char : // getstatic: java.lang.Character.TYPE - generateFieldAccess( + fieldAccess( Opcodes.OPC_getstatic, - 1, + 1, // return type size ConstantPool.JavaLangCharacterConstantPoolName, ConstantPool.TYPE, ConstantPool.JavaLangClassSignature); break; case TypeIds.T_int : // getstatic: java.lang.Integer.TYPE - generateFieldAccess( + fieldAccess( Opcodes.OPC_getstatic, - 1, + 1, // return type size ConstantPool.JavaLangIntegerConstantPoolName, ConstantPool.TYPE, ConstantPool.JavaLangClassSignature); break; case TypeIds.T_long : // getstatic: java.lang.Long.TYPE - generateFieldAccess( + fieldAccess( Opcodes.OPC_getstatic, - 1, + 1, // return type size ConstantPool.JavaLangLongConstantPoolName, ConstantPool.TYPE, ConstantPool.JavaLangClassSignature); break; case TypeIds.T_float : // getstatic: java.lang.Float.TYPE - generateFieldAccess( + fieldAccess( Opcodes.OPC_getstatic, - 1, + 1, // return type size ConstantPool.JavaLangFloatConstantPoolName, ConstantPool.TYPE, ConstantPool.JavaLangClassSignature); break; case TypeIds.T_double : // getstatic: java.lang.Double.TYPE - generateFieldAccess( + fieldAccess( Opcodes.OPC_getstatic, - 1, + 1, // return type size ConstantPool.JavaLangDoubleConstantPoolName, ConstantPool.TYPE, ConstantPool.JavaLangClassSignature); break; case TypeIds.T_boolean : // getstatic: java.lang.Boolean.TYPE - generateFieldAccess( + fieldAccess( Opcodes.OPC_getstatic, - 1, + 1, // return type size ConstantPool.JavaLangBooleanConstantPoolName, ConstantPool.TYPE, ConstantPool.JavaLangClassSignature); break; case TypeIds.T_void : // getstatic: java.lang.Void.TYPE - generateFieldAccess( + fieldAccess( Opcodes.OPC_getstatic, - 1, + 1, // return type size ConstantPool.JavaLangVoidConstantPoolName, ConstantPool.TYPE, ConstantPool.JavaLangClassSignature); @@ -3740,6 +3786,35 @@ writeUnsignedShort(this.constantPool.literalIndexForType(typeBinding)); } +protected void invoke(byte opcode, int receiverAndArgsSize, int returnTypeSize, char[] declaringClass, char[] selector, char[] signature) { + this.countLabels = 0; + if (opcode == Opcodes.OPC_invokeinterface) { + // invokeinterface + if (this.classFileOffset + 4 >= this.bCodeStream.length) { + resizeByteArray(); + } + this.position +=3; + this.bCodeStream[this.classFileOffset++] = opcode; + writeUnsignedShort(this.constantPool.literalIndexForMethod(declaringClass, selector, signature, true)); + this.bCodeStream[this.classFileOffset++] = (byte) receiverAndArgsSize; + this.bCodeStream[this.classFileOffset++] = 0; + } else { + // invokespecial + // invokestatic + // invokevirtual + if (this.classFileOffset + 2 >= this.bCodeStream.length) { + resizeByteArray(); + } + this.position++; + this.bCodeStream[this.classFileOffset++] = opcode; + writeUnsignedShort(this.constantPool.literalIndexForMethod(declaringClass, selector, signature, false)); + } + this.stackDepth += returnTypeSize - receiverAndArgsSize; + if (this.stackDepth > this.stackMax) { + this.stackMax = this.stackDepth; + } +} + public void invoke(byte opcode, MethodBinding methodBinding, TypeBinding declaringClass) { if (declaringClass == null) declaringClass = methodBinding.declaringClass; if (declaringClass.isNestedType()) { @@ -3835,35 +3910,6 @@ methodBinding.signature(this.classFile)); } -protected void invoke(byte opcode, int receiverAndArgsSize, int returnTypeSize, char[] declaringClass, char[] selector, char[] signature) { - this.countLabels = 0; - if (opcode == Opcodes.OPC_invokeinterface) { - // invokeinterface - if (this.classFileOffset + 4 >= this.bCodeStream.length) { - resizeByteArray(); - } - this.position +=3; - this.bCodeStream[this.classFileOffset++] = opcode; - writeUnsignedShort(this.constantPool.literalIndexForMethod(declaringClass, selector, signature, true)); - this.bCodeStream[this.classFileOffset++] = (byte) receiverAndArgsSize; - this.bCodeStream[this.classFileOffset++] = 0; - } else { - // invokespecial - // invokestatic - // invokevirtual - if (this.classFileOffset + 2 >= this.bCodeStream.length) { - resizeByteArray(); - } - this.position++; - this.bCodeStream[this.classFileOffset++] = opcode; - writeUnsignedShort(this.constantPool.literalIndexForMethod(declaringClass, selector, signature, false)); - } - this.stackDepth += returnTypeSize - receiverAndArgsSize; - if (this.stackDepth > this.stackMax) { - this.stackMax = this.stackDepth; - } -} - protected void invokeAccessibleObjectSetAccessible() { // invokevirtual: java.lang.reflect.AccessibleObject.setAccessible(Z)V; invoke( @@ -5142,7 +5188,7 @@ load(localBinding.type, localBinding.resolvedPosition); } -public final void load(TypeBinding typeBinding, int resolvedPosition) { +protected final void load(TypeBinding typeBinding, int resolvedPosition) { this.countLabels = 0; // Using dedicated int bytecode switch(typeBinding.id) { @@ -5685,32 +5731,6 @@ this.stackMax = this.stackDepth; } -public void putfield(FieldBinding fieldBinding) { - int returnTypeSize = 1; - if ((fieldBinding.type.id == TypeIds.T_double) || (fieldBinding.type.id == TypeIds.T_long)) { - returnTypeSize = 2; - } - generateFieldAccess( - Opcodes.OPC_putfield, - returnTypeSize, - fieldBinding.declaringClass, - fieldBinding.name, - fieldBinding.type); -} - -public void putstatic(FieldBinding fieldBinding) { - int returnTypeSize = 1; - if ((fieldBinding.type.id == TypeIds.T_double) || (fieldBinding.type.id == TypeIds.T_long)) { - returnTypeSize = 2; - } - generateFieldAccess( - Opcodes.OPC_putstatic, - returnTypeSize, - fieldBinding.declaringClass, - fieldBinding.name, - fieldBinding.type); -} - public void record(LocalVariableBinding local) { if ((this.generateAttributes & (ClassFileConstants.ATTR_VARS | ClassFileConstants.ATTR_STACK_MAP_TABLE Index: compiler/org/eclipse/jdt/internal/compiler/codegen/StackMapFrameCodeStream.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/StackMapFrameCodeStream.java,v retrieving revision 1.25 diff -u -r1.25 StackMapFrameCodeStream.java --- compiler/org/eclipse/jdt/internal/compiler/codegen/StackMapFrameCodeStream.java 8 Jul 2008 02:01:42 -0000 1.25 +++ compiler/org/eclipse/jdt/internal/compiler/codegen/StackMapFrameCodeStream.java 24 Sep 2008 12:36:52 -0000 @@ -273,7 +273,7 @@ // use in CLDC mode BranchLabel endLabel = new BranchLabel(this); if (syntheticFieldBinding != null) { // non interface case - getstatic(syntheticFieldBinding); + fieldAccess0(Opcodes.OPC_getstatic, syntheticFieldBinding, null /* default declaringClass */); dup(); ifnonnull(endLabel); pop(); @@ -316,7 +316,7 @@ if (syntheticFieldBinding != null) { // non interface case dup(); - putstatic(syntheticFieldBinding); + fieldAccess0(Opcodes.OPC_putstatic, syntheticFieldBinding, null /* default declaringClass */); } int fromPC = this.position; goto_(endLabel); Index: eval/org/eclipse/jdt/internal/eval/CodeSnippetFieldReference.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetFieldReference.java,v retrieving revision 1.43 diff -u -r1.43 CodeSnippetFieldReference.java --- eval/org/eclipse/jdt/internal/eval/CodeSnippetFieldReference.java 27 Jun 2008 16:04:07 -0000 1.43 +++ eval/org/eclipse/jdt/internal/eval/CodeSnippetFieldReference.java 24 Sep 2008 12:36:52 -0000 @@ -15,19 +15,16 @@ import org.eclipse.jdt.internal.compiler.ast.Expression; import org.eclipse.jdt.internal.compiler.ast.FieldReference; import org.eclipse.jdt.internal.compiler.ast.IntLiteral; -import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.codegen.CodeStream; +import org.eclipse.jdt.internal.compiler.codegen.Opcodes; import org.eclipse.jdt.internal.compiler.flow.FlowInfo; -import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; -import org.eclipse.jdt.internal.compiler.lookup.ParameterizedFieldBinding; import org.eclipse.jdt.internal.compiler.lookup.ProblemFieldBinding; import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons; -import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; -import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding; +import org.eclipse.jdt.internal.compiler.lookup.TypeIds; public class CodeSnippetFieldReference extends FieldReference implements ProblemReasons, EvaluationConstants { @@ -43,26 +40,30 @@ this.evaluationContext = evaluationContext; } public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) { - - if (this.codegenBinding.canBeSeenBy(this.receiverType, this, currentScope)) { - this.receiver.generateCode(currentScope, codeStream, !this.codegenBinding.isStatic()); + FieldBinding codegenBinding = this.binding.original(); + if (codegenBinding.canBeSeenBy(this.actualReceiverType, this, currentScope)) { + this.receiver.generateCode(currentScope, codeStream, !codegenBinding.isStatic()); assignment.expression.generateCode(currentScope, codeStream, true); - fieldStore(codeStream, this.codegenBinding, null, valueRequired); + fieldStore(codeStream, codegenBinding, null, valueRequired); } else { - codeStream.generateEmulationForField(this.codegenBinding); - this.receiver.generateCode(currentScope, codeStream, !this.codegenBinding.isStatic()); - if (this.codegenBinding.isStatic()) { // need a receiver? + codeStream.generateEmulationForField(codegenBinding); + this.receiver.generateCode(currentScope, codeStream, !codegenBinding.isStatic()); + if (codegenBinding.isStatic()) { // need a receiver? codeStream.aconst_null(); } assignment.expression.generateCode(currentScope, codeStream, true); if (valueRequired) { - if ((this.codegenBinding.type == TypeBinding.LONG) || (this.codegenBinding.type == TypeBinding.DOUBLE)) { - codeStream.dup2_x2(); - } else { - codeStream.dup_x2(); - } + switch (codegenBinding.type.id) { + case TypeIds.T_long : + case TypeIds.T_double : + codeStream.dup2_x2(); + break; + default : + codeStream.dup_x2(); + break; + } } - codeStream.generateEmulatedWriteAccessForField(this.codegenBinding); + codeStream.generateEmulatedWriteAccessForField(codegenBinding); } if (valueRequired){ codeStream.generateImplicitConversion(assignment.implicitConversion); @@ -76,33 +77,35 @@ * @param valueRequired boolean */ public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { - int pc = codeStream.position; if (this.constant != Constant.NotAConstant) { if (valueRequired) { codeStream.generateConstant(this.constant, this.implicitConversion); } } else { - boolean isStatic = this.codegenBinding.isStatic(); + FieldBinding codegenBinding = this.binding.original(); + boolean isStatic = codegenBinding.isStatic(); this.receiver.generateCode(currentScope, codeStream, !isStatic); if (valueRequired) { - Constant fieldConstant = this.codegenBinding.constant(); + Constant fieldConstant = codegenBinding.constant(); if (fieldConstant == Constant.NotAConstant) { - if (this.codegenBinding.declaringClass == null) { // array length + if (codegenBinding.declaringClass == null) { // array length codeStream.arraylength(); } else { - if (this.codegenBinding.canBeSeenBy(this.receiverType, this, currentScope)) { + if (codegenBinding.canBeSeenBy(this.actualReceiverType, this, currentScope)) { + TypeBinding someReceiverType = this.delegateThis != null ? this.delegateThis.type : this.actualReceiverType; + TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, someReceiverType, this.receiver.isImplicitThis()); if (isStatic) { - codeStream.getstatic(this.codegenBinding); + codeStream.fieldAccess0(Opcodes.OPC_getstatic , codegenBinding, constantPoolDeclaringClass); } else { - codeStream.getfield(this.codegenBinding); + codeStream.fieldAccess0(Opcodes.OPC_getfield, codegenBinding, constantPoolDeclaringClass); } } else { if (isStatic) { // we need a null on the stack to use the reflect emulation codeStream.aconst_null(); } - codeStream.generateEmulatedReadAccessForField(this.codegenBinding); + codeStream.generateEmulatedReadAccessForField(codegenBinding); } } codeStream.generateImplicitConversion(this.implicitConversion); @@ -124,15 +127,17 @@ } public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) { - boolean isStatic; - if (this.codegenBinding.canBeSeenBy(this.receiverType, this, currentScope)) { - this.receiver.generateCode(currentScope, codeStream, !(isStatic = this.codegenBinding.isStatic())); + FieldBinding codegenBinding = this.binding.original(); + if (codegenBinding.canBeSeenBy(this.actualReceiverType, this, currentScope)) { + this.receiver.generateCode(currentScope, codeStream, !(isStatic = codegenBinding.isStatic())); + TypeBinding someReceiverType = this.delegateThis != null ? this.delegateThis.type : this.actualReceiverType; + TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, someReceiverType, this.receiver.isImplicitThis()); if (isStatic) { - codeStream.getstatic(this.codegenBinding); + codeStream.fieldAccess0(Opcodes.OPC_getstatic, codegenBinding, constantPoolDeclaringClass); } else { codeStream.dup(); - codeStream.getfield(this.codegenBinding); + codeStream.fieldAccess0(Opcodes.OPC_getfield, codegenBinding, constantPoolDeclaringClass); } int operationTypeID; switch(operationTypeID = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) { @@ -155,17 +160,17 @@ // cast the value back to the array reference type codeStream.generateImplicitConversion(assignmentImplicitConversion); } - fieldStore(codeStream, this.codegenBinding, null, valueRequired); + fieldStore(codeStream, codegenBinding, null, valueRequired); } else { - this.receiver.generateCode(currentScope, codeStream, !(isStatic = this.codegenBinding.isStatic())); + this.receiver.generateCode(currentScope, codeStream, !(isStatic = codegenBinding.isStatic())); if (isStatic) { // used to store the value - codeStream.generateEmulationForField(this.codegenBinding); + codeStream.generateEmulationForField(codegenBinding); codeStream.aconst_null(); // used to retrieve the actual value codeStream.aconst_null(); - codeStream.generateEmulatedReadAccessForField(this.codegenBinding); + codeStream.generateEmulatedReadAccessForField(codegenBinding); } else { // used to store the value codeStream.generateEmulationForField(this.binding); @@ -173,7 +178,7 @@ // used to retrieve the actual value codeStream.dup(); - codeStream.generateEmulatedReadAccessForField(this.codegenBinding); + codeStream.generateEmulatedReadAccessForField(codegenBinding); } int operationTypeID; if ((operationTypeID = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) == T_JavaLangString) { @@ -195,7 +200,7 @@ // current stack is: // field receiver value if (valueRequired) { - if ((this.codegenBinding.type == TypeBinding.LONG) || (this.codegenBinding.type == TypeBinding.DOUBLE)) { + if ((codegenBinding.type == TypeBinding.LONG) || (codegenBinding.type == TypeBinding.DOUBLE)) { codeStream.dup2_x2(); } else { codeStream.dup_x2(); @@ -203,61 +208,69 @@ } // current stack is: // value field receiver value - codeStream.generateEmulatedWriteAccessForField(this.codegenBinding); + codeStream.generateEmulatedWriteAccessForField(codegenBinding); } } public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) { boolean isStatic; - if (this.codegenBinding.canBeSeenBy(this.receiverType, this, currentScope)) { + FieldBinding codegenBinding = this.binding.original(); + if (codegenBinding.canBeSeenBy(this.actualReceiverType, this, currentScope)) { super.generatePostIncrement(currentScope, codeStream, postIncrement, valueRequired); } else { - this.receiver.generateCode(currentScope, codeStream, !(isStatic = this.codegenBinding.isStatic())); + this.receiver.generateCode(currentScope, codeStream, !(isStatic = codegenBinding.isStatic())); if (isStatic) { codeStream.aconst_null(); } // the actual stack is: receiver codeStream.dup(); // the actual stack is: receiver receiver - codeStream.generateEmulatedReadAccessForField(this.codegenBinding); + codeStream.generateEmulatedReadAccessForField(codegenBinding); // the actual stack is: receiver value // receiver value // value receiver value dup_x1 or dup2_x1 if value required - // value value receiver value dup_x1 or dup2_x1 - // value value receiver pop or pop2 + // value value receiver value dup_x1 or dup2_x1 + // value value receiver pop or pop2 // value value receiver field generateEmulationForField - // value value field receiver swap - // value field receiver value field receiver dup2_x1 or dup2_x2 - // value field receiver value pop2 - // value field receiver newvalue generate constant + op - // value store - if (valueRequired) { - if ((this.codegenBinding.type == TypeBinding.LONG) || (this.codegenBinding.type == TypeBinding.DOUBLE)) { + // value value field receiver swap + // value field receiver value field receiver dup2_x1 or dup2_x2 + // value field receiver value pop2 + // value field receiver newvalue generate constant + op + // value store + int typeID; + switch (typeID = codegenBinding.type.id) { + case TypeIds.T_long : + case TypeIds.T_double : + if (valueRequired) { + codeStream.dup2_x1(); + } codeStream.dup2_x1(); - } else { + codeStream.pop2(); + break; + default : + if (valueRequired) { + codeStream.dup_x1(); + } codeStream.dup_x1(); - } - } - if ((this.codegenBinding.type == TypeBinding.LONG) || (this.codegenBinding.type == TypeBinding.DOUBLE)) { - codeStream.dup2_x1(); - codeStream.pop2(); - } else { - codeStream.dup_x1(); - codeStream.pop(); + codeStream.pop(); + break; } - codeStream.generateEmulationForField(this.codegenBinding); + codeStream.generateEmulationForField(codegenBinding); codeStream.swap(); - - if ((this.codegenBinding.type == TypeBinding.LONG) || (this.codegenBinding.type == TypeBinding.DOUBLE)) { - codeStream.dup2_x2(); - } else { - codeStream.dup2_x1(); + switch (typeID) { + case TypeIds.T_long : + case TypeIds.T_double : + codeStream.dup2_x2(); + break; + default : + codeStream.dup2_x1(); + break; } codeStream.pop2(); codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion); - codeStream.sendOperator(postIncrement.operator, this.codegenBinding.type.id); + codeStream.sendOperator(postIncrement.operator, codegenBinding.type.id); codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion); - codeStream.generateEmulatedWriteAccessForField(this.codegenBinding); + codeStream.generateEmulatedWriteAccessForField(codegenBinding); } } /* @@ -267,43 +280,6 @@ // The private access will be managed through the code generation if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0) return; - - // if field from parameterized type got found, use the original field at codegen time - if (this.binding instanceof ParameterizedFieldBinding) { - ParameterizedFieldBinding parameterizedField = (ParameterizedFieldBinding) this.binding; - this.codegenBinding = parameterizedField.originalField; - // extra cast needed if field type was type variable - if (this.codegenBinding.type.isTypeVariable()) { - TypeVariableBinding variableReturnType = (TypeVariableBinding) this.codegenBinding.type; - if (variableReturnType.firstBound != parameterizedField.type) { // no need for extra cast if same as first bound anyway - this.genericCast = parameterizedField.type.erasure(); - } - } - } else { - this.codegenBinding = this.binding; - } - - // if the binding declaring class is not visible, need special action - // for runtime compatibility on 1.2 VMs : change the declaring class of the binding - // NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type - TypeBinding someReceiverType = this.delegateThis != null ? this.delegateThis.type : this.receiverType; - if (this.binding.declaringClass != someReceiverType - && !someReceiverType.isArrayType() - && this.binding.declaringClass != null // array.length - && this.binding.constant() == Constant.NotAConstant) { - - CompilerOptions options = currentScope.compilerOptions(); - if ((options.targetJDK >= ClassFileConstants.JDK1_2 - && (options.complianceLevel >= ClassFileConstants.JDK1_4 || !this.receiver.isImplicitThis() || !this.codegenBinding.isStatic()) - && this.binding.declaringClass.id != T_JavaLangObject) // no change for Object fields - || !this.binding.declaringClass.canBeSeenBy(currentScope)) { - - this.codegenBinding = - currentScope.enclosingSourceType().getUpdatedFieldBinding( - this.codegenBinding, - (ReferenceBinding) someReceiverType.erasure()); - } - } } public TypeBinding resolveType(BlockScope scope) { // Answer the signature type of the field. @@ -311,13 +287,13 @@ // and initialized with a (compile time) constant // regular receiver reference - this.receiverType = this.receiver.resolveType(scope); - if (this.receiverType == null){ + this.actualReceiverType = this.receiver.resolveType(scope); + if (this.actualReceiverType == null){ this.constant = Constant.NotAConstant; return null; } // the case receiverType.isArrayType and token = 'length' is handled by the scope API - this.codegenBinding = this.binding = scope.getField(this.receiverType, this.token, this); + this.binding = scope.getField(this.actualReceiverType, this.token, this); FieldBinding firstAttempt = this.binding; boolean isNotVisible = false; if (!this.binding.isValidBinding()) { @@ -328,25 +304,25 @@ this.delegateThis = scope.getField(scope.enclosingSourceType(), DELEGATE_THIS, this); if (this.delegateThis == null){ // if not found then internal error, field should have been found this.constant = Constant.NotAConstant; - scope.problemReporter().invalidField(this, this.receiverType); + scope.problemReporter().invalidField(this, this.actualReceiverType); return null; } } else { this.constant = Constant.NotAConstant; - scope.problemReporter().invalidField(this, this.receiverType); + scope.problemReporter().invalidField(this, this.actualReceiverType); return null; } CodeSnippetScope localScope = new CodeSnippetScope(scope); - this.codegenBinding = this.binding = localScope.getFieldForCodeSnippet(this.delegateThis.type, this.token, this); + this.binding = localScope.getFieldForCodeSnippet(this.delegateThis.type, this.token, this); } } if (!this.binding.isValidBinding()) { this.constant = Constant.NotAConstant; if (isNotVisible) { - this.codegenBinding = this.binding = firstAttempt; + this.binding = firstAttempt; } - scope.problemReporter().invalidField(this, this.receiverType); + scope.problemReporter().invalidField(this, this.actualReceiverType); return null; } Index: eval/org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java,v retrieving revision 1.55 diff -u -r1.55 CodeSnippetSingleNameReference.java --- eval/org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java 12 Sep 2008 13:28:54 -0000 1.55 +++ eval/org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java 24 Sep 2008 12:36:52 -0000 @@ -16,13 +16,27 @@ import org.eclipse.jdt.internal.compiler.ast.Expression; import org.eclipse.jdt.internal.compiler.ast.IntLiteral; import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; -import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.codegen.CodeStream; +import org.eclipse.jdt.internal.compiler.codegen.Opcodes; import org.eclipse.jdt.internal.compiler.flow.FlowContext; import org.eclipse.jdt.internal.compiler.flow.FlowInfo; -import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.impl.Constant; -import org.eclipse.jdt.internal.compiler.lookup.*; +import org.eclipse.jdt.internal.compiler.lookup.Binding; +import org.eclipse.jdt.internal.compiler.lookup.BlockScope; +import org.eclipse.jdt.internal.compiler.lookup.ClassScope; +import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; +import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; +import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; +import org.eclipse.jdt.internal.compiler.lookup.ParameterizedFieldBinding; +import org.eclipse.jdt.internal.compiler.lookup.ProblemBinding; +import org.eclipse.jdt.internal.compiler.lookup.ProblemFieldBinding; +import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons; +import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; +import org.eclipse.jdt.internal.compiler.lookup.Scope; +import org.eclipse.jdt.internal.compiler.lookup.TagBits; +import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; +import org.eclipse.jdt.internal.compiler.lookup.TypeIds; +import org.eclipse.jdt.internal.compiler.lookup.VariableBinding; /** * A single name reference inside a code snippet can denote a field of a remote @@ -108,11 +122,11 @@ return; } if ((operation.right instanceof SingleNameReference) - && ((operator == PLUS) || (operator == MULTIPLY)) // only commutative operations - && ((variableReference = (SingleNameReference) operation.right).binding == this.binding) - && (operation.left.constant != Constant.NotAConstant) // exclude non constant expressions, since could have side-effect - && (((operation.left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) != T_JavaLangString) // exclude string concatenation which would occur backwards - && (((operation.right.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) != T_JavaLangString)) { // exclude string concatenation which would occur backwards + && ((operator == PLUS) || (operator == MULTIPLY)) // only commutative operations + && ((variableReference = (SingleNameReference) operation.right).binding == this.binding) + && (operation.left.constant != Constant.NotAConstant) // exclude non constant expressions, since could have side-effect + && (((operation.left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) != T_JavaLangString) // exclude string concatenation which would occur backwards + && (((operation.right.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) != T_JavaLangString)) { // exclude string concatenation which would occur backwards // i = value + i, then use the variable on the right hand side, since it has the correct implicit conversion variableReference.generateCompoundAssignment(currentScope, codeStream, this.syntheticAccessors == null ? null : this.syntheticAccessors[WRITE], operation.left, operator, operation.implicitConversion, valueRequired); if (valueRequired) { @@ -123,9 +137,9 @@ } switch (this.bits & RestrictiveFlagMASK) { case Binding.FIELD : // assigning to a field - FieldBinding fieldBinding = (FieldBinding) this.codegenBinding; - if (fieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) { - if (!fieldBinding.isStatic()) { // need a receiver? + FieldBinding codegenField = ((FieldBinding) this.binding).original(); + if (codegenField.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) { + if (!codegenField.isStatic()) { // need a receiver? if ((this.bits & DepthMASK) != 0) { ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT); Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/); @@ -135,13 +149,13 @@ } } assignment.expression.generateCode(currentScope, codeStream, true); - fieldStore(codeStream, fieldBinding, null, valueRequired); + fieldStore(codeStream, codegenField, null, valueRequired); if (valueRequired) { codeStream.generateImplicitConversion(assignment.implicitConversion); } } else { - codeStream.generateEmulationForField(fieldBinding); - if (!fieldBinding.isStatic()) { // need a receiver? + codeStream.generateEmulationForField(codegenField); + if (!codegenField.isStatic()) { // need a receiver? if ((this.bits & DepthMASK) != 0) { // internal error, per construction we should have found it // not yet supported @@ -154,20 +168,20 @@ } assignment.expression.generateCode(currentScope, codeStream, true); if (valueRequired) { - if ((fieldBinding.type == TypeBinding.LONG) || (fieldBinding.type == TypeBinding.DOUBLE)) { + if ((codegenField.type == TypeBinding.LONG) || (codegenField.type == TypeBinding.DOUBLE)) { codeStream.dup2_x2(); } else { codeStream.dup_x2(); } } - codeStream.generateEmulatedWriteAccessForField(fieldBinding); + codeStream.generateEmulatedWriteAccessForField(codegenField); if (valueRequired) { codeStream.generateImplicitConversion(assignment.implicitConversion); } } return; case Binding.LOCAL : // assigning to a local variable - LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding; + LocalVariableBinding localBinding = (LocalVariableBinding) this.binding; if (localBinding.resolvedPosition != -1) { assignment.expression.generateCode(currentScope, codeStream, true); } else { @@ -214,13 +228,15 @@ case Binding.FIELD : // reading a field if (!valueRequired) break; - FieldBinding fieldBinding = (FieldBinding) this.codegenBinding; - Constant fieldConstant = fieldBinding.constant(); + FieldBinding codegenField = ((FieldBinding) this.binding).original(); + Constant fieldConstant = codegenField.constant(); if (fieldConstant == Constant.NotAConstant) { // directly use inlined value for constant fields - if (fieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) { - // directly use inlined value for constant fields - boolean isStatic; - if (!(isStatic = fieldBinding.isStatic())) { + if (codegenField.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) { + TypeBinding someReceiverType = this.delegateThis != null ? this.delegateThis.type : this.actualReceiverType; + TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, someReceiverType, true /* implicit this */); + if (codegenField.isStatic()) { + codeStream.fieldAccess0(Opcodes.OPC_getstatic, codegenField, constantPoolDeclaringClass); + } else { if ((this.bits & DepthMASK) != 0) { ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT); Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/); @@ -228,16 +244,11 @@ } else { generateReceiver(codeStream); } - } - // managing private access - if (isStatic) { - codeStream.getstatic(fieldBinding); - } else { - codeStream.getfield(fieldBinding); + codeStream.fieldAccess0(Opcodes.OPC_getfield, codegenField, constantPoolDeclaringClass); } } else { // managing private access - if (!fieldBinding.isStatic()) { + if (!codegenField.isStatic()) { if ((this.bits & DepthMASK) != 0) { // internal error, per construction we should have found it // not yet supported @@ -248,7 +259,7 @@ } else { codeStream.aconst_null(); } - codeStream.generateEmulatedReadAccessForField(fieldBinding); + codeStream.generateEmulatedReadAccessForField(codegenField); } if (this.genericCast != null) codeStream.checkcast(this.genericCast); codeStream.generateImplicitConversion(this.implicitConversion); @@ -257,7 +268,7 @@ } break; case Binding.LOCAL : // reading a local - LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding; + LocalVariableBinding localBinding = (LocalVariableBinding) this.binding; if (!valueRequired) break; // outer local? @@ -282,21 +293,23 @@ public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, MethodBinding writeAccessor, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) { switch (this.bits & RestrictiveFlagMASK) { case Binding.FIELD : // assigning to a field - FieldBinding fieldBinding = (FieldBinding) this.codegenBinding; - if (fieldBinding.isStatic()) { - if (fieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) { - codeStream.getstatic(fieldBinding); + FieldBinding codegenField = ((FieldBinding) this.binding).original(); + if (codegenField.isStatic()) { + if (codegenField.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) { + TypeBinding someReceiverType = this.delegateThis != null ? this.delegateThis.type : this.actualReceiverType; + TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, someReceiverType, true /* implicit this */); + codeStream.fieldAccess0(Opcodes.OPC_getstatic, codegenField, constantPoolDeclaringClass); } else { // used to store the value - codeStream.generateEmulationForField(fieldBinding); + codeStream.generateEmulationForField(codegenField); codeStream.aconst_null(); // used to retrieve the actual value codeStream.aconst_null(); - codeStream.generateEmulatedReadAccessForField(fieldBinding); + codeStream.generateEmulatedReadAccessForField(codegenField); } } else { - if (fieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) { + if (codegenField.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) { if ((this.bits & DepthMASK) != 0) { ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT); Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/); @@ -305,7 +318,9 @@ generateReceiver(codeStream); } codeStream.dup(); - codeStream.getfield(fieldBinding); + TypeBinding someReceiverType = this.delegateThis != null ? this.delegateThis.type : this.actualReceiverType; + TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, someReceiverType, true /* implicit this */); + codeStream.fieldAccess0(Opcodes.OPC_getfield, codegenField, constantPoolDeclaringClass); } else { if ((this.bits & DepthMASK) != 0) { // internal error, per construction we should have found it @@ -313,17 +328,17 @@ currentScope.problemReporter().needImplementation(this); } // used to store the value - codeStream.generateEmulationForField(fieldBinding); + codeStream.generateEmulationForField(codegenField); generateReceiver(codeStream); // used to retrieve the actual value codeStream.dup(); - codeStream.generateEmulatedReadAccessForField(fieldBinding); + codeStream.generateEmulatedReadAccessForField(codegenField); } } break; case Binding.LOCAL : // assigning to a local variable (cannot assign to outer local) - LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding; + LocalVariableBinding localBinding = (LocalVariableBinding) this.binding; // using incr bytecode if possible switch (localBinding.type.id) { case T_JavaLangString : @@ -387,32 +402,40 @@ // store the result back into the variable switch (this.bits & RestrictiveFlagMASK) { case Binding.FIELD : // assigning to a field - FieldBinding fieldBinding = (FieldBinding) this.codegenBinding; - if (fieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) { - fieldStore(codeStream, fieldBinding, writeAccessor, valueRequired); + FieldBinding codegenField = ((FieldBinding) this.binding).original(); + if (codegenField.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) { + fieldStore(codeStream, codegenField, writeAccessor, valueRequired); } else { // current stack is: // field receiver value if (valueRequired) { - if ((fieldBinding.type == TypeBinding.LONG) || (fieldBinding.type == TypeBinding.DOUBLE)) { - codeStream.dup2_x2(); - } else { - codeStream.dup_x2(); - } + switch (codegenField.type.id) { + case TypeIds.T_long : + case TypeIds.T_double : + codeStream.dup2_x2(); + break; + default: + codeStream.dup_x2(); + break; + } } // current stack is: // value field receiver value - codeStream.generateEmulatedWriteAccessForField(fieldBinding); + codeStream.generateEmulatedWriteAccessForField(codegenField); } return; case Binding.LOCAL : // assigning to a local variable - LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding; + LocalVariableBinding localBinding = (LocalVariableBinding) this.binding; if (valueRequired) { - if ((localBinding.type == TypeBinding.LONG) || (localBinding.type == TypeBinding.DOUBLE)) { - codeStream.dup2(); - } else { - codeStream.dup(); - } + switch (localBinding.type.id) { + case TypeIds.T_long : + case TypeIds.T_double : + codeStream.dup2(); + break; + default: + codeStream.dup(); + break; + } } codeStream.store(localBinding, false); } @@ -420,11 +443,11 @@ public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) { switch (this.bits & RestrictiveFlagMASK) { case Binding.FIELD : // assigning to a field - FieldBinding fieldBinding = (FieldBinding) this.codegenBinding; - if (fieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) { + FieldBinding codegenField = ((FieldBinding) this.binding).original(); + if (codegenField.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) { super.generatePostIncrement(currentScope, codeStream, postIncrement, valueRequired); } else { - if (fieldBinding.isStatic()) { + if (codegenField.isStatic()) { codeStream.aconst_null(); } else { if ((this.bits & DepthMASK) != 0) { @@ -435,40 +458,48 @@ generateReceiver(codeStream); } } - codeStream.generateEmulatedReadAccessForField(fieldBinding); + codeStream.generateEmulatedReadAccessForField(codegenField); if (valueRequired) { - if ((fieldBinding.type == TypeBinding.LONG) || (fieldBinding.type == TypeBinding.DOUBLE)) { - codeStream.dup2(); - } else { - codeStream.dup(); + switch (codegenField.type.id) { + case TypeIds.T_long : + case TypeIds.T_double : + codeStream.dup2(); + break; + default: + codeStream.dup(); + break; } } - codeStream.generateEmulationForField(fieldBinding); - if ((fieldBinding.type == TypeBinding.LONG) || (fieldBinding.type == TypeBinding.DOUBLE)) { - codeStream.dup_x2(); - codeStream.pop(); - if (fieldBinding.isStatic()) { - codeStream.aconst_null(); - } else { - generateReceiver(codeStream); - } - codeStream.dup_x2(); - codeStream.pop(); - } else { - codeStream.dup_x1(); + codeStream.generateEmulationForField(codegenField); + switch (codegenField.type.id) { + case TypeIds.T_long : + case TypeIds.T_double : + codeStream.dup_x2(); + codeStream.pop(); + if (codegenField.isStatic()) { + codeStream.aconst_null(); + } else { + generateReceiver(codeStream); + } + codeStream.dup_x2(); + codeStream.pop(); + break; + default: + codeStream.dup_x1(); codeStream.pop(); - if (fieldBinding.isStatic()) { + if (codegenField.isStatic()) { codeStream.aconst_null(); } else { generateReceiver(codeStream); } codeStream.dup_x1(); codeStream.pop(); + break; } codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion); - codeStream.sendOperator(postIncrement.operator, fieldBinding.type.id); + codeStream.sendOperator(postIncrement.operator, codegenField.type.id); codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion); - codeStream.generateEmulatedWriteAccessForField(fieldBinding); + codeStream.generateEmulatedWriteAccessForField(codegenField); } return; case Binding.LOCAL : // assigning to a local variable @@ -478,7 +509,7 @@ public void generateReceiver(CodeStream codeStream) { codeStream.aload_0(); if (this.delegateThis != null) { - codeStream.getfield(this.delegateThis); // delegated field access + codeStream.fieldAccess0(Opcodes.OPC_getfield, this.delegateThis, null /* default declaringClass */); // delegate field access } } /** @@ -509,36 +540,12 @@ // if field from parameterized type got found, use the original field at codegen time if (this.binding instanceof ParameterizedFieldBinding) { ParameterizedFieldBinding parameterizedField = (ParameterizedFieldBinding) this.binding; - this.codegenBinding = parameterizedField.originalField; - FieldBinding fieldCodegenBinding = (FieldBinding)this.codegenBinding; + FieldBinding codegenField = parameterizedField.originalField; // extra cast needed if field type was type variable - if ((fieldCodegenBinding.type.tagBits & TagBits.HasTypeVariable) != 0) { - this.genericCast = fieldCodegenBinding.type.genericCast(currentScope.boxing(parameterizedField.type)); // runtimeType could be base type in boxing case + if ((codegenField.type.tagBits & TagBits.HasTypeVariable) != 0) { + this.genericCast = codegenField.type.genericCast(currentScope.boxing(parameterizedField.type)); // runtimeType could be base type in boxing case } } - if ((this.bits & Binding.FIELD) != 0) { - FieldBinding fieldBinding = (FieldBinding) this.binding; - - // if the binding declaring class is not visible, need special action - // for runtime compatibility on 1.2 VMs : change the declaring class of the binding - // NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type - // and not from Object or implicit static field access. - if (fieldBinding.declaringClass != this.delegateThis.type - && fieldBinding.declaringClass != null // array.length - && fieldBinding.constant() == Constant.NotAConstant) { - CompilerOptions options = currentScope.compilerOptions(); - if ((options.targetJDK >= ClassFileConstants.JDK1_2 - && (options.complianceLevel >= ClassFileConstants.JDK1_4 || !fieldBinding.isStatic()) - && fieldBinding.declaringClass.id != T_JavaLangObject) // no change for Object fields - || !fieldBinding.declaringClass.canBeSeenBy(currentScope)) { - - this.codegenBinding = - currentScope.enclosingSourceType().getUpdatedFieldBinding( - (FieldBinding)this.codegenBinding, - (ReferenceBinding)this.delegateThis.type.erasure()); - } - } - } } /** * Normal field binding did not work, try to bind to a field of the delegate receiver. @@ -551,7 +558,7 @@ this.delegateThis = scope.getField(scope.enclosingSourceType(), DELEGATE_THIS, this); if (this.delegateThis != null){ // if not found then internal error, field should have been found // will not support innerclass emulation inside delegate - this.codegenBinding = this.binding = scope.getField(this.delegateThis.type, this.token, this); + this.binding = scope.getField(this.delegateThis.type, this.token, this); if (!this.binding.isValidBinding()) { return super.reportError(scope); } @@ -569,13 +576,13 @@ if (((ProblemFieldBinding) fieldBinding).problemId() == NotVisible) { // manage the access to a private field of the enclosing type CodeSnippetScope localScope = new CodeSnippetScope(scope); - this.codegenBinding = this.binding = localScope.getFieldForCodeSnippet(this.delegateThis.type, this.token, this); + this.binding = localScope.getFieldForCodeSnippet(this.delegateThis.type, this.token, this); return checkFieldAccess(scope); } else { return super.reportError(scope); } } - this.codegenBinding = this.binding = fieldBinding; + this.binding = fieldBinding; return checkFieldAccess(scope); } } Index: eval/org/eclipse/jdt/internal/eval/CodeSnippetMessageSend.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetMessageSend.java,v retrieving revision 1.58 diff -u -r1.58 CodeSnippetMessageSend.java --- eval/org/eclipse/jdt/internal/eval/CodeSnippetMessageSend.java 17 Sep 2008 11:11:09 -0000 1.58 +++ eval/org/eclipse/jdt/internal/eval/CodeSnippetMessageSend.java 24 Sep 2008 12:36:52 -0000 @@ -74,7 +74,7 @@ // generate arguments generateArguments(this.binding, this.arguments, currentScope, codeStream); // actual message invocation - TypeBinding constantPoolDeclaringClass = getConstantPoolDeclaringClass(currentScope); + TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis(), this.receiverGenericCast != null); if (isStatic) { codeStream.invoke(Opcodes.OPC_invokestatic, codegenBinding, constantPoolDeclaringClass); } else if( (this.receiver.isSuper()) || codegenBinding.isPrivate()){ Index: eval/org/eclipse/jdt/internal/eval/CodeSnippetThisReference.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetThisReference.java,v retrieving revision 1.34 diff -u -r1.34 CodeSnippetThisReference.java --- eval/org/eclipse/jdt/internal/eval/CodeSnippetThisReference.java 27 Jun 2008 16:04:06 -0000 1.34 +++ eval/org/eclipse/jdt/internal/eval/CodeSnippetThisReference.java 24 Sep 2008 12:36:52 -0000 @@ -12,6 +12,7 @@ import org.eclipse.jdt.internal.compiler.ast.ThisReference; import org.eclipse.jdt.internal.compiler.codegen.CodeStream; +import org.eclipse.jdt.internal.compiler.codegen.Opcodes; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; @@ -58,7 +59,7 @@ int pc = codeStream.position; if (valueRequired) { codeStream.aload_0(); - codeStream.getfield(this.delegateThis); + codeStream.fieldAccess0(Opcodes.OPC_getfield, this.delegateThis, null /* default declaringClass */); // delegate field access } codeStream.recordPositionsFrom(pc, this.sourceStart); } Index: eval/org/eclipse/jdt/internal/eval/CodeSnippetQualifiedNameReference.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetQualifiedNameReference.java,v retrieving revision 1.57 diff -u -r1.57 CodeSnippetQualifiedNameReference.java --- eval/org/eclipse/jdt/internal/eval/CodeSnippetQualifiedNameReference.java 17 Sep 2008 09:08:39 -0000 1.57 +++ eval/org/eclipse/jdt/internal/eval/CodeSnippetQualifiedNameReference.java 24 Sep 2008 12:36:52 -0000 @@ -15,25 +15,19 @@ import org.eclipse.jdt.internal.compiler.ast.Expression; import org.eclipse.jdt.internal.compiler.ast.IntLiteral; import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference; -import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.codegen.CodeStream; import org.eclipse.jdt.internal.compiler.codegen.Opcodes; -import org.eclipse.jdt.internal.compiler.flow.FlowInfo; -import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.Binding; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.ClassScope; import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; -import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; import org.eclipse.jdt.internal.compiler.lookup.ProblemBinding; import org.eclipse.jdt.internal.compiler.lookup.ProblemFieldBinding; import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.Scope; -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.jdt.internal.compiler.lookup.VariableBinding; public class CodeSnippetQualifiedNameReference extends QualifiedNameReference implements EvaluationConstants, ProblemReasons { @@ -53,12 +47,12 @@ /** * Check and/or redirect the field access to the delegate receiver if any */ -public TypeBinding checkFieldAccess(BlockScope scope) { - // check for forward references - this.bits &= ~RestrictiveFlagMASK; // clear bits - this.bits |= Binding.FIELD; - return getOtherFieldBindings(scope); -} +//public TypeBinding checkFieldAccess(BlockScope scope) { +// // check for forward references +// this.bits &= ~RestrictiveFlagMASK; // clear bits +// this.bits |= Binding.FIELD; +// return getOtherFieldBindings(scope); +//} public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) { FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream); @@ -83,334 +77,102 @@ codeStream.generateImplicitConversion(assignment.implicitConversion); } } -public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { - int pc = codeStream.position; - if (this.constant != Constant.NotAConstant) { - if (valueRequired) { - codeStream.generateConstant(this.constant, this.implicitConversion); - } - } else { - FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream); - if (valueRequired) { - if (lastFieldBinding.declaringClass == null) { // array length - codeStream.arraylength(); - codeStream.generateImplicitConversion(this.implicitConversion); - } else { - Constant fieldConstant = lastFieldBinding.constant(); - if (fieldConstant != Constant.NotAConstant) { - if (!lastFieldBinding.isStatic()){ - codeStream.invokeObjectGetClass(); - codeStream.pop(); - } - // inline the last field constant - codeStream.generateConstant(fieldConstant, this.implicitConversion); - } else { - if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) { - if (lastFieldBinding.isStatic()) { - codeStream.getstatic(lastFieldBinding); - } else { - codeStream.getfield(lastFieldBinding); - } - } else { - codeStream.generateEmulatedReadAccessForField(lastFieldBinding); - } - codeStream.generateImplicitConversion(this.implicitConversion); - } - } - } else { - if (lastFieldBinding != null && !lastFieldBinding.isStatic()){ - codeStream.invokeObjectGetClass(); // perform null check - codeStream.pop(); - } - } - } - codeStream.recordPositionsFrom(pc, this.sourceStart); -} -public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) { +public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) { FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream); if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) { - if (lastFieldBinding.isStatic()){ - codeStream.getstatic(lastFieldBinding); - } else { - codeStream.dup(); - codeStream.getfield(lastFieldBinding); - } - // the last field access is a write access - // perform the actual compound operation - int operationTypeID; - switch(operationTypeID = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) { - case T_JavaLangString : - case T_JavaLangObject : - case T_undefined : - codeStream.generateStringConcatenationAppend(currentScope, null, expression); - break; - default : - // promote the array reference to the suitable operation type - codeStream.generateImplicitConversion(this.implicitConversion); - // generate the increment value (will by itself be promoted to the operation value) - if (expression == IntLiteral.One){ // prefix operation - codeStream.generateConstant(expression.constant, this.implicitConversion); - } else { - expression.generateCode(currentScope, codeStream, true); - } - // perform the operation - codeStream.sendOperator(operator, operationTypeID); - // cast the value back to the array reference type - codeStream.generateImplicitConversion(assignmentImplicitConversion); - } - // actual assignment - fieldStore(codeStream, lastFieldBinding, null, valueRequired); + super.generateCompoundAssignment(currentScope, codeStream, expression, operator, assignmentImplicitConversion, valueRequired); + return; + } + codeStream.generateEmulationForField(lastFieldBinding); + codeStream.swap(); + if (lastFieldBinding.isStatic()){ + codeStream.aconst_null(); + codeStream.swap(); } else { - if (lastFieldBinding.isStatic()){ - codeStream.generateEmulationForField(lastFieldBinding); - codeStream.swap(); - codeStream.aconst_null(); - codeStream.swap(); - - codeStream.generateEmulatedReadAccessForField(lastFieldBinding); - } else { - codeStream.generateEmulationForField(lastFieldBinding); - codeStream.swap(); - codeStream.dup(); - - codeStream.generateEmulatedReadAccessForField(lastFieldBinding); - } - // the last field access is a write access - // perform the actual compound operation - int operationTypeID; - if ((operationTypeID = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) == T_JavaLangString) { - codeStream.generateStringConcatenationAppend(currentScope, null, expression); + codeStream.dup(); + } + codeStream.generateEmulatedReadAccessForField(lastFieldBinding); + // the last field access is a write access + // perform the actual compound operation + int operationTypeID; + if ((operationTypeID = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) == T_JavaLangString) { + codeStream.generateStringConcatenationAppend(currentScope, null, expression); + } else { + // promote the array reference to the suitable operation type + codeStream.generateImplicitConversion(this.implicitConversion); + // generate the increment value (will by itself be promoted to the operation value) + if (expression == IntLiteral.One){ // prefix operation + codeStream.generateConstant(expression.constant, this.implicitConversion); } else { - // promote the array reference to the suitable operation type - codeStream.generateImplicitConversion(this.implicitConversion); - // generate the increment value (will by itself be promoted to the operation value) - if (expression == IntLiteral.One){ // prefix operation - codeStream.generateConstant(expression.constant, this.implicitConversion); - } else { - expression.generateCode(currentScope, codeStream, true); - } - // perform the operation - codeStream.sendOperator(operator, operationTypeID); - // cast the value back to the array reference type - codeStream.generateImplicitConversion(assignmentImplicitConversion); + expression.generateCode(currentScope, codeStream, true); } - // actual assignment + // perform the operation + codeStream.sendOperator(operator, operationTypeID); + // cast the value back to the array reference type + codeStream.generateImplicitConversion(assignmentImplicitConversion); + } + // actual assignment - // current stack is: - // field receiver value - if (valueRequired) { - if ((lastFieldBinding.type == TypeBinding.LONG) || (lastFieldBinding.type == TypeBinding.DOUBLE)) { - codeStream.dup2_x2(); - } else { - codeStream.dup_x2(); - } + // current stack is: + // field receiver value + if (valueRequired) { + if ((lastFieldBinding.type == TypeBinding.LONG) || (lastFieldBinding.type == TypeBinding.DOUBLE)) { + codeStream.dup2_x2(); + } else { + codeStream.dup_x2(); } - // current stack is: - // value field receiver value - codeStream.generateEmulatedWriteAccessForField(lastFieldBinding); } + // current stack is: + // value field receiver value + codeStream.generateEmulatedWriteAccessForField(lastFieldBinding); } public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) { - FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream); if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) { - SyntheticMethodBinding accessor = - this.syntheticReadAccessors == null - ? null - : this.syntheticReadAccessors[this.syntheticReadAccessors.length - 1]; - if (lastFieldBinding.isStatic()) { - if (accessor == null) { - codeStream.getstatic(lastFieldBinding); - } else { - codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */); - } + super.generatePostIncrement(currentScope, codeStream, postIncrement, valueRequired); + return; + } + codeStream.generateEmulatedReadAccessForField(lastFieldBinding); + if (valueRequired) { + if ((lastFieldBinding.type == TypeBinding.LONG) || (lastFieldBinding.type == TypeBinding.DOUBLE)) { + codeStream.dup2(); } else { codeStream.dup(); - if (accessor == null) { - codeStream.getfield(lastFieldBinding); - } else { - codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */); - } } - - TypeBinding requiredGenericCast = getGenericCast(this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length); - if (requiredGenericCast != null) codeStream.checkcast(requiredGenericCast); - codeStream.generateImplicitConversion(this.implicitConversion); - - // duplicate the old field value - int operandType = this.implicitConversion & TypeIds.COMPILE_TYPE_MASK; - if (valueRequired) { - if (lastFieldBinding.isStatic()) { - if (operandType == T_long || operandType == T_double) { - codeStream.dup2(); - } else { - codeStream.dup(); - } - } else { // Stack: [owner][old field value] ---> [old field value][owner][old field value] - if (operandType == T_long || operandType == T_double) { - codeStream.dup2_x1(); - } else { - codeStream.dup_x1(); - } - } + } + codeStream.generateEmulationForField(lastFieldBinding); + if ((lastFieldBinding.type == TypeBinding.LONG) || (lastFieldBinding.type == TypeBinding.DOUBLE)) { + codeStream.dup_x2(); + codeStream.pop(); + if (lastFieldBinding.isStatic()) { + codeStream.aconst_null(); + } else { + generateReadSequence(currentScope, codeStream); } - codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion); - codeStream.sendOperator(postIncrement.operator, operandType); - codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion); - fieldStore(codeStream, lastFieldBinding, this.syntheticWriteAccessor, false); + codeStream.dup_x2(); + codeStream.pop(); } else { - codeStream.generateEmulatedReadAccessForField(lastFieldBinding); - if (valueRequired) { - if ((lastFieldBinding.type == TypeBinding.LONG) || (lastFieldBinding.type == TypeBinding.DOUBLE)) { - codeStream.dup2(); - } else { - codeStream.dup(); - } - } - codeStream.generateEmulationForField(lastFieldBinding); - if ((lastFieldBinding.type == TypeBinding.LONG) || (lastFieldBinding.type == TypeBinding.DOUBLE)) { - codeStream.dup_x2(); - codeStream.pop(); - if (lastFieldBinding.isStatic()) { - codeStream.aconst_null(); - } else { - generateReadSequence(currentScope, codeStream); - } - codeStream.dup_x2(); - codeStream.pop(); + codeStream.dup_x1(); + codeStream.pop(); + if (lastFieldBinding.isStatic()) { + codeStream.aconst_null(); } else { - codeStream.dup_x1(); - codeStream.pop(); - if (lastFieldBinding.isStatic()) { - codeStream.aconst_null(); - } else { - generateReadSequence(currentScope, codeStream); - } - codeStream.dup_x1(); - codeStream.pop(); - } - codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion); - codeStream.sendOperator(postIncrement.operator, lastFieldBinding.type.id); - codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion); - codeStream.generateEmulatedWriteAccessForField(lastFieldBinding); - } -} -/* - * Generate code for all bindings (local and fields) excluding the last one, which may then be generated code - * for a read or write access. - */ -public FieldBinding generateReadSequence(BlockScope currentScope, CodeStream codeStream) { - - // determine the rank until which we now we do not need any actual value for the field access - int otherBindingsCount = this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length; - boolean needValue = otherBindingsCount == 0 || !this.otherBindings[0].isStatic(); - FieldBinding lastFieldBinding = null; - TypeBinding lastGenericCast = null; - - switch (this.bits & RestrictiveFlagMASK) { - case Binding.FIELD : - lastFieldBinding = (FieldBinding) this.codegenBinding; - lastGenericCast = this.genericCast; - // if first field is actually constant, we can inline it - if (lastFieldBinding.constant() != Constant.NotAConstant) { - break; - } - if (needValue) { - if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) { - if (!lastFieldBinding.isStatic()) { - if ((this.bits & DepthMASK) != 0) { - ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT); - Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/); - codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope); - } else { - generateReceiver(codeStream); - } - } - } else { - if (!lastFieldBinding.isStatic()) { - if ((this.bits & DepthMASK) != 0) { - // internal error, per construction we should have found it - // not yet supported - currentScope.problemReporter().needImplementation(this); - } else { - generateReceiver(codeStream); - } - } else { - codeStream.aconst_null(); - } - } - } - break; - case Binding.LOCAL : // reading the first local variable - if (!needValue) break; // no value needed - LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding; - // regular local variable read - Constant localConstant = localBinding.constant(); - if (localConstant != Constant.NotAConstant) { - codeStream.generateConstant(localConstant, 0); - // no implicit conversion - } else { - // outer local? - if ((this.bits & DepthMASK) != 0) { - // outer local can be reached either through a synthetic arg or a synthetic field - VariableBinding[] path = currentScope.getEmulationPath(localBinding); - codeStream.generateOuterAccess(path, this, localBinding, currentScope); - } else { - codeStream.load(localBinding); - } - } - } - - // all intermediate field accesses are read accesses - // only the last field binding is a write access - if (this.otherCodegenBindings != null) { - for (int i = 0; i < otherBindingsCount; i++) { - FieldBinding nextField = this.otherCodegenBindings[i]; - TypeBinding nextGenericCast = this.otherGenericCasts == null ? null : this.otherGenericCasts[i]; - if (lastFieldBinding != null) { - needValue = !nextField.isStatic(); - if (needValue) { - if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) { - Constant fieldConstant = lastFieldBinding.constant(); - if (fieldConstant != Constant.NotAConstant) { - if (lastFieldBinding != this.codegenBinding && !lastFieldBinding.isStatic()) { - codeStream.invokeObjectGetClass(); // perform null check - codeStream.pop(); - } - codeStream.generateConstant(fieldConstant, 0); - } else if (lastFieldBinding.isStatic()) { - codeStream.getstatic(lastFieldBinding); - } else { - codeStream.getfield(lastFieldBinding); - } - } else { - codeStream.generateEmulatedReadAccessForField(lastFieldBinding); - } - if (lastGenericCast != null) codeStream.checkcast(lastGenericCast); - } else { - if (this.codegenBinding != lastFieldBinding && !lastFieldBinding.isStatic()){ - codeStream.invokeObjectGetClass(); // perform null check - codeStream.pop(); - } - } - } - lastFieldBinding = nextField; - lastGenericCast = nextGenericCast; - if (lastFieldBinding != null && !lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) { - if (lastFieldBinding.isStatic()) { - codeStream.aconst_null(); - } - } + generateReadSequence(currentScope, codeStream); } + codeStream.dup_x1(); + codeStream.pop(); } - return lastFieldBinding; + codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion); + codeStream.sendOperator(postIncrement.operator, lastFieldBinding.type.id); + codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion); + codeStream.generateEmulatedWriteAccessForField(lastFieldBinding); } public void generateReceiver(CodeStream codeStream) { codeStream.aload_0(); if (this.delegateThis != null) { - codeStream.getfield(this.delegateThis); // delegated field access + codeStream.fieldAccess0(Opcodes.OPC_getfield, this.delegateThis, null /* default declaringClass */); // delegated field access } } public TypeBinding getOtherFieldBindings(BlockScope scope) { @@ -445,7 +207,7 @@ // allocation of the fieldBindings array and its respective constants int otherBindingsLength = length - index; - this.otherCodegenBindings = this.otherBindings = new FieldBinding[otherBindingsLength]; + this.otherBindings = new FieldBinding[otherBindingsLength]; // fill the first constant (the one of the binding) this.constant =((VariableBinding) this.binding).constant(); @@ -466,6 +228,7 @@ if (this.delegateThis == null){ // if not found then internal error, field should have been found return super.reportError(scope); } + this.actualReceiverType = this.delegateThis.type; } else { this.constant = Constant.NotAConstant; //don't fill other constants slots... scope.problemReporter().invalidField(this, field, index, type); @@ -494,83 +257,22 @@ } return (this.otherBindings[otherBindingsLength - 1]).type; } - /** - * Check and/or redirect the field access to the delegate receiver if any - */ - public TypeBinding getReceiverType(BlockScope currentScope) { - Scope scope = currentScope.parent; - while (true) { - switch (scope.kind) { - case Scope.CLASS_SCOPE : - return ((ClassScope) scope).referenceContext.binding; - default: - scope = scope.parent; - } - } - } - /** - * index is <0 to denote write access emulation - */ - public void manageSyntheticAccessIfNecessary( - BlockScope currentScope, - FieldBinding fieldBinding, - TypeBinding lastReceiverType, - int index, - FlowInfo flowInfo) { - - if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0) return; - - // if the binding declaring class is not visible, need special action - // for runtime compatibility on 1.2 VMs : change the declaring class of the binding - // NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type - boolean useDelegate; - if (index < 0) { // write-access? - useDelegate = fieldBinding == this.binding && this.delegateThis != null; - } else { - useDelegate = index == 0 && this.delegateThis != null; - } - if (useDelegate) { - lastReceiverType = this.delegateThis.type; - } - // if the binding declaring class is not visible, need special action - // for runtime compatibility on 1.2 VMs : change the declaring class of the binding - // NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type - // and not from Object or implicit static field access. - if (fieldBinding.declaringClass != lastReceiverType - && !lastReceiverType.isArrayType() - && fieldBinding.declaringClass != null // array.length - && fieldBinding.constant() == Constant.NotAConstant) { - CompilerOptions options = currentScope.compilerOptions(); - if ((options.targetJDK >= ClassFileConstants.JDK1_2 - && (options.complianceLevel >= ClassFileConstants.JDK1_4 || (index < 0 ? fieldBinding != this.binding : index > 0) || this.indexOfFirstFieldBinding > 1 || !fieldBinding.isStatic()) - && fieldBinding.declaringClass.id != T_JavaLangObject) // no change for Object fields - || !(useDelegate - ? new CodeSnippetScope(currentScope).canBeSeenByForCodeSnippet(fieldBinding.declaringClass, (ReferenceBinding) this.delegateThis.type) - : fieldBinding.declaringClass.canBeSeenBy(currentScope))) { - - if (index < 0) { // write-access? - if (fieldBinding == this.binding){ - this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType.erasure()); - } else { - if (this.otherCodegenBindings == this.otherBindings){ - int l = this.otherBindings.length; - System.arraycopy(this.otherBindings, 0, this.otherCodegenBindings = new FieldBinding[l], 0, l); - } - this.otherCodegenBindings[this.otherCodegenBindings.length-1] = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType.erasure()); - } - } if (index == 0){ - this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType.erasure()); - } else { - if (this.otherCodegenBindings == this.otherBindings){ - int l = this.otherBindings.length; - System.arraycopy(this.otherBindings, 0, this.otherCodegenBindings = new FieldBinding[l], 0, l); - } - this.otherCodegenBindings[index-1] = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType.erasure()); - } +/** + * Check and/or redirect the field access to the delegate receiver if any + */ +public TypeBinding getReceiverType(BlockScope currentScope) { + Scope scope = currentScope.parent; + while (true) { + switch (scope.kind) { + case Scope.CLASS_SCOPE : + return ((ClassScope) scope).referenceContext.binding; + default: + scope = scope.parent; } - } } +} + /** * Normal field binding did not work, try to bind to a field of the delegate receiver. */ @@ -593,7 +295,7 @@ if (((ProblemFieldBinding) fieldBinding).problemId() == NotVisible) { // manage the access to a private field of the enclosing type CodeSnippetScope localScope = new CodeSnippetScope(scope); - this.codegenBinding = this.binding = localScope.getFieldForCodeSnippet(this.delegateThis.type, this.tokens[0], this); + this.binding = localScope.getFieldForCodeSnippet(this.delegateThis.type, this.tokens[0], this); if (this.binding.isValidBinding()) { return checkFieldAccess(scope); } else { @@ -603,7 +305,7 @@ return super.reportError(scope); } } - this.codegenBinding = this.binding = fieldBinding; + this.binding = fieldBinding; return checkFieldAccess(scope); } @@ -628,7 +330,7 @@ // the TC is Flag_Type Flag_LocalField and Flag_TypeLocalField CodeSnippetScope localScope = new CodeSnippetScope(scope); - if ((this.codegenBinding = this.binding = localScope.getBinding(this.tokens, this.bits & RestrictiveFlagMASK, this, (ReferenceBinding) this.delegateThis.type)).isValidBinding()) { + if ((this.binding = localScope.getBinding(this.tokens, this.bits & RestrictiveFlagMASK, this, (ReferenceBinding) this.delegateThis.type)).isValidBinding()) { this.bits &= ~RestrictiveFlagMASK; // clear bits this.bits |= Binding.FIELD; return getOtherFieldBindings(scope); Index: codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMemberAccess.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMemberAccess.java,v retrieving revision 1.26 diff -u -r1.26 CompletionOnMemberAccess.java --- codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMemberAccess.java 27 Jun 2008 16:03:59 -0000 1.26 +++ codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMemberAccess.java 24 Sep 2008 12:36:50 -0000 @@ -53,9 +53,9 @@ public TypeBinding resolveType(BlockScope scope) { - this.receiverType = this.receiver.resolveType(scope); + this.actualReceiverType = this.receiver.resolveType(scope); - if ((this.receiverType == null || !this.receiverType.isValidBinding()) && this.receiver instanceof MessageSend) { + if ((this.actualReceiverType == null || !this.actualReceiverType.isValidBinding()) && this.receiver instanceof MessageSend) { MessageSend messageSend = (MessageSend) this.receiver; if(messageSend.receiver instanceof ThisReference) { Expression[] arguments = messageSend.arguments; @@ -73,10 +73,10 @@ } } - if (this.receiverType == null || this.receiverType.isBaseType() || !this.receiverType.isValidBinding()) + if (this.actualReceiverType == null || this.actualReceiverType.isBaseType() || !this.actualReceiverType.isValidBinding()) throw new CompletionNodeFound(); else - throw new CompletionNodeFound(this, this.receiverType, scope); + throw new CompletionNodeFound(this, this.actualReceiverType, scope); // array types are passed along to find the length field } } Index: codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnJavadocFieldReference.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnJavadocFieldReference.java,v retrieving revision 1.5 diff -u -r1.5 CompletionOnJavadocFieldReference.java --- codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnJavadocFieldReference.java 27 Jun 2008 16:03:59 -0000 1.5 +++ codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnJavadocFieldReference.java 24 Sep 2008 12:36:50 -0000 @@ -93,11 +93,11 @@ // Resolve only receiver if (this.receiver == null) { - this.receiverType = scope.enclosingSourceType(); + this.actualReceiverType = scope.enclosingSourceType(); } else if (scope.kind == Scope.CLASS_SCOPE) { - this.receiverType = this.receiver.resolveType((ClassScope) scope); + this.actualReceiverType = this.receiver.resolveType((ClassScope) scope); } else { - this.receiverType = this.receiver.resolveType((BlockScope)scope); + this.actualReceiverType = this.receiver.resolveType((BlockScope)scope); } return null; } Index: codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java,v retrieving revision 1.376 diff -u -r1.376 CompletionEngine.java --- codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java 18 Sep 2008 14:06:39 -0000 1.376 +++ codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java 24 Sep 2008 12:36:50 -0000 @@ -1927,8 +1927,8 @@ long completionPosition = fieldRef.nameSourcePosition; this.javadocTagPosition = fieldRef.tagSourceStart; - if (fieldRef.receiverType != null && fieldRef.receiverType.isValidBinding()) { - ReferenceBinding receiverType = (ReferenceBinding) fieldRef.receiverType; + if (fieldRef.actualReceiverType != null && fieldRef.actualReceiverType.isValidBinding()) { + ReferenceBinding receiverType = (ReferenceBinding) fieldRef.actualReceiverType; int rangeStart = (int) (completionPosition >>> 32); if (fieldRef.receiver.isThis()) { if (fieldRef.completeInText()) { @@ -1984,8 +1984,8 @@ null, -1, -1); - if (fieldRef.receiverType instanceof ReferenceBinding) { - ReferenceBinding refBinding = (ReferenceBinding)fieldRef.receiverType; + if (fieldRef.actualReceiverType instanceof ReferenceBinding) { + ReferenceBinding refBinding = (ReferenceBinding)fieldRef.actualReceiverType; if (this.completionToken == null || CharOperation.prefixEquals(this.completionToken, refBinding.sourceName) || (this.options.camelCaseMatch && CharOperation.camelCaseMatch(this.completionToken, refBinding.sourceName))) {