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 }