static jlong StrictJarFile_nativeStartIteration(JNIEnv* env, jobject, jlong nativeHandle, jstring prefix) { ScopedUtfChars prefixChars(env, prefix); if (prefixChars.c_str() == NULL) { return static_cast<jlong>(-1); } IterationHandle* handle = new IterationHandle(); int32_t error = 0; if (prefixChars.size() == 0) { error = StartIteration(reinterpret_cast<ZipArchiveHandle>(nativeHandle), handle->CookieAddress(), NULL, NULL); } else { ZipString entry_name(prefixChars.c_str()); error = StartIteration(reinterpret_cast<ZipArchiveHandle>(nativeHandle), handle->CookieAddress(), &entry_name, NULL); } if (error) { throwIoException(env, error); return static_cast<jlong>(-1); } return reinterpret_cast<jlong>(handle); }
const data::list<directory> & directory::get_dirs() const { dirs.clear(); #ifdef WIN32 string wild = full_path + L"*"; WIN32_FIND_DATA data; HANDLE fh = FindFirstFile(wild.w_string(), &data); bool finding = fh != INVALID_HANDLE_VALUE; while (finding) { string entry_name(data.cFileName); if ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0 && entry_name != string(L".") && entry_name != string(L"..")) dirs.append(directory(full_path + string(data.cFileName))); finding = FindNextFile(fh, &data) != 0; } if (fh != INVALID_HANDLE_VALUE) FindClose(fh); #else #error directory::get_dirs() not implemented #endif return dirs; } // directory::get_dirs()
TEST_FIXTURE(CompileFixture, MainEntry) { std::string entry_name("enter_fragment"); CHECK_EQUAL("Enterable_"+entry_name, fmt.get_invoke()); CHECK_EQUAL(1u, fmt.get_function_args("Enterable", entry_name).size()); CHECK_EQUAL(shade::formatter::Constants::void_, fmt.get_function_args("Enterable", entry_name)[0]); CHECK_EQUAL(2u, fmt.get_function_dispatch_args("Enterable", entry_name, 0).size()); CHECK_EQUAL("color", fmt.get_function_dispatch_args("Enterable", entry_name, 0)[0]); CHECK_EQUAL("light", fmt.get_function_dispatch_args("Enterable", entry_name, 0)[1]); CHECK_EQUAL(material_id, fmt.get_function_dispatch("Enterable", entry_name, 0).first); CHECK_EQUAL("Material_fragment_impl", fmt.get_function_dispatch("Enterable", entry_name, 0).second); }
char * do_job(int *fsize, char *inbuf) { /*int fs_type;*/ char *fat_base; char *entrys, *entry; int cluster; int filesize ; char *name; char *fbuf; int cnt, ret; char *pret; // debug ret = mbr_sector_size(inbuf); printf(" [mbr_sector_size] = %u\n", ret); pret = mbr_fat(inbuf); printf(" [mbr_fat] base=0x%x, fat=0x%x, offset=%d\n", (unsigned int)inbuf, (unsigned int)pret, pret - inbuf); ret = mbr_fat_cnt(inbuf); printf(" [mbr_fat_cnt] ret=%u\n", (unsigned)ret); ret = mbr_sectors_peer_fat(inbuf); printf(" [mbr_sectors_peer_fat] ret=%u\n", (unsigned)ret); ret = mbr_sectors_peer_cluster(inbuf); printf(" [mbr_sectors_peer_cluster] = %u\n", (unsigned)ret); pret = mbr_entrys(inbuf); printf(" [mbr_entrys] base=0x%x, entrys=0x%x, offset=%d\n", (unsigned int)inbuf, (unsigned int)pret, pret - inbuf); // debug end // get fat,entry 's address fat_base = mbr_fat(inbuf); printf("fat_base=%d\n", (unsigned)(fat_base - inbuf)); entrys = mbr_entrys(inbuf); printf("entrys=%d\n", (unsigned)(entrys - inbuf)); // value init cluster = -1; filesize = 0; // find uboot entry entry = entrys; while ( entry_is_null(entry) != 1) { name = entry_name(entry); if (strncmp(name, "UBOOT", 5) == 0) { printf("-------------get uboot------------\n"); cluster = entry_cluster(entry); filesize = entry_fsize(entry); break; } entry = entry_next_entry(entry); printf(" entry =%d\n", (entry - entry)); } if (cluster == -1) { printf("can't find file: UBOOT\n"); return NULL; } printf("begin read file\n"); // read uboot fbuf = malloc(filesize); cnt = 0; while (is_endofile(cluster) != 1) { cnt += read_content(fbuf + cnt, inbuf, min(filesize - cnt, cluster_size(inbuf)), cluster); cluster = next_cluster(fat_base, cluster); } *fsize = filesize; return fbuf; }
//------------------------------------------------------------------------------ // MethodHandles::generate_method_handle_stub // // Generate an "entry" field for a method handle. // This determines how the method handle will respond to calls. void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek) { // Here is the register state during an interpreted call, // as set up by generate_method_handle_interpreter_entry(): // - rbx: garbage temp (was MethodHandle.invoke methodOop, unused) // - rcx: receiver method handle // - rax: method handle type (only used by the check_mtype entry point) // - rsi/r13: sender SP (must preserve; see prepare_to_jump_from_interpreted) // - rdx: garbage temp, can blow away const Register rcx_recv = rcx; const Register rax_argslot = rax; const Register rbx_temp = rbx; const Register rdx_temp = rdx; // This guy is set up by prepare_to_jump_from_interpreted (from interpreted calls) // and gen_c2i_adapter (from compiled calls): const Register saved_last_sp = LP64_ONLY(r13) NOT_LP64(rsi); // Argument registers for _raise_exception. // 32-bit: Pass first two oop/int args in registers ECX and EDX. const Register rarg0_code = LP64_ONLY(j_rarg0) NOT_LP64(rcx); const Register rarg1_actual = LP64_ONLY(j_rarg1) NOT_LP64(rdx); const Register rarg2_required = LP64_ONLY(j_rarg2) NOT_LP64(rdi); assert_different_registers(rarg0_code, rarg1_actual, rarg2_required, saved_last_sp); guarantee(java_lang_invoke_MethodHandle::vmentry_offset_in_bytes() != 0, "must have offsets"); // some handy addresses Address rbx_method_fie( rbx, methodOopDesc::from_interpreted_offset() ); Address rbx_method_fce( rbx, methodOopDesc::from_compiled_offset() ); Address rcx_mh_vmtarget( rcx_recv, java_lang_invoke_MethodHandle::vmtarget_offset_in_bytes() ); Address rcx_dmh_vmindex( rcx_recv, java_lang_invoke_DirectMethodHandle::vmindex_offset_in_bytes() ); Address rcx_bmh_vmargslot( rcx_recv, java_lang_invoke_BoundMethodHandle::vmargslot_offset_in_bytes() ); Address rcx_bmh_argument( rcx_recv, java_lang_invoke_BoundMethodHandle::argument_offset_in_bytes() ); Address rcx_amh_vmargslot( rcx_recv, java_lang_invoke_AdapterMethodHandle::vmargslot_offset_in_bytes() ); Address rcx_amh_argument( rcx_recv, java_lang_invoke_AdapterMethodHandle::argument_offset_in_bytes() ); Address rcx_amh_conversion( rcx_recv, java_lang_invoke_AdapterMethodHandle::conversion_offset_in_bytes() ); Address vmarg; // __ argument_address(vmargslot) const int java_mirror_offset = klassOopDesc::klass_part_offset_in_bytes() + Klass::java_mirror_offset_in_bytes(); if (have_entry(ek)) { __ nop(); // empty stubs make SG sick return; } address interp_entry = __ pc(); trace_method_handle(_masm, entry_name(ek)); BLOCK_COMMENT(entry_name(ek)); switch ((int) ek) { case _raise_exception: { // Not a real MH entry, but rather shared code for raising an // exception. Since we use the compiled entry, arguments are // expected in compiler argument registers. assert(raise_exception_method(), "must be set"); assert(raise_exception_method()->from_compiled_entry(), "method must be linked"); const Register rdi_pc = rax; __ pop(rdi_pc); // caller PC __ mov(rsp, saved_last_sp); // cut the stack back to where the caller started Register rbx_method = rbx_temp; Label L_no_method; // FIXME: fill in _raise_exception_method with a suitable java.lang.invoke method __ movptr(rbx_method, ExternalAddress((address) &_raise_exception_method)); __ testptr(rbx_method, rbx_method); __ jccb(Assembler::zero, L_no_method); const int jobject_oop_offset = 0; __ movptr(rbx_method, Address(rbx_method, jobject_oop_offset)); // dereference the jobject __ testptr(rbx_method, rbx_method); __ jccb(Assembler::zero, L_no_method); __ verify_oop(rbx_method); NOT_LP64(__ push(rarg2_required)); __ push(rdi_pc); // restore caller PC __ jmp(rbx_method_fce); // jump to compiled entry // Do something that is at least causes a valid throw from the interpreter. __ bind(L_no_method); __ push(rarg2_required); __ push(rarg1_actual); __ jump(ExternalAddress(Interpreter::throw_WrongMethodType_entry())); } break; case _invokestatic_mh: case _invokespecial_mh: { Register rbx_method = rbx_temp; __ load_heap_oop(rbx_method, rcx_mh_vmtarget); // target is a methodOop __ verify_oop(rbx_method); // same as TemplateTable::invokestatic or invokespecial, // minus the CP setup and profiling: if (ek == _invokespecial_mh) { // Must load & check the first argument before entering the target method. __ load_method_handle_vmslots(rax_argslot, rcx_recv, rdx_temp); __ movptr(rcx_recv, __ argument_address(rax_argslot, -1)); __ null_check(rcx_recv); __ verify_oop(rcx_recv); } __ jmp(rbx_method_fie); } break; case _invokevirtual_mh: { // same as TemplateTable::invokevirtual, // minus the CP setup and profiling: // pick out the vtable index and receiver offset from the MH, // and then we can discard it: __ load_method_handle_vmslots(rax_argslot, rcx_recv, rdx_temp); Register rbx_index = rbx_temp; __ movl(rbx_index, rcx_dmh_vmindex); // Note: The verifier allows us to ignore rcx_mh_vmtarget. __ movptr(rcx_recv, __ argument_address(rax_argslot, -1)); __ null_check(rcx_recv, oopDesc::klass_offset_in_bytes()); // get receiver klass Register rax_klass = rax_argslot; __ load_klass(rax_klass, rcx_recv); __ verify_oop(rax_klass); // get target methodOop & entry point const int base = instanceKlass::vtable_start_offset() * wordSize; assert(vtableEntry::size() * wordSize == wordSize, "adjust the scaling in the code below"); Address vtable_entry_addr(rax_klass, rbx_index, Address::times_ptr, base + vtableEntry::method_offset_in_bytes()); Register rbx_method = rbx_temp; __ movptr(rbx_method, vtable_entry_addr); __ verify_oop(rbx_method); __ jmp(rbx_method_fie); } break; case _invokeinterface_mh: { // same as TemplateTable::invokeinterface, // minus the CP setup and profiling: // pick out the interface and itable index from the MH. __ load_method_handle_vmslots(rax_argslot, rcx_recv, rdx_temp); Register rdx_intf = rdx_temp; Register rbx_index = rbx_temp; __ load_heap_oop(rdx_intf, rcx_mh_vmtarget); __ movl(rbx_index, rcx_dmh_vmindex); __ movptr(rcx_recv, __ argument_address(rax_argslot, -1)); __ null_check(rcx_recv, oopDesc::klass_offset_in_bytes()); // get receiver klass Register rax_klass = rax_argslot; __ load_klass(rax_klass, rcx_recv); __ verify_oop(rax_klass); Register rdi_temp = rdi; Register rbx_method = rbx_index; // get interface klass Label no_such_interface; __ verify_oop(rdx_intf); __ lookup_interface_method(rax_klass, rdx_intf, // note: next two args must be the same: rbx_index, rbx_method, rdi_temp, no_such_interface); __ verify_oop(rbx_method); __ jmp(rbx_method_fie); __ hlt(); __ bind(no_such_interface); // Throw an exception. // For historical reasons, it will be IncompatibleClassChangeError. __ mov(rbx_temp, rcx_recv); // rarg2_required might be RCX assert_different_registers(rarg2_required, rbx_temp); __ movptr(rarg2_required, Address(rdx_intf, java_mirror_offset)); // required interface __ mov( rarg1_actual, rbx_temp); // bad receiver __ movl( rarg0_code, (int) Bytecodes::_invokeinterface); // who is complaining? __ jump(ExternalAddress(from_interpreted_entry(_raise_exception))); } break; case _bound_ref_mh: case _bound_int_mh: case _bound_long_mh: case _bound_ref_direct_mh: case _bound_int_direct_mh: case _bound_long_direct_mh: { bool direct_to_method = (ek >= _bound_ref_direct_mh); BasicType arg_type = T_ILLEGAL; int arg_mask = _INSERT_NO_MASK; int arg_slots = -1; get_ek_bound_mh_info(ek, arg_type, arg_mask, arg_slots); // make room for the new argument: __ movl(rax_argslot, rcx_bmh_vmargslot); __ lea(rax_argslot, __ argument_address(rax_argslot)); insert_arg_slots(_masm, arg_slots * stack_move_unit(), arg_mask, rax_argslot, rbx_temp, rdx_temp); // store bound argument into the new stack slot: __ load_heap_oop(rbx_temp, rcx_bmh_argument); if (arg_type == T_OBJECT) { __ movptr(Address(rax_argslot, 0), rbx_temp); } else { Address prim_value_addr(rbx_temp, java_lang_boxing_object::value_offset_in_bytes(arg_type)); const int arg_size = type2aelembytes(arg_type); __ load_sized_value(rdx_temp, prim_value_addr, arg_size, is_signed_subword_type(arg_type), rbx_temp); __ store_sized_value(Address(rax_argslot, 0), rdx_temp, arg_size, rbx_temp); } if (direct_to_method) { Register rbx_method = rbx_temp; __ load_heap_oop(rbx_method, rcx_mh_vmtarget); __ verify_oop(rbx_method); __ jmp(rbx_method_fie); } else { __ load_heap_oop(rcx_recv, rcx_mh_vmtarget); __ verify_oop(rcx_recv); __ jump_to_method_handle_entry(rcx_recv, rdx_temp); } } break; case _adapter_retype_only: case _adapter_retype_raw: // immediately jump to the next MH layer: __ load_heap_oop(rcx_recv, rcx_mh_vmtarget); __ verify_oop(rcx_recv); __ jump_to_method_handle_entry(rcx_recv, rdx_temp); // This is OK when all parameter types widen. // It is also OK when a return type narrows. break; case _adapter_check_cast: { // temps: Register rbx_klass = rbx_temp; // interesting AMH data // check a reference argument before jumping to the next layer of MH: __ movl(rax_argslot, rcx_amh_vmargslot); vmarg = __ argument_address(rax_argslot); // What class are we casting to? __ load_heap_oop(rbx_klass, rcx_amh_argument); // this is a Class object! __ load_heap_oop(rbx_klass, Address(rbx_klass, java_lang_Class::klass_offset_in_bytes())); Label done; __ movptr(rdx_temp, vmarg); __ testptr(rdx_temp, rdx_temp); __ jcc(Assembler::zero, done); // no cast if null __ load_klass(rdx_temp, rdx_temp); // live at this point: // - rbx_klass: klass required by the target method // - rdx_temp: argument klass to test // - rcx_recv: adapter method handle __ check_klass_subtype(rdx_temp, rbx_klass, rax_argslot, done); // If we get here, the type check failed! // Call the wrong_method_type stub, passing the failing argument type in rax. Register rax_mtype = rax_argslot; __ movl(rax_argslot, rcx_amh_vmargslot); // reload argslot field __ movptr(rdx_temp, vmarg); assert_different_registers(rarg2_required, rdx_temp); __ load_heap_oop(rarg2_required, rcx_amh_argument); // required class __ mov( rarg1_actual, rdx_temp); // bad object __ movl( rarg0_code, (int) Bytecodes::_checkcast); // who is complaining? __ jump(ExternalAddress(from_interpreted_entry(_raise_exception))); __ bind(done); // get the new MH: __ load_heap_oop(rcx_recv, rcx_mh_vmtarget); __ jump_to_method_handle_entry(rcx_recv, rdx_temp); } break; case _adapter_prim_to_prim: case _adapter_ref_to_prim: // handled completely by optimized cases __ stop("init_AdapterMethodHandle should not issue this"); break; case _adapter_opt_i2i: // optimized subcase of adapt_prim_to_prim //case _adapter_opt_f2i: // optimized subcase of adapt_prim_to_prim case _adapter_opt_l2i: // optimized subcase of adapt_prim_to_prim case _adapter_opt_unboxi: // optimized subcase of adapt_ref_to_prim { // perform an in-place conversion to int or an int subword __ movl(rax_argslot, rcx_amh_vmargslot); vmarg = __ argument_address(rax_argslot); switch (ek) { case _adapter_opt_i2i: __ movl(rdx_temp, vmarg); break; case _adapter_opt_l2i: { // just delete the extra slot; on a little-endian machine we keep the first __ lea(rax_argslot, __ argument_address(rax_argslot, 1)); remove_arg_slots(_masm, -stack_move_unit(), rax_argslot, rbx_temp, rdx_temp); vmarg = Address(rax_argslot, -Interpreter::stackElementSize); __ movl(rdx_temp, vmarg); } break; case _adapter_opt_unboxi: { // Load the value up from the heap. __ movptr(rdx_temp, vmarg); int value_offset = java_lang_boxing_object::value_offset_in_bytes(T_INT); #ifdef ASSERT for (int bt = T_BOOLEAN; bt < T_INT; bt++) { if (is_subword_type(BasicType(bt))) assert(value_offset == java_lang_boxing_object::value_offset_in_bytes(BasicType(bt)), ""); } #endif __ null_check(rdx_temp, value_offset); __ movl(rdx_temp, Address(rdx_temp, value_offset)); // We load this as a word. Because we are little-endian, // the low bits will be correct, but the high bits may need cleaning. // The vminfo will guide us to clean those bits. } break; default: ShouldNotReachHere(); } // Do the requested conversion and store the value. Register rbx_vminfo = rbx_temp; __ movl(rbx_vminfo, rcx_amh_conversion); assert(CONV_VMINFO_SHIFT == 0, "preshifted"); // get the new MH: __ load_heap_oop(rcx_recv, rcx_mh_vmtarget); // (now we are done with the old MH) // original 32-bit vmdata word must be of this form: // | MBZ:6 | signBitCount:8 | srcDstTypes:8 | conversionOp:8 | __ xchgptr(rcx, rbx_vminfo); // free rcx for shifts __ shll(rdx_temp /*, rcx*/); Label zero_extend, done; __ testl(rcx, CONV_VMINFO_SIGN_FLAG); __ jccb(Assembler::zero, zero_extend); // this path is taken for int->byte, int->short __ sarl(rdx_temp /*, rcx*/); __ jmpb(done); __ bind(zero_extend); // this is taken for int->char __ shrl(rdx_temp /*, rcx*/); __ bind(done); __ movl(vmarg, rdx_temp); // Store the value. __ xchgptr(rcx, rbx_vminfo); // restore rcx_recv __ jump_to_method_handle_entry(rcx_recv, rdx_temp); } break; case _adapter_opt_i2l: // optimized subcase of adapt_prim_to_prim case _adapter_opt_unboxl: // optimized subcase of adapt_ref_to_prim { // perform an in-place int-to-long or ref-to-long conversion __ movl(rax_argslot, rcx_amh_vmargslot); // on a little-endian machine we keep the first slot and add another after __ lea(rax_argslot, __ argument_address(rax_argslot, 1)); insert_arg_slots(_masm, stack_move_unit(), _INSERT_INT_MASK, rax_argslot, rbx_temp, rdx_temp); Address vmarg1(rax_argslot, -Interpreter::stackElementSize); Address vmarg2 = vmarg1.plus_disp(Interpreter::stackElementSize); switch (ek) { case _adapter_opt_i2l: { #ifdef _LP64 __ movslq(rdx_temp, vmarg1); // Load sign-extended __ movq(vmarg1, rdx_temp); // Store into first slot #else __ movl(rdx_temp, vmarg1); __ sarl(rdx_temp, BitsPerInt - 1); // __ extend_sign() __ movl(vmarg2, rdx_temp); // store second word #endif } break; case _adapter_opt_unboxl: { // Load the value up from the heap. __ movptr(rdx_temp, vmarg1); int value_offset = java_lang_boxing_object::value_offset_in_bytes(T_LONG); assert(value_offset == java_lang_boxing_object::value_offset_in_bytes(T_DOUBLE), ""); __ null_check(rdx_temp, value_offset); #ifdef _LP64 __ movq(rbx_temp, Address(rdx_temp, value_offset)); __ movq(vmarg1, rbx_temp); #else __ movl(rbx_temp, Address(rdx_temp, value_offset + 0*BytesPerInt)); __ movl(rdx_temp, Address(rdx_temp, value_offset + 1*BytesPerInt)); __ movl(vmarg1, rbx_temp); __ movl(vmarg2, rdx_temp); #endif } break; default: ShouldNotReachHere(); } __ load_heap_oop(rcx_recv, rcx_mh_vmtarget); __ jump_to_method_handle_entry(rcx_recv, rdx_temp); } break; case _adapter_opt_f2d: // optimized subcase of adapt_prim_to_prim case _adapter_opt_d2f: // optimized subcase of adapt_prim_to_prim { // perform an in-place floating primitive conversion __ movl(rax_argslot, rcx_amh_vmargslot); __ lea(rax_argslot, __ argument_address(rax_argslot, 1)); if (ek == _adapter_opt_f2d) { insert_arg_slots(_masm, stack_move_unit(), _INSERT_INT_MASK, rax_argslot, rbx_temp, rdx_temp); } Address vmarg(rax_argslot, -Interpreter::stackElementSize); #ifdef _LP64 if (ek == _adapter_opt_f2d) { __ movflt(xmm0, vmarg); __ cvtss2sd(xmm0, xmm0); __ movdbl(vmarg, xmm0); } else { __ movdbl(xmm0, vmarg); __ cvtsd2ss(xmm0, xmm0); __ movflt(vmarg, xmm0); } #else //_LP64 if (ek == _adapter_opt_f2d) { __ fld_s(vmarg); // load float to ST0 __ fstp_s(vmarg); // store single } else { __ fld_d(vmarg); // load double to ST0 __ fstp_s(vmarg); // store single } #endif //_LP64 if (ek == _adapter_opt_d2f) { remove_arg_slots(_masm, -stack_move_unit(), rax_argslot, rbx_temp, rdx_temp); } __ load_heap_oop(rcx_recv, rcx_mh_vmtarget); __ jump_to_method_handle_entry(rcx_recv, rdx_temp); } break; case _adapter_prim_to_ref: __ unimplemented(entry_name(ek)); // %%% FIXME: NYI break; case _adapter_swap_args: case _adapter_rot_args: // handled completely by optimized cases __ stop("init_AdapterMethodHandle should not issue this"); break; case _adapter_opt_swap_1: case _adapter_opt_swap_2: case _adapter_opt_rot_1_up: case _adapter_opt_rot_1_down: case _adapter_opt_rot_2_up: case _adapter_opt_rot_2_down: { int swap_bytes = 0, rotate = 0; get_ek_adapter_opt_swap_rot_info(ek, swap_bytes, rotate); // 'argslot' is the position of the first argument to swap __ movl(rax_argslot, rcx_amh_vmargslot); __ lea(rax_argslot, __ argument_address(rax_argslot)); // 'vminfo' is the second Register rbx_destslot = rbx_temp; __ movl(rbx_destslot, rcx_amh_conversion); assert(CONV_VMINFO_SHIFT == 0, "preshifted"); __ andl(rbx_destslot, CONV_VMINFO_MASK); __ lea(rbx_destslot, __ argument_address(rbx_destslot)); DEBUG_ONLY(verify_argslot(_masm, rbx_destslot, "swap point must fall within current frame")); if (!rotate) { for (int i = 0; i < swap_bytes; i += wordSize) { __ movptr(rdx_temp, Address(rax_argslot , i)); __ push(rdx_temp); __ movptr(rdx_temp, Address(rbx_destslot, i)); __ movptr(Address(rax_argslot, i), rdx_temp); __ pop(rdx_temp); __ movptr(Address(rbx_destslot, i), rdx_temp); } } else { // push the first chunk, which is going to get overwritten for (int i = swap_bytes; (i -= wordSize) >= 0; ) { __ movptr(rdx_temp, Address(rax_argslot, i)); __ push(rdx_temp); } if (rotate > 0) { // rotate upward __ subptr(rax_argslot, swap_bytes); #ifdef ASSERT { // Verify that argslot > destslot, by at least swap_bytes. Label L_ok; __ cmpptr(rax_argslot, rbx_destslot); __ jccb(Assembler::aboveEqual, L_ok); __ stop("source must be above destination (upward rotation)"); __ bind(L_ok); } #endif // work argslot down to destslot, copying contiguous data upwards // pseudo-code: // rax = src_addr - swap_bytes // rbx = dest_addr // while (rax >= rbx) *(rax + swap_bytes) = *(rax + 0), rax--; Label loop; __ bind(loop); __ movptr(rdx_temp, Address(rax_argslot, 0)); __ movptr(Address(rax_argslot, swap_bytes), rdx_temp); __ addptr(rax_argslot, -wordSize); __ cmpptr(rax_argslot, rbx_destslot); __ jccb(Assembler::aboveEqual, loop); } else { __ addptr(rax_argslot, swap_bytes); #ifdef ASSERT { // Verify that argslot < destslot, by at least swap_bytes. Label L_ok; __ cmpptr(rax_argslot, rbx_destslot); __ jccb(Assembler::belowEqual, L_ok); __ stop("source must be below destination (downward rotation)"); __ bind(L_ok); } #endif // work argslot up to destslot, copying contiguous data downwards // pseudo-code: // rax = src_addr + swap_bytes // rbx = dest_addr // while (rax <= rbx) *(rax - swap_bytes) = *(rax + 0), rax++; Label loop; __ bind(loop); __ movptr(rdx_temp, Address(rax_argslot, 0)); __ movptr(Address(rax_argslot, -swap_bytes), rdx_temp); __ addptr(rax_argslot, wordSize); __ cmpptr(rax_argslot, rbx_destslot); __ jccb(Assembler::belowEqual, loop); } // pop the original first chunk into the destination slot, now free for (int i = 0; i < swap_bytes; i += wordSize) { __ pop(rdx_temp); __ movptr(Address(rbx_destslot, i), rdx_temp); } } __ load_heap_oop(rcx_recv, rcx_mh_vmtarget); __ jump_to_method_handle_entry(rcx_recv, rdx_temp); } break; case _adapter_dup_args: { // 'argslot' is the position of the first argument to duplicate __ movl(rax_argslot, rcx_amh_vmargslot); __ lea(rax_argslot, __ argument_address(rax_argslot)); // 'stack_move' is negative number of words to duplicate Register rdx_stack_move = rdx_temp; __ movl2ptr(rdx_stack_move, rcx_amh_conversion); __ sarptr(rdx_stack_move, CONV_STACK_MOVE_SHIFT); int argslot0_num = 0; Address argslot0 = __ argument_address(RegisterOrConstant(argslot0_num)); assert(argslot0.base() == rsp, ""); int pre_arg_size = argslot0.disp(); assert(pre_arg_size % wordSize == 0, ""); assert(pre_arg_size > 0, "must include PC"); // remember the old rsp+1 (argslot[0]) Register rbx_oldarg = rbx_temp; __ lea(rbx_oldarg, argslot0); // move rsp down to make room for dups __ lea(rsp, Address(rsp, rdx_stack_move, Address::times_ptr)); // compute the new rsp+1 (argslot[0]) Register rdx_newarg = rdx_temp; __ lea(rdx_newarg, argslot0); __ push(rdi); // need a temp // (preceding push must be done after arg addresses are taken!) // pull down the pre_arg_size data (PC) for (int i = -pre_arg_size; i < 0; i += wordSize) { __ movptr(rdi, Address(rbx_oldarg, i)); __ movptr(Address(rdx_newarg, i), rdi); } // copy from rax_argslot[0...] down to new_rsp[1...] // pseudo-code: // rbx = old_rsp+1 // rdx = new_rsp+1 // rax = argslot // while (rdx < rbx) *rdx++ = *rax++ Label loop; __ bind(loop); __ movptr(rdi, Address(rax_argslot, 0)); __ movptr(Address(rdx_newarg, 0), rdi); __ addptr(rax_argslot, wordSize); __ addptr(rdx_newarg, wordSize); __ cmpptr(rdx_newarg, rbx_oldarg); __ jccb(Assembler::less, loop); __ pop(rdi); // restore temp __ load_heap_oop(rcx_recv, rcx_mh_vmtarget); __ jump_to_method_handle_entry(rcx_recv, rdx_temp); } break; case _adapter_drop_args: { // 'argslot' is the position of the first argument to nuke __ movl(rax_argslot, rcx_amh_vmargslot); __ lea(rax_argslot, __ argument_address(rax_argslot)); __ push(rdi); // need a temp // (must do previous push after argslot address is taken) // 'stack_move' is number of words to drop Register rdi_stack_move = rdi; __ movl2ptr(rdi_stack_move, rcx_amh_conversion); __ sarptr(rdi_stack_move, CONV_STACK_MOVE_SHIFT); remove_arg_slots(_masm, rdi_stack_move, rax_argslot, rbx_temp, rdx_temp); __ pop(rdi); // restore temp __ load_heap_oop(rcx_recv, rcx_mh_vmtarget); __ jump_to_method_handle_entry(rcx_recv, rdx_temp); } break; case _adapter_collect_args: __ unimplemented(entry_name(ek)); // %%% FIXME: NYI break; case _adapter_spread_args: // handled completely by optimized cases __ stop("init_AdapterMethodHandle should not issue this"); break; case _adapter_opt_spread_0: case _adapter_opt_spread_1: case _adapter_opt_spread_more: { // spread an array out into a group of arguments int length_constant = get_ek_adapter_opt_spread_info(ek); // find the address of the array argument __ movl(rax_argslot, rcx_amh_vmargslot); __ lea(rax_argslot, __ argument_address(rax_argslot)); // grab some temps { __ push(rsi); __ push(rdi); } // (preceding pushes must be done after argslot address is taken!) #define UNPUSH_RSI_RDI \ { __ pop(rdi); __ pop(rsi); } // arx_argslot points both to the array and to the first output arg vmarg = Address(rax_argslot, 0); // Get the array value. Register rsi_array = rsi; Register rdx_array_klass = rdx_temp; BasicType elem_type = T_OBJECT; int length_offset = arrayOopDesc::length_offset_in_bytes(); int elem0_offset = arrayOopDesc::base_offset_in_bytes(elem_type); __ movptr(rsi_array, vmarg); Label skip_array_check; if (length_constant == 0) { __ testptr(rsi_array, rsi_array); __ jcc(Assembler::zero, skip_array_check); } __ null_check(rsi_array, oopDesc::klass_offset_in_bytes()); __ load_klass(rdx_array_klass, rsi_array); // Check the array type. Register rbx_klass = rbx_temp; __ load_heap_oop(rbx_klass, rcx_amh_argument); // this is a Class object! __ load_heap_oop(rbx_klass, Address(rbx_klass, java_lang_Class::klass_offset_in_bytes())); Label ok_array_klass, bad_array_klass, bad_array_length; __ check_klass_subtype(rdx_array_klass, rbx_klass, rdi, ok_array_klass); // If we get here, the type check failed! __ jmp(bad_array_klass); __ bind(ok_array_klass); // Check length. if (length_constant >= 0) { __ cmpl(Address(rsi_array, length_offset), length_constant); } else { Register rbx_vminfo = rbx_temp; __ movl(rbx_vminfo, rcx_amh_conversion); assert(CONV_VMINFO_SHIFT == 0, "preshifted"); __ andl(rbx_vminfo, CONV_VMINFO_MASK); __ cmpl(rbx_vminfo, Address(rsi_array, length_offset)); } __ jcc(Assembler::notEqual, bad_array_length); Register rdx_argslot_limit = rdx_temp; // Array length checks out. Now insert any required stack slots. if (length_constant == -1) { // Form a pointer to the end of the affected region. __ lea(rdx_argslot_limit, Address(rax_argslot, Interpreter::stackElementSize)); // 'stack_move' is negative number of words to insert Register rdi_stack_move = rdi; __ movl2ptr(rdi_stack_move, rcx_amh_conversion); __ sarptr(rdi_stack_move, CONV_STACK_MOVE_SHIFT); Register rsi_temp = rsi_array; // spill this insert_arg_slots(_masm, rdi_stack_move, -1, rax_argslot, rbx_temp, rsi_temp); // reload the array (since rsi was killed) __ movptr(rsi_array, vmarg); } else if (length_constant > 1) { int arg_mask = 0; int new_slots = (length_constant - 1); for (int i = 0; i < new_slots; i++) { arg_mask <<= 1; arg_mask |= _INSERT_REF_MASK; } insert_arg_slots(_masm, new_slots * stack_move_unit(), arg_mask, rax_argslot, rbx_temp, rdx_temp); } else if (length_constant == 1) { // no stack resizing required } else if (length_constant == 0) { remove_arg_slots(_masm, -stack_move_unit(), rax_argslot, rbx_temp, rdx_temp); } // Copy from the array to the new slots. // Note: Stack change code preserves integrity of rax_argslot pointer. // So even after slot insertions, rax_argslot still points to first argument. if (length_constant == -1) { // [rax_argslot, rdx_argslot_limit) is the area we are inserting into. Register rsi_source = rsi_array; __ lea(rsi_source, Address(rsi_array, elem0_offset)); Label loop; __ bind(loop); __ movptr(rbx_temp, Address(rsi_source, 0)); __ movptr(Address(rax_argslot, 0), rbx_temp); __ addptr(rsi_source, type2aelembytes(elem_type)); __ addptr(rax_argslot, Interpreter::stackElementSize); __ cmpptr(rax_argslot, rdx_argslot_limit); __ jccb(Assembler::less, loop); } else if (length_constant == 0) { __ bind(skip_array_check); // nothing to copy } else { int elem_offset = elem0_offset; int slot_offset = 0; for (int index = 0; index < length_constant; index++) { __ movptr(rbx_temp, Address(rsi_array, elem_offset)); __ movptr(Address(rax_argslot, slot_offset), rbx_temp); elem_offset += type2aelembytes(elem_type); slot_offset += Interpreter::stackElementSize; } } // Arguments are spread. Move to next method handle. UNPUSH_RSI_RDI; __ load_heap_oop(rcx_recv, rcx_mh_vmtarget); __ jump_to_method_handle_entry(rcx_recv, rdx_temp); __ bind(bad_array_klass); UNPUSH_RSI_RDI; assert(!vmarg.uses(rarg2_required), "must be different registers"); __ movptr(rarg2_required, Address(rdx_array_klass, java_mirror_offset)); // required type __ movptr(rarg1_actual, vmarg); // bad array __ movl( rarg0_code, (int) Bytecodes::_aaload); // who is complaining? __ jump(ExternalAddress(from_interpreted_entry(_raise_exception))); __ bind(bad_array_length); UNPUSH_RSI_RDI; assert(!vmarg.uses(rarg2_required), "must be different registers"); __ mov (rarg2_required, rcx_recv); // AMH requiring a certain length __ movptr(rarg1_actual, vmarg); // bad array __ movl( rarg0_code, (int) Bytecodes::_arraylength); // who is complaining? __ jump(ExternalAddress(from_interpreted_entry(_raise_exception))); #undef UNPUSH_RSI_RDI } break; case _adapter_flyby: case _adapter_ricochet: __ unimplemented(entry_name(ek)); // %%% FIXME: NYI break; default: ShouldNotReachHere(); } __ hlt(); address me_cookie = MethodHandleEntry::start_compiled_entry(_masm, interp_entry); __ unimplemented(entry_name(ek)); // %%% FIXME: NYI init_entry(ek, MethodHandleEntry::finish_compiled_entry(_masm, me_cookie)); }