This commit is contained in:
J. Duke 2017-07-05 17:39:40 +02:00
commit 6de94414c6
107 changed files with 1880 additions and 875 deletions

View File

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

View File

@ -158,3 +158,5 @@ a8d643a4db47c7b58e0bcb49c77b5c3610de86a8 hs21-b03
3c76374706ea8a77e15aec8310e831e5734f8775 hs21-b04
b898f0fc3cedc972d884d31a751afd75969531cf jdk7-b135
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.
*
* 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 sun.jvm.hotspot.oops.Instance;
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
implements ClassObjectReference {
@ -39,7 +39,7 @@ public class ClassObjectReferenceImpl extends ObjectReferenceImpl
public ReferenceType reflectedType() {
if (reflectedType == null) {
Klass k = OopUtilities.classOopToKlass(ref());
Klass k = java_lang_Class.asKlass(ref());
reflectedType = vm.referenceType(k);
}
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.
*
* 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) {
super.iterateFields(visitor, doVMFields);
((InstanceKlass) getKlass()).iterateNonStaticFields(visitor);
((InstanceKlass) getKlass()).iterateNonStaticFields(visitor, this);
}
public void printValueOn(PrintStream tty) {

View File

@ -241,6 +241,10 @@ public class InstanceKlass extends Klass {
// Byteside of the header
private static long headerSize;
public long getObjectSize(Oop object) {
return getSizeHelper() * VM.getVM().getAddressSize();
}
public static long getHeaderSize() { return headerSize; }
// Accessors for declared fields
@ -459,7 +463,22 @@ public class InstanceKlass extends Klass {
visitor.doCInt(vtableLen, 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();
int length = (int) fields.getLength();
for (int index = 0; index < length; index += NEXT_OFFSET) {
@ -477,9 +496,9 @@ public class InstanceKlass extends Klass {
return getSuper();
}
public void iterateNonStaticFields(OopVisitor visitor) {
public void iterateNonStaticFields(OopVisitor visitor, Oop obj) {
if (getSuper() != null) {
((InstanceKlass) getSuper()).iterateNonStaticFields(visitor);
((InstanceKlass) getSuper()).iterateNonStaticFields(visitor, obj);
}
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.
*
* 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(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(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.
*
* 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
public long getObjectSize() {
Klass k = getKlass();
if (k instanceof InstanceKlass) {
return ((InstanceKlass)k).getSizeHelper()
* VM.getVM().getAddressSize();
}
// If it is not an instance, this method should be replaced.
return getHeaderSize();
// All other types should be overriding getObjectSize directly
return ((InstanceKlass)k).getObjectSize(this);
}
// Type test operations

View File

@ -74,9 +74,6 @@ public class OopUtilities implements /* imports */ JVMTIThreadState {
private static int THREAD_STATUS_TERMINATED;
*/
// java.lang.Class fields
private static OopField hcKlassField;
// java.util.concurrent.locks.AbstractOwnableSynchronizer fields
private static OopField absOwnSyncOwnerThreadField;
@ -268,27 +265,6 @@ public class OopUtilities implements /* imports */ JVMTIThreadState {
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
private static void initAbsOwnSyncFields() {
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() {
final InstanceKlass systemKls = getSystemDictionary().getSystemKlass();
systemKls.iterate(new DefaultOopVisitor() {
ObjectReader objReader = new ObjectReader();
public void doOop(sun.jvm.hotspot.oops.OopField field, boolean isVMField) {
if (field.getID().getName().equals("props")) {
try {
sysProps = (Properties) objReader.readObject(field.getValue(systemKls.getJavaMirror()));
} catch (Exception e) {
if (Assert.ASSERTS_ENABLED) {
e.printStackTrace();
}
}
}
}
}, false);
final InstanceKlass systemKls = getSystemDictionary().getSystemKlass();
systemKls.iterateStaticFields(new DefaultOopVisitor() {
ObjectReader objReader = new ObjectReader();
public void doOop(sun.jvm.hotspot.oops.OopField field, boolean isVMField) {
if (field.getID().getName().equals("props")) {
try {
sysProps = (Properties) objReader.readObject(field.getValue(getObj()));
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
}
}

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.
*
* This code is free software; you can redistribute it and/or modify it
@ -64,16 +64,16 @@ public class FinalizerInfo extends Tool {
*/
InstanceKlass ik =
SystemDictionaryHelper.findInstanceKlass("java.lang.ref.Finalizer");
final OopField queueField[] = new OopField[1];
ik.iterateFields(new DefaultOopVisitor() {
final Oop[] queueref = new Oop[1];
ik.iterateStaticFields(new DefaultOopVisitor() {
public void doOop(OopField field, boolean isVMField) {
String name = field.getID().getName();
if (name.equals("queue")) {
queueField[0] = field;
}
String name = field.getID().getName();
if (name.equals("queue")) {
queueref[0] = field.getValue(getObj());
}
}
}, false);
Oop queue = queueField[0].getValue(ik);
});
Oop queue = queueref[0];
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.
*
* 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 {
writeObjectHeader(instance);
Klass reflectedType = OopUtilities.classOopToKlass(instance);
Klass reflectedType = java_lang_Class.asKlass(instance);
boolean isInstanceKlass = (reflectedType instanceof InstanceKlass);
// reflectedType is null for primitive types (int.class etc).
if (reflectedType != null) {

View File

@ -455,7 +455,7 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
}
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.
// all other Class objects are covered by writeClassDumpRecords.
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.
*
* 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) {
if (obj instanceof InstanceKlass) {
final InstanceKlass ik = (InstanceKlass) obj;
ik.iterateFields(
ik.iterateStaticFields(
new DefaultOopVisitor() {
public void doOop(OopField field, boolean isVMField) {
Oop next = field.getValue(ik);
Oop next = field.getValue(getObj());
LivenessPathElement lp = new LivenessPathElement(null,
new NamedFieldIdentifier("Static field \"" +
field.getID().getName() +
@ -142,8 +142,7 @@ public class ReversePtrsAnalysis {
System.err.println();
}
}
},
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.
*
* 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())) {
res = new JSJavaThread(instance, this);
} else if (className.equals(javaLangClass())) {
Klass reflectedType = OopUtilities.classOopToKlass(instance);
Klass reflectedType = java_lang_Class.asKlass(instance);
if (reflectedType != null) {
JSJavaKlass jk = newJSJavaKlass(reflectedType);
// 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_MINOR_VER=0
HS_BUILD_NUMBER=06
HS_BUILD_NUMBER=07
JDK_MAJOR_VER=1
JDK_MINOR_VER=7

View File

@ -102,7 +102,7 @@ all: $(EXEC)
$(EXEC) : $(OBJECTS)
@echo Making adlc
$(QUIETLY) $(LINK_NOPROF.CC) -o $(EXEC) $(OBJECTS)
$(QUIETLY) $(HOST.LINK_NOPROF.CC) -o $(EXEC) $(OBJECTS)
# 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
@ -204,14 +204,14 @@ PROCESS_AD_FILES = awk '{ \
$(OUTDIR)/%.o: %.cpp
@echo Compiling $<
$(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
# them from objects of the same name built for the VM.
$(OUTDIR)/adlc-%.o: %.cpp
@echo Compiling $<
$(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
CPP = $(ALT_COMPILER_PATH)/g++
CC = $(ALT_COMPILER_PATH)/gcc
HOSTCPP = g++
HOSTCC = gcc
else
CPP = g++
CC = gcc
HOSTCPP = $(CPP)
HOSTCC = $(CC)
endif
AS = $(CC) -c

View File

@ -55,6 +55,14 @@ LINK_NOPROF.CC = $(CCC) $(LFLAGS) $(AOUT_FLAGS)
LINK_LIB.CC = $(CCC) $(LFLAGS) $(SHARED_FLAG)
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".
REMOVE_TARGET = rm -f $@

View File

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

View File

@ -93,16 +93,15 @@ if "%MSC_VER%" == "1500" (
echo Will generate VC9 {Visual Studio 2008}
) else (
if "%MSC_VER%" == "1600" (
echo Detected Visual Studio 2010, but
echo will generate VC9 {Visual Studio 2008}
echo Use conversion wizard in VS 2010.
echo Will generate VC10 {Visual Studio 2010}
set ProjectFile=%HotSpotBuildSpace%\jvm.vcxproj
) else (
echo Will generate VC7 project {Visual Studio 2003 .NET}
)
)
)
)
echo %ProjectFile%
echo %ProjectFile%
echo **************************************************************
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
# reference any of the HOTSPOTWORKSPACE, HOTSPOTBUILDSPACE,
# 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=\
$(WorkSpace)\src\share\tools\ProjectCreator\DirectoryTree.java \
@ -42,6 +38,7 @@ ProjectCreatorSources=\
$(WorkSpace)\src\share\tools\ProjectCreator\WinGammaPlatformVC7.java \
$(WorkSpace)\src\share\tools\ProjectCreator\WinGammaPlatformVC8.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\BuildConfig.java \
$(WorkSpace)\src\share\tools\ProjectCreator\ArgsParser.java

View File

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

View File

@ -1188,8 +1188,8 @@ void CppInterpreterGenerator::generate_compute_interpreter_state(const Register
__ st_ptr(O2, XXX_STATE(_stack)); // PREPUSH
__ lduh(max_stack, O3); // Full size expression stack
guarantee(!EnableMethodHandles, "no support yet for java.lang.invoke.MethodHandle"); //6815692
//6815692//if (EnableMethodHandles)
guarantee(!EnableInvokeDynamic, "no support yet for java.lang.invoke.MethodHandle"); //6815692
//6815692//if (EnableInvokeDynamic)
//6815692// __ inc(O3, methodOopDesc::extra_stack_entries());
__ sll(O3, LogBytesPerWord, 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)) {
get_2_byte_integer_at_bcp(bcp_offset, cache, tmp, Unsigned);
} 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);
assert(constantPoolCacheOopDesc::decode_secondary_index(~123) == 123, "else change next line");
xor3(tmp, -1, tmp); // convert to plain index
} 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);
} else {
ShouldNotReachHere();

View File

@ -262,7 +262,7 @@ address InterpreterGenerator::generate_abstract_entry(void) {
// Method handle invoker
// Dispatch a method of the form java.lang.invoke.MethodHandles::invoke(...)
address InterpreterGenerator::generate_method_handle_entry(void) {
if (!EnableMethodHandles) {
if (!EnableInvokeDynamic) {
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.
*
* 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.
nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
methodHandle method,
int compile_id,
int total_in_args,
int comp_args_on_stack, // in VMRegStackSlots
BasicType *in_sig_bt,
@ -2462,6 +2463,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
__ flush();
nmethod *nm = nmethod::new_native_nmethod(method,
compile_id,
masm->code(),
vep_offset,
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
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() {
NOT_LP64(ShouldNotCallThis());
assert(UseCompressedOops, "only for compressed oops code");

View File

@ -334,8 +334,8 @@ void TemplateTable::ldc(bool wide) {
void TemplateTable::fast_aldc(bool wide) {
transition(vtos, atos);
if (!EnableMethodHandles) {
// We should not encounter this bytecode if !EnableMethodHandles.
if (!EnableInvokeDynamic) {
// We should not encounter this bytecode if !EnableInvokeDynamic.
// 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.
__ 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.
// This would have to change if we ever save/restore shared code
// to be more pessimistic.
disp = (int64_t)adr._target - ((int64_t)CodeCache::low_bound() + sizeof(int));
if (!is_simm32(disp)) return false;
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);
}
// 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,
relocInfo::relocType rtype,
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
@ -7121,17 +7133,6 @@ void MacroAssembler::subptr(Register dst, Register 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
void MacroAssembler::testbool(Register dst) {
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) {
if (!VerifyOops) return;
@ -9018,14 +9041,7 @@ void MacroAssembler::string_compare(Register str1, Register str2,
movl(result, cnt1);
subl(cnt1, cnt2);
push(cnt1);
if (VM_Version::supports_cmov()) {
cmovl(Assembler::lessEqual, cnt2, result);
} else {
Label GT_LABEL;
jccb(Assembler::greater, GT_LABEL);
movl(cnt2, result);
bind(GT_LABEL);
}
cmov32(Assembler::lessEqual, cnt2, result);
// Is the minimum length zero?
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, RelocationHolder const& rspec, int format = 0);
bool reachable(AddressLiteral adr) NOT_LP64({ return true;});
// These are all easily abused and hence protected
@ -683,6 +682,8 @@ private:
static bool is_simm32(int32_t x) { return true; }
#endif // _LP64
static bool is_polling_page_far() NOT_LP64({ return false;});
// Generic instructions
// 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
@ -2094,7 +2095,10 @@ class MacroAssembler: public Assembler {
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, Register src) { LP64_ONLY(orq(dst, src)) NOT_LP64(orl(dst, src)); }
@ -2240,10 +2244,13 @@ public:
// 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 cmovptr(Condition cc, Register dst, Register 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, 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(Address dst, jobject obj);

View File

@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
#include "asm/assembler.hpp"
#include "c1/c1_Compilation.hpp"
#include "c1/c1_LIRAssembler.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)));
// 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 (rax, Address(rax, java_lang_String::count_offset_in_bytes()));
__ mov (rcx, rbx);
__ subptr (rbx, rax); // subtract lengths
__ push (rbx); // result
__ 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);
}
__ movl (rbx, Address(rbx, java_lang_String::count_offset_in_bytes()));
__ movl (rax, Address(rax, java_lang_String::count_offset_in_bytes()));
__ mov (rcx, rbx);
__ subptr(rbx, rax); // subtract lengths
__ push (rbx); // result
__ cmov (Assembler::lessEqual, rax, rcx);
// is minimum length 0?
Label noLoop, haveResult;
__ 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()),
relocInfo::poll_return_type);
// NOTE: the requires that the polling page be reachable else the reloc
// goes to the movq that loads the address and not the faulting instruction
// which breaks the signal handler code
__ test32(rax, polling_page);
if (Assembler::is_polling_page_far()) {
__ lea(rscratch1, polling_page);
__ relocate(relocInfo::poll_return_type);
__ testl(rax, Address(rscratch1, 0));
} else {
__ testl(rax, polling_page);
}
__ ret(0);
}
@ -661,20 +652,17 @@ void LIR_Assembler::return_op(LIR_Opr result) {
int LIR_Assembler::safepoint_poll(LIR_Opr tmp, CodeEmitInfo* info) {
AddressLiteral polling_page(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()),
relocInfo::poll_type);
if (info != NULL) {
add_debug_info_for_branch(info);
} else {
ShouldNotReachHere();
}
guarantee(info != NULL, "Shouldn't be NULL");
int offset = __ offset();
// NOTE: the requires that the polling page be reachable else the reloc
// goes to the movq that loads the address and not the faulting instruction
// which breaks the signal handler code
__ test32(rax, polling_page);
if (Assembler::is_polling_page_far()) {
__ lea(rscratch1, polling_page);
offset = __ offset();
add_debug_info_for_branch(info);
__ testl(rax, Address(rscratch1, 0));
} else {
add_debug_info_for_branch(info);
__ testl(rax, polling_page);
}
return offset;
}

View File

@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
#include "asm/assembler.hpp"
#include "c1/c1_Defs.hpp"
#include "c1/c1_MacroAssembler.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.
*
* This code is free software; you can redistribute it and/or modify it
@ -125,7 +125,7 @@
// Entry frames
#ifdef AMD64
#ifdef _WIN64
entry_frame_after_call_words = 8,
entry_frame_after_call_words = 28,
entry_frame_call_wrapper_offset = 2,
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)) {
load_unsigned_short(reg, Address(rsi, bcp_offset));
} 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));
// Check if the secondary index definition is still ~x, otherwise
// 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");
notl(reg); // convert to plain index
} 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));
} else {
ShouldNotReachHere();

View File

@ -213,7 +213,7 @@ void InterpreterMacroAssembler::get_cache_index_at_bcp(Register index,
if (index_size == sizeof(u2)) {
load_unsigned_short(index, Address(r13, bcp_offset));
} 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));
// Check if the secondary index definition is still ~x, otherwise
// 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");
notl(index); // convert to plain index
} 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));
} else {
ShouldNotReachHere();

View File

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

View File

@ -320,7 +320,7 @@ address InterpreterGenerator::generate_abstract_entry(void) {
// Method handle invoker
// Dispatch a method of the form java.lang.invoke.MethodHandles::invoke(...)
address InterpreterGenerator::generate_method_handle_entry(void) {
if (!EnableMethodHandles) {
if (!EnableInvokeDynamic) {
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.
*
* 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 {
public:
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 */ }
inline bool NativeInstruction::is_safepoint_poll() {
#ifdef AMD64
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);
if (Assembler::is_polling_page_far()) {
// two cases, depending on the choice of the base register in the address.
if (((ubyte_at(0) & NativeTstRegMem::instruction_rex_prefix_mask) == NativeTstRegMem::instruction_rex_prefix &&
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 {
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
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.
*
* 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) {
#ifdef _LP64
typedef Assembler::WhichOperand WhichOperand;
WhichOperand which = (WhichOperand) format();
// This format is imm but it is really disp32
which = Assembler::disp32_operand;
address orig_addr = old_addr_for(addr(), src, dest);
NativeInstruction* oni = nativeInstruction_at(orig_addr);
int32_t* orig_disp = (int32_t*) Assembler::locate_operand(orig_addr, which);
// This poll_addr is incorrect by the size of the instruction it is irrelevant
intptr_t poll_addr = (intptr_t)oni + *orig_disp;
if (!Assembler::is_polling_page_far()) {
typedef Assembler::WhichOperand WhichOperand;
WhichOperand which = (WhichOperand) format();
// This format is imm but it is really disp32
which = Assembler::disp32_operand;
address orig_addr = old_addr_for(addr(), src, dest);
NativeInstruction* oni = nativeInstruction_at(orig_addr);
int32_t* orig_disp = (int32_t*) Assembler::locate_operand(orig_addr, which);
// 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());
intptr_t new_disp = poll_addr - (intptr_t) ni;
int32_t* disp = (int32_t*) Assembler::locate_operand(addr(), which);
* disp = (int32_t)new_disp;
NativeInstruction* ni = nativeInstruction_at(addr());
intptr_t new_disp = poll_addr - (intptr_t) ni;
int32_t* disp = (int32_t*) Assembler::locate_operand(addr(), which);
* disp = (int32_t)new_disp;
}
#endif // _LP64
}
void poll_return_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {
#ifdef _LP64
typedef Assembler::WhichOperand WhichOperand;
WhichOperand which = (WhichOperand) format();
// This format is imm but it is really disp32
which = Assembler::disp32_operand;
address orig_addr = old_addr_for(addr(), src, dest);
NativeInstruction* oni = nativeInstruction_at(orig_addr);
int32_t* orig_disp = (int32_t*) Assembler::locate_operand(orig_addr, which);
// This poll_addr is incorrect by the size of the instruction it is irrelevant
intptr_t poll_addr = (intptr_t)oni + *orig_disp;
if (!Assembler::is_polling_page_far()) {
typedef Assembler::WhichOperand WhichOperand;
WhichOperand which = (WhichOperand) format();
// This format is imm but it is really disp32
which = Assembler::disp32_operand;
address orig_addr = old_addr_for(addr(), src, dest);
NativeInstruction* oni = nativeInstruction_at(orig_addr);
int32_t* orig_disp = (int32_t*) Assembler::locate_operand(orig_addr, which);
// 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());
intptr_t new_disp = poll_addr - (intptr_t) ni;
NativeInstruction* ni = nativeInstruction_at(addr());
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
}

View File

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

View File

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

View File

@ -144,8 +144,11 @@ class StubGenerator: public StubCodeGenerator {
// [ return_from_Java ] <--- rsp
// [ argument word n ]
// ...
// -8 [ argument word 1 ]
// -7 [ saved r15 ] <--- rsp_after_call
// -28 [ argument word 1 ]
// -27 [ saved xmm15 ] <--- rsp_after_call
// [ saved xmm7-xmm14 ]
// -9 [ saved xmm6 ] (each xmm register takes 2 slots)
// -7 [ saved r15 ]
// -6 [ saved r14 ]
// -5 [ saved r13 ]
// -4 [ saved r12 ]
@ -169,8 +172,11 @@ class StubGenerator: public StubCodeGenerator {
// Call stub stack layout word offsets from rbp
enum call_stub_layout {
#ifdef _WIN64
rsp_after_call_off = -7,
r15_off = rsp_after_call_off,
xmm_save_first = 6, // save from xmm6
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,
r13_off = -5,
r12_off = -4,
@ -208,6 +214,13 @@ class StubGenerator: public StubCodeGenerator {
#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) {
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,
@ -256,8 +269,11 @@ class StubGenerator: public StubCodeGenerator {
__ movptr(r13_save, r13);
__ movptr(r14_save, r14);
__ movptr(r15_save, r15);
#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 rsi_save(rbp, rsi_off * wordSize);
@ -360,6 +376,11 @@ class StubGenerator: public StubCodeGenerator {
#endif
// 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(r14, r14_save);
__ movptr(r13, r13_save);
@ -2428,8 +2449,8 @@ class StubGenerator: public StubCodeGenerator {
//
address generate_generic_copy(const char *name,
address byte_copy_entry, address short_copy_entry,
address int_copy_entry, address long_copy_entry,
address oop_copy_entry, address checkcast_copy_entry) {
address int_copy_entry, address oop_copy_entry,
address long_copy_entry, address checkcast_copy_entry) {
Label L_failed, L_failed_0, L_objArray;
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) {
#ifdef ASSERT
if (!EnableMethodHandles)
if (!EnableInvokeDynamic)
// @@@ FIXME: Should we correct interpreter_frame_sender_sp in the calling sequences?
// Probably, since deoptimization doesn't work yet.
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;
if (interpreter_frame != NULL) {
#ifdef ASSERT
if (!EnableMethodHandles)
if (!EnableInvokeDynamic)
// @@@ FIXME: Should we correct interpreter_frame_sender_sp in the calling sequences?
// Probably, since deoptimization doesn't work yet.
assert(caller->unextended_sp() == interpreter_frame->interpreter_frame_sender_sp(), "Frame not properly walkable");

View File

@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
#include "asm/assembler.hpp"
#include "interpreter/interpreter.hpp"
#include "interpreter/interpreterRuntime.hpp"
#include "interpreter/templateTable.hpp"
@ -391,8 +392,8 @@ void TemplateTable::ldc(bool wide) {
void TemplateTable::fast_aldc(bool wide) {
transition(vtos, atos);
if (!EnableMethodHandles) {
// We should not encounter this bytecode if !EnableMethodHandles.
if (!EnableInvokeDynamic) {
// We should not encounter this bytecode if !EnableInvokeDynamic.
// 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.
__ 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));
__ bswapl(temp);
__ cmpl(key, temp);
if (VM_Version::supports_cmov()) {
__ cmovl(Assembler::less , j, h); // j = h if (key < array[h].fast_match())
__ cmovl(Assembler::greaterEqual, i, h); // i = h if (key >= array[h].fast_match())
} else {
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); // }
}
// j = h if (key < array[h].fast_match())
__ cmov32(Assembler::less , j, h);
// i = h if (key >= array[h].fast_match())
__ cmov32(Assembler::greaterEqual, i, h);
// while (i+1 < j)
__ bind(entry);
__ 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)
{ Label entry, loop, exit;
__ 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
__ 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
__ jmpb(entry);
__ bind(loop);
__ cmpptr(Address(rcx, BasicObjectLock::obj_offset_in_bytes()), (int32_t)NULL_WORD); // check if current entry is used
// 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);
}
__ cmovptr(Assembler::equal, rdx, rcx); // if not used then remember entry in rdx
__ 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
__ 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) {
transition(vtos, atos);
if (!EnableMethodHandles) {
// We should not encounter this bytecode if !EnableMethodHandles.
if (!EnableInvokeDynamic) {
// We should not encounter this bytecode if !EnableInvokeDynamic.
// 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.
__ call_VM(noreg, CAST_FROM_FN_PTR(address,

View File

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

View File

@ -574,12 +574,11 @@ int MachCallDynamicJavaNode::ret_addr_offset()
// In os_cpu .ad file
// int MachCallRuntimeNode::ret_addr_offset()
// Indicate if the safepoint node needs the polling page as an input.
// Since amd64 does not have absolute addressing but RIP-relative
// addressing and the polling page is within 2G, it doesn't.
// Indicate if the safepoint node needs the polling page as an input,
// it does if the polling page is more than disp32 away.
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;
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_cr("popq\trbp");
st->print_cr("popq rbp");
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");
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
@ -1033,45 +1038,22 @@ void MachEpilogNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const
emit_opcode(cbuf, 0x58 | RBP_enc);
if (do_polling() && C->is_method_compilation()) {
// 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_return_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_return_type,
MacroAssembler _masm(&cbuf);
AddressLiteral polling_page(os::get_polling_page(), relocInfo::poll_return_type);
if (Assembler::is_polling_page_far()) {
__ lea(rscratch1, polling_page);
__ relocate(relocInfo::poll_return_type);
__ testl(rax, Address(rscratch1, 0));
} else {
__ testl(rax, polling_page);
}
}
}
uint MachEpilogNode::size(PhaseRegAlloc* ra_) const
{
Compile* C = ra_->C;
int framesize = C->frame_slots() << LogBytesPerInt;
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;
return MachNode::size(ra_); // too many variables; just compute it
// the hard way
}
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
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() {
assert(UseCompressedOops, "only for compressed oops code");
return (LogMinObjAlignmentInBytes <= 3);
@ -3406,8 +3392,8 @@ encode %{
}
if (EmitSync & 1) {
// 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.cmpptr(rsp, (int32_t)NULL_WORD) ;
masm.movptr (Address(boxReg, 0), (int32_t)intptr_t(markOopDesc::unused_mark())) ;
masm.cmpptr(rsp, (int32_t)NULL_WORD) ;
} else
if (EmitSync & 2) {
Label DONE_LABEL;
@ -3435,10 +3421,10 @@ encode %{
} else {
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.jcc (Assembler::notZero, IsInflated) ;
masm.jcc (Assembler::notZero, IsInflated) ;
// it's stack-locked, biased or neutral
// TODO: optimize markword triage order to reduce the number of
// conditional branches in the most common cases.
@ -3452,9 +3438,9 @@ encode %{
}
// was q will it destroy high?
masm.orl (tmpReg, 1) ;
masm.movptr(Address(boxReg, 0), tmpReg) ;
if (os::is_MP()) { masm.lock(); }
masm.orl (tmpReg, 1) ;
masm.movptr(Address(boxReg, 0), tmpReg) ;
if (os::is_MP()) { masm.lock(); }
masm.cmpxchgptr(boxReg, Address(objReg, 0)); // Updates tmpReg
if (_counters != NULL) {
masm.cond_inc32(Assembler::equal,
@ -3481,16 +3467,16 @@ encode %{
// fetched _owner. If the CAS is successful we may
// avoid an RTO->RTS upgrade on the $line.
// 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.movptr (tmpReg, Address(tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)) ;
masm.testptr(tmpReg, tmpReg) ;
masm.jcc (Assembler::notZero, DONE_LABEL) ;
masm.mov (boxReg, tmpReg) ;
masm.movptr (tmpReg, Address(tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)) ;
masm.testptr(tmpReg, tmpReg) ;
masm.jcc (Assembler::notZero, DONE_LABEL) ;
// It's inflated and appears unlocked
if (os::is_MP()) { masm.lock(); }
masm.cmpxchgptr(r15_thread, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2)) ;
if (os::is_MP()) { masm.lock(); }
masm.cmpxchgptr(r15_thread, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2)) ;
// Intentional fall-through into DONE_LABEL ...
masm.bind (DONE_LABEL) ;
@ -3509,8 +3495,8 @@ encode %{
Register tmpReg = as_Register($tmp$$reg);
MacroAssembler masm(&cbuf);
if (EmitSync & 4) {
masm.cmpptr(rsp, 0) ;
if (EmitSync & 4) {
masm.cmpptr(rsp, 0) ;
} else
if (EmitSync & 8) {
Label DONE_LABEL;
@ -3537,25 +3523,25 @@ encode %{
if (UseBiasedLocking && !UseOptoBiasInlining) {
masm.biased_locking_exit(objReg, tmpReg, DONE_LABEL);
}
masm.movptr(tmpReg, Address(objReg, 0)) ;
masm.cmpptr(Address(boxReg, 0), (int32_t)NULL_WORD) ;
masm.jcc (Assembler::zero, DONE_LABEL) ;
masm.testl (tmpReg, 0x02) ;
masm.jcc (Assembler::zero, Stacked) ;
masm.movptr(tmpReg, Address(objReg, 0)) ;
masm.cmpptr(Address(boxReg, 0), (int32_t)NULL_WORD) ;
masm.jcc (Assembler::zero, DONE_LABEL) ;
masm.testl (tmpReg, 0x02) ;
masm.jcc (Assembler::zero, Stacked) ;
// It's inflated
masm.movptr(boxReg, Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)) ;
masm.xorptr(boxReg, r15_thread) ;
masm.orptr (boxReg, Address (tmpReg, ObjectMonitor::recursions_offset_in_bytes()-2)) ;
masm.jcc (Assembler::notZero, DONE_LABEL) ;
masm.movptr(boxReg, Address (tmpReg, ObjectMonitor::cxq_offset_in_bytes()-2)) ;
masm.orptr (boxReg, Address (tmpReg, ObjectMonitor::EntryList_offset_in_bytes()-2)) ;
masm.jcc (Assembler::notZero, CheckSucc) ;
masm.movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), (int32_t)NULL_WORD) ;
masm.jmp (DONE_LABEL) ;
if ((EmitSync & 65536) == 0) {
masm.movptr(boxReg, Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)) ;
masm.xorptr(boxReg, r15_thread) ;
masm.orptr (boxReg, Address (tmpReg, ObjectMonitor::recursions_offset_in_bytes()-2)) ;
masm.jcc (Assembler::notZero, DONE_LABEL) ;
masm.movptr(boxReg, Address (tmpReg, ObjectMonitor::cxq_offset_in_bytes()-2)) ;
masm.orptr (boxReg, Address (tmpReg, ObjectMonitor::EntryList_offset_in_bytes()-2)) ;
masm.jcc (Assembler::notZero, CheckSucc) ;
masm.movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), (int32_t)NULL_WORD) ;
masm.jmp (DONE_LABEL) ;
if ((EmitSync & 65536) == 0) {
Label LSuccess, LGoSlowPath ;
masm.bind (CheckSucc) ;
masm.cmpptr(Address (tmpReg, ObjectMonitor::succ_offset_in_bytes()-2), (int32_t)NULL_WORD) ;
@ -3587,9 +3573,9 @@ encode %{
masm.jmp (DONE_LABEL) ;
}
masm.bind (Stacked) ;
masm.bind (Stacked) ;
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
if (EmitSync & 65536) {
@ -3910,22 +3896,6 @@ encode %{
// 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);
%}
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
operand immN() %{
match(ConN);
@ -4836,7 +4815,7 @@ operand regF()
%}
// Double register operands
operand regD()
operand regD()
%{
constraint(ALLOC_IN_RC(double_reg));
match(RegD);
@ -6564,6 +6543,16 @@ instruct loadConP0(rRegP dst, immP0 src, rFlagsReg cr)
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)
%{
match(Set dst src);
@ -7237,11 +7226,11 @@ instruct bytes_reverse_long(rRegL dst) %{
instruct bytes_reverse_unsigned_short(rRegI dst) %{
match(Set dst (ReverseBytesUS dst));
format %{ "bswapl $dst\n\t"
format %{ "bswapl $dst\n\t"
"shrl $dst,16\n\t" %}
ins_encode %{
__ bswapl($dst$$Register);
__ shrl($dst$$Register, 16);
__ shrl($dst$$Register, 16);
%}
ins_pipe( ialu_reg );
%}
@ -7249,11 +7238,11 @@ instruct bytes_reverse_unsigned_short(rRegI dst) %{
instruct bytes_reverse_short(rRegI dst) %{
match(Set dst (ReverseBytesS dst));
format %{ "bswapl $dst\n\t"
format %{ "bswapl $dst\n\t"
"sar $dst,16\n\t" %}
ins_encode %{
__ bswapl($dst$$Register);
__ sarl($dst$$Register, 16);
__ sarl($dst$$Register, 16);
%}
ins_pipe( ialu_reg );
%}
@ -7476,7 +7465,7 @@ instruct membar_volatile(rFlagsReg cr) %{
effect(KILL cr);
ins_cost(400);
format %{
format %{
$$template
if (os::is_MP()) {
$$emit$$"lock addl [rsp + #0], 0\t! membar_volatile"
@ -8287,7 +8276,7 @@ instruct storePConditional(memory heap_top_ptr,
rFlagsReg cr)
%{
match(Set cr (StorePConditional heap_top_ptr (Binary oldval newval)));
format %{ "cmpxchgq $heap_top_ptr, $newval\t# (ptr) "
"If rax == $heap_top_ptr then store $newval into $heap_top_ptr" %}
opcode(0x0F, 0xB1);
@ -9850,9 +9839,9 @@ instruct xorI_rReg(rRegI dst, rRegI src, rFlagsReg cr)
// Xor Register with Immediate -1
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 %{
__ notl($dst$$Register);
%}
@ -10093,9 +10082,9 @@ instruct xorL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
// Xor Register with Immediate -1
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 %{
__ notq($dst$$Register);
%}
@ -12469,14 +12458,33 @@ instruct cmpFastUnlock(rFlagsReg cr,
// Safepoint Instructions
instruct safePoint_poll(rFlagsReg cr)
%{
predicate(!Assembler::is_polling_page_far());
match(SafePoint);
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" %}
size(6); // Opcode + ModRM + Disp32 == 6 bytes
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);
%}

View File

@ -47,18 +47,6 @@ public class Util {
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) {
StringBuffer sb = new StringBuffer();

View File

@ -587,7 +587,6 @@ public abstract class WinGammaPlatform {
Vector allConfigs = new Vector();
allConfigs.add(new C1DebugConfig());
allConfigs.add(new C1FastDebugConfig());
allConfigs.add(new C1ProductConfig());
@ -655,6 +654,10 @@ public abstract class WinGammaPlatform {
boolean isHeader() {
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;
public void writeProjectFile(String projectFileName, String projectName,
Vector allConfigs) throws IOException {
Vector<BuildConfig> allConfigs) throws IOException {
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";};
public void writeProjectFile(String projectFileName, String projectName,
Vector allConfigs) throws IOException {
Vector<BuildConfig> allConfigs) throws IOException {
System.out.println();
System.out.println(" Writing .vcproj file: "+projectFileName);
// If we got this far without an error, we're safe to actually
@ -54,11 +54,11 @@ public class WinGammaPlatformVC7 extends WinGammaPlatform {
"SccLocalPath", ""
}
);
startTag("Platforms", null);
startTag("Platforms");
tag("Platform", new String[] {"Name", (String) BuildConfig.getField(null, "PlatformName")});
endTag("Platforms");
startTag("Configurations", null);
startTag("Configurations");
for (Iterator i = allConfigs.iterator(); i.hasNext(); ) {
writeConfiguration((BuildConfig)i.next());
@ -66,11 +66,11 @@ public class WinGammaPlatformVC7 extends WinGammaPlatform {
endTag("Configurations");
tag("References", null);
tag("References");
writeFiles(allConfigs);
tag("Globals", null);
tag("Globals");
endTag("VisualStudioProject");
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 {
TerminatorFilter(String fname) {
this.fname = fname;
@ -299,8 +277,8 @@ public class WinGammaPlatformVC7 extends WinGammaPlatform {
// - 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
// and remove from the list
Vector makeFilters(TreeSet<FileInfo> files) {
Vector rv = new Vector();
Vector<NameFilter> makeFilters(TreeSet<FileInfo> files) {
Vector<NameFilter> rv = new Vector<NameFilter>();
String sbase = Util.normalize(BuildConfig.getFieldString(null, "SourceBase")+"/src/");
String currentDir = "";
@ -370,13 +348,12 @@ public class WinGammaPlatformVC7 extends WinGammaPlatform {
rv.add(new SpecificNameFilter("Precompiled Header", new String[] {"precompiled.hpp"}));
// 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"));
return rv;
}
void writeFiles(Vector allConfigs) {
void writeFiles(Vector<BuildConfig> allConfigs) {
Hashtable allFiles = computeAttributedFiles(allConfigs);
@ -387,7 +364,7 @@ public class WinGammaPlatformVC7 extends WinGammaPlatform {
TreeSet sortedFiles = sortFiles(allFiles);
startTag("Files", null);
startTag("Files");
for (Iterator i = makeFilters(sortedFiles).iterator(); i.hasNext(); ) {
doWriteFiles(sortedFiles, allConfigNames, (NameFilter)i.next());
@ -555,35 +532,40 @@ public class WinGammaPlatformVC7 extends WinGammaPlatform {
int indent;
private void startTagPrim(String name,
String[] attrs,
boolean close) {
startTagPrim(name, attrs, close, true);
}
private void startTagPrim(String name,
String[] attrs,
boolean close) {
boolean close,
boolean newline) {
doIndent();
printWriter.print("<"+name);
indent++;
if (attrs != null) {
printWriter.println();
if (attrs != null && attrs.length > 0) {
for (int i=0; i<attrs.length; i+=2) {
doIndent();
printWriter.print(" " + attrs[i]+"=\""+attrs[i+1]+"\"");
if (i < attrs.length - 2) {
printWriter.println();
}
}
}
if (close) {
indent--;
//doIndent();
printWriter.println("/>");
printWriter.print(" />");
} else {
//doIndent();
printWriter.println(">");
printWriter.print(">");
}
if(newline) {
printWriter.println();
}
}
void startTag(String name, String[] attrs) {
void startTag(String name, String... attrs) {
startTagPrim(name, attrs, false);
}
@ -601,11 +583,25 @@ public class WinGammaPlatformVC7 extends WinGammaPlatform {
printWriter.println("</"+name+">");
}
void tag(String name, String[] attrs) {
void tag(String name, String... attrs) {
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()];
for (int i=0; i<attrs.size(); i++) {
s[i] = (String)attrs.elementAt(i);
@ -616,7 +612,7 @@ public class WinGammaPlatformVC7 extends WinGammaPlatform {
void doIndent() {
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, "nativeInst_sparc.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
AD.addInclude(AD._HPP_file, "memory/allocation.hpp");
AD.addInclude(AD._HPP_file, "opto/machnode.hpp");

View File

@ -30,6 +30,7 @@
#include "c1/c1_InstructionPrinter.hpp"
#include "ci/ciField.hpp"
#include "ci/ciKlass.hpp"
#include "compiler/compileBroker.hpp"
#include "interpreter/bytecode.hpp"
#include "runtime/sharedRuntime.hpp"
#include "utilities/bitMap.inline.hpp"
@ -3775,24 +3776,7 @@ void GraphBuilder::append_unsafe_CAS(ciMethod* callee) {
#ifndef PRODUCT
void GraphBuilder::print_inline_result(ciMethod* callee, bool res) {
const char sync_char = callee->is_synchronized() ? 's' : ' ';
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();
CompileTask::print_inlining(callee, scope()->level(), bci(), _inline_bailout_msg);
if (res && CIPrintMethodCodes) {
callee->print_codes();
}

View File

@ -1871,7 +1871,8 @@ void ciTypeFlow::Block::print_value_on(outputStream* st) const {
// ------------------------------------------------------------------
// ciTypeFlow::Block::print_on
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);
}
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",
tag, CHECK);
}
if (!EnableMethodHandles) {
if (!EnableInvokeDynamic) {
classfile_parse_error(
"This JVM does not support constant tag %u in class file %s",
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);
}
if (AnonymousClasses && has_cp_patch_at(index)) {
if (EnableInvokeDynamic && has_cp_patch_at(index)) {
Handle patch = clear_cp_patch_at(index);
guarantee_property(java_lang_String::is_instance(patch()),
"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);
check_property(
valid_cp_range(ref_index, length) &&
EnableMethodHandles,
EnableInvokeDynamic,
"Invalid constant pool index %u in class file %s",
ref_index, CHECK_(nullHandle));
constantTag tag = cp->tag_at(ref_index);
@ -487,7 +487,7 @@ constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) {
check_property(
valid_cp_range(ref_index, length) &&
cp->tag_at(ref_index).is_utf8() &&
EnableMethodHandles,
EnableInvokeDynamic,
"Invalid constant pool index %u in class file %s",
ref_index, CHECK_(nullHandle));
}
@ -522,7 +522,7 @@ constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) {
if (_cp_patches != NULL) {
// need to treat this_class specially...
assert(AnonymousClasses, "");
assert(EnableInvokeDynamic, "");
int this_class_index;
{
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) {
assert(AnonymousClasses, "");
assert(EnableInvokeDynamic, "");
BasicType patch_type = T_VOID;
switch (cp->tag_at(index).value()) {
@ -2103,7 +2103,7 @@ methodHandle ClassFileParser::parse_method(constantPoolHandle cp, bool is_interf
_has_vanilla_constructor = true;
}
if (EnableMethodHandles && (m->is_method_handle_invoke() ||
if (EnableInvokeDynamic && (m->is_method_handle_invoke() ||
m->is_method_handle_adapter())) {
THROW_MSG_(vmSymbols::java_lang_VirtualMachineError(),
"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
// a native wordSize field in Java, we must do it at this level.
if (!EnableMethodHandles) return;
if (!EnableInvokeDynamic) return;
int word_sig_index = 0;
const int cp_size = cp->length();
@ -3191,15 +3191,15 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
next_nonstatic_field_offset = first_nonstatic_field_offset;
// 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));
}
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));
}
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
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);
bool is_anonymous() {
assert(AnonymousClasses || _host_klass.is_null(), "");
assert(EnableInvokeDynamic || _host_klass.is_null(), "");
return _host_klass.not_null();
}
bool has_cp_patch_at(int index) {
assert(AnonymousClasses, "");
assert(EnableInvokeDynamic, "");
assert(index >= 0, "oob");
return (_cp_patches != NULL
&& index < _cp_patches->length()
@ -258,7 +258,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
// constant pool construction, but in later versions they can.
// %%% Let's phase out the old is_klass_reference.
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_reference());
}

View File

@ -301,6 +301,15 @@ jchar* java_lang_String::as_unicode_string(oop java_string, int& length) {
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) {
oop obj = java_string();
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() {
klassOop k = SystemDictionary::MethodHandle_klass();
if (k != NULL && EnableMethodHandles) {
if (k != NULL && EnableInvokeDynamic) {
bool allow_super = false;
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);
@ -2337,7 +2346,7 @@ void java_lang_invoke_MethodHandle::compute_offsets() {
void java_lang_invoke_MemberName::compute_offsets() {
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(_name_offset, k, vmSymbols::name_name(), vmSymbols::string_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() {
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);
}
}
void java_lang_invoke_BoundMethodHandle::compute_offsets() {
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(_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() {
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);
}
}
@ -2982,7 +2991,7 @@ void JavaClasses::compute_offsets() {
java_lang_Class::compute_offsets();
java_lang_Thread::compute_offsets();
java_lang_ThreadGroup::compute_offsets();
if (EnableMethodHandles) {
if (EnableInvokeDynamic) {
java_lang_invoke_MethodHandle::compute_offsets();
java_lang_invoke_MemberName::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_MethodType::compute_offsets();
java_lang_invoke_MethodTypeForm::compute_offsets();
}
if (EnableInvokeDynamic) {
java_lang_invoke_CallSite::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 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);
// 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.
*
* 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;
oop StringTable::lookup(int index, jchar* name,
@ -561,7 +534,7 @@ oop StringTable::lookup(Symbol* symbol) {
ResourceMark rm;
int 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);
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,
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);
oop string = the_table()->lookup(index, name, len, hashValue);
@ -663,10 +636,7 @@ void StringTable::verify() {
oop s = p->literal();
guarantee(s != NULL, "interned string is NULL");
guarantee(s->is_perm() || !JavaObjectsInPerm, "interned string not in permspace");
int length;
jchar* chars = java_lang_String::as_unicode_string(s, length);
unsigned int h = hash_string(chars, length);
unsigned int h = java_lang_String::hash_string(s);
guarantee(p->hash() == h, "broken hash in string table entry");
guarantee(the_table()->hash_to_index(h) == i,
"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.
*
* 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);
}
static int hash_string(jchar* s, int len);
// GC support
// Delete pointers to otherwise-unreachable objects.
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()) {
assert(AnonymousClasses, "");
assert(EnableInvokeDynamic, "");
// If it's anonymous, initialize it now, since nobody else will.
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
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) {
backup_symbol = find_backup_class_name(symbol);
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(PhantomReference_klass))->set_reference_type(REF_PHANTOM);
WKID meth_group_start = WK_KLASS_ENUM_NAME(MethodHandle_klass);
WKID meth_group_end = WK_KLASS_ENUM_NAME(WrongMethodTypeException_klass);
initialize_wk_klasses_until(meth_group_start, scan, CHECK);
if (EnableMethodHandles) {
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);
// JSR 292 classes
WKID jsr292_group_start = WK_KLASS_ENUM_NAME(MethodHandle_klass);
WKID jsr292_group_end = WK_KLASS_ENUM_NAME(CallSite_klass);
initialize_wk_klasses_until(jsr292_group_start, scan, CHECK);
if (EnableInvokeDynamic) {
initialize_wk_klasses_through(indy_group_end, scan, CHECK);
}
if (_well_known_klasses[indy_group_start] == NULL) {
// Skip the rest of the dynamic typing classes, if Linkage is not loaded.
scan = WKID(indy_group_end+1);
initialize_wk_klasses_through(jsr292_group_end, scan, CHECK);
} else {
// Skip the JSR 292 classes, if not enabled.
scan = WKID(jsr292_group_end + 1);
}
initialize_wk_klasses_until(WKID_LIMIT, scan, CHECK);
@ -2407,7 +2397,7 @@ methodOop SystemDictionary::find_method_handle_invoke(Symbol* name,
Symbol* signature,
KlassHandle accessing_klass,
TRAPS) {
if (!EnableMethodHandles) return NULL;
if (!EnableInvokeDynamic) return NULL;
vmSymbols::SID name_id = vmSymbols::find_sid(name);
assert(name_id != vmSymbols::NO_SID, "must be a known name");
unsigned int hash = invoke_method_table()->compute_hash(signature, name_id);

View File

@ -207,7 +207,7 @@ class SystemDictionary : AllStatic {
enum InitOption {
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.
// Options after this point will use resolve_or_null instead.

View File

@ -28,6 +28,7 @@
#include "code/nmethod.hpp"
#include "code/scopeDesc.hpp"
#include "compiler/abstractCompiler.hpp"
#include "compiler/compileBroker.hpp"
#include "compiler/compileLog.hpp"
#include "compiler/compilerOracle.hpp"
#include "compiler/disassembler.hpp"
@ -469,6 +470,7 @@ void nmethod::init_defaults() {
nmethod* nmethod::new_native_nmethod(methodHandle method,
int compile_id,
CodeBuffer *code_buffer,
int vep_offset,
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::Frame_Complete, frame_complete);
nm = new (native_nmethod_size)
nmethod(method(), native_nmethod_size, &offsets,
nmethod(method(), native_nmethod_size, compile_id, &offsets,
code_buffer, frame_size,
basic_lock_owner_sp_offset, basic_lock_sp_offset,
oop_maps);
@ -610,6 +612,7 @@ nmethod* nmethod::new_nmethod(methodHandle method,
nmethod::nmethod(
methodOop method,
int nmethod_size,
int compile_id,
CodeOffsets* offsets,
CodeBuffer* code_buffer,
int frame_size,
@ -644,7 +647,7 @@ nmethod::nmethod(
_handler_table_offset = _dependencies_offset;
_nul_chk_table_offset = _handler_table_offset;
_nmethod_end_offset = _nul_chk_table_offset;
_compile_id = 0; // default
_compile_id = compile_id;
_comp_level = CompLevel_none;
_entry_point = code_begin() + offsets->value(CodeOffsets::Entry);
_verified_entry_point = code_begin() + offsets->value(CodeOffsets::Verified_Entry);
@ -930,72 +933,11 @@ void nmethod::log_new_nmethod() const {
#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.
void nmethod::print_on(outputStream* st, const char* title) const {
void nmethod::print_on(outputStream* st, const char* msg) const {
if (st != NULL) {
ttyLocker ttyl;
print_compilation(st, /*method_name*/NULL, title,
method(), /*is_blocking*/false,
compile_id(),
is_osr_method() ? osr_entry_bci() : InvocationEntryBci,
comp_level());
CompileTask::print_compilation(st, this, msg);
if (WizardMode) st->print(" (" INTPTR_FORMAT ")", this);
}
}
@ -1309,8 +1251,7 @@ void nmethod::log_state_change() const {
}
}
if (PrintCompilation && _state != unloaded) {
print_on(tty, _state == zombie ? "made zombie " : "made not entrant ");
tty->cr();
print_on(tty, _state == zombie ? "made zombie" : "made not entrant");
}
}
@ -1816,7 +1757,7 @@ bool nmethod::test_set_oops_do_mark() {
break;
}
// 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;
}
}
@ -1841,7 +1782,7 @@ void nmethod::oops_do_marking_epilogue() {
nmethod* next = cur->_oops_do_mark_link;
cur->_oops_do_mark_link = NULL;
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;
}
void* required = _oops_do_mark_nmethods;
@ -2396,7 +2337,7 @@ void nmethod::print() const {
ResourceMark rm;
ttyLocker ttyl; // keep the following output all in one block
tty->print("Compiled ");
tty->print("Compiled method ");
if (is_compiled_by_c1()) {
tty->print("(c1) ");
@ -2408,8 +2349,8 @@ void nmethod::print() const {
tty->print("(nm) ");
}
print_on(tty, "nmethod");
tty->cr();
print_on(tty, NULL);
if (WizardMode) {
tty->print("((nmethod*) "INTPTR_FORMAT ") ", this);
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
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) {

View File

@ -229,6 +229,7 @@ class nmethod : public CodeBlob {
// For native wrappers
nmethod(methodOop method,
int nmethod_size,
int compile_id,
CodeOffsets* offsets,
CodeBuffer *code_buffer,
int frame_size,
@ -299,6 +300,7 @@ class nmethod : public CodeBlob {
int comp_level);
static nmethod* new_native_nmethod(methodHandle method,
int compile_id,
CodeBuffer *code_buffer,
int vep_offset,
int frame_complete,
@ -500,8 +502,8 @@ public:
address continuation_for_implicit_exception(address pc);
// On-stack replacement support
int osr_entry_bci() const { assert(_entry_bci != InvocationEntryBci, "wrong kind of nmethod"); return _entry_bci; }
address osr_entry() const { assert(_entry_bci != InvocationEntryBci, "wrong kind of nmethod"); return _osr_entry_point; }
int osr_entry_bci() const { assert(is_osr_method(), "wrong kind of nmethod"); return _entry_bci; }
address osr_entry() const { assert(is_osr_method(), "wrong kind of nmethod"); return _osr_entry_point; }
void invalidate_osr_method();
nmethod* osr_link() const { return _osr_link; }
void set_osr_link(nmethod *n) { _osr_link = n; }
@ -608,10 +610,6 @@ public:
void verify_scopes();
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
void print() const;
void print_code();
@ -627,7 +625,7 @@ public:
// need to re-define this from CodeBlob else the overload hides it
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
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
//
@ -284,32 +279,116 @@ void CompileTask::print_compilation(outputStream *st, methodOop method, char* me
// Otherwise it's the same as CompileTask::print_line()
//
void CompileTask::print_line_on_error(outputStream* st, char* buf, int buflen) {
methodOop method = (methodOop)JNIHandles::resolve(_method);
// print compiler name
st->print("%s:", CompileBroker::compiler(comp_level())->name());
char* method_name = NULL;
if (method != NULL) {
method_name = method->name_and_sig_as_C_string(buf, buflen);
}
print_compilation(st, method, method_name);
print_compilation(st);
}
// ------------------------------------------------------------------
// 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
// print compiler name if requested
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
void CompileTask::log_task(xmlStream* log) {
@ -874,6 +953,14 @@ void CompileBroker::compile_method_base(methodHandle method,
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
// we do not block the current thread.
@ -1078,7 +1165,13 @@ nmethod* CompileBroker::compile_method(methodHandle method, int osr_bci,
// do the compilation
if (method->is_native()) {
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 {
return NULL;
}
@ -1186,7 +1279,6 @@ uint CompileBroker::assign_compile_id(methodHandle method, int osr_bci) {
assert(MethodCompileQueue_lock->owner() == Thread::current(),
"must hold the compilation queue lock");
bool is_osr = (osr_bci != standard_entry_bci);
assert(!method->is_native(), "no longer compile natives");
uint id;
if (CICountOSR && is_osr) {
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.
*
* 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
const char* _comment; // more info about the task
void print_compilation(outputStream *st, methodOop method, char* method_name);
public:
CompileTask() {
_lock = new Monitor(Mutex::nonleaf+2, "CompileTaskLock");
@ -96,10 +95,26 @@ class CompileTask : public CHeapObj {
CompileTask* prev() const { return _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_line();
void print_line_on_error(outputStream* st, char* buf, int buflen);
void log_task(xmlStream* log);
void log_task_queued();
void log_task_start(CompileLog* log);

View File

@ -2383,17 +2383,6 @@ run:
}
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,
Bytecodes::name((Bytecodes::Code)opcode)));
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) {
methodOop result_oop = klass->uncached_lookup_method(name, signature);
if (EnableMethodHandles && result_oop != NULL) {
if (EnableInvokeDynamic && result_oop != NULL) {
switch (result_oop->intrinsic_id()) {
case vmIntrinsics::_invokeExact:
case vmIntrinsics::_invokeGeneric:
@ -214,7 +214,7 @@ void LinkResolver::lookup_implicit_method(methodHandle& result,
KlassHandle klass, Symbol* name, Symbol* signature,
KlassHandle current_klass,
TRAPS) {
if (EnableMethodHandles &&
if (EnableInvokeDynamic &&
klass() == SystemDictionary::MethodHandle_klass() &&
methodOopDesc::is_method_handle_invoke_name(name)) {
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.
*
* This code is free software; you can redistribute it and/or modify it
@ -80,16 +80,7 @@ public:
oop obj = *p;
if (obj->klass() == SystemDictionary::String_klass()) {
int hash;
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);
}
int hash = java_lang_String::hash_string(obj);
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");
constantPoolOop cp = (constantPoolOop) obj;
if (cp->tags() != NULL &&
(!JavaObjectsInPerm || (AnonymousClasses && cp->has_pseudo_string()))) {
(!JavaObjectsInPerm || (EnableInvokeDynamic && cp->has_pseudo_string()))) {
for (int i = 1; i < cp->length(); ++i) {
if (cp->tag_at(i).is_string()) {
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.
*
* 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 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.
// Method oops internally created for method handles may also
// 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) {
assert(AnonymousClasses, "");
assert(EnableInvokeDynamic, "");
set_pseudo_string(); // mark header
assert(tag_at(which).is_string() || tag_at(which).is_unresolved_string(), "Corrupted constant pool");
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 static_oop_field_count: %d", java_lang_Class::static_oop_field_count(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);
}
} else if (as_klassOop() == SystemDictionary::MethodType_klass()) {

View File

@ -182,7 +182,7 @@ class instanceKlass: public Klass {
// Protection domain.
oop _protection_domain;
// 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.
klassOop _host_klass;
// Class signers.

View File

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

View File

@ -500,7 +500,7 @@ const char* Klass::external_name() const {
if (oop_is_instance()) {
instanceKlass* ik = (instanceKlass*) this;
if (ik->is_anonymous()) {
assert(AnonymousClasses, "");
assert(EnableInvokeDynamic, "");
intptr_t hash = ik->java_mirror()->identity_hash();
char hash_buf[40];
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
// invokedynamic sometimes needs to push a bootstrap method, call site, and arglist,
// 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()
// RedefineClasses() support:

View File

@ -25,6 +25,7 @@
#include "precompiled.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "compiler/compileBroker.hpp"
#include "compiler/compileLog.hpp"
#include "interpreter/linkResolver.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");
}
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,
ciMethod* caller_method, Compile* C) {
// 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()) {
*wci_result = *(WarmCallInfo::always_hot());
if (PrintInlining && Verbose) {
print_indent(inline_depth());
CompileTask::print_inline_indent(inline_depth());
tty->print_cr("Inlined method is hot: ");
}
return NULL;
@ -116,7 +110,7 @@ const char* InlineTree::shouldInline(ciMethod* callee_method, ciMethod* caller_m
size < InlineThrowMaxSize ) {
wci_result->set_profit(wci_result->profit() * 100);
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());
}
return NULL;
@ -138,9 +132,9 @@ const char* InlineTree::shouldInline(ciMethod* callee_method, ciMethod* caller_m
max_size = C->freq_inline_size();
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);
print_indent(inline_depth());
CompileTask::print_inline_indent(inline_depth());
callee_method->print();
tty->cr();
}
@ -315,8 +309,25 @@ const char* InlineTree::try_to_inline(ciMethod* callee_method, ciMethod* caller_
if( inline_depth() > MaxInlineLevel ) {
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";
}
@ -368,18 +379,14 @@ bool pass_initial_checks(ciMethod* caller_method, int caller_bci, ciMethod* call
#ifndef PRODUCT
//------------------------------print_inlining---------------------------------
// 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 {
print_indent(inline_depth());
tty->print("@ %d ", caller_bci);
if( callee_method ) callee_method->print_short_name();
else tty->print(" callee not monotonic or profiled");
tty->print(" %s", (failure_msg ? failure_msg : "inline"));
if( Verbose && callee_method ) {
void InlineTree::print_inlining(ciMethod* callee_method, int caller_bci, const char* failure_msg) const {
CompileTask::print_inlining(callee_method, inline_depth(), caller_bci, failure_msg ? failure_msg : "inline");
if (callee_method == NULL) tty->print(" callee not monotonic or profiled");
if (Verbose && callee_method) {
const InlineTree *top = this;
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->cr();
}
#endif

View File

@ -673,7 +673,7 @@ void PhaseChaitin::gather_lrg_masks( bool after_aggressive ) {
case Op_RegD:
lrg.set_num_regs(2);
// Define platform specific register pressure
#ifdef SPARC
#if defined(SPARC) || defined(ARM)
lrg.set_reg_pressure(2);
#elif defined(IA32)
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();
}
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:
assert( !n->is_Call(), "" );
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.
*
* This code is free software; you can redistribute it and/or modify it
@ -27,6 +27,7 @@
#include "ci/ciCallSite.hpp"
#include "ci/ciMethodHandle.hpp"
#include "classfile/vmSymbols.hpp"
#include "compiler/compileBroker.hpp"
#include "compiler/compileLog.hpp"
#include "interpreter/linkResolver.hpp"
#include "opto/addnode.hpp"
@ -43,17 +44,17 @@
#ifndef PRODUCT
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) {
tty->print(" ");
for( int i = 0; i < depth; i++ ) tty->print(" ");
if (!PrintOpto) {
method->print_short_name();
tty->print(" ->");
if (!PrintInlining) {
if (!PrintOpto && !PrintCompilation) {
method->print_short_name();
tty->cr();
}
CompileTask::print_inlining(prof_method, depth, bci);
}
tty->print(" @ %d ", bci);
prof_method->print_short_name();
tty->print(" >>TypeProfile (%d/%d counts) = ", receiver_count, site_count);
CompileTask::print_inline_indent(depth);
tty->print(" \\-> TypeProfile (%d/%d counts) = ", receiver_count, site_count);
prof_klass->name()->print_symbol();
tty->print_cr(" (%d bytes)", prof_method->code_size());
tty->cr();
}
}
#endif
@ -269,13 +270,13 @@ CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index,
}
if (miss_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.
// 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);
}
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));
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.
*
* 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) {
stringStream bciStream;
ciMethod* last = NULL;
int last_bci;
while(caller) {
if (caller->has_method()) {
last = caller->method();
last_bci = caller->bci();
}
bciStream.print("%d ", caller->bci());
caller = caller->caller();
}
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) {
@ -628,6 +652,17 @@ void IdealGraphPrinter::walk_nodes(Node *start, void *param) {
GrowableArray<Node *> nodeStack(Thread::current()->resource_area(), 0, 0, NULL);
nodeStack.push(start);
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) {
Node *n = nodeStack.pop();
@ -686,16 +721,23 @@ void IdealGraphPrinter::print(Compile* compile, const char *name, Node *node, in
end_head();
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);
print_attr(BLOCK_NAME_PROPERTY, b->_succs[s]->_pre_order);
end_elem();
}
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(CONTROL_FLOW_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.
*
* This code is free software; you can redistribute it and/or modify it
@ -43,15 +43,6 @@ class ciMethod;
class IdealGraphPrinter
{
private:
enum State
{
Invalid,
Valid,
New
};
private:
static const char *INDENT;

View File

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

View File

@ -25,6 +25,7 @@
#include "precompiled.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "compiler/compileBroker.hpp"
#include "compiler/compileLog.hpp"
#include "oops/objArrayKlass.hpp"
#include "opto/addnode.hpp"
@ -388,11 +389,7 @@ JVMState* LibraryIntrinsic::generate(JVMState* jvms) {
#endif
if (kit.try_to_inline()) {
if (PrintIntrinsics || PrintInlining NOT_PRODUCT( || PrintOptoInlining) ) {
tty->print("Inlining intrinsic %s%s at bci:%d in",
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());
CompileTask::print_inlining(kit.callee(), jvms->depth() - 1, kit.bci(), is_virtual() ? "(intrinsic, virtual)" : "(intrinsic)");
}
C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_worked);
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
bool IdealLoopTree::policy_maximally_unroll( PhaseIdealLoop *phase ) const {
CountedLoopNode *cl = _head->as_CountedLoop();
assert( cl->is_normal_loop(), "" );
assert(cl->is_normal_loop(), "");
Node *init_n = cl->init_trip();
Node *limit_n = cl->limit();
// 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() ||
// protect against stride not being a constant
!cl->stride_is_con() ) {
!cl->stride_is_con()) {
return false;
}
int init = init_n->get_int();
@ -428,7 +428,31 @@ bool IdealLoopTree::policy_maximally_unroll( PhaseIdealLoop *phase ) const {
uint unroll_limit = (uint)LoopUnrollLimit * 4;
assert( (intx)unroll_limit == LoopUnrollLimit * 4, "LoopUnrollLimit must fit in 32bits");
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;
if (new_body_size <= unroll_limit &&
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 {
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
if( !cl->stride_is_con() ) return false;
if (!cl->stride_is_con()) return false;
// 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;
@ -485,21 +509,21 @@ bool IdealLoopTree::policy_unroll( PhaseIdealLoop *phase ) const {
// Non-constant bounds.
// 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.
if( init_n == NULL || !init_n->is_Con() ||
limit_n == NULL || !limit_n->is_Con() ) {
if (init_n == NULL || !init_n->is_Con() ||
limit_n == NULL || !limit_n->is_Con()) {
Node* phi = cl->phi();
if( phi != NULL ) {
if (phi != NULL) {
assert(phi->is_Phi() && phi->in(0) == _head, "Counted loop should have iv phi.");
const TypeInt* iv_type = phase->_igvn.type(phi)->is_int();
int next_stride = cl->stride_con() * 2; // stride after this unroll
if( next_stride > 0 ) {
if( iv_type->_lo + next_stride <= iv_type->_lo || // overflow
iv_type->_lo + next_stride > iv_type->_hi ) {
if (next_stride > 0) {
if (iv_type->_lo + next_stride <= iv_type->_lo || // overflow
iv_type->_lo + next_stride > iv_type->_hi) {
return false; // over-unrolling
}
} else if( next_stride < 0 ) {
if( iv_type->_hi + next_stride >= iv_type->_hi || // overflow
iv_type->_hi + next_stride < iv_type->_lo ) {
} else if (next_stride < 0) {
if (iv_type->_hi + next_stride >= iv_type->_hi || // overflow
iv_type->_hi + next_stride < iv_type->_lo) {
return false; // over-unrolling
}
}
@ -511,24 +535,33 @@ bool IdealLoopTree::policy_unroll( PhaseIdealLoop *phase ) const {
// Key test to unroll CaffeineMark's Logic test
int xors_in_loop = 0;
// Also count ModL, DivL and MulL which expand mightly
for( uint k = 0; k < _body.size(); k++ ) {
switch( _body.at(k)->Opcode() ) {
case Op_XorI: xors_in_loop++; break; // CaffeineMark's Logic test
case Op_ModL: body_size += 30; break;
case Op_DivL: body_size += 30; break;
case Op_MulL: body_size += 10; break;
}
for (uint k = 0; k < _body.size(); k++) {
Node* n = _body.at(k);
switch (n->Opcode()) {
case Op_XorI: xors_in_loop++; break; // CaffeineMark's Logic test
case Op_ModL: body_size += 30; 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
if( body_size > (uint)LoopUnrollLimit ) {
if( xors_in_loop >= 4 && body_size < (uint)LoopUnrollLimit*4) return true;
if (body_size > (uint)LoopUnrollLimit) {
if (xors_in_loop >= 4 && body_size < (uint)LoopUnrollLimit*4) return true;
// Normal case: loop too big
return false;
}
// 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)
return true;
@ -1608,15 +1641,7 @@ bool IdealLoopTree::policy_do_remove_empty_loop( PhaseIdealLoop *phase ) {
return false; // Malformed loop
if (!phase->is_member(this, phase->get_ctrl(cl->loopexit()->in(CountedLoopEndNode::TestValue))))
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
// Ensure only one phi which is the iv.
Node* iv = NULL;
@ -1629,6 +1654,43 @@ bool IdealLoopTree::policy_do_remove_empty_loop( PhaseIdealLoop *phase ) {
}
assert(iv == cl->phi(), "Wrong phi" );
#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
// iteration. Then the CountedLoopEnd will collapse (backedge never
// 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
PhaseIterGVN &igvn = phase->_igvn;
phase->C->print_method("Before beautify loops", 3);
igvn.hash_delete(_head); // Yank from hash before hacking edges
// 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;
int old_progress = C->major_progress();
uint orig_worklist_size = _igvn._worklist.size();
// Reset major-progress flag for the driver's heuristics
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.
// Do not bother doing this on the Root loop of course.
if( !_verify_me && !_verify_only && _ltree_root->_child ) {
C->print_method("Before beautify loops", 3);
if( _ltree_root->_child->beautify_loops( this ) ) {
// Re-build loop tree!
_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++)
C->set_major_progress();
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;
}

View File

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

View File

@ -427,6 +427,11 @@ public:
// Do ints take an entire long register or just half?
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.
// If it returns, the compiler should bailout to interpreter without error.
// 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
uint StrCompNode::match_edge(uint idx) const {
return idx == 2 || idx == 3; // StrComp (Binary str1 cnt1) (Binary str2 cnt2)
// Do not match memory edge.
uint StrIntrinsicNode::match_edge(uint idx) const {
return idx == 2 || idx == 3;
}
//------------------------------Ideal------------------------------------------
// Return a node which is more "ideal" than the current node. Strip out
// control copies
Node *StrCompNode::Ideal(PhaseGVN *phase, bool can_reshape){
return remove_dead_region(phase, can_reshape) ? this : NULL;
}
Node *StrIntrinsicNode::Ideal(PhaseGVN *phase, bool can_reshape) {
if (remove_dead_region(phase, can_reshape)) return this;
//=============================================================================
// Do we match on this edge? No memory edges
uint StrEqualsNode::match_edge(uint idx) const {
return idx == 2 || idx == 3; // StrEquals (Binary str1 str2) cnt
}
//------------------------------Ideal------------------------------------------
// Return a node which is more "ideal" than the current node. Strip out
// control copies
Node *StrEqualsNode::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 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;
if (can_reshape) {
Node* mem = phase->transform(in(MemNode::Memory));
// If transformed to a MergeMem, get the desired slice
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)) {
set_req(MemNode::Memory, mem);
return this;
}
}
return NULL;
}
//=============================================================================

View File

@ -776,67 +776,69 @@ public:
static bool step_through(Node** np, uint instance_id, PhaseTransform* phase);
};
//------------------------------StrComp-------------------------------------
class StrCompNode: public Node {
//------------------------------StrIntrinsic-------------------------------
// Base class for Ideal nodes used in String instrinsic code.
class StrIntrinsicNode: public Node {
public:
StrCompNode(Node* control, Node* char_array_mem,
Node* s1, Node* c1,
Node* s2, Node* c2): Node(control, char_array_mem,
s1, c1,
s2, c2) {};
virtual int Opcode() const;
StrIntrinsicNode(Node* control, Node* char_array_mem,
Node* s1, Node* c1, Node* s2, Node* c2):
Node(control, char_array_mem, s1, c1, s2, c2) {
}
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 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);
};
//------------------------------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-------------------------------------
class StrEqualsNode: public Node {
class StrEqualsNode: public StrIntrinsicNode {
public:
StrEqualsNode(Node* control, Node* char_array_mem,
Node* s1, Node* s2, Node* c): Node(control, char_array_mem,
s1, s2, c) {};
Node* s1, Node* s2, Node* c):
StrIntrinsicNode(control, char_array_mem, s1, s2, c) {};
virtual int Opcode() const;
virtual bool depends_only_on_test() const { return false; }
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-------------------------------------
class StrIndexOfNode: public Node {
class StrIndexOfNode: public StrIntrinsicNode {
public:
StrIndexOfNode(Node* control, Node* char_array_mem,
Node* s1, Node* c1,
Node* s2, Node* c2): Node(control, char_array_mem,
s1, c1,
s2, c2) {};
Node* s1, Node* c1, Node* s2, Node* c2):
StrIntrinsicNode(control, char_array_mem, s1, c1, s2, c2) {};
virtual int Opcode() const;
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 uint match_edge(uint idx) const;
virtual uint ideal_reg() const { return Op_RegI; }
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
};
//------------------------------AryEq---------------------------------------
class AryEqNode: public Node {
class AryEqNode: public StrIntrinsicNode {
public:
AryEqNode(Node* control, Node* char_array_mem,
Node* s1, Node* s2): Node(control, char_array_mem, s1, s2) {};
AryEqNode(Node* control, Node* char_array_mem, Node* s1, Node* s2):
StrIntrinsicNode(control, char_array_mem, s1, s2) {};
virtual int Opcode() const;
virtual bool depends_only_on_test() const { return false; }
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-----------------------------------------

View File

@ -1373,12 +1373,12 @@ static inline bool NotANode(const Node* n) {
//------------------------------find------------------------------------------
// Find a neighbor of this Node with the given _idx
// 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,
VectorSet &old_space, VectorSet &new_space ) {
static void find_recur(Compile* C, Node* &result, Node *n, int idx, bool only_ctrl,
VectorSet* old_space, VectorSet* new_space ) {
int node_idx = (idx >= 0) ? idx : -idx;
if (NotANode(n)) return; // Gracefully handle NULL, -1, 0xabababab, etc.
// Contained in new_space or old_space?
VectorSet *v = Compile::current()->node_arena()->contains(n) ? &new_space : &old_space;
// Contained in new_space or old_space? Check old_arena first since it's mostly empty.
VectorSet *v = C->old_arena()->contains(n) ? old_space : new_space;
if( v->test(n->_idx) ) return;
if( (int)n->_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);
for( uint i=0; i<n->len(); i++ ) {
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:
if (idx < 0 && !only_ctrl) {
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
// Search along debug_orig edges last:
for (Node* orig = n->debug_orig(); orig != NULL && n != orig; orig = orig->debug_orig()) {
if (NotANode(orig)) break;
find_recur( result, orig, idx, only_ctrl, old_space, new_space );
// Search along debug_orig edges last, checking for cycles
Node* orig = n->debug_orig();
if (orig != NULL) {
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
}
@ -1417,7 +1421,7 @@ Node* Node::find(int idx) const {
ResourceArea *area = Thread::current()->resource_area();
VectorSet old_space(area), new_space(area);
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;
}
@ -1427,7 +1431,7 @@ Node* Node::find_ctrl(int idx) const {
ResourceArea *area = Thread::current()->resource_area();
VectorSet old_space(area), new_space(area);
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;
}
#endif

View File

@ -112,7 +112,7 @@ bool MethodHandles::spot_check_entry_names() {
// 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");
@ -143,7 +143,7 @@ void MethodHandlesAdapterGenerator::generate() {
void MethodHandles::set_enabled(bool 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;
}
}
@ -2579,7 +2579,6 @@ static JNINativeMethod methods[] = {
{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.
static JNINativeMethod methods2[] = {
{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)) {
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 (!EnableMethodHandles) {
warning("JSR 292 method handles are disabled in this JVM. Use -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles to enable.");
if (!EnableInvokeDynamic) {
warning("JSR 292 is disabled in this JVM. Use -XX:+UnlockDiagnosticVMOptions -XX:+EnableInvokeDynamic to enable.");
return; // bind nothing
}
@ -2702,11 +2699,6 @@ JVM_ENTRY(void, JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass MHN_class))
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) {
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));
if (env->ExceptionOccurred()) {
if (PrintMiscellaneous && (Verbose || WizardMode)) {

View File

@ -2974,21 +2974,28 @@ jint Arguments::parse(const JavaVMInitArgs* args) {
}
#endif // PRODUCT
if (EnableInvokeDynamic && !EnableMethodHandles) {
if (!FLAG_IS_DEFAULT(EnableMethodHandles)) {
warning("forcing EnableMethodHandles true because EnableInvokeDynamic is true");
// Transitional
if (EnableMethodHandles || AnonymousClasses) {
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)) {
warning("forcing AnonymousClasses true because EnableMethodHandles is true");
// JSR 292 is not supported before 1.7
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)) {
warning("forcing ScavengeRootsInCode non-zero because EnableMethodHandles or AnonymousClasses is true");
warning("forcing ScavengeRootsInCode non-zero because EnableInvokeDynamic is true");
}
ScavengeRootsInCode = 1;
}

View File

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

View File

@ -2377,6 +2377,9 @@ class CommandLineFlags {
develop(intx, CICloneLoopTestLimit, 100, \
"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 */ \
\
diagnostic(bool, TraceRedundantCompiles, false, \
@ -3690,11 +3693,15 @@ class CommandLineFlags {
"Skip assert() and verify() which page-in unwanted shared " \
"objects. ") \
\
diagnostic(bool, EnableInvokeDynamic, true, \
"support JSR 292 (method handles, invokedynamic, " \
"anonymous classes") \
\
product(bool, AnonymousClasses, false, \
"support sun.misc.Unsafe.defineAnonymousClass") \
"support sun.misc.Unsafe.defineAnonymousClass (deprecated)") \
\
experimental(bool, EnableMethodHandles, false, \
"support method handles (true by default under JSR 292)") \
"support method handles (deprecated)") \
\
diagnostic(intx, MethodHandlePushLimit, 3, \
"number of additional stack slots a method handle may push") \
@ -3711,9 +3718,6 @@ class CommandLineFlags {
experimental(bool, TrustFinalNonStaticFields, false, \
"trust final non-static declarations for constant folding") \
\
experimental(bool, EnableInvokeDynamic, false, \
"recognize the invokedynamic instruction") \
\
experimental(bool, AllowTransitionalJSR292, true, \
"recognize pre-PFD formats of invokedynamic") \
\

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