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