# HG changeset patch # User twisti # Date 1397532109 36000 # Node ID ed29f7ff71ebb5918c7858d2f82f5213a1ca6372 # Parent 9dc7efd43c441d994126a11c1f9a52d26f5c676a add DeoptimizationStub diff -r 9dc7efd43c44 -r ed29f7ff71eb graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizationStub.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizationStub.java Mon Apr 14 17:21:49 2014 -1000 @@ -0,0 +1,45 @@ +/* + * 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.amd64; + +import static com.oracle.graal.amd64.AMD64.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.stubs.*; + +final class AMD64DeoptimizationStub extends DeoptimizationStub { + + private RegisterConfig registerConfig; + + public AMD64DeoptimizationStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { + super(providers, target, linkage); + registerConfig = new AMD64HotSpotRegisterConfig(target.arch, HotSpotGraalRuntime.runtime().getConfig(), new Register[]{rax, rbx, rcx, rdx, rsi, rdi, r8, r9, r10, r11, r13, r14}); + } + + @Override + public RegisterConfig getRegisterConfig() { + return registerConfig; + } +} diff -r 9dc7efd43c44 -r ed29f7ff71eb graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizeOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizeOp.java Mon Apr 14 15:36:27 2014 -1000 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizeOp.java Mon Apr 14 17:21:49 2014 -1000 @@ -41,6 +41,6 @@ @Override public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - AMD64Call.directCall(crb, masm, crb.foreignCalls.lookupForeignCall(UNCOMMON_TRAP), null, false, info); + AMD64Call.directCall(crb, masm, crb.foreignCalls.lookupForeignCall(UNCOMMON_TRAP_HANDLER), null, false, info); } } diff -r 9dc7efd43c44 -r ed29f7ff71eb graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java Mon Apr 14 15:36:27 2014 -1000 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java Mon Apr 14 17:21:49 2014 -1000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -26,6 +26,7 @@ import com.oracle.graal.asm.amd64.*; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.StandardOp.*; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.asm.*; @@ -33,11 +34,11 @@ * Removes the current frame and tail calls the uncommon trap routine. */ @Opcode("DEOPT_CALLER") -final class AMD64HotSpotDeoptimizeCallerOp extends AMD64HotSpotEpilogueOp { +final class AMD64HotSpotDeoptimizeCallerOp extends AMD64HotSpotEpilogueOp implements BlockEndOp { @Override public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { leaveFrameAndRestoreRbp(crb, masm); - AMD64Call.directJmp(crb, masm, crb.foreignCalls.lookupForeignCall(UNCOMMON_TRAP)); + AMD64Call.directJmp(crb, masm, crb.foreignCalls.lookupForeignCall(UNCOMMON_TRAP_HANDLER)); } } diff -r 9dc7efd43c44 -r ed29f7ff71eb graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEnterUnpackFramesStackFrameOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEnterUnpackFramesStackFrameOp.java Mon Apr 14 17:21:49 2014 -1000 @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2013, 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.amd64; + +import static com.oracle.graal.amd64.AMD64.*; +import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.hotspot.stubs.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.amd64.*; +import com.oracle.graal.lir.asm.*; + +/** + * Emits code that enters a stack frame which is tailored to call the C++ method + * {@link DeoptimizationStub#UNPACK_FRAMES Deoptimization::unpack_frames}. + */ +@Opcode("ENTER_UNPACK_FRAMES_STACK_FRAME") +final class AMD64HotSpotEnterUnpackFramesStackFrameOp extends AMD64LIRInstruction { + + private final Register thread; + private final int threadLastJavaSpOffset; + private final int threadLastJavaPcOffset; + private final int threadLastJavaFpOffset; + @Alive(REG) AllocatableValue framePc; + @Alive(REG) AllocatableValue senderSp; + @Alive(REG) AllocatableValue senderFp; + + AMD64HotSpotEnterUnpackFramesStackFrameOp(Register thread, int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadLastJavaFpOffset, AllocatableValue framePc, AllocatableValue senderSp, + AllocatableValue senderFp) { + this.thread = thread; + this.threadLastJavaSpOffset = threadLastJavaSpOffset; + this.threadLastJavaPcOffset = threadLastJavaPcOffset; + this.threadLastJavaFpOffset = threadLastJavaFpOffset; + this.framePc = framePc; + this.senderSp = senderSp; + this.senderFp = senderFp; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + final int totalFrameSize = crb.frameMap.totalFrameSize(); + masm.push(asRegister(framePc)); + masm.push(asRegister(senderFp)); + masm.movq(rbp, rsp); + + /* + * Allocate a full sized frame. Since return address and base pointer are already in place + * (see above) we allocate two words less. + */ + masm.decrementq(rsp, totalFrameSize - 2 * crb.target.wordSize); + + // Set up last Java values. + masm.movq(new AMD64Address(thread, threadLastJavaSpOffset), rsp); + + /* + * Save the PC since it cannot easily be retrieved using the last Java SP after we aligned + * SP. Don't need the precise return PC here, just precise enough to point into this code + * blob. + */ + masm.leaq(rax, new AMD64Address(rip, 0)); + masm.movq(new AMD64Address(thread, threadLastJavaPcOffset), rax); + + // Use BP because the frames look interpreted now. + masm.movq(new AMD64Address(thread, threadLastJavaFpOffset), rbp); + + // Align the stack for the following unpackFrames call. + masm.andq(rsp, -(crb.target.stackAlignment)); + } +} diff -r 9dc7efd43c44 -r ed29f7ff71eb graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEpilogueOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEpilogueOp.java Mon Apr 14 15:36:27 2014 -1000 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEpilogueOp.java Mon Apr 14 17:21:49 2014 -1000 @@ -29,7 +29,6 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.amd64.*; -import com.oracle.graal.lir.StandardOp.BlockEndOp; import com.oracle.graal.lir.*; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.asm.*; @@ -37,7 +36,7 @@ /** * Superclass for operations that use the value of RBP saved in a method's prologue. */ -abstract class AMD64HotSpotEpilogueOp extends AMD64LIRInstruction implements BlockEndOp { +abstract class AMD64HotSpotEpilogueOp extends AMD64LIRInstruction { /** * The type of location (i.e., stack or register) in which RBP is saved is not known until diff -r 9dc7efd43c44 -r ed29f7ff71eb graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java Mon Apr 14 15:36:27 2014 -1000 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java Mon Apr 14 17:21:49 2014 -1000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -51,7 +51,8 @@ @Override public void initialize(HotSpotProviders providers, HotSpotVMConfig config) { - Kind word = providers.getCodeCache().getTarget().wordKind; + TargetDescription target = providers.getCodeCache().getTarget(); + Kind word = target.wordKind; // The calling convention for the exception handler stub is (only?) defined in // TemplateInterpreterGenerator::generate_throw_exception() @@ -62,6 +63,8 @@ register(new HotSpotForeignCallLinkage(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF_NOFP, null, exceptionCc, NOT_REEXECUTABLE, ANY_LOCATION)); register(new HotSpotForeignCallLinkage(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF_NOFP, exceptionCc, null, NOT_REEXECUTABLE, ANY_LOCATION)); + link(new AMD64DeoptimizationStub(providers, target, registerStubCall(UNCOMMON_TRAP_HANDLER, REEXECUTABLE, LEAF, NO_LOCATIONS))); + // When the java.ext.dirs property is modified then the crypto classes might not be found. // If that's the case we ignore the ClassNotFoundException and continue since we cannot // replace a non-existing method anyway. diff -r 9dc7efd43c44 -r ed29f7ff71eb graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotJumpToExceptionHandlerInCallerOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotJumpToExceptionHandlerInCallerOp.java Mon Apr 14 15:36:27 2014 -1000 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotJumpToExceptionHandlerInCallerOp.java Mon Apr 14 17:21:49 2014 -1000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -31,6 +31,7 @@ import com.oracle.graal.asm.amd64.*; import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.StandardOp.*; import com.oracle.graal.lir.asm.*; /** @@ -38,7 +39,7 @@ * and jumps to the handler. */ @Opcode("JUMP_TO_EXCEPTION_HANDLER_IN_CALLER") -final class AMD64HotSpotJumpToExceptionHandlerInCallerOp extends AMD64HotSpotEpilogueOp { +final class AMD64HotSpotJumpToExceptionHandlerInCallerOp extends AMD64HotSpotEpilogueOp implements BlockEndOp { @Use(REG) AllocatableValue handlerInCallerPc; @Use(REG) AllocatableValue exception; diff -r 9dc7efd43c44 -r ed29f7ff71eb graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Mon Apr 14 15:36:27 2014 -1000 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Mon Apr 14 17:21:49 2014 -1000 @@ -25,6 +25,7 @@ import static com.oracle.graal.amd64.AMD64.*; import static com.oracle.graal.api.code.ValueUtil.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; +import static com.oracle.graal.hotspot.nodes.UncommonTrapCallNode.*; import java.util.*; @@ -43,7 +44,8 @@ import com.oracle.graal.hotspot.nodes.type.*; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.lir.*; -import com.oracle.graal.lir.StandardOp.NoOp; +import com.oracle.graal.lir.StandardOp.SaveRegistersOp; +import com.oracle.graal.lir.StandardOp.*; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.amd64.AMD64ControlFlow.CondMoveOp; import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapOp; @@ -176,12 +178,65 @@ super.emitForeignCall(linkage, result, arguments, temps, info); } - protected AMD64SaveRegistersOp emitSaveRegisters(Register[] savedRegisters, StackSlot[] savedRegisterLocations) { - AMD64SaveRegistersOp save = new AMD64SaveRegistersOp(savedRegisters, savedRegisterLocations, true); + public void emitLeaveCurrentStackFrame() { + append(new AMD64HotSpotLeaveCurrentStackFrameOp()); + } + + public void emitLeaveDeoptimizedStackFrame(Value frameSize, Value initialInfo) { + Variable frameSizeVariable = load(frameSize); + Variable initialInfoVariable = load(initialInfo); + append(new AMD64HotSpotLeaveDeoptimizedStackFrameOp(frameSizeVariable, initialInfoVariable)); + } + + public void emitEnterUnpackFramesStackFrame(Value framePc, Value senderSp, Value senderFp) { + Register thread = getProviders().getRegisters().getThreadRegister(); + Variable framePcVariable = load(framePc); + Variable senderSpVariable = load(senderSp); + Variable senderFpVariable = load(senderFp); + append(new AMD64HotSpotEnterUnpackFramesStackFrameOp(thread, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadLastJavaFpOffset(), framePcVariable, + senderSpVariable, senderFpVariable)); + } + + public void emitLeaveUnpackFramesStackFrame() { + Register thread = getProviders().getRegisters().getThreadRegister(); + append(new AMD64HotSpotLeaveUnpackFramesStackFrameOp(thread, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadLastJavaFpOffset())); + } + + /** + * @param savedRegisters the registers saved by this operation which may be subject to pruning + * @param savedRegisterLocations the slots to which the registers are saved + * @param supportsRemove determines if registers can be pruned + */ + protected AMD64SaveRegistersOp emitSaveRegisters(Register[] savedRegisters, StackSlot[] savedRegisterLocations, boolean supportsRemove) { + AMD64SaveRegistersOp save = new AMD64SaveRegistersOp(savedRegisters, savedRegisterLocations, supportsRemove); append(save); return save; } + /** + * Adds a node to the graph that saves all allocatable registers to the stack. + * + * @param supportsRemove determines if registers can be pruned + * @return the register save node + */ + private AMD64SaveRegistersOp emitSaveAllRegisters(Register[] savedRegisters, boolean supportsRemove) { + StackSlot[] savedRegisterLocations = new StackSlot[savedRegisters.length]; + for (int i = 0; i < savedRegisters.length; i++) { + PlatformKind kind = target().arch.getLargestStorableKind(savedRegisters[i].getRegisterCategory()); + assert kind != Kind.Illegal; + StackSlot spillSlot = getResult().getFrameMap().allocateSpillSlot(kind); + savedRegisterLocations[i] = spillSlot; + } + return emitSaveRegisters(savedRegisters, savedRegisterLocations, supportsRemove); + } + + @Override + public SaveRegistersOp emitSaveAllRegisters() { + // We are saving all registers. + // TODO Save upper half of YMM registers. + return emitSaveAllRegisters(cpuxmmRegisters, false); + } + protected void emitRestoreRegisters(AMD64SaveRegistersOp save) { append(new AMD64RestoreRegistersOp(save.getSlots().clone(), save)); } @@ -196,19 +251,11 @@ boolean destroysRegisters = hotspotLinkage.destroysRegisters(); AMD64SaveRegistersOp save = null; - StackSlot[] savedRegisterLocations = null; if (destroysRegisters) { if (getStub() != null) { if (getStub().preservesRegisters()) { Register[] savedRegisters = getResult().getFrameMap().registerConfig.getAllocatableRegisters(); - savedRegisterLocations = new StackSlot[savedRegisters.length]; - for (int i = 0; i < savedRegisters.length; i++) { - PlatformKind kind = target().arch.getLargestStorableKind(savedRegisters[i].getRegisterCategory()); - assert kind != Kind.Illegal; - StackSlot spillSlot = getResult().getFrameMap().allocateSpillSlot(kind); - savedRegisterLocations[i] = spillSlot; - } - save = emitSaveRegisters(savedRegisters, savedRegisterLocations); + save = emitSaveAllRegisters(savedRegisters, true); } } } @@ -233,9 +280,9 @@ if (destroysRegisters) { if (getStub() != null) { if (getStub().preservesRegisters()) { - assert !((AMD64HotSpotLIRGenerationResult) getResult()).getCalleeSaveInfo().containsKey(currentRuntimeCallInfo); - ((AMD64HotSpotLIRGenerationResult) getResult()).getCalleeSaveInfo().put(currentRuntimeCallInfo, save); - + AMD64HotSpotLIRGenerationResult generationResult = (AMD64HotSpotLIRGenerationResult) getResult(); + assert !generationResult.getCalleeSaveInfo().containsKey(currentRuntimeCallInfo); + generationResult.getCalleeSaveInfo().put(currentRuntimeCallInfo, save); emitRestoreRegisters(save); } else { assert zapRegisters(); @@ -246,6 +293,21 @@ return result; } + public Value emitUncommonTrapCall(Value trapRequest, SaveRegistersOp saveRegisterOp) { + ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(UNCOMMON_TRAP); + + Register thread = getProviders().getRegisters().getThreadRegister(); + append(new AMD64HotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), thread)); + Variable result = super.emitForeignCall(linkage, null, thread.asValue(Kind.Long), trapRequest); + append(new AMD64HotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaFpOffset(), thread)); + + Map calleeSaveInfo = ((AMD64HotSpotLIRGenerationResult) getResult()).getCalleeSaveInfo(); + assert !calleeSaveInfo.containsKey(currentRuntimeCallInfo); + calleeSaveInfo.put(currentRuntimeCallInfo, saveRegisterOp); + + return result; + } + protected AMD64ZapRegistersOp emitZapRegisters(Register[] zappedRegisters, Constant[] zapValues) { AMD64ZapRegistersOp zap = new AMD64ZapRegistersOp(zappedRegisters, zapValues); append(zap); @@ -374,6 +436,14 @@ } } + public void emitPushInterpreterFrame(Value frameSize, Value framePc, Value senderSp, Value initialInfo) { + Variable frameSizeVariable = load(frameSize); + Variable framePcVariable = load(framePc); + Variable senderSpVariable = load(senderSp); + Variable initialInfoVariable = load(initialInfo); + append(new AMD64HotSpotPushInterpreterFrameOp(frameSizeVariable, framePcVariable, senderSpVariable, initialInfoVariable)); + } + @Override public Variable emitLoad(PlatformKind kind, Value address, Access access) { AMD64AddressValue loadAddress = asAddressValue(address); diff -r 9dc7efd43c44 -r ed29f7ff71eb graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveCurrentStackFrameOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveCurrentStackFrameOp.java Mon Apr 14 17:21:49 2014 -1000 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2013, 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.amd64; + +import static com.oracle.graal.amd64.AMD64.*; + +import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.asm.*; + +/** + * Pops the current frame off the stack including the return address. + */ +@Opcode("LEAVE_CURRENT_STACK_FRAME") +final class AMD64HotSpotLeaveCurrentStackFrameOp extends AMD64HotSpotEpilogueOp { + + @Override + public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + leaveFrameAndRestoreRbp(crb, masm); + masm.addq(rsp, crb.target.arch.getReturnAddressSize()); + } +} diff -r 9dc7efd43c44 -r ed29f7ff71eb graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveDeoptimizedStackFrameOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveDeoptimizedStackFrameOp.java Mon Apr 14 17:21:49 2014 -1000 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2013, 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.amd64; + +import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.amd64.AMD64.*; +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.asm.*; + +/** + * Pops the current frame off the stack including the return address. + */ +@Opcode("LEAVE_DEOPTIMIZED_STACK_FRAME") +final class AMD64HotSpotLeaveDeoptimizedStackFrameOp extends AMD64HotSpotEpilogueOp { + + @Use(REG) AllocatableValue frameSize; + @Use(REG) AllocatableValue framePointer; + + public AMD64HotSpotLeaveDeoptimizedStackFrameOp(AllocatableValue frameSize, AllocatableValue initialInfo) { + this.frameSize = frameSize; + this.framePointer = initialInfo; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + masm.addq(rsp, asRegister(frameSize)); + // Restore the frame pointer before stack bang because if a stack overflow is thrown it + // needs to be pushed (and preserved). + masm.movq(rbp, asRegister(framePointer)); + } +} diff -r 9dc7efd43c44 -r ed29f7ff71eb graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveUnpackFramesStackFrameOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveUnpackFramesStackFrameOp.java Mon Apr 14 17:21:49 2014 -1000 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2013, 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.amd64; + +import static com.oracle.graal.amd64.AMD64.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.hotspot.stubs.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.amd64.*; +import com.oracle.graal.lir.asm.*; + +/** + * Emits code that leaves a stack frame which is tailored to call the C++ method + * {@link DeoptimizationStub#UNPACK_FRAMES Deoptimization::unpack_frames}. + */ +@Opcode("LEAVE_UNPACK_FRAMES_STACK_FRAME") +final class AMD64HotSpotLeaveUnpackFramesStackFrameOp extends AMD64LIRInstruction { + + private final Register thread; + private final int threadLastJavaSpOffset; + private final int threadLastJavaPcOffset; + private final int threadLastJavaFpOffset; + + AMD64HotSpotLeaveUnpackFramesStackFrameOp(Register thread, int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadLastJavaFpOffset) { + this.thread = thread; + this.threadLastJavaSpOffset = threadLastJavaSpOffset; + this.threadLastJavaPcOffset = threadLastJavaPcOffset; + this.threadLastJavaFpOffset = threadLastJavaFpOffset; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + // Restore stack pointer. + masm.movq(rsp, new AMD64Address(thread, threadLastJavaSpOffset)); + + // Clear last Java frame values. + masm.movslq(new AMD64Address(thread, threadLastJavaSpOffset), 0); + masm.movslq(new AMD64Address(thread, threadLastJavaPcOffset), 0); + masm.movslq(new AMD64Address(thread, threadLastJavaFpOffset), 0); + } +} diff -r 9dc7efd43c44 -r ed29f7ff71eb graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotPushInterpreterFrameOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotPushInterpreterFrameOp.java Mon Apr 14 17:21:49 2014 -1000 @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2013, 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.amd64; + +import static com.oracle.graal.amd64.AMD64.*; +import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.amd64.*; +import com.oracle.graal.lir.asm.*; + +/** + * Pushes an interpreter frame to the stack. + */ +@Opcode("PUSH_INTERPRETER_FRAME") +final class AMD64HotSpotPushInterpreterFrameOp extends AMD64LIRInstruction { + + @Alive(REG) AllocatableValue frameSize; + @Alive(REG) AllocatableValue framePc; + @Alive(REG) AllocatableValue senderSp; + @Alive(REG) AllocatableValue initialInfo; + + AMD64HotSpotPushInterpreterFrameOp(AllocatableValue frameSize, AllocatableValue framePc, AllocatableValue senderSp, AllocatableValue initialInfo) { + this.frameSize = frameSize; + this.framePc = framePc; + this.senderSp = senderSp; + this.initialInfo = initialInfo; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + final Register frameSizeRegister = asRegister(frameSize); + final Register framePcRegister = asRegister(framePc); + final Register senderSpRegister = asRegister(senderSp); + final Register initialInfoRegister = asRegister(initialInfo); + final HotSpotVMConfig config = HotSpotGraalRuntime.runtime().getConfig(); + final int wordSize = HotSpotGraalRuntime.runtime().getTarget().wordSize; + + // We'll push PC and BP by hand. + masm.subq(frameSizeRegister, 2 * wordSize); + + // Push return address. + masm.push(framePcRegister); + + // Prolog + masm.push(initialInfoRegister); + masm.movq(initialInfoRegister, rsp); + masm.subq(rsp, frameSizeRegister); + + // This value is corrected by layout_activation_impl. + masm.movptr(new AMD64Address(initialInfoRegister, config.frameInterpreterFrameLastSpOffset * wordSize), 0); + + // Make the frame walkable. + masm.movq(new AMD64Address(initialInfoRegister, config.frameInterpreterFrameSenderSpOffset * wordSize), senderSpRegister); + } +} diff -r 9dc7efd43c44 -r ed29f7ff71eb graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java Mon Apr 14 15:36:27 2014 -1000 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java Mon Apr 14 17:21:49 2014 -1000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -29,13 +29,14 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.amd64.*; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.StandardOp.*; import com.oracle.graal.lir.asm.*; /** * Returns from a function. */ @Opcode("RETURN") -final class AMD64HotSpotReturnOp extends AMD64HotSpotEpilogueOp { +final class AMD64HotSpotReturnOp extends AMD64HotSpotEpilogueOp implements BlockEndOp { @Use({REG, ILLEGAL}) protected Value value; private final boolean isStub; diff -r 9dc7efd43c44 -r ed29f7ff71eb graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotUnwindOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotUnwindOp.java Mon Apr 14 15:36:27 2014 -1000 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotUnwindOp.java Mon Apr 14 17:21:49 2014 -1000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -31,6 +31,7 @@ import com.oracle.graal.asm.amd64.*; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.StandardOp.*; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.asm.*; @@ -38,7 +39,7 @@ * Removes the current frame and jumps to the {@link UnwindExceptionToCallerStub}. */ @Opcode("UNWIND") -final class AMD64HotSpotUnwindOp extends AMD64HotSpotEpilogueOp { +final class AMD64HotSpotUnwindOp extends AMD64HotSpotEpilogueOp implements BlockEndOp { @Use({REG}) protected RegisterValue exception; diff -r 9dc7efd43c44 -r ed29f7ff71eb graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java Mon Apr 14 15:36:27 2014 -1000 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java Mon Apr 14 17:21:49 2014 -1000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -35,6 +35,7 @@ import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.type.*; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.StandardOp.SaveRegistersOp; import com.oracle.graal.lir.hsail.*; import com.oracle.graal.lir.hsail.HSAILControlFlow.CondMoveOp; import com.oracle.graal.lir.hsail.HSAILControlFlow.DeoptimizeOp; @@ -286,15 +287,15 @@ } public void emitTailcall(Value[] args, Value address) { - throw GraalInternalError.shouldNotReachHere("NYI"); + throw GraalInternalError.unimplemented(); } public void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReason reason) { - throw GraalInternalError.shouldNotReachHere("NYI"); + throw GraalInternalError.unimplemented(); } public StackSlot getLockSlot(int lockDepth) { - throw GraalInternalError.shouldNotReachHere("NYI"); + throw GraalInternalError.unimplemented(); } @Override @@ -310,4 +311,32 @@ append(new HSAILMove.UncompressPointer(result, asAllocatable(pointer), encoding.base, encoding.shift, encoding.alignment, nonNull)); return result; } + + public void emitLeaveCurrentStackFrame() { + throw GraalInternalError.unimplemented(); + } + + public void emitLeaveDeoptimizedStackFrame(Value frameSize, Value initialInfo) { + throw GraalInternalError.unimplemented(); + } + + public void emitEnterUnpackFramesStackFrame(Value framePc, Value senderSp, Value senderFp) { + throw GraalInternalError.unimplemented(); + } + + public void emitLeaveUnpackFramesStackFrame() { + throw GraalInternalError.unimplemented(); + } + + public SaveRegistersOp emitSaveAllRegisters() { + throw GraalInternalError.unimplemented(); + } + + public void emitPushInterpreterFrame(Value frameSize, Value framePc, Value senderSp, Value initialInfo) { + throw GraalInternalError.unimplemented(); + } + + public Value emitUncommonTrapCall(Value trapRequest, SaveRegistersOp saveRegisterOp) { + throw GraalInternalError.unimplemented(); + } } diff -r 9dc7efd43c44 -r ed29f7ff71eb graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotLIRGenerator.java Mon Apr 14 15:36:27 2014 -1000 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotLIRGenerator.java Mon Apr 14 17:21:49 2014 -1000 @@ -31,6 +31,7 @@ import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.lir.StandardOp.SaveRegistersOp; /** * LIR generator specialized for PTX HotSpot. @@ -70,4 +71,32 @@ // TODO throw GraalInternalError.unimplemented(); } + + public void emitLeaveCurrentStackFrame() { + throw GraalInternalError.unimplemented(); + } + + public void emitLeaveDeoptimizedStackFrame(Value frameSize, Value initialInfo) { + throw GraalInternalError.unimplemented(); + } + + public void emitEnterUnpackFramesStackFrame(Value framePc, Value senderSp, Value senderFp) { + throw GraalInternalError.unimplemented(); + } + + public void emitLeaveUnpackFramesStackFrame() { + throw GraalInternalError.unimplemented(); + } + + public SaveRegistersOp emitSaveAllRegisters() { + throw GraalInternalError.unimplemented(); + } + + public void emitPushInterpreterFrame(Value frameSize, Value framePc, Value senderSp, Value initialInfo) { + throw GraalInternalError.unimplemented(); + } + + public Value emitUncommonTrapCall(Value trapRequest, SaveRegistersOp saveRegisterOp) { + throw GraalInternalError.unimplemented(); + } } diff -r 9dc7efd43c44 -r ed29f7ff71eb graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizationStub.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizationStub.java Mon Apr 14 17:21:49 2014 -1000 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2012, 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.sparc; + +import static com.oracle.graal.sparc.SPARC.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.stubs.*; + +final class SPARCDeoptimizationStub extends DeoptimizationStub { + + private RegisterConfig registerConfig; + + public SPARCDeoptimizationStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { + super(providers, target, linkage); + registerConfig = new SPARCHotSpotRegisterConfig(target, new Register[]{o0, o1, o2, o3, o4, o5, o7, l0, l1, l2, l3, l4, l5, l6, l7, i0, i1, i2, i3, i4, i5, f0, f1, f2, f3, f4, f5, f6, f7}); + } + + @Override + public RegisterConfig getRegisterConfig() { + return registerConfig; + } +} diff -r 9dc7efd43c44 -r ed29f7ff71eb graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizeOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizeOp.java Mon Apr 14 15:36:27 2014 -1000 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizeOp.java Mon Apr 14 17:21:49 2014 -1000 @@ -49,6 +49,6 @@ // [Deopt Handler Code] // 0xffffffff749bb60c: call 0xffffffff748da540 ; {runtime_call} // 0xffffffff749bb610: nop - SPARCCall.directCall(crb, masm, crb.foreignCalls.lookupForeignCall(UNCOMMON_TRAP), null, false, info); + SPARCCall.directCall(crb, masm, crb.foreignCalls.lookupForeignCall(UNCOMMON_TRAP_HANDLER), null, false, info); } } diff -r 9dc7efd43c44 -r ed29f7ff71eb graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotDeoptimizeCallerOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotDeoptimizeCallerOp.java Mon Apr 14 15:36:27 2014 -1000 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotDeoptimizeCallerOp.java Mon Apr 14 17:21:49 2014 -1000 @@ -47,7 +47,7 @@ // HotSpotFrameContext frameContext = backend.new HotSpotFrameContext(isStub); // frameContext.enter(crb); Register scratch = g3; - SPARCCall.indirectJmp(crb, masm, scratch, crb.foreignCalls.lookupForeignCall(UNCOMMON_TRAP)); + SPARCCall.indirectJmp(crb, masm, scratch, crb.foreignCalls.lookupForeignCall(UNCOMMON_TRAP_HANDLER)); // frameContext.leave(crb); } diff -r 9dc7efd43c44 -r ed29f7ff71eb graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java Mon Apr 14 15:36:27 2014 -1000 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java Mon Apr 14 17:21:49 2014 -1000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -46,7 +46,8 @@ @Override public void initialize(HotSpotProviders providers, HotSpotVMConfig config) { - Kind word = providers.getCodeCache().getTarget().wordKind; + TargetDescription target = providers.getCodeCache().getTarget(); + Kind word = target.wordKind; // The calling convention for the exception handler stub is (only?) defined in // TemplateInterpreterGenerator::generate_throw_exception() @@ -60,6 +61,8 @@ register(new HotSpotForeignCallLinkage(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF_NOFP, outgoingExceptionCc, incomingExceptionCc, NOT_REEXECUTABLE, ANY_LOCATION)); register(new HotSpotForeignCallLinkage(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF_NOFP, outgoingExceptionCc, incomingExceptionCc, NOT_REEXECUTABLE, ANY_LOCATION)); + link(new SPARCDeoptimizationStub(providers, target, registerStubCall(UNCOMMON_TRAP_HANDLER, REEXECUTABLE, LEAF, NO_LOCATIONS))); + super.initialize(providers, config); } diff -r 9dc7efd43c44 -r ed29f7ff71eb graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java Mon Apr 14 15:36:27 2014 -1000 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java Mon Apr 14 17:21:49 2014 -1000 @@ -35,6 +35,7 @@ import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.StandardOp.SaveRegistersOp; import com.oracle.graal.lir.sparc.*; import com.oracle.graal.lir.sparc.SPARCMove.LoadOp; import com.oracle.graal.lir.sparc.SPARCMove.StoreConstantOp; @@ -258,4 +259,39 @@ // TODO throw GraalInternalError.unimplemented(); } + + public SaveRegistersOp emitSaveAllRegisters() { + // TODO Auto-generated method stub + throw GraalInternalError.unimplemented(); + } + + public void emitLeaveCurrentStackFrame() { + // TODO Auto-generated method stub + throw GraalInternalError.unimplemented(); + } + + public void emitLeaveDeoptimizedStackFrame(Value frameSize, Value initialInfo) { + // TODO Auto-generated method stub + throw GraalInternalError.unimplemented(); + } + + public void emitEnterUnpackFramesStackFrame(Value framePc, Value senderSp, Value senderFp) { + // TODO Auto-generated method stub + throw GraalInternalError.unimplemented(); + } + + public void emitLeaveUnpackFramesStackFrame() { + // TODO Auto-generated method stub + throw GraalInternalError.unimplemented(); + } + + public void emitPushInterpreterFrame(Value frameSize, Value framePc, Value senderSp, Value initialInfo) { + // TODO Auto-generated method stub + throw GraalInternalError.unimplemented(); + } + + public Value emitUncommonTrapCall(Value trapRequest, SaveRegistersOp saveRegisterOp) { + // TODO Auto-generated method stub + throw GraalInternalError.unimplemented(); + } } diff -r 9dc7efd43c44 -r ed29f7ff71eb 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 Mon Apr 14 15:36:27 2014 -1000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java Mon Apr 14 17:21:49 2014 -1000 @@ -45,9 +45,9 @@ public abstract class HotSpotBackend extends Backend { /** - * Descriptor for SharedRuntime::deopt_blob()->uncommon_trap(). + * Descriptor for {@link DeoptimizationStub}. */ - public static final ForeignCallDescriptor UNCOMMON_TRAP = new ForeignCallDescriptor("deoptimize", void.class); + public static final ForeignCallDescriptor UNCOMMON_TRAP_HANDLER = new ForeignCallDescriptor("uncommonTrapHandler", void.class); /** * Descriptor for {@link ExceptionHandlerStub}. This stub is called by the diff -r 9dc7efd43c44 -r ed29f7ff71eb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledRuntimeStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledRuntimeStub.java Mon Apr 14 15:36:27 2014 -1000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledRuntimeStub.java Mon Apr 14 17:21:49 2014 -1000 @@ -22,6 +22,8 @@ */ package com.oracle.graal.hotspot; +import static com.oracle.graal.hotspot.HotSpotBackend.*; + import com.oracle.graal.api.code.*; import com.oracle.graal.api.code.CompilationResult.Call; import com.oracle.graal.api.code.CompilationResult.DataPatch; @@ -41,8 +43,8 @@ public HotSpotCompiledRuntimeStub(TargetDescription target, Stub stub, CompilationResult compResult) { super(target, compResult); + this.stubName = stub.toString(); assert checkStubInvariants(compResult); - this.stubName = stub.toString(); } /** @@ -67,8 +69,13 @@ Call call = (Call) infopoint; assert call.target instanceof HotSpotForeignCallLinkage : this + " cannot have non runtime call: " + call.target; HotSpotForeignCallLinkage linkage = (HotSpotForeignCallLinkage) call.target; - assert !linkage.isCompiledStub() : this + " cannot call compiled stub " + linkage; + assert !linkage.isCompiledStub() || linkage.getDescriptor() == UNCOMMON_TRAP_HANDLER : this + " cannot call compiled stub " + linkage; } return true; } + + @Override + public String toString() { + return stubName != null ? stubName : super.toString(); + } } diff -r 9dc7efd43c44 -r ed29f7ff71eb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRGenerator.java Mon Apr 14 15:36:27 2014 -1000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRGenerator.java Mon Apr 14 17:21:49 2014 -1000 @@ -27,6 +27,7 @@ import com.oracle.graal.compiler.gen.*; import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.lir.StandardOp.SaveRegistersOp; import com.oracle.graal.nodes.spi.*; /** @@ -43,8 +44,22 @@ */ void emitTailcall(Value[] args, Value address); + void emitLeaveCurrentStackFrame(); + + void emitLeaveDeoptimizedStackFrame(Value frameSize, Value initialInfo); + + void emitEnterUnpackFramesStackFrame(Value framePc, Value senderSp, Value senderFp); + + void emitLeaveUnpackFramesStackFrame(); + + SaveRegistersOp emitSaveAllRegisters(); + void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReason reason); + void emitPushInterpreterFrame(Value frameSize, Value framePc, Value senderSp, Value initialInfo); + + Value emitUncommonTrapCall(Value trapRequest, SaveRegistersOp saveRegisterOp); + /** * Gets a stack slot for a lock at a given lock nesting depth. */ diff -r 9dc7efd43c44 -r ed29f7ff71eb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Mon Apr 14 15:36:27 2014 -1000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Mon Apr 14 17:21:49 2014 -1000 @@ -962,7 +962,10 @@ return javaThreadAnchorOffset + javaFrameAnchorFlagsOffset; } + // These are only valid on AMD64. @HotSpotVMConstant(name = "frame::arg_reg_save_area_bytes", archs = {"amd64"}) @Stable public int runtimeCallStackSize; + @HotSpotVMConstant(name = "frame::interpreter_frame_sender_sp_offset", archs = {"amd64"}) @Stable public int frameInterpreterFrameSenderSpOffset; + @HotSpotVMConstant(name = "frame::interpreter_frame_last_sp_offset", archs = {"amd64"}) @Stable public int frameInterpreterFrameLastSpOffset; @HotSpotVMField(name = "PtrQueue::_active", type = "bool", get = HotSpotVMField.Type.OFFSET) @Stable public int ptrQueueActiveOffset; @HotSpotVMField(name = "PtrQueue::_buf", type = "void**", get = HotSpotVMField.Type.OFFSET) @Stable public int ptrQueueBufferOffset; @@ -1348,7 +1351,6 @@ } @Stable public long handleDeoptStub; - @Stable public long uncommonTrapStub; @HotSpotVMField(name = "StubRoutines::_aescrypt_encryptBlock", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long aescryptEncryptBlockStub; @HotSpotVMField(name = "StubRoutines::_aescrypt_decryptBlock", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long aescryptDecryptBlockStub; @@ -1418,6 +1420,10 @@ @Stable public int graalCountersSize; + @Stable public long deoptimizationFetchUnrollInfo; + @Stable public long deoptimizationUncommonTrap; + @Stable public long deoptimizationUnpackFrames; + @HotSpotVMConstant(name = "Deoptimization::Reason_none") @Stable public int deoptReasonNone; @HotSpotVMConstant(name = "Deoptimization::Reason_null_check") @Stable public int deoptReasonNullCheck; @HotSpotVMConstant(name = "Deoptimization::Reason_range_check") @Stable public int deoptReasonRangeCheck; @@ -1448,6 +1454,19 @@ @HotSpotVMConstant(name = "Deoptimization::_reason_shift") @Stable public int deoptimizationReasonShift; @HotSpotVMConstant(name = "Deoptimization::_debug_id_shift") @Stable public int deoptimizationDebugIdShift; + @HotSpotVMConstant(name = "Deoptimization::Unpack_deopt") @Stable public int deoptimizationUnpackDeopt; + @HotSpotVMConstant(name = "Deoptimization::Unpack_exception") @Stable public int deoptimizationUnpackException; + @HotSpotVMConstant(name = "Deoptimization::Unpack_uncommon_trap") @Stable public int deoptimizationUnpackUncommonTrap; + @HotSpotVMConstant(name = "Deoptimization::Unpack_reexecute") @Stable public int deoptimizationUnpackReexecute; + + @HotSpotVMField(name = "Deoptimization::UnrollBlock::_size_of_deoptimized_frame", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset; + @HotSpotVMField(name = "Deoptimization::UnrollBlock::_caller_adjustment", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockCallerAdjustmentOffset; + @HotSpotVMField(name = "Deoptimization::UnrollBlock::_number_of_frames", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockNumberOfFramesOffset; + @HotSpotVMField(name = "Deoptimization::UnrollBlock::_total_frame_sizes", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockTotalFrameSizesOffset; + @HotSpotVMField(name = "Deoptimization::UnrollBlock::_frame_sizes", type = "intptr_t*", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockFrameSizesOffset; + @HotSpotVMField(name = "Deoptimization::UnrollBlock::_frame_pcs", type = "address*", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockFramePcsOffset; + @HotSpotVMField(name = "Deoptimization::UnrollBlock::_initial_info", type = "intptr_t", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockInitialInfoOffset; + @HotSpotVMConstant(name = "vmIntrinsics::_invokeBasic") @Stable public int vmIntrinsicInvokeBasic; @HotSpotVMConstant(name = "vmIntrinsics::_linkToVirtual") @Stable public int vmIntrinsicLinkToVirtual; @HotSpotVMConstant(name = "vmIntrinsics::_linkToStatic") @Stable public int vmIntrinsicLinkToStatic; diff -r 9dc7efd43c44 -r ed29f7ff71eb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java Mon Apr 14 15:36:27 2014 -1000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java Mon Apr 14 17:21:49 2014 -1000 @@ -30,6 +30,7 @@ import static com.oracle.graal.hotspot.nodes.NewArrayStubCall.*; import static com.oracle.graal.hotspot.nodes.NewInstanceStubCall.*; import static com.oracle.graal.hotspot.nodes.NewMultiArrayStubCall.*; +import static com.oracle.graal.hotspot.nodes.UncommonTrapCallNode.*; import static com.oracle.graal.hotspot.nodes.VMErrorNode.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; import static com.oracle.graal.hotspot.replacements.MonitorSnippets.*; @@ -37,6 +38,7 @@ import static com.oracle.graal.hotspot.replacements.SystemSubstitutions.*; import static com.oracle.graal.hotspot.replacements.ThreadSubstitutions.*; import static com.oracle.graal.hotspot.replacements.WriteBarrierSnippets.*; +import static com.oracle.graal.hotspot.stubs.DeoptimizationStub.*; import static com.oracle.graal.hotspot.stubs.ExceptionHandlerStub.*; import static com.oracle.graal.hotspot.stubs.NewArrayStub.*; import static com.oracle.graal.hotspot.stubs.NewInstanceStub.*; @@ -64,7 +66,7 @@ super(runtime, metaAccess, codeCache); } - private static void link(Stub stub) { + protected static void link(Stub stub) { stub.getLinkage().setCompiledStub(stub); } @@ -101,7 +103,6 @@ public void initialize(HotSpotProviders providers, HotSpotVMConfig c) { TargetDescription target = providers.getCodeCache().getTarget(); - registerForeignCall(UNCOMMON_TRAP, c.uncommonTrapStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); registerForeignCall(DEOPT_HANDLER, c.handleDeoptStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); registerForeignCall(IC_MISS_HANDLER, c.inlineCacheMissStub(), NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); @@ -114,8 +115,11 @@ registerForeignCall(EXCEPTION_HANDLER_FOR_PC, c.exceptionHandlerForPcAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION); registerForeignCall(EXCEPTION_HANDLER_FOR_RETURN_ADDRESS, c.exceptionHandlerForReturnAddressAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION); + registerForeignCall(FETCH_UNROLL_INFO, c.deoptimizationFetchUnrollInfo, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION); registerForeignCall(NEW_ARRAY_C, c.newArrayAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION); registerForeignCall(NEW_INSTANCE_C, c.newInstanceAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION); + registerForeignCall(UNCOMMON_TRAP, c.deoptimizationUncommonTrap, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, NOT_REEXECUTABLE, ANY_LOCATION); + registerForeignCall(UNPACK_FRAMES, c.deoptimizationUnpackFrames, NativeCall, DESTROYS_REGISTERS, LEAF, NOT_REEXECUTABLE, ANY_LOCATION); registerForeignCall(VM_MESSAGE_C, c.vmMessageAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, NO_LOCATIONS); link(new NewInstanceStub(providers, target, registerStubCall(NEW_INSTANCE, REEXECUTABLE, NOT_LEAF, ANY_LOCATION))); diff -r 9dc7efd43c44 -r ed29f7ff71eb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EnterUnpackFramesStackFrameNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EnterUnpackFramesStackFrameNode.java Mon Apr 14 17:21:49 2014 -1000 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2013, 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.nodes; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.stubs.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.word.*; + +/** + * Emits code to enter a low-level stack frame specifically to call out to the C++ method + * {@link DeoptimizationStub#UNPACK_FRAMES Deoptimization::unpack_frames}. + */ +public class EnterUnpackFramesStackFrameNode extends FixedWithNextNode implements LIRLowerable { + + @Input private ValueNode framePc; + @Input private ValueNode senderSp; + @Input private ValueNode senderFp; + + public EnterUnpackFramesStackFrameNode(ValueNode framePc, ValueNode senderSp, ValueNode senderFp) { + super(StampFactory.forVoid()); + this.framePc = framePc; + this.senderSp = senderSp; + this.senderFp = senderFp; + } + + @Override + public void generate(NodeLIRBuilderTool gen) { + Value operandValue = gen.operand(framePc); + Value senderSpValue = gen.operand(senderSp); + Value senderFpValue = gen.operand(senderFp); + ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitEnterUnpackFramesStackFrame(operandValue, senderSpValue, senderFpValue); + } + + @NodeIntrinsic + public static native void enterUnpackFramesStackFrame(Word framePc, Word senderSp, Word senderFp); +} diff -r 9dc7efd43c44 -r ed29f7ff71eb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveCurrentStackFrameNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveCurrentStackFrameNode.java Mon Apr 14 17:21:49 2014 -1000 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2013, 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.nodes; + +import com.oracle.graal.hotspot.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +/** + * Emits code to leave (pop) the current low-level stack frame. This operation also removes the + * return address if its location is on the stack. + */ +public class LeaveCurrentStackFrameNode extends FixedWithNextNode implements LIRLowerable { + + public LeaveCurrentStackFrameNode() { + super(StampFactory.forVoid()); + } + + @Override + public void generate(NodeLIRBuilderTool gen) { + ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitLeaveCurrentStackFrame(); + } + + @NodeIntrinsic + public static native void leaveCurrentStackFrame(); +} diff -r 9dc7efd43c44 -r ed29f7ff71eb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveDeoptimizedStackFrameNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveDeoptimizedStackFrameNode.java Mon Apr 14 17:21:49 2014 -1000 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2013, 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.nodes; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.stubs.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.word.*; + +/** + * Emits code to leave (pop) the current low-level stack frame which is being deoptimized. This node + * is only used in {@link DeoptimizationStub}. + */ +public class LeaveDeoptimizedStackFrameNode extends FixedWithNextNode implements LIRLowerable { + + @Input private ValueNode frameSize; + @Input private ValueNode initialInfo; + + public LeaveDeoptimizedStackFrameNode(ValueNode frameSize, ValueNode initialInfo) { + super(StampFactory.forVoid()); + this.frameSize = frameSize; + this.initialInfo = initialInfo; + } + + @Override + public void generate(NodeLIRBuilderTool gen) { + Value frameSizeValue = gen.operand(frameSize); + Value initialInfoValue = gen.operand(initialInfo); + ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitLeaveDeoptimizedStackFrame(frameSizeValue, initialInfoValue); + } + + @NodeIntrinsic + public static native void leaveDeoptimizedStackFrame(int frameSize, Word initialInfo); +} diff -r 9dc7efd43c44 -r ed29f7ff71eb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveUnpackFramesStackFrameNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveUnpackFramesStackFrameNode.java Mon Apr 14 17:21:49 2014 -1000 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2013, 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.nodes; + +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.stubs.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +/** + * Emits code to leave a low-level stack frame specifically to call out to the C++ method + * {@link DeoptimizationStub#UNPACK_FRAMES Deoptimization::unpack_frames}. + */ +public class LeaveUnpackFramesStackFrameNode extends FixedWithNextNode implements LIRLowerable { + + public LeaveUnpackFramesStackFrameNode() { + super(StampFactory.forVoid()); + } + + @Override + public void generate(NodeLIRBuilderTool gen) { + ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitLeaveUnpackFramesStackFrame(); + } + + @NodeIntrinsic + public static native void leaveUnpackFramesStackFrame(); +} diff -r 9dc7efd43c44 -r ed29f7ff71eb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PushInterpreterFrameNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PushInterpreterFrameNode.java Mon Apr 14 17:21:49 2014 -1000 @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2013, 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.nodes; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.word.*; + +/** + * A call to the runtime code implementing the uncommon trap logic. + */ +public class PushInterpreterFrameNode extends FixedWithNextNode implements LIRLowerable { + + @Input private ValueNode framePc; + @Input private ValueNode frameSize; + @Input private ValueNode senderSp; + @Input private ValueNode initialInfo; + + public PushInterpreterFrameNode(ValueNode frameSize, ValueNode framePc, ValueNode senderSp, ValueNode initialInfo) { + super(StampFactory.forVoid()); + this.frameSize = frameSize; + this.framePc = framePc; + this.senderSp = senderSp; + this.initialInfo = initialInfo; + } + + @Override + public void generate(NodeLIRBuilderTool gen) { + Value frameSizeValue = gen.operand(frameSize); + Value framePcValue = gen.operand(framePc); + Value senderSpValue = gen.operand(senderSp); + Value initialInfoValue = gen.operand(initialInfo); + ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitPushInterpreterFrame(frameSizeValue, framePcValue, senderSpValue, initialInfoValue); + } + + @NodeIntrinsic + public static native void pushInterpreterFrame(Word frameSize, Word framePc, Word senderSp, Word initialInfo); + +} diff -r 9dc7efd43c44 -r ed29f7ff71eb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SaveAllRegistersNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SaveAllRegistersNode.java Mon Apr 14 17:21:49 2014 -1000 @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2013, 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.nodes; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.lir.StandardOp.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +/** + * Saves all allocatable registers. + */ +public class SaveAllRegistersNode extends FixedWithNextNode implements LIRLowerable { + + private SaveRegistersOp saveRegistersOp; + + public SaveAllRegistersNode() { + super(StampFactory.forKind(Kind.Long)); + } + + @Override + public void generate(NodeLIRBuilderTool gen) { + saveRegistersOp = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitSaveAllRegisters(); + } + + /** + * @return the map from registers to the stack locations in they are saved + */ + public SaveRegistersOp getSaveRegistersOp() { + assert saveRegistersOp != null : "saved registers op has not yet been created"; + return saveRegistersOp; + } + + /** + * @return a token that couples this node to an {@link UncommonTrapCallNode} so that the latter + * has access to the {@linkplain SaveRegistersOp#getMap register save map} + */ + @NodeIntrinsic + public static native long saveAllRegisters(); +} diff -r 9dc7efd43c44 -r ed29f7ff71eb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java Mon Apr 14 15:36:27 2014 -1000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java Mon Apr 14 17:21:49 2014 -1000 @@ -68,7 +68,7 @@ @Override public void generate(NodeLIRBuilderTool gen) { assert graph().start() instanceof StubStartNode; - ForeignCallLinkage linkage = gen.getLIRGeneratorTool().getForeignCalls().lookupForeignCall(descriptor); + ForeignCallLinkage linkage = foreignCalls.lookupForeignCall(descriptor); Value[] operands = operands(gen); Value result = gen.getLIRGeneratorTool().emitForeignCall(linkage, null, operands); if (result != null) { diff -r 9dc7efd43c44 -r ed29f7ff71eb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/UncommonTrapCallNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/UncommonTrapCallNode.java Mon Apr 14 17:21:49 2014 -1000 @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2013, 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.nodes; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.lir.StandardOp.SaveRegistersOp; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.word.*; + +/** + * A call to the runtime code implementing the uncommon trap logic. + */ +@NodeInfo(allowedUsageTypes = {InputType.Memory}) +public class UncommonTrapCallNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Multi { + + @Input private ValueNode trapRequest; + @Input private SaveAllRegistersNode registerSaver; + private final ForeignCallsProvider foreignCalls; + public static final ForeignCallDescriptor UNCOMMON_TRAP = new ForeignCallDescriptor("uncommonTrap", Word.class, Word.class, int.class); + + public UncommonTrapCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ValueNode registerSaver, ValueNode trapRequest) { + super(StampFactory.forKind(Kind.fromJavaClass(UNCOMMON_TRAP.getResultType()))); + this.trapRequest = trapRequest; + this.registerSaver = (SaveAllRegistersNode) registerSaver; + this.foreignCalls = foreignCalls; + } + + @Override + public LocationIdentity[] getLocationIdentities() { + return foreignCalls.getKilledLocations(UNCOMMON_TRAP); + } + + public SaveRegistersOp getSaveRegistersOp() { + return registerSaver.getSaveRegistersOp(); + } + + @Override + public void generate(NodeLIRBuilderTool gen) { + Value trapRequestValue = gen.operand(trapRequest); + Value result = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitUncommonTrapCall(trapRequestValue, getSaveRegistersOp()); + gen.setResult(this, result); + } + + @NodeIntrinsic + public static native Word uncommonTrap(long registerSaver, int trapRequest); + + public MemoryCheckpoint asMemoryCheckpoint() { + return null; + } + + public MemoryPhiNode asMemoryPhi() { + return null; + } +} diff -r 9dc7efd43c44 -r ed29f7ff71eb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java Mon Apr 14 15:36:27 2014 -1000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java Mon Apr 14 17:21:49 2014 -1000 @@ -80,6 +80,20 @@ return config().threadExceptionPcOffset; } + public static final LocationIdentity LAST_JAVA_PC_LOCATION = new NamedLocationIdentity("LastJavaPc"); + + @Fold + public static int threadLastJavaPcOffset() { + return config().threadLastJavaPcOffset(); + } + + public static final LocationIdentity LAST_JAVA_FP_LOCATION = new NamedLocationIdentity("LastJavaFp"); + + @Fold + public static int threadLastJavaFpOffset() { + return config().threadLastJavaFpOffset(); + } + public static final LocationIdentity TLAB_TOP_LOCATION = new NamedLocationIdentity("TlabTop"); @Fold @@ -111,6 +125,16 @@ return config().pendingExceptionOffset; } + public static final LocationIdentity PENDING_DEOPTIMIZATION_LOCATION = new NamedLocationIdentity("PendingDeoptimization"); + + /** + * @see HotSpotVMConfig#pendingDeoptimizationOffset + */ + @Fold + private static int threadPendingDeoptimizationOffset() { + return config().pendingDeoptimizationOffset; + } + public static final LocationIdentity OBJECT_RESULT_LOCATION = new NamedLocationIdentity("ObjectResult"); @Fold @@ -140,6 +164,14 @@ thread.writeWord(threadExceptionPcOffset(), value, EXCEPTION_PC_LOCATION); } + public static void writeLastJavaPc(Word thread, Word value) { + thread.writeWord(threadLastJavaPcOffset(), value, LAST_JAVA_PC_LOCATION); + } + + public static void writeLastJavaFp(Word thread, Word value) { + thread.writeWord(threadLastJavaFpOffset(), value, LAST_JAVA_FP_LOCATION); + } + public static Word readTlabTop(Word thread) { return thread.readWord(threadTlabTopOffset(), TLAB_TOP_LOCATION); } @@ -174,6 +206,22 @@ } /** + * Reads the pending deoptimization value for the given thread. + * + * @return {@code true} if there was a pending deoptimization + */ + public static int readPendingDeoptimization(Word thread) { + return thread.readInt(threadPendingDeoptimizationOffset(), PENDING_DEOPTIMIZATION_LOCATION); + } + + /** + * Writes the pending deoptimization value for the given thread. + */ + public static void writePendingDeoptimization(Word thread, int value) { + thread.writeInt(threadPendingDeoptimizationOffset(), value, PENDING_DEOPTIMIZATION_LOCATION); + } + + /** * Gets and clears the object result from a runtime call stored in a thread local. * * @return the object that was in the thread local @@ -498,6 +546,9 @@ @NodeIntrinsic(value = ReadRegisterNode.class, setStampFromReturnType = true) public static native Word registerAsWord(@ConstantNodeParameter Register register, @ConstantNodeParameter boolean directUse, @ConstantNodeParameter boolean incoming); + @NodeIntrinsic(value = WriteRegisterNode.class, setStampFromReturnType = true) + public static native void writeRegisterAsWord(@ConstantNodeParameter Register register, Word value); + @SuppressWarnings("unused") @NodeIntrinsic(value = UnsafeLoadNode.class, setStampFromReturnType = true) private static Word loadWordFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter Kind wordKind, @ConstantNodeParameter LocationIdentity locationIdentity) { diff -r 9dc7efd43c44 -r ed29f7ff71eb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/DeoptimizationStub.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/DeoptimizationStub.java Mon Apr 14 17:21:49 2014 -1000 @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2013, 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.stubs; + +import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; +import static com.oracle.graal.hotspot.stubs.StubUtil.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.Node.ConstantNodeParameter; +import com.oracle.graal.graph.Node.NodeIntrinsic; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.replacements.*; +import com.oracle.graal.replacements.Snippet.*; +import com.oracle.graal.word.*; + +/** + * Deoptimization stub. + * + * This is the entry point for code which is returning to a de-optimized frame. + * + * The steps taken by this frame are as follows: + * + * - push a dummy "register_save" and save the return values (O0, O1, F0/F1, G1) and all potentially + * live registers (at a pollpoint many registers can be live). + * + * - call the C routine: Deoptimization::fetch_unroll_info (this function returns information about + * the number and size of interpreter frames which are equivalent to the frame which is being + * deoptimized) + * + * - deallocate the unpack frame, restoring only results values. Other volatile registers will now + * be captured in the vframeArray as needed. + * + * - deallocate the deoptimization frame + * + * - in a loop using the information returned in the previous step push new interpreter frames (take + * care to propagate the return values through each new frame pushed) + * + * - create a dummy "unpack_frame" and save the return values (O0, O1, F0) + * + * - call the C routine: Deoptimization::unpack_frames (this function lays out values on the + * interpreter frame which was just created) + * + * - deallocate the dummy unpack_frame + * + * - ensure that all the return values are correctly set and then do a return to the interpreter + * entry point + */ +public class DeoptimizationStub extends SnippetStub { + + private final TargetDescription target; + + public DeoptimizationStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { + super(providers, target, linkage); + this.target = target; + } + + @Override + public boolean preservesRegisters() { + return false; + } + + @Override + protected Object getConstantParameterValue(int index, String name) { + switch (index) { + case 0: + return providers.getRegisters().getThreadRegister(); + case 1: + return providers.getRegisters().getStackPointerRegister(); + default: + throw GraalInternalError.shouldNotReachHere("unknown parameter " + name + " at index " + index); + } + } + + /** + * Uncommon trap. + * + * We save the argument return registers. We call the first C routine, fetch_unroll_info(). This + * routine captures the return values and returns a structure which describes the current frame + * size and the sizes of all replacement frames. The current frame is compiled code and may + * contain many inlined functions, each with their own JVM state. We pop the current frame, then + * push all the new frames. Then we call the C routine unpack_frames() to populate these frames. + * Finally unpack_frames() returns us the new target address. Notice that callee-save registers + * are BLOWN here; they have already been captured in the vframeArray at the time the return PC + * was patched. + * + *

