776 }
777 };
778
779 class HandlerImpl {
780
781 public:
782
783 static int emit_exception_handler(CodeBuffer &cbuf);
784 static int emit_deopt_handler(CodeBuffer& cbuf);
785
786 static uint size_exception_handler() {
787 return MacroAssembler::far_branch_size();
788 }
789
790 static uint size_deopt_handler() {
791 // count one adr and one far branch instruction
792 return 4 * NativeInstruction::instruction_size;
793 }
794 };
795
796 bool preceded_by_ordered_load(const Node *barrier);
797
798 // Use barrier instructions rather than load acquire / store
799 // release.
800 const bool UseBarriersForVolatile = true;
801 %}
802
803 source %{
804
805 // AArch64 has load acquire and store release instructions which we
806 // use for ordered memory accesses, e.g. for volatiles. The ideal
807 // graph generator also inserts memory barriers around volatile
808 // accesses, and we don't want to generate both barriers and acq/rel
809 // instructions. So, when we emit a MemBarAcquire we look back in
810 // the ideal graph for an ordered load and only emit the barrier if
811 // we don't find one.
812
813 bool preceded_by_ordered_load(const Node *barrier) {
814 Node *x = barrier->lookup(TypeFunc::Parms);
815
816 if (! x)
817 return false;
818
819 if (x->is_DecodeNarrowPtr())
820 x = x->in(1);
821
822 if (x->is_Load())
823 return ! x->as_Load()->is_unordered();
824
825 return false;
826 }
827
828 #define __ _masm.
829
830 // advance declarations for helper functions to convert register
831 // indices to register objects
832
833 // the ad file has to provide implementations of certain methods
834 // expected by the generic code
835 //
836 // REQUIRED FUNCTIONALITY
837
838 //=============================================================================
839
840 // !!!!! Special hack to get all types of calls to specify the byte offset
841 // from the start of the call to the point where the return address
842 // will point.
843
844 int MachCallStaticJavaNode::ret_addr_offset()
845 {
846 // call should be a simple bl
847 // unless this is a method handle invoke in which case it is
5134 // by referring to it with a '$' prefix.
5135 // opcode -- Three instruction opcodes may be provided. These are referred
5136 // to within an encode class as $primary, $secondary, and $tertiary
5137 // rrspectively. The primary opcode is commonly used to
5138 // indicate the type of machine instruction, while secondary
5139 // and tertiary are often used for prefix options or addressing
5140 // modes.
5141 // ins_encode -- A list of encode classes with parameters. The encode class
5142 // name must have been defined in an 'enc_class' specification
5143 // in the encode section of the architecture description.
5144
5145 // ============================================================================
5146 // Memory (Load/Store) Instructions
5147
5148 // Load Instructions
5149
5150 // Load Byte (8 bit signed)
5151 instruct loadB(iRegINoSp dst, memory mem)
5152 %{
5153 match(Set dst (LoadB mem));
5154 predicate(UseBarriersForVolatile || n->as_Load()->is_unordered());
5155
5156 ins_cost(4 * INSN_COST);
5157 format %{ "ldrsbw $dst, $mem\t# byte" %}
5158
5159 ins_encode(aarch64_enc_ldrsbw(dst, mem));
5160
5161 ins_pipe(iload_reg_mem);
5162 %}
5163
5164 // Load Byte (8 bit signed) into long
5165 instruct loadB2L(iRegLNoSp dst, memory mem)
5166 %{
5167 match(Set dst (ConvI2L (LoadB mem)));
5168 predicate(UseBarriersForVolatile || n->in(1)->as_Load()->is_unordered());
5169
5170 ins_cost(4 * INSN_COST);
5171 format %{ "ldrsb $dst, $mem\t# byte" %}
5172
5173 ins_encode(aarch64_enc_ldrsb(dst, mem));
5174
5175 ins_pipe(iload_reg_mem);
5176 %}
5177
5178 // Load Byte (8 bit unsigned)
5179 instruct loadUB(iRegINoSp dst, memory mem)
5180 %{
5181 match(Set dst (LoadUB mem));
5182 predicate(UseBarriersForVolatile || n->as_Load()->is_unordered());
5183
5184 ins_cost(4 * INSN_COST);
5185 format %{ "ldrbw $dst, $mem\t# byte" %}
5186
5187 ins_encode(aarch64_enc_ldrb(dst, mem));
5188
5189 ins_pipe(iload_reg_mem);
5190 %}
5191
5192 // Load Byte (8 bit unsigned) into long
5193 instruct loadUB2L(iRegLNoSp dst, memory mem)
5194 %{
5195 match(Set dst (ConvI2L (LoadUB mem)));
5196 predicate(UseBarriersForVolatile || n->in(1)->as_Load()->is_unordered());
5197
5198 ins_cost(4 * INSN_COST);
5199 format %{ "ldrb $dst, $mem\t# byte" %}
5200
5201 ins_encode(aarch64_enc_ldrb(dst, mem));
5202
5203 ins_pipe(iload_reg_mem);
5204 %}
5205
5206 // Load Short (16 bit signed)
5207 instruct loadS(iRegINoSp dst, memory mem)
5208 %{
5209 match(Set dst (LoadS mem));
5210 predicate(UseBarriersForVolatile || n->as_Load()->is_unordered());
5211
5212 ins_cost(4 * INSN_COST);
5213 format %{ "ldrshw $dst, $mem\t# short" %}
5214
5215 ins_encode(aarch64_enc_ldrshw(dst, mem));
5216
5217 ins_pipe(iload_reg_mem);
5218 %}
5219
5220 // Load Short (16 bit signed) into long
5221 instruct loadS2L(iRegLNoSp dst, memory mem)
5222 %{
5223 match(Set dst (ConvI2L (LoadS mem)));
5224 predicate(UseBarriersForVolatile || n->in(1)->as_Load()->is_unordered());
5225
5226 ins_cost(4 * INSN_COST);
5227 format %{ "ldrsh $dst, $mem\t# short" %}
5228
5229 ins_encode(aarch64_enc_ldrsh(dst, mem));
5230
5231 ins_pipe(iload_reg_mem);
5232 %}
5233
5234 // Load Char (16 bit unsigned)
5235 instruct loadUS(iRegINoSp dst, memory mem)
5236 %{
5237 match(Set dst (LoadUS mem));
5238 predicate(UseBarriersForVolatile || n->as_Load()->is_unordered());
5239
5240 ins_cost(4 * INSN_COST);
5241 format %{ "ldrh $dst, $mem\t# short" %}
5242
5243 ins_encode(aarch64_enc_ldrh(dst, mem));
5244
5245 ins_pipe(iload_reg_mem);
5246 %}
5247
5248 // Load Short/Char (16 bit unsigned) into long
5249 instruct loadUS2L(iRegLNoSp dst, memory mem)
5250 %{
5251 match(Set dst (ConvI2L (LoadUS mem)));
5252 predicate(UseBarriersForVolatile || n->in(1)->as_Load()->is_unordered());
5253
5254 ins_cost(4 * INSN_COST);
5255 format %{ "ldrh $dst, $mem\t# short" %}
5256
5257 ins_encode(aarch64_enc_ldrh(dst, mem));
5258
5259 ins_pipe(iload_reg_mem);
5260 %}
5261
5262 // Load Integer (32 bit signed)
5263 instruct loadI(iRegINoSp dst, memory mem)
5264 %{
5265 match(Set dst (LoadI mem));
5266 predicate(UseBarriersForVolatile || n->as_Load()->is_unordered());
5267
5268 ins_cost(4 * INSN_COST);
5269 format %{ "ldrw $dst, $mem\t# int" %}
5270
5271 ins_encode(aarch64_enc_ldrw(dst, mem));
5272
5273 ins_pipe(iload_reg_mem);
5274 %}
5275
5276 // Load Integer (32 bit signed) into long
5277 instruct loadI2L(iRegLNoSp dst, memory mem)
5278 %{
5279 match(Set dst (ConvI2L (LoadI mem)));
5280 predicate(UseBarriersForVolatile || n->in(1)->as_Load()->is_unordered());
5281
5282 ins_cost(4 * INSN_COST);
5283 format %{ "ldrsw $dst, $mem\t# int" %}
5284
5285 ins_encode(aarch64_enc_ldrsw(dst, mem));
5286
5287 ins_pipe(iload_reg_mem);
5288 %}
5289
5290 // Load Integer (32 bit unsigned) into long
5291 instruct loadUI2L(iRegLNoSp dst, memory mem, immL_32bits mask)
5292 %{
5293 match(Set dst (AndL (ConvI2L (LoadI mem)) mask));
5294 predicate(UseBarriersForVolatile || n->in(1)->in(1)->as_Load()->is_unordered());
5295
5296 ins_cost(4 * INSN_COST);
5297 format %{ "ldrw $dst, $mem\t# int" %}
5298
5299 ins_encode(aarch64_enc_ldrw(dst, mem));
5300
5301 ins_pipe(iload_reg_mem);
5302 %}
5303
5304 // Load Long (64 bit signed)
5305 instruct loadL(iRegLNoSp dst, memory mem)
5306 %{
5307 match(Set dst (LoadL mem));
5308 predicate(UseBarriersForVolatile || n->as_Load()->is_unordered());
5309
5310 ins_cost(4 * INSN_COST);
5311 format %{ "ldr $dst, $mem\t# int" %}
5312
5313 ins_encode(aarch64_enc_ldr(dst, mem));
5314
5315 ins_pipe(iload_reg_mem);
5316 %}
5317
5318 // Load Range
5319 instruct loadRange(iRegINoSp dst, memory mem)
5320 %{
5321 match(Set dst (LoadRange mem));
5322
5323 ins_cost(4 * INSN_COST);
5324 format %{ "ldrw $dst, $mem\t# range" %}
5325
5326 ins_encode(aarch64_enc_ldrw(dst, mem));
5327
5328 ins_pipe(iload_reg_mem);
5329 %}
5330
5331 // Load Pointer
5332 instruct loadP(iRegPNoSp dst, memory mem)
5333 %{
5334 match(Set dst (LoadP mem));
5335 predicate(UseBarriersForVolatile || n->as_Load()->is_unordered());
5336
5337 ins_cost(4 * INSN_COST);
5338 format %{ "ldr $dst, $mem\t# ptr" %}
5339
5340 ins_encode(aarch64_enc_ldr(dst, mem));
5341
5342 ins_pipe(iload_reg_mem);
5343 %}
5344
5345 // Load Compressed Pointer
5346 instruct loadN(iRegNNoSp dst, memory mem)
5347 %{
5348 match(Set dst (LoadN mem));
5349 predicate(UseBarriersForVolatile || n->as_Load()->is_unordered());
5350
5351 ins_cost(4 * INSN_COST);
5352 format %{ "ldrw $dst, $mem\t# compressed ptr" %}
5353
5354 ins_encode(aarch64_enc_ldrw(dst, mem));
5355
5356 ins_pipe(iload_reg_mem);
5357 %}
5358
5359 // Load Klass Pointer
5360 instruct loadKlass(iRegPNoSp dst, memory mem)
5361 %{
5362 match(Set dst (LoadKlass mem));
5363 predicate(UseBarriersForVolatile || n->as_Load()->is_unordered());
5364
5365 ins_cost(4 * INSN_COST);
5366 format %{ "ldr $dst, $mem\t# class" %}
5367
5368 ins_encode(aarch64_enc_ldr(dst, mem));
5369
5370 ins_pipe(iload_reg_mem);
5371 %}
5372
5373 // Load Narrow Klass Pointer
5374 instruct loadNKlass(iRegNNoSp dst, memory mem)
5375 %{
5376 match(Set dst (LoadNKlass mem));
5377 predicate(UseBarriersForVolatile || n->as_Load()->is_unordered());
5378
5379 ins_cost(4 * INSN_COST);
5380 format %{ "ldrw $dst, $mem\t# compressed class ptr" %}
5381
5382 ins_encode(aarch64_enc_ldrw(dst, mem));
5383
5384 ins_pipe(iload_reg_mem);
5385 %}
5386
5387 // Load Float
5388 instruct loadF(vRegF dst, memory mem)
5389 %{
5390 match(Set dst (LoadF mem));
5391 predicate(UseBarriersForVolatile || n->as_Load()->is_unordered());
5392
5393 ins_cost(4 * INSN_COST);
5394 format %{ "ldrs $dst, $mem\t# float" %}
5395
5396 ins_encode( aarch64_enc_ldrs(dst, mem) );
5397
5398 ins_pipe(pipe_class_memory);
5399 %}
5400
5401 // Load Double
5402 instruct loadD(vRegD dst, memory mem)
5403 %{
5404 match(Set dst (LoadD mem));
5405 predicate(UseBarriersForVolatile || n->as_Load()->is_unordered());
5406
5407 ins_cost(4 * INSN_COST);
5408 format %{ "ldrd $dst, $mem\t# double" %}
5409
5410 ins_encode( aarch64_enc_ldrd(dst, mem) );
5411
5412 ins_pipe(pipe_class_memory);
5413 %}
5414
5415
5416 // Load Int Constant
5417 instruct loadConI(iRegINoSp dst, immI src)
5418 %{
5419 match(Set dst src);
5420
5421 ins_cost(INSN_COST);
5422 format %{ "mov $dst, $src\t# int" %}
5423
5424 ins_encode( aarch64_enc_movw_imm(dst, src) );
5425
5616
5617 // Store Instructions
5618
5619 // Store CMS card-mark Immediate
5620 instruct storeimmCM0(immI0 zero, memory mem)
5621 %{
5622 match(Set mem (StoreCM mem zero));
5623
5624 ins_cost(INSN_COST);
5625 format %{ "strb zr, $mem\t# byte" %}
5626
5627 ins_encode(aarch64_enc_strb0(mem));
5628
5629 ins_pipe(istore_mem);
5630 %}
5631
5632 // Store Byte
5633 instruct storeB(iRegIorL2I src, memory mem)
5634 %{
5635 match(Set mem (StoreB mem src));
5636 predicate(UseBarriersForVolatile || n->as_Store()->is_unordered());
5637
5638 ins_cost(INSN_COST);
5639 format %{ "strb $src, $mem\t# byte" %}
5640
5641 ins_encode(aarch64_enc_strb(src, mem));
5642
5643 ins_pipe(istore_reg_mem);
5644 %}
5645
5646
5647 instruct storeimmB0(immI0 zero, memory mem)
5648 %{
5649 match(Set mem (StoreB mem zero));
5650 predicate(UseBarriersForVolatile || n->as_Store()->is_unordered());
5651
5652 ins_cost(INSN_COST);
5653 format %{ "strb zr, $mem\t# byte" %}
5654
5655 ins_encode(aarch64_enc_strb0(mem));
5656
5657 ins_pipe(istore_mem);
5658 %}
5659
5660 // Store Char/Short
5661 instruct storeC(iRegIorL2I src, memory mem)
5662 %{
5663 match(Set mem (StoreC mem src));
5664 predicate(UseBarriersForVolatile || n->as_Store()->is_unordered());
5665
5666 ins_cost(INSN_COST);
5667 format %{ "strh $src, $mem\t# short" %}
5668
5669 ins_encode(aarch64_enc_strh(src, mem));
5670
5671 ins_pipe(istore_reg_mem);
5672 %}
5673
5674 instruct storeimmC0(immI0 zero, memory mem)
5675 %{
5676 match(Set mem (StoreC mem zero));
5677 predicate(UseBarriersForVolatile || n->as_Store()->is_unordered());
5678
5679 ins_cost(INSN_COST);
5680 format %{ "strh zr, $mem\t# short" %}
5681
5682 ins_encode(aarch64_enc_strh0(mem));
5683
5684 ins_pipe(istore_mem);
5685 %}
5686
5687 // Store Integer
5688
5689 instruct storeI(iRegIorL2I src, memory mem)
5690 %{
5691 match(Set mem(StoreI mem src));
5692 predicate(UseBarriersForVolatile || n->as_Store()->is_unordered());
5693
5694 ins_cost(INSN_COST);
5695 format %{ "strw $src, $mem\t# int" %}
5696
5697 ins_encode(aarch64_enc_strw(src, mem));
5698
5699 ins_pipe(istore_reg_mem);
5700 %}
5701
5702 instruct storeimmI0(immI0 zero, memory mem)
5703 %{
5704 match(Set mem(StoreI mem zero));
5705 predicate(UseBarriersForVolatile || n->as_Store()->is_unordered());
5706
5707 ins_cost(INSN_COST);
5708 format %{ "strw zr, $mem\t# int" %}
5709
5710 ins_encode(aarch64_enc_strw0(mem));
5711
5712 ins_pipe(istore_mem);
5713 %}
5714
5715 // Store Long (64 bit signed)
5716 instruct storeL(iRegL src, memory mem)
5717 %{
5718 match(Set mem (StoreL mem src));
5719 predicate(UseBarriersForVolatile || n->as_Store()->is_unordered());
5720
5721 ins_cost(INSN_COST);
5722 format %{ "str $src, $mem\t# int" %}
5723
5724 ins_encode(aarch64_enc_str(src, mem));
5725
5726 ins_pipe(istore_reg_mem);
5727 %}
5728
5729 // Store Long (64 bit signed)
5730 instruct storeimmL0(immL0 zero, memory mem)
5731 %{
5732 match(Set mem (StoreL mem zero));
5733 predicate(UseBarriersForVolatile || n->as_Store()->is_unordered());
5734
5735 ins_cost(INSN_COST);
5736 format %{ "str zr, $mem\t# int" %}
5737
5738 ins_encode(aarch64_enc_str0(mem));
5739
5740 ins_pipe(istore_mem);
5741 %}
5742
5743 // Store Pointer
5744 instruct storeP(iRegP src, memory mem)
5745 %{
5746 match(Set mem (StoreP mem src));
5747 predicate(UseBarriersForVolatile || n->as_Store()->is_unordered());
5748
5749 ins_cost(INSN_COST);
5750 format %{ "str $src, $mem\t# ptr" %}
5751
5752 ins_encode(aarch64_enc_str(src, mem));
5753
5754 ins_pipe(istore_reg_mem);
5755 %}
5756
5757 // Store Pointer
5758 instruct storeimmP0(immP0 zero, memory mem)
5759 %{
5760 match(Set mem (StoreP mem zero));
5761 predicate(UseBarriersForVolatile || n->as_Store()->is_unordered());
5762
5763 ins_cost(INSN_COST);
5764 format %{ "str zr, $mem\t# ptr" %}
5765
5766 ins_encode(aarch64_enc_str0(mem));
5767
5768 ins_pipe(istore_mem);
5769 %}
5770
5771 // Store Compressed Pointer
5772 instruct storeN(iRegN src, memory mem)
5773 %{
5774 match(Set mem (StoreN mem src));
5775 predicate(UseBarriersForVolatile || n->as_Store()->is_unordered());
5776
5777 ins_cost(INSN_COST);
5778 format %{ "strw $src, $mem\t# compressed ptr" %}
5779
5780 ins_encode(aarch64_enc_strw(src, mem));
5781
5782 ins_pipe(istore_reg_mem);
5783 %}
5784
5785 instruct storeImmN0(iRegIHeapbase heapbase, immN0 zero, memory mem)
5786 %{
5787 match(Set mem (StoreN mem zero));
5788 predicate(Universe::narrow_oop_base() == NULL &&
5789 Universe::narrow_klass_base() == NULL &&
5790 (UseBarriersForVolatile || n->as_Store()->is_unordered()));
5791
5792 ins_cost(INSN_COST);
5793 format %{ "strw rheapbase, $mem\t# compressed ptr (rheapbase==0)" %}
5794
5795 ins_encode(aarch64_enc_strw(heapbase, mem));
5796
5797 ins_pipe(istore_reg_mem);
5798 %}
5799
5800 // Store Float
5801 instruct storeF(vRegF src, memory mem)
5802 %{
5803 match(Set mem (StoreF mem src));
5804 predicate(UseBarriersForVolatile || n->as_Store()->is_unordered());
5805
5806 ins_cost(INSN_COST);
5807 format %{ "strs $src, $mem\t# float" %}
5808
5809 ins_encode( aarch64_enc_strs(src, mem) );
5810
5811 ins_pipe(pipe_class_memory);
5812 %}
5813
5814 // TODO
5815 // implement storeImmF0 and storeFImmPacked
5816
5817 // Store Double
5818 instruct storeD(vRegD src, memory mem)
5819 %{
5820 match(Set mem (StoreD mem src));
5821 predicate(UseBarriersForVolatile || n->as_Store()->is_unordered());
5822
5823 ins_cost(INSN_COST);
5824 format %{ "strd $src, $mem\t# double" %}
5825
5826 ins_encode( aarch64_enc_strd(src, mem) );
5827
5828 ins_pipe(pipe_class_memory);
5829 %}
5830
5831 // Store Compressed Klass Pointer
5832 instruct storeNKlass(iRegN src, memory mem)
5833 %{
5834 predicate(UseBarriersForVolatile || n->as_Store()->is_unordered());
5835 match(Set mem (StoreNKlass mem src));
5836
5837 ins_cost(INSN_COST);
5838 format %{ "strw $src, $mem\t# compressed klass ptr" %}
5839
5840 ins_encode(aarch64_enc_strw(src, mem));
5841
5842 ins_pipe(istore_reg_mem);
5843 %}
5844
5845 // TODO
5846 // implement storeImmD0 and storeDImmPacked
5847
5848 // prefetch instructions
5849 // Must be safe to execute with invalid address (cannot fault).
5850
5851 instruct prefetchalloc( memory mem ) %{
5852 match(PrefetchAllocation mem);
5853
5854 ins_cost(INSN_COST);
6276
6277 ins_pipe(ialu_reg);
6278 %}
6279
6280 // ============================================================================
6281 // MemBar Instruction
6282
6283 instruct load_fence() %{
6284 match(LoadFence);
6285 ins_cost(VOLATILE_REF_COST);
6286
6287 format %{ "load_fence" %}
6288
6289 ins_encode %{
6290 __ membar(Assembler::LoadLoad|Assembler::LoadStore);
6291 %}
6292 ins_pipe(pipe_serial);
6293 %}
6294
6295 instruct unnecessary_membar_acquire() %{
6296 predicate(! UseBarriersForVolatile && preceded_by_ordered_load(n));
6297 match(MemBarAcquire);
6298 ins_cost(0);
6299
6300 format %{ "membar_acquire (elided)" %}
6301
6302 ins_encode %{
6303 __ block_comment("membar_acquire (elided)");
6304 %}
6305
6306 ins_pipe(pipe_class_empty);
6307 %}
6308
6309 instruct membar_acquire() %{
6310 match(MemBarAcquire);
6311 ins_cost(VOLATILE_REF_COST);
6312
6313 format %{ "membar_acquire" %}
6314
6315 ins_encode %{
6316 __ membar(Assembler::LoadLoad|Assembler::LoadStore);
6328
6329 ins_encode %{
6330 __ membar(Assembler::LoadLoad|Assembler::LoadStore);
6331 %}
6332
6333 ins_pipe(pipe_serial);
6334 %}
6335
6336 instruct store_fence() %{
6337 match(StoreFence);
6338 ins_cost(VOLATILE_REF_COST);
6339
6340 format %{ "store_fence" %}
6341
6342 ins_encode %{
6343 __ membar(Assembler::LoadStore|Assembler::StoreStore);
6344 %}
6345 ins_pipe(pipe_serial);
6346 %}
6347
6348 instruct membar_release() %{
6349 match(MemBarRelease);
6350 ins_cost(VOLATILE_REF_COST);
6351
6352 format %{ "membar_release" %}
6353
6354 ins_encode %{
6355 __ membar(Assembler::LoadStore|Assembler::StoreStore);
6356 %}
6357 ins_pipe(pipe_serial);
6358 %}
6359
6360 instruct membar_storestore() %{
6361 match(MemBarStoreStore);
6362 ins_cost(VOLATILE_REF_COST);
6363
6364 format %{ "MEMBAR-store-store" %}
6365
6366 ins_encode %{
6367 __ membar(Assembler::StoreStore);
6368 %}
6369 ins_pipe(pipe_serial);
6370 %}
6371
6372 instruct membar_release_lock() %{
6373 match(MemBarReleaseLock);
6374 ins_cost(VOLATILE_REF_COST);
6375
6376 format %{ "membar_release_lock" %}
6377
6378 ins_encode %{
6379 __ membar(Assembler::LoadStore|Assembler::StoreStore);
6380 %}
6381
6382 ins_pipe(pipe_serial);
6383 %}
6384
6385 instruct membar_volatile() %{
6386 match(MemBarVolatile);
6387 ins_cost(VOLATILE_REF_COST*100);
6388
6389 format %{ "membar_volatile" %}
6390
6391 ins_encode %{
6392 __ membar(Assembler::StoreLoad);
6393 %}
6394
6395 ins_pipe(pipe_serial);
6396 %}
6397
6398 // ============================================================================
6399 // Cast/Convert Instructions
|
776 }
777 };
778
779 class HandlerImpl {
780
781 public:
782
783 static int emit_exception_handler(CodeBuffer &cbuf);
784 static int emit_deopt_handler(CodeBuffer& cbuf);
785
786 static uint size_exception_handler() {
787 return MacroAssembler::far_branch_size();
788 }
789
790 static uint size_deopt_handler() {
791 // count one adr and one far branch instruction
792 return 4 * NativeInstruction::instruction_size;
793 }
794 };
795
796 // graph traversal helpers
797 MemBarNode *has_parent_membar(const Node *n,
798 ProjNode *&ctl, ProjNode *&mem);
799 MemBarNode *has_child_membar(const MemBarNode *n,
800 ProjNode *&ctl, ProjNode *&mem);
801
802 // predicates controlling emit of ldr<x>/ldar<x> and associated dmb
803 bool unnecessary_acquire(const Node *barrier);
804 bool needs_acquiring_load(const Node *load);
805
806 // predicates controlling emit of str<x>/stlr<x> and associated dmbs
807 bool unnecessary_release(const Node *barrier);
808 bool unnecessary_volatile(const Node *barrier);
809 bool needs_releasing_store(const Node *store);
810
811 // Use barrier instructions rather than load acquire / store
812 // release.
813 const bool UseBarriersForVolatile = false;
814 // Use barrier instructions for unsafe volatile gets rather than
815 // trying to identify an exact signature for them
816 const bool UseBarriersForUnsafeVolatileGet = false;
817 %}
818
819 source %{
820
821 // AArch64 has ldar<x> and stlr<x> instructions which we can safely
822 // use to implement volatile reads and writes. For a volatile read
823 // we simply need
824 //
825 // ldar<x>
826 //
827 // and for a volatile write we need
828 //
829 // stlr<x>
830 //
831 // Alternatively, we can implement them by pairing a normal
832 // load/store with a memory barrier. For a volatile read we need
833 //
834 // ldr<x>
835 // dmb ishld
836 //
837 // for a volatile write
838 //
839 // dmb ish
840 // str<x>
841 // dmb ish
842 //
843 // In order to generate the desired instruction sequence we need to
844 // be able to identify specific 'signature' ideal graph node
845 // sequences which i) occur as a translation of a volatile reads or
846 // writes and ii) do not occur through any other translation or
847 // graph transformation. We can then provide alternative aldc
848 // matching rules which translate these node sequences to the
849 // desired machine code sequences. Selection of the alternative
850 // rules can be implemented by predicates which identify the
851 // relevant node sequences.
852 //
853 // The ideal graph generator translates a volatile read to the node
854 // sequence
855 //
856 // LoadX[mo_acquire]
857 // MemBarAcquire
858 //
859 // As a special case when using the compressed oops optimization we
860 // may also see this variant
861 //
862 // LoadN[mo_acquire]
863 // DecodeN
864 // MemBarAcquire
865 //
866 // A volatile write is translated to the node sequence
867 //
868 // MemBarRelease
869 // StoreX[mo_release]
870 // MemBarVolatile
871 //
872 // n.b. the above node patterns are generated with a strict
873 // 'signature' configuration of input and output dependencies (see
874 // the predicates below for exact details). The two signatures are
875 // unique to translated volatile reads/stores -- they will not
876 // appear as a result of any other bytecode translation or inlining
877 // nor as a consequence of optimizing transforms.
878 //
879 // We also want to catch inlined unsafe volatile gets and puts and
880 // be able to implement them using either ldar<x>/stlr<x> or some
881 // combination of ldr<x>/stlr<x> and dmb instructions.
882 //
883 // Inlined unsafe volatiles puts manifest as a minor variant of the
884 // normal volatile put node sequence containing an extra cpuorder
885 // membar
886 //
887 // MemBarRelease
888 // MemBarCPUOrder
889 // StoreX[mo_release]
890 // MemBarVolatile
891 //
892 // n.b. as an aside, the cpuorder membar is not itself subject to
893 // matching and translation by adlc rules. However, the rule
894 // predicates need to detect its presence in order to correctly
895 // select the desired adlc rules.
896 //
897 // Inlined unsafe volatiles gets manifest as a somewhat different
898 // node sequence to a normal volatile get
899 //
900 // MemBarCPUOrder
901 // || \\
902 // MemBarAcquire LoadX[mo_acquire]
903 // ||
904 // MemBarCPUOrder
905 //
906 // In this case the acquire membar does not directly depend on the
907 // load. However, we can be sure that the load is generated from an
908 // inlined unsafe volatile get if we see it dependent on this unique
909 // sequence of membar nodes. Similarly, given an acquire membar we
910 // can know that it was added because of an inlined unsafe volatile
911 // get if it is fed and feeds a cpuorder membar and if its feed
912 // membar also feeds an acquiring load.
913 //
914 // So, where we can identify these volatile read and write
915 // signatures we can choose to plant either of the above two code
916 // sequences. For a volatile read we can simply plant a normal
917 // ldr<x> and translate the MemBarAcquire to a dmb. However, we can
918 // also choose to inhibit translation of the MemBarAcquire and
919 // inhibit planting of the ldr<x>, instead planting an ldar<x>.
920 //
921 // When we recognise a volatile store signature we can choose to
922 // plant at a dmb ish as a translation for the MemBarRelease, a
923 // normal str<x> and then a dmb ish for the MemBarVolatile.
924 // Alternatively, we can inhibit translation of the MemBarRelease
925 // and MemBarVolatile and instead plant a simple stlr<x>
926 // instruction.
927 //
928 // Of course, the above only applies when we see these signature
929 // configurations. We still want to plant dmb instructions in any
930 // other cases where we may see a MemBarAcquire, MemBarRelease or
931 // MemBarVolatile. For example, at the end of a constructor which
932 // writes final/volatile fields we will see a MemBarRelease
933 // instruction and this needs a 'dmb ish' lest we risk the
934 // constructed object being visible without making the
935 // final/volatile field writes visible.
936 //
937 // n.b. the translation rules below which rely on detection of the
938 // volatile signatures and insert ldar<x> or stlr<x> are failsafe.
939 // If we see anything other than the signature configurations we
940 // always just translate the loads and stors to ldr<x> and str<x>
941 // and translate acquire, release and volatile membars to the
942 // relevant dmb instructions.
943 //
944 // n.b.b as a case in point for the above comment, the current
945 // predicates don't detect the precise signature for certain types
946 // of volatile object stores (where the heap_base input type is not
947 // known at compile-time to be non-NULL). In those cases the
948 // MemBarRelease and MemBarVolatile bracket an if-then-else sequence
949 // with a store in each branch (we need a different store depending
950 // on whether heap_base is actually NULL). In such a case we will
951 // just plant a dmb both before and after the branch/merge. The
952 // predicate could (and probably should) be fixed later to also
953 // detect this case.
954
955 // graph traversal helpers
956
957 // if node n is linked to a parent MemBarNode by an intervening
958 // Control or Memory ProjNode return the MemBarNode otherwise return
959 // NULL.
960 //
961 // n may only be a Load or a MemBar.
962 //
963 // The ProjNode* references c and m are used to return the relevant
964 // nodes.
965
966 MemBarNode *has_parent_membar(const Node *n, ProjNode *&c, ProjNode *&m)
967 {
968 Node *ctl = NULL;
969 Node *mem = NULL;
970 Node *membar = NULL;
971
972 if (n->is_Load()) {
973 ctl = n->lookup(LoadNode::Control);
974 mem = n->lookup(LoadNode::Memory);
975 } else if (n->is_MemBar()) {
976 ctl = n->lookup(TypeFunc::Control);
977 mem = n->lookup(TypeFunc::Memory);
978 } else {
979 return NULL;
980 }
981
982 if (!ctl || !mem || !ctl->is_Proj() || !mem->is_Proj())
983 return NULL;
984
985 c = ctl->as_Proj();
986
987 membar = ctl->lookup(0);
988
989 if (!membar || !membar->is_MemBar())
990 return NULL;
991
992 m = mem->as_Proj();
993
994 if (mem->lookup(0) != membar)
995 return NULL;
996
997 return membar->as_MemBar();
998 }
999
1000 // if n is linked to a child MemBarNode by intervening Control and
1001 // Memory ProjNodes return the MemBarNode otherwise return NULL.
1002 //
1003 // The ProjNode** arguments c and m are used to return pointers to
1004 // the relevant nodes. A null argument means don't don't return a
1005 // value.
1006
1007 MemBarNode *has_child_membar(const MemBarNode *n, ProjNode *&c, ProjNode *&m)
1008 {
1009 ProjNode *ctl = n->proj_out(TypeFunc::Control);
1010 ProjNode *mem = n->proj_out(TypeFunc::Memory);
1011
1012 // MemBar needs to have both a Ctl and Mem projection
1013 if (! ctl || ! mem)
1014 return NULL;
1015
1016 c = ctl;
1017 m = mem;
1018
1019 MemBarNode *child = NULL;
1020 Node *x;
1021
1022 for (DUIterator_Fast imax, i = ctl->fast_outs(imax); i < imax; i++) {
1023 x = ctl->fast_out(i);
1024 // if we see a membar we keep hold of it. we may also see a new
1025 // arena copy of the original but it will appear later
1026 if (x->is_MemBar()) {
1027 child = x->as_MemBar();
1028 break;
1029 }
1030 }
1031
1032 if (child == NULL)
1033 return NULL;
1034
1035 for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax; i++) {
1036 x = mem->fast_out(i);
1037 // if we see a membar we keep hold of it. we may also see a new
1038 // arena copy of the original but it will appear later
1039 if (x == child) {
1040 return child;
1041 }
1042 }
1043 return NULL;
1044 }
1045
1046 // predicates controlling emit of ldr<x>/ldar<x> and associated dmb
1047
1048 bool unnecessary_acquire(const Node *barrier) {
1049 // assert barrier->is_MemBar();
1050 if (UseBarriersForVolatile)
1051 // we need to plant a dmb
1052 return false;
1053
1054 // a volatile read derived from bytecode (or also from an inlined
1055 // SHA field read via LibraryCallKit::load_field_from_object)
1056 // manifests as a LoadX[mo_acquire] followed by an acquire membar
1057 // with a bogus read dependency on it's preceding load. so in those
1058 // cases we will find the load node at the PARMS offset of the
1059 // acquire membar. n.b. there may be an intervening DecodeN node.
1060 //
1061 // a volatile load derived from an inlined unsafe field access
1062 // manifests as a cpuorder membar with Ctl and Mem projections
1063 // feeding both an acquire membar and a LoadX[mo_acquire]. The
1064 // acquire then feeds another cpuorder membar via Ctl and Mem
1065 // projections. The load has no output dependency on these trailing
1066 // membars because subsequent nodes inserted into the graph take
1067 // their control feed from the final membar cpuorder meaning they
1068 // are all ordered after the load.
1069
1070 Node *x = barrier->lookup(TypeFunc::Parms);
1071 if (x) {
1072 // we are starting from an acquire and it has a fake dependency
1073 //
1074 // need to check for
1075 //
1076 // LoadX[mo_acquire]
1077 // { |1 }
1078 // {DecodeN}
1079 // |Parms
1080 // MemBarAcquire*
1081 //
1082 // where * tags node we were passed
1083 // and |k means input k
1084 if (x->is_DecodeNarrowPtr())
1085 x = x->in(1);
1086
1087 return (x->is_Load() && x->as_Load()->is_acquire());
1088 }
1089
1090 // only continue if we want to try to match unsafe volatile gets
1091 if (UseBarriersForUnsafeVolatileGet)
1092 return false;
1093
1094 // need to check for
1095 //
1096 // MemBarCPUOrder
1097 // || \\
1098 // MemBarAcquire* LoadX[mo_acquire]
1099 // ||
1100 // MemBarCPUOrder
1101 //
1102 // where * tags node we were passed
1103 // and || or \\ are Ctl+Mem feeds via intermediate Proj Nodes
1104
1105 // check for a parent MemBarCPUOrder
1106 ProjNode *ctl;
1107 ProjNode *mem;
1108 MemBarNode *parent = has_parent_membar(barrier, ctl, mem);
1109 if (!parent || parent->Opcode() != Op_MemBarCPUOrder)
1110 return false;
1111 // ensure the proj nodes both feed a LoadX[mo_acquire]
1112 LoadNode *ld = NULL;
1113 for (DUIterator_Fast imax, i = ctl->fast_outs(imax); i < imax; i++) {
1114 x = ctl->fast_out(i);
1115 // if we see a load we keep hold of it and stop searching
1116 if (x->is_Load()) {
1117 ld = x->as_Load();
1118 break;
1119 }
1120 }
1121 // it must be an acquiring load
1122 if (! ld || ! ld->is_acquire())
1123 return false;
1124 for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax; i++) {
1125 x = mem->fast_out(i);
1126 // if we see the same load we drop it and stop searching
1127 if (x == ld) {
1128 ld = NULL;
1129 break;
1130 }
1131 }
1132 // we must have dropped the load
1133 if (ld)
1134 return false;
1135 // check for a child cpuorder membar
1136 MemBarNode *child = has_child_membar(barrier->as_MemBar(), ctl, mem);
1137 if (!child || child->Opcode() != Op_MemBarCPUOrder)
1138 return false;
1139
1140 return true;
1141 }
1142
1143 bool needs_acquiring_load(const Node *n)
1144 {
1145 // assert n->is_Load();
1146 if (UseBarriersForVolatile)
1147 // we use a normal load and a dmb
1148 return false;
1149
1150 LoadNode *ld = n->as_Load();
1151
1152 if (!ld->is_acquire())
1153 return false;
1154
1155 // check if this load is feeding an acquire membar
1156 //
1157 // LoadX[mo_acquire]
1158 // { |1 }
1159 // {DecodeN}
1160 // |Parms
1161 // MemBarAcquire*
1162 //
1163 // where * tags node we were passed
1164 // and |k means input k
1165
1166 Node *start = ld;
1167 Node *mbacq = NULL;
1168
1169 // if we hit a DecodeNarrowPtr we reset the start node and restart
1170 // the search through the outputs
1171 restart:
1172
1173 for (DUIterator_Fast imax, i = start->fast_outs(imax); i < imax; i++) {
1174 Node *x = start->fast_out(i);
1175 if (x->is_MemBar() && x->Opcode() == Op_MemBarAcquire) {
1176 mbacq = x;
1177 } else if (!mbacq &&
1178 (x->is_DecodeNarrowPtr() ||
1179 (x->is_Mach() && x->Opcode() == Op_DecodeN))) {
1180 start = x;
1181 goto restart;
1182 }
1183 }
1184
1185 if (mbacq) {
1186 return true;
1187 }
1188
1189 // only continue if we want to try to match unsafe volatile gets
1190 if (UseBarriersForUnsafeVolatileGet)
1191 return false;
1192
1193 // check if Ctl and Proj feed comes from a MemBarCPUOrder
1194 //
1195 // MemBarCPUOrder
1196 // || \\
1197 // MemBarAcquire* LoadX[mo_acquire]
1198 // ||
1199 // MemBarCPUOrder
1200
1201 MemBarNode *membar;
1202 ProjNode *ctl;
1203 ProjNode *mem;
1204
1205 membar = has_parent_membar(ld, ctl, mem);
1206
1207 if (!membar || !membar->Opcode() == Op_MemBarCPUOrder)
1208 return false;
1209
1210 // ensure that there is a CPUOrder->Acquire->CPUOrder membar chain
1211
1212 membar = has_child_membar(membar, ctl, mem);
1213
1214 if (!membar || !membar->Opcode() == Op_MemBarAcquire)
1215 return false;
1216
1217 membar = has_child_membar(membar, ctl, mem);
1218
1219 if (!membar || !membar->Opcode() == Op_MemBarCPUOrder)
1220 return false;
1221
1222 return true;
1223 }
1224
1225 bool unnecessary_release(const Node *n) {
1226 // assert n->is_MemBar();
1227 if (UseBarriersForVolatile)
1228 // we need to plant a dmb
1229 return false;
1230
1231 // ok, so we can omit this release barrier if it has been inserted
1232 // as part of a volatile store sequence
1233 //
1234 // MemBarRelease
1235 // { || }
1236 // {MemBarCPUOrder} -- optional
1237 // || \\
1238 // || StoreX[mo_release]
1239 // | \ /
1240 // | MergeMem
1241 // | /
1242 // MemBarVolatile
1243 //
1244 // where
1245 // || and \\ represent Ctl and Mem feeds via Proj nodes
1246 // | \ and / indicate further routing of the Ctl and Mem feeds
1247 //
1248 // so we need to check that
1249 //
1250 // ia) the release membar (or its dependent cpuorder membar) feeds
1251 // control to a store node (via a Control project node)
1252 //
1253 // ii) the store is ordered release
1254 //
1255 // iii) the release membar (or its dependent cpuorder membar) feeds
1256 // control to a volatile membar (via the same Control project node)
1257 //
1258 // iv) the release membar feeds memory to a merge mem and to the
1259 // same store (both via a single Memory proj node)
1260 //
1261 // v) the store outputs to the merge mem
1262 //
1263 // vi) the merge mem outputs to the same volatile membar
1264 //
1265 // n.b. if this is an inlined unsafe node then the release membar
1266 // may feed its control and memory links via an intervening cpuorder
1267 // membar. this case can be dealt with when we check the release
1268 // membar projections. if they both feed a single cpuorder membar
1269 // node continue to make the same checks as above but with the
1270 // cpuorder membar substituted for the release membar. if they don't
1271 // both feed a cpuorder membar then the check fails.
1272 //
1273 // n.b.b. for an inlined unsafe store of an object in the case where
1274 // !TypePtr::NULL_PTR->higher_equal(type(heap_base_oop)) we may see
1275 // an embedded if then else where we expect the store. this is
1276 // needed to do the right type of store depending on whether
1277 // heap_base is NULL. We could check for that but for now we can
1278 // just take the hit of on inserting a redundant dmb for this
1279 // redundant volatile membar
1280
1281 MemBarNode *barrier = n->as_MemBar();
1282 ProjNode *ctl;
1283 ProjNode *mem;
1284 // check for an intervening cpuorder membar
1285 MemBarNode *b = has_child_membar(barrier, ctl, mem);
1286 if (b && b->Opcode() == Op_MemBarCPUOrder) {
1287 // ok, so start form the dependent cpuorder barrier
1288 barrier = b;
1289 }
1290 // check the ctl and mem flow
1291 ctl = barrier->proj_out(TypeFunc::Control);
1292 mem = barrier->proj_out(TypeFunc::Memory);
1293
1294 // the barrier needs to have both a Ctl and Mem projection
1295 if (! ctl || ! mem)
1296 return false;
1297
1298 Node *x = NULL;
1299 Node *mbvol = NULL;
1300 StoreNode * st = NULL;
1301
1302 // For a normal volatile write the Ctl ProjNode should have output
1303 // to a MemBarVolatile and a Store marked as releasing
1304 //
1305 // n.b. for an inlined unsafe store of an object in the case where
1306 // !TypePtr::NULL_PTR->higher_equal(type(heap_base_oop)) we may see
1307 // an embedded if then else where we expect the store. this is
1308 // needed to do the right type of store depending on whether
1309 // heap_base is NULL. We could check for that case too but for now
1310 // we can just take the hit of inserting a dmb and a non-volatile
1311 // store to implement the volatile store
1312
1313 for (DUIterator_Fast imax, i = ctl->fast_outs(imax); i < imax; i++) {
1314 x = ctl->fast_out(i);
1315 if (x->is_MemBar() && x->Opcode() == Op_MemBarVolatile) {
1316 if (mbvol) {
1317 return false;
1318 }
1319 mbvol = x;
1320 } else if (x->is_Store()) {
1321 st = x->as_Store();
1322 if (! st->is_release()) {
1323 return false;
1324 }
1325 } else if (!x->is_Mach()) {
1326 // we may see mach nodes added during matching but nothing else
1327 return false;
1328 }
1329 }
1330
1331 if (!mbvol || !st)
1332 return false;
1333
1334 // the Mem ProjNode should output to a MergeMem and the same Store
1335 Node *mm = NULL;
1336 for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax; i++) {
1337 x = mem->fast_out(i);
1338 if (!mm && x->is_MergeMem()) {
1339 mm = x;
1340 } else if (x != st && !x->is_Mach()) {
1341 // we may see mach nodes added during matching but nothing else
1342 return false;
1343 }
1344 }
1345
1346 if (!mm)
1347 return false;
1348
1349 // the MergeMem should output to the MemBarVolatile
1350 for (DUIterator_Fast imax, i = mm->fast_outs(imax); i < imax; i++) {
1351 x = mm->fast_out(i);
1352 if (x != mbvol && !x->is_Mach()) {
1353 // we may see mach nodes added during matching but nothing else
1354 return false;
1355 }
1356 }
1357
1358 return true;
1359 }
1360
1361 bool unnecessary_volatile(const Node *n) {
1362 // assert n->is_MemBar();
1363 if (UseBarriersForVolatile)
1364 // we need to plant a dmb
1365 return false;
1366
1367 // ok, so we can omit this volatile barrier if it has been inserted
1368 // as part of a volatile store sequence
1369 //
1370 // MemBarRelease
1371 // { || }
1372 // {MemBarCPUOrder} -- optional
1373 // || \\
1374 // || StoreX[mo_release]
1375 // | \ /
1376 // | MergeMem
1377 // | /
1378 // MemBarVolatile
1379 //
1380 // where
1381 // || and \\ represent Ctl and Mem feeds via Proj nodes
1382 // | \ and / indicate further routing of the Ctl and Mem feeds
1383 //
1384 // we need to check that
1385 //
1386 // i) the volatile membar gets its control feed from a release
1387 // membar (or its dependent cpuorder membar) via a Control project
1388 // node
1389 //
1390 // ii) the release membar (or its dependent cpuorder membar) also
1391 // feeds control to a store node via the same proj node
1392 //
1393 // iii) the store is ordered release
1394 //
1395 // iv) the release membar (or its dependent cpuorder membar) feeds
1396 // memory to a merge mem and to the same store (both via a single
1397 // Memory proj node)
1398 //
1399 // v) the store outputs to the merge mem
1400 //
1401 // vi) the merge mem outputs to the volatile membar
1402 //
1403 // n.b. for an inlined unsafe store of an object in the case where
1404 // !TypePtr::NULL_PTR->higher_equal(type(heap_base_oop)) we may see
1405 // an embedded if then else where we expect the store. this is
1406 // needed to do the right type of store depending on whether
1407 // heap_base is NULL. We could check for that but for now we can
1408 // just take the hit of on inserting a redundant dmb for this
1409 // redundant volatile membar
1410
1411 MemBarNode *mbvol = n->as_MemBar();
1412 Node *x = n->lookup(TypeFunc::Control);
1413
1414 if (! x || !x->is_Proj())
1415 return false;
1416
1417 ProjNode *proj = x->as_Proj();
1418
1419 x = proj->lookup(0);
1420
1421 if (!x || !x->is_MemBar())
1422 return false;
1423
1424 MemBarNode *barrier = x->as_MemBar();
1425
1426 // if the barrier is a release membar we have what we want. if it is
1427 // a cpuorder membar then we need to ensure that it is fed by a
1428 // release membar in which case we proceed to check the graph below
1429 // this cpuorder membar as the feed
1430
1431 if (x->Opcode() != Op_MemBarRelease) {
1432 if (x->Opcode() != Op_MemBarCPUOrder)
1433 return false;
1434 ProjNode *ctl;
1435 ProjNode *mem;
1436 MemBarNode *b = has_parent_membar(x, ctl, mem);
1437 if (!b || !b->Opcode() == Op_MemBarRelease)
1438 return false;
1439 }
1440
1441 ProjNode *ctl = barrier->proj_out(TypeFunc::Control);
1442 ProjNode *mem = barrier->proj_out(TypeFunc::Memory);
1443
1444 // barrier needs to have both a Ctl and Mem projection
1445 // and we need to have reached it via the Ctl projection
1446 if (! ctl || ! mem || ctl != proj)
1447 return false;
1448
1449 StoreNode * st = NULL;
1450
1451 // The Ctl ProjNode should have output to a MemBarVolatile and
1452 // a Store marked as releasing
1453 for (DUIterator_Fast imax, i = ctl->fast_outs(imax); i < imax; i++) {
1454 x = ctl->fast_out(i);
1455 if (x->is_MemBar() && x->Opcode() == Op_MemBarVolatile) {
1456 if (x != mbvol) {
1457 return false;
1458 }
1459 } else if (x->is_Store()) {
1460 st = x->as_Store();
1461 if (! st->is_release()) {
1462 return false;
1463 }
1464 } else if (!x->is_Mach()){
1465 // we may see mach nodes added during matching but nothing else
1466 return false;
1467 }
1468 }
1469
1470 if (!st)
1471 return false;
1472
1473 // the Mem ProjNode should output to a MergeMem and the same Store
1474 Node *mm = NULL;
1475 for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax; i++) {
1476 x = mem->fast_out(i);
1477 if (!mm && x->is_MergeMem()) {
1478 mm = x;
1479 } else if (x != st && !x->is_Mach()) {
1480 // we may see mach nodes added during matching but nothing else
1481 return false;
1482 }
1483 }
1484
1485 if (!mm)
1486 return false;
1487
1488 // the MergeMem should output to the MemBarVolatile
1489 for (DUIterator_Fast imax, i = mm->fast_outs(imax); i < imax; i++) {
1490 x = mm->fast_out(i);
1491 if (x != mbvol && !x->is_Mach()) {
1492 // we may see mach nodes added during matching but nothing else
1493 return false;
1494 }
1495 }
1496
1497 return true;
1498 }
1499
1500
1501
1502 bool needs_releasing_store(const Node *n)
1503 {
1504 // assert n->is_Store();
1505 if (UseBarriersForVolatile)
1506 // we use a normal store and dmb combination
1507 return false;
1508
1509 StoreNode *st = n->as_Store();
1510
1511 if (!st->is_release())
1512 return false;
1513
1514 // check if this store is bracketed by a release (or its dependent
1515 // cpuorder membar) and a volatile membar
1516 //
1517 // MemBarRelease
1518 // { || }
1519 // {MemBarCPUOrder} -- optional
1520 // || \\
1521 // || StoreX[mo_release]
1522 // | \ /
1523 // | MergeMem
1524 // | /
1525 // MemBarVolatile
1526 //
1527 // where
1528 // || and \\ represent Ctl and Mem feeds via Proj nodes
1529 // | \ and / indicate further routing of the Ctl and Mem feeds
1530 //
1531
1532
1533 Node *x = st->lookup(TypeFunc::Control);
1534
1535 if (! x || !x->is_Proj())
1536 return false;
1537
1538 ProjNode *proj = x->as_Proj();
1539
1540 x = proj->lookup(0);
1541
1542 if (!x || !x->is_MemBar())
1543 return false;
1544
1545 MemBarNode *barrier = x->as_MemBar();
1546
1547 // if the barrier is a release membar we have what we want. if it is
1548 // a cpuorder membar then we need to ensure that it is fed by a
1549 // release membar in which case we proceed to check the graph below
1550 // this cpuorder membar as the feed
1551
1552 if (x->Opcode() != Op_MemBarRelease) {
1553 if (x->Opcode() != Op_MemBarCPUOrder)
1554 return false;
1555 Node *ctl = x->lookup(TypeFunc::Control);
1556 Node *mem = x->lookup(TypeFunc::Memory);
1557 if (!ctl || !ctl->is_Proj() || !mem || !mem->is_Proj())
1558 return false;
1559 x = ctl->lookup(0);
1560 if (!x || !x->is_MemBar() || !x->Opcode() == Op_MemBarRelease)
1561 return false;
1562 Node *y = mem->lookup(0);
1563 if (!y || y != x)
1564 return false;
1565 }
1566
1567 ProjNode *ctl = barrier->proj_out(TypeFunc::Control);
1568 ProjNode *mem = barrier->proj_out(TypeFunc::Memory);
1569
1570 // MemBarRelease needs to have both a Ctl and Mem projection
1571 // and we need to have reached it via the Ctl projection
1572 if (! ctl || ! mem || ctl != proj)
1573 return false;
1574
1575 MemBarNode *mbvol = NULL;
1576
1577 // The Ctl ProjNode should have output to a MemBarVolatile and
1578 // a Store marked as releasing
1579 for (DUIterator_Fast imax, i = ctl->fast_outs(imax); i < imax; i++) {
1580 x = ctl->fast_out(i);
1581 if (x->is_MemBar() && x->Opcode() == Op_MemBarVolatile) {
1582 mbvol = x->as_MemBar();
1583 } else if (x->is_Store()) {
1584 if (x != st) {
1585 return false;
1586 }
1587 } else if (!x->is_Mach()){
1588 return false;
1589 }
1590 }
1591
1592 if (!mbvol)
1593 return false;
1594
1595 // the Mem ProjNode should output to a MergeMem and the same Store
1596 Node *mm = NULL;
1597 for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax; i++) {
1598 x = mem->fast_out(i);
1599 if (!mm && x->is_MergeMem()) {
1600 mm = x;
1601 } else if (x != st && !x->is_Mach()) {
1602 return false;
1603 }
1604 }
1605
1606 if (!mm)
1607 return false;
1608
1609 // the MergeMem should output to the MemBarVolatile
1610 for (DUIterator_Fast imax, i = mm->fast_outs(imax); i < imax; i++) {
1611 x = mm->fast_out(i);
1612 if (x != mbvol && !x->is_Mach()) {
1613 return false;
1614 }
1615 }
1616
1617 return true;
1618 }
1619
1620
1621
1622 #define __ _masm.
1623
1624 // advance declarations for helper functions to convert register
1625 // indices to register objects
1626
1627 // the ad file has to provide implementations of certain methods
1628 // expected by the generic code
1629 //
1630 // REQUIRED FUNCTIONALITY
1631
1632 //=============================================================================
1633
1634 // !!!!! Special hack to get all types of calls to specify the byte offset
1635 // from the start of the call to the point where the return address
1636 // will point.
1637
1638 int MachCallStaticJavaNode::ret_addr_offset()
1639 {
1640 // call should be a simple bl
1641 // unless this is a method handle invoke in which case it is
5928 // by referring to it with a '$' prefix.
5929 // opcode -- Three instruction opcodes may be provided. These are referred
5930 // to within an encode class as $primary, $secondary, and $tertiary
5931 // rrspectively. The primary opcode is commonly used to
5932 // indicate the type of machine instruction, while secondary
5933 // and tertiary are often used for prefix options or addressing
5934 // modes.
5935 // ins_encode -- A list of encode classes with parameters. The encode class
5936 // name must have been defined in an 'enc_class' specification
5937 // in the encode section of the architecture description.
5938
5939 // ============================================================================
5940 // Memory (Load/Store) Instructions
5941
5942 // Load Instructions
5943
5944 // Load Byte (8 bit signed)
5945 instruct loadB(iRegINoSp dst, memory mem)
5946 %{
5947 match(Set dst (LoadB mem));
5948 predicate(!needs_acquiring_load(n));
5949
5950 ins_cost(4 * INSN_COST);
5951 format %{ "ldrsbw $dst, $mem\t# byte" %}
5952
5953 ins_encode(aarch64_enc_ldrsbw(dst, mem));
5954
5955 ins_pipe(iload_reg_mem);
5956 %}
5957
5958 // Load Byte (8 bit signed) into long
5959 instruct loadB2L(iRegLNoSp dst, memory mem)
5960 %{
5961 match(Set dst (ConvI2L (LoadB mem)));
5962 predicate(!needs_acquiring_load(n->in(1)));
5963
5964 ins_cost(4 * INSN_COST);
5965 format %{ "ldrsb $dst, $mem\t# byte" %}
5966
5967 ins_encode(aarch64_enc_ldrsb(dst, mem));
5968
5969 ins_pipe(iload_reg_mem);
5970 %}
5971
5972 // Load Byte (8 bit unsigned)
5973 instruct loadUB(iRegINoSp dst, memory mem)
5974 %{
5975 match(Set dst (LoadUB mem));
5976 predicate(!needs_acquiring_load(n));
5977
5978 ins_cost(4 * INSN_COST);
5979 format %{ "ldrbw $dst, $mem\t# byte" %}
5980
5981 ins_encode(aarch64_enc_ldrb(dst, mem));
5982
5983 ins_pipe(iload_reg_mem);
5984 %}
5985
5986 // Load Byte (8 bit unsigned) into long
5987 instruct loadUB2L(iRegLNoSp dst, memory mem)
5988 %{
5989 match(Set dst (ConvI2L (LoadUB mem)));
5990 predicate(!needs_acquiring_load(n->in(1)));
5991
5992 ins_cost(4 * INSN_COST);
5993 format %{ "ldrb $dst, $mem\t# byte" %}
5994
5995 ins_encode(aarch64_enc_ldrb(dst, mem));
5996
5997 ins_pipe(iload_reg_mem);
5998 %}
5999
6000 // Load Short (16 bit signed)
6001 instruct loadS(iRegINoSp dst, memory mem)
6002 %{
6003 match(Set dst (LoadS mem));
6004 predicate(!needs_acquiring_load(n));
6005
6006 ins_cost(4 * INSN_COST);
6007 format %{ "ldrshw $dst, $mem\t# short" %}
6008
6009 ins_encode(aarch64_enc_ldrshw(dst, mem));
6010
6011 ins_pipe(iload_reg_mem);
6012 %}
6013
6014 // Load Short (16 bit signed) into long
6015 instruct loadS2L(iRegLNoSp dst, memory mem)
6016 %{
6017 match(Set dst (ConvI2L (LoadS mem)));
6018 predicate(!needs_acquiring_load(n->in(1)));
6019
6020 ins_cost(4 * INSN_COST);
6021 format %{ "ldrsh $dst, $mem\t# short" %}
6022
6023 ins_encode(aarch64_enc_ldrsh(dst, mem));
6024
6025 ins_pipe(iload_reg_mem);
6026 %}
6027
6028 // Load Char (16 bit unsigned)
6029 instruct loadUS(iRegINoSp dst, memory mem)
6030 %{
6031 match(Set dst (LoadUS mem));
6032 predicate(!needs_acquiring_load(n));
6033
6034 ins_cost(4 * INSN_COST);
6035 format %{ "ldrh $dst, $mem\t# short" %}
6036
6037 ins_encode(aarch64_enc_ldrh(dst, mem));
6038
6039 ins_pipe(iload_reg_mem);
6040 %}
6041
6042 // Load Short/Char (16 bit unsigned) into long
6043 instruct loadUS2L(iRegLNoSp dst, memory mem)
6044 %{
6045 match(Set dst (ConvI2L (LoadUS mem)));
6046 predicate(!needs_acquiring_load(n->in(1)));
6047
6048 ins_cost(4 * INSN_COST);
6049 format %{ "ldrh $dst, $mem\t# short" %}
6050
6051 ins_encode(aarch64_enc_ldrh(dst, mem));
6052
6053 ins_pipe(iload_reg_mem);
6054 %}
6055
6056 // Load Integer (32 bit signed)
6057 instruct loadI(iRegINoSp dst, memory mem)
6058 %{
6059 match(Set dst (LoadI mem));
6060 predicate(!needs_acquiring_load(n));
6061
6062 ins_cost(4 * INSN_COST);
6063 format %{ "ldrw $dst, $mem\t# int" %}
6064
6065 ins_encode(aarch64_enc_ldrw(dst, mem));
6066
6067 ins_pipe(iload_reg_mem);
6068 %}
6069
6070 // Load Integer (32 bit signed) into long
6071 instruct loadI2L(iRegLNoSp dst, memory mem)
6072 %{
6073 match(Set dst (ConvI2L (LoadI mem)));
6074 predicate(!needs_acquiring_load(n->in(1)));
6075
6076 ins_cost(4 * INSN_COST);
6077 format %{ "ldrsw $dst, $mem\t# int" %}
6078
6079 ins_encode(aarch64_enc_ldrsw(dst, mem));
6080
6081 ins_pipe(iload_reg_mem);
6082 %}
6083
6084 // Load Integer (32 bit unsigned) into long
6085 instruct loadUI2L(iRegLNoSp dst, memory mem, immL_32bits mask)
6086 %{
6087 match(Set dst (AndL (ConvI2L (LoadI mem)) mask));
6088 predicate(!needs_acquiring_load(n->in(1)->in(1)->as_Load()));
6089
6090 ins_cost(4 * INSN_COST);
6091 format %{ "ldrw $dst, $mem\t# int" %}
6092
6093 ins_encode(aarch64_enc_ldrw(dst, mem));
6094
6095 ins_pipe(iload_reg_mem);
6096 %}
6097
6098 // Load Long (64 bit signed)
6099 instruct loadL(iRegLNoSp dst, memory mem)
6100 %{
6101 match(Set dst (LoadL mem));
6102 predicate(!needs_acquiring_load(n));
6103
6104 ins_cost(4 * INSN_COST);
6105 format %{ "ldr $dst, $mem\t# int" %}
6106
6107 ins_encode(aarch64_enc_ldr(dst, mem));
6108
6109 ins_pipe(iload_reg_mem);
6110 %}
6111
6112 // Load Range
6113 instruct loadRange(iRegINoSp dst, memory mem)
6114 %{
6115 match(Set dst (LoadRange mem));
6116
6117 ins_cost(4 * INSN_COST);
6118 format %{ "ldrw $dst, $mem\t# range" %}
6119
6120 ins_encode(aarch64_enc_ldrw(dst, mem));
6121
6122 ins_pipe(iload_reg_mem);
6123 %}
6124
6125 // Load Pointer
6126 instruct loadP(iRegPNoSp dst, memory mem)
6127 %{
6128 match(Set dst (LoadP mem));
6129 predicate(!needs_acquiring_load(n));
6130
6131 ins_cost(4 * INSN_COST);
6132 format %{ "ldr $dst, $mem\t# ptr" %}
6133
6134 ins_encode(aarch64_enc_ldr(dst, mem));
6135
6136 ins_pipe(iload_reg_mem);
6137 %}
6138
6139 // Load Compressed Pointer
6140 instruct loadN(iRegNNoSp dst, memory mem)
6141 %{
6142 match(Set dst (LoadN mem));
6143 predicate(!needs_acquiring_load(n));
6144
6145 ins_cost(4 * INSN_COST);
6146 format %{ "ldrw $dst, $mem\t# compressed ptr" %}
6147
6148 ins_encode(aarch64_enc_ldrw(dst, mem));
6149
6150 ins_pipe(iload_reg_mem);
6151 %}
6152
6153 // Load Klass Pointer
6154 instruct loadKlass(iRegPNoSp dst, memory mem)
6155 %{
6156 match(Set dst (LoadKlass mem));
6157 predicate(!needs_acquiring_load(n));
6158
6159 ins_cost(4 * INSN_COST);
6160 format %{ "ldr $dst, $mem\t# class" %}
6161
6162 ins_encode(aarch64_enc_ldr(dst, mem));
6163
6164 ins_pipe(iload_reg_mem);
6165 %}
6166
6167 // Load Narrow Klass Pointer
6168 instruct loadNKlass(iRegNNoSp dst, memory mem)
6169 %{
6170 match(Set dst (LoadNKlass mem));
6171 predicate(!needs_acquiring_load(n));
6172
6173 ins_cost(4 * INSN_COST);
6174 format %{ "ldrw $dst, $mem\t# compressed class ptr" %}
6175
6176 ins_encode(aarch64_enc_ldrw(dst, mem));
6177
6178 ins_pipe(iload_reg_mem);
6179 %}
6180
6181 // Load Float
6182 instruct loadF(vRegF dst, memory mem)
6183 %{
6184 match(Set dst (LoadF mem));
6185 predicate(!needs_acquiring_load(n));
6186
6187 ins_cost(4 * INSN_COST);
6188 format %{ "ldrs $dst, $mem\t# float" %}
6189
6190 ins_encode( aarch64_enc_ldrs(dst, mem) );
6191
6192 ins_pipe(pipe_class_memory);
6193 %}
6194
6195 // Load Double
6196 instruct loadD(vRegD dst, memory mem)
6197 %{
6198 match(Set dst (LoadD mem));
6199 predicate(!needs_acquiring_load(n));
6200
6201 ins_cost(4 * INSN_COST);
6202 format %{ "ldrd $dst, $mem\t# double" %}
6203
6204 ins_encode( aarch64_enc_ldrd(dst, mem) );
6205
6206 ins_pipe(pipe_class_memory);
6207 %}
6208
6209
6210 // Load Int Constant
6211 instruct loadConI(iRegINoSp dst, immI src)
6212 %{
6213 match(Set dst src);
6214
6215 ins_cost(INSN_COST);
6216 format %{ "mov $dst, $src\t# int" %}
6217
6218 ins_encode( aarch64_enc_movw_imm(dst, src) );
6219
6410
6411 // Store Instructions
6412
6413 // Store CMS card-mark Immediate
6414 instruct storeimmCM0(immI0 zero, memory mem)
6415 %{
6416 match(Set mem (StoreCM mem zero));
6417
6418 ins_cost(INSN_COST);
6419 format %{ "strb zr, $mem\t# byte" %}
6420
6421 ins_encode(aarch64_enc_strb0(mem));
6422
6423 ins_pipe(istore_mem);
6424 %}
6425
6426 // Store Byte
6427 instruct storeB(iRegIorL2I src, memory mem)
6428 %{
6429 match(Set mem (StoreB mem src));
6430 predicate(!needs_releasing_store(n));
6431
6432 ins_cost(INSN_COST);
6433 format %{ "strb $src, $mem\t# byte" %}
6434
6435 ins_encode(aarch64_enc_strb(src, mem));
6436
6437 ins_pipe(istore_reg_mem);
6438 %}
6439
6440
6441 instruct storeimmB0(immI0 zero, memory mem)
6442 %{
6443 match(Set mem (StoreB mem zero));
6444 predicate(!needs_releasing_store(n));
6445
6446 ins_cost(INSN_COST);
6447 format %{ "strb zr, $mem\t# byte" %}
6448
6449 ins_encode(aarch64_enc_strb0(mem));
6450
6451 ins_pipe(istore_mem);
6452 %}
6453
6454 // Store Char/Short
6455 instruct storeC(iRegIorL2I src, memory mem)
6456 %{
6457 match(Set mem (StoreC mem src));
6458 predicate(!needs_releasing_store(n));
6459
6460 ins_cost(INSN_COST);
6461 format %{ "strh $src, $mem\t# short" %}
6462
6463 ins_encode(aarch64_enc_strh(src, mem));
6464
6465 ins_pipe(istore_reg_mem);
6466 %}
6467
6468 instruct storeimmC0(immI0 zero, memory mem)
6469 %{
6470 match(Set mem (StoreC mem zero));
6471 predicate(!needs_releasing_store(n));
6472
6473 ins_cost(INSN_COST);
6474 format %{ "strh zr, $mem\t# short" %}
6475
6476 ins_encode(aarch64_enc_strh0(mem));
6477
6478 ins_pipe(istore_mem);
6479 %}
6480
6481 // Store Integer
6482
6483 instruct storeI(iRegIorL2I src, memory mem)
6484 %{
6485 match(Set mem(StoreI mem src));
6486 predicate(!needs_releasing_store(n));
6487
6488 ins_cost(INSN_COST);
6489 format %{ "strw $src, $mem\t# int" %}
6490
6491 ins_encode(aarch64_enc_strw(src, mem));
6492
6493 ins_pipe(istore_reg_mem);
6494 %}
6495
6496 instruct storeimmI0(immI0 zero, memory mem)
6497 %{
6498 match(Set mem(StoreI mem zero));
6499 predicate(!needs_releasing_store(n));
6500
6501 ins_cost(INSN_COST);
6502 format %{ "strw zr, $mem\t# int" %}
6503
6504 ins_encode(aarch64_enc_strw0(mem));
6505
6506 ins_pipe(istore_mem);
6507 %}
6508
6509 // Store Long (64 bit signed)
6510 instruct storeL(iRegL src, memory mem)
6511 %{
6512 match(Set mem (StoreL mem src));
6513 predicate(!needs_releasing_store(n));
6514
6515 ins_cost(INSN_COST);
6516 format %{ "str $src, $mem\t# int" %}
6517
6518 ins_encode(aarch64_enc_str(src, mem));
6519
6520 ins_pipe(istore_reg_mem);
6521 %}
6522
6523 // Store Long (64 bit signed)
6524 instruct storeimmL0(immL0 zero, memory mem)
6525 %{
6526 match(Set mem (StoreL mem zero));
6527 predicate(!needs_releasing_store(n));
6528
6529 ins_cost(INSN_COST);
6530 format %{ "str zr, $mem\t# int" %}
6531
6532 ins_encode(aarch64_enc_str0(mem));
6533
6534 ins_pipe(istore_mem);
6535 %}
6536
6537 // Store Pointer
6538 instruct storeP(iRegP src, memory mem)
6539 %{
6540 match(Set mem (StoreP mem src));
6541 predicate(!needs_releasing_store(n));
6542
6543 ins_cost(INSN_COST);
6544 format %{ "str $src, $mem\t# ptr" %}
6545
6546 ins_encode(aarch64_enc_str(src, mem));
6547
6548 ins_pipe(istore_reg_mem);
6549 %}
6550
6551 // Store Pointer
6552 instruct storeimmP0(immP0 zero, memory mem)
6553 %{
6554 match(Set mem (StoreP mem zero));
6555 predicate(!needs_releasing_store(n));
6556
6557 ins_cost(INSN_COST);
6558 format %{ "str zr, $mem\t# ptr" %}
6559
6560 ins_encode(aarch64_enc_str0(mem));
6561
6562 ins_pipe(istore_mem);
6563 %}
6564
6565 // Store Compressed Pointer
6566 instruct storeN(iRegN src, memory mem)
6567 %{
6568 match(Set mem (StoreN mem src));
6569 predicate(!needs_releasing_store(n));
6570
6571 ins_cost(INSN_COST);
6572 format %{ "strw $src, $mem\t# compressed ptr" %}
6573
6574 ins_encode(aarch64_enc_strw(src, mem));
6575
6576 ins_pipe(istore_reg_mem);
6577 %}
6578
6579 instruct storeImmN0(iRegIHeapbase heapbase, immN0 zero, memory mem)
6580 %{
6581 match(Set mem (StoreN mem zero));
6582 predicate(Universe::narrow_oop_base() == NULL &&
6583 Universe::narrow_klass_base() == NULL &&
6584 (!needs_releasing_store(n)));
6585
6586 ins_cost(INSN_COST);
6587 format %{ "strw rheapbase, $mem\t# compressed ptr (rheapbase==0)" %}
6588
6589 ins_encode(aarch64_enc_strw(heapbase, mem));
6590
6591 ins_pipe(istore_reg_mem);
6592 %}
6593
6594 // Store Float
6595 instruct storeF(vRegF src, memory mem)
6596 %{
6597 match(Set mem (StoreF mem src));
6598 predicate(!needs_releasing_store(n));
6599
6600 ins_cost(INSN_COST);
6601 format %{ "strs $src, $mem\t# float" %}
6602
6603 ins_encode( aarch64_enc_strs(src, mem) );
6604
6605 ins_pipe(pipe_class_memory);
6606 %}
6607
6608 // TODO
6609 // implement storeImmF0 and storeFImmPacked
6610
6611 // Store Double
6612 instruct storeD(vRegD src, memory mem)
6613 %{
6614 match(Set mem (StoreD mem src));
6615 predicate(!needs_releasing_store(n));
6616
6617 ins_cost(INSN_COST);
6618 format %{ "strd $src, $mem\t# double" %}
6619
6620 ins_encode( aarch64_enc_strd(src, mem) );
6621
6622 ins_pipe(pipe_class_memory);
6623 %}
6624
6625 // Store Compressed Klass Pointer
6626 instruct storeNKlass(iRegN src, memory mem)
6627 %{
6628 predicate(!needs_releasing_store(n));
6629 match(Set mem (StoreNKlass mem src));
6630
6631 ins_cost(INSN_COST);
6632 format %{ "strw $src, $mem\t# compressed klass ptr" %}
6633
6634 ins_encode(aarch64_enc_strw(src, mem));
6635
6636 ins_pipe(istore_reg_mem);
6637 %}
6638
6639 // TODO
6640 // implement storeImmD0 and storeDImmPacked
6641
6642 // prefetch instructions
6643 // Must be safe to execute with invalid address (cannot fault).
6644
6645 instruct prefetchalloc( memory mem ) %{
6646 match(PrefetchAllocation mem);
6647
6648 ins_cost(INSN_COST);
7070
7071 ins_pipe(ialu_reg);
7072 %}
7073
7074 // ============================================================================
7075 // MemBar Instruction
7076
7077 instruct load_fence() %{
7078 match(LoadFence);
7079 ins_cost(VOLATILE_REF_COST);
7080
7081 format %{ "load_fence" %}
7082
7083 ins_encode %{
7084 __ membar(Assembler::LoadLoad|Assembler::LoadStore);
7085 %}
7086 ins_pipe(pipe_serial);
7087 %}
7088
7089 instruct unnecessary_membar_acquire() %{
7090 predicate(unnecessary_acquire(n));
7091 match(MemBarAcquire);
7092 ins_cost(0);
7093
7094 format %{ "membar_acquire (elided)" %}
7095
7096 ins_encode %{
7097 __ block_comment("membar_acquire (elided)");
7098 %}
7099
7100 ins_pipe(pipe_class_empty);
7101 %}
7102
7103 instruct membar_acquire() %{
7104 match(MemBarAcquire);
7105 ins_cost(VOLATILE_REF_COST);
7106
7107 format %{ "membar_acquire" %}
7108
7109 ins_encode %{
7110 __ membar(Assembler::LoadLoad|Assembler::LoadStore);
7122
7123 ins_encode %{
7124 __ membar(Assembler::LoadLoad|Assembler::LoadStore);
7125 %}
7126
7127 ins_pipe(pipe_serial);
7128 %}
7129
7130 instruct store_fence() %{
7131 match(StoreFence);
7132 ins_cost(VOLATILE_REF_COST);
7133
7134 format %{ "store_fence" %}
7135
7136 ins_encode %{
7137 __ membar(Assembler::LoadStore|Assembler::StoreStore);
7138 %}
7139 ins_pipe(pipe_serial);
7140 %}
7141
7142 instruct unnecessary_membar_release() %{
7143 predicate(unnecessary_release(n));
7144 match(MemBarRelease);
7145 ins_cost(0);
7146
7147 format %{ "membar_release (elided)" %}
7148
7149 ins_encode %{
7150 __ block_comment("membar_release (elided)");
7151 %}
7152 ins_pipe(pipe_serial);
7153 %}
7154
7155 instruct membar_release() %{
7156 match(MemBarRelease);
7157 ins_cost(VOLATILE_REF_COST);
7158
7159 format %{ "membar_release" %}
7160
7161 ins_encode %{
7162 __ membar(Assembler::LoadStore|Assembler::StoreStore);
7163 %}
7164 ins_pipe(pipe_serial);
7165 %}
7166
7167 instruct membar_storestore() %{
7168 match(MemBarStoreStore);
7169 ins_cost(VOLATILE_REF_COST);
7170
7171 format %{ "MEMBAR-store-store" %}
7172
7173 ins_encode %{
7174 __ membar(Assembler::StoreStore);
7175 %}
7176 ins_pipe(pipe_serial);
7177 %}
7178
7179 instruct membar_release_lock() %{
7180 match(MemBarReleaseLock);
7181 ins_cost(VOLATILE_REF_COST);
7182
7183 format %{ "membar_release_lock" %}
7184
7185 ins_encode %{
7186 __ membar(Assembler::LoadStore|Assembler::StoreStore);
7187 %}
7188
7189 ins_pipe(pipe_serial);
7190 %}
7191
7192 instruct unnecessary_membar_volatile() %{
7193 predicate(unnecessary_volatile(n));
7194 match(MemBarVolatile);
7195 ins_cost(0);
7196
7197 format %{ "membar_volatile (elided)" %}
7198
7199 ins_encode %{
7200 __ block_comment("membar_volatile (elided)");
7201 %}
7202
7203 ins_pipe(pipe_serial);
7204 %}
7205
7206 instruct membar_volatile() %{
7207 match(MemBarVolatile);
7208 ins_cost(VOLATILE_REF_COST*100);
7209
7210 format %{ "membar_volatile" %}
7211
7212 ins_encode %{
7213 __ membar(Assembler::StoreLoad);
7214 %}
7215
7216 ins_pipe(pipe_serial);
7217 %}
7218
7219 // ============================================================================
7220 // Cast/Convert Instructions
|