# HG changeset patch # User Lukas Stadler # Date 1397209939 -7200 # Node ID 36e1a11a72b3a9c139c265c31ad36c7d857b6b7c # Parent 10b0b01a4a61baf50227a30d6836d51a33781575 new StackIntrospection interface to allow access to stack contents diff -r 10b0b01a4a61 -r 36e1a11a72b3 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/stack/InspectedFrame.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/stack/InspectedFrame.java Fri Apr 11 11:52:19 2014 +0200 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. 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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.api.code.stack; + +import com.oracle.graal.api.meta.*; + +public interface InspectedFrame { + + /** + * Returns the value of the local at the given index. Currently only works for object values. + * This value is a copy iff {@link #isVirtual(int)} is true. + */ + Object getLocal(int index); + + /** + * Returns whether the local at the given index is a virtual object, and therefore the object + * returned by {@link #getLocal(int)} is a copy. + */ + boolean isVirtual(int index); + + /** + * Returns true if the stack frame is a compiled stack frame and there are virtual objects + * anywhere in the current state of the compiled method. This can return true even if + * {@link #isVirtual(int)} return false for all locals. + */ + boolean hasVirtualObjects(); + + /** + * This method will materialize all virtual objects, deoptimize the stack frame and make sure + * that subsequent execution of the deoptimized frame uses the materialized values. + */ + void materializeVirtualObjects(boolean invalidateCode); + + /** + * @return the current bytecode index + */ + int getBytecodeIndex(); + + /** + * @return the current method + */ + ResolvedJavaMethod getMethod(); +} diff -r 10b0b01a4a61 -r 36e1a11a72b3 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/stack/StackIntrospection.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/stack/StackIntrospection.java Fri Apr 11 11:52:19 2014 +0200 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. 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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.api.code.stack; + +import com.oracle.graal.api.meta.*; + +public interface StackIntrospection { + + /** + * Accesses the current stack, returning a collection of {@long InspectedFrame}s that can be + * used to inspect the stack frames' contents. + * + * @param initialMethod if this is non-{@code null}, then the stack trace will start at this + * method + * @param matchingMethod if this is non-{@code null}, then only matching stack frames are + * returned + */ + Iterable getStackTrace(ResolvedJavaMethod initialMethod, ResolvedJavaMethod matchingMethod); +} diff -r 10b0b01a4a61 -r 36e1a11a72b3 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java Fri Apr 11 13:41:16 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java Fri Apr 11 11:52:19 2014 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.compiler.target; import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.stack.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; import com.oracle.graal.compiler.gen.*; @@ -96,6 +97,8 @@ public abstract boolean shouldAllocateRegisters(); + public abstract StackIntrospection getStackIntrospection(); + /** * Emits the code for a given graph. * diff -r 10b0b01a4a61 -r 36e1a11a72b3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java Fri Apr 11 13:41:16 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java Fri Apr 11 11:52:19 2014 +0200 @@ -25,6 +25,7 @@ import java.util.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.stack.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.hotspot.meta.*; @@ -96,7 +97,7 @@ /** * Finds all the registers that are defined by some given LIR. - * + * * @param lir the LIR to examine * @return the registers that are defined by or used as temps for any instruction in {@code lir} */ @@ -134,7 +135,7 @@ * {@linkplain SaveRegistersOp#remove(Set) removed} as these registers are declared as * temporaries in the stub's {@linkplain ForeignCallLinkage linkage} (and thus will be saved by * the stub's caller). - * + * * @param stub the stub to update * @param destroyedRegisters the registers destroyed by the stub * @param calleeSaveInfo a map from debug infos to the operations that provide their @@ -158,6 +159,11 @@ } @Override + public StackIntrospection getStackIntrospection() { + return runtime; + } + + @Override public HotSpotProviders getProviders() { return (HotSpotProviders) super.getProviders(); } diff -r 10b0b01a4a61 -r 36e1a11a72b3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Fri Apr 11 13:41:16 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Fri Apr 11 11:52:19 2014 +0200 @@ -33,6 +33,7 @@ import sun.reflect.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.stack.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; import com.oracle.graal.api.runtime.*; @@ -49,7 +50,7 @@ /** * Singleton class holding the instance of the {@link GraalRuntime}. */ -public final class HotSpotGraalRuntime implements GraalRuntime, RuntimeProvider { +public final class HotSpotGraalRuntime implements GraalRuntime, RuntimeProvider, StackIntrospection { private static final HotSpotGraalRuntime instance = new HotSpotGraalRuntime(); static { @@ -363,6 +364,8 @@ public T getCapability(Class clazz) { if (clazz == RuntimeProvider.class) { return (T) this; + } else if (clazz == StackIntrospection.class) { + return (T) this; } else if (clazz == SnippetReflectionProvider.class) { return (T) getHostProviders().getSnippetReflection(); } @@ -441,4 +444,36 @@ throw GraalInternalError.shouldNotReachHere(); } } + + public Iterable getStackTrace(final ResolvedJavaMethod initialMethod, final ResolvedJavaMethod matchingMethod) { + class StackFrameIterator implements Iterator { + + private HotSpotStackFrameReference current = compilerToVm.getNextStackFrame(null, (HotSpotResolvedJavaMethod) initialMethod); + // we don't want to read ahead if hasNext isn't called + private boolean advanced = true; + + public boolean hasNext() { + update(); + return current != null; + } + + public InspectedFrame next() { + update(); + advanced = false; + return current; + } + + private void update() { + if (!advanced) { + current = compilerToVm.getNextStackFrame(current, (HotSpotResolvedJavaMethod) matchingMethod); + advanced = true; + } + } + } + return new Iterable() { + public Iterator iterator() { + return new StackFrameIterator(); + } + }; + } } diff -r 10b0b01a4a61 -r 36e1a11a72b3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotStackFrameReference.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotStackFrameReference.java Fri Apr 11 11:52:19 2014 +0200 @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. 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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot; + +import java.util.*; + +import com.oracle.graal.api.code.stack.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.bridge.*; +import com.oracle.graal.hotspot.meta.*; + +public class HotSpotStackFrameReference implements InspectedFrame { + + private CompilerToVM compilerToVM; + + // information used to find the stack frame + private long stackPointer; + private int frameNumber; + + // information about the stack frame's contents + private int bci; + private long metaspaceMethod; + private Object[] locals; + private boolean[] localIsVirtual; + + public long getStackPointer() { + return stackPointer; + } + + public int getFrameNumber() { + return frameNumber; + } + + public Object getLocal(int index) { + return locals[index]; + } + + public boolean isVirtual(int index) { + return localIsVirtual == null ? false : localIsVirtual[index]; + } + + public void materializeVirtualObjects(boolean invalidateCode) { + compilerToVM.materializeVirtualObjects(this, invalidateCode); + } + + public int getBytecodeIndex() { + return bci; + } + + public ResolvedJavaMethod getMethod() { + return HotSpotResolvedJavaMethod.fromMetaspace(metaspaceMethod); + } + + public boolean hasVirtualObjects() { + return localIsVirtual != null; + } + + @Override + public String toString() { + return "HotSpotStackFrameReference [stackPointer=" + stackPointer + ", frameNumber=" + frameNumber + ", bci=" + bci + ", method=" + getMethod() + ", locals=" + Arrays.toString(locals) + + ", localIsVirtual=" + Arrays.toString(localIsVirtual) + "]"; + } +} diff -r 10b0b01a4a61 -r 36e1a11a72b3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Fri Apr 11 13:41:16 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Fri Apr 11 11:52:19 2014 +0200 @@ -334,4 +334,22 @@ * @return milliseconds since VM start */ long getTimeStamp(); + + /** + * Looks for the next Java stack frame with the given method. + * + * @param frame the starting point of the search, where {@code null} refers to the topmost frame + * @param method the method to look for, where {@code null} means that any frame is returned + * @return the frame, or {@code null} if the end of the stack was reached during the search + */ + HotSpotStackFrameReference getNextStackFrame(HotSpotStackFrameReference frame, HotSpotResolvedJavaMethod method); + + /** + * Materialized all virtual objects within the given stack frame and update the locals within + * the given stackFrame object. + * + * @param invalidate if {@code true}, the compiled method for the stack frame will be + * invalidated. + */ + void materializeVirtualObjects(HotSpotStackFrameReference stackFrame, boolean invalidate); } diff -r 10b0b01a4a61 -r 36e1a11a72b3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Fri Apr 11 13:41:16 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Fri Apr 11 11:52:19 2014 +0200 @@ -179,5 +179,9 @@ public native boolean hasCompiledCodeForOSR(long metaspaceMethod, int entryBCI, int level); + public native HotSpotStackFrameReference getNextStackFrame(HotSpotStackFrameReference frame, HotSpotResolvedJavaMethod method); + + public native void materializeVirtualObjects(HotSpotStackFrameReference stackFrame, boolean invalidate); + public native long getTimeStamp(); } diff -r 10b0b01a4a61 -r 36e1a11a72b3 src/share/vm/classfile/systemDictionary.hpp --- a/src/share/vm/classfile/systemDictionary.hpp Fri Apr 11 13:41:16 2014 +0200 +++ b/src/share/vm/classfile/systemDictionary.hpp Fri Apr 11 11:52:19 2014 +0200 @@ -206,6 +206,7 @@ do_klass(HotSpotMonitorValue_klass, com_oracle_graal_hotspot_meta_HotSpotMonitorValue, Opt) \ do_klass(HotSpotObjectConstant_klass, com_oracle_graal_hotspot_meta_HotSpotObjectConstant, Opt) \ do_klass(HotSpotMetaspaceConstant_klass, com_oracle_graal_hotspot_meta_HotSpotMetaspaceConstant, Opt) \ + do_klass(HotSpotStackFrameReference_klass, com_oracle_graal_hotspot_HotSpotStackFrameReference, Opt) \ /* graal.api.code */ \ do_klass(Assumptions_klass, com_oracle_graal_api_code_Assumptions, Opt) \ do_klass(Assumptions_ConcreteMethod_klass, com_oracle_graal_api_code_Assumptions_ConcreteMethod, Opt) \ diff -r 10b0b01a4a61 -r 36e1a11a72b3 src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Fri Apr 11 13:41:16 2014 +0200 +++ b/src/share/vm/classfile/vmSymbols.hpp Fri Apr 11 11:52:19 2014 +0200 @@ -317,10 +317,11 @@ template(com_oracle_graal_hotspot_meta_HotSpotMonitorValue, "com/oracle/graal/hotspot/meta/HotSpotMonitorValue") \ template(com_oracle_graal_hotspot_meta_HotSpotObjectConstant, "com/oracle/graal/hotspot/meta/HotSpotObjectConstant") \ template(com_oracle_graal_hotspot_meta_HotSpotMetaspaceConstant, "com/oracle/graal/hotspot/meta/HotSpotMetaspaceConstant") \ + template(com_oracle_graal_hotspot_HotSpotStackFrameReference, "com/oracle/graal/hotspot/HotSpotStackFrameReference") \ /* graal.api.meta */ \ template(com_oracle_graal_api_meta_Constant, "com/oracle/graal/api/meta/Constant") \ template(com_oracle_graal_api_meta_PrimitiveConstant, "com/oracle/graal/api/meta/PrimitiveConstant") \ - template(com_oracle_graal_api_meta_NullConstant, "com/oracle/graal/api/meta/NullConstant") \ + template(com_oracle_graal_api_meta_NullConstant, "com/oracle/graal/api/meta/NullConstant") \ template(com_oracle_graal_api_meta_ConstantPool, "com/oracle/graal/api/meta/ConstantPool") \ template(com_oracle_graal_api_meta_ExceptionHandler, "com/oracle/graal/api/meta/ExceptionHandler") \ template(com_oracle_graal_api_meta_JavaMethod, "com/oracle/graal/api/meta/JavaMethod") \ diff -r 10b0b01a4a61 -r 36e1a11a72b3 src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Fri Apr 11 13:41:16 2014 +0200 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Fri Apr 11 11:52:19 2014 +0200 @@ -22,6 +22,7 @@ */ #include "precompiled.hpp" +#include "code/scopeDesc.hpp" #include "memory/oopFactory.hpp" #include "oops/generateOopMap.hpp" #include "oops/fieldStreams.hpp" @@ -39,6 +40,9 @@ #include "graal/graalVMToCompiler.hpp" #include "gc_implementation/g1/heapRegion.hpp" #include "runtime/javaCalls.hpp" +#include "runtime/deoptimization.hpp" +#include "runtime/vframe.hpp" +#include "runtime/vframe_hp.hpp" #include "runtime/vmStructs.hpp" #include "runtime/gpu.hpp" @@ -782,6 +786,239 @@ return tty->time_stamp().milliseconds(); C2V_END +// public native HotSpotStackFrameReference getNextStackFrame(HotSpotStackFrameReference frame, ResolvedJavaMethod method); +C2V_VMENTRY(jobject, getNextStackFrame, (JNIEnv *env, jobject compilerToVM, jobject hs_frame, jobject hs_method)) + ResourceMark rm; + + if (!thread->has_last_Java_frame()) return NULL; + methodHandle method = hs_method == NULL ? NULL : asMethod(HotSpotResolvedJavaMethod::metaspaceMethod(hs_method)); + Handle result = InstanceKlass::cast(HotSpotStackFrameReference::klass())->allocate_instance(thread); + HotSpotStackFrameReference::klass()->initialize(thread); + + StackFrameStream fst(thread); + if (hs_frame != NULL) { + // look for the correct stack frame if one is given + intptr_t* stack_pointer = (intptr_t*) HotSpotStackFrameReference::stackPointer(hs_frame); + while (fst.current()->sp() != stack_pointer && !fst.is_done()) { + fst.next(); + } + if (fst.current()->sp() != stack_pointer) { + THROW_MSG_NULL(vmSymbols::java_lang_IllegalStateException(), "stack frame not found") + } + } + + int frame_number = 0; + vframe* vf = vframe::new_vframe(fst.current(), fst.register_map(), thread); + if (hs_frame != NULL) { + // look for the correct vframe within the stack frame if one is given + int last_frame_number = HotSpotStackFrameReference::frameNumber(hs_frame); + while (frame_number < last_frame_number) { + if (vf->is_top()) { + THROW_MSG_NULL(vmSymbols::java_lang_IllegalStateException(), "invalid frame number") + } + vf = vf->sender(); + frame_number ++; + } + // move one frame forward + if (vf->is_top()) { + if (fst.is_done()) { + return NULL; + } + fst.next(); + vf = vframe::new_vframe(fst.current(), fst.register_map(), thread); + frame_number = 0; + } else { + vf = vf->sender(); + frame_number++; + } + } + + while (true) { + // look for the given method + while (true) { + StackValueCollection* locals = NULL; + if (vf->is_compiled_frame()) { + // compiled method frame + compiledVFrame* cvf = compiledVFrame::cast(vf); + if (method == NULL || cvf->method() == method()) { + GrowableArray* objects = cvf->scope()->objects(); + bool reallocated = false; + if (objects != NULL) { + reallocated = Deoptimization::realloc_objects(thread, fst.current(), objects, THREAD); + if (reallocated) { + Deoptimization::reassign_fields(fst.current(), fst.register_map(), objects); + } + + GrowableArray* local_values = cvf->scope()->locals(); + typeArrayHandle array = oopFactory::new_boolArray(local_values->length(), thread); + for (int i = 0; i < local_values->length(); i++) { + ScopeValue* value = local_values->at(i); + if (value->is_object()) { + array->bool_at_put(i, true); + } + } + HotSpotStackFrameReference::set_localIsVirtual(result, array()); + } else { + HotSpotStackFrameReference::set_localIsVirtual(result, NULL); + } + + locals = cvf->locals(); + HotSpotStackFrameReference::set_bci(result, cvf->bci()); + if (hs_method == NULL) { + HotSpotStackFrameReference::set_metaspaceMethod(result, (jlong) cvf->method()); + } else { + HotSpotStackFrameReference::set_metaspaceMethod(result, (jlong) method()); + } + } + } else if (vf->is_interpreted_frame()) { + // interpreted method frame + interpretedVFrame* ivf = interpretedVFrame::cast(vf); + if (method == NULL || ivf->method() == method()) { + locals = ivf->locals(); + HotSpotStackFrameReference::set_bci(result, ivf->bci()); + if (hs_method == NULL) { + HotSpotStackFrameReference::set_metaspaceMethod(result, (jlong) ivf->method()); + } else { + HotSpotStackFrameReference::set_metaspaceMethod(result, (jlong) method()); + } + HotSpotStackFrameReference::set_localIsVirtual(result, NULL); + } + } + + // locals != NULL means that we found a matching frame and result is already partially initialized + if (locals != NULL) { + HotSpotStackFrameReference::set_compilerToVM(result, JNIHandles::resolve(compilerToVM)); + HotSpotStackFrameReference::set_stackPointer(result, (jlong) fst.current()->sp()); + HotSpotStackFrameReference::set_frameNumber(result, frame_number); + + // initialize the locals array + objArrayHandle array = oopFactory::new_objectArray(locals->size(), thread); + for (int i = 0; i < locals->size(); i++) { + StackValue* var = locals->at(i); + if (var->type() == T_OBJECT) { + array->obj_at_put(i, locals->at(i)->get_obj()()); + } + } + HotSpotStackFrameReference::set_locals(result, array()); + + return JNIHandles::make_local(thread, result()); + } + + if (vf->is_top()) { + break; + } + frame_number++; + vf = vf->sender(); + } // end of vframe loop + + if (fst.is_done()) { + break; + } + fst.next(); + vf = vframe::new_vframe(fst.current(), fst.register_map(), thread); + frame_number = 0; + } // end of frame loop + + // the end was reached without finding a matching method + return NULL; +C2V_END + + + +// public native void materializeVirtualObjects(HotSpotStackFrameReference stackFrame, boolean invalidate); +C2V_VMENTRY(void, materializeVirtualObjects, (JNIEnv *env, jobject, jobject hs_frame, bool invalidate)) + ResourceMark rm; + + if (hs_frame == NULL) { + THROW_MSG(vmSymbols::java_lang_NullPointerException(), "stack frame is null") + } + + HotSpotStackFrameReference::klass()->initialize(thread); + + // look for the given stack frame + StackFrameStream fst(thread); + intptr_t* stack_pointer = (intptr_t*) HotSpotStackFrameReference::stackPointer(hs_frame); + while (fst.current()->sp() != stack_pointer && !fst.is_done()) { + fst.next(); + } + if (fst.current()->sp() != stack_pointer) { + THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "stack frame not found") + } + + if (invalidate) { + assert(fst.current()->cb()->is_nmethod(), "nmethod expected"); + ((nmethod*) fst.current()->cb())->make_not_entrant(); + } + Deoptimization::deoptimize(thread, *fst.current(), fst.register_map(), Deoptimization::Reason_none); + + vframe* vf = vframe::new_vframe(fst.current(), fst.register_map(), thread); + if (!vf->is_compiled_frame()) { + THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "compiled stack frame expected") + } + + GrowableArray* virtualFrames = new GrowableArray(10); + while (true) { + assert(vf->is_compiled_frame(), "Wrong frame type"); + virtualFrames->push(compiledVFrame::cast(vf)); + if (vf->is_top()) { + break; + } + vf = vf->sender(); + } + + int last_frame_number = HotSpotStackFrameReference::frameNumber(hs_frame); + if (last_frame_number >= virtualFrames->length()) { + THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "invalid frame number") + } + + // Reallocate the non-escaping objects and restore their fields. + assert (virtualFrames->at(last_frame_number)->scope() != NULL,"invalid scope"); + GrowableArray* objects = virtualFrames->at(last_frame_number)->scope()->objects(); + + if (objects == NULL) { + // no objects to materialize + return; + } + + bool reallocated = Deoptimization::realloc_objects(thread, fst.current(), objects, THREAD); + if (reallocated) { + Deoptimization::reassign_fields(fst.current(), fst.register_map(), objects); + + for (int frame_index = 0; frame_index < virtualFrames->length(); frame_index++) { + compiledVFrame* cvf = virtualFrames->at(frame_index); + + GrowableArray* scopeLocals = cvf->scope()->locals(); + StackValueCollection* locals = cvf->locals(); + + if (locals != NULL) { + for (int i2 = 0; i2 < locals->size(); i2++) { + StackValue* var = locals->at(i2); + if (var->type() == T_OBJECT && scopeLocals->at(i2)->is_object()) { + jvalue val; + val.l = (jobject) locals->at(i2)->get_obj()(); + cvf->update_local(T_OBJECT, i2, val); + } + } + } + } + + // all locals are materialized by now + HotSpotStackFrameReference::set_localIsVirtual(hs_frame, NULL); + + // update the locals array + objArrayHandle array = (objArrayOop) HotSpotStackFrameReference::locals(hs_frame); + StackValueCollection* locals = virtualFrames->at(last_frame_number)->locals(); + for (int i = 0; i < locals->size(); i++) { + StackValue* var = locals->at(i); + if (var->type() == T_OBJECT) { + array->obj_at_put(i, locals->at(i)->get_obj()()); + } + } + } +C2V_END + + + #define CC (char*) /*cast a literal from (const char*)*/ #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(c2v_ ## f)) @@ -798,6 +1035,7 @@ #define HS_CONFIG "Lcom/oracle/graal/hotspot/HotSpotVMConfig;" #define HS_INSTALLED_CODE "Lcom/oracle/graal/hotspot/meta/HotSpotInstalledCode;" #define NODE_CLASS "Lcom/oracle/graal/graph/NodeClass;" +#define HS_STACK_FRAME_REF "Lcom/oracle/graal/hotspot/HotSpotStackFrameReference;" #define METASPACE_KLASS "J" #define METASPACE_METHOD "J" #define METASPACE_METHOD_DATA "J" @@ -855,6 +1093,8 @@ {CC"isMature", CC"("METASPACE_METHOD_DATA")Z", FN_PTR(isMature)}, {CC"hasCompiledCodeForOSR", CC"("METASPACE_METHOD"II)Z", FN_PTR(hasCompiledCodeForOSR)}, {CC"getTimeStamp", CC"()J", FN_PTR(getTimeStamp)}, + {CC"getNextStackFrame", CC"("HS_STACK_FRAME_REF HS_RESOLVED_METHOD")"HS_STACK_FRAME_REF, FN_PTR(getNextStackFrame)}, + {CC"materializeVirtualObjects", CC"("HS_STACK_FRAME_REF"Z)V", FN_PTR(materializeVirtualObjects)}, }; int CompilerToVM_methods_count() { diff -r 10b0b01a4a61 -r 36e1a11a72b3 src/share/vm/graal/graalJavaAccess.hpp --- a/src/share/vm/graal/graalJavaAccess.hpp Fri Apr 11 13:41:16 2014 +0200 +++ b/src/share/vm/graal/graalJavaAccess.hpp Fri Apr 11 11:52:19 2014 +0200 @@ -202,17 +202,17 @@ start_class(Constant) \ oop_field(Constant, kind, "Lcom/oracle/graal/api/meta/Kind;") \ end_class \ - start_class(PrimitiveConstant) \ - long_field(PrimitiveConstant, primitive) \ + start_class(PrimitiveConstant) \ + long_field(PrimitiveConstant, primitive) \ end_class \ - start_class(NullConstant) \ + start_class(NullConstant) \ end_class \ - start_class(HotSpotObjectConstant) \ - oop_field(HotSpotObjectConstant, object, "Ljava/lang/Object;") \ + start_class(HotSpotObjectConstant) \ + oop_field(HotSpotObjectConstant, object, "Ljava/lang/Object;") \ end_class \ - start_class(HotSpotMetaspaceConstant) \ - long_field(HotSpotMetaspaceConstant, primitive) \ - oop_field(HotSpotMetaspaceConstant, metaspaceObject, "Ljava/lang/Object;") \ + start_class(HotSpotMetaspaceConstant) \ + long_field(HotSpotMetaspaceConstant, primitive) \ + oop_field(HotSpotMetaspaceConstant, metaspaceObject, "Ljava/lang/Object;") \ end_class \ start_class(Kind) \ char_field(Kind, typeChar) \ @@ -249,7 +249,16 @@ end_class \ start_class(SpeculationLog) \ oop_field(SpeculationLog, lastFailed, "Ljava/lang/Object;") \ - end_class + end_class \ + start_class(HotSpotStackFrameReference) \ + oop_field(HotSpotStackFrameReference, compilerToVM, "Lcom/oracle/graal/hotspot/bridge/CompilerToVM;") \ + long_field(HotSpotStackFrameReference, stackPointer) \ + int_field(HotSpotStackFrameReference, frameNumber) \ + int_field(HotSpotStackFrameReference, bci) \ + long_field(HotSpotStackFrameReference, metaspaceMethod) \ + oop_field(HotSpotStackFrameReference, locals, "[Ljava/lang/Object;") \ + oop_field(HotSpotStackFrameReference, localIsVirtual, "[Z") \ + end_class \ /* end*/ #define START_CLASS(name) \ diff -r 10b0b01a4a61 -r 36e1a11a72b3 src/share/vm/oops/method.cpp --- a/src/share/vm/oops/method.cpp Fri Apr 11 13:41:16 2014 +0200 +++ b/src/share/vm/oops/method.cpp Fri Apr 11 11:52:19 2014 +0200 @@ -216,7 +216,7 @@ Thread* myThread = Thread::current(); methodHandle h_this(myThread, this); -#ifdef ASSERT +#if defined(ASSERT) && !defined(GRAAL) bool has_capability = myThread->is_VM_thread() || myThread->is_ConcurrentGC_thread() || myThread->is_GC_task_thread(); diff -r 10b0b01a4a61 -r 36e1a11a72b3 src/share/vm/runtime/deoptimization.hpp --- a/src/share/vm/runtime/deoptimization.hpp Fri Apr 11 13:41:16 2014 +0200 +++ b/src/share/vm/runtime/deoptimization.hpp Fri Apr 11 11:52:19 2014 +0200 @@ -139,6 +139,8 @@ static void revoke_biases_of_monitors(CodeBlob* cb); #if defined(COMPILER2) || defined(GRAAL) +GRAAL_ONLY(public:) + // Support for restoring non-escaping objects static bool realloc_objects(JavaThread* thread, frame* fr, GrowableArray* objects, TRAPS); static void reassign_type_array_elements(frame* fr, RegisterMap* reg_map, ObjectValue* sv, typeArrayOop obj, BasicType type);