Wed, 21 May 2008 16:31:35 -0700
6703888: Compressed Oops: use the 32-bits gap after klass in a object
Summary: Use the gap also for a narrow oop field and a boxing object value.
Reviewed-by: coleenp, never
duke@435 | 1 | /* |
duke@435 | 2 | * Copyright 2003-2007 Sun Microsystems, Inc. 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 | * |
duke@435 | 19 | * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
duke@435 | 20 | * CA 95054 USA or visit www.sun.com if you need additional information or |
duke@435 | 21 | * have any questions. |
duke@435 | 22 | * |
duke@435 | 23 | */ |
duke@435 | 24 | |
duke@435 | 25 | #include "incls/_precompiled.incl" |
duke@435 | 26 | #include "incls/_interpreter_x86_64.cpp.incl" |
duke@435 | 27 | |
duke@435 | 28 | #define __ _masm-> |
duke@435 | 29 | |
duke@435 | 30 | |
duke@435 | 31 | #ifdef _WIN64 |
duke@435 | 32 | address AbstractInterpreterGenerator::generate_slow_signature_handler() { |
duke@435 | 33 | address entry = __ pc(); |
duke@435 | 34 | |
duke@435 | 35 | // rbx: method |
duke@435 | 36 | // r14: pointer to locals |
duke@435 | 37 | // c_rarg3: first stack arg - wordSize |
duke@435 | 38 | __ movq(c_rarg3, rsp); |
duke@435 | 39 | // adjust rsp |
duke@435 | 40 | __ subq(rsp, 4 * wordSize); |
duke@435 | 41 | __ call_VM(noreg, |
duke@435 | 42 | CAST_FROM_FN_PTR(address, |
duke@435 | 43 | InterpreterRuntime::slow_signature_handler), |
duke@435 | 44 | rbx, r14, c_rarg3); |
duke@435 | 45 | |
duke@435 | 46 | // rax: result handler |
duke@435 | 47 | |
duke@435 | 48 | // Stack layout: |
duke@435 | 49 | // rsp: 3 integer or float args (if static first is unused) |
duke@435 | 50 | // 1 float/double identifiers |
duke@435 | 51 | // return address |
duke@435 | 52 | // stack args |
duke@435 | 53 | // garbage |
duke@435 | 54 | // expression stack bottom |
duke@435 | 55 | // bcp (NULL) |
duke@435 | 56 | // ... |
duke@435 | 57 | |
duke@435 | 58 | // Do FP first so we can use c_rarg3 as temp |
duke@435 | 59 | __ movl(c_rarg3, Address(rsp, 3 * wordSize)); // float/double identifiers |
duke@435 | 60 | |
duke@435 | 61 | for ( int i= 0; i < Argument::n_int_register_parameters_c-1; i++ ) { |
duke@435 | 62 | XMMRegister floatreg = as_XMMRegister(i+1); |
duke@435 | 63 | Label isfloatordouble, isdouble, next; |
duke@435 | 64 | |
duke@435 | 65 | __ testl(c_rarg3, 1 << (i*2)); // Float or Double? |
duke@435 | 66 | __ jcc(Assembler::notZero, isfloatordouble); |
duke@435 | 67 | |
duke@435 | 68 | // Do Int register here |
duke@435 | 69 | switch ( i ) { |
duke@435 | 70 | case 0: |
duke@435 | 71 | __ movl(rscratch1, Address(rbx, methodOopDesc::access_flags_offset())); |
duke@435 | 72 | __ testl(rscratch1, JVM_ACC_STATIC); |
duke@435 | 73 | __ cmovq(Assembler::zero, c_rarg1, Address(rsp, 0)); |
duke@435 | 74 | break; |
duke@435 | 75 | case 1: |
duke@435 | 76 | __ movq(c_rarg2, Address(rsp, wordSize)); |
duke@435 | 77 | break; |
duke@435 | 78 | case 2: |
duke@435 | 79 | __ movq(c_rarg3, Address(rsp, 2 * wordSize)); |
duke@435 | 80 | break; |
duke@435 | 81 | default: |
duke@435 | 82 | break; |
duke@435 | 83 | } |
duke@435 | 84 | |
duke@435 | 85 | __ jmp (next); |
duke@435 | 86 | |
duke@435 | 87 | __ bind(isfloatordouble); |
duke@435 | 88 | __ testl(c_rarg3, 1 << ((i*2)+1)); // Double? |
duke@435 | 89 | __ jcc(Assembler::notZero, isdouble); |
duke@435 | 90 | |
duke@435 | 91 | // Do Float Here |
duke@435 | 92 | __ movflt(floatreg, Address(rsp, i * wordSize)); |
duke@435 | 93 | __ jmp(next); |
duke@435 | 94 | |
duke@435 | 95 | // Do Double here |
duke@435 | 96 | __ bind(isdouble); |
duke@435 | 97 | __ movdbl(floatreg, Address(rsp, i * wordSize)); |
duke@435 | 98 | |
duke@435 | 99 | __ bind(next); |
duke@435 | 100 | } |
duke@435 | 101 | |
duke@435 | 102 | |
duke@435 | 103 | // restore rsp |
duke@435 | 104 | __ addq(rsp, 4 * wordSize); |
duke@435 | 105 | |
duke@435 | 106 | __ ret(0); |
duke@435 | 107 | |
duke@435 | 108 | return entry; |
duke@435 | 109 | } |
duke@435 | 110 | #else |
duke@435 | 111 | address AbstractInterpreterGenerator::generate_slow_signature_handler() { |
duke@435 | 112 | address entry = __ pc(); |
duke@435 | 113 | |
duke@435 | 114 | // rbx: method |
duke@435 | 115 | // r14: pointer to locals |
duke@435 | 116 | // c_rarg3: first stack arg - wordSize |
duke@435 | 117 | __ movq(c_rarg3, rsp); |
duke@435 | 118 | // adjust rsp |
duke@435 | 119 | __ subq(rsp, 14 * wordSize); |
duke@435 | 120 | __ call_VM(noreg, |
duke@435 | 121 | CAST_FROM_FN_PTR(address, |
duke@435 | 122 | InterpreterRuntime::slow_signature_handler), |
duke@435 | 123 | rbx, r14, c_rarg3); |
duke@435 | 124 | |
duke@435 | 125 | // rax: result handler |
duke@435 | 126 | |
duke@435 | 127 | // Stack layout: |
duke@435 | 128 | // rsp: 5 integer args (if static first is unused) |
duke@435 | 129 | // 1 float/double identifiers |
duke@435 | 130 | // 8 double args |
duke@435 | 131 | // return address |
duke@435 | 132 | // stack args |
duke@435 | 133 | // garbage |
duke@435 | 134 | // expression stack bottom |
duke@435 | 135 | // bcp (NULL) |
duke@435 | 136 | // ... |
duke@435 | 137 | |
duke@435 | 138 | // Do FP first so we can use c_rarg3 as temp |
duke@435 | 139 | __ movl(c_rarg3, Address(rsp, 5 * wordSize)); // float/double identifiers |
duke@435 | 140 | |
duke@435 | 141 | for (int i = 0; i < Argument::n_float_register_parameters_c; i++) { |
duke@435 | 142 | const XMMRegister r = as_XMMRegister(i); |
duke@435 | 143 | |
duke@435 | 144 | Label d, done; |
duke@435 | 145 | |
duke@435 | 146 | __ testl(c_rarg3, 1 << i); |
duke@435 | 147 | __ jcc(Assembler::notZero, d); |
duke@435 | 148 | __ movflt(r, Address(rsp, (6 + i) * wordSize)); |
duke@435 | 149 | __ jmp(done); |
duke@435 | 150 | __ bind(d); |
duke@435 | 151 | __ movdbl(r, Address(rsp, (6 + i) * wordSize)); |
duke@435 | 152 | __ bind(done); |
duke@435 | 153 | } |
duke@435 | 154 | |
duke@435 | 155 | // Now handle integrals. Only do c_rarg1 if not static. |
duke@435 | 156 | __ movl(c_rarg3, Address(rbx, methodOopDesc::access_flags_offset())); |
duke@435 | 157 | __ testl(c_rarg3, JVM_ACC_STATIC); |
duke@435 | 158 | __ cmovq(Assembler::zero, c_rarg1, Address(rsp, 0)); |
duke@435 | 159 | |
duke@435 | 160 | __ movq(c_rarg2, Address(rsp, wordSize)); |
duke@435 | 161 | __ movq(c_rarg3, Address(rsp, 2 * wordSize)); |
duke@435 | 162 | __ movq(c_rarg4, Address(rsp, 3 * wordSize)); |
duke@435 | 163 | __ movq(c_rarg5, Address(rsp, 4 * wordSize)); |
duke@435 | 164 | |
duke@435 | 165 | // restore rsp |
duke@435 | 166 | __ addq(rsp, 14 * wordSize); |
duke@435 | 167 | |
duke@435 | 168 | __ ret(0); |
duke@435 | 169 | |
duke@435 | 170 | return entry; |
duke@435 | 171 | } |
duke@435 | 172 | #endif |
duke@435 | 173 | |
duke@435 | 174 | |
duke@435 | 175 | // |
duke@435 | 176 | // Various method entries |
duke@435 | 177 | // |
duke@435 | 178 | |
duke@435 | 179 | address InterpreterGenerator::generate_math_entry( |
duke@435 | 180 | AbstractInterpreter::MethodKind kind) { |
duke@435 | 181 | // rbx: methodOop |
duke@435 | 182 | |
duke@435 | 183 | if (!InlineIntrinsics) return NULL; // Generate a vanilla entry |
duke@435 | 184 | |
duke@435 | 185 | assert(kind == Interpreter::java_lang_math_sqrt, |
duke@435 | 186 | "Other intrinsics are not special"); |
duke@435 | 187 | |
duke@435 | 188 | address entry_point = __ pc(); |
duke@435 | 189 | |
duke@435 | 190 | // These don't need a safepoint check because they aren't virtually |
duke@435 | 191 | // callable. We won't enter these intrinsics from compiled code. |
duke@435 | 192 | // If in the future we added an intrinsic which was virtually callable |
duke@435 | 193 | // we'd have to worry about how to safepoint so that this code is used. |
duke@435 | 194 | |
duke@435 | 195 | // mathematical functions inlined by compiler |
duke@435 | 196 | // (interpreter must provide identical implementation |
duke@435 | 197 | // in order to avoid monotonicity bugs when switching |
duke@435 | 198 | // from interpreter to compiler in the middle of some |
duke@435 | 199 | // computation) |
duke@435 | 200 | |
duke@435 | 201 | // Note: For JDK 1.2 StrictMath doesn't exist and Math.sin/cos/sqrt are |
duke@435 | 202 | // native methods. Interpreter::method_kind(...) does a check for |
duke@435 | 203 | // native methods first before checking for intrinsic methods and |
duke@435 | 204 | // thus will never select this entry point. Make sure it is not |
duke@435 | 205 | // called accidentally since the SharedRuntime entry points will |
duke@435 | 206 | // not work for JDK 1.2. |
duke@435 | 207 | // |
duke@435 | 208 | // We no longer need to check for JDK 1.2 since it's EOL'ed. |
duke@435 | 209 | // The following check existed in pre 1.6 implementation, |
duke@435 | 210 | // if (Universe::is_jdk12x_version()) { |
duke@435 | 211 | // __ should_not_reach_here(); |
duke@435 | 212 | // } |
duke@435 | 213 | // Universe::is_jdk12x_version() always returns false since |
duke@435 | 214 | // the JDK version is not yet determined when this method is called. |
duke@435 | 215 | // This method is called during interpreter_init() whereas |
duke@435 | 216 | // JDK version is only determined when universe2_init() is called. |
duke@435 | 217 | |
duke@435 | 218 | // Note: For JDK 1.3 StrictMath exists and Math.sin/cos/sqrt are |
duke@435 | 219 | // java methods. Interpreter::method_kind(...) will select |
duke@435 | 220 | // this entry point for the corresponding methods in JDK 1.3. |
duke@435 | 221 | __ sqrtsd(xmm0, Address(rsp, wordSize)); |
duke@435 | 222 | |
duke@435 | 223 | __ popq(rax); |
duke@435 | 224 | __ movq(rsp, r13); |
duke@435 | 225 | __ jmp(rax); |
duke@435 | 226 | |
duke@435 | 227 | return entry_point; |
duke@435 | 228 | } |
duke@435 | 229 | |
duke@435 | 230 | |
duke@435 | 231 | // Abstract method entry |
duke@435 | 232 | // Attempt to execute abstract method. Throw exception |
duke@435 | 233 | address InterpreterGenerator::generate_abstract_entry(void) { |
duke@435 | 234 | // rbx: methodOop |
duke@435 | 235 | // r13: sender SP |
duke@435 | 236 | |
duke@435 | 237 | address entry_point = __ pc(); |
duke@435 | 238 | |
duke@435 | 239 | // abstract method entry |
duke@435 | 240 | // remove return address. Not really needed, since exception |
duke@435 | 241 | // handling throws away expression stack |
duke@435 | 242 | __ popq(rbx); |
duke@435 | 243 | |
duke@435 | 244 | // adjust stack to what a normal return would do |
duke@435 | 245 | __ movq(rsp, r13); |
duke@435 | 246 | |
duke@435 | 247 | // throw exception |
duke@435 | 248 | __ call_VM(noreg, CAST_FROM_FN_PTR(address, |
duke@435 | 249 | InterpreterRuntime::throw_AbstractMethodError)); |
duke@435 | 250 | // the call_VM checks for exception, so we should never return here. |
duke@435 | 251 | __ should_not_reach_here(); |
duke@435 | 252 | |
duke@435 | 253 | return entry_point; |
duke@435 | 254 | } |
duke@435 | 255 | |
duke@435 | 256 | |
duke@435 | 257 | // Empty method, generate a very fast return. |
duke@435 | 258 | |
duke@435 | 259 | address InterpreterGenerator::generate_empty_entry(void) { |
duke@435 | 260 | // rbx: methodOop |
duke@435 | 261 | // r13: sender sp must set sp to this value on return |
duke@435 | 262 | |
duke@435 | 263 | if (!UseFastEmptyMethods) { |
duke@435 | 264 | return NULL; |
duke@435 | 265 | } |
duke@435 | 266 | |
duke@435 | 267 | address entry_point = __ pc(); |
duke@435 | 268 | |
duke@435 | 269 | // If we need a safepoint check, generate full interpreter entry. |
duke@435 | 270 | Label slow_path; |
duke@435 | 271 | __ cmp32(ExternalAddress(SafepointSynchronize::address_of_state()), |
duke@435 | 272 | SafepointSynchronize::_not_synchronized); |
duke@435 | 273 | __ jcc(Assembler::notEqual, slow_path); |
duke@435 | 274 | |
duke@435 | 275 | // do nothing for empty methods (do not even increment invocation counter) |
duke@435 | 276 | // Code: _return |
duke@435 | 277 | // _return |
duke@435 | 278 | // return w/o popping parameters |
duke@435 | 279 | __ popq(rax); |
duke@435 | 280 | __ movq(rsp, r13); |
duke@435 | 281 | __ jmp(rax); |
duke@435 | 282 | |
duke@435 | 283 | __ bind(slow_path); |
duke@435 | 284 | (void) generate_normal_entry(false); |
duke@435 | 285 | return entry_point; |
duke@435 | 286 | |
duke@435 | 287 | } |
duke@435 | 288 | |
duke@435 | 289 | // Call an accessor method (assuming it is resolved, otherwise drop |
duke@435 | 290 | // into vanilla (slow path) entry |
duke@435 | 291 | address InterpreterGenerator::generate_accessor_entry(void) { |
duke@435 | 292 | // rbx: methodOop |
duke@435 | 293 | |
duke@435 | 294 | // r13: senderSP must preserver for slow path, set SP to it on fast path |
duke@435 | 295 | |
duke@435 | 296 | address entry_point = __ pc(); |
duke@435 | 297 | Label xreturn_path; |
duke@435 | 298 | |
duke@435 | 299 | // do fastpath for resolved accessor methods |
duke@435 | 300 | if (UseFastAccessorMethods) { |
duke@435 | 301 | // Code: _aload_0, _(i|a)getfield, _(i|a)return or any rewrites |
duke@435 | 302 | // thereof; parameter size = 1 |
duke@435 | 303 | // Note: We can only use this code if the getfield has been resolved |
duke@435 | 304 | // and if we don't have a null-pointer exception => check for |
duke@435 | 305 | // these conditions first and use slow path if necessary. |
duke@435 | 306 | Label slow_path; |
duke@435 | 307 | // If we need a safepoint check, generate full interpreter entry. |
duke@435 | 308 | __ cmp32(ExternalAddress(SafepointSynchronize::address_of_state()), |
duke@435 | 309 | SafepointSynchronize::_not_synchronized); |
duke@435 | 310 | |
duke@435 | 311 | __ jcc(Assembler::notEqual, slow_path); |
duke@435 | 312 | // rbx: method |
duke@435 | 313 | __ movq(rax, Address(rsp, wordSize)); |
duke@435 | 314 | |
duke@435 | 315 | // check if local 0 != NULL and read field |
duke@435 | 316 | __ testq(rax, rax); |
duke@435 | 317 | __ jcc(Assembler::zero, slow_path); |
duke@435 | 318 | |
duke@435 | 319 | __ movq(rdi, Address(rbx, methodOopDesc::constants_offset())); |
duke@435 | 320 | // read first instruction word and extract bytecode @ 1 and index @ 2 |
duke@435 | 321 | __ movq(rdx, Address(rbx, methodOopDesc::const_offset())); |
duke@435 | 322 | __ movl(rdx, Address(rdx, constMethodOopDesc::codes_offset())); |
duke@435 | 323 | // Shift codes right to get the index on the right. |
duke@435 | 324 | // The bytecode fetched looks like <index><0xb4><0x2a> |
duke@435 | 325 | __ shrl(rdx, 2 * BitsPerByte); |
duke@435 | 326 | __ shll(rdx, exact_log2(in_words(ConstantPoolCacheEntry::size()))); |
duke@435 | 327 | __ movq(rdi, Address(rdi, constantPoolOopDesc::cache_offset_in_bytes())); |
duke@435 | 328 | |
duke@435 | 329 | // rax: local 0 |
duke@435 | 330 | // rbx: method |
duke@435 | 331 | // rdx: constant pool cache index |
duke@435 | 332 | // rdi: constant pool cache |
duke@435 | 333 | |
duke@435 | 334 | // check if getfield has been resolved and read constant pool cache entry |
duke@435 | 335 | // check the validity of the cache entry by testing whether _indices field |
duke@435 | 336 | // contains Bytecode::_getfield in b1 byte. |
duke@435 | 337 | assert(in_words(ConstantPoolCacheEntry::size()) == 4, |
duke@435 | 338 | "adjust shift below"); |
duke@435 | 339 | __ movl(rcx, |
duke@435 | 340 | Address(rdi, |
duke@435 | 341 | rdx, |
duke@435 | 342 | Address::times_8, |
duke@435 | 343 | constantPoolCacheOopDesc::base_offset() + |
duke@435 | 344 | ConstantPoolCacheEntry::indices_offset())); |
duke@435 | 345 | __ shrl(rcx, 2 * BitsPerByte); |
duke@435 | 346 | __ andl(rcx, 0xFF); |
duke@435 | 347 | __ cmpl(rcx, Bytecodes::_getfield); |
duke@435 | 348 | __ jcc(Assembler::notEqual, slow_path); |
duke@435 | 349 | |
duke@435 | 350 | // Note: constant pool entry is not valid before bytecode is resolved |
duke@435 | 351 | __ movq(rcx, |
duke@435 | 352 | Address(rdi, |
duke@435 | 353 | rdx, |
duke@435 | 354 | Address::times_8, |
duke@435 | 355 | constantPoolCacheOopDesc::base_offset() + |
duke@435 | 356 | ConstantPoolCacheEntry::f2_offset())); |
duke@435 | 357 | // edx: flags |
duke@435 | 358 | __ movl(rdx, |
duke@435 | 359 | Address(rdi, |
duke@435 | 360 | rdx, |
duke@435 | 361 | Address::times_8, |
duke@435 | 362 | constantPoolCacheOopDesc::base_offset() + |
duke@435 | 363 | ConstantPoolCacheEntry::flags_offset())); |
duke@435 | 364 | |
duke@435 | 365 | Label notObj, notInt, notByte, notShort; |
duke@435 | 366 | const Address field_address(rax, rcx, Address::times_1); |
duke@435 | 367 | |
duke@435 | 368 | // Need to differentiate between igetfield, agetfield, bgetfield etc. |
duke@435 | 369 | // because they are different sizes. |
duke@435 | 370 | // Use the type from the constant pool cache |
duke@435 | 371 | __ shrl(rdx, ConstantPoolCacheEntry::tosBits); |
duke@435 | 372 | // Make sure we don't need to mask edx for tosBits after the above shift |
duke@435 | 373 | ConstantPoolCacheEntry::verify_tosBits(); |
duke@435 | 374 | |
duke@435 | 375 | __ cmpl(rdx, atos); |
duke@435 | 376 | __ jcc(Assembler::notEqual, notObj); |
duke@435 | 377 | // atos |
coleenp@548 | 378 | __ load_heap_oop(rax, field_address); |
duke@435 | 379 | __ jmp(xreturn_path); |
duke@435 | 380 | |
duke@435 | 381 | __ bind(notObj); |
duke@435 | 382 | __ cmpl(rdx, itos); |
duke@435 | 383 | __ jcc(Assembler::notEqual, notInt); |
duke@435 | 384 | // itos |
duke@435 | 385 | __ movl(rax, field_address); |
duke@435 | 386 | __ jmp(xreturn_path); |
duke@435 | 387 | |
duke@435 | 388 | __ bind(notInt); |
duke@435 | 389 | __ cmpl(rdx, btos); |
duke@435 | 390 | __ jcc(Assembler::notEqual, notByte); |
duke@435 | 391 | // btos |
duke@435 | 392 | __ load_signed_byte(rax, field_address); |
duke@435 | 393 | __ jmp(xreturn_path); |
duke@435 | 394 | |
duke@435 | 395 | __ bind(notByte); |
duke@435 | 396 | __ cmpl(rdx, stos); |
duke@435 | 397 | __ jcc(Assembler::notEqual, notShort); |
duke@435 | 398 | // stos |
duke@435 | 399 | __ load_signed_word(rax, field_address); |
duke@435 | 400 | __ jmp(xreturn_path); |
duke@435 | 401 | |
duke@435 | 402 | __ bind(notShort); |
duke@435 | 403 | #ifdef ASSERT |
duke@435 | 404 | Label okay; |
duke@435 | 405 | __ cmpl(rdx, ctos); |
duke@435 | 406 | __ jcc(Assembler::equal, okay); |
duke@435 | 407 | __ stop("what type is this?"); |
duke@435 | 408 | __ bind(okay); |
duke@435 | 409 | #endif |
duke@435 | 410 | // ctos |
duke@435 | 411 | __ load_unsigned_word(rax, field_address); |
duke@435 | 412 | |
duke@435 | 413 | __ bind(xreturn_path); |
duke@435 | 414 | |
duke@435 | 415 | // _ireturn/_areturn |
duke@435 | 416 | __ popq(rdi); |
duke@435 | 417 | __ movq(rsp, r13); |
duke@435 | 418 | __ jmp(rdi); |
duke@435 | 419 | __ ret(0); |
duke@435 | 420 | |
duke@435 | 421 | // generate a vanilla interpreter entry as the slow path |
duke@435 | 422 | __ bind(slow_path); |
duke@435 | 423 | (void) generate_normal_entry(false); |
duke@435 | 424 | } else { |
duke@435 | 425 | (void) generate_normal_entry(false); |
duke@435 | 426 | } |
duke@435 | 427 | |
duke@435 | 428 | return entry_point; |
duke@435 | 429 | } |
duke@435 | 430 | |
duke@435 | 431 | // This method tells the deoptimizer how big an interpreted frame must be: |
duke@435 | 432 | int AbstractInterpreter::size_activation(methodOop method, |
duke@435 | 433 | int tempcount, |
duke@435 | 434 | int popframe_extra_args, |
duke@435 | 435 | int moncount, |
duke@435 | 436 | int callee_param_count, |
duke@435 | 437 | int callee_locals, |
duke@435 | 438 | bool is_top_frame) { |
duke@435 | 439 | return layout_activation(method, |
duke@435 | 440 | tempcount, popframe_extra_args, moncount, |
duke@435 | 441 | callee_param_count, callee_locals, |
duke@435 | 442 | (frame*) NULL, (frame*) NULL, is_top_frame); |
duke@435 | 443 | } |
duke@435 | 444 | |
duke@435 | 445 | void Deoptimization::unwind_callee_save_values(frame* f, vframeArray* vframe_array) { |
duke@435 | 446 | |
duke@435 | 447 | // This code is sort of the equivalent of C2IAdapter::setup_stack_frame back in |
duke@435 | 448 | // the days we had adapter frames. When we deoptimize a situation where a |
duke@435 | 449 | // compiled caller calls a compiled caller will have registers it expects |
duke@435 | 450 | // to survive the call to the callee. If we deoptimize the callee the only |
duke@435 | 451 | // way we can restore these registers is to have the oldest interpreter |
duke@435 | 452 | // frame that we create restore these values. That is what this routine |
duke@435 | 453 | // will accomplish. |
duke@435 | 454 | |
duke@435 | 455 | // At the moment we have modified c2 to not have any callee save registers |
duke@435 | 456 | // so this problem does not exist and this routine is just a place holder. |
duke@435 | 457 | |
duke@435 | 458 | assert(f->is_interpreted_frame(), "must be interpreted"); |
duke@435 | 459 | } |