示例#1
0
static StgPtr
thread_TSO (StgTSO *tso)
{
    thread_(&tso->link);

    if (tso->why_blocked == BlockedOnBlackHole) {
	thread_(&tso->block_info.closure);
    }
    
    thread_stack(tso->sp, &(tso->stack[tso->stack_size]));
    return (StgPtr)tso + tso_sizeW(tso);
}
示例#2
0
  //------------------------------------------------------------------------------------------------------------------------
  // Continuation point for throwing of implicit exceptions that are not handled in
  // the current activation. Fabricates an exception oop and initiates normal
  // exception dispatching in this frame. Only callee-saved registers are preserved
  // (through the normal register window / RegisterMap handling).
  // If the compiler needs all registers to be preserved between the fault
  // point and the exception handler then it must assume responsibility for that in
  // AbstractCompiler::continuation_for_implicit_null_exception or
  // continuation_for_implicit_division_by_zero_exception. All other implicit
  // exceptions (e.g., NullPointerException or AbstractMethodError on entry) are
  // either at call sites or otherwise assume that stack unwinding will be initiated,
  // so caller saved registers were assumed volatile in the compiler.
  //
  address generate_throw_exception(const char* name, address runtime_entry, bool restore_saved_exception_pc) {
    int insts_size = VerifyThread ? 1 * K : 512;
    int locs_size  = 32;

    CodeBuffer code(name, insts_size, locs_size);
    MacroAssembler* _masm = new MacroAssembler(&code);

    const Register saved_exception_pc_addr = GR31_SCRATCH;
    const Register continuation            = GR30_SCRATCH;

    const Register saved_exception_pc      = GR31_SCRATCH;

    const BranchRegister continuation_br   = BR6_SCRATCH;

    // 4826555: nsk test stack016 fails.  See os_linux_ia64.cpp.
    // Reload register stack limit because the Linux kernel
    // doesn't reload GR4-7 from the ucontext.
    __ add(GR7_reg_stack_limit, thread_(register_stack_limit));
    __ ld8(GR7_reg_stack_limit, GR7_reg_stack_limit);

//  __ verify_thread();

    // If the exception occured at a call site target, RP contains the return address
    // (which is also the exception PC), and the call instruction has pushed a degenerate
    // register frame.  If the exception happened elsewhere, the signal handler has saved
    // the exception address in the thread state and we must execute a call instruction
    // in order to obtain a degenerate frame.  In either case, we must then push a frame
    // so we can execute a call_VM.

    if (restore_saved_exception_pc) {
      __ add(saved_exception_pc_addr, thread_(saved_exception_pc));
      __ ld8(saved_exception_pc, saved_exception_pc_addr);
      __ push_dummy_full_frame(saved_exception_pc);
    } else {
      __ push_full_frame();
    }

    // Install the exception oop in the thread state, etc.
    __ call_VM(noreg, runtime_entry);

    // Scale back to a thin frame for forward_exception.
    __ pop_full_to_thin_frame();

    // Branch to forward_exception.
    __ mova(continuation, StubRoutines::forward_exception_entry());
    __ mov(continuation_br, continuation);
    __ br(continuation_br);

    __ flush_bundle();

    RuntimeStub* stub = RuntimeStub::new_runtime_stub(name, &code, CodeBlob::frame_never_safe, 0, NULL, false);
    return stub->entry_point();
  }
