comparison graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/HotSpotAMD64Backend.java @ 5841:f84d11672a86

vtable dispatch inlining for megamorphic virtual calls now works and is enabled by default
author Doug Simon <doug.simon@oracle.com>
date Mon, 16 Jul 2012 15:20:50 +0200
parents f238fe91dc7f
children a432e6d43aa1
comparison
equal deleted inserted replaced
5840:f565e8d4d200 5841:f84d11672a86
110 final MethodCallTargetNode callTarget = x.callTarget(); 110 final MethodCallTargetNode callTarget = x.callTarget();
111 final InvokeKind invokeKind = callTarget.invokeKind(); 111 final InvokeKind invokeKind = callTarget.invokeKind();
112 Kind[] signature = MetaUtil.signatureToKinds(callTarget.targetMethod().signature(), callTarget.isStatic() ? null : callTarget.targetMethod().holder().kind()); 112 Kind[] signature = MetaUtil.signatureToKinds(callTarget.targetMethod().signature(), callTarget.isStatic() ? null : callTarget.targetMethod().holder().kind());
113 CallingConvention cc = frameMap.registerConfig.getCallingConvention(JavaCall, signature, target(), false); 113 CallingConvention cc = frameMap.registerConfig.getCallingConvention(JavaCall, signature, target(), false);
114 frameMap.callsMethod(cc, JavaCall); 114 frameMap.callsMethod(cc, JavaCall);
115
116 Value address = Constant.forLong(0L);
117
118 ValueNode methodOopNode = null;
119
120 if (callTarget.computedAddress() != null) {
121 // If a virtual dispatch address was computed, then an extra argument
122 // was append for passing the methodOop in RBX
123 methodOopNode = callTarget.arguments().remove(callTarget.arguments().size() - 1);
124
125 if (invokeKind == Virtual) {
126 address = operand(callTarget.computedAddress());
127 } else {
128 // An invokevirtual may have been canonicalized into an invokespecial;
129 // the methodOop argument is ignored in this case
130 }
131 }
132
115 List<Value> argList = visitInvokeArguments(cc, callTarget.arguments()); 133 List<Value> argList = visitInvokeArguments(cc, callTarget.arguments());
116 134
117 Value address = callTarget.address() == null ? Constant.forLong(0L) : operand(callTarget.address()); 135 if (methodOopNode != null) {
136 Value methodOopArg = operand(methodOopNode);
137 emitMove(methodOopArg, AMD64.rbx.asValue());
138 argList.add(methodOopArg);
139 }
118 140
119 final Mark[] callsiteForStaticCallStub = {null}; 141 final Mark[] callsiteForStaticCallStub = {null};
120
121 if (invokeKind == Static || invokeKind == Special) { 142 if (invokeKind == Static || invokeKind == Special) {
122 lir.stubs.add(new AMD64Code() { 143 lir.stubs.add(new AMD64Code() {
123 public String description() { 144 public String description() {
124 return "static call stub for Invoke" + invokeKind; 145 return "static call stub for Invoke" + invokeKind;
125 } 146 }
143 } else { 164 } else {
144 // The mark for an invocation that uses an inline cache must be placed at the instruction 165 // The mark for an invocation that uses an inline cache must be placed at the instruction
145 // that loads the klassOop from the inline cache so that the C++ code can find it 166 // that loads the klassOop from the inline cache so that the C++ code can find it
146 // and replace the inline null value with Universe::non_oop_word() 167 // and replace the inline null value with Universe::non_oop_word()
147 assert invokeKind == Virtual || invokeKind == Interface; 168 assert invokeKind == Virtual || invokeKind == Interface;
148 if (callTarget.address() == null) { 169 if (invokeKind == Virtual && callTarget.computedAddress() != null) {
170 tasm.recordMark(MARK_INLINE_INVOKEVIRTUAL);
171 } else {
149 tasm.recordMark(invokeKind == Virtual ? MARK_INVOKEVIRTUAL : MARK_INVOKEINTERFACE); 172 tasm.recordMark(invokeKind == Virtual ? MARK_INVOKEVIRTUAL : MARK_INVOKEINTERFACE);
150 AMD64MacroAssembler masm = (AMD64MacroAssembler) tasm.asm; 173 AMD64MacroAssembler masm = (AMD64MacroAssembler) tasm.asm;
151 AMD64Move.move(tasm, masm, AMD64.rax.asValue(Kind.Object), Constant.NULL_OBJECT); 174 AMD64Move.move(tasm, masm, AMD64.rax.asValue(Kind.Object), Constant.NULL_OBJECT);
152 } else {
153 tasm.recordMark(MARK_INLINE_INVOKEVIRTUAL);
154 } 175 }
155 } 176 }
156 } 177 }
157 public void atCall(TargetMethodAssembler tasm) { 178 public void atCall(TargetMethodAssembler tasm) {
158 if (invokeKind == Static || invokeKind == Special) { 179 if (invokeKind == Static || invokeKind == Special) {