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 }