Thu, 24 Mar 2011 02:11:50 -0700
7030207: Zero tweak to remove accidentally incorporated code
Summary: IcedTea contains a now-unmaintained ARM-specific interpreter and part of that interpreter was accidentally incorporated in one of the webrevs when Zero was initially imported.
Reviewed-by: twisti
Contributed-by: Gary Benson <gbenson@redhat.com>
duke@435 | 1 | /* |
never@2462 | 2 | * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. |
duke@435 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
duke@435 | 4 | * |
duke@435 | 5 | * This code is free software; you can redistribute it and/or modify it |
duke@435 | 6 | * under the terms of the GNU General Public License version 2 only, as |
duke@435 | 7 | * published by the Free Software Foundation. |
duke@435 | 8 | * |
duke@435 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
duke@435 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
duke@435 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
duke@435 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
duke@435 | 13 | * accompanied this code). |
duke@435 | 14 | * |
duke@435 | 15 | * You should have received a copy of the GNU General Public License version |
duke@435 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
duke@435 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
duke@435 | 18 | * |
trims@1907 | 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
trims@1907 | 20 | * or visit www.oracle.com if you need additional information or have any |
trims@1907 | 21 | * questions. |
duke@435 | 22 | * |
duke@435 | 23 | */ |
duke@435 | 24 | |
stefank@2314 | 25 | #include "precompiled.hpp" |
stefank@2314 | 26 | #include "interpreter/interpreter.hpp" |
stefank@2314 | 27 | #include "interpreter/interpreterGenerator.hpp" |
stefank@2314 | 28 | #include "interpreter/interpreterRuntime.hpp" |
stefank@2314 | 29 | #include "interpreter/templateTable.hpp" |
duke@435 | 30 | |
duke@435 | 31 | #ifndef CC_INTERP |
duke@435 | 32 | |
duke@435 | 33 | # define __ _masm-> |
duke@435 | 34 | |
duke@435 | 35 | void TemplateInterpreter::initialize() { |
duke@435 | 36 | if (_code != NULL) return; |
duke@435 | 37 | // assertions |
duke@435 | 38 | assert((int)Bytecodes::number_of_codes <= (int)DispatchTable::length, |
duke@435 | 39 | "dispatch table too small"); |
duke@435 | 40 | |
duke@435 | 41 | AbstractInterpreter::initialize(); |
duke@435 | 42 | |
duke@435 | 43 | TemplateTable::initialize(); |
duke@435 | 44 | |
duke@435 | 45 | // generate interpreter |
duke@435 | 46 | { ResourceMark rm; |
duke@435 | 47 | TraceTime timer("Interpreter generation", TraceStartupTime); |
duke@435 | 48 | int code_size = InterpreterCodeSize; |
duke@435 | 49 | NOT_PRODUCT(code_size *= 4;) // debug uses extra interpreter code space |
duke@435 | 50 | _code = new StubQueue(new InterpreterCodeletInterface, code_size, NULL, |
duke@435 | 51 | "Interpreter"); |
duke@435 | 52 | InterpreterGenerator g(_code); |
duke@435 | 53 | if (PrintInterpreter) print(); |
duke@435 | 54 | } |
duke@435 | 55 | |
duke@435 | 56 | // initialize dispatch table |
duke@435 | 57 | _active_table = _normal_table; |
duke@435 | 58 | } |
duke@435 | 59 | |
duke@435 | 60 | //------------------------------------------------------------------------------------------------------------------------ |
duke@435 | 61 | // Implementation of EntryPoint |
duke@435 | 62 | |
duke@435 | 63 | EntryPoint::EntryPoint() { |
duke@435 | 64 | assert(number_of_states == 9, "check the code below"); |
duke@435 | 65 | _entry[btos] = NULL; |
duke@435 | 66 | _entry[ctos] = NULL; |
duke@435 | 67 | _entry[stos] = NULL; |
duke@435 | 68 | _entry[atos] = NULL; |
duke@435 | 69 | _entry[itos] = NULL; |
duke@435 | 70 | _entry[ltos] = NULL; |
duke@435 | 71 | _entry[ftos] = NULL; |
duke@435 | 72 | _entry[dtos] = NULL; |
duke@435 | 73 | _entry[vtos] = NULL; |
duke@435 | 74 | } |
duke@435 | 75 | |
duke@435 | 76 | |
duke@435 | 77 | EntryPoint::EntryPoint(address bentry, address centry, address sentry, address aentry, address ientry, address lentry, address fentry, address dentry, address ventry) { |
duke@435 | 78 | assert(number_of_states == 9, "check the code below"); |
duke@435 | 79 | _entry[btos] = bentry; |
duke@435 | 80 | _entry[ctos] = centry; |
duke@435 | 81 | _entry[stos] = sentry; |
duke@435 | 82 | _entry[atos] = aentry; |
duke@435 | 83 | _entry[itos] = ientry; |
duke@435 | 84 | _entry[ltos] = lentry; |
duke@435 | 85 | _entry[ftos] = fentry; |
duke@435 | 86 | _entry[dtos] = dentry; |
duke@435 | 87 | _entry[vtos] = ventry; |
duke@435 | 88 | } |
duke@435 | 89 | |
duke@435 | 90 | |
duke@435 | 91 | void EntryPoint::set_entry(TosState state, address entry) { |
duke@435 | 92 | assert(0 <= state && state < number_of_states, "state out of bounds"); |
duke@435 | 93 | _entry[state] = entry; |
duke@435 | 94 | } |
duke@435 | 95 | |
duke@435 | 96 | |
duke@435 | 97 | address EntryPoint::entry(TosState state) const { |
duke@435 | 98 | assert(0 <= state && state < number_of_states, "state out of bounds"); |
duke@435 | 99 | return _entry[state]; |
duke@435 | 100 | } |
duke@435 | 101 | |
duke@435 | 102 | |
duke@435 | 103 | void EntryPoint::print() { |
duke@435 | 104 | tty->print("["); |
duke@435 | 105 | for (int i = 0; i < number_of_states; i++) { |
duke@435 | 106 | if (i > 0) tty->print(", "); |
duke@435 | 107 | tty->print(INTPTR_FORMAT, _entry[i]); |
duke@435 | 108 | } |
duke@435 | 109 | tty->print("]"); |
duke@435 | 110 | } |
duke@435 | 111 | |
duke@435 | 112 | |
duke@435 | 113 | bool EntryPoint::operator == (const EntryPoint& y) { |
duke@435 | 114 | int i = number_of_states; |
duke@435 | 115 | while (i-- > 0) { |
duke@435 | 116 | if (_entry[i] != y._entry[i]) return false; |
duke@435 | 117 | } |
duke@435 | 118 | return true; |
duke@435 | 119 | } |
duke@435 | 120 | |
duke@435 | 121 | |
duke@435 | 122 | //------------------------------------------------------------------------------------------------------------------------ |
duke@435 | 123 | // Implementation of DispatchTable |
duke@435 | 124 | |
duke@435 | 125 | EntryPoint DispatchTable::entry(int i) const { |
duke@435 | 126 | assert(0 <= i && i < length, "index out of bounds"); |
duke@435 | 127 | return |
duke@435 | 128 | EntryPoint( |
duke@435 | 129 | _table[btos][i], |
duke@435 | 130 | _table[ctos][i], |
duke@435 | 131 | _table[stos][i], |
duke@435 | 132 | _table[atos][i], |
duke@435 | 133 | _table[itos][i], |
duke@435 | 134 | _table[ltos][i], |
duke@435 | 135 | _table[ftos][i], |
duke@435 | 136 | _table[dtos][i], |
duke@435 | 137 | _table[vtos][i] |
duke@435 | 138 | ); |
duke@435 | 139 | } |
duke@435 | 140 | |
duke@435 | 141 | |
duke@435 | 142 | void DispatchTable::set_entry(int i, EntryPoint& entry) { |
duke@435 | 143 | assert(0 <= i && i < length, "index out of bounds"); |
duke@435 | 144 | assert(number_of_states == 9, "check the code below"); |
duke@435 | 145 | _table[btos][i] = entry.entry(btos); |
duke@435 | 146 | _table[ctos][i] = entry.entry(ctos); |
duke@435 | 147 | _table[stos][i] = entry.entry(stos); |
duke@435 | 148 | _table[atos][i] = entry.entry(atos); |
duke@435 | 149 | _table[itos][i] = entry.entry(itos); |
duke@435 | 150 | _table[ltos][i] = entry.entry(ltos); |
duke@435 | 151 | _table[ftos][i] = entry.entry(ftos); |
duke@435 | 152 | _table[dtos][i] = entry.entry(dtos); |
duke@435 | 153 | _table[vtos][i] = entry.entry(vtos); |
duke@435 | 154 | } |
duke@435 | 155 | |
duke@435 | 156 | |
duke@435 | 157 | bool DispatchTable::operator == (DispatchTable& y) { |
duke@435 | 158 | int i = length; |
duke@435 | 159 | while (i-- > 0) { |
duke@435 | 160 | EntryPoint t = y.entry(i); // for compiler compatibility (BugId 4150096) |
duke@435 | 161 | if (!(entry(i) == t)) return false; |
duke@435 | 162 | } |
duke@435 | 163 | return true; |
duke@435 | 164 | } |
duke@435 | 165 | |
duke@435 | 166 | address TemplateInterpreter::_remove_activation_entry = NULL; |
duke@435 | 167 | address TemplateInterpreter::_remove_activation_preserving_args_entry = NULL; |
duke@435 | 168 | |
duke@435 | 169 | |
duke@435 | 170 | address TemplateInterpreter::_throw_ArrayIndexOutOfBoundsException_entry = NULL; |
duke@435 | 171 | address TemplateInterpreter::_throw_ArrayStoreException_entry = NULL; |
duke@435 | 172 | address TemplateInterpreter::_throw_ArithmeticException_entry = NULL; |
duke@435 | 173 | address TemplateInterpreter::_throw_ClassCastException_entry = NULL; |
jrose@1145 | 174 | address TemplateInterpreter::_throw_WrongMethodType_entry = NULL; |
duke@435 | 175 | address TemplateInterpreter::_throw_NullPointerException_entry = NULL; |
duke@435 | 176 | address TemplateInterpreter::_throw_StackOverflowError_entry = NULL; |
duke@435 | 177 | address TemplateInterpreter::_throw_exception_entry = NULL; |
duke@435 | 178 | |
duke@435 | 179 | #ifndef PRODUCT |
duke@435 | 180 | EntryPoint TemplateInterpreter::_trace_code; |
duke@435 | 181 | #endif // !PRODUCT |
duke@435 | 182 | EntryPoint TemplateInterpreter::_return_entry[TemplateInterpreter::number_of_return_entries]; |
duke@435 | 183 | EntryPoint TemplateInterpreter::_earlyret_entry; |
duke@435 | 184 | EntryPoint TemplateInterpreter::_deopt_entry [TemplateInterpreter::number_of_deopt_entries ]; |
duke@435 | 185 | EntryPoint TemplateInterpreter::_continuation_entry; |
duke@435 | 186 | EntryPoint TemplateInterpreter::_safept_entry; |
duke@435 | 187 | |
duke@435 | 188 | address TemplateInterpreter::_return_3_addrs_by_index[TemplateInterpreter::number_of_return_addrs]; |
duke@435 | 189 | address TemplateInterpreter::_return_5_addrs_by_index[TemplateInterpreter::number_of_return_addrs]; |
duke@435 | 190 | |
duke@435 | 191 | DispatchTable TemplateInterpreter::_active_table; |
duke@435 | 192 | DispatchTable TemplateInterpreter::_normal_table; |
duke@435 | 193 | DispatchTable TemplateInterpreter::_safept_table; |
duke@435 | 194 | address TemplateInterpreter::_wentry_point[DispatchTable::length]; |
duke@435 | 195 | |
duke@435 | 196 | TemplateInterpreterGenerator::TemplateInterpreterGenerator(StubQueue* _code): AbstractInterpreterGenerator(_code) { |
duke@435 | 197 | _unimplemented_bytecode = NULL; |
duke@435 | 198 | _illegal_bytecode_sequence = NULL; |
duke@435 | 199 | } |
duke@435 | 200 | |
duke@435 | 201 | static const BasicType types[Interpreter::number_of_result_handlers] = { |
duke@435 | 202 | T_BOOLEAN, |
duke@435 | 203 | T_CHAR , |
duke@435 | 204 | T_BYTE , |
duke@435 | 205 | T_SHORT , |
duke@435 | 206 | T_INT , |
duke@435 | 207 | T_LONG , |
duke@435 | 208 | T_VOID , |
duke@435 | 209 | T_FLOAT , |
duke@435 | 210 | T_DOUBLE , |
duke@435 | 211 | T_OBJECT |
duke@435 | 212 | }; |
duke@435 | 213 | |
duke@435 | 214 | void TemplateInterpreterGenerator::generate_all() { |
duke@435 | 215 | AbstractInterpreterGenerator::generate_all(); |
duke@435 | 216 | |
duke@435 | 217 | { CodeletMark cm(_masm, "error exits"); |
duke@435 | 218 | _unimplemented_bytecode = generate_error_exit("unimplemented bytecode"); |
duke@435 | 219 | _illegal_bytecode_sequence = generate_error_exit("illegal bytecode sequence - method not verified"); |
duke@435 | 220 | } |
duke@435 | 221 | |
duke@435 | 222 | #ifndef PRODUCT |
duke@435 | 223 | if (TraceBytecodes) { |
duke@435 | 224 | CodeletMark cm(_masm, "bytecode tracing support"); |
duke@435 | 225 | Interpreter::_trace_code = |
duke@435 | 226 | EntryPoint( |
duke@435 | 227 | generate_trace_code(btos), |
duke@435 | 228 | generate_trace_code(ctos), |
duke@435 | 229 | generate_trace_code(stos), |
duke@435 | 230 | generate_trace_code(atos), |
duke@435 | 231 | generate_trace_code(itos), |
duke@435 | 232 | generate_trace_code(ltos), |
duke@435 | 233 | generate_trace_code(ftos), |
duke@435 | 234 | generate_trace_code(dtos), |
duke@435 | 235 | generate_trace_code(vtos) |
duke@435 | 236 | ); |
duke@435 | 237 | } |
duke@435 | 238 | #endif // !PRODUCT |
duke@435 | 239 | |
duke@435 | 240 | { CodeletMark cm(_masm, "return entry points"); |
duke@435 | 241 | for (int i = 0; i < Interpreter::number_of_return_entries; i++) { |
duke@435 | 242 | Interpreter::_return_entry[i] = |
duke@435 | 243 | EntryPoint( |
duke@435 | 244 | generate_return_entry_for(itos, i), |
duke@435 | 245 | generate_return_entry_for(itos, i), |
duke@435 | 246 | generate_return_entry_for(itos, i), |
duke@435 | 247 | generate_return_entry_for(atos, i), |
duke@435 | 248 | generate_return_entry_for(itos, i), |
duke@435 | 249 | generate_return_entry_for(ltos, i), |
duke@435 | 250 | generate_return_entry_for(ftos, i), |
duke@435 | 251 | generate_return_entry_for(dtos, i), |
duke@435 | 252 | generate_return_entry_for(vtos, i) |
duke@435 | 253 | ); |
duke@435 | 254 | } |
duke@435 | 255 | } |
duke@435 | 256 | |
duke@435 | 257 | { CodeletMark cm(_masm, "earlyret entry points"); |
duke@435 | 258 | Interpreter::_earlyret_entry = |
duke@435 | 259 | EntryPoint( |
duke@435 | 260 | generate_earlyret_entry_for(btos), |
duke@435 | 261 | generate_earlyret_entry_for(ctos), |
duke@435 | 262 | generate_earlyret_entry_for(stos), |
duke@435 | 263 | generate_earlyret_entry_for(atos), |
duke@435 | 264 | generate_earlyret_entry_for(itos), |
duke@435 | 265 | generate_earlyret_entry_for(ltos), |
duke@435 | 266 | generate_earlyret_entry_for(ftos), |
duke@435 | 267 | generate_earlyret_entry_for(dtos), |
duke@435 | 268 | generate_earlyret_entry_for(vtos) |
duke@435 | 269 | ); |
duke@435 | 270 | } |
duke@435 | 271 | |
duke@435 | 272 | { CodeletMark cm(_masm, "deoptimization entry points"); |
duke@435 | 273 | for (int i = 0; i < Interpreter::number_of_deopt_entries; i++) { |
duke@435 | 274 | Interpreter::_deopt_entry[i] = |
duke@435 | 275 | EntryPoint( |
duke@435 | 276 | generate_deopt_entry_for(itos, i), |
duke@435 | 277 | generate_deopt_entry_for(itos, i), |
duke@435 | 278 | generate_deopt_entry_for(itos, i), |
duke@435 | 279 | generate_deopt_entry_for(atos, i), |
duke@435 | 280 | generate_deopt_entry_for(itos, i), |
duke@435 | 281 | generate_deopt_entry_for(ltos, i), |
duke@435 | 282 | generate_deopt_entry_for(ftos, i), |
duke@435 | 283 | generate_deopt_entry_for(dtos, i), |
duke@435 | 284 | generate_deopt_entry_for(vtos, i) |
duke@435 | 285 | ); |
duke@435 | 286 | } |
duke@435 | 287 | } |
duke@435 | 288 | |
duke@435 | 289 | { CodeletMark cm(_masm, "result handlers for native calls"); |
duke@435 | 290 | // The various result converter stublets. |
duke@435 | 291 | int is_generated[Interpreter::number_of_result_handlers]; |
duke@435 | 292 | memset(is_generated, 0, sizeof(is_generated)); |
duke@435 | 293 | |
duke@435 | 294 | for (int i = 0; i < Interpreter::number_of_result_handlers; i++) { |
duke@435 | 295 | BasicType type = types[i]; |
duke@435 | 296 | if (!is_generated[Interpreter::BasicType_as_index(type)]++) { |
duke@435 | 297 | Interpreter::_native_abi_to_tosca[Interpreter::BasicType_as_index(type)] = generate_result_handler_for(type); |
duke@435 | 298 | } |
duke@435 | 299 | } |
duke@435 | 300 | } |
duke@435 | 301 | |
duke@435 | 302 | for (int j = 0; j < number_of_states; j++) { |
duke@435 | 303 | const TosState states[] = {btos, ctos, stos, itos, ltos, ftos, dtos, atos, vtos}; |
jrose@1161 | 304 | int index = Interpreter::TosState_as_index(states[j]); |
jrose@1161 | 305 | Interpreter::_return_3_addrs_by_index[index] = Interpreter::return_entry(states[j], 3); |
jrose@1161 | 306 | Interpreter::_return_5_addrs_by_index[index] = Interpreter::return_entry(states[j], 5); |
duke@435 | 307 | } |
duke@435 | 308 | |
duke@435 | 309 | { CodeletMark cm(_masm, "continuation entry points"); |
duke@435 | 310 | Interpreter::_continuation_entry = |
duke@435 | 311 | EntryPoint( |
duke@435 | 312 | generate_continuation_for(btos), |
duke@435 | 313 | generate_continuation_for(ctos), |
duke@435 | 314 | generate_continuation_for(stos), |
duke@435 | 315 | generate_continuation_for(atos), |
duke@435 | 316 | generate_continuation_for(itos), |
duke@435 | 317 | generate_continuation_for(ltos), |
duke@435 | 318 | generate_continuation_for(ftos), |
duke@435 | 319 | generate_continuation_for(dtos), |
duke@435 | 320 | generate_continuation_for(vtos) |
duke@435 | 321 | ); |
duke@435 | 322 | } |
duke@435 | 323 | |
duke@435 | 324 | { CodeletMark cm(_masm, "safepoint entry points"); |
duke@435 | 325 | Interpreter::_safept_entry = |
duke@435 | 326 | EntryPoint( |
duke@435 | 327 | generate_safept_entry_for(btos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), |
duke@435 | 328 | generate_safept_entry_for(ctos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), |
duke@435 | 329 | generate_safept_entry_for(stos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), |
duke@435 | 330 | generate_safept_entry_for(atos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), |
duke@435 | 331 | generate_safept_entry_for(itos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), |
duke@435 | 332 | generate_safept_entry_for(ltos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), |
duke@435 | 333 | generate_safept_entry_for(ftos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), |
duke@435 | 334 | generate_safept_entry_for(dtos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), |
duke@435 | 335 | generate_safept_entry_for(vtos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)) |
duke@435 | 336 | ); |
duke@435 | 337 | } |
duke@435 | 338 | |
duke@435 | 339 | { CodeletMark cm(_masm, "exception handling"); |
duke@435 | 340 | // (Note: this is not safepoint safe because thread may return to compiled code) |
duke@435 | 341 | generate_throw_exception(); |
duke@435 | 342 | } |
duke@435 | 343 | |
duke@435 | 344 | { CodeletMark cm(_masm, "throw exception entrypoints"); |
duke@435 | 345 | Interpreter::_throw_ArrayIndexOutOfBoundsException_entry = generate_ArrayIndexOutOfBounds_handler("java/lang/ArrayIndexOutOfBoundsException"); |
duke@435 | 346 | Interpreter::_throw_ArrayStoreException_entry = generate_klass_exception_handler("java/lang/ArrayStoreException" ); |
duke@435 | 347 | Interpreter::_throw_ArithmeticException_entry = generate_exception_handler("java/lang/ArithmeticException" , "/ by zero"); |
duke@435 | 348 | Interpreter::_throw_ClassCastException_entry = generate_ClassCastException_handler(); |
jrose@1145 | 349 | Interpreter::_throw_WrongMethodType_entry = generate_WrongMethodType_handler(); |
duke@435 | 350 | Interpreter::_throw_NullPointerException_entry = generate_exception_handler("java/lang/NullPointerException" , NULL ); |
duke@435 | 351 | Interpreter::_throw_StackOverflowError_entry = generate_StackOverflowError_handler(); |
duke@435 | 352 | } |
duke@435 | 353 | |
duke@435 | 354 | |
duke@435 | 355 | |
duke@435 | 356 | #define method_entry(kind) \ |
duke@435 | 357 | { CodeletMark cm(_masm, "method entry point (kind = " #kind ")"); \ |
duke@435 | 358 | Interpreter::_entry_table[Interpreter::kind] = generate_method_entry(Interpreter::kind); \ |
duke@435 | 359 | } |
duke@435 | 360 | |
duke@435 | 361 | // all non-native method kinds |
duke@435 | 362 | method_entry(zerolocals) |
duke@435 | 363 | method_entry(zerolocals_synchronized) |
duke@435 | 364 | method_entry(empty) |
duke@435 | 365 | method_entry(accessor) |
duke@435 | 366 | method_entry(abstract) |
jrose@1145 | 367 | method_entry(method_handle) |
duke@435 | 368 | method_entry(java_lang_math_sin ) |
duke@435 | 369 | method_entry(java_lang_math_cos ) |
duke@435 | 370 | method_entry(java_lang_math_tan ) |
duke@435 | 371 | method_entry(java_lang_math_abs ) |
duke@435 | 372 | method_entry(java_lang_math_sqrt ) |
duke@435 | 373 | method_entry(java_lang_math_log ) |
duke@435 | 374 | method_entry(java_lang_math_log10) |
duke@435 | 375 | |
duke@435 | 376 | // all native method kinds (must be one contiguous block) |
duke@435 | 377 | Interpreter::_native_entry_begin = Interpreter::code()->code_end(); |
duke@435 | 378 | method_entry(native) |
duke@435 | 379 | method_entry(native_synchronized) |
duke@435 | 380 | Interpreter::_native_entry_end = Interpreter::code()->code_end(); |
duke@435 | 381 | |
duke@435 | 382 | #undef method_entry |
duke@435 | 383 | |
duke@435 | 384 | // Bytecodes |
duke@435 | 385 | set_entry_points_for_all_bytes(); |
duke@435 | 386 | set_safepoints_for_all_bytes(); |
duke@435 | 387 | } |
duke@435 | 388 | |
duke@435 | 389 | //------------------------------------------------------------------------------------------------------------------------ |
duke@435 | 390 | |
duke@435 | 391 | address TemplateInterpreterGenerator::generate_error_exit(const char* msg) { |
duke@435 | 392 | address entry = __ pc(); |
duke@435 | 393 | __ stop(msg); |
duke@435 | 394 | return entry; |
duke@435 | 395 | } |
duke@435 | 396 | |
duke@435 | 397 | |
duke@435 | 398 | //------------------------------------------------------------------------------------------------------------------------ |
duke@435 | 399 | |
duke@435 | 400 | void TemplateInterpreterGenerator::set_entry_points_for_all_bytes() { |
duke@435 | 401 | for (int i = 0; i < DispatchTable::length; i++) { |
duke@435 | 402 | Bytecodes::Code code = (Bytecodes::Code)i; |
duke@435 | 403 | if (Bytecodes::is_defined(code)) { |
duke@435 | 404 | set_entry_points(code); |
duke@435 | 405 | } else { |
duke@435 | 406 | set_unimplemented(i); |
duke@435 | 407 | } |
duke@435 | 408 | } |
duke@435 | 409 | } |
duke@435 | 410 | |
duke@435 | 411 | |
duke@435 | 412 | void TemplateInterpreterGenerator::set_safepoints_for_all_bytes() { |
duke@435 | 413 | for (int i = 0; i < DispatchTable::length; i++) { |
duke@435 | 414 | Bytecodes::Code code = (Bytecodes::Code)i; |
duke@435 | 415 | if (Bytecodes::is_defined(code)) Interpreter::_safept_table.set_entry(code, Interpreter::_safept_entry); |
duke@435 | 416 | } |
duke@435 | 417 | } |
duke@435 | 418 | |
duke@435 | 419 | |
duke@435 | 420 | void TemplateInterpreterGenerator::set_unimplemented(int i) { |
duke@435 | 421 | address e = _unimplemented_bytecode; |
duke@435 | 422 | EntryPoint entry(e, e, e, e, e, e, e, e, e); |
duke@435 | 423 | Interpreter::_normal_table.set_entry(i, entry); |
duke@435 | 424 | Interpreter::_wentry_point[i] = _unimplemented_bytecode; |
duke@435 | 425 | } |
duke@435 | 426 | |
duke@435 | 427 | |
duke@435 | 428 | void TemplateInterpreterGenerator::set_entry_points(Bytecodes::Code code) { |
duke@435 | 429 | CodeletMark cm(_masm, Bytecodes::name(code), code); |
duke@435 | 430 | // initialize entry points |
duke@435 | 431 | assert(_unimplemented_bytecode != NULL, "should have been generated before"); |
duke@435 | 432 | assert(_illegal_bytecode_sequence != NULL, "should have been generated before"); |
duke@435 | 433 | address bep = _illegal_bytecode_sequence; |
duke@435 | 434 | address cep = _illegal_bytecode_sequence; |
duke@435 | 435 | address sep = _illegal_bytecode_sequence; |
duke@435 | 436 | address aep = _illegal_bytecode_sequence; |
duke@435 | 437 | address iep = _illegal_bytecode_sequence; |
duke@435 | 438 | address lep = _illegal_bytecode_sequence; |
duke@435 | 439 | address fep = _illegal_bytecode_sequence; |
duke@435 | 440 | address dep = _illegal_bytecode_sequence; |
duke@435 | 441 | address vep = _unimplemented_bytecode; |
duke@435 | 442 | address wep = _unimplemented_bytecode; |
duke@435 | 443 | // code for short & wide version of bytecode |
duke@435 | 444 | if (Bytecodes::is_defined(code)) { |
duke@435 | 445 | Template* t = TemplateTable::template_for(code); |
duke@435 | 446 | assert(t->is_valid(), "just checking"); |
duke@435 | 447 | set_short_entry_points(t, bep, cep, sep, aep, iep, lep, fep, dep, vep); |
duke@435 | 448 | } |
duke@435 | 449 | if (Bytecodes::wide_is_defined(code)) { |
duke@435 | 450 | Template* t = TemplateTable::template_for_wide(code); |
duke@435 | 451 | assert(t->is_valid(), "just checking"); |
duke@435 | 452 | set_wide_entry_point(t, wep); |
duke@435 | 453 | } |
duke@435 | 454 | // set entry points |
duke@435 | 455 | EntryPoint entry(bep, cep, sep, aep, iep, lep, fep, dep, vep); |
duke@435 | 456 | Interpreter::_normal_table.set_entry(code, entry); |
duke@435 | 457 | Interpreter::_wentry_point[code] = wep; |
duke@435 | 458 | } |
duke@435 | 459 | |
duke@435 | 460 | |
duke@435 | 461 | void TemplateInterpreterGenerator::set_wide_entry_point(Template* t, address& wep) { |
duke@435 | 462 | assert(t->is_valid(), "template must exist"); |
jcoomes@1844 | 463 | assert(t->tos_in() == vtos, "only vtos tos_in supported for wide instructions"); |
duke@435 | 464 | wep = __ pc(); generate_and_dispatch(t); |
duke@435 | 465 | } |
duke@435 | 466 | |
duke@435 | 467 | |
duke@435 | 468 | void TemplateInterpreterGenerator::set_short_entry_points(Template* t, address& bep, address& cep, address& sep, address& aep, address& iep, address& lep, address& fep, address& dep, address& vep) { |
duke@435 | 469 | assert(t->is_valid(), "template must exist"); |
duke@435 | 470 | switch (t->tos_in()) { |
twisti@1506 | 471 | case btos: |
twisti@1506 | 472 | case ctos: |
twisti@1506 | 473 | case stos: |
twisti@1506 | 474 | ShouldNotReachHere(); // btos/ctos/stos should use itos. |
twisti@1506 | 475 | break; |
duke@435 | 476 | case atos: vep = __ pc(); __ pop(atos); aep = __ pc(); generate_and_dispatch(t); break; |
duke@435 | 477 | case itos: vep = __ pc(); __ pop(itos); iep = __ pc(); generate_and_dispatch(t); break; |
duke@435 | 478 | case ltos: vep = __ pc(); __ pop(ltos); lep = __ pc(); generate_and_dispatch(t); break; |
duke@435 | 479 | case ftos: vep = __ pc(); __ pop(ftos); fep = __ pc(); generate_and_dispatch(t); break; |
duke@435 | 480 | case dtos: vep = __ pc(); __ pop(dtos); dep = __ pc(); generate_and_dispatch(t); break; |
duke@435 | 481 | case vtos: set_vtos_entry_points(t, bep, cep, sep, aep, iep, lep, fep, dep, vep); break; |
duke@435 | 482 | default : ShouldNotReachHere(); break; |
duke@435 | 483 | } |
duke@435 | 484 | } |
duke@435 | 485 | |
duke@435 | 486 | |
duke@435 | 487 | //------------------------------------------------------------------------------------------------------------------------ |
duke@435 | 488 | |
duke@435 | 489 | void TemplateInterpreterGenerator::generate_and_dispatch(Template* t, TosState tos_out) { |
duke@435 | 490 | if (PrintBytecodeHistogram) histogram_bytecode(t); |
duke@435 | 491 | #ifndef PRODUCT |
duke@435 | 492 | // debugging code |
duke@435 | 493 | if (CountBytecodes || TraceBytecodes || StopInterpreterAt > 0) count_bytecode(); |
duke@435 | 494 | if (PrintBytecodePairHistogram) histogram_bytecode_pair(t); |
duke@435 | 495 | if (TraceBytecodes) trace_bytecode(t); |
duke@435 | 496 | if (StopInterpreterAt > 0) stop_interpreter_at(); |
duke@435 | 497 | __ verify_FPU(1, t->tos_in()); |
duke@435 | 498 | #endif // !PRODUCT |
duke@435 | 499 | int step; |
duke@435 | 500 | if (!t->does_dispatch()) { |
duke@435 | 501 | step = t->is_wide() ? Bytecodes::wide_length_for(t->bytecode()) : Bytecodes::length_for(t->bytecode()); |
duke@435 | 502 | if (tos_out == ilgl) tos_out = t->tos_out(); |
duke@435 | 503 | // compute bytecode size |
duke@435 | 504 | assert(step > 0, "just checkin'"); |
duke@435 | 505 | // setup stuff for dispatching next bytecode |
duke@435 | 506 | if (ProfileInterpreter && VerifyDataPointer |
duke@435 | 507 | && methodDataOopDesc::bytecode_has_profile(t->bytecode())) { |
duke@435 | 508 | __ verify_method_data_pointer(); |
duke@435 | 509 | } |
duke@435 | 510 | __ dispatch_prolog(tos_out, step); |
duke@435 | 511 | } |
duke@435 | 512 | // generate template |
duke@435 | 513 | t->generate(_masm); |
duke@435 | 514 | // advance |
duke@435 | 515 | if (t->does_dispatch()) { |
duke@435 | 516 | #ifdef ASSERT |
duke@435 | 517 | // make sure execution doesn't go beyond this point if code is broken |
duke@435 | 518 | __ should_not_reach_here(); |
duke@435 | 519 | #endif // ASSERT |
duke@435 | 520 | } else { |
duke@435 | 521 | // dispatch to next bytecode |
duke@435 | 522 | __ dispatch_epilog(tos_out, step); |
duke@435 | 523 | } |
duke@435 | 524 | } |
duke@435 | 525 | |
duke@435 | 526 | //------------------------------------------------------------------------------------------------------------------------ |
duke@435 | 527 | // Entry points |
duke@435 | 528 | |
duke@435 | 529 | address TemplateInterpreter::return_entry(TosState state, int length) { |
duke@435 | 530 | guarantee(0 <= length && length < Interpreter::number_of_return_entries, "illegal length"); |
duke@435 | 531 | return _return_entry[length].entry(state); |
duke@435 | 532 | } |
duke@435 | 533 | |
duke@435 | 534 | |
duke@435 | 535 | address TemplateInterpreter::deopt_entry(TosState state, int length) { |
duke@435 | 536 | guarantee(0 <= length && length < Interpreter::number_of_deopt_entries, "illegal length"); |
duke@435 | 537 | return _deopt_entry[length].entry(state); |
duke@435 | 538 | } |
duke@435 | 539 | |
duke@435 | 540 | //------------------------------------------------------------------------------------------------------------------------ |
duke@435 | 541 | // Suport for invokes |
duke@435 | 542 | |
duke@435 | 543 | int TemplateInterpreter::TosState_as_index(TosState state) { |
duke@435 | 544 | assert( state < number_of_states , "Invalid state in TosState_as_index"); |
duke@435 | 545 | assert(0 <= (int)state && (int)state < TemplateInterpreter::number_of_return_addrs, "index out of bounds"); |
duke@435 | 546 | return (int)state; |
duke@435 | 547 | } |
duke@435 | 548 | |
duke@435 | 549 | |
duke@435 | 550 | //------------------------------------------------------------------------------------------------------------------------ |
duke@435 | 551 | // Safepoint suppport |
duke@435 | 552 | |
duke@435 | 553 | static inline void copy_table(address* from, address* to, int size) { |
duke@435 | 554 | // Copy non-overlapping tables. The copy has to occur word wise for MT safety. |
duke@435 | 555 | while (size-- > 0) *to++ = *from++; |
duke@435 | 556 | } |
duke@435 | 557 | |
duke@435 | 558 | void TemplateInterpreter::notice_safepoints() { |
duke@435 | 559 | if (!_notice_safepoints) { |
duke@435 | 560 | // switch to safepoint dispatch table |
duke@435 | 561 | _notice_safepoints = true; |
duke@435 | 562 | copy_table((address*)&_safept_table, (address*)&_active_table, sizeof(_active_table) / sizeof(address)); |
duke@435 | 563 | } |
duke@435 | 564 | } |
duke@435 | 565 | |
duke@435 | 566 | // switch from the dispatch table which notices safepoints back to the |
duke@435 | 567 | // normal dispatch table. So that we can notice single stepping points, |
duke@435 | 568 | // keep the safepoint dispatch table if we are single stepping in JVMTI. |
duke@435 | 569 | // Note that the should_post_single_step test is exactly as fast as the |
duke@435 | 570 | // JvmtiExport::_enabled test and covers both cases. |
duke@435 | 571 | void TemplateInterpreter::ignore_safepoints() { |
duke@435 | 572 | if (_notice_safepoints) { |
duke@435 | 573 | if (!JvmtiExport::should_post_single_step()) { |
duke@435 | 574 | // switch to normal dispatch table |
duke@435 | 575 | _notice_safepoints = false; |
duke@435 | 576 | copy_table((address*)&_normal_table, (address*)&_active_table, sizeof(_active_table) / sizeof(address)); |
duke@435 | 577 | } |
duke@435 | 578 | } |
duke@435 | 579 | } |
duke@435 | 580 | |
cfang@1335 | 581 | //------------------------------------------------------------------------------------------------------------------------ |
cfang@1335 | 582 | // Deoptimization support |
duke@435 | 583 | |
cfang@1335 | 584 | // If deoptimization happens, this function returns the point of next bytecode to continue execution |
cfang@1335 | 585 | address TemplateInterpreter::deopt_continue_after_entry(methodOop method, address bcp, int callee_parameters, bool is_top_frame) { |
cfang@1335 | 586 | return AbstractInterpreter::deopt_continue_after_entry(method, bcp, callee_parameters, is_top_frame); |
cfang@1335 | 587 | } |
duke@435 | 588 | |
cfang@1335 | 589 | // If deoptimization happens, this function returns the point where the interpreter reexecutes |
cfang@1335 | 590 | // the bytecode. |
cfang@1335 | 591 | // Note: Bytecodes::_athrow (C1 only) and Bytecodes::_return are the special cases |
cfang@1335 | 592 | // that do not return "Interpreter::deopt_entry(vtos, 0)" |
cfang@1335 | 593 | address TemplateInterpreter::deopt_reexecute_entry(methodOop method, address bcp) { |
duke@435 | 594 | assert(method->contains(bcp), "just checkin'"); |
never@2462 | 595 | Bytecodes::Code code = Bytecodes::java_code_at(method, bcp); |
duke@435 | 596 | if (code == Bytecodes::_return) { |
cfang@1335 | 597 | // This is used for deopt during registration of finalizers |
cfang@1335 | 598 | // during Object.<init>. We simply need to resume execution at |
cfang@1335 | 599 | // the standard return vtos bytecode to pop the frame normally. |
cfang@1335 | 600 | // reexecuting the real bytecode would cause double registration |
cfang@1335 | 601 | // of the finalizable object. |
cfang@1335 | 602 | return _normal_table.entry(Bytecodes::_return).entry(vtos); |
duke@435 | 603 | } else { |
cfang@1335 | 604 | return AbstractInterpreter::deopt_reexecute_entry(method, bcp); |
cfang@1335 | 605 | } |
cfang@1335 | 606 | } |
cfang@1335 | 607 | |
cfang@1335 | 608 | // If deoptimization happens, the interpreter should reexecute this bytecode. |
cfang@1335 | 609 | // This function mainly helps the compilers to set up the reexecute bit. |
cfang@1335 | 610 | bool TemplateInterpreter::bytecode_should_reexecute(Bytecodes::Code code) { |
cfang@1335 | 611 | if (code == Bytecodes::_return) { |
cfang@1335 | 612 | //Yes, we consider Bytecodes::_return as a special case of reexecution |
cfang@1335 | 613 | return true; |
cfang@1335 | 614 | } else { |
cfang@1335 | 615 | return AbstractInterpreter::bytecode_should_reexecute(code); |
duke@435 | 616 | } |
duke@435 | 617 | } |
duke@435 | 618 | |
duke@435 | 619 | #endif // !CC_INTERP |