View | Details | Raw Unified | Return to bug 247612 | Differences between
and this patch

Collapse All | Expand All

(-)compiler/org/eclipse/jdt/internal/compiler/ast/NameReference.java (-1 / +1 lines)
Lines 14-20 Link Here
14
14
15
public abstract class NameReference extends Reference implements InvocationSite {
15
public abstract class NameReference extends Reference implements InvocationSite {
16
16
17
	public Binding binding, codegenBinding; //may be aTypeBinding-aFieldBinding-aLocalVariableBinding
17
	public Binding binding; //may be aTypeBinding-aFieldBinding-aLocalVariableBinding
18
18
19
	public TypeBinding actualReceiverType;	// modified receiver type - actual one according to namelookup
19
	public TypeBinding actualReceiverType;	// modified receiver type - actual one according to namelookup
20
20
(-)compiler/org/eclipse/jdt/internal/compiler/ast/Clinit.java (-3 / +4 lines)
Lines 16-21 Link Here
16
import org.eclipse.jdt.internal.compiler.codegen.BranchLabel;
16
import org.eclipse.jdt.internal.compiler.codegen.BranchLabel;
17
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
17
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
18
import org.eclipse.jdt.internal.compiler.codegen.ConstantPool;
18
import org.eclipse.jdt.internal.compiler.codegen.ConstantPool;
19
import org.eclipse.jdt.internal.compiler.codegen.Opcodes;
19
import org.eclipse.jdt.internal.compiler.flow.ExceptionHandlingFlowContext;
20
import org.eclipse.jdt.internal.compiler.flow.ExceptionHandlingFlowContext;
20
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
21
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
21
import org.eclipse.jdt.internal.compiler.flow.InitializationFlowContext;
22
import org.eclipse.jdt.internal.compiler.flow.InitializationFlowContext;
Lines 173-179 Link Here
173
			falseLabel.place();
174
			falseLabel.place();
174
			codeStream.iconst_0();
175
			codeStream.iconst_0();
175
			jumpLabel.place();
176
			jumpLabel.place();
176
			codeStream.putstatic(this.assertionSyntheticFieldBinding);
177
			codeStream.fieldAccess(Opcodes.OPC_putstatic, this.assertionSyntheticFieldBinding, null /* default declaringClass */);
177
		}
178
		}
178
		// generate static fields/initializers/enum constants
179
		// generate static fields/initializers/enum constants
179
		final FieldDeclaration[] fieldDeclarations = declaringType.fields;
180
		final FieldDeclaration[] fieldDeclarations = declaringType.fields;
Lines 206-218 Link Here
206
						if (fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
207
						if (fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
207
							codeStream.dup();
208
							codeStream.dup();
208
							codeStream.generateInlinedValue(fieldDecl.binding.id);
209
							codeStream.generateInlinedValue(fieldDecl.binding.id);
209
							codeStream.getstatic(fieldDecl.binding);
210
							codeStream.fieldAccess(Opcodes.OPC_getstatic, fieldDecl.binding, null /* default declaringClass */);
210
							codeStream.aastore();
211
							codeStream.aastore();
211
						}
212
						}
212
					}
213
					}
213
				}
214
				}
214
			}
215
			}
215
			codeStream.putstatic(declaringType.enumValuesSyntheticfield);
216
			codeStream.fieldAccess(Opcodes.OPC_putstatic, declaringType.enumValuesSyntheticfield, null /* default declaringClass */);
216
			if (remainingFieldCount != 0) {
217
			if (remainingFieldCount != 0) {
217
				// if fields that are not enum constants need to be generated (static initializer/static field)
218
				// if fields that are not enum constants need to be generated (static initializer/static field)
218
				for (int i = 0, max = fieldDeclarations.length; i < max; i++) {
219
				for (int i = 0, max = fieldDeclarations.length; i < max; i++) {
(-)compiler/org/eclipse/jdt/internal/compiler/ast/Reference.java (-14 / +34 lines)
Lines 10-18 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.ast;
11
package org.eclipse.jdt.internal.compiler.ast;
12
12
13
import org.eclipse.jdt.internal.compiler.codegen.*;
13
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
14
import org.eclipse.jdt.internal.compiler.flow.*;
14
import org.eclipse.jdt.internal.compiler.codegen.Opcodes;
15
import org.eclipse.jdt.internal.compiler.lookup.*;
15
import org.eclipse.jdt.internal.compiler.flow.FlowContext;
16
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
17
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
18
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
19
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
20
import org.eclipse.jdt.internal.compiler.lookup.Scope;
21
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
22
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
16
23
17
public abstract class Reference extends Expression  {
24
public abstract class Reference extends Expression  {
18
/**
25
/**
Lines 26-67 Link Here
26
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
33
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
27
	return flowInfo;
34
	return flowInfo;
28
}
35
}
36
29
public FieldBinding fieldBinding() {
37
public FieldBinding fieldBinding() {
30
	//this method should be sent one FIELD-tagged references
38
	//this method should be sent one FIELD-tagged references
31
	//  (ref.bits & BindingIds.FIELD != 0)()
39
	//  (ref.bits & BindingIds.FIELD != 0)()
32
	return null ;
40
	return null ;
33
}
41
}
34
public void fieldStore(CodeStream codeStream, FieldBinding fieldBinding, MethodBinding syntheticWriteAccessor, boolean valueRequired) {
42
43
public void fieldStore(Scope currentScope, CodeStream codeStream, FieldBinding fieldBinding, MethodBinding syntheticWriteAccessor, TypeBinding receiverType, boolean isImplicitThisReceiver, boolean valueRequired) {
35
	int pc = codeStream.position;
44
	int pc = codeStream.position;
36
	if (fieldBinding.isStatic()) {
45
	if (fieldBinding.isStatic()) {
37
		if (valueRequired) {
46
		if (valueRequired) {
38
			if ((fieldBinding.type == TypeBinding.LONG) || (fieldBinding.type == TypeBinding.DOUBLE)) {
47
			switch (fieldBinding.type.id) {
39
				codeStream.dup2();
48
				case TypeIds.T_long :
40
			} else {
49
				case TypeIds.T_double :
41
				codeStream.dup();
50
					codeStream.dup2();
51
					break;
52
				default : 
53
					codeStream.dup();
54
					break;
42
			}
55
			}
43
		}
56
		}
44
		if (syntheticWriteAccessor == null) {
57
		if (syntheticWriteAccessor == null) {
45
			codeStream.putstatic(fieldBinding);
58
			TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, fieldBinding, receiverType, isImplicitThisReceiver);
59
			codeStream.fieldAccess(Opcodes.OPC_putstatic, fieldBinding, constantPoolDeclaringClass);
46
		} else {
60
		} else {
47
			codeStream.invoke(Opcodes.OPC_invokestatic, syntheticWriteAccessor, null /* default declaringClass */);
61
			codeStream.invoke(Opcodes.OPC_invokestatic, syntheticWriteAccessor, null /* default declaringClass */);
48
		}
62
		}
49
	} else { // Stack:  [owner][new field value]  ---> [new field value][owner][new field value]
63
	} else { // Stack:  [owner][new field value]  ---> [new field value][owner][new field value]
50
		if (valueRequired) {
64
		if (valueRequired) {
51
			if ((fieldBinding.type == TypeBinding.LONG) || (fieldBinding.type == TypeBinding.DOUBLE)) {
65
			switch (fieldBinding.type.id) {
52
				codeStream.dup2_x1();
66
				case TypeIds.T_long :
53
			} else {
67
				case TypeIds.T_double :
54
				codeStream.dup_x1();
68
					codeStream.dup2_x1();
69
					break;
70
				default : 
71
					codeStream.dup_x1();
72
					break;
55
			}
73
			}
56
		}
74
		}
57
		if (syntheticWriteAccessor == null) {
75
		if (syntheticWriteAccessor == null) {
58
			codeStream.putfield(fieldBinding);
76
			TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, fieldBinding, receiverType, isImplicitThisReceiver);
77
			codeStream.fieldAccess(Opcodes.OPC_putfield, fieldBinding, constantPoolDeclaringClass);
59
		} else {
78
		} else {
60
			codeStream.invoke(Opcodes.OPC_invokestatic, syntheticWriteAccessor, null /* default declaringClass */);
79
			codeStream.invoke(Opcodes.OPC_invokestatic, syntheticWriteAccessor, null /* default declaringClass */);
61
		}
80
		}
62
	}
81
	}
63
	codeStream.recordPositionsFrom(pc, this.sourceStart);
82
	codeStream.recordPositionsFrom(pc, this.sourceStart);
64
}
83
}
84
65
public abstract void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired);
85
public abstract void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired);
66
86
67
public abstract void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired);
87
public abstract void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired);
(-)compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java (-70 / +75 lines)
Lines 278-286 Link Here
278
	}
278
	}
279
	switch (this.bits & ASTNode.RestrictiveFlagMASK) {
279
	switch (this.bits & ASTNode.RestrictiveFlagMASK) {
280
		case Binding.FIELD : // assigning to a field
280
		case Binding.FIELD : // assigning to a field
281
			FieldBinding fieldBinding;
282
			int pc = codeStream.position;
281
			int pc = codeStream.position;
283
			if (!(fieldBinding = (FieldBinding) this.codegenBinding).isStatic()) { // need a receiver?
282
			FieldBinding codegenBinding = ((FieldBinding) this.binding).original();
283
			if (!codegenBinding.isStatic()) { // need a receiver?
284
				if ((this.bits & ASTNode.DepthMASK) != 0) {
284
				if ((this.bits & ASTNode.DepthMASK) != 0) {
285
					ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT);
285
					ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT);
286
					Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
286
					Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
Lines 291-304 Link Here
291
			}
291
			}
292
			codeStream.recordPositionsFrom(pc, this.sourceStart);
292
			codeStream.recordPositionsFrom(pc, this.sourceStart);
293
			assignment.expression.generateCode(currentScope, codeStream, true);
293
			assignment.expression.generateCode(currentScope, codeStream, true);
294
			fieldStore(codeStream, fieldBinding, this.syntheticAccessors == null ? null : this.syntheticAccessors[SingleNameReference.WRITE], valueRequired);
294
			fieldStore(currentScope, codeStream, codegenBinding, this.syntheticAccessors == null ? null : this.syntheticAccessors[SingleNameReference.WRITE], this.actualReceiverType, true /*implicit this*/, valueRequired);
295
			if (valueRequired) {
295
			if (valueRequired) {
296
				codeStream.generateImplicitConversion(assignment.implicitConversion);
296
				codeStream.generateImplicitConversion(assignment.implicitConversion);
297
			}
297
			}
298
			// no need for generic cast as value got dupped
298
			// no need for generic cast as value got dupped
299
			return;
299
			return;
300
		case Binding.LOCAL : // assigning to a local variable
300
		case Binding.LOCAL : // assigning to a local variable
301
			LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
301
			LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
302
			if (localBinding.resolvedPosition != -1) {
302
			if (localBinding.resolvedPosition != -1) {
303
				assignment.expression.generateCode(currentScope, codeStream, true);
303
				assignment.expression.generateCode(currentScope, codeStream, true);
304
			} else {
304
			} else {
Lines 314-324 Link Here
314
					if (valueRequired) {
314
					if (valueRequired) {
315
						codeStream.generateImplicitConversion(assignment.implicitConversion); // implicit conversion
315
						codeStream.generateImplicitConversion(assignment.implicitConversion); // implicit conversion
316
					} else {
316
					} else {
317
						if ((localBinding.type == TypeBinding.LONG) || (localBinding.type == TypeBinding.DOUBLE)) {
317
						switch(localBinding.type.id) {
318
							codeStream.pop2();
318
							case TypeIds.T_long :
319
						} else {
319
							case TypeIds.T_double :
320
							codeStream.pop();
320
								codeStream.pop2();
321
						}
321
								break;
322
							default :
323
								codeStream.pop();
324
								break;
325
						}						
322
					}
326
					}
323
				}
327
				}
324
				return;
328
				return;
Lines 354-361 Link Here
354
	} else {
358
	} else {
355
		switch (this.bits & ASTNode.RestrictiveFlagMASK) {
359
		switch (this.bits & ASTNode.RestrictiveFlagMASK) {
356
			case Binding.FIELD : // reading a field
360
			case Binding.FIELD : // reading a field
357
				FieldBinding fieldBinding = (FieldBinding) this.codegenBinding;
361
				FieldBinding codegenField = ((FieldBinding) this.binding).original();
358
				Constant fieldConstant = fieldBinding.constant();
362
				Constant fieldConstant = codegenField.constant();
359
				if (fieldConstant != Constant.NotAConstant) {
363
				if (fieldConstant != Constant.NotAConstant) {
360
					// directly use inlined value for constant fields
364
					// directly use inlined value for constant fields
361
					if (valueRequired) {
365
					if (valueRequired) {
Lines 364-370 Link Here
364
					codeStream.recordPositionsFrom(pc, this.sourceStart);
368
					codeStream.recordPositionsFrom(pc, this.sourceStart);
365
					return;
369
					return;
366
				}
370
				}
367
				if (fieldBinding.isStatic()) {
371
				if (codegenField.isStatic()) {
368
					if (!valueRequired
372
					if (!valueRequired
369
							// if no valueRequired, still need possible side-effects of <clinit> invocation, if field belongs to different class
373
							// if no valueRequired, still need possible side-effects of <clinit> invocation, if field belongs to different class
370
							&& ((FieldBinding)this.binding).original().declaringClass == this.actualReceiverType.erasure()
374
							&& ((FieldBinding)this.binding).original().declaringClass == this.actualReceiverType.erasure()
Lines 376-382 Link Here
376
					}
380
					}
377
					// managing private access
381
					// managing private access
378
					if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) {
382
					if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) {
379
						codeStream.getstatic(fieldBinding);
383
						TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, this.actualReceiverType, true /* implicit this */);
384
						codeStream.fieldAccess(Opcodes.OPC_getstatic, codegenField, constantPoolDeclaringClass);
380
					} else {
385
					} else {
381
						codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */);
386
						codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */);
382
					}
387
					}
Lines 398-411 Link Here
398
					}
403
					}
399
					// managing private access
404
					// managing private access
400
					if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) {
405
					if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) {
401
						codeStream.getfield(fieldBinding);
406
						TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, this.actualReceiverType, true /* implicit this */);
407
						codeStream.fieldAccess(Opcodes.OPC_getfield, codegenField, constantPoolDeclaringClass);
402
					} else {
408
					} else {
403
						codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */);
409
						codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */);
404
					}
410
					}
405
				}
411
				}
406
				break;
412
				break;
407
			case Binding.LOCAL : // reading a local
413
			case Binding.LOCAL : // reading a local
408
				LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
414
				LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
409
				if (!valueRequired && (this.implicitConversion & TypeIds.UNBOXING) == 0) {
415
				if (!valueRequired && (this.implicitConversion & TypeIds.UNBOXING) == 0) {
410
					// if no valueRequired, optimize out entire gen
416
					// if no valueRequired, optimize out entire gen
411
					codeStream.recordPositionsFrom(pc, this.sourceStart);
417
					codeStream.recordPositionsFrom(pc, this.sourceStart);
Lines 470-479 Link Here
470
public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, MethodBinding writeAccessor, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
476
public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, MethodBinding writeAccessor, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
471
	switch (this.bits & ASTNode.RestrictiveFlagMASK) {
477
	switch (this.bits & ASTNode.RestrictiveFlagMASK) {
472
		case Binding.FIELD : // assigning to a field
478
		case Binding.FIELD : // assigning to a field
473
			FieldBinding fieldBinding;
479
			FieldBinding codegenField = ((FieldBinding) this.binding).original();
474
			if ((fieldBinding = (FieldBinding) this.codegenBinding).isStatic()) {
480
			if (codegenField.isStatic()) {
475
				if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) {
481
				if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) {
476
					codeStream.getstatic(fieldBinding);
482
					TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, this.actualReceiverType, true /* implicit this */);					
483
					codeStream.fieldAccess(Opcodes.OPC_getstatic, codegenField, constantPoolDeclaringClass);
477
				} else {
484
				} else {
478
					codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */);
485
					codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */);
479
				}
486
				}
Lines 487-500 Link Here
487
				}
494
				}
488
				codeStream.dup();
495
				codeStream.dup();
489
				if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) {
496
				if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) {
490
					codeStream.getfield(fieldBinding);
497
					TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, this.actualReceiverType, true /* implicit this */);
498
					codeStream.fieldAccess(Opcodes.OPC_getfield, codegenField, constantPoolDeclaringClass);
491
				} else {
499
				} else {
492
					codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */);
500
					codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */);
493
				}
501
				}
494
			}
502
			}
495
			break;
503
			break;
496
		case Binding.LOCAL : // assigning to a local variable (cannot assign to outer local)
504
		case Binding.LOCAL : // assigning to a local variable (cannot assign to outer local)
497
			LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
505
			LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
498
			// using incr bytecode if possible
506
			// using incr bytecode if possible
499
			switch (localBinding.type.id) {
507
			switch (localBinding.type.id) {
500
				case T_JavaLangString :
508
				case T_JavaLangString :
Lines 564-579 Link Here
564
	// store the result back into the variable
572
	// store the result back into the variable
565
	switch (this.bits & ASTNode.RestrictiveFlagMASK) {
573
	switch (this.bits & ASTNode.RestrictiveFlagMASK) {
566
		case Binding.FIELD : // assigning to a field
574
		case Binding.FIELD : // assigning to a field
567
			fieldStore(codeStream, (FieldBinding) this.codegenBinding, writeAccessor, valueRequired);
575
			FieldBinding codegenField = ((FieldBinding) this.binding).original();
576
			fieldStore(currentScope, codeStream, codegenField, writeAccessor, this.actualReceiverType, true /* implicit this*/, valueRequired);
568
			// no need for generic cast as value got dupped
577
			// no need for generic cast as value got dupped
569
			return;
578
			return;
570
		case Binding.LOCAL : // assigning to a local variable
579
		case Binding.LOCAL : // assigning to a local variable
571
			LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
580
			LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
572
			if (valueRequired) {
581
			if (valueRequired) {
573
				if ((localBinding.type == TypeBinding.LONG) || (localBinding.type == TypeBinding.DOUBLE)) {
582
				switch (localBinding.type.id) {
574
					codeStream.dup2();
583
					case TypeIds.T_long :
575
				} else {
584
					case TypeIds.T_double :
576
					codeStream.dup();
585
						codeStream.dup2();
586
						break;
587
					default:
588
						codeStream.dup();
589
						break;
577
				}
590
				}
578
			}
591
			}
579
			codeStream.store(localBinding, false);
592
			codeStream.store(localBinding, false);
Lines 583-592 Link Here
583
public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
596
public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
584
	switch (this.bits & ASTNode.RestrictiveFlagMASK) {
597
	switch (this.bits & ASTNode.RestrictiveFlagMASK) {
585
		case Binding.FIELD : // assigning to a field
598
		case Binding.FIELD : // assigning to a field
586
			FieldBinding fieldBinding;
599
			FieldBinding codegenField = (((FieldBinding)this.binding).original());
587
			if ((fieldBinding = (FieldBinding) this.codegenBinding).isStatic()) {
600
			if (codegenField.isStatic()) {
588
				if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) {
601
				if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) {
589
					codeStream.getstatic(fieldBinding);
602
					TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, this.actualReceiverType, true /* implicit this */);
603
					codeStream.fieldAccess(Opcodes.OPC_getstatic, codegenField, constantPoolDeclaringClass);
590
				} else {
604
				} else {
591
					codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */);
605
					codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */);
592
				}
606
				}
Lines 600-606 Link Here
600
				}
614
				}
601
				codeStream.dup();
615
				codeStream.dup();
602
				if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) {
616
				if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) {
603
					codeStream.getfield(fieldBinding);
617
					TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, this.actualReceiverType, true /* implicit this */);
618
					codeStream.fieldAccess(Opcodes.OPC_getfield, codegenField, constantPoolDeclaringClass);
604
				} else {
619
				} else {
605
					codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */);
620
					codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */);
606
				}
621
				}
Lines 610-629 Link Here
610
				codeStream.checkcast(this.genericCast);
625
				codeStream.checkcast(this.genericCast);
611
				operandType = this.genericCast;
626
				operandType = this.genericCast;
612
			} else {
627
			} else {
613
				operandType = fieldBinding.type;
628
				operandType = codegenField.type;
614
			}
629
			}
615
			if (valueRequired) {
630
			if (valueRequired) {
616
				if (fieldBinding.isStatic()) {
631
				if (codegenField.isStatic()) {
617
					if ((operandType == TypeBinding.LONG) || (operandType == TypeBinding.DOUBLE)) {
632
					switch (operandType.id) {
618
						codeStream.dup2();
633
						case TypeIds.T_long :
619
					} else {
634
						case TypeIds.T_double :
620
						codeStream.dup();
635
							codeStream.dup2();
621
					}
636
							break;
637
						default:
638
							codeStream.dup();
639
							break;
640
					}					
622
				} else { // Stack:  [owner][old field value]  ---> [old field value][owner][old field value]
641
				} else { // Stack:  [owner][old field value]  ---> [old field value][owner][old field value]
623
					if ((operandType == TypeBinding.LONG) || (operandType == TypeBinding.DOUBLE)) {
642
					switch (operandType.id) {
624
						codeStream.dup2_x1();
643
						case TypeIds.T_long :
625
					} else {
644
						case TypeIds.T_double :
626
						codeStream.dup_x1();
645
							codeStream.dup2_x1();
646
							break;
647
						default:
648
							codeStream.dup_x1();
649
							break;
627
					}
650
					}
628
				}
651
				}
629
			}
652
			}
Lines 631-641 Link Here
631
			codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
654
			codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
632
			codeStream.sendOperator(postIncrement.operator, this.implicitConversion & TypeIds.COMPILE_TYPE_MASK);
655
			codeStream.sendOperator(postIncrement.operator, this.implicitConversion & TypeIds.COMPILE_TYPE_MASK);
633
			codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion);
656
			codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion);
634
			fieldStore(codeStream, fieldBinding, this.syntheticAccessors == null ? null : this.syntheticAccessors[SingleNameReference.WRITE], false);
657
			fieldStore(currentScope, codeStream, codegenField, this.syntheticAccessors == null ? null : this.syntheticAccessors[SingleNameReference.WRITE], this.actualReceiverType, true /*implicit this*/, false);
635
			// no need for generic cast 
658
			// no need for generic cast 
636
			return;
659
			return;
637
		case Binding.LOCAL : // assigning to a local variable
660
		case Binding.LOCAL : // assigning to a local variable
638
			LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
661
			LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
639
			// using incr bytecode if possible
662
			// using incr bytecode if possible
640
			if (localBinding.type == TypeBinding.INT) {
663
			if (localBinding.type == TypeBinding.INT) {
641
				if (valueRequired) {
664
				if (valueRequired) {
Lines 649-659 Link Here
649
			} else {
672
			} else {
650
				codeStream.load(localBinding);
673
				codeStream.load(localBinding);
651
				if (valueRequired){
674
				if (valueRequired){
652
					if ((localBinding.type == TypeBinding.LONG) || (localBinding.type == TypeBinding.DOUBLE)) {
675
					switch (localBinding.type.id) {
653
						codeStream.dup2();
676
						case TypeIds.T_long :
654
					} else {
677
						case TypeIds.T_double :
655
						codeStream.dup();
678
							codeStream.dup2();
656
					}
679
							break;
680
						default:
681
							codeStream.dup();
682
							break;
683
					}					
657
				}
684
				}
658
				codeStream.generateImplicitConversion(this.implicitConversion);
685
				codeStream.generateImplicitConversion(this.implicitConversion);
659
				codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
686
				codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
Lines 710-716 Link Here
710
	if ((this.bits & Binding.FIELD) != 0) {
737
	if ((this.bits & Binding.FIELD) != 0) {
711
		FieldBinding fieldBinding = (FieldBinding) this.binding;
738
		FieldBinding fieldBinding = (FieldBinding) this.binding;
712
		FieldBinding codegenField = fieldBinding.original();
739
		FieldBinding codegenField = fieldBinding.original();
713
		this.codegenBinding = codegenField;
714
		if (((this.bits & ASTNode.DepthMASK) != 0)
740
		if (((this.bits & ASTNode.DepthMASK) != 0)
715
			&& (codegenField.isPrivate() // private access
741
			&& (codegenField.isPrivate() // private access
716
				|| (codegenField.isProtected() // implicit protected access
742
				|| (codegenField.isProtected() // implicit protected access
Lines 723-748 Link Here
723
			currentScope.problemReporter().needToEmulateFieldAccess(codegenField, this, isReadAccess);
749
			currentScope.problemReporter().needToEmulateFieldAccess(codegenField, this, isReadAccess);
724
			return;
750
			return;
725
		}
751
		}
726
		// if the binding declaring class is not visible, need special action
727
		// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
728
		// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
729
		// and not from Object or implicit static field access.
730
		if (fieldBinding.declaringClass != this.actualReceiverType
731
				&& !this.actualReceiverType.isArrayType()
732
				&& fieldBinding.declaringClass != null // array.length
733
				&& fieldBinding.constant() == Constant.NotAConstant) {
734
			CompilerOptions options = currentScope.compilerOptions();
735
			if ((options.targetJDK >= ClassFileConstants.JDK1_2
736
					&& (options.complianceLevel >= ClassFileConstants.JDK1_4 || !fieldBinding.isStatic())
737
					&& fieldBinding.declaringClass.id != TypeIds.T_JavaLangObject) // no change for Object fields
738
					|| !fieldBinding.declaringClass.canBeSeenBy(currentScope)) {
739
740
					this.codegenBinding =
741
					    currentScope.enclosingSourceType().getUpdatedFieldBinding(
742
						       codegenField,
743
						        (ReferenceBinding)this.actualReceiverType.erasure());
744
			}
745
		}
746
	}
752
	}
747
}
753
}
748
754
Lines 832-838 Link Here
832
		this.actualReceiverType = scope.enclosingSourceType();
838
		this.actualReceiverType = scope.enclosingSourceType();
833
		this.binding = scope.getBinding(this.token, this.bits & ASTNode.RestrictiveFlagMASK, this, true /*resolve*/);
839
		this.binding = scope.getBinding(this.token, this.bits & ASTNode.RestrictiveFlagMASK, this, true /*resolve*/);
834
	}
840
	}
835
	this.codegenBinding = this.binding;
836
	if (this.binding.isValidBinding()) {
841
	if (this.binding.isValidBinding()) {
837
		switch (this.bits & ASTNode.RestrictiveFlagMASK) {
842
		switch (this.bits & ASTNode.RestrictiveFlagMASK) {
838
			case Binding.VARIABLE : // =========only variable============
843
			case Binding.VARIABLE : // =========only variable============
(-)compiler/org/eclipse/jdt/internal/compiler/ast/Javadoc.java (-5 / +5 lines)
Lines 373-383 Link Here
373
					if (scopeModifiers == -1) scopeModifiers = scope.getDeclarationModifiers();
373
					if (scopeModifiers == -1) scopeModifiers = scope.getDeclarationModifiers();
374
					scope.problemReporter().javadocInvalidValueReference(fieldRef.sourceStart, fieldRef.sourceEnd, scopeModifiers);
374
					scope.problemReporter().javadocInvalidValueReference(fieldRef.sourceStart, fieldRef.sourceEnd, scopeModifiers);
375
				}
375
				}
376
				else if (fieldRef.receiverType != null) {
376
				else if (fieldRef.actualReceiverType != null) {
377
					if (scope.enclosingSourceType().isCompatibleWith(fieldRef.receiverType)) {
377
					if (scope.enclosingSourceType().isCompatibleWith(fieldRef.actualReceiverType)) {
378
						fieldRef.bits |= ASTNode.SuperAccess;
378
						fieldRef.bits |= ASTNode.SuperAccess;
379
					}
379
					}
380
					fieldRef.methodBinding = scope.findMethod((ReferenceBinding)fieldRef.receiverType, fieldRef.token, new TypeBinding[0], fieldRef);
380
					fieldRef.methodBinding = scope.findMethod((ReferenceBinding)fieldRef.actualReceiverType, fieldRef.token, new TypeBinding[0], fieldRef);
381
				}
381
				}
382
			}
382
			}
383
383
Lines 390-397 Link Here
390
			}
390
			}
391
391
392
			// Verify type references
392
			// Verify type references
393
			if (!hasProblems && fieldRef.binding != null && fieldRef.binding.isValidBinding() && fieldRef.receiverType instanceof ReferenceBinding) {
393
			if (!hasProblems && fieldRef.binding != null && fieldRef.binding.isValidBinding() && fieldRef.actualReceiverType instanceof ReferenceBinding) {
394
				ReferenceBinding resolvedType = (ReferenceBinding) fieldRef.receiverType;
394
				ReferenceBinding resolvedType = (ReferenceBinding) fieldRef.actualReceiverType;
395
				verifyTypeReference(fieldRef, fieldRef.receiver, scope, source15, resolvedType, fieldRef.binding.modifiers);
395
				verifyTypeReference(fieldRef, fieldRef.receiver, scope, source15, resolvedType, fieldRef.binding.modifiers);
396
			}
396
			}
397
397
(-)compiler/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java (-5 / +8 lines)
Lines 140-150 Link Here
140
	codeStream.dup2();
140
	codeStream.dup2();
141
	codeStream.arrayAt(this.resolvedType.id);
141
	codeStream.arrayAt(this.resolvedType.id);
142
	if (valueRequired) {
142
	if (valueRequired) {
143
		if ((this.resolvedType == TypeBinding.LONG)
143
		switch(this.resolvedType.id) {
144
			|| (this.resolvedType == TypeBinding.DOUBLE)) {
144
			case TypeIds.T_long :
145
			codeStream.dup2_x2();
145
			case TypeIds.T_double :
146
		} else {
146
				codeStream.dup2_x2();
147
			codeStream.dup_x2();
147
				break;
148
			default :
149
				codeStream.dup_x2();
150
				break;
148
		}
151
		}
149
	}
152
	}
150
	codeStream.generateImplicitConversion(this.implicitConversion);
153
	codeStream.generateImplicitConversion(this.implicitConversion);
(-)compiler/org/eclipse/jdt/internal/compiler/ast/JavadocFieldReference.java (-8 / +8 lines)
Lines 41-59 Link Here
41
41
42
		this.constant = Constant.NotAConstant;
42
		this.constant = Constant.NotAConstant;
43
		if (this.receiver == null) {
43
		if (this.receiver == null) {
44
			this.receiverType = scope.enclosingReceiverType();
44
			this.actualReceiverType = scope.enclosingReceiverType();
45
		} else if (scope.kind == Scope.CLASS_SCOPE) {
45
		} else if (scope.kind == Scope.CLASS_SCOPE) {
46
			this.receiverType = this.receiver.resolveType((ClassScope) scope);
46
			this.actualReceiverType = this.receiver.resolveType((ClassScope) scope);
47
		} else {
47
		} else {
48
			this.receiverType = this.receiver.resolveType((BlockScope)scope);
48
			this.actualReceiverType = this.receiver.resolveType((BlockScope)scope);
49
		}
49
		}
50
		if (this.receiverType == null) {
50
		if (this.actualReceiverType == null) {
51
			return null;
51
			return null;
52
		}
52
		}
53
53
54
		Binding fieldBinding = (this.receiver != null && this.receiver.isThis())
54
		Binding fieldBinding = (this.receiver != null && this.receiver.isThis())
55
			? scope.classScope().getBinding(this.token, this.bits & RestrictiveFlagMASK, this, true /*resolve*/)
55
			? scope.classScope().getBinding(this.token, this.bits & RestrictiveFlagMASK, this, true /*resolve*/)
56
			: scope.getField(this.receiverType, this.token, this);
56
			: scope.getField(this.actualReceiverType, this.token, this);
57
		if (!fieldBinding.isValidBinding()) {
57
		if (!fieldBinding.isValidBinding()) {
58
			// implicit lookup may discover issues due to static/constructor contexts. javadoc must be resilient
58
			// implicit lookup may discover issues due to static/constructor contexts. javadoc must be resilient
59
			switch (fieldBinding.problemId()) {
59
			switch (fieldBinding.problemId()) {
Lines 72-79 Link Here
72
				// problem already got signaled on receiver, do not report secondary problem
72
				// problem already got signaled on receiver, do not report secondary problem
73
				return null;
73
				return null;
74
			}
74
			}
75
			if (this.receiverType instanceof ReferenceBinding) {
75
			if (this.actualReceiverType instanceof ReferenceBinding) {
76
				ReferenceBinding refBinding = (ReferenceBinding) this.receiverType;
76
				ReferenceBinding refBinding = (ReferenceBinding) this.actualReceiverType;
77
				MethodBinding possibleMethod = this.receiver.isThis()
77
				MethodBinding possibleMethod = this.receiver.isThis()
78
					? scope.getImplicitMethod(this.token, Binding.NO_TYPES, this)
78
					? scope.getImplicitMethod(this.token, Binding.NO_TYPES, this)
79
					: scope.getMethod(refBinding, this.token, Binding.NO_TYPES, this);
79
					: scope.getMethod(refBinding, this.token, Binding.NO_TYPES, this);
Lines 82-88 Link Here
82
				} else {
82
				} else {
83
					ProblemMethodBinding problemMethodBinding = (ProblemMethodBinding) possibleMethod;
83
					ProblemMethodBinding problemMethodBinding = (ProblemMethodBinding) possibleMethod;
84
					if (problemMethodBinding.closestMatch == null) {
84
					if (problemMethodBinding.closestMatch == null) {
85
						scope.problemReporter().javadocInvalidField(this, fieldBinding, this.receiverType, scope.getDeclarationModifiers());
85
						scope.problemReporter().javadocInvalidField(this, fieldBinding, this.actualReceiverType, scope.getDeclarationModifiers());
86
					} else {
86
					} else {
87
						this.methodBinding = problemMethodBinding.closestMatch;
87
						this.methodBinding = problemMethodBinding.closestMatch;
88
					}
88
					}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java (-7 / +10 lines)
Lines 228-234 Link Here
228
		if ((syntheticArg = syntheticArgs[i]).matchingField != null) {
228
		if ((syntheticArg = syntheticArgs[i]).matchingField != null) {
229
			codeStream.aload_0();
229
			codeStream.aload_0();
230
			codeStream.load(syntheticArg);
230
			codeStream.load(syntheticArg);
231
			codeStream.putfield(syntheticArg.matchingField);
231
			codeStream.fieldAccess(Opcodes.OPC_putfield, syntheticArg.matchingField, null /* default declaringClass */);
232
		}
232
		}
233
	}
233
	}
234
	syntheticArgs = nestedType.syntheticOuterLocalVariables();
234
	syntheticArgs = nestedType.syntheticOuterLocalVariables();
Lines 237-243 Link Here
237
		if ((syntheticArg = syntheticArgs[i]).matchingField != null) {
237
		if ((syntheticArg = syntheticArgs[i]).matchingField != null) {
238
			codeStream.aload_0();
238
			codeStream.aload_0();
239
			codeStream.load(syntheticArg);
239
			codeStream.load(syntheticArg);
240
			codeStream.putfield(syntheticArg.matchingField);
240
			codeStream.fieldAccess(Opcodes.OPC_putfield, syntheticArg.matchingField, null /* default declaringClass */);
241
		}
241
		}
242
	}
242
	}
243
}
243
}
Lines 277-287 Link Here
277
				LocalVariableBinding argBinding;
