1 11 package org.eclipse.jdt.internal.compiler.ast; 12 13 import org.eclipse.jdt.internal.compiler.ASTVisitor; 14 import org.eclipse.jdt.internal.compiler.ClassFile; 15 import org.eclipse.jdt.internal.compiler.CompilationResult; 16 import org.eclipse.jdt.internal.compiler.codegen.BranchLabel; 17 import org.eclipse.jdt.internal.compiler.codegen.CodeStream; 18 import org.eclipse.jdt.internal.compiler.codegen.ConstantPool; 19 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.InitializationFlowContext; 22 import org.eclipse.jdt.internal.compiler.lookup.Binding; 23 import org.eclipse.jdt.internal.compiler.lookup.BlockScope; 24 import org.eclipse.jdt.internal.compiler.lookup.ClassScope; 25 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; 26 import org.eclipse.jdt.internal.compiler.lookup.MethodScope; 27 import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; 28 import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; 29 import org.eclipse.jdt.internal.compiler.parser.Parser; 30 import org.eclipse.jdt.internal.compiler.problem.AbortMethod; 31 32 public class Clinit extends AbstractMethodDeclaration { 33 34 private FieldBinding assertionSyntheticFieldBinding = null; 35 private FieldBinding classLiteralSyntheticField = null; 36 37 public Clinit(CompilationResult compilationResult) { 38 super(compilationResult); 39 modifiers = 0; 40 selector = TypeConstants.CLINIT; 41 } 42 43 public void analyseCode( 44 ClassScope classScope, 45 InitializationFlowContext staticInitializerFlowContext, 46 FlowInfo flowInfo) { 47 48 if (ignoreFurtherInvestigation) 49 return; 50 try { 51 ExceptionHandlingFlowContext clinitContext = 52 new ExceptionHandlingFlowContext( 53 staticInitializerFlowContext.parent, 54 this, 55 Binding.NO_EXCEPTIONS, 56 scope, 57 FlowInfo.DEAD_END); 58 59 if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) { 61 this.bits |= ASTNode.NeedFreeReturn; 62 } 63 64 flowInfo = flowInfo.mergedWith(staticInitializerFlowContext.initsOnReturn); 66 FieldBinding[] fields = scope.enclosingSourceType().fields(); 67 for (int i = 0, count = fields.length; i < count; i++) { 68 FieldBinding field; 69 if ((field = fields[i]).isStatic() 70 && field.isFinal() 71 && (!flowInfo.isDefinitelyAssigned(fields[i]))) { 72 scope.problemReporter().uninitializedBlankFinalField( 73 field, 74 scope.referenceType().declarationOf(field.original())); 75 } 77 } 78 staticInitializerFlowContext.checkInitializerExceptions( 80 scope, 81 clinitContext, 82 flowInfo); 83 } catch (AbortMethod e) { 84 this.ignoreFurtherInvestigation = true; 85 } 86 } 87 88 94 public void generateCode(ClassScope classScope, ClassFile classFile) { 95 96 int clinitOffset = 0; 97 if (ignoreFurtherInvestigation) { 98 return; 100 } 101 try { 102 clinitOffset = classFile.contentsOffset; 103 this.generateCode(classScope, classFile, clinitOffset); 104 } catch (AbortMethod e) { 105 if (e.compilationResult == CodeStream.RESTART_IN_WIDE_MODE) { 113 try { 115 classFile.contentsOffset = clinitOffset; 116 classFile.methodCount--; 117 classFile.codeStream.wideMode = true; this.generateCode(classScope, classFile, clinitOffset); 119 } catch (AbortMethod e2) { 121 classFile.contentsOffset = clinitOffset; 122 classFile.methodCount--; 123 } 124 } else { 125 classFile.contentsOffset = clinitOffset; 127 classFile.methodCount--; 128 } 129 } 130 } 131 132 138 private void generateCode( 139 ClassScope classScope, 140 ClassFile classFile, 141 int clinitOffset) { 142 143 ConstantPool constantPool = classFile.constantPool; 144 int constantPoolOffset = constantPool.currentOffset; 145 int constantPoolIndex = constantPool.currentIndex; 146 classFile.generateMethodInfoHeaderForClinit(); 147 int codeAttributeOffset = classFile.contentsOffset; 148 classFile.generateCodeAttributeHeader(); 149 CodeStream codeStream = classFile.codeStream; 150 this.resolve(classScope); 151 152 codeStream.reset(this, classFile); 153 TypeDeclaration declaringType = classScope.referenceContext; 154 155 MethodScope staticInitializerScope = declaringType.staticInitializerScope; 157 staticInitializerScope.computeLocalVariablePositions(0, codeStream); 158 159 if (this.assertionSyntheticFieldBinding != null) { 162 codeStream.generateClassLiteralAccessForType( 164 classScope.outerMostClassScope().enclosingSourceType(), 165 this.classLiteralSyntheticField); 166 codeStream.invokeJavaLangClassDesiredAssertionStatus(); 167 BranchLabel falseLabel = new BranchLabel(codeStream); 168 codeStream.ifne(falseLabel); 169 codeStream.iconst_1(); 170 BranchLabel jumpLabel = new BranchLabel(codeStream); 171 codeStream.decrStackSize(1); 172 codeStream.goto_(jumpLabel); 173 falseLabel.place(); 174 codeStream.iconst_0(); 175 jumpLabel.place(); 176 codeStream.putstatic(this.assertionSyntheticFieldBinding); 177 } 178 final FieldDeclaration[] fieldDeclarations = declaringType.fields; 180 BlockScope lastInitializerScope = null; 181 if (TypeDeclaration.kind(declaringType.modifiers) == TypeDeclaration.ENUM_DECL) { 182 int enumCount = 0; 183 int remainingFieldCount = 0; 184 if (fieldDeclarations != null) { 185 for (int i = 0, max = fieldDeclarations.length; i < max; i++) { 186 FieldDeclaration fieldDecl = fieldDeclarations[i]; 187 if (fieldDecl.isStatic()) { 188 if (fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) { 189 fieldDecl.generateCode(staticInitializerScope, codeStream); 190 enumCount++; 191 } else { 192 remainingFieldCount++; 193 } 194 } 195 } 196 } 197 codeStream.generateInlinedValue(enumCount); 200 codeStream.anewarray(declaringType.binding); 201 if (enumCount > 0) { 202 if (fieldDeclarations != null) { 203 for (int i = 0, max = fieldDeclarations.length; i < max; i++) { 204 FieldDeclaration fieldDecl = fieldDeclarations[i]; 205 if (fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) { 207 codeStream.dup(); 208 codeStream.generateInlinedValue(fieldDecl.binding.id); 209 codeStream.getstatic(fieldDecl.binding); 210 codeStream.aastore(); 211 } 212 } 213 } 214 } 215 codeStream.putstatic(declaringType.enumValuesSyntheticfield); 216 if (remainingFieldCount != 0) { 217 for (int i = 0, max = fieldDeclarations.length; i < max; i++) { 219 FieldDeclaration fieldDecl = fieldDeclarations[i]; 220 switch (fieldDecl.getKind()) { 221 case AbstractVariableDeclaration.ENUM_CONSTANT : 222 break; 223 case AbstractVariableDeclaration.INITIALIZER : 224 if (!fieldDecl.isStatic()) 225 break; 226 lastInitializerScope = ((Initializer) fieldDecl).block.scope; 227 fieldDecl.generateCode(staticInitializerScope, codeStream); 228 break; 229 case AbstractVariableDeclaration.FIELD : 230 if (!fieldDecl.binding.isStatic()) 231 break; 232 lastInitializerScope = null; 233 fieldDecl.generateCode(staticInitializerScope, codeStream); 234 break; 235 } 236 } 237 } 238 } else { 239 if (fieldDeclarations != null) { 240 for (int i = 0, max = fieldDeclarations.length; i < max; i++) { 241 FieldDeclaration fieldDecl = fieldDeclarations[i]; 242 switch (fieldDecl.getKind()) { 243 case AbstractVariableDeclaration.INITIALIZER : 244 if (!fieldDecl.isStatic()) 245 break; 246 lastInitializerScope = ((Initializer) fieldDecl).block.scope; 247 fieldDecl.generateCode(staticInitializerScope, codeStream); 248 break; 249 case AbstractVariableDeclaration.FIELD : 250 if (!fieldDecl.binding.isStatic()) 251 break; 252 lastInitializerScope = null; 253 fieldDecl.generateCode(staticInitializerScope, codeStream); 254 break; 255 } 256 } 257 } 258 } 259 260 if (codeStream.position == 0) { 261 classFile.contentsOffset = clinitOffset; 264 classFile.methodCount--; 266 constantPool.resetForClinit(constantPoolIndex, constantPoolOffset); 268 } else { 269 if ((this.bits & ASTNode.NeedFreeReturn) != 0) { 270 int before = codeStream.position; 271 codeStream.return_(); 272 if (lastInitializerScope != null) { 273 codeStream.updateLastRecordedEndPC(lastInitializerScope, before); 275 } 276 } 277 codeStream.recordPositionsFrom(0, declaringType.sourceStart); 279 classFile.completeCodeAttributeForClinit(codeAttributeOffset); 280 } 281 } 282 283 public boolean isClinit() { 284 285 return true; 286 } 287 288 public boolean isInitializationMethod() { 289 290 return true; 291 } 292 293 public boolean isStatic() { 294 295 return true; 296 } 297 298 public void parseStatements(Parser parser, CompilationUnitDeclaration unit) { 299 } 301 302 public StringBuffer print(int tab, StringBuffer output) { 303 304 printIndent(tab, output).append("<clinit>()"); printBody(tab + 1, output); 306 return output; 307 } 308 309 public void resolve(ClassScope classScope) { 310 311 this.scope = new MethodScope(classScope, classScope.referenceContext, true); 312 } 313 314 public void traverse( 315 ASTVisitor visitor, 316 ClassScope classScope) { 317 318 visitor.visit(this, classScope); 319 visitor.endVisit(this, classScope); 320 } 321 322 public void setAssertionSupport(FieldBinding assertionSyntheticFieldBinding, boolean needClassLiteralField) { 323 324 this.assertionSyntheticFieldBinding = assertionSyntheticFieldBinding; 325 326 if (needClassLiteralField) { 328 SourceTypeBinding sourceType = 329 this.scope.outerMostClassScope().enclosingSourceType(); 330 if (!sourceType.isInterface() && !sourceType.isBaseType()) { 332 this.classLiteralSyntheticField = sourceType.addSyntheticFieldForClassLiteral(sourceType, scope); 333 } 334 } 335 } 336 337 } 338 | Popular Tags |