Mercurial > hg > graal-compiler
comparison graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotXirGenerator.java @ 5330:678f31e9724e
added -G:+CheckcastCounters to profile the paths taken through a compiled checkcast
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Tue, 01 May 2012 10:53:56 +0200 |
parents | 7ceb3f3671b9 |
children | b1de7c9ab0e0 |
comparison
equal
deleted
inserted
replaced
5329:7ceb3f3671b9 | 5330:678f31e9724e |
---|---|
23 package com.oracle.graal.hotspot.ri; | 23 package com.oracle.graal.hotspot.ri; |
24 | 24 |
25 import static com.oracle.graal.hotspot.ri.TemplateFlag.*; | 25 import static com.oracle.graal.hotspot.ri.TemplateFlag.*; |
26 import static com.oracle.max.cri.ci.CiValueUtil.*; | 26 import static com.oracle.max.cri.ci.CiValueUtil.*; |
27 | 27 |
28 import java.io.*; | |
28 import java.util.*; | 29 import java.util.*; |
29 import java.util.concurrent.*; | 30 import java.util.concurrent.*; |
30 | 31 |
32 import sun.misc.*; | |
33 | |
31 import com.oracle.graal.compiler.*; | 34 import com.oracle.graal.compiler.*; |
35 import com.oracle.graal.graph.*; | |
32 import com.oracle.graal.hotspot.*; | 36 import com.oracle.graal.hotspot.*; |
33 import com.oracle.graal.hotspot.Compiler; | 37 import com.oracle.graal.hotspot.Compiler; |
34 import com.oracle.max.asm.target.amd64.*; | 38 import com.oracle.max.asm.target.amd64.*; |
35 import com.oracle.max.cri.ci.CiAddress.Scale; | 39 import com.oracle.max.cri.ci.CiAddress.Scale; |
36 import com.oracle.max.cri.ci.*; | 40 import com.oracle.max.cri.ci.*; |
458 asm.callRuntime(config.newMultiArrayStub, result); | 462 asm.callRuntime(config.newMultiArrayStub, result); |
459 return asm.finishTemplate("multiNewArray" + dimensions); | 463 return asm.finishTemplate("multiNewArray" + dimensions); |
460 } | 464 } |
461 }; | 465 }; |
462 | 466 |
467 private static final CheckcastCounters checkcastCounters = GraalOptions.CheckcastCounters ? new CheckcastCounters() : null; | |
468 | |
469 public static class CheckcastCounters { | |
470 long hintsHits; | |
471 long hintsMisses; | |
472 long exact; | |
473 long noHints; | |
474 long isNull; | |
475 long exceptions; | |
476 | |
477 static final int hintsHitsOffset; | |
478 static final int hintsMissesOffset; | |
479 static final int exactOffset; | |
480 static final int noHintsOffset; | |
481 static final int isNullOffset; | |
482 static final int exceptionsOffset; | |
483 | |
484 static { | |
485 Unsafe unsafe = Unsafe.getUnsafe(); | |
486 try { | |
487 hintsHitsOffset = (int) unsafe.objectFieldOffset(CheckcastCounters.class.getDeclaredField("hintsHits")); | |
488 hintsMissesOffset = (int) unsafe.objectFieldOffset(CheckcastCounters.class.getDeclaredField("hintsMisses")); | |
489 exactOffset = (int) unsafe.objectFieldOffset(CheckcastCounters.class.getDeclaredField("exact")); | |
490 noHintsOffset = (int) unsafe.objectFieldOffset(CheckcastCounters.class.getDeclaredField("noHints")); | |
491 isNullOffset = (int) unsafe.objectFieldOffset(CheckcastCounters.class.getDeclaredField("isNull")); | |
492 exceptionsOffset = (int) unsafe.objectFieldOffset(CheckcastCounters.class.getDeclaredField("exceptions")); | |
493 } catch (Exception e) { | |
494 throw new GraalInternalError(e); | |
495 } | |
496 } | |
497 | |
498 private static void printCounter(PrintStream out, String label, long count, long total) { | |
499 double percent = ((double) (count * 100)) / total; | |
500 out.println(String.format("%16s: %5.2f%%%10d", label, percent, count)); | |
501 } | |
502 | |
503 public void printCounters(PrintStream out) { | |
504 long total = hintsHits + hintsMisses + exact + noHints + isNull + exceptions; | |
505 out.println(); | |
506 out.println("** Checkcast counters **"); | |
507 printCounter(out, "hintsHits", hintsHits, total); | |
508 printCounter(out, "hintsMisses", hintsMisses, total); | |
509 printCounter(out, "exact", exact, total); | |
510 printCounter(out, "noHints", noHints, total); | |
511 printCounter(out, "isNull", isNull, total); | |
512 printCounter(out, "exceptions", exceptions, total); | |
513 } | |
514 } | |
515 | |
463 private IndexTemplates checkCastTemplates = new IndexTemplates(NULL_CHECK, EXACT_HINTS) { | 516 private IndexTemplates checkCastTemplates = new IndexTemplates(NULL_CHECK, EXACT_HINTS) { |
517 | |
518 private void incCounter(CiXirAssembler asm, XirOperand counter, XirParameter counters, int offset) { | |
519 XirConstant offsetOp = asm.i(offset); | |
520 asm.pload(CiKind.Long, counter, counters, offsetOp, false); | |
521 asm.add(counter, counter, asm.i(1)); | |
522 asm.pstore(CiKind.Long, counters, offsetOp, counter, false); | |
523 } | |
464 | 524 |
465 @Override | 525 @Override |
466 protected XirTemplate create(CiXirAssembler asm, long flags, int hintCount) { | 526 protected XirTemplate create(CiXirAssembler asm, long flags, int hintCount) { |
467 asm.restart(CiKind.Void); | 527 asm.restart(CiKind.Void); |
528 boolean exact = is(EXACT_HINTS, flags); | |
529 XirParameter counters = GraalOptions.CheckcastCounters ? asm.createConstantInputParameter("counters", CiKind.Object) : null; | |
468 XirParameter object = asm.createInputParameter("object", CiKind.Object); | 530 XirParameter object = asm.createInputParameter("object", CiKind.Object); |
469 final XirOperand hub = is(EXACT_HINTS, flags) ? null : asm.createConstantInputParameter("hub", CiKind.Object); | 531 final XirOperand hub = exact ? null : asm.createConstantInputParameter("hub", CiKind.Object); |
470 | 532 |
471 XirOperand objHub = asm.createTemp("objHub", CiKind.Object); | 533 XirOperand objHub = asm.createTemp("objHub", CiKind.Object); |
472 | 534 XirOperand counter = counters != null ? asm.createTemp("counter", CiKind.Long) : null; |
473 XirLabel end = asm.createInlineLabel("end"); | 535 |
536 XirLabel success = asm.createInlineLabel("success"); | |
474 XirLabel slowPath = asm.createOutOfLineLabel("slow path"); | 537 XirLabel slowPath = asm.createOutOfLineLabel("slow path"); |
475 | 538 |
476 if (is(NULL_CHECK, flags)) { | 539 if (is(NULL_CHECK, flags)) { |
477 // null can be cast to anything | 540 // null can be cast to anything |
478 asm.jeq(end, object, asm.o(null)); | 541 if (counters != null) { |
542 XirLabel isNotNull = asm.createInlineLabel("isNull"); | |
543 asm.jneq(isNotNull, object, asm.o(null)); | |
544 incCounter(asm, counter, counters, CheckcastCounters.isNullOffset); | |
545 asm.jmp(success); | |
546 asm.bindInline(isNotNull); | |
547 } else { | |
548 asm.jeq(success, object, asm.o(null)); | |
549 } | |
550 | |
479 } | 551 } |
480 | 552 |
481 asm.pload(CiKind.Object, objHub, object, asm.i(config.hubOffset), false); | 553 asm.pload(CiKind.Object, objHub, object, asm.i(config.hubOffset), false); |
482 if (hintCount == 0) { | 554 if (hintCount == 0) { |
483 assert !is(EXACT_HINTS, flags); | 555 assert !exact; |
556 if (counters != null) { | |
557 incCounter(asm, counter, counters, CheckcastCounters.noHintsOffset); | |
558 } | |
559 | |
484 checkSubtype(asm, objHub, objHub, hub); | 560 checkSubtype(asm, objHub, objHub, hub); |
485 asm.jeq(slowPath, objHub, asm.o(null)); | 561 asm.jeq(slowPath, objHub, asm.o(null)); |
486 asm.bindInline(end); | 562 asm.bindInline(success); |
487 | 563 |
488 // -- out of line ------------------------------------------------------- | 564 // -- out of line ------------------------------------------------------- |
489 asm.bindOutOfLine(slowPath); | 565 asm.bindOutOfLine(slowPath); |
490 } else { | 566 } else { |
567 XirLabel hintsSuccess = counters == null ? success : asm.createInlineLabel("hintsSuccess"); | |
491 XirOperand scratchObject = asm.createRegisterTemp("scratch", CiKind.Object, AMD64.r10); | 568 XirOperand scratchObject = asm.createRegisterTemp("scratch", CiKind.Object, AMD64.r10); |
492 // if we get an exact match: succeed immediately | 569 // if we get an exact match: succeed immediately |
493 for (int i = 0; i < hintCount; i++) { | 570 for (int i = 0; i < hintCount; i++) { |
494 XirParameter hintHub = asm.createConstantInputParameter("hintHub" + i, CiKind.Object); | 571 XirParameter hintHub = asm.createConstantInputParameter("hintHub" + i, CiKind.Object); |
495 asm.mov(scratchObject, hintHub); | 572 asm.mov(scratchObject, hintHub); |
496 if (i < hintCount - 1) { | 573 if (i < hintCount - 1) { |
497 asm.jeq(end, objHub, scratchObject); | 574 asm.jeq(hintsSuccess, objHub, scratchObject); |
498 } else { | 575 } else { |
499 asm.jneq(slowPath, objHub, scratchObject); | 576 asm.jneq(slowPath, objHub, scratchObject); |
500 } | 577 } |
501 } | 578 } |
502 asm.bindInline(end); | 579 |
580 if (counters != null) { | |
581 asm.bindInline(hintsSuccess); | |
582 incCounter(asm, counter, counters, exact ? CheckcastCounters.exactOffset : CheckcastCounters.hintsHitsOffset); | |
583 } | |
584 | |
585 asm.bindInline(success); | |
503 | 586 |
504 // -- out of line ------------------------------------------------------- | 587 // -- out of line ------------------------------------------------------- |
505 asm.bindOutOfLine(slowPath); | 588 asm.bindOutOfLine(slowPath); |
506 if (!is(EXACT_HINTS, flags)) { | 589 if (!exact) { |
590 if (counters != null) { | |
591 incCounter(asm, counter, counters, CheckcastCounters.hintsMissesOffset); | |
592 } | |
507 checkSubtype(asm, objHub, objHub, hub); | 593 checkSubtype(asm, objHub, objHub, hub); |
508 asm.jneq(end, objHub, asm.o(null)); | 594 asm.jneq(success, objHub, asm.o(null)); |
509 } | 595 } |
510 } | 596 } |
511 | 597 |
512 RiDeoptReason deoptReason = is(EXACT_HINTS, flags) ? RiDeoptReason.OptimizedTypeCheckViolated : RiDeoptReason.ClassCastException; | 598 if (counters != null) { |
599 incCounter(asm, counter, counters, CheckcastCounters.exceptionsOffset); | |
600 } | |
601 RiDeoptReason deoptReason = exact ? RiDeoptReason.OptimizedTypeCheckViolated : RiDeoptReason.ClassCastException; | |
513 XirOperand scratch = asm.createRegisterTemp("scratch", target.wordKind, AMD64.r10); | 602 XirOperand scratch = asm.createRegisterTemp("scratch", target.wordKind, AMD64.r10); |
514 asm.mov(scratch, wordConst(asm, compiler.getRuntime().encodeDeoptActionAndReason(RiDeoptAction.InvalidateReprofile, deoptReason))); | 603 asm.mov(scratch, wordConst(asm, compiler.getRuntime().encodeDeoptActionAndReason(RiDeoptAction.InvalidateReprofile, deoptReason))); |
515 asm.callRuntime(CiRuntimeCall.Deoptimize, null); | 604 asm.callRuntime(CiRuntimeCall.Deoptimize, null); |
516 asm.shouldNotReachHere(); | 605 asm.shouldNotReachHere(); |
517 | 606 |
735 return new XirSnippet(multiNewArrayTemplate.get(site, lengths.length), params); | 824 return new XirSnippet(multiNewArrayTemplate.get(site, lengths.length), params); |
736 } | 825 } |
737 | 826 |
738 @Override | 827 @Override |
739 public XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiType type, RiResolvedType[] hints, boolean hintsExact) { | 828 public XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiType type, RiResolvedType[] hints, boolean hintsExact) { |
829 final boolean useCounters = GraalOptions.CheckcastCounters; | |
740 if (hints == null || hints.length == 0) { | 830 if (hints == null || hints.length == 0) { |
741 return new XirSnippet(checkCastTemplates.get(site, 0), receiver, hub); | 831 if (useCounters) { |
832 return new XirSnippet(checkCastTemplates.get(site, 0), XirArgument.forObject(checkcastCounters), receiver, hub); | |
833 } else { | |
834 return new XirSnippet(checkCastTemplates.get(site, 0), receiver, hub); | |
835 } | |
742 } else { | 836 } else { |
743 XirArgument[] params = new XirArgument[hints.length + (hintsExact ? 1 : 2)]; | 837 XirArgument[] params = new XirArgument[(useCounters ? 1 : 0) + hints.length + (hintsExact ? 1 : 2)]; |
744 int i = 0; | 838 int i = 0; |
839 if (useCounters) { | |
840 params[i++] = XirArgument.forObject(checkcastCounters); | |
841 } | |
745 params[i++] = receiver; | 842 params[i++] = receiver; |
746 if (!hintsExact) { | 843 if (!hintsExact) { |
747 params[i++] = hub; | 844 params[i++] = hub; |
748 } | 845 } |
749 for (RiResolvedType hint : hints) { | 846 for (RiResolvedType hint : hints) { |
915 | 1012 |
916 public XirTemplate get(XirSite site, CiKind kind, TemplateFlag... flags) { | 1013 public XirTemplate get(XirSite site, CiKind kind, TemplateFlag... flags) { |
917 return getInternal(getBits(kind.ordinal(), site, flags)); | 1014 return getInternal(getBits(kind.ordinal(), site, flags)); |
918 } | 1015 } |
919 } | 1016 } |
1017 | |
1018 public static void printCounters(PrintStream out) { | |
1019 if (GraalOptions.CheckcastCounters) { | |
1020 checkcastCounters.printCounters(out); | |
1021 } | |
1022 } | |
920 } | 1023 } |