277
				LocalVariableBinding argBinding;
278
				codeStream.addVisibleLocalVariable(argBinding = this.arguments[i].binding);
278
				codeStream.addVisibleLocalVariable(argBinding = this.arguments[i].binding);
279
				argBinding.recordInitializationStartPC(0);
279
				argBinding.recordInitializationStartPC(0);
280
				TypeBinding argType;
280
				switch(argBinding.type.id) {
281
				if ((argType = argBinding.type) == TypeBinding.LONG || (argType == TypeBinding.DOUBLE)) {
281
					case TypeIds.T_long :
282
					argSlotSize += 2;
282
					case TypeIds.T_double :
283
				} else {
283
						argSlotSize += 2;
284
					argSlotSize++;
284
						break;
285
					default :
286
						argSlotSize++;
287
						break;
285
				}
288
				}
286
			}
289
			}
287
		}
290
		}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/AssertStatement.java (-1 / +1 lines)
Lines 101-107 Link Here
101
101
102
		if (this.assertionSyntheticFieldBinding != null) {
102
		if (this.assertionSyntheticFieldBinding != null) {
103
			BranchLabel assertionActivationLabel = new BranchLabel(codeStream);
103
			BranchLabel assertionActivationLabel = new BranchLabel(codeStream);
104
			codeStream.getstatic(this.assertionSyntheticFieldBinding);
104
			codeStream.fieldAccess(Opcodes.OPC_getstatic, this.assertionSyntheticFieldBinding, null /* default declaringClass */);
105
			codeStream.ifne(assertionActivationLabel);
105
			codeStream.ifne(assertionActivationLabel);
106
106
107
			BranchLabel falseLabel;
107
			BranchLabel falseLabel;
(-)compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java (-90 / +67 lines)
Lines 17-23 Link Here
17
import org.eclipse.jdt.internal.compiler.codegen.Opcodes;
17
import org.eclipse.jdt.internal.compiler.codegen.Opcodes;
18
import org.eclipse.jdt.internal.compiler.flow.FlowContext;
18
import org.eclipse.jdt.internal.compiler.flow.FlowContext;
19
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
19
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
20
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
21
import org.eclipse.jdt.internal.compiler.impl.Constant;
20
import org.eclipse.jdt.internal.compiler.impl.Constant;
22
import org.eclipse.jdt.internal.compiler.lookup.Binding;
21
import org.eclipse.jdt.internal.compiler.lookup.Binding;
23
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
22
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
Lines 41-51 Link Here
41
	public Expression receiver;
40
	public Expression receiver;
42
	public char[] token;
41
	public char[] token;
43
	public FieldBinding binding;															// exact binding resulting from lookup
42
	public FieldBinding binding;															// exact binding resulting from lookup
44
	protected FieldBinding codegenBinding;									// actual binding used for code generation (if no synthetic accessor)
45
	public MethodBinding[] syntheticAccessors; // [0]=read accessor [1]=write accessor
43
	public MethodBinding[] syntheticAccessors; // [0]=read accessor [1]=write accessor
46
44
47
	public long nameSourcePosition; //(start<<32)+end
45
	public long nameSourcePosition; //(start<<32)+end
48
	public TypeBinding receiverType;
46
	public TypeBinding actualReceiverType;
49
	public TypeBinding genericCast;
47
	public TypeBinding genericCast;
50
48
51
public FieldReference(char[] source, long pos) {
49
public FieldReference(char[] source, long pos) {
Lines 162-178 Link Here
162
160
163
public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) {
161
public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) {
164
	int pc = codeStream.position;
162
	int pc = codeStream.position;
165
	this.receiver.generateCode(
163
	FieldBinding codegenBinding = this.binding.original();
166
		currentScope,
164
	this.receiver.generateCode(currentScope, codeStream, !codegenBinding.isStatic());
167
		codeStream,
168
		!this.codegenBinding.isStatic());
169
	codeStream.recordPositionsFrom(pc, this.sourceStart);
165
	codeStream.recordPositionsFrom(pc, this.sourceStart);
170
	assignment.expression.generateCode(currentScope, codeStream, true);
166
	assignment.expression.generateCode(currentScope, codeStream, true);
171
	fieldStore(
167
	fieldStore(currentScope, codeStream, codegenBinding, this.syntheticAccessors == null ? null : this.syntheticAccessors[FieldReference.WRITE], this.actualReceiverType, this.receiver.isImplicitThis(), valueRequired);
172
		codeStream,
173
		this.codegenBinding,
174
		this.syntheticAccessors == null ? null : this.syntheticAccessors[FieldReference.WRITE],
175
		valueRequired);
176
	if (valueRequired) {
168
	if (valueRequired) {
177
		codeStream.generateImplicitConversion(assignment.implicitConversion);
169
		codeStream.generateImplicitConversion(assignment.implicitConversion);
178
	}
170
	}
Lines 195-203 Link Here
195
		codeStream.recordPositionsFrom(pc, this.sourceStart);
187
		codeStream.recordPositionsFrom(pc, this.sourceStart);
196
		return;
188
		return;
197
	}
189
	}
198
	boolean isStatic = this.codegenBinding.isStatic();
190
	FieldBinding codegenBinding = this.binding.original();
191
	boolean isStatic = codegenBinding.isStatic();
199
	boolean isThisReceiver = this.receiver instanceof ThisReference;
192
	boolean isThisReceiver = this.receiver instanceof ThisReference;
200
	Constant fieldConstant = this.codegenBinding.constant();
193
	Constant fieldConstant = codegenBinding.constant();
201
	if (fieldConstant != Constant.NotAConstant) {
194
	if (fieldConstant != Constant.NotAConstant) {
202
		if (!isThisReceiver) {
195
		if (!isThisReceiver) {
203
			this.receiver.generateCode(currentScope, codeStream, !isStatic);
196
			this.receiver.generateCode(currentScope, codeStream, !isStatic);
Lines 218-224 Link Here
218
			|| (this.genericCast != null)) {
211
			|| (this.genericCast != null)) {
219
		this.receiver.generateCode(currentScope, codeStream, !isStatic);
212
		this.receiver.generateCode(currentScope, codeStream, !isStatic);
220
		pc = codeStream.position;
213
		pc = codeStream.position;
221
		if (this.codegenBinding.declaringClass == null) { // array length
214
		if (codegenBinding.declaringClass == null) { // array length
222
			codeStream.arraylength();
215
			codeStream.arraylength();
223
			if (valueRequired) {
216
			if (valueRequired) {
224
				codeStream.generateImplicitConversion(this.implicitConversion);
217
				codeStream.generateImplicitConversion(this.implicitConversion);
Lines 228-237 Link Here
228
			}
221
			}
229
		} else {
222
		} else {
230
			if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) {
223
			if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) {
224
				TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis());
231
				if (isStatic) {
225
				if (isStatic) {
232
					codeStream.getstatic(this.codegenBinding);
226
					codeStream.fieldAccess(Opcodes.OPC_getstatic, codegenBinding, constantPoolDeclaringClass);
233
				} else {
227
				} else {
234
					codeStream.getfield(this.codegenBinding);
228
					codeStream.fieldAccess(Opcodes.OPC_getfield, codegenBinding, constantPoolDeclaringClass);
235
				}
229
				}
236
			} else {
230
			} else {
237
				codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[FieldReference.READ], null /* default declaringClass */);
231
				codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[FieldReference.READ], null /* default declaringClass */);
Lines 244-250 Link Here
244
				boolean isUnboxing = (this.implicitConversion & TypeIds.UNBOXING) != 0;
238
				boolean isUnboxing = (this.implicitConversion & TypeIds.UNBOXING) != 0;
245
				// conversion only generated if unboxing
239
				// conversion only generated if unboxing
246
				if (isUnboxing) codeStream.generateImplicitConversion(this.implicitConversion);
240
				if (isUnboxing) codeStream.generateImplicitConversion(this.implicitConversion);
247
				switch (isUnboxing ? postConversionType(currentScope).id : this.codegenBinding.type.id) {
241
				switch (isUnboxing ? postConversionType(currentScope).id : codegenBinding.type.id) {
248
					case T_long :
242
					case T_long :
249
					case T_double :
243
					case T_double :
250
						codeStream.pop2();
244
						codeStream.pop2();
Lines 258-271 Link Here
258
		if (isThisReceiver) {
252
		if (isThisReceiver) {
259
			if (isStatic){
253
			if (isStatic){
260
				// if no valueRequired, still need possible side-effects of <clinit> invocation, if field belongs to different class
254
				// if no valueRequired, still need possible side-effects of <clinit> invocation, if field belongs to different class
261
				if (this.binding.original().declaringClass != this.receiverType.erasure()) {
255
				if (this.binding.original().declaringClass != this.actualReceiverType.erasure()) {
262
					MethodBinding accessor = this.syntheticAccessors == null ? null : this.syntheticAccessors[FieldReference.READ];
256
					MethodBinding accessor = this.syntheticAccessors == null ? null : this.syntheticAccessors[FieldReference.READ];
263
					if (accessor == null) {
257
					if (accessor == null) {
264
						codeStream.getstatic(this.codegenBinding);
258
						TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis());
259
						codeStream.fieldAccess(Opcodes.OPC_getstatic, codegenBinding, constantPoolDeclaringClass);
265
					} else {
260
					} else {
266
						codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */);
261
						codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */);
267
					}
262
					}
268
					switch (this.codegenBinding.type.id) {
263
					switch (codegenBinding.type.id) {
269
						case T_long :
264
						case T_long :
270
						case T_double :
265
						case T_double :
271
							codeStream.pop2();
266
							codeStream.pop2();
Lines 288-307 Link Here
288
283
289
public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
284
public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
290
	boolean isStatic;
285
	boolean isStatic;
291
	this.receiver.generateCode(
286
	FieldBinding codegenBinding = this.binding.original();
292
		currentScope,
287
	this.receiver.generateCode(currentScope, codeStream, !(isStatic = codegenBinding.isStatic()));
293
		codeStream,
294
		!(isStatic = this.codegenBinding.isStatic()));
295
	if (isStatic) {
288
	if (isStatic) {
296
		if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) {
289
		if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) {
297
			codeStream.getstatic(this.codegenBinding);
290
			TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis());
291
			codeStream.fieldAccess(Opcodes.OPC_getstatic, codegenBinding, constantPoolDeclaringClass);
298
		} else {
292
		} else {
299
			codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[FieldReference.READ], null /* default declaringClass */);
293
			codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[FieldReference.READ], null /* default declaringClass */);
300
		}
294
		}
301
	} else {
295
	} else {
302
		codeStream.dup();
296
		codeStream.dup();
303
		if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) {
297
		if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) {
304
			codeStream.getfield(this.codegenBinding);
298
			TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis());
299
			codeStream.fieldAccess(Opcodes.OPC_getfield, codegenBinding, constantPoolDeclaringClass);
305
		} else {
300
		} else {
306
			codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[FieldReference.READ], null /* default declaringClass */);
301
			codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[FieldReference.READ], null /* default declaringClass */);
307
		}
302
		}
Lines 329-358 Link Here
329
			// cast the value back to the array reference type
324
			// cast the value back to the array reference type
330
			codeStream.generateImplicitConversion(assignmentImplicitConversion);
325
			codeStream.generateImplicitConversion(assignmentImplicitConversion);
331
	}
326
	}
332
	fieldStore(
327
	fieldStore(currentScope, codeStream, codegenBinding, this.syntheticAccessors == null ? null : this.syntheticAccessors[FieldReference.WRITE], this.actualReceiverType, this.receiver.isImplicitThis(), valueRequired);
333
		codeStream,
334
		this.codegenBinding,
335
		this.syntheticAccessors == null ? null : this.syntheticAccessors[FieldReference.WRITE],
336
		valueRequired);
337
	// no need for generic cast as value got dupped
328
	// no need for generic cast as value got dupped
338
}
329
}
339
330
340
public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
331
public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
341
	boolean isStatic;
332
	boolean isStatic;
342
	this.receiver.generateCode(
333
	FieldBinding codegenBinding = this.binding.original();
343
		currentScope,
334
	this.receiver.generateCode(currentScope, codeStream, !(isStatic = codegenBinding.isStatic()));
344
		codeStream,
345
		!(isStatic = this.codegenBinding.isStatic()));
346
	if (isStatic) {
335
	if (isStatic) {
347
		if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) {
336
		if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) {
348
			codeStream.getstatic(this.codegenBinding);
337
			TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis());
338
			codeStream.fieldAccess(Opcodes.OPC_getstatic, codegenBinding, constantPoolDeclaringClass);
349
		} else {
339
		} else {
350
			codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[FieldReference.READ], null /* default declaringClass */);
340
			codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[FieldReference.READ], null /* default declaringClass */);
351
		}
341
		}
352
	} else {
342
	} else {
353
		codeStream.dup();
343
		codeStream.dup();
354
		if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) {
344
		if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) {
355
			codeStream.getfield(this.codegenBinding);
345
			TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis());
346
			codeStream.fieldAccess(Opcodes.OPC_getfield, codegenBinding, constantPoolDeclaringClass);
356
		} else {
347
		} else {
357
			codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[FieldReference.READ], null /* default declaringClass */);
348
			codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[FieldReference.READ], null /* default declaringClass */);
358
		}
349
		}
Lines 362-384 Link Here
362
		codeStream.checkcast(this.genericCast);
353
		codeStream.checkcast(this.genericCast);
363
		operandType = this.genericCast;
354
		operandType = this.genericCast;
364
	} else {
355
	} else {
365
		operandType = this.codegenBinding.type;
356
		operandType = codegenBinding.type;
366
	}	
357
	}	
367
	if (valueRequired) {
358
	if (valueRequired) {
368
		if (isStatic) {
359
		if (isStatic) {
369
			if ((operandType == TypeBinding.LONG)
360
			switch (operandType.id) {
370
				|| (operandType == TypeBinding.DOUBLE)) {
361
				case TypeIds.T_long :
371
				codeStream.dup2();
362
				case TypeIds.T_double :
372
			} else {
363
					codeStream.dup2();
373
				codeStream.dup();
364
					break;
374
			}
365
				default :
366
					codeStream.dup();
367
					break;
368
			}			
375
		} else { // Stack:  [owner][old field value]  ---> [old field value][owner][old field value]
369
		} else { // Stack:  [owner][old field value]  ---> [old field value][owner][old field value]
376
			if ((operandType == TypeBinding.LONG)
370
			switch (operandType.id) {
377
				|| (operandType == TypeBinding.DOUBLE)) {
371
				case TypeIds.T_long :
378
				codeStream.dup2_x1();
372
				case TypeIds.T_double :
379
			} else {
373
					codeStream.dup2_x1();
380
				codeStream.dup_x1();
374
					break;
381
			}
375
				default :
376
					codeStream.dup_x1();
377
					break;
378
			}			
382
		}
379
		}
383
	}
380
	}
384
	codeStream.generateImplicitConversion(this.implicitConversion);		
381
	codeStream.generateImplicitConversion(this.implicitConversion);		
Lines 388-394 Link Here
388
	codeStream.sendOperator(postIncrement.operator, this.implicitConversion & TypeIds.COMPILE_TYPE_MASK);
385
	codeStream.sendOperator(postIncrement.operator, this.implicitConversion & TypeIds.COMPILE_TYPE_MASK);
389
	codeStream.generateImplicitConversion(
386
	codeStream.generateImplicitConversion(
390
		postIncrement.preAssignImplicitConversion);
387
		postIncrement.preAssignImplicitConversion);
391
	fieldStore(codeStream, this.codegenBinding, this.syntheticAccessors == null ? null : this.syntheticAccessors[FieldReference.WRITE], false);
388
	fieldStore(currentScope, codeStream, codegenBinding, this.syntheticAccessors == null ? null : this.syntheticAccessors[FieldReference.WRITE], this.actualReceiverType, this.receiver.isImplicitThis(), false);
392
}
389
}
393
390
394
/**
391
/**
Lines 412-427 Link Here
412
	if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0)	return;
409
	if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0)	return;
413
410
414
	// if field from parameterized type got found, use the original field at codegen time
411
	// if field from parameterized type got found, use the original field at codegen time
415
	this.codegenBinding = this.binding.original();
412
	FieldBinding codegenBinding = this.binding.original();
416
413
417
	if (this.binding.isPrivate()) {
414
	if (this.binding.isPrivate()) {
418
		if ((currentScope.enclosingSourceType() != this.codegenBinding.declaringClass)
415
		if ((currentScope.enclosingSourceType() != codegenBinding.declaringClass)
419
				&& this.binding.constant() == Constant.NotAConstant) {
416
				&& this.binding.constant() == Constant.NotAConstant) {
420
			if (this.syntheticAccessors == null)
417
			if (this.syntheticAccessors == null)
421
				this.syntheticAccessors = new MethodBinding[2];
418
				this.syntheticAccessors = new MethodBinding[2];
422
			this.syntheticAccessors[isReadAccess ? FieldReference.READ : FieldReference.WRITE] =
419
			this.syntheticAccessors[isReadAccess ? FieldReference.READ : FieldReference.WRITE] =
423
				((SourceTypeBinding) this.codegenBinding.declaringClass).addSyntheticMethod(this.codegenBinding, isReadAccess);
420
				((SourceTypeBinding) codegenBinding.declaringClass).addSyntheticMethod(codegenBinding, isReadAccess);
424
			currentScope.problemReporter().needToEmulateFieldAccess(this.codegenBinding, this, isReadAccess);
421
			currentScope.problemReporter().needToEmulateFieldAccess(codegenBinding, this, isReadAccess);
425
			return;
422
			return;
426
		}
423
		}
427
424
Lines 433-440 Link Here
433
				.currentCompatibleType);
430
				.currentCompatibleType);
434
		if (this.syntheticAccessors == null)
431
		if (this.syntheticAccessors == null)
435
			this.syntheticAccessors = new MethodBinding[2];
432
			this.syntheticAccessors = new MethodBinding[2];
436
		this.syntheticAccessors[isReadAccess ? FieldReference.READ : FieldReference.WRITE] = destinationType.addSyntheticMethod(this.codegenBinding, isReadAccess);
433
		this.syntheticAccessors[isReadAccess ? FieldReference.READ : FieldReference.WRITE] = destinationType.addSyntheticMethod(codegenBinding, isReadAccess);
437
		currentScope.problemReporter().needToEmulateFieldAccess(this.codegenBinding, this, isReadAccess);
434
		currentScope.problemReporter().needToEmulateFieldAccess(codegenBinding, this, isReadAccess);
438
		return;
435
		return;
439
436
440
	} else if (this.binding.isProtected()) {
437
	} else if (this.binding.isProtected()) {
Lines 449-479 Link Here
449
					(this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT);
446
					(this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT);
450
			if (this.syntheticAccessors == null)
447
			if (this.syntheticAccessors == null)
451
				this.syntheticAccessors = new MethodBinding[2];
448
				this.syntheticAccessors = new MethodBinding[2];
452
			this.syntheticAccessors[isReadAccess ? FieldReference.READ : FieldReference.WRITE] = currentCompatibleType.addSyntheticMethod(this.codegenBinding, isReadAccess);
449
			this.syntheticAccessors[isReadAccess ? FieldReference.READ : FieldReference.WRITE] = currentCompatibleType.addSyntheticMethod(codegenBinding, isReadAccess);
453
			currentScope.problemReporter().needToEmulateFieldAccess(this.codegenBinding, this, isReadAccess);
450
			currentScope.problemReporter().needToEmulateFieldAccess(codegenBinding, this, isReadAccess);
454
			return;
451
			return;
455
		}
452
		}
456
	}
453
	}
457
	// if the binding declaring class is not visible, need special action
458
	// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
459
	// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
460
	// and not from Object or implicit static field access.
461
	if (this.binding.declaringClass != this.receiverType
462
			&& !this.receiverType.isArrayType()
463
			&& this.binding.declaringClass != null // array.length
464
			&& this.binding.constant() == Constant.NotAConstant) {
465
		CompilerOptions options = currentScope.compilerOptions();
466
		if ((options.targetJDK >= ClassFileConstants.JDK1_2
467
				&& (options.complianceLevel >= ClassFileConstants.JDK1_4 || !(this.receiver.isImplicitThis() && this.codegenBinding.isStatic()))
468
				&& this.binding.declaringClass.id != TypeIds.T_JavaLangObject) // no change for Object fields
469
			|| !this.binding.declaringClass.canBeSeenBy(currentScope)) {
470
471
			this.codegenBinding =
472
				currentScope.enclosingSourceType().getUpdatedFieldBinding(
473
					this.codegenBinding,
474
					(ReferenceBinding) this.receiverType.erasure());
475
		}
476
	}
477
}
454
}
478
455
479
public int nullStatus(FlowInfo flowInfo) {
456
public int nullStatus(FlowInfo flowInfo) {
Lines 546-580 Link Here
546
		this.receiver.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on
523
		this.receiver.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on
547
		receiverCast = true;
524
		receiverCast = true;
548
	}
525
	}
549
	this.receiverType = this.receiver.resolveType(scope);
526
	this.actualReceiverType = this.receiver.resolveType(scope);
550
	if (this.receiverType == null) {
527
	if (this.actualReceiverType == null) {
551
		this.constant = Constant.NotAConstant;
528
		this.constant = Constant.NotAConstant;
552
		return null;
529
		return null;
553
	}
530
	}
554
	if (receiverCast) {
531
	if (receiverCast) {
555
		 // due to change of declaring class with receiver type, only identity cast should be notified
532
		 // due to change of declaring class with receiver type, only identity cast should be notified
556
		if (((CastExpression)this.receiver).expression.resolvedType == this.receiverType) {
533
		if (((CastExpression)this.receiver).expression.resolvedType == this.actualReceiverType) {
557
				scope.problemReporter().unnecessaryCast((CastExpression)this.receiver);
534
				scope.problemReporter().unnecessaryCast((CastExpression)this.receiver);
558
		}
535
		}
559
	}
536
	}
560
	// the case receiverType.isArrayType and token = 'length' is handled by the scope API
537
	// the case receiverType.isArrayType and token = 'length' is handled by the scope API
561
	FieldBinding fieldBinding = this.codegenBinding = this.binding = scope.getField(this.receiverType, this.token, this);
538
	FieldBinding fieldBinding = this.binding = scope.getField(this.actualReceiverType, this.token, this);
562
	if (!fieldBinding.isValidBinding()) {
539
	if (!fieldBinding.isValidBinding()) {
563
		this.constant = Constant.NotAConstant;
540
		this.constant = Constant.NotAConstant;
564
		if (this.receiver.resolvedType instanceof ProblemReferenceBinding) {
541
		if (this.receiver.resolvedType instanceof ProblemReferenceBinding) {
565
			// problem already got signaled on receiver, do not report secondary problem
542
			// problem already got signaled on receiver, do not report secondary problem
566
			return null;
543
			return null;
567
		}
544
		}
568
		scope.problemReporter().invalidField(this, this.receiverType);
545
		scope.problemReporter().invalidField(this, this.actualReceiverType);
569
		return null;
546
		return null;
570
	}
547
	}
571
	TypeBinding receiverErasure = this.receiverType.erasure();
548
	TypeBinding receiverErasure = this.actualReceiverType.erasure();
572
	if (receiverErasure instanceof ReferenceBinding) {
549
	if (receiverErasure instanceof ReferenceBinding) {
573
		if (receiverErasure.findSuperTypeOriginatingFrom(fieldBinding.declaringClass) == null) {
550
		if (receiverErasure.findSuperTypeOriginatingFrom(fieldBinding.declaringClass) == null) {
574
			this.receiverType = fieldBinding.declaringClass; // handle indirect inheritance thru variable secondary bound
551
			this.actualReceiverType = fieldBinding.declaringClass; // handle indirect inheritance thru variable secondary bound
575
		}
552
		}
576
	}
553
	}
577
	this.receiver.computeConversion(scope, this.receiverType, this.receiverType);
554
	this.receiver.computeConversion(scope, this.actualReceiverType, this.actualReceiverType);
578
	if (isFieldUseDeprecated(fieldBinding, scope, (this.bits & ASTNode.IsStrictlyAssigned) !=0)) {
555
	if (isFieldUseDeprecated(fieldBinding, scope, (this.bits & ASTNode.IsStrictlyAssigned) !=0)) {
579
		scope.problemReporter().deprecatedField(fieldBinding, this);
556
		scope.problemReporter().deprecatedField(fieldBinding, this);
580
	}
557
	}
Lines 589-595 Link Here
589
		}
566
		}
590
		ReferenceBinding declaringClass = this.binding.declaringClass;
567
		ReferenceBinding declaringClass = this.binding.declaringClass;
591
		if (!isImplicitThisRcv
568
		if (!isImplicitThisRcv
592
				&& declaringClass != this.receiverType
569
				&& declaringClass != this.actualReceiverType
593
				&& declaringClass.canBeSeenBy(scope)) {
570
				&& declaringClass.canBeSeenBy(scope)) {
594
			scope.problemReporter().indirectAccessToStaticField(this, fieldBinding);
571
			scope.problemReporter().indirectAccessToStaticField(this, fieldBinding);
595
		}
572
		}
Lines 620-626 Link Here
620
}
597
}
621
598
622
public void setActualReceiverType(ReferenceBinding receiverType) {
599
public void setActualReceiverType(ReferenceBinding receiverType) {
623
	// ignored
600
	this.actualReceiverType = receiverType;
624
}
601
}
625
602
626
public void setDepth(int depth) {
603
public void setDepth(int depth) {
(-)compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java (-5 / +8 lines)
Lines 253-263 Link Here
253
		TypeBinding[] parameters = this.binding.parameters;
253
		TypeBinding[] parameters = this.binding.parameters;
254
		int size = 1; // an abstact method or a native method cannot be static
254
		int size = 1; // an abstact method or a native method cannot be static
255
		for (int i = 0, max = parameters.length; i < max; i++) {
255
		for (int i = 0, max = parameters.length; i < max; i++) {
256
			TypeBinding parameter = parameters[i];
256
			switch(parameters[i].id) {
257
			if (parameter == TypeBinding.LONG || parameter == TypeBinding.DOUBLE) {
257
				case TypeIds.T_long :
258
				size += 2;
258
				case TypeIds.T_double :
259
			} else {
259
					size += 2;
260
				size++;
260
					break;
261
				default :
262
					size++;
263
					break;
261
			}
264
			}
262
			if (size > 0xFF) {
265
			if (size > 0xFF) {
263
				this.scope.problemReporter().noMoreAvailableSpaceForArgument(this.scope.locals[i], this.scope.locals[i].declaration);
266
				this.scope.problemReporter().noMoreAvailableSpaceForArgument(this.scope.locals[i], this.scope.locals[i].declaration);
(-)compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java (-1 / +9 lines)
Lines 152-158 Link Here
152
				codeStream.updateLastRecordedEndPC(currentScope, position);
152
				codeStream.updateLastRecordedEndPC(currentScope, position);
153
				// Tune codestream stack size
153
				// Tune codestream stack size
154
				if (valueRequired) {
154
				if (valueRequired) {
155
					codeStream.decrStackSize(this.resolvedType == TypeBinding.LONG || this.resolvedType == TypeBinding.DOUBLE ? 2 : 1);
155
					switch(this.resolvedType.id) {
156
						case TypeIds.T_long :
157
						case TypeIds.T_double :
158
							codeStream.decrStackSize(2);
159
							break;
160
						default :
161
							codeStream.decrStackSize(1);
162
							break;
163
					}
156
				}
164
				}
157
			}
165
			}
158
		}
166
		}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/SynchronizedStatement.java (-6 / +9 lines)
Lines 94-105 Link Here
94
	// generate the synchronization expression
94
	// generate the synchronization expression
95
	this.expression.generateCode(this.scope, codeStream, true);
95
	this.expression.generateCode(this.scope, codeStream, true);
96
	if (this.block.isEmptyBlock()) {
96
	if (this.block.isEmptyBlock()) {
97
		if ((this.synchroVariable.type == TypeBinding.LONG)
97
		switch(this.synchroVariable.type.id) {
98
			|| (this.synchroVariable.type == TypeBinding.DOUBLE)) {
98
			case TypeIds.T_long :
99
			codeStream.dup2();
99
			case TypeIds.T_double :
100
		} else {
100
				codeStream.dup2();
101
			codeStream.dup();
101
				break;
102
		}
102
			default :
103
				codeStream.dup();
104
				break;
105
		}		
103
		// only take the lock
106
		// only take the lock
104
		codeStream.monitorenter();
107
		codeStream.monitorenter();
105
		codeStream.monitorexit();
108
		codeStream.monitorexit();
(-)compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java (-30 / +1 lines)
Lines 149-155 Link Here
149
149
150
	// actual message invocation
150
	// actual message invocation
151
	if (this.syntheticAccessor == null){
151
	if (this.syntheticAccessor == null){
152
		TypeBinding constantPoolDeclaringClass = getConstantPoolDeclaringClass(currentScope);
152
		TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis(), this.receiverGenericCast != null);
153
		if (isStatic){
153
		if (isStatic){
154
			codeStream.invoke(Opcodes.OPC_invokestatic, codegenBinding, constantPoolDeclaringClass);
154
			codeStream.invoke(Opcodes.OPC_invokestatic, codegenBinding, constantPoolDeclaringClass);
155
		} else if( (this.receiver.isSuper()) || codegenBinding.isPrivate()){
155
		} else if( (this.receiver.isSuper()) || codegenBinding.isPrivate()){
Lines 193-227 Link Here
193
	return this.genericTypeArguments;
193
	return this.genericTypeArguments;
194
}
194
}
195
195
196
protected TypeBinding getConstantPoolDeclaringClass(BlockScope currentScope) {
197
	// constantpool declaringClass
198
	MethodBinding codegenBinding = this.binding.original();
199
	TypeBinding constantPoolDeclaringClass = codegenBinding.declaringClass;
200
	// Post 1.4.0 target, array clone() invocations are qualified with array type
201
	// This is handled in array type #clone method binding resolution (see Scope and UpdatedMethodBinding)
202
	if (codegenBinding == currentScope.environment().arrayClone) {
203
		CompilerOptions options = currentScope.compilerOptions();
204
		if (options.sourceLevel > ClassFileConstants.JDK1_4 ) {
205
			constantPoolDeclaringClass = this.actualReceiverType.erasure();
206
		}
207
	} else {
208
		// if the binding declaring class is not visible, need special action
209
		// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
210
		// NOTE: from target 1.2 on, method's declaring class is touched if any different from receiver type
211
		// and not from Object or implicit static method call.
212
		if (constantPoolDeclaringClass != this.actualReceiverType && this.receiverGenericCast == null && !this.actualReceiverType.isArrayType()) {
213
			CompilerOptions options = currentScope.compilerOptions();
214
			if ((options.targetJDK >= ClassFileConstants.JDK1_2
215
						&& (options.complianceLevel >= ClassFileConstants.JDK1_4 || !(this.receiver.isImplicitThis() && codegenBinding.isStatic()))
216
						&& this.binding.declaringClass.id != TypeIds.T_JavaLangObject) // no change for Object methods
217
					|| !this.binding.declaringClass.canBeSeenBy(currentScope)) {
218
				constantPoolDeclaringClass = this.actualReceiverType.erasure();
219
			}
220
		}				
221
	}
222
	return constantPoolDeclaringClass;
223
}
224
225
public boolean isSuperAccess() {
196
public boolean isSuperAccess() {
226
	return this.receiver.isSuper();
197
	return this.receiver.isSuper();
227
}
198
}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java (-169 / +113 lines)
Lines 44-50 Link Here
44
44
45
	public char[][] tokens;
45
	public char[][] tokens;
46
	public long[] sourcePositions;
46
	public long[] sourcePositions;
47
	public FieldBinding[] otherBindings, otherCodegenBindings;
47
	public FieldBinding[] otherBindings;
48
	int[] otherDepths;
48
	int[] otherDepths;
49
	public int indexOfFirstFieldBinding;//points (into tokens) for the first token that corresponds to first FieldBinding
49
	public int indexOfFirstFieldBinding;//points (into tokens) for the first token that corresponds to first FieldBinding
50
	public SyntheticMethodBinding syntheticWriteAccessor;
50
	public SyntheticMethodBinding syntheticWriteAccessor;
Lines 69-75 Link Here
69
		case Binding.FIELD : // reading a field
69
		case Binding.FIELD : // reading a field
70
			lastFieldBinding = (FieldBinding) this.binding;
70
			lastFieldBinding = (FieldBinding) this.binding;
71
			if (needValue || complyTo14) {
71
			if (needValue || complyTo14) {
72
				manageSyntheticAccessIfNecessary(currentScope, lastFieldBinding, this.actualReceiverType, 0, flowInfo);
72
				manageSyntheticAccessIfNecessary(currentScope, lastFieldBinding, 0, flowInfo);
73
			}
73
			}
74
			// check if final blank field
74
			// check if final blank field
75
			if (lastFieldBinding.isBlankFinal()
75
			if (lastFieldBinding.isBlankFinal()
Lines 107-120 Link Here
107
			lastFieldBinding = this.otherBindings[i];
107
			lastFieldBinding = this.otherBindings[i];
108
			needValue = !this.otherBindings[i+1].isStatic();
108
			needValue = !this.otherBindings[i+1].isStatic();
109
			if (needValue || complyTo14) {
109
			if (needValue || complyTo14) {
110
				manageSyntheticAccessIfNecessary(
110
				manageSyntheticAccessIfNecessary(currentScope, lastFieldBinding, i + 1, flowInfo);
111
					currentScope,
112
					lastFieldBinding,
113
					i == 0
114
						? ((VariableBinding)this.binding).type
115
						: this.otherBindings[i-1].type,
116
					i + 1,
117
					flowInfo);
118
			}
111
			}
119
		}
112
		}
120
		lastFieldBinding = this.otherBindings[otherBindingsCount-1];
113
		lastFieldBinding = this.otherBindings[otherBindingsCount-1];
Lines 127-150 Link Here
127
				&& (!flowInfo.isDefinitelyAssigned(lastFieldBinding))) {
120
				&& (!flowInfo.isDefinitelyAssigned(lastFieldBinding))) {
128
			currentScope.problemReporter().uninitializedBlankFinalField(lastFieldBinding, this);
121
			currentScope.problemReporter().uninitializedBlankFinalField(lastFieldBinding, this);
129
		}
122
		}
130
		TypeBinding lastReceiverType;
123
		manageSyntheticAccessIfNecessary(currentScope, lastFieldBinding, otherBindingsCount, flowInfo);
131
		switch (otherBindingsCount) {
132
			case 0 :
133
				lastReceiverType = this.actualReceiverType;
134
				break;
135
			case 1 :
136
				lastReceiverType = ((VariableBinding)this.binding).type;
137
				break;
138
			default:
139
				lastReceiverType = this.otherBindings[otherBindingsCount-2].type;
140
				break;
141
		}
142
		manageSyntheticAccessIfNecessary(
143
			currentScope,
144
			lastFieldBinding,
145
			lastReceiverType,
146
			otherBindingsCount,
147
			flowInfo);
148
	}
124
	}
149
125
150
	if (assignment.expression != null) {
126
	if (assignment.expression != null) {
Lines 176-195 Link Here
176
			}
152
			}
177
		}
153
		}
178
	}
154
	}
179
	// equivalent to valuesRequired[maxOtherBindings]
155
	manageSyntheticAccessIfNecessary(currentScope, lastFieldBinding, -1 /*write-access*/, flowInfo);
