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.baseline.ia32; 014 015import static org.jikesrvm.compilers.baseline.ia32.BaselineCompilerImpl.FIVE_SLOTS; 016import static org.jikesrvm.compilers.baseline.ia32.BaselineCompilerImpl.FOUR_SLOTS; 017import static org.jikesrvm.compilers.baseline.ia32.BaselineCompilerImpl.NO_SLOT; 018import static org.jikesrvm.compilers.baseline.ia32.BaselineCompilerImpl.ONE_SLOT; 019import static org.jikesrvm.compilers.baseline.ia32.BaselineCompilerImpl.THREE_SLOTS; 020import static org.jikesrvm.compilers.baseline.ia32.BaselineCompilerImpl.TWO_SLOTS; 021import static org.jikesrvm.compilers.common.assembler.ia32.AssemblerConstants.BYTE; 022import static org.jikesrvm.compilers.common.assembler.ia32.AssemblerConstants.EQ; 023import static org.jikesrvm.compilers.common.assembler.ia32.AssemblerConstants.GE; 024import static org.jikesrvm.compilers.common.assembler.ia32.AssemblerConstants.GT; 025import static org.jikesrvm.compilers.common.assembler.ia32.AssemblerConstants.LE; 026import static org.jikesrvm.compilers.common.assembler.ia32.AssemblerConstants.LGE; 027import static org.jikesrvm.compilers.common.assembler.ia32.AssemblerConstants.LGT; 028import static org.jikesrvm.compilers.common.assembler.ia32.AssemblerConstants.LLE; 029import static org.jikesrvm.compilers.common.assembler.ia32.AssemblerConstants.LLT; 030import static org.jikesrvm.compilers.common.assembler.ia32.AssemblerConstants.LONG; 031import static org.jikesrvm.compilers.common.assembler.ia32.AssemblerConstants.LT; 032import static org.jikesrvm.compilers.common.assembler.ia32.AssemblerConstants.NE; 033import static org.jikesrvm.compilers.common.assembler.ia32.AssemblerConstants.WORD; 034import static org.jikesrvm.ia32.ArchConstants.SSE2_BASE; 035import static org.jikesrvm.ia32.ArchConstants.SSE2_FULL; 036import static org.jikesrvm.ia32.BaselineConstants.EBX_SAVE_OFFSET; 037import static org.jikesrvm.ia32.BaselineConstants.EDI_SAVE_OFFSET; 038import static org.jikesrvm.ia32.BaselineConstants.FPU_SAVE_OFFSET; 039import static org.jikesrvm.ia32.BaselineConstants.LG_WORDSIZE; 040import static org.jikesrvm.ia32.BaselineConstants.S0; 041import static org.jikesrvm.ia32.BaselineConstants.S1; 042import static org.jikesrvm.ia32.BaselineConstants.SP; 043import static org.jikesrvm.ia32.BaselineConstants.T0; 044import static org.jikesrvm.ia32.BaselineConstants.T0_SAVE_OFFSET; 045import static org.jikesrvm.ia32.BaselineConstants.T1; 046import static org.jikesrvm.ia32.BaselineConstants.T1_SAVE_OFFSET; 047import static org.jikesrvm.ia32.BaselineConstants.TR; 048import static org.jikesrvm.ia32.BaselineConstants.WORDSIZE; 049import static org.jikesrvm.ia32.BaselineConstants.XMM_SAVE_OFFSET; 050import static org.jikesrvm.ia32.RegisterConstants.EAX; 051import static org.jikesrvm.ia32.RegisterConstants.EBX; 052import static org.jikesrvm.ia32.RegisterConstants.ECX; 053import static org.jikesrvm.ia32.RegisterConstants.EDI; 054import static org.jikesrvm.ia32.RegisterConstants.EDX; 055import static org.jikesrvm.ia32.RegisterConstants.ESI; 056import static org.jikesrvm.ia32.RegisterConstants.FP0; 057import static org.jikesrvm.ia32.RegisterConstants.JTOC_REGISTER; 058import static org.jikesrvm.ia32.RegisterConstants.XMM0; 059import static org.jikesrvm.ia32.RegisterConstants.XMM1; 060import static org.jikesrvm.ia32.RegisterConstants.XMM2; 061import static org.jikesrvm.ia32.RegisterConstants.XMM3; 062import static org.jikesrvm.ia32.StackframeLayoutConstants.STACKFRAME_FRAME_POINTER_OFFSET; 063import static org.jikesrvm.ia32.StackframeLayoutConstants.STACKFRAME_METHOD_ID_OFFSET; 064import static org.jikesrvm.ia32.StackframeLayoutConstants.STACKFRAME_RETURN_ADDRESS_OFFSET; 065import static org.jikesrvm.objectmodel.TIBLayoutConstants.TIB_TYPE_INDEX; 066import static org.jikesrvm.runtime.EntrypointHelper.getMethodReference; 067 068import org.jikesrvm.VM; 069import org.jikesrvm.architecture.AbstractRegisters; 070import org.jikesrvm.classloader.Atom; 071import org.jikesrvm.classloader.MethodReference; 072import org.jikesrvm.classloader.RVMArray; 073import org.jikesrvm.classloader.RVMMethod; 074import org.jikesrvm.classloader.RVMType; 075import org.jikesrvm.classloader.TypeReference; 076import org.jikesrvm.compilers.common.CodeArray; 077import org.jikesrvm.compilers.common.assembler.ForwardReference; 078import org.jikesrvm.compilers.common.assembler.ia32.Assembler; 079import org.jikesrvm.ia32.RegisterConstants.GPR; 080import org.jikesrvm.jni.FunctionTable; 081import org.jikesrvm.mm.mminterface.MemoryManager; 082import org.jikesrvm.objectmodel.IMT; 083import org.jikesrvm.objectmodel.JavaHeader; 084import org.jikesrvm.objectmodel.ObjectModel; 085import org.jikesrvm.objectmodel.TIB; 086import org.jikesrvm.runtime.ArchEntrypoints; 087import org.jikesrvm.runtime.EntrypointHelper; 088import org.jikesrvm.runtime.Entrypoints; 089import org.jikesrvm.runtime.Magic; 090import org.jikesrvm.runtime.MagicNames; 091import org.jikesrvm.scheduler.RVMThread; 092import org.jikesrvm.util.ImmutableEntryHashMapRVM; 093import org.vmmagic.pragma.Uninterruptible; 094import org.vmmagic.unboxed.Address; 095import org.vmmagic.unboxed.AddressArray; 096import org.vmmagic.unboxed.Extent; 097import org.vmmagic.unboxed.ExtentArray; 098import org.vmmagic.unboxed.ObjectReference; 099import org.vmmagic.unboxed.ObjectReferenceArray; 100import org.vmmagic.unboxed.Offset; 101import org.vmmagic.unboxed.OffsetArray; 102import org.vmmagic.unboxed.Word; 103import org.vmmagic.unboxed.WordArray; 104 105/** 106 * Create magic code 107 */ 108final class BaselineMagic { 109 /** 110 * Map of method references to objects that will generate the necessary magic 111 */ 112 private static final ImmutableEntryHashMapRVM<MethodReference,MagicGenerator> generators = 113 new ImmutableEntryHashMapRVM<MethodReference,MagicGenerator>(); 114 115 /** 116 * When casting or loading object references should the reference be checked 117 * to see if it is an object reference first? 118 */ 119 private static final boolean VALIDATE_OBJECT_REFERENCES = false; 120 121 /** 122 * If a bad reference is encountered should we halt the VM? 123 */ 124 private static final boolean FAIL_ON_BAD_REFERENCES = true; 125 126 /** Constant for constructing quad-word (= 64 bit) Attempt generators */ 127 private static final boolean QUAD_WORD = true; 128 /** Constant for constructing double-word (= 32 bit) Attempt generators */ 129 private static final boolean DOUBLE_WORD = false; 130 131 /** 132 * Entry point to generating magic 133 * @param asm assembler to generate magic code into 134 * @param m method reference 135 * @param cm the method being compiled 136 * @param sd the depth of the stack 137 * @return {@code true} if magic was generated 138 */ 139 static boolean generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 140 MagicGenerator g = generators.get(m); 141 if (g != null) { 142 g.generateMagic(asm, m, cm, sd); 143 return true; 144 } else { 145 return false; 146 } 147 } 148 149 /** 150 * Flag to avoid recursive calls to check 151 */ 152 private static volatile boolean inCheck = false; 153 /** 154 * Method called to check an object reference is valid 155 * @param value the reference to check 156 */ 157 @SuppressWarnings("unused") 158 @Uninterruptible 159 private static void check(ObjectReference value) { 160 if (!inCheck) { 161 inCheck = true; 162 if (!MemoryManager.validRef(value) && FAIL_ON_BAD_REFERENCES) { 163 VM.sysFail("Bad object reference encountered"); 164 } 165 inCheck = false; 166 } 167 } 168 169 /** 170 * Reference of method that checks a reference 171 */ 172 private static final MethodReference checkMR = 173 EntrypointHelper.getMethodReference(BaselineMagic.class, 174 Atom.findOrCreateUnicodeAtom("check"), ObjectReference.class, void.class); 175 176 /** 177 * Parent of all magic generating classes 178 */ 179 private abstract static class MagicGenerator { 180 abstract void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd); 181 } 182 183 /** 184 * Add a reference check to a magic generator 185 */ 186 private static final class EarlyReferenceCheckDecorator extends MagicGenerator { 187 private final Offset offset; 188 private final MagicGenerator generator; 189 /** 190 * Construct decorator that will add reference checks 191 * @param offset on stack of reference to check 192 * @param generator the magic generator being decorated 193 */ 194 EarlyReferenceCheckDecorator(Offset offset, MagicGenerator generator) { 195 this.offset = offset; 196 this.generator = generator; 197 } 198 @Override 199 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 200 Class<?> dc = cm.getDeclaringClass().getClassForType(); 201 if ((dc != JavaHeader.class) && 202 (dc != ObjectModel.class)) { 203 if (checkMR.needsDynamicLink(cm)) { 204 BaselineCompilerImpl.emitDynamicLinkingSequence(asm, S0, checkMR, true); 205 if (offset.NE(NO_SLOT)) { 206 asm.emitMOV_Reg_RegDisp(T0, SP, offset); 207 } else { 208 asm.emitMOV_Reg_RegInd(T0, SP); 209 } 210 asm.emitPUSH_Reg(T0); 211 asm.emitCALL_RegDisp(S0, Magic.getTocPointer().toWord().toOffset()); 212 } else { 213 if (offset.NE(NO_SLOT)) { 214 asm.emitMOV_Reg_RegDisp(T0, SP, offset); 215 } else { 216 asm.emitMOV_Reg_RegInd(T0, SP); 217 } 218 asm.emitPUSH_Reg(T0); 219 asm.generateJTOCcall(checkMR.peekResolvedMethod().getOffset()); 220 } 221 } 222 generator.generateMagic(asm, m, cm, sd); 223 } 224 } 225 226 /** 227 * Add a reference check to a magic generator 228 */ 229 private static final class LateReferenceCheckDecorator extends MagicGenerator { 230 private final Offset offset; 231 private final MagicGenerator generator; 232 /** 233 * Construct decorator that will add reference checks 234 * @param offset on stack of reference to check 235 * @param generator the magic generator being decorated 236 */ 237 LateReferenceCheckDecorator(Offset offset, MagicGenerator generator) { 238 this.offset = offset; 239 this.generator = generator; 240 } 241 @Override 242 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 243 generator.generateMagic(asm, m, cm, sd); 244 Class<?> dc = cm.getDeclaringClass().getClassForType(); 245 if ((dc != JavaHeader.class) && 246 (dc != ObjectModel.class)) { 247 if (checkMR.needsDynamicLink(cm)) { 248 BaselineCompilerImpl.emitDynamicLinkingSequence(asm, S0, checkMR, true); 249 if (offset.NE(NO_SLOT)) { 250 asm.emitMOV_Reg_RegDisp(T0, SP, offset); 251 } else { 252 asm.emitMOV_Reg_RegInd(T0, SP); 253 } 254 asm.emitPUSH_Reg(T0); 255 asm.emitCALL_RegDisp(S0, Magic.getTocPointer().toWord().toOffset()); 256 } else { 257 if (offset.NE(NO_SLOT)) { 258 asm.emitMOV_Reg_RegDisp(T0, SP, offset); 259 } else { 260 asm.emitMOV_Reg_RegInd(T0, SP); 261 } 262 asm.emitPUSH_Reg(T0); 263 asm.generateJTOCcall(checkMR.peekResolvedMethod().getOffset()); 264 } 265 } 266 } 267 } 268 269 /** 270 * Load a 32bit quantity from an address 271 */ 272 private static final class Load32 extends MagicGenerator { 273 @Override 274 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 275 // No offset 276 asm.emitPOP_Reg(T0); // address 277 if (VM.BuildFor32Addr) { 278 asm.emitPUSH_RegInd(T0); // pushes [T0+0] 279 } else { 280 asm.emitMOV_Reg_RegInd(T0, T0); // 32bit load 281 asm.emitPUSH_Reg(T0); // 64bit push 282 } 283 } 284 } 285 /** 286 * Load a 64bit quantity from an address 287 */ 288 private static final class Load64 extends MagicGenerator { 289 @Override 290 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 291 // No offset 292 if (VM.VerifyAssertions) VM._assert(VM.BuildFor64Addr); 293 asm.emitPOP_Reg(T0); // address 294 asm.emitPUSH_RegInd(T0); // pushes [T0+0] 295 } 296 } 297 static { 298 MagicGenerator g = new Load32(); 299 generators.put(getMethodReference(Address.class, MagicNames.loadInt, int.class), g); 300 generators.put(getMethodReference(Address.class, MagicNames.prepareInt, int.class), g); 301 generators.put(getMethodReference(Address.class, MagicNames.loadFloat, float.class), g); 302 if (VM.BuildFor64Addr) { 303 g = new Load64(); 304 } 305 generators.put(getMethodReference(Address.class, MagicNames.loadAddress, Address.class), g); 306 generators.put(getMethodReference(Address.class, MagicNames.prepareAddress, Address.class), g); 307 generators.put(getMethodReference(Address.class, MagicNames.loadWord, Word.class), g); 308 generators.put(getMethodReference(Address.class, MagicNames.prepareWord, Word.class), g); 309 if (VALIDATE_OBJECT_REFERENCES) { 310 g = new LateReferenceCheckDecorator(NO_SLOT, g); 311 } 312 generators.put(getMethodReference(Address.class, MagicNames.prepareObjectReference, ObjectReference.class), g); 313 generators.put(getMethodReference(Address.class, MagicNames.loadObjectReference, ObjectReference.class), g); 314 } 315 316 /** 317 * Load a 32bit quantity from an address and offset parameter 318 */ 319 private static final class Load32_Offset extends MagicGenerator { 320 @Override 321 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 322 // Load at offset 323 asm.emitPOP_Reg(S0); // offset 324 asm.emitPOP_Reg(T0); // object ref 325 if (VM.BuildFor32Addr) { 326 asm.emitPUSH_RegIdx(T0, S0, BYTE, NO_SLOT); // pushes [T0+S0] 327 } else { 328 asm.emitMOV_Reg_RegIdx(T0, T0, S0, BYTE, NO_SLOT); // 32bit load 329 asm.emitPUSH_Reg(T0); // 64bit push 330 } 331 } 332 } 333 /** 334 * Load a 64bit quantity from an address and offset parameter 335 */ 336 private static final class Load64_Offset extends MagicGenerator { 337 @Override 338 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 339 // No offset 340 if (VM.VerifyAssertions) VM._assert(VM.BuildFor64Addr); 341 asm.emitPOP_Reg(S0); // offset 342 asm.emitPOP_Reg(T0); // object ref 343 asm.emitPUSH_RegIdx(T0, S0, BYTE, NO_SLOT); // pushes [T0+S0] 344 } 345 } 346 347 static { 348 MagicGenerator g = new Load32_Offset(); 349 generators.put(getMethodReference(Address.class, MagicNames.loadInt, Offset.class, int.class), g); 350 generators.put(getMethodReference(Address.class, MagicNames.prepareInt, Offset.class, int.class), g); 351 generators.put(getMethodReference(Address.class, MagicNames.loadFloat, Offset.class, float.class), g); 352 generators.put(getMethodReference(Magic.class, MagicNames.getIntAtOffset, Object.class, Offset.class, int.class), g); 353 generators.put(getMethodReference(Magic.class, MagicNames.getFloatAtOffset, Object.class, Offset.class, float.class), g); 354 generators.put(getMethodReference(Magic.class, MagicNames.prepareInt, Object.class, Offset.class, int.class), g); 355 if (VM.BuildFor64Addr) { 356 g = new Load64_Offset(); 357 } 358 generators.put(getMethodReference(Magic.class, MagicNames.prepareAddress, Object.class, Offset.class, Address.class), g); 359 generators.put(getMethodReference(Magic.class, MagicNames.prepareWord, Object.class, Offset.class, Word.class), g); 360 generators.put(getMethodReference(Address.class, MagicNames.loadAddress, Offset.class, Address.class), g); 361 generators.put(getMethodReference(Address.class, MagicNames.prepareAddress, Offset.class, Address.class), g); 362 generators.put(getMethodReference(Address.class, MagicNames.loadWord, Offset.class, Word.class), g); 363 generators.put(getMethodReference(Address.class, MagicNames.prepareWord, Offset.class, Word.class), g); 364 generators.put(getMethodReference(Magic.class, MagicNames.getWordAtOffset, Object.class, Offset.class, Word.class), g); 365 generators.put(getMethodReference(Magic.class, MagicNames.getAddressAtOffset, Object.class, Offset.class, Address.class), g); 366 generators.put(getMethodReference(Magic.class, MagicNames.getExtentAtOffset, Object.class, Offset.class, Extent.class), g); 367 generators.put(getMethodReference(Magic.class, MagicNames.getOffsetAtOffset, Object.class, Offset.class, Offset.class), g); 368 if (VALIDATE_OBJECT_REFERENCES) { 369 g = new LateReferenceCheckDecorator(NO_SLOT, g); 370 } 371 generators.put(getMethodReference(Address.class, MagicNames.prepareObjectReference, Offset.class, ObjectReference.class), g); 372 generators.put(getMethodReference(Address.class, MagicNames.loadObjectReference, Offset.class, ObjectReference.class), g); 373 generators.put(getMethodReference(Magic.class, MagicNames.getObjectAtOffset, Object.class, Offset.class, Object.class), g); 374 generators.put(getMethodReference(Magic.class, MagicNames.getTIBAtOffset, Object.class, Offset.class, TIB.class), g); 375 generators.put(getMethodReference(Magic.class, MagicNames.prepareObject, Object.class, Offset.class, Object.class), g); 376 } 377 378 /** 379 * Load a word-sized quantity from an address and offset parameter 380 */ 381 private static final class Magic_LoadWord_MD extends MagicGenerator { 382 @Override 383 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 384 asm.emitPOP_Reg(S0); // discard meta-data 385 // Load at offset 386 asm.emitPOP_Reg(S0); // offset 387 asm.emitPOP_Reg(T0); // object ref 388 asm.emitPUSH_RegIdx(T0, S0, BYTE, NO_SLOT); // pushes [T0+S0] 389 } 390 } 391 static { 392 MagicGenerator g = new Magic_LoadWord_MD(); 393 generators.put(getMethodReference(Magic.class, MagicNames.getWordAtOffset, Object.class, Offset.class, int.class, Word.class), g); 394 generators.put(getMethodReference(Magic.class, MagicNames.getAddressAtOffset, Object.class, Offset.class, int.class, Address.class), g); 395 generators.put(getMethodReference(Magic.class, MagicNames.getExtentAtOffset, Object.class, Offset.class, int.class, Extent.class), g); 396 generators.put(getMethodReference(Magic.class, MagicNames.getOffsetAtOffset, Object.class, Offset.class, int.class, Offset.class), g); 397 if (VALIDATE_OBJECT_REFERENCES) { 398 g = new LateReferenceCheckDecorator(NO_SLOT, g); 399 } 400 generators.put(getMethodReference(Magic.class, MagicNames.getObjectAtOffset, Object.class, Offset.class, int.class, Object.class), g); 401 } 402 403 /** 404 * Load a byte from an address 405 */ 406 private static final class LoadByte extends MagicGenerator { 407 @Override 408 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 409 // No offset 410 asm.emitPOP_Reg(T0); // base 411 asm.emitMOVSX_Reg_RegInd_Byte(T0, T0); 412 asm.emitPUSH_Reg(T0); 413 } 414 } 415 static { 416 // Load a byte 417 MagicGenerator g = new LoadByte(); 418 generators.put(getMethodReference(Address.class, MagicNames.loadByte, byte.class), g); 419 } 420 421 /** 422 * Load a byte from an address and offset parameter 423 */ 424 private static final class LoadByte_Offset extends MagicGenerator { 425 @Override 426 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 427 // Load at offset 428 asm.emitPOP_Reg(S0); // offset 429 asm.emitPOP_Reg(T0); // base 430 asm.emitMOVSX_Reg_RegIdx_Byte(T0, T0, S0, BYTE, NO_SLOT); // load and sign extend byte [T0+S0] 431 asm.emitPUSH_Reg(T0); 432 } 433 } 434 static { 435 MagicGenerator g = new LoadByte_Offset(); 436 generators.put(getMethodReference(Address.class, MagicNames.loadByte, Offset.class, byte.class), g); 437 generators.put(getMethodReference(Magic.class, MagicNames.getByteAtOffset, Object.class, Offset.class, byte.class), g); 438 } 439 440 /** 441 * Load an unsigned byte from an address and offset parameter 442 */ 443 private static final class LoadUnsignedByte_Offset extends MagicGenerator { 444 @Override 445 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 446 // Load at offset 447 asm.emitPOP_Reg(S0); // offset 448 asm.emitPOP_Reg(T0); // base 449 asm.emitMOVZX_Reg_RegIdx_Byte(T0, T0, S0, BYTE, NO_SLOT); // load and sign extend byte [T0+S0] 450 asm.emitPUSH_Reg(T0); 451 } 452 } 453 static { 454 MagicGenerator g = new LoadUnsignedByte_Offset(); 455 generators.put(getMethodReference(Magic.class, MagicNames.getUnsignedByteAtOffset, Object.class, Offset.class, byte.class), g); 456 } 457 458 /** 459 * Load a short quantity from an address 460 */ 461 private static final class LoadShort extends MagicGenerator { 462 @Override 463 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 464 // No offset 465 asm.emitPOP_Reg(T0); // base 466 asm.emitMOVSX_Reg_RegInd_Word(T0, T0); 467 asm.emitPUSH_Reg(T0); 468 } 469 } 470 static { 471 MagicGenerator g = new LoadShort(); 472 generators.put(getMethodReference(Address.class, MagicNames.loadShort, short.class), g); 473 } 474 475 /** 476 * Load a short quantity from an address plus offset 477 */ 478 private static final class LoadShort_Offset extends MagicGenerator { 479 @Override 480 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 481 // Load at offset 482 asm.emitPOP_Reg(S0); // offset 483 asm.emitPOP_Reg(T0); // base 484 asm.emitMOVSX_Reg_RegIdx_Word(T0, T0, S0, BYTE, NO_SLOT); // load and sign extend word [T0+S0] 485 asm.emitPUSH_Reg(T0); 486 } 487 } 488 static { 489 MagicGenerator g = new LoadShort_Offset(); 490 generators.put(getMethodReference(Address.class, MagicNames.loadShort, Offset.class, short.class), g); 491 generators.put(getMethodReference(Magic.class, MagicNames.getShortAtOffset, Object.class, Offset.class, short.class), g); 492 } 493 494 /** 495 * Load a char from an address 496 */ 497 private static final class LoadChar extends MagicGenerator { 498 @Override 499 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 500 // No offset 501 asm.emitPOP_Reg(T0); // base 502 asm.emitMOVZX_Reg_RegInd_Word(T0, T0); 503 asm.emitPUSH_Reg(T0); 504 } 505 } 506 static { 507 MagicGenerator g = new LoadChar(); 508 generators.put(getMethodReference(Address.class, MagicNames.loadChar, char.class), g); 509 } 510 511 /** 512 * Load a char from an address plus offset 513 */ 514 private static final class LoadChar_Offset extends MagicGenerator { 515 @Override 516 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 517 // Load at offset 518 asm.emitPOP_Reg(S0); // offset 519 asm.emitPOP_Reg(T0); // base 520 asm.emitMOVZX_Reg_RegIdx_Word(T0, T0, S0, BYTE, NO_SLOT); // load and sign extend word [T0+S0] 521 asm.emitPUSH_Reg(T0); 522 } 523 } 524 static { 525 MagicGenerator g = new LoadChar_Offset(); 526 generators.put(getMethodReference(Address.class, MagicNames.loadChar, Offset.class, char.class), g); 527 generators.put(getMethodReference(Magic.class, MagicNames.getCharAtOffset, Object.class, Offset.class, char.class), g); 528 } 529 530 /** 531 * Load a long-sized quantity from an address 532 */ 533 private static final class LoadLong extends MagicGenerator { 534 @Override 535 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 536 // No offset 537 asm.emitPOP_Reg(T0); // base 538 if (VM.BuildFor32Addr) { 539 asm.emitPUSH_RegDisp(T0, ONE_SLOT); // pushes [T0+4] 540 asm.emitPUSH_RegInd(T0); // pushes [T0] 541 } else { 542 asm.emitPUSH_Reg(T0); // create space 543 asm.emitPUSH_RegInd(T0); // pushes [T0] 544 } 545 } 546 } 547 static { 548 MagicGenerator g = new LoadLong(); 549 generators.put(getMethodReference(Address.class, MagicNames.loadDouble, double.class), g); 550 generators.put(getMethodReference(Address.class, MagicNames.loadLong, long.class), g); 551 generators.put(getMethodReference(Address.class, MagicNames.prepareLong, long.class), g); 552 } 553 554 /** 555 * Load a long-sized quantity from an address plus offset 556 */ 557 private static final class LoadLong_Offset extends MagicGenerator { 558 @Override 559 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 560 // Load at offset 561 asm.emitPOP_Reg(S0); // offset 562 asm.emitPOP_Reg(T0); // base 563 if (VM.BuildFor32Addr) { 564 asm.emitPUSH_RegIdx(T0, S0, BYTE, ONE_SLOT); // pushes [T0+S0+4] 565 asm.emitPUSH_RegIdx(T0, S0, BYTE, NO_SLOT); // pushes [T0+S0] 566 } else { 567 asm.emitPUSH_Reg(T0); // create space 568 asm.emitPUSH_RegIdx(T0, S0, BYTE, NO_SLOT); // pushes [T0+S0] 569 } 570 } 571 } 572 static { 573 MagicGenerator g = new LoadLong_Offset(); 574 generators.put(getMethodReference(Address.class, MagicNames.loadDouble, Offset.class, double.class), g); 575 generators.put(getMethodReference(Address.class, MagicNames.loadLong, Offset.class, long.class), g); 576 generators.put(getMethodReference(Address.class, MagicNames.prepareLong, Offset.class, long.class), g); 577 generators.put(getMethodReference(Magic.class, MagicNames.getDoubleAtOffset, Object.class, Offset.class, double.class), g); 578 generators.put(getMethodReference(Magic.class, MagicNames.getLongAtOffset, Object.class, Offset.class, long.class), g); 579 generators.put(getMethodReference(Magic.class, MagicNames.prepareLong, Object.class, Offset.class, long.class), g); 580 } 581 582 /** 583 * Store a 32bit quantity to an address 584 */ 585 private static final class Store32 extends MagicGenerator { 586 @Override 587 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 588 // No offset 589 asm.emitPOP_Reg(T0); // value 590 asm.emitPOP_Reg(S0); // address 591 asm.emitMOV_RegInd_Reg(S0, T0); // [S0+0] <- T0 592 } 593 } 594 /** 595 * Store a 64bit quantity to an address 596 */ 597 private static final class Store64 extends MagicGenerator { 598 @Override 599 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 600 // No offset 601 asm.emitPOP_Reg(T0); // value 602 asm.emitPOP_Reg(S0); // address 603 asm.emitMOV_RegInd_Reg_Quad(S0, T0); // [S0+0] <- T0 604 } 605 } 606 static { 607 MagicGenerator g = new Store32(); 608 generators.put(getMethodReference(Address.class, MagicNames.store, int.class, void.class), g); 609 generators.put(getMethodReference(Address.class, MagicNames.store, float.class, void.class), g); 610 if (VM.BuildFor64Addr) { 611 g = new Store64(); 612 } 613 generators.put(getMethodReference(Address.class, MagicNames.store, Address.class, void.class), g); 614 generators.put(getMethodReference(Address.class, MagicNames.store, Word.class, void.class), g); 615 if (VALIDATE_OBJECT_REFERENCES) { 616 g = new EarlyReferenceCheckDecorator(NO_SLOT, g); 617 } 618 generators.put(getMethodReference(Address.class, MagicNames.store, ObjectReference.class, void.class), g); 619 } 620 621 /** 622 * Store a 32bit quantity to an address plus offset 623 */ 624 private static final class Store32_Offset extends MagicGenerator { 625 @Override 626 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 627 // Store at offset 628 asm.emitPOP_Reg(S0); // offset 629 asm.emitPOP_Reg(T0); // value 630 asm.emitPOP_Reg(T1); // address 631 asm.emitMOV_RegIdx_Reg(T1, S0, BYTE, NO_SLOT, T0); // [T1+S0] <- T0 632 } 633 } 634 /** 635 * Store a 64bit quantity to an address plus offset 636 */ 637 private static final class Store64_Offset extends MagicGenerator { 638 @Override 639 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 640 // Store at offset 641 asm.emitPOP_Reg(S0); // offset 642 asm.emitPOP_Reg(T0); // value 643 asm.emitPOP_Reg(T1); // address 644 asm.emitMOV_RegIdx_Reg_Quad(T1, S0, BYTE, NO_SLOT, T0); // [T1+S0] <- T0 645 } 646 } 647 static { 648 MagicGenerator g = new Store32_Offset(); 649 generators.put(getMethodReference(Address.class, MagicNames.store, int.class, Offset.class, void.class), g); 650 generators.put(getMethodReference(Address.class, MagicNames.store, float.class, Offset.class, void.class), g); 651 if (VM.BuildFor64Addr) { 652 g = new Store64_Offset(); 653 } 654 generators.put(getMethodReference(Address.class, MagicNames.store, Address.class, Offset.class, void.class), g); 655 generators.put(getMethodReference(Address.class, MagicNames.store, Word.class, Offset.class, void.class), g); 656 if (VALIDATE_OBJECT_REFERENCES) { 657 g = new EarlyReferenceCheckDecorator(ONE_SLOT, g); 658 } 659 generators.put(getMethodReference(Address.class, MagicNames.store, ObjectReference.class, Offset.class, void.class), g); 660 } 661 662 /** 663 * Store a 32bit quantity to an address plus offset in the format used in 664 * {@link Magic} 665 */ 666 private static final class Magic_Store32 extends MagicGenerator { 667 @Override 668 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 669 asm.emitPOP_Reg(T0); // value 670 asm.emitPOP_Reg(S0); // offset 671 asm.emitPOP_Reg(T1); // obj ref 672 asm.emitMOV_RegIdx_Reg(T1, S0, BYTE, NO_SLOT, T0); // [T1+S0] <- T0 673 } 674 } 675 /** 676 * Store a 64bit quantity to an address plus offset in the format used in 677 * {@link Magic} 678 */ 679 private static final class Magic_Store64 extends MagicGenerator { 680 @Override 681 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 682 asm.emitPOP_Reg(T0); // value 683 asm.emitPOP_Reg(S0); // offset 684 asm.emitPOP_Reg(T1); // obj ref 685 asm.emitMOV_RegIdx_Reg_Quad(T1, S0, BYTE, NO_SLOT, T0); // [T1+S0] <- T0 686 } 687 } 688 static { 689 MagicGenerator g = new Magic_Store32(); 690 generators.put(getMethodReference(Magic.class, MagicNames.setIntAtOffset, Object.class, Offset.class, int.class, void.class), g); 691 generators.put(getMethodReference(Magic.class, MagicNames.setFloatAtOffset, Object.class, Offset.class, float.class, void.class), g); 692 if (VM.BuildFor64Addr) { 693 g = new Magic_Store64(); 694 } 695 generators.put(getMethodReference(Magic.class, MagicNames.setWordAtOffset, Object.class, Offset.class, Word.class, void.class), g); 696 generators.put(getMethodReference(Magic.class, MagicNames.setAddressAtOffset, Object.class, Offset.class, Address.class, void.class), g); 697 generators.put(getMethodReference(Magic.class, MagicNames.setExtentAtOffset, Object.class, Offset.class, Extent.class, void.class), g); 698 generators.put(getMethodReference(Magic.class, MagicNames.setOffsetAtOffset, Object.class, Offset.class, Offset.class, void.class), g); 699 if (VALIDATE_OBJECT_REFERENCES) { 700 g = new EarlyReferenceCheckDecorator(NO_SLOT, g); 701 } 702 generators.put(getMethodReference(Magic.class, MagicNames.setObjectAtOffset, Object.class, Offset.class, Object.class, void.class), g); 703 } 704 705 /** 706 * Store a 32bit quantity to an address plus offset in the format used in 707 * {@link Magic} with an additional meta-data argument 708 */ 709 private static final class Magic_Store32_MD extends MagicGenerator { 710 @Override 711 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 712 asm.emitPOP_Reg(T0); // discard meta-data 713 asm.emitPOP_Reg(T0); // value 714 asm.emitPOP_Reg(S0); // offset 715 asm.emitPOP_Reg(T1); // obj ref 716 asm.emitMOV_RegIdx_Reg(T1, S0, BYTE, NO_SLOT, T0); // [T1+S0] <- T0 717 } 718 } 719 /** 720 * Store a 64bit quantity to an address plus offset in the format used in 721 * {@link Magic} with an additional meta-data argument 722 */ 723 private static final class Magic_Store64_MD extends MagicGenerator { 724 @Override 725 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 726 asm.emitPOP_Reg(T0); // discard meta-data 727 asm.emitPOP_Reg(T0); // value 728 asm.emitPOP_Reg(S0); // offset 729 asm.emitPOP_Reg(T1); // obj ref 730 asm.emitMOV_RegIdx_Reg_Quad(T1, S0, BYTE, NO_SLOT, T0); // [T1+S0] <- T0 731 } 732 } 733 static { 734 MagicGenerator g = new Magic_Store32_MD(); 735 generators.put(getMethodReference(Magic.class, MagicNames.setIntAtOffset, Object.class, Offset.class, int.class, int.class, void.class), g); 736 generators.put(getMethodReference(Magic.class, MagicNames.setFloatAtOffset, Object.class, Offset.class, float.class, int.class, void.class), g); 737 if (VM.BuildFor64Addr) { 738 g = new Magic_Store64_MD(); 739 } 740 generators.put(getMethodReference(Magic.class, MagicNames.setWordAtOffset, Object.class, Offset.class, Word.class, int.class, void.class), g); 741 generators.put(getMethodReference(Magic.class, MagicNames.setAddressAtOffset, Object.class, Offset.class, Address.class, int.class, void.class), g); 742 generators.put(getMethodReference(Magic.class, MagicNames.setOffsetAtOffset, Object.class, Offset.class, Offset.class, int.class, void.class), g); 743 generators.put(getMethodReference(Magic.class, MagicNames.setExtentAtOffset, Object.class, Offset.class, Extent.class, int.class, void.class), g); 744 if (VALIDATE_OBJECT_REFERENCES) { 745 g = new EarlyReferenceCheckDecorator(ONE_SLOT, g); 746 } 747 generators.put(getMethodReference(Magic.class, MagicNames.setObjectAtOffset, Object.class, Offset.class, Object.class, int.class, void.class), g); 748 } 749 750 /** 751 * Store a 8bit quantity to an address plus offset 752 */ 753 private static final class Store8 extends MagicGenerator { 754 @Override 755 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 756 // No offset 757 asm.emitPOP_Reg(T0); // value 758 asm.emitPOP_Reg(T1); // base 759 asm.emitMOV_RegInd_Reg_Byte(T1, T0); 760 } 761 } 762 static { 763 MagicGenerator g = new Store8(); 764 generators.put(getMethodReference(Address.class, MagicNames.store, byte.class, void.class), g); 765 generators.put(getMethodReference(Address.class, MagicNames.store, boolean.class, void.class), g); 766 } 767 768 /** 769 * Store a 8bit quantity to an address plus offset 770 */ 771 private static final class Store8_Offset extends MagicGenerator { 772 @Override 773 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 774 // Store at offset 775 asm.emitPOP_Reg(S0); // offset 776 asm.emitPOP_Reg(T0); // value 777 asm.emitPOP_Reg(T1); // base 778 asm.emitMOV_RegIdx_Reg_Byte(T1, S0, BYTE, NO_SLOT, T0); // [T1+S0] <- (byte) T0 779 } 780 } 781 static { 782 MagicGenerator g = new Store8_Offset(); 783 generators.put(getMethodReference(Address.class, MagicNames.store, byte.class, Offset.class, void.class), g); 784 generators.put(getMethodReference(Address.class, MagicNames.store, boolean.class, Offset.class, void.class), g); 785 } 786 787 /** 788 * Store a 8bit quantity to an address plus offset in the format used in {@link Magic} 789 */ 790 private static final class Magic_Store8 extends MagicGenerator { 791 @Override 792 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 793 asm.emitPOP_Reg(T0); // value 794 asm.emitPOP_Reg(S0); // offset 795 asm.emitPOP_Reg(T1); // obj ref 796 asm.emitMOV_RegIdx_Reg_Byte(T1, S0, BYTE, NO_SLOT, T0); // [T1+S0] <- (byte) T0 797 } 798 } 799 static { 800 MagicGenerator g = new Magic_Store8(); 801 generators.put(getMethodReference(Magic.class, MagicNames.setBooleanAtOffset, Object.class, Offset.class, boolean.class, void.class), g); 802 generators.put(getMethodReference(Magic.class, MagicNames.setByteAtOffset, Object.class, Offset.class, byte.class, void.class), g); 803 } 804 805 /** 806 * Store a 8bit quantity to an address plus offset in the format used in 807 * {@link Magic} with an additional meta-data argument 808 */ 809 private static final class Magic_Store8_MD extends MagicGenerator { 810 @Override 811 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 812 asm.emitPOP_Reg(T0); // discard meta-data 813 asm.emitPOP_Reg(T0); // value 814 asm.emitPOP_Reg(S0); // offset 815 asm.emitPOP_Reg(T1); // obj ref 816 asm.emitMOV_RegIdx_Reg_Byte(T1, S0, BYTE, NO_SLOT, T0); // [T1+S0] <- (byte) T0 817 } 818 } 819 static { 820 MagicGenerator g = new Magic_Store8_MD(); 821 generators.put(getMethodReference(Magic.class, MagicNames.setBooleanAtOffset, Object.class, Offset.class, boolean.class, int.class, void.class), g); 822 generators.put(getMethodReference(Magic.class, MagicNames.setByteAtOffset, Object.class, Offset.class, byte.class, int.class, void.class), g); 823 } 824 825 /** 826 * Store a 16bit quantity to an address 827 */ 828 private static final class Store16 extends MagicGenerator { 829 @Override 830 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 831 // No offset 832 asm.emitPOP_Reg(T0); // value 833 asm.emitPOP_Reg(T1); // base 834 asm.emitMOV_RegInd_Reg_Word(T1, T0); 835 } 836 } 837 static { 838 MagicGenerator g = new Store16(); 839 generators.put(getMethodReference(Address.class, MagicNames.store, short.class, void.class), g); 840 generators.put(getMethodReference(Address.class, MagicNames.store, char.class, void.class), g); 841 } 842 843 /** 844 * Store a 16bit quantity to an address plus offset 845 */ 846 private static final class Store16_Offset extends MagicGenerator { 847 @Override 848 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 849 // Store at offset 850 asm.emitPOP_Reg(S0); // offset 851 asm.emitPOP_Reg(T0); // value 852 asm.emitPOP_Reg(T1); // base 853 asm.emitMOV_RegIdx_Reg_Word(T1, S0, BYTE, NO_SLOT, T0); // [T1+S0] <- (word) T0 854 } 855 } 856 static { 857 MagicGenerator g = new Store16_Offset(); 858 generators.put(getMethodReference(Address.class, MagicNames.store, short.class, Offset.class, void.class), g); 859 generators.put(getMethodReference(Address.class, MagicNames.store, char.class, Offset.class, void.class), g); 860 } 861 862 /** 863 * Store a 16 bit quantity to an address plus offset in the format used in {@link Magic} 864 */ 865 private static final class Magic_Store16 extends MagicGenerator { 866 @Override 867 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 868 asm.emitPOP_Reg(T0); // value 869 asm.emitPOP_Reg(S0); // offset 870 asm.emitPOP_Reg(T1); // obj ref 871 asm.emitMOV_RegIdx_Reg_Word(T1, S0, BYTE, NO_SLOT, T0); // [T1+S0] <- (word) T0 872 } 873 } 874 static { 875 MagicGenerator g = new Magic_Store16(); 876 generators.put(getMethodReference(Magic.class, MagicNames.setCharAtOffset, Object.class, Offset.class, char.class, void.class), g); 877 generators.put(getMethodReference(Magic.class, MagicNames.setShortAtOffset, Object.class, Offset.class, short.class, void.class), g); 878 } 879 880 /** 881 * Store a 16bit quantity to an address plus offset in the format used in 882 * {@link Magic} with an additional meta-data argument 883 */ 884 private static final class Magic_Store16_MD extends MagicGenerator { 885 @Override 886 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 887 asm.emitPOP_Reg(T0); // discard meta-data 888 asm.emitPOP_Reg(T0); // value 889 asm.emitPOP_Reg(S0); // offset 890 asm.emitPOP_Reg(T1); // obj ref 891 asm.emitMOV_RegIdx_Reg_Word(T1, S0, BYTE, NO_SLOT, T0); // [T1+S0] <- (word) T0 892 } 893 } 894 static { 895 MagicGenerator g = new Magic_Store16_MD(); 896 generators.put(getMethodReference(Magic.class, MagicNames.setCharAtOffset, Object.class, Offset.class, char.class, int.class, void.class), g); 897 generators.put(getMethodReference(Magic.class, MagicNames.setShortAtOffset, Object.class, Offset.class, short.class, int.class, void.class), g); 898 } 899 900 /** 901 * Store a long-sized quantity to an address 902 */ 903 private static final class StoreLong extends MagicGenerator { 904 @Override 905 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 906 // No offset 907 if (VM.BuildFor32Addr) { 908 asm.emitPOP_Reg(T0); // value low 909 asm.emitPOP_Reg(T1); // value high 910 asm.emitPOP_Reg(S0); // base 911 asm.emitMOV_RegInd_Reg(S0, T0); // value low 912 asm.emitMOV_RegDisp_Reg(S0, ONE_SLOT, T1); // value high 913 } else { 914 asm.emitPOP_Reg(T0); // value 915 asm.emitPOP_Reg(T1); // throw away slot 916 asm.emitPOP_Reg(T1); // base 917 asm.emitMOV_RegInd_Reg_Quad(T1, T0); 918 } 919 } 920 } 921 static { 922 MagicGenerator g = new StoreLong(); 923 generators.put(getMethodReference(Address.class, MagicNames.store, long.class, void.class), g); 924 generators.put(getMethodReference(Address.class, MagicNames.store, double.class, void.class), g); 925 } 926 927 /** 928 * Store a long-sized quantity to an address plus offset 929 */ 930 private static final class StoreLong_Offset extends MagicGenerator { 931 @Override 932 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 933 // Store at offset 934 if (VM.BuildFor32Addr) { 935 asm.emitPOP_Reg(T0); // T0 = offset 936 asm.emitADD_Reg_RegDisp(T0, SP, TWO_SLOTS); // T0 = base+offset 937 asm.emitPOP_RegInd(T0); // [T0] <- value low 938 asm.emitPOP_RegDisp(T0, ONE_SLOT); // [T0+4] <- value high 939 asm.emitPOP_Reg(T0); // throw away slot 940 } else { 941 asm.emitPOP_Reg(T0); // offset 942 asm.emitADD_Reg_RegDisp_Quad(T0, SP, TWO_SLOTS); // T0 = base+offset 943 asm.emitPOP_RegInd(T0); // T0 <- value 944 asm.emitPOP_Reg(T0); // throw away slot 945 asm.emitPOP_Reg(T0); // throw away slot 946 } 947 } 948 } 949 static { 950 MagicGenerator g = new StoreLong_Offset(); 951 generators.put(getMethodReference(Address.class, MagicNames.store, long.class, Offset.class, void.class), g); 952 generators.put(getMethodReference(Address.class, MagicNames.store, double.class, Offset.class, void.class), g); 953 } 954 955 /** 956 * Store a long-sized quantity to an address plus offset in the format used in 957 * {@link Magic} 958 */ 959 private static final class Magic_StoreLong extends MagicGenerator { 960 @Override 961 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 962 if (VM.BuildFor32Addr) { 963 asm.emitPOP_Reg(T0); // value low 964 asm.emitPOP_Reg(T1); // value high 965 asm.emitPOP_Reg(S0); // S0 = offset 966 asm.emitADD_Reg_RegInd(S0, SP); // S0 = base+offset 967 asm.emitMOV_RegInd_Reg(S0, T0); // [S0] <- value low 968 asm.emitPOP_Reg(T0); // throw away slot 969 asm.emitMOV_RegDisp_Reg(S0, ONE_SLOT, T1); // [S0+4] <- value high 970 } else { 971 asm.emitPOP_Reg(T0); // value 972 asm.emitPOP_Reg(T1); // throw away slot 973 asm.emitPOP_Reg(T1); // T1 = offset 974 asm.emitPOP_Reg(S0); // S0 = base 975 asm.emitMOV_RegIdx_Reg_Quad(S0, T1, BYTE, NO_SLOT, T0); // [base+offset] <- T0 976 } 977 } 978 } 979 static { 980 MagicGenerator g = new Magic_StoreLong(); 981 generators.put(getMethodReference(Magic.class, MagicNames.setLongAtOffset, Object.class, Offset.class, long.class, void.class), g); 982 generators.put(getMethodReference(Magic.class, MagicNames.setDoubleAtOffset, Object.class, Offset.class, double.class, void.class), g); 983 } 984 985 /** 986 * Store a long-sized quantity to an address plus offset in the format used in 987 * {@link Magic} with an additional meta-data argument 988 */ 989 private static final class Magic_StoreLong_MD extends MagicGenerator { 990 @Override 991 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 992 asm.emitPOP_Reg(T0); // discard meta-data 993 if (VM.BuildFor32Addr) { 994 asm.emitPOP_Reg(T0); // value low 995 asm.emitPOP_Reg(T1); // value high 996 asm.emitPOP_Reg(S0); // S0 = offset 997 asm.emitADD_Reg_RegInd(S0, SP); // S0 = base+offset 998 asm.emitMOV_RegInd_Reg(S0, T0); // [S0] <- value low 999 asm.emitPOP_Reg(T0); // throw away slot 1000 asm.emitMOV_RegDisp_Reg(S0, ONE_SLOT, T1); // [S0+4] <- value high 1001 } else { 1002 asm.emitPOP_Reg(T0); // value 1003 asm.emitPOP_Reg(T1); // throw away slot 1004 asm.emitPOP_Reg(T1); // T1 = offset 1005 asm.emitPOP_Reg(S0); // S0 = base 1006 asm.emitMOV_RegIdx_Reg_Quad(S0, T1, BYTE, NO_SLOT, T0); // [base+offset] <- T0 1007 } 1008 } 1009 } 1010 static { 1011 MagicGenerator g = new Magic_StoreLong_MD(); 1012 generators.put(getMethodReference(Magic.class, MagicNames.setLongAtOffset, Object.class, Offset.class, long.class, int.class, void.class), g); 1013 generators.put(getMethodReference(Magic.class, MagicNames.setDoubleAtOffset, Object.class, Offset.class, double.class, int.class, void.class), g); 1014 } 1015 1016 /** 1017 * Compare and swap a 32/64 bit value 1018 */ 1019 private static final class Attempt extends MagicGenerator { 1020 /** Perform quad word CAS */ 1021 private final boolean quad; 1022 Attempt(boolean quad) { 1023 this.quad = quad; 1024 } 1025 @Override 1026 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 1027 asm.emitPOP_Reg(T1); // newVal 1028 asm.emitPOP_Reg(EAX); // oldVal (EAX/T0 is implicit arg to LCMPXCHG) 1029 // No offset 1030 asm.emitPOP_Reg(S1); // S1 = base 1031 asm.emitXOR_Reg_Reg(S0, S0); // S0 = 0 1032 asm.emitLockNextInstruction(); 1033 if (!quad) { 1034 asm.emitCMPXCHG_RegInd_Reg(S1, T1); // atomic compare-and-exchange 1035 } else { 1036 asm.emitCMPXCHG_RegInd_Reg_Quad(S1, T1); // atomic compare-and-exchange 1037 } 1038 asm.emitSET_Cond_Reg_Byte(EQ, S0); // S0 = (EAX == [S1]) ? 1 : 0 1039 asm.emitPUSH_Reg(S0); 1040 } 1041 } 1042 static { 1043 MagicGenerator g = new Attempt(DOUBLE_WORD); 1044 generators.put(getMethodReference(Address.class, MagicNames.attempt, int.class, int.class, boolean.class), g); 1045 if (VM.BuildFor64Addr) { 1046 g = new Attempt(QUAD_WORD); 1047 } 1048 generators.put(getMethodReference(Address.class, MagicNames.attempt, Address.class, Address.class, boolean.class), g); 1049 generators.put(getMethodReference(Address.class, MagicNames.attempt, Word.class, Word.class, boolean.class), g); 1050 if (VALIDATE_OBJECT_REFERENCES) { 1051 g = new EarlyReferenceCheckDecorator(NO_SLOT, g); 1052 g = new EarlyReferenceCheckDecorator(ONE_SLOT, g); 1053 } 1054 generators.put(getMethodReference(Address.class, MagicNames.attempt, ObjectReference.class, ObjectReference.class, boolean.class), g); 1055 } 1056 1057 /** 1058 * Compare and swap a 32/64 bit value at an address plus offset 1059 */ 1060 private static final class Attempt_Offset extends MagicGenerator { 1061 /** Perform quad word CAS */ 1062 private final boolean quad; 1063 Attempt_Offset(boolean quad) { 1064 this.quad = quad; 1065 } 1066 @Override 1067 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 1068 // Offset passed 1069 asm.emitPOP_Reg(S1); // S1 = offset 1070 asm.emitPOP_Reg(T1); // newVal 1071 asm.emitPOP_Reg(EAX); // oldVal (EAX is implicit arg to LCMPX 1072 asm.emitPOP_Reg(S0); // S0 = base 1073 if (VM.BuildFor32Addr) { 1074 asm.emitADD_Reg_Reg(S1, S0); // S1 = base+offset 1075 } else { 1076 asm.emitADD_Reg_Reg_Quad(S1, S0); // S1 = base+offset 1077 } 1078 asm.emitXOR_Reg_Reg(S0, S0); // S0 = 0 1079 asm.emitLockNextInstruction(); 1080 if (!quad) { 1081 asm.emitCMPXCHG_RegInd_Reg(S1, T1); // atomic compare-and-exchange 1082 } else { 1083 asm.emitCMPXCHG_RegInd_Reg_Quad(S1, T1); // atomic compare-and-exchange 1084 } 1085 asm.emitSET_Cond_Reg_Byte(EQ, S0); // S0 = (EAX == [S0]) ? 1 : 0 1086 asm.emitPUSH_Reg(S0); 1087 } 1088 } 1089 static { 1090 MagicGenerator g = new Attempt_Offset(DOUBLE_WORD); 1091 generators.put(getMethodReference(Address.class, MagicNames.attempt, int.class, int.class, Offset.class, boolean.class), g); 1092 if (VM.BuildFor64Addr) { 1093 g = new Attempt_Offset(QUAD_WORD); 1094 } 1095 generators.put(getMethodReference(Address.class, MagicNames.attempt, Address.class, Address.class, Offset.class, boolean.class), g); 1096 generators.put(getMethodReference(Address.class, MagicNames.attempt, Word.class, Word.class, Offset.class, boolean.class), g); 1097 if (VALIDATE_OBJECT_REFERENCES) { 1098 g = new EarlyReferenceCheckDecorator(ONE_SLOT, g); 1099 g = new EarlyReferenceCheckDecorator(TWO_SLOTS, g); 1100 } 1101 generators.put(getMethodReference(Address.class, MagicNames.attempt, ObjectReference.class, ObjectReference.class, Offset.class, boolean.class), g); 1102 } 1103 1104 /** 1105 * Compare and swap a 32/64 bit value in the format used in {@link Magic} 1106 */ 1107 private static final class Magic_Attempt extends MagicGenerator { 1108 /** Perform quad word CAS */ 1109 private final boolean quad; 1110 Magic_Attempt(boolean quad) { 1111 this.quad = quad; 1112 } 1113 @Override 1114 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 1115 // attempt gets called with four arguments: base, offset, oldVal, newVal 1116 // returns ([base+offset] == oldVal) 1117 // if ([base+offset] == oldVal) [base+offset] := newVal 1118 // (operation on memory is atomic) 1119 asm.emitPOP_Reg(T1); // newVal 1120 asm.emitPOP_Reg(EAX); // oldVal (EAX is implicit arg to LCMPXCNG 1121 asm.emitPOP_Reg(S1); // S1 = offset 1122 asm.emitPOP_Reg(S0); // S0 = base 1123 if (VM.BuildFor32Addr) { 1124 asm.emitADD_Reg_Reg(S1, S0); // S1 = base+offset 1125 } else { 1126 asm.emitADD_Reg_Reg_Quad(S1, S0); // S1 = base+offset 1127 } 1128 asm.emitXOR_Reg_Reg(S0, S0); // S0 = 0 1129 asm.emitLockNextInstruction(); 1130 if (!quad) { 1131 asm.emitCMPXCHG_RegInd_Reg(S1, T1); // atomic compare-and-exchange 1132 } else { 1133 asm.emitCMPXCHG_RegInd_Reg_Quad(S1, T1); // atomic compare-and-exchange 1134 } 1135 asm.emitSET_Cond_Reg_Byte(EQ, S0); // S0 = (EAX == [S1]) ? 1 : 0 1136 asm.emitPUSH_Reg(S0); 1137 } 1138 } 1139 static { 1140 MagicGenerator g = new Magic_Attempt(DOUBLE_WORD); 1141 generators.put(getMethodReference(Magic.class, MagicNames.attemptInt, Object.class, Offset.class, int.class, int.class, boolean.class), g); 1142 if (VM.BuildFor64Addr) { 1143 g = new Magic_Attempt(QUAD_WORD); 1144 } 1145 generators.put(getMethodReference(Magic.class, MagicNames.attemptAddress, Object.class, Offset.class, Address.class, Address.class, boolean.class), g); 1146 generators.put(getMethodReference(Magic.class, MagicNames.attemptWord, Object.class, Offset.class, Word.class, Word.class, boolean.class), g); 1147 if (VALIDATE_OBJECT_REFERENCES) { 1148 g = new EarlyReferenceCheckDecorator(NO_SLOT, g); 1149 g = new EarlyReferenceCheckDecorator(ONE_SLOT, g); 1150 g = new EarlyReferenceCheckDecorator(THREE_SLOTS, g); 1151 } 1152 generators.put(getMethodReference(Magic.class, MagicNames.attemptObject, Object.class, Offset.class, Object.class, Object.class, boolean.class), g); 1153 } 1154 1155 /** 1156 * Compare and swap a long-sized value in the format used in {@link Magic} 1157 */ 1158 private static final class Magic_AttemptLong extends MagicGenerator { 1159 @Override 1160 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 1161 // attempt gets called with four arguments: base, offset, oldVal, newVal 1162 // returns ([base+offset] == oldVal) 1163 // if ([base+offset] == oldVal) [base+offset] := newVal 1164 // (operation on memory is atomic) 1165 if (VM.BuildFor32Addr) { 1166 //t1:t0 with s0:ebx 1167 asm.emitMOV_Reg_RegDisp(T1, SP, THREE_SLOTS); 1168 asm.emitMOV_Reg_RegDisp(T0, SP, TWO_SLOTS); // T1:T0 (EDX:EAX) -> oldVal 1169 asm.emitMOV_RegDisp_Reg(SP, THREE_SLOTS, EBX); // Save EBX 1170 asm.emitMOV_RegDisp_Reg(SP, TWO_SLOTS, ESI); // Save ESI 1171 asm.emitMOV_Reg_RegInd(EBX, SP); 1172 asm.emitMOV_Reg_RegDisp(S0, SP, ONE_SLOT); // S0:EBX (ECX:EBX) -> newVal 1173 asm.emitMOV_Reg_RegDisp(ESI, SP, FIVE_SLOTS); // ESI := base 1174 asm.emitADD_Reg_RegDisp(ESI, SP, FOUR_SLOTS); // ESI += offset 1175 asm.emitLockNextInstruction(); 1176 asm.emitCMPXCHG8B_RegInd(ESI); // atomic compare-and-exchange 1177 ForwardReference fr1 = asm.forwardJcc(NE); // skip if compare fails 1178 asm.emitMOV_RegDisp_Imm(SP, FIVE_SLOTS, 1); // 'push' true (overwriting base) 1179 ForwardReference fr2 = asm.forwardJMP(); // skip if compare fails 1180 fr1.resolve(asm); 1181 asm.emitMOV_RegDisp_Imm(SP, FIVE_SLOTS, 0); // 'push' false (overwriting base) 1182 fr2.resolve(asm); 1183 asm.emitMOV_Reg_RegDisp(EBX, SP, THREE_SLOTS); // Restore EBX 1184 asm.emitMOV_Reg_RegDisp(ESI, SP, TWO_SLOTS); // Restore ESI 1185 asm.emitADD_Reg_Imm(SP, WORDSIZE * 5); // adjust SP popping the 4 args (6 slots) and pushing the result 1186 } else { 1187 asm.emitPOP_Reg(T1); // newVal 1188 asm.emitPOP_Reg(EAX); // junk 1189 asm.emitPOP_Reg(EAX); // oldVal (EAX/T0 is implicit arg to LCMPXCHG) 1190 asm.emitPOP_Reg(S1); // junk 1191 asm.emitPOP_Reg(S1); // S1 = offset 1192 asm.emitPOP_Reg(S0); // S0 = base 1193 asm.emitADD_Reg_Reg_Quad(S1, S0); // S1 = base+offset 1194 asm.emitXOR_Reg_Reg(S0, S0); // S0 = 0 1195 asm.emitLockNextInstruction(); 1196 asm.emitCMPXCHG_RegInd_Reg_Quad(S1, T1); // atomic compare-and-exchange 1197 asm.emitSET_Cond_Reg_Byte(EQ, S0); // S0 = (EAX == [S1]) ? 1 : 0 1198 asm.emitPUSH_Reg(S0); 1199 } 1200 } 1201 } 1202 static { 1203 MagicGenerator g = new Magic_AttemptLong(); 1204 generators.put(getMethodReference(Magic.class, MagicNames.attemptLong, Object.class, Offset.class, long.class, long.class, boolean.class), g); 1205 } 1206 1207 /** 1208 * Prefetch from an address 1209 */ 1210 private static final class Prefetch extends MagicGenerator { 1211 @Override 1212 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 1213 asm.emitPOP_Reg(EDI); 1214 asm.emitPREFETCHNTA_Reg(EDI); 1215 } 1216 } 1217 static { 1218 MagicGenerator g = new Prefetch(); 1219 generators.put(getMethodReference(Address.class, MagicNames.prefetch, void.class), g); 1220 generators.put(getMethodReference(Address.class, MagicNames.prefetchNTA, void.class), g); 1221 } 1222 1223 /** 1224 * Get the type from an object 1225 */ 1226 private static final class GetObjectType extends MagicGenerator { 1227 @Override 1228 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 1229 asm.emitPOP_Reg(T0); // object ref 1230 asm.baselineEmitLoadTIB(S0, T0); 1231 asm.emitPUSH_RegDisp(S0, Offset.fromIntZeroExtend(TIB_TYPE_INDEX << LG_WORDSIZE)); // push RVMType slot of TIB 1232 } 1233 } 1234 static { 1235 MagicGenerator g = new GetObjectType(); 1236 generators.put(getMethodReference(Magic.class, MagicNames.getObjectType, Object.class, RVMType.class), g); 1237 } 1238 1239 /** 1240 * Perform no-operation 1241 */ 1242 private static final class Nop extends MagicGenerator { 1243 @Override 1244 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 1245 } 1246 } 1247 static { 1248 MagicGenerator g = new Nop(); 1249 Class<?>[] unboxedTypes = new Class<?>[]{Address.class, Extent.class, Offset.class, Word.class}; 1250 for (Class<?> type : unboxedTypes) { 1251 generators.put(getMethodReference(type, MagicNames.wordFromInt, int.class, type), g); 1252 if (VM.BuildFor32Addr) { 1253 generators.put(getMethodReference(type, MagicNames.wordFromIntSignExtend, int.class, type), g); 1254 generators.put(getMethodReference(type, MagicNames.wordFromIntZeroExtend, int.class, type), g); 1255 } 1256 generators.put(getMethodReference(type, MagicNames.wordToInt, int.class), g); 1257 if (type != Address.class) 1258 generators.put(getMethodReference(type, MagicNames.wordToAddress, Address.class), g); 1259 if (type != Extent.class) 1260 generators.put(getMethodReference(type, MagicNames.wordToExtent, Extent.class), g); 1261 if (type != Offset.class) 1262 generators.put(getMethodReference(type, MagicNames.wordToOffset, Offset.class), g); 1263 if (type != Word.class) 1264 generators.put(getMethodReference(type, MagicNames.wordToWord, Word.class), g); 1265 } 1266 generators.put(getMethodReference(Magic.class, MagicNames.floatAsIntBits, float.class, int.class), g); 1267 generators.put(getMethodReference(Magic.class, MagicNames.intBitsAsFloat, int.class, float.class), g); 1268 generators.put(getMethodReference(Magic.class, MagicNames.doubleAsLongBits, double.class, long.class), g); 1269 generators.put(getMethodReference(Magic.class, MagicNames.longBitsAsDouble, long.class, double.class), g); 1270 generators.put(getMethodReference(Magic.class, MagicNames.sync, void.class), g); 1271 generators.put(getMethodReference(Magic.class, MagicNames.isync, void.class), g); 1272 generators.put(getMethodReference(Magic.class, MagicNames.combinedLoadBarrier, void.class), g); 1273 generators.put(getMethodReference(Magic.class, MagicNames.storeStoreBarrier, void.class), g); 1274 if (VALIDATE_OBJECT_REFERENCES) { 1275 g = new EarlyReferenceCheckDecorator(NO_SLOT, g); 1276 } 1277 for (Class<?> type : unboxedTypes) { 1278 generators.put(getMethodReference(type, MagicNames.wordFromObject, Object.class, type), g); 1279 generators.put(getMethodReference(type, MagicNames.wordToObject, Object.class), g); 1280 generators.put(getMethodReference(type, MagicNames.wordToObjectReference, ObjectReference.class), g); 1281 } 1282 generators.put(getMethodReference(ObjectReference.class, MagicNames.wordFromObject, Object.class, ObjectReference.class), g); 1283 generators.put(getMethodReference(ObjectReference.class, MagicNames.wordToObject, Object.class), g); 1284 generators.put(getMethodReference(ObjectReference.class, MagicNames.wordToAddress, Address.class), g); 1285 generators.put(getMethodReference(Magic.class, MagicNames.codeArrayAsObject, CodeArray.class, Object.class), g); 1286 generators.put(getMethodReference(Magic.class, MagicNames.tibAsObject, TIB.class, Object.class), g); 1287 generators.put(getMethodReference(Magic.class, MagicNames.objectAsAddress, Object.class, Address.class), g); 1288 generators.put(getMethodReference(Magic.class, MagicNames.addressAsByteArray, Address.class, byte[].class), g); 1289 generators.put(getMethodReference(Magic.class, MagicNames.addressAsObject, Address.class, Object.class), g); 1290 generators.put(getMethodReference(Magic.class, MagicNames.addressAsTIB, Address.class, TIB.class), g); 1291 generators.put(getMethodReference(Magic.class, MagicNames.objectAsType, Object.class, RVMType.class), g); 1292 generators.put(getMethodReference(Magic.class, MagicNames.objectAsShortArray, Object.class, short[].class), g); 1293 generators.put(getMethodReference(Magic.class, MagicNames.objectAsIntArray, Object.class, int[].class), g); 1294 generators.put(getMethodReference(Magic.class, MagicNames.objectAsThread, Object.class, RVMThread.class), g); 1295 } 1296 1297 /** 1298 * Generate the MFENCE instruction. 1299 */ 1300 private static final class MFence extends MagicGenerator { 1301 @Override 1302 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 1303 asm.emitMFENCE(); 1304 } 1305 } 1306 static { 1307 generators.put(getMethodReference(Magic.class, MagicNames.fence, void.class), new MFence()); 1308 } 1309 1310 /** 1311 * Perform an operation to release a stack slot 1312 */ 1313 private static final class FreeStackSlot extends MagicGenerator { 1314 @Override 1315 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 1316 asm.emitPOP_Reg(T0); 1317 asm.emitPOP_Reg(T1); 1318 asm.emitPUSH_Reg(T0); 1319 } 1320 } 1321 static { 1322 MagicGenerator g = new FreeStackSlot(); 1323 Class<?>[] unboxedTypes = new Class<?>[]{Address.class, Extent.class, Offset.class, Word.class}; 1324 for (Class<?> type : unboxedTypes) { 1325 generators.put(getMethodReference(type, MagicNames.wordFromLong, long.class, type), g); 1326 } 1327 } 1328 1329 /** 1330 * Perform an operation to duplicate a stack slot 1331 */ 1332 private static final class DuplicateStackSlot extends MagicGenerator { 1333 @Override 1334 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 1335 asm.emitPOP_Reg(T0); 1336 asm.emitPUSH_Reg(T0); 1337 asm.emitPUSH_Reg(T0); 1338 } 1339 } 1340 static { 1341 if (VM.BuildFor64Addr) { 1342 MagicGenerator g = new DuplicateStackSlot(); 1343 Class<?>[] unboxedTypes = new Class<?>[]{Address.class, Extent.class, Offset.class, Word.class}; 1344 for (Class<?> type : unboxedTypes) { 1345 generators.put(getMethodReference(type, MagicNames.wordToLong, type, long.class), g); 1346 } 1347 } 1348 } 1349 1350 /** 1351 * Zero high part of 64bits 1352 */ 1353 private static final class QuadZeroExtend extends MagicGenerator { 1354 @Override 1355 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 1356 asm.emitPOP_Reg(T0); 1357 asm.emitMOV_Reg_Reg(T0, T0); 1358 asm.emitPUSH_Reg(T0); 1359 } 1360 } 1361 static { 1362 if (VM.BuildFor64Addr) { 1363 MagicGenerator g = new QuadZeroExtend(); 1364 Class<?>[] unboxedTypes = new Class<?>[]{Address.class, Extent.class, Offset.class, Word.class}; 1365 for (Class<?> type : unboxedTypes) { 1366 generators.put(getMethodReference(type, MagicNames.wordFromIntZeroExtend, int.class, type), g); 1367 } 1368 } 1369 } 1370 1371 /** 1372 * Sign extend 32bit int to 64bits 1373 */ 1374 private static final class QuadSignExtend extends MagicGenerator { 1375 @Override 1376 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 1377 asm.emitPOP_Reg(EAX); 1378 asm.emitCDQE(); 1379 asm.emitPUSH_Reg(EAX); 1380 } 1381 } 1382 static { 1383 if (VM.BuildFor64Addr) { 1384 MagicGenerator g = new QuadSignExtend(); 1385 Class<?>[] unboxedTypes = new Class<?>[]{Address.class, Extent.class, Offset.class, Word.class}; 1386 for (Class<?> type : unboxedTypes) { 1387 generators.put(getMethodReference(type, MagicNames.wordFromIntSignExtend, int.class, type), g); 1388 } 1389 } 1390 } 1391 1392 /** 1393 * Generate an address constant 1394 */ 1395 private static final class AddressConstant extends MagicGenerator { 1396 final int value; 1397 AddressConstant(int value) { 1398 this.value = value; 1399 } 1400 @Override 1401 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 1402 asm.emitPUSH_Imm(value); 1403 } 1404 } 1405 static { 1406 MagicGenerator zero = new AddressConstant(0); 1407 MagicGenerator one = new AddressConstant(1); 1408 MagicGenerator max = new AddressConstant(-1); 1409 Class<?>[] unboxedTypes = new Class<?>[]{Address.class, Extent.class, Offset.class, Word.class}; 1410 for (Class<?> type : unboxedTypes) { 1411 generators.put(getMethodReference(type, MagicNames.wordZero, type), zero); 1412 generators.put(getMethodReference(type, MagicNames.wordOne, type), one); 1413 generators.put(getMethodReference(type, MagicNames.wordMax, type), max); 1414 } 1415 generators.put(getMethodReference(ObjectReference.class, MagicNames.wordNull, ObjectReference.class), zero); 1416 if (JTOC_REGISTER == null) { 1417 MagicGenerator g = new AddressConstant(Magic.getTocPointer().toInt()); 1418 generators.put(getMethodReference(Magic.class, MagicNames.getJTOC, Address.class), g); 1419 generators.put(getMethodReference(Magic.class, MagicNames.getTocPointer, Address.class), g); 1420 } 1421 } 1422 1423 /** 1424 * Address comparison 1425 */ 1426 private static final class AddressComparison extends MagicGenerator { 1427 final byte comparator; 1428 AddressComparison(byte comparator) { 1429 this.comparator = comparator; 1430 } 1431 @Override 1432 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 1433 asm.emitPOP_Reg(S0); 1434 asm.emitPOP_Reg(T0); 1435 if (VM.BuildFor32Addr) { 1436 asm.emitCMP_Reg_Reg(T0, S0); 1437 } else { 1438 asm.emitCMP_Reg_Reg_Quad(T0, S0); 1439 } 1440 ForwardReference fr1 = asm.forwardJcc(comparator); 1441 asm.emitPUSH_Imm(0); 1442 ForwardReference fr2 = asm.forwardJMP(); 1443 fr1.resolve(asm); 1444 asm.emitPUSH_Imm(1); 1445 fr2.resolve(asm); 1446 } 1447 } 1448 static { 1449 MagicGenerator llt = new AddressComparison(LLT); 1450 MagicGenerator lle = new AddressComparison(LLE); 1451 MagicGenerator lgt = new AddressComparison(LGT); 1452 MagicGenerator lge = new AddressComparison(LGE); 1453 MagicGenerator eq = new AddressComparison(EQ); 1454 MagicGenerator ne = new AddressComparison(NE); 1455 // Unsigned unboxed types 1456 Class<?>[] unboxedTypes = new Class<?>[]{Address.class, Extent.class, Word.class}; 1457 for (Class<?> type : unboxedTypes) { 1458 generators.put(getMethodReference(type, MagicNames.wordLT, type, boolean.class), llt); 1459 generators.put(getMethodReference(type, MagicNames.wordLE, type, boolean.class), lle); 1460 generators.put(getMethodReference(type, MagicNames.wordGT, type, boolean.class), lgt); 1461 generators.put(getMethodReference(type, MagicNames.wordGE, type, boolean.class), lge); 1462 generators.put(getMethodReference(type, MagicNames.wordEQ, type, boolean.class), eq); 1463 generators.put(getMethodReference(type, MagicNames.wordNE, type, boolean.class), ne); 1464 } 1465 MagicGenerator lt = new AddressComparison(LT); 1466 MagicGenerator le = new AddressComparison(LE); 1467 MagicGenerator gt = new AddressComparison(GT); 1468 MagicGenerator ge = new AddressComparison(GE); 1469 // Signed unboxed types 1470 unboxedTypes = new Class<?>[]{Offset.class}; 1471 for (Class<?> type : unboxedTypes) { 1472 generators.put(getMethodReference(type, MagicNames.wordsLT, type, boolean.class), lt); 1473 generators.put(getMethodReference(type, MagicNames.wordsLE, type, boolean.class), le); 1474 generators.put(getMethodReference(type, MagicNames.wordsGT, type, boolean.class), gt); 1475 generators.put(getMethodReference(type, MagicNames.wordsGE, type, boolean.class), ge); 1476 generators.put(getMethodReference(type, MagicNames.wordEQ, type, boolean.class), eq); 1477 generators.put(getMethodReference(type, MagicNames.wordNE, type, boolean.class), ne); 1478 } 1479 } 1480 1481 /** 1482 * Is an address zero? 1483 */ 1484 private static final class AddressComparison_isZero extends MagicGenerator { 1485 @Override 1486 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 1487 asm.emitPOP_Reg(T0); 1488 if (VM.BuildFor32Addr) { 1489 asm.emitTEST_Reg_Reg(T0, T0); 1490 } else { 1491 asm.emitTEST_Reg_Reg_Quad(T0, T0); 1492 } 1493 ForwardReference fr1 = asm.forwardJcc(EQ); 1494 asm.emitPUSH_Imm(0); 1495 ForwardReference fr2 = asm.forwardJMP(); 1496 fr1.resolve(asm); 1497 asm.emitPUSH_Imm(1); 1498 fr2.resolve(asm); 1499 } 1500 } 1501 static { 1502 MagicGenerator g = new AddressComparison_isZero(); 1503 Class<?>[] unboxedTypes = new Class<?>[]{Address.class, Extent.class, Offset.class, Word.class}; 1504 for (Class<?> type : unboxedTypes) { 1505 generators.put(getMethodReference(type, MagicNames.wordIsZero, boolean.class), g); 1506 } 1507 if (VALIDATE_OBJECT_REFERENCES) { 1508 g = new EarlyReferenceCheckDecorator(NO_SLOT, g); 1509 } 1510 generators.put(getMethodReference(ObjectReference.class, MagicNames.wordIsNull, boolean.class), g); 1511 } 1512 1513 /** 1514 * Is an address max? 1515 */ 1516 private static final class AddressComparison_isMax extends MagicGenerator { 1517 @Override 1518 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 1519 asm.emitPOP_Reg(T0); 1520 if (VM.BuildFor32Addr) { 1521 asm.emitCMP_Reg_Imm(T0, -1); 1522 } else { 1523 asm.emitCMP_Reg_Imm_Quad(T0, -1); 1524 } 1525 ForwardReference fr1 = asm.forwardJcc(EQ); 1526 asm.emitPUSH_Imm(0); 1527 ForwardReference fr2 = asm.forwardJMP(); 1528 fr1.resolve(asm); 1529 asm.emitPUSH_Imm(1); 1530 fr2.resolve(asm); 1531 } 1532 } 1533 static { 1534 MagicGenerator g = new AddressComparison_isMax(); 1535 Class<?>[] unboxedTypes = new Class<?>[]{Address.class, Extent.class, Offset.class, Word.class}; 1536 for (Class<?> type : unboxedTypes) { 1537 generators.put(getMethodReference(type, MagicNames.wordIsMax, boolean.class), g); 1538 } 1539 } 1540 1541 /** 1542 * Addition of words 1543 */ 1544 private static final class WordPlus extends MagicGenerator { 1545 @Override 1546 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 1547 asm.emitPOP_Reg(T0); 1548 if (VM.BuildFor32Addr) { 1549 asm.emitADD_RegInd_Reg(SP, T0); 1550 } else { 1551 asm.emitADD_RegInd_Reg_Quad(SP, T0); 1552 } 1553 } 1554 } 1555 /** 1556 * Special case of 64bit addition to 32bit value 1557 */ 1558 private static final class WordPlus32 extends MagicGenerator { 1559 @Override 1560 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 1561 asm.emitPOP_Reg(EAX); 1562 asm.emitCDQE(); 1563 asm.emitADD_RegInd_Reg_Quad(SP, EAX); 1564 } 1565 } 1566 static { 1567 MagicGenerator g = new WordPlus(); 1568 generators.put(getMethodReference(Address.class, MagicNames.wordPlus, Offset.class, Address.class), g); 1569 generators.put(getMethodReference(Address.class, MagicNames.wordPlus, Extent.class, Address.class), g); 1570 generators.put(getMethodReference(Extent.class, MagicNames.wordPlus, Extent.class, Extent.class), g); 1571 generators.put(getMethodReference(Offset.class, MagicNames.wordPlus, Offset.class, Offset.class), g); 1572 generators.put(getMethodReference(Word.class, MagicNames.wordPlus, Word.class, Word.class), g); 1573 generators.put(getMethodReference(Word.class, MagicNames.wordPlus, Offset.class, Word.class), g); 1574 generators.put(getMethodReference(Word.class, MagicNames.wordPlus, Extent.class, Word.class), g); 1575 if (VM.BuildFor64Addr) { 1576 g = new WordPlus32(); 1577 } 1578 generators.put(getMethodReference(Address.class, MagicNames.wordPlus, int.class, Address.class), g); 1579 generators.put(getMethodReference(Extent.class, MagicNames.wordPlus, int.class, Extent.class), g); 1580 generators.put(getMethodReference(Offset.class, MagicNames.wordPlus, int.class, Offset.class), g); 1581 } 1582 1583 /** 1584 * Subtraction of words 1585 */ 1586 private static final class WordMinus extends MagicGenerator { 1587 @Override 1588 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 1589 asm.emitPOP_Reg(T0); 1590 if (VM.BuildFor32Addr) { 1591 asm.emitSUB_RegInd_Reg(SP, T0); 1592 } else { 1593 asm.emitSUB_RegInd_Reg_Quad(SP, T0); 1594 } 1595 } 1596 } 1597 /** 1598 * Special case of 64bit subtraction to 32bit value 1599 */ 1600 private static final class WordMinus32 extends MagicGenerator { 1601 @Override 1602 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 1603 asm.emitPOP_Reg(EAX); 1604 asm.emitCDQE(); 1605 asm.emitSUB_RegInd_Reg_Quad(SP, EAX); 1606 } 1607 } 1608 static { 1609 MagicGenerator g = new WordMinus(); 1610 generators.put(getMethodReference(Address.class, MagicNames.wordMinus, Offset.class, Address.class), g); 1611 generators.put(getMethodReference(Address.class, MagicNames.wordMinus, Extent.class, Address.class), g); 1612 generators.put(getMethodReference(Address.class, MagicNames.wordDiff, Address.class, Offset.class), g); 1613 generators.put(getMethodReference(Extent.class, MagicNames.wordMinus, Extent.class, Extent.class), g); 1614 generators.put(getMethodReference(Offset.class, MagicNames.wordMinus, Offset.class, Offset.class), g); 1615 generators.put(getMethodReference(Word.class, MagicNames.wordMinus, Word.class, Word.class), g); 1616 generators.put(getMethodReference(Word.class, MagicNames.wordMinus, Offset.class, Word.class), g); 1617 generators.put(getMethodReference(Word.class, MagicNames.wordMinus, Extent.class, Word.class), g); 1618 if (VM.BuildFor64Addr) { 1619 g = new WordMinus32(); 1620 } 1621 generators.put(getMethodReference(Address.class, MagicNames.wordMinus, int.class, Address.class), g); 1622 generators.put(getMethodReference(Extent.class, MagicNames.wordMinus, int.class, Extent.class), g); 1623 generators.put(getMethodReference(Offset.class, MagicNames.wordMinus, int.class, Offset.class), g); 1624 } 1625 1626 /** 1627 * Logical and of words 1628 */ 1629 private static final class WordAnd extends MagicGenerator { 1630 @Override 1631 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 1632 asm.emitPOP_Reg(T0); 1633 if (VM.BuildFor32Addr) { 1634 asm.emitAND_RegInd_Reg(SP, T0); 1635 } else { 1636 asm.emitAND_RegInd_Reg_Quad(SP, T0); 1637 } 1638 } 1639 } 1640 static { 1641 MagicGenerator g = new WordAnd(); 1642 generators.put(getMethodReference(Word.class, MagicNames.wordAnd, Word.class, Word.class), g); 1643 } 1644 1645 /** 1646 * Logical or of words 1647 */ 1648 private static final class WordOr extends MagicGenerator { 1649 @Override 1650 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 1651 asm.emitPOP_Reg(T0); 1652 if (VM.BuildFor32Addr) { 1653 asm.emitOR_RegInd_Reg(SP, T0); 1654 } else { 1655 asm.emitOR_RegInd_Reg_Quad(SP, T0); 1656 } 1657 } 1658 } 1659 static { 1660 MagicGenerator g = new WordOr(); 1661 generators.put(getMethodReference(Word.class, MagicNames.wordOr, Word.class, Word.class), g); 1662 } 1663 1664 /** 1665 * Logical xor of words 1666 */ 1667 private static final class WordXor extends MagicGenerator { 1668 @Override 1669 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 1670 asm.emitPOP_Reg(T0); 1671 if (VM.BuildFor32Addr) { 1672 asm.emitXOR_RegInd_Reg(SP, T0); 1673 } else { 1674 asm.emitXOR_RegInd_Reg_Quad(SP, T0); 1675 } 1676 } 1677 } 1678 static { 1679 MagicGenerator g = new WordXor(); 1680 generators.put(getMethodReference(Word.class, MagicNames.wordXor, Word.class, Word.class), g); 1681 } 1682 1683 /** 1684 * Logical left shift of words 1685 */ 1686 private static final class WordLsh extends MagicGenerator { 1687 @Override 1688 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 1689 asm.emitPOP_Reg(ECX); 1690 if (VM.BuildFor32Addr) { 1691 asm.emitSHL_RegInd_Reg(SP, ECX); 1692 } else { 1693 asm.emitSHL_RegInd_Reg_Quad(SP, ECX); 1694 } 1695 } 1696 } 1697 static { 1698 MagicGenerator g = new WordLsh(); 1699 generators.put(getMethodReference(Word.class, MagicNames.wordLsh, int.class, Word.class), g); 1700 } 1701 1702 /** 1703 * Logical right shift of words 1704 */ 1705 private static final class WordRshl extends MagicGenerator { 1706 @Override 1707 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 1708 asm.emitPOP_Reg(ECX); 1709 if (VM.BuildFor32Addr) { 1710 asm.emitSHR_RegInd_Reg(SP, ECX); 1711 } else { 1712 asm.emitSHR_RegInd_Reg_Quad(SP, ECX); 1713 } 1714 } 1715 } 1716 static { 1717 MagicGenerator g = new WordRshl(); 1718 generators.put(getMethodReference(Word.class, MagicNames.wordRshl, int.class, Word.class), g); 1719 } 1720 1721 /** 1722 * Arithmetic right shift of words 1723 */ 1724 private static final class WordRsha extends MagicGenerator { 1725 @Override 1726 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 1727 asm.emitPOP_Reg(ECX); 1728 if (VM.BuildFor32Addr) { 1729 asm.emitSAR_RegInd_Reg(SP, ECX); 1730 } else { 1731 asm.emitSAR_RegInd_Reg_Quad(SP, ECX); 1732 } 1733 } 1734 } 1735 static { 1736 MagicGenerator g = new WordRsha(); 1737 generators.put(getMethodReference(Word.class, MagicNames.wordRsha, int.class, Word.class), g); 1738 } 1739 1740 /** 1741 * Logical not of word 1742 */ 1743 private static final class WordNot extends MagicGenerator { 1744 @Override 1745 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 1746 if (VM.BuildFor32Addr) { 1747 asm.emitNOT_RegInd(SP); 1748 } else { 1749 asm.emitNOT_RegInd_Quad(SP); 1750 } 1751 } 1752 } 1753 static { 1754 MagicGenerator g = new WordNot(); 1755 generators.put(getMethodReference(Word.class, MagicNames.wordNot, Word.class), g); 1756 } 1757 1758 /** 1759 * Convert word to long 1760 */ 1761 private static final class WordToLong extends MagicGenerator { 1762 @Override 1763 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 1764 asm.emitPOP_Reg(T0); 1765 if (VM.BuildFor32Addr) { 1766 asm.emitPUSH_Imm(0); // upper 32 bits 1767 asm.emitPUSH_Reg(T0); // lower 32 bits 1768 } else { 1769 asm.emitPUSH_Reg(T0); // adjust stack 1770 asm.emitPUSH_Reg(T0); // long value 1771 } 1772 } 1773 } 1774 static { 1775 MagicGenerator g = new WordToLong(); 1776 Class<?>[] unboxedTypes = new Class<?>[]{Address.class, Extent.class, Offset.class, Word.class}; 1777 for (Class<?> type : unboxedTypes) { 1778 generators.put(getMethodReference(type, MagicNames.wordToLong, long.class), g); 1779 } 1780 } 1781 1782 /** 1783 * Set a register to a value from the stack 1784 */ 1785 private static final class SetRegister extends MagicGenerator { 1786 private final GPR reg; 1787 SetRegister(GPR reg) { 1788 this.reg = reg; 1789 } 1790 @Override 1791 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 1792 asm.emitPOP_Reg(reg); 1793 } 1794 } 1795 static { 1796 generators.put(getMethodReference(Magic.class, MagicNames.setESIAsThread, RVMThread.class, void.class), 1797 new SetRegister(ESI)); 1798 generators.put(getMethodReference(Magic.class, MagicNames.setThreadRegister, RVMThread.class, void.class), 1799 new SetRegister(TR)); 1800 } 1801 1802 /** 1803 * Put a register on to the stack 1804 */ 1805 private static final class GetRegister extends MagicGenerator { 1806 private final GPR reg; 1807 GetRegister(GPR reg) { 1808 this.reg = reg; 1809 } 1810 @Override 1811 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 1812 asm.emitPUSH_Reg(reg); 1813 } 1814 } 1815 static { 1816 generators.put(getMethodReference(Magic.class, MagicNames.getESIAsThread, RVMThread.class), 1817 new GetRegister(ESI)); 1818 generators.put(getMethodReference(Magic.class, MagicNames.getThreadRegister, RVMThread.class), 1819 new GetRegister(TR)); 1820 if (JTOC_REGISTER != null) { 1821 MagicGenerator g = new GetRegister(JTOC_REGISTER); 1822 generators.put(getMethodReference(Magic.class, MagicNames.getJTOC, Address.class), g); 1823 generators.put(getMethodReference(Magic.class, MagicNames.getTocPointer, Address.class), g); 1824 } 1825 } 1826 1827 /** 1828 * Reflective method dispatch 1829 */ 1830 private static final class InvokeMethodReturningObject extends MagicGenerator { 1831 @Override 1832 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 1833 Offset offset = ArchEntrypoints.reflectiveMethodInvokerInstructionsField.getOffset(); 1834 BaselineCompilerImpl.genParameterRegisterLoad(asm, 5); // pass 5 parameter words 1835 asm.generateJTOCcall(offset); 1836 asm.emitPUSH_Reg(T0); 1837 } 1838 } 1839 static { 1840 MagicGenerator g = new InvokeMethodReturningObject(); 1841 if (VALIDATE_OBJECT_REFERENCES) { 1842 g = new LateReferenceCheckDecorator(NO_SLOT, g); 1843 } 1844 generators.put(getMethodReference(Magic.class, MagicNames.invokeMethodReturningObject, CodeArray.class, WordArray.class, double[].class, byte[].class, WordArray.class, Object.class), g); 1845 } 1846 1847 /** 1848 * Reflective method dispatch 1849 */ 1850 private static final class InvokeMethodReturningVoid extends MagicGenerator { 1851 @Override 1852 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 1853 Offset offset = ArchEntrypoints.reflectiveMethodInvokerInstructionsField.getOffset(); 1854 BaselineCompilerImpl.genParameterRegisterLoad(asm, 5); // pass 5 parameter words 1855 asm.generateJTOCcall(offset); 1856 } 1857 } 1858 static { 1859 MagicGenerator g = new InvokeMethodReturningVoid(); 1860 generators.put(getMethodReference(Magic.class, MagicNames.invokeMethodReturningVoid, CodeArray.class, WordArray.class, double[].class, byte[].class, WordArray.class, void.class), g); 1861 } 1862 1863 /** 1864 * Reflective method dispatch 1865 */ 1866 private static final class InvokeMethodReturningInt extends MagicGenerator { 1867 @Override 1868 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 1869 Offset offset = ArchEntrypoints.reflectiveMethodInvokerInstructionsField.getOffset(); 1870 BaselineCompilerImpl.genParameterRegisterLoad(asm, 5); // pass 5 parameter words 1871 asm.generateJTOCcall(offset); 1872 asm.emitPUSH_Reg(T0); 1873 } 1874 } 1875 static { 1876 MagicGenerator g = new InvokeMethodReturningInt(); 1877 generators.put(getMethodReference(Magic.class, MagicNames.invokeMethodReturningInt, CodeArray.class, WordArray.class, double[].class, byte[].class, WordArray.class, int.class), g); 1878 } 1879 1880 /** 1881 * Reflective method dispatch 1882 */ 1883 private static final class InvokeMethodReturningLong extends MagicGenerator { 1884 @Override 1885 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 1886 Offset offset = ArchEntrypoints.reflectiveMethodInvokerInstructionsField.getOffset(); 1887 BaselineCompilerImpl.genParameterRegisterLoad(asm, 5); // pass 5 parameter words 1888 asm.generateJTOCcall(offset); 1889 if (VM.BuildFor32Addr) { 1890 asm.emitPUSH_Reg(T0); // high half 1891 asm.emitPUSH_Reg(T1); // low half 1892 } else { 1893 asm.emitPUSH_Reg(T0); // fill slot that will be thrown away or ignored 1894 asm.emitPUSH_Reg(T0); // push long value 1895 } 1896 } 1897 } 1898 static { 1899 MagicGenerator g = new InvokeMethodReturningLong(); 1900 generators.put(getMethodReference(Magic.class, MagicNames.invokeMethodReturningLong, CodeArray.class, WordArray.class, double[].class, byte[].class, WordArray.class, long.class), g); 1901 } 1902 1903 /** 1904 * Reflective method dispatch 1905 */ 1906 private static final class InvokeMethodReturningFloat extends MagicGenerator { 1907 @Override 1908 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 1909 Offset offset = ArchEntrypoints.reflectiveMethodInvokerInstructionsField.getOffset(); 1910 BaselineCompilerImpl.genParameterRegisterLoad(asm, 5); // pass 5 parameter words 1911 asm.generateJTOCcall(offset); 1912 asm.emitPUSH_Reg(T0); // create space 1913 if (SSE2_FULL) { 1914 asm.emitMOVSS_RegInd_Reg(SP, XMM0); 1915 } else { 1916 asm.emitFSTP_RegInd_Reg(SP, FP0); 1917 } 1918 } 1919 } 1920 static { 1921 MagicGenerator g = new InvokeMethodReturningFloat(); 1922 generators.put(getMethodReference(Magic.class, MagicNames.invokeMethodReturningFloat, CodeArray.class, WordArray.class, double[].class, byte[].class, WordArray.class, float.class), g); 1923 } 1924 1925 /** 1926 * Reflective method dispatch 1927 */ 1928 private static final class InvokeMethodReturningDouble extends MagicGenerator { 1929 @Override 1930 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 1931 Offset offset = ArchEntrypoints.reflectiveMethodInvokerInstructionsField.getOffset(); 1932 BaselineCompilerImpl.genParameterRegisterLoad(asm, 5); // pass 5 parameter words 1933 asm.generateJTOCcall(offset); 1934 asm.emitPUSH_Reg(T0); // create space 1935 asm.emitPUSH_Reg(T0); 1936 if (SSE2_FULL) { 1937 asm.emitMOVSD_RegInd_Reg(SP, XMM0); 1938 } else { 1939 asm.emitFSTP_RegInd_Reg_Quad(SP, FP0); 1940 } 1941 } 1942 } 1943 static { 1944 MagicGenerator g = new InvokeMethodReturningDouble(); 1945 generators.put(getMethodReference(Magic.class, MagicNames.invokeMethodReturningDouble, CodeArray.class, WordArray.class, double[].class, byte[].class, WordArray.class, double.class), g); 1946 } 1947 1948 /** 1949 * Invoke an entry point taking values off of the stack 1950 */ 1951 private static final class InvokeEntryPoint extends MagicGenerator { 1952 private final Offset offset; 1953 private final int args; 1954 InvokeEntryPoint(Offset offset, int args) { 1955 this.offset = offset; 1956 this.args = args; 1957 } 1958 @Override 1959 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 1960 BaselineCompilerImpl.genParameterRegisterLoad(asm, args); 1961 asm.generateJTOCcall(offset); 1962 } 1963 } 1964 static { 1965 generators.put(getMethodReference(Magic.class, MagicNames.saveThreadState, AbstractRegisters.class, void.class), 1966 new InvokeEntryPoint(ArchEntrypoints.saveThreadStateInstructionsField.getOffset(), 1)); 1967 generators.put(getMethodReference(Magic.class, MagicNames.threadSwitch, RVMThread.class, AbstractRegisters.class, void.class), 1968 new InvokeEntryPoint(ArchEntrypoints.threadSwitchInstructionsField.getOffset(), 2)); 1969 generators.put(getMethodReference(Magic.class, MagicNames.restoreHardwareExceptionState, AbstractRegisters.class, void.class), 1970 new InvokeEntryPoint(ArchEntrypoints.restoreHardwareExceptionStateInstructionsField.getOffset(), 1)); 1971 } 1972 1973 /** 1974 * Perform dynamic bridge from linker to compiled code 1975 */ 1976 private static final class DynamicBridgeTo extends MagicGenerator { 1977 @Override 1978 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 1979 if (VM.VerifyAssertions) VM._assert(cm.getDeclaringClass().hasDynamicBridgeAnnotation()); 1980 1981 // save the branch address for later 1982 asm.emitPOP_Reg(S0); // S0<-code address 1983 1984 if (VM.BuildFor32Addr) { 1985 asm.emitADD_Reg_Imm(SP, sd.toInt() - WORDSIZE); // just popped WORDSIZE bytes above. 1986 } else { 1987 asm.emitADD_Reg_Imm_Quad(SP, sd.toInt() - WORDSIZE); // just popped WORDSIZE bytes above. 1988 } 1989 if (SSE2_FULL) { 1990 // TODO: Restore SSE2 Control word? 1991 asm.emitMOVQ_Reg_RegDisp(XMM0, SP, XMM_SAVE_OFFSET.plus(0)); 1992 asm.emitMOVQ_Reg_RegDisp(XMM1, SP, XMM_SAVE_OFFSET.plus(8)); 1993 asm.emitMOVQ_Reg_RegDisp(XMM2, SP, XMM_SAVE_OFFSET.plus(16)); 1994 asm.emitMOVQ_Reg_RegDisp(XMM3, SP, XMM_SAVE_OFFSET.plus(24)); 1995 } else { 1996 // restore FPU state 1997 asm.emitFRSTOR_RegDisp(SP, FPU_SAVE_OFFSET); 1998 } 1999 2000 // restore GPRs 2001 if (VM.BuildFor32Addr) { 2002 asm.emitMOV_Reg_RegDisp(T0, SP, T0_SAVE_OFFSET); 2003 asm.emitMOV_Reg_RegDisp(T1, SP, T1_SAVE_OFFSET); 2004 asm.emitMOV_Reg_RegDisp(EBX, SP, EBX_SAVE_OFFSET); 2005 asm.emitMOV_Reg_RegDisp(EDI, SP, EDI_SAVE_OFFSET); 2006 } else { 2007 asm.emitMOV_Reg_RegDisp_Quad(T0, SP, T0_SAVE_OFFSET); 2008 asm.emitMOV_Reg_RegDisp_Quad(T1, SP, T1_SAVE_OFFSET); 2009 asm.emitMOV_Reg_RegDisp_Quad(EBX, SP, EBX_SAVE_OFFSET); 2010 asm.emitMOV_Reg_RegDisp_Quad(EDI, SP, EDI_SAVE_OFFSET); 2011 } 2012 2013 // pop frame 2014 asm.emitPOP_RegDisp(TR, ArchEntrypoints.framePointerField.getOffset()); // FP<-previous FP 2015 2016 // branch 2017 asm.emitJMP_Reg(S0); 2018 } 2019 } 2020 static { 2021 MagicGenerator g = new DynamicBridgeTo(); 2022 generators.put(getMethodReference(Magic.class, MagicNames.dynamicBridgeTo, CodeArray.class, void.class), g); 2023 } 2024 2025 /** 2026 * Exchange stacks 2027 */ 2028 private static final class ReturnToNewStack extends MagicGenerator { 2029 @Override 2030 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 2031 // SP gets frame pointer for new stack 2032 asm.emitPOP_Reg(SP); 2033 2034 // restore nonvolatile registers 2035 if (VM.BuildFor32Addr) { 2036 asm.emitMOV_Reg_RegDisp(EDI, SP, EDI_SAVE_OFFSET); 2037 asm.emitMOV_Reg_RegDisp(EBX, SP, EBX_SAVE_OFFSET); 2038 } else { 2039 asm.emitMOV_Reg_RegDisp_Quad(EDI, SP, EDI_SAVE_OFFSET); 2040 asm.emitMOV_Reg_RegDisp_Quad(EBX, SP, EBX_SAVE_OFFSET); 2041 } 2042 // discard current stack frame 2043 asm.emitPOP_RegDisp(TR, ArchEntrypoints.framePointerField.getOffset()); 2044 2045 // return to caller- pop parameters from stack 2046 int parameterWords = cm.getParameterWords() + (cm.isStatic() ? 0 : 1); // add 1 for this pointer 2047 asm.emitRET_Imm(parameterWords << LG_WORDSIZE); 2048 } 2049 } 2050 static { 2051 MagicGenerator g = new ReturnToNewStack(); 2052 generators.put(getMethodReference(Magic.class, MagicNames.returnToNewStack, Address.class, void.class), g); 2053 } 2054 2055 /** 2056 * Boot up calling of class initializers 2057 */ 2058 private static final class InvokeClassInitializer extends MagicGenerator { 2059 @Override 2060 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 2061 asm.emitPOP_Reg(S0); 2062 asm.emitCALL_Reg(S0); // call address just popped 2063 } 2064 } 2065 static { 2066 MagicGenerator g = new InvokeClassInitializer(); 2067 generators.put(getMethodReference(Magic.class, MagicNames.invokeClassInitializer, CodeArray.class, void.class), g); 2068 } 2069 2070 /** 2071 * Get frame pointer on entry to method 2072 */ 2073 private static final class GetFramePointer extends MagicGenerator { 2074 @Override 2075 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 2076 if (VM.BuildFor32Addr) { 2077 asm.emitLEA_Reg_RegDisp(S0, SP, sd); 2078 } else { 2079 asm.emitLEA_Reg_RegDisp_Quad(S0, SP, sd); 2080 } 2081 asm.emitPUSH_Reg(S0); 2082 } 2083 } 2084 static { 2085 MagicGenerator g = new GetFramePointer(); 2086 generators.put(getMethodReference(Magic.class, MagicNames.getFramePointer, Address.class), g); 2087 } 2088 2089 /** 2090 * Load an address from the stack and load the value at it plus a displacement 2091 */ 2092 private static final class GetValueAtDisplacement extends MagicGenerator { 2093 final Offset disp; 2094 GetValueAtDisplacement(Offset disp) { 2095 this.disp = disp; 2096 } 2097 @Override 2098 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 2099 asm.emitPOP_Reg(T0); 2100 asm.emitPUSH_RegDisp(T0, disp); 2101 } 2102 } 2103 static { 2104 generators.put(getMethodReference(Magic.class, MagicNames.getCallerFramePointer, Address.class, Address.class), 2105 new GetValueAtDisplacement(STACKFRAME_FRAME_POINTER_OFFSET)); 2106 generators.put(getMethodReference(Magic.class, MagicNames.getCompiledMethodID, Address.class, int.class), 2107 new GetValueAtDisplacement(STACKFRAME_METHOD_ID_OFFSET)); 2108 MagicGenerator g = new GetValueAtDisplacement(ObjectModel.getArrayLengthOffset()); 2109 generators.put(getMethodReference(Magic.class, MagicNames.getArrayLength, Object.class, int.class), g); 2110 Class<?>[] unboxedTypes = new Class<?>[]{AddressArray.class, CodeArray.class, ExtentArray.class, FunctionTable.class, IMT.class, ObjectReferenceArray.class, OffsetArray.class, TIB.class, WordArray.class}; 2111 for (Class<?> type : unboxedTypes) { 2112 generators.put(getMethodReference(type, MagicNames.addressArrayLength, int.class), g); 2113 } 2114 } 2115 2116 /** 2117 * Store a value to an address from the stack plus a displacement 2118 */ 2119 private static final class SetValueAtDisplacement extends MagicGenerator { 2120 final Offset disp; 2121 SetValueAtDisplacement(Offset disp) { 2122 this.disp = disp; 2123 } 2124 @Override 2125 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 2126 asm.emitPOP_Reg(T0); // value 2127 asm.emitPOP_Reg(S0); // fp 2128 if (VM.BuildFor32Addr) { 2129 asm.emitMOV_RegDisp_Reg(S0, disp, T0); // [S0+disp] <- T0 2130 } else { 2131 asm.emitMOV_RegDisp_Reg_Quad(S0, disp, T0); // [S0+disp] <- T0 2132 } 2133 } 2134 } 2135 static { 2136 generators.put(getMethodReference(Magic.class, MagicNames.setCallerFramePointer, Address.class, Address.class, void.class), 2137 new SetValueAtDisplacement(STACKFRAME_FRAME_POINTER_OFFSET)); 2138 generators.put(getMethodReference(Magic.class, MagicNames.setCompiledMethodID, Address.class, int.class, void.class), 2139 new SetValueAtDisplacement(STACKFRAME_METHOD_ID_OFFSET)); 2140 } 2141 2142 /** 2143 * Create an array for a runtime table 2144 * @see org.jikesrvm.objectmodel.RuntimeTable 2145 */ 2146 private static final class CreateArray extends MagicGenerator { 2147 private final RVMArray array; 2148 CreateArray(RVMArray array) { 2149 this.array = array; 2150 } 2151 @Override 2152 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 2153 int width = array.getLogElementSize(); 2154 Offset tibOffset = array.getTibOffset(); 2155 int headerSize = ObjectModel.computeHeaderSize(array); 2156 int whichAllocator = MemoryManager.pickAllocator(array, cm); 2157 int site = MemoryManager.getAllocationSite(true); 2158 int align = ObjectModel.getAlignment(array); 2159 int offset = ObjectModel.getOffsetForAlignment(array, false); 2160 // count is already on stack- nothing required 2161 asm.emitPUSH_Imm(width); // logElementSize 2162 asm.emitPUSH_Imm(headerSize); // headerSize 2163 asm.generateJTOCpush(tibOffset); // tib 2164 asm.emitPUSH_Imm(whichAllocator); // allocator 2165 asm.emitPUSH_Imm(align); 2166 asm.emitPUSH_Imm(offset); 2167 asm.emitPUSH_Imm(site); 2168 BaselineCompilerImpl.genParameterRegisterLoad(asm, 8); // pass 8 parameter words 2169 asm.generateJTOCcall(Entrypoints.resolvedNewArrayMethod.getOffset()); 2170 asm.emitPUSH_Reg(T0); 2171 } 2172 } 2173 static { 2174 Class<?>[] unboxedTypes = new Class<?>[] { AddressArray.class, 2175 CodeArray.class, ExtentArray.class, ObjectReferenceArray.class, 2176 OffsetArray.class, WordArray.class }; 2177 for (Class<?> type : unboxedTypes) { 2178 MagicGenerator g = new CreateArray(TypeReference.findOrCreate(type).resolve().asArray()); 2179 generators.put(getMethodReference(type, MagicNames.addressArrayCreate, int.class, type), g); 2180 } 2181 } 2182 2183 /** 2184 * Get a 32bit element from a runtime table 2185 * @see org.jikesrvm.objectmodel.RuntimeTable#get(int) 2186 */ 2187 private static final class Load32_Array extends MagicGenerator { 2188 @Override 2189 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 2190 asm.emitPOP_Reg(T0); // T0 is array index 2191 asm.emitPOP_Reg(S0); // S0 is array ref 2192 if (VM.BuildFor64Addr) { 2193 asm.emitAND_Reg_Reg(T0, T0); // clear MSBs 2194 } 2195 BaselineCompilerImpl.genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array 2196 // push [S0+T0<<2] 2197 asm.emitPUSH_RegIdx(S0, T0, WORD, NO_SLOT); 2198 } 2199 } 2200 /** 2201 * Get a 64bit element from a runtime table 2202 * @see org.jikesrvm.objectmodel.RuntimeTable#get(int) 2203 */ 2204 private static final class Load64_Array extends MagicGenerator { 2205 @Override 2206 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 2207 asm.emitPOP_Reg(T0); // T0 is array index 2208 asm.emitPOP_Reg(S0); // S0 is array ref 2209 if (VM.BuildFor64Addr) { 2210 asm.emitAND_Reg_Reg(T0, T0); // clear MSBs 2211 } 2212 BaselineCompilerImpl.genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array 2213 // push [S0+T0<<3] 2214 asm.emitPUSH_RegIdx(S0, T0, LONG, NO_SLOT); 2215 } 2216 } 2217 static { 2218 MagicGenerator g = VM.BuildFor32Addr ? new Load32_Array() : new Load64_Array(); 2219 Class<?>[] unboxedTypes = new Class<?>[] { AddressArray.class, 2220 ExtentArray.class, FunctionTable.class, IMT.class, 2221 ObjectReferenceArray.class, OffsetArray.class, 2222 TIB.class, WordArray.class }; 2223 Class<?>[] resultTypes = new Class<?>[] { Address.class, Extent.class, 2224 CodeArray.class, CodeArray.class, ObjectReference.class, Offset.class, 2225 Object.class, Word.class }; 2226 for (int i = 0; i < unboxedTypes.length; i++) { 2227 Class<?> type = unboxedTypes[i]; 2228 Class<?> result = resultTypes[i]; 2229 generators.put(getMethodReference(type, MagicNames.addressArrayGet, int.class, result), g); 2230 } 2231 } 2232 2233 /** 2234 * Get a byte element from a runtime table 2235 */ 2236 private static final class LoadByte_Array extends MagicGenerator { 2237 @Override 2238 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 2239 asm.emitPOP_Reg(T0); // T0 is array index 2240 asm.emitPOP_Reg(S0); // S0 is array ref 2241 if (VM.BuildFor64Addr) { 2242 asm.emitAND_Reg_Reg(T0, T0); // clear MSBs 2243 } 2244 BaselineCompilerImpl.genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array 2245 // T1 = (int)[S0+T0<<1] 2246 asm.emitMOVSX_Reg_RegIdx_Byte(T1, S0, T0, BYTE, NO_SLOT); 2247 asm.emitPUSH_Reg(T1); // push byte onto stack 2248 } 2249 } 2250 static { 2251 MagicGenerator g = new LoadByte_Array(); 2252 generators.put(getMethodReference(CodeArray.class, MagicNames.addressArrayGet, int.class, int.class), g); 2253 } 2254 2255 /** 2256 * Store a 32bit element to a runtime table 2257 * @see org.jikesrvm.objectmodel.RuntimeTable#set(int, Object) 2258 */ 2259 private static final class Store32_Array extends MagicGenerator { 2260 @Override 2261 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 2262 Barriers.compileModifyCheck(asm, 2 * WORDSIZE); 2263 asm.emitPOP_Reg(T1); // T1 is the value 2264 asm.emitPOP_Reg(T0); // T0 is array index 2265 if (VM.BuildFor64Addr) { 2266 asm.emitAND_Reg_Reg(T0, T0); // clear MSBs 2267 } 2268 asm.emitPOP_Reg(S0); // S0 is array ref 2269 BaselineCompilerImpl.genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array 2270 asm.emitMOV_RegIdx_Reg(S0, T0, WORD, NO_SLOT, T1); // [S0 + T0<<2] <- T1 2271 } 2272 } 2273 /** 2274 * Store a 64bit element to a runtime table 2275 * @see org.jikesrvm.objectmodel.RuntimeTable#set(int, Object) 2276 */ 2277 private static final class Store64_Array extends MagicGenerator { 2278 @Override 2279 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 2280 Barriers.compileModifyCheck(asm, 2 * WORDSIZE); 2281 asm.emitPOP_Reg(T1); // T1 is the value 2282 asm.emitPOP_Reg(T0); // T0 is array index 2283 if (VM.BuildFor64Addr) { 2284 asm.emitAND_Reg_Reg(T0, T0); // clear MSBs 2285 } 2286 asm.emitPOP_Reg(S0); // S0 is array ref 2287 BaselineCompilerImpl.genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array 2288 asm.emitMOV_RegIdx_Reg_Quad(S0, T0, LONG, NO_SLOT, T1); // [S0 + T0<<2] <- T1 2289 } 2290 } 2291 static { 2292 MagicGenerator g = VM.BuildFor32Addr ? new Store32_Array() : new Store64_Array(); 2293 Class<?>[] unboxedTypes = new Class<?>[] { AddressArray.class, 2294 ExtentArray.class, FunctionTable.class, IMT.class, 2295 ObjectReferenceArray.class, OffsetArray.class, 2296 TIB.class, WordArray.class }; 2297 Class<?>[] operandTypes = new Class<?>[] { Address.class, Extent.class, 2298 CodeArray.class, CodeArray.class, ObjectReference.class, Offset.class, 2299 Object.class, Word.class }; 2300 for (int i = 0; i < unboxedTypes.length; i++) { 2301 Class<?> type = unboxedTypes[i]; 2302 Class<?> operand = operandTypes[i]; 2303 generators.put(getMethodReference(type, MagicNames.addressArraySet, int.class, operand, void.class), g); 2304 } 2305 } 2306 2307 /** 2308 * Set a 8bit in a runtime table 2309 */ 2310 private static final class Store8_Array extends MagicGenerator { 2311 @Override 2312 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 2313 Barriers.compileModifyCheck(asm, 2 * WORDSIZE); 2314 asm.emitPOP_Reg(T1); // T1 is the value 2315 asm.emitPOP_Reg(T0); // T0 is array index 2316 if (VM.BuildFor64Addr) { 2317 asm.emitAND_Reg_Reg(T0, T0); // clear MSBs 2318 } 2319 asm.emitPOP_Reg(S0); // S0 is array ref 2320 BaselineCompilerImpl.genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array 2321 asm.emitMOV_RegIdx_Reg_Byte(S0, T0, BYTE, NO_SLOT, T1); // [S0 + T0<<2] <- T1 2322 } 2323 } 2324 static { 2325 MagicGenerator g = new Store8_Array(); 2326 generators.put(getMethodReference(CodeArray.class, MagicNames.addressArraySet, int.class, int.class, void.class), g); 2327 } 2328 2329 /** 2330 * Create address that holds return address 2331 */ 2332 private static final class GetReturnAddressLocation extends MagicGenerator { 2333 @Override 2334 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 2335 if (VM.BuildFor32Addr) { 2336 asm.emitADD_RegInd_Imm(SP, STACKFRAME_RETURN_ADDRESS_OFFSET.toInt()); 2337 } else { 2338 asm.emitADD_RegInd_Imm_Quad(SP, STACKFRAME_RETURN_ADDRESS_OFFSET.toInt()); 2339 } 2340 } 2341 } 2342 static { 2343 MagicGenerator g = new GetReturnAddressLocation(); 2344 generators.put(getMethodReference(Magic.class, MagicNames.getReturnAddressLocation, Address.class, Address.class), g); 2345 } 2346 2347 /** 2348 * Get a 64bit time base value (not accurate on certain multi-cores) 2349 */ 2350 private static final class GetTimeBase extends MagicGenerator { 2351 @Override 2352 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 2353 asm.emitRDTSC(); // read timestamp counter instruction 2354 asm.emitPUSH_Reg(EDX); // upper 32 bits 2355 asm.emitPUSH_Reg(EAX); // lower 32 bits 2356 } 2357 } 2358 static { 2359 MagicGenerator g = new GetTimeBase(); 2360 generators.put(getMethodReference(Magic.class, MagicNames.getTimeBase, long.class), g); 2361 } 2362 2363 /** 2364 * Pause hint that thread is contending for a lock 2365 */ 2366 private static final class Pause extends MagicGenerator { 2367 @Override 2368 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 2369 asm.emitPAUSE(); 2370 } 2371 } 2372 static { 2373 MagicGenerator g = new Pause(); 2374 generators.put(getMethodReference(Magic.class, MagicNames.pause, void.class), g); 2375 } 2376 2377 /** 2378 * Floating point square root 2379 */ 2380 private static final class Fsqrt extends MagicGenerator { 2381 @Override 2382 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 2383 if (SSE2_BASE) { 2384 asm.emitSQRTSS_Reg_RegInd(XMM0, SP); // XMM0 = sqrt(value) 2385 asm.emitMOVSS_RegInd_Reg(SP, XMM0); // set result on stack 2386 } else { 2387 VM.sysFail("Hardware sqrt only available for SSE"); 2388 } 2389 } 2390 } 2391 static { 2392 MagicGenerator g = new Fsqrt(); 2393 generators.put(getMethodReference(Magic.class, MagicNames.sqrt, float.class, float.class), g); 2394 } 2395 2396 /** 2397 * Double precision square root 2398 */ 2399 private static final class Dsqrt extends MagicGenerator { 2400 @Override 2401 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 2402 if (SSE2_BASE) { 2403 asm.emitSQRTSD_Reg_RegInd(XMM0, SP); // XMM0 = sqrt(value) 2404 asm.emitMOVSD_RegInd_Reg(SP, XMM0); // set result on stack 2405 } else { 2406 VM.sysFail("Hardware sqrt only available for SSE"); 2407 } 2408 } 2409 } 2410 static { 2411 MagicGenerator g = new Dsqrt(); 2412 generators.put(getMethodReference(Magic.class, MagicNames.sqrt, double.class, double.class), g); 2413 } 2414 2415 /** 2416 * Return the current inlining depth (always 0 for baseline) 2417 */ 2418 private static final class GetInlineDepth extends MagicGenerator { 2419 @Override 2420 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 2421 asm.emitPUSH_Imm(0); 2422 } 2423 } 2424 static { 2425 MagicGenerator g = new GetInlineDepth(); 2426 generators.put(getMethodReference(Magic.class, MagicNames.getInlineDepth, int.class), g); 2427 } 2428 2429 /** 2430 * Is the requested parameter a constant? Always {@code false} for baseline. 2431 */ 2432 private static final class IsConstantParameter extends MagicGenerator { 2433 @Override 2434 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) { 2435 asm.emitPOP_Reg(T0); 2436 asm.emitPUSH_Imm(0); 2437 } 2438 } 2439 static { 2440 MagicGenerator g = new IsConstantParameter(); 2441 generators.put(getMethodReference(Magic.class, MagicNames.isConstantParameter, int.class, boolean.class), g); 2442 } 2443}