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 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.fieldAccess0(Opcodes.OPC_getstatic, lastFieldBinding, constantPoolDeclaringClass); |
401 |
} else { |
348 |
} else { |
402 |
codeStream.getfield(lastFieldBinding); |
349 |
codeStream.fieldAccess0(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 436-464
Link Here
|
436 |
codeStream.recordPositionsFrom(pc, this.sourceStart); |
383 |
codeStream.recordPositionsFrom(pc, this.sourceStart); |
437 |
} |
384 |
} |
438 |
|
385 |
|
439 |
public void generateCompoundAssignment( |
386 |
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); |
387 |
FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream); |
448 |
SyntheticMethodBinding accessor = |
388 |
boolean isFirst = lastFieldBinding == this.binding |
449 |
this.syntheticReadAccessors == null |
389 |
&& (this.indexOfFirstFieldBinding == 1 || lastFieldBinding.declaringClass == currentScope.enclosingReceiverType()) |
450 |
? null |
390 |
&& this.otherBindings == null; // could be dup: next.next.next |
451 |
: this.syntheticReadAccessors[this.syntheticReadAccessors.length - 1]; |
391 |
TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, lastFieldBinding, getFinalReceiverType(), isFirst); |
|
|
392 |
SyntheticMethodBinding accessor = this.syntheticReadAccessors == null ? null : this.syntheticReadAccessors[this.syntheticReadAccessors.length - 1]; |
452 |
if (lastFieldBinding.isStatic()) { |
393 |
if (lastFieldBinding.isStatic()) { |
453 |
if (accessor == null) { |
394 |
if (accessor == null) { |
454 |
codeStream.getstatic(lastFieldBinding); |
395 |
codeStream.fieldAccess0(Opcodes.OPC_getstatic, lastFieldBinding, constantPoolDeclaringClass); |
455 |
} else { |
396 |
} else { |
456 |
codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */); |
397 |
codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */); |
457 |
} |
398 |
} |
458 |
} else { |
399 |
} else { |
459 |
codeStream.dup(); |
400 |
codeStream.dup(); |
460 |
if (accessor == null) { |
401 |
if (accessor == null) { |
461 |
codeStream.getfield(lastFieldBinding); |
402 |
codeStream.fieldAccess0(Opcodes.OPC_getfield, lastFieldBinding, constantPoolDeclaringClass); |
462 |
} else { |
403 |
} else { |
463 |
codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */); |
404 |
codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */); |
464 |
} |
405 |
} |
Lines 473-479
Link Here
|
473 |
codeStream.generateStringConcatenationAppend(currentScope, null, expression); |
414 |
codeStream.generateStringConcatenationAppend(currentScope, null, expression); |
474 |
break; |
415 |
break; |
475 |
default : |
416 |
default : |
476 |
TypeBinding requiredGenericCast = getGenericCast(this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length); |
417 |
TypeBinding requiredGenericCast = getGenericCast(this.otherBindings == null ? 0 : this.otherBindings.length); |
477 |
if (requiredGenericCast != null) codeStream.checkcast(requiredGenericCast); |
418 |
if (requiredGenericCast != null) codeStream.checkcast(requiredGenericCast); |
478 |
// promote the array reference to the suitable operation type |
419 |
// promote the array reference to the suitable operation type |
479 |
codeStream.generateImplicitConversion(this.implicitConversion); |
420 |
codeStream.generateImplicitConversion(this.implicitConversion); |
Lines 495-518
Link Here
|
495 |
|
436 |
|
496 |
public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) { |
437 |
public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) { |
497 |
FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream); |
438 |
FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream); |
|
|
439 |
boolean isFirst = lastFieldBinding == this.binding |
440 |
&& (this.indexOfFirstFieldBinding == 1 || lastFieldBinding.declaringClass == currentScope.enclosingReceiverType()) |
441 |
&& this.otherBindings == null; // could be dup: next.next.next |
442 |
TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, lastFieldBinding, getFinalReceiverType(), isFirst); |
498 |
SyntheticMethodBinding accessor = this.syntheticReadAccessors == null |
443 |
SyntheticMethodBinding accessor = this.syntheticReadAccessors == null |
499 |
? null |
444 |
? null |
500 |
: this.syntheticReadAccessors[this.syntheticReadAccessors.length - 1]; |
445 |
: this.syntheticReadAccessors[this.syntheticReadAccessors.length - 1]; |
501 |
if (lastFieldBinding.isStatic()) { |
446 |
if (lastFieldBinding.isStatic()) { |
502 |
if (accessor == null) { |
447 |
if (accessor == null) { |
503 |
codeStream.getstatic(lastFieldBinding); |
448 |
codeStream.fieldAccess0(Opcodes.OPC_getstatic, lastFieldBinding, constantPoolDeclaringClass); |
504 |
} else { |
449 |
} else { |
505 |
codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */); |
450 |
codeStream.invoke(Opcodes.OPC_invokestatic, accessor, constantPoolDeclaringClass); |
506 |
} |
451 |
} |
507 |
} else { |
452 |
} else { |
508 |
codeStream.dup(); |
453 |
codeStream.dup(); |
509 |
if (accessor == null) { |
454 |
if (accessor == null) { |
510 |
codeStream.getfield(lastFieldBinding); |
455 |
codeStream.fieldAccess0(Opcodes.OPC_getfield, lastFieldBinding, null /* default declaringClass */); |
511 |
} else { |
456 |
} else { |
512 |
codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */); |
457 |
codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */); |
513 |
} |
458 |
} |
514 |
} |
459 |
} |
515 |
TypeBinding requiredGenericCast = getGenericCast(this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length); |
460 |
TypeBinding requiredGenericCast = getGenericCast(this.otherBindings == null ? 0 : this.otherBindings.length); |
516 |
TypeBinding operandType; |
461 |
TypeBinding operandType; |
517 |
if (requiredGenericCast != null) { |
462 |
if (requiredGenericCast != null) { |
518 |
codeStream.checkcast(requiredGenericCast); |
463 |
codeStream.checkcast(requiredGenericCast); |
Lines 523-541
Link Here
|
523 |
// duplicate the old field value |
468 |
// duplicate the old field value |
524 |
if (valueRequired) { |
469 |
if (valueRequired) { |
525 |
if (lastFieldBinding.isStatic()) { |
470 |
if (lastFieldBinding.isStatic()) { |
526 |
if ((operandType == TypeBinding.LONG) |
471 |
switch (operandType.id) { |
527 |
|| (operandType == TypeBinding.DOUBLE)) { |
472 |
case TypeIds.T_long : |
528 |
codeStream.dup2(); |
473 |
case TypeIds.T_double : |
529 |
} else { |
474 |
codeStream.dup2(); |
530 |
codeStream.dup(); |
475 |
break; |
531 |
} |
476 |
default: |
|
|
477 |
codeStream.dup(); |
478 |
break; |
479 |
} |
532 |
} else { // Stack: [owner][old field value] ---> [old field value][owner][old field value] |
480 |
} else { // Stack: [owner][old field value] ---> [old field value][owner][old field value] |
533 |
if ((operandType == TypeBinding.LONG) |
481 |
switch (operandType.id) { |
534 |
|| (operandType == TypeBinding.DOUBLE)) { |
482 |
case TypeIds.T_long : |
535 |
codeStream.dup2_x1(); |
483 |
case TypeIds.T_double : |
536 |
} else { |
484 |
codeStream.dup2_x1(); |
537 |
codeStream.dup_x1(); |
485 |
break; |
538 |
} |
486 |
default: |
|
|
487 |
codeStream.dup_x1(); |
488 |
break; |
489 |
} |
539 |
} |
490 |
} |
540 |
} |
491 |
} |
541 |
codeStream.generateImplicitConversion(this.implicitConversion); |
492 |
codeStream.generateImplicitConversion(this.implicitConversion); |
Lines 554-569
Link Here
|
554 |
*/ |
505 |
*/ |
555 |
public FieldBinding generateReadSequence(BlockScope currentScope, CodeStream codeStream) { |
506 |
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 |
507 |
// 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; |
508 |
int otherBindingsCount = this.otherBindings == null ? 0 : this.otherBindings.length; |
558 |
boolean needValue = otherBindingsCount == 0 || !this.otherBindings[0].isStatic(); |
509 |
boolean needValue = otherBindingsCount == 0 || !this.otherBindings[0].isStatic(); |
559 |
FieldBinding lastFieldBinding = null; |
510 |
FieldBinding lastFieldBinding; |
560 |
TypeBinding lastGenericCast = null; |
511 |
TypeBinding lastGenericCast; |
|
|
512 |
TypeBinding lastReceiverType; |
561 |
boolean complyTo14 = currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4; |
513 |
boolean complyTo14 = currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4; |
562 |
|
514 |
|
563 |
switch (this.bits & ASTNode.RestrictiveFlagMASK) { |
515 |
switch (this.bits & ASTNode.RestrictiveFlagMASK) { |
564 |
case Binding.FIELD : |
516 |
case Binding.FIELD : |
565 |
lastFieldBinding = (FieldBinding) this.codegenBinding; |
517 |
lastFieldBinding = ((FieldBinding) this.binding).original(); |
566 |
lastGenericCast = this.genericCast; |
518 |
lastGenericCast = this.genericCast; |
|
|
519 |
lastReceiverType = this.actualReceiverType; |
567 |
// if first field is actually constant, we can inline it |
520 |
// if first field is actually constant, we can inline it |
568 |
if (lastFieldBinding.constant() != Constant.NotAConstant) { |
521 |
if (lastFieldBinding.constant() != Constant.NotAConstant) { |
569 |
break; |
522 |
break; |
Lines 581-588
Link Here
|
581 |
} |
534 |
} |
582 |
break; |
535 |
break; |
583 |
case Binding.LOCAL : // reading the first local variable |
536 |
case Binding.LOCAL : // reading the first local variable |
|
|
537 |
lastFieldBinding = null; |
538 |
lastGenericCast = null; |
539 |
lastReceiverType = null; |
584 |
if (!needValue) break; // no value needed |
540 |
if (!needValue) break; // no value needed |
585 |
LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding; |
541 |
LocalVariableBinding localBinding = (LocalVariableBinding) this.binding; |
586 |
// regular local variable read |
542 |
// regular local variable read |
587 |
Constant localConstant = localBinding.constant(); |
543 |
Constant localConstant = localBinding.constant(); |
588 |
if (localConstant != Constant.NotAConstant) { |
544 |
if (localConstant != Constant.NotAConstant) { |
Lines 598-612
Link Here
|
598 |
codeStream.load(localBinding); |
554 |
codeStream.load(localBinding); |
599 |
} |
555 |
} |
600 |
} |
556 |
} |
|
|
557 |
break; |
558 |
default : // should not occur |
559 |
return null; |
601 |
} |
560 |
} |
602 |
|
561 |
|
603 |
// all intermediate field accesses are read accesses |
562 |
// all intermediate field accesses are read accesses |
604 |
// only the last field binding is a write access |
563 |
// only the last field binding is a write access |
605 |
int positionsLength = this.sourcePositions.length; |
564 |
int positionsLength = this.sourcePositions.length; |
606 |
if (this.otherCodegenBindings != null) { |
565 |
FieldBinding initialFieldBinding = lastFieldBinding; // can be null if initial was a local binding |
|
|
566 |
if (this.otherBindings != null) { |
607 |
for (int i = 0; i < otherBindingsCount; i++) { |
567 |
for (int i = 0; i < otherBindingsCount; i++) { |
608 |
int pc = codeStream.position; |
568 |
int pc = codeStream.position; |
609 |
FieldBinding nextField = this.otherCodegenBindings[i]; |
569 |
FieldBinding nextField = this.otherBindings[i].original(); |
610 |
TypeBinding nextGenericCast = this.otherGenericCasts == null ? null : this.otherGenericCasts[i]; |
570 |
TypeBinding nextGenericCast = this.otherGenericCasts == null ? null : this.otherGenericCasts[i]; |
611 |
if (lastFieldBinding != null) { |
571 |
if (lastFieldBinding != null) { |
612 |
needValue = !nextField.isStatic(); |
572 |
needValue = !nextField.isStatic(); |
Lines 623-632
Link Here
|
623 |
if (needValue || (i > 0 && complyTo14) || lastGenericCast != null) { |
583 |
if (needValue || (i > 0 && complyTo14) || lastGenericCast != null) { |
624 |
MethodBinding accessor = this.syntheticReadAccessors == null ? null : this.syntheticReadAccessors[i]; |
584 |
MethodBinding accessor = this.syntheticReadAccessors == null ? null : this.syntheticReadAccessors[i]; |
625 |
if (accessor == null) { |
585 |
if (accessor == null) { |
|
|
586 |
TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, lastFieldBinding, lastReceiverType, i == 0 && this.indexOfFirstFieldBinding == 1); |
626 |
if (lastFieldBinding.isStatic()) { |
587 |
if (lastFieldBinding.isStatic()) { |
627 |
codeStream.getstatic(lastFieldBinding); |
588 |
codeStream.fieldAccess0(Opcodes.OPC_getstatic, lastFieldBinding, constantPoolDeclaringClass); |
628 |
} else { |
589 |
} else { |
629 |
codeStream.getfield(lastFieldBinding); |
590 |
codeStream.fieldAccess0(Opcodes.OPC_getfield, lastFieldBinding, constantPoolDeclaringClass); |
630 |
} |
591 |
} |
631 |
} else { |
592 |
} else { |
632 |
codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */); |
593 |
codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */); |
Lines 634-646
Link Here
|
634 |
if (lastGenericCast != null) codeStream.checkcast(lastGenericCast); |
595 |
if (lastGenericCast != null) codeStream.checkcast(lastGenericCast); |
635 |
if (!needValue) codeStream.pop(); |
596 |
if (!needValue) codeStream.pop(); |
636 |
} else { |
597 |
} else { |
637 |
if (this.codegenBinding == lastFieldBinding) { |
598 |
if (lastFieldBinding == initialFieldBinding) { |
638 |
if (lastFieldBinding.isStatic()){ |
599 |
if (lastFieldBinding.isStatic()){ |
639 |
// if no valueRequired, still need possible side-effects of <clinit> invocation, if field belongs to different class |
600 |
// 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()) { |
601 |
if (initialFieldBinding.declaringClass != this.actualReceiverType.erasure()) { |
641 |
MethodBinding accessor = this.syntheticReadAccessors == null ? null : this.syntheticReadAccessors[i]; |
602 |
MethodBinding accessor = this.syntheticReadAccessors == null ? null : this.syntheticReadAccessors[i]; |
642 |
if (accessor == null) { |
603 |
if (accessor == null) { |
643 |
codeStream.getstatic(lastFieldBinding); |
604 |
TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, lastFieldBinding, lastReceiverType, i == 0 && this.indexOfFirstFieldBinding == 1); |
|
|
605 |
codeStream.fieldAccess0(Opcodes.OPC_getstatic, lastFieldBinding, constantPoolDeclaringClass); |
644 |
} else { |
606 |
} else { |
645 |
codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */); |
607 |
codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */); |
646 |
} |
608 |
} |
Lines 658-663
Link Here
|
658 |
} |
620 |
} |
659 |
} |
621 |
} |
660 |
} |
622 |
} |
|
|
623 |
lastReceiverType = lastFieldBinding.type; |
661 |
lastFieldBinding = nextField; |
624 |
lastFieldBinding = nextField; |
662 |
lastGenericCast = nextGenericCast; |
625 |
lastGenericCast = nextGenericCast; |
663 |
} |
626 |
} |
Lines 676-690
Link Here
|
676 |
return null; |
639 |
return null; |
677 |
} |
640 |
} |
678 |
|
641 |
|
679 |
// get the matching codegenBinding |
|
|
680 |
protected FieldBinding getCodegenBinding(int index) { |
642 |
protected FieldBinding getCodegenBinding(int index) { |
681 |
if (index == 0){ |
643 |
if (index == 0){ |
682 |
return (FieldBinding)this.codegenBinding; |
644 |
return ((FieldBinding)this.binding).original(); |
683 |
} else { |
645 |
} else { |
684 |
return this.otherCodegenBindings[index-1]; |
646 |
return this.otherBindings[index-1].original(); |
685 |
} |
647 |
} |
686 |
} |
648 |
} |
687 |
|
649 |
|
|
|
650 |
/** |
651 |
* Returns the receiver type for the final field in sequence (i.e. the return type of the previous binding) |
652 |
* @return receiver type for the final field in sequence |
653 |
*/ |
654 |
protected TypeBinding getFinalReceiverType() { |
655 |
int otherBindingsCount = this.otherBindings == null ? 0 : this.otherBindings.length; |
656 |
switch (otherBindingsCount) { |
657 |
case 0 : |
658 |
return this.actualReceiverType; |
659 |
case 1 : |
660 |
return ((VariableBinding)this.binding).type; |
661 |
default: |
662 |
return this.otherBindings[otherBindingsCount-2].type; |
663 |
} |
664 |
} |
665 |
|
688 |
// get the matching generic cast |
666 |
// get the matching generic cast |
689 |
protected TypeBinding getGenericCast(int index) { |
667 |
protected TypeBinding getGenericCast(int index) { |
690 |
if (index == 0){ |
668 |
if (index == 0){ |
Lines 694-700
Link Here
|
694 |
return this.otherGenericCasts[index-1]; |
672 |
return this.otherGenericCasts[index-1]; |
695 |
} |
673 |
} |
696 |
} |
674 |
} |
697 |
|
|
|
698 |
public TypeBinding getOtherFieldBindings(BlockScope scope) { |
675 |
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) |
676 |
// 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; |
677 |
int length = this.tokens.length; |
Lines 730-736
Link Here
|
730 |
} |
707 |
} |
731 |
// allocation of the fieldBindings array and its respective constants |
708 |
// allocation of the fieldBindings array and its respective constants |
732 |
int otherBindingsLength = length - index; |
709 |
int otherBindingsLength = length - index; |
733 |
this.otherCodegenBindings = this.otherBindings = new FieldBinding[otherBindingsLength]; |
|
|
734 |
this.otherDepths = new int[otherBindingsLength]; |
710 |
this.otherDepths = new int[otherBindingsLength]; |
735 |
|
711 |
|
736 |
// fill the first constant (the one of the binding) |
712 |
// fill the first constant (the one of the binding) |
Lines 825-842
Link Here
|
825 |
/** |
801 |
/** |
826 |
* index is <0 to denote write access emulation |
802 |
* index is <0 to denote write access emulation |
827 |
*/ |
803 |
*/ |
828 |
public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FieldBinding fieldBinding, TypeBinding lastReceiverType, int index, FlowInfo flowInfo) { |
804 |
public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FieldBinding fieldBinding, int index, FlowInfo flowInfo) { |
829 |
if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0) return; |
805 |
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) |
806 |
// 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) |
807 |
if (fieldBinding.constant() != Constant.NotAConstant) |
832 |
return; |
808 |
return; |
833 |
|
809 |
|
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 |
810 |
if (fieldBinding.isPrivate()) { // private access |
841 |
FieldBinding someCodegenBinding = getCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index); |
811 |
FieldBinding someCodegenBinding = getCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index); |
842 |
if (someCodegenBinding.declaringClass != currentScope.enclosingSourceType()) { |
812 |
if (someCodegenBinding.declaringClass != currentScope.enclosingSourceType()) { |
Lines 852-885
Link Here
|
852 |
|
822 |
|
853 |
// implicit protected access |
823 |
// implicit protected access |
854 |
if (depth > 0 && (fieldBinding.declaringClass.getPackage() != currentScope.enclosingSourceType().getPackage())) { |
824 |
if (depth > 0 && (fieldBinding.declaringClass.getPackage() != currentScope.enclosingSourceType().getPackage())) { |
855 |
FieldBinding someCodegenBinding = getCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index); |
825 |
FieldBinding codegenField = getCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index); |
856 |
setSyntheticAccessor(fieldBinding, index, |
826 |
setSyntheticAccessor(fieldBinding, index, |
857 |
((SourceTypeBinding) currentScope.enclosingSourceType().enclosingTypeAt(depth)).addSyntheticMethod(someCodegenBinding, index >= 0 /*read-access?*/)); |
827 |
((SourceTypeBinding) currentScope.enclosingSourceType().enclosingTypeAt(depth)).addSyntheticMethod(codegenField, index >= 0 /*read-access?*/)); |
858 |
currentScope.problemReporter().needToEmulateFieldAccess(someCodegenBinding, this, index >= 0 /*read-access?*/); |
828 |
currentScope.problemReporter().needToEmulateFieldAccess(codegenField, this, index >= 0 /*read-access?*/); |
859 |
return; |
829 |
return; |
860 |
} |
830 |
} |
861 |
} |
831 |
} |
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 |
} |
832 |
} |
884 |
|
833 |
|
885 |
public int nullStatus(FlowInfo flowInfo) { |
834 |
public int nullStatus(FlowInfo flowInfo) { |
Lines 908-914
Link Here
|
908 |
*/ |
857 |
*/ |
909 |
public TypeBinding postConversionType(Scope scope) { |
858 |
public TypeBinding postConversionType(Scope scope) { |
910 |
TypeBinding convertedType = this.resolvedType; |
859 |
TypeBinding convertedType = this.resolvedType; |
911 |
TypeBinding requiredGenericCast = getGenericCast(this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length); |
860 |
TypeBinding requiredGenericCast = getGenericCast(this.otherBindings == null ? 0 : this.otherBindings.length); |
912 |
if (requiredGenericCast != null) |
861 |
if (requiredGenericCast != null) |
913 |
convertedType = requiredGenericCast; |
862 |
convertedType = requiredGenericCast; |
914 |
int runtimeType = (this.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4; |
863 |
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 |
922 |
// the TC is Flag_Type Flag_LocalField and Flag_TypeLocalField |
974 |
this.actualReceiverType = scope.enclosingReceiverType(); |
923 |
this.actualReceiverType = scope.enclosingReceiverType(); |
975 |
this.constant = Constant.NotAConstant; |
924 |
this.constant = Constant.NotAConstant; |
976 |
if ((this.codegenBinding = this.binding = scope.getBinding(this.tokens, this.bits & ASTNode.RestrictiveFlagMASK, this, true /*resolve*/)).isValidBinding()) { |
925 |
if ((this.binding = scope.getBinding(this.tokens, this.bits & ASTNode.RestrictiveFlagMASK, this, true /*resolve*/)).isValidBinding()) { |
977 |
switch (this.bits & ASTNode.RestrictiveFlagMASK) { |
926 |
switch (this.bits & ASTNode.RestrictiveFlagMASK) { |
978 |
case Binding.VARIABLE : //============only variable=========== |
927 |
case Binding.VARIABLE : //============only variable=========== |
979 |
case Binding.TYPE | Binding.VARIABLE : |
928 |
case Binding.TYPE | Binding.VARIABLE : |
Lines 1056-1074
Link Here
|
1056 |
return this.resolvedType = reportError(scope); |
1005 |
return this.resolvedType = reportError(scope); |
1057 |
} |
1006 |
} |
1058 |
|
1007 |
|
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) { |
1008 |
public void setFieldIndex(int index) { |
1073 |
this.indexOfFirstFieldBinding = index; |
1009 |
this.indexOfFirstFieldBinding = index; |
1074 |
} |
1010 |
} |