180
	TypeBinding lastReceiverType;
181
	switch (otherBindingsCount) {
182
		case 0 :
183
			lastReceiverType = this.actualReceiverType;
184
			break;
185
		case 1 :
186
			lastReceiverType = ((VariableBinding)this.binding).type;
187
			break;
188
		default :
189
			lastReceiverType = this.otherBindings[otherBindingsCount-2].type;
190
			break;
191
	}
192
	manageSyntheticAccessIfNecessary(currentScope, lastFieldBinding, lastReceiverType, -1 /*write-access*/, flowInfo);
193
156
194
	return flowInfo;
157
	return flowInfo;
195
}
158
}
Lines 207-213 Link Here
207
	switch (this.bits & ASTNode.RestrictiveFlagMASK) {
170
	switch (this.bits & ASTNode.RestrictiveFlagMASK) {
208
		case Binding.FIELD : // reading a field
171
		case Binding.FIELD : // reading a field
209
			if (needValue || complyTo14) {
172
			if (needValue || complyTo14) {
210
				manageSyntheticAccessIfNecessary(currentScope, (FieldBinding) this.binding, this.actualReceiverType, 0, flowInfo);
173
				manageSyntheticAccessIfNecessary(currentScope, (FieldBinding) this.binding, 0, flowInfo);
211
			}
174
			}
212
			if (this.indexOfFirstFieldBinding == 1) { // was an implicit reference to the first field binding
175
			if (this.indexOfFirstFieldBinding == 1) { // was an implicit reference to the first field binding
213
				FieldBinding fieldBinding = (FieldBinding) this.binding;
176
				FieldBinding fieldBinding = (FieldBinding) this.binding;
Lines 221-228 Link Here
221
			break;
184
			break;
222
		case Binding.LOCAL : // reading a local variable
185
		case Binding.LOCAL : // reading a local variable
223
			LocalVariableBinding localBinding;
186
			LocalVariableBinding localBinding;
224
			if (!flowInfo
187
			if (!flowInfo.isDefinitelyAssigned(localBinding = (LocalVariableBinding) this.binding)) {
225
				.isDefinitelyAssigned(localBinding = (LocalVariableBinding) this.binding)) {
226
				currentScope.problemReporter().uninitializedLocalVariable(localBinding, this);
188
				currentScope.problemReporter().uninitializedLocalVariable(localBinding, this);
227
			}
189
			}
228
			if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0)	{
190
			if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0)	{
Lines 240-259 Link Here
240
		for (int i = 0; i < otherBindingsCount; i++) {
202
		for (int i = 0; i < otherBindingsCount; i++) {
241
			needValue = i < otherBindingsCount-1 ? !this.otherBindings[i+1].isStatic() : valueRequired;
203
			needValue = i < otherBindingsCount-1 ? !this.otherBindings[i+1].isStatic() : valueRequired;
242
			if (needValue || complyTo14) {
204
			if (needValue || complyTo14) {
243
				TypeBinding lastReceiverType = getGenericCast(i);
205
				manageSyntheticAccessIfNecessary(currentScope, this.otherBindings[i], i + 1, flowInfo);
244
				if (lastReceiverType == null) {
245
					if (i == 0) {
246
						 lastReceiverType = ((VariableBinding)this.binding).type;
247
					} else {
248
						lastReceiverType = this.otherBindings[i-1].type;
249
					}
250
				}
251
				manageSyntheticAccessIfNecessary(
252
					currentScope,
253
					this.otherBindings[i],
254
					lastReceiverType,
255
					i + 1,
256
					flowInfo);
257
			}
206
			}
258
		}
207
		}
259
	}
208
	}
Lines 346-352 Link Here
346
	FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream);
295
	FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream);
347
	codeStream.recordPositionsFrom(pc , this.sourceStart);
296
	codeStream.recordPositionsFrom(pc , this.sourceStart);
348
	assignment.expression.generateCode(currentScope, codeStream, true);
297
	assignment.expression.generateCode(currentScope, codeStream, true);
349
	fieldStore(codeStream, lastFieldBinding, this.syntheticWriteAccessor, valueRequired);
298
	fieldStore(currentScope, codeStream, lastFieldBinding, this.syntheticWriteAccessor, getFinalReceiverType(), false /*implicit this*/, valueRequired);
350
	// equivalent to valuesRequired[maxOtherBindings]
299
	// equivalent to valuesRequired[maxOtherBindings]
351
	if (valueRequired) {
300
	if (valueRequired) {
352
		codeStream.generateImplicitConversion(assignment.implicitConversion);
301
		codeStream.generateImplicitConversion(assignment.implicitConversion);
Lines 376-382 Link Here
376
				boolean isFirst = lastFieldBinding == this.binding
325
				boolean isFirst = lastFieldBinding == this.binding
377
												&& (this.indexOfFirstFieldBinding == 1 || lastFieldBinding.declaringClass == currentScope.enclosingReceiverType())
326
												&& (this.indexOfFirstFieldBinding == 1 || lastFieldBinding.declaringClass == currentScope.enclosingReceiverType())
378
												&& this.otherBindings == null; // could be dup: next.next.next
327
												&& this.otherBindings == null; // could be dup: next.next.next
379
				TypeBinding requiredGenericCast = getGenericCast(this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length);
328
				TypeBinding requiredGenericCast = getGenericCast(this.otherBindings == null ? 0 : this.otherBindings.length);
380
				if (valueRequired
329
				if (valueRequired
381
						|| (!isFirst && currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4)
330
						|| (!isFirst && currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4)
382
						|| ((this.implicitConversion & TypeIds.UNBOXING) != 0)
331
						|| ((this.implicitConversion & TypeIds.UNBOXING) != 0)
Lines 391-405 Link Here
391
							codeStream.pop();
340
							codeStream.pop();
392
						}
341
						}
393
					} else {
342
					} else {
394
						SyntheticMethodBinding accessor =
343
						SyntheticMethodBinding accessor = this.syntheticReadAccessors == null ? null : this.syntheticReadAccessors[this.syntheticReadAccessors.length - 1];
395
							this.syntheticReadAccessors == null
396
								? null
397
								: this.syntheticReadAccessors[this.syntheticReadAccessors.length - 1];
398
						if (accessor == null) {
344
						if (accessor == null) {
345
							TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, lastFieldBinding, getFinalReceiverType(), isFirst);
399
							if (isStatic) {
346
							if (isStatic) {
400
								codeStream.getstatic(lastFieldBinding);
347
								codeStream.fieldAccess(Opcodes.OPC_getstatic, lastFieldBinding, constantPoolDeclaringClass);
401
							} else {
348
							} else {
402
								codeStream.getfield(lastFieldBinding);
349
								codeStream.fieldAccess(Opcodes.OPC_getfield, lastFieldBinding, constantPoolDeclaringClass);
403
							}
350
							}
404
						} else {
351
						} else {
405
							codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */);
352
							codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */);
Lines 418-423 Link Here
418
									break;
365
									break;
419
								default :
366
								default :
420
									codeStream.pop();
367
									codeStream.pop();
368
									break;
421
							}
369
							}
422
						}
370
						}
423
					}
371
					}
Lines 436-464 Link Here
436
	codeStream.recordPositionsFrom(pc, this.sourceStart);
384
	codeStream.recordPositionsFrom(pc, this.sourceStart);
437
}
385
}
438
386
439
public void generateCompoundAssignment(
387
public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
440
	BlockScope currentScope,
441
	CodeStream codeStream,
442
	Expression expression,
443
	int operator,
444
	int assignmentImplicitConversion,
445
	boolean valueRequired) {
446
447
	FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream);
388
	FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream);
448
	SyntheticMethodBinding accessor =
389
	boolean isFirst = lastFieldBinding == this.binding
449
		this.syntheticReadAccessors == null
390
		&& (this.indexOfFirstFieldBinding == 1 || lastFieldBinding.declaringClass == currentScope.enclosingReceiverType())
450
			? null
391
		&& this.otherBindings == null; // could be dup: next.next.next
451
			: this.syntheticReadAccessors[this.syntheticReadAccessors.length - 1];
392
	TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, lastFieldBinding, getFinalReceiverType(), isFirst);			
393
	SyntheticMethodBinding accessor = this.syntheticReadAccessors == null ? null : this.syntheticReadAccessors[this.syntheticReadAccessors.length - 1];
452
	if (lastFieldBinding.isStatic()) {
394
	if (lastFieldBinding.isStatic()) {
453
		if (accessor == null) {
395
		if (accessor == null) {
454
			codeStream.getstatic(lastFieldBinding);
396
			codeStream.fieldAccess(Opcodes.OPC_getstatic, lastFieldBinding, constantPoolDeclaringClass);
455
		} else {
397
		} else {
456
			codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */);
398
			codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */);
457
		}
399
		}
458
	} else {
400
	} else {
459
		codeStream.dup();
401
		codeStream.dup();
460
		if (accessor == null) {
402
		if (accessor == null) {
461
			codeStream.getfield(lastFieldBinding);
403
			codeStream.fieldAccess(Opcodes.OPC_getfield, lastFieldBinding, constantPoolDeclaringClass);
462
		} else {
404
		} else {
463
			codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */);
405
			codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */);
464
		}
406
		}
Lines 473-479 Link Here
473
			codeStream.generateStringConcatenationAppend(currentScope, null, expression);
415
			codeStream.generateStringConcatenationAppend(currentScope, null, expression);
474
			break;
416
			break;
475
		default :
417
		default :
476
			TypeBinding requiredGenericCast = getGenericCast(this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length);
418
			TypeBinding requiredGenericCast = getGenericCast(this.otherBindings == null ? 0 : this.otherBindings.length);
477
			if (requiredGenericCast != null) codeStream.checkcast(requiredGenericCast);
419
			if (requiredGenericCast != null) codeStream.checkcast(requiredGenericCast);
478
			// promote the array reference to the suitable operation type
420
			// promote the array reference to the suitable operation type
479
			codeStream.generateImplicitConversion(this.implicitConversion);
421
			codeStream.generateImplicitConversion(this.implicitConversion);
Lines 489-518 Link Here
489
			codeStream.generateImplicitConversion(assignmentImplicitConversion);
431
			codeStream.generateImplicitConversion(assignmentImplicitConversion);
490
	}
432
	}
491
	// actual assignment
433
	// actual assignment
492
	fieldStore(codeStream, lastFieldBinding, this.syntheticWriteAccessor, valueRequired);
434
	fieldStore(currentScope, codeStream, lastFieldBinding, this.syntheticWriteAccessor, getFinalReceiverType(), false /*implicit this*/, valueRequired);
493
	// equivalent to valuesRequired[maxOtherBindings]
435
	// equivalent to valuesRequired[maxOtherBindings]
494
}
436
}
495
437
496
public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
438
public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
497
	FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream);
439
	FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream);
440
	boolean isFirst = lastFieldBinding == this.binding
441
		&& (this.indexOfFirstFieldBinding == 1 || lastFieldBinding.declaringClass == currentScope.enclosingReceiverType())
442
		&& this.otherBindings == null; // could be dup: next.next.next
443
	TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, lastFieldBinding, getFinalReceiverType(), isFirst);			
498
	SyntheticMethodBinding accessor = this.syntheticReadAccessors == null
444
	SyntheticMethodBinding accessor = this.syntheticReadAccessors == null
499
			? null
445
			? null
500
			: this.syntheticReadAccessors[this.syntheticReadAccessors.length - 1];
446
			: this.syntheticReadAccessors[this.syntheticReadAccessors.length - 1];
501
	if (lastFieldBinding.isStatic()) {
447
	if (lastFieldBinding.isStatic()) {
502
		if (accessor == null) {
448
		if (accessor == null) {
503
			codeStream.getstatic(lastFieldBinding);
449
			codeStream.fieldAccess(Opcodes.OPC_getstatic, lastFieldBinding, constantPoolDeclaringClass);
504
		} else {
450
		} else {
505
			codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */);
451
			codeStream.invoke(Opcodes.OPC_invokestatic, accessor, constantPoolDeclaringClass);
506
		}
452
		}
507
	} else {
453
	} else {
508
		codeStream.dup();
454
		codeStream.dup();
509
		if (accessor == null) {
455
		if (accessor == null) {
510
			codeStream.getfield(lastFieldBinding);
456
			codeStream.fieldAccess(Opcodes.OPC_getfield, lastFieldBinding, null /* default declaringClass */);
511
		} else {
457
		} else {
512
			codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */);
458
			codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */);
513
		}
459
		}
514
	}
460
	}
515
	TypeBinding requiredGenericCast = getGenericCast(this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length);
461
	TypeBinding requiredGenericCast = getGenericCast(this.otherBindings == null ? 0 : this.otherBindings.length);
516
	TypeBinding operandType;
462
	TypeBinding operandType;
517
	if (requiredGenericCast != null) {
463
	if (requiredGenericCast != null) {
518
		codeStream.checkcast(requiredGenericCast);
464
		codeStream.checkcast(requiredGenericCast);
Lines 523-541 Link Here
523
	// duplicate the old field value
469
	// duplicate the old field value
524
	if (valueRequired) {
470
	if (valueRequired) {
525
		if (lastFieldBinding.isStatic()) {
471
		if (lastFieldBinding.isStatic()) {
526
			if ((operandType == TypeBinding.LONG)
472
			switch (operandType.id) {
527
				|| (operandType == TypeBinding.DOUBLE)) {
473
				case TypeIds.T_long :
528
				codeStream.dup2();
474
				case TypeIds.T_double :
529
			} else {
475
					codeStream.dup2();
530
				codeStream.dup();
476
					break;
531
			}
477
				default:
478
					codeStream.dup();
479
					break;
480
			}			
532
		} else { // Stack:  [owner][old field value]  ---> [old field value][owner][old field value]
481
		} else { // Stack:  [owner][old field value]  ---> [old field value][owner][old field value]
533
			if ((operandType == TypeBinding.LONG)
482
			switch (operandType.id) {
534
				|| (operandType == TypeBinding.DOUBLE)) {
483
				case TypeIds.T_long :
535
				codeStream.dup2_x1();
484
				case TypeIds.T_double :
536
			} else {
485
					codeStream.dup2_x1();
537
				codeStream.dup_x1();
486
					break;
538
			}
487
				default:
488
					codeStream.dup_x1();
489
					break;
490
			}			
539
		}
491
		}
540
	}
492
	}
541
	codeStream.generateImplicitConversion(this.implicitConversion);		
493
	codeStream.generateImplicitConversion(this.implicitConversion);		
Lines 545-551 Link Here
545
	codeStream.sendOperator(postIncrement.operator, this.implicitConversion & TypeIds.COMPILE_TYPE_MASK);
497
	codeStream.sendOperator(postIncrement.operator, this.implicitConversion & TypeIds.COMPILE_TYPE_MASK);
546
	codeStream.generateImplicitConversion(
498
	codeStream.generateImplicitConversion(
547
		postIncrement.preAssignImplicitConversion);
499
		postIncrement.preAssignImplicitConversion);
548
	fieldStore(codeStream, lastFieldBinding, this.syntheticWriteAccessor, false);
500
	fieldStore(currentScope, codeStream, lastFieldBinding, this.syntheticWriteAccessor, getFinalReceiverType(), false /*implicit this*/, false);
549
}
501
}
550
502
551
/*
503
/*
Lines 554-569 Link Here
554
 */
506
 */
555
public FieldBinding generateReadSequence(BlockScope currentScope, CodeStream codeStream) {
507
public FieldBinding generateReadSequence(BlockScope currentScope, CodeStream codeStream) {
556
	// determine the rank until which we now we do not need any actual value for the field access
508
	// determine the rank until which we now we do not need any actual value for the field access
557
	int otherBindingsCount = this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length;
509
	int otherBindingsCount = this.otherBindings == null ? 0 : this.otherBindings.length;
558
	boolean needValue = otherBindingsCount == 0 || !this.otherBindings[0].isStatic();
510
	boolean needValue = otherBindingsCount == 0 || !this.otherBindings[0].isStatic();
559
	FieldBinding lastFieldBinding = null;
511
	FieldBinding lastFieldBinding;
560
	TypeBinding lastGenericCast = null;
512
	TypeBinding lastGenericCast;
513
	TypeBinding lastReceiverType;
561
	boolean complyTo14 = currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4;
514
	boolean complyTo14 = currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4;
562
515
563
	switch (this.bits & ASTNode.RestrictiveFlagMASK) {
516
	switch (this.bits & ASTNode.RestrictiveFlagMASK) {
564
		case Binding.FIELD :
517
		case Binding.FIELD :
565
			lastFieldBinding = (FieldBinding) this.codegenBinding;
518
			lastFieldBinding = ((FieldBinding) this.binding).original();
566
			lastGenericCast = this.genericCast;
519
			lastGenericCast = this.genericCast;
520
			lastReceiverType = this.actualReceiverType;
567
			// if first field is actually constant, we can inline it
521
			// if first field is actually constant, we can inline it
568
			if (lastFieldBinding.constant() != Constant.NotAConstant) {
522
			if (lastFieldBinding.constant() != Constant.NotAConstant) {
569
				break;
523
				break;
Lines 581-588 Link Here
581
			}
535
			}
582
			break;
536
			break;
583
		case Binding.LOCAL : // reading the first local variable
537
		case Binding.LOCAL : // reading the first local variable
538
			lastFieldBinding = null;
539
			lastGenericCast = null;
540
			LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
541
			lastReceiverType = localBinding.type;
584
			if (!needValue) break; // no value needed
542
			if (!needValue) break; // no value needed
585
			LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
586
			// regular local variable read
543
			// regular local variable read
587
			Constant localConstant = localBinding.constant();
544
			Constant localConstant = localBinding.constant();
588
			if (localConstant != Constant.NotAConstant) {
545
			if (localConstant != Constant.NotAConstant) {
Lines 598-612 Link Here
598
					codeStream.load(localBinding);
555
					codeStream.load(localBinding);
599
				}
556
				}
600
			}
557
			}
558
			break;
559
		default : // should not occur
560
			return null;
601
	}
561
	}
602
562
603
	// all intermediate field accesses are read accesses
563
	// all intermediate field accesses are read accesses
604
	// only the last field binding is a write access
564
	// only the last field binding is a write access
605
	int positionsLength = this.sourcePositions.length;
565
	int positionsLength = this.sourcePositions.length;
606
	if (this.otherCodegenBindings != null) {
566
	FieldBinding initialFieldBinding = lastFieldBinding; // can be null if initial was a local binding
567
	if (this.otherBindings != null) {
607
		for (int i = 0; i < otherBindingsCount; i++) {
568
		for (int i = 0; i < otherBindingsCount; i++) {
608
			int pc = codeStream.position;
569
			int pc = codeStream.position;
609
			FieldBinding nextField = this.otherCodegenBindings[i];
570
			FieldBinding nextField = this.otherBindings[i].original();
610
			TypeBinding nextGenericCast = this.otherGenericCasts == null ? null : this.otherGenericCasts[i];
571
			TypeBinding nextGenericCast = this.otherGenericCasts == null ? null : this.otherGenericCasts[i];
611
			if (lastFieldBinding != null) {
572
			if (lastFieldBinding != null) {
612
				needValue = !nextField.isStatic();
573
				needValue = !nextField.isStatic();
Lines 623-646 Link Here
623
					if (needValue || (i > 0 && complyTo14) || lastGenericCast != null) {
584
					if (needValue || (i > 0 && complyTo14) || lastGenericCast != null) {
624
						MethodBinding accessor = this.syntheticReadAccessors == null ? null : this.syntheticReadAccessors[i];
585
						MethodBinding accessor = this.syntheticReadAccessors == null ? null : this.syntheticReadAccessors[i];
625
						if (accessor == null) {
586
						if (accessor == null) {
587
							TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, lastFieldBinding, lastReceiverType, i == 0 && this.indexOfFirstFieldBinding == 1);
626
							if (lastFieldBinding.isStatic()) {
588
							if (lastFieldBinding.isStatic()) {
627
								codeStream.getstatic(lastFieldBinding);
589
								codeStream.fieldAccess(Opcodes.OPC_getstatic, lastFieldBinding, constantPoolDeclaringClass);
628
							} else {
590
							} else {
629
								codeStream.getfield(lastFieldBinding);
591
								codeStream.fieldAccess(Opcodes.OPC_getfield, lastFieldBinding, constantPoolDeclaringClass);
630
							}
592
							}
631
						} else {
593
						} else {
632
							codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */);
594
							codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */);
633
						}
595
						}
634
						if (lastGenericCast != null) codeStream.checkcast(lastGenericCast);
596
						if (lastGenericCast != null) {
597
							codeStream.checkcast(lastGenericCast);
598
							lastReceiverType = lastGenericCast;
599
						} else {
600
							lastReceiverType = lastFieldBinding.type;
601
						}
635
						if (!needValue) codeStream.pop();
602
						if (!needValue) codeStream.pop();
636
					} else {
603
					} else {
637
						if (this.codegenBinding == lastFieldBinding) {
604
						if (lastFieldBinding == initialFieldBinding) {
638
							if (lastFieldBinding.isStatic()){
605
							if (lastFieldBinding.isStatic()){
639
								// if no valueRequired, still need possible side-effects of <clinit> invocation, if field belongs to different class
606
								// if no valueRequired, still need possible side-effects of <clinit> invocation, if field belongs to different class
640
								if (((FieldBinding)this.binding).original().declaringClass != this.actualReceiverType.erasure()) {
607
								if (initialFieldBinding.declaringClass != this.actualReceiverType.erasure()) {
641
									MethodBinding accessor = this.syntheticReadAccessors == null ? null : this.syntheticReadAccessors[i];
608
									MethodBinding accessor = this.syntheticReadAccessors == null ? null : this.syntheticReadAccessors[i];
642
									if (accessor == null) {
609
									if (accessor == null) {
643
										codeStream.getstatic(lastFieldBinding);
610
										TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, lastFieldBinding, lastReceiverType, i == 0 && this.indexOfFirstFieldBinding == 1);
611
										codeStream.fieldAccess(Opcodes.OPC_getstatic, lastFieldBinding, constantPoolDeclaringClass);
644
									} else {
612
									} else {
645
										codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */);
613
										codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */);
646
									}
614
									}
Lines 651-656 Link Here
651
							codeStream.invokeObjectGetClass(); // perform null check
619
							codeStream.invokeObjectGetClass(); // perform null check
652
							codeStream.pop();
620
							codeStream.pop();
653
						}
621
						}
622
						lastReceiverType = lastFieldBinding.type;
654
					}
623
					}
655
					if ((positionsLength - otherBindingsCount + i - 1) >= 0) {
624
					if ((positionsLength - otherBindingsCount + i - 1) >= 0) {
656
						int fieldPosition = (int) (this.sourcePositions[positionsLength - otherBindingsCount + i - 1] >>>32);
625
						int fieldPosition = (int) (this.sourcePositions[positionsLength - otherBindingsCount + i - 1] >>>32);
Lines 676-690 Link Here
676
	return null;
645
	return null;
677
}
646
}
678
647
679
// get the matching codegenBinding
680
protected FieldBinding getCodegenBinding(int index) {
648
protected FieldBinding getCodegenBinding(int index) {
681
  if (index == 0){
649
  if (index == 0){
682
		return (FieldBinding)this.codegenBinding;
650
		return ((FieldBinding)this.binding).original();
683
	} else {
651
	} else {
684
		return this.otherCodegenBindings[index-1];
652
		return this.otherBindings[index-1].original();
685
	}
653
	}
686
}
654
}
687
655
656
/**
657
 * Returns the receiver type for the final field in sequence (i.e. the return type of the previous binding)
658
 * @return receiver type for the final field in sequence
659
 */
660
protected TypeBinding getFinalReceiverType() {
661
	int otherBindingsCount = this.otherBindings == null ? 0 : this.otherBindings.length;
662
	switch (otherBindingsCount) {
663
		case 0 :
664
			return this.actualReceiverType;
665
		case 1 :
666
			return this.genericCast != null ? this.genericCast : ((VariableBinding)this.binding).type;
667
		default:
668
			TypeBinding previousGenericCast = this.otherGenericCasts == null ? null : this.otherGenericCasts[otherBindingsCount-2];
669
			return previousGenericCast != null ? previousGenericCast : this.otherBindings[otherBindingsCount-2].type;
670
	}	
671
}
672
688
// get the matching generic cast
673
// get the matching generic cast
689
protected TypeBinding getGenericCast(int index) {
674
protected TypeBinding getGenericCast(int index) {
690
   if (index == 0){
675
   if (index == 0){
Lines 694-700 Link Here
694
		return this.otherGenericCasts[index-1];
679
		return this.otherGenericCasts[index-1];
695
	}
680
	}
696
}
681
}
697
698
public TypeBinding getOtherFieldBindings(BlockScope scope) {
682
public TypeBinding getOtherFieldBindings(BlockScope scope) {
699
	// At this point restrictiveFlag may ONLY have two potential value : FIELD LOCAL (i.e cast <<(VariableBinding) binding>> is valid)
683
	// At this point restrictiveFlag may ONLY have two potential value : FIELD LOCAL (i.e cast <<(VariableBinding) binding>> is valid)
700
	int length = this.tokens.length;
684
	int length = this.tokens.length;
Lines 730-736 Link Here
730
	}
714
	}
731
	// allocation of the fieldBindings array	and its respective constants
715
	// allocation of the fieldBindings array	and its respective constants
732
	int otherBindingsLength = length - index;
716
	int otherBindingsLength = length - index;
733
	this.otherCodegenBindings = this.otherBindings = new FieldBinding[otherBindingsLength];
717
	this.otherBindings = new FieldBinding[otherBindingsLength];
734
	this.otherDepths = new int[otherBindingsLength];
718
	this.otherDepths = new int[otherBindingsLength];
735
719
736
	// fill the first constant (the one of the binding)
720
	// fill the first constant (the one of the binding)
Lines 825-848 Link Here
825
/**
809
/**
826
 * index is <0 to denote write access emulation
810
 * index is <0 to denote write access emulation
827
 */
811
 */
828
public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FieldBinding fieldBinding, TypeBinding lastReceiverType, 	int index, FlowInfo flowInfo) {
812
public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FieldBinding fieldBinding, int index, FlowInfo flowInfo) {
829
	if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0)	return;
813
	if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0)	return;
830
	// index == 0 denotes the first fieldBinding, index > 0 denotes one of the 'otherBindings', index < 0 denotes a write access (to last binding)
814
	// index == 0 denotes the first fieldBinding, index > 0 denotes one of the 'otherBindings', index < 0 denotes a write access (to last binding)
831
	if (fieldBinding.constant() != Constant.NotAConstant)
815
	if (fieldBinding.constant() != Constant.NotAConstant)
832
		return;
816
		return;
833
817
834
	// if field from parameterized type got found, use the original field at codegen time
835
	FieldBinding originalField = fieldBinding.original();
836
	if (originalField != fieldBinding) {
837
		setCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index, originalField);
838
	}
839
840
	if (fieldBinding.isPrivate()) { // private access
818
	if (fieldBinding.isPrivate()) { // private access
841
	    FieldBinding someCodegenBinding = getCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index);
819
	    FieldBinding codegenField = getCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index);
842
		if (someCodegenBinding.declaringClass != currentScope.enclosingSourceType()) {
820
	    ReferenceBinding declaringClass = codegenField.declaringClass;
843
		    setSyntheticAccessor(fieldBinding, index,
821
		if (declaringClass != currentScope.enclosingSourceType()) {
844
		            ((SourceTypeBinding) someCodegenBinding.declaringClass).addSyntheticMethod(someCodegenBinding, index >= 0 /*read-access?*/));
822
		    setSyntheticAccessor(fieldBinding, index, ((SourceTypeBinding) declaringClass).addSyntheticMethod(codegenField, index >= 0 /*read-access?*/));
845
			currentScope.problemReporter().needToEmulateFieldAccess(someCodegenBinding, this, index >= 0 /*read-access?*/);
823
			currentScope.problemReporter().needToEmulateFieldAccess(codegenField, this, index >= 0 /*read-access?*/);
846
			return;
824
			return;
847
		}
825
		}
848
	} else if (fieldBinding.isProtected()){
826
	} else if (fieldBinding.isProtected()){
Lines 852-885 Link Here
852
830
853
		// implicit protected access
831
		// implicit protected access
854
		if (depth > 0 && (fieldBinding.declaringClass.getPackage() != currentScope.enclosingSourceType().getPackage())) {
832
		if (depth > 0 && (fieldBinding.declaringClass.getPackage() != currentScope.enclosingSourceType().getPackage())) {
855
		    FieldBinding someCodegenBinding = getCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index);
833
		    FieldBinding codegenField = getCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index);
856
		    setSyntheticAccessor(fieldBinding, index,
834
		    setSyntheticAccessor(fieldBinding, index,
857
		            ((SourceTypeBinding) currentScope.enclosingSourceType().enclosingTypeAt(depth)).addSyntheticMethod(someCodegenBinding, index >= 0 /*read-access?*/));
835
		            ((SourceTypeBinding) currentScope.enclosingSourceType().enclosingTypeAt(depth)).addSyntheticMethod(codegenField, index >= 0 /*read-access?*/));
858
			currentScope.problemReporter().needToEmulateFieldAccess(someCodegenBinding, this, index >= 0 /*read-access?*/);
836
			currentScope.problemReporter().needToEmulateFieldAccess(codegenField, this, index >= 0 /*read-access?*/);
859
			return;
837
			return;
860
		}
