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