/*
* Copyright (c) 2011, 2011, 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.max.graal.examples.deopt;
import java.lang.reflect.*;
import java.util.*;
import com.oracle.max.graal.compiler.graphbuilder.*;
import com.oracle.max.graal.extensions.*;
import com.sun.cri.ci.*;
import com.sun.cri.ci.CiVirtualObject.CiVirtualObjectFactory;
import com.sun.cri.ri.*;
public class FrameModifierImpl implements FrameModifier {
private static DeoptHandler HANDLER = new DeoptHandler();
@Override
public CiFrame getFrame(RiRuntime runtime, CiFrame frame) {
if (frame.method.name().equals("testDeopt")) {
// get the handler method
CiKind returnKind = frame.method.signature().returnKind(true);
String methodName = "handle_" + returnKind;
Method method = null;
try {
method = DeoptHandler.class.getMethod(methodName, RiMethod.class, int.class, Object.class, int.class, int.class, int.class);
} catch (SecurityException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
RiResolvedMethod handlerMethod = runtime.getRiMethod(method);
assert handlerMethod != null : methodName + " not found...";
// put the current state (local vars, expressions, etc.) into an array
CiVirtualObjectFactory factory = new CiVirtualObjectFactory(runtime);
ArrayList<CiValue> originalValues = new ArrayList<CiValue>();
for (int i = 0; i < frame.values.length; i += FrameStateBuilder.stackSlots(frame.values[i].kind)) {
originalValues.add(factory.proxy(frame.values[i]));
}
CiValue boxedValues = factory.arrayProxy(runtime.getType(Object[].class), originalValues.toArray(new CiValue[originalValues.size()]));
// build the list of arguments
CiValue[] newValues = new CiValue[handlerMethod.maxLocals()];
int p = 0;
newValues[p++] = CiConstant.forObject(HANDLER); // receiver
newValues[p++] = CiConstant.forObject(frame.method); // method that caused deoptimization
newValues[p++] = CiConstant.forInt(frame.bci); // bytecode index
newValues[p++] = boxedValues; // original locals, expression stack and locks
newValues[p++] = CiConstant.forInt(frame.numLocals); // number of locals
newValues[p++] = CiConstant.forInt(frame.numStack); // size of expression stack
newValues[p++] = CiConstant.forInt(frame.numLocks); // number of locks
// fill the rest of the local variables with zeros
while (p < newValues.length) {
newValues[p++] = CiValue.IllegalValue;
}
// ... and return a new frame that points to the start of the handler method
return new CiFrame((CiFrame) frame.caller, handlerMethod, /*bci*/ 0, false, newValues, handlerMethod.maxLocals(), 0, 0);
}
return frame;
}
}