001 /* Copyright (c) 2005-2008, Torbjorn Ekman 002 * All rights reserved. 003 * 004 * Redistribution and use in source and binary forms, with or without 005 * modification, are permitted provided that the following conditions are met: 006 * 007 * 1. Redistributions of source code must retain the above copyright notice, 008 * this list of conditions and the following disclaimer. 009 * 010 * 2. Redistributions in binary form must reproduce the above copyright notice, 011 * this list of conditions and the following disclaimer in the documentation 012 * and/or other materials provided with the distribution. 013 * 014 * 3. Neither the name of the copyright holder nor the names of its 015 * contributors may be used to endorse or promote products derived from this 016 * software without specific prior written permission. 017 * 018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 021 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 022 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 023 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 024 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 025 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 026 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 027 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 028 * POSSIBILITY OF SUCH DAMAGE. 029 */ 030 031 aspect GenericsCodegen { 032 refine InnerClasses eq ClassDecl.superEnclosing() { 033 return superclass().erasure().enclosing(); 034 } 035 036 eq TypeVariable.typeDescriptor() = erasure().typeDescriptor(); 037 eq ParClassDecl.typeDescriptor() = erasure().typeDescriptor(); 038 eq ParInterfaceDecl.typeDescriptor() = erasure().typeDescriptor(); 039 040 eq GenericClassDeclSubstituted.typeDescriptor() = original().typeDescriptor(); 041 eq GenericInterfaceDeclSubstituted.typeDescriptor() = original().typeDescriptor(); 042 eq ClassDeclSubstituted.typeDescriptor() = original().typeDescriptor(); 043 eq InterfaceDeclSubstituted.typeDescriptor() = original().typeDescriptor(); 044 045 eq GenericClassDeclSubstituted.constantPoolName() = original().constantPoolName(); 046 eq GenericInterfaceDeclSubstituted.constantPoolName() = original().constantPoolName(); 047 eq ClassDeclSubstituted.constantPoolName() = original().constantPoolName(); 048 eq InterfaceDeclSubstituted.constantPoolName() = original().constantPoolName(); 049 050 eq ClassDeclSubstituted.uniqueIndex() = original().uniqueIndex(); 051 eq GenericClassDeclSubstituted.uniqueIndex() = original().uniqueIndex(); 052 eq InterfaceDeclSubstituted.uniqueIndex() = original().uniqueIndex(); 053 eq GenericInterfaceDeclSubstituted.uniqueIndex() = original().uniqueIndex(); 054 eq ParTypeDecl.uniqueIndex() = genericDecl().uniqueIndex(); 055 056 eq TypeVariable.arrayTypeDescriptor() = erasure().arrayTypeDescriptor(); 057 eq ParClassDecl.arrayTypeDescriptor() = erasure().arrayTypeDescriptor(); 058 eq ParInterfaceDecl.arrayTypeDescriptor() = erasure().arrayTypeDescriptor(); 059 //eq WildcardType.typeDescriptor() = erasure().typeDescriptor(); 060 061 eq GenericClassDeclSubstituted.arrayTypeDescriptor() = original().arrayTypeDescriptor(); 062 eq GenericInterfaceDeclSubstituted.arrayTypeDescriptor() = original().arrayTypeDescriptor(); 063 eq ClassDeclSubstituted.arrayTypeDescriptor() = original().arrayTypeDescriptor(); 064 eq InterfaceDeclSubstituted.arrayTypeDescriptor() = original().arrayTypeDescriptor(); 065 066 public ConstructorDecl ConstructorDeclSubstituted.createAccessor() { 067 return sourceConstructorDecl().createAccessor(); 068 } 069 070 protected TypeDecl ConstructorDeclSubstituted.createAnonymousJavaTypeDecl() { 071 return sourceConstructorDecl().createAnonymousJavaTypeDecl(); 072 } 073 074 refine CodeGeneration public void VarAccess.emitStore(CodeGeneration gen) { 075 Variable v = decl(); 076 if (v instanceof FieldDeclaration) { 077 FieldDeclaration f = (FieldDeclaration) v; 078 f = f.erasedField(); 079 if (requiresAccessor()) { 080 f.createAccessorWrite(fieldQualifierType()).emitInvokeMethod(gen, fieldQualifierType()); 081 } else { 082 f.emitStoreField(gen, fieldQualifierType()); 083 } 084 } else { 085 refined(gen); 086 } 087 } 088 refine CreateBCode public void VarAccess.createAssignLoadDest(CodeGeneration gen) { 089 Variable v = decl(); 090 if (v instanceof FieldDeclaration) { 091 createLoadQualifier(gen); 092 if (v.isInstanceVariable()) { 093 gen.emitDup(); 094 } 095 FieldDeclaration f = (FieldDeclaration) v; 096 f = f.erasedField(); 097 if (requiresAccessor()) { 098 f.createAccessor(fieldQualifierType()).emitInvokeMethod(gen, fieldQualifierType()); 099 } else { 100 f.emitLoadField(gen, fieldQualifierType()); 101 } 102 } else { 103 refined(gen); 104 } 105 } 106 107 refine CreateBCode public void VarAccess.createBCode(CodeGeneration gen) { 108 Variable v = decl(); 109 if (v instanceof FieldDeclaration) { 110 FieldDeclaration f = (FieldDeclaration) v; 111 f = f.erasedField(); 112 createLoadQualifier(gen); 113 if (f.isConstant() && (f.type().isPrimitive() || f.type().isString())) { 114 if (!f.isStatic()) { 115 fieldQualifierType().emitPop(gen); 116 } 117 f.constant().createBCode(gen); 118 } else if (requiresAccessor()) { 119 f.createAccessor(fieldQualifierType()).emitInvokeMethod(gen, fieldQualifierType()); 120 } else { 121 f.emitLoadField(gen, fieldQualifierType()); 122 } 123 if (f.type() != decl().type()) { 124 gen.emitCheckCast(decl().type()); 125 } 126 } else { 127 refined(gen); 128 } 129 } 130 131 refine CreateBCode public void MethodAccess.createBCode(CodeGeneration gen) { 132 MethodDecl decl = decl().erasedMethod(); 133 createLoadQualifier(gen); 134 135 if (program().options().hasOption("-debug")) { 136 if (decl.type().isUnknown()) { 137 System.err.println("Could not bind " + this); 138 for (int i = 0; i < getNumArg(); ++i) { 139 System.err.println("Argument " + getArg(i) 140 + " is of type " + getArg(i).type().typeName()); 141 if (getArg(i).varDecl() != null) { 142 System.err.println(getArg(i).varDecl() + " in " 143 + getArg(i).varDecl().hostType().typeName()); 144 } 145 } 146 if (isQualified()) { 147 System.err.println("Qualifier " + qualifier() 148 + " is of type " + qualifier().type().typeName()); 149 } 150 throw new Error("Could not bind " + this); 151 } 152 if (decl.getNumParameter() != getNumArg()) { 153 System.out.println(this 154 + " does not have the same number of arguments as " + decl); 155 } 156 } 157 158 for (int i = 0; i < getNumArg(); ++i) { 159 getArg(i).createBCode(gen); 160 // The cast or boxing/unboxing operation must know the bound rather than the erased type. 161 getArg(i).type().emitCastTo(gen, decl().getParameter(i).type()); // MethodInvocationConversion 162 } 163 164 if (!decl.isStatic() && isQualified() && prevExpr().isSuperAccess()) { 165 if (!hostType().instanceOf(prevExpr().type())) { 166 /* Should this be decl instead? possible copy/paste error? */ 167 decl().createSuperAccessor(superAccessorTarget()).emitInvokeMethod(gen, superAccessorTarget()); 168 } else { 169 decl.emitInvokeSpecialMethod(gen, methodQualifierType()); 170 } 171 } else { 172 decl.emitInvokeMethod(gen, methodQualifierType()); 173 } 174 175 if (decl.type() != decl().type()) { 176 gen.emitCheckCast(decl().type()); 177 } 178 } 179 180 refine InnerClasses protected TypeDecl MethodAccess.methodQualifierType() { 181 TypeDecl typeDecl = refined(); 182 if (typeDecl == null) { 183 return null; 184 } 185 typeDecl = typeDecl.erasure(); 186 MethodDecl m = decl().sourceMethodDecl(); 187 Collection methods = typeDecl.memberMethods(m.name()); 188 if (!methods.contains(decl()) && !methods.contains(m)) { 189 return m.hostType(); 190 } 191 return typeDecl.erasure(); 192 } 193 194 refine InnerClasses protected TypeDecl VarAccess.fieldQualifierType() { 195 TypeDecl typeDecl = refined(); 196 return typeDecl == null ? null : typeDecl.erasure(); 197 } 198 199 public void ConstructorDeclSubstituted.emitInvokeConstructor(CodeGeneration gen) { 200 erasedConstructor().emitInvokeConstructor(gen); 201 } 202 203 public void ParConstructorDecl.emitInvokeConstructor(CodeGeneration gen) { 204 genericConstructorDecl().emitInvokeConstructor(gen); 205 } 206 207 syn ConstructorDecl ConstructorDecl.erasedConstructor() = this; 208 eq ConstructorDeclSubstituted.erasedConstructor() = getOriginal().erasedConstructor(); 209 210 211 eq TypeVariable.constantPoolName() = erasure().constantPoolName(); 212 eq ParClassDecl.constantPoolName() = genericDecl().constantPoolName(); 213 eq ParInterfaceDecl.constantPoolName() = genericDecl().constantPoolName(); 214 215 public void BridgeMethodDecl.transformation() { } 216 public void MethodDeclSubstituted.transformation() { } 217 public void ParMethodDecl.transformation() { } 218 219 public static final int Modifiers.ACC_BRIDGE = 0x0040; 220 221 eq BridgeMethodDecl.flags() { 222 int res = super.flags(); 223 res |= Modifiers.ACC_BRIDGE; 224 res |= Modifiers.ACC_SYNTHETIC; 225 return res; 226 } 227 228 syn SimpleSet TypeDecl.bridgeCandidates(String signature) = SimpleSet.emptySet; 229 eq InterfaceDecl.bridgeCandidates(String signature) = ancestorMethods(signature); 230 eq ClassDecl.bridgeCandidates(String signature) { 231 SimpleSet set = ancestorMethods(signature); 232 for (Iterator iter = interfacesMethodsSignature(signature).iterator(); iter.hasNext(); ) { 233 set = set.add(iter.next()); 234 } 235 return set; 236 } 237 238 public void MethodDecl.transformation() { 239 super.transformation(); 240 HashSet processed = new HashSet(); 241 for (Iterator iter = hostType().bridgeCandidates(signature()).iterator(); iter.hasNext(); ) { 242 MethodDecl m = (MethodDecl) iter.next(); 243 if (this.overrides(m)) { 244 MethodDecl erased = m.erasedMethod(); 245 if (!erased.signature().equals(signature()) || erased.type().erasure() != type().erasure()) { 246 StringBuilder keyBuffer = new StringBuilder(); 247 for (int i = 0; i < getNumParameter(); i++) { 248 keyBuffer.append(erased.getParameter(i).type().erasure().fullName()); 249 } 250 keyBuffer.append(erased.type().erasure().fullName()); 251 String key = keyBuffer.toString(); 252 if (!processed.contains(key)) { 253 processed.add(key); 254 255 List args = new List(); 256 List parameters = new List(); 257 for (int i = 0; i < getNumParameter(); i++) { 258 args.add(new CastExpr(getParameter(i).type().erasure().createBoundAccess(), new VarAccess("p" + i))); 259 parameters.add(new ParameterDeclaration(erased.getParameter(i).type().erasure(), "p" + i)); 260 } 261 Stmt stmt; 262 if (type().isVoid()) { 263 stmt = new ExprStmt( 264 createBoundAccess( 265 args 266 ) 267 ); 268 } else { 269 stmt = new ReturnStmt( 270 createBoundAccess( 271 args 272 ) 273 ); 274 } 275 List modifiersList = new List(); 276 if (isPublic()) { 277 modifiersList.add(new Modifier("public")); 278 } else if (isProtected()) { 279 modifiersList.add(new Modifier("protected")); 280 } else if (isPrivate()) { 281 modifiersList.add(new Modifier("private")); 282 } 283 MethodDecl bridge = new BridgeMethodDecl( 284 new Modifiers(modifiersList), 285 erased.type().erasure().createBoundAccess(), 286 erased.name(), 287 parameters, 288 (List) getExceptionList().treeCopyNoTransform(), 289 new Opt( 290 new Block( 291 new List().add(stmt) 292 ) 293 ) 294 ); 295 hostType().addBodyDecl(bridge); 296 } 297 } 298 } 299 } 300 } 301 302 public void ParTypeDecl.transformation() { 303 } 304 305 refine Transformations public void TypeAccess.transformation() { 306 super.transformation(); 307 if (type().elementType().isNestedType() && hostType() != null) { 308 hostType().addUsedNestedType(type().elementType().erasure().sourceTypeDecl()); 309 } 310 } 311 312 // add Signature Attribute 313 refine AnnotationsCodegen eq TypeDecl.attributes() { 314 Collection c = refined(); 315 if (needsSignatureAttribute()) { 316 c.add(new SignatureAttribute(constantPool(), classSignature())); 317 } 318 return c; 319 } 320 321 refine AnnotationsCodegen eq MethodDecl.attributes() { 322 Collection c = refined(); 323 if (needsSignatureAttribute()) { 324 c.add(new SignatureAttribute(hostType().constantPool(), methodTypeSignature())); 325 } 326 return c; 327 } 328 329 refine AnnotationsCodegen eq FieldDeclaration.attributes() { 330 Collection c = refined(); 331 if (needsSignatureAttribute()) { 332 c.add(new SignatureAttribute(hostType().constantPool(), type().fieldTypeSignature())); 333 } 334 return c; 335 } 336 337 class SignatureAttribute extends Attribute { 338 public SignatureAttribute(ConstantPool cp, String signature) { 339 super(cp, "Signature"); 340 u2(cp.addUtf8(signature)); 341 } 342 } 343 344 // Determine which classes, interfaces, methods, and fields need a signature attribute 345 syn lazy boolean TypeDecl.needsSignatureAttribute() = false; 346 eq GenericClassDecl.needsSignatureAttribute() = true; 347 eq GenericInterfaceDecl.needsSignatureAttribute() = true; 348 eq ParClassDecl.needsSignatureAttribute() = true; 349 eq ParInterfaceDecl.needsSignatureAttribute() = true; 350 eq AbstractWildcardType.needsSignatureAttribute() = true; 351 eq TypeVariable.needsSignatureAttribute() = true; 352 eq ArrayDecl.needsSignatureAttribute() = elementType().needsSignatureAttribute(); 353 eq ClassDecl.needsSignatureAttribute() { 354 if (hasSuperclass() && superclass().needsSignatureAttribute()) { 355 return true; 356 } 357 for (Iterator<TypeDecl> iter = interfacesIterator(); iter.hasNext(); ) { 358 if (iter.next().needsSignatureAttribute()) { 359 return true; 360 } 361 } 362 return false; 363 } 364 365 eq InterfaceDecl.needsSignatureAttribute() { 366 for (Iterator<TypeDecl> iter = interfacesIterator(); iter.hasNext(); ) { 367 if (iter.next().needsSignatureAttribute()) { 368 return true; 369 } 370 } 371 return false; 372 } 373 374 syn boolean BodyDecl.needsSignatureAttribute() = false; 375 syn boolean MethodDecl.needsSignatureAttribute() { 376 if (type().needsSignatureAttribute()) { 377 return true; 378 } 379 for (int i = 0; i < getNumParameter(); i++) { 380 if (getParameter(i).type().needsSignatureAttribute()) { 381 return true; 382 } 383 } 384 return false; 385 } 386 387 eq GenericMethodDecl.needsSignatureAttribute() = true; 388 syn boolean ConstructorDecl.needsSignatureAttribute() { 389 for (int i = 0; i < getNumParameter(); i++) { 390 if (getParameter(i).type().needsSignatureAttribute()) { 391 return true; 392 } 393 } 394 return false; 395 } 396 eq GenericConstructorDecl.needsSignatureAttribute() = true; 397 398 eq FieldDeclaration.needsSignatureAttribute() = type().needsSignatureAttribute(); 399 400 // compute the signature string used for the signature attribute 401 syn lazy String TypeDecl.classSignature() = ""; 402 eq ClassDecl.classSignature() { 403 StringBuilder buf = new StringBuilder(); 404 // SuperclassSignature 405 if (hasSuperclass()) { 406 buf.append(superclass().classTypeSignature()); 407 } 408 // SuperinterfaceSignature* 409 for (Iterator<TypeDecl> iter = interfacesIterator(); iter.hasNext(); ) { 410 buf.append(iter.next().classTypeSignature()); 411 } 412 return buf.toString(); 413 } 414 eq InterfaceDecl.classSignature() { 415 StringBuilder buf = new StringBuilder(); 416 // SuperclassSignature 417 buf.append(typeObject().classTypeSignature()); 418 // SuperinterfaceSignature* 419 for (Iterator<TypeDecl> iter = interfacesIterator(); iter.hasNext(); ) { 420 buf.append(iter.next().classTypeSignature()); 421 } 422 return buf.toString(); 423 } 424 eq GenericClassDecl.classSignature() { 425 StringBuilder buf = new StringBuilder(); 426 // FormalTypeParameters 427 buf.append("<"); 428 for (int i = 0; i < getNumTypeParameter(); i++) { 429 buf.append(getTypeParameter(i).formalTypeParameter()); 430 } 431 buf.append(">"); 432 buf.append(super.classSignature()); 433 return buf.toString(); 434 } 435 eq GenericInterfaceDecl.classSignature() { 436 StringBuilder buf = new StringBuilder(); 437 // FormalTypeParameters 438 buf.append("<"); 439 for (int i = 0; i < getNumTypeParameter(); i++) { 440 buf.append(getTypeParameter(i).formalTypeParameter()); 441 } 442 buf.append(">"); 443 buf.append(super.classSignature()); 444 return buf.toString(); 445 } 446 447 // FormalTypeParameter 448 syn String TypeVariable.formalTypeParameter() { 449 StringBuilder buf = new StringBuilder(); 450 // Identifier 451 buf.append(name()); 452 buf.append(":"); 453 if (getNumTypeBound() > 0) { 454 // ClassBound InterfaceBound* 455 if (getTypeBound(0).type().isClassDecl()) { 456 buf.append(getTypeBound(0).type().fieldTypeSignature()); 457 } else { 458 buf.append(":" + getTypeBound(0).type().fieldTypeSignature()); 459 } 460 for (int i = 1; i < getNumTypeBound(); i++) { 461 buf.append(":" + getTypeBound(i).type().fieldTypeSignature()); 462 } 463 } 464 return buf.toString(); 465 } 466 467 syn lazy String TypeDecl.fieldTypeSignature() = classTypeSignature(); 468 eq ArrayDecl.fieldTypeSignature() = "[" + componentType().fieldTypeSignature(); 469 eq TypeVariable.fieldTypeSignature() = classTypeSignature(); 470 eq WildcardType.fieldTypeSignature() = "*"; 471 eq WildcardExtendsType.fieldTypeSignature() = "+" + extendsType().fieldTypeSignature(); 472 eq WildcardSuperType.fieldTypeSignature() = "-" + superType().fieldTypeSignature(); 473 eq PrimitiveType.fieldTypeSignature() = classTypeSignature(); 474 eq VoidType.fieldTypeSignature() = classTypeSignature(); 475 476 syn lazy String TypeDecl.classTypeSignature() = "L" + classTypeSignatureContents() + ";"; 477 eq ArrayDecl.classTypeSignature() = "[" + componentType().classTypeSignature(); 478 eq TypeVariable.classTypeSignature() = "T" + name() + ";"; 479 eq PrimitiveType.classTypeSignature() = typeDescriptor(); 480 eq VoidType.classTypeSignature() = typeDescriptor(); 481 482 syn String TypeDecl.classTypeSignatureContents() { 483 StringBuilder buf = new StringBuilder(); 484 if (isTopLevelType()) { 485 if (!packageName().equals("")) { 486 buf.append(packageName().replace('.', '/') + "/"); 487 } 488 } else { 489 buf.append(enclosingType().classTypeSignatureContents() + "."); 490 } 491 buf.append(name()); 492 buf.append(typeArgumentsOpt()); 493 return buf.toString(); 494 } 495 syn String TypeDecl.typeArgumentsOpt() = ""; 496 eq ParTypeDecl.typeArgumentsOpt() { 497 StringBuilder buf = new StringBuilder(); 498 buf.append("<"); 499 for (int i = 0; i < getNumArgument(); i++) { 500 buf.append(getArgument(i).type().fieldTypeSignature()); 501 } 502 buf.append(">"); 503 return buf.toString(); 504 } 505 eq RawClassDecl.typeArgumentsOpt() = ""; 506 eq RawInterfaceDecl.typeArgumentsOpt() = ""; 507 508 syn String MethodDecl.methodTypeSignature() { 509 StringBuilder buf = new StringBuilder(); 510 buf.append("("); 511 for (int i = 0; i < getNumParameter(); i++) { 512 buf.append(getParameter(i).type().classTypeSignature()); 513 } 514 buf.append(")"); 515 buf.append(type().classTypeSignature()); 516 for (int i = 0; i < getNumException(); i++) { 517 buf.append("^" + getException(i).type().classTypeSignature()); 518 } 519 return buf.toString(); 520 } 521 eq GenericMethodDecl.methodTypeSignature() { 522 StringBuilder buf = new StringBuilder(); 523 buf.append("<"); 524 for (int i = 0; i < getNumTypeParameter(); i++) { 525 TypeVariable param = getTypeParameter(i); 526 buf.append(param.getID() + ":" + param.classBound() + param.interfaceBounds()); 527 } 528 buf.append(">"); 529 buf.append(super.methodTypeSignature()); 530 return buf.toString(); 531 } 532 syn lazy String TypeVariable.classBound() { 533 if (getNumTypeBound() > 0) { 534 return getTypeBound(0).type().fieldTypeSignature(); 535 } 536 return ""; 537 } 538 syn lazy String TypeVariable.interfaceBounds() { 539 StringBuilder buf = new StringBuilder(); 540 for (int i = 1; i < getNumTypeBound(); ++i) { 541 buf.append(":"); 542 buf.append(getTypeBound(i).type().fieldTypeSignature()); 543 } 544 return buf.toString(); 545 } 546 }