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 static org.jikesrvm.SizeConstants.BYTES_IN_ADDRESS; 016 import static org.jikesrvm.SizeConstants.BYTES_IN_INT; 017 import static org.jikesrvm.SizeConstants.LOG_BYTES_IN_DOUBLE; 018 import static org.jikesrvm.SizeConstants.LOG_BYTES_IN_INT; 019 import static org.jikesrvm.SizeConstants.LOG_BYTES_IN_SHORT; 020 021 import org.jikesrvm.VM; 022 import org.vmmagic.pragma.Inline; 023 import org.vmmagic.pragma.Uninterruptible; 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 * Low level memory management functions. 031 * <p> 032 * Note that this class is "uninterruptible" - calling its methods will never 033 * cause the current thread to yield the CPU to another thread (one that 034 * might cause a GC, for example). 035 */ 036 @Uninterruptible 037 public class Memory { 038 039 //////////////////////// 040 // (1) Utilities for copying/filling/zeroing memory 041 //////////////////////// 042 043 /** 044 * How many bytes is considered large enough to justify the transition to 045 * C code to use memcpy? 046 */ 047 private static final int NATIVE_THRESHOLD = 512; 048 049 /** 050 * Allow the use of C based memcpy 051 */ 052 private static final boolean USE_NATIVE = true; 053 054 /** 055 * Number of bytes used when copying larger chunks of memory. Normally 8 bytes 056 * except on x87 Intel 057 */ 058 private static final int BYTES_IN_COPY = VM.BuildForIA32 && !VM.BuildForSSE2 ? 4 : 8; 059 060 @Inline 061 private static void copy8Bytes(Address dstPtr, Address srcPtr) { 062 if (BYTES_IN_COPY == 8) { 063 if (VM.BuildForIA32) { 064 dstPtr.store(srcPtr.loadLong()); 065 } else { 066 dstPtr.store(srcPtr.loadDouble()); 067 } 068 } else { 069 copy4Bytes(dstPtr, srcPtr); 070 copy4Bytes(dstPtr.plus(4), srcPtr.plus(4)); 071 } 072 } 073 @Inline 074 private static void copy4Bytes(Address dstPtr, Address srcPtr) { 075 dstPtr.store(srcPtr.loadInt()); 076 } 077 @Inline 078 private static void copy2Bytes(Address dstPtr, Address srcPtr) { 079 dstPtr.store(srcPtr.loadChar()); 080 } 081 @Inline 082 private static void copy1Bytes(Address dstPtr, Address srcPtr) { 083 dstPtr.store(srcPtr.loadByte()); 084 } 085 /** 086 * Low level copy of len elements from src[srcPos] to dst[dstPos]. 087 * 088 * Assumptions: <code> src != dst || (scrPos >= dstPos + 4) </code> 089 * and src and dst are 8Bit arrays. 090 * @param src the source array 091 * @param srcPos index in the source array to begin copy 092 * @param dst the destination array 093 * @param dstPos index in the destination array to being copy 094 * @param len number of array elements to copy 095 */ 096 public static void arraycopy8Bit(Object src, int srcPos, Object dst, int dstPos, int len) { 097 Address srcPtr = Magic.objectAsAddress(src).plus(srcPos); 098 Address dstPtr = Magic.objectAsAddress(dst).plus(dstPos); 099 aligned8Copy(dstPtr, srcPtr, len); 100 } 101 102 /** 103 * Low level copy of <code>copyBytes</code> bytes from <code>src[srcPos]</code> to <code>dst[dstPos]</code>. 104 * 105 * Assumption <code>src != dst || (srcPos >= dstPos)</code> and element size is 4 bytes. 106 * 107 * @param dstPtr The destination start address 108 * @param srcPtr The source start address 109 * @param copyBytes The number of bytes to be copied 110 */ 111 public static void aligned8Copy(Address dstPtr, Address srcPtr, int copyBytes) { 112 if (USE_NATIVE && copyBytes > NATIVE_THRESHOLD) { 113 memcopy(dstPtr, srcPtr, copyBytes); 114 } else { 115 if (copyBytes >= BYTES_IN_COPY && 116 (srcPtr.toWord().and(Word.fromIntZeroExtend(BYTES_IN_COPY - 1)) == 117 (dstPtr.toWord().and(Word.fromIntZeroExtend(BYTES_IN_COPY - 1))))) { 118 // relative alignment is the same 119 Address endPtr = srcPtr.plus(copyBytes); 120 Address wordEndPtr = endPtr.toWord().and(Word.fromIntZeroExtend(BYTES_IN_COPY-1).not()).toAddress(); 121 122 if (BYTES_IN_COPY == 8) { 123 if (srcPtr.toWord().and(Word.fromIntZeroExtend(1)).NE(Word.zero())) { 124 copy1Bytes(dstPtr, srcPtr); 125 srcPtr = srcPtr.plus(1); 126 dstPtr = dstPtr.plus(1); 127 } 128 if (srcPtr.toWord().and(Word.fromIntZeroExtend(2)).NE(Word.zero())) { 129 copy2Bytes(dstPtr, srcPtr); 130 srcPtr = srcPtr.plus(2); 131 dstPtr = dstPtr.plus(2); 132 } 133 if (srcPtr.toWord().and(Word.fromIntZeroExtend(4)).NE(Word.zero())) { 134 copy4Bytes(dstPtr, srcPtr); 135 srcPtr = srcPtr.plus(4); 136 dstPtr = dstPtr.plus(4); 137 } 138 } else { 139 if (srcPtr.toWord().and(Word.fromIntZeroExtend(1)).NE(Word.zero())) { 140 copy1Bytes(dstPtr, srcPtr); 141 srcPtr = srcPtr.plus(1); 142 dstPtr = dstPtr.plus(1); 143 } 144 if (srcPtr.toWord().and(Word.fromIntZeroExtend(2)).NE(Word.zero())) { 145 copy2Bytes(dstPtr, srcPtr); 146 srcPtr = srcPtr.plus(2); 147 dstPtr = dstPtr.plus(2); 148 } 149 } 150 while (srcPtr.LT(wordEndPtr)) { 151 if (BYTES_IN_COPY == 8) { 152 copy8Bytes(dstPtr, srcPtr); 153 } else { 154 copy4Bytes(dstPtr, srcPtr); 155 } 156 srcPtr = srcPtr.plus(BYTES_IN_COPY); 157 dstPtr = dstPtr.plus(BYTES_IN_COPY); 158 } 159 // if(VM.VerifyAssertions) VM._assert(wordEndPtr.EQ(srcPtr)); 160 if (BYTES_IN_COPY == 8) { 161 if (endPtr.toWord().and(Word.fromIntZeroExtend(4)).NE(Word.zero())) { 162 copy4Bytes(dstPtr, srcPtr); 163 srcPtr = srcPtr.plus(4); 164 dstPtr = dstPtr.plus(4); 165 } 166 if (endPtr.toWord().and(Word.fromIntZeroExtend(2)).NE(Word.zero())) { 167 copy2Bytes(dstPtr, srcPtr); 168 srcPtr = srcPtr.plus(2); 169 dstPtr = dstPtr.plus(2); 170 } 171 if (endPtr.toWord().and(Word.fromIntZeroExtend(1)).NE(Word.zero())) { 172 copy1Bytes(dstPtr, srcPtr); 173 } 174 } else { 175 if (endPtr.toWord().and(Word.fromIntZeroExtend(2)).NE(Word.zero())) { 176 copy2Bytes(dstPtr, srcPtr); 177 srcPtr = srcPtr.plus(2); 178 dstPtr = dstPtr.plus(2); 179 } 180 if (endPtr.toWord().and(Word.fromIntZeroExtend(1)).NE(Word.zero())) { 181 copy1Bytes(dstPtr, srcPtr); 182 } 183 } 184 } else { 185 Address endPtr = srcPtr.plus(copyBytes); 186 while (srcPtr.LT(endPtr)) { 187 dstPtr.store(srcPtr.loadByte()); 188 srcPtr = srcPtr.plus(1); 189 dstPtr = dstPtr.plus(1); 190 } 191 } 192 } 193 } 194 195 /** 196 * Low level copy of len elements from src[srcPos] to dst[dstPos]. 197 * <p> 198 * Assumption; {@code src != dst || (srcPos >= dstPos + 2)}. 199 * 200 * @param src the source array 201 * @param srcPos index in the source array to begin copy 202 * @param dst the destination array 203 * @param dstPos index in the destination array to being copy 204 * @param len number of array elements to copy 205 */ 206 public static void arraycopy16Bit(Object src, int srcPos, Object dst, int dstPos, int len) { 207 Address srcPtr = Magic.objectAsAddress(src).plus(srcPos << LOG_BYTES_IN_SHORT); 208 Address dstPtr = Magic.objectAsAddress(dst).plus(dstPos << LOG_BYTES_IN_SHORT); 209 int copyBytes = len << LOG_BYTES_IN_SHORT; 210 aligned16Copy(dstPtr, srcPtr, copyBytes); 211 } 212 /** 213 * Low level copy of <code>copyBytes</code> bytes from <code>src[srcPos]</code> to <code>dst[dstPos]</code>. 214 * <p> 215 * Assumption: <code>src != dst || (srcPos >= dstPos)</code> and element size is 2 bytes. 216 * 217 * @param dstPtr The destination start address 218 * @param srcPtr The source start address 219 * @param copyBytes The number of bytes to be copied 220 */ 221 public static void aligned16Copy(Address dstPtr, Address srcPtr, int copyBytes) { 222 if (USE_NATIVE && copyBytes > NATIVE_THRESHOLD) { 223 memcopy(dstPtr, srcPtr, copyBytes); 224 } else { 225 if (copyBytes >= BYTES_IN_COPY && 226 (srcPtr.toWord().and(Word.fromIntZeroExtend(BYTES_IN_COPY - 1)) == 227 (dstPtr.toWord().and(Word.fromIntZeroExtend(BYTES_IN_COPY - 1))))) { 228 // relative alignment is the same 229 Address endPtr = srcPtr.plus(copyBytes); 230 Address wordEndPtr = endPtr.toWord().and(Word.fromIntZeroExtend(BYTES_IN_COPY-1).not()).toAddress(); 231 232 if (BYTES_IN_COPY == 8) { 233 if (srcPtr.toWord().and(Word.fromIntZeroExtend(2)).NE(Word.zero())) { 234 copy2Bytes(dstPtr, srcPtr); 235 srcPtr = srcPtr.plus(2); 236 dstPtr = dstPtr.plus(2); 237 } 238 if (srcPtr.toWord().and(Word.fromIntZeroExtend(4)).NE(Word.zero())) { 239 copy4Bytes(dstPtr, srcPtr); 240 srcPtr = srcPtr.plus(4); 241 dstPtr = dstPtr.plus(4); 242 } 243 } else { 244 if (srcPtr.toWord().and(Word.fromIntZeroExtend(2)).NE(Word.zero())) { 245 copy2Bytes(dstPtr, srcPtr); 246 srcPtr = srcPtr.plus(2); 247 dstPtr = dstPtr.plus(2); 248 } 249 } 250 while (srcPtr.LT(wordEndPtr)) { 251 if (BYTES_IN_COPY == 8) { 252 copy8Bytes(dstPtr, srcPtr); 253 } else { 254 copy4Bytes(dstPtr, srcPtr); 255 } 256 srcPtr = srcPtr.plus(BYTES_IN_COPY); 257 dstPtr = dstPtr.plus(BYTES_IN_COPY); 258 } 259 // if(VM.VerifyAssertions) VM._assert(wordEndPtr.EQ(srcPtr)); 260 if (BYTES_IN_COPY == 8) { 261 if (endPtr.toWord().and(Word.fromIntZeroExtend(4)).NE(Word.zero())) { 262 copy4Bytes(dstPtr, srcPtr); 263 srcPtr = srcPtr.plus(4); 264 dstPtr = dstPtr.plus(4); 265 } 266 if (endPtr.toWord().and(Word.fromIntZeroExtend(2)).NE(Word.zero())) { 267 copy2Bytes(dstPtr, srcPtr); 268 } 269 } else { 270 if (endPtr.toWord().and(Word.fromIntZeroExtend(2)).NE(Word.zero())) { 271 copy2Bytes(dstPtr, srcPtr); 272 } 273 } 274 } else { 275 Address endPtr = srcPtr.plus(copyBytes); 276 while (srcPtr.LT(endPtr)) { 277 copy2Bytes(dstPtr, srcPtr); 278 srcPtr = srcPtr.plus(2); 279 dstPtr = dstPtr.plus(2); 280 } 281 } 282 } 283 } 284 285 /** 286 * Low level copy of <code>len</code> elements from <code>src[srcPos]</code> to <code>dst[dstPos]</code>. 287 * <p> 288 * Assumption: <code>src != dst || (srcPos >= dstPos)</code> and element size is 4 bytes. 289 * 290 * @param src the source array 291 * @param srcIdx index in the source array to begin copy 292 * @param dst the destination array 293 * @param dstIdx index in the destination array to being copy 294 * @param len number of array elements to copy 295 */ 296 public static void arraycopy32Bit(Object src, int srcIdx, Object dst, int dstIdx, int len) { 297 Address srcPtr = Magic.objectAsAddress(src).plus(srcIdx << LOG_BYTES_IN_INT); 298 Address dstPtr = Magic.objectAsAddress(dst).plus(dstIdx << LOG_BYTES_IN_INT); 299 int copyBytes = len << LOG_BYTES_IN_INT; 300 aligned32Copy(dstPtr, srcPtr, copyBytes); 301 } 302 303 /** 304 * Low level copy of <code>len</code> elements from <code>src[srcPos]</code> to <code>dst[dstPos]</code>. 305 * <p> 306 * Assumption: <code>src != dst || (srcPos >= dstPos)</code> and element size is 8 bytes. 307 * 308 * @param src the source array 309 * @param srcIdx index in the source array to begin copy 310 * @param dst the destination array 311 * @param dstIdx index in the destination array to being copy 312 * @param len number of array elements to copy 313 */ 314 public static void arraycopy64Bit(Object src, int srcIdx, Object dst, int dstIdx, int len) { 315 Offset srcOffset = Offset.fromIntZeroExtend(srcIdx << LOG_BYTES_IN_DOUBLE); 316 Offset dstOffset = Offset.fromIntZeroExtend(dstIdx << LOG_BYTES_IN_DOUBLE); 317 int copyBytes = len << LOG_BYTES_IN_DOUBLE; 318 aligned64Copy(Magic.objectAsAddress(dst).plus(dstOffset), Magic.objectAsAddress(src).plus(srcOffset), copyBytes); 319 } 320 321 /** 322 * Low level copy of <code>copyBytes</code> bytes from <code>src[srcPos]</code> to <code>dst[dstPos]</code>. 323 * 324 * Assumption <code>src != dst || (srcPos >= dstPos)</code> and element size is 8 bytes. 325 * 326 * @param dstPtr The destination start address 327 * @param srcPtr The source start address 328 * @param copyBytes The number of bytes to be copied 329 */ 330 public static void aligned64Copy(Address dstPtr, Address srcPtr, int copyBytes) { 331 if (USE_NATIVE && copyBytes > NATIVE_THRESHOLD) { 332 memcopy(dstPtr, srcPtr, copyBytes); 333 } else { 334 // The elements of long[] and double[] are always doubleword aligned 335 // therefore we can do 64 bit load/stores without worrying about alignment. 336 Address endPtr = srcPtr.plus(copyBytes); 337 while (srcPtr.LT(endPtr)) { 338 copy8Bytes(dstPtr, srcPtr); 339 srcPtr = srcPtr.plus(8); 340 dstPtr = dstPtr.plus(8); 341 } 342 } 343 } 344 345 346 /** 347 * Copy copyBytes from src to dst. 348 * Assumption: either the ranges are non overlapping, or {@code src >= dst + 4}. 349 * Also, src and dst are 4 byte aligned and numBytes is a multiple of 4. 350 * 351 * @param dst the destination addr 352 * @param src the source addr 353 * @param copyBytes the number of bytes top copy 354 */ 355 public static void aligned32Copy(Address dst, Address src, int copyBytes) { 356 if (VM.VerifyAssertions) { 357 VM._assert(copyBytes >= 0); 358 VM._assert((copyBytes & (BYTES_IN_INT - 1)) == 0); 359 VM._assert(src.toWord().and(Word.fromIntZeroExtend(BYTES_IN_INT - 1)).isZero()); 360 VM._assert(dst.toWord().and(Word.fromIntZeroExtend(BYTES_IN_INT - 1)).isZero()); 361 VM._assert(src.plus(copyBytes).LE(dst) || src.GE(dst.plus(BYTES_IN_INT))); 362 } 363 if (USE_NATIVE && copyBytes > NATIVE_THRESHOLD) { 364 memcopy(dst, src, copyBytes); 365 } else { 366 Offset numBytes = Offset.fromIntSignExtend(copyBytes); 367 if (BYTES_IN_COPY == 8 && copyBytes != 0) { 368 Word wordMask = Word.fromIntZeroExtend(BYTES_IN_COPY-1); 369 Word srcAlignment = src.toWord().and(wordMask); 370 if (srcAlignment.EQ(dst.toWord().and(wordMask))) { 371 Offset i = Offset.zero(); 372 if (srcAlignment.EQ(Word.fromIntZeroExtend(BYTES_IN_INT))) { 373 copy4Bytes(dst.plus(i), src.plus(i)); 374 i = i.plus(BYTES_IN_INT); 375 } 376 Word endAlignment = srcAlignment.plus(numBytes).and(wordMask); 377 numBytes = numBytes.minus(endAlignment.toOffset()); 378 for (; i.sLT(numBytes); i = i.plus(BYTES_IN_COPY)) { 379 copy8Bytes(dst.plus(i), src.plus(i)); 380 } 381 if (!endAlignment.isZero()) { 382 copy4Bytes(dst.plus(i), src.plus(i)); 383 } 384 return; 385 } 386 } 387 //normal case: 32 bit or (64 bit not aligned) 388 for (Offset i = Offset.zero(); i.sLT(numBytes); i = i.plus(BYTES_IN_INT)) { 389 copy4Bytes(dst.plus(i), src.plus(i)); 390 } 391 } 392 } 393 394 /** 395 * Copy numbytes from src to dst. 396 * Assumption: either the ranges are non overlapping, or {@code src >= dst + BYTES_IN_ADDRESS}. 397 * Also, src and dst are word aligned and numBytes is a multiple of BYTES_IN_ADDRESS. 398 * @param dst the destination addr 399 * @param src the source addr 400 * @param numBytes the number of bytes top copy 401 */ 402 public static void alignedWordCopy(Address dst, Address src, int numBytes) { 403 if (USE_NATIVE && numBytes > NATIVE_THRESHOLD) { 404 memcopy(dst, src, numBytes); 405 } else { 406 internalAlignedWordCopy(dst, src, numBytes); 407 } 408 } 409 410 /** 411 * Copy <code>numbytes</code> from <code>src</code> to <code>dst</code>. 412 * Assumption either the ranges are non overlapping, or <code>src >= dst + BYTES_IN_ADDRESS</code>. 413 * @param dst The destination addr 414 * @param src The source addr 415 * @param numBytes The number of bytes to copy 416 */ 417 private static void internalAlignedWordCopy(Address dst, Address src, int numBytes) { 418 Address end = src.plus(numBytes); 419 while (src.LT(end)) { 420 dst.store(src.loadWord()); 421 src = src.plus(BYTES_IN_ADDRESS); 422 dst = dst.plus(BYTES_IN_ADDRESS); 423 } 424 } 425 426 /** 427 * Copy a region of memory. 428 * <p> 429 * Assumption: source and destination regions do not overlap 430 * 431 * @param dst Destination address 432 * @param src Source address 433 * @param cnt Number of bytes to copy 434 */ 435 public static void memcopy(Address dst, Address src, Extent cnt) { 436 SysCall.sysCall.sysCopy(dst, src, cnt); 437 } 438 439 public static void memcopy(Address dst, Address src, int cnt) { 440 SysCall.sysCall.sysCopy(dst, src, Extent.fromIntSignExtend(cnt)); 441 } 442 443 /** 444 * Zero a region of memory. 445 * 446 * @param useNT use non-temporal instructions (if available) 447 * @param start of address range (inclusive) 448 * @param len extent to zero. 449 */ 450 public static void zero(boolean useNT, Address start, Extent len) { 451 if (useNT) { 452 SysCall.sysCall.sysZeroNT(start, len); 453 } else { 454 SysCall.sysCall.sysZero(start, len); 455 } 456 } 457 458 //////////////////////// 459 // (2) Cache management 460 //////////////////////// 461 462 /** 463 * Synchronize a region of memory: force data in dcache to be written out to main 464 * memory so that it will be seen by icache when instructions are fetched back. 465 * @param address Start of address range 466 * @param size Size of address range (bytes) 467 */ 468 public static void sync(Address address, int size) { 469 SysCall.sysCall.sysSyncCache(address, size); 470 } 471 472 //////////////////////// 473 // (3) MMap 474 //////////////////////// 475 476 // constants for protection and mapping calls 477 public static final int PROT_NONE = 0; 478 public static final int PROT_READ = 1; 479 public static final int PROT_WRITE = 2; 480 public static final int PROT_EXEC = 4; 481 482 public static final int MAP_PRIVATE = 2; 483 public static final int MAP_FIXED = (VM.BuildForLinux) ? 16 : (VM.BuildForOsx) ? 16 : (VM.BuildForSolaris) ? 0x10 :256; 484 public static final int MAP_ANONYMOUS = (VM.BuildForLinux) ? 32 : (VM.BuildForOsx) ? 0x1000 : (VM.BuildForSolaris) ? 0x100 : 16; 485 486 public static boolean isPageMultiple(int val) { 487 int pagesizeMask = getPagesize() - 1; 488 return ((val & pagesizeMask) == 0); 489 } 490 491 public static boolean isPageMultiple(Extent val) { 492 Word pagesizeMask = Word.fromIntZeroExtend(getPagesize() - 1); 493 return val.toWord().and(pagesizeMask).isZero(); 494 } 495 496 public static boolean isPageMultiple(Offset val) { 497 Word pagesizeMask = Word.fromIntZeroExtend(getPagesize() - 1); 498 return val.toWord().and(pagesizeMask).isZero(); 499 } 500 501 public static boolean isPageAligned(Address addr) { 502 Word pagesizeMask = Word.fromIntZeroExtend(getPagesize() - 1); 503 return addr.toWord().and(pagesizeMask).isZero(); 504 } 505 506 /** 507 * Do generic mmap non-file memory mapping call 508 * @param address Start of address range (Address) 509 * @param size Size of address range 510 * @param prot Protection (int) 511 * @param flags (int) 512 * @return Address (of region) if successful; errno (1 to 127) otherwise 513 */ 514 public static Address mmap(Address address, Extent size, int prot, int flags) { 515 if (VM.VerifyAssertions) { 516 VM._assert(isPageAligned(address) && isPageMultiple(size)); 517 } 518 return SysCall.sysCall.sysMMapErrno(address, size, prot, flags, -1, Offset.zero()); 519 } 520 521 /** 522 * Do mmap demand zero fixed address memory mapping call 523 * @param address Start of address range 524 * @param size Size of address range 525 * @return Address (of region) if successful; errno (1 to 127) otherwise 526 */ 527 public static Address dzmmap(Address address, Extent size) { 528 if (VM.VerifyAssertions) { 529 VM._assert(isPageAligned(address) && isPageMultiple(size)); 530 } 531 int prot = PROT_READ | PROT_WRITE | PROT_EXEC; 532 int flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED; 533 return mmap(address, size, prot, flags); 534 } 535 536 /** 537 * Do mprotect system call 538 * @param address Start of address range (Address) 539 * @param size Size of address range 540 * @param prot Protection (int) 541 * @return true iff success 542 */ 543 public static boolean mprotect(Address address, Extent size, int prot) { 544 if (VM.VerifyAssertions) { 545 VM._assert(isPageAligned(address) && isPageMultiple(size)); 546 } 547 return SysCall.sysCall.sysMProtect(address, size, prot) == 0; 548 } 549 550 private static int pagesize = -1; 551 private static int pagesizeLog = -1; 552 553 /** 554 * Do getpagesize call 555 * @return page size 556 */ 557 public static int getPagesize() { 558 if (pagesize == -1) { 559 pagesize = SysCall.sysCall.sysGetPageSize(); 560 pagesizeLog = -1; 561 int temp = pagesize; 562 while (temp > 0) { 563 temp >>>= 1; 564 pagesizeLog++; 565 } 566 if (VM.VerifyAssertions) VM._assert((1 << pagesizeLog) == pagesize); 567 } 568 return pagesize; 569 } 570 571 public static void dumpMemory(Address start, int beforeBytes, int afterBytes) { 572 573 beforeBytes = alignDown(beforeBytes, BYTES_IN_ADDRESS); 574 afterBytes = alignUp(afterBytes, BYTES_IN_ADDRESS); 575 VM.sysWrite("---- Dumping memory from "); 576 VM.sysWrite(start.minus(beforeBytes)); 577 VM.sysWrite(" to "); 578 VM.sysWrite(start.plus(afterBytes)); 579 VM.sysWrite(" ----\n"); 580 for (int i = -beforeBytes; i < afterBytes; i += BYTES_IN_ADDRESS) { 581 VM.sysWrite(i, ": "); 582 VM.sysWrite(start.plus(i)); 583 Word value = start.plus(i).loadWord(); 584 VM.sysWriteln(" ", value); 585 } 586 } 587 588 @Inline 589 public static Address alignUp(Address address, int alignment) { 590 return address.plus(alignment - 1).toWord().and(Word.fromIntSignExtend(~(alignment - 1))).toAddress(); 591 } 592 593 @Inline 594 public static Address alignDown(Address address, int alignment) { 595 return address.toWord().and(Word.fromIntSignExtend(~(alignment - 1))).toAddress(); 596 } 597 598 // These versions are here to accommodate the boot image writer 599 @Inline 600 public static int alignUp(int address, int alignment) { 601 return ((address + alignment - 1) & ~(alignment - 1)); 602 } 603 604 @Inline 605 public static int alignDown(int address, int alignment) { 606 return (address & ~(alignment - 1)); 607 } 608 }