示例#3
0
  //------------------------------------------------------------------------------------------------------------------------
  // Return point for a Java call if there's an exception thrown in Java code.
  // The exception is caught and transformed into a pending exception stored in
  // JavaThread that can be tested from within the VM.
  //
  address generate_catch_exception() {
    StubCodeMark mark(this, "StubRoutines", "catch_exception");

    address start = __ pc();

    // verify that thread corresponds
//  __ verify_thread();

    // set pending exception
//  __ verify_oop(GR8_exception, "generate_catch_exception");

    const Register pending_exception_addr   = GR2_SCRATCH;
    const Register exception_file_addr      = GR3_SCRATCH;
    const Register exception_line_addr      = GR31_SCRATCH;
    const Register exception_file           = GR30_SCRATCH;
    const Register exception_line           = GR29_SCRATCH;
    const Register call_stub_return_address = GR28_SCRATCH;

    const BranchRegister call_stub_return_address_br = BR6_SCRATCH;

    __ add(pending_exception_addr, thread_(pending_exception));
    __ mova(exception_file, (address)__FILE__);
    __ add(exception_file_addr, thread_(exception_file));
    __ mova(exception_line, (address)__LINE__);

    __ st8(pending_exception_addr, GR8_exception);
    __ st8(exception_file_addr, exception_file);
    __ add(exception_line_addr, thread_(exception_line));

    __ st8(exception_line_addr, exception_line);

    // complete return to VM
    assert(StubRoutines::_call_stub_return_address != NULL, "must have been generated before");

    __ mova(call_stub_return_address, StubRoutines::_call_stub_return_address);
    __ mov(call_stub_return_address_br, call_stub_return_address);
    __ br(call_stub_return_address_br);

    __ flush_bundle();

    return start;
  }
