001 /*
002 * This file is part of the Jikes RVM project (http://jikesrvm.org).
003 *
004 * This file is licensed to You under the Eclipse Public License (EPL);
005 * You may not use this file except in compliance with the License. You
006 * may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/eclipse-1.0.php
009 *
010 * See the COPYRIGHT.txt file distributed with this work for information
011 * regarding copyright ownership.
012 */
013 package org.jikesrvm.compilers.opt.bc2ir;
014
015 import static org.jikesrvm.SizeConstants.LOG_BYTES_IN_ADDRESS;
016 import static org.jikesrvm.SizeConstants.LOG_BYTES_IN_INT;
017 import static org.jikesrvm.compilers.opt.ir.Operators.ADDR_2INT;
018 import static org.jikesrvm.compilers.opt.ir.Operators.ADDR_2LONG;
019 import static org.jikesrvm.compilers.opt.ir.Operators.ARRAYLENGTH;
020 import static org.jikesrvm.compilers.opt.ir.Operators.ATTEMPT_ADDR;
021 import static org.jikesrvm.compilers.opt.ir.Operators.ATTEMPT_INT;
022 import static org.jikesrvm.compilers.opt.ir.Operators.ATTEMPT_LONG;
023 import static org.jikesrvm.compilers.opt.ir.Operators.BOOLEAN_CMP_ADDR;
024 import static org.jikesrvm.compilers.opt.ir.Operators.BYTE_LOAD;
025 import static org.jikesrvm.compilers.opt.ir.Operators.BYTE_STORE;
026 import static org.jikesrvm.compilers.opt.ir.Operators.CALL;
027 import static org.jikesrvm.compilers.opt.ir.Operators.DOUBLE_AS_LONG_BITS;
028 import static org.jikesrvm.compilers.opt.ir.Operators.DOUBLE_LOAD;
029 import static org.jikesrvm.compilers.opt.ir.Operators.DOUBLE_SQRT;
030 import static org.jikesrvm.compilers.opt.ir.Operators.DOUBLE_STORE;
031 import static org.jikesrvm.compilers.opt.ir.Operators.FLOAT_AS_INT_BITS;
032 import static org.jikesrvm.compilers.opt.ir.Operators.FLOAT_LOAD;
033 import static org.jikesrvm.compilers.opt.ir.Operators.FLOAT_SQRT;
034 import static org.jikesrvm.compilers.opt.ir.Operators.FLOAT_STORE;
035 import static org.jikesrvm.compilers.opt.ir.Operators.GET_OBJ_TIB;
036 import static org.jikesrvm.compilers.opt.ir.Operators.GET_TIME_BASE;
037 import static org.jikesrvm.compilers.opt.ir.Operators.GET_TYPE_FROM_TIB;
038 import static org.jikesrvm.compilers.opt.ir.Operators.INT_2ADDRSigExt;
039 import static org.jikesrvm.compilers.opt.ir.Operators.INT_2ADDRZerExt;
040 import static org.jikesrvm.compilers.opt.ir.Operators.INT_ADD;
041 import static org.jikesrvm.compilers.opt.ir.Operators.INT_BITS_AS_FLOAT;
042 import static org.jikesrvm.compilers.opt.ir.Operators.INT_LOAD;
043 import static org.jikesrvm.compilers.opt.ir.Operators.INT_SHL;
044 import static org.jikesrvm.compilers.opt.ir.Operators.INT_STORE;
045 import static org.jikesrvm.compilers.opt.ir.Operators.LONG_2ADDR;
046 import static org.jikesrvm.compilers.opt.ir.Operators.LONG_BITS_AS_DOUBLE;
047 import static org.jikesrvm.compilers.opt.ir.Operators.LONG_LOAD;
048 import static org.jikesrvm.compilers.opt.ir.Operators.LONG_STORE;
049 import static org.jikesrvm.compilers.opt.ir.Operators.PREPARE_ADDR;
050 import static org.jikesrvm.compilers.opt.ir.Operators.PREPARE_INT;
051 import static org.jikesrvm.compilers.opt.ir.Operators.PREPARE_LONG;
052 import static org.jikesrvm.compilers.opt.ir.Operators.REF_ADD;
053 import static org.jikesrvm.compilers.opt.ir.Operators.REF_AND;
054 import static org.jikesrvm.compilers.opt.ir.Operators.REF_LOAD;
055 import static org.jikesrvm.compilers.opt.ir.Operators.REF_MOVE;
056 import static org.jikesrvm.compilers.opt.ir.Operators.REF_NOT;
057 import static org.jikesrvm.compilers.opt.ir.Operators.REF_OR;
058 import static org.jikesrvm.compilers.opt.ir.Operators.REF_SHL;
059 import static org.jikesrvm.compilers.opt.ir.Operators.REF_SHR;
060 import static org.jikesrvm.compilers.opt.ir.Operators.REF_STORE;
061 import static org.jikesrvm.compilers.opt.ir.Operators.REF_SUB;
062 import static org.jikesrvm.compilers.opt.ir.Operators.REF_USHR;
063 import static org.jikesrvm.compilers.opt.ir.Operators.REF_XOR;
064 import static org.jikesrvm.compilers.opt.ir.Operators.SHORT_LOAD;
065 import static org.jikesrvm.compilers.opt.ir.Operators.SHORT_STORE;
066 import static org.jikesrvm.compilers.opt.ir.Operators.SYSCALL;
067 import static org.jikesrvm.compilers.opt.ir.Operators.UBYTE_LOAD;
068 import static org.jikesrvm.compilers.opt.ir.Operators.USHORT_LOAD;
069
070 import org.jikesrvm.VM;
071 import org.jikesrvm.ArchitectureSpecificOpt.GenerateMachineSpecificMagic;
072 import org.jikesrvm.classloader.Atom;
073 import org.jikesrvm.classloader.RVMField;
074 import org.jikesrvm.classloader.MemberReference;
075 import org.jikesrvm.classloader.MethodReference;
076 import org.jikesrvm.classloader.TypeReference;
077 import org.jikesrvm.compilers.opt.MagicNotImplementedException;
078 import org.jikesrvm.compilers.opt.OptimizingCompilerException;
079 import org.jikesrvm.compilers.opt.ir.Attempt;
080 import org.jikesrvm.compilers.opt.ir.Binary;
081 import org.jikesrvm.compilers.opt.ir.BooleanCmp;
082 import org.jikesrvm.compilers.opt.ir.Call;
083 import org.jikesrvm.compilers.opt.ir.GuardedUnary;
084 import org.jikesrvm.compilers.opt.ir.Instruction;
085 import org.jikesrvm.compilers.opt.ir.Load;
086 import org.jikesrvm.compilers.opt.ir.Move;
087 import org.jikesrvm.compilers.opt.ir.Nullary;
088 import org.jikesrvm.compilers.opt.ir.Operator;
089 import org.jikesrvm.compilers.opt.ir.Prepare;
090 import org.jikesrvm.compilers.opt.ir.Store;
091 import org.jikesrvm.compilers.opt.ir.Unary;
092 import org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand;
093 import org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand;
094 import org.jikesrvm.compilers.opt.ir.operand.ConditionOperand;
095 import org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand;
096 import org.jikesrvm.compilers.opt.ir.operand.LocationOperand;
097 import org.jikesrvm.compilers.opt.ir.operand.MethodOperand;
098 import org.jikesrvm.compilers.opt.ir.operand.ObjectConstantOperand;
099 import org.jikesrvm.compilers.opt.ir.operand.Operand;
100 import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand;
101 import org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand;
102 import org.jikesrvm.objectmodel.TIBLayoutConstants;
103 import org.jikesrvm.runtime.ArchEntrypoints;
104 import org.jikesrvm.runtime.MagicNames;
105 import org.vmmagic.pragma.Interruptible;
106 import org.vmmagic.unboxed.Address;
107 import org.vmmagic.unboxed.Offset;
108
109 /**
110 * This class implements the non-machine-specific magics for the opt compiler.
111 * By non-machine-specific we mean that the IR generated to implement the magic
112 * is independent of the target-architecture.
113 * It does not mean that the eventual MIR that implements the magic
114 * won't differ from architecture to architecture.
115 */
116 public class GenerateMagic implements TIBLayoutConstants {
117
118 /**
119 * "Semantic inlining" of methods of the Magic class.
120 * Based on the methodName, generate a sequence of opt instructions
121 * that implement the magic, updating the expression stack as necessary.
122 *
123 * @param bc2ir the bc2ir object that is generating the
124 * ir containing this magic
125 * @param gc must be bc2ir.gc
126 * @param meth the RVMMethod that is the magic method
127 */
128 static boolean generateMagic(BC2IR bc2ir, GenerationContext gc, MethodReference meth)
129 throws MagicNotImplementedException {
130
131 if (gc.method.hasNoInlinePragma()) gc.allocFrame = true;
132
133 // HACK: Don't schedule any bbs containing unsafe magics.
134 // TODO: move this to individual magics that are unsafe.
135 // -- igor 08/13/1999
136 bc2ir.markBBUnsafeForScheduling();
137 Atom methodName = meth.getName();
138
139 boolean address = (meth.getType() == TypeReference.Address);
140
141 // Address magic
142 TypeReference[] types = meth.getParameterTypes();
143 TypeReference returnType = meth.getReturnType();
144
145 if (address && isLoad(methodName)) {
146 // LOAD
147 Operand offset = (types.length == 0) ? new AddressConstantOperand(Address.zero()) : bc2ir.popAddress();
148 Operand base = bc2ir.popAddress();
149 RegisterOperand result = gc.temps.makeTemp(returnType);
150 bc2ir.appendInstruction(Load.create(getOperator(returnType, LOAD_OP), result, base, offset, null));
151 bc2ir.push(result.copyD2U(), returnType);
152
153 } else if (address && isPrepare(methodName)) {
154 // PREPARE
155 Operand offset = (types.length == 0) ? new AddressConstantOperand(Address.zero()) : bc2ir.popAddress();
156 Operand base = bc2ir.popAddress();
157 RegisterOperand result = gc.temps.makeTemp(returnType);
158 bc2ir.appendInstruction(Prepare.create(getOperator(returnType, PREPARE_OP), result, base, offset, null));
159 bc2ir.push(result.copyD2U(), returnType);
160
161 } else if (address && methodName == MagicNames.attempt) {
162 // ATTEMPT
163 TypeReference attemptType = types[0];
164
165 Operand offset = (types.length == 2) ? new AddressConstantOperand(Address.zero()) : bc2ir.popAddress();
166
167 Operand newVal = bc2ir.pop();
168 Operand oldVal = bc2ir.pop();
169 Operand base = bc2ir.popAddress();
170 RegisterOperand test = gc.temps.makeTempInt();
171 bc2ir.appendInstruction(Attempt.create(getOperator(attemptType, ATTEMPT_OP),
172 test,
173 base,
174 offset,
175 oldVal,
176 newVal,
177 null));
178 bc2ir.push(test.copyD2U(), returnType);
179
180 } else if (address && methodName == MagicNames.store) {
181 // STORE
182 TypeReference storeType = types[0];
183
184 Operand offset = (types.length == 1) ? new AddressConstantOperand(Address.zero()) : bc2ir.popAddress();
185
186 Operand val = bc2ir.pop(storeType);
187 Operand base = bc2ir.popAddress();
188 bc2ir.appendInstruction(Store.create(getOperator(storeType, STORE_OP), val, base, offset, null));
189
190 } else if (methodName == MagicNames.getThreadRegister) {
191 RegisterOperand rop = gc.temps.makeTROp();
192 bc2ir.markGuardlessNonNull(rop);
193 bc2ir.push(rop);
194 } else if (methodName == MagicNames.setThreadRegister) {
195 Operand val = bc2ir.popRef();
196 if (val instanceof RegisterOperand) {
197 bc2ir.appendInstruction(Move.create(REF_MOVE, gc.temps.makeTROp(), val));
198 } else {
199 String msg = " Unexpected operand Magic.setThreadRegister";
200 throw MagicNotImplementedException.UNEXPECTED(msg);
201 }
202 } else if (methodName == MagicNames.addressArrayCreate) {
203 Instruction s = bc2ir.generateAnewarray(null, meth.getType().getArrayElementType());
204 bc2ir.appendInstruction(s);
205 } else if (methodName == MagicNames.addressArrayLength) {
206 Operand op1 = bc2ir.pop();
207 bc2ir.clearCurrentGuard();
208 if (bc2ir.do_NullCheck(op1)) {
209 return true;
210 }
211 RegisterOperand t = gc.temps.makeTempInt();
212 Instruction s = GuardedUnary.create(ARRAYLENGTH, t, op1, bc2ir.getCurrentGuard());
213 bc2ir.push(t.copyD2U());
214 bc2ir.appendInstruction(s);
215 } else if (methodName == MagicNames.addressArrayGet) {
216 TypeReference elementType = meth.getReturnType();
217 Operand index = bc2ir.popInt();
218 Operand ref = bc2ir.popRef();
219 RegisterOperand offsetI = gc.temps.makeTempInt();
220 RegisterOperand offset = gc.temps.makeTempOffset();
221 RegisterOperand result;
222 if (meth.getType().isCodeArrayType()) {
223 if (VM.BuildForIA32) {
224 result = gc.temps.makeTemp(TypeReference.Byte);
225 bc2ir.appendInstruction(Load.create(BYTE_LOAD,
226 result,
227 ref,
228 index,
229 new LocationOperand(elementType),
230 new TrueGuardOperand()));
231 } else if (VM.BuildForPowerPC) {
232 result = gc.temps.makeTemp(TypeReference.Int);
233 bc2ir.appendInstruction(Binary.create(INT_SHL, offsetI, index, new IntConstantOperand(LOG_BYTES_IN_INT)));
234 bc2ir.appendInstruction(Unary.create(INT_2ADDRZerExt, offset, offsetI.copy()));
235 bc2ir.appendInstruction(Load.create(INT_LOAD,
236 result,
237 ref,
238 offset.copy(),
239 new LocationOperand(elementType),
240 new TrueGuardOperand()));
241 }
242 } else {
243 result = gc.temps.makeTemp(elementType);
244 bc2ir.appendInstruction(Binary.create(INT_SHL,
245 offsetI,
246 index,
247 new IntConstantOperand(LOG_BYTES_IN_ADDRESS)));
248 bc2ir.appendInstruction(Unary.create(INT_2ADDRZerExt, offset, offsetI.copy()));
249 bc2ir.appendInstruction(Load.create(REF_LOAD,
250 result,
251 ref,
252 offset.copy(),
253 new LocationOperand(elementType),
254 new TrueGuardOperand()));
255 }
256 bc2ir.push(result.copyD2U());
257 } else if (methodName == MagicNames.addressArraySet) {
258 TypeReference elementType = meth.getParameterTypes()[1];
259 Operand val = bc2ir.pop();
260 Operand index = bc2ir.popInt();
261 Operand ref = bc2ir.popRef();
262 RegisterOperand offsetI = gc.temps.makeTempInt();
263 RegisterOperand offset = gc.temps.makeTempOffset();
264 if (meth.getType().isCodeArrayType()) {
265 if (VM.BuildForIA32) {
266 bc2ir.appendInstruction(Store.create(BYTE_STORE,
267 val,
268 ref,
269 index,
270 new LocationOperand(elementType),
271 new TrueGuardOperand()));
272 } else if (VM.BuildForPowerPC) {
273 bc2ir.appendInstruction(Binary.create(INT_SHL, offsetI, index, new IntConstantOperand(LOG_BYTES_IN_INT)));
274 bc2ir.appendInstruction(Unary.create(INT_2ADDRZerExt, offset, offsetI.copy()));
275 bc2ir.appendInstruction(Store.create(INT_STORE,
276 val,
277 ref,
278 offset.copy(),
279 new LocationOperand(elementType),
280 new TrueGuardOperand()));
281 }
282 } else {
283 bc2ir.appendInstruction(Binary.create(INT_SHL,
284 offsetI,
285 index,
286 new IntConstantOperand(LOG_BYTES_IN_ADDRESS)));
287 bc2ir.appendInstruction(Unary.create(INT_2ADDRZerExt, offset, offsetI.copy()));
288 bc2ir.appendInstruction(Store.create(REF_STORE,
289 val,
290 ref,
291 offset.copy(),
292 new LocationOperand(elementType),
293 new TrueGuardOperand()));
294 }
295 } else if (methodName == MagicNames.getIntAtOffset) {
296 Operand offset = bc2ir.popAddress();
297 Operand object = bc2ir.popRef();
298 RegisterOperand val = gc.temps.makeTempInt();
299 bc2ir.appendInstruction(Load.create(INT_LOAD, val, object, offset, null));
300 bc2ir.push(val.copyD2U());
301 } else if (methodName == MagicNames.setIntAtOffset) {
302 LocationOperand loc = null;
303 if (meth.getParameterTypes().length == 4) {
304 loc = mapToMetadata(bc2ir.popInt());
305 }
306 Operand val = bc2ir.popInt();
307 Operand offset = bc2ir.popAddress();
308 Operand object = bc2ir.popRef();
309 bc2ir.appendInstruction(Store.create(INT_STORE, val, object, offset, loc));
310 } else if (methodName == MagicNames.getFloatAtOffset) {
311 Operand offset = bc2ir.popAddress();
312 Operand object = bc2ir.popRef();
313 RegisterOperand val = gc.temps.makeTempFloat();
314 bc2ir.appendInstruction(Load.create(FLOAT_LOAD, val, object, offset, null));
315 bc2ir.push(val.copyD2U());
316 } else if (methodName == MagicNames.setFloatAtOffset) {
317 LocationOperand loc = null;
318 if (meth.getParameterTypes().length == 4) {
319 loc = mapToMetadata(bc2ir.popInt());
320 }
321 Operand val = bc2ir.popFloat();
322 Operand offset = bc2ir.popAddress();
323 Operand object = bc2ir.popRef();
324 bc2ir.appendInstruction(Store.create(FLOAT_STORE, val, object, offset, loc));
325 } else if (methodName == MagicNames.getWordAtOffset) {
326 LocationOperand loc = null;
327 if (meth.getParameterTypes().length == 3) {
328 loc = mapToMetadata(bc2ir.popInt());
329 }
330 Operand offset = bc2ir.popAddress();
331 Operand object = bc2ir.popRef();
332 RegisterOperand val = gc.temps.makeTemp(TypeReference.Word);
333 bc2ir.appendInstruction(Load.create(REF_LOAD, val, object, offset, loc));
334 bc2ir.push(val.copyD2U());
335 } else if (methodName == MagicNames.getAddressAtOffset) {
336 LocationOperand loc = null;
337 if (meth.getParameterTypes().length == 3) {
338 loc = mapToMetadata(bc2ir.popInt());
339 }
340 Operand offset = bc2ir.popAddress();
341 Operand object = bc2ir.popRef();
342 RegisterOperand val = gc.temps.makeTemp(TypeReference.Address);
343 bc2ir.appendInstruction(Load.create(REF_LOAD, val, object, offset, loc));
344 bc2ir.push(val.copyD2U());
345 } else if (methodName == MagicNames.getExtentAtOffset) {
346 LocationOperand loc = null;
347 if (meth.getParameterTypes().length == 3) {
348 loc = mapToMetadata(bc2ir.popInt());
349 }
350 Operand offset = bc2ir.popAddress();
351 Operand object = bc2ir.popRef();
352 RegisterOperand val = gc.temps.makeTemp(TypeReference.Extent);
353 bc2ir.appendInstruction(Load.create(REF_LOAD, val, object, offset, loc));
354 bc2ir.push(val.copyD2U());
355 } else if (methodName == MagicNames.getOffsetAtOffset) {
356 LocationOperand loc = null;
357 if (meth.getParameterTypes().length == 3) {
358 loc = mapToMetadata(bc2ir.popInt());
359 }
360 Operand offset = bc2ir.popAddress();
361 Operand object = bc2ir.popRef();
362 RegisterOperand val = gc.temps.makeTemp(TypeReference.Offset);
363 bc2ir.appendInstruction(Load.create(REF_LOAD, val, object, offset, loc));
364 bc2ir.push(val.copyD2U());
365 } else if (methodName == MagicNames.setWordAtOffset ||
366 methodName == MagicNames.setAddressAtOffset ||
367 methodName == MagicNames.setOffsetAtOffset ||
368 methodName == MagicNames.setExtentAtOffset) {
369 LocationOperand loc = null;
370 if (meth.getParameterTypes().length == 4) {
371 loc = mapToMetadata(bc2ir.popInt());
372 }
373 Operand val = bc2ir.popRef();
374 Operand offset = bc2ir.popAddress();
375 Operand object = bc2ir.popRef();
376 bc2ir.appendInstruction(Store.create(REF_STORE, val, object, offset, loc));
377 } else if (methodName == MagicNames.getLongAtOffset) {
378 Operand offset = bc2ir.popAddress();
379 Operand object = bc2ir.popRef();
380 RegisterOperand val = gc.temps.makeTempLong();
381 bc2ir.appendInstruction(Load.create(LONG_LOAD, val, object, offset, null));
382 bc2ir.pushDual(val.copyD2U());
383 } else if (methodName == MagicNames.setLongAtOffset) {
384 LocationOperand loc = null;
385 if (meth.getParameterTypes().length == 4) {
386 loc = mapToMetadata(bc2ir.popInt());
387 }
388 Operand val = bc2ir.popLong();
389 Operand offset = bc2ir.popAddress();
390 Operand object = bc2ir.popRef();
391 bc2ir.appendInstruction(Store.create(LONG_STORE, val, object, offset, loc));
392 } else if (methodName == MagicNames.getDoubleAtOffset) {
393 Operand offset = bc2ir.popAddress();
394 Operand object = bc2ir.popRef();
395 RegisterOperand val = gc.temps.makeTempDouble();
396 bc2ir.appendInstruction(Load.create(DOUBLE_LOAD, val, object, offset, null));
397 bc2ir.pushDual(val.copyD2U());
398 } else if (methodName == MagicNames.setDoubleAtOffset) {
399 LocationOperand loc = null;
400 if (meth.getParameterTypes().length == 4) {
401 loc = mapToMetadata(bc2ir.popInt());
402 }
403 Operand val = bc2ir.popDouble();
404 Operand offset = bc2ir.popAddress();
405 Operand object = bc2ir.popRef();
406 bc2ir.appendInstruction(Store.create(DOUBLE_STORE, val, object, offset, loc));
407 } else if (methodName == MagicNames.getObjectAtOffset) {
408 LocationOperand loc = null;
409 if (meth.getParameterTypes().length == 3) {
410 loc = mapToMetadata(bc2ir.popInt());
411 }
412 Operand offset = bc2ir.popAddress();
413 Operand object = bc2ir.popRef();
414 RegisterOperand val = gc.temps.makeTemp(TypeReference.JavaLangObject);
415 bc2ir.appendInstruction(Load.create(REF_LOAD, val, object, offset, loc));
416 bc2ir.push(val.copyD2U());
417 } else if (methodName == MagicNames.getTIBAtOffset) {
418 Operand offset = bc2ir.popAddress();
419 Operand object = bc2ir.popRef();
420 RegisterOperand val = gc.temps.makeTemp(TypeReference.TIB);
421 bc2ir.appendInstruction(Load.create(REF_LOAD, val, object, offset, null));
422 bc2ir.push(val.copyD2U());
423 } else if (methodName == MagicNames.setObjectAtOffset) {
424 LocationOperand loc = null;
425 if (meth.getParameterTypes().length == 4) {
426 loc = mapToMetadata(bc2ir.popInt());
427 }
428 Operand val = bc2ir.popRef();
429 Operand offset = bc2ir.popAddress();
430 Operand object = bc2ir.popRef();
431 bc2ir.appendInstruction(Store.create(REF_STORE, val, object, offset, loc));
432 } else if (methodName == MagicNames.getByteAtOffset) {
433 Operand offset = bc2ir.popAddress();
434 Operand object = bc2ir.popRef();
435 RegisterOperand val = gc.temps.makeTemp(TypeReference.Byte);
436 bc2ir.appendInstruction(Load.create(BYTE_LOAD, val, object, offset, null));
437 bc2ir.push(val.copyD2U());
438 } else if (methodName == MagicNames.getUnsignedByteAtOffset) {
439 Operand offset = bc2ir.popAddress();
440 Operand object = bc2ir.popRef();
441 RegisterOperand val = gc.temps.makeTemp(TypeReference.Byte);
442 bc2ir.appendInstruction(Load.create(UBYTE_LOAD, val, object, offset, null));
443 bc2ir.push(val.copyD2U());
444 } else if (methodName == MagicNames.setByteAtOffset || methodName == MagicNames.setBooleanAtOffset) {
445 LocationOperand loc = null;
446 if (meth.getParameterTypes().length == 4) {
447 loc = mapToMetadata(bc2ir.popInt());
448 }
449 Operand val = bc2ir.popInt();
450 Operand offset = bc2ir.popAddress();
451 Operand object = bc2ir.popRef();
452 bc2ir.appendInstruction(Store.create(BYTE_STORE, val, object, offset, loc));
453 } else if (methodName == MagicNames.getShortAtOffset) {
454 Operand offset = bc2ir.popAddress();
455 Operand object = bc2ir.popRef();
456 RegisterOperand val = gc.temps.makeTemp(TypeReference.Char);
457 bc2ir.appendInstruction(Load.create(SHORT_LOAD, val, object, offset, null));
458 bc2ir.push(val.copyD2U());
459 } else if (methodName == MagicNames.getCharAtOffset) {
460 Operand offset = bc2ir.popAddress();
461 Operand object = bc2ir.popRef();
462 RegisterOperand val = gc.temps.makeTemp(TypeReference.Char);
463 bc2ir.appendInstruction(Load.create(USHORT_LOAD, val, object, offset, null));
464 bc2ir.push(val.copyD2U());
465 } else if (methodName == MagicNames.setCharAtOffset || methodName == MagicNames.setShortAtOffset) {
466 LocationOperand loc = null;
467 if (meth.getParameterTypes().length == 4) {
468 loc = mapToMetadata(bc2ir.popInt());
469 }
470 Operand val = bc2ir.popInt();
471 Operand offset = bc2ir.popAddress();
472 Operand object = bc2ir.popRef();
473 bc2ir.appendInstruction(Store.create(SHORT_STORE, val, object, offset, loc));
474 } else if (methodName == MagicNames.getMemoryInt) {
475 Operand memAddr = bc2ir.popAddress();
476 RegisterOperand val = gc.temps.makeTempInt();
477 bc2ir.appendInstruction(Load.create(INT_LOAD, val, memAddr, new AddressConstantOperand(Offset.zero()), null));
478 bc2ir.push(val.copyD2U());
479 } else if (methodName == MagicNames.getMemoryWord) {
480 Operand memAddr = bc2ir.popAddress();
481 RegisterOperand val = gc.temps.makeTemp(TypeReference.Word);
482 bc2ir.appendInstruction(Load.create(REF_LOAD, val, memAddr, new AddressConstantOperand(Offset.zero()), null));
483 bc2ir.push(val.copyD2U());
484 } else if (methodName == MagicNames.getMemoryAddress) {
485 Operand memAddr = bc2ir.popAddress();
486 RegisterOperand val = gc.temps.makeTemp(TypeReference.Address);
487 bc2ir.appendInstruction(Load.create(REF_LOAD, val, memAddr, new AddressConstantOperand(Offset.zero()), null));
488 bc2ir.push(val.copyD2U());
489 } else if (methodName == MagicNames.setMemoryInt) {
490 Operand val = bc2ir.popInt();
491 Operand memAddr = bc2ir.popAddress();
492 bc2ir.appendInstruction(Store.create(INT_STORE,
493 val,
494 memAddr,
495 new AddressConstantOperand(Offset.zero()),
496 null));
497 } else if (methodName == MagicNames.setMemoryWord) {
498 Operand val = bc2ir.popRef();
499 Operand memAddr = bc2ir.popAddress();
500 bc2ir.appendInstruction(Store.create(REF_STORE,
501 val,
502 memAddr,
503 new AddressConstantOperand(Offset.zero()),
504 null));
505 } else if (meth.isSysCall()) {
506 // All methods of SysCall have the following signature:
507 // callNAME(Address functionAddress, <var args to pass via native calling convention>)
508 // With POWEROPEN_ABI, functionAddress points to the function descriptor
509 TypeReference[] args = meth.getParameterTypes();
510 Instruction call = Call.create(SYSCALL, null, null, null, null, args.length - 1);
511 for (int i = args.length - 1; i >= 1; i--) {
512 Call.setParam(call, i - 1, bc2ir.pop(args[i]));
513 }
514 Operand functionAddress = bc2ir.pop(args[0]);
515 Call.setAddress(call, functionAddress);
516 if (!returnType.isVoidType()) {
517 RegisterOperand op0 = gc.temps.makeTemp(returnType);
518 Call.setResult(call, op0);
519 bc2ir.push(op0.copyD2U(), returnType);
520 }
521 Call.setMethod(call, MethodOperand.STATIC(meth, meth.peekResolvedMethod()));
522 bc2ir.appendInstruction(call);
523 } else if (meth.isSpecializedInvoke()) {
524 // The callsite looks like RETURN = INVOKE (ID, OBJECT, P0, P1 .. PN)
525 // And the actual method will look like RETURN = INVOKE (OBJECT, P0, P1 .. PN)
526
527 // Create the call instruction
528 Instruction call = Call.create(CALL, null, null, null, null, types.length - 1);
529
530 // Plumb all of the normal parameters into the call
531 for (int i = types.length - 1; i >= 2; i--) {
532 Call.setParam(call, i - 1, bc2ir.pop(types[i]));
533 }
534 // The object being specialized
535 Operand objectOperand = bc2ir.pop(types[1]);
536 Call.setParam(call, 0, objectOperand);
537 Operand guard = BC2IR.getGuard(objectOperand);
538 if (guard == null) {
539 // it's magic, so assume that it's OK....
540 guard = new TrueGuardOperand();
541 }
542 Call.setGuard(call, guard);
543
544 // Load the tib of this object
545 RegisterOperand tibObject = gc.temps.makeTemp(TypeReference.TIB);
546 bc2ir.appendInstruction(GuardedUnary.create(GET_OBJ_TIB, tibObject, objectOperand.copy(), guard.copy()));
547
548 // The index of the specialized method
549 Operand methodId = bc2ir.popInt();
550
551 // Add the base offset for specialized methods and convert from index to address
552 RegisterOperand tibOffset = gc.temps.makeTemp(TypeReference.Int);
553 bc2ir.appendInstruction(Binary.create(INT_ADD, tibOffset, methodId, new IntConstantOperand(TIB_FIRST_SPECIALIZED_METHOD_INDEX)));
554 bc2ir.appendInstruction(Binary.create(INT_SHL, tibOffset.copyRO(), tibOffset.copyD2U(), new IntConstantOperand(LOG_BYTES_IN_ADDRESS)));
555
556 // Load the code address from the TIB
557 RegisterOperand codeAddress = gc.temps.makeTemp(TypeReference.Address);
558 bc2ir.appendInstruction(Load.create(REF_LOAD, codeAddress, tibObject.copyD2U(), tibOffset.copyD2U(), null));
559
560 Call.setAddress(call, codeAddress.copyD2U());
561 if (!returnType.isVoidType()) {
562 RegisterOperand op0 = gc.temps.makeTemp(returnType);
563 Call.setResult(call, op0);
564 bc2ir.push(op0.copyD2U(), returnType);
565 }
566 bc2ir.appendInstruction(call);
567 } else if (methodName == MagicNames.threadAsCollectorThread) {
568 RegisterOperand reg = gc.temps.makeTemp(TypeReference.CollectorThread);
569 bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popRef()));
570 bc2ir.push(reg.copyD2U());
571 } else if (methodName == MagicNames.objectAsType) {
572 RegisterOperand reg = gc.temps.makeTemp(TypeReference.Type);
573 bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popRef()));
574 bc2ir.push(reg.copyD2U());
575 } else if (methodName == MagicNames.objectAsThread) {
576 RegisterOperand reg = gc.temps.makeTemp(TypeReference.Thread);
577 bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popRef()));
578 bc2ir.push(reg.copyD2U());
579 } else if (methodName == MagicNames.objectAsAddress) {
580 RegisterOperand reg = gc.temps.makeTemp(TypeReference.Address);
581 bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popRef()));
582 bc2ir.push(reg.copyD2U());
583 } else if (methodName == MagicNames.addressAsObject) {
584 RegisterOperand reg = gc.temps.makeTemp(TypeReference.JavaLangObject);
585 bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popAddress()));
586 bc2ir.push(reg.copyD2U());
587 } else if (methodName == MagicNames.addressAsTIB) {
588 RegisterOperand reg = gc.temps.makeTemp(TypeReference.TIB);
589 bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popAddress()));
590 bc2ir.push(reg.copyD2U());
591 } else if (methodName == MagicNames.addressAsByteArray) {
592 RegisterOperand reg = gc.temps.makeTemp(TypeReference.ByteArray);
593 bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popAddress()));
594 bc2ir.push(reg.copyD2U());
595 } else if (methodName == MagicNames.objectAsShortArray) {
596 RegisterOperand reg = gc.temps.makeTemp(TypeReference.ShortArray);
597 bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popRef()));
598 bc2ir.push(reg.copyD2U());
599 } else if (methodName == MagicNames.objectAsIntArray) {
600 RegisterOperand reg = gc.temps.makeTemp(TypeReference.IntArray);
601 bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popRef()));
602 bc2ir.push(reg.copyD2U());
603 } else if (methodName == MagicNames.floatAsIntBits) {
604 Operand val = bc2ir.popFloat();
605 RegisterOperand op0 = gc.temps.makeTempInt();
606 bc2ir.appendInstruction(Unary.create(FLOAT_AS_INT_BITS, op0, val));
607 bc2ir.push(op0.copyD2U());
608 } else if (methodName == MagicNames.intBitsAsFloat) {
609 Operand val = bc2ir.popInt();
610 RegisterOperand op0 = gc.temps.makeTempFloat();
611 bc2ir.appendInstruction(Unary.create(INT_BITS_AS_FLOAT, op0, val));
612 bc2ir.push(op0.copyD2U());
613 } else if (methodName == MagicNames.doubleAsLongBits) {
614 Operand val = bc2ir.popDouble();
615 RegisterOperand op0 = gc.temps.makeTempLong();
616 bc2ir.appendInstruction(Unary.create(DOUBLE_AS_LONG_BITS, op0, val));
617 bc2ir.pushDual(op0.copyD2U());
618 } else if (methodName == MagicNames.longBitsAsDouble) {
619 Operand val = bc2ir.popLong();
620 RegisterOperand op0 = gc.temps.makeTempDouble();
621 bc2ir.appendInstruction(Unary.create(LONG_BITS_AS_DOUBLE, op0, val));
622 bc2ir.pushDual(op0.copyD2U());
623 } else if (methodName == MagicNames.sqrt) {
624 TypeReference[] args = meth.getParameterTypes();
625 if (args[0] == TypeReference.Float) {
626 Operand val = bc2ir.popFloat();
627 RegisterOperand op0 = gc.temps.makeTempFloat();
628 bc2ir.appendInstruction(Unary.create(FLOAT_SQRT, op0, val));
629 bc2ir.push(op0.copyD2U());
630 } else if (args[0] == TypeReference.Double) {
631 Operand val = bc2ir.popDouble();
632 RegisterOperand op0 = gc.temps.makeTempDouble();
633 bc2ir.appendInstruction(Unary.create(DOUBLE_SQRT, op0, val));
634 bc2ir.pushDual(op0.copyD2U());
635 } else {
636 if (VM.VerifyAssertions)
637 VM._assert(false,"SQRT only handles Double or Float operands");
638 }
639 } else if (methodName == MagicNames.getObjectType) {
640 Operand val = bc2ir.popRef();
641 if(val.isObjectConstant()) {
642 bc2ir.push(new ObjectConstantOperand(val.getType().peekType(), Offset.zero()));
643 } else {
644 Operand guard = BC2IR.getGuard(val);
645 if (guard == null) {
646 // it's magic, so assume that it's OK....
647 guard = new TrueGuardOperand();
648 }
649 RegisterOperand tibPtr = gc.temps.makeTemp(TypeReference.TIB);
650 bc2ir.appendInstruction(GuardedUnary.create(GET_OBJ_TIB, tibPtr, val, guard));
651 RegisterOperand op0;
652 TypeReference argType = val.getType();
653 if (argType.isArrayType()) {
654 op0 = gc.temps.makeTemp(TypeReference.RVMArray);
655 } else {
656 if (argType == TypeReference.JavaLangObject ||
657 argType == TypeReference.JavaLangCloneable ||
658 argType == TypeReference.JavaIoSerializable) {
659 // could be an array or a class, so make op0 be a RVMType
660 op0 = gc.temps.makeTemp(TypeReference.Type);
661 } else {
662 op0 = gc.temps.makeTemp(TypeReference.Class);
663 }
664 }
665 bc2ir.markGuardlessNonNull(op0);
666 bc2ir.appendInstruction(Unary.create(GET_TYPE_FROM_TIB, op0, tibPtr.copyD2U()));
667 bc2ir.push(op0.copyD2U());
668 }
669 } else if (methodName == MagicNames.getArrayLength) {
670 Operand val = bc2ir.popRef();
671 RegisterOperand op0 = gc.temps.makeTempInt();
672 bc2ir.appendInstruction(GuardedUnary.create(ARRAYLENGTH, op0, val, new TrueGuardOperand()));
673 bc2ir.push(op0.copyD2U());
674 } else if (methodName == MagicNames.invokeClassInitializer) {
675 Instruction s = Call.create0(CALL, null, bc2ir.popRef(), null);
676 bc2ir.appendInstruction(s);
677 } else if ((methodName == MagicNames.invokeMethodReturningObject) ||
678 (methodName == MagicNames.invokeMethodReturningVoid) ||
679 (methodName == MagicNames.invokeMethodReturningLong) ||
680 (methodName == MagicNames.invokeMethodReturningDouble) ||
681 (methodName == MagicNames.invokeMethodReturningFloat) ||
682 (methodName == MagicNames.invokeMethodReturningInt)) {
683 Operand spills = bc2ir.popRef();
684 Operand fprmeta = bc2ir.popRef();
685 Operand fprs = bc2ir.popRef();
686 Operand gprs = bc2ir.popRef();
687 Operand code = bc2ir.popRef();
688 RegisterOperand res = null;
689 if (methodName == MagicNames.invokeMethodReturningObject) {
690 res = gc.temps.makeTemp(TypeReference.JavaLangObject);
691 bc2ir.push(res.copyD2U());
692 } else if (methodName == MagicNames.invokeMethodReturningLong) {
693 res = gc.temps.makeTemp(TypeReference.Long);
694 bc2ir.push(res.copyD2U(), TypeReference.Long);
695 } else if (methodName == MagicNames.invokeMethodReturningDouble) {
696 res = gc.temps.makeTempDouble();
697 bc2ir.push(res.copyD2U(), TypeReference.Double);
698 } else if (methodName == MagicNames.invokeMethodReturningFloat) {
699 res = gc.temps.makeTempFloat();
700 bc2ir.push(res.copyD2U(), TypeReference.Float);
701 } else if (methodName == MagicNames.invokeMethodReturningInt) {
702 res = gc.temps.makeTempInt();
703 bc2ir.push(res.copyD2U());
704 }
705 RVMField target = ArchEntrypoints.reflectiveMethodInvokerInstructionsField;
706 MethodOperand met = MethodOperand.STATIC(target);
707 Instruction s =
708 Call.create5(CALL, res, new AddressConstantOperand(target.getOffset()), met, code, gprs, fprs, fprmeta, spills);
709 bc2ir.appendInstruction(s);
710 } else if (methodName == MagicNames.saveThreadState) {
711 Operand p1 = bc2ir.popRef();
712 RVMField target = ArchEntrypoints.saveThreadStateInstructionsField;
713 MethodOperand mo = MethodOperand.STATIC(target);
714 bc2ir.appendInstruction(Call.create1(CALL, null, new AddressConstantOperand(target.getOffset()), mo, p1));
715 } else if (methodName == MagicNames.threadSwitch) {
716 Operand p2 = bc2ir.popRef();
717 Operand p1 = bc2ir.popRef();
718 RVMField target = ArchEntrypoints.threadSwitchInstructionsField;
719 MethodOperand mo = MethodOperand.STATIC(target);
720 bc2ir.appendInstruction(Call.create2(CALL, null, new AddressConstantOperand(target.getOffset()), mo, p1, p2));
721 } else if (methodName == MagicNames.restoreHardwareExceptionState) {
722 RVMField target = ArchEntrypoints.restoreHardwareExceptionStateInstructionsField;
723 MethodOperand mo = MethodOperand.STATIC(target);
724 bc2ir.appendInstruction(Call.create1(CALL,
725 null,
726 new AddressConstantOperand(target.getOffset()),
727 mo,
728 bc2ir.popRef()));
729 } else if (methodName == MagicNames.prepareInt) {
730 Operand offset = bc2ir.popAddress();
731 Operand base = bc2ir.popRef();
732 RegisterOperand val = gc.temps.makeTempInt();
733 bc2ir.appendInstruction(Prepare.create(PREPARE_INT, val, base, offset, null));
734 bc2ir.push(val.copyD2U());
735 } else if (methodName == MagicNames.prepareLong) {
736 Operand offset = bc2ir.popAddress();
737 Operand base = bc2ir.popRef();
738 RegisterOperand val = gc.temps.makeTempLong();
739 bc2ir.appendInstruction(Prepare.create(PREPARE_LONG, val, base, offset, null));
740 bc2ir.pushDual(val.copyD2U());
741 } else if (methodName == MagicNames.prepareObject) {
742 Operand offset = bc2ir.popAddress();
743 Operand base = bc2ir.popRef();
744 RegisterOperand val = gc.temps.makeTemp(TypeReference.JavaLangObject);
745 bc2ir.appendInstruction(Prepare.create(PREPARE_ADDR, val, base, offset, null));
746 bc2ir.push(val.copyD2U());
747 } else if (methodName == MagicNames.prepareAddress) {
748 Operand offset = bc2ir.popAddress();
749 Operand base = bc2ir.popRef();
750 RegisterOperand val = gc.temps.makeTemp(TypeReference.Address);
751 bc2ir.appendInstruction(Prepare.create(PREPARE_ADDR, val, base, offset, null));
752 bc2ir.push(val.copyD2U());
753 } else if (methodName == MagicNames.prepareWord) {
754 Operand offset = bc2ir.popAddress();
755 Operand base = bc2ir.popRef();
756 RegisterOperand val = gc.temps.makeTemp(TypeReference.Word);
757 bc2ir.appendInstruction(Prepare.create(PREPARE_ADDR, val, base, offset, null));
758 bc2ir.push(val.copyD2U());
759 } else if (methodName == MagicNames.attemptInt) {
760 Operand newVal = bc2ir.popInt();
761 Operand oldVal = bc2ir.popInt();
762 Operand offset = bc2ir.popAddress();
763 Operand base = bc2ir.popRef();
764 RegisterOperand test = gc.temps.makeTempBoolean();
765 bc2ir.appendInstruction(Attempt.create(ATTEMPT_INT, test, base, offset, oldVal, newVal, null));
766 bc2ir.push(test.copyD2U());
767 } else if (methodName == MagicNames.attemptLong) {
768 Operand newVal = bc2ir.popLong();
769 Operand oldVal = bc2ir.popLong();
770 Operand offset = bc2ir.popAddress();
771 Operand base = bc2ir.popRef();
772 RegisterOperand test = gc.temps.makeTempBoolean();
773 bc2ir.appendInstruction(Attempt.create(ATTEMPT_LONG, test, base, offset, oldVal, newVal, null));
774 bc2ir.push(test.copyD2U());
775 } else if (methodName == MagicNames.attemptObject) {
776 Operand newVal = bc2ir.popRef();
777 Operand oldVal = bc2ir.popRef();
778 Operand offset = bc2ir.popAddress();
779 Operand base = bc2ir.popRef();
780 RegisterOperand test = gc.temps.makeTempBoolean();
781 bc2ir.appendInstruction(Attempt.create(ATTEMPT_ADDR, test, base, offset, oldVal, newVal, null));
782 bc2ir.push(test.copyD2U());
783 } else if (methodName == MagicNames.attemptAddress) {
784 Operand newVal = bc2ir.popAddress();
785 Operand oldVal = bc2ir.popAddress();
786 Operand offset = bc2ir.popAddress();
787 Operand base = bc2ir.popRef();
788 RegisterOperand test = gc.temps.makeTempBoolean();
789 bc2ir.appendInstruction(Attempt.create(ATTEMPT_ADDR, test, base, offset, oldVal, newVal, null));
790 bc2ir.push(test.copyD2U());
791 } else if (methodName == MagicNames.attemptWord) {
792 Operand newVal = bc2ir.pop();
793 Operand oldVal = bc2ir.pop();
794 Operand offset = bc2ir.popAddress();
795 Operand base = bc2ir.popRef();
796 RegisterOperand test = gc.temps.makeTempBoolean();
797 bc2ir.appendInstruction(Attempt.create(ATTEMPT_ADDR, test, base, offset, oldVal, newVal, null));
798 bc2ir.push(test.copyD2U());
799 } else if (generatePolymorphicMagic(bc2ir, gc, meth, methodName)) {
800 return true;
801 } else if (methodName == MagicNames.getTimeBase) {
802 RegisterOperand op0 = gc.temps.makeTempLong();
803 bc2ir.appendInstruction(Nullary.create(GET_TIME_BASE, op0));
804 bc2ir.pushDual(op0.copyD2U());
805 } else if (methodName == MagicNames.getInlineDepth) {
806 bc2ir.push(new IntConstantOperand(gc.inlineSequence.getInlineDepth()));
807 } else if (methodName == MagicNames.isConstantParameter) {
808 Operand requestedOperand = bc2ir.pop();
809 if (!(requestedOperand instanceof IntConstantOperand)) {
810 throw new OptimizingCompilerException("Must supply constant to Magic.isConstantParameter");
811 }
812 int requested = ((IntConstantOperand)(requestedOperand)).value;
813 boolean isConstant = gc.arguments[requested].isConstant();
814 bc2ir.push(new IntConstantOperand(isConstant ? 1 : 0));
815 } else {
816 // Wasn't machine-independent, so try the machine-dependent magics next.
817 return GenerateMachineSpecificMagic.generateMagic(bc2ir, gc, meth);
818 }
819 return true;
820 } // generateMagic
821
822 // Generate magic where the untype operational semantics is identified by name.
823 // The operands' types are determined from the method signature.
824 //
825 static boolean generatePolymorphicMagic(BC2IR bc2ir, GenerationContext gc, MethodReference meth,
826 Atom methodName) {
827 TypeReference resultType = meth.getReturnType();
828 if (methodName == MagicNames.wordFromInt || methodName == MagicNames.wordFromIntSignExtend) {
829 RegisterOperand reg = gc.temps.makeTemp(resultType);
830 bc2ir.appendInstruction(Unary.create(INT_2ADDRSigExt, reg, bc2ir.popInt()));
831 bc2ir.push(reg.copyD2U());
832 } else if (methodName == MagicNames.wordFromIntZeroExtend) {
833 RegisterOperand reg = gc.temps.makeTemp(resultType);
834 bc2ir.appendInstruction(Unary.create(INT_2ADDRZerExt, reg, bc2ir.popInt()));
835 bc2ir.push(reg.copyD2U());
836 } else if (methodName == MagicNames.wordFromLong) {
837 RegisterOperand reg = gc.temps.makeTemp(resultType);
838 bc2ir.appendInstruction(Unary.create(LONG_2ADDR, reg, bc2ir.popLong()));
839 bc2ir.push(reg.copyD2U());
840 } else if (methodName == MagicNames.wordToInt) {
841 RegisterOperand reg = gc.temps.makeTempInt();
842 bc2ir.appendInstruction(Unary.create(ADDR_2INT, reg, bc2ir.popAddress()));
843 bc2ir.push(reg.copyD2U());
844 } else if (methodName == MagicNames.wordToLong) {
845 RegisterOperand lreg = gc.temps.makeTempLong();
846 bc2ir.appendInstruction(Unary.create(ADDR_2LONG, lreg, bc2ir.popAddress()));
847 bc2ir.pushDual(lreg.copyD2U());
848 } else if (methodName == MagicNames.wordToWord) {
849 RegisterOperand reg = gc.temps.makeTemp(TypeReference.Word);
850 bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popAddress()));
851 bc2ir.push(reg.copyD2U());
852 } else if (methodName == MagicNames.wordToAddress) {
853 RegisterOperand reg = gc.temps.makeTemp(TypeReference.Address);
854 bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popRef()));
855 bc2ir.push(reg.copyD2U());
856 } else if (methodName == MagicNames.wordToObject) {
857 RegisterOperand reg = gc.temps.makeTemp(TypeReference.JavaLangObject);
858 bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popRef()));
859 bc2ir.push(reg.copyD2U());
860 } else if (methodName == MagicNames.wordToObjectReference || methodName == MagicNames.wordFromObject) {
861 RegisterOperand reg = gc.temps.makeTemp(TypeReference.ObjectReference);
862 bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popRef()));
863 bc2ir.push(reg.copyD2U());
864 } else if (methodName == MagicNames.wordToOffset) {
865 RegisterOperand reg = gc.temps.makeTemp(TypeReference.Offset);
866 bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popAddress()));
867 bc2ir.push(reg.copyD2U());
868 } else if (methodName == MagicNames.wordToExtent) {
869 RegisterOperand reg = gc.temps.makeTemp(TypeReference.Extent);
870 bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popAddress()));
871 bc2ir.push(reg.copyD2U());
872 } else if (methodName == MagicNames.codeArrayAsObject) {
873 RegisterOperand reg = gc.temps.makeTemp(TypeReference.JavaLangObject);
874 bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.pop(TypeReference.CodeArray)));
875 bc2ir.push(reg.copyD2U());
876 } else if (methodName == MagicNames.tibAsObject) {
877 RegisterOperand reg = gc.temps.makeTemp(TypeReference.JavaLangObject);
878 bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.pop(TypeReference.TIB)));
879 bc2ir.push(reg.copyD2U());
880 } else if (methodName == MagicNames.wordPlus) {
881 Operand o2 = bc2ir.pop();
882 Operand o1 = bc2ir.pop();
883 RegisterOperand op0 = gc.temps.makeTemp(resultType);
884 if (VM.BuildFor64Addr && o2.isInt()) {
885 RegisterOperand op1 = gc.temps.makeTemp(resultType);
886 bc2ir.appendInstruction(Unary.create(INT_2ADDRSigExt, op1, o2));
887 bc2ir.appendInstruction(Binary.create(REF_ADD, op0, o1, op1.copyD2U()));
888 } else {
889 bc2ir.appendInstruction(Binary.create(REF_ADD, op0, o1, o2));
890 }
891 bc2ir.push(op0.copyD2U());
892 } else if (methodName == MagicNames.wordMinus) {
893 Operand o2 = bc2ir.pop();
894 Operand o1 = bc2ir.pop();
895 RegisterOperand op0 = gc.temps.makeTemp(resultType);
896 if (VM.BuildFor64Addr && o2.isInt()) {
897 RegisterOperand op1 = gc.temps.makeTemp(resultType);
898 bc2ir.appendInstruction(Unary.create(INT_2ADDRSigExt, op1, o2));
899 bc2ir.appendInstruction(Binary.create(REF_SUB, op0, o1, op1));
900 } else {
901 bc2ir.appendInstruction(Binary.create(REF_SUB, op0, o1, o2));
902 }
903 bc2ir.push(op0.copyD2U());
904 } else if (methodName == MagicNames.wordDiff) {
905 Operand o2 = bc2ir.pop();
906 Operand o1 = bc2ir.pop();
907 RegisterOperand op0 = gc.temps.makeTemp(resultType);
908 bc2ir.appendInstruction(Binary.create(REF_SUB, op0, o1, o2));
909 bc2ir.push(op0.copyD2U());
910 } else if (methodName == MagicNames.wordAnd) {
911 Operand o2 = bc2ir.pop();
912 Operand o1 = bc2ir.pop();
913 RegisterOperand op0 = gc.temps.makeTemp(resultType);
914 bc2ir.appendInstruction(Binary.create(REF_AND, op0, o1, o2));
915 bc2ir.push(op0.copyD2U());
916 } else if (methodName == MagicNames.wordOr) {
917 Operand o2 = bc2ir.pop();
918 Operand o1 = bc2ir.pop();
919 RegisterOperand op0 = gc.temps.makeTemp(resultType);
920 bc2ir.appendInstruction(Binary.create(REF_OR, op0, o1, o2));
921 bc2ir.push(op0.copyD2U());
922 } else if (methodName == MagicNames.wordXor) {
923 Operand o2 = bc2ir.pop();
924 Operand o1 = bc2ir.pop();
925 RegisterOperand op0 = gc.temps.makeTemp(resultType);
926 bc2ir.appendInstruction(Binary.create(REF_XOR, op0, o1, o2));
927 bc2ir.push(op0.copyD2U());
928 } else if (methodName == MagicNames.wordNot) {
929 Operand o1 = bc2ir.pop();
930 RegisterOperand op0 = gc.temps.makeTemp(resultType);
931 bc2ir.appendInstruction(Unary.create(REF_NOT, op0, o1));
932 bc2ir.push(op0.copyD2U());
933 } else if (methodName == MagicNames.wordZero || methodName == MagicNames.wordNull) {
934 RegisterOperand op0 = gc.temps.makeTemp(resultType);
935 bc2ir.appendInstruction(Move.create(REF_MOVE, op0, new AddressConstantOperand(Address.zero())));
936 bc2ir.push(op0.copyD2U());
937 } else if (methodName == MagicNames.wordOne) {
938 RegisterOperand op0 = gc.temps.makeTemp(resultType);
939 bc2ir.appendInstruction(Move.create(REF_MOVE, op0, new AddressConstantOperand(Address.fromIntZeroExtend(1))));
940 bc2ir.push(op0.copyD2U());
941 } else if (methodName == MagicNames.wordMax) {
942 RegisterOperand op0 = gc.temps.makeTemp(resultType);
943 bc2ir.appendInstruction(Move.create(REF_MOVE, op0, new AddressConstantOperand(Address.max())));
944 bc2ir.push(op0.copyD2U());
945 } else if (methodName == MagicNames.wordIsNull) {
946 RegisterOperand op0 = gc.temps.makeTemp(resultType);
947 bc2ir.appendInstruction(Move.create(REF_MOVE, op0, new AddressConstantOperand(Address.zero())));
948 ConditionOperand cond = ConditionOperand.EQUAL();
949 cmpHelper(bc2ir, gc, cond, op0.copyRO());
950 } else if (methodName == MagicNames.wordIsZero) {
951 RegisterOperand op0 = gc.temps.makeTemp(resultType);
952 bc2ir.appendInstruction(Move.create(REF_MOVE, op0, new AddressConstantOperand(Address.zero())));
953 ConditionOperand cond = ConditionOperand.EQUAL();
954 cmpHelper(bc2ir, gc, cond, op0.copyRO());
955 } else if (methodName == MagicNames.wordIsMax) {
956 RegisterOperand op0 = gc.temps.makeTemp(resultType);
957 bc2ir.appendInstruction(Move.create(REF_MOVE, op0, new AddressConstantOperand(Address.max())));
958 ConditionOperand cond = ConditionOperand.EQUAL();
959 cmpHelper(bc2ir, gc, cond, op0.copyRO());
960 } else if (methodName == MagicNames.wordEQ) {
961 ConditionOperand cond = ConditionOperand.EQUAL();
962 cmpHelper(bc2ir, gc, cond, null);
963 } else if (methodName == MagicNames.wordNE) {
964 ConditionOperand cond = ConditionOperand.NOT_EQUAL();
965 cmpHelper(bc2ir, gc, cond, null);
966 } else if (methodName == MagicNames.wordLT) {
967 ConditionOperand cond = ConditionOperand.LOWER();
968 cmpHelper(bc2ir, gc, cond, null);
969 } else if (methodName == MagicNames.wordLE) {
970 ConditionOperand cond = ConditionOperand.LOWER_EQUAL();
971 cmpHelper(bc2ir, gc, cond, null);
972 } else if (methodName == MagicNames.wordGT) {
973 ConditionOperand cond = ConditionOperand.HIGHER();
974 cmpHelper(bc2ir, gc, cond, null);
975 } else if (methodName == MagicNames.wordGE) {
976 ConditionOperand cond = ConditionOperand.HIGHER_EQUAL();
977 cmpHelper(bc2ir, gc, cond, null);
978 } else if (methodName == MagicNames.wordsLT) {
979 ConditionOperand cond = ConditionOperand.LESS();
980 cmpHelper(bc2ir, gc, cond, null);
981 } else if (methodName == MagicNames.wordsLE) {
982 ConditionOperand cond = ConditionOperand.LESS_EQUAL();
983 cmpHelper(bc2ir, gc, cond, null);
984 } else if (methodName == MagicNames.wordsGT) {
985 ConditionOperand cond = ConditionOperand.GREATER();
986 cmpHelper(bc2ir, gc, cond, null);
987 } else if (methodName == MagicNames.wordsGE) {
988 ConditionOperand cond = ConditionOperand.GREATER_EQUAL();
989 cmpHelper(bc2ir, gc, cond, null);
990 } else if (methodName == MagicNames.wordLsh) {
991 Operand op2 = bc2ir.popInt();
992 Operand op1 = bc2ir.popAddress();
993 RegisterOperand res = gc.temps.makeTemp(resultType);
994 bc2ir.appendInstruction(Binary.create(REF_SHL, res, op1, op2));
995 bc2ir.push(res.copyD2U());
996 } else if (methodName == MagicNames.wordRshl) {
997 Operand op2 = bc2ir.popInt();
998 Operand op1 = bc2ir.popAddress();
999 RegisterOperand res = gc.temps.makeTemp(resultType);
1000 bc2ir.appendInstruction(Binary.create(REF_USHR, res, op1, op2));
1001 bc2ir.push(res.copyD2U());
1002 } else if (methodName == MagicNames.wordRsha) {
1003 Operand op2 = bc2ir.popInt();
1004 Operand op1 = bc2ir.popAddress();
1005 RegisterOperand res = gc.temps.makeTemp(resultType);
1006 bc2ir.appendInstruction(Binary.create(REF_SHR, res, op1, op2));
1007 bc2ir.push(res.copyD2U());
1008 } else {
1009 return false;
1010 }
1011 return true;
1012 }
1013
1014 private static void cmpHelper(BC2IR bc2ir, GenerationContext gc, ConditionOperand cond,
1015 Operand given_o2) {
1016 Operand o2 = given_o2 == null ? bc2ir.pop() : given_o2;
1017 Operand o1 = bc2ir.pop();
1018 RegisterOperand res = gc.temps.makeTempInt();
1019 bc2ir.appendInstruction(BooleanCmp.create(BOOLEAN_CMP_ADDR,
1020 res.copyRO(),
1021 o1,
1022 o2,
1023 cond,
1024 new BranchProfileOperand()));
1025 bc2ir.push(res.copyD2U());
1026 }
1027
1028 private static LocationOperand mapToMetadata(Operand metadata) {
1029 if (metadata instanceof IntConstantOperand) {
1030 int index = ((IntConstantOperand) metadata).value;
1031 if (index == 0) return null;
1032 MemberReference mr = MemberReference.getMemberRef(index);
1033 return new LocationOperand(mr.asFieldReference());
1034 }
1035 return null;
1036 }
1037
1038 private static final int LOAD_OP = 1;
1039 private static final int PREPARE_OP = 2;
1040 private static final int STORE_OP = 3;
1041 private static final int ATTEMPT_OP = 4;
1042
1043 private static Operator getOperator(TypeReference type, int operatorClass)
1044 throws MagicNotImplementedException {
1045 if (operatorClass == LOAD_OP) {
1046 if (type == TypeReference.Address) return REF_LOAD;
1047 if (type == TypeReference.ObjectReference) return REF_LOAD;
1048 if (type == TypeReference.Word) return REF_LOAD;
1049 if (type == TypeReference.Offset) return REF_LOAD;
1050 if (type == TypeReference.Extent) return REF_LOAD;
1051 if (type == TypeReference.Int) return INT_LOAD;
1052 if (type == TypeReference.Byte) return BYTE_LOAD;
1053 if (type == TypeReference.Short) return SHORT_LOAD;
1054 if (type == TypeReference.Char) return USHORT_LOAD;
1055 if (type == TypeReference.Float) return FLOAT_LOAD;
1056 if (type == TypeReference.Double) return DOUBLE_LOAD;
1057 if (type == TypeReference.Long) return LONG_LOAD;
1058 } else if (operatorClass == PREPARE_OP) {
1059 if (type == TypeReference.Address) return PREPARE_ADDR;
1060 if (type == TypeReference.ObjectReference) return PREPARE_ADDR;
1061 if (type == TypeReference.Word) return PREPARE_ADDR;
1062 if (type == TypeReference.Int) return PREPARE_INT;
1063 if (type == TypeReference.Long) return PREPARE_LONG;
1064 } else if (operatorClass == ATTEMPT_OP) {
1065 if (type == TypeReference.Address) return ATTEMPT_ADDR;
1066 if (type == TypeReference.ObjectReference) return ATTEMPT_ADDR;
1067 if (type == TypeReference.Word) return ATTEMPT_ADDR;
1068 if (type == TypeReference.Int) return ATTEMPT_INT;
1069 if (type == TypeReference.Long) return ATTEMPT_LONG;
1070 } else if (operatorClass == STORE_OP) {
1071 if (type == TypeReference.Address) return REF_STORE;
1072 if (type == TypeReference.ObjectReference) return REF_STORE;
1073 if (type == TypeReference.Word) return REF_STORE;
1074 if (type == TypeReference.Offset) return REF_STORE;
1075 if (type == TypeReference.Extent) return REF_STORE;
1076 if (type == TypeReference.Int) return INT_STORE;
1077 if (type == TypeReference.Byte || type == TypeReference.Boolean) return BYTE_STORE;
1078 if (type == TypeReference.Short) return SHORT_STORE;
1079 if (type == TypeReference.Char) return SHORT_STORE;
1080 if (type == TypeReference.Float) return FLOAT_STORE;
1081 if (type == TypeReference.Double) return DOUBLE_STORE;
1082 if (type == TypeReference.Long) return LONG_STORE;
1083 }
1084 String msg = " Unexpected call to getOperator";
1085 throw MagicNotImplementedException.UNEXPECTED(msg);
1086 }
1087
1088 private static boolean isLoad(Atom methodName) {
1089 return isPrefix(MagicNames.loadPrefix, methodName.toByteArray());
1090 }
1091
1092 private static boolean isPrepare(Atom methodName) {
1093 return isPrefix(MagicNames.preparePrefix, methodName.toByteArray());
1094 }
1095
1096 /**
1097 * Is string <code>a</code> a prefix of string
1098 * <code>b</code>. String <code>b</code> is encoded as an ASCII byte
1099 * array.
1100 *
1101 * @param prefix Prefix atom
1102 * @param b String which may contain prefix, encoded as an ASCII
1103 * byte array.
1104 * @return <code>true</code> if <code>a</code> is a prefix of
1105 * <code>b</code>
1106 */
1107 @Interruptible
1108 private static boolean isPrefix(Atom prefix, byte[] b) {
1109 byte[] a = prefix.toByteArray();
1110 int aLen = a.length;
1111 if (aLen > b.length) {
1112 return false;
1113 }
1114 for (int i = 0; i < aLen; i++) {
1115 if (a[i] != b[i]) {
1116 return false;
1117 }
1118 }
1119 return true;
1120 }
1121
1122 }