Mercurial > hg > graal-jvmci-8
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; |