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 *
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 arraycopy8Bit(srcPtr, dstPtr, 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 srcPtr The source start address
108 * @param dstPtr The destination start address
109 * @param copyBytes The number of bytes to be copied
110 */
111 public static void arraycopy8Bit(Address srcPtr, Address dstPtr , 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 *
198 * Assumption 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 arraycopy16Bit(srcPtr, dstPtr, copyBytes);
211 }
212 /**
213 * Low level copy of <code>copyBytes</code> bytes from <code>src[srcPos]</code> to <code>dst[dstPos]</code>.
214 *
215 * Assumption <code>src != dst || (srcPos >= dstPos)</code> and element size is 2 bytes.
216 *
217 * @param srcPtr The source start address
218 * @param dstPtr The destination start address
219 * @param copyBytes The number of bytes to be copied
220 */
221 public static void arraycopy16Bit(Address srcPtr, Address dstPtr , 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 *
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 arraycopy32Bit(srcPtr, dstPtr, copyBytes);
301 }
302
303 /**
304 * Low level copy of <code>copyBytes</code> bytes from <code>src[srcPos]</code> to <code>dst[dstPos]</code>.
305 *
306 * Assumption <code>src != dst || (srcPos >= dstPos)</code> and element size is 4 bytes.
307 *
308 * @param srcPtr The source start address
309 * @param dstPtr The destination start address
310 * @param copyBytes The number of bytes to be copied
311 */
312 public static void arraycopy32Bit(Address srcPtr, Address dstPtr , int copyBytes) {
313 if (USE_NATIVE && copyBytes > NATIVE_THRESHOLD) {
314 memcopy(dstPtr, srcPtr, copyBytes);
315 } else {
316 // The elements of int[] and float[] are always 32 bit aligned
317 // therefore we can do 32 bit load/stores without worrying about alignment.
318 // TODO: optimize to use 64bit copies. Suspected problem in _202_jess with overlapping arrays
319 //aligned32Copy(dstPtr, srcPtr, Offset.fromIntSignExtend(len << LOG_BYTES_IN_INT));
320 Address endPtr = srcPtr.plus(copyBytes);
321 while (srcPtr.LT(endPtr)) {
322 dstPtr.store(srcPtr.loadInt());
323 srcPtr = srcPtr.plus(4);
324 dstPtr = dstPtr.plus(4);
325 }
326 }
327 }
328 /**
329 * Low level copy of <code>len</code> elements from <code>src[srcPos]</code> to <code>dst[dstPos]</code>.
330 *
331 * Assumption <code>src != dst || (srcPos >= dstPos)</code> and element size is 8 bytes.
332 *
333 * @param src the source array
334 * @param srcIdx index in the source array to begin copy
335 * @param dst the destination array
336 * @param dstIdx index in the destination array to being copy
337 * @param len number of array elements to copy
338 */
339 public static void arraycopy64Bit(Object src, int srcIdx, Object dst, int dstIdx, int len) {
340 Offset srcOffset = Offset.fromIntZeroExtend(srcIdx << LOG_BYTES_IN_DOUBLE);
341 Offset dstOffset = Offset.fromIntZeroExtend(dstIdx << LOG_BYTES_IN_DOUBLE);
342 int copyBytes = len << LOG_BYTES_IN_DOUBLE;
343 arraycopy64Bit(Magic.objectAsAddress(src).plus(srcOffset), Magic.objectAsAddress(dst).plus(dstOffset), copyBytes);
344 }
345
346 /**
347 * Low level copy of <code>copyBytes</code> bytes from <code>src[srcPos]</code> to <code>dst[dstPos]</code>.
348 *
349 * Assumption <code>src != dst || (srcPos >= dstPos)</code> and element size is 8 bytes.
350 *
351 * @param srcPtr The source start address
352 * @param dstPtr The destination start address
353 * @param copyBytes The number of bytes to be copied
354 */
355 public static void arraycopy64Bit(Address srcPtr, Address dstPtr , int copyBytes) {
356 if (USE_NATIVE && copyBytes > NATIVE_THRESHOLD) {
357 memcopy(dstPtr, srcPtr, copyBytes);
358 } else {
359 // The elements of long[] and double[] are always doubleword aligned
360 // therefore we can do 64 bit load/stores without worrying about alignment.
361 Address endPtr = srcPtr.plus(copyBytes);
362 while (srcPtr.LT(endPtr)) {
363 copy8Bytes(dstPtr, srcPtr);
364 srcPtr = srcPtr.plus(8);
365 dstPtr = dstPtr.plus(8);
366 }
367 }
368 }
369
370
371 /**
372 * Copy numbytes from src to dst.
373 * Assumption either the ranges are non overlapping, or src >= dst + 4.
374 * Also, src and dst are 4 byte aligned and numBytes is a multiple of 4.
375 * @param dst the destination addr
376 * @param src the source addr
377 * @param numBytes the number of bytes top copy
378 */
379 public static void aligned32Copy(Address dst, Address src, Offset numBytes) {
380 if (USE_NATIVE && numBytes.sGT(Offset.fromIntSignExtend(NATIVE_THRESHOLD))) {
381 memcopy(dst, src, numBytes.toWord().toExtent());
382 } else {
383 if (BYTES_IN_COPY == 8) {
384 Word wordMask = Word.fromIntZeroExtend(BYTES_IN_COPY-1);
385 Word srcAlignment = src.toWord().and(wordMask);
386 if (srcAlignment.EQ(dst.toWord().and(wordMask))) {
387 Offset i = Offset.zero();
388 if (srcAlignment.EQ(Word.fromIntZeroExtend(BYTES_IN_INT))) {
389 copy4Bytes(dst.plus(i), src.plus(i));
390 i = i.plus(BYTES_IN_INT);
391 }
392 Word endAlignment = srcAlignment.plus(numBytes).and(wordMask);
393 numBytes = numBytes.minus(endAlignment.toOffset());
394 for (; i.sLT(numBytes); i = i.plus(BYTES_IN_COPY)) {
395 copy8Bytes(dst.plus(i), src.plus(i));
396 }
397 if (!endAlignment.isZero()) {
398 copy4Bytes(dst.plus(i), src.plus(i));
399 }
400 return;
401 }
402 }
403 //normal case: 32 bit or (64 bit not aligned)
404 for (Offset i = Offset.zero(); i.sLT(numBytes); i = i.plus(BYTES_IN_INT)) {
405 copy4Bytes(dst.plus(i), src.plus(i));
406 }
407 }
408 }
409
410 public static void aligned32Copy(Address dst, Address src, int numBytes) {
411 aligned32Copy(dst, src, Offset.fromIntSignExtend(numBytes));
412 }
413
414 /**
415 * Copy numbytes from src to dst.
416 * Assumption either the ranges are non overlapping, or src >= dst + BYTES_IN_ADDRESS.
417 * Also, src and dst are word aligned and numBytes is a multiple of BYTES_IN_ADDRESS.
418 * @param dst the destination addr
419 * @param src the source addr
420 * @param numBytes the number of bytes top copy
421 */
422 public static void alignedWordCopy(Address dst, Address src, int numBytes) {
423 if (USE_NATIVE && numBytes > NATIVE_THRESHOLD) {
424 memcopy(dst, src, numBytes);
425 } else {
426 internalAlignedWordCopy(dst, src, numBytes);
427 }
428 }
429
430 /**
431 * Copy <code>numbytes</code> from <code>src</code> to <code>dst</code>.
432 * Assumption either the ranges are non overlapping, or <code>src >= dst + BYTES_IN_ADDRESS</code>.
433 * @param dst The destination addr
434 * @param src The source addr
435 * @param numBytes The number of bytes to copy
436 */
437 private static void internalAlignedWordCopy(Address dst, Address src, int numBytes) {
438 Address end = src.plus(numBytes);
439 while (src.LT(end)) {
440 dst.store(src.loadWord());
441 src = src.plus(BYTES_IN_ADDRESS);
442 dst = dst.plus(BYTES_IN_ADDRESS);
443 }
444 }
445
446 /**
447 * Copy a region of memory.
448 * @param dst Destination address
449 * @param src Source address
450 * @param cnt Number of bytes to copy
451 * Assumption: source and destination regions do not overlap
452 */
453 public static void memcopy(Address dst, Address src, Extent cnt) {
454 SysCall.sysCall.sysCopy(dst, src, cnt);
455 }
456
457 public static void memcopy(Address dst, Address src, int cnt) {
458 SysCall.sysCall.sysCopy(dst, src, Extent.fromIntSignExtend(cnt));
459 }
460
461 /**
462 * Zero a region of memory.
463 * @param start of address range (inclusive)
464 * @param len extent to zero.
465 */
466 public static void zero(Address start, Extent len) {
467 SysCall.sysCall.sysZero(start, len);
468 }
469
470 /**
471 * Zero a range of pages of memory.
472 * @param start Starting address (must be a page address)
473 * @param len Number of bytes (must be multiple of page size)
474 */
475 public static void zeroPages(Address start, int len) {
476 if (VM.VerifyAssertions) VM._assert(isPageAligned(start) && isPageMultiple(len));
477 SysCall.sysCall.sysZeroPages(start, len);
478 }
479
480 ////////////////////////
481 // (2) Cache management
482 ////////////////////////
483
484 /**
485 * Synchronize a region of memory: force data in dcache to be written out to main
486 * memory so that it will be seen by icache when instructions are fetched back.
487 * @param address Start of address range
488 * @param size Size of address range (bytes)
489 */
490 public static void sync(Address address, int size) {
491 SysCall.sysCall.sysSyncCache(address, size);
492 }
493
494 ////////////////////////
495 // (3) MMap
496 ////////////////////////
497
498 // constants for protection and mapping calls
499 public static final int PROT_NONE = 0;
500 public static final int PROT_READ = 1;
501 public static final int PROT_WRITE = 2;
502 public static final int PROT_EXEC = 4;
503
504 public static final int MAP_PRIVATE = 2;
505 public static final int MAP_FIXED = (VM.BuildForLinux) ? 16 : (VM.BuildForOsx) ? 16 : (VM.BuildForSolaris) ? 0x10 :256;
506 public static final int MAP_ANONYMOUS = (VM.BuildForLinux) ? 32 : (VM.BuildForOsx) ? 0x1000 : (VM.BuildForSolaris) ? 0x100 : 16;
507
508 public static boolean isPageMultiple(int val) {
509 int pagesizeMask = getPagesize() - 1;
510 return ((val & pagesizeMask) == 0);
511 }
512
513 public static boolean isPageMultiple(Extent val) {
514 Word pagesizeMask = Word.fromIntZeroExtend(getPagesize() - 1);
515 return val.toWord().and(pagesizeMask).isZero();
516 }
517
518 public static boolean isPageMultiple(Offset val) {
519 Word pagesizeMask = Word.fromIntZeroExtend(getPagesize() - 1);
520 return val.toWord().and(pagesizeMask).isZero();
521 }
522
523 public static boolean isPageAligned(Address addr) {
524 Word pagesizeMask = Word.fromIntZeroExtend(getPagesize() - 1);
525 return addr.toWord().and(pagesizeMask).isZero();
526 }
527
528 /**
529 * Do generic mmap non-file memory mapping call
530 * @param address Start of address range (Address)
531 * @param size Size of address range
532 * @param prot Protection (int)
533 * @param flags (int)
534 * @return Address (of region) if successful; errno (1 to 127) otherwise
535 */
536 public static Address mmap(Address address, Extent size, int prot, int flags) {
537 if (VM.VerifyAssertions) {
538 VM._assert(isPageAligned(address) && isPageMultiple(size));
539 }
540 return SysCall.sysCall.sysMMapErrno(address, size, prot, flags, -1, Offset.zero());
541 }
542
543 /**
544 * Do mmap demand zero fixed address memory mapping call
545 * @param address Start of address range
546 * @param size Size of address range
547 * @return Address (of region) if successful; errno (1 to 127) otherwise
548 */
549 public static Address dzmmap(Address address, Extent size) {
550 if (VM.VerifyAssertions) {
551 VM._assert(isPageAligned(address) && isPageMultiple(size));
552 }
553 int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
554 int flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED;
555 return mmap(address, size, prot, flags);
556 }
557
558 /**
559 * Do mprotect system call
560 * @param address Start of address range (Address)
561 * @param size Size of address range
562 * @param prot Protection (int)
563 * @return true iff success
564 */
565 public static boolean mprotect(Address address, Extent size, int prot) {
566 if (VM.VerifyAssertions) {
567 VM._assert(isPageAligned(address) && isPageMultiple(size));
568 }
569 return SysCall.sysCall.sysMProtect(address, size, prot) == 0;
570 }
571
572 private static int pagesize = -1;
573 private static int pagesizeLog = -1;
574
575 /**
576 * Do getpagesize call
577 * @return page size
578 */
579 public static int getPagesize() {
580 if (pagesize == -1) {
581 pagesize = SysCall.sysCall.sysGetPageSize();
582 pagesizeLog = -1;
583 int temp = pagesize;
584 while (temp > 0) {
585 temp >>>= 1;
586 pagesizeLog++;
587 }
588 if (VM.VerifyAssertions) VM._assert((1 << pagesizeLog) == pagesize);
589 }
590 return pagesize;
591 }
592
593 public static void dumpMemory(Address start, int beforeBytes, int afterBytes) {
594
595 beforeBytes = alignDown(beforeBytes, BYTES_IN_ADDRESS);
596 afterBytes = alignUp(afterBytes, BYTES_IN_ADDRESS);
597 VM.sysWrite("---- Dumping memory from ");
598 VM.sysWrite(start.minus(beforeBytes));
599 VM.sysWrite(" to ");
600 VM.sysWrite(start.plus(afterBytes));
601 VM.sysWrite(" ----\n");
602 for (int i = -beforeBytes; i < afterBytes; i += BYTES_IN_ADDRESS) {
603 VM.sysWrite(i, ": ");
604 VM.sysWrite(start.plus(i));
605 Word value = start.plus(i).loadWord();
606 VM.sysWriteln(" ", value);
607 }
608 }
609
610 @Inline
611 public static Address alignUp(Address address, int alignment) {
612 return address.plus(alignment - 1).toWord().and(Word.fromIntSignExtend(~(alignment - 1))).toAddress();
613 }
614
615 @Inline
616 public static Address alignDown(Address address, int alignment) {
617 return address.toWord().and(Word.fromIntSignExtend(~(alignment - 1))).toAddress();
618 }
619
620 // These versions are here to accommodate the boot image writer
621 @Inline
622 public static int alignUp(int address, int alignment) {
623 return ((address + alignment - 1) & ~(alignment - 1));
624 }
625
626 @Inline
627 public static int alignDown(int address, int alignment) {
628 return (address & ~(alignment - 1));
629 }
630 }