Mercurial > hg > graal-jvmci-8
comparison c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/HotSpotXirGenerator.java @ 1433:efba53f86c4f
various fixes and enhancements
* correct refmap->oopmap conversion (register numbering, stack slot numbering)
* fixes for inlining (correct scoping in exception handler lookup, NPE in scope conversion)
* support for "jump to runtime stub" (patching code needs to be aware of jmp instruction)
* provide more information about methods (to allow inlining: has_balanced_monitors, etc.)
* fixes to signature type lookup
* isSubTypeOf: correct handling of array classes
* RiType: componentType/arrayOf
* prologue: inline cache check, icmiss stub
* klass state check (resolved but not initialized) in newinstance
* card table write barriers
* c1x classes are optional (to allow running c1 without them)
* correct for stored frame pointer in calling conventions (methods with arguments on stack)
* getType(Class<?>) for some basic types, used for optimizations and folding
* RiMethod/RiType: throw exception instead of silent failure on unsupported operations
* RiType: resolved/unresolved array type support
* refactoring: new on-demand template generation mechanism
* optimizations: template specialization for no_null_check, given length, etc.
author | Lukas Stadler <lukas.stadler@oracle.com> |
---|---|
date | Thu, 16 Sep 2010 19:42:20 -0700 |
parents | 949ade3f2ff3 |
children | 72cfb36c6bb2 |
comparison
equal
deleted
inserted
replaced
1432:b61a43cd1255 | 1433:efba53f86c4f |
---|---|
25 import com.sun.cri.ci.CiAddress.Scale; | 25 import com.sun.cri.ci.CiAddress.Scale; |
26 import com.sun.cri.ci.*; | 26 import com.sun.cri.ci.*; |
27 import com.sun.cri.ri.*; | 27 import com.sun.cri.ri.*; |
28 import com.sun.cri.ri.RiType.Representation; | 28 import com.sun.cri.ri.RiType.Representation; |
29 import com.sun.cri.xir.*; | 29 import com.sun.cri.xir.*; |
30 import com.sun.cri.xir.CiXirAssembler.XirOperand; | |
31 import com.sun.cri.xir.CiXirAssembler.*; | 30 import com.sun.cri.xir.CiXirAssembler.*; |
31 import static com.sun.hotspot.c1x.TemplateFlag.*; | |
32 | 32 |
33 /** | 33 /** |
34 * | 34 * |
35 * @author Thomas Wuerthinger, Lukas Stadler | 35 * @author Thomas Wuerthinger, Lukas Stadler |
36 */ | 36 */ |
54 | 54 |
55 private static final Integer MARK_IMPLICIT_NULL = 0x3000; | 55 private static final Integer MARK_IMPLICIT_NULL = 0x3000; |
56 | 56 |
57 private static final Integer MARK_KLASS_PATCHING = 0x4000; | 57 private static final Integer MARK_KLASS_PATCHING = 0x4000; |
58 private static final Integer MARK_DUMMY_OOP_RELOCATION = 0x4001; | 58 private static final Integer MARK_DUMMY_OOP_RELOCATION = 0x4001; |
59 private static final Integer MARK_ACCESS_FIELD_PATCHING = 0x4002; | |
59 // @formatter:on | 60 // @formatter:on |
60 | 61 |
61 private final HotSpotVMConfig config; | 62 private final HotSpotVMConfig config; |
62 private final CiTarget target; | 63 private final CiTarget target; |
63 private final RiRegisterConfig registerConfig; | 64 private final RiRegisterConfig registerConfig; |
64 | 65 |
65 private CiXirAssembler asm; | 66 private CiXirAssembler asm; |
66 | |
67 private XirTemplate[] emptyTemplates = new XirTemplate[CiKind.values().length]; | |
68 private XirTemplate[] arrayLoadTemplates = 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]; | |
72 private XirTemplate prologueTemplate; | |
73 private XirTemplate staticPrologueTemplate; | |
74 private XirTemplate epilogueTemplate; | |
75 private XirTemplate arrayLengthTemplate; | |
76 private XirTemplate safepointTemplate; | |
77 private XirTemplate exceptionObjectTemplate; | |
78 private XirTemplate invokeStaticTemplate; | |
79 private XirTemplate invokeSpecialTemplate; | |
80 private XirTemplate invokeInterfaceTemplate; | |
81 private XirTemplate invokeVirtualTemplate; | |
82 | |
83 private XirTemplate newInstanceUnresolvedTemplate; | |
84 private XirPair newObjectArrayTemplate; | |
85 private XirTemplate newTypeArrayTemplate; | |
86 private XirPair resolveClassTemplate; | |
87 private XirPair checkCastTemplate; | |
88 | |
89 static class XirPair { | |
90 | |
91 final XirTemplate resolved; | |
92 final XirTemplate unresolved; | |
93 | |
94 XirPair(XirTemplate resolved, XirTemplate unresolved) { | |
95 this.resolved = resolved; | |
96 this.unresolved = unresolved; | |
97 } | |
98 } | |
99 | |
100 private XirPair[] putFieldTemplates = new XirPair[CiKind.values().length]; | |
101 private XirPair[] getFieldTemplates = new XirPair[CiKind.values().length]; | |
102 private XirPair[] putStaticTemplates = new XirPair[CiKind.values().length]; | |
103 private XirPair[] getStaticTemplates = new XirPair[CiKind.values().length]; | |
104 private XirPair instanceofTemplate; | |
105 private XirPair instanceofTemplateNonnull; | |
106 | 67 |
107 public HotSpotXirGenerator(HotSpotVMConfig config, CiTarget target, RiRegisterConfig registerConfig) { | 68 public HotSpotXirGenerator(HotSpotVMConfig config, CiTarget target, RiRegisterConfig registerConfig) { |
108 this.config = config; | 69 this.config = config; |
109 this.target = target; | 70 this.target = target; |
110 this.registerConfig = registerConfig; | 71 this.registerConfig = registerConfig; |
111 } | 72 } |
112 | 73 |
113 @Override | 74 private SimpleTemplates prologueTemplates = new SimpleTemplates(STATIC_METHOD, SYNCHRONIZED) { |
114 public List<XirTemplate> buildTemplates(CiXirAssembler asm) { | 75 |
115 this.asm = asm; | 76 @Override |
116 | 77 protected XirTemplate create(CiXirAssembler asm, long flags) { |
117 List<XirTemplate> templates = new ArrayList<XirTemplate>(); | 78 asm.restart(CiKind.Void); |
118 for (CiKind kind : CiKind.JAVA_VALUES) { | 79 XirOperand framePointer = asm.createRegister("frame pointer", CiKind.Word, AMD64.rbp); |
119 int index = kind.ordinal(); | 80 XirOperand stackPointer = asm.createRegister("stack pointer", CiKind.Word, AMD64.rsp); |
120 | 81 XirLabel unverifiedStub = null; |
121 if (kind == CiKind.Void) { | 82 |
122 asm.restart(CiKind.values()[index]); | 83 asm.mark(MARK_OSR_ENTRY); |
123 emptyTemplates[index] = asm.finishTemplate("empty-" + kind); | 84 asm.mark(MARK_UNVERIFIED_ENTRY); |
85 if (!is(STATIC_METHOD, flags)) { | |
86 unverifiedStub = asm.createOutOfLineLabel("unverified"); | |
87 | |
88 XirOperand temp = asm.createRegister("temp (r10)", CiKind.Word, AMD64.r10); | |
89 XirOperand cache = asm.createRegister("cache (rax)", CiKind.Word, AMD64.rax); | |
90 | |
91 CiCallingConvention conventions = registerConfig.getJavaCallingConvention(new CiKind[] { CiKind.Object}, false, target); | |
92 XirOperand receiver = asm.createRegister("cache (rax)", CiKind.Word, conventions.locations[0].asRegister()); | |
93 | |
94 asm.pload(CiKind.Word, temp, receiver, asm.i(config.hubOffset), false); | |
95 asm.jneq(unverifiedStub, cache, temp); | |
96 } | |
97 asm.align(config.codeEntryAlignment); | |
98 asm.mark(MARK_VERIFIED_ENTRY); | |
99 asm.push(framePointer); | |
100 asm.mov(framePointer, stackPointer); | |
101 asm.pushFrame(); | |
102 | |
103 if (is(SYNCHRONIZED, flags)) { | |
104 // TODO synchronized methods / monitors | |
105 } | |
106 | |
107 // -- out of line ------------------------------------------------------- | |
108 XirOperand thread = asm.createRegister("thread", CiKind.Word, AMD64.r15); | |
109 XirOperand exceptionOop = asm.createTemp("exception oop", CiKind.Object); | |
110 XirLabel unwind = asm.createOutOfLineLabel("unwind"); | |
111 asm.bindOutOfLine(unwind); | |
112 | |
113 asm.mark(MARK_UNWIND_ENTRY); | |
114 | |
115 asm.pload(CiKind.Object, exceptionOop, thread, asm.i(config.threadExceptionOopOffset), false); | |
116 asm.pstore(CiKind.Object, thread, asm.i(config.threadExceptionOopOffset), asm.createConstant(CiConstant.NULL_OBJECT), false); | |
117 asm.pstore(CiKind.Long, thread, asm.i(config.threadExceptionPcOffset), asm.l(0), false); | |
118 | |
119 asm.callRuntime(config.unwindExceptionStub, null, exceptionOop); | |
120 asm.shouldNotReachHere(); | |
121 | |
122 asm.mark(MARK_EXCEPTION_HANDLER_ENTRY); | |
123 asm.callRuntime(config.handleExceptionStub, null); | |
124 asm.shouldNotReachHere(); | |
125 | |
126 if (!is(STATIC_METHOD, flags)) { | |
127 asm.bindOutOfLine(unverifiedStub); | |
128 asm.jmpRuntime(config.inlineCacheMissStub); | |
129 } | |
130 | |
131 return asm.finishTemplate(is(STATIC_METHOD, flags) ? "static prologue" : "prologue"); | |
132 } | |
133 }; | |
134 | |
135 private SimpleTemplates epilogueTemplates = new SimpleTemplates(STATIC_METHOD, SYNCHRONIZED) { | |
136 | |
137 @Override | |
138 protected XirTemplate create(CiXirAssembler asm, long flags) { | |
139 asm.restart(CiKind.Void); | |
140 XirOperand framePointer = asm.createRegister("frame pointer", CiKind.Word, AMD64.rbp); | |
141 | |
142 if (is(SYNCHRONIZED, flags)) { | |
143 // TODO synchronized methods / monitors | |
144 } | |
145 | |
146 asm.popFrame(); | |
147 asm.pop(framePointer); | |
148 | |
149 // TODO safepoint check | |
150 | |
151 return asm.finishTemplate("epilogue"); | |
152 } | |
153 }; | |
154 | |
155 private SimpleTemplates safepointTemplates = new SimpleTemplates() { | |
156 | |
157 @Override | |
158 protected XirTemplate create(CiXirAssembler asm, long flags) { | |
159 asm.restart(CiKind.Void); | |
160 | |
161 // TODO safepoint | |
162 return asm.finishTemplate("safepoint"); | |
163 } | |
164 }; | |
165 | |
166 private SimpleTemplates exceptionObjectTemplates = new SimpleTemplates() { | |
167 | |
168 @Override | |
169 protected XirTemplate create(CiXirAssembler asm, long flags) { | |
170 XirOperand result = asm.restart(CiKind.Object); | |
171 XirOperand thread = asm.createRegister("thread", CiKind.Word, AMD64.r15); | |
172 | |
173 asm.pload(CiKind.Object, result, thread, asm.i(config.threadExceptionOopOffset), false); | |
174 asm.pstore(CiKind.Object, thread, asm.i(config.threadExceptionOopOffset), asm.o(null), false); | |
175 asm.pstore(CiKind.Long, thread, asm.i(config.threadExceptionPcOffset), asm.l(0), false); | |
176 | |
177 return asm.finishTemplate("exception object"); | |
178 } | |
179 }; | |
180 | |
181 private SimpleTemplates resolveClassTemplates = new SimpleTemplates(UNRESOLVED) { | |
182 | |
183 @Override | |
184 protected XirTemplate create(CiXirAssembler asm, long flags) { | |
185 XirOperand result = asm.restart(CiKind.Word); | |
186 if (is(UNRESOLVED, flags)) { | |
187 UnresolvedClassPatching patching = new UnresolvedClassPatching(asm, result, config); | |
188 patching.emitInline(); | |
189 // -- out of line ------------------------------------------------------- | |
190 patching.emitOutOfLine(); | |
124 } else { | 191 } else { |
125 asm.restart(); | 192 XirOperand type = asm.createConstantInputParameter("type", CiKind.Object); |
126 XirOperand result = asm.createTemp("result", kind); | 193 asm.mov(result, type); |
127 emptyTemplates[index] = asm.finishTemplate(result, "empty-" + kind); | 194 } |
128 | 195 return asm.finishTemplate(is(UNRESOLVED, flags) ? "resolve class (unresolved)" : "resolve class"); |
129 putFieldTemplates[index] = buildPutFieldTemplate(kind, kind == CiKind.Object); | 196 } |
130 getFieldTemplates[index] = buildGetFieldTemplate(kind); | 197 }; |
131 putStaticTemplates[index] = buildPutStaticTemplate(kind, kind == CiKind.Object); | 198 |
132 getStaticTemplates[index] = buildGetStaticTemplate(kind); | 199 private SimpleTemplates invokeInterfaceTemplates = new SimpleTemplates(NULL_CHECK) { |
133 arrayLoadTemplates[index] = buildArrayLoad(kind, asm, true, false); | 200 |
134 arrayStoreTemplates[index] = buildArrayStore(kind, asm, true, kind == CiKind.Object, kind == CiKind.Object, false); | 201 @Override |
135 arrayLoadTemplatesWithLength[index] = buildArrayLoad(kind, asm, true, true); | 202 protected XirTemplate create(CiXirAssembler asm, long flags) { |
136 arrayStoreTemplatesWithLength[index] = buildArrayStore(kind, asm, true, kind == CiKind.Object, kind == CiKind.Object, true); | 203 asm.restart(); |
137 // newArrayTemplates[index] = buildNewArray(kind); | 204 XirParameter receiver = asm.createInputParameter("receiver", CiKind.Object); |
138 } | 205 XirParameter addr = asm.createConstantInputParameter("addr", CiKind.Word); |
139 // templates.add(emptyTemplates[index]); | 206 XirOperand temp = asm.createRegister("temp", CiKind.Word, AMD64.rax); |
140 } | 207 |
141 | 208 if (is(NULL_CHECK, flags)) { |
142 asm.restart(); | 209 asm.nop(1); |
143 XirOperand result = asm.createTemp("result", CiKind.Word); | 210 asm.mark(MARK_IMPLICIT_NULL); |
144 emptyTemplates[CiKind.Word.ordinal()] = asm.finishTemplate(result, "empty-Word"); | 211 asm.pload(CiKind.Word, temp, receiver, true); |
145 | 212 } |
146 prologueTemplate = buildPrologue(false); | 213 asm.mark(MARK_INVOKEINTERFACE); |
147 staticPrologueTemplate = buildPrologue(true); | 214 asm.mov(temp, asm.createConstant(CiConstant.forObject(HotSpotProxy.DUMMY_CONSTANT_OBJ))); |
148 epilogueTemplate = buildEpilogue(); | 215 |
149 arrayLengthTemplate = buildArrayLength(); | 216 return asm.finishTemplate(addr, "invokeinterface"); |
150 exceptionObjectTemplate = buildExceptionObject(); | 217 } |
151 safepointTemplate = buildSafepoint(); | 218 }; |
152 instanceofTemplate = buildInstanceof(false); | 219 |
153 instanceofTemplateNonnull = buildInstanceof(true); | 220 private SimpleTemplates invokeVirtualTemplates = new SimpleTemplates(NULL_CHECK) { |
154 invokeStaticTemplate = buildInvokeStatic(); | 221 |
155 invokeSpecialTemplate = buildInvokeSpecial(); | 222 @Override |
156 invokeInterfaceTemplate = buildInvokeInterface(); | 223 protected XirTemplate create(CiXirAssembler asm, long flags) { |
157 invokeVirtualTemplate = buildInvokeVirtual(); | 224 asm.restart(); |
158 newInstanceUnresolvedTemplate = buildNewInstanceUnresolved(); | 225 XirParameter receiver = asm.createInputParameter("receiver", CiKind.Object); |
159 newObjectArrayTemplate = new XirPair(buildNewObjectArray(true), buildNewObjectArray(false)); | 226 XirParameter addr = asm.createConstantInputParameter("addr", CiKind.Word); |
160 newTypeArrayTemplate = buildNewTypeArray(); | 227 XirOperand temp = asm.createRegister("temp", CiKind.Word, AMD64.rax); |
161 resolveClassTemplate = new XirPair(buildResolveClass(true), buildResolveClass(false)); | 228 |
162 checkCastTemplate = buildCheckCast(); | 229 if (is(NULL_CHECK, flags)) { |
163 | 230 asm.nop(1); |
164 return templates; | 231 asm.mark(MARK_IMPLICIT_NULL); |
165 } | 232 asm.pload(CiKind.Word, temp, receiver, true); |
166 | 233 } |
167 private final OndemandTemplates<XirTemplate> newInstanceTemplates = new OndemandTemplates<XirTemplate>() { | 234 asm.mark(MARK_INVOKEVIRTUAL); |
168 | 235 asm.mov(temp, asm.createConstant(CiConstant.forObject(HotSpotProxy.DUMMY_CONSTANT_OBJ))); |
169 @Override | 236 |
170 protected XirTemplate create(CiXirAssembler asm, int size) { | 237 return asm.finishTemplate(addr, "invokevirtual"); |
171 return buildNewInstance(asm, size); | 238 } |
172 } | 239 }; |
173 }; | 240 |
174 | 241 private SimpleTemplates invokeSpecialTemplates = new SimpleTemplates(NULL_CHECK) { |
175 private final OndemandTemplates<XirPair> multiNewArrayTemplate = new OndemandTemplates<HotSpotXirGenerator.XirPair>() { | 242 |
176 | 243 @Override |
177 @Override | 244 protected XirTemplate create(CiXirAssembler asm, long flags) { |
178 protected XirPair create(CiXirAssembler asm, int dimensions) { | 245 asm.restart(); |
179 return new XirPair(buildMultiNewArray(dimensions, true), buildMultiNewArray(dimensions, false)); | 246 XirParameter receiver = asm.createInputParameter("receiver", CiKind.Object); |
180 } | 247 XirParameter addr = asm.createConstantInputParameter("addr", CiKind.Word); |
181 }; | 248 XirOperand temp = asm.createRegister("temp", CiKind.Word, AMD64.rax); |
182 | 249 XirLabel stub = asm.createOutOfLineLabel("call stub"); |
183 private XirTemplate buildPrologue(boolean staticMethod) { | 250 |
184 asm.restart(CiKind.Void); | 251 if (is(NULL_CHECK, flags)) { |
185 XirOperand temp = asm.createRegister("temp (rax)", CiKind.Int, AMD64.rax); | 252 asm.nop(1); |
186 XirOperand framePointer = asm.createRegister("frame pointer", CiKind.Word, AMD64.rbp); | 253 asm.mark(MARK_IMPLICIT_NULL); |
187 XirOperand stackPointer = asm.createRegister("stack pointer", CiKind.Word, AMD64.rsp); | 254 asm.pload(CiKind.Word, temp, receiver, true); |
188 | 255 } |
189 asm.align(config.codeEntryAlignment); | 256 asm.mark(MARK_INVOKESPECIAL); |
190 asm.mark(MARK_OSR_ENTRY); | 257 |
191 asm.mark(MARK_UNVERIFIED_ENTRY); | 258 // -- out of line ------------------------------------------------------- |
192 if (!staticMethod) { | 259 asm.bindOutOfLine(stub); |
193 // TODO do some checking... | 260 XirOperand method = asm.createRegister("method", CiKind.Word, AMD64.rbx); |
194 asm.add(temp, temp, asm.i(1)); | 261 asm.mark(MARK_STATIC_CALL_STUB, XirMark.CALLSITE); |
195 asm.sub(temp, temp, asm.i(1)); | 262 asm.mov(method, asm.w(0l)); |
196 asm.shouldNotReachHere(); | 263 XirLabel dummy = asm.createOutOfLineLabel("dummy"); |
197 | 264 asm.jmp(dummy); |
198 asm.align(config.codeEntryAlignment); | 265 asm.bindOutOfLine(dummy); |
199 } | 266 |
200 asm.mark(MARK_VERIFIED_ENTRY); | 267 return asm.finishTemplate(addr, "invokespecial"); |
201 asm.push(framePointer); | 268 } |
202 asm.mov(framePointer, stackPointer); | 269 }; |
203 asm.pushFrame(); | 270 |
204 | 271 private SimpleTemplates invokeStaticTemplates = new SimpleTemplates() { |
205 // -- out of line ------------------------------------------------------- | 272 |
206 XirOperand thread = asm.createRegister("thread", CiKind.Word, AMD64.r15); | 273 @Override |
207 XirOperand exceptionOop = asm.createTemp("exception oop", CiKind.Object); | 274 protected XirTemplate create(CiXirAssembler asm, long flags) { |
208 XirLabel unwind = asm.createOutOfLineLabel("unwind"); | 275 asm.restart(); |
209 asm.bindOutOfLine(unwind); | 276 XirParameter addr = asm.createConstantInputParameter("addr", CiKind.Word); |
210 | 277 |
211 asm.mark(MARK_UNWIND_ENTRY); | 278 XirLabel stub = asm.createOutOfLineLabel("call stub"); |
212 //asm.popFrame(); | 279 asm.mark(MARK_INVOKESTATIC); |
213 //asm.pop(framePointer); | 280 |
214 | 281 // -- out of line ------------------------------------------------------- |
215 // TODO synchronized methods / monitors | 282 asm.bindOutOfLine(stub); |
216 | 283 XirOperand method = asm.createRegister("method", CiKind.Word, AMD64.rbx); |
217 asm.pload(CiKind.Object, exceptionOop, thread, asm.i(config.threadExceptionOopOffset), false); | 284 asm.mark(MARK_STATIC_CALL_STUB, XirMark.CALLSITE); |
218 asm.pstore(CiKind.Object, thread, asm.i(config.threadExceptionOopOffset), asm.createConstant(CiConstant.NULL_OBJECT), false); | 285 asm.mov(method, asm.w(0l)); |
219 asm.pstore(CiKind.Long, thread, asm.i(config.threadExceptionPcOffset), asm.l(0), false); | 286 XirLabel dummy = asm.createOutOfLineLabel("dummy"); |
220 | 287 asm.jmp(dummy); |
221 asm.callRuntime(config.unwindExceptionStub, null, exceptionOop); | 288 asm.bindOutOfLine(dummy); |
222 asm.shouldNotReachHere(); | 289 |
223 | 290 return asm.finishTemplate(addr, "invokestatic"); |
224 asm.mark(MARK_EXCEPTION_HANDLER_ENTRY); | 291 } |
225 asm.callRuntime(config.handleExceptionStub, null); | 292 }; |
226 asm.shouldNotReachHere(); | 293 |
227 | 294 private SimpleTemplates monitorEnterTemplates = new SimpleTemplates(NULL_CHECK) { |
228 return asm.finishTemplate(staticMethod ? "static prologue" : "prologue"); | 295 |
229 } | 296 @Override |
230 | 297 protected XirTemplate create(CiXirAssembler asm, long flags) { |
231 private XirTemplate buildEpilogue() { | 298 asm.restart(CiKind.Void); |
232 asm.restart(CiKind.Void); | 299 XirParameter object = asm.createInputParameter("object", CiKind.Object); |
233 XirOperand framePointer = asm.createRegister("frame pointer", CiKind.Word, AMD64.rbp); | 300 XirOperand temp = asm.createRegister("temp", CiKind.Word, AMD64.rax); |
234 | 301 |
235 asm.popFrame(); | 302 if (is(NULL_CHECK, flags)) { |
236 asm.pop(framePointer); | 303 asm.nop(1); |
237 // TODO safepoint check | 304 asm.mark(MARK_IMPLICIT_NULL); |
238 | 305 asm.pload(CiKind.Word, temp, object, true); |
239 return asm.finishTemplate("epilogue"); | 306 } |
240 } | 307 |
241 | 308 return asm.finishTemplate("monitorEnter"); |
242 private XirTemplate buildArrayLength() { | 309 } |
243 XirOperand result = asm.restart(CiKind.Int); | 310 }; |
244 XirParameter object = asm.createInputParameter("object", CiKind.Object); | 311 |
245 asm.nop(1); | 312 private SimpleTemplates monitorExitTemplates = new SimpleTemplates(NULL_CHECK) { |
246 asm.mark(MARK_IMPLICIT_NULL); | 313 |
247 asm.pload(CiKind.Int, result, object, asm.i(config.arrayLengthOffset), true); | 314 @Override |
248 return asm.finishTemplate("arrayLength"); | 315 protected XirTemplate create(CiXirAssembler asm, long flags) { |
249 } | 316 asm.restart(CiKind.Void); |
250 | 317 XirParameter object = asm.createInputParameter("object", CiKind.Object); |
251 private XirTemplate buildExceptionObject() { | 318 XirOperand temp = asm.createRegister("temp", CiKind.Word, AMD64.rax); |
252 XirOperand result = asm.restart(CiKind.Object); | 319 |
253 XirOperand thread = asm.createRegister("thread", CiKind.Word, AMD64.r15); | 320 if (is(NULL_CHECK, flags)) { |
254 | 321 asm.nop(1); |
255 asm.pload(CiKind.Object, result, thread, asm.i(config.threadExceptionOopOffset), false); | 322 asm.mark(MARK_IMPLICIT_NULL); |
256 asm.pstore(CiKind.Object, thread, asm.i(config.threadExceptionOopOffset), asm.o(null), false); | 323 asm.pload(CiKind.Word, temp, object, true); |
257 asm.pstore(CiKind.Long, thread, asm.i(config.threadExceptionPcOffset), asm.l(0), false); | 324 } |
258 | 325 |
259 return asm.finishTemplate("exception object"); | 326 return asm.finishTemplate("monitorExit"); |
260 } | 327 } |
261 | 328 }; |
262 private XirTemplate buildSafepoint() { | 329 |
263 asm.restart(CiKind.Void); | 330 private KindTemplates getFieldTemplates = new KindTemplates(NULL_CHECK, UNRESOLVED) { |
264 | 331 |
265 // TODO safepoint | 332 @Override |
266 | 333 protected XirTemplate create(CiXirAssembler asm, long flags, CiKind kind) { |
267 return asm.finishTemplate("safepoint"); | |
268 } | |
269 | |
270 private XirPair buildGetFieldTemplate(CiKind kind) { | |
271 final XirTemplate resolved; | |
272 final XirTemplate unresolved; | |
273 { | |
274 // resolved case | |
275 XirOperand result = asm.restart(kind); | 334 XirOperand result = asm.restart(kind); |
276 XirParameter object = asm.createInputParameter("object", CiKind.Object); | 335 XirParameter object = asm.createInputParameter("object", CiKind.Object); |
336 | |
337 if (is(UNRESOLVED, flags)) { | |
338 UnresolvedFieldPatching fieldPatching = new UnresolvedFieldPatching(asm, object, result, false, is(NULL_CHECK, flags), config); | |
339 fieldPatching.emitInline(); | |
340 // -- out of line ------------------------------------------------------- | |
341 fieldPatching.emitOutOfLine(); | |
342 return asm.finishTemplate("getfield<" + kind + ">"); | |
343 } | |
277 XirParameter fieldOffset = asm.createConstantInputParameter("fieldOffset", CiKind.Int); | 344 XirParameter fieldOffset = asm.createConstantInputParameter("fieldOffset", CiKind.Int); |
278 asm.nop(1); | 345 if (is(NULL_CHECK, flags)) { |
279 asm.mark(MARK_IMPLICIT_NULL); | 346 asm.nop(1); |
280 asm.pload(kind, result, object, fieldOffset, true); | 347 asm.mark(MARK_IMPLICIT_NULL); |
281 resolved = asm.finishTemplate("getfield<" + kind + ">"); | 348 } |
282 } | 349 asm.pload(kind, result, object, fieldOffset, is(NULL_CHECK, flags)); |
283 unresolved = null; | 350 return asm.finishTemplate("getfield<" + kind + ">"); |
284 return new XirPair(resolved, unresolved); | 351 } |
285 } | 352 }; |
286 | 353 |
287 private XirPair buildPutFieldTemplate(CiKind kind, boolean genWriteBarrier) { | 354 private KindTemplates putFieldTemplates = new KindTemplates(WRITE_BARRIER, NULL_CHECK, UNRESOLVED) { |
288 final XirTemplate resolved; | 355 |
289 final XirTemplate unresolved; | 356 @Override |
290 { | 357 protected XirTemplate create(CiXirAssembler asm, long flags, CiKind kind) { |
291 // resolved case | |
292 asm.restart(CiKind.Void); | 358 asm.restart(CiKind.Void); |
293 XirParameter object = asm.createInputParameter("object", CiKind.Object); | 359 XirParameter object = asm.createInputParameter("object", CiKind.Object); |
294 XirParameter value = asm.createInputParameter("value", kind); | 360 XirParameter value = asm.createInputParameter("value", kind); |
361 | |
362 if (is(UNRESOLVED, flags)) { | |
363 UnresolvedFieldPatching fieldPatching = new UnresolvedFieldPatching(asm, object, value, false, is(NULL_CHECK, flags), config); | |
364 fieldPatching.emitInline(); | |
365 // -- out of line ------------------------------------------------------- | |
366 fieldPatching.emitOutOfLine(); | |
367 return asm.finishTemplate("putfield<" + kind + ">"); | |
368 } | |
295 XirParameter fieldOffset = asm.createConstantInputParameter("fieldOffset", CiKind.Int); | 369 XirParameter fieldOffset = asm.createConstantInputParameter("fieldOffset", CiKind.Int); |
296 asm.nop(1); | 370 if (is(NULL_CHECK, flags)) { |
297 asm.mark(MARK_IMPLICIT_NULL); | 371 asm.nop(1); |
298 asm.pstore(kind, object, fieldOffset, value, true); | 372 asm.mark(MARK_IMPLICIT_NULL); |
299 if (genWriteBarrier) { | 373 } |
300 // TODO write barrier | 374 asm.pstore(kind, object, fieldOffset, value, is(NULL_CHECK, flags)); |
301 // addWriteBarrier(asm, object, value); | 375 if (is(WRITE_BARRIER, flags)) { |
302 } | 376 writeBarrier(asm, object); |
303 resolved = asm.finishTemplate("putfield<" + kind + ", " + genWriteBarrier + ">"); | 377 } |
304 } | 378 return asm.finishTemplate("putfield<" + kind + ">"); |
305 unresolved = null; | 379 } |
306 return new XirPair(resolved, unresolved); | 380 }; |
307 } | 381 |
308 | 382 private final IndexTemplates newInstanceTemplates = new IndexTemplates() { |
309 private XirPair buildGetStaticTemplate(CiKind kind) { | 383 |
310 final XirTemplate resolved; | 384 @Override |
311 final XirTemplate unresolved; | 385 protected XirTemplate create(CiXirAssembler asm, long flags, int size) { |
312 { | 386 XirOperand result = asm.restart(CiKind.Word); |
313 // resolved case | 387 XirOperand type = asm.createInputParameter("type", CiKind.Object); |
314 XirOperand result = asm.restart(kind); | 388 |
389 XirOperand thread = asm.createRegister("thread", CiKind.Word, AMD64.r15); | |
390 XirOperand temp1 = asm.createRegister("temp1", CiKind.Word, AMD64.rcx); | |
391 XirOperand temp2 = asm.createRegister("temp2", CiKind.Word, AMD64.rbx); | |
392 XirOperand temp2i = asm.createRegister("temp2i", CiKind.Word, AMD64.rbx); | |
393 useRegisters(asm, AMD64.rsi); | |
394 XirLabel tlabFull = asm.createOutOfLineLabel("tlab full"); | |
395 XirLabel resume = asm.createInlineLabel("resume"); | |
396 | |
397 // check if the class is already initialized | |
398 asm.pload(CiKind.Int, temp2i, type, asm.i(config.klassStateOffset), false); | |
399 asm.jneq(tlabFull, temp2i, asm.i(config.klassStateFullyInitialized)); | |
400 | |
401 asm.pload(CiKind.Word, result, thread, asm.i(config.threadTlabTopOffset), false); | |
402 asm.add(temp1, result, asm.w(size)); | |
403 asm.pload(CiKind.Word, temp2, thread, asm.i(config.threadTlabEndOffset), false); | |
404 | |
405 asm.jgt(tlabFull, temp1, temp2); | |
406 asm.pstore(CiKind.Word, thread, asm.i(config.threadTlabTopOffset), temp1, false); | |
407 asm.bindInline(resume); | |
408 | |
409 asm.pload(CiKind.Word, temp1, type, asm.i(config.instanceHeaderPrototypeOffset), false); | |
410 asm.pstore(CiKind.Word, result, temp1, false); | |
411 asm.pstore(CiKind.Object, result, asm.i(config.hubOffset), type, false); | |
412 | |
413 if (size > 2 * target.wordSize) { | |
414 asm.mov(temp1, asm.w(0)); | |
415 for (int offset = 2 * target.wordSize; offset < size; offset += target.wordSize) { | |
416 asm.pstore(CiKind.Word, result, asm.i(offset), temp1, false); | |
417 } | |
418 } | |
419 | |
420 // -- out of line ------------------------------------------------------- | |
421 asm.bindOutOfLine(tlabFull); | |
422 XirOperand arg = asm.createRegister("runtime call argument", CiKind.Object, AMD64.rdx); | |
423 asm.mov(arg, type); | |
424 asm.callRuntime(config.newInstanceStub, result); | |
425 asm.jmp(resume); | |
426 | |
427 return asm.finishTemplate("new instance"); | |
428 } | |
429 }; | |
430 | |
431 private SimpleTemplates newInstanceUnresolvedTemplates = new SimpleTemplates() { | |
432 | |
433 @Override | |
434 protected XirTemplate create(CiXirAssembler asm, long flags) { | |
435 XirOperand result = asm.restart(CiKind.Word); | |
436 XirOperand arg = asm.createRegister("runtime call argument", CiKind.Object, AMD64.rdx); | |
437 | |
438 UnresolvedClassPatching patching = new UnresolvedClassPatching(asm, arg, config); | |
439 | |
440 patching.emitInline(); | |
441 useRegisters(asm, AMD64.rbx, AMD64.rcx, AMD64.rsi); | |
442 asm.callRuntime(config.unresolvedNewInstanceStub, result); | |
443 | |
444 // -- out of line ------------------------------------------------------- | |
445 patching.emitOutOfLine(); | |
446 | |
447 return asm.finishTemplate("new instance"); | |
448 } | |
449 }; | |
450 | |
451 private SimpleTemplates newObjectArrayTemplates = new SimpleTemplates(UNRESOLVED) { | |
452 | |
453 @Override | |
454 protected XirTemplate create(CiXirAssembler asm, long flags) { | |
455 XirOperand result = asm.restart(CiKind.Object); | |
456 | |
457 XirParameter lengthParam = asm.createInputParameter("length", CiKind.Int); | |
458 | |
459 XirOperand length = asm.createRegister("length", CiKind.Int, AMD64.rbx); | |
460 XirOperand hub = asm.createRegister("hub", CiKind.Object, AMD64.rdx); | |
461 | |
462 UnresolvedClassPatching patching = null; | |
463 if (is(UNRESOLVED, flags)) { | |
464 // insert the patching code for class resolving - the hub will end up in "hub" | |
465 patching = new UnresolvedClassPatching(asm, hub, config); | |
466 patching.emitInline(); | |
467 } else { | |
468 asm.mov(hub, asm.createConstantInputParameter("hub", CiKind.Object)); | |
469 } | |
470 | |
471 asm.mov(length, lengthParam); | |
472 useRegisters(asm, AMD64.rax, AMD64.rsi, AMD64.rcx, AMD64.rdi); | |
473 asm.callRuntime(config.newObjectArrayStub, result); | |
474 if (is(UNRESOLVED, flags)) { | |
475 patching.emitOutOfLine(); | |
476 } | |
477 return asm.finishTemplate(is(UNRESOLVED, flags) ? "newObjectArray (unresolved)" : "newObjectArray"); | |
478 } | |
479 }; | |
480 | |
481 private SimpleTemplates newTypeArrayTemplates = new SimpleTemplates() { | |
482 | |
483 @Override | |
484 protected XirTemplate create(CiXirAssembler asm, long flags) { | |
485 XirOperand result = asm.restart(CiKind.Object); | |
486 | |
487 XirParameter lengthParam = asm.createInputParameter("length", CiKind.Int); | |
488 XirParameter hubParam = asm.createConstantInputParameter("hub", CiKind.Object); | |
489 | |
490 XirOperand length = asm.createRegister("length", CiKind.Int, AMD64.rbx); | |
491 XirOperand hub = asm.createRegister("hub", CiKind.Object, AMD64.rdx); | |
492 | |
493 asm.mov(hub, hubParam); | |
494 asm.mov(length, lengthParam); | |
495 useRegisters(asm, AMD64.rax, AMD64.rsi, AMD64.rcx, AMD64.rdi); | |
496 asm.callRuntime(config.newTypeArrayStub, result); | |
497 | |
498 return asm.finishTemplate("newTypeArray"); | |
499 } | |
500 }; | |
501 | |
502 private final IndexTemplates multiNewArrayTemplate = new IndexTemplates(UNRESOLVED) { | |
503 | |
504 @Override | |
505 protected XirTemplate create(CiXirAssembler asm, long flags, int dimensions) { | |
506 XirOperand result = asm.restart(CiKind.Object); | |
507 | |
508 XirOperand hub = asm.createRegister("hub", CiKind.Object, AMD64.rax); | |
509 XirOperand rank = asm.createRegister("rank", CiKind.Int, AMD64.rbx); | |
510 XirOperand sizes = asm.createRegister("sizes", CiKind.Long, AMD64.rcx); | |
511 XirOperand thread = asm.createRegister("thread", CiKind.Long, AMD64.r15); | |
512 asm.add(sizes, thread, asm.l(config.threadMultiNewArrayStorage)); | |
513 for (int i = 0; i < dimensions; i++) { | |
514 XirParameter length = asm.createInputParameter("length" + i, CiKind.Int); | |
515 asm.pstore(CiKind.Int, sizes, asm.i(i * target.sizeInBytes(CiKind.Int)), length, false); | |
516 } | |
517 | |
518 UnresolvedClassPatching patching = null; | |
519 if (is(UNRESOLVED, flags)) { | |
520 // insert the patching code for class resolving - the hub will end up in "hub" | |
521 patching = new UnresolvedClassPatching(asm, hub, config); | |
522 patching.emitInline(); | |
523 } else { | |
524 asm.mov(hub, asm.createConstantInputParameter("hub", CiKind.Object)); | |
525 } | |
526 | |
527 asm.mov(rank, asm.i(dimensions)); | |
528 asm.callRuntime(config.newMultiArrayStub, result); | |
529 if (is(UNRESOLVED, flags)) { | |
530 patching.emitOutOfLine(); | |
531 } | |
532 return asm.finishTemplate(is(UNRESOLVED, flags) ? "multiNewArray" + dimensions + " (unresolved)" : "multiNewArray" + dimensions); | |
533 } | |
534 }; | |
535 | |
536 private SimpleTemplates checkCastTemplates = new SimpleTemplates(NULL_CHECK, UNRESOLVED) { | |
537 | |
538 @Override | |
539 protected XirTemplate create(CiXirAssembler asm, long flags) { | |
540 asm.restart(); | |
315 XirParameter object = asm.createInputParameter("object", CiKind.Object); | 541 XirParameter object = asm.createInputParameter("object", CiKind.Object); |
316 XirParameter fieldOffset = asm.createConstantInputParameter("fieldOffset", CiKind.Int); | 542 final XirOperand hub; |
317 asm.nop(1); | 543 final UnresolvedClassPatching patching; |
318 asm.mark(MARK_IMPLICIT_NULL); | 544 if (is(UNRESOLVED, flags)) { |
319 asm.pload(kind, result, object, fieldOffset, true); | 545 hub = asm.createTemp("hub", CiKind.Object); |
320 resolved = asm.finishTemplate("getfield<" + kind + ">"); | 546 // insert the patching code for class resolving - the hub will end up in "hub" |
321 } | 547 patching = new UnresolvedClassPatching(asm, hub, config); |
322 unresolved = null; | 548 patching.emitInline(); |
323 return new XirPair(resolved, unresolved); | 549 } else { |
324 } | 550 hub = asm.createConstantInputParameter("hub", CiKind.Object); |
325 | 551 patching = null; |
326 private XirPair buildPutStaticTemplate(CiKind kind, boolean genWriteBarrier) { | 552 } |
327 final XirTemplate resolved; | 553 |
328 final XirTemplate unresolved; | |
329 { | |
330 // resolved case | |
331 asm.restart(CiKind.Void); | |
332 XirParameter object = asm.createInputParameter("object", CiKind.Object); | |
333 XirParameter value = asm.createInputParameter("value", kind); | |
334 XirParameter fieldOffset = asm.createConstantInputParameter("fieldOffset", CiKind.Int); | |
335 asm.nop(1); | |
336 asm.mark(MARK_IMPLICIT_NULL); | |
337 asm.pstore(kind, object, fieldOffset, value, true); | |
338 if (genWriteBarrier) { | |
339 // TODO write barrier | |
340 // addWriteBarrier(asm, object, value); | |
341 } | |
342 resolved = asm.finishTemplate("putfield<" + kind + ", " + genWriteBarrier + ">"); | |
343 } | |
344 unresolved = null; | |
345 return new XirPair(resolved, unresolved); | |
346 } | |
347 | |
348 private XirPair buildInstanceof(boolean nonnull) { | |
349 final XirTemplate resolved; | |
350 final XirTemplate unresolved; | |
351 { | |
352 XirOperand result = asm.restart(CiKind.Boolean); | |
353 | |
354 XirParameter object = asm.createInputParameter("object", CiKind.Object); | |
355 XirParameter hub = asm.createConstantInputParameter("hub", CiKind.Object); | |
356 XirOperand objHub = asm.createTemp("objHub", CiKind.Object); | 554 XirOperand objHub = asm.createTemp("objHub", CiKind.Object); |
357 | 555 |
358 XirLabel end = asm.createInlineLabel("end"); | 556 XirLabel end = asm.createInlineLabel("end"); |
359 XirLabel slow_path = asm.createOutOfLineLabel("slow path"); | 557 XirLabel slow_path = asm.createOutOfLineLabel("slow path"); |
360 | 558 |
361 if (!nonnull) { | 559 if (is(NULL_CHECK, flags)) { |
560 // null can be cast to anything | |
561 asm.jeq(end, object, asm.o(null)); | |
562 } | |
563 | |
564 asm.pload(CiKind.Object, objHub, object, asm.i(config.hubOffset), false); | |
565 // if we get an exact match: succeed immediately | |
566 asm.jneq(slow_path, objHub, hub); | |
567 asm.bindInline(end); | |
568 | |
569 // -- out of line ------------------------------------------------------- | |
570 asm.bindOutOfLine(slow_path); | |
571 checkSubtype(asm, objHub, objHub, hub); | |
572 asm.jneq(end, objHub, asm.o(null)); | |
573 XirOperand scratch = asm.createRegister("scratch", CiKind.Object, AMD64.r10); | |
574 asm.mov(scratch, object); | |
575 asm.callRuntime(config.throwClassCastException, null); | |
576 asm.shouldNotReachHere(); | |
577 | |
578 if (is(UNRESOLVED, flags)) { | |
579 patching.emitOutOfLine(); | |
580 } | |
581 | |
582 return asm.finishTemplate(object, "instanceof"); | |
583 } | |
584 }; | |
585 | |
586 private SimpleTemplates instanceOfTemplates = new SimpleTemplates(NULL_CHECK, UNRESOLVED) { | |
587 | |
588 @Override | |
589 protected XirTemplate create(CiXirAssembler asm, long flags) { | |
590 XirOperand result = asm.restart(CiKind.Boolean); | |
591 XirParameter object = asm.createInputParameter("object", CiKind.Object); | |
592 final XirOperand hub; | |
593 final UnresolvedClassPatching patching; | |
594 if (is(UNRESOLVED, flags)) { | |
595 hub = asm.createTemp("hub", CiKind.Object); | |
596 // insert the patching code for class resolving - the hub will end up in "hub" | |
597 patching = new UnresolvedClassPatching(asm, hub, config); | |
598 patching.emitInline(); | |
599 } else { | |
600 hub = asm.createConstantInputParameter("hub", CiKind.Object); | |
601 patching = null; | |
602 } | |
603 | |
604 XirOperand objHub = asm.createTemp("objHub", CiKind.Object); | |
605 | |
606 XirLabel end = asm.createInlineLabel("end"); | |
607 XirLabel slow_path = asm.createOutOfLineLabel("slow path"); | |
608 | |
609 if (is(NULL_CHECK, flags)) { | |
362 // null isn't "instanceof" anything | 610 // null isn't "instanceof" anything |
363 asm.mov(result, asm.b(false)); | 611 asm.mov(result, asm.b(false)); |
364 asm.jeq(end, object, asm.o(null)); | 612 asm.jeq(end, object, asm.o(null)); |
365 } | 613 } |
614 | |
366 asm.pload(CiKind.Object, objHub, object, asm.i(config.hubOffset), false); | 615 asm.pload(CiKind.Object, objHub, object, asm.i(config.hubOffset), false); |
367 // if we get an exact match: succeed immediately | 616 // if we get an exact match: succeed immediately |
368 asm.mov(result, asm.b(true)); | 617 asm.mov(result, asm.b(true)); |
369 asm.jneq(slow_path, objHub, hub); | 618 asm.jneq(slow_path, objHub, hub); |
370 asm.bindInline(end); | 619 asm.bindInline(end); |
371 | 620 |
372 // -- out of line ------------------------------------------------------- | 621 // -- out of line ------------------------------------------------------- |
373 asm.bindOutOfLine(slow_path); | 622 asm.bindOutOfLine(slow_path); |
374 checkSubtype(result, objHub, hub); | 623 checkSubtype(asm, result, objHub, hub); |
375 asm.jmp(end); | 624 asm.jmp(end); |
376 | 625 |
377 resolved = asm.finishTemplate("instanceof-leaf<" + nonnull + ">"); | 626 if (is(UNRESOLVED, flags)) { |
378 } | 627 patching.emitOutOfLine(); |
379 { | 628 } |
380 XirOperand result = asm.restart(CiKind.Boolean); | 629 |
381 | 630 return asm.finishTemplate("instanceof"); |
382 XirParameter object = asm.createInputParameter("object", CiKind.Object); | 631 } |
383 XirOperand hub = asm.createTemp("hub", CiKind.Object); | 632 }; |
384 XirOperand objHub = asm.createTemp("objHub", CiKind.Object); | 633 |
385 | 634 private KindTemplates arrayLoadTemplates = new KindTemplates(NULL_CHECK, READ_BARRIER, BOUNDS_CHECK, GIVEN_LENGTH) { |
386 XirLabel end = asm.createInlineLabel("end"); | 635 |
387 XirLabel slow_path = asm.createOutOfLineLabel("slow path"); | 636 @Override |
388 | 637 protected XirTemplate create(CiXirAssembler asm, long flags, CiKind kind) { |
389 // insert the patching code for class resolving - the hub will end up in "hub" | 638 XirOperand result = asm.restart(kind); |
390 UnresolvedClassPatching patching = new UnresolvedClassPatching(asm, hub, config); | 639 XirParameter array = asm.createInputParameter("array", CiKind.Object); |
391 patching.emitInline(); | 640 XirParameter index = asm.createInputParameter("index", CiKind.Int); |
392 | 641 XirLabel failBoundsCheck = null; |
393 if (!nonnull) { | 642 // if the length is known the array cannot be null |
394 // null isn't "instanceof" anything | 643 boolean implicitNullException = is(NULL_CHECK, flags); |
395 asm.mov(result, asm.b(false)); | 644 |
396 asm.jeq(end, object, asm.o(null)); | 645 if (is(BOUNDS_CHECK, flags)) { |
397 } | 646 // load the array length and check the index |
398 asm.pload(CiKind.Object, objHub, object, asm.i(config.hubOffset), false); | 647 failBoundsCheck = asm.createOutOfLineLabel("failBoundsCheck"); |
399 // if we get an exact match: succeed immediately | 648 XirOperand length; |
400 asm.mov(result, asm.b(true)); | 649 if (is(GIVEN_LENGTH, flags)) { |
401 asm.jneq(slow_path, objHub, hub); | 650 length = asm.createInputParameter("length", CiKind.Int); |
402 asm.bindInline(end); | 651 } else { |
403 | 652 length = asm.createTemp("length", CiKind.Int); |
404 // -- out of line ------------------------------------------------------- | 653 if (implicitNullException) { |
405 asm.bindOutOfLine(slow_path); | 654 asm.nop(1); |
406 checkSubtype(result, objHub, hub); | 655 asm.mark(MARK_IMPLICIT_NULL); |
407 asm.jmp(end); | 656 } |
408 | 657 asm.pload(CiKind.Int, length, array, asm.i(config.arrayLengthOffset), implicitNullException); |
409 patching.emitOutOfLine(); | 658 implicitNullException = false; |
410 | 659 } |
411 unresolved = asm.finishTemplate("instanceof-leaf<" + nonnull + ">"); | 660 asm.jugteq(failBoundsCheck, index, length); |
412 } | 661 implicitNullException = false; |
413 return new XirPair(resolved, unresolved); | 662 } |
414 } | 663 int elemSize = target.sizeInBytes(kind); |
415 | 664 if (implicitNullException) { |
416 private XirPair buildCheckCast() { | |
417 final XirTemplate resolved; | |
418 final XirTemplate unresolved; | |
419 { | |
420 asm.restart(); | |
421 | |
422 XirParameter object = asm.createInputParameter("object", CiKind.Object); | |
423 XirParameter hub = asm.createConstantInputParameter("hub", CiKind.Object); | |
424 XirOperand objHub = asm.createTemp("objHub", CiKind.Object); | |
425 | |
426 XirLabel end = asm.createInlineLabel("end"); | |
427 XirLabel slow_path = asm.createOutOfLineLabel("slow path"); | |
428 | |
429 // null can be cast to anything | |
430 asm.jeq(end, object, asm.o(null)); | |
431 | |
432 asm.pload(CiKind.Object, objHub, object, asm.i(config.hubOffset), false); | |
433 // if we get an exact match: succeed immediately | |
434 asm.jneq(slow_path, objHub, hub); | |
435 asm.bindInline(end); | |
436 | |
437 // -- out of line ------------------------------------------------------- | |
438 asm.bindOutOfLine(slow_path); | |
439 checkSubtype(objHub, objHub, hub); | |
440 asm.jneq(end, objHub, asm.o(null)); | |
441 XirOperand scratch = asm.createRegister("scratch", CiKind.Object, AMD64.r10); | |
442 asm.mov(scratch, object); | |
443 asm.callRuntime(config.throwClassCastException, null); | |
444 asm.shouldNotReachHere(); | |
445 | |
446 resolved = asm.finishTemplate(object, "check cast"); | |
447 } | |
448 { | |
449 asm.restart(); | |
450 | |
451 XirParameter object = asm.createInputParameter("object", CiKind.Object); | |
452 XirOperand hub = asm.createTemp("hub", CiKind.Object); | |
453 XirOperand objHub = asm.createTemp("objHub", CiKind.Object); | |
454 | |
455 XirLabel end = asm.createInlineLabel("end"); | |
456 XirLabel slow_path = asm.createOutOfLineLabel("slow path"); | |
457 | |
458 // insert the patching code for class resolving - the hub will end up in "hub" | |
459 UnresolvedClassPatching patching = new UnresolvedClassPatching(asm, hub, config); | |
460 patching.emitInline(); | |
461 | |
462 // null can be cast to anything | |
463 asm.jeq(end, object, asm.o(null)); | |
464 | |
465 asm.pload(CiKind.Object, objHub, object, asm.i(config.hubOffset), false); | |
466 // if we get an exact match: succeed immediately | |
467 asm.jneq(slow_path, objHub, hub); | |
468 asm.bindInline(end); | |
469 | |
470 // -- out of line ------------------------------------------------------- | |
471 asm.bindOutOfLine(slow_path); | |
472 checkSubtype(objHub, objHub, hub); | |
473 asm.jneq(end, objHub, asm.o(null)); | |
474 XirOperand scratch = asm.createRegister("scratch", CiKind.Object, AMD64.r10); | |
475 asm.mov(scratch, object); | |
476 asm.callRuntime(config.throwClassCastException, null); | |
477 asm.shouldNotReachHere(); | |
478 | |
479 patching.emitOutOfLine(); | |
480 | |
481 unresolved = asm.finishTemplate(object, "check cast"); | |
482 } | |
483 return new XirPair(resolved, unresolved); | |
484 } | |
485 | |
486 private XirTemplate buildArrayStore(CiKind kind, CiXirAssembler asm, boolean genBoundsCheck, boolean genStoreCheck, boolean genWriteBarrier, boolean withLength) { | |
487 asm.restart(CiKind.Void); | |
488 XirParameter array = asm.createInputParameter("array", CiKind.Object); | |
489 XirParameter index = asm.createInputParameter("index", CiKind.Int); | |
490 XirParameter value = asm.createInputParameter("value", kind); | |
491 XirOperand temp = asm.createTemp("temp", CiKind.Word); | |
492 XirOperand valueHub = null; | |
493 XirOperand compHub = null; | |
494 XirLabel store = asm.createInlineLabel("store"); | |
495 XirLabel failBoundsCheck = null; | |
496 XirLabel slowStoreCheck = null; | |
497 // if the length is known the array cannot be null | |
498 boolean implicitNullException = !withLength; | |
499 | |
500 if (genBoundsCheck) { | |
501 // load the array length and check the index | |
502 failBoundsCheck = asm.createOutOfLineLabel("failBoundsCheck"); | |
503 XirOperand length; | |
504 if (withLength) { | |
505 length = asm.createInputParameter("length", CiKind.Int); | |
506 } else { | |
507 length = asm.createTemp("length", CiKind.Int); | |
508 asm.nop(1); | 665 asm.nop(1); |
509 asm.mark(MARK_IMPLICIT_NULL); | 666 asm.mark(MARK_IMPLICIT_NULL); |
510 asm.pload(CiKind.Int, length, array, asm.i(config.arrayLengthOffset), true); | 667 } |
668 asm.pload(kind, result, array, index, config.getArrayOffset(kind), Scale.fromInt(elemSize), implicitNullException); | |
669 if (is(BOUNDS_CHECK, flags)) { | |
670 asm.bindOutOfLine(failBoundsCheck); | |
671 asm.callRuntime(config.throwArrayIndexException, null); | |
672 asm.shouldNotReachHere(); | |
673 } | |
674 return asm.finishTemplate("arrayload<" + kind + ">"); | |
675 } | |
676 }; | |
677 | |
678 private KindTemplates arrayStoreTemplates = new KindTemplates(NULL_CHECK, WRITE_BARRIER, BOUNDS_CHECK, STORE_CHECK, GIVEN_LENGTH) { | |
679 | |
680 @Override | |
681 protected XirTemplate create(CiXirAssembler asm, long flags, CiKind kind) { | |
682 asm.restart(CiKind.Void); | |
683 XirParameter array = asm.createInputParameter("array", CiKind.Object); | |
684 XirParameter index = asm.createInputParameter("index", CiKind.Int); | |
685 XirParameter value = asm.createInputParameter("value", kind); | |
686 XirOperand temp = asm.createTemp("temp", CiKind.Word); | |
687 XirOperand valueHub = null; | |
688 XirOperand compHub = null; | |
689 XirLabel store = asm.createInlineLabel("store"); | |
690 XirLabel failBoundsCheck = null; | |
691 XirLabel slowStoreCheck = null; | |
692 // if the length is known the array cannot be null | |
693 boolean implicitNullException = is(NULL_CHECK, flags); | |
694 | |
695 if (is(BOUNDS_CHECK, flags)) { | |
696 // load the array length and check the index | |
697 failBoundsCheck = asm.createOutOfLineLabel("failBoundsCheck"); | |
698 XirOperand length; | |
699 if (is(GIVEN_LENGTH, flags)) { | |
700 length = asm.createInputParameter("length", CiKind.Int); | |
701 } else { | |
702 length = asm.createTemp("length", CiKind.Int); | |
703 if (implicitNullException) { | |
704 asm.nop(1); | |
705 asm.mark(MARK_IMPLICIT_NULL); | |
706 } | |
707 asm.pload(CiKind.Int, length, array, asm.i(config.arrayLengthOffset), implicitNullException); | |
708 implicitNullException = false; | |
709 } | |
710 asm.jugteq(failBoundsCheck, index, length); | |
711 | |
712 } | |
713 if (is(STORE_CHECK, flags) && kind == CiKind.Object) { | |
714 slowStoreCheck = asm.createOutOfLineLabel("slowStoreCheck"); | |
715 asm.jeq(store, value, asm.o(null)); // first check if value is null | |
716 valueHub = asm.createTemp("valueHub", CiKind.Object); | |
717 compHub = asm.createTemp("compHub", CiKind.Object); | |
718 if (implicitNullException) { | |
719 asm.mark(MARK_IMPLICIT_NULL); | |
720 } | |
721 asm.pload(CiKind.Object, compHub, array, asm.i(config.hubOffset), implicitNullException); | |
722 asm.pload(CiKind.Object, compHub, compHub, asm.i(config.arrayClassElementOffset), false); | |
723 asm.pload(CiKind.Object, valueHub, value, asm.i(config.hubOffset), false); | |
724 asm.jneq(slowStoreCheck, compHub, valueHub); // then check component hub matches value hub | |
725 | |
511 implicitNullException = false; | 726 implicitNullException = false; |
512 } | 727 } |
513 asm.jugteq(failBoundsCheck, index, length); | 728 asm.bindInline(store); |
514 | 729 int elemSize = target.sizeInBytes(kind); |
515 } | 730 |
516 if (genStoreCheck) { | |
517 slowStoreCheck = asm.createOutOfLineLabel("slowStoreCheck"); | |
518 asm.jeq(store, value, asm.o(null)); // first check if value is null | |
519 valueHub = asm.createTemp("valueHub", CiKind.Object); | |
520 compHub = asm.createTemp("compHub", CiKind.Object); | |
521 if (implicitNullException) { | 731 if (implicitNullException) { |
522 asm.mark(MARK_IMPLICIT_NULL); | 732 asm.mark(MARK_IMPLICIT_NULL); |
523 } | 733 } |
524 asm.pload(CiKind.Object, compHub, array, asm.i(config.hubOffset), implicitNullException); | 734 asm.pstore(kind, array, index, value, config.getArrayOffset(kind), Scale.fromInt(elemSize), implicitNullException); |
525 asm.pload(CiKind.Object, compHub, compHub, asm.i(config.arrayClassElementOffset), false); | 735 if (is(WRITE_BARRIER, flags)) { |
526 asm.pload(CiKind.Object, valueHub, value, asm.i(config.hubOffset), false); | 736 writeBarrier(asm, array); |
527 asm.jneq(slowStoreCheck, compHub, valueHub); // then check component hub matches value hub | 737 } |
528 | 738 |
529 implicitNullException = false; | 739 // -- out of line ------------------------------------------------------- |
530 } | 740 if (is(BOUNDS_CHECK, flags)) { |
531 asm.bindInline(store); | 741 asm.bindOutOfLine(failBoundsCheck); |
532 int elemSize = target.sizeInBytes(kind); | 742 asm.callRuntime(config.throwArrayIndexException, null); |
533 | 743 asm.shouldNotReachHere(); |
534 if (implicitNullException) { | 744 } |
535 asm.mark(MARK_IMPLICIT_NULL); | 745 if (is(STORE_CHECK, flags) && kind == CiKind.Object) { |
536 } | 746 useRegisters(asm, AMD64.rax); |
537 asm.pstore(kind, array, index, value, config.getArrayOffset(kind), Scale.fromInt(elemSize), implicitNullException); | 747 asm.bindOutOfLine(slowStoreCheck); |
538 if (genWriteBarrier) { | 748 checkSubtype(asm, temp, valueHub, compHub); |
539 // addWriteBarrier(asm, array, value); | 749 asm.jneq(store, temp, asm.w(0)); |
540 } | 750 asm.callRuntime(config.throwArrayStoreException, null); |
541 | 751 asm.jmp(store); |
542 // -- out of line ------------------------------------------------------- | 752 } |
543 if (genBoundsCheck) { | 753 return asm.finishTemplate("arraystore<" + kind + ">"); |
544 asm.bindOutOfLine(failBoundsCheck); | 754 } |
545 asm.callRuntime(config.throwArrayIndexException, null); | 755 }; |
546 asm.shouldNotReachHere(); | 756 |
547 } | 757 private SimpleTemplates arrayLengthTemplates = new SimpleTemplates(NULL_CHECK) { |
548 if (genStoreCheck) { | 758 |
549 asm.bindOutOfLine(slowStoreCheck); | 759 @Override |
550 checkSubtype(temp, valueHub, compHub); | 760 protected XirTemplate create(CiXirAssembler asm, long flags) { |
551 asm.jneq(store, temp, asm.w(0)); | 761 XirOperand result = asm.restart(CiKind.Int); |
552 asm.callRuntime(config.throwArrayStoreException, null); | 762 XirParameter object = asm.createInputParameter("object", CiKind.Object); |
553 asm.jmp(store); | 763 if (is(NULL_CHECK, flags)) { |
554 } | |
555 return asm.finishTemplate("arraystore<" + kind + ">"); | |
556 } | |
557 | |
558 private XirTemplate buildArrayLoad(CiKind kind, CiXirAssembler asm, boolean genBoundsCheck, boolean withLength) { | |
559 XirOperand result = asm.restart(kind); | |
560 XirParameter array = asm.createInputParameter("array", CiKind.Object); | |
561 XirParameter index = asm.createInputParameter("index", CiKind.Int); | |
562 XirLabel failBoundsCheck = null; | |
563 // if the length is known the array cannot be null | |
564 boolean implicitNullException = !withLength; | |
565 | |
566 if (genBoundsCheck) { | |
567 // load the array length and check the index | |
568 failBoundsCheck = asm.createOutOfLineLabel("failBoundsCheck"); | |
569 XirOperand length; | |
570 if (withLength) { | |
571 length = asm.createInputParameter("length", CiKind.Int); | |
572 } else { | |
573 length = asm.createTemp("length", CiKind.Int); | |
574 asm.nop(1); | 764 asm.nop(1); |
575 asm.mark(MARK_IMPLICIT_NULL); | 765 asm.mark(MARK_IMPLICIT_NULL); |
576 asm.pload(CiKind.Int, length, array, asm.i(config.arrayLengthOffset), true); | 766 } |
577 implicitNullException = false; | 767 asm.pload(CiKind.Int, result, object, asm.i(config.arrayLengthOffset), true); |
578 } | 768 return asm.finishTemplate("arrayLength"); |
579 asm.jugteq(failBoundsCheck, index, length); | 769 } |
580 implicitNullException = false; | 770 }; |
581 } | |
582 int elemSize = target.sizeInBytes(kind); | |
583 if (implicitNullException) { | |
584 asm.nop(1); | |
585 asm.mark(MARK_IMPLICIT_NULL); | |
586 } | |
587 asm.pload(kind, result, array, index, config.getArrayOffset(kind), Scale.fromInt(elemSize), implicitNullException); | |
588 if (genBoundsCheck) { | |
589 asm.bindOutOfLine(failBoundsCheck); | |
590 asm.callRuntime(config.throwArrayIndexException, null); | |
591 asm.shouldNotReachHere(); | |
592 } | |
593 return asm.finishTemplate("arrayload<" + kind + ">"); | |
594 } | |
595 | |
596 private XirTemplate buildInvokeStatic() { | |
597 asm.restart(); | |
598 XirParameter addr = asm.createConstantInputParameter("addr", CiKind.Word); | |
599 | |
600 XirLabel stub = asm.createOutOfLineLabel("call stub"); | |
601 asm.mark(MARK_INVOKESTATIC); | |
602 | |
603 // -- out of line ------------------------------------------------------- | |
604 asm.bindOutOfLine(stub); | |
605 XirOperand method = asm.createRegister("method", CiKind.Word, AMD64.rbx); | |
606 asm.mark(MARK_STATIC_CALL_STUB, XirMark.CALLSITE); | |
607 asm.mov(method, asm.w(0l)); | |
608 XirLabel dummy = asm.createOutOfLineLabel("dummy"); | |
609 asm.jmp(dummy); | |
610 asm.bindOutOfLine(dummy); | |
611 | |
612 return asm.finishTemplate(addr, "invokestatic"); | |
613 } | |
614 | |
615 private XirTemplate buildInvokeSpecial() { | |
616 asm.restart(); | |
617 XirParameter receiver = asm.createInputParameter("receiver", CiKind.Object); | |
618 XirParameter addr = asm.createConstantInputParameter("addr", CiKind.Word); | |
619 XirOperand temp = asm.createRegister("temp", CiKind.Word, AMD64.rax); | |
620 XirLabel stub = asm.createOutOfLineLabel("call stub"); | |
621 | |
622 asm.nop(1); | |
623 asm.mark(MARK_IMPLICIT_NULL); | |
624 asm.pload(CiKind.Word, temp, receiver, true); | |
625 asm.mark(MARK_INVOKESPECIAL); | |
626 | |
627 // -- out of line ------------------------------------------------------- | |
628 asm.bindOutOfLine(stub); | |
629 XirOperand method = asm.createRegister("method", CiKind.Word, AMD64.rbx); | |
630 asm.mark(MARK_STATIC_CALL_STUB, XirMark.CALLSITE); | |
631 asm.mov(method, asm.w(0l)); | |
632 XirLabel dummy = asm.createOutOfLineLabel("dummy"); | |
633 asm.jmp(dummy); | |
634 asm.bindOutOfLine(dummy); | |
635 | |
636 return asm.finishTemplate(addr, "invokespecial"); | |
637 } | |
638 | |
639 private XirTemplate buildInvokeInterface() { | |
640 asm.restart(); | |
641 XirParameter receiver = asm.createInputParameter("receiver", CiKind.Object); | |
642 XirParameter addr = asm.createConstantInputParameter("addr", CiKind.Word); | |
643 XirOperand method = asm.createRegister("method", CiKind.Object, AMD64.rbx); | |
644 XirOperand temp = asm.createRegister("temp", CiKind.Word, AMD64.rax); | |
645 XirLabel stub = asm.createOutOfLineLabel("call stub"); | |
646 | |
647 asm.nop(1); | |
648 asm.mark(MARK_IMPLICIT_NULL); | |
649 asm.pload(CiKind.Word, temp, receiver, true); | |
650 asm.mark(MARK_INVOKEINTERFACE); | |
651 asm.mov(method, asm.createConstant(CiConstant.forObject(HotSpotProxy.DUMMY_CONSTANT_OBJ))); | |
652 | |
653 // -- out of line ------------------------------------------------------- | |
654 asm.bindOutOfLine(stub); | |
655 asm.mark(MARK_STATIC_CALL_STUB, XirMark.CALLSITE); | |
656 asm.mov(method, asm.w(0l)); | |
657 XirLabel dummy = asm.createOutOfLineLabel("dummy"); | |
658 asm.jmp(dummy); | |
659 asm.bindOutOfLine(dummy); | |
660 | |
661 return asm.finishTemplate(addr, "invokespecial"); | |
662 } | |
663 | |
664 private XirTemplate buildInvokeVirtual() { | |
665 asm.restart(); | |
666 XirParameter receiver = asm.createInputParameter("receiver", CiKind.Object); | |
667 XirParameter addr = asm.createConstantInputParameter("addr", CiKind.Word); | |
668 XirOperand method = asm.createRegister("method", CiKind.Object, AMD64.rbx); | |
669 XirOperand temp = asm.createRegister("temp", CiKind.Word, AMD64.rax); | |
670 XirLabel stub = asm.createOutOfLineLabel("call stub"); | |
671 | |
672 asm.nop(1); | |
673 asm.mark(MARK_IMPLICIT_NULL); | |
674 asm.pload(CiKind.Word, temp, receiver, true); | |
675 asm.mark(MARK_INVOKEVIRTUAL); | |
676 asm.mov(method, asm.createConstant(CiConstant.forObject(HotSpotProxy.DUMMY_CONSTANT_OBJ))); | |
677 | |
678 // -- out of line ------------------------------------------------------- | |
679 asm.bindOutOfLine(stub); | |
680 asm.mark(MARK_STATIC_CALL_STUB, XirMark.CALLSITE); | |
681 asm.mov(method, asm.w(0l)); | |
682 XirLabel dummy = asm.createOutOfLineLabel("dummy"); | |
683 asm.jmp(dummy); | |
684 asm.bindOutOfLine(dummy); | |
685 | |
686 return asm.finishTemplate(addr, "invokespecial"); | |
687 } | |
688 | |
689 private XirTemplate buildNewInstance(CiXirAssembler asm, int size) { | |
690 XirOperand result = asm.restart(CiKind.Word); | |
691 XirOperand type = asm.createInputParameter("type", CiKind.Object); | |
692 | |
693 XirOperand thread = asm.createRegister("thread", CiKind.Word, AMD64.r15); | |
694 XirOperand temp1 = asm.createRegister("temp1", CiKind.Word, AMD64.rcx); | |
695 XirOperand temp2 = asm.createRegister("temp2", CiKind.Word, AMD64.rbx); | |
696 useRegisters(asm, AMD64.rsi); | |
697 XirLabel tlabFull = asm.createOutOfLineLabel("tlab full"); | |
698 XirLabel resume = asm.createInlineLabel("resume"); | |
699 | |
700 asm.pload(CiKind.Word, result, thread, asm.i(config.threadTlabTopOffset), false); | |
701 asm.add(temp1, result, asm.w(size)); | |
702 asm.pload(CiKind.Word, temp2, thread, asm.i(config.threadTlabEndOffset), false); | |
703 | |
704 asm.jgt(tlabFull, temp1, temp2); | |
705 asm.pstore(CiKind.Word, thread, asm.i(config.threadTlabTopOffset), temp1, false); | |
706 asm.bindInline(resume); | |
707 | |
708 asm.pload(CiKind.Word, temp1, type, asm.i(config.instanceHeaderPrototypeOffset), false); | |
709 asm.pstore(CiKind.Word, result, temp1, false); | |
710 asm.pstore(CiKind.Object, result, asm.i(config.hubOffset), type, false); | |
711 | |
712 if (size > 2 * target.wordSize) { | |
713 asm.mov(temp1, asm.w(0)); | |
714 for (int offset = 2 * target.wordSize; offset < size; offset += target.wordSize) { | |
715 asm.pstore(CiKind.Word, result, asm.i(offset), temp1, false); | |
716 } | |
717 } | |
718 | |
719 // -- out of line ------------------------------------------------------- | |
720 asm.bindOutOfLine(tlabFull); | |
721 XirOperand arg = asm.createRegister("runtime call argument", CiKind.Object, AMD64.rdx); | |
722 asm.mov(arg, type); | |
723 asm.callRuntime(config.newInstanceStub, result); | |
724 asm.jmp(resume); | |
725 | |
726 return asm.finishTemplate("new instance"); | |
727 } | |
728 | |
729 private XirTemplate buildNewInstanceUnresolved() { | |
730 XirOperand result = asm.restart(CiKind.Word); | |
731 XirOperand arg = asm.createRegister("runtime call argument", CiKind.Object, AMD64.rdx); | |
732 | |
733 UnresolvedClassPatching patching = new UnresolvedClassPatching(asm, arg, config); | |
734 | |
735 patching.emitInline(); | |
736 useRegisters(AMD64.rbx, AMD64.rcx, AMD64.rsi); | |
737 asm.callRuntime(config.newInstanceStub, result); | |
738 | |
739 // -- out of line ------------------------------------------------------- | |
740 patching.emitOutOfLine(); | |
741 | |
742 return asm.finishTemplate("new instance"); | |
743 } | |
744 | |
745 private XirTemplate buildNewObjectArray(boolean resolved) { | |
746 XirOperand result = asm.restart(CiKind.Object); | |
747 | |
748 XirParameter lengthParam = asm.createInputParameter("length", CiKind.Int); | |
749 | |
750 XirOperand length = asm.createRegister("length", CiKind.Int, AMD64.rbx); | |
751 XirOperand hub = asm.createRegister("hub", CiKind.Object, AMD64.rdx); | |
752 | |
753 UnresolvedClassPatching patching = null; | |
754 if (resolved) { | |
755 asm.mov(hub, asm.createConstantInputParameter("hub", CiKind.Object)); | |
756 } else { | |
757 // insert the patching code for class resolving - the hub will end up in "hub" | |
758 patching = new UnresolvedClassPatching(asm, hub, config); | |
759 patching.emitInline(); | |
760 } | |
761 | |
762 asm.mov(length, lengthParam); | |
763 useRegisters(AMD64.rsi, AMD64.rcx, AMD64.rdi); | |
764 asm.callRuntime(config.newObjectArrayStub, result); | |
765 if (!resolved) { | |
766 patching.emitOutOfLine(); | |
767 } | |
768 return asm.finishTemplate(resolved ? "newObjectArray" : "newObjectArray (unresolved)"); | |
769 } | |
770 | |
771 private XirTemplate buildMultiNewArray(int dimensions, boolean resolved) { | |
772 XirOperand result = asm.restart(CiKind.Object); | |
773 | |
774 XirOperand hub = asm.createRegister("hub", CiKind.Object, AMD64.rax); | |
775 XirOperand rank = asm.createRegister("rank", CiKind.Int, AMD64.rbx); | |
776 XirOperand sizes = asm.createRegister("sizes", CiKind.Long, AMD64.rcx); | |
777 XirOperand thread = asm.createRegister("thread", CiKind.Long, AMD64.r15); | |
778 asm.add(sizes, thread, asm.l(config.threadMultiNewArrayStorage)); | |
779 for (int i = 0; i < dimensions; i++) { | |
780 XirParameter length = asm.createInputParameter("length" + i, CiKind.Int); | |
781 asm.pstore(CiKind.Int, sizes, asm.i(i * target.sizeInBytes(CiKind.Int)), length, false); | |
782 } | |
783 | |
784 UnresolvedClassPatching patching = null; | |
785 if (resolved) { | |
786 asm.mov(hub, asm.createConstantInputParameter("hub", CiKind.Object)); | |
787 } else { | |
788 // insert the patching code for class resolving - the hub will end up in "hub" | |
789 patching = new UnresolvedClassPatching(asm, hub, config); | |
790 patching.emitInline(); | |
791 } | |
792 | |
793 asm.mov(rank, asm.i(dimensions)); | |
794 asm.callRuntime(config.newMultiArrayStub, result); | |
795 if (!resolved) { | |
796 patching.emitOutOfLine(); | |
797 } | |
798 return asm.finishTemplate(resolved ? "multiNewArray" + dimensions : "multiNewArray" + dimensions + " (unresolved)"); | |
799 } | |
800 | |
801 private XirTemplate buildNewTypeArray() { | |
802 XirOperand result = asm.restart(CiKind.Object); | |
803 | |
804 XirParameter lengthParam = asm.createInputParameter("length", CiKind.Int); | |
805 XirParameter hubParam = asm.createConstantInputParameter("hub", CiKind.Object); | |
806 | |
807 XirOperand length = asm.createRegister("length", CiKind.Int, AMD64.rbx); | |
808 XirOperand hub = asm.createRegister("hub", CiKind.Object, AMD64.rdx); | |
809 | |
810 asm.mov(hub, hubParam); | |
811 asm.mov(length, lengthParam); | |
812 useRegisters(AMD64.rsi, AMD64.rcx, AMD64.rdi); | |
813 asm.callRuntime(config.newTypeArrayStub, result); | |
814 | |
815 return asm.finishTemplate("newObjectArray"); | |
816 } | |
817 | |
818 private XirTemplate buildResolveClass(boolean resolved) { | |
819 XirOperand result = asm.restart(CiKind.Word); | |
820 if (resolved) { | |
821 XirOperand type = asm.createConstantInputParameter("type", CiKind.Object); | |
822 | |
823 asm.mov(result, type); | |
824 } else { | |
825 UnresolvedClassPatching patching = new UnresolvedClassPatching(asm, result, config); | |
826 patching.emitInline(); | |
827 // -- out of line ------------------------------------------------------- | |
828 patching.emitOutOfLine(); | |
829 } | |
830 return asm.finishTemplate(resolved ? "resolve class" : "resolve class (unresolved)"); | |
831 } | |
832 | |
833 @Override | |
834 public XirSnippet genArrayLength(XirSite site, XirArgument array) { | |
835 return new XirSnippet(arrayLengthTemplate, array); | |
836 } | |
837 | |
838 @Override | |
839 public XirSnippet genArrayLoad(XirSite site, XirArgument array, XirArgument index, XirArgument length, CiKind elementKind, RiType elementType) { | |
840 if (length == null) { | |
841 return new XirSnippet(arrayLoadTemplates[elementKind.ordinal()], array, index); | |
842 } | |
843 return new XirSnippet(arrayLoadTemplatesWithLength[elementKind.ordinal()], array, index, length); | |
844 } | |
845 | |
846 @Override | |
847 public XirSnippet genArrayStore(XirSite site, XirArgument array, XirArgument index, XirArgument length, XirArgument value, CiKind elementKind, RiType elementType) { | |
848 if (length == null) { | |
849 return new XirSnippet(arrayStoreTemplates[elementKind.ordinal()], array, index, value); | |
850 } | |
851 return new XirSnippet(arrayStoreTemplatesWithLength[elementKind.ordinal()], array, index, value, length); | |
852 } | |
853 | |
854 @Override | |
855 public XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiType type) { | |
856 if (type.isResolved()) { | |
857 return new XirSnippet(checkCastTemplate.resolved, receiver, hub); | |
858 } | |
859 return new XirSnippet(checkCastTemplate.unresolved, receiver); | |
860 } | |
861 | 771 |
862 @Override | 772 @Override |
863 public XirSnippet genPrologue(XirSite site, RiMethod method) { | 773 public XirSnippet genPrologue(XirSite site, RiMethod method) { |
864 boolean staticMethod = Modifier.isStatic(method.accessFlags()); | 774 boolean staticMethod = Modifier.isStatic(method.accessFlags()); |
865 return new XirSnippet(staticMethod ? staticPrologueTemplate : prologueTemplate); | 775 return new XirSnippet(staticMethod ? prologueTemplates.get(site, STATIC_METHOD) : prologueTemplates.get(site)); |
866 } | 776 } |
867 | 777 |
868 @Override | 778 @Override |
869 public XirSnippet genEpilogue(XirSite site, RiMethod method) { | 779 public XirSnippet genEpilogue(XirSite site, RiMethod method) { |
870 return new XirSnippet(epilogueTemplate); | 780 return new XirSnippet(epilogueTemplates.get(site)); |
871 } | 781 } |
872 | 782 |
873 @Override | 783 @Override |
874 public XirSnippet genGetField(XirSite site, XirArgument receiver, RiField field) { | 784 public XirSnippet genSafepoint(XirSite site) { |
875 XirPair pair = getFieldTemplates[field.kind().ordinal()]; | 785 return new XirSnippet(safepointTemplates.get(site)); |
876 if (field.isResolved()) { | 786 } |
877 return new XirSnippet(pair.resolved, receiver, XirArgument.forInt(((HotSpotField) field).offset())); | 787 |
878 } | 788 @Override |
879 return new XirSnippet(pair.unresolved, receiver); | 789 public XirSnippet genExceptionObject(XirSite site) { |
880 } | 790 return new XirSnippet(exceptionObjectTemplates.get(site)); |
881 | 791 } |
882 @Override | 792 |
883 public XirSnippet genGetStatic(XirSite site, XirArgument staticTuple, RiField field) { | 793 @Override |
884 XirPair pair = getStaticTemplates[field.kind().ordinal()]; | 794 public XirSnippet genResolveClass(XirSite site, RiType type, Representation representation) { |
885 if (field.isResolved()) { | 795 assert representation == Representation.ObjectHub : "unexpected representation: " + representation; |
886 return new XirSnippet(pair.resolved, staticTuple, XirArgument.forInt(((HotSpotField) field).offset())); | 796 if (type instanceof HotSpotTypeResolved) { |
887 } | 797 return new XirSnippet(resolveClassTemplates.get(site), XirArgument.forObject(type)); |
888 return new XirSnippet(pair.unresolved, staticTuple, null); | 798 } |
889 } | 799 return new XirSnippet(resolveClassTemplates.get(site, UNRESOLVED)); |
890 | |
891 @Override | |
892 public XirSnippet genPutField(XirSite site, XirArgument receiver, RiField field, XirArgument value) { | |
893 XirPair pair = putFieldTemplates[field.kind().ordinal()]; | |
894 if (field.isResolved()) { | |
895 return new XirSnippet(pair.resolved, receiver, value, XirArgument.forInt(((HotSpotField) field).offset())); | |
896 } | |
897 return new XirSnippet(pair.unresolved, receiver, value); | |
898 } | |
899 | |
900 @Override | |
901 public XirSnippet genPutStatic(XirSite site, XirArgument staticTuple, RiField field, XirArgument value) { | |
902 XirPair pair = putStaticTemplates[field.kind().ordinal()]; | |
903 if (field.isResolved()) { | |
904 return new XirSnippet(pair.resolved, staticTuple, value, XirArgument.forInt(((HotSpotField) field).offset())); | |
905 } | |
906 return new XirSnippet(pair.unresolved, staticTuple, value); | |
907 } | |
908 | |
909 @Override | |
910 public XirSnippet genInstanceOf(XirSite site, XirArgument receiver, XirArgument hub, RiType type) { | |
911 if (type.isResolved()) { | |
912 return new XirSnippet(instanceofTemplate.resolved, receiver, hub); | |
913 } | |
914 return new XirSnippet(instanceofTemplate.unresolved, receiver); | |
915 } | 800 } |
916 | 801 |
917 @Override | 802 @Override |
918 public XirSnippet genIntrinsic(XirSite site, XirArgument[] arguments, RiMethod method) { | 803 public XirSnippet genIntrinsic(XirSite site, XirArgument[] arguments, RiMethod method) { |
919 return null; | 804 return null; |
920 } | 805 } |
921 | 806 |
922 @Override | 807 @Override |
923 public XirSnippet genInvokeInterface(XirSite site, XirArgument receiver, RiMethod method) { | 808 public XirSnippet genInvokeInterface(XirSite site, XirArgument receiver, RiMethod method) { |
924 return new XirSnippet(invokeInterfaceTemplate, receiver, XirArgument.forWord(0)); | 809 return new XirSnippet(invokeInterfaceTemplates.get(site), receiver, XirArgument.forWord(0)); |
810 } | |
811 | |
812 @Override | |
813 public XirSnippet genInvokeVirtual(XirSite site, XirArgument receiver, RiMethod method) { | |
814 return new XirSnippet(invokeVirtualTemplates.get(site), receiver, XirArgument.forWord(0)); | |
925 } | 815 } |
926 | 816 |
927 @Override | 817 @Override |
928 public XirSnippet genInvokeSpecial(XirSite site, XirArgument receiver, RiMethod method) { | 818 public XirSnippet genInvokeSpecial(XirSite site, XirArgument receiver, RiMethod method) { |
929 return new XirSnippet(invokeSpecialTemplate, receiver, XirArgument.forWord(0)); | 819 return new XirSnippet(invokeSpecialTemplates.get(site), receiver, XirArgument.forWord(0)); |
930 } | 820 } |
931 | 821 |
932 @Override | 822 @Override |
933 public XirSnippet genInvokeStatic(XirSite site, RiMethod method) { | 823 public XirSnippet genInvokeStatic(XirSite site, RiMethod method) { |
934 return new XirSnippet(invokeStaticTemplate, XirArgument.forWord(0)); | 824 return new XirSnippet(invokeStaticTemplates.get(site), XirArgument.forWord(0)); |
935 } | |
936 | |
937 @Override | |
938 public XirSnippet genInvokeVirtual(XirSite site, XirArgument receiver, RiMethod method) { | |
939 return new XirSnippet(invokeVirtualTemplate, receiver, XirArgument.forWord(0)); | |
940 } | 825 } |
941 | 826 |
942 @Override | 827 @Override |
943 public XirSnippet genMonitorEnter(XirSite site, XirArgument receiver) { | 828 public XirSnippet genMonitorEnter(XirSite site, XirArgument receiver) { |
944 return new XirSnippet(emptyTemplates[CiKind.Void.ordinal()]); | 829 return new XirSnippet(monitorEnterTemplates.get(site), receiver); |
945 } | 830 } |
946 | 831 |
947 @Override | 832 @Override |
948 public XirSnippet genMonitorExit(XirSite site, XirArgument receiver) { | 833 public XirSnippet genMonitorExit(XirSite site, XirArgument receiver) { |
949 return new XirSnippet(emptyTemplates[CiKind.Void.ordinal()]); | 834 return new XirSnippet(monitorExitTemplates.get(site), receiver); |
835 } | |
836 | |
837 @Override | |
838 public XirSnippet genGetField(XirSite site, XirArgument object, RiField field) { | |
839 if (field.isResolved()) { | |
840 return new XirSnippet(getFieldTemplates.get(site, field.kind()), object, XirArgument.forInt(((HotSpotField) field).offset())); | |
841 } | |
842 return new XirSnippet(getFieldTemplates.get(site, field.kind(), UNRESOLVED), object); | |
843 } | |
844 | |
845 @Override | |
846 public XirSnippet genPutField(XirSite site, XirArgument object, RiField field, XirArgument value) { | |
847 if (field.isResolved()) { | |
848 return new XirSnippet(putFieldTemplates.get(site, field.kind()), object, value, XirArgument.forInt(((HotSpotField) field).offset())); | |
849 } | |
850 return new XirSnippet(putFieldTemplates.get(site, field.kind(), UNRESOLVED), object, value); | |
851 } | |
852 | |
853 @Override | |
854 public XirSnippet genGetStatic(XirSite site, XirArgument object, RiField field) { | |
855 if (field.isResolved()) { | |
856 return new XirSnippet(getFieldTemplates.get(site, field.kind()), object, XirArgument.forInt(((HotSpotField) field).offset())); | |
857 } | |
858 return new XirSnippet(getFieldTemplates.get(site, field.kind(), UNRESOLVED), object); | |
859 } | |
860 | |
861 @Override | |
862 public XirSnippet genPutStatic(XirSite site, XirArgument object, RiField field, XirArgument value) { | |
863 if (field.isResolved()) { | |
864 return new XirSnippet(putFieldTemplates.get(site, field.kind()), object, value, XirArgument.forInt(((HotSpotField) field).offset())); | |
865 } | |
866 return new XirSnippet(putFieldTemplates.get(site, field.kind(), UNRESOLVED), object, value); | |
867 } | |
868 | |
869 @Override | |
870 public XirSnippet genNewInstance(XirSite site, RiType type) { | |
871 if (type instanceof HotSpotTypeResolved) { | |
872 int instanceSize = ((HotSpotTypeResolved) type).instanceSize(); | |
873 return new XirSnippet(newInstanceTemplates.get(site, instanceSize), XirArgument.forObject(type)); | |
874 } | |
875 return new XirSnippet(newInstanceUnresolvedTemplates.get(site)); | |
950 } | 876 } |
951 | 877 |
952 @Override | 878 @Override |
953 public XirSnippet genNewArray(XirSite site, XirArgument length, CiKind elementKind, RiType componentType, RiType arrayType) { | 879 public XirSnippet genNewArray(XirSite site, XirArgument length, CiKind elementKind, RiType componentType, RiType arrayType) { |
954 if (elementKind == CiKind.Object) { | 880 if (elementKind == CiKind.Object) { |
955 if (arrayType instanceof HotSpotTypeResolved) { | 881 if (arrayType instanceof HotSpotTypeResolved) { |
956 return new XirSnippet(newObjectArrayTemplate.resolved, length, XirArgument.forObject(arrayType)); | 882 return new XirSnippet(newObjectArrayTemplates.get(site), length, XirArgument.forObject(arrayType)); |
957 } | 883 } |
958 return new XirSnippet(newObjectArrayTemplate.unresolved, length); | 884 return new XirSnippet(newObjectArrayTemplates.get(site, UNRESOLVED), length); |
959 } | 885 } |
960 assert arrayType == null; | 886 assert arrayType == null; |
961 arrayType = Compiler.getVMEntries().getPrimitiveArrayType(elementKind); | 887 arrayType = Compiler.getVMEntries().getPrimitiveArrayType(elementKind); |
962 return new XirSnippet(newTypeArrayTemplate, length, XirArgument.forObject(arrayType)); | 888 return new XirSnippet(newTypeArrayTemplates.get(site), length, XirArgument.forObject(arrayType)); |
963 } | |
964 | |
965 @Override | |
966 public XirSnippet genNewInstance(XirSite site, RiType type) { | |
967 if (type instanceof HotSpotTypeResolved) { | |
968 int instanceSize = ((HotSpotTypeResolved) type).instanceSize(); | |
969 return new XirSnippet(newInstanceTemplates.get(instanceSize), XirArgument.forObject(type)); | |
970 } | |
971 return new XirSnippet(newInstanceUnresolvedTemplate); | |
972 } | 889 } |
973 | 890 |
974 @Override | 891 @Override |
975 public XirSnippet genNewMultiArray(XirSite site, XirArgument[] lengths, RiType type) { | 892 public XirSnippet genNewMultiArray(XirSite site, XirArgument[] lengths, RiType type) { |
976 if (type instanceof HotSpotTypeResolved) { | 893 if (type instanceof HotSpotTypeResolved) { |
977 XirArgument[] params = Arrays.copyOf(lengths, lengths.length + 1); | 894 XirArgument[] params = Arrays.copyOf(lengths, lengths.length + 1); |
978 params[lengths.length] = XirArgument.forObject(type); | 895 params[lengths.length] = XirArgument.forObject(type); |
979 return new XirSnippet(multiNewArrayTemplate.get(lengths.length).resolved, params); | 896 return new XirSnippet(multiNewArrayTemplate.get(site, lengths.length), params); |
980 } | 897 } |
981 return new XirSnippet(multiNewArrayTemplate.get(lengths.length).unresolved, lengths); | 898 return new XirSnippet(multiNewArrayTemplate.get(site, lengths.length, UNRESOLVED), lengths); |
982 } | 899 } |
983 | 900 |
984 @Override | 901 @Override |
985 public XirSnippet genResolveClass(XirSite site, RiType type, Representation representation) { | 902 public XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiType type) { |
986 assert representation == Representation.ObjectHub : "unexpected representation: " + representation; | 903 if (type.isResolved()) { |
987 if (type instanceof HotSpotTypeResolved) { | 904 return new XirSnippet(checkCastTemplates.get(site), receiver, hub); |
988 return new XirSnippet(resolveClassTemplate.resolved, XirArgument.forObject(type)); | 905 } |
989 } | 906 return new XirSnippet(checkCastTemplates.get(site, UNRESOLVED), receiver); |
990 return new XirSnippet(resolveClassTemplate.unresolved); | 907 } |
991 } | 908 |
992 | 909 @Override |
993 @Override | 910 public XirSnippet genInstanceOf(XirSite site, XirArgument object, XirArgument hub, RiType type) { |
994 public XirSnippet genSafepoint(XirSite site) { | 911 if (type.isResolved()) { |
995 return new XirSnippet(safepointTemplate); | 912 return new XirSnippet(instanceOfTemplates.get(site), object, hub); |
996 } | 913 } |
997 | 914 return new XirSnippet(instanceOfTemplates.get(site, UNRESOLVED), object); |
998 @Override | 915 } |
999 public XirSnippet genExceptionObject(XirSite site) { | 916 |
1000 return new XirSnippet(exceptionObjectTemplate); | 917 @Override |
918 public XirSnippet genArrayLoad(XirSite site, XirArgument array, XirArgument index, XirArgument length, CiKind elementKind, RiType elementType) { | |
919 if (length == null) { | |
920 return new XirSnippet(arrayLoadTemplates.get(site, elementKind), array, index); | |
921 } | |
922 return new XirSnippet(arrayLoadTemplates.get(site, elementKind, GIVEN_LENGTH), array, index, length); | |
923 } | |
924 | |
925 @Override | |
926 public XirSnippet genArrayStore(XirSite site, XirArgument array, XirArgument index, XirArgument length, XirArgument value, CiKind elementKind, RiType elementType) { | |
927 if (length == null) { | |
928 return new XirSnippet(arrayStoreTemplates.get(site, elementKind), array, index, value); | |
929 } | |
930 return new XirSnippet(arrayStoreTemplates.get(site, elementKind, GIVEN_LENGTH), array, index, value, length); | |
931 } | |
932 | |
933 @Override | |
934 public XirSnippet genArrayLength(XirSite site, XirArgument array) { | |
935 return new XirSnippet(arrayLengthTemplates.get(site), array); | |
936 } | |
937 | |
938 @Override | |
939 public List<XirTemplate> buildTemplates(CiXirAssembler asm) { | |
940 this.asm = asm; | |
941 List<XirTemplate> templates = new ArrayList<XirTemplate>(); | |
942 return templates; | |
1001 } | 943 } |
1002 | 944 |
1003 private static class UnresolvedClassPatching { | 945 private static class UnresolvedClassPatching { |
1004 | 946 |
1005 private final XirLabel patchSite; | 947 private final XirLabel patchSite; |
1054 | 996 |
1055 state = State.Finished; | 997 state = State.Finished; |
1056 } | 998 } |
1057 } | 999 } |
1058 | 1000 |
1059 private void checkSubtype(XirOperand result, XirOperand objHub, XirOperand hub) { | 1001 private static class UnresolvedFieldPatching { |
1002 | |
1003 private final XirLabel patchSite; | |
1004 private final XirLabel replacement; | |
1005 private final XirLabel patchStub; | |
1006 private final CiXirAssembler asm; | |
1007 private final HotSpotVMConfig config; | |
1008 private State state; | |
1009 private final XirOperand receiver; | |
1010 private final XirOperand value; | |
1011 private final boolean put; | |
1012 private final boolean nullCheck; | |
1013 | |
1014 private enum State { | |
1015 New, Inline, Finished | |
1016 } | |
1017 | |
1018 public UnresolvedFieldPatching(CiXirAssembler asm, XirOperand receiver, XirOperand value, boolean put, boolean nullCheck, HotSpotVMConfig config) { | |
1019 this.asm = asm; | |
1020 this.receiver = receiver; | |
1021 this.value = value; | |
1022 this.put = put; | |
1023 this.nullCheck = nullCheck; | |
1024 this.config = config; | |
1025 patchSite = asm.createInlineLabel("patch site"); | |
1026 replacement = asm.createOutOfLineLabel("replacement"); | |
1027 patchStub = asm.createOutOfLineLabel("patch stub"); | |
1028 | |
1029 state = State.New; | |
1030 } | |
1031 | |
1032 public void emitInline() { | |
1033 assert state == State.New; | |
1034 if (nullCheck) { | |
1035 asm.nop(1); | |
1036 } | |
1037 asm.bindInline(patchSite); | |
1038 asm.mark(MARK_DUMMY_OOP_RELOCATION); | |
1039 if (nullCheck) { | |
1040 asm.mark(MARK_IMPLICIT_NULL); | |
1041 } | |
1042 asm.jmp(patchStub); | |
1043 | |
1044 // TODO: make this more generic & safe - this is needed to create space for patching | |
1045 asm.nop(5); | |
1046 | |
1047 state = State.Inline; | |
1048 } | |
1049 | |
1050 public void emitOutOfLine() { | |
1051 assert state == State.Inline; | |
1052 | |
1053 asm.bindOutOfLine(replacement); | |
1054 XirMark begin = asm.mark(null); | |
1055 if (put) { | |
1056 asm.pstore(value.kind, receiver, asm.i(Integer.MAX_VALUE), value, false); | |
1057 } else { | |
1058 asm.pload(value.kind, value, receiver, asm.i(Integer.MAX_VALUE), false); | |
1059 } | |
1060 XirMark end = asm.mark(null); | |
1061 // make this piece of data look like an instruction | |
1062 asm.rawBytes(new byte[] { (byte) 0xb8, 0, 0, 0x05, 0}); | |
1063 asm.mark(MARK_ACCESS_FIELD_PATCHING, begin, end); | |
1064 asm.bindOutOfLine(patchStub); | |
1065 asm.callRuntime(config.accessFieldStub, null); | |
1066 asm.jmp(patchSite); | |
1067 | |
1068 state = State.Finished; | |
1069 } | |
1070 } | |
1071 | |
1072 private void checkSubtype(CiXirAssembler asm, XirOperand result, XirOperand objHub, XirOperand hub) { | |
1060 asm.push(objHub); | 1073 asm.push(objHub); |
1061 asm.push(hub); | 1074 asm.push(hub); |
1062 asm.callRuntime(config.instanceofStub, null); | 1075 asm.callRuntime(config.instanceofStub, null); |
1063 asm.pop(result); | 1076 asm.pop(result); |
1064 asm.pop(result); | 1077 asm.pop(result); |
1070 asm.createRegister("reg", CiKind.Illegal, register); | 1083 asm.createRegister("reg", CiKind.Illegal, register); |
1071 } | 1084 } |
1072 } | 1085 } |
1073 } | 1086 } |
1074 | 1087 |
1075 private void useRegisters(CiRegister... registers) { | 1088 private void writeBarrier(CiXirAssembler asm, XirOperand base) { |
1076 useRegisters(asm, registers); | 1089 asm.shr(base, base, asm.i(config.cardtableShift)); |
1077 } | 1090 asm.pstore(CiKind.Boolean, asm.w(config.cardtableStartAddress), base, asm.b(false), false); |
1078 | 1091 } |
1079 private abstract class OndemandTemplates<T> { | 1092 |
1080 | 1093 /** |
1081 private ConcurrentHashMap<Integer, T> templates = new ConcurrentHashMap<Integer, T>(); | 1094 * Base class for all the ondemand template generators. It is not normally subclassed directly, but through one of |
1082 | 1095 * its subclasses (SimpleTemplates, KindTemplates, IndexTemplates). |
1083 protected abstract T create(CiXirAssembler asm, int index); | 1096 * |
1084 | 1097 * @author Lukas Stadler |
1085 public T get(int index) { | 1098 */ |
1086 T template = templates.get(index); | 1099 private abstract class Templates { |
1100 | |
1101 private ConcurrentHashMap<Long, XirTemplate> templates = new ConcurrentHashMap<Long, XirTemplate>(); | |
1102 private final long mask; | |
1103 | |
1104 /** | |
1105 * Each flag passed to this method will cause templates with and without it to be generated. | |
1106 */ | |
1107 public Templates(TemplateFlag... flags) { | |
1108 this.mask = getBits((int) INDEX_MASK, null, flags); | |
1109 } | |
1110 | |
1111 protected abstract XirTemplate create(CiXirAssembler asm, long flags); | |
1112 | |
1113 protected boolean is(TemplateFlag check, long flags) { | |
1114 return (flags & check.bits()) == check.bits(); | |
1115 } | |
1116 | |
1117 protected long getBits(int index, XirSite site, TemplateFlag... flags) { | |
1118 long bits = index; | |
1119 if (site != null) { | |
1120 bits |= site.requiresNullCheck() ? NULL_CHECK.bits() : 0; | |
1121 bits |= site.requiresReadBarrier() ? READ_BARRIER.bits() : 0; | |
1122 bits |= site.requiresWriteBarrier() ? WRITE_BARRIER.bits() : 0; | |
1123 bits |= site.requiresArrayStoreCheck() ? STORE_CHECK.bits() : 0; | |
1124 bits |= site.requiresBoundsCheck() ? BOUNDS_CHECK.bits() : 0; | |
1125 } | |
1126 if (flags != null) { | |
1127 for (TemplateFlag flag : flags) { | |
1128 bits |= flag.bits(); | |
1129 } | |
1130 } | |
1131 return bits; | |
1132 } | |
1133 | |
1134 protected XirTemplate getInternal(long flags) { | |
1135 flags = flags & mask; | |
1136 XirTemplate template = templates.get(flags); | |
1087 if (template == null) { | 1137 if (template == null) { |
1088 template = create(asm.copy(), index); | 1138 template = create(HotSpotXirGenerator.this.asm.copy(), flags); |
1089 templates.put(index, template); | 1139 templates.put(flags, template); |
1090 } | 1140 } |
1091 return template; | 1141 return template; |
1092 } | 1142 } |
1093 } | 1143 } |
1144 | |
1145 private abstract class SimpleTemplates extends Templates { | |
1146 | |
1147 public SimpleTemplates(TemplateFlag... flags) { | |
1148 super(flags); | |
1149 } | |
1150 | |
1151 public XirTemplate get(XirSite site, TemplateFlag... flags) { | |
1152 return getInternal(getBits(0, site, flags)); | |
1153 } | |
1154 } | |
1155 | |
1156 private abstract class IndexTemplates extends Templates { | |
1157 | |
1158 public IndexTemplates(TemplateFlag... flags) { | |
1159 super(flags); | |
1160 } | |
1161 | |
1162 @Override | |
1163 protected final XirTemplate create(CiXirAssembler asm, long flags) { | |
1164 return create(asm, flags & FLAGS_MASK, (int) (flags & INDEX_MASK)); | |
1165 } | |
1166 | |
1167 protected abstract XirTemplate create(CiXirAssembler asm, long flags, int index); | |
1168 | |
1169 public XirTemplate get(XirSite site, int size, TemplateFlag... flags) { | |
1170 return getInternal(getBits(size, site, flags)); | |
1171 } | |
1172 } | |
1173 | |
1174 private abstract class KindTemplates extends Templates { | |
1175 | |
1176 public KindTemplates(TemplateFlag... flags) { | |
1177 super(flags); | |
1178 } | |
1179 | |
1180 @Override | |
1181 protected final XirTemplate create(CiXirAssembler asm, long flags) { | |
1182 return create(asm, flags & FLAGS_MASK, CiKind.VALUES[(int) (flags & INDEX_MASK)]); | |
1183 } | |
1184 | |
1185 protected abstract XirTemplate create(CiXirAssembler asm, long flags, CiKind kind); | |
1186 | |
1187 public XirTemplate get(XirSite site, CiKind kind, TemplateFlag... flags) { | |
1188 return getInternal(getBits(kind.ordinal(), site, flags)); | |
1189 } | |
1190 } | |
1094 } | 1191 } |