示例#4
0
int main (int argc, char** argv)
{
    // Initialize ROS
    ros::init (argc, argv, "grasp");
    ros::NodeHandle n;
    ros::NodeHandle nh("~");

    ros::Subscriber sub = n.subscribe ("/jaco/tool_position", 1, arm_position_callback);
    ros::Subscriber sub2 = n.subscribe ("/jaco/finger_position", 1, fingers_position_callback);
    boost::thread thread_(thread_function);

    ros::Rate r(30);
    while(ros::ok() && !end_program){
        ros::spinOnce();
        r.sleep();
    }
    thread_.join();

    return 0;
}
示例#5
0
  //------------------------------------------------------------------------------------------------------------------------
  // Call stubs are used to call Java from C
  //
  // GR_I0 - call wrapper address     : address
  // GR_I1 - result                   : intptr_t*
  // GR_I2 - result type              : BasicType
  // GR_I3 - method                   : methodOop
  // GR_I4 - interpreter entry point  : address
  // GR_I5 - parameter block          : intptr_t*
  // GR_I6 - parameter count in words : int
  // GR_I7 - thread                   : Thread*
  //
  address generate_call_stub(address& return_address) {
    StubCodeMark mark(this, "StubRoutines", "call_stub");

    const Register result     = GR_I1;
    const Register type       = GR_I2;
    const Register method     = GR_I3;
    const Register entry_ptr  = GR_I4;
    const Register parms      = GR_I5;
    const Register parm_count = GR_I6;
    const Register thread     = GR_I7;

    const Register parm_size = GR31_SCRATCH;
    const Register entry     = GR30_SCRATCH;
    const Register arg       = GR29_SCRATCH;

    const Register out_tos   = GR49; // Equivalent of GR_Otos
    const Register out_parms = GR50; // Equivalent of GR_Olocals (unused)

    const BranchRegister    entry_br = BR6_SCRATCH;
    const PredicateRegister no_args  = PR6_SCRATCH;

    address start = __ emit_fd();

    // Must allocate 8 output registers in case we go thru an i2c
    // and the callee needs 8 input registers
    __ alloc(GR_Lsave_PFS, 8, 9, 8, 0);                     // save AR_PFS
    __ sxt4(parm_count, parm_count);                        // # of parms
    __ mov(GR_Lsave_SP, SP);                                // save caller's SP
    __ mov(GR_entry_frame_GR5, GR5_poll_page_addr);
    __ mov(GR_entry_frame_GR6, GR6_caller_BSP);
    __ mov(GR_entry_frame_GR7, GR7_reg_stack_limit);

    // We can not tolerate an eager RSE cpu. Itanium-1 & 2 do not support
    // this feature but we turn it off anyway
    const Register RSC   = GR2_SCRATCH;
    __ mov(RSC, AR_RSC);
    __ and3(RSC, -4, RSC);      // Turn off two low bits
    __ mov(AR_RSC, RSC);        //  enforced lazy mode

    __ shladd(parm_size, parm_count, Interpreter::logStackElementSize(), GR0); // size of stack space for the parms
    __ mov(GR_Lsave_RP, RP);                                // save return address

    __ add(parm_size, parm_size, 15);                       // round up to multiple of 16 bytes.  we use
                                                            // caller's 16-byte scratch area for params,
                                                            // so no need to add 16 to the current frame size.
    __ mov(GR_Lsave_LC, AR_LC);                             // save AR_LC
    __ add(out_parms, SP, Interpreter::stackElementSize());      // caller's SP+8 is 1st parm addr == target method locals addr

    __ and3(parm_size, parm_size, -16);
    __ cmp4(PR0, no_args, 0, parm_count, Assembler::less);  // any parms?

    __ mov(GR_entry_frame_GR4, GR4_thread);                 // save GR4_thread: it's a preserved register
    __ sub(SP, SP, parm_size);                              // allocate the space for args + scratch
    __ mov(entry_br, entry_ptr);

    __ mov(GR27_method, method);                            // load method
    __ mov(GR4_thread, thread);                             // load thread
    if (TaggedStackInterpreter) __ shl(parm_count, parm_count, 1);  // 2x tags
    __ sub(parm_count, parm_count, 1);                      // cloop counts down to zero

    // Initialize the register and memory stack limits for stack checking in compiled code
    __ add(GR7_reg_stack_limit, thread_(register_stack_limit));
    __ mov(GR6_caller_BSP, AR_BSP);                         // load register SP
    __ movl(GR5_poll_page_addr, (intptr_t) os::get_polling_page() );
    __ ld8(GR7_reg_stack_limit, GR7_reg_stack_limit);       // load register stack limit

    Label exit;

    __ mov(AR_LC, parm_count);
    __ mov(out_tos, out_parms);                             // out_tos = &out_parms[0]
    __ br(no_args, exit, Assembler::dpnt);

    // Reverse argument list and set up sender tos

    Label copy_word;
    __ bind(copy_word);

    __ ld8(arg, parms, BytesPerWord);                       // load *parms++
    __ st8(out_tos, arg, -BytesPerWord);                    // store *out_tos--
    __ cloop(copy_word, Assembler::sptk, Assembler::few);

    // Bias stack for tags.
    if (TaggedStackInterpreter) __ st8(out_tos, GR0, -BytesPerWord);
    __ bind(exit);

    __ mov(GR_entry_frame_TOS, out_tos);                    // so entry_frame_argument_at can find TOS

    // call interpreter frame manager

    // Remember the senderSP so we interpreter can pop c2i arguments off of the stack
    // when called via a c2i.

    __ mov(GR28_sender_SP, SP);

    __ call(entry_br);

    return_address = __ pc();

    // Store result depending on type.  Everything that is not
    // T_OBJECT, T_LONG, T_FLOAT, or T_DOUBLE is treated as T_INT.

    const PredicateRegister is_obj = PR6_SCRATCH;
    const PredicateRegister is_flt = PR7_SCRATCH;
    const PredicateRegister is_dbl = PR8_SCRATCH;
    const PredicateRegister is_lng = PR9_SCRATCH;

    __ cmp4(is_obj, PR0,    T_OBJECT, type, Assembler::equal);
    __ cmp4(is_flt, PR0,    T_FLOAT,  type, Assembler::equal);
    __ st4( result, GR_RET);

    __ st8( is_obj, result, GR_RET);
    __ stfs(is_flt, result, FR_RET);
    __ cmp4(is_dbl, PR0,    T_DOUBLE, type, Assembler::equal);

    __ stfd(is_dbl, result, FR_RET);
    __ cmp4(is_lng, PR0,    T_LONG,   type, Assembler::equal);
    __ mov(RP, GR_Lsave_RP);

    __ st8( is_lng, result, GR_RET);
    __ mov(GR4_thread, GR_entry_frame_GR4);

    __ mov(GR6_caller_BSP, GR_entry_frame_GR6);
    __ mov(GR7_reg_stack_limit, GR_entry_frame_GR7);
    __ mov(GR5_poll_page_addr, GR_entry_frame_GR5);
    __ mov(AR_PFS, GR_Lsave_PFS);

    __ mov(AR_LC, GR_Lsave_LC);
    __ mov(SP, GR_Lsave_SP);
    __ ret();

    return start;
  }
