Mercurial > hg > graal-jvmci-8
comparison src/cpu/sparc/vm/sharedRuntime_sparc.cpp @ 1006:dcf03e02b020
6879902: CTW failure jdk6_18/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp:845
Summary: For signatures with a large number of arguments the offset for the float store becomes too big and does not fit in 13-bit.
Reviewed-by: kvn, never
author | twisti |
---|---|
date | Tue, 06 Oct 2009 02:11:49 -0700 |
parents | 6b2273dd6fa9 |
children | 1ce3281a8e93 |
comparison
equal
deleted
inserted
replaced
997:46b819ba120b | 1006:dcf03e02b020 |
---|---|
538 // retun the amount of stack space these arguments will need. | 538 // retun the amount of stack space these arguments will need. |
539 return stk_reg_pairs; | 539 return stk_reg_pairs; |
540 | 540 |
541 } | 541 } |
542 | 542 |
543 // Helper class mostly to avoid passing masm everywhere, and handle store | 543 // Helper class mostly to avoid passing masm everywhere, and handle |
544 // displacement overflow logic for LP64 | 544 // store displacement overflow logic. |
545 class AdapterGenerator { | 545 class AdapterGenerator { |
546 MacroAssembler *masm; | 546 MacroAssembler *masm; |
547 #ifdef _LP64 | |
548 Register Rdisp; | 547 Register Rdisp; |
549 void set_Rdisp(Register r) { Rdisp = r; } | 548 void set_Rdisp(Register r) { Rdisp = r; } |
550 #endif // _LP64 | |
551 | 549 |
552 void patch_callers_callsite(); | 550 void patch_callers_callsite(); |
553 void tag_c2i_arg(frame::Tag t, Register base, int st_off, Register scratch); | 551 void tag_c2i_arg(frame::Tag t, Register base, int st_off, Register scratch); |
554 | 552 |
555 // base+st_off points to top of argument | 553 // base+st_off points to top of argument |
556 int arg_offset(const int st_off) { return st_off + Interpreter::value_offset_in_bytes(); } | 554 int arg_offset(const int st_off) { return st_off + Interpreter::value_offset_in_bytes(); } |
557 int next_arg_offset(const int st_off) { | 555 int next_arg_offset(const int st_off) { |
558 return st_off - Interpreter::stackElementSize() + Interpreter::value_offset_in_bytes(); | 556 return st_off - Interpreter::stackElementSize() + Interpreter::value_offset_in_bytes(); |
559 } | 557 } |
560 | 558 |
561 #ifdef _LP64 | 559 int tag_offset(const int st_off) { return st_off + Interpreter::tag_offset_in_bytes(); } |
562 // On _LP64 argument slot values are loaded first into a register | 560 int next_tag_offset(const int st_off) { |
563 // because they might not fit into displacement. | 561 return st_off - Interpreter::stackElementSize() + Interpreter::tag_offset_in_bytes(); |
564 Register arg_slot(const int st_off); | 562 } |
565 Register next_arg_slot(const int st_off); | 563 |
566 #else | 564 // Argument slot values may be loaded first into a register because |
567 int arg_slot(const int st_off) { return arg_offset(st_off); } | 565 // they might not fit into displacement. |
568 int next_arg_slot(const int st_off) { return next_arg_offset(st_off); } | 566 RegisterOrConstant arg_slot(const int st_off); |
569 #endif // _LP64 | 567 RegisterOrConstant next_arg_slot(const int st_off); |
568 | |
569 RegisterOrConstant tag_slot(const int st_off); | |
570 RegisterOrConstant next_tag_slot(const int st_off); | |
570 | 571 |
571 // Stores long into offset pointed to by base | 572 // Stores long into offset pointed to by base |
572 void store_c2i_long(Register r, Register base, | 573 void store_c2i_long(Register r, Register base, |
573 const int st_off, bool is_stack); | 574 const int st_off, bool is_stack); |
574 void store_c2i_object(Register r, Register base, | 575 void store_c2i_object(Register r, Register base, |
654 } | 655 } |
655 | 656 |
656 void AdapterGenerator::tag_c2i_arg(frame::Tag t, Register base, int st_off, | 657 void AdapterGenerator::tag_c2i_arg(frame::Tag t, Register base, int st_off, |
657 Register scratch) { | 658 Register scratch) { |
658 if (TaggedStackInterpreter) { | 659 if (TaggedStackInterpreter) { |
659 int tag_off = st_off + Interpreter::tag_offset_in_bytes(); | 660 RegisterOrConstant slot = tag_slot(st_off); |
660 #ifdef _LP64 | |
661 Register tag_slot = Rdisp; | |
662 __ set(tag_off, tag_slot); | |
663 #else | |
664 int tag_slot = tag_off; | |
665 #endif // _LP64 | |
666 // have to store zero because local slots can be reused (rats!) | 661 // have to store zero because local slots can be reused (rats!) |
667 if (t == frame::TagValue) { | 662 if (t == frame::TagValue) { |
668 __ st_ptr(G0, base, tag_slot); | 663 __ st_ptr(G0, base, slot); |
669 } else if (t == frame::TagCategory2) { | 664 } else if (t == frame::TagCategory2) { |
670 __ st_ptr(G0, base, tag_slot); | 665 __ st_ptr(G0, base, slot); |
671 int next_tag_off = st_off - Interpreter::stackElementSize() + | 666 __ st_ptr(G0, base, next_tag_slot(st_off)); |
672 Interpreter::tag_offset_in_bytes(); | |
673 #ifdef _LP64 | |
674 __ set(next_tag_off, tag_slot); | |
675 #else | |
676 tag_slot = next_tag_off; | |
677 #endif // _LP64 | |
678 __ st_ptr(G0, base, tag_slot); | |
679 } else { | 667 } else { |
680 __ mov(t, scratch); | 668 __ mov(t, scratch); |
681 __ st_ptr(scratch, base, tag_slot); | 669 __ st_ptr(scratch, base, slot); |
682 } | 670 } |
683 } | 671 } |
684 } | 672 } |
685 | 673 |
686 #ifdef _LP64 | 674 |
687 Register AdapterGenerator::arg_slot(const int st_off) { | 675 RegisterOrConstant AdapterGenerator::arg_slot(const int st_off) { |
688 __ set( arg_offset(st_off), Rdisp); | 676 RegisterOrConstant roc(arg_offset(st_off)); |
689 return Rdisp; | 677 return __ ensure_simm13_or_reg(roc, Rdisp); |
690 } | 678 } |
691 | 679 |
692 Register AdapterGenerator::next_arg_slot(const int st_off){ | 680 RegisterOrConstant AdapterGenerator::next_arg_slot(const int st_off) { |
693 __ set( next_arg_offset(st_off), Rdisp); | 681 RegisterOrConstant roc(next_arg_offset(st_off)); |
694 return Rdisp; | 682 return __ ensure_simm13_or_reg(roc, Rdisp); |
695 } | 683 } |
696 #endif // _LP64 | 684 |
685 | |
686 RegisterOrConstant AdapterGenerator::tag_slot(const int st_off) { | |
687 RegisterOrConstant roc(tag_offset(st_off)); | |
688 return __ ensure_simm13_or_reg(roc, Rdisp); | |
689 } | |
690 | |
691 RegisterOrConstant AdapterGenerator::next_tag_slot(const int st_off) { | |
692 RegisterOrConstant roc(next_tag_offset(st_off)); | |
693 return __ ensure_simm13_or_reg(roc, Rdisp); | |
694 } | |
695 | |
697 | 696 |
698 // Stores long into offset pointed to by base | 697 // Stores long into offset pointed to by base |
699 void AdapterGenerator::store_c2i_long(Register r, Register base, | 698 void AdapterGenerator::store_c2i_long(Register r, Register base, |
700 const int st_off, bool is_stack) { | 699 const int st_off, bool is_stack) { |
701 #ifdef _LP64 | 700 #ifdef _LP64 |
1050 // 32-bit build and aligned in the 64-bit build. Look for the obvious | 1049 // 32-bit build and aligned in the 64-bit build. Look for the obvious |
1051 // ldx/lddf optimizations. | 1050 // ldx/lddf optimizations. |
1052 | 1051 |
1053 // Load in argument order going down. | 1052 // Load in argument order going down. |
1054 const int ld_off = (total_args_passed-i)*Interpreter::stackElementSize(); | 1053 const int ld_off = (total_args_passed-i)*Interpreter::stackElementSize(); |
1055 #ifdef _LP64 | |
1056 set_Rdisp(G1_scratch); | 1054 set_Rdisp(G1_scratch); |
1057 #endif // _LP64 | |
1058 | 1055 |
1059 VMReg r_1 = regs[i].first(); | 1056 VMReg r_1 = regs[i].first(); |
1060 VMReg r_2 = regs[i].second(); | 1057 VMReg r_2 = regs[i].second(); |
1061 if (!r_1->is_valid()) { | 1058 if (!r_1->is_valid()) { |
1062 assert(!r_2->is_valid(), ""); | 1059 assert(!r_2->is_valid(), ""); |
1072 __ ld(Gargs, arg_slot(ld_off), r); | 1069 __ ld(Gargs, arg_slot(ld_off), r); |
1073 } else { | 1070 } else { |
1074 #ifdef _LP64 | 1071 #ifdef _LP64 |
1075 // In V9, longs are given 2 64-bit slots in the interpreter, but the | 1072 // In V9, longs are given 2 64-bit slots in the interpreter, but the |
1076 // data is passed in only 1 slot. | 1073 // data is passed in only 1 slot. |
1077 Register slot = (sig_bt[i]==T_LONG) ? | 1074 RegisterOrConstant slot = (sig_bt[i] == T_LONG) ? |
1078 next_arg_slot(ld_off) : arg_slot(ld_off); | 1075 next_arg_slot(ld_off) : arg_slot(ld_off); |
1079 __ ldx(Gargs, slot, r); | 1076 __ ldx(Gargs, slot, r); |
1080 #else | 1077 #else |
1081 // Need to load a 64-bit value into G1/G4, but G1/G4 is being used in the | 1078 // Need to load a 64-bit value into G1/G4, but G1/G4 is being used in the |
1082 // stack shuffle. Load the first 2 longs into G1/G4 later. | 1079 // stack shuffle. Load the first 2 longs into G1/G4 later. |
1090 #ifdef _LP64 | 1087 #ifdef _LP64 |
1091 // In V9, doubles are given 2 64-bit slots in the interpreter, but the | 1088 // In V9, doubles are given 2 64-bit slots in the interpreter, but the |
1092 // data is passed in only 1 slot. This code also handles longs that | 1089 // data is passed in only 1 slot. This code also handles longs that |
1093 // are passed on the stack, but need a stack-to-stack move through a | 1090 // are passed on the stack, but need a stack-to-stack move through a |
1094 // spare float register. | 1091 // spare float register. |
1095 Register slot = (sig_bt[i]==T_LONG || sig_bt[i] == T_DOUBLE) ? | 1092 RegisterOrConstant slot = (sig_bt[i] == T_LONG || sig_bt[i] == T_DOUBLE) ? |
1096 next_arg_slot(ld_off) : arg_slot(ld_off); | 1093 next_arg_slot(ld_off) : arg_slot(ld_off); |
1097 __ ldf(FloatRegisterImpl::D, Gargs, slot, r_1->as_FloatRegister()); | 1094 __ ldf(FloatRegisterImpl::D, Gargs, slot, r_1->as_FloatRegister()); |
1098 #else | 1095 #else |
1099 // Need to marshal 64-bit value from misaligned Lesp loads | 1096 // Need to marshal 64-bit value from misaligned Lesp loads |
1100 __ ldf(FloatRegisterImpl::S, Gargs, next_arg_slot(ld_off), r_1->as_FloatRegister()); | 1097 __ ldf(FloatRegisterImpl::S, Gargs, next_arg_slot(ld_off), r_1->as_FloatRegister()); |
1107 if (regs[i].first()->is_stack()) { | 1104 if (regs[i].first()->is_stack()) { |
1108 assert(r_1->as_FloatRegister() == F8, "fix this code"); | 1105 assert(r_1->as_FloatRegister() == F8, "fix this code"); |
1109 // Convert stack slot to an SP offset | 1106 // Convert stack slot to an SP offset |
1110 int st_off = reg2offset(regs[i].first()) + STACK_BIAS; | 1107 int st_off = reg2offset(regs[i].first()) + STACK_BIAS; |
1111 // Store down the shuffled stack word. Target address _is_ aligned. | 1108 // Store down the shuffled stack word. Target address _is_ aligned. |
1112 if (!r_2->is_valid()) __ stf(FloatRegisterImpl::S, r_1->as_FloatRegister(), SP, st_off); | 1109 RegisterOrConstant slot = __ ensure_simm13_or_reg(st_off, Rdisp); |
1113 else __ stf(FloatRegisterImpl::D, r_1->as_FloatRegister(), SP, st_off); | 1110 if (!r_2->is_valid()) __ stf(FloatRegisterImpl::S, r_1->as_FloatRegister(), SP, slot); |
1111 else __ stf(FloatRegisterImpl::D, r_1->as_FloatRegister(), SP, slot); | |
1114 } | 1112 } |
1115 } | 1113 } |
1116 bool made_space = false; | 1114 bool made_space = false; |
1117 #ifndef _LP64 | 1115 #ifndef _LP64 |
1118 // May need to pick up a few long args in G1/G4 | 1116 // May need to pick up a few long args in G1/G4 |