Mercurial > hg > graal-compiler
comparison c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/HotSpotXirGenerator.java @ 1429:abc670a709dc
* -XX:TraceC1X=0...5 controls the native c1x tracing
* -Dc1x.debug=true turns on the logging proxies and lots of log output on the java side
* provide more information about types to the compiler (type hierarchy, etc)
* provide exception handler tables to the compiler
* add exception handlers to the nmethod
* correct implementation of ExceptionObject
* exception handling/unwinding entry points
* modified versions of handle/unwind exception stubs using standard calling conventions
* exception throwing
* implicit null pointer exception, implicit div by 0 exception
* arraystore/classcast/arrayindex exceptions
* checkcast implementation
* newarray, anewarray, multinewarray implementation
* correct new instance initialization
* access to java class mirrors (for ldc)
* unresolved methods
* class resolving - class patching (asssembly prototype copying)
author | Lukas Stadler <lukas.stadler@oracle.com> |
---|---|
date | Tue, 31 Aug 2010 22:13:30 -0700 |
parents | 695451afc619 |
children | 949ade3f2ff3 |
comparison
equal
deleted
inserted
replaced
1428:695451afc619 | 1429:abc670a709dc |
---|---|
17 */ | 17 */ |
18 package com.sun.hotspot.c1x; | 18 package com.sun.hotspot.c1x; |
19 | 19 |
20 import java.lang.reflect.*; | 20 import java.lang.reflect.*; |
21 import java.util.*; | 21 import java.util.*; |
22 import java.util.concurrent.*; | |
22 | 23 |
23 import com.sun.c1x.target.amd64.*; | 24 import com.sun.c1x.target.amd64.*; |
24 import com.sun.cri.ci.CiAddress.Scale; | 25 import com.sun.cri.ci.CiAddress.Scale; |
25 import com.sun.cri.ci.*; | 26 import com.sun.cri.ci.*; |
26 import com.sun.cri.ri.*; | 27 import com.sun.cri.ri.*; |
34 * @author Thomas Wuerthinger, Lukas Stadler | 35 * @author Thomas Wuerthinger, Lukas Stadler |
35 */ | 36 */ |
36 public class HotSpotXirGenerator implements RiXirGenerator { | 37 public class HotSpotXirGenerator implements RiXirGenerator { |
37 | 38 |
38 // this needs to correspond to c1x_CodeInstaller.hpp | 39 // this needs to correspond to c1x_CodeInstaller.hpp |
39 private static final Integer MARK_VERIFIED_ENTRY = 0x0001; | 40 // @formatter:off |
40 private static final Integer MARK_UNVERIFIED_ENTRY = 0x0002; | 41 private static final Integer MARK_VERIFIED_ENTRY = 0x0001; |
41 private static final Integer MARK_OSR_ENTRY = 0x0003; | 42 private static final Integer MARK_UNVERIFIED_ENTRY = 0x0002; |
42 private static final Integer MARK_STATIC_CALL_STUB = 0x1000; | 43 private static final Integer MARK_OSR_ENTRY = 0x0003; |
43 private static final Integer MARK_INVOKE_INVALID = 0x2000; | 44 private static final Integer MARK_UNWIND_ENTRY = 0x0004; |
44 private static final Integer MARK_INVOKEINTERFACE = 0x2001; | 45 private static final Integer MARK_EXCEPTION_HANDLER_ENTRY = 0x0005; |
45 private static final Integer MARK_INVOKESTATIC = 0x2002; | 46 |
46 private static final Integer MARK_INVOKESPECIAL = 0x2003; | 47 private static final Integer MARK_STATIC_CALL_STUB = 0x1000; |
47 private static final Integer MARK_INVOKEVIRTUAL = 0x2004; | 48 |
48 private static final Integer MARK_IMPLICIT_NULL_EXCEPTION_TARGET = 0x3000; | 49 private static final Integer MARK_INVOKE_INVALID = 0x2000; |
50 private static final Integer MARK_INVOKEINTERFACE = 0x2001; | |
51 private static final Integer MARK_INVOKESTATIC = 0x2002; | |
52 private static final Integer MARK_INVOKESPECIAL = 0x2003; | |
53 private static final Integer MARK_INVOKEVIRTUAL = 0x2004; | |
54 | |
55 private static final Integer MARK_IMPLICIT_NULL = 0x3000; | |
56 | |
57 private static final Integer MARK_KLASS_PATCHING = 0x4000; | |
58 private static final Integer MARK_DUMMY_OOP_RELOCATION = 0x4001; | |
59 // @formatter:on | |
49 | 60 |
50 private final HotSpotVMConfig config; | 61 private final HotSpotVMConfig config; |
51 private final CiTarget target; | 62 private final CiTarget target; |
52 private final RiRegisterConfig registerConfig; | 63 private final RiRegisterConfig registerConfig; |
53 | 64 |
54 private CiXirAssembler asm; | 65 private CiXirAssembler asm; |
55 | 66 |
56 private XirTemplate[] emptyTemplates = new XirTemplate[CiKind.values().length]; | 67 private XirTemplate[] emptyTemplates = new XirTemplate[CiKind.values().length]; |
57 private XirTemplate[] arrayLoadTemplates = new XirTemplate[CiKind.values().length]; | 68 private XirTemplate[] arrayLoadTemplates = new XirTemplate[CiKind.values().length]; |
58 private XirTemplate[] arrayStoreTemplates = new XirTemplate[CiKind.values().length]; | 69 private XirTemplate[] arrayStoreTemplates = new XirTemplate[CiKind.values().length]; |
70 private XirTemplate[] arrayLoadTemplatesWithLength = new XirTemplate[CiKind.values().length]; | |
71 private XirTemplate[] arrayStoreTemplatesWithLength = new XirTemplate[CiKind.values().length]; | |
59 private XirTemplate prologueTemplate; | 72 private XirTemplate prologueTemplate; |
60 private XirTemplate staticPrologueTemplate; | 73 private XirTemplate staticPrologueTemplate; |
61 private XirTemplate epilogueTemplate; | 74 private XirTemplate epilogueTemplate; |
62 private XirTemplate arrayLengthTemplate; | 75 private XirTemplate arrayLengthTemplate; |
76 private XirTemplate safepointTemplate; | |
63 private XirTemplate exceptionObjectTemplate; | 77 private XirTemplate exceptionObjectTemplate; |
64 private XirTemplate invokeStaticTemplate; | 78 private XirTemplate invokeStaticTemplate; |
65 private XirTemplate invokeSpecialTemplate; | 79 private XirTemplate invokeSpecialTemplate; |
66 private XirTemplate invokeInterfaceTemplate; | 80 private XirTemplate invokeInterfaceTemplate; |
67 private XirTemplate invokeVirtualTemplate; | 81 private XirTemplate invokeVirtualTemplate; |
68 private XirTemplate newInstanceTemplate; | 82 |
83 private XirTemplate newInstanceUnresolvedTemplate; | |
84 private XirPair newObjectArrayTemplate; | |
85 private XirTemplate newTypeArrayTemplate; | |
86 private XirPair resolveClassTemplate; | |
87 private XirPair checkCastTemplate; | |
69 | 88 |
70 static class XirPair { | 89 static class XirPair { |
71 | 90 |
72 final XirTemplate resolved; | 91 final XirTemplate resolved; |
73 final XirTemplate unresolved; | 92 final XirTemplate unresolved; |
78 } | 97 } |
79 } | 98 } |
80 | 99 |
81 private XirPair[] putFieldTemplates = new XirPair[CiKind.values().length]; | 100 private XirPair[] putFieldTemplates = new XirPair[CiKind.values().length]; |
82 private XirPair[] getFieldTemplates = new XirPair[CiKind.values().length]; | 101 private XirPair[] getFieldTemplates = new XirPair[CiKind.values().length]; |
83 private XirPair[] putStaticFieldTemplates = new XirPair[CiKind.values().length]; | 102 private XirPair[] putStaticTemplates = new XirPair[CiKind.values().length]; |
84 private XirPair[] getStaticFieldTemplates = new XirPair[CiKind.values().length]; | 103 private XirPair[] getStaticTemplates = new XirPair[CiKind.values().length]; |
85 private XirPair instanceofTemplate; | 104 private XirPair instanceofTemplate; |
86 private XirPair instanceofTemplateNonnull; | 105 private XirPair instanceofTemplateNonnull; |
87 | 106 |
88 public HotSpotXirGenerator(HotSpotVMConfig config, CiTarget target, RiRegisterConfig registerConfig) { | 107 public HotSpotXirGenerator(HotSpotVMConfig config, CiTarget target, RiRegisterConfig registerConfig) { |
89 this.config = config; | 108 this.config = config; |
105 } else { | 124 } else { |
106 asm.restart(); | 125 asm.restart(); |
107 XirOperand result = asm.createTemp("result", kind); | 126 XirOperand result = asm.createTemp("result", kind); |
108 emptyTemplates[index] = asm.finishTemplate(result, "empty-" + kind); | 127 emptyTemplates[index] = asm.finishTemplate(result, "empty-" + kind); |
109 | 128 |
110 putFieldTemplates[index] = buildPutFieldTemplate(kind, kind == CiKind.Object, false); | 129 putFieldTemplates[index] = buildPutFieldTemplate(kind, kind == CiKind.Object); |
111 getFieldTemplates[index] = buildGetFieldTemplate(kind, false); | 130 getFieldTemplates[index] = buildGetFieldTemplate(kind); |
112 putStaticFieldTemplates[index] = buildPutFieldTemplate(kind, kind == CiKind.Object, true); | 131 putStaticTemplates[index] = buildPutStaticTemplate(kind, kind == CiKind.Object); |
113 getStaticFieldTemplates[index] = buildGetFieldTemplate(kind, true); | 132 getStaticTemplates[index] = buildGetStaticTemplate(kind); |
114 arrayLoadTemplates[index] = buildArrayLoad(kind, asm, true); | 133 arrayLoadTemplates[index] = buildArrayLoad(kind, asm, true, false); |
115 arrayStoreTemplates[index] = buildArrayStore(kind, asm, true, kind == CiKind.Object, kind == CiKind.Object); | 134 arrayStoreTemplates[index] = buildArrayStore(kind, asm, true, kind == CiKind.Object, kind == CiKind.Object, false); |
135 arrayLoadTemplatesWithLength[index] = buildArrayLoad(kind, asm, true, true); | |
136 arrayStoreTemplatesWithLength[index] = buildArrayStore(kind, asm, true, kind == CiKind.Object, kind == CiKind.Object, true); | |
116 // newArrayTemplates[index] = buildNewArray(kind); | 137 // newArrayTemplates[index] = buildNewArray(kind); |
117 } | 138 } |
118 // templates.add(emptyTemplates[index]); | 139 // templates.add(emptyTemplates[index]); |
119 } | 140 } |
120 | 141 |
125 prologueTemplate = buildPrologue(false); | 146 prologueTemplate = buildPrologue(false); |
126 staticPrologueTemplate = buildPrologue(true); | 147 staticPrologueTemplate = buildPrologue(true); |
127 epilogueTemplate = buildEpilogue(); | 148 epilogueTemplate = buildEpilogue(); |
128 arrayLengthTemplate = buildArrayLength(); | 149 arrayLengthTemplate = buildArrayLength(); |
129 exceptionObjectTemplate = buildExceptionObject(); | 150 exceptionObjectTemplate = buildExceptionObject(); |
151 safepointTemplate = buildSafepoint(); | |
130 instanceofTemplate = buildInstanceof(false); | 152 instanceofTemplate = buildInstanceof(false); |
131 instanceofTemplateNonnull = buildInstanceof(true); | 153 instanceofTemplateNonnull = buildInstanceof(true); |
132 invokeStaticTemplate = buildInvokeStatic(); | 154 invokeStaticTemplate = buildInvokeStatic(); |
133 invokeSpecialTemplate = buildInvokeSpecial(); | 155 invokeSpecialTemplate = buildInvokeSpecial(); |
134 invokeInterfaceTemplate = buildInvokeInterface(); | 156 invokeInterfaceTemplate = buildInvokeInterface(); |
135 invokeVirtualTemplate = buildInvokeVirtual(); | 157 invokeVirtualTemplate = buildInvokeVirtual(); |
136 newInstanceTemplate = buildNewInstance(); | 158 newInstanceUnresolvedTemplate = buildNewInstanceUnresolved(); |
159 newObjectArrayTemplate = new XirPair(buildNewObjectArray(true), buildNewObjectArray(false)); | |
160 newTypeArrayTemplate = buildNewTypeArray(); | |
161 resolveClassTemplate = new XirPair(buildResolveClass(true), buildResolveClass(false)); | |
162 checkCastTemplate = buildCheckCast(); | |
137 | 163 |
138 return templates; | 164 return templates; |
139 } | 165 } |
166 | |
167 private final OndemandTemplates<XirTemplate> newInstanceTemplates = new OndemandTemplates<XirTemplate>() { | |
168 | |
169 @Override | |
170 protected XirTemplate create(CiXirAssembler asm, int size) { | |
171 return buildNewInstance(asm, size); | |
172 } | |
173 }; | |
174 | |
175 private final OndemandTemplates<XirPair> multiNewArrayTemplate = new OndemandTemplates<HotSpotXirGenerator.XirPair>() { | |
176 | |
177 @Override | |
178 protected XirPair create(CiXirAssembler asm, int dimensions) { | |
179 return new XirPair(buildMultiNewArray(dimensions, true), buildMultiNewArray(dimensions, false)); | |
180 } | |
181 }; | |
140 | 182 |
141 private XirTemplate buildPrologue(boolean staticMethod) { | 183 private XirTemplate buildPrologue(boolean staticMethod) { |
142 asm.restart(CiKind.Void); | 184 asm.restart(CiKind.Void); |
143 XirOperand temp = asm.createRegister("temp (rax)", CiKind.Int, AMD64.rax); | 185 XirOperand temp = asm.createRegister("temp (rax)", CiKind.Int, AMD64.rax); |
144 XirOperand frame_pointer = asm.createRegister("frame pointer", CiKind.Word, AMD64.rbp); | 186 XirOperand framePointer = asm.createRegister("frame pointer", CiKind.Word, AMD64.rbp); |
187 XirOperand stackPointer = asm.createRegister("stack pointer", CiKind.Word, AMD64.rsp); | |
145 | 188 |
146 asm.align(config.codeEntryAlignment); | 189 asm.align(config.codeEntryAlignment); |
147 asm.mark(MARK_OSR_ENTRY); | 190 asm.mark(MARK_OSR_ENTRY); |
148 asm.mark(MARK_UNVERIFIED_ENTRY); | 191 asm.mark(MARK_UNVERIFIED_ENTRY); |
149 if (!staticMethod) { | 192 if (!staticMethod) { |
153 asm.shouldNotReachHere(); | 196 asm.shouldNotReachHere(); |
154 | 197 |
155 asm.align(config.codeEntryAlignment); | 198 asm.align(config.codeEntryAlignment); |
156 } | 199 } |
157 asm.mark(MARK_VERIFIED_ENTRY); | 200 asm.mark(MARK_VERIFIED_ENTRY); |
158 asm.push(frame_pointer); | 201 asm.push(framePointer); |
202 asm.mov(framePointer, stackPointer); | |
159 asm.pushFrame(); | 203 asm.pushFrame(); |
204 | |
205 // -- out of line ------------------------------------------------------- | |
206 XirOperand thread = asm.createRegister("thread", CiKind.Word, AMD64.r15); | |
207 XirOperand exceptionOop = asm.createTemp("exception oop", CiKind.Object); | |
208 XirLabel unwind = asm.createOutOfLineLabel("unwind"); | |
209 asm.bindOutOfLine(unwind); | |
210 | |
211 asm.mark(MARK_UNWIND_ENTRY); | |
212 //asm.popFrame(); | |
213 //asm.pop(framePointer); | |
214 | |
215 // TODO synchronized methods / monitors | |
216 | |
217 asm.pload(CiKind.Object, exceptionOop, thread, asm.i(config.threadExceptionOopOffset), false); | |
218 asm.pstore(CiKind.Object, thread, asm.i(config.threadExceptionOopOffset), asm.createConstant(CiConstant.NULL_OBJECT), false); | |
219 asm.pstore(CiKind.Long, thread, asm.i(config.threadExceptionPcOffset), asm.l(0), false); | |
220 | |
221 asm.callRuntime(config.unwindExceptionStub, null, exceptionOop); | |
222 asm.shouldNotReachHere(); | |
223 | |
224 asm.mark(MARK_EXCEPTION_HANDLER_ENTRY); | |
225 asm.callRuntime(config.handleExceptionStub, null); | |
226 asm.shouldNotReachHere(); | |
160 | 227 |
161 return asm.finishTemplate(staticMethod ? "static prologue" : "prologue"); | 228 return asm.finishTemplate(staticMethod ? "static prologue" : "prologue"); |
162 } | 229 } |
163 | 230 |
164 private XirTemplate buildEpilogue() { | 231 private XirTemplate buildEpilogue() { |
165 asm.restart(CiKind.Void); | 232 asm.restart(CiKind.Void); |
166 XirOperand frame_pointer = asm.createRegister("frame pointer", CiKind.Word, AMD64.rbp); | 233 XirOperand framePointer = asm.createRegister("frame pointer", CiKind.Word, AMD64.rbp); |
234 | |
167 asm.popFrame(); | 235 asm.popFrame(); |
168 asm.pop(frame_pointer); | 236 asm.pop(framePointer); |
169 // TODO safepoint check | 237 // TODO safepoint check |
238 | |
170 return asm.finishTemplate("epilogue"); | 239 return asm.finishTemplate("epilogue"); |
171 } | 240 } |
172 | 241 |
173 private XirTemplate buildArrayLength() { | 242 private XirTemplate buildArrayLength() { |
174 XirOperand result = asm.restart(CiKind.Int); | 243 XirOperand result = asm.restart(CiKind.Int); |
175 XirParameter object = asm.createInputParameter("object", CiKind.Object); | 244 XirParameter object = asm.createInputParameter("object", CiKind.Object); |
245 asm.mark(MARK_IMPLICIT_NULL); | |
176 asm.pload(CiKind.Int, result, object, asm.i(config.arrayLengthOffset), true); | 246 asm.pload(CiKind.Int, result, object, asm.i(config.arrayLengthOffset), true); |
177 return asm.finishTemplate("arrayLength"); | 247 return asm.finishTemplate("arrayLength"); |
178 } | 248 } |
179 | 249 |
180 private XirTemplate buildExceptionObject() { | 250 private XirTemplate buildExceptionObject() { |
181 asm.restart(); | 251 XirOperand result = asm.restart(CiKind.Object); |
182 XirOperand temp = asm.createRegister("temp (rax)", CiKind.Object, AMD64.rax); | 252 XirOperand thread = asm.createRegister("thread", CiKind.Word, AMD64.r15); |
183 return asm.finishTemplate(temp, "exception object"); | 253 |
184 } | 254 asm.pload(CiKind.Object, result, thread, asm.i(config.threadExceptionOopOffset), false); |
185 | 255 asm.pstore(CiKind.Object, thread, asm.i(config.threadExceptionOopOffset), asm.o(null), false); |
186 private XirPair buildGetFieldTemplate(CiKind kind, boolean isStatic) { | 256 asm.pstore(CiKind.Long, thread, asm.i(config.threadExceptionPcOffset), asm.l(0), false); |
257 | |
258 return asm.finishTemplate("exception object"); | |
259 } | |
260 | |
261 private XirTemplate buildSafepoint() { | |
262 asm.restart(CiKind.Void); | |
263 | |
264 // TODO safepoint | |
265 | |
266 return asm.finishTemplate("safepoint"); | |
267 } | |
268 | |
269 private XirPair buildGetFieldTemplate(CiKind kind) { | |
187 final XirTemplate resolved; | 270 final XirTemplate resolved; |
188 final XirTemplate unresolved; | 271 final XirTemplate unresolved; |
189 { | 272 { |
190 // resolved case | 273 // resolved case |
191 XirOperand result = asm.restart(kind); | 274 XirOperand result = asm.restart(kind); |
192 XirParameter object = asm.createInputParameter("object", CiKind.Object); | 275 XirParameter object = asm.createInputParameter("object", CiKind.Object); |
193 XirParameter fieldOffset = asm.createConstantInputParameter("fieldOffset", CiKind.Int); | 276 XirParameter fieldOffset = asm.createConstantInputParameter("fieldOffset", CiKind.Int); |
277 asm.mark(MARK_IMPLICIT_NULL); | |
194 asm.pload(kind, result, object, fieldOffset, true); | 278 asm.pload(kind, result, object, fieldOffset, true); |
195 resolved = asm.finishTemplate("getfield<" + kind + ">"); | 279 resolved = asm.finishTemplate("getfield<" + kind + ">"); |
196 } | 280 } |
197 if (isStatic) { | 281 unresolved = null; |
198 asm.restart(kind); | |
199 asm.shouldNotReachHere(); | |
200 | |
201 // XirParameter object = asm.createInputParameter("object", CiKind.Object); | |
202 // XirParameter guard = asm.createInputParameter("guard", CiKind.Object); | |
203 // XirOperand fieldOffset = asm.createTemp("fieldOffset", CiKind.Int); | |
204 // if (isStatic) { | |
205 // callRuntimeThroughStub(asm, "resolveGetStatic", fieldOffset, guard); | |
206 // } else { | |
207 // callRuntimeThroughStub(asm, "resolveGetField", fieldOffset, guard); | |
208 // } | |
209 // asm.pload(kind, result, object, fieldOffset, true); | |
210 | |
211 unresolved = asm.finishTemplate("getfield<" + kind + ">-unresolved"); | |
212 } else { | |
213 unresolved = null; | |
214 } | |
215 return new XirPair(resolved, unresolved); | 282 return new XirPair(resolved, unresolved); |
216 } | 283 } |
217 | 284 |
218 private XirPair buildPutFieldTemplate(CiKind kind, boolean genWriteBarrier, boolean isStatic) { | 285 private XirPair buildPutFieldTemplate(CiKind kind, boolean genWriteBarrier) { |
219 final XirTemplate resolved; | 286 final XirTemplate resolved; |
220 final XirTemplate unresolved; | 287 final XirTemplate unresolved; |
221 { | 288 { |
222 // resolved case | 289 // resolved case |
223 asm.restart(CiKind.Void); | 290 asm.restart(CiKind.Void); |
224 XirParameter object = asm.createInputParameter("object", CiKind.Object); | 291 XirParameter object = asm.createInputParameter("object", CiKind.Object); |
225 XirParameter value = asm.createInputParameter("value", kind); | 292 XirParameter value = asm.createInputParameter("value", kind); |
226 XirParameter fieldOffset = asm.createConstantInputParameter("fieldOffset", CiKind.Int); | 293 XirParameter fieldOffset = asm.createConstantInputParameter("fieldOffset", CiKind.Int); |
294 asm.mark(MARK_IMPLICIT_NULL); | |
227 asm.pstore(kind, object, fieldOffset, value, true); | 295 asm.pstore(kind, object, fieldOffset, value, true); |
228 if (genWriteBarrier) { | 296 if (genWriteBarrier) { |
229 // TODO write barrier | 297 // TODO write barrier |
230 // addWriteBarrier(asm, object, value); | 298 // addWriteBarrier(asm, object, value); |
231 } | 299 } |
232 resolved = asm.finishTemplate("putfield<" + kind + ", " + genWriteBarrier + ">"); | 300 resolved = asm.finishTemplate("putfield<" + kind + ", " + genWriteBarrier + ">"); |
233 } | 301 } |
234 if (isStatic) { | 302 unresolved = null; |
235 // unresolved case | 303 return new XirPair(resolved, unresolved); |
304 } | |
305 | |
306 private XirPair buildGetStaticTemplate(CiKind kind) { | |
307 final XirTemplate resolved; | |
308 final XirTemplate unresolved; | |
309 { | |
310 // resolved case | |
311 XirOperand result = asm.restart(kind); | |
312 XirParameter object = asm.createInputParameter("object", CiKind.Object); | |
313 XirParameter fieldOffset = asm.createConstantInputParameter("fieldOffset", CiKind.Int); | |
314 asm.mark(MARK_IMPLICIT_NULL); | |
315 asm.pload(kind, result, object, fieldOffset, true); | |
316 resolved = asm.finishTemplate("getfield<" + kind + ">"); | |
317 } | |
318 unresolved = null; | |
319 return new XirPair(resolved, unresolved); | |
320 } | |
321 | |
322 private XirPair buildPutStaticTemplate(CiKind kind, boolean genWriteBarrier) { | |
323 final XirTemplate resolved; | |
324 final XirTemplate unresolved; | |
325 { | |
326 // resolved case | |
236 asm.restart(CiKind.Void); | 327 asm.restart(CiKind.Void); |
237 asm.shouldNotReachHere(); | 328 XirParameter object = asm.createInputParameter("object", CiKind.Object); |
238 | 329 XirParameter value = asm.createInputParameter("value", kind); |
239 // XirParameter object = asm.createInputParameter("object", CiKind.Object); | 330 XirParameter fieldOffset = asm.createConstantInputParameter("fieldOffset", CiKind.Int); |
240 // XirParameter value = asm.createInputParameter("value", kind); | 331 asm.mark(MARK_IMPLICIT_NULL); |
241 // XirParameter guard = asm.createInputParameter("guard", CiKind.Object); | 332 asm.pstore(kind, object, fieldOffset, value, true); |
242 // XirOperand fieldOffset = asm.createTemp("fieldOffset", CiKind.Int); | 333 if (genWriteBarrier) { |
243 // if (isStatic) { | 334 // TODO write barrier |
244 // callRuntimeThroughStub(asm, "resolvePutStatic", fieldOffset, guard); | 335 // addWriteBarrier(asm, object, value); |
245 // } else { | 336 } |
246 // callRuntimeThroughStub(asm, "resolvePutField", fieldOffset, guard); | 337 resolved = asm.finishTemplate("putfield<" + kind + ", " + genWriteBarrier + ">"); |
247 // } | 338 } |
248 // asm.pstore(kind, object, fieldOffset, value, true); | 339 unresolved = null; |
249 // if (genWriteBarrier) { | |
250 // addWriteBarrier(asm, object, value); | |
251 // } | |
252 | |
253 unresolved = asm.finishTemplate("putfield<" + kind + ", " + genWriteBarrier + ">-unresolved"); | |
254 } else { | |
255 unresolved = null; | |
256 } | |
257 return new XirPair(resolved, unresolved); | 340 return new XirPair(resolved, unresolved); |
258 } | 341 } |
259 | 342 |
260 private XirPair buildInstanceof(boolean nonnull) { | 343 private XirPair buildInstanceof(boolean nonnull) { |
261 XirTemplate resolved; | 344 final XirTemplate resolved; |
262 XirTemplate unresolved; | 345 final XirTemplate unresolved; |
263 { | 346 { |
264 XirOperand result = asm.restart(CiKind.Boolean); | 347 XirOperand result = asm.restart(CiKind.Boolean); |
265 | 348 |
266 XirParameter object = asm.createInputParameter("object", CiKind.Object); | 349 XirParameter object = asm.createInputParameter("object", CiKind.Object); |
267 XirParameter hub = asm.createConstantInputParameter("hub", CiKind.Object); | 350 XirParameter hub = asm.createConstantInputParameter("hub", CiKind.Object); |
268 XirOperand temp = asm.createTemp("temp", CiKind.Object); | 351 XirOperand objHub = asm.createTemp("objHub", CiKind.Object); |
352 | |
269 XirLabel end = asm.createInlineLabel("end"); | 353 XirLabel end = asm.createInlineLabel("end"); |
270 XirLabel slow_path = asm.createOutOfLineLabel("slow path"); | 354 XirLabel slow_path = asm.createOutOfLineLabel("slow path"); |
271 | 355 |
272 asm.mov(result, asm.b(false)); | |
273 if (!nonnull) { | 356 if (!nonnull) { |
274 // first check for null | 357 // null isn't "instanceof" anything |
358 asm.mov(result, asm.b(false)); | |
275 asm.jeq(end, object, asm.o(null)); | 359 asm.jeq(end, object, asm.o(null)); |
276 } | 360 } |
277 asm.pload(CiKind.Object, temp, object, asm.i(config.hubOffset), !nonnull); | 361 asm.pload(CiKind.Object, objHub, object, asm.i(config.hubOffset), false); |
362 // if we get an exact match: succeed immediately | |
278 asm.mov(result, asm.b(true)); | 363 asm.mov(result, asm.b(true)); |
279 asm.jneq(slow_path, temp, hub); | 364 asm.jneq(slow_path, objHub, hub); |
280 | |
281 asm.bindInline(end); | 365 asm.bindInline(end); |
282 | 366 |
367 // -- out of line ------------------------------------------------------- | |
283 asm.bindOutOfLine(slow_path); | 368 asm.bindOutOfLine(slow_path); |
284 asm.push(temp); | 369 checkSubtype(result, objHub, hub); |
285 asm.push(hub); | |
286 asm.callRuntime(config.instanceofStub, result); | |
287 asm.pop(hub); | |
288 asm.pop(result); | |
289 asm.jmp(end); | 370 asm.jmp(end); |
371 | |
290 resolved = asm.finishTemplate("instanceof-leaf<" + nonnull + ">"); | 372 resolved = asm.finishTemplate("instanceof-leaf<" + nonnull + ">"); |
291 } | 373 } |
292 {/* | 374 { |
293 * // unresolved instanceof unresolved = buildUnresolvedInstanceOf(nonnull); | 375 XirOperand result = asm.restart(CiKind.Boolean); |
294 */ | 376 |
295 asm.restart(CiKind.Boolean); | |
296 XirParameter object = asm.createInputParameter("object", CiKind.Object); | 377 XirParameter object = asm.createInputParameter("object", CiKind.Object); |
297 System.out.println(object); | 378 XirOperand hub = asm.createTemp("hub", CiKind.Object); |
379 XirOperand objHub = asm.createTemp("objHub", CiKind.Object); | |
380 | |
381 XirLabel end = asm.createInlineLabel("end"); | |
382 XirLabel slow_path = asm.createOutOfLineLabel("slow path"); | |
383 | |
384 // insert the patching code for class resolving - the hub will end up in "hub" | |
385 UnresolvedClassPatching patching = new UnresolvedClassPatching(asm, hub, config); | |
386 patching.emitInline(); | |
387 | |
388 if (!nonnull) { | |
389 // null isn't "instanceof" anything | |
390 asm.mov(result, asm.b(false)); | |
391 asm.jeq(end, object, asm.o(null)); | |
392 } | |
393 asm.pload(CiKind.Object, objHub, object, asm.i(config.hubOffset), false); | |
394 // if we get an exact match: succeed immediately | |
395 asm.mov(result, asm.b(true)); | |
396 asm.jneq(slow_path, objHub, hub); | |
397 asm.bindInline(end); | |
398 | |
399 // -- out of line ------------------------------------------------------- | |
400 asm.bindOutOfLine(slow_path); | |
401 checkSubtype(result, objHub, hub); | |
402 asm.jmp(end); | |
403 | |
404 patching.emitOutOfLine(); | |
405 | |
406 unresolved = asm.finishTemplate("instanceof-leaf<" + nonnull + ">"); | |
407 } | |
408 return new XirPair(resolved, unresolved); | |
409 } | |
410 | |
411 private XirPair buildCheckCast() { | |
412 final XirTemplate resolved; | |
413 final XirTemplate unresolved; | |
414 { | |
415 asm.restart(); | |
416 | |
417 XirParameter object = asm.createInputParameter("object", CiKind.Object); | |
418 XirParameter hub = asm.createConstantInputParameter("hub", CiKind.Object); | |
419 XirOperand objHub = asm.createTemp("objHub", CiKind.Object); | |
420 | |
421 XirLabel end = asm.createInlineLabel("end"); | |
422 XirLabel slow_path = asm.createOutOfLineLabel("slow path"); | |
423 | |
424 // null can be cast to anything | |
425 asm.jeq(end, object, asm.o(null)); | |
426 | |
427 asm.pload(CiKind.Object, objHub, object, asm.i(config.hubOffset), false); | |
428 // if we get an exact match: succeed immediately | |
429 asm.jneq(slow_path, objHub, hub); | |
430 asm.bindInline(end); | |
431 | |
432 // -- out of line ------------------------------------------------------- | |
433 asm.bindOutOfLine(slow_path); | |
434 checkSubtype(objHub, objHub, hub); | |
435 asm.jneq(end, objHub, asm.o(null)); | |
436 XirOperand scratch = asm.createRegister("scratch", CiKind.Object, AMD64.r10); | |
437 asm.mov(scratch, object); | |
438 asm.callRuntime(config.throwClassCastException, null); | |
298 asm.shouldNotReachHere(); | 439 asm.shouldNotReachHere(); |
299 unresolved = asm.finishTemplate("instanceof-leaf<" + nonnull + ">"); | 440 |
441 resolved = asm.finishTemplate(object, "check cast"); | |
442 } | |
443 { | |
444 asm.restart(); | |
445 | |
446 XirParameter object = asm.createInputParameter("object", CiKind.Object); | |
447 XirOperand hub = asm.createTemp("hub", CiKind.Object); | |
448 XirOperand objHub = asm.createTemp("objHub", CiKind.Object); | |
449 | |
450 XirLabel end = asm.createInlineLabel("end"); | |
451 XirLabel slow_path = asm.createOutOfLineLabel("slow path"); | |
452 | |
453 // insert the patching code for class resolving - the hub will end up in "hub" | |
454 UnresolvedClassPatching patching = new UnresolvedClassPatching(asm, hub, config); | |
455 patching.emitInline(); | |
456 | |
457 // null can be cast to anything | |
458 asm.jeq(end, object, asm.o(null)); | |
459 | |
460 asm.pload(CiKind.Object, objHub, object, asm.i(config.hubOffset), false); | |
461 // if we get an exact match: succeed immediately | |
462 asm.jneq(slow_path, objHub, hub); | |
463 asm.bindInline(end); | |
464 | |
465 // -- out of line ------------------------------------------------------- | |
466 asm.bindOutOfLine(slow_path); | |
467 checkSubtype(objHub, objHub, hub); | |
468 asm.jneq(end, objHub, asm.o(null)); | |
469 XirOperand scratch = asm.createRegister("scratch", CiKind.Object, AMD64.r10); | |
470 asm.mov(scratch, object); | |
471 asm.callRuntime(config.throwClassCastException, null); | |
472 asm.shouldNotReachHere(); | |
473 | |
474 patching.emitOutOfLine(); | |
475 | |
476 unresolved = asm.finishTemplate(object, "check cast"); | |
300 } | 477 } |
301 return new XirPair(resolved, unresolved); | 478 return new XirPair(resolved, unresolved); |
302 } | 479 } |
303 | 480 |
304 private XirTemplate buildArrayStore(CiKind kind, CiXirAssembler asm, boolean genBoundsCheck, boolean genStoreCheck, boolean genWriteBarrier) { | 481 private XirTemplate buildArrayStore(CiKind kind, CiXirAssembler asm, boolean genBoundsCheck, boolean genStoreCheck, boolean genWriteBarrier, boolean withLength) { |
305 asm.restart(CiKind.Void); | 482 asm.restart(CiKind.Void); |
306 XirParameter array = asm.createInputParameter("array", CiKind.Object); | 483 XirParameter array = asm.createInputParameter("array", CiKind.Object); |
307 XirParameter index = asm.createInputParameter("index", CiKind.Int); | 484 XirParameter index = asm.createInputParameter("index", CiKind.Int); |
308 XirParameter value = asm.createInputParameter("value", kind); | 485 XirParameter value = asm.createInputParameter("value", kind); |
309 XirOperand length = asm.createTemp("length", CiKind.Int); | |
310 XirOperand temp = asm.createTemp("temp", CiKind.Word); | 486 XirOperand temp = asm.createTemp("temp", CiKind.Word); |
311 XirOperand valueHub = null; | 487 XirOperand valueHub = null; |
312 XirOperand compHub = null; | 488 XirOperand compHub = null; |
313 XirLabel store = asm.createInlineLabel("store"); | 489 XirLabel store = asm.createInlineLabel("store"); |
314 XirLabel failBoundsCheck = null; | 490 XirLabel failBoundsCheck = null; |
315 XirLabel slowStoreCheck = null; | 491 XirLabel slowStoreCheck = null; |
492 // if the length is known the array cannot be null | |
493 boolean implicitNullException = !withLength; | |
494 | |
316 if (genBoundsCheck) { | 495 if (genBoundsCheck) { |
317 // load the array length and check the index | 496 // load the array length and check the index |
318 failBoundsCheck = asm.createOutOfLineLabel("failBoundsCheck"); | 497 failBoundsCheck = asm.createOutOfLineLabel("failBoundsCheck"); |
319 asm.pload(CiKind.Int, length, array, asm.i(config.arrayLengthOffset), true); | 498 XirOperand length; |
499 if (withLength) { | |
500 length = asm.createInputParameter("length", CiKind.Int); | |
501 } else { | |
502 length = asm.createTemp("length", CiKind.Int); | |
503 asm.mark(MARK_IMPLICIT_NULL); | |
504 asm.pload(CiKind.Int, length, array, asm.i(config.arrayLengthOffset), true); | |
505 implicitNullException = false; | |
506 } | |
320 asm.jugteq(failBoundsCheck, index, length); | 507 asm.jugteq(failBoundsCheck, index, length); |
508 | |
321 } | 509 } |
322 if (genStoreCheck) { | 510 if (genStoreCheck) { |
323 slowStoreCheck = asm.createOutOfLineLabel("slowStoreCheck"); | 511 slowStoreCheck = asm.createOutOfLineLabel("slowStoreCheck"); |
324 asm.jeq(store, value, asm.o(null)); // first check if value is null | 512 asm.jeq(store, value, asm.o(null)); // first check if value is null |
325 valueHub = asm.createTemp("valueHub", CiKind.Object); | 513 valueHub = asm.createTemp("valueHub", CiKind.Object); |
326 compHub = asm.createTemp("compHub", CiKind.Object); | 514 compHub = asm.createTemp("compHub", CiKind.Object); |
327 asm.pload(CiKind.Object, compHub, array, asm.i(config.hubOffset), !genBoundsCheck); | 515 if (implicitNullException) { |
516 asm.mark(MARK_IMPLICIT_NULL); | |
517 } | |
518 asm.pload(CiKind.Object, compHub, array, asm.i(config.hubOffset), implicitNullException); | |
328 asm.pload(CiKind.Object, compHub, compHub, asm.i(config.arrayClassElementOffset), false); | 519 asm.pload(CiKind.Object, compHub, compHub, asm.i(config.arrayClassElementOffset), false); |
329 asm.pload(CiKind.Object, valueHub, value, asm.i(config.hubOffset), false); | 520 asm.pload(CiKind.Object, valueHub, value, asm.i(config.hubOffset), false); |
330 asm.jneq(slowStoreCheck, compHub, valueHub); // then check component hub matches value hub | 521 asm.jneq(slowStoreCheck, compHub, valueHub); // then check component hub matches value hub |
522 | |
523 implicitNullException = false; | |
331 } | 524 } |
332 asm.bindInline(store); | 525 asm.bindInline(store); |
333 int elemSize = target.sizeInBytes(kind); | 526 int elemSize = target.sizeInBytes(kind); |
334 asm.pstore(kind, array, index, value, config.getArrayOffset(kind), Scale.fromInt(elemSize), !genBoundsCheck && !genStoreCheck); | 527 |
528 if (implicitNullException) { | |
529 asm.mark(MARK_IMPLICIT_NULL); | |
530 } | |
531 asm.pstore(kind, array, index, value, config.getArrayOffset(kind), Scale.fromInt(elemSize), implicitNullException); | |
335 if (genWriteBarrier) { | 532 if (genWriteBarrier) { |
336 // addWriteBarrier(asm, array, value); | 533 // addWriteBarrier(asm, array, value); |
337 } | 534 } |
535 | |
536 // -- out of line ------------------------------------------------------- | |
338 if (genBoundsCheck) { | 537 if (genBoundsCheck) { |
339 asm.bindOutOfLine(failBoundsCheck); | 538 asm.bindOutOfLine(failBoundsCheck); |
539 asm.callRuntime(config.throwArrayIndexException, null); | |
340 asm.shouldNotReachHere(); | 540 asm.shouldNotReachHere(); |
341 // callRuntimeThroughStub(asm, "throwArrayIndexOutOfBoundsException", null, array, index); | |
342 } | 541 } |
343 if (genStoreCheck) { | 542 if (genStoreCheck) { |
344 asm.bindOutOfLine(slowStoreCheck); | 543 asm.bindOutOfLine(slowStoreCheck); |
345 asm.push(valueHub); | 544 checkSubtype(temp, valueHub, compHub); |
346 asm.push(compHub); | |
347 asm.callRuntime(config.instanceofStub, null); | |
348 asm.pop(temp); | |
349 asm.pop(temp); | |
350 asm.jneq(store, temp, asm.w(0)); | 545 asm.jneq(store, temp, asm.w(0)); |
351 asm.shouldNotReachHere(); | 546 asm.callRuntime(config.throwArrayStoreException, null); |
352 asm.jmp(store); | 547 asm.jmp(store); |
353 } | 548 } |
354 return asm.finishTemplate("arraystore<" + kind + ">"); | 549 return asm.finishTemplate("arraystore<" + kind + ">"); |
355 } | 550 } |
356 | 551 |
357 private XirTemplate buildArrayLoad(CiKind kind, CiXirAssembler asm, boolean genBoundsCheck) { | 552 private XirTemplate buildArrayLoad(CiKind kind, CiXirAssembler asm, boolean genBoundsCheck, boolean withLength) { |
358 XirOperand result = asm.restart(kind); | 553 XirOperand result = asm.restart(kind); |
359 XirParameter array = asm.createInputParameter("array", CiKind.Object); | 554 XirParameter array = asm.createInputParameter("array", CiKind.Object); |
360 XirParameter index = asm.createInputParameter("index", CiKind.Int); | 555 XirParameter index = asm.createInputParameter("index", CiKind.Int); |
361 XirOperand length = asm.createTemp("length", CiKind.Int); | 556 XirLabel failBoundsCheck = null; |
362 XirLabel fail = null; | 557 // if the length is known the array cannot be null |
558 boolean implicitNullException = !withLength; | |
559 | |
363 if (genBoundsCheck) { | 560 if (genBoundsCheck) { |
364 // load the array length and check the index | 561 // load the array length and check the index |
365 fail = asm.createOutOfLineLabel("fail"); | 562 failBoundsCheck = asm.createOutOfLineLabel("failBoundsCheck"); |
366 asm.pload(CiKind.Int, length, array, asm.i(config.arrayLengthOffset), true); | 563 XirOperand length; |
367 asm.jugteq(fail, index, length); | 564 if (withLength) { |
565 length = asm.createInputParameter("length", CiKind.Int); | |
566 } else { | |
567 length = asm.createTemp("length", CiKind.Int); | |
568 asm.mark(MARK_IMPLICIT_NULL); | |
569 asm.pload(CiKind.Int, length, array, asm.i(config.arrayLengthOffset), true); | |
570 implicitNullException = false; | |
571 } | |
572 asm.jugteq(failBoundsCheck, index, length); | |
573 implicitNullException = false; | |
368 } | 574 } |
369 int elemSize = target.sizeInBytes(kind); | 575 int elemSize = target.sizeInBytes(kind); |
370 asm.pload(kind, result, array, index, config.getArrayOffset(kind), Scale.fromInt(elemSize), !genBoundsCheck); | 576 if (implicitNullException) { |
577 asm.mark(MARK_IMPLICIT_NULL); | |
578 } | |
579 asm.pload(kind, result, array, index, config.getArrayOffset(kind), Scale.fromInt(elemSize), implicitNullException); | |
371 if (genBoundsCheck) { | 580 if (genBoundsCheck) { |
372 asm.bindOutOfLine(fail); | 581 asm.bindOutOfLine(failBoundsCheck); |
582 asm.callRuntime(config.throwArrayIndexException, null); | |
373 asm.shouldNotReachHere(); | 583 asm.shouldNotReachHere(); |
374 // callRuntimeThroughStub(asm, "throwArrayIndexOutOfBoundsException", null, array, index); | |
375 } | 584 } |
376 return asm.finishTemplate("arrayload<" + kind + ">"); | 585 return asm.finishTemplate("arrayload<" + kind + ">"); |
377 } | 586 } |
378 | 587 |
379 private XirTemplate buildInvokeStatic() { | 588 private XirTemplate buildInvokeStatic() { |
381 XirParameter addr = asm.createConstantInputParameter("addr", CiKind.Word); | 590 XirParameter addr = asm.createConstantInputParameter("addr", CiKind.Word); |
382 | 591 |
383 XirLabel stub = asm.createOutOfLineLabel("call stub"); | 592 XirLabel stub = asm.createOutOfLineLabel("call stub"); |
384 asm.mark(MARK_INVOKESTATIC); | 593 asm.mark(MARK_INVOKESTATIC); |
385 | 594 |
595 // -- out of line ------------------------------------------------------- | |
386 asm.bindOutOfLine(stub); | 596 asm.bindOutOfLine(stub); |
387 XirOperand method = asm.createRegister("method", CiKind.Word, AMD64.rbx); | 597 XirOperand method = asm.createRegister("method", CiKind.Word, AMD64.rbx); |
388 asm.mark(MARK_STATIC_CALL_STUB, XirMark.CALLSITE); | 598 asm.mark(MARK_STATIC_CALL_STUB, XirMark.CALLSITE); |
389 asm.mov(method, asm.w(0l)); | 599 asm.mov(method, asm.w(0l)); |
390 XirLabel dummy = asm.createOutOfLineLabel("dummy"); | 600 XirLabel dummy = asm.createOutOfLineLabel("dummy"); |
394 return asm.finishTemplate(addr, "invokestatic"); | 604 return asm.finishTemplate(addr, "invokestatic"); |
395 } | 605 } |
396 | 606 |
397 private XirTemplate buildInvokeSpecial() { | 607 private XirTemplate buildInvokeSpecial() { |
398 asm.restart(); | 608 asm.restart(); |
609 XirParameter receiver = asm.createInputParameter("receiver", CiKind.Object); | |
399 XirParameter addr = asm.createConstantInputParameter("addr", CiKind.Word); | 610 XirParameter addr = asm.createConstantInputParameter("addr", CiKind.Word); |
400 | 611 XirOperand temp = asm.createRegister("temp", CiKind.Word, AMD64.rax); |
401 XirLabel stub = asm.createOutOfLineLabel("call stub"); | 612 XirLabel stub = asm.createOutOfLineLabel("call stub"); |
613 | |
614 asm.mark(MARK_IMPLICIT_NULL); | |
615 asm.pload(CiKind.Word, temp, receiver, true); | |
402 asm.mark(MARK_INVOKESPECIAL); | 616 asm.mark(MARK_INVOKESPECIAL); |
403 | 617 |
618 // -- out of line ------------------------------------------------------- | |
404 asm.bindOutOfLine(stub); | 619 asm.bindOutOfLine(stub); |
405 XirOperand method = asm.createRegister("method", CiKind.Word, AMD64.rbx); | 620 XirOperand method = asm.createRegister("method", CiKind.Word, AMD64.rbx); |
406 asm.mark(MARK_STATIC_CALL_STUB, XirMark.CALLSITE); | 621 asm.mark(MARK_STATIC_CALL_STUB, XirMark.CALLSITE); |
407 asm.mov(method, asm.w(0l)); | 622 asm.mov(method, asm.w(0l)); |
408 XirLabel dummy = asm.createOutOfLineLabel("dummy"); | 623 XirLabel dummy = asm.createOutOfLineLabel("dummy"); |
412 return asm.finishTemplate(addr, "invokespecial"); | 627 return asm.finishTemplate(addr, "invokespecial"); |
413 } | 628 } |
414 | 629 |
415 private XirTemplate buildInvokeInterface() { | 630 private XirTemplate buildInvokeInterface() { |
416 asm.restart(); | 631 asm.restart(); |
632 XirParameter receiver = asm.createInputParameter("receiver", CiKind.Object); | |
417 XirParameter addr = asm.createConstantInputParameter("addr", CiKind.Word); | 633 XirParameter addr = asm.createConstantInputParameter("addr", CiKind.Word); |
418 XirOperand method = asm.createRegister("method", CiKind.Object, AMD64.rbx); | 634 XirOperand method = asm.createRegister("method", CiKind.Object, AMD64.rbx); |
419 | 635 XirOperand temp = asm.createRegister("temp", CiKind.Word, AMD64.rax); |
420 XirLabel stub = asm.createOutOfLineLabel("call stub"); | 636 XirLabel stub = asm.createOutOfLineLabel("call stub"); |
637 | |
638 asm.mark(MARK_IMPLICIT_NULL); | |
639 asm.pload(CiKind.Word, temp, receiver, true); | |
421 asm.mark(MARK_INVOKEINTERFACE); | 640 asm.mark(MARK_INVOKEINTERFACE); |
422 asm.mov(method, asm.createConstant(CiConstant.forObject(HotSpotProxy.DUMMY_CONSTANT_OBJ))); | 641 asm.mov(method, asm.createConstant(CiConstant.forObject(HotSpotProxy.DUMMY_CONSTANT_OBJ))); |
423 | 642 |
643 // -- out of line ------------------------------------------------------- | |
424 asm.bindOutOfLine(stub); | 644 asm.bindOutOfLine(stub); |
425 asm.mark(MARK_STATIC_CALL_STUB, XirMark.CALLSITE); | 645 asm.mark(MARK_STATIC_CALL_STUB, XirMark.CALLSITE); |
426 asm.mov(method, asm.w(0l)); | 646 asm.mov(method, asm.w(0l)); |
427 XirLabel dummy = asm.createOutOfLineLabel("dummy"); | 647 XirLabel dummy = asm.createOutOfLineLabel("dummy"); |
428 asm.jmp(dummy); | 648 asm.jmp(dummy); |
431 return asm.finishTemplate(addr, "invokespecial"); | 651 return asm.finishTemplate(addr, "invokespecial"); |
432 } | 652 } |
433 | 653 |
434 private XirTemplate buildInvokeVirtual() { | 654 private XirTemplate buildInvokeVirtual() { |
435 asm.restart(); | 655 asm.restart(); |
656 XirParameter receiver = asm.createInputParameter("receiver", CiKind.Object); | |
436 XirParameter addr = asm.createConstantInputParameter("addr", CiKind.Word); | 657 XirParameter addr = asm.createConstantInputParameter("addr", CiKind.Word); |
437 XirOperand method = asm.createRegister("method", CiKind.Object, AMD64.rbx); | 658 XirOperand method = asm.createRegister("method", CiKind.Object, AMD64.rbx); |
438 | 659 XirOperand temp = asm.createRegister("temp", CiKind.Word, AMD64.rax); |
439 XirLabel stub = asm.createOutOfLineLabel("call stub"); | 660 XirLabel stub = asm.createOutOfLineLabel("call stub"); |
661 | |
662 asm.mark(MARK_IMPLICIT_NULL); | |
663 asm.pload(CiKind.Word, temp, receiver, true); | |
440 asm.mark(MARK_INVOKEVIRTUAL); | 664 asm.mark(MARK_INVOKEVIRTUAL); |
441 asm.mov(method, asm.createConstant(CiConstant.forObject(HotSpotProxy.DUMMY_CONSTANT_OBJ))); | 665 asm.mov(method, asm.createConstant(CiConstant.forObject(HotSpotProxy.DUMMY_CONSTANT_OBJ))); |
442 | 666 |
667 // -- out of line ------------------------------------------------------- | |
443 asm.bindOutOfLine(stub); | 668 asm.bindOutOfLine(stub); |
444 asm.mark(MARK_STATIC_CALL_STUB, XirMark.CALLSITE); | 669 asm.mark(MARK_STATIC_CALL_STUB, XirMark.CALLSITE); |
445 asm.mov(method, asm.w(0l)); | 670 asm.mov(method, asm.w(0l)); |
446 XirLabel dummy = asm.createOutOfLineLabel("dummy"); | 671 XirLabel dummy = asm.createOutOfLineLabel("dummy"); |
447 asm.jmp(dummy); | 672 asm.jmp(dummy); |
448 asm.bindOutOfLine(dummy); | 673 asm.bindOutOfLine(dummy); |
449 | 674 |
450 asm.mark(MARK_IMPLICIT_NULL_EXCEPTION_TARGET, XirMark.CALLSITE); | |
451 asm.callRuntime(config.throwImplicitNullStub, null); | |
452 | |
453 return asm.finishTemplate(addr, "invokespecial"); | 675 return asm.finishTemplate(addr, "invokespecial"); |
454 } | 676 } |
455 | 677 |
456 private XirTemplate buildNewInstance() { | 678 private XirTemplate buildNewInstance(CiXirAssembler asm, int size) { |
457 XirOperand result = asm.restart(CiKind.Word); | 679 XirOperand result = asm.restart(CiKind.Word); |
458 XirOperand type = asm.createInputParameter("type", CiKind.Object); | 680 XirOperand type = asm.createInputParameter("type", CiKind.Object); |
459 XirOperand instanceSize = asm.createConstantInputParameter("instance size", CiKind.Word); | |
460 | 681 |
461 XirOperand thread = asm.createRegister("thread", CiKind.Word, AMD64.r15); | 682 XirOperand thread = asm.createRegister("thread", CiKind.Word, AMD64.r15); |
462 XirOperand temp1 = asm.createTemp("temp1", CiKind.Word); | 683 XirOperand temp1 = asm.createRegister("temp1", CiKind.Word, AMD64.rcx); |
463 XirOperand temp2 = asm.createTemp("temp2", CiKind.Word); | 684 XirOperand temp2 = asm.createRegister("temp2", CiKind.Word, AMD64.rbx); |
685 useRegisters(asm, AMD64.rsi); | |
464 XirLabel tlabFull = asm.createOutOfLineLabel("tlab full"); | 686 XirLabel tlabFull = asm.createOutOfLineLabel("tlab full"); |
465 XirLabel resume = asm.createInlineLabel("resume"); | 687 XirLabel resume = asm.createInlineLabel("resume"); |
466 | 688 |
467 asm.pload(CiKind.Word, result, thread, asm.i(config.threadTlabTopOffset), false); | 689 asm.pload(CiKind.Word, result, thread, asm.i(config.threadTlabTopOffset), false); |
468 asm.add(temp1, result, instanceSize); | 690 asm.add(temp1, result, asm.w(size)); |
469 asm.pload(CiKind.Word, temp2, thread, asm.i(config.threadTlabEndOffset), false); | 691 asm.pload(CiKind.Word, temp2, thread, asm.i(config.threadTlabEndOffset), false); |
470 | 692 |
471 asm.jgt(tlabFull, temp1, temp2); | 693 asm.jgt(tlabFull, temp1, temp2); |
472 asm.pstore(CiKind.Word, thread, asm.i(config.threadTlabTopOffset), temp1, false); | 694 asm.pstore(CiKind.Word, thread, asm.i(config.threadTlabTopOffset), temp1, false); |
473 asm.bindInline(resume); | 695 asm.bindInline(resume); |
474 | 696 |
475 asm.pload(CiKind.Word, temp1, type, asm.i(config.instanceHeaderPrototypeOffset), false); | 697 asm.pload(CiKind.Word, temp1, type, asm.i(config.instanceHeaderPrototypeOffset), false); |
476 asm.pstore(CiKind.Word, result, temp1, false); | 698 asm.pstore(CiKind.Word, result, temp1, false); |
477 asm.pstore(CiKind.Object, result, asm.i(config.hubOffset), type, false); | 699 asm.pstore(CiKind.Object, result, asm.i(config.hubOffset), type, false); |
478 | 700 |
701 if (size > 2 * target.wordSize) { | |
702 asm.mov(temp1, asm.w(0)); | |
703 for (int offset = 2 * target.wordSize; offset < size; offset += target.wordSize) { | |
704 asm.pstore(CiKind.Word, result, asm.i(offset), temp1, false); | |
705 } | |
706 } | |
707 | |
708 // -- out of line ------------------------------------------------------- | |
479 asm.bindOutOfLine(tlabFull); | 709 asm.bindOutOfLine(tlabFull); |
480 XirOperand arg = asm.createRegister("runtime call argument", CiKind.Object, AMD64.rdx); | 710 XirOperand arg = asm.createRegister("runtime call argument", CiKind.Object, AMD64.rdx); |
481 asm.mov(arg, type); | 711 asm.mov(arg, type); |
482 asm.callRuntime(config.newInstanceStub, result); | 712 asm.callRuntime(config.newInstanceStub, result); |
483 asm.jmp(resume); | 713 asm.jmp(resume); |
484 | 714 |
485 return asm.finishTemplate("new instance"); | 715 return asm.finishTemplate("new instance"); |
486 } | 716 } |
487 | 717 |
718 private XirTemplate buildNewInstanceUnresolved() { | |
719 XirOperand result = asm.restart(CiKind.Word); | |
720 XirOperand arg = asm.createRegister("runtime call argument", CiKind.Object, AMD64.rdx); | |
721 | |
722 UnresolvedClassPatching patching = new UnresolvedClassPatching(asm, arg, config); | |
723 | |
724 patching.emitInline(); | |
725 useRegisters(AMD64.rbx, AMD64.rcx, AMD64.rsi); | |
726 asm.callRuntime(config.newInstanceStub, result); | |
727 | |
728 // -- out of line ------------------------------------------------------- | |
729 patching.emitOutOfLine(); | |
730 | |
731 return asm.finishTemplate("new instance"); | |
732 } | |
733 | |
734 private XirTemplate buildNewObjectArray(boolean resolved) { | |
735 XirOperand result = asm.restart(CiKind.Object); | |
736 | |
737 XirParameter lengthParam = asm.createInputParameter("length", CiKind.Int); | |
738 | |
739 XirOperand length = asm.createRegister("length", CiKind.Int, AMD64.rbx); | |
740 XirOperand hub = asm.createRegister("hub", CiKind.Object, AMD64.rdx); | |
741 | |
742 UnresolvedClassPatching patching = null; | |
743 if (resolved) { | |
744 asm.mov(hub, asm.createConstantInputParameter("hub", CiKind.Object)); | |
745 } else { | |
746 // insert the patching code for class resolving - the hub will end up in "hub" | |
747 patching = new UnresolvedClassPatching(asm, hub, config); | |
748 patching.emitInline(); | |
749 } | |
750 | |
751 asm.mov(length, lengthParam); | |
752 useRegisters(AMD64.rsi, AMD64.rcx, AMD64.rdi); | |
753 asm.callRuntime(config.newObjectArrayStub, result); | |
754 if (!resolved) { | |
755 patching.emitOutOfLine(); | |
756 } | |
757 return asm.finishTemplate(resolved ? "newObjectArray" : "newObjectArray (unresolved)"); | |
758 } | |
759 | |
760 private XirTemplate buildMultiNewArray(int dimensions, boolean resolved) { | |
761 XirOperand result = asm.restart(CiKind.Object); | |
762 | |
763 XirOperand hub = asm.createRegister("hub", CiKind.Object, AMD64.rax); | |
764 XirOperand rank = asm.createRegister("rank", CiKind.Int, AMD64.rbx); | |
765 XirOperand sizes = asm.createRegister("sizes", CiKind.Long, AMD64.rcx); | |
766 XirOperand thread = asm.createRegister("thread", CiKind.Long, AMD64.r15); | |
767 asm.add(sizes, thread, asm.l(config.threadMultiNewArrayStorage)); | |
768 for (int i = 0; i < dimensions; i++) { | |
769 XirParameter length = asm.createInputParameter("length" + i, CiKind.Int); | |
770 asm.pstore(CiKind.Int, sizes, asm.i(i * target.sizeInBytes(CiKind.Int)), length, false); | |
771 } | |
772 | |
773 UnresolvedClassPatching patching = null; | |
774 if (resolved) { | |
775 asm.mov(hub, asm.createConstantInputParameter("hub", CiKind.Object)); | |
776 } else { | |
777 // insert the patching code for class resolving - the hub will end up in "hub" | |
778 patching = new UnresolvedClassPatching(asm, hub, config); | |
779 patching.emitInline(); | |
780 } | |
781 | |
782 asm.mov(rank, asm.i(dimensions)); | |
783 asm.callRuntime(config.newMultiArrayStub, result); | |
784 if (!resolved) { | |
785 patching.emitOutOfLine(); | |
786 } | |
787 return asm.finishTemplate(resolved ? "multiNewArray" + dimensions : "multiNewArray" + dimensions + " (unresolved)"); | |
788 } | |
789 | |
790 private XirTemplate buildNewTypeArray() { | |
791 XirOperand result = asm.restart(CiKind.Object); | |
792 | |
793 XirParameter lengthParam = asm.createInputParameter("length", CiKind.Int); | |
794 XirParameter hubParam = asm.createConstantInputParameter("hub", CiKind.Object); | |
795 | |
796 XirOperand length = asm.createRegister("length", CiKind.Int, AMD64.rbx); | |
797 XirOperand hub = asm.createRegister("hub", CiKind.Object, AMD64.rdx); | |
798 | |
799 asm.mov(hub, hubParam); | |
800 asm.mov(length, lengthParam); | |
801 useRegisters(AMD64.rsi, AMD64.rcx, AMD64.rdi); | |
802 asm.callRuntime(config.newTypeArrayStub, result); | |
803 | |
804 return asm.finishTemplate("newObjectArray"); | |
805 } | |
806 | |
807 private XirTemplate buildResolveClass(boolean resolved) { | |
808 XirOperand result = asm.restart(CiKind.Word); | |
809 if (resolved) { | |
810 XirOperand type = asm.createConstantInputParameter("type", CiKind.Object); | |
811 | |
812 asm.mov(result, type); | |
813 } else { | |
814 UnresolvedClassPatching patching = new UnresolvedClassPatching(asm, result, config); | |
815 patching.emitInline(); | |
816 // -- out of line ------------------------------------------------------- | |
817 patching.emitOutOfLine(); | |
818 } | |
819 return asm.finishTemplate(resolved ? "resolve class" : "resolve class (unresolved)"); | |
820 } | |
821 | |
488 @Override | 822 @Override |
489 public XirSnippet genArrayLength(XirSite site, XirArgument array) { | 823 public XirSnippet genArrayLength(XirSite site, XirArgument array) { |
490 return new XirSnippet(arrayLengthTemplate, array); | 824 return new XirSnippet(arrayLengthTemplate, array); |
491 } | 825 } |
492 | 826 |
493 @Override | 827 @Override |
494 public XirSnippet genArrayLoad(XirSite site, XirArgument array, XirArgument index, XirArgument length, CiKind elementKind, RiType elementType) { | 828 public XirSnippet genArrayLoad(XirSite site, XirArgument array, XirArgument index, XirArgument length, CiKind elementKind, RiType elementType) { |
495 // TODO: emit different template if length is present | 829 if (length == null) { |
496 return new XirSnippet(arrayLoadTemplates[elementKind.ordinal()], array, index); | 830 return new XirSnippet(arrayLoadTemplates[elementKind.ordinal()], array, index); |
831 } | |
832 return new XirSnippet(arrayLoadTemplatesWithLength[elementKind.ordinal()], array, index, length); | |
497 } | 833 } |
498 | 834 |
499 @Override | 835 @Override |
500 public XirSnippet genArrayStore(XirSite site, XirArgument array, XirArgument index, XirArgument length, XirArgument value, CiKind elementKind, RiType elementType) { | 836 public XirSnippet genArrayStore(XirSite site, XirArgument array, XirArgument index, XirArgument length, XirArgument value, CiKind elementKind, RiType elementType) { |
501 // TODO: emit different template if length is present | 837 if (length == null) { |
502 return new XirSnippet(arrayStoreTemplates[elementKind.ordinal()], array, index, value); | 838 return new XirSnippet(arrayStoreTemplates[elementKind.ordinal()], array, index, value); |
839 } | |
840 return new XirSnippet(arrayStoreTemplatesWithLength[elementKind.ordinal()], array, index, value, length); | |
503 } | 841 } |
504 | 842 |
505 @Override | 843 @Override |
506 public XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiType type) { | 844 public XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiType type) { |
507 return new XirSnippet(emptyTemplates[CiKind.Object.ordinal()]); | 845 if (type.isResolved()) { |
846 return new XirSnippet(checkCastTemplate.resolved, receiver, hub); | |
847 } | |
848 return new XirSnippet(checkCastTemplate.unresolved, receiver); | |
508 } | 849 } |
509 | 850 |
510 @Override | 851 @Override |
511 public XirSnippet genPrologue(XirSite site, RiMethod method) { | 852 public XirSnippet genPrologue(XirSite site, RiMethod method) { |
512 boolean staticMethod = Modifier.isStatic(method.accessFlags()); | 853 boolean staticMethod = Modifier.isStatic(method.accessFlags()); |
518 return new XirSnippet(epilogueTemplate); | 859 return new XirSnippet(epilogueTemplate); |
519 } | 860 } |
520 | 861 |
521 @Override | 862 @Override |
522 public XirSnippet genGetField(XirSite site, XirArgument receiver, RiField field) { | 863 public XirSnippet genGetField(XirSite site, XirArgument receiver, RiField field) { |
523 XirPair pair = getStaticFieldTemplates[field.kind().ordinal()]; | 864 XirPair pair = getFieldTemplates[field.kind().ordinal()]; |
524 assert field.isResolved() : "getfield doesn't expect unresolved fields"; | 865 if (field.isResolved()) { |
525 XirArgument offset = XirArgument.forInt(((HotSpotField) field).offset()); | 866 return new XirSnippet(pair.resolved, receiver, XirArgument.forInt(((HotSpotField) field).offset())); |
526 return new XirSnippet(pair.resolved, receiver, offset); | 867 } |
868 return new XirSnippet(pair.unresolved, receiver); | |
527 } | 869 } |
528 | 870 |
529 @Override | 871 @Override |
530 public XirSnippet genGetStatic(XirSite site, XirArgument staticTuple, RiField field) { | 872 public XirSnippet genGetStatic(XirSite site, XirArgument staticTuple, RiField field) { |
531 XirPair pair = getStaticFieldTemplates[field.kind().ordinal()]; | 873 XirPair pair = getStaticTemplates[field.kind().ordinal()]; |
532 if (field.isResolved()) { | 874 if (field.isResolved()) { |
533 XirArgument offset = XirArgument.forInt(((HotSpotField) field).offset()); | 875 return new XirSnippet(pair.resolved, staticTuple, XirArgument.forInt(((HotSpotField) field).offset())); |
534 return new XirSnippet(pair.resolved, staticTuple, offset); | |
535 } | 876 } |
536 return new XirSnippet(pair.unresolved, staticTuple, null); | 877 return new XirSnippet(pair.unresolved, staticTuple, null); |
537 } | 878 } |
538 | 879 |
539 @Override | 880 @Override |
540 public XirSnippet genPutField(XirSite site, XirArgument receiver, RiField field, XirArgument value) { | 881 public XirSnippet genPutField(XirSite site, XirArgument receiver, RiField field, XirArgument value) { |
541 XirPair pair = putFieldTemplates[field.kind().ordinal()]; | 882 XirPair pair = putFieldTemplates[field.kind().ordinal()]; |
542 assert field.isResolved() : "putfield doesn't expect unresolved fields"; | 883 if (field.isResolved()) { |
543 XirArgument offset = XirArgument.forInt(((HotSpotField) field).offset()); | 884 return new XirSnippet(pair.resolved, receiver, value, XirArgument.forInt(((HotSpotField) field).offset())); |
544 return new XirSnippet(pair.resolved, receiver, value, offset); | 885 } |
886 return new XirSnippet(pair.unresolved, receiver, value); | |
545 } | 887 } |
546 | 888 |
547 @Override | 889 @Override |
548 public XirSnippet genPutStatic(XirSite site, XirArgument staticTuple, RiField field, XirArgument value) { | 890 public XirSnippet genPutStatic(XirSite site, XirArgument staticTuple, RiField field, XirArgument value) { |
549 XirPair pair = putFieldTemplates[field.kind().ordinal()]; | 891 XirPair pair = putStaticTemplates[field.kind().ordinal()]; |
550 if (field.isResolved()) { | 892 if (field.isResolved()) { |
551 XirArgument offset = XirArgument.forInt(((HotSpotField) field).offset()); | 893 return new XirSnippet(pair.resolved, staticTuple, value, XirArgument.forInt(((HotSpotField) field).offset())); |
552 return new XirSnippet(pair.resolved, staticTuple, value, offset); | |
553 } | 894 } |
554 return new XirSnippet(pair.unresolved, staticTuple, value); | 895 return new XirSnippet(pair.unresolved, staticTuple, value); |
555 } | 896 } |
556 | 897 |
557 @Override | 898 @Override |
558 public XirSnippet genInstanceOf(XirSite site, XirArgument receiver, XirArgument hub, RiType type) { | 899 public XirSnippet genInstanceOf(XirSite site, XirArgument receiver, XirArgument hub, RiType type) { |
559 if (type.isResolved()) { | 900 if (type.isResolved()) { |
560 return new XirSnippet(instanceofTemplate.resolved, receiver, hub); | 901 return new XirSnippet(instanceofTemplate.resolved, receiver, hub); |
561 } | 902 } |
562 // XirArgument guard = guardFor(type, ResolveClass.SNIPPET); | |
563 return new XirSnippet(instanceofTemplate.unresolved, receiver); | 903 return new XirSnippet(instanceofTemplate.unresolved, receiver); |
564 } | 904 } |
565 | 905 |
566 @Override | 906 @Override |
567 public XirSnippet genIntrinsic(XirSite site, XirArgument[] arguments, RiMethod method) { | 907 public XirSnippet genIntrinsic(XirSite site, XirArgument[] arguments, RiMethod method) { |
568 return null; | 908 return null; |
569 } | 909 } |
570 | 910 |
571 @Override | 911 @Override |
572 public XirSnippet genInvokeInterface(XirSite site, XirArgument receiver, RiMethod method) { | 912 public XirSnippet genInvokeInterface(XirSite site, XirArgument receiver, RiMethod method) { |
573 return new XirSnippet(invokeInterfaceTemplate, XirArgument.forWord(0)); | 913 return new XirSnippet(invokeInterfaceTemplate, receiver, XirArgument.forWord(0)); |
574 } | 914 } |
575 | 915 |
576 @Override | 916 @Override |
577 public XirSnippet genInvokeSpecial(XirSite site, XirArgument receiver, RiMethod method) { | 917 public XirSnippet genInvokeSpecial(XirSite site, XirArgument receiver, RiMethod method) { |
578 return new XirSnippet(invokeSpecialTemplate, XirArgument.forWord(0)); | 918 return new XirSnippet(invokeSpecialTemplate, receiver, XirArgument.forWord(0)); |
579 } | 919 } |
580 | 920 |
581 @Override | 921 @Override |
582 public XirSnippet genInvokeStatic(XirSite site, RiMethod method) { | 922 public XirSnippet genInvokeStatic(XirSite site, RiMethod method) { |
583 return new XirSnippet(invokeStaticTemplate, XirArgument.forWord(0)); | 923 return new XirSnippet(invokeStaticTemplate, XirArgument.forWord(0)); |
584 } | 924 } |
585 | 925 |
586 @Override | 926 @Override |
587 public XirSnippet genInvokeVirtual(XirSite site, XirArgument receiver, RiMethod method) { | 927 public XirSnippet genInvokeVirtual(XirSite site, XirArgument receiver, RiMethod method) { |
588 return new XirSnippet(invokeVirtualTemplate, XirArgument.forWord(0)); | 928 return new XirSnippet(invokeVirtualTemplate, receiver, XirArgument.forWord(0)); |
589 } | 929 } |
590 | 930 |
591 @Override | 931 @Override |
592 public XirSnippet genMonitorEnter(XirSite site, XirArgument receiver) { | 932 public XirSnippet genMonitorEnter(XirSite site, XirArgument receiver) { |
593 return new XirSnippet(emptyTemplates[CiKind.Void.ordinal()]); | 933 return new XirSnippet(emptyTemplates[CiKind.Void.ordinal()]); |
598 return new XirSnippet(emptyTemplates[CiKind.Void.ordinal()]); | 938 return new XirSnippet(emptyTemplates[CiKind.Void.ordinal()]); |
599 } | 939 } |
600 | 940 |
601 @Override | 941 @Override |
602 public XirSnippet genNewArray(XirSite site, XirArgument length, CiKind elementKind, RiType componentType, RiType arrayType) { | 942 public XirSnippet genNewArray(XirSite site, XirArgument length, CiKind elementKind, RiType componentType, RiType arrayType) { |
603 return new XirSnippet(emptyTemplates[CiKind.Object.ordinal()]); | 943 if (elementKind == CiKind.Object) { |
944 if (arrayType instanceof HotSpotTypeResolved) { | |
945 return new XirSnippet(newObjectArrayTemplate.resolved, length, XirArgument.forObject(arrayType)); | |
946 } | |
947 return new XirSnippet(newObjectArrayTemplate.unresolved, length); | |
948 } | |
949 assert arrayType == null; | |
950 arrayType = Compiler.getVMEntries().getPrimitiveArrayType(elementKind); | |
951 return new XirSnippet(newTypeArrayTemplate, length, XirArgument.forObject(arrayType)); | |
604 } | 952 } |
605 | 953 |
606 @Override | 954 @Override |
607 public XirSnippet genNewInstance(XirSite site, RiType type) { | 955 public XirSnippet genNewInstance(XirSite site, RiType type) { |
608 assert type instanceof HotSpotTypeResolved; | 956 if (type instanceof HotSpotTypeResolved) { |
609 HotSpotTypeResolved resolved = (HotSpotTypeResolved) type; | 957 int instanceSize = ((HotSpotTypeResolved) type).instanceSize(); |
610 return new XirSnippet(newInstanceTemplate, XirArgument.forObject(type), XirArgument.forWord(resolved.instanceSize())); | 958 return new XirSnippet(newInstanceTemplates.get(instanceSize), XirArgument.forObject(type)); |
959 } | |
960 return new XirSnippet(newInstanceUnresolvedTemplate); | |
611 } | 961 } |
612 | 962 |
613 @Override | 963 @Override |
614 public XirSnippet genNewMultiArray(XirSite site, XirArgument[] lengths, RiType type) { | 964 public XirSnippet genNewMultiArray(XirSite site, XirArgument[] lengths, RiType type) { |
615 return new XirSnippet(emptyTemplates[CiKind.Object.ordinal()]); | 965 if (type instanceof HotSpotTypeResolved) { |
966 XirArgument[] params = Arrays.copyOf(lengths, lengths.length + 1); | |
967 params[lengths.length] = XirArgument.forObject(type); | |
968 return new XirSnippet(multiNewArrayTemplate.get(lengths.length).resolved, params); | |
969 } | |
970 return new XirSnippet(multiNewArrayTemplate.get(lengths.length).unresolved, lengths); | |
616 } | 971 } |
617 | 972 |
618 @Override | 973 @Override |
619 public XirSnippet genResolveClass(XirSite site, RiType type, Representation representation) { | 974 public XirSnippet genResolveClass(XirSite site, RiType type, Representation representation) { |
620 XirOperand result = asm.restart(CiKind.Object); | 975 assert representation == Representation.ObjectHub; |
621 if (type.isResolved()) { | 976 if (type instanceof HotSpotTypeResolved) { |
622 asm.mov(result, asm.o(type)); | 977 return new XirSnippet(resolveClassTemplate.resolved, XirArgument.forObject(type)); |
623 return new XirSnippet(asm.finishTemplate("resolve class")); | 978 } |
624 } | 979 return new XirSnippet(resolveClassTemplate.unresolved); |
625 asm.shouldNotReachHere(); | |
626 return new XirSnippet(asm.finishTemplate("resolve class")); | |
627 | |
628 } | 980 } |
629 | 981 |
630 @Override | 982 @Override |
631 public XirSnippet genSafepoint(XirSite site) { | 983 public XirSnippet genSafepoint(XirSite site) { |
632 return new XirSnippet(emptyTemplates[CiKind.Void.ordinal()]); | 984 return new XirSnippet(safepointTemplate); |
633 } | 985 } |
634 | 986 |
635 @Override | 987 @Override |
636 public XirSnippet genExceptionObject(XirSite site) { | 988 public XirSnippet genExceptionObject(XirSite site) { |
637 return new XirSnippet(exceptionObjectTemplate); | 989 return new XirSnippet(exceptionObjectTemplate); |
638 } | 990 } |
639 | 991 |
992 private static class UnresolvedClassPatching { | |
993 | |
994 private final XirLabel patchSite; | |
995 private final XirLabel replacement; | |
996 private final XirLabel patchStub; | |
997 private final CiXirAssembler asm; | |
998 private final HotSpotVMConfig config; | |
999 private final XirOperand arg; | |
1000 private State state; | |
1001 | |
1002 private enum State { | |
1003 New, Inline, Finished | |
1004 } | |
1005 | |
1006 public UnresolvedClassPatching(CiXirAssembler asm, XirOperand arg, HotSpotVMConfig config) { | |
1007 this.asm = asm; | |
1008 this.arg = arg; | |
1009 this.config = config; | |
1010 patchSite = asm.createInlineLabel("patch site"); | |
1011 replacement = asm.createOutOfLineLabel("replacement"); | |
1012 patchStub = asm.createOutOfLineLabel("patch stub"); | |
1013 | |
1014 state = State.New; | |
1015 } | |
1016 | |
1017 public void emitInline() { | |
1018 assert state == State.New; | |
1019 | |
1020 asm.bindInline(patchSite); | |
1021 asm.mark(MARK_DUMMY_OOP_RELOCATION); | |
1022 asm.jmp(patchStub); | |
1023 | |
1024 // TODO: make this more generic & safe - this is needed to create space for patching | |
1025 asm.nop(5); | |
1026 | |
1027 state = State.Inline; | |
1028 } | |
1029 | |
1030 public void emitOutOfLine() { | |
1031 assert state == State.Inline; | |
1032 | |
1033 asm.bindOutOfLine(replacement); | |
1034 XirMark begin = asm.mark(null); | |
1035 asm.mov(arg, asm.createConstant(CiConstant.forObject(null))); | |
1036 XirMark end = asm.mark(null); | |
1037 // make this piece of data look like an instruction | |
1038 asm.rawBytes(new byte[] { (byte) 0xb8, 0, 0, 0x05, 0}); | |
1039 asm.mark(MARK_KLASS_PATCHING, begin, end); | |
1040 asm.bindOutOfLine(patchStub); | |
1041 asm.callRuntime(config.loadKlassStub, null); | |
1042 asm.jmp(patchSite); | |
1043 | |
1044 state = State.Finished; | |
1045 } | |
1046 } | |
1047 | |
1048 private void checkSubtype(XirOperand result, XirOperand objHub, XirOperand hub) { | |
1049 asm.push(objHub); | |
1050 asm.push(hub); | |
1051 asm.callRuntime(config.instanceofStub, null); | |
1052 asm.pop(result); | |
1053 asm.pop(result); | |
1054 } | |
1055 | |
1056 private void useRegisters(CiXirAssembler asm, CiRegister... registers) { | |
1057 if (registers != null) { | |
1058 for (CiRegister register : registers) { | |
1059 asm.createRegister("reg", CiKind.Illegal, register); | |
1060 } | |
1061 } | |
1062 } | |
1063 | |
1064 private void useRegisters(CiRegister... registers) { | |
1065 useRegisters(asm, registers); | |
1066 } | |
1067 | |
1068 private abstract class OndemandTemplates<T> { | |
1069 | |
1070 private ConcurrentHashMap<Integer, T> templates = new ConcurrentHashMap<Integer, T>(); | |
1071 | |
1072 protected abstract T create(CiXirAssembler asm, int index); | |
1073 | |
1074 public T get(int index) { | |
1075 T template = templates.get(index); | |
1076 if (template == null) { | |
1077 template = create(asm.copy(), index); | |
1078 templates.put(index, template); | |
1079 } | |
1080 return template; | |
1081 } | |
1082 } | |
640 } | 1083 } |