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