This commit is contained in:
J. Duke 2017-07-05 17:39:43 +02:00
commit f9b24fa99d
127 changed files with 2303 additions and 1631 deletions

View File

@ -110,3 +110,4 @@ cc58c11af15411042719e9c82707fdbef60a9e0f jdk7-b130
c6f380693342feadccc5fe2c5adf500e861361aa jdk7-b133 c6f380693342feadccc5fe2c5adf500e861361aa jdk7-b133
ddc2fcb3682ffd27f44354db666128827be7e3c3 jdk7-b134 ddc2fcb3682ffd27f44354db666128827be7e3c3 jdk7-b134
783bd02b4ab4596059c74b10a1793d7bd2f1c157 jdk7-b135 783bd02b4ab4596059c74b10a1793d7bd2f1c157 jdk7-b135
2fe76e73adaa5133ac559f0b3c2c0707eca04580 jdk7-b136

View File

@ -158,3 +158,5 @@ a8d643a4db47c7b58e0bcb49c77b5c3610de86a8 hs21-b03
3c76374706ea8a77e15aec8310e831e5734f8775 hs21-b04 3c76374706ea8a77e15aec8310e831e5734f8775 hs21-b04
b898f0fc3cedc972d884d31a751afd75969531cf jdk7-b135 b898f0fc3cedc972d884d31a751afd75969531cf jdk7-b135
b898f0fc3cedc972d884d31a751afd75969531cf hs21-b05 b898f0fc3cedc972d884d31a751afd75969531cf hs21-b05
bd586e392d93b7ed7a1636dcc8da2b6a4203a102 jdk7-b136
bd586e392d93b7ed7a1636dcc8da2b6a4203a102 hs21-b06

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -27,7 +27,7 @@ package sun.jvm.hotspot.jdi;
import com.sun.jdi.*; import com.sun.jdi.*;
import sun.jvm.hotspot.oops.Instance; import sun.jvm.hotspot.oops.Instance;
import sun.jvm.hotspot.oops.Klass; import sun.jvm.hotspot.oops.Klass;
import sun.jvm.hotspot.oops.OopUtilities; import sun.jvm.hotspot.oops.java_lang_Class;
public class ClassObjectReferenceImpl extends ObjectReferenceImpl public class ClassObjectReferenceImpl extends ObjectReferenceImpl
implements ClassObjectReference { implements ClassObjectReference {
@ -39,7 +39,7 @@ public class ClassObjectReferenceImpl extends ObjectReferenceImpl
public ReferenceType reflectedType() { public ReferenceType reflectedType() {
if (reflectedType == null) { if (reflectedType == null) {
Klass k = OopUtilities.classOopToKlass(ref()); Klass k = java_lang_Class.asKlass(ref());
reflectedType = vm.referenceType(k); reflectedType = vm.referenceType(k);
} }
return reflectedType; return reflectedType;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -64,7 +64,7 @@ public class Instance extends Oop {
public void iterateFields(OopVisitor visitor, boolean doVMFields) { public void iterateFields(OopVisitor visitor, boolean doVMFields) {
super.iterateFields(visitor, doVMFields); super.iterateFields(visitor, doVMFields);
((InstanceKlass) getKlass()).iterateNonStaticFields(visitor); ((InstanceKlass) getKlass()).iterateNonStaticFields(visitor, this);
} }
public void printValueOn(PrintStream tty) { public void printValueOn(PrintStream tty) {

View File

@ -241,6 +241,10 @@ public class InstanceKlass extends Klass {
// Byteside of the header // Byteside of the header
private static long headerSize; private static long headerSize;
public long getObjectSize(Oop object) {
return getSizeHelper() * VM.getVM().getAddressSize();
}
public static long getHeaderSize() { return headerSize; } public static long getHeaderSize() { return headerSize; }
// Accessors for declared fields // Accessors for declared fields
@ -459,7 +463,22 @@ public class InstanceKlass extends Klass {
visitor.doCInt(vtableLen, true); visitor.doCInt(vtableLen, true);
visitor.doCInt(itableLen, true); visitor.doCInt(itableLen, true);
} }
}
/*
* Visit the static fields of this InstanceKlass with the obj of
* the visitor set to the oop holding the fields, which is
* currently the java mirror.
*/
public void iterateStaticFields(OopVisitor visitor) {
visitor.setObj(getJavaMirror());
visitor.prologue();
iterateStaticFieldsInternal(visitor);
visitor.epilogue();
}
void iterateStaticFieldsInternal(OopVisitor visitor) {
TypeArray fields = getFields(); TypeArray fields = getFields();
int length = (int) fields.getLength(); int length = (int) fields.getLength();
for (int index = 0; index < length; index += NEXT_OFFSET) { for (int index = 0; index < length; index += NEXT_OFFSET) {
@ -477,9 +496,9 @@ public class InstanceKlass extends Klass {
return getSuper(); return getSuper();
} }
public void iterateNonStaticFields(OopVisitor visitor) { public void iterateNonStaticFields(OopVisitor visitor, Oop obj) {
if (getSuper() != null) { if (getSuper() != null) {
((InstanceKlass) getSuper()).iterateNonStaticFields(visitor); ((InstanceKlass) getSuper()).iterateNonStaticFields(visitor, obj);
} }
TypeArray fields = getFields(); TypeArray fields = getFields();

View File

@ -0,0 +1,67 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.oops;
import java.io.*;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.memory.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.types.*;
import sun.jvm.hotspot.utilities.*;
// An InstanceKlass is the VM level representation of a Java class.
public class InstanceMirrorKlass extends InstanceKlass {
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
initialize(VM.getVM().getTypeDataBase());
}
});
}
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
// Just make sure it's there for now
Type type = db.lookupType("instanceMirrorKlass");
}
InstanceMirrorKlass(OopHandle handle, ObjectHeap heap) {
super(handle, heap);
}
public long getObjectSize(Oop o) {
return java_lang_Class.getOopSize(o) * VM.getVM().getAddressSize();
}
public void iterateNonStaticFields(OopVisitor visitor, Oop obj) {
super.iterateNonStaticFields(visitor, obj);
// Fetch the real klass from the mirror object
Klass klass = java_lang_Class.asKlass(obj);
if (klass instanceof InstanceKlass) {
((InstanceKlass)klass).iterateStaticFields(visitor);
}
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -362,7 +362,16 @@ public class ObjectHeap {
if (klass.equals(compiledICHolderKlassHandle)) return new CompiledICHolder(handle, this); if (klass.equals(compiledICHolderKlassHandle)) return new CompiledICHolder(handle, this);
if (klass.equals(methodDataKlassHandle)) return new MethodData(handle, this); if (klass.equals(methodDataKlassHandle)) return new MethodData(handle, this);
} }
if (klass.equals(instanceKlassKlassHandle)) return new InstanceKlass(handle, this); if (klass.equals(instanceKlassKlassHandle)) {
InstanceKlass ik = new InstanceKlass(handle, this);
if (ik.getName().asString().equals("java/lang/Class")) {
// We would normally do this using the vtable style
// lookup but since it's not used for these currently
// it's simpler to just check for the name.
return new InstanceMirrorKlass(handle, this);
}
return ik;
}
if (klass.equals(objArrayKlassKlassHandle)) return new ObjArrayKlass(handle, this); if (klass.equals(objArrayKlassKlassHandle)) return new ObjArrayKlass(handle, this);
if (klass.equals(typeArrayKlassKlassHandle)) return new TypeArrayKlass(handle, this); if (klass.equals(typeArrayKlassKlassHandle)) return new TypeArrayKlass(handle, this);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -103,12 +103,8 @@ public class Oop {
// Returns the byte size of this object // Returns the byte size of this object
public long getObjectSize() { public long getObjectSize() {
Klass k = getKlass(); Klass k = getKlass();
if (k instanceof InstanceKlass) { // All other types should be overriding getObjectSize directly
return ((InstanceKlass)k).getSizeHelper() return ((InstanceKlass)k).getObjectSize(this);
* VM.getVM().getAddressSize();
}
// If it is not an instance, this method should be replaced.
return getHeaderSize();
} }
// Type test operations // Type test operations

View File

@ -74,9 +74,6 @@ public class OopUtilities implements /* imports */ JVMTIThreadState {
private static int THREAD_STATUS_TERMINATED; private static int THREAD_STATUS_TERMINATED;
*/ */
// java.lang.Class fields
private static OopField hcKlassField;
// java.util.concurrent.locks.AbstractOwnableSynchronizer fields // java.util.concurrent.locks.AbstractOwnableSynchronizer fields
private static OopField absOwnSyncOwnerThreadField; private static OopField absOwnSyncOwnerThreadField;
@ -268,27 +265,6 @@ public class OopUtilities implements /* imports */ JVMTIThreadState {
return null; return null;
} }
// initialize fields for java.lang.Class
private static void initClassFields() {
if (hcKlassField == null) {
// hc_klass is a HotSpot magic field and hence we can't
// find it from InstanceKlass for java.lang.Class.
TypeDataBase db = VM.getVM().getTypeDataBase();
int hcKlassOffset = (int) db.lookupType("java_lang_Class").getCIntegerField("klass_offset").getValue();
if (VM.getVM().isCompressedOopsEnabled()) {
hcKlassField = new NarrowOopField(new NamedFieldIdentifier("hc_klass"), hcKlassOffset, true);
} else {
hcKlassField = new OopField(new NamedFieldIdentifier("hc_klass"), hcKlassOffset, true);
}
}
}
/** get klassOop field at offset hc_klass_offset from a java.lang.Class object */
public static Klass classOopToKlass(Oop aClass) {
initClassFields();
return (Klass) hcKlassField.getValue(aClass);
}
// initialize fields for j.u.c.l AbstractOwnableSynchornizer class // initialize fields for j.u.c.l AbstractOwnableSynchornizer class
private static void initAbsOwnSyncFields() { private static void initAbsOwnSyncFields() {
if (absOwnSyncOwnerThreadField == null) { if (absOwnSyncOwnerThreadField == null) {

View File

@ -0,0 +1,77 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.oops;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.memory.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.types.Type;
import sun.jvm.hotspot.types.TypeDataBase;
import sun.jvm.hotspot.utilities.*;
import sun.jvm.hotspot.jdi.JVMTIThreadState;
/** A utility class encapsulating useful oop operations */
// initialize fields for java.lang.Class
public class java_lang_Class {
// java.lang.Class fields
static OopField klassField;
static IntField oopSizeField;
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
initialize(VM.getVM().getTypeDataBase());
}
});
}
private static synchronized void initialize(TypeDataBase db) {
// klass and oop_size are HotSpot magic fields and hence we can't
// find them from InstanceKlass for java.lang.Class.
Type jlc = db.lookupType("java_lang_Class");
int klassOffset = (int) jlc.getCIntegerField("klass_offset").getValue();
if (VM.getVM().isCompressedOopsEnabled()) {
klassField = new NarrowOopField(new NamedFieldIdentifier("klass"), klassOffset, true);
} else {
klassField = new OopField(new NamedFieldIdentifier("klass"), klassOffset, true);
}
int oopSizeOffset = (int) jlc.getCIntegerField("oop_size_offset").getValue();
oopSizeField = new IntField(new NamedFieldIdentifier("oop_size"), oopSizeOffset, true);
}
/** get klassOop field at offset hc_klass_offset from a java.lang.Class object */
public static Klass asKlass(Oop aClass) {
return (Klass) java_lang_Class.klassField.getValue(aClass);
}
/** get oop_size field at offset oop_size_offset from a java.lang.Class object */
public static long getOopSize(Oop aClass) {
return java_lang_Class.oopSizeField.getValue(aClass);
}
}

View File

@ -839,20 +839,18 @@ public class VM {
} }
private void readSystemProperties() { private void readSystemProperties() {
final InstanceKlass systemKls = getSystemDictionary().getSystemKlass(); final InstanceKlass systemKls = getSystemDictionary().getSystemKlass();
systemKls.iterate(new DefaultOopVisitor() { systemKls.iterateStaticFields(new DefaultOopVisitor() {
ObjectReader objReader = new ObjectReader(); ObjectReader objReader = new ObjectReader();
public void doOop(sun.jvm.hotspot.oops.OopField field, boolean isVMField) { public void doOop(sun.jvm.hotspot.oops.OopField field, boolean isVMField) {
if (field.getID().getName().equals("props")) { if (field.getID().getName().equals("props")) {
try { try {
sysProps = (Properties) objReader.readObject(field.getValue(systemKls.getJavaMirror())); sysProps = (Properties) objReader.readObject(field.getValue(getObj()));
} catch (Exception e) { } catch (Exception e) {
if (Assert.ASSERTS_ENABLED) { e.printStackTrace();
e.printStackTrace(); }
} }
} }
} });
}
}, false);
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -64,16 +64,16 @@ public class FinalizerInfo extends Tool {
*/ */
InstanceKlass ik = InstanceKlass ik =
SystemDictionaryHelper.findInstanceKlass("java.lang.ref.Finalizer"); SystemDictionaryHelper.findInstanceKlass("java.lang.ref.Finalizer");
final OopField queueField[] = new OopField[1]; final Oop[] queueref = new Oop[1];
ik.iterateFields(new DefaultOopVisitor() { ik.iterateStaticFields(new DefaultOopVisitor() {
public void doOop(OopField field, boolean isVMField) { public void doOop(OopField field, boolean isVMField) {
String name = field.getID().getName(); String name = field.getID().getName();
if (name.equals("queue")) { if (name.equals("queue")) {
queueField[0] = field; queueref[0] = field.getValue(getObj());
} }
} }
}, false); });
Oop queue = queueField[0].getValue(ik); Oop queue = queueref[0];
InstanceKlass k = (InstanceKlass) queue.getKlass(); InstanceKlass k = (InstanceKlass) queue.getKlass();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2004, 2007, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -164,7 +164,7 @@ public class HeapGXLWriter extends AbstractHeapGraphWriter {
protected void writeClass(Instance instance) throws IOException { protected void writeClass(Instance instance) throws IOException {
writeObjectHeader(instance); writeObjectHeader(instance);
Klass reflectedType = OopUtilities.classOopToKlass(instance); Klass reflectedType = java_lang_Class.asKlass(instance);
boolean isInstanceKlass = (reflectedType instanceof InstanceKlass); boolean isInstanceKlass = (reflectedType instanceof InstanceKlass);
// reflectedType is null for primitive types (int.class etc). // reflectedType is null for primitive types (int.class etc).
if (reflectedType != null) { if (reflectedType != null) {

View File

@ -455,7 +455,7 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
} }
protected void writeClass(Instance instance) throws IOException { protected void writeClass(Instance instance) throws IOException {
Klass reflectedKlass = OopUtilities.classOopToKlass(instance); Klass reflectedKlass = java_lang_Class.asKlass(instance);
// dump instance record only for primitive type Class objects. // dump instance record only for primitive type Class objects.
// all other Class objects are covered by writeClassDumpRecords. // all other Class objects are covered by writeClassDumpRecords.
if (reflectedKlass == null) { if (reflectedKlass == null) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -117,10 +117,10 @@ public class ReversePtrsAnalysis {
public boolean doObj(Oop obj) { public boolean doObj(Oop obj) {
if (obj instanceof InstanceKlass) { if (obj instanceof InstanceKlass) {
final InstanceKlass ik = (InstanceKlass) obj; final InstanceKlass ik = (InstanceKlass) obj;
ik.iterateFields( ik.iterateStaticFields(
new DefaultOopVisitor() { new DefaultOopVisitor() {
public void doOop(OopField field, boolean isVMField) { public void doOop(OopField field, boolean isVMField) {
Oop next = field.getValue(ik); Oop next = field.getValue(getObj());
LivenessPathElement lp = new LivenessPathElement(null, LivenessPathElement lp = new LivenessPathElement(null,
new NamedFieldIdentifier("Static field \"" + new NamedFieldIdentifier("Static field \"" +
field.getID().getName() + field.getID().getName() +
@ -142,8 +142,7 @@ public class ReversePtrsAnalysis {
System.err.println(); System.err.println();
} }
} }
}, });
false);
} }
return false; return false;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -158,7 +158,7 @@ public class JSJavaFactoryImpl implements JSJavaFactory {
} else if (className.equals(javaLangThread())) { } else if (className.equals(javaLangThread())) {
res = new JSJavaThread(instance, this); res = new JSJavaThread(instance, this);
} else if (className.equals(javaLangClass())) { } else if (className.equals(javaLangClass())) {
Klass reflectedType = OopUtilities.classOopToKlass(instance); Klass reflectedType = java_lang_Class.asKlass(instance);
if (reflectedType != null) { if (reflectedType != null) {
JSJavaKlass jk = newJSJavaKlass(reflectedType); JSJavaKlass jk = newJSJavaKlass(reflectedType);
// we don't support mirrors of VM internal Klasses // we don't support mirrors of VM internal Klasses

View File

@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2011
HS_MAJOR_VER=21 HS_MAJOR_VER=21
HS_MINOR_VER=0 HS_MINOR_VER=0
HS_BUILD_NUMBER=06 HS_BUILD_NUMBER=07
JDK_MAJOR_VER=1 JDK_MAJOR_VER=1
JDK_MINOR_VER=7 JDK_MINOR_VER=7

View File

@ -102,7 +102,7 @@ all: $(EXEC)
$(EXEC) : $(OBJECTS) $(EXEC) : $(OBJECTS)
@echo Making adlc @echo Making adlc
$(QUIETLY) $(LINK_NOPROF.CC) -o $(EXEC) $(OBJECTS) $(QUIETLY) $(HOST.LINK_NOPROF.CC) -o $(EXEC) $(OBJECTS)
# Random dependencies: # Random dependencies:
$(OBJECTS): opcodes.hpp classes.hpp adlc.hpp adlcVMDeps.hpp adlparse.hpp archDesc.hpp arena.hpp dict2.hpp filebuff.hpp forms.hpp formsopt.hpp formssel.hpp $(OBJECTS): opcodes.hpp classes.hpp adlc.hpp adlcVMDeps.hpp adlparse.hpp archDesc.hpp arena.hpp dict2.hpp filebuff.hpp forms.hpp formsopt.hpp formssel.hpp
@ -204,14 +204,14 @@ PROCESS_AD_FILES = awk '{ \
$(OUTDIR)/%.o: %.cpp $(OUTDIR)/%.o: %.cpp
@echo Compiling $< @echo Compiling $<
$(QUIETLY) $(REMOVE_TARGET) $(QUIETLY) $(REMOVE_TARGET)
$(QUIETLY) $(COMPILE.CC) -o $@ $< $(COMPILE_DONE) $(QUIETLY) $(HOST.COMPILE.CC) -o $@ $< $(COMPILE_DONE)
# Some object files are given a prefix, to disambiguate # Some object files are given a prefix, to disambiguate
# them from objects of the same name built for the VM. # them from objects of the same name built for the VM.
$(OUTDIR)/adlc-%.o: %.cpp $(OUTDIR)/adlc-%.o: %.cpp
@echo Compiling $< @echo Compiling $<
$(QUIETLY) $(REMOVE_TARGET) $(QUIETLY) $(REMOVE_TARGET)
$(QUIETLY) $(COMPILE.CC) -o $@ $< $(COMPILE_DONE) $(QUIETLY) $(HOST.COMPILE.CC) -o $@ $< $(COMPILE_DONE)
# ######################################################################### # #########################################################################

View File

@ -30,9 +30,13 @@
ifdef CROSS_COMPILE_ARCH ifdef CROSS_COMPILE_ARCH
CPP = $(ALT_COMPILER_PATH)/g++ CPP = $(ALT_COMPILER_PATH)/g++
CC = $(ALT_COMPILER_PATH)/gcc CC = $(ALT_COMPILER_PATH)/gcc
HOSTCPP = g++
HOSTCC = gcc
else else
CPP = g++ CPP = g++
CC = gcc CC = gcc
HOSTCPP = $(CPP)
HOSTCC = $(CC)
endif endif
AS = $(CC) -c AS = $(CC) -c

View File

@ -55,6 +55,14 @@ LINK_NOPROF.CC = $(CCC) $(LFLAGS) $(AOUT_FLAGS)
LINK_LIB.CC = $(CCC) $(LFLAGS) $(SHARED_FLAG) LINK_LIB.CC = $(CCC) $(LFLAGS) $(SHARED_FLAG)
PREPROCESS.CC = $(CC_COMPILE) -E PREPROCESS.CC = $(CC_COMPILE) -E
# cross compiling the jvm with c2 requires host compilers to build
# adlc tool
HOST.CC_COMPILE = $(HOSTCPP) $(CPPFLAGS) $(CFLAGS)
HOST.COMPILE.CC = $(HOST.CC_COMPILE) -c
HOST.LINK_NOPROF.CC = $(HOSTCPP) $(LFLAGS) $(AOUT_FLAGS)
# Effect of REMOVE_TARGET is to delete out-of-date files during "gnumake -k". # Effect of REMOVE_TARGET is to delete out-of-date files during "gnumake -k".
REMOVE_TARGET = rm -f $@ REMOVE_TARGET = rm -f $@

View File

@ -29,6 +29,9 @@ CPP = CC
CC = cc CC = cc
AS = $(CC) -c AS = $(CC) -c
HOSTCPP = $(CPP)
HOSTCC = $(CC)
ARCHFLAG = $(ARCHFLAG/$(BUILDARCH)) ARCHFLAG = $(ARCHFLAG/$(BUILDARCH))
ARCHFLAG/i486 = -m32 ARCHFLAG/i486 = -m32
ARCHFLAG/amd64 = -m64 ARCHFLAG/amd64 = -m64

View File

@ -93,16 +93,15 @@ if "%MSC_VER%" == "1500" (
echo Will generate VC9 {Visual Studio 2008} echo Will generate VC9 {Visual Studio 2008}
) else ( ) else (
if "%MSC_VER%" == "1600" ( if "%MSC_VER%" == "1600" (
echo Detected Visual Studio 2010, but echo Will generate VC10 {Visual Studio 2010}
echo will generate VC9 {Visual Studio 2008} set ProjectFile=%HotSpotBuildSpace%\jvm.vcxproj
echo Use conversion wizard in VS 2010.
) else ( ) else (
echo Will generate VC7 project {Visual Studio 2003 .NET} echo Will generate VC7 project {Visual Studio 2003 .NET}
) )
) )
) )
) )
echo %ProjectFile% echo %ProjectFile%
echo ************************************************************** echo **************************************************************
REM Test all variables to see whether the directories they REM Test all variables to see whether the directories they

View File

@ -27,10 +27,6 @@
# This is used externally by both batch and IDE builds, so can't # This is used externally by both batch and IDE builds, so can't
# reference any of the HOTSPOTWORKSPACE, HOTSPOTBUILDSPACE, # reference any of the HOTSPOTWORKSPACE, HOTSPOTBUILDSPACE,
# HOTSPOTRELEASEBINDEST, or HOTSPOTDEBUGBINDEST environment variables. # HOTSPOTRELEASEBINDEST, or HOTSPOTDEBUGBINDEST environment variables.
#
# NOTE: unfortunately the ProjectCreatorSources list must be kept
# synchronized between this and the Solaris version
# (make/solaris/makefiles/projectcreator.make).
ProjectCreatorSources=\ ProjectCreatorSources=\
$(WorkSpace)\src\share\tools\ProjectCreator\DirectoryTree.java \ $(WorkSpace)\src\share\tools\ProjectCreator\DirectoryTree.java \
@ -42,6 +38,7 @@ ProjectCreatorSources=\
$(WorkSpace)\src\share\tools\ProjectCreator\WinGammaPlatformVC7.java \ $(WorkSpace)\src\share\tools\ProjectCreator\WinGammaPlatformVC7.java \
$(WorkSpace)\src\share\tools\ProjectCreator\WinGammaPlatformVC8.java \ $(WorkSpace)\src\share\tools\ProjectCreator\WinGammaPlatformVC8.java \
$(WorkSpace)\src\share\tools\ProjectCreator\WinGammaPlatformVC9.java \ $(WorkSpace)\src\share\tools\ProjectCreator\WinGammaPlatformVC9.java \
$(WorkSpace)\src\share\tools\ProjectCreator\WinGammaPlatformVC10.java \
$(WorkSpace)\src\share\tools\ProjectCreator\Util.java \ $(WorkSpace)\src\share\tools\ProjectCreator\Util.java \
$(WorkSpace)\src\share\tools\ProjectCreator\BuildConfig.java \ $(WorkSpace)\src\share\tools\ProjectCreator\BuildConfig.java \
$(WorkSpace)\src\share\tools\ProjectCreator\ArgsParser.java $(WorkSpace)\src\share\tools\ProjectCreator\ArgsParser.java

View File

@ -65,8 +65,8 @@ VcVersion=VC9
!elseif "$(MSC_VER)" == "1600" !elseif "$(MSC_VER)" == "1600"
# for compatibility - we don't yet have a ProjectCreator for VC10 VcVersion=VC10
VcVersion=VC9 ProjectFile=jvm.vcxproj
!else !else

View File

@ -1188,8 +1188,8 @@ void CppInterpreterGenerator::generate_compute_interpreter_state(const Register
__ st_ptr(O2, XXX_STATE(_stack)); // PREPUSH __ st_ptr(O2, XXX_STATE(_stack)); // PREPUSH
__ lduh(max_stack, O3); // Full size expression stack __ lduh(max_stack, O3); // Full size expression stack
guarantee(!EnableMethodHandles, "no support yet for java.lang.invoke.MethodHandle"); //6815692 guarantee(!EnableInvokeDynamic, "no support yet for java.lang.invoke.MethodHandle"); //6815692
//6815692//if (EnableMethodHandles) //6815692//if (EnableInvokeDynamic)
//6815692// __ inc(O3, methodOopDesc::extra_stack_entries()); //6815692// __ inc(O3, methodOopDesc::extra_stack_entries());
__ sll(O3, LogBytesPerWord, O3); __ sll(O3, LogBytesPerWord, O3);
__ sub(O2, O3, O3); __ sub(O2, O3, O3);

View File

@ -743,12 +743,12 @@ void InterpreterMacroAssembler::get_cache_index_at_bcp(Register cache, Register
if (index_size == sizeof(u2)) { if (index_size == sizeof(u2)) {
get_2_byte_integer_at_bcp(bcp_offset, cache, tmp, Unsigned); get_2_byte_integer_at_bcp(bcp_offset, cache, tmp, Unsigned);
} else if (index_size == sizeof(u4)) { } else if (index_size == sizeof(u4)) {
assert(EnableInvokeDynamic, "giant index used only for EnableInvokeDynamic"); assert(EnableInvokeDynamic, "giant index used only for JSR 292");
get_4_byte_integer_at_bcp(bcp_offset, cache, tmp); get_4_byte_integer_at_bcp(bcp_offset, cache, tmp);
assert(constantPoolCacheOopDesc::decode_secondary_index(~123) == 123, "else change next line"); assert(constantPoolCacheOopDesc::decode_secondary_index(~123) == 123, "else change next line");
xor3(tmp, -1, tmp); // convert to plain index xor3(tmp, -1, tmp); // convert to plain index
} else if (index_size == sizeof(u1)) { } else if (index_size == sizeof(u1)) {
assert(EnableMethodHandles, "tiny index used only for EnableMethodHandles"); assert(EnableInvokeDynamic, "tiny index used only for JSR 292");
ldub(Lbcp, bcp_offset, tmp); ldub(Lbcp, bcp_offset, tmp);
} else { } else {
ShouldNotReachHere(); ShouldNotReachHere();

View File

@ -262,7 +262,7 @@ address InterpreterGenerator::generate_abstract_entry(void) {
// Method handle invoker // Method handle invoker
// Dispatch a method of the form java.lang.invoke.MethodHandles::invoke(...) // Dispatch a method of the form java.lang.invoke.MethodHandles::invoke(...)
address InterpreterGenerator::generate_method_handle_entry(void) { address InterpreterGenerator::generate_method_handle_entry(void) {
if (!EnableMethodHandles) { if (!EnableInvokeDynamic) {
return generate_abstract_entry(); return generate_abstract_entry();
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -1769,6 +1769,7 @@ static void create_inner_frame(MacroAssembler* masm, bool* already_created) {
// returns. // returns.
nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler* masm, nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
methodHandle method, methodHandle method,
int compile_id,
int total_in_args, int total_in_args,
int comp_args_on_stack, // in VMRegStackSlots int comp_args_on_stack, // in VMRegStackSlots
BasicType *in_sig_bt, BasicType *in_sig_bt,
@ -2462,6 +2463,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
__ flush(); __ flush();
nmethod *nm = nmethod::new_native_nmethod(method, nmethod *nm = nmethod::new_native_nmethod(method,
compile_id,
masm->code(), masm->code(),
vep_offset, vep_offset,
frame_complete, frame_complete,

View File

@ -1843,6 +1843,10 @@ const int Matcher::init_array_short_size = 8 * BytesPerLong;
// registers? True for Intel but false for most RISCs // registers? True for Intel but false for most RISCs
const bool Matcher::clone_shift_expressions = false; const bool Matcher::clone_shift_expressions = false;
// Do we need to mask the count passed to shift instructions or does
// the cpu only look at the lower 5/6 bits anyway?
const bool Matcher::need_masked_shift_count = false;
bool Matcher::narrow_oop_use_complex_address() { bool Matcher::narrow_oop_use_complex_address() {
NOT_LP64(ShouldNotCallThis()); NOT_LP64(ShouldNotCallThis());
assert(UseCompressedOops, "only for compressed oops code"); assert(UseCompressedOops, "only for compressed oops code");

View File

@ -334,8 +334,8 @@ void TemplateTable::ldc(bool wide) {
void TemplateTable::fast_aldc(bool wide) { void TemplateTable::fast_aldc(bool wide) {
transition(vtos, atos); transition(vtos, atos);
if (!EnableMethodHandles) { if (!EnableInvokeDynamic) {
// We should not encounter this bytecode if !EnableMethodHandles. // We should not encounter this bytecode if !EnableInvokeDynamic.
// The verifier will stop it. However, if we get past the verifier, // The verifier will stop it. However, if we get past the verifier,
// this will stop the thread in a reasonable way, without crashing the JVM. // this will stop the thread in a reasonable way, without crashing the JVM.
__ call_VM(noreg, CAST_FROM_FN_PTR(address, __ call_VM(noreg, CAST_FROM_FN_PTR(address,

View File

@ -3510,7 +3510,6 @@ bool Assembler::reachable(AddressLiteral adr) {
// anywhere in the codeCache then we are always reachable. // anywhere in the codeCache then we are always reachable.
// This would have to change if we ever save/restore shared code // This would have to change if we ever save/restore shared code
// to be more pessimistic. // to be more pessimistic.
disp = (int64_t)adr._target - ((int64_t)CodeCache::low_bound() + sizeof(int)); disp = (int64_t)adr._target - ((int64_t)CodeCache::low_bound() + sizeof(int));
if (!is_simm32(disp)) return false; if (!is_simm32(disp)) return false;
disp = (int64_t)adr._target - ((int64_t)CodeCache::high_bound() + sizeof(int)); disp = (int64_t)adr._target - ((int64_t)CodeCache::high_bound() + sizeof(int));
@ -3534,6 +3533,14 @@ bool Assembler::reachable(AddressLiteral adr) {
return is_simm32(disp); return is_simm32(disp);
} }
// Check if the polling page is not reachable from the code cache using rip-relative
// addressing.
bool Assembler::is_polling_page_far() {
intptr_t addr = (intptr_t)os::get_polling_page();
return !is_simm32(addr - (intptr_t)CodeCache::low_bound()) ||
!is_simm32(addr - (intptr_t)CodeCache::high_bound());
}
void Assembler::emit_data64(jlong data, void Assembler::emit_data64(jlong data,
relocInfo::relocType rtype, relocInfo::relocType rtype,
int format) { int format) {
@ -6886,6 +6893,11 @@ void MacroAssembler::sign_extend_short(Register reg) {
} }
} }
void MacroAssembler::testl(Register dst, AddressLiteral src) {
assert(reachable(src), "Address should be reachable");
testl(dst, as_Address(src));
}
////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////
#ifndef SERIALGC #ifndef SERIALGC
@ -7121,17 +7133,6 @@ void MacroAssembler::subptr(Register dst, Register src) {
LP64_ONLY(subq(dst, src)) NOT_LP64(subl(dst, src)); LP64_ONLY(subq(dst, src)) NOT_LP64(subl(dst, src));
} }
void MacroAssembler::test32(Register src1, AddressLiteral src2) {
// src2 must be rval
if (reachable(src2)) {
testl(src1, as_Address(src2));
} else {
lea(rscratch1, src2);
testl(src1, Address(rscratch1, 0));
}
}
// C++ bool manipulation // C++ bool manipulation
void MacroAssembler::testbool(Register dst) { void MacroAssembler::testbool(Register dst) {
if(sizeof(bool) == 1) if(sizeof(bool) == 1)
@ -7768,6 +7769,28 @@ void MacroAssembler::xorps(XMMRegister dst, AddressLiteral src) {
} }
} }
void MacroAssembler::cmov32(Condition cc, Register dst, Address src) {
if (VM_Version::supports_cmov()) {
cmovl(cc, dst, src);
} else {
Label L;
jccb(negate_condition(cc), L);
movl(dst, src);
bind(L);
}
}
void MacroAssembler::cmov32(Condition cc, Register dst, Register src) {
if (VM_Version::supports_cmov()) {
cmovl(cc, dst, src);
} else {
Label L;
jccb(negate_condition(cc), L);
movl(dst, src);
bind(L);
}
}
void MacroAssembler::verify_oop(Register reg, const char* s) { void MacroAssembler::verify_oop(Register reg, const char* s) {
if (!VerifyOops) return; if (!VerifyOops) return;
@ -9018,14 +9041,7 @@ void MacroAssembler::string_compare(Register str1, Register str2,
movl(result, cnt1); movl(result, cnt1);
subl(cnt1, cnt2); subl(cnt1, cnt2);
push(cnt1); push(cnt1);
if (VM_Version::supports_cmov()) { cmov32(Assembler::lessEqual, cnt2, result);
cmovl(Assembler::lessEqual, cnt2, result);
} else {
Label GT_LABEL;
jccb(Assembler::greater, GT_LABEL);
movl(cnt2, result);
bind(GT_LABEL);
}
// Is the minimum length zero? // Is the minimum length zero?
testl(cnt2, cnt2); testl(cnt2, cnt2);

View File

@ -580,7 +580,6 @@ private:
void emit_data64(jlong data, relocInfo::relocType rtype, int format = 0); void emit_data64(jlong data, relocInfo::relocType rtype, int format = 0);
void emit_data64(jlong data, RelocationHolder const& rspec, int format = 0); void emit_data64(jlong data, RelocationHolder const& rspec, int format = 0);
bool reachable(AddressLiteral adr) NOT_LP64({ return true;}); bool reachable(AddressLiteral adr) NOT_LP64({ return true;});
// These are all easily abused and hence protected // These are all easily abused and hence protected
@ -683,6 +682,8 @@ private:
static bool is_simm32(int32_t x) { return true; } static bool is_simm32(int32_t x) { return true; }
#endif // _LP64 #endif // _LP64
static bool is_polling_page_far() NOT_LP64({ return false;});
// Generic instructions // Generic instructions
// Does 32bit or 64bit as needed for the platform. In some sense these // Does 32bit or 64bit as needed for the platform. In some sense these
// belong in macro assembler but there is no need for both varieties to exist // belong in macro assembler but there is no need for both varieties to exist
@ -2094,7 +2095,10 @@ class MacroAssembler: public Assembler {
void leal32(Register dst, Address src) { leal(dst, src); } void leal32(Register dst, Address src) { leal(dst, src); }
void test32(Register src1, AddressLiteral src2); // Import other testl() methods from the parent class or else
// they will be hidden by the following overriding declaration.
using Assembler::testl;
void testl(Register dst, AddressLiteral src);
void orptr(Register dst, Address src) { LP64_ONLY(orq(dst, src)) NOT_LP64(orl(dst, src)); } void orptr(Register dst, Address src) { LP64_ONLY(orq(dst, src)) NOT_LP64(orl(dst, src)); }
void orptr(Register dst, Register src) { LP64_ONLY(orq(dst, src)) NOT_LP64(orl(dst, src)); } void orptr(Register dst, Register src) { LP64_ONLY(orq(dst, src)) NOT_LP64(orl(dst, src)); }
@ -2240,10 +2244,13 @@ public:
// Data // Data
void cmov(Condition cc, Register dst, Register src) { LP64_ONLY(cmovq(cc, dst, src)) NOT_LP64(cmovl(cc, dst, src)); } void cmov32( Condition cc, Register dst, Address src);
void cmov32( Condition cc, Register dst, Register src);
void cmovptr(Condition cc, Register dst, Address src) { LP64_ONLY(cmovq(cc, dst, src)) NOT_LP64(cmovl(cc, dst, src)); } void cmov( Condition cc, Register dst, Register src) { cmovptr(cc, dst, src); }
void cmovptr(Condition cc, Register dst, Register src) { LP64_ONLY(cmovq(cc, dst, src)) NOT_LP64(cmovl(cc, dst, src)); }
void cmovptr(Condition cc, Register dst, Address src) { LP64_ONLY(cmovq(cc, dst, src)) NOT_LP64(cmov32(cc, dst, src)); }
void cmovptr(Condition cc, Register dst, Register src) { LP64_ONLY(cmovq(cc, dst, src)) NOT_LP64(cmov32(cc, dst, src)); }
void movoop(Register dst, jobject obj); void movoop(Register dst, jobject obj);
void movoop(Address dst, jobject obj); void movoop(Address dst, jobject obj);

View File

@ -23,6 +23,7 @@
*/ */
#include "precompiled.hpp" #include "precompiled.hpp"
#include "asm/assembler.hpp"
#include "c1/c1_Compilation.hpp" #include "c1/c1_Compilation.hpp"
#include "c1/c1_LIRAssembler.hpp" #include "c1/c1_LIRAssembler.hpp"
#include "c1/c1_MacroAssembler.hpp" #include "c1/c1_MacroAssembler.hpp"
@ -569,24 +570,13 @@ void LIR_Assembler::emit_string_compare(LIR_Opr arg0, LIR_Opr arg1, LIR_Opr dst,
__ lea (rdi, Address(rdi, rcx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR))); __ lea (rdi, Address(rdi, rcx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
// compute minimum length (in rax) and difference of lengths (on top of stack) // compute minimum length (in rax) and difference of lengths (on top of stack)
if (VM_Version::supports_cmov()) { __ movl (rbx, Address(rbx, java_lang_String::count_offset_in_bytes()));
__ movl (rbx, Address(rbx, java_lang_String::count_offset_in_bytes())); __ movl (rax, Address(rax, java_lang_String::count_offset_in_bytes()));
__ movl (rax, Address(rax, java_lang_String::count_offset_in_bytes())); __ mov (rcx, rbx);
__ mov (rcx, rbx); __ subptr(rbx, rax); // subtract lengths
__ subptr (rbx, rax); // subtract lengths __ push (rbx); // result
__ push (rbx); // result __ cmov (Assembler::lessEqual, rax, rcx);
__ cmov (Assembler::lessEqual, rax, rcx);
} else {
Label L;
__ movl (rbx, Address(rbx, java_lang_String::count_offset_in_bytes()));
__ movl (rcx, Address(rax, java_lang_String::count_offset_in_bytes()));
__ mov (rax, rbx);
__ subptr (rbx, rcx);
__ push (rbx);
__ jcc (Assembler::lessEqual, L);
__ mov (rax, rcx);
__ bind (L);
}
// is minimum length 0? // is minimum length 0?
Label noLoop, haveResult; Label noLoop, haveResult;
__ testptr (rax, rax); __ testptr (rax, rax);
@ -648,12 +638,13 @@ void LIR_Assembler::return_op(LIR_Opr result) {
AddressLiteral polling_page(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()), AddressLiteral polling_page(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()),
relocInfo::poll_return_type); relocInfo::poll_return_type);
// NOTE: the requires that the polling page be reachable else the reloc if (Assembler::is_polling_page_far()) {
// goes to the movq that loads the address and not the faulting instruction __ lea(rscratch1, polling_page);
// which breaks the signal handler code __ relocate(relocInfo::poll_return_type);
__ testl(rax, Address(rscratch1, 0));
__ test32(rax, polling_page); } else {
__ testl(rax, polling_page);
}
__ ret(0); __ ret(0);
} }
@ -661,20 +652,17 @@ void LIR_Assembler::return_op(LIR_Opr result) {
int LIR_Assembler::safepoint_poll(LIR_Opr tmp, CodeEmitInfo* info) { int LIR_Assembler::safepoint_poll(LIR_Opr tmp, CodeEmitInfo* info) {
AddressLiteral polling_page(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()), AddressLiteral polling_page(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()),
relocInfo::poll_type); relocInfo::poll_type);
guarantee(info != NULL, "Shouldn't be NULL");
if (info != NULL) {
add_debug_info_for_branch(info);
} else {
ShouldNotReachHere();
}
int offset = __ offset(); int offset = __ offset();
if (Assembler::is_polling_page_far()) {
// NOTE: the requires that the polling page be reachable else the reloc __ lea(rscratch1, polling_page);
// goes to the movq that loads the address and not the faulting instruction offset = __ offset();
// which breaks the signal handler code add_debug_info_for_branch(info);
__ testl(rax, Address(rscratch1, 0));
__ test32(rax, polling_page); } else {
add_debug_info_for_branch(info);
__ testl(rax, polling_page);
}
return offset; return offset;
} }

View File

@ -23,6 +23,7 @@
*/ */
#include "precompiled.hpp" #include "precompiled.hpp"
#include "asm/assembler.hpp"
#include "c1/c1_Defs.hpp" #include "c1/c1_Defs.hpp"
#include "c1/c1_MacroAssembler.hpp" #include "c1/c1_MacroAssembler.hpp"
#include "c1/c1_Runtime1.hpp" #include "c1/c1_Runtime1.hpp"

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -125,7 +125,7 @@
// Entry frames // Entry frames
#ifdef AMD64 #ifdef AMD64
#ifdef _WIN64 #ifdef _WIN64
entry_frame_after_call_words = 8, entry_frame_after_call_words = 28,
entry_frame_call_wrapper_offset = 2, entry_frame_call_wrapper_offset = 2,
arg_reg_save_area_bytes = 32, // Register argument save area arg_reg_save_area_bytes = 32, // Register argument save area

View File

@ -215,7 +215,7 @@ void InterpreterMacroAssembler::get_cache_index_at_bcp(Register reg, int bcp_off
if (index_size == sizeof(u2)) { if (index_size == sizeof(u2)) {
load_unsigned_short(reg, Address(rsi, bcp_offset)); load_unsigned_short(reg, Address(rsi, bcp_offset));
} else if (index_size == sizeof(u4)) { } else if (index_size == sizeof(u4)) {
assert(EnableInvokeDynamic, "giant index used only for EnableInvokeDynamic"); assert(EnableInvokeDynamic, "giant index used only for JSR 292");
movl(reg, Address(rsi, bcp_offset)); movl(reg, Address(rsi, bcp_offset));
// Check if the secondary index definition is still ~x, otherwise // Check if the secondary index definition is still ~x, otherwise
// we have to change the following assembler code to calculate the // we have to change the following assembler code to calculate the
@ -223,7 +223,7 @@ void InterpreterMacroAssembler::get_cache_index_at_bcp(Register reg, int bcp_off
assert(constantPoolCacheOopDesc::decode_secondary_index(~123) == 123, "else change next line"); assert(constantPoolCacheOopDesc::decode_secondary_index(~123) == 123, "else change next line");
notl(reg); // convert to plain index notl(reg); // convert to plain index
} else if (index_size == sizeof(u1)) { } else if (index_size == sizeof(u1)) {
assert(EnableMethodHandles, "tiny index used only for EnableMethodHandles"); assert(EnableInvokeDynamic, "tiny index used only for JSR 292");
load_unsigned_byte(reg, Address(rsi, bcp_offset)); load_unsigned_byte(reg, Address(rsi, bcp_offset));
} else { } else {
ShouldNotReachHere(); ShouldNotReachHere();

View File

@ -213,7 +213,7 @@ void InterpreterMacroAssembler::get_cache_index_at_bcp(Register index,
if (index_size == sizeof(u2)) { if (index_size == sizeof(u2)) {
load_unsigned_short(index, Address(r13, bcp_offset)); load_unsigned_short(index, Address(r13, bcp_offset));
} else if (index_size == sizeof(u4)) { } else if (index_size == sizeof(u4)) {
assert(EnableInvokeDynamic, "giant index used only for EnableInvokeDynamic"); assert(EnableInvokeDynamic, "giant index used only for JSR 292");
movl(index, Address(r13, bcp_offset)); movl(index, Address(r13, bcp_offset));
// Check if the secondary index definition is still ~x, otherwise // Check if the secondary index definition is still ~x, otherwise
// we have to change the following assembler code to calculate the // we have to change the following assembler code to calculate the
@ -221,7 +221,7 @@ void InterpreterMacroAssembler::get_cache_index_at_bcp(Register index,
assert(constantPoolCacheOopDesc::decode_secondary_index(~123) == 123, "else change next line"); assert(constantPoolCacheOopDesc::decode_secondary_index(~123) == 123, "else change next line");
notl(index); // convert to plain index notl(index); // convert to plain index
} else if (index_size == sizeof(u1)) { } else if (index_size == sizeof(u1)) {
assert(EnableMethodHandles, "tiny index used only for EnableMethodHandles"); assert(EnableInvokeDynamic, "tiny index used only for JSR 292");
load_unsigned_byte(index, Address(r13, bcp_offset)); load_unsigned_byte(index, Address(r13, bcp_offset));
} else { } else {
ShouldNotReachHere(); ShouldNotReachHere();

View File

@ -233,7 +233,7 @@ address InterpreterGenerator::generate_abstract_entry(void) {
// Method handle invoker // Method handle invoker
// Dispatch a method of the form java.lang.invoke.MethodHandles::invoke(...) // Dispatch a method of the form java.lang.invoke.MethodHandles::invoke(...)
address InterpreterGenerator::generate_method_handle_entry(void) { address InterpreterGenerator::generate_method_handle_entry(void) {
if (!EnableMethodHandles) { if (!EnableInvokeDynamic) {
return generate_abstract_entry(); return generate_abstract_entry();
} }

View File

@ -320,7 +320,7 @@ address InterpreterGenerator::generate_abstract_entry(void) {
// Method handle invoker // Method handle invoker
// Dispatch a method of the form java.lang.invoke.MethodHandles::invoke(...) // Dispatch a method of the form java.lang.invoke.MethodHandles::invoke(...)
address InterpreterGenerator::generate_method_handle_entry(void) { address InterpreterGenerator::generate_method_handle_entry(void) {
if (!EnableMethodHandles) { if (!EnableInvokeDynamic) {
return generate_abstract_entry(); return generate_abstract_entry();
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -519,7 +519,11 @@ class NativeReturnX: public NativeInstruction {
class NativeTstRegMem: public NativeInstruction { class NativeTstRegMem: public NativeInstruction {
public: public:
enum Intel_specific_constants { enum Intel_specific_constants {
instruction_code_memXregl = 0x85 instruction_rex_prefix_mask = 0xF0,
instruction_rex_prefix = Assembler::REX,
instruction_code_memXregl = 0x85,
modrm_mask = 0x38, // select reg from the ModRM byte
modrm_reg = 0x00 // rax
}; };
}; };
@ -533,12 +537,25 @@ inline bool NativeInstruction::is_cond_jump() { return (int_at(0) & 0xF0FF) =
(ubyte_at(0) & 0xF0) == 0x70; /* short jump */ } (ubyte_at(0) & 0xF0) == 0x70; /* short jump */ }
inline bool NativeInstruction::is_safepoint_poll() { inline bool NativeInstruction::is_safepoint_poll() {
#ifdef AMD64 #ifdef AMD64
if ( ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl && if (Assembler::is_polling_page_far()) {
ubyte_at(1) == 0x05 ) { // 00 rax 101 // two cases, depending on the choice of the base register in the address.
address fault = addr_at(6) + int_at(2); if (((ubyte_at(0) & NativeTstRegMem::instruction_rex_prefix_mask) == NativeTstRegMem::instruction_rex_prefix &&
return os::is_poll_address(fault); ubyte_at(1) == NativeTstRegMem::instruction_code_memXregl &&
(ubyte_at(2) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg) ||
ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl &&
(ubyte_at(1) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg) {
return true;
} else {
return false;
}
} else { } else {
return false; if (ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl &&
ubyte_at(1) == 0x05) { // 00 rax 101
address fault = addr_at(6) + int_at(2);
return os::is_poll_address(fault);
} else {
return false;
}
} }
#else #else
return ( ubyte_at(0) == NativeMovRegMem::instruction_code_mem2reg || return ( ubyte_at(0) == NativeMovRegMem::instruction_code_mem2reg ||

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -198,41 +198,44 @@ void Relocation::pd_swap_out_breakpoint(address x, short* instrs, int instrlen)
void poll_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) { void poll_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {
#ifdef _LP64 #ifdef _LP64
typedef Assembler::WhichOperand WhichOperand; if (!Assembler::is_polling_page_far()) {
WhichOperand which = (WhichOperand) format(); typedef Assembler::WhichOperand WhichOperand;
// This format is imm but it is really disp32 WhichOperand which = (WhichOperand) format();
which = Assembler::disp32_operand; // This format is imm but it is really disp32
address orig_addr = old_addr_for(addr(), src, dest); which = Assembler::disp32_operand;
NativeInstruction* oni = nativeInstruction_at(orig_addr); address orig_addr = old_addr_for(addr(), src, dest);
int32_t* orig_disp = (int32_t*) Assembler::locate_operand(orig_addr, which); NativeInstruction* oni = nativeInstruction_at(orig_addr);
// This poll_addr is incorrect by the size of the instruction it is irrelevant int32_t* orig_disp = (int32_t*) Assembler::locate_operand(orig_addr, which);
intptr_t poll_addr = (intptr_t)oni + *orig_disp; // This poll_addr is incorrect by the size of the instruction it is irrelevant
intptr_t poll_addr = (intptr_t)oni + *orig_disp;
NativeInstruction* ni = nativeInstruction_at(addr()); NativeInstruction* ni = nativeInstruction_at(addr());
intptr_t new_disp = poll_addr - (intptr_t) ni; intptr_t new_disp = poll_addr - (intptr_t) ni;
int32_t* disp = (int32_t*) Assembler::locate_operand(addr(), which);
* disp = (int32_t)new_disp;
int32_t* disp = (int32_t*) Assembler::locate_operand(addr(), which);
* disp = (int32_t)new_disp;
}
#endif // _LP64 #endif // _LP64
} }
void poll_return_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) { void poll_return_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {
#ifdef _LP64 #ifdef _LP64
typedef Assembler::WhichOperand WhichOperand; if (!Assembler::is_polling_page_far()) {
WhichOperand which = (WhichOperand) format(); typedef Assembler::WhichOperand WhichOperand;
// This format is imm but it is really disp32 WhichOperand which = (WhichOperand) format();
which = Assembler::disp32_operand; // This format is imm but it is really disp32
address orig_addr = old_addr_for(addr(), src, dest); which = Assembler::disp32_operand;
NativeInstruction* oni = nativeInstruction_at(orig_addr); address orig_addr = old_addr_for(addr(), src, dest);
int32_t* orig_disp = (int32_t*) Assembler::locate_operand(orig_addr, which); NativeInstruction* oni = nativeInstruction_at(orig_addr);
// This poll_addr is incorrect by the size of the instruction it is irrelevant int32_t* orig_disp = (int32_t*) Assembler::locate_operand(orig_addr, which);
intptr_t poll_addr = (intptr_t)oni + *orig_disp; // This poll_addr is incorrect by the size of the instruction it is irrelevant
intptr_t poll_addr = (intptr_t)oni + *orig_disp;
NativeInstruction* ni = nativeInstruction_at(addr()); NativeInstruction* ni = nativeInstruction_at(addr());
intptr_t new_disp = poll_addr - (intptr_t) ni; intptr_t new_disp = poll_addr - (intptr_t) ni;
int32_t* disp = (int32_t*) Assembler::locate_operand(addr(), which); int32_t* disp = (int32_t*) Assembler::locate_operand(addr(), which);
* disp = (int32_t)new_disp; * disp = (int32_t)new_disp;
}
#endif // _LP64 #endif // _LP64
} }

View File

@ -1111,6 +1111,7 @@ void SharedRuntime::restore_native_result(MacroAssembler *masm, BasicType ret_ty
// returns. // returns.
nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
methodHandle method, methodHandle method,
int compile_id,
int total_in_args, int total_in_args,
int comp_args_on_stack, int comp_args_on_stack,
BasicType *in_sig_bt, BasicType *in_sig_bt,
@ -1854,6 +1855,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
__ flush(); __ flush();
nmethod *nm = nmethod::new_native_nmethod(method, nmethod *nm = nmethod::new_native_nmethod(method,
compile_id,
masm->code(), masm->code(),
vep_offset, vep_offset,
frame_complete, frame_complete,

View File

@ -1174,6 +1174,7 @@ static void restore_args(MacroAssembler *masm, int arg_count, int first_arg, VMR
// returns. // returns.
nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
methodHandle method, methodHandle method,
int compile_id,
int total_in_args, int total_in_args,
int comp_args_on_stack, int comp_args_on_stack,
BasicType *in_sig_bt, BasicType *in_sig_bt,
@ -1881,6 +1882,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
__ flush(); __ flush();
nmethod *nm = nmethod::new_native_nmethod(method, nmethod *nm = nmethod::new_native_nmethod(method,
compile_id,
masm->code(), masm->code(),
vep_offset, vep_offset,
frame_complete, frame_complete,

View File

@ -144,8 +144,11 @@ class StubGenerator: public StubCodeGenerator {
// [ return_from_Java ] <--- rsp // [ return_from_Java ] <--- rsp
// [ argument word n ] // [ argument word n ]
// ... // ...
// -8 [ argument word 1 ] // -28 [ argument word 1 ]
// -7 [ saved r15 ] <--- rsp_after_call // -27 [ saved xmm15 ] <--- rsp_after_call
// [ saved xmm7-xmm14 ]
// -9 [ saved xmm6 ] (each xmm register takes 2 slots)
// -7 [ saved r15 ]
// -6 [ saved r14 ] // -6 [ saved r14 ]
// -5 [ saved r13 ] // -5 [ saved r13 ]
// -4 [ saved r12 ] // -4 [ saved r12 ]
@ -169,8 +172,11 @@ class StubGenerator: public StubCodeGenerator {
// Call stub stack layout word offsets from rbp // Call stub stack layout word offsets from rbp
enum call_stub_layout { enum call_stub_layout {
#ifdef _WIN64 #ifdef _WIN64
rsp_after_call_off = -7, xmm_save_first = 6, // save from xmm6
r15_off = rsp_after_call_off, xmm_save_last = 15, // to xmm15
xmm_save_base = -9,
rsp_after_call_off = xmm_save_base - 2 * (xmm_save_last - xmm_save_first), // -27
r15_off = -7,
r14_off = -6, r14_off = -6,
r13_off = -5, r13_off = -5,
r12_off = -4, r12_off = -4,
@ -208,6 +214,13 @@ class StubGenerator: public StubCodeGenerator {
#endif #endif
}; };
#ifdef _WIN64
Address xmm_save(int reg) {
assert(reg >= xmm_save_first && reg <= xmm_save_last, "XMM register number out of range");
return Address(rbp, (xmm_save_base - (reg - xmm_save_first) * 2) * wordSize);
}
#endif
address generate_call_stub(address& return_address) { address generate_call_stub(address& return_address) {
assert((int)frame::entry_frame_after_call_words == -(int)rsp_after_call_off + 1 && assert((int)frame::entry_frame_after_call_words == -(int)rsp_after_call_off + 1 &&
(int)frame::entry_frame_call_wrapper_offset == (int)call_wrapper_off, (int)frame::entry_frame_call_wrapper_offset == (int)call_wrapper_off,
@ -256,8 +269,11 @@ class StubGenerator: public StubCodeGenerator {
__ movptr(r13_save, r13); __ movptr(r13_save, r13);
__ movptr(r14_save, r14); __ movptr(r14_save, r14);
__ movptr(r15_save, r15); __ movptr(r15_save, r15);
#ifdef _WIN64 #ifdef _WIN64
for (int i = 6; i <= 15; i++) {
__ movdqu(xmm_save(i), as_XMMRegister(i));
}
const Address rdi_save(rbp, rdi_off * wordSize); const Address rdi_save(rbp, rdi_off * wordSize);
const Address rsi_save(rbp, rsi_off * wordSize); const Address rsi_save(rbp, rsi_off * wordSize);
@ -360,6 +376,11 @@ class StubGenerator: public StubCodeGenerator {
#endif #endif
// restore regs belonging to calling function // restore regs belonging to calling function
#ifdef _WIN64
for (int i = 15; i >= 6; i--) {
__ movdqu(as_XMMRegister(i), xmm_save(i));
}
#endif
__ movptr(r15, r15_save); __ movptr(r15, r15_save);
__ movptr(r14, r14_save); __ movptr(r14, r14_save);
__ movptr(r13, r13_save); __ movptr(r13, r13_save);
@ -2428,8 +2449,8 @@ class StubGenerator: public StubCodeGenerator {
// //
address generate_generic_copy(const char *name, address generate_generic_copy(const char *name,
address byte_copy_entry, address short_copy_entry, address byte_copy_entry, address short_copy_entry,
address int_copy_entry, address long_copy_entry, address int_copy_entry, address oop_copy_entry,
address oop_copy_entry, address checkcast_copy_entry) { address long_copy_entry, address checkcast_copy_entry) {
Label L_failed, L_failed_0, L_objArray; Label L_failed, L_failed_0, L_objArray;
Label L_copy_bytes, L_copy_shorts, L_copy_ints, L_copy_longs; Label L_copy_bytes, L_copy_shorts, L_copy_ints, L_copy_longs;

View File

@ -1527,7 +1527,7 @@ int AbstractInterpreter::layout_activation(methodOop method,
if (interpreter_frame != NULL) { if (interpreter_frame != NULL) {
#ifdef ASSERT #ifdef ASSERT
if (!EnableMethodHandles) if (!EnableInvokeDynamic)
// @@@ FIXME: Should we correct interpreter_frame_sender_sp in the calling sequences? // @@@ FIXME: Should we correct interpreter_frame_sender_sp in the calling sequences?
// Probably, since deoptimization doesn't work yet. // Probably, since deoptimization doesn't work yet.
assert(caller->unextended_sp() == interpreter_frame->interpreter_frame_sender_sp(), "Frame not properly walkable"); assert(caller->unextended_sp() == interpreter_frame->interpreter_frame_sender_sp(), "Frame not properly walkable");

View File

@ -1541,7 +1541,7 @@ int AbstractInterpreter::layout_activation(methodOop method,
tempcount* Interpreter::stackElementWords + popframe_extra_args; tempcount* Interpreter::stackElementWords + popframe_extra_args;
if (interpreter_frame != NULL) { if (interpreter_frame != NULL) {
#ifdef ASSERT #ifdef ASSERT
if (!EnableMethodHandles) if (!EnableInvokeDynamic)
// @@@ FIXME: Should we correct interpreter_frame_sender_sp in the calling sequences? // @@@ FIXME: Should we correct interpreter_frame_sender_sp in the calling sequences?
// Probably, since deoptimization doesn't work yet. // Probably, since deoptimization doesn't work yet.
assert(caller->unextended_sp() == interpreter_frame->interpreter_frame_sender_sp(), "Frame not properly walkable"); assert(caller->unextended_sp() == interpreter_frame->interpreter_frame_sender_sp(), "Frame not properly walkable");

View File

@ -23,6 +23,7 @@
*/ */
#include "precompiled.hpp" #include "precompiled.hpp"
#include "asm/assembler.hpp"
#include "interpreter/interpreter.hpp" #include "interpreter/interpreter.hpp"
#include "interpreter/interpreterRuntime.hpp" #include "interpreter/interpreterRuntime.hpp"
#include "interpreter/templateTable.hpp" #include "interpreter/templateTable.hpp"
@ -391,8 +392,8 @@ void TemplateTable::ldc(bool wide) {
void TemplateTable::fast_aldc(bool wide) { void TemplateTable::fast_aldc(bool wide) {
transition(vtos, atos); transition(vtos, atos);
if (!EnableMethodHandles) { if (!EnableInvokeDynamic) {
// We should not encounter this bytecode if !EnableMethodHandles. // We should not encounter this bytecode if !EnableInvokeDynamic.
// The verifier will stop it. However, if we get past the verifier, // The verifier will stop it. However, if we get past the verifier,
// this will stop the thread in a reasonable way, without crashing the JVM. // this will stop the thread in a reasonable way, without crashing the JVM.
__ call_VM(noreg, CAST_FROM_FN_PTR(address, __ call_VM(noreg, CAST_FROM_FN_PTR(address,
@ -1939,18 +1940,10 @@ void TemplateTable::fast_binaryswitch() {
__ movl(temp, Address(array, h, Address::times_8, 0*wordSize)); __ movl(temp, Address(array, h, Address::times_8, 0*wordSize));
__ bswapl(temp); __ bswapl(temp);
__ cmpl(key, temp); __ cmpl(key, temp);
if (VM_Version::supports_cmov()) { // j = h if (key < array[h].fast_match())
__ cmovl(Assembler::less , j, h); // j = h if (key < array[h].fast_match()) __ cmov32(Assembler::less , j, h);
__ cmovl(Assembler::greaterEqual, i, h); // i = h if (key >= array[h].fast_match()) // i = h if (key >= array[h].fast_match())
} else { __ cmov32(Assembler::greaterEqual, i, h);
Label set_i, end_of_if;
__ jccb(Assembler::greaterEqual, set_i); // {
__ mov(j, h); // j = h;
__ jmp(end_of_if); // }
__ bind(set_i); // else {
__ mov(i, h); // i = h;
__ bind(end_of_if); // }
}
// while (i+1 < j) // while (i+1 < j)
__ bind(entry); __ bind(entry);
__ leal(h, Address(i, 1)); // i+1 __ leal(h, Address(i, 1)); // i+1
@ -3478,22 +3471,14 @@ void TemplateTable::monitorenter() {
// find a free slot in the monitor block (result in rdx) // find a free slot in the monitor block (result in rdx)
{ Label entry, loop, exit; { Label entry, loop, exit;
__ movptr(rcx, monitor_block_top); // points to current entry, starting with top-most entry __ movptr(rcx, monitor_block_top); // points to current entry, starting with top-most entry
__ lea(rbx, monitor_block_bot); // points to word before bottom of monitor block
__ lea(rbx, monitor_block_bot); // points to word before bottom of monitor block
__ jmpb(entry); __ jmpb(entry);
__ bind(loop); __ bind(loop);
__ cmpptr(Address(rcx, BasicObjectLock::obj_offset_in_bytes()), (int32_t)NULL_WORD); // check if current entry is used __ cmpptr(Address(rcx, BasicObjectLock::obj_offset_in_bytes()), (int32_t)NULL_WORD); // check if current entry is used
__ cmovptr(Assembler::equal, rdx, rcx); // if not used then remember entry in rdx
// TODO - need new func here - kbt
if (VM_Version::supports_cmov()) {
__ cmov(Assembler::equal, rdx, rcx); // if not used then remember entry in rdx
} else {
Label L;
__ jccb(Assembler::notEqual, L);
__ mov(rdx, rcx); // if not used then remember entry in rdx
__ bind(L);
}
__ cmpptr(rax, Address(rcx, BasicObjectLock::obj_offset_in_bytes())); // check if current entry is for same object __ cmpptr(rax, Address(rcx, BasicObjectLock::obj_offset_in_bytes())); // check if current entry is for same object
__ jccb(Assembler::equal, exit); // if same object then stop searching __ jccb(Assembler::equal, exit); // if same object then stop searching
__ addptr(rcx, entry_size); // otherwise advance to next entry __ addptr(rcx, entry_size); // otherwise advance to next entry

View File

@ -405,8 +405,8 @@ void TemplateTable::ldc(bool wide) {
void TemplateTable::fast_aldc(bool wide) { void TemplateTable::fast_aldc(bool wide) {
transition(vtos, atos); transition(vtos, atos);
if (!EnableMethodHandles) { if (!EnableInvokeDynamic) {
// We should not encounter this bytecode if !EnableMethodHandles. // We should not encounter this bytecode if !EnableInvokeDynamic.
// The verifier will stop it. However, if we get past the verifier, // The verifier will stop it. However, if we get past the verifier,
// this will stop the thread in a reasonable way, without crashing the JVM. // this will stop the thread in a reasonable way, without crashing the JVM.
__ call_VM(noreg, CAST_FROM_FN_PTR(address, __ call_VM(noreg, CAST_FROM_FN_PTR(address,

View File

@ -429,6 +429,11 @@ void VM_Version::get_processor_features() {
UseXmmI2D = false; UseXmmI2D = false;
} }
} }
if( FLAG_IS_DEFAULT(UseSSE42Intrinsics) ) {
if( supports_sse4_2() && UseSSE >= 4 ) {
UseSSE42Intrinsics = true;
}
}
// Use count leading zeros count instruction if available. // Use count leading zeros count instruction if available.
if (supports_lzcnt()) { if (supports_lzcnt()) {

View File

@ -1393,6 +1393,10 @@ const int Matcher::init_array_short_size = 8 * BytesPerLong;
// registers? True for Intel but false for most RISCs // registers? True for Intel but false for most RISCs
const bool Matcher::clone_shift_expressions = true; const bool Matcher::clone_shift_expressions = true;
// Do we need to mask the count passed to shift instructions or does
// the cpu only look at the lower 5/6 bits anyway?
const bool Matcher::need_masked_shift_count = false;
bool Matcher::narrow_oop_use_complex_address() { bool Matcher::narrow_oop_use_complex_address() {
ShouldNotCallThis(); ShouldNotCallThis();
return true; return true;

View File

@ -574,12 +574,11 @@ int MachCallDynamicJavaNode::ret_addr_offset()
// In os_cpu .ad file // In os_cpu .ad file
// int MachCallRuntimeNode::ret_addr_offset() // int MachCallRuntimeNode::ret_addr_offset()
// Indicate if the safepoint node needs the polling page as an input. // Indicate if the safepoint node needs the polling page as an input,
// Since amd64 does not have absolute addressing but RIP-relative // it does if the polling page is more than disp32 away.
// addressing and the polling page is within 2G, it doesn't.
bool SafePointNode::needs_polling_address_input() bool SafePointNode::needs_polling_address_input()
{ {
return false; return Assembler::is_polling_page_far();
} }
// //
@ -992,15 +991,21 @@ void MachEpilogNode::format(PhaseRegAlloc* ra_, outputStream* st) const
framesize -= 2*wordSize; framesize -= 2*wordSize;
if (framesize) { if (framesize) {
st->print_cr("addq\trsp, %d\t# Destroy frame", framesize); st->print_cr("addq rsp, %d\t# Destroy frame", framesize);
st->print("\t"); st->print("\t");
} }
st->print_cr("popq\trbp"); st->print_cr("popq rbp");
if (do_polling() && C->is_method_compilation()) { if (do_polling() && C->is_method_compilation()) {
st->print_cr("\ttestl\trax, [rip + #offset_to_poll_page]\t"
"# Safepoint: poll for GC");
st->print("\t"); st->print("\t");
if (Assembler::is_polling_page_far()) {
st->print_cr("movq rscratch1, #polling_page_address\n\t"
"testl rax, [rscratch1]\t"
"# Safepoint: poll for GC");
} else {
st->print_cr("testl rax, [rip + #offset_to_poll_page]\t"
"# Safepoint: poll for GC");
}
} }
} }
#endif #endif
@ -1033,45 +1038,22 @@ void MachEpilogNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const
emit_opcode(cbuf, 0x58 | RBP_enc); emit_opcode(cbuf, 0x58 | RBP_enc);
if (do_polling() && C->is_method_compilation()) { if (do_polling() && C->is_method_compilation()) {
// testl %rax, off(%rip) // Opcode + ModRM + Disp32 == 6 bytes MacroAssembler _masm(&cbuf);
// XXX reg_mem doesn't support RIP-relative addressing yet AddressLiteral polling_page(os::get_polling_page(), relocInfo::poll_return_type);
cbuf.set_insts_mark(); if (Assembler::is_polling_page_far()) {
cbuf.relocate(cbuf.insts_mark(), relocInfo::poll_return_type, 0); // XXX __ lea(rscratch1, polling_page);
emit_opcode(cbuf, 0x85); // testl __ relocate(relocInfo::poll_return_type);
emit_rm(cbuf, 0x0, RAX_enc, 0x5); // 00 rax 101 == 0x5 __ testl(rax, Address(rscratch1, 0));
// cbuf.insts_mark() is beginning of instruction } else {
emit_d32_reloc(cbuf, os::get_polling_page()); __ testl(rax, polling_page);
// relocInfo::poll_return_type, }
} }
} }
uint MachEpilogNode::size(PhaseRegAlloc* ra_) const uint MachEpilogNode::size(PhaseRegAlloc* ra_) const
{ {
Compile* C = ra_->C; return MachNode::size(ra_); // too many variables; just compute it
int framesize = C->frame_slots() << LogBytesPerInt; // the hard way
assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
// Remove word for return adr already pushed
// and RBP
framesize -= 2*wordSize;
uint size = 0;
if (do_polling() && C->is_method_compilation()) {
size += 6;
}
// count popq rbp
size++;
if (framesize) {
if (framesize < 0x80) {
size += 4;
} else if (framesize) {
size += 7;
}
}
return size;
} }
int MachEpilogNode::reloc() const int MachEpilogNode::reloc() const
@ -2000,6 +1982,10 @@ const int Matcher::init_array_short_size = 8 * BytesPerLong;
// into registers? True for Intel but false for most RISCs // into registers? True for Intel but false for most RISCs
const bool Matcher::clone_shift_expressions = true; const bool Matcher::clone_shift_expressions = true;
// Do we need to mask the count passed to shift instructions or does
// the cpu only look at the lower 5/6 bits anyway?
const bool Matcher::need_masked_shift_count = false;
bool Matcher::narrow_oop_use_complex_address() { bool Matcher::narrow_oop_use_complex_address() {
assert(UseCompressedOops, "only for compressed oops code"); assert(UseCompressedOops, "only for compressed oops code");
return (LogMinObjAlignmentInBytes <= 3); return (LogMinObjAlignmentInBytes <= 3);
@ -3406,8 +3392,8 @@ encode %{
} }
if (EmitSync & 1) { if (EmitSync & 1) {
// Without cast to int32_t a movptr will destroy r10 which is typically obj // Without cast to int32_t a movptr will destroy r10 which is typically obj
masm.movptr (Address(boxReg, 0), (int32_t)intptr_t(markOopDesc::unused_mark())) ; masm.movptr (Address(boxReg, 0), (int32_t)intptr_t(markOopDesc::unused_mark())) ;
masm.cmpptr(rsp, (int32_t)NULL_WORD) ; masm.cmpptr(rsp, (int32_t)NULL_WORD) ;
} else } else
if (EmitSync & 2) { if (EmitSync & 2) {
Label DONE_LABEL; Label DONE_LABEL;
@ -3435,10 +3421,10 @@ encode %{
} else { } else {
Label DONE_LABEL, IsInflated, Egress; Label DONE_LABEL, IsInflated, Egress;
masm.movptr(tmpReg, Address(objReg, 0)) ; masm.movptr(tmpReg, Address(objReg, 0)) ;
masm.testl (tmpReg, 0x02) ; // inflated vs stack-locked|neutral|biased masm.testl (tmpReg, 0x02) ; // inflated vs stack-locked|neutral|biased
masm.jcc (Assembler::notZero, IsInflated) ; masm.jcc (Assembler::notZero, IsInflated) ;
// it's stack-locked, biased or neutral // it's stack-locked, biased or neutral
// TODO: optimize markword triage order to reduce the number of // TODO: optimize markword triage order to reduce the number of
// conditional branches in the most common cases. // conditional branches in the most common cases.
@ -3452,9 +3438,9 @@ encode %{
} }
// was q will it destroy high? // was q will it destroy high?
masm.orl (tmpReg, 1) ; masm.orl (tmpReg, 1) ;
masm.movptr(Address(boxReg, 0), tmpReg) ; masm.movptr(Address(boxReg, 0), tmpReg) ;
if (os::is_MP()) { masm.lock(); } if (os::is_MP()) { masm.lock(); }
masm.cmpxchgptr(boxReg, Address(objReg, 0)); // Updates tmpReg masm.cmpxchgptr(boxReg, Address(objReg, 0)); // Updates tmpReg
if (_counters != NULL) { if (_counters != NULL) {
masm.cond_inc32(Assembler::equal, masm.cond_inc32(Assembler::equal,
@ -3481,16 +3467,16 @@ encode %{
// fetched _owner. If the CAS is successful we may // fetched _owner. If the CAS is successful we may
// avoid an RTO->RTS upgrade on the $line. // avoid an RTO->RTS upgrade on the $line.
// Without cast to int32_t a movptr will destroy r10 which is typically obj // Without cast to int32_t a movptr will destroy r10 which is typically obj
masm.movptr(Address(boxReg, 0), (int32_t)intptr_t(markOopDesc::unused_mark())) ; masm.movptr(Address(boxReg, 0), (int32_t)intptr_t(markOopDesc::unused_mark())) ;
masm.mov (boxReg, tmpReg) ; masm.mov (boxReg, tmpReg) ;
masm.movptr (tmpReg, Address(tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)) ; masm.movptr (tmpReg, Address(tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)) ;
masm.testptr(tmpReg, tmpReg) ; masm.testptr(tmpReg, tmpReg) ;
masm.jcc (Assembler::notZero, DONE_LABEL) ; masm.jcc (Assembler::notZero, DONE_LABEL) ;
// It's inflated and appears unlocked // It's inflated and appears unlocked
if (os::is_MP()) { masm.lock(); } if (os::is_MP()) { masm.lock(); }
masm.cmpxchgptr(r15_thread, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2)) ; masm.cmpxchgptr(r15_thread, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2)) ;
// Intentional fall-through into DONE_LABEL ... // Intentional fall-through into DONE_LABEL ...
masm.bind (DONE_LABEL) ; masm.bind (DONE_LABEL) ;
@ -3509,8 +3495,8 @@ encode %{
Register tmpReg = as_Register($tmp$$reg); Register tmpReg = as_Register($tmp$$reg);
MacroAssembler masm(&cbuf); MacroAssembler masm(&cbuf);
if (EmitSync & 4) { if (EmitSync & 4) {
masm.cmpptr(rsp, 0) ; masm.cmpptr(rsp, 0) ;
} else } else
if (EmitSync & 8) { if (EmitSync & 8) {
Label DONE_LABEL; Label DONE_LABEL;
@ -3537,25 +3523,25 @@ encode %{
if (UseBiasedLocking && !UseOptoBiasInlining) { if (UseBiasedLocking && !UseOptoBiasInlining) {
masm.biased_locking_exit(objReg, tmpReg, DONE_LABEL); masm.biased_locking_exit(objReg, tmpReg, DONE_LABEL);
} }
masm.movptr(tmpReg, Address(objReg, 0)) ; masm.movptr(tmpReg, Address(objReg, 0)) ;
masm.cmpptr(Address(boxReg, 0), (int32_t)NULL_WORD) ; masm.cmpptr(Address(boxReg, 0), (int32_t)NULL_WORD) ;
masm.jcc (Assembler::zero, DONE_LABEL) ; masm.jcc (Assembler::zero, DONE_LABEL) ;
masm.testl (tmpReg, 0x02) ; masm.testl (tmpReg, 0x02) ;
masm.jcc (Assembler::zero, Stacked) ; masm.jcc (Assembler::zero, Stacked) ;
// It's inflated // It's inflated
masm.movptr(boxReg, Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)) ; masm.movptr(boxReg, Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)) ;
masm.xorptr(boxReg, r15_thread) ; masm.xorptr(boxReg, r15_thread) ;
masm.orptr (boxReg, Address (tmpReg, ObjectMonitor::recursions_offset_in_bytes()-2)) ; masm.orptr (boxReg, Address (tmpReg, ObjectMonitor::recursions_offset_in_bytes()-2)) ;
masm.jcc (Assembler::notZero, DONE_LABEL) ; masm.jcc (Assembler::notZero, DONE_LABEL) ;
masm.movptr(boxReg, Address (tmpReg, ObjectMonitor::cxq_offset_in_bytes()-2)) ; masm.movptr(boxReg, Address (tmpReg, ObjectMonitor::cxq_offset_in_bytes()-2)) ;
masm.orptr (boxReg, Address (tmpReg, ObjectMonitor::EntryList_offset_in_bytes()-2)) ; masm.orptr (boxReg, Address (tmpReg, ObjectMonitor::EntryList_offset_in_bytes()-2)) ;
masm.jcc (Assembler::notZero, CheckSucc) ; masm.jcc (Assembler::notZero, CheckSucc) ;
masm.movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), (int32_t)NULL_WORD) ; masm.movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), (int32_t)NULL_WORD) ;
masm.jmp (DONE_LABEL) ; masm.jmp (DONE_LABEL) ;
if ((EmitSync & 65536) == 0) { if ((EmitSync & 65536) == 0) {
Label LSuccess, LGoSlowPath ; Label LSuccess, LGoSlowPath ;
masm.bind (CheckSucc) ; masm.bind (CheckSucc) ;
masm.cmpptr(Address (tmpReg, ObjectMonitor::succ_offset_in_bytes()-2), (int32_t)NULL_WORD) ; masm.cmpptr(Address (tmpReg, ObjectMonitor::succ_offset_in_bytes()-2), (int32_t)NULL_WORD) ;
@ -3587,9 +3573,9 @@ encode %{
masm.jmp (DONE_LABEL) ; masm.jmp (DONE_LABEL) ;
} }
masm.bind (Stacked) ; masm.bind (Stacked) ;
masm.movptr(tmpReg, Address (boxReg, 0)) ; // re-fetch masm.movptr(tmpReg, Address (boxReg, 0)) ; // re-fetch
if (os::is_MP()) { masm.lock(); } if (os::is_MP()) { masm.lock(); }
masm.cmpxchgptr(tmpReg, Address(objReg, 0)); // Uses RAX which is box masm.cmpxchgptr(tmpReg, Address(objReg, 0)); // Uses RAX which is box
if (EmitSync & 65536) { if (EmitSync & 65536) {
@ -3910,22 +3896,6 @@ encode %{
// done: // done:
%} %}
// Safepoint Poll. This polls the safepoint page, and causes an
// exception if it is not readable. Unfortunately, it kills
// RFLAGS in the process.
enc_class enc_safepoint_poll
%{
// testl %rax, off(%rip) // Opcode + ModRM + Disp32 == 6 bytes
// XXX reg_mem doesn't support RIP-relative addressing yet
cbuf.set_insts_mark();
cbuf.relocate(cbuf.insts_mark(), relocInfo::poll_type, 0); // XXX
emit_opcode(cbuf, 0x85); // testl
emit_rm(cbuf, 0x0, RAX_enc, 0x5); // 00 rax 101 == 0x5
// cbuf.insts_mark() is beginning of instruction
emit_d32_reloc(cbuf, os::get_polling_page());
// relocInfo::poll_type,
%}
%} %}
@ -4229,6 +4199,15 @@ operand immP0()
interface(CONST_INTER); interface(CONST_INTER);
%} %}
operand immP_poll() %{
predicate(n->get_ptr() != 0 && n->get_ptr() == (intptr_t)os::get_polling_page());
match(ConP);
// formats are generated automatically for constants and base registers
format %{ %}
interface(CONST_INTER);
%}
// Pointer Immediate // Pointer Immediate
operand immN() %{ operand immN() %{
match(ConN); match(ConN);
@ -4836,7 +4815,7 @@ operand regF()
%} %}
// Double register operands // Double register operands
operand regD() operand regD()
%{ %{
constraint(ALLOC_IN_RC(double_reg)); constraint(ALLOC_IN_RC(double_reg));
match(RegD); match(RegD);
@ -6564,6 +6543,16 @@ instruct loadConP0(rRegP dst, immP0 src, rFlagsReg cr)
ins_pipe(ialu_reg); ins_pipe(ialu_reg);
%} %}
instruct loadConP_poll(rRegP dst, immP_poll src) %{
match(Set dst src);
format %{ "movq $dst, $src\t!ptr" %}
ins_encode %{
AddressLiteral polling_page(os::get_polling_page(), relocInfo::poll_type);
__ lea($dst$$Register, polling_page);
%}
ins_pipe(ialu_reg_fat);
%}
instruct loadConP31(rRegP dst, immP31 src, rFlagsReg cr) instruct loadConP31(rRegP dst, immP31 src, rFlagsReg cr)
%{ %{
match(Set dst src); match(Set dst src);
@ -7237,11 +7226,11 @@ instruct bytes_reverse_long(rRegL dst) %{
instruct bytes_reverse_unsigned_short(rRegI dst) %{ instruct bytes_reverse_unsigned_short(rRegI dst) %{
match(Set dst (ReverseBytesUS dst)); match(Set dst (ReverseBytesUS dst));
format %{ "bswapl $dst\n\t" format %{ "bswapl $dst\n\t"
"shrl $dst,16\n\t" %} "shrl $dst,16\n\t" %}
ins_encode %{ ins_encode %{
__ bswapl($dst$$Register); __ bswapl($dst$$Register);
__ shrl($dst$$Register, 16); __ shrl($dst$$Register, 16);
%} %}
ins_pipe( ialu_reg ); ins_pipe( ialu_reg );
%} %}
@ -7249,11 +7238,11 @@ instruct bytes_reverse_unsigned_short(rRegI dst) %{
instruct bytes_reverse_short(rRegI dst) %{ instruct bytes_reverse_short(rRegI dst) %{
match(Set dst (ReverseBytesS dst)); match(Set dst (ReverseBytesS dst));
format %{ "bswapl $dst\n\t" format %{ "bswapl $dst\n\t"
"sar $dst,16\n\t" %} "sar $dst,16\n\t" %}
ins_encode %{ ins_encode %{
__ bswapl($dst$$Register); __ bswapl($dst$$Register);
__ sarl($dst$$Register, 16); __ sarl($dst$$Register, 16);
%} %}
ins_pipe( ialu_reg ); ins_pipe( ialu_reg );
%} %}
@ -7476,7 +7465,7 @@ instruct membar_volatile(rFlagsReg cr) %{
effect(KILL cr); effect(KILL cr);
ins_cost(400); ins_cost(400);
format %{ format %{
$$template $$template
if (os::is_MP()) { if (os::is_MP()) {
$$emit$$"lock addl [rsp + #0], 0\t! membar_volatile" $$emit$$"lock addl [rsp + #0], 0\t! membar_volatile"
@ -8287,7 +8276,7 @@ instruct storePConditional(memory heap_top_ptr,
rFlagsReg cr) rFlagsReg cr)
%{ %{
match(Set cr (StorePConditional heap_top_ptr (Binary oldval newval))); match(Set cr (StorePConditional heap_top_ptr (Binary oldval newval)));
format %{ "cmpxchgq $heap_top_ptr, $newval\t# (ptr) " format %{ "cmpxchgq $heap_top_ptr, $newval\t# (ptr) "
"If rax == $heap_top_ptr then store $newval into $heap_top_ptr" %} "If rax == $heap_top_ptr then store $newval into $heap_top_ptr" %}
opcode(0x0F, 0xB1); opcode(0x0F, 0xB1);
@ -9850,9 +9839,9 @@ instruct xorI_rReg(rRegI dst, rRegI src, rFlagsReg cr)
// Xor Register with Immediate -1 // Xor Register with Immediate -1
instruct xorI_rReg_im1(rRegI dst, immI_M1 imm) %{ instruct xorI_rReg_im1(rRegI dst, immI_M1 imm) %{
match(Set dst (XorI dst imm)); match(Set dst (XorI dst imm));
format %{ "not $dst" %} format %{ "not $dst" %}
ins_encode %{ ins_encode %{
__ notl($dst$$Register); __ notl($dst$$Register);
%} %}
@ -10093,9 +10082,9 @@ instruct xorL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
// Xor Register with Immediate -1 // Xor Register with Immediate -1
instruct xorL_rReg_im1(rRegL dst, immL_M1 imm) %{ instruct xorL_rReg_im1(rRegL dst, immL_M1 imm) %{
match(Set dst (XorL dst imm)); match(Set dst (XorL dst imm));
format %{ "notq $dst" %} format %{ "notq $dst" %}
ins_encode %{ ins_encode %{
__ notq($dst$$Register); __ notq($dst$$Register);
%} %}
@ -12469,14 +12458,33 @@ instruct cmpFastUnlock(rFlagsReg cr,
// Safepoint Instructions // Safepoint Instructions
instruct safePoint_poll(rFlagsReg cr) instruct safePoint_poll(rFlagsReg cr)
%{ %{
predicate(!Assembler::is_polling_page_far());
match(SafePoint); match(SafePoint);
effect(KILL cr); effect(KILL cr);
format %{ "testl rax, [rip + #offset_to_poll_page]\t" format %{ "testl rax, [rip + #offset_to_poll_page]\t"
"# Safepoint: poll for GC" %} "# Safepoint: poll for GC" %}
size(6); // Opcode + ModRM + Disp32 == 6 bytes
ins_cost(125); ins_cost(125);
ins_encode(enc_safepoint_poll); ins_encode %{
AddressLiteral addr(os::get_polling_page(), relocInfo::poll_type);
__ testl(rax, addr);
%}
ins_pipe(ialu_reg_mem);
%}
instruct safePoint_poll_far(rFlagsReg cr, rRegP poll)
%{
predicate(Assembler::is_polling_page_far());
match(SafePoint poll);
effect(KILL cr, USE poll);
format %{ "testl rax, [$poll]\t"
"# Safepoint: poll for GC" %}
ins_cost(125);
ins_encode %{
__ relocate(relocInfo::poll_type);
__ testl(rax, Address($poll$$Register, 0));
%}
ins_pipe(ialu_reg_mem); ins_pipe(ialu_reg_mem);
%} %}

View File

@ -47,18 +47,6 @@ public class Util {
return sb.toString(); return sb.toString();
} }
static String join(String padder, String v[]) {
StringBuffer sb = new StringBuffer();
for (int i=0; i<v.length; i++) {
sb.append(v[i]);
if (i < (v.length - 1)) sb.append(padder);
}
return sb.toString();
}
static String prefixed_join(String padder, Vector v, boolean quoted) { static String prefixed_join(String padder, Vector v, boolean quoted) {
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();

View File

@ -587,7 +587,6 @@ public abstract class WinGammaPlatform {
Vector allConfigs = new Vector(); Vector allConfigs = new Vector();
allConfigs.add(new C1DebugConfig()); allConfigs.add(new C1DebugConfig());
allConfigs.add(new C1FastDebugConfig()); allConfigs.add(new C1FastDebugConfig());
allConfigs.add(new C1ProductConfig()); allConfigs.add(new C1ProductConfig());
@ -655,6 +654,10 @@ public abstract class WinGammaPlatform {
boolean isHeader() { boolean isHeader() {
return attr.shortName.endsWith(".h") || attr.shortName.endsWith(".hpp"); return attr.shortName.endsWith(".h") || attr.shortName.endsWith(".hpp");
} }
boolean isCpp() {
return attr.shortName.endsWith(".cpp");
}
} }
@ -708,7 +711,7 @@ public abstract class WinGammaPlatform {
PrintWriter printWriter; PrintWriter printWriter;
public void writeProjectFile(String projectFileName, String projectName, public void writeProjectFile(String projectFileName, String projectName,
Vector allConfigs) throws IOException { Vector<BuildConfig> allConfigs) throws IOException {
throw new RuntimeException("use compiler version specific version"); throw new RuntimeException("use compiler version specific version");
} }
} }

View File

@ -0,0 +1,545 @@
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.TreeSet;
import java.util.UUID;
import java.util.Vector;
public class WinGammaPlatformVC10 extends WinGammaPlatformVC7 {
@Override
protected String getProjectExt() {
return ".vcxproj";
}
@Override
public void writeProjectFile(String projectFileName, String projectName,
Vector<BuildConfig> allConfigs) throws IOException {
System.out.println();
System.out.print(" Writing .vcxproj file: " + projectFileName);
String projDir = Util.normalize(new File(projectFileName).getParent());
printWriter = new PrintWriter(projectFileName, "UTF-8");
printWriter.println("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
startTag("Project",
"DefaultTargets", "Build",
"ToolsVersion", "4.0",
"xmlns", "http://schemas.microsoft.com/developer/msbuild/2003");
startTag("ItemGroup",
"Label", "ProjectConfigurations");
for (BuildConfig cfg : allConfigs) {
startTag("ProjectConfiguration",
"Include", cfg.get("Name"));
tagData("Configuration", cfg.get("Id"));
tagData("Platform", cfg.get("PlatformName"));
endTag("ProjectConfiguration");
}
endTag("ItemGroup");
startTag("PropertyGroup", "Label", "Globals");
tagData("ProjectGuid", "{8822CB5C-1C41-41C2-8493-9F6E1994338B}");
tag("SccProjectName");
tag("SccLocalPath");
endTag("PropertyGroup");
tag("Import", "Project", "$(VCTargetsPath)\\Microsoft.Cpp.Default.props");
for (BuildConfig cfg : allConfigs) {
startTag(cfg, "PropertyGroup", "Label", "Configuration");
tagData("ConfigurationType", "DynamicLibrary");
tagData("UseOfMfc", "false");
endTag("PropertyGroup");
}
tag("Import", "Project", "$(VCTargetsPath)\\Microsoft.Cpp.props");
startTag("ImportGroup", "Label", "ExtensionSettings");
endTag("ImportGroup");
for (BuildConfig cfg : allConfigs) {
startTag(cfg, "ImportGroup", "Label", "PropertySheets");
tag("Import",
"Project", "$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props",
"Condition", "exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')",
"Label", "LocalAppDataPlatform");
endTag("ImportGroup");
}
tag("PropertyGroup", "Label", "UserMacros");
startTag("PropertyGroup");
tagData("_ProjectFileVersion", "10.0.30319.1");
for (BuildConfig cfg : allConfigs) {
tagData(cfg, "OutDir", cfg.get("OutputDir") + Util.sep);
tagData(cfg, "IntDir", cfg.get("OutputDir") + Util.sep);
tagData(cfg, "LinkIncremental", "false");
}
for (BuildConfig cfg : allConfigs) {
tagData(cfg, "CodeAnalysisRuleSet", "AllRules.ruleset");
tag(cfg, "CodeAnalysisRules");
tag(cfg, "CodeAnalysisRuleAssemblies");
}
endTag("PropertyGroup");
for (BuildConfig cfg : allConfigs) {
startTag(cfg, "ItemDefinitionGroup");
startTag("ClCompile");
tagV(cfg.getV("CompilerFlags"));
endTag("ClCompile");
startTag("Link");
tagV(cfg.getV("LinkerFlags"));
endTag("Link");
startTag("PostBuildEvent");
tagData("Message", BuildConfig.getFieldString(null, "PostbuildDescription"));
tagData("Command", cfg.expandFormat(BuildConfig.getFieldString(null, "PostbuildCommand").replace("\t", "\r\n")));
endTag("PostBuildEvent");
startTag("PreLinkEvent");
tagData("Message", BuildConfig.getFieldString(null, "PrelinkDescription"));
tagData("Command", cfg.expandFormat(BuildConfig.getFieldString(null, "PrelinkCommand").replace("\t", "\r\n")));
endTag("PreLinkEvent");
endTag("ItemDefinitionGroup");
}
writeFiles(allConfigs, projDir);
tag("Import", "Project", "$(VCTargetsPath)\\Microsoft.Cpp.targets");
startTag("ImportGroup", "Label", "ExtensionTargets");
endTag("ImportGroup");
endTag("Project");
printWriter.close();
System.out.println(" Done.");
writeFilterFile(projectFileName, projectName, allConfigs, projDir);
writeUserFile(projectFileName, allConfigs);
}
private void writeUserFile(String projectFileName, Vector<BuildConfig> allConfigs) throws FileNotFoundException, UnsupportedEncodingException {
String userFileName = projectFileName + ".user";
if (new File(userFileName).exists()) {
return;
}
System.out.print(" Writing .vcxproj.user file: " + userFileName);
printWriter = new PrintWriter(userFileName, "UTF-8");
printWriter.println("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
startTag("Project",
"ToolsVersion", "4.0",
"xmlns", "http://schemas.microsoft.com/developer/msbuild/2003");
for (BuildConfig cfg : allConfigs) {
startTag(cfg, "PropertyGroup");
tagData("LocalDebuggerCommand", "$(TargetDir)/hotspot.exe");
endTag("PropertyGroup");
}
endTag("Project");
printWriter.close();
System.out.println(" Done.");
}
private void writeFilterFile(String projectFileName, String projectName,
Vector<BuildConfig> allConfigs, String base) throws FileNotFoundException, UnsupportedEncodingException {
String filterFileName = projectFileName + ".filters";
System.out.print(" Writing .vcxproj.filters file: " + filterFileName);
printWriter = new PrintWriter(filterFileName, "UTF-8");
printWriter.println("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
startTag("Project",
"ToolsVersion", "4.0",
"xmlns", "http://schemas.microsoft.com/developer/msbuild/2003");
Hashtable<String, FileAttribute> allFiles = computeAttributedFiles(allConfigs);
TreeSet<FileInfo> sortedFiles = sortFiles(allFiles);
Vector<NameFilter> filters = makeFilters(sortedFiles);
// first all filters
startTag("ItemGroup");
for (NameFilter filter : filters) {
doWriteFilter(filter, "");
}
startTag("Filter", "Include", "Resource Files");
UUID uuid = UUID.randomUUID();
tagData("UniqueIdentifier", "{" + uuid.toString() + "}");
tagData("Extensions", "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe");
endTag("Filter");
endTag("ItemGroup");
// then all cpp files
startTag("ItemGroup");
for (NameFilter filter : filters) {
doWriteFiles(sortedFiles, filter, "", "ClCompile", new Evaluator() {
public boolean pick(FileInfo fi) {
return fi.isCpp();
}
}, base);
}
endTag("ItemGroup");
// then all header files
startTag("ItemGroup");
for (NameFilter filter : filters) {
doWriteFiles(sortedFiles, filter, "", "ClInclude", new Evaluator() {
public boolean pick(FileInfo fi) {
return fi.isHeader();
}
}, base);
}
endTag("ItemGroup");
// then all other files
startTag("ItemGroup");
for (NameFilter filter : filters) {
doWriteFiles(sortedFiles, filter, "", "None", new Evaluator() {
public boolean pick(FileInfo fi) {
return true;
}
}, base);
}
endTag("ItemGroup");
endTag("Project");
printWriter.close();
System.out.println(" Done.");
}
private void doWriteFilter(NameFilter filter, String start) {
startTag("Filter", "Include", start + filter.fname);
UUID uuid = UUID.randomUUID();
tagData("UniqueIdentifier", "{" + uuid.toString() + "}");
endTag("Filter");
if (filter instanceof ContainerFilter) {
Iterator i = ((ContainerFilter)filter).babies();
while (i.hasNext()) {
doWriteFilter((NameFilter)i.next(), start + filter.fname + "\\");
}
}
}
interface Evaluator {
boolean pick(FileInfo fi);
}
private void doWriteFiles(TreeSet<FileInfo> allFiles, NameFilter filter, String start, String tool, Evaluator eval, String base) {
if (filter instanceof ContainerFilter) {
Iterator i = ((ContainerFilter)filter).babies();
while (i.hasNext()) {
doWriteFiles(allFiles, (NameFilter)i.next(), start + filter.fname + "\\", tool, eval, base);
}
}
else {
Iterator i = allFiles.iterator();
while (i.hasNext()) {
FileInfo fi = (FileInfo)i.next();
if (!filter.match(fi)) {
continue;
}
if (eval.pick(fi)) {
startTag(tool, "Include", rel(fi.full, base));
tagData("Filter", start + filter.fname);
endTag(tool);
// we not gonna look at this file anymore (sic!)
i.remove();
}
}
}
}
void writeFiles(Vector<BuildConfig> allConfigs, String projDir) {
Hashtable<String, FileAttribute> allFiles = computeAttributedFiles(allConfigs);
TreeSet<FileInfo> sortedFiles = sortFiles(allFiles);
// first cpp-files
startTag("ItemGroup");
for (FileInfo fi : sortedFiles) {
if (!fi.isCpp()) {
continue;
}
writeFile("ClCompile", allConfigs, fi, projDir);
}
endTag("ItemGroup");
// then header-files
startTag("ItemGroup");
for (FileInfo fi : sortedFiles) {
if (!fi.isHeader()) {
continue;
}
writeFile("ClInclude", allConfigs, fi, projDir);
}
endTag("ItemGroup");
// then others
startTag("ItemGroup");
for (FileInfo fi : sortedFiles) {
if (fi.isHeader() || fi.isCpp()) {
continue;
}
writeFile("None", allConfigs, fi, projDir);
}
endTag("ItemGroup");
}
/**
* Make "path" into a relative path using "base" as the base.
*
* path and base are assumed to be normalized with / as the file separator.
* returned path uses "\\" as file separator
*/
private String rel(String path, String base)
{
if(!base.endsWith("/")) {
base += "/";
}
String[] pathTok = path.split("/");
String[] baseTok = base.split("/");
int pi = 0;
int bi = 0;
StringBuilder newPath = new StringBuilder();
// first step past all path components that are the same
while (pi < pathTok.length &&
bi < baseTok.length &&
pathTok[pi].equals(baseTok[bi])) {
pi++;
bi++;
}
// for each path component left in base, add "../"
while (bi < baseTok.length) {
bi++;
newPath.append("..\\");
}
// now add everything left in path
while (pi < pathTok.length) {
newPath.append(pathTok[pi]);
pi++;
if (pi != pathTok.length) {
newPath.append("\\");
}
}
return newPath.toString();
}
private void writeFile(String tool, Vector<BuildConfig> allConfigs, FileInfo fi, String base) {
if (fi.attr.configs == null && fi.attr.pchRoot == false && fi.attr.noPch == false) {
tag(tool, "Include", rel(fi.full, base));
}
else {
startTag(tool, "Include", rel(fi.full, base));
for (BuildConfig cfg : allConfigs) {
if (fi.attr.configs != null && !fi.attr.configs.contains(cfg.get("Name"))) {
tagData(cfg, "ExcludedFromBuild", "true");
}
if (fi.attr.pchRoot) {
tagData(cfg, "PrecompiledHeader", "Create");
}
if (fi.attr.noPch) {
startTag(cfg, "PrecompiledHeader");
endTag("PrecompiledHeader");
}
}
endTag(tool);
}
}
String buildCond(BuildConfig cfg) {
return "'$(Configuration)|$(Platform)'=='"+cfg.get("Name")+"'";
}
void tagV(Vector<String> v) {
Iterator<String> i = v.iterator();
while(i.hasNext()) {
String name = i.next();
String data = i.next();
tagData(name, data);
}
}
void tagData(BuildConfig cfg, String name, String data) {
tagData(name, data, "Condition", buildCond(cfg));
}
void tag(BuildConfig cfg, String name, String... attrs) {
String[] ss = new String[attrs.length + 2];
ss[0] = "Condition";
ss[1] = buildCond(cfg);
System.arraycopy(attrs, 0, ss, 2, attrs.length);
tag(name, ss);
}
void startTag(BuildConfig cfg, String name, String... attrs) {
String[] ss = new String[attrs.length + 2];
ss[0] = "Condition";
ss[1] = buildCond(cfg);
System.arraycopy(attrs, 0, ss, 2, attrs.length);
startTag(name, ss);
}
}
class CompilerInterfaceVC10 extends CompilerInterface {
@Override
Vector getBaseCompilerFlags(Vector defines, Vector includes, String outDir) {
Vector rv = new Vector();
addAttr(rv, "AdditionalIncludeDirectories", Util.join(";", includes));
addAttr(rv, "PreprocessorDefinitions",
Util.join(";", defines).replace("\\\"", "\""));
addAttr(rv, "PrecompiledHeaderFile", "precompiled.hpp");
addAttr(rv, "PrecompiledHeaderOutputFile", outDir+Util.sep+"vm.pch");
addAttr(rv, "AssemblerListingLocation", outDir);
addAttr(rv, "ObjectFileName", outDir+Util.sep);
addAttr(rv, "ProgramDataBaseFileName", outDir+Util.sep+"jvm.pdb");
// Set /nologo option
addAttr(rv, "SuppressStartupBanner", "true");
// Surpass the default /Tc or /Tp.
addAttr(rv, "CompileAs", "Default");
// Set /W3 option.
addAttr(rv, "WarningLevel", "Level3");
// Set /WX option,
addAttr(rv, "TreatWarningAsError", "true");
// Set /GS option
addAttr(rv, "BufferSecurityCheck", "false");
// Set /Zi option.
addAttr(rv, "DebugInformationFormat", "ProgramDatabase");
// Set /Yu option.
addAttr(rv, "PrecompiledHeader", "Use");
// Set /EHsc- option
addAttr(rv, "ExceptionHandling", "");
addAttr(rv, "MultiProcessorCompilation", "true");
return rv;
}
@Override
Vector getDebugCompilerFlags(String opt) {
Vector rv = new Vector();
// Set /On option
addAttr(rv, "Optimization", opt);
// Set /FR option.
addAttr(rv, "BrowseInformation", "true");
addAttr(rv, "BrowseInformationFile", "$(IntDir)");
// Set /MD option.
addAttr(rv, "RuntimeLibrary", "MultiThreadedDLL");
// Set /Oy- option
addAttr(rv, "OmitFramePointers", "false");
return rv;
}
@Override
Vector getProductCompilerFlags() {
Vector rv = new Vector();
// Set /O2 option.
addAttr(rv, "Optimization", "MaxSpeed");
// Set /Oy- option
addAttr(rv, "OmitFramePointers", "false");
// Set /Ob option. 1 is expandOnlyInline
addAttr(rv, "InlineFunctionExpansion", "OnlyExplicitInline");
// Set /GF option.
addAttr(rv, "StringPooling", "true");
// Set /MD option. 2 is rtMultiThreadedDLL
addAttr(rv, "RuntimeLibrary", "MultiThreadedDLL");
// Set /Gy option
addAttr(rv, "FunctionLevelLinking", "true");
return rv;
}
@Override
Vector getBaseLinkerFlags(String outDir, String outDll, String platformName) {
Vector rv = new Vector();
addAttr(rv, "AdditionalOptions",
"/export:JNI_GetDefaultJavaVMInitArgs " +
"/export:JNI_CreateJavaVM " +
"/export:JVM_FindClassFromBootLoader "+
"/export:JNI_GetCreatedJavaVMs "+
"/export:jio_snprintf /export:jio_printf "+
"/export:jio_fprintf /export:jio_vfprintf "+
"/export:jio_vsnprintf "+
"/export:JVM_GetVersionInfo "+
"/export:JVM_GetThreadStateNames "+
"/export:JVM_GetThreadStateValues "+
"/export:JVM_InitAgentProperties");
addAttr(rv, "AdditionalDependencies", "kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;Wsock32.lib;winmm.lib");
addAttr(rv, "OutputFile", outDll);
addAttr(rv, "SuppressStartupBanner", "true");
addAttr(rv, "ModuleDefinitionFile", outDir+Util.sep+"vm.def");
addAttr(rv, "ProgramDatabaseFile", outDir+Util.sep+"jvm.pdb");
addAttr(rv, "SubSystem", "Windows");
addAttr(rv, "BaseAddress", "0x8000000");
addAttr(rv, "ImportLibrary", outDir+Util.sep+"jvm.lib");
if(platformName.equals("Win32")) {
addAttr(rv, "TargetMachine", "MachineX86");
} else {
addAttr(rv, "TargetMachine", "MachineX64");
}
return rv;
}
@Override
Vector getDebugLinkerFlags() {
Vector rv = new Vector();
// /DEBUG option
addAttr(rv, "GenerateDebugInformation", "true");
return rv;
}
@Override
Vector getProductLinkerFlags() {
Vector rv = new Vector();
// Set /OPT:REF option.
addAttr(rv, "OptimizeReferences", "true");
// Set /OPT:ICF option.
addAttr(rv, "EnableCOMDATFolding", "true");
return rv;
}
@Override
void getAdditionalNonKernelLinkerFlags(Vector rv) {
extAttr(rv, "AdditionalOptions", " /export:AsyncGetCallTrace");
}
@Override
String getOptFlag() {
return "MaxSpeed";
}
@Override
String getNoOptFlag() {
return "Disabled";
}
@Override
String makeCfgName(String flavourBuild, String platform) {
return flavourBuild + "|" + platform;
}
}

View File

@ -35,7 +35,7 @@ public class WinGammaPlatformVC7 extends WinGammaPlatform {
String projectVersion() {return "7.10";}; String projectVersion() {return "7.10";};
public void writeProjectFile(String projectFileName, String projectName, public void writeProjectFile(String projectFileName, String projectName,
Vector allConfigs) throws IOException { Vector<BuildConfig> allConfigs) throws IOException {
System.out.println(); System.out.println();
System.out.println(" Writing .vcproj file: "+projectFileName); System.out.println(" Writing .vcproj file: "+projectFileName);
// If we got this far without an error, we're safe to actually // If we got this far without an error, we're safe to actually
@ -54,11 +54,11 @@ public class WinGammaPlatformVC7 extends WinGammaPlatform {
"SccLocalPath", "" "SccLocalPath", ""
} }
); );
startTag("Platforms", null); startTag("Platforms");
tag("Platform", new String[] {"Name", (String) BuildConfig.getField(null, "PlatformName")}); tag("Platform", new String[] {"Name", (String) BuildConfig.getField(null, "PlatformName")});
endTag("Platforms"); endTag("Platforms");
startTag("Configurations", null); startTag("Configurations");
for (Iterator i = allConfigs.iterator(); i.hasNext(); ) { for (Iterator i = allConfigs.iterator(); i.hasNext(); ) {
writeConfiguration((BuildConfig)i.next()); writeConfiguration((BuildConfig)i.next());
@ -66,11 +66,11 @@ public class WinGammaPlatformVC7 extends WinGammaPlatform {
endTag("Configurations"); endTag("Configurations");
tag("References", null); tag("References");
writeFiles(allConfigs); writeFiles(allConfigs);
tag("Globals", null); tag("Globals");
endTag("VisualStudioProject"); endTag("VisualStudioProject");
printWriter.close(); printWriter.close();
@ -190,28 +190,6 @@ public class WinGammaPlatformVC7 extends WinGammaPlatform {
} }
} }
class TypeFilter extends NameFilter {
String[] exts;
TypeFilter(String fname, String[] exts) {
this.fname = fname;
this.exts = exts;
}
boolean match(FileInfo fi) {
for (int i=0; i<exts.length; i++) {
if (fi.full.endsWith(exts[i])) {
return true;
}
}
return false;
}
String filterString() {
return Util.join(";", exts);
}
}
class TerminatorFilter extends NameFilter { class TerminatorFilter extends NameFilter {
TerminatorFilter(String fname) { TerminatorFilter(String fname) {
this.fname = fname; this.fname = fname;
@ -299,8 +277,8 @@ public class WinGammaPlatformVC7 extends WinGammaPlatform {
// - container filter just provides a container to group together real filters // - container filter just provides a container to group together real filters
// - real filter can select elements from the set according to some rule, put it into XML // - real filter can select elements from the set according to some rule, put it into XML
// and remove from the list // and remove from the list
Vector makeFilters(TreeSet<FileInfo> files) { Vector<NameFilter> makeFilters(TreeSet<FileInfo> files) {
Vector rv = new Vector(); Vector<NameFilter> rv = new Vector<NameFilter>();
String sbase = Util.normalize(BuildConfig.getFieldString(null, "SourceBase")+"/src/"); String sbase = Util.normalize(BuildConfig.getFieldString(null, "SourceBase")+"/src/");
String currentDir = ""; String currentDir = "";
@ -370,13 +348,12 @@ public class WinGammaPlatformVC7 extends WinGammaPlatform {
rv.add(new SpecificNameFilter("Precompiled Header", new String[] {"precompiled.hpp"})); rv.add(new SpecificNameFilter("Precompiled Header", new String[] {"precompiled.hpp"}));
// this one is to catch files not caught by other filters // this one is to catch files not caught by other filters
//rv.add(new TypeFilter("Header Files", new String[] {"h", "hpp", "hxx", "hm", "inl", "fi", "fd"}));
rv.add(new TerminatorFilter("Source Files")); rv.add(new TerminatorFilter("Source Files"));
return rv; return rv;
} }
void writeFiles(Vector allConfigs) { void writeFiles(Vector<BuildConfig> allConfigs) {
Hashtable allFiles = computeAttributedFiles(allConfigs); Hashtable allFiles = computeAttributedFiles(allConfigs);
@ -387,7 +364,7 @@ public class WinGammaPlatformVC7 extends WinGammaPlatform {
TreeSet sortedFiles = sortFiles(allFiles); TreeSet sortedFiles = sortFiles(allFiles);
startTag("Files", null); startTag("Files");
for (Iterator i = makeFilters(sortedFiles).iterator(); i.hasNext(); ) { for (Iterator i = makeFilters(sortedFiles).iterator(); i.hasNext(); ) {
doWriteFiles(sortedFiles, allConfigNames, (NameFilter)i.next()); doWriteFiles(sortedFiles, allConfigNames, (NameFilter)i.next());
@ -555,35 +532,40 @@ public class WinGammaPlatformVC7 extends WinGammaPlatform {
int indent; int indent;
private void startTagPrim(String name,
String[] attrs,
boolean close) {
startTagPrim(name, attrs, close, true);
}
private void startTagPrim(String name, private void startTagPrim(String name,
String[] attrs, String[] attrs,
boolean close) { boolean close,
boolean newline) {
doIndent(); doIndent();
printWriter.print("<"+name); printWriter.print("<"+name);
indent++; indent++;
if (attrs != null) { if (attrs != null && attrs.length > 0) {
printWriter.println();
for (int i=0; i<attrs.length; i+=2) { for (int i=0; i<attrs.length; i+=2) {
doIndent();
printWriter.print(" " + attrs[i]+"=\""+attrs[i+1]+"\""); printWriter.print(" " + attrs[i]+"=\""+attrs[i+1]+"\"");
if (i < attrs.length - 2) { if (i < attrs.length - 2) {
printWriter.println();
} }
} }
} }
if (close) { if (close) {
indent--; indent--;
//doIndent(); printWriter.print(" />");
printWriter.println("/>");
} else { } else {
//doIndent(); printWriter.print(">");
printWriter.println(">"); }
if(newline) {
printWriter.println();
} }
} }
void startTag(String name, String[] attrs) { void startTag(String name, String... attrs) {
startTagPrim(name, attrs, false); startTagPrim(name, attrs, false);
} }
@ -601,11 +583,25 @@ public class WinGammaPlatformVC7 extends WinGammaPlatform {
printWriter.println("</"+name+">"); printWriter.println("</"+name+">");
} }
void tag(String name, String[] attrs) { void tag(String name, String... attrs) {
startTagPrim(name, attrs, true); startTagPrim(name, attrs, true);
} }
void tagV(String name, Vector attrs) { void tagData(String name, String data) {
doIndent();
printWriter.print("<"+name+">");
printWriter.print(data);
printWriter.println("</"+name+">");
}
void tagData(String name, String data, String... attrs) {
startTagPrim(name, attrs, false, false);
printWriter.print(data);
printWriter.println("</"+name+">");
indent--;
}
void tagV(String name, Vector attrs) {
String s[] = new String [attrs.size()]; String s[] = new String [attrs.size()];
for (int i=0; i<attrs.size(); i++) { for (int i=0; i<attrs.size(); i++) {
s[i] = (String)attrs.elementAt(i); s[i] = (String)attrs.elementAt(i);
@ -616,7 +612,7 @@ public class WinGammaPlatformVC7 extends WinGammaPlatform {
void doIndent() { void doIndent() {
for (int i=0; i<indent; i++) { for (int i=0; i<indent; i++) {
printWriter.print(" "); printWriter.print(" ");
} }
} }

View File

@ -239,6 +239,11 @@ int main(int argc, char *argv[])
AD.addInclude(AD._CPP_file, "assembler_sparc.inline.hpp"); AD.addInclude(AD._CPP_file, "assembler_sparc.inline.hpp");
AD.addInclude(AD._CPP_file, "nativeInst_sparc.hpp"); AD.addInclude(AD._CPP_file, "nativeInst_sparc.hpp");
AD.addInclude(AD._CPP_file, "vmreg_sparc.inline.hpp"); AD.addInclude(AD._CPP_file, "vmreg_sparc.inline.hpp");
#endif
#ifdef TARGET_ARCH_arm
AD.addInclude(AD._CPP_file, "assembler_arm.inline.hpp");
AD.addInclude(AD._CPP_file, "nativeInst_arm.hpp");
AD.addInclude(AD._CPP_file, "vmreg_arm.inline.hpp");
#endif #endif
AD.addInclude(AD._HPP_file, "memory/allocation.hpp"); AD.addInclude(AD._HPP_file, "memory/allocation.hpp");
AD.addInclude(AD._HPP_file, "opto/machnode.hpp"); AD.addInclude(AD._HPP_file, "opto/machnode.hpp");

View File

@ -30,6 +30,7 @@
#include "c1/c1_InstructionPrinter.hpp" #include "c1/c1_InstructionPrinter.hpp"
#include "ci/ciField.hpp" #include "ci/ciField.hpp"
#include "ci/ciKlass.hpp" #include "ci/ciKlass.hpp"
#include "compiler/compileBroker.hpp"
#include "interpreter/bytecode.hpp" #include "interpreter/bytecode.hpp"
#include "runtime/sharedRuntime.hpp" #include "runtime/sharedRuntime.hpp"
#include "utilities/bitMap.inline.hpp" #include "utilities/bitMap.inline.hpp"
@ -3775,24 +3776,7 @@ void GraphBuilder::append_unsafe_CAS(ciMethod* callee) {
#ifndef PRODUCT #ifndef PRODUCT
void GraphBuilder::print_inline_result(ciMethod* callee, bool res) { void GraphBuilder::print_inline_result(ciMethod* callee, bool res) {
const char sync_char = callee->is_synchronized() ? 's' : ' '; CompileTask::print_inlining(callee, scope()->level(), bci(), _inline_bailout_msg);
const char exception_char = callee->has_exception_handlers() ? '!' : ' ';
const char monitors_char = callee->has_monitor_bytecodes() ? 'm' : ' ';
tty->print(" %c%c%c ", sync_char, exception_char, monitors_char);
for (int i = 0; i < scope()->level(); i++) tty->print(" ");
if (res) {
tty->print(" ");
} else {
tty->print("- ");
}
tty->print("@ %d ", bci());
callee->print_short_name();
tty->print(" (%d bytes)", callee->code_size());
if (_inline_bailout_msg) {
tty->print(" %s", _inline_bailout_msg);
}
tty->cr();
if (res && CIPrintMethodCodes) { if (res && CIPrintMethodCodes) {
callee->print_codes(); callee->print_codes();
} }

View File

@ -1871,7 +1871,8 @@ void ciTypeFlow::Block::print_value_on(outputStream* st) const {
// ------------------------------------------------------------------ // ------------------------------------------------------------------
// ciTypeFlow::Block::print_on // ciTypeFlow::Block::print_on
void ciTypeFlow::Block::print_on(outputStream* st) const { void ciTypeFlow::Block::print_on(outputStream* st) const {
if ((Verbose || WizardMode)) { if ((Verbose || WizardMode) && (limit() >= 0)) {
// Don't print 'dummy' blocks (i.e. blocks with limit() '-1')
outer()->method()->print_codes_on(start(), limit(), st); outer()->method()->print_codes_on(start(), limit(), st);
} }
st->print_cr(" ==================================================== "); st->print_cr(" ==================================================== ");

View File

@ -152,7 +152,7 @@ void ClassFileParser::parse_constant_pool_entries(constantPoolHandle cp, int len
"Class file version does not support constant tag %u in class file %s", "Class file version does not support constant tag %u in class file %s",
tag, CHECK); tag, CHECK);
} }
if (!EnableMethodHandles) { if (!EnableInvokeDynamic) {
classfile_parse_error( classfile_parse_error(
"This JVM does not support constant tag %u in class file %s", "This JVM does not support constant tag %u in class file %s",
tag, CHECK); tag, CHECK);
@ -260,7 +260,7 @@ void ClassFileParser::parse_constant_pool_entries(constantPoolHandle cp, int len
verify_legal_utf8((unsigned char*)utf8_buffer, utf8_length, CHECK); verify_legal_utf8((unsigned char*)utf8_buffer, utf8_length, CHECK);
} }
if (AnonymousClasses && has_cp_patch_at(index)) { if (EnableInvokeDynamic && has_cp_patch_at(index)) {
Handle patch = clear_cp_patch_at(index); Handle patch = clear_cp_patch_at(index);
guarantee_property(java_lang_String::is_instance(patch()), guarantee_property(java_lang_String::is_instance(patch()),
"Illegal utf8 patch at %d in class file %s", "Illegal utf8 patch at %d in class file %s",
@ -443,7 +443,7 @@ constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) {
int ref_index = cp->method_handle_index_at(index); int ref_index = cp->method_handle_index_at(index);
check_property( check_property(
valid_cp_range(ref_index, length) && valid_cp_range(ref_index, length) &&
EnableMethodHandles, EnableInvokeDynamic,
"Invalid constant pool index %u in class file %s", "Invalid constant pool index %u in class file %s",
ref_index, CHECK_(nullHandle)); ref_index, CHECK_(nullHandle));
constantTag tag = cp->tag_at(ref_index); constantTag tag = cp->tag_at(ref_index);
@ -487,7 +487,7 @@ constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) {
check_property( check_property(
valid_cp_range(ref_index, length) && valid_cp_range(ref_index, length) &&
cp->tag_at(ref_index).is_utf8() && cp->tag_at(ref_index).is_utf8() &&
EnableMethodHandles, EnableInvokeDynamic,
"Invalid constant pool index %u in class file %s", "Invalid constant pool index %u in class file %s",
ref_index, CHECK_(nullHandle)); ref_index, CHECK_(nullHandle));
} }
@ -522,7 +522,7 @@ constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) {
if (_cp_patches != NULL) { if (_cp_patches != NULL) {
// need to treat this_class specially... // need to treat this_class specially...
assert(AnonymousClasses, ""); assert(EnableInvokeDynamic, "");
int this_class_index; int this_class_index;
{ {
cfs->guarantee_more(8, CHECK_(nullHandle)); // flags, this_class, super_class, infs_len cfs->guarantee_more(8, CHECK_(nullHandle)); // flags, this_class, super_class, infs_len
@ -677,7 +677,7 @@ constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) {
void ClassFileParser::patch_constant_pool(constantPoolHandle cp, int index, Handle patch, TRAPS) { void ClassFileParser::patch_constant_pool(constantPoolHandle cp, int index, Handle patch, TRAPS) {
assert(AnonymousClasses, ""); assert(EnableInvokeDynamic, "");
BasicType patch_type = T_VOID; BasicType patch_type = T_VOID;
switch (cp->tag_at(index).value()) { switch (cp->tag_at(index).value()) {
@ -2103,7 +2103,7 @@ methodHandle ClassFileParser::parse_method(constantPoolHandle cp, bool is_interf
_has_vanilla_constructor = true; _has_vanilla_constructor = true;
} }
if (EnableMethodHandles && (m->is_method_handle_invoke() || if (EnableInvokeDynamic && (m->is_method_handle_invoke() ||
m->is_method_handle_adapter())) { m->is_method_handle_adapter())) {
THROW_MSG_(vmSymbols::java_lang_VirtualMachineError(), THROW_MSG_(vmSymbols::java_lang_VirtualMachineError(),
"Method handle invokers must be defined internally to the VM", nullHandle); "Method handle invokers must be defined internally to the VM", nullHandle);
@ -2771,7 +2771,7 @@ void ClassFileParser::java_lang_invoke_MethodHandle_fix_pre(constantPoolHandle c
// This is not particularly nice, but since there is no way to express // This is not particularly nice, but since there is no way to express
// a native wordSize field in Java, we must do it at this level. // a native wordSize field in Java, we must do it at this level.
if (!EnableMethodHandles) return; if (!EnableInvokeDynamic) return;
int word_sig_index = 0; int word_sig_index = 0;
const int cp_size = cp->length(); const int cp_size = cp->length();
@ -3191,15 +3191,15 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
next_nonstatic_field_offset = first_nonstatic_field_offset; next_nonstatic_field_offset = first_nonstatic_field_offset;
// adjust the vmentry field declaration in java.lang.invoke.MethodHandle // adjust the vmentry field declaration in java.lang.invoke.MethodHandle
if (EnableMethodHandles && class_name == vmSymbols::java_lang_invoke_MethodHandle() && class_loader.is_null()) { if (EnableInvokeDynamic && class_name == vmSymbols::java_lang_invoke_MethodHandle() && class_loader.is_null()) {
java_lang_invoke_MethodHandle_fix_pre(cp, fields, &fac, CHECK_(nullHandle)); java_lang_invoke_MethodHandle_fix_pre(cp, fields, &fac, CHECK_(nullHandle));
} }
if (AllowTransitionalJSR292 && if (AllowTransitionalJSR292 &&
EnableMethodHandles && class_name == vmSymbols::java_dyn_MethodHandle() && class_loader.is_null()) { EnableInvokeDynamic && class_name == vmSymbols::java_dyn_MethodHandle() && class_loader.is_null()) {
java_lang_invoke_MethodHandle_fix_pre(cp, fields, &fac, CHECK_(nullHandle)); java_lang_invoke_MethodHandle_fix_pre(cp, fields, &fac, CHECK_(nullHandle));
} }
if (AllowTransitionalJSR292 && if (AllowTransitionalJSR292 &&
EnableMethodHandles && class_name == vmSymbols::sun_dyn_MethodHandleImpl() && class_loader.is_null()) { EnableInvokeDynamic && class_name == vmSymbols::sun_dyn_MethodHandleImpl() && class_loader.is_null()) {
// allow vmentry field in MethodHandleImpl also // allow vmentry field in MethodHandleImpl also
java_lang_invoke_MethodHandle_fix_pre(cp, fields, &fac, CHECK_(nullHandle)); java_lang_invoke_MethodHandle_fix_pre(cp, fields, &fac, CHECK_(nullHandle));
} }

View File

@ -231,11 +231,11 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
char* skip_over_field_signature(char* signature, bool void_ok, unsigned int length, TRAPS); char* skip_over_field_signature(char* signature, bool void_ok, unsigned int length, TRAPS);
bool is_anonymous() { bool is_anonymous() {
assert(AnonymousClasses || _host_klass.is_null(), ""); assert(EnableInvokeDynamic || _host_klass.is_null(), "");
return _host_klass.not_null(); return _host_klass.not_null();
} }
bool has_cp_patch_at(int index) { bool has_cp_patch_at(int index) {
assert(AnonymousClasses, ""); assert(EnableInvokeDynamic, "");
assert(index >= 0, "oob"); assert(index >= 0, "oob");
return (_cp_patches != NULL return (_cp_patches != NULL
&& index < _cp_patches->length() && index < _cp_patches->length()
@ -258,7 +258,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
// constant pool construction, but in later versions they can. // constant pool construction, but in later versions they can.
// %%% Let's phase out the old is_klass_reference. // %%% Let's phase out the old is_klass_reference.
bool is_klass_reference(constantPoolHandle cp, int index) { bool is_klass_reference(constantPoolHandle cp, int index) {
return ((LinkWellKnownClasses || AnonymousClasses) return ((LinkWellKnownClasses || EnableInvokeDynamic)
? cp->tag_at(index).is_klass_or_reference() ? cp->tag_at(index).is_klass_or_reference()
: cp->tag_at(index).is_klass_reference()); : cp->tag_at(index).is_klass_reference());
} }

View File

@ -301,6 +301,15 @@ jchar* java_lang_String::as_unicode_string(oop java_string, int& length) {
return result; return result;
} }
unsigned int java_lang_String::hash_string(oop java_string) {
typeArrayOop value = java_lang_String::value(java_string);
int offset = java_lang_String::offset(java_string);
int length = java_lang_String::length(java_string);
if (length == 0) return 0;
return hash_string(value->char_at_addr(offset), length);
}
Symbol* java_lang_String::as_symbol(Handle java_string, TRAPS) { Symbol* java_lang_String::as_symbol(Handle java_string, TRAPS) {
oop obj = java_string(); oop obj = java_string();
typeArrayOop value = java_lang_String::value(obj); typeArrayOop value = java_lang_String::value(obj);
@ -2322,7 +2331,7 @@ int java_lang_invoke_AdapterMethodHandle::_conversion_offset;
void java_lang_invoke_MethodHandle::compute_offsets() { void java_lang_invoke_MethodHandle::compute_offsets() {
klassOop k = SystemDictionary::MethodHandle_klass(); klassOop k = SystemDictionary::MethodHandle_klass();
if (k != NULL && EnableMethodHandles) { if (k != NULL && EnableInvokeDynamic) {
bool allow_super = false; bool allow_super = false;
if (AllowTransitionalJSR292) allow_super = true; // temporary, to access java.dyn.MethodHandleImpl if (AllowTransitionalJSR292) allow_super = true; // temporary, to access java.dyn.MethodHandleImpl
compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::java_lang_invoke_MethodType_signature(), allow_super); compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::java_lang_invoke_MethodType_signature(), allow_super);
@ -2337,7 +2346,7 @@ void java_lang_invoke_MethodHandle::compute_offsets() {
void java_lang_invoke_MemberName::compute_offsets() { void java_lang_invoke_MemberName::compute_offsets() {
klassOop k = SystemDictionary::MemberName_klass(); klassOop k = SystemDictionary::MemberName_klass();
if (k != NULL && EnableMethodHandles) { if (k != NULL && EnableInvokeDynamic) {
compute_offset(_clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature()); compute_offset(_clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature());
compute_offset(_name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature()); compute_offset(_name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::object_signature()); compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::object_signature());
@ -2349,14 +2358,14 @@ void java_lang_invoke_MemberName::compute_offsets() {
void java_lang_invoke_DirectMethodHandle::compute_offsets() { void java_lang_invoke_DirectMethodHandle::compute_offsets() {
klassOop k = SystemDictionary::DirectMethodHandle_klass(); klassOop k = SystemDictionary::DirectMethodHandle_klass();
if (k != NULL && EnableMethodHandles) { if (k != NULL && EnableInvokeDynamic) {
compute_offset(_vmindex_offset, k, vmSymbols::vmindex_name(), vmSymbols::int_signature(), true); compute_offset(_vmindex_offset, k, vmSymbols::vmindex_name(), vmSymbols::int_signature(), true);
} }
} }
void java_lang_invoke_BoundMethodHandle::compute_offsets() { void java_lang_invoke_BoundMethodHandle::compute_offsets() {
klassOop k = SystemDictionary::BoundMethodHandle_klass(); klassOop k = SystemDictionary::BoundMethodHandle_klass();
if (k != NULL && EnableMethodHandles) { if (k != NULL && EnableInvokeDynamic) {
compute_offset(_vmargslot_offset, k, vmSymbols::vmargslot_name(), vmSymbols::int_signature(), true); compute_offset(_vmargslot_offset, k, vmSymbols::vmargslot_name(), vmSymbols::int_signature(), true);
compute_offset(_argument_offset, k, vmSymbols::argument_name(), vmSymbols::object_signature(), true); compute_offset(_argument_offset, k, vmSymbols::argument_name(), vmSymbols::object_signature(), true);
} }
@ -2364,7 +2373,7 @@ void java_lang_invoke_BoundMethodHandle::compute_offsets() {
void java_lang_invoke_AdapterMethodHandle::compute_offsets() { void java_lang_invoke_AdapterMethodHandle::compute_offsets() {
klassOop k = SystemDictionary::AdapterMethodHandle_klass(); klassOop k = SystemDictionary::AdapterMethodHandle_klass();
if (k != NULL && EnableMethodHandles) { if (k != NULL && EnableInvokeDynamic) {
compute_offset(_conversion_offset, k, vmSymbols::conversion_name(), vmSymbols::int_signature(), true); compute_offset(_conversion_offset, k, vmSymbols::conversion_name(), vmSymbols::int_signature(), true);
} }
} }
@ -2982,7 +2991,7 @@ void JavaClasses::compute_offsets() {
java_lang_Class::compute_offsets(); java_lang_Class::compute_offsets();
java_lang_Thread::compute_offsets(); java_lang_Thread::compute_offsets();
java_lang_ThreadGroup::compute_offsets(); java_lang_ThreadGroup::compute_offsets();
if (EnableMethodHandles) { if (EnableInvokeDynamic) {
java_lang_invoke_MethodHandle::compute_offsets(); java_lang_invoke_MethodHandle::compute_offsets();
java_lang_invoke_MemberName::compute_offsets(); java_lang_invoke_MemberName::compute_offsets();
java_lang_invoke_DirectMethodHandle::compute_offsets(); java_lang_invoke_DirectMethodHandle::compute_offsets();
@ -2990,8 +2999,6 @@ void JavaClasses::compute_offsets() {
java_lang_invoke_AdapterMethodHandle::compute_offsets(); java_lang_invoke_AdapterMethodHandle::compute_offsets();
java_lang_invoke_MethodType::compute_offsets(); java_lang_invoke_MethodType::compute_offsets();
java_lang_invoke_MethodTypeForm::compute_offsets(); java_lang_invoke_MethodTypeForm::compute_offsets();
}
if (EnableInvokeDynamic) {
java_lang_invoke_CallSite::compute_offsets(); java_lang_invoke_CallSite::compute_offsets();
} }
java_security_AccessControlContext::compute_offsets(); java_security_AccessControlContext::compute_offsets();

View File

@ -109,6 +109,30 @@ class java_lang_String : AllStatic {
static char* as_platform_dependent_str(Handle java_string, TRAPS); static char* as_platform_dependent_str(Handle java_string, TRAPS);
static jchar* as_unicode_string(oop java_string, int& length); static jchar* as_unicode_string(oop java_string, int& length);
// Compute the hash value for a java.lang.String object which would
// contain the characters passed in. This hash value is used for at
// least two purposes.
//
// (a) As the hash value used by the StringTable for bucket selection
// and comparison (stored in the HashtableEntry structures). This
// is used in the String.intern() method.
//
// (b) As the hash value used by the String object itself, in
// String.hashCode(). This value is normally calculate in Java code
// in the String.hashCode method(), but is precomputed for String
// objects in the shared archive file.
//
// For this reason, THIS ALGORITHM MUST MATCH String.hashCode().
static unsigned int hash_string(jchar* s, int len) {
unsigned int h = 0;
while (len-- > 0) {
h = 31*h + (unsigned int) *s;
s++;
}
return h;
}
static unsigned int hash_string(oop java_string);
static bool equals(oop java_string, jchar* chars, int len); static bool equals(oop java_string, jchar* chars, int len);
// Conversion between '.' and '/' formats // Conversion between '.' and '/' formats

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -480,33 +480,6 @@ class StableMemoryChecker : public StackObj {
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
// Compute the hash value for a java.lang.String object which would
// contain the characters passed in. This hash value is used for at
// least two purposes.
//
// (a) As the hash value used by the StringTable for bucket selection
// and comparison (stored in the HashtableEntry structures). This
// is used in the String.intern() method.
//
// (b) As the hash value used by the String object itself, in
// String.hashCode(). This value is normally calculate in Java code
// in the String.hashCode method(), but is precomputed for String
// objects in the shared archive file.
//
// For this reason, THIS ALGORITHM MUST MATCH String.hashCode().
int StringTable::hash_string(jchar* s, int len) {
unsigned h = 0;
while (len-- > 0) {
h = 31*h + (unsigned) *s;
s++;
}
return h;
}
StringTable* StringTable::_the_table = NULL; StringTable* StringTable::_the_table = NULL;
oop StringTable::lookup(int index, jchar* name, oop StringTable::lookup(int index, jchar* name,
@ -561,7 +534,7 @@ oop StringTable::lookup(Symbol* symbol) {
ResourceMark rm; ResourceMark rm;
int length; int length;
jchar* chars = symbol->as_unicode(length); jchar* chars = symbol->as_unicode(length);
unsigned int hashValue = hash_string(chars, length); unsigned int hashValue = java_lang_String::hash_string(chars, length);
int index = the_table()->hash_to_index(hashValue); int index = the_table()->hash_to_index(hashValue);
return the_table()->lookup(index, chars, length, hashValue); return the_table()->lookup(index, chars, length, hashValue);
} }
@ -569,7 +542,7 @@ oop StringTable::lookup(Symbol* symbol) {
oop StringTable::intern(Handle string_or_null, jchar* name, oop StringTable::intern(Handle string_or_null, jchar* name,
int len, TRAPS) { int len, TRAPS) {
unsigned int hashValue = hash_string(name, len); unsigned int hashValue = java_lang_String::hash_string(name, len);
int index = the_table()->hash_to_index(hashValue); int index = the_table()->hash_to_index(hashValue);
oop string = the_table()->lookup(index, name, len, hashValue); oop string = the_table()->lookup(index, name, len, hashValue);
@ -663,10 +636,7 @@ void StringTable::verify() {
oop s = p->literal(); oop s = p->literal();
guarantee(s != NULL, "interned string is NULL"); guarantee(s != NULL, "interned string is NULL");
guarantee(s->is_perm() || !JavaObjectsInPerm, "interned string not in permspace"); guarantee(s->is_perm() || !JavaObjectsInPerm, "interned string not in permspace");
unsigned int h = java_lang_String::hash_string(s);
int length;
jchar* chars = java_lang_String::as_unicode_string(s, length);
unsigned int h = hash_string(chars, length);
guarantee(p->hash() == h, "broken hash in string table entry"); guarantee(p->hash() == h, "broken hash in string table entry");
guarantee(the_table()->hash_to_index(h) == i, guarantee(the_table()->hash_to_index(h) == i,
"wrong index in string table"); "wrong index in string table");

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -242,8 +242,6 @@ public:
_the_table = new StringTable(t, number_of_entries); _the_table = new StringTable(t, number_of_entries);
} }
static int hash_string(jchar* s, int len);
// GC support // GC support
// Delete pointers to otherwise-unreachable objects. // Delete pointers to otherwise-unreachable objects.
static void unlink(BoolObjectClosure* cl); static void unlink(BoolObjectClosure* cl);

View File

@ -1017,7 +1017,7 @@ klassOop SystemDictionary::parse_stream(Symbol* class_name,
} }
if (host_klass.not_null() && k.not_null()) { if (host_klass.not_null() && k.not_null()) {
assert(AnonymousClasses, ""); assert(EnableInvokeDynamic, "");
// If it's anonymous, initialize it now, since nobody else will. // If it's anonymous, initialize it now, since nobody else will.
k->set_host_klass(host_klass()); k->set_host_klass(host_klass());
@ -1940,7 +1940,7 @@ bool SystemDictionary::initialize_wk_klass(WKID id, int init_opt, TRAPS) {
} }
Symbol* backup_symbol = NULL; // symbol to try if the current symbol fails Symbol* backup_symbol = NULL; // symbol to try if the current symbol fails
if (init_opt == SystemDictionary::Pre_JSR292) { if (init_opt == SystemDictionary::Pre_JSR292) {
if (!EnableMethodHandles) try_load = false; // do not bother to load such classes if (!EnableInvokeDynamic) try_load = false; // do not bother to load such classes
if (AllowTransitionalJSR292) { if (AllowTransitionalJSR292) {
backup_symbol = find_backup_class_name(symbol); backup_symbol = find_backup_class_name(symbol);
if (try_load && PreferTransitionalJSR292) { if (try_load && PreferTransitionalJSR292) {
@ -2038,25 +2038,15 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) {
instanceKlass::cast(WK_KLASS(FinalReference_klass))->set_reference_type(REF_FINAL); instanceKlass::cast(WK_KLASS(FinalReference_klass))->set_reference_type(REF_FINAL);
instanceKlass::cast(WK_KLASS(PhantomReference_klass))->set_reference_type(REF_PHANTOM); instanceKlass::cast(WK_KLASS(PhantomReference_klass))->set_reference_type(REF_PHANTOM);
WKID meth_group_start = WK_KLASS_ENUM_NAME(MethodHandle_klass); // JSR 292 classes
WKID meth_group_end = WK_KLASS_ENUM_NAME(WrongMethodTypeException_klass); WKID jsr292_group_start = WK_KLASS_ENUM_NAME(MethodHandle_klass);
initialize_wk_klasses_until(meth_group_start, scan, CHECK); WKID jsr292_group_end = WK_KLASS_ENUM_NAME(CallSite_klass);
if (EnableMethodHandles) { initialize_wk_klasses_until(jsr292_group_start, scan, CHECK);
initialize_wk_klasses_through(meth_group_end, scan, CHECK);
}
if (_well_known_klasses[meth_group_start] == NULL) {
// Skip the rest of the method handle classes, if MethodHandle is not loaded.
scan = WKID(meth_group_end+1);
}
WKID indy_group_start = WK_KLASS_ENUM_NAME(Linkage_klass);
WKID indy_group_end = WK_KLASS_ENUM_NAME(CallSite_klass);
initialize_wk_klasses_until(indy_group_start, scan, CHECK);
if (EnableInvokeDynamic) { if (EnableInvokeDynamic) {
initialize_wk_klasses_through(indy_group_end, scan, CHECK); initialize_wk_klasses_through(jsr292_group_end, scan, CHECK);
} } else {
if (_well_known_klasses[indy_group_start] == NULL) { // Skip the JSR 292 classes, if not enabled.
// Skip the rest of the dynamic typing classes, if Linkage is not loaded. scan = WKID(jsr292_group_end + 1);
scan = WKID(indy_group_end+1);
} }
initialize_wk_klasses_until(WKID_LIMIT, scan, CHECK); initialize_wk_klasses_until(WKID_LIMIT, scan, CHECK);
@ -2407,7 +2397,7 @@ methodOop SystemDictionary::find_method_handle_invoke(Symbol* name,
Symbol* signature, Symbol* signature,
KlassHandle accessing_klass, KlassHandle accessing_klass,
TRAPS) { TRAPS) {
if (!EnableMethodHandles) return NULL; if (!EnableInvokeDynamic) return NULL;
vmSymbols::SID name_id = vmSymbols::find_sid(name); vmSymbols::SID name_id = vmSymbols::find_sid(name);
assert(name_id != vmSymbols::NO_SID, "must be a known name"); assert(name_id != vmSymbols::NO_SID, "must be a known name");
unsigned int hash = invoke_method_table()->compute_hash(signature, name_id); unsigned int hash = invoke_method_table()->compute_hash(signature, name_id);

View File

@ -207,7 +207,7 @@ class SystemDictionary : AllStatic {
enum InitOption { enum InitOption {
Pre, // preloaded; error if not present Pre, // preloaded; error if not present
Pre_JSR292, // preloaded if EnableMethodHandles Pre_JSR292, // preloaded if EnableInvokeDynamic
// Order is significant. Options before this point require resolve_or_fail. // Order is significant. Options before this point require resolve_or_fail.
// Options after this point will use resolve_or_null instead. // Options after this point will use resolve_or_null instead.

View File

@ -28,6 +28,7 @@
#include "code/nmethod.hpp" #include "code/nmethod.hpp"
#include "code/scopeDesc.hpp" #include "code/scopeDesc.hpp"
#include "compiler/abstractCompiler.hpp" #include "compiler/abstractCompiler.hpp"
#include "compiler/compileBroker.hpp"
#include "compiler/compileLog.hpp" #include "compiler/compileLog.hpp"
#include "compiler/compilerOracle.hpp" #include "compiler/compilerOracle.hpp"
#include "compiler/disassembler.hpp" #include "compiler/disassembler.hpp"
@ -469,6 +470,7 @@ void nmethod::init_defaults() {
nmethod* nmethod::new_native_nmethod(methodHandle method, nmethod* nmethod::new_native_nmethod(methodHandle method,
int compile_id,
CodeBuffer *code_buffer, CodeBuffer *code_buffer,
int vep_offset, int vep_offset,
int frame_complete, int frame_complete,
@ -485,7 +487,7 @@ nmethod* nmethod::new_native_nmethod(methodHandle method,
offsets.set_value(CodeOffsets::Verified_Entry, vep_offset); offsets.set_value(CodeOffsets::Verified_Entry, vep_offset);
offsets.set_value(CodeOffsets::Frame_Complete, frame_complete); offsets.set_value(CodeOffsets::Frame_Complete, frame_complete);
nm = new (native_nmethod_size) nm = new (native_nmethod_size)
nmethod(method(), native_nmethod_size, &offsets, nmethod(method(), native_nmethod_size, compile_id, &offsets,
code_buffer, frame_size, code_buffer, frame_size,
basic_lock_owner_sp_offset, basic_lock_sp_offset, basic_lock_owner_sp_offset, basic_lock_sp_offset,
oop_maps); oop_maps);
@ -610,6 +612,7 @@ nmethod* nmethod::new_nmethod(methodHandle method,
nmethod::nmethod( nmethod::nmethod(
methodOop method, methodOop method,
int nmethod_size, int nmethod_size,
int compile_id,
CodeOffsets* offsets, CodeOffsets* offsets,
CodeBuffer* code_buffer, CodeBuffer* code_buffer,
int frame_size, int frame_size,
@ -644,7 +647,7 @@ nmethod::nmethod(
_handler_table_offset = _dependencies_offset; _handler_table_offset = _dependencies_offset;
_nul_chk_table_offset = _handler_table_offset; _nul_chk_table_offset = _handler_table_offset;
_nmethod_end_offset = _nul_chk_table_offset; _nmethod_end_offset = _nul_chk_table_offset;
_compile_id = 0; // default _compile_id = compile_id;
_comp_level = CompLevel_none; _comp_level = CompLevel_none;
_entry_point = code_begin() + offsets->value(CodeOffsets::Entry); _entry_point = code_begin() + offsets->value(CodeOffsets::Entry);
_verified_entry_point = code_begin() + offsets->value(CodeOffsets::Verified_Entry); _verified_entry_point = code_begin() + offsets->value(CodeOffsets::Verified_Entry);
@ -930,72 +933,11 @@ void nmethod::log_new_nmethod() const {
#undef LOG_OFFSET #undef LOG_OFFSET
void nmethod::print_compilation(outputStream *st, const char *method_name, const char *title,
methodOop method, bool is_blocking, int compile_id, int bci, int comp_level) {
bool is_synchronized = false, has_xhandler = false, is_native = false;
int code_size = -1;
if (method != NULL) {
is_synchronized = method->is_synchronized();
has_xhandler = method->has_exception_handler();
is_native = method->is_native();
code_size = method->code_size();
}
// print compilation number
st->print("%7d %3d", (int)tty->time_stamp().milliseconds(), compile_id);
// print method attributes
const bool is_osr = bci != InvocationEntryBci;
const char blocking_char = is_blocking ? 'b' : ' ';
const char compile_type = is_osr ? '%' : ' ';
const char sync_char = is_synchronized ? 's' : ' ';
const char exception_char = has_xhandler ? '!' : ' ';
const char native_char = is_native ? 'n' : ' ';
st->print("%c%c%c%c%c ", compile_type, sync_char, exception_char, blocking_char, native_char);
if (TieredCompilation) {
st->print("%d ", comp_level);
}
// print optional title
bool do_nl = false;
if (title != NULL) {
int tlen = (int) strlen(title);
bool do_nl = false;
if (tlen > 0 && title[tlen-1] == '\n') { tlen--; do_nl = true; }
st->print("%.*s", tlen, title);
} else {
do_nl = true;
}
// print method name string if given
if (method_name != NULL) {
st->print(method_name);
} else {
// otherwise as the method to print itself
if (method != NULL && !Universe::heap()->is_gc_active()) {
method->print_short_name(st);
} else {
st->print("(method)");
}
}
if (method != NULL) {
// print osr_bci if any
if (is_osr) st->print(" @ %d", bci);
// print method size
st->print(" (%d bytes)", code_size);
}
if (do_nl) st->cr();
}
// Print out more verbose output usually for a newly created nmethod. // Print out more verbose output usually for a newly created nmethod.
void nmethod::print_on(outputStream* st, const char* title) const { void nmethod::print_on(outputStream* st, const char* msg) const {
if (st != NULL) { if (st != NULL) {
ttyLocker ttyl; ttyLocker ttyl;
print_compilation(st, /*method_name*/NULL, title, CompileTask::print_compilation(st, this, msg);
method(), /*is_blocking*/false,
compile_id(),
is_osr_method() ? osr_entry_bci() : InvocationEntryBci,
comp_level());
if (WizardMode) st->print(" (" INTPTR_FORMAT ")", this); if (WizardMode) st->print(" (" INTPTR_FORMAT ")", this);
} }
} }
@ -1309,8 +1251,7 @@ void nmethod::log_state_change() const {
} }
} }
if (PrintCompilation && _state != unloaded) { if (PrintCompilation && _state != unloaded) {
print_on(tty, _state == zombie ? "made zombie " : "made not entrant "); print_on(tty, _state == zombie ? "made zombie" : "made not entrant");
tty->cr();
} }
} }
@ -1816,7 +1757,7 @@ bool nmethod::test_set_oops_do_mark() {
break; break;
} }
// Mark was clear when we first saw this guy. // Mark was clear when we first saw this guy.
NOT_PRODUCT(if (TraceScavenge) print_on(tty, "oops_do, mark\n")); NOT_PRODUCT(if (TraceScavenge) print_on(tty, "oops_do, mark"));
return false; return false;
} }
} }
@ -1841,7 +1782,7 @@ void nmethod::oops_do_marking_epilogue() {
nmethod* next = cur->_oops_do_mark_link; nmethod* next = cur->_oops_do_mark_link;
cur->_oops_do_mark_link = NULL; cur->_oops_do_mark_link = NULL;
cur->fix_oop_relocations(); cur->fix_oop_relocations();
NOT_PRODUCT(if (TraceScavenge) cur->print_on(tty, "oops_do, unmark\n")); NOT_PRODUCT(if (TraceScavenge) cur->print_on(tty, "oops_do, unmark"));
cur = next; cur = next;
} }
void* required = _oops_do_mark_nmethods; void* required = _oops_do_mark_nmethods;
@ -2396,7 +2337,7 @@ void nmethod::print() const {
ResourceMark rm; ResourceMark rm;
ttyLocker ttyl; // keep the following output all in one block ttyLocker ttyl; // keep the following output all in one block
tty->print("Compiled "); tty->print("Compiled method ");
if (is_compiled_by_c1()) { if (is_compiled_by_c1()) {
tty->print("(c1) "); tty->print("(c1) ");
@ -2408,8 +2349,8 @@ void nmethod::print() const {
tty->print("(nm) "); tty->print("(nm) ");
} }
print_on(tty, "nmethod"); print_on(tty, NULL);
tty->cr();
if (WizardMode) { if (WizardMode) {
tty->print("((nmethod*) "INTPTR_FORMAT ") ", this); tty->print("((nmethod*) "INTPTR_FORMAT ") ", this);
tty->print(" for method " INTPTR_FORMAT , (address)method()); tty->print(" for method " INTPTR_FORMAT , (address)method());
@ -2796,7 +2737,8 @@ void nmethod::print_code_comment_on(outputStream* st, int column, u_char* begin,
#ifndef PRODUCT #ifndef PRODUCT
void nmethod::print_value_on(outputStream* st) const { void nmethod::print_value_on(outputStream* st) const {
print_on(st, "nmethod"); st->print("nmethod");
print_on(st, NULL);
} }
void nmethod::print_calls(outputStream* st) { void nmethod::print_calls(outputStream* st) {

View File

@ -229,6 +229,7 @@ class nmethod : public CodeBlob {
// For native wrappers // For native wrappers
nmethod(methodOop method, nmethod(methodOop method,
int nmethod_size, int nmethod_size,
int compile_id,
CodeOffsets* offsets, CodeOffsets* offsets,
CodeBuffer *code_buffer, CodeBuffer *code_buffer,
int frame_size, int frame_size,
@ -299,6 +300,7 @@ class nmethod : public CodeBlob {
int comp_level); int comp_level);
static nmethod* new_native_nmethod(methodHandle method, static nmethod* new_native_nmethod(methodHandle method,
int compile_id,
CodeBuffer *code_buffer, CodeBuffer *code_buffer,
int vep_offset, int vep_offset,
int frame_complete, int frame_complete,
@ -500,8 +502,8 @@ public:
address continuation_for_implicit_exception(address pc); address continuation_for_implicit_exception(address pc);
// On-stack replacement support // On-stack replacement support
int osr_entry_bci() const { assert(_entry_bci != InvocationEntryBci, "wrong kind of nmethod"); return _entry_bci; } int osr_entry_bci() const { assert(is_osr_method(), "wrong kind of nmethod"); return _entry_bci; }
address osr_entry() const { assert(_entry_bci != InvocationEntryBci, "wrong kind of nmethod"); return _osr_entry_point; } address osr_entry() const { assert(is_osr_method(), "wrong kind of nmethod"); return _osr_entry_point; }
void invalidate_osr_method(); void invalidate_osr_method();
nmethod* osr_link() const { return _osr_link; } nmethod* osr_link() const { return _osr_link; }
void set_osr_link(nmethod *n) { _osr_link = n; } void set_osr_link(nmethod *n) { _osr_link = n; }
@ -608,10 +610,6 @@ public:
void verify_scopes(); void verify_scopes();
void verify_interrupt_point(address interrupt_point); void verify_interrupt_point(address interrupt_point);
// print compilation helper
static void print_compilation(outputStream *st, const char *method_name, const char *title,
methodOop method, bool is_blocking, int compile_id, int bci, int comp_level);
// printing support // printing support
void print() const; void print() const;
void print_code(); void print_code();
@ -627,7 +625,7 @@ public:
// need to re-define this from CodeBlob else the overload hides it // need to re-define this from CodeBlob else the overload hides it
virtual void print_on(outputStream* st) const { CodeBlob::print_on(st); } virtual void print_on(outputStream* st) const { CodeBlob::print_on(st); }
void print_on(outputStream* st, const char* title) const; void print_on(outputStream* st, const char* msg) const;
// Logging // Logging
void log_identity(xmlStream* log) const; void log_identity(xmlStream* log) const;

View File

@ -268,11 +268,6 @@ void CompileTask::print() {
} }
void CompileTask::print_compilation(outputStream *st, methodOop method, char* method_name) {
nmethod::print_compilation(st, method_name,/*title*/ NULL, method,
is_blocking(), compile_id(), osr_bci(), comp_level());
}
// ------------------------------------------------------------------ // ------------------------------------------------------------------
// CompileTask::print_line_on_error // CompileTask::print_line_on_error
// //
@ -284,32 +279,116 @@ void CompileTask::print_compilation(outputStream *st, methodOop method, char* me
// Otherwise it's the same as CompileTask::print_line() // Otherwise it's the same as CompileTask::print_line()
// //
void CompileTask::print_line_on_error(outputStream* st, char* buf, int buflen) { void CompileTask::print_line_on_error(outputStream* st, char* buf, int buflen) {
methodOop method = (methodOop)JNIHandles::resolve(_method);
// print compiler name // print compiler name
st->print("%s:", CompileBroker::compiler(comp_level())->name()); st->print("%s:", CompileBroker::compiler(comp_level())->name());
char* method_name = NULL; print_compilation(st);
if (method != NULL) {
method_name = method->name_and_sig_as_C_string(buf, buflen);
}
print_compilation(st, method, method_name);
} }
// ------------------------------------------------------------------ // ------------------------------------------------------------------
// CompileTask::print_line // CompileTask::print_line
void CompileTask::print_line() { void CompileTask::print_line() {
Thread *thread = Thread::current();
methodHandle method(thread,
(methodOop)JNIHandles::resolve(method_handle()));
ResourceMark rm(thread);
ttyLocker ttyl; // keep the following output all in one block ttyLocker ttyl; // keep the following output all in one block
// print compiler name if requested // print compiler name if requested
if (CIPrintCompilerName) tty->print("%s:", CompileBroker::compiler(comp_level())->name()); if (CIPrintCompilerName) tty->print("%s:", CompileBroker::compiler(comp_level())->name());
print_compilation(tty, method(), NULL); print_compilation();
} }
// ------------------------------------------------------------------
// CompileTask::print_compilation_impl
void CompileTask::print_compilation_impl(outputStream* st, methodOop method, int compile_id, int comp_level, bool is_osr_method, int osr_bci, bool is_blocking, const char* msg) {
st->print("%7d ", (int) st->time_stamp().milliseconds()); // print timestamp
st->print("%4d ", compile_id); // print compilation number
// method attributes
const char compile_type = is_osr_method ? '%' : ' ';
const char sync_char = method->is_synchronized() ? 's' : ' ';
const char exception_char = method->has_exception_handler() ? '!' : ' ';
const char blocking_char = is_blocking ? 'b' : ' ';
const char native_char = method->is_native() ? 'n' : ' ';
// print method attributes
st->print("%c%c%c%c%c ", compile_type, sync_char, exception_char, blocking_char, native_char);
if (TieredCompilation) {
if (comp_level != -1) st->print("%d ", comp_level);
else st->print("- ");
}
st->print(" "); // more indent
method->print_short_name(st);
if (is_osr_method) {
st->print(" @ %d", osr_bci);
}
st->print(" (%d bytes)", method->code_size());
if (msg != NULL) {
st->print(" %s", msg);
}
st->cr();
}
// ------------------------------------------------------------------
// CompileTask::print_inlining
void CompileTask::print_inlining(outputStream* st, ciMethod* method, int inline_level, int bci, const char* msg) {
// 1234567
st->print(" "); // print timestamp
// 1234
st->print(" "); // print compilation number
// method attributes
const char sync_char = method->is_synchronized() ? 's' : ' ';
const char exception_char = method->has_exception_handlers() ? '!' : ' ';
const char monitors_char = method->has_monitor_bytecodes() ? 'm' : ' ';
// print method attributes
st->print(" %c%c%c ", sync_char, exception_char, monitors_char);
if (TieredCompilation) {
st->print(" ");
}
st->print(" "); // more indent
st->print(" "); // initial inlining indent
for (int i = 0; i < inline_level; i++) st->print(" ");
st->print("@ %d ", bci); // print bci
method->print_short_name(st);
st->print(" (%d bytes)", method->code_size());
if (msg != NULL) {
st->print(" %s", msg);
}
st->cr();
}
// ------------------------------------------------------------------
// CompileTask::print_inline_indent
void CompileTask::print_inline_indent(int inline_level, outputStream* st) {
// 1234567
st->print(" "); // print timestamp
// 1234
st->print(" "); // print compilation number
// %s!bn
st->print(" "); // print method attributes
if (TieredCompilation) {
st->print(" ");
}
st->print(" "); // more indent
st->print(" "); // initial inlining indent
for (int i = 0; i < inline_level; i++) st->print(" ");
}
// ------------------------------------------------------------------
// CompileTask::print_compilation
void CompileTask::print_compilation(outputStream* st) {
oop rem = JNIHandles::resolve(method_handle());
assert(rem != NULL && rem->is_method(), "must be");
methodOop method = (methodOop) rem;
bool is_osr_method = osr_bci() != InvocationEntryBci;
print_compilation_impl(st, method, compile_id(), comp_level(), is_osr_method, osr_bci(), is_blocking());
}
// ------------------------------------------------------------------ // ------------------------------------------------------------------
// CompileTask::log_task // CompileTask::log_task
void CompileTask::log_task(xmlStream* log) { void CompileTask::log_task(xmlStream* log) {
@ -874,6 +953,14 @@ void CompileBroker::compile_method_base(methodHandle method,
return; return;
} }
#ifndef PRODUCT
if (osr_bci != -1 && !FLAG_IS_DEFAULT(OSROnlyBCI)) {
if ((OSROnlyBCI > 0) ? (OSROnlyBCI != osr_bci) : (-OSROnlyBCI == osr_bci)) {
// Positive OSROnlyBCI means only compile that bci. Negative means don't compile that BCI.
return;
}
}
#endif
// If this method is already in the compile queue, then // If this method is already in the compile queue, then
// we do not block the current thread. // we do not block the current thread.
@ -1078,7 +1165,13 @@ nmethod* CompileBroker::compile_method(methodHandle method, int osr_bci,
// do the compilation // do the compilation
if (method->is_native()) { if (method->is_native()) {
if (!PreferInterpreterNativeStubs) { if (!PreferInterpreterNativeStubs) {
(void) AdapterHandlerLibrary::create_native_wrapper(method); // Acquire our lock.
int compile_id;
{
MutexLocker locker(MethodCompileQueue_lock, THREAD);
compile_id = assign_compile_id(method, standard_entry_bci);
}
(void) AdapterHandlerLibrary::create_native_wrapper(method, compile_id);
} else { } else {
return NULL; return NULL;
} }
@ -1186,7 +1279,6 @@ uint CompileBroker::assign_compile_id(methodHandle method, int osr_bci) {
assert(MethodCompileQueue_lock->owner() == Thread::current(), assert(MethodCompileQueue_lock->owner() == Thread::current(),
"must hold the compilation queue lock"); "must hold the compilation queue lock");
bool is_osr = (osr_bci != standard_entry_bci); bool is_osr = (osr_bci != standard_entry_bci);
assert(!method->is_native(), "no longer compile natives");
uint id; uint id;
if (CICountOSR && is_osr) { if (CICountOSR && is_osr) {
id = ++_osr_compilation_id; id = ++_osr_compilation_id;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -56,7 +56,6 @@ class CompileTask : public CHeapObj {
int _hot_count; // information about its invocation counter int _hot_count; // information about its invocation counter
const char* _comment; // more info about the task const char* _comment; // more info about the task
void print_compilation(outputStream *st, methodOop method, char* method_name);
public: public:
CompileTask() { CompileTask() {
_lock = new Monitor(Mutex::nonleaf+2, "CompileTaskLock"); _lock = new Monitor(Mutex::nonleaf+2, "CompileTaskLock");
@ -96,10 +95,26 @@ class CompileTask : public CHeapObj {
CompileTask* prev() const { return _prev; } CompileTask* prev() const { return _prev; }
void set_prev(CompileTask* prev) { _prev = prev; } void set_prev(CompileTask* prev) { _prev = prev; }
private:
static void print_compilation_impl(outputStream* st, methodOop method, int compile_id, int comp_level, bool is_osr_method = false, int osr_bci = -1, bool is_blocking = false, const char* msg = NULL);
public:
void print_compilation(outputStream* st = tty);
static void print_compilation(outputStream* st, const nmethod* nm, const char* msg = NULL) {
print_compilation_impl(st, nm->method(), nm->compile_id(), nm->comp_level(), nm->is_osr_method(), nm->is_osr_method() ? nm->osr_entry_bci() : -1, /*is_blocking*/ false, msg);
}
static void print_inlining(outputStream* st, ciMethod* method, int inline_level, int bci, const char* msg = NULL);
static void print_inlining(ciMethod* method, int inline_level, int bci, const char* msg = NULL) {
print_inlining(tty, method, inline_level, bci, msg);
}
static void print_inline_indent(int inline_level, outputStream* st = tty);
void print(); void print();
void print_line(); void print_line();
void print_line_on_error(outputStream* st, char* buf, int buflen); void print_line_on_error(outputStream* st, char* buf, int buflen);
void log_task(xmlStream* log); void log_task(xmlStream* log);
void log_task_queued(); void log_task_queued();
void log_task_start(CompileLog* log); void log_task_start(CompileLog* log);

View File

@ -2383,17 +2383,6 @@ run:
} }
DEFAULT: DEFAULT:
#ifdef ZERO
// Some zero configurations use the C++ interpreter as a
// fallback interpreter and have support for platform
// specific fast bytecodes which aren't supported here, so
// redispatch to the equivalent non-fast bytecode when they
// are encountered.
if (Bytecodes::is_defined((Bytecodes::Code)opcode)) {
opcode = (jubyte)Bytecodes::java_code((Bytecodes::Code)opcode);
goto opcode_switch;
}
#endif
fatal(err_msg("Unimplemented opcode %d = %s", opcode, fatal(err_msg("Unimplemented opcode %d = %s", opcode,
Bytecodes::name((Bytecodes::Code)opcode))); Bytecodes::name((Bytecodes::Code)opcode)));
goto finish; goto finish;

View File

@ -176,7 +176,7 @@ void LinkResolver::resolve_klass_no_update(KlassHandle& result, constantPoolHand
void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) { void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) {
methodOop result_oop = klass->uncached_lookup_method(name, signature); methodOop result_oop = klass->uncached_lookup_method(name, signature);
if (EnableMethodHandles && result_oop != NULL) { if (EnableInvokeDynamic && result_oop != NULL) {
switch (result_oop->intrinsic_id()) { switch (result_oop->intrinsic_id()) {
case vmIntrinsics::_invokeExact: case vmIntrinsics::_invokeExact:
case vmIntrinsics::_invokeGeneric: case vmIntrinsics::_invokeGeneric:
@ -214,7 +214,7 @@ void LinkResolver::lookup_implicit_method(methodHandle& result,
KlassHandle klass, Symbol* name, Symbol* signature, KlassHandle klass, Symbol* name, Symbol* signature,
KlassHandle current_klass, KlassHandle current_klass,
TRAPS) { TRAPS) {
if (EnableMethodHandles && if (EnableInvokeDynamic &&
klass() == SystemDictionary::MethodHandle_klass() && klass() == SystemDictionary::MethodHandle_klass() &&
methodOopDesc::is_method_handle_invoke_name(name)) { methodOopDesc::is_method_handle_invoke_name(name)) {
if (!THREAD->is_Compiler_thread() && !MethodHandles::enabled()) { if (!THREAD->is_Compiler_thread() && !MethodHandles::enabled()) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -80,16 +80,7 @@ public:
oop obj = *p; oop obj = *p;
if (obj->klass() == SystemDictionary::String_klass()) { if (obj->klass() == SystemDictionary::String_klass()) {
int hash; int hash = java_lang_String::hash_string(obj);
typeArrayOop value = java_lang_String::value(obj);
int length = java_lang_String::length(obj);
if (length == 0) {
hash = 0;
} else {
int offset = java_lang_String::offset(obj);
jchar* s = value->char_at_addr(offset);
hash = StringTable::hash_string(s, length);
}
obj->int_field_put(hash_offset, hash); obj->int_field_put(hash_offset, hash);
} }
} }

View File

@ -286,7 +286,7 @@ void constantPoolKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
assert(obj->is_constantPool(), "should be constant pool"); assert(obj->is_constantPool(), "should be constant pool");
constantPoolOop cp = (constantPoolOop) obj; constantPoolOop cp = (constantPoolOop) obj;
if (cp->tags() != NULL && if (cp->tags() != NULL &&
(!JavaObjectsInPerm || (AnonymousClasses && cp->has_pseudo_string()))) { (!JavaObjectsInPerm || (EnableInvokeDynamic && cp->has_pseudo_string()))) {
for (int i = 1; i < cp->length(); ++i) { for (int i = 1; i < cp->length(); ++i) {
if (cp->tag_at(i).is_string()) { if (cp->tag_at(i).is_string()) {
oop* base = cp->obj_at_addr_raw(i); oop* base = cp->obj_at_addr_raw(i);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -429,7 +429,7 @@ class constantPoolOopDesc : public oopDesc {
// A "pseudo-string" is an non-string oop that has found is way into // A "pseudo-string" is an non-string oop that has found is way into
// a String entry. // a String entry.
// Under AnonymousClasses this can happen if the user patches a live // Under EnableInvokeDynamic this can happen if the user patches a live
// object into a CONSTANT_String entry of an anonymous class. // object into a CONSTANT_String entry of an anonymous class.
// Method oops internally created for method handles may also // Method oops internally created for method handles may also
// use pseudo-strings to link themselves to related metaobjects. // use pseudo-strings to link themselves to related metaobjects.
@ -442,7 +442,7 @@ class constantPoolOopDesc : public oopDesc {
} }
void pseudo_string_at_put(int which, oop x) { void pseudo_string_at_put(int which, oop x) {
assert(AnonymousClasses, ""); assert(EnableInvokeDynamic, "");
set_pseudo_string(); // mark header set_pseudo_string(); // mark header
assert(tag_at(which).is_string() || tag_at(which).is_unresolved_string(), "Corrupted constant pool"); assert(tag_at(which).is_string() || tag_at(which).is_unresolved_string(), "Corrupted constant pool");
string_at_put(which, x); // this works just fine string_at_put(which, x); // this works just fine

View File

@ -2337,7 +2337,7 @@ void instanceKlass::oop_print_on(oop obj, outputStream* st) {
st->print_cr(BULLET"fake entry for oop_size: %d", java_lang_Class::oop_size(obj)); st->print_cr(BULLET"fake entry for oop_size: %d", java_lang_Class::oop_size(obj));
st->print_cr(BULLET"fake entry for static_oop_field_count: %d", java_lang_Class::static_oop_field_count(obj)); st->print_cr(BULLET"fake entry for static_oop_field_count: %d", java_lang_Class::static_oop_field_count(obj));
klassOop real_klass = java_lang_Class::as_klassOop(obj); klassOop real_klass = java_lang_Class::as_klassOop(obj);
if (real_klass && real_klass->klass_part()->oop_is_instance()) { if (real_klass != NULL && real_klass->klass_part()->oop_is_instance()) {
instanceKlass::cast(real_klass)->do_local_static_fields(&print_field); instanceKlass::cast(real_klass)->do_local_static_fields(&print_field);
} }
} else if (as_klassOop() == SystemDictionary::MethodType_klass()) { } else if (as_klassOop() == SystemDictionary::MethodType_klass()) {

View File

@ -182,7 +182,7 @@ class instanceKlass: public Klass {
// Protection domain. // Protection domain.
oop _protection_domain; oop _protection_domain;
// Host class, which grants its access privileges to this class also. // Host class, which grants its access privileges to this class also.
// This is only non-null for an anonymous class (AnonymousClasses enabled). // This is only non-null for an anonymous class (JSR 292 enabled).
// The host class is either named, or a previously loaded anonymous class. // The host class is either named, or a previously loaded anonymous class.
klassOop _host_klass; klassOop _host_klass;
// Class signers. // Class signers.

View File

@ -36,6 +36,8 @@
class instanceMirrorKlass: public instanceKlass { class instanceMirrorKlass: public instanceKlass {
friend class VMStructs;
private: private:
static int _offset_of_static_fields; static int _offset_of_static_fields;

View File

@ -500,7 +500,7 @@ const char* Klass::external_name() const {
if (oop_is_instance()) { if (oop_is_instance()) {
instanceKlass* ik = (instanceKlass*) this; instanceKlass* ik = (instanceKlass*) this;
if (ik->is_anonymous()) { if (ik->is_anonymous()) {
assert(AnonymousClasses, ""); assert(EnableInvokeDynamic, "");
intptr_t hash = ik->java_mirror()->identity_hash(); intptr_t hash = ik->java_mirror()->identity_hash();
char hash_buf[40]; char hash_buf[40];
sprintf(hash_buf, "/" UINTX_FORMAT, (uintx)hash); sprintf(hash_buf, "/" UINTX_FORMAT, (uintx)hash);

View File

@ -607,7 +607,7 @@ class methodOopDesc : public oopDesc {
// method handles want to be able to push a few extra values (e.g., a bound receiver), and // method handles want to be able to push a few extra values (e.g., a bound receiver), and
// invokedynamic sometimes needs to push a bootstrap method, call site, and arglist, // invokedynamic sometimes needs to push a bootstrap method, call site, and arglist,
// all without checking for a stack overflow // all without checking for a stack overflow
static int extra_stack_entries() { return (EnableMethodHandles ? (int)MethodHandlePushLimit : 0) + (EnableInvokeDynamic ? 3 : 0); } static int extra_stack_entries() { return EnableInvokeDynamic ? (int) MethodHandlePushLimit + 3 : 0; }
static int extra_stack_words(); // = extra_stack_entries() * Interpreter::stackElementSize() static int extra_stack_words(); // = extra_stack_entries() * Interpreter::stackElementSize()
// RedefineClasses() support: // RedefineClasses() support:

View File

@ -25,6 +25,7 @@
#include "precompiled.hpp" #include "precompiled.hpp"
#include "classfile/systemDictionary.hpp" #include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp" #include "classfile/vmSymbols.hpp"
#include "compiler/compileBroker.hpp"
#include "compiler/compileLog.hpp" #include "compiler/compileLog.hpp"
#include "interpreter/linkResolver.hpp" #include "interpreter/linkResolver.hpp"
#include "oops/objArrayKlass.hpp" #include "oops/objArrayKlass.hpp"
@ -75,13 +76,6 @@ InlineTree::InlineTree(Compile* c, ciMethod* callee_method, JVMState* caller_jvm
assert(!UseOldInlining, "do not use for old stuff"); assert(!UseOldInlining, "do not use for old stuff");
} }
static void print_indent(int depth) {
tty->print(" ");
for (int i = depth; i != 0; --i) tty->print(" ");
}
static bool is_init_with_ea(ciMethod* callee_method, static bool is_init_with_ea(ciMethod* callee_method,
ciMethod* caller_method, Compile* C) { ciMethod* caller_method, Compile* C) {
// True when EA is ON and a java constructor is called or // True when EA is ON and a java constructor is called or
@ -100,7 +94,7 @@ const char* InlineTree::shouldInline(ciMethod* callee_method, ciMethod* caller_m
if(callee_method->should_inline()) { if(callee_method->should_inline()) {
*wci_result = *(WarmCallInfo::always_hot()); *wci_result = *(WarmCallInfo::always_hot());
if (PrintInlining && Verbose) { if (PrintInlining && Verbose) {
print_indent(inline_depth()); CompileTask::print_inline_indent(inline_depth());
tty->print_cr("Inlined method is hot: "); tty->print_cr("Inlined method is hot: ");
} }
return NULL; return NULL;
@ -116,7 +110,7 @@ const char* InlineTree::shouldInline(ciMethod* callee_method, ciMethod* caller_m
size < InlineThrowMaxSize ) { size < InlineThrowMaxSize ) {
wci_result->set_profit(wci_result->profit() * 100); wci_result->set_profit(wci_result->profit() * 100);
if (PrintInlining && Verbose) { if (PrintInlining && Verbose) {
print_indent(inline_depth()); CompileTask::print_inline_indent(inline_depth());
tty->print_cr("Inlined method with many throws (throws=%d):", callee_method->interpreter_throwout_count()); tty->print_cr("Inlined method with many throws (throws=%d):", callee_method->interpreter_throwout_count());
} }
return NULL; return NULL;
@ -138,9 +132,9 @@ const char* InlineTree::shouldInline(ciMethod* callee_method, ciMethod* caller_m
max_size = C->freq_inline_size(); max_size = C->freq_inline_size();
if (size <= max_size && TraceFrequencyInlining) { if (size <= max_size && TraceFrequencyInlining) {
print_indent(inline_depth()); CompileTask::print_inline_indent(inline_depth());
tty->print_cr("Inlined frequent method (freq=%d count=%d):", freq, call_site_count); tty->print_cr("Inlined frequent method (freq=%d count=%d):", freq, call_site_count);
print_indent(inline_depth()); CompileTask::print_inline_indent(inline_depth());
callee_method->print(); callee_method->print();
tty->cr(); tty->cr();
} }
@ -315,8 +309,25 @@ const char* InlineTree::try_to_inline(ciMethod* callee_method, ciMethod* caller_
if( inline_depth() > MaxInlineLevel ) { if( inline_depth() > MaxInlineLevel ) {
return "inlining too deep"; return "inlining too deep";
} }
if( method() == callee_method &&
inline_depth() > MaxRecursiveInlineLevel ) { // We need to detect recursive inlining of method handle targets: if
// the current method is a method handle adapter and one of the
// callers is the same method as the callee, we bail out if
// MaxRecursiveInlineLevel is hit.
if (method()->is_method_handle_adapter()) {
JVMState* jvms = caller_jvms();
int inline_level = 0;
while (jvms != NULL && jvms->has_method()) {
if (jvms->method() == callee_method) {
inline_level++;
if (inline_level > MaxRecursiveInlineLevel)
return "recursively inlining too deep";
}
jvms = jvms->caller();
}
}
if (method() == callee_method && inline_depth() > MaxRecursiveInlineLevel) {
return "recursively inlining too deep"; return "recursively inlining too deep";
} }
@ -368,18 +379,14 @@ bool pass_initial_checks(ciMethod* caller_method, int caller_bci, ciMethod* call
#ifndef PRODUCT #ifndef PRODUCT
//------------------------------print_inlining--------------------------------- //------------------------------print_inlining---------------------------------
// Really, the failure_msg can be a success message also. // Really, the failure_msg can be a success message also.
void InlineTree::print_inlining(ciMethod *callee_method, int caller_bci, const char *failure_msg) const { void InlineTree::print_inlining(ciMethod* callee_method, int caller_bci, const char* failure_msg) const {
print_indent(inline_depth()); CompileTask::print_inlining(callee_method, inline_depth(), caller_bci, failure_msg ? failure_msg : "inline");
tty->print("@ %d ", caller_bci); if (callee_method == NULL) tty->print(" callee not monotonic or profiled");
if( callee_method ) callee_method->print_short_name(); if (Verbose && callee_method) {
else tty->print(" callee not monotonic or profiled");
tty->print(" %s", (failure_msg ? failure_msg : "inline"));
if( Verbose && callee_method ) {
const InlineTree *top = this; const InlineTree *top = this;
while( top->caller_tree() != NULL ) { top = top->caller_tree(); } while( top->caller_tree() != NULL ) { top = top->caller_tree(); }
tty->print(" bcs: %d+%d invoked: %d", top->count_inline_bcs(), callee_method->code_size(), callee_method->interpreter_invocation_count()); tty->print(" bcs: %d+%d invoked: %d", top->count_inline_bcs(), callee_method->code_size(), callee_method->interpreter_invocation_count());
} }
tty->cr();
} }
#endif #endif

View File

@ -673,7 +673,7 @@ void PhaseChaitin::gather_lrg_masks( bool after_aggressive ) {
case Op_RegD: case Op_RegD:
lrg.set_num_regs(2); lrg.set_num_regs(2);
// Define platform specific register pressure // Define platform specific register pressure
#ifdef SPARC #if defined(SPARC) || defined(ARM)
lrg.set_reg_pressure(2); lrg.set_reg_pressure(2);
#elif defined(IA32) #elif defined(IA32)
if( ireg == Op_RegL ) { if( ireg == Op_RegL ) {

View File

@ -2544,6 +2544,36 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
frc.inc_inner_loop_count(); frc.inc_inner_loop_count();
} }
break; break;
case Op_LShiftI:
case Op_RShiftI:
case Op_URShiftI:
case Op_LShiftL:
case Op_RShiftL:
case Op_URShiftL:
if (Matcher::need_masked_shift_count) {
// The cpu's shift instructions don't restrict the count to the
// lower 5/6 bits. We need to do the masking ourselves.
Node* in2 = n->in(2);
juint mask = (n->bottom_type() == TypeInt::INT) ? (BitsPerInt - 1) : (BitsPerLong - 1);
const TypeInt* t = in2->find_int_type();
if (t != NULL && t->is_con()) {
juint shift = t->get_con();
if (shift > mask) { // Unsigned cmp
Compile* C = Compile::current();
n->set_req(2, ConNode::make(C, TypeInt::make(shift & mask)));
}
} else {
if (t == NULL || t->_lo < 0 || t->_hi > (int)mask) {
Compile* C = Compile::current();
Node* shift = new (C, 3) AndINode(in2, ConNode::make(C, TypeInt::make(mask)));
n->set_req(2, shift);
}
}
if (in2->outcnt() == 0) { // Remove dead node
in2->disconnect_inputs(NULL);
}
}
break;
default: default:
assert( !n->is_Call(), "" ); assert( !n->is_Call(), "" );
assert( !n->is_Mem(), "" ); assert( !n->is_Mem(), "" );

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -27,6 +27,7 @@
#include "ci/ciCallSite.hpp" #include "ci/ciCallSite.hpp"
#include "ci/ciMethodHandle.hpp" #include "ci/ciMethodHandle.hpp"
#include "classfile/vmSymbols.hpp" #include "classfile/vmSymbols.hpp"
#include "compiler/compileBroker.hpp"
#include "compiler/compileLog.hpp" #include "compiler/compileLog.hpp"
#include "interpreter/linkResolver.hpp" #include "interpreter/linkResolver.hpp"
#include "opto/addnode.hpp" #include "opto/addnode.hpp"
@ -43,17 +44,17 @@
#ifndef PRODUCT #ifndef PRODUCT
void trace_type_profile(ciMethod *method, int depth, int bci, ciMethod *prof_method, ciKlass *prof_klass, int site_count, int receiver_count) { void trace_type_profile(ciMethod *method, int depth, int bci, ciMethod *prof_method, ciKlass *prof_klass, int site_count, int receiver_count) {
if (TraceTypeProfile || PrintInlining || PrintOptoInlining) { if (TraceTypeProfile || PrintInlining || PrintOptoInlining) {
tty->print(" "); if (!PrintInlining) {
for( int i = 0; i < depth; i++ ) tty->print(" "); if (!PrintOpto && !PrintCompilation) {
if (!PrintOpto) { method->print_short_name();
method->print_short_name(); tty->cr();
tty->print(" ->"); }
CompileTask::print_inlining(prof_method, depth, bci);
} }
tty->print(" @ %d ", bci); CompileTask::print_inline_indent(depth);
prof_method->print_short_name(); tty->print(" \\-> TypeProfile (%d/%d counts) = ", receiver_count, site_count);
tty->print(" >>TypeProfile (%d/%d counts) = ", receiver_count, site_count);
prof_klass->name()->print_symbol(); prof_klass->name()->print_symbol();
tty->print_cr(" (%d bytes)", prof_method->code_size()); tty->cr();
} }
} }
#endif #endif
@ -269,13 +270,13 @@ CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index,
} }
if (miss_cg != NULL) { if (miss_cg != NULL) {
if (next_hit_cg != NULL) { if (next_hit_cg != NULL) {
NOT_PRODUCT(trace_type_profile(jvms->method(), jvms->depth(), jvms->bci(), next_receiver_method, profile.receiver(1), site_count, profile.receiver_count(1))); NOT_PRODUCT(trace_type_profile(jvms->method(), jvms->depth() - 1, jvms->bci(), next_receiver_method, profile.receiver(1), site_count, profile.receiver_count(1)));
// We don't need to record dependency on a receiver here and below. // We don't need to record dependency on a receiver here and below.
// Whenever we inline, the dependency is added by Parse::Parse(). // Whenever we inline, the dependency is added by Parse::Parse().
miss_cg = CallGenerator::for_predicted_call(profile.receiver(1), miss_cg, next_hit_cg, PROB_MAX); miss_cg = CallGenerator::for_predicted_call(profile.receiver(1), miss_cg, next_hit_cg, PROB_MAX);
} }
if (miss_cg != NULL) { if (miss_cg != NULL) {
NOT_PRODUCT(trace_type_profile(jvms->method(), jvms->depth(), jvms->bci(), receiver_method, profile.receiver(0), site_count, receiver_count)); NOT_PRODUCT(trace_type_profile(jvms->method(), jvms->depth() - 1, jvms->bci(), receiver_method, profile.receiver(0), site_count, receiver_count));
cg = CallGenerator::for_predicted_call(profile.receiver(0), miss_cg, hit_cg, profile.receiver_prob(0)); cg = CallGenerator::for_predicted_call(profile.receiver(0), miss_cg, hit_cg, profile.receiver_prob(0));
if (cg != NULL) return cg; if (cg != NULL) return cg;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -599,11 +599,35 @@ void IdealGraphPrinter::visit_node(Node *n, void *param) {
if (caller != NULL) { if (caller != NULL) {
stringStream bciStream; stringStream bciStream;
ciMethod* last = NULL;
int last_bci;
while(caller) { while(caller) {
if (caller->has_method()) {
last = caller->method();
last_bci = caller->bci();
}
bciStream.print("%d ", caller->bci()); bciStream.print("%d ", caller->bci());
caller = caller->caller(); caller = caller->caller();
} }
print_prop("bci", bciStream.as_string()); print_prop("bci", bciStream.as_string());
if (last != NULL && last->has_linenumber_table() && last_bci >= 0) {
print_prop("line", last->line_number_from_bci(last_bci));
}
}
if (node->debug_orig() != NULL) {
stringStream dorigStream;
Node* dorig = node->debug_orig();
if (dorig) {
dorigStream.print("%d ", dorig->_idx);
Node* first = dorig;
dorig = first->debug_orig();
while (dorig && dorig != first) {
dorigStream.print("%d ", dorig->_idx);
dorig = dorig->debug_orig();
}
}
print_prop("debug_orig", dorigStream.as_string());
} }
if (_chaitin && _chaitin != (PhaseChaitin *)0xdeadbeef) { if (_chaitin && _chaitin != (PhaseChaitin *)0xdeadbeef) {
@ -628,6 +652,17 @@ void IdealGraphPrinter::walk_nodes(Node *start, void *param) {
GrowableArray<Node *> nodeStack(Thread::current()->resource_area(), 0, 0, NULL); GrowableArray<Node *> nodeStack(Thread::current()->resource_area(), 0, 0, NULL);
nodeStack.push(start); nodeStack.push(start);
visited.test_set(start->_idx); visited.test_set(start->_idx);
if (C->cfg() != NULL) {
// once we have a CFG there are some nodes that aren't really
// reachable but are in the CFG so add them here.
for (uint i = 0; i < C->cfg()->_blocks.size(); i++) {
Block *b = C->cfg()->_blocks[i];
for (uint s = 0; s < b->_nodes.size(); s++) {
nodeStack.push(b->_nodes[s]);
}
}
}
while(nodeStack.length() > 0) { while(nodeStack.length() > 0) {
Node *n = nodeStack.pop(); Node *n = nodeStack.pop();
@ -686,16 +721,23 @@ void IdealGraphPrinter::print(Compile* compile, const char *name, Node *node, in
end_head(); end_head();
head(SUCCESSORS_ELEMENT); head(SUCCESSORS_ELEMENT);
for (uint s = 0; s < C->cfg()->_blocks[i]->_num_succs; s++) { for (uint s = 0; s < b->_num_succs; s++) {
begin_elem(SUCCESSOR_ELEMENT); begin_elem(SUCCESSOR_ELEMENT);
print_attr(BLOCK_NAME_PROPERTY, b->_succs[s]->_pre_order); print_attr(BLOCK_NAME_PROPERTY, b->_succs[s]->_pre_order);
end_elem(); end_elem();
} }
tail(SUCCESSORS_ELEMENT); tail(SUCCESSORS_ELEMENT);
head(NODES_ELEMENT);
for (uint s = 0; s < b->_nodes.size(); s++) {
begin_elem(NODE_ELEMENT);
print_attr(NODE_ID_PROPERTY, get_node_id(b->_nodes[s]));
end_elem();
}
tail(NODES_ELEMENT);
tail(BLOCK_ELEMENT); tail(BLOCK_ELEMENT);
} }
tail(CONTROL_FLOW_ELEMENT); tail(CONTROL_FLOW_ELEMENT);
} }
tail(GRAPH_ELEMENT); tail(GRAPH_ELEMENT);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -43,15 +43,6 @@ class ciMethod;
class IdealGraphPrinter class IdealGraphPrinter
{ {
private:
enum State
{
Invalid,
Valid,
New
};
private: private:
static const char *INDENT; static const char *INDENT;

View File

@ -42,6 +42,9 @@
#ifdef TARGET_ARCH_MODEL_zero #ifdef TARGET_ARCH_MODEL_zero
# include "adfiles/ad_zero.hpp" # include "adfiles/ad_zero.hpp"
#endif #endif
#ifdef TARGET_ARCH_MODEL_arm
# include "adfiles/ad_arm.hpp"
#endif
// Optimization - Graph Style // Optimization - Graph Style

View File

@ -25,6 +25,7 @@
#include "precompiled.hpp" #include "precompiled.hpp"
#include "classfile/systemDictionary.hpp" #include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp" #include "classfile/vmSymbols.hpp"
#include "compiler/compileBroker.hpp"
#include "compiler/compileLog.hpp" #include "compiler/compileLog.hpp"
#include "oops/objArrayKlass.hpp" #include "oops/objArrayKlass.hpp"
#include "opto/addnode.hpp" #include "opto/addnode.hpp"
@ -388,11 +389,7 @@ JVMState* LibraryIntrinsic::generate(JVMState* jvms) {
#endif #endif
if (kit.try_to_inline()) { if (kit.try_to_inline()) {
if (PrintIntrinsics || PrintInlining NOT_PRODUCT( || PrintOptoInlining) ) { if (PrintIntrinsics || PrintInlining NOT_PRODUCT( || PrintOptoInlining) ) {
tty->print("Inlining intrinsic %s%s at bci:%d in", CompileTask::print_inlining(kit.callee(), jvms->depth() - 1, kit.bci(), is_virtual() ? "(intrinsic, virtual)" : "(intrinsic)");
vmIntrinsics::name_at(intrinsic_id()),
(is_virtual() ? " (virtual)" : ""), kit.bci());
kit.caller()->print_short_name(tty);
tty->print_cr(" (%d bytes)", kit.caller()->code_size());
} }
C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_worked); C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_worked);
if (C->log()) { if (C->log()) {

View File

@ -396,16 +396,16 @@ void PhaseIdealLoop::do_peeling( IdealLoopTree *loop, Node_List &old_new ) {
// Return exact loop trip count, or 0 if not maximally unrolling // Return exact loop trip count, or 0 if not maximally unrolling
bool IdealLoopTree::policy_maximally_unroll( PhaseIdealLoop *phase ) const { bool IdealLoopTree::policy_maximally_unroll( PhaseIdealLoop *phase ) const {
CountedLoopNode *cl = _head->as_CountedLoop(); CountedLoopNode *cl = _head->as_CountedLoop();
assert( cl->is_normal_loop(), "" ); assert(cl->is_normal_loop(), "");
Node *init_n = cl->init_trip(); Node *init_n = cl->init_trip();
Node *limit_n = cl->limit(); Node *limit_n = cl->limit();
// Non-constant bounds // Non-constant bounds
if( init_n == NULL || !init_n->is_Con() || if (init_n == NULL || !init_n->is_Con() ||
limit_n == NULL || !limit_n->is_Con() || limit_n == NULL || !limit_n->is_Con() ||
// protect against stride not being a constant // protect against stride not being a constant
!cl->stride_is_con() ) { !cl->stride_is_con()) {
return false; return false;
} }
int init = init_n->get_int(); int init = init_n->get_int();
@ -428,7 +428,31 @@ bool IdealLoopTree::policy_maximally_unroll( PhaseIdealLoop *phase ) const {
uint unroll_limit = (uint)LoopUnrollLimit * 4; uint unroll_limit = (uint)LoopUnrollLimit * 4;
assert( (intx)unroll_limit == LoopUnrollLimit * 4, "LoopUnrollLimit must fit in 32bits"); assert( (intx)unroll_limit == LoopUnrollLimit * 4, "LoopUnrollLimit must fit in 32bits");
cl->set_trip_count(trip_count); cl->set_trip_count(trip_count);
if( trip_count <= unroll_limit && body_size <= unroll_limit ) { if (trip_count > unroll_limit || body_size > unroll_limit) {
return false;
}
// Currently we don't have policy to optimize one iteration loops.
// Maximally unrolling transformation is used for that:
// it is peeled and the original loop become non reachable (dead).
if (trip_count == 1)
return true;
// Do not unroll a loop with String intrinsics code.
// String intrinsics are large and have loops.
for (uint k = 0; k < _body.size(); k++) {
Node* n = _body.at(k);
switch (n->Opcode()) {
case Op_StrComp:
case Op_StrEquals:
case Op_StrIndexOf:
case Op_AryEq: {
return false;
}
} // switch
}
if (body_size <= unroll_limit) {
uint new_body_size = body_size * trip_count; uint new_body_size = body_size * trip_count;
if (new_body_size <= unroll_limit && if (new_body_size <= unroll_limit &&
body_size == new_body_size / trip_count && body_size == new_body_size / trip_count &&
@ -448,13 +472,13 @@ bool IdealLoopTree::policy_maximally_unroll( PhaseIdealLoop *phase ) const {
bool IdealLoopTree::policy_unroll( PhaseIdealLoop *phase ) const { bool IdealLoopTree::policy_unroll( PhaseIdealLoop *phase ) const {
CountedLoopNode *cl = _head->as_CountedLoop(); CountedLoopNode *cl = _head->as_CountedLoop();
assert( cl->is_normal_loop() || cl->is_main_loop(), "" ); assert(cl->is_normal_loop() || cl->is_main_loop(), "");
// protect against stride not being a constant // protect against stride not being a constant
if( !cl->stride_is_con() ) return false; if (!cl->stride_is_con()) return false;
// protect against over-unrolling // protect against over-unrolling
if( cl->trip_count() <= 1 ) return false; if (cl->trip_count() <= 1) return false;
int future_unroll_ct = cl->unrolled_count() * 2; int future_unroll_ct = cl->unrolled_count() * 2;
@ -485,21 +509,21 @@ bool IdealLoopTree::policy_unroll( PhaseIdealLoop *phase ) const {
// Non-constant bounds. // Non-constant bounds.
// Protect against over-unrolling when init or/and limit are not constant // Protect against over-unrolling when init or/and limit are not constant
// (so that trip_count's init value is maxint) but iv range is known. // (so that trip_count's init value is maxint) but iv range is known.
if( init_n == NULL || !init_n->is_Con() || if (init_n == NULL || !init_n->is_Con() ||
limit_n == NULL || !limit_n->is_Con() ) { limit_n == NULL || !limit_n->is_Con()) {
Node* phi = cl->phi(); Node* phi = cl->phi();
if( phi != NULL ) { if (phi != NULL) {
assert(phi->is_Phi() && phi->in(0) == _head, "Counted loop should have iv phi."); assert(phi->is_Phi() && phi->in(0) == _head, "Counted loop should have iv phi.");
const TypeInt* iv_type = phase->_igvn.type(phi)->is_int(); const TypeInt* iv_type = phase->_igvn.type(phi)->is_int();
int next_stride = cl->stride_con() * 2; // stride after this unroll int next_stride = cl->stride_con() * 2; // stride after this unroll
if( next_stride > 0 ) { if (next_stride > 0) {
if( iv_type->_lo + next_stride <= iv_type->_lo || // overflow if (iv_type->_lo + next_stride <= iv_type->_lo || // overflow
iv_type->_lo + next_stride > iv_type->_hi ) { iv_type->_lo + next_stride > iv_type->_hi) {
return false; // over-unrolling return false; // over-unrolling
} }
} else if( next_stride < 0 ) { } else if (next_stride < 0) {
if( iv_type->_hi + next_stride >= iv_type->_hi || // overflow if (iv_type->_hi + next_stride >= iv_type->_hi || // overflow
iv_type->_hi + next_stride < iv_type->_lo ) { iv_type->_hi + next_stride < iv_type->_lo) {
return false; // over-unrolling return false; // over-unrolling
} }
} }
@ -511,24 +535,33 @@ bool IdealLoopTree::policy_unroll( PhaseIdealLoop *phase ) const {
// Key test to unroll CaffeineMark's Logic test // Key test to unroll CaffeineMark's Logic test
int xors_in_loop = 0; int xors_in_loop = 0;
// Also count ModL, DivL and MulL which expand mightly // Also count ModL, DivL and MulL which expand mightly
for( uint k = 0; k < _body.size(); k++ ) { for (uint k = 0; k < _body.size(); k++) {
switch( _body.at(k)->Opcode() ) { Node* n = _body.at(k);
case Op_XorI: xors_in_loop++; break; // CaffeineMark's Logic test switch (n->Opcode()) {
case Op_ModL: body_size += 30; break; case Op_XorI: xors_in_loop++; break; // CaffeineMark's Logic test
case Op_DivL: body_size += 30; break; case Op_ModL: body_size += 30; break;
case Op_MulL: body_size += 10; break; case Op_DivL: body_size += 30; break;
} case Op_MulL: body_size += 10; break;
case Op_StrComp:
case Op_StrEquals:
case Op_StrIndexOf:
case Op_AryEq: {
// Do not unroll a loop with String intrinsics code.
// String intrinsics are large and have loops.
return false;
}
} // switch
} }
// Check for being too big // Check for being too big
if( body_size > (uint)LoopUnrollLimit ) { if (body_size > (uint)LoopUnrollLimit) {
if( xors_in_loop >= 4 && body_size < (uint)LoopUnrollLimit*4) return true; if (xors_in_loop >= 4 && body_size < (uint)LoopUnrollLimit*4) return true;
// Normal case: loop too big // Normal case: loop too big
return false; return false;
} }
// Check for stride being a small enough constant // Check for stride being a small enough constant
if( abs(cl->stride_con()) > (1<<3) ) return false; if (abs(cl->stride_con()) > (1<<3)) return false;
// Unroll once! (Each trip will soon do double iterations) // Unroll once! (Each trip will soon do double iterations)
return true; return true;
@ -1608,15 +1641,7 @@ bool IdealLoopTree::policy_do_remove_empty_loop( PhaseIdealLoop *phase ) {
return false; // Malformed loop return false; // Malformed loop
if (!phase->is_member(this, phase->get_ctrl(cl->loopexit()->in(CountedLoopEndNode::TestValue)))) if (!phase->is_member(this, phase->get_ctrl(cl->loopexit()->in(CountedLoopEndNode::TestValue))))
return false; // Infinite loop return false; // Infinite loop
#ifndef PRODUCT
if (PrintOpto) {
tty->print("Removing empty loop");
this->dump_head();
} else if (TraceLoopOpts) {
tty->print("Empty ");
this->dump_head();
}
#endif
#ifdef ASSERT #ifdef ASSERT
// Ensure only one phi which is the iv. // Ensure only one phi which is the iv.
Node* iv = NULL; Node* iv = NULL;
@ -1629,6 +1654,43 @@ bool IdealLoopTree::policy_do_remove_empty_loop( PhaseIdealLoop *phase ) {
} }
assert(iv == cl->phi(), "Wrong phi" ); assert(iv == cl->phi(), "Wrong phi" );
#endif #endif
// main and post loops have explicitly created zero trip guard
bool needs_guard = !cl->is_main_loop() && !cl->is_post_loop();
if (needs_guard) {
// Check for an obvious zero trip guard.
Node* inctrl = cl->in(LoopNode::EntryControl);
if (inctrl->Opcode() == Op_IfTrue) {
// The test should look like just the backedge of a CountedLoop
Node* iff = inctrl->in(0);
if (iff->is_If()) {
Node* bol = iff->in(1);
if (bol->is_Bool() && bol->as_Bool()->_test._test == cl->loopexit()->test_trip()) {
Node* cmp = bol->in(1);
if (cmp->is_Cmp() && cmp->in(1) == cl->init_trip() && cmp->in(2) == cl->limit()) {
needs_guard = false;
}
}
}
}
}
#ifndef PRODUCT
if (PrintOpto) {
tty->print("Removing empty loop with%s zero trip guard", needs_guard ? "out" : "");
this->dump_head();
} else if (TraceLoopOpts) {
tty->print("Empty with%s zero trip guard ", needs_guard ? "out" : "");
this->dump_head();
}
#endif
if (needs_guard) {
// Peel the loop to ensure there's a zero trip guard
Node_List old_new;
phase->do_peeling(this, old_new);
}
// Replace the phi at loop head with the final value of the last // Replace the phi at loop head with the final value of the last
// iteration. Then the CountedLoopEnd will collapse (backedge never // iteration. Then the CountedLoopEnd will collapse (backedge never
// taken) and all loop-invariant uses of the exit values will be correct. // taken) and all loop-invariant uses of the exit values will be correct.

View File

@ -1064,8 +1064,6 @@ bool IdealLoopTree::beautify_loops( PhaseIdealLoop *phase ) {
// Cache parts in locals for easy // Cache parts in locals for easy
PhaseIterGVN &igvn = phase->_igvn; PhaseIterGVN &igvn = phase->_igvn;
phase->C->print_method("Before beautify loops", 3);
igvn.hash_delete(_head); // Yank from hash before hacking edges igvn.hash_delete(_head); // Yank from hash before hacking edges
// Check for multiple fall-in paths. Peel off a landing pad if need be. // Check for multiple fall-in paths. Peel off a landing pad if need be.
@ -1547,6 +1545,7 @@ void PhaseIdealLoop::build_and_optimize(bool do_split_ifs, bool do_loop_pred) {
ResourceMark rm; ResourceMark rm;
int old_progress = C->major_progress(); int old_progress = C->major_progress();
uint orig_worklist_size = _igvn._worklist.size();
// Reset major-progress flag for the driver's heuristics // Reset major-progress flag for the driver's heuristics
C->clear_major_progress(); C->clear_major_progress();
@ -1610,6 +1609,7 @@ void PhaseIdealLoop::build_and_optimize(bool do_split_ifs, bool do_loop_pred) {
// Split shared headers and insert loop landing pads. // Split shared headers and insert loop landing pads.
// Do not bother doing this on the Root loop of course. // Do not bother doing this on the Root loop of course.
if( !_verify_me && !_verify_only && _ltree_root->_child ) { if( !_verify_me && !_verify_only && _ltree_root->_child ) {
C->print_method("Before beautify loops", 3);
if( _ltree_root->_child->beautify_loops( this ) ) { if( _ltree_root->_child->beautify_loops( this ) ) {
// Re-build loop tree! // Re-build loop tree!
_ltree_root->_child = NULL; _ltree_root->_child = NULL;
@ -1694,7 +1694,7 @@ void PhaseIdealLoop::build_and_optimize(bool do_split_ifs, bool do_loop_pred) {
for (int i = 0; i < old_progress; i++) for (int i = 0; i < old_progress; i++)
C->set_major_progress(); C->set_major_progress();
assert(C->unique() == unique, "verification mode made Nodes? ? ?"); assert(C->unique() == unique, "verification mode made Nodes? ? ?");
assert(_igvn._worklist.size() == 0, "shouldn't push anything"); assert(_igvn._worklist.size() == orig_worklist_size, "shouldn't push anything");
return; return;
} }

View File

@ -49,6 +49,9 @@
#ifdef TARGET_ARCH_MODEL_zero #ifdef TARGET_ARCH_MODEL_zero
# include "adfiles/ad_zero.hpp" # include "adfiles/ad_zero.hpp"
#endif #endif
#ifdef TARGET_ARCH_MODEL_arm
# include "adfiles/ad_arm.hpp"
#endif
OptoReg::Name OptoReg::c_frame_pointer; OptoReg::Name OptoReg::c_frame_pointer;

View File

@ -427,6 +427,11 @@ public:
// Do ints take an entire long register or just half? // Do ints take an entire long register or just half?
static const bool int_in_long; static const bool int_in_long;
// Do the processor's shift instructions only use the low 5/6 bits
// of the count for 32/64 bit ints? If not we need to do the masking
// ourselves.
static const bool need_masked_shift_count;
// This routine is run whenever a graph fails to match. // This routine is run whenever a graph fails to match.
// If it returns, the compiler should bailout to interpreter without error. // If it returns, the compiler should bailout to interpreter without error.
// In non-product mode, SoftMatchFailure is false to detect non-canonical // In non-product mode, SoftMatchFailure is false to detect non-canonical

View File

@ -2617,54 +2617,28 @@ Node* ClearArrayNode::clear_memory(Node* ctl, Node* mem, Node* dest,
} }
//============================================================================= //=============================================================================
// Do we match on this edge? No memory edges // Do not match memory edge.
uint StrCompNode::match_edge(uint idx) const { uint StrIntrinsicNode::match_edge(uint idx) const {
return idx == 2 || idx == 3; // StrComp (Binary str1 cnt1) (Binary str2 cnt2) return idx == 2 || idx == 3;
} }
//------------------------------Ideal------------------------------------------ //------------------------------Ideal------------------------------------------
// Return a node which is more "ideal" than the current node. Strip out // Return a node which is more "ideal" than the current node. Strip out
// control copies // control copies
Node *StrCompNode::Ideal(PhaseGVN *phase, bool can_reshape){ Node *StrIntrinsicNode::Ideal(PhaseGVN *phase, bool can_reshape) {
return remove_dead_region(phase, can_reshape) ? this : NULL; if (remove_dead_region(phase, can_reshape)) return this;
}
//============================================================================= if (can_reshape) {
// Do we match on this edge? No memory edges Node* mem = phase->transform(in(MemNode::Memory));
uint StrEqualsNode::match_edge(uint idx) const { // If transformed to a MergeMem, get the desired slice
return idx == 2 || idx == 3; // StrEquals (Binary str1 str2) cnt uint alias_idx = phase->C->get_alias_index(adr_type());
} mem = mem->is_MergeMem() ? mem->as_MergeMem()->memory_at(alias_idx) : mem;
if (mem != in(MemNode::Memory)) {
//------------------------------Ideal------------------------------------------ set_req(MemNode::Memory, mem);
// Return a node which is more "ideal" than the current node. Strip out return this;
// control copies }
Node *StrEqualsNode::Ideal(PhaseGVN *phase, bool can_reshape){ }
return remove_dead_region(phase, can_reshape) ? this : NULL; return NULL;
}
//=============================================================================
// Do we match on this edge? No memory edges
uint StrIndexOfNode::match_edge(uint idx) const {
return idx == 2 || idx == 3; // StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)
}
//------------------------------Ideal------------------------------------------
// Return a node which is more "ideal" than the current node. Strip out
// control copies
Node *StrIndexOfNode::Ideal(PhaseGVN *phase, bool can_reshape){
return remove_dead_region(phase, can_reshape) ? this : NULL;
}
//=============================================================================
// Do we match on this edge? No memory edges
uint AryEqNode::match_edge(uint idx) const {
return idx == 2 || idx == 3; // StrEquals ary1 ary2
}
//------------------------------Ideal------------------------------------------
// Return a node which is more "ideal" than the current node. Strip out
// control copies
Node *AryEqNode::Ideal(PhaseGVN *phase, bool can_reshape){
return remove_dead_region(phase, can_reshape) ? this : NULL;
} }
//============================================================================= //=============================================================================

View File

@ -776,67 +776,69 @@ public:
static bool step_through(Node** np, uint instance_id, PhaseTransform* phase); static bool step_through(Node** np, uint instance_id, PhaseTransform* phase);
}; };
//------------------------------StrComp------------------------------------- //------------------------------StrIntrinsic-------------------------------
class StrCompNode: public Node { // Base class for Ideal nodes used in String instrinsic code.
class StrIntrinsicNode: public Node {
public: public:
StrCompNode(Node* control, Node* char_array_mem, StrIntrinsicNode(Node* control, Node* char_array_mem,
Node* s1, Node* c1, Node* s1, Node* c1, Node* s2, Node* c2):
Node* s2, Node* c2): Node(control, char_array_mem, Node(control, char_array_mem, s1, c1, s2, c2) {
s1, c1, }
s2, c2) {};
virtual int Opcode() const; StrIntrinsicNode(Node* control, Node* char_array_mem,
Node* s1, Node* s2, Node* c):
Node(control, char_array_mem, s1, s2, c) {
}
StrIntrinsicNode(Node* control, Node* char_array_mem,
Node* s1, Node* s2):
Node(control, char_array_mem, s1, s2) {
}
virtual bool depends_only_on_test() const { return false; } virtual bool depends_only_on_test() const { return false; }
virtual const Type* bottom_type() const { return TypeInt::INT; }
virtual const TypePtr* adr_type() const { return TypeAryPtr::CHARS; } virtual const TypePtr* adr_type() const { return TypeAryPtr::CHARS; }
virtual uint match_edge(uint idx) const; virtual uint match_edge(uint idx) const;
virtual uint ideal_reg() const { return Op_RegI; } virtual uint ideal_reg() const { return Op_RegI; }
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
}; };
//------------------------------StrComp-------------------------------------
class StrCompNode: public StrIntrinsicNode {
public:
StrCompNode(Node* control, Node* char_array_mem,
Node* s1, Node* c1, Node* s2, Node* c2):
StrIntrinsicNode(control, char_array_mem, s1, c1, s2, c2) {};
virtual int Opcode() const;
virtual const Type* bottom_type() const { return TypeInt::INT; }
};
//------------------------------StrEquals------------------------------------- //------------------------------StrEquals-------------------------------------
class StrEqualsNode: public Node { class StrEqualsNode: public StrIntrinsicNode {
public: public:
StrEqualsNode(Node* control, Node* char_array_mem, StrEqualsNode(Node* control, Node* char_array_mem,
Node* s1, Node* s2, Node* c): Node(control, char_array_mem, Node* s1, Node* s2, Node* c):
s1, s2, c) {}; StrIntrinsicNode(control, char_array_mem, s1, s2, c) {};
virtual int Opcode() const; virtual int Opcode() const;
virtual bool depends_only_on_test() const { return false; }
virtual const Type* bottom_type() const { return TypeInt::BOOL; } virtual const Type* bottom_type() const { return TypeInt::BOOL; }
virtual const TypePtr* adr_type() const { return TypeAryPtr::CHARS; }
virtual uint match_edge(uint idx) const;
virtual uint ideal_reg() const { return Op_RegI; }
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
}; };
//------------------------------StrIndexOf------------------------------------- //------------------------------StrIndexOf-------------------------------------
class StrIndexOfNode: public Node { class StrIndexOfNode: public StrIntrinsicNode {
public: public:
StrIndexOfNode(Node* control, Node* char_array_mem, StrIndexOfNode(Node* control, Node* char_array_mem,
Node* s1, Node* c1, Node* s1, Node* c1, Node* s2, Node* c2):
Node* s2, Node* c2): Node(control, char_array_mem, StrIntrinsicNode(control, char_array_mem, s1, c1, s2, c2) {};
s1, c1,
s2, c2) {};
virtual int Opcode() const; virtual int Opcode() const;
virtual bool depends_only_on_test() const { return false; }
virtual const Type* bottom_type() const { return TypeInt::INT; } virtual const Type* bottom_type() const { return TypeInt::INT; }
virtual const TypePtr* adr_type() const { return TypeAryPtr::CHARS; }
virtual uint match_edge(uint idx) const;
virtual uint ideal_reg() const { return Op_RegI; }
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
}; };
//------------------------------AryEq--------------------------------------- //------------------------------AryEq---------------------------------------
class AryEqNode: public Node { class AryEqNode: public StrIntrinsicNode {
public: public:
AryEqNode(Node* control, Node* char_array_mem, AryEqNode(Node* control, Node* char_array_mem, Node* s1, Node* s2):
Node* s1, Node* s2): Node(control, char_array_mem, s1, s2) {}; StrIntrinsicNode(control, char_array_mem, s1, s2) {};
virtual int Opcode() const; virtual int Opcode() const;
virtual bool depends_only_on_test() const { return false; }
virtual const Type* bottom_type() const { return TypeInt::BOOL; } virtual const Type* bottom_type() const { return TypeInt::BOOL; }
virtual const TypePtr* adr_type() const { return TypeAryPtr::CHARS; }
virtual uint match_edge(uint idx) const;
virtual uint ideal_reg() const { return Op_RegI; }
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
}; };
//------------------------------MemBar----------------------------------------- //------------------------------MemBar-----------------------------------------

View File

@ -1373,12 +1373,12 @@ static inline bool NotANode(const Node* n) {
//------------------------------find------------------------------------------ //------------------------------find------------------------------------------
// Find a neighbor of this Node with the given _idx // Find a neighbor of this Node with the given _idx
// If idx is negative, find its absolute value, following both _in and _out. // If idx is negative, find its absolute value, following both _in and _out.
static void find_recur( Node* &result, Node *n, int idx, bool only_ctrl, static void find_recur(Compile* C, Node* &result, Node *n, int idx, bool only_ctrl,
VectorSet &old_space, VectorSet &new_space ) { VectorSet* old_space, VectorSet* new_space ) {
int node_idx = (idx >= 0) ? idx : -idx; int node_idx = (idx >= 0) ? idx : -idx;
if (NotANode(n)) return; // Gracefully handle NULL, -1, 0xabababab, etc. if (NotANode(n)) return; // Gracefully handle NULL, -1, 0xabababab, etc.
// Contained in new_space or old_space? // Contained in new_space or old_space? Check old_arena first since it's mostly empty.
VectorSet *v = Compile::current()->node_arena()->contains(n) ? &new_space : &old_space; VectorSet *v = C->old_arena()->contains(n) ? old_space : new_space;
if( v->test(n->_idx) ) return; if( v->test(n->_idx) ) return;
if( (int)n->_idx == node_idx if( (int)n->_idx == node_idx
debug_only(|| n->debug_idx() == node_idx) ) { debug_only(|| n->debug_idx() == node_idx) ) {
@ -1390,19 +1390,23 @@ static void find_recur( Node* &result, Node *n, int idx, bool only_ctrl,
v->set(n->_idx); v->set(n->_idx);
for( uint i=0; i<n->len(); i++ ) { for( uint i=0; i<n->len(); i++ ) {
if( only_ctrl && !(n->is_Region()) && (n->Opcode() != Op_Root) && (i != TypeFunc::Control) ) continue; if( only_ctrl && !(n->is_Region()) && (n->Opcode() != Op_Root) && (i != TypeFunc::Control) ) continue;
find_recur( result, n->in(i), idx, only_ctrl, old_space, new_space ); find_recur(C, result, n->in(i), idx, only_ctrl, old_space, new_space );
} }
// Search along forward edges also: // Search along forward edges also:
if (idx < 0 && !only_ctrl) { if (idx < 0 && !only_ctrl) {
for( uint j=0; j<n->outcnt(); j++ ) { for( uint j=0; j<n->outcnt(); j++ ) {
find_recur( result, n->raw_out(j), idx, only_ctrl, old_space, new_space ); find_recur(C, result, n->raw_out(j), idx, only_ctrl, old_space, new_space );
} }
} }
#ifdef ASSERT #ifdef ASSERT
// Search along debug_orig edges last: // Search along debug_orig edges last, checking for cycles
for (Node* orig = n->debug_orig(); orig != NULL && n != orig; orig = orig->debug_orig()) { Node* orig = n->debug_orig();
if (NotANode(orig)) break; if (orig != NULL) {
find_recur( result, orig, idx, only_ctrl, old_space, new_space ); do {
if (NotANode(orig)) break;
find_recur(C, result, orig, idx, only_ctrl, old_space, new_space );
orig = orig->debug_orig();
} while (orig != NULL && orig != n->debug_orig());
} }
#endif //ASSERT #endif //ASSERT
} }
@ -1417,7 +1421,7 @@ Node* Node::find(int idx) const {
ResourceArea *area = Thread::current()->resource_area(); ResourceArea *area = Thread::current()->resource_area();
VectorSet old_space(area), new_space(area); VectorSet old_space(area), new_space(area);
Node* result = NULL; Node* result = NULL;
find_recur( result, (Node*) this, idx, false, old_space, new_space ); find_recur(Compile::current(), result, (Node*) this, idx, false, &old_space, &new_space );
return result; return result;
} }
@ -1427,7 +1431,7 @@ Node* Node::find_ctrl(int idx) const {
ResourceArea *area = Thread::current()->resource_area(); ResourceArea *area = Thread::current()->resource_area();
VectorSet old_space(area), new_space(area); VectorSet old_space(area), new_space(area);
Node* result = NULL; Node* result = NULL;
find_recur( result, (Node*) this, idx, true, old_space, new_space ); find_recur(Compile::current(), result, (Node*) this, idx, true, &old_space, &new_space );
return result; return result;
} }
#endif #endif

View File

@ -112,7 +112,7 @@ bool MethodHandles::spot_check_entry_names() {
// MethodHandles::generate_adapters // MethodHandles::generate_adapters
// //
void MethodHandles::generate_adapters() { void MethodHandles::generate_adapters() {
if (!EnableMethodHandles || SystemDictionary::MethodHandle_klass() == NULL) return; if (!EnableInvokeDynamic || SystemDictionary::MethodHandle_klass() == NULL) return;
assert(_adapter_code == NULL, "generate only once"); assert(_adapter_code == NULL, "generate only once");
@ -143,7 +143,7 @@ void MethodHandlesAdapterGenerator::generate() {
void MethodHandles::set_enabled(bool z) { void MethodHandles::set_enabled(bool z) {
if (_enabled != z) { if (_enabled != z) {
guarantee(z && EnableMethodHandles, "can only enable once, and only if -XX:+EnableMethodHandles"); guarantee(z && EnableInvokeDynamic, "can only enable once, and only if -XX:+EnableInvokeDynamic");
_enabled = z; _enabled = z;
} }
} }
@ -2579,7 +2579,6 @@ static JNINativeMethod methods[] = {
{CC"getMembers", CC"("CLS""STRG""STRG"I"CLS"I["MEM")I", FN_PTR(MHN_getMembers)} {CC"getMembers", CC"("CLS""STRG""STRG"I"CLS"I["MEM")I", FN_PTR(MHN_getMembers)}
}; };
// More entry points specifically for EnableInvokeDynamic.
// FIXME: Remove methods2 after AllowTransitionalJSR292 is removed. // FIXME: Remove methods2 after AllowTransitionalJSR292 is removed.
static JNINativeMethod methods2[] = { static JNINativeMethod methods2[] = {
{CC"registerBootstrap", CC"("CLS MH")V", FN_PTR(MHN_registerBootstrap)}, {CC"registerBootstrap", CC"("CLS MH")V", FN_PTR(MHN_registerBootstrap)},
@ -2618,10 +2617,8 @@ static void hack_signatures(JNINativeMethod* methods, jint num_methods, const ch
JVM_ENTRY(void, JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass MHN_class)) { JVM_ENTRY(void, JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass MHN_class)) {
assert(MethodHandles::spot_check_entry_names(), "entry enum is OK"); assert(MethodHandles::spot_check_entry_names(), "entry enum is OK");
// note: this explicit warning-producing stuff will be replaced by auto-detection of the JSR 292 classes if (!EnableInvokeDynamic) {
warning("JSR 292 is disabled in this JVM. Use -XX:+UnlockDiagnosticVMOptions -XX:+EnableInvokeDynamic to enable.");
if (!EnableMethodHandles) {
warning("JSR 292 method handles are disabled in this JVM. Use -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles to enable.");
return; // bind nothing return; // bind nothing
} }
@ -2702,11 +2699,6 @@ JVM_ENTRY(void, JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass MHN_class))
MethodHandles::set_enabled(true); MethodHandles::set_enabled(true);
} }
if (!EnableInvokeDynamic) {
warning("JSR 292 invokedynamic is disabled in this JVM. Use -XX:+UnlockExperimentalVMOptions -XX:+EnableInvokeDynamic to enable.");
return; // bind nothing
}
if (AllowTransitionalJSR292) { if (AllowTransitionalJSR292) {
ThreadToNativeFromVM ttnfv(thread); ThreadToNativeFromVM ttnfv(thread);

View File

@ -1560,7 +1560,7 @@ JVM_ENTRY(void, JVM_RegisterUnsafeMethods(JNIEnv *env, jclass unsafecls))
} }
} }
} }
if (AnonymousClasses) { if (EnableInvokeDynamic) {
env->RegisterNatives(unsafecls, anonk_methods, sizeof(anonk_methods)/sizeof(JNINativeMethod)); env->RegisterNatives(unsafecls, anonk_methods, sizeof(anonk_methods)/sizeof(JNINativeMethod));
if (env->ExceptionOccurred()) { if (env->ExceptionOccurred()) {
if (PrintMiscellaneous && (Verbose || WizardMode)) { if (PrintMiscellaneous && (Verbose || WizardMode)) {

View File

@ -2974,21 +2974,28 @@ jint Arguments::parse(const JavaVMInitArgs* args) {
} }
#endif // PRODUCT #endif // PRODUCT
if (EnableInvokeDynamic && !EnableMethodHandles) { // Transitional
if (!FLAG_IS_DEFAULT(EnableMethodHandles)) { if (EnableMethodHandles || AnonymousClasses) {
warning("forcing EnableMethodHandles true because EnableInvokeDynamic is true"); if (!EnableInvokeDynamic && !FLAG_IS_DEFAULT(EnableInvokeDynamic)) {
warning("EnableMethodHandles and AnonymousClasses are obsolete. Keeping EnableInvokeDynamic disabled.");
} else {
EnableInvokeDynamic = true;
} }
EnableMethodHandles = true;
} }
if (EnableMethodHandles && !AnonymousClasses) {
if (!FLAG_IS_DEFAULT(AnonymousClasses)) { // JSR 292 is not supported before 1.7
warning("forcing AnonymousClasses true because EnableMethodHandles is true"); if (!JDK_Version::is_gte_jdk17x_version()) {
if (EnableInvokeDynamic) {
if (!FLAG_IS_DEFAULT(EnableInvokeDynamic)) {
warning("JSR 292 is not supported before 1.7. Disabling support.");
}
EnableInvokeDynamic = false;
} }
AnonymousClasses = true;
} }
if ((EnableMethodHandles || AnonymousClasses) && ScavengeRootsInCode == 0) {
if (EnableInvokeDynamic && ScavengeRootsInCode == 0) {
if (!FLAG_IS_DEFAULT(ScavengeRootsInCode)) { if (!FLAG_IS_DEFAULT(ScavengeRootsInCode)) {
warning("forcing ScavengeRootsInCode non-zero because EnableMethodHandles or AnonymousClasses is true"); warning("forcing ScavengeRootsInCode non-zero because EnableInvokeDynamic is true");
} }
ScavengeRootsInCode = 1; ScavengeRootsInCode = 1;
} }

View File

@ -396,8 +396,6 @@ void NonTieredCompPolicy::trace_osr_request(methodHandle method, nmethod* osr, i
// SimpleCompPolicy - compile current method // SimpleCompPolicy - compile current method
void SimpleCompPolicy::method_invocation_event( methodHandle m, TRAPS) { void SimpleCompPolicy::method_invocation_event( methodHandle m, TRAPS) {
assert(UseCompiler || CompileTheWorld, "UseCompiler should be set by now.");
int hot_count = m->invocation_count(); int hot_count = m->invocation_count();
reset_counter_for_invocation_event(m); reset_counter_for_invocation_event(m);
const char* comment = "count"; const char* comment = "count";
@ -413,8 +411,6 @@ void SimpleCompPolicy::method_invocation_event( methodHandle m, TRAPS) {
} }
void SimpleCompPolicy::method_back_branch_event(methodHandle m, int bci, TRAPS) { void SimpleCompPolicy::method_back_branch_event(methodHandle m, int bci, TRAPS) {
assert(UseCompiler || CompileTheWorld, "UseCompiler should be set by now.");
int hot_count = m->backedge_count(); int hot_count = m->backedge_count();
const char* comment = "backedge_count"; const char* comment = "backedge_count";
@ -432,8 +428,6 @@ const char* StackWalkCompPolicy::_msg = NULL;
// Consider m for compilation // Consider m for compilation
void StackWalkCompPolicy::method_invocation_event(methodHandle m, TRAPS) { void StackWalkCompPolicy::method_invocation_event(methodHandle m, TRAPS) {
assert(UseCompiler || CompileTheWorld, "UseCompiler should be set by now.");
int hot_count = m->invocation_count(); int hot_count = m->invocation_count();
reset_counter_for_invocation_event(m); reset_counter_for_invocation_event(m);
const char* comment = "count"; const char* comment = "count";
@ -473,8 +467,6 @@ void StackWalkCompPolicy::method_invocation_event(methodHandle m, TRAPS) {
} }
void StackWalkCompPolicy::method_back_branch_event(methodHandle m, int bci, TRAPS) { void StackWalkCompPolicy::method_back_branch_event(methodHandle m, int bci, TRAPS) {
assert(UseCompiler || CompileTheWorld, "UseCompiler should be set by now.");
int hot_count = m->backedge_count(); int hot_count = m->backedge_count();
const char* comment = "backedge_count"; const char* comment = "backedge_count";

View File

@ -2377,6 +2377,9 @@ class CommandLineFlags {
develop(intx, CICloneLoopTestLimit, 100, \ develop(intx, CICloneLoopTestLimit, 100, \
"size limit for blocks heuristically cloned in ciTypeFlow") \ "size limit for blocks heuristically cloned in ciTypeFlow") \
\ \
develop(intx, OSROnlyBCI, -1, \
"OSR only at this bci. Negative values mean exclude that bci") \
\
/* temp diagnostics */ \ /* temp diagnostics */ \
\ \
diagnostic(bool, TraceRedundantCompiles, false, \ diagnostic(bool, TraceRedundantCompiles, false, \
@ -3690,11 +3693,15 @@ class CommandLineFlags {
"Skip assert() and verify() which page-in unwanted shared " \ "Skip assert() and verify() which page-in unwanted shared " \
"objects. ") \ "objects. ") \
\ \
diagnostic(bool, EnableInvokeDynamic, true, \
"support JSR 292 (method handles, invokedynamic, " \
"anonymous classes") \
\
product(bool, AnonymousClasses, false, \ product(bool, AnonymousClasses, false, \
"support sun.misc.Unsafe.defineAnonymousClass") \ "support sun.misc.Unsafe.defineAnonymousClass (deprecated)") \
\ \
experimental(bool, EnableMethodHandles, false, \ experimental(bool, EnableMethodHandles, false, \
"support method handles (true by default under JSR 292)") \ "support method handles (deprecated)") \
\ \
diagnostic(intx, MethodHandlePushLimit, 3, \ diagnostic(intx, MethodHandlePushLimit, 3, \
"number of additional stack slots a method handle may push") \ "number of additional stack slots a method handle may push") \
@ -3711,9 +3718,6 @@ class CommandLineFlags {
experimental(bool, TrustFinalNonStaticFields, false, \ experimental(bool, TrustFinalNonStaticFields, false, \
"trust final non-static declarations for constant folding") \ "trust final non-static declarations for constant folding") \
\ \
experimental(bool, EnableInvokeDynamic, false, \
"recognize the invokedynamic instruction") \
\
experimental(bool, AllowTransitionalJSR292, true, \ experimental(bool, AllowTransitionalJSR292, true, \
"recognize pre-PFD formats of invokedynamic") \ "recognize pre-PFD formats of invokedynamic") \
\ \

Some files were not shown because too many files have changed in this diff Show More