+ * ATTENTION: We cannot do any complicated operations e.g. logging via printf in this snippet + * because we change the current stack layout and so the code is very sensitive to register + * allocation. + */ + @Snippet + private static void uncommonTrapHandler(@ConstantParameter Register threadRegister, @ConstantParameter Register stackPointerRegister) { + final Word thread = registerAsWord(threadRegister); + long registerSaver = SaveAllRegistersNode.saveAllRegisters(); + + final int actionAndReason = readPendingDeoptimization(thread); + writePendingDeoptimization(thread, -1); + + final Word unrollBlock = UncommonTrapCallNode.uncommonTrap(registerSaver, actionAndReason); + + // Pop all the frames we must move/replace. + // + // Frame picture (youngest to oldest) + // 1: self-frame (no frame link) + // 2: deoptimizing frame (no frame link) + // 3: caller of deoptimizing frame (could be compiled/interpreted). + + // Pop self-frame. + LeaveCurrentStackFrameNode.leaveCurrentStackFrame(); + + // Load the initial info we should save (e.g. frame pointer). + final Word initialInfo = unrollBlock.readWord(deoptimizationUnrollBlockInitialInfoOffset()); + + // Pop deoptimized frame + final int sizeOfDeoptimizedFrame = unrollBlock.readInt(deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset()); + LeaveDeoptimizedStackFrameNode.leaveDeoptimizedStackFrame(sizeOfDeoptimizedFrame, initialInfo); + + /* + * Stack bang to make sure there's enough room for the interpreter frames. Bang stack for + * total size of the interpreter frames plus shadow page size. Bang one page at a time + * because large sizes can bang beyond yellow and red zones. + */ + final int totalFrameSizes = unrollBlock.readInt(deoptimizationUnrollBlockTotalFrameSizesOffset()); + final int bangPages = NumUtil.roundUp(totalFrameSizes, pageSize()) / pageSize() + stackShadowPages(); + Word stackPointer = readRegister(stackPointerRegister); + + for (int i = 1; i < bangPages; i++) { + stackPointer.writeInt(-(i * pageSize()), i); + } + + // Load number of interpreter frames. + final int numberOfFrames = unrollBlock.readInt(deoptimizationUnrollBlockNumberOfFramesOffset()); + + // Load address of array of frame sizes. + final Word frameSizes = unrollBlock.readWord(deoptimizationUnrollBlockFrameSizesOffset()); + + // Load address of array of frame PCs. + final Word framePcs = unrollBlock.readWord(deoptimizationUnrollBlockFramePcsOffset()); + + /* + * Get the current stack pointer (sender's original SP) before adjustment so that we can + * save it in the skeletal interpreter frame. + */ + Word senderSp = readRegister(stackPointerRegister); + + // Adjust old interpreter frame to make space for new frame's extra Java locals. + final int callerAdjustment = unrollBlock.readInt(deoptimizationUnrollBlockCallerAdjustmentOffset()); + writeRegister(stackPointerRegister, readRegister(stackPointerRegister).subtract(callerAdjustment)); + + for (int i = 0; i < numberOfFrames; i++) { + final Word frameSize = frameSizes.readWord(i * wordSize()); + final Word framePc = framePcs.readWord(i * wordSize()); + + // Push an interpreter frame onto the stack. + PushInterpreterFrameNode.pushInterpreterFrame(frameSize, framePc, senderSp, initialInfo); + + // Get the current stack pointer (sender SP) and pass it to next frame. + senderSp = readRegister(stackPointerRegister); + } + + // Get final return address. + final Word framePc = framePcs.readWord(numberOfFrames * wordSize()); + + /* + * Enter a frame to call out to unpack frames. Since we changed the stack pointer to an + * unknown alignment we need to align it here before calling C++ code. + */ + final Word senderFp = initialInfo; + EnterUnpackFramesStackFrameNode.enterUnpackFramesStackFrame(framePc, senderSp, senderFp); + + // Pass uncommon trap mode to unpack frames. + final int mode = deoptimizationUnpackUncommonTrap(); + unpackFrames(UNPACK_FRAMES, thread, mode); + + LeaveUnpackFramesStackFrameNode.leaveUnpackFramesStackFrame(); + } + + /** + * Reads the value of the passed register as a Word. + */ + private static Word readRegister(Register register) { + return registerAsWord(register, false, false); + } + + /** + * Writes the value of the passed register. + * + * @param value value the register should be set to + */ + private static void writeRegister(Register register, Word value) { + writeRegisterAsWord(register, value); + } + + @Fold + private static int stackShadowPages() { + return config().useStackBanging ? config().stackShadowPages : 0; + } + + @Fold + private static int deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset() { + return config().deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset; + } + + @Fold + private static int deoptimizationUnrollBlockCallerAdjustmentOffset() { + return config().deoptimizationUnrollBlockCallerAdjustmentOffset; + } + + @Fold + private static int deoptimizationUnrollBlockNumberOfFramesOffset() { + return config().deoptimizationUnrollBlockNumberOfFramesOffset; + } + + @Fold + private static int deoptimizationUnrollBlockTotalFrameSizesOffset() { + return config().deoptimizationUnrollBlockTotalFrameSizesOffset; + } + + @Fold + private static int deoptimizationUnrollBlockFrameSizesOffset() { + return config().deoptimizationUnrollBlockFrameSizesOffset; + } + + @Fold + private static int deoptimizationUnrollBlockFramePcsOffset() { + return config().deoptimizationUnrollBlockFramePcsOffset; + } + + @Fold + private static int deoptimizationUnrollBlockInitialInfoOffset() { + return config().deoptimizationUnrollBlockInitialInfoOffset; + } + + @Fold + private static int deoptimizationUnpackDeopt() { + return config().deoptimizationUnpackDeopt; + } + + @Fold + private static int deoptimizationUnpackUncommonTrap() { + return config().deoptimizationUnpackUncommonTrap; + } + + public static final ForeignCallDescriptor FETCH_UNROLL_INFO = descriptorFor(DeoptimizationStub.class, "fetchUnrollInfo"); + public static final ForeignCallDescriptor UNPACK_FRAMES = descriptorFor(DeoptimizationStub.class, "unpackFrames"); + + @NodeIntrinsic(value = StubForeignCallNode.class, setStampFromReturnType = true) + public static native Word fetchUnrollInfo(@ConstantNodeParameter ForeignCallDescriptor fetchUnrollInfo, Word thread); + + @NodeIntrinsic(value = StubForeignCallNode.class, setStampFromReturnType = true) + public static native int unpackFrames(@ConstantNodeParameter ForeignCallDescriptor unpackFrames, Word thread, int mode); +} diff -r 9dc7efd43c44 -r ed29f7ff71eb src/cpu/x86/vm/sharedRuntime_x86_64.cpp --- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Mon Apr 14 15:36:27 2014 -1000 +++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Mon Apr 14 17:21:49 2014 -1000 @@ -3360,10 +3360,9 @@ #ifdef GRAAL int implicit_exception_uncommon_trap_offset = __ pc() - start; + __ pushptr(Address(r15_thread, in_bytes(JavaThread::graal_implicit_exception_pc_offset()))); - int uncommon_trap_offset = __ pc() - start; - // Save everything in sight. RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words); // fetch_unroll_info needs to call last_java_frame() @@ -3643,7 +3642,6 @@ _deopt_blob = DeoptimizationBlob::create(&buffer, oop_maps, 0, exception_offset, reexecute_offset, frame_size_in_words); _deopt_blob->set_unpack_with_exception_in_tls_offset(exception_in_tls_offset); #ifdef GRAAL - _deopt_blob->set_uncommon_trap_offset(uncommon_trap_offset); _deopt_blob->set_implicit_exception_uncommon_trap_offset(implicit_exception_uncommon_trap_offset); #endif } diff -r 9dc7efd43c44 -r ed29f7ff71eb src/cpu/x86/vm/vmStructs_x86.hpp --- a/src/cpu/x86/vm/vmStructs_x86.hpp Mon Apr 14 15:36:27 2014 -1000 +++ b/src/cpu/x86/vm/vmStructs_x86.hpp Mon Apr 14 17:21:49 2014 -1000 @@ -47,6 +47,8 @@ #define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \ declare_constant(frame::arg_reg_save_area_bytes) \ + declare_constant(frame::interpreter_frame_sender_sp_offset) \ + declare_constant(frame::interpreter_frame_last_sp_offset) \ declare_constant(VM_Version::CPU_CX8) \ declare_constant(VM_Version::CPU_CMOV) \ declare_constant(VM_Version::CPU_FXSR) \ diff -r 9dc7efd43c44 -r ed29f7ff71eb src/share/vm/code/codeBlob.hpp --- a/src/share/vm/code/codeBlob.hpp Mon Apr 14 15:36:27 2014 -1000 +++ b/src/share/vm/code/codeBlob.hpp Mon Apr 14 17:21:49 2014 -1000 @@ -358,8 +358,6 @@ int _unpack_with_exception_in_tls; #ifdef GRAAL - // (thomaswue) Offset when Graal calls uncommon_trap. - int _uncommon_trap_offset; int _implicit_exception_uncommon_trap_offset; #endif @@ -417,12 +415,6 @@ address unpack_with_exception_in_tls() const { return code_begin() + _unpack_with_exception_in_tls; } #ifdef GRAAL - // (thomaswue) Offset when Graal calls uncommon_trap. - void set_uncommon_trap_offset(int offset) { - _uncommon_trap_offset = offset; - assert(contains(code_begin() + _uncommon_trap_offset), "must be PC inside codeblob"); - } - address uncommon_trap() const { return code_begin() + _uncommon_trap_offset; } void set_implicit_exception_uncommon_trap_offset(int offset) { _implicit_exception_uncommon_trap_offset = offset; assert(contains(code_begin() + _implicit_exception_uncommon_trap_offset), "must be PC inside codeblob"); diff -r 9dc7efd43c44 -r ed29f7ff71eb src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Mon Apr 14 15:36:27 2014 -1000 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Mon Apr 14 17:21:49 2014 -1000 @@ -157,7 +157,6 @@ //------------------------------------------------------------------------------------------------ set_address("handleDeoptStub", SharedRuntime::deopt_blob()->unpack()); - set_address("uncommonTrapStub", SharedRuntime::deopt_blob()->uncommon_trap()); set_address("registerFinalizerAddress", SharedRuntime::register_finalizer); set_address("exceptionHandlerForReturnAddressAddress", SharedRuntime::exception_handler_for_return_address); @@ -191,6 +190,10 @@ set_address("writeBarrierPostAddress", GraalRuntime::write_barrier_post); set_address("validateObject", GraalRuntime::validate_object); + set_address("deoptimizationFetchUnrollInfo", Deoptimization::fetch_unroll_info); + set_address("deoptimizationUncommonTrap", Deoptimization::uncommon_trap); + set_address("deoptimizationUnpackFrames", Deoptimization::unpack_frames); + //------------------------------------------------------------------------------------------------ set_int("graalCountersThreadOffset", in_bytes(JavaThread::graal_counters_offset())); diff -r 9dc7efd43c44 -r ed29f7ff71eb src/share/vm/runtime/deoptimization.cpp --- a/src/share/vm/runtime/deoptimization.cpp Mon Apr 14 15:36:27 2014 -1000 +++ b/src/share/vm/runtime/deoptimization.cpp Mon Apr 14 17:21:49 2014 -1000 @@ -357,7 +357,10 @@ unpack_sp = deoptee.unextended_sp(); #ifdef ASSERT - assert(cb->is_deoptimization_stub() || cb->is_uncommon_trap_stub(), "just checking"); + assert(cb->is_deoptimization_stub() || + cb->is_uncommon_trap_stub() || + strcmp("Stub", cb->name()) == 0, + err_msg("unexpected code blob: %s", cb->name())); #endif #else intptr_t* unpack_sp = stub_frame.sender(&dummy_map).unextended_sp();