Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 113530 Details for
Bug 247612
[compiler] Compiler could avoid allocating field bindings for receiver type change
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
[patch]
Better patch
247612.txt (text/plain), 204.61 KB, created by
Philipe Mulet
on 2008-09-25 17:22:05 EDT
(
hide
)
Description:
Better patch
Filename:
MIME Type:
Creator:
Philipe Mulet
Created:
2008-09-25 17:22:05 EDT
Size:
204.61 KB
patch
obsolete
>### 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 25 Sep 2008 21:20:22 -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 25 Sep 2008 21:20:12 -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.fieldAccess(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.fieldAccess(Opcodes.OPC_getstatic, fieldDecl.binding, null /* default declaringClass */); > codeStream.aastore(); > } > } > } > } >- codeStream.putstatic(declaringType.enumValuesSyntheticfield); >+ codeStream.fieldAccess(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/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 25 Sep 2008 21:20:24 -0000 >@@ -10,9 +10,16 @@ > *******************************************************************************/ > 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.Scope; >+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; >+import org.eclipse.jdt.internal.compiler.lookup.TypeIds; > > public abstract class Reference extends Expression { > /** >@@ -26,42 +33,55 @@ > 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) { >+ >+public void fieldStore(Scope currentScope, CodeStream codeStream, FieldBinding fieldBinding, MethodBinding syntheticWriteAccessor, TypeBinding receiverType, boolean isImplicitThisReceiver, 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); >+ TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, fieldBinding, receiverType, isImplicitThisReceiver); >+ codeStream.fieldAccess(Opcodes.OPC_putstatic, fieldBinding, constantPoolDeclaringClass); > } 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); >+ TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, fieldBinding, receiverType, isImplicitThisReceiver); >+ codeStream.fieldAccess(Opcodes.OPC_putfield, fieldBinding, constantPoolDeclaringClass); > } 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/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 25 Sep 2008 21:20:26 -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(currentScope, codeStream, codegenBinding, this.syntheticAccessors == null ? null : this.syntheticAccessors[SingleNameReference.WRITE], this.actualReceiverType, true /*implicit this*/, 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 { >@@ -314,11 +314,15 @@ > if (valueRequired) { > codeStream.generateImplicitConversion(assignment.implicitConversion); // implicit conversion > } else { >- if ((localBinding.type == TypeBinding.LONG) || (localBinding.type == TypeBinding.DOUBLE)) { >- codeStream.pop2(); >- } else { >- codeStream.pop(); >- } >+ switch(localBinding.type.id) { >+ case TypeIds.T_long : >+ case TypeIds.T_double : >+ codeStream.pop2(); >+ break; >+ default : >+ codeStream.pop(); >+ break; >+ } > } > } > return; >@@ -354,8 +358,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 +368,7 @@ > codeStream.recordPositionsFrom(pc, this.sourceStart); > return; > } >- if (fieldBinding.isStatic()) { >+ if (codegenField.isStatic()) { > if (!valueRequired > // if no valueRequired, still need possible side-effects of <clinit> invocation, if field belongs to different class > && ((FieldBinding)this.binding).original().declaringClass == this.actualReceiverType.erasure() >@@ -376,7 +380,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.fieldAccess(Opcodes.OPC_getstatic, codegenField, constantPoolDeclaringClass); > } else { > codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */); > } >@@ -398,14 +403,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.fieldAccess(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 +476,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.fieldAccess(Opcodes.OPC_getstatic, codegenField, constantPoolDeclaringClass); > } else { > codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */); > } >@@ -487,14 +494,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.fieldAccess(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 +572,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(currentScope, codeStream, codegenField, writeAccessor, this.actualReceiverType, true /* implicit this*/, 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 +596,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.fieldAccess(Opcodes.OPC_getstatic, codegenField, constantPoolDeclaringClass); > } else { > codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */); > } >@@ -600,7 +614,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.fieldAccess(Opcodes.OPC_getfield, codegenField, constantPoolDeclaringClass); > } else { > codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */); > } >@@ -610,20 +625,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 +654,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(currentScope, codeStream, codegenField, this.syntheticAccessors == null ? null : this.syntheticAccessors[SingleNameReference.WRITE], this.actualReceiverType, true /*implicit this*/, 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 +672,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 +737,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 +749,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 +838,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/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 25 Sep 2008 21:20:20 -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/ArrayReference.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java,v >retrieving revision 1.50 >diff -u -r1.50 ArrayReference.java >--- compiler/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java 27 Jun 2008 16:03:54 -0000 1.50 >+++ compiler/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java 25 Sep 2008 21:20:10 -0000 >@@ -140,11 +140,14 @@ > codeStream.dup2(); > codeStream.arrayAt(this.resolvedType.id); > if (valueRequired) { >- if ((this.resolvedType == TypeBinding.LONG) >- || (this.resolvedType == TypeBinding.DOUBLE)) { >- codeStream.dup2_x2(); >- } else { >- codeStream.dup_x2(); >+ switch(this.resolvedType.id) { >+ case TypeIds.T_long : >+ case TypeIds.T_double : >+ codeStream.dup2_x2(); >+ break; >+ default : >+ codeStream.dup_x2(); >+ break; > } > } > codeStream.generateImplicitConversion(this.implicitConversion); >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 25 Sep 2008 21:20:20 -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/ConstructorDeclaration.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java,v >retrieving revision 1.96 >diff -u -r1.96 ConstructorDeclaration.java >--- compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java 24 Sep 2008 16:05:23 -0000 1.96 >+++ compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java 25 Sep 2008 21:20:13 -0000 >@@ -228,7 +228,7 @@ > if ((syntheticArg = syntheticArgs[i]).matchingField != null) { > codeStream.aload_0(); > codeStream.load(syntheticArg); >- codeStream.putfield(syntheticArg.matchingField); >+ codeStream.fieldAccess(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.fieldAccess(Opcodes.OPC_putfield, syntheticArg.matchingField, null /* default declaringClass */); > } > } > } >@@ -277,11 +277,14 @@ > LocalVariableBinding argBinding; > codeStream.addVisibleLocalVariable(argBinding = this.arguments[i].binding); > argBinding.recordInitializationStartPC(0); >- TypeBinding argType; >- if ((argType = argBinding.type) == TypeBinding.LONG || (argType == TypeBinding.DOUBLE)) { >- argSlotSize += 2; >- } else { >- argSlotSize++; >+ switch(argBinding.type.id) { >+ case TypeIds.T_long : >+ case TypeIds.T_double : >+ argSlotSize += 2; >+ break; >+ default : >+ argSlotSize++; >+ break; > } > } > } >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 25 Sep 2008 21:20:12 -0000 >@@ -101,7 +101,7 @@ > > if (this.assertionSyntheticFieldBinding != null) { > BranchLabel assertionActivationLabel = new BranchLabel(codeStream); >- codeStream.getstatic(this.assertionSyntheticFieldBinding); >+ codeStream.fieldAccess(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 25 Sep 2008 21:20:18 -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,17 +160,11 @@ > > public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) { > int pc = codeStream.position; >- this.receiver.generateCode( >- currentScope, >- codeStream, >- !this.codegenBinding.isStatic()); >+ FieldBinding codegenBinding = this.binding.original(); >+ this.receiver.generateCode(currentScope, codeStream, !codegenBinding.isStatic()); > codeStream.recordPositionsFrom(pc, this.sourceStart); > assignment.expression.generateCode(currentScope, codeStream, true); >- fieldStore( >- codeStream, >- this.codegenBinding, >- this.syntheticAccessors == null ? null : this.syntheticAccessors[FieldReference.WRITE], >- valueRequired); >+ fieldStore(currentScope, codeStream, codegenBinding, this.syntheticAccessors == null ? null : this.syntheticAccessors[FieldReference.WRITE], this.actualReceiverType, this.receiver.isImplicitThis(), valueRequired); > if (valueRequired) { > codeStream.generateImplicitConversion(assignment.implicitConversion); > } >@@ -195,9 +187,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 +211,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 +221,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.fieldAccess(Opcodes.OPC_getstatic, codegenBinding, constantPoolDeclaringClass); > } else { >- codeStream.getfield(this.codegenBinding); >+ codeStream.fieldAccess(Opcodes.OPC_getfield, codegenBinding, constantPoolDeclaringClass); > } > } else { > codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[FieldReference.READ], null /* default declaringClass */); >@@ -244,7 +238,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 +252,15 @@ > if (isThisReceiver) { > if (isStatic){ > // if no valueRequired, still need possible side-effects of <clinit> 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.fieldAccess(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 +283,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.fieldAccess(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.fieldAccess(Opcodes.OPC_getfield, codegenBinding, constantPoolDeclaringClass); > } else { > codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[FieldReference.READ], null /* default declaringClass */); > } >@@ -329,30 +324,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(currentScope, codeStream, codegenBinding, this.syntheticAccessors == null ? null : this.syntheticAccessors[FieldReference.WRITE], this.actualReceiverType, this.receiver.isImplicitThis(), 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.fieldAccess(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.fieldAccess(Opcodes.OPC_getfield, codegenBinding, constantPoolDeclaringClass); > } else { > codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[FieldReference.READ], null /* default declaringClass */); > } >@@ -362,23 +353,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 +385,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(currentScope, codeStream, codegenBinding, this.syntheticAccessors == null ? null : this.syntheticAccessors[FieldReference.WRITE], this.actualReceiverType, this.receiver.isImplicitThis(), false); > } > > /** >@@ -412,16 +409,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 +430,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 +446,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 +523,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 +566,7 @@ > } > ReferenceBinding declaringClass = this.binding.declaringClass; > if (!isImplicitThisRcv >- && declaringClass != this.receiverType >+ && declaringClass != this.actualReceiverType > && declaringClass.canBeSeenBy(scope)) { > scope.problemReporter().indirectAccessToStaticField(this, fieldBinding); > } >@@ -620,7 +597,7 @@ > } > > public void setActualReceiverType(ReferenceBinding receiverType) { >- // ignored >+ this.actualReceiverType = receiverType; > } > > public void setDepth(int depth) { >Index: compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java,v >retrieving revision 1.100 >diff -u -r1.100 AbstractMethodDeclaration.java >--- compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java 7 Jul 2008 17:08:07 -0000 1.100 >+++ compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java 25 Sep 2008 21:20:10 -0000 >@@ -253,11 +253,14 @@ > TypeBinding[] parameters = this.binding.parameters; > int size = 1; // an abstact method or a native method cannot be static > for (int i = 0, max = parameters.length; i < max; i++) { >- TypeBinding parameter = parameters[i]; >- if (parameter == TypeBinding.LONG || parameter == TypeBinding.DOUBLE) { >- size += 2; >- } else { >- size++; >+ switch(parameters[i].id) { >+ case TypeIds.T_long : >+ case TypeIds.T_double : >+ size += 2; >+ break; >+ default : >+ size++; >+ break; > } > if (size > 0xFF) { > this.scope.problemReporter().noMoreAvailableSpaceForArgument(this.scope.locals[i], this.scope.locals[i].declaration); >Index: compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java,v >retrieving revision 1.89 >diff -u -r1.89 ConditionalExpression.java >--- compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java 27 Jun 2008 16:03:55 -0000 1.89 >+++ compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java 25 Sep 2008 21:20:13 -0000 >@@ -152,7 +152,15 @@ > codeStream.updateLastRecordedEndPC(currentScope, position); > // Tune codestream stack size > if (valueRequired) { >- codeStream.decrStackSize(this.resolvedType == TypeBinding.LONG || this.resolvedType == TypeBinding.DOUBLE ? 2 : 1); >+ switch(this.resolvedType.id) { >+ case TypeIds.T_long : >+ case TypeIds.T_double : >+ codeStream.decrStackSize(2); >+ break; >+ default : >+ codeStream.decrStackSize(1); >+ break; >+ } > } > } > } >Index: compiler/org/eclipse/jdt/internal/compiler/ast/SynchronizedStatement.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SynchronizedStatement.java,v >retrieving revision 1.50 >diff -u -r1.50 SynchronizedStatement.java >--- compiler/org/eclipse/jdt/internal/compiler/ast/SynchronizedStatement.java 27 Jun 2008 16:03:55 -0000 1.50 >+++ compiler/org/eclipse/jdt/internal/compiler/ast/SynchronizedStatement.java 25 Sep 2008 21:20:28 -0000 >@@ -94,12 +94,15 @@ > // generate the synchronization expression > this.expression.generateCode(this.scope, codeStream, true); > if (this.block.isEmptyBlock()) { >- if ((this.synchroVariable.type == TypeBinding.LONG) >- || (this.synchroVariable.type == TypeBinding.DOUBLE)) { >- codeStream.dup2(); >- } else { >- codeStream.dup(); >- } >+ switch(this.synchroVariable.type.id) { >+ case TypeIds.T_long : >+ case TypeIds.T_double : >+ codeStream.dup2(); >+ break; >+ default : >+ codeStream.dup(); >+ break; >+ } > // only take the lock > codeStream.monitorenter(); > codeStream.monitorexit(); >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 25 Sep 2008 21:20:22 -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/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 25 Sep 2008 21:20:24 -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); > } > } > } >@@ -346,7 +295,7 @@ > FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream); > codeStream.recordPositionsFrom(pc , this.sourceStart); > assignment.expression.generateCode(currentScope, codeStream, true); >- fieldStore(codeStream, lastFieldBinding, this.syntheticWriteAccessor, valueRequired); >+ fieldStore(currentScope, codeStream, lastFieldBinding, this.syntheticWriteAccessor, getFinalReceiverType(), false /*implicit this*/, valueRequired); > // equivalent to valuesRequired[maxOtherBindings] > if (valueRequired) { > codeStream.generateImplicitConversion(assignment.implicitConversion); >@@ -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.fieldAccess(Opcodes.OPC_getstatic, lastFieldBinding, constantPoolDeclaringClass); > } else { >- codeStream.getfield(lastFieldBinding); >+ codeStream.fieldAccess(Opcodes.OPC_getfield, lastFieldBinding, constantPoolDeclaringClass); > } > } else { > codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */); >@@ -418,6 +365,7 @@ > break; > default : > codeStream.pop(); >+ break; > } > } > } >@@ -436,29 +384,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.fieldAccess(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.fieldAccess(Opcodes.OPC_getfield, lastFieldBinding, constantPoolDeclaringClass); > } else { > codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */); > } >@@ -473,7 +415,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); >@@ -489,30 +431,34 @@ > codeStream.generateImplicitConversion(assignmentImplicitConversion); > } > // actual assignment >- fieldStore(codeStream, lastFieldBinding, this.syntheticWriteAccessor, valueRequired); >+ fieldStore(currentScope, codeStream, lastFieldBinding, this.syntheticWriteAccessor, getFinalReceiverType(), false /*implicit this*/, valueRequired); > // equivalent to valuesRequired[maxOtherBindings] > } > > 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.fieldAccess(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.fieldAccess(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 +469,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); >@@ -545,7 +497,7 @@ > codeStream.sendOperator(postIncrement.operator, this.implicitConversion & TypeIds.COMPILE_TYPE_MASK); > codeStream.generateImplicitConversion( > postIncrement.preAssignImplicitConversion); >- fieldStore(codeStream, lastFieldBinding, this.syntheticWriteAccessor, false); >+ fieldStore(currentScope, codeStream, lastFieldBinding, this.syntheticWriteAccessor, getFinalReceiverType(), false /*implicit this*/, false); > } > > /* >@@ -554,16 +506,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 +535,11 @@ > } > break; > case Binding.LOCAL : // reading the first local variable >+ lastFieldBinding = null; >+ lastGenericCast = null; >+ LocalVariableBinding localBinding = (LocalVariableBinding) this.binding; >+ lastReceiverType = localBinding.type; > if (!needValue) break; // no value needed >- LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding; > // regular local variable read > Constant localConstant = localBinding.constant(); > if (localConstant != Constant.NotAConstant) { >@@ -598,15 +555,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,24 +584,31 @@ > 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.fieldAccess(Opcodes.OPC_getstatic, lastFieldBinding, constantPoolDeclaringClass); > } else { >- codeStream.getfield(lastFieldBinding); >+ codeStream.fieldAccess(Opcodes.OPC_getfield, lastFieldBinding, constantPoolDeclaringClass); > } > } else { > codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */); > } >- if (lastGenericCast != null) codeStream.checkcast(lastGenericCast); >+ if (lastGenericCast != null) { >+ codeStream.checkcast(lastGenericCast); >+ lastReceiverType = lastGenericCast; >+ } else { >+ lastReceiverType = lastFieldBinding.type; >+ } > if (!needValue) codeStream.pop(); > } else { >- if (this.codegenBinding == lastFieldBinding) { >+ if (lastFieldBinding == initialFieldBinding) { > if (lastFieldBinding.isStatic()){ > // if no valueRequired, still need possible side-effects of <clinit> 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.fieldAccess(Opcodes.OPC_getstatic, lastFieldBinding, constantPoolDeclaringClass); > } else { > codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */); > } >@@ -651,6 +619,7 @@ > codeStream.invokeObjectGetClass(); // perform null check > codeStream.pop(); > } >+ lastReceiverType = lastFieldBinding.type; > } > if ((positionsLength - otherBindingsCount + i - 1) >= 0) { > int fieldPosition = (int) (this.sourcePositions[positionsLength - otherBindingsCount + i - 1] >>>32); >@@ -676,15 +645,31 @@ > 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 this.genericCast != null ? this.genericCast : ((VariableBinding)this.binding).type; >+ default: >+ TypeBinding previousGenericCast = this.otherGenericCasts == null ? null : this.otherGenericCasts[otherBindingsCount-2]; >+ return previousGenericCast != null ? previousGenericCast : this.otherBindings[otherBindingsCount-2].type; >+ } >+} >+ > // get the matching generic cast > protected TypeBinding getGenericCast(int index) { > if (index == 0){ >@@ -694,7 +679,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 +714,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]; > this.otherDepths = new int[otherBindingsLength]; > > // fill the first constant (the one of the binding) >@@ -825,24 +809,18 @@ > /** > * 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()) { >- setSyntheticAccessor(fieldBinding, index, >- ((SourceTypeBinding) someCodegenBinding.declaringClass).addSyntheticMethod(someCodegenBinding, index >= 0 /*read-access?*/)); >- currentScope.problemReporter().needToEmulateFieldAccess(someCodegenBinding, this, index >= 0 /*read-access?*/); >+ FieldBinding codegenField = getCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index); >+ ReferenceBinding declaringClass = codegenField.declaringClass; >+ if (declaringClass != currentScope.enclosingSourceType()) { >+ setSyntheticAccessor(fieldBinding, index, ((SourceTypeBinding) declaringClass).addSyntheticMethod(codegenField, index >= 0 /*read-access?*/)); >+ currentScope.problemReporter().needToEmulateFieldAccess(codegenField, this, index >= 0 /*read-access?*/); > return; > } > } else if (fieldBinding.isProtected()){ >@@ -852,34 +830,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 +865,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 +930,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 +1013,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 25 Sep 2008 21:20:15 -0000 >@@ -104,9 +104,9 @@ > this.initialization.generateCode(currentScope, codeStream, true); > // store into field > if (isStatic) { >- codeStream.putstatic(this.binding); >+ codeStream.fieldAccess(Opcodes.OPC_putstatic, this.binding, null /* default declaringClass */); > } else { >- codeStream.putfield(this.binding); >+ codeStream.fieldAccess(Opcodes.OPC_putfield, this.binding, null /* default declaringClass */); > } > } > codeStream.recordPositionsFrom(pc, this.sourceStart); >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.167 >diff -u -r1.167 CodeStream.java >--- compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java 24 Sep 2008 16:05:22 -0000 1.167 >+++ compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java 25 Sep 2008 21:20:40 -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 fieldAccess(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); >+ fieldAccess(Opcodes.OPC_getstatic, syntheticFieldBinding, null /* default declaringClass */); > dup(); > ifnonnull(endLabel); > pop(); >@@ -1684,7 +1744,7 @@ > > if (syntheticFieldBinding != null) { // non interface case > dup(); >- putstatic(syntheticFieldBinding); >+ fieldAccess(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); >+ fieldAccess(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); >+ fieldAccess(Opcodes.OPC_getfield, fieldBinding, null /* default declaringClass */); > } else { > invoke(Opcodes.OPC_invokestatic, (MethodBinding) mappingSequence[i], null /* default declaringClass */); > } >@@ -2348,18 +2357,29 @@ > for (int i = 0; i < (syntheticArguments == null ? 0 : syntheticArguments.length); i++) { > TypeBinding type; > load((type = syntheticArguments[i].type), resolvedPosition); >- if ((type == TypeBinding.DOUBLE) || (type == TypeBinding.LONG)) >- resolvedPosition += 2; >- else >- resolvedPosition++; >+ switch(type.id) { >+ case TypeIds.T_long : >+ case TypeIds.T_double : >+ resolvedPosition += 2; >+ break; >+ default : >+ resolvedPosition++; >+ break; >+ } > } > } > for (int i = 0; i < length; i++) { >- load(parameters[i], resolvedPosition); >- if ((parameters[i] == TypeBinding.DOUBLE) || (parameters[i] == TypeBinding.LONG)) >- resolvedPosition += 2; >- else >- resolvedPosition++; >+ TypeBinding parameter; >+ load(parameter = parameters[i], resolvedPosition); >+ switch(parameter.id) { >+ case TypeIds.T_long : >+ case TypeIds.T_double : >+ resolvedPosition += 2; >+ break; >+ default : >+ resolvedPosition++; >+ break; >+ } > } > > if (declaringClass.isNestedType()) { >@@ -2367,11 +2387,16 @@ > SyntheticArgumentBinding[] syntheticArguments = nestedType.syntheticOuterLocalVariables(); > for (int i = 0; i < (syntheticArguments == null ? 0 : syntheticArguments.length); i++) { > TypeBinding type; >- load((type = syntheticArguments[i].type), resolvedPosition); >- if ((type == TypeBinding.DOUBLE) || (type == TypeBinding.LONG)) >- resolvedPosition += 2; >- else >- resolvedPosition++; >+ load(type = syntheticArguments[i].type, resolvedPosition); >+ switch(type.id) { >+ case TypeIds.T_long : >+ case TypeIds.T_double : >+ resolvedPosition += 2; >+ break; >+ default : >+ resolvedPosition++; >+ break; >+ } > } > } > invoke(Opcodes.OPC_invokespecial, constructorBinding, null /* default declaringClass */); >@@ -2400,11 +2425,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); >+ fieldAccess(Opcodes.OPC_getstatic, scope.referenceContext.enumValuesSyntheticfield, null /* default declaringClass */); > dup(); > astore_0(); > iconst_0(); >@@ -2425,11 +2448,11 @@ > public void generateSyntheticBodyForFieldReadAccess(SyntheticMethodBinding accessBinding) { > initializeMaxLocals(accessBinding); > FieldBinding fieldBinding = accessBinding.targetReadField; >- if (fieldBinding.isStatic()) >- getstatic(fieldBinding); >- else { >+ if (fieldBinding.isStatic()) { >+ fieldAccess(Opcodes.OPC_getstatic, fieldBinding, null /* default declaringClass */); >+ } else { > aload_0(); >- getfield(fieldBinding); >+ fieldAccess(Opcodes.OPC_getfield, fieldBinding, null /* default declaringClass */); > } > switch (fieldBinding.type.id) { > // case T_void : >@@ -2461,11 +2484,11 @@ > FieldBinding fieldBinding = accessBinding.targetWriteField; > if (fieldBinding.isStatic()) { > load(fieldBinding.type, 0); >- putstatic(fieldBinding); >+ fieldAccess(Opcodes.OPC_putstatic, fieldBinding, null /* default declaringClass */); > } else { > aload_0(); > load(fieldBinding.type, 1); >- putfield(fieldBinding); >+ fieldAccess(Opcodes.OPC_putfield, fieldBinding, null /* default declaringClass */); > } > return_(); > } >@@ -2495,10 +2518,15 @@ > } else { > load(parameter, resolvedPosition); > } >- if ((parameter == TypeBinding.DOUBLE) || (parameter == TypeBinding.LONG)) >- resolvedPosition += 2; >- else >- resolvedPosition++; >+ switch(parameter.id) { >+ case TypeIds.T_long : >+ case TypeIds.T_double : >+ resolvedPosition += 2; >+ break; >+ default : >+ resolvedPosition++; >+ break; >+ } > } > if (targetMethod.isStatic()) > invoke(Opcodes.OPC_invokestatic, targetMethod, null /* default declaringClass */); >@@ -2551,7 +2579,7 @@ > initializeMaxLocals(methodBinding); > final BranchLabel nullLabel = new BranchLabel(this); > FieldBinding syntheticFieldBinding = methodBinding.targetReadField; >- getstatic(syntheticFieldBinding); >+ fieldAccess(Opcodes.OPC_getstatic, syntheticFieldBinding, null /* default declaringClass */); > dup(); > ifnull(nullLabel); > areturn(); >@@ -2575,7 +2603,7 @@ > final ExceptionLabel anyExceptionHandler = new ExceptionLabel(this, TypeBinding.LONG /* represents NoSuchFieldError*/); > anyExceptionHandler.placeStart(); > aload_0(); >- getstatic(fieldBinding); >+ fieldAccess(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 +2619,7 @@ > } > aload_0(); > dup(); >- putstatic(syntheticFieldBinding); >+ fieldAccess(Opcodes.OPC_putstatic, syntheticFieldBinding, null /* default declaringClass */); > areturn(); > removeVariable(localVariableBinding); > } >@@ -2868,116 +2896,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(Scope 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(Scope 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); >@@ -3726,6 +3793,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()) { >@@ -3808,35 +3904,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( >@@ -5115,7 +5182,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) { >@@ -5658,32 +5725,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 25 Sep 2008 21:20:42 -0000 >@@ -273,7 +273,7 @@ > // use in CLDC mode > BranchLabel endLabel = new BranchLabel(this); > if (syntheticFieldBinding != null) { // non interface case >- getstatic(syntheticFieldBinding); >+ fieldAccess(Opcodes.OPC_getstatic, syntheticFieldBinding, null /* default declaringClass */); > dup(); > ifnonnull(endLabel); > pop(); >@@ -316,7 +316,7 @@ > > if (syntheticFieldBinding != null) { // non interface case > dup(); >- putstatic(syntheticFieldBinding); >+ fieldAccess(Opcodes.OPC_putstatic, syntheticFieldBinding, null /* default declaringClass */); > } > int fromPC = this.position; > goto_(endLabel); >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 25 Sep 2008 21:19:38 -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 25 Sep 2008 21:19:38 -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: 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 25 Sep 2008 21:20:49 -0000 >@@ -19,19 +19,16 @@ > 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.MethodBinding; > 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; >@@ -50,274 +47,238 @@ > super(sources, positions, sourceStart, sourceEnd); > this.evaluationContext = evaluationContext; > } >-/** >- * 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 void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) { >- >- FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream); >- if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) { >- // the last field access is a write access >- assignment.expression.generateCode(currentScope, codeStream, true); >- fieldStore(codeStream, lastFieldBinding, null, valueRequired); >- } else { >- codeStream.generateEmulationForField(lastFieldBinding); >- codeStream.swap(); >- assignment.expression.generateCode(currentScope, codeStream, true); >- if (valueRequired) { >- if ((lastFieldBinding.type == TypeBinding.LONG) || (lastFieldBinding.type == TypeBinding.DOUBLE)) { >- codeStream.dup2_x2(); >- } else { >- codeStream.dup_x2(); >- } >- } >- codeStream.generateEmulatedWriteAccessForField(lastFieldBinding); >- } >- if (valueRequired) { >- 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(); >+ if ((this.bits & Binding.VARIABLE) == 0) { // nothing to do if type ref >+ codeStream.recordPositionsFrom(pc, this.sourceStart); >+ return; >+ } >+ FieldBinding lastFieldBinding = this.otherBindings == null ? (FieldBinding) this.binding : this.otherBindings[this.otherBindings.length-1]; >+ if (lastFieldBinding.canBeSeenBy(getFinalReceiverType(), this, currentScope)) { >+ super.generateCode(currentScope, codeStream, valueRequired); >+ return; >+ } >+ lastFieldBinding = generateReadSequence(currentScope, codeStream); >+ if (lastFieldBinding != null) { >+ boolean isStatic = lastFieldBinding.isStatic(); >+ Constant fieldConstant = lastFieldBinding.constant(); >+ if (fieldConstant != Constant.NotAConstant) { >+ if (!isStatic){ >+ codeStream.invokeObjectGetClass(); >+ codeStream.pop(); >+ } >+ if (valueRequired) { // inline the last field constant >+ codeStream.generateConstant(fieldConstant, this.implicitConversion); >+ } >+ } else { >+ 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.otherBindings == null ? 0 : this.otherBindings.length); >+ if (valueRequired >+ || (!isFirst && currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) >+ || ((this.implicitConversion & TypeIds.UNBOXING) != 0) >+ || requiredGenericCast != null) { >+ int lastFieldPc = codeStream.position; >+ if (lastFieldBinding.declaringClass == null) { // array length >+ codeStream.arraylength(); >+ if (valueRequired) { >+ codeStream.generateImplicitConversion(this.implicitConversion); >+ } else { >+ // could occur if !valueRequired but compliance >= 1.4 > 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); >- } >+ codeStream.generateEmulatedReadAccessForField(lastFieldBinding); >+ if (requiredGenericCast != null) codeStream.checkcast(requiredGenericCast); >+ if (valueRequired) { >+ codeStream.generateImplicitConversion(this.implicitConversion); > } else { >- codeStream.generateEmulatedReadAccessForField(lastFieldBinding); >+ boolean isUnboxing = (this.implicitConversion & TypeIds.UNBOXING) != 0; >+ // conversion only generated if unboxing >+ if (isUnboxing) codeStream.generateImplicitConversion(this.implicitConversion); >+ switch (isUnboxing ? postConversionType(currentScope).id : lastFieldBinding.type.id) { >+ case T_long : >+ case T_double : >+ codeStream.pop2(); >+ break; >+ default : >+ codeStream.pop(); >+ } > } >- codeStream.generateImplicitConversion(this.implicitConversion); > } >- } >- } else { >- if (lastFieldBinding != null && !lastFieldBinding.isStatic()){ >- codeStream.invokeObjectGetClass(); // perform null check >- codeStream.pop(); >+ >+ int fieldPosition = (int) (this.sourcePositions[this.sourcePositions.length - 1] >>> 32); >+ codeStream.recordPositionsFrom(lastFieldPc, fieldPosition); >+ } else { >+ if (!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) { >- >- 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); >+/** >+ * Check and/or redirect the field access to the delegate receiver if any >+ */ >+public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) { >+ FieldBinding lastFieldBinding = this.otherBindings == null ? (FieldBinding) this.binding : this.otherBindings[this.otherBindings.length-1]; >+ if (lastFieldBinding.canBeSeenBy(getFinalReceiverType(), this, currentScope)) { >+ super.generateAssignment(currentScope, codeStream, assignment, valueRequired); >+ return; >+ } >+ lastFieldBinding = generateReadSequence(currentScope, codeStream); >+ codeStream.generateEmulationForField(lastFieldBinding); >+ codeStream.swap(); >+ assignment.expression.generateCode(currentScope, codeStream, true); >+ if (valueRequired) { >+ switch (lastFieldBinding.type.id) { >+ case TypeIds.T_long : >+ case TypeIds.T_double : >+ codeStream.dup2_x2(); > 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); >+ codeStream.dup_x2(); >+ break; >+ } >+ } >+ codeStream.generateEmulatedWriteAccessForField(lastFieldBinding); >+ if (valueRequired) { >+ codeStream.generateImplicitConversion(assignment.implicitConversion); >+ } >+} >+ >+public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) { >+ FieldBinding lastFieldBinding = this.otherBindings == null ? (FieldBinding) this.binding : this.otherBindings[this.otherBindings.length-1]; >+ if (lastFieldBinding.canBeSeenBy(getFinalReceiverType(), this, currentScope)) { >+ super.generateCompoundAssignment(currentScope, codeStream, expression, operator, assignmentImplicitConversion, valueRequired); >+ return; >+ } >+ lastFieldBinding = generateReadSequence(currentScope, codeStream); >+ if (lastFieldBinding.isStatic()){ >+ codeStream.generateEmulationForField(lastFieldBinding); >+ codeStream.swap(); >+ codeStream.aconst_null(); >+ codeStream.swap(); >+ codeStream.generateEmulatedReadAccessForField(lastFieldBinding); > } else { >- if (lastFieldBinding.isStatic()){ >- codeStream.generateEmulationForField(lastFieldBinding); >- codeStream.swap(); >- codeStream.aconst_null(); >- codeStream.swap(); >+ codeStream.generateEmulationForField(lastFieldBinding); >+ codeStream.swap(); >+ codeStream.dup(); > >- 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.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); >- } >- // actual assignment >- >- // current stack is: >- // field receiver value >- if (valueRequired) { >- if ((lastFieldBinding.type == TypeBinding.LONG) || (lastFieldBinding.type == TypeBinding.DOUBLE)) { >+ 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 >+ >+ // current stack is: >+ // field receiver value >+ if (valueRequired) { >+ switch (lastFieldBinding.type.id) { >+ case TypeIds.T_long : >+ case TypeIds.T_double : > codeStream.dup2_x2(); >- } else { >+ break; >+ default : > codeStream.dup_x2(); >- } >+ break; > } >- // 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]; >+ FieldBinding lastFieldBinding = this.otherBindings == null ? (FieldBinding) this.binding : this.otherBindings[this.otherBindings.length-1]; >+ if (lastFieldBinding.canBeSeenBy(getFinalReceiverType(), this, currentScope)) { >+ super.generatePostIncrement(currentScope, codeStream, postIncrement, valueRequired); >+ return; >+ } >+ lastFieldBinding = generateReadSequence(currentScope, codeStream); >+ codeStream.generateEmulatedReadAccessForField(lastFieldBinding); >+ if (valueRequired) { >+ switch (lastFieldBinding.type.id) { >+ case TypeIds.T_long : >+ case TypeIds.T_double : >+ codeStream.dup2(); >+ break; >+ default : >+ codeStream.dup(); >+ break; >+ } >+ } >+ codeStream.generateEmulationForField(lastFieldBinding); >+ if ((lastFieldBinding.type == TypeBinding.LONG) || (lastFieldBinding.type == TypeBinding.DOUBLE)) { >+ codeStream.dup_x2(); >+ codeStream.pop(); > if (lastFieldBinding.isStatic()) { >- if (accessor == null) { >- codeStream.getstatic(lastFieldBinding); >- } else { >- codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */); >- } >+ codeStream.aconst_null(); > } 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(); >- } >- } >+ 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(); >+ generateReadSequence(currentScope, codeStream); > } >- codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion); >- codeStream.sendOperator(postIncrement.operator, lastFieldBinding.type.id); >- codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion); >- codeStream.generateEmulatedWriteAccessForField(lastFieldBinding); >+ 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; >+ 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 & 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; > } > if (needValue) { >- if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) { >+ if (lastFieldBinding.canBeSeenBy(this.actualReceiverType, this, currentScope)) { > if (!lastFieldBinding.isStatic()) { > if ((this.bits & DepthMASK) != 0) { > ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT); >@@ -343,8 +304,11 @@ > } > break; > case Binding.LOCAL : // reading the first local variable >+ lastFieldBinding = null; >+ lastGenericCast = null; >+ LocalVariableBinding localBinding = (LocalVariableBinding) this.binding; >+ lastReceiverType = localBinding.type; > if (!needValue) break; // no value needed >- LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding; > // regular local variable read > Constant localConstant = localBinding.constant(); > if (localConstant != Constant.NotAConstant) { >@@ -360,62 +324,107 @@ > 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 >- if (this.otherCodegenBindings != null) { >+ int positionsLength = this.sourcePositions.length; >+ FieldBinding initialFieldBinding = lastFieldBinding; // can be null if initial was a local binding >+ if (this.otherBindings != null) { > for (int i = 0; i < otherBindingsCount; i++) { >- FieldBinding nextField = this.otherCodegenBindings[i]; >+ int pc = codeStream.position; >+ FieldBinding nextField = this.otherBindings[i].original(); > 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(); >+ Constant fieldConstant = lastFieldBinding.constant(); >+ if (fieldConstant != Constant.NotAConstant) { >+ if (i > 0 && !lastFieldBinding.isStatic()) { >+ codeStream.invokeObjectGetClass(); // perform null check >+ codeStream.pop(); >+ } >+ if (needValue) { >+ codeStream.generateConstant(fieldConstant, 0); >+ } >+ } else { >+ if (needValue || (i > 0 && complyTo14) || lastGenericCast != null) { >+ if (lastFieldBinding.canBeSeenBy(lastReceiverType, this, currentScope)) { >+ 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.fieldAccess(Opcodes.OPC_getstatic, lastFieldBinding, constantPoolDeclaringClass); >+ } else { >+ codeStream.fieldAccess(Opcodes.OPC_getfield, lastFieldBinding, constantPoolDeclaringClass); >+ } >+ } else { >+ codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */); > } >- codeStream.generateConstant(fieldConstant, 0); >- } else if (lastFieldBinding.isStatic()) { >- codeStream.getstatic(lastFieldBinding); > } else { >- codeStream.getfield(lastFieldBinding); >+ codeStream.generateEmulatedReadAccessForField(lastFieldBinding); >+ } >+ if (lastGenericCast != null) { >+ codeStream.checkcast(lastGenericCast); >+ lastReceiverType = lastGenericCast; >+ } else { >+ lastReceiverType = lastFieldBinding.type; > } >+ if (!needValue) codeStream.pop(); > } else { >- codeStream.generateEmulatedReadAccessForField(lastFieldBinding); >+ if (lastFieldBinding == initialFieldBinding) { >+ if (lastFieldBinding.isStatic()){ >+ // if no valueRequired, still need possible side-effects of <clinit> invocation, if field belongs to different class >+ if (initialFieldBinding.declaringClass != this.actualReceiverType.erasure()) { >+ if (lastFieldBinding.canBeSeenBy(lastReceiverType, this, currentScope)) { >+ MethodBinding accessor = this.syntheticReadAccessors == null ? null : this.syntheticReadAccessors[i]; >+ if (accessor == null) { >+ TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, lastFieldBinding, lastReceiverType, i == 0 && this.indexOfFirstFieldBinding == 1); >+ codeStream.fieldAccess(Opcodes.OPC_getstatic, lastFieldBinding, constantPoolDeclaringClass); >+ } else { >+ codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */); >+ } >+ } else { >+ codeStream.generateEmulatedReadAccessForField(lastFieldBinding); >+ } >+ codeStream.pop(); >+ } >+ } >+ } else if (!lastFieldBinding.isStatic()){ >+ codeStream.invokeObjectGetClass(); // perform null check >+ codeStream.pop(); >+ } >+ lastReceiverType = lastFieldBinding.type; > } >- if (lastGenericCast != null) codeStream.checkcast(lastGenericCast); >- } else { >- if (this.codegenBinding != lastFieldBinding && !lastFieldBinding.isStatic()){ >- codeStream.invokeObjectGetClass(); // perform null check >- codeStream.pop(); >+ if ((positionsLength - otherBindingsCount + i - 1) >= 0) { >+ int fieldPosition = (int) (this.sourcePositions[positionsLength - otherBindingsCount + i - 1] >>>32); >+ codeStream.recordPositionsFrom(pc, fieldPosition); > } > } > } > lastFieldBinding = nextField; > lastGenericCast = nextGenericCast; >- if (lastFieldBinding != null && !lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) { >+ if (lastFieldBinding != null && !lastFieldBinding.canBeSeenBy(lastReceiverType, this, currentScope)) { > if (lastFieldBinding.isStatic()) { > codeStream.aconst_null(); > } >- } >+ } > } > } >- return lastFieldBinding; >+ return lastFieldBinding; > } > >+ > public void generateReceiver(CodeStream codeStream) { > codeStream.aload_0(); > if (this.delegateThis != null) { >- codeStream.getfield(this.delegateThis); // delegated field access >+ codeStream.fieldAccess(Opcodes.OPC_getfield, this.delegateThis, null /* default declaringClass */); // delegated field access > } > } >+ > 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; > if ((this.bits & Binding.FIELD) != 0) { > if (!((FieldBinding) this.binding).isStatic()) { //must check for the static status.... >@@ -445,7 +454,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 +475,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,93 +504,61 @@ > } > 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; >- } >- } >+ >+public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FieldBinding fieldBinding, int index, FlowInfo flowInfo) { >+ // do nothing >+} >+/** >+ * index is <0 to denote write access emulation >+ */ >+/* >+public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FieldBinding fieldBinding, 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; > } >- /** >- * 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()); >- } >- } >+ 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))) { >+ >+lastReceiverType > } > } >+} >+*/ > /** > * Normal field binding did not work, try to bind to a field of the delegate receiver. > */ > public TypeBinding reportError(BlockScope scope) { >- > if (this.evaluationContext.declaringTypeName != null) { > this.delegateThis = scope.getField(scope.enclosingSourceType(), DELEGATE_THIS, this); > 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 { > return super.reportError(scope); > } >@@ -593,7 +571,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,37 +581,27 @@ > return super.reportError(scope); > } > } >- this.codegenBinding = this.binding = fieldBinding; >+ this.binding = fieldBinding; > return checkFieldAccess(scope); > } > > TypeBinding result; >- if (this.binding instanceof ProblemFieldBinding >- && ((ProblemFieldBinding) this.binding).problemId() == NotVisible) { >- result = resolveTypeVisibility(scope); >- if (result == null) { >+ if (this.binding instanceof ProblemFieldBinding && ((ProblemFieldBinding) this.binding).problemId() == NotVisible) { >+ // field and/or local are done before type lookups >+ // the only available value for the restrictiveFlag BEFORE >+ // the TC is Flag_Type Flag_LocalField and Flag_TypeLocalField >+ CodeSnippetScope localScope = new CodeSnippetScope(scope); >+ 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; >+ result = getOtherFieldBindings(scope); >+ } else { > return super.reportError(scope); > } >- if (result.isValidBinding()) { >+ if (result != null && result.isValidBinding()) { > return result; > } > } >- >- return super.reportError(scope); >-} >-public TypeBinding resolveTypeVisibility(BlockScope scope) { >- // field and/or local are done before type lookups >- >- // the only available value for the restrictiveFlag BEFORE >- // 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()) { >- this.bits &= ~RestrictiveFlagMASK; // clear bits >- this.bits |= Binding.FIELD; >- return getOtherFieldBindings(scope); >- } >- //========error cases=============== > return super.reportError(scope); > } > } >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 25 Sep 2008 21:20:47 -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(currentScope, codeStream, codegenBinding, null, this.actualReceiverType, this.receiver.isImplicitThis(), 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,34 @@ > * @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 constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis()); > if (isStatic) { >- codeStream.getstatic(this.codegenBinding); >+ codeStream.fieldAccess(Opcodes.OPC_getstatic , codegenBinding, constantPoolDeclaringClass); > } else { >- codeStream.getfield(this.codegenBinding); >+ codeStream.fieldAccess(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 +126,16 @@ > } > > 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 constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis()); > if (isStatic) { >- codeStream.getstatic(this.codegenBinding); >+ codeStream.fieldAccess(Opcodes.OPC_getstatic, codegenBinding, constantPoolDeclaringClass); > } else { > codeStream.dup(); >- codeStream.getfield(this.codegenBinding); >+ codeStream.fieldAccess(Opcodes.OPC_getfield, codegenBinding, constantPoolDeclaringClass); > } > int operationTypeID; > switch(operationTypeID = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) { >@@ -155,17 +158,17 @@ > // cast the value back to the array reference type > codeStream.generateImplicitConversion(assignmentImplicitConversion); > } >- fieldStore(codeStream, this.codegenBinding, null, valueRequired); >+ fieldStore(currentScope, codeStream, codegenBinding, null, this.actualReceiverType, this.receiver.isImplicitThis(), 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 +176,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 +198,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 +206,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 +278,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 +285,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 +302,26 @@ > 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; > } >+ this.actualReceiverType = this.delegateThis.type; > } 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 25 Sep 2008 21:20:51 -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 >@@ -93,7 +107,6 @@ > > } > public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) { >- > // optimizing assignment like: i = i + 1 or i = 1 + i > if (assignment.expression.isCompactableOperation()) { > BinaryExpression operation = (BinaryExpression) assignment.expression; >@@ -108,11 +121,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 +136,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 +148,13 @@ > } > } > assignment.expression.generateCode(currentScope, codeStream, true); >- fieldStore(codeStream, fieldBinding, null, valueRequired); >+ fieldStore(currentScope, codeStream, codegenField, null, this.actualReceiverType, this.delegateThis == null /*implicit this*/, 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 +167,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 +227,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.fieldAccess(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 +243,11 @@ > } else { > generateReceiver(codeStream); > } >- } >- // managing private access >- if (isStatic) { >- codeStream.getstatic(fieldBinding); >- } else { >- codeStream.getfield(fieldBinding); >+ codeStream.fieldAccess(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 +258,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 +267,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 +292,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.fieldAccess(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 +317,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.fieldAccess(Opcodes.OPC_getfield, codegenField, constantPoolDeclaringClass); > } else { > if ((this.bits & DepthMASK) != 0) { > // internal error, per construction we should have found it >@@ -313,17 +327,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 +401,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(currentScope, codeStream, codegenField, writeAccessor, this.actualReceiverType, this.delegateThis == null /* implicit this */, 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 +442,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 +457,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 +508,7 @@ > public void generateReceiver(CodeStream codeStream) { > codeStream.aload_0(); > if (this.delegateThis != null) { >- codeStream.getfield(this.delegateThis); // delegated field access >+ codeStream.fieldAccess(Opcodes.OPC_getfield, this.delegateThis, null /* default declaringClass */); // delegate field access > } > } > /** >@@ -509,36 +539,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. >@@ -550,8 +556,9 @@ > if (this.evaluationContext.declaringTypeName != null) { > 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.actualReceiverType = this.delegateThis.type; > // 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); > } >@@ -563,19 +570,20 @@ > if (this.evaluationContext.declaringTypeName != null) { > 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.actualReceiverType = this.delegateThis.type; > // will not support innerclass emulation inside delegate > FieldBinding fieldBinding = scope.getField(this.delegateThis.type, this.token, this); > if (!fieldBinding.isValidBinding()) { > 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 25 Sep 2008 21:20:49 -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 25 Sep 2008 21:20:51 -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.fieldAccess(Opcodes.OPC_getfield, this.delegateThis, null /* default declaringClass */); // delegate field access > } > codeStream.recordPositionsFrom(pc, this.sourceStart); > } >Index: compiler/org/eclipse/jdt/internal/compiler/ClassFile.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java,v >retrieving revision 1.179 >diff -u -r1.179 ClassFile.java >--- compiler/org/eclipse/jdt/internal/compiler/ClassFile.java 24 Sep 2008 16:05:23 -0000 1.179 >+++ compiler/org/eclipse/jdt/internal/compiler/ClassFile.java 25 Sep 2008 21:20:10 -0000 >@@ -4194,12 +4194,7 @@ > * > * @param codeAttributeOffset <CODE>int</CODE> > */ >- public void completeCodeAttributeForProblemMethod( >- AbstractMethodDeclaration method, >- MethodBinding binding, >- int codeAttributeOffset, >- int[] startLineIndexes, >- int problemLine) { >+ public void completeCodeAttributeForProblemMethod(AbstractMethodDeclaration method, MethodBinding binding, int codeAttributeOffset, int[] startLineIndexes, int problemLine) { > // reinitialize the localContents with the byte modified by the code stream > this.contents = this.codeStream.bCodeStream; > int localContentsOffset = this.codeStream.classFileOffset; >@@ -4391,11 +4386,15 @@ > descriptorIndex = this.constantPool.literalIndex(argumentBinding.signature()); > this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8); > this.contents[localContentsOffset++] = (byte) descriptorIndex; >- if ((argumentBinding == TypeBinding.LONG) >- || (argumentBinding == TypeBinding.DOUBLE)) >- argSize += 2; >- else >- argSize++; >+ switch(argumentBinding.id) { >+ case TypeIds.T_long : >+ case TypeIds.T_double : >+ argSize += 2; >+ break; >+ default : >+ argSize++; >+ break; >+ } > this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8); > this.contents[localContentsOffset++] = (byte) resolvedPosition; > } >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 25 Sep 2008 21:20:47 -0000 >@@ -11,7 +11,6 @@ > package org.eclipse.jdt.internal.compiler.lookup; > > import java.util.HashMap; >-import java.util.Hashtable; > import java.util.Iterator; > > import org.eclipse.jdt.core.compiler.CharOperation; >@@ -26,8 +25,8 @@ > import org.eclipse.jdt.internal.compiler.ast.TypeReference; > import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; > import org.eclipse.jdt.internal.compiler.impl.Constant; >-import org.eclipse.jdt.internal.compiler.util.Util; > import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable; >+import org.eclipse.jdt.internal.compiler.util.Util; > > public class SourceTypeBinding extends ReferenceBinding { > public ReferenceBinding superclass; >@@ -39,15 +38,13 @@ > > public ClassScope scope; > >- // Synthetics are separated into 5 categories: methods, super methods, fields, class literals, changed declaring type bindings and bridge methods >+ // Synthetics are separated into 4 categories: methods, super methods, fields, class literals and bridge methods > // if a new category is added, also increment MAX_SYNTHETICS > private final static int METHOD_EMUL = 0; > private final static int FIELD_EMUL = 1; > private final static int CLASS_LITERAL_EMUL = 2; >- /** @deprecated */ >- private final static int RECEIVER_TYPE_EMUL = 3; > >- private final static int MAX_SYNTHETICS = 4; >+ private final static int MAX_SYNTHETICS = 3; > > HashMap[] synthetics; > char[] genericReferenceTypeSignature; >@@ -1065,25 +1062,6 @@ > public ReferenceBinding[] memberTypes() { > return this.memberTypes; > } >-///** @deprecated */ >-public FieldBinding getUpdatedFieldBinding(FieldBinding targetField, ReferenceBinding newDeclaringClass) { >- if (this.synthetics == null) >- this.synthetics = new HashMap[MAX_SYNTHETICS]; >- if (this.synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL] == null) >- this.synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL] = new HashMap(5); >- >- Hashtable fieldMap = (Hashtable) this.synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL].get(targetField); >- if (fieldMap == null) { >- fieldMap = new Hashtable(5); >- this.synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL].put(targetField, fieldMap); >- } >- FieldBinding updatedField = (FieldBinding) fieldMap.get(newDeclaringClass); >- if (updatedField == null){ >- updatedField = new FieldBinding(targetField, newDeclaringClass); >- fieldMap.put(newDeclaringClass, updatedField); >- } >- return updatedField; >-} > > public boolean hasMemberTypes() { > return this.memberTypes.length > 0; >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 25 Sep 2008 21:19:36 -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))) { >#P org.eclipse.jdt.core.tests.compiler >Index: src/org/eclipse/jdt/core/tests/eval/CodeSnippetTest.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/eval/CodeSnippetTest.java,v >retrieving revision 1.17 >diff -u -r1.17 CodeSnippetTest.java >--- src/org/eclipse/jdt/core/tests/eval/CodeSnippetTest.java 27 Jun 2008 16:04:47 -0000 1.17 >+++ src/org/eclipse/jdt/core/tests/eval/CodeSnippetTest.java 25 Sep 2008 21:21:02 -0000 >@@ -675,6 +675,199 @@ > "10".toCharArray()); > } > /** >+ * Tests that the run() method defined in an anonymous class doesn't interfer with the >+ * code snippet support (see PR #1G1C0HR). >+ */ >+public void testRunMethodInAnonymous2() { >+ evaluateWithExpectedDisplayString(buildCharArray(new String[] { >+ "class X {", >+ " public int i = 0;", >+ " public boolean finished = false;", >+ "}", >+ "final X x = new X();", >+ "(new Thread() {", >+ " public void run() {", >+ " for (int i=0;i<10;i++) {", >+ " try {", >+ " Thread.currentThread().sleep(10);", >+ " } catch (InterruptedException e) {", >+ " }", >+ " ++x.i;", >+ " }", >+ " x.finished = true;", >+ " }", >+ "}).start();", >+ "while (!x.finished) Thread.currentThread().sleep(100);", >+ "x.i"}), >+ "10".toCharArray()); >+} >+/** >+ * Tests that the run() method defined in an anonymous class doesn't interfer with the >+ * code snippet support (see PR #1G1C0HR). >+ */ >+public void testRunMethodInAnonymous3() { >+ evaluateWithExpectedDisplayString(buildCharArray(new String[] { >+ "class X {", >+ " public int i = 0;", >+ " public boolean finished = false;", >+ "}", >+ "final X x = new X();", >+ "(new Thread() {", >+ " public void run() {", >+ " for (int i=0;i<10;i++) {", >+ " try {", >+ " Thread.currentThread().sleep(10);", >+ " } catch (InterruptedException e) {", >+ " }", >+ " x.i += 1;", >+ " }", >+ " x.finished = true;", >+ " }", >+ "}).start();", >+ "while (!x.finished) Thread.currentThread().sleep(100);", >+ "x.i"}), >+ "10".toCharArray()); >+} >+/** >+ * Tests that the run() method defined in an anonymous class doesn't interfer with the >+ * code snippet support (see PR #1G1C0HR). >+ */ >+public void testRunMethodInAnonymous4() { >+ evaluateWithExpectedDisplayString(buildCharArray(new String[] { >+ "class X {", >+ " public int i = 0;", >+ " public boolean finished = false;", >+ "}", >+ "final X x = new X();", >+ "(new Thread() {", >+ " public void run() {", >+ " for (int i=0;i<10;i++) {", >+ " try {", >+ " Thread.currentThread().sleep(10);", >+ " } catch (InterruptedException e) {", >+ " }", >+ " x.i = x.i + 1;", >+ " }", >+ " x.finished = true;", >+ " }", >+ "}).start();", >+ "while (!x.finished) Thread.currentThread().sleep(100);", >+ "x.i"}), >+ "10".toCharArray()); >+} >+/** >+ * Tests that the run() method defined in an anonymous class doesn't interfer with the >+ * code snippet support (see PR #1G1C0HR). >+ */ >+public void testRunMethodInAnonymous5() { >+ evaluateWithExpectedDisplayString(buildCharArray(new String[] { >+ "class X {", >+ " public int i = 0;", >+ " public boolean finished = false;", >+ " public X self() { return this; }", >+ "}", >+ "final X x = new X();", >+ "(new Thread() {", >+ " public void run() {", >+ " for (int i=0;i<10;i++) {", >+ " try {", >+ " Thread.currentThread().sleep(10);", >+ " } catch (InterruptedException e) {", >+ " }", >+ " x.self().i++;", >+ " }", >+ " x.finished = true;", >+ " }", >+ "}).start();", >+ "while (!x.finished) Thread.currentThread().sleep(100);", >+ "x.i"}), >+ "10".toCharArray()); >+} >+/** >+ * Tests that the run() method defined in an anonymous class doesn't interfer with the >+ * code snippet support (see PR #1G1C0HR). >+ */ >+public void testRunMethodInAnonymous6() { >+ evaluateWithExpectedDisplayString(buildCharArray(new String[] { >+ "class X {", >+ " public int i = 0;", >+ " public boolean finished = false;", >+ " public X self() { return this; }", >+ "}", >+ "final X x = new X();", >+ "(new Thread() {", >+ " public void run() {", >+ " for (int i=0;i<10;i++) {", >+ " try {", >+ " Thread.currentThread().sleep(10);", >+ " } catch (InterruptedException e) {", >+ " }", >+ " ++ (x.self().i);", >+ " }", >+ " x.finished = true;", >+ " }", >+ "}).start();", >+ "while (!x.finished) Thread.currentThread().sleep(100);", >+ "x.i"}), >+ "10".toCharArray()); >+} >+/** >+ * Tests that the run() method defined in an anonymous class doesn't interfer with the >+ * code snippet support (see PR #1G1C0HR). >+ */ >+public void testRunMethodInAnonymous7() { >+ evaluateWithExpectedDisplayString(buildCharArray(new String[] { >+ "class X {", >+ " public int i = 0;", >+ " public boolean finished = false;", >+ " public X self() { return this; }", >+ "}", >+ "final X x = new X();", >+ "(new Thread() {", >+ " public void run() {", >+ " for (int i=0;i<10;i++) {", >+ " try {", >+ " Thread.currentThread().sleep(10);", >+ " } catch (InterruptedException e) {", >+ " }", >+ " x.self().i += 1;", >+ " }", >+ " x.finished = true;", >+ " }", >+ "}).start();", >+ "while (!x.finished) Thread.currentThread().sleep(100);", >+ "x.i"}), >+ "10".toCharArray()); >+} >+/** >+ * Tests that the run() method defined in an anonymous class doesn't interfer with the >+ * code snippet support (see PR #1G1C0HR). >+ */ >+public void testRunMethodInAnonymous8() { >+ evaluateWithExpectedDisplayString(buildCharArray(new String[] { >+ "class X {", >+ " public int i = 0;", >+ " public boolean finished = false;", >+ " public X self() { return this; }", >+ "}", >+ "final X x = new X();", >+ "(new Thread() {", >+ " public void run() {", >+ " for (int i=0;i<10;i++) {", >+ " try {", >+ " Thread.currentThread().sleep(10);", >+ " } catch (InterruptedException e) {", >+ " }", >+ " x.self().i = x.self().i + 1;", >+ " }", >+ " x.finished = true;", >+ " }", >+ "}).start();", >+ "while (!x.finished) Thread.currentThread().sleep(100);", >+ "x.i"}), >+ "10".toCharArray()); >+} >+/** > * https://bugs.eclipse.org/bugs/show_bug.cgi?id=89632 > */ > public void testFor89632() { >Index: src/org/eclipse/jdt/core/tests/eval/DebugEvaluationTest.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/eval/DebugEvaluationTest.java,v >retrieving revision 1.39 >diff -u -r1.39 DebugEvaluationTest.java >--- src/org/eclipse/jdt/core/tests/eval/DebugEvaluationTest.java 25 Sep 2008 11:33:40 -0000 1.39 >+++ src/org/eclipse/jdt/core/tests/eval/DebugEvaluationTest.java 25 Sep 2008 21:21:07 -0000 >@@ -731,7 +731,7 @@ > /** > * changing the value of a public field > */ >-public void test018() throws Exception { >+public void testONLY_018() throws Exception { > try { > String sourceA018 = > "public class A018 {\n" + >@@ -967,8 +967,6 @@ > + "\tpublic String c = null;\n" > + "}"; > compileAndDeploy(sourceC23, "C23"); >- >- > String sourceB23 = > "public class B23 {\n" > + "\tpublic C23 c = new C23();\n"
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 247612
:
113015
|
113351
|
113390
|
113439
|
113465
|
113490
| 113530