838
		}
861
	}
839
	}
862
	// if the binding declaring class is not visible, need special action
863
	// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
864
	// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
865
	// and not from Object or implicit static field access.
866
	if (fieldBinding.declaringClass != lastReceiverType
867
			&& !lastReceiverType.isArrayType()
868
			&& fieldBinding.declaringClass != null // array.length
869
			&& fieldBinding.constant() == Constant.NotAConstant) {
870
		CompilerOptions options = currentScope.compilerOptions();
871
		if ((options.targetJDK >= ClassFileConstants.JDK1_2
872
				&& (options.complianceLevel >= ClassFileConstants.JDK1_4 || !(index <= 1 &&  this.indexOfFirstFieldBinding == 1 && fieldBinding.isStatic()))
873
				&& fieldBinding.declaringClass.id != TypeIds.T_JavaLangObject) // no change for Object fields
874
				|| !fieldBinding.declaringClass.canBeSeenBy(currentScope)) {
875
876
		    setCodegenBinding(
877
		            index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index,
878
		            currentScope.enclosingSourceType().getUpdatedFieldBinding(
879
		                    getCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index),
880
		                    (ReferenceBinding)lastReceiverType.erasure()));
881
		}
882
	}
883
}
840
}
884
841
885
public int nullStatus(FlowInfo flowInfo) {
842
public int nullStatus(FlowInfo flowInfo) {
Lines 908-914 Link Here
908
 */
865
 */
909
public TypeBinding postConversionType(Scope scope) {
866
public TypeBinding postConversionType(Scope scope) {
910
	TypeBinding convertedType = this.resolvedType;
867
	TypeBinding convertedType = this.resolvedType;
911
	TypeBinding requiredGenericCast = getGenericCast(this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length);
868
	TypeBinding requiredGenericCast = getGenericCast(this.otherBindings == null ? 0 : this.otherBindings.length);
912
	if (requiredGenericCast != null)
869
	if (requiredGenericCast != null)
913
		convertedType = requiredGenericCast;
870
		convertedType = requiredGenericCast;
914
	int runtimeType = (this.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4;
871
	int runtimeType = (this.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4;
Lines 973-979 Link Here
973
	// the TC is Flag_Type Flag_LocalField and Flag_TypeLocalField
930
	// the TC is Flag_Type Flag_LocalField and Flag_TypeLocalField
974
	this.actualReceiverType = scope.enclosingReceiverType();
931
	this.actualReceiverType = scope.enclosingReceiverType();
975
	this.constant = Constant.NotAConstant;
932
	this.constant = Constant.NotAConstant;
976
	if ((this.codegenBinding = this.binding = scope.getBinding(this.tokens, this.bits & ASTNode.RestrictiveFlagMASK, this, true /*resolve*/)).isValidBinding()) {
933
	if ((this.binding = scope.getBinding(this.tokens, this.bits & ASTNode.RestrictiveFlagMASK, this, true /*resolve*/)).isValidBinding()) {
977
		switch (this.bits & ASTNode.RestrictiveFlagMASK) {
934
		switch (this.bits & ASTNode.RestrictiveFlagMASK) {
978
			case Binding.VARIABLE : //============only variable===========
935
			case Binding.VARIABLE : //============only variable===========
979
			case Binding.TYPE | Binding.VARIABLE :
936
			case Binding.TYPE | Binding.VARIABLE :
Lines 1056-1074 Link Here
1056
	return this.resolvedType = reportError(scope);
1013
	return this.resolvedType = reportError(scope);
1057
}
1014
}
1058
1015
1059
// set the matching codegenBinding and generic cast
1060
protected void setCodegenBinding(int index, FieldBinding someCodegenBinding) {
1061
	if (index == 0){
1062
		this.codegenBinding = someCodegenBinding;
1063
	} else {
1064
	    int length = this.otherBindings.length;
1065
		if (this.otherCodegenBindings == this.otherBindings){
1066
			System.arraycopy(this.otherBindings, 0, this.otherCodegenBindings = new FieldBinding[length], 0, length);
1067
		}
1068
		this.otherCodegenBindings[index-1] = someCodegenBinding;
1069
	}
1070
}
1071
1072
public void setFieldIndex(int index) {
1016
public void setFieldIndex(int index) {
1073
	this.indexOfFirstFieldBinding = index;
1017
	this.indexOfFirstFieldBinding = index;
1074
}
1018
}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java (-2 / +2 lines)
Lines 104-112 Link Here
104
		this.initialization.generateCode(currentScope, codeStream, true);
104
		this.initialization.generateCode(currentScope, codeStream, true);
105
		// store into field
105
		// store into field
106
		if (isStatic) {
106
		if (isStatic) {
107
			codeStream.putstatic(this.binding);
107
			codeStream.fieldAccess(Opcodes.OPC_putstatic, this.binding, null /* default declaringClass */);
108
		} else {
108
		} else {
109
			codeStream.putfield(this.binding);
109
			codeStream.fieldAccess(Opcodes.OPC_putfield, this.binding, null /* default declaringClass */);
110
		}
110
		}
111
	}
111
	}
112
	codeStream.recordPositionsFrom(pc, this.sourceStart);
112
	codeStream.recordPositionsFrom(pc, this.sourceStart);
(-)compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java (-183 / +224 lines)
Lines 21-26 Link Here
21
import org.eclipse.jdt.internal.compiler.ast.OperatorIds;
21
import org.eclipse.jdt.internal.compiler.ast.OperatorIds;
22
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
22
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
23
import org.eclipse.jdt.internal.compiler.flow.UnconditionalFlowInfo;
23
import org.eclipse.jdt.internal.compiler.flow.UnconditionalFlowInfo;
24
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
24
import org.eclipse.jdt.internal.compiler.impl.Constant;
25
import org.eclipse.jdt.internal.compiler.impl.Constant;
25
import org.eclipse.jdt.internal.compiler.lookup.*;
26
import org.eclipse.jdt.internal.compiler.lookup.*;
26
import org.eclipse.jdt.internal.compiler.problem.AbortMethod;
27
import org.eclipse.jdt.internal.compiler.problem.AbortMethod;
Lines 1214-1219 Link Here
1214
	this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_fdiv;
1215
	this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_fdiv;
1215
}
1216
}
1216
1217
1218
public void fieldAccess(byte opcode, FieldBinding fieldBinding, TypeBinding declaringClass) {
1219
	if (declaringClass == null) declaringClass = fieldBinding.declaringClass;
1220
	if (declaringClass.leafComponentType().isNestedType()) {
1221
		this.classFile.recordInnerClasses(declaringClass);
1222
	}
1223
	TypeBinding returnType = fieldBinding.type;
1224
	int returnTypeSize;
1225
	switch (returnType.id) {
1226
		case TypeIds.T_long :
1227
		case TypeIds.T_double :
1228
			returnTypeSize = 2;
1229
			break;
1230
		default :
1231
			returnTypeSize = 1;
1232
			break;
1233
	}
1234
	this.fieldAccess(opcode, returnTypeSize, declaringClass.constantPoolName(), fieldBinding.name, returnType.signature());
1235
}
1236
1237
private void fieldAccess(byte opcode, int returnTypeSize, char[] declaringClass, char[] fieldName, char[] signature) {
1238
	this.countLabels = 0;
1239
	switch(opcode) {
1240
		case Opcodes.OPC_getfield :
1241
			if (returnTypeSize == 2) {
1242
				this.stackDepth++;
1243
			}
1244
			break;
1245
		case Opcodes.OPC_getstatic :
1246
			if (returnTypeSize == 2) {
1247
				this.stackDepth += 2;
1248
			} else {
1249
				this.stackDepth++;
1250
			}
1251
			break;
1252
		case Opcodes.OPC_putfield :
1253
			if (returnTypeSize == 2) {
1254
				this.stackDepth -= 3;
1255
			} else {
1256
				this.stackDepth -= 2;
1257
			}
1258
			break;
1259
		case Opcodes.OPC_putstatic :
1260
			if (returnTypeSize == 2) {
1261
				this.stackDepth -= 2;
1262
			} else {
1263
				this.stackDepth--;
1264
			}
1265
	}
1266
	if (this.stackDepth > this.stackMax) {
1267
		this.stackMax = this.stackDepth;
1268
	}
1269
	if (this.classFileOffset + 2 >= this.bCodeStream.length) {
1270
		resizeByteArray();
1271
	}
1272
	this.position++;
1273
	this.bCodeStream[this.classFileOffset++] = opcode;
1274
	writeUnsignedShort(this.constantPool.literalIndexForField(declaringClass, fieldName, signature));
1275
}
1276
1217
public void fload(int iArg) {
1277
public void fload(int iArg) {
1218
	this.countLabels = 0;
1278
	this.countLabels = 0;
1219
	this.stackDepth++;
1279
	this.stackDepth++;
Lines 1641-1647 Link Here
1641
	} else {
1701
	} else {
1642
		BranchLabel endLabel = new BranchLabel(this);
1702
		BranchLabel endLabel = new BranchLabel(this);
1643
		if (syntheticFieldBinding != null) { // non interface case
1703
		if (syntheticFieldBinding != null) { // non interface case
1644
			getstatic(syntheticFieldBinding);
1704
			fieldAccess(Opcodes.OPC_getstatic, syntheticFieldBinding, null /* default declaringClass */);
1645
			dup();
1705
			dup();
1646
			ifnonnull(endLabel);
1706
			ifnonnull(endLabel);
1647
			pop();
1707
			pop();
Lines 1684-1690 Link Here
1684
1744
1685
		if (syntheticFieldBinding != null) { // non interface case
1745
		if (syntheticFieldBinding != null) { // non interface case
1686
			dup();
1746
			dup();
1687
			putstatic(syntheticFieldBinding);
1747
			fieldAccess(Opcodes.OPC_putstatic, syntheticFieldBinding, null /* default declaringClass */);
1688
		}
1748
		}
1689
		goto_(endLabel);
1749
		goto_(endLabel);
1690
1750
Lines 1877-1933 Link Here
1877
	invokeAccessibleObjectSetAccessible();
1937
	invokeAccessibleObjectSetAccessible();
1878
}
1938
}
1879
1939
1880
private void generateFieldAccess(byte opcode, int returnTypeSize, char[] declaringClass, char[] name, char[] signature) {
1881
	this.countLabels = 0;
1882
	switch(opcode) {
1883
		case Opcodes.OPC_getfield :
1884
			if (returnTypeSize == 2) {
1885
				this.stackDepth++;
1886
			}
1887
			break;
1888
		case Opcodes.OPC_getstatic :
1889
			if (returnTypeSize == 2) {
1890
				this.stackDepth += 2;
1891
			} else {
1892
				this.stackDepth++;
1893
			}
1894
			break;
1895
		case Opcodes.OPC_putfield :
1896
			if (returnTypeSize == 2) {
1897
				this.stackDepth -= 3;
1898
			} else {
1899
				this.stackDepth -= 2;
1900
			}
1901
			break;
1902
		case Opcodes.OPC_putstatic :
1903
			if (returnTypeSize == 2) {
1904
				this.stackDepth -= 2;
1905
			} else {
1906
				this.stackDepth--;
1907
			}
1908
	}
1909
	if (this.stackDepth > this.stackMax) {
1910
		this.stackMax = this.stackDepth;
1911
	}
1912
	if (this.classFileOffset + 2 >= this.bCodeStream.length) {
1913
		resizeByteArray();
1914
	}
1915
	this.position++;
1916
	this.bCodeStream[this.classFileOffset++] = opcode;
1917
	writeUnsignedShort(this.constantPool.literalIndexForField(declaringClass, name, signature));
1918
}
1919
1920
private void generateFieldAccess(byte opcode, int returnTypeSize, ReferenceBinding binding, char[] name, TypeBinding type) {
1921
	if (binding.isNestedType()) {
1922
		this.classFile.recordInnerClasses(binding);
1923
	}
1924
	TypeBinding leafComponentType = type.leafComponentType();
1925
	if (leafComponentType.isNestedType()) {
1926
		this.classFile.recordInnerClasses(leafComponentType);
1927
	}
1928
	this.generateFieldAccess(opcode, returnTypeSize, binding.constantPoolName(), name, type.signature());
1929
}
1930
1931
/**
1940
/**
1932
 * Generates the sequence of instructions which will perform the conversion of the expression
1941
 * Generates the sequence of instructions which will perform the conversion of the expression
1933
 * on the stack into a different type (e.g. long l = someInt; --> i2l must be inserted).
1942
 * on the stack into a different type (e.g. long l = someInt; --> i2l must be inserted).
Lines 2251-2264 Link Here
2251
	} else if (mappingSequence[0] instanceof FieldBinding) {
2260
	} else if (mappingSequence[0] instanceof FieldBinding) {
2252
		FieldBinding fieldBinding = (FieldBinding) mappingSequence[0];
2261
		FieldBinding fieldBinding = (FieldBinding) mappingSequence[0];
2253
		aload_0();
2262
		aload_0();
2254
		getfield(fieldBinding);
2263
		fieldAccess(Opcodes.OPC_getfield, fieldBinding, null /* default declaringClass */);
2255
	} else {
2264
	} else {
2256
		load((LocalVariableBinding) mappingSequence[0]);
2265
		load((LocalVariableBinding) mappingSequence[0]);
2257
	}
2266
	}
2258
	for (int i = 1, length = mappingSequence.length; i < length; i++) {
2267
	for (int i = 1, length = mappingSequence.length; i < length; i++) {
2259
		if (mappingSequence[i] instanceof FieldBinding) {
2268
		if (mappingSequence[i] instanceof FieldBinding) {
2260
			FieldBinding fieldBinding = (FieldBinding) mappingSequence[i];
2269
			FieldBinding fieldBinding = (FieldBinding) mappingSequence[i];
2261
			getfield(fieldBinding);
2270
			fieldAccess(Opcodes.OPC_getfield, fieldBinding, null /* default declaringClass */);
2262
		} else {
2271
		} else {
2263
			invoke(Opcodes.OPC_invokestatic, (MethodBinding) mappingSequence[i], null /* default declaringClass */);
2272
			invoke(Opcodes.OPC_invokestatic, (MethodBinding) mappingSequence[i], null /* default declaringClass */);
2264
		}
2273
		}
Lines 2348-2365 Link Here
2348
		for (int i = 0; i < (syntheticArguments == null ? 0 : syntheticArguments.length); i++) {
2357
		for (int i = 0; i < (syntheticArguments == null ? 0 : syntheticArguments.length); i++) {
2349
			TypeBinding type;
2358
			TypeBinding type;
2350
			load((type = syntheticArguments[i].type), resolvedPosition);
2359
			load((type = syntheticArguments[i].type), resolvedPosition);
2351
			if ((type == TypeBinding.DOUBLE) || (type == TypeBinding.LONG))
2360
			switch(type.id) {
2352
				resolvedPosition += 2;
2361
				case TypeIds.T_long :
2353
			else
2362
				case TypeIds.T_double :
2354
				resolvedPosition++;
2363
					resolvedPosition += 2;
2364
					break;
2365
				default :
2366
					resolvedPosition++;
2367
					break;
2368
			}
2355
		}
2369
		}
2356
	}
2370
	}
2357
	for (int i = 0; i < length; i++) {
2371
	for (int i = 0; i < length; i++) {
2358
		load(parameters[i], resolvedPosition);
2372
		TypeBinding parameter;
2359
		if ((parameters[i] == TypeBinding.DOUBLE) || (parameters[i] == TypeBinding.LONG))
2373
		load(parameter = parameters[i], resolvedPosition);
2360
			resolvedPosition += 2;
2374
		switch(parameter.id) {
2361
		else
2375
			case TypeIds.T_long :
2362
			resolvedPosition++;
2376
			case TypeIds.T_double :
2377
				resolvedPosition += 2;
2378
				break;
2379
			default :
2380
				resolvedPosition++;
2381
				break;
2382
		}
2363
	}
2383
	}
2364
2384
2365
	if (declaringClass.isNestedType()) {
2385
	if (declaringClass.isNestedType()) {
Lines 2367-2377 Link Here
2367
		SyntheticArgumentBinding[] syntheticArguments = nestedType.syntheticOuterLocalVariables();
2387
		SyntheticArgumentBinding[] syntheticArguments = nestedType.syntheticOuterLocalVariables();
2368
		for (int i = 0; i < (syntheticArguments == null ? 0 : syntheticArguments.length); i++) {
2388
		for (int i = 0; i < (syntheticArguments == null ? 0 : syntheticArguments.length); i++) {
2369
			TypeBinding type;
2389
			TypeBinding type;
2370
			load((type = syntheticArguments[i].type), resolvedPosition);
2390
			load(type = syntheticArguments[i].type, resolvedPosition);
2371
			if ((type == TypeBinding.DOUBLE) || (type == TypeBinding.LONG))
2391
			switch(type.id) {
2372
				resolvedPosition += 2;
2392
				case TypeIds.T_long :
2373
			else
2393
				case TypeIds.T_double :
2374
				resolvedPosition++;
2394
					resolvedPosition += 2;
2395
					break;
2396
				default :
2397
					resolvedPosition++;
2398
					break;
2399
			}			
2375
		}
2400
		}
2376
	}
2401
	}
2377
	invoke(Opcodes.OPC_invokespecial, constructorBinding, null /* default declaringClass */);
2402
	invoke(Opcodes.OPC_invokespecial, constructorBinding, null /* default declaringClass */);
Lines 2400-2410 Link Here
2400
//}
2425
//}
2401
public void generateSyntheticBodyForEnumValues(SyntheticMethodBinding methodBinding) {
2426
public void generateSyntheticBodyForEnumValues(SyntheticMethodBinding methodBinding) {
2402
	ClassScope scope = ((SourceTypeBinding)methodBinding.declaringClass).scope;
2427
	ClassScope scope = ((SourceTypeBinding)methodBinding.declaringClass).scope;
2403
	FieldBinding enumValuesSyntheticfield = scope.referenceContext.enumValuesSyntheticfield;
2404
	initializeMaxLocals(methodBinding);
2428
	initializeMaxLocals(methodBinding);
2405
	TypeBinding enumArray = methodBinding.returnType;
2429
	TypeBinding enumArray = methodBinding.returnType;
2406
2430
	fieldAccess(Opcodes.OPC_getstatic, scope.referenceContext.enumValuesSyntheticfield, null /* default declaringClass */);
2407
	getstatic(enumValuesSyntheticfield);
2408
	dup();
2431
	dup();
2409
	astore_0();
2432
	astore_0();
2410
	iconst_0();
2433
	iconst_0();
Lines 2425-2435 Link Here
2425
public void generateSyntheticBodyForFieldReadAccess(SyntheticMethodBinding accessBinding) {
2448
public void generateSyntheticBodyForFieldReadAccess(SyntheticMethodBinding accessBinding) {
2426
	initializeMaxLocals(accessBinding);
2449
	initializeMaxLocals(accessBinding);
2427
	FieldBinding fieldBinding = accessBinding.targetReadField;
2450
	FieldBinding fieldBinding = accessBinding.targetReadField;
2428
	if (fieldBinding.isStatic())
2451
	if (fieldBinding.isStatic()) {
2429
		getstatic(fieldBinding);
2452
		fieldAccess(Opcodes.OPC_getstatic, fieldBinding, null /* default declaringClass */);
2430
	else {
2453
	} else {
2431
		aload_0();
2454
		aload_0();
2432
		getfield(fieldBinding);
2455
		fieldAccess(Opcodes.OPC_getfield, fieldBinding, null /* default declaringClass */);
2433
	}
2456
	}
2434
	switch (fieldBinding.type.id) {
2457
	switch (fieldBinding.type.id) {
2435
//		case T_void :
2458
//		case T_void :
Lines 2461-2471 Link Here
2461
	FieldBinding fieldBinding = accessBinding.targetWriteField;
2484
	FieldBinding fieldBinding = accessBinding.targetWriteField;
2462
	if (fieldBinding.isStatic()) {
2485
	if (fieldBinding.isStatic()) {
2463
		load(fieldBinding.type, 0);
2486
		load(fieldBinding.type, 0);
2464
		putstatic(fieldBinding);
2487
		fieldAccess(Opcodes.OPC_putstatic, fieldBinding, null /* default declaringClass */);
2465
	} else {
2488
	} else {
2466
		aload_0();
2489
		aload_0();
2467
		load(fieldBinding.type, 1);
2490
		load(fieldBinding.type, 1);
2468
		putfield(fieldBinding);
2491
		fieldAccess(Opcodes.OPC_putfield, fieldBinding, null /* default declaringClass */);
2469
	}
2492
	}
2470
	return_();
2493
	return_();
2471
}
2494
}
Lines 2495-2504 Link Here
2495
	    } else {
2518
	    } else {
2496
			load(parameter, resolvedPosition);
2519
			load(parameter, resolvedPosition);
2497
		}
2520
		}
2498
		if ((parameter == TypeBinding.DOUBLE) || (parameter == TypeBinding.LONG))
2521
		switch(parameter.id) {
2499
			resolvedPosition += 2;
2522
			case TypeIds.T_long :
2500
		else
2523
			case TypeIds.T_double :
2501
			resolvedPosition++;
2524
				resolvedPosition += 2;
2525
				break;
2526
			default :
2527
				resolvedPosition++;
2528
				break;
2529
		}
2502
	}
2530
	}
2503
	if (targetMethod.isStatic())
2531
	if (targetMethod.isStatic())
2504
		invoke(Opcodes.OPC_invokestatic, targetMethod, null /* default declaringClass */);
2532
		invoke(Opcodes.OPC_invokestatic, targetMethod, null /* default declaringClass */);
Lines 2551-2557 Link Here
2551
	initializeMaxLocals(methodBinding);
2579
	initializeMaxLocals(methodBinding);
2552
	final BranchLabel nullLabel = new BranchLabel(this);
2580
	final BranchLabel nullLabel = new BranchLabel(this);
2553
	FieldBinding syntheticFieldBinding = methodBinding.targetReadField;
2581
	FieldBinding syntheticFieldBinding = methodBinding.targetReadField;
2554
	getstatic(syntheticFieldBinding);
2582
	fieldAccess(Opcodes.OPC_getstatic, syntheticFieldBinding, null /* default declaringClass */);
2555
	dup();
2583
	dup();
2556
	ifnull(nullLabel);
2584
	ifnull(nullLabel);
2557
	areturn();
2585
	areturn();
Lines 2575-2581 Link Here
2575
				final ExceptionLabel anyExceptionHandler = new ExceptionLabel(this, TypeBinding.LONG /* represents NoSuchFieldError*/);
2603
				final ExceptionLabel anyExceptionHandler = new ExceptionLabel(this, TypeBinding.LONG /* represents NoSuchFieldError*/);
2576
				anyExceptionHandler.placeStart();
2604
				anyExceptionHandler.placeStart();
2577
				aload_0();
2605
				aload_0();
2578
				getstatic(fieldBinding);
2606
				fieldAccess(Opcodes.OPC_getstatic, fieldBinding, null /* default declaringClass */);
2579
				invokeEnumOrdinal(enumBinding.constantPoolName());
2607
				invokeEnumOrdinal(enumBinding.constantPoolName());
2580
				this.generateInlinedValue(fieldBinding.id + 1); // zero should not be returned see bug 141810
2608
				this.generateInlinedValue(fieldBinding.id + 1); // zero should not be returned see bug 141810
2581
				iastore();
2609
				iastore();
Lines 2591-2597 Link Here
2591
	}
2619
	}
2592
	aload_0();
2620
	aload_0();
2593
	dup();
2621
	dup();
2594
	putstatic(syntheticFieldBinding);
2622
	fieldAccess(Opcodes.OPC_putstatic, syntheticFieldBinding, null /* default declaringClass */);
2595
	areturn();
2623
	areturn();
2596
	removeVariable(localVariableBinding);
2624
	removeVariable(localVariableBinding);
2597
}
2625
}
Lines 2868-2983 Link Here
2868
	return contents;
2896
	return contents;
2869
}
2897
}
2870
2898
2871
public void getfield(FieldBinding fieldBinding) {
2899
/**
2872
	int returnTypeSize = 1;
2900
 * Returns the type that should be substituted to original binding declaring class as the proper receiver type
2873
	if ((fieldBinding.type.id == TypeIds.T_double) || (fieldBinding.type.id == TypeIds.T_long)) {
2901
 * @param currentScope
2874
		returnTypeSize = 2;
2902
 * @param codegenBinding
2875
	}
2903
 * @param actualReceiverType
2876
	generateFieldAccess(
2904
 * @param isImplicitThisReceiver
2877
			Opcodes.OPC_getfield,
2905
 * @return the receiver type to use in constant pool
2878
			returnTypeSize,
2906
 */
2879
			fieldBinding.declaringClass,
2907
public static TypeBinding getConstantPoolDeclaringClass(Scope currentScope, FieldBinding codegenBinding, TypeBinding actualReceiverType, boolean isImplicitThisReceiver) {
2880
			fieldBinding.name,
2908
	ReferenceBinding constantPoolDeclaringClass = codegenBinding.declaringClass;
2881
			fieldBinding.type);
2909
	// if the binding declaring class is not visible, need special action
2910
	// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
2911
	// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
2912
	// and not from Object or implicit static field access.
2913
	if (constantPoolDeclaringClass != actualReceiverType.erasure()
2914
			&& !actualReceiverType.isArrayType()
2915
			&& constantPoolDeclaringClass != null // array.length
2916
			&& codegenBinding.constant() == Constant.NotAConstant) {
2917
		CompilerOptions options = currentScope.compilerOptions();
2918
		if ((options.targetJDK >= ClassFileConstants.JDK1_2
2919
					&& (options.complianceLevel >= ClassFileConstants.JDK1_4 || !(isImplicitThisReceiver && codegenBinding.isStatic()))
2920
					&& constantPoolDeclaringClass.id != TypeIds.T_JavaLangObject) // no change for Object fields
2921
				|| !constantPoolDeclaringClass.canBeSeenBy(currentScope)) {
2922
2923
			return actualReceiverType.erasure();
2924
		}
2925
	}	
2926
	return constantPoolDeclaringClass;
2882
}
2927
}
2883
2928
2929
/**
2930
 * Returns the type that should be substituted to original binding declaring class as the proper receiver type
2931
 * @param currentScope
2932
 * @param codegenBinding
2933
 * @param actualReceiverType
2934
 * @param isImplicitThisReceiver
2935
 * @param hasGenericCast
2936
 * @return the receiver type to use in constant pool
2937
 */
