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.runtime; 014 015 import org.jikesrvm.VM; 016 import org.jikesrvm.Constants; 017 import org.jikesrvm.ArchitectureSpecific.CodeArray; 018 import org.jikesrvm.mm.mminterface.Barriers; 019 import org.jikesrvm.objectmodel.TIB; 020 import org.jikesrvm.util.BitVector; 021 import org.jikesrvm.util.ImmutableEntryIdentityHashMapRVM; 022 import org.vmmagic.pragma.Uninterruptible; 023 import org.vmmagic.pragma.UninterruptibleNoWarn; 024 import org.vmmagic.unboxed.Address; 025 import org.vmmagic.unboxed.Extent; 026 import org.vmmagic.unboxed.Offset; 027 import org.vmmagic.unboxed.Word; 028 029 /** 030 * The static fields and methods comprising a running virtual machine image. 031 * 032 * <p> These fields, methods and literal constants form the "root set" 033 * of all the objects in the running virtual machine. They are stored 034 * in an array where the middle element is always pointed to by the 035 * virtual machine's "table of contents" (JTOC) register. The slots of 036 * this array hold either primitives (int, long, float, double), 037 * object pointers, or array pointers. To enable the garbage collector 038 * to differentiate between reference and non-reference values, 039 * reference values are indexed positively and numeric values 040 * negatively with respect to the middle of the table. 041 * 042 * <p> Consider the following declarations: 043 * 044 * <pre> 045 * class A { static int i = 123; } 046 * class B { static String s = "abc"; } 047 * class C { static double d = 4.56; } 048 * class D { static void m() {} } 049 * </pre> 050 * 051 * <p>Here's a picture of what the corresponding JTOC would look like 052 * in memory: 053 * 054 * <pre> 055 * +---------------+ 056 * | ... | 057 * +---------------+ 058 * field -6 | C.d (hi) | 059 * +---------------+ 060 * field -5 | C.d (lo) | 061 * +---------------+ 062 * literal -4 | 4.56 (hi) | 063 * +---------------+ 064 * literal -3 | 4.56 (lo) | 065 * +---------------+ 066 * field -2 | A.i | 067 * +---------------+ 068 * literal -1 | 123 | 069 * +---------------+ +---------------+ 070 * [jtoc register]-> 0:| 0 | | (header) | 071 * +---------------+ +---------------+ 072 * literal 1:| (objref) --------->| "abc" | 073 * +---------------+ +---------------+ 074 * field 2:| B.s | 075 * +---------------+ +---------------+ 076 * 3:| (coderef) ------+ | (header) | 077 * +---------------+ | +---------------+ 078 * | ... | +-->| machine code | 079 * +---------------+ | for "m" | 080 * +---------------+ 081 * </pre> 082 */ 083 public class Statics implements Constants { 084 /** 085 * How many 32bit slots do we want in the JTOC to hold numeric (non-reference) values? 086 */ 087 private static final int numNumericSlots = 0x20000; // 128k 088 089 /** 090 * How many reference-sized slots do we want in the JTOC to hold reference values? 091 */ 092 private static final int numReferenceSlots = 0x20000; // 128k 093 094 /** 095 * Static data values (pointed to by JTOC register). 096 * This is currently fixed-size, although at one point the system's plans 097 * called for making it dynamically growable. We could also make it 098 * non-contiguous. 099 */ 100 private static final int[] slots = new int[numNumericSlots + (VM.BuildFor64Addr ? 2 : 1) * numReferenceSlots]; 101 102 /** 103 * Object version of the slots used during boot image creation and 104 * destroyed shortly after. This is required to support conversion 105 * of a slot address to its associated object during boot image 106 * creation. 107 */ 108 private static Object[] objectSlots = new Object[slots.length]; 109 110 /** 111 * The logical middle of the table, references are slots above this and 112 * numeric values below this. The JTOC points to the middle of the 113 * table. 114 */ 115 public static final int middleOfTable = numNumericSlots; 116 117 /** Next available numeric slot number */ 118 private static volatile int nextNumericSlot = middleOfTable - 1; 119 120 /** 121 * Numeric slot hole. Holes are created to align 8byte values. We 122 * allocate into a hole rather than consume another numeric slot. 123 * The value of middleOfTable indicates the slot isn't in use. 124 */ 125 private static volatile int numericSlotHole = middleOfTable; 126 127 /** Next available reference slot number */ 128 private static volatile int nextReferenceSlot = middleOfTable; 129 130 /** 131 * Bit vector indicating whether a numeric slot is a field (true) or a 132 * literal (false). 133 */ 134 private static final BitVector numericFieldVector = new BitVector(middleOfTable); 135 136 /** 137 * Map of objects to their literal offsets 138 */ 139 private static final ImmutableEntryIdentityHashMapRVM<Object, Integer> objectLiterals = 140 new ImmutableEntryIdentityHashMapRVM<Object, Integer>(); 141 142 static { 143 // allocate a slot to be null - offset zero should map to null 144 int offset = allocateReferenceSlot(false).toInt(); 145 if (VM.VerifyAssertions) VM._assert(offset == 0); 146 } 147 148 /** 149 * Conversion from JTOC slot index to JTOC offset. 150 */ 151 @Uninterruptible 152 public static Offset slotAsOffset(int slot) { 153 return Offset.fromIntSignExtend((slot - middleOfTable) << LOG_BYTES_IN_INT); 154 } 155 156 /** 157 * Conversion from JTOC offset to JTOC slot index. 158 */ 159 @Uninterruptible 160 public static int offsetAsSlot(Offset offset) { 161 if (VM.VerifyAssertions) VM._assert((offset.toInt() & 3) == 0); 162 return middleOfTable + (offset.toInt() >> LOG_BYTES_IN_INT); 163 } 164 165 /** 166 * Return the lowest slot number in use 167 */ 168 public static int getLowestInUseSlot() { 169 return nextNumericSlot + 1; 170 } 171 172 /** 173 * Return the highest slot number in use 174 */ 175 public static int getHighestInUseSlot() { 176 return nextReferenceSlot - (VM.BuildFor32Addr ? 1 : 2); 177 } 178 179 /** 180 * Find the given literal in the int like literal map, if not found 181 * create a slot for the literal and place an entry in the map 182 * @param literal the literal value to find or create 183 * @return the offset in the JTOC of the literal 184 */ 185 public static int findOrCreateIntSizeLiteral(int literal) { 186 final int bottom = getLowestInUseSlot(); 187 final int top = middleOfTable; 188 for (int i=top; i >= bottom; i--) { 189 if ((slots[i] == literal) && !numericFieldVector.get(i) && (i != numericSlotHole)) { 190 return slotAsOffset(i).toInt(); 191 } 192 } 193 Offset newOff = allocateNumericSlot(BYTES_IN_INT, false); 194 setSlotContents(newOff, literal); 195 return newOff.toInt(); 196 } 197 198 /** 199 * Find the given literal in the long like literal map, if not found 200 * create a slot for the literal and place an entry in the map 201 * @param literal the literal value to find or create 202 * @return the offset in the JTOC of the literal 203 */ 204 public static int findOrCreateLongSizeLiteral(long literal) { 205 final int bottom = getLowestInUseSlot(); 206 final int top = middleOfTable & 0xFFFFFFFE; 207 for (int i=top; i >= bottom; i-=2) { 208 Offset off = slotAsOffset(i); 209 if ((getSlotContentsAsLong(off) == literal) && 210 !numericFieldVector.get(i) && !(numericFieldVector.get(i+1)) && 211 (i != numericSlotHole) && (i+1 != numericSlotHole)) { 212 return slotAsOffset(i).toInt(); 213 } 214 } 215 Offset newOff = allocateNumericSlot(BYTES_IN_LONG, false); 216 setSlotContents(newOff, literal); 217 return newOff.toInt(); 218 } 219 220 /** 221 * Find the given literal in the 16byte like literal map, if not found 222 * create a slot for the literal and place an entry in the map 223 * @param literal_high the high part of the literal value to find or create 224 * @param literal_low the low part of the literal value to find or create 225 * @return the offset in the JTOC of the literal 226 */ 227 public static int findOrCreate16ByteSizeLiteral(long literal_high, long literal_low) { 228 final int bottom = getLowestInUseSlot(); 229 final int top = middleOfTable & 0xFFFFFFFC; 230 for (int i=top; i >= bottom; i-=4) { 231 Offset off = slotAsOffset(i); 232 if ((getSlotContentsAsLong(off) == literal_low) && 233 (getSlotContentsAsLong(off.plus(8)) == literal_high) && 234 !numericFieldVector.get(i) && !(numericFieldVector.get(i+1)) && 235 !numericFieldVector.get(i+2) && !(numericFieldVector.get(i+3)) && 236 (i != numericSlotHole) && (i+1 != numericSlotHole) && 237 (i+2 != numericSlotHole) && (i+3 != numericSlotHole)) { 238 return slotAsOffset(i).toInt(); 239 } 240 } 241 Offset newOff = allocateNumericSlot(16, false); 242 setSlotContents(newOff, literal_low); 243 setSlotContents(newOff.plus(8), literal_high); 244 return newOff.toInt(); 245 } 246 247 /** 248 * Find or allocate a slot in the JTOC for an object literal. 249 * @param literal value 250 * @return offset of slot that was allocated 251 * Side effect: literal value is stored into JTOC 252 */ 253 public static int findOrCreateObjectLiteral(Object literal) { 254 int off = findObjectLiteral(literal); 255 if (off != 0) { 256 return off; 257 } else { 258 Offset newOff = allocateReferenceSlot(false); 259 setSlotContents(newOff, literal); 260 synchronized(objectLiterals) { 261 objectLiterals.put(literal, newOff.toInt()); 262 } 263 return newOff.toInt(); 264 } 265 } 266 267 /** 268 * Find a slot in the JTOC with this object literal in else return 0 269 * @param literal value 270 * @return offset containing literal or 0 271 */ 272 public static int findObjectLiteral(Object literal) { 273 synchronized (objectLiterals) { 274 Integer result = objectLiterals.get(literal); 275 return result == null ? 0 : result.intValue(); 276 } 277 } 278 279 /** 280 * Marks a slot that was previously a field as being a literal as its value is 281 * final. 282 */ 283 public static synchronized void markAsNumericLiteral(int size, Offset fieldOffset) { 284 int slot = offsetAsSlot(fieldOffset); 285 if (size == BYTES_IN_LONG) { 286 numericFieldVector.clear(slot); 287 numericFieldVector.clear(slot+1); 288 } else { 289 numericFieldVector.clear(slot); 290 } 291 } 292 293 /** 294 * Marks a slot that was previously a field as being a literal as its value is 295 * final. 296 */ 297 public static synchronized void markAsReferenceLiteral(Offset fieldOffset) { 298 Object literal = getSlotContentsAsObject(fieldOffset); 299 if (!VM.runningVM && literal instanceof TIB) { 300 // TIB is just a wrapper for the boot image, so don't place the wrapper 301 // in objectLiterals 302 return; 303 } else if (literal != null) { 304 if (findObjectLiteral(literal) == 0) { 305 synchronized(objectLiterals) { 306 objectLiterals.put(literal, fieldOffset.toInt()); 307 } 308 } 309 } 310 } 311 312 /** 313 * Allocate a numeric slot in the JTOC. 314 * @param size of slot 315 * @param field is the slot for a field 316 * @return offset of slot that was allocated as int 317 * (two slots are allocated for longs and doubles) 318 */ 319 public static synchronized Offset allocateNumericSlot(int size, boolean field) { 320 // Result slot 321 int slot; 322 // Allocate 2 or 4 slots for wide items after possibly blowing 323 // other slots for alignment. 324 if (size == 16) { 325 // widen for a wide 326 nextNumericSlot-=3; 327 // check alignment 328 if ((nextNumericSlot & 1) != 0) { 329 // slot isn't 8byte aligned so increase by 1 and record hole 330 nextNumericSlot--; 331 numericSlotHole = nextNumericSlot + 4; 332 } 333 if ((nextNumericSlot & 3) != 0) { 334 // slot not 16byte aligned, ignore any holes 335 nextNumericSlot-=2; 336 } 337 // Remember the slot and adjust the next available slot 338 slot = nextNumericSlot; 339 nextNumericSlot--; 340 if (field) { 341 numericFieldVector.set(slot); 342 numericFieldVector.set(slot+1); 343 numericFieldVector.set(slot+2); 344 numericFieldVector.set(slot+3); 345 } 346 } else if (size == BYTES_IN_LONG) { 347 // widen for a wide 348 nextNumericSlot--; 349 // check alignment 350 if ((nextNumericSlot & 1) != 0) { 351 // slot isn't 8byte aligned so increase by 1 and record hole 352 nextNumericSlot--; 353 numericSlotHole = nextNumericSlot + 2; 354 } 355 // Remember the slot and adjust the next available slot 356 slot = nextNumericSlot; 357 nextNumericSlot--; 358 if (field) { 359 numericFieldVector.set(slot); 360 numericFieldVector.set(slot+1); 361 } 362 } else { 363 // 4byte quantity, try to reuse hole if one is available 364 if (numericSlotHole != middleOfTable) { 365 slot = numericSlotHole; 366 numericSlotHole = middleOfTable; 367 } else { 368 slot = nextNumericSlot; 369 nextNumericSlot--; 370 } 371 if (field) { 372 numericFieldVector.set(slot); 373 } 374 } 375 if (nextNumericSlot < 0) { 376 enlargeTable(); 377 } 378 return slotAsOffset(slot); 379 } 380 381 /** 382 * Allocate a reference slot in the JTOC. 383 * @param field is the slot for a field 384 * @return offset of slot that was allocated as int 385 * (two slots are allocated on 64bit architectures) 386 */ 387 public static synchronized Offset allocateReferenceSlot(boolean field) { 388 int slot = nextReferenceSlot; 389 nextReferenceSlot += getReferenceSlotSize(); 390 if (nextReferenceSlot >= slots.length) { 391 enlargeTable(); 392 } 393 return slotAsOffset(slot); 394 } 395 396 /** 397 * Grow the statics table 398 */ 399 private static void enlargeTable() { 400 // !!TODO: enlarge slots[] and descriptions[], and modify JTOC register to 401 // point to newly enlarged slots[] 402 // NOTE: very tricky on IA32 because opt uses 32 bit literal address to access JTOC. 403 VM.sysFail("Statics.enlargeTable: jtoc is full"); 404 } 405 406 /** 407 * Fetch number of numeric JTOC slots currently allocated. 408 */ 409 @Uninterruptible 410 public static int getNumberOfNumericSlots() { 411 return middleOfTable - nextNumericSlot; 412 } 413 414 /** 415 * Fetch number of reference JTOC slots currently allocated. 416 */ 417 @Uninterruptible 418 public static int getNumberOfReferenceSlots() { 419 return nextReferenceSlot - middleOfTable; 420 } 421 422 /** 423 * Fetch total number of slots comprising the JTOC. 424 */ 425 @Uninterruptible 426 public static int getTotalNumberOfSlots() { 427 return slots.length; 428 } 429 430 /** 431 * Does specified JTOC slot contain a reference? 432 * @param slot obtained from offsetAsSlot() 433 * @return {@code true} --> slot contains a reference 434 */ 435 @Uninterruptible 436 public static boolean isReference(int slot) { 437 return slot >= middleOfTable; 438 } 439 440 /** 441 * Does specified JTOC slot contain an int sized literal? 442 * @param slot obtained from offsetAsSlot() 443 * @return {@code true} --> slot contains a reference 444 */ 445 public static boolean isIntSizeLiteral(int slot) { 446 if (isReference(slot) || slot < getLowestInUseSlot()) { 447 return false; 448 } else { 449 return !numericFieldVector.get(slot); 450 } 451 } 452 453 /** 454 * Does specified JTOC slot contain a long sized literal? 455 * @param slot obtained from offsetAsSlot() 456 * @return {@code true} --> slot contains a reference 457 */ 458 public static boolean isLongSizeLiteral(int slot) { 459 if (isReference(slot) || slot < getLowestInUseSlot() || ((slot & 1) != 0)) { 460 return false; 461 } else { 462 return !numericFieldVector.get(slot) && !numericFieldVector.get(slot+1); 463 } 464 } 465 466 /** 467 * Does specified JTOC slot contain a reference literal? 468 * @param slot obtained from offsetAsSlot() 469 * @return {@code true} --> slot contains a reference 470 */ 471 public static boolean isReferenceLiteral(int slot) { 472 if (!isReference(slot) || slot > getHighestInUseSlot()) { 473 return false; 474 } else { 475 return (slotAsOffset(slot).toInt() == 0) || 476 (findObjectLiteral(getSlotContentsAsObject(slotAsOffset(slot))) != 0); 477 } 478 } 479 480 /** 481 * Get size occupied by a reference 482 */ 483 @Uninterruptible 484 public static int getReferenceSlotSize() { 485 return VM.BuildFor64Addr ? 2 : 1; 486 } 487 488 /** 489 * Fetch JTOC object (for JNI environment and GC). 490 */ 491 @Uninterruptible 492 public static Address getSlots() { 493 return Magic.objectAsAddress(slots).plus(middleOfTable << LOG_BYTES_IN_INT); 494 } 495 496 /** 497 * Fetch JTOC object (for JNI environment and GC). 498 */ 499 @Uninterruptible 500 public static int[] getSlotsAsIntArray() { 501 return slots; 502 } 503 504 /** 505 * Fetch contents of a slot, as an integer 506 */ 507 @Uninterruptible 508 public static int getSlotContentsAsInt(Offset offset) { 509 if (VM.runningVM) { 510 return Magic.getIntAtOffset(slots, offset.plus(middleOfTable << LOG_BYTES_IN_INT)); 511 } else { 512 int slot = offsetAsSlot(offset); 513 return slots[slot]; 514 } 515 } 516 517 /** 518 * Fetch contents of a slot-pair, as a long integer. 519 */ 520 @Uninterruptible 521 public static long getSlotContentsAsLong(Offset offset) { 522 if (VM.runningVM) { 523 return Magic.getLongAtOffset(slots, offset.plus(middleOfTable << LOG_BYTES_IN_INT)); 524 } else { 525 int slot = offsetAsSlot(offset); 526 long result; 527 if (VM.LittleEndian) { 528 result = (((long) slots[slot + 1]) << BITS_IN_INT); // hi 529 result |= (slots[slot]) & 0xFFFFFFFFL; // lo 530 } else { 531 result = (((long) slots[slot]) << BITS_IN_INT); // hi 532 result |= (slots[slot + 1]) & 0xFFFFFFFFL; // lo 533 } 534 return result; 535 } 536 } 537 538 /** 539 * Fetch contents of a slot, as an object. 540 */ 541 @Uninterruptible 542 public static Object getSlotContentsAsObject(Offset offset) { 543 if (VM.runningVM) { 544 return Magic.getObjectAtOffset(slots, offset.plus(middleOfTable << LOG_BYTES_IN_INT)); 545 } else { 546 return objectSlots[offsetAsSlot(offset)]; 547 } 548 } 549 550 /** 551 * Fetch contents of a slot, as an Address. 552 */ 553 @UninterruptibleNoWarn("Interruptible code only reachable during boot image creation") 554 public static Address getSlotContentsAsAddress(Offset offset) { 555 if (VM.runningVM) { 556 if (VM.BuildFor32Addr) { 557 return Address.fromIntSignExtend(getSlotContentsAsInt(offset)); 558 } else { 559 return Address.fromLong(getSlotContentsAsLong(offset)); 560 } 561 } else { 562 // Addresses are represented by objects in the tools building the VM 563 Object unboxed = objectSlots[offsetAsSlot(offset)]; 564 if (unboxed instanceof Address) { 565 return (Address) unboxed; 566 } else if (unboxed instanceof Word) { 567 return ((Word) unboxed).toAddress(); 568 } else if (unboxed instanceof Extent) { 569 return ((Extent) unboxed).toWord().toAddress(); 570 } else if (unboxed instanceof Offset) { 571 return ((Offset) unboxed).toWord().toAddress(); 572 } else { 573 if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); 574 return Address.zero(); 575 } 576 } 577 } 578 579 /** 580 * Set contents of a slot, as an integer. 581 */ 582 @Uninterruptible 583 public static void setSlotContents(Offset offset, int value) { 584 if (VM.runningVM) { 585 Magic.setIntAtOffset(slots, offset.plus(middleOfTable << LOG_BYTES_IN_INT), value); 586 } else { 587 slots[offsetAsSlot(offset)] = value; 588 } 589 } 590 591 /** 592 * Set contents of a slot, as an float. 593 */ 594 @Uninterruptible 595 public static void setSlotContents(Offset offset, float value) { 596 if (VM.runningVM) { 597 Magic.setFloatAtOffset(slots, offset.plus(middleOfTable << LOG_BYTES_IN_INT), value); 598 } else { 599 slots[offsetAsSlot(offset)] = Magic.floatAsIntBits(value); 600 } 601 } 602 603 /** 604 * Set contents of a slot, as a double. 605 */ 606 @Uninterruptible 607 public static void setSlotContents(Offset offset, double value) { 608 if (VM.runningVM) { 609 Magic.setDoubleAtOffset(slots, offset.plus(middleOfTable << LOG_BYTES_IN_INT), value); 610 } else { 611 int slot = offsetAsSlot(offset); 612 long value64bits = Magic.doubleAsLongBits(value); 613 if (VM.LittleEndian) { 614 slots[slot + 1] = (int) (value64bits >>> BITS_IN_INT); // hi 615 slots[slot] = (int) (value64bits); // lo 616 } else { 617 slots[slot] = (int) (value64bits >>> BITS_IN_INT); // hi 618 slots[slot + 1] = (int) (value64bits); // lo 619 } 620 } 621 } 622 623 /** 624 * Set contents of a slot, as a long integer. 625 */ 626 @Uninterruptible 627 public static void setSlotContents(Offset offset, long value) { 628 if (VM.runningVM) { 629 Magic.setLongAtOffset(slots, offset.plus(middleOfTable << LOG_BYTES_IN_INT), value); 630 } else { 631 int slot = offsetAsSlot(offset); 632 if (VM.LittleEndian) { 633 slots[slot + 1] = (int) (value >>> BITS_IN_INT); // hi 634 slots[slot] = (int) (value); // lo 635 } else { 636 slots[slot] = (int) (value >>> BITS_IN_INT); // hi 637 slots[slot + 1] = (int) (value); // lo 638 } 639 } 640 } 641 642 /** 643 * Set contents of a slot, as an object. 644 */ 645 @UninterruptibleNoWarn("Interruptible code only reachable during boot image creation") 646 public static void setSlotContents(Offset offset, Object object) { 647 // NB uninterruptible warnings are disabled for this method due to 648 // the array store which could cause a fault - this can't actually 649 // happen as the fault would only ever occur when not running the 650 // VM. We suppress the warning as we know the error can't happen. 651 652 if (VM.runningVM && Barriers.NEEDS_OBJECT_PUTSTATIC_BARRIER) { 653 Barriers.objectStaticWrite(object, offset, 0); 654 } else { 655 setSlotContents(offset, Magic.objectAsAddress(object).toWord()); 656 } 657 if (VM.VerifyAssertions) VM._assert(offset.toInt() > 0); 658 if (!VM.runningVM && objectSlots != null) { 659 // When creating the boot image objectSlots is populated as 660 // Magic won't work in the bootstrap JVM. 661 objectSlots[offsetAsSlot(offset)] = Magic.bootImageIntern(object); 662 } 663 } 664 665 /** 666 * Set contents of a slot, as a CodeArray. 667 */ 668 @Uninterruptible 669 public static void setSlotContents(Offset offset, CodeArray code) { 670 setSlotContents(offset, Magic.codeArrayAsObject(code)); 671 } 672 673 /** 674 * Set contents of a slot, as a CodeArray. 675 */ 676 @Uninterruptible 677 public static void setSlotContents(Offset offset, TIB tib) { 678 setSlotContents(offset, Magic.tibAsObject(tib)); 679 } 680 681 /** 682 * Set contents of a slot, as a Word. 683 */ 684 @Uninterruptible 685 public static void setSlotContents(Offset offset, Word word) { 686 if (VM.runningVM) { 687 Magic.setWordAtOffset(slots, offset.plus(middleOfTable << LOG_BYTES_IN_INT), word); 688 } else { 689 if (VM.BuildFor32Addr) { 690 setSlotContents(offset, word.toInt()); 691 } else { 692 setSlotContents(offset, word.toLong()); 693 } 694 } 695 } 696 697 /** 698 * Set contents of a slot, as a Address 699 */ 700 @Uninterruptible 701 public static void setSlotContents(Offset offset, Address value) { 702 if (VM.runningVM) { 703 Magic.setAddressAtOffset(slots, offset.plus(middleOfTable << LOG_BYTES_IN_INT), value); 704 } else { 705 if (VM.BuildFor32Addr) { 706 setSlotContents(offset, value.toInt()); 707 } else { 708 setSlotContents(offset, value.toLong()); 709 } 710 } 711 } 712 713 /** 714 * Set contents of a slot, as a Extent 715 */ 716 @Uninterruptible 717 public static void setSlotContents(Offset offset, Extent value) { 718 if (VM.runningVM) { 719 Magic.setExtentAtOffset(slots, offset.plus(middleOfTable << LOG_BYTES_IN_INT), value); 720 } else { 721 if (VM.BuildFor32Addr) { 722 setSlotContents(offset, value.toInt()); 723 } else { 724 setSlotContents(offset, value.toLong()); 725 } 726 } 727 } 728 729 /** 730 * Set contents of a slot, as a Offset 731 */ 732 @Uninterruptible 733 public static void setSlotContents(Offset offset, Offset value) { 734 if (VM.runningVM) { 735 Magic.setOffsetAtOffset(slots, offset.plus(middleOfTable << LOG_BYTES_IN_INT), value); 736 } else { 737 if (VM.BuildFor32Addr) { 738 setSlotContents(offset, value.toInt()); 739 } else { 740 setSlotContents(offset, value.toLong()); 741 } 742 } 743 } 744 745 /** 746 * Inform Statics that boot image instantiation is over and that 747 * unnecessary data structures, for runtime, can be released. 748 * @return information that may later be restored to help generate 749 * the boot image report 750 */ 751 public static Object bootImageInstantiationFinished() { 752 Object t = objectSlots; 753 objectSlots = null; 754 return t; 755 } 756 757 /** 758 * After serializing Statics the boot image writer generates 759 * a report. This method is called to restore data lost by the call 760 * to bootImageInstantiationFinished. 761 * @param slots object slots to restore 762 */ 763 public static void bootImageReportGeneration(Object slots) { 764 objectSlots = (Object[])slots; 765 } 766 }