diff options
author | Feng Qian <fqian@google.com> | 2009-06-17 12:12:20 -0700 |
---|---|---|
committer | Feng Qian <fqian@google.com> | 2009-06-17 12:12:20 -0700 |
commit | 5f1ab04193ad0130ca8204aadaceae083aca9881 (patch) | |
tree | 5a92cd389e2cfe7fb67197ce14b38469462379f8 /JavaScriptCore/wtf | |
parent | 194315e5a908cc8ed67d597010544803eef1ac59 (diff) | |
download | external_webkit-5f1ab04193ad0130ca8204aadaceae083aca9881.zip external_webkit-5f1ab04193ad0130ca8204aadaceae083aca9881.tar.gz external_webkit-5f1ab04193ad0130ca8204aadaceae083aca9881.tar.bz2 |
Get WebKit r44544.
Diffstat (limited to 'JavaScriptCore/wtf')
43 files changed, 3526 insertions, 612 deletions
diff --git a/JavaScriptCore/wtf/ASCIICType.h b/JavaScriptCore/wtf/ASCIICType.h index 0c2ca70..0c3c29f 100644 --- a/JavaScriptCore/wtf/ASCIICType.h +++ b/JavaScriptCore/wtf/ASCIICType.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -149,4 +149,18 @@ namespace WTF { inline bool isASCIIPrintable(int c) { return c >= ' ' && c <= '~'; } } +using WTF::isASCII; +using WTF::isASCIIAlpha; +using WTF::isASCIIAlphanumeric; +using WTF::isASCIIDigit; +using WTF::isASCIIHexDigit; +using WTF::isASCIILower; +using WTF::isASCIIOctalDigit; +using WTF::isASCIIPrintable; +using WTF::isASCIISpace; +using WTF::isASCIIUpper; +using WTF::toASCIIHexValue; +using WTF::toASCIILower; +using WTF::toASCIIUpper; + #endif diff --git a/JavaScriptCore/wtf/AVLTree.h b/JavaScriptCore/wtf/AVLTree.h index 18db8ff..d7470e7 100644 --- a/JavaScriptCore/wtf/AVLTree.h +++ b/JavaScriptCore/wtf/AVLTree.h @@ -764,7 +764,7 @@ AVLTree<Abstractor, maxDepth, BSet>::remove(key k) handle h = abs.root; handle parent = null(), child; - int cmp, cmp_shortened_sub_with_path; + int cmp, cmp_shortened_sub_with_path = 0; for (;;) { if (h == null()) diff --git a/JavaScriptCore/wtf/CrossThreadRefCounted.h b/JavaScriptCore/wtf/CrossThreadRefCounted.h index 82f1ba1..281dfa6 100644 --- a/JavaScriptCore/wtf/CrossThreadRefCounted.h +++ b/JavaScriptCore/wtf/CrossThreadRefCounted.h @@ -35,7 +35,6 @@ #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> #include <wtf/Threading.h> -#include <wtf/TypeTraits.h> namespace WTF { @@ -66,6 +65,11 @@ namespace WTF { void deref(); T* release(); + bool isShared() const + { + return !m_refCounter.hasOneRef() || (m_threadSafeRefCounter && !m_threadSafeRefCounter->hasOneRef()); + } + #ifndef NDEBUG bool mayBePassedToAnotherThread() const { ASSERT(!m_threadId); return m_refCounter.hasOneRef(); } #endif diff --git a/JavaScriptCore/wtf/CurrentTime.h b/JavaScriptCore/wtf/CurrentTime.h index f70f98f..436e054 100644 --- a/JavaScriptCore/wtf/CurrentTime.h +++ b/JavaScriptCore/wtf/CurrentTime.h @@ -36,7 +36,7 @@ namespace WTF { // Returns the current system (UTC) time in seconds, starting January 1, 1970. // Precision varies depending on a platform but usually is as good or better - // then a millisecond. + // than a millisecond. double currentTime(); #if PLATFORM(ANDROID) diff --git a/JavaScriptCore/wtf/DateMath.cpp b/JavaScriptCore/wtf/DateMath.cpp new file mode 100644 index 0000000..3d3ede2 --- /dev/null +++ b/JavaScriptCore/wtf/DateMath.cpp @@ -0,0 +1,895 @@ +/* + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Alternatively, the contents of this file may be used under the terms + * of either the Mozilla Public License Version 1.1, found at + * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public + * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html + * (the "GPL"), in which case the provisions of the MPL or the GPL are + * applicable instead of those above. If you wish to allow use of your + * version of this file only under the terms of one of those two + * licenses (the MPL or the GPL) and not to allow others to use your + * version of this file under the LGPL, indicate your decision by + * deletingthe provisions above and replace them with the notice and + * other provisions required by the MPL or the GPL, as the case may be. + * If you do not delete the provisions above, a recipient may use your + * version of this file under any of the LGPL, the MPL or the GPL. + */ + +#include "config.h" +#include "DateMath.h" + +#include "Assertions.h" +#include "ASCIICType.h" +#include "CurrentTime.h" +#include "MathExtras.h" +#include "StringExtras.h" + +#include <algorithm> +#include <limits.h> +#include <limits> +#include <stdint.h> +#include <time.h> + + +#if HAVE(ERRNO_H) +#include <errno.h> +#endif + +#if PLATFORM(DARWIN) +#include <notify.h> +#endif + +#if HAVE(SYS_TIME_H) +#include <sys/time.h> +#endif + +#if HAVE(SYS_TIMEB_H) +#include <sys/timeb.h> +#endif + +#define NaN std::numeric_limits<double>::quiet_NaN() + +namespace WTF { + +/* Constants */ + +static const double minutesPerDay = 24.0 * 60.0; +static const double secondsPerDay = 24.0 * 60.0 * 60.0; +static const double secondsPerYear = 24.0 * 60.0 * 60.0 * 365.0; + +static const double usecPerSec = 1000000.0; + +static const double maxUnixTime = 2145859200.0; // 12/31/2037 + +// Day of year for the first day of each month, where index 0 is January, and day 0 is January 1. +// First for non-leap years, then for leap years. +static const int firstDayOfMonth[2][12] = { + {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}, + {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335} +}; + +static inline bool isLeapYear(int year) +{ + if (year % 4 != 0) + return false; + if (year % 400 == 0) + return true; + if (year % 100 == 0) + return false; + return true; +} + +static inline int daysInYear(int year) +{ + return 365 + isLeapYear(year); +} + +static inline double daysFrom1970ToYear(int year) +{ + // The Gregorian Calendar rules for leap years: + // Every fourth year is a leap year. 2004, 2008, and 2012 are leap years. + // However, every hundredth year is not a leap year. 1900 and 2100 are not leap years. + // Every four hundred years, there's a leap year after all. 2000 and 2400 are leap years. + + static const int leapDaysBefore1971By4Rule = 1970 / 4; + static const int excludedLeapDaysBefore1971By100Rule = 1970 / 100; + static const int leapDaysBefore1971By400Rule = 1970 / 400; + + const double yearMinusOne = year - 1; + const double yearsToAddBy4Rule = floor(yearMinusOne / 4.0) - leapDaysBefore1971By4Rule; + const double yearsToExcludeBy100Rule = floor(yearMinusOne / 100.0) - excludedLeapDaysBefore1971By100Rule; + const double yearsToAddBy400Rule = floor(yearMinusOne / 400.0) - leapDaysBefore1971By400Rule; + + return 365.0 * (year - 1970) + yearsToAddBy4Rule - yearsToExcludeBy100Rule + yearsToAddBy400Rule; +} + +static inline double msToDays(double ms) +{ + return floor(ms / msPerDay); +} + +static inline int msToYear(double ms) +{ + int approxYear = static_cast<int>(floor(ms / (msPerDay * 365.2425)) + 1970); + double msFromApproxYearTo1970 = msPerDay * daysFrom1970ToYear(approxYear); + if (msFromApproxYearTo1970 > ms) + return approxYear - 1; + if (msFromApproxYearTo1970 + msPerDay * daysInYear(approxYear) <= ms) + return approxYear + 1; + return approxYear; +} + +static inline int dayInYear(double ms, int year) +{ + return static_cast<int>(msToDays(ms) - daysFrom1970ToYear(year)); +} + +static inline double msToMilliseconds(double ms) +{ + double result = fmod(ms, msPerDay); + if (result < 0) + result += msPerDay; + return result; +} + +// 0: Sunday, 1: Monday, etc. +static inline int msToWeekDay(double ms) +{ + int wd = (static_cast<int>(msToDays(ms)) + 4) % 7; + if (wd < 0) + wd += 7; + return wd; +} + +static inline int msToSeconds(double ms) +{ + double result = fmod(floor(ms / msPerSecond), secondsPerMinute); + if (result < 0) + result += secondsPerMinute; + return static_cast<int>(result); +} + +static inline int msToMinutes(double ms) +{ + double result = fmod(floor(ms / msPerMinute), minutesPerHour); + if (result < 0) + result += minutesPerHour; + return static_cast<int>(result); +} + +static inline int msToHours(double ms) +{ + double result = fmod(floor(ms/msPerHour), hoursPerDay); + if (result < 0) + result += hoursPerDay; + return static_cast<int>(result); +} + +static inline int monthFromDayInYear(int dayInYear, bool leapYear) +{ + const int d = dayInYear; + int step; + + if (d < (step = 31)) + return 0; + step += (leapYear ? 29 : 28); + if (d < step) + return 1; + if (d < (step += 31)) + return 2; + if (d < (step += 30)) + return 3; + if (d < (step += 31)) + return 4; + if (d < (step += 30)) + return 5; + if (d < (step += 31)) + return 6; + if (d < (step += 31)) + return 7; + if (d < (step += 30)) + return 8; + if (d < (step += 31)) + return 9; + if (d < (step += 30)) + return 10; + return 11; +} + +static inline bool checkMonth(int dayInYear, int& startDayOfThisMonth, int& startDayOfNextMonth, int daysInThisMonth) +{ + startDayOfThisMonth = startDayOfNextMonth; + startDayOfNextMonth += daysInThisMonth; + return (dayInYear <= startDayOfNextMonth); +} + +static inline int dayInMonthFromDayInYear(int dayInYear, bool leapYear) +{ + const int d = dayInYear; + int step; + int next = 30; + + if (d <= next) + return d + 1; + const int daysInFeb = (leapYear ? 29 : 28); + if (checkMonth(d, step, next, daysInFeb)) + return d - step; + if (checkMonth(d, step, next, 31)) + return d - step; + if (checkMonth(d, step, next, 30)) + return d - step; + if (checkMonth(d, step, next, 31)) + return d - step; + if (checkMonth(d, step, next, 30)) + return d - step; + if (checkMonth(d, step, next, 31)) + return d - step; + if (checkMonth(d, step, next, 31)) + return d - step; + if (checkMonth(d, step, next, 30)) + return d - step; + if (checkMonth(d, step, next, 31)) + return d - step; + if (checkMonth(d, step, next, 30)) + return d - step; + step = next; + return d - step; +} + +static inline int monthToDayInYear(int month, bool isLeapYear) +{ + return firstDayOfMonth[isLeapYear][month]; +} + +static inline double timeToMS(double hour, double min, double sec, double ms) +{ + return (((hour * minutesPerHour + min) * secondsPerMinute + sec) * msPerSecond + ms); +} + +static int dateToDayInYear(int year, int month, int day) +{ + year += month / 12; + + month %= 12; + if (month < 0) { + month += 12; + --year; + } + + int yearday = static_cast<int>(floor(daysFrom1970ToYear(year))); + int monthday = monthToDayInYear(month, isLeapYear(year)); + + return yearday + monthday + day - 1; +} + +double getCurrentUTCTime() +{ + return floor(getCurrentUTCTimeWithMicroseconds()); +} + +// Returns current time in milliseconds since 1 Jan 1970. +double getCurrentUTCTimeWithMicroseconds() +{ + return currentTime() * 1000.0; +} + +void getLocalTime(const time_t* localTime, struct tm* localTM) +{ +#if COMPILER(MSVC7) || COMPILER(MINGW) || PLATFORM(WIN_CE) + *localTM = *localtime(localTime); +#elif COMPILER(MSVC) + localtime_s(localTM, localTime); +#else + localtime_r(localTime, localTM); +#endif +} + +// There is a hard limit at 2038 that we currently do not have a workaround +// for (rdar://problem/5052975). +static inline int maximumYearForDST() +{ + return 2037; +} + +static inline int minimumYearForDST() +{ + // Because of the 2038 issue (see maximumYearForDST) if the current year is + // greater than the max year minus 27 (2010), we want to use the max year + // minus 27 instead, to ensure there is a range of 28 years that all years + // can map to. + return std::min(msToYear(getCurrentUTCTime()), maximumYearForDST() - 27) ; +} + +/* + * Find an equivalent year for the one given, where equivalence is deterined by + * the two years having the same leapness and the first day of the year, falling + * on the same day of the week. + * + * This function returns a year between this current year and 2037, however this + * function will potentially return incorrect results if the current year is after + * 2010, (rdar://problem/5052975), if the year passed in is before 1900 or after + * 2100, (rdar://problem/5055038). + */ +int equivalentYearForDST(int year) +{ + // It is ok if the cached year is not the current year as long as the rules + // for DST did not change between the two years; if they did the app would need + // to be restarted. + static int minYear = minimumYearForDST(); + int maxYear = maximumYearForDST(); + + int difference; + if (year > maxYear) + difference = minYear - year; + else if (year < minYear) + difference = maxYear - year; + else + return year; + + int quotient = difference / 28; + int product = (quotient) * 28; + + year += product; + ASSERT((year >= minYear && year <= maxYear) || (product - year == static_cast<int>(NaN))); + return year; +} + +static int32_t calculateUTCOffset() +{ + tm localt; + memset(&localt, 0, sizeof(localt)); + + // get the difference between this time zone and UTC on Jan 01, 2000 12:00:00 AM + localt.tm_mday = 1; + localt.tm_year = 100; + time_t utcOffset = 946684800 - mktime(&localt); + + return static_cast<int32_t>(utcOffset * 1000); +} + +#if PLATFORM(DARWIN) +static int32_t s_cachedUTCOffset; // In milliseconds. An assumption here is that access to an int32_t variable is atomic on platforms that take this code path. +static bool s_haveCachedUTCOffset; +static int s_notificationToken; +#endif + +/* + * Get the difference in milliseconds between this time zone and UTC (GMT) + * NOT including DST. + */ +double getUTCOffset() +{ +#if PLATFORM(DARWIN) + if (s_haveCachedUTCOffset) { + int notified; + uint32_t status = notify_check(s_notificationToken, ¬ified); + if (status == NOTIFY_STATUS_OK && !notified) + return s_cachedUTCOffset; + } +#endif + + int32_t utcOffset = calculateUTCOffset(); + +#if PLATFORM(DARWIN) + // Theoretically, it is possible that several threads will be executing this code at once, in which case we will have a race condition, + // and a newer value may be overwritten. In practice, time zones don't change that often. + s_cachedUTCOffset = utcOffset; +#endif + + return utcOffset; +} + +/* + * Get the DST offset for the time passed in. Takes + * seconds (not milliseconds) and cannot handle dates before 1970 + * on some OS' + */ +static double getDSTOffsetSimple(double localTimeSeconds, double utcOffset) +{ + if (localTimeSeconds > maxUnixTime) + localTimeSeconds = maxUnixTime; + else if (localTimeSeconds < 0) // Go ahead a day to make localtime work (does not work with 0) + localTimeSeconds += secondsPerDay; + + //input is UTC so we have to shift back to local time to determine DST thus the + getUTCOffset() + double offsetTime = (localTimeSeconds * msPerSecond) + utcOffset; + + // Offset from UTC but doesn't include DST obviously + int offsetHour = msToHours(offsetTime); + int offsetMinute = msToMinutes(offsetTime); + + // FIXME: time_t has a potential problem in 2038 + time_t localTime = static_cast<time_t>(localTimeSeconds); + + tm localTM; + getLocalTime(&localTime, &localTM); + + double diff = ((localTM.tm_hour - offsetHour) * secondsPerHour) + ((localTM.tm_min - offsetMinute) * 60); + + if (diff < 0) + diff += secondsPerDay; + + return (diff * msPerSecond); +} + +// Get the DST offset, given a time in UTC +static double getDSTOffset(double ms, double utcOffset) +{ + // On Mac OS X, the call to localtime (see getDSTOffsetSimple) will return historically accurate + // DST information (e.g. New Zealand did not have DST from 1946 to 1974) however the JavaScript + // standard explicitly dictates that historical information should not be considered when + // determining DST. For this reason we shift away from years that localtime can handle but would + // return historically accurate information. + int year = msToYear(ms); + int equivalentYear = equivalentYearForDST(year); + if (year != equivalentYear) { + bool leapYear = isLeapYear(year); + int dayInYearLocal = dayInYear(ms, year); + int dayInMonth = dayInMonthFromDayInYear(dayInYearLocal, leapYear); + int month = monthFromDayInYear(dayInYearLocal, leapYear); + int day = dateToDayInYear(equivalentYear, month, dayInMonth); + ms = (day * msPerDay) + msToMilliseconds(ms); + } + + return getDSTOffsetSimple(ms / msPerSecond, utcOffset); +} + +double gregorianDateTimeToMS(const GregorianDateTime& t, double milliSeconds, bool inputIsUTC) +{ + int day = dateToDayInYear(t.year + 1900, t.month, t.monthDay); + double ms = timeToMS(t.hour, t.minute, t.second, milliSeconds); + double result = (day * msPerDay) + ms; + + if (!inputIsUTC) { // convert to UTC + double utcOffset = getUTCOffset(); + result -= utcOffset; + result -= getDSTOffset(result, utcOffset); + } + + return result; +} + +void msToGregorianDateTime(double ms, bool outputIsUTC, GregorianDateTime& tm) +{ + // input is UTC + double dstOff = 0.0; + const double utcOff = getUTCOffset(); + + if (!outputIsUTC) { // convert to local time + dstOff = getDSTOffset(ms, utcOff); + ms += dstOff + utcOff; + } + + const int year = msToYear(ms); + tm.second = msToSeconds(ms); + tm.minute = msToMinutes(ms); + tm.hour = msToHours(ms); + tm.weekDay = msToWeekDay(ms); + tm.yearDay = dayInYear(ms, year); + tm.monthDay = dayInMonthFromDayInYear(tm.yearDay, isLeapYear(year)); + tm.month = monthFromDayInYear(tm.yearDay, isLeapYear(year)); + tm.year = year - 1900; + tm.isDST = dstOff != 0.0; + + tm.utcOffset = static_cast<long>((dstOff + utcOff) / msPerSecond); + tm.timeZone = NULL; +} + +void initializeDates() +{ +#ifndef NDEBUG + static bool alreadyInitialized; + ASSERT(!alreadyInitialized++); +#endif + + equivalentYearForDST(2000); // Need to call once to initialize a static used in this function. +#if PLATFORM(DARWIN) + // Register for a notification whenever the time zone changes. + uint32_t status = notify_register_check("com.apple.system.timezone", &s_notificationToken); + if (status == NOTIFY_STATUS_OK) { + s_cachedUTCOffset = calculateUTCOffset(); + s_haveCachedUTCOffset = true; + } +#endif +} + +static inline double ymdhmsToSeconds(long year, int mon, int day, int hour, int minute, int second) +{ + double days = (day - 32075) + + floor(1461 * (year + 4800.0 + (mon - 14) / 12) / 4) + + 367 * (mon - 2 - (mon - 14) / 12 * 12) / 12 + - floor(3 * ((year + 4900.0 + (mon - 14) / 12) / 100) / 4) + - 2440588; + return ((days * hoursPerDay + hour) * minutesPerHour + minute) * secondsPerMinute + second; +} + +// We follow the recommendation of RFC 2822 to consider all +// obsolete time zones not listed here equivalent to "-0000". +static const struct KnownZone { +#if !PLATFORM(WIN_OS) + const +#endif + char tzName[4]; + int tzOffset; +} known_zones[] = { + { "UT", 0 }, + { "GMT", 0 }, + { "EST", -300 }, + { "EDT", -240 }, + { "CST", -360 }, + { "CDT", -300 }, + { "MST", -420 }, + { "MDT", -360 }, + { "PST", -480 }, + { "PDT", -420 } +}; + +inline static void skipSpacesAndComments(const char*& s) +{ + int nesting = 0; + char ch; + while ((ch = *s)) { + if (!isASCIISpace(ch)) { + if (ch == '(') + nesting++; + else if (ch == ')' && nesting > 0) + nesting--; + else if (nesting == 0) + break; + } + s++; + } +} + +// returns 0-11 (Jan-Dec); -1 on failure +static int findMonth(const char* monthStr) +{ + ASSERT(monthStr); + char needle[4]; + for (int i = 0; i < 3; ++i) { + if (!*monthStr) + return -1; + needle[i] = static_cast<char>(toASCIILower(*monthStr++)); + } + needle[3] = '\0'; + const char *haystack = "janfebmaraprmayjunjulaugsepoctnovdec"; + const char *str = strstr(haystack, needle); + if (str) { + int position = static_cast<int>(str - haystack); + if (position % 3 == 0) + return position / 3; + } + return -1; +} + +static bool parseLong(const char* string, char** stopPosition, int base, long* result) +{ + *result = strtol(string, stopPosition, base); + // Avoid the use of errno as it is not available on Windows CE + if (string == *stopPosition || *result == LONG_MIN || *result == LONG_MAX) + return false; + return true; +} + +double parseDateFromNullTerminatedCharacters(const char* dateString) +{ + // This parses a date in the form: + // Tuesday, 09-Nov-99 23:12:40 GMT + // or + // Sat, 01-Jan-2000 08:00:00 GMT + // or + // Sat, 01 Jan 2000 08:00:00 GMT + // or + // 01 Jan 99 22:00 +0100 (exceptions in rfc822/rfc2822) + // ### non RFC formats, added for Javascript: + // [Wednesday] January 09 1999 23:12:40 GMT + // [Wednesday] January 09 23:12:40 GMT 1999 + // + // We ignore the weekday. + + // Skip leading space + skipSpacesAndComments(dateString); + + long month = -1; + const char *wordStart = dateString; + // Check contents of first words if not number + while (*dateString && !isASCIIDigit(*dateString)) { + if (isASCIISpace(*dateString) || *dateString == '(') { + if (dateString - wordStart >= 3) + month = findMonth(wordStart); + skipSpacesAndComments(dateString); + wordStart = dateString; + } else + dateString++; + } + + // Missing delimiter between month and day (like "January29")? + if (month == -1 && wordStart != dateString) + month = findMonth(wordStart); + + skipSpacesAndComments(dateString); + + if (!*dateString) + return NaN; + + // ' 09-Nov-99 23:12:40 GMT' + char* newPosStr; + long day; + if (!parseLong(dateString, &newPosStr, 10, &day)) + return NaN; + dateString = newPosStr; + + if (!*dateString) + return NaN; + + if (day < 0) + return NaN; + + long year = 0; + if (day > 31) { + // ### where is the boundary and what happens below? + if (*dateString != '/') + return NaN; + // looks like a YYYY/MM/DD date + if (!*++dateString) + return NaN; + year = day; + if (!parseLong(dateString, &newPosStr, 10, &month)) + return NaN; + month -= 1; + dateString = newPosStr; + if (*dateString++ != '/' || !*dateString) + return NaN; + if (!parseLong(dateString, &newPosStr, 10, &day)) + return NaN; + dateString = newPosStr; + } else if (*dateString == '/' && month == -1) { + dateString++; + // This looks like a MM/DD/YYYY date, not an RFC date. + month = day - 1; // 0-based + if (!parseLong(dateString, &newPosStr, 10, &day)) + return NaN; + if (day < 1 || day > 31) + return NaN; + dateString = newPosStr; + if (*dateString == '/') + dateString++; + if (!*dateString) + return NaN; + } else { + if (*dateString == '-') + dateString++; + + skipSpacesAndComments(dateString); + + if (*dateString == ',') + dateString++; + + if (month == -1) { // not found yet + month = findMonth(dateString); + if (month == -1) + return NaN; + + while (*dateString && *dateString != '-' && *dateString != ',' && !isASCIISpace(*dateString)) + dateString++; + + if (!*dateString) + return NaN; + + // '-99 23:12:40 GMT' + if (*dateString != '-' && *dateString != '/' && *dateString != ',' && !isASCIISpace(*dateString)) + return NaN; + dateString++; + } + } + + if (month < 0 || month > 11) + return NaN; + + // '99 23:12:40 GMT' + if (year <= 0 && *dateString) { + if (!parseLong(dateString, &newPosStr, 10, &year)) + return NaN; + } + + // Don't fail if the time is missing. + long hour = 0; + long minute = 0; + long second = 0; + if (!*newPosStr) + dateString = newPosStr; + else { + // ' 23:12:40 GMT' + if (!(isASCIISpace(*newPosStr) || *newPosStr == ',')) { + if (*newPosStr != ':') + return NaN; + // There was no year; the number was the hour. + year = -1; + } else { + // in the normal case (we parsed the year), advance to the next number + dateString = ++newPosStr; + skipSpacesAndComments(dateString); + } + + parseLong(dateString, &newPosStr, 10, &hour); + // Do not check for errno here since we want to continue + // even if errno was set becasue we are still looking + // for the timezone! + + // Read a number? If not, this might be a timezone name. + if (newPosStr != dateString) { + dateString = newPosStr; + + if (hour < 0 || hour > 23) + return NaN; + + if (!*dateString) + return NaN; + + // ':12:40 GMT' + if (*dateString++ != ':') + return NaN; + + if (!parseLong(dateString, &newPosStr, 10, &minute)) + return NaN; + dateString = newPosStr; + + if (minute < 0 || minute > 59) + return NaN; + + // ':40 GMT' + if (*dateString && *dateString != ':' && !isASCIISpace(*dateString)) + return NaN; + + // seconds are optional in rfc822 + rfc2822 + if (*dateString ==':') { + dateString++; + + if (!parseLong(dateString, &newPosStr, 10, &second)) + return NaN; + dateString = newPosStr; + + if (second < 0 || second > 59) + return NaN; + } + + skipSpacesAndComments(dateString); + + if (strncasecmp(dateString, "AM", 2) == 0) { + if (hour > 12) + return NaN; + if (hour == 12) + hour = 0; + dateString += 2; + skipSpacesAndComments(dateString); + } else if (strncasecmp(dateString, "PM", 2) == 0) { + if (hour > 12) + return NaN; + if (hour != 12) + hour += 12; + dateString += 2; + skipSpacesAndComments(dateString); + } + } + } + + bool haveTZ = false; + int offset = 0; + + // Don't fail if the time zone is missing. + // Some websites omit the time zone (4275206). + if (*dateString) { + if (strncasecmp(dateString, "GMT", 3) == 0 || strncasecmp(dateString, "UTC", 3) == 0) { + dateString += 3; + haveTZ = true; + } + + if (*dateString == '+' || *dateString == '-') { + long o; + if (!parseLong(dateString, &newPosStr, 10, &o)) + return NaN; + dateString = newPosStr; + + if (o < -9959 || o > 9959) + return NaN; + + int sgn = (o < 0) ? -1 : 1; + o = abs(o); + if (*dateString != ':') { + offset = ((o / 100) * 60 + (o % 100)) * sgn; + } else { // GMT+05:00 + long o2; + if (!parseLong(dateString, &newPosStr, 10, &o2)) + return NaN; + dateString = newPosStr; + offset = (o * 60 + o2) * sgn; + } + haveTZ = true; + } else { + for (int i = 0; i < int(sizeof(known_zones) / sizeof(KnownZone)); i++) { + if (0 == strncasecmp(dateString, known_zones[i].tzName, strlen(known_zones[i].tzName))) { + offset = known_zones[i].tzOffset; + dateString += strlen(known_zones[i].tzName); + haveTZ = true; + break; + } + } + } + } + + skipSpacesAndComments(dateString); + + if (*dateString && year == -1) { + if (!parseLong(dateString, &newPosStr, 10, &year)) + return NaN; + dateString = newPosStr; + } + + skipSpacesAndComments(dateString); + + // Trailing garbage + if (*dateString) + return NaN; + + // Y2K: Handle 2 digit years. + if (year >= 0 && year < 100) { + if (year < 50) + year += 2000; + else + year += 1900; + } + + // fall back to local timezone + if (!haveTZ) { + GregorianDateTime t; + t.monthDay = day; + t.month = month; + t.year = year - 1900; + t.isDST = -1; + t.second = second; + t.minute = minute; + t.hour = hour; + + // Use our gregorianDateTimeToMS() rather than mktime() as the latter can't handle the full year range. + return gregorianDateTimeToMS(t, 0, false); + } + + return (ymdhmsToSeconds(year, month + 1, day, hour, minute, second) - (offset * 60.0)) * msPerSecond; +} + +double timeClip(double t) +{ + if (!isfinite(t)) + return NaN; + if (fabs(t) > 8.64E15) + return NaN; + return trunc(t); +} + + +} // namespace WTF diff --git a/JavaScriptCore/wtf/DateMath.h b/JavaScriptCore/wtf/DateMath.h new file mode 100644 index 0000000..8690a49 --- /dev/null +++ b/JavaScriptCore/wtf/DateMath.h @@ -0,0 +1,187 @@ +/* + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + */ + +#ifndef DateMath_h +#define DateMath_h + +#include <time.h> +#include <string.h> +#include <wtf/Noncopyable.h> + +namespace WTF { + +struct GregorianDateTime; + +void initializeDates(); +void msToGregorianDateTime(double, bool outputIsUTC, GregorianDateTime&); +double gregorianDateTimeToMS(const GregorianDateTime&, double, bool inputIsUTC); +double getUTCOffset(); +int equivalentYearForDST(int year); +double getCurrentUTCTime(); +double getCurrentUTCTimeWithMicroseconds(); +void getLocalTime(const time_t*, tm*); + +// Not really math related, but this is currently the only shared place to put these. +double parseDateFromNullTerminatedCharacters(const char*); +double timeClip(double); + +const char * const weekdayName[7] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" }; +const char * const monthName[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + +const double hoursPerDay = 24.0; +const double minutesPerHour = 60.0; +const double secondsPerHour = 60.0 * 60.0; +const double secondsPerMinute = 60.0; +const double msPerSecond = 1000.0; +const double msPerMinute = 60.0 * 1000.0; +const double msPerHour = 60.0 * 60.0 * 1000.0; +const double msPerDay = 24.0 * 60.0 * 60.0 * 1000.0; + +// Intentionally overridding the default tm of the system +// Tee members of tm differ on various operating systems. +struct GregorianDateTime : Noncopyable { + GregorianDateTime() + : second(0) + , minute(0) + , hour(0) + , weekDay(0) + , monthDay(0) + , yearDay(0) + , month(0) + , year(0) + , isDST(0) + , utcOffset(0) + , timeZone(0) + { + } + + ~GregorianDateTime() + { + delete [] timeZone; + } + + GregorianDateTime(const tm& inTm) + : second(inTm.tm_sec) + , minute(inTm.tm_min) + , hour(inTm.tm_hour) + , weekDay(inTm.tm_wday) + , monthDay(inTm.tm_mday) + , yearDay(inTm.tm_yday) + , month(inTm.tm_mon) + , year(inTm.tm_year) + , isDST(inTm.tm_isdst) + { +#if !PLATFORM(WIN_OS) && !PLATFORM(SOLARIS) && !COMPILER(RVCT) + utcOffset = static_cast<int>(inTm.tm_gmtoff); + + int inZoneSize = strlen(inTm.tm_zone) + 1; + timeZone = new char[inZoneSize]; + strncpy(timeZone, inTm.tm_zone, inZoneSize); +#else + utcOffset = static_cast<int>(getUTCOffset() / msPerSecond + (isDST ? secondsPerHour : 0)); + timeZone = 0; +#endif + } + + operator tm() const + { + tm ret; + memset(&ret, 0, sizeof(ret)); + + ret.tm_sec = second; + ret.tm_min = minute; + ret.tm_hour = hour; + ret.tm_wday = weekDay; + ret.tm_mday = monthDay; + ret.tm_yday = yearDay; + ret.tm_mon = month; + ret.tm_year = year; + ret.tm_isdst = isDST; + +#if !PLATFORM(WIN_OS) && !PLATFORM(SOLARIS) && !COMPILER(RVCT) + ret.tm_gmtoff = static_cast<long>(utcOffset); + ret.tm_zone = timeZone; +#endif + + return ret; + } + + void copyFrom(const GregorianDateTime& rhs) + { + second = rhs.second; + minute = rhs.minute; + hour = rhs.hour; + weekDay = rhs.weekDay; + monthDay = rhs.monthDay; + yearDay = rhs.yearDay; + month = rhs.month; + year = rhs.year; + isDST = rhs.isDST; + utcOffset = rhs.utcOffset; + if (rhs.timeZone) { + int inZoneSize = strlen(rhs.timeZone) + 1; + timeZone = new char[inZoneSize]; + strncpy(timeZone, rhs.timeZone, inZoneSize); + } else + timeZone = 0; + } + + int second; + int minute; + int hour; + int weekDay; + int monthDay; + int yearDay; + int month; + int year; + int isDST; + int utcOffset; + char* timeZone; +}; + +static inline int gmtoffset(const GregorianDateTime& t) +{ + return t.utcOffset; +} + +} // namespace WTF + +#endif // DateMath_h diff --git a/JavaScriptCore/wtf/FastAllocBase.h b/JavaScriptCore/wtf/FastAllocBase.h new file mode 100644 index 0000000..71e6bfa --- /dev/null +++ b/JavaScriptCore/wtf/FastAllocBase.h @@ -0,0 +1,400 @@ +/* + * Copyright (C) 2008, 2009 Paul Pedriana <ppedriana@ea.com>. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef FastAllocBase_h +#define FastAllocBase_h + +// Provides customizable overrides of fastMalloc/fastFree and operator new/delete +// +// Provided functionality: +// namespace WTF { +// class FastAllocBase; +// +// T* fastNew<T>(); +// T* fastNew<T>(arg); +// T* fastNew<T>(arg, arg); +// T* fastNewArray<T>(count); +// void fastDelete(T* p); +// void fastDeleteArray(T* p); +// void fastNonNullDelete(T* p); +// void fastNonNullDeleteArray(T* p); +// } +// +// FastDelete assumes that the underlying +// +// Example usage: +// class Widget : public FastAllocBase { ... }; +// +// char* charPtr = fastNew<char>(); +// fastDelete(charPtr); +// +// char* charArrayPtr = fastNewArray<char>(37); +// fastDeleteArray(charArrayPtr); +// +// void** voidPtrPtr = fastNew<void*>(); +// fastDelete(voidPtrPtr); +// +// void** voidPtrArrayPtr = fastNewArray<void*>(37); +// fastDeleteArray(voidPtrArrayPtr); +// +// POD* podPtr = fastNew<POD>(); +// fastDelete(podPtr); +// +// POD* podArrayPtr = fastNewArray<POD>(37); +// fastDeleteArray(podArrayPtr); +// +// Object* objectPtr = fastNew<Object>(); +// fastDelete(objectPtr); +// +// Object* objectArrayPtr = fastNewArray<Object>(37); +// fastDeleteArray(objectArrayPtr); +// + +#include <new> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include "FastMalloc.h" +#include "TypeTraits.h" +#include <wtf/Assertions.h> + +namespace WTF { + + class FastAllocBase { + public: + // Placement operator new. + void* operator new(size_t, void* p) { return p; } + void* operator new[](size_t, void* p) { return p; } + + void* operator new(size_t size) + { + void* p = fastMalloc(size); + fastMallocMatchValidateMalloc(p, Internal::AllocTypeClassNew); + return p; + } + + void operator delete(void* p) + { + fastMallocMatchValidateFree(p, Internal::AllocTypeClassNew); + fastFree(p); + } + + void* operator new[](size_t size) + { + void* p = fastMalloc(size); + fastMallocMatchValidateMalloc(p, Internal::AllocTypeClassNewArray); + return p; + } + + void operator delete[](void* p) + { + fastMallocMatchValidateFree(p, Internal::AllocTypeClassNewArray); + fastFree(p); + } + }; + + // fastNew / fastDelete + + template <typename T> + inline T* fastNew() + { + void* p = fastMalloc(sizeof(T)); + + if (!p) + return 0; + + fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew); + return ::new(p) T; + } + + template <typename T, typename Arg1> + inline T* fastNew(Arg1 arg1) + { + void* p = fastMalloc(sizeof(T)); + + if (!p) + return 0; + + fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew); + return ::new(p) T(arg1); + } + + template <typename T, typename Arg1, typename Arg2> + inline T* fastNew(Arg1 arg1, Arg2 arg2) + { + void* p = fastMalloc(sizeof(T)); + + if (!p) + return 0; + + fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew); + return ::new(p) T(arg1, arg2); + } + + template <typename T, typename Arg1, typename Arg2, typename Arg3> + inline T* fastNew(Arg1 arg1, Arg2 arg2, Arg3 arg3) + { + void* p = fastMalloc(sizeof(T)); + + if (!p) + return 0; + + fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew); + return ::new(p) T(arg1, arg2, arg3); + } + + template <typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4> + inline T* fastNew(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) + { + void* p = fastMalloc(sizeof(T)); + + if (!p) + return 0; + + fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew); + return ::new(p) T(arg1, arg2, arg3, arg4); + } + + template <typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5> + inline T* fastNew(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5) + { + void* p = fastMalloc(sizeof(T)); + + if (!p) + return 0; + + fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew); + return ::new(p) T(arg1, arg2, arg3, arg4, arg5); + } + + namespace Internal { + + // We define a union of pointer to an integer and pointer to T. + // When non-POD arrays are allocated we add a few leading bytes to tell what + // the size of the array is. We return to the user the pointer to T. + // The way to think of it is as if we allocate a struct like so: + // struct Array { + // AllocAlignmentInteger m_size; + // T m_T[array count]; + // }; + + template <typename T> + union ArraySize { + AllocAlignmentInteger* size; + T* t; + }; + + // This is a support template for fastNewArray. + // This handles the case wherein T has a trivial ctor and a trivial dtor. + template <typename T, bool trivialCtor, bool trivialDtor> + struct NewArrayImpl { + static T* fastNewArray(size_t count) + { + T* p = static_cast<T*>(fastMalloc(sizeof(T) * count)); + fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray); + return p; + } + }; + + // This is a support template for fastNewArray. + // This handles the case wherein T has a non-trivial ctor and a trivial dtor. + template <typename T> + struct NewArrayImpl<T, false, true> { + static T* fastNewArray(size_t count) + { + T* p = static_cast<T*>(fastMalloc(sizeof(T) * count)); + + if (!p) + return 0; + + fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray); + + for (T* pObject = p, *pObjectEnd = pObject + count; pObject != pObjectEnd; ++pObject) + ::new(pObject) T; + + return p; + } + }; + + // This is a support template for fastNewArray. + // This handles the case wherein T has a trivial ctor and a non-trivial dtor. + template <typename T> + struct NewArrayImpl<T, true, false> { + static T* fastNewArray(size_t count) + { + void* p = fastMalloc(sizeof(AllocAlignmentInteger) + (sizeof(T) * count)); + ArraySize<T> a = { static_cast<AllocAlignmentInteger*>(p) }; + + if (!p) + return 0; + + fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray); + *a.size++ = count; + // No need to construct the objects in this case. + + return a.t; + } + }; + + // This is a support template for fastNewArray. + // This handles the case wherein T has a non-trivial ctor and a non-trivial dtor. + template <typename T> + struct NewArrayImpl<T, false, false> { + static T* fastNewArray(size_t count) + { + void* p = fastMalloc(sizeof(AllocAlignmentInteger) + (sizeof(T) * count)); + ArraySize<T> a = { static_cast<AllocAlignmentInteger*>(p) }; + + if (!p) + return 0; + + fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray); + *a.size++ = count; + + for (T* pT = a.t, *pTEnd = pT + count; pT != pTEnd; ++pT) + ::new(pT) T; + + return a.t; + } + }; + } // namespace Internal + + template <typename T> + inline T* fastNewArray(size_t count) + { + return Internal::NewArrayImpl<T, WTF::HasTrivialConstructor<T>::value, WTF::HasTrivialDestructor<T>::value>::fastNewArray(count); + } + + template <typename T> + inline void fastDelete(T* p) + { + if (!p) + return; + + fastMallocMatchValidateFree(p, Internal::AllocTypeFastNew); + p->~T(); + fastFree(p); + } + + namespace Internal { + // This is a support template for fastDeleteArray. + // This handles the case wherein T has a trivial dtor. + template <typename T, bool trivialDtor> + struct DeleteArrayImpl { + static void fastDeleteArray(void* p) + { + // No need to destruct the objects in this case. + // We expect that fastFree checks for null. + fastMallocMatchValidateFree(p, Internal::AllocTypeFastNewArray); + fastFree(p); + } + }; + + // This is a support template for fastDeleteArray. + // This handles the case wherein T has a non-trivial dtor. + template <typename T> + struct DeleteArrayImpl<T, false> { + static void fastDeleteArray(T* p) + { + if (!p) + return; + + ArraySize<T> a; + a.t = p; + a.size--; // Decrement size pointer + + T* pEnd = p + *a.size; + while (pEnd-- != p) + pEnd->~T(); + + fastMallocMatchValidateFree(a.size, Internal::AllocTypeFastNewArray); + fastFree(a.size); + } + }; + + } // namespace Internal + + template <typename T> + void fastDeleteArray(T* p) + { + Internal::DeleteArrayImpl<T, WTF::HasTrivialDestructor<T>::value>::fastDeleteArray(p); + } + + + template <typename T> + inline void fastNonNullDelete(T* p) + { + fastMallocMatchValidateFree(p, Internal::AllocTypeFastNew); + p->~T(); + fastFree(p); + } + + namespace Internal { + // This is a support template for fastDeleteArray. + // This handles the case wherein T has a trivial dtor. + template <typename T, bool trivialDtor> + struct NonNullDeleteArrayImpl { + static void fastNonNullDeleteArray(void* p) + { + fastMallocMatchValidateFree(p, Internal::AllocTypeFastNewArray); + // No need to destruct the objects in this case. + fastFree(p); + } + }; + + // This is a support template for fastDeleteArray. + // This handles the case wherein T has a non-trivial dtor. + template <typename T> + struct NonNullDeleteArrayImpl<T, false> { + static void fastNonNullDeleteArray(T* p) + { + ArraySize<T> a; + a.t = p; + a.size--; + + T* pEnd = p + *a.size; + while (pEnd-- != p) + pEnd->~T(); + + fastMallocMatchValidateFree(a.size, Internal::AllocTypeFastNewArray); + fastFree(a.size); + } + }; + + } // namespace Internal + + template <typename T> + void fastNonNullDeleteArray(T* p) + { + Internal::NonNullDeleteArrayImpl<T, WTF::HasTrivialDestructor<T>::value>::fastNonNullDeleteArray(p); + } + + +} // namespace WTF + +#endif // FastAllocBase_h diff --git a/JavaScriptCore/wtf/FastMalloc.cpp b/JavaScriptCore/wtf/FastMalloc.cpp index bcac242..c65ba85 100644 --- a/JavaScriptCore/wtf/FastMalloc.cpp +++ b/JavaScriptCore/wtf/FastMalloc.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2005, 2007, The Android Open Source Project +// Copyright (c) 2005, 2007, Google Inc. // All rights reserved. // Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. // @@ -78,6 +78,7 @@ #include "FastMalloc.h" #include "Assertions.h" +#include <limits> #if ENABLE(JSC_MULTIPLE_THREADS) #include <pthread.h> #endif @@ -151,6 +152,19 @@ void fastMallocAllow() namespace WTF { +#if ENABLE(FAST_MALLOC_MATCH_VALIDATION) + +namespace Internal { + +void fastMallocMatchFailed(void*) +{ + CRASH(); +} + +} // namespace Internal + +#endif + void* fastZeroedMalloc(size_t n) { void* result = fastMalloc(n); @@ -183,13 +197,34 @@ namespace WTF { void* tryFastMalloc(size_t n) { ASSERT(!isForbidden()); + +#if ENABLE(FAST_MALLOC_MATCH_VALIDATION) + if (std::numeric_limits<size_t>::max() - sizeof(AllocAlignmentInteger) <= n) // If overflow would occur... + return 0; + + void* result = malloc(n + sizeof(AllocAlignmentInteger)); + if (!result) + return 0; + + *static_cast<AllocAlignmentInteger*>(result) = Internal::AllocTypeMalloc; + result = static_cast<AllocAlignmentInteger*>(result) + 1; + + return result; +#else return malloc(n); +#endif } void* fastMalloc(size_t n) { ASSERT(!isForbidden()); + +#if ENABLE(FAST_MALLOC_MATCH_VALIDATION) + void* result = tryFastMalloc(n); +#else void* result = malloc(n); +#endif + if (!result) CRASH(); return result; @@ -198,13 +233,36 @@ void* fastMalloc(size_t n) void* tryFastCalloc(size_t n_elements, size_t element_size) { ASSERT(!isForbidden()); + +#if ENABLE(FAST_MALLOC_MATCH_VALIDATION) + size_t totalBytes = n_elements * element_size; + if (n_elements > 1 && element_size && (totalBytes / element_size) != n_elements || (std::numeric_limits<size_t>::max() - sizeof(AllocAlignmentInteger) <= totalBytes)) + return 0; + + totalBytes += sizeof(AllocAlignmentInteger); + void* result = malloc(totalBytes); + if (!result) + return 0; + + memset(result, 0, totalBytes); + *static_cast<AllocAlignmentInteger*>(result) = Internal::AllocTypeMalloc; + result = static_cast<AllocAlignmentInteger*>(result) + 1; + return result; +#else return calloc(n_elements, element_size); +#endif } void* fastCalloc(size_t n_elements, size_t element_size) { ASSERT(!isForbidden()); + +#if ENABLE(FAST_MALLOC_MATCH_VALIDATION) + void* result = tryFastCalloc(n_elements, element_size); +#else void* result = calloc(n_elements, element_size); +#endif + if (!result) CRASH(); return result; @@ -213,19 +271,57 @@ void* fastCalloc(size_t n_elements, size_t element_size) void fastFree(void* p) { ASSERT(!isForbidden()); + +#if ENABLE(FAST_MALLOC_MATCH_VALIDATION) + if (!p) + return; + + AllocAlignmentInteger* header = Internal::fastMallocMatchValidationValue(p); + if (*header != Internal::AllocTypeMalloc) + Internal::fastMallocMatchFailed(p); + free(header); +#else free(p); +#endif } void* tryFastRealloc(void* p, size_t n) { ASSERT(!isForbidden()); + +#if ENABLE(FAST_MALLOC_MATCH_VALIDATION) + if (p) { + if (std::numeric_limits<size_t>::max() - sizeof(AllocAlignmentInteger) <= n) // If overflow would occur... + return 0; + AllocAlignmentInteger* header = Internal::fastMallocMatchValidationValue(p); + if (*header != Internal::AllocTypeMalloc) + Internal::fastMallocMatchFailed(p); + void* result = realloc(header, n + sizeof(AllocAlignmentInteger)); + if (!result) + return 0; + + // This should not be needed because the value is already there: + // *static_cast<AllocAlignmentInteger*>(result) = Internal::AllocTypeMalloc; + result = static_cast<AllocAlignmentInteger*>(result) + 1; + return result; + } else { + return fastMalloc(n); + } +#else return realloc(p, n); +#endif } void* fastRealloc(void* p, size_t n) { ASSERT(!isForbidden()); + +#if ENABLE(FAST_MALLOC_MATCH_VALIDATION) + void* result = tryFastRealloc(p, n); +#else void* result = realloc(p, n); +#endif + if (!result) CRASH(); return result; @@ -265,6 +361,7 @@ extern "C" const int jscore_fastmalloc_introspection = 0; #include "TCSystemAlloc.h" #include <algorithm> #include <errno.h> +#include <limits> #include <new> #include <pthread.h> #include <stdarg.h> @@ -3294,7 +3391,20 @@ template <bool crashOnFailure> ALWAYS_INLINE #endif void* malloc(size_t size) { - void* result = do_malloc(size); +#if ENABLE(FAST_MALLOC_MATCH_VALIDATION) + if (std::numeric_limits<size_t>::max() - sizeof(AllocAlignmentInteger) <= size) // If overflow would occur... + return 0; + size += sizeof(AllocAlignmentInteger); + void* result = do_malloc(size); + if (!result) + return 0; + + *static_cast<AllocAlignmentInteger*>(result) = Internal::AllocTypeMalloc; + result = static_cast<AllocAlignmentInteger*>(result) + 1; +#else + void* result = do_malloc(size); +#endif + #ifndef WTF_CHANGES MallocHook::InvokeNewHook(result, size); #endif @@ -3308,7 +3418,18 @@ void free(void* ptr) { #ifndef WTF_CHANGES MallocHook::InvokeDeleteHook(ptr); #endif - do_free(ptr); + +#if ENABLE(FAST_MALLOC_MATCH_VALIDATION) + if (!ptr) + return; + + AllocAlignmentInteger* header = Internal::fastMallocMatchValidationValue(ptr); + if (*header != Internal::AllocTypeMalloc) + Internal::fastMallocMatchFailed(ptr); + do_free(header); +#else + do_free(ptr); +#endif } #ifndef WTF_CHANGES @@ -3331,16 +3452,31 @@ template <bool crashOnFailure> ALWAYS_INLINE #endif void* calloc(size_t n, size_t elem_size) { - const size_t totalBytes = n * elem_size; + size_t totalBytes = n * elem_size; // Protect against overflow if (n > 1 && elem_size && (totalBytes / elem_size) != n) return 0; - - void* result = do_malloc(totalBytes); - if (result != NULL) { + +#if ENABLE(FAST_MALLOC_MATCH_VALIDATION) + if (std::numeric_limits<size_t>::max() - sizeof(AllocAlignmentInteger) <= totalBytes) // If overflow would occur... + return 0; + + totalBytes += sizeof(AllocAlignmentInteger); + void* result = do_malloc(totalBytes); + if (!result) + return 0; + memset(result, 0, totalBytes); - } + *static_cast<AllocAlignmentInteger*>(result) = Internal::AllocTypeMalloc; + result = static_cast<AllocAlignmentInteger*>(result) + 1; +#else + void* result = do_malloc(totalBytes); + if (result != NULL) { + memset(result, 0, totalBytes); + } +#endif + #ifndef WTF_CHANGES MallocHook::InvokeNewHook(result, totalBytes); #endif @@ -3381,10 +3517,14 @@ ALWAYS_INLINE #endif void* realloc(void* old_ptr, size_t new_size) { if (old_ptr == NULL) { +#if ENABLE(FAST_MALLOC_MATCH_VALIDATION) + void* result = malloc(new_size); +#else void* result = do_malloc(new_size); #ifndef WTF_CHANGES MallocHook::InvokeNewHook(result, new_size); #endif +#endif return result; } if (new_size == 0) { @@ -3395,6 +3535,16 @@ void* realloc(void* old_ptr, size_t new_size) { return NULL; } +#if ENABLE(FAST_MALLOC_MATCH_VALIDATION) + if (std::numeric_limits<size_t>::max() - sizeof(AllocAlignmentInteger) <= new_size) // If overflow would occur... + return 0; + new_size += sizeof(AllocAlignmentInteger); + AllocAlignmentInteger* header = Internal::fastMallocMatchValidationValue(old_ptr); + if (*header != Internal::AllocTypeMalloc) + Internal::fastMallocMatchFailed(old_ptr); + old_ptr = header; +#endif + // Get the size of the old entry const PageID p = reinterpret_cast<uintptr_t>(old_ptr) >> kPageShift; size_t cl = pageheap->GetSizeClassIfCached(p); @@ -3431,8 +3581,14 @@ void* realloc(void* old_ptr, size_t new_size) { // that we already know the sizeclass of old_ptr. The benefit // would be small, so don't bother. do_free(old_ptr); +#if ENABLE(FAST_MALLOC_MATCH_VALIDATION) + new_ptr = static_cast<AllocAlignmentInteger*>(new_ptr) + 1; +#endif return new_ptr; } else { +#if ENABLE(FAST_MALLOC_MATCH_VALIDATION) + old_ptr = pByte + sizeof(AllocAlignmentInteger); // Set old_ptr back to the user pointer. +#endif return old_ptr; } } @@ -3933,7 +4089,7 @@ extern "C" { malloc_introspection_t jscore_fastmalloc_introspection = { &FastMallocZone::enumerate, &FastMallocZone::goodSize, &FastMallocZone::check, &FastMallocZone::print, &FastMallocZone::log, &FastMallocZone::forceLock, &FastMallocZone::forceUnlock, &FastMallocZone::statistics -#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) +#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !PLATFORM(IPHONE) , 0 // zone_locked will not be called on the zone unless it advertises itself as version five or higher. #endif diff --git a/JavaScriptCore/wtf/FastMalloc.h b/JavaScriptCore/wtf/FastMalloc.h index f1264ac..9e13cf9 100644 --- a/JavaScriptCore/wtf/FastMalloc.h +++ b/JavaScriptCore/wtf/FastMalloc.h @@ -56,6 +56,95 @@ namespace WTF { }; FastMallocStatistics fastMallocStatistics(); + // This defines a type which holds an unsigned integer and is the same + // size as the minimally aligned memory allocation. + typedef unsigned long long AllocAlignmentInteger; + + namespace Internal { + enum AllocType { // Start with an unusual number instead of zero, because zero is common. + AllocTypeMalloc = 0x375d6750, // Encompasses fastMalloc, fastZeroedMalloc, fastCalloc, fastRealloc. + AllocTypeClassNew, // Encompasses class operator new from FastAllocBase. + AllocTypeClassNewArray, // Encompasses class operator new[] from FastAllocBase. + AllocTypeFastNew, // Encompasses fastNew. + AllocTypeFastNewArray, // Encompasses fastNewArray. + AllocTypeNew, // Encompasses global operator new. + AllocTypeNewArray // Encompasses global operator new[]. + }; + } + +#if ENABLE(FAST_MALLOC_MATCH_VALIDATION) + + // Malloc validation is a scheme whereby a tag is attached to an + // allocation which identifies how it was originally allocated. + // This allows us to verify that the freeing operation matches the + // allocation operation. If memory is allocated with operator new[] + // but freed with free or delete, this system would detect that. + // In the implementation here, the tag is an integer prepended to + // the allocation memory which is assigned one of the AllocType + // enumeration values. An alternative implementation of this + // scheme could store the tag somewhere else or ignore it. + // Users of FastMalloc don't need to know or care how this tagging + // is implemented. + + namespace Internal { + + // Return the AllocType tag associated with the allocated block p. + inline AllocType fastMallocMatchValidationType(const void* p) + { + const AllocAlignmentInteger* type = static_cast<const AllocAlignmentInteger*>(p) - 1; + return static_cast<AllocType>(*type); + } + + // Return the address of the AllocType tag associated with the allocated block p. + inline AllocAlignmentInteger* fastMallocMatchValidationValue(void* p) + { + return reinterpret_cast<AllocAlignmentInteger*>(static_cast<char*>(p) - sizeof(AllocAlignmentInteger)); + } + + // Set the AllocType tag to be associaged with the allocated block p. + inline void setFastMallocMatchValidationType(void* p, AllocType allocType) + { + AllocAlignmentInteger* type = static_cast<AllocAlignmentInteger*>(p) - 1; + *type = static_cast<AllocAlignmentInteger>(allocType); + } + + // Handle a detected alloc/free mismatch. By default this calls CRASH(). + void fastMallocMatchFailed(void* p); + + } // namespace Internal + + // This is a higher level function which is used by FastMalloc-using code. + inline void fastMallocMatchValidateMalloc(void* p, Internal::AllocType allocType) + { + if (!p) + return; + + Internal::setFastMallocMatchValidationType(p, allocType); + } + + // This is a higher level function which is used by FastMalloc-using code. + inline void fastMallocMatchValidateFree(void* p, Internal::AllocType allocType) + { + if (!p) + return; + + if (Internal::fastMallocMatchValidationType(p) != allocType) + Internal::fastMallocMatchFailed(p); + Internal::setFastMallocMatchValidationType(p, Internal::AllocTypeMalloc); // Set it to this so that fastFree thinks it's OK. + } + +#else + + inline void fastMallocMatchValidateMalloc(void*, Internal::AllocType) + { + } + + inline void fastMallocMatchValidateFree(void*, Internal::AllocType) + { + } + +#endif + } // namespace WTF using WTF::fastMalloc; diff --git a/JavaScriptCore/wtf/GOwnPtr.cpp b/JavaScriptCore/wtf/GOwnPtr.cpp index 58869f4..432885f 100644 --- a/JavaScriptCore/wtf/GOwnPtr.cpp +++ b/JavaScriptCore/wtf/GOwnPtr.cpp @@ -56,4 +56,10 @@ template <> void freeOwnedGPtr<GDir>(GDir* ptr) g_dir_close(ptr); } +template <> void freeOwnedGPtr<GHashTable>(GHashTable* ptr) +{ + if (ptr) + g_hash_table_unref(ptr); +} + } // namespace WTF diff --git a/JavaScriptCore/wtf/GOwnPtr.h b/JavaScriptCore/wtf/GOwnPtr.h index bbb793a..8d03ff2 100644 --- a/JavaScriptCore/wtf/GOwnPtr.h +++ b/JavaScriptCore/wtf/GOwnPtr.h @@ -35,6 +35,7 @@ namespace WTF { template<> void freeOwnedGPtr<GMutex>(GMutex*); template<> void freeOwnedGPtr<GPatternSpec>(GPatternSpec*); template<> void freeOwnedGPtr<GDir>(GDir*); + template<> void freeOwnedGPtr<GHashTable>(GHashTable*); template <typename T> class GOwnPtr : Noncopyable { public: diff --git a/JavaScriptCore/wtf/NotFound.h b/JavaScriptCore/wtf/NotFound.h index f0bb866..4263bce 100644 --- a/JavaScriptCore/wtf/NotFound.h +++ b/JavaScriptCore/wtf/NotFound.h @@ -32,4 +32,6 @@ namespace WTF { } // namespace WTF +using WTF::notFound; + #endif // NotFound_h diff --git a/JavaScriptCore/wtf/OwnFastMallocPtr.h b/JavaScriptCore/wtf/OwnFastMallocPtr.h new file mode 100644 index 0000000..5c0d064 --- /dev/null +++ b/JavaScriptCore/wtf/OwnFastMallocPtr.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef OwnFastMallocPtr_h +#define OwnFastMallocPtr_h + +#include "FastMalloc.h" +#include "Noncopyable.h" + +namespace WTF { + + template<class T> class OwnFastMallocPtr : Noncopyable { + public: + explicit OwnFastMallocPtr(T* ptr) : m_ptr(ptr) + { + } + + ~OwnFastMallocPtr() + { + fastFree(m_ptr); + } + + T* get() const { return m_ptr; } + T* release() { T* ptr = m_ptr; m_ptr = 0; return ptr; } + + private: + T* m_ptr; + }; + +} // namespace WTF + +using WTF::OwnFastMallocPtr; + +#endif // OwnFastMallocPtr_h diff --git a/JavaScriptCore/wtf/OwnPtr.h b/JavaScriptCore/wtf/OwnPtr.h index af939e7..9e4bd32 100644 --- a/JavaScriptCore/wtf/OwnPtr.h +++ b/JavaScriptCore/wtf/OwnPtr.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -23,40 +23,16 @@ #include "Assertions.h" #include "Noncopyable.h" +#include "OwnPtrCommon.h" #include "TypeTraits.h" #include <algorithm> #include <memory> -#if PLATFORM(WIN) - -typedef struct HBITMAP__* HBITMAP; -typedef struct HBRUSH__* HBRUSH; -typedef struct HFONT__* HFONT; -typedef struct HPALETTE__* HPALETTE; -typedef struct HPEN__* HPEN; -typedef struct HRGN__* HRGN; - -#endif - namespace WTF { // Unlike most of our smart pointers, OwnPtr can take either the pointer type or the pointed-to type. - template <typename T> inline void deleteOwnedPtr(T* ptr) - { - typedef char known[sizeof(T) ? 1 : -1]; - if (sizeof(known)) - delete ptr; - } - -#if PLATFORM(WIN) - void deleteOwnedPtr(HBITMAP); - void deleteOwnedPtr(HBRUSH); - void deleteOwnedPtr(HFONT); - void deleteOwnedPtr(HPALETTE); - void deleteOwnedPtr(HPEN); - void deleteOwnedPtr(HRGN); -#endif + template <typename T> class PassOwnPtr; template <typename T> class OwnPtr : Noncopyable { public: @@ -65,6 +41,15 @@ namespace WTF { explicit OwnPtr(PtrType ptr = 0) : m_ptr(ptr) { } OwnPtr(std::auto_ptr<ValueType> autoPtr) : m_ptr(autoPtr.release()) { } + // See comment in PassOwnPtr.h for why this takes a const reference. + template <typename U> OwnPtr(const PassOwnPtr<U>& o); + + // This copy constructor is used implicitly by gcc when it generates + // transients for assigning a PassOwnPtr<T> object to a stack-allocated + // OwnPtr<T> object. It should never be called explicitly and gcc + // should optimize away the constructor when generating code. + OwnPtr(const OwnPtr<ValueType>& o); + ~OwnPtr() { deleteOwnedPtr(m_ptr); } PtrType get() const { return m_ptr; } @@ -86,19 +71,50 @@ namespace WTF { typedef PtrType OwnPtr::*UnspecifiedBoolType; operator UnspecifiedBoolType() const { return m_ptr ? &OwnPtr::m_ptr : 0; } + OwnPtr& operator=(const PassOwnPtr<T>&); + template <typename U> OwnPtr& operator=(const PassOwnPtr<U>&); + void swap(OwnPtr& o) { std::swap(m_ptr, o.m_ptr); } private: PtrType m_ptr; }; - - template <typename T> inline void swap(OwnPtr<T>& a, OwnPtr<T>& b) { a.swap(b); } + + template <typename T> template <typename U> inline OwnPtr<T>::OwnPtr(const PassOwnPtr<U>& o) + : m_ptr(o.release()) + { + } + + template <typename T> inline OwnPtr<T>& OwnPtr<T>::operator=(const PassOwnPtr<T>& o) + { + T* ptr = m_ptr; + m_ptr = o.release(); + ASSERT(!ptr || m_ptr != ptr); + if (ptr) + deleteOwnedPtr(ptr); + return *this; + } + + template <typename T> template <typename U> inline OwnPtr<T>& OwnPtr<T>::operator=(const PassOwnPtr<U>& o) + { + T* ptr = m_ptr; + m_ptr = o.release(); + ASSERT(!ptr || m_ptr != ptr); + if (ptr) + deleteOwnedPtr(ptr); + return *this; + } + + template <typename T> inline void swap(OwnPtr<T>& a, OwnPtr<T>& b) + { + a.swap(b); + } template <typename T, typename U> inline bool operator==(const OwnPtr<T>& a, U* b) - { + { return a.get() == b; } - + template <typename T, typename U> inline bool operator==(T* a, const OwnPtr<U>& b) { return a == b.get(); @@ -110,10 +126,10 @@ namespace WTF { } template <typename T, typename U> inline bool operator!=(T* a, const OwnPtr<U>& b) - { + { return a != b.get(); } - + template <typename T> inline typename OwnPtr<T>::PtrType getPtr(const OwnPtr<T>& p) { return p.get(); diff --git a/JavaScriptCore/wtf/OwnPtrCommon.h b/JavaScriptCore/wtf/OwnPtrCommon.h new file mode 100644 index 0000000..6cd8bdd --- /dev/null +++ b/JavaScriptCore/wtf/OwnPtrCommon.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WTF_OwnPtrCommon_h +#define WTF_OwnPtrCommon_h + +#if PLATFORM(WIN) +typedef struct HBITMAP__* HBITMAP; +typedef struct HBRUSH__* HBRUSH; +typedef struct HFONT__* HFONT; +typedef struct HPALETTE__* HPALETTE; +typedef struct HPEN__* HPEN; +typedef struct HRGN__* HRGN; +#endif + +namespace WTF { + + template <typename T> inline void deleteOwnedPtr(T* ptr) + { + typedef char known[sizeof(T) ? 1 : -1]; + if (sizeof(known)) + delete ptr; + } + +#if PLATFORM(WIN) + void deleteOwnedPtr(HBITMAP); + void deleteOwnedPtr(HBRUSH); + void deleteOwnedPtr(HFONT); + void deleteOwnedPtr(HPALETTE); + void deleteOwnedPtr(HPEN); + void deleteOwnedPtr(HRGN); +#endif + +} // namespace WTF + +#endif // WTF_OwnPtrCommon_h diff --git a/JavaScriptCore/wtf/PassOwnPtr.h b/JavaScriptCore/wtf/PassOwnPtr.h new file mode 100644 index 0000000..ae70457 --- /dev/null +++ b/JavaScriptCore/wtf/PassOwnPtr.h @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WTF_PassOwnPtr_h +#define WTF_PassOwnPtr_h + +#include "Assertions.h" +#include "OwnPtrCommon.h" +#include "TypeTraits.h" + +namespace WTF { + + // Unlike most of our smart pointers, PassOwnPtr can take either the pointer type or the pointed-to type. + + template <typename T> class OwnPtr; + + template <typename T> class PassOwnPtr { + public: + typedef typename RemovePointer<T>::Type ValueType; + typedef ValueType* PtrType; + + PassOwnPtr(PtrType ptr = 0) : m_ptr(ptr) { } + // It somewhat breaks the type system to allow transfer of ownership out of + // a const PassOwnPtr. However, it makes it much easier to work with PassOwnPtr + // temporaries, and we don't really have a need to use real const PassOwnPtrs + // anyway. + PassOwnPtr(const PassOwnPtr& o) : m_ptr(o.release()) { } + template <typename U> PassOwnPtr(const PassOwnPtr<U>& o) : m_ptr(o.release()) { } + + ~PassOwnPtr() { deleteOwnedPtr(m_ptr); } + + PtrType get() const { return m_ptr; } + + void clear() { m_ptr = 0; } + PtrType release() const { PtrType ptr = m_ptr; m_ptr = 0; return ptr; } + + ValueType& operator*() const { ASSERT(m_ptr); return *m_ptr; } + PtrType operator->() const { ASSERT(m_ptr); return m_ptr; } + + bool operator!() const { return !m_ptr; } + + // This conversion operator allows implicit conversion to bool but not to other integer types. + typedef PtrType PassOwnPtr::*UnspecifiedBoolType; + operator UnspecifiedBoolType() const { return m_ptr ? &PassOwnPtr::m_ptr : 0; } + + PassOwnPtr& operator=(T*); + PassOwnPtr& operator=(const PassOwnPtr<T>&); + template <typename U> PassOwnPtr& operator=(const PassOwnPtr<U>&); + + private: + mutable PtrType m_ptr; + }; + + template <typename T> inline PassOwnPtr<T>& PassOwnPtr<T>::operator=(T* optr) + { + T* ptr = m_ptr; + m_ptr = optr; + ASSERT(!ptr || m_ptr != ptr); + if (ptr) + deleteOwnedPtr(ptr); + return *this; + } + + template <typename T> inline PassOwnPtr<T>& PassOwnPtr<T>::operator=(const PassOwnPtr<T>& optr) + { + T* ptr = m_ptr; + m_ptr = optr.release(); + ASSERT(!ptr || m_ptr != ptr); + if (ptr) + deleteOwnedPtr(ptr); + return *this; + } + + template <typename T> template <typename U> inline PassOwnPtr<T>& PassOwnPtr<T>::operator=(const PassOwnPtr<U>& optr) + { + T* ptr = m_ptr; + m_ptr = optr.release(); + ASSERT(!ptr || m_ptr != ptr); + if (ptr) + deleteOwnedPtr(ptr); + return *this; + } + + template <typename T, typename U> inline bool operator==(const PassOwnPtr<T>& a, const PassOwnPtr<U>& b) + { + return a.get() == b.get(); + } + + template <typename T, typename U> inline bool operator==(const PassOwnPtr<T>& a, const OwnPtr<U>& b) + { + return a.get() == b.get(); + } + + template <typename T, typename U> inline bool operator==(const OwnPtr<T>& a, const PassOwnPtr<U>& b) + { + return a.get() == b.get(); + } + + template <typename T, typename U> inline bool operator==(const PassOwnPtr<T>& a, U* b) + { + return a.get() == b; + } + + template <typename T, typename U> inline bool operator==(T* a, const PassOwnPtr<U>& b) + { + return a == b.get(); + } + + template <typename T, typename U> inline bool operator!=(const PassOwnPtr<T>& a, const PassOwnPtr<U>& b) + { + return a.get() != b.get(); + } + + template <typename T, typename U> inline bool operator!=(const PassOwnPtr<T>& a, const OwnPtr<U>& b) + { + return a.get() != b.get(); + } + + template <typename T, typename U> inline bool operator!=(const OwnPtr<T>& a, const PassOwnPtr<U>& b) + { + return a.get() != b.get(); + } + + template <typename T, typename U> inline bool operator!=(const PassOwnPtr<T>& a, U* b) + { + return a.get() != b; + } + + template <typename T, typename U> inline bool operator!=(T* a, const PassOwnPtr<U>& b) + { + return a != b.get(); + } + + template <typename T, typename U> inline PassOwnPtr<T> static_pointer_cast(const PassOwnPtr<U>& p) + { + return PassOwnPtr<T>(static_cast<T*>(p.release())); + } + + template <typename T, typename U> inline PassOwnPtr<T> const_pointer_cast(const PassOwnPtr<U>& p) + { + return PassOwnPtr<T>(const_cast<T*>(p.release())); + } + + template <typename T> inline T* getPtr(const PassOwnPtr<T>& p) + { + return p.get(); + } + +} // namespace WTF + +using WTF::PassOwnPtr; +using WTF::const_pointer_cast; +using WTF::static_pointer_cast; + +#endif // WTF_PassOwnPtr_h diff --git a/JavaScriptCore/wtf/PassRefPtr.h b/JavaScriptCore/wtf/PassRefPtr.h index c1dc309..d80ed62 100644 --- a/JavaScriptCore/wtf/PassRefPtr.h +++ b/JavaScriptCore/wtf/PassRefPtr.h @@ -40,7 +40,7 @@ namespace WTF { PassRefPtr(const PassRefPtr& o) : m_ptr(o.releaseRef()) {} template <typename U> PassRefPtr(const PassRefPtr<U>& o) : m_ptr(o.releaseRef()) { } - ALWAYS_INLINE ~PassRefPtr() { if (T* ptr = m_ptr) ptr->deref(); } + ALWAYS_INLINE ~PassRefPtr() { if (UNLIKELY(m_ptr != 0)) m_ptr->deref(); } template <class U> PassRefPtr(const RefPtr<U>& o) : m_ptr(o.get()) { if (T* ptr = m_ptr) ptr->ref(); } diff --git a/JavaScriptCore/wtf/Platform.h b/JavaScriptCore/wtf/Platform.h index 23e6c8b..e34f7c3 100644 --- a/JavaScriptCore/wtf/Platform.h +++ b/JavaScriptCore/wtf/Platform.h @@ -46,6 +46,7 @@ #elif !defined(MAC_OS_X_VERSION_10_6) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6 #define BUILDING_ON_LEOPARD 1 #endif +#include <TargetConditionals.h> #endif /* PLATFORM(WIN_OS) */ @@ -63,6 +64,13 @@ #define WTF_PLATFORM_WIN_CE 1 #endif +/* PLATFORM(LINUX) */ +/* Operating system level dependencies for Linux-like systems that */ +/* should be used regardless of operating environment */ +#ifdef __linux__ +#define WTF_PLATFORM_LINUX 1 +#endif + /* PLATFORM(FREEBSD) */ /* Operating system level dependencies for FreeBSD-like systems that */ /* should be used regardless of operating environment */ @@ -142,11 +150,30 @@ #define WTF_PLATFORM_WIN 1 #endif +/* PLATFORM(IPHONE) */ +#if (defined(TARGET_OS_EMBEDDED) && TARGET_OS_EMBEDDED) || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) +#define WTF_PLATFORM_IPHONE 1 +#endif + +/* PLATFORM(IPHONE_SIMULATOR) */ +#if defined(TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR +#define WTF_PLATFORM_IPHONE 1 +#define WTF_PLATFORM_IPHONE_SIMULATOR 1 +#else +#define WTF_PLATFORM_IPHONE_SIMULATOR 0 +#endif + +#if !defined(WTF_PLATFORM_IPHONE) +#define WTF_PLATFORM_IPHONE 0 +#endif + /* Graphics engines */ /* PLATFORM(CG) and PLATFORM(CI) */ -#if PLATFORM(MAC) +#if PLATFORM(MAC) || PLATFORM(IPHONE) #define WTF_PLATFORM_CG 1 +#endif +#if PLATFORM(MAC) && !PLATFORM(IPHONE) #define WTF_PLATFORM_CI 1 #endif @@ -189,9 +216,7 @@ // Prevents Webkit from drawing the caret in textfields and textareas // This prevents unnecessary invals. #define ENABLE_TEXT_CARET 1 -#if WTF_USE_V8 #define ENABLE_JAVASCRIPT_DEBUGGER 0 -#endif #endif // ANDROID /* CPU */ @@ -230,6 +255,9 @@ #define WTF_PLATFORM_FORCE_PACK 1 #endif #endif +#if defined(__ARM_ARCH_7A__) +#define WTF_PLATFORM_ARM_V7 1 +#endif /* PLATFORM(X86) */ #if defined(__i386__) \ @@ -242,7 +270,6 @@ /* PLATFORM(X86_64) */ #if defined(__x86_64__) \ - || defined(__ia64__) \ || defined(_M_X64) #define WTF_PLATFORM_X86_64 1 #endif @@ -315,7 +342,7 @@ #define WTF_COMPILER_WINSCW 1 #endif -#if (PLATFORM(MAC) || PLATFORM(WIN)) && !defined(ENABLE_JSC_MULTIPLE_THREADS) +#if (PLATFORM(IPHONE) || PLATFORM(MAC) || PLATFORM(WIN)) && !defined(ENABLE_JSC_MULTIPLE_THREADS) #define ENABLE_JSC_MULTIPLE_THREADS 1 #endif @@ -330,7 +357,7 @@ #define WTF_USE_ICU_UNICODE 1 #endif -#if PLATFORM(MAC) +#if PLATFORM(MAC) && !PLATFORM(IPHONE) #define WTF_PLATFORM_CF 1 #define WTF_USE_PTHREADS 1 #if !defined(ENABLE_MAC_JAVA_BRIDGE) @@ -348,11 +375,24 @@ #define WTF_USE_PTHREADS 1 #endif +#if PLATFORM(IPHONE) +#define WTF_PLATFORM_CF 1 +#define WTF_USE_PTHREADS 1 +#define ENABLE_FTPDIR 1 +#define ENABLE_MAC_JAVA_BRIDGE 0 +#define ENABLE_ICONDATABASE 0 +#define ENABLE_GEOLOCATION 1 +#define ENABLE_NETSCAPE_PLUGIN_API 0 +#define HAVE_READLINE 1 +#define ENABLE_REPAINT_THROTTLING 1 +#endif + #if PLATFORM(WIN) #define WTF_USE_WININET 1 #endif #if PLATFORM(WX) +#define ENABLE_ASSEMBLER 1 #define WTF_USE_CURL 1 #define WTF_USE_PTHREADS 1 #endif @@ -364,15 +404,11 @@ #endif #if !defined(HAVE_ACCESSIBILITY) -#if PLATFORM(MAC) || PLATFORM(WIN) || PLATFORM(GTK) || PLATFORM(CHROMIUM) +#if PLATFORM(IPHONE) || PLATFORM(MAC) || PLATFORM(WIN) || PLATFORM(GTK) || PLATFORM(CHROMIUM) #define HAVE_ACCESSIBILITY 1 #endif #endif /* !defined(HAVE_ACCESSIBILITY) */ -#if COMPILER(GCC) -#define HAVE_COMPUTED_GOTO 1 -#endif - #if PLATFORM(DARWIN) #define HAVE_ERRNO_H 1 @@ -385,8 +421,13 @@ #define HAVE_SYS_TIME_H 1 #define HAVE_SYS_TIMEB_H 1 -#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) +#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !PLATFORM(IPHONE) #define HAVE_MADV_FREE_REUSE 1 +#define HAVE_MADV_FREE 1 +#endif + +#if PLATFORM(IPHONE) +#define HAVE_MADV_FREE 1 #endif #elif PLATFORM(WIN_OS) @@ -438,6 +479,12 @@ /* ENABLE macro defaults */ +/* fastMalloc match validation allows for runtime verification that + new is matched by delete, fastMalloc is matched by fastFree, etc. */ +#if !defined(ENABLE_FAST_MALLOC_MATCH_VALIDATION) +#define ENABLE_FAST_MALLOC_MATCH_VALIDATION 0 +#endif + #if !defined(ENABLE_ICONDATABASE) #define ENABLE_ICONDATABASE 1 #endif @@ -470,16 +517,15 @@ #define ENABLE_OPCODE_STATS 0 #endif -#if !defined(ENABLE_CODEBLOCK_SAMPLING) +#define ENABLE_SAMPLING_COUNTERS 0 +#define ENABLE_SAMPLING_FLAGS 0 +#define ENABLE_OPCODE_SAMPLING 0 #define ENABLE_CODEBLOCK_SAMPLING 0 +#if ENABLE(CODEBLOCK_SAMPLING) && !ENABLE(OPCODE_SAMPLING) +#error "CODEBLOCK_SAMPLING requires OPCODE_SAMPLING" #endif - -#if ENABLE(CODEBLOCK_SAMPLING) && !defined(ENABLE_OPCODE_SAMPLING) -#define ENABLE_OPCODE_SAMPLING 1 -#endif - -#if !defined(ENABLE_OPCODE_SAMPLING) -#define ENABLE_OPCODE_SAMPLING 0 +#if ENABLE(OPCODE_SAMPLING) || ENABLE(SAMPLING_FLAGS) +#define ENABLE_SAMPLING_THREAD 1 #endif #if !defined(ENABLE_GEOLOCATION) @@ -511,41 +557,79 @@ /* The JIT is tested & working on x86_64 Mac */ #if PLATFORM(X86_64) && PLATFORM(MAC) #define ENABLE_JIT 1 - #define WTF_USE_JIT_STUB_ARGUMENT_REGISTER 1 /* The JIT is tested & working on x86 Mac */ #elif PLATFORM(X86) && PLATFORM(MAC) #define ENABLE_JIT 1 #define WTF_USE_JIT_STUB_ARGUMENT_VA_LIST 1 +#elif PLATFORM(ARM_V7) && PLATFORM(IPHONE) + /* Under development, temporarily disabled until 16Mb link range limit in assembler is fixed. */ + #define ENABLE_JIT 0 + #define ENABLE_JIT_OPTIMIZE_NATIVE_CALL 0 /* The JIT is tested & working on x86 Windows */ #elif PLATFORM(X86) && PLATFORM(WIN) #define ENABLE_JIT 1 - #define WTF_USE_JIT_STUB_ARGUMENT_REGISTER 1 #endif - #define ENABLE_JIT_OPTIMIZE_CALL 1 - #define ENABLE_JIT_OPTIMIZE_PROPERTY_ACCESS 1 - #define ENABLE_JIT_OPTIMIZE_ARITHMETIC 1 #endif -#if ENABLE(JIT) -#if !(USE(JIT_STUB_ARGUMENT_VA_LIST) || USE(JIT_STUB_ARGUMENT_REGISTER) || USE(JIT_STUB_ARGUMENT_STACK)) -#error Please define one of the JIT_STUB_ARGUMENT settings. -#elif (USE(JIT_STUB_ARGUMENT_VA_LIST) && USE(JIT_STUB_ARGUMENT_REGISTER)) \ - || (USE(JIT_STUB_ARGUMENT_VA_LIST) && USE(JIT_STUB_ARGUMENT_STACK)) \ - || (USE(JIT_STUB_ARGUMENT_REGISTER) && USE(JIT_STUB_ARGUMENT_STACK)) -#error Please do not define more than one of the JIT_STUB_ARGUMENT settings. +#ifndef ENABLE_JIT_OPTIMIZE_CALL +#define ENABLE_JIT_OPTIMIZE_CALL 1 +#endif +#ifndef ENABLE_JIT_OPTIMIZE_NATIVE_CALL +#define ENABLE_JIT_OPTIMIZE_NATIVE_CALL 1 +#endif +#ifndef ENABLE_JIT_OPTIMIZE_PROPERTY_ACCESS +#define ENABLE_JIT_OPTIMIZE_PROPERTY_ACCESS 1 +#endif +#ifndef ENABLE_JIT_OPTIMIZE_ARITHMETIC +#define ENABLE_JIT_OPTIMIZE_ARITHMETIC 1 +#endif +#ifndef ENABLE_JIT_OPTIMIZE_METHOD_CALLS +#define ENABLE_JIT_OPTIMIZE_METHOD_CALLS 1 +#endif + +#if PLATFORM(X86) && COMPILER(MSVC) +#define JSC_HOST_CALL __fastcall +#elif PLATFORM(X86) && COMPILER(GCC) +#define JSC_HOST_CALL __attribute__ ((fastcall)) +#else +#define JSC_HOST_CALL +#endif + +#if COMPILER(GCC) && !ENABLE(JIT) +#define HAVE_COMPUTED_GOTO 1 #endif + +#if ENABLE(JIT) && defined(COVERAGE) + #define WTF_USE_INTERPRETER 0 +#else + #define WTF_USE_INTERPRETER 1 #endif -/* WREC supports x86 & x86-64, and has been tested on Mac and Windows ('cept on 64-bit on Mac). */ -#if (!defined(ENABLE_WREC) && PLATFORM(X86) && PLATFORM(MAC)) \ - || (!defined(ENABLE_WREC) && PLATFORM(X86_64) && PLATFORM(MAC)) \ - || (!defined(ENABLE_WREC) && PLATFORM(X86) && PLATFORM(WIN)) -#define ENABLE_WREC 1 +/* Yet Another Regex Runtime. */ +/* YARR supports x86 & x86-64, and has been tested on Mac and Windows. */ +#if (!defined(ENABLE_YARR_JIT) && PLATFORM(X86) && PLATFORM(MAC)) \ + || (!defined(ENABLE_YARR_JIT) && PLATFORM(X86_64) && PLATFORM(MAC)) \ + /* Under development, temporarily disabled until 16Mb link range limit in assembler is fixed. */ \ + || (!defined(ENABLE_YARR_JIT) && PLATFORM(ARM_V7) && PLATFORM(IPHONE) && 0) \ + || (!defined(ENABLE_YARR_JIT) && PLATFORM(X86) && PLATFORM(WIN)) +#define ENABLE_YARR 1 +#define ENABLE_YARR_JIT 1 +#endif +/* Sanity Check */ +#if ENABLE(YARR_JIT) && !ENABLE(YARR) +#error "YARR_JIT requires YARR" #endif -#if ENABLE(JIT) || ENABLE(WREC) +#if ENABLE(JIT) || ENABLE(YARR_JIT) #define ENABLE_ASSEMBLER 1 #endif +/* Setting this flag prevents the assembler from using RWX memory; this may improve + security but currectly comes at a significant performance cost. */ +#if PLATFORM(ARM_V7) && PLATFORM(IPHONE) +#define ENABLE_ASSEMBLER_WX_EXCLUSIVE 1 +#else +#define ENABLE_ASSEMBLER_WX_EXCLUSIVE 0 +#endif #if !defined(ENABLE_PAN_SCROLLING) && PLATFORM(WIN_OS) #define ENABLE_PAN_SCROLLING 1 diff --git a/JavaScriptCore/wtf/RefCounted.h b/JavaScriptCore/wtf/RefCounted.h index 93ee0da..c174145 100644 --- a/JavaScriptCore/wtf/RefCounted.h +++ b/JavaScriptCore/wtf/RefCounted.h @@ -57,7 +57,9 @@ protected: { } - ~RefCountedBase() {} + ~RefCountedBase() + { + } // Returns whether the pointer should be freed or not. bool derefBase() @@ -75,7 +77,20 @@ protected: return false; } -protected: + // Helper for generating JIT code. Please do not use for non-JIT purposes. + int* addressOfCount() + { + return &m_refCount; + } + +#ifndef NDEBUG + bool deletionHasBegun() const + { + return m_deletionHasBegun; + } +#endif + +private: template<class T> friend class CrossThreadRefCounted; @@ -95,7 +110,9 @@ public: } protected: - ~RefCounted() {} + ~RefCounted() + { + } }; } // namespace WTF diff --git a/JavaScriptCore/wtf/StdLibExtras.h b/JavaScriptCore/wtf/StdLibExtras.h index 14227ab..afc5e8a 100644 --- a/JavaScriptCore/wtf/StdLibExtras.h +++ b/JavaScriptCore/wtf/StdLibExtras.h @@ -47,14 +47,14 @@ namespace WTF { * C++'s idea of a reinterpret_cast lacks sufficient cojones. */ template<typename TO, typename FROM> - TO bitwise_cast(FROM in) + TO bitwise_cast(FROM from) { - COMPILE_ASSERT(sizeof(TO) == sizeof(FROM), WTF_wtf_reinterpret_cast_sizeof_types_is_equal); + COMPILE_ASSERT(sizeof(TO) == sizeof(FROM), WTF_bitwise_cast_sizeof_casted_types_is_equal); union { FROM from; TO to; } u; - u.from = in; + u.from = from; return u.to; } diff --git a/JavaScriptCore/wtf/StringExtras.h b/JavaScriptCore/wtf/StringExtras.h index 881b066..926fd61 100644 --- a/JavaScriptCore/wtf/StringExtras.h +++ b/JavaScriptCore/wtf/StringExtras.h @@ -29,6 +29,10 @@ #include <stdarg.h> #include <stdio.h> +#if HAVE(STRINGS_H) +#include <strings.h> +#endif + #if COMPILER(MSVC) inline int snprintf(char* buffer, size_t count, const char* format, ...) diff --git a/JavaScriptCore/wtf/TCPackedCache.h b/JavaScriptCore/wtf/TCPackedCache.h index a33cb77..0464f8f 100644 --- a/JavaScriptCore/wtf/TCPackedCache.h +++ b/JavaScriptCore/wtf/TCPackedCache.h @@ -1,4 +1,4 @@ -// Copyright (c) 2007, The Android Open Source Project +// Copyright (c) 2007, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without diff --git a/JavaScriptCore/wtf/TCPageMap.h b/JavaScriptCore/wtf/TCPageMap.h index 9ffd77b..3f56c24 100644 --- a/JavaScriptCore/wtf/TCPageMap.h +++ b/JavaScriptCore/wtf/TCPageMap.h @@ -1,4 +1,4 @@ -// Copyright (c) 2005, The Android Open Source Project +// Copyright (c) 2005, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without diff --git a/JavaScriptCore/wtf/TCSpinLock.h b/JavaScriptCore/wtf/TCSpinLock.h index d651e31..ced2283 100644 --- a/JavaScriptCore/wtf/TCSpinLock.h +++ b/JavaScriptCore/wtf/TCSpinLock.h @@ -1,4 +1,4 @@ -// Copyright (c) 2005, 2006, The Android Open Source Project +// Copyright (c) 2005, 2006, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without diff --git a/JavaScriptCore/wtf/TCSystemAlloc.cpp b/JavaScriptCore/wtf/TCSystemAlloc.cpp index bf2dcb1..478ce63 100644 --- a/JavaScriptCore/wtf/TCSystemAlloc.cpp +++ b/JavaScriptCore/wtf/TCSystemAlloc.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2005, 2007, The Android Open Source Project +// Copyright (c) 2005, 2007, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -388,10 +388,17 @@ void TCMalloc_SystemRelease(void* start, size_t length) while (madvise(start, length, MADV_FREE_REUSABLE) == -1 && errno == EAGAIN) { } } -#elif HAVE(MADV_DONTNEED) +#elif HAVE(MADV_FREE) || HAVE(MADV_DONTNEED) void TCMalloc_SystemRelease(void* start, size_t length) { + // MADV_FREE clears the modified bit on pages, which allows + // them to be discarded immediately. +#if HAVE(MADV_FREE) + const int advice = MADV_FREE; +#else + const int advice = MADV_DONTNEED; +#endif if (FLAGS_malloc_devmem_start) { // It's not safe to use MADV_DONTNEED if we've been mapping // /dev/mem for heap memory @@ -418,7 +425,7 @@ void TCMalloc_SystemRelease(void* start, size_t length) // Note -- ignoring most return codes, because if this fails it // doesn't matter... while (madvise(reinterpret_cast<char*>(new_start), new_end - new_start, - MADV_DONTNEED) == -1 && + advice) == -1 && errno == EAGAIN) { // NOP } diff --git a/JavaScriptCore/wtf/TCSystemAlloc.h b/JavaScriptCore/wtf/TCSystemAlloc.h index f2c915e..8e3a01a 100644 --- a/JavaScriptCore/wtf/TCSystemAlloc.h +++ b/JavaScriptCore/wtf/TCSystemAlloc.h @@ -1,4 +1,4 @@ -// Copyright (c) 2005, 2007, The Android Open Source Project +// Copyright (c) 2005, 2007, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without diff --git a/JavaScriptCore/wtf/ThreadSpecific.h b/JavaScriptCore/wtf/ThreadSpecific.h index 8aaaf5f..b07a9a2 100644 --- a/JavaScriptCore/wtf/ThreadSpecific.h +++ b/JavaScriptCore/wtf/ThreadSpecific.h @@ -45,13 +45,15 @@ #if USE(PTHREADS) #include <pthread.h> +#elif PLATFORM(QT) +#include <QThreadStorage> #elif PLATFORM(WIN_OS) #include <windows.h> #endif namespace WTF { -#if !USE(PTHREADS) && PLATFORM(WIN_OS) +#if !USE(PTHREADS) && !PLATFORM(QT) && PLATFORM(WIN_OS) // ThreadSpecificThreadExit should be called each time when a thread is detached. // This is done automatically for threads created with WTF::createThread. void ThreadSpecificThreadExit(); @@ -66,7 +68,7 @@ public: ~ThreadSpecific(); private: -#if !USE(PTHREADS) && PLATFORM(WIN_OS) +#if !USE(PTHREADS) && !PLATFORM(QT) && PLATFORM(WIN_OS) friend void ThreadSpecificThreadExit(); #endif @@ -74,7 +76,7 @@ private: void set(T*); void static destroy(void* ptr); -#if USE(PTHREADS) || PLATFORM(WIN_OS) +#if USE(PTHREADS) || PLATFORM(QT) || PLATFORM(WIN_OS) struct Data : Noncopyable { Data(T* value, ThreadSpecific<T>* owner) : value(value), owner(owner) {} @@ -88,6 +90,8 @@ private: #if USE(PTHREADS) pthread_key_t m_key; +#elif PLATFORM(QT) + QThreadStorage<Data*> m_key; #elif PLATFORM(WIN_OS) int m_index; #endif @@ -122,6 +126,37 @@ inline void ThreadSpecific<T>::set(T* ptr) pthread_setspecific(m_key, new Data(ptr, this)); } +#elif PLATFORM(QT) + +template<typename T> +inline ThreadSpecific<T>::ThreadSpecific() +{ +} + +template<typename T> +inline ThreadSpecific<T>::~ThreadSpecific() +{ + Data* data = static_cast<Data*>(m_key.localData()); + if (data) + data->destructor(data); +} + +template<typename T> +inline T* ThreadSpecific<T>::get() +{ + Data* data = static_cast<Data*>(m_key.localData()); + return data ? data->value : 0; +} + +template<typename T> +inline void ThreadSpecific<T>::set(T* ptr) +{ + ASSERT(!get()); + Data* data = new Data(ptr, this); + data->destructor = &ThreadSpecific<T>::destroy; + m_key.setLocalData(data); +} + #elif PLATFORM(WIN_OS) // The maximum number of TLS keys that can be created. For simplification, we assume that: @@ -189,6 +224,8 @@ inline void ThreadSpecific<T>::destroy(void* ptr) #if USE(PTHREADS) pthread_setspecific(data->owner->m_key, 0); +#elif PLATFORM(QT) + data->owner->m_key.setLocalData(0); #elif PLATFORM(WIN_OS) TlsSetValue(tlsKeys()[data->owner->m_index], 0); #else diff --git a/JavaScriptCore/wtf/ThreadingNone.cpp b/JavaScriptCore/wtf/ThreadingNone.cpp index 24431fc..e713102 100644 --- a/JavaScriptCore/wtf/ThreadingNone.cpp +++ b/JavaScriptCore/wtf/ThreadingNone.cpp @@ -33,11 +33,11 @@ namespace WTF { void initializeThreading() { } -ThreadIdentifier createThreadInternal(ThreadFunction, void*, const char*) { return 0; } +ThreadIdentifier createThreadInternal(ThreadFunction, void*, const char*) { return ThreadIdentifier(); } void setThreadNameInternal(const char*) { } int waitForThreadCompletion(ThreadIdentifier, void**) { return 0; } void detachThread(ThreadIdentifier) { } -ThreadIdentifier currentThread() { return 0; } +ThreadIdentifier currentThread() { return ThreadIdentifier(); } bool isMainThread() { return true; } Mutex::Mutex() { } diff --git a/JavaScriptCore/wtf/ThreadingPthreads.cpp b/JavaScriptCore/wtf/ThreadingPthreads.cpp index ebfd78f..f54dd3f 100644 --- a/JavaScriptCore/wtf/ThreadingPthreads.cpp +++ b/JavaScriptCore/wtf/ThreadingPthreads.cpp @@ -114,14 +114,14 @@ static ThreadIdentifier establishIdentifierForPthreadHandle(pthread_t& pthreadHa static ThreadIdentifier identifierCount = 1; threadMap().add(identifierCount, pthreadHandle); - + return identifierCount++; } static pthread_t pthreadHandleForIdentifier(ThreadIdentifier id) { MutexLocker locker(threadMapMutex()); - + return threadMap().get(id); } @@ -130,7 +130,7 @@ static void clearPthreadHandleForIdentifier(ThreadIdentifier id) MutexLocker locker(threadMapMutex()); ASSERT(threadMap().contains(id)); - + threadMap().remove(id); } @@ -161,7 +161,7 @@ ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, con ThreadData* threadData = new ThreadData(); threadData->entryPoint = entryPoint; threadData->arg = data; - + if (pthread_create(&threadHandle, 0, runThreadWithRegistration, static_cast<void*>(threadData))) { LOG_ERROR("Failed to create pthread at entry point %p with data %p", entryPoint, data); return 0; @@ -183,7 +183,7 @@ ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, con void setThreadNameInternal(const char* threadName) { -#if PLATFORM(DARWIN) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) +#if PLATFORM(DARWIN) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !PLATFORM(IPHONE) pthread_setname_np(threadName); #else UNUSED_PARAM(threadName); @@ -193,13 +193,13 @@ void setThreadNameInternal(const char* threadName) int waitForThreadCompletion(ThreadIdentifier threadID, void** result) { ASSERT(threadID); - + pthread_t pthreadHandle = pthreadHandleForIdentifier(threadID); - + int joinResult = pthread_join(pthreadHandle, result); if (joinResult == EDEADLK) LOG_ERROR("ThreadIdentifier %u was found to be deadlocked trying to quit", threadID); - + clearPthreadHandleForIdentifier(threadID); return joinResult; } @@ -207,11 +207,11 @@ int waitForThreadCompletion(ThreadIdentifier threadID, void** result) void detachThread(ThreadIdentifier threadID) { ASSERT(threadID); - + pthread_t pthreadHandle = pthreadHandleForIdentifier(threadID); - + pthread_detach(pthreadHandle); - + clearPthreadHandleForIdentifier(threadID); } @@ -247,11 +247,11 @@ void Mutex::lock() int result = pthread_mutex_lock(&m_mutex); ASSERT_UNUSED(result, !result); } - + bool Mutex::tryLock() { int result = pthread_mutex_trylock(&m_mutex); - + if (result == 0) return true; if (result == EBUSY) @@ -314,7 +314,7 @@ void ThreadCondition::broadcast() int result = pthread_cond_broadcast(&m_condition); ASSERT_UNUSED(result, !result); } - + } // namespace WTF #endif // USE(PTHREADS) diff --git a/JavaScriptCore/wtf/ThreadingWin.cpp b/JavaScriptCore/wtf/ThreadingWin.cpp index 415ba53..ea18656 100644 --- a/JavaScriptCore/wtf/ThreadingWin.cpp +++ b/JavaScriptCore/wtf/ThreadingWin.cpp @@ -243,7 +243,7 @@ int waitForThreadCompletion(ThreadIdentifier threadID, void** result) void detachThread(ThreadIdentifier threadID) { ASSERT(threadID); - + HANDLE threadHandle = threadHandleForIdentifier(threadID); if (threadHandle) CloseHandle(threadHandle); diff --git a/JavaScriptCore/wtf/TypeTraits.h b/JavaScriptCore/wtf/TypeTraits.h index 2aeabcf..6ce6a3e 100644 --- a/JavaScriptCore/wtf/TypeTraits.h +++ b/JavaScriptCore/wtf/TypeTraits.h @@ -24,6 +24,10 @@ #include "Platform.h" +#if (defined(__GLIBCXX__) && (__GLIBCXX__ >= 20070724) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || (defined(_MSC_VER) && (_MSC_VER >= 1600)) +#include <type_traits> +#endif + namespace WTF { // The following are provided in this file: @@ -128,6 +132,208 @@ namespace WTF { typedef T Type; }; +#if (defined(__GLIBCXX__) && (__GLIBCXX__ >= 20070724) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || (defined(_MSC_VER) && (_MSC_VER >= 1600)) + + // GCC's libstdc++ 20070724 and later supports C++ TR1 type_traits in the std namespace. + // VC10 (VS2010) and later support C++ TR1 type_traits in the std::tr1 namespace. + template<typename T> struct HasTrivialConstructor : public std::tr1::has_trivial_constructor<T> { }; + template<typename T> struct HasTrivialDestructor : public std::tr1::has_trivial_destructor<T> { }; + +#else + + // This compiler doesn't provide type traits, so we provide basic HasTrivialConstructor + // and HasTrivialDestructor definitions. The definitions here include most built-in + // scalar types but do not include POD structs and classes. For the intended purposes of + // type_traits this results correct but potentially less efficient code. + template <typename T, T v> + struct IntegralConstant { + static const T value = v; + typedef T value_type; + typedef IntegralConstant<T, v> type; + }; + + typedef IntegralConstant<bool, true> true_type; + typedef IntegralConstant<bool, false> false_type; + +#if defined(_MSC_VER) && (_MSC_VER >= 1400) + // VC8 (VS2005) and later have built-in compiler support for HasTrivialConstructor / HasTrivialDestructor, + // but for some unexplained reason it doesn't work on built-in types. + template <typename T> struct HasTrivialConstructor : public IntegralConstant<bool, __has_trivial_constructor(T)>{ }; + template <typename T> struct HasTrivialDestructor : public IntegralConstant<bool, __has_trivial_destructor(T)>{ }; +#else + template <typename T> struct HasTrivialConstructor : public false_type{ }; + template <typename T> struct HasTrivialDestructor : public false_type{ }; +#endif + + template <typename T> struct HasTrivialConstructor<T*> : public true_type{ }; + template <typename T> struct HasTrivialDestructor<T*> : public true_type{ }; + + template <> struct HasTrivialConstructor<float> : public true_type{ }; + template <> struct HasTrivialConstructor<const float> : public true_type{ }; + template <> struct HasTrivialConstructor<volatile float> : public true_type{ }; + template <> struct HasTrivialConstructor<const volatile float> : public true_type{ }; + + template <> struct HasTrivialConstructor<double> : public true_type{ }; + template <> struct HasTrivialConstructor<const double> : public true_type{ }; + template <> struct HasTrivialConstructor<volatile double> : public true_type{ }; + template <> struct HasTrivialConstructor<const volatile double> : public true_type{ }; + + template <> struct HasTrivialConstructor<long double> : public true_type{ }; + template <> struct HasTrivialConstructor<const long double> : public true_type{ }; + template <> struct HasTrivialConstructor<volatile long double> : public true_type{ }; + template <> struct HasTrivialConstructor<const volatile long double> : public true_type{ }; + + template <> struct HasTrivialConstructor<unsigned char> : public true_type{ }; + template <> struct HasTrivialConstructor<const unsigned char> : public true_type{ }; + template <> struct HasTrivialConstructor<volatile unsigned char> : public true_type{ }; + template <> struct HasTrivialConstructor<const volatile unsigned char> : public true_type{ }; + + template <> struct HasTrivialConstructor<unsigned short> : public true_type{ }; + template <> struct HasTrivialConstructor<const unsigned short> : public true_type{ }; + template <> struct HasTrivialConstructor<volatile unsigned short> : public true_type{ }; + template <> struct HasTrivialConstructor<const volatile unsigned short> : public true_type{ }; + + template <> struct HasTrivialConstructor<unsigned int> : public true_type{ }; + template <> struct HasTrivialConstructor<const unsigned int> : public true_type{ }; + template <> struct HasTrivialConstructor<volatile unsigned int> : public true_type{ }; + template <> struct HasTrivialConstructor<const volatile unsigned int> : public true_type{ }; + + template <> struct HasTrivialConstructor<unsigned long> : public true_type{ }; + template <> struct HasTrivialConstructor<const unsigned long> : public true_type{ }; + template <> struct HasTrivialConstructor<volatile unsigned long> : public true_type{ }; + template <> struct HasTrivialConstructor<const volatile unsigned long> : public true_type{ }; + + template <> struct HasTrivialConstructor<unsigned long long> : public true_type{ }; + template <> struct HasTrivialConstructor<const unsigned long long> : public true_type{ }; + template <> struct HasTrivialConstructor<volatile unsigned long long> : public true_type{ }; + template <> struct HasTrivialConstructor<const volatile unsigned long long> : public true_type{ }; + + template <> struct HasTrivialConstructor<signed char> : public true_type{ }; + template <> struct HasTrivialConstructor<const signed char> : public true_type{ }; + template <> struct HasTrivialConstructor<volatile signed char> : public true_type{ }; + template <> struct HasTrivialConstructor<const volatile signed char> : public true_type{ }; + + template <> struct HasTrivialConstructor<signed short> : public true_type{ }; + template <> struct HasTrivialConstructor<const signed short> : public true_type{ }; + template <> struct HasTrivialConstructor<volatile signed short> : public true_type{ }; + template <> struct HasTrivialConstructor<const volatile signed short> : public true_type{ }; + + template <> struct HasTrivialConstructor<signed int> : public true_type{ }; + template <> struct HasTrivialConstructor<const signed int> : public true_type{ }; + template <> struct HasTrivialConstructor<volatile signed int> : public true_type{ }; + template <> struct HasTrivialConstructor<const volatile signed int> : public true_type{ }; + + template <> struct HasTrivialConstructor<signed long> : public true_type{ }; + template <> struct HasTrivialConstructor<const signed long> : public true_type{ }; + template <> struct HasTrivialConstructor<volatile signed long> : public true_type{ }; + template <> struct HasTrivialConstructor<const volatile signed long> : public true_type{ }; + + template <> struct HasTrivialConstructor<signed long long> : public true_type{ }; + template <> struct HasTrivialConstructor<const signed long long> : public true_type{ }; + template <> struct HasTrivialConstructor<volatile signed long long> : public true_type{ }; + template <> struct HasTrivialConstructor<const volatile signed long long> : public true_type{ }; + + template <> struct HasTrivialConstructor<bool> : public true_type{ }; + template <> struct HasTrivialConstructor<const bool> : public true_type{ }; + template <> struct HasTrivialConstructor<volatile bool> : public true_type{ }; + template <> struct HasTrivialConstructor<const volatile bool> : public true_type{ }; + + template <> struct HasTrivialConstructor<char> : public true_type{ }; + template <> struct HasTrivialConstructor<const char> : public true_type{ }; + template <> struct HasTrivialConstructor<volatile char> : public true_type{ }; + template <> struct HasTrivialConstructor<const volatile char> : public true_type{ }; + + #if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) + template <> struct HasTrivialConstructor<wchar_t> : public true_type{ }; + template <> struct HasTrivialConstructor<const wchar_t> : public true_type{ }; + template <> struct HasTrivialConstructor<volatile wchar_t> : public true_type{ }; + template <> struct HasTrivialConstructor<const volatile wchar_t> : public true_type{ }; + #endif + + template <> struct HasTrivialDestructor<float> : public true_type{ }; + template <> struct HasTrivialDestructor<const float> : public true_type{ }; + template <> struct HasTrivialDestructor<volatile float> : public true_type{ }; + template <> struct HasTrivialDestructor<const volatile float> : public true_type{ }; + + template <> struct HasTrivialDestructor<double> : public true_type{ }; + template <> struct HasTrivialDestructor<const double> : public true_type{ }; + template <> struct HasTrivialDestructor<volatile double> : public true_type{ }; + template <> struct HasTrivialDestructor<const volatile double> : public true_type{ }; + + template <> struct HasTrivialDestructor<long double> : public true_type{ }; + template <> struct HasTrivialDestructor<const long double> : public true_type{ }; + template <> struct HasTrivialDestructor<volatile long double> : public true_type{ }; + template <> struct HasTrivialDestructor<const volatile long double> : public true_type{ }; + + template <> struct HasTrivialDestructor<unsigned char> : public true_type{ }; + template <> struct HasTrivialDestructor<const unsigned char> : public true_type{ }; + template <> struct HasTrivialDestructor<volatile unsigned char> : public true_type{ }; + template <> struct HasTrivialDestructor<const volatile unsigned char> : public true_type{ }; + + template <> struct HasTrivialDestructor<unsigned short> : public true_type{ }; + template <> struct HasTrivialDestructor<const unsigned short> : public true_type{ }; + template <> struct HasTrivialDestructor<volatile unsigned short> : public true_type{ }; + template <> struct HasTrivialDestructor<const volatile unsigned short> : public true_type{ }; + + template <> struct HasTrivialDestructor<unsigned int> : public true_type{ }; + template <> struct HasTrivialDestructor<const unsigned int> : public true_type{ }; + template <> struct HasTrivialDestructor<volatile unsigned int> : public true_type{ }; + template <> struct HasTrivialDestructor<const volatile unsigned int> : public true_type{ }; + + template <> struct HasTrivialDestructor<unsigned long> : public true_type{ }; + template <> struct HasTrivialDestructor<const unsigned long> : public true_type{ }; + template <> struct HasTrivialDestructor<volatile unsigned long> : public true_type{ }; + template <> struct HasTrivialDestructor<const volatile unsigned long> : public true_type{ }; + + template <> struct HasTrivialDestructor<unsigned long long> : public true_type{ }; + template <> struct HasTrivialDestructor<const unsigned long long> : public true_type{ }; + template <> struct HasTrivialDestructor<volatile unsigned long long> : public true_type{ }; + template <> struct HasTrivialDestructor<const volatile unsigned long long> : public true_type{ }; + + template <> struct HasTrivialDestructor<signed char> : public true_type{ }; + template <> struct HasTrivialDestructor<const signed char> : public true_type{ }; + template <> struct HasTrivialDestructor<volatile signed char> : public true_type{ }; + template <> struct HasTrivialDestructor<const volatile signed char> : public true_type{ }; + + template <> struct HasTrivialDestructor<signed short> : public true_type{ }; + template <> struct HasTrivialDestructor<const signed short> : public true_type{ }; + template <> struct HasTrivialDestructor<volatile signed short> : public true_type{ }; + template <> struct HasTrivialDestructor<const volatile signed short> : public true_type{ }; + + template <> struct HasTrivialDestructor<signed int> : public true_type{ }; + template <> struct HasTrivialDestructor<const signed int> : public true_type{ }; + template <> struct HasTrivialDestructor<volatile signed int> : public true_type{ }; + template <> struct HasTrivialDestructor<const volatile signed int> : public true_type{ }; + + template <> struct HasTrivialDestructor<signed long> : public true_type{ }; + template <> struct HasTrivialDestructor<const signed long> : public true_type{ }; + template <> struct HasTrivialDestructor<volatile signed long> : public true_type{ }; + template <> struct HasTrivialDestructor<const volatile signed long> : public true_type{ }; + + template <> struct HasTrivialDestructor<signed long long> : public true_type{ }; + template <> struct HasTrivialDestructor<const signed long long> : public true_type{ }; + template <> struct HasTrivialDestructor<volatile signed long long> : public true_type{ }; + template <> struct HasTrivialDestructor<const volatile signed long long> : public true_type{ }; + + template <> struct HasTrivialDestructor<bool> : public true_type{ }; + template <> struct HasTrivialDestructor<const bool> : public true_type{ }; + template <> struct HasTrivialDestructor<volatile bool> : public true_type{ }; + template <> struct HasTrivialDestructor<const volatile bool> : public true_type{ }; + + template <> struct HasTrivialDestructor<char> : public true_type{ }; + template <> struct HasTrivialDestructor<const char> : public true_type{ }; + template <> struct HasTrivialDestructor<volatile char> : public true_type{ }; + template <> struct HasTrivialDestructor<const volatile char> : public true_type{ }; + + #if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) + template <> struct HasTrivialDestructor<wchar_t> : public true_type{ }; + template <> struct HasTrivialDestructor<const wchar_t> : public true_type{ }; + template <> struct HasTrivialDestructor<volatile wchar_t> : public true_type{ }; + template <> struct HasTrivialDestructor<const volatile wchar_t> : public true_type{ }; + #endif + +#endif // __GLIBCXX__, etc. + } // namespace WTF #endif // TypeTraits_h diff --git a/JavaScriptCore/wtf/VMTags.h b/JavaScriptCore/wtf/VMTags.h new file mode 100644 index 0000000..519f518 --- /dev/null +++ b/JavaScriptCore/wtf/VMTags.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VMTags_h +#define VMTags_h + +#include <wtf/Platform.h> + +// On Mac OS X, the VM subsystem allows tagging memory requested from mmap and vm_map +// in order to aid tools that inspect system memory use. +#if PLATFORM(DARWIN) && !defined(BUILDING_ON_TIGER) + +#include <mach/vm_statistics.h> + +#if defined(VM_MEMORY_JAVASCRIPT_CORE) && defined(VM_MEMORY_JAVASCRIPT_JIT_REGISTER_FILE) && defined(VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR) && defined(VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR) +#define VM_TAG_FOR_COLLECTOR_MEMORY VM_MAKE_TAG(VM_MEMORY_JAVASCRIPT_CORE) +#define VM_TAG_FOR_REGISTERFILE_MEMORY VM_MAKE_TAG(VM_MEMORY_JAVASCRIPT_JIT_REGISTER_FILE) +#define VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY VM_MAKE_TAG(VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR) +#else +#define VM_TAG_FOR_COLLECTOR_MEMORY VM_MAKE_TAG(63) +#define VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY VM_MAKE_TAG(64) +#define VM_TAG_FOR_REGISTERFILE_MEMORY VM_MAKE_TAG(65) +#endif // defined(VM_MEMORY_JAVASCRIPT_CORE) && defined(VM_MEMORY_JAVASCRIPT_JIT_REGISTER_FILE) && defined(VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR) && defined(VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR) + +#else // PLATFORM(DARWIN) && !defined(BUILDING_ON_TIGER) + +#define VM_TAG_FOR_COLLECTOR_MEMORY -1 +#define VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY -1 +#define VM_TAG_FOR_REGISTERFILE_MEMORY -1 + +#endif // PLATFORM(DARWIN) && !defined(BUILDING_ON_TIGER) + +#endif // VMTags_h diff --git a/JavaScriptCore/wtf/Vector.h b/JavaScriptCore/wtf/Vector.h index 190226d..dcfeb29 100644 --- a/JavaScriptCore/wtf/Vector.h +++ b/JavaScriptCore/wtf/Vector.h @@ -692,7 +692,7 @@ namespace WTF { } template<typename T, size_t inlineCapacity> - void Vector<T, inlineCapacity>::resize(size_t size) + inline void Vector<T, inlineCapacity>::resize(size_t size) { if (size <= m_size) TypeOperations::destruct(begin() + size, end()); @@ -781,6 +781,8 @@ namespace WTF { if (!begin()) return; } + if (newSize < m_size) + CRASH(); T* dest = end(); for (size_t i = 0; i < dataSize; ++i) new (&dest[i]) T(data[i]); @@ -788,7 +790,7 @@ namespace WTF { } template<typename T, size_t inlineCapacity> template<typename U> - inline void Vector<T, inlineCapacity>::append(const U& val) + ALWAYS_INLINE void Vector<T, inlineCapacity>::append(const U& val) { const U* ptr = &val; if (size() == capacity()) { @@ -842,6 +844,8 @@ namespace WTF { if (!begin()) return; } + if (newSize < m_size) + CRASH(); T* spot = begin() + position; TypeOperations::moveOverlapping(spot, end(), spot + dataSize); for (size_t i = 0; i < dataSize; ++i) diff --git a/JavaScriptCore/wtf/dtoa.cpp b/JavaScriptCore/wtf/dtoa.cpp index c104dad..9509388 100644 --- a/JavaScriptCore/wtf/dtoa.cpp +++ b/JavaScriptCore/wtf/dtoa.cpp @@ -150,6 +150,8 @@ #include <wtf/FastMalloc.h> #include <wtf/Threading.h> +#include <stdio.h> + #if COMPILER(MSVC) #pragma warning(disable: 4244) #pragma warning(disable: 4245) @@ -189,13 +191,13 @@ typedef union { double d; uint32_t L[2]; } U; #endif #else #ifdef IEEE_8087 -#define word0(x) ((U*)&x)->L[1] -#define word1(x) ((U*)&x)->L[0] +#define word0(x) (x)->L[1] +#define word1(x) (x)->L[0] #else -#define word0(x) ((U*)&x)->L[0] -#define word1(x) ((U*)&x)->L[1] +#define word0(x) (x)->L[0] +#define word1(x) (x)->L[1] #endif -#define dval(x) ((U*)&x)->d +#define dval(x) (x)->d #endif /* The following definition of Storeinc is appropriate for MIPS processors. @@ -275,32 +277,29 @@ typedef union { double d; uint32_t L[2]; } U; #define Kmax 15 -struct Bigint { - struct Bigint* next; - int k, maxwds, sign, wds; - uint32_t x[1]; -}; - -static Bigint* Balloc(int k) -{ - int x = 1 << k; - Bigint* rv = (Bigint*)fastMalloc(sizeof(Bigint) + (x - 1)*sizeof(uint32_t)); - rv->k = k; - rv->maxwds = x; - rv->next = 0; - rv->sign = rv->wds = 0; - - return rv; -} - -static void Bfree(Bigint* v) -{ - fastFree(v); -} +struct BigInt { + BigInt() : sign(0), wds(0) { } + BigInt(const BigInt& other) : sign(other.sign), wds(other.wds) + { + for (int i = 0; i < 64; ++i) + x[i] = other.x[i]; + } -#define Bcopy(x, y) memcpy((char*)&x->sign, (char*)&y->sign, y->wds * sizeof(int32_t) + 2 * sizeof(int)) + BigInt& operator=(const BigInt& other) + { + sign = other.sign; + wds = other.wds; + for (int i = 0; i < 64; ++i) + x[i] = other.x[i]; + return *this; + } + + int sign; + int wds; + uint32_t x[64]; +}; -static Bigint* multadd(Bigint* b, int m, int a) /* multiply by m and add a */ +static void multadd(BigInt& b, int m, int a) /* multiply by m and add a */ { #ifdef USE_LONG_LONG unsigned long long carry; @@ -308,8 +307,8 @@ static Bigint* multadd(Bigint* b, int m, int a) /* multiply by m and add a */ uint32_t carry; #endif - int wds = b->wds; - uint32_t* x = b->x; + int wds = b.wds; + uint32_t* x = b.x; int i = 0; carry = a; do { @@ -333,19 +332,12 @@ static Bigint* multadd(Bigint* b, int m, int a) /* multiply by m and add a */ } while (++i < wds); if (carry) { - if (wds >= b->maxwds) { - Bigint* b1 = Balloc(b->k + 1); - Bcopy(b1, b); - Bfree(b); - b = b1; - } - b->x[wds++] = (uint32_t)carry; - b->wds = wds; + b.x[wds++] = (uint32_t)carry; + b.wds = wds; } - return b; } -static Bigint* s2b(const char* s, int nd0, int nd, uint32_t y9) +static void s2b(BigInt& b, const char* s, int nd0, int nd, uint32_t y9) { int k; int32_t y; @@ -353,27 +345,26 @@ static Bigint* s2b(const char* s, int nd0, int nd, uint32_t y9) for (k = 0, y = 1; x > y; y <<= 1, k++) { } #ifdef Pack_32 - Bigint* b = Balloc(k); - b->x[0] = y9; - b->wds = 1; + b.sign = 0; + b.x[0] = y9; + b.wds = 1; #else - Bigint* b = Balloc(k + 1); - b->x[0] = y9 & 0xffff; - b->wds = (b->x[1] = y9 >> 16) ? 2 : 1; + b.sign = 0; + b.x[0] = y9 & 0xffff; + b.wds = (b->x[1] = y9 >> 16) ? 2 : 1; #endif int i = 9; if (9 < nd0) { s += 9; do { - b = multadd(b, 10, *s++ - '0'); + multadd(b, 10, *s++ - '0'); } while (++i < nd0); s++; } else s += 10; for (; i < nd; i++) - b = multadd(b, 10, *s++ - '0'); - return b; + multadd(b, 10, *s++ - '0'); } static int hi0bits(uint32_t x) @@ -446,21 +437,21 @@ static int lo0bits (uint32_t* y) return k; } -static Bigint* i2b(int i) +static void i2b(BigInt& b, int i) { - Bigint* b; - - b = Balloc(1); - b->x[0] = i; - b->wds = 1; - return b; + b.sign = 0; + b.x[0] = i; + b.wds = 1; } -static Bigint* mult(Bigint* a, Bigint* b) +static void mult(BigInt& aRef, const BigInt& bRef) { - Bigint* c; - int k, wa, wb, wc; - uint32_t *x, *xa, *xae, *xb, *xbe, *xc, *xc0; + const BigInt* a = &aRef; + const BigInt* b = &bRef; + BigInt c; + int wa, wb, wc; + const uint32_t *x = 0, *xa, *xb, *xae, *xbe; + uint32_t *xc, *xc0; uint32_t y; #ifdef USE_LONG_LONG unsigned long long carry, z; @@ -469,24 +460,22 @@ static Bigint* mult(Bigint* a, Bigint* b) #endif if (a->wds < b->wds) { - c = a; + const BigInt* tmp = a; a = b; - b = c; + b = tmp; } - k = a->k; + wa = a->wds; wb = b->wds; wc = wa + wb; - if (wc > a->maxwds) - k++; - c = Balloc(k); - for (x = c->x, xa = x + wc; x < xa; x++) - *x = 0; + + for (xc = c.x, xa = xc + wc; xc < xa; xc++) + *xc = 0; xa = a->x; xae = xa + wa; xb = b->x; xbe = xb + wb; - xc0 = c->x; + xc0 = c.x; #ifdef USE_LONG_LONG for (; xb < xbe; xc0++) { if ((y = *xb++)) { @@ -548,33 +537,43 @@ static Bigint* mult(Bigint* a, Bigint* b) } #endif #endif - for (xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) { } - c->wds = wc; - return c; + for (xc0 = c.x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) { } + c.wds = wc; + aRef = c; } -static Bigint* p5s; +struct P5Node { + BigInt val; + P5Node* next; +}; + +static P5Node* p5s; static int p5s_count; -static Bigint* pow5mult(Bigint* b, int k) +static ALWAYS_INLINE void pow5mult(BigInt& b, int k) { static int p05[3] = { 5, 25, 125 }; if (int i = k & 3) - b = multadd(b, p05[i - 1], 0); + multadd(b, p05[i - 1], 0); if (!(k >>= 2)) - return b; + return; #if ENABLE(JSC_MULTIPLE_THREADS) s_dtoaP5Mutex->lock(); #endif - Bigint* p5 = p5s; + P5Node* p5 = p5s; + if (!p5) { /* first time */ - p5 = p5s = i2b(625); + p5 = new P5Node; + i2b(p5->val, 625); + p5->next = 0; + p5s = p5; p5s_count = 1; } + int p5s_count_local = p5s_count; #if ENABLE(JSC_MULTIPLE_THREADS) s_dtoaP5Mutex->unlock(); @@ -582,11 +581,9 @@ static Bigint* pow5mult(Bigint* b, int k) int p5s_used = 0; for (;;) { - if (k & 1) { - Bigint* b1 = mult(b, p5); - Bfree(b); - b = b1; - } + if (k & 1) + mult(b, p5->val); + if (!(k >>= 1)) break; @@ -596,7 +593,10 @@ static Bigint* pow5mult(Bigint* b, int k) #endif if (p5s_used == p5s_count) { ASSERT(!p5->next); - p5->next = mult(p5, p5); + p5->next = new P5Node; + p5->next->next = 0; + p5->next->val = p5->val; + mult(p5->next->val, p5->next->val); ++p5s_count; } @@ -607,30 +607,21 @@ static Bigint* pow5mult(Bigint* b, int k) } p5 = p5->next; } - - return b; } -static Bigint* lshift(Bigint* b, int k) +static ALWAYS_INLINE void lshift(BigInt& b, int k) { - Bigint* result = b; - #ifdef Pack_32 int n = k >> 5; #else int n = k >> 4; #endif - int k1 = b->k; - int n1 = n + b->wds + 1; - for (int i = b->maxwds; n1 > i; i <<= 1) - k1++; - if (b->k < k1) - result = Balloc(k1); + int n1 = n + b.wds + 1; - const uint32_t* srcStart = b->x; - uint32_t* dstStart = result->x; - const uint32_t* src = srcStart + b->wds - 1; + const uint32_t* srcStart = b.x; + uint32_t* dstStart = b.x; + const uint32_t* src = srcStart + b.wds - 1; uint32_t* dst = dstStart + n1 - 1; #ifdef Pack_32 if (k &= 0x1f) { @@ -642,7 +633,7 @@ static Bigint* lshift(Bigint* b, int k) } *dst = hiSubword; ASSERT(dst == dstStart + n); - result->wds = b->wds + n + (result->x[n1 - 1] != 0); + b.wds = b.wds + n + (b.x[n1 - 1] != 0); } #else if (k &= 0xf) { @@ -661,30 +652,26 @@ static Bigint* lshift(Bigint* b, int k) do { *--dst = *src--; } while (src >= srcStart); - result->wds = b->wds + n; + b.wds = b.wds + n; } for (dst = dstStart + n; dst != dstStart; ) *--dst = 0; - - if (result != b) - Bfree(b); - return result; } -static int cmp(Bigint* a, Bigint* b) +static int cmp(const BigInt& a, const BigInt& b) { - uint32_t *xa, *xa0, *xb, *xb0; + const uint32_t *xa, *xa0, *xb, *xb0; int i, j; - i = a->wds; - j = b->wds; - ASSERT(i <= 1 || a->x[i - 1]); - ASSERT(j <= 1 || b->x[j - 1]); + i = a.wds; + j = b.wds; + ASSERT(i <= 1 || a.x[i - 1]); + ASSERT(j <= 1 || b.x[j - 1]); if (i -= j) return i; - xa0 = a->x; + xa0 = a.x; xa = xa0 + j; - xb0 = b->x; + xb0 = b.x; xb = xb0 + j; for (;;) { if (*--xa != *--xb) @@ -695,35 +682,37 @@ static int cmp(Bigint* a, Bigint* b) return 0; } -static Bigint* diff(Bigint* a, Bigint* b) +static ALWAYS_INLINE void diff(BigInt& c, const BigInt& aRef, const BigInt& bRef) { - Bigint* c; + const BigInt* a = &aRef; + const BigInt* b = &bRef; int i, wa, wb; - uint32_t *xa, *xae, *xb, *xbe, *xc; + uint32_t *xc; - i = cmp(a,b); + i = cmp(*a, *b); if (!i) { - c = Balloc(0); - c->wds = 1; - c->x[0] = 0; - return c; + c.sign = 0; + c.wds = 1; + c.x[0] = 0; + return; } if (i < 0) { - c = a; + const BigInt* tmp = a; a = b; - b = c; + b = tmp; i = 1; } else i = 0; - c = Balloc(a->k); - c->sign = i; + + c.wds = 0; + c.sign = i; wa = a->wds; - xa = a->x; - xae = xa + wa; + const uint32_t* xa = a->x; + const uint32_t* xae = xa + wa; wb = b->wds; - xb = b->x; - xbe = xb + wb; - xc = c->x; + const uint32_t* xb = b->x; + const uint32_t* xbe = xb + wb; + xc = c.x; #ifdef USE_LONG_LONG unsigned long long borrow = 0; do { @@ -768,14 +757,13 @@ static Bigint* diff(Bigint* a, Bigint* b) #endif while (!*--xc) wa--; - c->wds = wa; - return c; + c.wds = wa; } -static double ulp(double x) +static double ulp(U *x) { register int32_t L; - double a; + U u; L = (word0(x) & Exp_mask) - (P - 1) * Exp_msk1; #ifndef Avoid_Underflow @@ -783,41 +771,41 @@ static double ulp(double x) if (L > 0) { #endif #endif - word0(a) = L; - word1(a) = 0; + word0(&u) = L; + word1(&u) = 0; #ifndef Avoid_Underflow #ifndef Sudden_Underflow } else { L = -L >> Exp_shift; if (L < Exp_shift) { - word0(a) = 0x80000 >> L; - word1(a) = 0; + word0(&u) = 0x80000 >> L; + word1(&u) = 0; } else { - word0(a) = 0; + word0(&u) = 0; L -= Exp_shift; - word1(a) = L >= 31 ? 1 : 1 << 31 - L; + word1(&u) = L >= 31 ? 1 : 1 << 31 - L; } } #endif #endif - return dval(a); + return dval(&u); } -static double b2d(Bigint* a, int* e) +static double b2d(const BigInt& a, int* e) { - uint32_t* xa; - uint32_t* xa0; + const uint32_t* xa; + const uint32_t* xa0; uint32_t w; uint32_t y; uint32_t z; int k; - double d; + U d; -#define d0 word0(d) -#define d1 word1(d) +#define d0 word0(&d) +#define d1 word1(&d) - xa0 = a->x; - xa = xa0 + a->wds; + xa0 = a.x; + xa = xa0 + a.wds; y = *--xa; ASSERT(y); k = hi0bits(y); @@ -857,12 +845,11 @@ static double b2d(Bigint* a, int* e) ret_d: #undef d0 #undef d1 - return dval(d); + return dval(&d); } -static Bigint* d2b(double d, int* e, int* bits) +static ALWAYS_INLINE void d2b(BigInt& b, U* d, int* e, int* bits) { - Bigint* b; int de, k; uint32_t *x, y, z; #ifndef Sudden_Underflow @@ -871,12 +858,13 @@ static Bigint* d2b(double d, int* e, int* bits) #define d0 word0(d) #define d1 word1(d) + b.sign = 0; #ifdef Pack_32 - b = Balloc(1); + b.wds = 1; #else - b = Balloc(2); + b.wds = 2; #endif - x = b->x; + x = b.x; z = d0 & Frac_mask; d0 &= 0x7fffffff; /* clear sign bit, which we ignore */ @@ -896,14 +884,14 @@ static Bigint* d2b(double d, int* e, int* bits) #ifndef Sudden_Underflow i = #endif - b->wds = (x[1] = z) ? 2 : 1; + b.wds = (x[1] = z) ? 2 : 1; } else { k = lo0bits(&z); x[0] = z; #ifndef Sudden_Underflow i = #endif - b->wds = 1; + b.wds = 1; k += 32; } #else @@ -958,30 +946,29 @@ static Bigint* d2b(double d, int* e, int* bits) #endif } #endif - return b; } #undef d0 #undef d1 -static double ratio(Bigint* a, Bigint* b) +static double ratio(const BigInt& a, const BigInt& b) { - double da, db; + U da, db; int k, ka, kb; - dval(da) = b2d(a, &ka); - dval(db) = b2d(b, &kb); + dval(&da) = b2d(a, &ka); + dval(&db) = b2d(b, &kb); #ifdef Pack_32 - k = ka - kb + 32 * (a->wds - b->wds); + k = ka - kb + 32 * (a.wds - b.wds); #else - k = ka - kb + 16 * (a->wds - b->wds); + k = ka - kb + 16 * (a.wds - b.wds); #endif if (k > 0) - word0(da) += k * Exp_msk1; + word0(&da) += k * Exp_msk1; else { k = -k; - word0(db) += k * Exp_msk1; + word0(&db) += k * Exp_msk1; } - return dval(da) / dval(db); + return dval(&da) / dval(&db); } static const double tens[] = { @@ -1031,7 +1018,7 @@ static int match(const char** sp, const char* t) } #ifndef No_Hex_NaN -static void hexnan(double* rvp, const char** sp) +static void hexnan(U* rvp, const char** sp) { uint32_t c, x[2]; const char* s; @@ -1070,8 +1057,8 @@ static void hexnan(double* rvp, const char** sp) x[1] = (x[1] << 4) | c; } if ((x[0] &= 0xfffff) || x[1]) { - word0(*rvp) = Exp_mask | x[0]; - word1(*rvp) = x[1]; + word0(rvp) = Exp_mask | x[0]; + word1(rvp) = x[1]; } } #endif /*No_Hex_NaN*/ @@ -1085,16 +1072,17 @@ double strtod(const char* s00, char** se) int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign, e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign; const char *s, *s0, *s1; - double aadj, aadj1, adj, rv, rv0; + double aadj, aadj1; + U aadj2, adj, rv, rv0; int32_t L; uint32_t y, z; - Bigint *bb = NULL, *bb1 = NULL, *bd = NULL, *bd0 = NULL, *bs = NULL, *delta = NULL; + BigInt bb, bb1, bd, bd0, bs, delta; #ifdef SET_INEXACT int inexact, oldinexact; #endif sign = nz0 = nz = 0; - dval(rv) = 0.; + dval(&rv) = 0; for (s = s00; ; s++) switch (*s) { case '-': @@ -1209,16 +1197,16 @@ dig_done: --s; if (!match(&s,"inity")) ++s; - word0(rv) = 0x7ff00000; - word1(rv) = 0; + word0(&rv) = 0x7ff00000; + word1(&rv) = 0; goto ret; } break; case 'n': case 'N': if (match(&s, "an")) { - word0(rv) = NAN_WORD0; - word1(rv) = NAN_WORD1; + word0(&rv) = NAN_WORD0; + word1(&rv) = NAN_WORD1; #ifndef No_Hex_NaN if (*s == '(') /*)*/ hexnan(&rv, &s); @@ -1243,21 +1231,20 @@ ret0: if (!nd0) nd0 = nd; k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1; - dval(rv) = y; + dval(&rv) = y; if (k > 9) { #ifdef SET_INEXACT if (k > DBL_DIG) oldinexact = get_inexact(); #endif - dval(rv) = tens[k - 9] * dval(rv) + z; + dval(&rv) = tens[k - 9] * dval(&rv) + z; } - bd0 = 0; if (nd <= DBL_DIG && Flt_Rounds == 1) { if (!e) goto ret; if (e > 0) { if (e <= Ten_pmax) { - /* rv = */ rounded_product(dval(rv), tens[e]); + /* rv = */ rounded_product(dval(&rv), tens[e]); goto ret; } i = DBL_DIG - nd; @@ -1266,14 +1253,14 @@ ret0: * this for larger i values. */ e -= i; - dval(rv) *= tens[i]; - /* rv = */ rounded_product(dval(rv), tens[e]); + dval(&rv) *= tens[i]; + /* rv = */ rounded_product(dval(&rv), tens[e]); goto ret; } } #ifndef Inaccurate_Divide else if (e >= -Ten_pmax) { - /* rv = */ rounded_quotient(dval(rv), tens[-e]); + /* rv = */ rounded_quotient(dval(&rv), tens[-e]); goto ret; } #endif @@ -1293,7 +1280,7 @@ ret0: if (e1 > 0) { if ((i = e1 & 15)) - dval(rv) *= tens[i]; + dval(&rv) *= tens[i]; if (e1 &= ~15) { if (e1 > DBL_MAX_10_EXP) { ovfl: @@ -1301,38 +1288,36 @@ ovfl: errno = ERANGE; #endif /* Can't trust HUGE_VAL */ - word0(rv) = Exp_mask; - word1(rv) = 0; + word0(&rv) = Exp_mask; + word1(&rv) = 0; #ifdef SET_INEXACT /* set overflow bit */ - dval(rv0) = 1e300; - dval(rv0) *= dval(rv0); + dval(&rv0) = 1e300; + dval(&rv0) *= dval(&rv0); #endif - if (bd0) - goto retfree; goto ret; } e1 >>= 4; for (j = 0; e1 > 1; j++, e1 >>= 1) if (e1 & 1) - dval(rv) *= bigtens[j]; + dval(&rv) *= bigtens[j]; /* The last multiplication could overflow. */ - word0(rv) -= P * Exp_msk1; - dval(rv) *= bigtens[j]; - if ((z = word0(rv) & Exp_mask) > Exp_msk1 * (DBL_MAX_EXP + Bias - P)) + word0(&rv) -= P * Exp_msk1; + dval(&rv) *= bigtens[j]; + if ((z = word0(&rv) & Exp_mask) > Exp_msk1 * (DBL_MAX_EXP + Bias - P)) goto ovfl; if (z > Exp_msk1 * (DBL_MAX_EXP + Bias - 1 - P)) { /* set to largest number */ /* (Can't trust DBL_MAX) */ - word0(rv) = Big0; - word1(rv) = Big1; + word0(&rv) = Big0; + word1(&rv) = Big1; } else - word0(rv) += P * Exp_msk1; + word0(&rv) += P * Exp_msk1; } } else if (e1 < 0) { e1 = -e1; if ((i = e1 & 15)) - dval(rv) /= tens[i]; + dval(&rv) /= tens[i]; if (e1 >>= 4) { if (e1 >= 1 << n_bigtens) goto undfl; @@ -1341,42 +1326,40 @@ ovfl: scale = 2 * P; for (j = 0; e1 > 0; j++, e1 >>= 1) if (e1 & 1) - dval(rv) *= tinytens[j]; - if (scale && (j = (2 * P) + 1 - ((word0(rv) & Exp_mask) >> Exp_shift)) > 0) { + dval(&rv) *= tinytens[j]; + if (scale && (j = (2 * P) + 1 - ((word0(&rv) & Exp_mask) >> Exp_shift)) > 0) { /* scaled rv is denormal; zap j low bits */ if (j >= 32) { - word1(rv) = 0; + word1(&rv) = 0; if (j >= 53) - word0(rv) = (P + 2) * Exp_msk1; + word0(&rv) = (P + 2) * Exp_msk1; else - word0(rv) &= 0xffffffff << (j - 32); + word0(&rv) &= 0xffffffff << (j - 32); } else - word1(rv) &= 0xffffffff << j; + word1(&rv) &= 0xffffffff << j; } #else for (j = 0; e1 > 1; j++, e1 >>= 1) if (e1 & 1) - dval(rv) *= tinytens[j]; + dval(&rv) *= tinytens[j]; /* The last multiplication could underflow. */ - dval(rv0) = dval(rv); - dval(rv) *= tinytens[j]; - if (!dval(rv)) { - dval(rv) = 2. * dval(rv0); - dval(rv) *= tinytens[j]; + dval(&rv0) = dval(&rv); + dval(&rv) *= tinytens[j]; + if (!dval(&rv)) { + dval(&rv) = 2. * dval(&rv0); + dval(&rv) *= tinytens[j]; #endif - if (!dval(rv)) { + if (!dval(&rv)) { undfl: - dval(rv) = 0.; + dval(&rv) = 0.; #ifndef NO_ERRNO errno = ERANGE; #endif - if (bd0) - goto retfree; goto ret; } #ifndef Avoid_Underflow - word0(rv) = Tiny0; - word1(rv) = Tiny1; + word0(&rv) = Tiny0; + word1(&rv) = Tiny1; /* The refinement below will clean * this approximation up. */ @@ -1389,13 +1372,12 @@ undfl: /* Put digits into bd: true value = bd * 10^e */ - bd0 = s2b(s0, nd0, nd, y); + s2b(bd0, s0, nd0, nd, y); for (;;) { - bd = Balloc(bd0->k); - Bcopy(bd, bd0); - bb = d2b(dval(rv), &bbe, &bbbits); /* rv = bb * 2^bbe */ - bs = i2b(1); + bd = bd0; + d2b(bb, &rv, &bbe, &bbbits); /* rv = bb * 2^bbe */ + i2b(bs, 1); if (e >= 0) { bb2 = bb5 = 0; @@ -1442,33 +1424,31 @@ undfl: bs2 -= i; } if (bb5 > 0) { - bs = pow5mult(bs, bb5); - bb1 = mult(bs, bb); - Bfree(bb); - bb = bb1; + pow5mult(bs, bb5); + mult(bb, bs); } if (bb2 > 0) - bb = lshift(bb, bb2); + lshift(bb, bb2); if (bd5 > 0) - bd = pow5mult(bd, bd5); + pow5mult(bd, bd5); if (bd2 > 0) - bd = lshift(bd, bd2); + lshift(bd, bd2); if (bs2 > 0) - bs = lshift(bs, bs2); - delta = diff(bb, bd); - dsign = delta->sign; - delta->sign = 0; + lshift(bs, bs2); + diff(delta, bb, bd); + dsign = delta.sign; + delta.sign = 0; i = cmp(delta, bs); if (i < 0) { /* Error is less than half an ulp -- check for * special case of mantissa a power of two. */ - if (dsign || word1(rv) || word0(rv) & Bndry_mask + if (dsign || word1(&rv) || word0(&rv) & Bndry_mask #ifdef Avoid_Underflow - || (word0(rv) & Exp_mask) <= (2 * P + 1) * Exp_msk1 + || (word0(&rv) & Exp_mask) <= (2 * P + 1) * Exp_msk1 #else - || (word0(rv) & Exp_mask) <= Exp_msk1 + || (word0(&rv) & Exp_mask) <= Exp_msk1 #endif ) { #ifdef SET_INEXACT @@ -1477,14 +1457,14 @@ undfl: #endif break; } - if (!delta->x[0] && delta->wds <= 1) { + if (!delta.x[0] && delta.wds <= 1) { /* exact result */ #ifdef SET_INEXACT inexact = 0; #endif break; } - delta = lshift(delta,Log2P); + lshift(delta, Log2P); if (cmp(delta, bs) > 0) goto drop_down; break; @@ -1492,26 +1472,26 @@ undfl: if (i == 0) { /* exactly half-way between */ if (dsign) { - if ((word0(rv) & Bndry_mask1) == Bndry_mask1 - && word1(rv) == ( + if ((word0(&rv) & Bndry_mask1) == Bndry_mask1 + && word1(&rv) == ( #ifdef Avoid_Underflow - (scale && (y = word0(rv) & Exp_mask) <= 2 * P * Exp_msk1) + (scale && (y = word0(&rv) & Exp_mask) <= 2 * P * Exp_msk1) ? (0xffffffff & (0xffffffff << (2 * P + 1 - (y >> Exp_shift)))) : #endif 0xffffffff)) { /*boundary case -- increment exponent*/ - word0(rv) = (word0(rv) & Exp_mask) + Exp_msk1; - word1(rv) = 0; + word0(&rv) = (word0(&rv) & Exp_mask) + Exp_msk1; + word1(&rv) = 0; #ifdef Avoid_Underflow dsign = 0; #endif break; } - } else if (!(word0(rv) & Bndry_mask) && !word1(rv)) { + } else if (!(word0(&rv) & Bndry_mask) && !word1(&rv)) { drop_down: /* boundary case -- decrement exponent */ #ifdef Sudden_Underflow /*{{*/ - L = word0(rv) & Exp_mask; + L = word0(&rv) & Exp_mask; #ifdef Avoid_Underflow if (L <= (scale ? (2 * P + 1) * Exp_msk1 : Exp_msk1)) #else @@ -1522,7 +1502,7 @@ drop_down: #else /*Sudden_Underflow}{*/ #ifdef Avoid_Underflow if (scale) { - L = word0(rv) & Exp_mask; + L = word0(&rv) & Exp_mask; if (L <= (2 * P + 1) * Exp_msk1) { if (L > (P + 2) * Exp_msk1) /* round even ==> */ @@ -1533,20 +1513,20 @@ drop_down: } } #endif /*Avoid_Underflow*/ - L = (word0(rv) & Exp_mask) - Exp_msk1; + L = (word0(&rv) & Exp_mask) - Exp_msk1; #endif /*Sudden_Underflow}}*/ - word0(rv) = L | Bndry_mask1; - word1(rv) = 0xffffffff; + word0(&rv) = L | Bndry_mask1; + word1(&rv) = 0xffffffff; break; } - if (!(word1(rv) & LSB)) + if (!(word1(&rv) & LSB)) break; if (dsign) - dval(rv) += ulp(dval(rv)); + dval(&rv) += ulp(&rv); else { - dval(rv) -= ulp(dval(rv)); + dval(&rv) -= ulp(&rv); #ifndef Sudden_Underflow - if (!dval(rv)) + if (!dval(&rv)) goto undfl; #endif } @@ -1558,9 +1538,9 @@ drop_down: if ((aadj = ratio(delta, bs)) <= 2.) { if (dsign) aadj = aadj1 = 1.; - else if (word1(rv) || word0(rv) & Bndry_mask) { + else if (word1(&rv) || word0(&rv) & Bndry_mask) { #ifndef Sudden_Underflow - if (word1(rv) == Tiny1 && !word0(rv)) + if (word1(&rv) == Tiny1 && !word0(&rv)) goto undfl; #endif aadj = 1.; @@ -1592,23 +1572,23 @@ drop_down: aadj1 += 0.5; #endif /*Check_FLT_ROUNDS*/ } - y = word0(rv) & Exp_mask; + y = word0(&rv) & Exp_mask; /* Check for overflow */ if (y == Exp_msk1 * (DBL_MAX_EXP + Bias - 1)) { - dval(rv0) = dval(rv); - word0(rv) -= P * Exp_msk1; - adj = aadj1 * ulp(dval(rv)); - dval(rv) += adj; - if ((word0(rv) & Exp_mask) >= Exp_msk1 * (DBL_MAX_EXP + Bias - P)) { - if (word0(rv0) == Big0 && word1(rv0) == Big1) + dval(&rv0) = dval(&rv); + word0(&rv) -= P * Exp_msk1; + adj.d = aadj1 * ulp(&rv); + dval(&rv) += adj.d; + if ((word0(&rv) & Exp_mask) >= Exp_msk1 * (DBL_MAX_EXP + Bias - P)) { + if (word0(&rv0) == Big0 && word1(&rv0) == Big1) goto ovfl; - word0(rv) = Big0; - word1(rv) = Big1; + word0(&rv) = Big0; + word1(&rv) = Big1; goto cont; } else - word0(rv) += P * Exp_msk1; + word0(&rv) += P * Exp_msk1; } else { #ifdef Avoid_Underflow if (scale && y <= 2 * P * Exp_msk1) { @@ -1618,30 +1598,32 @@ drop_down: aadj = z; aadj1 = dsign ? aadj : -aadj; } - word0(aadj1) += (2 * P + 1) * Exp_msk1 - y; + dval(&aadj2) = aadj1; + word0(&aadj2) += (2 * P + 1) * Exp_msk1 - y; + aadj1 = dval(&aadj2); } - adj = aadj1 * ulp(dval(rv)); - dval(rv) += adj; + adj.d = aadj1 * ulp(&rv); + dval(&rv) += adj.d; #else #ifdef Sudden_Underflow - if ((word0(rv) & Exp_mask) <= P * Exp_msk1) { - dval(rv0) = dval(rv); - word0(rv) += P * Exp_msk1; - adj = aadj1 * ulp(dval(rv)); - dval(rv) += adj; - if ((word0(rv) & Exp_mask) <= P * Exp_msk1) + if ((word0(&rv) & Exp_mask) <= P * Exp_msk1) { + dval(&rv0) = dval(&rv); + word0(&rv) += P * Exp_msk1; + adj.d = aadj1 * ulp(&rv); + dval(&rv) += adj.d; + if ((word0(&rv) & Exp_mask) <= P * Exp_msk1) { - if (word0(rv0) == Tiny0 && word1(rv0) == Tiny1) + if (word0(&rv0) == Tiny0 && word1(&rv0) == Tiny1) goto undfl; - word0(rv) = Tiny0; - word1(rv) = Tiny1; + word0(&rv) = Tiny0; + word1(&rv) = Tiny1; goto cont; } else - word0(rv) -= P * Exp_msk1; + word0(&rv) -= P * Exp_msk1; } else { - adj = aadj1 * ulp(dval(rv)); - dval(rv) += adj; + adj.d = aadj1 * ulp(&rv); + dval(&rv) += adj.d; } #else /*Sudden_Underflow*/ /* Compute adj so that the IEEE rounding rules will @@ -1656,12 +1638,12 @@ drop_down: if (!dsign) aadj1 = -aadj1; } - adj = aadj1 * ulp(dval(rv)); - dval(rv) += adj; + adj.d = aadj1 * ulp(&rv); + dval(&rv) += adj.d; #endif /*Sudden_Underflow*/ #endif /*Avoid_Underflow*/ } - z = word0(rv) & Exp_mask; + z = word0(&rv) & Exp_mask; #ifndef SET_INEXACT #ifdef Avoid_Underflow if (!scale) @@ -1671,7 +1653,7 @@ drop_down: L = (int32_t)aadj; aadj -= L; /* The tolerances below are conservative. */ - if (dsign || word1(rv) || word0(rv) & Bndry_mask) { + if (dsign || word1(&rv) || word0(&rv) & Bndry_mask) { if (aadj < .4999999 || aadj > .5000001) break; } else if (aadj < .4999999 / FLT_RADIX) @@ -1679,53 +1661,44 @@ drop_down: } #endif cont: - Bfree(bb); - Bfree(bd); - Bfree(bs); - Bfree(delta); + ; } #ifdef SET_INEXACT if (inexact) { if (!oldinexact) { - word0(rv0) = Exp_1 + (70 << Exp_shift); - word1(rv0) = 0; - dval(rv0) += 1.; + word0(&rv0) = Exp_1 + (70 << Exp_shift); + word1(&rv0) = 0; + dval(&rv0) += 1.; } } else if (!oldinexact) clear_inexact(); #endif #ifdef Avoid_Underflow if (scale) { - word0(rv0) = Exp_1 - 2 * P * Exp_msk1; - word1(rv0) = 0; - dval(rv) *= dval(rv0); + word0(&rv0) = Exp_1 - 2 * P * Exp_msk1; + word1(&rv0) = 0; + dval(&rv) *= dval(&rv0); #ifndef NO_ERRNO /* try to avoid the bug of testing an 8087 register value */ - if (word0(rv) == 0 && word1(rv) == 0) + if (word0(&rv) == 0 && word1(&rv) == 0) errno = ERANGE; #endif } #endif /* Avoid_Underflow */ #ifdef SET_INEXACT - if (inexact && !(word0(rv) & Exp_mask)) { + if (inexact && !(word0(&rv) & Exp_mask)) { /* set underflow bit */ - dval(rv0) = 1e-300; - dval(rv0) *= dval(rv0); + dval(&rv0) = 1e-300; + dval(&rv0) *= dval(&rv0); } #endif -retfree: - Bfree(bb); - Bfree(bd); - Bfree(bs); - Bfree(bd0); - Bfree(delta); ret: if (se) *se = const_cast<char*>(s); - return sign ? -dval(rv) : dval(rv); + return sign ? -dval(&rv) : dval(&rv); } -static int quorem(Bigint* b, Bigint* S) +static ALWAYS_INLINE int quorem(BigInt& b, BigInt& S) { int n; uint32_t *bx, *bxe, q, *sx, *sxe; @@ -1738,13 +1711,13 @@ static int quorem(Bigint* b, Bigint* S) #endif #endif - n = S->wds; - ASSERT_WITH_MESSAGE(b->wds <= n, "oversize b in quorem"); - if (b->wds < n) + n = S.wds; + ASSERT_WITH_MESSAGE(b.wds <= n, "oversize b in quorem"); + if (b.wds < n) return 0; - sx = S->x; + sx = S.x; sxe = sx + --n; - bx = b->x; + bx = b.x; bxe = bx + n; q = *bxe / (*sxe + 1); /* ensure q <= true quotient */ ASSERT_WITH_MESSAGE(q <= 9, "oversized quotient in quorem"); @@ -1779,18 +1752,18 @@ static int quorem(Bigint* b, Bigint* S) #endif } while (sx <= sxe); if (!*bxe) { - bx = b->x; + bx = b.x; while (--bxe > bx && !*bxe) --n; - b->wds = n; + b.wds = n; } } if (cmp(b, S) >= 0) { q++; borrow = 0; carry = 0; - bx = b->x; - sx = S->x; + bx = b.x; + sx = S.x; do { #ifdef USE_LONG_LONG ys = *sx++ + carry; @@ -1818,68 +1791,17 @@ static int quorem(Bigint* b, Bigint* S) #endif #endif } while (sx <= sxe); - bx = b->x; + bx = b.x; bxe = bx + n; if (!*bxe) { while (--bxe > bx && !*bxe) --n; - b->wds = n; + b.wds = n; } } return q; } -#if !ENABLE(JSC_MULTIPLE_THREADS) -static char* dtoa_result; -#endif - -static char* rv_alloc(int i) -{ - int k; - - int j = sizeof(uint32_t); - for (k = 0; - sizeof(Bigint) - sizeof(uint32_t) - sizeof(int) + j <= (unsigned)i; - j <<= 1) - k++; - int* r = (int*)Balloc(k); - *r = k; - return -#if !ENABLE(JSC_MULTIPLE_THREADS) - dtoa_result = -#endif - (char*)(r + 1); -} - -static char* nrv_alloc(const char* s, char** rve, int n) -{ - char* rv = rv_alloc(n); - char* t = rv; - - while ((*t = *s++)) - t++; - if (rve) - *rve = t; - return rv; -} - -/* freedtoa(s) must be used to free values s returned by dtoa - * when MULTIPLE_THREADS is #defined. It should be used in all cases, - * but for consistency with earlier versions of dtoa, it is optional - * when MULTIPLE_THREADS is not defined. - */ - -void freedtoa(char* s) -{ - Bigint* b = (Bigint*)((int*)s - 1); - b->maxwds = 1 << (b->k = *(int*)b); - Bfree(b); -#if !ENABLE(JSC_MULTIPLE_THREADS) - if (s == dtoa_result) - dtoa_result = 0; -#endif -} - /* dtoa for IEEE arithmetic (dmg): convert double to ASCII string. * * Inspired by "How to Print Floating-Point Numbers Accurately" by @@ -1914,7 +1836,7 @@ void freedtoa(char* s) * calculation. */ -char* dtoa(double d, int ndigits, int* decpt, int* sign, char** rve) +void dtoa(char* result, double dd, int ndigits, int* decpt, int* sign, char** rve) { /* Arguments ndigits, decpt, sign are similar to those @@ -1933,38 +1855,37 @@ char* dtoa(double d, int ndigits, int* decpt, int* sign, char** rve) int denorm; uint32_t x; #endif - Bigint *b, *b1, *delta, *mlo = NULL, *mhi, *S; - double d2, ds, eps; + BigInt b, b1, delta, mlo, mhi, S; + U d2, eps, u; + double ds; char *s, *s0; #ifdef SET_INEXACT int inexact, oldinexact; #endif -#if !ENABLE(JSC_MULTIPLE_THREADS) - if (dtoa_result) { - freedtoa(dtoa_result); - dtoa_result = 0; - } -#endif - - if (word0(d) & Sign_bit) { + u.d = dd; + if (word0(&u) & Sign_bit) { /* set sign for everything, including 0's and NaNs */ *sign = 1; - word0(d) &= ~Sign_bit; /* clear sign bit */ + word0(&u) &= ~Sign_bit; /* clear sign bit */ } else *sign = 0; - if ((word0(d) & Exp_mask) == Exp_mask) + if ((word0(&u) & Exp_mask) == Exp_mask) { /* Infinity or NaN */ *decpt = 9999; - if (!word1(d) && !(word0(d) & 0xfffff)) - return nrv_alloc("Infinity", rve, 8); - return nrv_alloc("NaN", rve, 3); + if (!word1(&u) && !(word0(&u) & 0xfffff)) + strcpy(result, "Infinity"); + else + strcpy(result, "NaN"); + return; } - if (!dval(d)) { + if (!dval(&u)) { *decpt = 1; - return nrv_alloc("0", rve, 1); + result[0] = '0'; + result[1] = '\0'; + return; } #ifdef SET_INEXACT @@ -1972,15 +1893,15 @@ char* dtoa(double d, int ndigits, int* decpt, int* sign, char** rve) inexact = 1; #endif - b = d2b(dval(d), &be, &bbits); + d2b(b, &u, &be, &bbits); #ifdef Sudden_Underflow - i = (int)(word0(d) >> Exp_shift1 & (Exp_mask >> Exp_shift1)); + i = (int)(word0(&u) >> Exp_shift1 & (Exp_mask >> Exp_shift1)); #else - if ((i = (int)(word0(d) >> Exp_shift1 & (Exp_mask >> Exp_shift1)))) { + if ((i = (int)(word0(&u) >> Exp_shift1 & (Exp_mask >> Exp_shift1)))) { #endif - dval(d2) = dval(d); - word0(d2) &= Frac_mask1; - word0(d2) |= Exp_11; + dval(&d2) = dval(&u); + word0(&d2) &= Frac_mask1; + word0(&d2) |= Exp_11; /* log(x) ~=~ log(1.5) + (x-1.5)/1.5 * log10(x) = log(x) / log(10) @@ -2011,21 +1932,21 @@ char* dtoa(double d, int ndigits, int* decpt, int* sign, char** rve) /* d is denormalized */ i = bbits + be + (Bias + (P - 1) - 1); - x = (i > 32) ? (word0(d) << (64 - i)) | (word1(d) >> (i - 32)) - : word1(d) << (32 - i); - dval(d2) = x; - word0(d2) -= 31 * Exp_msk1; /* adjust exponent */ + x = (i > 32) ? (word0(&u) << (64 - i)) | (word1(&u) >> (i - 32)) + : word1(&u) << (32 - i); + dval(&d2) = x; + word0(&d2) -= 31 * Exp_msk1; /* adjust exponent */ i -= (Bias + (P - 1) - 1) + 1; denorm = 1; } #endif - ds = (dval(d2) - 1.5) * 0.289529654602168 + 0.1760912590558 + (i * 0.301029995663981); + ds = (dval(&d2) - 1.5) * 0.289529654602168 + 0.1760912590558 + (i * 0.301029995663981); k = (int)ds; if (ds < 0. && ds != k) k--; /* want k = floor(ds) */ k_check = 1; if (k >= 0 && k <= Ten_pmax) { - if (dval(d) < tens[k]) + if (dval(&u) < tens[k]) k--; k_check = 0; } @@ -2059,14 +1980,14 @@ char* dtoa(double d, int ndigits, int* decpt, int* sign, char** rve) ilim = ilim1 = -1; i = 18; ndigits = 0; - s = s0 = rv_alloc(i); + s = s0 = result; if (ilim >= 0 && ilim <= Quick_max && try_quick) { /* Try to get by with floating-point arithmetic. */ i = 0; - dval(d2) = dval(d); + dval(&d2) = dval(&u); k0 = k; ilim0 = ilim; ieps = 2; /* conservative */ @@ -2076,7 +1997,7 @@ char* dtoa(double d, int ndigits, int* decpt, int* sign, char** rve) if (j & Bletch) { /* prevent overflows */ j &= Bletch - 1; - dval(d) /= bigtens[n_bigtens - 1]; + dval(&u) /= bigtens[n_bigtens - 1]; ieps++; } for (; j; j >>= 1, i++) { @@ -2085,32 +2006,32 @@ char* dtoa(double d, int ndigits, int* decpt, int* sign, char** rve) ds *= bigtens[i]; } } - dval(d) /= ds; + dval(&u) /= ds; } else if ((j1 = -k)) { - dval(d) *= tens[j1 & 0xf]; + dval(&u) *= tens[j1 & 0xf]; for (j = j1 >> 4; j; j >>= 1, i++) { if (j & 1) { ieps++; - dval(d) *= bigtens[i]; + dval(&u) *= bigtens[i]; } } } - if (k_check && dval(d) < 1. && ilim > 0) { + if (k_check && dval(&u) < 1. && ilim > 0) { if (ilim1 <= 0) goto fast_failed; ilim = ilim1; k--; - dval(d) *= 10.; + dval(&u) *= 10.; ieps++; } - dval(eps) = (ieps * dval(d)) + 7.; - word0(eps) -= (P - 1) * Exp_msk1; + dval(&eps) = (ieps * dval(&u)) + 7.; + word0(&eps) -= (P - 1) * Exp_msk1; if (ilim == 0) { - S = mhi = 0; - dval(d) -= 5.; - if (dval(d) > dval(eps)) + S = mhi = BigInt(); + dval(&u) -= 5.; + if (dval(&u) > dval(&eps)) goto one_digit; - if (dval(d) < -dval(eps)) + if (dval(&u) < -dval(&eps)) goto no_digits; goto fast_failed; } @@ -2119,36 +2040,36 @@ char* dtoa(double d, int ndigits, int* decpt, int* sign, char** rve) /* Use Steele & White method of only * generating digits needed. */ - dval(eps) = (0.5 / tens[ilim - 1]) - dval(eps); + dval(&eps) = (0.5 / tens[ilim - 1]) - dval(&eps); for (i = 0;;) { - L = (long int)dval(d); - dval(d) -= L; + L = (long int)dval(&u); + dval(&u) -= L; *s++ = '0' + (int)L; - if (dval(d) < dval(eps)) - goto ret1; - if (1. - dval(d) < dval(eps)) + if (dval(&u) < dval(&eps)) + goto ret; + if (1. - dval(&u) < dval(&eps)) goto bump_up; if (++i >= ilim) break; - dval(eps) *= 10.; - dval(d) *= 10.; + dval(&eps) *= 10.; + dval(&u) *= 10.; } } else { #endif /* Generate ilim digits, then fix them up. */ - dval(eps) *= tens[ilim - 1]; - for (i = 1;; i++, dval(d) *= 10.) { - L = (int32_t)(dval(d)); - if (!(dval(d) -= L)) + dval(&eps) *= tens[ilim - 1]; + for (i = 1;; i++, dval(&u) *= 10.) { + L = (int32_t)(dval(&u)); + if (!(dval(&u) -= L)) ilim = i; *s++ = '0' + (int)L; if (i == ilim) { - if (dval(d) > 0.5 + dval(eps)) + if (dval(&u) > 0.5 + dval(&eps)) goto bump_up; - else if (dval(d) < 0.5 - dval(eps)) { + else if (dval(&u) < 0.5 - dval(&eps)) { while (*--s == '0') { } s++; - goto ret1; + goto ret; } break; } @@ -2158,7 +2079,7 @@ char* dtoa(double d, int ndigits, int* decpt, int* sign, char** rve) #endif fast_failed: s = s0; - dval(d) = dval(d2); + dval(&u) = dval(&d2); k = k0; ilim = ilim0; } @@ -2169,31 +2090,31 @@ fast_failed: /* Yes. */ ds = tens[k]; if (ndigits < 0 && ilim <= 0) { - S = mhi = 0; - if (ilim < 0 || dval(d) <= 5 * ds) + S = mhi = BigInt(); + if (ilim < 0 || dval(&u) <= 5 * ds) goto no_digits; goto one_digit; } - for (i = 1;; i++, dval(d) *= 10.) { - L = (int32_t)(dval(d) / ds); - dval(d) -= L * ds; + for (i = 1;; i++, dval(&u) *= 10.) { + L = (int32_t)(dval(&u) / ds); + dval(&u) -= L * ds; #ifdef Check_FLT_ROUNDS /* If FLT_ROUNDS == 2, L will usually be high by 1 */ - if (dval(d) < 0) { + if (dval(&u) < 0) { L--; - dval(d) += ds; + dval(&u) += ds; } #endif *s++ = '0' + (int)L; - if (!dval(d)) { + if (!dval(&u)) { #ifdef SET_INEXACT inexact = 0; #endif break; } if (i == ilim) { - dval(d) += dval(d); - if (dval(d) > ds || (dval(d) == ds && (L & 1))) { + dval(&u) += dval(&u); + if (dval(&u) > ds || (dval(&u) == ds && (L & 1))) { bump_up: while (*--s == '9') if (s == s0) { @@ -2206,12 +2127,12 @@ bump_up: break; } } - goto ret1; + goto ret; } m2 = b2; m5 = b5; - mhi = mlo = 0; + mhi = mlo = BigInt(); if (leftright) { i = #ifndef Sudden_Underflow @@ -2220,7 +2141,7 @@ bump_up: 1 + P - bbits; b2 += i; s2 += i; - mhi = i2b(1); + i2b(mhi, 1); } if (m2 > 0 && s2 > 0) { i = m2 < s2 ? m2 : s2; @@ -2231,26 +2152,24 @@ bump_up: if (b5 > 0) { if (leftright) { if (m5 > 0) { - mhi = pow5mult(mhi, m5); - b1 = mult(mhi, b); - Bfree(b); - b = b1; + pow5mult(mhi, m5); + mult(b, mhi); } if ((j = b5 - m5)) - b = pow5mult(b, j); + pow5mult(b, j); } else - b = pow5mult(b, b5); + pow5mult(b, b5); } - S = i2b(1); + i2b(S, 1); if (s5 > 0) - S = pow5mult(S, s5); + pow5mult(S, s5); /* Check for special case that d is a normalized power of 2. */ spec_case = 0; - if (!word1(d) && !(word0(d) & Bndry_mask) + if (!word1(&u) && !(word0(&u) & Bndry_mask) #ifndef Sudden_Underflow - && word0(d) & (Exp_mask & ~Exp_msk1) + && word0(&u) & (Exp_mask & ~Exp_msk1) #endif ) { /* The special case */ @@ -2267,10 +2186,10 @@ bump_up: * can do shifts and ors to compute the numerator for q. */ #ifdef Pack_32 - if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds - 1]) : 1) + s2) & 0x1f)) + if ((i = ((s5 ? 32 - hi0bits(S.x[S.wds - 1]) : 1) + s2) & 0x1f)) i = 32 - i; #else - if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds - 1]) : 1) + s2) & 0xf)) + if ((i = ((s5 ? 32 - hi0bits(S.x[S.wds - 1]) : 1) + s2) & 0xf)) i = 16 - i; #endif if (i > 4) { @@ -2285,22 +2204,22 @@ bump_up: s2 += i; } if (b2 > 0) - b = lshift(b, b2); + lshift(b, b2); if (s2 > 0) - S = lshift(S, s2); + lshift(S, s2); if (k_check) { if (cmp(b,S) < 0) { k--; - b = multadd(b, 10, 0); /* we botched the k estimate */ + multadd(b, 10, 0); /* we botched the k estimate */ if (leftright) - mhi = multadd(mhi, 10, 0); + multadd(mhi, 10, 0); ilim = ilim1; } } if (leftright) { if (m2 > 0) - mhi = lshift(mhi, m2); + lshift(mhi, m2); /* Compute mlo -- check for special case * that d is a normalized power of 2. @@ -2308,9 +2227,8 @@ bump_up: mlo = mhi; if (spec_case) { - mhi = Balloc(mhi->k); - Bcopy(mhi, mlo); - mhi = lshift(mhi, Log2P); + mhi = mlo; + lshift(mhi, Log2P); } for (i = 1;;i++) { @@ -2319,10 +2237,9 @@ bump_up: * that will round to d? */ j = cmp(b, mlo); - delta = diff(S, mhi); - j1 = delta->sign ? 1 : cmp(b, delta); - Bfree(delta); - if (j1 == 0 && !(word1(d) & 1)) { + diff(delta, S, mhi); + j1 = delta.sign ? 1 : cmp(b, delta); + if (j1 == 0 && !(word1(&u) & 1)) { if (dig == '9') goto round_9_up; if (j > 0) @@ -2334,15 +2251,15 @@ bump_up: *s++ = dig; goto ret; } - if (j < 0 || (j == 0 && !(word1(d) & 1))) { - if (!b->x[0] && b->wds <= 1) { + if (j < 0 || (j == 0 && !(word1(&u) & 1))) { + if (!b.x[0] && b.wds <= 1) { #ifdef SET_INEXACT inexact = 0; #endif goto accept_dig; } if (j1 > 0) { - b = lshift(b, 1); + lshift(b, 1); j1 = cmp(b, S); if ((j1 > 0 || (j1 == 0 && (dig & 1))) && dig++ == '9') goto round_9_up; @@ -2363,18 +2280,14 @@ round_9_up: *s++ = dig; if (i == ilim) break; - b = multadd(b, 10, 0); - if (mlo == mhi) - mlo = mhi = multadd(mhi, 10, 0); - else { - mlo = multadd(mlo, 10, 0); - mhi = multadd(mhi, 10, 0); - } + multadd(b, 10, 0); + multadd(mlo, 10, 0); + multadd(mhi, 10, 0); } } else for (i = 1;; i++) { *s++ = dig = quorem(b,S) + '0'; - if (!b->x[0] && b->wds <= 1) { + if (!b.x[0] && b.wds <= 1) { #ifdef SET_INEXACT inexact = 0; #endif @@ -2382,12 +2295,12 @@ round_9_up: } if (i >= ilim) break; - b = multadd(b, 10, 0); + multadd(b, 10, 0); } /* Round off last digit */ - b = lshift(b, 1); + lshift(b, 1); j = cmp(b, S); if (j > 0 || (j == 0 && (dig & 1))) { roundoff: @@ -2411,29 +2324,20 @@ one_digit: k++; goto ret; ret: - Bfree(S); - if (mhi) { - if (mlo && mlo != mhi) - Bfree(mlo); - Bfree(mhi); - } -ret1: #ifdef SET_INEXACT if (inexact) { if (!oldinexact) { - word0(d) = Exp_1 + (70 << Exp_shift); - word1(d) = 0; - dval(d) += 1.; + word0(&u) = Exp_1 + (70 << Exp_shift); + word1(&u) = 0; + dval(&u) += 1.; } } else if (!oldinexact) clear_inexact(); #endif - Bfree(b); *s = 0; *decpt = k + 1; if (rve) *rve = s; - return s0; } } // namespace WTF diff --git a/JavaScriptCore/wtf/dtoa.h b/JavaScriptCore/wtf/dtoa.h index ed858c0..cbec7c7 100644 --- a/JavaScriptCore/wtf/dtoa.h +++ b/JavaScriptCore/wtf/dtoa.h @@ -30,8 +30,7 @@ namespace WTF { extern WTF::Mutex* s_dtoaP5Mutex; double strtod(const char* s00, char** se); - char* dtoa(double d, int ndigits, int* decpt, int* sign, char** rve); - void freedtoa(char* s); + void dtoa(char* result, double d, int ndigits, int* decpt, int* sign, char** rve); } // namespace WTF diff --git a/JavaScriptCore/wtf/ThreadingGtk.cpp b/JavaScriptCore/wtf/gtk/ThreadingGtk.cpp index b4f4de1..b4f4de1 100644 --- a/JavaScriptCore/wtf/ThreadingGtk.cpp +++ b/JavaScriptCore/wtf/gtk/ThreadingGtk.cpp diff --git a/JavaScriptCore/wtf/ThreadingQt.cpp b/JavaScriptCore/wtf/qt/ThreadingQt.cpp index 1fdd2bb..1fdd2bb 100644 --- a/JavaScriptCore/wtf/ThreadingQt.cpp +++ b/JavaScriptCore/wtf/qt/ThreadingQt.cpp diff --git a/JavaScriptCore/wtf/unicode/Unicode.h b/JavaScriptCore/wtf/unicode/Unicode.h index e6e8f23..f86a9b7 100644 --- a/JavaScriptCore/wtf/unicode/Unicode.h +++ b/JavaScriptCore/wtf/unicode/Unicode.h @@ -28,6 +28,8 @@ #include "qt4/UnicodeQt4.h" #elif USE(ICU_UNICODE) #include <wtf/unicode/icu/UnicodeIcu.h> +#elif USE(GLIB_UNICODE) +#include <wtf/unicode/glib/UnicodeGLib.h> #else #error "Unknown Unicode implementation" #endif diff --git a/JavaScriptCore/wtf/unicode/glib/UnicodeGLib.cpp b/JavaScriptCore/wtf/unicode/glib/UnicodeGLib.cpp new file mode 100644 index 0000000..a779b36 --- /dev/null +++ b/JavaScriptCore/wtf/unicode/glib/UnicodeGLib.cpp @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2008 Jürg Billeter <j@bitron.ch> + * Copyright (C) 2008 Dominik Röttsches <dominik.roettsches@access-company.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "UnicodeGLib.h" + +namespace WTF { +namespace Unicode { + +UChar32 foldCase(UChar32 ch) +{ + GOwnPtr<GError> gerror; + + GOwnPtr<char> utf8char; + utf8char.set(g_ucs4_to_utf8(reinterpret_cast<gunichar*>(&ch), 1, 0, 0, &gerror.outPtr())); + if (gerror) + return ch; + + GOwnPtr<char> utf8caseFolded; + utf8caseFolded.set(g_utf8_casefold(utf8char.get(), -1)); + + GOwnPtr<gunichar> ucs4Result; + ucs4Result.set(g_utf8_to_ucs4_fast(utf8caseFolded.get(), -1, 0)); + + return *ucs4Result; +} + +int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error) +{ + *error = false; + GOwnPtr<GError> gerror; + + GOwnPtr<char> utf8src; + utf8src.set(g_utf16_to_utf8(src, srcLength, 0, 0, &gerror.outPtr())); + if (gerror) { + *error = true; + return -1; + } + + GOwnPtr<char> utf8result; + utf8result.set(g_utf8_casefold(utf8src.get(), -1)); + + long utf16resultLength = -1; + GOwnPtr<UChar> utf16result; + utf16result.set(g_utf8_to_utf16(utf8result.get(), -1, 0, &utf16resultLength, &gerror.outPtr())); + if (gerror) { + *error = true; + return -1; + } + + if (utf16resultLength > resultLength) { + *error = true; + return utf16resultLength; + } + memcpy(result, utf16result.get(), utf16resultLength * sizeof(UChar)); + + return utf16resultLength; +} + +int toLower(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error) +{ + *error = false; + GOwnPtr<GError> gerror; + + GOwnPtr<char> utf8src; + utf8src.set(g_utf16_to_utf8(src, srcLength, 0, 0, &gerror.outPtr())); + if (gerror) { + *error = true; + return -1; + } + + GOwnPtr<char> utf8result; + utf8result.set(g_utf8_strdown(utf8src.get(), -1)); + + long utf16resultLength = -1; + GOwnPtr<UChar> utf16result; + utf16result.set(g_utf8_to_utf16(utf8result.get(), -1, 0, &utf16resultLength, &gerror.outPtr())); + if (gerror) { + *error = true; + return -1; + } + + if (utf16resultLength > resultLength) { + *error = true; + return utf16resultLength; + } + memcpy(result, utf16result.get(), utf16resultLength * sizeof(UChar)); + + return utf16resultLength; +} + +int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error) +{ + *error = false; + GOwnPtr<GError> gerror; + + GOwnPtr<char> utf8src; + utf8src.set(g_utf16_to_utf8(src, srcLength, 0, 0, &gerror.outPtr())); + if (gerror) { + *error = true; + return -1; + } + + GOwnPtr<char> utf8result; + utf8result.set(g_utf8_strup(utf8src.get(), -1)); + + long utf16resultLength = -1; + GOwnPtr<UChar> utf16result; + utf16result.set(g_utf8_to_utf16(utf8result.get(), -1, 0, &utf16resultLength, &gerror.outPtr())); + if (gerror) { + *error = true; + return -1; + } + + if (utf16resultLength > resultLength) { + *error = true; + return utf16resultLength; + } + memcpy(result, utf16result.get(), utf16resultLength * sizeof(UChar)); + + return utf16resultLength; +} + +Direction direction(UChar32 c) +{ + PangoBidiType type = pango_bidi_type_for_unichar(c); + switch (type) { + case PANGO_BIDI_TYPE_L: + return LeftToRight; + case PANGO_BIDI_TYPE_R: + return RightToLeft; + case PANGO_BIDI_TYPE_AL: + return RightToLeftArabic; + case PANGO_BIDI_TYPE_LRE: + return LeftToRightEmbedding; + case PANGO_BIDI_TYPE_RLE: + return RightToLeftEmbedding; + case PANGO_BIDI_TYPE_LRO: + return LeftToRightOverride; + case PANGO_BIDI_TYPE_RLO: + return RightToLeftOverride; + case PANGO_BIDI_TYPE_PDF: + return PopDirectionalFormat; + case PANGO_BIDI_TYPE_EN: + return EuropeanNumber; + case PANGO_BIDI_TYPE_AN: + return ArabicNumber; + case PANGO_BIDI_TYPE_ES: + return EuropeanNumberSeparator; + case PANGO_BIDI_TYPE_ET: + return EuropeanNumberTerminator; + case PANGO_BIDI_TYPE_CS: + return CommonNumberSeparator; + case PANGO_BIDI_TYPE_NSM: + return NonSpacingMark; + case PANGO_BIDI_TYPE_BN: + return BoundaryNeutral; + case PANGO_BIDI_TYPE_B: + return BlockSeparator; + case PANGO_BIDI_TYPE_S: + return SegmentSeparator; + case PANGO_BIDI_TYPE_WS: + return WhiteSpaceNeutral; + default: + return OtherNeutral; + } +} + +int umemcasecmp(const UChar* a, const UChar* b, int len) +{ + GOwnPtr<char> utf8a; + GOwnPtr<char> utf8b; + + utf8a.set(g_utf16_to_utf8(a, len, 0, 0, 0)); + utf8b.set(g_utf16_to_utf8(b, len, 0, 0, 0)); + + GOwnPtr<char> foldedA; + GOwnPtr<char> foldedB; + + foldedA.set(g_utf8_casefold(utf8a.get(), -1)); + foldedB.set(g_utf8_casefold(utf8b.get(), -1)); + + // FIXME: umemcasecmp needs to mimic u_memcasecmp of icu + // from the ICU docs: + // "Compare two strings case-insensitively using full case folding. + // his is equivalent to u_strcmp(u_strFoldCase(s1, n, options), u_strFoldCase(s2, n, options))." + // + // So it looks like we don't need the full g_utf8_collate here, + // but really a bitwise comparison of casefolded unicode chars (not utf-8 bytes). + // As there is no direct equivalent to this icu function in GLib, for now + // we'll use g_utf8_collate(): + + return g_utf8_collate(foldedA.get(), foldedB.get()); +} + +} +} diff --git a/JavaScriptCore/wtf/unicode/glib/UnicodeGLib.h b/JavaScriptCore/wtf/unicode/glib/UnicodeGLib.h new file mode 100644 index 0000000..c03d3ec --- /dev/null +++ b/JavaScriptCore/wtf/unicode/glib/UnicodeGLib.h @@ -0,0 +1,238 @@ +/* + * Copyright (C) 2006 George Staikos <staikos@kde.org> + * Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com> + * Copyright (C) 2007 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2008 Jürg Billeter <j@bitron.ch> + * Copyright (C) 2008 Dominik Röttsches <dominik.roettsches@access-company.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef UnicodeGLib_h +#define UnicodeGLib_h + +#include "UnicodeMacrosFromICU.h" +#include <wtf/GOwnPtr.h> + +#include <glib.h> +#include <pango/pango.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +typedef uint16_t UChar; +typedef int32_t UChar32; + +namespace WTF { +namespace Unicode { + +enum Direction { + LeftToRight, + RightToLeft, + EuropeanNumber, + EuropeanNumberSeparator, + EuropeanNumberTerminator, + ArabicNumber, + CommonNumberSeparator, + BlockSeparator, + SegmentSeparator, + WhiteSpaceNeutral, + OtherNeutral, + LeftToRightEmbedding, + LeftToRightOverride, + RightToLeftArabic, + RightToLeftEmbedding, + RightToLeftOverride, + PopDirectionalFormat, + NonSpacingMark, + BoundaryNeutral +}; + +enum DecompositionType { + DecompositionNone, + DecompositionCanonical, + DecompositionCompat, + DecompositionCircle, + DecompositionFinal, + DecompositionFont, + DecompositionFraction, + DecompositionInitial, + DecompositionIsolated, + DecompositionMedial, + DecompositionNarrow, + DecompositionNoBreak, + DecompositionSmall, + DecompositionSquare, + DecompositionSub, + DecompositionSuper, + DecompositionVertical, + DecompositionWide, +}; + +enum CharCategory { + NoCategory = 0, + Other_NotAssigned = U_MASK(G_UNICODE_UNASSIGNED), + Letter_Uppercase = U_MASK(G_UNICODE_UPPERCASE_LETTER), + Letter_Lowercase = U_MASK(G_UNICODE_LOWERCASE_LETTER), + Letter_Titlecase = U_MASK(G_UNICODE_TITLECASE_LETTER), + Letter_Modifier = U_MASK(G_UNICODE_MODIFIER_LETTER), + Letter_Other = U_MASK(G_UNICODE_OTHER_LETTER), + + Mark_NonSpacing = U_MASK(G_UNICODE_NON_SPACING_MARK), + Mark_Enclosing = U_MASK(G_UNICODE_ENCLOSING_MARK), + Mark_SpacingCombining = U_MASK(G_UNICODE_COMBINING_MARK), + + Number_DecimalDigit = U_MASK(G_UNICODE_DECIMAL_NUMBER), + Number_Letter = U_MASK(G_UNICODE_LETTER_NUMBER), + Number_Other = U_MASK(G_UNICODE_OTHER_NUMBER), + + Separator_Space = U_MASK(G_UNICODE_SPACE_SEPARATOR), + Separator_Line = U_MASK(G_UNICODE_LINE_SEPARATOR), + Separator_Paragraph = U_MASK(G_UNICODE_PARAGRAPH_SEPARATOR), + + Other_Control = U_MASK(G_UNICODE_CONTROL), + Other_Format = U_MASK(G_UNICODE_FORMAT), + Other_PrivateUse = U_MASK(G_UNICODE_PRIVATE_USE), + Other_Surrogate = U_MASK(G_UNICODE_SURROGATE), + + Punctuation_Dash = U_MASK(G_UNICODE_DASH_PUNCTUATION), + Punctuation_Open = U_MASK(G_UNICODE_OPEN_PUNCTUATION), + Punctuation_Close = U_MASK(G_UNICODE_CLOSE_PUNCTUATION), + Punctuation_Connector = U_MASK(G_UNICODE_CONNECT_PUNCTUATION), + Punctuation_Other = U_MASK(G_UNICODE_OTHER_PUNCTUATION), + + Symbol_Math = U_MASK(G_UNICODE_MATH_SYMBOL), + Symbol_Currency = U_MASK(G_UNICODE_CURRENCY_SYMBOL), + Symbol_Modifier = U_MASK(G_UNICODE_MODIFIER_SYMBOL), + Symbol_Other = U_MASK(G_UNICODE_OTHER_SYMBOL), + + Punctuation_InitialQuote = U_MASK(G_UNICODE_INITIAL_PUNCTUATION), + Punctuation_FinalQuote = U_MASK(G_UNICODE_FINAL_PUNCTUATION) +}; + +UChar32 foldCase(UChar32); + +int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error); + +int toLower(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error); + +inline UChar32 toLower(UChar32 c) +{ + return g_unichar_tolower(c); +} + +inline UChar32 toUpper(UChar32 c) +{ + return g_unichar_toupper(c); +} + +int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error); + +inline UChar32 toTitleCase(UChar32 c) +{ + return g_unichar_totitle(c); +} + +inline bool isArabicChar(UChar32 c) +{ + return c >= 0x0600 && c <= 0x06FF; +} + +inline bool isFormatChar(UChar32 c) +{ + return g_unichar_type(c) == G_UNICODE_FORMAT; +} + +inline bool isSeparatorSpace(UChar32 c) +{ + return g_unichar_type(c) == G_UNICODE_SPACE_SEPARATOR; +} + +inline bool isPrintableChar(UChar32 c) +{ + return g_unichar_isprint(c); +} + +inline bool isDigit(UChar32 c) +{ + return g_unichar_isdigit(c); +} + +inline bool isPunct(UChar32 c) +{ + return g_unichar_ispunct(c); +} + +inline bool hasLineBreakingPropertyComplexContext(UChar32 c) +{ + // FIXME + return false; +} + +inline bool hasLineBreakingPropertyComplexContextOrIdeographic(UChar32 c) +{ + // FIXME + return false; +} + +inline UChar32 mirroredChar(UChar32 c) +{ + gunichar mirror = 0; + g_unichar_get_mirror_char(c, &mirror); + return mirror; +} + +inline CharCategory category(UChar32 c) +{ + if (c > 0xffff) + return NoCategory; + + return (CharCategory) U_MASK(g_unichar_type(c)); +} + +Direction direction(UChar32); + +inline bool isLower(UChar32 c) +{ + return g_unichar_islower(c); +} + +inline int digitValue(UChar32 c) +{ + return g_unichar_digit_value(c); +} + +inline uint8_t combiningClass(UChar32 c) +{ + // FIXME + // return g_unichar_combining_class(c); + return 0; +} + +inline DecompositionType decompositionType(UChar32 c) +{ + // FIXME + return DecompositionNone; +} + +int umemcasecmp(const UChar*, const UChar*, int len); + +} +} + +#endif + diff --git a/JavaScriptCore/wtf/unicode/glib/UnicodeMacrosFromICU.h b/JavaScriptCore/wtf/unicode/glib/UnicodeMacrosFromICU.h new file mode 100644 index 0000000..5d3eca6 --- /dev/null +++ b/JavaScriptCore/wtf/unicode/glib/UnicodeMacrosFromICU.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2006 George Staikos <staikos@kde.org> + * Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com> + * Copyright (C) 2007 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2008 Jürg Billeter <j@bitron.ch> + * Copyright (C) 2008 Dominik Röttsches <dominik.roettsches@access-company.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef UnicodeMacrosFromICU_h +#define UnicodeMacrosFromICU_h + +// some defines from ICU + +#define U16_IS_LEAD(c) (((c)&0xfffffc00)==0xd800) +#define U16_IS_TRAIL(c) (((c)&0xfffffc00)==0xdc00) +#define U16_SURROGATE_OFFSET ((0xd800<<10UL)+0xdc00-0x10000) +#define U16_GET_SUPPLEMENTARY(lead, trail) \ + (((UChar32)(lead)<<10UL)+(UChar32)(trail)-U16_SURROGATE_OFFSET) + +#define U16_LEAD(supplementary) (UChar)(((supplementary)>>10)+0xd7c0) +#define U16_TRAIL(supplementary) (UChar)(((supplementary)&0x3ff)|0xdc00) + +#define U_IS_SURROGATE(c) (((c)&0xfffff800)==0xd800) +#define U16_IS_SINGLE(c) !U_IS_SURROGATE(c) +#define U16_IS_SURROGATE(c) U_IS_SURROGATE(c) +#define U16_IS_SURROGATE_LEAD(c) (((c)&0x400)==0) + +#define U16_PREV(s, start, i, c) { \ + (c)=(s)[--(i)]; \ + if(U16_IS_TRAIL(c)) { \ + uint16_t __c2; \ + if((i)>(start) && U16_IS_LEAD(__c2=(s)[(i)-1])) { \ + --(i); \ + (c)=U16_GET_SUPPLEMENTARY(__c2, (c)); \ + } \ + } \ +} + +#define U16_NEXT(s, i, length, c) { \ + (c)=(s)[(i)++]; \ + if(U16_IS_LEAD(c)) { \ + uint16_t __c2; \ + if((i)<(length) && U16_IS_TRAIL(__c2=(s)[(i)])) { \ + ++(i); \ + (c)=U16_GET_SUPPLEMENTARY((c), __c2); \ + } \ + } \ +} + +#define U_MASK(x) ((uint32_t)1<<(x)) + +#endif + diff --git a/JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h b/JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h index de5e082..35c6fbf 100644 --- a/JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h +++ b/JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h @@ -184,6 +184,12 @@ inline bool hasLineBreakingPropertyComplexContext(UChar32 c) return u_getIntPropertyValue(c, UCHAR_LINE_BREAK) == U_LB_COMPLEX_CONTEXT; } +inline bool hasLineBreakingPropertyComplexContextOrIdeographic(UChar32 c) +{ + int32_t prop = u_getIntPropertyValue(c, UCHAR_LINE_BREAK); + return prop == U_LB_COMPLEX_CONTEXT || prop == U_LB_IDEOGRAPHIC; +} + inline UChar32 mirroredChar(UChar32 c) { return u_charMirror(c); diff --git a/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h b/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h index f65e292..1531694 100644 --- a/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h +++ b/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h @@ -92,6 +92,17 @@ typedef uint32_t UChar32; } \ } +#define U16_PREV(s, start, i, c) { \ + (c)=(s)[--(i)]; \ + if(U16_IS_TRAIL(c)) { \ + uint16_t __c2; \ + if((i)>(start) && U16_IS_LEAD(__c2=(s)[(i)-1])) { \ + --(i); \ + (c)=U16_GET_SUPPLEMENTARY(__c2, (c)); \ + } \ + } \ +} + #define U_MASK(x) ((uint32_t)1<<(x)) namespace WTF { |