2938
public static TypeBinding getConstantPoolDeclaringClass(Scope currentScope, MethodBinding codegenBinding, TypeBinding actualReceiverType, boolean isImplicitThisReceiver, boolean hasGenericCast) {
2939
	TypeBinding constantPoolDeclaringClass = codegenBinding.declaringClass;
2940
	// Post 1.4.0 target, array clone() invocations are qualified with array type
2941
	// This is handled in array type #clone method binding resolution (see Scope and UpdatedMethodBinding)
2942
	if (codegenBinding == currentScope.environment().arrayClone) {
2943
		CompilerOptions options = currentScope.compilerOptions();
2944
		if (options.sourceLevel > ClassFileConstants.JDK1_4 ) {
2945
			constantPoolDeclaringClass = actualReceiverType.erasure();
2946
		}
2947
	} else {
2948
		// if the binding declaring class is not visible, need special action
2949
		// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
2950
		// NOTE: from target 1.2 on, method's declaring class is touched if any different from receiver type
2951
		// and not from Object or implicit static method call.
2952
		if (constantPoolDeclaringClass != actualReceiverType.erasure() && !hasGenericCast && !actualReceiverType.isArrayType()) {
2953
			CompilerOptions options = currentScope.compilerOptions();
2954
			if ((options.targetJDK >= ClassFileConstants.JDK1_2
2955
						&& (options.complianceLevel >= ClassFileConstants.JDK1_4 || !(isImplicitThisReceiver && codegenBinding.isStatic()))
2956
						&& codegenBinding.declaringClass.id != TypeIds.T_JavaLangObject) // no change for Object methods
2957
					|| !codegenBinding.declaringClass.canBeSeenBy(currentScope)) {
2958
				constantPoolDeclaringClass = actualReceiverType.erasure();
2959
			}
2960
		}				
2961
	}
2962
	return constantPoolDeclaringClass;
2963
}
2884
protected int getPosition() {
2964
protected int getPosition() {
2885
	return this.position;
2965
	return this.position;
2886
}
2966
}
2887
2967
2888
public void getstatic(FieldBinding fieldBinding) {
2889
	int returnTypeSize = 1;
2890
	if ((fieldBinding.type.id == TypeIds.T_double) || (fieldBinding.type.id == TypeIds.T_long)) {
2891
		returnTypeSize = 2;
2892
	}
2893
	generateFieldAccess(
2894
			Opcodes.OPC_getstatic,
2895
			returnTypeSize,
2896
			fieldBinding.declaringClass,
2897
			fieldBinding.name,
2898
			fieldBinding.type);
2899
}
2900
2901
public void getTYPE(int baseTypeID) {
2968
public void getTYPE(int baseTypeID) {
2902
	this.countLabels = 0;
2969
	this.countLabels = 0;
2903
	switch (baseTypeID) {
2970
	switch (baseTypeID) {
2904
		case TypeIds.T_byte :
2971
		case TypeIds.T_byte :
2905
			// getstatic: java.lang.Byte.TYPE
2972
			// getstatic: java.lang.Byte.TYPE
2906
			generateFieldAccess(
2973
			fieldAccess(
2907
					Opcodes.OPC_getstatic,
2974
					Opcodes.OPC_getstatic,
2908
					1,
2975
					1, // return type size
2909
					ConstantPool.JavaLangByteConstantPoolName,
2976
					ConstantPool.JavaLangByteConstantPoolName,
2910
					ConstantPool.TYPE,
2977
					ConstantPool.TYPE,
2911
					ConstantPool.JavaLangClassSignature);
2978
					ConstantPool.JavaLangClassSignature);
2912
			break;
2979
			break;
2913
		case TypeIds.T_short :
2980
		case TypeIds.T_short :
2914
			// getstatic: java.lang.Short.TYPE
2981
			// getstatic: java.lang.Short.TYPE
2915
			generateFieldAccess(
2982
			fieldAccess(
2916
					Opcodes.OPC_getstatic,
2983
					Opcodes.OPC_getstatic,
2917
					1,
2984
					1, // return type size
2918
					ConstantPool.JavaLangShortConstantPoolName,
2985
					ConstantPool.JavaLangShortConstantPoolName,
2919
					ConstantPool.TYPE,
2986
					ConstantPool.TYPE,
2920
					ConstantPool.JavaLangClassSignature);
2987
					ConstantPool.JavaLangClassSignature);
2921
			break;
2988
			break;
2922
		case TypeIds.T_char :
2989
		case TypeIds.T_char :
2923
			// getstatic: java.lang.Character.TYPE
2990
			// getstatic: java.lang.Character.TYPE
2924
			generateFieldAccess(
2991
			fieldAccess(
2925
					Opcodes.OPC_getstatic,
2992
					Opcodes.OPC_getstatic,
2926
					1,
2993
					1, // return type size
2927
					ConstantPool.JavaLangCharacterConstantPoolName,
2994
					ConstantPool.JavaLangCharacterConstantPoolName,
2928
					ConstantPool.TYPE,
2995
					ConstantPool.TYPE,
2929
					ConstantPool.JavaLangClassSignature);
2996
					ConstantPool.JavaLangClassSignature);
2930
			break;
2997
			break;
2931
		case TypeIds.T_int :
2998
		case TypeIds.T_int :
2932
			// getstatic: java.lang.Integer.TYPE
2999
			// getstatic: java.lang.Integer.TYPE
2933
			generateFieldAccess(
3000
			fieldAccess(
2934
					Opcodes.OPC_getstatic,
3001
					Opcodes.OPC_getstatic,
2935
					1,
3002
					1, // return type size
2936
					ConstantPool.JavaLangIntegerConstantPoolName,
3003
					ConstantPool.JavaLangIntegerConstantPoolName,
2937
					ConstantPool.TYPE,
3004
					ConstantPool.TYPE,
2938
					ConstantPool.JavaLangClassSignature);
3005
					ConstantPool.JavaLangClassSignature);
2939
			break;
3006
			break;
2940
		case TypeIds.T_long :
3007
		case TypeIds.T_long :
2941
			// getstatic: java.lang.Long.TYPE
3008
			// getstatic: java.lang.Long.TYPE
2942
			generateFieldAccess(
3009
			fieldAccess(
2943
					Opcodes.OPC_getstatic,
3010
					Opcodes.OPC_getstatic,
2944
					1,
3011
					1, // return type size
2945
					ConstantPool.JavaLangLongConstantPoolName,
3012
					ConstantPool.JavaLangLongConstantPoolName,
2946
					ConstantPool.TYPE,
3013
					ConstantPool.TYPE,
2947
					ConstantPool.JavaLangClassSignature);
3014
					ConstantPool.JavaLangClassSignature);
2948
			break;
3015
			break;
2949
		case TypeIds.T_float :
3016
		case TypeIds.T_float :
2950
			// getstatic: java.lang.Float.TYPE
3017
			// getstatic: java.lang.Float.TYPE
2951
			generateFieldAccess(
3018
			fieldAccess(
2952
					Opcodes.OPC_getstatic,
3019
					Opcodes.OPC_getstatic,
2953
					1,
3020
					1, // return type size
2954
					ConstantPool.JavaLangFloatConstantPoolName,
3021
					ConstantPool.JavaLangFloatConstantPoolName,
2955
					ConstantPool.TYPE,
3022
					ConstantPool.TYPE,
2956
					ConstantPool.JavaLangClassSignature);
3023
					ConstantPool.JavaLangClassSignature);
2957
			break;
3024
			break;
2958
		case TypeIds.T_double :
3025
		case TypeIds.T_double :
2959
			// getstatic: java.lang.Double.TYPE
3026
			// getstatic: java.lang.Double.TYPE
2960
			generateFieldAccess(
3027
			fieldAccess(
2961
					Opcodes.OPC_getstatic,
3028
					Opcodes.OPC_getstatic,
2962
					1,
3029
					1, // return type size
2963
					ConstantPool.JavaLangDoubleConstantPoolName,
3030
					ConstantPool.JavaLangDoubleConstantPoolName,
2964
					ConstantPool.TYPE,
3031
					ConstantPool.TYPE,
2965
					ConstantPool.JavaLangClassSignature);
3032
					ConstantPool.JavaLangClassSignature);
2966
			break;
3033
			break;
2967
		case TypeIds.T_boolean :
3034
		case TypeIds.T_boolean :
2968
			// getstatic: java.lang.Boolean.TYPE
3035
			// getstatic: java.lang.Boolean.TYPE
2969
			generateFieldAccess(
3036
			fieldAccess(
2970
					Opcodes.OPC_getstatic,
3037
					Opcodes.OPC_getstatic,
2971
					1,
3038
					1, // return type size
2972
					ConstantPool.JavaLangBooleanConstantPoolName,
3039
					ConstantPool.JavaLangBooleanConstantPoolName,
2973
					ConstantPool.TYPE,
3040
					ConstantPool.TYPE,
2974
					ConstantPool.JavaLangClassSignature);
3041
					ConstantPool.JavaLangClassSignature);
2975
			break;
3042
			break;
2976
		case TypeIds.T_void :
3043
		case TypeIds.T_void :
2977
			// getstatic: java.lang.Void.TYPE
3044
			// getstatic: java.lang.Void.TYPE
2978
			generateFieldAccess(
3045
			fieldAccess(
2979
					Opcodes.OPC_getstatic,
3046
					Opcodes.OPC_getstatic,
2980
					1,
3047
					1, // return type size
2981
					ConstantPool.JavaLangVoidConstantPoolName,
3048
					ConstantPool.JavaLangVoidConstantPoolName,
2982
					ConstantPool.TYPE,
3049
					ConstantPool.TYPE,
2983
					ConstantPool.JavaLangClassSignature);
3050
					ConstantPool.JavaLangClassSignature);
Lines 3726-3731 Link Here
3726
	writeUnsignedShort(this.constantPool.literalIndexForType(typeBinding));
3793
	writeUnsignedShort(this.constantPool.literalIndexForType(typeBinding));
3727
}
3794
}
3728
3795
3796
protected void invoke(byte opcode, int receiverAndArgsSize, int returnTypeSize, char[] declaringClass, char[] selector, char[] signature) {
3797
	this.countLabels = 0;
3798
	if (opcode == Opcodes.OPC_invokeinterface) {
3799
		// invokeinterface
3800
		if (this.classFileOffset + 4 >= this.bCodeStream.length) {
3801
			resizeByteArray();
3802
		}
3803
		this.position +=3;
3804
		this.bCodeStream[this.classFileOffset++] = opcode;
3805
		writeUnsignedShort(this.constantPool.literalIndexForMethod(declaringClass, selector, signature, true));
3806
		this.bCodeStream[this.classFileOffset++] = (byte) receiverAndArgsSize;
3807
		this.bCodeStream[this.classFileOffset++] = 0;
3808
	} else {
3809
		// invokespecial
3810
		// invokestatic
3811
		// invokevirtual
3812
		if (this.classFileOffset + 2 >= this.bCodeStream.length) {
3813
			resizeByteArray();
3814
		}
3815
		this.position++;
3816
		this.bCodeStream[this.classFileOffset++] = opcode;
3817
		writeUnsignedShort(this.constantPool.literalIndexForMethod(declaringClass, selector, signature, false));
3818
	}
3819
	this.stackDepth += returnTypeSize - receiverAndArgsSize;
3820
	if (this.stackDepth > this.stackMax) {
3821
		this.stackMax = this.stackDepth;
3822
	}
3823
}
3824
3729
public void invoke(byte opcode, MethodBinding methodBinding, TypeBinding declaringClass) {
3825
public void invoke(byte opcode, MethodBinding methodBinding, TypeBinding declaringClass) {
3730
	if (declaringClass == null) declaringClass = methodBinding.declaringClass;
3826
	if (declaringClass == null) declaringClass = methodBinding.declaringClass;
3731
    if (declaringClass.isNestedType()) {
3827
    if (declaringClass.isNestedType()) {
Lines 3808-3842 Link Here
3808
			methodBinding.signature(this.classFile));
3904
			methodBinding.signature(this.classFile));
3809
}
3905
}
3810
3906
3811
protected void invoke(byte opcode, int receiverAndArgsSize, int returnTypeSize, char[] declaringClass, char[] selector, char[] signature) {
3812
	this.countLabels = 0;
3813
	if (opcode == Opcodes.OPC_invokeinterface) {
3814
		// invokeinterface
3815
		if (this.classFileOffset + 4 >= this.bCodeStream.length) {
3816
			resizeByteArray();
3817
		}
3818
		this.position +=3;
3819
		this.bCodeStream[this.classFileOffset++] = opcode;
3820
		writeUnsignedShort(this.constantPool.literalIndexForMethod(declaringClass, selector, signature, true));
3821
		this.bCodeStream[this.classFileOffset++] = (byte) receiverAndArgsSize;
3822
		this.bCodeStream[this.classFileOffset++] = 0;
3823
	} else {
3824
		// invokespecial
3825
		// invokestatic
3826
		// invokevirtual
3827
		if (this.classFileOffset + 2 >= this.bCodeStream.length) {
3828
			resizeByteArray();
3829
		}
3830
		this.position++;
3831
		this.bCodeStream[this.classFileOffset++] = opcode;
3832
		writeUnsignedShort(this.constantPool.literalIndexForMethod(declaringClass, selector, signature, false));
3833
	}
3834
	this.stackDepth += returnTypeSize - receiverAndArgsSize;
3835
	if (this.stackDepth > this.stackMax) {
3836
		this.stackMax = this.stackDepth;
3837
	}
3838
}
3839
3840
protected void invokeAccessibleObjectSetAccessible() {
3907
protected void invokeAccessibleObjectSetAccessible() {
3841
	// invokevirtual: java.lang.reflect.AccessibleObject.setAccessible(Z)V;
3908
	// invokevirtual: java.lang.reflect.AccessibleObject.setAccessible(Z)V;
3842
	invoke(
3909
	invoke(
Lines 5115-5121 Link Here
5115
	load(localBinding.type, localBinding.resolvedPosition);
5182
	load(localBinding.type, localBinding.resolvedPosition);
5116
}
5183
}
5117
5184
5118
public final void load(TypeBinding typeBinding, int resolvedPosition) {
5185
protected final void load(TypeBinding typeBinding, int resolvedPosition) {
5119
	this.countLabels = 0;
5186
	this.countLabels = 0;
5120
	// Using dedicated int bytecode
5187
	// Using dedicated int bytecode
5121
	switch(typeBinding.id) {
5188
	switch(typeBinding.id) {
Lines 5658-5689 Link Here
5658
		this.stackMax = this.stackDepth;
5725
		this.stackMax = this.stackDepth;
5659
}
5726
}
5660
5727
5661
public void putfield(FieldBinding fieldBinding) {
5662
	int returnTypeSize = 1;
5663
	if ((fieldBinding.type.id == TypeIds.T_double) || (fieldBinding.type.id == TypeIds.T_long)) {
5664
		returnTypeSize = 2;
5665
	}
5666
	generateFieldAccess(
5667
			Opcodes.OPC_putfield,
5668
			returnTypeSize,
5669
			fieldBinding.declaringClass,
5670
			fieldBinding.name,
5671
			fieldBinding.type);
5672
}
5673
5674
public void putstatic(FieldBinding fieldBinding) {
5675
	int returnTypeSize = 1;
5676
	if ((fieldBinding.type.id == TypeIds.T_double) || (fieldBinding.type.id == TypeIds.T_long)) {
5677
		returnTypeSize = 2;
5678
	}
5679
	generateFieldAccess(
5680
			Opcodes.OPC_putstatic,
5681
			returnTypeSize,
5682
			fieldBinding.declaringClass,
5683
			fieldBinding.name,
5684
			fieldBinding.type);
5685
}
5686
5687
public void record(LocalVariableBinding local) {
5728
public void record(LocalVariableBinding local) {
5688
	if ((this.generateAttributes & (ClassFileConstants.ATTR_VARS
5729
	if ((this.generateAttributes & (ClassFileConstants.ATTR_VARS
5689
			| ClassFileConstants.ATTR_STACK_MAP_TABLE
5730
			| ClassFileConstants.ATTR_STACK_MAP_TABLE
(-)compiler/org/eclipse/jdt/internal/compiler/codegen/StackMapFrameCodeStream.java (-2 / +2 lines)
Lines 273-279 Link Here
273
		// use in CLDC mode
273
		// use in CLDC mode
274
		BranchLabel endLabel = new BranchLabel(this);
274
		BranchLabel endLabel = new BranchLabel(this);
275
		if (syntheticFieldBinding != null) { // non interface case
275
		if (syntheticFieldBinding != null) { // non interface case
276
			getstatic(syntheticFieldBinding);
276
			fieldAccess(Opcodes.OPC_getstatic, syntheticFieldBinding, null /* default declaringClass */);
277
			dup();
277
			dup();
278
			ifnonnull(endLabel);
278
			ifnonnull(endLabel);
279
			pop();
279
			pop();
Lines 316-322 Link Here
316
316
317
		if (syntheticFieldBinding != null) { // non interface case
317
		if (syntheticFieldBinding != null) { // non interface case
318
			dup();
318
			dup();
319
			putstatic(syntheticFieldBinding);
319
			fieldAccess(Opcodes.OPC_putstatic, syntheticFieldBinding, null /* default declaringClass */);
320
		}
320
		}
321
		int fromPC = this.position;
321
		int fromPC = this.position;
322
		goto_(endLabel);
322
		goto_(endLabel);
(-)codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMemberAccess.java (-4 / +4 lines)
Lines 53-61 Link Here
53
53
54
	public TypeBinding resolveType(BlockScope scope) {
54
	public TypeBinding resolveType(BlockScope scope) {
55
55
56
		this.receiverType = this.receiver.resolveType(scope);
56
		this.actualReceiverType = this.receiver.resolveType(scope);
57
57
58
		if ((this.receiverType == null || !this.receiverType.isValidBinding()) && this.receiver instanceof MessageSend) {
58
		if ((this.actualReceiverType == null || !this.actualReceiverType.isValidBinding()) && this.receiver instanceof MessageSend) {
59
			MessageSend messageSend = (MessageSend) this.receiver;
59
			MessageSend messageSend = (MessageSend) this.receiver;
60
			if(messageSend.receiver instanceof ThisReference) {
60
			if(messageSend.receiver instanceof ThisReference) {
61
				Expression[] arguments = messageSend.arguments;
61
				Expression[] arguments = messageSend.arguments;
Lines 73-82 Link Here
73
			}
73
			}
74
		}
74
		}
75
75
76
		if (this.receiverType == null || this.receiverType.isBaseType() || !this.receiverType.isValidBinding())
76
		if (this.actualReceiverType == null || this.actualReceiverType.isBaseType() || !this.actualReceiverType.isValidBinding())
77
			throw new CompletionNodeFound();
77
			throw new CompletionNodeFound();
78
		else
78
		else
79
			throw new CompletionNodeFound(this, this.receiverType, scope);
79
			throw new CompletionNodeFound(this, this.actualReceiverType, scope);
80
		// array types are passed along to find the length field
80
		// array types are passed along to find the length field
81
	}
81
	}
82
}
82
}
(-)codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnJavadocFieldReference.java (-3 / +3 lines)
Lines 93-103 Link Here
93
93
94
		// Resolve only receiver
94
		// Resolve only receiver
95
		if (this.receiver == null) {
95
		if (this.receiver == null) {
96
			this.receiverType = scope.enclosingSourceType();
96
			this.actualReceiverType = scope.enclosingSourceType();
97
		} else if (scope.kind == Scope.CLASS_SCOPE) {
97
		} else if (scope.kind == Scope.CLASS_SCOPE) {
98
			this.receiverType = this.receiver.resolveType((ClassScope) scope);
98
			this.actualReceiverType = this.receiver.resolveType((ClassScope) scope);
99
		} else {
99
		} else {
100
			this.receiverType = this.receiver.resolveType((BlockScope)scope);
100
			this.actualReceiverType = this.receiver.resolveType((BlockScope)scope);
101
		}
101
		}
102
		return null;
102
		return null;
103
	}
103
	}
(-)eval/org/eclipse/jdt/internal/eval/CodeSnippetQualifiedNameReference.java (-349 / +317 lines)
Lines 19-37 Link Here
19
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
19
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
20
import org.eclipse.jdt.internal.compiler.codegen.Opcodes;
20
import org.eclipse.jdt.internal.compiler.codegen.Opcodes;
21
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
21
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
22
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
23
import org.eclipse.jdt.internal.compiler.impl.Constant;
22
import org.eclipse.jdt.internal.compiler.impl.Constant;
24
import org.eclipse.jdt.internal.compiler.lookup.Binding;
23
import org.eclipse.jdt.internal.compiler.lookup.Binding;
25
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
24
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
26
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
27
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
25
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
28
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
26
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
27
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
29
import org.eclipse.jdt.internal.compiler.lookup.ProblemBinding;
28
import org.eclipse.jdt.internal.compiler.lookup.ProblemBinding;
30
import org.eclipse.jdt.internal.compiler.lookup.ProblemFieldBinding;
29
import org.eclipse.jdt.internal.compiler.lookup.ProblemFieldBinding;
31
import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
30
import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
32
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
31
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
33
import org.eclipse.jdt.internal.compiler.lookup.Scope;
34
import org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding;
35
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
32
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
36
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
33
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
37
import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
34
import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
Lines 50-323 Link Here
50
	super(sources, positions, sourceStart, sourceEnd);
47
	super(sources, positions, sourceStart, sourceEnd);
51
	this.evaluationContext = evaluationContext;
48
	this.evaluationContext = evaluationContext;
52
}
49
}
53
/**
54
 * Check and/or redirect the field access to the delegate receiver if any
55
 */
56
public TypeBinding checkFieldAccess(BlockScope scope) {
57
	// check for forward references
58
	this.bits &= ~RestrictiveFlagMASK; // clear bits
59
	this.bits |= Binding.FIELD;
60
	return getOtherFieldBindings(scope);
61
}
62
public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) {
63
64
	FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream);
65
	if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
66
		// the last field access is a write access
67
		assignment.expression.generateCode(currentScope, codeStream, true);
68
		fieldStore(codeStream, lastFieldBinding, null, valueRequired);
69
	} else {
70
		codeStream.generateEmulationForField(lastFieldBinding);
71
		codeStream.swap();
72
		assignment.expression.generateCode(currentScope, codeStream, true);
73
		if (valueRequired) {
74
			if ((lastFieldBinding.type == TypeBinding.LONG) || (lastFieldBinding.type == TypeBinding.DOUBLE)) {
75
				codeStream.dup2_x2();
76
			} else {
77
				codeStream.dup_x2();
78
			}
79
		}
80
		codeStream.generateEmulatedWriteAccessForField(lastFieldBinding);
81
	}
82
	if (valueRequired) {
83
		codeStream.generateImplicitConversion(assignment.implicitConversion);
84
	}
85
}
86
public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
50
public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
87
	int pc = codeStream.position;
51
	int pc = codeStream.position;
88
	if (this.constant != Constant.NotAConstant) {
52
	if ((this.bits & Binding.VARIABLE) == 0) { // nothing to do if type ref
89
		if (valueRequired) {
53
		codeStream.recordPositionsFrom(pc, this.sourceStart);
90
			codeStream.generateConstant(this.constant, this.implicitConversion);
54
		return;
91
		}
55
	}
92
	} else {
56
	FieldBinding lastFieldBinding = this.otherBindings == null ? (FieldBinding) this.binding : this.otherBindings[this.otherBindings.length-1];
93
		FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream);
57
	if (lastFieldBinding.canBeSeenBy(getFinalReceiverType(), this, currentScope)) {
94
		if (valueRequired) {
58
		super.generateCode(currentScope, codeStream, valueRequired);
95
			if (lastFieldBinding.declaringClass == null) { // array length
59
		return;
96
				codeStream.arraylength();
60
	}
97
				codeStream.generateImplicitConversion(this.implicitConversion);
61
	lastFieldBinding = generateReadSequence(currentScope, codeStream);
98
			} else {
62
	if (lastFieldBinding != null) {
99
				Constant fieldConstant = lastFieldBinding.constant();
63
		boolean isStatic = lastFieldBinding.isStatic();
100
				if (fieldConstant != Constant.NotAConstant) {
64
		Constant fieldConstant = lastFieldBinding.constant();
101
					if (!lastFieldBinding.isStatic()){
65
		if (fieldConstant != Constant.NotAConstant) {
102
						codeStream.invokeObjectGetClass();
66
			if (!isStatic){
67
				codeStream.invokeObjectGetClass();
68
				codeStream.pop();
69
			}
70
			if (valueRequired) { // inline the last field constant
71
				codeStream.generateConstant(fieldConstant, this.implicitConversion);
72
			}
73
		} else {
74
			boolean isFirst = lastFieldBinding == this.binding
75
											&& (this.indexOfFirstFieldBinding == 1 || lastFieldBinding.declaringClass == currentScope.enclosingReceiverType())
76
											&& this.otherBindings == null; // could be dup: next.next.next
77
			TypeBinding requiredGenericCast = getGenericCast(this.otherBindings == null ? 0 : this.otherBindings.length);
78
			if (valueRequired
79
					|| (!isFirst && currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4)
80
					|| ((this.implicitConversion & TypeIds.UNBOXING) != 0)
81
					|| requiredGenericCast != null) {
82
				int lastFieldPc = codeStream.position;
83
				if (lastFieldBinding.declaringClass == null) { // array length
84
					codeStream.arraylength();
85
					if (valueRequired) {
86
						codeStream.generateImplicitConversion(this.implicitConversion);
87
					} else {
88
						// could occur if !valueRequired but compliance >= 1.4
103
						codeStream.pop();
89
						codeStream.pop();
104
					}
90
					}
105
					// inline the last field constant
106
					codeStream.generateConstant(fieldConstant, this.implicitConversion);
107
				} else {
91
				} else {
108
					if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
92
					codeStream.generateEmulatedReadAccessForField(lastFieldBinding);
109
						if (lastFieldBinding.isStatic()) {
93
					if (requiredGenericCast != null) codeStream.checkcast(requiredGenericCast);
110
							codeStream.getstatic(lastFieldBinding);
94
					if (valueRequired) {
111
						} else {
95
						codeStream.generateImplicitConversion(this.implicitConversion);
112
							codeStream.getfield(lastFieldBinding);
113
						}
114
					} else {
96
					} else {
115
						codeStream.generateEmulatedReadAccessForField(lastFieldBinding);
97
						boolean isUnboxing = (this.implicitConversion & TypeIds.UNBOXING) != 0;
98
						// conversion only generated if unboxing
99
						if (isUnboxing) codeStream.generateImplicitConversion(this.implicitConversion);
100
						switch (isUnboxing ? postConversionType(currentScope).id : lastFieldBinding.type.id) {
101
							case T_long :
102
							case T_double :
103
								codeStream.pop2();
104
								break;
105
							default :
106
								codeStream.pop();
107
						}
116
					}
108
					}
117
					codeStream.generateImplicitConversion(this.implicitConversion);
118
				}
109
				}
119
			}
110
120
		} else {
111
				int fieldPosition = (int) (this.sourcePositions[this.sourcePositions.length - 1] >>> 32);
121
			if (lastFieldBinding != null && !lastFieldBinding.isStatic()){
112
				codeStream.recordPositionsFrom(lastFieldPc, fieldPosition);
122
				codeStream.invokeObjectGetClass(); // perform null check
113
			} else {
123
				codeStream.pop();
114
				if (!isStatic){
115
					codeStream.invokeObjectGetClass(); // perform null check
116
					codeStream.pop();
117
				}
124
			}
118
			}
125
		}
119
		}
126
	}
120
	}
127
	codeStream.recordPositionsFrom(pc, this.sourceStart);
121
	codeStream.recordPositionsFrom(pc, this.sourceStart);
128
}
122
}
129
public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
123
/**
130
124
 * Check and/or redirect the field access to the delegate receiver if any
131
	FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream);
125
 */
132
	if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
126
public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) {
133
		if (lastFieldBinding.isStatic()){
127
    FieldBinding lastFieldBinding = this.otherBindings == null ? (FieldBinding) this.binding : this.otherBindings[this.otherBindings.length-1];
134
			codeStream.getstatic(lastFieldBinding);
128
	if (lastFieldBinding.canBeSeenBy(getFinalReceiverType(), this, currentScope)) {
135
		} else {
129
		super.generateAssignment(currentScope, codeStream, assignment, valueRequired);
136
			codeStream.dup();
130
		return;
137
			codeStream.getfield(lastFieldBinding);
131
	}
138
		}
132
	lastFieldBinding = generateReadSequence(currentScope, codeStream);
139
		// the last field access is a write access
133
	codeStream.generateEmulationForField(lastFieldBinding);
140
		// perform the actual compound operation
134
	codeStream.swap();
141
		int operationTypeID;
135
	assignment.expression.generateCode(currentScope, codeStream, true);
142
		switch(operationTypeID = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) {
136
	if (valueRequired) {
143
			case T_JavaLangString :
137
		switch (lastFieldBinding.type.id) {
144
			case T_JavaLangObject :
138
			case TypeIds.T_long :
145
			case T_undefined :
139
			case TypeIds.T_double :
146
				codeStream.generateStringConcatenationAppend(currentScope, null, expression);
140
				codeStream.dup2_x2();
147
				break;
141
				break;
148
			default :
142
			default :
149
				// promote the array reference to the suitable operation type
143
				codeStream.dup_x2();
150
				codeStream.generateImplicitConversion(this.implicitConversion);
144
			break;	
151
				// generate the increment value (will by itself  be promoted to the operation value)
145
		}		
152
				if (expression == IntLiteral.One){ // prefix operation
146
	}
153
					codeStream.generateConstant(expression.constant, this.implicitConversion);
147
	codeStream.generateEmulatedWriteAccessForField(lastFieldBinding);
154
				} else {
148
	if (valueRequired) {
155
					expression.generateCode(currentScope, codeStream, true);
149
		codeStream.generateImplicitConversion(assignment.implicitConversion);
156
				}
150
	}
157
				// perform the operation
151
}
158
				codeStream.sendOperator(operator, operationTypeID);
152
159
				// cast the value back to the array reference type
153
public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
160
				codeStream.generateImplicitConversion(assignmentImplicitConversion);
154
    FieldBinding lastFieldBinding = this.otherBindings == null ? (FieldBinding) this.binding : this.otherBindings[this.otherBindings.length-1];
161
		}
155
	if (lastFieldBinding.canBeSeenBy(getFinalReceiverType(), this, currentScope)) {
162
		// actual assignment
156
		super.generateCompoundAssignment(currentScope, codeStream, expression, operator, assignmentImplicitConversion, valueRequired);
163
		fieldStore(codeStream, lastFieldBinding, null, valueRequired);
157
		return;
158
	}
159
	lastFieldBinding = generateReadSequence(currentScope, codeStream);
160
	if (lastFieldBinding.isStatic()){
161
		codeStream.generateEmulationForField(lastFieldBinding);
162
		codeStream.swap();
163
		codeStream.aconst_null();
164
		codeStream.swap();
165
		codeStream.generateEmulatedReadAccessForField(lastFieldBinding);
164
	} else {
166
	} else {
165
		if (lastFieldBinding.isStatic()){
167
		codeStream.generateEmulationForField(lastFieldBinding);
166
			codeStream.generateEmulationForField(lastFieldBinding);
168
		codeStream.swap();
167
			codeStream.swap();
169
		codeStream.dup();
168
			codeStream.aconst_null();
169
			codeStream.swap();
170
170
171
			codeStream.generateEmulatedReadAccessForField(lastFieldBinding);
171
		codeStream.generateEmulatedReadAccessForField(lastFieldBinding);
172
		} else {
172
	}
173
			codeStream.generateEmulationForField(lastFieldBinding);
173
	// the last field access is a write access
174
			codeStream.swap();
174
	// perform the actual compound operation
175
			codeStream.dup();
175
	int operationTypeID;
176
176
	if ((operationTypeID = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) == T_JavaLangString) {
177
			codeStream.generateEmulatedReadAccessForField(lastFieldBinding);
177
		codeStream.generateStringConcatenationAppend(currentScope, null, expression);
178
		}
178
	} else {
179
		// the last field access is a write access
179
		// promote the array reference to the suitable operation type
180
		// perform the actual compound operation
180
		codeStream.generateImplicitConversion(this.implicitConversion);
181
		int operationTypeID;
181
		// generate the increment value (will by itself  be promoted to the operation value)
182
		if ((operationTypeID = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) == T_JavaLangString) {
182
		if (expression == IntLiteral.One){ // prefix operation
183
			codeStream.generateStringConcatenationAppend(currentScope, null, expression);
183
			codeStream.generateConstant(expression.constant, this.implicitConversion);
184
		} else {
184
		} else {
185
			// promote the array reference to the suitable operation type
185
			expression.generateCode(currentScope, codeStream, true);
186
			codeStream.generateImplicitConversion(this.implicitConversion);
186
		}
187
			// generate the increment value (will by itself  be promoted to the operation value)
187
		// perform the operation
188
			if (expression == IntLiteral.One){ // prefix operation
188
		codeStream.sendOperator(operator, operationTypeID);
189
				codeStream.generateConstant(expression.constant, this.implicitConversion);
189
		// cast the value back to the array reference type
190
			} else {
190
		codeStream.generateImplicitConversion(assignmentImplicitConversion);
191
				expression.generateCode(currentScope, codeStream, true);
191
	}
192
			}
192
	// actual assignment
193
			// perform the operation
193
194
			codeStream.sendOperator(operator, operationTypeID);
194
	// current stack is:
195
			// cast the value back to the array reference type
195
	// field receiver value
196
			codeStream.generateImplicitConversion(assignmentImplicitConversion);
196
	if (valueRequired) {
197
		}
197
		switch (lastFieldBinding.type.id) {
198
		// actual assignment
198
			case TypeIds.T_long :
199
199
			case TypeIds.T_double :
200
		// current stack is:
201
		// field receiver value
202
		if (valueRequired) {
203
			if ((lastFieldBinding.type == TypeBinding.LONG) || (lastFieldBinding.type == TypeBinding.DOUBLE)) {
204
				codeStream.dup2_x2();
200
				codeStream.dup2_x2();
205
			} else {
201
				break;
202
			default :
206
				codeStream.dup_x2();
203
				codeStream.dup_x2();
207
			}
204
			break;	
208
		}
205
		}
209
		// current stack is:
210
		// value field receiver value
211
		codeStream.generateEmulatedWriteAccessForField(lastFieldBinding);
212
	}
206
	}
207
	// current stack is:
208
	// value field receiver value
209
	codeStream.generateEmulatedWriteAccessForField(lastFieldBinding);
213
}
210
}
214
public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
211
public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
215
212
    FieldBinding lastFieldBinding = this.otherBindings == null ? (FieldBinding) this.binding : this.otherBindings[this.otherBindings.length-1];
