Patch to build 64 bit VM

Greg Lewis glewis at eyesbeyond.com
Mon Dec 22 06:09:53 PST 2008


G'day Xiaobin,

On Wed, Dec 17, 2008 at 09:14:16PM -0800, Xiaobin Lu wrote:
> I am attaching the patch for building 64 bit VM. They are BSD specific 
> files.  Would someone review it and help me check it in?

Sure.  Can you comment a little on the changes to
src/os_cpu/bsd_x86/vm/bytes_bsd_x86.inline.hpp?  It seems like the diff is
bigger than the changes if that makes sense (i.e. there are some whitespace
changes due to control flow changes which are hiding those).

> diff -r de4c58dbee8f src/cpu/x86/vm/stubGenerator_x86_32.cpp
> --- a/src/cpu/x86/vm/stubGenerator_x86_64.cpp	Wed Nov 26 05:05:13 2008 -0800
> +++ b/src/cpu/x86/vm/stubGenerator_x86_64.cpp	Wed Dec 17 21:06:49 2008 -0800
> @@ -954,9 +954,9 @@ class StubGenerator: public StubCodeGene
>      __ jcc(Assembler::zero, exit); // if obj is NULL it is OK
>      // Check if the oop is in the right area of memory
>      __ movptr(c_rarg2, rax);
> -    __ movptr(c_rarg3, (int64_t) Universe::verify_oop_mask());
> +    __ movptr(c_rarg3, (intptr_t) Universe::verify_oop_mask());
>      __ andptr(c_rarg2, c_rarg3);
> -    __ movptr(c_rarg3, (int64_t) Universe::verify_oop_bits());
> +    __ movptr(c_rarg3, (intptr_t) Universe::verify_oop_bits());
>      __ cmpptr(c_rarg2, c_rarg3);
>      __ jcc(Assembler::notZero, error);
>  
> @@ -969,9 +969,9 @@ class StubGenerator: public StubCodeGene
>      __ jcc(Assembler::zero, error); // if klass is NULL it is broken
>      // Check if the klass is in the right area of memory
>      __ mov(c_rarg2, rax);
> -    __ movptr(c_rarg3, (int64_t) Universe::verify_klass_mask());
> +    __ movptr(c_rarg3, (intptr_t) Universe::verify_klass_mask());
>      __ andptr(c_rarg2, c_rarg3);
> -    __ movptr(c_rarg3, (int64_t) Universe::verify_klass_bits());
> +    __ movptr(c_rarg3, (intptr_t) Universe::verify_klass_bits());
>      __ cmpptr(c_rarg2, c_rarg3);
>      __ jcc(Assembler::notZero, error);
>  
> @@ -980,9 +980,9 @@ class StubGenerator: public StubCodeGene
>      __ testptr(rax, rax);
>      __ jcc(Assembler::zero, error); // if klass' klass is NULL it is broken
>      // Check if the klass' klass is in the right area of memory
> -    __ movptr(c_rarg3, (int64_t) Universe::verify_klass_mask());
> +    __ movptr(c_rarg3, (intptr_t) Universe::verify_klass_mask());
>      __ andptr(rax, c_rarg3);
> -    __ movptr(c_rarg3, (int64_t) Universe::verify_klass_bits());
> +    __ movptr(c_rarg3, (intptr_t) Universe::verify_klass_bits());
>      __ cmpptr(rax, c_rarg3);
>      __ jcc(Assembler::notZero, error);
> 
> diff -r de4c58dbee8f src/os_cpu/bsd_x86/vm/bytes_bsd_x86.inline.hpp
> --- a/src/os_cpu/bsd_x86/vm/bytes_bsd_x86.inline.hpp	Wed Nov 26 05:05:13 2008 -0800
> +++ b/src/os_cpu/bsd_x86/vm/bytes_bsd_x86.inline.hpp	Wed Dec 17 21:06:49 2008 -0800
> @@ -32,9 +32,9 @@
>  
>  #if defined(AMD64)
>  #  if defined(__APPLE__)
> -#    define bswap16(x)	OSSwapInt16(x)
> -#    define bswap32(x)	OSSwapInt32(x)
> -#    define bswap64(x)	OSSwapInt64(x)
> +#    define bswap_16(x)	OSSwapInt16(x)
> +#    define bswap_32(x)	OSSwapInt32(x)
> +#    define bswap_64(x)	OSSwapInt64(x)
>  #  elif defined(__OpenBSD__)
>  #    define bswap_16(x)	swap16(x)
>  #    define bswap_32(x)	swap32(x)
> diff -r de4c58dbee8f src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp
> --- a/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp	Wed Nov 26 05:05:13 2008 -0800
> +++ b/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp	Wed Dec 17 21:06:49 2008 -0800
> @@ -456,197 +456,191 @@ JVM_handle_bsd_signal(int sig,
>          if (nm != NULL && nm->has_unsafe_access()) {
>            stub = StubRoutines::handler_for_unsafe_access();
>          }
> +      } else {
> +#if defined(AMD64) && !defined(__APPLE__)
> +        if (sig == SIGFPE  &&
> +            (info->si_code == FPE_INTDIV || info->si_code == FPE_FLTDIV)) {
> +          stub =
> +            SharedRuntime::
> +            continuation_for_implicit_exception(thread,
> +                                                pc,
> +                                                SharedRuntime::
> +                                                IMPLICIT_DIVIDE_BY_ZERO);
> +#else
> +        if (sig == SIGFPE /* && info->si_code == FPE_INTDIV */) {
> +          // HACK: si_code does not work on bsd 2.2.12-20!!!
> +          int op = pc[0];
> +#  ifdef AMD64
> +          // Skip REX
> +          if ((pc[0] & 0xf0) == 0x40) {
> +            op = pc[1];
> +#  endif     
> +          if (op == 0xDB) {
> +            // FIST
> +            // TODO: The encoding of D2I in i486.ad can cause an exception
> +            // prior to the fist instruction if there was an invalid operation
> +            // pending. We want to dismiss that exception. From the win_32
> +            // side it also seems that if it really was the fist causing
> +            // the exception that we do the d2i by hand with different
> +            // rounding. Seems kind of weird.
> +            // NOTE: that we take the exception at the NEXT floating point instruction.
> +            assert(pc[0] == 0xDB, "not a FIST opcode");
> +            assert(pc[1] == 0x14, "not a FIST opcode");
> +            assert(pc[2] == 0x24, "not a FIST opcode");
> +            return true;
> +          } else if (op == 0xF7) {
> +            // IDIV
> +            stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_DIVIDE_BY_ZERO);
> +          } else {
> +            // TODO: handle more cases if we are using other x86 instructions
> +            //   that can generate SIGFPE signal on bsd.
> +            tty->print_cr("unknown opcode 0x%X with SIGFPE.", op);
> +            fatal("please update this code.");
> +          }
> +#endif // AMD64
> +          } else if ((sig == SIGSEGV || sig == SIGBUS) &&
> +                     !MacroAssembler::needs_explicit_null_check((intptr_t)info->si_addr)) {
> +            // Determination of interpreter/vtable stub/compiled code null exception
> +            stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL);
> +          }
> +        } else if (thread->thread_state() == _thread_in_vm &&
> +                   sig == SIGBUS && /* info->si_code == BUS_OBJERR && */
> +                   thread->doing_unsafe_access()) {
> +          stub = StubRoutines::handler_for_unsafe_access();
> +        }
> +
> +        // jni_fast_Get<Primitive>Field can trap at certain pc's if a GC kicks in
> +        // and the heap gets shrunk before the field access.
> +        if ((sig == SIGSEGV) || (sig == SIGBUS)) {
> +          address addr = JNI_FastGetField::find_slowcase_pc(pc);
> +          if (addr != (address)-1) {
> +            stub = addr;
> +          }
> +        }
> +
> +        // Check to see if we caught the safepoint code in the
> +        // process of write protecting the memory serialization page.
> +        // It write enables the page immediately after protecting it
> +        // so we can just return to retry the write.
> +        if ((sig == SIGSEGV || sig == SIGBUS) &&
> +            os::is_memory_serialize_page(thread, (address) info->si_addr)) {
> +          // Block current thread until the memory serialize page permission restored.
> +          os::block_on_serialize_page_trap();
> +          return true;
> +        }
>        }
> -      else
> +#ifndef AMD64
> +      // Execution protection violation
> +      //
> +      // This should be kept as the last step in the triage.  We don't
> +      // have a dedicated trap number for a no-execute fault, so be
> +      // conservative and allow other handlers the first shot.
> +      //
> +      // Note: We don't test that info->si_code == SEGV_ACCERR here.
> +      // this si_code is so generic that it is almost meaningless; and
> +      // the si_code for this condition may change in the future.
> +      // Furthermore, a false-positive should be harmless.
> +      if (UnguardOnExecutionViolation > 0 &&
> +          (sig == SIGSEGV || sig == SIGBUS) &&
> +          uc->context_trapno == trap_page_fault) {
> +        int page_size = os::vm_page_size();
> +        address addr = (address) info->si_addr;
> +        address pc = os::Bsd::ucontext_get_pc(uc);
> +        // Make sure the pc and the faulting address are sane.
> +        //
> +        // If an instruction spans a page boundary, and the page containing
> +        // the beginning of the instruction is executable but the following
> +        // page is not, the pc and the faulting address might be slightly
> +        // different - we still want to unguard the 2nd page in this case.
> +        //
> +        // 15 bytes seems to be a (very) safe value for max instruction size.
> +        bool pc_is_near_addr =
> +          (pointer_delta((void*) addr, (void*) pc, sizeof(char)) < 15);
> +        bool instr_spans_page_boundary =
> +          (align_size_down((intptr_t) pc ^ (intptr_t) addr,
> +                           (intptr_t) page_size) > 0);
>  
> -#if defined(AMD64) && !defined(__APPLE__)
> -      if (sig == SIGFPE  &&
> -          (info->si_code == FPE_INTDIV || info->si_code == FPE_FLTDIV)) {
> -        stub =
> -          SharedRuntime::
> -          continuation_for_implicit_exception(thread,
> -                                              pc,
> -                                              SharedRuntime::
> -                                              IMPLICIT_DIVIDE_BY_ZERO);
> +        if (pc == addr || (pc_is_near_addr && instr_spans_page_boundary)) {
> +          static volatile address last_addr =
> +            (address) os::non_memory_address_word();
>  
> -#else
> -      if (sig == SIGFPE /* && info->si_code == FPE_INTDIV */) {
> -        // HACK: si_code does not work on bsd 2.2.12-20!!!
> -        int op = pc[0];
> +          // In conservative mode, don't unguard unless the address is in the VM
> +          if (addr != last_addr &&
> +              (UnguardOnExecutionViolation > 1 || os::address_is_in_vm(addr))) {
> +
> +            // Unguard and retry
> +            address page_start =
> +              (address) align_size_down((intptr_t) addr, (intptr_t) page_size);
> +            bool res = os::unguard_memory((char*) page_start, page_size);
> +            
> +            if (PrintMiscellaneous && Verbose) {
> +              char buf[256];
> +              jio_snprintf(buf, sizeof(buf), "Execution protection violation "
> +                           "at " INTPTR_FORMAT
> +                           ", unguarding " INTPTR_FORMAT ": %s, errno=%d", addr,
> +                           page_start, (res ? "success" : "failed"), errno);
> +              tty->print_raw_cr(buf);
> +            }
> +            stub = pc;
> +
> +            // Set last_addr so if we fault again at the same address, we don't end
> +            // up in an endless loop.
> +            //
> +            // There are two potential complications here.  Two threads trapping at
> +            // the same address at the same time could cause one of the threads to
> +            // think it already unguarded, and abort the VM.  Likely very rare.
> +            //
> +            // The other race involves two threads alternately trapping at
> +            // different addresses and failing to unguard the page, resulting in
> +            // an endless loop.  This condition is probably even more unlikely than
> +            // the first.
> +            //
> +            // Although both cases could be avoided by using locks or thread local
> +            // last_addr, these solutions are unnecessary complication: this
> +            // handler is a best-effort safety net, not a complete solution.  It is
> +            // disabled by default and should only be used as a workaround in case
> +            // we missed any no-execute-unsafe VM code.
> +            
> +            last_addr = addr;
> +          }
> +        }
> +      }
> +#endif // !AMD64
> +      if (stub != NULL) {
> +        // save all thread context in case we need to restore it
> +        if (thread != NULL) thread->set_saved_exception_pc(pc);
>          
> -#  ifdef AMD64
> -        // Skip REX
> -        if ((pc[0] & 0xf0) == 0x40) {
> -          op = pc[1];
> -#  endif
> -        
> -        if (op == 0xDB) {
> -          // FIST
> -          // TODO: The encoding of D2I in i486.ad can cause an exception
> -          // prior to the fist instruction if there was an invalid operation
> -          // pending. We want to dismiss that exception. From the win_32
> -          // side it also seems that if it really was the fist causing
> -          // the exception that we do the d2i by hand with different
> -          // rounding. Seems kind of weird.
> -          // NOTE: that we take the exception at the NEXT floating point instruction.
> -          assert(pc[0] == 0xDB, "not a FIST opcode");
> -          assert(pc[1] == 0x14, "not a FIST opcode");
> -          assert(pc[2] == 0x24, "not a FIST opcode");
> -          return true;
> -        } else if (op == 0xF7) {
> -          // IDIV
> -          stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_DIVIDE_BY_ZERO);
> -        } else {
> -          // TODO: handle more cases if we are using other x86 instructions
> -          //   that can generate SIGFPE signal on bsd.
> -          tty->print_cr("unknown opcode 0x%X with SIGFPE.", op);
> -          fatal("please update this code.");
> -        }
> -#endif // AMD64
> -      } else if ((sig == SIGSEGV || sig == SIGBUS) &&
> -               !MacroAssembler::needs_explicit_null_check((intptr_t)info->si_addr)) {
> -          // Determination of interpreter/vtable stub/compiled code null exception
> -          stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL);
> +        uc->context_pc = (intptr_t)stub;
> +        return true;
>        }
> -    } else if (thread->thread_state() == _thread_in_vm &&
> -               sig == SIGBUS && /* info->si_code == BUS_OBJERR && */
> -               thread->doing_unsafe_access()) {
> -        stub = StubRoutines::handler_for_unsafe_access();
> -    }
>  
> -    // jni_fast_Get<Primitive>Field can trap at certain pc's if a GC kicks in
> -    // and the heap gets shrunk before the field access.
> -    if ((sig == SIGSEGV) || (sig == SIGBUS)) {
> -      address addr = JNI_FastGetField::find_slowcase_pc(pc);
> -      if (addr != (address)-1) {
> -        stub = addr;
> +      // signal-chaining
> +      if (os::Bsd::chained_handler(sig, info, ucVoid)) {
> +        return true;
>        }
> -    }
>  
> -    // Check to see if we caught the safepoint code in the
> -    // process of write protecting the memory serialization page.
> -    // It write enables the page immediately after protecting it
> -    // so we can just return to retry the write.
> -    if ((sig == SIGSEGV || sig == SIGBUS) &&
> -        os::is_memory_serialize_page(thread, (address) info->si_addr)) {
> -      // Block current thread until the memory serialize page permission restored.
> -      os::block_on_serialize_page_trap();
> -      return true;
> +      if (!abort_if_unrecognized) {
> +        // caller wants another chance, so give it to him
> +        return false;
> +      }
> +
> +      if (pc == NULL && uc != NULL) {
> +        pc = os::Bsd::ucontext_get_pc(uc);
> +      }
> +
> +      // unmask current signal
> +      sigset_t newset;
> +      sigemptyset(&newset);
> +      sigaddset(&newset, sig);
> +      sigprocmask(SIG_UNBLOCK, &newset, NULL);
> +      
> +      VMError err(t, sig, pc, info, ucVoid);
> +      err.report_and_die();
> +      
> +      ShouldNotReachHere();
>      }
>    }
> -
> -#ifndef AMD64
> -  // Execution protection violation
> -  //
> -  // This should be kept as the last step in the triage.  We don't
> -  // have a dedicated trap number for a no-execute fault, so be
> -  // conservative and allow other handlers the first shot.
> -  //
> -  // Note: We don't test that info->si_code == SEGV_ACCERR here.
> -  // this si_code is so generic that it is almost meaningless; and
> -  // the si_code for this condition may change in the future.
> -  // Furthermore, a false-positive should be harmless.
> -  if (UnguardOnExecutionViolation > 0 &&
> -      (sig == SIGSEGV || sig == SIGBUS) &&
> -      uc->context_trapno == trap_page_fault) {
> -    int page_size = os::vm_page_size();
> -    address addr = (address) info->si_addr;
> -    address pc = os::Bsd::ucontext_get_pc(uc);
> -    // Make sure the pc and the faulting address are sane.
> -    //
> -    // If an instruction spans a page boundary, and the page containing
> -    // the beginning of the instruction is executable but the following
> -    // page is not, the pc and the faulting address might be slightly
> -    // different - we still want to unguard the 2nd page in this case.
> -    //
> -    // 15 bytes seems to be a (very) safe value for max instruction size.
> -    bool pc_is_near_addr =
> -      (pointer_delta((void*) addr, (void*) pc, sizeof(char)) < 15);
> -    bool instr_spans_page_boundary =
> -      (align_size_down((intptr_t) pc ^ (intptr_t) addr,
> -                       (intptr_t) page_size) > 0);
> -
> -    if (pc == addr || (pc_is_near_addr && instr_spans_page_boundary)) {
> -      static volatile address last_addr =
> -        (address) os::non_memory_address_word();
> -
> -      // In conservative mode, don't unguard unless the address is in the VM
> -      if (addr != last_addr &&
> -          (UnguardOnExecutionViolation > 1 || os::address_is_in_vm(addr))) {
> -
> -        // Unguard and retry
> -        address page_start =
> -          (address) align_size_down((intptr_t) addr, (intptr_t) page_size);
> -        bool res = os::unguard_memory((char*) page_start, page_size);
> -
> -        if (PrintMiscellaneous && Verbose) {
> -          char buf[256];
> -          jio_snprintf(buf, sizeof(buf), "Execution protection violation "
> -                       "at " INTPTR_FORMAT
> -                       ", unguarding " INTPTR_FORMAT ": %s, errno=%d", addr,
> -                       page_start, (res ? "success" : "failed"), errno);
> -          tty->print_raw_cr(buf);
> -        }
> -        stub = pc;
> -
> -        // Set last_addr so if we fault again at the same address, we don't end
> -        // up in an endless loop.
> -        //
> -        // There are two potential complications here.  Two threads trapping at
> -        // the same address at the same time could cause one of the threads to
> -        // think it already unguarded, and abort the VM.  Likely very rare.
> -        //
> -        // The other race involves two threads alternately trapping at
> -        // different addresses and failing to unguard the page, resulting in
> -        // an endless loop.  This condition is probably even more unlikely than
> -        // the first.
> -        //
> -        // Although both cases could be avoided by using locks or thread local
> -        // last_addr, these solutions are unnecessary complication: this
> -        // handler is a best-effort safety net, not a complete solution.  It is
> -        // disabled by default and should only be used as a workaround in case
> -        // we missed any no-execute-unsafe VM code.
> -
> -        last_addr = addr;
> -      }
> -    }
> -  }
> -#endif // !AMD64
> -
> -  if (stub != NULL) {
> -    // save all thread context in case we need to restore it
> -    if (thread != NULL) thread->set_saved_exception_pc(pc);
> -
> -    uc->context_pc = (intptr_t)stub;
> -    return true;
> -  }
> -
> -  // signal-chaining
> -  if (os::Bsd::chained_handler(sig, info, ucVoid)) {
> -     return true;
> -  }
> -
> -  if (!abort_if_unrecognized) {
> -    // caller wants another chance, so give it to him
> -    return false;
> -  }
> -
> -  if (pc == NULL && uc != NULL) {
> -    pc = os::Bsd::ucontext_get_pc(uc);
> -  }
> -
> -  // unmask current signal
> -  sigset_t newset;
> -  sigemptyset(&newset);
> -  sigaddset(&newset, sig);
> -  sigprocmask(SIG_UNBLOCK, &newset, NULL);
> -
> -  VMError err(t, sig, pc, info, ucVoid);
> -  err.report_and_die();
> -
> -  ShouldNotReachHere();
>  }
> -
>  #ifdef _ALLBSD_SOURCE
>  // From solaris_i486.s ported to bsd_i486.s
>  extern "C" void fixcw();

> 


-- 
Greg Lewis                          Email   : glewis at eyesbeyond.com
Eyes Beyond                         Web     : http://www.eyesbeyond.com
Information Technology              FreeBSD : glewis at FreeBSD.org



More information about the bsd-port-dev mailing list