1 24 25 package org.aspectj.compiler.base.ast; 26 27 import org.aspectj.compiler.base.*; 28 import org.aspectj.compiler.crosscuts.AccessFixer; 29 import org.aspectj.compiler.crosscuts.joinpoints.CalleeSideCallJp; 30 31 import org.aspectj.compiler.base.cst.BlockScope; 32 33 import org.aspectj.compiler.base.bcg.CodeBuilder; 34 import org.aspectj.compiler.base.bcg.Label; 35 36 import java.util.*; 37 38 39 47 public class CallExpr extends AnyCallExpr implements SOLink { 48 49 52 public void walkFlow(FlowCheckerPass w) { 53 if (getExpr() != null) { 54 w.process(getExpr()); 55 } 56 w.process(getArgs()); 57 if (getMethod().getThrows() != null) { 58 TypeDs ts = getMethod().getThrows(); 59 for (int i = 0, len = ts.size(); i < len; i++) { 60 w.setExns(w.getExns().add((NameType) ts.get(i).getType())); 61 } 62 } 63 } 64 65 public ASTObject postMove(MovingWalker walker) { 67 return walker.moveLinkExpr(this); 68 } 69 70 public ASTObject postScope(ScopeWalker walker) { 72 if (method != null) 73 return this; 74 75 Type lookupType; 76 if (expr != null) { 77 lookupType = expr.getType(); 78 } else { 79 lookupType = walker.getScope().findMethodLookupType(id, this); 80 if (lookupType == null) { 81 this.showError("can't find any method with name: " + id); 82 return this; 83 } 84 } 85 86 method = lookupType.getMethod(id, this, args, true); 87 if (method == null) { 89 setType(getTypeManager().TYPE_NOT_FOUND); 90 return this; 91 } 92 93 if (expr != null && expr instanceof SuperExpr) { 94 if (method.isStatic()) { 95 } else { 96 setIsSuper(true); 97 } 98 } 99 100 if (getExpr() == null) { 101 setExpr( 102 (method.isStatic()) 103 ? getAST().makeTypeExpr(lookupType) 104 : (Expr) getAST().makeQualifiedThis(lookupType)); 105 } 106 107 return super.postScope(walker); 109 } 110 111 114 public void postInnerInfo(InnerInfoPass w) { 115 if (expr == null && method != null) { 116 w.checkStaticAccess(this, method); 117 setExpr(getAST().makePrimary(getMethod(), w.currentType())); 118 } 119 } 120 121 125 public boolean hasLegalProtectedAccess(Type fromType) { 126 if (expr == null || getIsSuper() || expr instanceof SuperExpr) 127 return true; 128 return expr.getType().isSubtypeOf(fromType); 129 } 130 131 public void checkSpec() { 132 if (method == null) 133 return; 134 if (expr instanceof TypeExpr && !method.isStatic()) { 135 showError( 136 "non-static method " 137 + method.toShortString() 138 + " cannot be accessed through a static reference"); 139 } 140 if (getIsSuper()) { 141 if (method.isAbstract()) { 142 showError( 143 "abstract method " + method.toShortString() + " cannot be target of super"); 144 } 145 } 146 } 147 148 public boolean isLegalStmt() { 149 return true; 150 } 151 152 public ASTObject postFixAST(final ASTFixerPass fixer) { 153 if (getIsSuper()) { 154 MethodDec superMethodDec = getMethodDec(); 155 CalleeSideCallJp targetPoint = 156 (CalleeSideCallJp) getWorld().calleeSideCallPoints.get(superMethodDec); 157 if (targetPoint == null || !targetPoint.hasPlans()) { 158 return this; 159 } 160 161 setMethod(targetPoint.getPostMethodDec().getMethod()); 162 } 163 setExpr(method.updateTargetExpr(getExpr())); 165 return this; 166 } 167 168 public ASTObject fixAccessPost(AccessFixer fixer) { 170 if (getMethod() == null) 171 return this; if (getMethod().isAccessible(this, true)) 174 return this; 175 176 getCompiler().showMessage( 177 " fixing privileged call: " + getMethod().toShortString()); 178 180 Method newMethod = getMethod().getBackdoorMethod(); 181 if (!fixer.apply) 182 return this; 183 184 CallExpr newCallExpr = getAST().makeCall(newMethod, getExpr(), getArgs()); 185 newCallExpr.setSource(this); 186 return newCallExpr; 187 } 188 189 public MethodDec getMethodDec() { 190 return (MethodDec) method.getCorrespondingDec(); 191 } 192 public void setMethodDec(MethodDec md) { 193 setMethod((Method) md.getCorrespondingSemanticObject()); 194 } 195 public CodeDec getCodeDec() { 196 return getMethodDec(); 197 } 198 public SemanticObject getTarget() { 199 return getMethod(); 200 } 201 public void setTarget(SemanticObject newTarget) { 202 setMethod((Method) newTarget); 203 } 204 205 public Type getReturnType() { 206 return getMethod().getReturnType(); 207 } 208 209 public Type getCalledType() { 210 if (expr == null) { 211 return getDeclaringType(); 212 } else { 213 return expr.getType(); 214 } 215 } 216 217 public CallExpr(SourceLocation source, Expr expr, String id) { 218 this(source, expr, id, new Exprs(source)); 219 } 220 221 public Type discoverType() { 222 if (getMethod() == null) 223 return getTypeManager().anyType; 224 else 225 return getMethod().getReturnType(); 226 } 227 228 static Expr makeParentExpr(Method md, Expr instance) { 229 if (instance != null) 230 return instance; 231 if (md.isStatic()) { 232 return md.getAST().makeTypeExpr(md.getDeclaringType()); 233 } else { 234 return null; } 236 } 237 238 public Expr getExprOrThis() { 239 if (method.isStatic()) 240 return null; 241 if (expr != null) 243 return expr; 244 return new ThisExpr(getSourceLocation(), method.getDeclaringType()); 245 } 246 247 private boolean isInlinableTarget(Expr e, Type bytecodeType) { 248 if (e == null) return true; 249 if (e instanceof TypeExpr) return true; 250 if (e instanceof ThisExpr) { 251 ThisExpr thisExpr = (ThisExpr)e; 252 if (thisExpr.getType() == bytecodeType) return true; 253 } 254 return false; 255 } 256 257 public boolean tryToInline(Type bytecodeType) { 258 if (!isInlinableTarget(getExpr(), bytecodeType)) return false; 261 262 263 264 MethodDec md = getMethodDec(); 265 if (md.containsTypes()) return false; 266 267 final AST ast = getAST(); 268 269 try { 270 if (getParent() instanceof ReturnStmt) { 271 RemapWalker rw = new RemapWalker(getCompiler(), args, md, null, null); 273 274 getParent().replaceWith(rw.remap()); 275 } else if (getParent() instanceof ExprStmt) { 276 String label = getWorld().genLabel(); 278 RemapWalker rw = new RemapWalker(getCompiler(), args, md, label, null); 279 getParent().replaceWith(rw.remap()); 280 } else if (isEffectiveCast(getParent())) { 281 ReturnStmt s = getEnclosingReturnStmt(this); 282 RemapWalker rw = new RemapWalker(getCompiler(), args, md, null, s.getExpr().getType()); 283 s.replaceWith(rw.remap()); 284 } else { 285 return false; 286 } 287 } catch (InvalidOptimizationException e) { 288 return false; 289 } 290 291 md.getDeclaringType().getTypeDec().getBody().remove(md); 292 return true; 293 } 294 295 private ReturnStmt getEnclosingReturnStmt(ASTObject o) { 296 if (o instanceof ReturnStmt) return (ReturnStmt) o; 297 else return getEnclosingReturnStmt(o.getParent()); 298 } 299 300 301 302 private boolean isEffectiveCast(ASTObject o) { 303 if (o instanceof ParenExpr) return isEffectiveCast(o.getParent()); 304 if (o instanceof CastExpr) return isEffectiveCast1(o.getParent()); 305 else return false; 306 } 307 308 309 private boolean isEffectiveCast1(ASTObject o) { 310 if (o instanceof ParenExpr) return isEffectiveCast1(o.getParent()); 311 if (o instanceof ReturnStmt) return true; 312 else return false; 313 } 314 315 static class InvalidOptimizationException extends RuntimeException {} 316 317 class RemapWalker extends MovingWalker { 318 private Exprs args; 319 private MethodDec calledMethodDec; 320 private String breakLabel; 321 322 private Type desiredReturnType; 323 324 private List argRefs; 328 private VarDec returnVarDec; 329 330 public RemapWalker(JavaCompiler compiler, Exprs args, MethodDec calledMethodDec, 331 String breakLabel, 332 Type desiredReturnType) { 333 super(compiler); 334 this.args = args; 335 this.calledMethodDec = calledMethodDec; 336 this.breakLabel = breakLabel; 337 this.desiredReturnType = desiredReturnType; 338 } 339 340 341 public Stmt remap() { 342 final AST ast = this.getAST(); 343 344 349 Stmts stmts = this.remapStmts(); 350 Stmt ret = ast.makeBlock(stmts); 352 if (breakLabel != null) ret = ast.makeLabeled(breakLabel, ret); 355 return ret; 356 } 357 358 public Stmts remapStmts() { 359 final AST ast = this.getAST(); 360 Stmts block = ast.makeStmts(); 361 this.argRefs = new ArrayList(); 363 364 Set effectivelyFinalFormals = calledMethodDec.getEffectivelyFinalFormals(); 365 366 for (int i=0; i<args.size(); i++) { 367 FormalDec formal = calledMethodDec.getFormals().get(i); 368 Type type = formal.getType(); 369 370 Expr arg = (Expr)args.get(i).copy(); 371 372 if (effectivelyFinalFormals.contains(formal) && args.get(i).canBeCopied()) { 373 argRefs.add(ast.makeCast(type, arg)); 374 } else { 375 VarDec dec = ast.makeVarDec(type, formal.getId(), arg); 376 block.add(dec); 377 argRefs.add(ast.makeVar(dec)); 378 } 379 } 380 381 Stmts body = (Stmts)calledMethodDec.getBody().getStmts().copy(); 382 386 body = (Stmts)process(body); 388 block.addAll(body); return block; 394 } 395 396 protected Expr handleFreeVar(VarExpr var) { 397 VarDec varDec = var.getVarDec(); 398 if (!(varDec instanceof FormalDec)) { 399 return super.handleFreeVar(var); 400 } 401 402 FormalDec formalDec = (FormalDec)varDec; 403 int index = calledMethodDec.getFormals().indexOf(formalDec); 404 if (index == -1) return super.handleFreeVar(var); 405 406 407 return (Expr)((Expr)argRefs.get(index)).copy(); 410 } 411 412 private ASTObject handleReturn(ReturnStmt object) { 413 final AST ast = this.getAST(); 414 if (breakLabel == null) { 416 if (desiredReturnType != null) { 420 if (desiredReturnType.isAssignableFrom(object.getExpr().getType())) { 422 object.setExpr(ast.makeCast(desiredReturnType, object.getExpr())); 423 } else { 424 throw new InvalidOptimizationException(); 426 } 427 } 428 return object; 429 } 430 431 Stmt stmt = ast.makeBreak(breakLabel); 432 433 Expr expr = object.getExpr(); 434 if (expr == null) return stmt; 435 if (expr.canBeCopied()) return stmt; 436 if (expr.isLegalStmt()) return ast.makeBlock(ast.makeStmt(expr), stmt); 437 438 return ast.makeVarDec(calledMethodDec.getResultType(), "retValue", expr, true); 439 } 440 452 public Expr moveThisExpr(ThisExpr thisExpr, Type thisType) { 453 return thisExpr; 454 } 455 456 public ASTObject process(ASTObject object) { 457 if (object instanceof TypeDec || object instanceof CodeDec) { 459 return object; 460 } 461 462 object = super.process(object); 463 if (object instanceof ReturnStmt) { 464 return handleReturn((ReturnStmt)object); 465 } else { 466 return object; 467 } 468 } 469 470 471 } 472 473 public void unparse(CodeWriter writer) { 474 if (expr != null) { 475 writer.write(expr); 476 writer.write('.'); 477 } 478 479 if (method != null) 480 id = method.getBytecodeId(); 481 writer.write(id); 482 writer.openParen('('); 483 writer.write(args); 484 writer.closeParen(')'); 485 } 486 487 public CallExpr( 488 SourceLocation source, 489 Method toMethod, 490 Expr instance, 491 Exprs args) { 492 this( 493 source, 494 makeParentExpr(toMethod, instance), 495 toMethod.getId(), 496 args, 497 toMethod, 498 false); 499 } 500 501 public CallExpr(SourceLocation source, String _id, Exprs _args) { 502 this(source, new ThisExpr(source), _id, _args); 503 } 504 505 public CallExpr(SourceLocation source, Expr expr, String _id, Exprs _args) { 506 this(source, expr, _id, _args, null, false); 507 } 508 509 private boolean needsAccessMethod(InnerAccessFixer w) { 510 Expr q = getExpr(); 511 MethodDec oldMethodDec = getMethodDec(); 512 513 if (!w.isAccessible(oldMethodDec, q)) { 518 return true; 519 } else { 520 if (getIsSuper()) { 521 if (getExpr() instanceof ThisExpr || getExpr() instanceof SuperExpr) { 523 return false; 524 } else { 525 return true; 526 } 527 } else { 533 return false; 534 } 535 } 536 } 537 538 541 public ASTObject postInnerAccess(InnerAccessFixer w) { 542 547 if (!needsAccessMethod(w)) 548 return this; 549 551 Expr q = getExpr(); 552 MethodDec oldMethodDec = getMethodDec(); 553 554 Type qType = q.getType(); 555 MethodDec newMethodDec = w.getAccessMethod(qType, oldMethodDec, "", this); 556 setMethod(newMethodDec.getMethod()); 557 if (!oldMethodDec.isStatic()) { 558 getArgs().add(0, q); 559 setExpr(getAST().makeTypeExpr(qType)); 560 } 561 return this; 562 } 563 564 public MethodDec buildAccessMethod(InnerAccessFixer w) { 565 final AST ast = getAST(); 566 Expr q = getExpr(); 567 Type qType = q.getType(); 568 569 Type returnType = getReturnType(); 570 Method oldMethod = getMethod(); 571 572 Formals newFormals = (Formals) oldMethod.getFormals().copy(); 573 Exprs newArgs = ast.makeVars(newFormals); 574 Expr newExpr = w.makeInsidePrimary(oldMethod.isStatic(), newFormals, qType); 575 576 CallExpr newCall = ast.makeCall(oldMethod, newExpr, newArgs); 577 if (getIsSuper()) 578 newCall.setIsSuper(true); 579 580 return w.makeAccessMethod(returnType, newFormals, newCall); 581 } 582 583 protected void cgValue(CodeBuilder cb) { 586 cb.enterLocation(getSourceLocation()); 587 MethodDec dec = getMethodDec(); 588 String name = dec.getInternalId(); 589 String descriptor = dec.getDescriptor(); 590 int delta = dec.getStackDelta(); 591 if (dec.isStatic()) 592 getExpr().cgEffect(cb); 593 else 594 getExpr().cgValue(cb); 595 getArgs().cgValues(cb, dec.getFormals()); 596 RefType refTy = (RefType) getExpr().getType(); 597 NameType ty = 598 (refTy instanceof ArrayType) 599 ? getTypeManager().getObjectType() 600 : (NameType) refTy; 601 if (dec.getDeclaringType().isObject()) { 602 ty = getTypeManager().getObjectType(); 609 } 610 if (dec.isStatic()) { 611 cb.emitINVOKESTATIC(ty, name, descriptor, delta); 612 } else if (getIsSuper()) { 613 cb.emitINVOKESPECIAL(ty, name, descriptor, delta); 614 } else if (dec.isPrivate()) { 615 cb.emitINVOKESPECIAL(ty, name, descriptor, delta); 616 } else if (ty.isInterface()) { 617 int arglen = -delta + dec.getResultType().getSlotCount(); 618 cb.emitINVOKEINTERFACE(ty, name, descriptor, delta, arglen); 619 } else { 620 cb.emitINVOKEVIRTUAL(ty, name, descriptor, delta); 621 } 622 } 623 624 protected Expr expr; 626 public Expr getExpr() { return expr; } 627 public void setExpr(Expr _expr) { 628 if (_expr != null) _expr.setParent(this); 629 expr = _expr; 630 } 631 632 protected String id; 633 public String getId() { return id; } 634 public void setId(String _id) { id = _id; } 635 636 protected Exprs args; 637 public Exprs getArgs() { return args; } 638 public void setArgs(Exprs _args) { 639 if (_args != null) _args.setParent(this); 640 args = _args; 641 } 642 643 protected Method method; 644 public Method getMethod() { return method; } 645 public void setMethod(Method _method) { method = _method; } 646 647 protected boolean isSuper; 648 public boolean getIsSuper() { return isSuper; } 649 public void setIsSuper(boolean _isSuper) { isSuper = _isSuper; } 650 651 public CallExpr(SourceLocation location, Expr _expr, String _id, Exprs _args, Method _method, boolean _isSuper) { 652 super(location); 653 setExpr(_expr); 654 setId(_id); 655 setArgs(_args); 656 setMethod(_method); 657 setIsSuper(_isSuper); 658 } 659 protected CallExpr(SourceLocation source) { 660 super(source); 661 } 662 663 public ASTObject copyWalk(CopyWalker walker) { 664 CallExpr ret = new CallExpr(getSourceLocation()); 665 ret.preCopy(walker, this); 666 if (expr != null) ret.setExpr( (Expr)walker.process(expr) ); 667 ret.id = id; 668 if (args != null) ret.setArgs( (Exprs)walker.process(args) ); 669 ret.method = method; 670 ret.isSuper = isSuper; 671 return ret; 672 } 673 674 public ASTObject getChildAt(int childIndex) { 675 switch(childIndex) { 676 case 0: return expr; 677 case 1: return args; 678 default: return super.getChildAt(childIndex); 679 } 680 } 681 public String getChildNameAt(int childIndex) { 682 switch(childIndex) { 683 case 0: return "expr"; 684 case 1: return "args"; 685 default: return super.getChildNameAt(childIndex); 686 } 687 } 688 public void setChildAt(int childIndex, ASTObject child) { 689 switch(childIndex) { 690 case 0: setExpr((Expr)child); return; 691 case 1: setArgs((Exprs)child); return; 692 default: super.setChildAt(childIndex, child); return; 693 } 694 } 695 public int getChildCount() { 696 return 2; 697 } 698 699 public String getDefaultDisplayName() { 700 return "CallExpr(id: "+id+", "+"method: "+method+", "+"isSuper: "+isSuper+")"; 701 } 702 703 } 705 | Popular Tags |