Example #1
0
// Code generation
address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* _masm) {
  // I5_savedSP: sender SP (must preserve)
  // G4 (Gargs): incoming argument list (must preserve)
  // G5_method:  invoke methodOop; becomes method type.
  // G3_method_handle: receiver method handle (must load from sp[MethodTypeForm.vmslots])
  // O0, O1: garbage temps, blown away
  Register O0_argslot = O0;
  Register O1_scratch = O1;

  // emit WrongMethodType path first, to enable back-branch from main path
  Label wrong_method_type;
  __ bind(wrong_method_type);
  __ jump_to(AddressLiteral(Interpreter::throw_WrongMethodType_entry()), O1_scratch);
  __ delayed()->nop();

  // here's where control starts out:
  __ align(CodeEntryAlignment);
  address entry_point = __ pc();

  // fetch the MethodType from the method handle into G5_method_type
  {
    Register tem = G5_method;
    assert(tem == G5_method_type, "yes, it's the same register");
    for (jint* pchase = methodOopDesc::method_type_offsets_chain(); (*pchase) != -1; pchase++) {
      __ ld_ptr(Address(tem, *pchase), G5_method_type);
    }
  }

  // given the MethodType, find out where the MH argument is buried
  __ ld_ptr(Address(G5_method_type, __ delayed_value(java_dyn_MethodType::form_offset_in_bytes, O1_scratch)),        O0_argslot);
  __ ldsw(  Address(O0_argslot,     __ delayed_value(java_dyn_MethodTypeForm::vmslots_offset_in_bytes, O1_scratch)), O0_argslot);
  __ ld_ptr(__ argument_address(O0_argslot), G3_method_handle);

  __ check_method_handle_type(G5_method_type, G3_method_handle, O1_scratch, wrong_method_type);
  __ jump_to_method_handle_entry(G3_method_handle, O1_scratch);

  return entry_point;
}
Example #2
0
		T operator()() { return delayed_value(); }
Example #3
0
		T operator()( const T& value, float delta_time ) { add_sample( value, delta_time ); return delayed_value(); }
Example #4
0
// Code generation
address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* _masm) {
  // rbx: methodOop
  // rcx: receiver method handle (must load from sp[MethodTypeForm.vmslots])
  // rsi/r13: sender SP (must preserve; see prepare_to_jump_from_interpreted)
  // rdx, rdi: garbage temp, blown away

  Register rbx_method = rbx;
  Register rcx_recv   = rcx;
  Register rax_mtype  = rax;
  Register rdx_temp   = rdx;
  Register rdi_temp   = rdi;

  // emit WrongMethodType path first, to enable jccb back-branch from main path
  Label wrong_method_type;
  __ bind(wrong_method_type);
  Label invoke_generic_slow_path;
  assert(methodOopDesc::intrinsic_id_size_in_bytes() == sizeof(u1), "");;
  __ cmpb(Address(rbx_method, methodOopDesc::intrinsic_id_offset_in_bytes()), (int) vmIntrinsics::_invokeExact);
  __ jcc(Assembler::notEqual, invoke_generic_slow_path);
  __ push(rax_mtype);       // required mtype
  __ push(rcx_recv);        // bad mh (1st stacked argument)
  __ jump(ExternalAddress(Interpreter::throw_WrongMethodType_entry()));

  // here's where control starts out:
  __ align(CodeEntryAlignment);
  address entry_point = __ pc();

  // fetch the MethodType from the method handle into rax (the 'check' register)
  {
    Register tem = rbx_method;
    for (jint* pchase = methodOopDesc::method_type_offsets_chain(); (*pchase) != -1; pchase++) {
      __ movptr(rax_mtype, Address(tem, *pchase));
      tem = rax_mtype;          // in case there is another indirection
    }
  }

  // given the MethodType, find out where the MH argument is buried
  __ load_heap_oop(rdx_temp, Address(rax_mtype, __ delayed_value(java_lang_invoke_MethodType::form_offset_in_bytes, rdi_temp)));
  Register rdx_vmslots = rdx_temp;
  __ movl(rdx_vmslots, Address(rdx_temp, __ delayed_value(java_lang_invoke_MethodTypeForm::vmslots_offset_in_bytes, rdi_temp)));
  __ movptr(rcx_recv, __ argument_address(rdx_vmslots));

  trace_method_handle(_masm, "invokeExact");

  __ check_method_handle_type(rax_mtype, rcx_recv, rdi_temp, wrong_method_type);
  __ jump_to_method_handle_entry(rcx_recv, rdi_temp);

  // for invokeGeneric (only), apply argument and result conversions on the fly
  __ bind(invoke_generic_slow_path);
#ifdef ASSERT
  { Label L;
    __ cmpb(Address(rbx_method, methodOopDesc::intrinsic_id_offset_in_bytes()), (int) vmIntrinsics::_invokeGeneric);
    __ jcc(Assembler::equal, L);
    __ stop("bad methodOop::intrinsic_id");
    __ bind(L);
  }
#endif //ASSERT
  Register rbx_temp = rbx_method;  // don't need it now

  // make room on the stack for another pointer:
  Register rcx_argslot = rcx_recv;
  __ lea(rcx_argslot, __ argument_address(rdx_vmslots, 1));
  insert_arg_slots(_masm, 2 * stack_move_unit(), _INSERT_REF_MASK,
                   rcx_argslot, rbx_temp, rdx_temp);

  // load up an adapter from the calling type (Java weaves this)
  __ load_heap_oop(rdx_temp, Address(rax_mtype, __ delayed_value(java_lang_invoke_MethodType::form_offset_in_bytes, rdi_temp)));
  Register rdx_adapter = rdx_temp;
  // __ load_heap_oop(rdx_adapter, Address(rdx_temp, java_lang_invoke_MethodTypeForm::genericInvoker_offset_in_bytes()));
  // deal with old JDK versions:
  __ lea(rdi_temp, Address(rdx_temp, __ delayed_value(java_lang_invoke_MethodTypeForm::genericInvoker_offset_in_bytes, rdi_temp)));
  __ cmpptr(rdi_temp, rdx_temp);
  Label sorry_no_invoke_generic;
  __ jcc(Assembler::below, sorry_no_invoke_generic);

  __ load_heap_oop(rdx_adapter, Address(rdi_temp, 0));
  __ testptr(rdx_adapter, rdx_adapter);
  __ jcc(Assembler::zero, sorry_no_invoke_generic);
  __ movptr(Address(rcx_argslot, 1 * Interpreter::stackElementSize), rdx_adapter);
  // As a trusted first argument, pass the type being called, so the adapter knows
  // the actual types of the arguments and return values.
  // (Generic invokers are shared among form-families of method-type.)
  __ movptr(Address(rcx_argslot, 0 * Interpreter::stackElementSize), rax_mtype);
  // FIXME: assert that rdx_adapter is of the right method-type.
  __ mov(rcx, rdx_adapter);
  trace_method_handle(_masm, "invokeGeneric");
  __ jump_to_method_handle_entry(rcx, rdi_temp);

  __ bind(sorry_no_invoke_generic); // no invokeGeneric implementation available!
  __ movptr(rcx_recv, Address(rcx_argslot, -1 * Interpreter::stackElementSize));  // recover original MH
  __ push(rax_mtype);       // required mtype
  __ push(rcx_recv);        // bad mh (1st stacked argument)
  __ jump(ExternalAddress(Interpreter::throw_WrongMethodType_entry()));

  return entry_point;
}