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.FENCE; 032 import static org.jikesrvm.compilers.opt.ir.Operators.FLOAT_AS_INT_BITS; 033 import static org.jikesrvm.compilers.opt.ir.Operators.FLOAT_LOAD; 034 import static org.jikesrvm.compilers.opt.ir.Operators.FLOAT_SQRT; 035 import static org.jikesrvm.compilers.opt.ir.Operators.FLOAT_STORE; 036 import static org.jikesrvm.compilers.opt.ir.Operators.GET_OBJ_TIB; 037 import static org.jikesrvm.compilers.opt.ir.Operators.GET_TIME_BASE; 038 import static org.jikesrvm.compilers.opt.ir.Operators.GET_TYPE_FROM_TIB; 039 import static org.jikesrvm.compilers.opt.ir.Operators.INT_2ADDRSigExt; 040 import static org.jikesrvm.compilers.opt.ir.Operators.INT_2ADDRZerExt; 041 import static org.jikesrvm.compilers.opt.ir.Operators.INT_ADD; 042 import static org.jikesrvm.compilers.opt.ir.Operators.INT_BITS_AS_FLOAT; 043 import static org.jikesrvm.compilers.opt.ir.Operators.INT_LOAD; 044 import static org.jikesrvm.compilers.opt.ir.Operators.INT_SHL; 045 import static org.jikesrvm.compilers.opt.ir.Operators.INT_STORE; 046 import static org.jikesrvm.compilers.opt.ir.Operators.LONG_2ADDR; 047 import static org.jikesrvm.compilers.opt.ir.Operators.LONG_BITS_AS_DOUBLE; 048 import static org.jikesrvm.compilers.opt.ir.Operators.LONG_LOAD; 049 import static org.jikesrvm.compilers.opt.ir.Operators.LONG_STORE; 050 import static org.jikesrvm.compilers.opt.ir.Operators.PREPARE_ADDR; 051 import static org.jikesrvm.compilers.opt.ir.Operators.PREPARE_INT; 052 import static org.jikesrvm.compilers.opt.ir.Operators.PREPARE_LONG; 053 import static org.jikesrvm.compilers.opt.ir.Operators.READ_CEILING; 054 import static org.jikesrvm.compilers.opt.ir.Operators.REF_ADD; 055 import static org.jikesrvm.compilers.opt.ir.Operators.REF_AND; 056 import static org.jikesrvm.compilers.opt.ir.Operators.REF_LOAD; 057 import static org.jikesrvm.compilers.opt.ir.Operators.REF_MOVE; 058 import static org.jikesrvm.compilers.opt.ir.Operators.REF_NOT; 059 import static org.jikesrvm.compilers.opt.ir.Operators.REF_OR; 060 import static org.jikesrvm.compilers.opt.ir.Operators.REF_SHL; 061 import static org.jikesrvm.compilers.opt.ir.Operators.REF_SHR; 062 import static org.jikesrvm.compilers.opt.ir.Operators.REF_STORE; 063 import static org.jikesrvm.compilers.opt.ir.Operators.REF_SUB; 064 import static org.jikesrvm.compilers.opt.ir.Operators.REF_USHR; 065 import static org.jikesrvm.compilers.opt.ir.Operators.REF_XOR; 066 import static org.jikesrvm.compilers.opt.ir.Operators.SHORT_LOAD; 067 import static org.jikesrvm.compilers.opt.ir.Operators.SHORT_STORE; 068 import static org.jikesrvm.compilers.opt.ir.Operators.SYSCALL; 069 import static org.jikesrvm.compilers.opt.ir.Operators.UBYTE_LOAD; 070 import static org.jikesrvm.compilers.opt.ir.Operators.USHORT_LOAD; 071 import static org.jikesrvm.compilers.opt.ir.Operators.WRITE_FLOOR; 072 073 import org.jikesrvm.VM; 074 import org.jikesrvm.ArchitectureSpecificOpt.GenerateMachineSpecificMagic; 075 import org.jikesrvm.classloader.Atom; 076 import org.jikesrvm.classloader.RVMField; 077 import org.jikesrvm.classloader.MemberReference; 078 import org.jikesrvm.classloader.MethodReference; 079 import org.jikesrvm.classloader.TypeReference; 080 import org.jikesrvm.compilers.opt.MagicNotImplementedException; 081 import org.jikesrvm.compilers.opt.OptimizingCompilerException; 082 import org.jikesrvm.compilers.opt.ir.Attempt; 083 import org.jikesrvm.compilers.opt.ir.Binary; 084 import org.jikesrvm.compilers.opt.ir.BooleanCmp; 085 import org.jikesrvm.compilers.opt.ir.Call; 086 import org.jikesrvm.compilers.opt.ir.Empty; 087 import org.jikesrvm.compilers.opt.ir.GuardedUnary; 088 import org.jikesrvm.compilers.opt.ir.Instruction; 089 import org.jikesrvm.compilers.opt.ir.Load; 090 import org.jikesrvm.compilers.opt.ir.Move; 091 import org.jikesrvm.compilers.opt.ir.Nullary; 092 import org.jikesrvm.compilers.opt.ir.Operator; 093 import org.jikesrvm.compilers.opt.ir.Prepare; 094 import org.jikesrvm.compilers.opt.ir.Store; 095 import org.jikesrvm.compilers.opt.ir.Unary; 096 import org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand; 097 import org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand; 098 import org.jikesrvm.compilers.opt.ir.operand.ConditionOperand; 099 import org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand; 100 import org.jikesrvm.compilers.opt.ir.operand.LocationOperand; 101 import org.jikesrvm.compilers.opt.ir.operand.MethodOperand; 102 import org.jikesrvm.compilers.opt.ir.operand.ObjectConstantOperand; 103 import org.jikesrvm.compilers.opt.ir.operand.Operand; 104 import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand; 105 import org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand; 106 import org.jikesrvm.objectmodel.TIBLayoutConstants; 107 import org.jikesrvm.runtime.ArchEntrypoints; 108 import org.jikesrvm.runtime.MagicNames; 109 import org.vmmagic.pragma.Interruptible; 110 import org.vmmagic.unboxed.Address; 111 import org.vmmagic.unboxed.Offset; 112 113 /** 114 * This class implements the non-machine-specific magics for the opt compiler. 115 * By non-machine-specific we mean that the IR generated to implement the magic 116 * is independent of the target-architecture. 117 * It does not mean that the eventual MIR that implements the magic 118 * won't differ from architecture to architecture. 119 */ 120 public class GenerateMagic implements TIBLayoutConstants { 121 122 /** 123 * "Semantic inlining" of methods of the Magic class. 124 * Based on the methodName, generate a sequence of opt instructions 125 * that implement the magic, updating the expression stack as necessary. 126 * 127 * @param bc2ir the bc2ir object that is generating the 128 * ir containing this magic 129 * @param gc must be bc2ir.gc 130 * @param meth the RVMMethod that is the magic method 131 */ 132 static boolean generateMagic(BC2IR bc2ir, GenerationContext gc, MethodReference meth) 133 throws MagicNotImplementedException { 134 135 if (gc.method.hasNoInlinePragma()) gc.allocFrame = true; 136 137 // HACK: Don't schedule any bbs containing unsafe magics. 138 // TODO: move this to individual magics that are unsafe. 139 // -- igor 08/13/1999 140 bc2ir.markBBUnsafeForScheduling(); 141 Atom methodName = meth.getName(); 142 143 boolean address = (meth.getType() == TypeReference.Address); 144 145 // Address magic 146 TypeReference[] types = meth.getParameterTypes(); 147 TypeReference returnType = meth.getReturnType(); 148 149 if (address && isLoad(methodName)) { 150 // LOAD 151 Operand offset = (types.length == 0) ? new AddressConstantOperand(Address.zero()) : bc2ir.popAddress(); 152 Operand base = bc2ir.popAddress(); 153 RegisterOperand result = gc.temps.makeTemp(returnType); 154 bc2ir.appendInstruction(Load.create(getOperator(returnType, LOAD_OP), result, base, offset, null)); 155 bc2ir.push(result.copyD2U(), returnType); 156 157 } else if (address && isPrepare(methodName)) { 158 // PREPARE 159 Operand offset = (types.length == 0) ? new AddressConstantOperand(Address.zero()) : bc2ir.popAddress(); 160 Operand base = bc2ir.popAddress(); 161 RegisterOperand result = gc.temps.makeTemp(returnType); 162 bc2ir.appendInstruction(Prepare.create(getOperator(returnType, PREPARE_OP), result, base, offset, null)); 163 bc2ir.push(result.copyD2U(), returnType); 164 165 } else if (address && methodName == MagicNames.attempt) { 166 // ATTEMPT 167 TypeReference attemptType = types[0]; 168 169 Operand offset = (types.length == 2) ? new AddressConstantOperand(Address.zero()) : bc2ir.popAddress(); 170 171 Operand newVal = bc2ir.pop(); 172 Operand oldVal = bc2ir.pop(); 173 Operand base = bc2ir.popAddress(); 174 RegisterOperand test = gc.temps.makeTempInt(); 175 bc2ir.appendInstruction(Attempt.create(getOperator(attemptType, ATTEMPT_OP), 176 test, 177 base, 178 offset, 179 oldVal, 180 newVal, 181 null)); 182 bc2ir.push(test.copyD2U(), returnType); 183 184 } else if (address && methodName == MagicNames.store) { 185 // STORE 186 TypeReference storeType = types[0]; 187 188 Operand offset = (types.length == 1) ? new AddressConstantOperand(Address.zero()) : bc2ir.popAddress(); 189 190 Operand val = bc2ir.pop(storeType); 191 Operand base = bc2ir.popAddress(); 192 bc2ir.appendInstruction(Store.create(getOperator(storeType, STORE_OP), val, base, offset, null)); 193 194 } else if (methodName == MagicNames.getThreadRegister) { 195 RegisterOperand rop = gc.temps.makeTROp(); 196 bc2ir.markGuardlessNonNull(rop); 197 bc2ir.push(rop); 198 } else if (methodName == MagicNames.setThreadRegister) { 199 Operand val = bc2ir.popRef(); 200 if (val instanceof RegisterOperand) { 201 bc2ir.appendInstruction(Move.create(REF_MOVE, gc.temps.makeTROp(), val)); 202 } else { 203 String msg = " Unexpected operand Magic.setThreadRegister"; 204 throw MagicNotImplementedException.UNEXPECTED(msg); 205 } 206 } else if (methodName == MagicNames.addressArrayCreate) { 207 Instruction s = bc2ir.generateAnewarray(null, meth.getType().getArrayElementType()); 208 bc2ir.appendInstruction(s); 209 } else if (methodName == MagicNames.addressArrayLength) { 210 Operand op1 = bc2ir.pop(); 211 bc2ir.clearCurrentGuard(); 212 if (bc2ir.do_NullCheck(op1)) { 213 return true; 214 } 215 RegisterOperand t = gc.temps.makeTempInt(); 216 Instruction s = GuardedUnary.create(ARRAYLENGTH, t, op1, bc2ir.getCurrentGuard()); 217 bc2ir.push(t.copyD2U()); 218 bc2ir.appendInstruction(s); 219 } else if (methodName == MagicNames.addressArrayGet) { 220 TypeReference elementType = meth.getReturnType(); 221 Operand index = bc2ir.popInt(); 222 Operand ref = bc2ir.popRef(); 223 RegisterOperand offsetI = gc.temps.makeTempInt(); 224 RegisterOperand offset = gc.temps.makeTempOffset(); 225 RegisterOperand result; 226 if (meth.getType().isCodeArrayType()) { 227 if (VM.BuildForIA32) { 228 result = gc.temps.makeTemp(TypeReference.Byte); 229 bc2ir.appendInstruction(Load.create(BYTE_LOAD, 230 result, 231 ref, 232 index, 233 new LocationOperand(elementType), 234 new TrueGuardOperand())); 235 } else if (VM.BuildForPowerPC) { 236 result = gc.temps.makeTemp(TypeReference.Int); 237 bc2ir.appendInstruction(Binary.create(INT_SHL, offsetI, index, new IntConstantOperand(LOG_BYTES_IN_INT))); 238 bc2ir.appendInstruction(Unary.create(INT_2ADDRZerExt, offset, offsetI.copy())); 239 bc2ir.appendInstruction(Load.create(INT_LOAD, 240 result, 241 ref, 242 offset.copy(), 243 new LocationOperand(elementType), 244 new TrueGuardOperand())); 245 } 246 } else { 247 result = gc.temps.makeTemp(elementType); 248 bc2ir.appendInstruction(Binary.create(INT_SHL, 249 offsetI, 250 index, 251 new IntConstantOperand(LOG_BYTES_IN_ADDRESS))); 252 bc2ir.appendInstruction(Unary.create(INT_2ADDRZerExt, offset, offsetI.copy())); 253 bc2ir.appendInstruction(Load.create(REF_LOAD, 254 result, 255 ref, 256 offset.copy(), 257 new LocationOperand(elementType), 258 new TrueGuardOperand())); 259 } 260 bc2ir.push(result.copyD2U()); 261 } else if (methodName == MagicNames.addressArraySet) { 262 TypeReference elementType = meth.getParameterTypes()[1]; 263 Operand val = bc2ir.pop(); 264 Operand index = bc2ir.popInt(); 265 Operand ref = bc2ir.popRef(); 266 RegisterOperand offsetI = gc.temps.makeTempInt(); 267 RegisterOperand offset = gc.temps.makeTempOffset(); 268 if (meth.getType().isCodeArrayType()) { 269 if (VM.BuildForIA32) { 270 bc2ir.appendInstruction(Store.create(BYTE_STORE, 271 val, 272 ref, 273 index, 274 new LocationOperand(elementType), 275 new TrueGuardOperand())); 276 } else if (VM.BuildForPowerPC) { 277 bc2ir.appendInstruction(Binary.create(INT_SHL, offsetI, index, new IntConstantOperand(LOG_BYTES_IN_INT))); 278 bc2ir.appendInstruction(Unary.create(INT_2ADDRZerExt, offset, offsetI.copy())); 279 bc2ir.appendInstruction(Store.create(INT_STORE, 280 val, 281 ref, 282 offset.copy(), 283 new LocationOperand(elementType), 284 new TrueGuardOperand())); 285 } 286 } else { 287 bc2ir.appendInstruction(Binary.create(INT_SHL, 288 offsetI, 289 index, 290 new IntConstantOperand(LOG_BYTES_IN_ADDRESS))); 291 bc2ir.appendInstruction(Unary.create(INT_2ADDRZerExt, offset, offsetI.copy())); 292 bc2ir.appendInstruction(Store.create(REF_STORE, 293 val, 294 ref, 295 offset.copy(), 296 new LocationOperand(elementType), 297 new TrueGuardOperand())); 298 } 299 } else if (methodName == MagicNames.getIntAtOffset) { 300 Operand offset = bc2ir.popAddress(); 301 Operand object = bc2ir.popRef(); 302 RegisterOperand val = gc.temps.makeTempInt(); 303 bc2ir.appendInstruction(Load.create(INT_LOAD, val, object, offset, null)); 304 bc2ir.push(val.copyD2U()); 305 } else if (methodName == MagicNames.setIntAtOffset) { 306 LocationOperand loc = null; 307 if (meth.getParameterTypes().length == 4) { 308 loc = mapToMetadata(bc2ir.popInt()); 309 } 310 Operand val = bc2ir.popInt(); 311 Operand offset = bc2ir.popAddress(); 312 Operand object = bc2ir.popRef(); 313 bc2ir.appendInstruction(Store.create(INT_STORE, val, object, offset, loc)); 314 } else if (methodName == MagicNames.getFloatAtOffset) { 315 Operand offset = bc2ir.popAddress(); 316 Operand object = bc2ir.popRef(); 317 RegisterOperand val = gc.temps.makeTempFloat(); 318 bc2ir.appendInstruction(Load.create(FLOAT_LOAD, val, object, offset, null)); 319 bc2ir.push(val.copyD2U()); 320 } else if (methodName == MagicNames.setFloatAtOffset) { 321 LocationOperand loc = null; 322 if (meth.getParameterTypes().length == 4) { 323 loc = mapToMetadata(bc2ir.popInt()); 324 } 325 Operand val = bc2ir.popFloat(); 326 Operand offset = bc2ir.popAddress(); 327 Operand object = bc2ir.popRef(); 328 bc2ir.appendInstruction(Store.create(FLOAT_STORE, val, object, offset, loc)); 329 } else if (methodName == MagicNames.getWordAtOffset) { 330 LocationOperand loc = null; 331 if (meth.getParameterTypes().length == 3) { 332 loc = mapToMetadata(bc2ir.popInt()); 333 } 334 Operand offset = bc2ir.popAddress(); 335 Operand object = bc2ir.popRef(); 336 RegisterOperand val = gc.temps.makeTemp(TypeReference.Word); 337 bc2ir.appendInstruction(Load.create(REF_LOAD, val, object, offset, loc)); 338 bc2ir.push(val.copyD2U()); 339 } else if (methodName == MagicNames.getAddressAtOffset) { 340 LocationOperand loc = null; 341 if (meth.getParameterTypes().length == 3) { 342 loc = mapToMetadata(bc2ir.popInt()); 343 } 344 Operand offset = bc2ir.popAddress(); 345 Operand object = bc2ir.popRef(); 346 RegisterOperand val = gc.temps.makeTemp(TypeReference.Address); 347 bc2ir.appendInstruction(Load.create(REF_LOAD, val, object, offset, loc)); 348 bc2ir.push(val.copyD2U()); 349 } else if (methodName == MagicNames.getExtentAtOffset) { 350 LocationOperand loc = null; 351 if (meth.getParameterTypes().length == 3) { 352 loc = mapToMetadata(bc2ir.popInt()); 353 } 354 Operand offset = bc2ir.popAddress(); 355 Operand object = bc2ir.popRef(); 356 RegisterOperand val = gc.temps.makeTemp(TypeReference.Extent); 357 bc2ir.appendInstruction(Load.create(REF_LOAD, val, object, offset, loc)); 358 bc2ir.push(val.copyD2U()); 359 } else if (methodName == MagicNames.getOffsetAtOffset) { 360 LocationOperand loc = null; 361 if (meth.getParameterTypes().length == 3) { 362 loc = mapToMetadata(bc2ir.popInt()); 363 } 364 Operand offset = bc2ir.popAddress(); 365 Operand object = bc2ir.popRef(); 366 RegisterOperand val = gc.temps.makeTemp(TypeReference.Offset); 367 bc2ir.appendInstruction(Load.create(REF_LOAD, val, object, offset, loc)); 368 bc2ir.push(val.copyD2U()); 369 } else if (methodName == MagicNames.setWordAtOffset || 370 methodName == MagicNames.setAddressAtOffset || 371 methodName == MagicNames.setOffsetAtOffset || 372 methodName == MagicNames.setExtentAtOffset) { 373 LocationOperand loc = null; 374 if (meth.getParameterTypes().length == 4) { 375 loc = mapToMetadata(bc2ir.popInt()); 376 } 377 Operand val = bc2ir.popRef(); 378 Operand offset = bc2ir.popAddress(); 379 Operand object = bc2ir.popRef(); 380 bc2ir.appendInstruction(Store.create(REF_STORE, val, object, offset, loc)); 381 } else if (methodName == MagicNames.getLongAtOffset) { 382 Operand offset = bc2ir.popAddress(); 383 Operand object = bc2ir.popRef(); 384 RegisterOperand val = gc.temps.makeTempLong(); 385 bc2ir.appendInstruction(Load.create(LONG_LOAD, val, object, offset, null)); 386 bc2ir.pushDual(val.copyD2U()); 387 } else if (methodName == MagicNames.setLongAtOffset) { 388 LocationOperand loc = null; 389 if (meth.getParameterTypes().length == 4) { 390 loc = mapToMetadata(bc2ir.popInt()); 391 } 392 Operand val = bc2ir.popLong(); 393 Operand offset = bc2ir.popAddress(); 394 Operand object = bc2ir.popRef(); 395 bc2ir.appendInstruction(Store.create(LONG_STORE, val, object, offset, loc)); 396 } else if (methodName == MagicNames.getDoubleAtOffset) { 397 Operand offset = bc2ir.popAddress(); 398 Operand object = bc2ir.popRef(); 399 RegisterOperand val = gc.temps.makeTempDouble(); 400 bc2ir.appendInstruction(Load.create(DOUBLE_LOAD, val, object, offset, null)); 401 bc2ir.pushDual(val.copyD2U()); 402 } else if (methodName == MagicNames.setDoubleAtOffset) { 403 LocationOperand loc = null; 404 if (meth.getParameterTypes().length == 4) { 405 loc = mapToMetadata(bc2ir.popInt()); 406 } 407 Operand val = bc2ir.popDouble(); 408 Operand offset = bc2ir.popAddress(); 409 Operand object = bc2ir.popRef(); 410 bc2ir.appendInstruction(Store.create(DOUBLE_STORE, val, object, offset, loc)); 411 } else if (methodName == MagicNames.getObjectAtOffset) { 412 LocationOperand loc = null; 413 if (meth.getParameterTypes().length == 3) { 414 loc = mapToMetadata(bc2ir.popInt()); 415 } 416 Operand offset = bc2ir.popAddress(); 417 Operand object = bc2ir.popRef(); 418 RegisterOperand val = gc.temps.makeTemp(TypeReference.JavaLangObject); 419 bc2ir.appendInstruction(Load.create(REF_LOAD, val, object, offset, loc)); 420 bc2ir.push(val.copyD2U()); 421 } else if (methodName == MagicNames.getTIBAtOffset) { 422 Operand offset = bc2ir.popAddress(); 423 Operand object = bc2ir.popRef(); 424 RegisterOperand val = gc.temps.makeTemp(TypeReference.TIB); 425 bc2ir.appendInstruction(Load.create(REF_LOAD, val, object, offset, null)); 426 bc2ir.push(val.copyD2U()); 427 } else if (methodName == MagicNames.setObjectAtOffset) { 428 LocationOperand loc = null; 429 if (meth.getParameterTypes().length == 4) { 430 loc = mapToMetadata(bc2ir.popInt()); 431 } 432 Operand val = bc2ir.popRef(); 433 Operand offset = bc2ir.popAddress(); 434 Operand object = bc2ir.popRef(); 435 bc2ir.appendInstruction(Store.create(REF_STORE, val, object, offset, loc)); 436 } else if (methodName == MagicNames.getByteAtOffset) { 437 Operand offset = bc2ir.popAddress(); 438 Operand object = bc2ir.popRef(); 439 RegisterOperand val = gc.temps.makeTemp(TypeReference.Byte); 440 bc2ir.appendInstruction(Load.create(BYTE_LOAD, val, object, offset, null)); 441 bc2ir.push(val.copyD2U()); 442 } else if (methodName == MagicNames.getUnsignedByteAtOffset) { 443 Operand offset = bc2ir.popAddress(); 444 Operand object = bc2ir.popRef(); 445 RegisterOperand val = gc.temps.makeTemp(TypeReference.Byte); 446 bc2ir.appendInstruction(Load.create(UBYTE_LOAD, val, object, offset, null)); 447 bc2ir.push(val.copyD2U()); 448 } else if (methodName == MagicNames.setByteAtOffset || methodName == MagicNames.setBooleanAtOffset) { 449 LocationOperand loc = null; 450 if (meth.getParameterTypes().length == 4) { 451 loc = mapToMetadata(bc2ir.popInt()); 452 } 453 Operand val = bc2ir.popInt(); 454 Operand offset = bc2ir.popAddress(); 455 Operand object = bc2ir.popRef(); 456 bc2ir.appendInstruction(Store.create(BYTE_STORE, val, object, offset, loc)); 457 } else if (methodName == MagicNames.getShortAtOffset) { 458 Operand offset = bc2ir.popAddress(); 459 Operand object = bc2ir.popRef(); 460 RegisterOperand val = gc.temps.makeTemp(TypeReference.Char); 461 bc2ir.appendInstruction(Load.create(SHORT_LOAD, val, object, offset, null)); 462 bc2ir.push(val.copyD2U()); 463 } else if (methodName == MagicNames.getCharAtOffset) { 464 Operand offset = bc2ir.popAddress(); 465 Operand object = bc2ir.popRef(); 466 RegisterOperand val = gc.temps.makeTemp(TypeReference.Char); 467 bc2ir.appendInstruction(Load.create(USHORT_LOAD, val, object, offset, null)); 468 bc2ir.push(val.copyD2U()); 469 } else if (methodName == MagicNames.setCharAtOffset || methodName == MagicNames.setShortAtOffset) { 470 LocationOperand loc = null; 471 if (meth.getParameterTypes().length == 4) { 472 loc = mapToMetadata(bc2ir.popInt()); 473 } 474 Operand val = bc2ir.popInt(); 475 Operand offset = bc2ir.popAddress(); 476 Operand object = bc2ir.popRef(); 477 bc2ir.appendInstruction(Store.create(SHORT_STORE, val, object, offset, loc)); 478 } else if (methodName == MagicNames.getMemoryInt) { 479 Operand memAddr = bc2ir.popAddress(); 480 RegisterOperand val = gc.temps.makeTempInt(); 481 bc2ir.appendInstruction(Load.create(INT_LOAD, val, memAddr, new AddressConstantOperand(Offset.zero()), null)); 482 bc2ir.push(val.copyD2U()); 483 } else if (methodName == MagicNames.getMemoryWord) { 484 Operand memAddr = bc2ir.popAddress(); 485 RegisterOperand val = gc.temps.makeTemp(TypeReference.Word); 486 bc2ir.appendInstruction(Load.create(REF_LOAD, val, memAddr, new AddressConstantOperand(Offset.zero()), null)); 487 bc2ir.push(val.copyD2U()); 488 } else if (methodName == MagicNames.getMemoryAddress) { 489 Operand memAddr = bc2ir.popAddress(); 490 RegisterOperand val = gc.temps.makeTemp(TypeReference.Address); 491 bc2ir.appendInstruction(Load.create(REF_LOAD, val, memAddr, new AddressConstantOperand(Offset.zero()), null)); 492 bc2ir.push(val.copyD2U()); 493 } else if (methodName == MagicNames.setMemoryInt) { 494 Operand val = bc2ir.popInt(); 495 Operand memAddr = bc2ir.popAddress(); 496 bc2ir.appendInstruction(Store.create(INT_STORE, 497 val, 498 memAddr, 499 new AddressConstantOperand(Offset.zero()), 500 null)); 501 } else if (methodName == MagicNames.setMemoryWord) { 502 Operand val = bc2ir.popRef(); 503 Operand memAddr = bc2ir.popAddress(); 504 bc2ir.appendInstruction(Store.create(REF_STORE, 505 val, 506 memAddr, 507 new AddressConstantOperand(Offset.zero()), 508 null)); 509 } else if (meth.isSysCall()) { 510 // All methods of SysCall have the following signature: 511 // callNAME(Address functionAddress, <var args to pass via native calling convention>) 512 // With POWEROPEN_ABI, functionAddress points to the function descriptor 513 TypeReference[] args = meth.getParameterTypes(); 514 Instruction call = Call.create(SYSCALL, null, null, null, null, args.length - 1); 515 for (int i = args.length - 1; i >= 1; i--) { 516 Call.setParam(call, i - 1, bc2ir.pop(args[i])); 517 } 518 Operand functionAddress = bc2ir.pop(args[0]); 519 Call.setAddress(call, functionAddress); 520 if (!returnType.isVoidType()) { 521 RegisterOperand op0 = gc.temps.makeTemp(returnType); 522 Call.setResult(call, op0); 523 bc2ir.push(op0.copyD2U(), returnType); 524 } 525 Call.setMethod(call, MethodOperand.STATIC(meth, meth.peekResolvedMethod())); 526 bc2ir.appendInstruction(call); 527 } else if (meth.isSpecializedInvoke()) { 528 // The callsite looks like RETURN = INVOKE (ID, OBJECT, P0, P1 .. PN) 529 // And the actual method will look like RETURN = INVOKE (OBJECT, P0, P1 .. PN) 530 531 // Create the call instruction 532 Instruction call = Call.create(CALL, null, null, null, null, types.length - 1); 533 534 // Plumb all of the normal parameters into the call 535 for (int i = types.length - 1; i >= 2; i--) { 536 Call.setParam(call, i - 1, bc2ir.pop(types[i])); 537 } 538 // The object being specialized 539 Operand objectOperand = bc2ir.pop(types[1]); 540 Call.setParam(call, 0, objectOperand); 541 Operand guard = BC2IR.getGuard(objectOperand); 542 if (guard == null) { 543 // it's magic, so assume that it's OK.... 544 guard = new TrueGuardOperand(); 545 } 546 Call.setGuard(call, guard); 547 548 // Load the tib of this object 549 RegisterOperand tibObject = gc.temps.makeTemp(TypeReference.TIB); 550 bc2ir.appendInstruction(GuardedUnary.create(GET_OBJ_TIB, tibObject, objectOperand.copy(), guard.copy())); 551 552 // The index of the specialized method 553 Operand methodId = bc2ir.popInt(); 554 555 // Add the base offset for specialized methods and convert from index to address 556 RegisterOperand tibOffset = gc.temps.makeTemp(TypeReference.Int); 557 bc2ir.appendInstruction(Binary.create(INT_ADD, tibOffset, methodId, new IntConstantOperand(TIB_FIRST_SPECIALIZED_METHOD_INDEX))); 558 bc2ir.appendInstruction(Binary.create(INT_SHL, tibOffset.copyRO(), tibOffset.copyD2U(), new IntConstantOperand(LOG_BYTES_IN_ADDRESS))); 559 560 // Load the code address from the TIB 561 RegisterOperand codeAddress = gc.temps.makeTemp(TypeReference.Address); 562 bc2ir.appendInstruction(Load.create(REF_LOAD, codeAddress, tibObject.copyD2U(), tibOffset.copyD2U(), null)); 563 564 Call.setAddress(call, codeAddress.copyD2U()); 565 if (!returnType.isVoidType()) { 566 RegisterOperand op0 = gc.temps.makeTemp(returnType); 567 Call.setResult(call, op0); 568 bc2ir.push(op0.copyD2U(), returnType); 569 } 570 bc2ir.appendInstruction(call); 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(VM.NOT_REACHED,"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 (methodName == MagicNames.fence) { 800 bc2ir.appendInstruction(Empty.create(FENCE)); 801 } else if (methodName == MagicNames.readCeiling) { 802 bc2ir.appendInstruction(Empty.create(READ_CEILING)); 803 } else if (methodName == MagicNames.writeFloor) { 804 bc2ir.appendInstruction(Empty.create(WRITE_FLOOR)); 805 } else if (generatePolymorphicMagic(bc2ir, gc, meth, methodName)) { 806 return true; 807 } else if (methodName == MagicNames.getTimeBase) { 808 RegisterOperand op0 = gc.temps.makeTempLong(); 809 bc2ir.appendInstruction(Nullary.create(GET_TIME_BASE, op0)); 810 bc2ir.pushDual(op0.copyD2U()); 811 } else if (methodName == MagicNames.getInlineDepth) { 812 bc2ir.push(new IntConstantOperand(gc.inlineSequence.getInlineDepth())); 813 } else if (methodName == MagicNames.isConstantParameter) { 814 Operand requestedOperand = bc2ir.pop(); 815 if (!(requestedOperand instanceof IntConstantOperand)) { 816 throw new OptimizingCompilerException("Must supply constant to Magic.isConstantParameter"); 817 } 818 int requested = ((IntConstantOperand)(requestedOperand)).value; 819 boolean isConstant = gc.arguments[requested].isConstant(); 820 bc2ir.push(new IntConstantOperand(isConstant ? 1 : 0)); 821 } else { 822 // Wasn't machine-independent, so try the machine-dependent magics next. 823 return GenerateMachineSpecificMagic.generateMagic(bc2ir, gc, meth); 824 } 825 return true; 826 } // generateMagic 827 828 // Generate magic where the untype operational semantics is identified by name. 829 // The operands' types are determined from the method signature. 830 // 831 static boolean generatePolymorphicMagic(BC2IR bc2ir, GenerationContext gc, MethodReference meth, 832 Atom methodName) { 833 TypeReference resultType = meth.getReturnType(); 834 if (methodName == MagicNames.wordFromInt || methodName == MagicNames.wordFromIntSignExtend) { 835 RegisterOperand reg = gc.temps.makeTemp(resultType); 836 bc2ir.appendInstruction(Unary.create(INT_2ADDRSigExt, reg, bc2ir.popInt())); 837 bc2ir.push(reg.copyD2U()); 838 } else if (methodName == MagicNames.wordFromIntZeroExtend) { 839 RegisterOperand reg = gc.temps.makeTemp(resultType); 840 bc2ir.appendInstruction(Unary.create(INT_2ADDRZerExt, reg, bc2ir.popInt())); 841 bc2ir.push(reg.copyD2U()); 842 } else if (methodName == MagicNames.wordFromLong) { 843 RegisterOperand reg = gc.temps.makeTemp(resultType); 844 bc2ir.appendInstruction(Unary.create(LONG_2ADDR, reg, bc2ir.popLong())); 845 bc2ir.push(reg.copyD2U()); 846 } else if (methodName == MagicNames.wordToInt) { 847 RegisterOperand reg = gc.temps.makeTempInt(); 848 bc2ir.appendInstruction(Unary.create(ADDR_2INT, reg, bc2ir.popAddress())); 849 bc2ir.push(reg.copyD2U()); 850 } else if (methodName == MagicNames.wordToLong) { 851 RegisterOperand lreg = gc.temps.makeTempLong(); 852 bc2ir.appendInstruction(Unary.create(ADDR_2LONG, lreg, bc2ir.popAddress())); 853 bc2ir.pushDual(lreg.copyD2U()); 854 } else if (methodName == MagicNames.wordToWord) { 855 RegisterOperand reg = gc.temps.makeTemp(TypeReference.Word); 856 bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popAddress())); 857 bc2ir.push(reg.copyD2U()); 858 } else if (methodName == MagicNames.wordToAddress) { 859 RegisterOperand reg = gc.temps.makeTemp(TypeReference.Address); 860 bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popRef())); 861 bc2ir.push(reg.copyD2U()); 862 } else if (methodName == MagicNames.wordToObject) { 863 RegisterOperand reg = gc.temps.makeTemp(TypeReference.JavaLangObject); 864 bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popRef())); 865 bc2ir.push(reg.copyD2U()); 866 } else if (methodName == MagicNames.wordToObjectReference || methodName == MagicNames.wordFromObject) { 867 RegisterOperand reg = gc.temps.makeTemp(TypeReference.ObjectReference); 868 bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popRef())); 869 bc2ir.push(reg.copyD2U()); 870 } else if (methodName == MagicNames.wordToOffset) { 871 RegisterOperand reg = gc.temps.makeTemp(TypeReference.Offset); 872 bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popAddress())); 873 bc2ir.push(reg.copyD2U()); 874 } else if (methodName == MagicNames.wordToExtent) { 875 RegisterOperand reg = gc.temps.makeTemp(TypeReference.Extent); 876 bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popAddress())); 877 bc2ir.push(reg.copyD2U()); 878 } else if (methodName == MagicNames.codeArrayAsObject) { 879 RegisterOperand reg = gc.temps.makeTemp(TypeReference.JavaLangObject); 880 bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.pop(TypeReference.CodeArray))); 881 bc2ir.push(reg.copyD2U()); 882 } else if (methodName == MagicNames.tibAsObject) { 883 RegisterOperand reg = gc.temps.makeTemp(TypeReference.JavaLangObject); 884 bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.pop(TypeReference.TIB))); 885 bc2ir.push(reg.copyD2U()); 886 } else if (methodName == MagicNames.wordPlus) { 887 Operand o2 = bc2ir.pop(); 888 Operand o1 = bc2ir.pop(); 889 RegisterOperand op0 = gc.temps.makeTemp(resultType); 890 if (VM.BuildFor64Addr && o2.isInt()) { 891 RegisterOperand op1 = gc.temps.makeTemp(resultType); 892 bc2ir.appendInstruction(Unary.create(INT_2ADDRSigExt, op1, o2)); 893 bc2ir.appendInstruction(Binary.create(REF_ADD, op0, o1, op1.copyD2U())); 894 } else { 895 bc2ir.appendInstruction(Binary.create(REF_ADD, op0, o1, o2)); 896 } 897 bc2ir.push(op0.copyD2U()); 898 } else if (methodName == MagicNames.wordMinus) { 899 Operand o2 = bc2ir.pop(); 900 Operand o1 = bc2ir.pop(); 901 RegisterOperand op0 = gc.temps.makeTemp(resultType); 902 if (VM.BuildFor64Addr && o2.isInt()) { 903 RegisterOperand op1 = gc.temps.makeTemp(resultType); 904 bc2ir.appendInstruction(Unary.create(INT_2ADDRSigExt, op1, o2)); 905 bc2ir.appendInstruction(Binary.create(REF_SUB, op0, o1, op1)); 906 } else { 907 bc2ir.appendInstruction(Binary.create(REF_SUB, op0, o1, o2)); 908 } 909 bc2ir.push(op0.copyD2U()); 910 } else if (methodName == MagicNames.wordDiff) { 911 Operand o2 = bc2ir.pop(); 912 Operand o1 = bc2ir.pop(); 913 RegisterOperand op0 = gc.temps.makeTemp(resultType); 914 bc2ir.appendInstruction(Binary.create(REF_SUB, op0, o1, o2)); 915 bc2ir.push(op0.copyD2U()); 916 } else if (methodName == MagicNames.wordAnd) { 917 Operand o2 = bc2ir.pop(); 918 Operand o1 = bc2ir.pop(); 919 RegisterOperand op0 = gc.temps.makeTemp(resultType); 920 bc2ir.appendInstruction(Binary.create(REF_AND, op0, o1, o2)); 921 bc2ir.push(op0.copyD2U()); 922 } else if (methodName == MagicNames.wordOr) { 923 Operand o2 = bc2ir.pop(); 924 Operand o1 = bc2ir.pop(); 925 RegisterOperand op0 = gc.temps.makeTemp(resultType); 926 bc2ir.appendInstruction(Binary.create(REF_OR, op0, o1, o2)); 927 bc2ir.push(op0.copyD2U()); 928 } else if (methodName == MagicNames.wordXor) { 929 Operand o2 = bc2ir.pop(); 930 Operand o1 = bc2ir.pop(); 931 RegisterOperand op0 = gc.temps.makeTemp(resultType); 932 bc2ir.appendInstruction(Binary.create(REF_XOR, op0, o1, o2)); 933 bc2ir.push(op0.copyD2U()); 934 } else if (methodName == MagicNames.wordNot) { 935 Operand o1 = bc2ir.pop(); 936 RegisterOperand op0 = gc.temps.makeTemp(resultType); 937 bc2ir.appendInstruction(Unary.create(REF_NOT, op0, o1)); 938 bc2ir.push(op0.copyD2U()); 939 } else if (methodName == MagicNames.wordZero || methodName == MagicNames.wordNull) { 940 RegisterOperand op0 = gc.temps.makeTemp(resultType); 941 bc2ir.appendInstruction(Move.create(REF_MOVE, op0, new AddressConstantOperand(Address.zero()))); 942 bc2ir.push(op0.copyD2U()); 943 } else if (methodName == MagicNames.wordOne) { 944 RegisterOperand op0 = gc.temps.makeTemp(resultType); 945 bc2ir.appendInstruction(Move.create(REF_MOVE, op0, new AddressConstantOperand(Address.fromIntZeroExtend(1)))); 946 bc2ir.push(op0.copyD2U()); 947 } else if (methodName == MagicNames.wordMax) { 948 RegisterOperand op0 = gc.temps.makeTemp(resultType); 949 bc2ir.appendInstruction(Move.create(REF_MOVE, op0, new AddressConstantOperand(Address.max()))); 950 bc2ir.push(op0.copyD2U()); 951 } else if (methodName == MagicNames.wordIsNull) { 952 RegisterOperand op0 = gc.temps.makeTemp(resultType); 953 bc2ir.appendInstruction(Move.create(REF_MOVE, op0, new AddressConstantOperand(Address.zero()))); 954 ConditionOperand cond = ConditionOperand.EQUAL(); 955 cmpHelper(bc2ir, gc, cond, op0.copyRO()); 956 } else if (methodName == MagicNames.wordIsZero) { 957 RegisterOperand op0 = gc.temps.makeTemp(resultType); 958 bc2ir.appendInstruction(Move.create(REF_MOVE, op0, new AddressConstantOperand(Address.zero()))); 959 ConditionOperand cond = ConditionOperand.EQUAL(); 960 cmpHelper(bc2ir, gc, cond, op0.copyRO()); 961 } else if (methodName == MagicNames.wordIsMax) { 962 RegisterOperand op0 = gc.temps.makeTemp(resultType); 963 bc2ir.appendInstruction(Move.create(REF_MOVE, op0, new AddressConstantOperand(Address.max()))); 964 ConditionOperand cond = ConditionOperand.EQUAL(); 965 cmpHelper(bc2ir, gc, cond, op0.copyRO()); 966 } else if (methodName == MagicNames.wordEQ) { 967 ConditionOperand cond = ConditionOperand.EQUAL(); 968 cmpHelper(bc2ir, gc, cond, null); 969 } else if (methodName == MagicNames.wordNE) { 970 ConditionOperand cond = ConditionOperand.NOT_EQUAL(); 971 cmpHelper(bc2ir, gc, cond, null); 972 } else if (methodName == MagicNames.wordLT) { 973 ConditionOperand cond = ConditionOperand.LOWER(); 974 cmpHelper(bc2ir, gc, cond, null); 975 } else if (methodName == MagicNames.wordLE) { 976 ConditionOperand cond = ConditionOperand.LOWER_EQUAL(); 977 cmpHelper(bc2ir, gc, cond, null); 978 } else if (methodName == MagicNames.wordGT) { 979 ConditionOperand cond = ConditionOperand.HIGHER(); 980 cmpHelper(bc2ir, gc, cond, null); 981 } else if (methodName == MagicNames.wordGE) { 982 ConditionOperand cond = ConditionOperand.HIGHER_EQUAL(); 983 cmpHelper(bc2ir, gc, cond, null); 984 } else if (methodName == MagicNames.wordsLT) { 985 ConditionOperand cond = ConditionOperand.LESS(); 986 cmpHelper(bc2ir, gc, cond, null); 987 } else if (methodName == MagicNames.wordsLE) { 988 ConditionOperand cond = ConditionOperand.LESS_EQUAL(); 989 cmpHelper(bc2ir, gc, cond, null); 990 } else if (methodName == MagicNames.wordsGT) { 991 ConditionOperand cond = ConditionOperand.GREATER(); 992 cmpHelper(bc2ir, gc, cond, null); 993 } else if (methodName == MagicNames.wordsGE) { 994 ConditionOperand cond = ConditionOperand.GREATER_EQUAL(); 995 cmpHelper(bc2ir, gc, cond, null); 996 } else if (methodName == MagicNames.wordLsh) { 997 Operand op2 = bc2ir.popInt(); 998 Operand op1 = bc2ir.popAddress(); 999 RegisterOperand res = gc.temps.makeTemp(resultType); 1000 bc2ir.appendInstruction(Binary.create(REF_SHL, res, op1, op2)); 1001 bc2ir.push(res.copyD2U()); 1002 } else if (methodName == MagicNames.wordRshl) { 1003 Operand op2 = bc2ir.popInt(); 1004 Operand op1 = bc2ir.popAddress(); 1005 RegisterOperand res = gc.temps.makeTemp(resultType); 1006 bc2ir.appendInstruction(Binary.create(REF_USHR, res, op1, op2)); 1007 bc2ir.push(res.copyD2U()); 1008 } else if (methodName == MagicNames.wordRsha) { 1009 Operand op2 = bc2ir.popInt(); 1010 Operand op1 = bc2ir.popAddress(); 1011 RegisterOperand res = gc.temps.makeTemp(resultType); 1012 bc2ir.appendInstruction(Binary.create(REF_SHR, res, op1, op2)); 1013 bc2ir.push(res.copyD2U()); 1014 } else { 1015 return false; 1016 } 1017 return true; 1018 } 1019 1020 private static void cmpHelper(BC2IR bc2ir, GenerationContext gc, ConditionOperand cond, 1021 Operand given_o2) { 1022 Operand o2 = given_o2 == null ? bc2ir.pop() : given_o2; 1023 Operand o1 = bc2ir.pop(); 1024 RegisterOperand res = gc.temps.makeTempInt(); 1025 bc2ir.appendInstruction(BooleanCmp.create(BOOLEAN_CMP_ADDR, 1026 res.copyRO(), 1027 o1, 1028 o2, 1029 cond, 1030 new BranchProfileOperand())); 1031 bc2ir.push(res.copyD2U()); 1032 } 1033 1034 private static LocationOperand mapToMetadata(Operand metadata) { 1035 if (metadata instanceof IntConstantOperand) { 1036 int index = ((IntConstantOperand) metadata).value; 1037 if (index == 0) return null; 1038 MemberReference mr = MemberReference.getMemberRef(index); 1039 return new LocationOperand(mr.asFieldReference()); 1040 } 1041 return null; 1042 } 1043 1044 private static final int LOAD_OP = 1; 1045 private static final int PREPARE_OP = 2; 1046 private static final int STORE_OP = 3; 1047 private static final int ATTEMPT_OP = 4; 1048 1049 private static Operator getOperator(TypeReference type, int operatorClass) 1050 throws MagicNotImplementedException { 1051 if (operatorClass == LOAD_OP) { 1052 if (type == TypeReference.Address) return REF_LOAD; 1053 if (type == TypeReference.ObjectReference) return REF_LOAD; 1054 if (type == TypeReference.Word) return REF_LOAD; 1055 if (type == TypeReference.Offset) return REF_LOAD; 1056 if (type == TypeReference.Extent) return REF_LOAD; 1057 if (type == TypeReference.Int) return INT_LOAD; 1058 if (type == TypeReference.Byte) return BYTE_LOAD; 1059 if (type == TypeReference.Short) return SHORT_LOAD; 1060 if (type == TypeReference.Char) return USHORT_LOAD; 1061 if (type == TypeReference.Float) return FLOAT_LOAD; 1062 if (type == TypeReference.Double) return DOUBLE_LOAD; 1063 if (type == TypeReference.Long) return LONG_LOAD; 1064 } else if (operatorClass == PREPARE_OP) { 1065 if (type == TypeReference.Address) return PREPARE_ADDR; 1066 if (type == TypeReference.ObjectReference) return PREPARE_ADDR; 1067 if (type == TypeReference.Word) return PREPARE_ADDR; 1068 if (type == TypeReference.Int) return PREPARE_INT; 1069 if (type == TypeReference.Long) return PREPARE_LONG; 1070 } else if (operatorClass == ATTEMPT_OP) { 1071 if (type == TypeReference.Address) return ATTEMPT_ADDR; 1072 if (type == TypeReference.ObjectReference) return ATTEMPT_ADDR; 1073 if (type == TypeReference.Word) return ATTEMPT_ADDR; 1074 if (type == TypeReference.Int) return ATTEMPT_INT; 1075 if (type == TypeReference.Long) return ATTEMPT_LONG; 1076 } else if (operatorClass == STORE_OP) { 1077 if (type == TypeReference.Address) return REF_STORE; 1078 if (type == TypeReference.ObjectReference) return REF_STORE; 1079 if (type == TypeReference.Word) return REF_STORE; 1080 if (type == TypeReference.Offset) return REF_STORE; 1081 if (type == TypeReference.Extent) return REF_STORE; 1082 if (type == TypeReference.Int) return INT_STORE; 1083 if (type == TypeReference.Byte || type == TypeReference.Boolean) return BYTE_STORE; 1084 if (type == TypeReference.Short) return SHORT_STORE; 1085 if (type == TypeReference.Char) return SHORT_STORE; 1086 if (type == TypeReference.Float) return FLOAT_STORE; 1087 if (type == TypeReference.Double) return DOUBLE_STORE; 1088 if (type == TypeReference.Long) return LONG_STORE; 1089 } 1090 String msg = " Unexpected call to getOperator"; 1091 throw MagicNotImplementedException.UNEXPECTED(msg); 1092 } 1093 1094 private static boolean isLoad(Atom methodName) { 1095 return isPrefix(MagicNames.loadPrefix, methodName.toByteArray()); 1096 } 1097 1098 private static boolean isPrepare(Atom methodName) { 1099 return isPrefix(MagicNames.preparePrefix, methodName.toByteArray()); 1100 } 1101 1102 /** 1103 * Is string <code>a</code> a prefix of string 1104 * <code>b</code>. String <code>b</code> is encoded as an ASCII byte 1105 * array. 1106 * 1107 * @param prefix Prefix atom 1108 * @param b String which may contain prefix, encoded as an ASCII 1109 * byte array. 1110 * @return <code>true</code> if <code>a</code> is a prefix of 1111 * <code>b</code> 1112 */ 1113 @Interruptible 1114 private static boolean isPrefix(Atom prefix, byte[] b) { 1115 byte[] a = prefix.toByteArray(); 1116 int aLen = a.length; 1117 if (aLen > b.length) { 1118 return false; 1119 } 1120 for (int i = 0; i < aLen; i++) { 1121 if (a[i] != b[i]) { 1122 return false; 1123 } 1124 } 1125 return true; 1126 } 1127 1128 }