Wed, 22 Jan 2014 17:42:23 -0800
Merge
never@1445 | 1 | /* |
mikael@6198 | 2 | * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. |
twisti@1814 | 3 | * Copyright 2007, 2008, 2010 Red Hat, Inc. |
never@1445 | 4 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
never@1445 | 5 | * |
never@1445 | 6 | * This code is free software; you can redistribute it and/or modify it |
never@1445 | 7 | * under the terms of the GNU General Public License version 2 only, as |
never@1445 | 8 | * published by the Free Software Foundation. |
never@1445 | 9 | * |
never@1445 | 10 | * This code is distributed in the hope that it will be useful, but WITHOUT |
never@1445 | 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
never@1445 | 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
never@1445 | 13 | * version 2 for more details (a copy is included in the LICENSE file that |
never@1445 | 14 | * accompanied this code). |
never@1445 | 15 | * |
never@1445 | 16 | * You should have received a copy of the GNU General Public License version |
never@1445 | 17 | * 2 along with this work; if not, write to the Free Software Foundation, |
never@1445 | 18 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
never@1445 | 19 | * |
trims@1907 | 20 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
trims@1907 | 21 | * or visit www.oracle.com if you need additional information or have any |
trims@1907 | 22 | * questions. |
never@1445 | 23 | * |
never@1445 | 24 | */ |
never@1445 | 25 | |
stefank@2314 | 26 | #include "precompiled.hpp" |
stefank@2314 | 27 | #include "asm/assembler.hpp" |
stefank@2314 | 28 | #include "assembler_zero.inline.hpp" |
stefank@2314 | 29 | #include "interpreter/interpreter.hpp" |
stefank@2314 | 30 | #include "nativeInst_zero.hpp" |
stefank@2314 | 31 | #include "oops/instanceOop.hpp" |
coleenp@4037 | 32 | #include "oops/method.hpp" |
stefank@2314 | 33 | #include "oops/objArrayKlass.hpp" |
stefank@2314 | 34 | #include "oops/oop.inline.hpp" |
stefank@2314 | 35 | #include "prims/methodHandles.hpp" |
stefank@2314 | 36 | #include "runtime/frame.inline.hpp" |
stefank@2314 | 37 | #include "runtime/handles.inline.hpp" |
stefank@2314 | 38 | #include "runtime/sharedRuntime.hpp" |
stefank@2314 | 39 | #include "runtime/stubCodeGenerator.hpp" |
stefank@2314 | 40 | #include "runtime/stubRoutines.hpp" |
stefank@4299 | 41 | #include "runtime/thread.inline.hpp" |
stefank@2314 | 42 | #include "stack_zero.inline.hpp" |
stefank@2314 | 43 | #include "utilities/top.hpp" |
stefank@2314 | 44 | #ifdef COMPILER2 |
stefank@2314 | 45 | #include "opto/runtime.hpp" |
stefank@2314 | 46 | #endif |
never@1445 | 47 | |
never@1445 | 48 | // Declaration and definition of StubGenerator (no .hpp file). |
never@1445 | 49 | // For a more detailed description of the stub routine structure |
never@1445 | 50 | // see the comment in stubRoutines.hpp |
never@1445 | 51 | |
never@1445 | 52 | class StubGenerator: public StubCodeGenerator { |
never@1445 | 53 | private: |
never@1445 | 54 | // The call stub is used to call Java from C |
never@1445 | 55 | static void call_stub( |
never@1445 | 56 | JavaCallWrapper *call_wrapper, |
never@1445 | 57 | intptr_t* result, |
never@1445 | 58 | BasicType result_type, |
coleenp@4037 | 59 | Method* method, |
never@1445 | 60 | address entry_point, |
never@1445 | 61 | intptr_t* parameters, |
never@1445 | 62 | int parameter_words, |
never@1445 | 63 | TRAPS) { |
never@1445 | 64 | JavaThread *thread = (JavaThread *) THREAD; |
never@1445 | 65 | ZeroStack *stack = thread->zero_stack(); |
never@1445 | 66 | |
never@1445 | 67 | // Make sure we have no pending exceptions |
never@1445 | 68 | assert(!HAS_PENDING_EXCEPTION, "call_stub called with pending exception"); |
never@1445 | 69 | |
never@1445 | 70 | // Set up the stack if necessary |
never@1445 | 71 | bool stack_needs_teardown = false; |
never@1445 | 72 | if (stack->needs_setup()) { |
twisti@1866 | 73 | size_t zero_stack_size = stack->suggest_size(thread); |
never@1445 | 74 | stack->setup(alloca(zero_stack_size), zero_stack_size); |
never@1445 | 75 | stack_needs_teardown = true; |
never@1445 | 76 | } |
never@1445 | 77 | |
never@1445 | 78 | // Allocate and initialize our frame |
twisti@1814 | 79 | EntryFrame *frame = |
twisti@1814 | 80 | EntryFrame::build(parameters, parameter_words, call_wrapper, THREAD); |
never@1445 | 81 | |
twisti@1814 | 82 | if (!HAS_PENDING_EXCEPTION) { |
twisti@1814 | 83 | // Push the frame |
twisti@1814 | 84 | thread->push_zero_frame(frame); |
never@1445 | 85 | |
twisti@1814 | 86 | // Make the call |
twisti@1814 | 87 | Interpreter::invoke_method(method, entry_point, THREAD); |
twisti@1814 | 88 | |
twisti@1814 | 89 | // Store the result |
twisti@1814 | 90 | if (!HAS_PENDING_EXCEPTION) { |
twisti@1814 | 91 | switch (result_type) { |
twisti@1814 | 92 | case T_INT: |
twisti@1814 | 93 | *(jint *) result = *(jint *) stack->sp(); |
twisti@1814 | 94 | break; |
twisti@1814 | 95 | case T_LONG: |
twisti@1814 | 96 | *(jlong *) result = *(jlong *) stack->sp(); |
twisti@1814 | 97 | break; |
twisti@1814 | 98 | case T_FLOAT: |
twisti@1814 | 99 | *(jfloat *) result = *(jfloat *) stack->sp(); |
twisti@1814 | 100 | break; |
twisti@1814 | 101 | case T_DOUBLE: |
twisti@1814 | 102 | *(jdouble *) result = *(jdouble *) stack->sp(); |
twisti@1814 | 103 | break; |
twisti@1814 | 104 | case T_OBJECT: |
twisti@1814 | 105 | *(oop *) result = *(oop *) stack->sp(); |
twisti@1814 | 106 | break; |
twisti@1814 | 107 | default: |
twisti@1814 | 108 | ShouldNotReachHere(); |
twisti@1814 | 109 | } |
never@1445 | 110 | } |
twisti@1814 | 111 | |
twisti@1814 | 112 | // Unwind the frame |
twisti@1814 | 113 | thread->pop_zero_frame(); |
never@1445 | 114 | } |
never@1445 | 115 | |
never@1445 | 116 | // Tear down the stack if necessary |
never@1445 | 117 | if (stack_needs_teardown) |
never@1445 | 118 | stack->teardown(); |
never@1445 | 119 | } |
never@1445 | 120 | |
never@1445 | 121 | // These stubs get called from some dumb test routine. |
never@1445 | 122 | // I'll write them properly when they're called from |
never@1445 | 123 | // something that's actually doing something. |
never@1445 | 124 | static void fake_arraycopy_stub(address src, address dst, int count) { |
never@1445 | 125 | assert(count == 0, "huh?"); |
never@1445 | 126 | } |
never@1445 | 127 | |
never@1445 | 128 | void generate_arraycopy_stubs() { |
never@1445 | 129 | // Call the conjoint generation methods immediately after |
never@1445 | 130 | // the disjoint ones so that short branches from the former |
never@1445 | 131 | // to the latter can be generated. |
never@1445 | 132 | StubRoutines::_jbyte_disjoint_arraycopy = (address) fake_arraycopy_stub; |
never@1445 | 133 | StubRoutines::_jbyte_arraycopy = (address) fake_arraycopy_stub; |
never@1445 | 134 | |
never@1445 | 135 | StubRoutines::_jshort_disjoint_arraycopy = (address) fake_arraycopy_stub; |
never@1445 | 136 | StubRoutines::_jshort_arraycopy = (address) fake_arraycopy_stub; |
never@1445 | 137 | |
never@1445 | 138 | StubRoutines::_jint_disjoint_arraycopy = (address) fake_arraycopy_stub; |
never@1445 | 139 | StubRoutines::_jint_arraycopy = (address) fake_arraycopy_stub; |
never@1445 | 140 | |
never@1445 | 141 | StubRoutines::_jlong_disjoint_arraycopy = (address) fake_arraycopy_stub; |
never@1445 | 142 | StubRoutines::_jlong_arraycopy = (address) fake_arraycopy_stub; |
never@1445 | 143 | |
never@1445 | 144 | StubRoutines::_oop_disjoint_arraycopy = ShouldNotCallThisStub(); |
never@1445 | 145 | StubRoutines::_oop_arraycopy = ShouldNotCallThisStub(); |
never@1445 | 146 | |
never@1445 | 147 | StubRoutines::_checkcast_arraycopy = ShouldNotCallThisStub(); |
never@1445 | 148 | StubRoutines::_unsafe_arraycopy = ShouldNotCallThisStub(); |
never@1445 | 149 | StubRoutines::_generic_arraycopy = ShouldNotCallThisStub(); |
never@1445 | 150 | |
never@1445 | 151 | // We don't generate specialized code for HeapWord-aligned source |
never@1445 | 152 | // arrays, so just use the code we've already generated |
never@1445 | 153 | StubRoutines::_arrayof_jbyte_disjoint_arraycopy = |
never@1445 | 154 | StubRoutines::_jbyte_disjoint_arraycopy; |
never@1445 | 155 | StubRoutines::_arrayof_jbyte_arraycopy = |
never@1445 | 156 | StubRoutines::_jbyte_arraycopy; |
never@1445 | 157 | |
never@1445 | 158 | StubRoutines::_arrayof_jshort_disjoint_arraycopy = |
never@1445 | 159 | StubRoutines::_jshort_disjoint_arraycopy; |
never@1445 | 160 | StubRoutines::_arrayof_jshort_arraycopy = |
never@1445 | 161 | StubRoutines::_jshort_arraycopy; |
never@1445 | 162 | |
never@1445 | 163 | StubRoutines::_arrayof_jint_disjoint_arraycopy = |
never@1445 | 164 | StubRoutines::_jint_disjoint_arraycopy; |
never@1445 | 165 | StubRoutines::_arrayof_jint_arraycopy = |
never@1445 | 166 | StubRoutines::_jint_arraycopy; |
never@1445 | 167 | |
never@1445 | 168 | StubRoutines::_arrayof_jlong_disjoint_arraycopy = |
never@1445 | 169 | StubRoutines::_jlong_disjoint_arraycopy; |
never@1445 | 170 | StubRoutines::_arrayof_jlong_arraycopy = |
never@1445 | 171 | StubRoutines::_jlong_arraycopy; |
never@1445 | 172 | |
never@1445 | 173 | StubRoutines::_arrayof_oop_disjoint_arraycopy = |
never@1445 | 174 | StubRoutines::_oop_disjoint_arraycopy; |
never@1445 | 175 | StubRoutines::_arrayof_oop_arraycopy = |
never@1445 | 176 | StubRoutines::_oop_arraycopy; |
never@1445 | 177 | } |
never@1445 | 178 | |
omajid@5497 | 179 | static int SafeFetch32(int *adr, int errValue) { |
omajid@5497 | 180 | int value = errValue; |
omajid@5497 | 181 | value = *adr; |
omajid@5497 | 182 | return value; |
omajid@5497 | 183 | } |
omajid@5497 | 184 | |
omajid@5497 | 185 | static intptr_t SafeFetchN(intptr_t *adr, intptr_t errValue) { |
omajid@5497 | 186 | intptr_t value = errValue; |
omajid@5497 | 187 | value = *adr; |
omajid@5497 | 188 | return value; |
omajid@5497 | 189 | } |
omajid@5497 | 190 | |
omajid@5497 | 191 | |
never@1445 | 192 | void generate_initial() { |
never@1445 | 193 | // Generates all stubs and initializes the entry points |
never@1445 | 194 | |
never@1445 | 195 | // entry points that exist in all platforms Note: This is code |
never@1445 | 196 | // that could be shared among different platforms - however the |
never@1445 | 197 | // benefit seems to be smaller than the disadvantage of having a |
never@1445 | 198 | // much more complicated generator structure. See also comment in |
never@1445 | 199 | // stubRoutines.hpp. |
never@1445 | 200 | |
never@1445 | 201 | StubRoutines::_forward_exception_entry = ShouldNotCallThisStub(); |
never@1445 | 202 | StubRoutines::_call_stub_entry = (address) call_stub; |
never@1445 | 203 | StubRoutines::_catch_exception_entry = ShouldNotCallThisStub(); |
never@1445 | 204 | |
never@1445 | 205 | // atomic calls |
never@1445 | 206 | StubRoutines::_atomic_xchg_entry = ShouldNotCallThisStub(); |
never@1445 | 207 | StubRoutines::_atomic_xchg_ptr_entry = ShouldNotCallThisStub(); |
never@1445 | 208 | StubRoutines::_atomic_cmpxchg_entry = ShouldNotCallThisStub(); |
never@1445 | 209 | StubRoutines::_atomic_cmpxchg_ptr_entry = ShouldNotCallThisStub(); |
never@1445 | 210 | StubRoutines::_atomic_cmpxchg_long_entry = ShouldNotCallThisStub(); |
never@1445 | 211 | StubRoutines::_atomic_add_entry = ShouldNotCallThisStub(); |
never@1445 | 212 | StubRoutines::_atomic_add_ptr_entry = ShouldNotCallThisStub(); |
never@1445 | 213 | StubRoutines::_fence_entry = ShouldNotCallThisStub(); |
never@1445 | 214 | |
never@1445 | 215 | // amd64 does this here, sparc does it in generate_all() |
never@1445 | 216 | StubRoutines::_handler_for_unsafe_access_entry = |
never@1445 | 217 | ShouldNotCallThisStub(); |
never@1445 | 218 | } |
never@1445 | 219 | |
never@1445 | 220 | void generate_all() { |
never@1445 | 221 | // Generates all stubs and initializes the entry points |
never@1445 | 222 | |
never@1445 | 223 | // These entry points require SharedInfo::stack0 to be set up in |
never@1445 | 224 | // non-core builds and need to be relocatable, so they each |
never@1445 | 225 | // fabricate a RuntimeStub internally. |
never@1445 | 226 | StubRoutines::_throw_AbstractMethodError_entry = |
never@1445 | 227 | ShouldNotCallThisStub(); |
never@1445 | 228 | |
never@1445 | 229 | StubRoutines::_throw_NullPointerException_at_call_entry = |
never@1445 | 230 | ShouldNotCallThisStub(); |
never@1445 | 231 | |
never@1445 | 232 | StubRoutines::_throw_StackOverflowError_entry = |
never@1445 | 233 | ShouldNotCallThisStub(); |
never@1445 | 234 | |
never@1445 | 235 | // support for verify_oop (must happen after universe_init) |
never@1445 | 236 | StubRoutines::_verify_oop_subroutine_entry = |
never@1445 | 237 | ShouldNotCallThisStub(); |
never@1445 | 238 | |
never@1445 | 239 | // arraycopy stubs used by compilers |
never@1445 | 240 | generate_arraycopy_stubs(); |
omajid@5497 | 241 | |
omajid@5497 | 242 | // Safefetch stubs. |
omajid@5497 | 243 | StubRoutines::_safefetch32_entry = CAST_FROM_FN_PTR(address, StubGenerator::SafeFetch32); |
omajid@5497 | 244 | StubRoutines::_safefetch32_fault_pc = NULL; |
omajid@5497 | 245 | StubRoutines::_safefetch32_continuation_pc = NULL; |
omajid@5497 | 246 | |
omajid@5497 | 247 | StubRoutines::_safefetchN_entry = CAST_FROM_FN_PTR(address, StubGenerator::SafeFetchN); |
omajid@5497 | 248 | StubRoutines::_safefetchN_fault_pc = NULL; |
omajid@5497 | 249 | StubRoutines::_safefetchN_continuation_pc = NULL; |
never@1445 | 250 | } |
never@1445 | 251 | |
never@1445 | 252 | public: |
never@1445 | 253 | StubGenerator(CodeBuffer* code, bool all) : StubCodeGenerator(code) { |
never@1445 | 254 | if (all) { |
never@1445 | 255 | generate_all(); |
never@1445 | 256 | } else { |
never@1445 | 257 | generate_initial(); |
never@1445 | 258 | } |
never@1445 | 259 | } |
never@1445 | 260 | }; |
never@1445 | 261 | |
never@1445 | 262 | void StubGenerator_generate(CodeBuffer* code, bool all) { |
never@1445 | 263 | StubGenerator g(code, all); |
never@1445 | 264 | } |
never@1445 | 265 | |
twisti@1814 | 266 | EntryFrame *EntryFrame::build(const intptr_t* parameters, |
never@1445 | 267 | int parameter_words, |
twisti@1814 | 268 | JavaCallWrapper* call_wrapper, |
twisti@1814 | 269 | TRAPS) { |
twisti@1814 | 270 | |
twisti@1814 | 271 | ZeroStack *stack = ((JavaThread *) THREAD)->zero_stack(); |
twisti@1814 | 272 | stack->overflow_check(header_words + parameter_words, CHECK_NULL); |
never@1445 | 273 | |
never@1445 | 274 | stack->push(0); // next_frame, filled in later |
never@1445 | 275 | intptr_t *fp = stack->sp(); |
never@1445 | 276 | assert(fp - stack->sp() == next_frame_off, "should be"); |
never@1445 | 277 | |
never@1445 | 278 | stack->push(ENTRY_FRAME); |
never@1445 | 279 | assert(fp - stack->sp() == frame_type_off, "should be"); |
never@1445 | 280 | |
never@1445 | 281 | stack->push((intptr_t) call_wrapper); |
never@1445 | 282 | assert(fp - stack->sp() == call_wrapper_off, "should be"); |
never@1445 | 283 | |
never@1445 | 284 | for (int i = 0; i < parameter_words; i++) |
never@1445 | 285 | stack->push(parameters[i]); |
never@1445 | 286 | |
never@1445 | 287 | return (EntryFrame *) fp; |
never@1445 | 288 | } |