示例#6
0
  //------------------------------------------------------------------------------------------------------------------------
  // Continuation point for runtime calls returning with a pending exception.
  // The pending exception check happened in the runtime or native call stub.
  // The pending exception in Thread is converted into a Java-level exception.
  //
  // Contract with Java-level exception handlers:
  //
  address generate_forward_exception() {
    StubCodeMark mark(this, "StubRoutines", "forward exception");

    address start = __ pc();

    // Upon entry, GR_Lsave_RP has the return address returning into Java
    // compiled code; i.e. the return address becomes the throwing pc.

    const Register pending_exception_addr = GR31_SCRATCH;
    const Register handler                = GR30_SCRATCH;

    const PredicateRegister is_not_null   = PR15_SCRATCH;
    const BranchRegister    handler_br    = BR6_SCRATCH;

    // Allocate abi scratch, since the compiler didn't allocate a memory frame.
    // pop_dummy_thin_frame will restore the caller's SP.
    __ sub(SP, SP, 16);

#ifdef ASSERT
    // Get pending exception oop.
    __ add(pending_exception_addr, thread_(pending_exception));
    __ ld8(GR8_exception, pending_exception_addr);

    // Make sure that this code is only executed if there is a pending exception.
    {
      Label not_null;
      __ cmp(is_not_null, PR0, 0, GR8_exception, Assembler::notEqual);
      __ br(is_not_null, not_null);
      __ stop("StubRoutines::forward exception: no pending exception (1)");
      __ bind(not_null);
    }

//  __ verify_oop(GR8_exception, "generate_forward_exception");
#endif

    // Find exception handler
    __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), GR_Lsave_RP);

    __ mov(handler, GR_RET);

    // Load pending exception oop.
    __ add(pending_exception_addr, thread_(pending_exception));
    __ ld8(GR8_exception, pending_exception_addr);

    // The exception pc is the return address in the caller.
    __ mov(GR9_issuing_pc, GR_Lsave_RP);

    // Uses GR2, BR6
    __ pop_dummy_thin_frame();
    // Now in caller of native/stub register frame

#ifdef ASSERT
    // make sure exception is set
    {
      Label not_null;
      __ cmp(is_not_null, PR0, 0, GR8_exception, Assembler::notEqual);
      __ br(is_not_null, not_null);
      __ stop("StubRoutines::forward exception: no pending exception (2)");
      __ bind(not_null);
    }
#endif
    // clear pending exception
    __ st8(pending_exception_addr, GR0);

    // jump to exception handler
    __ mov(handler_br, handler);
    __ br(handler_br);

    __ flush_bundle();

    return start;
  }
