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