001/* 002 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.truffle; 024 025import static com.oracle.graal.truffle.TruffleCompilerOptions.*; 026 027import java.lang.ref.*; 028import java.util.*; 029import java.util.stream.*; 030 031import jdk.internal.jvmci.code.*; 032 033import com.oracle.graal.debug.*; 034import com.oracle.truffle.api.*; 035import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; 036import com.oracle.truffle.api.impl.*; 037import com.oracle.truffle.api.nodes.*; 038 039public final class OptimizedAssumption extends AbstractAssumption { 040 041 private static class Entry { 042 WeakReference<InstalledCode> installedCode; 043 long version; 044 Entry next; 045 } 046 047 private Entry first; 048 049 public OptimizedAssumption(String name) { 050 super(name); 051 } 052 053 @Override 054 public void check() throws InvalidAssumptionException { 055 if (!this.isValid()) { 056 CompilerDirectives.transferToInterpreterAndInvalidate(); 057 throw new InvalidAssumptionException(); 058 } 059 } 060 061 @Override 062 public synchronized void invalidate() { 063 if (isValid) { 064 invalidateImpl(); 065 } 066 } 067 068 @TruffleBoundary 069 private void invalidateImpl() { 070 boolean invalidatedInstalledCode = false; 071 Entry e = first; 072 while (e != null) { 073 InstalledCode installedCode = e.installedCode.get(); 074 if (installedCode != null && installedCode.getVersion() == e.version) { 075 invalidateWithReason(installedCode, "assumption invalidated"); 076 invalidatedInstalledCode = true; 077 if (TraceTruffleAssumptions.getValue()) { 078 logInvalidatedInstalledCode(installedCode); 079 } 080 } 081 e = e.next; 082 } 083 first = null; 084 isValid = false; 085 086 if (TraceTruffleAssumptions.getValue()) { 087 if (invalidatedInstalledCode) { 088 logStackTrace(); 089 } 090 } 091 } 092 093 public synchronized void registerInstalledCode(InstalledCode installedCode) { 094 if (isValid) { 095 Entry e = new Entry(); 096 e.installedCode = new WeakReference<>(installedCode); 097 e.version = installedCode.getVersion(); 098 e.next = first; 099 first = e; 100 } else { 101 invalidateWithReason(installedCode, "assumption already invalidated when installing code"); 102 if (TraceTruffleAssumptions.getValue()) { 103 logInvalidatedInstalledCode(installedCode); 104 logStackTrace(); 105 } 106 } 107 } 108 109 private void invalidateWithReason(InstalledCode installedCode, String reason) { 110 if (installedCode instanceof OptimizedCallTarget) { 111 ((OptimizedCallTarget) installedCode).invalidate(this, reason); 112 } else { 113 installedCode.invalidate(); 114 } 115 } 116 117 @Override 118 public boolean isValid() { 119 return isValid; 120 } 121 122 private void logInvalidatedInstalledCode(InstalledCode installedCode) { 123 TTY.out().out().printf("assumption '%s' invalidated installed code '%s'\n", name, installedCode); 124 } 125 126 private static void logStackTrace() { 127 final int skip = 1; 128 final int limit = TraceTruffleStackTraceLimit.getValue(); 129 StackTraceElement[] stackTrace = new Throwable().getStackTrace(); 130 String suffix = stackTrace.length > skip + limit ? "\n ..." : ""; 131 TTY.out().out().println(Arrays.stream(stackTrace).skip(skip).limit(limit).map(StackTraceElement::toString).collect(Collectors.joining("\n ", "", suffix))); 132 } 133}