示例#7
0
// ToDo: too big to inline
static /* STATIC_INLINE */ StgPtr
thread_obj (StgInfoTable *info, StgPtr p)
{
    switch (info->type) {
    case THUNK_0_1:
	return p + sizeofW(StgThunk) + 1;

    case FUN_0_1:
    case CONSTR_0_1:
	return p + sizeofW(StgHeader) + 1;
	
    case FUN_1_0:
    case CONSTR_1_0:
	thread(&((StgClosure *)p)->payload[0]);
	return p + sizeofW(StgHeader) + 1;
	
    case THUNK_1_0:
	thread(&((StgThunk *)p)->payload[0]);
	return p + sizeofW(StgThunk) + 1;
	
    case THUNK_0_2:
	return p + sizeofW(StgThunk) + 2;

    case FUN_0_2:
    case CONSTR_0_2:
	return p + sizeofW(StgHeader) + 2;
	
    case THUNK_1_1:
	thread(&((StgThunk *)p)->payload[0]);
	return p + sizeofW(StgThunk) + 2;

    case FUN_1_1:
    case CONSTR_1_1:
	thread(&((StgClosure *)p)->payload[0]);
	return p + sizeofW(StgHeader) + 2;
	
    case THUNK_2_0:
	thread(&((StgThunk *)p)->payload[0]);
	thread(&((StgThunk *)p)->payload[1]);
	return p + sizeofW(StgThunk) + 2;

    case FUN_2_0:
    case CONSTR_2_0:
	thread(&((StgClosure *)p)->payload[0]);
	thread(&((StgClosure *)p)->payload[1]);
	return p + sizeofW(StgHeader) + 2;
	
#ifdef ALLOW_INTERPRETER
    case BCO: {
	StgBCO *bco = (StgBCO *)p;
	thread_(&bco->instrs);
	thread_(&bco->literals);
	thread_(&bco->ptrs);
	return p + bco_sizeW(bco);
    }
#endif // ALLOW_INTERPRETER

    case THUNK:
    {
	StgPtr end;
	
	end = (P_)((StgThunk *)p)->payload + 
	    info->layout.payload.ptrs;
	for (p = (P_)((StgThunk *)p)->payload; p < end; p++) {
	    thread((StgClosure **)p);
	}
	return p + info->layout.payload.nptrs;
    }

    case FUN:
    case CONSTR:
    case STABLE_NAME:
    case IND_PERM:
    case MUT_VAR_CLEAN:
    case MUT_VAR_DIRTY:
    case CAF_BLACKHOLE:
    case SE_CAF_BLACKHOLE:
    case SE_BLACKHOLE:
    case BLACKHOLE:
    {
	StgPtr end;
	
	end = (P_)((StgClosure *)p)->payload + 
	    info->layout.payload.ptrs;
	for (p = (P_)((StgClosure *)p)->payload; p < end; p++) {
	    thread((StgClosure **)p);
	}
	return p + info->layout.payload.nptrs;
    }
    
    case WEAK:
    {
	StgWeak *w = (StgWeak *)p;
	thread(&w->key);
	thread(&w->value);
	thread(&w->finalizer);
	if (w->link != NULL) {
	    thread_(&w->link);
	}
	return p + sizeofW(StgWeak);
    }
    
    case IND_OLDGEN:
    case IND_OLDGEN_PERM:
	thread(&((StgInd *)p)->indirectee);
	return p + sizeofW(StgInd);

    case THUNK_SELECTOR:
    { 
	StgSelector *s = (StgSelector *)p;
	thread(&s->selectee);
	return p + THUNK_SELECTOR_sizeW();
    }
    
    case AP_STACK:
	return thread_AP_STACK((StgAP_STACK *)p);
	
    case PAP:
	return thread_PAP((StgPAP *)p);

    case AP:
	return thread_AP((StgAP *)p);
	
    case ARR_WORDS:
	return p + arr_words_sizeW((StgArrWords *)p);
	
    case MUT_ARR_PTRS_CLEAN:
    case MUT_ARR_PTRS_DIRTY:
    case MUT_ARR_PTRS_FROZEN:
    case MUT_ARR_PTRS_FROZEN0:
	// follow everything 
    {
	StgPtr next;
	
	next = p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
	for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) {
	    thread((StgClosure **)p);
	}
	return p;
    }
    
    case TSO:
	return thread_TSO((StgTSO *)p);
    
    default:
	barf("update_fwd: unknown/strange object  %d", (int)(info->type));
	return NULL;
    }
}
示例#8
0
// Call an accessor method (assuming it is resolved, otherwise drop into
// vanilla (slow path) entry.
address InterpreterGenerator::generate_accessor_entry(void) {
  if (!UseFastAccessorMethods && (!FLAG_IS_ERGO(UseFastAccessorMethods))) {
    return NULL;
  }

  Label Lslow_path, Lacquire;

  const Register
         Rclass_or_obj = R3_ARG1,
         Rconst_method = R4_ARG2,
         Rcodes        = Rconst_method,
         Rcpool_cache  = R5_ARG3,
         Rscratch      = R11_scratch1,
         Rjvmti_mode   = Rscratch,
         Roffset       = R12_scratch2,
         Rflags        = R6_ARG4,
         Rbtable       = R7_ARG5;

  static address branch_table[number_of_states];

  address entry = __ pc();

  // Check for safepoint:
  // Ditch this, real man don't need safepoint checks.

  // Also check for JVMTI mode
  // Check for null obj, take slow path if so.
  __ ld(Rclass_or_obj, Interpreter::stackElementSize, CC_INTERP_ONLY(R17_tos) NOT_CC_INTERP(R15_esp));
  __ lwz(Rjvmti_mode, thread_(interp_only_mode));
  __ cmpdi(CCR1, Rclass_or_obj, 0);
  __ cmpwi(CCR0, Rjvmti_mode, 0);
  __ crorc(/*CCR0 eq*/2, /*CCR1 eq*/4+2, /*CCR0 eq*/2);
  __ beq(CCR0, Lslow_path); // this==null or jvmti_mode!=0

  // Do 2 things in parallel:
  // 1. Load the index out of the first instruction word, which looks like this:
  //    <0x2a><0xb4><index (2 byte, native endianess)>.
  // 2. Load constant pool cache base.
  __ ld(Rconst_method, in_bytes(Method::const_offset()), R19_method);
  __ ld(Rcpool_cache, in_bytes(ConstMethod::constants_offset()), Rconst_method);

  __ lhz(Rcodes, in_bytes(ConstMethod::codes_offset()) + 2, Rconst_method); // Lower half of 32 bit field.
  __ ld(Rcpool_cache, ConstantPool::cache_offset_in_bytes(), Rcpool_cache);

  // Get the const pool entry by means of <index>.
  const int codes_shift = exact_log2(in_words(ConstantPoolCacheEntry::size()) * BytesPerWord);
  __ slwi(Rscratch, Rcodes, codes_shift); // (codes&0xFFFF)<<codes_shift
  __ add(Rcpool_cache, Rscratch, Rcpool_cache);

  // Check if cpool cache entry is resolved.
  // We are resolved if the indices offset contains the current bytecode.
  ByteSize cp_base_offset = ConstantPoolCache::base_offset();
  // Big Endian:
  __ lbz(Rscratch, in_bytes(cp_base_offset) + in_bytes(ConstantPoolCacheEntry::indices_offset()) + 7 - 2, Rcpool_cache);
  __ cmpwi(CCR0, Rscratch, Bytecodes::_getfield);
  __ bne(CCR0, Lslow_path);
  __ isync(); // Order succeeding loads wrt. load of _indices field from cpool_cache.

  // Finally, start loading the value: Get cp cache entry into regs.
  __ ld(Rflags, in_bytes(cp_base_offset) + in_bytes(ConstantPoolCacheEntry::flags_offset()), Rcpool_cache);
  __ ld(Roffset, in_bytes(cp_base_offset) + in_bytes(ConstantPoolCacheEntry::f2_offset()), Rcpool_cache);

  // Following code is from templateTable::getfield_or_static
  // Load pointer to branch table
  __ load_const_optimized(Rbtable, (address)branch_table, Rscratch);

  // Get volatile flag
  __ rldicl(Rscratch, Rflags, 64-ConstantPoolCacheEntry::is_volatile_shift, 63); // extract volatile bit
  // note: sync is needed before volatile load on PPC64

  // Check field type
  __ rldicl(Rflags, Rflags, 64-ConstantPoolCacheEntry::tos_state_shift, 64-ConstantPoolCacheEntry::tos_state_bits);

#ifdef ASSERT
  Label LFlagInvalid;
  __ cmpldi(CCR0, Rflags, number_of_states);
  __ bge(CCR0, LFlagInvalid);

  __ ld(R9_ARG7, 0, R1_SP);
  __ ld(R10_ARG8, 0, R21_sender_SP);
  __ cmpd(CCR0, R9_ARG7, R10_ARG8);
  __ asm_assert_eq("backlink", 0x543);
#endif // ASSERT
  __ mr(R1_SP, R21_sender_SP); // Cut the stack back to where the caller started.

  // Load from branch table and dispatch (volatile case: one instruction ahead)
  __ sldi(Rflags, Rflags, LogBytesPerWord);
  __ cmpwi(CCR6, Rscratch, 1); // volatile?
  if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
    __ sldi(Rscratch, Rscratch, exact_log2(BytesPerInstWord)); // volatile ? size of 1 instruction : 0
  }
  __ ldx(Rbtable, Rbtable, Rflags);

  if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
    __ subf(Rbtable, Rscratch, Rbtable); // point to volatile/non-volatile entry point
  }
  __ mtctr(Rbtable);
  __ bctr();