216
    FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream);
213
	if (lastFieldBinding.canBeSeenBy(getFinalReceiverType(), this, currentScope)) {
217
	if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
214
		super.generatePostIncrement(currentScope, codeStream, postIncrement, valueRequired);
218
		SyntheticMethodBinding accessor =
215
		return;
219
			this.syntheticReadAccessors == null
216
	}
220
				? null
217
	lastFieldBinding = generateReadSequence(currentScope, codeStream);
221
				: this.syntheticReadAccessors[this.syntheticReadAccessors.length - 1];
218
	codeStream.generateEmulatedReadAccessForField(lastFieldBinding);
219
	if (valueRequired) {
220
		switch (lastFieldBinding.type.id) {
221
			case TypeIds.T_long :
222
			case TypeIds.T_double :
223
				codeStream.dup2();
224
				break;
225
			default :
226
				codeStream.dup();
227
			break;	
228
		}		
229
	}
230
	codeStream.generateEmulationForField(lastFieldBinding);
231
	if ((lastFieldBinding.type == TypeBinding.LONG) || (lastFieldBinding.type == TypeBinding.DOUBLE)) {
232
		codeStream.dup_x2();
233
		codeStream.pop();
222
		if (lastFieldBinding.isStatic()) {
234
		if (lastFieldBinding.isStatic()) {
223
			if (accessor == null) {
235
			codeStream.aconst_null();
224
				codeStream.getstatic(lastFieldBinding);
225
			} else {
226
				codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */);
227
			}
228
		} else {
236
		} else {
229
			codeStream.dup();
237
			generateReadSequence(currentScope, codeStream);
230
			if (accessor == null) {
231
				codeStream.getfield(lastFieldBinding);
232
			} else {
233
				codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */);
234
			}
235
		}
236
237
		TypeBinding requiredGenericCast = getGenericCast(this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length);
238
		if (requiredGenericCast != null) codeStream.checkcast(requiredGenericCast);
239
		codeStream.generateImplicitConversion(this.implicitConversion);
240
241
		// duplicate the old field value
242
		int operandType = this.implicitConversion & TypeIds.COMPILE_TYPE_MASK;
243
		if (valueRequired) {
244
			if (lastFieldBinding.isStatic()) {
245
				if (operandType == T_long || operandType == T_double) {
246
					codeStream.dup2();
247
				} else {
248
					codeStream.dup();
249
				}
250
			} else { // Stack:  [owner][old field value]  ---> [old field value][owner][old field value]
251
				if (operandType == T_long || operandType == T_double) {
252
					codeStream.dup2_x1();
253
				} else {
254
					codeStream.dup_x1();
255
				}
256
			}
257
		}
238
		}
258
		codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
239
		codeStream.dup_x2();
259
		codeStream.sendOperator(postIncrement.operator, operandType);
240
		codeStream.pop();
260
		codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion);
261
		fieldStore(codeStream, lastFieldBinding, this.syntheticWriteAccessor, false);
262
	} else {
241
	} else {
263
		codeStream.generateEmulatedReadAccessForField(lastFieldBinding);
242
		codeStream.dup_x1();
264
		if (valueRequired) {
243
		codeStream.pop();
265
			if ((lastFieldBinding.type == TypeBinding.LONG) || (lastFieldBinding.type == TypeBinding.DOUBLE)) {
244
		if (lastFieldBinding.isStatic()) {
266
				codeStream.dup2();
245
			codeStream.aconst_null();
267
			} else {
268
				codeStream.dup();
269
			}
270
		}
271
		codeStream.generateEmulationForField(lastFieldBinding);
272
		if ((lastFieldBinding.type == TypeBinding.LONG) || (lastFieldBinding.type == TypeBinding.DOUBLE)) {
273
			codeStream.dup_x2();
274
			codeStream.pop();
275
			if (lastFieldBinding.isStatic()) {
276
				codeStream.aconst_null();
277
			} else {
278
				generateReadSequence(currentScope, codeStream);
279
			}
280
			codeStream.dup_x2();
281
			codeStream.pop();
282
		} else {
246
		} else {
283
			codeStream.dup_x1();
247
			generateReadSequence(currentScope, codeStream);
284
			codeStream.pop();
285
			if (lastFieldBinding.isStatic()) {
286
				codeStream.aconst_null();
287
			} else {
288
				generateReadSequence(currentScope, codeStream);
289
			}
290
			codeStream.dup_x1();
291
			codeStream.pop();
292
		}
248
		}
293
		codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
249
		codeStream.dup_x1();
294
		codeStream.sendOperator(postIncrement.operator, lastFieldBinding.type.id);
250
		codeStream.pop();
295
		codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion);
296
		codeStream.generateEmulatedWriteAccessForField(lastFieldBinding);
297
	}
251
	}
252
	codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
253
	codeStream.sendOperator(postIncrement.operator, lastFieldBinding.type.id);
254
	codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion);
255
	codeStream.generateEmulatedWriteAccessForField(lastFieldBinding);
298
}
256
}
257
299
/*
258
/*
300
 * Generate code for all bindings (local and fields) excluding the last one, which may then be generated code
259
 * Generate code for all bindings (local and fields) excluding the last one, which may then be generated code
301
 * for a read or write access.
260
 * for a read or write access.
302
 */
261
 */
303
public FieldBinding generateReadSequence(BlockScope currentScope, CodeStream codeStream) {
262
public FieldBinding generateReadSequence(BlockScope currentScope, CodeStream codeStream) {
304
305
	// determine the rank until which we now we do not need any actual value for the field access
263
	// determine the rank until which we now we do not need any actual value for the field access
306
	int otherBindingsCount = this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length;
264
	int otherBindingsCount = this.otherBindings == null ? 0 : this.otherBindings.length;
307
	boolean needValue = otherBindingsCount == 0 || !this.otherBindings[0].isStatic();
265
	boolean needValue = otherBindingsCount == 0 || !this.otherBindings[0].isStatic();
308
	FieldBinding lastFieldBinding = null;
266
	FieldBinding lastFieldBinding;
309
	TypeBinding lastGenericCast = null;
267
	TypeBinding lastGenericCast;
310
268
	TypeBinding lastReceiverType;
269
	boolean complyTo14 = currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4;
270
	
311
	switch (this.bits & RestrictiveFlagMASK) {
271
	switch (this.bits & RestrictiveFlagMASK) {
312
		case Binding.FIELD :
272
		case Binding.FIELD :
313
			lastFieldBinding = (FieldBinding) this.codegenBinding;
273
			lastFieldBinding = ((FieldBinding) this.binding).original();
314
			lastGenericCast = this.genericCast;
274
			lastGenericCast = this.genericCast;
275
			lastReceiverType = this.actualReceiverType;
315
			// if first field is actually constant, we can inline it
276
			// if first field is actually constant, we can inline it
316
			if (lastFieldBinding.constant() != Constant.NotAConstant) {
277
			if (lastFieldBinding.constant() != Constant.NotAConstant) {
317
				break;
278
				break;
318
			}
279
			}
319
			if (needValue) {
280
			if (needValue) {
320
				if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
281
				if (lastFieldBinding.canBeSeenBy(this.actualReceiverType, this, currentScope)) {
321
					if (!lastFieldBinding.isStatic()) {
282
					if (!lastFieldBinding.isStatic()) {
322
						if ((this.bits & DepthMASK) != 0) {
283
						if ((this.bits & DepthMASK) != 0) {
323
							ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT);
284
							ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT);
Lines 343-350 Link Here
343
			}
304
			}
344
			break;
305
			break;
345
		case Binding.LOCAL : // reading the first local variable
306
		case Binding.LOCAL : // reading the first local variable
307
			lastFieldBinding = null;
308
			lastGenericCast = null;
309
			LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
310
			lastReceiverType = localBinding.type;
346
			if (!needValue) break; // no value needed
311
			if (!needValue) break; // no value needed
347
			LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
348
			// regular local variable read
312
			// regular local variable read
349
			Constant localConstant = localBinding.constant();
313
			Constant localConstant = localBinding.constant();
350
			if (localConstant != Constant.NotAConstant) {
314
			if (localConstant != Constant.NotAConstant) {
Lines 360-421 Link Here
360
					codeStream.load(localBinding);
324
					codeStream.load(localBinding);
361
				}
325
				}
362
			}
326
			}
327
			break;
328
		default : // should not occur
329
			return null;			
363
	}
330
	}
364
365
	// all intermediate field accesses are read accesses
331
	// all intermediate field accesses are read accesses
366
	// only the last field binding is a write access
332
	// only the last field binding is a write access
367
	if (this.otherCodegenBindings != null) {
333
	int positionsLength = this.sourcePositions.length;
334
	FieldBinding initialFieldBinding = lastFieldBinding; // can be null if initial was a local binding
335
	if (this.otherBindings != null) {
368
		for (int i = 0; i < otherBindingsCount; i++) {
336
		for (int i = 0; i < otherBindingsCount; i++) {
369
			FieldBinding nextField = this.otherCodegenBindings[i];
337
			int pc = codeStream.position;
338
			FieldBinding nextField = this.otherBindings[i].original();
370
			TypeBinding nextGenericCast = this.otherGenericCasts == null ? null : this.otherGenericCasts[i];
339
			TypeBinding nextGenericCast = this.otherGenericCasts == null ? null : this.otherGenericCasts[i];
371
			if (lastFieldBinding != null) {
340
			if (lastFieldBinding != null) {
372
				needValue = !nextField.isStatic();
341
				needValue = !nextField.isStatic();
373
				if (needValue) {
342
				Constant fieldConstant = lastFieldBinding.constant();
374
					if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
343
				if (fieldConstant != Constant.NotAConstant) {
375
						Constant fieldConstant = lastFieldBinding.constant();
344
					if (i > 0 && !lastFieldBinding.isStatic()) {
376
						if (fieldConstant != Constant.NotAConstant) {
345
						codeStream.invokeObjectGetClass(); // perform null check
377
							if (lastFieldBinding != this.codegenBinding && !lastFieldBinding.isStatic()) {
346
						codeStream.pop();
378
								codeStream.invokeObjectGetClass(); // perform null check
347
					}
379
								codeStream.pop();
348
					if (needValue) {
349
						codeStream.generateConstant(fieldConstant, 0);
350
					}
351
				} else {
352
					if (needValue || (i > 0 && complyTo14) || lastGenericCast != null) {
353
						if (lastFieldBinding.canBeSeenBy(lastReceiverType, this, currentScope)) {
354
							MethodBinding accessor = this.syntheticReadAccessors == null ? null : this.syntheticReadAccessors[i];
355
							if (accessor == null) {
356
								TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, lastFieldBinding, lastReceiverType, i == 0 && this.indexOfFirstFieldBinding == 1);
357
								if (lastFieldBinding.isStatic()) {
358
									codeStream.fieldAccess(Opcodes.OPC_getstatic, lastFieldBinding, constantPoolDeclaringClass);
359
								} else {
360
									codeStream.fieldAccess(Opcodes.OPC_getfield, lastFieldBinding, constantPoolDeclaringClass);
361
								}
362
							} else {
363
								codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */);
380
							}
364
							}
381
							codeStream.generateConstant(fieldConstant, 0);
382
						} else if (lastFieldBinding.isStatic()) {
383
							codeStream.getstatic(lastFieldBinding);
384
						} else {
365
						} else {
385
							codeStream.getfield(lastFieldBinding);
366
							codeStream.generateEmulatedReadAccessForField(lastFieldBinding);
367
						}
368
						if (lastGenericCast != null) {
369
							codeStream.checkcast(lastGenericCast);
370
							lastReceiverType = lastGenericCast;
371
						} else {
372
							lastReceiverType = lastFieldBinding.type;
386
						}
373
						}
374
						if (!needValue) codeStream.pop();
387
					} else {
375
					} else {
388
						codeStream.generateEmulatedReadAccessForField(lastFieldBinding);
376
						if (lastFieldBinding == initialFieldBinding) {
377
							if (lastFieldBinding.isStatic()){
378
								// if no valueRequired, still need possible side-effects of <clinit> invocation, if field belongs to different class
379
								if (initialFieldBinding.declaringClass != this.actualReceiverType.erasure()) {
380
									if (lastFieldBinding.canBeSeenBy(lastReceiverType, this, currentScope)) {
381
										MethodBinding accessor = this.syntheticReadAccessors == null ? null : this.syntheticReadAccessors[i];
382
										if (accessor == null) {
383
											TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, lastFieldBinding, lastReceiverType, i == 0 && this.indexOfFirstFieldBinding == 1);
384
											codeStream.fieldAccess(Opcodes.OPC_getstatic, lastFieldBinding, constantPoolDeclaringClass);
385
										} else {
386
											codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */);
387
										}
388
									} else {
389
										codeStream.generateEmulatedReadAccessForField(lastFieldBinding);
390
									}
391
									codeStream.pop();
392
								}
393
							}
394
						} else if (!lastFieldBinding.isStatic()){
395
							codeStream.invokeObjectGetClass(); // perform null check
396
							codeStream.pop();
397
						}
398
						lastReceiverType = lastFieldBinding.type;
389
					}
399
					}
390
					if (lastGenericCast != null) codeStream.checkcast(lastGenericCast);
400
					if ((positionsLength - otherBindingsCount + i - 1) >= 0) {
391
				} else {
401
						int fieldPosition = (int) (this.sourcePositions[positionsLength - otherBindingsCount + i - 1] >>>32);
392
					if (this.codegenBinding != lastFieldBinding && !lastFieldBinding.isStatic()){
402
						codeStream.recordPositionsFrom(pc, fieldPosition);
393
						codeStream.invokeObjectGetClass(); // perform null check
394
						codeStream.pop();
395
					}
403
					}
396
				}
404
				}
397
			}
405
			}
398
			lastFieldBinding = nextField;
406
			lastFieldBinding = nextField;
399
			lastGenericCast = nextGenericCast;
407
			lastGenericCast = nextGenericCast;
400
			if (lastFieldBinding != null && !lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
408
			if (lastFieldBinding != null && !lastFieldBinding.canBeSeenBy(lastReceiverType, this, currentScope)) {
401
				if (lastFieldBinding.isStatic()) {
409
				if (lastFieldBinding.isStatic()) {
402
					codeStream.aconst_null();
410
					codeStream.aconst_null();
403
				}
411
				}
404
			}
412
			}			
405
		}
413
		}
406
	}
414
	}
407
	return lastFieldBinding;
415
	return lastFieldBinding;	
408
}
416
}
409
417
418
410
public void generateReceiver(CodeStream codeStream) {
419
public void generateReceiver(CodeStream codeStream) {
411
	codeStream.aload_0();
420
	codeStream.aload_0();
412
	if (this.delegateThis != null) {
421
	if (this.delegateThis != null) {
413
		codeStream.getfield(this.delegateThis); // delegated field access
422
		codeStream.fieldAccess(Opcodes.OPC_getfield, this.delegateThis, null /* default declaringClass */); // delegated field access
414
	}
423
	}
415
}
424
}
425
416
public TypeBinding getOtherFieldBindings(BlockScope scope) {
426
public TypeBinding getOtherFieldBindings(BlockScope scope) {
417
	// At this point restrictiveFlag may ONLY have two potential value : FIELD LOCAL (i.e cast <<(VariableBinding) binding>> is valid)
427
	// At this point restrictiveFlag may ONLY have two potential value : FIELD LOCAL (i.e cast <<(VariableBinding) binding>> is valid)
418
419
	int length = this.tokens.length;
428
	int length = this.tokens.length;
420
	if ((this.bits & Binding.FIELD) != 0) {
429
	if ((this.bits & Binding.FIELD) != 0) {
421
		if (!((FieldBinding) this.binding).isStatic()) { //must check for the static status....
430
		if (!((FieldBinding) this.binding).isStatic()) { //must check for the static status....
Lines 445-451 Link Here
445
454
446
	// allocation of the fieldBindings array	and its respective constants
455
	// allocation of the fieldBindings array	and its respective constants
447
	int otherBindingsLength = length - index;
456
	int otherBindingsLength = length - index;
448
	this.otherCodegenBindings = this.otherBindings = new FieldBinding[otherBindingsLength];
457
	this.otherBindings = new FieldBinding[otherBindingsLength];
449
458
450
	// fill the first constant (the one of the binding)
459
	// fill the first constant (the one of the binding)
451
	this.constant =((VariableBinding) this.binding).constant();
460
	this.constant =((VariableBinding) this.binding).constant();
Lines 466-471 Link Here
466
					if (this.delegateThis == null){  // if not found then internal error, field should have been found
475
					if (this.delegateThis == null){  // if not found then internal error, field should have been found
467
						return super.reportError(scope);
476
						return super.reportError(scope);
468
					}
477
					}
478
					this.actualReceiverType = this.delegateThis.type;
469
				} else {
479
				} else {
470
					this.constant = Constant.NotAConstant; //don't fill other constants slots...
480
					this.constant = Constant.NotAConstant; //don't fill other constants slots...
471
					scope.problemReporter().invalidField(this, field, index, type);
481
					scope.problemReporter().invalidField(this, field, index, type);
Lines 494-586 Link Here
494
	}
504
	}
495
	return (this.otherBindings[otherBindingsLength - 1]).type;
505
	return (this.otherBindings[otherBindingsLength - 1]).type;
496
}
506
}
497
	/**
507
498
	 * Check and/or redirect the field access to the delegate receiver if any
508
public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FieldBinding fieldBinding, int index, FlowInfo flowInfo) {
499
	 */
509
	// do nothing
500
	public TypeBinding getReceiverType(BlockScope currentScope) {
510
}
501
		Scope scope = currentScope.parent;
511
/**
502
		while (true) {
512
 * index is <0 to denote write access emulation
503
				switch (scope.kind) {
513
 */
504
					case Scope.CLASS_SCOPE :
514
/*
505
						return ((ClassScope) scope).referenceContext.binding;
515
public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FieldBinding fieldBinding, int index, FlowInfo flowInfo) {
506
					default:
516
	if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0) return;
507
						scope = scope.parent;
517
508
				}
518
	// if the binding declaring class is not visible, need special action
509
		}
519
	// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
520
	// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
521
	boolean useDelegate;
522
	if (index < 0) { // write-access?
523
	    useDelegate = fieldBinding == this.binding && this.delegateThis != null;
524
	} else {
525
		useDelegate = index == 0 && this.delegateThis != null;
510
	}
526
	}
511
	/**
512
	 * index is <0 to denote write access emulation
513
	 */
514
	public void manageSyntheticAccessIfNecessary(
515
		BlockScope currentScope,
516
		FieldBinding fieldBinding,
517
		TypeBinding lastReceiverType,
518
		int index,
519
		FlowInfo flowInfo) {
520
521
		if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0) return;
522
523
		// if the binding declaring class is not visible, need special action
524
		// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
525
		// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
526
		boolean useDelegate;
527
		if (index < 0) { // write-access?
528
		    useDelegate = fieldBinding == this.binding && this.delegateThis != null;
529
		} else {
530
			useDelegate = index == 0 && this.delegateThis != null;
531
		}
532
527
533
		if (useDelegate) {
528
	if (useDelegate) {
534
			lastReceiverType = this.delegateThis.type;
529
		lastReceiverType = this.delegateThis.type;
535
		}
530
	}
536
		// if the binding declaring class is not visible, need special action
531
	// if the binding declaring class is not visible, need special action
537
		// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
532
	// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
538
		// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
533
	// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
539
		// and not from Object or implicit static field access.
534
	// and not from Object or implicit static field access.
540
		if (fieldBinding.declaringClass != lastReceiverType
535
	if (fieldBinding.declaringClass != lastReceiverType
541
				&& !lastReceiverType.isArrayType()
536
			&& !lastReceiverType.isArrayType()
542
				&& fieldBinding.declaringClass != null // array.length
537
			&& fieldBinding.declaringClass != null // array.length
543
				&& fieldBinding.constant() == Constant.NotAConstant) {
538
			&& fieldBinding.constant() == Constant.NotAConstant) {
544
			CompilerOptions options = currentScope.compilerOptions();
539
		CompilerOptions options = currentScope.compilerOptions();
545
			if ((options.targetJDK >= ClassFileConstants.JDK1_2
540
		if ((options.targetJDK >= ClassFileConstants.JDK1_2
546
					&& (options.complianceLevel >= ClassFileConstants.JDK1_4 || (index < 0 ? fieldBinding != this.binding : index > 0) || this.indexOfFirstFieldBinding > 1 || !fieldBinding.isStatic())
541
				&& (options.complianceLevel >= ClassFileConstants.JDK1_4 || (index < 0 ? fieldBinding != this.binding : index > 0) || this.indexOfFirstFieldBinding > 1 || !fieldBinding.isStatic())
547
					&& fieldBinding.declaringClass.id != T_JavaLangObject) // no change for Object fields
542
				&& fieldBinding.declaringClass.id != T_JavaLangObject) // no change for Object fields
548
				|| !(useDelegate
543
			|| !(useDelegate
549
						? new CodeSnippetScope(currentScope).canBeSeenByForCodeSnippet(fieldBinding.declaringClass, (ReferenceBinding) this.delegateThis.type)
544
					? new CodeSnippetScope(currentScope).canBeSeenByForCodeSnippet(fieldBinding.declaringClass, (ReferenceBinding) this.delegateThis.type)
550
						: fieldBinding.declaringClass.canBeSeenBy(currentScope))) {
545
					: fieldBinding.declaringClass.canBeSeenBy(currentScope))) {
551
546
552
			    if (index < 0) { // write-access?
547
lastReceiverType
553
					if (fieldBinding == this.binding){
554
						this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType.erasure());
555
					} else {
556
						if (this.otherCodegenBindings == this.otherBindings){
557
							int l = this.otherBindings.length;
558
							System.arraycopy(this.otherBindings, 0, this.otherCodegenBindings = new FieldBinding[l], 0, l);
559
						}
560
						this.otherCodegenBindings[this.otherCodegenBindings.length-1] = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType.erasure());
561
					}
562
			    } if (index == 0){
563
					this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType.erasure());
564
				} else {
565
					if (this.otherCodegenBindings == this.otherBindings){
566
						int l = this.otherBindings.length;
567
						System.arraycopy(this.otherBindings, 0, this.otherCodegenBindings = new FieldBinding[l], 0, l);
568
					}
569
					this.otherCodegenBindings[index-1] = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType.erasure());
570
				}
571
			}
572
		}
548
		}
573
	}
549
	}
550
}
551
*/
574
/**
552
/**
575
 * Normal field binding did not work, try to bind to a field of the delegate receiver.
553
 * Normal field binding did not work, try to bind to a field of the delegate receiver.
576
 */
554
 */
577
public TypeBinding reportError(BlockScope scope) {
555
public TypeBinding reportError(BlockScope scope) {
578
579
	if (this.evaluationContext.declaringTypeName != null) {
556
	if (this.evaluationContext.declaringTypeName != null) {
580
		this.delegateThis = scope.getField(scope.enclosingSourceType(), DELEGATE_THIS, this);
557
		this.delegateThis = scope.getField(scope.enclosingSourceType(), DELEGATE_THIS, this);
581
		if (this.delegateThis == null){  // if not found then internal error, field should have been found
558
		if (this.delegateThis == null){  // if not found then internal error, field should have been found
582
			return super.reportError(scope);
559
			return super.reportError(scope);
583
		}
560
		}
561
		this.actualReceiverType = this.delegateThis.type;
584
	} else {
562
	} else {
585
		return super.reportError(scope);
563
		return super.reportError(scope);
586
	}
564
	}
Lines 593-599 Link Here
593
			if (((ProblemFieldBinding) fieldBinding).problemId() == NotVisible) {
571
			if (((ProblemFieldBinding) fieldBinding).problemId() == NotVisible) {
594
				// manage the access to a private field of the enclosing type
572
				// manage the access to a private field of the enclosing type
595
				CodeSnippetScope localScope = new CodeSnippetScope(scope);
573
				CodeSnippetScope localScope = new CodeSnippetScope(scope);
596
				this.codegenBinding = this.binding = localScope.getFieldForCodeSnippet(this.delegateThis.type, this.tokens[0], this);
574
				this.binding = localScope.getFieldForCodeSnippet(this.delegateThis.type, this.tokens[0], this);
597
				if (this.binding.isValidBinding()) {
575
				if (this.binding.isValidBinding()) {
598
					return checkFieldAccess(scope);
576
					return checkFieldAccess(scope);
599
				} else {
577
				} else {
Lines 603-639 Link Here
603
				return super.reportError(scope);
581
				return super.reportError(scope);
604
			}
582
			}
605
		}
583
		}
606
		this.codegenBinding = this.binding = fieldBinding;
584
		this.binding = fieldBinding;
607
		return checkFieldAccess(scope);
585
		return checkFieldAccess(scope);
608
	}
586
	}
609
587
610
	TypeBinding result;
588
	TypeBinding result;
611
	if (this.binding instanceof ProblemFieldBinding
589
	if (this.binding instanceof ProblemFieldBinding && ((ProblemFieldBinding) this.binding).problemId() == NotVisible) {
612
		&& ((ProblemFieldBinding) this.binding).problemId() == NotVisible) {
590
		// field and/or local are done before type lookups
613
		result = resolveTypeVisibility(scope);
591
		// the only available value for the restrictiveFlag BEFORE
614
		if (result == null) {
592
		// the TC is Flag_Type Flag_LocalField and Flag_TypeLocalField
593
		CodeSnippetScope localScope = new CodeSnippetScope(scope);
594
		if ((this.binding = localScope.getBinding(this.tokens, this.bits & RestrictiveFlagMASK, this, (ReferenceBinding) this.delegateThis.type)).isValidBinding()) {
595
			this.bits &= ~RestrictiveFlagMASK; // clear bits
596
			this.bits |= Binding.FIELD;
597
			result = getOtherFieldBindings(scope);
598
		} else {
615
			return super.reportError(scope);
599
			return super.reportError(scope);
616
		}
600
		}
617
		if (result.isValidBinding()) {
601
		if (result != null && result.isValidBinding()) {
618
			return result;
602
			return result;
619
		}
603
		}
620
	}
604
	}
621
622
	return super.reportError(scope);
