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