#ifdef ASSERT
  __ bind(LFlagInvalid);
  __ stop("got invalid flag", 0x6541);

  bool all_uninitialized = true,
       all_initialized   = true;
  for (int i = 0; i<number_of_states; ++i) {
    all_uninitialized = all_uninitialized && (branch_table[i] == NULL);
    all_initialized   = all_initialized   && (branch_table[i] != NULL);
  }
  assert(all_uninitialized != all_initialized, "consistency"); // either or

  __ fence(); // volatile entry point (one instruction before non-volatile_entry point)
  if (branch_table[vtos] == 0) branch_table[vtos] = __ pc(); // non-volatile_entry point
  if (branch_table[dtos] == 0) branch_table[dtos] = __ pc(); // non-volatile_entry point
  if (branch_table[ftos] == 0) branch_table[ftos] = __ pc(); // non-volatile_entry point
  __ stop("unexpected type", 0x6551);
#endif

  if (branch_table[itos] == 0) { // generate only once
    __ align(32, 28, 28); // align load
    __ fence(); // volatile entry point (one instruction before non-volatile_entry point)
    branch_table[itos] = __ pc(); // non-volatile_entry point
    __ lwax(R3_RET, Rclass_or_obj, Roffset);
    __ beq(CCR6, Lacquire);
    __ blr();
  }

  if (branch_table[ltos] == 0) { // generate only once
    __ align(32, 28, 28); // align load
    __ fence(); // volatile entry point (one instruction before non-volatile_entry point)
    branch_table[ltos] = __ pc(); // non-volatile_entry point
    __ ldx(R3_RET, Rclass_or_obj, Roffset);
    __ beq(CCR6, Lacquire);
    __ blr();
  }

  if (branch_table[btos] == 0) { // generate only once
    __ align(32, 28, 28); // align load
    __ fence(); // volatile entry point (one instruction before non-volatile_entry point)
    branch_table[btos] = __ pc(); // non-volatile_entry point
    __ lbzx(R3_RET, Rclass_or_obj, Roffset);
    __ extsb(R3_RET, R3_RET);
    __ beq(CCR6, Lacquire);
    __ blr();
  }

  if (branch_table[ctos] == 0) { // generate only once
    __ align(32, 28, 28); // align load
    __ fence(); // volatile entry point (one instruction before non-volatile_entry point)
    branch_table[ctos] = __ pc(); // non-volatile_entry point
    __ lhzx(R3_RET, Rclass_or_obj, Roffset);
    __ beq(CCR6, Lacquire);
    __ blr();
  }

  if (branch_table[stos] == 0) { // generate only once
    __ align(32, 28, 28); // align load
    __ fence(); // volatile entry point (one instruction before non-volatile_entry point)
    branch_table[stos] = __ pc(); // non-volatile_entry point
    __ lhax(R3_RET, Rclass_or_obj, Roffset);
    __ beq(CCR6, Lacquire);
    __ blr();
  }

  if (branch_table[atos] == 0) { // generate only once
    __ align(32, 28, 28); // align load
    __ fence(); // volatile entry point (one instruction before non-volatile_entry point)
    branch_table[atos] = __ pc(); // non-volatile_entry point
    __ load_heap_oop(R3_RET, (RegisterOrConstant)Roffset, Rclass_or_obj);
    __ verify_oop(R3_RET);
    //__ dcbt(R3_RET); // prefetch
    __ beq(CCR6, Lacquire);
    __ blr();
  }

  __ align(32, 12);
  __ bind(Lacquire);
  __ twi_0(R3_RET);
  __ isync(); // acquire
  __ blr();

#ifdef ASSERT
  for (int i = 0; i<number_of_states; ++i) {
    assert(branch_table[i], "accessor_entry initialization");
    //tty->print_cr("accessor_entry: branch_table[%d] = 0x%llx (opcode 0x%llx)", i, branch_table[i], *((unsigned int*)branch_table[i]));
  }
#endif

  __ bind(Lslow_path);
  __ branch_to_entry(Interpreter::entry_for_kind(Interpreter::zerolocals), Rscratch);
  __ flush();

  return entry;
}