aoqi@0: /* aoqi@0: * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: * aoqi@0: */ aoqi@0: aoqi@0: #include "precompiled.hpp" aoqi@0: #include "code/debugInfo.hpp" aoqi@0: #include "oops/oop.inline.hpp" aoqi@0: #include "runtime/frame.inline.hpp" aoqi@0: #include "runtime/handles.inline.hpp" aoqi@0: #include "runtime/stackValue.hpp" aoqi@0: aoqi@0: StackValue* StackValue::create_stack_value(const frame* fr, const RegisterMap* reg_map, ScopeValue* sv) { aoqi@0: if (sv->is_location()) { aoqi@0: // Stack or register value aoqi@0: Location loc = ((LocationValue *)sv)->location(); aoqi@0: aoqi@0: #ifdef SPARC aoqi@0: // %%%%% Callee-save floats will NOT be working on a Sparc until we aoqi@0: // handle the case of a 2 floats in a single double register. aoqi@0: assert( !(loc.is_register() && loc.type() == Location::float_in_dbl), "Sparc does not handle callee-save floats yet" ); aoqi@0: #endif // SPARC aoqi@0: aoqi@0: // First find address of value aoqi@0: aoqi@0: address value_addr = loc.is_register() aoqi@0: // Value was in a callee-save register aoqi@0: ? reg_map->location(VMRegImpl::as_VMReg(loc.register_number())) aoqi@0: // Else value was directly saved on the stack. The frame's original stack pointer, aoqi@0: // before any extension by its callee (due to Compiler1 linkage on SPARC), must be used. aoqi@0: : ((address)fr->unextended_sp()) + loc.stack_offset(); aoqi@0: aoqi@0: // Then package it right depending on type aoqi@0: // Note: the transfer of the data is thru a union that contains aoqi@0: // an intptr_t. This is because an interpreter stack slot is aoqi@0: // really an intptr_t. The use of a union containing an intptr_t aoqi@0: // ensures that on a 64 bit platform we have proper alignment aoqi@0: // and that we store the value where the interpreter will expect aoqi@0: // to find it (i.e. proper endian). Similarly on a 32bit platform aoqi@0: // using the intptr_t ensures that when a value is larger than aoqi@0: // a stack slot (jlong/jdouble) that we capture the proper part aoqi@0: // of the value for the stack slot in question. aoqi@0: // aoqi@0: switch( loc.type() ) { aoqi@0: case Location::float_in_dbl: { // Holds a float in a double register? aoqi@0: // The callee has no clue whether the register holds a float, aoqi@0: // double or is unused. He always saves a double. Here we know aoqi@0: // a double was saved, but we only want a float back. Narrow the aoqi@0: // saved double to the float that the JVM wants. aoqi@0: assert( loc.is_register(), "floats always saved to stack in 1 word" ); aoqi@0: union { intptr_t p; jfloat jf; } value; aoqi@0: value.p = (intptr_t) CONST64(0xDEADDEAFDEADDEAF); aoqi@0: value.jf = (jfloat) *(jdouble*) value_addr; aoqi@0: return new StackValue(value.p); // 64-bit high half is stack junk aoqi@0: } aoqi@0: case Location::int_in_long: { // Holds an int in a long register? aoqi@0: // The callee has no clue whether the register holds an int, aoqi@0: // long or is unused. He always saves a long. Here we know aoqi@0: // a long was saved, but we only want an int back. Narrow the aoqi@0: // saved long to the int that the JVM wants. aoqi@0: assert( loc.is_register(), "ints always saved to stack in 1 word" ); aoqi@0: union { intptr_t p; jint ji;} value; aoqi@0: value.p = (intptr_t) CONST64(0xDEADDEAFDEADDEAF); aoqi@0: value.ji = (jint) *(jlong*) value_addr; aoqi@0: return new StackValue(value.p); // 64-bit high half is stack junk aoqi@0: } aoqi@0: #ifdef _LP64 aoqi@0: case Location::dbl: aoqi@0: // Double value in an aligned adjacent pair aoqi@0: return new StackValue(*(intptr_t*)value_addr); aoqi@0: case Location::lng: aoqi@0: // Long value in an aligned adjacent pair aoqi@0: return new StackValue(*(intptr_t*)value_addr); aoqi@0: case Location::narrowoop: { aoqi@0: union { intptr_t p; narrowOop noop;} value; aoqi@0: value.p = (intptr_t) CONST64(0xDEADDEAFDEADDEAF); aoqi@0: if (loc.is_register()) { aoqi@0: // The callee has no clue whether the register holds an int, aoqi@0: // long or is unused. He always saves a long. Here we know aoqi@0: // a long was saved, but we only want an int back. Narrow the aoqi@0: // saved long to the int that the JVM wants. aoqi@0: value.noop = (narrowOop) *(julong*) value_addr; aoqi@0: } else { aoqi@0: value.noop = *(narrowOop*) value_addr; aoqi@0: } aoqi@0: // Decode narrowoop and wrap a handle around the oop aoqi@0: Handle h(oopDesc::decode_heap_oop(value.noop)); aoqi@0: return new StackValue(h); aoqi@0: } aoqi@0: #endif aoqi@0: case Location::oop: { aoqi@0: oop val = *(oop *)value_addr; aoqi@0: #ifdef _LP64 aoqi@0: if (Universe::is_narrow_oop_base(val)) { aoqi@0: // Compiled code may produce decoded oop = narrow_oop_base aoqi@0: // when a narrow oop implicit null check is used. aoqi@0: // The narrow_oop_base could be NULL or be the address aoqi@0: // of the page below heap. Use NULL value for both cases. aoqi@0: val = (oop)NULL; aoqi@0: } aoqi@0: #endif aoqi@0: Handle h(val); // Wrap a handle around the oop aoqi@0: return new StackValue(h); aoqi@0: } aoqi@0: case Location::addr: { aoqi@0: ShouldNotReachHere(); // both C1 and C2 now inline jsrs aoqi@0: } aoqi@0: case Location::normal: { aoqi@0: // Just copy all other bits straight through aoqi@0: union { intptr_t p; jint ji;} value; aoqi@0: value.p = (intptr_t) CONST64(0xDEADDEAFDEADDEAF); aoqi@0: value.ji = *(jint*)value_addr; aoqi@0: return new StackValue(value.p); aoqi@0: } aoqi@0: case Location::invalid: aoqi@0: return new StackValue(); aoqi@0: default: aoqi@0: ShouldNotReachHere(); aoqi@0: } aoqi@0: aoqi@0: } else if (sv->is_constant_int()) { aoqi@0: // Constant int: treat same as register int. aoqi@0: union { intptr_t p; jint ji;} value; aoqi@0: value.p = (intptr_t) CONST64(0xDEADDEAFDEADDEAF); aoqi@0: value.ji = (jint)((ConstantIntValue*)sv)->value(); aoqi@0: return new StackValue(value.p); aoqi@0: } else if (sv->is_constant_oop()) { aoqi@0: // constant oop aoqi@0: return new StackValue(sv->as_ConstantOopReadValue()->value()); aoqi@0: #ifdef _LP64 aoqi@0: } else if (sv->is_constant_double()) { aoqi@0: // Constant double in a single stack slot aoqi@0: union { intptr_t p; double d; } value; aoqi@0: value.p = (intptr_t) CONST64(0xDEADDEAFDEADDEAF); aoqi@0: value.d = ((ConstantDoubleValue *)sv)->value(); aoqi@0: return new StackValue(value.p); aoqi@0: } else if (sv->is_constant_long()) { aoqi@0: // Constant long in a single stack slot aoqi@0: union { intptr_t p; jlong jl; } value; aoqi@0: value.p = (intptr_t) CONST64(0xDEADDEAFDEADDEAF); aoqi@0: value.jl = ((ConstantLongValue *)sv)->value(); aoqi@0: return new StackValue(value.p); aoqi@0: #endif aoqi@0: } else if (sv->is_object()) { // Scalar replaced object in compiled frame aoqi@0: Handle ov = ((ObjectValue *)sv)->value(); aoqi@0: return new StackValue(ov, (ov.is_null()) ? 1 : 0); aoqi@0: } aoqi@0: aoqi@0: // Unknown ScopeValue type aoqi@0: ShouldNotReachHere(); aoqi@0: return new StackValue((intptr_t) 0); // dummy aoqi@0: } aoqi@0: aoqi@0: aoqi@0: BasicLock* StackValue::resolve_monitor_lock(const frame* fr, Location location) { aoqi@0: assert(location.is_stack(), "for now we only look at the stack"); aoqi@0: int word_offset = location.stack_offset() / wordSize; aoqi@0: // (stack picture) aoqi@0: // high: [ ] word_offset + 1 aoqi@0: // low [ ] word_offset aoqi@0: // aoqi@0: // sp-> [ ] 0 aoqi@0: // the word_offset is the distance from the stack pointer to the lowest address aoqi@0: // The frame's original stack pointer, before any extension by its callee aoqi@0: // (due to Compiler1 linkage on SPARC), must be used. aoqi@0: return (BasicLock*) (fr->unextended_sp() + word_offset); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: #ifndef PRODUCT aoqi@0: aoqi@0: void StackValue::print_on(outputStream* st) const { aoqi@0: switch(_type) { aoqi@0: case T_INT: aoqi@0: st->print("%d (int) %f (float) %x (hex)", *(int *)&_i, *(float *)&_i, *(int *)&_i); aoqi@0: break; aoqi@0: aoqi@0: case T_OBJECT: aoqi@0: _o()->print_value_on(st); aoqi@0: st->print(" <" INTPTR_FORMAT ">", p2i((address)_o())); aoqi@0: break; aoqi@0: aoqi@0: case T_CONFLICT: aoqi@0: st->print("conflict"); aoqi@0: break; aoqi@0: aoqi@0: default: aoqi@0: ShouldNotReachHere(); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: #endif