623
}
624
public TypeBinding resolveTypeVisibility(BlockScope scope) {
625
	// field and/or local are done before type lookups
626
627
	// the only available value for the restrictiveFlag BEFORE
628
	// the TC is Flag_Type Flag_LocalField and Flag_TypeLocalField
629
630
	CodeSnippetScope localScope = new CodeSnippetScope(scope);
631
	if ((this.codegenBinding = this.binding = localScope.getBinding(this.tokens, this.bits & RestrictiveFlagMASK, this, (ReferenceBinding) this.delegateThis.type)).isValidBinding()) {
632
		this.bits &= ~RestrictiveFlagMASK; // clear bits
633
		this.bits |= Binding.FIELD;
634
		return getOtherFieldBindings(scope);
635
	}
636
	//========error cases===============
637
	return super.reportError(scope);
605
	return super.reportError(scope);
638
}
606
}
639
}
607
}
(-)eval/org/eclipse/jdt/internal/eval/CodeSnippetFieldReference.java (-112 / +87 lines)
Lines 15-33 Link Here
15
import org.eclipse.jdt.internal.compiler.ast.Expression;
15
import org.eclipse.jdt.internal.compiler.ast.Expression;
16
import org.eclipse.jdt.internal.compiler.ast.FieldReference;
16
import org.eclipse.jdt.internal.compiler.ast.FieldReference;
17
import org.eclipse.jdt.internal.compiler.ast.IntLiteral;
17
import org.eclipse.jdt.internal.compiler.ast.IntLiteral;
18
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
19
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
18
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
19
import org.eclipse.jdt.internal.compiler.codegen.Opcodes;
20
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
20
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
21
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
22
import org.eclipse.jdt.internal.compiler.impl.Constant;
21
import org.eclipse.jdt.internal.compiler.impl.Constant;
23
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
22
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
24
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
23
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
25
import org.eclipse.jdt.internal.compiler.lookup.ParameterizedFieldBinding;
26
import org.eclipse.jdt.internal.compiler.lookup.ProblemFieldBinding;
24
import org.eclipse.jdt.internal.compiler.lookup.ProblemFieldBinding;
27
import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
25
import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
28
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
29
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
26
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
30
import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
27
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
31
28
32
public class CodeSnippetFieldReference extends FieldReference implements ProblemReasons, EvaluationConstants {
29
public class CodeSnippetFieldReference extends FieldReference implements ProblemReasons, EvaluationConstants {
33
30
Lines 43-68 Link Here
43
	this.evaluationContext = evaluationContext;
40
	this.evaluationContext = evaluationContext;
44
}
41
}
45
public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) {
42
public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) {
46
43
	FieldBinding codegenBinding = this.binding.original();
47
	if (this.codegenBinding.canBeSeenBy(this.receiverType, this, currentScope)) {
44
	if (codegenBinding.canBeSeenBy(this.actualReceiverType, this, currentScope)) {
48
		this.receiver.generateCode(currentScope, codeStream, !this.codegenBinding.isStatic());
45
		this.receiver.generateCode(currentScope, codeStream, !codegenBinding.isStatic());
49
		assignment.expression.generateCode(currentScope, codeStream, true);
46
		assignment.expression.generateCode(currentScope, codeStream, true);
50
		fieldStore(codeStream, this.codegenBinding, null, valueRequired);
47
		fieldStore(currentScope, codeStream, codegenBinding, null, this.actualReceiverType, this.receiver.isImplicitThis(), valueRequired);
51
	} else {
48
	} else {
52
		codeStream.generateEmulationForField(this.codegenBinding);
49
		codeStream.generateEmulationForField(codegenBinding);
53
		this.receiver.generateCode(currentScope, codeStream, !this.codegenBinding.isStatic());
50
		this.receiver.generateCode(currentScope, codeStream, !codegenBinding.isStatic());
54
		if (this.codegenBinding.isStatic()) { // need a receiver?
51
		if (codegenBinding.isStatic()) { // need a receiver?
55
			codeStream.aconst_null();
52
			codeStream.aconst_null();
56
		}
53
		}
57
		assignment.expression.generateCode(currentScope, codeStream, true);
54
		assignment.expression.generateCode(currentScope, codeStream, true);
58
		if (valueRequired) {
55
		if (valueRequired) {
59
			if ((this.codegenBinding.type == TypeBinding.LONG) || (this.codegenBinding.type == TypeBinding.DOUBLE)) {
56
			switch (codegenBinding.type.id) {
60
				codeStream.dup2_x2();
57
				case TypeIds.T_long :
61
			} else {
58
				case TypeIds.T_double :
62
				codeStream.dup_x2();
59
					codeStream.dup2_x2();
63
			}
60
					break;
61
				default :
62
					codeStream.dup_x2();
63
					break;
64
			}			
64
		}
65
		}
65
		codeStream.generateEmulatedWriteAccessForField(this.codegenBinding);
66
		codeStream.generateEmulatedWriteAccessForField(codegenBinding);
66
	}
67
	}
67
	if (valueRequired){
68
	if (valueRequired){
68
		codeStream.generateImplicitConversion(assignment.implicitConversion);
69
		codeStream.generateImplicitConversion(assignment.implicitConversion);
Lines 76-108 Link Here
76
 * @param valueRequired boolean
77
 * @param valueRequired boolean
77
 */
78
 */
78
public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
79
public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
79
80
	int pc = codeStream.position;
80
	int pc = codeStream.position;
81
	if (this.constant != Constant.NotAConstant) {
81
	if (this.constant != Constant.NotAConstant) {
82
		if (valueRequired) {
82
		if (valueRequired) {
83
			codeStream.generateConstant(this.constant, this.implicitConversion);
83
			codeStream.generateConstant(this.constant, this.implicitConversion);
84
		}
84
		}
85
	} else {
85
	} else {
86
		boolean isStatic = this.codegenBinding.isStatic();
86
		FieldBinding codegenBinding = this.binding.original();
87
		boolean isStatic = codegenBinding.isStatic();
87
		this.receiver.generateCode(currentScope, codeStream, !isStatic);
88
		this.receiver.generateCode(currentScope, codeStream, !isStatic);
88
		if (valueRequired) {
89
		if (valueRequired) {
89
			Constant fieldConstant = this.codegenBinding.constant();
90
			Constant fieldConstant = codegenBinding.constant();
90
			if (fieldConstant == Constant.NotAConstant) {
91
			if (fieldConstant == Constant.NotAConstant) {
91
				if (this.codegenBinding.declaringClass == null) { // array length
92
				if (codegenBinding.declaringClass == null) { // array length
92
					codeStream.arraylength();
93
					codeStream.arraylength();
93
				} else {
94
				} else {
94
					if (this.codegenBinding.canBeSeenBy(this.receiverType, this, currentScope)) {
95
					if (codegenBinding.canBeSeenBy(this.actualReceiverType, this, currentScope)) {
96
						TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis());
95
						if (isStatic) {
97
						if (isStatic) {
96
							codeStream.getstatic(this.codegenBinding);
98
							codeStream.fieldAccess(Opcodes.OPC_getstatic , codegenBinding, constantPoolDeclaringClass);
97
						} else {
99
						} else {
98
							codeStream.getfield(this.codegenBinding);
100
							codeStream.fieldAccess(Opcodes.OPC_getfield, codegenBinding, constantPoolDeclaringClass);
99
						}
101
						}
100
					} else {
102
					} else {
101
						if (isStatic) {
103
						if (isStatic) {
102
							// we need a null on the stack to use the reflect emulation
104
							// we need a null on the stack to use the reflect emulation
103
							codeStream.aconst_null();
105
							codeStream.aconst_null();
104
						}
106
						}
105
						codeStream.generateEmulatedReadAccessForField(this.codegenBinding);
107
						codeStream.generateEmulatedReadAccessForField(codegenBinding);
106
					}
108
					}
107
				}
109
				}
108
				codeStream.generateImplicitConversion(this.implicitConversion);
110
				codeStream.generateImplicitConversion(this.implicitConversion);
Lines 124-138 Link Here
124
}
126
}
125
127
126
public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
128
public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
127
128
	boolean isStatic;
129
	boolean isStatic;
129
	if (this.codegenBinding.canBeSeenBy(this.receiverType, this, currentScope)) {
130
	FieldBinding codegenBinding = this.binding.original();
130
		this.receiver.generateCode(currentScope, codeStream, !(isStatic = this.codegenBinding.isStatic()));
131
	if (codegenBinding.canBeSeenBy(this.actualReceiverType, this, currentScope)) {
132
		this.receiver.generateCode(currentScope, codeStream, !(isStatic = codegenBinding.isStatic()));
133
		TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis());
131
		if (isStatic) {
134
		if (isStatic) {
132
			codeStream.getstatic(this.codegenBinding);
135
			codeStream.fieldAccess(Opcodes.OPC_getstatic, codegenBinding, constantPoolDeclaringClass);
133
		} else {
136
		} else {
134
			codeStream.dup();
137
			codeStream.dup();
135
			codeStream.getfield(this.codegenBinding);
138
			codeStream.fieldAccess(Opcodes.OPC_getfield, codegenBinding, constantPoolDeclaringClass);
136
		}
139
		}
137
		int operationTypeID;
140
		int operationTypeID;
138
		switch(operationTypeID = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) {
141
		switch(operationTypeID = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) {
Lines 155-171 Link Here
155
				// cast the value back to the array reference type
158
				// cast the value back to the array reference type
156
				codeStream.generateImplicitConversion(assignmentImplicitConversion);
159
				codeStream.generateImplicitConversion(assignmentImplicitConversion);
157
		}
160
		}
158
		fieldStore(codeStream, this.codegenBinding, null, valueRequired);
161
		fieldStore(currentScope, codeStream, codegenBinding, null, this.actualReceiverType, this.receiver.isImplicitThis(), valueRequired);
159
	} else {
162
	} else {
160
		this.receiver.generateCode(currentScope, codeStream, !(isStatic = this.codegenBinding.isStatic()));
163
		this.receiver.generateCode(currentScope, codeStream, !(isStatic = codegenBinding.isStatic()));
161
		if (isStatic) {
164
		if (isStatic) {
162
			// used to store the value
165
			// used to store the value
163
			codeStream.generateEmulationForField(this.codegenBinding);
166
			codeStream.generateEmulationForField(codegenBinding);
164
			codeStream.aconst_null();
167
			codeStream.aconst_null();
165
168
166
			// used to retrieve the actual value
169
			// used to retrieve the actual value
167
			codeStream.aconst_null();
170
			codeStream.aconst_null();
168
			codeStream.generateEmulatedReadAccessForField(this.codegenBinding);
171
			codeStream.generateEmulatedReadAccessForField(codegenBinding);
169
		} else {
172
		} else {
170
			// used to store the value
173
			// used to store the value
171
			codeStream.generateEmulationForField(this.binding);
174
			codeStream.generateEmulationForField(this.binding);
Lines 173-179 Link Here
173
176
174
			// used to retrieve the actual value
177
			// used to retrieve the actual value
175
			codeStream.dup();
178
			codeStream.dup();
176
			codeStream.generateEmulatedReadAccessForField(this.codegenBinding);
179
			codeStream.generateEmulatedReadAccessForField(codegenBinding);
177
		}
180
		}
178
		int operationTypeID;
181
		int operationTypeID;
179
		if ((operationTypeID = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) == T_JavaLangString) {
182
		if ((operationTypeID = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) == T_JavaLangString) {
Lines 195-201 Link Here
195
		// current stack is:
198
		// current stack is:
196
		// field receiver value
199
		// field receiver value
197
		if (valueRequired) {
200
		if (valueRequired) {
198
			if ((this.codegenBinding.type == TypeBinding.LONG) || (this.codegenBinding.type == TypeBinding.DOUBLE)) {
201
			if ((codegenBinding.type == TypeBinding.LONG) || (codegenBinding.type == TypeBinding.DOUBLE)) {
199
				codeStream.dup2_x2();
202
				codeStream.dup2_x2();
200
			} else {
203
			} else {
201
				codeStream.dup_x2();
204
				codeStream.dup_x2();
Lines 203-263 Link Here
203
		}
206
		}
204
		// current stack is:
207
		// current stack is:
205
		// value field receiver value
208
		// value field receiver value
206
		codeStream.generateEmulatedWriteAccessForField(this.codegenBinding);
209
		codeStream.generateEmulatedWriteAccessForField(codegenBinding);
207
	}
210
	}
208
}
211
}
209
public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
212
public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
210
	boolean isStatic;
213
	boolean isStatic;
211
	if (this.codegenBinding.canBeSeenBy(this.receiverType, this, currentScope)) {
214
	FieldBinding codegenBinding = this.binding.original();
215
	if (codegenBinding.canBeSeenBy(this.actualReceiverType, this, currentScope)) {
212
		super.generatePostIncrement(currentScope, codeStream, postIncrement, valueRequired);
216
		super.generatePostIncrement(currentScope, codeStream, postIncrement, valueRequired);
213
	} else {
217
	} else {
214
		this.receiver.generateCode(currentScope, codeStream, !(isStatic = this.codegenBinding.isStatic()));
218
		this.receiver.generateCode(currentScope, codeStream, !(isStatic = codegenBinding.isStatic()));
215
		if (isStatic) {
219
		if (isStatic) {
216
			codeStream.aconst_null();
220
			codeStream.aconst_null();
217
		}
221
		}
218
		// the actual stack is: receiver
222
		// the actual stack is: receiver
219
		codeStream.dup();
223
		codeStream.dup();
220
		// the actual stack is: receiver receiver
224
		// the actual stack is: receiver receiver
221
		codeStream.generateEmulatedReadAccessForField(this.codegenBinding);
225
		codeStream.generateEmulatedReadAccessForField(codegenBinding);
222
		// the actual stack is: receiver value
226
		// the actual stack is: receiver value
223
		// receiver value
227
		// receiver value
224
		// value receiver value 							dup_x1 or dup2_x1 if value required
228
		// value receiver value 							dup_x1 or dup2_x1 if value required
225
		// value value receiver value						dup_x1 or dup2_x1
229
		// value value receiver value					dup_x1 or dup2_x1
226
		// value value receiver								pop or pop2
230
		// value value receiver							pop or pop2
227
		// value value receiver field						generateEmulationForField
231
		// value value receiver field						generateEmulationForField
228
		// value value field receiver 						swap
232
		// value value field receiver 					swap
229
		// value field receiver value field receiver 		dup2_x1 or dup2_x2
233
		// value field receiver value field receiver 	dup2_x1 or dup2_x2
230
		// value field receiver value 				 		pop2
234
		// value field receiver value 				 	pop2
231
		// value field receiver newvalue 				 	generate constant + op
235
		// value field receiver newvalue 				generate constant + op
232
		// value 											store
236
		// value 												store
233
		if (valueRequired) {
237
		int typeID;
234
			if ((this.codegenBinding.type == TypeBinding.LONG) || (this.codegenBinding.type == TypeBinding.DOUBLE)) {
238
		switch (typeID = codegenBinding.type.id) {
239
			case TypeIds.T_long :
240
			case TypeIds.T_double :
241
				if (valueRequired) {
242
					codeStream.dup2_x1();
243
				}
235
				codeStream.dup2_x1();
244
				codeStream.dup2_x1();
236
			} else {
245
				codeStream.pop2();
246
				break;
247
			default :
248
				if (valueRequired) {
249
					codeStream.dup_x1();
250
				}
237
				codeStream.dup_x1();
251
				codeStream.dup_x1();
238
			}
252
				codeStream.pop();
239
		}
253
				break;
240
		if ((this.codegenBinding.type == TypeBinding.LONG) || (this.codegenBinding.type == TypeBinding.DOUBLE)) {
241
			codeStream.dup2_x1();
242
			codeStream.pop2();
243
		} else {
244
			codeStream.dup_x1();
245
			codeStream.pop();
246
		}
254
		}
247
		codeStream.generateEmulationForField(this.codegenBinding);
255
		codeStream.generateEmulationForField(codegenBinding);
248
		codeStream.swap();
256
		codeStream.swap();
249
257
		switch (typeID) {
250
		if ((this.codegenBinding.type == TypeBinding.LONG) || (this.codegenBinding.type == TypeBinding.DOUBLE)) {
258
			case TypeIds.T_long :
251
			codeStream.dup2_x2();
259
			case TypeIds.T_double :
252
		} else {
260
				codeStream.dup2_x2();
253
			codeStream.dup2_x1();
261
				break;
262
			default :
263
				codeStream.dup2_x1();
264
				break;
254
		}
265
		}
255
		codeStream.pop2();
266
		codeStream.pop2();
256
267
257
		codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
268
		codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
258
		codeStream.sendOperator(postIncrement.operator, this.codegenBinding.type.id);
269
		codeStream.sendOperator(postIncrement.operator, codegenBinding.type.id);
259
		codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion);
270
		codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion);
260
		codeStream.generateEmulatedWriteAccessForField(this.codegenBinding);
271
		codeStream.generateEmulatedWriteAccessForField(codegenBinding);
261
	}
272
	}
262
}
273
}
263
/*
274
/*
Lines 267-309 Link Here
267
	// The private access will be managed through the code generation
278
	// The private access will be managed through the code generation
268
279
269
	if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0) return;
280
	if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0) return;
270
271
	// if field from parameterized type got found, use the original field at codegen time
272
	if (this.binding instanceof ParameterizedFieldBinding) {
273
	    ParameterizedFieldBinding parameterizedField = (ParameterizedFieldBinding) this.binding;
274
	    this.codegenBinding = parameterizedField.originalField;
275
	    // extra cast needed if field type was type variable
276
	    if (this.codegenBinding.type.isTypeVariable()) {
277
	        TypeVariableBinding variableReturnType = (TypeVariableBinding) this.codegenBinding.type;
278
	        if (variableReturnType.firstBound != parameterizedField.type) { // no need for extra cast if same as first bound anyway
279
			    this.genericCast = parameterizedField.type.erasure();
280
	        }
281
	    }
282
	} else {
283
	    this.codegenBinding = this.binding;
284
	}
285
286
	// if the binding declaring class is not visible, need special action
287
	// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
288
	// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
289
	TypeBinding someReceiverType = this.delegateThis != null ? this.delegateThis.type : this.receiverType;
290
	if (this.binding.declaringClass != someReceiverType
291
			&& !someReceiverType.isArrayType()
292
			&& this.binding.declaringClass != null // array.length
293
			&& this.binding.constant() == Constant.NotAConstant) {
294
295
		CompilerOptions options = currentScope.compilerOptions();
296
		if ((options.targetJDK >= ClassFileConstants.JDK1_2
297
				&& (options.complianceLevel >= ClassFileConstants.JDK1_4 || !this.receiver.isImplicitThis() || !this.codegenBinding.isStatic())
298
				&& this.binding.declaringClass.id != T_JavaLangObject) // no change for Object fields
299
			|| !this.binding.declaringClass.canBeSeenBy(currentScope)) {
300
301
			this.codegenBinding =
302
				currentScope.enclosingSourceType().getUpdatedFieldBinding(
303
					this.codegenBinding,
304
					(ReferenceBinding) someReceiverType.erasure());
305
		}
306
	}
307
}
281
}
308
public TypeBinding resolveType(BlockScope scope) {
282
public TypeBinding resolveType(BlockScope scope) {
309
	// Answer the signature type of the field.
283
	// Answer the signature type of the field.
Lines 311-323 Link Here
311
	// and initialized with a (compile time) constant
285
	// and initialized with a (compile time) constant
312
286
313
	// regular receiver reference
287
	// regular receiver reference
314
	this.receiverType = this.receiver.resolveType(scope);
288
	this.actualReceiverType = this.receiver.resolveType(scope);
315
	if (this.receiverType == null){
289
	if (this.actualReceiverType == null){
316
		this.constant = Constant.NotAConstant;
290
		this.constant = Constant.NotAConstant;
317
		return null;
291
		return null;
318
	}
292
	}
319
	// the case receiverType.isArrayType and token = 'length' is handled by the scope API
293
	// the case receiverType.isArrayType and token = 'length' is handled by the scope API
320
	this.codegenBinding = this.binding = scope.getField(this.receiverType, this.token, this);
294
	this.binding = scope.getField(this.actualReceiverType, this.token, this);
321
	FieldBinding firstAttempt = this.binding;
295
	FieldBinding firstAttempt = this.binding;
322
	boolean isNotVisible = false;
296
	boolean isNotVisible = false;
323
	if (!this.binding.isValidBinding()) {
297
	if (!this.binding.isValidBinding()) {
Lines 328-352 Link Here
328
					this.delegateThis = scope.getField(scope.enclosingSourceType(), DELEGATE_THIS, this);
302
					this.delegateThis = scope.getField(scope.enclosingSourceType(), DELEGATE_THIS, this);
329
					if (this.delegateThis == null){  // if not found then internal error, field should have been found
303
					if (this.delegateThis == null){  // if not found then internal error, field should have been found
330
						this.constant = Constant.NotAConstant;
304
						this.constant = Constant.NotAConstant;
331
						scope.problemReporter().invalidField(this, this.receiverType);
305
						scope.problemReporter().invalidField(this, this.actualReceiverType);
332
						return null;
306
						return null;
333
					}
307
					}
308
					this.actualReceiverType = this.delegateThis.type;
334
				} else {
309
				} else {
335
					this.constant = Constant.NotAConstant;
310
					this.constant = Constant.NotAConstant;
336
					scope.problemReporter().invalidField(this, this.receiverType);
311
					scope.problemReporter().invalidField(this, this.actualReceiverType);
337
					return null;
312
					return null;
338
				}
313
				}
339
			CodeSnippetScope localScope = new CodeSnippetScope(scope);
314
			CodeSnippetScope localScope = new CodeSnippetScope(scope);
340
			this.codegenBinding = this.binding = localScope.getFieldForCodeSnippet(this.delegateThis.type, this.token, this);
315
			this.binding = localScope.getFieldForCodeSnippet(this.delegateThis.type, this.token, this);
341
		}
316
		}
342
	}
317
	}
343
318
344
	if (!this.binding.isValidBinding()) {
319
	if (!this.binding.isValidBinding()) {
345
		this.constant = Constant.NotAConstant;
320
		this.constant = Constant.NotAConstant;
346
		if (isNotVisible) {
321
		if (isNotVisible) {
347
			this.codegenBinding = this.binding = firstAttempt;
322
			this.binding = firstAttempt;
348
		}
323
		}
349
		scope.problemReporter().invalidField(this, this.receiverType);
324
		scope.problemReporter().invalidField(this, this.actualReceiverType);
350
		return null;
325
		return null;
351
	}
326
	}
352
327
(-)eval/org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java (-114 / +122 lines)
Lines 16-28 Link Here
16
import org.eclipse.jdt.internal.compiler.ast.Expression;
16
import org.eclipse.jdt.internal.compiler.ast.Expression;
17
import org.eclipse.jdt.internal.compiler.ast.IntLiteral;
17
import org.eclipse.jdt.internal.compiler.ast.IntLiteral;
18
import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
18
import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
19
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
20
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
19
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
20
import org.eclipse.jdt.internal.compiler.codegen.Opcodes;
21
import org.eclipse.jdt.internal.compiler.flow.FlowContext;
21
import org.eclipse.jdt.internal.compiler.flow.FlowContext;
22
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
22
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
23
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
24
import org.eclipse.jdt.internal.compiler.impl.Constant;
23
import org.eclipse.jdt.internal.compiler.impl.Constant;
25
import org.eclipse.jdt.internal.compiler.lookup.*;
24
import org.eclipse.jdt.internal.compiler.lookup.Binding;
25
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
26
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
27
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
28
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
29
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
30
import org.eclipse.jdt.internal.compiler.lookup.ParameterizedFieldBinding;
31
import org.eclipse.jdt.internal.compiler.lookup.ProblemBinding;
32
import org.eclipse.jdt.internal.compiler.lookup.ProblemFieldBinding;
33
import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
34
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
35
import org.eclipse.jdt.internal.compiler.lookup.Scope;
36
import org.eclipse.jdt.internal.compiler.lookup.TagBits;
37
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
38
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
39
import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
26
40
27
/**
41
/**
28
 * A single name reference inside a code snippet can denote a field of a remote
42
 * A single name reference inside a code snippet can denote a field of a remote
Lines 93-99 Link Here
93
107
94
}
108
}
95
public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) {
109
public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) {
96
97
	// optimizing assignment like: i = i + 1 or i = 1 + i
110
	// optimizing assignment like: i = i + 1 or i = 1 + i
98
	if (assignment.expression.isCompactableOperation()) {
111
	if (assignment.expression.isCompactableOperation()) {
99
		BinaryExpression operation = (BinaryExpression) assignment.expression;
112
		BinaryExpression operation = (BinaryExpression) assignment.expression;
Lines 108-118 Link Here
108
			return;
121
			return;
109
		}
122
		}
110
		if ((operation.right instanceof SingleNameReference)
123
		if ((operation.right instanceof SingleNameReference)
111
			&& ((operator == PLUS) || (operator == MULTIPLY)) // only commutative operations
124
				&& ((operator == PLUS) || (operator == MULTIPLY)) // only commutative operations
112
			&& ((variableReference = (SingleNameReference) operation.right).binding == this.binding)
125
				&& ((variableReference = (SingleNameReference) operation.right).binding == this.binding)
113
			&& (operation.left.constant != Constant.NotAConstant) // exclude non constant expressions, since could have side-effect
126
				&& (operation.left.constant != Constant.NotAConstant) // exclude non constant expressions, since could have side-effect
114
			&& (((operation.left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) != T_JavaLangString) // exclude string concatenation which would occur backwards
127
				&& (((operation.left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) != T_JavaLangString) // exclude string concatenation which would occur backwards
115
			&& (((operation.right.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) != T_JavaLangString)) { // exclude string concatenation which would occur backwards
128
				&& (((operation.right.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) != T_JavaLangString)) { // exclude string concatenation which would occur backwards
116
			// i = value + i, then use the variable on the right hand side, since it has the correct implicit conversion
129
			// i = value + i, then use the variable on the right hand side, since it has the correct implicit conversion
117
			variableReference.generateCompoundAssignment(currentScope, codeStream, this.syntheticAccessors == null ? null : this.syntheticAccessors[WRITE], operation.left, operator, operation.implicitConversion, valueRequired);
130
			variableReference.generateCompoundAssignment(currentScope, codeStream, this.syntheticAccessors == null ? null : this.syntheticAccessors[WRITE], operation.left, operator, operation.implicitConversion, valueRequired);
118
			if (valueRequired) {
131
			if (valueRequired) {
Lines 123-131 Link Here
123
	}
136
	}
124
	switch (this.bits & RestrictiveFlagMASK) {
137
	switch (this.bits & RestrictiveFlagMASK) {
125
		case Binding.FIELD : // assigning to a field
138
		case Binding.FIELD : // assigning to a field
126
			FieldBinding fieldBinding = (FieldBinding) this.codegenBinding;
139
			FieldBinding codegenField = ((FieldBinding) this.binding).original();
127
			if (fieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
140
			if (codegenField.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
128
				if (!fieldBinding.isStatic()) { // need a receiver?
141
				if (!codegenField.isStatic()) { // need a receiver?
129
					if ((this.bits & DepthMASK) != 0) {
142
					if ((this.bits & DepthMASK) != 0) {
130
						ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT);
143
						ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT);
131
						Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
144
						Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
Lines 135-147 Link Here
135
					}
148
					}
136
				}
149
				}
137
				assignment.expression.generateCode(currentScope, codeStream, true);
150
				assignment.expression.generateCode(currentScope, codeStream, true);
138
				fieldStore(codeStream, fieldBinding, null, valueRequired);
151
				fieldStore(currentScope, codeStream, codegenField, null, this.actualReceiverType, this.delegateThis == null /*implicit this*/, valueRequired);
139
				if (valueRequired) {
152
				if (valueRequired) {
140
					codeStream.generateImplicitConversion(assignment.implicitConversion);
153
					codeStream.generateImplicitConversion(assignment.implicitConversion);
141
				}
154
				}
142
			} else {
155
			} else {
143
				codeStream.generateEmulationForField(fieldBinding);
156
				codeStream.generateEmulationForField(codegenField);
144
				if (!fieldBinding.isStatic()) { // need a receiver?
157
				if (!codegenField.isStatic()) { // need a receiver?
145
					if ((this.bits & DepthMASK) != 0) {
158
					if ((this.bits & DepthMASK) != 0) {
146
						// internal error, per construction we should have found it
159
						// internal error, per construction we should have found it
147
						// not yet supported
160
						// not yet supported
Lines 154-173 Link Here
154
				}
167
				}
155
				assignment.expression.generateCode(currentScope, codeStream, true);
168
				assignment.expression.generateCode(currentScope, codeStream, true);
156
				if (valueRequired) {
169
				if (valueRequired) {
157
					if ((fieldBinding.type == TypeBinding.LONG) || (fieldBinding.type == TypeBinding.DOUBLE)) {
170
					if ((codegenField.type == TypeBinding.LONG) || (codegenField.type == TypeBinding.DOUBLE)) {
158
						codeStream.dup2_x2();
171
						codeStream.dup2_x2();
159
					} else {
172
					} else {
160
						codeStream.dup_x2();
173
						codeStream.dup_x2();
161
					}
174
					}
162
				}
175
				}
163
				codeStream.generateEmulatedWriteAccessForField(fieldBinding);
176
				codeStream.generateEmulatedWriteAccessForField(codegenField);
164
				if (valueRequired) {
177
				if (valueRequired) {
165
					codeStream.generateImplicitConversion(assignment.implicitConversion);
178
					codeStream.generateImplicitConversion(assignment.implicitConversion);
166
				}
179
				}
167
			}
180
			}
168
			return;
181
			return;
169
		case Binding.LOCAL : // assigning to a local variable
182
		case Binding.LOCAL : // assigning to a local variable
170
			LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
183
			LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
171
			if (localBinding.resolvedPosition != -1) {
184
			if (localBinding.resolvedPosition != -1) {
172
				assignment.expression.generateCode(currentScope, codeStream, true);
185
				assignment.expression.generateCode(currentScope, codeStream, true);
173
			} else {
186
			} else {
Lines 214-226 Link Here
214
			case Binding.FIELD : // reading a field
227
			case Binding.FIELD : // reading a field
215
				if (!valueRequired)
228
				if (!valueRequired)
216
					break;
229
					break;
217
				FieldBinding fieldBinding = (FieldBinding) this.codegenBinding;
230
				FieldBinding codegenField = ((FieldBinding) this.binding).original();
218
				Constant fieldConstant = fieldBinding.constant();
231
				Constant fieldConstant = codegenField.constant();
219
				if (fieldConstant == Constant.NotAConstant) { // directly use inlined value for constant fields
232
				if (fieldConstant == Constant.NotAConstant) { // directly use inlined value for constant fields
220
					if (fieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
233
					if (codegenField.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
221
						 // directly use inlined value for constant fields
234
						TypeBinding someReceiverType = this.delegateThis != null ? this.delegateThis.type : this.actualReceiverType;
222
						boolean isStatic;
235
						TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, someReceiverType, true /* implicit this */);
223
						if (!(isStatic = fieldBinding.isStatic())) {
236
						if (codegenField.isStatic()) {
237
							codeStream.fieldAccess(Opcodes.OPC_getstatic, codegenField, constantPoolDeclaringClass);
238
						} else {
224
							if ((this.bits & DepthMASK) != 0) {
239
							if ((this.bits & DepthMASK) != 0) {
225
								ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT);
240
								ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT);
226
								Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
241
								Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
Lines 228-243 Link Here
228
							} else {
243
							} else {
229
								generateReceiver(codeStream);
244
								generateReceiver(codeStream);
230
							}
245
							}
231
						}
246
							codeStream.fieldAccess(Opcodes.OPC_getfield, codegenField, constantPoolDeclaringClass);
232
						// managing private access
233
						if (isStatic) {
234
							codeStream.getstatic(fieldBinding);
235
						} else {
236
							codeStream.getfield(fieldBinding);
237
						}
247
						}
238
					} else {
248
					} else {
239
						// managing private access
249
						// managing private access
240
						if (!fieldBinding.isStatic()) {
250
						if (!codegenField.isStatic()) {
241
							if ((this.bits & DepthMASK) != 0) {
251
							if ((this.bits & DepthMASK) != 0) {
242
								// internal error, per construction we should have found it
252
								// internal error, per construction we should have found it
243
								// not yet supported
253
								// not yet supported
Lines 248-254 Link Here
248
						} else {
258
						} else {
249
							codeStream.aconst_null();
259
							codeStream.aconst_null();
250
						}
260
						}
251
						codeStream.generateEmulatedReadAccessForField(fieldBinding);
261
						codeStream.generateEmulatedReadAccessForField(codegenField);
252
					}
262
					}
253
					if (this.genericCast != null) codeStream.checkcast(this.genericCast);
263
					if (this.genericCast != null) codeStream.checkcast(this.genericCast);
254
					codeStream.generateImplicitConversion(this.implicitConversion);
264
					codeStream.generateImplicitConversion(this.implicitConversion);
Lines 257-263 Link Here
257
				}
267
				}
258
				break;
268
				break;
259
			case Binding.LOCAL : // reading a local
269
			case Binding.LOCAL : // reading a local
260
				LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
270
				LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
261
				if (!valueRequired)
271
				if (!valueRequired)
262
					break;
272
					break;
263
				// outer local?
273
				// outer local?
Lines 282-302 Link Here
282
public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, MethodBinding writeAccessor, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
292
public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, MethodBinding writeAccessor, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
283
	switch (this.bits & RestrictiveFlagMASK) {
293
	switch (this.bits & RestrictiveFlagMASK) {
284
		case Binding.FIELD : // assigning to a field
294
		case Binding.FIELD : // assigning to a field
285
			FieldBinding fieldBinding = (FieldBinding) this.codegenBinding;
295
			FieldBinding codegenField = ((FieldBinding) this.binding).original();
286
			if (fieldBinding.isStatic()) {
296
			if (codegenField.isStatic()) {
287
				if (fieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
297
				if (codegenField.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
288
					codeStream.getstatic(fieldBinding);
298
					TypeBinding someReceiverType = this.delegateThis != null ? this.delegateThis.type : this.actualReceiverType;
299
					TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, someReceiverType, true /* implicit this */);
300
					codeStream.fieldAccess(Opcodes.OPC_getstatic, codegenField, constantPoolDeclaringClass);
289
				} else {
301
				} else {
290
					// used to store the value
302
					// used to store the value
291
					codeStream.generateEmulationForField(fieldBinding);
303
					codeStream.generateEmulationForField(codegenField);
292
					codeStream.aconst_null();
304
					codeStream.aconst_null();
293
305
294
					// used to retrieve the actual value
306
					// used to retrieve the actual value
295
					codeStream.aconst_null();
307
					codeStream.aconst_null();
296
					codeStream.generateEmulatedReadAccessForField(fieldBinding);
308
					codeStream.generateEmulatedReadAccessForField(codegenField);
297
				}
309
				}
298
			} else {
310
			} else {
299
				if (fieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
311
				if (codegenField.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
300
					if ((this.bits & DepthMASK) != 0) {
312
					if ((this.bits & DepthMASK) != 0) {
301
						ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT);
313
						ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT);
302
						Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
314
						Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
Lines 305-311 Link Here
305
						generateReceiver(codeStream);
317
						generateReceiver(codeStream);
306
					}
318
					}
307
					codeStream.dup();
319
					codeStream.dup();
308
					codeStream.getfield(fieldBinding);
320
					TypeBinding someReceiverType = this.delegateThis != null ? this.delegateThis.type : this.actualReceiverType;
321
					TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, someReceiverType, true /* implicit this */);
322
					codeStream.fieldAccess(Opcodes.OPC_getfield, codegenField, constantPoolDeclaringClass);
309
				} else {
323
				} else {
310
					if ((this.bits & DepthMASK) != 0) {
324
					if ((this.bits & DepthMASK) != 0) {
311
						// internal error, per construction we should have found it
325
						// internal error, per construction we should have found it
Lines 313-329 Link Here
313
						currentScope.problemReporter().needImplementation(this);
327
						currentScope.problemReporter().needImplementation(this);
314
					}
328
					}
315
					// used to store the value
329
					// used to store the value
316
					codeStream.generateEmulationForField(fieldBinding);
330
					codeStream.generateEmulationForField(codegenField);
317
					generateReceiver(codeStream);
331
					generateReceiver(codeStream);
318
332
319
					// used to retrieve the actual value
333
					// used to retrieve the actual value
320
					codeStream.dup();
334
					codeStream.dup();
321
					codeStream.generateEmulatedReadAccessForField(fieldBinding);
335
					codeStream.generateEmulatedReadAccessForField(codegenField);
322
				}
336
				}
323
			}
337
			}
324
			break;
338
			break;
325
		case Binding.LOCAL : // assigning to a local variable (cannot assign to outer local)
339
		case Binding.LOCAL : // assigning to a local variable (cannot assign to outer local)
326
			LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
340
			LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
327
			// using incr bytecode if possible
341
			// using incr bytecode if possible
328
			switch (localBinding.type.id) {
342
			switch (localBinding.type.id) {
329
				case T_JavaLangString :
343
				case T_JavaLangString :
Lines 387-418 Link Here
387
	// store the result back into the variable
401
	// store the result back into the variable
388
	switch (this.bits & RestrictiveFlagMASK) {
402
	switch (this.bits & RestrictiveFlagMASK) {
389
		case Binding.FIELD : // assigning to a field
403
		case Binding.FIELD : // assigning to a field
390
			FieldBinding fieldBinding = (FieldBinding) this.codegenBinding;
404
			FieldBinding codegenField = ((FieldBinding) this.binding).original();
391
			if (fieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
405
			if (codegenField.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
392
				fieldStore(codeStream, fieldBinding, writeAccessor, valueRequired);
406
				fieldStore(currentScope, codeStream, codegenField, writeAccessor, this.actualReceiverType, this.delegateThis == null /* implicit this */, valueRequired);
393
			} else {
407
			} else {
394
				// current stack is:
408
				// current stack is:
395
				// field receiver value
409
				// field receiver value
396
				if (valueRequired) {
410
				if (valueRequired) {
397
					if ((fieldBinding.type == TypeBinding.LONG) || (fieldBinding.type == TypeBinding.DOUBLE)) {
411
					switch (codegenField.type.id) {
398
						codeStream.dup2_x2();
412
						case TypeIds.T_long :
399
					} else {
413
						case TypeIds.T_double :
400
						codeStream.dup_x2();
414
							codeStream.dup2_x2();
401
					}
415
							break;
416
						default:
417
							codeStream.dup_x2();
418
							break;
419
					}					
402
				}
420
				}
403
				// current stack is:
421
				// current stack is:
404
				// value field receiver value
422
				// value field receiver value
405
				codeStream.generateEmulatedWriteAccessForField(fieldBinding);
423
				codeStream.generateEmulatedWriteAccessForField(codegenField);
406
			}
424
			}
407
			return;
425
			return;
408
		case Binding.LOCAL : // assigning to a local variable
426
		case Binding.LOCAL : // assigning to a local variable
409
			LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
427
			LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
410
			if (valueRequired) {
428
			if (valueRequired) {
411
				if ((localBinding.type == TypeBinding.LONG) || (localBinding.type == TypeBinding.DOUBLE)) {
429
				switch (localBinding.type.id) {
412
					codeStream.dup2();
430
					case TypeIds.T_long :
413
				} else {
431
					case TypeIds.T_double :
414
					codeStream.dup();
432
						codeStream.dup2();
415
				}
433
						break;
434
					default:
435
						codeStream.dup();
436
						break;
437
				}				
416
			}
438
			}
417
			codeStream.store(localBinding, false);
439
			codeStream.store(localBinding, false);
418
	}
440
	}
Lines 420-430 Link Here
420
public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
442
public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
421
	switch (this.bits & RestrictiveFlagMASK) {
443
	switch (this.bits & RestrictiveFlagMASK) {
422
		case Binding.FIELD : // assigning to a field
444
		case Binding.FIELD : // assigning to a field
423
			FieldBinding fieldBinding = (FieldBinding) this.codegenBinding;
445
			FieldBinding codegenField = ((FieldBinding) this.binding).original();
424
			if (fieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
446
			if (codegenField.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
425
				super.generatePostIncrement(currentScope, codeStream, postIncrement, valueRequired);
447
				super.generatePostIncrement(currentScope, codeStream, postIncrement, valueRequired);
426
			} else {
448
			} else {
427
				if (fieldBinding.isStatic()) {
449
				if (codegenField.isStatic()) {
428
					codeStream.aconst_null();
450
					codeStream.aconst_null();
429
				} else {
451
				} else {
430
					if ((this.bits & DepthMASK) != 0) {
452
					if ((this.bits & DepthMASK) != 0) {
Lines 435-474 Link Here
435
						generateReceiver(codeStream);
457
						generateReceiver(codeStream);
436
					}
458
					}
437
				}
459
				}
438
				codeStream.generateEmulatedReadAccessForField(fieldBinding);
460
				codeStream.generateEmulatedReadAccessForField(codegenField);
439
				if (valueRequired) {
461
				if (valueRequired) {
440
					if ((fieldBinding.type == TypeBinding.LONG) || (fieldBinding.type == TypeBinding.DOUBLE)) {
462
					switch (codegenField.type.id) {
441
						codeStream.dup2();
463
						case TypeIds.T_long :
442
					} else {
464
						case TypeIds.T_double :
443
						codeStream.dup();
465
							codeStream.dup2();
466
							break;
467
						default:
468
							codeStream.dup();
469
							break;
444
					}
470
					}
445
				}
471
				}
446
				codeStream.generateEmulationForField(fieldBinding);
472
				codeStream.generateEmulationForField(codegenField);
447
				if ((fieldBinding.type == TypeBinding.LONG) || (fieldBinding.type == TypeBinding.DOUBLE)) {
473
				switch (codegenField.type.id) {
448
					codeStream.dup_x2();
474
					case TypeIds.T_long :
449
					codeStream.pop();
475
					case TypeIds.T_double :
450
					if (fieldBinding.isStatic()) {
476
						codeStream.dup_x2();
451
						codeStream.aconst_null();
477
						codeStream.pop();
452
					} else {
478
						if (codegenField.isStatic()) {
453
						generateReceiver(codeStream);
479
							codeStream.aconst_null();
454
					}
480
						} else {
455
					codeStream.dup_x2();
481
							generateReceiver(codeStream);
456
					codeStream.pop();
482
						}
457
				} else {
483
						codeStream.dup_x2();
458
					codeStream.dup_x1();
484
						codeStream.pop();
485
						break;
486
					default:
487
						codeStream.dup_x1();
459
					codeStream.pop();
488
					codeStream.pop();
460
					if (fieldBinding.isStatic()) {
489
					if (codegenField.isStatic()) {
461
						codeStream.aconst_null();
490
						codeStream.aconst_null();
462
					} else {
491
					} else {
463
						generateReceiver(codeStream);
492
						generateReceiver(codeStream);
464
					}
493
					}
465
					codeStream.dup_x1();
494
					codeStream.dup_x1();
466
					codeStream.pop();
495
					codeStream.pop();
496
						break;
467
				}
497
				}
468
				codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
498
				codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
469
				codeStream.sendOperator(postIncrement.operator, fieldBinding.type.id);
499
				codeStream.sendOperator(postIncrement.operator, codegenField.type.id);
470
				codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion);
500
				codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion);
471
				codeStream.generateEmulatedWriteAccessForField(fieldBinding);
501
				codeStream.generateEmulatedWriteAccessForField(codegenField);
472
			}
502
			}
473
			return;
503
			return;
474
		case Binding.LOCAL : // assigning to a local variable
504
		case Binding.LOCAL : // assigning to a local variable
Lines 478-484 Link Here
478
public void generateReceiver(CodeStream codeStream) {
508
public void generateReceiver(CodeStream codeStream) {
479
	codeStream.aload_0();
509
	codeStream.aload_0();
480
	if (this.delegateThis != null) {
510
	if (this.delegateThis != null) {
481
		codeStream.getfield(this.delegateThis); // delegated field access
511
		codeStream.fieldAccess(Opcodes.OPC_getfield, this.delegateThis, null /* default declaringClass */); // delegate field access
482
	}
512
	}
483
}
513
}
484
/**
514
/**
Lines 509-544 Link Here
509
	// if field from parameterized type got found, use the original field at codegen time
539
	// if field from parameterized type got found, use the original field at codegen time
510
	if (this.binding instanceof ParameterizedFieldBinding) {
540
	if (this.binding instanceof ParameterizedFieldBinding) {
511
	    ParameterizedFieldBinding parameterizedField = (ParameterizedFieldBinding) this.binding;
541
	    ParameterizedFieldBinding parameterizedField = (ParameterizedFieldBinding) this.binding;
512
	    this.codegenBinding = parameterizedField.originalField;
542
	    FieldBinding codegenField = parameterizedField.originalField;
513
	    FieldBinding fieldCodegenBinding = (FieldBinding)this.codegenBinding;
514
	    // extra cast needed if field type was type variable
543
	    // extra cast needed if field type was type variable
515
	    if ((fieldCodegenBinding.type.tagBits & TagBits.HasTypeVariable) != 0) {
544
	    if ((codegenField.type.tagBits & TagBits.HasTypeVariable) != 0) {
516
	        this.genericCast = fieldCodegenBinding.type.genericCast(currentScope.boxing(parameterizedField.type)); // runtimeType could be base type in boxing case
545
	        this.genericCast = codegenField.type.genericCast(currentScope.boxing(parameterizedField.type)); // runtimeType could be base type in boxing case
517
	    }
546
	    }
518
	}
547
	}
519
	if ((this.bits & Binding.FIELD) != 0) {
520
		FieldBinding fieldBinding = (FieldBinding) this.binding;
521
522
		// if the binding declaring class is not visible, need special action
523
		// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
524
		// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
525
		// and not from Object or implicit static field access.
526
		if (fieldBinding.declaringClass != this.delegateThis.type
527
				&& fieldBinding.declaringClass != null // array.length
528
				&& fieldBinding.constant() == Constant.NotAConstant) {
529
			CompilerOptions options = currentScope.compilerOptions();
530
			if ((options.targetJDK >= ClassFileConstants.JDK1_2
531
					&& (options.complianceLevel >= ClassFileConstants.JDK1_4 || !fieldBinding.isStatic())
532
					&& fieldBinding.declaringClass.id != T_JavaLangObject) // no change for Object fields
533
				|| !fieldBinding.declaringClass.canBeSeenBy(currentScope)) {
534
535
				this.codegenBinding =
536
				    currentScope.enclosingSourceType().getUpdatedFieldBinding(
537
					       (FieldBinding)this.codegenBinding,
538
					        (ReferenceBinding)this.delegateThis.type.erasure());
539
			}
540
		}
541
	}
542
}
548
}
543
/**
549
/**
544
 * Normal field binding did not work, try to bind to a field of the delegate receiver.
550
 * Normal field binding did not work, try to bind to a field of the delegate receiver.
Lines 550-557 Link Here
550
		if (this.evaluationContext.declaringTypeName != null) {
556
		if (this.evaluationContext.declaringTypeName != null) {
551
			this.delegateThis = scope.getField(scope.enclosingSourceType(), DELEGATE_THIS, this);
557
			this.delegateThis = scope.getField(scope.enclosingSourceType(), DELEGATE_THIS, this);
552
			if (this.delegateThis != null){  // if not found then internal error, field should have been found
558
			if (this.delegateThis != null){  // if not found then internal error, field should have been found
559
				this.actualReceiverType = this.delegateThis.type;
553
				// will not support innerclass emulation inside delegate
560
				// will not support innerclass emulation inside delegate
554
				this.codegenBinding = this.binding = scope.getField(this.delegateThis.type, this.token, this);
561
				this.binding = scope.getField(this.delegateThis.type, this.token, this);
555
				if (!this.binding.isValidBinding()) {
562
				if (!this.binding.isValidBinding()) {
556
					return super.reportError(scope);
563
					return super.reportError(scope);
557
				}
564
				}
Lines 563-581 Link Here
563
		if (this.evaluationContext.declaringTypeName != null) {
570
		if (this.evaluationContext.declaringTypeName != null) {
564
			this.delegateThis = scope.getField(scope.enclosingSourceType(), DELEGATE_THIS, this);
571
			this.delegateThis = scope.getField(scope.enclosingSourceType(), DELEGATE_THIS, this);
565
			if (this.delegateThis != null){  // if not found then internal error, field should have been found
572
			if (this.delegateThis != null){  // if not found then internal error, field should have been found
573
				this.actualReceiverType = this.delegateThis.type;
566
				// will not support innerclass emulation inside delegate
574
				// will not support innerclass emulation inside delegate
567
				FieldBinding fieldBinding = scope.getField(this.delegateThis.type, this.token, this);
575
				FieldBinding fieldBinding = scope.getField(this.delegateThis.type, this.token, this);
568
				if (!fieldBinding.isValidBinding()) {
576
				if (!fieldBinding.isValidBinding()) {
569
					if (((ProblemFieldBinding) fieldBinding).problemId() == NotVisible) {
577
					if (((ProblemFieldBinding) fieldBinding).problemId() == NotVisible) {
570
						// manage the access to a private field of the enclosing type
578
						// manage the access to a private field of the enclosing type
571
						CodeSnippetScope localScope = new CodeSnippetScope(scope);
579
						CodeSnippetScope localScope = new CodeSnippetScope(scope);
572
						this.codegenBinding = this.binding = localScope.getFieldForCodeSnippet(this.delegateThis.type, this.token, this);
580
						this.binding = localScope.getFieldForCodeSnippet(this.delegateThis.type, this.token, this);
573
						return checkFieldAccess(scope);
581
						return checkFieldAccess(scope);
574
					} else {
582
					} else {
575
						return super.reportError(scope);
583
						return super.reportError(scope);
576
					}
584
					}
577
				}
585
				}
578
				this.codegenBinding = this.binding = fieldBinding;
586
				this.binding = fieldBinding;
579
				return checkFieldAccess(scope);
587
				return checkFieldAccess(scope);
580
			}
588
			}
581
		}
589
		}
(-)eval/org/eclipse/jdt/internal/eval/CodeSnippetMessageSend.java (-1 / +1 lines)
Lines 74-80 Link Here
74
		// generate arguments
74
		// generate arguments
75
		generateArguments(this.binding, this.arguments, currentScope, codeStream);
75
		generateArguments(this.binding, this.arguments, currentScope, codeStream);
76
		// actual message invocation
76
		// actual message invocation
77
		TypeBinding constantPoolDeclaringClass = getConstantPoolDeclaringClass(currentScope);
77
		TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis(), this.receiverGenericCast != null);
78
		if (isStatic) {
78
		if (isStatic) {
79
			codeStream.invoke(Opcodes.OPC_invokestatic, codegenBinding, constantPoolDeclaringClass);
79
			codeStream.invoke(Opcodes.OPC_invokestatic, codegenBinding, constantPoolDeclaringClass);
80
		} else if( (this.receiver.isSuper()) || codegenBinding.isPrivate()){
80
		} else if( (this.receiver.isSuper()) || codegenBinding.isPrivate()){
(-)eval/org/eclipse/jdt/internal/eval/CodeSnippetThisReference.java (-1 / +2 lines)
Lines 12-17 Link Here
12
12
13
import org.eclipse.jdt.internal.compiler.ast.ThisReference;
13
import org.eclipse.jdt.internal.compiler.ast.ThisReference;
14
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
14
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
15
import org.eclipse.jdt.internal.compiler.codegen.Opcodes;
15
import org.eclipse.jdt.internal.compiler.impl.Constant;
16
import org.eclipse.jdt.internal.compiler.impl.Constant;
16
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
17
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
17
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
18
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
Lines 58-64 Link Here
58
		int pc = codeStream.position;
59
		int pc = codeStream.position;
59
		if (valueRequired) {
60
		if (valueRequired) {
60
			codeStream.aload_0();
61
			codeStream.aload_0();
61
			codeStream.getfield(this.delegateThis);
62
			codeStream.fieldAccess(Opcodes.OPC_getfield, this.delegateThis, null /* default declaringClass */); // delegate field access
62
		}
63
		}
