comparison c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/HotSpotXirGenerator.java @ 2061:c0b1d6a44a02

Implemented fast inline array allocation.
author Thomas Wuerthinger <wuerthinger@ssw.jku.at>
date Sat, 22 Jan 2011 14:37:43 +0100
parents 40bcc41390e4
children 50b45e2d9725
comparison
equal deleted inserted replaced
2060:40bcc41390e4 2061:c0b1d6a44a02
432 @Override 432 @Override
433 protected XirTemplate create(CiXirAssembler asm, long flags, int size) { 433 protected XirTemplate create(CiXirAssembler asm, long flags, int size) {
434 XirOperand result = asm.restart(CiKind.Word); 434 XirOperand result = asm.restart(CiKind.Word);
435 XirOperand type = asm.createInputParameter("type", CiKind.Object); 435 XirOperand type = asm.createInputParameter("type", CiKind.Object);
436 436
437 XirOperand thread = asm.createRegisterTemp("thread", CiKind.Word, AMD64.r15);
438 XirOperand temp1 = asm.createRegisterTemp("temp1", CiKind.Word, AMD64.rcx); 437 XirOperand temp1 = asm.createRegisterTemp("temp1", CiKind.Word, AMD64.rcx);
439 XirOperand temp2 = asm.createRegisterTemp("temp2", CiKind.Word, AMD64.rbx); 438 XirOperand temp2 = asm.createRegisterTemp("temp2", CiKind.Word, AMD64.rbx);
440 XirOperand temp2i = asm.createRegisterTemp("temp2i", CiKind.Int, AMD64.rbx); 439 XirOperand temp2i = asm.createRegisterTemp("temp2i", CiKind.Int, AMD64.rbx);
441 useRegisters(asm, AMD64.rsi); 440 useRegisters(asm, AMD64.rsi);
442 XirLabel tlabFull = asm.createOutOfLineLabel("tlab full"); 441 XirLabel tlabFull = asm.createOutOfLineLabel("tlab full");
444 443
445 // check if the class is already initialized 444 // check if the class is already initialized
446 asm.pload(CiKind.Int, temp2i, type, asm.i(config.klassStateOffset), false); 445 asm.pload(CiKind.Int, temp2i, type, asm.i(config.klassStateOffset), false);
447 asm.jneq(tlabFull, temp2i, asm.i(config.klassStateFullyInitialized)); 446 asm.jneq(tlabFull, temp2i, asm.i(config.klassStateFullyInitialized));
448 447
448 XirOperand thread = asm.createRegisterTemp("thread", CiKind.Word, AMD64.r15);
449 asm.pload(CiKind.Word, result, thread, asm.i(config.threadTlabTopOffset), false); 449 asm.pload(CiKind.Word, result, thread, asm.i(config.threadTlabTopOffset), false);
450 asm.add(temp1, result, asm.w(size)); 450 asm.add(temp1, result, asm.w(size));
451 asm.pload(CiKind.Word, temp2, thread, asm.i(config.threadTlabEndOffset), false); 451 asm.pload(CiKind.Word, temp2, thread, asm.i(config.threadTlabEndOffset), false);
452 452
453 asm.jgt(tlabFull, temp1, temp2); 453 asm.jgt(tlabFull, temp1, temp2);
454 asm.pstore(CiKind.Word, thread, asm.i(config.threadTlabTopOffset), temp1, false); 454 asm.pstore(CiKind.Word, thread, asm.i(config.threadTlabTopOffset), temp1, false);
455
455 asm.bindInline(resume); 456 asm.bindInline(resume);
456 457
457 asm.pload(CiKind.Word, temp1, type, asm.i(config.instanceHeaderPrototypeOffset), false); 458 asm.pload(CiKind.Word, temp1, type, asm.i(config.instanceHeaderPrototypeOffset), false);
458 asm.pstore(CiKind.Word, result, temp1, false); 459 asm.pstore(CiKind.Word, result, temp1, false);
459 asm.pstore(CiKind.Object, result, asm.i(config.hubOffset), type, false); 460 asm.pstore(CiKind.Object, result, asm.i(config.hubOffset), type, false);
495 496
496 return asm.finishTemplate("new instance"); 497 return asm.finishTemplate("new instance");
497 } 498 }
498 }; 499 };
499 500
500 private SimpleTemplates newObjectArrayTemplates = new SimpleTemplates(UNRESOLVED) { 501 private SimpleTemplates newObjectArrayCloneTemplates = new SimpleTemplates() {
501 502
502 @Override 503 @Override
503 protected XirTemplate create(CiXirAssembler asm, long flags) { 504 protected XirTemplate create(CiXirAssembler asm, long flags) {
504 XirOperand result = asm.restart(CiKind.Object); 505 XirOperand result = asm.restart(CiKind.Object);
505 506 XirParameter lengthParam = asm.createInputParameter("length", CiKind.Int, true);
506 XirParameter lengthParam = asm.createInputParameter("length", CiKind.Int); 507 XirParameter src = asm.createInputParameter("src", CiKind.Object);
507 508
509 // Set up length and hub.
508 XirOperand length = asm.createRegisterTemp("length", CiKind.Int, AMD64.rbx); 510 XirOperand length = asm.createRegisterTemp("length", CiKind.Int, AMD64.rbx);
509 XirOperand hub = asm.createRegisterTemp("hub", CiKind.Object, AMD64.rdx); 511 XirOperand hub = asm.createRegisterTemp("hub", CiKind.Object, AMD64.rdx);
510 512 asm.pload(CiKind.Object, hub, src, asm.i(config.hubOffset), false);
511 UnresolvedClassPatching patching = null;
512 if (is(UNRESOLVED, flags)) {
513 // insert the patching code for class resolving - the hub will end up in "hub"
514 patching = new UnresolvedClassPatching(asm, hub, config);
515 patching.emitInline();
516 } else {
517 asm.mov(hub, asm.createConstantInputParameter("hub", CiKind.Object));
518 }
519
520 asm.mov(length, lengthParam); 513 asm.mov(length, lengthParam);
514
521 useRegisters(asm, AMD64.rsi, AMD64.rcx, AMD64.rdi, AMD64.rax); 515 useRegisters(asm, AMD64.rsi, AMD64.rcx, AMD64.rdi, AMD64.rax);
522 asm.callRuntime(config.newObjectArrayStub, result); 516 asm.callRuntime(config.newObjectArrayStub, result);
523 if (is(UNRESOLVED, flags)) { 517 return asm.finishTemplate("objectArrayClone");
524 patching.emitOutOfLine(); 518 }
525 } 519 };
520
521 private SimpleTemplates newObjectArrayTemplates = new SimpleTemplates(UNRESOLVED) {
522
523 @Override
524 protected XirTemplate create(CiXirAssembler asm, long flags) {
525 emitNewTypeArray(asm, flags, CiKind.Object, config.useFastNewObjectArray, config.newObjectArrayStub);
526 return asm.finishTemplate(is(UNRESOLVED, flags) ? "newObjectArray (unresolved)" : "newObjectArray"); 526 return asm.finishTemplate(is(UNRESOLVED, flags) ? "newObjectArray (unresolved)" : "newObjectArray");
527 } 527 }
528 }; 528 };
529 529
530 private SimpleTemplates newTypeArrayTemplates = new SimpleTemplates() { 530 private void emitNewTypeArray(CiXirAssembler asm, long flags, CiKind kind, boolean useFast, long slowPathStub) {
531 531 XirOperand result = asm.restart(CiKind.Word);
532 @Override 532
533 protected XirTemplate create(CiXirAssembler asm, long flags) { 533 XirParameter lengthParam = asm.createInputParameter("length", CiKind.Int, true);
534 XirOperand result = asm.restart(CiKind.Object); 534
535 535 XirOperand length = asm.createRegisterTemp("length", CiKind.Int, AMD64.rbx);
536 XirParameter lengthParam = asm.createInputParameter("length", CiKind.Int); 536 XirOperand hub = asm.createRegisterTemp("hub", CiKind.Object, AMD64.rdx);
537 XirParameter hubParam = asm.createConstantInputParameter("hub", CiKind.Object); 537
538 538 // Registers rsi, rcx, rdi, and rax are needed by the runtime call.
539 XirOperand length = asm.createRegisterTemp("length", CiKind.Int, AMD64.rbx); 539 // Hub needs to be on rdx, length on rbx.
540 XirOperand hub = asm.createRegisterTemp("hub", CiKind.Object, AMD64.rdx); 540 XirOperand temp1 = asm.createRegisterTemp("temp1", CiKind.Word, AMD64.rcx);
541 541 XirOperand temp2 = asm.createRegisterTemp("temp2", CiKind.Word, AMD64.rax);
542 asm.mov(hub, hubParam); 542 XirOperand temp3 = asm.createRegisterTemp("temp3", CiKind.Word, AMD64.rdi);
543 asm.mov(length, lengthParam); 543 XirOperand size = asm.createRegisterTemp("size", CiKind.Int, AMD64.rsi);
544 useRegisters(asm, AMD64.rsi, AMD64.rcx, AMD64.rdi, AMD64.rax); 544
545 asm.callRuntime(config.newTypeArrayStub, result); 545 UnresolvedClassPatching patching = null;
546 546 if (is(UNRESOLVED, flags)) {
547 return asm.finishTemplate("newTypeArray"); 547 // insert the patching code for class resolving - the hub will end up in "hub"
548 patching = new UnresolvedClassPatching(asm, hub, config);
549 patching.emitInline();
550 } else {
551 asm.mov(hub, asm.createConstantInputParameter("hub", CiKind.Object));
552 }
553
554 asm.mov(length, lengthParam);
555
556 if (useFast) {
557
558 XirLabel slowPath = asm.createOutOfLineLabel("slowPath");
559
560 XirLabel done = asm.createInlineLabel("done");
561
562 // Check for negative array size.
563 // TODO: Also check for upper bound
564 asm.jlt(slowPath, length, asm.i(0));
565
566 final int aligning = target.wordSize;
567 final int arrayLengthOffset = target.wordSize * 2;
568 final int arrayElementOffset = config.getArrayOffset(kind);
569
570 // Calculate aligned size
571 asm.mov(size, length);
572 int scale = CiUtil.log2(kind.sizeInBytes(target.wordSize));
573 if (scale != 0) {
574 asm.shl(size, size, asm.i(scale));
575 }
576 asm.add(size, size, asm.i(arrayElementOffset + aligning - 1));
577 long mask = 0xFFFFFFFFL;
578 mask <<= CiUtil.log2(aligning);
579 asm.and(size, size, asm.i((int) mask));
580
581 // Try tlab allocation
582 XirOperand thread = asm.createRegisterTemp("thread", CiKind.Word, AMD64.r15);
583 asm.pload(CiKind.Word, result, thread, asm.i(config.threadTlabTopOffset), false);
584 asm.add(temp1, result, size);
585 asm.pload(CiKind.Word, temp2, thread, asm.i(config.threadTlabEndOffset), false);
586 asm.jgt(slowPath, temp1, temp2);
587 asm.pstore(CiKind.Word, thread, asm.i(config.threadTlabTopOffset), temp1, false);
588
589 // Now the new object is in result, store mark word and klass
590 asm.pload(CiKind.Word, temp1, hub, asm.i(config.instanceHeaderPrototypeOffset), false);
591 asm.pstore(CiKind.Word, result, temp1, false);
592 asm.pstore(CiKind.Object, result, asm.i(config.hubOffset), hub, false);
593
594 // Store array length
595 asm.pstore(CiKind.Int, result, asm.i(arrayLengthOffset), length, false);
596
597 // Initialize with 0
598 XirLabel top = asm.createInlineLabel("top");
599 asm.sub(size, size, asm.i(arrayElementOffset));
600 asm.shr(size, size, asm.i(Scale.Times8.log2));
601 asm.jeq(done, size, asm.i(0));
602 asm.xor(temp3, temp3, temp3);
603 asm.bindInline(top);
604 asm.pstore(CiKind.Word, result, size, temp3, arrayElementOffset - target.wordSize, Scale.Times8, false);
605 asm.decAndJumpNotZero(top, size);
606
607 asm.bindInline(done);
608
609 // Slow path
610 asm.bindOutOfLine(slowPath);
611 asm.callRuntime(slowPathStub, result);
612 asm.jmp(done);
613 } else {
614 asm.callRuntime(slowPathStub, result);
615 }
616
617 if (patching != null) {
618 patching.emitOutOfLine();
619 }
620 }
621
622 private KindTemplates newTypeArrayTemplates = new KindTemplates() {
623 @Override
624 protected XirTemplate create(CiXirAssembler asm, long flags, CiKind kind) {
625 emitNewTypeArray(asm, flags, kind, config.useFastNewTypeArray, config.newTypeArrayStub);
626 return asm.finishTemplate("newTypeArray<" + kind.toString() + ">");
548 } 627 }
549 }; 628 };
550 629
551 private final IndexTemplates multiNewArrayTemplate = new IndexTemplates(UNRESOLVED) { 630 private final IndexTemplates multiNewArrayTemplate = new IndexTemplates(UNRESOLVED) {
552 631
558 XirOperand rank = asm.createRegisterTemp("rank", CiKind.Int, AMD64.rbx); 637 XirOperand rank = asm.createRegisterTemp("rank", CiKind.Int, AMD64.rbx);
559 XirOperand sizes = asm.createRegisterTemp("sizes", CiKind.Long, AMD64.rcx); 638 XirOperand sizes = asm.createRegisterTemp("sizes", CiKind.Long, AMD64.rcx);
560 XirOperand thread = asm.createRegisterTemp("thread", CiKind.Long, AMD64.r15); 639 XirOperand thread = asm.createRegisterTemp("thread", CiKind.Long, AMD64.r15);
561 asm.add(sizes, thread, asm.l(config.threadMultiNewArrayStorage)); 640 asm.add(sizes, thread, asm.l(config.threadMultiNewArrayStorage));
562 for (int i = 0; i < dimensions; i++) { 641 for (int i = 0; i < dimensions; i++) {
563 XirParameter length = asm.createInputParameter("length" + i, CiKind.Int); 642 XirParameter length = asm.createInputParameter("length" + i, CiKind.Int, true);
564 asm.pstore(CiKind.Int, sizes, asm.i(i * target.sizeInBytes(CiKind.Int)), length, false); 643 asm.pstore(CiKind.Int, sizes, asm.i(i * target.sizeInBytes(CiKind.Int)), length, false);
565 } 644 }
566 645
567 UnresolvedClassPatching patching = null; 646 UnresolvedClassPatching patching = null;
568 if (is(UNRESOLVED, flags)) { 647 if (is(UNRESOLVED, flags)) {
699 778
700 @Override 779 @Override
701 protected XirTemplate create(CiXirAssembler asm, long flags, CiKind kind) { 780 protected XirTemplate create(CiXirAssembler asm, long flags, CiKind kind) {
702 XirOperand result = asm.restart(kind); 781 XirOperand result = asm.restart(kind);
703 XirParameter array = asm.createInputParameter("array", CiKind.Object); 782 XirParameter array = asm.createInputParameter("array", CiKind.Object);
704 XirParameter index = asm.createInputParameter("index", CiKind.Int); 783 XirParameter index = asm.createInputParameter("index", CiKind.Int, true);
705 XirLabel failBoundsCheck = null; 784 XirLabel failBoundsCheck = null;
706 // if the length is known the array cannot be null 785 // if the length is known the array cannot be null
707 boolean implicitNullException = is(NULL_CHECK, flags); 786 boolean implicitNullException = is(NULL_CHECK, flags);
708 787
709 if (is(BOUNDS_CHECK, flags)) { 788 if (is(BOUNDS_CHECK, flags)) {
710 // load the array length and check the index 789 // load the array length and check the index
711 failBoundsCheck = asm.createOutOfLineLabel("failBoundsCheck"); 790 failBoundsCheck = asm.createOutOfLineLabel("failBoundsCheck");
712 XirOperand length; 791 XirOperand length;
713 if (is(GIVEN_LENGTH, flags)) { 792 if (is(GIVEN_LENGTH, flags)) {
714 length = asm.createInputParameter("length", CiKind.Int); 793 length = asm.createInputParameter("length", CiKind.Int, true);
715 } else { 794 } else {
716 length = genArrayLength(array, implicitNullException); 795 length = genArrayLength(array, implicitNullException);
717 } 796 }
718 asm.jugteq(failBoundsCheck, index, length); 797 asm.jugteq(failBoundsCheck, index, length);
719 implicitNullException = false; 798 implicitNullException = false;
768 847
769 @Override 848 @Override
770 protected XirTemplate create(CiXirAssembler asm, long flags, CiKind kind) { 849 protected XirTemplate create(CiXirAssembler asm, long flags, CiKind kind) {
771 asm.restart(CiKind.Void); 850 asm.restart(CiKind.Void);
772 XirParameter src = asm.createInputParameter("src", CiKind.Object); 851 XirParameter src = asm.createInputParameter("src", CiKind.Object);
773 XirParameter srcPos = asm.createInputParameter("srcPos", CiKind.Int); 852 XirParameter srcPos = asm.createInputParameter("srcPos", CiKind.Int, true);
774 XirParameter dest = asm.createInputParameter("dest", CiKind.Object); 853 XirParameter dest = asm.createInputParameter("dest", CiKind.Object);
775 XirParameter destPos = asm.createInputParameter("destPos", CiKind.Int); 854 XirParameter destPos = asm.createInputParameter("destPos", CiKind.Int, true);
776 XirParameter length = asm.createInputParameter("length", CiKind.Int); 855 XirParameter length = asm.createInputParameter("length", CiKind.Int, true);
777 856
778 XirOperand tempSrc = asm.createTemp("tempSrc", CiKind.Word); 857 XirOperand tempSrc = asm.createTemp("tempSrc", CiKind.Word);
779 XirOperand tempDest = asm.createTemp("tempDest", CiKind.Word); 858 XirOperand tempDest = asm.createTemp("tempDest", CiKind.Word);
780 XirOperand lengthOperand = asm.createTemp("lengthOperand", CiKind.Int); 859 XirOperand lengthOperand = asm.createRegisterTemp("lengthOperand", CiKind.Int, AMD64.rax);
860
861 XirOperand compHub = null;
862 XirOperand valueHub = null;
863 XirOperand temp = null;
864 XirLabel store = null;
865 XirLabel slowStoreCheck = null;
866
867 if (is(STORE_CHECK, flags)) {
868 valueHub = asm.createRegisterTemp("valueHub", CiKind.Word, AMD64.rdi);
869 compHub = asm.createRegisterTemp("compHub", CiKind.Word, AMD64.rsi);
870 temp = asm.createRegisterTemp("temp", CiKind.Word, AMD64.r10);
871 }
781 872
782 // Calculate the factor for the repeat move instruction. 873 // Calculate the factor for the repeat move instruction.
783 int elementSize = kind.sizeInBytes(target.wordSize); 874 int elementSize = kind.sizeInBytes(target.wordSize);
784 int factor; 875 int factor;
785 boolean wordSize; 876 boolean wordSize;
804 asm.lea(tempDest, dest, destPos, config.getArrayOffset(kind), Scale.fromInt(elementSize)); 895 asm.lea(tempDest, dest, destPos, config.getArrayOffset(kind), Scale.fromInt(elementSize));
805 896
806 XirLabel reverse = null; 897 XirLabel reverse = null;
807 XirLabel normal = null; 898 XirLabel normal = null;
808 899
809 if (!is(INPUTS_DIFFERENT, flags) && !is(INPUTS_SAME, flags)) { 900 if (is(STORE_CHECK, flags)) {
810 normal = asm.createInlineLabel("reverse"); 901 reverse = asm.createInlineLabel("reverse");
902 asm.jneq(reverse, src, dest);
903 }
904
905 if (!is(STORE_CHECK, flags) && !is(INPUTS_DIFFERENT, flags) && !is(INPUTS_SAME, flags)) {
906 normal = asm.createInlineLabel("normal");
811 asm.jneq(normal, src, dest); 907 asm.jneq(normal, src, dest);
812 } 908 }
813 909
814 if (!is(INPUTS_DIFFERENT, flags)) { 910 if (!is(INPUTS_DIFFERENT, flags)) {
815 reverse = asm.createInlineLabel("reverse"); 911 if (reverse == null) {
912 reverse = asm.createInlineLabel("reverse");
913 }
816 asm.jlt(reverse, srcPos, destPos); 914 asm.jlt(reverse, srcPos, destPos);
817 } 915 }
818 916
819 if (!is(INPUTS_DIFFERENT, flags) && !is(INPUTS_SAME, flags)) { 917 if (!is(STORE_CHECK, flags) && !is(INPUTS_DIFFERENT, flags) && !is(INPUTS_SAME, flags)) {
820 asm.bindInline(normal); 918 asm.bindInline(normal);
821 } 919 }
822 920
823 // Everything set up => repeat mov. 921 // Everything set up => repeat mov.
824 if (wordSize) { 922 if (wordSize) {
825 asm.repmov(tempSrc, tempDest, lengthOperand); 923 asm.repmov(tempSrc, tempDest, lengthOperand);
826 } else { 924 } else {
827 asm.repmovb(tempSrc, tempDest, lengthOperand); 925 asm.repmovb(tempSrc, tempDest, lengthOperand);
828 } 926 }
829 927
830 if (!is(INPUTS_DIFFERENT, flags)) { 928 if (!is(INPUTS_DIFFERENT, flags) || is(STORE_CHECK, flags)) {
831 929
832 XirLabel end = asm.createInlineLabel("end"); 930 XirLabel end = asm.createInlineLabel("end");
833 asm.jmp(end); 931 asm.jmp(end);
834 932
835 // Implement reverse copy, because srcPos < destPos and src == dest. 933 // Implement reverse copy, because srcPos < destPos and src == dest.
836 asm.bindInline(reverse); 934 asm.bindInline(reverse);
837 935
838 CiKind copyKind = wordSize ? CiKind.Word : CiKind.Byte; 936 if (is(STORE_CHECK, flags)) {
937 asm.pload(CiKind.Object, compHub, dest, asm.i(config.hubOffset), false);
938 asm.pload(CiKind.Object, compHub, compHub, asm.i(config.arrayClassElementOffset), false);
939 }
940
941 CiKind copyKind = wordSize ? CiKind.Object : CiKind.Byte;
839 XirOperand tempValue = asm.createTemp("tempValue", copyKind); 942 XirOperand tempValue = asm.createTemp("tempValue", copyKind);
840 XirLabel start = asm.createInlineLabel("start"); 943 XirLabel start = asm.createInlineLabel("start");
841 asm.bindInline(start); 944 asm.bindInline(start);
842 asm.sub(lengthOperand, lengthOperand, asm.i(1)); 945 asm.sub(lengthOperand, lengthOperand, asm.i(1));
843 asm.jlt(end, lengthOperand, asm.i(0)); 946 asm.jlt(end, lengthOperand, asm.i(0));
844 947
845 Scale scale = wordSize ? Scale.fromInt(target.wordSize) : Scale.Times1; 948 Scale scale = wordSize ? Scale.fromInt(target.wordSize) : Scale.Times1;
846 asm.pload(copyKind, tempValue, tempSrc, lengthOperand, 0, scale, false); 949 asm.pload(copyKind, tempValue, tempSrc, lengthOperand, 0, scale, false);
950
951 if (is(STORE_CHECK, flags)) {
952 slowStoreCheck = asm.createOutOfLineLabel("slowStoreCheck");
953 store = asm.createInlineLabel("store");
954 asm.jeq(store, tempValue, asm.o(null)); // first check if value is null
955 asm.pload(CiKind.Object, valueHub, tempValue, asm.i(config.hubOffset), false);
956 asm.jneq(slowStoreCheck, compHub, valueHub); // then check component hub matches value hub
957 asm.bindInline(store);
958 }
959
847 asm.pstore(copyKind, tempDest, lengthOperand, tempValue, 0, scale, false); 960 asm.pstore(copyKind, tempDest, lengthOperand, tempValue, 0, scale, false);
848 961
849 asm.jmp(start); 962 asm.jmp(start);
850 asm.bindInline(end); 963 asm.bindInline(end);
851 } 964 }
872 asm.sub(tempDestEnd, tempDestEnd, asm.i(1)); 985 asm.sub(tempDestEnd, tempDestEnd, asm.i(1));
873 asm.jneq(writeBarrierLoop, tempDestEnd, tempDest); 986 asm.jneq(writeBarrierLoop, tempDestEnd, tempDest);
874 asm.jmp(back); 987 asm.jmp(back);
875 } 988 }
876 989
990 if (is(STORE_CHECK, flags)) {
991 assert kind == CiKind.Object;
992 useRegisters(asm, AMD64.rax);
993 asm.bindOutOfLine(slowStoreCheck);
994 checkSubtype(asm, temp, valueHub, compHub);
995 asm.jneq(store, temp, asm.w(0));
996 asm.callRuntime(config.throwArrayStoreException, null);
997 asm.jmp(store);
998 }
999
877 return asm.finishTemplate("arraycopy<" + kind + ">"); 1000 return asm.finishTemplate("arraycopy<" + kind + ">");
878 } 1001 }
879 }; 1002 };
880 1003
881 private KindTemplates arrayStoreTemplates = new KindTemplates(NULL_CHECK, WRITE_BARRIER, BOUNDS_CHECK, STORE_CHECK, GIVEN_LENGTH) { 1004 private KindTemplates arrayStoreTemplates = new KindTemplates(NULL_CHECK, WRITE_BARRIER, BOUNDS_CHECK, STORE_CHECK, GIVEN_LENGTH) {
882 1005
883 @Override 1006 @Override
884 protected XirTemplate create(CiXirAssembler asm, long flags, CiKind kind) { 1007 protected XirTemplate create(CiXirAssembler asm, long flags, CiKind kind) {
885 asm.restart(CiKind.Void); 1008 asm.restart(CiKind.Void);
886 XirParameter array = asm.createInputParameter("array", CiKind.Object); 1009 XirParameter array = asm.createInputParameter("array", CiKind.Object);
887 XirParameter index = asm.createInputParameter("index", CiKind.Int); 1010 XirParameter index = asm.createInputParameter("index", CiKind.Int, true);
888 XirParameter value = asm.createInputParameter("value", kind); 1011 XirParameter value = asm.createInputParameter("value", kind, kind != CiKind.Object);
889 XirOperand temp = asm.createTemp("temp", CiKind.Word); 1012 XirOperand temp = asm.createTemp("temp", CiKind.Word);
890 XirOperand valueHub = null; 1013 XirOperand valueHub = null;
891 XirOperand compHub = null; 1014 XirOperand compHub = null;
892 XirLabel store = asm.createInlineLabel("store"); 1015 XirLabel store = asm.createInlineLabel("store");
893 XirLabel failBoundsCheck = null; 1016 XirLabel failBoundsCheck = null;
1100 } 1223 }
1101 return new XirSnippet(newObjectArrayTemplates.get(site, UNRESOLVED), length); 1224 return new XirSnippet(newObjectArrayTemplates.get(site, UNRESOLVED), length);
1102 } 1225 }
1103 assert arrayType == null; 1226 assert arrayType == null;
1104 arrayType = Compiler.getVMEntries().getPrimitiveArrayType(elementKind); 1227 arrayType = Compiler.getVMEntries().getPrimitiveArrayType(elementKind);
1105 return new XirSnippet(newTypeArrayTemplates.get(site), length, XirArgument.forObject(arrayType)); 1228 return new XirSnippet(newTypeArrayTemplates.get(site, elementKind), length, XirArgument.forObject(arrayType));
1229 }
1230
1231 @Override
1232 public XirSnippet genNewObjectArrayClone(XirSite site, XirArgument newLength, XirArgument referenceArray) {
1233 return new XirSnippet(newObjectArrayCloneTemplates.get(site), newLength, referenceArray);
1106 } 1234 }
1107 1235
1108 @Override 1236 @Override
1109 public XirSnippet genNewMultiArray(XirSite site, XirArgument[] lengths, RiType type) { 1237 public XirSnippet genNewMultiArray(XirSite site, XirArgument[] lengths, RiType type) {
1110 if (type instanceof HotSpotTypeResolved) { 1238 if (type instanceof HotSpotTypeResolved) {
1337 private void writeBarrier(CiXirAssembler asm, XirOperand base) { 1465 private void writeBarrier(CiXirAssembler asm, XirOperand base) {
1338 asm.shr(base, base, asm.i(config.cardtableShift)); 1466 asm.shr(base, base, asm.i(config.cardtableShift));
1339 asm.pstore(CiKind.Boolean, asm.w(config.cardtableStartAddress), base, asm.b(false), false); 1467 asm.pstore(CiKind.Boolean, asm.w(config.cardtableStartAddress), base, asm.b(false), false);
1340 } 1468 }
1341 1469
1470 public boolean is(TemplateFlag check, long flags) {
1471 return (flags & check.bits()) == check.bits();
1472 }
1473
1342 /** 1474 /**
1343 * Base class for all the ondemand template generators. It is not normally subclassed directly, but through one of 1475 * Base class for all the ondemand template generators. It is not normally subclassed directly, but through one of
1344 * its subclasses (SimpleTemplates, KindTemplates, IndexTemplates). 1476 * its subclasses (SimpleTemplates, KindTemplates, IndexTemplates).
1345 * 1477 *
1346 * @author Lukas Stadler 1478 * @author Lukas Stadler
1356 public Templates(TemplateFlag... flags) { 1488 public Templates(TemplateFlag... flags) {
1357 this.mask = getBits((int) INDEX_MASK, null, flags); 1489 this.mask = getBits((int) INDEX_MASK, null, flags);
1358 } 1490 }
1359 1491
1360 protected abstract XirTemplate create(CiXirAssembler asm, long flags); 1492 protected abstract XirTemplate create(CiXirAssembler asm, long flags);
1361
1362 protected boolean is(TemplateFlag check, long flags) {
1363 return (flags & check.bits()) == check.bits();
1364 }
1365 1493
1366 protected long getBits(int index, XirSite site, TemplateFlag... flags) { 1494 protected long getBits(int index, XirSite site, TemplateFlag... flags) {
1367 long bits = index; 1495 long bits = index;
1368 if (site != null) { 1496 if (site != null) {
1369 bits |= site.requiresNullCheck() ? NULL_CHECK.bits() : 0; 1497 bits |= site.requiresNullCheck() ? NULL_CHECK.bits() : 0;