hotspot/src/cpu/x86/vm/interpreter_x86_64.cpp

Print this page
rev 611 : Merge

*** 1,10 **** - #ifdef USE_PRAGMA_IDENT_SRC - #pragma ident "@(#)interpreter_x86_64.cpp 1.68 07/09/17 09:26:03 JVM" - #endif /* ! * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. --- 1,7 ---- /* ! * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.
*** 36,48 **** address entry = __ pc(); // rbx: method // r14: pointer to locals // c_rarg3: first stack arg - wordSize ! __ movq(c_rarg3, rsp); // adjust rsp ! __ subq(rsp, 4 * wordSize); __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::slow_signature_handler), rbx, r14, c_rarg3); --- 33,45 ---- address entry = __ pc(); // rbx: method // r14: pointer to locals // c_rarg3: first stack arg - wordSize ! __ mov(c_rarg3, rsp); // adjust rsp ! __ subptr(rsp, 4 * wordSize); __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::slow_signature_handler), rbx, r14, c_rarg3);
*** 71,87 **** // Do Int register here switch ( i ) { case 0: __ movl(rscratch1, Address(rbx, methodOopDesc::access_flags_offset())); __ testl(rscratch1, JVM_ACC_STATIC); ! __ cmovq(Assembler::zero, c_rarg1, Address(rsp, 0)); break; case 1: ! __ movq(c_rarg2, Address(rsp, wordSize)); break; case 2: ! __ movq(c_rarg3, Address(rsp, 2 * wordSize)); break; default: break; } --- 68,84 ---- // Do Int register here switch ( i ) { case 0: __ movl(rscratch1, Address(rbx, methodOopDesc::access_flags_offset())); __ testl(rscratch1, JVM_ACC_STATIC); ! __ cmovptr(Assembler::zero, c_rarg1, Address(rsp, 0)); break; case 1: ! __ movptr(c_rarg2, Address(rsp, wordSize)); break; case 2: ! __ movptr(c_rarg3, Address(rsp, 2 * wordSize)); break; default: break; }
*** 102,112 **** __ bind(next); } // restore rsp ! __ addq(rsp, 4 * wordSize); __ ret(0); return entry; } --- 99,109 ---- __ bind(next); } // restore rsp ! __ addptr(rsp, 4 * wordSize); __ ret(0); return entry; }
*** 115,127 **** address entry = __ pc(); // rbx: method // r14: pointer to locals // c_rarg3: first stack arg - wordSize ! __ movq(c_rarg3, rsp); // adjust rsp ! __ subq(rsp, 14 * wordSize); __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::slow_signature_handler), rbx, r14, c_rarg3); --- 112,124 ---- address entry = __ pc(); // rbx: method // r14: pointer to locals // c_rarg3: first stack arg - wordSize ! __ mov(c_rarg3, rsp); // adjust rsp ! __ subptr(rsp, 14 * wordSize); __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::slow_signature_handler), rbx, r14, c_rarg3);
*** 156,174 **** } // Now handle integrals. Only do c_rarg1 if not static. __ movl(c_rarg3, Address(rbx, methodOopDesc::access_flags_offset())); __ testl(c_rarg3, JVM_ACC_STATIC); ! __ cmovq(Assembler::zero, c_rarg1, Address(rsp, 0)); ! __ movq(c_rarg2, Address(rsp, wordSize)); ! __ movq(c_rarg3, Address(rsp, 2 * wordSize)); ! __ movq(c_rarg4, Address(rsp, 3 * wordSize)); ! __ movq(c_rarg5, Address(rsp, 4 * wordSize)); // restore rsp ! __ addq(rsp, 14 * wordSize); __ ret(0); return entry; } --- 153,171 ---- } // Now handle integrals. Only do c_rarg1 if not static. __ movl(c_rarg3, Address(rbx, methodOopDesc::access_flags_offset())); __ testl(c_rarg3, JVM_ACC_STATIC); ! __ cmovptr(Assembler::zero, c_rarg1, Address(rsp, 0)); ! __ movptr(c_rarg2, Address(rsp, wordSize)); ! __ movptr(c_rarg3, Address(rsp, 2 * wordSize)); ! __ movptr(c_rarg4, Address(rsp, 3 * wordSize)); ! __ movptr(c_rarg5, Address(rsp, 4 * wordSize)); // restore rsp ! __ addptr(rsp, 14 * wordSize); __ ret(0); return entry; }
*** 177,194 **** // // Various method entries // ! address InterpreterGenerator::generate_math_entry( ! AbstractInterpreter::MethodKind kind) { ! // rbx: methodOop ! if (!InlineIntrinsics) return NULL; // Generate a vanilla entry ! assert(kind == Interpreter::java_lang_math_sqrt, ! "Other intrinsics are not special"); address entry_point = __ pc(); // These don't need a safepoint check because they aren't virtually // callable. We won't enter these intrinsics from compiled code. --- 174,190 ---- // // Various method entries // ! address InterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKind kind) { ! // rbx,: methodOop ! // rcx: scratrch ! // r13: sender sp ! if (!InlineIntrinsics) return NULL; // Generate a vanilla entry address entry_point = __ pc(); // These don't need a safepoint check because they aren't virtually // callable. We won't enter these intrinsics from compiled code.
*** 198,207 **** --- 194,208 ---- // mathematical functions inlined by compiler // (interpreter must provide identical implementation // in order to avoid monotonicity bugs when switching // from interpreter to compiler in the middle of some // computation) + // + // stack: [ ret adr ] <-- rsp + // [ lo(arg) ] + // [ hi(arg) ] + // // Note: For JDK 1.2 StrictMath doesn't exist and Math.sin/cos/sqrt are // native methods. Interpreter::method_kind(...) does a check for // native methods first before checking for intrinsic methods and // thus will never select this entry point. Make sure it is not
*** 219,232 **** // JDK version is only determined when universe2_init() is called. // Note: For JDK 1.3 StrictMath exists and Math.sin/cos/sqrt are // java methods. Interpreter::method_kind(...) will select // this entry point for the corresponding methods in JDK 1.3. __ sqrtsd(xmm0, Address(rsp, wordSize)); ! __ popq(rax); ! __ movq(rsp, r13); __ jmp(rax); return entry_point; } --- 220,269 ---- // JDK version is only determined when universe2_init() is called. // Note: For JDK 1.3 StrictMath exists and Math.sin/cos/sqrt are // java methods. Interpreter::method_kind(...) will select // this entry point for the corresponding methods in JDK 1.3. + // get argument + + if (kind == Interpreter::java_lang_math_sqrt) { __ sqrtsd(xmm0, Address(rsp, wordSize)); + } else { + __ fld_d(Address(rsp, wordSize)); + switch (kind) { + case Interpreter::java_lang_math_sin : + __ trigfunc('s'); + break; + case Interpreter::java_lang_math_cos : + __ trigfunc('c'); + break; + case Interpreter::java_lang_math_tan : + __ trigfunc('t'); + break; + case Interpreter::java_lang_math_abs: + __ fabs(); + break; + case Interpreter::java_lang_math_log: + __ flog(); + break; + case Interpreter::java_lang_math_log10: + __ flog10(); + break; + default : + ShouldNotReachHere(); + } + + // return double result in xmm0 for interpreter and compilers. + __ subptr(rsp, 2*wordSize); + // Round to 64bit precision + __ fstp_d(Address(rsp, 0)); + __ movdbl(xmm0, Address(rsp, 0)); + __ addptr(rsp, 2*wordSize); + } ! ! __ pop(rax); ! __ mov(rsp, r13); __ jmp(rax); return entry_point; }
*** 240,253 **** address entry_point = __ pc(); // abstract method entry // remove return address. Not really needed, since exception // handling throws away expression stack ! __ popq(rbx); // adjust stack to what a normal return would do ! __ movq(rsp, r13); // throw exception __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError)); // the call_VM checks for exception, so we should never return here. --- 277,290 ---- address entry_point = __ pc(); // abstract method entry // remove return address. Not really needed, since exception // handling throws away expression stack ! __ pop(rbx); // adjust stack to what a normal return would do ! __ mov(rsp, r13); // throw exception __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError)); // the call_VM checks for exception, so we should never return here.
*** 277,438 **** // do nothing for empty methods (do not even increment invocation counter) // Code: _return // _return // return w/o popping parameters ! __ popq(rax); ! __ movq(rsp, r13); __ jmp(rax); __ bind(slow_path); (void) generate_normal_entry(false); return entry_point; } - // Call an accessor method (assuming it is resolved, otherwise drop - // into vanilla (slow path) entry - address InterpreterGenerator::generate_accessor_entry(void) { - // rbx: methodOop - - // r13: senderSP must preserver for slow path, set SP to it on fast path - - address entry_point = __ pc(); - Label xreturn_path; - - // do fastpath for resolved accessor methods - if (UseFastAccessorMethods) { - // Code: _aload_0, _(i|a)getfield, _(i|a)return or any rewrites - // thereof; parameter size = 1 - // Note: We can only use this code if the getfield has been resolved - // and if we don't have a null-pointer exception => check for - // these conditions first and use slow path if necessary. - Label slow_path; - // If we need a safepoint check, generate full interpreter entry. - __ cmp32(ExternalAddress(SafepointSynchronize::address_of_state()), - SafepointSynchronize::_not_synchronized); - - __ jcc(Assembler::notEqual, slow_path); - // rbx: method - __ movq(rax, Address(rsp, wordSize)); - - // check if local 0 != NULL and read field - __ testq(rax, rax); - __ jcc(Assembler::zero, slow_path); - - __ movq(rdi, Address(rbx, methodOopDesc::constants_offset())); - // read first instruction word and extract bytecode @ 1 and index @ 2 - __ movq(rdx, Address(rbx, methodOopDesc::const_offset())); - __ movl(rdx, Address(rdx, constMethodOopDesc::codes_offset())); - // Shift codes right to get the index on the right. - // The bytecode fetched looks like <index><0xb4><0x2a> - __ shrl(rdx, 2 * BitsPerByte); - __ shll(rdx, exact_log2(in_words(ConstantPoolCacheEntry::size()))); - __ movq(rdi, Address(rdi, constantPoolOopDesc::cache_offset_in_bytes())); - - // rax: local 0 - // rbx: method - // rdx: constant pool cache index - // rdi: constant pool cache - - // check if getfield has been resolved and read constant pool cache entry - // check the validity of the cache entry by testing whether _indices field - // contains Bytecode::_getfield in b1 byte. - assert(in_words(ConstantPoolCacheEntry::size()) == 4, - "adjust shift below"); - __ movl(rcx, - Address(rdi, - rdx, - Address::times_8, - constantPoolCacheOopDesc::base_offset() + - ConstantPoolCacheEntry::indices_offset())); - __ shrl(rcx, 2 * BitsPerByte); - __ andl(rcx, 0xFF); - __ cmpl(rcx, Bytecodes::_getfield); - __ jcc(Assembler::notEqual, slow_path); - - // Note: constant pool entry is not valid before bytecode is resolved - __ movq(rcx, - Address(rdi, - rdx, - Address::times_8, - constantPoolCacheOopDesc::base_offset() + - ConstantPoolCacheEntry::f2_offset())); - // edx: flags - __ movl(rdx, - Address(rdi, - rdx, - Address::times_8, - constantPoolCacheOopDesc::base_offset() + - ConstantPoolCacheEntry::flags_offset())); - - Label notObj, notInt, notByte, notShort; - const Address field_address(rax, rcx, Address::times_1); - - // Need to differentiate between igetfield, agetfield, bgetfield etc. - // because they are different sizes. - // Use the type from the constant pool cache - __ shrl(rdx, ConstantPoolCacheEntry::tosBits); - // Make sure we don't need to mask edx for tosBits after the above shift - ConstantPoolCacheEntry::verify_tosBits(); - - __ cmpl(rdx, atos); - __ jcc(Assembler::notEqual, notObj); - // atos - __ movq(rax, field_address); - __ jmp(xreturn_path); - - __ bind(notObj); - __ cmpl(rdx, itos); - __ jcc(Assembler::notEqual, notInt); - // itos - __ movl(rax, field_address); - __ jmp(xreturn_path); - - __ bind(notInt); - __ cmpl(rdx, btos); - __ jcc(Assembler::notEqual, notByte); - // btos - __ load_signed_byte(rax, field_address); - __ jmp(xreturn_path); - - __ bind(notByte); - __ cmpl(rdx, stos); - __ jcc(Assembler::notEqual, notShort); - // stos - __ load_signed_word(rax, field_address); - __ jmp(xreturn_path); - - __ bind(notShort); - #ifdef ASSERT - Label okay; - __ cmpl(rdx, ctos); - __ jcc(Assembler::equal, okay); - __ stop("what type is this?"); - __ bind(okay); - #endif - // ctos - __ load_unsigned_word(rax, field_address); - - __ bind(xreturn_path); - - // _ireturn/_areturn - __ popq(rdi); - __ movq(rsp, r13); - __ jmp(rdi); - __ ret(0); - - // generate a vanilla interpreter entry as the slow path - __ bind(slow_path); - (void) generate_normal_entry(false); - } else { - (void) generate_normal_entry(false); - } - - return entry_point; - } - // This method tells the deoptimizer how big an interpreted frame must be: int AbstractInterpreter::size_activation(methodOop method, int tempcount, int popframe_extra_args, int moncount, --- 314,333 ---- // do nothing for empty methods (do not even increment invocation counter) // Code: _return // _return // return w/o popping parameters ! __ pop(rax); ! __ mov(rsp, r13); __ jmp(rax); __ bind(slow_path); (void) generate_normal_entry(false); return entry_point; } // This method tells the deoptimizer how big an interpreted frame must be: int AbstractInterpreter::size_activation(methodOop method, int tempcount, int popframe_extra_args, int moncount,
*** 458,464 **** // At the moment we have modified c2 to not have any callee save registers // so this problem does not exist and this routine is just a place holder. assert(f->is_interpreted_frame(), "must be interpreted"); } - - --- 353,357 ----