< prev index next >

src/cpu/x86/vm/stubGenerator_x86_32.cpp

Print this page




  21  * questions.
  22  *
  23  */
  24 
  25 #include "precompiled.hpp"
  26 #include "asm/macroAssembler.hpp"
  27 #include "asm/macroAssembler.inline.hpp"
  28 #include "interpreter/interpreter.hpp"
  29 #include "nativeInst_x86.hpp"
  30 #include "oops/instanceOop.hpp"
  31 #include "oops/method.hpp"
  32 #include "oops/objArrayKlass.hpp"
  33 #include "oops/oop.inline.hpp"
  34 #include "prims/methodHandles.hpp"
  35 #include "runtime/frame.inline.hpp"
  36 #include "runtime/handles.inline.hpp"
  37 #include "runtime/sharedRuntime.hpp"
  38 #include "runtime/stubCodeGenerator.hpp"
  39 #include "runtime/stubRoutines.hpp"
  40 #include "runtime/thread.inline.hpp"

  41 #include "utilities/top.hpp"
  42 #ifdef COMPILER2
  43 #include "opto/runtime.hpp"
  44 #endif
  45 
  46 // Declaration and definition of StubGenerator (no .hpp file).
  47 // For a more detailed description of the stub routine structure
  48 // see the comment in stubRoutines.hpp
  49 
  50 #define __ _masm->
  51 #define a__ ((Assembler*)_masm)->
  52 
  53 #ifdef PRODUCT
  54 #define BLOCK_COMMENT(str) /* nothing */
  55 #else
  56 #define BLOCK_COMMENT(str) __ block_comment(str)
  57 #endif
  58 
  59 #define BIND(label) bind(label); BLOCK_COMMENT(#label ":")
  60 


 691     __ pusha();                                  // push registers (eip = return address & msg are already pushed)
 692     BLOCK_COMMENT("call MacroAssembler::debug");
 693     __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, MacroAssembler::debug32)));
 694     __ popa();
 695     __ ret(3 * wordSize);                        // pop arguments
 696     return start;
 697   }
 698 
 699   //
 700   //  Generate pre-barrier for array stores
 701   //
 702   //  Input:
 703   //     start   -  starting address
 704   //     count   -  element count
 705   void  gen_write_ref_array_pre_barrier(Register start, Register count, bool uninitialized_target) {
 706     assert_different_registers(start, count);
 707     BarrierSet* bs = Universe::heap()->barrier_set();
 708     switch (bs->kind()) {
 709       case BarrierSet::G1SATBCT:
 710       case BarrierSet::G1SATBCTLogging:

 711         // With G1, don't generate the call if we statically know that the target in uninitialized
 712         if (!uninitialized_target) {
 713            __ pusha();                      // push registers
 714            __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre),
 715                            start, count);
 716            __ popa();
 717          }
 718         break;
 719       case BarrierSet::CardTableModRef:
 720       case BarrierSet::CardTableExtension:
 721       case BarrierSet::ModRef:
 722         break;
 723       default      :
 724         ShouldNotReachHere();
 725 
 726     }
 727   }
 728 
 729 
 730   //
 731   // Generate a post-barrier for an array store
 732   //
 733   //     start    -  starting address
 734   //     count    -  element count
 735   //
 736   //  The two input registers are overwritten.
 737   //
 738   void  gen_write_ref_array_post_barrier(Register start, Register count) {
 739     BarrierSet* bs = Universe::heap()->barrier_set();
 740     assert_different_registers(start, count);
 741     switch (bs->kind()) {
 742       case BarrierSet::G1SATBCT:
 743       case BarrierSet::G1SATBCTLogging:

 744         {
 745           __ pusha();                      // push registers
 746           __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post),
 747                           start, count);
 748           __ popa();
 749         }
 750         break;
 751 
 752       case BarrierSet::CardTableModRef:
 753       case BarrierSet::CardTableExtension:
 754         {
 755           CardTableModRefBS* ct = (CardTableModRefBS*)bs;
 756           assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");
 757 
 758           Label L_loop;
 759           const Register end = count;  // elements count; end == start+count-1
 760           assert_different_registers(start, end);
 761 
 762           __ lea(end,  Address(start, count, Address::times_ptr, -wordSize));
 763           __ shrptr(start, CardTableModRefBS::card_shift);


1467     __ lea(end_from, end_from_addr);
1468     __ lea(end_to,   end_to_addr);
1469     assert(length == count, "");        // else fix next line:
1470     __ negptr(count);                   // negate and test the length
1471     __ jccb(Assembler::notZero, L_load_element);
1472 
1473     // Empty array:  Nothing to do.
1474     __ xorptr(rax, rax);                  // return 0 on (trivial) success
1475     __ jmp(L_done);
1476 
1477     // ======== begin loop ========
1478     // (Loop is rotated; its entry is L_load_element.)
1479     // Loop control:
1480     //   for (count = -count; count != 0; count++)
1481     // Base pointers src, dst are biased by 8*count,to last element.
1482     __ align(OptoLoopAlignment);
1483 
1484     __ BIND(L_store_element);
1485     __ movptr(to_element_addr, elem);     // store the oop
1486     __ increment(count);                // increment the count toward zero






1487     __ jccb(Assembler::zero, L_do_card_marks);
1488 
1489     // ======== loop entry is here ========
1490     __ BIND(L_load_element);






1491     __ movptr(elem, from_element_addr);   // load the oop
1492     __ testptr(elem, elem);






1493     __ jccb(Assembler::zero, L_store_element);
1494 
1495     // (Could do a trick here:  Remember last successful non-null
1496     // element stored and make a quick oop equality check on it.)
1497 
1498     __ movptr(elem_klass, elem_klass_addr); // query the object klass
1499     generate_type_check(elem_klass, ckoff_arg, ckval_arg, temp,
1500                         &L_store_element, NULL);
1501     // (On fall-through, we have failed the element type check.)
1502     // ======== end loop ========
1503 
1504     // It was a real error; we must depend on the caller to finish the job.
1505     // Register "count" = -1 * number of *remaining* oops, length_arg = *total* oops.
1506     // Emit GC store barriers for the oops we have copied (length_arg + count),
1507     // and report their number to the caller.
1508     assert_different_registers(to, count, rax);
1509     Label L_post_barrier;
1510     __ addl(count, length_arg);         // transfers = (length - remaining)
1511     __ movl2ptr(rax, count);            // save the value
1512     __ notptr(rax);                     // report (-1^K) to caller (does not affect flags)




  21  * questions.
  22  *
  23  */
  24 
  25 #include "precompiled.hpp"
  26 #include "asm/macroAssembler.hpp"
  27 #include "asm/macroAssembler.inline.hpp"
  28 #include "interpreter/interpreter.hpp"
  29 #include "nativeInst_x86.hpp"
  30 #include "oops/instanceOop.hpp"
  31 #include "oops/method.hpp"
  32 #include "oops/objArrayKlass.hpp"
  33 #include "oops/oop.inline.hpp"
  34 #include "prims/methodHandles.hpp"
  35 #include "runtime/frame.inline.hpp"
  36 #include "runtime/handles.inline.hpp"
  37 #include "runtime/sharedRuntime.hpp"
  38 #include "runtime/stubCodeGenerator.hpp"
  39 #include "runtime/stubRoutines.hpp"
  40 #include "runtime/thread.inline.hpp"
  41 #include "utilities/macros.hpp"
  42 #include "utilities/top.hpp"
  43 #ifdef COMPILER2
  44 #include "opto/runtime.hpp"
  45 #endif
  46 
  47 // Declaration and definition of StubGenerator (no .hpp file).
  48 // For a more detailed description of the stub routine structure
  49 // see the comment in stubRoutines.hpp
  50 
  51 #define __ _masm->
  52 #define a__ ((Assembler*)_masm)->
  53 
  54 #ifdef PRODUCT
  55 #define BLOCK_COMMENT(str) /* nothing */
  56 #else
  57 #define BLOCK_COMMENT(str) __ block_comment(str)
  58 #endif
  59 
  60 #define BIND(label) bind(label); BLOCK_COMMENT(#label ":")
  61 


 692     __ pusha();                                  // push registers (eip = return address & msg are already pushed)
 693     BLOCK_COMMENT("call MacroAssembler::debug");
 694     __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, MacroAssembler::debug32)));
 695     __ popa();
 696     __ ret(3 * wordSize);                        // pop arguments
 697     return start;
 698   }
 699 
 700   //
 701   //  Generate pre-barrier for array stores
 702   //
 703   //  Input:
 704   //     start   -  starting address
 705   //     count   -  element count
 706   void  gen_write_ref_array_pre_barrier(Register start, Register count, bool uninitialized_target) {
 707     assert_different_registers(start, count);
 708     BarrierSet* bs = Universe::heap()->barrier_set();
 709     switch (bs->kind()) {
 710       case BarrierSet::G1SATBCT:
 711       case BarrierSet::G1SATBCTLogging:
 712       case BarrierSet::ShenandoahBarrierSet:
 713         // With G1, don't generate the call if we statically know that the target in uninitialized
 714         if (!uninitialized_target) {
 715            __ pusha();                      // push registers
 716            __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre),
 717                            start, count);
 718            __ popa();
 719          }
 720         break;
 721       case BarrierSet::CardTableModRef:
 722       case BarrierSet::CardTableExtension:
 723       case BarrierSet::ModRef:
 724         break;
 725       default      :
 726         ShouldNotReachHere();
 727 
 728     }
 729   }
 730 
 731 
 732   //
 733   // Generate a post-barrier for an array store
 734   //
 735   //     start    -  starting address
 736   //     count    -  element count
 737   //
 738   //  The two input registers are overwritten.
 739   //
 740   void  gen_write_ref_array_post_barrier(Register start, Register count) {
 741     BarrierSet* bs = Universe::heap()->barrier_set();
 742     assert_different_registers(start, count);
 743     switch (bs->kind()) {
 744       case BarrierSet::G1SATBCT:
 745       case BarrierSet::G1SATBCTLogging:
 746       case BarrierSet::ShenandoahBarrierSet:
 747         {
 748           __ pusha();                      // push registers
 749           __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post),
 750                           start, count);
 751           __ popa();
 752         }
 753         break;
 754 
 755       case BarrierSet::CardTableModRef:
 756       case BarrierSet::CardTableExtension:
 757         {
 758           CardTableModRefBS* ct = (CardTableModRefBS*)bs;
 759           assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");
 760 
 761           Label L_loop;
 762           const Register end = count;  // elements count; end == start+count-1
 763           assert_different_registers(start, end);
 764 
 765           __ lea(end,  Address(start, count, Address::times_ptr, -wordSize));
 766           __ shrptr(start, CardTableModRefBS::card_shift);


1470     __ lea(end_from, end_from_addr);
1471     __ lea(end_to,   end_to_addr);
1472     assert(length == count, "");        // else fix next line:
1473     __ negptr(count);                   // negate and test the length
1474     __ jccb(Assembler::notZero, L_load_element);
1475 
1476     // Empty array:  Nothing to do.
1477     __ xorptr(rax, rax);                  // return 0 on (trivial) success
1478     __ jmp(L_done);
1479 
1480     // ======== begin loop ========
1481     // (Loop is rotated; its entry is L_load_element.)
1482     // Loop control:
1483     //   for (count = -count; count != 0; count++)
1484     // Base pointers src, dst are biased by 8*count,to last element.
1485     __ align(OptoLoopAlignment);
1486 
1487     __ BIND(L_store_element);
1488     __ movptr(to_element_addr, elem);     // store the oop
1489     __ increment(count);                // increment the count toward zero
1490 #if INCLUDE_ALL_GCS
1491     if (UseShenandoahGC) {
1492       // Shenandoah barrier is too big for 8-bit offsets to work
1493       __ jcc(Assembler::zero, L_do_card_marks);
1494     } else
1495 #endif
1496     __ jccb(Assembler::zero, L_do_card_marks);
1497 
1498     // ======== loop entry is here ========
1499     __ BIND(L_load_element);
1500 #if INCLUDE_ALL_GCS
1501     if (UseShenandoahGC) {
1502       // Needs GC barriers
1503       __ load_heap_oop(elem, from_element_addr);
1504     } else
1505 #endif
1506     __ movptr(elem, from_element_addr);   // load the oop
1507     __ testptr(elem, elem);
1508 #if INCLUDE_ALL_GCS
1509     if (UseShenandoahGC) {
1510       // Shenandoah barrier is too big for 8-bit offsets to work
1511       __ jcc(Assembler::zero, L_store_element);
1512     } else
1513 #endif
1514     __ jccb(Assembler::zero, L_store_element);
1515 
1516     // (Could do a trick here:  Remember last successful non-null
1517     // element stored and make a quick oop equality check on it.)
1518 
1519     __ movptr(elem_klass, elem_klass_addr); // query the object klass
1520     generate_type_check(elem_klass, ckoff_arg, ckval_arg, temp,
1521                         &L_store_element, NULL);
1522     // (On fall-through, we have failed the element type check.)
1523     // ======== end loop ========
1524 
1525     // It was a real error; we must depend on the caller to finish the job.
1526     // Register "count" = -1 * number of *remaining* oops, length_arg = *total* oops.
1527     // Emit GC store barriers for the oops we have copied (length_arg + count),
1528     // and report their number to the caller.
1529     assert_different_registers(to, count, rax);
1530     Label L_post_barrier;
1531     __ addl(count, length_arg);         // transfers = (length - remaining)
1532     __ movl2ptr(rax, count);            // save the value
1533     __ notptr(rax);                     // report (-1^K) to caller (does not affect flags)


< prev index next >