63
		codeStream.recordPositionsFrom(pc, this.sourceStart);
64
		codeStream.recordPositionsFrom(pc, this.sourceStart);
64
	}
65
	}
(-)compiler/org/eclipse/jdt/internal/compiler/ClassFile.java (-11 / +10 lines)
Lines 4194-4205 Link Here
4194
	 *
4194
	 *
4195
	 * @param codeAttributeOffset <CODE>int</CODE>
4195
	 * @param codeAttributeOffset <CODE>int</CODE>
4196
	 */
4196
	 */
4197
	public void completeCodeAttributeForProblemMethod(
4197
	public void completeCodeAttributeForProblemMethod(AbstractMethodDeclaration method, MethodBinding binding, int codeAttributeOffset, int[] startLineIndexes, int problemLine) {
4198
		AbstractMethodDeclaration method,
4199
		MethodBinding binding,
4200
		int codeAttributeOffset,
4201
		int[] startLineIndexes,
4202
		int problemLine) {
4203
		// reinitialize the localContents with the byte modified by the code stream
4198
		// reinitialize the localContents with the byte modified by the code stream
4204
		this.contents = this.codeStream.bCodeStream;
4199
		this.contents = this.codeStream.bCodeStream;
4205
		int localContentsOffset = this.codeStream.classFileOffset;
4200
		int localContentsOffset = this.codeStream.classFileOffset;
Lines 4391-4401 Link Here
4391
						descriptorIndex = this.constantPool.literalIndex(argumentBinding.signature());
4386
						descriptorIndex = this.constantPool.literalIndex(argumentBinding.signature());
4392
						this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
4387
						this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
4393
						this.contents[localContentsOffset++] = (byte) descriptorIndex;
4388
						this.contents[localContentsOffset++] = (byte) descriptorIndex;
4394
						if ((argumentBinding == TypeBinding.LONG)
4389
						switch(argumentBinding.id) {
4395
							|| (argumentBinding == TypeBinding.DOUBLE))
4390
							case TypeIds.T_long :
4396
							argSize += 2;
4391
							case TypeIds.T_double :
4397
						else
4392
								argSize += 2;
4398
							argSize++;
4393
								break;
4394
							default :
4395
								argSize++;
4396
								break;
4397
						}
4399
						this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
4398
						this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
4400
						this.contents[localContentsOffset++] = (byte) resolvedPosition;
4399
						this.contents[localContentsOffset++] = (byte) resolvedPosition;
4401
					}
4400
					}
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java (-25 / +3 lines)
Lines 11-17 Link Here
11
package org.eclipse.jdt.internal.compiler.lookup;
11
package org.eclipse.jdt.internal.compiler.lookup;
12
12
13
import java.util.HashMap;
13
import java.util.HashMap;
14
import java.util.Hashtable;
15
import java.util.Iterator;
14
import java.util.Iterator;
16
15
17
import org.eclipse.jdt.core.compiler.CharOperation;
16
import org.eclipse.jdt.core.compiler.CharOperation;
Lines 26-33 Link Here
26
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
25
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
27
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
26
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
28
import org.eclipse.jdt.internal.compiler.impl.Constant;
27
import org.eclipse.jdt.internal.compiler.impl.Constant;
29
import org.eclipse.jdt.internal.compiler.util.Util;
30
import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
28
import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
29
import org.eclipse.jdt.internal.compiler.util.Util;
31
30
32
public class SourceTypeBinding extends ReferenceBinding {
31
public class SourceTypeBinding extends ReferenceBinding {
33
	public ReferenceBinding superclass;
32
	public ReferenceBinding superclass;
Lines 39-53 Link Here
39
38
40
	public ClassScope scope;
39
	public ClassScope scope;
41
40
42
	// Synthetics are separated into 5 categories: methods, super methods, fields, class literals, changed declaring type bindings and bridge methods
41
	// Synthetics are separated into 4 categories: methods, super methods, fields, class literals and bridge methods
43
	// if a new category is added, also increment MAX_SYNTHETICS
42
	// if a new category is added, also increment MAX_SYNTHETICS
44
	private final static int METHOD_EMUL = 0;
43
	private final static int METHOD_EMUL = 0;
45
	private final static int FIELD_EMUL = 1;
44
	private final static int FIELD_EMUL = 1;
46
	private final static int CLASS_LITERAL_EMUL = 2;
45
	private final static int CLASS_LITERAL_EMUL = 2;
47
	/** @deprecated */
48
	private final static int RECEIVER_TYPE_EMUL = 3;
49
46
50
	private final static int MAX_SYNTHETICS = 4;
47
	private final static int MAX_SYNTHETICS = 3;
51
48
52
	HashMap[] synthetics;
49
	HashMap[] synthetics;
53
	char[] genericReferenceTypeSignature;
50
	char[] genericReferenceTypeSignature;
Lines 1065-1089 Link Here
1065
public ReferenceBinding[] memberTypes() {
1062
public ReferenceBinding[] memberTypes() {
1066
	return this.memberTypes;
1063
	return this.memberTypes;
1067
}
1064
}
1068
///** @deprecated */
1069
public FieldBinding getUpdatedFieldBinding(FieldBinding targetField, ReferenceBinding newDeclaringClass) {
1070
	if (this.synthetics == null)
1071
		this.synthetics = new HashMap[MAX_SYNTHETICS];
1072
	if (this.synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL] == null)
1073
		this.synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL] = new HashMap(5);
1074
1075
	Hashtable fieldMap = (Hashtable) this.synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL].get(targetField);
1076
	if (fieldMap == null) {
1077
		fieldMap = new Hashtable(5);
1078
		this.synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL].put(targetField, fieldMap);
1079
	}
1080
	FieldBinding updatedField = (FieldBinding) fieldMap.get(newDeclaringClass);
1081
	if (updatedField == null){
1082
		updatedField = new FieldBinding(targetField, newDeclaringClass);
1083
		fieldMap.put(newDeclaringClass, updatedField);
1084
	}
1085
	return updatedField;
1086
}
1087
1065
1088
public boolean hasMemberTypes() {
1066
public boolean hasMemberTypes() {
1089
    return this.memberTypes.length > 0;
1067
    return this.memberTypes.length > 0;
(-)codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java (-4 / +4 lines)
Lines 1927-1934 Link Here
1927
				long completionPosition = fieldRef.nameSourcePosition;
1927
				long completionPosition = fieldRef.nameSourcePosition;
1928
				this.javadocTagPosition = fieldRef.tagSourceStart;
1928
				this.javadocTagPosition = fieldRef.tagSourceStart;
1929
1929
1930
				if (fieldRef.receiverType != null && fieldRef.receiverType.isValidBinding()) {
1930
				if (fieldRef.actualReceiverType != null && fieldRef.actualReceiverType.isValidBinding()) {
1931
					ReferenceBinding receiverType = (ReferenceBinding) fieldRef.receiverType;
1931
					ReferenceBinding receiverType = (ReferenceBinding) fieldRef.actualReceiverType;
1932
					int rangeStart = (int) (completionPosition >>> 32);
1932
					int rangeStart = (int) (completionPosition >>> 32);
1933
					if (fieldRef.receiver.isThis()) {
1933
					if (fieldRef.receiver.isThis()) {
1934
						if (fieldRef.completeInText()) {
1934
						if (fieldRef.completeInText()) {
Lines 1984-1991 Link Here
1984
							null,
1984
							null,
1985
							-1,
1985
							-1,
1986
							-1);
1986
							-1);
1987
						if (fieldRef.receiverType instanceof ReferenceBinding) {
1987
						if (fieldRef.actualReceiverType instanceof ReferenceBinding) {
1988
							ReferenceBinding refBinding = (ReferenceBinding)fieldRef.receiverType;
1988
							ReferenceBinding refBinding = (ReferenceBinding)fieldRef.actualReceiverType;
1989
							if (this.completionToken == null
1989
							if (this.completionToken == null
1990
									|| CharOperation.prefixEquals(this.completionToken, refBinding.sourceName)
1990
									|| CharOperation.prefixEquals(this.completionToken, refBinding.sourceName)
1991
									|| (this.options.camelCaseMatch && CharOperation.camelCaseMatch(this.completionToken, refBinding.sourceName))) {
1991
									|| (this.options.camelCaseMatch && CharOperation.camelCaseMatch(this.completionToken, refBinding.sourceName))) {
(-)src/org/eclipse/jdt/core/tests/eval/CodeSnippetTest.java (+193 lines)
Lines 675-680 Link Here
675
		"10".toCharArray());
675
		"10".toCharArray());
676
}
676
}
677
/**
677
/**
678
 * Tests that the run() method defined in an anonymous class doesn't interfer with the
679
 * code snippet support (see PR #1G1C0HR).
680
 */
681
public void testRunMethodInAnonymous2() {
682
	evaluateWithExpectedDisplayString(buildCharArray(new String[] {
683
		"class X {",
684
		"	public int i = 0;",
685
		"   public boolean finished = false;",
686
		"}",
687
		"final X x = new X();",
688
		"(new Thread() {",
689
		"	public void run() {",
690
		"		for (int i=0;i<10;i++) {",
691
		"			try {",
692
		"				Thread.currentThread().sleep(10);",
693
		"			} catch (InterruptedException e) {",
694
		"			}",
695
		"			++x.i;",
696
		"		}",
697
		"       x.finished = true;",
698
		"	}",
699
		"}).start();",
700
		"while (!x.finished) Thread.currentThread().sleep(100);",
701
		"x.i"}),
702
		"10".toCharArray());
703
}
704
/**
705
 * Tests that the run() method defined in an anonymous class doesn't interfer with the
706
 * code snippet support (see PR #1G1C0HR).
707
 */
708
public void testRunMethodInAnonymous3() {
709
	evaluateWithExpectedDisplayString(buildCharArray(new String[] {
710
		"class X {",
711
		"	public int i = 0;",
712
		"   public boolean finished = false;",
713
		"}",
714
		"final X x = new X();",
715
		"(new Thread() {",
716
		"	public void run() {",
717
		"		for (int i=0;i<10;i++) {",
718
		"			try {",
719
		"				Thread.currentThread().sleep(10);",
720
		"			} catch (InterruptedException e) {",
721
		"			}",
722
		"			x.i += 1;",
723
		"		}",
724
		"       x.finished = true;",
725
		"	}",
726
		"}).start();",
727
		"while (!x.finished) Thread.currentThread().sleep(100);",
728
		"x.i"}),
729
		"10".toCharArray());
730
}
731
/**
732
 * Tests that the run() method defined in an anonymous class doesn't interfer with the
733
 * code snippet support (see PR #1G1C0HR).
734
 */
735
public void testRunMethodInAnonymous4() {
736
	evaluateWithExpectedDisplayString(buildCharArray(new String[] {
737
		"class X {",
738
		"	public int i = 0;",
739
		"   public boolean finished = false;",
740
		"}",
741
		"final X x = new X();",
742
		"(new Thread() {",
743
		"	public void run() {",
744
		"		for (int i=0;i<10;i++) {",
745
		"			try {",
746
		"				Thread.currentThread().sleep(10);",
747
		"			} catch (InterruptedException e) {",
748
		"			}",
749
		"			x.i = x.i + 1;",
750
		"		}",
751
		"       x.finished = true;",
752
		"	}",
753
		"}).start();",
754
		"while (!x.finished) Thread.currentThread().sleep(100);",
755
		"x.i"}),
756
		"10".toCharArray());
757
}
758
/**
759
 * Tests that the run() method defined in an anonymous class doesn't interfer with the
760
 * code snippet support (see PR #1G1C0HR).
761
 */
762
public void testRunMethodInAnonymous5() {
763
	evaluateWithExpectedDisplayString(buildCharArray(new String[] {
764
		"class X {",
765
		"	public int i = 0;",
766
		"   public boolean finished = false;",
767
		"	public X self() { return this; }",
768
		"}",
769
		"final X x = new X();",
770
		"(new Thread() {",
771
		"	public void run() {",
772
		"		for (int i=0;i<10;i++) {",
773
		"			try {",
774
		"				Thread.currentThread().sleep(10);",
775
		"			} catch (InterruptedException e) {",
776
		"			}",
777
		"			x.self().i++;",
778
		"		}",
779
		"       x.finished = true;",
780
		"	}",
781
		"}).start();",
782
		"while (!x.finished) Thread.currentThread().sleep(100);",
783
		"x.i"}),
784
		"10".toCharArray());
785
}
786
/**
787
 * Tests that the run() method defined in an anonymous class doesn't interfer with the
788
 * code snippet support (see PR #1G1C0HR).
789
 */
790
public void testRunMethodInAnonymous6() {
791
	evaluateWithExpectedDisplayString(buildCharArray(new String[] {
792
		"class X {",
793
		"	public int i = 0;",
794
		"   public boolean finished = false;",
795
		"	public X self() { return this; }",
796
		"}",
797
		"final X x = new X();",
798
		"(new Thread() {",
799
		"	public void run() {",
800
		"		for (int i=0;i<10;i++) {",
801
		"			try {",
802
		"				Thread.currentThread().sleep(10);",
803
		"			} catch (InterruptedException e) {",
804
		"			}",
805
		"			++ (x.self().i);",
806
		"		}",
807
		"       x.finished = true;",
808
		"	}",
809
		"}).start();",
810
		"while (!x.finished) Thread.currentThread().sleep(100);",
811
		"x.i"}),
812
		"10".toCharArray());
813
}
814
/**
815
 * Tests that the run() method defined in an anonymous class doesn't interfer with the
816
 * code snippet support (see PR #1G1C0HR).
817
 */
818
public void testRunMethodInAnonymous7() {
819
	evaluateWithExpectedDisplayString(buildCharArray(new String[] {
820
		"class X {",
821
		"	public int i = 0;",
822
		"   public boolean finished = false;",
823
		"	public X self() { return this; }",
824
		"}",
825
		"final X x = new X();",
826
		"(new Thread() {",
827
		"	public void run() {",
828
		"		for (int i=0;i<10;i++) {",
829
		"			try {",
830
		"				Thread.currentThread().sleep(10);",
831
		"			} catch (InterruptedException e) {",
832
		"			}",
833
		"			x.self().i += 1;",
834
		"		}",
835
		"       x.finished = true;",
836
		"	}",
837
		"}).start();",
838
		"while (!x.finished) Thread.currentThread().sleep(100);",
839
		"x.i"}),
840
		"10".toCharArray());
841
}
842
/**
843
 * Tests that the run() method defined in an anonymous class doesn't interfer with the
844
 * code snippet support (see PR #1G1C0HR).
845
 */
846
public void testRunMethodInAnonymous8() {
847
	evaluateWithExpectedDisplayString(buildCharArray(new String[] {
848
		"class X {",
849
		"	public int i = 0;",
850
		"   public boolean finished = false;",
851
		"	public X self() { return this; }",
852
		"}",
853
		"final X x = new X();",
854
		"(new Thread() {",
855
		"	public void run() {",
856
		"		for (int i=0;i<10;i++) {",
857
		"			try {",
858
		"				Thread.currentThread().sleep(10);",
859
		"			} catch (InterruptedException e) {",
860
		"			}",
861
		"			x.self().i = x.self().i + 1;",
862
		"		}",
863
		"       x.finished = true;",
864
		"	}",
865
		"}).start();",
866
		"while (!x.finished) Thread.currentThread().sleep(100);",
867
		"x.i"}),
868
		"10".toCharArray());
869
}
870
/**
678
 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=89632
871
 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=89632
679
 */
872
 */
680
public void testFor89632() {
873
public void testFor89632() {
(-)src/org/eclipse/jdt/core/tests/eval/DebugEvaluationTest.java (-3 / +1 lines)
Lines 731-737 Link Here
731
/**
731
/**
732
 * changing the value of a public field
732
 * changing the value of a public field
733
 */
733
 */
734
public void test018() throws Exception {
734
public void testONLY_018() throws Exception {
735
	try {
735
	try {
736
		String sourceA018 =
736
		String sourceA018 =
737
			"public class A018 {\n" +
737
			"public class A018 {\n" +
Lines 967-974 Link Here
967
				+ "\tpublic String c = null;\n"
967
				+ "\tpublic String c = null;\n"
968
				+ "}";
968
				+ "}";
969
		compileAndDeploy(sourceC23, "C23");
969
		compileAndDeploy(sourceC23, "C23");
970
971
972
		String sourceB23 =
970
		String sourceB23 =
973
			"public class B23 {\n"
971
			"public class B23 {\n"
974
				+ "\tpublic C23 c = new C23();\n"
972
				+ "\tpublic C23 c = new C23();\n"

Return to bug 247612