stubGenerator_x86_64.cpp revision 362
196N/A * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. 0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 0N/A * This code is free software; you can redistribute it and/or modify it 0N/A * under the terms of the GNU General Public License version 2 only, as 0N/A * published by the Free Software Foundation. 0N/A * This code is distributed in the hope that it will be useful, but WITHOUT 0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 0N/A * version 2 for more details (a copy is included in the LICENSE file that 0N/A * accompanied this code). 0N/A * You should have received a copy of the GNU General Public License version 0N/A * 2 along with this work; if not, write to the Free Software Foundation, 0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 0N/A * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 0N/A * CA 95054 USA or visit www.sun.com if you need additional information or 0N/A * have any questions. 0N/A#
include "incls/_precompiled.incl" 0N/A// Declaration and definition of StubGenerator (no .hpp file). 0N/A// For a more detailed description of the stub routine structure 0N/A// Stub Code definitions 0N/A // pc is the instruction which we must emulate 0N/A // doing a no-op is fine: return garbage from the load 0N/A // therefore, compute npc 0N/A // request an async exception 0N/A // return address of next instruction to execute 0N/A // Call stubs are used to call Java from C 0N/A // c_rarg0: call wrapper address address 0N/A // c_rarg1: result address 0N/A // c_rarg2: result type BasicType 0N/A // c_rarg3: method methodOop 0N/A // c_rarg4: (interpreter) entry point address 0N/A // c_rarg5: parameters intptr_t* 0N/A // 16(rbp): parameter size (in words) int 0N/A // 24(rbp): thread Thread* 0N/A // [ return_from_Java ] <--- rsp 0N/A // [ argument word n ] 0N/A // -12 [ argument word 1 ] 0N/A // -11 [ saved r15 ] <--- rsp_after_call 0N/A // -10 [ saved r14 ] 0N/A // -6 [ call wrapper ] 0N/A // -4 [ result type ] 0N/A // -2 [ entry point ] 0N/A // -1 [ parameters ] 0N/A // 0 [ saved rbp ] <--- rbp 0N/A // 1 [ return address ] 0N/A // 2 [ parameter size ] 0N/A // Windows Arguments: 0N/A // c_rarg0: call wrapper address address 0N/A // c_rarg1: result address 0N/A // c_rarg2: result type BasicType 0N/A // c_rarg3: method methodOop 0N/A // 48(rbp): (interpreter) entry point address 0N/A // 56(rbp): parameters intptr_t* 0N/A // 64(rbp): parameter size (in words) int 0N/A // 72(rbp): thread Thread* 0N/A // [ return_from_Java ] <--- rsp 0N/A // [ argument word n ] 0N/A // -8 [ argument word 1 ] 0N/A // -7 [ saved r15 ] <--- rsp_after_call 0N/A // 0 [ saved rbp ] <--- rbp 0N/A // 1 [ return address ] 0N/A // 2 [ call wrapper ] 0N/A // 4 [ result type ] 0N/A // 6 [ entry point ] 0N/A // 8 [ parameter size ] 0N/A // Windows reserves the callers stack space for arguments 1-4. 0N/A // We spill c_rarg0-c_rarg3 to this space. 0N/A // Call stub stack layout word offsets from rbp 0N/A "adjust this code");
0N/A // same as in generate_catch_exception()! 0N/A // same as in generate_catch_exception()! 0N/A // save register parameters 0N/A // save regs belonging to calling function 0N/A // Load up thread register 0N/A // make sure we have no pending exceptions 0N/A __ stop(
"StubRoutines::call_stub: entered with pending exception");
0N/A // pass parameters if any 0N/A // call Java function 0N/A // store result depending on type (everything that is not 0N/A // T_OBJECT, T_LONG, T_FLOAT or T_DOUBLE is treated as T_INT) 0N/A // handle T_INT case 0N/A // verify that threads correspond 0N/A __ stop(
"StubRoutines::call_stub: threads must correspond");
0N/A // restore regs belonging to calling function 0N/A // handle return types different from T_INT 0N/A // Return point for a Java call if there's an exception thrown in 0N/A // Java code. The exception is caught and transformed into a 0N/A // pending exception stored in JavaThread that can be tested from 0N/A // Note: Usually the parameters are removed by the callee. In case 0N/A // of an exception crossing an activation frame boundary, that is 0N/A // not the case if the callee is compiled code => need to setup the 0N/A // rax: exception oop 0N/A // same as in generate_call_stub(): 0N/A // verify that threads correspond 0N/A __ stop(
"StubRoutines::catch_exception: threads must correspond");
0N/A // set pending exception 0N/A // complete return to VM 0N/A "_call_stub_return_address must have been generated before");
0N/A // Continuation point for runtime calls returning with a pending 0N/A // exception. The pending exception check happened in the runtime 0N/A // or native call stub. The pending exception in Thread is 0N/A // converted into a Java-level exception. 0N/A // Contract with Java-level exception handlers: 0N/A // NOTE: At entry of this stub, exception-pc must be on stack !! 0N/A // Upon entry, the sp points to the return address returning into 0N/A // Java (interpreted or compiled) code; i.e., the return address 0N/A // becomes the throwing pc. 0N/A // Arguments pushed before the runtime call are still on the stack 0N/A // but the exception handler will reset the stack pointer -> 0N/A // ignore them. A potential result in registers can be ignored as 0N/A // make sure this code is only executed if there is a pending exception 0N/A __ stop(
"StubRoutines::forward exception: no pending exception (1)");
0N/A // compute exception handler into rbx 0N/A // setup rax & rdx, remove return address & clear pending exception 0N/A // make sure exception is set 0N/A __ stop(
"StubRoutines::forward exception: no pending exception (2)");
0N/A // continue at exception handler (return address removed) 0N/A // rbx: exception handler 0N/A // Support for jint atomic::xchg(jint exchange_value, volatile jint* dest) 0N/A // c_rarg0: exchange_value 0N/A // *dest <- ex, return (orig *dest) 0N/A // Support for intptr_t atomic::xchg_ptr(intptr_t exchange_value, volatile intptr_t* dest) 0N/A // c_rarg0: exchange_value 0N/A // *dest <- ex, return (orig *dest) 0N/A // Support for jint atomic::atomic_cmpxchg(jint exchange_value, volatile jint* dest, 0N/A // jint compare_value) 0N/A // c_rarg0: exchange_value 0N/A // c_rarg2: compare_value 0N/A // if ( compare_value == *dest ) { 0N/A // *dest = exchange_value 0N/A // return compare_value; 0N/A // Support for jint atomic::atomic_cmpxchg_long(jlong exchange_value, 0N/A // volatile jlong* dest, 0N/A // jlong compare_value) 0N/A // c_rarg0: exchange_value 0N/A // c_rarg2: compare_value 0N/A // if ( compare_value == *dest ) { 0N/A // *dest = exchange_value 0N/A // return compare_value; 0N/A // Support for jint atomic::add(jint add_value, volatile jint* dest) 0N/A // c_rarg0: add_value 0N/A // *dest += add_value 0N/A // Support for intptr_t atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest) 0N/A // c_rarg0: add_value 0N/A // *dest += add_value 0N/A // Support for intptr_t OrderAccess::fence() 0N/A // Support for intptr_t get_previous_fp() 0N/A // This routine is used to find the previous frame pointer for the 0N/A // caller (current_frame_guess). This is used as part of debugging 0N/A // ps() is seemingly lost trying to find frames. 0N/A // This code assumes that caller current_frame_guess) has a frame. 0N/A //---------------------------------------------------------------------------------------------------- 0N/A // Support for void verify_mxcsr() 0N/A // This routine is used with -Xcheck:jni to verify that native 0N/A // JNI code does not return to Java code without restoring the 0N/A // MXCSR register to our expected state. 0N/A __ warn(
"MXCSR changed by native JNI code, use -XX:+RestoreMXCSROnJNICall");
0N/A // The following routine generates a subroutine to throw an 0N/A // asynchronous UnknownError when an unsafe access gets a fault that 0N/A // could not be reasonably prevented by the programmer. (Example: 0N/A // Non-destructive plausibility checks for oops 0N/A // all args on stack! 0N/A // Stack after saving c_rarg3: 0N/A // [tos + 0]: saved c_rarg3 0N/A // [tos + 1]: saved c_rarg2 124N/A // [tos + 2]: saved r12 (several TemplateTable methods use it) 124N/A // [tos + 3]: saved flags 124N/A // [tos + 4]: return address 124N/A // * [tos + 5]: error message (char*) 124N/A // * [tos + 6]: object to verify (oop) 124N/A // * [tos + 7]: saved rax - saved by caller and bashed 0N/A // * = popped on exit 0N/A // save c_rarg2 and c_rarg3 124N/A // After previous pushes. 124N/A // Before the call to MacroAssembler::debug(), see below. 0N/A // make sure object is 'reasonable' 0N/A // Check if the oop is in the right area of memory 124N/A // set r12 to heapbase for load_klass() 0N/A // make sure klass is 'reasonable' 0N/A // Check if the klass is in the right area of memory 0N/A // make sure klass' klass is 'reasonable' 0N/A // Check if the klass' klass is in the right area of memory 0N/A // return if everything seems ok 124N/A // debug(char* msg, int64_t pc, int64_t regs[]) 0N/A // We've popped the registers we'd saved (c_rarg3, c_rarg2 and flags), and 0N/A // pushed all the registers, so now the stack looks like: 0N/A // [tos + 0] 16 saved registers 0N/A // [tos + 16] return address 124N/A // * [tos + 17] error message (char*) 124N/A // * [tos + 18] object to verify (oop) 124N/A // * [tos + 19] saved rax - saved by caller and bashed 0N/A // Verify that a register contains clean 32-bits positive value 0N/A // (high 32-bits are 0) so it could be used in 64-bits shifts. 0N/A // Rint - 32-bits value 0N/A __ stop(
"high 32-bits of int value are not 0");
0N/A // Generate overlap test for array copy stubs 0N/A // c_rarg2 - element count 0N/A // rax - &from[element count - 1] 0N/A // Registers r9 and r10 are used to save rdi and rsi on Windows, which latter 0N/A // are non-volatile. r9 and r10 should not be used by the caller. 0N/A "unexpected argument registers");
0N/A "unexpected argument registers");
0N/A // Generate code for an array write pre barrier 0N/A // addr - starting address 0N/A // count - element count 0N/A // Destroy no registers! 0N/A // Generate code for an array write post barrier 0N/A // start - register containing starting address of destination array 0N/A // end - register containing ending address of destination array 0N/A // scratch - scratch register 0N/A // The input registers are overwritten. 0N/A // The ending address is inclusive. 0N/A // must compute element count unless barrier set interface is changed (other platforms supply count) 0N/A // Copy big chunks forward 0N/A // end_from - source arrays end address 0N/A // end_to - destination array end address 0N/A // qword_count - 64-bits element count, negative 0N/A // L_copy_32_bytes - entry label 0N/A // L_copy_8_bytes - exit label 0N/A // Copy big chunks backward 0N/A // from - source arrays address 0N/A // dest - destination array address 0N/A // qword_count - 64-bits element count 0N/A // L_copy_32_bytes - entry label 0N/A // L_copy_8_bytes - exit label 0N/A // aligned - true => Input and output aligned on a HeapWord == 8-byte boundary 0N/A // name - stub name string 0N/A // c_rarg0 - source array address 0N/A // c_rarg1 - destination array address 0N/A // c_rarg2 - element count, treated as ssize_t, can be zero 0N/A // If 'from' and/or 'to' are aligned on 4-, 2-, or 1-byte boundaries, 0N/A // we let the hardware handle it. The one to eight bytes within words, 0N/A // dwords or qwords that span cache line boundaries will still be loaded 0N/A // and stored atomically. 0N/A // disjoint_byte_copy_entry is set to the no-overlap entry point 0N/A // used by generate_conjoint_byte_copy(). 0N/A // End pointers are inclusive, and if count is not zero they point 0N/A // to the last unit copied: end_to[0] := end_from[0] 0N/A __ enter();
// required for proper stackwalking of RuntimeStub frame 0N/A // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) 0N/A // r9 and r10 may be used to save non-volatile registers 0N/A // 'from', 'to' and 'count' are now valid 0N/A // Copy from low to high addresses. Use 'to' as scratch. 0N/A // Copy trailing qwords 0N/A // Check for and copy trailing dword 0N/A // Check for and copy trailing word 0N/A // Check for and copy trailing byte 0N/A __ leave();
// required for proper stackwalking of RuntimeStub frame 0N/A // Copy in 32-bytes chunks 0N/A // aligned - true => Input and output aligned on a HeapWord == 8-byte boundary 0N/A // name - stub name string 0N/A // c_rarg0 - source array address 0N/A // c_rarg1 - destination array address 0N/A // c_rarg2 - element count, treated as ssize_t, can be zero 0N/A // If 'from' and/or 'to' are aligned on 4-, 2-, or 1-byte boundaries, 0N/A // we let the hardware handle it. The one to eight bytes within words, 0N/A // dwords or qwords that span cache line boundaries will still be loaded 0N/A // and stored atomically. 0N/A __ enter();
// required for proper stackwalking of RuntimeStub frame 0N/A // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) 0N/A // r9 and r10 may be used to save non-volatile registers 0N/A // 'from', 'to' and 'count' are now valid 0N/A // Copy from high to low addresses. 0N/A // Check for and copy trailing byte 0N/A // Check for and copy trailing word 0N/A // Check for and copy trailing dword 0N/A // Copy trailing qwords 0N/A __ leave();
// required for proper stackwalking of RuntimeStub frame 0N/A // Copy in 32-bytes chunks 0N/A __ leave();
// required for proper stackwalking of RuntimeStub frame 0N/A // aligned - true => Input and output aligned on a HeapWord == 8-byte boundary 0N/A // name - stub name string 0N/A // c_rarg0 - source array address 0N/A // c_rarg1 - destination array address 0N/A // c_rarg2 - element count, treated as ssize_t, can be zero 0N/A // If 'from' and/or 'to' are aligned on 4- or 2-byte boundaries, we 0N/A // let the hardware handle it. The two or four words within dwords 0N/A // or qwords that span cache line boundaries will still be loaded 0N/A // and stored atomically. 0N/A // disjoint_short_copy_entry is set to the no-overlap entry point 0N/A // used by generate_conjoint_short_copy(). 0N/A // End pointers are inclusive, and if count is not zero they point 0N/A // to the last unit copied: end_to[0] := end_from[0] 0N/A __ enter();
// required for proper stackwalking of RuntimeStub frame 0N/A // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) 0N/A // r9 and r10 may be used to save non-volatile registers 0N/A // 'from', 'to' and 'count' are now valid 0N/A // Copy from low to high addresses. Use 'to' as scratch. 0N/A // Copy trailing qwords 0N/A // Original 'dest' is trashed, so we can't use it as a 0N/A // base register for a possible trailing word copy 0N/A // Check for and copy trailing dword 0N/A // Check for and copy trailing word 0N/A __ leave();
// required for proper stackwalking of RuntimeStub frame 0N/A // Copy in 32-bytes chunks 0N/A // aligned - true => Input and output aligned on a HeapWord == 8-byte boundary 0N/A // name - stub name string 0N/A // c_rarg0 - source array address 0N/A // c_rarg1 - destination array address 0N/A // c_rarg2 - element count, treated as ssize_t, can be zero 0N/A // If 'from' and/or 'to' are aligned on 4- or 2-byte boundaries, we 0N/A // let the hardware handle it. The two or four words within dwords 0N/A // or qwords that span cache line boundaries will still be loaded 0N/A // and stored atomically. 0N/A __ enter();
// required for proper stackwalking of RuntimeStub frame 0N/A // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) 0N/A // r9 and r10 may be used to save non-volatile registers 0N/A // 'from', 'to' and 'count' are now valid 0N/A // Copy from high to low addresses. Use 'to' as scratch. 0N/A // Check for and copy trailing word 0N/A // Check for and copy trailing dword 0N/A // Copy trailing qwords 0N/A __ leave();
// required for proper stackwalking of RuntimeStub frame 0N/A // Copy in 32-bytes chunks 0N/A __ leave();
// required for proper stackwalking of RuntimeStub frame 0N/A // aligned - true => Input and output aligned on a HeapWord == 8-byte boundary 113N/A // is_oop - true => oop array, so generate store check code 0N/A // name - stub name string 0N/A // c_rarg0 - source array address 0N/A // c_rarg1 - destination array address 0N/A // c_rarg2 - element count, treated as ssize_t, can be zero 0N/A // If 'from' and/or 'to' are aligned on 4-byte boundaries, we let 0N/A // the hardware handle it. The two dwords within qwords that span 0N/A // cache line boundaries will still be loaded and stored atomicly. 0N/A // disjoint_int_copy_entry is set to the no-overlap entry point 113N/A // used by generate_conjoint_int_oop_copy(). 0N/A // End pointers are inclusive, and if count is not zero they point 0N/A // to the last unit copied: end_to[0] := end_from[0] 0N/A __ enter();
// required for proper stackwalking of RuntimeStub frame 113N/A // no registers are destroyed by this call 0N/A // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) 0N/A // r9 and r10 may be used to save non-volatile registers 0N/A // 'from', 'to' and 'count' are now valid 0N/A // Copy from low to high addresses. Use 'to' as scratch. 0N/A // Copy trailing qwords 0N/A // Check for and copy trailing dword 0N/A __ leave();
// required for proper stackwalking of RuntimeStub frame 0N/A // Copy 32-bytes chunks 0N/A // aligned - true => Input and output aligned on a HeapWord == 8-byte boundary 113N/A // is_oop - true => oop array, so generate store check code 0N/A // name - stub name string 0N/A // c_rarg0 - source array address 0N/A // c_rarg1 - destination array address 0N/A // c_rarg2 - element count, treated as ssize_t, can be zero 0N/A // If 'from' and/or 'to' are aligned on 4-byte boundaries, we let 0N/A // the hardware handle it. The two dwords within qwords that span 0N/A // cache line boundaries will still be loaded and stored atomicly. 0N/A __ enter();
// required for proper stackwalking of RuntimeStub frame 113N/A // no registers are destroyed by this call 0N/A // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) 0N/A // r9 and r10 may be used to save non-volatile registers 0N/A // 'from', 'to' and 'count' are now valid 0N/A // Copy from high to low addresses. Use 'to' as scratch. 0N/A // Check for and copy trailing dword 0N/A // Copy trailing qwords 0N/A __ leave();
// required for proper stackwalking of RuntimeStub frame 0N/A // Copy in 32-bytes chunks 0N/A __ leave();
// required for proper stackwalking of RuntimeStub frame 0N/A // aligned - true => Input and output aligned on a HeapWord boundary == 8 bytes 0N/A // is_oop - true => oop array, so generate store check code 0N/A // name - stub name string 0N/A // c_rarg0 - source array address 0N/A // c_rarg1 - destination array address 0N/A // c_rarg2 - element count, treated as ssize_t, can be zero 0N/A // disjoint_oop_copy_entry or disjoint_long_copy_entry is set to the 0N/A // no-overlap entry point used by generate_conjoint_long_oop_copy(). 0N/A // End pointers are inclusive, and if count is not zero they point 0N/A // to the last unit copied: end_to[0] := end_from[0] 0N/A __ enter();
// required for proper stackwalking of RuntimeStub frame 0N/A // Save no-overlap entry point for generate_conjoint_long_oop_copy() 0N/A // no registers are destroyed by this call 0N/A // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) 0N/A // r9 and r10 may be used to save non-volatile registers 0N/A // 'from', 'to' and 'qword_count' are now valid 0N/A // Copy from low to high addresses. Use 'to' as scratch. 0N/A // Copy trailing qwords 0N/A __ leave();
// required for proper stackwalking of RuntimeStub frame 0N/A // Copy 64-byte chunks 0N/A __ leave();
// required for proper stackwalking of RuntimeStub frame 0N/A // aligned - true => Input and output aligned on a HeapWord boundary == 8 bytes 0N/A // is_oop - true => oop array, so generate store check code 0N/A // name - stub name string 0N/A // c_rarg0 - source array address 0N/A // c_rarg1 - destination array address 0N/A // c_rarg2 - element count, treated as ssize_t, can be zero 0N/A __ enter();
// required for proper stackwalking of RuntimeStub frame 0N/A // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) 0N/A // r9 and r10 may be used to save non-volatile registers 0N/A // 'from', 'to' and 'qword_count' are now valid 0N/A // Save to and count for store barrier 0N/A // No registers are destroyed by this call 0N/A // Copy trailing qwords 0N/A __ leave();
// required for proper stackwalking of RuntimeStub frame 0N/A // Copy in 32-bytes chunks 0N/A __ leave();
// required for proper stackwalking of RuntimeStub frame 0N/A // Helper for generating a dynamic type check. 0N/A // Smashes no registers. 0N/A // a couple of useful fields in sub_klass: 0N/A // if the pointers are equal, we are done (e.g., String[] elements) 0N/A // check the supertype display: 0N/A // if it was a primary super, we can just fail immediately 0N/A // Now do a linear scan of the secondary super-klass chain. 0N/A // The repne_scan instruction uses fixed registers, which we must spill. 0N/A // (We need a couple more temps in any case.) 0N/A // This code is rarely used, so simplicity is a virtue here. 0N/A // Load the array length. 0N/A // Skip to start of data. 0N/A // Scan rcx words at [rdi] for occurance of rax 0N/A // Set NZ/Z based on last compare 113N/A // Compare against compressed form. Don't need to uncompress because 113N/A // looks like orig rax is restored in popq below. 0N/A // Unspill the temp. registers: 0N/A // Success. Cache the super we found and proceed in triumph. 0N/A // Fall through on failure! 0N/A // Generate checkcasting array copy stub 0N/A // c_rarg0 - source array address 0N/A // c_rarg1 - destination array address 0N/A // c_rarg2 - element count, treated as ssize_t, can be zero 0N/A // c_rarg3 - size_t ckoff (super_check_offset) 0N/A // c_rarg4 - oop ckval (super_klass) 0N/A // rsp+40 - oop ckval (super_klass) 0N/A // rax == 0 - success 0N/A // rax == -1^K - failure, where K is partial transfer count 0N/A // Input registers (after setup_arg_regs) 0N/A // Registers used as temps (r13, r14 are save-on-entry) 0N/A // End pointers are inclusive, and if length is not zero they point 0N/A // to the last unit copied: end_to[0] := end_from[0] 0N/A //--------------------------------------------------------------- 0N/A // Assembler stub will be used for this call to arraycopy 0N/A // if the two arrays are subtypes of Object[] but the 0N/A // destination array type is not equal to or a supertype 0N/A // of the source type. Each element must be separately 0N/A __ enter();
// required for proper stackwalking of RuntimeStub frame 0N/A // caller guarantees that the arrays really are different 0N/A // otherwise, we would have to make conjoint checks 0N/A __ stop(
"checkcast_copy within a single array");
0N/A // allocate spill slots for r13, r14 0N/A // ckoff => rcx, ckval => r8 0N/A // r9 and r10 may be used to save non-volatile registers 0N/A // last argument (#4) is on stack on Win64 0N/A // check that int operands are properly extended to size_t 0N/A // The ckoff and ckval must be mutually consistent, 0N/A // even though caller generates both. 0N/A // Loop-invariant addresses. They are exclusive end pointers. 0N/A // Loop-variant addresses. They assume post-incremented count < 0. 0N/A // Copy from low to high addresses, indexed from the end of each array. 0N/A // Empty array: Nothing to do. 0N/A // ======== begin loop ======== 0N/A // (Loop is rotated; its entry is L_load_element.) 0N/A // for (count = -count; count != 0; count++) 0N/A // Base pointers src, dst are biased by 8*(count-1),to last element. 0N/A // ======== loop entry is here ======== 0N/A // ======== end loop ======== 0N/A // It was a real error; we must depend on the caller to finish the job. 0N/A // Register rdx = -1 * number of *remaining* oops, r14 = *total* oops. 0N/A // Emit GC store barriers for the oops we have copied (r14 + rdx), 0N/A // and report their number to the caller. 0N/A // Come here on success only. 0N/A // Common exit point (success or failure). 0N/A __ leave();
// required for proper stackwalking of RuntimeStub frame 0N/A // Generate 'unsafe' array copy stub 0N/A // Though just as safe as the other stubs, it takes an unscaled 0N/A // size_t argument instead of an element count. 0N/A // c_rarg0 - source array address 0N/A // c_rarg1 - destination array address 0N/A // c_rarg2 - byte count, treated as ssize_t, can be zero 0N/A // Examines the alignment of the operands and dispatches 0N/A // to a long, int, short, or byte copy loop. 0N/A // Input registers (before setup_arg_regs) 0N/A // Register used as a temp 0N/A __ enter();
// required for proper stackwalking of RuntimeStub frame 0N/A // bump this on entry, not on exit: 0N/A // Perform range checks on the proposed arraycopy. 0N/A // Kills temp, but nothing else. 0N/A // Also, clean the sign bits of src_pos and dst_pos. 0N/A // if (src_pos + length > arrayOop(src)->length()) FAIL; 0N/A // if (dst_pos + length > arrayOop(dst)->length()) FAIL; 0N/A // Have to clean up high 32-bits of 'src_pos' and 'dst_pos'. 0N/A // Move with sign extension can be used since they are positive. 0N/A // Generate generic array copy stubs 0N/A // c_rarg0 - src oop 0N/A // c_rarg1 - src_pos (32-bits) 0N/A // c_rarg2 - dst oop 0N/A // c_rarg3 - dst_pos (32-bits) 0N/A // c_rarg4 - element count (32-bits) 0N/A // rsp+40 - element count (32-bits) 0N/A // rax == 0 - success 0N/A // rax == -1^K - failure, where K is partial transfer count 0N/A // elements count is on stack on Win64 0N/A // Short-hop target to L_failed. Makes for denser prologue code. 0N/A __ enter();
// required for proper stackwalking of RuntimeStub frame 0N/A // bump this on entry, not on exit: 0N/A //----------------------------------------------------------------------- 0N/A // Assembler stub will be used for this call to arraycopy 0N/A // if the following conditions are met: 0N/A // (1) src and dst must not be null. 0N/A // (2) src_pos must not be negative. 0N/A // (3) dst_pos must not be negative. 0N/A // (4) length must not be negative. 0N/A // (5) src klass and dst klass should be the same and not NULL. 0N/A // (6) src and dst should be arrays. 0N/A // (7) src_pos + length must not exceed length of src. 0N/A // (8) dst_pos + length must not exceed length of dst. 0N/A // if (src == NULL) return -1; 0N/A // if (src_pos < 0) return -1; 0N/A // if (dst == NULL) return -1; 0N/A // if (dst_pos < 0) return -1; 0N/A // The first four tests are very dense code, 0N/A // but not quite dense enough to put four 0N/A // jumps in a 16-byte instruction fetch buffer. 0N/A // That's good, because some branch predicters 0N/A // do not like jumps so close together. 0N/A // Make sure of this. 0N/A // registers used as temp 0N/A // if (length < 0) return -1; 0N/A // assert(src->klass() != NULL); 0N/A // Load layout helper (32-bits) 0N/A // |array_tag| | header_size | element_type | |log2_element_size| 0N/A // 32 30 24 16 8 2 0 0N/A // array_tag: typeArray = 0x3, objArray = 0x2, non-array = 0x0 0N/A // Handle objArrays completely differently... 0N/A // if (src->klass() != dst->klass()) return -1; 0N/A // if (!src->is_Array()) return -1; 0N/A // At this point, it is known to be a typeArray (array_tag 0x3). 0N/A // src_addr = (src + array_header_in_bytes()) + (src_pos << log2elemsize); 0N/A // dst_addr = (dst + array_header_in_bytes()) + (dst_pos << log2elemsize); 0N/A // next registers should be set before the jump to corresponding stub 0N/A // 'from', 'to', 'count' registers should be set in such order 0N/A // since they are the same as 'src', 'src_pos', 'dst'. 0N/A __ stop(
"must be long copy, but elsize is wrong");
0N/A // live at this point: r10_src_klass, src[_pos], dst[_pos] 0N/A // test array classes for subtyping 0N/A // Identically typed arrays can be copied without element-wise checks. 0N/A // live at this point: r10_src_klass, !r11_length 0N/A // assert(r11_length == C_RARG4); // will reload from here 0N/A // Before looking at dst.length, make sure dst is also an objArray. 0N/A // It is safe to examine both src.length and dst.length. 0N/A // Marshal the base address arguments now, freeing registers. 0N/A // Generate the type check. 0N/A // Fetch destination element klass from the objArrayKlass header. 0N/A // the checkcast_copy loop needs two extra arguments: 0N/A __ leave();
// required for proper stackwalking of RuntimeStub frame 0N/A // Call the conjoint generation methods immediately after 0N/A // the disjoint ones so that short branches from the former 0N/A // to the latter can be generated. 0N/A // We don't generate specialized code for HeapWord-aligned source 0N/A // arrays, so just use the code we've already generated 0N/A // Continuation point for throwing of implicit exceptions that are 0N/A // not handled in the current activation. Fabricates an exception 0N/A // oop and initiates normal exception dispatching in this 0N/A // frame. Since we need to preserve callee-saved values (currently 0N/A // only for C2, but done for C1 as well) we need a callee-saved oop 0N/A // map and therefore have to make these stubs into RuntimeStubs 0N/A // rather than BufferBlobs. If the compiler needs all registers to 0N/A // be preserved between the fault point and the exception handler 0N/A // then it must assume responsibility for that in 0N/A // AbstractCompiler::continuation_for_implicit_null_exception or 0N/A // continuation_for_implicit_division_by_zero_exception. All other 0N/A // implicit exceptions (e.g., NullPointerException or 0N/A // AbstractMethodError on entry) are either at call sites or 0N/A // otherwise assume that stack unwinding will be initiated, so 0N/A // caller saved registers were assumed volatile in the compiler. 0N/A // Information about frame layout at time of blocking runtime call. 0N/A // Note that we only have to preserve callee-saved registers since 0N/A // the compilers are responsible for supplying a continuation point 0N/A // if they expect all registers to be preserved. 0N/A // This is an inlined and slightly modified version of call_VM 0N/A // which has the ability to fetch the return PC out of 0N/A // thread-local storage and also sets up last_Java_sp slightly 0N/A // differently than the real call_VM 0N/A __ enter();
// required for proper stackwalking of RuntimeStub frame 0N/A // return address and rbp are already in place 0N/A // Set up last_Java_sp and last_Java_fp 0N/A __ leave();
// required for proper stackwalking of RuntimeStub frame 0N/A // check for pending exceptions 0N/A // codeBlob framesize is in words (not VMRegImpl::slot_size) 0N/A // Generates all stubs and initializes the entry points 0N/A // This platform-specific stub is needed by generate_call_stub() 0N/A // entry points that exist in all platforms Note: This is code 0N/A // that could be shared among different platforms - however the 0N/A // benefit seems to be smaller than the disadvantage of having a 0N/A // much more complicated generator structure. See also comment in 0N/A // is referenced by megamorphic call 0N/A // platform dependent 0N/A // Generates all stubs and initializes the entry points 0N/A // These entry points require SharedInfo::stack0 to be set up in 0N/A // non-core builds and need to be relocatable, so they each 0N/A // fabricate a RuntimeStub internally. 0N/A // entry points that are platform specific 0N/A // support for verify_oop (must happen after universe_init) 0N/A // arraycopy stubs used by compilers 0N/A};
// end class declaration