# HG changeset patch # User Robert Clipsham # Date 1246921047 -3600 # Node ID d28cd7c45267f8efb6efd0dffd49619f122861dc # Parent b265fb6ce15b1646e073592a0e3f8d10043ac15d Removed druntime from the repository. Updated .hgignore to ignore druntime. diff -r b265fb6ce15b -r d28cd7c45267 .hgignore --- a/.hgignore Mon Jul 06 23:56:11 2009 +0100 +++ b/.hgignore Mon Jul 06 23:57:27 2009 +0100 @@ -21,6 +21,7 @@ ^tests/dstress/ ^tests/reference/ ^tango/ +^druntime/ ^import/ ^bin/ldc2?$ ^bin/ldc2?\.conf$ diff -r b265fb6ce15b -r d28cd7c45267 druntime/import/core/bitmanip.di --- a/druntime/import/core/bitmanip.di Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,262 +0,0 @@ -/** - * This module contains a collection of bit-level operations. - * - * Copyright: Copyright (c) 2005-2008, The D Runtime Project - * License: BSD Style, see LICENSE - * Authors: Walter Bright, Don Clugston, Sean Kelly - */ -module core.bitmanip; - - -version( DDoc ) -{ - /** - * Scans the bits in v starting with bit 0, looking - * for the first set bit. - * Returns: - * The bit number of the first bit set. - * The return value is undefined if v is zero. - */ - int bsf( uint v ); - - - /** - * Scans the bits in v from the most significant bit - * to the least significant bit, looking - * for the first set bit. - * Returns: - * The bit number of the first bit set. - * The return value is undefined if v is zero. - * Example: - * --- - * import bitmanip; - * - * int main() - * { - * uint v; - * int x; - * - * v = 0x21; - * x = bsf(v); - * printf("bsf(x%x) = %d\n", v, x); - * x = bsr(v); - * printf("bsr(x%x) = %d\n", v, x); - * return 0; - * } - * --- - * Output: - * bsf(x21) = 0
- * bsr(x21) = 5 - */ - int bsr( uint v ); - - - /** - * Tests the bit. - */ - int bt( uint* p, uint bitnum ); - - - /** - * Tests and complements the bit. - */ - int btc( uint* p, uint bitnum ); - - - /** - * Tests and resets (sets to 0) the bit. - */ - int btr( uint* p, uint bitnum ); - - - /** - * Tests and sets the bit. - * Params: - * p = a non-NULL pointer to an array of uints. - * index = a bit number, starting with bit 0 of p[0], - * and progressing. It addresses bits like the expression: - --- - p[index / (uint.sizeof*8)] & (1 << (index & ((uint.sizeof*8) - 1))) - --- - * Returns: - * A non-zero value if the bit was set, and a zero - * if it was clear. - * - * Example: - * --- - import bitmanip; - - int main() - { - uint array[2]; - - array[0] = 2; - array[1] = 0x100; - - printf("btc(array, 35) = %d\n", btc(array, 35)); - printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); - - printf("btc(array, 35) = %d\n", btc(array, 35)); - printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); - - printf("bts(array, 35) = %d\n", bts(array, 35)); - printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); - - printf("btr(array, 35) = %d\n", btr(array, 35)); - printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); - - printf("bt(array, 1) = %d\n", bt(array, 1)); - printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); - - return 0; - } - * --- - * Output: -
-    btc(array, 35) = 0
-    array = [0]:x2, [1]:x108
-    btc(array, 35) = -1
-    array = [0]:x2, [1]:x100
-    bts(array, 35) = 0
-    array = [0]:x2, [1]:x108
-    btr(array, 35) = -1
-    array = [0]:x2, [1]:x100
-    bt(array, 1) = -1
-    array = [0]:x2, [1]:x100
-    
- */ - int bts( uint* p, uint bitnum ); - - - /** - * Swaps bytes in a 4 byte uint end-to-end, i.e. byte 0 becomes - * byte 3, byte 1 becomes byte 2, byte 2 becomes byte 1, byte 3 - * becomes byte 0. - */ - uint bswap( uint v ); - - - /** - * Reads I/O port at port_address. - */ - ubyte inp( uint port_address ); - - - /** - * ditto - */ - ushort inpw( uint port_address ); - - - /** - * ditto - */ - uint inpl( uint port_address ); - - - /** - * Writes and returns value to I/O port at port_address. - */ - ubyte outp( uint port_address, ubyte value ); - - - /** - * ditto - */ - ushort outpw( uint port_address, ushort value ); - - - /** - * ditto - */ - uint outpl( uint port_address, uint value ); -} -else -{ - public import std.intrinsic; -} - - -/** - * Calculates the number of set bits in a 32-bit integer. - */ -int popcnt( uint x ) -{ - // Avoid branches, and the potential for cache misses which - // could be incurred with a table lookup. - - // We need to mask alternate bits to prevent the - // sum from overflowing. - // add neighbouring bits. Each bit is 0 or 1. - x = x - ((x>>1) & 0x5555_5555); - // now each two bits of x is a number 00,01 or 10. - // now add neighbouring pairs - x = ((x&0xCCCC_CCCC)>>2) + (x&0x3333_3333); - // now each nibble holds 0000-0100. Adding them won't - // overflow any more, so we don't need to mask any more - - // Now add the nibbles, then the bytes, then the words - // We still need to mask to prevent double-counting. - // Note that if we used a rotate instead of a shift, we - // wouldn't need the masks, and could just divide the sum - // by 8 to account for the double-counting. - // On some CPUs, it may be faster to perform a multiply. - - x += (x>>4); - x &= 0x0F0F_0F0F; - x += (x>>8); - x &= 0x00FF_00FF; - x += (x>>16); - x &= 0xFFFF; - return x; -} - - -/** - * Reverses the order of bits in a 32-bit integer. - */ -uint bitswap( uint x ) -{ - - version( D_InlineAsm_X86 ) - { - asm - { - // Author: Tiago Gasiba. - mov EDX, EAX; - shr EAX, 1; - and EDX, 0x5555_5555; - and EAX, 0x5555_5555; - shl EDX, 1; - or EAX, EDX; - mov EDX, EAX; - shr EAX, 2; - and EDX, 0x3333_3333; - and EAX, 0x3333_3333; - shl EDX, 2; - or EAX, EDX; - mov EDX, EAX; - shr EAX, 4; - and EDX, 0x0f0f_0f0f; - and EAX, 0x0f0f_0f0f; - shl EDX, 4; - or EAX, EDX; - bswap EAX; - } - } - else - { - // swap odd and even bits - x = ((x >> 1) & 0x5555_5555) | ((x & 0x5555_5555) << 1); - // swap consecutive pairs - x = ((x >> 2) & 0x3333_3333) | ((x & 0x3333_3333) << 2); - // swap nibbles - x = ((x >> 4) & 0x0F0F_0F0F) | ((x & 0x0F0F_0F0F) << 4); - // swap bytes - x = ((x >> 8) & 0x00FF_00FF) | ((x & 0x00FF_00FF) << 8); - // swap 2-byte long pairs - x = ( x >> 16 ) | ( x << 16); - return x; - - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/import/core/stdc/complex.d --- a/druntime/import/core/stdc/complex.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,107 +0,0 @@ -/** - * D header file for C99. - * - * Copyright: Copyright Sean Kelly 2005 - 2009. - * License: Boost License 1.0. - * Authors: Sean Kelly - * Standards: ISO/IEC 9899:1999 (E) - * - * Copyright Sean Kelly 2005 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module core.stdc.config; - -extern (C): - -version( Windows ) -{ - alias int c_long; - alias uint c_ulong; -} -else -{ - static if( (void*).sizeof > int.sizeof ) - { - alias long c_long; - alias ulong c_ulong; - } - else - { - alias int c_long; - alias uint c_ulong; - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/import/core/stdc/ctype.d --- a/druntime/import/core/stdc/ctype.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ -/** - * D header file for C99. - * - * Copyright: Copyright Sean Kelly 2005 - 2009. - * License: Boost License 1.0. - * Authors: Sean Kelly - * Standards: ISO/IEC 9899:1999 (E) - * - * Copyright Sean Kelly 2005 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module core.stdc.errno; - -extern (C) int getErrno(); // for internal use -extern (C) int setErrno(int); // for internal use - -alias getErrno errno; -alias setErrno errno; - -extern (C): - -version( Windows ) -{ - enum EPERM = 1; // Operation not permitted - enum ENOENT = 2; // No such file or directory - enum ESRCH = 3; // No such process - enum EINTR = 4; // Interrupted system call - enum EIO = 5; // I/O error - enum ENXIO = 6; // No such device or address - enum E2BIG = 7; // Argument list too long - enum ENOEXEC = 8; // Exec format error - enum EBADF = 9; // Bad file number - enum ECHILD = 10; // No child processes - enum EAGAIN = 11; // Try again - enum ENOMEM = 12; // Out of memory - enum EACCES = 13; // Permission denied - enum EFAULT = 14; // Bad address - enum EBUSY = 16; // Device or resource busy - enum EEXIST = 17; // File exists - enum EXDEV = 18; // Cross-device link - enum ENODEV = 19; // No such device - enum ENOTDIR = 20; // Not a directory - enum EISDIR = 21; // Is a directory - enum EINVAL = 22; // Invalid argument - enum ENFILE = 23; // File table overflow - enum EMFILE = 24; // Too many open files - enum ENOTTY = 25; // Not a typewriter - enum EFBIG = 27; // File too large - enum ENOSPC = 28; // No space left on device - enum ESPIPE = 29; // Illegal seek - enum EROFS = 30; // Read-only file system - enum EMLINK = 31; // Too many links - enum EPIPE = 32; // Broken pipe - enum EDOM = 33; // Math argument out of domain of func - enum ERANGE = 34; // Math result not representable - enum EDEADLK = 36; // Resource deadlock would occur - enum ENAMETOOLONG = 38; // File name too long - enum ENOLCK = 39; // No record locks available - enum ENOSYS = 40; // Function not implemented - enum ENOTEMPTY = 41; // Directory not empty - enum EILSEQ = 42; // Illegal byte sequence - enum EDEADLOCK = EDEADLK; -} -else version( linux ) -{ - enum EPERM = 1; // Operation not permitted - enum ENOENT = 2; // No such file or directory - enum ESRCH = 3; // No such process - enum EINTR = 4; // Interrupted system call - enum EIO = 5; // I/O error - enum ENXIO = 6; // No such device or address - enum E2BIG = 7; // Argument list too long - enum ENOEXEC = 8; // Exec format error - enum EBADF = 9; // Bad file number - enum ECHILD = 10; // No child processes - enum EAGAIN = 11; // Try again - enum ENOMEM = 12; // Out of memory - enum EACCES = 13; // Permission denied - enum EFAULT = 14; // Bad address - enum ENOTBLK = 15; // Block device required - enum EBUSY = 16; // Device or resource busy - enum EEXIST = 17; // File exists - enum EXDEV = 18; // Cross-device link - enum ENODEV = 19; // No such device - enum ENOTDIR = 20; // Not a directory - enum EISDIR = 21; // Is a directory - enum EINVAL = 22; // Invalid argument - enum ENFILE = 23; // File table overflow - enum EMFILE = 24; // Too many open files - enum ENOTTY = 25; // Not a typewriter - enum ETXTBSY = 26; // Text file busy - enum EFBIG = 27; // File too large - enum ENOSPC = 28; // No space left on device - enum ESPIPE = 29; // Illegal seek - enum EROFS = 30; // Read-only file system - enum EMLINK = 31; // Too many links - enum EPIPE = 32; // Broken pipe - enum EDOM = 33; // Math argument out of domain of func - enum ERANGE = 34; // Math result not representable - enum EDEADLK = 35; // Resource deadlock would occur - enum ENAMETOOLONG = 36; // File name too long - enum ENOLCK = 37; // No record locks available - enum ENOSYS = 38; // Function not implemented - enum ENOTEMPTY = 39; // Directory not empty - enum ELOOP = 40; // Too many symbolic links encountered - enum EWOULDBLOCK = EAGAIN; // Operation would block - enum ENOMSG = 42; // No message of desired type - enum EIDRM = 43; // Identifier removed - enum ECHRNG = 44; // Channel number out of range - enum EL2NSYNC = 45; // Level 2 not synchronized - enum EL3HLT = 46; // Level 3 halted - enum EL3RST = 47; // Level 3 reset - enum ELNRNG = 48; // Link number out of range - enum EUNATCH = 49; // Protocol driver not attached - enum ENOCSI = 50; // No CSI structure available - enum EL2HLT = 51; // Level 2 halted - enum EBADE = 52; // Invalid exchange - enum EBADR = 53; // Invalid request descriptor - enum EXFULL = 54; // Exchange full - enum ENOANO = 55; // No anode - enum EBADRQC = 56; // Invalid request code - enum EBADSLT = 57; // Invalid slot - enum EDEADLOCK = EDEADLK; - enum EBFONT = 59; // Bad font file format - enum ENOSTR = 60; // Device not a stream - enum ENODATA = 61; // No data available - enum ETIME = 62; // Timer expired - enum ENOSR = 63; // Out of streams resources - enum ENONET = 64; // Machine is not on the network - enum ENOPKG = 65; // Package not installed - enum EREMOTE = 66; // Object is remote - enum ENOLINK = 67; // Link has been severed - enum EADV = 68; // Advertise error - enum ESRMNT = 69; // Srmount error - enum ECOMM = 70; // Communication error on send - enum EPROTO = 71; // Protocol error - enum EMULTIHOP = 72; // Multihop attempted - enum EDOTDOT = 73; // RFS specific error - enum EBADMSG = 74; // Not a data message - enum EOVERFLOW = 75; // Value too large for defined data type - enum ENOTUNIQ = 76; // Name not unique on network - enum EBADFD = 77; // File descriptor in bad state - enum EREMCHG = 78; // Remote address changed - enum ELIBACC = 79; // Can not access a needed shared library - enum ELIBBAD = 80; // Accessing a corrupted shared library - enum ELIBSCN = 81; // .lib section in a.out corrupted - enum ELIBMAX = 82; // Attempting to link in too many shared libraries - enum ELIBEXEC = 83; // Cannot exec a shared library directly - enum EILSEQ = 84; // Illegal byte sequence - enum ERESTART = 85; // Interrupted system call should be restarted - enum ESTRPIPE = 86; // Streams pipe error - enum EUSERS = 87; // Too many users - enum ENOTSOCK = 88; // Socket operation on non-socket - enum EDESTADDRREQ = 89; // Destination address required - enum EMSGSIZE = 90; // Message too long - enum EPROTOTYPE = 91; // Protocol wrong type for socket - enum ENOPROTOOPT = 92; // Protocol not available - enum EPROTONOSUPPORT = 93; // Protocol not supported - enum ESOCKTNOSUPPORT = 94; // Socket type not supported - enum EOPNOTSUPP = 95; // Operation not supported on transport endpoint - enum EPFNOSUPPORT = 96; // Protocol family not supported - enum EAFNOSUPPORT = 97; // Address family not supported by protocol - enum EADDRINUSE = 98; // Address already in use - enum EADDRNOTAVAIL = 99; // Cannot assign requested address - enum ENETDOWN = 100; // Network is down - enum ENETUNREACH = 101; // Network is unreachable - enum ENETRESET = 102; // Network dropped connection because of reset - enum ECONNABORTED = 103; // Software caused connection abort - enum ECONNRESET = 104; // Connection reset by peer - enum ENOBUFS = 105; // No buffer space available - enum EISCONN = 106; // Transport endpoint is already connected - enum ENOTCONN = 107; // Transport endpoint is not connected - enum ESHUTDOWN = 108; // Cannot send after transport endpoint shutdown - enum ETOOMANYREFS = 109; // Too many references: cannot splice - enum ETIMEDOUT = 110; // Connection timed out - enum ECONNREFUSED = 111; // Connection refused - enum EHOSTDOWN = 112; // Host is down - enum EHOSTUNREACH = 113; // No route to host - enum EALREADY = 114; // Operation already in progress - enum EINPROGRESS = 115; // Operation now in progress - enum ESTALE = 116; // Stale NFS file handle - enum EUCLEAN = 117; // Structure needs cleaning - enum ENOTNAM = 118; // Not a XENIX named type file - enum ENAVAIL = 119; // No XENIX semaphores available - enum EISNAM = 120; // Is a named type file - enum EREMOTEIO = 121; // Remote I/O error - enum EDQUOT = 122; // Quota exceeded - enum ENOMEDIUM = 123; // No medium found - enum EMEDIUMTYPE = 124; // Wrong medium type - enum ECANCELED = 125; // Operation Canceled - enum ENOKEY = 126; // Required key not available - enum EKEYEXPIRED = 127; // Key has expired - enum EKEYREVOKED = 128; // Key has been revoked - enum EKEYREJECTED = 129; // Key was rejected by service - enum EOWNERDEAD = 130; // Owner died - enum ENOTRECOVERABLE = 131; // State not recoverable -} -else version( OSX ) -{ - enum EPERM = 1; // Operation not permitted - enum ENOENT = 2; // No such file or directory - enum ESRCH = 3; // No such process - enum EINTR = 4; // Interrupted system call - enum EIO = 5; // Input/output error - enum ENXIO = 6; // Device not configured - enum E2BIG = 7; // Argument list too long - enum ENOEXEC = 8; // Exec format error - enum EBADF = 9; // Bad file descriptor - enum ECHILD = 10; // No child processes - enum EDEADLK = 11; // Resource deadlock avoided - enum ENOMEM = 12; // Cannot allocate memory - enum EACCES = 13; // Permission denied - enum EFAULT = 14; // Bad address - enum EBUSY = 16; // Device busy - enum EEXIST = 17; // File exists - enum EXDEV = 18; // Cross-device link - enum ENODEV = 19; // Operation not supported by device - enum ENOTDIR = 20; // Not a directory - enum EISDIR = 21; // Is a directory - enum EINVAL = 22; // Invalid argument - enum ENFILE = 23; // Too many open files in system - enum EMFILE = 24; // Too many open files - enum ENOTTY = 25; // Inappropriate ioctl for device - enum ETXTBSY = 26; // Text file busy - enum EFBIG = 27; // File too large - enum ENOSPC = 28; // No space left on device - enum ESPIPE = 29; // Illegal seek - enum EROFS = 30; // Read-only file system - enum EMLINK = 31; // Too many links - enum EPIPE = 32; // Broken pipe - enum EDOM = 33; // Numerical argument out of domain - enum ERANGE = 34; // Result too large - enum EAGAIN = 35; // Resource temporarily unavailable - enum EWOULDBLOCK = EAGAIN; // Operation would block - enum EINPROGRESS = 36; // Operation now in progress - enum EALREADY = 37; // Operation already in progress - enum ENOTSOCK = 38; // Socket operation on non-socket - enum EDESTADDRREQ = 39; // Destination address required - enum EMSGSIZE = 40; // Message too long - enum EPROTOTYPE = 41; // Protocol wrong type for socket - enum ENOPROTOOPT = 42; // Protocol not available - enum EPROTONOSUPPORT = 43; // Protocol not supported - enum ENOTSUP = 45; // Operation not supported - enum EOPNOTSUPP = ENOTSUP; // Operation not supported on socket - enum EAFNOSUPPORT = 47; // Address family not supported by protocol family - enum EADDRINUSE = 48; // Address already in use - enum EADDRNOTAVAIL = 49; // Can't assign requested address - enum ENETDOWN = 50; // Network is down - enum ENETUNREACH = 51; // Network is unreachable - enum ENETRESET = 52; // Network dropped connection on reset - enum ECONNABORTED = 53; // Software caused connection abort - enum ECONNRESET = 54; // Connection reset by peer - enum ENOBUFS = 55; // No buffer space available - enum EISCONN = 56; // Socket is already connected - enum ENOTCONN = 57; // Socket is not connected - enum ETIMEDOUT = 60; // Operation timed out - enum ECONNREFUSED = 61; // Connection refused - enum ELOOP = 62; // Too many levels of symbolic links - enum ENAMETOOLONG = 63; // File name too long - enum EHOSTUNREACH = 65; // No route to host - enum ENOTEMPTY = 66; // Directory not empty - enum EDQUOT = 69; // Disc quota exceeded - enum ESTALE = 70; // Stale NFS file handle - enum ENOLCK = 77; // No locks available - enum ENOSYS = 78; // Function not implemented - enum EOVERFLOW = 84; // Value too large to be stored in data type - enum ECANCELED = 89; // Operation canceled - enum EIDRM = 90; // Identifier removed - enum ENOMSG = 91; // No message of desired type - enum EILSEQ = 92; // Illegal byte sequence - enum EBADMSG = 94; // Bad message - enum EMULTIHOP = 95; // Reserved - enum ENODATA = 96; // No message available on STREAM - enum ENOLINK = 97; // Reserved - enum ENOSR = 98; // No STREAM resources - enum ENOSTR = 99; // Not a STREAM - enum EPROTO = 100; // Protocol error - enum ETIME = 101; // STREAM ioctl timeout - enum ELAST = 101; // Must be equal largest errno -} -else version( freebsd ) -{ - enum EPERM = 1; // Operation not permitted - enum ENOENT = 2; // No such file or directory - enum ESRCH = 3; // No such process - enum EINTR = 4; // Interrupted system call - enum EIO = 5; // Input/output error - enum ENXIO = 6; // Device not configured - enum E2BIG = 7; // Argument list too long - enum ENOEXEC = 8; // Exec format error - enum EBADF = 9; // Bad file descriptor - enum ECHILD = 10; // No child processes - enum EDEADLK = 11; // Resource deadlock avoided - enum ENOMEM = 12; // Cannot allocate memory - enum EACCES = 13; // Permission denied - enum EFAULT = 14; // Bad address - enum ENOTBLK = 15; // Block device required - enum EBUSY = 16; // Device busy - enum EEXIST = 17; // File exists - enum EXDEV = 18; // Cross-device link - enum ENODEV = 19; // Operation not supported by device - enum ENOTDIR = 20; // Not a directory - enum EISDIR = 21; // Is a directory - enum EINVAL = 22; // Invalid argument - enum ENFILE = 23; // Too many open files in system - enum EMFILE = 24; // Too many open files - enum ENOTTY = 25; // Inappropriate ioctl for device - enum ETXTBSY = 26; // Text file busy - enum EFBIG = 27; // File too large - enum ENOSPC = 28; // No space left on device - enum ESPIPE = 29; // Illegal seek - enum EROFS = 30; // Read-only file system - enum EMLINK = 31; // Too many links - enum EPIPE = 32; // Broken pipe - enum EDOM = 33; // Numerical argument out of domain - enum ERANGE = 34; // Result too large - enum EAGAIN = 35; // Resource temporarily unavailable - enum EWOULDBLOCK = EAGAIN; // Operation would block - enum EINPROGRESS = 36; // Operation now in progress - enum EALREADY = 37; // Operation already in progress - enum ENOTSOCK = 38; // Socket operation on non-socket - enum EDESTADDRREQ = 39; // Destination address required - enum EMSGSIZE = 40; // Message too long - enum EPROTOTYPE = 41; // Protocol wrong type for socket - enum ENOPROTOOPT = 42; // Protocol not available - enum EPROTONOSUPPORT = 43; // Protocol not supported - enum ENOTSUP = 45; // Operation not supported - enum EOPNOTSUPP = ENOTSUP; // Operation not supported on socket - enum EAFNOSUPPORT = 47; // Address family not supported by protocol family - enum EADDRINUSE = 48; // Address already in use - enum EADDRNOTAVAIL = 49; // Can't assign requested address - enum ENETDOWN = 50; // Network is down - enum ENETUNREACH = 51; // Network is unreachable - enum ENETRESET = 52; // Network dropped connection on reset - enum ECONNABORTED = 53; // Software caused connection abort - enum ECONNRESET = 54; // Connection reset by peer - enum ENOBUFS = 55; // No buffer space available - enum EISCONN = 56; // Socket is already connected - enum ENOTCONN = 57; // Socket is not connected - enum ESHUTDOWN = 58; // Can't send after socket shutdown - enum ETOOMANYREFS = 59; // Too many refrences; can't splice - enum ETIMEDOUT = 60; // Operation timed out - enum ECONNREFUSED = 61; // Connection refused - enum ELOOP = 62; // Too many levels of symbolic links - enum ENAMETOOLONG = 63; // File name too long - enum EHOSTUNREACH = 65; // No route to host - enum ENOTEMPTY = 66; // Directory not empty - enum EPROCLIM = 67; // Too many processes - enum EUSERS = 68; // Too many users - enum EDQUOT = 69; // Disc quota exceeded - enum ESTALE = 70; // Stale NFS file handle - enum EREMOTE = 71; // Too many levels of remote in path - enum EBADRPC = 72; // RPC struct is bad - enum ERPCMISMATCH = 73; // RPC version wrong - enum EPROGUNAVAIL = 74; // RPC prog. not avail - enum EPROGMISMATCH = 75; // Program version wrong - enum EPROCUNAVAIL = 76; // Bad procedure for program - enum ENOLCK = 77; // No locks available - enum ENOSYS = 78; // Function not implemented - enum EFTYPE = 79; // Inappropriate file type or format - enum EAUTH = 80; // Authentication error - enum ENEEDAUTH = 81; // Need authenticator - enum EIDRM = 82; // Itendifier removed - enum ENOMSG = 83; // No message of desired type - enum EOVERFLOW = 84; // Value too large to be stored in data type - enum ECANCELED = 85; // Operation canceled - enum EILSEQ = 86; // Illegal byte sequence - enum ENOATTR = 87; // Attribute not found - enum EDOOFUS = 88; // Programming error - enum EBADMSG = 89; // Bad message - enum EMULTIHOP = 90; // Multihop attempted - enum ENOLINK = 91; // Link has been severed - enum EPROTO = 92; // Protocol error - enum ELAST = 92; // Must be equal largest errno -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/import/core/stdc/fenv.d --- a/druntime/import/core/stdc/fenv.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,142 +0,0 @@ -/** - * D header file for C99. - * - * Copyright: Copyright Sean Kelly 2005 - 2009. - * License: Boost License 1.0. - * Authors: Sean Kelly - * Standards: ISO/IEC 9899:1999 (E) - * - * Copyright Sean Kelly 2005 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module core.stdc.float_; - -extern (C): - -enum FLT_ROUNDS = 1; -enum FLT_EVAL_METHOD = 2; -enum FLT_RADIX = 2; - -enum DECIMAL_DIG = real.dig; -enum FLT_DIG = float.dig; -enum DBL_DIG = double.dig; -enum LDBL_DIG = real.dig; - -enum FLT_MANT_DIG = float.mant_dig; -enum DBL_MANT_DIG = double.mant_dig; -enum LDBL_MANT_DIG = real.mant_dig; - -enum FLT_MIN = float.min; -enum DBL_MIN = double.min; -enum LDBL_MIN = real.min; - -enum FLT_MAX = float.max; -enum DBL_MAX = double.max; -enum LDBL_MAX = real.max; - -enum FLT_EPSILON = float.epsilon; -enum DBL_EPSILON = double.epsilon; -enum LDBL_EPSILON = real.epsilon; - -enum FLT_MIN_EXP = float.min_exp; -enum DBL_MIN_EXP = double.min_exp; -enum LDBL_MIN_EXP = real.min_exp; - -enum FLT_MAX_EXP = float.max_exp; -enum DBL_MAX_EXP = double.max_exp; -enum LDBL_MAX_EXP = real.max_exp; - -enum FLT_MIN_10_EXP = float.min_10_exp; -enum DBL_MIN_10_EXP = double.min_10_exp; -enum LDBL_MIN_10_EXP = real.min_10_exp; - -enum FLT_MAX_10_EXP = float.max_10_exp; -enum DBL_MAX_10_EXP = double.max_10_exp; -enum LDBL_MAX_10_EXP = real.max_10_exp; diff -r b265fb6ce15b -r d28cd7c45267 druntime/import/core/stdc/inttypes.d --- a/druntime/import/core/stdc/inttypes.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,256 +0,0 @@ -/** - * D header file for C99. - * - * Copyright: Copyright Sean Kelly 2005 - 2009. - * License: Boost License 1.0. - * Authors: Sean Kelly - * Standards: ISO/IEC 9899:1999 (E) - * - * Copyright Sean Kelly 2005 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module core.stdc.locale; - -extern (C): - -struct lconv -{ - char* decimal_point; - char* thousands_sep; - char* grouping; - char* int_curr_symbol; - char* currency_symbol; - char* mon_decimal_point; - char* mon_thousands_sep; - char* mon_grouping; - char* positive_sign; - char* negative_sign; - byte int_frac_digits; - byte frac_digits; - byte p_cs_precedes; - byte p_sep_by_space; - byte n_cs_precedes; - byte n_sep_by_space; - byte p_sign_posn; - byte n_sign_posn; - byte int_p_cs_precedes; - byte int_p_sep_by_space; - byte int_n_cs_precedes; - byte int_n_sep_by_space; - byte int_p_sign_posn; - byte int_n_sign_posn; -} - -enum LC_CTYPE = 0; -enum LC_NUMERIC = 1; -enum LC_TIME = 2; -enum LC_COLLATE = 3; -enum LC_MONETARY = 4; -enum LC_ALL = 6; -enum LC_PAPER = 7; // non-standard -enum LC_NAME = 8; // non-standard -enum LC_ADDRESS = 9; // non-standard -enum LC_TELEPHONE = 10; // non-standard -enum LC_MEASUREMENT = 11; // non-standard -enum LC_IDENTIFICATION = 12; // non-standard - -char* setlocale(int category, in char* locale); -lconv* localeconv(); diff -r b265fb6ce15b -r d28cd7c45267 druntime/import/core/stdc/math.d --- a/druntime/import/core/stdc/math.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,933 +0,0 @@ -/** - * D header file for C99. - * - * Copyright: Copyright Sean Kelly 2005 - 2009. - * License: Boost License 1.0. - * Authors: Sean Kelly - * Standards: ISO/IEC 9899:1999 (E) - * - * Copyright Sean Kelly 2005 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module core.stdc.signal; - -extern (C): - -// this should be volatile -alias int sig_atomic_t; - -private alias void function(int) sigfn_t; - -version( Posix ) -{ - enum SIG_ERR = cast(sigfn_t) -1; - enum SIG_DFL = cast(sigfn_t) 0; - enum SIG_IGN = cast(sigfn_t) 1; - - // standard C signals - enum SIGABRT = 6; // Abnormal termination - enum SIGFPE = 8; // Floating-point error - enum SIGILL = 4; // Illegal hardware instruction - enum SIGINT = 2; // Terminal interrupt character - enum SIGSEGV = 11; // Invalid memory reference - enum SIGTERM = 15; // Termination -} -else -{ - enum SIG_ERR = cast(sigfn_t) -1; - enum SIG_DFL = cast(sigfn_t) 0; - enum SIG_IGN = cast(sigfn_t) 1; - - // standard C signals - enum SIGABRT = 22; // Abnormal termination - enum SIGFPE = 8; // Floating-point error - enum SIGILL = 4; // Illegal hardware instruction - enum SIGINT = 2; // Terminal interrupt character - enum SIGSEGV = 11; // Invalid memory reference - enum SIGTERM = 15; // Termination -} - -sigfn_t signal(int sig, sigfn_t func); -int raise(int sig); diff -r b265fb6ce15b -r d28cd7c45267 druntime/import/core/stdc/stdarg.d --- a/druntime/import/core/stdc/stdarg.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -/** - * D header file for C99. - * - * Copyright: Copyright Sean Kelly 2005 - 2009. - * License: Boost License 1.0. - * Authors: Sean Kelly - * Standards: ISO/IEC 9899:1999 (E) - * - * Copyright Sean Kelly 2005 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module core.stdc.stddef; - -extern (C): - -//alias typeof(int.sizeof) size_t; -//alias typeof(cast(void*)0 - cast(void*)0) ptrdiff_t; - -version( Windows ) -{ - alias wchar wchar_t; -} -else -{ - alias dchar wchar_t; -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/import/core/stdc/stdint.d --- a/druntime/import/core/stdc/stdint.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,154 +0,0 @@ -/** - * D header file for C99. - * - * Copyright: Copyright Sean Kelly 2005 - 2009. - * License: Boost License 1.0. - * Authors: Sean Kelly - * Standards: ISO/IEC 9899:1999 (E) - * - * Copyright Sean Kelly 2005 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module core.stdc.stdio; - -private -{ - import core.stdc.config; - import core.stdc.stddef; // for size_t - import core.stdc.stdarg; // for va_list -} - -extern (C): - -version( Windows ) -{ - enum - { - BUFSIZ = 0x4000, - EOF = -1, - FOPEN_MAX = 20, - FILENAME_MAX = 256, // 255 plus NULL - TMP_MAX = 32767, - SYS_OPEN = 20, // non-standard - } - - enum int _NFILE = 60; // non-standard - enum string _P_tmpdir = "\\"; // non-standard - enum wstring _wP_tmpdir = "\\"; // non-standard - enum int L_tmpnam = _P_tmpdir.length + 12; -} -else version( linux ) -{ - enum - { - BUFSIZ = 8192, - EOF = -1, - FOPEN_MAX = 16, - FILENAME_MAX = 4095, - TMP_MAX = 238328, - L_tmpnam = 20 - } -} -else version( OSX ) -{ - enum - { - BUFSIZ = 1024, - EOF = -1, - FOPEN_MAX = 20, - FILENAME_MAX = 1024, - TMP_MAX = 308915776, - L_tmpnam = 1024, - } - - private - { - struct __sbuf - { - ubyte* _base; - int _size; - } - - struct __sFILEX - { - - } - } -} -else version ( FreeBSD ) -{ - enum - { - EOF = -1, - FOPEN_MAX = 20, - FILENAME_MAX = 1024, - TMP_MAX = 308915776, - L_tmpnam = 1024 - } - - private - { - struct __sbuf - { - ubyte *_base; - int _size; - } - struct __sFILEX - { - - } - } -} -else -{ - static assert( false ); -} - -enum -{ - SEEK_SET, - SEEK_CUR, - SEEK_END -} - -struct _iobuf -{ - align (1): - version( Windows ) - { - char* _ptr; - int _cnt; - char* _base; - int _flag; - int _file; - int _charbuf; - int _bufsiz; - int __tmpnum; - } - else version( linux ) - { - char* _read_ptr; - char* _read_end; - char* _read_base; - char* _write_base; - char* _write_ptr; - char* _write_end; - char* _buf_base; - char* _buf_end; - char* _save_base; - char* _backup_base; - char* _save_end; - void* _markers; - _iobuf* _chain; - int _fileno; - int _blksize; - int _old_offset; - ushort _cur_column; - byte _vtable_offset; - char[1] _shortbuf; - void* _lock; - } - else version( OSX ) - { - ubyte* _p; - int _r; - int _w; - short _flags; - short _file; - __sbuf _bf; - int _lbfsize; - - int* function(void*) _close; - int* function(void*, char*, int) _read; - fpos_t* function(void*, fpos_t, int) _seek; - int* function(void*, char *, int) _write; - - __sbuf _ub; - __sFILEX* _extra; - int _ur; - - ubyte[3] _ubuf; - ubyte[1] _nbuf; - - __sbuf _lb; - - int _blksize; - fpos_t _offset; - } - else version( FreeBSD ) - { - ubyte* _p; - int _r; - int _w; - short _flags; - short _file; - __sbuf _bf; - int _lbfsize; - - void* function() _cookie; - int* function(void*) _close; - int* function(void*, char*, int) _read; - fpos_t* function(void*, fpos_t, int) _seek; - int* function(void*, char *, int) _write; - - __sbuf _ub; - __sFILEX* _extra; - int _ur; - - ubyte[3] _ubuf; - ubyte[1] _nbuf; - - __sbuf _lb; - - int _blksize; - fpos_t _offset; - } - else - { - static assert( false ); - } -} - -alias shared(_iobuf) FILE; - -enum -{ - _F_RDWR = 0x0003, // non-standard - _F_READ = 0x0001, // non-standard - _F_WRIT = 0x0002, // non-standard - _F_BUF = 0x0004, // non-standard - _F_LBUF = 0x0008, // non-standard - _F_ERR = 0x0010, // non-standard - _F_EOF = 0x0020, // non-standard - _F_BIN = 0x0040, // non-standard - _F_IN = 0x0080, // non-standard - _F_OUT = 0x0100, // non-standard - _F_TERM = 0x0200, // non-standard -} - -version( Windows ) -{ - enum - { - _IOFBF = 0, - _IOLBF = 0x40, - _IONBF = 4, - _IOREAD = 1, // non-standard - _IOWRT = 2, // non-standard - _IOMYBUF = 8, // non-standard - _IOEOF = 0x10, // non-standard - _IOERR = 0x20, // non-standard - _IOSTRG = 0x40, // non-standard - _IORW = 0x80, // non-standard - _IOTRAN = 0x100, // non-standard - _IOAPP = 0x200, // non-standard - } - - extern shared void function() _fcloseallp; - - private extern shared FILE[_NFILE] _iob; - - shared stdin = &_iob[0]; - shared stdout = &_iob[1]; - shared stderr = &_iob[2]; - shared stdaux = &_iob[3]; - shared stdprn = &_iob[4]; -} -else version( linux ) -{ - enum - { - _IOFBF = 0, - _IOLBF = 1, - _IONBF = 2, - } - - extern shared FILE* stdin; - extern shared FILE* stdout; - extern shared FILE* stderr; -} -else version( OSX ) -{ - enum - { - _IOFBF = 0, - _IOLBF = 1, - _IONBF = 2, - } - - private extern shared FILE* __stdinp; - private extern shared FILE* __stdoutp; - private extern shared FILE* __stderrp; - - alias __stdinp stdin; - alias __stdoutp stdout; - alias __stderrp stderr; -} -else version( FreeBSD ) -{ - private extern shared FILE[3] __sF; - - shared stdin = &__sF[0]; - shared stdout = &__sF[1]; - shared stderr = &__sF[2]; -} -else -{ - static assert( false ); -} - -alias int fpos_t; - -int remove(in char* filename); -int rename(in char* from, in char* to); - -FILE* tmpfile(); -char* tmpnam(char* s); - -int fclose(FILE* stream); -int fflush(FILE* stream); -FILE* fopen(in char* filename, in char* mode); -FILE* freopen(in char* filename, in char* mode, FILE* stream); - -void setbuf(FILE* stream, char* buf); -int setvbuf(FILE* stream, char* buf, int mode, size_t size); - -int fprintf(FILE* stream, in char* format, ...); -int fscanf(FILE* stream, in char* format, ...); -int sprintf(char* s, in char* format, ...); -int sscanf(in char* s, in char* format, ...); -int vfprintf(FILE* stream, in char* format, va_list arg); -int vfscanf(FILE* stream, in char* format, va_list arg); -int vsprintf(char* s, in char* format, va_list arg); -int vsscanf(in char* s, in char* format, va_list arg); -int vprintf(in char* format, va_list arg); -int vscanf(in char* format, va_list arg); -int printf(in char* format, ...); -int scanf(in char* format, ...); - -int fgetc(FILE* stream); -int fputc(int c, FILE* stream); - -char* fgets(char* s, int n, FILE* stream); -int fputs(in char* s, FILE* stream); -char* gets(char* s); -int puts(in char* s); - -extern (D) -{ - int getchar() { return getc(stdin); } - int putchar(int c) { return putc(c,stdout); } - int getc(FILE* stream) { return fgetc(stream); } - int putc(int c, FILE* stream) { return fputc(c,stream); } -} - -int ungetc(int c, FILE* stream); - -size_t fread(void* ptr, size_t size, size_t nmemb, FILE* stream); -size_t fwrite(in void* ptr, size_t size, size_t nmemb, FILE* stream); - -int fgetpos(FILE* stream, fpos_t * pos); -int fsetpos(FILE* stream, in fpos_t* pos); - -int fseek(FILE* stream, c_long offset, int whence); -c_long ftell(FILE* stream); - -version( Windows ) -{ - extern (D) - { - void rewind(FILE* stream) { fseek(stream,0L,SEEK_SET); stream._flag&=~_IOERR; } - void clearerr(FILE* stream) { stream._flag &= ~(_IOERR|_IOEOF); } - int feof(FILE* stream) { return stream._flag&_IOEOF; } - int ferror(FILE* stream) { return stream._flag&_IOERR; } - } - int _snprintf(char* s, size_t n, in char* fmt, ...); - alias _snprintf snprintf; - - int _vsnprintf(char* s, size_t n, in char* format, va_list arg); - alias _vsnprintf vsnprintf; -} -else version( linux ) -{ - void rewind(FILE* stream); - void clearerr(FILE* stream); - int feof(FILE* stream); - int ferror(FILE* stream); - int fileno(FILE *); - - int snprintf(char* s, size_t n, in char* format, ...); - int vsnprintf(char* s, size_t n, in char* format, va_list arg); -} -else version( OSX ) -{ - void rewind(FILE*); - void clearerr(FILE*); - int feof(FILE*); - int ferror(FILE*); - int fileno(FILE*); - - int snprintf(char* s, size_t n, in char* format, ...); - int vsnprintf(char* s, size_t n, in char* format, va_list arg); -} -else version( FreeBSD ) -{ - void rewind(FILE*); - void clearerr(FILE*); - int feof(FILE*); - int ferror(FILE*); - int fileno(FILE*); - - int snprintf(char* s, size_t n, in char* format, ...); - int vsnprintf(char* s, size_t n, in char* format, va_list arg); -} -else -{ - static assert( false ); -} - -void perror(in char* s); diff -r b265fb6ce15b -r d28cd7c45267 druntime/import/core/stdc/stdlib.d --- a/druntime/import/core/stdc/stdlib.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -/** - * D header file for C99. - * - * Copyright: Copyright Sean Kelly 2005 - 2009. - * License: Boost License 1.0. - * Authors: Sean Kelly - * Standards: ISO/IEC 9899:1999 (E) - * - * Copyright Sean Kelly 2005 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module core.stdc.string; - -private import core.stdc.stddef; // for size_t - -extern (C): - -void* memchr(in void* s, int c, size_t n); -int memcmp(in void* s1, in void* s2, size_t n); -void* memcpy(void* s1, in void* s2, size_t n); -void* memmove(void* s1, in void* s2, size_t n); -void* memset(void* s, int c, size_t n); - -char* strcpy(char* s1, in char* s2); -char* strncpy(char* s1, in char* s2, size_t n); -char* strcat(char* s1, in char* s2); -char* strncat(char* s1, in char* s2, size_t n); -int strcmp(in char* s1, in char* s2); -int strcoll(in char* s1, in char* s2); -int strncmp(in char* s1, in char* s2, size_t n); -size_t strxfrm(char* s1, in char* s2, size_t n); -char* strchr(in char* s, int c); -size_t strcspn(in char* s1, in char* s2); -char* strpbrk(in char* s1, in char* s2); -char* strrchr(in char* s, int c); -size_t strspn(in char* s1, in char* s2); -char* strstr(in char* s1, in char* s2); -char* strtok(char* s1, in char* s2); -char* strerror(int errnum); -size_t strlen(in char* s); diff -r b265fb6ce15b -r d28cd7c45267 druntime/import/core/stdc/tgmath.d --- a/druntime/import/core/stdc/tgmath.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,657 +0,0 @@ -/** - * D header file for C99. - * - * Copyright: Copyright Sean Kelly 2005 - 2009. - * License: Boost License 1.0. - * Authors: Sean Kelly - * Standards: ISO/IEC 9899:1999 (E) - * - * Copyright Sean Kelly 2005 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module core.stdc.time; - -private import core.stdc.config; -private import core.stdc.stddef; // for size_t - -extern (C): - -version( Windows ) -{ - struct tm - { - int tm_sec; // seconds after the minute - [0, 60] - int tm_min; // minutes after the hour - [0, 59] - int tm_hour; // hours since midnight - [0, 23] - int tm_mday; // day of the month - [1, 31] - int tm_mon; // months since January - [0, 11] - int tm_year; // years since 1900 - int tm_wday; // days since Sunday - [0, 6] - int tm_yday; // days since January 1 - [0, 365] - int tm_isdst; // Daylight Saving Time flag - } -} -else -{ - struct tm - { - int tm_sec; // seconds after the minute [0-60] - int tm_min; // minutes after the hour [0-59] - int tm_hour; // hours since midnight [0-23] - int tm_mday; // day of the month [1-31] - int tm_mon; // months since January [0-11] - int tm_year; // years since 1900 - int tm_wday; // days since Sunday [0-6] - int tm_yday; // days since January 1 [0-365] - int tm_isdst; // Daylight Savings Time flag - c_long tm_gmtoff; // offset from CUT in seconds - char* tm_zone; // timezone abbreviation - } -} - -alias c_long time_t; -alias c_long clock_t; - -version( Windows ) -{ - clock_t CLOCKS_PER_SEC = 1000; -} -else version( OSX ) -{ - clock_t CLOCKS_PER_SEC = 100; -} -else version( freebsd ) -{ - clock_t CLOCKS_PER_SEC = 128; -} -else -{ - clock_t CLOCKS_PER_SEC = 1000000; -} - -clock_t clock(); -double difftime(time_t time1, time_t time0); -time_t mktime(tm* timeptr); -time_t time(time_t* timer); -char* asctime(in tm* timeptr); -char* ctime(in time_t* timer); -tm* gmtime(in time_t* timer); -tm* localtime(in time_t* timer); -size_t strftime(char* s, size_t maxsize, in char* format, in tm* timeptr); - -version( Windows ) -{ - void tzset(); // non-standard - void _tzset(); // non-standard - char* _strdate(char* s); // non-standard - char* _strtime(char* s); // non-standard -} -else version( linux ) -{ - void tzset(); // non-standard -} -else version( freebsd ) -{ - void tzset(); // non-standard -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/import/core/stdc/wchar_.d --- a/druntime/import/core/stdc/wchar_.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,108 +0,0 @@ -/** - * D header file for C99. - * - * Copyright: Copyright Sean Kelly 2005 - 2009. - * License: Boost License 1.0. - * Authors: Sean Kelly - * Standards: ISO/IEC 9899:1999 (E) - * - * Copyright Sean Kelly 2005 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module core.stdc.wctype; - -public import core.stdc.wchar_; // for wint_t, WEOF - -extern (C): - -alias wchar_t wctrans_t; -alias wchar_t wctype_t; - -int iswalnum(wint_t wc); -int iswalpha(wint_t wc); -int iswblank(wint_t wc); -int iswcntrl(wint_t wc); -int iswdigit(wint_t wc); -int iswgraph(wint_t wc); -int iswlower(wint_t wc); -int iswprint(wint_t wc); -int iswpunct(wint_t wc); -int iswspace(wint_t wc); -int iswupper(wint_t wc); -int iswxdigit(wint_t wc); - -int iswctype(wint_t wc, wctype_t desc); -wctype_t wctype(in char* property); -wint_t towlower(wint_t wc); -wint_t towupper(wint_t wc); -wint_t towctrans(wint_t wc, wctrans_t desc); -wctrans_t wctrans(in char* property); \ No newline at end of file diff -r b265fb6ce15b -r d28cd7c45267 druntime/import/core/sys/osx/mach/kern_return.d --- a/druntime/import/core/sys/osx/mach/kern_return.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -/** - * D header file for OSX. - * - * Copyright: Copyright Sean Kelly 2008 - 2009. - * License: Boost License 1.0. - * Authors: Sean Kelly - * - * Copyright Sean Kelly 2008 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module core.sys.osx.mach.port; - -extern (C): - -version( X86 ) - version = i386; -version( X86_64 ) - version = i386; -version( i386 ) -{ - alias uint natural_t; - alias natural_t mach_port_t; -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/import/core/sys/osx/mach/semaphore.d --- a/druntime/import/core/sys/osx/mach/semaphore.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -/** - * D header file for OSX. - * - * Copyright: Copyright Sean Kelly 2008 - 2009. - * License: Boost License 1.0. - * Authors: Sean Kelly - * - * Copyright Sean Kelly 2008 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module core.sys.osx.mach.thread_act; - -public import core.sys.osx.mach.kern_return; -public import core.sys.osx.mach.port; - -extern (C): - -version( X86 ) - version = i386; -version( X86_64 ) - version = i386; -version( i386 ) -{ - alias mach_port_t thread_act_t; - alias void thread_state_t; - alias int thread_state_flavor_t; - alias natural_t mach_msg_type_number_t; - - enum - { - x86_THREAD_STATE32 = 1, - x86_FLOAT_STATE32 = 2, - x86_EXCEPTION_STATE32 = 3, - x86_THREAD_STATE64 = 4, - x86_FLOAT_STATE64 = 5, - x86_EXCEPTION_STATE64 = 6, - x86_THREAD_STATE = 7, - x86_FLOAT_STATE = 8, - x86_EXCEPTION_STATE = 9, - x86_DEBUG_STATE32 = 10, - x86_DEBUG_STATE64 = 11, - x86_DEBUG_STATE = 12, - THREAD_STATE_NONE = 13, - } - - struct x86_thread_state32_t - { - uint eax; - uint ebx; - uint ecx; - uint edx; - uint edi; - uint esi; - uint ebp; - uint esp; - uint ss; - uint eflags; - uint eip; - uint cs; - uint ds; - uint es; - uint fs; - uint gs; - } - - struct x86_thread_state64_t - { - ulong rax; - ulong rbx; - ulong rcx; - ulong rdx; - ulong rdi; - ulong rsi; - ulong rbp; - ulong rsp; - ulong r8; - ulong r9; - ulong r10; - ulong r11; - ulong r12; - ulong r13; - ulong r14; - ulong r15; - ulong rip; - ulong rflags; - ulong cs; - ulong fs; - ulong gs; - } - - struct x86_state_hdr_t - { - int flavor; - int count; - } - - struct x86_thread_state_t - { - x86_state_hdr_t tsh; - union _uts - { - x86_thread_state32_t ts32; - x86_thread_state64_t ts64; - } - _uts uts; - } - - enum : mach_msg_type_number_t - { - x86_THREAD_STATE32_COUNT = cast(mach_msg_type_number_t)( x86_thread_state32_t.sizeof / int.sizeof ), - x86_THREAD_STATE64_COUNT = cast(mach_msg_type_number_t)( x86_thread_state64_t.sizeof / int.sizeof ), - x86_THREAD_STATE_COUNT = cast(mach_msg_type_number_t)( x86_thread_state_t.sizeof / int.sizeof ), - } - - alias x86_THREAD_STATE MACHINE_THREAD_STATE; - alias x86_THREAD_STATE_COUNT MACHINE_THREAD_STATE_COUNT; - - mach_port_t mach_thread_self(); - kern_return_t thread_suspend(thread_act_t); - kern_return_t thread_resume(thread_act_t); - kern_return_t thread_get_state(thread_act_t, thread_state_flavor_t, thread_state_t*, mach_msg_type_number_t*); -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/import/core/sys/posix/arpa/inet.d --- a/druntime/import/core/sys/posix/arpa/inet.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,132 +0,0 @@ -/** - * D header file for POSIX. - * - * Copyright: Copyright Sean Kelly 2005 - 2009. - * License: Boost License 1.0. - * Authors: Sean Kelly - * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition - * - * Copyright Sean Kelly 2005 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module core.sys.posix.config; - -public import core.stdc.config; - -extern (C): - -version( linux ) -{ - version( X86_64 ) - { - enum bool __USE_LARGEFILE64 = true; - } - else - { - enum bool __USE_LARGEFILE64 = false; - } - enum bool __USE_FILE_OFFSET64 = __USE_LARGEFILE64; - enum bool __REDIRECT = false; -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/import/core/sys/posix/dirent.d --- a/druntime/import/core/sys/posix/dirent.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,203 +0,0 @@ -/** - * D header file for POSIX. - * - * Copyright: Copyright Sean Kelly 2005 - 2009. - * License: Boost License 1.0. - * Authors: Sean Kelly - * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition - * - * Copyright Sean Kelly 2005 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module core.sys.posix.dlfcn; - -private import core.sys.posix.config; - -extern (C): - -// -// XOpen (XSI) -// -/* -RTLD_LAZY -RTLD_NOW -RTLD_GLOBAL -RTLD_LOCAL - -int dlclose(void*); -char* dlerror(); -void* dlopen(in char*, int); -void* dlsym(void*, in char*); -*/ - -version( linux ) -{ - enum RTLD_LAZY = 0x00001; - enum RTLD_NOW = 0x00002; - enum RTLD_GLOBAL = 0x00100; - enum RTLD_LOCAL = 0x00000; - - int dlclose(void*); - char* dlerror(); - void* dlopen(in char*, int); - void* dlsym(void*, in char*); -} -else version( OSX ) -{ - enum RTLD_LAZY = 0x00001; - enum RTLD_NOW = 0x00002; - enum RTLD_GLOBAL = 0x00100; - enum RTLD_LOCAL = 0x00000; - - int dlclose(void*); - char* dlerror(); - void* dlopen(in char*, int); - void* dlsym(void*, in char*); -} -else version( freebsd ) -{ - enum RTLD_LAZY = 1; - enum RTLD_NOW = 2; - enum RTLD_GLOBAL = 0x100; - enum RTLD_LOCAL = 0; - - int dlclose(void*); - char* dlerror(); - void* dlopen(in char*, int); - void* dlsym(void*, in char*); -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/import/core/sys/posix/fcntl.d --- a/druntime/import/core/sys/posix/fcntl.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,253 +0,0 @@ -/** - * D header file for POSIX. - * - * Copyright: Copyright Sean Kelly 2005 - 2009. - * License: Boost License 1.0. - * Authors: Sean Kelly - * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition - * - * Copyright Sean Kelly 2005 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module core.sys.posix.inttypes; - -private import core.sys.posix.config; -public import core.stdc.inttypes; - -// -// Required -// -/* -intmax_t imaxabs(intmax_t); -imaxdiv_t imaxdiv(intmax_t, intmax_t); -intmax_t strtoimax(in char*, char**, int); -uintmax_t strtoumax(in char *, char**, int); -intmax_t wcstoimax(in wchar_t*, wchar_t**, int); -uintmax_t wcstoumax(in wchar_t*, wchar_t**, int); -*/ -intmax_t imaxabs(intmax_t); -imaxdiv_t imaxdiv(intmax_t, intmax_t); -intmax_t strtoimax(in char*, char**, int); -uintmax_t strtoumax(in char *, char**, int); -intmax_t wcstoimax(in wchar_t*, wchar_t**, int); -uintmax_t wcstoumax(in wchar_t*, wchar_t**, int); diff -r b265fb6ce15b -r d28cd7c45267 druntime/import/core/sys/posix/net/if_.d --- a/druntime/import/core/sys/posix/net/if_.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ -/** - * D header file for POSIX. - * - * Copyright: Copyright Sean Kelly 2005 - 2009. - * License: Boost License 1.0. - * Authors: Sean Kelly - * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition - * - * Copyright Sean Kelly 2005 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module core.sys.posix.netinet.in_; - -private import core.sys.posix.config; -public import core.stdc.inttypes; // for uint32_t, uint16_t, uint8_t -public import core.sys.posix.arpa.inet; -public import core.sys.posix.sys.socket; // for sa_family_t - -extern (C): - -// -// Required -// -/* -NOTE: The following must must be defined in core.sys.posix.arpa.inet to break - a circular import: in_port_t, in_addr_t, struct in_addr, INET_ADDRSTRLEN. - -in_port_t -in_addr_t - -sa_family_t // from core.sys.posix.sys.socket -uint8_t // from core.stdc.inttypes -uint32_t // from core.stdc.inttypes - -struct in_addr -{ - in_addr_t s_addr; -} - -struct sockaddr_in -{ - sa_family_t sin_family; - in_port_t sin_port; - in_addr sin_addr; -} - -IPPROTO_IP -IPPROTO_ICMP -IPPROTO_TCP -IPPROTO_UDP - -INADDR_ANY -INADDR_BROADCAST - -INET_ADDRSTRLEN - -htonl() // from core.sys.posix.arpa.inet -htons() // from core.sys.posix.arpa.inet -ntohl() // from core.sys.posix.arpa.inet -ntohs() // from core.sys.posix.arpa.inet -*/ - -version( linux ) -{ - private enum __SOCK_SIZE__ = 16; - - struct sockaddr_in - { - sa_family_t sin_family; - in_port_t sin_port; - in_addr sin_addr; - - /* Pad to size of `struct sockaddr'. */ - ubyte[__SOCK_SIZE__ - sa_family_t.sizeof - - in_port_t.sizeof - in_addr.sizeof] __pad; - } - - enum - { - IPPROTO_IP = 0, - IPPROTO_ICMP = 1, - IPPROTO_TCP = 6, - IPPROTO_UDP = 17 - } - - enum uint INADDR_ANY = 0x00000000; - enum uint INADDR_BROADCAST = 0xffffffff; - - enum INET_ADDRSTRLEN = 16; -} -else version( OSX ) -{ - private enum __SOCK_SIZE__ = 16; - - struct sockaddr_in - { - ubyte sin_len; - sa_family_t sin_family; - in_port_t sin_port; - in_addr sin_addr; - ubyte[8] sin_zero; - } - - enum - { - IPPROTO_IP = 0, - IPPROTO_ICMP = 1, - IPPROTO_TCP = 6, - IPPROTO_UDP = 17 - } - - enum uint INADDR_ANY = 0x00000000; - enum uint INADDR_BROADCAST = 0xffffffff; - - enum INET_ADDRSTRLEN = 16; -} -else version( freebsd ) -{ - private enum __SOCK_SIZE__ = 16; - - struct sockaddr_in - { - ubyte sin_len; - sa_family_t sin_family; - in_port_t sin_port; - in_addr sin_addr; - ubyte[8] sin_zero; - } - - enum - { - IPPROTO_IP = 0, - IPPROTO_ICMP = 1, - IPPROTO_TCP = 6, - IPPROTO_UDP = 17 - } - - enum uint INADDR_ANY = 0x00000000; - enum uint INADDR_BROADCAST = 0xffffffff; -} - - -// -// IPV6 (IP6) -// -/* -NOTE: The following must must be defined in core.sys.posix.arpa.inet to break - a circular import: INET6_ADDRSTRLEN. - -struct in6_addr -{ - uint8_t[16] s6_addr; -} - -struct sockaddr_in6 -{ - sa_family_t sin6_family; - in_port_t sin6_port; - uint32_t sin6_flowinfo; - in6_addr sin6_addr; - uint32_t sin6_scope_id; -} - -extern in6_addr in6addr_any; -extern in6_addr in6addr_loopback; - -struct ipv6_mreq -{ - in6_addr ipv6mr_multiaddr; - uint ipv6mr_interface; -} - -IPPROTO_IPV6 - -INET6_ADDRSTRLEN - -IPV6_JOIN_GROUP -IPV6_LEAVE_GROUP -IPV6_MULTICAST_HOPS -IPV6_MULTICAST_IF -IPV6_MULTICAST_LOOP -IPV6_UNICAST_HOPS -IPV6_V6ONLY - -// macros -int IN6_IS_ADDR_UNSPECIFIED(in6_addr*) -int IN6_IS_ADDR_LOOPBACK(in6_addr*) -int IN6_IS_ADDR_MULTICAST(in6_addr*) -int IN6_IS_ADDR_LINKLOCAL(in6_addr*) -int IN6_IS_ADDR_SITELOCAL(in6_addr*) -int IN6_IS_ADDR_V4MAPPED(in6_addr*) -int IN6_IS_ADDR_V4COMPAT(in6_addr*) -int IN6_IS_ADDR_MC_NODELOCAL(in6_addr*) -int IN6_IS_ADDR_MC_LINKLOCAL(in6_addr*) -int IN6_IS_ADDR_MC_SITELOCAL(in6_addr*) -int IN6_IS_ADDR_MC_ORGLOCAL(in6_addr*) -int IN6_IS_ADDR_MC_GLOBAL(in6_addr*) -*/ - -version ( linux ) -{ - struct in6_addr - { - union - { - uint8_t[16] s6_addr; - uint16_t[8] s6_addr16; - uint32_t[4] s6_addr32; - } - } - - struct sockaddr_in6 - { - sa_family_t sin6_family; - in_port_t sin6_port; - uint32_t sin6_flowinfo; - in6_addr sin6_addr; - uint32_t sin6_scope_id; - } - - extern in6_addr in6addr_any; - extern in6_addr in6addr_loopback; - - struct ipv6_mreq - { - in6_addr ipv6mr_multiaddr; - uint ipv6mr_interface; - } - - enum : uint - { - IPPROTO_IPV6 = 41, - - INET6_ADDRSTRLEN = 46, - - IPV6_JOIN_GROUP = 20, - IPV6_LEAVE_GROUP = 21, - IPV6_MULTICAST_HOPS = 18, - IPV6_MULTICAST_IF = 17, - IPV6_MULTICAST_LOOP = 19, - IPV6_UNICAST_HOPS = 16, - IPV6_V6ONLY = 26 - } - - // macros - extern (D) int IN6_IS_ADDR_UNSPECIFIED( in6_addr* addr ) - { - return (cast(uint32_t*) addr)[0] == 0 && - (cast(uint32_t*) addr)[1] == 0 && - (cast(uint32_t*) addr)[2] == 0 && - (cast(uint32_t*) addr)[3] == 0; - } - - extern (D) int IN6_IS_ADDR_LOOPBACK( in6_addr* addr ) - { - return (cast(uint32_t*) addr)[0] == 0 && - (cast(uint32_t*) addr)[1] == 0 && - (cast(uint32_t*) addr)[2] == 0 && - (cast(uint32_t*) addr)[3] == htonl( 1 ); - } - - extern (D) int IN6_IS_ADDR_MULTICAST( in6_addr* addr ) - { - return (cast(uint8_t*) addr)[0] == 0xff; - } - - extern (D) int IN6_IS_ADDR_LINKLOCAL( in6_addr* addr ) - { - return ((cast(uint32_t*) addr)[0] & htonl( 0xffc00000 )) == htonl( 0xfe800000 ); - } - - extern (D) int IN6_IS_ADDR_SITELOCAL( in6_addr* addr ) - { - return ((cast(uint32_t*) addr)[0] & htonl( 0xffc00000 )) == htonl( 0xfec00000 ); - } - - extern (D) int IN6_IS_ADDR_V4MAPPED( in6_addr* addr ) - { - return (cast(uint32_t*) addr)[0] == 0 && - (cast(uint32_t*) addr)[1] == 0 && - (cast(uint32_t*) addr)[2] == htonl( 0xffff ); - } - - extern (D) int IN6_IS_ADDR_V4COMPAT( in6_addr* addr ) - { - return (cast(uint32_t*) addr)[0] == 0 && - (cast(uint32_t*) addr)[1] == 0 && - (cast(uint32_t*) addr)[2] == 0 && - ntohl( (cast(uint32_t*) addr)[3] ) > 1; - } - - extern (D) int IN6_IS_ADDR_MC_NODELOCAL( in6_addr* addr ) - { - return IN6_IS_ADDR_MULTICAST( addr ) && - ((cast(uint8_t*) addr)[1] & 0xf) == 0x1; - } - - extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( in6_addr* addr ) - { - return IN6_IS_ADDR_MULTICAST( addr ) && - ((cast(uint8_t*) addr)[1] & 0xf) == 0x2; - } - - extern (D) int IN6_IS_ADDR_MC_SITELOCAL( in6_addr* addr ) - { - return IN6_IS_ADDR_MULTICAST(addr) && - ((cast(uint8_t*) addr)[1] & 0xf) == 0x5; - } - - extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( in6_addr* addr ) - { - return IN6_IS_ADDR_MULTICAST( addr) && - ((cast(uint8_t*) addr)[1] & 0xf) == 0x8; - } - - extern (D) int IN6_IS_ADDR_MC_GLOBAL( in6_addr* addr ) - { - return IN6_IS_ADDR_MULTICAST( addr ) && - ((cast(uint8_t*) addr)[1] & 0xf) == 0xe; - } -} -else version( OSX ) -{ - struct in6_addr - { - union - { - uint8_t[16] s6_addr; - uint16_t[8] s6_addr16; - uint32_t[4] s6_addr32; - } - } - - struct sockaddr_in6 - { - uint8_t sin6_len; - sa_family_t sin6_family; - in_port_t sin6_port; - uint32_t sin6_flowinfo; - in6_addr sin6_addr; - uint32_t sin6_scope_id; - } - - extern in6_addr in6addr_any; - extern in6_addr in6addr_loopback; - - struct ipv6_mreq - { - in6_addr ipv6mr_multiaddr; - uint ipv6mr_interface; - } - - enum : uint - { - IPPROTO_IPV6 = 41, - - INET6_ADDRSTRLEN = 46, - - IPV6_JOIN_GROUP = 12, - IPV6_LEAVE_GROUP = 13, - IPV6_MULTICAST_HOPS = 10, - IPV6_MULTICAST_IF = 9, - IPV6_MULTICAST_LOOP = 11, - IPV6_UNICAST_HOPS = 4, - IPV6_V6ONLY = 27 - } - - // macros - extern (D) int IN6_IS_ADDR_UNSPECIFIED( in6_addr* addr ) - { - return (cast(uint32_t*) addr)[0] == 0 && - (cast(uint32_t*) addr)[1] == 0 && - (cast(uint32_t*) addr)[2] == 0 && - (cast(uint32_t*) addr)[3] == 0; - } - - extern (D) int IN6_IS_ADDR_LOOPBACK( in6_addr* addr ) - { - return (cast(uint32_t*) addr)[0] == 0 && - (cast(uint32_t*) addr)[1] == 0 && - (cast(uint32_t*) addr)[2] == 0 && - (cast(uint32_t*) addr)[3] == ntohl( 1 ); - } - - extern (D) int IN6_IS_ADDR_MULTICAST( in6_addr* addr ) - { - return addr.s6_addr[0] == 0xff; - } - - extern (D) int IN6_IS_ADDR_LINKLOCAL( in6_addr* addr ) - { - return addr.s6_addr[0] == 0xfe && (addr.s6_addr[1] & 0xc0) == 0x80; - } - - extern (D) int IN6_IS_ADDR_SITELOCAL( in6_addr* addr ) - { - return addr.s6_addr[0] == 0xfe && (addr.s6_addr[1] & 0xc0) == 0xc0; - } - - extern (D) int IN6_IS_ADDR_V4MAPPED( in6_addr* addr ) - { - return (cast(uint32_t*) addr)[0] == 0 && - (cast(uint32_t*) addr)[1] == 0 && - (cast(uint32_t*) addr)[2] == ntohl( 0x0000ffff ); - } - - extern (D) int IN6_IS_ADDR_V4COMPAT( in6_addr* addr ) - { - return (cast(uint32_t*) addr)[0] == 0 && - (cast(uint32_t*) addr)[1] == 0 && - (cast(uint32_t*) addr)[2] == 0 && - (cast(uint32_t*) addr)[3] != 0 && - (cast(uint32_t*) addr)[3] != ntohl( 1 ); - } - - extern (D) int IN6_IS_ADDR_MC_NODELOCAL( in6_addr* addr ) - { - return IN6_IS_ADDR_MULTICAST( addr ) && - ((cast(uint8_t*) addr)[1] & 0xf) == 0x1; - } - - extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( in6_addr* addr ) - { - return IN6_IS_ADDR_MULTICAST( addr ) && - ((cast(uint8_t*) addr)[1] & 0xf) == 0x2; - } - - extern (D) int IN6_IS_ADDR_MC_SITELOCAL( in6_addr* addr ) - { - return IN6_IS_ADDR_MULTICAST(addr) && - ((cast(uint8_t*) addr)[1] & 0xf) == 0x5; - } - - extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( in6_addr* addr ) - { - return IN6_IS_ADDR_MULTICAST( addr) && - ((cast(uint8_t*) addr)[1] & 0xf) == 0x8; - } - - extern (D) int IN6_IS_ADDR_MC_GLOBAL( in6_addr* addr ) - { - return IN6_IS_ADDR_MULTICAST( addr ) && - ((cast(uint8_t*) addr)[1] & 0xf) == 0xe; - } -} - - -// -// Raw Sockets (RS) -// -/* -IPPROTO_RAW -*/ - -version (linux ) -{ - enum uint IPPROTO_RAW = 255; -} -else version( OSX ) -{ - enum uint IPPROTO_RAW = 255; -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/import/core/sys/posix/netinet/tcp.d --- a/druntime/import/core/sys/posix/netinet/tcp.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -/** - * D header file for POSIX. - * - * Copyright: Copyright Sean Kelly 2005 - 2009. - * License: Boost License 1.0. - * Authors: Sean Kelly - * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition - * - * Copyright Sean Kelly 2005 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module core.sys.posix.poll; - -private import core.sys.posix.config; - -extern (C): - -// -// XOpen (XSI) -// -/* -struct pollfd -{ - int fd; - short events; - short revents; -} - -nfds_t - -POLLIN -POLLRDNORM -POLLRDBAND -POLLPRI -POLLOUT -POLLWRNORM -POLLWRBAND -POLLERR -POLLHUP -POLLNVAL - -int poll(pollfd[], nfds_t, int); -*/ - -version( linux ) -{ - struct pollfd - { - int fd; - short events; - short revents; - } - - alias c_ulong nfds_t; - - enum - { - POLLIN = 0x001, - POLLRDNORM = 0x040, - POLLRDBAND = 0x080, - POLLPRI = 0x002, - POLLOUT = 0x004, - POLLWRNORM = 0x100, - POLLWRBAND = 0x200, - POLLERR = 0x008, - POLLHUP = 0x010, - POLLNVAL = 0x020, - } - - int poll(pollfd*, nfds_t, int); -} -else version( OSX ) -{ - struct pollfd - { - int fd; - short events; - short revents; - }; - - alias uint nfds_t; - - enum - { - POLLIN = 0x0001, - POLLPRI = 0x0002, - POLLOUT = 0x0004, - POLLRDNORM = 0x0040, - POLLWRNORM = POLLOUT, - POLLRDBAND = 0x0080, - POLLWRBAND = 0x0100, - POLLEXTEND = 0x0200, - POLLATTRIB = 0x0400, - POLLNLINK = 0x0800, - POLLWRITE = 0x1000, - POLLERR = 0x0008, - POLLHUP = 0x0010, - POLLNVAL = 0x0020, - - POLLSTANDARD = (POLLIN|POLLPRI|POLLOUT|POLLRDNORM|POLLRDBAND| - POLLWRBAND|POLLERR|POLLHUP|POLLNVAL) - } - - int poll(pollfd*, nfds_t, int); -} -else version( freebsd ) -{ - struct pollfd - { - int fd; - short events; - short revents; - }; - - alias uint nfds_t; - - enum - { - POLLIN = 0x0001, - POLLPRI = 0x0002, - POLLOUT = 0x0004, - POLLRDNORM = 0x0040, - POLLWRNORM = POLLOUT, - POLLRDBAND = 0x0080, - POLLWRBAND = 0x0100, - //POLLEXTEND = 0x0200, - //POLLATTRIB = 0x0400, - //POLLNLINK = 0x0800, - //POLLWRITE = 0x1000, - POLLERR = 0x0008, - POLLHUP = 0x0010, - POLLNVAL = 0x0020, - - POLLSTANDARD = (POLLIN|POLLPRI|POLLOUT|POLLRDNORM|POLLRDBAND| - POLLWRBAND|POLLERR|POLLHUP|POLLNVAL) - } - - int poll(pollfd*, nfds_t, int); -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/import/core/sys/posix/pthread.d --- a/druntime/import/core/sys/posix/pthread.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,585 +0,0 @@ -/** - * D header file for POSIX. - * - * Copyright: Copyright Sean Kelly 2005 - 2009. - * License: Boost License 1.0. - * Authors: Sean Kelly - * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition - * - * Copyright Sean Kelly 2005 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module core.sys.posix.sched; - -private import core.sys.posix.config; -public import core.sys.posix.time; -public import core.sys.posix.sys.types; - -extern (C): - -// -// Required -// -/* -struct sched_param -{ - int sched_priority (THR) - int sched_ss_low_priority (SS|TSP) - struct timespec sched_ss_repl_period (SS|TSP) - struct timespec sched_ss_init_budget (SS|TSP) - int sched_ss_max_repl (SS|TSP) -} - -SCHED_FIFO -SCHED_RR -SCHED_SPORADIC (SS|TSP) -SCHED_OTHER - -int sched_getparam(pid_t, sched_param*); -int sched_getscheduler(pid_t); -int sched_setparam(pid_t, in sched_param*); -int sched_setscheduler(pid_t, int, in sched_param*); -*/ - -version( linux ) -{ - struct sched_param - { - int sched_priority; - } - - enum SCHED_OTHER = 0; - enum SCHED_FIFO = 1; - enum SCHED_RR = 2; - //SCHED_SPORADIC (SS|TSP) -} -else version( OSX ) -{ - enum SCHED_OTHER = 1; - enum SCHED_FIFO = 4; - enum SCHED_RR = 2; - //SCHED_SPORADIC (SS|TSP) - - private enum __SCHED_PARAM_SIZE__ = 4; - - struct sched_param - { - int sched_priority; - byte[__PTHREAD_MUTEX_SIZE__] __opaque; - } -} -else version( freebsd ) -{ - struct sched_param - { - int sched_priority; - } - - enum SCHED_FIFO = 1; - enum SCHED_OTHER = 2; - enum SCHED_RR = 3; - //SCHED_SPORADIC (SS|TSP) -} - -int sched_getparam(pid_t, sched_param*); -int sched_getscheduler(pid_t); -int sched_setparam(pid_t, in sched_param*); -int sched_setscheduler(pid_t, int, in sched_param*); - -// -// Thread (THR) -// -/* -int sched_yield(); -*/ - -version( linux ) -{ - int sched_yield(); -} -else version( OSX ) -{ - int sched_yield(); -} -else version( freebsd ) -{ - int sched_yield(); -} - -// -// Scheduling (TPS) -// -/* -int sched_get_priority_max(int); -int sched_get_priority_min(int); -int sched_rr_get_interval(pid_t, timespec*); -*/ - -version( linux ) -{ - int sched_get_priority_max(int); - int sched_get_priority_min(int); - int sched_rr_get_interval(pid_t, timespec*); -} -else version( OSX ) -{ - int sched_get_priority_min(int); - int sched_get_priority_max(int); - //int sched_rr_get_interval(pid_t, timespec*); // FIXME: unavailable? -} -else version( freebsd ) -{ - int sched_get_priority_min(int); - int sched_get_priority_max(int); - int sched_rr_get_interval(pid_t, timespec*); -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/import/core/sys/posix/semaphore.d --- a/druntime/import/core/sys/posix/semaphore.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,102 +0,0 @@ -/** - * D header file for POSIX. - * - * Copyright: Copyright Sean Kelly 2005 - 2009. - * License: Boost License 1.0. - * Authors: Sean Kelly - * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition - * - * Copyright Sean Kelly 2005 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module core.sys.posix.setjmp; - -private import core.sys.posix.config; -private import core.sys.posix.signal; // for sigset_t - -extern (C): - -// -// Required -// -/* -jmp_buf - -int setjmp(jmp_buf); -void longjmp(jmp_buf, int); -*/ - -version( linux ) -{ - version( X86_64 ) - { - //enum JB_BX = 0; - //enum JB_BP = 1; - //enum JB_12 = 2; - //enum JB_13 = 3; - //enum JB_14 = 4; - //enum JB_15 = 5; - //enum JB_SP = 6; - //enum JB_PC = 7; - //enum JB_SIZE = 64; - - alias long[8] __jmp_buf; - } - else version( X86 ) - { - //enum JB_BX = 0; - //enum JB_SI = 1; - //enum JB_DI = 2; - //enum JB_BP = 3; - //enum JB_SP = 4; - //enum JB_PC = 5; - //enum JB_SIZE = 24; - - alias int[6] __jmp_buf; - } - else version ( SPARC ) - { - alias int[3] __jmp_buf; - } - - struct __jmp_buf_tag - { - __jmp_buf __jmpbuf; - int __mask_was_saved; - sigset_t __saved_mask; - } - - alias __jmp_buf_tag[1] jmp_buf; - - alias _setjmp setjmp; // see XOpen block - void longjmp(jmp_buf, int); -} - -// -// C Extension (CX) -// -/* -sigjmp_buf - -int sigsetjmp(sigjmp_buf, int); -void siglongjmp(sigjmp_buf, int); -*/ - -version( linux ) -{ - alias jmp_buf sigjmp_buf; - - int __sigsetjmp(sigjmp_buf, int); - alias __sigsetjmp sigsetjmp; - void siglongjmp(sigjmp_buf, int); -} - -// -// XOpen (XSI) -// -/* -int _setjmp(jmp_buf); -void _longjmp(jmp_buf, int); -*/ - -version( linux ) -{ - int _setjmp(jmp_buf); - void _longjmp(jmp_buf, int); -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/import/core/sys/posix/signal.d --- a/druntime/import/core/sys/posix/signal.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,843 +0,0 @@ -/** - * D header file for POSIX. - * - * Copyright: Copyright Sean Kelly 2005 - 2009. - * License: Boost License 1.0. - * Authors: Sean Kelly - * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition - * - * Copyright Sean Kelly 2005 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module core.sys.posix.stdio; - -private import core.sys.posix.config; -public import core.stdc.stdio; -public import core.sys.posix.sys.types; // for off_t - -extern (C): - -// -// Required (defined in core.stdc.stdio) -// -/* -BUFSIZ -_IOFBF -_IOLBF -_IONBF -L_tmpnam -SEEK_CUR -SEEK_END -SEEK_SET -FILENAME_MAX -FOPEN_MAX -TMP_MAX -EOF -NULL -stderr -stdin -stdout -FILE -fpos_t -size_t - -void clearerr(FILE*); -int fclose(FILE*); -int feof(FILE*); -int ferror(FILE*); -int fflush(FILE*); -int fgetc(FILE*); -int fgetpos(FILE*, fpos_t *); -char* fgets(char*, int, FILE*); -FILE* fopen(in char*, in char*); -int fprintf(FILE*, in char*, ...); -int fputc(int, FILE*); -int fputs(in char*, FILE*); -size_t fread(void *, size_t, size_t, FILE*); -FILE* freopen(in char*, in char*, FILE*); -int fscanf(FILE*, in char*, ...); -int fseek(FILE*, c_long, int); -int fsetpos(FILE*, in fpos_t*); -c_long ftell(FILE*); -size_t fwrite(in void *, size_t, size_t, FILE*); -int getc(FILE*); -int getchar(); -char* gets(char*); -void perror(in char*); -int printf(in char*, ...); -int putc(int, FILE*); -int putchar(int); -int puts(in char*); -int remove(in char*); -int rename(in char*, in char*); -void rewind(FILE*); -int scanf(in char*, ...); -void setbuf(FILE*, char*); -int setvbuf(FILE*, char*, int, size_t); -int snprintf(char*, size_t, in char*, ...); -int sprintf(char*, in char*, ...); -int sscanf(in char*, in char*, int ...); -FILE* tmpfile(); -char* tmpnam(char*); -int ungetc(int, FILE*); -int vfprintf(FILE*, in char*, va_list); -int vfscanf(FILE*, in char*, va_list); -int vprintf(in char*, va_list); -int vscanf(in char*, va_list); -int vsnprintf(char*, size_t, in char*, va_list); -int vsprintf(char*, in char*, va_list); -int vsscanf(in char*, in char*, va_list arg); -*/ - -version( linux ) -{ - static if( __USE_LARGEFILE64 ) - { - int fgetpos64(FILE*, fpos_t *); - alias fgetpos64 fgetpos; - - FILE* fopen64(in char*, in char*); - alias fopen64 fopen; - - FILE* freopen64(in char*, in char*, FILE*); - alias freopen64 freopen; - - int fseek64(FILE*, c_long, int); - alias fseek64 fseek; - - int fsetpos64(FILE*, in fpos_t*); - alias fsetpos64 fsetpos; - - FILE* tmpfile64(); - alias tmpfile64 tmpfile; - } - else - { - int fgetpos(FILE*, fpos_t *); - FILE* fopen(in char*, in char*); - FILE* freopen(in char*, in char*, FILE*); - int fseek(FILE*, c_long, int); - int fsetpos(FILE*, in fpos_t*); - FILE* tmpfile(); - } -} - -// -// C Extension (CX) -// -/* -L_ctermid - -char* ctermid(char*); -FILE* fdopen(int, in char*); -int fileno(FILE*); -int fseeko(FILE*, off_t, int); -off_t ftello(FILE*); -char* gets(char*); -FILE* popen(in char*, in char*); -*/ - -version( linux ) -{ - enum L_ctermid = 9; - - static if( __USE_FILE_OFFSET64 ) - { - int fseeko64(FILE*, off_t, int); - alias fseeko64 fseeko; - } - else - { - int fseeko(FILE*, off_t, int); - } - - static if( __USE_LARGEFILE64 ) - { - off_t ftello64(FILE*); - alias ftello64 ftello; - } - else - { - off_t ftello(FILE*); - } -} -else -{ - int fseeko(FILE*, off_t, int); - off_t ftello(FILE*); -} - -char* ctermid(char*); -FILE* fdopen(int, in char*); -int fileno(FILE*); -//int fseeko(FILE*, off_t, int); -//off_t ftello(FILE*); -char* gets(char*); -FILE* popen(in char*, in char*); - -// -// Thread-Safe Functions (TSF) -// -/* -void flockfile(FILE*); -int ftrylockfile(FILE*); -void funlockfile(FILE*); -int getc_unlocked(FILE*); -int getchar_unlocked(); -int putc_unlocked(int, FILE*); -int putchar_unlocked(int); -*/ - -version( linux ) -{ - void flockfile(FILE*); - int ftrylockfile(FILE*); - void funlockfile(FILE*); - int getc_unlocked(FILE*); - int getchar_unlocked(); - int putc_unlocked(int, FILE*); - int putchar_unlocked(int); -} - -// -// XOpen (XSI) -// -/* -P_tmpdir -va_list (defined in core.stdc.stdarg) - -char* tempnam(in char*, in char*); -*/ - -version( linux ) -{ - enum P_tmpdir = "/tmp"; - - char* tempnam(in char*, in char*); -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/import/core/sys/posix/stdlib.d --- a/druntime/import/core/sys/posix/stdlib.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,310 +0,0 @@ -/** - * D header file for POSIX. - * - * Copyright: Copyright Sean Kelly 2005 - 2009. - * License: Boost License 1.0. - * Authors: Sean Kelly - * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition - * - * Copyright Sean Kelly 2005 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module core.sys.posix.sys.ipc; - -private import core.sys.posix.config; -public import core.sys.posix.sys.types; // for uid_t, gid_t, mode_t, key_t - -extern (C): - -// -// XOpen (XSI) -// -/* -struct ipc_perm -{ - uid_t uid; - gid_t gid; - uid_t cuid; - gid_t cgid; - mode_t mode; -} - -IPC_CREAT -IPC_EXCL -IPC_NOWAIT - -IPC_PRIVATE - -IPC_RMID -IPC_SET -IPC_STAT - -key_t ftok(in char*, int); -*/ - -version( linux ) -{ - struct ipc_perm - { - key_t __key; - uid_t uid; - gid_t gid; - uid_t cuid; - gid_t cgid; - ushort mode; - ushort __pad1; - ushort __seq; - ushort __pad2; - c_ulong __unused1; - c_ulong __unused2; - } - - enum IPC_CREAT = 01000; - enum IPC_EXCL = 02000; - enum IPC_NOWAIT = 04000; - - enum key_t IPC_PRIVATE = 0; - - enum IPC_RMID = 0; - enum IPC_SET = 1; - enum IPC_STAT = 2; - - key_t ftok(in char*, int); -} -else version( OSX ) -{ - -} -else version( freebsd ) -{ - struct ipc_perm - { - ushort cuid; - ushort cguid; - ushort uid; - ushort gid; - ushort mode; - ushort seq; - key_t key; - } - - enum IPC_CREAT = 01000; - enum IPC_EXCL = 02000; - enum IPC_NOWAIT = 04000; - - enum key_t IPC_PRIVATE = 0; - - enum IPC_RMID = 0; - enum IPC_SET = 1; - enum IPC_STAT = 2; - - key_t ftok(in char*, int); -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/import/core/sys/posix/sys/mman.d --- a/druntime/import/core/sys/posix/sys/mman.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,313 +0,0 @@ -/** - * D header file for POSIX. - * - * Copyright: Copyright Sean Kelly 2005 - 2009. - * License: Boost License 1.0. - * Authors: Sean Kelly - * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition - * - * Copyright Sean Kelly 2005 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module core.sys.posix.sys.select; - -private import core.sys.posix.config; -public import core.stdc.time; // for timespec -public import core.sys.posix.sys.time; // for timeval -public import core.sys.posix.sys.types; // for time_t -public import core.sys.posix.signal; // for sigset_t - -extern (C): - -// -// Required -// -/* -NOTE: This module requires timeval from core.sys.posix.sys.time, but timeval - is supposedly an XOpen extension. As a result, this header will not - compile on platforms that are not XSI-compliant. This must be resolved - on a per-platform basis. - -fd_set - -void FD_CLR(int fd, fd_set* fdset); -int FD_ISSET(int fd, fd_set* fdset); -void FD_SET(int fd, fd_set* fdset); -void FD_ZERO(fd_set* fdset); - -FD_SETSIZE - -int pselect(int, fd_set*, fd_set*, fd_set*, in timespec*, in sigset_t*); -int select(int, fd_set*, fd_set*, fd_set*, timeval*); -*/ - -version( linux ) -{ - private - { - alias c_long __fd_mask; - enum __NFDBITS = 8 * __fd_mask.sizeof; - - extern (D) int __FDELT( int d ) - { - return d / __NFDBITS; - } - - extern (D) int __FDMASK( int d ) - { - return cast(__fd_mask) 1 << ( d % __NFDBITS ); - } - } - - enum FD_SETSIZE = 1024; - - struct fd_set - { - __fd_mask[FD_SETSIZE / __NFDBITS] fds_bits; - } - - extern (D) void FD_CLR( int fd, fd_set* fdset ) - { - fdset.fds_bits[__FDELT( fd )] &= ~__FDMASK( fd ); - } - - extern (D) int FD_ISSET( int fd, fd_set* fdset ) - { - return fdset.fds_bits[__FDELT( fd )] & __FDMASK( fd ); - } - - extern (D) void FD_SET( int fd, fd_set* fdset ) - { - fdset.fds_bits[__FDELT( fd )] |= __FDMASK( fd ); - } - - extern (D) void FD_ZERO( fd_set* fdset ) - { - fdset.fds_bits[0 .. $] = 0; - } - - /+ - + GNU ASM Implementation - + - # define __FD_ZERO(fdsp) \ - do { \ - int __d0, __d1; \ - __asm__ __volatile__ ("cld; rep; stosl" \ - : "=c" (__d0), "=D" (__d1) \ - : "a" (0), "0" (sizeof (fd_set) \ - / sizeof (__fd_mask)), \ - "1" (&__FDS_BITS (fdsp)[0]) \ - : "memory"); \ - } while (0) - - # define __FD_SET(fd, fdsp) \ - __asm__ __volatile__ ("btsl %1,%0" \ - : "=m" (__FDS_BITS (fdsp)[__FDELT (fd)]) \ - : "r" (((int) (fd)) % __NFDBITS) \ - : "cc","memory") - # define __FD_CLR(fd, fdsp) \ - __asm__ __volatile__ ("btrl %1,%0" \ - : "=m" (__FDS_BITS (fdsp)[__FDELT (fd)]) \ - : "r" (((int) (fd)) % __NFDBITS) \ - : "cc","memory") - # define __FD_ISSET(fd, fdsp) \ - (__extension__ \ - ({register char __result; \ - __asm__ __volatile__ ("btl %1,%2 ; setcb %b0" \ - : "=q" (__result) \ - : "r" (((int) (fd)) % __NFDBITS), \ - "m" (__FDS_BITS (fdsp)[__FDELT (fd)]) \ - : "cc"); \ - __result; })) - +/ - - int pselect(int, fd_set*, fd_set*, fd_set*, in timespec*, in sigset_t*); - int select(int, fd_set*, fd_set*, fd_set*, timeval*); -} -else version( OSX ) -{ - private - { - enum uint __DARWIN_NBBY = 8; /* bits in a byte */ - enum uint __DARWIN_NFDBITS = (int.sizeof * __DARWIN_NBBY); /* bits per mask */ - } - - enum FD_SETSIZE = 1024; - - struct fd_set - { - int[(FD_SETSIZE + (__DARWIN_NFDBITS - 1)) / __DARWIN_NFDBITS] fds_bits; - } - - extern (D) void FD_CLR( int fd, fd_set* fdset ) - { - fdset.fds_bits[fd / __DARWIN_NFDBITS] &= ~(1 << (fd % __DARWIN_NFDBITS)); - } - - extern (D) int FD_ISSET( int fd, fd_set* fdset ) - { - return fdset.fds_bits[fd / __DARWIN_NFDBITS] & (1 << (fd % __DARWIN_NFDBITS)); - } - - extern (D) void FD_SET( int fd, fd_set* fdset ) - { - fdset.fds_bits[fd / __DARWIN_NFDBITS] |= 1 << (fd % __DARWIN_NFDBITS); - } - - extern (D) void FD_ZERO( fd_set* fdset ) - { - fdset.fds_bits[0 .. $] = 0; - } - - int pselect(int, fd_set*, fd_set*, fd_set*, in timespec*, in sigset_t*); - int select(int, fd_set*, fd_set*, fd_set*, timeval*); -} -else version( freebsd ) -{ - private - { - enum uint _NFDBITS = c_ulong.sizeof * 8; - } - - enum uint FD_SETSIZE = 1024; - - struct fd_set - { - c_ulong fds_bits[(FD_SETSIZE + (_NFDBITS - 1)) / _NFDBITS]; - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/import/core/sys/posix/sys/shm.d --- a/druntime/import/core/sys/posix/sys/shm.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,116 +0,0 @@ -/** - * D header file for POSIX. - * - * Copyright: Copyright Sean Kelly 2005 - 2009. - * License: Boost License 1.0. - * Authors: Sean Kelly - * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition - * - * Copyright Sean Kelly 2005 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module core.sys.posix.sys.socket; - -private import core.sys.posix.config; -public import core.sys.posix.sys.types; // for ssize_t, size_t -public import core.sys.posix.sys.uio; // for iovec - -extern (C): - -// -// Required -// -/* -socklen_t -sa_family_t - -struct sockaddr -{ - sa_family_t sa_family; - char sa_data[]; -} - -struct sockaddr_storage -{ - sa_family_t ss_family; -} - -struct msghdr -{ - void* msg_name; - socklen_t msg_namelen; - struct iovec* msg_iov; - int msg_iovlen; - void* msg_control; - socklen_t msg_controllen; - int msg_flags; -} - -struct iovec {} // from core.sys.posix.sys.uio - -struct cmsghdr -{ - socklen_t cmsg_len; - int cmsg_level; - int cmsg_type; -} - -SCM_RIGHTS - -CMSG_DATA(cmsg) -CMSG_NXTHDR(mhdr,cmsg) -CMSG_FIRSTHDR(mhdr) - -struct linger -{ - int l_onoff; - int l_linger; -} - -SOCK_DGRAM -SOCK_SEQPACKET -SOCK_STREAM - -SOL_SOCKET - -SO_ACCEPTCONN -SO_BROADCAST -SO_DEBUG -SO_DONTROUTE -SO_ERROR -SO_KEEPALIVE -SO_LINGER -SO_OOBINLINE -SO_RCVBUF -SO_RCVLOWAT -SO_RCVTIMEO -SO_REUSEADDR -SO_SNDBUF -SO_SNDLOWAT -SO_SNDTIMEO -SO_TYPE - -SOMAXCONN - -MSG_CTRUNC -MSG_DONTROUTE -MSG_EOR -MSG_OOB -MSG_PEEK -MSG_TRUNC -MSG_WAITALL - -AF_INET -AF_UNIX -AF_UNSPEC - -SHUT_RD -SHUT_RDWR -SHUT_WR - -int accept(int, sockaddr*, socklen_t*); -int bind(int, in sockaddr*, socklen_t); -int connect(int, in sockaddr*, socklen_t); -int getpeername(int, sockaddr*, socklen_t*); -int getsockname(int, sockaddr*, socklen_t*); -int getsockopt(int, int, int, void*, socklen_t*); -int listen(int, int); -ssize_t recv(int, void*, size_t, int); -ssize_t recvfrom(int, void*, size_t, int, sockaddr*, socklen_t*); -ssize_t recvmsg(int, msghdr*, int); -ssize_t send(int, in void*, size_t, int); -ssize_t sendmsg(int, in msghdr*, int); -ssize_t sendto(int, in void*, size_t, int, in sockaddr*, socklen_t); -int setsockopt(int, int, int, in void*, socklen_t); -int shutdown(int, int); -int socket(int, int, int); -int sockatmark(int); -int socketpair(int, int, int, int[2]); -*/ - -version( linux ) -{ - alias uint socklen_t; - alias ushort sa_family_t; - - struct sockaddr - { - sa_family_t sa_family; - byte[14] sa_data; - } - - private enum : size_t - { - _SS_SIZE = 128, - _SS_PADSIZE = _SS_SIZE - (c_ulong.sizeof * 2) - } - - struct sockaddr_storage - { - sa_family_t ss_family; - c_ulong __ss_align; - byte[_SS_PADSIZE] __ss_padding; - } - - struct msghdr - { - void* msg_name; - socklen_t msg_namelen; - iovec* msg_iov; - size_t msg_iovlen; - void* msg_control; - size_t msg_controllen; - int msg_flags; - } - - struct cmsghdr - { - size_t cmsg_len; - int cmsg_level; - int cmsg_type; - static if( false /* (!is( __STRICT_ANSI__ ) && __GNUC__ >= 2) || __STDC_VERSION__ >= 199901L */ ) - { - ubyte[1] __cmsg_data; - } - } - - enum : uint - { - SCM_RIGHTS = 0x01 - } - - static if( false /* (!is( __STRICT_ANSI__ ) && __GNUC__ >= 2) || __STDC_VERSION__ >= 199901L */ ) - { - extern (D) ubyte[1] CMSG_DATA( cmsghdr* cmsg ) { return cmsg.__cmsg_data; } - } - else - { - extern (D) ubyte* CMSG_DATA( cmsghdr* cmsg ) { return cast(ubyte*)( cmsg + 1 ); } - } - - private cmsghdr* __cmsg_nxthdr(msghdr*, cmsghdr*); - alias __cmsg_nxthdr CMSG_NXTHDR; - - extern (D) size_t CMSG_FIRSTHDR( msghdr* mhdr ) - { - return cast(size_t)( mhdr.msg_controllen >= cmsghdr.sizeof - ? cast(cmsghdr*) mhdr.msg_control - : cast(cmsghdr*) null ); - } - - struct linger - { - int l_onoff; - int l_linger; - } - - enum - { - SOCK_DGRAM = 2, - SOCK_SEQPACKET = 5, - SOCK_STREAM = 1 - } - - enum - { - SOL_SOCKET = 1 - } - - enum - { - SO_ACCEPTCONN = 30, - SO_BROADCAST = 6, - SO_DEBUG = 1, - SO_DONTROUTE = 5, - SO_ERROR = 4, - SO_KEEPALIVE = 9, - SO_LINGER = 13, - SO_OOBINLINE = 10, - SO_RCVBUF = 8, - SO_RCVLOWAT = 18, - SO_RCVTIMEO = 20, - SO_REUSEADDR = 2, - SO_SNDBUF = 7, - SO_SNDLOWAT = 19, - SO_SNDTIMEO = 21, - SO_TYPE = 3 - } - - enum - { - SOMAXCONN = 128 - } - - enum : uint - { - MSG_CTRUNC = 0x08, - MSG_DONTROUTE = 0x04, - MSG_EOR = 0x80, - MSG_OOB = 0x01, - MSG_PEEK = 0x02, - MSG_TRUNC = 0x20, - MSG_WAITALL = 0x100 - } - - enum - { - AF_INET = 2, - AF_UNIX = 1, - AF_UNSPEC = 0 - } - - enum - { - SHUT_RD, - SHUT_WR, - SHUT_RDWR - } - - int accept(int, sockaddr*, socklen_t*); - int bind(int, in sockaddr*, socklen_t); - int connect(int, in sockaddr*, socklen_t); - int getpeername(int, sockaddr*, socklen_t*); - int getsockname(int, sockaddr*, socklen_t*); - int getsockopt(int, int, int, void*, socklen_t*); - int listen(int, int); - ssize_t recv(int, void*, size_t, int); - ssize_t recvfrom(int, void*, size_t, int, sockaddr*, socklen_t*); - ssize_t recvmsg(int, msghdr*, int); - ssize_t send(int, in void*, size_t, int); - ssize_t sendmsg(int, in msghdr*, int); - ssize_t sendto(int, in void*, size_t, int, in sockaddr*, socklen_t); - int setsockopt(int, int, int, in void*, socklen_t); - int shutdown(int, int); - int socket(int, int, int); - int sockatmark(int); - int socketpair(int, int, int, int[2]); -} -else version( OSX ) -{ - alias uint socklen_t; - alias ubyte sa_family_t; - - struct sockaddr - { - ubyte sa_len; - sa_family_t sa_family; - byte[14] sa_data; - } - - private enum : size_t - { - _SS_PAD1 = long.sizeof - ubyte.sizeof - sa_family_t.sizeof, - _SS_PAD2 = 128 - ubyte.sizeof - sa_family_t.sizeof - _SS_PAD1 - long.sizeof - } - - struct sockaddr_storage - { - ubyte ss_len; - sa_family_t ss_family; - byte[_SS_PAD1] __ss_pad1; - long __ss_align; - byte[_SS_PAD2] __ss_pad2; - } - - struct msghdr - { - void* msg_name; - socklen_t msg_namelen; - iovec* msg_iov; - int msg_iovlen; - void* msg_control; - socklen_t msg_controllen; - int msg_flags; - } - - struct cmsghdr - { - socklen_t cmsg_len; - int cmsg_level; - int cmsg_type; - } - - enum : uint - { - SCM_RIGHTS = 0x01 - } - - /+ - CMSG_DATA(cmsg) ((unsigned char *)(cmsg) + \ - ALIGN(sizeof(struct cmsghdr))) - CMSG_NXTHDR(mhdr, cmsg) \ - (((unsigned char *)(cmsg) + ALIGN((cmsg)->cmsg_len) + \ - ALIGN(sizeof(struct cmsghdr)) > \ - (unsigned char *)(mhdr)->msg_control +(mhdr)->msg_controllen) ? \ - (struct cmsghdr *)0 /* NULL */ : \ - (struct cmsghdr *)((unsigned char *)(cmsg) + ALIGN((cmsg)->cmsg_len))) - CMSG_FIRSTHDR(mhdr) ((struct cmsghdr *)(mhdr)->msg_control) - +/ - - struct linger - { - int l_onoff; - int l_linger; - } - - enum - { - SOCK_DGRAM = 2, - SOCK_SEQPACKET = 5, - SOCK_STREAM = 1 - } - - enum : uint - { - SOL_SOCKET = 0xffff - } - - enum : uint - { - SO_ACCEPTCONN = 0x0002, - SO_BROADCAST = 0x0020, - SO_DEBUG = 0x0001, - SO_DONTROUTE = 0x0010, - SO_ERROR = 0x1007, - SO_KEEPALIVE = 0x0008, - SO_LINGER = 0x1080, - SO_OOBINLINE = 0x0100, - SO_RCVBUF = 0x1002, - SO_RCVLOWAT = 0x1004, - SO_RCVTIMEO = 0x1006, - SO_REUSEADDR = 0x0004, - SO_SNDBUF = 0x1001, - SO_SNDLOWAT = 0x1003, - SO_SNDTIMEO = 0x1005, - SO_TYPE = 0x1008 - } - - enum - { - SOMAXCONN = 128 - } - - enum : uint - { - MSG_CTRUNC = 0x20, - MSG_DONTROUTE = 0x4, - MSG_EOR = 0x8, - MSG_OOB = 0x1, - MSG_PEEK = 0x2, - MSG_TRUNC = 0x10, - MSG_WAITALL = 0x40 - } - - enum - { - AF_INET = 2, - AF_UNIX = 1, - AF_UNSPEC = 0 - } - - enum - { - SHUT_RD, - SHUT_WR, - SHUT_RDWR - } - - int accept(int, sockaddr*, socklen_t*); - int bind(int, in sockaddr*, socklen_t); - int connect(int, in sockaddr*, socklen_t); - int getpeername(int, sockaddr*, socklen_t*); - int getsockname(int, sockaddr*, socklen_t*); - int getsockopt(int, int, int, void*, socklen_t*); - int listen(int, int); - ssize_t recv(int, void*, size_t, int); - ssize_t recvfrom(int, void*, size_t, int, sockaddr*, socklen_t*); - ssize_t recvmsg(int, msghdr*, int); - ssize_t send(int, in void*, size_t, int); - ssize_t sendmsg(int, in msghdr*, int); - ssize_t sendto(int, in void*, size_t, int, in sockaddr*, socklen_t); - int setsockopt(int, int, int, in void*, socklen_t); - int shutdown(int, int); - int socket(int, int, int); - int sockatmark(int); - int socketpair(int, int, int, int[2]); -} -else version( freebsd ) -{ - alias uint socklen_t; - alias ubyte sa_family_t; - - struct sockaddr - { - ubyte sa_len; - sa_family_t sa_family; - byte[14] sa_data; - } - - private - { - enum _SS_ALIGNSIZE = long.sizeof; - enum _SS_MAXSIZE = 128; - enum _SS_PAD1SIZE = _SS_ALIGNSIZE - ubyte.sizeof - sa_family_t.sizeof; - enum _SS_PAD2SIZE = _SS_MAXSIZE - ubyte.sizeof - sa_family_t.sizeof - _SS_PAD1SIZE - _SS_ALIGNSIZE; - } - - struct sockaddr_storage - { - ubyte ss_len; - sa_family_t ss_family; - byte[_SS_PAD1SIZE] __ss_pad1; - long __ss_align; - byte[_SS_PAD2SIZE] __ss_pad2; - } - - struct msghdr - { - void* msg_name; - socklen_t msg_namelen; - iovec* msg_iov; - int msg_iovlen; - void* msg_control; - socklen_t msg_controllen; - int msg_flags; - } - - struct cmsghdr - { - socklen_t cmsg_len; - int cmsg_level; - int cmsg_type; - } - - enum : uint - { - SCM_RIGHTS = 0x01 - } - - /+ - CMSG_DATA(cmsg) ((unsigned char *)(cmsg) + \ - ALIGN(sizeof(struct cmsghdr))) - CMSG_NXTHDR(mhdr, cmsg) \ - (((unsigned char *)(cmsg) + ALIGN((cmsg)->cmsg_len) + \ - ALIGN(sizeof(struct cmsghdr)) > \ - (unsigned char *)(mhdr)->msg_control +(mhdr)->msg_controllen) ? \ - (struct cmsghdr *)0 /* NULL */ : \ - (struct cmsghdr *)((unsigned char *)(cmsg) + ALIGN((cmsg)->cmsg_len))) - CMSG_FIRSTHDR(mhdr) ((struct cmsghdr *)(mhdr)->msg_control) - +/ - - struct linger - { - int l_onoff; - int l_linger; - } - - enum - { - SOCK_DGRAM = 2, - SOCK_SEQPACKET = 5, - SOCK_STREAM = 1 - } - - enum : uint - { - SOL_SOCKET = 0xffff - } - - enum : uint - { - SO_ACCEPTCONN = 0x0002, - SO_BROADCAST = 0x0020, - SO_DEBUG = 0x0001, - SO_DONTROUTE = 0x0010, - SO_ERROR = 0x1007, - SO_KEEPALIVE = 0x0008, - SO_LINGER = 0x1080, - SO_OOBINLINE = 0x0100, - SO_RCVBUF = 0x1002, - SO_RCVLOWAT = 0x1004, - SO_RCVTIMEO = 0x1006, - SO_REUSEADDR = 0x0004, - SO_SNDBUF = 0x1001, - SO_SNDLOWAT = 0x1003, - SO_SNDTIMEO = 0x1005, - SO_TYPE = 0x1008 - } - - enum - { - SOMAXCONN = 128 - } - - enum : uint - { - MSG_CTRUNC = 0x20, - MSG_DONTROUTE = 0x4, - MSG_EOR = 0x8, - MSG_OOB = 0x1, - MSG_PEEK = 0x2, - MSG_TRUNC = 0x10, - MSG_WAITALL = 0x40 - } - - enum - { - AF_INET = 2, - AF_UNIX = 1, - AF_UNSPEC = 0 - } - - enum - { - SHUT_RD = 0, - SHUT_WR = 1, - SHUT_RDWR = 2 - } - - int accept(int, sockaddr*, socklen_t*); - int bind(int, in sockaddr*, socklen_t); - int connect(int, in sockaddr*, socklen_t); - int getpeername(int, sockaddr*, socklen_t*); - int getsockname(int, sockaddr*, socklen_t*); - int getsockopt(int, int, int, void*, socklen_t*); - int listen(int, int); - ssize_t recv(int, void*, size_t, int); - ssize_t recvfrom(int, void*, size_t, int, sockaddr*, socklen_t*); - ssize_t recvmsg(int, msghdr*, int); - ssize_t send(int, in void*, size_t, int); - ssize_t sendmsg(int, in msghdr*, int); - ssize_t sendto(int, in void*, size_t, int, in sockaddr*, socklen_t); - int setsockopt(int, int, int, in void*, socklen_t); - int shutdown(int, int); - int socket(int, int, int); - int sockatmark(int); - int socketpair(int, int, int, int[2]); -} - -// -// IPV6 (IP6) -// -/* -AF_INET6 -*/ - -version( linux ) -{ - enum - { - AF_INET6 = 10 - } -} -else version( OSX ) -{ - enum - { - AF_INET6 = 30 - } -} -else version( freebsd ) -{ - enum - { - AF_INET6 = 28 - } -} - -// -// Raw Sockets (RS) -// -/* -SOCK_RAW -*/ - -version( linux ) -{ - enum - { - SOCK_RAW = 3 - } -} -else version( OSX ) -{ - enum - { - SOCK_RAW = 3 - } -} -else version( freebsd ) -{ - enum - { - SOCK_RAW = 3 - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/import/core/sys/posix/sys/stat.d --- a/druntime/import/core/sys/posix/sys/stat.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,425 +0,0 @@ -/** - * D header file for POSIX. - * - * Copyright: Copyright Sean Kelly 2005 - 2009. - * License: Boost License 1.0. - * Authors: Sean Kelly - * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition - * - * Copyright Sean Kelly 2005 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module core.sys.posix.sys.time; - -private import core.sys.posix.config; -public import core.sys.posix.sys.types; // for time_t, suseconds_t -public import core.sys.posix.sys.select; // for fd_set, FD_CLR() FD_ISSET() FD_SET() FD_ZERO() FD_SETSIZE, select() - -extern (C): - -// -// XOpen (XSI) -// -/* -struct timeval -{ - time_t tv_sec; - suseconds_t tv_usec; -} - -struct itimerval -{ - timeval it_interval; - timeval it_value; -} - -ITIMER_REAL -ITIMER_VIRTUAL -ITIMER_PROF - -int getitimer(int, itimerval*); -int gettimeofday(timeval*, void*); -int select(int, fd_set*, fd_set*, fd_set*, timeval*); (defined in core.sys.posix.sys.signal) -int setitimer(int, in itimerval*, itimerval*); -int utimes(in char*, in timeval[2]); // LEGACY -*/ - -version( linux ) -{ - struct timeval - { - time_t tv_sec; - suseconds_t tv_usec; - } - - struct itimerval - { - timeval it_interval; - timeval it_value; - } - - enum ITIMER_REAL = 0; - enum ITIMER_VIRTUAL = 1; - enum ITIMER_PROF = 2; - - int getitimer(int, itimerval*); - int gettimeofday(timeval*, void*); - int setitimer(int, in itimerval*, itimerval*); - int utimes(in char*, in timeval[2]); // LEGACY -} -else version( OSX ) -{ - struct timeval - { - time_t tv_sec; - suseconds_t tv_usec; - } - - struct itimerval - { - timeval it_interval; - timeval it_value; - } - - // non-standard - struct timezone_t - { - int tz_minuteswest; - int tz_dsttime; - } - - int getitimer(int, itimerval*); - int gettimeofday(timeval*, timezone_t*); // timezone_t* is normally void* - int setitimer(int, in itimerval*, itimerval*); - int utimes(in char*, in timeval[2]); -} -else version( freebsd ) -{ - struct timeval - { - time_t tv_sec; - suseconds_t tv_usec; - } - - struct itimerval - { - timeval it_interval; - timeval it_value; - } - - // non-standard - struct timezone_t - { - int tz_minuteswest; - int tz_dsttime; - } - - int getitimer(int, itimerval*); - int gettimeofday(timeval*, timezone_t*); // timezone_t* is normally void* - int setitimer(int, in itimerval*, itimerval*); - int utimes(in char*, in timeval[2]); -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/import/core/sys/posix/sys/types.d --- a/druntime/import/core/sys/posix/sys/types.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,429 +0,0 @@ -/** - * D header file for POSIX. - * - * Copyright: Copyright Sean Kelly 2005 - 2009. - * License: Boost License 1.0. - * Authors: Sean Kelly - * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition - * - * Copyright Sean Kelly 2005 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module core.sys.posix.sys.uio; - -private import core.sys.posix.config; -public import core.sys.posix.sys.types; // for ssize_t, size_t - -extern (C): - -// -// Required -// -/* -struct iovec -{ - void* iov_base; - size_t iov_len; -} - -ssize_t // from core.sys.posix.sys.types -size_t // from core.sys.posix.sys.types - -ssize_t readv(int, in iovec*, int); -ssize_t writev(int, in iovec*, int); -*/ - -version( linux ) -{ - struct iovec - { - void* iov_base; - size_t iov_len; - } - - ssize_t readv(int, in iovec*, int); - ssize_t writev(int, in iovec*, int); -} -else version( OSX ) -{ - struct iovec - { - void* iov_base; - size_t iov_len; - } - - ssize_t readv(int, in iovec*, int); - ssize_t writev(int, in iovec*, int); -} -else version( freebsd ) -{ - struct iovec - { - void* iov_base; - size_t iov_len; - } - - ssize_t readv(int, in iovec*, int); - ssize_t writev(int, in iovec*, int); -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/import/core/sys/posix/sys/wait.d --- a/druntime/import/core/sys/posix/sys/wait.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,141 +0,0 @@ -/** - * D header file for POSIX. - * - * Copyright: Copyright Sean Kelly 2005 - 2009. - * License: Boost License 1.0. - * Authors: Sean Kelly - * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition - * - * Copyright Sean Kelly 2005 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module core.sys.posix.termios; - -private import core.sys.posix.config; -public import core.sys.posix.sys.types; // for pid_t - -extern (C): - -// -// Required -// -/* -cc_t -speed_t -tcflag_t - -NCCS - -struct termios -{ - tcflag_t c_iflag; - tcflag_t c_oflag; - tcflag_t c_cflag; - tcflag_t c_lflag; - cc_t[NCCS] c_cc; -} - -VEOF -VEOL -VERASE -VINTR -VKILL -VMIN -VQUIT -VSTART -VSTOP -VSUSP -VTIME - -BRKINT -ICRNL -IGNBRK -IGNCR -IGNPAR -INLCR -INPCK -ISTRIP -IXOFF -IXON -PARMRK - -OPOST - -B0 -B50 -B75 -B110 -B134 -B150 -B200 -B300 -B600 -B1200 -B1800 -B2400 -B4800 -B9600 -B19200 -B38400 - -CSIZE - CS5 - CS6 - CS7 - CS8 -CSTOPB -CREAD -PARENB -PARODD -HUPCL -CLOCAL - -ECHO -ECHOE -ECHOK -ECHONL -ICANON -IEXTEN -ISIG -NOFLSH -TOSTOP - -TCSANOW -TCSADRAIN -TCSAFLUSH - -TCIFLUSH -TCIOFLUSH -TCOFLUSH - -TCIOFF -TCION -TCOOFF -TCOON - -speed_t cfgetispeed(in termios*); -speed_t cfgetospeed(in termios*); -int cfsetispeed(termios*, speed_t); -int cfsetospeed(termios*, speed_t); -int tcdrain(int); -int tcflow(int, int); -int tcflush(int, int); -int tcgetattr(int, termios*); -int tcsendbreak(int, int); -int tcsetattr(int, int, in termios*); -*/ - -version( OSX ) -{ - alias ubyte cc_t; - alias uint speed_t; - alias uint tcflag_t; - - enum NCCS = 20; - - struct termios - { - tcflag_t c_iflag; - tcflag_t c_oflag; - tcflag_t c_cflag; - tcflag_t c_lflag; - cc_t[NCCS] c_cc; - speed_t c_ispeed; - speed_t c_ospeed; - } - - enum VEOF = 0; - enum VEOL = 1; - enum VERASE = 3; - enum VINTR = 8; - enum VKILL = 5; - enum VMIN = 16; - enum VQUIT = 9; - enum VSTART = 12; - enum VSTOP = 13; - enum VSUSP = 10; - enum VTIME = 17; - - enum BRKINT = 0x0000002; - enum ICRNL = 0x0000100; - enum IGNBRK = 0x0000001; - enum IGNCR = 0x0000080; - enum IGNPAR = 0x0000004; - enum INLCR = 0x0000040; - enum INPCK = 0x0000010; - enum ISTRIP = 0x0000020; - enum IXOFF = 0x0000400; - enum IXON = 0x0000200; - enum PARMRK = 0x0000008; - - enum OPOST = 0x0000001; - - enum B0 = 0; - enum B50 = 50; - enum B75 = 75; - enum B110 = 110; - enum B134 = 134; - enum B150 = 150; - enum B200 = 200; - enum B300 = 300; - enum B600 = 600; - enum B1200 = 1200; - enum B1800 = 1800; - enum B2400 = 2400; - enum B4800 = 4800; - enum B9600 = 9600; - enum B19200 = 19200; - enum B38400 = 38400; - - enum CSIZE = 0x0000300; - enum CS5 = 0x0000000; - enum CS6 = 0x0000100; - enum CS7 = 0x0000200; - enum CS8 = 0x0000300; - enum CSTOPB = 0x0000400; - enum CREAD = 0x0000800; - enum PARENB = 0x0001000; - enum PARODD = 0x0002000; - enum HUPCL = 0x0004000; - enum CLOCAL = 0x0008000; - - enum ECHO = 0x00000008; - enum ECHOE = 0x00000002; - enum ECHOK = 0x00000004; - enum ECHONL = 0x00000010; - enum ICANON = 0x00000100; - enum IEXTEN = 0x00000400; - enum ISIG = 0x00000080; - enum NOFLSH = 0x80000000; - enum TOSTOP = 0x00400000; - - enum TCSANOW = 0; - enum TCSADRAIN = 1; - enum TCSAFLUSH = 2; - - enum TCIFLUSH = 1; - enum TCOFLUSH = 2; - enum TCIOFLUSH = 3; - - enum TCIOFF = 3; - enum TCION = 4; - enum TCOOFF = 1; - enum TCOON = 2; - - speed_t cfgetispeed(in termios*); - speed_t cfgetospeed(in termios*); - int cfsetispeed(termios*, speed_t); - int cfsetospeed(termios*, speed_t); - int tcdrain(int); - int tcflow(int, int); - int tcflush(int, int); - int tcgetattr(int, termios*); - int tcsendbreak(int, int); - int tcsetattr(int, int, in termios*); - -} -else version( linux ) -{ - alias ubyte cc_t; - alias uint speed_t; - alias uint tcflag_t; - - enum NCCS = 32; - - struct termios - { - tcflag_t c_iflag; - tcflag_t c_oflag; - tcflag_t c_cflag; - tcflag_t c_lflag; - cc_t c_line; - cc_t[NCCS] c_cc; - speed_t c_ispeed; - speed_t c_ospeed; - } - - enum VEOF = 4; - enum VEOL = 11; - enum VERASE = 2; - enum VINTR = 0; - enum VKILL = 3; - enum VMIN = 6; - enum VQUIT = 1; - enum VSTART = 8; - enum VSTOP = 9; - enum VSUSP = 10; - enum VTIME = 5; - - enum BRKINT = 0000002; - enum ICRNL = 0000400; - enum IGNBRK = 0000001; - enum IGNCR = 0000200; - enum IGNPAR = 0000004; - enum INLCR = 0000100; - enum INPCK = 0000020; - enum ISTRIP = 0000040; - enum IXOFF = 0010000; - enum IXON = 0002000; - enum PARMRK = 0000010; - - enum OPOST = 0000001; - - enum B0 = 0000000; - enum B50 = 0000001; - enum B75 = 0000002; - enum B110 = 0000003; - enum B134 = 0000004; - enum B150 = 0000005; - enum B200 = 0000006; - enum B300 = 0000007; - enum B600 = 0000010; - enum B1200 = 0000011; - enum B1800 = 0000012; - enum B2400 = 0000013; - enum B4800 = 0000014; - enum B9600 = 0000015; - enum B19200 = 0000016; - enum B38400 = 0000017; - - enum CSIZE = 0000060; - enum CS5 = 0000000; - enum CS6 = 0000020; - enum CS7 = 0000040; - enum CS8 = 0000060; - enum CSTOPB = 0000100; - enum CREAD = 0000200; - enum PARENB = 0000400; - enum PARODD = 0001000; - enum HUPCL = 0002000; - enum CLOCAL = 0004000; - - enum ECHO = 0000010; - enum ECHOE = 0000020; - enum ECHOK = 0000040; - enum ECHONL = 0000100; - enum ICANON = 0000002; - enum IEXTEN = 0100000; - enum ISIG = 0000001; - enum NOFLSH = 0000200; - enum TOSTOP = 0000400; - - enum TCSANOW = 0; - enum TCSADRAIN = 1; - enum TCSAFLUSH = 2; - - enum TCIFLUSH = 0; - enum TCOFLUSH = 1; - enum TCIOFLUSH = 2; - - enum TCIOFF = 2; - enum TCION = 3; - enum TCOOFF = 0; - enum TCOON = 1; - - speed_t cfgetispeed(in termios*); - speed_t cfgetospeed(in termios*); - int cfsetispeed(termios*, speed_t); - int cfsetospeed(termios*, speed_t); - int tcdrain(int); - int tcflow(int, int); - int tcflush(int, int); - int tcgetattr(int, termios*); - int tcsendbreak(int, int); - int tcsetattr(int, int, in termios*); -} -else version ( freebsd ) -{ - alias ubyte cc_t; - alias uint speed_t; - alias uint tcflag_t; - - enum NCCS = 20; - - struct termios - { - tcflag_t c_iflag; - tcflag_t c_oflag; - tcflag_t c_cflag; - tcflag_t c_lflag; - cc_t[NCCS] c_cc; - speed_t c_ispeed; - speed_t c_ospeed; - } - - enum VEOF = 0; - enum VEOL = 1; - enum VERASE = 3; - enum VINTR = 8; - enum VKILL = 5; - enum VMIN = 16; - enum VQUIT = 9; - enum VSTART = 12; - enum VSTOP = 13; - enum VSUSP = 10; - enum VTIME = 17; - - enum BRKINT = 0x0000002; - enum ICRNL = 0x0000100; - enum IGNBRK = 0x0000001; - enum IGNCR = 0x0000080; - enum IGNPAR = 0x0000004; - enum INLCR = 0x0000040; - enum INPCK = 0x0000010; - enum ISTRIP = 0x0000020; - enum IXOFF = 0x0000400; - enum IXON = 0x0000200; - enum PARMRK = 0x0000008; - - enum OPOST = 0x0000001; - - enum B0 = 0; - enum B50 = 50; - enum B75 = 75; - enum B110 = 110; - enum B134 = 134; - enum B150 = 150; - enum B200 = 200; - enum B300 = 300; - enum B600 = 600; - enum B1200 = 1200; - enum B1800 = 1800; - enum B2400 = 2400; - enum B4800 = 4800; - enum B9600 = 9600; - enum B19200 = 19200; - enum B38400 = 38400; - - enum CSIZE = 0x0000300; - enum CS5 = 0x0000000; - enum CS6 = 0x0000100; - enum CS7 = 0x0000200; - enum CS8 = 0x0000300; - enum CSTOPB = 0x0000400; - enum CREAD = 0x0000800; - enum PARENB = 0x0001000; - enum PARODD = 0x0002000; - enum HUPCL = 0x0004000; - enum CLOCAL = 0x0008000; - - enum ECHO = 0x00000008; - enum ECHOE = 0x00000002; - enum ECHOK = 0x00000004; - enum ECHONL = 0x00000010; - enum ICANON = 0x00000100; - enum IEXTEN = 0x00000400; - enum ISIG = 0x00000080; - enum NOFLSH = 0x80000000; - enum TOSTOP = 0x00400000; - - enum TCSANOW = 0; - enum TCSADRAIN = 1; - enum TCSAFLUSH = 2; - - enum TCIFLUSH = 1; - enum TCOFLUSH = 2; - enum TCIOFLUSH = 3; - - enum TCIOFF = 3; - enum TCION = 4; - enum TCOOFF = 1; - enum TCOON = 2; - - speed_t cfgetispeed(in termios*); - speed_t cfgetospeed(in termios*); - int cfsetispeed(termios*, speed_t); - int cfsetospeed(termios*, speed_t); - int tcdrain(int); - int tcflow(int, int); - int tcflush(int, int); - int tcgetattr(int, termios*); - int tcsendbreak(int, int); - int tcsetattr(int, int, in termios*); - -} - -// -// XOpen (XSI) -// -/* -IXANY - -ONLCR -OCRNL -ONOCR -ONLRET -OFILL -NLDLY - NL0 - NL1 -CRDLY - CR0 - CR1 - CR2 - CR3 -TABDLY - TAB0 - TAB1 - TAB2 - TAB3 -BSDLY - BS0 - BS1 -VTDLY - VT0 - VT1 -FFDLY - FF0 - FF1 - -pid_t tcgetsid(int); -*/ - -version( linux ) -{ - enum IXANY = 0004000; - - enum ONLCR = 0000004; - enum OCRNL = 0000010; - enum ONOCR = 0000020; - enum ONLRET = 0000040; - enum OFILL = 0000100; - enum NLDLY = 0000400; - enum NL0 = 0000000; - enum NL1 = 0000400; - enum CRDLY = 0003000; - enum CR0 = 0000000; - enum CR1 = 0001000; - enum CR2 = 0002000; - enum CR3 = 0003000; - enum TABDLY = 0014000; - enum TAB0 = 0000000; - enum TAB1 = 0004000; - enum TAB2 = 0010000; - enum TAB3 = 0014000; - enum BSDLY = 0020000; - enum BS0 = 0000000; - enum BS1 = 0020000; - enum VTDLY = 0040000; - enum VT0 = 0000000; - enum VT1 = 0040000; - enum FFDLY = 0100000; - enum FF0 = 0000000; - enum FF1 = 0100000; - - pid_t tcgetsid(int); -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/import/core/sys/posix/time.d --- a/druntime/import/core/sys/posix/time.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,270 +0,0 @@ -/** - * D header file for POSIX. - * - * Copyright: Copyright Sean Kelly 2005 - 2009. - * License: Boost License 1.0. - * Authors: Sean Kelly - * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition - * - * Copyright Sean Kelly 2005 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module core.sys.posix.ucontext; - -private import core.sys.posix.config; -public import core.sys.posix.signal; // for sigset_t, stack_t - -extern (C): - -// -// XOpen (XSI) -// -/* -mcontext_t - -struct ucontext_t -{ - ucontext_t* uc_link; - sigset_t uc_sigmask; - stack_t uc_stack; - mcontext_t uc_mcontext; -} -*/ - -version( linux ) -{ - - version( X86_64 ) - { - private - { - struct _libc_fpxreg - { - ushort[4] significand; - ushort exponent; - ushort[3] padding; - } - - struct _libc_xmmreg - { - uint[4] element; - } - - struct _libc_fpstate - { - ushort cwd; - ushort swd; - ushort ftw; - ushort fop; - ulong rip; - ulong rdp; - uint mxcsr; - uint mxcr_mask; - _libc_fpxreg[8] _st; - _libc_xmmreg[16] _xmm; - uint[24] padding; - } - - enum NGREG = 23; - - alias c_long greg_t; - alias greg_t[NGREG] gregset_t; - alias _libc_fpstate* fpregset_t; - } - - struct mcontext_t - { - gregset_t gregs; - fpregset_t fpregs; - c_ulong[8] __reserved1; - } - - struct ucontext_t - { - c_ulong uc_flags; - ucontext_t* uc_link; - stack_t uc_stack; - mcontext_t uc_mcontext; - sigset_t uc_sigmask; - _libc_fpstate __fpregs_mem; - } - } - else version( X86 ) - { - private - { - struct _libc_fpreg - { - ushort[4] significand; - ushort exponent; - } - - struct _libc_fpstate - { - c_ulong cw; - c_ulong sw; - c_ulong tag; - c_ulong ipoff; - c_ulong cssel; - c_ulong dataoff; - c_ulong datasel; - _libc_fpreg[8] _st; - c_ulong status; - } - - enum NGREG = 19; - - alias int greg_t; - alias greg_t[NGREG] gregset_t; - alias _libc_fpstate* fpregset_t; - } - - struct mcontext_t - { - gregset_t gregs; - fpregset_t fpregs; - c_ulong oldmask; - c_ulong cr2; - } - - struct ucontext_t - { - c_ulong uc_flags; - ucontext_t* uc_link; - stack_t uc_stack; - mcontext_t uc_mcontext; - sigset_t uc_sigmask; - _libc_fpstate __fpregs_mem; - } - } -} - -// -// Obsolescent (OB) -// -/* -int getcontext(ucontext_t*); -void makecontext(ucontext_t*, void function(), int, ...); -int setcontext(in ucontext_t*); -int swapcontext(ucontext_t*, in ucontext_t*); -*/ - -static if( is( ucontext_t ) ) -{ - int getcontext(ucontext_t*); - void makecontext(ucontext_t*, void function(), int, ...); - int setcontext(in ucontext_t*); - int swapcontext(ucontext_t*, in ucontext_t*); -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/import/core/sys/posix/unistd.d --- a/druntime/import/core/sys/posix/unistd.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,599 +0,0 @@ -/** - * D header file for POSIX. - * - * Copyright: Copyright Sean Kelly 2005 - 2009. - * License: Boost License 1.0. - * Authors: Sean Kelly - * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition - * - * Copyright Sean Kelly 2005 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module core.sys.posix.utime; - -private import core.sys.posix.config; -public import core.sys.posix.sys.types; // for time_t - -extern (C): - -// -// Required -// -/* -struct utimbuf -{ - time_t actime; - time_t modtime; -} - -int utime(in char*, in utimbuf*); -*/ - -version( linux ) -{ - struct utimbuf - { - time_t actime; - time_t modtime; - } - - int utime(in char*, in utimbuf*); -} -else version( OSX ) -{ - struct utimbuf - { - time_t actime; - time_t modtime; - } - - int utime(in char*, in utimbuf*); -} -else version( freebsd ) -{ - struct utimbuf - { - time_t actime; - time_t modtime; - } - - int utime(in char*, in utimbuf*); -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/import/core/sys/windows/windows.d --- a/druntime/import/core/sys/windows/windows.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3181 +0,0 @@ -/** - * Windows is a registered trademark of Microsoft Corporation in the United - * States and other countries. - * - * Copyright: Copyright Digital Mars 2000 - 2009. - * License: - * bsr(x21) = 5 - */ -pure nothrow int bsr( uint v ); - - -/** - * Tests the bit. - */ -pure nothrow int bt( in uint* p, uint bitnum ); - - -/** - * Tests and complements the bit. - */ -nothrow int btc( uint* p, uint bitnum ); - - -/** - * Tests and resets (sets to 0) the bit. - */ -nothrow int btr( uint* p, uint bitnum ); - - -/** - * Tests and sets the bit. - * Params: - * p = a non-NULL pointer to an array of uints. - * index = a bit number, starting with bit 0 of p[0], - * and progressing. It addresses bits like the expression: ---- -p[index / (uint.sizeof*8)] & (1 << (index & ((uint.sizeof*8) - 1))) ---- - * Returns: - * A non-zero value if the bit was set, and a zero - * if it was clear. - * - * Example: - * --- -import std.intrinsic; - -int main() -{ - uint array[2]; - - array[0] = 2; - array[1] = 0x100; - - printf("btc(array, 35) = %d\n", btc(array, 35)); - printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); - - printf("btc(array, 35) = %d\n", btc(array, 35)); - printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); - - printf("bts(array, 35) = %d\n", bts(array, 35)); - printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); - - printf("btr(array, 35) = %d\n", btr(array, 35)); - printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); - - printf("bt(array, 1) = %d\n", bt(array, 1)); - printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); - - return 0; -} - * --- - * Output: -
-btc(array, 35) = 0
-array = [0]:x2, [1]:x108
-btc(array, 35) = -1
-array = [0]:x2, [1]:x100
-bts(array, 35) = 0
-array = [0]:x2, [1]:x108
-btr(array, 35) = -1
-array = [0]:x2, [1]:x100
-bt(array, 1) = -1
-array = [0]:x2, [1]:x100
-
- */ -nothrow int bts( uint* p, uint bitnum ); - - -/** - * Swaps bytes in a 4 byte uint end-to-end, i.e. byte 0 becomes - * byte 3, byte 1 becomes byte 2, byte 2 becomes byte 1, byte 3 - * becomes byte 0. - */ -pure nothrow uint bswap( uint v ); - - -/** - * Reads I/O port at port_address. - */ -nothrow ubyte inp( uint port_address ); - - -/** - * ditto - */ -nothrow ushort inpw( uint port_address ); - - -/** - * ditto - */ -nothrow uint inpl( uint port_address ); - - -/** - * Writes and returns value to I/O port at port_address. - */ -nothrow ubyte outp( uint port_address, ubyte value ); - - -/** - * ditto - */ -nothrow ushort outpw( uint port_address, ushort value ); - - -/** - * ditto - */ -nothrow uint outpl( uint port_address, uint value ); diff -r b265fb6ce15b -r d28cd7c45267 druntime/import/std/stdarg.di --- a/druntime/import/std/stdarg.di Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -/** - * These functions are built-in intrinsics to the compiler. - * - * Copyright: Public Domain - * License: Public Domain - * Authors: David Friedman - */ -module std.stdarg; - -version( GNU ) -{ - private import gcc.builtins; - alias __builtin_va_list va_list; - alias __builtin_va_end va_end; - alias __builtin_va_copy va_copy; -} - -template va_start(T) -{ - void va_start( out va_list ap, inout T parmn ) - { - - } -} - -template va_arg(T) -{ - T va_arg( inout va_list ap ) - { - return T.init; - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/build-dmd.bat --- a/druntime/src/build-dmd.bat Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -@echo off -set OLDHOME=%HOME% -set HOME=%CD% -make clean all -fdmd-win32.mak -set HOME=%OLDHOME% \ No newline at end of file diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/build-dmd.sh --- a/druntime/src/build-dmd.sh Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -#!/usr/bin/env bash - -OLDHOME=$HOME -export HOME=`pwd` - -goerror(){ - export HOME=$OLDHOME - echo "=" - echo "= *** Error ***" - echo "=" - exit 1 -} - -make clean -fdmd-posix.mak || goerror -make -fdmd-posix.mak || goerror -chmod 644 ../import/core/*.di || goerror -chmod 644 ../import/core/sync/*.di || goerror - -export HOME=$OLDHOME diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/build-ldc.sh --- a/druntime/src/build-ldc.sh Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -#!/usr/bin/env bash - -OLDHOME=$HOME -export HOME=`pwd` - -goerror(){ - export HOME=$OLDHOME - echo "=" - echo "= *** Error ***" - echo "=" - exit 1 -} - -make clean -fldc-posix.mak || goerror -make -fldc-posix.mak || goerror -chmod 644 ../import/core/*.di || goerror -chmod 644 ../import/core/sync/*.di || goerror - -export HOME=$OLDHOME diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/common/core/bitmanip.d --- a/druntime/src/common/core/bitmanip.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,286 +0,0 @@ -/** - * This module contains a collection of bit-level operations. - * - * Copyright: Copyright (c) 2005-2008, The D Runtime Project - * License: BSD Style, see LICENSE - * Authors: Walter Bright, Don Clugston, Sean Kelly - */ -module core.bitmanip; - - -version( DDoc ) -{ - /** - * Scans the bits in v starting with bit 0, looking - * for the first set bit. - * Returns: - * The bit number of the first bit set. - * The return value is undefined if v is zero. - */ - int bsf( uint v ); - - - /** - * Scans the bits in v from the most significant bit - * to the least significant bit, looking - * for the first set bit. - * Returns: - * The bit number of the first bit set. - * The return value is undefined if v is zero. - * Example: - * --- - * import core.bitmanip; - * - * int main() - * { - * uint v; - * int x; - * - * v = 0x21; - * x = bsf(v); - * printf("bsf(x%x) = %d\n", v, x); - * x = bsr(v); - * printf("bsr(x%x) = %d\n", v, x); - * return 0; - * } - * --- - * Output: - * bsf(x21) = 0
- * bsr(x21) = 5 - */ - int bsr( uint v ); - - - /** - * Tests the bit. - */ - int bt( uint* p, uint bitnum ); - - - /** - * Tests and complements the bit. - */ - int btc( uint* p, uint bitnum ); - - - /** - * Tests and resets (sets to 0) the bit. - */ - int btr( uint* p, uint bitnum ); - - - /** - * Tests and sets the bit. - * Params: - * p = a non-NULL pointer to an array of uints. - * index = a bit number, starting with bit 0 of p[0], - * and progressing. It addresses bits like the expression: - --- - p[index / (uint.sizeof*8)] & (1 << (index & ((uint.sizeof*8) - 1))) - --- - * Returns: - * A non-zero value if the bit was set, and a zero - * if it was clear. - * - * Example: - * --- - import core.bitmanip; - - int main() - { - uint array[2]; - - array[0] = 2; - array[1] = 0x100; - - printf("btc(array, 35) = %d\n", btc(array, 35)); - printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); - - printf("btc(array, 35) = %d\n", btc(array, 35)); - printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); - - printf("bts(array, 35) = %d\n", bts(array, 35)); - printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); - - printf("btr(array, 35) = %d\n", btr(array, 35)); - printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); - - printf("bt(array, 1) = %d\n", bt(array, 1)); - printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); - - return 0; - } - * --- - * Output: -
-    btc(array, 35) = 0
-    array = [0]:x2, [1]:x108
-    btc(array, 35) = -1
-    array = [0]:x2, [1]:x100
-    bts(array, 35) = 0
-    array = [0]:x2, [1]:x108
-    btr(array, 35) = -1
-    array = [0]:x2, [1]:x100
-    bt(array, 1) = -1
-    array = [0]:x2, [1]:x100
-    
- */ - int bts( uint* p, uint bitnum ); - - - /** - * Swaps bytes in a 4 byte uint end-to-end, i.e. byte 0 becomes - * byte 3, byte 1 becomes byte 2, byte 2 becomes byte 1, byte 3 - * becomes byte 0. - */ - uint bswap( uint v ); - - - /** - * Reads I/O port at port_address. - */ - ubyte inp( uint port_address ); - - - /** - * ditto - */ - ushort inpw( uint port_address ); - - - /** - * ditto - */ - uint inpl( uint port_address ); - - - /** - * Writes and returns value to I/O port at port_address. - */ - ubyte outp( uint port_address, ubyte value ); - - - /** - * ditto - */ - ushort outpw( uint port_address, ushort value ); - - - /** - * ditto - */ - uint outpl( uint port_address, uint value ); -} -else -{ - public import std.intrinsic; -} - - -/** - * Calculates the number of set bits in a 32-bit integer. - */ -int popcnt( uint x ) -{ - // Avoid branches, and the potential for cache misses which - // could be incurred with a table lookup. - - // We need to mask alternate bits to prevent the - // sum from overflowing. - // add neighbouring bits. Each bit is 0 or 1. - x = x - ((x>>1) & 0x5555_5555); - // now each two bits of x is a number 00,01 or 10. - // now add neighbouring pairs - x = ((x&0xCCCC_CCCC)>>2) + (x&0x3333_3333); - // now each nibble holds 0000-0100. Adding them won't - // overflow any more, so we don't need to mask any more - - // Now add the nibbles, then the bytes, then the words - // We still need to mask to prevent double-counting. - // Note that if we used a rotate instead of a shift, we - // wouldn't need the masks, and could just divide the sum - // by 8 to account for the double-counting. - // On some CPUs, it may be faster to perform a multiply. - - x += (x>>4); - x &= 0x0F0F_0F0F; - x += (x>>8); - x &= 0x00FF_00FF; - x += (x>>16); - x &= 0xFFFF; - return x; -} - - -debug( UnitTest ) -{ - unittest - { - assert( popcnt( 0 ) == 0 ); - assert( popcnt( 7 ) == 3 ); - assert( popcnt( 0xAA )== 4 ); - assert( popcnt( 0x8421_1248 ) == 8 ); - assert( popcnt( 0xFFFF_FFFF ) == 32 ); - assert( popcnt( 0xCCCC_CCCC ) == 16 ); - assert( popcnt( 0x7777_7777 ) == 24 ); - } -} - - -/** - * Reverses the order of bits in a 32-bit integer. - */ -uint bitswap( uint x ) -{ - - version( D_InlineAsm_X86 ) - { - asm - { - // Author: Tiago Gasiba. - mov EDX, EAX; - shr EAX, 1; - and EDX, 0x5555_5555; - and EAX, 0x5555_5555; - shl EDX, 1; - or EAX, EDX; - mov EDX, EAX; - shr EAX, 2; - and EDX, 0x3333_3333; - and EAX, 0x3333_3333; - shl EDX, 2; - or EAX, EDX; - mov EDX, EAX; - shr EAX, 4; - and EDX, 0x0f0f_0f0f; - and EAX, 0x0f0f_0f0f; - shl EDX, 4; - or EAX, EDX; - bswap EAX; - } - } - else - { - // swap odd and even bits - x = ((x >> 1) & 0x5555_5555) | ((x & 0x5555_5555) << 1); - // swap consecutive pairs - x = ((x >> 2) & 0x3333_3333) | ((x & 0x3333_3333) << 2); - // swap nibbles - x = ((x >> 4) & 0x0F0F_0F0F) | ((x & 0x0F0F_0F0F) << 4); - // swap bytes - x = ((x >> 8) & 0x00FF_00FF) | ((x & 0x00FF_00FF) << 8); - // swap 2-byte long pairs - x = ( x >> 16 ) | ( x << 16); - return x; - - } -} - - -debug( UnitTest ) -{ - unittest - { - assert( bitswap( 0x8000_0100 ) == 0x0080_0001 ); - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/common/core/bitop.d --- a/druntime/src/common/core/bitop.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,290 +0,0 @@ -/** - * This module contains a collection of bit-level operations. - * - * Copyright: Copyright Don Clugston 2005 - 2009. - * License:
- * bsr(x21) = 5 - */ - int bsr( uint v ); - - - /** - * Tests the bit. - */ - int bt( uint* p, uint bitnum ); - - - /** - * Tests and complements the bit. - */ - int btc( uint* p, uint bitnum ); - - - /** - * Tests and resets (sets to 0) the bit. - */ - int btr( uint* p, uint bitnum ); - - - /** - * Tests and sets the bit. - * Params: - * p = a non-NULL pointer to an array of uints. - * index = a bit number, starting with bit 0 of p[0], - * and progressing. It addresses bits like the expression: - --- - p[index / (uint.sizeof*8)] & (1 << (index & ((uint.sizeof*8) - 1))) - --- - * Returns: - * A non-zero value if the bit was set, and a zero - * if it was clear. - * - * Example: - * --- - import core.bitop; - - int main() - { - uint array[2]; - - array[0] = 2; - array[1] = 0x100; - - printf("btc(array, 35) = %d\n", btc(array, 35)); - printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); - - printf("btc(array, 35) = %d\n", btc(array, 35)); - printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); - - printf("bts(array, 35) = %d\n", bts(array, 35)); - printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); - - printf("btr(array, 35) = %d\n", btr(array, 35)); - printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); - - printf("bt(array, 1) = %d\n", bt(array, 1)); - printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); - - return 0; - } - * --- - * Output: -
-    btc(array, 35) = 0
-    array = [0]:x2, [1]:x108
-    btc(array, 35) = -1
-    array = [0]:x2, [1]:x100
-    bts(array, 35) = 0
-    array = [0]:x2, [1]:x108
-    btr(array, 35) = -1
-    array = [0]:x2, [1]:x100
-    bt(array, 1) = -1
-    array = [0]:x2, [1]:x100
-    
- */ - int bts( uint* p, uint bitnum ); - - - /** - * Swaps bytes in a 4 byte uint end-to-end, i.e. byte 0 becomes - * byte 3, byte 1 becomes byte 2, byte 2 becomes byte 1, byte 3 - * becomes byte 0. - */ - uint bswap( uint v ); - - - /** - * Reads I/O port at port_address. - */ - ubyte inp( uint port_address ); - - - /** - * ditto - */ - ushort inpw( uint port_address ); - - - /** - * ditto - */ - uint inpl( uint port_address ); - - - /** - * Writes and returns value to I/O port at port_address. - */ - ubyte outp( uint port_address, ubyte value ); - - - /** - * ditto - */ - ushort outpw( uint port_address, ushort value ); - - - /** - * ditto - */ - uint outpl( uint port_address, uint value ); -} -else -{ - public import std.intrinsic; -} - - -/** - * Calculates the number of set bits in a 32-bit integer. - */ -int popcnt( uint x ) -{ - // Avoid branches, and the potential for cache misses which - // could be incurred with a table lookup. - - // We need to mask alternate bits to prevent the - // sum from overflowing. - // add neighbouring bits. Each bit is 0 or 1. - x = x - ((x>>1) & 0x5555_5555); - // now each two bits of x is a number 00,01 or 10. - // now add neighbouring pairs - x = ((x&0xCCCC_CCCC)>>2) + (x&0x3333_3333); - // now each nibble holds 0000-0100. Adding them won't - // overflow any more, so we don't need to mask any more - - // Now add the nibbles, then the bytes, then the words - // We still need to mask to prevent double-counting. - // Note that if we used a rotate instead of a shift, we - // wouldn't need the masks, and could just divide the sum - // by 8 to account for the double-counting. - // On some CPUs, it may be faster to perform a multiply. - - x += (x>>4); - x &= 0x0F0F_0F0F; - x += (x>>8); - x &= 0x00FF_00FF; - x += (x>>16); - x &= 0xFFFF; - return x; -} - - -debug( UnitTest ) -{ - unittest - { - assert( popcnt( 0 ) == 0 ); - assert( popcnt( 7 ) == 3 ); - assert( popcnt( 0xAA )== 4 ); - assert( popcnt( 0x8421_1248 ) == 8 ); - assert( popcnt( 0xFFFF_FFFF ) == 32 ); - assert( popcnt( 0xCCCC_CCCC ) == 16 ); - assert( popcnt( 0x7777_7777 ) == 24 ); - } -} - - -/** - * Reverses the order of bits in a 32-bit integer. - */ -uint bitswap( uint x ) -{ - - version( D_InlineAsm_X86 ) - { - asm - { - // Author: Tiago Gasiba. - mov EDX, EAX; - shr EAX, 1; - and EDX, 0x5555_5555; - and EAX, 0x5555_5555; - shl EDX, 1; - or EAX, EDX; - mov EDX, EAX; - shr EAX, 2; - and EDX, 0x3333_3333; - and EAX, 0x3333_3333; - shl EDX, 2; - or EAX, EDX; - mov EDX, EAX; - shr EAX, 4; - and EDX, 0x0f0f_0f0f; - and EAX, 0x0f0f_0f0f; - shl EDX, 4; - or EAX, EDX; - bswap EAX; - } - } - else - { - // swap odd and even bits - x = ((x >> 1) & 0x5555_5555) | ((x & 0x5555_5555) << 1); - // swap consecutive pairs - x = ((x >> 2) & 0x3333_3333) | ((x & 0x3333_3333) << 2); - // swap nibbles - x = ((x >> 4) & 0x0F0F_0F0F) | ((x & 0x0F0F_0F0F) << 4); - // swap bytes - x = ((x >> 8) & 0x00FF_00FF) | ((x & 0x00FF_00FF) << 8); - // swap 2-byte long pairs - x = ( x >> 16 ) | ( x << 16); - return x; - - } -} - - -debug( UnitTest ) -{ - unittest - { - assert( bitswap( 0x8000_0100 ) == 0x0080_0001 ); - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/common/core/exception.d --- a/druntime/src/common/core/exception.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,279 +0,0 @@ -/** - * The exception module defines all system-level exceptions and provides a - * mechanism to alter system-level error handling. - * - * Copyright: Copyright Sean Kelly 2005 - 2009. - * License:
. - * Authors: Sean Kelly - * - * Copyright Sean Kelly 2005 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module core.runtime; - - -private -{ - extern (C) bool rt_isHalting(); - - alias bool function() ModuleUnitTester; - alias bool function(Object) CollectHandler; - alias Exception.TraceInfo function( void* ptr = null ) TraceHandler; - - extern (C) void rt_setCollectHandler( CollectHandler h ); - extern (C) void rt_setTraceHandler( TraceHandler h ); - - alias void delegate( Throwable ) ExceptionHandler; - extern (C) bool rt_init( ExceptionHandler dg = null ); - extern (C) bool rt_term( ExceptionHandler dg = null ); - - extern (C) void* rt_loadLibrary( in char[] name ); - extern (C) bool rt_unloadLibrary( void* ptr ); -} - - -/////////////////////////////////////////////////////////////////////////////// -// Runtime -/////////////////////////////////////////////////////////////////////////////// - - -/** - * This struct encapsulates all functionality related to the underlying runtime - * module for the calling context. - */ -struct Runtime -{ - /** - * Initializes the runtime. This call is to be used in instances where the - * standard program initialization process is not executed. This is most - * often in shared libraries or in libraries linked to a C program. - * - * Params: - * dg = A delegate which will receive any exception thrown during the - * initialization process or null if such exceptions should be - * discarded. - * - * Returns: - * true if initialization succeeds and false if initialization fails. - */ - static bool initialize( ExceptionHandler dg = null ) - { - return rt_init( dg ); - } - - - /** - * Terminates the runtime. This call is to be used in instances where the - * standard program termination process will not be not executed. This is - * most often in shared libraries or in libraries linked to a C program. - * - * Params: - * dg = A delegate which will receive any exception thrown during the - * termination process or null if such exceptions should be - * discarded. - * - * Returns: - * true if termination succeeds and false if termination fails. - */ - static bool terminate( ExceptionHandler dg = null ) - { - return rt_term( dg ); - } - - - /** - * Returns true if the runtime is halting. Under normal circumstances, - * this will be set between the time that normal application code has - * exited and before module dtors are called. - * - * Returns: - * true if the runtime is halting. - */ - static bool isHalting() - { - return rt_isHalting(); - } - - - /** - * Locates a dynamic library with the supplied library name and dynamically - * loads it into the caller's address space. If the library contains a D - * runtime it will be integrated with the current runtime. - * - * Params: - * name = The name of the dynamic library to load. - * - * Returns: - * A reference to the library or null on error. - */ - static void* loadLibrary( in char[] name ) - { - return rt_loadLibrary( name ); - } - - - /** - * Unloads the dynamic library referenced by p. If this library contains a - * D runtime then any necessary finalization or cleanup of that runtime - * will be performed. - * - * Params: - * p = A reference to the library to unload. - */ - static bool unloadLibrary( void* p ) - { - return rt_unloadLibrary( p ); - } - - - /** - * Overrides the default trace mechanism with s user-supplied version. A - * trace represents the context from which an exception was thrown, and the - * trace handler will be called when this occurs. The pointer supplied to - * this routine indicates the base address from which tracing should occur. - * If the supplied pointer is null then the trace routine should determine - * an appropriate calling context from which to begin the trace. - * - * Params: - * h = The new trace handler. Set to null to use the default handler. - */ - static void traceHandler( TraceHandler h ) - { - rt_setTraceHandler( h ); - } - - - /** - * Overrides the default collect hander with a user-supplied version. This - * routine will be called for each resource object that is finalized in a - * non-deterministic manner--typically during a garbage collection cycle. - * If the supplied routine returns true then the object's dtor will called - * as normal, but if the routine returns false than the dtor will not be - * called. The default behavior is for all object dtors to be called. - * - * Params: - * h = The new collect handler. Set to null to use the default handler. - */ - static void collectHandler( CollectHandler h ) - { - rt_setCollectHandler( h ); - } - - - /** - * Overrides the default module unit tester with a user-supplied version. - * This routine will be called once on program initialization. The return - * value of this routine indicates to the runtime whether the body of the - * program will be executed. - * - * Params: - * h = The new unit tester. Set to null to use the default unit tester. - */ - static void moduleUnitTester( ModuleUnitTester h ) - { - sm_moduleUnitTester = h; - } - - -private: - // Unit tests should only be run in single-threaded - __gshared ModuleUnitTester sm_moduleUnitTester = null; -} - - -/////////////////////////////////////////////////////////////////////////////// -// Overridable Callbacks -/////////////////////////////////////////////////////////////////////////////// - - -/** - * This routine is called by the runtime to run module unit tests on startup. - * The user-supplied unit tester will be called if one has been supplied, - * otherwise all unit tests will be run in sequence. - * - * Returns: - * true if execution should continue after testing is complete and false if - * not. Default behavior is to return true. - */ -extern (C) bool runModuleUnitTests() -{ - if( Runtime.sm_moduleUnitTester is null ) - { - foreach( m; ModuleInfo ) - { - if( m.unitTest ) - m.unitTest(); - } - return true; - } - return Runtime.sm_moduleUnitTester(); -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/common/core/stdc/errno.c --- a/druntime/src/common/core/stdc/errno.c Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -/** - * This file contains wrapper functions for macro-defined C rouines. - * - * Copyright: Copyright Sean Kelly 2005 - 2009. - * License: Boost License 1.0. - * Authors: Sean Kelly - * - * Copyright Sean Kelly 2005 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module core.sync.barrier; - - -public import core.sync.exception; -private import core.sync.condition; -private import core.sync.mutex; - -version( Win32 ) -{ - private import core.sys.windows.windows; -} -else version( Posix ) -{ - private import core.stdc.errno; - private import core.sys.posix.pthread; -} - - -//////////////////////////////////////////////////////////////////////////////// -// Barrier -// -// void wait(); -//////////////////////////////////////////////////////////////////////////////// - - -/** - * This class represents a barrier across which threads may only travel in - * groups of a specific size. - */ -class Barrier -{ - //////////////////////////////////////////////////////////////////////////// - // Initialization - //////////////////////////////////////////////////////////////////////////// - - - /** - * Initializes a barrier object which releases threads in groups of limit - * in size. - * - * Params: - * limit = The number of waiting threads to release in unison. - * - * Throws: - * SyncException on error. - */ - this( uint limit ) - in - { - assert( limit > 0 ); - } - body - { - m_lock = new Mutex; - m_cond = new Condition( m_lock ); - m_group = 0; - m_limit = limit; - m_count = limit; - } - - - //////////////////////////////////////////////////////////////////////////// - // General Actions - //////////////////////////////////////////////////////////////////////////// - - - /** - * Wait for the pre-determined number of threads and then proceed. - * - * Throws: - * SyncException on error. - */ - void wait() - { - synchronized( m_lock ) - { - uint group = m_group; - - if( --m_count == 0 ) - { - m_group++; - m_count = m_limit; - m_cond.notifyAll(); - } - while( group == m_group ) - m_cond.wait(); - } - } - - -private: - Mutex m_lock; - Condition m_cond; - uint m_group; - uint m_limit; - uint m_count; -} - - -//////////////////////////////////////////////////////////////////////////////// -// Unit Tests -//////////////////////////////////////////////////////////////////////////////// - - -version( unittest ) -{ - private import core.thread; - - - unittest - { - int numThreads = 10; - auto barrier = new Barrier( numThreads ); - auto synInfo = new Object; - int numReady = 0; - int numPassed = 0; - - void threadFn() - { - synchronized( synInfo ) - { - ++numReady; - } - barrier.wait(); - synchronized( synInfo ) - { - ++numPassed; - } - } - - auto group = new ThreadGroup; - - for( int i = 0; i < numThreads; ++i ) - { - group.create( &threadFn ); - } - group.joinAll(); - assert( numReady == numThreads && numPassed == numThreads ); - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/common/core/sync/condition.d --- a/druntime/src/common/core/sync/condition.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,573 +0,0 @@ -/** - * The condition module provides a primitive for synchronized condition - * checking. - * - * Copyright: Copyright Sean Kelly 2005 - 2009. - * License: = 0 ); - } - body - { - version( Win32 ) - { - enum : uint - { - TICKS_PER_MILLI = 10_000, - MAX_WAIT_MILLIS = uint.max - 1 - } - - period /= TICKS_PER_MILLI; - if( period > MAX_WAIT_MILLIS ) - period = MAX_WAIT_MILLIS; - return timedWait( cast(uint) period ); - } - else version( Posix ) - { - timespec t = void; - mktspec( t, period ); - - int rc = pthread_cond_timedwait( &m_hndl, m_mutexAddr, &t ); - if( !rc ) - return true; - if( rc == ETIMEDOUT ) - return false; - throw new SyncException( "Unable to wait for condition" ); - } - } - - /** - * Notifies one waiter. - * - * Throws: - * SyncException on error. - */ - void notify() - { - version( Win32 ) - { - notify( false ); - } - else version( Posix ) - { - int rc = pthread_cond_signal( &m_hndl ); - if( rc ) - throw new SyncException( "Unable to notify condition" ); - } - } - - - /** - * Notifies all waiters. - * - * Throws: - * SyncException on error. - */ - void notifyAll() - { - version( Win32 ) - { - notify( true ); - } - else version( Posix ) - { - int rc = pthread_cond_broadcast( &m_hndl ); - if( rc ) - throw new SyncException( "Unable to notify condition" ); - } - } - - -private: - version( Win32 ) - { - bool timedWait( DWORD timeout ) - { - int numSignalsLeft; - int numWaitersGone; - DWORD rc; - - rc = WaitForSingleObject( m_blockLock, INFINITE ); - assert( rc == WAIT_OBJECT_0 ); - - m_numWaitersBlocked++; - - rc = ReleaseSemaphore( m_blockLock, 1, null ); - assert( rc ); - - m_assocMutex.unlock(); - scope(failure) m_assocMutex.lock(); - - rc = WaitForSingleObject( m_blockQueue, timeout ); - assert( rc == WAIT_OBJECT_0 || rc == WAIT_TIMEOUT ); - bool timedOut = (rc == WAIT_TIMEOUT); - - EnterCriticalSection( &m_unblockLock ); - scope(failure) LeaveCriticalSection( &m_unblockLock ); - - if( (numSignalsLeft = m_numWaitersToUnblock) != 0 ) - { - if ( timedOut ) - { - // timeout (or canceled) - if( m_numWaitersBlocked != 0 ) - { - m_numWaitersBlocked--; - // do not unblock next waiter below (already unblocked) - numSignalsLeft = 0; - } - else - { - // spurious wakeup pending!! - m_numWaitersGone = 1; - } - } - if( --m_numWaitersToUnblock == 0 ) - { - if( m_numWaitersBlocked != 0 ) - { - // open the gate - rc = ReleaseSemaphore( m_blockLock, 1, null ); - assert( rc ); - // do not open the gate below again - numSignalsLeft = 0; - } - else if( (numWaitersGone = m_numWaitersGone) != 0 ) - { - m_numWaitersGone = 0; - } - } - } - else if( ++m_numWaitersGone == int.max / 2 ) - { - // timeout/canceled or spurious event :-) - rc = WaitForSingleObject( m_blockLock, INFINITE ); - assert( rc == WAIT_OBJECT_0 ); - // something is going on here - test of timeouts? - m_numWaitersBlocked -= m_numWaitersGone; - rc = ReleaseSemaphore( m_blockLock, 1, null ); - assert( rc == WAIT_OBJECT_0 ); - m_numWaitersGone = 0; - } - - LeaveCriticalSection( &m_unblockLock ); - - if( numSignalsLeft == 1 ) - { - // better now than spurious later (same as ResetEvent) - for( ; numWaitersGone > 0; --numWaitersGone ) - { - rc = WaitForSingleObject( m_blockQueue, INFINITE ); - assert( rc == WAIT_OBJECT_0 ); - } - // open the gate - rc = ReleaseSemaphore( m_blockLock, 1, null ); - assert( rc ); - } - else if( numSignalsLeft != 0 ) - { - // unblock next waiter - rc = ReleaseSemaphore( m_blockQueue, 1, null ); - assert( rc ); - } - m_assocMutex.lock(); - return !timedOut; - } - - - void notify( bool all ) - { - DWORD rc; - - EnterCriticalSection( &m_unblockLock ); - scope(failure) LeaveCriticalSection( &m_unblockLock ); - - if( m_numWaitersToUnblock != 0 ) - { - if( m_numWaitersBlocked == 0 ) - { - LeaveCriticalSection( &m_unblockLock ); - return; - } - if( all ) - { - m_numWaitersToUnblock += m_numWaitersBlocked; - m_numWaitersBlocked = 0; - } - else - { - m_numWaitersToUnblock++; - m_numWaitersBlocked--; - } - LeaveCriticalSection( &m_unblockLock ); - } - else if( m_numWaitersBlocked > m_numWaitersGone ) - { - rc = WaitForSingleObject( m_blockLock, INFINITE ); - assert( rc == WAIT_OBJECT_0 ); - if( 0 != m_numWaitersGone ) - { - m_numWaitersBlocked -= m_numWaitersGone; - m_numWaitersGone = 0; - } - if( all ) - { - m_numWaitersToUnblock = m_numWaitersBlocked; - m_numWaitersBlocked = 0; - } - else - { - m_numWaitersToUnblock = 1; - m_numWaitersBlocked--; - } - LeaveCriticalSection( &m_unblockLock ); - rc = ReleaseSemaphore( m_blockQueue, 1, null ); - assert( rc ); - } - else - { - LeaveCriticalSection( &m_unblockLock ); - } - } - - - // NOTE: This implementation uses Algorithm 8c as described here: - // http://groups.google.com/group/comp.programming.threads/ - // browse_frm/thread/1692bdec8040ba40/e7a5f9d40e86503a - HANDLE m_blockLock; // auto-reset event (now semaphore) - HANDLE m_blockQueue; // auto-reset event (now semaphore) - Mutex m_assocMutex; // external mutex/CS - CRITICAL_SECTION m_unblockLock; // internal mutex/CS - int m_numWaitersGone = 0; - int m_numWaitersBlocked = 0; - int m_numWaitersToUnblock = 0; - } - else version( Posix ) - { - pthread_cond_t m_hndl; - pthread_mutex_t* m_mutexAddr; - } -} - - -//////////////////////////////////////////////////////////////////////////////// -// Unit Tests -//////////////////////////////////////////////////////////////////////////////// - - -version( unittest ) -{ - private import core.thread; - private import core.sync.mutex; - private import core.sync.semaphore; - - - void testNotify() - { - auto mutex = new Mutex; - auto condReady = new Condition( mutex ); - auto semDone = new Semaphore; - auto synLoop = new Object; - int numWaiters = 10; - int numTries = 10; - int numReady = 0; - int numTotal = 0; - int numDone = 0; - int numPost = 0; - - void waiter() - { - for( int i = 0; i < numTries; ++i ) - { - synchronized( mutex ) - { - while( numReady < 1 ) - { - condReady.wait(); - } - --numReady; - ++numTotal; - } - - synchronized( synLoop ) - { - ++numDone; - } - semDone.wait(); - } - } - - auto group = new ThreadGroup; - - for( int i = 0; i < numWaiters; ++i ) - group.create( &waiter ); - - for( int i = 0; i < numTries; ++i ) - { - for( int j = 0; j < numWaiters; ++j ) - { - synchronized( mutex ) - { - ++numReady; - condReady.notify(); - } - } - while( true ) - { - synchronized( synLoop ) - { - if( numDone >= numWaiters ) - break; - } - Thread.yield(); - } - for( int j = 0; j < numWaiters; ++j ) - { - semDone.notify(); - } - } - - group.joinAll(); - assert( numTotal == numWaiters * numTries ); - } - - - void testNotifyAll() - { - auto mutex = new Mutex; - auto condReady = new Condition( mutex ); - int numWaiters = 10; - int numReady = 0; - int numDone = 0; - bool alert = false; - - void waiter() - { - synchronized( mutex ) - { - ++numReady; - while( !alert ) - condReady.wait(); - ++numDone; - } - } - - auto group = new ThreadGroup; - - for( int i = 0; i < numWaiters; ++i ) - group.create( &waiter ); - - while( true ) - { - synchronized( mutex ) - { - if( numReady >= numWaiters ) - { - alert = true; - condReady.notifyAll(); - break; - } - } - Thread.yield(); - } - group.joinAll(); - assert( numReady == numWaiters && numDone == numWaiters ); - } - - - void testWaitTimeout() - { - auto mutex = new Mutex; - auto condReady = new Condition( mutex ); - bool waiting = false; - bool alertedOne = true; - bool alertedTwo = true; - - void waiter() - { - synchronized( mutex ) - { - waiting = true; - alertedOne = condReady.wait( 10_000_000 ); // 1s - alertedTwo = condReady.wait( 10_000_000 ); // 1s - } - } - - auto thread = new Thread( &waiter ); - thread.start(); - - while( true ) - { - synchronized( mutex ) - { - if( waiting ) - { - condReady.notify(); - break; - } - } - Thread.yield(); - } - thread.join(); - assert( waiting && alertedOne && !alertedTwo ); - } - - - unittest - { - testNotify(); - testNotifyAll(); - testWaitTimeout(); - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/common/core/sync/config.d --- a/druntime/src/common/core/sync/config.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -/** - * The config module contains utility routines and configuration information - * specific to this package. - * - * Copyright: Copyright Sean Kelly 2005 - 2009. - * License: Boost License 1.0. - * Authors: Sean Kelly - * - * Copyright Sean Kelly 2005 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module core.sync.exception; - - -/** - * Base class for synchronization exceptions. - */ -class SyncException : Exception -{ - this( string msg ) - { - super( msg ); - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/common/core/sync/mutex.d --- a/druntime/src/common/core/sync/mutex.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,268 +0,0 @@ -/** - * The mutex module provides a primitive for maintaining mutually exclusive - * access. - * - * Copyright: Copyright Sean Kelly 2005 - 2009. - * License: 0 ) - m_writerQueue.notify(); - } - } - } - - - /** - * Attempts to acquire a read lock on the enclosing mutex. If one can - * be obtained without blocking, the lock is acquired and true is - * returned. If not, the lock is not acquired and false is returned. - * - * Returns: - * true if the lock was acquired and false if not. - */ - bool tryLock() - { - synchronized( m_commonMutex ) - { - if( shouldQueueReader() ) - return false; - ++m_numActiveReaders; - return true; - } - } - - - private: - bool shouldQueueReader() - { - if( m_numActiveWriters > 0 ) - return true; - - switch( m_policy ) - { - case Policy.PREFER_WRITERS: - return m_numQueuedWriters > 0; - - case Policy.PREFER_READERS: - default: - break; - } - - return false; - } - - struct MonitorProxy - { - Object.Monitor link; - } - - MonitorProxy m_proxy; - } - - - //////////////////////////////////////////////////////////////////////////// - // Writer - //////////////////////////////////////////////////////////////////////////// - - - /** - * This class can be considered a mutex in its own right, and is used to - * negotiate a write lock for the enclosing mutex. - */ - class Writer : - Object.Monitor - { - /** - * Initializes a read/write mutex writer proxy object. - */ - this() - { - m_proxy.link = this; - (cast(void**) this)[1] = &m_proxy; - } - - - /** - * Acquires a write lock on the enclosing mutex. - */ - void lock() - { - synchronized( m_commonMutex ) - { - ++m_numQueuedWriters; - scope(exit) --m_numQueuedWriters; - - while( shouldQueueWriter() ) - m_writerQueue.wait(); - ++m_numActiveWriters; - } - } - - - /** - * Releases a write lock on the enclosing mutex. - */ - void unlock() - { - synchronized( m_commonMutex ) - { - if( --m_numActiveWriters < 1 ) - { - switch( m_policy ) - { - default: - case Policy.PREFER_READERS: - if( m_numQueuedReaders > 0 ) - m_readerQueue.notifyAll(); - else if( m_numQueuedWriters > 0 ) - m_writerQueue.notify(); - break; - case Policy.PREFER_WRITERS: - if( m_numQueuedWriters > 0 ) - m_writerQueue.notify(); - else if( m_numQueuedReaders > 0 ) - m_readerQueue.notifyAll(); - } - } - } - } - - - /** - * Attempts to acquire a write lock on the enclosing mutex. If one can - * be obtained without blocking, the lock is acquired and true is - * returned. If not, the lock is not acquired and false is returned. - * - * Returns: - * true if the lock was acquired and false if not. - */ - bool tryLock() - { - synchronized( m_commonMutex ) - { - if( shouldQueueWriter() ) - return false; - ++m_numActiveWriters; - return true; - } - } - - - private: - bool shouldQueueWriter() - { - if( m_numActiveWriters > 0 || - m_numActiveReaders > 0 ) - return true; - switch( m_policy ) - { - case Policy.PREFER_READERS: - return m_numQueuedReaders > 0; - - case Policy.PREFER_WRITERS: - default: - break; - } - - return false; - } - - struct MonitorProxy - { - Object.Monitor link; - } - - MonitorProxy m_proxy; - } - - -private: - Policy m_policy; - Reader m_reader; - Writer m_writer; - - Mutex m_commonMutex; - Condition m_readerQueue; - Condition m_writerQueue; - - int m_numQueuedReaders; - int m_numActiveReaders; - int m_numQueuedWriters; - int m_numActiveWriters; -} - - -//////////////////////////////////////////////////////////////////////////////// -// Unit Tests -//////////////////////////////////////////////////////////////////////////////// - - -version( unittest ) -{ - static if( !is( typeof( Thread ) ) ) - private import core.thread; - - - void testRead( ReadWriteMutex.Policy policy ) - { - auto mutex = new ReadWriteMutex( policy ); - auto synInfo = new Object; - int numThreads = 10; - int numReaders = 0; - int maxReaders = 0; - - void readerFn() - { - synchronized( mutex.reader() ) - { - synchronized( synInfo ) - { - if( ++numReaders > maxReaders ) - maxReaders = numReaders; - } - Thread.sleep( 100_000 ); // 1ms - synchronized( synInfo ) - { - --numReaders; - } - } - } - - auto group = new ThreadGroup; - - for( int i = 0; i < numThreads; ++i ) - { - group.create( &readerFn ); - } - group.joinAll(); - assert( numReaders < 1 && maxReaders > 1 ); - } - - - void testReadWrite( ReadWriteMutex.Policy policy ) - { - auto mutex = new ReadWriteMutex( policy ); - auto synInfo = new Object; - int numThreads = 10; - int numReaders = 0; - int numWriters = 0; - int maxReaders = 0; - int maxWriters = 0; - int numTries = 20; - - void readerFn() - { - for( int i = 0; i < numTries; ++i ) - { - synchronized( mutex.reader() ) - { - synchronized( synInfo ) - { - if( ++numReaders > maxReaders ) - maxReaders = numReaders; - } - Thread.sleep( 100_000 ); // 1ms - synchronized( synInfo ) - { - --numReaders; - } - } - } - } - - void writerFn() - { - for( int i = 0; i < numTries; ++i ) - { - synchronized( mutex.writer() ) - { - synchronized( synInfo ) - { - if( ++numWriters > maxWriters ) - maxWriters = numWriters; - } - Thread.sleep( 100_000 ); // 1ms - synchronized( synInfo ) - { - --numWriters; - } - } - } - } - - auto group = new ThreadGroup; - - for( int i = 0; i < numThreads; ++i ) - { - group.create( &readerFn ); - group.create( &writerFn ); - } - group.joinAll(); - assert( numReaders < 1 && maxReaders > 1 && - numWriters < 1 && maxWriters < 2 ); - } - - - unittest - { - testRead( ReadWriteMutex.Policy.PREFER_READERS ); - testRead( ReadWriteMutex.Policy.PREFER_WRITERS ); - testReadWrite( ReadWriteMutex.Policy.PREFER_READERS ); - testReadWrite( ReadWriteMutex.Policy.PREFER_WRITERS ); - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/common/core/sync/semaphore.d --- a/druntime/src/common/core/sync/semaphore.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,506 +0,0 @@ -/** - * The semaphore module provides a general use semaphore for synchronization. - * - * Copyright: Copyright Sean Kelly 2005 - 2009. - * License: = 0 ); - } - body - { - version( Win32 ) - { - enum : uint - { - TICKS_PER_MILLI = 10_000, - MAX_WAIT_MILLIS = uint.max - 1 - } - - period /= TICKS_PER_MILLI; - if( period > MAX_WAIT_MILLIS ) - period = MAX_WAIT_MILLIS; - switch( WaitForSingleObject( m_hndl, cast(uint) period ) ) - { - case WAIT_OBJECT_0: - return true; - case WAIT_TIMEOUT: - return false; - default: - throw new SyncException( "Unable to wait for semaphore" ); - } - } - else version( OSX ) - { - mach_timespec_t t = void; - (cast(byte*) &t)[0 .. t.sizeof] = 0; - - if( period != 0 ) - { - enum : uint - { - NANOS_PER_TICK = 100, - TICKS_PER_SECOND = 10_000_000, - NANOS_PER_SECOND = NANOS_PER_TICK * TICKS_PER_SECOND, - } - - if( t.tv_sec.max - t.tv_sec < period / TICKS_PER_SECOND ) - { - t.tv_sec = t.tv_sec.max; - t.tv_nsec = 0; - } - else - { - t.tv_sec += cast(typeof(t.tv_sec)) (period / TICKS_PER_SECOND); - long ns = (period % TICKS_PER_SECOND) * NANOS_PER_TICK; - if( NANOS_PER_SECOND - t.tv_nsec > ns ) - t.tv_nsec = cast(typeof(t.tv_nsec)) ns; - else - { - t.tv_sec += 1; - t.tv_nsec += ns - NANOS_PER_SECOND; - } - } - } - while( true ) - { - auto rc = semaphore_timedwait( m_hndl, t ); - if( !rc ) - return true; - if( rc == KERN_OPERATION_TIMED_OUT ) - return false; - if( rc != KERN_ABORTED || errno != EINTR ) - throw new SyncException( "Unable to wait for semaphore" ); - } - // -w trip - return false; - } - else version( Posix ) - { - timespec t = void; - mktspec( t, period ); - - while( true ) - { - if( !sem_timedwait( &m_hndl, &t ) ) - return true; - if( errno == ETIMEDOUT ) - return false; - if( errno != EINTR ) - throw new SyncException( "Unable to wait for semaphore" ); - } - // -w trip - return false; - } - } - - - /** - * Atomically increment the current count by one. This will notify one - * waiter, if there are any in the queue. - * - * Throws: - * SyncException on error. - */ - void notify() - { - version( Win32 ) - { - if( !ReleaseSemaphore( m_hndl, 1, null ) ) - throw new SyncException( "Unable to notify semaphore" ); - } - else version( OSX ) - { - auto rc = semaphore_signal( m_hndl ); - if( rc ) - throw new SyncException( "Unable to notify semaphore" ); - } - else version( Posix ) - { - int rc = sem_post( &m_hndl ); - if( rc ) - throw new SyncException( "Unable to notify semaphore" ); - } - } - - - /** - * If the current count is equal to zero, return. Otherwise, atomically - * decrement the count by one and return true. - * - * Throws: - * SyncException on error. - * - * Returns: - * true if the count was above zero and false if not. - */ - bool tryWait() - { - version( Win32 ) - { - switch( WaitForSingleObject( m_hndl, 0 ) ) - { - case WAIT_OBJECT_0: - return true; - case WAIT_TIMEOUT: - return false; - default: - throw new SyncException( "Unable to wait for semaphore" ); - } - } - else version( OSX ) - { - return wait( 0 ); - } - else version( Posix ) - { - while( true ) - { - if( !sem_trywait( &m_hndl ) ) - return true; - if( errno == EAGAIN ) - return false; - if( errno != EINTR ) - throw new SyncException( "Unable to wait for semaphore" ); - } - // -w trip - return false; - } - } - - -private: - version( Win32 ) - { - HANDLE m_hndl; - } - else version( OSX ) - { - semaphore_t m_hndl; - } - else version( Posix ) - { - sem_t m_hndl; - } -} - - -//////////////////////////////////////////////////////////////////////////////// -// Unit Tests -//////////////////////////////////////////////////////////////////////////////// - - -version( unittest ) -{ - private import core.thread; - - - void testWait() - { - auto semaphore = new Semaphore; - int numToProduce = 10; - bool allProduced = false; - auto synProduced = new Object; - int numConsumed = 0; - auto synConsumed = new Object; - int numConsumers = 10; - int numComplete = 0; - auto synComplete = new Object; - - void consumer() - { - while( true ) - { - semaphore.wait(); - - synchronized( synProduced ) - { - if( allProduced ) - break; - } - - synchronized( synConsumed ) - { - ++numConsumed; - } - } - - synchronized( synComplete ) - { - ++numComplete; - } - } - - void producer() - { - assert( !semaphore.tryWait() ); - - for( int i = 0; i < numToProduce; ++i ) - { - semaphore.notify(); - Thread.yield(); - } - Thread.sleep( 10_000_000 ); // 1s - synchronized( synProduced ) - { - allProduced = true; - } - - for( int i = 0; i < numConsumers; ++i ) - { - semaphore.notify(); - Thread.yield(); - } - - for( int i = numConsumers * 10000; i > 0; --i ) - { - synchronized( synComplete ) - { - if( numComplete == numConsumers ) - break; - } - Thread.yield(); - } - - synchronized( synComplete ) - { - assert( numComplete == numConsumers ); - } - - synchronized( synConsumed ) - { - assert( numConsumed == numToProduce ); - } - - assert( !semaphore.tryWait() ); - semaphore.notify(); - assert( semaphore.tryWait() ); - assert( !semaphore.tryWait() ); - } - - auto group = new ThreadGroup; - - for( int i = 0; i < numConsumers; ++i ) - group.create( &consumer ); - group.create( &producer ); - group.joinAll(); - } - - - void testWaitTimeout() - { - auto synReady = new Object; - auto semReady = new Semaphore; - bool waiting = false; - bool alertedOne = true; - bool alertedTwo = true; - - void waiter() - { - synchronized( synReady ) - { - waiting = true; - } - alertedOne = semReady.wait( 10_000_000 ); // 100ms - alertedTwo = semReady.wait( 10_000_000 ); // 100ms - } - - auto thread = new Thread( &waiter ); - thread.start(); - - while( true ) - { - synchronized( synReady ) - { - if( waiting ) - { - semReady.notify(); - break; - } - } - Thread.yield(); - } - thread.join(); - assert( waiting && alertedOne && !alertedTwo ); - } - - - unittest - { - testWait(); - testWaitTimeout(); - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/common/core/thread.d --- a/druntime/src/common/core/thread.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3516 +0,0 @@ -/** - * The thread module provides support for thread creation and management. - * - * Copyright: Copyright Sean Kelly 2005 - 2009. - * License: = 0 ); - } - body - { - version( Windows ) - { - enum : uint - { - TICKS_PER_MILLI = 10_000, - MAX_SLEEP_MILLIS = uint.max - 1 - } - - // NOTE: In instances where all other threads in the process have a - // lower priority than the current thread, the current thread - // will not yield with a sleep time of zero. However, unlike - // yield(), the user is not asking for a yield to occur but - // only for execution to suspend for the requested interval. - // Therefore, expected performance may not be met if a yield - // is forced upon the user. - period /= TICKS_PER_MILLI; - while( period > MAX_SLEEP_MILLIS ) - { - Sleep( MAX_SLEEP_MILLIS ); - period -= MAX_SLEEP_MILLIS; - } - Sleep( cast(uint) period ); - } - else version( Posix ) - { - timespec tin = void; - timespec tout = void; - - enum : uint - { - NANOS_PER_TICK = 100, - TICKS_PER_SECOND = 10_000_000, - } - enum : typeof(period) - { - MAX_SLEEP_TICKS = cast(typeof(period)) tin.tv_sec.max * TICKS_PER_SECOND - } - - do - { - if( period > MAX_SLEEP_TICKS ) - { - tin.tv_sec = tin.tv_sec.max; - tin.tv_nsec = 0; - } - else - { - tin.tv_sec = cast(typeof(tin.tv_sec)) (period / TICKS_PER_SECOND); - tin.tv_nsec = cast(typeof(tin.tv_nsec)) (period % TICKS_PER_SECOND) * NANOS_PER_TICK; - } - while( true ) - { - if( !nanosleep( &tin, &tout ) ) - return; - if( getErrno() != EINTR ) - throw new ThreadException( "Unable to sleep for the specified duration" ); - tin = tout; - } - period -= (cast(typeof(period)) tin.tv_sec) * TICKS_PER_SECOND; - period -= (cast(typeof(period)) tin.tv_nsec) / NANOS_PER_TICK; - } while( period > 0 ); - } - } - - - /** - * Forces a context switch to occur away from the calling thread. - */ - static void yield() - { - version( Windows ) - { - // NOTE: Sleep(1) is necessary because Sleep(0) does not give - // lower priority threads any timeslice, so looping on - // Sleep(0) could be resource-intensive in some cases. - Sleep( 1 ); - } - else version( Posix ) - { - sched_yield(); - } - } - - - /////////////////////////////////////////////////////////////////////////// - // Thread Accessors - /////////////////////////////////////////////////////////////////////////// - - - /** - * Provides a reference to the calling thread. - * - * Returns: - * The thread object representing the calling thread. The result of - * deleting this object is undefined. - */ - static Thread getThis() - { - // NOTE: This function may not be called until thread_init has - // completed. See thread_suspendAll for more information - // on why this might occur. - version( Windows ) - { - return cast(Thread) TlsGetValue( sm_this ); - } - else version( Posix ) - { - return cast(Thread) pthread_getspecific( sm_this ); - } - } - - - /** - * Provides a list of all threads currently being tracked by the system. - * - * Returns: - * An array containing references to all threads currently being - * tracked by the system. The result of deleting any contained - * objects is undefined. - */ - static Thread[] getAll() - { - synchronized( slock ) - { - size_t pos = 0; - Thread[] buf = new Thread[sm_tlen]; - - foreach( Thread t; Thread ) - { - buf[pos++] = t; - } - return buf; - } - } - - - /** - * Operates on all threads currently being tracked by the system. The - * result of deleting any Thread object is undefined. - * - * Params: - * dg = The supplied code as a delegate. - * - * Returns: - * Zero if all elemented are visited, nonzero if not. - */ - static int opApply( int delegate( inout Thread ) dg ) - { - synchronized( slock ) - { - int ret = 0; - - for( Thread t = sm_tbeg; t; t = t.next ) - { - ret = dg( t ); - if( ret ) - break; - } - return ret; - } - } - - - /////////////////////////////////////////////////////////////////////////// - // Local Storage Actions - /////////////////////////////////////////////////////////////////////////// - - - /** - * Indicates the number of local storage pointers available at program - * startup. It is recommended that this number be at least 64. - */ - static const uint LOCAL_MAX = 64; - - - /** - * Reserves a local storage pointer for use and initializes this location - * to null for all running threads. - * - * Returns: - * A key representing the array offset of this memory location. - */ - static uint createLocal() - { - synchronized( slock ) - { - foreach( uint key, inout bool set; sm_local ) - { - if( !set ) - { - //foreach( Thread t; sm_tbeg ) Bug in GDC 0.24 SVN (r139) - for( Thread t = sm_tbeg; t; t = t.next ) - { - t.m_local[key] = null; - } - set = true; - return key; - } - } - throw new ThreadException( "No more local storage slots available" ); - } - } - - - /** - * Marks the supplied key as available and sets the associated location - * to null for all running threads. It is assumed that any key passed - * to this function is valid. The result of calling this function for - * a key which is still in use is undefined. - * - * Params: - * key = The key to delete. - */ - static void deleteLocal( uint key ) - { - synchronized( slock ) - { - sm_local[key] = false; - // foreach( Thread t; sm_tbeg ) Bug in GDC 0.24 SVN (r139) - for( Thread t = sm_tbeg; t; t = t.next ) - { - t.m_local[key] = null; - } - } - } - - - /** - * Loads the value stored at key within a thread-local static array. It is - * assumed that any key passed to this function is valid. - * - * Params: - * key = The location which holds the desired data. - * - * Returns: - * The data associated with the supplied key. - */ - static void* getLocal( uint key ) - { - return getThis().m_local[key]; - } - - - /** - * Stores the supplied value at key within a thread-local static array. It - * is assumed that any key passed to this function is valid. - * - * Params: - * key = The location to store the supplied data. - * val = The data to store. - * - * Returns: - * A copy of the data which has just been stored. - */ - static void* setLocal( uint key, void* val ) - { - return getThis().m_local[key] = val; - } - - - /////////////////////////////////////////////////////////////////////////// - // Static Initalizer - /////////////////////////////////////////////////////////////////////////// - - - /** - * This initializer is used to set thread constants. All functional - * initialization occurs within thread_init(). - */ - static this() - { - version( Windows ) - { - PRIORITY_MIN = -15; - PRIORITY_MAX = 15; - } - else version( Posix ) - { - int policy; - sched_param param; - pthread_t self = pthread_self(); - - int status = pthread_getschedparam( self, &policy, ¶m ); - assert( status == 0 ); - - PRIORITY_MIN = sched_get_priority_min( policy ); - assert( PRIORITY_MIN != -1 ); - - PRIORITY_MAX = sched_get_priority_max( policy ); - assert( PRIORITY_MAX != -1 ); - } - } - - -private: - // - // Initializes a thread object which has no associated executable function. - // This is used for the main thread initialized in thread_init(). - // - this() - { - m_call = Call.NO; - m_curr = &m_main; - - void* pstart = cast(void*) &_tlsstart; - void* pend = cast(void*) &_tlsend; - m_tls = pstart[0 .. pend - pstart]; - } - - - // - // Thread entry point. Invokes the function or delegate passed on - // construction (if any). - // - final void run() - { - switch( m_call ) - { - case Call.FN: - m_fn(); - break; - case Call.DG: - m_dg(); - break; - default: - break; - } - } - - -private: - // - // The type of routine passed on thread construction. - // - enum Call - { - NO, - FN, - DG - } - - - // - // Standard types - // - version( Windows ) - { - alias uint TLSKey; - alias uint ThreadAddr; - } - else version( Posix ) - { - alias pthread_key_t TLSKey; - alias pthread_t ThreadAddr; - } - - - // - // Local storage - // - __gshared bool[LOCAL_MAX] sm_local; - __gshared TLSKey sm_this; - - void*[LOCAL_MAX] m_local; - - - // - // Standard thread data - // - version( Windows ) - { - HANDLE m_hndl; - } - else version( OSX ) - { - mach_port_t m_tmach; - } - ThreadAddr m_addr; - Call m_call; - char[] m_name; - union - { - void function() m_fn; - void delegate() m_dg; - } - size_t m_sz; - version( Posix ) - { - bool m_isRunning; - } - bool m_isDaemon; - Object m_unhandled; - - -private: - /////////////////////////////////////////////////////////////////////////// - // Storage of Active Thread - /////////////////////////////////////////////////////////////////////////// - - - // - // Sets a thread-local reference to the current thread object. - // - static void setThis( Thread t ) - { - version( Windows ) - { - TlsSetValue( sm_this, cast(void*) t ); - } - else version( Posix ) - { - pthread_setspecific( sm_this, cast(void*) t ); - } - } - - -private: - /////////////////////////////////////////////////////////////////////////// - // Thread Context and GC Scanning Support - /////////////////////////////////////////////////////////////////////////// - - - final void pushContext( Context* c ) - in - { - assert( !c.within ); - } - body - { - c.within = m_curr; - m_curr = c; - } - - - final void popContext() - in - { - assert( m_curr && m_curr.within ); - } - body - { - Context* c = m_curr; - m_curr = c.within; - c.within = null; - } - - - final Context* topContext() - in - { - assert( m_curr ); - } - body - { - return m_curr; - } - - - static struct Context - { - void* bstack, - tstack; - Context* within; - Context* next, - prev; - } - - - Context m_main; - Context* m_curr; - bool m_lock; - void[] m_tls; // spans implicit thread local storage - - version( Windows ) - { - version( X86 ) - { - uint[8] m_reg; // edi,esi,ebp,esp,ebx,edx,ecx,eax - } - else version( X86_64 ) - { - ulong[16] m_reg; // rdi,rsi,rbp,rsp,rbx,rdx,rcx,rax - // r8,r9,r10,r11,r12,r13,r14,r15 - } - else - { - static assert( "Architecture not supported." ); - } - } - else version( OSX ) - { - version( X86 ) - { - uint[8] m_reg; // edi,esi,ebp,esp,ebx,edx,ecx,eax - } - else version( X86_64 ) - { - ulong[16] m_reg; // rdi,rsi,rbp,rsp,rbx,rdx,rcx,rax - // r8,r9,r10,r11,r12,r13,r14,r15 - } - else - { - static assert( "Architecture not supported." ); - } - } - - -private: - /////////////////////////////////////////////////////////////////////////// - // GC Scanning Support - /////////////////////////////////////////////////////////////////////////// - - - // NOTE: The GC scanning process works like so: - // - // 1. Suspend all threads. - // 2. Scan the stacks of all suspended threads for roots. - // 3. Resume all threads. - // - // Step 1 and 3 require a list of all threads in the system, while - // step 2 requires a list of all thread stacks (each represented by - // a Context struct). Traditionally, there was one stack per thread - // and the Context structs were not necessary. However, Fibers have - // changed things so that each thread has its own 'main' stack plus - // an arbitrary number of nested stacks (normally referenced via - // m_curr). Also, there may be 'free-floating' stacks in the system, - // which are Fibers that are not currently executing on any specific - // thread but are still being processed and still contain valid - // roots. - // - // To support all of this, the Context struct has been created to - // represent a stack range, and a global list of Context structs has - // been added to enable scanning of these stack ranges. The lifetime - // (and presence in the Context list) of a thread's 'main' stack will - // be equivalent to the thread's lifetime. So the Ccontext will be - // added to the list on thread entry, and removed from the list on - // thread exit (which is essentially the same as the presence of a - // Thread object in its own global list). The lifetime of a Fiber's - // context, however, will be tied to the lifetime of the Fiber object - // itself, and Fibers are expected to add/remove their Context struct - // on construction/deletion. - - - // - // All use of the global lists should synchronize on this lock. - // - static Object slock() - { - return Thread.classinfo; - } - - - __gshared - { - Context* sm_cbeg; - size_t sm_clen; - - Thread sm_tbeg; - size_t sm_tlen; - } - - // - // Used for ordering threads in the global thread list. - // - Thread prev; - Thread next; - - - /////////////////////////////////////////////////////////////////////////// - // Global Context List Operations - /////////////////////////////////////////////////////////////////////////// - - - // - // Add a context to the global context list. - // - static void add( Context* c ) - in - { - assert( c ); - assert( !c.next && !c.prev ); - } - body - { - synchronized( slock ) - { - if( sm_cbeg ) - { - c.next = sm_cbeg; - sm_cbeg.prev = c; - } - sm_cbeg = c; - ++sm_clen; - } - } - - - // - // Remove a context from the global context list. - // - static void remove( Context* c ) - in - { - assert( c ); - assert( c.next || c.prev ); - } - body - { - synchronized( slock ) - { - if( c.prev ) - c.prev.next = c.next; - if( c.next ) - c.next.prev = c.prev; - if( sm_cbeg == c ) - sm_cbeg = c.next; - --sm_clen; - } - // NOTE: Don't null out c.next or c.prev because opApply currently - // follows c.next after removing a node. This could be easily - // addressed by simply returning the next node from this - // function, however, a context should never be re-added to the - // list anyway and having next and prev be non-null is a good way - // to ensure that. - } - - - /////////////////////////////////////////////////////////////////////////// - // Global Thread List Operations - /////////////////////////////////////////////////////////////////////////// - - - // - // Add a thread to the global thread list. - // - static void add( Thread t ) - in - { - assert( t ); - assert( !t.next && !t.prev ); - assert( t.isRunning ); - } - body - { - synchronized( slock ) - { - if( sm_tbeg ) - { - t.next = sm_tbeg; - sm_tbeg.prev = t; - } - sm_tbeg = t; - ++sm_tlen; - } - } - - - // - // Remove a thread from the global thread list. - // - static void remove( Thread t ) - in - { - assert( t ); - assert( t.next || t.prev ); - version( Windows ) - { - // NOTE: This doesn't work for Posix as m_isRunning must be set to - // false after the thread is removed during normal execution. - assert( !t.isRunning ); - } - } - body - { - synchronized( slock ) - { - // NOTE: When a thread is removed from the global thread list its - // main context is invalid and should be removed as well. - // It is possible that t.m_curr could reference more - // than just the main context if the thread exited abnormally - // (if it was terminated), but we must assume that the user - // retains a reference to them and that they may be re-used - // elsewhere. Therefore, it is the responsibility of any - // object that creates contexts to clean them up properly - // when it is done with them. - remove( &t.m_main ); - - if( t.prev ) - t.prev.next = t.next; - if( t.next ) - t.next.prev = t.prev; - if( sm_tbeg == t ) - sm_tbeg = t.next; - --sm_tlen; - } - // NOTE: Don't null out t.next or t.prev because opApply currently - // follows t.next after removing a node. This could be easily - // addressed by simply returning the next node from this - // function, however, a thread should never be re-added to the - // list anyway and having next and prev be non-null is a good way - // to ensure that. - } -} - - -/////////////////////////////////////////////////////////////////////////////// -// GC Support Routines -/////////////////////////////////////////////////////////////////////////////// - - -/** - * Initializes the thread module. This function must be called by the - * garbage collector on startup and before any other thread routines - * are called. - */ -extern (C) void thread_init() -{ - // NOTE: If thread_init itself performs any allocations then the thread - // routines reserved for garbage collector use may be called while - // thread_init is being processed. However, since no memory should - // exist to be scanned at this point, it is sufficient for these - // functions to detect the condition and return immediately. - - version( Windows ) - { - Thread.sm_this = TlsAlloc(); - assert( Thread.sm_this != TLS_OUT_OF_INDEXES ); - } - else version( Posix ) - { - int status; - sigaction_t sigusr1 = void; - sigaction_t sigusr2 = void; - - // This is a quick way to zero-initialize the structs without using - // memset or creating a link dependency on their static initializer. - (cast(byte*) &sigusr1)[0 .. sigaction_t.sizeof] = 0; - (cast(byte*) &sigusr2)[0 .. sigaction_t.sizeof] = 0; - - // NOTE: SA_RESTART indicates that system calls should restart if they - // are interrupted by a signal, but this is not available on all - // Posix systems, even those that support multithreading. - static if( is( typeof( SA_RESTART ) ) ) - sigusr1.sa_flags = SA_RESTART; - else - sigusr1.sa_flags = 0; - sigusr1.sa_handler = &thread_suspendHandler; - // NOTE: We want to ignore all signals while in this handler, so fill - // sa_mask to indicate this. - status = sigfillset( &sigusr1.sa_mask ); - assert( status == 0 ); - - // NOTE: Since SIGUSR2 should only be issued for threads within the - // suspend handler, we don't want this signal to trigger a - // restart. - sigusr2.sa_flags = 0; - sigusr2.sa_handler = &thread_resumeHandler; - // NOTE: We want to ignore all signals while in this handler, so fill - // sa_mask to indicate this. - status = sigfillset( &sigusr2.sa_mask ); - assert( status == 0 ); - - status = sigaction( SIGUSR1, &sigusr1, null ); - assert( status == 0 ); - - status = sigaction( SIGUSR2, &sigusr2, null ); - assert( status == 0 ); - - status = sem_init( &suspendCount, 0, 0 ); - assert( status == 0 ); - - status = pthread_key_create( &Thread.sm_this, null ); - assert( status == 0 ); - } - - thread_attachThis(); -} - - -/** - * Registers the calling thread for use with the D Runtime. If this routine - * is called for a thread which is already registered, the result is undefined. - */ -extern (C) void thread_attachThis() -{ - version( Windows ) - { - Thread thisThread = new Thread(); - Thread.Context* thisContext = &thisThread.m_main; - assert( thisContext == thisThread.m_curr ); - - thisThread.m_addr = GetCurrentThreadId(); - thisThread.m_hndl = GetCurrentThreadHandle(); - thisContext.bstack = getStackBottom(); - thisContext.tstack = thisContext.bstack; - - thisThread.m_isDaemon = true; - - Thread.setThis( thisThread ); - } - else version( Posix ) - { - Thread thisThread = new Thread(); - Thread.Context* thisContext = thisThread.m_curr; - assert( thisContext == &thisThread.m_main ); - - thisThread.m_addr = pthread_self(); - thisContext.bstack = getStackBottom(); - thisContext.tstack = thisContext.bstack; - - thisThread.m_isRunning = true; - thisThread.m_isDaemon = true; - - Thread.setThis( thisThread ); - } - version( OSX ) - { - thisThread.m_tmach = pthread_mach_thread_np( thisThread.m_addr ); - assert( thisThread.m_tmach != thisThread.m_tmach.init ); - } - - Thread.add( thisThread ); - Thread.add( thisContext ); -} - - -/** - * Deregisters the calling thread from use with the runtime. If this routine - * is called for a thread which is already registered, the result is undefined. - */ -extern (C) void thread_detachThis() -{ - Thread.remove( Thread.getThis() ); -} - - -/** - * Joins all non-daemon threads that are currently running. This is done by - * performing successive scans through the thread list until a scan consists - * of only daemon threads. - */ -extern (C) void thread_joinAll() -{ - - while( true ) - { - Thread nonDaemon = null; - - foreach( t; Thread ) - { - if( !t.isDaemon ) - { - nonDaemon = t; - break; - } - } - if( nonDaemon is null ) - return; - nonDaemon.join(); - } -} - - -/** - * Performs intermediate shutdown of the thread module. - */ -static ~this() -{ - // NOTE: The functionality related to garbage collection must be minimally - // operable after this dtor completes. Therefore, only minimal - // cleanup may occur. - - for( Thread t = Thread.sm_tbeg; t; t = t.next ) - { - if( !t.isRunning ) - Thread.remove( t ); - } -} - - -// Used for needLock below -private __gshared bool multiThreadedFlag = false; - - -/** - * This function is used to determine whether the the process is - * multi-threaded. Optimizations may only be performed on this - * value if the programmer can guarantee that no path from the - * enclosed code will start a thread. - * - * Returns: - * True if Thread.start() has been called in this process. - */ -extern (C) bool thread_needLock() -{ - return multiThreadedFlag; -} - - -// Used for suspendAll/resumeAll below -private __gshared uint suspendDepth = 0; - - -/** - * Suspend all threads but the calling thread for "stop the world" garbage - * collection runs. This function may be called multiple times, and must - * be followed by a matching number of calls to thread_resumeAll before - * processing is resumed. - * - * Throws: - * ThreadException if the suspend operation fails for a running thread. - */ -extern (C) void thread_suspendAll() -{ - /** - * Suspend the specified thread and load stack and register information for - * use by thread_scanAll. If the supplied thread is the calling thread, - * stack and register information will be loaded but the thread will not - * be suspended. If the suspend operation fails and the thread is not - * running then it will be removed from the global thread list, otherwise - * an exception will be thrown. - * - * Params: - * t = The thread to suspend. - * - * Throws: - * ThreadException if the suspend operation fails for a running thread. - */ - void suspend( Thread t ) - { - version( Windows ) - { - if( t.m_addr != GetCurrentThreadId() && SuspendThread( t.m_hndl ) == 0xFFFFFFFF ) - { - if( !t.isRunning ) - { - Thread.remove( t ); - return; - } - throw new ThreadException( "Unable to suspend thread" ); - } - - CONTEXT context = void; - context.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL; - - if( !GetThreadContext( t.m_hndl, &context ) ) - throw new ThreadException( "Unable to load thread context" ); - - version( X86 ) - { - if( !t.m_lock ) - t.m_curr.tstack = cast(void*) context.Esp; - // eax,ebx,ecx,edx,edi,esi,ebp,esp - t.m_reg[0] = context.Eax; - t.m_reg[1] = context.Ebx; - t.m_reg[2] = context.Ecx; - t.m_reg[3] = context.Edx; - t.m_reg[4] = context.Edi; - t.m_reg[5] = context.Esi; - t.m_reg[6] = context.Ebp; - t.m_reg[7] = context.Esp; - } - else - { - static assert( "Architecture not supported." ); - } - } - else version( OSX ) - { - if( t.m_addr != pthread_self() && thread_suspend( t.m_tmach ) != KERN_SUCCESS ) - { - if( !t.isRunning ) - { - Thread.remove( t ); - return; - } - throw new ThreadException( "Unable to suspend thread" ); - } - - version( X86 ) - { - x86_thread_state32_t state = void; - mach_msg_type_number_t count = x86_THREAD_STATE32_COUNT; - - if( thread_get_state( t.m_tmach, x86_THREAD_STATE32, &state, &count ) != KERN_SUCCESS ) - throw new ThreadException( "Unable to load thread state" ); - if( !t.m_lock ) - t.m_curr.tstack = cast(void*) state.esp; - // eax,ebx,ecx,edx,edi,esi,ebp,esp - t.m_reg[0] = state.eax; - t.m_reg[1] = state.ebx; - t.m_reg[2] = state.ecx; - t.m_reg[3] = state.edx; - t.m_reg[4] = state.edi; - t.m_reg[5] = state.esi; - t.m_reg[6] = state.ebp; - t.m_reg[7] = state.esp; - } - else version( X86_64 ) - { - x86_thread_state64_t state = void; - mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT; - - if( thread_get_state( t.m_tmach, x86_THREAD_STATE64, &state, &count ) != KERN_SUCCESS ) - throw new ThreadException( "Unable to load thread state" ); - if( !t.m_lock ) - t.m_curr.tstack = cast(void*) state.rsp; - // rax,rbx,rcx,rdx,rdi,rsi,rbp,rsp - t.m_reg[0] = state.rax; - t.m_reg[1] = state.rbx; - t.m_reg[2] = state.rcx; - t.m_reg[3] = state.rdx; - t.m_reg[4] = state.rdi; - t.m_reg[5] = state.rsi; - t.m_reg[6] = state.rbp; - t.m_reg[7] = state.rsp; - // r8,r9,r10,r11,r12,r13,r14,r15 - t.m_reg[8] = state.r8; - t.m_reg[9] = state.r9; - t.m_reg[10] = state.r10; - t.m_reg[11] = state.r11; - t.m_reg[12] = state.r12; - t.m_reg[13] = state.r13; - t.m_reg[14] = state.r14; - t.m_reg[15] = state.r15; - } - else - { - static assert( "Architecture not supported." ); - } - } - else version( Posix ) - { - if( t.m_addr != pthread_self() ) - { - if( pthread_kill( t.m_addr, SIGUSR1 ) != 0 ) - { - if( !t.isRunning ) - { - Thread.remove( t ); - return; - } - throw new ThreadException( "Unable to suspend thread" ); - } - // NOTE: It's really not ideal to wait for each thread to - // signal individually -- rather, it would be better to - // suspend them all and wait once at the end. However, - // semaphores don't really work this way, and the obvious - // alternative (looping on an atomic suspend count) - // requires either the atomic module (which only works on - // x86) or other specialized functionality. It would - // also be possible to simply loop on sem_wait at the - // end, but I'm not convinced that this would be much - // faster than the current approach. - sem_wait( &suspendCount ); - } - else if( !t.m_lock ) - { - t.m_curr.tstack = getStackTop(); - } - } - } - - - // NOTE: We've got an odd chicken & egg problem here, because while the GC - // is required to call thread_init before calling any other thread - // routines, thread_init may allocate memory which could in turn - // trigger a collection. Thus, thread_suspendAll, thread_scanAll, - // and thread_resumeAll must be callable before thread_init - // completes, with the assumption that no other GC memory has yet - // been allocated by the system, and thus there is no risk of losing - // data if the global thread list is empty. The check of - // Thread.sm_tbeg below is done to ensure thread_init has completed, - // and therefore that calling Thread.getThis will not result in an - // error. For the short time when Thread.sm_tbeg is null, there is - // no reason not to simply call the multithreaded code below, with - // the expectation that the foreach loop will never be entered. - if( !multiThreadedFlag && Thread.sm_tbeg ) - { - if( ++suspendDepth == 1 ) - suspend( Thread.getThis() ); - return; - } - synchronized( Thread.slock ) - { - if( ++suspendDepth > 1 ) - return; - - // NOTE: I'd really prefer not to check isRunning within this loop but - // not doing so could be problematic if threads are termianted - // abnormally and a new thread is created with the same thread - // address before the next GC run. This situation might cause - // the same thread to be suspended twice, which would likely - // cause the second suspend to fail, the garbage collection to - // abort, and Bad Things to occur. - for( Thread t = Thread.sm_tbeg; t; t = t.next ) - { - if( t.isRunning ) - suspend( t ); - else - Thread.remove( t ); - } - - version( Posix ) - { - // wait on semaphore -- see note in suspend for - // why this is currently not implemented - } - } -} - - -/** - * Resume all threads but the calling thread for "stop the world" garbage - * collection runs. This function must be called once for each preceding - * call to thread_suspendAll before the threads are actually resumed. - * - * In: - * This routine must be preceded by a call to thread_suspendAll. - * - * Throws: - * ThreadException if the resume operation fails for a running thread. - */ -extern (C) void thread_resumeAll() -in -{ - assert( suspendDepth > 0 ); -} -body -{ - /** - * Resume the specified thread and unload stack and register information. - * If the supplied thread is the calling thread, stack and register - * information will be unloaded but the thread will not be resumed. If - * the resume operation fails and the thread is not running then it will - * be removed from the global thread list, otherwise an exception will be - * thrown. - * - * Params: - * t = The thread to resume. - * - * Throws: - * ThreadException if the resume fails for a running thread. - */ - void resume( Thread t ) - { - version( Windows ) - { - if( t.m_addr != GetCurrentThreadId() && ResumeThread( t.m_hndl ) == 0xFFFFFFFF ) - { - if( !t.isRunning ) - { - Thread.remove( t ); - return; - } - throw new ThreadException( "Unable to resume thread" ); - } - - if( !t.m_lock ) - t.m_curr.tstack = t.m_curr.bstack; - t.m_reg[0 .. $] = 0; - } - else version( OSX ) - { - if( t.m_addr != pthread_self() && thread_resume( t.m_tmach ) != KERN_SUCCESS ) - { - if( !t.isRunning ) - { - Thread.remove( t ); - return; - } - throw new ThreadException( "Unable to resume thread" ); - } - - if( !t.m_lock ) - t.m_curr.tstack = t.m_curr.bstack; - t.m_reg[0 .. $] = 0; - } - else version( Posix ) - { - if( t.m_addr != pthread_self() ) - { - if( pthread_kill( t.m_addr, SIGUSR2 ) != 0 ) - { - if( !t.isRunning ) - { - Thread.remove( t ); - return; - } - throw new ThreadException( "Unable to resume thread" ); - } - } - else if( !t.m_lock ) - { - t.m_curr.tstack = t.m_curr.bstack; - } - } - } - - - // NOTE: See thread_suspendAll for the logic behind this. - if( !multiThreadedFlag && Thread.sm_tbeg ) - { - if( --suspendDepth == 0 ) - resume( Thread.getThis() ); - return; - } - synchronized( Thread.slock ) - { - if( --suspendDepth > 0 ) - return; - - for( Thread t = Thread.sm_tbeg; t; t = t.next ) - { - resume( t ); - } - } -} - - -private alias void delegate( void*, void* ) scanAllThreadsFn; - - -/** - * The main entry point for garbage collection. The supplied delegate - * will be passed ranges representing both stack and register values. - * - * Params: - * scan = The scanner function. It should scan from p1 through p2 - 1. - * curStackTop = An optional pointer to the top of the calling thread's stack. - * - * In: - * This routine must be preceded by a call to thread_suspendAll. - */ -extern (C) void thread_scanAll( scanAllThreadsFn scan, void* curStackTop = null ) -in -{ - assert( suspendDepth > 0 ); -} -body -{ - Thread thisThread = null; - void* oldStackTop = null; - - if( curStackTop && Thread.sm_tbeg ) - { - thisThread = Thread.getThis(); - if( !thisThread.m_lock ) - { - oldStackTop = thisThread.m_curr.tstack; - thisThread.m_curr.tstack = curStackTop; - } - } - - scope( exit ) - { - if( curStackTop && Thread.sm_tbeg ) - { - if( !thisThread.m_lock ) - { - thisThread.m_curr.tstack = oldStackTop; - } - } - } - - // NOTE: Synchronizing on Thread.slock is not needed because this - // function may only be called after all other threads have - // been suspended from within the same lock. - for( Thread.Context* c = Thread.sm_cbeg; c; c = c.next ) - { - version( StackGrowsDown ) - { - // NOTE: We can't index past the bottom of the stack - // so don't do the "+1" for StackGrowsDown. - if( c.tstack && c.tstack < c.bstack ) - scan( c.tstack, c.bstack ); - } - else - { - if( c.bstack && c.bstack < c.tstack ) - scan( c.bstack, c.tstack + 1 ); - } - } - - for( Thread t = Thread.sm_tbeg; t; t = t.next ) - { - scan( &t.m_tls[0], &t.m_tls[0] + t.m_tls.length ); - - version( Windows ) - { - scan( &t.m_reg[0], &t.m_reg[0] + t.m_reg.length ); - } - } -} - - -/////////////////////////////////////////////////////////////////////////////// -// Thread Local -/////////////////////////////////////////////////////////////////////////////// - - -/** - * This class encapsulates the operations required to initialize, access, and - * destroy thread local data. - */ -class ThreadLocal( T ) -{ - /////////////////////////////////////////////////////////////////////////// - // Initialization - /////////////////////////////////////////////////////////////////////////// - - - /** - * Initializes thread local storage for the indicated value which will be - * initialized to def for all threads. - * - * Params: - * def = The default value to return if no value has been explicitly set. - */ - this( T def = T.init ) - { - m_def = def; - m_key = Thread.createLocal(); - } - - - ~this() - { - Thread.deleteLocal( m_key ); - } - - - /////////////////////////////////////////////////////////////////////////// - // Accessors - /////////////////////////////////////////////////////////////////////////// - - - /** - * Gets the value last set by the calling thread, or def if no such value - * has been set. - * - * Returns: - * The stored value or def if no value is stored. - */ - T val() - { - Wrap* wrap = cast(Wrap*) Thread.getLocal( m_key ); - - return wrap ? wrap.val : m_def; - } - - - /** - * Copies newval to a location specific to the calling thread, and returns - * newval. - * - * Params: - * newval = The value to set. - * - * Returns: - * The value passed to this function. - */ - T val( T newval ) - { - Wrap* wrap = cast(Wrap*) Thread.getLocal( m_key ); - - if( wrap is null ) - { - wrap = new Wrap; - Thread.setLocal( m_key, wrap ); - } - wrap.val = newval; - return newval; - } - - -private: - // - // A wrapper for the stored data. This is needed for determining whether - // set has ever been called for this thread (and therefore whether the - // default value should be returned) and also to flatten the differences - // between data that is smaller and larger than (void*).sizeof. The - // obvious tradeoff here is an extra per-thread allocation for each - // ThreadLocal value as compared to calling the Thread routines directly. - // - struct Wrap - { - T val; - } - - - T m_def; - uint m_key; -} - - -/////////////////////////////////////////////////////////////////////////////// -// Thread Group -/////////////////////////////////////////////////////////////////////////////// - - -/** - * This class is intended to simplify certain common programming techniques. - */ -class ThreadGroup -{ - /** - * Creates and starts a new Thread object that executes fn and adds it to - * the list of tracked threads. - * - * Params: - * fn = The thread function. - * - * Returns: - * A reference to the newly created thread. - */ - final Thread create( void function() fn ) - { - Thread t = new Thread( fn ); - - t.start(); - synchronized( this ) - { - m_all[t] = t; - } - return t; - } - - - /** - * Creates and starts a new Thread object that executes dg and adds it to - * the list of tracked threads. - * - * Params: - * dg = The thread function. - * - * Returns: - * A reference to the newly created thread. - */ - final Thread create( void delegate() dg ) - { - Thread t = new Thread( dg ); - - t.start(); - synchronized( this ) - { - m_all[t] = t; - } - return t; - } - - - /** - * Add t to the list of tracked threads if it is not already being tracked. - * - * Params: - * t = The thread to add. - * - * In: - * t must not be null. - */ - final void add( Thread t ) - in - { - assert( t ); - } - body - { - synchronized( this ) - { - m_all[t] = t; - } - } - - - /** - * Removes t from the list of tracked threads. No operation will be - * performed if t is not currently being tracked by this object. - * - * Params: - * t = The thread to remove. - * - * In: - * t must not be null. - */ - final void remove( Thread t ) - in - { - assert( t ); - } - body - { - synchronized( this ) - { - m_all.remove( t ); - } - } - - - /** - * Operates on all threads currently tracked by this object. - */ - final int opApply( int delegate( inout Thread ) dg ) - { - synchronized( this ) - { - int ret = 0; - - // NOTE: This loop relies on the knowledge that m_all uses the - // Thread object for both the key and the mapped value. - foreach( Thread t; m_all.keys ) - { - ret = dg( t ); - if( ret ) - break; - } - return ret; - } - } - - - /** - * Iteratively joins all tracked threads. This function will block add, - * remove, and opApply until it completes. - * - * Params: - * rethrow = Rethrow any unhandled exception which may have caused the - * current thread to terminate. - * - * Throws: - * Any exception not handled by the joined threads. - */ - final void joinAll( bool rethrow = true ) - { - synchronized( this ) - { - // NOTE: This loop relies on the knowledge that m_all uses the - // Thread object for both the key and the mapped value. - foreach( Thread t; m_all.keys ) - { - t.join( rethrow ); - } - } - } - - -private: - Thread[Thread] m_all; -} - - -/////////////////////////////////////////////////////////////////////////////// -// Fiber Platform Detection and Memory Allocation -/////////////////////////////////////////////////////////////////////////////// - - -private -{ - version( D_InlineAsm_X86 ) - { - version( X86_64 ) - { - - } - else - { - version( Windows ) - version = AsmX86_Win32; - else version( Posix ) - version = AsmX86_Posix; - } - } - else version( PPC ) - { - version( Posix ) - version = AsmPPC_Posix; - } - - - version( Posix ) - { - import core.sys.posix.unistd; // for sysconf - import core.sys.posix.sys.mman; // for mmap - import core.sys.posix.stdlib; // for malloc, valloc, free - - version( AsmX86_Win32 ) {} else - version( AsmX86_Posix ) {} else - version( AsmPPC_Posix ) {} else - { - // NOTE: The ucontext implementation requires architecture specific - // data definitions to operate so testing for it must be done - // by checking for the existence of ucontext_t rather than by - // a version identifier. Please note that this is considered - // an obsolescent feature according to the POSIX spec, so a - // custom solution is still preferred. - import core.sys.posix.ucontext; - } - } - - const size_t PAGESIZE; -} - - -static this() -{ - static if( is( typeof( GetSystemInfo ) ) ) - { - SYSTEM_INFO info; - GetSystemInfo( &info ); - - PAGESIZE = info.dwPageSize; - assert( PAGESIZE < int.max ); - } - else static if( is( typeof( sysconf ) ) && - is( typeof( _SC_PAGESIZE ) ) ) - { - PAGESIZE = cast(size_t) sysconf( _SC_PAGESIZE ); - assert( PAGESIZE < int.max ); - } - else - { - version( PPC ) - PAGESIZE = 8192; - else - PAGESIZE = 4096; - } -} - - -/////////////////////////////////////////////////////////////////////////////// -// Fiber Entry Point and Context Switch -/////////////////////////////////////////////////////////////////////////////// - - -private -{ - extern (C) void fiber_entryPoint() - { - Fiber obj = Fiber.getThis(); - assert( obj ); - - assert( Thread.getThis().m_curr is obj.m_ctxt ); - volatile Thread.getThis().m_lock = false; - obj.m_ctxt.tstack = obj.m_ctxt.bstack; - obj.m_state = Fiber.State.EXEC; - - try - { - obj.run(); - } - catch( Object o ) - { - obj.m_unhandled = o; - } - - static if( is( ucontext_t ) ) - obj.m_ucur = &obj.m_utxt; - - obj.m_state = Fiber.State.TERM; - obj.switchOut(); - } - - - // NOTE: If AsmPPC_Posix is defined then the context switch routine will - // be defined externally until GDC supports inline PPC ASM. - version( AsmPPC_Posix ) - extern (C) void fiber_switchContext( void** oldp, void* newp ); - else - extern (C) void fiber_switchContext( void** oldp, void* newp ) - { - // NOTE: The data pushed and popped in this routine must match the - // default stack created by Fiber.initStack or the initial - // switch into a new context will fail. - - version( AsmX86_Win32 ) - { - asm - { - naked; - - // save current stack state - push EBP; - mov EBP, ESP; - push EAX; - push dword ptr FS:[0]; - push dword ptr FS:[4]; - push dword ptr FS:[8]; - push EBX; - push ESI; - push EDI; - - // store oldp again with more accurate address - mov EAX, dword ptr 8[EBP]; - mov [EAX], ESP; - // load newp to begin context switch - mov ESP, dword ptr 12[EBP]; - - // load saved state from new stack - pop EDI; - pop ESI; - pop EBX; - pop dword ptr FS:[8]; - pop dword ptr FS:[4]; - pop dword ptr FS:[0]; - pop EAX; - pop EBP; - - // 'return' to complete switch - ret; - } - } - else version( AsmX86_Posix ) - { - asm - { - naked; - - // save current stack state - push EBP; - mov EBP, ESP; - push EAX; - push EBX; - push ESI; - push EDI; - - // store oldp again with more accurate address - mov EAX, dword ptr 8[EBP]; - mov [EAX], ESP; - // load newp to begin context switch - mov ESP, dword ptr 12[EBP]; - - // load saved state from new stack - pop EDI; - pop ESI; - pop EBX; - pop EAX; - pop EBP; - - // 'return' to complete switch - ret; - } - } - else static if( is( ucontext_t ) ) - { - Fiber cfib = Fiber.getThis(); - void* ucur = cfib.m_ucur; - - *oldp = &ucur; - swapcontext( **(cast(ucontext_t***) oldp), - *(cast(ucontext_t**) newp) ); - } - } -} - - -/////////////////////////////////////////////////////////////////////////////// -// Fiber -/////////////////////////////////////////////////////////////////////////////// - - -/** - * This class provides a cooperative concurrency mechanism integrated with the - * threading and garbage collection functionality. Calling a fiber may be - * considered a blocking operation that returns when the fiber yields (via - * Fiber.yield()). Execution occurs within the context of the calling thread - * so synchronization is not necessary to guarantee memory visibility so long - * as the same thread calls the fiber each time. Please note that there is no - * requirement that a fiber be bound to one specific thread. Rather, fibers - * may be freely passed between threads so long as they are not currently - * executing. Like threads, a new fiber thread may be created using either - * derivation or composition, as in the following example. - * - * Example: - * ---------------------------------------------------------------------- - * - * class DerivedFiber : Fiber - * { - * this() - * { - * super( &run ); - * } - * - * private : - * void run() - * { - * printf( "Derived fiber running.\n" ); - * } - * } - * - * void fiberFunc() - * { - * printf( "Composed fiber running.\n" ); - * Fiber.yield(); - * printf( "Composed fiber running.\n" ); - * } - * - * // create instances of each type - * Fiber derived = new DerivedFiber(); - * Fiber composed = new Fiber( &fiberFunc ); - * - * // call both fibers once - * derived.call(); - * composed.call(); - * printf( "Execution returned to calling context.\n" ); - * composed.call(); - * - * // since each fiber has run to completion, each should have state TERM - * assert( derived.state == Fiber.State.TERM ); - * assert( composed.state == Fiber.State.TERM ); - * - * ---------------------------------------------------------------------- - * - * Authors: Based on a design by Mikola Lysenko. - */ -class Fiber -{ - /////////////////////////////////////////////////////////////////////////// - // Initialization - /////////////////////////////////////////////////////////////////////////// - - - /** - * Initializes a fiber object which is associated with a static - * D function. - * - * Params: - * fn = The thread function. - * sz = The stack size for this fiber. - * - * In: - * fn must not be null. - */ - this( void function() fn, size_t sz = PAGESIZE ) - in - { - assert( fn ); - } - body - { - m_fn = fn; - m_call = Call.FN; - m_state = State.HOLD; - allocStack( sz ); - initStack(); - } - - - /** - * Initializes a fiber object which is associated with a dynamic - * D function. - * - * Params: - * dg = The thread function. - * sz = The stack size for this fiber. - * - * In: - * dg must not be null. - */ - this( void delegate() dg, size_t sz = PAGESIZE ) - in - { - assert( dg ); - } - body - { - m_dg = dg; - m_call = Call.DG; - m_state = State.HOLD; - allocStack( sz ); - initStack(); - } - - - /** - * Cleans up any remaining resources used by this object. - */ - ~this() - { - // NOTE: A live reference to this object will exist on its associated - // stack from the first time its call() method has been called - // until its execution completes with State.TERM. Thus, the only - // times this dtor should be called are either if the fiber has - // terminated (and therefore has no active stack) or if the user - // explicitly deletes this object. The latter case is an error - // but is not easily tested for, since State.HOLD may imply that - // the fiber was just created but has never been run. There is - // not a compelling case to create a State.INIT just to offer a - // means of ensuring the user isn't violating this object's - // contract, so for now this requirement will be enforced by - // documentation only. - freeStack(); - } - - - /////////////////////////////////////////////////////////////////////////// - // General Actions - /////////////////////////////////////////////////////////////////////////// - - - /** - * Transfers execution to this fiber object. The calling context will be - * suspended until the fiber calls Fiber.yield() or until it terminates - * via an unhandled exception. - * - * Params: - * rethrow = Rethrow any unhandled exception which may have caused this - * fiber to terminate. - * - * In: - * This fiber must be in state HOLD. - * - * Throws: - * Any exception not handled by the joined thread. - * - * Returns: - * Any exception not handled by this fiber if rethrow = false, null - * otherwise. - */ - final Object call( bool rethrow = true ) - in - { - assert( m_state == State.HOLD ); - } - body - { - Fiber cur = getThis(); - - static if( is( ucontext_t ) ) - m_ucur = cur ? &cur.m_utxt : &Fiber.sm_utxt; - - setThis( this ); - this.switchIn(); - setThis( cur ); - - static if( is( ucontext_t ) ) - m_ucur = null; - - // NOTE: If the fiber has terminated then the stack pointers must be - // reset. This ensures that the stack for this fiber is not - // scanned if the fiber has terminated. This is necessary to - // prevent any references lingering on the stack from delaying - // the collection of otherwise dead objects. The most notable - // being the current object, which is referenced at the top of - // fiber_entryPoint. - if( m_state == State.TERM ) - { - m_ctxt.tstack = m_ctxt.bstack; - } - if( m_unhandled ) - { - Object obj = m_unhandled; - m_unhandled = null; - if( rethrow ) - throw obj; - return obj; - } - return null; - } - - - /** - * Resets this fiber so that it may be re-used. This routine may only be - * called for fibers that have terminated, as doing otherwise could result - * in scope-dependent functionality that is not executed. Stack-based - * classes, for example, may not be cleaned up properly if a fiber is reset - * before it has terminated. - * - * In: - * This fiber must be in state TERM. - */ - final void reset() - in - { - assert( m_state == State.TERM ); - assert( m_ctxt.tstack == m_ctxt.bstack ); - } - body - { - m_state = State.HOLD; - initStack(); - m_unhandled = null; - } - - - /////////////////////////////////////////////////////////////////////////// - // General Properties - /////////////////////////////////////////////////////////////////////////// - - - /** - * A fiber may occupy one of three states: HOLD, EXEC, and TERM. The HOLD - * state applies to any fiber that is suspended and ready to be called. - * The EXEC state will be set for any fiber that is currently executing. - * And the TERM state is set when a fiber terminates. Once a fiber - * terminates, it must be reset before it may be called again. - */ - enum State - { - HOLD, /// - EXEC, /// - TERM /// - } - - - /** - * Gets the current state of this fiber. - * - * Returns: - * The state of this fiber as an enumerated value. - */ - final State state() - { - return m_state; - } - - - /////////////////////////////////////////////////////////////////////////// - // Actions on Calling Fiber - /////////////////////////////////////////////////////////////////////////// - - - /** - * Forces a context switch to occur away from the calling fiber. - */ - static void yield() - { - Fiber cur = getThis(); - assert( cur, "Fiber.yield() called with no active fiber" ); - assert( cur.m_state == State.EXEC ); - - static if( is( ucontext_t ) ) - cur.m_ucur = &cur.m_utxt; - - cur.m_state = State.HOLD; - cur.switchOut(); - cur.m_state = State.EXEC; - } - - - /** - * Forces a context switch to occur away from the calling fiber and then - * throws obj in the calling fiber. - * - * Params: - * obj = The object to throw. - * - * In: - * obj must not be null. - */ - static void yieldAndThrow( Object obj ) - in - { - assert( obj ); - } - body - { - Fiber cur = getThis(); - assert( cur, "Fiber.yield() called with no active fiber" ); - assert( cur.m_state == State.EXEC ); - - static if( is( ucontext_t ) ) - cur.m_ucur = &cur.m_utxt; - - cur.m_unhandled = obj; - cur.m_state = State.HOLD; - cur.switchOut(); - cur.m_state = State.EXEC; - } - - - /////////////////////////////////////////////////////////////////////////// - // Fiber Accessors - /////////////////////////////////////////////////////////////////////////// - - - /** - * Provides a reference to the calling fiber or null if no fiber is - * currently active. - * - * Returns: - * The fiber object representing the calling fiber or null if no fiber - * is currently active. The result of deleting this object is undefined. - */ - static Fiber getThis() - { - version( Windows ) - { - return cast(Fiber) TlsGetValue( sm_this ); - } - else version( Posix ) - { - return cast(Fiber) pthread_getspecific( sm_this ); - } - } - - - /////////////////////////////////////////////////////////////////////////// - // Static Initialization - /////////////////////////////////////////////////////////////////////////// - - - static this() - { - version( Windows ) - { - sm_this = TlsAlloc(); - assert( sm_this != TLS_OUT_OF_INDEXES ); - } - else version( Posix ) - { - int status; - - status = pthread_key_create( &sm_this, null ); - assert( status == 0 ); - - static if( is( ucontext_t ) ) - { - status = getcontext( &sm_utxt ); - assert( status == 0 ); - } - } - } - - -private: - // - // Initializes a fiber object which has no associated executable function. - // - this() - { - m_call = Call.NO; - } - - - // - // Fiber entry point. Invokes the function or delegate passed on - // construction (if any). - // - final void run() - { - switch( m_call ) - { - case Call.FN: - m_fn(); - break; - case Call.DG: - m_dg(); - break; - default: - break; - } - } - - -private: - // - // The type of routine passed on fiber construction. - // - enum Call - { - NO, - FN, - DG - } - - - // - // Standard fiber data - // - Call m_call; - union - { - void function() m_fn; - void delegate() m_dg; - } - bool m_isRunning; - Object m_unhandled; - State m_state; - - -private: - /////////////////////////////////////////////////////////////////////////// - // Stack Management - /////////////////////////////////////////////////////////////////////////// - - - // - // Allocate a new stack for this fiber. - // - final void allocStack( size_t sz ) - in - { - assert( !m_pmem && !m_ctxt ); - } - body - { - // adjust alloc size to a multiple of PAGESIZE - sz += PAGESIZE - 1; - sz -= sz % PAGESIZE; - - // NOTE: This instance of Thread.Context is dynamic so Fiber objects - // can be collected by the GC so long as no user level references - // to the object exist. If m_ctxt were not dynamic then its - // presence in the global context list would be enough to keep - // this object alive indefinitely. An alternative to allocating - // room for this struct explicitly would be to mash it into the - // base of the stack being allocated below. However, doing so - // requires too much special logic to be worthwhile. - m_ctxt = new Thread.Context; - - static if( is( typeof( VirtualAlloc ) ) ) - { - // reserve memory for stack - m_pmem = VirtualAlloc( null, - sz + PAGESIZE, - MEM_RESERVE, - PAGE_NOACCESS ); - if( !m_pmem ) - { - throw new FiberException( "Unable to reserve memory for stack" ); - } - - version( StackGrowsDown ) - { - void* stack = m_pmem + PAGESIZE; - void* guard = m_pmem; - void* pbase = stack + sz; - } - else - { - void* stack = m_pmem; - void* guard = m_pmem + sz; - void* pbase = stack; - } - - // allocate reserved stack segment - stack = VirtualAlloc( stack, - sz, - MEM_COMMIT, - PAGE_READWRITE ); - if( !stack ) - { - throw new FiberException( "Unable to allocate memory for stack" ); - } - - // allocate reserved guard page - guard = VirtualAlloc( guard, - PAGESIZE, - MEM_COMMIT, - PAGE_READWRITE | PAGE_GUARD ); - if( !guard ) - { - throw new FiberException( "Unable to create guard page for stack" ); - } - - m_ctxt.bstack = pbase; - m_ctxt.tstack = pbase; - m_size = sz; - } - else - { static if( is( typeof( mmap ) ) ) - { - m_pmem = mmap( null, - sz, - PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANON, - -1, - 0 ); - if( m_pmem == MAP_FAILED ) - m_pmem = null; - } - else static if( is( typeof( valloc ) ) ) - { - m_pmem = valloc( sz ); - } - else static if( is( typeof( malloc ) ) ) - { - m_pmem = malloc( sz ); - } - else - { - m_pmem = null; - } - - if( !m_pmem ) - { - throw new FiberException( "Unable to allocate memory for stack" ); - } - - version( StackGrowsDown ) - { - m_ctxt.bstack = m_pmem + sz; - m_ctxt.tstack = m_pmem + sz; - } - else - { - m_ctxt.bstack = m_pmem; - m_ctxt.tstack = m_pmem; - } - m_size = sz; - } - - Thread.add( m_ctxt ); - } - - - // - // Free this fiber's stack. - // - final void freeStack() - in - { - assert( m_pmem && m_ctxt ); - } - body - { - // NOTE: Since this routine is only ever expected to be called from - // the dtor, pointers to freed data are not set to null. - - // NOTE: m_ctxt is guaranteed to be alive because it is held in the - // global context list. - Thread.remove( m_ctxt ); - - static if( is( typeof( VirtualAlloc ) ) ) - { - VirtualFree( m_pmem, 0, MEM_RELEASE ); - } - else static if( is( typeof( mmap ) ) ) - { - munmap( m_pmem, m_size ); - } - else static if( is( typeof( valloc ) ) ) - { - free( m_pmem ); - } - else static if( is( typeof( malloc ) ) ) - { - free( m_pmem ); - } - delete m_ctxt; - } - - - // - // Initialize the allocated stack. - // - final void initStack() - in - { - assert( m_ctxt.tstack && m_ctxt.tstack == m_ctxt.bstack ); - assert( cast(size_t) m_ctxt.bstack % (void*).sizeof == 0 ); - } - body - { - void* pstack = m_ctxt.tstack; - scope( exit ) m_ctxt.tstack = pstack; - - void push( size_t val ) - { - version( StackGrowsDown ) - { - pstack -= size_t.sizeof; - *(cast(size_t*) pstack) = val; - } - else - { - pstack += size_t.sizeof; - *(cast(size_t*) pstack) = val; - } - } - - // NOTE: On OS X the stack must be 16-byte aligned according to the - // IA-32 call spec. - version( OSX ) - { - version( StackGrowsDown ) - { - pstack = cast(void*)(cast(uint)(pstack) - (cast(uint)(pstack) & 0x0F)); - } - else - { - pstack = cast(void*)(cast(uint)(pstack) + (cast(uint)(pstack) & 0x0F)); - } - } - - version( AsmX86_Win32 ) - { - push( cast(size_t) &fiber_entryPoint ); // EIP - push( 0xFFFFFFFF ); // EBP - push( 0x00000000 ); // EAX - push( 0xFFFFFFFF ); // FS:[0] - version( StackGrowsDown ) - { - push( cast(size_t) m_ctxt.bstack ); // FS:[4] - push( cast(size_t) m_ctxt.bstack - m_size ); // FS:[8] - } - else - { - push( cast(size_t) m_ctxt.bstack ); // FS:[4] - push( cast(size_t) m_ctxt.bstack + m_size ); // FS:[8] - } - push( 0x00000000 ); // EBX - push( 0x00000000 ); // ESI - push( 0x00000000 ); // EDI - } - else version( AsmX86_Posix ) - { - push( 0x00000000 ); // Pad stack for OSX - push( cast(size_t) &fiber_entryPoint ); // EIP - push( 0x00000000 ); // EBP - push( 0x00000000 ); // EAX - push( 0x00000000 ); // EBX - push( 0x00000000 ); // ESI - push( 0x00000000 ); // EDI - } - else version( AsmPPC_Posix ) - { - version( StackGrowsDown ) - { - pstack -= int.sizeof * 5; - } - else - { - pstack += int.sizeof * 5; - } - - push( cast(size_t) &fiber_entryPoint ); // link register - push( 0x00000000 ); // control register - push( 0x00000000 ); // old stack pointer - - // GPR values - version( StackGrowsDown ) - { - pstack -= int.sizeof * 20; - } - else - { - pstack += int.sizeof * 20; - } - - assert( cast(uint) pstack & 0x0f == 0 ); - } - else static if( is( ucontext_t ) ) - { - getcontext( &m_utxt ); - m_utxt.uc_stack.ss_sp = m_ctxt.bstack; - m_utxt.uc_stack.ss_size = m_size; - makecontext( &m_utxt, &fiber_entryPoint, 0 ); - // NOTE: If ucontext is being used then the top of the stack will - // be a pointer to the ucontext_t struct for that fiber. - push( cast(size_t) &m_utxt ); - } - } - - - Thread.Context* m_ctxt; - size_t m_size; - void* m_pmem; - - static if( is( ucontext_t ) ) - { - // NOTE: The static ucontext instance is used to represent the context - // of the main application thread. - static ucontext_t sm_utxt = void; - ucontext_t m_utxt = void; - ucontext_t* m_ucur = null; - } - - -private: - /////////////////////////////////////////////////////////////////////////// - // Storage of Active Fiber - /////////////////////////////////////////////////////////////////////////// - - - // - // Sets a thread-local reference to the current fiber object. - // - static void setThis( Fiber f ) - { - version( Windows ) - { - TlsSetValue( sm_this, cast(void*) f ); - } - else version( Posix ) - { - pthread_setspecific( sm_this, cast(void*) f ); - } - } - - - __gshared Thread.TLSKey sm_this; - - -private: - /////////////////////////////////////////////////////////////////////////// - // Context Switching - /////////////////////////////////////////////////////////////////////////// - - - // - // Switches into the stack held by this fiber. - // - final void switchIn() - { - Thread tobj = Thread.getThis(); - void** oldp = &tobj.m_curr.tstack; - void* newp = m_ctxt.tstack; - - // NOTE: The order of operations here is very important. The current - // stack top must be stored before m_lock is set, and pushContext - // must not be called until after m_lock is set. This process - // is intended to prevent a race condition with the suspend - // mechanism used for garbage collection. If it is not followed, - // a badly timed collection could cause the GC to scan from the - // bottom of one stack to the top of another, or to miss scanning - // a stack that still contains valid data. The old stack pointer - // oldp will be set again before the context switch to guarantee - // that it points to exactly the correct stack location so the - // successive pop operations will succeed. - *oldp = getStackTop(); - volatile tobj.m_lock = true; - tobj.pushContext( m_ctxt ); - - fiber_switchContext( oldp, newp ); - - // NOTE: As above, these operations must be performed in a strict order - // to prevent Bad Things from happening. - tobj.popContext(); - volatile tobj.m_lock = false; - tobj.m_curr.tstack = tobj.m_curr.bstack; - } - - - // - // Switches out of the current stack and into the enclosing stack. - // - final void switchOut() - { - Thread tobj = Thread.getThis(); - void** oldp = &m_ctxt.tstack; - void* newp = tobj.m_curr.within.tstack; - - // NOTE: The order of operations here is very important. The current - // stack top must be stored before m_lock is set, and pushContext - // must not be called until after m_lock is set. This process - // is intended to prevent a race condition with the suspend - // mechanism used for garbage collection. If it is not followed, - // a badly timed collection could cause the GC to scan from the - // bottom of one stack to the top of another, or to miss scanning - // a stack that still contains valid data. The old stack pointer - // oldp will be set again before the context switch to guarantee - // that it points to exactly the correct stack location so the - // successive pop operations will succeed. - *oldp = getStackTop(); - volatile tobj.m_lock = true; - - fiber_switchContext( oldp, newp ); - - // NOTE: As above, these operations must be performed in a strict order - // to prevent Bad Things from happening. - volatile tobj.m_lock = false; - tobj.m_curr.tstack = tobj.m_curr.bstack; - } -} - -version (OSX) -{ - /* The Mach-O object file format does not allow for thread local storage - * declarations. So, instead we roll our own by putting tls into - * the sections __tlsdata and __tlscoal_nt. - */ - - extern (D) - void* ___tls_get_addr(void* p) - { - return p; - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/common/core/threadasm.S --- a/druntime/src/common/core/threadasm.S Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,143 +0,0 @@ -/** - * Support code for mutithreading. - * - * Copyright: Copyright Mikola Lysenko 2005 - 2009. - * License: Boost License 1.0. - * Authors: Walter Bright - * - * Copyright Digital Mars 2004 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module rt.aApply; - -private import rt.util.utf; - -/********************************************** - */ - -// dg is D, but _aApplycd() is C -extern (D) typedef int delegate(void *) dg_t; - -extern (C) int _aApplycd1(char[] aa, dg_t dg) -{ int result; - size_t i; - size_t len = aa.length; - - debug(apply) printf("_aApplycd1(), len = %d\n", len); - for (i = 0; i < len; ) - { dchar d; - - d = aa[i]; - if (d & 0x80) - d = decode(aa, i); - else - i++; - result = dg(cast(void *)&d); - if (result) - break; - } - return result; -} - -extern (C) int _aApplywd1(wchar[] aa, dg_t dg) -{ int result; - size_t i; - size_t len = aa.length; - - debug(apply) printf("_aApplywd1(), len = %d\n", len); - for (i = 0; i < len; ) - { dchar d; - - d = aa[i]; - if (d & ~0x7F) - d = decode(aa, i); - else - i++; - result = dg(cast(void *)&d); - if (result) - break; - } - return result; -} - -extern (C) int _aApplycw1(char[] aa, dg_t dg) -{ int result; - size_t i; - size_t len = aa.length; - - debug(apply) printf("_aApplycw1(), len = %d\n", len); - for (i = 0; i < len; ) - { dchar d; - wchar w; - - w = aa[i]; - if (w & 0x80) - { d = decode(aa, i); - if (d <= 0xFFFF) - w = cast(wchar) d; - else - { - w = cast(wchar)((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); - result = dg(cast(void *)&w); - if (result) - break; - w = cast(wchar)(((d - 0x10000) & 0x3FF) + 0xDC00); - } - } - else - i++; - result = dg(cast(void *)&w); - if (result) - break; - } - return result; -} - -extern (C) int _aApplywc1(wchar[] aa, dg_t dg) -{ int result; - size_t i; - size_t len = aa.length; - - debug(apply) printf("_aApplywc1(), len = %d\n", len); - for (i = 0; i < len; ) - { dchar d; - wchar w; - char c; - - w = aa[i]; - if (w & ~0x7F) - { - char[4] buf; - - d = decode(aa, i); - auto b = toUTF8(buf, d); - foreach (char c2; b) - { - result = dg(cast(void *)&c2); - if (result) - return result; - } - continue; - } - else - { c = cast(char)w; - i++; - } - result = dg(cast(void *)&c); - if (result) - break; - } - return result; -} - -extern (C) int _aApplydc1(dchar[] aa, dg_t dg) -{ int result; - - debug(apply) printf("_aApplydc1(), len = %d\n", aa.length); - foreach (dchar d; aa) - { - char c; - - if (d & ~0x7F) - { - char[4] buf; - - auto b = toUTF8(buf, d); - foreach (char c2; b) - { - result = dg(cast(void *)&c2); - if (result) - return result; - } - continue; - } - else - { - c = cast(char)d; - } - result = dg(cast(void *)&c); - if (result) - break; - } - return result; -} - -extern (C) int _aApplydw1(dchar[] aa, dg_t dg) -{ int result; - - debug(apply) printf("_aApplydw1(), len = %d\n", aa.length); - foreach (dchar d; aa) - { - wchar w; - - if (d <= 0xFFFF) - w = cast(wchar) d; - else - { - w = cast(wchar)((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); - result = dg(cast(void *)&w); - if (result) - break; - w = cast(wchar)(((d - 0x10000) & 0x3FF) + 0xDC00); - } - result = dg(cast(void *)&w); - if (result) - break; - } - return result; -} - - -/****************************************************************************/ - -// dg is D, but _aApplycd2() is C -extern (D) typedef int delegate(void *, void *) dg2_t; - -extern (C) int _aApplycd2(char[] aa, dg2_t dg) -{ int result; - size_t i; - size_t n; - size_t len = aa.length; - - debug(apply) printf("_aApplycd2(), len = %d\n", len); - for (i = 0; i < len; i += n) - { dchar d; - - d = aa[i]; - if (d & 0x80) - { - n = i; - d = decode(aa, n); - n -= i; - } - else - n = 1; - result = dg(&i, cast(void *)&d); - if (result) - break; - } - return result; -} - -extern (C) int _aApplywd2(wchar[] aa, dg2_t dg) -{ int result; - size_t i; - size_t n; - size_t len = aa.length; - - debug(apply) printf("_aApplywd2(), len = %d\n", len); - for (i = 0; i < len; i += n) - { dchar d; - - d = aa[i]; - if (d & ~0x7F) - { - n = i; - d = decode(aa, n); - n -= i; - } - else - n = 1; - result = dg(&i, cast(void *)&d); - if (result) - break; - } - return result; -} - -extern (C) int _aApplycw2(char[] aa, dg2_t dg) -{ int result; - size_t i; - size_t n; - size_t len = aa.length; - - debug(apply) printf("_aApplycw2(), len = %d\n", len); - for (i = 0; i < len; i += n) - { dchar d; - wchar w; - - w = aa[i]; - if (w & 0x80) - { n = i; - d = decode(aa, n); - n -= i; - if (d <= 0xFFFF) - w = cast(wchar) d; - else - { - w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); - result = dg(&i, cast(void *)&w); - if (result) - break; - w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00); - } - } - else - n = 1; - result = dg(&i, cast(void *)&w); - if (result) - break; - } - return result; -} - -extern (C) int _aApplywc2(wchar[] aa, dg2_t dg) -{ int result; - size_t i; - size_t n; - size_t len = aa.length; - - debug(apply) printf("_aApplywc2(), len = %d\n", len); - for (i = 0; i < len; i += n) - { dchar d; - wchar w; - char c; - - w = aa[i]; - if (w & ~0x7F) - { - char[4] buf; - - n = i; - d = decode(aa, n); - n -= i; - auto b = toUTF8(buf, d); - foreach (char c2; b) - { - result = dg(&i, cast(void *)&c2); - if (result) - return result; - } - continue; - } - else - { c = cast(char)w; - n = 1; - } - result = dg(&i, cast(void *)&c); - if (result) - break; - } - return result; -} - -extern (C) int _aApplydc2(dchar[] aa, dg2_t dg) -{ int result; - size_t i; - size_t len = aa.length; - - debug(apply) printf("_aApplydc2(), len = %d\n", len); - for (i = 0; i < len; i++) - { dchar d; - char c; - - d = aa[i]; - if (d & ~0x7F) - { - char[4] buf; - - auto b = toUTF8(buf, d); - foreach (char c2; b) - { - result = dg(&i, cast(void *)&c2); - if (result) - return result; - } - continue; - } - else - { c = cast(char)d; - } - result = dg(&i, cast(void *)&c); - if (result) - break; - } - return result; -} - -extern (C) int _aApplydw2(dchar[] aa, dg2_t dg) -{ int result; - - debug(apply) printf("_aApplydw2(), len = %d\n", aa.length); - foreach (size_t i, dchar d; aa) - { - wchar w; - auto j = i; - - if (d <= 0xFFFF) - w = cast(wchar) d; - else - { - w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); - result = dg(&j, cast(void *)&w); - if (result) - break; - w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00); - } - result = dg(&j, cast(void *)&w); - if (result) - break; - } - return result; -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/aApplyR.d --- a/druntime/src/compiler/dmd/aApplyR.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,957 +0,0 @@ -/** - * This code handles decoding UTF strings for foreach_reverse loops. There are - * 6 combinations of conversions between char, wchar, and dchar, and 2 of each - * of those. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: >= 1; - c = aa[i]; - } - d |= (c & m) << j; - } - result = dg(cast(void *)&d); - if (result) - break; - } - return result; -} - -unittest -{ - debug(apply) printf("_aApplyRcd1.unittest\n"); - - auto s = "hello"c[]; - int i; - - foreach_reverse(dchar d; s) - { - switch (i) - { - case 0: assert(d == 'o'); break; - case 1: assert(d == 'l'); break; - case 2: assert(d == 'l'); break; - case 3: assert(d == 'e'); break; - case 4: assert(d == 'h'); break; - default: assert(0); - } - i++; - } - assert(i == 5); - - s = "a\u1234\U00100456b"; - i = 0; - foreach_reverse(dchar d; s) - { - //printf("i = %d, d = %x\n", i, d); - switch (i) - { - case 0: assert(d == 'b'); break; - case 1: assert(d == '\U00100456'); break; - case 2: assert(d == '\u1234'); break; - case 3: assert(d == 'a'); break; - default: assert(0); - } - i++; - } - assert(i == 4); -} - -/*****************************/ - -extern (C) int _aApplyRwd1(in wchar[] aa, dg_t dg) -{ int result; - - debug(apply) printf("_aApplyRwd1(), len = %d\n", aa.length); - for (size_t i = aa.length; i != 0; ) - { dchar d; - - i--; - d = aa[i]; - if (d >= 0xDC00 && d <= 0xDFFF) - { if (i == 0) - onUnicodeError("Invalid UTF-16 sequence", 0); - i--; - d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00); - } - result = dg(cast(void *)&d); - if (result) - break; - } - return result; -} - -unittest -{ - debug(apply) printf("_aApplyRwd1.unittest\n"); - - auto s = "hello"w[]; - int i; - - foreach_reverse(dchar d; s) - { - switch (i) - { - case 0: assert(d == 'o'); break; - case 1: assert(d == 'l'); break; - case 2: assert(d == 'l'); break; - case 3: assert(d == 'e'); break; - case 4: assert(d == 'h'); break; - default: assert(0); - } - i++; - } - assert(i == 5); - - s = "a\u1234\U00100456b"; - i = 0; - foreach_reverse(dchar d; s) - { - //printf("i = %d, d = %x\n", i, d); - switch (i) - { - case 0: assert(d == 'b'); break; - case 1: assert(d == '\U00100456'); break; - case 2: assert(d == '\u1234'); break; - case 3: assert(d == 'a'); break; - default: assert(0); - } - i++; - } - assert(i == 4); -} - -/*****************************/ - -extern (C) int _aApplyRcw1(in char[] aa, dg_t dg) -{ int result; - - debug(apply) printf("_aApplyRcw1(), len = %d\n", aa.length); - for (size_t i = aa.length; i != 0; ) - { dchar d; - wchar w; - - i--; - w = aa[i]; - if (w & 0x80) - { char c = cast(char)w; - uint j; - uint m = 0x3F; - d = 0; - while ((c & 0xC0) != 0xC0) - { if (i == 0) - onUnicodeError("Invalid UTF-8 sequence", 0); - i--; - d |= (c & 0x3F) << j; - j += 6; - m >>= 1; - c = aa[i]; - } - d |= (c & m) << j; - - if (d <= 0xFFFF) - w = cast(wchar) d; - else - { - w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); - result = dg(cast(void *)&w); - if (result) - break; - w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00); - } - } - result = dg(cast(void *)&w); - if (result) - break; - } - return result; -} - -unittest -{ - debug(apply) printf("_aApplyRcw1.unittest\n"); - - auto s = "hello"c[]; - int i; - - foreach_reverse(wchar d; s) - { - switch (i) - { - case 0: assert(d == 'o'); break; - case 1: assert(d == 'l'); break; - case 2: assert(d == 'l'); break; - case 3: assert(d == 'e'); break; - case 4: assert(d == 'h'); break; - default: assert(0); - } - i++; - } - assert(i == 5); - - s = "a\u1234\U00100456b"; - i = 0; - foreach_reverse(wchar d; s) - { - //printf("i = %d, d = %x\n", i, d); - switch (i) - { - case 0: assert(d == 'b'); break; - case 1: assert(d == 0xDBC1); break; - case 2: assert(d == 0xDC56); break; - case 3: assert(d == 0x1234); break; - case 4: assert(d == 'a'); break; - default: assert(0); - } - i++; - } - assert(i == 5); -} - -/*****************************/ - -extern (C) int _aApplyRwc1(in wchar[] aa, dg_t dg) -{ int result; - - debug(apply) printf("_aApplyRwc1(), len = %d\n", aa.length); - for (size_t i = aa.length; i != 0; ) - { dchar d; - char c; - - i--; - d = aa[i]; - if (d >= 0xDC00 && d <= 0xDFFF) - { if (i == 0) - onUnicodeError("Invalid UTF-16 sequence", 0); - i--; - d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00); - } - - if (d & ~0x7F) - { - char[4] buf; - - auto b = toUTF8(buf, d); - foreach (char c2; b) - { - result = dg(cast(void *)&c2); - if (result) - return result; - } - continue; - } - c = cast(char)d; - result = dg(cast(void *)&c); - if (result) - break; - } - return result; -} - -unittest -{ - debug(apply) printf("_aApplyRwc1.unittest\n"); - - auto s = "hello"w[]; - int i; - - foreach_reverse(char d; s) - { - switch (i) - { - case 0: assert(d == 'o'); break; - case 1: assert(d == 'l'); break; - case 2: assert(d == 'l'); break; - case 3: assert(d == 'e'); break; - case 4: assert(d == 'h'); break; - default: assert(0); - } - i++; - } - assert(i == 5); - - s = "a\u1234\U00100456b"; - i = 0; - foreach_reverse(char d; s) - { - //printf("i = %d, d = %x\n", i, d); - switch (i) - { - case 0: assert(d == 'b'); break; - case 1: assert(d == 0xF4); break; - case 2: assert(d == 0x80); break; - case 3: assert(d == 0x91); break; - case 4: assert(d == 0x96); break; - case 5: assert(d == 0xE1); break; - case 6: assert(d == 0x88); break; - case 7: assert(d == 0xB4); break; - case 8: assert(d == 'a'); break; - default: assert(0); - } - i++; - } - assert(i == 9); -} - -/*****************************/ - -extern (C) int _aApplyRdc1(in dchar[] aa, dg_t dg) -{ int result; - - debug(apply) printf("_aApplyRdc1(), len = %d\n", aa.length); - for (size_t i = aa.length; i != 0;) - { dchar d = aa[--i]; - char c; - - if (d & ~0x7F) - { - char[4] buf; - - auto b = toUTF8(buf, d); - foreach (char c2; b) - { - result = dg(cast(void *)&c2); - if (result) - return result; - } - continue; - } - else - { - c = cast(char)d; - } - result = dg(cast(void *)&c); - if (result) - break; - } - return result; -} - -unittest -{ - debug(apply) printf("_aApplyRdc1.unittest\n"); - - auto s = "hello"d[]; - int i; - - foreach_reverse(char d; s) - { - switch (i) - { - case 0: assert(d == 'o'); break; - case 1: assert(d == 'l'); break; - case 2: assert(d == 'l'); break; - case 3: assert(d == 'e'); break; - case 4: assert(d == 'h'); break; - default: assert(0); - } - i++; - } - assert(i == 5); - - s = "a\u1234\U00100456b"; - i = 0; - foreach_reverse(char d; s) - { - //printf("i = %d, d = %x\n", i, d); - switch (i) - { - case 0: assert(d == 'b'); break; - case 1: assert(d == 0xF4); break; - case 2: assert(d == 0x80); break; - case 3: assert(d == 0x91); break; - case 4: assert(d == 0x96); break; - case 5: assert(d == 0xE1); break; - case 6: assert(d == 0x88); break; - case 7: assert(d == 0xB4); break; - case 8: assert(d == 'a'); break; - default: assert(0); - } - i++; - } - assert(i == 9); -} - -/*****************************/ - -extern (C) int _aApplyRdw1(in dchar[] aa, dg_t dg) -{ int result; - - debug(apply) printf("_aApplyRdw1(), len = %d\n", aa.length); - for (size_t i = aa.length; i != 0; ) - { dchar d = aa[--i]; - wchar w; - - if (d <= 0xFFFF) - w = cast(wchar) d; - else - { - w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); - result = dg(cast(void *)&w); - if (result) - break; - w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00); - } - result = dg(cast(void *)&w); - if (result) - break; - } - return result; -} - -unittest -{ - debug(apply) printf("_aApplyRdw1.unittest\n"); - - auto s = "hello"d[]; - int i; - - foreach_reverse(wchar d; s) - { - switch (i) - { - case 0: assert(d == 'o'); break; - case 1: assert(d == 'l'); break; - case 2: assert(d == 'l'); break; - case 3: assert(d == 'e'); break; - case 4: assert(d == 'h'); break; - default: assert(0); - } - i++; - } - assert(i == 5); - - s = "a\u1234\U00100456b"; - i = 0; - foreach_reverse(wchar d; s) - { - //printf("i = %d, d = %x\n", i, d); - switch (i) - { - case 0: assert(d == 'b'); break; - case 1: assert(d == 0xDBC1); break; - case 2: assert(d == 0xDC56); break; - case 3: assert(d == 0x1234); break; - case 4: assert(d == 'a'); break; - default: assert(0); - } - i++; - } - assert(i == 5); -} - - -/****************************************************************************/ -/* 2 argument versions */ - -// dg is D, but _aApplyRcd2() is C -extern (D) typedef int delegate(void *, void *) dg2_t; - -extern (C) int _aApplyRcd2(in char[] aa, dg2_t dg) -{ int result; - size_t i; - size_t len = aa.length; - - debug(apply) printf("_aApplyRcd2(), len = %d\n", len); - for (i = len; i != 0; ) - { dchar d; - - i--; - d = aa[i]; - if (d & 0x80) - { char c = cast(char)d; - uint j; - uint m = 0x3F; - d = 0; - while ((c & 0xC0) != 0xC0) - { if (i == 0) - onUnicodeError("Invalid UTF-8 sequence", 0); - i--; - d |= (c & 0x3F) << j; - j += 6; - m >>= 1; - c = aa[i]; - } - d |= (c & m) << j; - } - result = dg(&i, cast(void *)&d); - if (result) - break; - } - return result; -} - -unittest -{ - debug(apply) printf("_aApplyRcd2.unittest\n"); - - auto s = "hello"c[]; - int i; - - foreach_reverse(k, dchar d; s) - { - assert(k == 4 - i); - switch (i) - { - case 0: assert(d == 'o'); break; - case 1: assert(d == 'l'); break; - case 2: assert(d == 'l'); break; - case 3: assert(d == 'e'); break; - case 4: assert(d == 'h'); break; - default: assert(0); - } - i++; - } - assert(i == 5); - - s = "a\u1234\U00100456b"; - i = 0; - foreach_reverse(k, dchar d; s) - { - //printf("i = %d, k = %d, d = %x\n", i, k, d); - switch (i) - { - case 0: assert(d == 'b'); assert(k == 8); break; - case 1: assert(d == '\U00100456'); assert(k == 4); break; - case 2: assert(d == '\u1234'); assert(k == 1); break; - case 3: assert(d == 'a'); assert(k == 0); break; - default: assert(0); - } - i++; - } - assert(i == 4); -} - -/*****************************/ - -extern (C) int _aApplyRwd2(in wchar[] aa, dg2_t dg) -{ int result; - - debug(apply) printf("_aApplyRwd2(), len = %d\n", aa.length); - for (size_t i = aa.length; i != 0; ) - { dchar d; - - i--; - d = aa[i]; - if (d >= 0xDC00 && d <= 0xDFFF) - { if (i == 0) - onUnicodeError("Invalid UTF-16 sequence", 0); - i--; - d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00); - } - result = dg(&i, cast(void *)&d); - if (result) - break; - } - return result; -} - -unittest -{ - debug(apply) printf("_aApplyRwd2.unittest\n"); - - auto s = "hello"w[]; - int i; - - foreach_reverse(k, dchar d; s) - { - //printf("i = %d, k = %d, d = %x\n", i, k, d); - assert(k == 4 - i); - switch (i) - { - case 0: assert(d == 'o'); break; - case 1: assert(d == 'l'); break; - case 2: assert(d == 'l'); break; - case 3: assert(d == 'e'); break; - case 4: assert(d == 'h'); break; - default: assert(0); - } - i++; - } - assert(i == 5); - - s = "a\u1234\U00100456b"; - i = 0; - foreach_reverse(k, dchar d; s) - { - //printf("i = %d, k = %d, d = %x\n", i, k, d); - switch (i) - { - case 0: assert(k == 4); assert(d == 'b'); break; - case 1: assert(k == 2); assert(d == '\U00100456'); break; - case 2: assert(k == 1); assert(d == '\u1234'); break; - case 3: assert(k == 0); assert(d == 'a'); break; - default: assert(0); - } - i++; - } - assert(i == 4); -} - -/*****************************/ - -extern (C) int _aApplyRcw2(in char[] aa, dg2_t dg) -{ int result; - - debug(apply) printf("_aApplyRcw2(), len = %d\n", aa.length); - for (size_t i = aa.length; i != 0; ) - { dchar d; - wchar w; - - i--; - w = aa[i]; - if (w & 0x80) - { char c = cast(char)w; - uint j; - uint m = 0x3F; - d = 0; - while ((c & 0xC0) != 0xC0) - { if (i == 0) - onUnicodeError("Invalid UTF-8 sequence", 0); - i--; - d |= (c & 0x3F) << j; - j += 6; - m >>= 1; - c = aa[i]; - } - d |= (c & m) << j; - - if (d <= 0xFFFF) - w = cast(wchar) d; - else - { - w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); - result = dg(&i, cast(void *)&w); - if (result) - break; - w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00); - } - } - result = dg(&i, cast(void *)&w); - if (result) - break; - } - return result; -} - -unittest -{ - debug(apply) printf("_aApplyRcw2.unittest\n"); - - auto s = "hello"c[]; - int i; - - foreach_reverse(k, wchar d; s) - { - //printf("i = %d, k = %d, d = %x\n", i, k, d); - assert(k == 4 - i); - switch (i) - { - case 0: assert(d == 'o'); break; - case 1: assert(d == 'l'); break; - case 2: assert(d == 'l'); break; - case 3: assert(d == 'e'); break; - case 4: assert(d == 'h'); break; - default: assert(0); - } - i++; - } - assert(i == 5); - - s = "a\u1234\U00100456b"; - i = 0; - foreach_reverse(k, wchar d; s) - { - //printf("i = %d, k = %d, d = %x\n", i, k, d); - switch (i) - { - case 0: assert(k == 8); assert(d == 'b'); break; - case 1: assert(k == 4); assert(d == 0xDBC1); break; - case 2: assert(k == 4); assert(d == 0xDC56); break; - case 3: assert(k == 1); assert(d == 0x1234); break; - case 4: assert(k == 0); assert(d == 'a'); break; - default: assert(0); - } - i++; - } - assert(i == 5); -} - -/*****************************/ - -extern (C) int _aApplyRwc2(in wchar[] aa, dg2_t dg) -{ int result; - - debug(apply) printf("_aApplyRwc2(), len = %d\n", aa.length); - for (size_t i = aa.length; i != 0; ) - { dchar d; - char c; - - i--; - d = aa[i]; - if (d >= 0xDC00 && d <= 0xDFFF) - { if (i == 0) - onUnicodeError("Invalid UTF-16 sequence", 0); - i--; - d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00); - } - - if (d & ~0x7F) - { - char[4] buf; - - auto b = toUTF8(buf, d); - foreach (char c2; b) - { - result = dg(&i, cast(void *)&c2); - if (result) - return result; - } - continue; - } - c = cast(char)d; - result = dg(&i, cast(void *)&c); - if (result) - break; - } - return result; -} - -unittest -{ - debug(apply) printf("_aApplyRwc2.unittest\n"); - - auto s = "hello"w[]; - int i; - - foreach_reverse(k, char d; s) - { - //printf("i = %d, k = %d, d = %x\n", i, k, d); - assert(k == 4 - i); - switch (i) - { - case 0: assert(d == 'o'); break; - case 1: assert(d == 'l'); break; - case 2: assert(d == 'l'); break; - case 3: assert(d == 'e'); break; - case 4: assert(d == 'h'); break; - default: assert(0); - } - i++; - } - assert(i == 5); - - s = "a\u1234\U00100456b"; - i = 0; - foreach_reverse(k, char d; s) - { - //printf("i = %d, k = %d, d = %x\n", i, k, d); - switch (i) - { - case 0: assert(k == 4); assert(d == 'b'); break; - case 1: assert(k == 2); assert(d == 0xF4); break; - case 2: assert(k == 2); assert(d == 0x80); break; - case 3: assert(k == 2); assert(d == 0x91); break; - case 4: assert(k == 2); assert(d == 0x96); break; - case 5: assert(k == 1); assert(d == 0xE1); break; - case 6: assert(k == 1); assert(d == 0x88); break; - case 7: assert(k == 1); assert(d == 0xB4); break; - case 8: assert(k == 0); assert(d == 'a'); break; - default: assert(0); - } - i++; - } - assert(i == 9); -} - -/*****************************/ - -extern (C) int _aApplyRdc2(in dchar[] aa, dg2_t dg) -{ int result; - - debug(apply) printf("_aApplyRdc2(), len = %d\n", aa.length); - for (size_t i = aa.length; i != 0; ) - { dchar d = aa[--i]; - char c; - - if (d & ~0x7F) - { - char[4] buf; - - auto b = toUTF8(buf, d); - foreach (char c2; b) - { - result = dg(&i, cast(void *)&c2); - if (result) - return result; - } - continue; - } - else - { c = cast(char)d; - } - result = dg(&i, cast(void *)&c); - if (result) - break; - } - return result; -} - -unittest -{ - debug(apply) printf("_aApplyRdc2.unittest\n"); - - auto s = "hello"d[]; - int i; - - foreach_reverse(k, char d; s) - { - //printf("i = %d, k = %d, d = %x\n", i, k, d); - assert(k == 4 - i); - switch (i) - { - case 0: assert(d == 'o'); break; - case 1: assert(d == 'l'); break; - case 2: assert(d == 'l'); break; - case 3: assert(d == 'e'); break; - case 4: assert(d == 'h'); break; - default: assert(0); - } - i++; - } - assert(i == 5); - - s = "a\u1234\U00100456b"; - i = 0; - foreach_reverse(k, char d; s) - { - //printf("i = %d, k = %d, d = %x\n", i, k, d); - switch (i) - { - case 0: assert(k == 3); assert(d == 'b'); break; - case 1: assert(k == 2); assert(d == 0xF4); break; - case 2: assert(k == 2); assert(d == 0x80); break; - case 3: assert(k == 2); assert(d == 0x91); break; - case 4: assert(k == 2); assert(d == 0x96); break; - case 5: assert(k == 1); assert(d == 0xE1); break; - case 6: assert(k == 1); assert(d == 0x88); break; - case 7: assert(k == 1); assert(d == 0xB4); break; - case 8: assert(k == 0); assert(d == 'a'); break; - default: assert(0); - } - i++; - } - assert(i == 9); -} - -/*****************************/ - -extern (C) int _aApplyRdw2(in dchar[] aa, dg2_t dg) -{ int result; - - debug(apply) printf("_aApplyRdw2(), len = %d\n", aa.length); - for (size_t i = aa.length; i != 0; ) - { dchar d = aa[--i]; - wchar w; - - if (d <= 0xFFFF) - w = cast(wchar) d; - else - { - w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); - result = dg(&i, cast(void *)&w); - if (result) - break; - w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00); - } - result = dg(&i, cast(void *)&w); - if (result) - break; - } - return result; -} - -unittest -{ - debug(apply) printf("_aApplyRdw2.unittest\n"); - - auto s = "hello"d[]; - int i; - - foreach_reverse(k, wchar d; s) - { - //printf("i = %d, k = %d, d = %x\n", i, k, d); - assert(k == 4 - i); - switch (i) - { - case 0: assert(d == 'o'); break; - case 1: assert(d == 'l'); break; - case 2: assert(d == 'l'); break; - case 3: assert(d == 'e'); break; - case 4: assert(d == 'h'); break; - default: assert(0); - } - i++; - } - assert(i == 5); - - s = "a\u1234\U00100456b"; - i = 0; - foreach_reverse(k, wchar d; s) - { - //printf("i = %d, k = %d, d = %x\n", i, k, d); - switch (i) - { - case 0: assert(k == 3); assert(d == 'b'); break; - case 1: assert(k == 2); assert(d == 0xDBC1); break; - case 2: assert(k == 2); assert(d == 0xDC56); break; - case 3: assert(k == 1); assert(d == 0x1234); break; - case 4: assert(k == 0); assert(d == 'a'); break; - default: assert(0); - } - i++; - } - assert(i == 5); -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/aaA.d --- a/druntime/src/compiler/dmd/aaA.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,872 +0,0 @@ -/** - * Implementation of associative arrays. - * - * Copyright: Copyright Digital Mars 2000 - 2009. - * License: aa.a.b.length * 4) - { - //printf("rehash\n"); - _aaRehash(aa,keyti); - } - -Lret: - return cast(void *)(e + 1) + keysize; -} - - -/************************************************* - * Get pointer to value in associative array indexed by key. - * Returns null if it is not already there. - */ - -void* _aaGetRvalue(AA aa, TypeInfo keyti, size_t valuesize, ...) -{ - //printf("_aaGetRvalue(valuesize = %u)\n", valuesize); - if (!aa.a) - return null; - - auto pkey = cast(void *)(&valuesize + 1); - auto keysize = aligntsize(keyti.tsize()); - auto len = aa.a.b.length; - - if (len) - { - auto key_hash = keyti.getHash(pkey); - //printf("hash = %d\n", key_hash); - size_t i = key_hash % len; - auto e = aa.a.b[i]; - while (e !is null) - { - if (key_hash == e.hash) - { - auto c = keyti.compare(pkey, e + 1); - if (c == 0) - return cast(void *)(e + 1) + keysize; - e = (c < 0) ? e.left : e.right; - } - else - e = (key_hash < e.hash) ? e.left : e.right; - } - } - return null; // not found, caller will throw exception -} - - -/************************************************* - * Determine if key is in aa. - * Returns: - * null not in aa - * !=null in aa, return pointer to value - */ - -void* _aaIn(AA aa, TypeInfo keyti, ...) -in -{ -} -out (result) -{ - //assert(result == 0 || result == 1); -} -body -{ - if (aa.a) - { - auto pkey = cast(void *)(&keyti + 1); - - //printf("_aaIn(), .length = %d, .ptr = %x\n", aa.a.length, cast(uint)aa.a.ptr); - auto len = aa.a.b.length; - - if (len) - { - auto key_hash = keyti.getHash(pkey); - //printf("hash = %d\n", key_hash); - size_t i = key_hash % len; - auto e = aa.a.b[i]; - while (e !is null) - { - if (key_hash == e.hash) - { - auto c = keyti.compare(pkey, e + 1); - if (c == 0) - return cast(void *)(e + 1) + aligntsize(keyti.tsize()); - e = (c < 0) ? e.left : e.right; - } - else - e = (key_hash < e.hash) ? e.left : e.right; - } - } - } - - // Not found - return null; -} - -/************************************************* - * Delete key entry in aa[]. - * If key is not in aa[], do nothing. - */ - -void _aaDel(AA aa, TypeInfo keyti, ...) -{ - auto pkey = cast(void *)(&keyti + 1); - aaA *e; - - if (aa.a && aa.a.b.length) - { - auto key_hash = keyti.getHash(pkey); - //printf("hash = %d\n", key_hash); - size_t i = key_hash % aa.a.b.length; - auto pe = &aa.a.b[i]; - while ((e = *pe) !is null) // null means not found - { - if (key_hash == e.hash) - { - auto c = keyti.compare(pkey, e + 1); - if (c == 0) - { - if (!e.left && !e.right) - { - *pe = null; - } - else if (e.left && !e.right) - { - *pe = e.left; - e.left = null; - } - else if (!e.left && e.right) - { - *pe = e.right; - e.right = null; - } - else - { - *pe = e.left; - e.left = null; - do - pe = &(*pe).right; - while (*pe); - *pe = e.right; - e.right = null; - } - - aa.a.nodes--; - gc_free(e); - break; - } - pe = (c < 0) ? &e.left : &e.right; - } - else - pe = (key_hash < e.hash) ? &e.left : &e.right; - } - } -} - - -/******************************************** - * Produce array of values from aa. - */ - -ArrayRet_t _aaValues(AA aa, size_t keysize, size_t valuesize) -in -{ - assert(keysize == aligntsize(keysize)); -} -body -{ - size_t resi; - Array a; - - void _aaValues_x(aaA* e) - { - do - { - memcpy(a.ptr + resi * valuesize, - cast(byte*)e + aaA.sizeof + keysize, - valuesize); - resi++; - if (e.left) - { if (!e.right) - { e = e.left; - continue; - } - _aaValues_x(e.left); - } - e = e.right; - } while (e !is null); - } - - if (aa.a) - { - a.length = _aaLen(aa); - a.ptr = cast(byte*) gc_malloc(a.length * valuesize, - valuesize < (void*).sizeof ? BlkAttr.NO_SCAN : 0); - resi = 0; - foreach (e; aa.a.b) - { - if (e) - _aaValues_x(e); - } - assert(resi == a.length); - } - return *cast(ArrayRet_t*)(&a); -} - - -/******************************************** - * Rehash an array. - */ - -void* _aaRehash(AA* paa, TypeInfo keyti) -in -{ - //_aaInvAh(paa); -} -out (result) -{ - //_aaInvAh(result); -} -body -{ - BB newb; - - void _aaRehash_x(aaA* olde) - { - while (1) - { - auto left = olde.left; - auto right = olde.right; - olde.left = null; - olde.right = null; - - aaA *e; - - //printf("rehash %p\n", olde); - auto key_hash = olde.hash; - size_t i = key_hash % newb.b.length; - auto pe = &newb.b[i]; - while ((e = *pe) !is null) - { - //printf("\te = %p, e.left = %p, e.right = %p\n", e, e.left, e.right); - assert(e.left != e); - assert(e.right != e); - if (key_hash == e.hash) - { - auto c = keyti.compare(olde + 1, e + 1); - assert(c != 0); - pe = (c < 0) ? &e.left : &e.right; - } - else - pe = (key_hash < e.hash) ? &e.left : &e.right; - } - *pe = olde; - - if (right) - { - if (!left) - { olde = right; - continue; - } - _aaRehash_x(right); - } - if (!left) - break; - olde = left; - } - } - - //printf("Rehash\n"); - if (paa.a) - { - auto aa = paa.a; - auto len = _aaLen(*paa); - if (len) - { size_t i; - - for (i = 0; i < prime_list.length - 1; i++) - { - if (len <= prime_list[i]) - break; - } - len = prime_list[i]; - newb.b = new aaA*[len]; - - foreach (e; aa.b) - { - if (e) - _aaRehash_x(e); - } - delete aa.b; - - newb.nodes = aa.nodes; - newb.keyti = aa.keyti; - } - - *paa.a = newb; - _aaBalance(paa); - } - return (*paa).a; -} - -/******************************************** - * Balance an array. - */ - -void _aaBalance(AA* paa) -{ - //printf("_aaBalance()\n"); - if (paa.a) - { - aaA*[16] tmp; - aaA*[] array = tmp; - auto aa = paa.a; - foreach (j, e; aa.b) - { - /* Temporarily store contents of bucket in array[] - */ - size_t k = 0; - void addToArray(aaA* e) - { - while (e) - { addToArray(e.left); - if (k == array.length) - array.length = array.length * 2; - array[k++] = e; - e = e.right; - } - } - addToArray(e); - /* The contents of the bucket are now sorted into array[]. - * Rebuild the tree. - */ - void buildTree(aaA** p, size_t x1, size_t x2) - { - if (x1 >= x2) - *p = null; - else - { auto mid = (x1 + x2) >> 1; - *p = array[mid]; - buildTree(&(*p).left, x1, mid); - buildTree(&(*p).right, mid + 1, x2); - } - } - auto p = &aa.b[j]; - buildTree(p, 0, k); - } - } -} -/******************************************** - * Produce array of N byte keys from aa. - */ - -ArrayRet_t _aaKeys(AA aa, size_t keysize) -{ - byte[] res; - size_t resi; - - void _aaKeys_x(aaA* e) - { - do - { - memcpy(&res[resi * keysize], cast(byte*)(e + 1), keysize); - resi++; - if (e.left) - { if (!e.right) - { e = e.left; - continue; - } - _aaKeys_x(e.left); - } - e = e.right; - } while (e !is null); - } - - auto len = _aaLen(aa); - if (!len) - return 0; - res = (cast(byte*) gc_malloc(len * keysize, - !(aa.a.keyti.flags() & 1) ? BlkAttr.NO_SCAN : 0))[0 .. len * keysize]; - resi = 0; - foreach (e; aa.a.b) - { - if (e) - _aaKeys_x(e); - } - assert(resi == len); - - Array a; - a.length = len; - a.ptr = res.ptr; - return *cast(ArrayRet_t*)(&a); -} - - -/********************************************** - * 'apply' for associative arrays - to support foreach - */ - -// dg is D, but _aaApply() is C -extern (D) typedef int delegate(void *) dg_t; - -int _aaApply(AA aa, size_t keysize, dg_t dg) -in -{ - assert(aligntsize(keysize) == keysize); -} -body -{ int result; - - //printf("_aaApply(aa = x%llx, keysize = %d, dg = x%llx)\n", aa.a, keysize, dg); - - int treewalker(aaA* e) - { int result; - - do - { - //printf("treewalker(e = %p, dg = x%llx)\n", e, dg); - result = dg(cast(void *)(e + 1) + keysize); - if (result) - break; - if (e.right) - { if (!e.left) - { - e = e.right; - continue; - } - result = treewalker(e.right); - if (result) - break; - } - e = e.left; - } while (e); - - return result; - } - - if (aa.a) - { - foreach (e; aa.a.b) - { - if (e) - { - result = treewalker(e); - if (result) - break; - } - } - } - return result; -} - -// dg is D, but _aaApply2() is C -extern (D) typedef int delegate(void *, void *) dg2_t; - -int _aaApply2(AA aa, size_t keysize, dg2_t dg) -in -{ - assert(aligntsize(keysize) == keysize); -} -body -{ int result; - - //printf("_aaApply(aa = x%llx, keysize = %d, dg = x%llx)\n", aa.a, keysize, dg); - - int treewalker(aaA* e) - { int result; - - do - { - //printf("treewalker(e = %p, dg = x%llx)\n", e, dg); - result = dg(cast(void *)(e + 1), cast(void *)(e + 1) + keysize); - if (result) - break; - if (e.right) - { if (!e.left) - { - e = e.right; - continue; - } - result = treewalker(e.right); - if (result) - break; - } - e = e.left; - } while (e); - - return result; - } - - if (aa.a) - { - foreach (e; aa.a.b) - { - if (e) - { - result = treewalker(e); - if (result) - break; - } - } - } - return result; -} - - -/*********************************** - * Construct an associative array of type ti from - * length pairs of key/value pairs. - */ - -extern (C) -BB* _d_assocarrayliteralT(TypeInfo_AssociativeArray ti, size_t length, ...) -{ - auto valuesize = ti.next.tsize(); // value size - auto keyti = ti.key; - auto keysize = keyti.tsize(); // key size - BB* result; - - //printf("_d_assocarrayliteralT(keysize = %d, valuesize = %d, length = %d)\n", keysize, valuesize, length); - //printf("tivalue = %.*s\n", ti.next.classinfo.name); - if (length == 0 || valuesize == 0 || keysize == 0) - { - ; - } - else - { - va_list q; - va_start!(size_t)(q, length); - - result = new BB(); - result.keyti = keyti; - size_t i; - - for (i = 0; i < prime_list.length - 1; i++) - { - if (length <= prime_list[i]) - break; - } - auto len = prime_list[i]; - result.b = new aaA*[len]; - - size_t keystacksize = (keysize + int.sizeof - 1) & ~(int.sizeof - 1); - size_t valuestacksize = (valuesize + int.sizeof - 1) & ~(int.sizeof - 1); - - size_t keytsize = aligntsize(keysize); - - for (size_t j = 0; j < length; j++) - { void* pkey = q; - q += keystacksize; - void* pvalue = q; - q += valuestacksize; - aaA* e; - - auto key_hash = keyti.getHash(pkey); - //printf("hash = %d\n", key_hash); - i = key_hash % len; - auto pe = &result.b[i]; - while (1) - { - e = *pe; - if (!e) - { - // Not found, create new elem - //printf("create new one\n"); - e = cast(aaA *) cast(void*) new void[aaA.sizeof + keytsize + valuesize]; - memcpy(e + 1, pkey, keysize); - e.hash = key_hash; - *pe = e; - result.nodes++; - break; - } - if (key_hash == e.hash) - { - auto c = keyti.compare(pkey, e + 1); - if (c == 0) - break; - pe = (c < 0) ? &e.left : &e.right; - } - else - pe = (key_hash < e.hash) ? &e.left : &e.right; - } - memcpy(cast(void *)(e + 1) + keytsize, pvalue, valuesize); - } - - va_end(q); - } - return result; -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/adi.d --- a/druntime/src/compiler/dmd/adi.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,603 +0,0 @@ -/** - * Implementation of dynamic array property support routines. - * - * Copyright: Copyright Digital Mars 2000 - 2009. - * License: = lo); - } - if (lo == hi) - break; - - debug(adi) printf("\tstridelo = %d, stridehi = %d\n", stridelo, stridehi); - if (stridelo == stridehi) - { - - memcpy(tmp.ptr, lo, stridelo); - memcpy(lo, hi, stridelo); - memcpy(hi, tmp.ptr, stridelo); - lo += stridelo; - hi--; - continue; - } - - /* Shift the whole array. This is woefully inefficient - */ - memcpy(tmp.ptr, hi, stridehi); - memcpy(tmplo.ptr, lo, stridelo); - memmove(lo + stridehi, lo + stridelo , (hi - lo) - stridelo); - memcpy(lo, tmp.ptr, stridehi); - memcpy(hi + stridehi - stridelo, tmplo.ptr, stridelo); - - lo += stridehi; - hi = hi - 1 + (stridehi - stridelo); - } - } - return *cast(long*)(&a); -} - -unittest -{ - auto a = "abcd"c[]; - - auto r = a.dup.reverse; - //writefln(r); - assert(r == "dcba"); - - a = "a\u1235\u1234c"; - //writefln(a); - r = a.dup.reverse; - //writefln(r); - assert(r == "c\u1234\u1235a"); - - a = "ab\u1234c"; - //writefln(a); - r = a.dup.reverse; - //writefln(r); - assert(r == "c\u1234ba"); - - a = "\u3026\u2021\u3061\n"; - r = a.dup.reverse; - assert(r == "\n\u3061\u2021\u3026"); -} - - -/********************************************** - * Reverse array of wchars. - * Handled separately because embedded multiword encodings should not be - * reversed. - */ - -extern (C) long _adReverseWchar(wchar[] a) -{ - if (a.length > 1) - { - wchar[2] tmp; - wchar* lo = a.ptr; - wchar* hi = &a[length - 1]; - - while (lo < hi) - { auto clo = *lo; - auto chi = *hi; - - if ((clo < 0xD800 || clo > 0xDFFF) && - (chi < 0xD800 || chi > 0xDFFF)) - { - *lo = chi; - *hi = clo; - lo++; - hi--; - continue; - } - - int stridelo = 1 + (clo >= 0xD800 && clo <= 0xDBFF); - - int stridehi = 1; - if (chi >= 0xDC00 && chi <= 0xDFFF) - { - chi = *--hi; - stridehi++; - assert(hi >= lo); - } - if (lo == hi) - break; - - if (stridelo == stridehi) - { int stmp; - - assert(stridelo == 2); - assert(stmp.sizeof == 2 * (*lo).sizeof); - stmp = *cast(int*)lo; - *cast(int*)lo = *cast(int*)hi; - *cast(int*)hi = stmp; - lo += stridelo; - hi--; - continue; - } - - /* Shift the whole array. This is woefully inefficient - */ - memcpy(tmp.ptr, hi, stridehi * wchar.sizeof); - memcpy(hi + stridehi - stridelo, lo, stridelo * wchar.sizeof); - memmove(lo + stridehi, lo + stridelo , (hi - (lo + stridelo)) * wchar.sizeof); - memcpy(lo, tmp.ptr, stridehi * wchar.sizeof); - - lo += stridehi; - hi = hi - 1 + (stridehi - stridelo); - } - } - return *cast(long*)(&a); -} - -unittest -{ - wstring a = "abcd"; - - auto r = a.dup.reverse; - assert(r == "dcba"); - - a = "a\U00012356\U00012346c"; - r = a.dup.reverse; - assert(r == "c\U00012346\U00012356a"); - - a = "ab\U00012345c"; - r = a.dup.reverse; - assert(r == "c\U00012345ba"); -} - - -/********************************************** - * Support for array.reverse property. - */ - -extern (C) long _adReverse(Array a, size_t szelem) -out (result) -{ - assert(result is *cast(long*)(&a)); -} -body -{ - if (a.length >= 2) - { - byte* tmp; - byte[16] buffer; - - void* lo = a.ptr; - void* hi = a.ptr + (a.length - 1) * szelem; - - tmp = buffer.ptr; - if (szelem > 16) - { - //version (Windows) - tmp = cast(byte*) alloca(szelem); - //else - //tmp = gc_malloc(szelem); - } - - for (; lo < hi; lo += szelem, hi -= szelem) - { - memcpy(tmp, lo, szelem); - memcpy(lo, hi, szelem); - memcpy(hi, tmp, szelem); - } - - version (Windows) - { - } - else - { - //if (szelem > 16) - // BUG: bad code is generate for delete pointer, tries - // to call delclass. - //gc_free(tmp); - } - } - return *cast(long*)(&a); -} - -unittest -{ - debug(adi) printf("array.reverse.unittest\n"); - - int[] a = new int[5]; - int[] b; - size_t i; - - for (i = 0; i < 5; i++) - a[i] = i; - b = a.reverse; - assert(b is a); - for (i = 0; i < 5; i++) - assert(a[i] == 4 - i); - - struct X20 - { // More than 16 bytes in size - int a; - int b, c, d, e; - } - - X20[] c = new X20[5]; - X20[] d; - - for (i = 0; i < 5; i++) - { c[i].a = i; - c[i].e = 10; - } - d = c.reverse; - assert(d is c); - for (i = 0; i < 5; i++) - { - assert(c[i].a == 4 - i); - assert(c[i].e == 10); - } -} - -/********************************************** - * Sort array of chars. - */ - -extern (C) long _adSortChar(char[] a) -{ - if (a.length > 1) - { - dstring da = toUTF32(a); - da.sort; - size_t i = 0; - foreach (dchar d; da) - { char[4] buf; - auto t = toUTF8(buf, d); - a[i .. i + t.length] = t[]; - i += t.length; - } - delete da; - } - return *cast(long*)(&a); -} - -/********************************************** - * Sort array of wchars. - */ - -extern (C) long _adSortWchar(wchar[] a) -{ - if (a.length > 1) - { - dstring da = toUTF32(a); - da.sort; - size_t i = 0; - foreach (dchar d; da) - { wchar[2] buf; - auto t = toUTF16(buf, d); - a[i .. i + t.length] = t[]; - i += t.length; - } - delete da; - } - return *cast(long*)(&a); -} - -/*************************************** - * Support for array equality test. - * Returns: - * 1 equal - * 0 not equal - */ - -extern (C) int _adEq(Array a1, Array a2, TypeInfo ti) -{ - debug(adi) printf("_adEq(a1.length = %d, a2.length = %d)\n", a1.length, a2.length); - if (a1.length != a2.length) - return 0; // not equal - auto sz = ti.tsize(); - auto p1 = a1.ptr; - auto p2 = a2.ptr; - - if (sz == 1) - // We should really have a ti.isPOD() check for this - return (memcmp(p1, p2, a1.length) == 0); - - for (size_t i = 0; i < a1.length; i++) - { - if (!ti.equals(p1 + i * sz, p2 + i * sz)) - return 0; // not equal - } - return 1; // equal -} - -extern (C) int _adEq2(Array a1, Array a2, TypeInfo ti) -{ - debug(adi) printf("_adEq2(a1.length = %d, a2.length = %d)\n", a1.length, a2.length); - if (a1.length != a2.length) - return 0; // not equal - if (!ti.equals(&a1, &a2)) - return 0; - return 1; -} -unittest -{ - debug(adi) printf("array.Eq unittest\n"); - - auto a = "hello"c; - - assert(a != "hel"); - assert(a != "helloo"); - assert(a != "betty"); - assert(a == "hello"); - assert(a != "hxxxx"); -} - -/*************************************** - * Support for array compare test. - */ - -extern (C) int _adCmp(Array a1, Array a2, TypeInfo ti) -{ - debug(adi) printf("adCmp()\n"); - auto len = a1.length; - if (a2.length < len) - len = a2.length; - auto sz = ti.tsize(); - void *p1 = a1.ptr; - void *p2 = a2.ptr; - - if (sz == 1) - { // We should really have a ti.isPOD() check for this - auto c = memcmp(p1, p2, len); - if (c) - return c; - } - else - { - for (size_t i = 0; i < len; i++) - { - auto c = ti.compare(p1 + i * sz, p2 + i * sz); - if (c) - return c; - } - } - if (a1.length == a2.length) - return 0; - return (a1.length > a2.length) ? 1 : -1; -} - -extern (C) int _adCmp2(Array a1, Array a2, TypeInfo ti) -{ - debug(adi) printf("_adCmp2(a1.length = %d, a2.length = %d)\n", a1.length, a2.length); - return ti.compare(&a1, &a2); -} -unittest -{ - debug(adi) printf("array.Cmp unittest\n"); - - auto a = "hello"c; - - assert(a > "hel"); - assert(a >= "hel"); - assert(a < "helloo"); - assert(a <= "helloo"); - assert(a > "betty"); - assert(a >= "betty"); - assert(a == "hello"); - assert(a <= "hello"); - assert(a >= "hello"); -} - -/*************************************** - * Support for array compare test. - */ - -extern (C) int _adCmpChar(Array a1, Array a2) -{ - version (X86) - { - asm - { naked ; - - push EDI ; - push ESI ; - - mov ESI,a1+4[4+ESP] ; - mov EDI,a2+4[4+ESP] ; - - mov ECX,a1[4+ESP] ; - mov EDX,a2[4+ESP] ; - - cmp ECX,EDX ; - jb GotLength ; - - mov ECX,EDX ; - -GotLength: - cmp ECX,4 ; - jb DoBytes ; - - // Do alignment if neither is dword aligned - test ESI,3 ; - jz Aligned ; - - test EDI,3 ; - jz Aligned ; -DoAlign: - mov AL,[ESI] ; //align ESI to dword bounds - mov DL,[EDI] ; - - cmp AL,DL ; - jnz Unequal ; - - inc ESI ; - inc EDI ; - - test ESI,3 ; - - lea ECX,[ECX-1] ; - jnz DoAlign ; -Aligned: - mov EAX,ECX ; - - // do multiple of 4 bytes at a time - - shr ECX,2 ; - jz TryOdd ; - - repe ; - cmpsd ; - - jnz UnequalQuad ; - -TryOdd: - mov ECX,EAX ; -DoBytes: - // if still equal and not end of string, do up to 3 bytes slightly - // slower. - - and ECX,3 ; - jz Equal ; - - repe ; - cmpsb ; - - jnz Unequal ; -Equal: - mov EAX,a1[4+ESP] ; - mov EDX,a2[4+ESP] ; - - sub EAX,EDX ; - pop ESI ; - - pop EDI ; - ret ; - -UnequalQuad: - mov EDX,[EDI-4] ; - mov EAX,[ESI-4] ; - - cmp AL,DL ; - jnz Unequal ; - - cmp AH,DH ; - jnz Unequal ; - - shr EAX,16 ; - - shr EDX,16 ; - - cmp AL,DL ; - jnz Unequal ; - - cmp AH,DH ; -Unequal: - sbb EAX,EAX ; - pop ESI ; - - or EAX,1 ; - pop EDI ; - - ret ; - } - } - else - { - int len; - int c; - - debug(adi) printf("adCmpChar()\n"); - len = a1.length; - if (a2.length < len) - len = a2.length; - c = memcmp(cast(char *)a1.ptr, cast(char *)a2.ptr, len); - if (!c) - c = cast(int)a1.length - cast(int)a2.length; - return c; - } -} - -unittest -{ - debug(adi) printf("array.CmpChar unittest\n"); - - auto a = "hello"c; - - assert(a > "hel"); - assert(a >= "hel"); - assert(a < "helloo"); - assert(a <= "helloo"); - assert(a > "betty"); - assert(a >= "betty"); - assert(a == "hello"); - assert(a <= "hello"); - assert(a >= "hello"); -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/alloca.d --- a/druntime/src/compiler/dmd/alloca.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,135 +0,0 @@ -/** - * Implementation of alloca() standard C routine. - * - * Copyright: Copyright Digital Mars 1990 - 2009. - * License: Boost License 1.0. - * Authors: Walter Bright, based on code originally written by Burton Radons - * - * Copyright Digital Mars 2008 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module rt.arraybyte; - -import rt.util.cpuid; - -version (unittest) -{ - private import core.stdc.stdio : printf; - /* This is so unit tests will test every CPU variant - */ - int cpuid; - const int CPUID_MAX = 4; - bool mmx() { return cpuid == 1 && rt.util.cpuid.mmx(); } - bool sse() { return cpuid == 2 && rt.util.cpuid.sse(); } - bool sse2() { return cpuid == 3 && rt.util.cpuid.sse2(); } - bool amd3dnow() { return cpuid == 4 && rt.util.cpuid.amd3dnow(); } -} -else -{ - alias rt.util.cpuid.mmx mmx; - alias rt.util.cpuid.sse sse; - alias rt.util.cpuid.sse2 sse2; - alias rt.util.cpuid.amd3dnow amd3dnow; -} - -//version = log; - -bool disjoint(T)(T[] a, T[] b) -{ - return (a.ptr + a.length <= b.ptr || b.ptr + b.length <= a.ptr); -} - -alias byte T; - -extern (C): - -/* ======================================================================== */ - - -/*********************** - * Computes: - * a[] = b[] + value - */ - -T[] _arraySliceExpAddSliceAssign_a(T[] a, T value, T[] b) -{ - return _arraySliceExpAddSliceAssign_g(a, value, b); -} - -T[] _arraySliceExpAddSliceAssign_h(T[] a, T value, T[] b) -{ - return _arraySliceExpAddSliceAssign_g(a, value, b); -} - -T[] _arraySliceExpAddSliceAssign_g(T[] a, T value, T[] b) -in -{ - assert(a.length == b.length); - assert(disjoint(a, b)); -} -body -{ - //printf("_arraySliceExpAddSliceAssign_g()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 1088% faster - if (sse2() && a.length >= 64) - { - auto n = aptr + (a.length & ~63); - - uint l = cast(ubyte) value; - l |= (l << 8); - l |= (l << 16); - - if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM4, l; - pshufd XMM4, XMM4, 0; - - align 8; - startaddsse2u: - add ESI, 64; - movdqu XMM0, [EAX]; - movdqu XMM1, [EAX+16]; - movdqu XMM2, [EAX+32]; - movdqu XMM3, [EAX+48]; - add EAX, 64; - paddb XMM0, XMM4; - paddb XMM1, XMM4; - paddb XMM2, XMM4; - paddb XMM3, XMM4; - movdqu [ESI -64], XMM0; - movdqu [ESI+16-64], XMM1; - movdqu [ESI+32-64], XMM2; - movdqu [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startaddsse2u; - - mov aptr, ESI; - mov bptr, EAX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM4, l; - pshufd XMM4, XMM4, 0; - - align 8; - startaddsse2a: - add ESI, 64; - movdqa XMM0, [EAX]; - movdqa XMM1, [EAX+16]; - movdqa XMM2, [EAX+32]; - movdqa XMM3, [EAX+48]; - add EAX, 64; - paddb XMM0, XMM4; - paddb XMM1, XMM4; - paddb XMM2, XMM4; - paddb XMM3, XMM4; - movdqa [ESI -64], XMM0; - movdqa [ESI+16-64], XMM1; - movdqa [ESI+32-64], XMM2; - movdqa [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startaddsse2a; - - mov aptr, ESI; - mov bptr, EAX; - } - } - } - else - // MMX version is 1000% faster - if (mmx() && a.length >= 32) - { - auto n = aptr + (a.length & ~31); - - uint l = cast(ubyte) value; - l |= (l << 8); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd MM4, l; - pshufw MM4, MM4, 0; - - align 4; - startaddmmx: - add ESI, 32; - movq MM0, [EAX]; - movq MM1, [EAX+8]; - movq MM2, [EAX+16]; - movq MM3, [EAX+24]; - add EAX, 32; - paddb MM0, MM4; - paddb MM1, MM4; - paddb MM2, MM4; - paddb MM3, MM4; - movq [ESI -32], MM0; - movq [ESI+8 -32], MM1; - movq [ESI+16-32], MM2; - movq [ESI+24-32], MM3; - cmp ESI, EDI; - jb startaddmmx; - - emms; - mov aptr, ESI; - mov bptr, EAX; - } - } - /* trying to be fair and treat normal 32-bit cpu the same way as we do - * the SIMD units, with unrolled asm. There's not enough registers, - * really. - */ - else - if (a.length >= 4) - { - - auto n = aptr + (a.length & ~3); - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov CL, value; - - align 4; - startadd386: - add ESI, 4; - mov DX, [EAX]; - mov BX, [EAX+2]; - add EAX, 4; - add BL, CL; - add BH, CL; - add DL, CL; - add DH, CL; - mov [ESI -4], DX; - mov [ESI+2 -4], BX; - cmp ESI, EDI; - jb startadd386; - - mov aptr, ESI; - mov bptr, EAX; - } - - } - } - - while (aptr < aend) - *aptr++ = cast(T)(*bptr++ + value); - - return a; -} - -unittest -{ - printf("_arraySliceExpAddSliceAssign_g unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] + 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] + 6)) - { - printf("[%d]: %d != %d + 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] + c[] - */ - -T[] _arraySliceSliceAddSliceAssign_a(T[] a, T[] c, T[] b) -{ - return _arraySliceSliceAddSliceAssign_g(a, c, b); -} - -T[] _arraySliceSliceAddSliceAssign_h(T[] a, T[] c, T[] b) -{ - return _arraySliceSliceAddSliceAssign_g(a, c, b); -} - -T[] _arraySliceSliceAddSliceAssign_g(T[] a, T[] c, T[] b) -in -{ - assert(a.length == b.length && b.length == c.length); - assert(disjoint(a, b)); - assert(disjoint(a, c)); - assert(disjoint(b, c)); -} -body -{ - //printf("_arraySliceSliceAddSliceAssign_g()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - auto cptr = c.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 5739% faster - if (sse2() && a.length >= 64) - { - auto n = aptr + (a.length & ~63); - - if (((cast(uint) aptr | cast(uint) bptr | cast(uint) cptr) & 15) != 0) - { - version (log) printf("\tsse2 unaligned\n"); - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 8; - startaddlsse2u: - add ESI, 64; - movdqu XMM0, [EAX]; - movdqu XMM1, [EAX+16]; - movdqu XMM2, [EAX+32]; - movdqu XMM3, [EAX+48]; - add EAX, 64; - movdqu XMM4, [ECX]; - movdqu XMM5, [ECX+16]; - movdqu XMM6, [ECX+32]; - movdqu XMM7, [ECX+48]; - add ECX, 64; - paddb XMM0, XMM4; - paddb XMM1, XMM5; - paddb XMM2, XMM6; - paddb XMM3, XMM7; - movdqu [ESI -64], XMM0; - movdqu [ESI+16-64], XMM1; - movdqu [ESI+32-64], XMM2; - movdqu [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startaddlsse2u; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - else - { - version (log) printf("\tsse2 aligned\n"); - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 8; - startaddlsse2a: - add ESI, 64; - movdqa XMM0, [EAX]; - movdqa XMM1, [EAX+16]; - movdqa XMM2, [EAX+32]; - movdqa XMM3, [EAX+48]; - add EAX, 64; - movdqa XMM4, [ECX]; - movdqa XMM5, [ECX+16]; - movdqa XMM6, [ECX+32]; - movdqa XMM7, [ECX+48]; - add ECX, 64; - paddb XMM0, XMM4; - paddb XMM1, XMM5; - paddb XMM2, XMM6; - paddb XMM3, XMM7; - movdqa [ESI -64], XMM0; - movdqa [ESI+16-64], XMM1; - movdqa [ESI+32-64], XMM2; - movdqa [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startaddlsse2a; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - else - // MMX version is 4428% faster - if (mmx() && a.length >= 32) - { - version (log) printf("\tmmx\n"); - auto n = aptr + (a.length & ~31); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 4; - startaddlmmx: - add ESI, 32; - movq MM0, [EAX]; - movq MM1, [EAX+8]; - movq MM2, [EAX+16]; - movq MM3, [EAX+24]; - add EAX, 32; - movq MM4, [ECX]; - movq MM5, [ECX+8]; - movq MM6, [ECX+16]; - movq MM7, [ECX+24]; - add ECX, 32; - paddb MM0, MM4; - paddb MM1, MM5; - paddb MM2, MM6; - paddb MM3, MM7; - movq [ESI -32], MM0; - movq [ESI+8 -32], MM1; - movq [ESI+16-32], MM2; - movq [ESI+24-32], MM3; - cmp ESI, EDI; - jb startaddlmmx; - - emms; - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - - version (log) if (aptr < aend) printf("\tbase\n"); - while (aptr < aend) - *aptr++ = cast(T)(*bptr++ + *cptr++); - - return a; -} - -unittest -{ - printf("_arraySliceSliceAddSliceAssign_g unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] + b[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] + b[i])) - { - printf("[%d]: %d != %d + %d\n", i, c[i], a[i], b[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] += value - */ - -T[] _arrayExpSliceAddass_a(T[] a, T value) -{ - return _arrayExpSliceAddass_g(a, value); -} - -T[] _arrayExpSliceAddass_h(T[] a, T value) -{ - return _arrayExpSliceAddass_g(a, value); -} - -T[] _arrayExpSliceAddass_g(T[] a, T value) -{ - //printf("_arrayExpSliceAddass_g(a.length = %d, value = %Lg)\n", a.length, cast(real)value); - auto aptr = a.ptr; - auto aend = aptr + a.length; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 1578% faster - if (sse2() && a.length >= 64) - { - auto n = aptr + (a.length & ~63); - - uint l = cast(ubyte) value; - l |= (l << 8); - l |= (l << 16); - - if (((cast(uint) aptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - movd XMM4, l; - pshufd XMM4, XMM4, 0; - - align 8; - startaddasssse2u: - movdqu XMM0, [ESI]; - movdqu XMM1, [ESI+16]; - movdqu XMM2, [ESI+32]; - movdqu XMM3, [ESI+48]; - add ESI, 64; - paddb XMM0, XMM4; - paddb XMM1, XMM4; - paddb XMM2, XMM4; - paddb XMM3, XMM4; - movdqu [ESI -64], XMM0; - movdqu [ESI+16-64], XMM1; - movdqu [ESI+32-64], XMM2; - movdqu [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startaddasssse2u; - - mov aptr, ESI; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - movd XMM4, l; - pshufd XMM4, XMM4, 0; - - align 8; - startaddasssse2a: - movdqa XMM0, [ESI]; - movdqa XMM1, [ESI+16]; - movdqa XMM2, [ESI+32]; - movdqa XMM3, [ESI+48]; - add ESI, 64; - paddb XMM0, XMM4; - paddb XMM1, XMM4; - paddb XMM2, XMM4; - paddb XMM3, XMM4; - movdqa [ESI -64], XMM0; - movdqa [ESI+16-64], XMM1; - movdqa [ESI+32-64], XMM2; - movdqa [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startaddasssse2a; - - mov aptr, ESI; - } - } - } - else - // MMX version is 1721% faster - if (mmx() && a.length >= 32) - { - - auto n = aptr + (a.length & ~31); - - uint l = cast(ubyte) value; - l |= (l << 8); - - asm - { - mov ESI, aptr; - mov EDI, n; - movd MM4, l; - pshufw MM4, MM4, 0; - - align 8; - startaddassmmx: - movq MM0, [ESI]; - movq MM1, [ESI+8]; - movq MM2, [ESI+16]; - movq MM3, [ESI+24]; - add ESI, 32; - paddb MM0, MM4; - paddb MM1, MM4; - paddb MM2, MM4; - paddb MM3, MM4; - movq [ESI -32], MM0; - movq [ESI+8 -32], MM1; - movq [ESI+16-32], MM2; - movq [ESI+24-32], MM3; - cmp ESI, EDI; - jb startaddassmmx; - - emms; - mov aptr, ESI; - } - } - } - - while (aptr < aend) - *aptr++ += value; - - return a; -} - -unittest -{ - printf("_arrayExpSliceAddass_g unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] += 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] + 6)) - { - printf("[%d]: %d != %d + 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] += b[] - */ - -T[] _arraySliceSliceAddass_a(T[] a, T[] b) -{ - return _arraySliceSliceAddass_g(a, b); -} - -T[] _arraySliceSliceAddass_h(T[] a, T[] b) -{ - return _arraySliceSliceAddass_g(a, b); -} - -T[] _arraySliceSliceAddass_g(T[] a, T[] b) -in -{ - assert (a.length == b.length); - assert (disjoint(a, b)); -} -body -{ - //printf("_arraySliceSliceAddass_g()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 4727% faster - if (sse2() && a.length >= 64) - { - auto n = aptr + (a.length & ~63); - - if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 8; - startaddasslsse2u: - movdqu XMM0, [ESI]; - movdqu XMM1, [ESI+16]; - movdqu XMM2, [ESI+32]; - movdqu XMM3, [ESI+48]; - add ESI, 64; - movdqu XMM4, [ECX]; - movdqu XMM5, [ECX+16]; - movdqu XMM6, [ECX+32]; - movdqu XMM7, [ECX+48]; - add ECX, 64; - paddb XMM0, XMM4; - paddb XMM1, XMM5; - paddb XMM2, XMM6; - paddb XMM3, XMM7; - movdqu [ESI -64], XMM0; - movdqu [ESI+16-64], XMM1; - movdqu [ESI+32-64], XMM2; - movdqu [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startaddasslsse2u; - - mov aptr, ESI; - mov bptr, ECX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 8; - startaddasslsse2a: - movdqa XMM0, [ESI]; - movdqa XMM1, [ESI+16]; - movdqa XMM2, [ESI+32]; - movdqa XMM3, [ESI+48]; - add ESI, 64; - movdqa XMM4, [ECX]; - movdqa XMM5, [ECX+16]; - movdqa XMM6, [ECX+32]; - movdqa XMM7, [ECX+48]; - add ECX, 64; - paddb XMM0, XMM4; - paddb XMM1, XMM5; - paddb XMM2, XMM6; - paddb XMM3, XMM7; - movdqa [ESI -64], XMM0; - movdqa [ESI+16-64], XMM1; - movdqa [ESI+32-64], XMM2; - movdqa [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startaddasslsse2a; - - mov aptr, ESI; - mov bptr, ECX; - } - } - } - else - // MMX version is 3059% faster - if (mmx() && a.length >= 32) - { - - auto n = aptr + (a.length & ~31); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 8; - startaddasslmmx: - movq MM0, [ESI]; - movq MM1, [ESI+8]; - movq MM2, [ESI+16]; - movq MM3, [ESI+24]; - add ESI, 32; - movq MM4, [ECX]; - movq MM5, [ECX+8]; - movq MM6, [ECX+16]; - movq MM7, [ECX+24]; - add ECX, 32; - paddb MM0, MM4; - paddb MM1, MM5; - paddb MM2, MM6; - paddb MM3, MM7; - movq [ESI -32], MM0; - movq [ESI+8 -32], MM1; - movq [ESI+16-32], MM2; - movq [ESI+24-32], MM3; - cmp ESI, EDI; - jb startaddasslmmx; - - emms; - mov aptr, ESI; - mov bptr, ECX; - } - } - } - - while (aptr < aend) - *aptr++ += *bptr++; - - return a; -} - -unittest -{ - printf("_arraySliceSliceAddass_g unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] += b[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] + b[i])) - { - printf("[%d]: %d != %d + %d\n", i, c[i], a[i], b[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - - -/*********************** - * Computes: - * a[] = b[] - value - */ - -T[] _arraySliceExpMinSliceAssign_a(T[] a, T value, T[] b) -{ - return _arraySliceExpMinSliceAssign_g(a, value, b); -} - -T[] _arraySliceExpMinSliceAssign_h(T[] a, T value, T[] b) -{ - return _arraySliceExpMinSliceAssign_g(a, value, b); -} - -T[] _arraySliceExpMinSliceAssign_g(T[] a, T value, T[] b) -in -{ - assert(a.length == b.length); - assert(disjoint(a, b)); -} -body -{ - //printf("_arraySliceExpMinSliceAssign_g()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 1189% faster - if (sse2() && a.length >= 64) - { - auto n = aptr + (a.length & ~63); - - uint l = cast(ubyte) value; - l |= (l << 8); - l |= (l << 16); - - if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM4, l; - pshufd XMM4, XMM4, 0; - - align 8; - startsubsse2u: - add ESI, 64; - movdqu XMM0, [EAX]; - movdqu XMM1, [EAX+16]; - movdqu XMM2, [EAX+32]; - movdqu XMM3, [EAX+48]; - add EAX, 64; - psubb XMM0, XMM4; - psubb XMM1, XMM4; - psubb XMM2, XMM4; - psubb XMM3, XMM4; - movdqu [ESI -64], XMM0; - movdqu [ESI+16-64], XMM1; - movdqu [ESI+32-64], XMM2; - movdqu [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsubsse2u; - - mov aptr, ESI; - mov bptr, EAX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM4, l; - pshufd XMM4, XMM4, 0; - - align 8; - startsubsse2a: - add ESI, 64; - movdqa XMM0, [EAX]; - movdqa XMM1, [EAX+16]; - movdqa XMM2, [EAX+32]; - movdqa XMM3, [EAX+48]; - add EAX, 64; - psubb XMM0, XMM4; - psubb XMM1, XMM4; - psubb XMM2, XMM4; - psubb XMM3, XMM4; - movdqa [ESI -64], XMM0; - movdqa [ESI+16-64], XMM1; - movdqa [ESI+32-64], XMM2; - movdqa [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsubsse2a; - - mov aptr, ESI; - mov bptr, EAX; - } - } - } - else - // MMX version is 1079% faster - if (mmx() && a.length >= 32) - { - auto n = aptr + (a.length & ~31); - - uint l = cast(ubyte) value; - l |= (l << 8); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd MM4, l; - pshufw MM4, MM4, 0; - - align 4; - startsubmmx: - add ESI, 32; - movq MM0, [EAX]; - movq MM1, [EAX+8]; - movq MM2, [EAX+16]; - movq MM3, [EAX+24]; - add EAX, 32; - psubb MM0, MM4; - psubb MM1, MM4; - psubb MM2, MM4; - psubb MM3, MM4; - movq [ESI -32], MM0; - movq [ESI+8 -32], MM1; - movq [ESI+16-32], MM2; - movq [ESI+24-32], MM3; - cmp ESI, EDI; - jb startsubmmx; - - emms; - mov aptr, ESI; - mov bptr, EAX; - } - } - // trying to be fair and treat normal 32-bit cpu the same way as we do the SIMD units, with unrolled asm. There's not enough registers, really. - else - if (a.length >= 4) - { - auto n = aptr + (a.length & ~3); - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov CL, value; - - align 4; - startsub386: - add ESI, 4; - mov DX, [EAX]; - mov BX, [EAX+2]; - add EAX, 4; - sub BL, CL; - sub BH, CL; - sub DL, CL; - sub DH, CL; - mov [ESI -4], DX; - mov [ESI+2 -4], BX; - cmp ESI, EDI; - jb startsub386; - - mov aptr, ESI; - mov bptr, EAX; - } - } - } - - while (aptr < aend) - *aptr++ = cast(T)(*bptr++ - value); - - return a; -} - -unittest -{ - printf("_arraySliceExpMinSliceAssign_g unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] = b[] - 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(b[i] - 6)) - { - printf("[%d]: %d != %d - 6\n", i, c[i], b[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = value - b[] - */ - -T[] _arrayExpSliceMinSliceAssign_a(T[] a, T[] b, T value) -{ - return _arrayExpSliceMinSliceAssign_g(a, b, value); -} - -T[] _arrayExpSliceMinSliceAssign_h(T[] a, T[] b, T value) -{ - return _arrayExpSliceMinSliceAssign_g(a, b, value); -} - -T[] _arrayExpSliceMinSliceAssign_g(T[] a, T[] b, T value) -in -{ - assert(a.length == b.length); - assert(disjoint(a, b)); -} -body -{ - //printf("_arrayExpSliceMinSliceAssign_g()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 8748% faster - if (sse2() && a.length >= 64) - { - auto n = aptr + (a.length & ~63); - - uint l = cast(ubyte) value; - l |= (l << 8); - l |= (l << 16); - - if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM4, l; - pshufd XMM4, XMM4, 0; - - align 8; - startsubrsse2u: - add ESI, 64; - movdqa XMM5, XMM4; - movdqa XMM6, XMM4; - movdqu XMM0, [EAX]; - movdqu XMM1, [EAX+16]; - psubb XMM5, XMM0; - psubb XMM6, XMM1; - movdqu [ESI -64], XMM5; - movdqu [ESI+16-64], XMM6; - movdqa XMM5, XMM4; - movdqa XMM6, XMM4; - movdqu XMM2, [EAX+32]; - movdqu XMM3, [EAX+48]; - add EAX, 64; - psubb XMM5, XMM2; - psubb XMM6, XMM3; - movdqu [ESI+32-64], XMM5; - movdqu [ESI+48-64], XMM6; - cmp ESI, EDI; - jb startsubrsse2u; - - mov aptr, ESI; - mov bptr, EAX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM4, l; - pshufd XMM4, XMM4, 0; - - align 8; - startsubrsse2a: - add ESI, 64; - movdqa XMM5, XMM4; - movdqa XMM6, XMM4; - movdqa XMM0, [EAX]; - movdqa XMM1, [EAX+16]; - psubb XMM5, XMM0; - psubb XMM6, XMM1; - movdqa [ESI -64], XMM5; - movdqa [ESI+16-64], XMM6; - movdqa XMM5, XMM4; - movdqa XMM6, XMM4; - movdqa XMM2, [EAX+32]; - movdqa XMM3, [EAX+48]; - add EAX, 64; - psubb XMM5, XMM2; - psubb XMM6, XMM3; - movdqa [ESI+32-64], XMM5; - movdqa [ESI+48-64], XMM6; - cmp ESI, EDI; - jb startsubrsse2a; - - mov aptr, ESI; - mov bptr, EAX; - } - } - } - else - // MMX version is 7397% faster - if (mmx() && a.length >= 32) - { - auto n = aptr + (a.length & ~31); - - uint l = cast(ubyte) value; - l |= (l << 8); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd MM4, l; - pshufw MM4, MM4, 0; - - align 4; - startsubrmmx: - add ESI, 32; - movq MM5, MM4; - movq MM6, MM4; - movq MM0, [EAX]; - movq MM1, [EAX+8]; - psubb MM5, MM0; - psubb MM6, MM1; - movq [ESI -32], MM5; - movq [ESI+8 -32], MM6; - movq MM5, MM4; - movq MM6, MM4; - movq MM2, [EAX+16]; - movq MM3, [EAX+24]; - add EAX, 32; - psubb MM5, MM2; - psubb MM6, MM3; - movq [ESI+16-32], MM5; - movq [ESI+24-32], MM6; - cmp ESI, EDI; - jb startsubrmmx; - - emms; - mov aptr, ESI; - mov bptr, EAX; - } - } - - } - - while (aptr < aend) - *aptr++ = cast(T)(value - *bptr++); - - return a; -} - -unittest -{ - printf("_arrayExpSliceMinSliceAssign_g unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] = 6 - b[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(6 - b[i])) - { - printf("[%d]: %d != 6 - %d\n", i, c[i], b[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] - c[] - */ - -T[] _arraySliceSliceMinSliceAssign_a(T[] a, T[] c, T[] b) -{ - return _arraySliceSliceMinSliceAssign_g(a, c, b); -} - -T[] _arraySliceSliceMinSliceAssign_h(T[] a, T[] c, T[] b) -{ - return _arraySliceSliceMinSliceAssign_g(a, c, b); -} - -T[] _arraySliceSliceMinSliceAssign_g(T[] a, T[] c, T[] b) -in -{ - assert(a.length == b.length && b.length == c.length); - assert(disjoint(a, b)); - assert(disjoint(a, c)); - assert(disjoint(b, c)); -} -body -{ - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - auto cptr = c.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 5756% faster - if (sse2() && a.length >= 64) - { - auto n = aptr + (a.length & ~63); - - if (((cast(uint) aptr | cast(uint) bptr | cast(uint) cptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 8; - startsublsse2u: - add ESI, 64; - movdqu XMM0, [EAX]; - movdqu XMM1, [EAX+16]; - movdqu XMM2, [EAX+32]; - movdqu XMM3, [EAX+48]; - add EAX, 64; - movdqu XMM4, [ECX]; - movdqu XMM5, [ECX+16]; - movdqu XMM6, [ECX+32]; - movdqu XMM7, [ECX+48]; - add ECX, 64; - psubb XMM0, XMM4; - psubb XMM1, XMM5; - psubb XMM2, XMM6; - psubb XMM3, XMM7; - movdqu [ESI -64], XMM0; - movdqu [ESI+16-64], XMM1; - movdqu [ESI+32-64], XMM2; - movdqu [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsublsse2u; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 8; - startsublsse2a: - add ESI, 64; - movdqa XMM0, [EAX]; - movdqa XMM1, [EAX+16]; - movdqa XMM2, [EAX+32]; - movdqa XMM3, [EAX+48]; - add EAX, 64; - movdqa XMM4, [ECX]; - movdqa XMM5, [ECX+16]; - movdqa XMM6, [ECX+32]; - movdqa XMM7, [ECX+48]; - add ECX, 64; - psubb XMM0, XMM4; - psubb XMM1, XMM5; - psubb XMM2, XMM6; - psubb XMM3, XMM7; - movdqa [ESI -64], XMM0; - movdqa [ESI+16-64], XMM1; - movdqa [ESI+32-64], XMM2; - movdqa [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsublsse2a; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - else - // MMX version is 4428% faster - if (mmx() && a.length >= 32) - { - auto n = aptr + (a.length & ~31); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 8; - startsublmmx: - add ESI, 32; - movq MM0, [EAX]; - movq MM1, [EAX+8]; - movq MM2, [EAX+16]; - movq MM3, [EAX+24]; - add EAX, 32; - movq MM4, [ECX]; - movq MM5, [ECX+8]; - movq MM6, [ECX+16]; - movq MM7, [ECX+24]; - add ECX, 32; - psubb MM0, MM4; - psubb MM1, MM5; - psubb MM2, MM6; - psubb MM3, MM7; - movq [ESI -32], MM0; - movq [ESI+8 -32], MM1; - movq [ESI+16-32], MM2; - movq [ESI+24-32], MM3; - cmp ESI, EDI; - jb startsublmmx; - - emms; - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - - while (aptr < aend) - *aptr++ = cast(T)(*bptr++ - *cptr++); - - return a; -} - -unittest -{ - printf("_arraySliceSliceMinSliceAssign_g unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] - b[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] - b[i])) - { - printf("[%d]: %d != %d - %d\n", i, c[i], a[i], b[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] -= value - */ - -T[] _arrayExpSliceMinass_a(T[] a, T value) -{ - return _arrayExpSliceMinass_g(a, value); -} - -T[] _arrayExpSliceMinass_h(T[] a, T value) -{ - return _arrayExpSliceMinass_g(a, value); -} - -T[] _arrayExpSliceMinass_g(T[] a, T value) -{ - //printf("_arrayExpSliceMinass_g(a.length = %d, value = %Lg)\n", a.length, cast(real)value); - auto aptr = a.ptr; - auto aend = aptr + a.length; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 1577% faster - if (sse2() && a.length >= 64) - { - auto n = aptr + (a.length & ~63); - - uint l = cast(ubyte) value; - l |= (l << 8); - l |= (l << 16); - - if (((cast(uint) aptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - movd XMM4, l; - pshufd XMM4, XMM4, 0; - - align 8; - startsubasssse2u: - movdqu XMM0, [ESI]; - movdqu XMM1, [ESI+16]; - movdqu XMM2, [ESI+32]; - movdqu XMM3, [ESI+48]; - add ESI, 64; - psubb XMM0, XMM4; - psubb XMM1, XMM4; - psubb XMM2, XMM4; - psubb XMM3, XMM4; - movdqu [ESI -64], XMM0; - movdqu [ESI+16-64], XMM1; - movdqu [ESI+32-64], XMM2; - movdqu [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsubasssse2u; - - mov aptr, ESI; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - movd XMM4, l; - pshufd XMM4, XMM4, 0; - - align 8; - startsubasssse2a: - movdqa XMM0, [ESI]; - movdqa XMM1, [ESI+16]; - movdqa XMM2, [ESI+32]; - movdqa XMM3, [ESI+48]; - add ESI, 64; - psubb XMM0, XMM4; - psubb XMM1, XMM4; - psubb XMM2, XMM4; - psubb XMM3, XMM4; - movdqa [ESI -64], XMM0; - movdqa [ESI+16-64], XMM1; - movdqa [ESI+32-64], XMM2; - movdqa [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsubasssse2a; - - mov aptr, ESI; - } - } - } - else - // MMX version is 1577% faster - if (mmx() && a.length >= 32) - { - - auto n = aptr + (a.length & ~31); - - uint l = cast(ubyte) value; - l |= (l << 8); - - asm - { - mov ESI, aptr; - mov EDI, n; - movd MM4, l; - pshufw MM4, MM4, 0; - - align 8; - startsubassmmx: - movq MM0, [ESI]; - movq MM1, [ESI+8]; - movq MM2, [ESI+16]; - movq MM3, [ESI+24]; - add ESI, 32; - psubb MM0, MM4; - psubb MM1, MM4; - psubb MM2, MM4; - psubb MM3, MM4; - movq [ESI -32], MM0; - movq [ESI+8 -32], MM1; - movq [ESI+16-32], MM2; - movq [ESI+24-32], MM3; - cmp ESI, EDI; - jb startsubassmmx; - - emms; - mov aptr, ESI; - } - } - } - - while (aptr < aend) - *aptr++ -= value; - - return a; -} - -unittest -{ - printf("_arrayExpSliceMinass_g unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] -= 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] - 6)) - { - printf("[%d]: %d != %d - 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] -= b[] - */ - -T[] _arraySliceSliceMinass_a(T[] a, T[] b) -{ - return _arraySliceSliceMinass_g(a, b); -} - -T[] _arraySliceSliceMinass_h(T[] a, T[] b) -{ - return _arraySliceSliceMinass_g(a, b); -} - -T[] _arraySliceSliceMinass_g(T[] a, T[] b) -in -{ - assert (a.length == b.length); - assert (disjoint(a, b)); -} -body -{ - //printf("_arraySliceSliceMinass_g()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 4800% faster - if (sse2() && a.length >= 64) - { - auto n = aptr + (a.length & ~63); - - if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 8; - startsubasslsse2u: - movdqu XMM0, [ESI]; - movdqu XMM1, [ESI+16]; - movdqu XMM2, [ESI+32]; - movdqu XMM3, [ESI+48]; - add ESI, 64; - movdqu XMM4, [ECX]; - movdqu XMM5, [ECX+16]; - movdqu XMM6, [ECX+32]; - movdqu XMM7, [ECX+48]; - add ECX, 64; - psubb XMM0, XMM4; - psubb XMM1, XMM5; - psubb XMM2, XMM6; - psubb XMM3, XMM7; - movdqu [ESI -64], XMM0; - movdqu [ESI+16-64], XMM1; - movdqu [ESI+32-64], XMM2; - movdqu [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsubasslsse2u; - - mov aptr, ESI; - mov bptr, ECX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 8; - startsubasslsse2a: - movdqa XMM0, [ESI]; - movdqa XMM1, [ESI+16]; - movdqa XMM2, [ESI+32]; - movdqa XMM3, [ESI+48]; - add ESI, 64; - movdqa XMM4, [ECX]; - movdqa XMM5, [ECX+16]; - movdqa XMM6, [ECX+32]; - movdqa XMM7, [ECX+48]; - add ECX, 64; - psubb XMM0, XMM4; - psubb XMM1, XMM5; - psubb XMM2, XMM6; - psubb XMM3, XMM7; - movdqa [ESI -64], XMM0; - movdqa [ESI+16-64], XMM1; - movdqa [ESI+32-64], XMM2; - movdqa [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsubasslsse2a; - - mov aptr, ESI; - mov bptr, ECX; - } - } - } - else - // MMX version is 3107% faster - if (mmx() && a.length >= 32) - { - - auto n = aptr + (a.length & ~31); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 8; - startsubasslmmx: - movq MM0, [ESI]; - movq MM1, [ESI+8]; - movq MM2, [ESI+16]; - movq MM3, [ESI+24]; - add ESI, 32; - movq MM4, [ECX]; - movq MM5, [ECX+8]; - movq MM6, [ECX+16]; - movq MM7, [ECX+24]; - add ECX, 32; - psubb MM0, MM4; - psubb MM1, MM5; - psubb MM2, MM6; - psubb MM3, MM7; - movq [ESI -32], MM0; - movq [ESI+8 -32], MM1; - movq [ESI+16-32], MM2; - movq [ESI+24-32], MM3; - cmp ESI, EDI; - jb startsubasslmmx; - - emms; - mov aptr, ESI; - mov bptr, ECX; - } - } - } - - while (aptr < aend) - *aptr++ -= *bptr++; - - return a; -} - -unittest -{ - printf("_arraySliceSliceMinass_g unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] -= b[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] - b[i])) - { - printf("[%d]: %d != %d - %d\n", i, c[i], a[i], b[i]); - assert(0); - } - } - } - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/arraycast.d --- a/druntime/src/compiler/dmd/arraycast.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,94 +0,0 @@ -/** - * Implementation of array cast support routines. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: = 8) - { - auto n = aptr + (b.length & ~7); - - // Unaligned case - asm - { - mov EAX, bptr; // left operand - mov ECX, cptr; // right operand - mov ESI, aptr; // destination operand - mov EDI, n; // end comparison - - align 8; - startsseloopb: - movupd XMM0, [EAX]; - movupd XMM1, [EAX+16]; - movupd XMM2, [EAX+32]; - movupd XMM3, [EAX+48]; - add EAX, 64; - movupd XMM4, [ECX]; - movupd XMM5, [ECX+16]; - movupd XMM6, [ECX+32]; - movupd XMM7, [ECX+48]; - add ESI, 64; - subpd XMM0, XMM4; - subpd XMM1, XMM5; - subpd XMM2, XMM6; - subpd XMM3, XMM7; - add ECX, 64; - movupd [ESI+ 0-64], XMM0; - movupd [ESI+16-64], XMM1; - movupd [ESI+32-64], XMM2; - movupd [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloopb; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - - // Handle remainder - while (aptr < aend) - *aptr++ = *bptr++ - *cptr++; - - return a; -} - - -unittest -{ - printf("_arraySliceSliceMinSliceAssign_d unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] - b[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] - b[i])) - { - printf("[%d]: %g != %g - %g\n", i, c[i], a[i], b[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] + value - */ - -T[] _arraySliceExpAddSliceAssign_d(T[] a, T value, T[] b) -in -{ - assert(a.length == b.length); - assert(disjoint(a, b)); -} -body -{ - //printf("_arraySliceExpAddSliceAssign_d()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 version is 305% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - // Unaligned case - asm - { - mov EAX, bptr; - mov ESI, aptr; - mov EDI, n; - movsd XMM4, value; - shufpd XMM4, XMM4, 0; - - align 8; - startsseloop: - add ESI, 64; - movupd XMM0, [EAX]; - movupd XMM1, [EAX+16]; - movupd XMM2, [EAX+32]; - movupd XMM3, [EAX+48]; - add EAX, 64; - addpd XMM0, XMM4; - addpd XMM1, XMM4; - addpd XMM2, XMM4; - addpd XMM3, XMM4; - movupd [ESI+ 0-64], XMM0; - movupd [ESI+16-64], XMM1; - movupd [ESI+32-64], XMM2; - movupd [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloop; - - mov aptr, ESI; - mov bptr, EAX; - } - } - } - - while (aptr < aend) - *aptr++ = *bptr++ + value; - - return a; -} - -unittest -{ - printf("_arraySliceExpAddSliceAssign_d unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] + 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] + 6)) - { - printf("[%d]: %g != %g + 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] += value - */ - -T[] _arrayExpSliceAddass_d(T[] a, T value) -{ - //printf("_arrayExpSliceAddass_d(a.length = %d, value = %Lg)\n", a.length, cast(real)value); - auto aptr = a.ptr; - auto aend = aptr + a.length; - - version (D_InlineAsm_X86) - { - // SSE2 version is 114% faster - if (sse2() && a.length >= 8) - { - auto n = cast(T*)((cast(uint)aend) & ~7); - if (aptr < n) - - // Unaligned case - asm - { - mov ESI, aptr; - mov EDI, n; - movsd XMM4, value; - shufpd XMM4, XMM4, 0; - - align 8; - startsseloopa: - movupd XMM0, [ESI]; - movupd XMM1, [ESI+16]; - movupd XMM2, [ESI+32]; - movupd XMM3, [ESI+48]; - add ESI, 64; - addpd XMM0, XMM4; - addpd XMM1, XMM4; - addpd XMM2, XMM4; - addpd XMM3, XMM4; - movupd [ESI+ 0-64], XMM0; - movupd [ESI+16-64], XMM1; - movupd [ESI+32-64], XMM2; - movupd [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloopa; - - mov aptr, ESI; - } - } - } - - while (aptr < aend) - *aptr++ += value; - - return a; -} - -unittest -{ - printf("_arrayExpSliceAddass_d unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] += 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] + 6)) - { - printf("[%d]: %g != %g + 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] += b[] - */ - -T[] _arraySliceSliceAddass_d(T[] a, T[] b) -in -{ - assert (a.length == b.length); - assert (disjoint(a, b)); -} -body -{ - //printf("_arraySliceSliceAddass_d()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 version is 183% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - // Unaligned case - asm - { - mov ECX, bptr; // right operand - mov ESI, aptr; // destination operand - mov EDI, n; // end comparison - - align 8; - startsseloopb: - movupd XMM0, [ESI]; - movupd XMM1, [ESI+16]; - movupd XMM2, [ESI+32]; - movupd XMM3, [ESI+48]; - add ESI, 64; - movupd XMM4, [ECX]; - movupd XMM5, [ECX+16]; - movupd XMM6, [ECX+32]; - movupd XMM7, [ECX+48]; - add ECX, 64; - addpd XMM0, XMM4; - addpd XMM1, XMM5; - addpd XMM2, XMM6; - addpd XMM3, XMM7; - movupd [ESI+ 0-64], XMM0; - movupd [ESI+16-64], XMM1; - movupd [ESI+32-64], XMM2; - movupd [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloopb; - - mov aptr, ESI; - mov bptr, ECX; - } - } - } - - while (aptr < aend) - *aptr++ += *bptr++; - - return a; -} - -unittest -{ - printf("_arraySliceSliceAddass_d unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] += b[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] + b[i])) - { - printf("[%d]: %g != %g + %g\n", i, c[i], a[i], b[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] - value - */ - -T[] _arraySliceExpMinSliceAssign_d(T[] a, T value, T[] b) -in -{ - assert (a.length == b.length); - assert (disjoint(a, b)); -} -body -{ - //printf("_arraySliceExpMinSliceAssign_d()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 version is 305% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - // Unaligned case - asm - { - mov EAX, bptr; - mov ESI, aptr; - mov EDI, n; - movsd XMM4, value; - shufpd XMM4, XMM4, 0; - - align 8; - startsseloop: - add ESI, 64; - movupd XMM0, [EAX]; - movupd XMM1, [EAX+16]; - movupd XMM2, [EAX+32]; - movupd XMM3, [EAX+48]; - add EAX, 64; - subpd XMM0, XMM4; - subpd XMM1, XMM4; - subpd XMM2, XMM4; - subpd XMM3, XMM4; - movupd [ESI+ 0-64], XMM0; - movupd [ESI+16-64], XMM1; - movupd [ESI+32-64], XMM2; - movupd [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloop; - - mov aptr, ESI; - mov bptr, EAX; - } - } - } - - while (aptr < aend) - *aptr++ = *bptr++ - value; - - return a; -} - -unittest -{ - printf("_arraySliceExpMinSliceAssign_d unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] - 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] - 6)) - { - printf("[%d]: %g != %g - 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = value - b[] - */ - -T[] _arrayExpSliceMinSliceAssign_d(T[] a, T[] b, T value) -in -{ - assert (a.length == b.length); - assert (disjoint(a, b)); -} -body -{ - //printf("_arrayExpSliceMinSliceAssign_d()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 version is 66% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - // Unaligned case - asm - { - mov EAX, bptr; - mov ESI, aptr; - mov EDI, n; - movsd XMM4, value; - shufpd XMM4, XMM4, 0; - - align 8; - startsseloop: - add ESI, 64; - movapd XMM5, XMM4; - movapd XMM6, XMM4; - movupd XMM0, [EAX]; - movupd XMM1, [EAX+16]; - movupd XMM2, [EAX+32]; - movupd XMM3, [EAX+48]; - add EAX, 64; - subpd XMM5, XMM0; - subpd XMM6, XMM1; - movupd [ESI+ 0-64], XMM5; - movupd [ESI+16-64], XMM6; - movapd XMM5, XMM4; - movapd XMM6, XMM4; - subpd XMM5, XMM2; - subpd XMM6, XMM3; - movupd [ESI+32-64], XMM5; - movupd [ESI+48-64], XMM6; - cmp ESI, EDI; - jb startsseloop; - - mov aptr, ESI; - mov bptr, EAX; - } - } - } - - while (aptr < aend) - *aptr++ = value - *bptr++; - - return a; -} - -unittest -{ - printf("_arrayExpSliceMinSliceAssign_d unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = 6 - a[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(6 - a[i])) - { - printf("[%d]: %g != 6 - %g\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] -= value - */ - -T[] _arrayExpSliceMinass_d(T[] a, T value) -{ - //printf("_arrayExpSliceMinass_d(a.length = %d, value = %Lg)\n", a.length, cast(real)value); - auto aptr = a.ptr; - auto aend = aptr + a.length; - - version (D_InlineAsm_X86) - { - // SSE2 version is 115% faster - if (sse2() && a.length >= 8) - { - auto n = cast(T*)((cast(uint)aend) & ~7); - if (aptr < n) - - // Unaligned case - asm - { - mov ESI, aptr; - mov EDI, n; - movsd XMM4, value; - shufpd XMM4, XMM4, 0; - - align 8; - startsseloopa: - movupd XMM0, [ESI]; - movupd XMM1, [ESI+16]; - movupd XMM2, [ESI+32]; - movupd XMM3, [ESI+48]; - add ESI, 64; - subpd XMM0, XMM4; - subpd XMM1, XMM4; - subpd XMM2, XMM4; - subpd XMM3, XMM4; - movupd [ESI+ 0-64], XMM0; - movupd [ESI+16-64], XMM1; - movupd [ESI+32-64], XMM2; - movupd [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloopa; - - mov aptr, ESI; - } - } - } - - while (aptr < aend) - *aptr++ -= value; - - return a; -} - -unittest -{ - printf("_arrayExpSliceMinass_d unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] -= 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] - 6)) - { - printf("[%d]: %g != %g - 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] -= b[] - */ - -T[] _arraySliceSliceMinass_d(T[] a, T[] b) -in -{ - assert (a.length == b.length); - assert (disjoint(a, b)); -} -body -{ - //printf("_arraySliceSliceMinass_d()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 version is 183% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - // Unaligned case - asm - { - mov ECX, bptr; // right operand - mov ESI, aptr; // destination operand - mov EDI, n; // end comparison - - align 8; - startsseloopb: - movupd XMM0, [ESI]; - movupd XMM1, [ESI+16]; - movupd XMM2, [ESI+32]; - movupd XMM3, [ESI+48]; - add ESI, 64; - movupd XMM4, [ECX]; - movupd XMM5, [ECX+16]; - movupd XMM6, [ECX+32]; - movupd XMM7, [ECX+48]; - add ECX, 64; - subpd XMM0, XMM4; - subpd XMM1, XMM5; - subpd XMM2, XMM6; - subpd XMM3, XMM7; - movupd [ESI+ 0-64], XMM0; - movupd [ESI+16-64], XMM1; - movupd [ESI+32-64], XMM2; - movupd [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloopb; - - mov aptr, ESI; - mov bptr, ECX; - } - } - } - - while (aptr < aend) - *aptr++ -= *bptr++; - - return a; -} - -unittest -{ - printf("_arrayExpSliceMinass_d unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] -= 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] - 6)) - { - printf("[%d]: %g != %g - 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] * value - */ - -T[] _arraySliceExpMulSliceAssign_d(T[] a, T value, T[] b) -in -{ - assert(a.length == b.length); - assert(disjoint(a, b)); -} -body -{ - //printf("_arraySliceExpMulSliceAssign_d()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 version is 304% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - // Unaligned case - asm - { - mov EAX, bptr; - mov ESI, aptr; - mov EDI, n; - movsd XMM4, value; - shufpd XMM4, XMM4, 0; - - align 8; - startsseloop: - add ESI, 64; - movupd XMM0, [EAX]; - movupd XMM1, [EAX+16]; - movupd XMM2, [EAX+32]; - movupd XMM3, [EAX+48]; - add EAX, 64; - mulpd XMM0, XMM4; - mulpd XMM1, XMM4; - mulpd XMM2, XMM4; - mulpd XMM3, XMM4; - movupd [ESI+ 0-64], XMM0; - movupd [ESI+16-64], XMM1; - movupd [ESI+32-64], XMM2; - movupd [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloop; - - mov aptr, ESI; - mov bptr, EAX; - } - } - } - - while (aptr < aend) - *aptr++ = *bptr++ * value; - - return a; -} - -unittest -{ - printf("_arraySliceExpMulSliceAssign_d unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] * 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] * 6)) - { - printf("[%d]: %g != %g * 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] * c[] - */ - -T[] _arraySliceSliceMulSliceAssign_d(T[] a, T[] c, T[] b) -in -{ - assert(a.length == b.length && b.length == c.length); - assert(disjoint(a, b)); - assert(disjoint(a, c)); - assert(disjoint(b, c)); -} -body -{ - //printf("_arraySliceSliceMulSliceAssign_d()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - auto cptr = c.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 version is 329% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - // Unaligned case - asm - { - mov EAX, bptr; // left operand - mov ECX, cptr; // right operand - mov ESI, aptr; // destination operand - mov EDI, n; // end comparison - - align 8; - startsseloopb: - movupd XMM0, [EAX]; - movupd XMM1, [EAX+16]; - movupd XMM2, [EAX+32]; - movupd XMM3, [EAX+48]; - add ESI, 64; - movupd XMM4, [ECX]; - movupd XMM5, [ECX+16]; - movupd XMM6, [ECX+32]; - movupd XMM7, [ECX+48]; - add EAX, 64; - mulpd XMM0, XMM4; - mulpd XMM1, XMM5; - mulpd XMM2, XMM6; - mulpd XMM3, XMM7; - add ECX, 64; - movupd [ESI+ 0-64], XMM0; - movupd [ESI+16-64], XMM1; - movupd [ESI+32-64], XMM2; - movupd [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloopb; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - - while (aptr < aend) - *aptr++ = *bptr++ * *cptr++; - - return a; -} - -unittest -{ - printf("_arraySliceSliceMulSliceAssign_d unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] * b[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] * b[i])) - { - printf("[%d]: %g != %g * %g\n", i, c[i], a[i], b[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] *= value - */ - -T[] _arrayExpSliceMulass_d(T[] a, T value) -{ - //printf("_arrayExpSliceMulass_d(a.length = %d, value = %Lg)\n", a.length, cast(real)value); - auto aptr = a.ptr; - auto aend = aptr + a.length; - - version (D_InlineAsm_X86) - { - // SSE2 version is 109% faster - if (sse2() && a.length >= 8) - { - auto n = cast(T*)((cast(uint)aend) & ~7); - if (aptr < n) - - // Unaligned case - asm - { - mov ESI, aptr; - mov EDI, n; - movsd XMM4, value; - shufpd XMM4, XMM4, 0; - - align 8; - startsseloopa: - movupd XMM0, [ESI]; - movupd XMM1, [ESI+16]; - movupd XMM2, [ESI+32]; - movupd XMM3, [ESI+48]; - add ESI, 64; - mulpd XMM0, XMM4; - mulpd XMM1, XMM4; - mulpd XMM2, XMM4; - mulpd XMM3, XMM4; - movupd [ESI+ 0-64], XMM0; - movupd [ESI+16-64], XMM1; - movupd [ESI+32-64], XMM2; - movupd [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloopa; - - mov aptr, ESI; - } - } - } - - while (aptr < aend) - *aptr++ *= value; - - return a; -} - -unittest -{ - printf("_arrayExpSliceMulass_d unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] *= 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] * 6)) - { - printf("[%d]: %g != %g * 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] *= b[] - */ - -T[] _arraySliceSliceMulass_d(T[] a, T[] b) -in -{ - assert (a.length == b.length); - assert (disjoint(a, b)); -} -body -{ - //printf("_arraySliceSliceMulass_d()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 version is 205% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - // Unaligned case - asm - { - mov ECX, bptr; // right operand - mov ESI, aptr; // destination operand - mov EDI, n; // end comparison - - align 8; - startsseloopb: - movupd XMM0, [ESI]; - movupd XMM1, [ESI+16]; - movupd XMM2, [ESI+32]; - movupd XMM3, [ESI+48]; - add ESI, 64; - movupd XMM4, [ECX]; - movupd XMM5, [ECX+16]; - movupd XMM6, [ECX+32]; - movupd XMM7, [ECX+48]; - add ECX, 64; - mulpd XMM0, XMM4; - mulpd XMM1, XMM5; - mulpd XMM2, XMM6; - mulpd XMM3, XMM7; - movupd [ESI+ 0-64], XMM0; - movupd [ESI+16-64], XMM1; - movupd [ESI+32-64], XMM2; - movupd [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloopb; - - mov aptr, ESI; - mov bptr, ECX; - } - } - } - - while (aptr < aend) - *aptr++ *= *bptr++; - - return a; -} - -unittest -{ - printf("_arrayExpSliceMulass_d unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] *= 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] * 6)) - { - printf("[%d]: %g != %g * 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] / value - */ - -T[] _arraySliceExpDivSliceAssign_d(T[] a, T value, T[] b) -in -{ - assert(a.length == b.length); - assert(disjoint(a, b)); -} -body -{ - //printf("_arraySliceExpDivSliceAssign_d()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - /* Multiplying by the reciprocal is faster, but does - * not produce as accurate an answer. - */ - T recip = cast(T)1 / value; - - version (D_InlineAsm_X86) - { - // SSE2 version is 299% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - // Unaligned case - asm - { - mov EAX, bptr; - mov ESI, aptr; - mov EDI, n; - movsd XMM4, recip; - //movsd XMM4, value - //rcpsd XMM4, XMM4 - shufpd XMM4, XMM4, 0; - - align 8; - startsseloop: - add ESI, 64; - movupd XMM0, [EAX]; - movupd XMM1, [EAX+16]; - movupd XMM2, [EAX+32]; - movupd XMM3, [EAX+48]; - add EAX, 64; - mulpd XMM0, XMM4; - mulpd XMM1, XMM4; - mulpd XMM2, XMM4; - mulpd XMM3, XMM4; - //divpd XMM0, XMM4; - //divpd XMM1, XMM4; - //divpd XMM2, XMM4; - //divpd XMM3, XMM4; - movupd [ESI+ 0-64], XMM0; - movupd [ESI+16-64], XMM1; - movupd [ESI+32-64], XMM2; - movupd [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloop; - - mov aptr, ESI; - mov bptr, EAX; - } - } - } - - while (aptr < aend) - { - *aptr++ = *bptr++ / value; - //*aptr++ = *bptr++ * recip; - } - - return a; -} - -unittest -{ - printf("_arraySliceExpDivSliceAssign_d unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] / 8; - - for (int i = 0; i < dim; i++) - { - //printf("[%d]: %g ?= %g / 8\n", i, c[i], a[i]); - if (c[i] != cast(T)(a[i] / 8)) - { - printf("[%d]: %g != %g / 8\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] /= value - */ - -T[] _arrayExpSliceDivass_d(T[] a, T value) -{ - //printf("_arrayExpSliceDivass_d(a.length = %d, value = %Lg)\n", a.length, cast(real)value); - auto aptr = a.ptr; - auto aend = aptr + a.length; - - /* Multiplying by the reciprocal is faster, but does - * not produce as accurate an answer. - */ - T recip = cast(T)1 / value; - - version (D_InlineAsm_X86) - { - // SSE2 version is 65% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - // Unaligned case - asm - { - mov ESI, aptr; - mov EDI, n; - movsd XMM4, recip; - //movsd XMM4, value - //rcpsd XMM4, XMM4 - shufpd XMM4, XMM4, 0; - - align 8; - startsseloopa: - movupd XMM0, [ESI]; - movupd XMM1, [ESI+16]; - movupd XMM2, [ESI+32]; - movupd XMM3, [ESI+48]; - add ESI, 64; - mulpd XMM0, XMM4; - mulpd XMM1, XMM4; - mulpd XMM2, XMM4; - mulpd XMM3, XMM4; - //divpd XMM0, XMM4; - //divpd XMM1, XMM4; - //divpd XMM2, XMM4; - //divpd XMM3, XMM4; - movupd [ESI+ 0-64], XMM0; - movupd [ESI+16-64], XMM1; - movupd [ESI+32-64], XMM2; - movupd [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloopa; - - mov aptr, ESI; - } - } - } - - while (aptr < aend) - *aptr++ *= recip; - - return a; -} - - -unittest -{ - printf("_arrayExpSliceDivass_d unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] /= 8; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] / 8)) - { - printf("[%d]: %g != %g / 8\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] -= b[] * value - */ - -T[] _arraySliceExpMulSliceMinass_d(T[] a, T value, T[] b) -{ - return _arraySliceExpMulSliceAddass_d(a, -value, b); -} - -/*********************** - * Computes: - * a[] += b[] * value - */ - -T[] _arraySliceExpMulSliceAddass_d(T[] a, T value, T[] b) -in -{ - assert(a.length == b.length); - assert(disjoint(a, b)); -} -body -{ - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - // Handle remainder - while (aptr < aend) - *aptr++ += *bptr++ * value; - - return a; -} - -unittest -{ - printf("_arraySliceExpMulSliceAddass_d unittest\n"); - - cpuid = 1; - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 1; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - b[] = c[]; - c[] += a[] * 6; - - for (int i = 0; i < dim; i++) - { - //printf("[%d]: %g ?= %g + %g * 6\n", i, c[i], b[i], a[i]); - if (c[i] != cast(T)(b[i] + a[i] * 6)) - { - printf("[%d]: %g ?= %g + %g * 6\n", i, c[i], b[i], a[i]); - assert(0); - } - } - } - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/arrayfloat.d --- a/druntime/src/compiler/dmd/arrayfloat.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2309 +0,0 @@ -/** - * Contains SSE2 and MMX versions of certain operations for float. - * - * Copyright: Copyright Digital Mars 2008 - 2009. - * License: = 16) - { - version (log) printf("\tsse unaligned\n"); - auto n = aptr + (b.length & ~15); - - // Unaligned case - asm - { - mov EAX, bptr; // left operand - mov ECX, cptr; // right operand - mov ESI, aptr; // destination operand - mov EDI, n; // end comparison - - align 8; - startsseloopb: - movups XMM0, [EAX]; - movups XMM1, [EAX+16]; - movups XMM2, [EAX+32]; - movups XMM3, [EAX+48]; - add EAX, 64; - movups XMM4, [ECX]; - movups XMM5, [ECX+16]; - movups XMM6, [ECX+32]; - movups XMM7, [ECX+48]; - add ESI, 64; - addps XMM0, XMM4; - addps XMM1, XMM5; - addps XMM2, XMM6; - addps XMM3, XMM7; - add ECX, 64; - movups [ESI+ 0-64], XMM0; - movups [ESI+16-64], XMM1; - movups [ESI+32-64], XMM2; - movups [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloopb; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - else - // 3DNow! version is only 13% faster - if (amd3dnow() && b.length >= 8) - { - version (log) printf("\tamd3dnow\n"); - auto n = aptr + (b.length & ~7); - - asm - { - mov ESI, aptr; // destination operand - mov EDI, n; // end comparison - mov EAX, bptr; // left operand - mov ECX, cptr; // right operand - - align 4; - start3dnow: - movq MM0, [EAX]; - movq MM1, [EAX+8]; - movq MM2, [EAX+16]; - movq MM3, [EAX+24]; - pfadd MM0, [ECX]; - pfadd MM1, [ECX+8]; - pfadd MM2, [ECX+16]; - pfadd MM3, [ECX+24]; - movq [ESI], MM0; - movq [ESI+8], MM1; - movq [ESI+16], MM2; - movq [ESI+24], MM3; - add ECX, 32; - add ESI, 32; - add EAX, 32; - cmp ESI, EDI; - jb start3dnow; - - emms; - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - - // Handle remainder - version (log) if (aptr < aend) printf("\tbase\n"); - while (aptr < aend) - *aptr++ = *bptr++ + *cptr++; - - return a; -} - - -unittest -{ - printf("_arraySliceSliceAddSliceAssign_f unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] + b[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] + b[i])) - { - printf("[%d]: %g != %g + %g\n", i, c[i], a[i], b[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] - c[] - */ - -T[] _arraySliceSliceMinSliceAssign_f(T[] a, T[] c, T[] b) -in -{ - assert(a.length == b.length && b.length == c.length); - assert(disjoint(a, b)); - assert(disjoint(a, c)); - assert(disjoint(b, c)); -} -body -{ - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - auto cptr = c.ptr; - - version (D_InlineAsm_X86) - { - // SSE version is 834% faster - if (sse() && b.length >= 16) - { - auto n = aptr + (b.length & ~15); - - // Unaligned case - asm - { - mov EAX, bptr; // left operand - mov ECX, cptr; // right operand - mov ESI, aptr; // destination operand - mov EDI, n; // end comparison - - align 8; - startsseloopb: - movups XMM0, [EAX]; - movups XMM1, [EAX+16]; - movups XMM2, [EAX+32]; - movups XMM3, [EAX+48]; - add EAX, 64; - movups XMM4, [ECX]; - movups XMM5, [ECX+16]; - movups XMM6, [ECX+32]; - movups XMM7, [ECX+48]; - add ESI, 64; - subps XMM0, XMM4; - subps XMM1, XMM5; - subps XMM2, XMM6; - subps XMM3, XMM7; - add ECX, 64; - movups [ESI+ 0-64], XMM0; - movups [ESI+16-64], XMM1; - movups [ESI+32-64], XMM2; - movups [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloopb; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - else - // 3DNow! version is only 13% faster - if (amd3dnow() && b.length >= 8) - { - auto n = aptr + (b.length & ~7); - - asm - { - mov ESI, aptr; // destination operand - mov EDI, n; // end comparison - mov EAX, bptr; // left operand - mov ECX, cptr; // right operand - - align 4; - start3dnow: - movq MM0, [EAX]; - movq MM1, [EAX+8]; - movq MM2, [EAX+16]; - movq MM3, [EAX+24]; - pfsub MM0, [ECX]; - pfsub MM1, [ECX+8]; - pfsub MM2, [ECX+16]; - pfsub MM3, [ECX+24]; - movq [ESI], MM0; - movq [ESI+8], MM1; - movq [ESI+16], MM2; - movq [ESI+24], MM3; - add ECX, 32; - add ESI, 32; - add EAX, 32; - cmp ESI, EDI; - jb start3dnow; - - emms; - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - - // Handle remainder - while (aptr < aend) - *aptr++ = *bptr++ - *cptr++; - - return a; -} - - -unittest -{ - printf("_arraySliceSliceMinSliceAssign_f unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] - b[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] - b[i])) - { - printf("[%d]: %g != %gd - %g\n", i, c[i], a[i], b[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] + value - */ - -T[] _arraySliceExpAddSliceAssign_f(T[] a, T value, T[] b) -in -{ - assert(a.length == b.length); - assert(disjoint(a, b)); -} -body -{ - //printf("_arraySliceExpAddSliceAssign_f()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE version is 665% faster - if (sse() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - // Unaligned case - asm - { - mov EAX, bptr; - mov ESI, aptr; - mov EDI, n; - movss XMM4, value; - shufps XMM4, XMM4, 0; - - align 8; - startsseloop: - add ESI, 64; - movups XMM0, [EAX]; - movups XMM1, [EAX+16]; - movups XMM2, [EAX+32]; - movups XMM3, [EAX+48]; - add EAX, 64; - addps XMM0, XMM4; - addps XMM1, XMM4; - addps XMM2, XMM4; - addps XMM3, XMM4; - movups [ESI+ 0-64], XMM0; - movups [ESI+16-64], XMM1; - movups [ESI+32-64], XMM2; - movups [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloop; - - mov aptr, ESI; - mov bptr, EAX; - } - } - else - // 3DNow! version is 69% faster - if (amd3dnow() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - ulong w = *cast(uint *) &value; - ulong v = w | (w << 32L); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movq MM4, qword ptr [v]; - - align 8; - start3dnow: - movq MM0, [EAX]; - movq MM1, [EAX+8]; - movq MM2, [EAX+16]; - movq MM3, [EAX+24]; - pfadd MM0, MM4; - pfadd MM1, MM4; - pfadd MM2, MM4; - pfadd MM3, MM4; - movq [ESI], MM0; - movq [ESI+8], MM1; - movq [ESI+16], MM2; - movq [ESI+24], MM3; - add ESI, 32; - add EAX, 32; - cmp ESI, EDI; - jb start3dnow; - - emms; - mov aptr, ESI; - mov bptr, EAX; - } - } - } - - while (aptr < aend) - *aptr++ = *bptr++ + value; - - return a; -} - -unittest -{ - printf("_arraySliceExpAddSliceAssign_f unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] + 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] + 6)) - { - printf("[%d]: %g != %g + 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] += value - */ - -T[] _arrayExpSliceAddass_f(T[] a, T value) -{ - //printf("_arrayExpSliceAddass_f(a.length = %d, value = %Lg)\n", a.length, cast(real)value); - auto aptr = a.ptr; - auto aend = aptr + a.length; - - version (D_InlineAsm_X86) - { - // SSE version is 302% faster - if (sse() && a.length >= 16) - { - // align pointer - auto n = cast(T*)((cast(uint)aptr + 15) & ~15); - while (aptr < n) - *aptr++ += value; - n = cast(T*)((cast(uint)aend) & ~15); - if (aptr < n) - - // Aligned case - asm - { - mov ESI, aptr; - mov EDI, n; - movss XMM4, value; - shufps XMM4, XMM4, 0; - - align 8; - startsseloopa: - movaps XMM0, [ESI]; - movaps XMM1, [ESI+16]; - movaps XMM2, [ESI+32]; - movaps XMM3, [ESI+48]; - add ESI, 64; - addps XMM0, XMM4; - addps XMM1, XMM4; - addps XMM2, XMM4; - addps XMM3, XMM4; - movaps [ESI+ 0-64], XMM0; - movaps [ESI+16-64], XMM1; - movaps [ESI+32-64], XMM2; - movaps [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloopa; - - mov aptr, ESI; - } - } - else - // 3DNow! version is 63% faster - if (amd3dnow() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - ulong w = *cast(uint *) &value; - ulong v = w | (w << 32L); - - asm - { - mov ESI, dword ptr [aptr]; - mov EDI, dword ptr [n]; - movq MM4, qword ptr [v]; - - align 8; - start3dnow: - movq MM0, [ESI]; - movq MM1, [ESI+8]; - movq MM2, [ESI+16]; - movq MM3, [ESI+24]; - pfadd MM0, MM4; - pfadd MM1, MM4; - pfadd MM2, MM4; - pfadd MM3, MM4; - movq [ESI], MM0; - movq [ESI+8], MM1; - movq [ESI+16], MM2; - movq [ESI+24], MM3; - add ESI, 32; - cmp ESI, EDI; - jb start3dnow; - - emms; - mov dword ptr [aptr], ESI; - } - } - } - - while (aptr < aend) - *aptr++ += value; - - return a; -} - -unittest -{ - printf("_arrayExpSliceAddass_f unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] += 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] + 6)) - { - printf("[%d]: %g != %g + 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] += b[] - */ - -T[] _arraySliceSliceAddass_f(T[] a, T[] b) -in -{ - assert (a.length == b.length); - assert (disjoint(a, b)); -} -body -{ - //printf("_arraySliceSliceAddass_f()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE version is 468% faster - if (sse() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - // Unaligned case - asm - { - mov ECX, bptr; // right operand - mov ESI, aptr; // destination operand - mov EDI, n; // end comparison - - align 8; - startsseloopb: - movups XMM0, [ESI]; - movups XMM1, [ESI+16]; - movups XMM2, [ESI+32]; - movups XMM3, [ESI+48]; - add ESI, 64; - movups XMM4, [ECX]; - movups XMM5, [ECX+16]; - movups XMM6, [ECX+32]; - movups XMM7, [ECX+48]; - add ECX, 64; - addps XMM0, XMM4; - addps XMM1, XMM5; - addps XMM2, XMM6; - addps XMM3, XMM7; - movups [ESI+ 0-64], XMM0; - movups [ESI+16-64], XMM1; - movups [ESI+32-64], XMM2; - movups [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloopb; - - mov aptr, ESI; - mov bptr, ECX; - } - } - else - // 3DNow! version is 57% faster - if (amd3dnow() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - asm - { - mov ESI, dword ptr [aptr]; // destination operand - mov EDI, dword ptr [n]; // end comparison - mov ECX, dword ptr [bptr]; // right operand - - align 4; - start3dnow: - movq MM0, [ESI]; - movq MM1, [ESI+8]; - movq MM2, [ESI+16]; - movq MM3, [ESI+24]; - pfadd MM0, [ECX]; - pfadd MM1, [ECX+8]; - pfadd MM2, [ECX+16]; - pfadd MM3, [ECX+24]; - movq [ESI], MM0; - movq [ESI+8], MM1; - movq [ESI+16], MM2; - movq [ESI+24], MM3; - add ESI, 32; - add ECX, 32; - cmp ESI, EDI; - jb start3dnow; - - emms; - mov dword ptr [aptr], ESI; - mov dword ptr [bptr], ECX; - } - } - } - - while (aptr < aend) - *aptr++ += *bptr++; - - return a; -} - -unittest -{ - printf("_arraySliceSliceAddass_f unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] += b[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] + b[i])) - { - printf("[%d]: %g != %g + %g\n", i, c[i], a[i], b[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] - value - */ - -T[] _arraySliceExpMinSliceAssign_f(T[] a, T value, T[] b) -in -{ - assert (a.length == b.length); - assert (disjoint(a, b)); -} -body -{ - //printf("_arraySliceExpMinSliceAssign_f()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE version is 622% faster - if (sse() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - // Unaligned case - asm - { - mov EAX, bptr; - mov ESI, aptr; - mov EDI, n; - movss XMM4, value; - shufps XMM4, XMM4, 0; - - align 8; - startsseloop: - add ESI, 64; - movups XMM0, [EAX]; - movups XMM1, [EAX+16]; - movups XMM2, [EAX+32]; - movups XMM3, [EAX+48]; - add EAX, 64; - subps XMM0, XMM4; - subps XMM1, XMM4; - subps XMM2, XMM4; - subps XMM3, XMM4; - movups [ESI+ 0-64], XMM0; - movups [ESI+16-64], XMM1; - movups [ESI+32-64], XMM2; - movups [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloop; - - mov aptr, ESI; - mov bptr, EAX; - } - } - else - // 3DNow! version is 67% faster - if (amd3dnow() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - T[2] w; - - w[0] = w[1] = value; - - asm - { - mov ESI, dword ptr [aptr]; - mov EDI, dword ptr [n]; - mov EAX, dword ptr [bptr]; - movq MM4, qword ptr [w]; - - align 8; - start3dnow: - movq MM0, [EAX]; - movq MM1, [EAX+8]; - movq MM2, [EAX+16]; - movq MM3, [EAX+24]; - pfsub MM0, MM4; - pfsub MM1, MM4; - pfsub MM2, MM4; - pfsub MM3, MM4; - movq [ESI], MM0; - movq [ESI+8], MM1; - movq [ESI+16], MM2; - movq [ESI+24], MM3; - add ESI, 32; - add EAX, 32; - cmp ESI, EDI; - jb start3dnow; - - emms; - mov dword ptr [aptr], ESI; - mov dword ptr [bptr], EAX; - } - } - } - - while (aptr < aend) - *aptr++ = *bptr++ - value; - - return a; -} - -unittest -{ - printf("_arraySliceExpMinSliceAssign_f unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] - 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] - 6)) - { - printf("[%d]: %g != %g - 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = value - b[] - */ - -T[] _arrayExpSliceMinSliceAssign_f(T[] a, T[] b, T value) -in -{ - assert (a.length == b.length); - assert (disjoint(a, b)); -} -body -{ - //printf("_arrayExpSliceMinSliceAssign_f()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE version is 690% faster - if (sse() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - // Unaligned case - asm - { - mov EAX, bptr; - mov ESI, aptr; - mov EDI, n; - movss XMM4, value; - shufps XMM4, XMM4, 0; - - align 8; - startsseloop: - add ESI, 64; - movaps XMM5, XMM4; - movaps XMM6, XMM4; - movups XMM0, [EAX]; - movups XMM1, [EAX+16]; - movups XMM2, [EAX+32]; - movups XMM3, [EAX+48]; - add EAX, 64; - subps XMM5, XMM0; - subps XMM6, XMM1; - movups [ESI+ 0-64], XMM5; - movups [ESI+16-64], XMM6; - movaps XMM5, XMM4; - movaps XMM6, XMM4; - subps XMM5, XMM2; - subps XMM6, XMM3; - movups [ESI+32-64], XMM5; - movups [ESI+48-64], XMM6; - cmp ESI, EDI; - jb startsseloop; - - mov aptr, ESI; - mov bptr, EAX; - } - } - else - // 3DNow! version is 67% faster - if (amd3dnow() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - ulong w = *cast(uint *) &value; - ulong v = w | (w << 32L); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movq MM4, qword ptr [v]; - - align 8; - start3dnow: - movq MM0, [EAX]; - movq MM1, [EAX+8]; - movq MM2, [EAX+16]; - movq MM3, [EAX+24]; - pfsubr MM0, MM4; - pfsubr MM1, MM4; - pfsubr MM2, MM4; - pfsubr MM3, MM4; - movq [ESI], MM0; - movq [ESI+8], MM1; - movq [ESI+16], MM2; - movq [ESI+24], MM3; - add ESI, 32; - add EAX, 32; - cmp ESI, EDI; - jb start3dnow; - - emms; - mov aptr, ESI; - mov bptr, EAX; - } - } - } - - while (aptr < aend) - *aptr++ = value - *bptr++; - - return a; -} - -unittest -{ - printf("_arrayExpSliceMinSliceAssign_f unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = 6 - a[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(6 - a[i])) - { - printf("[%d]: %g != 6 - %g\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] -= value - */ - -T[] _arrayExpSliceMinass_f(T[] a, T value) -{ - //printf("_arrayExpSliceMinass_f(a.length = %d, value = %Lg)\n", a.length, cast(real)value); - auto aptr = a.ptr; - auto aend = aptr + a.length; - - version (D_InlineAsm_X86) - { - // SSE version is 304% faster - if (sse() && a.length >= 16) - { - // align pointer - auto n = cast(T*)((cast(uint)aptr + 15) & ~15); - while (aptr < n) - *aptr++ -= value; - n = cast(T*)((cast(uint)aend) & ~15); - if (aptr < n) - - // Aligned case - asm - { - mov ESI, aptr; - mov EDI, n; - movss XMM4, value; - shufps XMM4, XMM4, 0; - - align 8; - startsseloopa: - movaps XMM0, [ESI]; - movaps XMM1, [ESI+16]; - movaps XMM2, [ESI+32]; - movaps XMM3, [ESI+48]; - add ESI, 64; - subps XMM0, XMM4; - subps XMM1, XMM4; - subps XMM2, XMM4; - subps XMM3, XMM4; - movaps [ESI+ 0-64], XMM0; - movaps [ESI+16-64], XMM1; - movaps [ESI+32-64], XMM2; - movaps [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloopa; - - mov aptr, ESI; - } - } - else - // 3DNow! version is 63% faster - if (amd3dnow() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - ulong w = *cast(uint *) &value; - ulong v = w | (w << 32L); - - asm - { - mov ESI, dword ptr [aptr]; - mov EDI, dword ptr [n]; - movq MM4, qword ptr [v]; - - align 8; - start: - movq MM0, [ESI]; - movq MM1, [ESI+8]; - movq MM2, [ESI+16]; - movq MM3, [ESI+24]; - pfsub MM0, MM4; - pfsub MM1, MM4; - pfsub MM2, MM4; - pfsub MM3, MM4; - movq [ESI], MM0; - movq [ESI+8], MM1; - movq [ESI+16], MM2; - movq [ESI+24], MM3; - add ESI, 32; - cmp ESI, EDI; - jb start; - - emms; - mov dword ptr [aptr], ESI; - } - } - } - - while (aptr < aend) - *aptr++ -= value; - - return a; -} - -unittest -{ - printf("_arrayExpSliceminass_f unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] -= 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] - 6)) - { - printf("[%d]: %g != %g - 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] -= b[] - */ - -T[] _arraySliceSliceMinass_f(T[] a, T[] b) -in -{ - assert (a.length == b.length); - assert (disjoint(a, b)); -} -body -{ - //printf("_arraySliceSliceMinass_f()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE version is 468% faster - if (sse() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - // Unaligned case - asm - { - mov ECX, bptr; // right operand - mov ESI, aptr; // destination operand - mov EDI, n; // end comparison - - align 8; - startsseloopb: - movups XMM0, [ESI]; - movups XMM1, [ESI+16]; - movups XMM2, [ESI+32]; - movups XMM3, [ESI+48]; - add ESI, 64; - movups XMM4, [ECX]; - movups XMM5, [ECX+16]; - movups XMM6, [ECX+32]; - movups XMM7, [ECX+48]; - add ECX, 64; - subps XMM0, XMM4; - subps XMM1, XMM5; - subps XMM2, XMM6; - subps XMM3, XMM7; - movups [ESI+ 0-64], XMM0; - movups [ESI+16-64], XMM1; - movups [ESI+32-64], XMM2; - movups [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloopb; - - mov aptr, ESI; - mov bptr, ECX; - } - } - else - // 3DNow! version is 57% faster - if (amd3dnow() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - asm - { - mov ESI, dword ptr [aptr]; // destination operand - mov EDI, dword ptr [n]; // end comparison - mov ECX, dword ptr [bptr]; // right operand - - align 4; - start: - movq MM0, [ESI]; - movq MM1, [ESI+8]; - movq MM2, [ESI+16]; - movq MM3, [ESI+24]; - pfsub MM0, [ECX]; - pfsub MM1, [ECX+8]; - pfsub MM2, [ECX+16]; - pfsub MM3, [ECX+24]; - movq [ESI], MM0; - movq [ESI+8], MM1; - movq [ESI+16], MM2; - movq [ESI+24], MM3; - add ESI, 32; - add ECX, 32; - cmp ESI, EDI; - jb start; - - emms; - mov aptr, ESI; - mov bptr, ECX; - } - } - } - - while (aptr < aend) - *aptr++ -= *bptr++; - - return a; -} - -unittest -{ - printf("_arrayExpSliceMinass_f unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] -= 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] - 6)) - { - printf("[%d]: %g != %g - 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] * value - */ - -T[] _arraySliceExpMulSliceAssign_f(T[] a, T value, T[] b) -in -{ - assert(a.length == b.length); - assert(disjoint(a, b)); -} -body -{ - //printf("_arraySliceExpMulSliceAssign_f()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE version is 607% faster - if (sse() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - // Unaligned case - asm - { - mov EAX, bptr; - mov ESI, aptr; - mov EDI, n; - movss XMM4, value; - shufps XMM4, XMM4, 0; - - align 8; - startsseloop: - add ESI, 64; - movups XMM0, [EAX]; - movups XMM1, [EAX+16]; - movups XMM2, [EAX+32]; - movups XMM3, [EAX+48]; - add EAX, 64; - mulps XMM0, XMM4; - mulps XMM1, XMM4; - mulps XMM2, XMM4; - mulps XMM3, XMM4; - movups [ESI+ 0-64], XMM0; - movups [ESI+16-64], XMM1; - movups [ESI+32-64], XMM2; - movups [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloop; - - mov aptr, ESI; - mov bptr, EAX; - } - } - else - // 3DNow! version is 69% faster - if (amd3dnow() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - ulong w = *cast(uint *) &value; - ulong v = w | (w << 32L); - - asm - { - mov ESI, dword ptr [aptr]; - mov EDI, dword ptr [n]; - mov EAX, dword ptr [bptr]; - movq MM4, qword ptr [v]; - - align 8; - start: - movq MM0, [EAX]; - movq MM1, [EAX+8]; - movq MM2, [EAX+16]; - movq MM3, [EAX+24]; - pfmul MM0, MM4; - pfmul MM1, MM4; - pfmul MM2, MM4; - pfmul MM3, MM4; - movq [ESI], MM0; - movq [ESI+8], MM1; - movq [ESI+16], MM2; - movq [ESI+24], MM3; - add ESI, 32; - add EAX, 32; - cmp ESI, EDI; - jb start; - - emms; - mov aptr, ESI; - mov bptr, EAX; - } - } - } - - while (aptr < aend) - *aptr++ = *bptr++ * value; - - return a; -} - -unittest -{ - printf("_arraySliceExpMulSliceAssign_f unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] * 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] * 6)) - { - printf("[%d]: %g != %g * 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] * c[] - */ - -T[] _arraySliceSliceMulSliceAssign_f(T[] a, T[] c, T[] b) -in -{ - assert(a.length == b.length && b.length == c.length); - assert(disjoint(a, b)); - assert(disjoint(a, c)); - assert(disjoint(b, c)); -} -body -{ - //printf("_arraySliceSliceMulSliceAssign_f()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - auto cptr = c.ptr; - - version (D_InlineAsm_X86) - { - // SSE version is 833% faster - if (sse() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - // Unaligned case - asm - { - mov EAX, bptr; // left operand - mov ECX, cptr; // right operand - mov ESI, aptr; // destination operand - mov EDI, n; // end comparison - - align 8; - startsseloopb: - movups XMM0, [EAX]; - movups XMM1, [EAX+16]; - movups XMM2, [EAX+32]; - movups XMM3, [EAX+48]; - add ESI, 64; - movups XMM4, [ECX]; - movups XMM5, [ECX+16]; - movups XMM6, [ECX+32]; - movups XMM7, [ECX+48]; - add EAX, 64; - mulps XMM0, XMM4; - mulps XMM1, XMM5; - mulps XMM2, XMM6; - mulps XMM3, XMM7; - add ECX, 64; - movups [ESI+ 0-64], XMM0; - movups [ESI+16-64], XMM1; - movups [ESI+32-64], XMM2; - movups [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloopb; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - else - // 3DNow! version is only 13% faster - if (amd3dnow() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - asm - { - mov ESI, dword ptr [aptr]; // destination operand - mov EDI, dword ptr [n]; // end comparison - mov EAX, dword ptr [bptr]; // left operand - mov ECX, dword ptr [cptr]; // right operand - - align 4; - start: - movq MM0, [EAX]; - movq MM1, [EAX+8]; - movq MM2, [EAX+16]; - movq MM3, [EAX+24]; - pfmul MM0, [ECX]; - pfmul MM1, [ECX+8]; - pfmul MM2, [ECX+16]; - pfmul MM3, [ECX+24]; - movq [ESI], MM0; - movq [ESI+8], MM1; - movq [ESI+16], MM2; - movq [ESI+24], MM3; - add ECX, 32; - add ESI, 32; - add EAX, 32; - cmp ESI, EDI; - jb start; - - emms; - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - - while (aptr < aend) - *aptr++ = *bptr++ * *cptr++; - - return a; -} - -unittest -{ - printf("_arraySliceSliceMulSliceAssign_f unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] * b[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] * b[i])) - { - printf("[%d]: %g != %g * %g\n", i, c[i], a[i], b[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] *= value - */ - -T[] _arrayExpSliceMulass_f(T[] a, T value) -{ - //printf("_arrayExpSliceMulass_f(a.length = %d, value = %Lg)\n", a.length, cast(real)value); - auto aptr = a.ptr; - auto aend = aptr + a.length; - - version (D_InlineAsm_X86) - { - // SSE version is 303% faster - if (sse() && a.length >= 16) - { - // align pointer - auto n = cast(T*)((cast(uint)aptr + 15) & ~15); - while (aptr < n) - *aptr++ *= value; - n = cast(T*)((cast(uint)aend) & ~15); - if (aptr < n) - - // Aligned case - asm - { - mov ESI, aptr; - mov EDI, n; - movss XMM4, value; - shufps XMM4, XMM4, 0; - - align 8; - startsseloopa: - movaps XMM0, [ESI]; - movaps XMM1, [ESI+16]; - movaps XMM2, [ESI+32]; - movaps XMM3, [ESI+48]; - add ESI, 64; - mulps XMM0, XMM4; - mulps XMM1, XMM4; - mulps XMM2, XMM4; - mulps XMM3, XMM4; - movaps [ESI+ 0-64], XMM0; - movaps [ESI+16-64], XMM1; - movaps [ESI+32-64], XMM2; - movaps [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloopa; - - mov aptr, ESI; - } - } - else - // 3DNow! version is 63% faster - if (amd3dnow() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - ulong w = *cast(uint *) &value; - ulong v = w | (w << 32L); - - asm - { - mov ESI, dword ptr [aptr]; - mov EDI, dword ptr [n]; - movq MM4, qword ptr [v]; - - align 8; - start: - movq MM0, [ESI]; - movq MM1, [ESI+8]; - movq MM2, [ESI+16]; - movq MM3, [ESI+24]; - pfmul MM0, MM4; - pfmul MM1, MM4; - pfmul MM2, MM4; - pfmul MM3, MM4; - movq [ESI], MM0; - movq [ESI+8], MM1; - movq [ESI+16], MM2; - movq [ESI+24], MM3; - add ESI, 32; - cmp ESI, EDI; - jb start; - - emms; - mov dword ptr [aptr], ESI; - } - } - } - - while (aptr < aend) - *aptr++ *= value; - - return a; -} - -unittest -{ - printf("_arrayExpSliceMulass_f unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] *= 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] * 6)) - { - printf("[%d]: %g != %g * 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] *= b[] - */ - -T[] _arraySliceSliceMulass_f(T[] a, T[] b) -in -{ - assert (a.length == b.length); - assert (disjoint(a, b)); -} -body -{ - //printf("_arraySliceSliceMulass_f()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE version is 525% faster - if (sse() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - // Unaligned case - asm - { - mov ECX, bptr; // right operand - mov ESI, aptr; // destination operand - mov EDI, n; // end comparison - - align 8; - startsseloopb: - movups XMM0, [ESI]; - movups XMM1, [ESI+16]; - movups XMM2, [ESI+32]; - movups XMM3, [ESI+48]; - add ESI, 64; - movups XMM4, [ECX]; - movups XMM5, [ECX+16]; - movups XMM6, [ECX+32]; - movups XMM7, [ECX+48]; - add ECX, 64; - mulps XMM0, XMM4; - mulps XMM1, XMM5; - mulps XMM2, XMM6; - mulps XMM3, XMM7; - movups [ESI+ 0-64], XMM0; - movups [ESI+16-64], XMM1; - movups [ESI+32-64], XMM2; - movups [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloopb; - - mov aptr, ESI; - mov bptr, ECX; - } - } - else - // 3DNow! version is 57% faster - if (amd3dnow() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - asm - { - mov ESI, dword ptr [aptr]; // destination operand - mov EDI, dword ptr [n]; // end comparison - mov ECX, dword ptr [bptr]; // right operand - - align 4; - start: - movq MM0, [ESI]; - movq MM1, [ESI+8]; - movq MM2, [ESI+16]; - movq MM3, [ESI+24]; - pfmul MM0, [ECX]; - pfmul MM1, [ECX+8]; - pfmul MM2, [ECX+16]; - pfmul MM3, [ECX+24]; - movq [ESI], MM0; - movq [ESI+8], MM1; - movq [ESI+16], MM2; - movq [ESI+24], MM3; - add ESI, 32; - add ECX, 32; - cmp ESI, EDI; - jb start; - - emms; - mov dword ptr [aptr], ESI; - mov dword ptr [bptr], ECX; - } - } - } - - while (aptr < aend) - *aptr++ *= *bptr++; - - return a; -} - -unittest -{ - printf("_arrayExpSliceMulass_f unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] *= 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] * 6)) - { - printf("[%d]: %g != %g * 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] / value - */ - -T[] _arraySliceExpDivSliceAssign_f(T[] a, T value, T[] b) -in -{ - assert(a.length == b.length); - assert(disjoint(a, b)); -} -body -{ - //printf("_arraySliceExpDivSliceAssign_f()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - /* Multiplying by the reciprocal is faster, but does - * not produce as accurate an answer. - */ - T recip = cast(T)1 / value; - - version (D_InlineAsm_X86) - { - // SSE version is 587% faster - if (sse() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - // Unaligned case - asm - { - mov EAX, bptr; - mov ESI, aptr; - mov EDI, n; - movss XMM4, recip; - //movss XMM4, value - //rcpss XMM4, XMM4 - shufps XMM4, XMM4, 0; - - align 8; - startsseloop: - add ESI, 64; - movups XMM0, [EAX]; - movups XMM1, [EAX+16]; - movups XMM2, [EAX+32]; - movups XMM3, [EAX+48]; - add EAX, 64; - mulps XMM0, XMM4; - mulps XMM1, XMM4; - mulps XMM2, XMM4; - mulps XMM3, XMM4; - //divps XMM0, XMM4; - //divps XMM1, XMM4; - //divps XMM2, XMM4; - //divps XMM3, XMM4; - movups [ESI+ 0-64], XMM0; - movups [ESI+16-64], XMM1; - movups [ESI+32-64], XMM2; - movups [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloop; - - mov aptr, ESI; - mov bptr, EAX; - } - } - else - // 3DNow! version is 72% faster - if (amd3dnow() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - T[2] w = void; - - w[0] = recip; - w[1] = recip; - - asm - { - mov ESI, dword ptr [aptr]; - mov EDI, dword ptr [n]; - mov EAX, dword ptr [bptr]; - movq MM4, qword ptr [w]; - - align 8; - start: - movq MM0, [EAX]; - movq MM1, [EAX+8]; - movq MM2, [EAX+16]; - movq MM3, [EAX+24]; - pfmul MM0, MM4; - pfmul MM1, MM4; - pfmul MM2, MM4; - pfmul MM3, MM4; - movq [ESI], MM0; - movq [ESI+8], MM1; - movq [ESI+16], MM2; - movq [ESI+24], MM3; - add ESI, 32; - add EAX, 32; - cmp ESI, EDI; - jb start; - - emms; - mov dword ptr [aptr], ESI; - mov dword ptr [bptr], EAX; - } - } - } - - while (aptr < aend) - *aptr++ = *bptr++ * recip; - - return a; -} - -unittest -{ - printf("_arraySliceExpDivSliceAssign_f unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] / 8; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] / 8)) - { - printf("[%d]: %g != %g / 8\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] /= value - */ - -T[] _arrayExpSliceDivass_f(T[] a, T value) -{ - //printf("_arrayExpSliceDivass_f(a.length = %d, value = %Lg)\n", a.length, cast(real)value); - auto aptr = a.ptr; - auto aend = aptr + a.length; - - /* Multiplying by the reciprocal is faster, but does - * not produce as accurate an answer. - */ - T recip = cast(T)1 / value; - - version (D_InlineAsm_X86) - { - // SSE version is 245% faster - if (sse() && a.length >= 16) - { - // align pointer - auto n = cast(T*)((cast(uint)aptr + 15) & ~15); - while (aptr < n) - *aptr++ *= recip; - n = cast(T*)((cast(uint)aend) & ~15); - if (aptr < n) - - // Aligned case - asm - { - mov ESI, aptr; - mov EDI, n; - movss XMM4, recip; - //movss XMM4, value - //rcpss XMM4, XMM4 - shufps XMM4, XMM4, 0; - - align 8; - startsseloopa: - movaps XMM0, [ESI]; - movaps XMM1, [ESI+16]; - movaps XMM2, [ESI+32]; - movaps XMM3, [ESI+48]; - add ESI, 64; - mulps XMM0, XMM4; - mulps XMM1, XMM4; - mulps XMM2, XMM4; - mulps XMM3, XMM4; - //divps XMM0, XMM4; - //divps XMM1, XMM4; - //divps XMM2, XMM4; - //divps XMM3, XMM4; - movaps [ESI+ 0-64], XMM0; - movaps [ESI+16-64], XMM1; - movaps [ESI+32-64], XMM2; - movaps [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloopa; - - mov aptr, ESI; - } - } - else - // 3DNow! version is 57% faster - if (amd3dnow() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - T[2] w = void; - - w[0] = w[1] = recip; - - asm - { - mov ESI, dword ptr [aptr]; - mov EDI, dword ptr [n]; - movq MM4, qword ptr [w]; - - align 8; - start: - movq MM0, [ESI]; - movq MM1, [ESI+8]; - movq MM2, [ESI+16]; - movq MM3, [ESI+24]; - pfmul MM0, MM4; - pfmul MM1, MM4; - pfmul MM2, MM4; - pfmul MM3, MM4; - movq [ESI], MM0; - movq [ESI+8], MM1; - movq [ESI+16], MM2; - movq [ESI+24], MM3; - add ESI, 32; - cmp ESI, EDI; - jb start; - - emms; - mov dword ptr [aptr], ESI; - } - } - } - - while (aptr < aend) - *aptr++ *= recip; - - return a; -} - -unittest -{ - printf("_arrayExpSliceDivass_f unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] /= 8; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] / 8)) - { - printf("[%d]: %g != %g / 8\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] -= b[] * value - */ - -T[] _arraySliceExpMulSliceMinass_f(T[] a, T value, T[] b) -{ - return _arraySliceExpMulSliceAddass_f(a, -value, b); -} - -/*********************** - * Computes: - * a[] += b[] * value - */ - -T[] _arraySliceExpMulSliceAddass_f(T[] a, T value, T[] b) -in -{ - assert(a.length == b.length); - assert(disjoint(a, b)); -} -body -{ - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - // Handle remainder - while (aptr < aend) - *aptr++ += *bptr++ * value; - - return a; -} - -unittest -{ - printf("_arraySliceExpMulSliceAddass_f unittest\n"); - - cpuid = 1; - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 1; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - b[] = c[]; - c[] += a[] * 6; - - for (int i = 0; i < dim; i++) - { - //printf("[%d]: %g ?= %g + %g * 6\n", i, c[i], b[i], a[i]); - if (c[i] != cast(T)(b[i] + a[i] * 6)) - { - printf("[%d]: %g ?= %g + %g * 6\n", i, c[i], b[i], a[i]); - assert(0); - } - } - } - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/arrayint.d --- a/druntime/src/compiler/dmd/arrayint.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2430 +0,0 @@ -/** - * Contains MMX versions of certain operations for dchar, int, and uint ('w', - * 'i' and 'k' suffixes). - * - * Copyright: Copyright Digital Mars 2008 - 2009. - * License: = 8) - { - auto n = aptr + (a.length & ~7); - - uint l = value; - - if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startaddsse2u: - add ESI, 32; - movdqu XMM0, [EAX]; - movdqu XMM1, [EAX+16]; - add EAX, 32; - paddd XMM0, XMM2; - paddd XMM1, XMM2; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startaddsse2u; - - mov aptr, ESI; - mov bptr, EAX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startaddsse2a: - add ESI, 32; - movdqa XMM0, [EAX]; - movdqa XMM1, [EAX+16]; - add EAX, 32; - paddd XMM0, XMM2; - paddd XMM1, XMM2; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startaddsse2a; - - mov aptr, ESI; - mov bptr, EAX; - } - } - } - else - // MMX version is 298% faster - if (mmx() && a.length >= 4) - { - auto n = aptr + (a.length & ~3); - - ulong l = cast(uint) value | (cast(ulong)cast(uint) value << 32); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movq MM2, l; - - align 4; - startmmx: - add ESI, 16; - movq MM0, [EAX]; - movq MM1, [EAX+8]; - add EAX, 16; - paddd MM0, MM2; - paddd MM1, MM2; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - mov bptr, EAX; - } - } - else - if (a.length >= 2) - { - auto n = aptr + (a.length & ~1); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov EDX, value; - - align 4; - start386: - add ESI, 8; - mov EBX, [EAX]; - mov ECX, [EAX+4]; - add EAX, 8; - add EBX, EDX; - add ECX, EDX; - mov [ESI -8], EBX; - mov [ESI+4-8], ECX; - cmp ESI, EDI; - jb start386; - - mov aptr, ESI; - mov bptr, EAX; - } - } - } - - while (aptr < aend) - *aptr++ = *bptr++ + value; - - return a; -} - -unittest -{ - printf("_arraySliceExpAddSliceAssign_i unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] + 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] + 6)) - { - printf("[%d]: %d != %d + 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] + c[] - */ - -T[] _arraySliceSliceAddSliceAssign_w(T[] a, T[] c, T[] b) -{ - return _arraySliceSliceAddSliceAssign_i(a, c, b); -} - -T[] _arraySliceSliceAddSliceAssign_k(T[] a, T[] c, T[] b) -{ - return _arraySliceSliceAddSliceAssign_i(a, c, b); -} - -T[] _arraySliceSliceAddSliceAssign_i(T[] a, T[] c, T[] b) -in -{ - assert(a.length == b.length && b.length == c.length); - assert(disjoint(a, b)); - assert(disjoint(a, c)); - assert(disjoint(b, c)); -} -body -{ - //printf("_arraySliceSliceAddSliceAssign_i()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - auto cptr = c.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 1710% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - if (((cast(uint) aptr | cast(uint) bptr | cast(uint) cptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 4; - startsse2u: - add ESI, 32; - movdqu XMM0, [EAX]; - movdqu XMM2, [ECX]; - movdqu XMM1, [EAX+16]; - movdqu XMM3, [ECX+16]; - add EAX, 32; - add ECX, 32; - paddd XMM0, XMM2; - paddd XMM1, XMM3; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2u; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 4; - startsse2a: - add ESI, 32; - movdqa XMM0, [EAX]; - movdqa XMM2, [ECX]; - movdqa XMM1, [EAX+16]; - movdqa XMM3, [ECX+16]; - add EAX, 32; - add ECX, 32; - paddd XMM0, XMM2; - paddd XMM1, XMM3; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2a; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - else - // MMX version is 995% faster - if (mmx() && a.length >= 4) - { - auto n = aptr + (a.length & ~3); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 4; - startmmx: - add ESI, 16; - movq MM0, [EAX]; - movq MM2, [ECX]; - movq MM1, [EAX+8]; - movq MM3, [ECX+8]; - add EAX, 16; - add ECX, 16; - paddd MM0, MM2; - paddd MM1, MM3; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - -normal: - while (aptr < aend) - *aptr++ = *bptr++ + *cptr++; - - return a; -} - -unittest -{ - printf("_arraySliceSliceAddSliceAssign_i unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] + b[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] + b[i])) - { - printf("[%d]: %d != %d + %d\n", i, c[i], a[i], b[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] += value - */ - -T[] _arrayExpSliceAddass_w(T[] a, T value) -{ - return _arrayExpSliceAddass_i(a, value); -} - -T[] _arrayExpSliceAddass_k(T[] a, T value) -{ - return _arrayExpSliceAddass_i(a, value); -} - -T[] _arrayExpSliceAddass_i(T[] a, T value) -{ - //printf("_arrayExpSliceAddass_i(a.length = %d, value = %Lg)\n", a.length, cast(real)value); - auto aptr = a.ptr; - auto aend = aptr + a.length; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 83% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - uint l = value; - - if (((cast(uint) aptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startaddsse2u: - movdqu XMM0, [ESI]; - movdqu XMM1, [ESI+16]; - add ESI, 32; - paddd XMM0, XMM2; - paddd XMM1, XMM2; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startaddsse2u; - - mov aptr, ESI; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startaddsse2a: - movdqa XMM0, [ESI]; - movdqa XMM1, [ESI+16]; - add ESI, 32; - paddd XMM0, XMM2; - paddd XMM1, XMM2; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startaddsse2a; - - mov aptr, ESI; - } - } - } - else - // MMX version is 81% faster - if (mmx() && a.length >= 4) - { - auto n = aptr + (a.length & ~3); - - ulong l = cast(uint) value | (cast(ulong)cast(uint) value << 32); - - asm - { - mov ESI, aptr; - mov EDI, n; - movq MM2, l; - - align 4; - startmmx: - movq MM0, [ESI]; - movq MM1, [ESI+8]; - add ESI, 16; - paddd MM0, MM2; - paddd MM1, MM2; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - } - } - else - if (a.length >= 2) - { - auto n = aptr + (a.length & ~1); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EDX, value; - - align 4; - start386: - mov EBX, [ESI]; - mov ECX, [ESI+4]; - add ESI, 8; - add EBX, EDX; - add ECX, EDX; - mov [ESI -8], EBX; - mov [ESI+4-8], ECX; - cmp ESI, EDI; - jb start386; - - mov aptr, ESI; - } - } - } - - while (aptr < aend) - *aptr++ += value; - - return a; -} - -unittest -{ - printf("_arrayExpSliceAddass_i unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - a[] += 6; - - for (int i = 0; i < dim; i++) - { - if (a[i] != cast(T)(c[i] + 6)) - { - printf("[%d]: %d != %d + 6\n", i, a[i], c[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] += b[] - */ - -T[] _arraySliceSliceAddass_w(T[] a, T[] b) -{ - return _arraySliceSliceAddass_i(a, b); -} - -T[] _arraySliceSliceAddass_k(T[] a, T[] b) -{ - return _arraySliceSliceAddass_i(a, b); -} - -T[] _arraySliceSliceAddass_i(T[] a, T[] b) -in -{ - assert (a.length == b.length); - assert (disjoint(a, b)); -} -body -{ - //printf("_arraySliceSliceAddass_i()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 695% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 4; - startsse2u: - movdqu XMM0, [ESI]; - movdqu XMM2, [ECX]; - movdqu XMM1, [ESI+16]; - movdqu XMM3, [ECX+16]; - add ESI, 32; - add ECX, 32; - paddd XMM0, XMM2; - paddd XMM1, XMM3; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2u; - - mov aptr, ESI; - mov bptr, ECX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 4; - startsse2a: - movdqa XMM0, [ESI]; - movdqa XMM2, [ECX]; - movdqa XMM1, [ESI+16]; - movdqa XMM3, [ECX+16]; - add ESI, 32; - add ECX, 32; - paddd XMM0, XMM2; - paddd XMM1, XMM3; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2a; - - mov aptr, ESI; - mov bptr, ECX; - } - } - } - else - // MMX version is 471% faster - if (mmx() && a.length >= 4) - { - auto n = aptr + (a.length & ~3); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 4; - startmmx: - movq MM0, [ESI]; - movq MM2, [ECX]; - movq MM1, [ESI+8]; - movq MM3, [ECX+8]; - add ESI, 16; - add ECX, 16; - paddd MM0, MM2; - paddd MM1, MM3; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - mov bptr, ECX; - } - } - } - -normal: - while (aptr < aend) - *aptr++ += *bptr++; - - return a; -} - -unittest -{ - printf("_arraySliceSliceAddass_i unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - b[] = c[]; - c[] += a[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(b[i] + a[i])) - { - printf("[%d]: %d != %d + %d\n", i, c[i], b[i], a[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] - value - */ - -T[] _arraySliceExpMinSliceAssign_w(T[] a, T value, T[] b) -{ - return _arraySliceExpMinSliceAssign_i(a, value, b); -} - -T[] _arraySliceExpMinSliceAssign_k(T[] a, T value, T[] b) -{ - return _arraySliceExpMinSliceAssign_i(a, value, b); -} - -T[] _arraySliceExpMinSliceAssign_i(T[] a, T value, T[] b) -in -{ - assert(a.length == b.length); - assert(disjoint(a, b)); -} -body -{ - //printf("_arraySliceExpMinSliceAssign_i()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 400% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - uint l = value; - - if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startaddsse2u: - add ESI, 32; - movdqu XMM0, [EAX]; - movdqu XMM1, [EAX+16]; - add EAX, 32; - psubd XMM0, XMM2; - psubd XMM1, XMM2; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startaddsse2u; - - mov aptr, ESI; - mov bptr, EAX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startaddsse2a: - add ESI, 32; - movdqa XMM0, [EAX]; - movdqa XMM1, [EAX+16]; - add EAX, 32; - psubd XMM0, XMM2; - psubd XMM1, XMM2; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startaddsse2a; - - mov aptr, ESI; - mov bptr, EAX; - } - } - } - else - // MMX version is 315% faster - if (mmx() && a.length >= 4) - { - auto n = aptr + (a.length & ~3); - - ulong l = cast(uint) value | (cast(ulong)cast(uint) value << 32); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movq MM2, l; - - align 4; - startmmx: - add ESI, 16; - movq MM0, [EAX]; - movq MM1, [EAX+8]; - add EAX, 16; - psubd MM0, MM2; - psubd MM1, MM2; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - mov bptr, EAX; - } - } - else - if (a.length >= 2) - { - auto n = aptr + (a.length & ~1); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov EDX, value; - - align 4; - start386: - add ESI, 8; - mov EBX, [EAX]; - mov ECX, [EAX+4]; - add EAX, 8; - sub EBX, EDX; - sub ECX, EDX; - mov [ESI -8], EBX; - mov [ESI+4-8], ECX; - cmp ESI, EDI; - jb start386; - - mov aptr, ESI; - mov bptr, EAX; - } - } - } - - while (aptr < aend) - *aptr++ = *bptr++ - value; - - return a; -} - -unittest -{ - printf("_arraySliceExpMinSliceAssign_i unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] - 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] - 6)) - { - printf("[%d]: %d != %d - 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = value - b[] - */ - -T[] _arrayExpSliceMinSliceAssign_w(T[] a, T[] b, T value) -{ - return _arrayExpSliceMinSliceAssign_i(a, b, value); -} - -T[] _arrayExpSliceMinSliceAssign_k(T[] a, T[] b, T value) -{ - return _arrayExpSliceMinSliceAssign_i(a, b, value); -} - -T[] _arrayExpSliceMinSliceAssign_i(T[] a, T[] b, T value) -in -{ - assert(a.length == b.length); - assert(disjoint(a, b)); -} -body -{ - //printf("_arrayExpSliceMinSliceAssign_i()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 1812% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - uint l = value; - - if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM4, l; - pshufd XMM4, XMM4, 0; - - align 4; - startaddsse2u: - add ESI, 32; - movdqu XMM2, [EAX]; - movdqu XMM3, [EAX+16]; - movdqa XMM0, XMM4; - movdqa XMM1, XMM4; - add EAX, 32; - psubd XMM0, XMM2; - psubd XMM1, XMM3; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startaddsse2u; - - mov aptr, ESI; - mov bptr, EAX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM4, l; - pshufd XMM4, XMM4, 0; - - align 4; - startaddsse2a: - add ESI, 32; - movdqa XMM2, [EAX]; - movdqa XMM3, [EAX+16]; - movdqa XMM0, XMM4; - movdqa XMM1, XMM4; - add EAX, 32; - psubd XMM0, XMM2; - psubd XMM1, XMM3; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startaddsse2a; - - mov aptr, ESI; - mov bptr, EAX; - } - } - } - else - // MMX version is 1077% faster - if (mmx() && a.length >= 4) - { - auto n = aptr + (a.length & ~3); - - ulong l = cast(uint) value | (cast(ulong)cast(uint) value << 32); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movq MM4, l; - - align 4; - startmmx: - add ESI, 16; - movq MM2, [EAX]; - movq MM3, [EAX+8]; - movq MM0, MM4; - movq MM1, MM4; - add EAX, 16; - psubd MM0, MM2; - psubd MM1, MM3; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - mov bptr, EAX; - } - } - } - - while (aptr < aend) - *aptr++ = value - *bptr++; - - return a; -} - -unittest -{ - printf("_arrayExpSliceMinSliceAssign_i unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = 6 - a[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(6 - a[i])) - { - printf("[%d]: %d != 6 - %d\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] - c[] - */ - -T[] _arraySliceSliceMinSliceAssign_w(T[] a, T[] c, T[] b) -{ - return _arraySliceSliceMinSliceAssign_i(a, c, b); -} - -T[] _arraySliceSliceMinSliceAssign_k(T[] a, T[] c, T[] b) -{ - return _arraySliceSliceMinSliceAssign_i(a, c, b); -} - -T[] _arraySliceSliceMinSliceAssign_i(T[] a, T[] c, T[] b) -in -{ - assert(a.length == b.length && b.length == c.length); - assert(disjoint(a, b)); - assert(disjoint(a, c)); - assert(disjoint(b, c)); -} -body -{ - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - auto cptr = c.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 1721% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - if (((cast(uint) aptr | cast(uint) bptr | cast(uint) cptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 4; - startsse2u: - add ESI, 32; - movdqu XMM0, [EAX]; - movdqu XMM2, [ECX]; - movdqu XMM1, [EAX+16]; - movdqu XMM3, [ECX+16]; - add EAX, 32; - add ECX, 32; - psubd XMM0, XMM2; - psubd XMM1, XMM3; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2u; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 4; - startsse2a: - add ESI, 32; - movdqa XMM0, [EAX]; - movdqa XMM2, [ECX]; - movdqa XMM1, [EAX+16]; - movdqa XMM3, [ECX+16]; - add EAX, 32; - add ECX, 32; - psubd XMM0, XMM2; - psubd XMM1, XMM3; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2a; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - else - // MMX version is 1002% faster - if (mmx() && a.length >= 4) - { - auto n = aptr + (a.length & ~3); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 4; - startmmx: - add ESI, 16; - movq MM0, [EAX]; - movq MM2, [ECX]; - movq MM1, [EAX+8]; - movq MM3, [ECX+8]; - add EAX, 16; - add ECX, 16; - psubd MM0, MM2; - psubd MM1, MM3; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - - while (aptr < aend) - *aptr++ = *bptr++ - *cptr++; - - return a; -} - -unittest -{ - printf("_arraySliceSliceMinSliceAssign_i unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] - b[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] - b[i])) - { - printf("[%d]: %d != %d - %d\n", i, c[i], a[i], b[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] -= value - */ - -T[] _arrayExpSliceMinass_w(T[] a, T value) -{ - return _arrayExpSliceMinass_i(a, value); -} - -T[] _arrayExpSliceMinass_k(T[] a, T value) -{ - return _arrayExpSliceMinass_i(a, value); -} - -T[] _arrayExpSliceMinass_i(T[] a, T value) -{ - //printf("_arrayExpSliceMinass_i(a.length = %d, value = %Lg)\n", a.length, cast(real)value); - auto aptr = a.ptr; - auto aend = aptr + a.length; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 81% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - uint l = value; - - if (((cast(uint) aptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startaddsse2u: - movdqu XMM0, [ESI]; - movdqu XMM1, [ESI+16]; - add ESI, 32; - psubd XMM0, XMM2; - psubd XMM1, XMM2; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startaddsse2u; - - mov aptr, ESI; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startaddsse2a: - movdqa XMM0, [ESI]; - movdqa XMM1, [ESI+16]; - add ESI, 32; - psubd XMM0, XMM2; - psubd XMM1, XMM2; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startaddsse2a; - - mov aptr, ESI; - } - } - } - else - // MMX version is 81% faster - if (mmx() && a.length >= 4) - { - auto n = aptr + (a.length & ~3); - - ulong l = cast(uint) value | (cast(ulong)cast(uint) value << 32); - - asm - { - mov ESI, aptr; - mov EDI, n; - movq MM2, l; - - align 4; - startmmx: - movq MM0, [ESI]; - movq MM1, [ESI+8]; - add ESI, 16; - psubd MM0, MM2; - psubd MM1, MM2; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - } - } - else - if (a.length >= 2) - { - auto n = aptr + (a.length & ~1); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EDX, value; - - align 4; - start386: - mov EBX, [ESI]; - mov ECX, [ESI+4]; - add ESI, 8; - sub EBX, EDX; - sub ECX, EDX; - mov [ESI -8], EBX; - mov [ESI+4-8], ECX; - cmp ESI, EDI; - jb start386; - - mov aptr, ESI; - } - } - } - - while (aptr < aend) - *aptr++ -= value; - - return a; -} - -unittest -{ - printf("_arrayExpSliceMinass_i unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - a[] -= 6; - - for (int i = 0; i < dim; i++) - { - if (a[i] != cast(T)(c[i] - 6)) - { - printf("[%d]: %d != %d - 6\n", i, a[i], c[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] -= b[] - */ - -T[] _arraySliceSliceMinass_w(T[] a, T[] b) -{ - return _arraySliceSliceMinass_i(a, b); -} - -T[] _arraySliceSliceMinass_k(T[] a, T[] b) -{ - return _arraySliceSliceMinass_i(a, b); -} - -T[] _arraySliceSliceMinass_i(T[] a, T[] b) -in -{ - assert (a.length == b.length); - assert (disjoint(a, b)); -} -body -{ - //printf("_arraySliceSliceMinass_i()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 731% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 4; - startsse2u: - movdqu XMM0, [ESI]; - movdqu XMM2, [ECX]; - movdqu XMM1, [ESI+16]; - movdqu XMM3, [ECX+16]; - add ESI, 32; - add ECX, 32; - psubd XMM0, XMM2; - psubd XMM1, XMM3; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2u; - - mov aptr, ESI; - mov bptr, ECX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 4; - startsse2a: - movdqa XMM0, [ESI]; - movdqa XMM2, [ECX]; - movdqa XMM1, [ESI+16]; - movdqa XMM3, [ECX+16]; - add ESI, 32; - add ECX, 32; - psubd XMM0, XMM2; - psubd XMM1, XMM3; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2a; - - mov aptr, ESI; - mov bptr, ECX; - } - } - } - else - // MMX version is 441% faster - if (mmx() && a.length >= 4) - { - auto n = aptr + (a.length & ~3); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 4; - startmmx: - movq MM0, [ESI]; - movq MM2, [ECX]; - movq MM1, [ESI+8]; - movq MM3, [ECX+8]; - add ESI, 16; - add ECX, 16; - psubd MM0, MM2; - psubd MM1, MM3; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - mov bptr, ECX; - } - } - } - - while (aptr < aend) - *aptr++ -= *bptr++; - - return a; -} - -unittest -{ - printf("_arraySliceSliceMinass_i unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - b[] = c[]; - c[] -= a[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(b[i] - a[i])) - { - printf("[%d]: %d != %d - %d\n", i, c[i], b[i], a[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] * value - */ - -T[] _arraySliceExpMulSliceAssign_w(T[] a, T value, T[] b) -{ - return _arraySliceExpMulSliceAssign_i(a, value, b); -} - -T[] _arraySliceExpMulSliceAssign_k(T[] a, T value, T[] b) -{ - return _arraySliceExpMulSliceAssign_i(a, value, b); -} - -T[] _arraySliceExpMulSliceAssign_i(T[] a, T value, T[] b) -in -{ - assert(a.length == b.length); - assert(disjoint(a, b)); -} -body -{ - //printf("_arraySliceExpMulSliceAssign_i()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (none) // multiplying a pair is not supported by MMX - { - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 1380% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - uint l = value; - - if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0) - { - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startsse2u: - add ESI, 32; - movdqu XMM0, [EAX]; - movdqu XMM1, [EAX+16]; - add EAX, 32; - pmuludq XMM0, XMM2; - pmuludq XMM1, XMM2; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2u; - - mov aptr, ESI; - mov bptr, EAX; - } - } - else - { - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startsse2a: - add ESI, 32; - movdqa XMM0, [EAX]; - movdqa XMM1, [EAX+16]; - add EAX, 32; - pmuludq XMM0, XMM2; - pmuludq XMM1, XMM2; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2a; - - mov aptr, ESI; - mov bptr, EAX; - } - } - } - else - { - // MMX version is 1380% faster - if (mmx() && a.length >= 4) - { - auto n = aptr + (a.length & ~3); - - ulong l = cast(uint) value | (cast(ulong)cast(uint) value << 32); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movq MM2, l; - - align 4; - startmmx: - add ESI, 16; - movq MM0, [EAX]; - movq MM1, [EAX+8]; - add EAX, 16; - pmuludq MM0, MM2; // only multiplies low 32 bits - pmuludq MM1, MM2; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - mov bptr, EAX; - } - } - } - } - } - - while (aptr < aend) - *aptr++ = *bptr++ * value; - - return a; -} - -unittest -{ - printf("_arraySliceExpMulSliceAssign_s unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] * 6; - - for (int i = 0; i < dim; i++) - { - //printf("[%d]: %d ?= %d * 6\n", i, c[i], a[i]); - if (c[i] != cast(T)(a[i] * 6)) - { - printf("[%d]: %d != %d * 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] * c[] - */ - -T[] _arraySliceSliceMulSliceAssign_w(T[] a, T[] c, T[] b) -{ - return _arraySliceSliceMulSliceAssign_i(a, c, b); -} - -T[] _arraySliceSliceMulSliceAssign_k(T[] a, T[] c, T[] b) -{ - return _arraySliceSliceMulSliceAssign_i(a, c, b); -} - -T[] _arraySliceSliceMulSliceAssign_i(T[] a, T[] c, T[] b) -in -{ - assert(a.length == b.length && b.length == c.length); - assert(disjoint(a, b)); - assert(disjoint(a, c)); - assert(disjoint(b, c)); -} -body -{ - //printf("_arraySliceSliceMulSliceAssign_i()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - auto cptr = c.ptr; - - version (none) - { - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 1407% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - if (((cast(uint) aptr | cast(uint) bptr | cast(uint) cptr) & 15) != 0) - { - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 4; - startsse2u: - add ESI, 32; - movdqu XMM0, [EAX]; - movdqu XMM2, [ECX]; - movdqu XMM1, [EAX+16]; - movdqu XMM3, [ECX+16]; - add EAX, 32; - add ECX, 32; - pmuludq XMM0, XMM2; - pmuludq XMM1, XMM3; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2u; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - else - { - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 4; - startsse2a: - add ESI, 32; - movdqa XMM0, [EAX]; - movdqa XMM2, [ECX]; - movdqa XMM1, [EAX+16]; - movdqa XMM3, [ECX+16]; - add EAX, 32; - add ECX, 32; - pmuludq XMM0, XMM2; - pmuludq XMM1, XMM3; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2a; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - else - // MMX version is 1029% faster - if (mmx() && a.length >= 4) - { - auto n = aptr + (a.length & ~3); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 4; - startmmx: - add ESI, 16; - movq MM0, [EAX]; - movq MM2, [ECX]; - movq MM1, [EAX+8]; - movq MM3, [ECX+8]; - add EAX, 16; - add ECX, 16; - pmuludq MM0, MM2; - pmuludq MM1, MM3; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - } - - while (aptr < aend) - *aptr++ = *bptr++ * *cptr++; - - return a; -} - -unittest -{ - printf("_arraySliceSliceMulSliceAssign_i unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] * b[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] * b[i])) - { - printf("[%d]: %d != %d * %d\n", i, c[i], a[i], b[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] *= value - */ - -T[] _arrayExpSliceMulass_w(T[] a, T value) -{ - return _arrayExpSliceMulass_i(a, value); -} - -T[] _arrayExpSliceMulass_k(T[] a, T value) -{ - return _arrayExpSliceMulass_i(a, value); -} - -T[] _arrayExpSliceMulass_i(T[] a, T value) -{ - //printf("_arrayExpSliceMulass_i(a.length = %d, value = %Lg)\n", a.length, cast(real)value); - auto aptr = a.ptr; - auto aend = aptr + a.length; - - version (none) - { - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 400% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - uint l = value; - - if (((cast(uint) aptr) & 15) != 0) - { - asm - { - mov ESI, aptr; - mov EDI, n; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startsse2u: - movdqu XMM0, [ESI]; - movdqu XMM1, [ESI+16]; - add ESI, 32; - pmuludq XMM0, XMM2; - pmuludq XMM1, XMM2; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2u; - - mov aptr, ESI; - } - } - else - { - asm - { - mov ESI, aptr; - mov EDI, n; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startsse2a: - movdqa XMM0, [ESI]; - movdqa XMM1, [ESI+16]; - add ESI, 32; - pmuludq XMM0, XMM2; - pmuludq XMM1, XMM2; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2a; - - mov aptr, ESI; - } - } - } - else - // MMX version is 402% faster - if (mmx() && a.length >= 4) - { - auto n = aptr + (a.length & ~3); - - ulong l = cast(uint) value | (cast(ulong)cast(uint) value << 32); - - asm - { - mov ESI, aptr; - mov EDI, n; - movq MM2, l; - - align 4; - startmmx: - movq MM0, [ESI]; - movq MM1, [ESI+8]; - add ESI, 16; - pmuludq MM0, MM2; - pmuludq MM1, MM2; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - } - } - } - } - - while (aptr < aend) - *aptr++ *= value; - - return a; -} - -unittest -{ - printf("_arrayExpSliceMulass_i unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - b[] = a[]; - a[] *= 6; - - for (int i = 0; i < dim; i++) - { - if (a[i] != cast(T)(b[i] * 6)) - { - printf("[%d]: %d != %d * 6\n", i, a[i], b[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] *= b[] - */ - -T[] _arraySliceSliceMulass_w(T[] a, T[] b) -{ - return _arraySliceSliceMulass_i(a, b); -} - -T[] _arraySliceSliceMulass_k(T[] a, T[] b) -{ - return _arraySliceSliceMulass_i(a, b); -} - -T[] _arraySliceSliceMulass_i(T[] a, T[] b) -in -{ - assert (a.length == b.length); - assert (disjoint(a, b)); -} -body -{ - //printf("_arraySliceSliceMulass_i()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (none) - { - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 873% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0) - { - asm - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 4; - startsse2u: - movdqu XMM0, [ESI]; - movdqu XMM2, [ECX]; - movdqu XMM1, [ESI+16]; - movdqu XMM3, [ECX+16]; - add ESI, 32; - add ECX, 32; - pmuludq XMM0, XMM2; - pmuludq XMM1, XMM3; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2u; - - mov aptr, ESI; - mov bptr, ECX; - } - } - else - { - asm - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 4; - startsse2a: - movdqa XMM0, [ESI]; - movdqa XMM2, [ECX]; - movdqa XMM1, [ESI+16]; - movdqa XMM3, [ECX+16]; - add ESI, 32; - add ECX, 32; - pmuludq XMM0, XMM2; - pmuludq XMM1, XMM3; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2a; - - mov aptr, ESI; - mov bptr, ECX; - } - } - } -/+ BUG: comment out this section until we figure out what is going - wrong with the invalid pshufd instructions. - - else - // MMX version is 573% faster - if (mmx() && a.length >= 4) - { - auto n = aptr + (a.length & ~3); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 4; - startmmx: - movq MM0, [ESI]; - movq MM2, [ECX]; - movq MM1, [ESI+8]; - movq MM3, [ECX+8]; - pxor MM4, MM4; - pxor MM5, MM5; - punpckldq MM4, MM0; - punpckldq MM5, MM2; - add ESI, 16; - add ECX, 16; - pmuludq MM4, MM5; - pshufd MM4, MM4, 8; // ? - movq [ESI -16], MM4; - pxor MM4, MM4; - pxor MM5, MM5; - punpckldq MM4, MM1; - punpckldq MM5, MM3; - pmuludq MM4, MM5; - pshufd MM4, MM4, 8; // ? - movq [ESI+8-16], MM4; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - mov bptr, ECX; - } - } -+/ - } - } - - while (aptr < aend) - *aptr++ *= *bptr++; - - return a; -} - -unittest -{ - printf("_arraySliceSliceMulass_i unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - b[] = a[]; - a[] *= c[]; - - for (int i = 0; i < dim; i++) - { - if (a[i] != cast(T)(b[i] * c[i])) - { - printf("[%d]: %d != %d * %d\n", i, a[i], b[i], c[i]); - assert(0); - } - } - } - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/arrayreal.d --- a/druntime/src/compiler/dmd/arrayreal.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,241 +0,0 @@ -/** - * Contains SSE2 and MMX versions of certain operations for real. - * - * Copyright: Copyright Digital Mars 2008 - 2009. - * License: = 16) - { - auto n = aptr + (a.length & ~15); - - uint l = cast(ushort) value; - l |= (l << 16); - - if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startaddsse2u: - add ESI, 32; - movdqu XMM0, [EAX]; - movdqu XMM1, [EAX+16]; - add EAX, 32; - paddw XMM0, XMM2; - paddw XMM1, XMM2; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startaddsse2u; - - mov aptr, ESI; - mov bptr, EAX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startaddsse2a: - add ESI, 32; - movdqa XMM0, [EAX]; - movdqa XMM1, [EAX+16]; - add EAX, 32; - paddw XMM0, XMM2; - paddw XMM1, XMM2; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startaddsse2a; - - mov aptr, ESI; - mov bptr, EAX; - } - } - } - else - // MMX version is 3343% faster - if (mmx() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - uint l = cast(ushort) value; - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd MM2, l; - pshufw MM2, MM2, 0; - - align 4; - startmmx: - add ESI, 16; - movq MM0, [EAX]; - movq MM1, [EAX+8]; - add EAX, 16; - paddw MM0, MM2; - paddw MM1, MM2; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - mov bptr, EAX; - } - } - } - - while (aptr < aend) - *aptr++ = cast(T)(*bptr++ + value); - - return a; -} - -unittest -{ - printf("_arraySliceExpAddSliceAssign_s unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] + 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] + 6)) - { - printf("[%d]: %d != %d + 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] + c[] - */ - -T[] _arraySliceSliceAddSliceAssign_u(T[] a, T[] c, T[] b) -{ - return _arraySliceSliceAddSliceAssign_s(a, c, b); -} - -T[] _arraySliceSliceAddSliceAssign_t(T[] a, T[] c, T[] b) -{ - return _arraySliceSliceAddSliceAssign_s(a, c, b); -} - -T[] _arraySliceSliceAddSliceAssign_s(T[] a, T[] c, T[] b) -in -{ - assert(a.length == b.length && b.length == c.length); - assert(disjoint(a, b)); - assert(disjoint(a, c)); - assert(disjoint(b, c)); -} -body -{ - //printf("_arraySliceSliceAddSliceAssign_s()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - auto cptr = c.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 3777% faster - if (sse2() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - if (((cast(uint) aptr | cast(uint) bptr | cast(uint) cptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 4; - startsse2u: - add ESI, 32; - movdqu XMM0, [EAX]; - movdqu XMM1, [EAX+16]; - add EAX, 32; - movdqu XMM2, [ECX]; - movdqu XMM3, [ECX+16]; - add ECX, 32; - paddw XMM0, XMM2; - paddw XMM1, XMM3; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2u; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 4; - startsse2a: - add ESI, 32; - movdqa XMM0, [EAX]; - movdqa XMM1, [EAX+16]; - add EAX, 32; - movdqa XMM2, [ECX]; - movdqa XMM3, [ECX+16]; - add ECX, 32; - paddw XMM0, XMM2; - paddw XMM1, XMM3; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2a; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - else - // MMX version is 2068% faster - if (mmx() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 4; - startmmx: - add ESI, 16; - movq MM0, [EAX]; - movq MM1, [EAX+8]; - add EAX, 16; - movq MM2, [ECX]; - movq MM3, [ECX+8]; - add ECX, 16; - paddw MM0, MM2; - paddw MM1, MM3; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - - while (aptr < aend) - *aptr++ = cast(T)(*bptr++ + *cptr++); - - return a; -} - -unittest -{ - printf("_arraySliceSliceAddSliceAssign_s unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] + b[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] + b[i])) - { - printf("[%d]: %d != %d + %d\n", i, c[i], a[i], b[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] += value - */ - -T[] _arrayExpSliceAddass_u(T[] a, T value) -{ - return _arrayExpSliceAddass_s(a, value); -} - -T[] _arrayExpSliceAddass_t(T[] a, T value) -{ - return _arrayExpSliceAddass_s(a, value); -} - -T[] _arrayExpSliceAddass_s(T[] a, T value) -{ - //printf("_arrayExpSliceAddass_s(a.length = %d, value = %Lg)\n", a.length, cast(real)value); - auto aptr = a.ptr; - auto aend = aptr + a.length; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 832% faster - if (sse2() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - uint l = cast(ushort) value; - l |= (l << 16); - - if (((cast(uint) aptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startaddsse2u: - movdqu XMM0, [ESI]; - movdqu XMM1, [ESI+16]; - add ESI, 32; - paddw XMM0, XMM2; - paddw XMM1, XMM2; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startaddsse2u; - - mov aptr, ESI; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startaddsse2a: - movdqa XMM0, [ESI]; - movdqa XMM1, [ESI+16]; - add ESI, 32; - paddw XMM0, XMM2; - paddw XMM1, XMM2; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startaddsse2a; - - mov aptr, ESI; - } - } - } - else - // MMX version is 826% faster - if (mmx() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - uint l = cast(ushort) value; - - asm - { - mov ESI, aptr; - mov EDI, n; - movd MM2, l; - pshufw MM2, MM2, 0; - - align 4; - startmmx: - movq MM0, [ESI]; - movq MM1, [ESI+8]; - add ESI, 16; - paddw MM0, MM2; - paddw MM1, MM2; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - } - } - } - - while (aptr < aend) - *aptr++ += value; - - return a; -} - -unittest -{ - printf("_arrayExpSliceAddass_s unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - a[] += 6; - - for (int i = 0; i < dim; i++) - { - if (a[i] != cast(T)(c[i] + 6)) - { - printf("[%d]: %d != %d + 6\n", i, a[i], c[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] += b[] - */ - -T[] _arraySliceSliceAddass_u(T[] a, T[] b) -{ - return _arraySliceSliceAddass_s(a, b); -} - -T[] _arraySliceSliceAddass_t(T[] a, T[] b) -{ - return _arraySliceSliceAddass_s(a, b); -} - -T[] _arraySliceSliceAddass_s(T[] a, T[] b) -in -{ - assert (a.length == b.length); - assert (disjoint(a, b)); -} -body -{ - //printf("_arraySliceSliceAddass_s()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 2085% faster - if (sse2() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 4; - startsse2u: - movdqu XMM0, [ESI]; - movdqu XMM1, [ESI+16]; - add ESI, 32; - movdqu XMM2, [ECX]; - movdqu XMM3, [ECX+16]; - add ECX, 32; - paddw XMM0, XMM2; - paddw XMM1, XMM3; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2u; - - mov aptr, ESI; - mov bptr, ECX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 4; - startsse2a: - movdqa XMM0, [ESI]; - movdqa XMM1, [ESI+16]; - add ESI, 32; - movdqa XMM2, [ECX]; - movdqa XMM3, [ECX+16]; - add ECX, 32; - paddw XMM0, XMM2; - paddw XMM1, XMM3; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2a; - - mov aptr, ESI; - mov bptr, ECX; - } - } - } - else - // MMX version is 1022% faster - if (mmx() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 4; - start: - movq MM0, [ESI]; - movq MM1, [ESI+8]; - add ESI, 16; - movq MM2, [ECX]; - movq MM3, [ECX+8]; - add ECX, 16; - paddw MM0, MM2; - paddw MM1, MM3; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb start; - - emms; - mov aptr, ESI; - mov bptr, ECX; - } - } - } - - while (aptr < aend) - *aptr++ += *bptr++; - - return a; -} - -unittest -{ - printf("_arraySliceSliceAddass_s unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - b[] = c[]; - c[] += a[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(b[i] + a[i])) - { - printf("[%d]: %d != %d + %d\n", i, c[i], b[i], a[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] - value - */ - -T[] _arraySliceExpMinSliceAssign_u(T[] a, T value, T[] b) -{ - return _arraySliceExpMinSliceAssign_s(a, value, b); -} - -T[] _arraySliceExpMinSliceAssign_t(T[] a, T value, T[] b) -{ - return _arraySliceExpMinSliceAssign_s(a, value, b); -} - -T[] _arraySliceExpMinSliceAssign_s(T[] a, T value, T[] b) -in -{ - assert(a.length == b.length); - assert(disjoint(a, b)); -} -body -{ - //printf("_arraySliceExpMinSliceAssign_s()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 3695% faster - if (sse2() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - uint l = cast(ushort) value; - l |= (l << 16); - - if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startaddsse2u: - add ESI, 32; - movdqu XMM0, [EAX]; - movdqu XMM1, [EAX+16]; - add EAX, 32; - psubw XMM0, XMM2; - psubw XMM1, XMM2; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startaddsse2u; - - mov aptr, ESI; - mov bptr, EAX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startaddsse2a: - add ESI, 32; - movdqa XMM0, [EAX]; - movdqa XMM1, [EAX+16]; - add EAX, 32; - psubw XMM0, XMM2; - psubw XMM1, XMM2; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startaddsse2a; - - mov aptr, ESI; - mov bptr, EAX; - } - } - } - else - // MMX version is 3049% faster - if (mmx() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - uint l = cast(ushort) value; - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd MM2, l; - pshufw MM2, MM2, 0; - - align 4; - startmmx: - add ESI, 16; - movq MM0, [EAX]; - movq MM1, [EAX+8]; - add EAX, 16; - psubw MM0, MM2; - psubw MM1, MM2; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - mov bptr, EAX; - } - } - } - - while (aptr < aend) - *aptr++ = cast(T)(*bptr++ - value); - - return a; -} - -unittest -{ - printf("_arraySliceExpMinSliceAssign_s unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] - 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] - 6)) - { - printf("[%d]: %d != %d - 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = value - b[] - */ - -T[] _arrayExpSliceMinSliceAssign_u(T[] a, T[] b, T value) -{ - return _arrayExpSliceMinSliceAssign_s(a, b, value); -} - -T[] _arrayExpSliceMinSliceAssign_t(T[] a, T[] b, T value) -{ - return _arrayExpSliceMinSliceAssign_s(a, b, value); -} - -T[] _arrayExpSliceMinSliceAssign_s(T[] a, T[] b, T value) -in -{ - assert(a.length == b.length); - assert(disjoint(a, b)); -} -body -{ - //printf("_arrayExpSliceMinSliceAssign_s()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 4995% faster - if (sse2() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - uint l = cast(ushort) value; - l |= (l << 16); - - if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - - align 4; - startaddsse2u: - movd XMM2, l; - pshufd XMM2, XMM2, 0; - movd XMM3, l; - pshufd XMM3, XMM3, 0; - add ESI, 32; - movdqu XMM0, [EAX]; - movdqu XMM1, [EAX+16]; - add EAX, 32; - psubw XMM2, XMM0; - psubw XMM3, XMM1; - movdqu [ESI -32], XMM2; - movdqu [ESI+16-32], XMM3; - cmp ESI, EDI; - jb startaddsse2u; - - mov aptr, ESI; - mov bptr, EAX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - - align 4; - startaddsse2a: - movd XMM2, l; - pshufd XMM2, XMM2, 0; - movd XMM3, l; - pshufd XMM3, XMM3, 0; - add ESI, 32; - movdqa XMM0, [EAX]; - movdqa XMM1, [EAX+16]; - add EAX, 32; - psubw XMM2, XMM0; - psubw XMM3, XMM1; - movdqa [ESI -32], XMM2; - movdqa [ESI+16-32], XMM3; - cmp ESI, EDI; - jb startaddsse2a; - - mov aptr, ESI; - mov bptr, EAX; - } - } - } - else - // MMX version is 4562% faster - if (mmx() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - uint l = cast(ushort) value; - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd MM4, l; - pshufw MM4, MM4, 0; - - align 4; - startmmx: - add ESI, 16; - movq MM2, [EAX]; - movq MM3, [EAX+8]; - movq MM0, MM4; - movq MM1, MM4; - add EAX, 16; - psubw MM0, MM2; - psubw MM1, MM3; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - mov bptr, EAX; - } - } - } - - while (aptr < aend) - *aptr++ = cast(T)(value - *bptr++); - - return a; -} - -unittest -{ - printf("_arrayExpSliceMinSliceAssign_s unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = 6 - a[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(6 - a[i])) - { - printf("[%d]: %d != 6 - %d\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] - c[] - */ - -T[] _arraySliceSliceMinSliceAssign_u(T[] a, T[] c, T[] b) -{ - return _arraySliceSliceMinSliceAssign_s(a, c, b); -} - -T[] _arraySliceSliceMinSliceAssign_t(T[] a, T[] c, T[] b) -{ - return _arraySliceSliceMinSliceAssign_s(a, c, b); -} - -T[] _arraySliceSliceMinSliceAssign_s(T[] a, T[] c, T[] b) -in -{ - assert(a.length == b.length && b.length == c.length); - assert(disjoint(a, b)); - assert(disjoint(a, c)); - assert(disjoint(b, c)); -} -body -{ - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - auto cptr = c.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 4129% faster - if (sse2() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - if (((cast(uint) aptr | cast(uint) bptr | cast(uint) cptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 4; - startsse2u: - add ESI, 32; - movdqu XMM0, [EAX]; - movdqu XMM1, [EAX+16]; - add EAX, 32; - movdqu XMM2, [ECX]; - movdqu XMM3, [ECX+16]; - add ECX, 32; - psubw XMM0, XMM2; - psubw XMM1, XMM3; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2u; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 4; - startsse2a: - add ESI, 32; - movdqa XMM0, [EAX]; - movdqa XMM1, [EAX+16]; - add EAX, 32; - movdqa XMM2, [ECX]; - movdqa XMM3, [ECX+16]; - add ECX, 32; - psubw XMM0, XMM2; - psubw XMM1, XMM3; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2a; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - else - // MMX version is 2018% faster - if (mmx() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 4; - startmmx: - add ESI, 16; - movq MM0, [EAX]; - movq MM1, [EAX+8]; - add EAX, 16; - movq MM2, [ECX]; - movq MM3, [ECX+8]; - add ECX, 16; - psubw MM0, MM2; - psubw MM1, MM3; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - - while (aptr < aend) - *aptr++ = cast(T)(*bptr++ - *cptr++); - - return a; -} - -unittest -{ - printf("_arraySliceSliceMinSliceAssign_s unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] - b[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] - b[i])) - { - printf("[%d]: %d != %d - %d\n", i, c[i], a[i], b[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] -= value - */ - -T[] _arrayExpSliceMinass_u(T[] a, T value) -{ - return _arrayExpSliceMinass_s(a, value); -} - -T[] _arrayExpSliceMinass_t(T[] a, T value) -{ - return _arrayExpSliceMinass_s(a, value); -} - -T[] _arrayExpSliceMinass_s(T[] a, T value) -{ - //printf("_arrayExpSliceMinass_s(a.length = %d, value = %Lg)\n", a.length, cast(real)value); - auto aptr = a.ptr; - auto aend = aptr + a.length; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 835% faster - if (sse2() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - uint l = cast(ushort) value; - l |= (l << 16); - - if (((cast(uint) aptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startaddsse2u: - movdqu XMM0, [ESI]; - movdqu XMM1, [ESI+16]; - add ESI, 32; - psubw XMM0, XMM2; - psubw XMM1, XMM2; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startaddsse2u; - - mov aptr, ESI; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startaddsse2a: - movdqa XMM0, [ESI]; - movdqa XMM1, [ESI+16]; - add ESI, 32; - psubw XMM0, XMM2; - psubw XMM1, XMM2; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startaddsse2a; - - mov aptr, ESI; - } - } - } - else - // MMX version is 835% faster - if (mmx() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - uint l = cast(ushort) value; - - asm - { - mov ESI, aptr; - mov EDI, n; - movd MM2, l; - pshufw MM2, MM2, 0; - - align 4; - startmmx: - movq MM0, [ESI]; - movq MM1, [ESI+8]; - add ESI, 16; - psubw MM0, MM2; - psubw MM1, MM2; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - } - } - } - - while (aptr < aend) - *aptr++ -= value; - - return a; -} - -unittest -{ - printf("_arrayExpSliceMinass_s unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - a[] -= 6; - - for (int i = 0; i < dim; i++) - { - if (a[i] != cast(T)(c[i] - 6)) - { - printf("[%d]: %d != %d - 6\n", i, a[i], c[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] -= b[] - */ - -T[] _arraySliceSliceMinass_u(T[] a, T[] b) -{ - return _arraySliceSliceMinass_s(a, b); -} - -T[] _arraySliceSliceMinass_t(T[] a, T[] b) -{ - return _arraySliceSliceMinass_s(a, b); -} - -T[] _arraySliceSliceMinass_s(T[] a, T[] b) -in -{ - assert (a.length == b.length); - assert (disjoint(a, b)); -} -body -{ - //printf("_arraySliceSliceMinass_s()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 2121% faster - if (sse2() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 4; - startsse2u: - movdqu XMM0, [ESI]; - movdqu XMM1, [ESI+16]; - add ESI, 32; - movdqu XMM2, [ECX]; - movdqu XMM3, [ECX+16]; - add ECX, 32; - psubw XMM0, XMM2; - psubw XMM1, XMM3; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2u; - - mov aptr, ESI; - mov bptr, ECX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 4; - startsse2a: - movdqa XMM0, [ESI]; - movdqa XMM1, [ESI+16]; - add ESI, 32; - movdqa XMM2, [ECX]; - movdqa XMM3, [ECX+16]; - add ECX, 32; - psubw XMM0, XMM2; - psubw XMM1, XMM3; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2a; - - mov aptr, ESI; - mov bptr, ECX; - } - } - } - else - // MMX version is 1116% faster - if (mmx() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 4; - start: - movq MM0, [ESI]; - movq MM1, [ESI+8]; - add ESI, 16; - movq MM2, [ECX]; - movq MM3, [ECX+8]; - add ECX, 16; - psubw MM0, MM2; - psubw MM1, MM3; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb start; - - emms; - mov aptr, ESI; - mov bptr, ECX; - } - } - } - - while (aptr < aend) - *aptr++ -= *bptr++; - - return a; -} - -unittest -{ - printf("_arraySliceSliceMinass_s unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - b[] = c[]; - c[] -= a[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(b[i] - a[i])) - { - printf("[%d]: %d != %d - %d\n", i, c[i], b[i], a[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] * value - */ - -T[] _arraySliceExpMulSliceAssign_u(T[] a, T value, T[] b) -{ - return _arraySliceExpMulSliceAssign_s(a, value, b); -} - -T[] _arraySliceExpMulSliceAssign_t(T[] a, T value, T[] b) -{ - return _arraySliceExpMulSliceAssign_s(a, value, b); -} - -T[] _arraySliceExpMulSliceAssign_s(T[] a, T value, T[] b) -in -{ - assert(a.length == b.length); - assert(disjoint(a, b)); -} -body -{ - //printf("_arraySliceExpMulSliceAssign_s()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 3733% faster - if (sse2() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - uint l = cast(ushort) value; - l |= l << 16; - - if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0) - { - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startsse2u: - add ESI, 32; - movdqu XMM0, [EAX]; - movdqu XMM1, [EAX+16]; - add EAX, 32; - pmullw XMM0, XMM2; - pmullw XMM1, XMM2; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2u; - - mov aptr, ESI; - mov bptr, EAX; - } - } - else - { - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startsse2a: - add ESI, 32; - movdqa XMM0, [EAX]; - movdqa XMM1, [EAX+16]; - add EAX, 32; - pmullw XMM0, XMM2; - pmullw XMM1, XMM2; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2a; - - mov aptr, ESI; - mov bptr, EAX; - } - } - } - else - // MMX version is 3733% faster - if (mmx() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - uint l = cast(ushort) value; - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd MM2, l; - pshufw MM2, MM2, 0; - - align 4; - startmmx: - add ESI, 16; - movq MM0, [EAX]; - movq MM1, [EAX+8]; - add EAX, 16; - pmullw MM0, MM2; - pmullw MM1, MM2; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - mov bptr, EAX; - } - } - } - - while (aptr < aend) - *aptr++ = cast(T)(*bptr++ * value); - - return a; -} - -unittest -{ - printf("_arraySliceExpMulSliceAssign_s unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] * 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] * 6)) - { - printf("[%d]: %d != %d * 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] * c[] - */ - -T[] _arraySliceSliceMulSliceAssign_u(T[] a, T[] c, T[] b) -{ - return _arraySliceSliceMulSliceAssign_s(a, c, b); -} - -T[] _arraySliceSliceMulSliceAssign_t(T[] a, T[] c, T[] b) -{ - return _arraySliceSliceMulSliceAssign_s(a, c, b); -} - -T[] _arraySliceSliceMulSliceAssign_s(T[] a, T[] c, T[] b) -in -{ - assert(a.length == b.length && b.length == c.length); - assert(disjoint(a, b)); - assert(disjoint(a, c)); - assert(disjoint(b, c)); -} -body -{ - //printf("_arraySliceSliceMulSliceAssign_s()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - auto cptr = c.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 2515% faster - if (sse2() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - if (((cast(uint) aptr | cast(uint) bptr | cast(uint) cptr) & 15) != 0) - { - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 4; - startsse2u: - add ESI, 32; - movdqu XMM0, [EAX]; - movdqu XMM2, [ECX]; - movdqu XMM1, [EAX+16]; - movdqu XMM3, [ECX+16]; - add EAX, 32; - add ECX, 32; - pmullw XMM0, XMM2; - pmullw XMM1, XMM3; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2u; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - else - { - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 4; - startsse2a: - add ESI, 32; - movdqa XMM0, [EAX]; - movdqa XMM2, [ECX]; - movdqa XMM1, [EAX+16]; - movdqa XMM3, [ECX+16]; - add EAX, 32; - add ECX, 32; - pmullw XMM0, XMM2; - pmullw XMM1, XMM3; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2a; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - else - // MMX version is 2515% faster - if (mmx() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 4; - startmmx: - add ESI, 16; - movq MM0, [EAX]; - movq MM2, [ECX]; - movq MM1, [EAX+8]; - movq MM3, [ECX+8]; - add EAX, 16; - add ECX, 16; - pmullw MM0, MM2; - pmullw MM1, MM3; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - - while (aptr < aend) - *aptr++ = cast(T)(*bptr++ * *cptr++); - - return a; -} - -unittest -{ - printf("_arraySliceSliceMulSliceAssign_s unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] * b[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] * b[i])) - { - printf("[%d]: %d != %d * %d\n", i, c[i], a[i], b[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] *= value - */ - -T[] _arrayExpSliceMulass_u(T[] a, T value) -{ - return _arrayExpSliceMulass_s(a, value); -} - -T[] _arrayExpSliceMulass_t(T[] a, T value) -{ - return _arrayExpSliceMulass_s(a, value); -} - -T[] _arrayExpSliceMulass_s(T[] a, T value) -{ - //printf("_arrayExpSliceMulass_s(a.length = %d, value = %Lg)\n", a.length, cast(real)value); - auto aptr = a.ptr; - auto aend = aptr + a.length; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 2044% faster - if (sse2() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - uint l = cast(ushort) value; - l |= l << 16; - - if (((cast(uint) aptr) & 15) != 0) - { - asm - { - mov ESI, aptr; - mov EDI, n; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startsse2u: - movdqu XMM0, [ESI]; - movdqu XMM1, [ESI+16]; - add ESI, 32; - pmullw XMM0, XMM2; - pmullw XMM1, XMM2; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2u; - - mov aptr, ESI; - } - } - else - { - asm - { - mov ESI, aptr; - mov EDI, n; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startsse2a: - movdqa XMM0, [ESI]; - movdqa XMM1, [ESI+16]; - add ESI, 32; - pmullw XMM0, XMM2; - pmullw XMM1, XMM2; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2a; - - mov aptr, ESI; - } - } - } - else - // MMX version is 2056% faster - if (mmx() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - uint l = cast(ushort) value; - - asm - { - mov ESI, aptr; - mov EDI, n; - movd MM2, l; - pshufw MM2, MM2, 0; - - align 4; - startmmx: - movq MM0, [ESI]; - movq MM1, [ESI+8]; - add ESI, 16; - pmullw MM0, MM2; - pmullw MM1, MM2; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - } - } - } - - while (aptr < aend) - *aptr++ *= value; - - return a; -} - -unittest -{ - printf("_arrayExpSliceMulass_s unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - b[] = a[]; - a[] *= 6; - - for (int i = 0; i < dim; i++) - { - if (a[i] != cast(T)(b[i] * 6)) - { - printf("[%d]: %d != %d * 6\n", i, a[i], b[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] *= b[] - */ - -T[] _arraySliceSliceMulass_u(T[] a, T[] b) -{ - return _arraySliceSliceMulass_s(a, b); -} - -T[] _arraySliceSliceMulass_t(T[] a, T[] b) -{ - return _arraySliceSliceMulass_s(a, b); -} - -T[] _arraySliceSliceMulass_s(T[] a, T[] b) -in -{ - assert (a.length == b.length); - assert (disjoint(a, b)); -} -body -{ - //printf("_arraySliceSliceMulass_s()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 2519% faster - if (sse2() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0) - { - asm - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 4; - startsse2u: - movdqu XMM0, [ESI]; - movdqu XMM2, [ECX]; - movdqu XMM1, [ESI+16]; - movdqu XMM3, [ECX+16]; - add ESI, 32; - add ECX, 32; - pmullw XMM0, XMM2; - pmullw XMM1, XMM3; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2u; - - mov aptr, ESI; - mov bptr, ECX; - } - } - else - { - asm - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 4; - startsse2a: - movdqa XMM0, [ESI]; - movdqa XMM2, [ECX]; - movdqa XMM1, [ESI+16]; - movdqa XMM3, [ECX+16]; - add ESI, 32; - add ECX, 32; - pmullw XMM0, XMM2; - pmullw XMM1, XMM3; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2a; - - mov aptr, ESI; - mov bptr, ECX; - } - } - } - else - // MMX version is 1712% faster - if (mmx() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 4; - startmmx: - movq MM0, [ESI]; - movq MM2, [ECX]; - movq MM1, [ESI+8]; - movq MM3, [ECX+8]; - add ESI, 16; - add ECX, 16; - pmullw MM0, MM2; - pmullw MM1, MM3; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - mov bptr, ECX; - } - } - } - - while (aptr < aend) - *aptr++ *= *bptr++; - - return a; -} - -unittest -{ - printf("_arraySliceSliceMulass_s unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - b[] = a[]; - a[] *= c[]; - - for (int i = 0; i < dim; i++) - { - if (a[i] != cast(T)(b[i] * c[i])) - { - printf("[%d]: %d != %d * %d\n", i, a[i], b[i], c[i]); - assert(0); - } - } - } - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/cast_.d --- a/druntime/src/compiler/dmd/cast_.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,169 +0,0 @@ -/** - * Implementation of array assignment support routines. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: Boost License 1.0. - * Authors: Walter Bright, Sean Kelly - * - * Copyright Digital Mars 2000 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module rt.cover; - -private -{ - version( Windows ) - import core.sys.windows.windows; - else version( Posix ) - { - import core.sys.posix.fcntl; - import core.sys.posix.unistd; - } - import core.bitop; - import core.stdc.stdio; - import rt.util.utf; - - struct BitArray - { - size_t len; - uint* ptr; - - bool opIndex( size_t i ) - in - { - assert( i < len ); - } - body - { - return cast(bool) bt( ptr, i ); - } - } - - struct Cover - { - string filename; - BitArray valid; - uint[] data; - } - - __gshared - { - Cover[] gdata; - string srcpath; - string dstpath; - bool merge; - } -} - - -/** - * Set path to where source files are located. - * - * Params: - * pathname = The new path name. - */ -extern (C) void dmd_coverSourcePath( string pathname ) -{ - srcpath = pathname; -} - - -/** - * Set path to where listing files are to be written. - * - * Params: - * pathname = The new path name. - */ -extern (C) void dmd_coverDestPath( string pathname ) -{ - dstpath = pathname; -} - - -/** - * Set merge mode. - * - * Params: - * flag = true means new data is summed with existing data in the listing - * file; false means a new listing file is always created. - */ -extern (C) void dmd_coverSetMerge( bool flag ) -{ - merge = flag; -} - - -/** - * The coverage callback. - * - * Params: - * filename = The name of the coverage file. - * valid = ??? - * data = ??? - */ -extern (C) void _d_cover_register( string filename, BitArray valid, uint[] data ) -{ - Cover c; - - c.filename = filename; - c.valid = valid; - c.data = data; - gdata ~= c; -} - - -static ~this() -{ - const NUMLINES = 16384 - 1; - const NUMCHARS = 16384 * 16 - 1; - - char[] srcbuf = new char[NUMCHARS]; - char[][] srclines = new char[][NUMLINES]; - char[] lstbuf = new char[NUMCHARS]; - char[][] lstlines = new char[][NUMLINES]; - - foreach( Cover c; gdata ) - { - if( !readFile( appendFN( srcpath, c.filename ), srcbuf ) ) - continue; - splitLines( srcbuf, srclines ); - - if( merge ) - { - if( !readFile( addExt( baseName( c.filename ), "lst" ), lstbuf ) ) - break; - splitLines( lstbuf, lstlines ); - - for( size_t i = 0; i < lstlines.length; ++i ) - { - if( i >= c.data.length ) - break; - - int count = 0; - - foreach( char c2; lstlines[i] ) - { - switch( c2 ) - { - case ' ': - continue; - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - count = count * 10 + c2 - '0'; - continue; - default: - break; - } - } - c.data[i] += count; - } - } - - FILE* flst = fopen( (addExt( baseName( c.filename ), "lst\0" )).ptr, "wb" ); - - if( !flst ) - continue; //throw new Exception( "Error opening file for write: " ~ lstfn ); - - uint nno; - uint nyes; - - for( int i = 0; i < c.data.length; i++ ) - { - if( i < srclines.length ) - { - uint n = c.data[i]; - char[] line = srclines[i]; - - line = expandTabs( line ); - - if( n == 0 ) - { - if( c.valid[i] ) - { - nno++; - fprintf( flst, "0000000|%.*s\n", line ); - } - else - { - fprintf( flst, " |%.*s\n", line ); - } - } - else - { - nyes++; - fprintf( flst, "%7u|%.*s\n", n, line ); - } - } - } - if( nyes + nno ) // no divide by 0 bugs - { - fprintf( flst, "%.*s is %d%% covered\n", c.filename, ( nyes * 100 ) / ( nyes + nno ) ); - } - fclose( flst ); - } -} - - -string appendFN( string path, string name ) -{ - version( Windows ) - const char sep = '\\'; - else - const char sep = '/'; - - auto dest = path; - - if( dest && dest[$ - 1] != sep ) - dest ~= sep; - dest ~= name; - return dest; -} - - -string baseName( string name, string ext = null ) -{ - auto i = name.length; - for( ; i > 0; --i ) - { - version( Windows ) - { - if( name[i - 1] == ':' || name[i - 1] == '\\' ) - break; - } - else version( Posix ) - { - if( name[i - 1] == '/' ) - break; - } - } - return chomp( name[i .. $], ext ? ext : "" ); -} - - -string getExt( string name ) -{ - auto i = name.length; - - while( i > 0 ) - { - if( name[i - 1] == '.' ) - return name[i .. $]; - --i; - version( Windows ) - { - if( name[i] == ':' || name[i] == '\\' ) - break; - } - else version( Posix ) - { - if( name[i] == '/' ) - break; - } - } - return null; -} - - -string addExt( string name, string ext ) -{ - auto existing = getExt( name ); - - if( existing.length == 0 ) - { - if( name.length && name[$ - 1] == '.' ) - name ~= ext; - else - name = name ~ "." ~ ext; - } - else - { - name = name[0 .. $ - existing.length] ~ ext; - } - return name; -} - - -string chomp( string str, string delim = null ) -{ - if( delim is null ) - { - auto len = str.length; - - if( len ) - { - auto c = str[len - 1]; - - if( c == '\r' ) - --len; - else if( c == '\n' && str[--len - 1] == '\r' ) - --len; - } - return str[0 .. len]; - } - else if( str.length >= delim.length ) - { - if( str[$ - delim.length .. $] == delim ) - return str[0 .. $ - delim.length]; - } - return str; -} - - -bool readFile( string name, inout char[] buf ) -{ - version( Windows ) - { - auto wnamez = toUTF16z( name ); - HANDLE file = CreateFileW( wnamez, - GENERIC_READ, - FILE_SHARE_READ, - null, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, - cast(HANDLE) null ); - - delete wnamez; - if( file == INVALID_HANDLE_VALUE ) - return false; - scope( exit ) CloseHandle( file ); - - DWORD num = 0; - DWORD pos = 0; - - buf.length = 4096; - while( true ) - { - if( !ReadFile( file, &buf[pos], cast(DWORD)( buf.length - pos ), &num, null ) ) - return false; - if( !num ) - break; - pos += num; - buf.length = pos * 2; - } - buf.length = pos; - return true; - } - else version( Posix ) - { - char[] namez = new char[name.length + 1]; - namez[0 .. name.length] = name; - namez[$ - 1] = 0; - int file = open( namez.ptr, O_RDONLY ); - - delete namez; - if( file == -1 ) - return false; - scope( exit ) close( file ); - - int num = 0; - uint pos = 0; - - buf.length = 4096; - while( true ) - { - num = read( file, &buf[pos], cast(uint)( buf.length - pos ) ); - if( num == -1 ) - return false; - if( !num ) - break; - pos += num; - buf.length = pos * 2; - } - buf.length = pos; - return true; - } -} - - -void splitLines( char[] buf, inout char[][] lines ) -{ - size_t beg = 0, - pos = 0; - - lines.length = 0; - for( ; pos < buf.length; ++pos ) - { - char c = buf[pos]; - - switch( buf[pos] ) - { - case '\r': - case '\n': - lines ~= buf[beg .. pos]; - beg = pos + 1; - if( buf[pos] == '\r' && pos < buf.length - 1 && buf[pos + 1] == '\n' ) - ++pos, ++beg; - default: - continue; - } - } - if( beg != pos ) - { - lines ~= buf[beg .. pos]; - } -} - - -char[] expandTabs( char[] str, int tabsize = 8 ) -{ - const dchar LS = '\u2028'; // UTF line separator - const dchar PS = '\u2029'; // UTF paragraph separator - - bool changes = false; - char[] result = str; - int column; - int nspaces; - - foreach( size_t i, dchar c; str ) - { - switch( c ) - { - case '\t': - nspaces = tabsize - (column % tabsize); - if( !changes ) - { - changes = true; - result = null; - result.length = str.length + nspaces - 1; - result.length = i + nspaces; - result[0 .. i] = str[0 .. i]; - result[i .. i + nspaces] = ' '; - } - else - { int j = result.length; - result.length = j + nspaces; - result[j .. j + nspaces] = ' '; - } - column += nspaces; - break; - - case '\r': - case '\n': - case PS: - case LS: - column = 0; - goto L1; - - default: - column++; - L1: - if (changes) - { - if (c <= 0x7F) - result ~= c; - else - encode(result, c); - } - break; - } - } - return result; -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/critical.c --- a/druntime/src/compiler/dmd/critical.c Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,173 +0,0 @@ -/** - * Implementation of support routines for synchronized blocks. - * - * Copyright: Copyright Digital Mars 2000 - 2009. - * License: next) - { - pthread_mutex_lock(&critical_section.cs); - if (!dcs->next) // if, in the meantime, another thread didn't set it - { - dcs->next = dcs_list; - dcs_list = dcs; - pthread_mutex_init(&dcs->cs, &_criticals_attr); - } - pthread_mutex_unlock(&critical_section.cs); - } - pthread_mutex_lock(&dcs->cs); -} - -void _d_criticalexit(D_CRITICAL_SECTION *dcs) -{ - //printf("_d_criticalexit(dcs = x%x)\n", dcs); - pthread_mutex_unlock(&dcs->cs); -} - -void _STI_critical_init() -{ - if (!dcs_list) - { //printf("_STI_critical_init()\n"); - pthread_mutexattr_init(&_criticals_attr); - pthread_mutexattr_settype(&_criticals_attr, PTHREAD_MUTEX_RECURSIVE); - - // The global critical section doesn't need to be recursive - pthread_mutex_init(&critical_section.cs, 0); - dcs_list = &critical_section; - } -} - -void _STD_critical_term() -{ - if (dcs_list) - { //printf("_STI_critical_term()\n"); - while (dcs_list) - { - //printf("\tlooping... %x\n", dcs_list); - pthread_mutex_destroy(&dcs_list->cs); - dcs_list = dcs_list->next; - } - } -} - -#endif - diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/deh.c --- a/druntime/src/compiler/dmd/deh.c Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,724 +0,0 @@ -/** - * Implementation of exception handling support routines for Windows. - * - * Copyright: Copyright Digital Mars 1999 - 2009. - * License: ExceptionFlags & EXCEPTION_UNWIND) - { - // Call all the finally blocks in this frame - _d_local_unwind(handler_table, frame, -1); - } - else - { - // Jump to catch block if matching one is found - - int ndx,prev_ndx,i; - struct DHandlerInfo *phi; - struct DCatchInfo *pci; - struct DCatchBlock *pcb; - unsigned ncatches; // number of catches in the current handler - Object *pti; - ClassInfo *ci; - - ci = NULL; // only compute it if we need it - - // walk through handler table, checking each handler - // with an index smaller than the current table_index - for (ndx = frame->table_index; ndx != -1; ndx = prev_ndx) - { - phi = &handler_table->handler_info[ndx]; - prev_ndx = phi->prev_index; - if (phi->cioffset) - { - // this is a catch handler (no finally) - pci = (struct DCatchInfo *)((char *)handler_table + phi->cioffset); - ncatches = pci->ncatches; - for (i = 0; i < ncatches; i++) - { - pcb = &pci->catch_block[i]; - - if (!ci) - { - // This code must match the translation code - if (exception_record->ExceptionCode == STATUS_DIGITAL_MARS_D_EXCEPTION) - { - //printf("ei[0] = %p\n", exception_record->ExceptionInformation[0]); - ci = **(ClassInfo ***)(exception_record->ExceptionInformation[0]); - } - else - ci = &_Class_9Throwable; - } - - if (_d_isbaseof(ci, pcb->type)) - { - // Matched the catch type, so we've found the handler. - int regebp; - - pti = _d_translate_se_to_d_exception(exception_record); - - // Initialize catch variable - regebp = (int)&frame->ebp; // EBP for this frame - *(void **)(regebp + (pcb->bpoffset)) = pti; - - // Have system call all finally blocks in intervening frames - _global_unwind(frame, exception_record); - - // Call all the finally blocks skipped in this frame - _d_local_unwind(handler_table, frame, ndx); - - frame->table_index = prev_ndx; // we are out of this handler - - // Jump to catch block. Does not return. - { - unsigned catch_esp; - fp_t catch_addr; - - catch_addr = (fp_t)(pcb->code); - catch_esp = regebp - handler_table->espoffset - sizeof(fp_t); - _asm - { - mov EAX,catch_esp - mov ECX,catch_addr - mov [EAX],ECX - mov EBP,regebp - mov ESP,EAX // reset stack - ret // jump to catch block - } - } - } - } - } - } - } - return ExceptionContinueSearch; -} - -/*********************************** - * Exception filter for use in __try..__except block - * surrounding call to Dmain() - */ - -int _d_exception_filter(struct _EXCEPTION_POINTERS *eptrs, - int retval, - Object **exception_object) -{ - *exception_object = _d_translate_se_to_d_exception(eptrs->ExceptionRecord); - return retval; -} - -/*********************************** - * Throw a D object. - */ - -void __stdcall _d_throw(Object *h) -{ - //printf("_d_throw(h = %p, &h = %p)\n", h, &h); - //printf("\tvptr = %p\n", *(void **)h); - RaiseException(STATUS_DIGITAL_MARS_D_EXCEPTION, - EXCEPTION_NONCONTINUABLE, - 1, (DWORD *)&h); -} - -/*********************************** - * Create an exception object - */ - -Object *_d_create_exception_object(ClassInfo *ci, char *msg) -{ - Throwable *exc; - - exc = (Throwable *)_d_newclass(ci); - // BUG: what if _d_newclass() throws an out of memory exception? - - if (msg) - { - exc->msglen = strlen(msg); - exc->msg = msg; - } - return (Object *)exc; -} - -/*********************************** - * Converts a Windows Structured Exception code to a D Exception Object. - */ - -Object *_d_translate_se_to_d_exception(EXCEPTION_RECORD *exception_record) -{ - Object *pti; - - switch (exception_record->ExceptionCode) { - case STATUS_DIGITAL_MARS_D_EXCEPTION: - // Generated D exception - pti = (Object *)(exception_record->ExceptionInformation[0]); - break; - - case STATUS_INTEGER_DIVIDE_BY_ZERO: - pti = _d_create_exception_object(&_Class_5Error, "Integer Divide by Zero"); - break; - - case STATUS_FLOAT_DIVIDE_BY_ZERO: - pti = _d_create_exception_object(&_Class_5Error, "Float Divide by Zero"); - break; - - case STATUS_ACCESS_VIOLATION: - pti = _d_create_exception_object(&_Class_5Error, "Access Violation"); - break; - - case STATUS_STACK_OVERFLOW: - pti = _d_create_exception_object(&_Class_5Error, "Stack Overflow"); - break; - - case STATUS_DATATYPE_MISALIGNMENT: - pti = _d_create_exception_object(&_Class_5Error, "Datatype Misalignment"); - break; - - case STATUS_ARRAY_BOUNDS_EXCEEDED: - pti = _d_create_exception_object(&_Class_5Error, "Array Bounds Exceeded"); - break; - - case STATUS_FLOAT_INVALID_OPERATION: - pti = _d_create_exception_object(&_Class_5Error, "Invalid Floating Point Operation"); - break; - - case STATUS_FLOAT_DENORMAL_OPERAND: - pti = _d_create_exception_object(&_Class_5Error, "Floating Point Denormal Operand"); - break; - - case STATUS_FLOAT_INEXACT_RESULT: - pti = _d_create_exception_object(&_Class_5Error, "Floating Point Inexact Result"); - break; - - case STATUS_FLOAT_OVERFLOW: - pti = _d_create_exception_object(&_Class_5Error, "Floating Point Overflow"); - break; - - case STATUS_FLOAT_UNDERFLOW: - pti = _d_create_exception_object(&_Class_5Error, "Floating Point Underflow"); - break; - - case STATUS_FLOAT_STACK_CHECK: - pti = _d_create_exception_object(&_Class_5Error, "Floating Point Stack Check"); - break; - - case STATUS_PRIVILEGED_INSTRUCTION: - pti = _d_create_exception_object(&_Class_5Error, "Privileged Instruction"); - break; - - case STATUS_ILLEGAL_INSTRUCTION: - pti = _d_create_exception_object(&_Class_5Error, "Illegal Instruction"); - break; - - case STATUS_BREAKPOINT: - pti = _d_create_exception_object(&_Class_5Error, "Breakpoint"); - break; - - case STATUS_IN_PAGE_ERROR: - pti = _d_create_exception_object(&_Class_5Error, "Win32 In Page Exception"); - break; -/* - case STATUS_INTEGER_OVERFLOW: // not supported on any x86 processor - case STATUS_INVALID_DISPOSITION: - case STATUS_NONCONTINUABLE_EXCEPTION: - case STATUS_SINGLE_STEP: - case DBG_CONTROL_C: // only when a debugger is attached - // In DMC, but not in Microsoft docs - case STATUS_GUARD_PAGE_VIOLATION: - case STATUS_INVALID_HANDLE: -*/ - // convert all other exception codes into a Win32Exception - default: - pti = _d_create_exception_object(&_Class_5Error, "Win32 Exception"); - break; - } - - return pti; -} - -/************************************** - * Call finally blocks in the current stack frame until stop_index. - * This is roughly equivalent to _local_unwind() for C in \src\win32\ehsup.c - */ - -void __cdecl _d_local_unwind(struct DHandlerTable *handler_table, - struct DEstablisherFrame *frame, int stop_index) -{ - struct DHandlerInfo *phi; - struct DCatchInfo *pci; - int i; - - // Set up a special exception handler to catch double-fault exceptions. - __asm - { - push dword ptr -1 - push dword ptr 0 - push offset _local_except_handler // defined in src\win32\ehsup.c - push dword ptr fs:_except_list - mov FS:_except_list,ESP - } - - for (i = frame->table_index; i != -1 && i != stop_index; i = phi->prev_index) - { - phi = &handler_table->handler_info[i]; - if (phi->finally_code) - { - // Note that it is unnecessary to adjust the ESP, as the finally block - // accesses all items on the stack as relative to EBP. - - DWORD *catch_ebp = &frame->ebp; - void *blockaddr = phi->finally_code; - - _asm - { - push EBX - mov EBX,blockaddr - push EBP - mov EBP,catch_ebp - call EBX - pop EBP - pop EBX - } - } - } - - _asm - { - pop FS:_except_list - add ESP,12 - } -} - -/*********************************** - * external version of the unwinder - */ - -__declspec(naked) void __cdecl _d_local_unwind2() -{ - __asm - { - jmp _d_local_unwind - } -} - -/*********************************** - * The frame handler, this is called for each frame that has been registered - * in the OS except_list. - * Input: - * EAX the handler table for the frame - */ - -EXCEPTION_DISPOSITION _d_monitor_handler( - EXCEPTION_RECORD *exception_record, - struct DEstablisherFrame *frame, - CONTEXT context, - void *dispatcher_context) -{ - if (exception_record->ExceptionFlags & EXCEPTION_UNWIND) - { - _d_monitorexit((Object *)frame->table_index); - } - else - { - } - return ExceptionContinueSearch; -} - -/*********************************** - */ - -void _d_monitor_prolog(void *x, void *y, Object *h) -{ - __asm - { - push EAX - } - //printf("_d_monitor_prolog(x=%p, y=%p, h=%p)\n", x, y, h); - _d_monitorenter(h); - __asm - { - pop EAX - } -} - -/*********************************** - */ - -void _d_monitor_epilog(void *x, void *y, Object *h) -{ - //printf("_d_monitor_epilog(x=%p, y=%p, h=%p)\n", x, y, h); - __asm - { - push EAX - push EDX - } - _d_monitorexit(h); - __asm - { - pop EDX - pop EAX - } -} - -#endif - -/* ======================== linux =============================== */ - -#if linux - -#include "mars.h" - -extern ClassInfo D6object9Throwable7__ClassZ; -#define _Class_9Throwable D6object9Throwable7__ClassZ; - -extern ClassInfo D6object5Error7__ClassZ; -#define _Class_5Error D6object5Error7__ClassZ - -typedef int (*fp_t)(); // function pointer in ambient memory model - -struct DHandlerInfo -{ - unsigned offset; // offset from function address to start of guarded section - int prev_index; // previous table index - unsigned cioffset; // offset to DCatchInfo data from start of table (!=0 if try-catch) - void *finally_code; // pointer to finally code to execute - // (!=0 if try-finally) -}; - -// Address of DHandlerTable, searched for by eh_finddata() - -struct DHandlerTable -{ - void *fptr; // pointer to start of function - unsigned espoffset; // offset of ESP from EBP - unsigned retoffset; // offset from start of function to return code - unsigned nhandlers; // dimension of handler_info[] - struct DHandlerInfo handler_info[1]; -}; - -struct DCatchBlock -{ - ClassInfo *type; // catch type - unsigned bpoffset; // EBP offset of catch var - void *code; // catch handler code -}; - -// Create one of these for each try-catch -struct DCatchInfo -{ - unsigned ncatches; // number of catch blocks - struct DCatchBlock catch_block[1]; // data for each catch block -}; - -// One of these is generated for each function with try-catch or try-finally - -struct FuncTable -{ - void *fptr; // pointer to start of function - struct DHandlerTable *handlertable; // eh data for this function - unsigned size; // size of function in bytes -}; - -extern struct FuncTable *table_start; -extern struct FuncTable *table_end; - -void terminate() -{ -// _asm -// { -// hlt -// } -} - -/******************************************* - * Given address that is inside a function, - * figure out which function it is in. - * Return DHandlerTable if there is one, NULL if not. - */ - -struct DHandlerTable *__eh_finddata(void *address) -{ - struct FuncTable *ft; - - for (ft = (struct FuncTable *)table_start; - ft < (struct FuncTable *)table_end; - ft++) - { - if (ft->fptr <= address && - address < (void *)((char *)ft->fptr + ft->size)) - { - return ft->handlertable; - } - } - return NULL; -} - - -/****************************** - * Given EBP, find return address to caller, and caller's EBP. - * Input: - * regbp Value of EBP for current function - * *pretaddr Return address - * Output: - * *pretaddr return address to caller - * Returns: - * caller's EBP - */ - -unsigned __eh_find_caller(unsigned regbp, unsigned *pretaddr) -{ - unsigned bp = *(unsigned *)regbp; - - if (bp) // if not end of call chain - { - // Perform sanity checks on new EBP. - // If it is screwed up, terminate() hopefully before we do more damage. - if (bp <= regbp) - // stack should grow to smaller values - terminate(); - - *pretaddr = *(unsigned *)(regbp + sizeof(int)); - } - return bp; -} - -/*********************************** - * Throw a D object. - */ - -void __stdcall _d_throw(Object *h) -{ - unsigned regebp; - - //printf("_d_throw(h = %p, &h = %p)\n", h, &h); - //printf("\tvptr = %p\n", *(void **)h); - - regebp = _EBP; - - while (1) // for each function on the stack - { - struct DHandlerTable *handler_table; - struct FuncTable *pfunc; - struct DHandlerInfo *phi; - unsigned retaddr; - unsigned funcoffset; - unsigned spoff; - unsigned retoffset; - int index; - int dim; - int ndx; - int prev_ndx; - - regebp = __eh_find_caller(regebp,&retaddr); - if (!regebp) - // if end of call chain - break; - - handler_table = __eh_finddata((void *)retaddr); // find static data associated with function - if (!handler_table) // if no static data - { - continue; - } - funcoffset = (unsigned)handler_table->fptr; - spoff = handler_table->espoffset; - retoffset = handler_table->retoffset; - -#ifdef DEBUG - printf("retaddr = x%x\n",(unsigned)retaddr); - printf("regebp=x%04x, funcoffset=x%04x, spoff=x%x, retoffset=x%x\n", - regebp,funcoffset,spoff,retoffset); -#endif - - // Find start index for retaddr in static data - dim = handler_table->nhandlers; - index = -1; - for (int i = 0; i < dim; i++) - { - phi = &handler_table->handler_info[i]; - - if ((unsigned)retaddr >= funcoffset + phi->offset) - index = i; - } - - // walk through handler table, checking each handler - // with an index smaller than the current table_index - for (ndx = index; ndx != -1; ndx = prev_ndx) - { - phi = &handler_table->handler_info[ndx]; - prev_ndx = phi->prev_index; - if (phi->cioffset) - { - // this is a catch handler (no finally) - struct DCatchInfo *pci; - int ncatches; - int i; - - pci = (struct DCatchInfo *)((char *)handler_table + phi->cioffset); - ncatches = pci->ncatches; - for (i = 0; i < ncatches; i++) - { - struct DCatchBlock *pcb; - ClassInfo *ci = **(ClassInfo ***)h; - - pcb = &pci->catch_block[i]; - - if (_d_isbaseof(ci, pcb->type)) - { // Matched the catch type, so we've found the handler. - - // Initialize catch variable - *(void **)(regebp + (pcb->bpoffset)) = h; - - // Jump to catch block. Does not return. - { - unsigned catch_esp; - fp_t catch_addr; - - catch_addr = (fp_t)(pcb->code); - catch_esp = regebp - handler_table->espoffset - sizeof(fp_t); - _asm - { - mov EAX,catch_esp - mov ECX,catch_addr - mov [EAX],ECX - mov EBP,regebp - mov ESP,EAX // reset stack - ret // jump to catch block - } - } - } - } - } - else if (phi->finally_code) - { // Call finally block - // Note that it is unnecessary to adjust the ESP, as the finally block - // accesses all items on the stack as relative to EBP. - - void *blockaddr = phi->finally_code; - - _asm - { - push EBX - mov EBX,blockaddr - push EBP - mov EBP,regebp - call EBX - pop EBP - pop EBX - } - } - } - } -} - - -#endif diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/deh2.d --- a/druntime/src/compiler/dmd/deh2.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,316 +0,0 @@ -/** - * Implementation of exception handling support routines for Posix. - * - * Copyright: Copyright Digital Mars 2000 - 2009. - * License: funcoffset + phi.offset && - cast(uint)retaddr <= funcoffset + phi.endoffset) - index = i; - } - debug printf("index = %d\n", index); - - // walk through handler table, checking each handler - // with an index smaller than the current table_index - for (ndx = index; ndx != -1; ndx = prev_ndx) - { - phi = &handler_table.handler_info[ndx]; - prev_ndx = phi.prev_index; - if (phi.cioffset) - { - // this is a catch handler (no finally) - DCatchInfo *pci; - int ncatches; - int i; - - pci = cast(DCatchInfo *)(cast(char *)handler_table + phi.cioffset); - ncatches = pci.ncatches; - for (i = 0; i < ncatches; i++) - { - DCatchBlock *pcb; - ClassInfo ci = **cast(ClassInfo **)h; - - pcb = &pci.catch_block[i]; - - if (_d_isbaseof(ci, pcb.type)) - { // Matched the catch type, so we've found the handler. - - // Initialize catch variable - *cast(void **)(regebp + (pcb.bpoffset)) = h; - - // Jump to catch block. Does not return. - { - uint catch_esp; - fp_t catch_addr; - - catch_addr = cast(fp_t)(pcb.code); - catch_esp = regebp - handler_table.espoffset - fp_t.sizeof; - asm - { - mov EAX,catch_esp ; - mov ECX,catch_addr ; - mov [EAX],ECX ; - mov EBP,regebp ; - mov ESP,EAX ; // reset stack - ret ; // jump to catch block - } - } - } - } - } - else if (phi.finally_code) - { // Call finally block - // Note that it is unnecessary to adjust the ESP, as the finally block - // accesses all items on the stack as relative to EBP. - - void *blockaddr = phi.finally_code; - - version (OSX) - { - asm - { - sub ESP,4 ; // align stack to 16 - push EBX ; - mov EBX,blockaddr ; - push EBP ; - mov EBP,regebp ; - call EBX ; - pop EBP ; - pop EBX ; - add ESP,4 ; - } - } - else - { - asm - { - push EBX ; - mov EBX,blockaddr ; - push EBP ; - mov EBP,regebp ; - call EBX ; - pop EBP ; - pop EBX ; - } - } - } - } - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/dmain2.BAK --- a/druntime/src/compiler/dmd/dmain2.BAK Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,374 +0,0 @@ -/* - * Placed into the Public Domain. - * written by Walter Bright - * www.digitalmars.com - */ - -/* - * Modified by Sean Kelly for use with the D Runtime Project - */ - -module rt.dmain2; - -private -{ - import memory; - import util.console; - import core.stdc.stddef; - import core.stdc.stdlib; - import core.stdc.string; -} - -version (Windows) -{ - extern (Windows) alias int function() FARPROC; - extern (Windows) FARPROC GetProcAddress(void*, in char*); - extern (Windows) void* LoadLibraryA(in char*); - extern (Windows) int FreeLibrary(void*); - extern (Windows) void* LocalFree(void*); - extern (Windows) wchar_t* GetCommandLineW(); - extern (Windows) wchar_t** CommandLineToArgvW(wchar_t*, int*); - extern (Windows) export int WideCharToMultiByte(uint, uint, wchar_t*, int, char*, int, char*, int); - pragma(lib, "shell32.lib"); // needed for CommandLineToArgvW -} - -extern (C) void _STI_monitor_staticctor(); -extern (C) void _STD_monitor_staticdtor(); -extern (C) void _STI_critical_init(); -extern (C) void _STD_critical_term(); -extern (C) void gc_init(); -extern (C) void gc_term(); -extern (C) void _minit(); -extern (C) void _moduleCtor(); -extern (C) void _moduleDtor(); -extern (C) void thread_joinAll(); - -/*********************************** - * These are a temporary means of providing a GC hook for DLL use. They may be - * replaced with some other similar functionality later. - */ -extern (C) -{ - void* gc_getProxy(); - void gc_setProxy(void* p); - void gc_clrProxy(); - - alias void* function() gcGetFn; - alias void function(void*) gcSetFn; - alias void function() gcClrFn; -} - -extern (C) void* rt_loadLibrary(in char[] name) -{ - version (Windows) - { - char[260] temp = void; - temp[0 .. name.length] = name[]; - temp[name.length] = cast(char) 0; - void* ptr = LoadLibraryA(temp.ptr); - if (ptr is null) - return ptr; - gcSetFn gcSet = cast(gcSetFn) GetProcAddress(ptr, "gc_setProxy"); - if (gcSet !is null) - gcSet(gc_getProxy()); - return ptr; - - } - else version (linux) - { - throw new Exception("rt_loadLibrary not yet implemented on linux."); - } -} - -extern (C) bool rt_unloadLibrary(void* ptr) -{ - version (Windows) - { - gcClrFn gcClr = cast(gcClrFn) GetProcAddress(ptr, "gc_clrProxy"); - if (gcClr !is null) - gcClr(); - return FreeLibrary(ptr) != 0; - } - else version (linux) - { - throw new Exception("rt_unloadLibrary not yet implemented on linux."); - } -} - -/*********************************** - * These functions must be defined for any D program linked - * against this library. - */ -extern (C) void onAssertError(string file, size_t line); -extern (C) void onAssertErrorMsg(string file, size_t line, string msg); -extern (C) void onRangeError(string file, size_t line); -extern (C) void onHiddenFuncError(Object o); -extern (C) void onSwitchError(string file, size_t line); -extern (C) bool runModuleUnitTests(); - -// this function is called from the utf module -//extern (C) void onUnicodeError(string msg, size_t idx); - -/*********************************** - * These are internal callbacks for various language errors. - */ -extern (C) void _d_assert(string file, uint line) -{ - onAssertError(file, line); -} - -extern (C) static void _d_assert_msg(string msg, string file, uint line) -{ - onAssertErrorMsg(file, line, msg); -} - -extern (C) void _d_array_bounds(string file, uint line) -{ - onRangeError(file, line); -} - -extern (C) void _d_switch_error(string file, uint line) -{ - onSwitchError(file, line); -} - -extern (C) void _d_hidden_func() -{ - Object o; - asm - { - mov o, EAX; - } - onHiddenFuncError(o); -} - -bool _d_isHalting = false; - -extern (C) bool rt_isHalting() -{ - return _d_isHalting; -} - -extern (C) bool rt_trapExceptions = true; - -void _d_criticalInit() -{ - version (linux) - { - _STI_monitor_staticctor(); - _STI_critical_init(); - } -} - -alias void delegate(Throwable) ExceptionHandler; - -extern (C) bool rt_init(ExceptionHandler dg = null) -{ - _d_criticalInit(); - - try - { - gc_init(); - initStaticDataGC(); - version (Windows) - _minit(); - _moduleCtor(); - return true; - } - catch (Throwable e) - { - if (dg) - dg(e); - } - catch - { - - } - _d_criticalTerm(); - return false; -} - -void _d_criticalTerm() -{ - version (linux) - { - _STD_critical_term(); - _STD_monitor_staticdtor(); - } -} - -extern (C) bool rt_term(ExceptionHandler dg = null) -{ - try - { - thread_joinAll(); - _d_isHalting = true; - _moduleDtor(); - gc_term(); - return true; - } - catch (Throwable e) - { - if (dg) - dg(e); - } - catch - { - - } - finally - { - _d_criticalTerm(); - } - return false; -} - -/*********************************** - * The D main() function supplied by the user's program - */ -int main(char[][] args); - -/*********************************** - * Substitutes for the C main() function. - * It's purpose is to wrap the call to the D main() - * function and catch any unhandled exceptions. - */ - -extern (C) int main(int argc, char **argv) -{ - char[][] args; - int result; - - version (linux) - { - _STI_monitor_staticctor(); - _STI_critical_init(); - } - - version (Windows) - { - wchar_t* wcbuf = GetCommandLineW(); - size_t wclen = wcslen(wcbuf); - int wargc = 0; - wchar_t** wargs = CommandLineToArgvW(wcbuf, &wargc); - assert(wargc == argc); - - char* cargp = null; - size_t cargl = WideCharToMultiByte(65001, 0, wcbuf, wclen, null, 0, null, 0); - - cargp = cast(char*) alloca(cargl); - args = ((cast(char[]*) alloca(wargc * (char[]).sizeof)))[0 .. wargc]; - - for (size_t i = 0, p = 0; i < wargc; i++) - { - int wlen = wcslen(wargs[i]); - int clen = WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, null, 0, null, 0); - args[i] = cargp[p .. p+clen]; - p += clen; assert(p <= cargl); - WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, &args[i][0], clen, null, 0); - } - LocalFree(wargs); - wargs = null; - wargc = 0; - } - else version (linux) - { - char[]* am = cast(char[]*) malloc(argc * (char[]).sizeof); - scope(exit) free(am); - - for (size_t i = 0; i < argc; i++) - { - auto len = strlen(argv[i]); - am[i] = argv[i][0 .. len]; - } - args = am[0 .. argc]; - } - - bool trapExceptions = rt_trapExceptions; - - void tryExec(void delegate() dg) - { - - if (trapExceptions) - { - try - { - dg(); - } - catch (Throwable e) - { - while (e) - { - if (e.file) - { - // fprintf(stderr, "%.*s(%u): %.*s\n", e.file, e.line, e.msg); - console (e.classinfo.name)("@")(e.file)("(")(e.line)("): ")(e.msg)("\n"); - } - else - { - // fprintf(stderr, "%.*s\n", e.toString()); - console (e.toString)("\n"); - } - if (e.info) - { - console ("----------------\n"); - foreach (t; e.info) - console (t)("\n"); - } - if (e.next) - console ("\n"); - e = e.next; - } - result = EXIT_FAILURE; - } - catch (Object o) - { - // fprintf(stderr, "%.*s\n", o.toString()); - console (o.toString)("\n"); - result = EXIT_FAILURE; - } - } - else - { - dg(); - } - } - - // NOTE: The lifetime of a process is much like the lifetime of an object: - // it is initialized, then used, then destroyed. If initialization - // fails, the successive two steps are never reached. However, if - // initialization succeeds, then cleanup will occur even if the use - // step fails in some way. Here, the use phase consists of running - // the user's main function. If main terminates with an exception, - // the exception is handled and then cleanup begins. An exception - // thrown during cleanup, however, will abort the cleanup process. - - void runMain() - { - result = main(args); - } - - void runAll() - { - gc_init(); - initStaticDataGC(); - version (Windows) - _minit(); - _moduleCtor(); - if (runModuleUnitTests()) - tryExec(&runMain); - thread_joinAll(); - _d_isHalting = true; - _moduleDtor(); - gc_term(); - } - - tryExec(&runAll); - - version (linux) - { - _STD_critical_term(); - _STD_monitor_staticdtor(); - } - return result; -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/dmain2.d --- a/druntime/src/compiler/dmd/dmain2.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,394 +0,0 @@ -/** - * Contains main program entry point and support routines. - * - * Copyright: Copyright Digital Mars 2000 - 2009. - * License: p.length) - { - size_t size = p.length * sizeelem; - auto info = gc_query(p.data); - - if (info.size <= newsize || info.base != p.data) - { - if (info.size >= PAGESIZE && info.base == p.data) - { // Try to extend in-place - auto u = gc_extend(p.data, (newsize + 1) - info.size, (newsize + 1) - info.size); - if (u) - { - goto L1; - } - } - newdata = cast(byte *)gc_malloc(newsize + 1, info.attr); - newdata[0 .. size] = p.data[0 .. size]; - } - L1: - newdata[size .. newsize] = 0; - } - } - else - { - newdata = cast(byte *)gc_calloc(newsize + 1, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0); - } - } - else - { - newdata = p.data; - } - - p.data = newdata; - p.length = newlength; - return newdata[0 .. newlength]; - -Loverflow: - onOutOfMemoryError(); -} - - -/** - * Resize arrays for non-zero initializers. - * p pointer to array lvalue to be updated - * newlength new .length property of array - * sizeelem size of each element of array - * initsize size of initializer - * ... initializer - */ -extern (C) byte[] _d_arraysetlengthiT(TypeInfo ti, size_t newlength, Array *p) -in -{ - assert(!p.length || p.data); -} -body -{ - byte* newdata; - size_t sizeelem = ti.next.tsize(); - void[] initializer = ti.next.init(); - size_t initsize = initializer.length; - - assert(sizeelem); - assert(initsize); - assert(initsize <= sizeelem); - assert((sizeelem / initsize) * initsize == sizeelem); - - debug(PRINTF) - { - printf("_d_arraysetlengthiT(p = %p, sizeelem = %d, newlength = %d, initsize = %d)\n", p, sizeelem, newlength, initsize); - if (p) - printf("\tp.data = %p, p.length = %d\n", p.data, p.length); - } - - if (newlength) - { - version (D_InlineAsm_X86) - { - size_t newsize = void; - - asm - { - mov EAX,newlength ; - mul EAX,sizeelem ; - mov newsize,EAX ; - jc Loverflow ; - } - } - else - { - size_t newsize = sizeelem * newlength; - - if (newsize / newlength != sizeelem) - goto Loverflow; - } - debug(PRINTF) printf("newsize = %x, newlength = %x\n", newsize, newlength); - - size_t size = p.length * sizeelem; - - if (p.data) - { - newdata = p.data; - if (newlength > p.length) - { - auto info = gc_query(p.data); - - if (info.size <= newsize || info.base != p.data) - { - if (info.size >= PAGESIZE && info.base == p.data) - { // Try to extend in-place - auto u = gc_extend(p.data, (newsize + 1) - info.size, (newsize + 1) - info.size); - if (u) - { - goto L1; - } - } - newdata = cast(byte *)gc_malloc(newsize + 1, info.attr); - newdata[0 .. size] = p.data[0 .. size]; - L1: ; - } - } - } - else - { - newdata = cast(byte *)gc_malloc(newsize + 1, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0); - } - - auto q = initializer.ptr; // pointer to initializer - - if (newsize > size) - { - if (initsize == 1) - { - debug(PRINTF) printf("newdata = %p, size = %d, newsize = %d, *q = %d\n", newdata, size, newsize, *cast(byte*)q); - newdata[size .. newsize] = *(cast(byte*)q); - } - else - { - for (size_t u = size; u < newsize; u += initsize) - { - memcpy(newdata + u, q, initsize); - } - } - } - } - else - { - newdata = p.data; - } - - p.data = newdata; - p.length = newlength; - return newdata[0 .. newlength]; - -Loverflow: - onOutOfMemoryError(); -} - - -/** - * Append y[] to array x[]. - * size is size of each array element. - */ -extern (C) long _d_arrayappendT(TypeInfo ti, Array *px, byte[] y) -{ - auto sizeelem = ti.next.tsize(); // array element size - auto info = gc_query(px.data); - auto length = px.length; - auto newlength = length + y.length; - auto newsize = newlength * sizeelem; - - if (info.size < newsize || info.base != px.data) - { byte* newdata; - - if (info.size >= PAGESIZE && info.base == px.data) - { // Try to extend in-place - auto u = gc_extend(px.data, (newsize + 1) - info.size, (newsize + 1) - info.size); - if (u) - { - goto L1; - } - } - newdata = cast(byte *)gc_malloc(newCapacity(newlength, sizeelem) + 1, info.attr); - memcpy(newdata, px.data, length * sizeelem); - px.data = newdata; - } - L1: - px.length = newlength; - memcpy(px.data + length * sizeelem, y.ptr, y.length * sizeelem); - return *cast(long*)px; -} - - -/** - * - */ -size_t newCapacity(size_t newlength, size_t size) -{ - version(none) - { - size_t newcap = newlength * size; - } - else - { - /* - * Better version by Dave Fladebo: - * This uses an inverse logorithmic algorithm to pre-allocate a bit more - * space for larger arrays. - * - Arrays smaller than PAGESIZE bytes are left as-is, so for the most - * common cases, memory allocation is 1 to 1. The small overhead added - * doesn't affect small array perf. (it's virtually the same as - * current). - * - Larger arrays have some space pre-allocated. - * - As the arrays grow, the relative pre-allocated space shrinks. - * - The logorithmic algorithm allocates relatively more space for - * mid-size arrays, making it very fast for medium arrays (for - * mid-to-large arrays, this turns out to be quite a bit faster than the - * equivalent realloc() code in C, on Linux at least. Small arrays are - * just as fast as GCC). - * - Perhaps most importantly, overall memory usage and stress on the GC - * is decreased significantly for demanding environments. - */ - size_t newcap = newlength * size; - size_t newext = 0; - - if (newcap > PAGESIZE) - { - //double mult2 = 1.0 + (size / log10(pow(newcap * 2.0,2.0))); - - // redo above line using only integer math - - static int log2plus1(size_t c) - { int i; - - if (c == 0) - i = -1; - else - for (i = 1; c >>= 1; i++) - { - } - return i; - } - - /* The following setting for mult sets how much bigger - * the new size will be over what is actually needed. - * 100 means the same size, more means proportionally more. - * More means faster but more memory consumption. - */ - //long mult = 100 + (1000L * size) / (6 * log2plus1(newcap)); - long mult = 100 + (1000L * size) / log2plus1(newcap); - - // testing shows 1.02 for large arrays is about the point of diminishing return - if (mult < 102) - mult = 102; - newext = cast(size_t)((newcap * mult) / 100); - newext -= newext % size; - debug(PRINTF) printf("mult: %2.2f, alloc: %2.2f\n",mult/100.0,newext / cast(double)size); - } - newcap = newext > newcap ? newext : newcap; - debug(PRINTF) printf("newcap = %d, newlength = %d, size = %d\n", newcap, newlength, size); - } - return newcap; -} - - -/** - * - */ -extern (C) byte[] _d_arrayappendcT(TypeInfo ti, inout byte[] x, ...) -{ - auto sizeelem = ti.next.tsize(); // array element size - auto info = gc_query(x.ptr); - auto length = x.length; - auto newlength = length + 1; - auto newsize = newlength * sizeelem; - - assert(info.size == 0 || length * sizeelem <= info.size); - - debug(PRINTF) printf("_d_arrayappendcT(sizeelem = %d, ptr = %p, length = %d, cap = %d)\n", sizeelem, x.ptr, x.length, info.size); - - if (info.size <= newsize || info.base != x.ptr) - { byte* newdata; - - if (info.size >= PAGESIZE && info.base == x.ptr) - { // Try to extend in-place - auto u = gc_extend(x.ptr, (newsize + 1) - info.size, (newsize + 1) - info.size); - if (u) - { - goto L1; - } - } - debug(PRINTF) printf("_d_arrayappendcT(length = %d, newlength = %d, cap = %d)\n", length, newlength, info.size); - auto newcap = newCapacity(newlength, sizeelem); - assert(newcap >= newlength * sizeelem); - newdata = cast(byte *)gc_malloc(newcap + 1, info.attr); - memcpy(newdata, x.ptr, length * sizeelem); - (cast(void**)(&x))[1] = newdata; - } - L1: - byte *argp = cast(byte *)(&ti + 2); - - *cast(size_t *)&x = newlength; - x.ptr[length * sizeelem .. newsize] = argp[0 .. sizeelem]; - assert((cast(size_t)x.ptr & 15) == 0); - assert(gc_sizeOf(x.ptr) > x.length * sizeelem); - return x; -} - - -/** - * - */ -extern (C) byte[] _d_arraycatT(TypeInfo ti, byte[] x, byte[] y) -out (result) -{ - auto sizeelem = ti.next.tsize(); // array element size - debug(PRINTF) printf("_d_arraycatT(%d,%p ~ %d,%p sizeelem = %d => %d,%p)\n", x.length, x.ptr, y.length, y.ptr, sizeelem, result.length, result.ptr); - assert(result.length == x.length + y.length); - for (size_t i = 0; i < x.length * sizeelem; i++) - assert((cast(byte*)result)[i] == (cast(byte*)x)[i]); - for (size_t i = 0; i < y.length * sizeelem; i++) - assert((cast(byte*)result)[x.length * sizeelem + i] == (cast(byte*)y)[i]); - - size_t cap = gc_sizeOf(result.ptr); - assert(!cap || cap > result.length * sizeelem); -} -body -{ - version (none) - { - /* Cannot use this optimization because: - * char[] a, b; - * char c = 'a'; - * b = a ~ c; - * c = 'b'; - * will change the contents of b. - */ - if (!y.length) - return x; - if (!x.length) - return y; - } - - debug(PRINTF) printf("_d_arraycatT(%d,%p ~ %d,%p)\n", x.length, x.ptr, y.length, y.ptr); - auto sizeelem = ti.next.tsize(); // array element size - debug(PRINTF) printf("_d_arraycatT(%d,%p ~ %d,%p sizeelem = %d)\n", x.length, x.ptr, y.length, y.ptr, sizeelem); - size_t xlen = x.length * sizeelem; - size_t ylen = y.length * sizeelem; - size_t len = xlen + ylen; - - if (!len) - return null; - - byte* p = cast(byte*)gc_malloc(len + 1, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0); - memcpy(p, x.ptr, xlen); - memcpy(p + xlen, y.ptr, ylen); - p[len] = 0; - return p[0 .. x.length + y.length]; -} - - -/** - * - */ -extern (C) byte[] _d_arraycatnT(TypeInfo ti, uint n, ...) -{ void* a; - size_t length; - byte[]* p; - uint i; - byte[] b; - auto size = ti.next.tsize(); // array element size - - p = cast(byte[]*)(&n + 1); - - for (i = 0; i < n; i++) - { - b = *p++; - length += b.length; - } - if (!length) - return null; - - a = gc_malloc(length * size, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0); - p = cast(byte[]*)(&n + 1); - - uint j = 0; - for (i = 0; i < n; i++) - { - b = *p++; - if (b.length) - { - memcpy(a + j, b.ptr, b.length * size); - j += b.length * size; - } - } - - byte[] result; - *cast(int *)&result = length; // jam length - (cast(void **)&result)[1] = a; // jam ptr - return result; -} - - -/** - * - */ -extern (C) void* _d_arrayliteralT(TypeInfo ti, size_t length, ...) -{ - auto sizeelem = ti.next.tsize(); // array element size - void* result; - - debug(PRINTF) printf("_d_arrayliteralT(sizeelem = %d, length = %d)\n", sizeelem, length); - if (length == 0 || sizeelem == 0) - result = null; - else - { - result = gc_malloc(length * sizeelem, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0); - - va_list q; - va_start!(size_t)(q, length); - - size_t stacksize = (sizeelem + int.sizeof - 1) & ~(int.sizeof - 1); - - if (stacksize == sizeelem) - { - memcpy(result, q, length * sizeelem); - } - else - { - for (size_t i = 0; i < length; i++) - { - memcpy(result + i * sizeelem, q, sizeelem); - q += stacksize; - } - } - - va_end(q); - } - return result; -} - - -/** - * Support for array.dup property. - */ -struct Array2 -{ - size_t length; - void* ptr; -} - - -/** - * - */ -extern (C) long _adDupT(TypeInfo ti, Array2 a) -out (result) -{ - auto sizeelem = ti.next.tsize(); // array element size - assert(memcmp((*cast(Array2*)&result).ptr, a.ptr, a.length * sizeelem) == 0); -} -body -{ - Array2 r; - - if (a.length) - { - auto sizeelem = ti.next.tsize(); // array element size - auto size = a.length * sizeelem; - r.ptr = gc_malloc(size, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0); - r.length = a.length; - memcpy(r.ptr, a.ptr, size); - } - return *cast(long*)(&r); -} - - -unittest -{ - int[] a; - int[] b; - int i; - - a = new int[3]; - a[0] = 1; a[1] = 2; a[2] = 3; - b = a.dup; - assert(b.length == 3); - for (i = 0; i < 3; i++) - assert(b[i] == i + 1); -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/llmath.d --- a/druntime/src/compiler/dmd/llmath.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,531 +0,0 @@ -/** - * Support for 64-bit longs. - * - * Copyright: Copyright Digital Mars 1993 - 2009. - * License: Boost License 1.0. - * Authors: Walter Bright, Sean Kelly - * - * Copyright Digital Mars 2000 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -#include - -#if __cplusplus -extern "C" { -#endif - -struct ClassInfo; -struct Vtbl; - -typedef struct Vtbl -{ - size_t len; - void **vptr; -} Vtbl; - -typedef struct Interface -{ - struct ClassInfo *classinfo; - struct Vtbl vtbl; - int offset; -} Interface; - -typedef struct Object -{ - void **vptr; - void *monitor; -} Object; - -typedef struct ClassInfo -{ - Object object; - - size_t initlen; - void *init; - - size_t namelen; - char *name; - - Vtbl vtbl; - - size_t interfacelen; - Interface *interfaces; - - struct ClassInfo *baseClass; - - void *destructor; - void *invariant; - - int flags; -} ClassInfo; - -typedef struct Throwable -{ - Object object; - - size_t msglen; - char* msg; - - size_t filelen; - char* file; - - size_t line; - - struct Interface *info; - struct Throwable *next; -} Throwable; - -typedef struct Array -{ - size_t length; - void *ptr; -} Array; - -typedef struct Delegate -{ - void *thisptr; - void (*funcptr)(); -} Delegate; - -void _d_monitorenter(Object *h); -void _d_monitorexit(Object *h); - -int _d_isbaseof(ClassInfo *b, ClassInfo *c); -Object *_d_dynamic_cast(Object *o, ClassInfo *ci); - -Object * _d_newclass(ClassInfo *ci); -void _d_delclass(Object **p); - -void _d_OutOfMemory(); - -#if __cplusplus -} -#endif diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/memory.d --- a/druntime/src/compiler/dmd/memory.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,213 +0,0 @@ -/** - * This module exposes functionality for inspecting and manipulating memory. - * - * Copyright: Copyright Digital Mars 2000 - 2009. - * License: Boost License 1.0. - * Authors: Walter Bright - * - * Copyright Digital Mars 2004 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module rt.memset; - -extern (C) -{ - // Functions from the C library. - void *memcpy(void *, void *, size_t); -} - -extern (C): - -short *_memset16(short *p, short value, size_t count) -{ - short *pstart = p; - short *ptop; - - for (ptop = &p[count]; p < ptop; p++) - *p = value; - return pstart; -} - -int *_memset32(int *p, int value, size_t count) -{ -version (X86) -{ - asm - { - mov EDI,p ; - mov EAX,value ; - mov ECX,count ; - mov EDX,EDI ; - rep ; - stosd ; - mov EAX,EDX ; - } -} -else -{ - int *pstart = p; - int *ptop; - - for (ptop = &p[count]; p < ptop; p++) - *p = value; - return pstart; -} -} - -long *_memset64(long *p, long value, size_t count) -{ - long *pstart = p; - long *ptop; - - for (ptop = &p[count]; p < ptop; p++) - *p = value; - return pstart; -} - -cdouble *_memset128(cdouble *p, cdouble value, size_t count) -{ - cdouble *pstart = p; - cdouble *ptop; - - for (ptop = &p[count]; p < ptop; p++) - *p = value; - return pstart; -} - -real *_memset80(real *p, real value, size_t count) -{ - real *pstart = p; - real *ptop; - - for (ptop = &p[count]; p < ptop; p++) - *p = value; - return pstart; -} - -creal *_memset160(creal *p, creal value, size_t count) -{ - creal *pstart = p; - creal *ptop; - - for (ptop = &p[count]; p < ptop; p++) - *p = value; - return pstart; -} - -void *_memsetn(void *p, void *value, int count, size_t sizelem) -{ void *pstart = p; - int i; - - for (i = 0; i < count; i++) - { - memcpy(p, value, sizelem); - p = cast(void *)(cast(char *)p + sizelem); - } - return pstart; -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/minit.asm --- a/druntime/src/compiler/dmd/minit.asm Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,85 +0,0 @@ -;_ minit.asm -; Module initialization support. -; -; Copyright: Copyright Digital Mars 2000 - 2009. -; License: Boost License 1.0. - * Authors: Walter Bright, Sean Kelly - * - * Copyright Digital Mars 2000 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -#include -#include -#include - -#if _WIN32 -#elif linux || __APPLE__ -#define USE_PTHREADS 1 -#else -#endif - -#if _WIN32 -#include -#endif - -#if USE_PTHREADS -#include -#endif - -#include "mars.h" - -// This is what the monitor reference in Object points to -typedef struct Monitor -{ - void* impl; // for user-level monitors - Array devt; // for internal monitors - -#if _WIN32 - CRITICAL_SECTION mon; -#endif - -#if USE_PTHREADS - pthread_mutex_t mon; -#endif -} Monitor; - -#define MONPTR(h) (&((Monitor *)(h)->monitor)->mon) - -static volatile int inited; - -/* =============================== Win32 ============================ */ - -#if _WIN32 - -static CRITICAL_SECTION _monitor_critsec; - -void _STI_monitor_staticctor() -{ - if (!inited) - { InitializeCriticalSection(&_monitor_critsec); - inited = 1; - } -} - -void _STD_monitor_staticdtor() -{ - if (inited) - { inited = 0; - DeleteCriticalSection(&_monitor_critsec); - } -} - -void _d_monitor_create(Object *h) -{ - /* - * NOTE: Assume this is only called when h->monitor is null prior to the - * call. However, please note that another thread may call this function - * at the same time, so we can not assert this here. Instead, try and - * create a lock, and if one already exists then forget about it. - */ - - //printf("+_d_monitor_create(%p)\n", h); - assert(h); - Monitor *cs = NULL; - EnterCriticalSection(&_monitor_critsec); - if (!h->monitor) - { - cs = (Monitor *)calloc(sizeof(Monitor), 1); - assert(cs); - InitializeCriticalSection(&cs->mon); - h->monitor = (void *)cs; - cs = NULL; - } - LeaveCriticalSection(&_monitor_critsec); - if (cs) - free(cs); - //printf("-_d_monitor_create(%p)\n", h); -} - -void _d_monitor_destroy(Object *h) -{ - //printf("+_d_monitor_destroy(%p)\n", h); - assert(h && h->monitor && !(((Monitor*)h->monitor)->impl)); - DeleteCriticalSection(MONPTR(h)); - free((void *)h->monitor); - h->monitor = NULL; - //printf("-_d_monitor_destroy(%p)\n", h); -} - -int _d_monitor_lock(Object *h) -{ - //printf("+_d_monitor_acquire(%p)\n", h); - assert(h && h->monitor && !(((Monitor*)h->monitor)->impl)); - EnterCriticalSection(MONPTR(h)); - //printf("-_d_monitor_acquire(%p)\n", h); -} - -void _d_monitor_unlock(Object *h) -{ - //printf("+_d_monitor_release(%p)\n", h); - assert(h && h->monitor && !(((Monitor*)h->monitor)->impl)); - LeaveCriticalSection(MONPTR(h)); - //printf("-_d_monitor_release(%p)\n", h); -} - -#endif - -/* =============================== linux ============================ */ - -#if USE_PTHREADS - -#ifndef PTHREAD_MUTEX_RECURSIVE -# define PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP -#endif - -// Includes attribute fixes from David Friedman's GDC port - -static pthread_mutex_t _monitor_critsec; -static pthread_mutexattr_t _monitors_attr; - -void _STI_monitor_staticctor() -{ - if (!inited) - { - pthread_mutexattr_init(&_monitors_attr); - pthread_mutexattr_settype(&_monitors_attr, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(&_monitor_critsec, 0); - inited = 1; - } -} - -void _STD_monitor_staticdtor() -{ - if (inited) - { inited = 0; - pthread_mutex_destroy(&_monitor_critsec); - pthread_mutexattr_destroy(&_monitors_attr); - } -} - -void _d_monitor_create(Object *h) -{ - /* - * NOTE: Assume this is only called when h->monitor is null prior to the - * call. However, please note that another thread may call this function - * at the same time, so we can not assert this here. Instead, try and - * create a lock, and if one already exists then forget about it. - */ - - //printf("+_d_monitor_create(%p)\n", h); - assert(h); - Monitor *cs = NULL; - pthread_mutex_lock(&_monitor_critsec); - if (!h->monitor) - { - cs = (Monitor *)calloc(sizeof(Monitor), 1); - assert(cs); - pthread_mutex_init(&cs->mon, & _monitors_attr); - h->monitor = (void *)cs; - cs = NULL; - } - pthread_mutex_unlock(&_monitor_critsec); - if (cs) - free(cs); - //printf("-_d_monitor_create(%p)\n", h); -} - -void _d_monitor_destroy(Object *h) -{ - //printf("+_d_monitor_destroy(%p)\n", h); - assert(h && h->monitor && !(((Monitor*)h->monitor)->impl)); - pthread_mutex_destroy(MONPTR(h)); - free((void *)h->monitor); - h->monitor = NULL; - //printf("-_d_monitor_destroy(%p)\n", h); -} - -int _d_monitor_lock(Object *h) -{ - //printf("+_d_monitor_acquire(%p)\n", h); - assert(h && h->monitor && !(((Monitor*)h->monitor)->impl)); - pthread_mutex_lock(MONPTR(h)); - //printf("-_d_monitor_acquire(%p)\n", h); -} - -void _d_monitor_unlock(Object *h) -{ - //printf("+_d_monitor_release(%p)\n", h); - assert(h && h->monitor && !(((Monitor*)h->monitor)->impl)); - pthread_mutex_unlock(MONPTR(h)); - //printf("-_d_monitor_release(%p)\n", h); -} - -#endif diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/obj.d --- a/druntime/src/compiler/dmd/obj.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -/** - * Containts object comparator functions called by generated code. - * - * Copyright: Copyright Digital Mars 2002 - 2009. - * License: Boost License 1.0. - * Authors: Walter Bright, Sean Kelly - * - * Copyright Digital Mars 2000 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ - -module object; - -private -{ - import core.stdc.string; - import core.stdc.stdlib; - // HACK: This versioning is to provide for the different treatment of - // imports in a normal vs. a -lib build. It should really be fixed - // correctly before the next release. - version (D_Ddoc) - import util.string; - else - import rt.util.string; - debug(PRINTF) import core.stdc.stdio; - - extern (C) void onOutOfMemoryError(); - extern (C) Object _d_newclass(ClassInfo ci); -} - -// NOTE: For some reason, this declaration method doesn't work -// in this particular file (and this file only). It must -// be a DMD thing. -//alias typeof(int.sizeof) size_t; -//alias typeof(cast(void*)0 - cast(void*)0) ptrdiff_t; - -version(X86_64) -{ - alias ulong size_t; - alias long ptrdiff_t; -} -else -{ - alias uint size_t; - alias int ptrdiff_t; -} - -alias size_t hash_t; -alias bool equals_t; - -alias immutable(char)[] string; -alias immutable(wchar)[] wstring; -alias immutable(dchar)[] dstring; - -/** - * All D class objects inherit from Object. - */ -class Object -{ - /** - * Convert Object to a human readable string. - */ - string toString() - { - return this.classinfo.name; - } - - /** - * Compute hash function for Object. - */ - hash_t toHash() - { - // BUG: this prevents a compacting GC from working, needs to be fixed - return cast(hash_t)cast(void*)this; - } - - /** - * Compare with another Object obj. - * Returns: - * $(TABLE - * $(TR $(TD this < obj) $(TD < 0)) - * $(TR $(TD this == obj) $(TD 0)) - * $(TR $(TD this > obj) $(TD > 0)) - * ) - */ - int opCmp(Object o) - { - // BUG: this prevents a compacting GC from working, needs to be fixed - //return cast(int)cast(void*)this - cast(int)cast(void*)o; - - throw new Exception("need opCmp for class " ~ this.classinfo.name); - //return this !is o; - } - - /** - * Returns !=0 if this object does have the same contents as obj. - */ - equals_t opEquals(Object o) - { - return this is o; - } - - interface Monitor - { - void lock(); - void unlock(); - } - - /** - * Create instance of class specified by classname. - * The class must either have no constructors or have - * a default constructor. - * Returns: - * null if failed - */ - static Object factory(string classname) - { - auto ci = ClassInfo.find(classname); - if (ci) - { - return ci.create(); - } - return null; - } -} - -/** - * Information about an interface. - * When an object is accessed via an interface, an Interface* appears as the - * first entry in its vtbl. - */ -struct Interface -{ - ClassInfo classinfo; /// .classinfo for this interface (not for containing class) - void*[] vtbl; - ptrdiff_t offset; /// offset to Interface 'this' from Object 'this' -} - -/** - * Runtime type information about a class. Can be retrieved for any class type - * or instance by using the .classinfo property. - * A pointer to this appears as the first entry in the class's vtbl[]. - */ -class ClassInfo : Object -{ - byte[] init; /** class static initializer - * (init.length gives size in bytes of class) - */ - string name; /// class name - void*[] vtbl; /// virtual function pointer table - Interface[] interfaces; /// interfaces this class implements - ClassInfo base; /// base class - void* destructor; - void function(Object) classInvariant; - uint flags; - // 1: // is IUnknown or is derived from IUnknown - // 2: // has no possible pointers into GC memory - // 4: // has offTi[] member - // 8: // has constructors - // 16: // has xgetMembers member - // 32: // has typeinfo member - void* deallocator; - OffsetTypeInfo[] offTi; - void function(Object) defaultConstructor; // default Constructor - const(MemberInfo[]) function(in char[]) xgetMembers; - TypeInfo typeinfo; - - /** - * Search all modules for ClassInfo corresponding to classname. - * Returns: null if not found - */ - static ClassInfo find(in char[] classname) - { - foreach (m; ModuleInfo) - { - //writefln("module %s, %d", m.name, m.localClasses.length); - foreach (c; m.localClasses) - { - //writefln("\tclass %s", c.name); - if (c.name == classname) - return c; - } - } - return null; - } - - /** - * Create instance of Object represented by 'this'. - */ - Object create() - { - if (flags & 8 && !defaultConstructor) - return null; - Object o = _d_newclass(this); - if (flags & 8 && defaultConstructor) - { - defaultConstructor(o); - } - return o; - } - - /** - * Search for all members with the name 'name'. - * If name[] is null, return all members. - */ - const(MemberInfo[]) getMembers(in char[] name) - { - if (flags & 16 && xgetMembers) - return xgetMembers(name); - return null; - } -} - -/** - * Array of pairs giving the offset and type information for each - * member in an aggregate. - */ -struct OffsetTypeInfo -{ - size_t offset; /// Offset of member from start of object - TypeInfo ti; /// TypeInfo for this member -} - -/** - * Runtime type information about a type. - * Can be retrieved for any type using a - * TypeidExpression. - */ -class TypeInfo -{ - override hash_t toHash() - { - hash_t hash; - - foreach (char c; this.toString()) - hash = hash * 9 + c; - return hash; - } - - override int opCmp(Object o) - { - if (this is o) - return 0; - TypeInfo ti = cast(TypeInfo)o; - if (ti is null) - return 1; - return dstrcmp(this.toString(), ti.toString()); - } - - override equals_t opEquals(Object o) - { - /* TypeInfo instances are singletons, but duplicates can exist - * across DLL's. Therefore, comparing for a name match is - * sufficient. - */ - if (this is o) - return true; - TypeInfo ti = cast(TypeInfo)o; - return ti && this.toString() == ti.toString(); - } - - /// Returns a hash of the instance of a type. - hash_t getHash(in void* p) { return cast(hash_t)p; } - - /// Compares two instances for equality. - equals_t equals(in void* p1, in void* p2) { return p1 == p2; } - - /// Compares two instances for <, ==, or >. - int compare(in void* p1, in void* p2) { return 0; } - - /// Returns size of the type. - size_t tsize() { return 0; } - - /// Swaps two instances of the type. - void swap(void* p1, void* p2) - { - size_t n = tsize(); - for (size_t i = 0; i < n; i++) - { - byte t = (cast(byte *)p1)[i]; - (cast(byte*)p1)[i] = (cast(byte*)p2)[i]; - (cast(byte*)p2)[i] = t; - } - } - - /// Get TypeInfo for 'next' type, as defined by what kind of type this is, - /// null if none. - TypeInfo next() { return null; } - - /// Return default initializer, null if default initialize to 0 - void[] init() { return null; } - - /// Get flags for type: 1 means GC should scan for pointers - uint flags() { return 0; } - - /// Get type information on the contents of the type; null if not available - OffsetTypeInfo[] offTi() { return null; } - /// Run the destructor on the object and all its sub-objects - void destroy(void* p) {} - /// Run the postblit on the object and all its sub-objects - void postblit(void* p) {} -} - -class TypeInfo_Typedef : TypeInfo -{ - override string toString() { return name; } - - override equals_t opEquals(Object o) - { - TypeInfo_Typedef c; - return this is o || - ((c = cast(TypeInfo_Typedef)o) !is null && - this.name == c.name && - this.base == c.base); - } - - override hash_t getHash(in void* p) { return base.getHash(p); } - override equals_t equals(in void* p1, in void* p2) { return base.equals(p1, p2); } - override int compare(in void* p1, in void* p2) { return base.compare(p1, p2); } - override size_t tsize() { return base.tsize(); } - override void swap(void* p1, void* p2) { return base.swap(p1, p2); } - - override TypeInfo next() { return base.next(); } - override uint flags() { return base.flags(); } - override void[] init() { return m_init.length ? m_init : base.init(); } - - TypeInfo base; - string name; - void[] m_init; -} - -class TypeInfo_Enum : TypeInfo_Typedef -{ - -} - -class TypeInfo_Pointer : TypeInfo -{ - override string toString() { return m_next.toString() ~ "*"; } - - override equals_t opEquals(Object o) - { - TypeInfo_Pointer c; - return this is o || - ((c = cast(TypeInfo_Pointer)o) !is null && - this.m_next == c.m_next); - } - - override hash_t getHash(in void* p) - { - return cast(hash_t)*cast(void**)p; - } - - override equals_t equals(in void* p1, in void* p2) - { - return *cast(void**)p1 == *cast(void**)p2; - } - - override int compare(in void* p1, in void* p2) - { - if (*cast(void**)p1 < *cast(void**)p2) - return -1; - else if (*cast(void**)p1 > *cast(void**)p2) - return 1; - else - return 0; - } - - override size_t tsize() - { - return (void*).sizeof; - } - - override void swap(void* p1, void* p2) - { - void* tmp = *cast(void**)p1; - *cast(void**)p1 = *cast(void**)p2; - *cast(void**)p2 = tmp; - } - - override TypeInfo next() { return m_next; } - override uint flags() { return 1; } - - TypeInfo m_next; -} - -class TypeInfo_Array : TypeInfo -{ - override string toString() { return value.toString() ~ "[]"; } - - override equals_t opEquals(Object o) - { - TypeInfo_Array c; - return this is o || - ((c = cast(TypeInfo_Array)o) !is null && - this.value == c.value); - } - - override hash_t getHash(in void* p) - { - size_t sz = value.tsize(); - hash_t hash = 0; - void[] a = *cast(void[]*)p; - for (size_t i = 0; i < a.length; i++) - hash += value.getHash(a.ptr + i * sz) * 11; - return hash; - } - - override equals_t equals(in void* p1, in void* p2) - { - void[] a1 = *cast(void[]*)p1; - void[] a2 = *cast(void[]*)p2; - if (a1.length != a2.length) - return false; - size_t sz = value.tsize(); - for (size_t i = 0; i < a1.length; i++) - { - if (!value.equals(a1.ptr + i * sz, a2.ptr + i * sz)) - return false; - } - return true; - } - - override int compare(in void* p1, in void* p2) - { - void[] a1 = *cast(void[]*)p1; - void[] a2 = *cast(void[]*)p2; - size_t sz = value.tsize(); - size_t len = a1.length; - - if (a2.length < len) - len = a2.length; - for (size_t u = 0; u < len; u++) - { - int result = value.compare(a1.ptr + u * sz, a2.ptr + u * sz); - if (result) - return result; - } - return cast(int)a1.length - cast(int)a2.length; - } - - override size_t tsize() - { - return (void[]).sizeof; - } - - override void swap(void* p1, void* p2) - { - void[] tmp = *cast(void[]*)p1; - *cast(void[]*)p1 = *cast(void[]*)p2; - *cast(void[]*)p2 = tmp; - } - - TypeInfo value; - - override TypeInfo next() - { - return value; - } - - override uint flags() { return 1; } -} - -class TypeInfo_StaticArray : TypeInfo -{ - override string toString() - { - char[10] tmp = void; - return cast(string)(value.toString() ~ "[" ~ tmp.intToString(len) ~ "]"); - } - - override equals_t opEquals(Object o) - { - TypeInfo_StaticArray c; - return this is o || - ((c = cast(TypeInfo_StaticArray)o) !is null && - this.len == c.len && - this.value == c.value); - } - - override hash_t getHash(in void* p) - { - size_t sz = value.tsize(); - hash_t hash = 0; - for (size_t i = 0; i < len; i++) - hash += value.getHash(p + i * sz); - return hash; - } - - override equals_t equals(in void* p1, in void* p2) - { - size_t sz = value.tsize(); - - for (size_t u = 0; u < len; u++) - { - if (!value.equals(p1 + u * sz, p2 + u * sz)) - return false; - } - return true; - } - - override int compare(in void* p1, in void* p2) - { - size_t sz = value.tsize(); - - for (size_t u = 0; u < len; u++) - { - int result = value.compare(p1 + u * sz, p2 + u * sz); - if (result) - return result; - } - return 0; - } - - override size_t tsize() - { - return len * value.tsize(); - } - - override void swap(void* p1, void* p2) - { - void* tmp; - size_t sz = value.tsize(); - ubyte[16] buffer; - void* pbuffer; - - if (sz < buffer.sizeof) - tmp = buffer.ptr; - else - tmp = pbuffer = (new void[sz]).ptr; - - for (size_t u = 0; u < len; u += sz) - { size_t o = u * sz; - memcpy(tmp, p1 + o, sz); - memcpy(p1 + o, p2 + o, sz); - memcpy(p2 + o, tmp, sz); - } - if (pbuffer) - delete pbuffer; - } - - override void[] init() { return value.init(); } - override TypeInfo next() { return value; } - override uint flags() { return value.flags(); } - - override void destroy(void* p) - { - auto sz = value.tsize(); - p += sz * len; - foreach (i; 0 .. len) - { - p -= sz; - value.destroy(p); - } - } - - override void postblit(void* p) - { - auto sz = value.tsize(); - foreach (i; 0 .. len) - { - value.postblit(p); - p += sz; - } - } - - TypeInfo value; - size_t len; -} - -class TypeInfo_AssociativeArray : TypeInfo -{ - override string toString() - { - return cast(string)(next.toString() ~ "[" ~ key.toString() ~ "]"); - } - - override equals_t opEquals(Object o) - { - TypeInfo_AssociativeArray c; - return this is o || - ((c = cast(TypeInfo_AssociativeArray)o) !is null && - this.key == c.key && - this.value == c.value); - } - - // BUG: need to add the rest of the functions - - override size_t tsize() - { - return (char[int]).sizeof; - } - - override TypeInfo next() { return value; } - override uint flags() { return 1; } - - TypeInfo value; - TypeInfo key; -} - -class TypeInfo_Function : TypeInfo -{ - override string toString() - { - return cast(string)(next.toString() ~ "()"); - } - - override equals_t opEquals(Object o) - { - TypeInfo_Function c; - return this is o || - ((c = cast(TypeInfo_Function)o) !is null && - this.next == c.next); - } - - // BUG: need to add the rest of the functions - - override size_t tsize() - { - return 0; // no size for functions - } - - TypeInfo next; -} - -class TypeInfo_Delegate : TypeInfo -{ - override string toString() - { - return cast(string)(next.toString() ~ " delegate()"); - } - - override equals_t opEquals(Object o) - { - TypeInfo_Delegate c; - return this is o || - ((c = cast(TypeInfo_Delegate)o) !is null && - this.next == c.next); - } - - // BUG: need to add the rest of the functions - - override size_t tsize() - { - alias int delegate() dg; - return dg.sizeof; - } - - override uint flags() { return 1; } - - TypeInfo next; -} - -class TypeInfo_Class : TypeInfo -{ - override string toString() { return info.name; } - - override equals_t opEquals(Object o) - { - TypeInfo_Class c; - return this is o || - ((c = cast(TypeInfo_Class)o) !is null && - this.info.name == c.classinfo.name); - } - - override hash_t getHash(in void* p) - { - Object o = *cast(Object*)p; - return o ? o.toHash() : 0; - } - - override equals_t equals(in void* p1, in void* p2) - { - Object o1 = *cast(Object*)p1; - Object o2 = *cast(Object*)p2; - - return (o1 is o2) || (o1 && o1.opEquals(o2)); - } - - override int compare(in void* p1, in void* p2) - { - Object o1 = *cast(Object*)p1; - Object o2 = *cast(Object*)p2; - int c = 0; - - // Regard null references as always being "less than" - if (o1 !is o2) - { - if (o1) - { - if (!o2) - c = 1; - else - c = o1.opCmp(o2); - } - else - c = -1; - } - return c; - } - - override size_t tsize() - { - return Object.sizeof; - } - - override uint flags() { return 1; } - - override OffsetTypeInfo[] offTi() - { - return (info.flags & 4) ? info.offTi : null; - } - - ClassInfo info; -} - -class TypeInfo_Interface : TypeInfo -{ - override string toString() { return info.name; } - - override equals_t opEquals(Object o) - { - TypeInfo_Interface c; - return this is o || - ((c = cast(TypeInfo_Interface)o) !is null && - this.info.name == c.classinfo.name); - } - - override hash_t getHash(in void* p) - { - Interface* pi = **cast(Interface ***)*cast(void**)p; - Object o = cast(Object)(*cast(void**)p - pi.offset); - assert(o); - return o.toHash(); - } - - override equals_t equals(in void* p1, in void* p2) - { - Interface* pi = **cast(Interface ***)*cast(void**)p1; - Object o1 = cast(Object)(*cast(void**)p1 - pi.offset); - pi = **cast(Interface ***)*cast(void**)p2; - Object o2 = cast(Object)(*cast(void**)p2 - pi.offset); - - return o1 == o2 || (o1 && o1.opCmp(o2) == 0); - } - - override int compare(in void* p1, in void* p2) - { - Interface* pi = **cast(Interface ***)*cast(void**)p1; - Object o1 = cast(Object)(*cast(void**)p1 - pi.offset); - pi = **cast(Interface ***)*cast(void**)p2; - Object o2 = cast(Object)(*cast(void**)p2 - pi.offset); - int c = 0; - - // Regard null references as always being "less than" - if (o1 != o2) - { - if (o1) - { - if (!o2) - c = 1; - else - c = o1.opCmp(o2); - } - else - c = -1; - } - return c; - } - - override size_t tsize() - { - return Object.sizeof; - } - - override uint flags() { return 1; } - - ClassInfo info; -} - -class TypeInfo_Struct : TypeInfo -{ - override string toString() { return name; } - - override equals_t opEquals(Object o) - { - TypeInfo_Struct s; - return this is o || - ((s = cast(TypeInfo_Struct)o) !is null && - this.name == s.name && - this.init.length == s.init.length); - } - - override hash_t getHash(in void* p) - { - assert(p); - if (xtoHash) - { - debug(PRINTF) printf("getHash() using xtoHash\n"); - return (*xtoHash)(p); - } - else - { - hash_t h; - debug(PRINTF) printf("getHash() using default hash\n"); - // A sorry hash algorithm. - // Should use the one for strings. - // BUG: relies on the GC not moving objects - auto q = cast(const(ubyte)*)p; - for (size_t i = 0; i < init.length; i++) - { - h = h * 9 + *q; - q++; - } - return h; - } - } - - override equals_t equals(in void* p1, in void* p2) - { - if (p1 == p2) - return true; - else if (!p1 || !p2) - return false; - else if (xopEquals) - return (*xopEquals)(p1, p2); - else - // BUG: relies on the GC not moving objects - return memcmp(p1, p2, init.length) == 0; - } - - override int compare(in void* p1, in void* p2) - { - // Regard null references as always being "less than" - if (p1 != p2) - { - if (p1) - { - if (!p2) - return true; - else if (xopCmp) - return (*xopCmp)(p2, p1); - else - // BUG: relies on the GC not moving objects - return memcmp(p1, p2, init.length); - } - else - return -1; - } - return 0; - } - - override size_t tsize() - { - return init.length; - } - - override void[] init() { return m_init; } - - override uint flags() { return m_flags; } - - override void destroy(void* p) - { - if (xdtor) - (*xdtor)(p); - } - - override void postblit(void* p) - { - if (xpostblit) - (*xpostblit)(p); - } - - string name; - void[] m_init; // initializer; init.ptr == null if 0 initialize - - hash_t function(in void*) xtoHash; - equals_t function(in void*, in void*) xopEquals; - int function(in void*, in void*) xopCmp; - char[] function(in void*) xtoString; - - uint m_flags; - - const(MemberInfo[]) function(in char[]) xgetMembers; - void function(void*) xdtor; - void function(void*) xpostblit; -} - -class TypeInfo_Tuple : TypeInfo -{ - TypeInfo[] elements; - - override string toString() - { - string s = "("; - foreach (i, element; elements) - { - if (i) - s ~= ','; - s ~= element.toString(); - } - s ~= ")"; - return s; - } - - override equals_t opEquals(Object o) - { - if (this is o) - return true; - - auto t = cast(TypeInfo_Tuple)o; - if (t && elements.length == t.elements.length) - { - for (size_t i = 0; i < elements.length; i++) - { - if (elements[i] != t.elements[i]) - return false; - } - return true; - } - return false; - } - - override hash_t getHash(in void* p) - { - assert(0); - } - - override equals_t equals(in void* p1, in void* p2) - { - assert(0); - } - - override int compare(in void* p1, in void* p2) - { - assert(0); - } - - override size_t tsize() - { - assert(0); - } - - override void swap(void* p1, void* p2) - { - assert(0); - } - - override void destroy(void* p) - { - assert(0); - } - - override void postblit(void* p) - { - assert(0); - } -} - -class TypeInfo_Const : TypeInfo -{ - override string toString() - { - return cast(string) ("const(" ~ base.toString() ~ ")"); - } - - override equals_t opEquals(Object o) { return base.opEquals(o); } - override hash_t getHash(in void *p) { return base.getHash(p); } - override equals_t equals(in void *p1, in void *p2) { return base.equals(p1, p2); } - override int compare(in void *p1, in void *p2) { return base.compare(p1, p2); } - override size_t tsize() { return base.tsize(); } - override void swap(void *p1, void *p2) { return base.swap(p1, p2); } - - override TypeInfo next() { return base.next(); } - override uint flags() { return base.flags(); } - override void[] init() { return base.init(); } - - TypeInfo base; -} - -class TypeInfo_Invariant : TypeInfo_Const -{ - override string toString() - { - return cast(string) ("immutable(" ~ base.toString() ~ ")"); - } -} - -class TypeInfo_Shared : TypeInfo_Const -{ - override string toString() - { - return cast(string) ("shared(" ~ base.toString() ~ ")"); - } -} - -abstract class MemberInfo -{ - string name(); -} - -class MemberInfo_field : MemberInfo -{ - this(string name, TypeInfo ti, size_t offset) - { - m_name = name; - m_typeinfo = ti; - m_offset = offset; - } - - override string name() { return m_name; } - TypeInfo typeInfo() { return m_typeinfo; } - size_t offset() { return m_offset; } - - string m_name; - TypeInfo m_typeinfo; - size_t m_offset; -} - -class MemberInfo_function : MemberInfo -{ - this(string name, TypeInfo ti, void* fp, uint flags) - { - m_name = name; - m_typeinfo = ti; - m_fp = fp; - m_flags = flags; - } - - override string name() { return m_name; } - TypeInfo typeInfo() { return m_typeinfo; } - void* fp() { return m_fp; } - uint flags() { return m_flags; } - - string m_name; - TypeInfo m_typeinfo; - void* m_fp; - uint m_flags; -} - - -/////////////////////////////////////////////////////////////////////////////// -// Throwable -/////////////////////////////////////////////////////////////////////////////// - - -class Throwable : Object -{ - interface TraceInfo - { - int opApply(int delegate(inout char[])); - } - - string msg; - string file; - size_t line; - TraceInfo info; - Throwable next; - - this(string msg, Throwable next = null) - { - this.msg = msg; - this.next = next; - this.info = traceContext(); - } - - this(string msg, string file, size_t line, Throwable next = null) - { - this(msg, next); - this.file = file; - this.line = line; - this.info = traceContext(); - } - - override string toString() - { - char[10] tmp = void; - char[] buf; - - for (Throwable e = this; e !is null; e = e.next) - { - if (e.file) - { - buf ~= e.classinfo.name ~ "@" ~ e.file ~ "(" ~ tmp.intToString(e.line) ~ "): " ~ e.msg; - } - else - { - buf ~= e.classinfo.name ~ ": " ~ e.msg; - } - if (e.info) - { - buf ~= "\n----------------"; - foreach (t; e.info) - buf ~= "\n" ~ t; - } - if (e.next) - buf ~= "\n"; - } - return cast(string) buf; - } -} - - -alias Throwable.TraceInfo function(void* ptr = null) TraceHandler; -private __gshared TraceHandler traceHandler = null; - - -/** - * Overrides the default trace hander with a user-supplied version. - * - * Params: - * h = The new trace handler. Set to null to use the default handler. - */ -extern (C) void rt_setTraceHandler(TraceHandler h) -{ - traceHandler = h; -} - - -/** - * This function will be called when an exception is constructed. The - * user-supplied trace handler will be called if one has been supplied, - * otherwise no trace will be generated. - * - * Params: - * ptr = A pointer to the location from which to generate the trace, or null - * if the trace should be generated from within the trace handler - * itself. - * - * Returns: - * An object describing the current calling context or null if no handler is - * supplied. - */ -Throwable.TraceInfo traceContext(void* ptr = null) -{ - if (traceHandler is null) - return null; - return traceHandler(ptr); -} - - -class Exception : Throwable -{ - this(string msg, Throwable next = null) - { - super(msg, next); - } - - this(string msg, string file, size_t line, Throwable next = null) - { - super(msg, file, line, next); - } -} - - -class Error : Throwable -{ - this(string msg, Throwable next = null) - { - super(msg, next); - } - - this(string msg, string file, size_t line, Throwable next = null) - { - super(msg, file, line, next); - } -} - - -/////////////////////////////////////////////////////////////////////////////// -// ModuleInfo -/////////////////////////////////////////////////////////////////////////////// - - -enum -{ - MIctorstart = 1, // we've started constructing it - MIctordone = 2, // finished construction - MIstandalone = 4, // module ctor does not depend on other module - // ctors being done first - MIhasictor = 8, // has ictor member -} - - -class ModuleInfo -{ - string name; - ModuleInfo[] importedModules; - ClassInfo[] localClasses; - uint flags; - - void function() ctor; // module static constructor (order dependent) - void function() dtor; // module static destructor - void function() unitTest; // module unit tests - - void* xgetMembers; // module getMembers() function - - void function() ictor; // module static constructor (order independent) - - void*[4] reserved; // for future expansion - - static int opApply(int delegate(inout ModuleInfo) dg) - { - int ret = 0; - - foreach (m; _moduleinfo_array) - { - ret = dg(m); - if (ret) - break; - } - return ret; - } -} - - -// Windows: this gets initialized by minit.asm -// Posix: this gets initialized in _moduleCtor() -extern (C) __gshared ModuleInfo[] _moduleinfo_array; - - -version (linux) -{ - // This linked list is created by a compiler generated function inserted - // into the .ctor list by the compiler. - struct ModuleReference - { - ModuleReference* next; - ModuleInfo mod; - } - - extern (C) __gshared ModuleReference* _Dmodule_ref; // start of linked list -} - -version (FreeBSD) -{ - // This linked list is created by a compiler generated function inserted - // into the .ctor list by the compiler. - struct ModuleReference - { - ModuleReference* next; - ModuleInfo mod; - } - - extern (C) __gshared ModuleReference* _Dmodule_ref; // start of linked list -} - -version (Solaris) -{ - // This linked list is created by a compiler generated function inserted - // into the .ctor list by the compiler. - struct ModuleReference - { - ModuleReference* next; - ModuleInfo mod; - } - - extern (C) __gshared ModuleReference* _Dmodule_ref; // start of linked list -} - -version (OSX) -{ - extern (C) - { - extern __gshared void* _minfo_beg; - extern __gshared void* _minfo_end; - } -} - -__gshared ModuleInfo[] _moduleinfo_dtors; -__gshared uint _moduleinfo_dtors_i; - -// Register termination function pointers -extern (C) int _fatexit(void*); - -/** - * Initialize the modules. - */ - -extern (C) void _moduleCtor() -{ - debug(PRINTF) printf("_moduleCtor()\n"); - version (linux) - { - int len = 0; - ModuleReference *mr; - - for (mr = _Dmodule_ref; mr; mr = mr.next) - len++; - _moduleinfo_array = new ModuleInfo[len]; - len = 0; - for (mr = _Dmodule_ref; mr; mr = mr.next) - { _moduleinfo_array[len] = mr.mod; - len++; - } - } - - version (FreeBSD) - { - int len = 0; - ModuleReference *mr; - - for (mr = _Dmodule_ref; mr; mr = mr.next) - len++; - _moduleinfo_array = new ModuleInfo[len]; - len = 0; - for (mr = _Dmodule_ref; mr; mr = mr.next) - { _moduleinfo_array[len] = mr.mod; - len++; - } - } - - version (Solaris) - { - int len = 0; - ModuleReference *mr; - - for (mr = _Dmodule_ref; mr; mr = mr.next) - len++; - _moduleinfo_array = new ModuleInfo[len]; - len = 0; - for (mr = _Dmodule_ref; mr; mr = mr.next) - { _moduleinfo_array[len] = mr.mod; - len++; - } - } - - version (OSX) - { - /* The ModuleInfo references are stored in the special segment - * __minfodata, which is bracketed by the segments __minfo_beg - * and __minfo_end. The variables _minfo_beg and _minfo_end - * are of zero size and are in the two bracketing segments, - * respectively. - */ - size_t length = cast(ModuleInfo*)&_minfo_end - cast(ModuleInfo*)&_minfo_beg; - _moduleinfo_array = (cast(ModuleInfo*)&_minfo_beg)[0 .. length]; - debug printf("moduleinfo: ptr = %p, length = %d\n", _moduleinfo_array.ptr, _moduleinfo_array.length); - - debug foreach (m; _moduleinfo_array) - { - //printf("\t%p\n", m); - printf("\t%.*s\n", m.name); - } - } - - version (Windows) - { - // Ensure module destructors also get called on program termination - //_fatexit(&_STD_moduleDtor); - } - - _moduleinfo_dtors = new ModuleInfo[_moduleinfo_array.length]; - debug(PRINTF) printf("_moduleinfo_dtors = x%x\n", cast(void*)_moduleinfo_dtors); - _moduleIndependentCtors(); - _moduleCtor2(_moduleinfo_array, 0); -} - -extern (C) void _moduleIndependentCtors() -{ - debug(PRINTF) printf("_moduleIndependentCtors()\n"); - foreach (m; _moduleinfo_array) - { - if (m && m.flags & MIhasictor && m.ictor) - { - (*m.ictor)(); - } - } -} - -void _moduleCtor2(ModuleInfo[] mi, int skip) -{ - debug(PRINTF) printf("_moduleCtor2(): %d modules\n", mi.length); - for (uint i = 0; i < mi.length; i++) - { - ModuleInfo m = mi[i]; - - debug(PRINTF) printf("\tmodule[%d] = '%p'\n", i, m); - if (!m) - continue; - debug(PRINTF) printf("\tmodule[%d] = '%.*s'\n", i, m.name); - if (m.flags & MIctordone) - continue; - debug(PRINTF) printf("\tmodule[%d] = '%.*s', m = x%x\n", i, m.name, m); - - if (m.ctor || m.dtor) - { - if (m.flags & MIctorstart) - { if (skip || m.flags & MIstandalone) - continue; - throw new Exception("Cyclic dependency in module " ~ m.name); - } - - m.flags |= MIctorstart; - _moduleCtor2(m.importedModules, 0); - if (m.ctor) - (*m.ctor)(); - m.flags &= ~MIctorstart; - m.flags |= MIctordone; - - // Now that construction is done, register the destructor - //printf("\tadding module dtor x%x\n", m); - assert(_moduleinfo_dtors_i < _moduleinfo_dtors.length); - _moduleinfo_dtors[_moduleinfo_dtors_i++] = m; - } - else - { - m.flags |= MIctordone; - _moduleCtor2(m.importedModules, 1); - } - } -} - -/** - * Destruct the modules. - */ - -// Starting the name with "_STD" means under Posix a pointer to the -// function gets put in the .dtors segment. - -extern (C) void _moduleDtor() -{ - debug(PRINTF) printf("_moduleDtor(): %d modules\n", _moduleinfo_dtors_i); - - for (uint i = _moduleinfo_dtors_i; i-- != 0;) - { - ModuleInfo m = _moduleinfo_dtors[i]; - - debug(PRINTF) printf("\tmodule[%d] = '%.*s', x%x\n", i, m.name, m); - if (m.dtor) - { - (*m.dtor)(); - } - } - debug(PRINTF) printf("_moduleDtor() done\n"); -} - -/////////////////////////////////////////////////////////////////////////////// -// Monitor -/////////////////////////////////////////////////////////////////////////////// - -alias Object.Monitor IMonitor; -alias void delegate(Object) DEvent; - -// NOTE: The dtor callback feature is only supported for monitors that are not -// supplied by the user. The assumption is that any object with a user- -// supplied monitor may have special storage or lifetime requirements and -// that as a result, storing references to local objects within Monitor -// may not be safe or desirable. Thus, devt is only valid if impl is -// null. -struct Monitor -{ - IMonitor impl; - /* internal */ - DEvent[] devt; - /* stuff */ -} - -Monitor* getMonitor(Object h) -{ - return cast(Monitor*) (cast(void**) h)[1]; -} - -void setMonitor(Object h, Monitor* m) -{ - (cast(void**) h)[1] = m; -} - -extern (C) void _d_monitor_create(Object); -extern (C) void _d_monitor_destroy(Object); -extern (C) void _d_monitor_lock(Object); -extern (C) int _d_monitor_unlock(Object); - -extern (C) void _d_monitordelete(Object h, bool det) -{ - Monitor* m = getMonitor(h); - - if (m !is null) - { - IMonitor i = m.impl; - if (i is null) - { - _d_monitor_devt(m, h); - _d_monitor_destroy(h); - setMonitor(h, null); - return; - } - if (det && (cast(void*) i) !is (cast(void*) h)) - delete i; - setMonitor(h, null); - } -} - -extern (C) void _d_monitorenter(Object h) -{ - Monitor* m = getMonitor(h); - - if (m is null) - { - _d_monitor_create(h); - m = getMonitor(h); - } - - IMonitor i = m.impl; - - if (i is null) - { - _d_monitor_lock(h); - return; - } - i.lock(); -} - -extern (C) void _d_monitorexit(Object h) -{ - Monitor* m = getMonitor(h); - IMonitor i = m.impl; - - if (i is null) - { - _d_monitor_unlock(h); - return; - } - i.unlock(); -} - -extern (C) void _d_monitor_devt(Monitor* m, Object h) -{ - if (m.devt.length) - { - DEvent[] devt; - - synchronized (h) - { - devt = m.devt; - m.devt = null; - } - foreach (v; devt) - { - if (v) - v(h); - } - free(devt.ptr); - } -} - -extern (C) void rt_attachDisposeEvent(Object h, DEvent e) -{ - synchronized (h) - { - Monitor* m = getMonitor(h); - assert(m.impl is null); - - foreach (inout v; m.devt) - { - if (v is null || v == e) - { - v = e; - return; - } - } - - auto len = m.devt.length + 4; // grow by 4 elements - auto pos = m.devt.length; // insert position - auto p = realloc(m.devt.ptr, DEvent.sizeof * len); - if (!p) - onOutOfMemoryError(); - m.devt = (cast(DEvent*)p)[0 .. len]; - m.devt[pos+1 .. len] = null; - m.devt[pos] = e; - } -} - -extern (C) void rt_detachDisposeEvent(Object h, DEvent e) -{ - synchronized (h) - { - Monitor* m = getMonitor(h); - assert(m.impl is null); - - foreach (p, v; m.devt) - { - if (v == e) - { - memmove(&m.devt[p], - &m.devt[p+1], - (m.devt.length - p - 1) * DEvent.sizeof); - m.devt[$ - 1] = null; - return; - } - } - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/posix.mak --- a/druntime/src/compiler/dmd/posix.mak Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ -# Makefile to build the compiler runtime D library for Linux -# Designed to work with GNU make -# Targets: -# make -# Same as make all -# make debug -# Build the debug version of the library -# make release -# Build the release version of the library -# make doc -# Generate documentation -# make clean -# Delete all files created by build process - -# Essentials - -LIBDIR=../../../lib -DOCDIR=../../../doc -IMPDIR=../../../import -LIBBASENAME=libdruntime-rt-dmd.a -MODULES= -BUILDS=debug release unittest - -MODULES_BASE=aaA aApply aApplyR adi alloca arrayassign arraybyte \ - arraycast arraycat arraydouble arrayfloat arrayint arrayreal \ - arrayshort cast_ cmath2 cover deh2 dmain2 invariant invariant_ \ - lifetime llmath memory memset obj object_ qsort switch_ trace -# NOTE: trace.o and cover.o are not necessary for a successful build -# as both are used for debugging features (profiling and coverage) -# NOTE: a pre-compiled minit.obj has been provided in dmd for Win32 and -# minit.asm is not used by dmd for Linux -# NOTE: deh.o is only needed for Win32, Linux uses deh2.o -MODULES_UTIL=$(addprefix util/,console cpuid ctype string utf) -MODULES_TI=$(addprefix typeinfo/ti_,AC Acdouble Acfloat Acreal Adouble \ - Afloat Ag Aint Along Areal Ashort byte C cdouble cfloat char creal \ - dchar delegate double float idouble ifloat int ireal long ptr real \ - short ubyte uint ulong ushort void wchar) -C_SRCS=complex.c critical.c memory_osx.c monitor.c - -# Symbols - -DMD=dmd -DOCFLAGS=-version=DDoc -DFLAGS_release=-d -release -O -inline -w -nofloat -DFLAGS_debug=-d -g -w -nofloat -DFLAGS_unittest=$(DFLAGS_release) -unittest -CFLAGS_release=-m32 -O -CFLAGS_debug=-m32 -g -CFLAGS_unittest=$(CFLAGS_release) - -# Derived symbols - -C_OBJS=$(addsuffix .o,$(basename $(C_SRCS))) -AS_OBJS=$(addsuffix .o,$(basename $(AS_SRCS))) -ALL_MODULES=$(MODULES_BASE) $(MODULES_UTIL) $(MODULES_TI) -D_SRCS=$(addsuffix .d,$(ALL_MODULES)) -ALLLIBS=$(addsuffix /$(LIBBASENAME),$(addprefix $(LIBDIR)/,$(BUILDS))) - -# Patterns - -$(LIBDIR)/%/$(LIBBASENAME) : $(D_SRCS) $(C_SRCS) $(AS_SRCS) - $(CC) -c $(CFLAGS_$*) $(C_SRCS) - $(DMD) $(DFLAGS_$*) -lib -of$@ $(D_SRCS) $(C_OBJS) $(AS_OBJS) - rm $(C_OBJS) $(AS_OBJS) - -$(DOCDIR)/%.html : %.d - $(DMD) -c -d -o- -Df$@ $< - -$(IMPDIR)/%.di : %.d - $(DMD) -c -d -o- -Hf$@ $< - -# Rulez - -all : $(BUILDS) doc - -debug : $(LIBDIR)/debug/$(LIBBASENAME) $(IMPORTS) -release : $(LIBDIR)/release/$(LIBBASENAME) $(IMPORTS) -unittest : $(LIBDIR)/unittest/$(LIBBASENAME) $(IMPORTS) -#doc : $(DOCS) - -clean : - rm -f $(IMPORTS) $(DOCS) $(ALLLIBS) diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/qsort.d --- a/druntime/src/compiler/dmd/qsort.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,158 +0,0 @@ -/* - Portions of this file are: - Copyright Prototronics, 1987 - Totem Lake P.O. 8117 - Kirkland, Washington 98034 - (206) 820-1972 - Licensed to Digital Mars. - - June 11, 1987 from Ray Gardner's - Denver, Colorado) public domain version - - Use qsort2.d instead of this file if a redistributable version of - _adSort() is required. -*/ - -module rt.qsort; - -/* -** Sorts an array starting at base, of length nbr_elements, each -** element of size width_bytes, ordered via compare_function; which -** is called as (*comp_fp)(ptr_to_element1, ptr_to_element2) -** and returns < 0 if element1 < element2, 0 if element1 = element2, -** > 0 if element1 > element2. Most of the refinements are due to -** R. Sedgewick. See "Implementing Quicksort Programs", Comm. ACM, -** Oct. 1978, and Corrigendum, Comm. ACM, June 1979. -*/ - -//debug=qsort; // uncomment to turn on debugging printf's - - -struct Array -{ - size_t length; - void* ptr; -} - - -private const int _maxspan = 7; // subarrays of _maxspan or fewer elements - // will be sorted by a simple insertion sort - -/* Adjust _maxspan according to relative cost of a swap and a compare. Reduce -_maxspan (not less than 1) if a swap is very expensive such as when you have -an array of large structures to be sorted, rather than an array of pointers to -structures. The default value is optimized for a high cost for compares. */ - - -extern (C) long _adSort(Array a, TypeInfo ti) -{ - byte* base; - byte*[40] stack; // stack - byte** sp; // stack pointer - byte* i, j, limit; // scan and limit pointers - uint thresh; // size of _maxspan elements in bytes - uint width = ti.tsize(); - - base = cast(byte *)a.ptr; - thresh = _maxspan * width; // init threshold - sp = stack.ptr; // init stack pointer - limit = base + a.length * width; // pointer past end of array - while (1) // repeat until done then return - { - while (limit - base > thresh) // if more than _maxspan elements - { - //swap middle, base - ti.swap((cast(uint)(limit - base) >> 1) - - (((cast(uint)(limit - base) >> 1)) % width) + base, base); - - i = base + width; // i scans from left to right - j = limit - width; // j scans from right to left - - if (ti.compare(i, j) > 0) // Sedgewick's - ti.swap(i, j); // three-element sort - if (ti.compare(base, j) > 0) // sets things up - ti.swap(base, j); // so that - if (ti.compare(i, base) > 0) // *i <= *base <= *j - ti.swap(i, base); // *base is the pivot element - - while (1) - { - do // move i right until *i >= pivot - i += width; - while (ti.compare(i, base) < 0); - do // move j left until *j <= pivot - j -= width; - while (ti.compare(j, base) > 0); - if (i > j) // break loop if pointers crossed - break; - ti.swap(i, j); // else swap elements, keep scanning - } - ti.swap(base, j); // move pivot into correct place - if (j - base > limit - i) // if left subarray is larger... - { - sp[0] = base; // stack left subarray base - sp[1] = j; // and limit - base = i; // sort the right subarray - } - else // else right subarray is larger - { - sp[0] = i; // stack right subarray base - sp[1] = limit; // and limit - limit = j; // sort the left subarray - } - sp += 2; // increment stack pointer - assert(sp < cast(byte**)stack + stack.length); - } - - // Insertion sort on remaining subarray - i = base + width; - while (i < limit) - { - j = i; - while (j > base && ti.compare(j - width, j) > 0) - { - ti.swap(j - width, j); - j -= width; - } - i += width; - } - - if (sp > stack.ptr) // if any entries on stack... - { - sp -= 2; // pop the base and limit - base = sp[0]; - limit = sp[1]; - } - else // else stack empty, all done - return *cast(long*)(&a); - } - assert(0); -} - - -unittest -{ - debug(qsort) printf("array.sort.unittest()\n"); - - int a[] = new int[10]; - - a[0] = 23; - a[1] = 1; - a[2] = 64; - a[3] = 5; - a[4] = 6; - a[5] = 5; - a[6] = 17; - a[7] = 3; - a[8] = 0; - a[9] = -1; - - a.sort; - - for (int i = 0; i < a.length - 1; i++) - { - //printf("i = %d", i); - //printf(" %d %d\n", a[i], a[i + 1]); - assert(a[i] <= a[i + 1]); - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/qsort2.d --- a/druntime/src/compiler/dmd/qsort2.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -/** - * This is a public domain version of qsort.d. All it does is call C's - * qsort(), but runs a little slower since it needs to synchronize a global - * variable. - * - * Copyright: Copyright Digital Mars 2000 - 2009. - * License: = 0); - assert(ca.length >= 0); - - // Make sure table[] is sorted correctly - int j; - - for (j = 1; j < table.length; j++) - { - int len1 = table[j - 1].length; - int len2 = table[j].length; - - assert(len1 <= len2); - if (len1 == len2) - { - int ci; - - ci = memcmp(table[j - 1].ptr, table[j].ptr, len1); - assert(ci < 0); // ci==0 means a duplicate - } - } -} -out (result) -{ - int i; - int cj; - - //printf("out _d_switch_string()\n"); - if (result == -1) - { - // Not found - for (i = 0; i < table.length; i++) - { - if (table[i].length == ca.length) - { cj = memcmp(table[i].ptr, ca.ptr, ca.length); - assert(cj != 0); - } - } - } - else - { - assert(0 <= result && result < table.length); - for (i = 0; 1; i++) - { - assert(i < table.length); - if (table[i].length == ca.length) - { - cj = memcmp(table[i].ptr, ca.ptr, ca.length); - if (cj == 0) - { - assert(i == result); - break; - } - } - } - } -} -body -{ - //printf("body _d_switch_string(%.*s)\n", ca); - int low; - int high; - int mid; - int c; - char[] pca; - - low = 0; - high = table.length; - - version (none) - { - // Print table - printf("ca[] = '%s'\n", cast(char *)ca); - for (mid = 0; mid < high; mid++) - { - pca = table[mid]; - printf("table[%d] = %d, '%.*s'\n", mid, pca.length, pca); - } - } - if (high && - ca.length >= table[0].length && - ca.length <= table[high - 1].length) - { - // Looking for 0 length string, which would only be at the beginning - if (ca.length == 0) - return 0; - - char c1 = ca[0]; - - // Do binary search - while (low < high) - { - mid = (low + high) >> 1; - pca = table[mid]; - c = ca.length - pca.length; - if (c == 0) - { - c = cast(ubyte)c1 - cast(ubyte)pca[0]; - if (c == 0) - { - c = memcmp(ca.ptr, pca.ptr, ca.length); - if (c == 0) - { //printf("found %d\n", mid); - return mid; - } - } - } - if (c < 0) - { - high = mid; - } - else - { - low = mid + 1; - } - } - } - - //printf("not found\n"); - return -1; // not found -} - -unittest -{ - switch (cast(char []) "c") - { - case "coo": - default: - break; - } -} - -/********************************** - * Same thing, but for wide chars. - */ - -int _d_switch_ustring(wchar[][] table, wchar[] ca) -in -{ - //printf("in _d_switch_ustring()\n"); - assert(table.length >= 0); - assert(ca.length >= 0); - - // Make sure table[] is sorted correctly - int j; - - for (j = 1; j < table.length; j++) - { - int len1 = table[j - 1].length; - int len2 = table[j].length; - - assert(len1 <= len2); - if (len1 == len2) - { - int c; - - c = memcmp(table[j - 1].ptr, table[j].ptr, len1 * wchar.sizeof); - assert(c < 0); // c==0 means a duplicate - } - } -} -out (result) -{ - int i; - int c; - - //printf("out _d_switch_string()\n"); - if (result == -1) - { - // Not found - for (i = 0; i < table.length; i++) - { - if (table[i].length == ca.length) - { c = memcmp(table[i].ptr, ca.ptr, ca.length * wchar.sizeof); - assert(c != 0); - } - } - } - else - { - assert(0 <= result && result < table.length); - for (i = 0; 1; i++) - { - assert(i < table.length); - if (table[i].length == ca.length) - { - c = memcmp(table[i].ptr, ca.ptr, ca.length * wchar.sizeof); - if (c == 0) - { - assert(i == result); - break; - } - } - } - } -} -body -{ - //printf("body _d_switch_ustring()\n"); - int low; - int high; - int mid; - int c; - wchar[] pca; - - low = 0; - high = table.length; - -/* - // Print table - wprintf("ca[] = '%.*s'\n", ca); - for (mid = 0; mid < high; mid++) - { - pca = table[mid]; - wprintf("table[%d] = %d, '%.*s'\n", mid, pca.length, pca); - } -*/ - - // Do binary search - while (low < high) - { - mid = (low + high) >> 1; - pca = table[mid]; - c = ca.length - pca.length; - if (c == 0) - { - c = memcmp(ca.ptr, pca.ptr, ca.length * wchar.sizeof); - if (c == 0) - { //printf("found %d\n", mid); - return mid; - } - } - if (c < 0) - { - high = mid; - } - else - { - low = mid + 1; - } - } - //printf("not found\n"); - return -1; // not found -} - - -unittest -{ - switch (cast(wchar []) "c") - { - case "coo": - default: - break; - } -} - - -/********************************** - * Same thing, but for wide chars. - */ - -int _d_switch_dstring(dchar[][] table, dchar[] ca) -in -{ - //printf("in _d_switch_dstring()\n"); - assert(table.length >= 0); - assert(ca.length >= 0); - - // Make sure table[] is sorted correctly - int j; - - for (j = 1; j < table.length; j++) - { - int len1 = table[j - 1].length; - int len2 = table[j].length; - - assert(len1 <= len2); - if (len1 == len2) - { - int c; - - c = memcmp(table[j - 1].ptr, table[j].ptr, len1 * dchar.sizeof); - assert(c < 0); // c==0 means a duplicate - } - } -} -out (result) -{ - int i; - int c; - - //printf("out _d_switch_string()\n"); - if (result == -1) - { - // Not found - for (i = 0; i < table.length; i++) - { - if (table[i].length == ca.length) - { c = memcmp(table[i].ptr, ca.ptr, ca.length * dchar.sizeof); - assert(c != 0); - } - } - } - else - { - assert(0 <= result && result < table.length); - for (i = 0; 1; i++) - { - assert(i < table.length); - if (table[i].length == ca.length) - { - c = memcmp(table[i].ptr, ca.ptr, ca.length * dchar.sizeof); - if (c == 0) - { - assert(i == result); - break; - } - } - } - } -} -body -{ - //printf("body _d_switch_ustring()\n"); - int low; - int high; - int mid; - int c; - dchar[] pca; - - low = 0; - high = table.length; - -/* - // Print table - wprintf("ca[] = '%.*s'\n", ca); - for (mid = 0; mid < high; mid++) - { - pca = table[mid]; - wprintf("table[%d] = %d, '%.*s'\n", mid, pca.length, pca); - } -*/ - - // Do binary search - while (low < high) - { - mid = (low + high) >> 1; - pca = table[mid]; - c = ca.length - pca.length; - if (c == 0) - { - c = memcmp(ca.ptr, pca.ptr, ca.length * dchar.sizeof); - if (c == 0) - { //printf("found %d\n", mid); - return mid; - } - } - if (c < 0) - { - high = mid; - } - else - { - low = mid + 1; - } - } - //printf("not found\n"); - return -1; // not found -} - - -unittest -{ - switch (cast(dchar []) "c") - { - case "coo": - default: - break; - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/tls.S --- a/druntime/src/compiler/dmd/tls.S Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -/** - * Contains support code for thread-local storage. - * - * Copyright: Copyright Digital Mars 2008 - 2009. - * License: = count) - { uint u2; - uint c2; - - u2 = (u + 1 < num) ? u + 1 : u; - c2 = base[u2].count; - if (c2 < count) - c2 = count; - trace_place(base[u].sym,c2); - } - else - break; - } - - // Clean up - trace_free(base); - } -} - -///////////////////////////////////// -// Initialize and terminate. - -static this() -{ - trace_init(); -} - -static ~this() -{ - trace_term(); -} - -/////////////////////////////////// -// Report results. -// Also compute nsymbols. - -static void trace_report(Symbol* s) -{ SymPair* sp; - uint count; - - //printf("trace_report()\n"); - while (s) - { nsymbols++; - if (s.Sl) - trace_report(s.Sl); - fprintf(fplog,"------------------\n"); - count = 0; - for (sp = s.Sfanin; sp; sp = sp.next) - { - fprintf(fplog,"\t%5d\t%.*s\n", sp.count, sp.sym.Sident); - count += sp.count; - } - fprintf(fplog,"%.*s\t%u\t%lld\t%lld\n",s.Sident,count,s.totaltime,s.functime); - for (sp = s.Sfanout; sp; sp = sp.next) - { - fprintf(fplog,"\t%5d\t%.*s\n",sp.count,sp.sym.Sident); - } - s = s.Sr; - } -} - -//////////////////////////////////// -// Allocate and fill array of symbols. - -static void trace_array(Symbol *s) -{ - __gshared uint u; - - if (!psymbols) - { u = 0; - psymbols = cast(Symbol **)trace_malloc((Symbol *).sizeof * nsymbols); - } - while (s) - { - psymbols[u++] = s; - trace_array(s.Sl); - s = s.Sr; - } -} - - -////////////////////////////////////// -// Qsort() comparison routine for array of pointers to Symbol's. - -static int symbol_cmp(in void* e1, in void* e2) -{ Symbol** ps1; - Symbol** ps2; - timer_t diff; - - ps1 = cast(Symbol **)e1; - ps2 = cast(Symbol **)e2; - - diff = (*ps2).functime - (*ps1).functime; - return (diff == 0) ? 0 : ((diff > 0) ? 1 : -1); -} - - -/////////////////////////////////// -// Report function timings - -static void trace_times(Symbol* root) -{ uint u; - timer_t freq; - - // Sort array - qsort(psymbols, nsymbols, (Symbol *).sizeof, &symbol_cmp); - - // Print array - QueryPerformanceFrequency(&freq); - fprintf(fplog,"\n======== Timer Is %lld Ticks/Sec, Times are in Microsecs ========\n\n",freq); - fprintf(fplog," Num Tree Func Per\n"); - fprintf(fplog," Calls Time Time Call\n\n"); - for (u = 0; u < nsymbols; u++) - { Symbol* s = psymbols[u]; - timer_t tl,tr; - timer_t fl,fr; - timer_t pl,pr; - timer_t percall; - SymPair* sp; - uint calls; - char[] id; - - version (Windows) - { - char* p = (s.Sident ~ '\0').ptr; - p = unmangle_ident(p); - if (p) - id = p[0 .. strlen(p)]; - } - if (!id) - id = s.Sident; - calls = 0; - for (sp = s.Sfanin; sp; sp = sp.next) - calls += sp.count; - if (calls == 0) - calls = 1; - -version (all) -{ - tl = (s.totaltime * 1000000) / freq; - fl = (s.functime * 1000000) / freq; - percall = s.functime / calls; - pl = (s.functime * 1000000) / calls / freq; - - fprintf(fplog,"%7d%12lld%12lld%12lld %.*s\n", - calls,tl,fl,pl,id); -} -else -{ - tl = s.totaltime / freq; - tr = ((s.totaltime - tl * freq) * 10000000) / freq; - - fl = s.functime / freq; - fr = ((s.functime - fl * freq) * 10000000) / freq; - - percall = s.functime / calls; - pl = percall / freq; - pr = ((percall - pl * freq) * 10000000) / freq; - - fprintf(fplog,"%7d\t%3lld.%07lld\t%3lld.%07lld\t%3lld.%07lld\t%.*s\n", - calls,tl,tr,fl,fr,pl,pr,id); -} - if (id !is s.Sident) - free(id.ptr); - } -} - - -/////////////////////////////////// -// Initialize. - -static void trace_init() -{ - if (!trace_inited) - { - trace_inited = 1; - - { // See if we can determine the overhead. - uint u; - timer_t starttime; - timer_t endtime; - Stack *st; - - st = trace_tos; - trace_tos = null; - QueryPerformanceCounter(&starttime); - for (u = 0; u < 100; u++) - { - asm - { - call _trace_pro_n ; - db 0 ; - call _trace_epi_n ; - } - } - QueryPerformanceCounter(&endtime); - trace_ohd = (endtime - starttime) / u; - //printf("trace_ohd = %lld\n",trace_ohd); - if (trace_ohd > 0) - trace_ohd--; // round down - trace_tos = st; - } - } -} - -///////////////////////////////// -// Terminate. - -void trace_term() -{ - //printf("trace_term()\n"); - if (trace_inited == 1) - { Stack *n; - - trace_inited = 2; - - // Free remainder of the stack - while (trace_tos) - { - n = trace_tos.prev; - stack_free(trace_tos); - trace_tos = n; - } - - while (stack_freelist) - { - n = stack_freelist.prev; - stack_free(stack_freelist); - stack_freelist = n; - } - - // Merge in data from any existing file - trace_merge(); - - // Report results - fplog = fopen(trace_logfilename.ptr, "w"); - if (fplog) - { nsymbols = 0; - trace_report(root); - trace_array(root); - trace_times(root); - fclose(fplog); - } - - // Output function link order - fpdef = fopen(trace_deffilename.ptr,"w"); - if (fpdef) - { fprintf(fpdef,"\nFUNCTIONS\n"); - trace_order(root); - fclose(fpdef); - } - - trace_free(psymbols); - psymbols = null; - } -} - -///////////////////////////////// -// Our storage allocator. - -static void *trace_malloc(size_t nbytes) -{ void *p; - - p = malloc(nbytes); - if (!p) - exit(EXIT_FAILURE); - return p; -} - -static void trace_free(void *p) -{ - free(p); -} - -////////////////////////////////////////////// -// - -static Symbol* trace_addsym(char[] id) -{ - Symbol** parent; - Symbol* rover; - Symbol* s; - int cmp; - char c; - - //printf("trace_addsym('%s',%d)\n",p,len); - parent = &root; - rover = *parent; - while (rover !is null) // while we haven't run out of tree - { - cmp = dstrcmp(id, rover.Sident); - if (cmp == 0) - { - return rover; - } - parent = (cmp < 0) ? /* if we go down left side */ - &(rover.Sl) : /* then get left child */ - &(rover.Sr); /* else get right child */ - rover = *parent; /* get child */ - } - /* not in table, so insert into table */ - s = cast(Symbol *)trace_malloc(Symbol.sizeof); - memset(s,0,Symbol.sizeof); - s.Sident = id; - *parent = s; // link new symbol into tree - return s; -} - -/*********************************** - * Add symbol s with count to SymPair list. - */ - -static void trace_sympair_add(SymPair** psp, Symbol* s, uint count) -{ SymPair* sp; - - for (; 1; psp = &sp.next) - { - sp = *psp; - if (!sp) - { - sp = cast(SymPair *)trace_malloc(SymPair.sizeof); - sp.sym = s; - sp.count = 0; - sp.next = null; - *psp = sp; - break; - } - else if (sp.sym == s) - { - break; - } - } - sp.count += count; -} - -////////////////////////////////////////////// -// - -static void trace_pro(char[] id) -{ - Stack* n; - Symbol* s; - timer_t starttime; - timer_t t; - - QueryPerformanceCounter(&starttime); - if (id.length == 0) - return; - if (!trace_inited) - trace_init(); // initialize package - n = stack_malloc(); - n.prev = trace_tos; - trace_tos = n; - s = trace_addsym(id); - trace_tos.sym = s; - if (trace_tos.prev) - { - Symbol* prev; - int i; - - // Accumulate Sfanout and Sfanin - prev = trace_tos.prev.sym; - trace_sympair_add(&prev.Sfanout,s,1); - trace_sympair_add(&s.Sfanin,prev,1); - } - QueryPerformanceCounter(&t); - trace_tos.starttime = starttime; - trace_tos.ohd = trace_ohd + t - starttime; - trace_tos.subtime = 0; - //printf("trace_tos.ohd=%lld, trace_ohd=%lld + t=%lld - starttime=%lld\n", - // trace_tos.ohd,trace_ohd,t,starttime); -} - -///////////////////////////////////////// -// - -static void trace_epi() -{ Stack* n; - timer_t endtime; - timer_t t; - timer_t ohd; - - //printf("trace_epi()\n"); - if (trace_tos) - { - timer_t starttime; - timer_t totaltime; - - QueryPerformanceCounter(&endtime); - starttime = trace_tos.starttime; - totaltime = endtime - starttime - trace_tos.ohd; - if (totaltime < 0) - { //printf("endtime=%lld - starttime=%lld - trace_tos.ohd=%lld < 0\n", - // endtime,starttime,trace_tos.ohd); - totaltime = 0; // round off error, just make it 0 - } - - // totaltime is time spent in this function + all time spent in - // subfunctions - bookkeeping overhead. - trace_tos.sym.totaltime += totaltime; - - //if (totaltime < trace_tos.subtime) - //printf("totaltime=%lld < trace_tos.subtime=%lld\n",totaltime,trace_tos.subtime); - trace_tos.sym.functime += totaltime - trace_tos.subtime; - ohd = trace_tos.ohd; - n = trace_tos.prev; - stack_free(trace_tos); - trace_tos = n; - if (n) - { QueryPerformanceCounter(&t); - n.ohd += ohd + t - endtime; - n.subtime += totaltime; - //printf("n.ohd = %lld\n",n.ohd); - } - } -} - - -////////////////////////// FILE INTERFACE ///////////////////////// - -///////////////////////////////////// -// Read line from file fp. -// Returns: -// trace_malloc'd line buffer -// null if end of file - -static char* trace_readline(FILE* fp) -{ int c; - int dim; - int i; - char *buf; - - //printf("trace_readline(%p)\n", fp); - i = 0; - dim = 0; - buf = null; - while (1) - { - if (i == dim) - { char *p; - - dim += 80; - p = cast(char *)trace_malloc(dim); - memcpy(p,buf,i); - trace_free(buf); - buf = p; - } - c = fgetc(fp); - switch (c) - { - case EOF: - if (i == 0) - { trace_free(buf); - return null; - } - case '\n': - goto L1; - default: - break; - } - buf[i] = cast(char)c; - i++; - } -L1: - buf[i] = 0; - //printf("line '%s'\n",buf); - return buf; -} - -////////////////////////////////////// -// Skip space - -static char *skipspace(char *p) -{ - while (isspace(*p)) - p++; - return p; -} - -//////////////////////////////////////////////////////// -// Merge in profiling data from existing file. - -static void trace_merge() -{ FILE *fp; - char *buf; - char *p; - uint count; - Symbol *s; - SymPair *sfanin; - SymPair **psp; - - if (trace_logfilename && (fp = fopen(trace_logfilename.ptr,"r")) !is null) - { - buf = null; - sfanin = null; - psp = &sfanin; - while (1) - { - trace_free(buf); - buf = trace_readline(fp); - if (!buf) - break; - switch (*buf) - { - case '=': // ignore rest of file - trace_free(buf); - goto L1; - case ' ': - case '\t': // fan in or fan out line - count = strtoul(buf,&p,10); - if (p == buf) // if invalid conversion - continue; - p = skipspace(p); - if (!*p) - continue; - s = trace_addsym(p[0 .. strlen(p)]); - trace_sympair_add(psp,s,count); - break; - default: - if (!isalpha(*buf)) - { - if (!sfanin) - psp = &sfanin; - continue; // regard unrecognized line as separator - } - case '?': - case '_': - case '$': - case '@': - p = buf; - while (isgraph(*p)) - p++; - *p = 0; - //printf("trace_addsym('%s')\n",buf); - s = trace_addsym(buf[0 .. strlen(buf)]); - if (s.Sfanin) - { SymPair *sp; - - for (; sfanin; sfanin = sp) - { - trace_sympair_add(&s.Sfanin,sfanin.sym,sfanin.count); - sp = sfanin.next; - trace_free(sfanin); - } - } - else - { s.Sfanin = sfanin; - } - sfanin = null; - psp = &s.Sfanout; - - { timer_t t; - - p++; - count = strtoul(p,&p,10); - t = cast(long)strtoull(p,&p,10); - s.totaltime += t; - t = cast(long)strtoull(p,&p,10); - s.functime += t; - } - break; - } - } - L1: - fclose(fp); - } -} - -////////////////////////// COMPILER INTERFACE ///////////////////// - -///////////////////////////////////////////// -// Function called by trace code in function prolog. - -void _trace_pro_n() -{ - /* Length of string is either: - * db length - * ascii string - * or: - * db 0x0FF - * db 0 - * dw length - * ascii string - */ - - version (OSX) - { // 16 byte align stack - asm - { naked ; - pushad ; - mov ECX,8*4[ESP] ; - xor EAX,EAX ; - mov AL,[ECX] ; - cmp AL,0xFF ; - jne L1 ; - cmp byte ptr 1[ECX],0 ; - jne L1 ; - mov AX,2[ECX] ; - add 8*4[ESP],3 ; - add ECX,3 ; - L1: inc EAX ; - inc ECX ; - add 8*4[ESP],EAX ; - dec EAX ; - sub ESP,4 ; - push ECX ; - push EAX ; - call trace_pro ; - add ESP,12 ; - popad ; - ret ; - } - } - else - { - asm - { naked ; - pushad ; - mov ECX,8*4[ESP] ; - xor EAX,EAX ; - mov AL,[ECX] ; - cmp AL,0xFF ; - jne L1 ; - cmp byte ptr 1[ECX],0 ; - jne L1 ; - mov AX,2[ECX] ; - add 8*4[ESP],3 ; - add ECX,3 ; - L1: inc EAX ; - inc ECX ; - add 8*4[ESP],EAX ; - dec EAX ; - push ECX ; - push EAX ; - call trace_pro ; - add ESP,8 ; - popad ; - ret ; - } - } -} - -///////////////////////////////////////////// -// Function called by trace code in function epilog. - - -void _trace_epi_n() -{ - version (OSX) - { // 16 byte align stack - asm - { naked ; - pushad ; - sub ESP,12 ; - } - trace_epi(); - asm - { - add ESP,12 ; - popad ; - ret ; - } - } - else - { - asm - { naked ; - pushad ; - } - trace_epi(); - asm - { - popad ; - ret ; - } - } -} - - -version (Windows) -{ - extern (Windows) - { - export int QueryPerformanceCounter(timer_t *); - export int QueryPerformanceFrequency(timer_t *); - } -} -else version (X86) -{ - extern (D) - { - void QueryPerformanceCounter(timer_t* ctr) - { - asm - { naked ; - mov ECX,EAX ; - rdtsc ; - mov [ECX],EAX ; - mov 4[ECX],EDX ; - ret ; - } - } - - void QueryPerformanceFrequency(timer_t* freq) - { - *freq = 3579545; - } - } -} -else -{ - static assert(0); -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/typeinfo/ti_AC.d --- a/druntime/src/compiler/dmd/typeinfo/ti_AC.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,107 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: 0) - c = 1; - return c; - } - - override size_t tsize() - { - return (Object[]).sizeof; - } - - override uint flags() - { - return 1; - } - - override TypeInfo next() - { - return typeid(Object); - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/typeinfo/ti_Acdouble.d --- a/druntime/src/compiler/dmd/typeinfo/ti_Acdouble.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,94 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: s2.length) - return 1; - return 0; - } - - override size_t tsize() - { - return (cdouble[]).sizeof; - } - - override uint flags() - { - return 1; - } - - override TypeInfo next() - { - return typeid(cdouble); - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/typeinfo/ti_Acfloat.d --- a/druntime/src/compiler/dmd/typeinfo/ti_Acfloat.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,92 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: s2.length) - return 1; - return 0; - } - - override size_t tsize() - { - return (cfloat[]).sizeof; - } - - override uint flags() - { - return 1; - } - - override TypeInfo next() - { - return typeid(cfloat); - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/typeinfo/ti_Acreal.d --- a/druntime/src/compiler/dmd/typeinfo/ti_Acreal.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,95 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: s2.length) - return 1; - return 0; - } - - override size_t tsize() - { - return (creal[]).sizeof; - } - - override uint flags() - { - return 1; - } - - override TypeInfo next() - { - return typeid(creal); - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/typeinfo/ti_Adouble.d --- a/druntime/src/compiler/dmd/typeinfo/ti_Adouble.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,104 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: s2.length) - return 1; - return 0; - } - - override size_t tsize() - { - return (double[]).sizeof; - } - - override uint flags() - { - return 1; - } - - override TypeInfo next() - { - return typeid(double); - } -} - -// idouble[] - -class TypeInfo_Ap : TypeInfo_Ad -{ - override string toString() { return "idouble[]"; } - - override TypeInfo next() - { - return typeid(idouble); - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/typeinfo/ti_Afloat.d --- a/druntime/src/compiler/dmd/typeinfo/ti_Afloat.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: s2.length) - return 1; - return 0; - } - - override size_t tsize() - { - return (float[]).sizeof; - } - - override uint flags() - { - return 1; - } - - override TypeInfo next() - { - return typeid(float); - } -} - -// ifloat[] - -class TypeInfo_Ao : TypeInfo_Af -{ - override string toString() { return "ifloat[]"; } - - override TypeInfo next() - { - return typeid(ifloat); - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/typeinfo/ti_Ag.d --- a/druntime/src/compiler/dmd/typeinfo/ti_Ag.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,228 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: s2.length) - return 1; - return 0; - } - - override size_t tsize() - { - return (byte[]).sizeof; - } - - override uint flags() - { - return 1; - } - - override TypeInfo next() - { - return typeid(byte); - } -} - - -// ubyte[] - -class TypeInfo_Ah : TypeInfo_Ag -{ - override string toString() { return "ubyte[]"; } - - override int compare(in void* p1, in void* p2) - { - char[] s1 = *cast(char[]*)p1; - char[] s2 = *cast(char[]*)p2; - - return dstrcmp(s1, s2); - } - - override TypeInfo next() - { - return typeid(ubyte); - } -} - -// void[] - -class TypeInfo_Av : TypeInfo_Ah -{ - override string toString() { return "void[]"; } - - override TypeInfo next() - { - return typeid(void); - } -} - -// bool[] - -class TypeInfo_Ab : TypeInfo_Ah -{ - override string toString() { return "bool[]"; } - - override TypeInfo next() - { - return typeid(bool); - } -} - -// char[] - -class TypeInfo_Aa : TypeInfo_Ag -{ - override string toString() { return "char[]"; } - - override hash_t getHash(in void* p) - { char[] s = *cast(char[]*)p; - hash_t hash = 0; - -version (all) -{ - foreach (char c; s) - hash = hash * 11 + c; -} -else -{ - size_t len = s.length; - char *str = s; - - while (1) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash *= 9; - hash += *cast(ubyte *)str; - return hash; - - case 2: - hash *= 9; - hash += *cast(ushort *)str; - return hash; - - case 3: - hash *= 9; - hash += (*cast(ushort *)str << 8) + - (cast(ubyte *)str)[2]; - return hash; - - default: - hash *= 9; - hash += *cast(uint *)str; - str += 4; - len -= 4; - break; - } - } -} - return hash; - } - - override TypeInfo next() - { - return typeid(char); - } -} - -// string - -class TypeInfo_Aya : TypeInfo_Aa -{ - override string toString() { return "immutable(char)[]"; } - - override TypeInfo next() - { - return typeid(immutable(char)); - } -} - diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/typeinfo/ti_Aint.d --- a/druntime/src/compiler/dmd/typeinfo/ti_Aint.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,140 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: s2.length) - return 1; - return 0; - } - - override size_t tsize() - { - return (int[]).sizeof; - } - - override uint flags() - { - return 1; - } - - override TypeInfo next() - { - return typeid(int); - } -} - -unittest -{ - int[][] a = [[5,3,8,7], [2,5,3,8,7]]; - a.sort; - assert(a == [[2,5,3,8,7], [5,3,8,7]]); - - a = [[5,3,8,7], [5,3,8]]; - a.sort; - assert(a == [[5,3,8], [5,3,8,7]]); -} - -// uint[] - -class TypeInfo_Ak : TypeInfo_Ai -{ - override string toString() { return "uint[]"; } - - override int compare(in void* p1, in void* p2) - { - uint[] s1 = *cast(uint[]*)p1; - uint[] s2 = *cast(uint[]*)p2; - size_t len = s1.length; - - if (s2.length < len) - len = s2.length; - for (size_t u = 0; u < len; u++) - { - int result = s1[u] - s2[u]; - if (result) - return result; - } - if (s1.length < s2.length) - return -1; - else if (s1.length > s2.length) - return 1; - return 0; - } - - override TypeInfo next() - { - return typeid(uint); - } -} - -// dchar[] - -class TypeInfo_Aw : TypeInfo_Ak -{ - override string toString() { return "dchar[]"; } - - override TypeInfo next() - { - return typeid(dchar); - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/typeinfo/ti_Along.d --- a/druntime/src/compiler/dmd/typeinfo/ti_Along.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,120 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: s2[u]) - return 1; - } - if (s1.length < s2.length) - return -1; - else if (s1.length > s2.length) - return 1; - return 0; - } - - override size_t tsize() - { - return (long[]).sizeof; - } - - override uint flags() - { - return 1; - } - - override TypeInfo next() - { - return typeid(long); - } -} - - -// ulong[] - -class TypeInfo_Am : TypeInfo_Al -{ - override string toString() { return "ulong[]"; } - - override int compare(in void* p1, in void* p2) - { - ulong[] s1 = *cast(ulong[]*)p1; - ulong[] s2 = *cast(ulong[]*)p2; - size_t len = s1.length; - - if (s2.length < len) - len = s2.length; - for (size_t u = 0; u < len; u++) - { - if (s1[u] < s2[u]) - return -1; - else if (s1[u] > s2[u]) - return 1; - } - if (s1.length < s2.length) - return -1; - else if (s1.length > s2.length) - return 1; - return 0; - } - - override TypeInfo next() - { - return typeid(ulong); - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/typeinfo/ti_Areal.d --- a/druntime/src/compiler/dmd/typeinfo/ti_Areal.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,105 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: s2.length) - return 1; - return 0; - } - - override size_t tsize() - { - return (real[]).sizeof; - } - - override uint flags() - { - return 1; - } - - override TypeInfo next() - { - return typeid(real); - } -} - -// ireal[] - -class TypeInfo_Aj : TypeInfo_Ae -{ - override string toString() { return "ireal[]"; } - - override TypeInfo next() - { - return typeid(ireal); - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/typeinfo/ti_Ashort.d --- a/druntime/src/compiler/dmd/typeinfo/ti_Ashort.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,143 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: s2.length) - return 1; - return 0; - } - - override size_t tsize() - { - return (short[]).sizeof; - } - - override uint flags() - { - return 1; - } - - override TypeInfo next() - { - return typeid(short); - } -} - - -// ushort[] - -class TypeInfo_At : TypeInfo_As -{ - override string toString() { return "ushort[]"; } - - override int compare(in void* p1, in void* p2) - { - ushort[] s1 = *cast(ushort[]*)p1; - ushort[] s2 = *cast(ushort[]*)p2; - size_t len = s1.length; - - if (s2.length < len) - len = s2.length; - for (size_t u = 0; u < len; u++) - { - int result = s1[u] - s2[u]; - if (result) - return result; - } - if (s1.length < s2.length) - return -1; - else if (s1.length > s2.length) - return 1; - return 0; - } - - override TypeInfo next() - { - return typeid(ushort); - } -} - -// wchar[] - -class TypeInfo_Au : TypeInfo_At -{ - override string toString() { return "wchar[]"; } - - override TypeInfo next() - { - return typeid(wchar); - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/typeinfo/ti_C.d --- a/druntime/src/compiler/dmd/typeinfo/ti_C.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: f2.re) - result = 1; - else if (f1.im < f2.im) - result = -1; - else if (f1.im > f2.im) - result = 1; - else - result = 0; - return result; - } - - override equals_t equals(in void* p1, in void* p2) - { - return _equals(*cast(cdouble *)p1, *cast(cdouble *)p2); - } - - override int compare(in void* p1, in void* p2) - { - return _compare(*cast(cdouble *)p1, *cast(cdouble *)p2); - } - - override size_t tsize() - { - return cdouble.sizeof; - } - - override void swap(void *p1, void *p2) - { - cdouble t; - - t = *cast(cdouble *)p1; - *cast(cdouble *)p1 = *cast(cdouble *)p2; - *cast(cdouble *)p2 = t; - } - - override void[] init() - { static immutable cdouble r; - - return (cast(cdouble *)&r)[0 .. 1]; - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/typeinfo/ti_cfloat.d --- a/druntime/src/compiler/dmd/typeinfo/ti_cfloat.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,76 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: f2.re) - result = 1; - else if (f1.im < f2.im) - result = -1; - else if (f1.im > f2.im) - result = 1; - else - result = 0; - return result; - } - - override equals_t equals(in void* p1, in void* p2) - { - return _equals(*cast(cfloat *)p1, *cast(cfloat *)p2); - } - - override int compare(in void* p1, in void* p2) - { - return _compare(*cast(cfloat *)p1, *cast(cfloat *)p2); - } - - override size_t tsize() - { - return cfloat.sizeof; - } - - override void swap(void *p1, void *p2) - { - cfloat t; - - t = *cast(cfloat *)p1; - *cast(cfloat *)p1 = *cast(cfloat *)p2; - *cast(cfloat *)p2 = t; - } - - override void[] init() - { static immutable cfloat r; - - return (cast(cfloat *)&r)[0 .. 1]; - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/typeinfo/ti_char.d --- a/druntime/src/compiler/dmd/typeinfo/ti_char.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: f2.re) - result = 1; - else if (f1.im < f2.im) - result = -1; - else if (f1.im > f2.im) - result = 1; - else - result = 0; - return result; - } - - override equals_t equals(in void* p1, in void* p2) - { - return _equals(*cast(creal *)p1, *cast(creal *)p2); - } - - override int compare(in void* p1, in void* p2) - { - return _compare(*cast(creal *)p1, *cast(creal *)p2); - } - - override size_t tsize() - { - return creal.sizeof; - } - - override void swap(void *p1, void *p2) - { - creal t; - - t = *cast(creal *)p1; - *cast(creal *)p1 = *cast(creal *)p2; - *cast(creal *)p2 = t; - } - - override void[] init() - { static immutable creal r; - - return (cast(creal *)&r)[0 .. 1]; - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/typeinfo/ti_dchar.d --- a/druntime/src/compiler/dmd/typeinfo/ti_dchar.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: Boost License 1.0. - * Authors: Walter Bright - * - * Copyright Digital Mars 2004 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module rt.typeinfo.ti_double; - -// double - -class TypeInfo_d : TypeInfo -{ - override string toString() { return "double"; } - - override hash_t getHash(in void* p) - { - return (cast(uint *)p)[0] + (cast(uint *)p)[1]; - } - - static equals_t _equals(double f1, double f2) - { - return f1 == f2 || - (f1 !<>= f1 && f2 !<>= f2); - } - - static int _compare(double d1, double d2) - { - if (d1 !<>= d2) // if either are NaN - { - if (d1 !<>= d1) - { if (d2 !<>= d2) - return 0; - return -1; - } - return 1; - } - return (d1 == d2) ? 0 : ((d1 < d2) ? -1 : 1); - } - - override equals_t equals(in void* p1, in void* p2) - { - return _equals(*cast(double *)p1, *cast(double *)p2); - } - - override int compare(in void* p1, in void* p2) - { - return _compare(*cast(double *)p1, *cast(double *)p2); - } - - override size_t tsize() - { - return double.sizeof; - } - - override void swap(void *p1, void *p2) - { - double t; - - t = *cast(double *)p1; - *cast(double *)p1 = *cast(double *)p2; - *cast(double *)p2 = t; - } - - override void[] init() - { static immutable double r; - - return (cast(double *)&r)[0 .. 1]; - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/typeinfo/ti_float.d --- a/druntime/src/compiler/dmd/typeinfo/ti_float.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: = f1 && f2 !<>= f2); - } - - static int _compare(float d1, float d2) - { - if (d1 !<>= d2) // if either are NaN - { - if (d1 !<>= d1) - { if (d2 !<>= d2) - return 0; - return -1; - } - return 1; - } - return (d1 == d2) ? 0 : ((d1 < d2) ? -1 : 1); - } - - override equals_t equals(in void* p1, in void* p2) - { - return _equals(*cast(float *)p1, *cast(float *)p2); - } - - override int compare(in void* p1, in void* p2) - { - return _compare(*cast(float *)p1, *cast(float *)p2); - } - - override size_t tsize() - { - return float.sizeof; - } - - override void swap(void *p1, void *p2) - { - float t; - - t = *cast(float *)p1; - *cast(float *)p1 = *cast(float *)p2; - *cast(float *)p2 = t; - } - - override void[] init() - { static immutable float r; - - return (cast(float *)&r)[0 .. 1]; - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/typeinfo/ti_idouble.d --- a/druntime/src/compiler/dmd/typeinfo/ti_idouble.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: *cast(int*) p2) - return 1; - return 0; - } - - override size_t tsize() - { - return int.sizeof; - } - - override void swap(void *p1, void *p2) - { - int t; - - t = *cast(int *)p1; - *cast(int *)p1 = *cast(int *)p2; - *cast(int *)p2 = t; - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/typeinfo/ti_ireal.d --- a/druntime/src/compiler/dmd/typeinfo/ti_ireal.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: *cast(long *)p2) - return 1; - return 0; - } - - override size_t tsize() - { - return long.sizeof; - } - - override void swap(void *p1, void *p2) - { - long t; - - t = *cast(long *)p1; - *cast(long *)p1 = *cast(long *)p2; - *cast(long *)p2 = t; - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/typeinfo/ti_ptr.d --- a/druntime/src/compiler/dmd/typeinfo/ti_ptr.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: Boost License 1.0. - * Authors: Walter Bright - * - * Copyright Digital Mars 2004 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module rt.typeinfo.ti_real; - -// real - -class TypeInfo_e : TypeInfo -{ - override string toString() { return "real"; } - - override hash_t getHash(in void* p) - { - return (cast(uint *)p)[0] + (cast(uint *)p)[1] + (cast(ushort *)p)[4]; - } - - static equals_t _equals(real f1, real f2) - { - return f1 == f2 || - (f1 !<>= f1 && f2 !<>= f2); - } - - static int _compare(real d1, real d2) - { - if (d1 !<>= d2) // if either are NaN - { - if (d1 !<>= d1) - { if (d2 !<>= d2) - return 0; - return -1; - } - return 1; - } - return (d1 == d2) ? 0 : ((d1 < d2) ? -1 : 1); - } - - override equals_t equals(in void* p1, in void* p2) - { - return _equals(*cast(real *)p1, *cast(real *)p2); - } - - override int compare(in void* p1, in void* p2) - { - return _compare(*cast(real *)p1, *cast(real *)p2); - } - - override size_t tsize() - { - return real.sizeof; - } - - override void swap(void *p1, void *p2) - { - real t; - - t = *cast(real *)p1; - *cast(real *)p1 = *cast(real *)p2; - *cast(real *)p2 = t; - } - - override void[] init() - { static immutable real r; - - return (cast(real *)&r)[0 .. 1]; - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/typeinfo/ti_short.d --- a/druntime/src/compiler/dmd/typeinfo/ti_short.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: *cast(uint*) p2) - return 1; - return 0; - } - - override size_t tsize() - { - return uint.sizeof; - } - - override void swap(void *p1, void *p2) - { - int t; - - t = *cast(uint *)p1; - *cast(uint *)p1 = *cast(uint *)p2; - *cast(uint *)p2 = t; - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/typeinfo/ti_ulong.d --- a/druntime/src/compiler/dmd/typeinfo/ti_ulong.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: *cast(ulong *)p2) - return 1; - return 0; - } - - override size_t tsize() - { - return ulong.sizeof; - } - - override void swap(void *p1, void *p2) - { - ulong t; - - t = *cast(ulong *)p1; - *cast(ulong *)p1 = *cast(ulong *)p2; - *cast(ulong *)p2 = t; - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/typeinfo/ti_ushort.d --- a/druntime/src/compiler/dmd/typeinfo/ti_ushort.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: =0x48 && x<=0x80) - || x==0x86 || x==0x87 - || (x>=0x66 && x<=0x68) || (x>=0x39 && x<=0x3E)){ - datacache[level].lineSize = 64; - } else datacache[level].lineSize = 32; - } - } - } - - uint[4] a; - bool firstTime = true; - // On a multi-core system, this could theoretically fail, but it's only used - // for old single-core CPUs. - uint numinfos = 1; - do { - asm { - mov EAX, 2; - cpuid; - mov a, EAX; - mov a+4, EBX; - mov a+8, ECX; - mov a+12, EDX; - } - if (firstTime) { - if (a[0]==0x0000_7001 && a[3]==0x80 && a[1]==0 && a[2]==0) { - // Cyrix MediaGX MMXEnhanced returns: EAX= 00007001, EDX=00000080. - // These are NOT standard Intel values - // (TLB = 32 entry, 4 way associative, 4K pages) - // (L1 cache = 16K, 4way, linesize16) - datacache[0].size=8; - datacache[0].associativity=4; - datacache[0].lineSize=16; - return; - } - // lsb of a is how many times to loop. - numinfos = a[0] & 0xFF; - // and otherwise it should be ignored - a[0] &= 0xFFFF_FF00; - firstTime = false; - } - for (int c=0; c<4;++c) { - // high bit set == no info. - if (a[c] & 0x8000_0000) continue; - decipherCpuid2(cast(ubyte)(a[c] & 0xFF)); - decipherCpuid2(cast(ubyte)((a[c]>>8) & 0xFF)); - decipherCpuid2(cast(ubyte)((a[c]>>16) & 0xFF)); - decipherCpuid2(cast(ubyte)((a[c]>>24) & 0xFF)); - } - } while (--numinfos); -} - -// CPUID4: "Deterministic cache parameters" leaf -void getcacheinfoCPUID4() -{ - int cachenum = 0; - for(;;) { - uint a, b, number_of_sets; - asm { - mov EAX, 4; - mov ECX, cachenum; - cpuid; - mov a, EAX; - mov b, EBX; - mov number_of_sets, ECX; - } - ++cachenum; - if ((a&0x1F)==0) break; // no more caches - uint numthreads = ((a>>14) & 0xFFF) + 1; - uint numcores = ((a>>26) & 0x3F) + 1; - if (numcores > maxCores) maxCores = numcores; - if ((a&0x1F)!=1 && ((a&0x1F)!=3)) continue; // we only want data & unified caches - - ++number_of_sets; - ubyte level = cast(ubyte)(((a>>5)&7)-1); - if (level > datacache.length) continue; // ignore deep caches - datacache[level].associativity = a & 0x200 ? ubyte.max :cast(ubyte)((b>>22)+1); - datacache[level].lineSize = (b & 0xFFF)+ 1; // system coherency line size - uint line_partitions = ((b >> 12)& 0x3FF) + 1; - // Size = number of sets * associativity * cachelinesize * linepartitions - // and must convert to Kb, also dividing by the number of hyperthreads using this cache. - ulong sz = (datacache[level].associativity< ubyte.max)? number_of_sets * - datacache[level].associativity : number_of_sets; - datacache[level].size = cast(uint)( - (sz * datacache[level].lineSize * line_partitions ) / (numthreads *1024)); - if (level == 0 && (a&0xF)==3) { - // Halve the size for unified L1 caches - datacache[level].size/=2; - } - } -} - -// CPUID8000_0005 & 6 -void getAMDcacheinfo() -{ - uint c5, c6, d6; - asm { - mov EAX, 0x8000_0005; // L1 cache - cpuid; - // EAX has L1_TLB_4M. - // EBX has L1_TLB_4K - // EDX has L1 instruction cache - mov c5, ECX; - } - - datacache[0].size = ( (c5>>24) & 0xFF); - datacache[0].associativity = cast(ubyte)( (c5 >> 16) & 0xFF); - datacache[0].lineSize = c5 & 0xFF; - - if (max_extended_cpuid >= 0x8000_0006) { - // AMD K6-III or K6-2+ or later. - ubyte numcores = 1; - if (max_extended_cpuid >=0x8000_0008) { - asm { - mov EAX, 0x8000_0008; - cpuid; - mov numcores, CL; - } - ++numcores; - if (numcores>maxCores) maxCores = numcores; - } - asm { - mov EAX, 0x8000_0006; // L2/L3 cache - cpuid; - mov c6, ECX; // L2 cache info - mov d6, EDX; // L3 cache info - } - - immutable ubyte [] assocmap = [ 0, 1, 2, 0, 4, 0, 8, 0, 16, 0, 32, 48, 64, 96, 128, 0xFF ]; - datacache[1].size = (c6>>16) & 0xFFFF; - datacache[1].associativity = assocmap[(c6>>12)&0xF]; - datacache[1].lineSize = c6 & 0xFF; - - // The L3 cache value is TOTAL, not per core. - datacache[2].size = ((d6>>18)*512)/numcores; // could be up to 2 * this, -1. - datacache[2].associativity = assocmap[(d6>>12)&0xF]; - datacache[2].lineSize = d6 & 0xFF; - } -} - - -void cpuidX86() -{ - char * venptr = vendorID.ptr; - asm { - mov EAX, 0; - cpuid; - mov max_cpuid, EAX; - mov EAX, venptr; - mov [EAX], EBX; - mov [EAX + 4], EDX; - mov [EAX + 8], ECX; - mov EAX, 0x8000_0000; - cpuid; - mov max_extended_cpuid, EAX; - } - - probablyIntel = vendorID == "GenuineIntel"; - probablyAMD = vendorID == "AuthenticAMD"; - uint a, b, c, d; - uint apic = 0; // brand index, apic id - asm { - mov EAX, 1; // model, stepping - cpuid; - mov a, EAX; - mov apic, EBX; - mov miscfeatures, ECX; - mov features, EDX; - } - amdfeatures = 0; - amdmiscfeatures = 0; - if (max_extended_cpuid >= 0x8000_0001) { - asm { - mov EAX, 0x8000_0001; - cpuid; - mov amdmiscfeatures, ECX; - mov amdfeatures, EDX; - } - } - // Try to detect fraudulent vendorIDs - if (amd3dnow) probablyIntel = false; - - stepping = a & 0xF; - uint fbase = (a >> 8) & 0xF; - uint mbase = (a >> 4) & 0xF; - family = ((fbase == 0xF) || (fbase == 0)) ? fbase + (a >> 20) & 0xFF : fbase; - model = ((fbase == 0xF) || (fbase == 6 && probablyIntel) ) ? - mbase + ((a >> 12) & 0xF0) : mbase; - - if (!probablyIntel && max_extended_cpuid >= 0x8000_0008) { - // determine max number of cores for AMD - asm { - mov EAX, 0x8000_0008; - cpuid; - mov c, ECX; - } - uint apicsize = (c>>12) & 0xF; - if (apicsize == 0) { - // use legacy method - if (hyperThreadingBit) maxCores = c & 0xFF; - else maxCores = 1; - } else { - // maxcores = 2^ apicsize - maxCores = 1; - while (apicsize) { maxCores<<=1; --apicsize; } - } - } - - if (max_extended_cpuid >= 0x8000_0004) { - char *procptr = processorNameBuffer.ptr; - asm { - push ESI; - mov ESI, procptr; - mov EAX, 0x8000_0002; - cpuid; - mov [ESI], EAX; - mov [ESI+4], EBX; - mov [ESI+8], ECX; - mov [ESI+12], EDX; - mov EAX, 0x8000_0003; - cpuid; - mov [ESI+16], EAX; - mov [ESI+20], EBX; - mov [ESI+24], ECX; - mov [ESI+28], EDX; - mov EAX, 0x8000_0004; - cpuid; - mov [ESI+32], EAX; - mov [ESI+36], EBX; - mov [ESI+40], ECX; - mov [ESI+44], EDX; - pop ESI; - } - // Intel P4 and PM pad at front with spaces. - // Other CPUs pad at end with nulls. - int start = 0, end = 0; - while (processorNameBuffer[start] == ' ') { ++start; } - while (processorNameBuffer[$-end-1] == 0) { ++end; } - processorName = processorNameBuffer[start..$-end]; - } else { - processorName[] = "Unknown CPU"; - } - // Determine cache sizes - - // Intel docs specify that they return 0 for 0x8000_0005. - // AMD docs do not specify the behaviour for 0004 and 0002. - // Centaur/VIA and most other manufacturers use the AMD method, - // except Cyrix MediaGX MMX Enhanced uses their OWN form of CPUID2! - // NS Geode GX1 provides CyrixCPUID2 _and_ does the same wrong behaviour - // for CPUID80000005. But Geode GX uses the AMD method - - // Deal with Geode GX1 - make it same as MediaGX MMX. - if (max_extended_cpuid==0x8000_0005 && max_cpuid==2) { - max_extended_cpuid = 0x8000_0004; - } - // Therefore, we try the AMD method unless it's an Intel chip. - // If we still have no info, try the Intel methods. - datacache[0].size = 0; - if (max_cpuid<2 || !probablyIntel) { - if (max_extended_cpuid >= 0x8000_0005) { - getAMDcacheinfo(); - } else if (probablyAMD) { - // According to AMDProcRecognitionAppNote, this means CPU - // K5 model 0, or Am5x86 (model 4), or Am4x86DX4 (model 4) - // Am5x86 has 16Kb 4-way unified data & code cache. - datacache[0].size = 8; - datacache[0].associativity = 4; - datacache[0].lineSize = 32; - } else { - // Some obscure CPU. - // Values for Cyrix 6x86MX (family 6, model 0) - datacache[0].size = 64; - datacache[0].associativity = 4; - datacache[0].lineSize = 32; - } - } - if ((datacache[0].size == 0) && max_cpuid>=4) { - getcacheinfoCPUID4(); - } - if ((datacache[0].size == 0) && max_cpuid>=2) { - getcacheinfoCPUID2(); - } - if (datacache[0].size == 0) { - // Pentium, PMMX, late model 486, or an obscure CPU - if (mmx) { // Pentium MMX. Also has 8kB code cache. - datacache[0].size = 16; - datacache[0].associativity = 4; - datacache[0].lineSize = 32; - } else { // Pentium 1 (which also has 8kB code cache) - // or 486. - // Cyrix 6x86: 16, 4way, 32 linesize - datacache[0].size = 8; - datacache[0].associativity = 2; - datacache[0].lineSize = 32; - } - } - if (hyperThreadingBit) maxThreads = (apic>>>16) & 0xFF; - else maxThreads = maxCores; -} - -// Return true if the cpuid instruction is supported. -// BUG(WONTFIX): Returns false for Cyrix 6x86 and 6x86L. They will be treated as 486 machines. -bool hasCPUID() -{ - uint flags; - asm { - pushfd; - pop EAX; - mov flags, EAX; - xor EAX, 0x0020_0000; - push EAX; - popfd; - pushfd; - pop EAX; - xor flags, EAX; - } - return (flags & 0x0020_0000) !=0; -} - -} else { // inline asm X86 - - bool hasCPUID() { return false; } - - void cpuidX86() - { - datacache[0].size = 8; - datacache[0].associativity = 2; - datacache[0].lineSize = 32; - } -} - -// TODO: Implement this function with OS support -void cpuidPPC() -{ - enum :int { PPC601, PPC603, PPC603E, PPC604, - PPC604E, PPC620, PPCG3, PPCG4, PPCG5 }; - - // TODO: - // asm { mfpvr; } returns the CPU version but unfortunately it can - // only be used in kernel mode. So OS support is required. - int cputype = PPC603; - - // 601 has a 8KB combined data & code L1 cache. - uint sizes[] = [4, 8, 16, 16, 32, 32, 32, 32, 64]; - ubyte ways[] = [8, 2, 4, 4, 4, 8, 8, 8, 8]; - uint L2size[]= [0, 0, 0, 0, 0, 0, 0, 256, 512]; - uint L3size[]= [0, 0, 0, 0, 0, 0, 0, 2048, 0]; - - datacache[0].size = sizes[cputype]; - datacache[0].associativity = ways[cputype]; - datacache[0].lineSize = (cputype==PPCG5)? 128 : - (cputype == PPC620 || cputype == PPCG3)? 64 : 32; - datacache[1].size = L2size[cputype]; - datacache[2].size = L3size[cputype]; - datacache[1].lineSize = datacache[0].lineSize; - datacache[2].lineSize = datacache[0].lineSize; -} - -// TODO: Implement this function with OS support -void cpuidSparc() -{ - // UltaSparcIIi : L1 = 16, 2way. L2 = 512, 4 way. - // UltraSparcIII : L1 = 64, 4way. L2= 4096 or 8192. - // UltraSparcIIIi: L1 = 64, 4way. L2= 1024, 4 way - // UltraSparcIV : L1 = 64, 4way. L2 = 16*1024. - // UltraSparcIV+ : L1 = 64, 4way. L2 = 2048, L3=32*1024. - // Sparc64V : L1 = 128, 2way. L2 = 4096 4way. -} - - -static this() -{ - if (hasCPUID()) { - cpuidX86(); - } else { - // it's a 386 or 486, or a Cyrix 6x86. - //Probably still has an external cache. - } - if (datacache[0].size==0) { - // Guess same as Pentium 1. - datacache[0].size = 8; - datacache[0].associativity = 2; - datacache[0].lineSize = 32; - } - numCacheLevels = 1; - // And now fill up all the unused levels with full memory space. - for (int i=1; i< datacache.length; ++i) { - if (datacache[i].size==0) { - // Set all remaining levels of cache equal to full address space. - datacache[i].size = uint.max/1024; - datacache[i].associativity = 1; - datacache[i].lineSize = datacache[i-1].lineSize; - } else numCacheLevels = i+1; - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/util/ctype.d --- a/druntime/src/compiler/dmd/util/ctype.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,92 +0,0 @@ -/** - * Simple ASCII char classification functions. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: Boost License 1.0. - * Authors: Sean Kelly - * - * Copyright Sean Kelly 2005 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module rt.util.string; - -private import core.stdc.string; - -char[] intToString( char[] buf, uint val ) -{ - assert( buf.length > 9 ); - auto p = buf.ptr + buf.length; - - do - { - *--p = cast(char)(val % 10 + '0'); - } while( val /= 10 ); - - return buf[p - buf.ptr .. $]; -} - - -int dstrcmp( in char[] s1, in char[] s2 ) -{ - auto len = s1.length; - if( s2.length < len ) - len = s2.length; - if( memcmp( s1.ptr, s2.ptr, len ) == 0 ) - return 0; - return s1.length > s2.length ? 1 : -1; -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/util/utf.d --- a/druntime/src/compiler/dmd/util/utf.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,901 +0,0 @@ -/******************************************** - * Encode and decode UTF-8, UTF-16 and UTF-32 strings. - * - * For Win32 systems, the C wchar_t type is UTF-16 and corresponds to the D - * wchar type. - * For Posix systems, the C wchar_t type is UTF-32 and corresponds to - * the D utf.dchar type. - * - * UTF character support is restricted to (\u0000 <= character <= \U0010FFFF). - * - * See_Also: - * $(LINK2 http://en.wikipedia.org/wiki/Unicode, Wikipedia)
- * $(LINK http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8)
- * $(LINK http://anubis.dkuug.dk/JTC1/SC2/WG2/docs/n1335) - * Macros: - * WIKI = Phobos/StdUtf - * - * Copyright: Copyright Digital Mars 2003 - 2009. - * License: = 0xD800 && u <= 0xDBFF); -} - -/** - * stride() returns the length of a UTF-32 sequence starting at index i - * in string s. - * Returns: The return value will always be 1. - */ -uint stride(in dchar[] s, size_t i) -{ - return 1; -} - -/******************************************* - * Given an index i into an array of characters s[], - * and assuming that index i is at the start of a UTF character, - * determine the number of UCS characters up to that index i. - */ - -size_t toUCSindex(in char[] s, size_t i) -{ - size_t n; - size_t j; - - for (j = 0; j < i; ) - { - j += stride(s, j); - n++; - } - if (j > i) - { - onUnicodeError("invalid UTF-8 sequence", j); - } - return n; -} - -/** ditto */ -size_t toUCSindex(in wchar[] s, size_t i) -{ - size_t n; - size_t j; - - for (j = 0; j < i; ) - { - j += stride(s, j); - n++; - } - if (j > i) - { - onUnicodeError("invalid UTF-16 sequence", j); - } - return n; -} - -/** ditto */ -size_t toUCSindex(in dchar[] s, size_t i) -{ - return i; -} - -/****************************************** - * Given a UCS index n into an array of characters s[], return the UTF index. - */ - -size_t toUTFindex(in char[] s, size_t n) -{ - size_t i; - - while (n--) - { - uint j = UTF8stride[s[i]]; - if (j == 0xFF) - onUnicodeError("invalid UTF-8 sequence", i); - i += j; - } - return i; -} - -/** ditto */ -size_t toUTFindex(in wchar[] s, size_t n) -{ - size_t i; - - while (n--) - { wchar u = s[i]; - - i += 1 + (u >= 0xD800 && u <= 0xDBFF); - } - return i; -} - -/** ditto */ -size_t toUTFindex(in dchar[] s, size_t n) -{ - return n; -} - -/* =================== Decode ======================= */ - -/*************** - * Decodes and returns character starting at s[idx]. idx is advanced past the - * decoded character. If the character is not well formed, a UtfException is - * thrown and idx remains unchanged. - */ -dchar decode(in char[] s, inout size_t idx) - in - { - assert(idx >= 0 && idx < s.length); - } - out (result) - { - assert(isValidDchar(result)); - } - body - { - size_t len = s.length; - dchar V; - size_t i = idx; - char u = s[i]; - - if (u & 0x80) - { uint n; - char u2; - - /* The following encodings are valid, except for the 5 and 6 byte - * combinations: - * 0xxxxxxx - * 110xxxxx 10xxxxxx - * 1110xxxx 10xxxxxx 10xxxxxx - * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - * 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx - * 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx - */ - for (n = 1; ; n++) - { - if (n > 4) - goto Lerr; // only do the first 4 of 6 encodings - if (((u << n) & 0x80) == 0) - { - if (n == 1) - goto Lerr; - break; - } - } - - // Pick off (7 - n) significant bits of B from first byte of octet - V = cast(dchar)(u & ((1 << (7 - n)) - 1)); - - if (i + (n - 1) >= len) - goto Lerr; // off end of string - - /* The following combinations are overlong, and illegal: - * 1100000x (10xxxxxx) - * 11100000 100xxxxx (10xxxxxx) - * 11110000 1000xxxx (10xxxxxx 10xxxxxx) - * 11111000 10000xxx (10xxxxxx 10xxxxxx 10xxxxxx) - * 11111100 100000xx (10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx) - */ - u2 = s[i + 1]; - if ((u & 0xFE) == 0xC0 || - (u == 0xE0 && (u2 & 0xE0) == 0x80) || - (u == 0xF0 && (u2 & 0xF0) == 0x80) || - (u == 0xF8 && (u2 & 0xF8) == 0x80) || - (u == 0xFC && (u2 & 0xFC) == 0x80)) - goto Lerr; // overlong combination - - for (uint j = 1; j != n; j++) - { - u = s[i + j]; - if ((u & 0xC0) != 0x80) - goto Lerr; // trailing bytes are 10xxxxxx - V = (V << 6) | (u & 0x3F); - } - if (!isValidDchar(V)) - goto Lerr; - i += n; - } - else - { - V = cast(dchar) u; - i++; - } - - idx = i; - return V; - - Lerr: - onUnicodeError("invalid UTF-8 sequence", i); - return V; // dummy return - } - -unittest -{ size_t i; - dchar c; - - debug(utf) printf("utf.decode.unittest\n"); - - static s1 = "abcd"c; - i = 0; - c = decode(s1, i); - assert(c == cast(dchar)'a'); - assert(i == 1); - c = decode(s1, i); - assert(c == cast(dchar)'b'); - assert(i == 2); - - static s2 = "\xC2\xA9"c; - i = 0; - c = decode(s2, i); - assert(c == cast(dchar)'\u00A9'); - assert(i == 2); - - static s3 = "\xE2\x89\xA0"c; - i = 0; - c = decode(s3, i); - assert(c == cast(dchar)'\u2260'); - assert(i == 3); - - static s4 = - [ "\xE2\x89"c[], // too short - "\xC0\x8A", - "\xE0\x80\x8A", - "\xF0\x80\x80\x8A", - "\xF8\x80\x80\x80\x8A", - "\xFC\x80\x80\x80\x80\x8A", - ]; - - for (int j = 0; j < s4.length; j++) - { - try - { - i = 0; - c = decode(s4[j], i); - assert(0); - } - catch (Object o) - { - i = 23; - } - assert(i == 23); - } -} - -/** ditto */ - -dchar decode(in wchar[] s, inout size_t idx) - in - { - assert(idx >= 0 && idx < s.length); - } - out (result) - { - assert(isValidDchar(result)); - } - body - { - string msg; - dchar V; - size_t i = idx; - uint u = s[i]; - - if (u & ~0x7F) - { if (u >= 0xD800 && u <= 0xDBFF) - { uint u2; - - if (i + 1 == s.length) - { msg = "surrogate UTF-16 high value past end of string"; - goto Lerr; - } - u2 = s[i + 1]; - if (u2 < 0xDC00 || u2 > 0xDFFF) - { msg = "surrogate UTF-16 low value out of range"; - goto Lerr; - } - u = ((u - 0xD7C0) << 10) + (u2 - 0xDC00); - i += 2; - } - else if (u >= 0xDC00 && u <= 0xDFFF) - { msg = "unpaired surrogate UTF-16 value"; - goto Lerr; - } - else if (u == 0xFFFE || u == 0xFFFF) - { msg = "illegal UTF-16 value"; - goto Lerr; - } - else - i++; - } - else - { - i++; - } - - idx = i; - return cast(dchar)u; - - Lerr: - onUnicodeError(msg, i); - return cast(dchar)u; // dummy return - } - -/** ditto */ - -dchar decode(in dchar[] s, inout size_t idx) - in - { - assert(idx >= 0 && idx < s.length); - } - body - { - size_t i = idx; - dchar c = s[i]; - - if (!isValidDchar(c)) - goto Lerr; - idx = i + 1; - return c; - - Lerr: - onUnicodeError("invalid UTF-32 value", i); - return c; // dummy return - } - - -/* =================== Encode ======================= */ - -/******************************* - * Encodes character c and appends it to array s[]. - */ -void encode(inout char[] s, dchar c) - in - { - assert(isValidDchar(c)); - } - body - { - char[] r = s; - - if (c <= 0x7F) - { - r ~= cast(char) c; - } - else - { - char[4] buf; - uint L; - - if (c <= 0x7FF) - { - buf[0] = cast(char)(0xC0 | (c >> 6)); - buf[1] = cast(char)(0x80 | (c & 0x3F)); - L = 2; - } - else if (c <= 0xFFFF) - { - buf[0] = cast(char)(0xE0 | (c >> 12)); - buf[1] = cast(char)(0x80 | ((c >> 6) & 0x3F)); - buf[2] = cast(char)(0x80 | (c & 0x3F)); - L = 3; - } - else if (c <= 0x10FFFF) - { - buf[0] = cast(char)(0xF0 | (c >> 18)); - buf[1] = cast(char)(0x80 | ((c >> 12) & 0x3F)); - buf[2] = cast(char)(0x80 | ((c >> 6) & 0x3F)); - buf[3] = cast(char)(0x80 | (c & 0x3F)); - L = 4; - } - else - { - assert(0); - } - r ~= buf[0 .. L]; - } - s = r; - } - -unittest -{ - debug(utf) printf("utf.encode.unittest\n"); - - char[] s = "abcd".dup; - encode(s, cast(dchar)'a'); - assert(s.length == 5); - assert(s == "abcda"); - - encode(s, cast(dchar)'\u00A9'); - assert(s.length == 7); - assert(s == "abcda\xC2\xA9"); - //assert(s == "abcda\u00A9"); // BUG: fix compiler - - encode(s, cast(dchar)'\u2260'); - assert(s.length == 10); - assert(s == "abcda\xC2\xA9\xE2\x89\xA0"); -} - -/** ditto */ - -void encode(inout wchar[] s, dchar c) - in - { - assert(isValidDchar(c)); - } - body - { - wchar[] r = s; - - if (c <= 0xFFFF) - { - r ~= cast(wchar) c; - } - else - { - wchar[2] buf; - - buf[0] = cast(wchar) ((((c - 0x10000) >> 10) & 0x3FF) + 0xD800); - buf[1] = cast(wchar) (((c - 0x10000) & 0x3FF) + 0xDC00); - r ~= buf; - } - s = r; - } - -/** ditto */ -void encode(inout dchar[] s, dchar c) - in - { - assert(isValidDchar(c)); - } - body - { - s ~= c; - } - -/** -Returns the code length of $(D c) in the encoding using $(D C) as a -code point. The code is returned in character count, not in bytes. - */ - -ubyte codeLength(C)(dchar c) -{ - - static if (C.sizeof == 1) - { - return - c <= 0x7F ? 1 - : c <= 0x7FF ? 2 - : c <= 0xFFFF ? 3 - : c <= 0x10FFFF ? 4 - : (assert(false), 6); -} - - else static if (C.sizeof == 2) -{ - return c <= 0xFFFF ? 1 : 2; - } - else - { - static assert(C.sizeof == 4); - return 1; - } -} - -/* =================== Validation ======================= */ - -/*********************************** -Checks to see if string is well formed or not. $(D S) can be an array - of $(D char), $(D wchar), or $(D dchar). Throws a $(D UtfException) - if it is not. Use to check all untrusted input for correctness. - */ -void validate(S)(in S s) -{ - auto len = s.length; - for (size_t i = 0; i < len; ) - { - decode(s, i); - } -} - -/* =================== Conversion to UTF8 ======================= */ - -char[] toUTF8(char[4] buf, dchar c) - in - { - assert(isValidDchar(c)); - } - body - { - if (c <= 0x7F) - { - buf[0] = cast(char) c; - return buf[0 .. 1]; - } - else if (c <= 0x7FF) - { - buf[0] = cast(char)(0xC0 | (c >> 6)); - buf[1] = cast(char)(0x80 | (c & 0x3F)); - return buf[0 .. 2]; - } - else if (c <= 0xFFFF) - { - buf[0] = cast(char)(0xE0 | (c >> 12)); - buf[1] = cast(char)(0x80 | ((c >> 6) & 0x3F)); - buf[2] = cast(char)(0x80 | (c & 0x3F)); - return buf[0 .. 3]; - } - else if (c <= 0x10FFFF) - { - buf[0] = cast(char)(0xF0 | (c >> 18)); - buf[1] = cast(char)(0x80 | ((c >> 12) & 0x3F)); - buf[2] = cast(char)(0x80 | ((c >> 6) & 0x3F)); - buf[3] = cast(char)(0x80 | (c & 0x3F)); - return buf[0 .. 4]; - } - assert(0); - } - -/******************* - * Encodes string s into UTF-8 and returns the encoded string. - */ -string toUTF8(string s) - in - { - validate(s); - } - body - { - return s; - } - -/** ditto */ -string toUTF8(in wchar[] s) -{ - char[] r; - size_t i; - size_t slen = s.length; - - r.length = slen; - - for (i = 0; i < slen; i++) - { wchar c = s[i]; - - if (c <= 0x7F) - r[i] = cast(char)c; // fast path for ascii - else - { - r.length = i; - foreach (dchar c; s[i .. slen]) - { - encode(r, c); - } - break; - } - } - return cast(string)r; -} - -/** ditto */ -string toUTF8(in dchar[] s) -{ - char[] r; - size_t i; - size_t slen = s.length; - - r.length = slen; - - for (i = 0; i < slen; i++) - { dchar c = s[i]; - - if (c <= 0x7F) - r[i] = cast(char)c; // fast path for ascii - else - { - r.length = i; - foreach (dchar d; s[i .. slen]) - { - encode(r, d); - } - break; - } - } - return cast(string)r; -} - -/* =================== Conversion to UTF16 ======================= */ - -wchar[] toUTF16(wchar[2] buf, dchar c) - in - { - assert(isValidDchar(c)); - } - body - { - if (c <= 0xFFFF) - { - buf[0] = cast(wchar) c; - return buf[0 .. 1]; - } - else - { - buf[0] = cast(wchar) ((((c - 0x10000) >> 10) & 0x3FF) + 0xD800); - buf[1] = cast(wchar) (((c - 0x10000) & 0x3FF) + 0xDC00); - return buf[0 .. 2]; - } - } - -/**************** - * Encodes string s into UTF-16 and returns the encoded string. - * toUTF16z() is suitable for calling the 'W' functions in the Win32 API that take - * an LPWSTR or LPCWSTR argument. - */ -wstring toUTF16(in char[] s) -{ - wchar[] r; - size_t slen = s.length; - - r.length = slen; - r.length = 0; - for (size_t i = 0; i < slen; ) - { - dchar c = s[i]; - if (c <= 0x7F) - { - i++; - r ~= cast(wchar)c; - } - else - { - c = decode(s, i); - encode(r, c); - } - } - return cast(wstring)r; -} - -alias const(wchar)* wptr; -/** ditto */ -wptr toUTF16z(in char[] s) -{ - wchar[] r; - size_t slen = s.length; - - r.length = slen + 1; - r.length = 0; - for (size_t i = 0; i < slen; ) - { - dchar c = s[i]; - if (c <= 0x7F) - { - i++; - r ~= cast(wchar)c; - } - else - { - c = decode(s, i); - encode(r, c); - } - } - r ~= "\000"; - return r.ptr; -} - -/** ditto */ -wstring toUTF16(wstring s) - in - { - validate(s); - } - body - { - return s; - } - -/** ditto */ -wstring toUTF16(in dchar[] s) -{ - wchar[] r; - size_t slen = s.length; - - r.length = slen; - r.length = 0; - for (size_t i = 0; i < slen; i++) - { - encode(r, s[i]); - } - return cast(wstring)r; -} - -/* =================== Conversion to UTF32 ======================= */ - -/***** - * Encodes string s into UTF-32 and returns the encoded string. - */ -dstring toUTF32(in char[] s) -{ - dchar[] r; - size_t slen = s.length; - size_t j = 0; - - r.length = slen; // r[] will never be longer than s[] - for (size_t i = 0; i < slen; ) - { - dchar c = s[i]; - if (c >= 0x80) - c = decode(s, i); - else - i++; // c is ascii, no need for decode - r[j++] = c; - } - return cast(dstring)r[0 .. j]; -} - -/** ditto */ -dstring toUTF32(in wchar[] s) -{ - dchar[] r; - size_t slen = s.length; - size_t j = 0; - - r.length = slen; // r[] will never be longer than s[] - for (size_t i = 0; i < slen; ) - { - dchar c = s[i]; - if (c >= 0x80) - c = decode(s, i); - else - i++; // c is ascii, no need for decode - r[j++] = c; - } - return cast(dstring)r[0 .. j]; -} - -/** ditto */ -dstring toUTF32(dstring s) - in - { - validate(s); - } - body - { - return s; - } - -/* ================================ tests ================================== */ - -unittest -{ - debug(utf) printf("utf.toUTF.unittest\n"); - - auto c = "hello"c[]; - auto w = toUTF16(c); - assert(w == "hello"); - auto d = toUTF32(c); - assert(d == "hello"); - - c = toUTF8(w); - assert(c == "hello"); - d = toUTF32(w); - assert(d == "hello"); - - c = toUTF8(d); - assert(c == "hello"); - w = toUTF16(d); - assert(w == "hello"); - - - c = "hel\u1234o"; - w = toUTF16(c); - assert(w == "hel\u1234o"); - d = toUTF32(c); - assert(d == "hel\u1234o"); - - c = toUTF8(w); - assert(c == "hel\u1234o"); - d = toUTF32(w); - assert(d == "hel\u1234o"); - - c = toUTF8(d); - assert(c == "hel\u1234o"); - w = toUTF16(d); - assert(w == "hel\u1234o"); - - - c = "he\U0010AAAAllo"; - w = toUTF16(c); - //foreach (wchar c; w) printf("c = x%x\n", c); - //foreach (wchar c; cast(wstring)"he\U0010AAAAllo") printf("c = x%x\n", c); - assert(w == "he\U0010AAAAllo"); - d = toUTF32(c); - assert(d == "he\U0010AAAAllo"); - - c = toUTF8(w); - assert(c == "he\U0010AAAAllo"); - d = toUTF32(w); - assert(d == "he\U0010AAAAllo"); - - c = toUTF8(d); - assert(c == "he\U0010AAAAllo"); - w = toUTF16(d); - assert(w == "he\U0010AAAAllo"); -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/dmd/win32.mak --- a/druntime/src/compiler/dmd/win32.mak Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,175 +0,0 @@ -# Makefile to build the D runtime library core components for Posix -# Designed to work with GNU make -# Targets: -# make -# Same as make all -# make debug -# Build the debug version of the library -# make release -# Build the release version of the library -# make doc -# Generate documentation -# make clean -# Delete all files created by build process - -# Essentials - -LIBDIR=..\..\..\lib -DOCDIR=..\..\..\doc -IMPDIR=..\..\..\import -LIBBASENAME=druntime_rt_dmd.lib -#MODULES=bitop exception memory runtime thread vararg \ -# $(addprefix sync/,barrier condition config exception mutex rwmutex semaphore) -BUILDS=debug release unittest - -MODULES_BASE= \ - aaA.d \ - aApply.d \ - aApplyR.d \ - adi.d \ - arrayassign.d \ - arraybyte.d \ - arraycast.d \ - arraycat.d \ - arraydouble.d \ - arrayfloat.d \ - arrayint.d \ - arrayreal.d \ - arrayshort.d \ - cast_.d \ - cover.d \ - dmain2.d \ - invariant.d \ - invariant_.d \ - lifetime.d \ - memory.d \ - memset.d \ - obj.d \ - object_.d \ - qsort.d \ - switch_.d \ - trace.d -# NOTE: trace.d and cover.d are not necessary for a successful build -# as both are used for debugging features (profiling and coverage) -# NOTE: a pre-compiled minit.obj has been provided in dmd for Win32 and -# minit.asm is not used by dmd for Linux - -MODULES_UTIL= \ - util\console.d \ - util\cpuid.d \ - util\ctype.d \ - util\string.d \ - util\utf.d - -MODULES_TI= \ - typeinfo\ti_AC.d \ - typeinfo\ti_Acdouble.d \ - typeinfo\ti_Acfloat.d \ - typeinfo\ti_Acreal.d \ - typeinfo\ti_Adouble.d \ - typeinfo\ti_Afloat.d \ - typeinfo\ti_Ag.d \ - typeinfo\ti_Aint.d \ - typeinfo\ti_Along.d \ - typeinfo\ti_Areal.d \ - typeinfo\ti_Ashort.d \ - typeinfo\ti_byte.d \ - typeinfo\ti_C.d \ - typeinfo\ti_cdouble.d \ - typeinfo\ti_cfloat.d \ - typeinfo\ti_char.d \ - typeinfo\ti_creal.d \ - typeinfo\ti_dchar.d \ - typeinfo\ti_delegate.d \ - typeinfo\ti_double.d \ - typeinfo\ti_float.d \ - typeinfo\ti_idouble.d \ - typeinfo\ti_ifloat.d \ - typeinfo\ti_int.d \ - typeinfo\ti_ireal.d \ - typeinfo\ti_long.d \ - typeinfo\ti_ptr.d \ - typeinfo\ti_real.d \ - typeinfo\ti_short.d \ - typeinfo\ti_ubyte.d \ - typeinfo\ti_uint.d \ - typeinfo\ti_ulong.d \ - typeinfo\ti_ushort.d \ - typeinfo\ti_void.d \ - typeinfo\ti_wchar.d - -C_SRCS=complex.c critical.c deh.c monitor.c - -# Symbols - -CC=dmc -DMD=dmd -DOCFLAGS=-version=DDoc -DFLAGS_release=-d -release -O -inline -w -nofloat -DFLAGS_debug=-d -g -w -nofloat -DFLAGS_unittest=$(DFLAGS_release) -unittest -CFLAGS_release=-mn -6 -r -CFLAGS_debug=-g -mn -6 -r -CFLAGS_unittest=$(CFLAGS_release) - -# Derived symbols - -C_OBJS=complex.obj critical.obj deh.obj monitor.obj -AS_OBJS=minit.obj -ALL_MODULES=$(MODULES_BASE) $(MODULES_UTIL) $(MODULES_TI) -D_SRCS=$(ALL_MODULES) -ALLLIBS=\ - $(LIBDIR)\debug\$(LIBBASENAME) \ - $(LIBDIR)\release\$(LIBBASENAME) \ - $(LIBDIR)\unittest\$(LIBBASENAME) - -# Patterns - -#$(LIBDIR)\%\$(LIBBASENAME) : $(D_SRCS) $(C_SRCS) $(AS_OBJS) -# $(CC) -c $(CFLAGS_$*) $(C_SRCS) -# $(DMD) $(DFLAGS_$*) -lib -of$@ $(D_SRCS) $(C_OBJS) $(AS_OBJS) -# del $(C_OBJS) - -#$(DOCDIR)\%.html : %.d -# $(DMD) -c -d -o- -Df$@ $< - -#$(IMPDIR)\%.di : %.d -# $(DMD) -c -d -o- -Hf$@ $< - -# Patterns - debug - -$(LIBDIR)\debug\$(LIBBASENAME) : $(D_SRCS) $(C_SRCS) $(AS_OBJS) - $(CC) -c $(CFLAGS_debug) $(C_SRCS) - $(DMD) $(DFLAGS_debug) -lib -of$@ $(D_SRCS) $(C_OBJS) $(AS_OBJS) - del $(C_OBJS) - -# Patterns - release - -$(LIBDIR)\release\$(LIBBASENAME) : $(D_SRCS) $(C_SRCS) $(AS_OBJS) - $(CC) -c $(CFLAGS_release) $(C_SRCS) - $(DMD) $(DFLAGS_release) -lib -of$@ $(D_SRCS) $(C_OBJS) $(AS_OBJS) - del $(C_OBJS) - -# Patterns - unittest - -$(LIBDIR)\unittest\$(LIBBASENAME) : $(D_SRCS) $(C_SRCS) $(AS_OBJS) - $(CC) -c $(CFLAGS_unittest) $(C_SRCS) - $(DMD) $(DFLAGS_unittest) -lib -of$@ $(D_SRCS) $(C_OBJS) $(AS_OBJS) - del $(C_OBJS) - -# Patterns - asm - -minit.obj : minit.asm - $(CC) -c $** - -# Rulez - -all : $(BUILDS) doc - -debug : $(LIBDIR)\debug\$(LIBBASENAME) $(IMPORTS) -release : $(LIBDIR)\release\$(LIBBASENAME) $(IMPORTS) -unittest : $(LIBDIR)\unittest\$(LIBBASENAME) $(IMPORTS) -#doc : $(DOCS) - -clean : - del $(IMPORTS) $(DOCS) $(ALLLIBS) diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/aApply.d --- a/druntime/src/compiler/ldc/aApply.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,386 +0,0 @@ -/** - * This code handles decoding UTF strings for foreach loops. There are 6 - * combinations of conversions between char, wchar, and dchar, and 2 of each - * of those. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: > 10) & 0x3FF) + 0xD800); - result = dg(cast(void *)&w); - if (result) - break; - w = cast(wchar)(((d - 0x10000) & 0x3FF) + 0xDC00); - } - } - else - i++; - result = dg(cast(void *)&w); - if (result) - break; - } - return result; -} - -extern (C) int _aApplywc1(wchar[] aa, dg_t dg) -{ int result; - size_t i; - size_t len = aa.length; - - debug(apply) printf("_aApplywc1(), len = %d\n", len); - for (i = 0; i < len; ) - { dchar d; - wchar w; - char c; - - w = aa[i]; - if (w & ~0x7F) - { - char[4] buf; - - d = decode(aa, i); - auto b = toUTF8(buf, d); - foreach (char c2; b) - { - result = dg(cast(void *)&c2); - if (result) - return result; - } - continue; - } - else - { c = cast(char)w; - i++; - } - result = dg(cast(void *)&c); - if (result) - break; - } - return result; -} - -extern (C) int _aApplydc1(dchar[] aa, dg_t dg) -{ int result; - - debug(apply) printf("_aApplydc1(), len = %d\n", aa.length); - foreach (dchar d; aa) - { - char c; - - if (d & ~0x7F) - { - char[4] buf; - - auto b = toUTF8(buf, d); - foreach (char c2; b) - { - result = dg(cast(void *)&c2); - if (result) - return result; - } - continue; - } - else - { - c = cast(char)d; - } - result = dg(cast(void *)&c); - if (result) - break; - } - return result; -} - -extern (C) int _aApplydw1(dchar[] aa, dg_t dg) -{ int result; - - debug(apply) printf("_aApplydw1(), len = %d\n", aa.length); - foreach (dchar d; aa) - { - wchar w; - - if (d <= 0xFFFF) - w = cast(wchar) d; - else - { - w = cast(wchar)((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); - result = dg(cast(void *)&w); - if (result) - break; - w = cast(wchar)(((d - 0x10000) & 0x3FF) + 0xDC00); - } - result = dg(cast(void *)&w); - if (result) - break; - } - return result; -} - - -/****************************************************************************/ - -// dg is D, but _aApplycd2() is C -extern (D) typedef int delegate(void *, void *) dg2_t; - -extern (C) int _aApplycd2(char[] aa, dg2_t dg) -{ int result; - size_t i; - size_t n; - size_t len = aa.length; - - debug(apply) printf("_aApplycd2(), len = %d\n", len); - for (i = 0; i < len; i += n) - { dchar d; - - d = aa[i]; - if (d & 0x80) - { - n = i; - d = decode(aa, n); - n -= i; - } - else - n = 1; - result = dg(&i, cast(void *)&d); - if (result) - break; - } - return result; -} - -extern (C) int _aApplywd2(wchar[] aa, dg2_t dg) -{ int result; - size_t i; - size_t n; - size_t len = aa.length; - - debug(apply) printf("_aApplywd2(), len = %d\n", len); - for (i = 0; i < len; i += n) - { dchar d; - - d = aa[i]; - if (d & ~0x7F) - { - n = i; - d = decode(aa, n); - n -= i; - } - else - n = 1; - result = dg(&i, cast(void *)&d); - if (result) - break; - } - return result; -} - -extern (C) int _aApplycw2(char[] aa, dg2_t dg) -{ int result; - size_t i; - size_t n; - size_t len = aa.length; - - debug(apply) printf("_aApplycw2(), len = %d\n", len); - for (i = 0; i < len; i += n) - { dchar d; - wchar w; - - w = aa[i]; - if (w & 0x80) - { n = i; - d = decode(aa, n); - n -= i; - if (d <= 0xFFFF) - w = cast(wchar) d; - else - { - w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); - result = dg(&i, cast(void *)&w); - if (result) - break; - w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00); - } - } - else - n = 1; - result = dg(&i, cast(void *)&w); - if (result) - break; - } - return result; -} - -extern (C) int _aApplywc2(wchar[] aa, dg2_t dg) -{ int result; - size_t i; - size_t n; - size_t len = aa.length; - - debug(apply) printf("_aApplywc2(), len = %d\n", len); - for (i = 0; i < len; i += n) - { dchar d; - wchar w; - char c; - - w = aa[i]; - if (w & ~0x7F) - { - char[4] buf; - - n = i; - d = decode(aa, n); - n -= i; - auto b = toUTF8(buf, d); - foreach (char c2; b) - { - result = dg(&i, cast(void *)&c2); - if (result) - return result; - } - continue; - } - else - { c = cast(char)w; - n = 1; - } - result = dg(&i, cast(void *)&c); - if (result) - break; - } - return result; -} - -extern (C) int _aApplydc2(dchar[] aa, dg2_t dg) -{ int result; - size_t i; - size_t len = aa.length; - - debug(apply) printf("_aApplydc2(), len = %d\n", len); - for (i = 0; i < len; i++) - { dchar d; - char c; - - d = aa[i]; - if (d & ~0x7F) - { - char[4] buf; - - auto b = toUTF8(buf, d); - foreach (char c2; b) - { - result = dg(&i, cast(void *)&c2); - if (result) - return result; - } - continue; - } - else - { c = cast(char)d; - } - result = dg(&i, cast(void *)&c); - if (result) - break; - } - return result; -} - -extern (C) int _aApplydw2(dchar[] aa, dg2_t dg) -{ int result; - - debug(apply) printf("_aApplydw2(), len = %d\n", aa.length); - foreach (size_t i, dchar d; aa) - { - wchar w; - auto j = i; - - if (d <= 0xFFFF) - w = cast(wchar) d; - else - { - w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); - result = dg(&j, cast(void *)&w); - if (result) - break; - w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00); - } - result = dg(&j, cast(void *)&w); - if (result) - break; - } - return result; -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/aApplyR.d --- a/druntime/src/compiler/ldc/aApplyR.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,957 +0,0 @@ -/** - * This code handles decoding UTF strings for foreach_reverse loops. There are - * 6 combinations of conversions between char, wchar, and dchar, and 2 of each - * of those. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: >= 1; - c = aa[i]; - } - d |= (c & m) << j; - } - result = dg(cast(void *)&d); - if (result) - break; - } - return result; -} - -unittest -{ - debug(apply) printf("_aApplyRcd1.unittest\n"); - - auto s = "hello"c[]; - int i; - - foreach_reverse(dchar d; s) - { - switch (i) - { - case 0: assert(d == 'o'); break; - case 1: assert(d == 'l'); break; - case 2: assert(d == 'l'); break; - case 3: assert(d == 'e'); break; - case 4: assert(d == 'h'); break; - default: assert(0); - } - i++; - } - assert(i == 5); - - s = "a\u1234\U00100456b"; - i = 0; - foreach_reverse(dchar d; s) - { - //printf("i = %d, d = %x\n", i, d); - switch (i) - { - case 0: assert(d == 'b'); break; - case 1: assert(d == '\U00100456'); break; - case 2: assert(d == '\u1234'); break; - case 3: assert(d == 'a'); break; - default: assert(0); - } - i++; - } - assert(i == 4); -} - -/*****************************/ - -extern (C) int _aApplyRwd1(in wchar[] aa, dg_t dg) -{ int result; - - debug(apply) printf("_aApplyRwd1(), len = %d\n", aa.length); - for (size_t i = aa.length; i != 0; ) - { dchar d; - - i--; - d = aa[i]; - if (d >= 0xDC00 && d <= 0xDFFF) - { if (i == 0) - onUnicodeError("Invalid UTF-16 sequence", 0); - i--; - d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00); - } - result = dg(cast(void *)&d); - if (result) - break; - } - return result; -} - -unittest -{ - debug(apply) printf("_aApplyRwd1.unittest\n"); - - auto s = "hello"w[]; - int i; - - foreach_reverse(dchar d; s) - { - switch (i) - { - case 0: assert(d == 'o'); break; - case 1: assert(d == 'l'); break; - case 2: assert(d == 'l'); break; - case 3: assert(d == 'e'); break; - case 4: assert(d == 'h'); break; - default: assert(0); - } - i++; - } - assert(i == 5); - - s = "a\u1234\U00100456b"; - i = 0; - foreach_reverse(dchar d; s) - { - //printf("i = %d, d = %x\n", i, d); - switch (i) - { - case 0: assert(d == 'b'); break; - case 1: assert(d == '\U00100456'); break; - case 2: assert(d == '\u1234'); break; - case 3: assert(d == 'a'); break; - default: assert(0); - } - i++; - } - assert(i == 4); -} - -/*****************************/ - -extern (C) int _aApplyRcw1(in char[] aa, dg_t dg) -{ int result; - - debug(apply) printf("_aApplyRcw1(), len = %d\n", aa.length); - for (size_t i = aa.length; i != 0; ) - { dchar d; - wchar w; - - i--; - w = aa[i]; - if (w & 0x80) - { char c = cast(char)w; - uint j; - uint m = 0x3F; - d = 0; - while ((c & 0xC0) != 0xC0) - { if (i == 0) - onUnicodeError("Invalid UTF-8 sequence", 0); - i--; - d |= (c & 0x3F) << j; - j += 6; - m >>= 1; - c = aa[i]; - } - d |= (c & m) << j; - - if (d <= 0xFFFF) - w = cast(wchar) d; - else - { - w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); - result = dg(cast(void *)&w); - if (result) - break; - w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00); - } - } - result = dg(cast(void *)&w); - if (result) - break; - } - return result; -} - -unittest -{ - debug(apply) printf("_aApplyRcw1.unittest\n"); - - auto s = "hello"c[]; - int i; - - foreach_reverse(wchar d; s) - { - switch (i) - { - case 0: assert(d == 'o'); break; - case 1: assert(d == 'l'); break; - case 2: assert(d == 'l'); break; - case 3: assert(d == 'e'); break; - case 4: assert(d == 'h'); break; - default: assert(0); - } - i++; - } - assert(i == 5); - - s = "a\u1234\U00100456b"; - i = 0; - foreach_reverse(wchar d; s) - { - //printf("i = %d, d = %x\n", i, d); - switch (i) - { - case 0: assert(d == 'b'); break; - case 1: assert(d == 0xDBC1); break; - case 2: assert(d == 0xDC56); break; - case 3: assert(d == 0x1234); break; - case 4: assert(d == 'a'); break; - default: assert(0); - } - i++; - } - assert(i == 5); -} - -/*****************************/ - -extern (C) int _aApplyRwc1(in wchar[] aa, dg_t dg) -{ int result; - - debug(apply) printf("_aApplyRwc1(), len = %d\n", aa.length); - for (size_t i = aa.length; i != 0; ) - { dchar d; - char c; - - i--; - d = aa[i]; - if (d >= 0xDC00 && d <= 0xDFFF) - { if (i == 0) - onUnicodeError("Invalid UTF-16 sequence", 0); - i--; - d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00); - } - - if (d & ~0x7F) - { - char[4] buf; - - auto b = toUTF8(buf, d); - foreach (char c2; b) - { - result = dg(cast(void *)&c2); - if (result) - return result; - } - continue; - } - c = cast(char)d; - result = dg(cast(void *)&c); - if (result) - break; - } - return result; -} - -unittest -{ - debug(apply) printf("_aApplyRwc1.unittest\n"); - - auto s = "hello"w[]; - int i; - - foreach_reverse(char d; s) - { - switch (i) - { - case 0: assert(d == 'o'); break; - case 1: assert(d == 'l'); break; - case 2: assert(d == 'l'); break; - case 3: assert(d == 'e'); break; - case 4: assert(d == 'h'); break; - default: assert(0); - } - i++; - } - assert(i == 5); - - s = "a\u1234\U00100456b"; - i = 0; - foreach_reverse(char d; s) - { - //printf("i = %d, d = %x\n", i, d); - switch (i) - { - case 0: assert(d == 'b'); break; - case 1: assert(d == 0xF4); break; - case 2: assert(d == 0x80); break; - case 3: assert(d == 0x91); break; - case 4: assert(d == 0x96); break; - case 5: assert(d == 0xE1); break; - case 6: assert(d == 0x88); break; - case 7: assert(d == 0xB4); break; - case 8: assert(d == 'a'); break; - default: assert(0); - } - i++; - } - assert(i == 9); -} - -/*****************************/ - -extern (C) int _aApplyRdc1(in dchar[] aa, dg_t dg) -{ int result; - - debug(apply) printf("_aApplyRdc1(), len = %d\n", aa.length); - for (size_t i = aa.length; i != 0;) - { dchar d = aa[--i]; - char c; - - if (d & ~0x7F) - { - char[4] buf; - - auto b = toUTF8(buf, d); - foreach (char c2; b) - { - result = dg(cast(void *)&c2); - if (result) - return result; - } - continue; - } - else - { - c = cast(char)d; - } - result = dg(cast(void *)&c); - if (result) - break; - } - return result; -} - -unittest -{ - debug(apply) printf("_aApplyRdc1.unittest\n"); - - auto s = "hello"d[]; - int i; - - foreach_reverse(char d; s) - { - switch (i) - { - case 0: assert(d == 'o'); break; - case 1: assert(d == 'l'); break; - case 2: assert(d == 'l'); break; - case 3: assert(d == 'e'); break; - case 4: assert(d == 'h'); break; - default: assert(0); - } - i++; - } - assert(i == 5); - - s = "a\u1234\U00100456b"; - i = 0; - foreach_reverse(char d; s) - { - //printf("i = %d, d = %x\n", i, d); - switch (i) - { - case 0: assert(d == 'b'); break; - case 1: assert(d == 0xF4); break; - case 2: assert(d == 0x80); break; - case 3: assert(d == 0x91); break; - case 4: assert(d == 0x96); break; - case 5: assert(d == 0xE1); break; - case 6: assert(d == 0x88); break; - case 7: assert(d == 0xB4); break; - case 8: assert(d == 'a'); break; - default: assert(0); - } - i++; - } - assert(i == 9); -} - -/*****************************/ - -extern (C) int _aApplyRdw1(in dchar[] aa, dg_t dg) -{ int result; - - debug(apply) printf("_aApplyRdw1(), len = %d\n", aa.length); - for (size_t i = aa.length; i != 0; ) - { dchar d = aa[--i]; - wchar w; - - if (d <= 0xFFFF) - w = cast(wchar) d; - else - { - w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); - result = dg(cast(void *)&w); - if (result) - break; - w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00); - } - result = dg(cast(void *)&w); - if (result) - break; - } - return result; -} - -unittest -{ - debug(apply) printf("_aApplyRdw1.unittest\n"); - - auto s = "hello"d[]; - int i; - - foreach_reverse(wchar d; s) - { - switch (i) - { - case 0: assert(d == 'o'); break; - case 1: assert(d == 'l'); break; - case 2: assert(d == 'l'); break; - case 3: assert(d == 'e'); break; - case 4: assert(d == 'h'); break; - default: assert(0); - } - i++; - } - assert(i == 5); - - s = "a\u1234\U00100456b"; - i = 0; - foreach_reverse(wchar d; s) - { - //printf("i = %d, d = %x\n", i, d); - switch (i) - { - case 0: assert(d == 'b'); break; - case 1: assert(d == 0xDBC1); break; - case 2: assert(d == 0xDC56); break; - case 3: assert(d == 0x1234); break; - case 4: assert(d == 'a'); break; - default: assert(0); - } - i++; - } - assert(i == 5); -} - - -/****************************************************************************/ -/* 2 argument versions */ - -// dg is D, but _aApplyRcd2() is C -extern (D) typedef int delegate(void *, void *) dg2_t; - -extern (C) int _aApplyRcd2(in char[] aa, dg2_t dg) -{ int result; - size_t i; - size_t len = aa.length; - - debug(apply) printf("_aApplyRcd2(), len = %d\n", len); - for (i = len; i != 0; ) - { dchar d; - - i--; - d = aa[i]; - if (d & 0x80) - { char c = cast(char)d; - uint j; - uint m = 0x3F; - d = 0; - while ((c & 0xC0) != 0xC0) - { if (i == 0) - onUnicodeError("Invalid UTF-8 sequence", 0); - i--; - d |= (c & 0x3F) << j; - j += 6; - m >>= 1; - c = aa[i]; - } - d |= (c & m) << j; - } - result = dg(&i, cast(void *)&d); - if (result) - break; - } - return result; -} - -unittest -{ - debug(apply) printf("_aApplyRcd2.unittest\n"); - - auto s = "hello"c[]; - int i; - - foreach_reverse(k, dchar d; s) - { - assert(k == 4 - i); - switch (i) - { - case 0: assert(d == 'o'); break; - case 1: assert(d == 'l'); break; - case 2: assert(d == 'l'); break; - case 3: assert(d == 'e'); break; - case 4: assert(d == 'h'); break; - default: assert(0); - } - i++; - } - assert(i == 5); - - s = "a\u1234\U00100456b"; - i = 0; - foreach_reverse(k, dchar d; s) - { - //printf("i = %d, k = %d, d = %x\n", i, k, d); - switch (i) - { - case 0: assert(d == 'b'); assert(k == 8); break; - case 1: assert(d == '\U00100456'); assert(k == 4); break; - case 2: assert(d == '\u1234'); assert(k == 1); break; - case 3: assert(d == 'a'); assert(k == 0); break; - default: assert(0); - } - i++; - } - assert(i == 4); -} - -/*****************************/ - -extern (C) int _aApplyRwd2(in wchar[] aa, dg2_t dg) -{ int result; - - debug(apply) printf("_aApplyRwd2(), len = %d\n", aa.length); - for (size_t i = aa.length; i != 0; ) - { dchar d; - - i--; - d = aa[i]; - if (d >= 0xDC00 && d <= 0xDFFF) - { if (i == 0) - onUnicodeError("Invalid UTF-16 sequence", 0); - i--; - d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00); - } - result = dg(&i, cast(void *)&d); - if (result) - break; - } - return result; -} - -unittest -{ - debug(apply) printf("_aApplyRwd2.unittest\n"); - - auto s = "hello"w[]; - int i; - - foreach_reverse(k, dchar d; s) - { - //printf("i = %d, k = %d, d = %x\n", i, k, d); - assert(k == 4 - i); - switch (i) - { - case 0: assert(d == 'o'); break; - case 1: assert(d == 'l'); break; - case 2: assert(d == 'l'); break; - case 3: assert(d == 'e'); break; - case 4: assert(d == 'h'); break; - default: assert(0); - } - i++; - } - assert(i == 5); - - s = "a\u1234\U00100456b"; - i = 0; - foreach_reverse(k, dchar d; s) - { - //printf("i = %d, k = %d, d = %x\n", i, k, d); - switch (i) - { - case 0: assert(k == 4); assert(d == 'b'); break; - case 1: assert(k == 2); assert(d == '\U00100456'); break; - case 2: assert(k == 1); assert(d == '\u1234'); break; - case 3: assert(k == 0); assert(d == 'a'); break; - default: assert(0); - } - i++; - } - assert(i == 4); -} - -/*****************************/ - -extern (C) int _aApplyRcw2(in char[] aa, dg2_t dg) -{ int result; - - debug(apply) printf("_aApplyRcw2(), len = %d\n", aa.length); - for (size_t i = aa.length; i != 0; ) - { dchar d; - wchar w; - - i--; - w = aa[i]; - if (w & 0x80) - { char c = cast(char)w; - uint j; - uint m = 0x3F; - d = 0; - while ((c & 0xC0) != 0xC0) - { if (i == 0) - onUnicodeError("Invalid UTF-8 sequence", 0); - i--; - d |= (c & 0x3F) << j; - j += 6; - m >>= 1; - c = aa[i]; - } - d |= (c & m) << j; - - if (d <= 0xFFFF) - w = cast(wchar) d; - else - { - w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); - result = dg(&i, cast(void *)&w); - if (result) - break; - w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00); - } - } - result = dg(&i, cast(void *)&w); - if (result) - break; - } - return result; -} - -unittest -{ - debug(apply) printf("_aApplyRcw2.unittest\n"); - - auto s = "hello"c[]; - int i; - - foreach_reverse(k, wchar d; s) - { - //printf("i = %d, k = %d, d = %x\n", i, k, d); - assert(k == 4 - i); - switch (i) - { - case 0: assert(d == 'o'); break; - case 1: assert(d == 'l'); break; - case 2: assert(d == 'l'); break; - case 3: assert(d == 'e'); break; - case 4: assert(d == 'h'); break; - default: assert(0); - } - i++; - } - assert(i == 5); - - s = "a\u1234\U00100456b"; - i = 0; - foreach_reverse(k, wchar d; s) - { - //printf("i = %d, k = %d, d = %x\n", i, k, d); - switch (i) - { - case 0: assert(k == 8); assert(d == 'b'); break; - case 1: assert(k == 4); assert(d == 0xDBC1); break; - case 2: assert(k == 4); assert(d == 0xDC56); break; - case 3: assert(k == 1); assert(d == 0x1234); break; - case 4: assert(k == 0); assert(d == 'a'); break; - default: assert(0); - } - i++; - } - assert(i == 5); -} - -/*****************************/ - -extern (C) int _aApplyRwc2(in wchar[] aa, dg2_t dg) -{ int result; - - debug(apply) printf("_aApplyRwc2(), len = %d\n", aa.length); - for (size_t i = aa.length; i != 0; ) - { dchar d; - char c; - - i--; - d = aa[i]; - if (d >= 0xDC00 && d <= 0xDFFF) - { if (i == 0) - onUnicodeError("Invalid UTF-16 sequence", 0); - i--; - d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00); - } - - if (d & ~0x7F) - { - char[4] buf; - - auto b = toUTF8(buf, d); - foreach (char c2; b) - { - result = dg(&i, cast(void *)&c2); - if (result) - return result; - } - continue; - } - c = cast(char)d; - result = dg(&i, cast(void *)&c); - if (result) - break; - } - return result; -} - -unittest -{ - debug(apply) printf("_aApplyRwc2.unittest\n"); - - auto s = "hello"w[]; - int i; - - foreach_reverse(k, char d; s) - { - //printf("i = %d, k = %d, d = %x\n", i, k, d); - assert(k == 4 - i); - switch (i) - { - case 0: assert(d == 'o'); break; - case 1: assert(d == 'l'); break; - case 2: assert(d == 'l'); break; - case 3: assert(d == 'e'); break; - case 4: assert(d == 'h'); break; - default: assert(0); - } - i++; - } - assert(i == 5); - - s = "a\u1234\U00100456b"; - i = 0; - foreach_reverse(k, char d; s) - { - //printf("i = %d, k = %d, d = %x\n", i, k, d); - switch (i) - { - case 0: assert(k == 4); assert(d == 'b'); break; - case 1: assert(k == 2); assert(d == 0xF4); break; - case 2: assert(k == 2); assert(d == 0x80); break; - case 3: assert(k == 2); assert(d == 0x91); break; - case 4: assert(k == 2); assert(d == 0x96); break; - case 5: assert(k == 1); assert(d == 0xE1); break; - case 6: assert(k == 1); assert(d == 0x88); break; - case 7: assert(k == 1); assert(d == 0xB4); break; - case 8: assert(k == 0); assert(d == 'a'); break; - default: assert(0); - } - i++; - } - assert(i == 9); -} - -/*****************************/ - -extern (C) int _aApplyRdc2(in dchar[] aa, dg2_t dg) -{ int result; - - debug(apply) printf("_aApplyRdc2(), len = %d\n", aa.length); - for (size_t i = aa.length; i != 0; ) - { dchar d = aa[--i]; - char c; - - if (d & ~0x7F) - { - char[4] buf; - - auto b = toUTF8(buf, d); - foreach (char c2; b) - { - result = dg(&i, cast(void *)&c2); - if (result) - return result; - } - continue; - } - else - { c = cast(char)d; - } - result = dg(&i, cast(void *)&c); - if (result) - break; - } - return result; -} - -unittest -{ - debug(apply) printf("_aApplyRdc2.unittest\n"); - - auto s = "hello"d[]; - int i; - - foreach_reverse(k, char d; s) - { - //printf("i = %d, k = %d, d = %x\n", i, k, d); - assert(k == 4 - i); - switch (i) - { - case 0: assert(d == 'o'); break; - case 1: assert(d == 'l'); break; - case 2: assert(d == 'l'); break; - case 3: assert(d == 'e'); break; - case 4: assert(d == 'h'); break; - default: assert(0); - } - i++; - } - assert(i == 5); - - s = "a\u1234\U00100456b"; - i = 0; - foreach_reverse(k, char d; s) - { - //printf("i = %d, k = %d, d = %x\n", i, k, d); - switch (i) - { - case 0: assert(k == 3); assert(d == 'b'); break; - case 1: assert(k == 2); assert(d == 0xF4); break; - case 2: assert(k == 2); assert(d == 0x80); break; - case 3: assert(k == 2); assert(d == 0x91); break; - case 4: assert(k == 2); assert(d == 0x96); break; - case 5: assert(k == 1); assert(d == 0xE1); break; - case 6: assert(k == 1); assert(d == 0x88); break; - case 7: assert(k == 1); assert(d == 0xB4); break; - case 8: assert(k == 0); assert(d == 'a'); break; - default: assert(0); - } - i++; - } - assert(i == 9); -} - -/*****************************/ - -extern (C) int _aApplyRdw2(in dchar[] aa, dg2_t dg) -{ int result; - - debug(apply) printf("_aApplyRdw2(), len = %d\n", aa.length); - for (size_t i = aa.length; i != 0; ) - { dchar d = aa[--i]; - wchar w; - - if (d <= 0xFFFF) - w = cast(wchar) d; - else - { - w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); - result = dg(&i, cast(void *)&w); - if (result) - break; - w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00); - } - result = dg(&i, cast(void *)&w); - if (result) - break; - } - return result; -} - -unittest -{ - debug(apply) printf("_aApplyRdw2.unittest\n"); - - auto s = "hello"d[]; - int i; - - foreach_reverse(k, wchar d; s) - { - //printf("i = %d, k = %d, d = %x\n", i, k, d); - assert(k == 4 - i); - switch (i) - { - case 0: assert(d == 'o'); break; - case 1: assert(d == 'l'); break; - case 2: assert(d == 'l'); break; - case 3: assert(d == 'e'); break; - case 4: assert(d == 'h'); break; - default: assert(0); - } - i++; - } - assert(i == 5); - - s = "a\u1234\U00100456b"; - i = 0; - foreach_reverse(k, wchar d; s) - { - //printf("i = %d, k = %d, d = %x\n", i, k, d); - switch (i) - { - case 0: assert(k == 3); assert(d == 'b'); break; - case 1: assert(k == 2); assert(d == 0xDBC1); break; - case 2: assert(k == 2); assert(d == 0xDC56); break; - case 3: assert(k == 1); assert(d == 0x1234); break; - case 4: assert(k == 0); assert(d == 'a'); break; - default: assert(0); - } - i++; - } - assert(i == 5); -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/aaA.d --- a/druntime/src/compiler/ldc/aaA.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,872 +0,0 @@ -/** - * Implementation of associative arrays. - * - * Copyright: Copyright Digital Mars 2000 - 2009. - * License: aa.a.b.length * 4) - { - //printf("rehash\n"); - _aaRehash(aa,keyti); - } - -Lret: - return cast(void *)(e + 1) + keysize; -} - - -/************************************************* - * Get pointer to value in associative array indexed by key. - * Returns null if it is not already there. - */ - -void* _aaGetRvalue(AA aa, TypeInfo keyti, size_t valuesize, ...) -{ - //printf("_aaGetRvalue(valuesize = %u)\n", valuesize); - if (!aa.a) - return null; - - auto pkey = cast(void *)(&valuesize + 1); - auto keysize = aligntsize(keyti.tsize()); - auto len = aa.a.b.length; - - if (len) - { - auto key_hash = keyti.getHash(pkey); - //printf("hash = %d\n", key_hash); - size_t i = key_hash % len; - auto e = aa.a.b[i]; - while (e !is null) - { - if (key_hash == e.hash) - { - auto c = keyti.compare(pkey, e + 1); - if (c == 0) - return cast(void *)(e + 1) + keysize; - e = (c < 0) ? e.left : e.right; - } - else - e = (key_hash < e.hash) ? e.left : e.right; - } - } - return null; // not found, caller will throw exception -} - - -/************************************************* - * Determine if key is in aa. - * Returns: - * null not in aa - * !=null in aa, return pointer to value - */ - -void* _aaIn(AA aa, TypeInfo keyti, ...) -in -{ -} -out (result) -{ - //assert(result == 0 || result == 1); -} -body -{ - if (aa.a) - { - auto pkey = cast(void *)(&keyti + 1); - - //printf("_aaIn(), .length = %d, .ptr = %x\n", aa.a.length, cast(uint)aa.a.ptr); - auto len = aa.a.b.length; - - if (len) - { - auto key_hash = keyti.getHash(pkey); - //printf("hash = %d\n", key_hash); - size_t i = key_hash % len; - auto e = aa.a.b[i]; - while (e !is null) - { - if (key_hash == e.hash) - { - auto c = keyti.compare(pkey, e + 1); - if (c == 0) - return cast(void *)(e + 1) + aligntsize(keyti.tsize()); - e = (c < 0) ? e.left : e.right; - } - else - e = (key_hash < e.hash) ? e.left : e.right; - } - } - } - - // Not found - return null; -} - -/************************************************* - * Delete key entry in aa[]. - * If key is not in aa[], do nothing. - */ - -void _aaDel(AA aa, TypeInfo keyti, ...) -{ - auto pkey = cast(void *)(&keyti + 1); - aaA *e; - - if (aa.a && aa.a.b.length) - { - auto key_hash = keyti.getHash(pkey); - //printf("hash = %d\n", key_hash); - size_t i = key_hash % aa.a.b.length; - auto pe = &aa.a.b[i]; - while ((e = *pe) !is null) // null means not found - { - if (key_hash == e.hash) - { - auto c = keyti.compare(pkey, e + 1); - if (c == 0) - { - if (!e.left && !e.right) - { - *pe = null; - } - else if (e.left && !e.right) - { - *pe = e.left; - e.left = null; - } - else if (!e.left && e.right) - { - *pe = e.right; - e.right = null; - } - else - { - *pe = e.left; - e.left = null; - do - pe = &(*pe).right; - while (*pe); - *pe = e.right; - e.right = null; - } - - aa.a.nodes--; - gc_free(e); - break; - } - pe = (c < 0) ? &e.left : &e.right; - } - else - pe = (key_hash < e.hash) ? &e.left : &e.right; - } - } -} - - -/******************************************** - * Produce array of values from aa. - */ - -ArrayRet_t _aaValues(AA aa, size_t keysize, size_t valuesize) -in -{ - assert(keysize == aligntsize(keysize)); -} -body -{ - size_t resi; - Array a; - - void _aaValues_x(aaA* e) - { - do - { - memcpy(a.ptr + resi * valuesize, - cast(byte*)e + aaA.sizeof + keysize, - valuesize); - resi++; - if (e.left) - { if (!e.right) - { e = e.left; - continue; - } - _aaValues_x(e.left); - } - e = e.right; - } while (e !is null); - } - - if (aa.a) - { - a.length = _aaLen(aa); - a.ptr = cast(byte*) gc_malloc(a.length * valuesize, - valuesize < (void*).sizeof ? BlkAttr.NO_SCAN : 0); - resi = 0; - foreach (e; aa.a.b) - { - if (e) - _aaValues_x(e); - } - assert(resi == a.length); - } - return *cast(ArrayRet_t*)(&a); -} - - -/******************************************** - * Rehash an array. - */ - -void* _aaRehash(AA* paa, TypeInfo keyti) -in -{ - //_aaInvAh(paa); -} -out (result) -{ - //_aaInvAh(result); -} -body -{ - BB newb; - - void _aaRehash_x(aaA* olde) - { - while (1) - { - auto left = olde.left; - auto right = olde.right; - olde.left = null; - olde.right = null; - - aaA *e; - - //printf("rehash %p\n", olde); - auto key_hash = olde.hash; - size_t i = key_hash % newb.b.length; - auto pe = &newb.b[i]; - while ((e = *pe) !is null) - { - //printf("\te = %p, e.left = %p, e.right = %p\n", e, e.left, e.right); - assert(e.left != e); - assert(e.right != e); - if (key_hash == e.hash) - { - auto c = keyti.compare(olde + 1, e + 1); - assert(c != 0); - pe = (c < 0) ? &e.left : &e.right; - } - else - pe = (key_hash < e.hash) ? &e.left : &e.right; - } - *pe = olde; - - if (right) - { - if (!left) - { olde = right; - continue; - } - _aaRehash_x(right); - } - if (!left) - break; - olde = left; - } - } - - //printf("Rehash\n"); - if (paa.a) - { - auto aa = paa.a; - auto len = _aaLen(*paa); - if (len) - { size_t i; - - for (i = 0; i < prime_list.length - 1; i++) - { - if (len <= prime_list[i]) - break; - } - len = prime_list[i]; - newb.b = new aaA*[len]; - - foreach (e; aa.b) - { - if (e) - _aaRehash_x(e); - } - delete aa.b; - - newb.nodes = aa.nodes; - newb.keyti = aa.keyti; - } - - *paa.a = newb; - _aaBalance(paa); - } - return (*paa).a; -} - -/******************************************** - * Balance an array. - */ - -void _aaBalance(AA* paa) -{ - //printf("_aaBalance()\n"); - if (paa.a) - { - aaA*[16] tmp; - aaA*[] array = tmp; - auto aa = paa.a; - foreach (j, e; aa.b) - { - /* Temporarily store contents of bucket in array[] - */ - size_t k = 0; - void addToArray(aaA* e) - { - while (e) - { addToArray(e.left); - if (k == array.length) - array.length = array.length * 2; - array[k++] = e; - e = e.right; - } - } - addToArray(e); - /* The contents of the bucket are now sorted into array[]. - * Rebuild the tree. - */ - void buildTree(aaA** p, size_t x1, size_t x2) - { - if (x1 >= x2) - *p = null; - else - { auto mid = (x1 + x2) >> 1; - *p = array[mid]; - buildTree(&(*p).left, x1, mid); - buildTree(&(*p).right, mid + 1, x2); - } - } - auto p = &aa.b[j]; - buildTree(p, 0, k); - } - } -} -/******************************************** - * Produce array of N byte keys from aa. - */ - -ArrayRet_t _aaKeys(AA aa, size_t keysize) -{ - byte[] res; - size_t resi; - - void _aaKeys_x(aaA* e) - { - do - { - memcpy(&res[resi * keysize], cast(byte*)(e + 1), keysize); - resi++; - if (e.left) - { if (!e.right) - { e = e.left; - continue; - } - _aaKeys_x(e.left); - } - e = e.right; - } while (e !is null); - } - - auto len = _aaLen(aa); - if (!len) - return 0; - res = (cast(byte*) gc_malloc(len * keysize, - !(aa.a.keyti.flags() & 1) ? BlkAttr.NO_SCAN : 0))[0 .. len * keysize]; - resi = 0; - foreach (e; aa.a.b) - { - if (e) - _aaKeys_x(e); - } - assert(resi == len); - - Array a; - a.length = len; - a.ptr = res.ptr; - return *cast(ArrayRet_t*)(&a); -} - - -/********************************************** - * 'apply' for associative arrays - to support foreach - */ - -// dg is D, but _aaApply() is C -extern (D) typedef int delegate(void *) dg_t; - -int _aaApply(AA aa, size_t keysize, dg_t dg) -in -{ - assert(aligntsize(keysize) == keysize); -} -body -{ int result; - - //printf("_aaApply(aa = x%llx, keysize = %d, dg = x%llx)\n", aa.a, keysize, dg); - - int treewalker(aaA* e) - { int result; - - do - { - //printf("treewalker(e = %p, dg = x%llx)\n", e, dg); - result = dg(cast(void *)(e + 1) + keysize); - if (result) - break; - if (e.right) - { if (!e.left) - { - e = e.right; - continue; - } - result = treewalker(e.right); - if (result) - break; - } - e = e.left; - } while (e); - - return result; - } - - if (aa.a) - { - foreach (e; aa.a.b) - { - if (e) - { - result = treewalker(e); - if (result) - break; - } - } - } - return result; -} - -// dg is D, but _aaApply2() is C -extern (D) typedef int delegate(void *, void *) dg2_t; - -int _aaApply2(AA aa, size_t keysize, dg2_t dg) -in -{ - assert(aligntsize(keysize) == keysize); -} -body -{ int result; - - //printf("_aaApply(aa = x%llx, keysize = %d, dg = x%llx)\n", aa.a, keysize, dg); - - int treewalker(aaA* e) - { int result; - - do - { - //printf("treewalker(e = %p, dg = x%llx)\n", e, dg); - result = dg(cast(void *)(e + 1), cast(void *)(e + 1) + keysize); - if (result) - break; - if (e.right) - { if (!e.left) - { - e = e.right; - continue; - } - result = treewalker(e.right); - if (result) - break; - } - e = e.left; - } while (e); - - return result; - } - - if (aa.a) - { - foreach (e; aa.a.b) - { - if (e) - { - result = treewalker(e); - if (result) - break; - } - } - } - return result; -} - - -/*********************************** - * Construct an associative array of type ti from - * length pairs of key/value pairs. - */ - -extern (C) -BB* _d_assocarrayliteralT(TypeInfo_AssociativeArray ti, size_t length, ...) -{ - auto valuesize = ti.next.tsize(); // value size - auto keyti = ti.key; - auto keysize = keyti.tsize(); // key size - BB* result; - - //printf("_d_assocarrayliteralT(keysize = %d, valuesize = %d, length = %d)\n", keysize, valuesize, length); - //printf("tivalue = %.*s\n", ti.next.classinfo.name); - if (length == 0 || valuesize == 0 || keysize == 0) - { - ; - } - else - { - va_list q; - va_start!(size_t)(q, length); - - result = new BB(); - result.keyti = keyti; - size_t i; - - for (i = 0; i < prime_list.length - 1; i++) - { - if (length <= prime_list[i]) - break; - } - auto len = prime_list[i]; - result.b = new aaA*[len]; - - size_t keystacksize = (keysize + int.sizeof - 1) & ~(int.sizeof - 1); - size_t valuestacksize = (valuesize + int.sizeof - 1) & ~(int.sizeof - 1); - - size_t keytsize = aligntsize(keysize); - - for (size_t j = 0; j < length; j++) - { void* pkey = q; - q += keystacksize; - void* pvalue = q; - q += valuestacksize; - aaA* e; - - auto key_hash = keyti.getHash(pkey); - //printf("hash = %d\n", key_hash); - i = key_hash % len; - auto pe = &result.b[i]; - while (1) - { - e = *pe; - if (!e) - { - // Not found, create new elem - //printf("create new one\n"); - e = cast(aaA *) cast(void*) new void[aaA.sizeof + keytsize + valuesize]; - memcpy(e + 1, pkey, keysize); - e.hash = key_hash; - *pe = e; - result.nodes++; - break; - } - if (key_hash == e.hash) - { - auto c = keyti.compare(pkey, e + 1); - if (c == 0) - break; - pe = (c < 0) ? &e.left : &e.right; - } - else - pe = (key_hash < e.hash) ? &e.left : &e.right; - } - memcpy(cast(void *)(e + 1) + keytsize, pvalue, valuesize); - } - - va_end(q); - } - return result; -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/adi.d --- a/druntime/src/compiler/ldc/adi.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,603 +0,0 @@ -/** - * Implementation of dynamic array property support routines. - * - * Copyright: Copyright Digital Mars 2000 - 2009. - * License: = lo); - } - if (lo == hi) - break; - - debug(adi) printf("\tstridelo = %d, stridehi = %d\n", stridelo, stridehi); - if (stridelo == stridehi) - { - - memcpy(tmp.ptr, lo, stridelo); - memcpy(lo, hi, stridelo); - memcpy(hi, tmp.ptr, stridelo); - lo += stridelo; - hi--; - continue; - } - - /* Shift the whole array. This is woefully inefficient - */ - memcpy(tmp.ptr, hi, stridehi); - memcpy(tmplo.ptr, lo, stridelo); - memmove(lo + stridehi, lo + stridelo , (hi - lo) - stridelo); - memcpy(lo, tmp.ptr, stridehi); - memcpy(hi + stridehi - stridelo, tmplo.ptr, stridelo); - - lo += stridehi; - hi = hi - 1 + (stridehi - stridelo); - } - } - return *cast(long*)(&a); -} - -unittest -{ - auto a = "abcd"c[]; - - auto r = a.dup.reverse; - //writefln(r); - assert(r == "dcba"); - - a = "a\u1235\u1234c"; - //writefln(a); - r = a.dup.reverse; - //writefln(r); - assert(r == "c\u1234\u1235a"); - - a = "ab\u1234c"; - //writefln(a); - r = a.dup.reverse; - //writefln(r); - assert(r == "c\u1234ba"); - - a = "\u3026\u2021\u3061\n"; - r = a.dup.reverse; - assert(r == "\n\u3061\u2021\u3026"); -} - - -/********************************************** - * Reverse array of wchars. - * Handled separately because embedded multiword encodings should not be - * reversed. - */ - -extern (C) long _adReverseWchar(wchar[] a) -{ - if (a.length > 1) - { - wchar[2] tmp; - wchar* lo = a.ptr; - wchar* hi = &a[length - 1]; - - while (lo < hi) - { auto clo = *lo; - auto chi = *hi; - - if ((clo < 0xD800 || clo > 0xDFFF) && - (chi < 0xD800 || chi > 0xDFFF)) - { - *lo = chi; - *hi = clo; - lo++; - hi--; - continue; - } - - int stridelo = 1 + (clo >= 0xD800 && clo <= 0xDBFF); - - int stridehi = 1; - if (chi >= 0xDC00 && chi <= 0xDFFF) - { - chi = *--hi; - stridehi++; - assert(hi >= lo); - } - if (lo == hi) - break; - - if (stridelo == stridehi) - { int stmp; - - assert(stridelo == 2); - assert(stmp.sizeof == 2 * (*lo).sizeof); - stmp = *cast(int*)lo; - *cast(int*)lo = *cast(int*)hi; - *cast(int*)hi = stmp; - lo += stridelo; - hi--; - continue; - } - - /* Shift the whole array. This is woefully inefficient - */ - memcpy(tmp.ptr, hi, stridehi * wchar.sizeof); - memcpy(hi + stridehi - stridelo, lo, stridelo * wchar.sizeof); - memmove(lo + stridehi, lo + stridelo , (hi - (lo + stridelo)) * wchar.sizeof); - memcpy(lo, tmp.ptr, stridehi * wchar.sizeof); - - lo += stridehi; - hi = hi - 1 + (stridehi - stridelo); - } - } - return *cast(long*)(&a); -} - -unittest -{ - wstring a = "abcd"; - - auto r = a.dup.reverse; - assert(r == "dcba"); - - a = "a\U00012356\U00012346c"; - r = a.dup.reverse; - assert(r == "c\U00012346\U00012356a"); - - a = "ab\U00012345c"; - r = a.dup.reverse; - assert(r == "c\U00012345ba"); -} - - -/********************************************** - * Support for array.reverse property. - */ - -extern (C) long _adReverse(Array a, size_t szelem) -out (result) -{ - assert(result is *cast(long*)(&a)); -} -body -{ - if (a.length >= 2) - { - byte* tmp; - byte[16] buffer; - - void* lo = a.ptr; - void* hi = a.ptr + (a.length - 1) * szelem; - - tmp = buffer.ptr; - if (szelem > 16) - { - //version (Windows) - tmp = cast(byte*) alloca(szelem); - //else - //tmp = gc_malloc(szelem); - } - - for (; lo < hi; lo += szelem, hi -= szelem) - { - memcpy(tmp, lo, szelem); - memcpy(lo, hi, szelem); - memcpy(hi, tmp, szelem); - } - - version (Windows) - { - } - else - { - //if (szelem > 16) - // BUG: bad code is generate for delete pointer, tries - // to call delclass. - //gc_free(tmp); - } - } - return *cast(long*)(&a); -} - -unittest -{ - debug(adi) printf("array.reverse.unittest\n"); - - int[] a = new int[5]; - int[] b; - size_t i; - - for (i = 0; i < 5; i++) - a[i] = i; - b = a.reverse; - assert(b is a); - for (i = 0; i < 5; i++) - assert(a[i] == 4 - i); - - struct X20 - { // More than 16 bytes in size - int a; - int b, c, d, e; - } - - X20[] c = new X20[5]; - X20[] d; - - for (i = 0; i < 5; i++) - { c[i].a = i; - c[i].e = 10; - } - d = c.reverse; - assert(d is c); - for (i = 0; i < 5; i++) - { - assert(c[i].a == 4 - i); - assert(c[i].e == 10); - } -} - -/********************************************** - * Sort array of chars. - */ - -extern (C) long _adSortChar(char[] a) -{ - if (a.length > 1) - { - dstring da = toUTF32(a); - da.sort; - size_t i = 0; - foreach (dchar d; da) - { char[4] buf; - auto t = toUTF8(buf, d); - a[i .. i + t.length] = t[]; - i += t.length; - } - delete da; - } - return *cast(long*)(&a); -} - -/********************************************** - * Sort array of wchars. - */ - -extern (C) long _adSortWchar(wchar[] a) -{ - if (a.length > 1) - { - dstring da = toUTF32(a); - da.sort; - size_t i = 0; - foreach (dchar d; da) - { wchar[2] buf; - auto t = toUTF16(buf, d); - a[i .. i + t.length] = t[]; - i += t.length; - } - delete da; - } - return *cast(long*)(&a); -} - -/*************************************** - * Support for array equality test. - * Returns: - * 1 equal - * 0 not equal - */ - -extern (C) int _adEq(Array a1, Array a2, TypeInfo ti) -{ - debug(adi) printf("_adEq(a1.length = %d, a2.length = %d)\n", a1.length, a2.length); - if (a1.length != a2.length) - return 0; // not equal - auto sz = ti.tsize(); - auto p1 = a1.ptr; - auto p2 = a2.ptr; - - if (sz == 1) - // We should really have a ti.isPOD() check for this - return (memcmp(p1, p2, a1.length) == 0); - - for (size_t i = 0; i < a1.length; i++) - { - if (!ti.equals(p1 + i * sz, p2 + i * sz)) - return 0; // not equal - } - return 1; // equal -} - -extern (C) int _adEq2(Array a1, Array a2, TypeInfo ti) -{ - debug(adi) printf("_adEq2(a1.length = %d, a2.length = %d)\n", a1.length, a2.length); - if (a1.length != a2.length) - return 0; // not equal - if (!ti.equals(&a1, &a2)) - return 0; - return 1; -} -unittest -{ - debug(adi) printf("array.Eq unittest\n"); - - auto a = "hello"c; - - assert(a != "hel"); - assert(a != "helloo"); - assert(a != "betty"); - assert(a == "hello"); - assert(a != "hxxxx"); -} - -/*************************************** - * Support for array compare test. - */ - -extern (C) int _adCmp(Array a1, Array a2, TypeInfo ti) -{ - debug(adi) printf("adCmp()\n"); - auto len = a1.length; - if (a2.length < len) - len = a2.length; - auto sz = ti.tsize(); - void *p1 = a1.ptr; - void *p2 = a2.ptr; - - if (sz == 1) - { // We should really have a ti.isPOD() check for this - auto c = memcmp(p1, p2, len); - if (c) - return c; - } - else - { - for (size_t i = 0; i < len; i++) - { - auto c = ti.compare(p1 + i * sz, p2 + i * sz); - if (c) - return c; - } - } - if (a1.length == a2.length) - return 0; - return (a1.length > a2.length) ? 1 : -1; -} - -extern (C) int _adCmp2(Array a1, Array a2, TypeInfo ti) -{ - debug(adi) printf("_adCmp2(a1.length = %d, a2.length = %d)\n", a1.length, a2.length); - return ti.compare(&a1, &a2); -} -unittest -{ - debug(adi) printf("array.Cmp unittest\n"); - - auto a = "hello"c; - - assert(a > "hel"); - assert(a >= "hel"); - assert(a < "helloo"); - assert(a <= "helloo"); - assert(a > "betty"); - assert(a >= "betty"); - assert(a == "hello"); - assert(a <= "hello"); - assert(a >= "hello"); -} - -/*************************************** - * Support for array compare test. - */ - -extern (C) int _adCmpChar(Array a1, Array a2) -{ - version (X86) - { - asm - { naked ; - - push EDI ; - push ESI ; - - mov ESI,a1+4[4+ESP] ; - mov EDI,a2+4[4+ESP] ; - - mov ECX,a1[4+ESP] ; - mov EDX,a2[4+ESP] ; - - cmp ECX,EDX ; - jb GotLength ; - - mov ECX,EDX ; - -GotLength: - cmp ECX,4 ; - jb DoBytes ; - - // Do alignment if neither is dword aligned - test ESI,3 ; - jz Aligned ; - - test EDI,3 ; - jz Aligned ; -DoAlign: - mov AL,[ESI] ; //align ESI to dword bounds - mov DL,[EDI] ; - - cmp AL,DL ; - jnz Unequal ; - - inc ESI ; - inc EDI ; - - test ESI,3 ; - - lea ECX,[ECX-1] ; - jnz DoAlign ; -Aligned: - mov EAX,ECX ; - - // do multiple of 4 bytes at a time - - shr ECX,2 ; - jz TryOdd ; - - repe ; - cmpsd ; - - jnz UnequalQuad ; - -TryOdd: - mov ECX,EAX ; -DoBytes: - // if still equal and not end of string, do up to 3 bytes slightly - // slower. - - and ECX,3 ; - jz Equal ; - - repe ; - cmpsb ; - - jnz Unequal ; -Equal: - mov EAX,a1[4+ESP] ; - mov EDX,a2[4+ESP] ; - - sub EAX,EDX ; - pop ESI ; - - pop EDI ; - ret ; - -UnequalQuad: - mov EDX,[EDI-4] ; - mov EAX,[ESI-4] ; - - cmp AL,DL ; - jnz Unequal ; - - cmp AH,DH ; - jnz Unequal ; - - shr EAX,16 ; - - shr EDX,16 ; - - cmp AL,DL ; - jnz Unequal ; - - cmp AH,DH ; -Unequal: - sbb EAX,EAX ; - pop ESI ; - - or EAX,1 ; - pop EDI ; - - ret ; - } - } - else - { - int len; - int c; - - debug(adi) printf("adCmpChar()\n"); - len = a1.length; - if (a2.length < len) - len = a2.length; - c = memcmp(cast(char *)a1.ptr, cast(char *)a2.ptr, len); - if (!c) - c = cast(int)a1.length - cast(int)a2.length; - return c; - } -} - -unittest -{ - debug(adi) printf("array.CmpChar unittest\n"); - - auto a = "hello"c; - - assert(a > "hel"); - assert(a >= "hel"); - assert(a < "helloo"); - assert(a <= "helloo"); - assert(a > "betty"); - assert(a >= "betty"); - assert(a == "hello"); - assert(a <= "hello"); - assert(a >= "hello"); -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/alloca.d --- a/druntime/src/compiler/ldc/alloca.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,135 +0,0 @@ -/** - * Implementation of alloca() standard C routine. - * - * Copyright: Copyright Digital Mars 1990 - 2009. - * License: Boost License 1.0. - * Authors: Walter Bright, based on code originally written by Burton Radons - * - * Copyright Digital Mars 2008 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module rt.arraybyte; - -import rt.util.cpuid; - -version (unittest) -{ - private import core.stdc.stdio : printf; - /* This is so unit tests will test every CPU variant - */ - int cpuid; - const int CPUID_MAX = 4; - bool mmx() { return cpuid == 1 && rt.util.cpuid.mmx(); } - bool sse() { return cpuid == 2 && rt.util.cpuid.sse(); } - bool sse2() { return cpuid == 3 && rt.util.cpuid.sse2(); } - bool amd3dnow() { return cpuid == 4 && rt.util.cpuid.amd3dnow(); } -} -else -{ - alias rt.util.cpuid.mmx mmx; - alias rt.util.cpuid.sse sse; - alias rt.util.cpuid.sse2 sse2; - alias rt.util.cpuid.amd3dnow amd3dnow; -} - -//version = log; - -bool disjoint(T)(T[] a, T[] b) -{ - return (a.ptr + a.length <= b.ptr || b.ptr + b.length <= a.ptr); -} - -alias byte T; - -extern (C): - -/* ======================================================================== */ - - -/*********************** - * Computes: - * a[] = b[] + value - */ - -T[] _arraySliceExpAddSliceAssign_a(T[] a, T value, T[] b) -{ - return _arraySliceExpAddSliceAssign_g(a, value, b); -} - -T[] _arraySliceExpAddSliceAssign_h(T[] a, T value, T[] b) -{ - return _arraySliceExpAddSliceAssign_g(a, value, b); -} - -T[] _arraySliceExpAddSliceAssign_g(T[] a, T value, T[] b) -in -{ - assert(a.length == b.length); - assert(disjoint(a, b)); -} -body -{ - //printf("_arraySliceExpAddSliceAssign_g()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 1088% faster - if (sse2() && a.length >= 64) - { - auto n = aptr + (a.length & ~63); - - uint l = cast(ubyte) value; - l |= (l << 8); - l |= (l << 16); - - if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM4, l; - pshufd XMM4, XMM4, 0; - - align 8; - startaddsse2u: - add ESI, 64; - movdqu XMM0, [EAX]; - movdqu XMM1, [EAX+16]; - movdqu XMM2, [EAX+32]; - movdqu XMM3, [EAX+48]; - add EAX, 64; - paddb XMM0, XMM4; - paddb XMM1, XMM4; - paddb XMM2, XMM4; - paddb XMM3, XMM4; - movdqu [ESI -64], XMM0; - movdqu [ESI+16-64], XMM1; - movdqu [ESI+32-64], XMM2; - movdqu [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startaddsse2u; - - mov aptr, ESI; - mov bptr, EAX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM4, l; - pshufd XMM4, XMM4, 0; - - align 8; - startaddsse2a: - add ESI, 64; - movdqa XMM0, [EAX]; - movdqa XMM1, [EAX+16]; - movdqa XMM2, [EAX+32]; - movdqa XMM3, [EAX+48]; - add EAX, 64; - paddb XMM0, XMM4; - paddb XMM1, XMM4; - paddb XMM2, XMM4; - paddb XMM3, XMM4; - movdqa [ESI -64], XMM0; - movdqa [ESI+16-64], XMM1; - movdqa [ESI+32-64], XMM2; - movdqa [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startaddsse2a; - - mov aptr, ESI; - mov bptr, EAX; - } - } - } - else - // MMX version is 1000% faster - if (mmx() && a.length >= 32) - { - auto n = aptr + (a.length & ~31); - - uint l = cast(ubyte) value; - l |= (l << 8); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd MM4, l; - pshufw MM4, MM4, 0; - - align 4; - startaddmmx: - add ESI, 32; - movq MM0, [EAX]; - movq MM1, [EAX+8]; - movq MM2, [EAX+16]; - movq MM3, [EAX+24]; - add EAX, 32; - paddb MM0, MM4; - paddb MM1, MM4; - paddb MM2, MM4; - paddb MM3, MM4; - movq [ESI -32], MM0; - movq [ESI+8 -32], MM1; - movq [ESI+16-32], MM2; - movq [ESI+24-32], MM3; - cmp ESI, EDI; - jb startaddmmx; - - emms; - mov aptr, ESI; - mov bptr, EAX; - } - } - /* trying to be fair and treat normal 32-bit cpu the same way as we do - * the SIMD units, with unrolled asm. There's not enough registers, - * really. - */ - else - if (a.length >= 4) - { - - auto n = aptr + (a.length & ~3); - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov CL, value; - - align 4; - startadd386: - add ESI, 4; - mov DX, [EAX]; - mov BX, [EAX+2]; - add EAX, 4; - add BL, CL; - add BH, CL; - add DL, CL; - add DH, CL; - mov [ESI -4], DX; - mov [ESI+2 -4], BX; - cmp ESI, EDI; - jb startadd386; - - mov aptr, ESI; - mov bptr, EAX; - } - - } - } - - while (aptr < aend) - *aptr++ = cast(T)(*bptr++ + value); - - return a; -} - -unittest -{ - printf("_arraySliceExpAddSliceAssign_g unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] + 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] + 6)) - { - printf("[%d]: %d != %d + 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] + c[] - */ - -T[] _arraySliceSliceAddSliceAssign_a(T[] a, T[] c, T[] b) -{ - return _arraySliceSliceAddSliceAssign_g(a, c, b); -} - -T[] _arraySliceSliceAddSliceAssign_h(T[] a, T[] c, T[] b) -{ - return _arraySliceSliceAddSliceAssign_g(a, c, b); -} - -T[] _arraySliceSliceAddSliceAssign_g(T[] a, T[] c, T[] b) -in -{ - assert(a.length == b.length && b.length == c.length); - assert(disjoint(a, b)); - assert(disjoint(a, c)); - assert(disjoint(b, c)); -} -body -{ - //printf("_arraySliceSliceAddSliceAssign_g()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - auto cptr = c.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 5739% faster - if (sse2() && a.length >= 64) - { - auto n = aptr + (a.length & ~63); - - if (((cast(uint) aptr | cast(uint) bptr | cast(uint) cptr) & 15) != 0) - { - version (log) printf("\tsse2 unaligned\n"); - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 8; - startaddlsse2u: - add ESI, 64; - movdqu XMM0, [EAX]; - movdqu XMM1, [EAX+16]; - movdqu XMM2, [EAX+32]; - movdqu XMM3, [EAX+48]; - add EAX, 64; - movdqu XMM4, [ECX]; - movdqu XMM5, [ECX+16]; - movdqu XMM6, [ECX+32]; - movdqu XMM7, [ECX+48]; - add ECX, 64; - paddb XMM0, XMM4; - paddb XMM1, XMM5; - paddb XMM2, XMM6; - paddb XMM3, XMM7; - movdqu [ESI -64], XMM0; - movdqu [ESI+16-64], XMM1; - movdqu [ESI+32-64], XMM2; - movdqu [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startaddlsse2u; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - else - { - version (log) printf("\tsse2 aligned\n"); - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 8; - startaddlsse2a: - add ESI, 64; - movdqa XMM0, [EAX]; - movdqa XMM1, [EAX+16]; - movdqa XMM2, [EAX+32]; - movdqa XMM3, [EAX+48]; - add EAX, 64; - movdqa XMM4, [ECX]; - movdqa XMM5, [ECX+16]; - movdqa XMM6, [ECX+32]; - movdqa XMM7, [ECX+48]; - add ECX, 64; - paddb XMM0, XMM4; - paddb XMM1, XMM5; - paddb XMM2, XMM6; - paddb XMM3, XMM7; - movdqa [ESI -64], XMM0; - movdqa [ESI+16-64], XMM1; - movdqa [ESI+32-64], XMM2; - movdqa [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startaddlsse2a; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - else - // MMX version is 4428% faster - if (mmx() && a.length >= 32) - { - version (log) printf("\tmmx\n"); - auto n = aptr + (a.length & ~31); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 4; - startaddlmmx: - add ESI, 32; - movq MM0, [EAX]; - movq MM1, [EAX+8]; - movq MM2, [EAX+16]; - movq MM3, [EAX+24]; - add EAX, 32; - movq MM4, [ECX]; - movq MM5, [ECX+8]; - movq MM6, [ECX+16]; - movq MM7, [ECX+24]; - add ECX, 32; - paddb MM0, MM4; - paddb MM1, MM5; - paddb MM2, MM6; - paddb MM3, MM7; - movq [ESI -32], MM0; - movq [ESI+8 -32], MM1; - movq [ESI+16-32], MM2; - movq [ESI+24-32], MM3; - cmp ESI, EDI; - jb startaddlmmx; - - emms; - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - - version (log) if (aptr < aend) printf("\tbase\n"); - while (aptr < aend) - *aptr++ = cast(T)(*bptr++ + *cptr++); - - return a; -} - -unittest -{ - printf("_arraySliceSliceAddSliceAssign_g unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] + b[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] + b[i])) - { - printf("[%d]: %d != %d + %d\n", i, c[i], a[i], b[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] += value - */ - -T[] _arrayExpSliceAddass_a(T[] a, T value) -{ - return _arrayExpSliceAddass_g(a, value); -} - -T[] _arrayExpSliceAddass_h(T[] a, T value) -{ - return _arrayExpSliceAddass_g(a, value); -} - -T[] _arrayExpSliceAddass_g(T[] a, T value) -{ - //printf("_arrayExpSliceAddass_g(a.length = %d, value = %Lg)\n", a.length, cast(real)value); - auto aptr = a.ptr; - auto aend = aptr + a.length; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 1578% faster - if (sse2() && a.length >= 64) - { - auto n = aptr + (a.length & ~63); - - uint l = cast(ubyte) value; - l |= (l << 8); - l |= (l << 16); - - if (((cast(uint) aptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - movd XMM4, l; - pshufd XMM4, XMM4, 0; - - align 8; - startaddasssse2u: - movdqu XMM0, [ESI]; - movdqu XMM1, [ESI+16]; - movdqu XMM2, [ESI+32]; - movdqu XMM3, [ESI+48]; - add ESI, 64; - paddb XMM0, XMM4; - paddb XMM1, XMM4; - paddb XMM2, XMM4; - paddb XMM3, XMM4; - movdqu [ESI -64], XMM0; - movdqu [ESI+16-64], XMM1; - movdqu [ESI+32-64], XMM2; - movdqu [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startaddasssse2u; - - mov aptr, ESI; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - movd XMM4, l; - pshufd XMM4, XMM4, 0; - - align 8; - startaddasssse2a: - movdqa XMM0, [ESI]; - movdqa XMM1, [ESI+16]; - movdqa XMM2, [ESI+32]; - movdqa XMM3, [ESI+48]; - add ESI, 64; - paddb XMM0, XMM4; - paddb XMM1, XMM4; - paddb XMM2, XMM4; - paddb XMM3, XMM4; - movdqa [ESI -64], XMM0; - movdqa [ESI+16-64], XMM1; - movdqa [ESI+32-64], XMM2; - movdqa [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startaddasssse2a; - - mov aptr, ESI; - } - } - } - else - // MMX version is 1721% faster - if (mmx() && a.length >= 32) - { - - auto n = aptr + (a.length & ~31); - - uint l = cast(ubyte) value; - l |= (l << 8); - - asm - { - mov ESI, aptr; - mov EDI, n; - movd MM4, l; - pshufw MM4, MM4, 0; - - align 8; - startaddassmmx: - movq MM0, [ESI]; - movq MM1, [ESI+8]; - movq MM2, [ESI+16]; - movq MM3, [ESI+24]; - add ESI, 32; - paddb MM0, MM4; - paddb MM1, MM4; - paddb MM2, MM4; - paddb MM3, MM4; - movq [ESI -32], MM0; - movq [ESI+8 -32], MM1; - movq [ESI+16-32], MM2; - movq [ESI+24-32], MM3; - cmp ESI, EDI; - jb startaddassmmx; - - emms; - mov aptr, ESI; - } - } - } - - while (aptr < aend) - *aptr++ += value; - - return a; -} - -unittest -{ - printf("_arrayExpSliceAddass_g unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] += 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] + 6)) - { - printf("[%d]: %d != %d + 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] += b[] - */ - -T[] _arraySliceSliceAddass_a(T[] a, T[] b) -{ - return _arraySliceSliceAddass_g(a, b); -} - -T[] _arraySliceSliceAddass_h(T[] a, T[] b) -{ - return _arraySliceSliceAddass_g(a, b); -} - -T[] _arraySliceSliceAddass_g(T[] a, T[] b) -in -{ - assert (a.length == b.length); - assert (disjoint(a, b)); -} -body -{ - //printf("_arraySliceSliceAddass_g()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 4727% faster - if (sse2() && a.length >= 64) - { - auto n = aptr + (a.length & ~63); - - if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 8; - startaddasslsse2u: - movdqu XMM0, [ESI]; - movdqu XMM1, [ESI+16]; - movdqu XMM2, [ESI+32]; - movdqu XMM3, [ESI+48]; - add ESI, 64; - movdqu XMM4, [ECX]; - movdqu XMM5, [ECX+16]; - movdqu XMM6, [ECX+32]; - movdqu XMM7, [ECX+48]; - add ECX, 64; - paddb XMM0, XMM4; - paddb XMM1, XMM5; - paddb XMM2, XMM6; - paddb XMM3, XMM7; - movdqu [ESI -64], XMM0; - movdqu [ESI+16-64], XMM1; - movdqu [ESI+32-64], XMM2; - movdqu [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startaddasslsse2u; - - mov aptr, ESI; - mov bptr, ECX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 8; - startaddasslsse2a: - movdqa XMM0, [ESI]; - movdqa XMM1, [ESI+16]; - movdqa XMM2, [ESI+32]; - movdqa XMM3, [ESI+48]; - add ESI, 64; - movdqa XMM4, [ECX]; - movdqa XMM5, [ECX+16]; - movdqa XMM6, [ECX+32]; - movdqa XMM7, [ECX+48]; - add ECX, 64; - paddb XMM0, XMM4; - paddb XMM1, XMM5; - paddb XMM2, XMM6; - paddb XMM3, XMM7; - movdqa [ESI -64], XMM0; - movdqa [ESI+16-64], XMM1; - movdqa [ESI+32-64], XMM2; - movdqa [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startaddasslsse2a; - - mov aptr, ESI; - mov bptr, ECX; - } - } - } - else - // MMX version is 3059% faster - if (mmx() && a.length >= 32) - { - - auto n = aptr + (a.length & ~31); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 8; - startaddasslmmx: - movq MM0, [ESI]; - movq MM1, [ESI+8]; - movq MM2, [ESI+16]; - movq MM3, [ESI+24]; - add ESI, 32; - movq MM4, [ECX]; - movq MM5, [ECX+8]; - movq MM6, [ECX+16]; - movq MM7, [ECX+24]; - add ECX, 32; - paddb MM0, MM4; - paddb MM1, MM5; - paddb MM2, MM6; - paddb MM3, MM7; - movq [ESI -32], MM0; - movq [ESI+8 -32], MM1; - movq [ESI+16-32], MM2; - movq [ESI+24-32], MM3; - cmp ESI, EDI; - jb startaddasslmmx; - - emms; - mov aptr, ESI; - mov bptr, ECX; - } - } - } - - while (aptr < aend) - *aptr++ += *bptr++; - - return a; -} - -unittest -{ - printf("_arraySliceSliceAddass_g unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] += b[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] + b[i])) - { - printf("[%d]: %d != %d + %d\n", i, c[i], a[i], b[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - - -/*********************** - * Computes: - * a[] = b[] - value - */ - -T[] _arraySliceExpMinSliceAssign_a(T[] a, T value, T[] b) -{ - return _arraySliceExpMinSliceAssign_g(a, value, b); -} - -T[] _arraySliceExpMinSliceAssign_h(T[] a, T value, T[] b) -{ - return _arraySliceExpMinSliceAssign_g(a, value, b); -} - -T[] _arraySliceExpMinSliceAssign_g(T[] a, T value, T[] b) -in -{ - assert(a.length == b.length); - assert(disjoint(a, b)); -} -body -{ - //printf("_arraySliceExpMinSliceAssign_g()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 1189% faster - if (sse2() && a.length >= 64) - { - auto n = aptr + (a.length & ~63); - - uint l = cast(ubyte) value; - l |= (l << 8); - l |= (l << 16); - - if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM4, l; - pshufd XMM4, XMM4, 0; - - align 8; - startsubsse2u: - add ESI, 64; - movdqu XMM0, [EAX]; - movdqu XMM1, [EAX+16]; - movdqu XMM2, [EAX+32]; - movdqu XMM3, [EAX+48]; - add EAX, 64; - psubb XMM0, XMM4; - psubb XMM1, XMM4; - psubb XMM2, XMM4; - psubb XMM3, XMM4; - movdqu [ESI -64], XMM0; - movdqu [ESI+16-64], XMM1; - movdqu [ESI+32-64], XMM2; - movdqu [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsubsse2u; - - mov aptr, ESI; - mov bptr, EAX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM4, l; - pshufd XMM4, XMM4, 0; - - align 8; - startsubsse2a: - add ESI, 64; - movdqa XMM0, [EAX]; - movdqa XMM1, [EAX+16]; - movdqa XMM2, [EAX+32]; - movdqa XMM3, [EAX+48]; - add EAX, 64; - psubb XMM0, XMM4; - psubb XMM1, XMM4; - psubb XMM2, XMM4; - psubb XMM3, XMM4; - movdqa [ESI -64], XMM0; - movdqa [ESI+16-64], XMM1; - movdqa [ESI+32-64], XMM2; - movdqa [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsubsse2a; - - mov aptr, ESI; - mov bptr, EAX; - } - } - } - else - // MMX version is 1079% faster - if (mmx() && a.length >= 32) - { - auto n = aptr + (a.length & ~31); - - uint l = cast(ubyte) value; - l |= (l << 8); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd MM4, l; - pshufw MM4, MM4, 0; - - align 4; - startsubmmx: - add ESI, 32; - movq MM0, [EAX]; - movq MM1, [EAX+8]; - movq MM2, [EAX+16]; - movq MM3, [EAX+24]; - add EAX, 32; - psubb MM0, MM4; - psubb MM1, MM4; - psubb MM2, MM4; - psubb MM3, MM4; - movq [ESI -32], MM0; - movq [ESI+8 -32], MM1; - movq [ESI+16-32], MM2; - movq [ESI+24-32], MM3; - cmp ESI, EDI; - jb startsubmmx; - - emms; - mov aptr, ESI; - mov bptr, EAX; - } - } - // trying to be fair and treat normal 32-bit cpu the same way as we do the SIMD units, with unrolled asm. There's not enough registers, really. - else - if (a.length >= 4) - { - auto n = aptr + (a.length & ~3); - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov CL, value; - - align 4; - startsub386: - add ESI, 4; - mov DX, [EAX]; - mov BX, [EAX+2]; - add EAX, 4; - sub BL, CL; - sub BH, CL; - sub DL, CL; - sub DH, CL; - mov [ESI -4], DX; - mov [ESI+2 -4], BX; - cmp ESI, EDI; - jb startsub386; - - mov aptr, ESI; - mov bptr, EAX; - } - } - } - - while (aptr < aend) - *aptr++ = cast(T)(*bptr++ - value); - - return a; -} - -unittest -{ - printf("_arraySliceExpMinSliceAssign_g unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] = b[] - 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(b[i] - 6)) - { - printf("[%d]: %d != %d - 6\n", i, c[i], b[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = value - b[] - */ - -T[] _arrayExpSliceMinSliceAssign_a(T[] a, T[] b, T value) -{ - return _arrayExpSliceMinSliceAssign_g(a, b, value); -} - -T[] _arrayExpSliceMinSliceAssign_h(T[] a, T[] b, T value) -{ - return _arrayExpSliceMinSliceAssign_g(a, b, value); -} - -T[] _arrayExpSliceMinSliceAssign_g(T[] a, T[] b, T value) -in -{ - assert(a.length == b.length); - assert(disjoint(a, b)); -} -body -{ - //printf("_arrayExpSliceMinSliceAssign_g()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 8748% faster - if (sse2() && a.length >= 64) - { - auto n = aptr + (a.length & ~63); - - uint l = cast(ubyte) value; - l |= (l << 8); - l |= (l << 16); - - if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM4, l; - pshufd XMM4, XMM4, 0; - - align 8; - startsubrsse2u: - add ESI, 64; - movdqa XMM5, XMM4; - movdqa XMM6, XMM4; - movdqu XMM0, [EAX]; - movdqu XMM1, [EAX+16]; - psubb XMM5, XMM0; - psubb XMM6, XMM1; - movdqu [ESI -64], XMM5; - movdqu [ESI+16-64], XMM6; - movdqa XMM5, XMM4; - movdqa XMM6, XMM4; - movdqu XMM2, [EAX+32]; - movdqu XMM3, [EAX+48]; - add EAX, 64; - psubb XMM5, XMM2; - psubb XMM6, XMM3; - movdqu [ESI+32-64], XMM5; - movdqu [ESI+48-64], XMM6; - cmp ESI, EDI; - jb startsubrsse2u; - - mov aptr, ESI; - mov bptr, EAX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM4, l; - pshufd XMM4, XMM4, 0; - - align 8; - startsubrsse2a: - add ESI, 64; - movdqa XMM5, XMM4; - movdqa XMM6, XMM4; - movdqa XMM0, [EAX]; - movdqa XMM1, [EAX+16]; - psubb XMM5, XMM0; - psubb XMM6, XMM1; - movdqa [ESI -64], XMM5; - movdqa [ESI+16-64], XMM6; - movdqa XMM5, XMM4; - movdqa XMM6, XMM4; - movdqa XMM2, [EAX+32]; - movdqa XMM3, [EAX+48]; - add EAX, 64; - psubb XMM5, XMM2; - psubb XMM6, XMM3; - movdqa [ESI+32-64], XMM5; - movdqa [ESI+48-64], XMM6; - cmp ESI, EDI; - jb startsubrsse2a; - - mov aptr, ESI; - mov bptr, EAX; - } - } - } - else - // MMX version is 7397% faster - if (mmx() && a.length >= 32) - { - auto n = aptr + (a.length & ~31); - - uint l = cast(ubyte) value; - l |= (l << 8); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd MM4, l; - pshufw MM4, MM4, 0; - - align 4; - startsubrmmx: - add ESI, 32; - movq MM5, MM4; - movq MM6, MM4; - movq MM0, [EAX]; - movq MM1, [EAX+8]; - psubb MM5, MM0; - psubb MM6, MM1; - movq [ESI -32], MM5; - movq [ESI+8 -32], MM6; - movq MM5, MM4; - movq MM6, MM4; - movq MM2, [EAX+16]; - movq MM3, [EAX+24]; - add EAX, 32; - psubb MM5, MM2; - psubb MM6, MM3; - movq [ESI+16-32], MM5; - movq [ESI+24-32], MM6; - cmp ESI, EDI; - jb startsubrmmx; - - emms; - mov aptr, ESI; - mov bptr, EAX; - } - } - - } - - while (aptr < aend) - *aptr++ = cast(T)(value - *bptr++); - - return a; -} - -unittest -{ - printf("_arrayExpSliceMinSliceAssign_g unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] = 6 - b[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(6 - b[i])) - { - printf("[%d]: %d != 6 - %d\n", i, c[i], b[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] - c[] - */ - -T[] _arraySliceSliceMinSliceAssign_a(T[] a, T[] c, T[] b) -{ - return _arraySliceSliceMinSliceAssign_g(a, c, b); -} - -T[] _arraySliceSliceMinSliceAssign_h(T[] a, T[] c, T[] b) -{ - return _arraySliceSliceMinSliceAssign_g(a, c, b); -} - -T[] _arraySliceSliceMinSliceAssign_g(T[] a, T[] c, T[] b) -in -{ - assert(a.length == b.length && b.length == c.length); - assert(disjoint(a, b)); - assert(disjoint(a, c)); - assert(disjoint(b, c)); -} -body -{ - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - auto cptr = c.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 5756% faster - if (sse2() && a.length >= 64) - { - auto n = aptr + (a.length & ~63); - - if (((cast(uint) aptr | cast(uint) bptr | cast(uint) cptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 8; - startsublsse2u: - add ESI, 64; - movdqu XMM0, [EAX]; - movdqu XMM1, [EAX+16]; - movdqu XMM2, [EAX+32]; - movdqu XMM3, [EAX+48]; - add EAX, 64; - movdqu XMM4, [ECX]; - movdqu XMM5, [ECX+16]; - movdqu XMM6, [ECX+32]; - movdqu XMM7, [ECX+48]; - add ECX, 64; - psubb XMM0, XMM4; - psubb XMM1, XMM5; - psubb XMM2, XMM6; - psubb XMM3, XMM7; - movdqu [ESI -64], XMM0; - movdqu [ESI+16-64], XMM1; - movdqu [ESI+32-64], XMM2; - movdqu [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsublsse2u; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 8; - startsublsse2a: - add ESI, 64; - movdqa XMM0, [EAX]; - movdqa XMM1, [EAX+16]; - movdqa XMM2, [EAX+32]; - movdqa XMM3, [EAX+48]; - add EAX, 64; - movdqa XMM4, [ECX]; - movdqa XMM5, [ECX+16]; - movdqa XMM6, [ECX+32]; - movdqa XMM7, [ECX+48]; - add ECX, 64; - psubb XMM0, XMM4; - psubb XMM1, XMM5; - psubb XMM2, XMM6; - psubb XMM3, XMM7; - movdqa [ESI -64], XMM0; - movdqa [ESI+16-64], XMM1; - movdqa [ESI+32-64], XMM2; - movdqa [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsublsse2a; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - else - // MMX version is 4428% faster - if (mmx() && a.length >= 32) - { - auto n = aptr + (a.length & ~31); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 8; - startsublmmx: - add ESI, 32; - movq MM0, [EAX]; - movq MM1, [EAX+8]; - movq MM2, [EAX+16]; - movq MM3, [EAX+24]; - add EAX, 32; - movq MM4, [ECX]; - movq MM5, [ECX+8]; - movq MM6, [ECX+16]; - movq MM7, [ECX+24]; - add ECX, 32; - psubb MM0, MM4; - psubb MM1, MM5; - psubb MM2, MM6; - psubb MM3, MM7; - movq [ESI -32], MM0; - movq [ESI+8 -32], MM1; - movq [ESI+16-32], MM2; - movq [ESI+24-32], MM3; - cmp ESI, EDI; - jb startsublmmx; - - emms; - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - - while (aptr < aend) - *aptr++ = cast(T)(*bptr++ - *cptr++); - - return a; -} - -unittest -{ - printf("_arraySliceSliceMinSliceAssign_g unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] - b[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] - b[i])) - { - printf("[%d]: %d != %d - %d\n", i, c[i], a[i], b[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] -= value - */ - -T[] _arrayExpSliceMinass_a(T[] a, T value) -{ - return _arrayExpSliceMinass_g(a, value); -} - -T[] _arrayExpSliceMinass_h(T[] a, T value) -{ - return _arrayExpSliceMinass_g(a, value); -} - -T[] _arrayExpSliceMinass_g(T[] a, T value) -{ - //printf("_arrayExpSliceMinass_g(a.length = %d, value = %Lg)\n", a.length, cast(real)value); - auto aptr = a.ptr; - auto aend = aptr + a.length; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 1577% faster - if (sse2() && a.length >= 64) - { - auto n = aptr + (a.length & ~63); - - uint l = cast(ubyte) value; - l |= (l << 8); - l |= (l << 16); - - if (((cast(uint) aptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - movd XMM4, l; - pshufd XMM4, XMM4, 0; - - align 8; - startsubasssse2u: - movdqu XMM0, [ESI]; - movdqu XMM1, [ESI+16]; - movdqu XMM2, [ESI+32]; - movdqu XMM3, [ESI+48]; - add ESI, 64; - psubb XMM0, XMM4; - psubb XMM1, XMM4; - psubb XMM2, XMM4; - psubb XMM3, XMM4; - movdqu [ESI -64], XMM0; - movdqu [ESI+16-64], XMM1; - movdqu [ESI+32-64], XMM2; - movdqu [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsubasssse2u; - - mov aptr, ESI; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - movd XMM4, l; - pshufd XMM4, XMM4, 0; - - align 8; - startsubasssse2a: - movdqa XMM0, [ESI]; - movdqa XMM1, [ESI+16]; - movdqa XMM2, [ESI+32]; - movdqa XMM3, [ESI+48]; - add ESI, 64; - psubb XMM0, XMM4; - psubb XMM1, XMM4; - psubb XMM2, XMM4; - psubb XMM3, XMM4; - movdqa [ESI -64], XMM0; - movdqa [ESI+16-64], XMM1; - movdqa [ESI+32-64], XMM2; - movdqa [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsubasssse2a; - - mov aptr, ESI; - } - } - } - else - // MMX version is 1577% faster - if (mmx() && a.length >= 32) - { - - auto n = aptr + (a.length & ~31); - - uint l = cast(ubyte) value; - l |= (l << 8); - - asm - { - mov ESI, aptr; - mov EDI, n; - movd MM4, l; - pshufw MM4, MM4, 0; - - align 8; - startsubassmmx: - movq MM0, [ESI]; - movq MM1, [ESI+8]; - movq MM2, [ESI+16]; - movq MM3, [ESI+24]; - add ESI, 32; - psubb MM0, MM4; - psubb MM1, MM4; - psubb MM2, MM4; - psubb MM3, MM4; - movq [ESI -32], MM0; - movq [ESI+8 -32], MM1; - movq [ESI+16-32], MM2; - movq [ESI+24-32], MM3; - cmp ESI, EDI; - jb startsubassmmx; - - emms; - mov aptr, ESI; - } - } - } - - while (aptr < aend) - *aptr++ -= value; - - return a; -} - -unittest -{ - printf("_arrayExpSliceMinass_g unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] -= 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] - 6)) - { - printf("[%d]: %d != %d - 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] -= b[] - */ - -T[] _arraySliceSliceMinass_a(T[] a, T[] b) -{ - return _arraySliceSliceMinass_g(a, b); -} - -T[] _arraySliceSliceMinass_h(T[] a, T[] b) -{ - return _arraySliceSliceMinass_g(a, b); -} - -T[] _arraySliceSliceMinass_g(T[] a, T[] b) -in -{ - assert (a.length == b.length); - assert (disjoint(a, b)); -} -body -{ - //printf("_arraySliceSliceMinass_g()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 4800% faster - if (sse2() && a.length >= 64) - { - auto n = aptr + (a.length & ~63); - - if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 8; - startsubasslsse2u: - movdqu XMM0, [ESI]; - movdqu XMM1, [ESI+16]; - movdqu XMM2, [ESI+32]; - movdqu XMM3, [ESI+48]; - add ESI, 64; - movdqu XMM4, [ECX]; - movdqu XMM5, [ECX+16]; - movdqu XMM6, [ECX+32]; - movdqu XMM7, [ECX+48]; - add ECX, 64; - psubb XMM0, XMM4; - psubb XMM1, XMM5; - psubb XMM2, XMM6; - psubb XMM3, XMM7; - movdqu [ESI -64], XMM0; - movdqu [ESI+16-64], XMM1; - movdqu [ESI+32-64], XMM2; - movdqu [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsubasslsse2u; - - mov aptr, ESI; - mov bptr, ECX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 8; - startsubasslsse2a: - movdqa XMM0, [ESI]; - movdqa XMM1, [ESI+16]; - movdqa XMM2, [ESI+32]; - movdqa XMM3, [ESI+48]; - add ESI, 64; - movdqa XMM4, [ECX]; - movdqa XMM5, [ECX+16]; - movdqa XMM6, [ECX+32]; - movdqa XMM7, [ECX+48]; - add ECX, 64; - psubb XMM0, XMM4; - psubb XMM1, XMM5; - psubb XMM2, XMM6; - psubb XMM3, XMM7; - movdqa [ESI -64], XMM0; - movdqa [ESI+16-64], XMM1; - movdqa [ESI+32-64], XMM2; - movdqa [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsubasslsse2a; - - mov aptr, ESI; - mov bptr, ECX; - } - } - } - else - // MMX version is 3107% faster - if (mmx() && a.length >= 32) - { - - auto n = aptr + (a.length & ~31); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 8; - startsubasslmmx: - movq MM0, [ESI]; - movq MM1, [ESI+8]; - movq MM2, [ESI+16]; - movq MM3, [ESI+24]; - add ESI, 32; - movq MM4, [ECX]; - movq MM5, [ECX+8]; - movq MM6, [ECX+16]; - movq MM7, [ECX+24]; - add ECX, 32; - psubb MM0, MM4; - psubb MM1, MM5; - psubb MM2, MM6; - psubb MM3, MM7; - movq [ESI -32], MM0; - movq [ESI+8 -32], MM1; - movq [ESI+16-32], MM2; - movq [ESI+24-32], MM3; - cmp ESI, EDI; - jb startsubasslmmx; - - emms; - mov aptr, ESI; - mov bptr, ECX; - } - } - } - - while (aptr < aend) - *aptr++ -= *bptr++; - - return a; -} - -unittest -{ - printf("_arraySliceSliceMinass_g unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] -= b[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] - b[i])) - { - printf("[%d]: %d != %d - %d\n", i, c[i], a[i], b[i]); - assert(0); - } - } - } - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/arraycast.d --- a/druntime/src/compiler/ldc/arraycast.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,94 +0,0 @@ -/** - * Implementation of array cast support routines. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: = 8) - { - auto n = aptr + (b.length & ~7); - - // Unaligned case - asm - { - mov EAX, bptr; // left operand - mov ECX, cptr; // right operand - mov ESI, aptr; // destination operand - mov EDI, n; // end comparison - - align 8; - startsseloopb: - movupd XMM0, [EAX]; - movupd XMM1, [EAX+16]; - movupd XMM2, [EAX+32]; - movupd XMM3, [EAX+48]; - add EAX, 64; - movupd XMM4, [ECX]; - movupd XMM5, [ECX+16]; - movupd XMM6, [ECX+32]; - movupd XMM7, [ECX+48]; - add ESI, 64; - subpd XMM0, XMM4; - subpd XMM1, XMM5; - subpd XMM2, XMM6; - subpd XMM3, XMM7; - add ECX, 64; - movupd [ESI+ 0-64], XMM0; - movupd [ESI+16-64], XMM1; - movupd [ESI+32-64], XMM2; - movupd [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloopb; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - - // Handle remainder - while (aptr < aend) - *aptr++ = *bptr++ - *cptr++; - - return a; -} - - -unittest -{ - printf("_arraySliceSliceMinSliceAssign_d unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] - b[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] - b[i])) - { - printf("[%d]: %g != %g - %g\n", i, c[i], a[i], b[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] + value - */ - -T[] _arraySliceExpAddSliceAssign_d(T[] a, T value, T[] b) -in -{ - assert(a.length == b.length); - assert(disjoint(a, b)); -} -body -{ - //printf("_arraySliceExpAddSliceAssign_d()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 version is 305% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - // Unaligned case - asm - { - mov EAX, bptr; - mov ESI, aptr; - mov EDI, n; - movsd XMM4, value; - shufpd XMM4, XMM4, 0; - - align 8; - startsseloop: - add ESI, 64; - movupd XMM0, [EAX]; - movupd XMM1, [EAX+16]; - movupd XMM2, [EAX+32]; - movupd XMM3, [EAX+48]; - add EAX, 64; - addpd XMM0, XMM4; - addpd XMM1, XMM4; - addpd XMM2, XMM4; - addpd XMM3, XMM4; - movupd [ESI+ 0-64], XMM0; - movupd [ESI+16-64], XMM1; - movupd [ESI+32-64], XMM2; - movupd [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloop; - - mov aptr, ESI; - mov bptr, EAX; - } - } - } - - while (aptr < aend) - *aptr++ = *bptr++ + value; - - return a; -} - -unittest -{ - printf("_arraySliceExpAddSliceAssign_d unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] + 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] + 6)) - { - printf("[%d]: %g != %g + 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] += value - */ - -T[] _arrayExpSliceAddass_d(T[] a, T value) -{ - //printf("_arrayExpSliceAddass_d(a.length = %d, value = %Lg)\n", a.length, cast(real)value); - auto aptr = a.ptr; - auto aend = aptr + a.length; - - version (D_InlineAsm_X86) - { - // SSE2 version is 114% faster - if (sse2() && a.length >= 8) - { - auto n = cast(T*)((cast(uint)aend) & ~7); - if (aptr < n) - - // Unaligned case - asm - { - mov ESI, aptr; - mov EDI, n; - movsd XMM4, value; - shufpd XMM4, XMM4, 0; - - align 8; - startsseloopa: - movupd XMM0, [ESI]; - movupd XMM1, [ESI+16]; - movupd XMM2, [ESI+32]; - movupd XMM3, [ESI+48]; - add ESI, 64; - addpd XMM0, XMM4; - addpd XMM1, XMM4; - addpd XMM2, XMM4; - addpd XMM3, XMM4; - movupd [ESI+ 0-64], XMM0; - movupd [ESI+16-64], XMM1; - movupd [ESI+32-64], XMM2; - movupd [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloopa; - - mov aptr, ESI; - } - } - } - - while (aptr < aend) - *aptr++ += value; - - return a; -} - -unittest -{ - printf("_arrayExpSliceAddass_d unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] += 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] + 6)) - { - printf("[%d]: %g != %g + 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] += b[] - */ - -T[] _arraySliceSliceAddass_d(T[] a, T[] b) -in -{ - assert (a.length == b.length); - assert (disjoint(a, b)); -} -body -{ - //printf("_arraySliceSliceAddass_d()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 version is 183% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - // Unaligned case - asm - { - mov ECX, bptr; // right operand - mov ESI, aptr; // destination operand - mov EDI, n; // end comparison - - align 8; - startsseloopb: - movupd XMM0, [ESI]; - movupd XMM1, [ESI+16]; - movupd XMM2, [ESI+32]; - movupd XMM3, [ESI+48]; - add ESI, 64; - movupd XMM4, [ECX]; - movupd XMM5, [ECX+16]; - movupd XMM6, [ECX+32]; - movupd XMM7, [ECX+48]; - add ECX, 64; - addpd XMM0, XMM4; - addpd XMM1, XMM5; - addpd XMM2, XMM6; - addpd XMM3, XMM7; - movupd [ESI+ 0-64], XMM0; - movupd [ESI+16-64], XMM1; - movupd [ESI+32-64], XMM2; - movupd [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloopb; - - mov aptr, ESI; - mov bptr, ECX; - } - } - } - - while (aptr < aend) - *aptr++ += *bptr++; - - return a; -} - -unittest -{ - printf("_arraySliceSliceAddass_d unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] += b[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] + b[i])) - { - printf("[%d]: %g != %g + %g\n", i, c[i], a[i], b[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] - value - */ - -T[] _arraySliceExpMinSliceAssign_d(T[] a, T value, T[] b) -in -{ - assert (a.length == b.length); - assert (disjoint(a, b)); -} -body -{ - //printf("_arraySliceExpMinSliceAssign_d()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 version is 305% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - // Unaligned case - asm - { - mov EAX, bptr; - mov ESI, aptr; - mov EDI, n; - movsd XMM4, value; - shufpd XMM4, XMM4, 0; - - align 8; - startsseloop: - add ESI, 64; - movupd XMM0, [EAX]; - movupd XMM1, [EAX+16]; - movupd XMM2, [EAX+32]; - movupd XMM3, [EAX+48]; - add EAX, 64; - subpd XMM0, XMM4; - subpd XMM1, XMM4; - subpd XMM2, XMM4; - subpd XMM3, XMM4; - movupd [ESI+ 0-64], XMM0; - movupd [ESI+16-64], XMM1; - movupd [ESI+32-64], XMM2; - movupd [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloop; - - mov aptr, ESI; - mov bptr, EAX; - } - } - } - - while (aptr < aend) - *aptr++ = *bptr++ - value; - - return a; -} - -unittest -{ - printf("_arraySliceExpMinSliceAssign_d unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] - 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] - 6)) - { - printf("[%d]: %g != %g - 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = value - b[] - */ - -T[] _arrayExpSliceMinSliceAssign_d(T[] a, T[] b, T value) -in -{ - assert (a.length == b.length); - assert (disjoint(a, b)); -} -body -{ - //printf("_arrayExpSliceMinSliceAssign_d()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 version is 66% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - // Unaligned case - asm - { - mov EAX, bptr; - mov ESI, aptr; - mov EDI, n; - movsd XMM4, value; - shufpd XMM4, XMM4, 0; - - align 8; - startsseloop: - add ESI, 64; - movapd XMM5, XMM4; - movapd XMM6, XMM4; - movupd XMM0, [EAX]; - movupd XMM1, [EAX+16]; - movupd XMM2, [EAX+32]; - movupd XMM3, [EAX+48]; - add EAX, 64; - subpd XMM5, XMM0; - subpd XMM6, XMM1; - movupd [ESI+ 0-64], XMM5; - movupd [ESI+16-64], XMM6; - movapd XMM5, XMM4; - movapd XMM6, XMM4; - subpd XMM5, XMM2; - subpd XMM6, XMM3; - movupd [ESI+32-64], XMM5; - movupd [ESI+48-64], XMM6; - cmp ESI, EDI; - jb startsseloop; - - mov aptr, ESI; - mov bptr, EAX; - } - } - } - - while (aptr < aend) - *aptr++ = value - *bptr++; - - return a; -} - -unittest -{ - printf("_arrayExpSliceMinSliceAssign_d unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = 6 - a[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(6 - a[i])) - { - printf("[%d]: %g != 6 - %g\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] -= value - */ - -T[] _arrayExpSliceMinass_d(T[] a, T value) -{ - //printf("_arrayExpSliceMinass_d(a.length = %d, value = %Lg)\n", a.length, cast(real)value); - auto aptr = a.ptr; - auto aend = aptr + a.length; - - version (D_InlineAsm_X86) - { - // SSE2 version is 115% faster - if (sse2() && a.length >= 8) - { - auto n = cast(T*)((cast(uint)aend) & ~7); - if (aptr < n) - - // Unaligned case - asm - { - mov ESI, aptr; - mov EDI, n; - movsd XMM4, value; - shufpd XMM4, XMM4, 0; - - align 8; - startsseloopa: - movupd XMM0, [ESI]; - movupd XMM1, [ESI+16]; - movupd XMM2, [ESI+32]; - movupd XMM3, [ESI+48]; - add ESI, 64; - subpd XMM0, XMM4; - subpd XMM1, XMM4; - subpd XMM2, XMM4; - subpd XMM3, XMM4; - movupd [ESI+ 0-64], XMM0; - movupd [ESI+16-64], XMM1; - movupd [ESI+32-64], XMM2; - movupd [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloopa; - - mov aptr, ESI; - } - } - } - - while (aptr < aend) - *aptr++ -= value; - - return a; -} - -unittest -{ - printf("_arrayExpSliceMinass_d unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] -= 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] - 6)) - { - printf("[%d]: %g != %g - 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] -= b[] - */ - -T[] _arraySliceSliceMinass_d(T[] a, T[] b) -in -{ - assert (a.length == b.length); - assert (disjoint(a, b)); -} -body -{ - //printf("_arraySliceSliceMinass_d()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 version is 183% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - // Unaligned case - asm - { - mov ECX, bptr; // right operand - mov ESI, aptr; // destination operand - mov EDI, n; // end comparison - - align 8; - startsseloopb: - movupd XMM0, [ESI]; - movupd XMM1, [ESI+16]; - movupd XMM2, [ESI+32]; - movupd XMM3, [ESI+48]; - add ESI, 64; - movupd XMM4, [ECX]; - movupd XMM5, [ECX+16]; - movupd XMM6, [ECX+32]; - movupd XMM7, [ECX+48]; - add ECX, 64; - subpd XMM0, XMM4; - subpd XMM1, XMM5; - subpd XMM2, XMM6; - subpd XMM3, XMM7; - movupd [ESI+ 0-64], XMM0; - movupd [ESI+16-64], XMM1; - movupd [ESI+32-64], XMM2; - movupd [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloopb; - - mov aptr, ESI; - mov bptr, ECX; - } - } - } - - while (aptr < aend) - *aptr++ -= *bptr++; - - return a; -} - -unittest -{ - printf("_arrayExpSliceMinass_d unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] -= 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] - 6)) - { - printf("[%d]: %g != %g - 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] * value - */ - -T[] _arraySliceExpMulSliceAssign_d(T[] a, T value, T[] b) -in -{ - assert(a.length == b.length); - assert(disjoint(a, b)); -} -body -{ - //printf("_arraySliceExpMulSliceAssign_d()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 version is 304% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - // Unaligned case - asm - { - mov EAX, bptr; - mov ESI, aptr; - mov EDI, n; - movsd XMM4, value; - shufpd XMM4, XMM4, 0; - - align 8; - startsseloop: - add ESI, 64; - movupd XMM0, [EAX]; - movupd XMM1, [EAX+16]; - movupd XMM2, [EAX+32]; - movupd XMM3, [EAX+48]; - add EAX, 64; - mulpd XMM0, XMM4; - mulpd XMM1, XMM4; - mulpd XMM2, XMM4; - mulpd XMM3, XMM4; - movupd [ESI+ 0-64], XMM0; - movupd [ESI+16-64], XMM1; - movupd [ESI+32-64], XMM2; - movupd [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloop; - - mov aptr, ESI; - mov bptr, EAX; - } - } - } - - while (aptr < aend) - *aptr++ = *bptr++ * value; - - return a; -} - -unittest -{ - printf("_arraySliceExpMulSliceAssign_d unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] * 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] * 6)) - { - printf("[%d]: %g != %g * 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] * c[] - */ - -T[] _arraySliceSliceMulSliceAssign_d(T[] a, T[] c, T[] b) -in -{ - assert(a.length == b.length && b.length == c.length); - assert(disjoint(a, b)); - assert(disjoint(a, c)); - assert(disjoint(b, c)); -} -body -{ - //printf("_arraySliceSliceMulSliceAssign_d()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - auto cptr = c.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 version is 329% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - // Unaligned case - asm - { - mov EAX, bptr; // left operand - mov ECX, cptr; // right operand - mov ESI, aptr; // destination operand - mov EDI, n; // end comparison - - align 8; - startsseloopb: - movupd XMM0, [EAX]; - movupd XMM1, [EAX+16]; - movupd XMM2, [EAX+32]; - movupd XMM3, [EAX+48]; - add ESI, 64; - movupd XMM4, [ECX]; - movupd XMM5, [ECX+16]; - movupd XMM6, [ECX+32]; - movupd XMM7, [ECX+48]; - add EAX, 64; - mulpd XMM0, XMM4; - mulpd XMM1, XMM5; - mulpd XMM2, XMM6; - mulpd XMM3, XMM7; - add ECX, 64; - movupd [ESI+ 0-64], XMM0; - movupd [ESI+16-64], XMM1; - movupd [ESI+32-64], XMM2; - movupd [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloopb; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - - while (aptr < aend) - *aptr++ = *bptr++ * *cptr++; - - return a; -} - -unittest -{ - printf("_arraySliceSliceMulSliceAssign_d unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] * b[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] * b[i])) - { - printf("[%d]: %g != %g * %g\n", i, c[i], a[i], b[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] *= value - */ - -T[] _arrayExpSliceMulass_d(T[] a, T value) -{ - //printf("_arrayExpSliceMulass_d(a.length = %d, value = %Lg)\n", a.length, cast(real)value); - auto aptr = a.ptr; - auto aend = aptr + a.length; - - version (D_InlineAsm_X86) - { - // SSE2 version is 109% faster - if (sse2() && a.length >= 8) - { - auto n = cast(T*)((cast(uint)aend) & ~7); - if (aptr < n) - - // Unaligned case - asm - { - mov ESI, aptr; - mov EDI, n; - movsd XMM4, value; - shufpd XMM4, XMM4, 0; - - align 8; - startsseloopa: - movupd XMM0, [ESI]; - movupd XMM1, [ESI+16]; - movupd XMM2, [ESI+32]; - movupd XMM3, [ESI+48]; - add ESI, 64; - mulpd XMM0, XMM4; - mulpd XMM1, XMM4; - mulpd XMM2, XMM4; - mulpd XMM3, XMM4; - movupd [ESI+ 0-64], XMM0; - movupd [ESI+16-64], XMM1; - movupd [ESI+32-64], XMM2; - movupd [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloopa; - - mov aptr, ESI; - } - } - } - - while (aptr < aend) - *aptr++ *= value; - - return a; -} - -unittest -{ - printf("_arrayExpSliceMulass_d unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] *= 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] * 6)) - { - printf("[%d]: %g != %g * 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] *= b[] - */ - -T[] _arraySliceSliceMulass_d(T[] a, T[] b) -in -{ - assert (a.length == b.length); - assert (disjoint(a, b)); -} -body -{ - //printf("_arraySliceSliceMulass_d()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 version is 205% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - // Unaligned case - asm - { - mov ECX, bptr; // right operand - mov ESI, aptr; // destination operand - mov EDI, n; // end comparison - - align 8; - startsseloopb: - movupd XMM0, [ESI]; - movupd XMM1, [ESI+16]; - movupd XMM2, [ESI+32]; - movupd XMM3, [ESI+48]; - add ESI, 64; - movupd XMM4, [ECX]; - movupd XMM5, [ECX+16]; - movupd XMM6, [ECX+32]; - movupd XMM7, [ECX+48]; - add ECX, 64; - mulpd XMM0, XMM4; - mulpd XMM1, XMM5; - mulpd XMM2, XMM6; - mulpd XMM3, XMM7; - movupd [ESI+ 0-64], XMM0; - movupd [ESI+16-64], XMM1; - movupd [ESI+32-64], XMM2; - movupd [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloopb; - - mov aptr, ESI; - mov bptr, ECX; - } - } - } - - while (aptr < aend) - *aptr++ *= *bptr++; - - return a; -} - -unittest -{ - printf("_arrayExpSliceMulass_d unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] *= 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] * 6)) - { - printf("[%d]: %g != %g * 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] / value - */ - -T[] _arraySliceExpDivSliceAssign_d(T[] a, T value, T[] b) -in -{ - assert(a.length == b.length); - assert(disjoint(a, b)); -} -body -{ - //printf("_arraySliceExpDivSliceAssign_d()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - /* Multiplying by the reciprocal is faster, but does - * not produce as accurate an answer. - */ - T recip = cast(T)1 / value; - - version (D_InlineAsm_X86) - { - // SSE2 version is 299% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - // Unaligned case - asm - { - mov EAX, bptr; - mov ESI, aptr; - mov EDI, n; - movsd XMM4, recip; - //movsd XMM4, value - //rcpsd XMM4, XMM4 - shufpd XMM4, XMM4, 0; - - align 8; - startsseloop: - add ESI, 64; - movupd XMM0, [EAX]; - movupd XMM1, [EAX+16]; - movupd XMM2, [EAX+32]; - movupd XMM3, [EAX+48]; - add EAX, 64; - mulpd XMM0, XMM4; - mulpd XMM1, XMM4; - mulpd XMM2, XMM4; - mulpd XMM3, XMM4; - //divpd XMM0, XMM4; - //divpd XMM1, XMM4; - //divpd XMM2, XMM4; - //divpd XMM3, XMM4; - movupd [ESI+ 0-64], XMM0; - movupd [ESI+16-64], XMM1; - movupd [ESI+32-64], XMM2; - movupd [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloop; - - mov aptr, ESI; - mov bptr, EAX; - } - } - } - - while (aptr < aend) - { - *aptr++ = *bptr++ / value; - //*aptr++ = *bptr++ * recip; - } - - return a; -} - -unittest -{ - printf("_arraySliceExpDivSliceAssign_d unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] / 8; - - for (int i = 0; i < dim; i++) - { - //printf("[%d]: %g ?= %g / 8\n", i, c[i], a[i]); - if (c[i] != cast(T)(a[i] / 8)) - { - printf("[%d]: %g != %g / 8\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] /= value - */ - -T[] _arrayExpSliceDivass_d(T[] a, T value) -{ - //printf("_arrayExpSliceDivass_d(a.length = %d, value = %Lg)\n", a.length, cast(real)value); - auto aptr = a.ptr; - auto aend = aptr + a.length; - - /* Multiplying by the reciprocal is faster, but does - * not produce as accurate an answer. - */ - T recip = cast(T)1 / value; - - version (D_InlineAsm_X86) - { - // SSE2 version is 65% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - // Unaligned case - asm - { - mov ESI, aptr; - mov EDI, n; - movsd XMM4, recip; - //movsd XMM4, value - //rcpsd XMM4, XMM4 - shufpd XMM4, XMM4, 0; - - align 8; - startsseloopa: - movupd XMM0, [ESI]; - movupd XMM1, [ESI+16]; - movupd XMM2, [ESI+32]; - movupd XMM3, [ESI+48]; - add ESI, 64; - mulpd XMM0, XMM4; - mulpd XMM1, XMM4; - mulpd XMM2, XMM4; - mulpd XMM3, XMM4; - //divpd XMM0, XMM4; - //divpd XMM1, XMM4; - //divpd XMM2, XMM4; - //divpd XMM3, XMM4; - movupd [ESI+ 0-64], XMM0; - movupd [ESI+16-64], XMM1; - movupd [ESI+32-64], XMM2; - movupd [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloopa; - - mov aptr, ESI; - } - } - } - - while (aptr < aend) - *aptr++ *= recip; - - return a; -} - - -unittest -{ - printf("_arrayExpSliceDivass_d unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] /= 8; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] / 8)) - { - printf("[%d]: %g != %g / 8\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] -= b[] * value - */ - -T[] _arraySliceExpMulSliceMinass_d(T[] a, T value, T[] b) -{ - return _arraySliceExpMulSliceAddass_d(a, -value, b); -} - -/*********************** - * Computes: - * a[] += b[] * value - */ - -T[] _arraySliceExpMulSliceAddass_d(T[] a, T value, T[] b) -in -{ - assert(a.length == b.length); - assert(disjoint(a, b)); -} -body -{ - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - // Handle remainder - while (aptr < aend) - *aptr++ += *bptr++ * value; - - return a; -} - -unittest -{ - printf("_arraySliceExpMulSliceAddass_d unittest\n"); - - cpuid = 1; - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 1; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - b[] = c[]; - c[] += a[] * 6; - - for (int i = 0; i < dim; i++) - { - //printf("[%d]: %g ?= %g + %g * 6\n", i, c[i], b[i], a[i]); - if (c[i] != cast(T)(b[i] + a[i] * 6)) - { - printf("[%d]: %g ?= %g + %g * 6\n", i, c[i], b[i], a[i]); - assert(0); - } - } - } - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/arrayfloat.d --- a/druntime/src/compiler/ldc/arrayfloat.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2309 +0,0 @@ -/** - * Contains SSE2 and MMX versions of certain operations for float. - * - * Copyright: Copyright Digital Mars 2008 - 2009. - * License: = 16) - { - version (log) printf("\tsse unaligned\n"); - auto n = aptr + (b.length & ~15); - - // Unaligned case - asm - { - mov EAX, bptr; // left operand - mov ECX, cptr; // right operand - mov ESI, aptr; // destination operand - mov EDI, n; // end comparison - - align 8; - startsseloopb: - movups XMM0, [EAX]; - movups XMM1, [EAX+16]; - movups XMM2, [EAX+32]; - movups XMM3, [EAX+48]; - add EAX, 64; - movups XMM4, [ECX]; - movups XMM5, [ECX+16]; - movups XMM6, [ECX+32]; - movups XMM7, [ECX+48]; - add ESI, 64; - addps XMM0, XMM4; - addps XMM1, XMM5; - addps XMM2, XMM6; - addps XMM3, XMM7; - add ECX, 64; - movups [ESI+ 0-64], XMM0; - movups [ESI+16-64], XMM1; - movups [ESI+32-64], XMM2; - movups [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloopb; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - else - // 3DNow! version is only 13% faster - if (amd3dnow() && b.length >= 8) - { - version (log) printf("\tamd3dnow\n"); - auto n = aptr + (b.length & ~7); - - asm - { - mov ESI, aptr; // destination operand - mov EDI, n; // end comparison - mov EAX, bptr; // left operand - mov ECX, cptr; // right operand - - align 4; - start3dnow: - movq MM0, [EAX]; - movq MM1, [EAX+8]; - movq MM2, [EAX+16]; - movq MM3, [EAX+24]; - pfadd MM0, [ECX]; - pfadd MM1, [ECX+8]; - pfadd MM2, [ECX+16]; - pfadd MM3, [ECX+24]; - movq [ESI], MM0; - movq [ESI+8], MM1; - movq [ESI+16], MM2; - movq [ESI+24], MM3; - add ECX, 32; - add ESI, 32; - add EAX, 32; - cmp ESI, EDI; - jb start3dnow; - - emms; - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - - // Handle remainder - version (log) if (aptr < aend) printf("\tbase\n"); - while (aptr < aend) - *aptr++ = *bptr++ + *cptr++; - - return a; -} - - -unittest -{ - printf("_arraySliceSliceAddSliceAssign_f unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] + b[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] + b[i])) - { - printf("[%d]: %g != %g + %g\n", i, c[i], a[i], b[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] - c[] - */ - -T[] _arraySliceSliceMinSliceAssign_f(T[] a, T[] c, T[] b) -in -{ - assert(a.length == b.length && b.length == c.length); - assert(disjoint(a, b)); - assert(disjoint(a, c)); - assert(disjoint(b, c)); -} -body -{ - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - auto cptr = c.ptr; - - version (D_InlineAsm_X86) - { - // SSE version is 834% faster - if (sse() && b.length >= 16) - { - auto n = aptr + (b.length & ~15); - - // Unaligned case - asm - { - mov EAX, bptr; // left operand - mov ECX, cptr; // right operand - mov ESI, aptr; // destination operand - mov EDI, n; // end comparison - - align 8; - startsseloopb: - movups XMM0, [EAX]; - movups XMM1, [EAX+16]; - movups XMM2, [EAX+32]; - movups XMM3, [EAX+48]; - add EAX, 64; - movups XMM4, [ECX]; - movups XMM5, [ECX+16]; - movups XMM6, [ECX+32]; - movups XMM7, [ECX+48]; - add ESI, 64; - subps XMM0, XMM4; - subps XMM1, XMM5; - subps XMM2, XMM6; - subps XMM3, XMM7; - add ECX, 64; - movups [ESI+ 0-64], XMM0; - movups [ESI+16-64], XMM1; - movups [ESI+32-64], XMM2; - movups [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloopb; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - else - // 3DNow! version is only 13% faster - if (amd3dnow() && b.length >= 8) - { - auto n = aptr + (b.length & ~7); - - asm - { - mov ESI, aptr; // destination operand - mov EDI, n; // end comparison - mov EAX, bptr; // left operand - mov ECX, cptr; // right operand - - align 4; - start3dnow: - movq MM0, [EAX]; - movq MM1, [EAX+8]; - movq MM2, [EAX+16]; - movq MM3, [EAX+24]; - pfsub MM0, [ECX]; - pfsub MM1, [ECX+8]; - pfsub MM2, [ECX+16]; - pfsub MM3, [ECX+24]; - movq [ESI], MM0; - movq [ESI+8], MM1; - movq [ESI+16], MM2; - movq [ESI+24], MM3; - add ECX, 32; - add ESI, 32; - add EAX, 32; - cmp ESI, EDI; - jb start3dnow; - - emms; - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - - // Handle remainder - while (aptr < aend) - *aptr++ = *bptr++ - *cptr++; - - return a; -} - - -unittest -{ - printf("_arraySliceSliceMinSliceAssign_f unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] - b[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] - b[i])) - { - printf("[%d]: %g != %gd - %g\n", i, c[i], a[i], b[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] + value - */ - -T[] _arraySliceExpAddSliceAssign_f(T[] a, T value, T[] b) -in -{ - assert(a.length == b.length); - assert(disjoint(a, b)); -} -body -{ - //printf("_arraySliceExpAddSliceAssign_f()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE version is 665% faster - if (sse() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - // Unaligned case - asm - { - mov EAX, bptr; - mov ESI, aptr; - mov EDI, n; - movss XMM4, value; - shufps XMM4, XMM4, 0; - - align 8; - startsseloop: - add ESI, 64; - movups XMM0, [EAX]; - movups XMM1, [EAX+16]; - movups XMM2, [EAX+32]; - movups XMM3, [EAX+48]; - add EAX, 64; - addps XMM0, XMM4; - addps XMM1, XMM4; - addps XMM2, XMM4; - addps XMM3, XMM4; - movups [ESI+ 0-64], XMM0; - movups [ESI+16-64], XMM1; - movups [ESI+32-64], XMM2; - movups [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloop; - - mov aptr, ESI; - mov bptr, EAX; - } - } - else - // 3DNow! version is 69% faster - if (amd3dnow() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - ulong w = *cast(uint *) &value; - ulong v = w | (w << 32L); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movq MM4, qword ptr [v]; - - align 8; - start3dnow: - movq MM0, [EAX]; - movq MM1, [EAX+8]; - movq MM2, [EAX+16]; - movq MM3, [EAX+24]; - pfadd MM0, MM4; - pfadd MM1, MM4; - pfadd MM2, MM4; - pfadd MM3, MM4; - movq [ESI], MM0; - movq [ESI+8], MM1; - movq [ESI+16], MM2; - movq [ESI+24], MM3; - add ESI, 32; - add EAX, 32; - cmp ESI, EDI; - jb start3dnow; - - emms; - mov aptr, ESI; - mov bptr, EAX; - } - } - } - - while (aptr < aend) - *aptr++ = *bptr++ + value; - - return a; -} - -unittest -{ - printf("_arraySliceExpAddSliceAssign_f unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] + 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] + 6)) - { - printf("[%d]: %g != %g + 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] += value - */ - -T[] _arrayExpSliceAddass_f(T[] a, T value) -{ - //printf("_arrayExpSliceAddass_f(a.length = %d, value = %Lg)\n", a.length, cast(real)value); - auto aptr = a.ptr; - auto aend = aptr + a.length; - - version (D_InlineAsm_X86) - { - // SSE version is 302% faster - if (sse() && a.length >= 16) - { - // align pointer - auto n = cast(T*)((cast(uint)aptr + 15) & ~15); - while (aptr < n) - *aptr++ += value; - n = cast(T*)((cast(uint)aend) & ~15); - if (aptr < n) - - // Aligned case - asm - { - mov ESI, aptr; - mov EDI, n; - movss XMM4, value; - shufps XMM4, XMM4, 0; - - align 8; - startsseloopa: - movaps XMM0, [ESI]; - movaps XMM1, [ESI+16]; - movaps XMM2, [ESI+32]; - movaps XMM3, [ESI+48]; - add ESI, 64; - addps XMM0, XMM4; - addps XMM1, XMM4; - addps XMM2, XMM4; - addps XMM3, XMM4; - movaps [ESI+ 0-64], XMM0; - movaps [ESI+16-64], XMM1; - movaps [ESI+32-64], XMM2; - movaps [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloopa; - - mov aptr, ESI; - } - } - else - // 3DNow! version is 63% faster - if (amd3dnow() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - ulong w = *cast(uint *) &value; - ulong v = w | (w << 32L); - - asm - { - mov ESI, dword ptr [aptr]; - mov EDI, dword ptr [n]; - movq MM4, qword ptr [v]; - - align 8; - start3dnow: - movq MM0, [ESI]; - movq MM1, [ESI+8]; - movq MM2, [ESI+16]; - movq MM3, [ESI+24]; - pfadd MM0, MM4; - pfadd MM1, MM4; - pfadd MM2, MM4; - pfadd MM3, MM4; - movq [ESI], MM0; - movq [ESI+8], MM1; - movq [ESI+16], MM2; - movq [ESI+24], MM3; - add ESI, 32; - cmp ESI, EDI; - jb start3dnow; - - emms; - mov dword ptr [aptr], ESI; - } - } - } - - while (aptr < aend) - *aptr++ += value; - - return a; -} - -unittest -{ - printf("_arrayExpSliceAddass_f unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] += 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] + 6)) - { - printf("[%d]: %g != %g + 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] += b[] - */ - -T[] _arraySliceSliceAddass_f(T[] a, T[] b) -in -{ - assert (a.length == b.length); - assert (disjoint(a, b)); -} -body -{ - //printf("_arraySliceSliceAddass_f()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE version is 468% faster - if (sse() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - // Unaligned case - asm - { - mov ECX, bptr; // right operand - mov ESI, aptr; // destination operand - mov EDI, n; // end comparison - - align 8; - startsseloopb: - movups XMM0, [ESI]; - movups XMM1, [ESI+16]; - movups XMM2, [ESI+32]; - movups XMM3, [ESI+48]; - add ESI, 64; - movups XMM4, [ECX]; - movups XMM5, [ECX+16]; - movups XMM6, [ECX+32]; - movups XMM7, [ECX+48]; - add ECX, 64; - addps XMM0, XMM4; - addps XMM1, XMM5; - addps XMM2, XMM6; - addps XMM3, XMM7; - movups [ESI+ 0-64], XMM0; - movups [ESI+16-64], XMM1; - movups [ESI+32-64], XMM2; - movups [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloopb; - - mov aptr, ESI; - mov bptr, ECX; - } - } - else - // 3DNow! version is 57% faster - if (amd3dnow() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - asm - { - mov ESI, dword ptr [aptr]; // destination operand - mov EDI, dword ptr [n]; // end comparison - mov ECX, dword ptr [bptr]; // right operand - - align 4; - start3dnow: - movq MM0, [ESI]; - movq MM1, [ESI+8]; - movq MM2, [ESI+16]; - movq MM3, [ESI+24]; - pfadd MM0, [ECX]; - pfadd MM1, [ECX+8]; - pfadd MM2, [ECX+16]; - pfadd MM3, [ECX+24]; - movq [ESI], MM0; - movq [ESI+8], MM1; - movq [ESI+16], MM2; - movq [ESI+24], MM3; - add ESI, 32; - add ECX, 32; - cmp ESI, EDI; - jb start3dnow; - - emms; - mov dword ptr [aptr], ESI; - mov dword ptr [bptr], ECX; - } - } - } - - while (aptr < aend) - *aptr++ += *bptr++; - - return a; -} - -unittest -{ - printf("_arraySliceSliceAddass_f unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] += b[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] + b[i])) - { - printf("[%d]: %g != %g + %g\n", i, c[i], a[i], b[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] - value - */ - -T[] _arraySliceExpMinSliceAssign_f(T[] a, T value, T[] b) -in -{ - assert (a.length == b.length); - assert (disjoint(a, b)); -} -body -{ - //printf("_arraySliceExpMinSliceAssign_f()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE version is 622% faster - if (sse() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - // Unaligned case - asm - { - mov EAX, bptr; - mov ESI, aptr; - mov EDI, n; - movss XMM4, value; - shufps XMM4, XMM4, 0; - - align 8; - startsseloop: - add ESI, 64; - movups XMM0, [EAX]; - movups XMM1, [EAX+16]; - movups XMM2, [EAX+32]; - movups XMM3, [EAX+48]; - add EAX, 64; - subps XMM0, XMM4; - subps XMM1, XMM4; - subps XMM2, XMM4; - subps XMM3, XMM4; - movups [ESI+ 0-64], XMM0; - movups [ESI+16-64], XMM1; - movups [ESI+32-64], XMM2; - movups [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloop; - - mov aptr, ESI; - mov bptr, EAX; - } - } - else - // 3DNow! version is 67% faster - if (amd3dnow() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - T[2] w; - - w[0] = w[1] = value; - - asm - { - mov ESI, dword ptr [aptr]; - mov EDI, dword ptr [n]; - mov EAX, dword ptr [bptr]; - movq MM4, qword ptr [w]; - - align 8; - start3dnow: - movq MM0, [EAX]; - movq MM1, [EAX+8]; - movq MM2, [EAX+16]; - movq MM3, [EAX+24]; - pfsub MM0, MM4; - pfsub MM1, MM4; - pfsub MM2, MM4; - pfsub MM3, MM4; - movq [ESI], MM0; - movq [ESI+8], MM1; - movq [ESI+16], MM2; - movq [ESI+24], MM3; - add ESI, 32; - add EAX, 32; - cmp ESI, EDI; - jb start3dnow; - - emms; - mov dword ptr [aptr], ESI; - mov dword ptr [bptr], EAX; - } - } - } - - while (aptr < aend) - *aptr++ = *bptr++ - value; - - return a; -} - -unittest -{ - printf("_arraySliceExpMinSliceAssign_f unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] - 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] - 6)) - { - printf("[%d]: %g != %g - 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = value - b[] - */ - -T[] _arrayExpSliceMinSliceAssign_f(T[] a, T[] b, T value) -in -{ - assert (a.length == b.length); - assert (disjoint(a, b)); -} -body -{ - //printf("_arrayExpSliceMinSliceAssign_f()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE version is 690% faster - if (sse() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - // Unaligned case - asm - { - mov EAX, bptr; - mov ESI, aptr; - mov EDI, n; - movss XMM4, value; - shufps XMM4, XMM4, 0; - - align 8; - startsseloop: - add ESI, 64; - movaps XMM5, XMM4; - movaps XMM6, XMM4; - movups XMM0, [EAX]; - movups XMM1, [EAX+16]; - movups XMM2, [EAX+32]; - movups XMM3, [EAX+48]; - add EAX, 64; - subps XMM5, XMM0; - subps XMM6, XMM1; - movups [ESI+ 0-64], XMM5; - movups [ESI+16-64], XMM6; - movaps XMM5, XMM4; - movaps XMM6, XMM4; - subps XMM5, XMM2; - subps XMM6, XMM3; - movups [ESI+32-64], XMM5; - movups [ESI+48-64], XMM6; - cmp ESI, EDI; - jb startsseloop; - - mov aptr, ESI; - mov bptr, EAX; - } - } - else - // 3DNow! version is 67% faster - if (amd3dnow() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - ulong w = *cast(uint *) &value; - ulong v = w | (w << 32L); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movq MM4, qword ptr [v]; - - align 8; - start3dnow: - movq MM0, [EAX]; - movq MM1, [EAX+8]; - movq MM2, [EAX+16]; - movq MM3, [EAX+24]; - pfsubr MM0, MM4; - pfsubr MM1, MM4; - pfsubr MM2, MM4; - pfsubr MM3, MM4; - movq [ESI], MM0; - movq [ESI+8], MM1; - movq [ESI+16], MM2; - movq [ESI+24], MM3; - add ESI, 32; - add EAX, 32; - cmp ESI, EDI; - jb start3dnow; - - emms; - mov aptr, ESI; - mov bptr, EAX; - } - } - } - - while (aptr < aend) - *aptr++ = value - *bptr++; - - return a; -} - -unittest -{ - printf("_arrayExpSliceMinSliceAssign_f unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = 6 - a[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(6 - a[i])) - { - printf("[%d]: %g != 6 - %g\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] -= value - */ - -T[] _arrayExpSliceMinass_f(T[] a, T value) -{ - //printf("_arrayExpSliceMinass_f(a.length = %d, value = %Lg)\n", a.length, cast(real)value); - auto aptr = a.ptr; - auto aend = aptr + a.length; - - version (D_InlineAsm_X86) - { - // SSE version is 304% faster - if (sse() && a.length >= 16) - { - // align pointer - auto n = cast(T*)((cast(uint)aptr + 15) & ~15); - while (aptr < n) - *aptr++ -= value; - n = cast(T*)((cast(uint)aend) & ~15); - if (aptr < n) - - // Aligned case - asm - { - mov ESI, aptr; - mov EDI, n; - movss XMM4, value; - shufps XMM4, XMM4, 0; - - align 8; - startsseloopa: - movaps XMM0, [ESI]; - movaps XMM1, [ESI+16]; - movaps XMM2, [ESI+32]; - movaps XMM3, [ESI+48]; - add ESI, 64; - subps XMM0, XMM4; - subps XMM1, XMM4; - subps XMM2, XMM4; - subps XMM3, XMM4; - movaps [ESI+ 0-64], XMM0; - movaps [ESI+16-64], XMM1; - movaps [ESI+32-64], XMM2; - movaps [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloopa; - - mov aptr, ESI; - } - } - else - // 3DNow! version is 63% faster - if (amd3dnow() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - ulong w = *cast(uint *) &value; - ulong v = w | (w << 32L); - - asm - { - mov ESI, dword ptr [aptr]; - mov EDI, dword ptr [n]; - movq MM4, qword ptr [v]; - - align 8; - start: - movq MM0, [ESI]; - movq MM1, [ESI+8]; - movq MM2, [ESI+16]; - movq MM3, [ESI+24]; - pfsub MM0, MM4; - pfsub MM1, MM4; - pfsub MM2, MM4; - pfsub MM3, MM4; - movq [ESI], MM0; - movq [ESI+8], MM1; - movq [ESI+16], MM2; - movq [ESI+24], MM3; - add ESI, 32; - cmp ESI, EDI; - jb start; - - emms; - mov dword ptr [aptr], ESI; - } - } - } - - while (aptr < aend) - *aptr++ -= value; - - return a; -} - -unittest -{ - printf("_arrayExpSliceminass_f unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] -= 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] - 6)) - { - printf("[%d]: %g != %g - 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] -= b[] - */ - -T[] _arraySliceSliceMinass_f(T[] a, T[] b) -in -{ - assert (a.length == b.length); - assert (disjoint(a, b)); -} -body -{ - //printf("_arraySliceSliceMinass_f()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE version is 468% faster - if (sse() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - // Unaligned case - asm - { - mov ECX, bptr; // right operand - mov ESI, aptr; // destination operand - mov EDI, n; // end comparison - - align 8; - startsseloopb: - movups XMM0, [ESI]; - movups XMM1, [ESI+16]; - movups XMM2, [ESI+32]; - movups XMM3, [ESI+48]; - add ESI, 64; - movups XMM4, [ECX]; - movups XMM5, [ECX+16]; - movups XMM6, [ECX+32]; - movups XMM7, [ECX+48]; - add ECX, 64; - subps XMM0, XMM4; - subps XMM1, XMM5; - subps XMM2, XMM6; - subps XMM3, XMM7; - movups [ESI+ 0-64], XMM0; - movups [ESI+16-64], XMM1; - movups [ESI+32-64], XMM2; - movups [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloopb; - - mov aptr, ESI; - mov bptr, ECX; - } - } - else - // 3DNow! version is 57% faster - if (amd3dnow() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - asm - { - mov ESI, dword ptr [aptr]; // destination operand - mov EDI, dword ptr [n]; // end comparison - mov ECX, dword ptr [bptr]; // right operand - - align 4; - start: - movq MM0, [ESI]; - movq MM1, [ESI+8]; - movq MM2, [ESI+16]; - movq MM3, [ESI+24]; - pfsub MM0, [ECX]; - pfsub MM1, [ECX+8]; - pfsub MM2, [ECX+16]; - pfsub MM3, [ECX+24]; - movq [ESI], MM0; - movq [ESI+8], MM1; - movq [ESI+16], MM2; - movq [ESI+24], MM3; - add ESI, 32; - add ECX, 32; - cmp ESI, EDI; - jb start; - - emms; - mov aptr, ESI; - mov bptr, ECX; - } - } - } - - while (aptr < aend) - *aptr++ -= *bptr++; - - return a; -} - -unittest -{ - printf("_arrayExpSliceMinass_f unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] -= 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] - 6)) - { - printf("[%d]: %g != %g - 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] * value - */ - -T[] _arraySliceExpMulSliceAssign_f(T[] a, T value, T[] b) -in -{ - assert(a.length == b.length); - assert(disjoint(a, b)); -} -body -{ - //printf("_arraySliceExpMulSliceAssign_f()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE version is 607% faster - if (sse() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - // Unaligned case - asm - { - mov EAX, bptr; - mov ESI, aptr; - mov EDI, n; - movss XMM4, value; - shufps XMM4, XMM4, 0; - - align 8; - startsseloop: - add ESI, 64; - movups XMM0, [EAX]; - movups XMM1, [EAX+16]; - movups XMM2, [EAX+32]; - movups XMM3, [EAX+48]; - add EAX, 64; - mulps XMM0, XMM4; - mulps XMM1, XMM4; - mulps XMM2, XMM4; - mulps XMM3, XMM4; - movups [ESI+ 0-64], XMM0; - movups [ESI+16-64], XMM1; - movups [ESI+32-64], XMM2; - movups [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloop; - - mov aptr, ESI; - mov bptr, EAX; - } - } - else - // 3DNow! version is 69% faster - if (amd3dnow() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - ulong w = *cast(uint *) &value; - ulong v = w | (w << 32L); - - asm - { - mov ESI, dword ptr [aptr]; - mov EDI, dword ptr [n]; - mov EAX, dword ptr [bptr]; - movq MM4, qword ptr [v]; - - align 8; - start: - movq MM0, [EAX]; - movq MM1, [EAX+8]; - movq MM2, [EAX+16]; - movq MM3, [EAX+24]; - pfmul MM0, MM4; - pfmul MM1, MM4; - pfmul MM2, MM4; - pfmul MM3, MM4; - movq [ESI], MM0; - movq [ESI+8], MM1; - movq [ESI+16], MM2; - movq [ESI+24], MM3; - add ESI, 32; - add EAX, 32; - cmp ESI, EDI; - jb start; - - emms; - mov aptr, ESI; - mov bptr, EAX; - } - } - } - - while (aptr < aend) - *aptr++ = *bptr++ * value; - - return a; -} - -unittest -{ - printf("_arraySliceExpMulSliceAssign_f unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] * 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] * 6)) - { - printf("[%d]: %g != %g * 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] * c[] - */ - -T[] _arraySliceSliceMulSliceAssign_f(T[] a, T[] c, T[] b) -in -{ - assert(a.length == b.length && b.length == c.length); - assert(disjoint(a, b)); - assert(disjoint(a, c)); - assert(disjoint(b, c)); -} -body -{ - //printf("_arraySliceSliceMulSliceAssign_f()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - auto cptr = c.ptr; - - version (D_InlineAsm_X86) - { - // SSE version is 833% faster - if (sse() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - // Unaligned case - asm - { - mov EAX, bptr; // left operand - mov ECX, cptr; // right operand - mov ESI, aptr; // destination operand - mov EDI, n; // end comparison - - align 8; - startsseloopb: - movups XMM0, [EAX]; - movups XMM1, [EAX+16]; - movups XMM2, [EAX+32]; - movups XMM3, [EAX+48]; - add ESI, 64; - movups XMM4, [ECX]; - movups XMM5, [ECX+16]; - movups XMM6, [ECX+32]; - movups XMM7, [ECX+48]; - add EAX, 64; - mulps XMM0, XMM4; - mulps XMM1, XMM5; - mulps XMM2, XMM6; - mulps XMM3, XMM7; - add ECX, 64; - movups [ESI+ 0-64], XMM0; - movups [ESI+16-64], XMM1; - movups [ESI+32-64], XMM2; - movups [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloopb; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - else - // 3DNow! version is only 13% faster - if (amd3dnow() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - asm - { - mov ESI, dword ptr [aptr]; // destination operand - mov EDI, dword ptr [n]; // end comparison - mov EAX, dword ptr [bptr]; // left operand - mov ECX, dword ptr [cptr]; // right operand - - align 4; - start: - movq MM0, [EAX]; - movq MM1, [EAX+8]; - movq MM2, [EAX+16]; - movq MM3, [EAX+24]; - pfmul MM0, [ECX]; - pfmul MM1, [ECX+8]; - pfmul MM2, [ECX+16]; - pfmul MM3, [ECX+24]; - movq [ESI], MM0; - movq [ESI+8], MM1; - movq [ESI+16], MM2; - movq [ESI+24], MM3; - add ECX, 32; - add ESI, 32; - add EAX, 32; - cmp ESI, EDI; - jb start; - - emms; - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - - while (aptr < aend) - *aptr++ = *bptr++ * *cptr++; - - return a; -} - -unittest -{ - printf("_arraySliceSliceMulSliceAssign_f unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] * b[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] * b[i])) - { - printf("[%d]: %g != %g * %g\n", i, c[i], a[i], b[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] *= value - */ - -T[] _arrayExpSliceMulass_f(T[] a, T value) -{ - //printf("_arrayExpSliceMulass_f(a.length = %d, value = %Lg)\n", a.length, cast(real)value); - auto aptr = a.ptr; - auto aend = aptr + a.length; - - version (D_InlineAsm_X86) - { - // SSE version is 303% faster - if (sse() && a.length >= 16) - { - // align pointer - auto n = cast(T*)((cast(uint)aptr + 15) & ~15); - while (aptr < n) - *aptr++ *= value; - n = cast(T*)((cast(uint)aend) & ~15); - if (aptr < n) - - // Aligned case - asm - { - mov ESI, aptr; - mov EDI, n; - movss XMM4, value; - shufps XMM4, XMM4, 0; - - align 8; - startsseloopa: - movaps XMM0, [ESI]; - movaps XMM1, [ESI+16]; - movaps XMM2, [ESI+32]; - movaps XMM3, [ESI+48]; - add ESI, 64; - mulps XMM0, XMM4; - mulps XMM1, XMM4; - mulps XMM2, XMM4; - mulps XMM3, XMM4; - movaps [ESI+ 0-64], XMM0; - movaps [ESI+16-64], XMM1; - movaps [ESI+32-64], XMM2; - movaps [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloopa; - - mov aptr, ESI; - } - } - else - // 3DNow! version is 63% faster - if (amd3dnow() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - ulong w = *cast(uint *) &value; - ulong v = w | (w << 32L); - - asm - { - mov ESI, dword ptr [aptr]; - mov EDI, dword ptr [n]; - movq MM4, qword ptr [v]; - - align 8; - start: - movq MM0, [ESI]; - movq MM1, [ESI+8]; - movq MM2, [ESI+16]; - movq MM3, [ESI+24]; - pfmul MM0, MM4; - pfmul MM1, MM4; - pfmul MM2, MM4; - pfmul MM3, MM4; - movq [ESI], MM0; - movq [ESI+8], MM1; - movq [ESI+16], MM2; - movq [ESI+24], MM3; - add ESI, 32; - cmp ESI, EDI; - jb start; - - emms; - mov dword ptr [aptr], ESI; - } - } - } - - while (aptr < aend) - *aptr++ *= value; - - return a; -} - -unittest -{ - printf("_arrayExpSliceMulass_f unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] *= 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] * 6)) - { - printf("[%d]: %g != %g * 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] *= b[] - */ - -T[] _arraySliceSliceMulass_f(T[] a, T[] b) -in -{ - assert (a.length == b.length); - assert (disjoint(a, b)); -} -body -{ - //printf("_arraySliceSliceMulass_f()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE version is 525% faster - if (sse() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - // Unaligned case - asm - { - mov ECX, bptr; // right operand - mov ESI, aptr; // destination operand - mov EDI, n; // end comparison - - align 8; - startsseloopb: - movups XMM0, [ESI]; - movups XMM1, [ESI+16]; - movups XMM2, [ESI+32]; - movups XMM3, [ESI+48]; - add ESI, 64; - movups XMM4, [ECX]; - movups XMM5, [ECX+16]; - movups XMM6, [ECX+32]; - movups XMM7, [ECX+48]; - add ECX, 64; - mulps XMM0, XMM4; - mulps XMM1, XMM5; - mulps XMM2, XMM6; - mulps XMM3, XMM7; - movups [ESI+ 0-64], XMM0; - movups [ESI+16-64], XMM1; - movups [ESI+32-64], XMM2; - movups [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloopb; - - mov aptr, ESI; - mov bptr, ECX; - } - } - else - // 3DNow! version is 57% faster - if (amd3dnow() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - asm - { - mov ESI, dword ptr [aptr]; // destination operand - mov EDI, dword ptr [n]; // end comparison - mov ECX, dword ptr [bptr]; // right operand - - align 4; - start: - movq MM0, [ESI]; - movq MM1, [ESI+8]; - movq MM2, [ESI+16]; - movq MM3, [ESI+24]; - pfmul MM0, [ECX]; - pfmul MM1, [ECX+8]; - pfmul MM2, [ECX+16]; - pfmul MM3, [ECX+24]; - movq [ESI], MM0; - movq [ESI+8], MM1; - movq [ESI+16], MM2; - movq [ESI+24], MM3; - add ESI, 32; - add ECX, 32; - cmp ESI, EDI; - jb start; - - emms; - mov dword ptr [aptr], ESI; - mov dword ptr [bptr], ECX; - } - } - } - - while (aptr < aend) - *aptr++ *= *bptr++; - - return a; -} - -unittest -{ - printf("_arrayExpSliceMulass_f unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] *= 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] * 6)) - { - printf("[%d]: %g != %g * 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] / value - */ - -T[] _arraySliceExpDivSliceAssign_f(T[] a, T value, T[] b) -in -{ - assert(a.length == b.length); - assert(disjoint(a, b)); -} -body -{ - //printf("_arraySliceExpDivSliceAssign_f()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - /* Multiplying by the reciprocal is faster, but does - * not produce as accurate an answer. - */ - T recip = cast(T)1 / value; - - version (D_InlineAsm_X86) - { - // SSE version is 587% faster - if (sse() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - // Unaligned case - asm - { - mov EAX, bptr; - mov ESI, aptr; - mov EDI, n; - movss XMM4, recip; - //movss XMM4, value - //rcpss XMM4, XMM4 - shufps XMM4, XMM4, 0; - - align 8; - startsseloop: - add ESI, 64; - movups XMM0, [EAX]; - movups XMM1, [EAX+16]; - movups XMM2, [EAX+32]; - movups XMM3, [EAX+48]; - add EAX, 64; - mulps XMM0, XMM4; - mulps XMM1, XMM4; - mulps XMM2, XMM4; - mulps XMM3, XMM4; - //divps XMM0, XMM4; - //divps XMM1, XMM4; - //divps XMM2, XMM4; - //divps XMM3, XMM4; - movups [ESI+ 0-64], XMM0; - movups [ESI+16-64], XMM1; - movups [ESI+32-64], XMM2; - movups [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloop; - - mov aptr, ESI; - mov bptr, EAX; - } - } - else - // 3DNow! version is 72% faster - if (amd3dnow() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - T[2] w = void; - - w[0] = recip; - w[1] = recip; - - asm - { - mov ESI, dword ptr [aptr]; - mov EDI, dword ptr [n]; - mov EAX, dword ptr [bptr]; - movq MM4, qword ptr [w]; - - align 8; - start: - movq MM0, [EAX]; - movq MM1, [EAX+8]; - movq MM2, [EAX+16]; - movq MM3, [EAX+24]; - pfmul MM0, MM4; - pfmul MM1, MM4; - pfmul MM2, MM4; - pfmul MM3, MM4; - movq [ESI], MM0; - movq [ESI+8], MM1; - movq [ESI+16], MM2; - movq [ESI+24], MM3; - add ESI, 32; - add EAX, 32; - cmp ESI, EDI; - jb start; - - emms; - mov dword ptr [aptr], ESI; - mov dword ptr [bptr], EAX; - } - } - } - - while (aptr < aend) - *aptr++ = *bptr++ * recip; - - return a; -} - -unittest -{ - printf("_arraySliceExpDivSliceAssign_f unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] / 8; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] / 8)) - { - printf("[%d]: %g != %g / 8\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] /= value - */ - -T[] _arrayExpSliceDivass_f(T[] a, T value) -{ - //printf("_arrayExpSliceDivass_f(a.length = %d, value = %Lg)\n", a.length, cast(real)value); - auto aptr = a.ptr; - auto aend = aptr + a.length; - - /* Multiplying by the reciprocal is faster, but does - * not produce as accurate an answer. - */ - T recip = cast(T)1 / value; - - version (D_InlineAsm_X86) - { - // SSE version is 245% faster - if (sse() && a.length >= 16) - { - // align pointer - auto n = cast(T*)((cast(uint)aptr + 15) & ~15); - while (aptr < n) - *aptr++ *= recip; - n = cast(T*)((cast(uint)aend) & ~15); - if (aptr < n) - - // Aligned case - asm - { - mov ESI, aptr; - mov EDI, n; - movss XMM4, recip; - //movss XMM4, value - //rcpss XMM4, XMM4 - shufps XMM4, XMM4, 0; - - align 8; - startsseloopa: - movaps XMM0, [ESI]; - movaps XMM1, [ESI+16]; - movaps XMM2, [ESI+32]; - movaps XMM3, [ESI+48]; - add ESI, 64; - mulps XMM0, XMM4; - mulps XMM1, XMM4; - mulps XMM2, XMM4; - mulps XMM3, XMM4; - //divps XMM0, XMM4; - //divps XMM1, XMM4; - //divps XMM2, XMM4; - //divps XMM3, XMM4; - movaps [ESI+ 0-64], XMM0; - movaps [ESI+16-64], XMM1; - movaps [ESI+32-64], XMM2; - movaps [ESI+48-64], XMM3; - cmp ESI, EDI; - jb startsseloopa; - - mov aptr, ESI; - } - } - else - // 3DNow! version is 57% faster - if (amd3dnow() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - T[2] w = void; - - w[0] = w[1] = recip; - - asm - { - mov ESI, dword ptr [aptr]; - mov EDI, dword ptr [n]; - movq MM4, qword ptr [w]; - - align 8; - start: - movq MM0, [ESI]; - movq MM1, [ESI+8]; - movq MM2, [ESI+16]; - movq MM3, [ESI+24]; - pfmul MM0, MM4; - pfmul MM1, MM4; - pfmul MM2, MM4; - pfmul MM3, MM4; - movq [ESI], MM0; - movq [ESI+8], MM1; - movq [ESI+16], MM2; - movq [ESI+24], MM3; - add ESI, 32; - cmp ESI, EDI; - jb start; - - emms; - mov dword ptr [aptr], ESI; - } - } - } - - while (aptr < aend) - *aptr++ *= recip; - - return a; -} - -unittest -{ - printf("_arrayExpSliceDivass_f unittest\n"); - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - c[] /= 8; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] / 8)) - { - printf("[%d]: %g != %g / 8\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] -= b[] * value - */ - -T[] _arraySliceExpMulSliceMinass_f(T[] a, T value, T[] b) -{ - return _arraySliceExpMulSliceAddass_f(a, -value, b); -} - -/*********************** - * Computes: - * a[] += b[] * value - */ - -T[] _arraySliceExpMulSliceAddass_f(T[] a, T value, T[] b) -in -{ - assert(a.length == b.length); - assert(disjoint(a, b)); -} -body -{ - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - // Handle remainder - while (aptr < aend) - *aptr++ += *bptr++ * value; - - return a; -} - -unittest -{ - printf("_arraySliceExpMulSliceAddass_f unittest\n"); - - cpuid = 1; - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 1; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - b[] = c[]; - c[] += a[] * 6; - - for (int i = 0; i < dim; i++) - { - //printf("[%d]: %g ?= %g + %g * 6\n", i, c[i], b[i], a[i]); - if (c[i] != cast(T)(b[i] + a[i] * 6)) - { - printf("[%d]: %g ?= %g + %g * 6\n", i, c[i], b[i], a[i]); - assert(0); - } - } - } - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/arrayint.d --- a/druntime/src/compiler/ldc/arrayint.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2430 +0,0 @@ -/** - * Contains MMX versions of certain operations for dchar, int, and uint ('w', - * 'i' and 'k' suffixes). - * - * Copyright: Copyright Digital Mars 2008 - 2009. - * License: = 8) - { - auto n = aptr + (a.length & ~7); - - uint l = value; - - if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startaddsse2u: - add ESI, 32; - movdqu XMM0, [EAX]; - movdqu XMM1, [EAX+16]; - add EAX, 32; - paddd XMM0, XMM2; - paddd XMM1, XMM2; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startaddsse2u; - - mov aptr, ESI; - mov bptr, EAX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startaddsse2a: - add ESI, 32; - movdqa XMM0, [EAX]; - movdqa XMM1, [EAX+16]; - add EAX, 32; - paddd XMM0, XMM2; - paddd XMM1, XMM2; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startaddsse2a; - - mov aptr, ESI; - mov bptr, EAX; - } - } - } - else - // MMX version is 298% faster - if (mmx() && a.length >= 4) - { - auto n = aptr + (a.length & ~3); - - ulong l = cast(uint) value | (cast(ulong)cast(uint) value << 32); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movq MM2, l; - - align 4; - startmmx: - add ESI, 16; - movq MM0, [EAX]; - movq MM1, [EAX+8]; - add EAX, 16; - paddd MM0, MM2; - paddd MM1, MM2; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - mov bptr, EAX; - } - } - else - if (a.length >= 2) - { - auto n = aptr + (a.length & ~1); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov EDX, value; - - align 4; - start386: - add ESI, 8; - mov EBX, [EAX]; - mov ECX, [EAX+4]; - add EAX, 8; - add EBX, EDX; - add ECX, EDX; - mov [ESI -8], EBX; - mov [ESI+4-8], ECX; - cmp ESI, EDI; - jb start386; - - mov aptr, ESI; - mov bptr, EAX; - } - } - } - - while (aptr < aend) - *aptr++ = *bptr++ + value; - - return a; -} - -unittest -{ - printf("_arraySliceExpAddSliceAssign_i unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] + 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] + 6)) - { - printf("[%d]: %d != %d + 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] + c[] - */ - -T[] _arraySliceSliceAddSliceAssign_w(T[] a, T[] c, T[] b) -{ - return _arraySliceSliceAddSliceAssign_i(a, c, b); -} - -T[] _arraySliceSliceAddSliceAssign_k(T[] a, T[] c, T[] b) -{ - return _arraySliceSliceAddSliceAssign_i(a, c, b); -} - -T[] _arraySliceSliceAddSliceAssign_i(T[] a, T[] c, T[] b) -in -{ - assert(a.length == b.length && b.length == c.length); - assert(disjoint(a, b)); - assert(disjoint(a, c)); - assert(disjoint(b, c)); -} -body -{ - //printf("_arraySliceSliceAddSliceAssign_i()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - auto cptr = c.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 1710% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - if (((cast(uint) aptr | cast(uint) bptr | cast(uint) cptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 4; - startsse2u: - add ESI, 32; - movdqu XMM0, [EAX]; - movdqu XMM2, [ECX]; - movdqu XMM1, [EAX+16]; - movdqu XMM3, [ECX+16]; - add EAX, 32; - add ECX, 32; - paddd XMM0, XMM2; - paddd XMM1, XMM3; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2u; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 4; - startsse2a: - add ESI, 32; - movdqa XMM0, [EAX]; - movdqa XMM2, [ECX]; - movdqa XMM1, [EAX+16]; - movdqa XMM3, [ECX+16]; - add EAX, 32; - add ECX, 32; - paddd XMM0, XMM2; - paddd XMM1, XMM3; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2a; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - else - // MMX version is 995% faster - if (mmx() && a.length >= 4) - { - auto n = aptr + (a.length & ~3); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 4; - startmmx: - add ESI, 16; - movq MM0, [EAX]; - movq MM2, [ECX]; - movq MM1, [EAX+8]; - movq MM3, [ECX+8]; - add EAX, 16; - add ECX, 16; - paddd MM0, MM2; - paddd MM1, MM3; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - -normal: - while (aptr < aend) - *aptr++ = *bptr++ + *cptr++; - - return a; -} - -unittest -{ - printf("_arraySliceSliceAddSliceAssign_i unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] + b[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] + b[i])) - { - printf("[%d]: %d != %d + %d\n", i, c[i], a[i], b[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] += value - */ - -T[] _arrayExpSliceAddass_w(T[] a, T value) -{ - return _arrayExpSliceAddass_i(a, value); -} - -T[] _arrayExpSliceAddass_k(T[] a, T value) -{ - return _arrayExpSliceAddass_i(a, value); -} - -T[] _arrayExpSliceAddass_i(T[] a, T value) -{ - //printf("_arrayExpSliceAddass_i(a.length = %d, value = %Lg)\n", a.length, cast(real)value); - auto aptr = a.ptr; - auto aend = aptr + a.length; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 83% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - uint l = value; - - if (((cast(uint) aptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startaddsse2u: - movdqu XMM0, [ESI]; - movdqu XMM1, [ESI+16]; - add ESI, 32; - paddd XMM0, XMM2; - paddd XMM1, XMM2; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startaddsse2u; - - mov aptr, ESI; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startaddsse2a: - movdqa XMM0, [ESI]; - movdqa XMM1, [ESI+16]; - add ESI, 32; - paddd XMM0, XMM2; - paddd XMM1, XMM2; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startaddsse2a; - - mov aptr, ESI; - } - } - } - else - // MMX version is 81% faster - if (mmx() && a.length >= 4) - { - auto n = aptr + (a.length & ~3); - - ulong l = cast(uint) value | (cast(ulong)cast(uint) value << 32); - - asm - { - mov ESI, aptr; - mov EDI, n; - movq MM2, l; - - align 4; - startmmx: - movq MM0, [ESI]; - movq MM1, [ESI+8]; - add ESI, 16; - paddd MM0, MM2; - paddd MM1, MM2; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - } - } - else - if (a.length >= 2) - { - auto n = aptr + (a.length & ~1); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EDX, value; - - align 4; - start386: - mov EBX, [ESI]; - mov ECX, [ESI+4]; - add ESI, 8; - add EBX, EDX; - add ECX, EDX; - mov [ESI -8], EBX; - mov [ESI+4-8], ECX; - cmp ESI, EDI; - jb start386; - - mov aptr, ESI; - } - } - } - - while (aptr < aend) - *aptr++ += value; - - return a; -} - -unittest -{ - printf("_arrayExpSliceAddass_i unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - a[] += 6; - - for (int i = 0; i < dim; i++) - { - if (a[i] != cast(T)(c[i] + 6)) - { - printf("[%d]: %d != %d + 6\n", i, a[i], c[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] += b[] - */ - -T[] _arraySliceSliceAddass_w(T[] a, T[] b) -{ - return _arraySliceSliceAddass_i(a, b); -} - -T[] _arraySliceSliceAddass_k(T[] a, T[] b) -{ - return _arraySliceSliceAddass_i(a, b); -} - -T[] _arraySliceSliceAddass_i(T[] a, T[] b) -in -{ - assert (a.length == b.length); - assert (disjoint(a, b)); -} -body -{ - //printf("_arraySliceSliceAddass_i()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 695% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 4; - startsse2u: - movdqu XMM0, [ESI]; - movdqu XMM2, [ECX]; - movdqu XMM1, [ESI+16]; - movdqu XMM3, [ECX+16]; - add ESI, 32; - add ECX, 32; - paddd XMM0, XMM2; - paddd XMM1, XMM3; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2u; - - mov aptr, ESI; - mov bptr, ECX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 4; - startsse2a: - movdqa XMM0, [ESI]; - movdqa XMM2, [ECX]; - movdqa XMM1, [ESI+16]; - movdqa XMM3, [ECX+16]; - add ESI, 32; - add ECX, 32; - paddd XMM0, XMM2; - paddd XMM1, XMM3; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2a; - - mov aptr, ESI; - mov bptr, ECX; - } - } - } - else - // MMX version is 471% faster - if (mmx() && a.length >= 4) - { - auto n = aptr + (a.length & ~3); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 4; - startmmx: - movq MM0, [ESI]; - movq MM2, [ECX]; - movq MM1, [ESI+8]; - movq MM3, [ECX+8]; - add ESI, 16; - add ECX, 16; - paddd MM0, MM2; - paddd MM1, MM3; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - mov bptr, ECX; - } - } - } - -normal: - while (aptr < aend) - *aptr++ += *bptr++; - - return a; -} - -unittest -{ - printf("_arraySliceSliceAddass_i unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - b[] = c[]; - c[] += a[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(b[i] + a[i])) - { - printf("[%d]: %d != %d + %d\n", i, c[i], b[i], a[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] - value - */ - -T[] _arraySliceExpMinSliceAssign_w(T[] a, T value, T[] b) -{ - return _arraySliceExpMinSliceAssign_i(a, value, b); -} - -T[] _arraySliceExpMinSliceAssign_k(T[] a, T value, T[] b) -{ - return _arraySliceExpMinSliceAssign_i(a, value, b); -} - -T[] _arraySliceExpMinSliceAssign_i(T[] a, T value, T[] b) -in -{ - assert(a.length == b.length); - assert(disjoint(a, b)); -} -body -{ - //printf("_arraySliceExpMinSliceAssign_i()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 400% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - uint l = value; - - if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startaddsse2u: - add ESI, 32; - movdqu XMM0, [EAX]; - movdqu XMM1, [EAX+16]; - add EAX, 32; - psubd XMM0, XMM2; - psubd XMM1, XMM2; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startaddsse2u; - - mov aptr, ESI; - mov bptr, EAX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startaddsse2a: - add ESI, 32; - movdqa XMM0, [EAX]; - movdqa XMM1, [EAX+16]; - add EAX, 32; - psubd XMM0, XMM2; - psubd XMM1, XMM2; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startaddsse2a; - - mov aptr, ESI; - mov bptr, EAX; - } - } - } - else - // MMX version is 315% faster - if (mmx() && a.length >= 4) - { - auto n = aptr + (a.length & ~3); - - ulong l = cast(uint) value | (cast(ulong)cast(uint) value << 32); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movq MM2, l; - - align 4; - startmmx: - add ESI, 16; - movq MM0, [EAX]; - movq MM1, [EAX+8]; - add EAX, 16; - psubd MM0, MM2; - psubd MM1, MM2; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - mov bptr, EAX; - } - } - else - if (a.length >= 2) - { - auto n = aptr + (a.length & ~1); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov EDX, value; - - align 4; - start386: - add ESI, 8; - mov EBX, [EAX]; - mov ECX, [EAX+4]; - add EAX, 8; - sub EBX, EDX; - sub ECX, EDX; - mov [ESI -8], EBX; - mov [ESI+4-8], ECX; - cmp ESI, EDI; - jb start386; - - mov aptr, ESI; - mov bptr, EAX; - } - } - } - - while (aptr < aend) - *aptr++ = *bptr++ - value; - - return a; -} - -unittest -{ - printf("_arraySliceExpMinSliceAssign_i unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] - 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] - 6)) - { - printf("[%d]: %d != %d - 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = value - b[] - */ - -T[] _arrayExpSliceMinSliceAssign_w(T[] a, T[] b, T value) -{ - return _arrayExpSliceMinSliceAssign_i(a, b, value); -} - -T[] _arrayExpSliceMinSliceAssign_k(T[] a, T[] b, T value) -{ - return _arrayExpSliceMinSliceAssign_i(a, b, value); -} - -T[] _arrayExpSliceMinSliceAssign_i(T[] a, T[] b, T value) -in -{ - assert(a.length == b.length); - assert(disjoint(a, b)); -} -body -{ - //printf("_arrayExpSliceMinSliceAssign_i()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 1812% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - uint l = value; - - if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM4, l; - pshufd XMM4, XMM4, 0; - - align 4; - startaddsse2u: - add ESI, 32; - movdqu XMM2, [EAX]; - movdqu XMM3, [EAX+16]; - movdqa XMM0, XMM4; - movdqa XMM1, XMM4; - add EAX, 32; - psubd XMM0, XMM2; - psubd XMM1, XMM3; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startaddsse2u; - - mov aptr, ESI; - mov bptr, EAX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM4, l; - pshufd XMM4, XMM4, 0; - - align 4; - startaddsse2a: - add ESI, 32; - movdqa XMM2, [EAX]; - movdqa XMM3, [EAX+16]; - movdqa XMM0, XMM4; - movdqa XMM1, XMM4; - add EAX, 32; - psubd XMM0, XMM2; - psubd XMM1, XMM3; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startaddsse2a; - - mov aptr, ESI; - mov bptr, EAX; - } - } - } - else - // MMX version is 1077% faster - if (mmx() && a.length >= 4) - { - auto n = aptr + (a.length & ~3); - - ulong l = cast(uint) value | (cast(ulong)cast(uint) value << 32); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movq MM4, l; - - align 4; - startmmx: - add ESI, 16; - movq MM2, [EAX]; - movq MM3, [EAX+8]; - movq MM0, MM4; - movq MM1, MM4; - add EAX, 16; - psubd MM0, MM2; - psubd MM1, MM3; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - mov bptr, EAX; - } - } - } - - while (aptr < aend) - *aptr++ = value - *bptr++; - - return a; -} - -unittest -{ - printf("_arrayExpSliceMinSliceAssign_i unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = 6 - a[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(6 - a[i])) - { - printf("[%d]: %d != 6 - %d\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] - c[] - */ - -T[] _arraySliceSliceMinSliceAssign_w(T[] a, T[] c, T[] b) -{ - return _arraySliceSliceMinSliceAssign_i(a, c, b); -} - -T[] _arraySliceSliceMinSliceAssign_k(T[] a, T[] c, T[] b) -{ - return _arraySliceSliceMinSliceAssign_i(a, c, b); -} - -T[] _arraySliceSliceMinSliceAssign_i(T[] a, T[] c, T[] b) -in -{ - assert(a.length == b.length && b.length == c.length); - assert(disjoint(a, b)); - assert(disjoint(a, c)); - assert(disjoint(b, c)); -} -body -{ - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - auto cptr = c.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 1721% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - if (((cast(uint) aptr | cast(uint) bptr | cast(uint) cptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 4; - startsse2u: - add ESI, 32; - movdqu XMM0, [EAX]; - movdqu XMM2, [ECX]; - movdqu XMM1, [EAX+16]; - movdqu XMM3, [ECX+16]; - add EAX, 32; - add ECX, 32; - psubd XMM0, XMM2; - psubd XMM1, XMM3; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2u; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 4; - startsse2a: - add ESI, 32; - movdqa XMM0, [EAX]; - movdqa XMM2, [ECX]; - movdqa XMM1, [EAX+16]; - movdqa XMM3, [ECX+16]; - add EAX, 32; - add ECX, 32; - psubd XMM0, XMM2; - psubd XMM1, XMM3; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2a; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - else - // MMX version is 1002% faster - if (mmx() && a.length >= 4) - { - auto n = aptr + (a.length & ~3); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 4; - startmmx: - add ESI, 16; - movq MM0, [EAX]; - movq MM2, [ECX]; - movq MM1, [EAX+8]; - movq MM3, [ECX+8]; - add EAX, 16; - add ECX, 16; - psubd MM0, MM2; - psubd MM1, MM3; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - - while (aptr < aend) - *aptr++ = *bptr++ - *cptr++; - - return a; -} - -unittest -{ - printf("_arraySliceSliceMinSliceAssign_i unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] - b[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] - b[i])) - { - printf("[%d]: %d != %d - %d\n", i, c[i], a[i], b[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] -= value - */ - -T[] _arrayExpSliceMinass_w(T[] a, T value) -{ - return _arrayExpSliceMinass_i(a, value); -} - -T[] _arrayExpSliceMinass_k(T[] a, T value) -{ - return _arrayExpSliceMinass_i(a, value); -} - -T[] _arrayExpSliceMinass_i(T[] a, T value) -{ - //printf("_arrayExpSliceMinass_i(a.length = %d, value = %Lg)\n", a.length, cast(real)value); - auto aptr = a.ptr; - auto aend = aptr + a.length; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 81% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - uint l = value; - - if (((cast(uint) aptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startaddsse2u: - movdqu XMM0, [ESI]; - movdqu XMM1, [ESI+16]; - add ESI, 32; - psubd XMM0, XMM2; - psubd XMM1, XMM2; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startaddsse2u; - - mov aptr, ESI; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startaddsse2a: - movdqa XMM0, [ESI]; - movdqa XMM1, [ESI+16]; - add ESI, 32; - psubd XMM0, XMM2; - psubd XMM1, XMM2; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startaddsse2a; - - mov aptr, ESI; - } - } - } - else - // MMX version is 81% faster - if (mmx() && a.length >= 4) - { - auto n = aptr + (a.length & ~3); - - ulong l = cast(uint) value | (cast(ulong)cast(uint) value << 32); - - asm - { - mov ESI, aptr; - mov EDI, n; - movq MM2, l; - - align 4; - startmmx: - movq MM0, [ESI]; - movq MM1, [ESI+8]; - add ESI, 16; - psubd MM0, MM2; - psubd MM1, MM2; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - } - } - else - if (a.length >= 2) - { - auto n = aptr + (a.length & ~1); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EDX, value; - - align 4; - start386: - mov EBX, [ESI]; - mov ECX, [ESI+4]; - add ESI, 8; - sub EBX, EDX; - sub ECX, EDX; - mov [ESI -8], EBX; - mov [ESI+4-8], ECX; - cmp ESI, EDI; - jb start386; - - mov aptr, ESI; - } - } - } - - while (aptr < aend) - *aptr++ -= value; - - return a; -} - -unittest -{ - printf("_arrayExpSliceMinass_i unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - a[] -= 6; - - for (int i = 0; i < dim; i++) - { - if (a[i] != cast(T)(c[i] - 6)) - { - printf("[%d]: %d != %d - 6\n", i, a[i], c[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] -= b[] - */ - -T[] _arraySliceSliceMinass_w(T[] a, T[] b) -{ - return _arraySliceSliceMinass_i(a, b); -} - -T[] _arraySliceSliceMinass_k(T[] a, T[] b) -{ - return _arraySliceSliceMinass_i(a, b); -} - -T[] _arraySliceSliceMinass_i(T[] a, T[] b) -in -{ - assert (a.length == b.length); - assert (disjoint(a, b)); -} -body -{ - //printf("_arraySliceSliceMinass_i()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 731% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 4; - startsse2u: - movdqu XMM0, [ESI]; - movdqu XMM2, [ECX]; - movdqu XMM1, [ESI+16]; - movdqu XMM3, [ECX+16]; - add ESI, 32; - add ECX, 32; - psubd XMM0, XMM2; - psubd XMM1, XMM3; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2u; - - mov aptr, ESI; - mov bptr, ECX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 4; - startsse2a: - movdqa XMM0, [ESI]; - movdqa XMM2, [ECX]; - movdqa XMM1, [ESI+16]; - movdqa XMM3, [ECX+16]; - add ESI, 32; - add ECX, 32; - psubd XMM0, XMM2; - psubd XMM1, XMM3; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2a; - - mov aptr, ESI; - mov bptr, ECX; - } - } - } - else - // MMX version is 441% faster - if (mmx() && a.length >= 4) - { - auto n = aptr + (a.length & ~3); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 4; - startmmx: - movq MM0, [ESI]; - movq MM2, [ECX]; - movq MM1, [ESI+8]; - movq MM3, [ECX+8]; - add ESI, 16; - add ECX, 16; - psubd MM0, MM2; - psubd MM1, MM3; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - mov bptr, ECX; - } - } - } - - while (aptr < aend) - *aptr++ -= *bptr++; - - return a; -} - -unittest -{ - printf("_arraySliceSliceMinass_i unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - b[] = c[]; - c[] -= a[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(b[i] - a[i])) - { - printf("[%d]: %d != %d - %d\n", i, c[i], b[i], a[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] * value - */ - -T[] _arraySliceExpMulSliceAssign_w(T[] a, T value, T[] b) -{ - return _arraySliceExpMulSliceAssign_i(a, value, b); -} - -T[] _arraySliceExpMulSliceAssign_k(T[] a, T value, T[] b) -{ - return _arraySliceExpMulSliceAssign_i(a, value, b); -} - -T[] _arraySliceExpMulSliceAssign_i(T[] a, T value, T[] b) -in -{ - assert(a.length == b.length); - assert(disjoint(a, b)); -} -body -{ - //printf("_arraySliceExpMulSliceAssign_i()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (none) // multiplying a pair is not supported by MMX - { - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 1380% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - uint l = value; - - if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0) - { - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startsse2u: - add ESI, 32; - movdqu XMM0, [EAX]; - movdqu XMM1, [EAX+16]; - add EAX, 32; - pmuludq XMM0, XMM2; - pmuludq XMM1, XMM2; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2u; - - mov aptr, ESI; - mov bptr, EAX; - } - } - else - { - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startsse2a: - add ESI, 32; - movdqa XMM0, [EAX]; - movdqa XMM1, [EAX+16]; - add EAX, 32; - pmuludq XMM0, XMM2; - pmuludq XMM1, XMM2; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2a; - - mov aptr, ESI; - mov bptr, EAX; - } - } - } - else - { - // MMX version is 1380% faster - if (mmx() && a.length >= 4) - { - auto n = aptr + (a.length & ~3); - - ulong l = cast(uint) value | (cast(ulong)cast(uint) value << 32); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movq MM2, l; - - align 4; - startmmx: - add ESI, 16; - movq MM0, [EAX]; - movq MM1, [EAX+8]; - add EAX, 16; - pmuludq MM0, MM2; // only multiplies low 32 bits - pmuludq MM1, MM2; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - mov bptr, EAX; - } - } - } - } - } - - while (aptr < aend) - *aptr++ = *bptr++ * value; - - return a; -} - -unittest -{ - printf("_arraySliceExpMulSliceAssign_s unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] * 6; - - for (int i = 0; i < dim; i++) - { - //printf("[%d]: %d ?= %d * 6\n", i, c[i], a[i]); - if (c[i] != cast(T)(a[i] * 6)) - { - printf("[%d]: %d != %d * 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] * c[] - */ - -T[] _arraySliceSliceMulSliceAssign_w(T[] a, T[] c, T[] b) -{ - return _arraySliceSliceMulSliceAssign_i(a, c, b); -} - -T[] _arraySliceSliceMulSliceAssign_k(T[] a, T[] c, T[] b) -{ - return _arraySliceSliceMulSliceAssign_i(a, c, b); -} - -T[] _arraySliceSliceMulSliceAssign_i(T[] a, T[] c, T[] b) -in -{ - assert(a.length == b.length && b.length == c.length); - assert(disjoint(a, b)); - assert(disjoint(a, c)); - assert(disjoint(b, c)); -} -body -{ - //printf("_arraySliceSliceMulSliceAssign_i()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - auto cptr = c.ptr; - - version (none) - { - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 1407% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - if (((cast(uint) aptr | cast(uint) bptr | cast(uint) cptr) & 15) != 0) - { - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 4; - startsse2u: - add ESI, 32; - movdqu XMM0, [EAX]; - movdqu XMM2, [ECX]; - movdqu XMM1, [EAX+16]; - movdqu XMM3, [ECX+16]; - add EAX, 32; - add ECX, 32; - pmuludq XMM0, XMM2; - pmuludq XMM1, XMM3; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2u; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - else - { - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 4; - startsse2a: - add ESI, 32; - movdqa XMM0, [EAX]; - movdqa XMM2, [ECX]; - movdqa XMM1, [EAX+16]; - movdqa XMM3, [ECX+16]; - add EAX, 32; - add ECX, 32; - pmuludq XMM0, XMM2; - pmuludq XMM1, XMM3; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2a; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - else - // MMX version is 1029% faster - if (mmx() && a.length >= 4) - { - auto n = aptr + (a.length & ~3); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 4; - startmmx: - add ESI, 16; - movq MM0, [EAX]; - movq MM2, [ECX]; - movq MM1, [EAX+8]; - movq MM3, [ECX+8]; - add EAX, 16; - add ECX, 16; - pmuludq MM0, MM2; - pmuludq MM1, MM3; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - } - - while (aptr < aend) - *aptr++ = *bptr++ * *cptr++; - - return a; -} - -unittest -{ - printf("_arraySliceSliceMulSliceAssign_i unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] * b[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] * b[i])) - { - printf("[%d]: %d != %d * %d\n", i, c[i], a[i], b[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] *= value - */ - -T[] _arrayExpSliceMulass_w(T[] a, T value) -{ - return _arrayExpSliceMulass_i(a, value); -} - -T[] _arrayExpSliceMulass_k(T[] a, T value) -{ - return _arrayExpSliceMulass_i(a, value); -} - -T[] _arrayExpSliceMulass_i(T[] a, T value) -{ - //printf("_arrayExpSliceMulass_i(a.length = %d, value = %Lg)\n", a.length, cast(real)value); - auto aptr = a.ptr; - auto aend = aptr + a.length; - - version (none) - { - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 400% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - uint l = value; - - if (((cast(uint) aptr) & 15) != 0) - { - asm - { - mov ESI, aptr; - mov EDI, n; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startsse2u: - movdqu XMM0, [ESI]; - movdqu XMM1, [ESI+16]; - add ESI, 32; - pmuludq XMM0, XMM2; - pmuludq XMM1, XMM2; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2u; - - mov aptr, ESI; - } - } - else - { - asm - { - mov ESI, aptr; - mov EDI, n; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startsse2a: - movdqa XMM0, [ESI]; - movdqa XMM1, [ESI+16]; - add ESI, 32; - pmuludq XMM0, XMM2; - pmuludq XMM1, XMM2; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2a; - - mov aptr, ESI; - } - } - } - else - // MMX version is 402% faster - if (mmx() && a.length >= 4) - { - auto n = aptr + (a.length & ~3); - - ulong l = cast(uint) value | (cast(ulong)cast(uint) value << 32); - - asm - { - mov ESI, aptr; - mov EDI, n; - movq MM2, l; - - align 4; - startmmx: - movq MM0, [ESI]; - movq MM1, [ESI+8]; - add ESI, 16; - pmuludq MM0, MM2; - pmuludq MM1, MM2; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - } - } - } - } - - while (aptr < aend) - *aptr++ *= value; - - return a; -} - -unittest -{ - printf("_arrayExpSliceMulass_i unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - b[] = a[]; - a[] *= 6; - - for (int i = 0; i < dim; i++) - { - if (a[i] != cast(T)(b[i] * 6)) - { - printf("[%d]: %d != %d * 6\n", i, a[i], b[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] *= b[] - */ - -T[] _arraySliceSliceMulass_w(T[] a, T[] b) -{ - return _arraySliceSliceMulass_i(a, b); -} - -T[] _arraySliceSliceMulass_k(T[] a, T[] b) -{ - return _arraySliceSliceMulass_i(a, b); -} - -T[] _arraySliceSliceMulass_i(T[] a, T[] b) -in -{ - assert (a.length == b.length); - assert (disjoint(a, b)); -} -body -{ - //printf("_arraySliceSliceMulass_i()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (none) - { - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 873% faster - if (sse2() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0) - { - asm - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 4; - startsse2u: - movdqu XMM0, [ESI]; - movdqu XMM2, [ECX]; - movdqu XMM1, [ESI+16]; - movdqu XMM3, [ECX+16]; - add ESI, 32; - add ECX, 32; - pmuludq XMM0, XMM2; - pmuludq XMM1, XMM3; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2u; - - mov aptr, ESI; - mov bptr, ECX; - } - } - else - { - asm - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 4; - startsse2a: - movdqa XMM0, [ESI]; - movdqa XMM2, [ECX]; - movdqa XMM1, [ESI+16]; - movdqa XMM3, [ECX+16]; - add ESI, 32; - add ECX, 32; - pmuludq XMM0, XMM2; - pmuludq XMM1, XMM3; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2a; - - mov aptr, ESI; - mov bptr, ECX; - } - } - } -/+ BUG: comment out this section until we figure out what is going - wrong with the invalid pshufd instructions. - - else - // MMX version is 573% faster - if (mmx() && a.length >= 4) - { - auto n = aptr + (a.length & ~3); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 4; - startmmx: - movq MM0, [ESI]; - movq MM2, [ECX]; - movq MM1, [ESI+8]; - movq MM3, [ECX+8]; - pxor MM4, MM4; - pxor MM5, MM5; - punpckldq MM4, MM0; - punpckldq MM5, MM2; - add ESI, 16; - add ECX, 16; - pmuludq MM4, MM5; - pshufd MM4, MM4, 8; // ? - movq [ESI -16], MM4; - pxor MM4, MM4; - pxor MM5, MM5; - punpckldq MM4, MM1; - punpckldq MM5, MM3; - pmuludq MM4, MM5; - pshufd MM4, MM4, 8; // ? - movq [ESI+8-16], MM4; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - mov bptr, ECX; - } - } -+/ - } - } - - while (aptr < aend) - *aptr++ *= *bptr++; - - return a; -} - -unittest -{ - printf("_arraySliceSliceMulass_i unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - b[] = a[]; - a[] *= c[]; - - for (int i = 0; i < dim; i++) - { - if (a[i] != cast(T)(b[i] * c[i])) - { - printf("[%d]: %d != %d * %d\n", i, a[i], b[i], c[i]); - assert(0); - } - } - } - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/arrayreal.d --- a/druntime/src/compiler/ldc/arrayreal.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,241 +0,0 @@ -/** - * Contains SSE2 and MMX versions of certain operations for real. - * - * Copyright: Copyright Digital Mars 2008 - 2009. - * License: = 16) - { - auto n = aptr + (a.length & ~15); - - uint l = cast(ushort) value; - l |= (l << 16); - - if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startaddsse2u: - add ESI, 32; - movdqu XMM0, [EAX]; - movdqu XMM1, [EAX+16]; - add EAX, 32; - paddw XMM0, XMM2; - paddw XMM1, XMM2; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startaddsse2u; - - mov aptr, ESI; - mov bptr, EAX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startaddsse2a: - add ESI, 32; - movdqa XMM0, [EAX]; - movdqa XMM1, [EAX+16]; - add EAX, 32; - paddw XMM0, XMM2; - paddw XMM1, XMM2; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startaddsse2a; - - mov aptr, ESI; - mov bptr, EAX; - } - } - } - else - // MMX version is 3343% faster - if (mmx() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - uint l = cast(ushort) value; - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd MM2, l; - pshufw MM2, MM2, 0; - - align 4; - startmmx: - add ESI, 16; - movq MM0, [EAX]; - movq MM1, [EAX+8]; - add EAX, 16; - paddw MM0, MM2; - paddw MM1, MM2; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - mov bptr, EAX; - } - } - } - - while (aptr < aend) - *aptr++ = cast(T)(*bptr++ + value); - - return a; -} - -unittest -{ - printf("_arraySliceExpAddSliceAssign_s unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] + 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] + 6)) - { - printf("[%d]: %d != %d + 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] + c[] - */ - -T[] _arraySliceSliceAddSliceAssign_u(T[] a, T[] c, T[] b) -{ - return _arraySliceSliceAddSliceAssign_s(a, c, b); -} - -T[] _arraySliceSliceAddSliceAssign_t(T[] a, T[] c, T[] b) -{ - return _arraySliceSliceAddSliceAssign_s(a, c, b); -} - -T[] _arraySliceSliceAddSliceAssign_s(T[] a, T[] c, T[] b) -in -{ - assert(a.length == b.length && b.length == c.length); - assert(disjoint(a, b)); - assert(disjoint(a, c)); - assert(disjoint(b, c)); -} -body -{ - //printf("_arraySliceSliceAddSliceAssign_s()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - auto cptr = c.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 3777% faster - if (sse2() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - if (((cast(uint) aptr | cast(uint) bptr | cast(uint) cptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 4; - startsse2u: - add ESI, 32; - movdqu XMM0, [EAX]; - movdqu XMM1, [EAX+16]; - add EAX, 32; - movdqu XMM2, [ECX]; - movdqu XMM3, [ECX+16]; - add ECX, 32; - paddw XMM0, XMM2; - paddw XMM1, XMM3; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2u; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 4; - startsse2a: - add ESI, 32; - movdqa XMM0, [EAX]; - movdqa XMM1, [EAX+16]; - add EAX, 32; - movdqa XMM2, [ECX]; - movdqa XMM3, [ECX+16]; - add ECX, 32; - paddw XMM0, XMM2; - paddw XMM1, XMM3; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2a; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - else - // MMX version is 2068% faster - if (mmx() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 4; - startmmx: - add ESI, 16; - movq MM0, [EAX]; - movq MM1, [EAX+8]; - add EAX, 16; - movq MM2, [ECX]; - movq MM3, [ECX+8]; - add ECX, 16; - paddw MM0, MM2; - paddw MM1, MM3; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - - while (aptr < aend) - *aptr++ = cast(T)(*bptr++ + *cptr++); - - return a; -} - -unittest -{ - printf("_arraySliceSliceAddSliceAssign_s unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] + b[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] + b[i])) - { - printf("[%d]: %d != %d + %d\n", i, c[i], a[i], b[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] += value - */ - -T[] _arrayExpSliceAddass_u(T[] a, T value) -{ - return _arrayExpSliceAddass_s(a, value); -} - -T[] _arrayExpSliceAddass_t(T[] a, T value) -{ - return _arrayExpSliceAddass_s(a, value); -} - -T[] _arrayExpSliceAddass_s(T[] a, T value) -{ - //printf("_arrayExpSliceAddass_s(a.length = %d, value = %Lg)\n", a.length, cast(real)value); - auto aptr = a.ptr; - auto aend = aptr + a.length; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 832% faster - if (sse2() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - uint l = cast(ushort) value; - l |= (l << 16); - - if (((cast(uint) aptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startaddsse2u: - movdqu XMM0, [ESI]; - movdqu XMM1, [ESI+16]; - add ESI, 32; - paddw XMM0, XMM2; - paddw XMM1, XMM2; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startaddsse2u; - - mov aptr, ESI; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startaddsse2a: - movdqa XMM0, [ESI]; - movdqa XMM1, [ESI+16]; - add ESI, 32; - paddw XMM0, XMM2; - paddw XMM1, XMM2; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startaddsse2a; - - mov aptr, ESI; - } - } - } - else - // MMX version is 826% faster - if (mmx() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - uint l = cast(ushort) value; - - asm - { - mov ESI, aptr; - mov EDI, n; - movd MM2, l; - pshufw MM2, MM2, 0; - - align 4; - startmmx: - movq MM0, [ESI]; - movq MM1, [ESI+8]; - add ESI, 16; - paddw MM0, MM2; - paddw MM1, MM2; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - } - } - } - - while (aptr < aend) - *aptr++ += value; - - return a; -} - -unittest -{ - printf("_arrayExpSliceAddass_s unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - a[] += 6; - - for (int i = 0; i < dim; i++) - { - if (a[i] != cast(T)(c[i] + 6)) - { - printf("[%d]: %d != %d + 6\n", i, a[i], c[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] += b[] - */ - -T[] _arraySliceSliceAddass_u(T[] a, T[] b) -{ - return _arraySliceSliceAddass_s(a, b); -} - -T[] _arraySliceSliceAddass_t(T[] a, T[] b) -{ - return _arraySliceSliceAddass_s(a, b); -} - -T[] _arraySliceSliceAddass_s(T[] a, T[] b) -in -{ - assert (a.length == b.length); - assert (disjoint(a, b)); -} -body -{ - //printf("_arraySliceSliceAddass_s()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 2085% faster - if (sse2() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 4; - startsse2u: - movdqu XMM0, [ESI]; - movdqu XMM1, [ESI+16]; - add ESI, 32; - movdqu XMM2, [ECX]; - movdqu XMM3, [ECX+16]; - add ECX, 32; - paddw XMM0, XMM2; - paddw XMM1, XMM3; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2u; - - mov aptr, ESI; - mov bptr, ECX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 4; - startsse2a: - movdqa XMM0, [ESI]; - movdqa XMM1, [ESI+16]; - add ESI, 32; - movdqa XMM2, [ECX]; - movdqa XMM3, [ECX+16]; - add ECX, 32; - paddw XMM0, XMM2; - paddw XMM1, XMM3; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2a; - - mov aptr, ESI; - mov bptr, ECX; - } - } - } - else - // MMX version is 1022% faster - if (mmx() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 4; - start: - movq MM0, [ESI]; - movq MM1, [ESI+8]; - add ESI, 16; - movq MM2, [ECX]; - movq MM3, [ECX+8]; - add ECX, 16; - paddw MM0, MM2; - paddw MM1, MM3; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb start; - - emms; - mov aptr, ESI; - mov bptr, ECX; - } - } - } - - while (aptr < aend) - *aptr++ += *bptr++; - - return a; -} - -unittest -{ - printf("_arraySliceSliceAddass_s unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - b[] = c[]; - c[] += a[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(b[i] + a[i])) - { - printf("[%d]: %d != %d + %d\n", i, c[i], b[i], a[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] - value - */ - -T[] _arraySliceExpMinSliceAssign_u(T[] a, T value, T[] b) -{ - return _arraySliceExpMinSliceAssign_s(a, value, b); -} - -T[] _arraySliceExpMinSliceAssign_t(T[] a, T value, T[] b) -{ - return _arraySliceExpMinSliceAssign_s(a, value, b); -} - -T[] _arraySliceExpMinSliceAssign_s(T[] a, T value, T[] b) -in -{ - assert(a.length == b.length); - assert(disjoint(a, b)); -} -body -{ - //printf("_arraySliceExpMinSliceAssign_s()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 3695% faster - if (sse2() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - uint l = cast(ushort) value; - l |= (l << 16); - - if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startaddsse2u: - add ESI, 32; - movdqu XMM0, [EAX]; - movdqu XMM1, [EAX+16]; - add EAX, 32; - psubw XMM0, XMM2; - psubw XMM1, XMM2; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startaddsse2u; - - mov aptr, ESI; - mov bptr, EAX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startaddsse2a: - add ESI, 32; - movdqa XMM0, [EAX]; - movdqa XMM1, [EAX+16]; - add EAX, 32; - psubw XMM0, XMM2; - psubw XMM1, XMM2; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startaddsse2a; - - mov aptr, ESI; - mov bptr, EAX; - } - } - } - else - // MMX version is 3049% faster - if (mmx() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - uint l = cast(ushort) value; - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd MM2, l; - pshufw MM2, MM2, 0; - - align 4; - startmmx: - add ESI, 16; - movq MM0, [EAX]; - movq MM1, [EAX+8]; - add EAX, 16; - psubw MM0, MM2; - psubw MM1, MM2; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - mov bptr, EAX; - } - } - } - - while (aptr < aend) - *aptr++ = cast(T)(*bptr++ - value); - - return a; -} - -unittest -{ - printf("_arraySliceExpMinSliceAssign_s unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] - 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] - 6)) - { - printf("[%d]: %d != %d - 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = value - b[] - */ - -T[] _arrayExpSliceMinSliceAssign_u(T[] a, T[] b, T value) -{ - return _arrayExpSliceMinSliceAssign_s(a, b, value); -} - -T[] _arrayExpSliceMinSliceAssign_t(T[] a, T[] b, T value) -{ - return _arrayExpSliceMinSliceAssign_s(a, b, value); -} - -T[] _arrayExpSliceMinSliceAssign_s(T[] a, T[] b, T value) -in -{ - assert(a.length == b.length); - assert(disjoint(a, b)); -} -body -{ - //printf("_arrayExpSliceMinSliceAssign_s()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 4995% faster - if (sse2() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - uint l = cast(ushort) value; - l |= (l << 16); - - if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - - align 4; - startaddsse2u: - movd XMM2, l; - pshufd XMM2, XMM2, 0; - movd XMM3, l; - pshufd XMM3, XMM3, 0; - add ESI, 32; - movdqu XMM0, [EAX]; - movdqu XMM1, [EAX+16]; - add EAX, 32; - psubw XMM2, XMM0; - psubw XMM3, XMM1; - movdqu [ESI -32], XMM2; - movdqu [ESI+16-32], XMM3; - cmp ESI, EDI; - jb startaddsse2u; - - mov aptr, ESI; - mov bptr, EAX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - - align 4; - startaddsse2a: - movd XMM2, l; - pshufd XMM2, XMM2, 0; - movd XMM3, l; - pshufd XMM3, XMM3, 0; - add ESI, 32; - movdqa XMM0, [EAX]; - movdqa XMM1, [EAX+16]; - add EAX, 32; - psubw XMM2, XMM0; - psubw XMM3, XMM1; - movdqa [ESI -32], XMM2; - movdqa [ESI+16-32], XMM3; - cmp ESI, EDI; - jb startaddsse2a; - - mov aptr, ESI; - mov bptr, EAX; - } - } - } - else - // MMX version is 4562% faster - if (mmx() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - uint l = cast(ushort) value; - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd MM4, l; - pshufw MM4, MM4, 0; - - align 4; - startmmx: - add ESI, 16; - movq MM2, [EAX]; - movq MM3, [EAX+8]; - movq MM0, MM4; - movq MM1, MM4; - add EAX, 16; - psubw MM0, MM2; - psubw MM1, MM3; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - mov bptr, EAX; - } - } - } - - while (aptr < aend) - *aptr++ = cast(T)(value - *bptr++); - - return a; -} - -unittest -{ - printf("_arrayExpSliceMinSliceAssign_s unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = 6 - a[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(6 - a[i])) - { - printf("[%d]: %d != 6 - %d\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] - c[] - */ - -T[] _arraySliceSliceMinSliceAssign_u(T[] a, T[] c, T[] b) -{ - return _arraySliceSliceMinSliceAssign_s(a, c, b); -} - -T[] _arraySliceSliceMinSliceAssign_t(T[] a, T[] c, T[] b) -{ - return _arraySliceSliceMinSliceAssign_s(a, c, b); -} - -T[] _arraySliceSliceMinSliceAssign_s(T[] a, T[] c, T[] b) -in -{ - assert(a.length == b.length && b.length == c.length); - assert(disjoint(a, b)); - assert(disjoint(a, c)); - assert(disjoint(b, c)); -} -body -{ - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - auto cptr = c.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 4129% faster - if (sse2() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - if (((cast(uint) aptr | cast(uint) bptr | cast(uint) cptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 4; - startsse2u: - add ESI, 32; - movdqu XMM0, [EAX]; - movdqu XMM1, [EAX+16]; - add EAX, 32; - movdqu XMM2, [ECX]; - movdqu XMM3, [ECX+16]; - add ECX, 32; - psubw XMM0, XMM2; - psubw XMM1, XMM3; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2u; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 4; - startsse2a: - add ESI, 32; - movdqa XMM0, [EAX]; - movdqa XMM1, [EAX+16]; - add EAX, 32; - movdqa XMM2, [ECX]; - movdqa XMM3, [ECX+16]; - add ECX, 32; - psubw XMM0, XMM2; - psubw XMM1, XMM3; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2a; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - else - // MMX version is 2018% faster - if (mmx() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 4; - startmmx: - add ESI, 16; - movq MM0, [EAX]; - movq MM1, [EAX+8]; - add EAX, 16; - movq MM2, [ECX]; - movq MM3, [ECX+8]; - add ECX, 16; - psubw MM0, MM2; - psubw MM1, MM3; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - - while (aptr < aend) - *aptr++ = cast(T)(*bptr++ - *cptr++); - - return a; -} - -unittest -{ - printf("_arraySliceSliceMinSliceAssign_s unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] - b[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] - b[i])) - { - printf("[%d]: %d != %d - %d\n", i, c[i], a[i], b[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] -= value - */ - -T[] _arrayExpSliceMinass_u(T[] a, T value) -{ - return _arrayExpSliceMinass_s(a, value); -} - -T[] _arrayExpSliceMinass_t(T[] a, T value) -{ - return _arrayExpSliceMinass_s(a, value); -} - -T[] _arrayExpSliceMinass_s(T[] a, T value) -{ - //printf("_arrayExpSliceMinass_s(a.length = %d, value = %Lg)\n", a.length, cast(real)value); - auto aptr = a.ptr; - auto aend = aptr + a.length; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 835% faster - if (sse2() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - uint l = cast(ushort) value; - l |= (l << 16); - - if (((cast(uint) aptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startaddsse2u: - movdqu XMM0, [ESI]; - movdqu XMM1, [ESI+16]; - add ESI, 32; - psubw XMM0, XMM2; - psubw XMM1, XMM2; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startaddsse2u; - - mov aptr, ESI; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startaddsse2a: - movdqa XMM0, [ESI]; - movdqa XMM1, [ESI+16]; - add ESI, 32; - psubw XMM0, XMM2; - psubw XMM1, XMM2; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startaddsse2a; - - mov aptr, ESI; - } - } - } - else - // MMX version is 835% faster - if (mmx() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - uint l = cast(ushort) value; - - asm - { - mov ESI, aptr; - mov EDI, n; - movd MM2, l; - pshufw MM2, MM2, 0; - - align 4; - startmmx: - movq MM0, [ESI]; - movq MM1, [ESI+8]; - add ESI, 16; - psubw MM0, MM2; - psubw MM1, MM2; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - } - } - } - - while (aptr < aend) - *aptr++ -= value; - - return a; -} - -unittest -{ - printf("_arrayExpSliceMinass_s unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - a[] = c[]; - a[] -= 6; - - for (int i = 0; i < dim; i++) - { - if (a[i] != cast(T)(c[i] - 6)) - { - printf("[%d]: %d != %d - 6\n", i, a[i], c[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] -= b[] - */ - -T[] _arraySliceSliceMinass_u(T[] a, T[] b) -{ - return _arraySliceSliceMinass_s(a, b); -} - -T[] _arraySliceSliceMinass_t(T[] a, T[] b) -{ - return _arraySliceSliceMinass_s(a, b); -} - -T[] _arraySliceSliceMinass_s(T[] a, T[] b) -in -{ - assert (a.length == b.length); - assert (disjoint(a, b)); -} -body -{ - //printf("_arraySliceSliceMinass_s()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 2121% faster - if (sse2() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0) - { - asm // unaligned case - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 4; - startsse2u: - movdqu XMM0, [ESI]; - movdqu XMM1, [ESI+16]; - add ESI, 32; - movdqu XMM2, [ECX]; - movdqu XMM3, [ECX+16]; - add ECX, 32; - psubw XMM0, XMM2; - psubw XMM1, XMM3; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2u; - - mov aptr, ESI; - mov bptr, ECX; - } - } - else - { - asm // aligned case - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 4; - startsse2a: - movdqa XMM0, [ESI]; - movdqa XMM1, [ESI+16]; - add ESI, 32; - movdqa XMM2, [ECX]; - movdqa XMM3, [ECX+16]; - add ECX, 32; - psubw XMM0, XMM2; - psubw XMM1, XMM3; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2a; - - mov aptr, ESI; - mov bptr, ECX; - } - } - } - else - // MMX version is 1116% faster - if (mmx() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 4; - start: - movq MM0, [ESI]; - movq MM1, [ESI+8]; - add ESI, 16; - movq MM2, [ECX]; - movq MM3, [ECX+8]; - add ECX, 16; - psubw MM0, MM2; - psubw MM1, MM3; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb start; - - emms; - mov aptr, ESI; - mov bptr, ECX; - } - } - } - - while (aptr < aend) - *aptr++ -= *bptr++; - - return a; -} - -unittest -{ - printf("_arraySliceSliceMinass_s unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - b[] = c[]; - c[] -= a[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(b[i] - a[i])) - { - printf("[%d]: %d != %d - %d\n", i, c[i], b[i], a[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] * value - */ - -T[] _arraySliceExpMulSliceAssign_u(T[] a, T value, T[] b) -{ - return _arraySliceExpMulSliceAssign_s(a, value, b); -} - -T[] _arraySliceExpMulSliceAssign_t(T[] a, T value, T[] b) -{ - return _arraySliceExpMulSliceAssign_s(a, value, b); -} - -T[] _arraySliceExpMulSliceAssign_s(T[] a, T value, T[] b) -in -{ - assert(a.length == b.length); - assert(disjoint(a, b)); -} -body -{ - //printf("_arraySliceExpMulSliceAssign_s()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 3733% faster - if (sse2() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - uint l = cast(ushort) value; - l |= l << 16; - - if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0) - { - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startsse2u: - add ESI, 32; - movdqu XMM0, [EAX]; - movdqu XMM1, [EAX+16]; - add EAX, 32; - pmullw XMM0, XMM2; - pmullw XMM1, XMM2; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2u; - - mov aptr, ESI; - mov bptr, EAX; - } - } - else - { - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startsse2a: - add ESI, 32; - movdqa XMM0, [EAX]; - movdqa XMM1, [EAX+16]; - add EAX, 32; - pmullw XMM0, XMM2; - pmullw XMM1, XMM2; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2a; - - mov aptr, ESI; - mov bptr, EAX; - } - } - } - else - // MMX version is 3733% faster - if (mmx() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - uint l = cast(ushort) value; - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - movd MM2, l; - pshufw MM2, MM2, 0; - - align 4; - startmmx: - add ESI, 16; - movq MM0, [EAX]; - movq MM1, [EAX+8]; - add EAX, 16; - pmullw MM0, MM2; - pmullw MM1, MM2; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - mov bptr, EAX; - } - } - } - - while (aptr < aend) - *aptr++ = cast(T)(*bptr++ * value); - - return a; -} - -unittest -{ - printf("_arraySliceExpMulSliceAssign_s unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] * 6; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] * 6)) - { - printf("[%d]: %d != %d * 6\n", i, c[i], a[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] = b[] * c[] - */ - -T[] _arraySliceSliceMulSliceAssign_u(T[] a, T[] c, T[] b) -{ - return _arraySliceSliceMulSliceAssign_s(a, c, b); -} - -T[] _arraySliceSliceMulSliceAssign_t(T[] a, T[] c, T[] b) -{ - return _arraySliceSliceMulSliceAssign_s(a, c, b); -} - -T[] _arraySliceSliceMulSliceAssign_s(T[] a, T[] c, T[] b) -in -{ - assert(a.length == b.length && b.length == c.length); - assert(disjoint(a, b)); - assert(disjoint(a, c)); - assert(disjoint(b, c)); -} -body -{ - //printf("_arraySliceSliceMulSliceAssign_s()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - auto cptr = c.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 2515% faster - if (sse2() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - if (((cast(uint) aptr | cast(uint) bptr | cast(uint) cptr) & 15) != 0) - { - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 4; - startsse2u: - add ESI, 32; - movdqu XMM0, [EAX]; - movdqu XMM2, [ECX]; - movdqu XMM1, [EAX+16]; - movdqu XMM3, [ECX+16]; - add EAX, 32; - add ECX, 32; - pmullw XMM0, XMM2; - pmullw XMM1, XMM3; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2u; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - else - { - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 4; - startsse2a: - add ESI, 32; - movdqa XMM0, [EAX]; - movdqa XMM2, [ECX]; - movdqa XMM1, [EAX+16]; - movdqa XMM3, [ECX+16]; - add EAX, 32; - add ECX, 32; - pmullw XMM0, XMM2; - pmullw XMM1, XMM3; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2a; - - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - else - // MMX version is 2515% faster - if (mmx() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov EAX, bptr; - mov ECX, cptr; - - align 4; - startmmx: - add ESI, 16; - movq MM0, [EAX]; - movq MM2, [ECX]; - movq MM1, [EAX+8]; - movq MM3, [ECX+8]; - add EAX, 16; - add ECX, 16; - pmullw MM0, MM2; - pmullw MM1, MM3; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - mov bptr, EAX; - mov cptr, ECX; - } - } - } - - while (aptr < aend) - *aptr++ = cast(T)(*bptr++ * *cptr++); - - return a; -} - -unittest -{ - printf("_arraySliceSliceMulSliceAssign_s unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - c[] = a[] * b[]; - - for (int i = 0; i < dim; i++) - { - if (c[i] != cast(T)(a[i] * b[i])) - { - printf("[%d]: %d != %d * %d\n", i, c[i], a[i], b[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] *= value - */ - -T[] _arrayExpSliceMulass_u(T[] a, T value) -{ - return _arrayExpSliceMulass_s(a, value); -} - -T[] _arrayExpSliceMulass_t(T[] a, T value) -{ - return _arrayExpSliceMulass_s(a, value); -} - -T[] _arrayExpSliceMulass_s(T[] a, T value) -{ - //printf("_arrayExpSliceMulass_s(a.length = %d, value = %Lg)\n", a.length, cast(real)value); - auto aptr = a.ptr; - auto aend = aptr + a.length; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 2044% faster - if (sse2() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - uint l = cast(ushort) value; - l |= l << 16; - - if (((cast(uint) aptr) & 15) != 0) - { - asm - { - mov ESI, aptr; - mov EDI, n; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startsse2u: - movdqu XMM0, [ESI]; - movdqu XMM1, [ESI+16]; - add ESI, 32; - pmullw XMM0, XMM2; - pmullw XMM1, XMM2; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2u; - - mov aptr, ESI; - } - } - else - { - asm - { - mov ESI, aptr; - mov EDI, n; - movd XMM2, l; - pshufd XMM2, XMM2, 0; - - align 4; - startsse2a: - movdqa XMM0, [ESI]; - movdqa XMM1, [ESI+16]; - add ESI, 32; - pmullw XMM0, XMM2; - pmullw XMM1, XMM2; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2a; - - mov aptr, ESI; - } - } - } - else - // MMX version is 2056% faster - if (mmx() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - uint l = cast(ushort) value; - - asm - { - mov ESI, aptr; - mov EDI, n; - movd MM2, l; - pshufw MM2, MM2, 0; - - align 4; - startmmx: - movq MM0, [ESI]; - movq MM1, [ESI+8]; - add ESI, 16; - pmullw MM0, MM2; - pmullw MM1, MM2; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - } - } - } - - while (aptr < aend) - *aptr++ *= value; - - return a; -} - -unittest -{ - printf("_arrayExpSliceMulass_s unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - b[] = a[]; - a[] *= 6; - - for (int i = 0; i < dim; i++) - { - if (a[i] != cast(T)(b[i] * 6)) - { - printf("[%d]: %d != %d * 6\n", i, a[i], b[i]); - assert(0); - } - } - } - } -} - - -/* ======================================================================== */ - -/*********************** - * Computes: - * a[] *= b[] - */ - -T[] _arraySliceSliceMulass_u(T[] a, T[] b) -{ - return _arraySliceSliceMulass_s(a, b); -} - -T[] _arraySliceSliceMulass_t(T[] a, T[] b) -{ - return _arraySliceSliceMulass_s(a, b); -} - -T[] _arraySliceSliceMulass_s(T[] a, T[] b) -in -{ - assert (a.length == b.length); - assert (disjoint(a, b)); -} -body -{ - //printf("_arraySliceSliceMulass_s()\n"); - auto aptr = a.ptr; - auto aend = aptr + a.length; - auto bptr = b.ptr; - - version (D_InlineAsm_X86) - { - // SSE2 aligned version is 2519% faster - if (sse2() && a.length >= 16) - { - auto n = aptr + (a.length & ~15); - - if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0) - { - asm - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 4; - startsse2u: - movdqu XMM0, [ESI]; - movdqu XMM2, [ECX]; - movdqu XMM1, [ESI+16]; - movdqu XMM3, [ECX+16]; - add ESI, 32; - add ECX, 32; - pmullw XMM0, XMM2; - pmullw XMM1, XMM3; - movdqu [ESI -32], XMM0; - movdqu [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2u; - - mov aptr, ESI; - mov bptr, ECX; - } - } - else - { - asm - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 4; - startsse2a: - movdqa XMM0, [ESI]; - movdqa XMM2, [ECX]; - movdqa XMM1, [ESI+16]; - movdqa XMM3, [ECX+16]; - add ESI, 32; - add ECX, 32; - pmullw XMM0, XMM2; - pmullw XMM1, XMM3; - movdqa [ESI -32], XMM0; - movdqa [ESI+16-32], XMM1; - cmp ESI, EDI; - jb startsse2a; - - mov aptr, ESI; - mov bptr, ECX; - } - } - } - else - // MMX version is 1712% faster - if (mmx() && a.length >= 8) - { - auto n = aptr + (a.length & ~7); - - asm - { - mov ESI, aptr; - mov EDI, n; - mov ECX, bptr; - - align 4; - startmmx: - movq MM0, [ESI]; - movq MM2, [ECX]; - movq MM1, [ESI+8]; - movq MM3, [ECX+8]; - add ESI, 16; - add ECX, 16; - pmullw MM0, MM2; - pmullw MM1, MM3; - movq [ESI -16], MM0; - movq [ESI+8-16], MM1; - cmp ESI, EDI; - jb startmmx; - - emms; - mov aptr, ESI; - mov bptr, ECX; - } - } - } - - while (aptr < aend) - *aptr++ *= *bptr++; - - return a; -} - -unittest -{ - printf("_arraySliceSliceMulass_s unittest\n"); - - for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) - { - version (log) printf(" cpuid %d\n", cpuid); - - for (int j = 0; j < 2; j++) - { - const int dim = 67; - T[] a = new T[dim + j]; // aligned on 16 byte boundary - a = a[j .. dim + j]; // misalign for second iteration - T[] b = new T[dim + j]; - b = b[j .. dim + j]; - T[] c = new T[dim + j]; - c = c[j .. dim + j]; - - for (int i = 0; i < dim; i++) - { a[i] = cast(T)i; - b[i] = cast(T)(i + 7); - c[i] = cast(T)(i * 2); - } - - b[] = a[]; - a[] *= c[]; - - for (int i = 0; i < dim; i++) - { - if (a[i] != cast(T)(b[i] * c[i])) - { - printf("[%d]: %d != %d * %d\n", i, a[i], b[i], c[i]); - assert(0); - } - } - } - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/cast_.d --- a/druntime/src/compiler/ldc/cast_.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,169 +0,0 @@ -/** - * Implementation of array assignment support routines. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: Boost License 1.0. - * Authors: Walter Bright, Sean Kelly - * - * Copyright Digital Mars 2000 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module rt.cover; - -private -{ - version( Windows ) - import core.sys.windows.windows; - else version( Posix ) - { - import core.sys.posix.fcntl; - import core.sys.posix.unistd; - } - import core.bitop; - import core.stdc.stdio; - import rt.util.utf; - - struct BitArray - { - size_t len; - uint* ptr; - - bool opIndex( size_t i ) - in - { - assert( i < len ); - } - body - { - return cast(bool) bt( ptr, i ); - } - } - - struct Cover - { - string filename; - BitArray valid; - uint[] data; - } - - __gshared - { - Cover[] gdata; - string srcpath; - string dstpath; - bool merge; - } -} - - -/** - * Set path to where source files are located. - * - * Params: - * pathname = The new path name. - */ -extern (C) void dmd_coverSourcePath( string pathname ) -{ - srcpath = pathname; -} - - -/** - * Set path to where listing files are to be written. - * - * Params: - * pathname = The new path name. - */ -extern (C) void dmd_coverDestPath( string pathname ) -{ - dstpath = pathname; -} - - -/** - * Set merge mode. - * - * Params: - * flag = true means new data is summed with existing data in the listing - * file; false means a new listing file is always created. - */ -extern (C) void dmd_coverSetMerge( bool flag ) -{ - merge = flag; -} - - -/** - * The coverage callback. - * - * Params: - * filename = The name of the coverage file. - * valid = ??? - * data = ??? - */ -extern (C) void _d_cover_register( string filename, BitArray valid, uint[] data ) -{ - Cover c; - - c.filename = filename; - c.valid = valid; - c.data = data; - gdata ~= c; -} - - -static ~this() -{ - const NUMLINES = 16384 - 1; - const NUMCHARS = 16384 * 16 - 1; - - char[] srcbuf = new char[NUMCHARS]; - char[][] srclines = new char[][NUMLINES]; - char[] lstbuf = new char[NUMCHARS]; - char[][] lstlines = new char[][NUMLINES]; - - foreach( Cover c; gdata ) - { - if( !readFile( appendFN( srcpath, c.filename ), srcbuf ) ) - continue; - splitLines( srcbuf, srclines ); - - if( merge ) - { - if( !readFile( addExt( baseName( c.filename ), "lst" ), lstbuf ) ) - break; - splitLines( lstbuf, lstlines ); - - for( size_t i = 0; i < lstlines.length; ++i ) - { - if( i >= c.data.length ) - break; - - int count = 0; - - foreach( char c2; lstlines[i] ) - { - switch( c2 ) - { - case ' ': - continue; - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - count = count * 10 + c2 - '0'; - continue; - default: - break; - } - } - c.data[i] += count; - } - } - - FILE* flst = fopen( (addExt( baseName( c.filename ), "lst\0" )).ptr, "wb" ); - - if( !flst ) - continue; //throw new Exception( "Error opening file for write: " ~ lstfn ); - - uint nno; - uint nyes; - - for( int i = 0; i < c.data.length; i++ ) - { - if( i < srclines.length ) - { - uint n = c.data[i]; - char[] line = srclines[i]; - - line = expandTabs( line ); - - if( n == 0 ) - { - if( c.valid[i] ) - { - nno++; - fprintf( flst, "0000000|%.*s\n", line ); - } - else - { - fprintf( flst, " |%.*s\n", line ); - } - } - else - { - nyes++; - fprintf( flst, "%7u|%.*s\n", n, line ); - } - } - } - if( nyes + nno ) // no divide by 0 bugs - { - fprintf( flst, "%.*s is %d%% covered\n", c.filename, ( nyes * 100 ) / ( nyes + nno ) ); - } - fclose( flst ); - } -} - - -string appendFN( string path, string name ) -{ - version( Windows ) - const char sep = '\\'; - else - const char sep = '/'; - - auto dest = path; - - if( dest && dest[$ - 1] != sep ) - dest ~= sep; - dest ~= name; - return dest; -} - - -string baseName( string name, string ext = null ) -{ - auto i = name.length; - for( ; i > 0; --i ) - { - version( Windows ) - { - if( name[i - 1] == ':' || name[i - 1] == '\\' ) - break; - } - else version( Posix ) - { - if( name[i - 1] == '/' ) - break; - } - } - return chomp( name[i .. $], ext ? ext : "" ); -} - - -string getExt( string name ) -{ - auto i = name.length; - - while( i > 0 ) - { - if( name[i - 1] == '.' ) - return name[i .. $]; - --i; - version( Windows ) - { - if( name[i] == ':' || name[i] == '\\' ) - break; - } - else version( Posix ) - { - if( name[i] == '/' ) - break; - } - } - return null; -} - - -string addExt( string name, string ext ) -{ - auto existing = getExt( name ); - - if( existing.length == 0 ) - { - if( name.length && name[$ - 1] == '.' ) - name ~= ext; - else - name = name ~ "." ~ ext; - } - else - { - name = name[0 .. $ - existing.length] ~ ext; - } - return name; -} - - -string chomp( string str, string delim = null ) -{ - if( delim is null ) - { - auto len = str.length; - - if( len ) - { - auto c = str[len - 1]; - - if( c == '\r' ) - --len; - else if( c == '\n' && str[--len - 1] == '\r' ) - --len; - } - return str[0 .. len]; - } - else if( str.length >= delim.length ) - { - if( str[$ - delim.length .. $] == delim ) - return str[0 .. $ - delim.length]; - } - return str; -} - - -bool readFile( string name, inout char[] buf ) -{ - version( Windows ) - { - auto wnamez = toUTF16z( name ); - HANDLE file = CreateFileW( wnamez, - GENERIC_READ, - FILE_SHARE_READ, - null, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, - cast(HANDLE) null ); - - delete wnamez; - if( file == INVALID_HANDLE_VALUE ) - return false; - scope( exit ) CloseHandle( file ); - - DWORD num = 0; - DWORD pos = 0; - - buf.length = 4096; - while( true ) - { - if( !ReadFile( file, &buf[pos], cast(DWORD)( buf.length - pos ), &num, null ) ) - return false; - if( !num ) - break; - pos += num; - buf.length = pos * 2; - } - buf.length = pos; - return true; - } - else version( Posix ) - { - char[] namez = new char[name.length + 1]; - namez[0 .. name.length] = name; - namez[$ - 1] = 0; - int file = open( namez.ptr, O_RDONLY ); - - delete namez; - if( file == -1 ) - return false; - scope( exit ) close( file ); - - int num = 0; - uint pos = 0; - - buf.length = 4096; - while( true ) - { - num = read( file, &buf[pos], cast(uint)( buf.length - pos ) ); - if( num == -1 ) - return false; - if( !num ) - break; - pos += num; - buf.length = pos * 2; - } - buf.length = pos; - return true; - } -} - - -void splitLines( char[] buf, inout char[][] lines ) -{ - size_t beg = 0, - pos = 0; - - lines.length = 0; - for( ; pos < buf.length; ++pos ) - { - char c = buf[pos]; - - switch( buf[pos] ) - { - case '\r': - case '\n': - lines ~= buf[beg .. pos]; - beg = pos + 1; - if( buf[pos] == '\r' && pos < buf.length - 1 && buf[pos + 1] == '\n' ) - ++pos, ++beg; - default: - continue; - } - } - if( beg != pos ) - { - lines ~= buf[beg .. pos]; - } -} - - -char[] expandTabs( char[] str, int tabsize = 8 ) -{ - const dchar LS = '\u2028'; // UTF line separator - const dchar PS = '\u2029'; // UTF paragraph separator - - bool changes = false; - char[] result = str; - int column; - int nspaces; - - foreach( size_t i, dchar c; str ) - { - switch( c ) - { - case '\t': - nspaces = tabsize - (column % tabsize); - if( !changes ) - { - changes = true; - result = null; - result.length = str.length + nspaces - 1; - result.length = i + nspaces; - result[0 .. i] = str[0 .. i]; - result[i .. i + nspaces] = ' '; - } - else - { int j = result.length; - result.length = j + nspaces; - result[j .. j + nspaces] = ' '; - } - column += nspaces; - break; - - case '\r': - case '\n': - case PS: - case LS: - column = 0; - goto L1; - - default: - column++; - L1: - if (changes) - { - if (c <= 0x7F) - result ~= c; - else - encode(result, c); - } - break; - } - } - return result; -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/critical.c --- a/druntime/src/compiler/ldc/critical.c Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,173 +0,0 @@ -/** - * Implementation of support routines for synchronized blocks. - * - * Copyright: Copyright Digital Mars 2000 - 2009. - * License: next) - { - pthread_mutex_lock(&critical_section.cs); - if (!dcs->next) // if, in the meantime, another thread didn't set it - { - dcs->next = dcs_list; - dcs_list = dcs; - pthread_mutex_init(&dcs->cs, &_criticals_attr); - } - pthread_mutex_unlock(&critical_section.cs); - } - pthread_mutex_lock(&dcs->cs); -} - -void _d_criticalexit(D_CRITICAL_SECTION *dcs) -{ - //printf("_d_criticalexit(dcs = x%x)\n", dcs); - pthread_mutex_unlock(&dcs->cs); -} - -void _STI_critical_init() -{ - if (!dcs_list) - { //printf("_STI_critical_init()\n"); - pthread_mutexattr_init(&_criticals_attr); - pthread_mutexattr_settype(&_criticals_attr, PTHREAD_MUTEX_RECURSIVE); - - // The global critical section doesn't need to be recursive - pthread_mutex_init(&critical_section.cs, 0); - dcs_list = &critical_section; - } -} - -void _STD_critical_term() -{ - if (dcs_list) - { //printf("_STI_critical_term()\n"); - while (dcs_list) - { - //printf("\tlooping... %x\n", dcs_list); - pthread_mutex_destroy(&dcs_list->cs); - dcs_list = dcs_list->next; - } - } -} - -#endif - diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/deh.c --- a/druntime/src/compiler/ldc/deh.c Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,724 +0,0 @@ -/** - * Implementation of exception handling support routines for Windows. - * - * Copyright: Copyright Digital Mars 1999 - 2009. - * License: ExceptionFlags & EXCEPTION_UNWIND) - { - // Call all the finally blocks in this frame - _d_local_unwind(handler_table, frame, -1); - } - else - { - // Jump to catch block if matching one is found - - int ndx,prev_ndx,i; - struct DHandlerInfo *phi; - struct DCatchInfo *pci; - struct DCatchBlock *pcb; - unsigned ncatches; // number of catches in the current handler - Object *pti; - ClassInfo *ci; - - ci = NULL; // only compute it if we need it - - // walk through handler table, checking each handler - // with an index smaller than the current table_index - for (ndx = frame->table_index; ndx != -1; ndx = prev_ndx) - { - phi = &handler_table->handler_info[ndx]; - prev_ndx = phi->prev_index; - if (phi->cioffset) - { - // this is a catch handler (no finally) - pci = (struct DCatchInfo *)((char *)handler_table + phi->cioffset); - ncatches = pci->ncatches; - for (i = 0; i < ncatches; i++) - { - pcb = &pci->catch_block[i]; - - if (!ci) - { - // This code must match the translation code - if (exception_record->ExceptionCode == STATUS_DIGITAL_MARS_D_EXCEPTION) - { - //printf("ei[0] = %p\n", exception_record->ExceptionInformation[0]); - ci = **(ClassInfo ***)(exception_record->ExceptionInformation[0]); - } - else - ci = &_Class_9Throwable; - } - - if (_d_isbaseof(ci, pcb->type)) - { - // Matched the catch type, so we've found the handler. - int regebp; - - pti = _d_translate_se_to_d_exception(exception_record); - - // Initialize catch variable - regebp = (int)&frame->ebp; // EBP for this frame - *(void **)(regebp + (pcb->bpoffset)) = pti; - - // Have system call all finally blocks in intervening frames - _global_unwind(frame, exception_record); - - // Call all the finally blocks skipped in this frame - _d_local_unwind(handler_table, frame, ndx); - - frame->table_index = prev_ndx; // we are out of this handler - - // Jump to catch block. Does not return. - { - unsigned catch_esp; - fp_t catch_addr; - - catch_addr = (fp_t)(pcb->code); - catch_esp = regebp - handler_table->espoffset - sizeof(fp_t); - _asm - { - mov EAX,catch_esp - mov ECX,catch_addr - mov [EAX],ECX - mov EBP,regebp - mov ESP,EAX // reset stack - ret // jump to catch block - } - } - } - } - } - } - } - return ExceptionContinueSearch; -} - -/*********************************** - * Exception filter for use in __try..__except block - * surrounding call to Dmain() - */ - -int _d_exception_filter(struct _EXCEPTION_POINTERS *eptrs, - int retval, - Object **exception_object) -{ - *exception_object = _d_translate_se_to_d_exception(eptrs->ExceptionRecord); - return retval; -} - -/*********************************** - * Throw a D object. - */ - -void __stdcall _d_throw(Object *h) -{ - //printf("_d_throw(h = %p, &h = %p)\n", h, &h); - //printf("\tvptr = %p\n", *(void **)h); - RaiseException(STATUS_DIGITAL_MARS_D_EXCEPTION, - EXCEPTION_NONCONTINUABLE, - 1, (DWORD *)&h); -} - -/*********************************** - * Create an exception object - */ - -Object *_d_create_exception_object(ClassInfo *ci, char *msg) -{ - Throwable *exc; - - exc = (Throwable *)_d_newclass(ci); - // BUG: what if _d_newclass() throws an out of memory exception? - - if (msg) - { - exc->msglen = strlen(msg); - exc->msg = msg; - } - return (Object *)exc; -} - -/*********************************** - * Converts a Windows Structured Exception code to a D Exception Object. - */ - -Object *_d_translate_se_to_d_exception(EXCEPTION_RECORD *exception_record) -{ - Object *pti; - - switch (exception_record->ExceptionCode) { - case STATUS_DIGITAL_MARS_D_EXCEPTION: - // Generated D exception - pti = (Object *)(exception_record->ExceptionInformation[0]); - break; - - case STATUS_INTEGER_DIVIDE_BY_ZERO: - pti = _d_create_exception_object(&_Class_5Error, "Integer Divide by Zero"); - break; - - case STATUS_FLOAT_DIVIDE_BY_ZERO: - pti = _d_create_exception_object(&_Class_5Error, "Float Divide by Zero"); - break; - - case STATUS_ACCESS_VIOLATION: - pti = _d_create_exception_object(&_Class_5Error, "Access Violation"); - break; - - case STATUS_STACK_OVERFLOW: - pti = _d_create_exception_object(&_Class_5Error, "Stack Overflow"); - break; - - case STATUS_DATATYPE_MISALIGNMENT: - pti = _d_create_exception_object(&_Class_5Error, "Datatype Misalignment"); - break; - - case STATUS_ARRAY_BOUNDS_EXCEEDED: - pti = _d_create_exception_object(&_Class_5Error, "Array Bounds Exceeded"); - break; - - case STATUS_FLOAT_INVALID_OPERATION: - pti = _d_create_exception_object(&_Class_5Error, "Invalid Floating Point Operation"); - break; - - case STATUS_FLOAT_DENORMAL_OPERAND: - pti = _d_create_exception_object(&_Class_5Error, "Floating Point Denormal Operand"); - break; - - case STATUS_FLOAT_INEXACT_RESULT: - pti = _d_create_exception_object(&_Class_5Error, "Floating Point Inexact Result"); - break; - - case STATUS_FLOAT_OVERFLOW: - pti = _d_create_exception_object(&_Class_5Error, "Floating Point Overflow"); - break; - - case STATUS_FLOAT_UNDERFLOW: - pti = _d_create_exception_object(&_Class_5Error, "Floating Point Underflow"); - break; - - case STATUS_FLOAT_STACK_CHECK: - pti = _d_create_exception_object(&_Class_5Error, "Floating Point Stack Check"); - break; - - case STATUS_PRIVILEGED_INSTRUCTION: - pti = _d_create_exception_object(&_Class_5Error, "Privileged Instruction"); - break; - - case STATUS_ILLEGAL_INSTRUCTION: - pti = _d_create_exception_object(&_Class_5Error, "Illegal Instruction"); - break; - - case STATUS_BREAKPOINT: - pti = _d_create_exception_object(&_Class_5Error, "Breakpoint"); - break; - - case STATUS_IN_PAGE_ERROR: - pti = _d_create_exception_object(&_Class_5Error, "Win32 In Page Exception"); - break; -/* - case STATUS_INTEGER_OVERFLOW: // not supported on any x86 processor - case STATUS_INVALID_DISPOSITION: - case STATUS_NONCONTINUABLE_EXCEPTION: - case STATUS_SINGLE_STEP: - case DBG_CONTROL_C: // only when a debugger is attached - // In DMC, but not in Microsoft docs - case STATUS_GUARD_PAGE_VIOLATION: - case STATUS_INVALID_HANDLE: -*/ - // convert all other exception codes into a Win32Exception - default: - pti = _d_create_exception_object(&_Class_5Error, "Win32 Exception"); - break; - } - - return pti; -} - -/************************************** - * Call finally blocks in the current stack frame until stop_index. - * This is roughly equivalent to _local_unwind() for C in \src\win32\ehsup.c - */ - -void __cdecl _d_local_unwind(struct DHandlerTable *handler_table, - struct DEstablisherFrame *frame, int stop_index) -{ - struct DHandlerInfo *phi; - struct DCatchInfo *pci; - int i; - - // Set up a special exception handler to catch double-fault exceptions. - __asm - { - push dword ptr -1 - push dword ptr 0 - push offset _local_except_handler // defined in src\win32\ehsup.c - push dword ptr fs:_except_list - mov FS:_except_list,ESP - } - - for (i = frame->table_index; i != -1 && i != stop_index; i = phi->prev_index) - { - phi = &handler_table->handler_info[i]; - if (phi->finally_code) - { - // Note that it is unnecessary to adjust the ESP, as the finally block - // accesses all items on the stack as relative to EBP. - - DWORD *catch_ebp = &frame->ebp; - void *blockaddr = phi->finally_code; - - _asm - { - push EBX - mov EBX,blockaddr - push EBP - mov EBP,catch_ebp - call EBX - pop EBP - pop EBX - } - } - } - - _asm - { - pop FS:_except_list - add ESP,12 - } -} - -/*********************************** - * external version of the unwinder - */ - -__declspec(naked) void __cdecl _d_local_unwind2() -{ - __asm - { - jmp _d_local_unwind - } -} - -/*********************************** - * The frame handler, this is called for each frame that has been registered - * in the OS except_list. - * Input: - * EAX the handler table for the frame - */ - -EXCEPTION_DISPOSITION _d_monitor_handler( - EXCEPTION_RECORD *exception_record, - struct DEstablisherFrame *frame, - CONTEXT context, - void *dispatcher_context) -{ - if (exception_record->ExceptionFlags & EXCEPTION_UNWIND) - { - _d_monitorexit((Object *)frame->table_index); - } - else - { - } - return ExceptionContinueSearch; -} - -/*********************************** - */ - -void _d_monitor_prolog(void *x, void *y, Object *h) -{ - __asm - { - push EAX - } - //printf("_d_monitor_prolog(x=%p, y=%p, h=%p)\n", x, y, h); - _d_monitorenter(h); - __asm - { - pop EAX - } -} - -/*********************************** - */ - -void _d_monitor_epilog(void *x, void *y, Object *h) -{ - //printf("_d_monitor_epilog(x=%p, y=%p, h=%p)\n", x, y, h); - __asm - { - push EAX - push EDX - } - _d_monitorexit(h); - __asm - { - pop EDX - pop EAX - } -} - -#endif - -/* ======================== linux =============================== */ - -#if linux - -#include "mars.h" - -extern ClassInfo D6object9Throwable7__ClassZ; -#define _Class_9Throwable D6object9Throwable7__ClassZ; - -extern ClassInfo D6object5Error7__ClassZ; -#define _Class_5Error D6object5Error7__ClassZ - -typedef int (*fp_t)(); // function pointer in ambient memory model - -struct DHandlerInfo -{ - unsigned offset; // offset from function address to start of guarded section - int prev_index; // previous table index - unsigned cioffset; // offset to DCatchInfo data from start of table (!=0 if try-catch) - void *finally_code; // pointer to finally code to execute - // (!=0 if try-finally) -}; - -// Address of DHandlerTable, searched for by eh_finddata() - -struct DHandlerTable -{ - void *fptr; // pointer to start of function - unsigned espoffset; // offset of ESP from EBP - unsigned retoffset; // offset from start of function to return code - unsigned nhandlers; // dimension of handler_info[] - struct DHandlerInfo handler_info[1]; -}; - -struct DCatchBlock -{ - ClassInfo *type; // catch type - unsigned bpoffset; // EBP offset of catch var - void *code; // catch handler code -}; - -// Create one of these for each try-catch -struct DCatchInfo -{ - unsigned ncatches; // number of catch blocks - struct DCatchBlock catch_block[1]; // data for each catch block -}; - -// One of these is generated for each function with try-catch or try-finally - -struct FuncTable -{ - void *fptr; // pointer to start of function - struct DHandlerTable *handlertable; // eh data for this function - unsigned size; // size of function in bytes -}; - -extern struct FuncTable *table_start; -extern struct FuncTable *table_end; - -void terminate() -{ -// _asm -// { -// hlt -// } -} - -/******************************************* - * Given address that is inside a function, - * figure out which function it is in. - * Return DHandlerTable if there is one, NULL if not. - */ - -struct DHandlerTable *__eh_finddata(void *address) -{ - struct FuncTable *ft; - - for (ft = (struct FuncTable *)table_start; - ft < (struct FuncTable *)table_end; - ft++) - { - if (ft->fptr <= address && - address < (void *)((char *)ft->fptr + ft->size)) - { - return ft->handlertable; - } - } - return NULL; -} - - -/****************************** - * Given EBP, find return address to caller, and caller's EBP. - * Input: - * regbp Value of EBP for current function - * *pretaddr Return address - * Output: - * *pretaddr return address to caller - * Returns: - * caller's EBP - */ - -unsigned __eh_find_caller(unsigned regbp, unsigned *pretaddr) -{ - unsigned bp = *(unsigned *)regbp; - - if (bp) // if not end of call chain - { - // Perform sanity checks on new EBP. - // If it is screwed up, terminate() hopefully before we do more damage. - if (bp <= regbp) - // stack should grow to smaller values - terminate(); - - *pretaddr = *(unsigned *)(regbp + sizeof(int)); - } - return bp; -} - -/*********************************** - * Throw a D object. - */ - -void __stdcall _d_throw(Object *h) -{ - unsigned regebp; - - //printf("_d_throw(h = %p, &h = %p)\n", h, &h); - //printf("\tvptr = %p\n", *(void **)h); - - regebp = _EBP; - - while (1) // for each function on the stack - { - struct DHandlerTable *handler_table; - struct FuncTable *pfunc; - struct DHandlerInfo *phi; - unsigned retaddr; - unsigned funcoffset; - unsigned spoff; - unsigned retoffset; - int index; - int dim; - int ndx; - int prev_ndx; - - regebp = __eh_find_caller(regebp,&retaddr); - if (!regebp) - // if end of call chain - break; - - handler_table = __eh_finddata((void *)retaddr); // find static data associated with function - if (!handler_table) // if no static data - { - continue; - } - funcoffset = (unsigned)handler_table->fptr; - spoff = handler_table->espoffset; - retoffset = handler_table->retoffset; - -#ifdef DEBUG - printf("retaddr = x%x\n",(unsigned)retaddr); - printf("regebp=x%04x, funcoffset=x%04x, spoff=x%x, retoffset=x%x\n", - regebp,funcoffset,spoff,retoffset); -#endif - - // Find start index for retaddr in static data - dim = handler_table->nhandlers; - index = -1; - for (int i = 0; i < dim; i++) - { - phi = &handler_table->handler_info[i]; - - if ((unsigned)retaddr >= funcoffset + phi->offset) - index = i; - } - - // walk through handler table, checking each handler - // with an index smaller than the current table_index - for (ndx = index; ndx != -1; ndx = prev_ndx) - { - phi = &handler_table->handler_info[ndx]; - prev_ndx = phi->prev_index; - if (phi->cioffset) - { - // this is a catch handler (no finally) - struct DCatchInfo *pci; - int ncatches; - int i; - - pci = (struct DCatchInfo *)((char *)handler_table + phi->cioffset); - ncatches = pci->ncatches; - for (i = 0; i < ncatches; i++) - { - struct DCatchBlock *pcb; - ClassInfo *ci = **(ClassInfo ***)h; - - pcb = &pci->catch_block[i]; - - if (_d_isbaseof(ci, pcb->type)) - { // Matched the catch type, so we've found the handler. - - // Initialize catch variable - *(void **)(regebp + (pcb->bpoffset)) = h; - - // Jump to catch block. Does not return. - { - unsigned catch_esp; - fp_t catch_addr; - - catch_addr = (fp_t)(pcb->code); - catch_esp = regebp - handler_table->espoffset - sizeof(fp_t); - _asm - { - mov EAX,catch_esp - mov ECX,catch_addr - mov [EAX],ECX - mov EBP,regebp - mov ESP,EAX // reset stack - ret // jump to catch block - } - } - } - } - } - else if (phi->finally_code) - { // Call finally block - // Note that it is unnecessary to adjust the ESP, as the finally block - // accesses all items on the stack as relative to EBP. - - void *blockaddr = phi->finally_code; - - _asm - { - push EBX - mov EBX,blockaddr - push EBP - mov EBP,regebp - call EBX - pop EBP - pop EBX - } - } - } - } -} - - -#endif diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/deh2.d --- a/druntime/src/compiler/ldc/deh2.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,316 +0,0 @@ -/** - * Implementation of exception handling support routines for Posix. - * - * Copyright: Copyright Digital Mars 2000 - 2009. - * License: funcoffset + phi.offset && - cast(uint)retaddr <= funcoffset + phi.endoffset) - index = i; - } - debug printf("index = %d\n", index); - - // walk through handler table, checking each handler - // with an index smaller than the current table_index - for (ndx = index; ndx != -1; ndx = prev_ndx) - { - phi = &handler_table.handler_info[ndx]; - prev_ndx = phi.prev_index; - if (phi.cioffset) - { - // this is a catch handler (no finally) - DCatchInfo *pci; - int ncatches; - int i; - - pci = cast(DCatchInfo *)(cast(char *)handler_table + phi.cioffset); - ncatches = pci.ncatches; - for (i = 0; i < ncatches; i++) - { - DCatchBlock *pcb; - ClassInfo ci = **cast(ClassInfo **)h; - - pcb = &pci.catch_block[i]; - - if (_d_isbaseof(ci, pcb.type)) - { // Matched the catch type, so we've found the handler. - - // Initialize catch variable - *cast(void **)(regebp + (pcb.bpoffset)) = h; - - // Jump to catch block. Does not return. - { - uint catch_esp; - fp_t catch_addr; - - catch_addr = cast(fp_t)(pcb.code); - catch_esp = regebp - handler_table.espoffset - fp_t.sizeof; - asm - { - mov EAX,catch_esp ; - mov ECX,catch_addr ; - mov [EAX],ECX ; - mov EBP,regebp ; - mov ESP,EAX ; // reset stack - ret ; // jump to catch block - } - } - } - } - } - else if (phi.finally_code) - { // Call finally block - // Note that it is unnecessary to adjust the ESP, as the finally block - // accesses all items on the stack as relative to EBP. - - void *blockaddr = phi.finally_code; - - version (OSX) - { - asm - { - sub ESP,4 ; // align stack to 16 - push EBX ; - mov EBX,blockaddr ; - push EBP ; - mov EBP,regebp ; - call EBX ; - pop EBP ; - pop EBX ; - add ESP,4 ; - } - } - else - { - asm - { - push EBX ; - mov EBX,blockaddr ; - push EBP ; - mov EBP,regebp ; - call EBX ; - pop EBP ; - pop EBX ; - } - } - } - } - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/dmain2.BAK --- a/druntime/src/compiler/ldc/dmain2.BAK Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,374 +0,0 @@ -/* - * Placed into the Public Domain. - * written by Walter Bright - * www.digitalmars.com - */ - -/* - * Modified by Sean Kelly for use with the D Runtime Project - */ - -module rt.dmain2; - -private -{ - import memory; - import util.console; - import core.stdc.stddef; - import core.stdc.stdlib; - import core.stdc.string; -} - -version (Windows) -{ - extern (Windows) alias int function() FARPROC; - extern (Windows) FARPROC GetProcAddress(void*, in char*); - extern (Windows) void* LoadLibraryA(in char*); - extern (Windows) int FreeLibrary(void*); - extern (Windows) void* LocalFree(void*); - extern (Windows) wchar_t* GetCommandLineW(); - extern (Windows) wchar_t** CommandLineToArgvW(wchar_t*, int*); - extern (Windows) export int WideCharToMultiByte(uint, uint, wchar_t*, int, char*, int, char*, int); - pragma(lib, "shell32.lib"); // needed for CommandLineToArgvW -} - -extern (C) void _STI_monitor_staticctor(); -extern (C) void _STD_monitor_staticdtor(); -extern (C) void _STI_critical_init(); -extern (C) void _STD_critical_term(); -extern (C) void gc_init(); -extern (C) void gc_term(); -extern (C) void _minit(); -extern (C) void _moduleCtor(); -extern (C) void _moduleDtor(); -extern (C) void thread_joinAll(); - -/*********************************** - * These are a temporary means of providing a GC hook for DLL use. They may be - * replaced with some other similar functionality later. - */ -extern (C) -{ - void* gc_getProxy(); - void gc_setProxy(void* p); - void gc_clrProxy(); - - alias void* function() gcGetFn; - alias void function(void*) gcSetFn; - alias void function() gcClrFn; -} - -extern (C) void* rt_loadLibrary(in char[] name) -{ - version (Windows) - { - char[260] temp = void; - temp[0 .. name.length] = name[]; - temp[name.length] = cast(char) 0; - void* ptr = LoadLibraryA(temp.ptr); - if (ptr is null) - return ptr; - gcSetFn gcSet = cast(gcSetFn) GetProcAddress(ptr, "gc_setProxy"); - if (gcSet !is null) - gcSet(gc_getProxy()); - return ptr; - - } - else version (linux) - { - throw new Exception("rt_loadLibrary not yet implemented on linux."); - } -} - -extern (C) bool rt_unloadLibrary(void* ptr) -{ - version (Windows) - { - gcClrFn gcClr = cast(gcClrFn) GetProcAddress(ptr, "gc_clrProxy"); - if (gcClr !is null) - gcClr(); - return FreeLibrary(ptr) != 0; - } - else version (linux) - { - throw new Exception("rt_unloadLibrary not yet implemented on linux."); - } -} - -/*********************************** - * These functions must be defined for any D program linked - * against this library. - */ -extern (C) void onAssertError(string file, size_t line); -extern (C) void onAssertErrorMsg(string file, size_t line, string msg); -extern (C) void onRangeError(string file, size_t line); -extern (C) void onHiddenFuncError(Object o); -extern (C) void onSwitchError(string file, size_t line); -extern (C) bool runModuleUnitTests(); - -// this function is called from the utf module -//extern (C) void onUnicodeError(string msg, size_t idx); - -/*********************************** - * These are internal callbacks for various language errors. - */ -extern (C) void _d_assert(string file, uint line) -{ - onAssertError(file, line); -} - -extern (C) static void _d_assert_msg(string msg, string file, uint line) -{ - onAssertErrorMsg(file, line, msg); -} - -extern (C) void _d_array_bounds(string file, uint line) -{ - onRangeError(file, line); -} - -extern (C) void _d_switch_error(string file, uint line) -{ - onSwitchError(file, line); -} - -extern (C) void _d_hidden_func() -{ - Object o; - asm - { - mov o, EAX; - } - onHiddenFuncError(o); -} - -bool _d_isHalting = false; - -extern (C) bool rt_isHalting() -{ - return _d_isHalting; -} - -extern (C) bool rt_trapExceptions = true; - -void _d_criticalInit() -{ - version (linux) - { - _STI_monitor_staticctor(); - _STI_critical_init(); - } -} - -alias void delegate(Throwable) ExceptionHandler; - -extern (C) bool rt_init(ExceptionHandler dg = null) -{ - _d_criticalInit(); - - try - { - gc_init(); - initStaticDataGC(); - version (Windows) - _minit(); - _moduleCtor(); - return true; - } - catch (Throwable e) - { - if (dg) - dg(e); - } - catch - { - - } - _d_criticalTerm(); - return false; -} - -void _d_criticalTerm() -{ - version (linux) - { - _STD_critical_term(); - _STD_monitor_staticdtor(); - } -} - -extern (C) bool rt_term(ExceptionHandler dg = null) -{ - try - { - thread_joinAll(); - _d_isHalting = true; - _moduleDtor(); - gc_term(); - return true; - } - catch (Throwable e) - { - if (dg) - dg(e); - } - catch - { - - } - finally - { - _d_criticalTerm(); - } - return false; -} - -/*********************************** - * The D main() function supplied by the user's program - */ -int main(char[][] args); - -/*********************************** - * Substitutes for the C main() function. - * It's purpose is to wrap the call to the D main() - * function and catch any unhandled exceptions. - */ - -extern (C) int main(int argc, char **argv) -{ - char[][] args; - int result; - - version (linux) - { - _STI_monitor_staticctor(); - _STI_critical_init(); - } - - version (Windows) - { - wchar_t* wcbuf = GetCommandLineW(); - size_t wclen = wcslen(wcbuf); - int wargc = 0; - wchar_t** wargs = CommandLineToArgvW(wcbuf, &wargc); - assert(wargc == argc); - - char* cargp = null; - size_t cargl = WideCharToMultiByte(65001, 0, wcbuf, wclen, null, 0, null, 0); - - cargp = cast(char*) alloca(cargl); - args = ((cast(char[]*) alloca(wargc * (char[]).sizeof)))[0 .. wargc]; - - for (size_t i = 0, p = 0; i < wargc; i++) - { - int wlen = wcslen(wargs[i]); - int clen = WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, null, 0, null, 0); - args[i] = cargp[p .. p+clen]; - p += clen; assert(p <= cargl); - WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, &args[i][0], clen, null, 0); - } - LocalFree(wargs); - wargs = null; - wargc = 0; - } - else version (linux) - { - char[]* am = cast(char[]*) malloc(argc * (char[]).sizeof); - scope(exit) free(am); - - for (size_t i = 0; i < argc; i++) - { - auto len = strlen(argv[i]); - am[i] = argv[i][0 .. len]; - } - args = am[0 .. argc]; - } - - bool trapExceptions = rt_trapExceptions; - - void tryExec(void delegate() dg) - { - - if (trapExceptions) - { - try - { - dg(); - } - catch (Throwable e) - { - while (e) - { - if (e.file) - { - // fprintf(stderr, "%.*s(%u): %.*s\n", e.file, e.line, e.msg); - console (e.classinfo.name)("@")(e.file)("(")(e.line)("): ")(e.msg)("\n"); - } - else - { - // fprintf(stderr, "%.*s\n", e.toString()); - console (e.toString)("\n"); - } - if (e.info) - { - console ("----------------\n"); - foreach (t; e.info) - console (t)("\n"); - } - if (e.next) - console ("\n"); - e = e.next; - } - result = EXIT_FAILURE; - } - catch (Object o) - { - // fprintf(stderr, "%.*s\n", o.toString()); - console (o.toString)("\n"); - result = EXIT_FAILURE; - } - } - else - { - dg(); - } - } - - // NOTE: The lifetime of a process is much like the lifetime of an object: - // it is initialized, then used, then destroyed. If initialization - // fails, the successive two steps are never reached. However, if - // initialization succeeds, then cleanup will occur even if the use - // step fails in some way. Here, the use phase consists of running - // the user's main function. If main terminates with an exception, - // the exception is handled and then cleanup begins. An exception - // thrown during cleanup, however, will abort the cleanup process. - - void runMain() - { - result = main(args); - } - - void runAll() - { - gc_init(); - initStaticDataGC(); - version (Windows) - _minit(); - _moduleCtor(); - if (runModuleUnitTests()) - tryExec(&runMain); - thread_joinAll(); - _d_isHalting = true; - _moduleDtor(); - gc_term(); - } - - tryExec(&runAll); - - version (linux) - { - _STD_critical_term(); - _STD_monitor_staticdtor(); - } - return result; -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/dmain2.d --- a/druntime/src/compiler/ldc/dmain2.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,394 +0,0 @@ -/** - * Contains main program entry point and support routines. - * - * Copyright: Copyright Digital Mars 2000 - 2009. - * License: TypeidExpression. - */ -class TypeInfo : Object -{ - override hash_t toHash() - { - hash_t hash; - - foreach (char c; this.toString()) - hash = hash * 9 + c; - return hash; - } - - override int opCmp(Object o) - { - if (this is o) - return 0; - TypeInfo ti = cast(TypeInfo)o; - if (ti is null) - return 1; - return dstrcmp(this.toString(), ti.toString()); - } - - override equals_t opEquals(Object o) - { - /* TypeInfo instances are singletons, but duplicates can exist - * across DLL's. Therefore, comparing for a name match is - * sufficient. - */ - if (this is o) - return true; - TypeInfo ti = cast(TypeInfo)o; - return ti && this.toString() == ti.toString(); - } - - /// Returns a hash of the instance of a type. - hash_t getHash(in void* p) { return cast(hash_t)p; } - - /// Compares two instances for equality. - equals_t equals(in void* p1, in void* p2) { return p1 == p2; } - - /// Compares two instances for <, ==, or >. - int compare(in void* p1, in void* p2) { return 0; } - - /// Returns size of the type. - size_t tsize() { return 0; } - - /// Swaps two instances of the type. - void swap(void* p1, void* p2) - { - size_t n = tsize(); - for (size_t i = 0; i < n; i++) - { - byte t = (cast(byte *)p1)[i]; - (cast(byte*)p1)[i] = (cast(byte*)p2)[i]; - (cast(byte*)p2)[i] = t; - } - } - - /// Get TypeInfo for 'next' type, as defined by what kind of type this is, - /// null if none. - TypeInfo next() { return null; } - - /// Return default initializer, null if default initialize to 0 - void[] init() { return null; } - - /// Get flags for type: 1 means GC should scan for pointers - uint flags() { return 0; } - - /// Get type information on the contents of the type; null if not available - OffsetTypeInfo[] offTi() { return null; } - /// Run the destructor on the object and all its sub-objects - void destroy(void* p) {} - /// Run the postblit on the object and all its sub-objects - void postblit(void* p) {} -} - -class TypeInfo_Typedef : TypeInfo -{ - override string toString() { return name; } - - override equals_t opEquals(Object o) - { - TypeInfo_Typedef c; - return this is o || - ((c = cast(TypeInfo_Typedef)o) !is null && - this.name == c.name && - this.base == c.base); - } - - override hash_t getHash(in void* p) { return base.getHash(p); } - override equals_t equals(in void* p1, in void* p2) { return base.equals(p1, p2); } - override int compare(in void* p1, in void* p2) { return base.compare(p1, p2); } - override size_t tsize() { return base.tsize(); } - override void swap(void* p1, void* p2) { return base.swap(p1, p2); } - - override TypeInfo next() { return base.next(); } - override uint flags() { return base.flags(); } - override void[] init() { return m_init.length ? m_init : base.init(); } - - TypeInfo base; - string name; - void[] m_init; -} - -class TypeInfo_Enum : TypeInfo_Typedef -{ - -} - -class TypeInfo_Pointer : TypeInfo -{ - override string toString() { return m_next.toString() ~ "*"; } - - override equals_t opEquals(Object o) - { - TypeInfo_Pointer c; - return this is o || - ((c = cast(TypeInfo_Pointer)o) !is null && - this.m_next == c.m_next); - } - - override hash_t getHash(in void* p) - { - return cast(hash_t)*cast(void**)p; - } - - override equals_t equals(in void* p1, in void* p2) - { - return *cast(void**)p1 == *cast(void**)p2; - } - - override int compare(in void* p1, in void* p2) - { - if (*cast(void**)p1 < *cast(void**)p2) - return -1; - else if (*cast(void**)p1 > *cast(void**)p2) - return 1; - else - return 0; - } - - override size_t tsize() - { - return (void*).sizeof; - } - - override void swap(void* p1, void* p2) - { - void* tmp = *cast(void**)p1; - *cast(void**)p1 = *cast(void**)p2; - *cast(void**)p2 = tmp; - } - - override TypeInfo next() { return m_next; } - override uint flags() { return 1; } - - TypeInfo m_next; -} - -class TypeInfo_Array : TypeInfo -{ - override string toString() { return value.toString() ~ "[]"; } - - override equals_t opEquals(Object o) - { - TypeInfo_Array c; - return this is o || - ((c = cast(TypeInfo_Array)o) !is null && - this.value == c.value); - } - - override hash_t getHash(in void* p) - { - size_t sz = value.tsize(); - hash_t hash = 0; - void[] a = *cast(void[]*)p; - for (size_t i = 0; i < a.length; i++) - hash += value.getHash(a.ptr + i * sz) * 11; - return hash; - } - - override equals_t equals(in void* p1, in void* p2) - { - void[] a1 = *cast(void[]*)p1; - void[] a2 = *cast(void[]*)p2; - if (a1.length != a2.length) - return false; - size_t sz = value.tsize(); - for (size_t i = 0; i < a1.length; i++) - { - if (!value.equals(a1.ptr + i * sz, a2.ptr + i * sz)) - return false; - } - return true; - } - - override int compare(in void* p1, in void* p2) - { - void[] a1 = *cast(void[]*)p1; - void[] a2 = *cast(void[]*)p2; - size_t sz = value.tsize(); - size_t len = a1.length; - - if (a2.length < len) - len = a2.length; - for (size_t u = 0; u < len; u++) - { - int result = value.compare(a1.ptr + u * sz, a2.ptr + u * sz); - if (result) - return result; - } - return cast(int)a1.length - cast(int)a2.length; - } - - override size_t tsize() - { - return (void[]).sizeof; - } - - override void swap(void* p1, void* p2) - { - void[] tmp = *cast(void[]*)p1; - *cast(void[]*)p1 = *cast(void[]*)p2; - *cast(void[]*)p2 = tmp; - } - - TypeInfo value; - - override TypeInfo next() - { - return value; - } - - override uint flags() { return 1; } -} - -class TypeInfo_StaticArray : TypeInfo -{ - override string toString() - { - char[10] tmp = void; - return cast(string)(value.toString() ~ "[" ~ tmp.intToString(len) ~ "]"); - } - - override equals_t opEquals(Object o) - { - TypeInfo_StaticArray c; - return this is o || - ((c = cast(TypeInfo_StaticArray)o) !is null && - this.len == c.len && - this.value == c.value); - } - - override hash_t getHash(in void* p) - { - size_t sz = value.tsize(); - hash_t hash = 0; - for (size_t i = 0; i < len; i++) - hash += value.getHash(p + i * sz); - return hash; - } - - override equals_t equals(in void* p1, in void* p2) - { - size_t sz = value.tsize(); - - for (size_t u = 0; u < len; u++) - { - if (!value.equals(p1 + u * sz, p2 + u * sz)) - return false; - } - return true; - } - - override int compare(in void* p1, in void* p2) - { - size_t sz = value.tsize(); - - for (size_t u = 0; u < len; u++) - { - int result = value.compare(p1 + u * sz, p2 + u * sz); - if (result) - return result; - } - return 0; - } - - override size_t tsize() - { - return len * value.tsize(); - } - - override void swap(void* p1, void* p2) - { - void* tmp; - size_t sz = value.tsize(); - ubyte[16] buffer; - void* pbuffer; - - if (sz < buffer.sizeof) - tmp = buffer.ptr; - else - tmp = pbuffer = (new void[sz]).ptr; - - for (size_t u = 0; u < len; u += sz) - { size_t o = u * sz; - memcpy(tmp, p1 + o, sz); - memcpy(p1 + o, p2 + o, sz); - memcpy(p2 + o, tmp, sz); - } - if (pbuffer) - delete pbuffer; - } - - override void[] init() { return value.init(); } - override TypeInfo next() { return value; } - override uint flags() { return value.flags(); } - - override void destroy(void* p) - { - auto sz = value.tsize(); - p += sz * len; - foreach (i; 0 .. len) - { - p -= sz; - value.destroy(p); - } - } - - override void postblit(void* p) - { - auto sz = value.tsize(); - foreach (i; 0 .. len) - { - value.postblit(p); - p += sz; - } - } - - TypeInfo value; - size_t len; -} - -class TypeInfo_AssociativeArray : TypeInfo -{ - override string toString() - { - return cast(string)(next.toString() ~ "[" ~ key.toString() ~ "]"); - } - - override equals_t opEquals(Object o) - { - TypeInfo_AssociativeArray c; - return this is o || - ((c = cast(TypeInfo_AssociativeArray)o) !is null && - this.key == c.key && - this.value == c.value); - } - - // BUG: need to add the rest of the functions - - override size_t tsize() - { - return (char[int]).sizeof; - } - - override TypeInfo next() { return value; } - override uint flags() { return 1; } - - TypeInfo value; - TypeInfo key; -} - -class TypeInfo_Function : TypeInfo -{ - override string toString() - { - return cast(string)(next.toString() ~ "()"); - } - - override equals_t opEquals(Object o) - { - TypeInfo_Function c; - return this is o || - ((c = cast(TypeInfo_Function)o) !is null && - this.next == c.next); - } - - // BUG: need to add the rest of the functions - - override size_t tsize() - { - return 0; // no size for functions - } - - TypeInfo next; -} - -class TypeInfo_Delegate : TypeInfo -{ - override string toString() - { - return cast(string)(next.toString() ~ " delegate()"); - } - - override equals_t opEquals(Object o) - { - TypeInfo_Delegate c; - return this is o || - ((c = cast(TypeInfo_Delegate)o) !is null && - this.next == c.next); - } - - // BUG: need to add the rest of the functions - - override size_t tsize() - { - alias int delegate() dg; - return dg.sizeof; - } - - override uint flags() { return 1; } - - TypeInfo next; -} - -class TypeInfo_Class : TypeInfo -{ - override string toString() { return info.name; } - - override equals_t opEquals(Object o) - { - TypeInfo_Class c; - return this is o || - ((c = cast(TypeInfo_Class)o) !is null && - this.info.name == c.classinfo.name); - } - - override hash_t getHash(in void* p) - { - Object o = *cast(Object*)p; - return o ? o.toHash() : 0; - } - - override equals_t equals(in void* p1, in void* p2) - { - Object o1 = *cast(Object*)p1; - Object o2 = *cast(Object*)p2; - - return (o1 is o2) || (o1 && o1.opEquals(o2)); - } - - override int compare(in void* p1, in void* p2) - { - Object o1 = *cast(Object*)p1; - Object o2 = *cast(Object*)p2; - int c = 0; - - // Regard null references as always being "less than" - if (o1 !is o2) - { - if (o1) - { - if (!o2) - c = 1; - else - c = o1.opCmp(o2); - } - else - c = -1; - } - return c; - } - - override size_t tsize() - { - return Object.sizeof; - } - - override uint flags() { return 1; } - - override OffsetTypeInfo[] offTi() - { - return (info.flags & 4) ? info.offTi : null; - } - - ClassInfo info; -} - -class TypeInfo_Interface : TypeInfo -{ - override string toString() { return info.name; } - - override equals_t opEquals(Object o) - { - TypeInfo_Interface c; - return this is o || - ((c = cast(TypeInfo_Interface)o) !is null && - this.info.name == c.classinfo.name); - } - - override hash_t getHash(in void* p) - { - Interface* pi = **cast(Interface ***)*cast(void**)p; - Object o = cast(Object)(*cast(void**)p - pi.offset); - assert(o); - return o.toHash(); - } - - override equals_t equals(in void* p1, in void* p2) - { - Interface* pi = **cast(Interface ***)*cast(void**)p1; - Object o1 = cast(Object)(*cast(void**)p1 - pi.offset); - pi = **cast(Interface ***)*cast(void**)p2; - Object o2 = cast(Object)(*cast(void**)p2 - pi.offset); - - return o1 == o2 || (o1 && o1.opCmp(o2) == 0); - } - - override int compare(in void* p1, in void* p2) - { - Interface* pi = **cast(Interface ***)*cast(void**)p1; - Object o1 = cast(Object)(*cast(void**)p1 - pi.offset); - pi = **cast(Interface ***)*cast(void**)p2; - Object o2 = cast(Object)(*cast(void**)p2 - pi.offset); - int c = 0; - - // Regard null references as always being "less than" - if (o1 != o2) - { - if (o1) - { - if (!o2) - c = 1; - else - c = o1.opCmp(o2); - } - else - c = -1; - } - return c; - } - - override size_t tsize() - { - return Object.sizeof; - } - - override uint flags() { return 1; } - - ClassInfo info; -} - -class TypeInfo_Struct : TypeInfo -{ - override string toString() { return name; } - - override equals_t opEquals(Object o) - { - TypeInfo_Struct s; - return this is o || - ((s = cast(TypeInfo_Struct)o) !is null && - this.name == s.name && - this.init.length == s.init.length); - } - - override hash_t getHash(in void* p) - { - assert(p); - if (xtoHash) - { - debug(PRINTF) printf("getHash() using xtoHash\n"); - return (*xtoHash)(p); - } - else - { - hash_t h; - debug(PRINTF) printf("getHash() using default hash\n"); - // A sorry hash algorithm. - // Should use the one for strings. - // BUG: relies on the GC not moving objects - auto q = cast(const(ubyte)*)p; - for (size_t i = 0; i < init.length; i++) - { - h = h * 9 + *q; - q++; - } - return h; - } - } - - override equals_t equals(in void* p1, in void* p2) - { - if (p1 == p2) - return true; - else if (!p1 || !p2) - return false; - else if (xopEquals) - return (*xopEquals)(p1, p2); - else - // BUG: relies on the GC not moving objects - return memcmp(p1, p2, init.length) == 0; - } - - override int compare(in void* p1, in void* p2) - { - // Regard null references as always being "less than" - if (p1 != p2) - { - if (p1) - { - if (!p2) - return true; - else if (xopCmp) - return (*xopCmp)(p2, p1); - else - // BUG: relies on the GC not moving objects - return memcmp(p1, p2, init.length); - } - else - return -1; - } - return 0; - } - - override size_t tsize() - { - return init.length; - } - - override void[] init() { return m_init; } - - override uint flags() { return m_flags; } - - override void destroy(void* p) - { - if (xdtor) - (*xdtor)(p); - } - - override void postblit(void* p) - { - if (xpostblit) - (*xpostblit)(p); - } - - string name; - void[] m_init; // initializer; init.ptr == null if 0 initialize - - hash_t function(in void*) xtoHash; - equals_t function(in void*, in void*) xopEquals; - int function(in void*, in void*) xopCmp; - string function(in void*) xtoString; - - uint m_flags; - - const(MemberInfo[]) function(in char[]) xgetMembers; - void function(void*) xdtor; - void function(void*) xpostblit; -} - -class TypeInfo_Tuple : TypeInfo -{ - TypeInfo[] elements; - - override string toString() - { - string s = "("; - foreach (i, element; elements) - { - if (i) - s ~= ','; - s ~= element.toString(); - } - s ~= ")"; - return s; - } - - override equals_t opEquals(Object o) - { - if (this is o) - return true; - - auto t = cast(TypeInfo_Tuple)o; - if (t && elements.length == t.elements.length) - { - for (size_t i = 0; i < elements.length; i++) - { - if (elements[i] != t.elements[i]) - return false; - } - return true; - } - return false; - } - - override hash_t getHash(in void* p) - { - assert(0); - } - - override equals_t equals(in void* p1, in void* p2) - { - assert(0); - } - - override int compare(in void* p1, in void* p2) - { - assert(0); - } - - override size_t tsize() - { - assert(0); - } - - override void swap(void* p1, void* p2) - { - assert(0); - } - - override void destroy(void* p) - { - assert(0); - } - - override void postblit(void* p) - { - assert(0); - } -} - -class TypeInfo_Const : TypeInfo -{ - override string toString() - { - return cast(string) ("const(" ~ base.toString() ~ ")"); - } - - override equals_t opEquals(Object o) { return base.opEquals(o); } - override hash_t getHash(in void *p) { return base.getHash(p); } - override equals_t equals(in void *p1, in void *p2) { return base.equals(p1, p2); } - override int compare(in void *p1, in void *p2) { return base.compare(p1, p2); } - override size_t tsize() { return base.tsize(); } - override void swap(void *p1, void *p2) { return base.swap(p1, p2); } - - override TypeInfo next() { return base.next(); } - override uint flags() { return base.flags(); } - override void[] init() { return base.init(); } - - TypeInfo base; -} - -class TypeInfo_Invariant : TypeInfo_Const -{ - override string toString() - { - return cast(string) ("immutable(" ~ base.toString() ~ ")"); - } -} - -class TypeInfo_Shared : TypeInfo_Const -{ - override string toString() - { - return cast(string) ("shared(" ~ base.toString() ~ ")"); - } -} - -abstract class MemberInfo -{ - string name(); -} - -class MemberInfo_field : MemberInfo -{ - this(string name, TypeInfo ti, size_t offset) - { - m_name = name; - m_typeinfo = ti; - m_offset = offset; - } - - override string name() { return m_name; } - TypeInfo typeInfo() { return m_typeinfo; } - size_t offset() { return m_offset; } - - string m_name; - TypeInfo m_typeinfo; - size_t m_offset; -} - -class MemberInfo_function : MemberInfo -{ - this(string name, TypeInfo ti, void* fp, uint flags) - { - m_name = name; - m_typeinfo = ti; - m_fp = fp; - m_flags = flags; - } - - override string name() { return m_name; } - TypeInfo typeInfo() { return m_typeinfo; } - void* fp() { return m_fp; } - uint flags() { return m_flags; } - - string m_name; - TypeInfo m_typeinfo; - void* m_fp; - uint m_flags; -} - - -/////////////////////////////////////////////////////////////////////////////// -// Throwable -/////////////////////////////////////////////////////////////////////////////// - - -class Throwable : Object -{ - interface TraceInfo - { - int opApply(int delegate(inout char[])); - } - - string msg; - string file; - size_t line; - TraceInfo info; - Throwable next; - - this(string msg, Throwable next = null) - { - this.msg = msg; - this.next = next; - this.info = traceContext(); - } - - this(string msg, string file, size_t line, Throwable next = null) - { - this(msg, next); - this.file = file; - this.line = line; - this.info = traceContext(); - } - - override string toString() - { - char[10] tmp = void; - char[] buf; - - for (Throwable e = this; e !is null; e = e.next) - { - if (e.file) - { - buf ~= e.classinfo.name ~ "@" ~ e.file ~ "(" ~ tmp.intToString(e.line) ~ "): " ~ e.msg; - } - else - { - buf ~= e.classinfo.name ~ ": " ~ e.msg; - } - if (e.info) - { - buf ~= "\n----------------"; - foreach (t; e.info) - buf ~= "\n" ~ t; - } - if (e.next) - buf ~= "\n"; - } - return cast(string) buf; - } -} - - -alias Throwable.TraceInfo function(void* ptr = null) TraceHandler; -private __gshared TraceHandler traceHandler = null; - - -/** - * Overrides the default trace hander with a user-supplied version. - * - * Params: - * h = The new trace handler. Set to null to use the default handler. - */ -extern (C) void rt_setTraceHandler(TraceHandler h) -{ - traceHandler = h; -} - - -/** - * This function will be called when an exception is constructed. The - * user-supplied trace handler will be called if one has been supplied, - * otherwise no trace will be generated. - * - * Params: - * ptr = A pointer to the location from which to generate the trace, or null - * if the trace should be generated from within the trace handler - * itself. - * - * Returns: - * An object describing the current calling context or null if no handler is - * supplied. - */ -Throwable.TraceInfo traceContext(void* ptr = null) -{ - if (traceHandler is null) - return null; - return traceHandler(ptr); -} - - -class Exception : Throwable -{ - this(string msg, Throwable next = null) - { - super(msg, next); - } - - this(string msg, string file, size_t line, Throwable next = null) - { - super(msg, file, line, next); - } -} - - -class Error : Throwable -{ - this(string msg, Throwable next = null) - { - super(msg, next); - } - - this(string msg, string file, size_t line, Throwable next = null) - { - super(msg, file, line, next); - } -} - - -/////////////////////////////////////////////////////////////////////////////// -// ModuleInfo -/////////////////////////////////////////////////////////////////////////////// - - -enum -{ - MIctorstart = 1, // we've started constructing it - MIctordone = 2, // finished construction - MIstandalone = 4, // module ctor does not depend on other module - // ctors being done first - MIhasictor = 8, // has ictor member -} - - -class ModuleInfo -{ - string name; - ModuleInfo[] importedModules; - ClassInfo[] localClasses; - uint flags; - - void function() ctor; // module static constructor (order dependent) - void function() dtor; // module static destructor - void function() unitTest; // module unit tests - - void* xgetMembers; // module getMembers() function - - void function() ictor; // module static constructor (order independent) - - void*[4] reserved; // for future expansion - - static int opApply(int delegate(inout ModuleInfo) dg) - { - int ret = 0; - - foreach (m; _moduleinfo_array) - { - ret = dg(m); - if (ret) - break; - } - return ret; - } -} - - -// Windows: this gets initialized by minit.asm -// Posix: this gets initialized in _moduleCtor() -extern (C) __gshared ModuleInfo[] _moduleinfo_array; - - -version (linux) -{ - // This linked list is created by a compiler generated function inserted - // into the .ctor list by the compiler. - struct ModuleReference - { - ModuleReference* next; - ModuleInfo mod; - } - - extern (C) __gshared ModuleReference* _Dmodule_ref; // start of linked list -} - -version (FreeBSD) -{ - // This linked list is created by a compiler generated function inserted - // into the .ctor list by the compiler. - struct ModuleReference - { - ModuleReference* next; - ModuleInfo mod; - } - - extern (C) __gshared ModuleReference* _Dmodule_ref; // start of linked list -} - -version (Solaris) -{ - // This linked list is created by a compiler generated function inserted - // into the .ctor list by the compiler. - struct ModuleReference - { - ModuleReference* next; - ModuleInfo mod; - } - - extern (C) __gshared ModuleReference* _Dmodule_ref; // start of linked list -} - -version (OSX) -{ - extern (C) - { - extern __gshared void* _minfo_beg; - extern __gshared void* _minfo_end; - } -} - -__gshared ModuleInfo[] _moduleinfo_dtors; -__gshared uint _moduleinfo_dtors_i; - -// Register termination function pointers -extern (C) int _fatexit(void*); - -/** - * Initialize the modules. - */ - -extern (C) void _moduleCtor() -{ - debug(PRINTF) printf("_moduleCtor()\n"); - version (linux) - { - int len = 0; - ModuleReference *mr; - - for (mr = _Dmodule_ref; mr; mr = mr.next) - len++; - _moduleinfo_array = new ModuleInfo[len]; - len = 0; - for (mr = _Dmodule_ref; mr; mr = mr.next) - { _moduleinfo_array[len] = mr.mod; - len++; - } - } - - version (FreeBSD) - { - int len = 0; - ModuleReference *mr; - - for (mr = _Dmodule_ref; mr; mr = mr.next) - len++; - _moduleinfo_array = new ModuleInfo[len]; - len = 0; - for (mr = _Dmodule_ref; mr; mr = mr.next) - { _moduleinfo_array[len] = mr.mod; - len++; - } - } - - version (Solaris) - { - int len = 0; - ModuleReference *mr; - - for (mr = _Dmodule_ref; mr; mr = mr.next) - len++; - _moduleinfo_array = new ModuleInfo[len]; - len = 0; - for (mr = _Dmodule_ref; mr; mr = mr.next) - { _moduleinfo_array[len] = mr.mod; - len++; - } - } - - version (OSX) - { - /* The ModuleInfo references are stored in the special segment - * __minfodata, which is bracketed by the segments __minfo_beg - * and __minfo_end. The variables _minfo_beg and _minfo_end - * are of zero size and are in the two bracketing segments, - * respectively. - */ - size_t length = cast(ModuleInfo*)&_minfo_end - cast(ModuleInfo*)&_minfo_beg; - _moduleinfo_array = (cast(ModuleInfo*)&_minfo_beg)[0 .. length]; - debug printf("moduleinfo: ptr = %p, length = %d\n", _moduleinfo_array.ptr, _moduleinfo_array.length); - - debug foreach (m; _moduleinfo_array) - { - //printf("\t%p\n", m); - printf("\t%.*s\n", m.name); - } - } - - version (Windows) - { - // Ensure module destructors also get called on program termination - //_fatexit(&_STD_moduleDtor); - } - - _moduleinfo_dtors = new ModuleInfo[_moduleinfo_array.length]; - debug(PRINTF) printf("_moduleinfo_dtors = x%x\n", cast(void*)_moduleinfo_dtors); - _moduleIndependentCtors(); - _moduleCtor2(_moduleinfo_array, 0); -} - -extern (C) void _moduleIndependentCtors() -{ - debug(PRINTF) printf("_moduleIndependentCtors()\n"); - foreach (m; _moduleinfo_array) - { - if (m && m.flags & MIhasictor && m.ictor) - { - (*m.ictor)(); - } - } -} - -void _moduleCtor2(ModuleInfo[] mi, int skip) -{ - debug(PRINTF) printf("_moduleCtor2(): %d modules\n", mi.length); - for (uint i = 0; i < mi.length; i++) - { - ModuleInfo m = mi[i]; - - debug(PRINTF) printf("\tmodule[%d] = '%p'\n", i, m); - if (!m) - continue; - debug(PRINTF) printf("\tmodule[%d] = '%.*s'\n", i, m.name); - if (m.flags & MIctordone) - continue; - debug(PRINTF) printf("\tmodule[%d] = '%.*s', m = x%x\n", i, m.name, m); - - if (m.ctor || m.dtor) - { - if (m.flags & MIctorstart) - { if (skip || m.flags & MIstandalone) - continue; - throw new Exception("Cyclic dependency in module " ~ m.name); - } - - m.flags |= MIctorstart; - _moduleCtor2(m.importedModules, 0); - if (m.ctor) - (*m.ctor)(); - m.flags &= ~MIctorstart; - m.flags |= MIctordone; - - // Now that construction is done, register the destructor - //printf("\tadding module dtor x%x\n", m); - assert(_moduleinfo_dtors_i < _moduleinfo_dtors.length); - _moduleinfo_dtors[_moduleinfo_dtors_i++] = m; - } - else - { - m.flags |= MIctordone; - _moduleCtor2(m.importedModules, 1); - } - } -} - -/** - * Destruct the modules. - */ - -// Starting the name with "_STD" means under Posix a pointer to the -// function gets put in the .dtors segment. - -extern (C) void _moduleDtor() -{ - debug(PRINTF) printf("_moduleDtor(): %d modules\n", _moduleinfo_dtors_i); - - for (uint i = _moduleinfo_dtors_i; i-- != 0;) - { - ModuleInfo m = _moduleinfo_dtors[i]; - - debug(PRINTF) printf("\tmodule[%d] = '%.*s', x%x\n", i, m.name, m); - if (m.dtor) - { - (*m.dtor)(); - } - } - debug(PRINTF) printf("_moduleDtor() done\n"); -} - -/////////////////////////////////////////////////////////////////////////////// -// Monitor -/////////////////////////////////////////////////////////////////////////////// - -alias Object.Monitor IMonitor; -alias void delegate(Object) DEvent; - -// NOTE: The dtor callback feature is only supported for monitors that are not -// supplied by the user. The assumption is that any object with a user- -// supplied monitor may have special storage or lifetime requirements and -// that as a result, storing references to local objects within Monitor -// may not be safe or desirable. Thus, devt is only valid if impl is -// null. -struct Monitor -{ - IMonitor impl; - /* internal */ - DEvent[] devt; - /* stuff */ -} - -Monitor* getMonitor(Object h) -{ - return cast(Monitor*) (cast(void**) h)[1]; -} - -void setMonitor(Object h, Monitor* m) -{ - (cast(void**) h)[1] = m; -} - -extern (C) void _d_monitor_create(Object); -extern (C) void _d_monitor_destroy(Object); -extern (C) void _d_monitor_lock(Object); -extern (C) int _d_monitor_unlock(Object); - -extern (C) void _d_monitordelete(Object h, bool det) -{ - Monitor* m = getMonitor(h); - - if (m !is null) - { - IMonitor i = m.impl; - if (i is null) - { - _d_monitor_devt(m, h); - _d_monitor_destroy(h); - setMonitor(h, null); - return; - } - if (det && (cast(void*) i) !is (cast(void*) h)) - delete i; - setMonitor(h, null); - } -} - -extern (C) void _d_monitorenter(Object h) -{ - Monitor* m = getMonitor(h); - - if (m is null) - { - _d_monitor_create(h); - m = getMonitor(h); - } - - IMonitor i = m.impl; - - if (i is null) - { - _d_monitor_lock(h); - return; - } - i.lock(); -} - -extern (C) void _d_monitorexit(Object h) -{ - Monitor* m = getMonitor(h); - IMonitor i = m.impl; - - if (i is null) - { - _d_monitor_unlock(h); - return; - } - i.unlock(); -} - -extern (C) void _d_monitor_devt(Monitor* m, Object h) -{ - if (m.devt.length) - { - DEvent[] devt; - - synchronized (h) - { - devt = m.devt; - m.devt = null; - } - foreach (v; devt) - { - if (v) - v(h); - } - free(devt.ptr); - } -} - -extern (C) void rt_attachDisposeEvent(Object h, DEvent e) -{ - synchronized (h) - { - Monitor* m = getMonitor(h); - assert(m.impl is null); - - foreach (inout v; m.devt) - { - if (v is null || v == e) - { - v = e; - return; - } - } - - auto len = m.devt.length + 4; // grow by 4 elements - auto pos = m.devt.length; // insert position - auto p = realloc(m.devt.ptr, DEvent.sizeof * len); - if (!p) - onOutOfMemoryError(); - m.devt = (cast(DEvent*)p)[0 .. len]; - m.devt[pos+1 .. len] = null; - m.devt[pos] = e; - } -} - -extern (C) void rt_detachDisposeEvent(Object h, DEvent e) -{ - synchronized (h) - { - Monitor* m = getMonitor(h); - assert(m.impl is null); - - foreach (p, v; m.devt) - { - if (v == e) - { - memmove(&m.devt[p], - &m.devt[p+1], - (m.devt.length - p - 1) * DEvent.sizeof); - m.devt[$ - 1] = null; - return; - } - } - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/invariant.d --- a/druntime/src/compiler/ldc/invariant.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -/** - * Implementation of invariant support routines. - * - * Copyright: Copyright Digital Mars 2007 - 2009. - * License: p.length) - { - size_t size = p.length * sizeelem; - auto info = gc_query(p.data); - - if (info.size <= newsize || info.base != p.data) - { - if (info.size >= PAGESIZE && info.base == p.data) - { // Try to extend in-place - auto u = gc_extend(p.data, (newsize + 1) - info.size, (newsize + 1) - info.size); - if (u) - { - goto L1; - } - } - newdata = cast(byte *)gc_malloc(newsize + 1, info.attr); - newdata[0 .. size] = p.data[0 .. size]; - } - L1: - newdata[size .. newsize] = 0; - } - } - else - { - newdata = cast(byte *)gc_calloc(newsize + 1, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0); - } - } - else - { - newdata = p.data; - } - - p.data = newdata; - p.length = newlength; - return newdata[0 .. newlength]; - -Loverflow: - onOutOfMemoryError(); -} - - -/** - * Resize arrays for non-zero initializers. - * p pointer to array lvalue to be updated - * newlength new .length property of array - * sizeelem size of each element of array - * initsize size of initializer - * ... initializer - */ -extern (C) byte[] _d_arraysetlengthiT(TypeInfo ti, size_t newlength, Array *p) -in -{ - assert(!p.length || p.data); -} -body -{ - byte* newdata; - size_t sizeelem = ti.next.tsize(); - void[] initializer = ti.next.init(); - size_t initsize = initializer.length; - - assert(sizeelem); - assert(initsize); - assert(initsize <= sizeelem); - assert((sizeelem / initsize) * initsize == sizeelem); - - debug(PRINTF) - { - printf("_d_arraysetlengthiT(p = %p, sizeelem = %d, newlength = %d, initsize = %d)\n", p, sizeelem, newlength, initsize); - if (p) - printf("\tp.data = %p, p.length = %d\n", p.data, p.length); - } - - if (newlength) - { - version (D_InlineAsm_X86) - { - size_t newsize = void; - - asm - { - mov EAX,newlength ; - mul EAX,sizeelem ; - mov newsize,EAX ; - jc Loverflow ; - } - } - else - { - size_t newsize = sizeelem * newlength; - - if (newsize / newlength != sizeelem) - goto Loverflow; - } - debug(PRINTF) printf("newsize = %x, newlength = %x\n", newsize, newlength); - - size_t size = p.length * sizeelem; - - if (p.data) - { - newdata = p.data; - if (newlength > p.length) - { - auto info = gc_query(p.data); - - if (info.size <= newsize || info.base != p.data) - { - if (info.size >= PAGESIZE && info.base == p.data) - { // Try to extend in-place - auto u = gc_extend(p.data, (newsize + 1) - info.size, (newsize + 1) - info.size); - if (u) - { - goto L1; - } - } - newdata = cast(byte *)gc_malloc(newsize + 1, info.attr); - newdata[0 .. size] = p.data[0 .. size]; - L1: ; - } - } - } - else - { - newdata = cast(byte *)gc_malloc(newsize + 1, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0); - } - - auto q = initializer.ptr; // pointer to initializer - - if (newsize > size) - { - if (initsize == 1) - { - debug(PRINTF) printf("newdata = %p, size = %d, newsize = %d, *q = %d\n", newdata, size, newsize, *cast(byte*)q); - newdata[size .. newsize] = *(cast(byte*)q); - } - else - { - for (size_t u = size; u < newsize; u += initsize) - { - memcpy(newdata + u, q, initsize); - } - } - } - } - else - { - newdata = p.data; - } - - p.data = newdata; - p.length = newlength; - return newdata[0 .. newlength]; - -Loverflow: - onOutOfMemoryError(); -} - - -/** - * Append y[] to array x[]. - * size is size of each array element. - */ -extern (C) long _d_arrayappendT(TypeInfo ti, Array *px, byte[] y) -{ - auto sizeelem = ti.next.tsize(); // array element size - auto info = gc_query(px.data); - auto length = px.length; - auto newlength = length + y.length; - auto newsize = newlength * sizeelem; - - if (info.size < newsize || info.base != px.data) - { byte* newdata; - - if (info.size >= PAGESIZE && info.base == px.data) - { // Try to extend in-place - auto u = gc_extend(px.data, (newsize + 1) - info.size, (newsize + 1) - info.size); - if (u) - { - goto L1; - } - } - newdata = cast(byte *)gc_malloc(newCapacity(newlength, sizeelem) + 1, info.attr); - memcpy(newdata, px.data, length * sizeelem); - px.data = newdata; - } - L1: - px.length = newlength; - memcpy(px.data + length * sizeelem, y.ptr, y.length * sizeelem); - return *cast(long*)px; -} - - -/** - * - */ -size_t newCapacity(size_t newlength, size_t size) -{ - version(none) - { - size_t newcap = newlength * size; - } - else - { - /* - * Better version by Dave Fladebo: - * This uses an inverse logorithmic algorithm to pre-allocate a bit more - * space for larger arrays. - * - Arrays smaller than PAGESIZE bytes are left as-is, so for the most - * common cases, memory allocation is 1 to 1. The small overhead added - * doesn't affect small array perf. (it's virtually the same as - * current). - * - Larger arrays have some space pre-allocated. - * - As the arrays grow, the relative pre-allocated space shrinks. - * - The logorithmic algorithm allocates relatively more space for - * mid-size arrays, making it very fast for medium arrays (for - * mid-to-large arrays, this turns out to be quite a bit faster than the - * equivalent realloc() code in C, on Linux at least. Small arrays are - * just as fast as GCC). - * - Perhaps most importantly, overall memory usage and stress on the GC - * is decreased significantly for demanding environments. - */ - size_t newcap = newlength * size; - size_t newext = 0; - - if (newcap > PAGESIZE) - { - //double mult2 = 1.0 + (size / log10(pow(newcap * 2.0,2.0))); - - // redo above line using only integer math - - static int log2plus1(size_t c) - { int i; - - if (c == 0) - i = -1; - else - for (i = 1; c >>= 1; i++) - { - } - return i; - } - - /* The following setting for mult sets how much bigger - * the new size will be over what is actually needed. - * 100 means the same size, more means proportionally more. - * More means faster but more memory consumption. - */ - //long mult = 100 + (1000L * size) / (6 * log2plus1(newcap)); - long mult = 100 + (1000L * size) / log2plus1(newcap); - - // testing shows 1.02 for large arrays is about the point of diminishing return - if (mult < 102) - mult = 102; - newext = cast(size_t)((newcap * mult) / 100); - newext -= newext % size; - debug(PRINTF) printf("mult: %2.2f, alloc: %2.2f\n",mult/100.0,newext / cast(double)size); - } - newcap = newext > newcap ? newext : newcap; - debug(PRINTF) printf("newcap = %d, newlength = %d, size = %d\n", newcap, newlength, size); - } - return newcap; -} - - -/** - * - */ -extern (C) byte[] _d_arrayappendcT(TypeInfo ti, inout byte[] x, ...) -{ - auto sizeelem = ti.next.tsize(); // array element size - auto info = gc_query(x.ptr); - auto length = x.length; - auto newlength = length + 1; - auto newsize = newlength * sizeelem; - - assert(info.size == 0 || length * sizeelem <= info.size); - - debug(PRINTF) printf("_d_arrayappendcT(sizeelem = %d, ptr = %p, length = %d, cap = %d)\n", sizeelem, x.ptr, x.length, info.size); - - if (info.size <= newsize || info.base != x.ptr) - { byte* newdata; - - if (info.size >= PAGESIZE && info.base == x.ptr) - { // Try to extend in-place - auto u = gc_extend(x.ptr, (newsize + 1) - info.size, (newsize + 1) - info.size); - if (u) - { - goto L1; - } - } - debug(PRINTF) printf("_d_arrayappendcT(length = %d, newlength = %d, cap = %d)\n", length, newlength, info.size); - auto newcap = newCapacity(newlength, sizeelem); - assert(newcap >= newlength * sizeelem); - newdata = cast(byte *)gc_malloc(newcap + 1, info.attr); - memcpy(newdata, x.ptr, length * sizeelem); - (cast(void**)(&x))[1] = newdata; - } - L1: - byte *argp = cast(byte *)(&ti + 2); - - *cast(size_t *)&x = newlength; - x.ptr[length * sizeelem .. newsize] = argp[0 .. sizeelem]; - assert((cast(size_t)x.ptr & 15) == 0); - assert(gc_sizeOf(x.ptr) > x.length * sizeelem); - return x; -} - - -/** - * - */ -extern (C) byte[] _d_arraycatT(TypeInfo ti, byte[] x, byte[] y) -out (result) -{ - auto sizeelem = ti.next.tsize(); // array element size - debug(PRINTF) printf("_d_arraycatT(%d,%p ~ %d,%p sizeelem = %d => %d,%p)\n", x.length, x.ptr, y.length, y.ptr, sizeelem, result.length, result.ptr); - assert(result.length == x.length + y.length); - for (size_t i = 0; i < x.length * sizeelem; i++) - assert((cast(byte*)result)[i] == (cast(byte*)x)[i]); - for (size_t i = 0; i < y.length * sizeelem; i++) - assert((cast(byte*)result)[x.length * sizeelem + i] == (cast(byte*)y)[i]); - - size_t cap = gc_sizeOf(result.ptr); - assert(!cap || cap > result.length * sizeelem); -} -body -{ - version (none) - { - /* Cannot use this optimization because: - * char[] a, b; - * char c = 'a'; - * b = a ~ c; - * c = 'b'; - * will change the contents of b. - */ - if (!y.length) - return x; - if (!x.length) - return y; - } - - debug(PRINTF) printf("_d_arraycatT(%d,%p ~ %d,%p)\n", x.length, x.ptr, y.length, y.ptr); - auto sizeelem = ti.next.tsize(); // array element size - debug(PRINTF) printf("_d_arraycatT(%d,%p ~ %d,%p sizeelem = %d)\n", x.length, x.ptr, y.length, y.ptr, sizeelem); - size_t xlen = x.length * sizeelem; - size_t ylen = y.length * sizeelem; - size_t len = xlen + ylen; - - if (!len) - return null; - - byte* p = cast(byte*)gc_malloc(len + 1, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0); - memcpy(p, x.ptr, xlen); - memcpy(p + xlen, y.ptr, ylen); - p[len] = 0; - return p[0 .. x.length + y.length]; -} - - -/** - * - */ -extern (C) byte[] _d_arraycatnT(TypeInfo ti, uint n, ...) -{ void* a; - size_t length; - byte[]* p; - uint i; - byte[] b; - auto size = ti.next.tsize(); // array element size - - p = cast(byte[]*)(&n + 1); - - for (i = 0; i < n; i++) - { - b = *p++; - length += b.length; - } - if (!length) - return null; - - a = gc_malloc(length * size, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0); - p = cast(byte[]*)(&n + 1); - - uint j = 0; - for (i = 0; i < n; i++) - { - b = *p++; - if (b.length) - { - memcpy(a + j, b.ptr, b.length * size); - j += b.length * size; - } - } - - byte[] result; - *cast(int *)&result = length; // jam length - (cast(void **)&result)[1] = a; // jam ptr - return result; -} - - -/** - * - */ -extern (C) void* _d_arrayliteralT(TypeInfo ti, size_t length, ...) -{ - auto sizeelem = ti.next.tsize(); // array element size - void* result; - - debug(PRINTF) printf("_d_arrayliteralT(sizeelem = %d, length = %d)\n", sizeelem, length); - if (length == 0 || sizeelem == 0) - result = null; - else - { - result = gc_malloc(length * sizeelem, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0); - - va_list q; - va_start!(size_t)(q, length); - - size_t stacksize = (sizeelem + int.sizeof - 1) & ~(int.sizeof - 1); - - if (stacksize == sizeelem) - { - memcpy(result, q, length * sizeelem); - } - else - { - for (size_t i = 0; i < length; i++) - { - memcpy(result + i * sizeelem, q, sizeelem); - q += stacksize; - } - } - - va_end(q); - } - return result; -} - - -/** - * Support for array.dup property. - */ -struct Array2 -{ - size_t length; - void* ptr; -} - - -/** - * - */ -extern (C) long _adDupT(TypeInfo ti, Array2 a) -out (result) -{ - auto sizeelem = ti.next.tsize(); // array element size - assert(memcmp((*cast(Array2*)&result).ptr, a.ptr, a.length * sizeelem) == 0); -} -body -{ - Array2 r; - - if (a.length) - { - auto sizeelem = ti.next.tsize(); // array element size - auto size = a.length * sizeelem; - r.ptr = gc_malloc(size, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0); - r.length = a.length; - memcpy(r.ptr, a.ptr, size); - } - return *cast(long*)(&r); -} - - -unittest -{ - int[] a; - int[] b; - int i; - - a = new int[3]; - a[0] = 1; a[1] = 2; a[2] = 3; - b = a.dup; - assert(b.length == 3); - for (i = 0; i < 3; i++) - assert(b[i] == i + 1); -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/llmath.d --- a/druntime/src/compiler/ldc/llmath.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,531 +0,0 @@ -/** - * Support for 64-bit longs. - * - * Copyright: Copyright Digital Mars 1993 - 2009. - * License: Boost License 1.0. - * Authors: Walter Bright, Sean Kelly - * - * Copyright Digital Mars 2000 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -#include - -#if __cplusplus -extern "C" { -#endif - -struct ClassInfo; -struct Vtbl; - -typedef struct Vtbl -{ - size_t len; - void **vptr; -} Vtbl; - -typedef struct Interface -{ - struct ClassInfo *classinfo; - struct Vtbl vtbl; - int offset; -} Interface; - -typedef struct Object -{ - void **vptr; - void *monitor; -} Object; - -typedef struct ClassInfo -{ - Object object; - - size_t initlen; - void *init; - - size_t namelen; - char *name; - - Vtbl vtbl; - - size_t interfacelen; - Interface *interfaces; - - struct ClassInfo *baseClass; - - void *destructor; - void *invariant; - - int flags; -} ClassInfo; - -typedef struct Throwable -{ - Object object; - - size_t msglen; - char* msg; - - size_t filelen; - char* file; - - size_t line; - - struct Interface *info; - struct Throwable *next; -} Throwable; - -typedef struct Array -{ - size_t length; - void *ptr; -} Array; - -typedef struct Delegate -{ - void *thisptr; - void (*funcptr)(); -} Delegate; - -void _d_monitorenter(Object *h); -void _d_monitorexit(Object *h); - -int _d_isbaseof(ClassInfo *b, ClassInfo *c); -Object *_d_dynamic_cast(Object *o, ClassInfo *ci); - -Object * _d_newclass(ClassInfo *ci); -void _d_delclass(Object **p); - -void _d_OutOfMemory(); - -#if __cplusplus -} -#endif diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/memory.d --- a/druntime/src/compiler/ldc/memory.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,213 +0,0 @@ -/** - * This module exposes functionality for inspecting and manipulating memory. - * - * Copyright: Copyright Digital Mars 2000 - 2009. - * License: Boost License 1.0. - * Authors: Walter Bright - * - * Copyright Digital Mars 2004 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module rt.memset; - -extern (C) -{ - // Functions from the C library. - void *memcpy(void *, void *, size_t); -} - -extern (C): - -short *_memset16(short *p, short value, size_t count) -{ - short *pstart = p; - short *ptop; - - for (ptop = &p[count]; p < ptop; p++) - *p = value; - return pstart; -} - -int *_memset32(int *p, int value, size_t count) -{ -version (X86) -{ - asm - { - mov EDI,p ; - mov EAX,value ; - mov ECX,count ; - mov EDX,EDI ; - rep ; - stosd ; - mov EAX,EDX ; - } -} -else -{ - int *pstart = p; - int *ptop; - - for (ptop = &p[count]; p < ptop; p++) - *p = value; - return pstart; -} -} - -long *_memset64(long *p, long value, size_t count) -{ - long *pstart = p; - long *ptop; - - for (ptop = &p[count]; p < ptop; p++) - *p = value; - return pstart; -} - -cdouble *_memset128(cdouble *p, cdouble value, size_t count) -{ - cdouble *pstart = p; - cdouble *ptop; - - for (ptop = &p[count]; p < ptop; p++) - *p = value; - return pstart; -} - -real *_memset80(real *p, real value, size_t count) -{ - real *pstart = p; - real *ptop; - - for (ptop = &p[count]; p < ptop; p++) - *p = value; - return pstart; -} - -creal *_memset160(creal *p, creal value, size_t count) -{ - creal *pstart = p; - creal *ptop; - - for (ptop = &p[count]; p < ptop; p++) - *p = value; - return pstart; -} - -void *_memsetn(void *p, void *value, int count, size_t sizelem) -{ void *pstart = p; - int i; - - for (i = 0; i < count; i++) - { - memcpy(p, value, sizelem); - p = cast(void *)(cast(char *)p + sizelem); - } - return pstart; -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/minit.asm --- a/druntime/src/compiler/ldc/minit.asm Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,85 +0,0 @@ -;_ minit.asm -; Module initialization support. -; -; Copyright: Copyright Digital Mars 2000 - 2009. -; License: Boost License 1.0. - * Authors: Walter Bright, Sean Kelly - * - * Copyright Digital Mars 2000 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -#include -#include -#include - -#if _WIN32 -#elif linux || __APPLE__ -#define USE_PTHREADS 1 -#else -#endif - -#if _WIN32 -#include -#endif - -#if USE_PTHREADS -#include -#endif - -#include "mars.h" - -// This is what the monitor reference in Object points to -typedef struct Monitor -{ - void* impl; // for user-level monitors - Array devt; // for internal monitors - -#if _WIN32 - CRITICAL_SECTION mon; -#endif - -#if USE_PTHREADS - pthread_mutex_t mon; -#endif -} Monitor; - -#define MONPTR(h) (&((Monitor *)(h)->monitor)->mon) - -static volatile int inited; - -/* =============================== Win32 ============================ */ - -#if _WIN32 - -static CRITICAL_SECTION _monitor_critsec; - -void _STI_monitor_staticctor() -{ - if (!inited) - { InitializeCriticalSection(&_monitor_critsec); - inited = 1; - } -} - -void _STD_monitor_staticdtor() -{ - if (inited) - { inited = 0; - DeleteCriticalSection(&_monitor_critsec); - } -} - -void _d_monitor_create(Object *h) -{ - /* - * NOTE: Assume this is only called when h->monitor is null prior to the - * call. However, please note that another thread may call this function - * at the same time, so we can not assert this here. Instead, try and - * create a lock, and if one already exists then forget about it. - */ - - //printf("+_d_monitor_create(%p)\n", h); - assert(h); - Monitor *cs = NULL; - EnterCriticalSection(&_monitor_critsec); - if (!h->monitor) - { - cs = (Monitor *)calloc(sizeof(Monitor), 1); - assert(cs); - InitializeCriticalSection(&cs->mon); - h->monitor = (void *)cs; - cs = NULL; - } - LeaveCriticalSection(&_monitor_critsec); - if (cs) - free(cs); - //printf("-_d_monitor_create(%p)\n", h); -} - -void _d_monitor_destroy(Object *h) -{ - //printf("+_d_monitor_destroy(%p)\n", h); - assert(h && h->monitor && !(((Monitor*)h->monitor)->impl)); - DeleteCriticalSection(MONPTR(h)); - free((void *)h->monitor); - h->monitor = NULL; - //printf("-_d_monitor_destroy(%p)\n", h); -} - -int _d_monitor_lock(Object *h) -{ - //printf("+_d_monitor_acquire(%p)\n", h); - assert(h && h->monitor && !(((Monitor*)h->monitor)->impl)); - EnterCriticalSection(MONPTR(h)); - //printf("-_d_monitor_acquire(%p)\n", h); -} - -void _d_monitor_unlock(Object *h) -{ - //printf("+_d_monitor_release(%p)\n", h); - assert(h && h->monitor && !(((Monitor*)h->monitor)->impl)); - LeaveCriticalSection(MONPTR(h)); - //printf("-_d_monitor_release(%p)\n", h); -} - -#endif - -/* =============================== linux ============================ */ - -#if USE_PTHREADS - -#ifndef PTHREAD_MUTEX_RECURSIVE -# define PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP -#endif - -// Includes attribute fixes from David Friedman's GDC port - -static pthread_mutex_t _monitor_critsec; -static pthread_mutexattr_t _monitors_attr; - -void _STI_monitor_staticctor() -{ - if (!inited) - { - pthread_mutexattr_init(&_monitors_attr); - pthread_mutexattr_settype(&_monitors_attr, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(&_monitor_critsec, 0); - inited = 1; - } -} - -void _STD_monitor_staticdtor() -{ - if (inited) - { inited = 0; - pthread_mutex_destroy(&_monitor_critsec); - pthread_mutexattr_destroy(&_monitors_attr); - } -} - -void _d_monitor_create(Object *h) -{ - /* - * NOTE: Assume this is only called when h->monitor is null prior to the - * call. However, please note that another thread may call this function - * at the same time, so we can not assert this here. Instead, try and - * create a lock, and if one already exists then forget about it. - */ - - //printf("+_d_monitor_create(%p)\n", h); - assert(h); - Monitor *cs = NULL; - pthread_mutex_lock(&_monitor_critsec); - if (!h->monitor) - { - cs = (Monitor *)calloc(sizeof(Monitor), 1); - assert(cs); - pthread_mutex_init(&cs->mon, & _monitors_attr); - h->monitor = (void *)cs; - cs = NULL; - } - pthread_mutex_unlock(&_monitor_critsec); - if (cs) - free(cs); - //printf("-_d_monitor_create(%p)\n", h); -} - -void _d_monitor_destroy(Object *h) -{ - //printf("+_d_monitor_destroy(%p)\n", h); - assert(h && h->monitor && !(((Monitor*)h->monitor)->impl)); - pthread_mutex_destroy(MONPTR(h)); - free((void *)h->monitor); - h->monitor = NULL; - //printf("-_d_monitor_destroy(%p)\n", h); -} - -int _d_monitor_lock(Object *h) -{ - //printf("+_d_monitor_acquire(%p)\n", h); - assert(h && h->monitor && !(((Monitor*)h->monitor)->impl)); - pthread_mutex_lock(MONPTR(h)); - //printf("-_d_monitor_acquire(%p)\n", h); -} - -void _d_monitor_unlock(Object *h) -{ - //printf("+_d_monitor_release(%p)\n", h); - assert(h && h->monitor && !(((Monitor*)h->monitor)->impl)); - pthread_mutex_unlock(MONPTR(h)); - //printf("-_d_monitor_release(%p)\n", h); -} - -#endif diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/obj.d --- a/druntime/src/compiler/ldc/obj.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -/** - * Containts object comparator functions called by generated code. - * - * Copyright: Copyright Digital Mars 2002 - 2009. - * License: thresh) // if more than _maxspan elements - { - //swap middle, base - ti.swap((cast(uint)(limit - base) >> 1) - - (((cast(uint)(limit - base) >> 1)) % width) + base, base); - - i = base + width; // i scans from left to right - j = limit - width; // j scans from right to left - - if (ti.compare(i, j) > 0) // Sedgewick's - ti.swap(i, j); // three-element sort - if (ti.compare(base, j) > 0) // sets things up - ti.swap(base, j); // so that - if (ti.compare(i, base) > 0) // *i <= *base <= *j - ti.swap(i, base); // *base is the pivot element - - while (1) - { - do // move i right until *i >= pivot - i += width; - while (ti.compare(i, base) < 0); - do // move j left until *j <= pivot - j -= width; - while (ti.compare(j, base) > 0); - if (i > j) // break loop if pointers crossed - break; - ti.swap(i, j); // else swap elements, keep scanning - } - ti.swap(base, j); // move pivot into correct place - if (j - base > limit - i) // if left subarray is larger... - { - sp[0] = base; // stack left subarray base - sp[1] = j; // and limit - base = i; // sort the right subarray - } - else // else right subarray is larger - { - sp[0] = i; // stack right subarray base - sp[1] = limit; // and limit - limit = j; // sort the left subarray - } - sp += 2; // increment stack pointer - assert(sp < cast(byte**)stack + stack.length); - } - - // Insertion sort on remaining subarray - i = base + width; - while (i < limit) - { - j = i; - while (j > base && ti.compare(j - width, j) > 0) - { - ti.swap(j - width, j); - j -= width; - } - i += width; - } - - if (sp > stack.ptr) // if any entries on stack... - { - sp -= 2; // pop the base and limit - base = sp[0]; - limit = sp[1]; - } - else // else stack empty, all done - return *cast(long*)(&a); - } - assert(0); -} - - -unittest -{ - debug(qsort) printf("array.sort.unittest()\n"); - - int a[] = new int[10]; - - a[0] = 23; - a[1] = 1; - a[2] = 64; - a[3] = 5; - a[4] = 6; - a[5] = 5; - a[6] = 17; - a[7] = 3; - a[8] = 0; - a[9] = -1; - - a.sort; - - for (int i = 0; i < a.length - 1; i++) - { - //printf("i = %d", i); - //printf(" %d %d\n", a[i], a[i + 1]); - assert(a[i] <= a[i + 1]); - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/qsort2.d --- a/druntime/src/compiler/ldc/qsort2.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -/** - * This is a public domain version of qsort.d. All it does is call C's - * qsort(), but runs a little slower since it needs to synchronize a global - * variable. - * - * Copyright: Copyright Digital Mars 2000 - 2009. - * License: = 0); - assert(ca.length >= 0); - - // Make sure table[] is sorted correctly - int j; - - for (j = 1; j < table.length; j++) - { - int len1 = table[j - 1].length; - int len2 = table[j].length; - - assert(len1 <= len2); - if (len1 == len2) - { - int ci; - - ci = memcmp(table[j - 1].ptr, table[j].ptr, len1); - assert(ci < 0); // ci==0 means a duplicate - } - } -} -out (result) -{ - int i; - int cj; - - //printf("out _d_switch_string()\n"); - if (result == -1) - { - // Not found - for (i = 0; i < table.length; i++) - { - if (table[i].length == ca.length) - { cj = memcmp(table[i].ptr, ca.ptr, ca.length); - assert(cj != 0); - } - } - } - else - { - assert(0 <= result && result < table.length); - for (i = 0; 1; i++) - { - assert(i < table.length); - if (table[i].length == ca.length) - { - cj = memcmp(table[i].ptr, ca.ptr, ca.length); - if (cj == 0) - { - assert(i == result); - break; - } - } - } - } -} -body -{ - //printf("body _d_switch_string(%.*s)\n", ca); - int low; - int high; - int mid; - int c; - char[] pca; - - low = 0; - high = table.length; - - version (none) - { - // Print table - printf("ca[] = '%s'\n", cast(char *)ca); - for (mid = 0; mid < high; mid++) - { - pca = table[mid]; - printf("table[%d] = %d, '%.*s'\n", mid, pca.length, pca); - } - } - if (high && - ca.length >= table[0].length && - ca.length <= table[high - 1].length) - { - // Looking for 0 length string, which would only be at the beginning - if (ca.length == 0) - return 0; - - char c1 = ca[0]; - - // Do binary search - while (low < high) - { - mid = (low + high) >> 1; - pca = table[mid]; - c = ca.length - pca.length; - if (c == 0) - { - c = cast(ubyte)c1 - cast(ubyte)pca[0]; - if (c == 0) - { - c = memcmp(ca.ptr, pca.ptr, ca.length); - if (c == 0) - { //printf("found %d\n", mid); - return mid; - } - } - } - if (c < 0) - { - high = mid; - } - else - { - low = mid + 1; - } - } - } - - //printf("not found\n"); - return -1; // not found -} - -unittest -{ - switch (cast(char []) "c") - { - case "coo": - default: - break; - } -} - -/********************************** - * Same thing, but for wide chars. - */ - -int _d_switch_ustring(wchar[][] table, wchar[] ca) -in -{ - //printf("in _d_switch_ustring()\n"); - assert(table.length >= 0); - assert(ca.length >= 0); - - // Make sure table[] is sorted correctly - int j; - - for (j = 1; j < table.length; j++) - { - int len1 = table[j - 1].length; - int len2 = table[j].length; - - assert(len1 <= len2); - if (len1 == len2) - { - int c; - - c = memcmp(table[j - 1].ptr, table[j].ptr, len1 * wchar.sizeof); - assert(c < 0); // c==0 means a duplicate - } - } -} -out (result) -{ - int i; - int c; - - //printf("out _d_switch_string()\n"); - if (result == -1) - { - // Not found - for (i = 0; i < table.length; i++) - { - if (table[i].length == ca.length) - { c = memcmp(table[i].ptr, ca.ptr, ca.length * wchar.sizeof); - assert(c != 0); - } - } - } - else - { - assert(0 <= result && result < table.length); - for (i = 0; 1; i++) - { - assert(i < table.length); - if (table[i].length == ca.length) - { - c = memcmp(table[i].ptr, ca.ptr, ca.length * wchar.sizeof); - if (c == 0) - { - assert(i == result); - break; - } - } - } - } -} -body -{ - //printf("body _d_switch_ustring()\n"); - int low; - int high; - int mid; - int c; - wchar[] pca; - - low = 0; - high = table.length; - -/* - // Print table - wprintf("ca[] = '%.*s'\n", ca); - for (mid = 0; mid < high; mid++) - { - pca = table[mid]; - wprintf("table[%d] = %d, '%.*s'\n", mid, pca.length, pca); - } -*/ - - // Do binary search - while (low < high) - { - mid = (low + high) >> 1; - pca = table[mid]; - c = ca.length - pca.length; - if (c == 0) - { - c = memcmp(ca.ptr, pca.ptr, ca.length * wchar.sizeof); - if (c == 0) - { //printf("found %d\n", mid); - return mid; - } - } - if (c < 0) - { - high = mid; - } - else - { - low = mid + 1; - } - } - //printf("not found\n"); - return -1; // not found -} - - -unittest -{ - switch (cast(wchar []) "c") - { - case "coo": - default: - break; - } -} - - -/********************************** - * Same thing, but for wide chars. - */ - -int _d_switch_dstring(dchar[][] table, dchar[] ca) -in -{ - //printf("in _d_switch_dstring()\n"); - assert(table.length >= 0); - assert(ca.length >= 0); - - // Make sure table[] is sorted correctly - int j; - - for (j = 1; j < table.length; j++) - { - int len1 = table[j - 1].length; - int len2 = table[j].length; - - assert(len1 <= len2); - if (len1 == len2) - { - int c; - - c = memcmp(table[j - 1].ptr, table[j].ptr, len1 * dchar.sizeof); - assert(c < 0); // c==0 means a duplicate - } - } -} -out (result) -{ - int i; - int c; - - //printf("out _d_switch_string()\n"); - if (result == -1) - { - // Not found - for (i = 0; i < table.length; i++) - { - if (table[i].length == ca.length) - { c = memcmp(table[i].ptr, ca.ptr, ca.length * dchar.sizeof); - assert(c != 0); - } - } - } - else - { - assert(0 <= result && result < table.length); - for (i = 0; 1; i++) - { - assert(i < table.length); - if (table[i].length == ca.length) - { - c = memcmp(table[i].ptr, ca.ptr, ca.length * dchar.sizeof); - if (c == 0) - { - assert(i == result); - break; - } - } - } - } -} -body -{ - //printf("body _d_switch_ustring()\n"); - int low; - int high; - int mid; - int c; - dchar[] pca; - - low = 0; - high = table.length; - -/* - // Print table - wprintf("ca[] = '%.*s'\n", ca); - for (mid = 0; mid < high; mid++) - { - pca = table[mid]; - wprintf("table[%d] = %d, '%.*s'\n", mid, pca.length, pca); - } -*/ - - // Do binary search - while (low < high) - { - mid = (low + high) >> 1; - pca = table[mid]; - c = ca.length - pca.length; - if (c == 0) - { - c = memcmp(ca.ptr, pca.ptr, ca.length * dchar.sizeof); - if (c == 0) - { //printf("found %d\n", mid); - return mid; - } - } - if (c < 0) - { - high = mid; - } - else - { - low = mid + 1; - } - } - //printf("not found\n"); - return -1; // not found -} - - -unittest -{ - switch (cast(dchar []) "c") - { - case "coo": - default: - break; - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/tls.S --- a/druntime/src/compiler/ldc/tls.S Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -/** - * Contains support code for thread-local storage. - * - * Copyright: Copyright Digital Mars 2008 - 2009. - * License: = count) - { uint u2; - uint c2; - - u2 = (u + 1 < num) ? u + 1 : u; - c2 = base[u2].count; - if (c2 < count) - c2 = count; - trace_place(base[u].sym,c2); - } - else - break; - } - - // Clean up - trace_free(base); - } -} - -///////////////////////////////////// -// Initialize and terminate. - -static this() -{ - trace_init(); -} - -static ~this() -{ - trace_term(); -} - -/////////////////////////////////// -// Report results. -// Also compute nsymbols. - -static void trace_report(Symbol* s) -{ SymPair* sp; - uint count; - - //printf("trace_report()\n"); - while (s) - { nsymbols++; - if (s.Sl) - trace_report(s.Sl); - fprintf(fplog,"------------------\n"); - count = 0; - for (sp = s.Sfanin; sp; sp = sp.next) - { - fprintf(fplog,"\t%5d\t%.*s\n", sp.count, sp.sym.Sident); - count += sp.count; - } - fprintf(fplog,"%.*s\t%u\t%lld\t%lld\n",s.Sident,count,s.totaltime,s.functime); - for (sp = s.Sfanout; sp; sp = sp.next) - { - fprintf(fplog,"\t%5d\t%.*s\n",sp.count,sp.sym.Sident); - } - s = s.Sr; - } -} - -//////////////////////////////////// -// Allocate and fill array of symbols. - -static void trace_array(Symbol *s) -{ - __gshared uint u; - - if (!psymbols) - { u = 0; - psymbols = cast(Symbol **)trace_malloc((Symbol *).sizeof * nsymbols); - } - while (s) - { - psymbols[u++] = s; - trace_array(s.Sl); - s = s.Sr; - } -} - - -////////////////////////////////////// -// Qsort() comparison routine for array of pointers to Symbol's. - -static int symbol_cmp(in void* e1, in void* e2) -{ Symbol** ps1; - Symbol** ps2; - timer_t diff; - - ps1 = cast(Symbol **)e1; - ps2 = cast(Symbol **)e2; - - diff = (*ps2).functime - (*ps1).functime; - return (diff == 0) ? 0 : ((diff > 0) ? 1 : -1); -} - - -/////////////////////////////////// -// Report function timings - -static void trace_times(Symbol* root) -{ uint u; - timer_t freq; - - // Sort array - qsort(psymbols, nsymbols, (Symbol *).sizeof, &symbol_cmp); - - // Print array - QueryPerformanceFrequency(&freq); - fprintf(fplog,"\n======== Timer Is %lld Ticks/Sec, Times are in Microsecs ========\n\n",freq); - fprintf(fplog," Num Tree Func Per\n"); - fprintf(fplog," Calls Time Time Call\n\n"); - for (u = 0; u < nsymbols; u++) - { Symbol* s = psymbols[u]; - timer_t tl,tr; - timer_t fl,fr; - timer_t pl,pr; - timer_t percall; - SymPair* sp; - uint calls; - char[] id; - - version (Windows) - { - char* p = (s.Sident ~ '\0').ptr; - p = unmangle_ident(p); - if (p) - id = p[0 .. strlen(p)]; - } - if (!id) - id = s.Sident; - calls = 0; - for (sp = s.Sfanin; sp; sp = sp.next) - calls += sp.count; - if (calls == 0) - calls = 1; - -version (all) -{ - tl = (s.totaltime * 1000000) / freq; - fl = (s.functime * 1000000) / freq; - percall = s.functime / calls; - pl = (s.functime * 1000000) / calls / freq; - - fprintf(fplog,"%7d%12lld%12lld%12lld %.*s\n", - calls,tl,fl,pl,id); -} -else -{ - tl = s.totaltime / freq; - tr = ((s.totaltime - tl * freq) * 10000000) / freq; - - fl = s.functime / freq; - fr = ((s.functime - fl * freq) * 10000000) / freq; - - percall = s.functime / calls; - pl = percall / freq; - pr = ((percall - pl * freq) * 10000000) / freq; - - fprintf(fplog,"%7d\t%3lld.%07lld\t%3lld.%07lld\t%3lld.%07lld\t%.*s\n", - calls,tl,tr,fl,fr,pl,pr,id); -} - if (id !is s.Sident) - free(id.ptr); - } -} - - -/////////////////////////////////// -// Initialize. - -static void trace_init() -{ - if (!trace_inited) - { - trace_inited = 1; - - { // See if we can determine the overhead. - uint u; - timer_t starttime; - timer_t endtime; - Stack *st; - - st = trace_tos; - trace_tos = null; - QueryPerformanceCounter(&starttime); - for (u = 0; u < 100; u++) - { - asm - { - call _trace_pro_n ; - db 0 ; - call _trace_epi_n ; - } - } - QueryPerformanceCounter(&endtime); - trace_ohd = (endtime - starttime) / u; - //printf("trace_ohd = %lld\n",trace_ohd); - if (trace_ohd > 0) - trace_ohd--; // round down - trace_tos = st; - } - } -} - -///////////////////////////////// -// Terminate. - -void trace_term() -{ - //printf("trace_term()\n"); - if (trace_inited == 1) - { Stack *n; - - trace_inited = 2; - - // Free remainder of the stack - while (trace_tos) - { - n = trace_tos.prev; - stack_free(trace_tos); - trace_tos = n; - } - - while (stack_freelist) - { - n = stack_freelist.prev; - stack_free(stack_freelist); - stack_freelist = n; - } - - // Merge in data from any existing file - trace_merge(); - - // Report results - fplog = fopen(trace_logfilename.ptr, "w"); - if (fplog) - { nsymbols = 0; - trace_report(root); - trace_array(root); - trace_times(root); - fclose(fplog); - } - - // Output function link order - fpdef = fopen(trace_deffilename.ptr,"w"); - if (fpdef) - { fprintf(fpdef,"\nFUNCTIONS\n"); - trace_order(root); - fclose(fpdef); - } - - trace_free(psymbols); - psymbols = null; - } -} - -///////////////////////////////// -// Our storage allocator. - -static void *trace_malloc(size_t nbytes) -{ void *p; - - p = malloc(nbytes); - if (!p) - exit(EXIT_FAILURE); - return p; -} - -static void trace_free(void *p) -{ - free(p); -} - -////////////////////////////////////////////// -// - -static Symbol* trace_addsym(char[] id) -{ - Symbol** parent; - Symbol* rover; - Symbol* s; - int cmp; - char c; - - //printf("trace_addsym('%s',%d)\n",p,len); - parent = &root; - rover = *parent; - while (rover !is null) // while we haven't run out of tree - { - cmp = dstrcmp(id, rover.Sident); - if (cmp == 0) - { - return rover; - } - parent = (cmp < 0) ? /* if we go down left side */ - &(rover.Sl) : /* then get left child */ - &(rover.Sr); /* else get right child */ - rover = *parent; /* get child */ - } - /* not in table, so insert into table */ - s = cast(Symbol *)trace_malloc(Symbol.sizeof); - memset(s,0,Symbol.sizeof); - s.Sident = id; - *parent = s; // link new symbol into tree - return s; -} - -/*********************************** - * Add symbol s with count to SymPair list. - */ - -static void trace_sympair_add(SymPair** psp, Symbol* s, uint count) -{ SymPair* sp; - - for (; 1; psp = &sp.next) - { - sp = *psp; - if (!sp) - { - sp = cast(SymPair *)trace_malloc(SymPair.sizeof); - sp.sym = s; - sp.count = 0; - sp.next = null; - *psp = sp; - break; - } - else if (sp.sym == s) - { - break; - } - } - sp.count += count; -} - -////////////////////////////////////////////// -// - -static void trace_pro(char[] id) -{ - Stack* n; - Symbol* s; - timer_t starttime; - timer_t t; - - QueryPerformanceCounter(&starttime); - if (id.length == 0) - return; - if (!trace_inited) - trace_init(); // initialize package - n = stack_malloc(); - n.prev = trace_tos; - trace_tos = n; - s = trace_addsym(id); - trace_tos.sym = s; - if (trace_tos.prev) - { - Symbol* prev; - int i; - - // Accumulate Sfanout and Sfanin - prev = trace_tos.prev.sym; - trace_sympair_add(&prev.Sfanout,s,1); - trace_sympair_add(&s.Sfanin,prev,1); - } - QueryPerformanceCounter(&t); - trace_tos.starttime = starttime; - trace_tos.ohd = trace_ohd + t - starttime; - trace_tos.subtime = 0; - //printf("trace_tos.ohd=%lld, trace_ohd=%lld + t=%lld - starttime=%lld\n", - // trace_tos.ohd,trace_ohd,t,starttime); -} - -///////////////////////////////////////// -// - -static void trace_epi() -{ Stack* n; - timer_t endtime; - timer_t t; - timer_t ohd; - - //printf("trace_epi()\n"); - if (trace_tos) - { - timer_t starttime; - timer_t totaltime; - - QueryPerformanceCounter(&endtime); - starttime = trace_tos.starttime; - totaltime = endtime - starttime - trace_tos.ohd; - if (totaltime < 0) - { //printf("endtime=%lld - starttime=%lld - trace_tos.ohd=%lld < 0\n", - // endtime,starttime,trace_tos.ohd); - totaltime = 0; // round off error, just make it 0 - } - - // totaltime is time spent in this function + all time spent in - // subfunctions - bookkeeping overhead. - trace_tos.sym.totaltime += totaltime; - - //if (totaltime < trace_tos.subtime) - //printf("totaltime=%lld < trace_tos.subtime=%lld\n",totaltime,trace_tos.subtime); - trace_tos.sym.functime += totaltime - trace_tos.subtime; - ohd = trace_tos.ohd; - n = trace_tos.prev; - stack_free(trace_tos); - trace_tos = n; - if (n) - { QueryPerformanceCounter(&t); - n.ohd += ohd + t - endtime; - n.subtime += totaltime; - //printf("n.ohd = %lld\n",n.ohd); - } - } -} - - -////////////////////////// FILE INTERFACE ///////////////////////// - -///////////////////////////////////// -// Read line from file fp. -// Returns: -// trace_malloc'd line buffer -// null if end of file - -static char* trace_readline(FILE* fp) -{ int c; - int dim; - int i; - char *buf; - - //printf("trace_readline(%p)\n", fp); - i = 0; - dim = 0; - buf = null; - while (1) - { - if (i == dim) - { char *p; - - dim += 80; - p = cast(char *)trace_malloc(dim); - memcpy(p,buf,i); - trace_free(buf); - buf = p; - } - c = fgetc(fp); - switch (c) - { - case EOF: - if (i == 0) - { trace_free(buf); - return null; - } - case '\n': - goto L1; - default: - break; - } - buf[i] = cast(char)c; - i++; - } -L1: - buf[i] = 0; - //printf("line '%s'\n",buf); - return buf; -} - -////////////////////////////////////// -// Skip space - -static char *skipspace(char *p) -{ - while (isspace(*p)) - p++; - return p; -} - -//////////////////////////////////////////////////////// -// Merge in profiling data from existing file. - -static void trace_merge() -{ FILE *fp; - char *buf; - char *p; - uint count; - Symbol *s; - SymPair *sfanin; - SymPair **psp; - - if (trace_logfilename && (fp = fopen(trace_logfilename.ptr,"r")) !is null) - { - buf = null; - sfanin = null; - psp = &sfanin; - while (1) - { - trace_free(buf); - buf = trace_readline(fp); - if (!buf) - break; - switch (*buf) - { - case '=': // ignore rest of file - trace_free(buf); - goto L1; - case ' ': - case '\t': // fan in or fan out line - count = strtoul(buf,&p,10); - if (p == buf) // if invalid conversion - continue; - p = skipspace(p); - if (!*p) - continue; - s = trace_addsym(p[0 .. strlen(p)]); - trace_sympair_add(psp,s,count); - break; - default: - if (!isalpha(*buf)) - { - if (!sfanin) - psp = &sfanin; - continue; // regard unrecognized line as separator - } - case '?': - case '_': - case '$': - case '@': - p = buf; - while (isgraph(*p)) - p++; - *p = 0; - //printf("trace_addsym('%s')\n",buf); - s = trace_addsym(buf[0 .. strlen(buf)]); - if (s.Sfanin) - { SymPair *sp; - - for (; sfanin; sfanin = sp) - { - trace_sympair_add(&s.Sfanin,sfanin.sym,sfanin.count); - sp = sfanin.next; - trace_free(sfanin); - } - } - else - { s.Sfanin = sfanin; - } - sfanin = null; - psp = &s.Sfanout; - - { timer_t t; - - p++; - count = strtoul(p,&p,10); - t = cast(long)strtoull(p,&p,10); - s.totaltime += t; - t = cast(long)strtoull(p,&p,10); - s.functime += t; - } - break; - } - } - L1: - fclose(fp); - } -} - -////////////////////////// COMPILER INTERFACE ///////////////////// - -///////////////////////////////////////////// -// Function called by trace code in function prolog. - -void _trace_pro_n() -{ - /* Length of string is either: - * db length - * ascii string - * or: - * db 0x0FF - * db 0 - * dw length - * ascii string - */ - - version (OSX) - { // 16 byte align stack - asm - { naked ; - pushad ; - mov ECX,8*4[ESP] ; - xor EAX,EAX ; - mov AL,[ECX] ; - cmp AL,0xFF ; - jne L1 ; - cmp byte ptr 1[ECX],0 ; - jne L1 ; - mov AX,2[ECX] ; - add 8*4[ESP],3 ; - add ECX,3 ; - L1: inc EAX ; - inc ECX ; - add 8*4[ESP],EAX ; - dec EAX ; - sub ESP,4 ; - push ECX ; - push EAX ; - call trace_pro ; - add ESP,12 ; - popad ; - ret ; - } - } - else - { - asm - { naked ; - pushad ; - mov ECX,8*4[ESP] ; - xor EAX,EAX ; - mov AL,[ECX] ; - cmp AL,0xFF ; - jne L1 ; - cmp byte ptr 1[ECX],0 ; - jne L1 ; - mov AX,2[ECX] ; - add 8*4[ESP],3 ; - add ECX,3 ; - L1: inc EAX ; - inc ECX ; - add 8*4[ESP],EAX ; - dec EAX ; - push ECX ; - push EAX ; - call trace_pro ; - add ESP,8 ; - popad ; - ret ; - } - } -} - -///////////////////////////////////////////// -// Function called by trace code in function epilog. - - -void _trace_epi_n() -{ - version (OSX) - { // 16 byte align stack - asm - { naked ; - pushad ; - sub ESP,12 ; - } - trace_epi(); - asm - { - add ESP,12 ; - popad ; - ret ; - } - } - else - { - asm - { naked ; - pushad ; - } - trace_epi(); - asm - { - popad ; - ret ; - } - } -} - - -version (Windows) -{ - extern (Windows) - { - export int QueryPerformanceCounter(timer_t *); - export int QueryPerformanceFrequency(timer_t *); - } -} -else version (X86) -{ - extern (D) - { - void QueryPerformanceCounter(timer_t* ctr) - { - asm - { naked ; - mov ECX,EAX ; - rdtsc ; - mov [ECX],EAX ; - mov 4[ECX],EDX ; - ret ; - } - } - - void QueryPerformanceFrequency(timer_t* freq) - { - *freq = 3579545; - } - } -} -else -{ - static assert(0); -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/typeinfo/ti_AC.d --- a/druntime/src/compiler/ldc/typeinfo/ti_AC.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,107 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: 0) - c = 1; - return c; - } - - override size_t tsize() - { - return (Object[]).sizeof; - } - - override uint flags() - { - return 1; - } - - override TypeInfo next() - { - return typeid(Object); - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/typeinfo/ti_Acdouble.d --- a/druntime/src/compiler/ldc/typeinfo/ti_Acdouble.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,94 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: s2.length) - return 1; - return 0; - } - - override size_t tsize() - { - return (cdouble[]).sizeof; - } - - override uint flags() - { - return 1; - } - - override TypeInfo next() - { - return typeid(cdouble); - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/typeinfo/ti_Acfloat.d --- a/druntime/src/compiler/ldc/typeinfo/ti_Acfloat.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,92 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: s2.length) - return 1; - return 0; - } - - override size_t tsize() - { - return (cfloat[]).sizeof; - } - - override uint flags() - { - return 1; - } - - override TypeInfo next() - { - return typeid(cfloat); - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/typeinfo/ti_Acreal.d --- a/druntime/src/compiler/ldc/typeinfo/ti_Acreal.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,95 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: s2.length) - return 1; - return 0; - } - - override size_t tsize() - { - return (creal[]).sizeof; - } - - override uint flags() - { - return 1; - } - - override TypeInfo next() - { - return typeid(creal); - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/typeinfo/ti_Adouble.d --- a/druntime/src/compiler/ldc/typeinfo/ti_Adouble.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,104 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: s2.length) - return 1; - return 0; - } - - override size_t tsize() - { - return (double[]).sizeof; - } - - override uint flags() - { - return 1; - } - - override TypeInfo next() - { - return typeid(double); - } -} - -// idouble[] - -class TypeInfo_Ap : TypeInfo_Ad -{ - override string toString() { return "idouble[]"; } - - override TypeInfo next() - { - return typeid(idouble); - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/typeinfo/ti_Afloat.d --- a/druntime/src/compiler/ldc/typeinfo/ti_Afloat.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: s2.length) - return 1; - return 0; - } - - override size_t tsize() - { - return (float[]).sizeof; - } - - override uint flags() - { - return 1; - } - - override TypeInfo next() - { - return typeid(float); - } -} - -// ifloat[] - -class TypeInfo_Ao : TypeInfo_Af -{ - override string toString() { return "ifloat[]"; } - - override TypeInfo next() - { - return typeid(ifloat); - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/typeinfo/ti_Ag.d --- a/druntime/src/compiler/ldc/typeinfo/ti_Ag.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,228 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: s2.length) - return 1; - return 0; - } - - override size_t tsize() - { - return (byte[]).sizeof; - } - - override uint flags() - { - return 1; - } - - override TypeInfo next() - { - return typeid(byte); - } -} - - -// ubyte[] - -class TypeInfo_Ah : TypeInfo_Ag -{ - override string toString() { return "ubyte[]"; } - - override int compare(in void* p1, in void* p2) - { - char[] s1 = *cast(char[]*)p1; - char[] s2 = *cast(char[]*)p2; - - return dstrcmp(s1, s2); - } - - override TypeInfo next() - { - return typeid(ubyte); - } -} - -// void[] - -class TypeInfo_Av : TypeInfo_Ah -{ - override string toString() { return "void[]"; } - - override TypeInfo next() - { - return typeid(void); - } -} - -// bool[] - -class TypeInfo_Ab : TypeInfo_Ah -{ - override string toString() { return "bool[]"; } - - override TypeInfo next() - { - return typeid(bool); - } -} - -// char[] - -class TypeInfo_Aa : TypeInfo_Ag -{ - override string toString() { return "char[]"; } - - override hash_t getHash(in void* p) - { char[] s = *cast(char[]*)p; - hash_t hash = 0; - -version (all) -{ - foreach (char c; s) - hash = hash * 11 + c; -} -else -{ - size_t len = s.length; - char *str = s; - - while (1) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash *= 9; - hash += *cast(ubyte *)str; - return hash; - - case 2: - hash *= 9; - hash += *cast(ushort *)str; - return hash; - - case 3: - hash *= 9; - hash += (*cast(ushort *)str << 8) + - (cast(ubyte *)str)[2]; - return hash; - - default: - hash *= 9; - hash += *cast(uint *)str; - str += 4; - len -= 4; - break; - } - } -} - return hash; - } - - override TypeInfo next() - { - return typeid(char); - } -} - -// string - -class TypeInfo_Aya : TypeInfo_Aa -{ - override string toString() { return "immutable(char)[]"; } - - override TypeInfo next() - { - return typeid(immutable(char)); - } -} - diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/typeinfo/ti_Aint.d --- a/druntime/src/compiler/ldc/typeinfo/ti_Aint.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,140 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: s2.length) - return 1; - return 0; - } - - override size_t tsize() - { - return (int[]).sizeof; - } - - override uint flags() - { - return 1; - } - - override TypeInfo next() - { - return typeid(int); - } -} - -unittest -{ - int[][] a = [[5,3,8,7], [2,5,3,8,7]]; - a.sort; - assert(a == [[2,5,3,8,7], [5,3,8,7]]); - - a = [[5,3,8,7], [5,3,8]]; - a.sort; - assert(a == [[5,3,8], [5,3,8,7]]); -} - -// uint[] - -class TypeInfo_Ak : TypeInfo_Ai -{ - override string toString() { return "uint[]"; } - - override int compare(in void* p1, in void* p2) - { - uint[] s1 = *cast(uint[]*)p1; - uint[] s2 = *cast(uint[]*)p2; - size_t len = s1.length; - - if (s2.length < len) - len = s2.length; - for (size_t u = 0; u < len; u++) - { - int result = s1[u] - s2[u]; - if (result) - return result; - } - if (s1.length < s2.length) - return -1; - else if (s1.length > s2.length) - return 1; - return 0; - } - - override TypeInfo next() - { - return typeid(uint); - } -} - -// dchar[] - -class TypeInfo_Aw : TypeInfo_Ak -{ - override string toString() { return "dchar[]"; } - - override TypeInfo next() - { - return typeid(dchar); - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/typeinfo/ti_Along.d --- a/druntime/src/compiler/ldc/typeinfo/ti_Along.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,120 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: s2[u]) - return 1; - } - if (s1.length < s2.length) - return -1; - else if (s1.length > s2.length) - return 1; - return 0; - } - - override size_t tsize() - { - return (long[]).sizeof; - } - - override uint flags() - { - return 1; - } - - override TypeInfo next() - { - return typeid(long); - } -} - - -// ulong[] - -class TypeInfo_Am : TypeInfo_Al -{ - override string toString() { return "ulong[]"; } - - override int compare(in void* p1, in void* p2) - { - ulong[] s1 = *cast(ulong[]*)p1; - ulong[] s2 = *cast(ulong[]*)p2; - size_t len = s1.length; - - if (s2.length < len) - len = s2.length; - for (size_t u = 0; u < len; u++) - { - if (s1[u] < s2[u]) - return -1; - else if (s1[u] > s2[u]) - return 1; - } - if (s1.length < s2.length) - return -1; - else if (s1.length > s2.length) - return 1; - return 0; - } - - override TypeInfo next() - { - return typeid(ulong); - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/typeinfo/ti_Areal.d --- a/druntime/src/compiler/ldc/typeinfo/ti_Areal.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,105 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: s2.length) - return 1; - return 0; - } - - override size_t tsize() - { - return (real[]).sizeof; - } - - override uint flags() - { - return 1; - } - - override TypeInfo next() - { - return typeid(real); - } -} - -// ireal[] - -class TypeInfo_Aj : TypeInfo_Ae -{ - override string toString() { return "ireal[]"; } - - override TypeInfo next() - { - return typeid(ireal); - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/typeinfo/ti_Ashort.d --- a/druntime/src/compiler/ldc/typeinfo/ti_Ashort.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,143 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: s2.length) - return 1; - return 0; - } - - override size_t tsize() - { - return (short[]).sizeof; - } - - override uint flags() - { - return 1; - } - - override TypeInfo next() - { - return typeid(short); - } -} - - -// ushort[] - -class TypeInfo_At : TypeInfo_As -{ - override string toString() { return "ushort[]"; } - - override int compare(in void* p1, in void* p2) - { - ushort[] s1 = *cast(ushort[]*)p1; - ushort[] s2 = *cast(ushort[]*)p2; - size_t len = s1.length; - - if (s2.length < len) - len = s2.length; - for (size_t u = 0; u < len; u++) - { - int result = s1[u] - s2[u]; - if (result) - return result; - } - if (s1.length < s2.length) - return -1; - else if (s1.length > s2.length) - return 1; - return 0; - } - - override TypeInfo next() - { - return typeid(ushort); - } -} - -// wchar[] - -class TypeInfo_Au : TypeInfo_At -{ - override string toString() { return "wchar[]"; } - - override TypeInfo next() - { - return typeid(wchar); - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/typeinfo/ti_C.d --- a/druntime/src/compiler/ldc/typeinfo/ti_C.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: f2.re) - result = 1; - else if (f1.im < f2.im) - result = -1; - else if (f1.im > f2.im) - result = 1; - else - result = 0; - return result; - } - - override equals_t equals(in void* p1, in void* p2) - { - return _equals(*cast(cdouble *)p1, *cast(cdouble *)p2); - } - - override int compare(in void* p1, in void* p2) - { - return _compare(*cast(cdouble *)p1, *cast(cdouble *)p2); - } - - override size_t tsize() - { - return cdouble.sizeof; - } - - override void swap(void *p1, void *p2) - { - cdouble t; - - t = *cast(cdouble *)p1; - *cast(cdouble *)p1 = *cast(cdouble *)p2; - *cast(cdouble *)p2 = t; - } - - override void[] init() - { static immutable cdouble r; - - return (cast(cdouble *)&r)[0 .. 1]; - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/typeinfo/ti_cfloat.d --- a/druntime/src/compiler/ldc/typeinfo/ti_cfloat.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,76 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: f2.re) - result = 1; - else if (f1.im < f2.im) - result = -1; - else if (f1.im > f2.im) - result = 1; - else - result = 0; - return result; - } - - override equals_t equals(in void* p1, in void* p2) - { - return _equals(*cast(cfloat *)p1, *cast(cfloat *)p2); - } - - override int compare(in void* p1, in void* p2) - { - return _compare(*cast(cfloat *)p1, *cast(cfloat *)p2); - } - - override size_t tsize() - { - return cfloat.sizeof; - } - - override void swap(void *p1, void *p2) - { - cfloat t; - - t = *cast(cfloat *)p1; - *cast(cfloat *)p1 = *cast(cfloat *)p2; - *cast(cfloat *)p2 = t; - } - - override void[] init() - { static immutable cfloat r; - - return (cast(cfloat *)&r)[0 .. 1]; - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/typeinfo/ti_char.d --- a/druntime/src/compiler/ldc/typeinfo/ti_char.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: f2.re) - result = 1; - else if (f1.im < f2.im) - result = -1; - else if (f1.im > f2.im) - result = 1; - else - result = 0; - return result; - } - - override equals_t equals(in void* p1, in void* p2) - { - return _equals(*cast(creal *)p1, *cast(creal *)p2); - } - - override int compare(in void* p1, in void* p2) - { - return _compare(*cast(creal *)p1, *cast(creal *)p2); - } - - override size_t tsize() - { - return creal.sizeof; - } - - override void swap(void *p1, void *p2) - { - creal t; - - t = *cast(creal *)p1; - *cast(creal *)p1 = *cast(creal *)p2; - *cast(creal *)p2 = t; - } - - override void[] init() - { static immutable creal r; - - return (cast(creal *)&r)[0 .. 1]; - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/typeinfo/ti_dchar.d --- a/druntime/src/compiler/ldc/typeinfo/ti_dchar.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: Boost License 1.0. - * Authors: Walter Bright - * - * Copyright Digital Mars 2004 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module rt.typeinfo.ti_double; - -// double - -class TypeInfo_d : TypeInfo -{ - override string toString() { return "double"; } - - override hash_t getHash(in void* p) - { - return (cast(uint *)p)[0] + (cast(uint *)p)[1]; - } - - static equals_t _equals(double f1, double f2) - { - return f1 == f2 || - (f1 !<>= f1 && f2 !<>= f2); - } - - static int _compare(double d1, double d2) - { - if (d1 !<>= d2) // if either are NaN - { - if (d1 !<>= d1) - { if (d2 !<>= d2) - return 0; - return -1; - } - return 1; - } - return (d1 == d2) ? 0 : ((d1 < d2) ? -1 : 1); - } - - override equals_t equals(in void* p1, in void* p2) - { - return _equals(*cast(double *)p1, *cast(double *)p2); - } - - override int compare(in void* p1, in void* p2) - { - return _compare(*cast(double *)p1, *cast(double *)p2); - } - - override size_t tsize() - { - return double.sizeof; - } - - override void swap(void *p1, void *p2) - { - double t; - - t = *cast(double *)p1; - *cast(double *)p1 = *cast(double *)p2; - *cast(double *)p2 = t; - } - - override void[] init() - { static immutable double r; - - return (cast(double *)&r)[0 .. 1]; - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/typeinfo/ti_float.d --- a/druntime/src/compiler/ldc/typeinfo/ti_float.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: = f1 && f2 !<>= f2); - } - - static int _compare(float d1, float d2) - { - if (d1 !<>= d2) // if either are NaN - { - if (d1 !<>= d1) - { if (d2 !<>= d2) - return 0; - return -1; - } - return 1; - } - return (d1 == d2) ? 0 : ((d1 < d2) ? -1 : 1); - } - - override equals_t equals(in void* p1, in void* p2) - { - return _equals(*cast(float *)p1, *cast(float *)p2); - } - - override int compare(in void* p1, in void* p2) - { - return _compare(*cast(float *)p1, *cast(float *)p2); - } - - override size_t tsize() - { - return float.sizeof; - } - - override void swap(void *p1, void *p2) - { - float t; - - t = *cast(float *)p1; - *cast(float *)p1 = *cast(float *)p2; - *cast(float *)p2 = t; - } - - override void[] init() - { static immutable float r; - - return (cast(float *)&r)[0 .. 1]; - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/typeinfo/ti_idouble.d --- a/druntime/src/compiler/ldc/typeinfo/ti_idouble.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: *cast(int*) p2) - return 1; - return 0; - } - - override size_t tsize() - { - return int.sizeof; - } - - override void swap(void *p1, void *p2) - { - int t; - - t = *cast(int *)p1; - *cast(int *)p1 = *cast(int *)p2; - *cast(int *)p2 = t; - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/typeinfo/ti_ireal.d --- a/druntime/src/compiler/ldc/typeinfo/ti_ireal.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: *cast(long *)p2) - return 1; - return 0; - } - - override size_t tsize() - { - return long.sizeof; - } - - override void swap(void *p1, void *p2) - { - long t; - - t = *cast(long *)p1; - *cast(long *)p1 = *cast(long *)p2; - *cast(long *)p2 = t; - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/typeinfo/ti_ptr.d --- a/druntime/src/compiler/ldc/typeinfo/ti_ptr.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: Boost License 1.0. - * Authors: Walter Bright - * - * Copyright Digital Mars 2004 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module rt.typeinfo.ti_real; - -// real - -class TypeInfo_e : TypeInfo -{ - override string toString() { return "real"; } - - override hash_t getHash(in void* p) - { - return (cast(uint *)p)[0] + (cast(uint *)p)[1] + (cast(ushort *)p)[4]; - } - - static equals_t _equals(real f1, real f2) - { - return f1 == f2 || - (f1 !<>= f1 && f2 !<>= f2); - } - - static int _compare(real d1, real d2) - { - if (d1 !<>= d2) // if either are NaN - { - if (d1 !<>= d1) - { if (d2 !<>= d2) - return 0; - return -1; - } - return 1; - } - return (d1 == d2) ? 0 : ((d1 < d2) ? -1 : 1); - } - - override equals_t equals(in void* p1, in void* p2) - { - return _equals(*cast(real *)p1, *cast(real *)p2); - } - - override int compare(in void* p1, in void* p2) - { - return _compare(*cast(real *)p1, *cast(real *)p2); - } - - override size_t tsize() - { - return real.sizeof; - } - - override void swap(void *p1, void *p2) - { - real t; - - t = *cast(real *)p1; - *cast(real *)p1 = *cast(real *)p2; - *cast(real *)p2 = t; - } - - override void[] init() - { static immutable real r; - - return (cast(real *)&r)[0 .. 1]; - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/typeinfo/ti_short.d --- a/druntime/src/compiler/ldc/typeinfo/ti_short.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: *cast(uint*) p2) - return 1; - return 0; - } - - override size_t tsize() - { - return uint.sizeof; - } - - override void swap(void *p1, void *p2) - { - int t; - - t = *cast(uint *)p1; - *cast(uint *)p1 = *cast(uint *)p2; - *cast(uint *)p2 = t; - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/typeinfo/ti_ulong.d --- a/druntime/src/compiler/ldc/typeinfo/ti_ulong.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: *cast(ulong *)p2) - return 1; - return 0; - } - - override size_t tsize() - { - return ulong.sizeof; - } - - override void swap(void *p1, void *p2) - { - ulong t; - - t = *cast(ulong *)p1; - *cast(ulong *)p1 = *cast(ulong *)p2; - *cast(ulong *)p2 = t; - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/typeinfo/ti_ushort.d --- a/druntime/src/compiler/ldc/typeinfo/ti_ushort.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -/** - * TypeInfo support code. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: =0x48 && x<=0x80) - || x==0x86 || x==0x87 - || (x>=0x66 && x<=0x68) || (x>=0x39 && x<=0x3E)){ - datacache[level].lineSize = 64; - } else datacache[level].lineSize = 32; - } - } - } - - uint[4] a; - bool firstTime = true; - // On a multi-core system, this could theoretically fail, but it's only used - // for old single-core CPUs. - uint numinfos = 1; - do { - asm { - mov EAX, 2; - cpuid; - mov a, EAX; - mov a+4, EBX; - mov a+8, ECX; - mov a+12, EDX; - } - if (firstTime) { - if (a[0]==0x0000_7001 && a[3]==0x80 && a[1]==0 && a[2]==0) { - // Cyrix MediaGX MMXEnhanced returns: EAX= 00007001, EDX=00000080. - // These are NOT standard Intel values - // (TLB = 32 entry, 4 way associative, 4K pages) - // (L1 cache = 16K, 4way, linesize16) - datacache[0].size=8; - datacache[0].associativity=4; - datacache[0].lineSize=16; - return; - } - // lsb of a is how many times to loop. - numinfos = a[0] & 0xFF; - // and otherwise it should be ignored - a[0] &= 0xFFFF_FF00; - firstTime = false; - } - for (int c=0; c<4;++c) { - // high bit set == no info. - if (a[c] & 0x8000_0000) continue; - decipherCpuid2(cast(ubyte)(a[c] & 0xFF)); - decipherCpuid2(cast(ubyte)((a[c]>>8) & 0xFF)); - decipherCpuid2(cast(ubyte)((a[c]>>16) & 0xFF)); - decipherCpuid2(cast(ubyte)((a[c]>>24) & 0xFF)); - } - } while (--numinfos); -} - -// CPUID4: "Deterministic cache parameters" leaf -void getcacheinfoCPUID4() -{ - int cachenum = 0; - for(;;) { - uint a, b, number_of_sets; - asm { - mov EAX, 4; - mov ECX, cachenum; - cpuid; - mov a, EAX; - mov b, EBX; - mov number_of_sets, ECX; - } - ++cachenum; - if ((a&0x1F)==0) break; // no more caches - uint numthreads = ((a>>14) & 0xFFF) + 1; - uint numcores = ((a>>26) & 0x3F) + 1; - if (numcores > maxCores) maxCores = numcores; - if ((a&0x1F)!=1 && ((a&0x1F)!=3)) continue; // we only want data & unified caches - - ++number_of_sets; - ubyte level = cast(ubyte)(((a>>5)&7)-1); - if (level > datacache.length) continue; // ignore deep caches - datacache[level].associativity = a & 0x200 ? ubyte.max :cast(ubyte)((b>>22)+1); - datacache[level].lineSize = (b & 0xFFF)+ 1; // system coherency line size - uint line_partitions = ((b >> 12)& 0x3FF) + 1; - // Size = number of sets * associativity * cachelinesize * linepartitions - // and must convert to Kb, also dividing by the number of hyperthreads using this cache. - ulong sz = (datacache[level].associativity< ubyte.max)? number_of_sets * - datacache[level].associativity : number_of_sets; - datacache[level].size = cast(uint)( - (sz * datacache[level].lineSize * line_partitions ) / (numthreads *1024)); - if (level == 0 && (a&0xF)==3) { - // Halve the size for unified L1 caches - datacache[level].size/=2; - } - } -} - -// CPUID8000_0005 & 6 -void getAMDcacheinfo() -{ - uint c5, c6, d6; - asm { - mov EAX, 0x8000_0005; // L1 cache - cpuid; - // EAX has L1_TLB_4M. - // EBX has L1_TLB_4K - // EDX has L1 instruction cache - mov c5, ECX; - } - - datacache[0].size = ( (c5>>24) & 0xFF); - datacache[0].associativity = cast(ubyte)( (c5 >> 16) & 0xFF); - datacache[0].lineSize = c5 & 0xFF; - - if (max_extended_cpuid >= 0x8000_0006) { - // AMD K6-III or K6-2+ or later. - ubyte numcores = 1; - if (max_extended_cpuid >=0x8000_0008) { - asm { - mov EAX, 0x8000_0008; - cpuid; - mov numcores, CL; - } - ++numcores; - if (numcores>maxCores) maxCores = numcores; - } - asm { - mov EAX, 0x8000_0006; // L2/L3 cache - cpuid; - mov c6, ECX; // L2 cache info - mov d6, EDX; // L3 cache info - } - - immutable ubyte [] assocmap = [ 0, 1, 2, 0, 4, 0, 8, 0, 16, 0, 32, 48, 64, 96, 128, 0xFF ]; - datacache[1].size = (c6>>16) & 0xFFFF; - datacache[1].associativity = assocmap[(c6>>12)&0xF]; - datacache[1].lineSize = c6 & 0xFF; - - // The L3 cache value is TOTAL, not per core. - datacache[2].size = ((d6>>18)*512)/numcores; // could be up to 2 * this, -1. - datacache[2].associativity = assocmap[(d6>>12)&0xF]; - datacache[2].lineSize = d6 & 0xFF; - } -} - - -void cpuidX86() -{ - char * venptr = vendorID.ptr; - asm { - mov EAX, 0; - cpuid; - mov max_cpuid, EAX; - mov EAX, venptr; - mov [EAX], EBX; - mov [EAX + 4], EDX; - mov [EAX + 8], ECX; - mov EAX, 0x8000_0000; - cpuid; - mov max_extended_cpuid, EAX; - } - - probablyIntel = vendorID == "GenuineIntel"; - probablyAMD = vendorID == "AuthenticAMD"; - uint a, b, c, d; - uint apic = 0; // brand index, apic id - asm { - mov EAX, 1; // model, stepping - cpuid; - mov a, EAX; - mov apic, EBX; - mov miscfeatures, ECX; - mov features, EDX; - } - amdfeatures = 0; - amdmiscfeatures = 0; - if (max_extended_cpuid >= 0x8000_0001) { - asm { - mov EAX, 0x8000_0001; - cpuid; - mov amdmiscfeatures, ECX; - mov amdfeatures, EDX; - } - } - // Try to detect fraudulent vendorIDs - if (amd3dnow) probablyIntel = false; - - stepping = a & 0xF; - uint fbase = (a >> 8) & 0xF; - uint mbase = (a >> 4) & 0xF; - family = ((fbase == 0xF) || (fbase == 0)) ? fbase + (a >> 20) & 0xFF : fbase; - model = ((fbase == 0xF) || (fbase == 6 && probablyIntel) ) ? - mbase + ((a >> 12) & 0xF0) : mbase; - - if (!probablyIntel && max_extended_cpuid >= 0x8000_0008) { - // determine max number of cores for AMD - asm { - mov EAX, 0x8000_0008; - cpuid; - mov c, ECX; - } - uint apicsize = (c>>12) & 0xF; - if (apicsize == 0) { - // use legacy method - if (hyperThreadingBit) maxCores = c & 0xFF; - else maxCores = 1; - } else { - // maxcores = 2^ apicsize - maxCores = 1; - while (apicsize) { maxCores<<=1; --apicsize; } - } - } - - if (max_extended_cpuid >= 0x8000_0004) { - char *procptr = processorNameBuffer.ptr; - asm { - push ESI; - mov ESI, procptr; - mov EAX, 0x8000_0002; - cpuid; - mov [ESI], EAX; - mov [ESI+4], EBX; - mov [ESI+8], ECX; - mov [ESI+12], EDX; - mov EAX, 0x8000_0003; - cpuid; - mov [ESI+16], EAX; - mov [ESI+20], EBX; - mov [ESI+24], ECX; - mov [ESI+28], EDX; - mov EAX, 0x8000_0004; - cpuid; - mov [ESI+32], EAX; - mov [ESI+36], EBX; - mov [ESI+40], ECX; - mov [ESI+44], EDX; - pop ESI; - } - // Intel P4 and PM pad at front with spaces. - // Other CPUs pad at end with nulls. - int start = 0, end = 0; - while (processorNameBuffer[start] == ' ') { ++start; } - while (processorNameBuffer[$-end-1] == 0) { ++end; } - processorName = processorNameBuffer[start..$-end]; - } else { - processorName[] = "Unknown CPU"; - } - // Determine cache sizes - - // Intel docs specify that they return 0 for 0x8000_0005. - // AMD docs do not specify the behaviour for 0004 and 0002. - // Centaur/VIA and most other manufacturers use the AMD method, - // except Cyrix MediaGX MMX Enhanced uses their OWN form of CPUID2! - // NS Geode GX1 provides CyrixCPUID2 _and_ does the same wrong behaviour - // for CPUID80000005. But Geode GX uses the AMD method - - // Deal with Geode GX1 - make it same as MediaGX MMX. - if (max_extended_cpuid==0x8000_0005 && max_cpuid==2) { - max_extended_cpuid = 0x8000_0004; - } - // Therefore, we try the AMD method unless it's an Intel chip. - // If we still have no info, try the Intel methods. - datacache[0].size = 0; - if (max_cpuid<2 || !probablyIntel) { - if (max_extended_cpuid >= 0x8000_0005) { - getAMDcacheinfo(); - } else if (probablyAMD) { - // According to AMDProcRecognitionAppNote, this means CPU - // K5 model 0, or Am5x86 (model 4), or Am4x86DX4 (model 4) - // Am5x86 has 16Kb 4-way unified data & code cache. - datacache[0].size = 8; - datacache[0].associativity = 4; - datacache[0].lineSize = 32; - } else { - // Some obscure CPU. - // Values for Cyrix 6x86MX (family 6, model 0) - datacache[0].size = 64; - datacache[0].associativity = 4; - datacache[0].lineSize = 32; - } - } - if ((datacache[0].size == 0) && max_cpuid>=4) { - getcacheinfoCPUID4(); - } - if ((datacache[0].size == 0) && max_cpuid>=2) { - getcacheinfoCPUID2(); - } - if (datacache[0].size == 0) { - // Pentium, PMMX, late model 486, or an obscure CPU - if (mmx) { // Pentium MMX. Also has 8kB code cache. - datacache[0].size = 16; - datacache[0].associativity = 4; - datacache[0].lineSize = 32; - } else { // Pentium 1 (which also has 8kB code cache) - // or 486. - // Cyrix 6x86: 16, 4way, 32 linesize - datacache[0].size = 8; - datacache[0].associativity = 2; - datacache[0].lineSize = 32; - } - } - if (hyperThreadingBit) maxThreads = (apic>>>16) & 0xFF; - else maxThreads = maxCores; -} - -// Return true if the cpuid instruction is supported. -// BUG(WONTFIX): Returns false for Cyrix 6x86 and 6x86L. They will be treated as 486 machines. -bool hasCPUID() -{ - uint flags; - asm { - pushfd; - pop EAX; - mov flags, EAX; - xor EAX, 0x0020_0000; - push EAX; - popfd; - pushfd; - pop EAX; - xor flags, EAX; - } - return (flags & 0x0020_0000) !=0; -} - -} else { // inline asm X86 - - bool hasCPUID() { return false; } - - void cpuidX86() - { - datacache[0].size = 8; - datacache[0].associativity = 2; - datacache[0].lineSize = 32; - } -} - -// TODO: Implement this function with OS support -void cpuidPPC() -{ - enum :int { PPC601, PPC603, PPC603E, PPC604, - PPC604E, PPC620, PPCG3, PPCG4, PPCG5 }; - - // TODO: - // asm { mfpvr; } returns the CPU version but unfortunately it can - // only be used in kernel mode. So OS support is required. - int cputype = PPC603; - - // 601 has a 8KB combined data & code L1 cache. - uint sizes[] = [4, 8, 16, 16, 32, 32, 32, 32, 64]; - ubyte ways[] = [8, 2, 4, 4, 4, 8, 8, 8, 8]; - uint L2size[]= [0, 0, 0, 0, 0, 0, 0, 256, 512]; - uint L3size[]= [0, 0, 0, 0, 0, 0, 0, 2048, 0]; - - datacache[0].size = sizes[cputype]; - datacache[0].associativity = ways[cputype]; - datacache[0].lineSize = (cputype==PPCG5)? 128 : - (cputype == PPC620 || cputype == PPCG3)? 64 : 32; - datacache[1].size = L2size[cputype]; - datacache[2].size = L3size[cputype]; - datacache[1].lineSize = datacache[0].lineSize; - datacache[2].lineSize = datacache[0].lineSize; -} - -// TODO: Implement this function with OS support -void cpuidSparc() -{ - // UltaSparcIIi : L1 = 16, 2way. L2 = 512, 4 way. - // UltraSparcIII : L1 = 64, 4way. L2= 4096 or 8192. - // UltraSparcIIIi: L1 = 64, 4way. L2= 1024, 4 way - // UltraSparcIV : L1 = 64, 4way. L2 = 16*1024. - // UltraSparcIV+ : L1 = 64, 4way. L2 = 2048, L3=32*1024. - // Sparc64V : L1 = 128, 2way. L2 = 4096 4way. -} - - -static this() -{ - if (hasCPUID()) { - cpuidX86(); - } else { - // it's a 386 or 486, or a Cyrix 6x86. - //Probably still has an external cache. - } - if (datacache[0].size==0) { - // Guess same as Pentium 1. - datacache[0].size = 8; - datacache[0].associativity = 2; - datacache[0].lineSize = 32; - } - numCacheLevels = 1; - // And now fill up all the unused levels with full memory space. - for (int i=1; i< datacache.length; ++i) { - if (datacache[i].size==0) { - // Set all remaining levels of cache equal to full address space. - datacache[i].size = uint.max/1024; - datacache[i].associativity = 1; - datacache[i].lineSize = datacache[i-1].lineSize; - } else numCacheLevels = i+1; - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/util/ctype.d --- a/druntime/src/compiler/ldc/util/ctype.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,92 +0,0 @@ -/** - * Simple ASCII char classification functions. - * - * Copyright: Copyright Digital Mars 2004 - 2009. - * License: Boost License 1.0. - * Authors: Sean Kelly - * - * Copyright Sean Kelly 2005 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module rt.util.string; - -private import core.stdc.string; - -char[] intToString( char[] buf, uint val ) -{ - assert( buf.length > 9 ); - auto p = buf.ptr + buf.length; - - do - { - *--p = cast(char)(val % 10 + '0'); - } while( val /= 10 ); - - return buf[p - buf.ptr .. $]; -} - - -int dstrcmp( in char[] s1, in char[] s2 ) -{ - auto len = s1.length; - if( s2.length < len ) - len = s2.length; - if( memcmp( s1.ptr, s2.ptr, len ) == 0 ) - return 0; - return s1.length > s2.length ? 1 : -1; -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/util/utf.d --- a/druntime/src/compiler/ldc/util/utf.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,901 +0,0 @@ -/******************************************** - * Encode and decode UTF-8, UTF-16 and UTF-32 strings. - * - * For Win32 systems, the C wchar_t type is UTF-16 and corresponds to the D - * wchar type. - * For Posix systems, the C wchar_t type is UTF-32 and corresponds to - * the D utf.dchar type. - * - * UTF character support is restricted to (\u0000 <= character <= \U0010FFFF). - * - * See_Also: - * $(LINK2 http://en.wikipedia.org/wiki/Unicode, Wikipedia)
- * $(LINK http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8)
- * $(LINK http://anubis.dkuug.dk/JTC1/SC2/WG2/docs/n1335) - * Macros: - * WIKI = Phobos/StdUtf - * - * Copyright: Copyright Digital Mars 2003 - 2009. - * License: = 0xD800 && u <= 0xDBFF); -} - -/** - * stride() returns the length of a UTF-32 sequence starting at index i - * in string s. - * Returns: The return value will always be 1. - */ -uint stride(in dchar[] s, size_t i) -{ - return 1; -} - -/******************************************* - * Given an index i into an array of characters s[], - * and assuming that index i is at the start of a UTF character, - * determine the number of UCS characters up to that index i. - */ - -size_t toUCSindex(in char[] s, size_t i) -{ - size_t n; - size_t j; - - for (j = 0; j < i; ) - { - j += stride(s, j); - n++; - } - if (j > i) - { - onUnicodeError("invalid UTF-8 sequence", j); - } - return n; -} - -/** ditto */ -size_t toUCSindex(in wchar[] s, size_t i) -{ - size_t n; - size_t j; - - for (j = 0; j < i; ) - { - j += stride(s, j); - n++; - } - if (j > i) - { - onUnicodeError("invalid UTF-16 sequence", j); - } - return n; -} - -/** ditto */ -size_t toUCSindex(in dchar[] s, size_t i) -{ - return i; -} - -/****************************************** - * Given a UCS index n into an array of characters s[], return the UTF index. - */ - -size_t toUTFindex(in char[] s, size_t n) -{ - size_t i; - - while (n--) - { - uint j = UTF8stride[s[i]]; - if (j == 0xFF) - onUnicodeError("invalid UTF-8 sequence", i); - i += j; - } - return i; -} - -/** ditto */ -size_t toUTFindex(in wchar[] s, size_t n) -{ - size_t i; - - while (n--) - { wchar u = s[i]; - - i += 1 + (u >= 0xD800 && u <= 0xDBFF); - } - return i; -} - -/** ditto */ -size_t toUTFindex(in dchar[] s, size_t n) -{ - return n; -} - -/* =================== Decode ======================= */ - -/*************** - * Decodes and returns character starting at s[idx]. idx is advanced past the - * decoded character. If the character is not well formed, a UtfException is - * thrown and idx remains unchanged. - */ -dchar decode(in char[] s, inout size_t idx) - in - { - assert(idx >= 0 && idx < s.length); - } - out (result) - { - assert(isValidDchar(result)); - } - body - { - size_t len = s.length; - dchar V; - size_t i = idx; - char u = s[i]; - - if (u & 0x80) - { uint n; - char u2; - - /* The following encodings are valid, except for the 5 and 6 byte - * combinations: - * 0xxxxxxx - * 110xxxxx 10xxxxxx - * 1110xxxx 10xxxxxx 10xxxxxx - * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - * 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx - * 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx - */ - for (n = 1; ; n++) - { - if (n > 4) - goto Lerr; // only do the first 4 of 6 encodings - if (((u << n) & 0x80) == 0) - { - if (n == 1) - goto Lerr; - break; - } - } - - // Pick off (7 - n) significant bits of B from first byte of octet - V = cast(dchar)(u & ((1 << (7 - n)) - 1)); - - if (i + (n - 1) >= len) - goto Lerr; // off end of string - - /* The following combinations are overlong, and illegal: - * 1100000x (10xxxxxx) - * 11100000 100xxxxx (10xxxxxx) - * 11110000 1000xxxx (10xxxxxx 10xxxxxx) - * 11111000 10000xxx (10xxxxxx 10xxxxxx 10xxxxxx) - * 11111100 100000xx (10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx) - */ - u2 = s[i + 1]; - if ((u & 0xFE) == 0xC0 || - (u == 0xE0 && (u2 & 0xE0) == 0x80) || - (u == 0xF0 && (u2 & 0xF0) == 0x80) || - (u == 0xF8 && (u2 & 0xF8) == 0x80) || - (u == 0xFC && (u2 & 0xFC) == 0x80)) - goto Lerr; // overlong combination - - for (uint j = 1; j != n; j++) - { - u = s[i + j]; - if ((u & 0xC0) != 0x80) - goto Lerr; // trailing bytes are 10xxxxxx - V = (V << 6) | (u & 0x3F); - } - if (!isValidDchar(V)) - goto Lerr; - i += n; - } - else - { - V = cast(dchar) u; - i++; - } - - idx = i; - return V; - - Lerr: - onUnicodeError("invalid UTF-8 sequence", i); - return V; // dummy return - } - -unittest -{ size_t i; - dchar c; - - debug(utf) printf("utf.decode.unittest\n"); - - static s1 = "abcd"c; - i = 0; - c = decode(s1, i); - assert(c == cast(dchar)'a'); - assert(i == 1); - c = decode(s1, i); - assert(c == cast(dchar)'b'); - assert(i == 2); - - static s2 = "\xC2\xA9"c; - i = 0; - c = decode(s2, i); - assert(c == cast(dchar)'\u00A9'); - assert(i == 2); - - static s3 = "\xE2\x89\xA0"c; - i = 0; - c = decode(s3, i); - assert(c == cast(dchar)'\u2260'); - assert(i == 3); - - static s4 = - [ "\xE2\x89"c[], // too short - "\xC0\x8A", - "\xE0\x80\x8A", - "\xF0\x80\x80\x8A", - "\xF8\x80\x80\x80\x8A", - "\xFC\x80\x80\x80\x80\x8A", - ]; - - for (int j = 0; j < s4.length; j++) - { - try - { - i = 0; - c = decode(s4[j], i); - assert(0); - } - catch (Object o) - { - i = 23; - } - assert(i == 23); - } -} - -/** ditto */ - -dchar decode(in wchar[] s, inout size_t idx) - in - { - assert(idx >= 0 && idx < s.length); - } - out (result) - { - assert(isValidDchar(result)); - } - body - { - string msg; - dchar V; - size_t i = idx; - uint u = s[i]; - - if (u & ~0x7F) - { if (u >= 0xD800 && u <= 0xDBFF) - { uint u2; - - if (i + 1 == s.length) - { msg = "surrogate UTF-16 high value past end of string"; - goto Lerr; - } - u2 = s[i + 1]; - if (u2 < 0xDC00 || u2 > 0xDFFF) - { msg = "surrogate UTF-16 low value out of range"; - goto Lerr; - } - u = ((u - 0xD7C0) << 10) + (u2 - 0xDC00); - i += 2; - } - else if (u >= 0xDC00 && u <= 0xDFFF) - { msg = "unpaired surrogate UTF-16 value"; - goto Lerr; - } - else if (u == 0xFFFE || u == 0xFFFF) - { msg = "illegal UTF-16 value"; - goto Lerr; - } - else - i++; - } - else - { - i++; - } - - idx = i; - return cast(dchar)u; - - Lerr: - onUnicodeError(msg, i); - return cast(dchar)u; // dummy return - } - -/** ditto */ - -dchar decode(in dchar[] s, inout size_t idx) - in - { - assert(idx >= 0 && idx < s.length); - } - body - { - size_t i = idx; - dchar c = s[i]; - - if (!isValidDchar(c)) - goto Lerr; - idx = i + 1; - return c; - - Lerr: - onUnicodeError("invalid UTF-32 value", i); - return c; // dummy return - } - - -/* =================== Encode ======================= */ - -/******************************* - * Encodes character c and appends it to array s[]. - */ -void encode(inout char[] s, dchar c) - in - { - assert(isValidDchar(c)); - } - body - { - char[] r = s; - - if (c <= 0x7F) - { - r ~= cast(char) c; - } - else - { - char[4] buf; - uint L; - - if (c <= 0x7FF) - { - buf[0] = cast(char)(0xC0 | (c >> 6)); - buf[1] = cast(char)(0x80 | (c & 0x3F)); - L = 2; - } - else if (c <= 0xFFFF) - { - buf[0] = cast(char)(0xE0 | (c >> 12)); - buf[1] = cast(char)(0x80 | ((c >> 6) & 0x3F)); - buf[2] = cast(char)(0x80 | (c & 0x3F)); - L = 3; - } - else if (c <= 0x10FFFF) - { - buf[0] = cast(char)(0xF0 | (c >> 18)); - buf[1] = cast(char)(0x80 | ((c >> 12) & 0x3F)); - buf[2] = cast(char)(0x80 | ((c >> 6) & 0x3F)); - buf[3] = cast(char)(0x80 | (c & 0x3F)); - L = 4; - } - else - { - assert(0); - } - r ~= buf[0 .. L]; - } - s = r; - } - -unittest -{ - debug(utf) printf("utf.encode.unittest\n"); - - char[] s = "abcd".dup; - encode(s, cast(dchar)'a'); - assert(s.length == 5); - assert(s == "abcda"); - - encode(s, cast(dchar)'\u00A9'); - assert(s.length == 7); - assert(s == "abcda\xC2\xA9"); - //assert(s == "abcda\u00A9"); // BUG: fix compiler - - encode(s, cast(dchar)'\u2260'); - assert(s.length == 10); - assert(s == "abcda\xC2\xA9\xE2\x89\xA0"); -} - -/** ditto */ - -void encode(inout wchar[] s, dchar c) - in - { - assert(isValidDchar(c)); - } - body - { - wchar[] r = s; - - if (c <= 0xFFFF) - { - r ~= cast(wchar) c; - } - else - { - wchar[2] buf; - - buf[0] = cast(wchar) ((((c - 0x10000) >> 10) & 0x3FF) + 0xD800); - buf[1] = cast(wchar) (((c - 0x10000) & 0x3FF) + 0xDC00); - r ~= buf; - } - s = r; - } - -/** ditto */ -void encode(inout dchar[] s, dchar c) - in - { - assert(isValidDchar(c)); - } - body - { - s ~= c; - } - -/** -Returns the code length of $(D c) in the encoding using $(D C) as a -code point. The code is returned in character count, not in bytes. - */ - -ubyte codeLength(C)(dchar c) -{ - - static if (C.sizeof == 1) - { - return - c <= 0x7F ? 1 - : c <= 0x7FF ? 2 - : c <= 0xFFFF ? 3 - : c <= 0x10FFFF ? 4 - : (assert(false), 6); -} - - else static if (C.sizeof == 2) -{ - return c <= 0xFFFF ? 1 : 2; - } - else - { - static assert(C.sizeof == 4); - return 1; - } -} - -/* =================== Validation ======================= */ - -/*********************************** -Checks to see if string is well formed or not. $(D S) can be an array - of $(D char), $(D wchar), or $(D dchar). Throws a $(D UtfException) - if it is not. Use to check all untrusted input for correctness. - */ -void validate(S)(in S s) -{ - auto len = s.length; - for (size_t i = 0; i < len; ) - { - decode(s, i); - } -} - -/* =================== Conversion to UTF8 ======================= */ - -char[] toUTF8(char[4] buf, dchar c) - in - { - assert(isValidDchar(c)); - } - body - { - if (c <= 0x7F) - { - buf[0] = cast(char) c; - return buf[0 .. 1]; - } - else if (c <= 0x7FF) - { - buf[0] = cast(char)(0xC0 | (c >> 6)); - buf[1] = cast(char)(0x80 | (c & 0x3F)); - return buf[0 .. 2]; - } - else if (c <= 0xFFFF) - { - buf[0] = cast(char)(0xE0 | (c >> 12)); - buf[1] = cast(char)(0x80 | ((c >> 6) & 0x3F)); - buf[2] = cast(char)(0x80 | (c & 0x3F)); - return buf[0 .. 3]; - } - else if (c <= 0x10FFFF) - { - buf[0] = cast(char)(0xF0 | (c >> 18)); - buf[1] = cast(char)(0x80 | ((c >> 12) & 0x3F)); - buf[2] = cast(char)(0x80 | ((c >> 6) & 0x3F)); - buf[3] = cast(char)(0x80 | (c & 0x3F)); - return buf[0 .. 4]; - } - assert(0); - } - -/******************* - * Encodes string s into UTF-8 and returns the encoded string. - */ -string toUTF8(string s) - in - { - validate(s); - } - body - { - return s; - } - -/** ditto */ -string toUTF8(in wchar[] s) -{ - char[] r; - size_t i; - size_t slen = s.length; - - r.length = slen; - - for (i = 0; i < slen; i++) - { wchar c = s[i]; - - if (c <= 0x7F) - r[i] = cast(char)c; // fast path for ascii - else - { - r.length = i; - foreach (dchar c; s[i .. slen]) - { - encode(r, c); - } - break; - } - } - return cast(string)r; -} - -/** ditto */ -string toUTF8(in dchar[] s) -{ - char[] r; - size_t i; - size_t slen = s.length; - - r.length = slen; - - for (i = 0; i < slen; i++) - { dchar c = s[i]; - - if (c <= 0x7F) - r[i] = cast(char)c; // fast path for ascii - else - { - r.length = i; - foreach (dchar d; s[i .. slen]) - { - encode(r, d); - } - break; - } - } - return cast(string)r; -} - -/* =================== Conversion to UTF16 ======================= */ - -wchar[] toUTF16(wchar[2] buf, dchar c) - in - { - assert(isValidDchar(c)); - } - body - { - if (c <= 0xFFFF) - { - buf[0] = cast(wchar) c; - return buf[0 .. 1]; - } - else - { - buf[0] = cast(wchar) ((((c - 0x10000) >> 10) & 0x3FF) + 0xD800); - buf[1] = cast(wchar) (((c - 0x10000) & 0x3FF) + 0xDC00); - return buf[0 .. 2]; - } - } - -/**************** - * Encodes string s into UTF-16 and returns the encoded string. - * toUTF16z() is suitable for calling the 'W' functions in the Win32 API that take - * an LPWSTR or LPCWSTR argument. - */ -wstring toUTF16(in char[] s) -{ - wchar[] r; - size_t slen = s.length; - - r.length = slen; - r.length = 0; - for (size_t i = 0; i < slen; ) - { - dchar c = s[i]; - if (c <= 0x7F) - { - i++; - r ~= cast(wchar)c; - } - else - { - c = decode(s, i); - encode(r, c); - } - } - return cast(wstring)r; -} - -alias const(wchar)* wptr; -/** ditto */ -wptr toUTF16z(in char[] s) -{ - wchar[] r; - size_t slen = s.length; - - r.length = slen + 1; - r.length = 0; - for (size_t i = 0; i < slen; ) - { - dchar c = s[i]; - if (c <= 0x7F) - { - i++; - r ~= cast(wchar)c; - } - else - { - c = decode(s, i); - encode(r, c); - } - } - r ~= "\000"; - return r.ptr; -} - -/** ditto */ -wstring toUTF16(wstring s) - in - { - validate(s); - } - body - { - return s; - } - -/** ditto */ -wstring toUTF16(in dchar[] s) -{ - wchar[] r; - size_t slen = s.length; - - r.length = slen; - r.length = 0; - for (size_t i = 0; i < slen; i++) - { - encode(r, s[i]); - } - return cast(wstring)r; -} - -/* =================== Conversion to UTF32 ======================= */ - -/***** - * Encodes string s into UTF-32 and returns the encoded string. - */ -dstring toUTF32(in char[] s) -{ - dchar[] r; - size_t slen = s.length; - size_t j = 0; - - r.length = slen; // r[] will never be longer than s[] - for (size_t i = 0; i < slen; ) - { - dchar c = s[i]; - if (c >= 0x80) - c = decode(s, i); - else - i++; // c is ascii, no need for decode - r[j++] = c; - } - return cast(dstring)r[0 .. j]; -} - -/** ditto */ -dstring toUTF32(in wchar[] s) -{ - dchar[] r; - size_t slen = s.length; - size_t j = 0; - - r.length = slen; // r[] will never be longer than s[] - for (size_t i = 0; i < slen; ) - { - dchar c = s[i]; - if (c >= 0x80) - c = decode(s, i); - else - i++; // c is ascii, no need for decode - r[j++] = c; - } - return cast(dstring)r[0 .. j]; -} - -/** ditto */ -dstring toUTF32(dstring s) - in - { - validate(s); - } - body - { - return s; - } - -/* ================================ tests ================================== */ - -unittest -{ - debug(utf) printf("utf.toUTF.unittest\n"); - - auto c = "hello"c[]; - auto w = toUTF16(c); - assert(w == "hello"); - auto d = toUTF32(c); - assert(d == "hello"); - - c = toUTF8(w); - assert(c == "hello"); - d = toUTF32(w); - assert(d == "hello"); - - c = toUTF8(d); - assert(c == "hello"); - w = toUTF16(d); - assert(w == "hello"); - - - c = "hel\u1234o"; - w = toUTF16(c); - assert(w == "hel\u1234o"); - d = toUTF32(c); - assert(d == "hel\u1234o"); - - c = toUTF8(w); - assert(c == "hel\u1234o"); - d = toUTF32(w); - assert(d == "hel\u1234o"); - - c = toUTF8(d); - assert(c == "hel\u1234o"); - w = toUTF16(d); - assert(w == "hel\u1234o"); - - - c = "he\U0010AAAAllo"; - w = toUTF16(c); - //foreach (wchar c; w) printf("c = x%x\n", c); - //foreach (wchar c; cast(wstring)"he\U0010AAAAllo") printf("c = x%x\n", c); - assert(w == "he\U0010AAAAllo"); - d = toUTF32(c); - assert(d == "he\U0010AAAAllo"); - - c = toUTF8(w); - assert(c == "he\U0010AAAAllo"); - d = toUTF32(w); - assert(d == "he\U0010AAAAllo"); - - c = toUTF8(d); - assert(c == "he\U0010AAAAllo"); - w = toUTF16(d); - assert(w == "he\U0010AAAAllo"); -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/compiler/ldc/win32.mak --- a/druntime/src/compiler/ldc/win32.mak Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,175 +0,0 @@ -# Makefile to build the D runtime library core components for Posix -# Designed to work with GNU make -# Targets: -# make -# Same as make all -# make debug -# Build the debug version of the library -# make release -# Build the release version of the library -# make doc -# Generate documentation -# make clean -# Delete all files created by build process - -# Essentials - -LIBDIR=..\..\..\lib -DOCDIR=..\..\..\doc -IMPDIR=..\..\..\import -LIBBASENAME=druntime_rt_dmd.lib -#MODULES=bitop exception memory runtime thread vararg \ -# $(addprefix sync/,barrier condition config exception mutex rwmutex semaphore) -BUILDS=debug release unittest - -MODULES_BASE= \ - aaA.d \ - aApply.d \ - aApplyR.d \ - adi.d \ - arrayassign.d \ - arraybyte.d \ - arraycast.d \ - arraycat.d \ - arraydouble.d \ - arrayfloat.d \ - arrayint.d \ - arrayreal.d \ - arrayshort.d \ - cast_.d \ - cover.d \ - dmain2.d \ - invariant.d \ - invariant_.d \ - lifetime.d \ - memory.d \ - memset.d \ - obj.d \ - object_.d \ - qsort.d \ - switch_.d \ - trace.d -# NOTE: trace.d and cover.d are not necessary for a successful build -# as both are used for debugging features (profiling and coverage) -# NOTE: a pre-compiled minit.obj has been provided in dmd for Win32 and -# minit.asm is not used by dmd for Linux - -MODULES_UTIL= \ - util\console.d \ - util\cpuid.d \ - util\ctype.d \ - util\string.d \ - util\utf.d - -MODULES_TI= \ - typeinfo\ti_AC.d \ - typeinfo\ti_Acdouble.d \ - typeinfo\ti_Acfloat.d \ - typeinfo\ti_Acreal.d \ - typeinfo\ti_Adouble.d \ - typeinfo\ti_Afloat.d \ - typeinfo\ti_Ag.d \ - typeinfo\ti_Aint.d \ - typeinfo\ti_Along.d \ - typeinfo\ti_Areal.d \ - typeinfo\ti_Ashort.d \ - typeinfo\ti_byte.d \ - typeinfo\ti_C.d \ - typeinfo\ti_cdouble.d \ - typeinfo\ti_cfloat.d \ - typeinfo\ti_char.d \ - typeinfo\ti_creal.d \ - typeinfo\ti_dchar.d \ - typeinfo\ti_delegate.d \ - typeinfo\ti_double.d \ - typeinfo\ti_float.d \ - typeinfo\ti_idouble.d \ - typeinfo\ti_ifloat.d \ - typeinfo\ti_int.d \ - typeinfo\ti_ireal.d \ - typeinfo\ti_long.d \ - typeinfo\ti_ptr.d \ - typeinfo\ti_real.d \ - typeinfo\ti_short.d \ - typeinfo\ti_ubyte.d \ - typeinfo\ti_uint.d \ - typeinfo\ti_ulong.d \ - typeinfo\ti_ushort.d \ - typeinfo\ti_void.d \ - typeinfo\ti_wchar.d - -C_SRCS=complex.c critical.c deh.c monitor.c - -# Symbols - -CC=dmc -DMD=dmd -DOCFLAGS=-version=DDoc -DFLAGS_release=-d -release -O -inline -w -nofloat -DFLAGS_debug=-d -g -w -nofloat -DFLAGS_unittest=$(DFLAGS_release) -unittest -CFLAGS_release=-mn -6 -r -CFLAGS_debug=-g -mn -6 -r -CFLAGS_unittest=$(CFLAGS_release) - -# Derived symbols - -C_OBJS=complex.obj critical.obj deh.obj monitor.obj -AS_OBJS=minit.obj -ALL_MODULES=$(MODULES_BASE) $(MODULES_UTIL) $(MODULES_TI) -D_SRCS=$(ALL_MODULES) -ALLLIBS=\ - $(LIBDIR)\debug\$(LIBBASENAME) \ - $(LIBDIR)\release\$(LIBBASENAME) \ - $(LIBDIR)\unittest\$(LIBBASENAME) - -# Patterns - -#$(LIBDIR)\%\$(LIBBASENAME) : $(D_SRCS) $(C_SRCS) $(AS_OBJS) -# $(CC) -c $(CFLAGS_$*) $(C_SRCS) -# $(DMD) $(DFLAGS_$*) -lib -of$@ $(D_SRCS) $(C_OBJS) $(AS_OBJS) -# del $(C_OBJS) - -#$(DOCDIR)\%.html : %.d -# $(DMD) -c -d -o- -Df$@ $< - -#$(IMPDIR)\%.di : %.d -# $(DMD) -c -d -o- -Hf$@ $< - -# Patterns - debug - -$(LIBDIR)\debug\$(LIBBASENAME) : $(D_SRCS) $(C_SRCS) $(AS_OBJS) - $(CC) -c $(CFLAGS_debug) $(C_SRCS) - $(DMD) $(DFLAGS_debug) -lib -of$@ $(D_SRCS) $(C_OBJS) $(AS_OBJS) - del $(C_OBJS) - -# Patterns - release - -$(LIBDIR)\release\$(LIBBASENAME) : $(D_SRCS) $(C_SRCS) $(AS_OBJS) - $(CC) -c $(CFLAGS_release) $(C_SRCS) - $(DMD) $(DFLAGS_release) -lib -of$@ $(D_SRCS) $(C_OBJS) $(AS_OBJS) - del $(C_OBJS) - -# Patterns - unittest - -$(LIBDIR)\unittest\$(LIBBASENAME) : $(D_SRCS) $(C_SRCS) $(AS_OBJS) - $(CC) -c $(CFLAGS_unittest) $(C_SRCS) - $(DMD) $(DFLAGS_unittest) -lib -of$@ $(D_SRCS) $(C_OBJS) $(AS_OBJS) - del $(C_OBJS) - -# Patterns - asm - -minit.obj : minit.asm - $(CC) -c $** - -# Rulez - -all : $(BUILDS) doc - -debug : $(LIBDIR)\debug\$(LIBBASENAME) $(IMPORTS) -release : $(LIBDIR)\release\$(LIBBASENAME) $(IMPORTS) -unittest : $(LIBDIR)\unittest\$(LIBBASENAME) $(IMPORTS) -#doc : $(DOCS) - -clean : - del $(IMPORTS) $(DOCS) $(ALLLIBS) diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/dmd-posix.mak --- a/druntime/src/dmd-posix.mak Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -# Makefile to build the composite D runtime library for Linux -# Designed to work with GNU make -# Targets: -# make -# Same as make all -# make debug -# Build the debug version of the library -# make release -# Build the release version of the library -# make doc -# Generate documentation -# make clean -# Delete all files created by build process - -# Essentials - -LIBDIR:=../lib -DOCDIR:=../doc -LIBBASENAME=libdruntime.a - -DIR_CC=common -DIR_RT=compiler/dmd -DIR_GC=gc/basic - -# Symbols - -DMD=dmd - -# Targets - -all : debug release doc unittest $(LIBDIR)/$(LIBBASENAME) - -# unittest : -# $(MAKE) -fdmd-posix.mak lib MAKE_LIB="unittest" -# dmd -unittest unittest ../import/core/stdc/stdarg \ -# -defaultlib="$(DUP_TARGET)" -debuglib="$(DUP_TARGET)" -# $(RM) stdarg.o -# ./unittest - -debug release unittest : - @$(MAKE) DMD=$(DMD) -C $(DIR_CC) --no-print-directory -fposix.mak $@ - @$(MAKE) DMD=$(DMD) -C $(DIR_RT) --no-print-directory -fposix.mak $@ - @$(MAKE) DMD=$(DMD) -C $(DIR_GC) --no-print-directory -fposix.mak $@ - @$(DMD) -lib -of$(LIBDIR)/$@/$(LIBBASENAME) \ - $(LIBDIR)/$@/libdruntime-core.a \ - $(LIBDIR)/$@/libdruntime-rt-dmd.a \ - $(LIBDIR)/$@/libdruntime-gc-basic.a - -$(LIBDIR)/$(LIBBASENAME) : $(LIBDIR)/release/$(LIBBASENAME) - ln -sf $(realpath $<) $@ - -doc : $(ALL_DOCS) - $(MAKE) DMD=$(DMD) -C $(DIR_CC) --no-print-directory -fposix.mak doc -# $(MAKE) DMD=$(DMD) -C $(DIR_RT) --no-print-directory -fposix.mak doc -# $(MAKE) DMD=$(DMD) -C $(DIR_GC) --no-print-directory -fposix.mak doc - -###################################################### - -clean : - $(MAKE) DMD=$(DMD) -C $(DIR_CC) --no-print-directory -fposix.mak clean - $(MAKE) DMD=$(DMD) -C $(DIR_RT) --no-print-directory -fposix.mak clean - $(MAKE) DMD=$(DMD) -C $(DIR_GC) --no-print-directory -fposix.mak clean -#find . -name "*.di" | xargs $(RM) - rm -rf $(LIBDIR) $(DOCDIR) - -# install : -# make -C $(DIR_CC) --no-print-directory -fposix.mak install -# make -C $(DIR_RT) --no-print-directory -fposix.mak install -# make -C $(DIR_GC) --no-print-directory -fposix.mak install -# $(CP) $(LIB_MASK) $(LIB_DEST)/. -# $(CP) $(DUP_MASK) $(LIB_DEST)/. - diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/dmd-win32.mak --- a/druntime/src/dmd-win32.mak Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,89 +0,0 @@ -# Makefile to build the composite D runtime library for Linux -# Designed to work with GNU make -# Targets: -# make -# Same as make all -# make debug -# Build the debug version of the library -# make release -# Build the release version of the library -# make doc -# Generate documentation -# make clean -# Delete all files created by build process - -# Essentials - -LIBDIR=..\lib -DOCDIR=..\doc -LIBBASENAME=druntime.lib - -DIR_CC=common -DIR_RT=compiler\dmd -DIR_GC=gc\basic - -# Symbols - -DMD=dmd - -# Targets - -all : debug release doc unittest $(LIBDIR)\$(LIBBASENAME) - -# unittest : -# $(MAKE) -fdmd-posix.mak lib MAKE_LIB="unittest" -# dmd -unittest unittest ../import/core/stdc/stdarg \ -# -defaultlib="$(DUP_TARGET)" -debuglib="$(DUP_TARGET)" -# $(RM) stdarg.o -# ./unittest - -debug release unittest : - cd $(DIR_CC) - make DMD=$(DMD) -fwin32.mak $@ - cd .. - cd $(DIR_RT) - make DMD=$(DMD) -fwin32.mak $@ - cd ..\.. - cd $(DIR_GC) - make DMD=$(DMD) -fwin32.mak $@ - cd ..\.. - $(DMD) -lib -of$(LIBDIR)\$@\$(LIBBASENAME) \ - $(LIBDIR)\$@\druntime_core.lib \ - $(LIBDIR)\$@\druntime_rt_dmd.lib \ - $(LIBDIR)\$@\druntime_gc_basic.lib - -$(LIBDIR)\$(LIBBASENAME) : $(LIBDIR)\release\$(LIBBASENAME) - copy /y $** $@ - -doc : $(ALL_DOCS) - cd $(DIR_CC) - make DMD=$(DMD) -fwin32.mak $@ - cd .. -# cd $(DIR_RT) -# make DMD=$(DMD) -fwin32.mak $@ -# cd ..\.. -# cd $(DIR_GC) -# make DMD=$(DMD) -fwin32.mak $@ -# cd ..\.. - -###################################################### - -clean : $(ALL_DOCS) - cd $(DIR_CC) - make DMD=$(DMD) -fwin32.mak $@ - cd .. - cd $(DIR_RT) - make DMD=$(DMD) -fwin32.mak $@ - cd ..\.. - cd $(DIR_GC) - make DMD=$(DMD) -fwin32.mak $@ - cd ..\.. -#find . -name "*.di" | xargs $(RM) -#rm -rf $(LIBDIR) $(DOCDIR) - -# install : -# make -C $(DIR_CC) --no-print-directory -fposix.mak install -# make -C $(DIR_RT) --no-print-directory -fposix.mak install -# make -C $(DIR_GC) --no-print-directory -fposix.mak install -# $(CP) $(LIB_MASK) $(LIB_DEST)\. -# $(CP) $(DUP_MASK) $(LIB_DEST)\. diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/dmd.conf --- a/druntime/src/dmd.conf Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -[Environment] -DFLAGS="-I%HOME%/common" "-I%HOME%/../import" diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/gc/basic/gc.d --- a/druntime/src/gc/basic/gc.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,315 +0,0 @@ -/** - * Contains the external GC interface. - * - * Copyright: Copyright Digital Mars 2005 - 2009. - * License: Boost License 1.0. - * Authors: Walter Bright, David Friedman, Sean Kelly - * - * Copyright Digital Mars 2005 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module gc.gcalloc; - - -version (Windows) -{ - private import core.sys.windows.windows; - - alias int pthread_t; - - pthread_t pthread_self() - { - return cast(pthread_t) GetCurrentThreadId(); - } - - //version = GC_Use_Alloc_Win32; -} -else version (Posix) -{ - private import core.sys.posix.sys.mman; - private import core.stdc.stdlib; - - //version = GC_Use_Alloc_MMap; -} -else -{ - private import core.stdc.stdlib; - - //version = GC_Use_Alloc_Malloc; -} - -/+ -static if(is(typeof(VirtualAlloc))) - version = GC_Use_Alloc_Win32; -else static if (is(typeof(mmap))) - version = GC_Use_Alloc_MMap; -else static if (is(typeof(valloc))) - version = GC_Use_Alloc_Valloc; -else static if (is(typeof(malloc))) - version = GC_Use_Alloc_Malloc; -else static assert(false, "No supported allocation methods available."); -+/ - -static if (is(typeof(VirtualAlloc))) // version (GC_Use_Alloc_Win32) -{ - /** - * Map memory. - */ - void *os_mem_map(size_t nbytes) - { - return VirtualAlloc(null, nbytes, MEM_RESERVE, PAGE_READWRITE); - } - - - /** - * Commit memory. - * Returns: - * 0 success - * !=0 failure - */ - int os_mem_commit(void *base, size_t offset, size_t nbytes) - { void *p; - - p = VirtualAlloc(base + offset, nbytes, MEM_COMMIT, PAGE_READWRITE); - return cast(int)(p is null); - } - - - /** - * Decommit memory. - * Returns: - * 0 success - * !=0 failure - */ - int os_mem_decommit(void *base, size_t offset, size_t nbytes) - { - return cast(int)(VirtualFree(base + offset, nbytes, MEM_DECOMMIT) == 0); - } - - - /** - * Unmap memory allocated with os_mem_map(). - * Memory must have already been decommitted. - * Returns: - * 0 success - * !=0 failure - */ - int os_mem_unmap(void *base, size_t nbytes) - { - return cast(int)(VirtualFree(base, 0, MEM_RELEASE) == 0); - } -} -else static if (is(typeof(mmap))) // else version (GC_Use_Alloc_MMap) -{ - void *os_mem_map(size_t nbytes) - { void *p; - - p = mmap(null, nbytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); - return (p == MAP_FAILED) ? null : p; - } - - - int os_mem_commit(void *base, size_t offset, size_t nbytes) - { - return 0; - } - - - int os_mem_decommit(void *base, size_t offset, size_t nbytes) - { - return 0; - } - - - int os_mem_unmap(void *base, size_t nbytes) - { - return munmap(base, nbytes); - } -} -else static if (is(typeof(valloc))) // else version (GC_Use_Alloc_Valloc) -{ - void *os_mem_map(size_t nbytes) - { - return valloc(nbytes); - } - - - int os_mem_commit(void *base, size_t offset, size_t nbytes) - { - return 0; - } - - - int os_mem_decommit(void *base, size_t offset, size_t nbytes) - { - return 0; - } - - - int os_mem_unmap(void *base, size_t nbytes) - { - free(base); - return 0; - } -} -else static if (is(typeof(malloc))) // else version (GC_Use_Alloc_Malloc) -{ - // NOTE: This assumes malloc granularity is at least (void*).sizeof. If - // (req_size + PAGESIZE) is allocated, and the pointer is rounded up - // to PAGESIZE alignment, there will be space for a void* at the end - // after PAGESIZE bytes used by the GC. - - - private import gcx : PAGESIZE; - - - const size_t PAGE_MASK = PAGESIZE - 1; - - - void *os_mem_map(size_t nbytes) - { byte *p, q; - p = cast(byte *) malloc(nbytes + PAGESIZE); - q = p + ((PAGESIZE - ((cast(size_t) p & PAGE_MASK))) & PAGE_MASK); - * cast(void**)(q + nbytes) = p; - return q; - } - - - int os_mem_commit(void *base, size_t offset, size_t nbytes) - { - return 0; - } - - - int os_mem_decommit(void *base, size_t offset, size_t nbytes) - { - return 0; - } - - - int os_mem_unmap(void *base, size_t nbytes) - { - free( *cast(void**)( cast(byte*) base + nbytes ) ); - return 0; - } -} -else -{ - static assert(false, "No supported allocation methods available."); -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/gc/basic/gcbits.d --- a/druntime/src/gc/basic/gcbits.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,193 +0,0 @@ -/** - * Contains a bitfield used by the GC. - * - * Copyright: Copyright Digital Mars 2005 - 2009. - * License: Boost License 1.0. - * Authors: Walter Bright, Sean Kelly - * - * Copyright Digital Mars 2005 - 2009. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ -module gc.gcstats; - - -/** - * - */ -struct GCStats -{ - size_t poolsize; // total size of pool - size_t usedsize; // bytes allocated - size_t freeblocks; // number of blocks marked FREE - size_t freelistsize; // total of memory on free lists - size_t pageblocks; // number of blocks marked PAGE -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/gc/basic/gcx.d --- a/druntime/src/gc/basic/gcx.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3010 +0,0 @@ -/** - * Contains the garbage collector implementation. - * - * Copyright: Copyright Digital Mars 2001 - 2009. - * License: 0); - gcx.disabled--; - } - else synchronized (gcLock) - { - assert(gcx.disabled > 0); - gcx.disabled--; - } - } - - - /** - * - */ - void disable() - { - if (!thread_needLock()) - { - gcx.disabled++; - } - else synchronized (gcLock) - { - gcx.disabled++; - } - } - - - /** - * - */ - uint getAttr(void* p) - { - if (!p) - { - return 0; - } - - uint go() - { - Pool* pool = gcx.findPool(p); - uint oldb = 0; - - if (pool) - { - auto biti = cast(size_t)(p - pool.baseAddr) / 16; - - oldb = gcx.getBits(pool, biti); - } - return oldb; - } - - if (!thread_needLock()) - { - return go(); - } - else synchronized (gcLock) - { - return go(); - } - } - - - /** - * - */ - uint setAttr(void* p, uint mask) - { - if (!p) - { - return 0; - } - - uint go() - { - Pool* pool = gcx.findPool(p); - uint oldb = 0; - - if (pool) - { - auto biti = cast(size_t)(p - pool.baseAddr) / 16; - - oldb = gcx.getBits(pool, biti); - gcx.setBits(pool, biti, mask); - } - return oldb; - } - - if (!thread_needLock()) - { - return go(); - } - else synchronized (gcLock) - { - return go(); - } - } - - - /** - * - */ - uint clrAttr(void* p, uint mask) - { - if (!p) - { - return 0; - } - - uint go() - { - Pool* pool = gcx.findPool(p); - uint oldb = 0; - - if (pool) - { - auto biti = cast(size_t)(p - pool.baseAddr) / 16; - - oldb = gcx.getBits(pool, biti); - gcx.clrBits(pool, biti, mask); - } - return oldb; - } - - if (!thread_needLock()) - { - return go(); - } - else synchronized (gcLock) - { - return go(); - } - } - - - /** - * - */ - void *malloc(size_t size, uint bits = 0) - { - if (!size) - { - return null; - } - - // Since a finalizer could launch a new thread, we always need to lock - // when collecting. The safest way to do this is to simply always lock - // when allocating. - synchronized (gcLock) - { - return mallocNoSync(size, bits); - } - } - - - // - // - // - private void *mallocNoSync(size_t size, uint bits = 0) - { - assert(size != 0); - - void *p = null; - Bins bin; - - //debug(PRINTF) printf("GC::malloc(size = %d, gcx = %p)\n", size, gcx); - assert(gcx); - //debug(PRINTF) printf("gcx.self = %x, pthread_self() = %x\n", gcx.self, pthread_self()); - - size += SENTINEL_EXTRA; - - // Compute size bin - // Cache previous binsize lookup - Dave Fladebo. - __gshared size_t lastsize = -1; - __gshared Bins lastbin; - if (size == lastsize) - bin = lastbin; - else - { - bin = gcx.findBin(size); - lastsize = size; - lastbin = bin; - } - - if (bin < B_PAGE) - { - int state = gcx.disabled ? 1 : 0; - bool collected = false; - - while (!gcx.bucket[bin] && !gcx.allocPage(bin)) - { - switch (state) - { - case 0: - gcx.fullcollectshell(); - collected = true; - state = 1; - continue; - case 1: - gcx.newPool(1); - state = 2; - continue; - case 2: - if (collected) - onOutOfMemoryError(); - state = 0; - continue; - default: - assert(false); - } - } - p = gcx.bucket[bin]; - - // Return next item from free list - gcx.bucket[bin] = (cast(List*)p).next; - if( !(bits & BlkAttr.NO_SCAN) ) - memset(p + size, 0, binsize[bin] - size); - //debug(PRINTF) printf("\tmalloc => %x\n", p); - debug (MEMSTOMP) memset(p, 0xF0, size); - } - else - { - p = gcx.bigAlloc(size); - if (!p) - onOutOfMemoryError(); - } - size -= SENTINEL_EXTRA; - p = sentinel_add(p); - sentinel_init(p, size); - gcx.log_malloc(p, size); - - if (bits) - { - Pool *pool = gcx.findPool(p); - assert(pool); - - gcx.setBits(pool, cast(size_t)(p - pool.baseAddr) / 16, bits); - } - return p; - } - - - /** - * - */ - void *calloc(size_t size, uint bits = 0) - { - if (!size) - { - return null; - } - - // Since a finalizer could launch a new thread, we always need to lock - // when collecting. The safest way to do this is to simply always lock - // when allocating. - synchronized (gcLock) - { - return callocNoSync(size, bits); - } - } - - - // - // - // - private void *callocNoSync(size_t size, uint bits = 0) - { - assert(size != 0); - - //debug(PRINTF) printf("calloc: %x len %d\n", p, len); - void *p = mallocNoSync(size, bits); - memset(p, 0, size); - return p; - } - - - /** - * - */ - void *realloc(void *p, size_t size, uint bits = 0) - { - // Since a finalizer could launch a new thread, we always need to lock - // when collecting. The safest way to do this is to simply always lock - // when allocating. - synchronized (gcLock) - { - return reallocNoSync(p, size, bits); - } - } - - - // - // - // - private void *reallocNoSync(void *p, size_t size, uint bits = 0) - { - if (!size) - { if (p) - { freeNoSync(p); - p = null; - } - } - else if (!p) - { - p = mallocNoSync(size, bits); - } - else - { void *p2; - size_t psize; - - //debug(PRINTF) printf("GC::realloc(p = %x, size = %u)\n", p, size); - version (SENTINEL) - { - sentinel_Invariant(p); - psize = *sentinel_size(p); - if (psize != size) - { - if (psize) - { - Pool *pool = gcx.findPool(p); - - if (pool) - { - auto biti = cast(size_t)(p - pool.baseAddr) / 16; - - if (bits) - { - gcx.clrBits(pool, biti, BlkAttr.ALL_BITS); - gcx.setBits(pool, biti, bits); - } - else - { - bits = gcx.getBits(pool, biti); - } - } - } - p2 = mallocNoSync(size, bits); - if (psize < size) - size = psize; - //debug(PRINTF) printf("\tcopying %d bytes\n",size); - memcpy(p2, p, size); - p = p2; - } - } - else - { - psize = gcx.findSize(p); // find allocated size - if (psize >= PAGESIZE && size >= PAGESIZE) - { - auto psz = psize / PAGESIZE; - auto newsz = (size + PAGESIZE - 1) / PAGESIZE; - if (newsz == psz) - return p; - - auto pool = gcx.findPool(p); - auto pagenum = (p - pool.baseAddr) / PAGESIZE; - - if (newsz < psz) - { // Shrink in place - synchronized (gcLock) - { - debug (MEMSTOMP) memset(p + size, 0xF2, psize - size); - pool.freePages(pagenum + newsz, psz - newsz); - } - return p; - } - else if (pagenum + newsz <= pool.npages) - { - // Attempt to expand in place - synchronized (gcLock) - { - for (size_t i = pagenum + psz; 1;) - { - if (i == pagenum + newsz) - { - debug (MEMSTOMP) memset(p + psize, 0xF0, size - psize); - memset(&pool.pagetable[pagenum + psz], B_PAGEPLUS, newsz - psz); - return p; - } - if (i == pool.ncommitted) - { - auto u = pool.extendPages(pagenum + newsz - pool.ncommitted); - if (u == OPFAIL) - break; - i = pagenum + newsz; - continue; - } - if (pool.pagetable[i] != B_FREE) - break; - i++; - } - } - } - } - if (psize < size || // if new size is bigger - psize > size * 2) // or less than half - { - if (psize) - { - Pool *pool = gcx.findPool(p); - - if (pool) - { - auto biti = cast(size_t)(p - pool.baseAddr) / 16; - - if (bits) - { - gcx.clrBits(pool, biti, BlkAttr.ALL_BITS); - gcx.setBits(pool, biti, bits); - } - else - { - bits = gcx.getBits(pool, biti); - } - } - } - p2 = mallocNoSync(size, bits); - if (psize < size) - size = psize; - //debug(PRINTF) printf("\tcopying %d bytes\n",size); - memcpy(p2, p, size); - p = p2; - } - } - } - return p; - } - - - /** - * Attempt to in-place enlarge the memory block pointed to by p by at least - * minbytes beyond its current capacity, up to a maximum of maxsize. This - * does not attempt to move the memory block (like realloc() does). - * - * Returns: - * 0 if could not extend p, - * total size of entire memory block if successful. - */ - size_t extend(void* p, size_t minsize, size_t maxsize) - { - if (!thread_needLock()) - { - return extendNoSync(p, minsize, maxsize); - } - else synchronized (gcLock) - { - return extendNoSync(p, minsize, maxsize); - } - } - - - // - // - // - private size_t extendNoSync(void* p, size_t minsize, size_t maxsize) - in - { - assert( minsize <= maxsize ); - } - body - { - //debug(PRINTF) printf("GC::extend(p = %x, minsize = %u, maxsize = %u)\n", p, minsize, maxsize); - version (SENTINEL) - { - return 0; - } - auto psize = gcx.findSize(p); // find allocated size - if (psize < PAGESIZE) - return 0; // cannot extend buckets - - auto psz = psize / PAGESIZE; - auto minsz = (minsize + PAGESIZE - 1) / PAGESIZE; - auto maxsz = (maxsize + PAGESIZE - 1) / PAGESIZE; - - auto pool = gcx.findPool(p); - auto pagenum = (p - pool.baseAddr) / PAGESIZE; - - size_t sz; - for (sz = 0; sz < maxsz; sz++) - { - auto i = pagenum + psz + sz; - if (i == pool.ncommitted) - break; - if (pool.pagetable[i] != B_FREE) - { if (sz < minsz) - return 0; - break; - } - } - if (sz >= minsz) - { - } - else if (pagenum + psz + sz == pool.ncommitted) - { - auto u = pool.extendPages(minsz - sz); - if (u == OPFAIL) - return 0; - sz = minsz; - } - else - return 0; - debug (MEMSTOMP) memset(p + psize, 0xF0, (psz + sz) * PAGESIZE - psize); - memset(pool.pagetable + pagenum + psz, B_PAGEPLUS, sz); - gcx.p_cache = null; - gcx.size_cache = 0; - return (psz + sz) * PAGESIZE; - } - - - /** - * - */ - size_t reserve(size_t size) - { - if (!size) - { - return 0; - } - - if (!thread_needLock()) - { - return reserveNoSync(size); - } - else synchronized (gcLock) - { - return reserveNoSync(size); - } - } - - - // - // - // - private size_t reserveNoSync(size_t size) - { - assert(size != 0); - assert(gcx); - - return gcx.reserve(size); - } - - - /** - * - */ - void free(void *p) - { - if (!p) - { - return; - } - - if (!thread_needLock()) - { - return freeNoSync(p); - } - else synchronized (gcLock) - { - return freeNoSync(p); - } - } - - - // - // - // - private void freeNoSync(void *p) - { - assert (p); - - Pool* pool; - size_t pagenum; - Bins bin; - size_t biti; - - // Find which page it is in - pool = gcx.findPool(p); - if (!pool) // if not one of ours - return; // ignore - sentinel_Invariant(p); - p = sentinel_sub(p); - pagenum = cast(size_t)(p - pool.baseAddr) / PAGESIZE; - biti = cast(size_t)(p - pool.baseAddr) / 16; - gcx.clrBits(pool, biti, BlkAttr.ALL_BITS); - - bin = cast(Bins)pool.pagetable[pagenum]; - if (bin == B_PAGE) // if large alloc - { size_t npages; - size_t n; - - // Free pages - npages = 1; - n = pagenum; - while (++n < pool.ncommitted && pool.pagetable[n] == B_PAGEPLUS) - npages++; - debug (MEMSTOMP) memset(p, 0xF2, npages * PAGESIZE); - pool.freePages(pagenum, npages); - } - else - { // Add to free list - List *list = cast(List*)p; - - debug (MEMSTOMP) memset(p, 0xF2, binsize[bin]); - - list.next = gcx.bucket[bin]; - gcx.bucket[bin] = list; - } - gcx.log_free(sentinel_add(p)); - } - - - /** - * Determine the base address of the block containing p. If p is not a gc - * allocated pointer, return null. - */ - void* addrOf(void *p) - { - if (!p) - { - return null; - } - - if (!thread_needLock()) - { - return addrOfNoSync(p); - } - else synchronized (gcLock) - { - return addrOfNoSync(p); - } - } - - - // - // - // - void* addrOfNoSync(void *p) - { - if (!p) - { - return null; - } - - return gcx.findBase(p); - } - - - /** - * Determine the allocated size of pointer p. If p is an interior pointer - * or not a gc allocated pointer, return 0. - */ - size_t sizeOf(void *p) - { - if (!p) - { - return 0; - } - - if (!thread_needLock()) - { - return sizeOfNoSync(p); - } - else synchronized (gcLock) - { - return sizeOfNoSync(p); - } - } - - - // - // - // - private size_t sizeOfNoSync(void *p) - { - assert (p); - - version (SENTINEL) - { - p = sentinel_sub(p); - size_t size = gcx.findSize(p); - - // Check for interior pointer - // This depends on: - // 1) size is a power of 2 for less than PAGESIZE values - // 2) base of memory pool is aligned on PAGESIZE boundary - if (cast(size_t)p & (size - 1) & (PAGESIZE - 1)) - size = 0; - return size ? size - SENTINEL_EXTRA : 0; - } - else - { - if (p == gcx.p_cache) - return gcx.size_cache; - - size_t size = gcx.findSize(p); - - // Check for interior pointer - // This depends on: - // 1) size is a power of 2 for less than PAGESIZE values - // 2) base of memory pool is aligned on PAGESIZE boundary - if (cast(size_t)p & (size - 1) & (PAGESIZE - 1)) - size = 0; - else - { - gcx.p_cache = p; - gcx.size_cache = size; - } - - return size; - } - } - - - /** - * Determine the base address of the block containing p. If p is not a gc - * allocated pointer, return null. - */ - BlkInfo query(void *p) - { - if (!p) - { - BlkInfo i; - return i; - } - - if (!thread_needLock()) - { - return queryNoSync(p); - } - else synchronized (gcLock) - { - return queryNoSync(p); - } - } - - - // - // - // - BlkInfo queryNoSync(void *p) - { - assert(p); - - return gcx.getInfo(p); - } - - - /** - * Verify that pointer p: - * 1) belongs to this memory pool - * 2) points to the start of an allocated piece of memory - * 3) is not on a free list - */ - void check(void *p) - { - if (!p) - { - return; - } - - if (!thread_needLock()) - { - checkNoSync(p); - } - else synchronized (gcLock) - { - checkNoSync(p); - } - } - - - // - // - // - private void checkNoSync(void *p) - { - assert(p); - - sentinel_Invariant(p); - debug (PTRCHECK) - { - Pool* pool; - size_t pagenum; - Bins bin; - size_t size; - - p = sentinel_sub(p); - pool = gcx.findPool(p); - assert(pool); - pagenum = cast(size_t)(p - pool.baseAddr) / PAGESIZE; - bin = cast(Bins)pool.pagetable[pagenum]; - assert(bin <= B_PAGE); - size = binsize[bin]; - assert((cast(size_t)p & (size - 1)) == 0); - - debug (PTRCHECK2) - { - if (bin < B_PAGE) - { - // Check that p is not on a free list - List *list; - - for (list = gcx.bucket[bin]; list; list = list.next) - { - assert(cast(void*)list != p); - } - } - } - } - } - - - // - // - // - private void setStackBottom(void *p) - { - version (STACKGROWSDOWN) - { - //p = (void *)((uint *)p + 4); - if (p > gcx.stackBottom) - { - //debug(PRINTF) printf("setStackBottom(%x)\n", p); - gcx.stackBottom = p; - } - } - else - { - //p = (void *)((uint *)p - 4); - if (p < gcx.stackBottom) - { - //debug(PRINTF) printf("setStackBottom(%x)\n", p); - gcx.stackBottom = cast(char*)p; - } - } - } - - - /** - * add p to list of roots - */ - void addRoot(void *p) - { - if (!p) - { - return; - } - - if (!thread_needLock()) - { - gcx.addRoot(p); - } - else synchronized (gcLock) - { - gcx.addRoot(p); - } - } - - - /** - * remove p from list of roots - */ - void removeRoot(void *p) - { - if (!p) - { - return; - } - - if (!thread_needLock()) - { - gcx.removeRoot(p); - } - else synchronized (gcLock) - { - gcx.removeRoot(p); - } - } - - - /** - * - */ - int delegate(int delegate(inout void*)) rootIter() - { - if (!thread_needLock()) - { - return &gcx.rootIter; - } - else synchronized (gcLock) - { - return &gcx.rootIter; - } - } - - - /** - * add range to scan for roots - */ - void addRange(void *p, size_t sz) - { - if (!p || !sz) - { - return; - } - - //debug(PRINTF) printf("+GC.addRange(pbot = x%x, ptop = x%x)\n", pbot, ptop); - if (!thread_needLock()) - { - gcx.addRange(p, p + sz); - } - else synchronized (gcLock) - { - gcx.addRange(p, p + sz); - } - //debug(PRINTF) printf("-GC.addRange()\n"); - } - - - /** - * remove range - */ - void removeRange(void *p) - { - if (!p) - { - return; - } - - if (!thread_needLock()) - { - gcx.removeRange(p); - } - else synchronized (gcLock) - { - gcx.removeRange(p); - } - } - - - /** - * - */ - int delegate(int delegate(inout Range)) rangeIter() - { - if (!thread_needLock()) - { - return &gcx.rangeIter; - } - else synchronized (gcLock) - { - return &gcx.rangeIter; - } - } - - - /** - * do full garbage collection - */ - void fullCollect() - { - debug(PRINTF) printf("GC.fullCollect()\n"); - - // Since a finalizer could launch a new thread, we always need to lock - // when collecting. - synchronized (gcLock) - { - gcx.fullcollectshell(); - } - - version (none) - { - GCStats stats; - - getStats(stats); - debug(PRINTF) printf("poolsize = %x, usedsize = %x, freelistsize = %x\n", - stats.poolsize, stats.usedsize, stats.freelistsize); - } - - gcx.log_collect(); - } - - - /** - * do full garbage collection ignoring roots - */ - void fullCollectNoStack() - { - // Since a finalizer could launch a new thread, we always need to lock - // when collecting. - synchronized (gcLock) - { - gcx.noStack++; - gcx.fullcollectshell(); - gcx.noStack--; - } - } - - - /** - * minimize free space usage - */ - void minimize() - { - if (!thread_needLock()) - { - gcx.minimize(); - } - else synchronized (gcLock) - { - gcx.minimize(); - } - } - - - /** - * Retrieve statistics about garbage collection. - * Useful for debugging and tuning. - */ - void getStats(out GCStats stats) - { - if (!thread_needLock()) - { - getStatsNoSync(stats); - } - else synchronized (gcLock) - { - getStatsNoSync(stats); - } - } - - - // - // - // - private void getStatsNoSync(out GCStats stats) - { - size_t psize = 0; - size_t usize = 0; - size_t flsize = 0; - - size_t n; - size_t bsize = 0; - - //debug(PRINTF) printf("getStats()\n"); - memset(&stats, 0, GCStats.sizeof); - - for (n = 0; n < gcx.npools; n++) - { Pool *pool = gcx.pooltable[n]; - - psize += pool.ncommitted * PAGESIZE; - for (size_t j = 0; j < pool.ncommitted; j++) - { - Bins bin = cast(Bins)pool.pagetable[j]; - if (bin == B_FREE) - stats.freeblocks++; - else if (bin == B_PAGE) - stats.pageblocks++; - else if (bin < B_PAGE) - bsize += PAGESIZE; - } - } - - for (n = 0; n < B_PAGE; n++) - { - //debug(PRINTF) printf("bin %d\n", n); - for (List *list = gcx.bucket[n]; list; list = list.next) - { - //debug(PRINTF) printf("\tlist %x\n", list); - flsize += binsize[n]; - } - } - - usize = bsize - flsize; - - stats.poolsize = psize; - stats.usedsize = bsize - flsize; - stats.freelistsize = flsize; - } -} - - -/* ============================ Gcx =============================== */ - -enum -{ PAGESIZE = 4096, - COMMITSIZE = (4096*16), - POOLSIZE = (4096*256), -} - - -enum -{ - B_16, - B_32, - B_64, - B_128, - B_256, - B_512, - B_1024, - B_2048, - B_PAGE, // start of large alloc - B_PAGEPLUS, // continuation of large alloc - B_FREE, // free page - B_UNCOMMITTED, // memory not committed for this page - B_MAX -} - - -alias ubyte Bins; - - -struct List -{ - List *next; -} - - -struct Range -{ - void *pbot; - void *ptop; -} - - -immutable uint binsize[B_MAX] = [ 16,32,64,128,256,512,1024,2048,4096 ]; -immutable uint notbinsize[B_MAX] = [ ~(16u-1),~(32u-1),~(64u-1),~(128u-1),~(256u-1), - ~(512u-1),~(1024u-1),~(2048u-1),~(4096u-1) ]; - -/* ============================ Gcx =============================== */ - - -struct Gcx -{ - debug (THREADINVARIANT) - { - pthread_t self; - void thread_Invariant() - { - if (self != pthread_self()) - printf("thread_Invariant(): gcx = %x, self = %x, pthread_self() = %x\n", this, self, pthread_self()); - assert(self == pthread_self()); - } - } - else - { - void thread_Invariant() { } - } - - void *p_cache; - size_t size_cache; - - size_t nroots; - size_t rootdim; - void **roots; - - size_t nranges; - size_t rangedim; - Range *ranges; - - uint noStack; // !=0 means don't scan stack - uint log; // turn on logging - uint anychanges; - void *stackBottom; - uint inited; - int disabled; // turn off collections if >0 - - byte *minAddr; // min(baseAddr) - byte *maxAddr; // max(topAddr) - - size_t npools; - Pool **pooltable; - - List *bucket[B_MAX]; // free list for each size - - - void initialize() - { int dummy; - - (cast(byte*)&this)[0 .. Gcx.sizeof] = 0; - stackBottom = cast(char*)&dummy; - log_init(); - debug (THREADINVARIANT) - self = pthread_self(); - //printf("gcx = %p, self = %x\n", this, self); - inited = 1; - } - - - void Dtor() - { - inited = 0; - - for (size_t i = 0; i < npools; i++) - { Pool *pool = pooltable[i]; - - pool.Dtor(); - cstdlib.free(pool); - } - if (pooltable) - cstdlib.free(pooltable); - - if (roots) - cstdlib.free(roots); - - if (ranges) - cstdlib.free(ranges); - } - - - void Invariant() { } - - - invariant() - { - if (inited) - { - //printf("Gcx.invariant(): this = %p\n", this); - size_t i; - - // Assure we're called on the right thread - debug (THREADINVARIANT) assert(self == pthread_self()); - - for (i = 0; i < npools; i++) - { Pool *pool = pooltable[i]; - - pool.Invariant(); - if (i == 0) - { - assert(minAddr == pool.baseAddr); - } - if (i + 1 < npools) - { - assert(pool.opCmp(pooltable[i + 1]) < 0); - } - else if (i + 1 == npools) - { - assert(maxAddr == pool.topAddr); - } - } - - if (roots) - { - assert(rootdim != 0); - assert(nroots <= rootdim); - } - - if (ranges) - { - assert(rangedim != 0); - assert(nranges <= rangedim); - - for (i = 0; i < nranges; i++) - { - assert(ranges[i].pbot); - assert(ranges[i].ptop); - assert(ranges[i].pbot <= ranges[i].ptop); - } - } - - for (i = 0; i < B_PAGE; i++) - { - for (List *list = bucket[i]; list; list = list.next) - { - } - } - } - } - - - /** - * - */ - void addRoot(void *p) - { - if (nroots == rootdim) - { - size_t newdim = rootdim * 2 + 16; - void** newroots; - - newroots = cast(void**)cstdlib.malloc(newdim * newroots[0].sizeof); - if (!newroots) - onOutOfMemoryError(); - if (roots) - { memcpy(newroots, roots, nroots * newroots[0].sizeof); - cstdlib.free(roots); - } - roots = newroots; - rootdim = newdim; - } - roots[nroots] = p; - nroots++; - } - - - /** - * - */ - void removeRoot(void *p) - { - for (size_t i = nroots; i--;) - { - if (roots[i] == p) - { - nroots--; - memmove(roots + i, roots + i + 1, (nroots - i) * roots[0].sizeof); - return; - } - } - assert(0); - } - - - /** - * - */ - int rootIter(int delegate(inout void*) dg) - { - int result = 0; - for( size_t i = 0; i < nroots; ++i ) - { - result = dg(roots[i]); - if (result) - break; - } - return result; - } - - - /** - * - */ - void addRange(void *pbot, void *ptop) - { - //debug(PRINTF) printf("Thread %x ", pthread_self()); - debug(PRINTF) printf("%x.Gcx::addRange(%x, %x), nranges = %d\n", this, pbot, ptop, nranges); - if (nranges == rangedim) - { - size_t newdim = rangedim * 2 + 16; - Range *newranges; - - newranges = cast(Range*)cstdlib.malloc(newdim * newranges[0].sizeof); - if (!newranges) - onOutOfMemoryError(); - if (ranges) - { memcpy(newranges, ranges, nranges * newranges[0].sizeof); - cstdlib.free(ranges); - } - ranges = newranges; - rangedim = newdim; - } - ranges[nranges].pbot = pbot; - ranges[nranges].ptop = ptop; - nranges++; - } - - - /** - * - */ - void removeRange(void *pbot) - { - //debug(PRINTF) printf("Thread %x ", pthread_self()); - debug(PRINTF) printf("%x.Gcx.removeRange(%x), nranges = %d\n", this, pbot, nranges); - for (size_t i = nranges; i--;) - { - if (ranges[i].pbot == pbot) - { - nranges--; - memmove(ranges + i, ranges + i + 1, (nranges - i) * ranges[0].sizeof); - return; - } - } - debug(PRINTF) printf("Wrong thread\n"); - - // This is a fatal error, but ignore it. - // The problem is that we can get a Close() call on a thread - // other than the one the range was allocated on. - //assert(zero); - } - - - /** - * - */ - int rangeIter(int delegate(inout Range) dg) - { - int result = 0; - for( size_t i = 0; i < nranges; ++i ) - { - result = dg(ranges[i]); - if (result) - break; - } - return result; - } - - - /** - * Find Pool that pointer is in. - * Return null if not in a Pool. - * Assume pooltable[] is sorted. - */ - Pool *findPool(void *p) - { - if (p >= minAddr && p < maxAddr) - { - if (npools == 1) - { - return pooltable[0]; - } - - for (size_t i = 0; i < npools; i++) - { Pool *pool; - - pool = pooltable[i]; - if (p < pool.topAddr) - { if (pool.baseAddr <= p) - return pool; - break; - } - } - } - return null; - } - - - /** - * Find base address of block containing pointer p. - * Returns null if not a gc'd pointer - */ - void* findBase(void *p) - { - Pool *pool; - - pool = findPool(p); - if (pool) - { - size_t offset = cast(size_t)(p - pool.baseAddr); - size_t pn = offset / PAGESIZE; - Bins bin = cast(Bins)pool.pagetable[pn]; - - // Adjust bit to be at start of allocated memory block - if (bin <= B_PAGE) - { - return pool.baseAddr + (offset & notbinsize[bin]); - } - else if (bin == B_PAGEPLUS) - { - do - { --pn, offset -= PAGESIZE; - } while (cast(Bins)pool.pagetable[pn] == B_PAGEPLUS); - - return pool.baseAddr + (offset & (offset.max ^ (PAGESIZE-1))); - } - else - { - // we are in a B_FREE or B_UNCOMMITTED page - return null; - } - } - return null; - } - - - /** - * Find size of pointer p. - * Returns 0 if not a gc'd pointer - */ - size_t findSize(void *p) - { - Pool* pool; - size_t size = 0; - - pool = findPool(p); - if (pool) - { - size_t pagenum; - Bins bin; - - pagenum = cast(size_t)(p - pool.baseAddr) / PAGESIZE; - bin = cast(Bins)pool.pagetable[pagenum]; - size = binsize[bin]; - if (bin == B_PAGE) - { size_t npages = pool.ncommitted; - ubyte* pt; - size_t i; - - pt = &pool.pagetable[0]; - for (i = pagenum + 1; i < npages; i++) - { - if (pt[i] != B_PAGEPLUS) - break; - } - size = (i - pagenum) * PAGESIZE; - } - } - return size; - } - - - /** - * - */ - BlkInfo getInfo(void* p) - { - Pool* pool; - BlkInfo info; - - pool = findPool(p); - if (pool) - { - size_t offset = cast(size_t)(p - pool.baseAddr); - size_t pn = offset / PAGESIZE; - Bins bin = cast(Bins)pool.pagetable[pn]; - - //////////////////////////////////////////////////////////////////// - // findAddr - //////////////////////////////////////////////////////////////////// - - if (bin <= B_PAGE) - { - info.base = pool.baseAddr + (offset & notbinsize[bin]); - } - else if (bin == B_PAGEPLUS) - { - do - { --pn, offset -= PAGESIZE; - } while (cast(Bins)pool.pagetable[pn] == B_PAGEPLUS); - - info.base = pool.baseAddr + (offset & (offset.max ^ (PAGESIZE-1))); - - // fix bin for use by size calc below - bin = cast(Bins)pool.pagetable[pn]; - } - - //////////////////////////////////////////////////////////////////// - // findSize - //////////////////////////////////////////////////////////////////// - - info.size = binsize[bin]; - if (bin == B_PAGE) - { size_t npages = pool.ncommitted; - ubyte* pt; - size_t i; - - pt = &pool.pagetable[0]; - for (i = pn + 1; i < npages; i++) - { - if (pt[i] != B_PAGEPLUS) - break; - } - info.size = (i - pn) * PAGESIZE; - } - - //////////////////////////////////////////////////////////////////// - // getBits - //////////////////////////////////////////////////////////////////// - - info.attr = getBits(pool, cast(size_t)(offset / 16)); - } - return info; - } - - - /** - * Compute bin for size. - */ - static Bins findBin(size_t size) - { Bins bin; - - if (size <= 256) - { - if (size <= 64) - { - if (size <= 16) - bin = B_16; - else if (size <= 32) - bin = B_32; - else - bin = B_64; - } - else - { - if (size <= 128) - bin = B_128; - else - bin = B_256; - } - } - else - { - if (size <= 1024) - { - if (size <= 512) - bin = B_512; - else - bin = B_1024; - } - else - { - if (size <= 2048) - bin = B_2048; - else - bin = B_PAGE; - } - } - return bin; - } - - - /** - * Allocate a new pool of at least size bytes. - * Sort it into pooltable[]. - * Mark all memory in the pool as B_FREE. - * Return the actual number of bytes reserved or 0 on error. - */ - size_t reserve(size_t size) - { - size_t npages = (size + PAGESIZE - 1) / PAGESIZE; - Pool* pool = newPool(npages); - - if (!pool || pool.extendPages(npages) == OPFAIL) - return 0; - return pool.ncommitted * PAGESIZE; - } - - - /** - * Minimizes physical memory usage by returning free pools to the OS. - */ - void minimize() - { - size_t n; - size_t pn; - Pool* pool; - size_t ncommitted; - - for (n = 0; n < npools; n++) - { - pool = pooltable[n]; - ncommitted = pool.ncommitted; - for (pn = 0; pn < ncommitted; pn++) - { - if (cast(Bins)pool.pagetable[pn] != B_FREE) - break; - } - if (pn < ncommitted) - { - n++; - continue; - } - pool.Dtor(); - cstdlib.free(pool); - memmove(pooltable + n, - pooltable + n + 1, - (--npools - n) * (Pool*).sizeof); - minAddr = pooltable[0].baseAddr; - maxAddr = pooltable[npools - 1].topAddr; - } - } - - - /** - * Allocate a chunk of memory that is larger than a page. - * Return null if out of memory. - */ - void *bigAlloc(size_t size) - { - Pool* pool; - size_t npages; - size_t n; - size_t pn; - size_t freedpages; - void* p; - int state; - bool collected = false; - - npages = (size + PAGESIZE - 1) / PAGESIZE; - - for (state = disabled ? 1 : 0; ; ) - { - // This code could use some refinement when repeatedly - // allocating very large arrays. - - for (n = 0; n < npools; n++) - { - pool = pooltable[n]; - pn = pool.allocPages(npages); - if (pn != OPFAIL) - goto L1; - } - - // Failed - switch (state) - { - case 0: - // Try collecting - collected = true; - freedpages = fullcollectshell(); - if (freedpages >= npools * ((POOLSIZE / PAGESIZE) / 4)) - { state = 1; - continue; - } - // Release empty pools to prevent bloat - minimize(); - // Allocate new pool - pool = newPool(npages); - if (!pool) - { state = 2; - continue; - } - pn = pool.allocPages(npages); - assert(pn != OPFAIL); - goto L1; - case 1: - // Release empty pools to prevent bloat - minimize(); - // Allocate new pool - pool = newPool(npages); - if (!pool) - { - if (collected) - goto Lnomemory; - state = 0; - continue; - } - pn = pool.allocPages(npages); - assert(pn != OPFAIL); - goto L1; - case 2: - goto Lnomemory; - default: - assert(false); - } - } - - L1: - pool.pagetable[pn] = B_PAGE; - if (npages > 1) - memset(&pool.pagetable[pn + 1], B_PAGEPLUS, npages - 1); - p = pool.baseAddr + pn * PAGESIZE; - memset(cast(char *)p + size, 0, npages * PAGESIZE - size); - debug (MEMSTOMP) memset(p, 0xF1, size); - //debug(PRINTF) printf("\tp = %x\n", p); - return p; - - Lnomemory: - return null; // let caller handle the error - } - - - /** - * Allocate a new pool with at least npages in it. - * Sort it into pooltable[]. - * Return null if failed. - */ - Pool *newPool(size_t npages) - { - Pool* pool; - Pool** newpooltable; - size_t newnpools; - size_t i; - - //debug(PRINTF) printf("************Gcx::newPool(npages = %d)****************\n", npages); - - // Round up to COMMITSIZE pages - npages = (npages + (COMMITSIZE/PAGESIZE) - 1) & ~(COMMITSIZE/PAGESIZE - 1); - - // Minimum of POOLSIZE - if (npages < POOLSIZE/PAGESIZE) - npages = POOLSIZE/PAGESIZE; - else if (npages > POOLSIZE/PAGESIZE) - { // Give us 150% of requested size, so there's room to extend - auto n = npages + (npages >> 1); - if (n < size_t.max/PAGESIZE) - npages = n; - } - - // Allocate successively larger pools up to 8 megs - if (npools) - { size_t n; - - n = npools; - if (n > 8) - n = 8; // cap pool size at 8 megs - n *= (POOLSIZE / PAGESIZE); - if (npages < n) - npages = n; - } - - pool = cast(Pool *)cstdlib.calloc(1, Pool.sizeof); - if (pool) - { - pool.initialize(npages); - if (!pool.baseAddr) - goto Lerr; - - newnpools = npools + 1; - newpooltable = cast(Pool **)cstdlib.realloc(pooltable, newnpools * (Pool *).sizeof); - if (!newpooltable) - goto Lerr; - - // Sort pool into newpooltable[] - for (i = 0; i < npools; i++) - { - if (pool.opCmp(newpooltable[i]) < 0) - break; - } - memmove(newpooltable + i + 1, newpooltable + i, (npools - i) * (Pool *).sizeof); - newpooltable[i] = pool; - - pooltable = newpooltable; - npools = newnpools; - - minAddr = pooltable[0].baseAddr; - maxAddr = pooltable[npools - 1].topAddr; - } - return pool; - - Lerr: - pool.Dtor(); - cstdlib.free(pool); - return null; - } - - - /** - * Allocate a page of bin's. - * Returns: - * 0 failed - */ - int allocPage(Bins bin) - { - Pool* pool; - size_t n; - size_t pn; - byte* p; - byte* ptop; - - //debug(PRINTF) printf("Gcx::allocPage(bin = %d)\n", bin); - for (n = 0; n < npools; n++) - { - pool = pooltable[n]; - pn = pool.allocPages(1); - if (pn != OPFAIL) - goto L1; - } - return 0; // failed - - L1: - pool.pagetable[pn] = cast(ubyte)bin; - - // Convert page to free list - size_t size = binsize[bin]; - List **b = &bucket[bin]; - - p = pool.baseAddr + pn * PAGESIZE; - ptop = p + PAGESIZE; - for (; p < ptop; p += size) - { - (cast(List *)p).next = *b; - *b = cast(List *)p; - } - return 1; - } - - - /** - * Search a range of memory values and mark any pointers into the GC pool. - */ - void mark(void *pbot, void *ptop) - { - void **p1 = cast(void **)pbot; - void **p2 = cast(void **)ptop; - size_t pcache = 0; - uint changes = 0; - - //printf("marking range: %p -> %p\n", pbot, ptop); - for (; p1 < p2; p1++) - { - Pool *pool; - byte *p = cast(byte *)(*p1); - - //if (log) debug(PRINTF) printf("\tmark %x\n", p); - if (p >= minAddr && p < maxAddr) - { - if ((cast(size_t)p & ~(PAGESIZE-1)) == pcache) - continue; - - pool = findPool(p); - if (pool) - { - size_t offset = cast(size_t)(p - pool.baseAddr); - size_t biti; - size_t pn = offset / PAGESIZE; - Bins bin = cast(Bins)pool.pagetable[pn]; - - //debug(PRINTF) printf("\t\tfound pool %x, base=%x, pn = %d, bin = %d, biti = x%x\n", pool, pool.baseAddr, pn, bin, biti); - - // Adjust bit to be at start of allocated memory block - if (bin <= B_PAGE) - { - biti = (offset & notbinsize[bin]) >> 4; - //debug(PRINTF) printf("\t\tbiti = x%x\n", biti); - } - else if (bin == B_PAGEPLUS) - { - do - { --pn; - } while (cast(Bins)pool.pagetable[pn] == B_PAGEPLUS); - biti = pn * (PAGESIZE / 16); - } - else - { - // Don't mark bits in B_FREE or B_UNCOMMITTED pages - continue; - } - - if (bin >= B_PAGE) // Cache B_PAGE and B_PAGEPLUS lookups - pcache = cast(size_t)p & ~(PAGESIZE-1); - - //debug(PRINTF) printf("\t\tmark(x%x) = %d\n", biti, pool.mark.test(biti)); - if (!pool.mark.test(biti)) - { - //if (log) debug(PRINTF) printf("\t\tmarking %x\n", p); - pool.mark.set(biti); - if (!pool.noscan.test(biti)) - { - pool.scan.set(biti); - changes = 1; - } - log_parent(sentinel_add(pool.baseAddr + biti * 16), sentinel_add(pbot)); - } - } - } - } - anychanges |= changes; - } - - - /** - * Return number of full pages free'd. - */ - size_t fullcollectshell() - { - // The purpose of the 'shell' is to ensure all the registers - // get put on the stack so they'll be scanned - void *sp; - size_t result; - version (GNU) - { - __builtin_unwind_init(); - sp = & sp; - } - else - { - asm - { - pushad ; - mov sp[EBP],ESP ; - } - } - result = fullcollect(sp); - version (GNU) - { - // nothing to do - } - else - { - asm - { - popad ; - } - } - return result; - } - - - /** - * - */ - size_t fullcollect(void *stackTop) - { - size_t n; - Pool* pool; - - debug(COLLECT_PRINTF) printf("Gcx.fullcollect()\n"); - - thread_suspendAll(); - - p_cache = null; - size_cache = 0; - - anychanges = 0; - for (n = 0; n < npools; n++) - { - pool = pooltable[n]; - pool.mark.zero(); - pool.scan.zero(); - pool.freebits.zero(); - } - - // Mark each free entry, so it doesn't get scanned - for (n = 0; n < B_PAGE; n++) - { - for (List *list = bucket[n]; list; list = list.next) - { - pool = findPool(list); - assert(pool); - pool.freebits.set(cast(size_t)(cast(byte*)list - pool.baseAddr) / 16); - } - } - - for (n = 0; n < npools; n++) - { - pool = pooltable[n]; - pool.mark.copy(&pool.freebits); - } - - version (MULTI_THREADED) - { - if (!noStack) - { - // Scan stacks and registers for each paused thread - thread_scanAll( &mark, stackTop ); - } - } - else - { - if (!noStack) - { - // Scan stack for main thread - debug(PRINTF) printf(" scan stack bot = %x, top = %x\n", stackTop, stackBottom); - version (STACKGROWSDOWN) - mark(stackTop, stackBottom); - else - mark(stackBottom, stackTop); - } - } - - // Scan roots[] - debug(COLLECT_PRINTF) printf("scan roots[]\n"); - mark(roots, roots + nroots); - - // Scan ranges[] - debug(COLLECT_PRINTF) printf("scan ranges[]\n"); - //log++; - for (n = 0; n < nranges; n++) - { - debug(COLLECT_PRINTF) printf("\t%x .. %x\n", ranges[n].pbot, ranges[n].ptop); - mark(ranges[n].pbot, ranges[n].ptop); - } - //log--; - - debug(COLLECT_PRINTF) printf("\tscan heap\n"); - while (anychanges) - { - anychanges = 0; - for (n = 0; n < npools; n++) - { - uint *bbase; - uint *b; - uint *btop; - - pool = pooltable[n]; - - bbase = pool.scan.base(); - btop = bbase + pool.scan.nwords; - for (b = bbase; b < btop;) - { Bins bin; - size_t pn; - size_t u; - size_t bitm; - byte* o; - - bitm = *b; - if (!bitm) - { b++; - continue; - } - *b = 0; - - o = pool.baseAddr + (b - bbase) * 32 * 16; - if (!(bitm & 0xFFFF)) - { - bitm >>= 16; - o += 16 * 16; - } - for (; bitm; o += 16, bitm >>= 1) - { - if (!(bitm & 1)) - continue; - - pn = cast(size_t)(o - pool.baseAddr) / PAGESIZE; - bin = cast(Bins)pool.pagetable[pn]; - if (bin < B_PAGE) - { - mark(o, o + binsize[bin]); - } - else if (bin == B_PAGE || bin == B_PAGEPLUS) - { - if (bin == B_PAGEPLUS) - { - while (pool.pagetable[pn - 1] != B_PAGE) - pn--; - } - u = 1; - while (pn + u < pool.ncommitted && pool.pagetable[pn + u] == B_PAGEPLUS) - u++; - mark(o, o + u * PAGESIZE); - } - } - } - } - } - - thread_resumeAll(); - - // Free up everything not marked - debug(COLLECT_PRINTF) printf("\tfree'ing\n"); - size_t freedpages = 0; - size_t freed = 0; - for (n = 0; n < npools; n++) - { size_t pn; - size_t ncommitted; - uint* bbase; - - pool = pooltable[n]; - bbase = pool.mark.base(); - ncommitted = pool.ncommitted; - for (pn = 0; pn < ncommitted; pn++, bbase += PAGESIZE / (32 * 16)) - { - Bins bin = cast(Bins)pool.pagetable[pn]; - - if (bin < B_PAGE) - { byte* p; - byte* ptop; - size_t biti; - size_t bitstride; - auto size = binsize[bin]; - - p = pool.baseAddr + pn * PAGESIZE; - ptop = p + PAGESIZE; - biti = pn * (PAGESIZE/16); - bitstride = size / 16; - - version(none) // BUG: doesn't work because freebits() must also be cleared - { - // If free'd entire page - if (bbase[0] == 0 && bbase[1] == 0 && bbase[2] == 0 && bbase[3] == 0 && - bbase[4] == 0 && bbase[5] == 0 && bbase[6] == 0 && bbase[7] == 0) - { - for (; p < ptop; p += size, biti += bitstride) - { - if (pool.finals.nbits && pool.finals.testClear(biti)) - rt_finalize(cast(List *)sentinel_add(p), false/*noStack > 0*/); - gcx.clrBits(pool, biti, BlkAttr.ALL_BITS); - - List *list = cast(List *)p; - //debug(PRINTF) printf("\tcollecting %x\n", list); - log_free(sentinel_add(list)); - - debug (MEMSTOMP) memset(p, 0xF3, size); - } - pool.pagetable[pn] = B_FREE; - freed += PAGESIZE; - //debug(PRINTF) printf("freeing entire page %d\n", pn); - continue; - } - } - for (; p < ptop; p += size, biti += bitstride) - { - if (!pool.mark.test(biti)) - { - sentinel_Invariant(sentinel_add(p)); - - pool.freebits.set(biti); - if (pool.finals.nbits && pool.finals.testClear(biti)) - rt_finalize(cast(List *)sentinel_add(p), false/*noStack > 0*/); - clrBits(pool, biti, BlkAttr.ALL_BITS); - - List *list = cast(List *)p; - debug(PRINTF) printf("\tcollecting %x\n", list); - log_free(sentinel_add(list)); - - debug (MEMSTOMP) memset(p, 0xF3, size); - - freed += size; - } - } - } - else if (bin == B_PAGE) - { size_t biti = pn * (PAGESIZE / 16); - - if (!pool.mark.test(biti)) - { byte *p = pool.baseAddr + pn * PAGESIZE; - - sentinel_Invariant(sentinel_add(p)); - if (pool.finals.nbits && pool.finals.testClear(biti)) - rt_finalize(sentinel_add(p), false/*noStack > 0*/); - clrBits(pool, biti, BlkAttr.ALL_BITS); - - debug(COLLECT_PRINTF) printf("\tcollecting big %x\n", p); - log_free(sentinel_add(p)); - pool.pagetable[pn] = B_FREE; - freedpages++; - debug (MEMSTOMP) memset(p, 0xF3, PAGESIZE); - while (pn + 1 < ncommitted && pool.pagetable[pn + 1] == B_PAGEPLUS) - { - pn++; - pool.pagetable[pn] = B_FREE; - freedpages++; - - debug (MEMSTOMP) - { p += PAGESIZE; - memset(p, 0xF3, PAGESIZE); - } - } - } - } - } - } - - // Zero buckets - bucket[] = null; - - // Free complete pages, rebuild free list - debug(COLLECT_PRINTF) printf("\tfree complete pages\n"); - size_t recoveredpages = 0; - for (n = 0; n < npools; n++) - { size_t pn; - size_t ncommitted; - - pool = pooltable[n]; - ncommitted = pool.ncommitted; - for (pn = 0; pn < ncommitted; pn++) - { - Bins bin = cast(Bins)pool.pagetable[pn]; - size_t biti; - size_t u; - - if (bin < B_PAGE) - { - size_t size = binsize[bin]; - size_t bitstride = size / 16; - size_t bitbase = pn * (PAGESIZE / 16); - size_t bittop = bitbase + (PAGESIZE / 16); - byte* p; - - biti = bitbase; - for (biti = bitbase; biti < bittop; biti += bitstride) - { if (!pool.freebits.test(biti)) - goto Lnotfree; - } - pool.pagetable[pn] = B_FREE; - recoveredpages++; - continue; - - Lnotfree: - p = pool.baseAddr + pn * PAGESIZE; - for (u = 0; u < PAGESIZE; u += size) - { biti = bitbase + u / 16; - if (pool.freebits.test(biti)) - { List *list; - - list = cast(List *)(p + u); - if (list.next != bucket[bin]) // avoid unnecessary writes - list.next = bucket[bin]; - bucket[bin] = list; - } - } - } - } - } - - debug(COLLECT_PRINTF) printf("recovered pages = %d\n", recoveredpages); - debug(COLLECT_PRINTF) printf("\tfree'd %u bytes, %u pages from %u pools\n", freed, freedpages, npools); - - return freedpages + recoveredpages; - } - - - /** - * - */ - uint getBits(Pool* pool, size_t biti) - in - { - assert( pool ); - } - body - { - uint bits; - - if (pool.finals.nbits && - pool.finals.test(biti)) - bits |= BlkAttr.FINALIZE; - if (pool.noscan.test(biti)) - bits |= BlkAttr.NO_SCAN; -// if (pool.nomove.nbits && -// pool.nomove.test(biti)) -// bits |= BlkAttr.NO_MOVE; - return bits; - } - - - /** - * - */ - void setBits(Pool* pool, size_t biti, uint mask) - in - { - assert( pool ); - } - body - { - if (mask & BlkAttr.FINALIZE) - { - if (!pool.finals.nbits) - pool.finals.alloc(pool.mark.nbits); - pool.finals.set(biti); - } - if (mask & BlkAttr.NO_SCAN) - { - pool.noscan.set(biti); - } -// if (mask & BlkAttr.NO_MOVE) -// { -// if (!pool.nomove.nbits) -// pool.nomove.alloc(pool.mark.nbits); -// pool.nomove.set(biti); -// } - } - - - /** - * - */ - void clrBits(Pool* pool, size_t biti, uint mask) - in - { - assert( pool ); - } - body - { - if (mask & BlkAttr.FINALIZE && pool.finals.nbits) - pool.finals.clear(biti); - if (mask & BlkAttr.NO_SCAN) - pool.noscan.clear(biti); -// if (mask & BlkAttr.NO_MOVE && pool.nomove.nbits) -// pool.nomove.clear(biti); - } - - - /***** Leak Detector ******/ - - - debug (LOGGING) - { - LogArray current; - LogArray prev; - - - void log_init() - { - //debug(PRINTF) printf("+log_init()\n"); - current.reserve(1000); - prev.reserve(1000); - //debug(PRINTF) printf("-log_init()\n"); - } - - - void log_malloc(void *p, size_t size) - { - //debug(PRINTF) printf("+log_malloc(p = %x, size = %d)\n", p, size); - Log log; - - log.p = p; - log.size = size; - log.line = GC.line; - log.file = GC.file; - log.parent = null; - - GC.line = 0; - GC.file = null; - - current.push(log); - //debug(PRINTF) printf("-log_malloc()\n"); - } - - - void log_free(void *p) - { - //debug(PRINTF) printf("+log_free(%x)\n", p); - size_t i; - - i = current.find(p); - if (i == OPFAIL) - { - debug(PRINTF) printf("free'ing unallocated memory %x\n", p); - } - else - current.remove(i); - //debug(PRINTF) printf("-log_free()\n"); - } - - - void log_collect() - { - //debug(PRINTF) printf("+log_collect()\n"); - // Print everything in current that is not in prev - - debug(PRINTF) printf("New pointers this cycle: --------------------------------\n"); - size_t used = 0; - for (size_t i = 0; i < current.dim; i++) - { - size_t j; - - j = prev.find(current.data[i].p); - if (j == OPFAIL) - current.data[i].print(); - else - used++; - } - - debug(PRINTF) printf("All roots this cycle: --------------------------------\n"); - for (size_t i = 0; i < current.dim; i++) - { - void *p; - size_t j; - - p = current.data[i].p; - if (!findPool(current.data[i].parent)) - { - j = prev.find(current.data[i].p); - if (j == OPFAIL) - debug(PRINTF) printf("N"); - else - debug(PRINTF) printf(" ");; - current.data[i].print(); - } - } - - debug(PRINTF) printf("Used = %d-------------------------------------------------\n", used); - prev.copy(¤t); - - debug(PRINTF) printf("-log_collect()\n"); - } - - - void log_parent(void *p, void *parent) - { - //debug(PRINTF) printf("+log_parent()\n"); - size_t i; - - i = current.find(p); - if (i == OPFAIL) - { - debug(PRINTF) printf("parent'ing unallocated memory %x, parent = %x\n", p, parent); - Pool *pool; - pool = findPool(p); - assert(pool); - size_t offset = cast(size_t)(p - pool.baseAddr); - size_t biti; - size_t pn = offset / PAGESIZE; - Bins bin = cast(Bins)pool.pagetable[pn]; - biti = (offset & notbinsize[bin]); - debug(PRINTF) printf("\tbin = %d, offset = x%x, biti = x%x\n", bin, offset, biti); - } - else - { - current.data[i].parent = parent; - } - //debug(PRINTF) printf("-log_parent()\n"); - } - - } - else - { - void log_init() { } - void log_malloc(void *p, size_t size) { } - void log_free(void *p) { } - void log_collect() { } - void log_parent(void *p, void *parent) { } - } -} - - -/* ============================ Pool =============================== */ - - -struct Pool -{ - byte* baseAddr; - byte* topAddr; - GCBits mark; // entries already scanned, or should not be scanned - GCBits scan; // entries that need to be scanned - GCBits freebits; // entries that are on the free list - GCBits finals; // entries that need finalizer run on them - GCBits noscan; // entries that should not be scanned - - size_t npages; - size_t ncommitted; // ncommitted <= npages - ubyte* pagetable; - - - void initialize(size_t npages) - { - size_t poolsize; - - //debug(PRINTF) printf("Pool::Pool(%u)\n", npages); - poolsize = npages * PAGESIZE; - assert(poolsize >= POOLSIZE); - baseAddr = cast(byte *)os_mem_map(poolsize); - - // Some of the code depends on page alignment of memory pools - assert((cast(size_t)baseAddr & (PAGESIZE - 1)) == 0); - - if (!baseAddr) - { - //debug(PRINTF) printf("GC fail: poolsize = x%x, errno = %d\n", poolsize, errno); - //debug(PRINTF) printf("message = '%s'\n", sys_errlist[errno]); - - npages = 0; - poolsize = 0; - } - //assert(baseAddr); - topAddr = baseAddr + poolsize; - - mark.alloc(cast(size_t)poolsize / 16); - scan.alloc(cast(size_t)poolsize / 16); - freebits.alloc(cast(size_t)poolsize / 16); - noscan.alloc(cast(size_t)poolsize / 16); - - pagetable = cast(ubyte*)cstdlib.malloc(npages); - if (!pagetable) - onOutOfMemoryError(); - memset(pagetable, B_UNCOMMITTED, npages); - - this.npages = npages; - ncommitted = 0; - } - - - void Dtor() - { - if (baseAddr) - { - int result; - - if (ncommitted) - { - result = os_mem_decommit(baseAddr, 0, ncommitted * PAGESIZE); - assert(result == 0); - ncommitted = 0; - } - - if (npages) - { - result = os_mem_unmap(baseAddr, npages * PAGESIZE); - assert(result == 0); - npages = 0; - } - - baseAddr = null; - topAddr = null; - } - if (pagetable) - cstdlib.free(pagetable); - - mark.Dtor(); - scan.Dtor(); - freebits.Dtor(); - finals.Dtor(); - noscan.Dtor(); - } - - - void Invariant() { } - - - invariant() - { - //mark.Invariant(); - //scan.Invariant(); - //freebits.Invariant(); - //finals.Invariant(); - //noscan.Invariant(); - - if (baseAddr) - { - //if (baseAddr + npages * PAGESIZE != topAddr) - //printf("baseAddr = %p, npages = %d, topAddr = %p\n", baseAddr, npages, topAddr); - assert(baseAddr + npages * PAGESIZE == topAddr); - assert(ncommitted <= npages); - } - - for (size_t i = 0; i < npages; i++) - { Bins bin = cast(Bins)pagetable[i]; - - assert(bin < B_MAX); - } - } - - - /** - * Allocate n pages from Pool. - * Returns OPFAIL on failure. - */ - size_t allocPages(size_t n) - { - size_t i; - size_t n2; - - //debug(PRINTF) printf("Pool::allocPages(n = %d)\n", n); - n2 = n; - for (i = 0; i < ncommitted; i++) - { - if (pagetable[i] == B_FREE) - { - if (--n2 == 0) - { //debug(PRINTF) printf("\texisting pn = %d\n", i - n + 1); - return i - n + 1; - } - } - else - n2 = n; - } - return extendPages(n); - } - - /** - * Extend Pool by n pages. - * Returns OPFAIL on failure. - */ - size_t extendPages(size_t n) - { - //debug(PRINTF) printf("Pool::extendPages(n = %d)\n", n); - if (ncommitted + n <= npages) - { - size_t tocommit; - - tocommit = (n + (COMMITSIZE/PAGESIZE) - 1) & ~(COMMITSIZE/PAGESIZE - 1); - if (ncommitted + tocommit > npages) - tocommit = npages - ncommitted; - //debug(PRINTF) printf("\tlooking to commit %d more pages\n", tocommit); - //fflush(stdout); - if (os_mem_commit(baseAddr, ncommitted * PAGESIZE, tocommit * PAGESIZE) == 0) - { - memset(pagetable + ncommitted, B_FREE, tocommit); - auto i = ncommitted; - ncommitted += tocommit; - - while (i && pagetable[i - 1] == B_FREE) - i--; - - return i; - } - //debug(PRINTF) printf("\tfailed to commit %d pages\n", tocommit); - } - - return OPFAIL; - } - - - /** - * Free npages pages starting with pagenum. - */ - void freePages(size_t pagenum, size_t npages) - { - memset(&pagetable[pagenum], B_FREE, npages); - } - - - /** - * Used for sorting pooltable[] - */ - int opCmp(Pool *p2) - { - if (baseAddr < p2.baseAddr) - return -1; - else - return cast(int)(baseAddr > p2.baseAddr); - } -} - - -/* ============================ SENTINEL =============================== */ - - -version (SENTINEL) -{ - const size_t SENTINEL_PRE = cast(size_t) 0xF4F4F4F4F4F4F4F4UL; // 32 or 64 bits - const ubyte SENTINEL_POST = 0xF5; // 8 bits - const uint SENTINEL_EXTRA = 2 * size_t.sizeof + 1; - - - size_t* sentinel_size(void *p) { return &(cast(size_t *)p)[-2]; } - size_t* sentinel_pre(void *p) { return &(cast(size_t *)p)[-1]; } - ubyte* sentinel_post(void *p) { return &(cast(ubyte *)p)[*sentinel_size(p)]; } - - - void sentinel_init(void *p, size_t size) - { - *sentinel_size(p) = size; - *sentinel_pre(p) = SENTINEL_PRE; - *sentinel_post(p) = SENTINEL_POST; - } - - - void sentinel_Invariant(void *p) - { - assert(*sentinel_pre(p) == SENTINEL_PRE); - assert(*sentinel_post(p) == SENTINEL_POST); - } - - - void *sentinel_add(void *p) - { - return p + 2 * size_t.sizeof; - } - - - void *sentinel_sub(void *p) - { - return p - 2 * size_t.sizeof; - } -} -else -{ - const uint SENTINEL_EXTRA = 0; - - - void sentinel_init(void *p, size_t size) - { - } - - - void sentinel_Invariant(void *p) - { - } - - - void *sentinel_add(void *p) - { - return p; - } - - - void *sentinel_sub(void *p) - { - return p; - } -} diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/gc/basic/posix.mak --- a/druntime/src/gc/basic/posix.mak Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -# Makefile to build the garbage collector D library for Posix -# Designed to work with GNU make -# Targets: -# make -# Same as make all -# make debug -# Build the debug version of the library -# make release -# Build the release version of the library -# make doc -# Generate documentation -# make clean -# Delete all files created by build process - -# Essentials - -LIBDIR=../../../lib -DOCDIR=../../../doc -IMPDIR=../../../import -LIBBASENAME=libdruntime-gc-basic.a -MODULES=gc gcalloc gcbits gcstats gcx -BUILDS=debug release unittest - -# Symbols - -DMD=dmd -DOCFLAGS=-version=DDoc -DFLAGS_release=-d -release -O -inline -w -nofloat -DFLAGS_debug=-d -g -w -nofloat -DFLAGS_unittest=$(DFLAGS_release) -unittest -CFLAGS_release=-m32 -O -CFLAGS_debug=-m32 -g -CFLAGS_unittest=$(CFLAGS_release) - -# Derived symbols - -SRCS=$(addsuffix .d,$(MODULES)) -DOCS= -IMPORTS= -ALLLIBS=$(addsuffix /$(LIBBASENAME),$(addprefix $(LIBDIR)/,$(BUILDS))) - -# Patterns - -$(LIBDIR)/%/$(LIBBASENAME) : $(SRCS) - $(DMD) $(DFLAGS_$*) -lib -of$@ $^ - -$(DOCDIR)/%.html : %.d - $(DMD) -c -d -o- -Df$@ $< - -$(IMPDIR)/%.di : %.d - $(DMD) -c -d -o- -Hf$@ $< - -# Rulez - -all : $(BUILDS) doc - -debug : $(LIBDIR)/debug/$(LIBBASENAME) $(IMPORTS) -release : $(LIBDIR)/release/$(LIBBASENAME) $(IMPORTS) -unittest : $(LIBDIR)/unittest/$(LIBBASENAME) $(IMPORTS) -#doc : $(DOCS) - -clean : - rm -f $(IMPORTS) $(DOCS) $(ALLLIBS) diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/gc/basic/win32.mak --- a/druntime/src/gc/basic/win32.mak Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ -# Makefile to build the garbage collector D library for Posix -# Designed to work with GNU make -# Targets: -# make -# Same as make all -# make debug -# Build the debug version of the library -# make release -# Build the release version of the library -# make doc -# Generate documentation -# make clean -# Delete all files created by build process - -# Essentials - -LIBDIR=..\..\..\lib -DOCDIR=..\..\..\doc -IMPDIR=..\..\..\import -LIBBASENAME=druntime_gc_basic.lib -#MODULES=gc gcalloc gcbits gcstats gcx -BUILDS=debug release unittest - -# Symbols - -CC=dmc -DMD=dmd -DOCFLAGS=-version=DDoc -DFLAGS_release=-d -release -O -inline -w -nofloat -DFLAGS_debug=-d -g -w -nofloat -DFLAGS_unittest=$(DFLAGS_release) -unittest -CFLAGS_release=-mn -6 -r -CFLAGS_debug=-g -mn -6 -r -CFLAGS_unittest=$(CFLAGS_release) - -# Derived symbols - -SRCS=gc.d gcalloc.d gcbits.d gcstats.d gcx.d -DOCS= -IMPORTS= -ALLLIBS=\ - $(LIBDIR)\debug\$(LIBBASENAME) \ - $(LIBDIR)\release\$(LIBBASENAME) \ - $(LIBDIR)\unittest\$(LIBBASENAME) - -# Patterns - -#$(LIBDIR)\%\$(LIBBASENAME) : $(SRCS) -# $(DMD) $(DFLAGS_$*) -lib -of$@ $^ - -#$(DOCDIR)\%.html : %.d -# $(DMD) -c -d -o- -Df$@ $< - -#$(IMPDIR)\%.di : %.d -# $(DMD) -c -d -o- -Hf$@ $< - -# Patterns - debug - -$(LIBDIR)\debug\$(LIBBASENAME) : $(SRCS) - $(DMD) $(DFLAGS_debug) -lib -of$@ $** - -# Patterns - release - -$(LIBDIR)\release\$(LIBBASENAME) : $(SRCS) - $(DMD) $(DFLAGS_release) -lib -of$@ $** - -# Patterns - unittest - -$(LIBDIR)\unittest\$(LIBBASENAME) : $(SRCS) - $(DMD) $(DFLAGS_unittest) -lib -of$@ $** - -# Rulez - -all : $(BUILDS) doc - -debug : $(LIBDIR)\debug\$(LIBBASENAME) $(IMPORTS) -release : $(LIBDIR)\release\$(LIBBASENAME) $(IMPORTS) -unittest : $(LIBDIR)\unittest\$(LIBBASENAME) $(IMPORTS) -#doc : $(DOCS) - -clean : - del $(IMPORTS) $(DOCS) $(ALLLIBS) diff -r b265fb6ce15b -r d28cd7c45267 druntime/src/gc/stub/gc.d --- a/druntime/src/gc/stub/gc.d Mon Jul 06 23:56:11 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,359 +0,0 @@ -/** - * This module contains a minimal garbage collector implementation according to - * published requirements. This library is mostly intended to serve as an - * example, but it is usable in applications which do not rely on a garbage - * collector to clean up memory (ie. when dynamic array resizing is not used, - * and all memory allocated with 'new' is freed deterministically with - * 'delete'). - * - * Please note that block attribute data must be tracked, or at a minimum, the - * FINALIZE bit must be tracked for any allocated memory block because calling - * rt_finalize on a non-object block can result in an access violation. In the - * allocator below, this tracking is done via a leading uint bitmask. A real - * allocator may do better to store this data separately, similar to the basic - * GC. - * - * Copyright: Copyright Sean Kelly 2005 - 2009. - * License: