author | Kyle Huey <khuey@kylehuey.com> |
Thu, 18 Aug 2011 16:03:20 -0400 | |
changeset 75478 | b6b6c8e74766b7616d9f603a63528b7501b04f2c |
parent 75475 | 932c8414512f32c41e0d3eb9c9e483658ed7ab27 (current diff) |
parent 75477 | ab68ef485d775c88114cc1b4cccc33fd66798efb (diff) |
child 75479 | 2578bdcf32ee0727411fd5547600e0686e1d76f6 |
push id | 21028 |
push user | khuey@mozilla.com |
push date | Thu, 18 Aug 2011 20:03:24 +0000 |
treeherder | mozilla-central@b6b6c8e74766 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
milestone | 9.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/content/base/src/nsGkAtomList.h +++ b/content/base/src/nsGkAtomList.h @@ -65,16 +65,17 @@ GK_ATOM(_empty, "") GK_ATOM(moz, "_moz") GK_ATOM(moztype, "_moz-type") GK_ATOM(mozdirty, "_moz_dirty") GK_ATOM(mozdonotsend, "moz-do-not-send") GK_ATOM(mozeditorbogusnode, "_moz_editor_bogus_node") GK_ATOM(mozgeneratedcontentbefore, "_moz_generated_content_before") GK_ATOM(mozgeneratedcontentafter, "_moz_generated_content_after") GK_ATOM(mozgeneratedcontentimage, "_moz_generated_content_image") +GK_ATOM(_moz_original_size, "_moz_original_size") GK_ATOM(_moz_target, "_moz_target") GK_ATOM(_moz_type, "_moz-type") GK_ATOM(menuactive, "_moz-menuactive") GK_ATOM(_poundDefault, "#default") GK_ATOM(_asterix, "*") GK_ATOM(a, "a") GK_ATOM(abbr, "abbr") GK_ATOM(abort, "abort")
--- a/layout/xul/base/src/nsResizerFrame.cpp +++ b/layout/xul/base/src/nsResizerFrame.cpp @@ -56,16 +56,17 @@ #include "nsIBaseWindow.h" #include "nsPIDOMWindow.h" #include "nsGUIEvent.h" #include "nsEventDispatcher.h" #include "nsContentUtils.h" #include "nsMenuPopupFrame.h" #include "nsIScreenManager.h" #include "mozilla/dom/Element.h" +#include "nsContentErrors.h" // // NS_NewResizerFrame // // Creates a new Resizer frame and returns it // nsIFrame* @@ -248,69 +249,41 @@ nsResizerFrame::HandleEvent(nsPresContex // the resizer invisible. nsRect appUnitsRect = rect.ToAppUnits(aPresContext->AppUnitsPerDevPixel()); if (appUnitsRect.width < mRect.width && mouseMove.x) appUnitsRect.width = mRect.width; if (appUnitsRect.height < mRect.height && mouseMove.y) appUnitsRect.height = mRect.height; nsIntRect cssRect = appUnitsRect.ToInsidePixels(nsPresContext::AppUnitsPerCSSPixel()); - nsAutoString widthstr, heightstr; - widthstr.AppendInt(cssRect.width); - heightstr.AppendInt(cssRect.height); - - // for XUL elements, just set the width and height attributes. For - // other elements, set style.width and style.height - if (contentToResize->IsXUL()) { - nsIntRect oldRect; - nsWeakFrame weakFrame(menuPopupFrame); - if (menuPopupFrame) { - nsCOMPtr<nsIWidget> widget; - menuPopupFrame->GetWidget(getter_AddRefs(widget)); - if (widget) - widget->GetScreenBounds(oldRect); - - // convert the new rectangle into outer window coordinates - nsIntPoint clientOffset = widget->GetClientOffset(); - rect.x -= clientOffset.x; - rect.y -= clientOffset.y; - } + nsIntRect oldRect; + nsWeakFrame weakFrame(menuPopupFrame); + if (menuPopupFrame) { + nsCOMPtr<nsIWidget> widget; + menuPopupFrame->GetWidget(getter_AddRefs(widget)); + if (widget) + widget->GetScreenBounds(oldRect); - // only set the property if the element could have changed in that direction - if (direction.mHorizontal) { - contentToResize->SetAttr(kNameSpaceID_None, nsGkAtoms::width, widthstr, PR_TRUE); - } - if (direction.mVertical) { - contentToResize->SetAttr(kNameSpaceID_None, nsGkAtoms::height, heightstr, PR_TRUE); - } - - if (weakFrame.IsAlive() && - (oldRect.x != rect.x || oldRect.y != rect.y) && - (!menuPopupFrame->IsAnchored() || - menuPopupFrame->PopupLevel() != ePopupLevelParent)) { - menuPopupFrame->MoveTo(rect.x, rect.y, PR_TRUE); - } + // convert the new rectangle into outer window coordinates + nsIntPoint clientOffset = widget->GetClientOffset(); + rect.x -= clientOffset.x; + rect.y -= clientOffset.y; } - else { - nsCOMPtr<nsIDOMElementCSSInlineStyle> inlineStyleContent = - do_QueryInterface(contentToResize); - if (inlineStyleContent) { - nsCOMPtr<nsIDOMCSSStyleDeclaration> decl; - inlineStyleContent->GetStyle(getter_AddRefs(decl)); - // only set the property if the element could have changed in that direction - if (direction.mHorizontal) { - widthstr.AppendLiteral("px"); - decl->SetProperty(NS_LITERAL_STRING("width"), widthstr, EmptyString()); - } - if (direction.mVertical) { - heightstr.AppendLiteral("px"); - decl->SetProperty(NS_LITERAL_STRING("height"), heightstr, EmptyString()); - } - } + SizeInfo sizeInfo, originalSizeInfo; + sizeInfo.width.AppendInt(cssRect.width); + sizeInfo.height.AppendInt(cssRect.height); + ResizeContent(contentToResize, direction, sizeInfo, &originalSizeInfo); + MaybePersistOriginalSize(contentToResize, originalSizeInfo); + + if (weakFrame.IsAlive() && + (oldRect.x != rect.x || oldRect.y != rect.y) && + (!menuPopupFrame->IsAnchored() || + menuPopupFrame->PopupLevel() != ePopupLevelParent)) { + menuPopupFrame->MoveTo(rect.x, rect.y, PR_TRUE); } } else { window->SetPositionAndSize(rect.x, rect.y, rect.width, rect.height, PR_TRUE); // do the repaint. } doDefault = PR_FALSE; } @@ -318,16 +291,35 @@ nsResizerFrame::HandleEvent(nsPresContex break; case NS_MOUSE_CLICK: if (NS_IS_MOUSE_LEFT_CLICK(aEvent)) { MouseClicked(aPresContext, aEvent); } break; + + case NS_MOUSE_DOUBLECLICK: + if (aEvent->eventStructType == NS_MOUSE_EVENT && + static_cast<nsMouseEvent*>(aEvent)->button == nsMouseEvent::eLeftButton) + { + nsCOMPtr<nsIBaseWindow> window; + nsIPresShell* presShell = aPresContext->GetPresShell(); + nsIContent* contentToResize = + GetContentToResize(presShell, getter_AddRefs(window)); + if (contentToResize) { + nsIFrame* frameToResize = contentToResize->GetPrimaryFrame(); + if (frameToResize && frameToResize->GetType() == nsGkAtoms::menuPopupFrame) + break; // Don't restore original sizing for menupopup frames until + // we handle screen constraints here. (Bug 357725) + + RestoreOriginalSize(contentToResize); + } + } + break; } if (!doDefault) *aEventStatus = nsEventStatus_eConsumeNoDefault; if (doDefault && weakFrame.IsAlive()) return nsTitleBarFrame::HandleEvent(aPresContext, aEvent, aEventStatus); @@ -413,16 +405,112 @@ nsResizerFrame::AdjustDimensions(PRInt32 case 1: *aSize+= aResizerDirection*aMovement; // use one as a minimum size or the element could disappear if (*aSize < 1) *aSize = 1; } } +/* static */ void +nsResizerFrame::ResizeContent(nsIContent* aContent, const Direction& aDirection, + const SizeInfo& aSizeInfo, SizeInfo* aOriginalSizeInfo) +{ + // for XUL elements, just set the width and height attributes. For + // other elements, set style.width and style.height + if (aContent->IsXUL()) { + if (aOriginalSizeInfo) { + aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::width, + aOriginalSizeInfo->width); + aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::height, + aOriginalSizeInfo->height); + } + // only set the property if the element could have changed in that direction + if (aDirection.mHorizontal) { + aContent->SetAttr(kNameSpaceID_None, nsGkAtoms::width, aSizeInfo.width, PR_TRUE); + } + if (aDirection.mVertical) { + aContent->SetAttr(kNameSpaceID_None, nsGkAtoms::height, aSizeInfo.height, PR_TRUE); + } + } + else { + nsCOMPtr<nsIDOMElementCSSInlineStyle> inlineStyleContent = + do_QueryInterface(aContent); + if (inlineStyleContent) { + nsCOMPtr<nsIDOMCSSStyleDeclaration> decl; + inlineStyleContent->GetStyle(getter_AddRefs(decl)); + + if (aOriginalSizeInfo) { + decl->GetPropertyValue(NS_LITERAL_STRING("width"), + aOriginalSizeInfo->width); + decl->GetPropertyValue(NS_LITERAL_STRING("height"), + aOriginalSizeInfo->height); + } + + // only set the property if the element could have changed in that direction + if (aDirection.mHorizontal) { + nsAutoString widthstr(aSizeInfo.width); + if (!widthstr.IsEmpty() && + !Substring(widthstr, widthstr.Length() - 2, 2).EqualsLiteral("px")) + widthstr.AppendLiteral("px"); + decl->SetProperty(NS_LITERAL_STRING("width"), widthstr, EmptyString()); + } + if (aDirection.mVertical) { + nsAutoString heightstr(aSizeInfo.height); + if (!heightstr.IsEmpty() && + !Substring(heightstr, heightstr.Length() - 2, 2).EqualsLiteral("px")) + heightstr.AppendLiteral("px"); + decl->SetProperty(NS_LITERAL_STRING("height"), heightstr, EmptyString()); + } + } + } +} + +/* static */ void +nsResizerFrame::SizeInfoDtorFunc(void *aObject, nsIAtom *aPropertyName, + void *aPropertyValue, void *aData) +{ + nsResizerFrame::SizeInfo *propertyValue = + static_cast<nsResizerFrame::SizeInfo*>(aPropertyValue); + delete propertyValue; +} + +/* static */ void +nsResizerFrame::MaybePersistOriginalSize(nsIContent* aContent, + const SizeInfo& aSizeInfo) +{ + nsresult rv; + + aContent->GetProperty(nsGkAtoms::_moz_original_size, &rv); + if (rv != NS_PROPTABLE_PROP_NOT_THERE) + return; + + nsAutoPtr<SizeInfo> sizeInfo(new SizeInfo(aSizeInfo)); + rv = aContent->SetProperty(nsGkAtoms::_moz_original_size, sizeInfo.get(), + &SizeInfoDtorFunc); + if (NS_SUCCEEDED(rv)) + sizeInfo.forget(); +} + +/* static */ void +nsResizerFrame::RestoreOriginalSize(nsIContent* aContent) +{ + nsresult rv; + SizeInfo* sizeInfo = + static_cast<SizeInfo*>(aContent->GetProperty(nsGkAtoms::_moz_original_size, + &rv)); + if (NS_FAILED(rv)) + return; + + NS_ASSERTION(sizeInfo, "We set a null sizeInfo!?"); + Direction direction = {1, 1}; + ResizeContent(aContent, direction, *sizeInfo, nsnull); + aContent->DeleteProperty(nsGkAtoms::_moz_original_size); +} + /* returns a Direction struct containing the horizontal and vertical direction */ nsResizerFrame::Direction nsResizerFrame::GetDirection() { static const nsIContent::AttrValuesArray strings[] = {&nsGkAtoms::topleft, &nsGkAtoms::top, &nsGkAtoms::topright, &nsGkAtoms::left, &nsGkAtoms::right,
--- a/layout/xul/base/src/nsResizerFrame.h +++ b/layout/xul/base/src/nsResizerFrame.h @@ -66,14 +66,23 @@ public: protected: nsIContent* GetContentToResize(nsIPresShell* aPresShell, nsIBaseWindow** aWindow); Direction GetDirection(); static void AdjustDimensions(PRInt32* aPos, PRInt32* aSize, PRInt32 aMovement, PRInt8 aResizerDirection); + struct SizeInfo { + nsString width, height; + }; + static void SizeInfoDtorFunc(void *aObject, nsIAtom *aPropertyName, + void *aPropertyValue, void *aData); + static void ResizeContent(nsIContent* aContent, const Direction& aDirection, + const SizeInfo& aSizeInfo, SizeInfo* aOriginalSizeInfo); + static void MaybePersistOriginalSize(nsIContent* aContent, const SizeInfo& aSizeInfo); + static void RestoreOriginalSize(nsIContent* aContent); protected: nsIntRect mMouseDownRect; nsIntPoint mMouseDownPoint; }; // class nsResizerFrame #endif /* nsResizerFrame_h___ */
--- a/layout/xul/base/test/window_resizer_element.xul +++ b/layout/xul/base/test/window_resizer_element.xul @@ -36,20 +36,27 @@ function testResizer(resizerid, noShrink synthesizeMouse(document.documentElement, originalX + 5 + mouseX * scale, originalY + 5 + mouseY * scale, { type:"mousemove" }); var newrect = document.getElementById(resizerid + "-container").getBoundingClientRect(); is(Math.round(newrect.width), Math.round(expectedWidth), "resize element " + resizerid + " " + testid + " width moving " + mouseX + "," + mouseY + ",,," + hResize); is(Math.round(newrect.height), Math.round(expectedHeight), "resize element " + resizerid + " " + testid + " height moving " + mouseX + "," + mouseY); - // move it back before we release! - synthesizeMouse(document.documentElement, originalX + 5, originalY + 5, { type:"mousemove" }); - synthesizeMouse(document.documentElement, originalX + 5, originalY + 5, { type:"mouseup" }); - } + // release + synthesizeMouse(document.documentElement, originalX + 5 + mouseX * scale, + originalY + 5 + mouseY * scale, { type:"mouseup" }); } + // return to the original size + synthesizeMouse(document.documentElement, originalX + 5 + mouseX * scale, + originalY + 5 + mouseY * scale, { type:"dblclick" }); } + var newrect = document.getElementById(resizerid + "-container").getBoundingClientRect(); + is(Math.round(newrect.width), Math.round(rect.width), "resize element " + resizerid + + " " + testid + " doubleclicking to restore original size"); + is(Math.round(newrect.height), Math.round(rect.height), "resize element " + resizerid + + " " + testid + " doubleclicking to restore original size"); } } function doTest() { // first, check if a resizer with a element attribute set to an element that // does not exist does not cause a problem var resizer = document.getElementById("notfound"); synthesizeMouse(resizer, 5, 5, { type:"mousedown" });
--- a/nsprpub/admin/repackage.sh +++ b/nsprpub/admin/repackage.sh @@ -59,20 +59,20 @@ # Note! Files written with Gnu tar are not readable by some non-Gnu # versions. Sun, in particular. # # # # # ------------------------------------------------------------------ -FROMTOP=/share/builds/components/nspr20/v4.8.9 -TOTOP=./v4.8.9 -NSPRDIR=nspr-4.8.9 -SOURCETAG=NSPR_4_8_9_RTM +FROMTOP=/share/builds/components/nspr20/v4.9 +TOTOP=./v4.9 +NSPRDIR=nspr-4.9 +SOURCETAG=NSPR_4_9_RTM # # enumerate Unix object directories on /s/b/c UNIX_OBJDIRS=" HP-UXB.11.11_64_DBG.OBJ HP-UXB.11.11_64_OPT.OBJ HP-UXB.11.11_DBG.OBJ HP-UXB.11.11_OPT.OBJ
--- a/nsprpub/configure +++ b/nsprpub/configure @@ -725,18 +725,18 @@ echo "$ac_t""$build" 1>&6 test "$host_alias" != "$target_alias" && test "$program_prefix$program_suffix$program_transform_name" = \ NONENONEs,x,x, && program_prefix=${target_alias}- MOD_MAJOR_VERSION=4 -MOD_MINOR_VERSION=8 -MOD_PATCH_VERSION=9 +MOD_MINOR_VERSION=9 +MOD_PATCH_VERSION=0 NSPR_MODNAME=nspr20 _HAVE_PTHREADS= USE_PTHREADS= USE_USER_PTHREADS= USE_NSPR_THREADS= USE_N32= USE_64= USE_CPLUS= @@ -873,21 +873,51 @@ esac case "$target" in *-android*|*-linuxandroid*) if test -z "$android_ndk" ; then { echo "configure: error: You must specify --with-android-ndk=/path/to/ndk when targeting Android." 1>&2; exit 1; } fi if test -z "$android_toolchain" ; then - android_toolchain="$android_ndk"/build/prebuilt/`uname -s | tr "[:upper:]" "[:lower:]"`-x86/arm-eabi-4.4.0 + echo $ac_n "checking for android toolchain directory""... $ac_c" 1>&6 +echo "configure:883: checking for android toolchain directory" >&5 + + kernel_name=`uname -s | tr "[:upper:]" "[:lower:]"` + + android_toolchain="$android_ndk"/build/prebuilt/$kernel_name-x86/arm-eabi-4.4.0 + + # With newer NDK, the toolchain path has changed. + if ! test -d "$android_toolchain" ; then + android_toolchain="$android_ndk"/toolchains/arm-$kernel_name-androideabi-4.4.3/prebuilt/$kernel_name-x86 + fi + + if test -d "$android_toolchain" ; then + echo "$ac_t""$android_toolchain" 1>&6 + else + { echo "configure: error: not found. You have to specify --with-android-toolchain=/path/to/ndk/toolchain." 1>&2; exit 1; } + fi fi if test -z "$android_platform" ; then - android_platform="$android_ndk"/build/platforms/android-5/arch-arm + echo $ac_n "checking for android platform directory""... $ac_c" 1>&6 +echo "configure:903: checking for android platform directory" >&5 + + android_platform="$android_ndk"/build/platforms/android-5/arch-arm + + # With newer NDK, the platform path has changed. + if ! test -d "$android_platform" ; then + android_platform="$android_ndk"/platforms/android-5/arch-arm + fi + + if test -d "$android_platform" ; then + echo "$ac_t""$android_platform" 1>&6 + else + { echo "configure: error: not found. You have to specify --with-android-platform=/path/to/ndk/platform." 1>&2; exit 1; } + fi fi AS="$android_toolchain"/bin/"$android_tool_prefix"-as CC="$android_toolchain"/bin/"$android_tool_prefix"-gcc CXX="$android_toolchain"/bin/"$android_tool_prefix"-g++ CPP="$android_toolchain"/bin/"$android_tool_prefix"-cpp LD="$android_toolchain"/bin/"$android_tool_prefix"-ld AR="$android_toolchain"/bin/"$android_tool_prefix"-ar @@ -1208,17 +1238,17 @@ if test -z "$CXX"; then esac fi if test -z "$SKIP_PATH_CHECKS"; then # Extract the first word of "$WHOAMI whoami", so it can be a program name with args. set dummy $WHOAMI whoami; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1217: checking for $ac_word" >&5 +echo "configure:1247: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_WHOAMI'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else case "$WHOAMI" in /*) ac_cv_path_WHOAMI="$WHOAMI" # Let the user override the test with a path. ;; ?:/*) @@ -1270,32 +1300,33 @@ else cat >> confdefs.h <<\EOF #define NDEBUG 1 EOF DEFINES="$DEFINES -UDEBUG" fi if test -z "$SKIP_COMPILER_CHECKS"; then -if test "$target" != "$host"; then + +if test "$target" != "$host" -o -n "$CROSS_COMPILE"; then echo "cross compiling from $host to $target" cross_compiling=yes _SAVE_CC="$CC" _SAVE_CFLAGS="$CFLAGS" _SAVE_LDFLAGS="$LDFLAGS" echo $ac_n "checking for $host compiler""... $ac_c" 1>&6 -echo "configure:1288: checking for $host compiler" >&5 +echo "configure:1319: checking for $host compiler" >&5 for ac_prog in $HOST_CC gcc cc /usr/ucb/cc do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1294: checking for $ac_word" >&5 +echo "configure:1325: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_HOST_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$HOST_CC"; then ac_cv_prog_HOST_CC="$HOST_CC" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" @@ -1331,26 +1362,26 @@ test -n "$HOST_CC" || HOST_CC="""" HOST_LDFLAGS="$LDFLAGS" fi CC="$HOST_CC" CFLAGS="$HOST_CFLAGS" LDFLAGS="$HOST_LDFLAGS" echo $ac_n "checking whether the $host compiler ($HOST_CC $HOST_CFLAGS $HOST_LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:1340: checking whether the $host compiler ($HOST_CC $HOST_CFLAGS $HOST_LDFLAGS) works" >&5 +echo "configure:1371: checking whether the $host compiler ($HOST_CC $HOST_CFLAGS $HOST_LDFLAGS) works" >&5 cat > conftest.$ac_ext <<EOF -#line 1342 "configure" +#line 1373 "configure" #include "confdefs.h" int main() { return(0); ; return 0; } EOF -if { (eval echo configure:1349: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1380: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_prog_host_cc_works=1 echo "$ac_t""yes" 1>&6 else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* { echo "configure: error: installation or configuration problem: $host compiler $HOST_CC cannot create executables." 1>&2; exit 1; } fi @@ -1358,28 +1389,34 @@ rm -f conftest* CC=$_SAVE_CC CFLAGS=$_SAVE_CFLAGS LDFLAGS=$_SAVE_LDFLAGS case "$build:$target" in powerpc-apple-darwin8*:i?86-apple-darwin*) _SAVE_CFLAGS=$CFLAGS - _SAVE_CXXFLAGS=$CXXLAGS + _SAVE_CXXFLAGS=$CXXFLAGS CFLAGS="-isysroot /Developer/SDKs/MacOSX10.4u.sdk $CFLAGS" CXXFLAGS="-isysroot /Developer/SDKs/MacOSX10.4u.sdk $CXXFLAGS" - ;; - esac + ;; + *:arm*-apple-darwin*) + _SAVE_CFLAGS=$CFLAGS + _SAVE_CXXFLAGS=$CXXFLAGS + CFLAGS="-isysroot $MACOS_SDK_DIR $CFLAGS" + CXXFLAGS="-isysroot $MACOS_SDK_DIR $CXXFLAGS" + ;; + esac for ac_prog in $CC "${target_alias}-gcc" "${target}-gcc" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1378: checking for $ac_word" >&5 +echo "configure:1415: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" @@ -1403,17 +1440,17 @@ fi test -n "$CC" && break done test -n "$CC" || CC="echo" unset ac_cv_prog_CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1412: checking for $ac_word" >&5 +echo "configure:1449: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" @@ -1433,17 +1470,17 @@ if test -n "$CC"; then else echo "$ac_t""no" 1>&6 fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1442: checking for $ac_word" >&5 +echo "configure:1479: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_prog_rejected=no @@ -1484,17 +1521,17 @@ else fi if test -z "$CC"; then case "`uname -s`" in *win32* | *WIN32*) # Extract the first word of "cl", so it can be a program name with args. set dummy cl; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1493: checking for $ac_word" >&5 +echo "configure:1530: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" @@ -1516,33 +1553,33 @@ else fi ;; esac fi test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:1525: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 +echo "configure:1562: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. ac_cpp='$CPP $CPPFLAGS' ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' cross_compiling=$ac_cv_prog_cc_cross cat > conftest.$ac_ext << EOF -#line 1536 "configure" +#line 1573 "configure" #include "confdefs.h" main(){return(0);} EOF -if { (eval echo configure:1541: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1578: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then ac_cv_prog_cc_cross=no else ac_cv_prog_cc_cross=yes fi else @@ -1558,31 +1595,31 @@ ac_compile='${CC-cc} -c $CFLAGS $CPPFLAG ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' cross_compiling=$ac_cv_prog_cc_cross echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 if test $ac_cv_prog_cc_works = no; then { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:1567: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "configure:1604: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 -echo "configure:1572: checking whether we are using GNU C" >&5 +echo "configure:1609: checking whether we are using GNU C" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.c <<EOF #ifdef __GNUC__ yes; #endif EOF -if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1581: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1618: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no fi fi echo "$ac_t""$ac_cv_prog_gcc" 1>&6 @@ -1591,17 +1628,17 @@ if test $ac_cv_prog_gcc = yes; then else GCC= fi ac_test_CFLAGS="${CFLAGS+set}" ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 -echo "configure:1600: checking whether ${CC-cc} accepts -g" >&5 +echo "configure:1637: checking whether ${CC-cc} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else echo 'void f(){}' > conftest.c if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then ac_cv_prog_cc_g=yes else ac_cv_prog_cc_g=no @@ -1628,17 +1665,17 @@ else fi if test -n "$USE_CPLUS"; then for ac_prog in $CXX "${target_alias}-g++" "${target}-g++" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1637: checking for $ac_word" >&5 +echo "configure:1674: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" @@ -1664,17 +1701,17 @@ done test -n "$CXX" || CXX="echo" unset ac_cv_prog_CXX for ac_prog in $CCC c++ g++ gcc CC cxx cc++ cl do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1673: checking for $ac_word" >&5 +echo "configure:1710: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" @@ -1696,33 +1733,33 @@ else fi test -n "$CXX" && break done test -n "$CXX" || CXX="gcc" echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:1705: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5 +echo "configure:1742: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5 ac_ext=C # CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' cross_compiling=$ac_cv_prog_cxx_cross cat > conftest.$ac_ext << EOF -#line 1716 "configure" +#line 1753 "configure" #include "confdefs.h" int main(){return(0);} EOF -if { (eval echo configure:1721: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1758: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then ac_cv_prog_cxx_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then ac_cv_prog_cxx_cross=no else ac_cv_prog_cxx_cross=yes fi else @@ -1738,31 +1775,31 @@ ac_compile='${CC-cc} -c $CFLAGS $CPPFLAG ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' cross_compiling=$ac_cv_prog_cc_cross echo "$ac_t""$ac_cv_prog_cxx_works" 1>&6 if test $ac_cv_prog_cxx_works = no; then { echo "configure: error: installation or configuration problem: C++ compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:1747: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "configure:1784: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cxx_cross" 1>&6 cross_compiling=$ac_cv_prog_cxx_cross echo $ac_n "checking whether we are using GNU C++""... $ac_c" 1>&6 -echo "configure:1752: checking whether we are using GNU C++" >&5 +echo "configure:1789: checking whether we are using GNU C++" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gxx'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.C <<EOF #ifdef __GNUC__ yes; #endif EOF -if { ac_try='${CXX-g++} -E conftest.C'; { (eval echo configure:1761: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then +if { ac_try='${CXX-g++} -E conftest.C'; { (eval echo configure:1798: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gxx=yes else ac_cv_prog_gxx=no fi fi echo "$ac_t""$ac_cv_prog_gxx" 1>&6 @@ -1771,17 +1808,17 @@ if test $ac_cv_prog_gxx = yes; then else GXX= fi ac_test_CXXFLAGS="${CXXFLAGS+set}" ac_save_CXXFLAGS="$CXXFLAGS" CXXFLAGS= echo $ac_n "checking whether ${CXX-g++} accepts -g""... $ac_c" 1>&6 -echo "configure:1780: checking whether ${CXX-g++} accepts -g" >&5 +echo "configure:1817: checking whether ${CXX-g++} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cxx_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else echo 'void f(){}' > conftest.cc if test -z "`${CXX-g++} -g -c conftest.cc 2>&1`"; then ac_cv_prog_cxx_g=yes else ac_cv_prog_cxx_g=no @@ -1805,28 +1842,28 @@ else else CXXFLAGS= fi fi fi case "$build:$target" in - powerpc-apple-darwin8*:i?86-apple-darwin*) + powerpc-apple-darwin8*:i?86-apple-darwin*|*:arm*-apple-darwin*) CFLAGS=$_SAVE_CFLAGS CXXFLAGS=$_SAVE_CXXFLAGS ;; esac for ac_prog in $RANLIB "${target_alias}-ranlib" "${target}-ranlib" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1825: checking for $ac_word" >&5 +echo "configure:1862: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" @@ -1851,17 +1888,17 @@ test -n "$RANLIB" && break done test -n "$RANLIB" || RANLIB="echo" for ac_prog in $AR "${target_alias}-ar" "${target}-ar" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1860: checking for $ac_word" >&5 +echo "configure:1897: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" @@ -1886,17 +1923,17 @@ test -n "$AR" && break done test -n "$AR" || AR="echo" for ac_prog in $AS "${target_alias}-as" "${target}-as" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1895: checking for $ac_word" >&5 +echo "configure:1932: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_AS'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$AS"; then ac_cv_prog_AS="$AS" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" @@ -1921,17 +1958,17 @@ test -n "$AS" && break done test -n "$AS" || AS="echo" for ac_prog in $LD "${target_alias}-ld" "${target}-ld" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1930: checking for $ac_word" >&5 +echo "configure:1967: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_LD'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$LD"; then ac_cv_prog_LD="$LD" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" @@ -1956,17 +1993,17 @@ test -n "$LD" && break done test -n "$LD" || LD="echo" for ac_prog in $STRIP "${target_alias}-strip" "${target}-strip" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1965: checking for $ac_word" >&5 +echo "configure:2002: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_STRIP'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" @@ -1991,17 +2028,17 @@ test -n "$STRIP" && break done test -n "$STRIP" || STRIP="echo" for ac_prog in $WINDRES "${target_alias}-windres" "${target}-windres" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2000: checking for $ac_word" >&5 +echo "configure:2037: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_WINDRES'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$WINDRES"; then ac_cv_prog_WINDRES="$WINDRES" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" @@ -2026,17 +2063,17 @@ test -n "$WINDRES" && break done test -n "$WINDRES" || WINDRES="echo" else # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2035: checking for $ac_word" >&5 +echo "configure:2072: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" @@ -2056,17 +2093,17 @@ if test -n "$CC"; then else echo "$ac_t""no" 1>&6 fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2065: checking for $ac_word" >&5 +echo "configure:2102: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_prog_rejected=no @@ -2107,17 +2144,17 @@ else fi if test -z "$CC"; then case "`uname -s`" in *win32* | *WIN32*) # Extract the first word of "cl", so it can be a program name with args. set dummy cl; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2116: checking for $ac_word" >&5 +echo "configure:2153: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" @@ -2139,33 +2176,33 @@ else fi ;; esac fi test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:2148: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 +echo "configure:2185: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. ac_cpp='$CPP $CPPFLAGS' ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' cross_compiling=$ac_cv_prog_cc_cross cat > conftest.$ac_ext << EOF -#line 2159 "configure" +#line 2196 "configure" #include "confdefs.h" main(){return(0);} EOF -if { (eval echo configure:2164: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2201: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then ac_cv_prog_cc_cross=no else ac_cv_prog_cc_cross=yes fi else @@ -2181,31 +2218,31 @@ ac_compile='${CC-cc} -c $CFLAGS $CPPFLAG ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' cross_compiling=$ac_cv_prog_cc_cross echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 if test $ac_cv_prog_cc_works = no; then { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:2190: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "configure:2227: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 -echo "configure:2195: checking whether we are using GNU C" >&5 +echo "configure:2232: checking whether we are using GNU C" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.c <<EOF #ifdef __GNUC__ yes; #endif EOF -if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:2204: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:2241: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no fi fi echo "$ac_t""$ac_cv_prog_gcc" 1>&6 @@ -2214,17 +2251,17 @@ if test $ac_cv_prog_gcc = yes; then else GCC= fi ac_test_CFLAGS="${CFLAGS+set}" ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 -echo "configure:2223: checking whether ${CC-cc} accepts -g" >&5 +echo "configure:2260: checking whether ${CC-cc} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else echo 'void f(){}' > conftest.c if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then ac_cv_prog_cc_g=yes else ac_cv_prog_cc_g=no @@ -2254,17 +2291,17 @@ fi if test "$CC" = "cl" -a -z "$CXX"; then CXX=$CC else for ac_prog in $CCC c++ g++ gcc CC cxx cc++ cl do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2263: checking for $ac_word" >&5 +echo "configure:2300: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" @@ -2286,33 +2323,33 @@ else fi test -n "$CXX" && break done test -n "$CXX" || CXX="gcc" echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:2295: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5 +echo "configure:2332: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5 ac_ext=C # CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' cross_compiling=$ac_cv_prog_cxx_cross cat > conftest.$ac_ext << EOF -#line 2306 "configure" +#line 2343 "configure" #include "confdefs.h" int main(){return(0);} EOF -if { (eval echo configure:2311: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2348: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then ac_cv_prog_cxx_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then ac_cv_prog_cxx_cross=no else ac_cv_prog_cxx_cross=yes fi else @@ -2328,31 +2365,31 @@ ac_compile='${CC-cc} -c $CFLAGS $CPPFLAG ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' cross_compiling=$ac_cv_prog_cc_cross echo "$ac_t""$ac_cv_prog_cxx_works" 1>&6 if test $ac_cv_prog_cxx_works = no; then { echo "configure: error: installation or configuration problem: C++ compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:2337: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "configure:2374: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cxx_cross" 1>&6 cross_compiling=$ac_cv_prog_cxx_cross echo $ac_n "checking whether we are using GNU C++""... $ac_c" 1>&6 -echo "configure:2342: checking whether we are using GNU C++" >&5 +echo "configure:2379: checking whether we are using GNU C++" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gxx'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.C <<EOF #ifdef __GNUC__ yes; #endif EOF -if { ac_try='${CXX-g++} -E conftest.C'; { (eval echo configure:2351: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then +if { ac_try='${CXX-g++} -E conftest.C'; { (eval echo configure:2388: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gxx=yes else ac_cv_prog_gxx=no fi fi echo "$ac_t""$ac_cv_prog_gxx" 1>&6 @@ -2361,17 +2398,17 @@ if test $ac_cv_prog_gxx = yes; then else GXX= fi ac_test_CXXFLAGS="${CXXFLAGS+set}" ac_save_CXXFLAGS="$CXXFLAGS" CXXFLAGS= echo $ac_n "checking whether ${CXX-g++} accepts -g""... $ac_c" 1>&6 -echo "configure:2370: checking whether ${CXX-g++} accepts -g" >&5 +echo "configure:2407: checking whether ${CXX-g++} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cxx_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else echo 'void f(){}' > conftest.cc if test -z "`${CXX-g++} -g -c conftest.cc 2>&1`"; then ac_cv_prog_cxx_g=yes else ac_cv_prog_cxx_g=no @@ -2395,72 +2432,72 @@ else else CXXFLAGS= fi fi fi fi echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 -echo "configure:2404: checking how to run the C preprocessor" >&5 +echo "configure:2441: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # This must be in double quotes, not single quotes, because CPP may get # substituted into the Makefile and "${CC-cc}" will confuse make. CPP="${CC-cc} -E" # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext <<EOF -#line 2419 "configure" +#line 2456 "configure" #include "confdefs.h" #include <assert.h> Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2425: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2462: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext <<EOF -#line 2436 "configure" +#line 2473 "configure" #include "confdefs.h" #include <assert.h> Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2442: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2479: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* CPP="${CC-cc} -nologo -E" cat > conftest.$ac_ext <<EOF -#line 2453 "configure" +#line 2490 "configure" #include "confdefs.h" #include <assert.h> Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2459: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2496: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* @@ -2477,17 +2514,17 @@ fi else ac_cv_prog_CPP="$CPP" fi echo "$ac_t""$CPP" 1>&6 # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2486: checking for $ac_word" >&5 +echo "configure:2523: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" @@ -2509,17 +2546,17 @@ else echo "$ac_t""no" 1>&6 fi for ac_prog in as do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2518: checking for $ac_word" >&5 +echo "configure:2555: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_AS'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else case "$AS" in /*) ac_cv_path_AS="$AS" # Let the user override the test with a path. ;; ?:/*) @@ -2550,17 +2587,17 @@ test -n "$AS" && break done test -n "$AS" || AS="$CC" for ac_prog in ar do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2559: checking for $ac_word" >&5 +echo "configure:2596: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_AR'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else case "$AR" in /*) ac_cv_path_AR="$AR" # Let the user override the test with a path. ;; ?:/*) @@ -2591,17 +2628,17 @@ test -n "$AR" && break done test -n "$AR" || AR="echo not_ar" for ac_prog in ld link do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2600: checking for $ac_word" >&5 +echo "configure:2637: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_LD'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else case "$LD" in /*) ac_cv_path_LD="$LD" # Let the user override the test with a path. ;; ?:/*) @@ -2632,17 +2669,17 @@ test -n "$LD" && break done test -n "$LD" || LD="echo not_ld" for ac_prog in strip do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2641: checking for $ac_word" >&5 +echo "configure:2678: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_STRIP'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else case "$STRIP" in /*) ac_cv_path_STRIP="$STRIP" # Let the user override the test with a path. ;; ?:/*) @@ -2673,17 +2710,17 @@ test -n "$STRIP" && break done test -n "$STRIP" || STRIP="echo not_strip" for ac_prog in windres do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2682: checking for $ac_word" >&5 +echo "configure:2719: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_WINDRES'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else case "$WINDRES" in /*) ac_cv_path_WINDRES="$WINDRES" # Let the user override the test with a path. ;; ?:/*) @@ -2741,39 +2778,39 @@ esac if test "$cross_compiling" = "yes"; then CROSS_COMPILE=1 else CROSS_COMPILE= fi echo $ac_n "checking for gcc -pipe support""... $ac_c" 1>&6 -echo "configure:2750: checking for gcc -pipe support" >&5 +echo "configure:2787: checking for gcc -pipe support" >&5 if test -n "$GNU_CC" && test -n "$GNU_CXX" && test -n "$GNU_AS"; then echo '#include <stdio.h>' > dummy-hello.c echo 'int main() { printf("Hello World\n"); return 0; }' >> dummy-hello.c ${CC} -S dummy-hello.c -o dummy-hello.s 2>&5 cat dummy-hello.s | ${AS} -o dummy-hello.S - 2>&5 if test $? = 0; then _res_as_stdin="yes" else _res_as_stdin="no" fi if test "$_res_as_stdin" = "yes"; then _SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -pipe" cat > conftest.$ac_ext <<EOF -#line 2765 "configure" +#line 2802 "configure" #include "confdefs.h" #include <stdio.h> int main() { printf("Hello World\n"); ; return 0; } EOF -if { (eval echo configure:2772: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2809: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* _res_gcc_pipe="yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* _res_gcc_pipe="no" fi @@ -2793,26 +2830,26 @@ else echo "$ac_t""no" 1>&6 fi _SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -fprofile-generate -fprofile-correction" echo $ac_n "checking whether C compiler supports -fprofile-generate""... $ac_c" 1>&6 -echo "configure:2802: checking whether C compiler supports -fprofile-generate" >&5 +echo "configure:2839: checking whether C compiler supports -fprofile-generate" >&5 cat > conftest.$ac_ext <<EOF -#line 2804 "configure" +#line 2841 "configure" #include "confdefs.h" int main() { return 0; ; return 0; } EOF -if { (eval echo configure:2811: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2848: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* PROFILE_GEN_CFLAGS="-fprofile-generate" result="yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* result="no" @@ -2825,17 +2862,17 @@ if test $result = "yes"; then PROFILE_USE_CFLAGS="-fprofile-use -fprofile-correction -Wcoverage-mismatch" PROFILE_USE_LDFLAGS="-fprofile-use" fi CFLAGS="$_SAVE_CFLAGS" if test "$GNU_CC"; then echo $ac_n "checking for visibility(hidden) attribute""... $ac_c" 1>&6 -echo "configure:2834: checking for visibility(hidden) attribute" >&5 +echo "configure:2871: checking for visibility(hidden) attribute" >&5 if eval "test \"`echo '$''{'ac_cv_visibility_hidden'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.c <<EOF int foo __attribute__ ((visibility ("hidden"))) = 1; EOF ac_cv_visibility_hidden=no if ${CC-cc} -Werror -S conftest.c -o conftest.s >/dev/null 2>&1; then @@ -2849,17 +2886,17 @@ fi echo "$ac_t""$ac_cv_visibility_hidden" 1>&6 if test "$ac_cv_visibility_hidden" = "yes"; then cat >> confdefs.h <<\EOF #define HAVE_VISIBILITY_HIDDEN_ATTRIBUTE 1 EOF echo $ac_n "checking for visibility pragma support""... $ac_c" 1>&6 -echo "configure:2858: checking for visibility pragma support" >&5 +echo "configure:2895: checking for visibility pragma support" >&5 if eval "test \"`echo '$''{'ac_cv_visibility_pragma'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.c <<EOF #pragma GCC visibility push(hidden) int foo_hidden = 1; #pragma GCC visibility push(default) int foo_default = 1; @@ -2902,17 +2939,17 @@ fi # GNU_CC fi # SKIP_COMPILER_CHECKS if test -z "$SKIP_PATH_CHECKS"; then for ac_prog in perl5 perl do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2911: checking for $ac_word" >&5 +echo "configure:2948: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_PERL'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else case "$PERL" in /*) ac_cv_path_PERL="$PERL" # Let the user override the test with a path. ;; ?:/*) @@ -3223,24 +3260,24 @@ yes) no) MOZ_THUMB2= thumb_flag="-marm" ;; *) _SAVE_CFLAGS="$CFLAGS" CFLAGS="$arch_flag" cat > conftest.$ac_ext <<EOF -#line 3232 "configure" +#line 3269 "configure" #include "confdefs.h" int main() { return sizeof(__thumb2__); ; return 0; } EOF -if { (eval echo configure:3239: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3276: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* MOZ_THUMB2=1 else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* MOZ_THUMB2= fi @@ -3292,26 +3329,26 @@ no) ;; esac all_flags=`echo $arch_flag $thumb_flag $thumb_interwork_flag $fpu_flag $float_abi_flag $soft_float_flag` if test -n "$all_flags"; then _SAVE_CFLAGS="$CFLAGS" CFLAGS="$all_flags" echo $ac_n "checking whether the chosen combination of compiler flags ($all_flags) works""... $ac_c" 1>&6 -echo "configure:3301: checking whether the chosen combination of compiler flags ($all_flags) works" >&5 +echo "configure:3338: checking whether the chosen combination of compiler flags ($all_flags) works" >&5 cat > conftest.$ac_ext <<EOF -#line 3303 "configure" +#line 3340 "configure" #include "confdefs.h" int main() { return 0; ; return 0; } EOF -if { (eval echo configure:3310: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3347: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* echo "$ac_t""yes" 1>&6 else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* { echo "configure: error: no" 1>&2; exit 1; } fi @@ -3358,27 +3395,27 @@ EOF cat >> confdefs.h <<\EOF #define SYSV 1 EOF DSO_LDOPTS='-brtl -bnortllib -bM:SRE -bnoentry -bexpall -blibpath:/usr/lib:/lib' ac_safe=`echo "sys/atomic_op.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for sys/atomic_op.h""... $ac_c" 1>&6 -echo "configure:3367: checking for sys/atomic_op.h" >&5 +echo "configure:3404: checking for sys/atomic_op.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 3372 "configure" +#line 3409 "configure" #include "confdefs.h" #include <sys/atomic_op.h> EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:3377: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:3414: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* eval "ac_cv_header_$ac_safe=yes" else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 @@ -3564,36 +3601,36 @@ EOF PR_MD_ARCH_DIR=beos RESOLVE_LINK_SYMBOLS=1 case "${target_cpu}" in i*86) _OPTIMIZE_FLAGS=-O2 _DEBUG_FLAGS='-gdwarf-2 -O0' MKSHLIB='$(CCC) $(DSO_LDOPTS) -o $@' echo $ac_n "checking for gethostbyaddr in -lbind""... $ac_c" 1>&6 -echo "configure:3573: checking for gethostbyaddr in -lbind" >&5 +echo "configure:3610: checking for gethostbyaddr in -lbind" >&5 ac_lib_var=`echo bind'_'gethostbyaddr | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lbind $LIBS" cat > conftest.$ac_ext <<EOF -#line 3581 "configure" +#line 3618 "configure" #include "confdefs.h" /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char gethostbyaddr(); int main() { gethostbyaddr() ; return 0; } EOF -if { (eval echo configure:3592: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3629: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi @@ -3770,30 +3807,66 @@ EOF cat >> confdefs.h <<\EOF #define HAVE_SOCKLEN_T 1 EOF AS='$(CC) -x assembler-with-cpp' CFLAGS="$CFLAGS -Wall -fno-common" case "${target_cpu}" in + arm*) + CPU_ARCH=arm + ;; i*86*) if test -n "$USE_64"; then CPU_ARCH=x86_64 else CPU_ARCH=i386 fi ;; *) CPU_ARCH=ppc ;; esac if test "`echo $CC | grep -c '\-arch '`" = "0"; then CC="$CC -arch $CPU_ARCH" fi + ac_safe=`echo "crt_externs.h" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for crt_externs.h""... $ac_c" 1>&6 +echo "configure:3835: checking for crt_externs.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 3840 "configure" +#include "confdefs.h" +#include <crt_externs.h> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:3845: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +fi + DSO_CFLAGS=-fPIC DSO_LDOPTS='-dynamiclib -compatibility_version 1 -current_version 1 -all_load -install_name @executable_path/$@ -headerpad_max_install_names' _OPTIMIZE_FLAGS=-O2 MKSHLIB='$(CC) $(DSO_LDOPTS) -o $@' STRIP="$STRIP -x -S" DLL_SUFFIX=dylib USE_PTHREADS=1 MDCPUCFG_H=_darwin.cfg @@ -4937,27 +5010,27 @@ EOF if test -z "$GNU_CC"; then CC="$CC -std1 -ieee_with_inexact" if test "$OS_RELEASE" != "V2.0"; then CC="$CC -readonly_strings" fi _OPTIMIZE_FLAGS="$_OPTIMIZE_FLAGS -Olimit 4000" ac_safe=`echo "machine/builtins.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for machine/builtins.h""... $ac_c" 1>&6 -echo "configure:4946: checking for machine/builtins.h" >&5 +echo "configure:5019: checking for machine/builtins.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 4951 "configure" +#line 5024 "configure" #include "confdefs.h" #include <machine/builtins.h> EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:4956: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:5029: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* eval "ac_cv_header_$ac_safe=yes" else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 @@ -5596,63 +5669,63 @@ if test -z "$SKIP_LIBRARY_CHECKS"; then case $target in *-darwin*|*-beos*|*-os2*) ;; *) echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6 -echo "configure:5605: checking for dlopen in -ldl" >&5 +echo "configure:5678: checking for dlopen in -ldl" >&5 ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-ldl $LIBS" cat > conftest.$ac_ext <<EOF -#line 5613 "configure" +#line 5686 "configure" #include "confdefs.h" /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char dlopen(); int main() { dlopen() ; return 0; } EOF -if { (eval echo configure:5624: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5697: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 ac_safe=`echo "dlfcn.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for dlfcn.h""... $ac_c" 1>&6 -echo "configure:5641: checking for dlfcn.h" >&5 +echo "configure:5714: checking for dlfcn.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 5646 "configure" +#line 5719 "configure" #include "confdefs.h" #include <dlfcn.h> EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:5651: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:5724: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* eval "ac_cv_header_$ac_safe=yes" else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 @@ -5675,23 +5748,23 @@ fi ;; esac if test $ac_cv_prog_gcc = yes; then echo $ac_n "checking whether ${CC-cc} needs -traditional""... $ac_c" 1>&6 -echo "configure:5684: checking whether ${CC-cc} needs -traditional" >&5 +echo "configure:5757: checking whether ${CC-cc} needs -traditional" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc_traditional'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_pattern="Autoconf.*'x'" cat > conftest.$ac_ext <<EOF -#line 5690 "configure" +#line 5763 "configure" #include "confdefs.h" #include <sgtty.h> Autoconf TIOCGETP EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | egrep "$ac_pattern" >/dev/null 2>&1; then rm -rf conftest* ac_cv_prog_gcc_traditional=yes @@ -5699,17 +5772,17 @@ else rm -rf conftest* ac_cv_prog_gcc_traditional=no fi rm -f conftest* if test $ac_cv_prog_gcc_traditional = no; then cat > conftest.$ac_ext <<EOF -#line 5708 "configure" +#line 5781 "configure" #include "confdefs.h" #include <termio.h> Autoconf TCGETA EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | egrep "$ac_pattern" >/dev/null 2>&1; then rm -rf conftest* ac_cv_prog_gcc_traditional=yes @@ -5723,22 +5796,22 @@ echo "$ac_t""$ac_cv_prog_gcc_traditional if test $ac_cv_prog_gcc_traditional = yes; then CC="$CC -traditional" fi fi for ac_func in lchown strerror do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:5732: checking for $ac_func" >&5 +echo "configure:5805: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 5737 "configure" +#line 5810 "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func(); below. */ #include <assert.h> /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func(); @@ -5751,17 +5824,17 @@ int main() { #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else $ac_func(); #endif ; return 0; } EOF -if { (eval echo configure:5760: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5833: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_func_$ac_func=no" fi @@ -5802,17 +5875,17 @@ if test "$CCACHE" != "no"; then fi fi fi for ac_prog in $CCACHE ccache do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:5811: checking for $ac_word" >&5 +echo "configure:5884: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_CCACHE'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else case "$CCACHE" in /*) ac_cv_path_CCACHE="$CCACHE" # Let the user override the test with a path. ;; ?:/*) @@ -5861,17 +5934,17 @@ if test "${enable_strip+set}" = set; the fi case "${target_os}" in hpux*) if test -z "$GNU_CC"; then echo $ac_n "checking for +Olit support""... $ac_c" 1>&6 -echo "configure:5870: checking for +Olit support" >&5 +echo "configure:5943: checking for +Olit support" >&5 if eval "test \"`echo '$''{'ac_cv_hpux_usable_olit_option'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_cv_hpux_usable_olit_option=no rm -f conftest* echo 'int main() { return 0; }' | cat > conftest.c ${CC-cc} ${CFLAGS} +Olit=all -o conftest conftest.c > conftest.out 2>&1 if test $? -eq 0; then @@ -5903,17 +5976,17 @@ darwin*) _HAVE_PTHREADS=1 ;; wince*) _HAVE_PTHREADS= ;; *) echo $ac_n "checking for pthread_create in -lpthreads""... $ac_c" 1>&6 -echo "configure:5912: checking for pthread_create in -lpthreads" >&5 +echo "configure:5985: checking for pthread_create in -lpthreads" >&5 echo " #include <pthread.h> void *foo(void *v) { return v; } int main() { pthread_t t; if (!pthread_create(&t, 0, &foo, 0)) { pthread_join(t, 0); } @@ -5925,17 +5998,17 @@ echo " rm -f dummy.c dummy${ac_exeext} ; if test "$_res" = "0"; then echo "$ac_t""yes" 1>&6 _HAVE_PTHREADS=1 _PTHREAD_LDFLAGS="-lpthreads" else echo "$ac_t""no" 1>&6 echo $ac_n "checking for pthread_create in -lpthread""... $ac_c" 1>&6 -echo "configure:5934: checking for pthread_create in -lpthread" >&5 +echo "configure:6007: checking for pthread_create in -lpthread" >&5 echo " #include <pthread.h> void *foo(void *v) { return v; } int main() { pthread_t t; if (!pthread_create(&t, 0, &foo, 0)) { pthread_join(t, 0); } @@ -5947,17 +6020,17 @@ echo " rm -f dummy.c dummy${ac_exeext} ; if test "$_res" = "0"; then echo "$ac_t""yes" 1>&6 _HAVE_PTHREADS=1 _PTHREAD_LDFLAGS="-lpthread" else echo "$ac_t""no" 1>&6 echo $ac_n "checking for pthread_create in -lc_r""... $ac_c" 1>&6 -echo "configure:5956: checking for pthread_create in -lc_r" >&5 +echo "configure:6029: checking for pthread_create in -lc_r" >&5 echo " #include <pthread.h> void *foo(void *v) { return v; } int main() { pthread_t t; if (!pthread_create(&t, 0, &foo, 0)) { pthread_join(t, 0); } @@ -5969,17 +6042,17 @@ echo " rm -f dummy.c dummy${ac_exeext} ; if test "$_res" = "0"; then echo "$ac_t""yes" 1>&6 _HAVE_PTHREADS=1 _PTHREAD_LDFLAGS="-lc_r" else echo "$ac_t""no" 1>&6 echo $ac_n "checking for pthread_create in -lc""... $ac_c" 1>&6 -echo "configure:5978: checking for pthread_create in -lc" >&5 +echo "configure:6051: checking for pthread_create in -lc" >&5 echo " #include <pthread.h> void *foo(void *v) { return v; } int main() { pthread_t t; if (!pthread_create(&t, 0, &foo, 0)) { pthread_join(t, 0); } @@ -6087,17 +6160,17 @@ if test "${enable_ipv6+set}" = set; then fi fi if test -n "$USE_PTHREADS"; then rm -f conftest* ac_cv_have_dash_pthread=no echo $ac_n "checking whether ${CC-cc} accepts -pthread""... $ac_c" 1>&6 -echo "configure:6096: checking whether ${CC-cc} accepts -pthread" >&5 +echo "configure:6169: checking whether ${CC-cc} accepts -pthread" >&5 echo 'int main() { return 0; }' | cat > conftest.c ${CC-cc} -pthread -o conftest conftest.c > conftest.out 2>&1 if test $? -eq 0; then if test -z "`egrep -i '(unrecognize|unknown)' conftest.out | grep pthread`" && test -z "`egrep -i '(error|incorrect)' conftest.out`" ; then ac_cv_have_dash_pthread=yes case "$target_os" in freebsd*) # Freebsd doesn't use -pthread for compiles, it uses them for linking @@ -6110,17 +6183,17 @@ echo "configure:6096: checking whether $ fi fi rm -f conftest* echo "$ac_t""$ac_cv_have_dash_pthread" 1>&6 ac_cv_have_dash_pthreads=no if test "$ac_cv_have_dash_pthread" = "no"; then echo $ac_n "checking whether ${CC-cc} accepts -pthreads""... $ac_c" 1>&6 -echo "configure:6119: checking whether ${CC-cc} accepts -pthreads" >&5 +echo "configure:6192: checking whether ${CC-cc} accepts -pthreads" >&5 echo 'int main() { return 0; }' | cat > conftest.c ${CC-cc} -pthreads -o conftest conftest.c > conftest.out 2>&1 if test $? -eq 0; then if test -z "`egrep -i '(unrecognize|unknown)' conftest.out | grep pthreads`" && test -z "`egrep -i '(error|incorrect)' conftest.out`" ; then ac_cv_have_dash_pthreads=yes CFLAGS="$CFLAGS -pthreads" CXXFLAGS="$CXXFLAGS -pthreads" fi
--- a/nsprpub/configure.in +++ b/nsprpub/configure.in @@ -44,18 +44,18 @@ AC_INIT(config/libc_r.h) AC_CONFIG_AUX_DIR(${srcdir}/build/autoconf) AC_CANONICAL_SYSTEM dnl ======================================================== dnl = Defaults dnl ======================================================== MOD_MAJOR_VERSION=4 -MOD_MINOR_VERSION=8 -MOD_PATCH_VERSION=9 +MOD_MINOR_VERSION=9 +MOD_PATCH_VERSION=0 NSPR_MODNAME=nspr20 _HAVE_PTHREADS= USE_PTHREADS= USE_USER_PTHREADS= USE_NSPR_THREADS= USE_N32= USE_64= USE_CPLUS= @@ -165,21 +165,49 @@ esac case "$target" in *-android*|*-linuxandroid*) if test -z "$android_ndk" ; then AC_MSG_ERROR([You must specify --with-android-ndk=/path/to/ndk when targeting Android.]) fi if test -z "$android_toolchain" ; then - android_toolchain="$android_ndk"/build/prebuilt/`uname -s | tr "[[:upper:]]" "[[:lower:]]"`-x86/arm-eabi-4.4.0 + AC_MSG_CHECKING([for android toolchain directory]) + + kernel_name=`uname -s | tr "[[:upper:]]" "[[:lower:]]"` + + android_toolchain="$android_ndk"/build/prebuilt/$kernel_name-x86/arm-eabi-4.4.0 + + # With newer NDK, the toolchain path has changed. + if ! test -d "$android_toolchain" ; then + android_toolchain="$android_ndk"/toolchains/arm-$kernel_name-androideabi-4.4.3/prebuilt/$kernel_name-x86 + fi + + if test -d "$android_toolchain" ; then + AC_MSG_RESULT([$android_toolchain]) + else + AC_MSG_ERROR([not found. You have to specify --with-android-toolchain=/path/to/ndk/toolchain.]) + fi fi if test -z "$android_platform" ; then - android_platform="$android_ndk"/build/platforms/android-5/arch-arm + AC_MSG_CHECKING([for android platform directory]) + + android_platform="$android_ndk"/build/platforms/android-5/arch-arm + + # With newer NDK, the platform path has changed. + if ! test -d "$android_platform" ; then + android_platform="$android_ndk"/platforms/android-5/arch-arm + fi + + if test -d "$android_platform" ; then + AC_MSG_RESULT([$android_platform]) + else + AC_MSG_ERROR([not found. You have to specify --with-android-platform=/path/to/ndk/platform.]) + fi fi dnl set up compilers AS="$android_toolchain"/bin/"$android_tool_prefix"-as CC="$android_toolchain"/bin/"$android_tool_prefix"-gcc CXX="$android_toolchain"/bin/"$android_tool_prefix"-g++ CPP="$android_toolchain"/bin/"$android_tool_prefix"-cpp LD="$android_toolchain"/bin/"$android_tool_prefix"-ld @@ -494,17 +522,21 @@ else AC_DEFINE(NDEBUG) DEFINES="$DEFINES -UDEBUG" fi if test -z "$SKIP_COMPILER_CHECKS"; then dnl ======================================================== dnl Checks for compilers. dnl ======================================================== -if test "$target" != "$host"; then + +dnl Explicitly honor $CROSS_COMPILE to allow cross-compiling +dnl between toolkits on the same architecture, as when +dnl targeting the iOS Simulator from OS X. +if test "$target" != "$host" -o -n "$CROSS_COMPILE"; then echo "cross compiling from $host to $target" cross_compiling=yes _SAVE_CC="$CC" _SAVE_CFLAGS="$CFLAGS" _SAVE_LDFLAGS="$LDFLAGS" AC_MSG_CHECKING([for $host compiler]) @@ -536,33 +568,42 @@ if test "$target" != "$host"; then case "$build:$target" in powerpc-apple-darwin8*:i?86-apple-darwin*) dnl The Darwin cross compiler doesn't necessarily point itself at a dnl root that has libraries for the proper architecture, it defaults dnl to the system root. The libraries in the system root on current dnl versions of PPC OS X 10.4 aren't fat, so these target compiler dnl checks will fail. Fake a working SDK in that case. _SAVE_CFLAGS=$CFLAGS - _SAVE_CXXFLAGS=$CXXLAGS + _SAVE_CXXFLAGS=$CXXFLAGS CFLAGS="-isysroot /Developer/SDKs/MacOSX10.4u.sdk $CFLAGS" CXXFLAGS="-isysroot /Developer/SDKs/MacOSX10.4u.sdk $CXXFLAGS" - ;; - esac + ;; + *:arm*-apple-darwin*) + dnl The arm compiler doesn't appear to know about its root by default, + dnl so explicitly pass it one here. Later on we'll put this in CFLAGS + dnl anyway. + _SAVE_CFLAGS=$CFLAGS + _SAVE_CXXFLAGS=$CXXFLAGS + CFLAGS="-isysroot $MACOS_SDK_DIR $CFLAGS" + CXXFLAGS="-isysroot $MACOS_SDK_DIR $CXXFLAGS" + ;; + esac AC_CHECK_PROGS(CC, $CC "${target_alias}-gcc" "${target}-gcc", echo) unset ac_cv_prog_CC AC_PROG_CC if test -n "$USE_CPLUS"; then AC_CHECK_PROGS(CXX, $CXX "${target_alias}-g++" "${target}-g++", echo) unset ac_cv_prog_CXX AC_PROG_CXX fi case "$build:$target" in - powerpc-apple-darwin8*:i?86-apple-darwin*) + powerpc-apple-darwin8*:i?86-apple-darwin*|*:arm*-apple-darwin*) dnl Revert the changes made above. From this point on, the target dnl compiler will never be used without applying the SDK to CFLAGS dnl (see --with-macos-sdk below). CFLAGS=$_SAVE_CFLAGS CXXFLAGS=$_SAVE_CXXFLAGS ;; esac @@ -1301,30 +1342,34 @@ case "$target" in *-darwin*) AC_DEFINE(XP_UNIX) AC_DEFINE(DARWIN) AC_DEFINE(HAVE_BSD_FLOCK) AC_DEFINE(HAVE_SOCKLEN_T) AS='$(CC) -x assembler-with-cpp' CFLAGS="$CFLAGS -Wall -fno-common" case "${target_cpu}" in + arm*) + CPU_ARCH=arm + ;; i*86*) if test -n "$USE_64"; then CPU_ARCH=x86_64 else CPU_ARCH=i386 fi ;; *) CPU_ARCH=ppc ;; esac if test "`echo $CC | grep -c '\-arch '`" = "0"; then CC="$CC -arch $CPU_ARCH" fi + AC_CHECK_HEADER(crt_externs.h) DSO_CFLAGS=-fPIC DSO_LDOPTS='-dynamiclib -compatibility_version 1 -current_version 1 -all_load -install_name @executable_path/$@ -headerpad_max_install_names' _OPTIMIZE_FLAGS=-O2 MKSHLIB='$(CC) $(DSO_LDOPTS) -o $@' STRIP="$STRIP -x -S" DLL_SUFFIX=dylib USE_PTHREADS=1 MDCPUCFG_H=_darwin.cfg
--- a/nsprpub/lib/ds/plarena.c +++ b/nsprpub/lib/ds/plarena.c @@ -124,17 +124,25 @@ PR_IMPLEMENT(void) PL_InitArenaPool( pool->mask = pmasks[align]; else pool->mask = PR_BITMASK(PR_CeilingLog2(align)); pool->first.next = NULL; pool->first.base = pool->first.avail = pool->first.limit = (PRUword)PL_ARENA_ALIGN(pool, &pool->first + 1); pool->current = &pool->first; - pool->arenasize = size; + /* + * Compute the net size so that each arena's gross size is |size|. + * sizeof(PLArena) + pool->mask is the header and alignment slop + * that PL_ArenaAllocate adds to the net size. + */ + if (size > sizeof(PLArena) + pool->mask) + pool->arenasize = size - (sizeof(PLArena) + pool->mask); + else + pool->arenasize = size; #ifdef PL_ARENAMETER memset(&pool->stats, 0, sizeof pool->stats); pool->stats.name = strdup(name); pool->stats.next = arena_stats_list; arena_stats_list = &pool->stats; #endif }
--- a/nsprpub/lib/ds/plarenas.h +++ b/nsprpub/lib/ds/plarenas.h @@ -39,17 +39,22 @@ #define PLARENAS_H PR_BEGIN_EXTERN_C typedef struct PLArenaPool PLArenaPool; /* ** Initialize an arena pool with the given name for debugging and metering, -** with a minimum size per arena of size bytes. +** with a minimum gross size per arena of size bytes. The net size per arena +** is smaller than the gross size by a header of four pointers plus any +** necessary padding for alignment. +** +** Note: choose a gross size that's a power of two to avoid the heap allocator +** rounding the size up. **/ PR_EXTERN(void) PL_InitArenaPool( PLArenaPool *pool, const char *name, PRUint32 size, PRUint32 align); /* ** Finish using arenas, freeing all memory associated with them. **/ PR_EXTERN(void) PL_ArenaFinish(void);
deleted file mode 100644 --- a/nsprpub/lib/msgc/Makefile.in +++ /dev/null @@ -1,52 +0,0 @@ -# -# ***** BEGIN LICENSE BLOCK ***** -# 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 the Netscape Portable Runtime (NSPR). -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998-2000 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either 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. -# -# ***** END LICENSE BLOCK ***** - -MOD_DEPTH = ../.. -topsrcdir = @top_srcdir@ -srcdir = @srcdir@ -VPATH = @srcdir@ - -include $(MOD_DEPTH)/config/autoconf.mk - -include $(topsrcdir)/config/config.mk - -DIRS = include src tests - -include $(topsrcdir)/config/rules.mk - -export:: $(TARGETS) -
deleted file mode 100644 --- a/nsprpub/lib/msgc/include/.cvsignore +++ /dev/null @@ -1,1 +0,0 @@ -Makefile
deleted file mode 100644 --- a/nsprpub/lib/msgc/include/Makefile.in +++ /dev/null @@ -1,57 +0,0 @@ -# -# ***** BEGIN LICENSE BLOCK ***** -# 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 the Netscape Portable Runtime (NSPR). -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998-2000 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either 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. -# -# ***** END LICENSE BLOCK ***** - -#! gmake - -MOD_DEPTH = ../../.. -topsrcdir = @top_srcdir@ -srcdir = @srcdir@ -VPATH = @srcdir@ - -include $(MOD_DEPTH)/config/autoconf.mk -include $(topsrcdir)/config/config.mk - -EXPORT_HEADERS = prgc.h -HEADERS = $(EXPORT_HEADERS) gcint.h - -RELEASE_HEADERS = $(EXPORT_HEADERS) -RELEASE_HEADERS_DEST = $(RELEASE_INCLUDE_DIR) - -include $(topsrcdir)/config/rules.mk - -export:: $(EXPORT_HEADERS) - $(INSTALL) -m 444 $(EXPORT_HEADERS) $(dist_includedir)
deleted file mode 100644 --- a/nsprpub/lib/msgc/include/gcint.h +++ /dev/null @@ -1,129 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * 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 the Netscape Portable Runtime (NSPR). - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either 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. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef gcint_h___ -#define gcint_h___ - -#include "prmon.h" -#include "prgc.h" - -extern PRLogModuleInfo *_pr_msgc_lm; -extern GCInfo _pr_gcData; - -#if defined(_WIN32) && !defined(DEBUG) -#undef INLINE_LOCK -#endif - -#ifdef INLINE_LOCK -#define LOCK_GC() EnterCriticalSection(&_pr_gcData.lock->mutexHandle) -#define UNLOCK_GC() LeaveCriticalSection(&_pr_gcData.lock->mutexHandle) -#else -#define LOCK_GC() PR_EnterMonitor(_pr_gcData.lock) -#define UNLOCK_GC() PR_ExitMonitor (_pr_gcData.lock) -#define GC_IS_LOCKED() (PR_GetMonitorEntryCount(_pr_gcData.lock)!=0) -#endif - -#ifdef DEBUG -#define _GCTRACE(x, y) if (_pr_gcData.flags & x) GCTrace y -#else -#define _GCTRACE(x, y) -#endif - -extern GCBeginGCHook *_pr_beginGCHook; -extern void *_pr_beginGCHookArg; -extern GCBeginGCHook *_pr_endGCHook; -extern void *_pr_endGCHookArg; - -extern GCBeginFinalizeHook *_pr_beginFinalizeHook; -extern void *_pr_beginFinalizeHookArg; -extern GCBeginFinalizeHook *_pr_endFinalizeHook; -extern void *_pr_endFinalizeHookArg; - -extern int _pr_do_a_dump; -extern FILE *_pr_dump_file; - -extern PRLogModuleInfo *_pr_gc_lm; - -/* -** Root finders. Root finders are used by the GC to find pointers into -** the GC heap that are not contained in the GC heap. -*/ -typedef struct RootFinderStr RootFinder; - -struct RootFinderStr { - RootFinder *next; - GCRootFinder *func; - char *name; - void *arg; -}; -extern RootFinder *_pr_rootFinders; - -typedef struct CollectorTypeStr { - GCType gctype; - PRUint32 flags; -} CollectorType; - -#define GC_MAX_TYPES 256 -extern CollectorType *_pr_collectorTypes; - -#define _GC_TYPE_BUSY 0x1 -#define _GC_TYPE_FINAL 0x2 -#define _GC_TYPE_WEAK 0x4 - -/* Slot in _pr_gcTypes used for free memory */ -#define FREE_MEMORY_TYPEIX 255 - -extern void _PR_InitGC(PRWord flags); -extern void _MD_InitGC(void); -extern void PR_CALLBACK _PR_ScanFinalQueue(void *notused); - -/* -** Grow the GC Heap. -*/ -extern void *_MD_GrowGCHeap(PRUint32 *sizep); - -/* -** Extend the GC Heap. -*/ -extern PRBool _MD_ExtendGCHeap(char *base, PRInt32 oldSize, PRInt32 newSize); - -/* -** Free a GC segment. -*/ -extern void _MD_FreeGCSegment(void *base, PRInt32 len); - -#endif /* gcint_h___ */
deleted file mode 100644 --- a/nsprpub/lib/msgc/include/prgc.h +++ /dev/null @@ -1,419 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * 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 the Netscape Portable Runtime (NSPR). - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either 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. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef prgc_h___ -#define prgc_h___ - -/* -** API to NSPR gc memory system. -*/ -#include "prtypes.h" -#include "prmon.h" -#include "prthread.h" -#include <stdio.h> - -#if defined(WIN16) -#define GCPTR __far -#else -#define GCPTR -#endif - - -PR_BEGIN_EXTERN_C - -/* -** Initialize the garbage collector. -** "flags" is the trace flags (see below). -** "initialHeapSize" is the initial size of the heap and may be zero -** if the default is desired. -** "segmentSize" is the size of each segment of memory added to the -** heap when the heap is grown. -*/ -PR_EXTERN(void) PR_InitGC( - PRWord flags, PRInt32 initialHeapSize, PRInt32 segmentSize, PRThreadScope scope); - -/* -** Shuts down gc and frees up all memory associated with it. -*/ -PR_EXTERN(void) PR_ShutdownGC(PRBool finalizeOnExit); - -/* -** This walk function will be called for every gc object in the -** heap as it is walked. If it returns non-zero, the walk is terminated. -*/ -typedef PRInt32 (*PRWalkFun)(void GCPTR* obj, void* data); - -/* -** GC Type record. This defines all of the GC operations used on a -** particular object type. These structures are passed to -** PR_RegisterType. -*/ -typedef struct GCType { - /* - ** Scan an object that is in the GC heap and call GCInfo.livePointer - ** on all of the pointers in it. If this slot is null then the object - ** won't be scanned (i.e. it has no embedded pointers). - */ - void (PR_CALLBACK *scan)(void GCPTR *obj); - - /* - ** Finalize an object that has no references. This is called by the - ** GC after it has determined where the object debris is but before - ** it has moved the debris to the logical "free list". The object is - ** marked alive for this call and removed from the list of objects - ** that need finalization (finalization only happens once for an - ** object). If this slot is null then the object doesn't need - ** finalization. - */ - void (PR_CALLBACK *finalize)(void GCPTR *obj); - - /* - ** Dump out an object during a PR_DumpGCHeap(). This is used as a - ** debugging tool. - */ - void (PR_CALLBACK *dump)(FILE *out, void GCPTR *obj, PRBool detailed, PRIntn indentLevel); - - /* - ** Add object to summary table. - */ - void (PR_CALLBACK *summarize)(void GCPTR *obj, PRUint32 bytes); - - /* - ** Free hook called by GC when the object is being freed. - */ - void (PR_CALLBACK *free)(void *obj); - - /* Weak pointer support: If the object has a weak pointer (Note: - at most one), this function is used to get the weak link's - offset from the start of the body of a gc object */ - PRUint32 (PR_CALLBACK *getWeakLinkOffset)(void *obj); - - /* Descriptive character for dumping this GCType */ - char kindChar; - - /* - ** Walker routine. This routine should apply fun(obj->ptr, data) - ** for every gc pointer within the object. - */ - PRInt32 (PR_CALLBACK *walk)(void GCPTR *obj, PRWalkFun fun, void* data); -} GCType; - -/* -** This data structure must be added as the hash table passed to -** the summarize method of GCType. -*/ -typedef struct PRSummaryEntry { - void* clazz; - PRInt32 instancesCount; - PRInt32 totalSize; -} PRSummaryEntry; - -/* -** This function pointer must be registered by users of nspr -** to produce the finally summary after all object in the -** heap have been visited. -*/ -typedef void (PR_CALLBACK *PRSummaryPrinter)(FILE *out, void* closure); - -PR_EXTERN(void) PR_CALLBACK PR_RegisterSummaryPrinter(PRSummaryPrinter fun, void* closure); - -typedef void PR_CALLBACK GCRootFinder(void *arg); -typedef void PR_CALLBACK GCBeginFinalizeHook(void *arg); -typedef void PR_CALLBACK GCEndFinalizeHook(void *arg); -typedef void PR_CALLBACK GCBeginGCHook(void *arg); -typedef void PR_CALLBACK GCEndGCHook(void *arg); - -typedef enum { PR_GCBEGIN, PR_GCEND } GCLockHookArg; - -typedef void PR_CALLBACK GCLockHookFunc(GCLockHookArg arg1, void *arg2); - -typedef struct GCLockHook GCLockHook; - -struct GCLockHook { - GCLockHookFunc* func; - void* arg; - GCLockHook* next; - GCLockHook* prev; -}; - - -/* -** Hooks which are called at the beginning and end of the GC process. -** The begin hooks are called before the root finding step. The hooks are -** called with threading disabled, so it is now allowed to re-enter the -** kernel. The end hooks are called after the gc has finished but before -** the finalizer has run. -*/ -PR_EXTERN(void) PR_CALLBACK PR_SetBeginGCHook(GCBeginGCHook *hook, void *arg); -PR_EXTERN(void) PR_CALLBACK PR_GetBeginGCHook(GCBeginGCHook **hook, void **arg); -PR_EXTERN(void) PR_CALLBACK PR_SetEndGCHook(GCBeginGCHook *hook, void *arg); -PR_EXTERN(void) PR_CALLBACK PR_GetEndGCHook(GCEndGCHook **hook, void **arg); - -/* -** Called before SuspendAll is called by dogc, so that GC thread can hold -** all the locks before hand to avoid any deadlocks -*/ - -/* -PR_EXTERN(void) PR_SetGCLockHook(GCLockHook *hook, void *arg); -PR_EXTERN(void) PR_GetGCLockHook(GCLockHook **hook, void **arg); -*/ - -PR_EXTERN(int) PR_RegisterGCLockHook(GCLockHookFunc *hook, void *arg); - -/* -** Hooks which are called at the beginning and end of the GC finalization -** process. After the GC has identified all of the dead objects in the -** heap, it looks for objects that need finalization. Before it calls the -** first finalization proc (see the GCType structure above) it calls the -** begin hook. When it has finalized the last object it calls the end -** hook. -*/ -PR_EXTERN(void) PR_SetBeginFinalizeHook(GCBeginFinalizeHook *hook, void *arg); -PR_EXTERN(void) PR_GetBeginFinalizeHook(GCBeginFinalizeHook **hook, void **arg); -PR_EXTERN(void) PR_SetEndFinalizeHook(GCBeginFinalizeHook *hook, void *arg); -PR_EXTERN(void) PR_GetEndFinalizeHook(GCEndFinalizeHook **hook, void **arg); - -/* -** Register a GC type. Return's the index into the GC internal type -** table. The returned value is passed to PR_AllocMemory. After the call, -** the "type" memory belongs to the GC (the caller must not free it or -** change it). -*/ -PR_EXTERN(PRInt32) PR_RegisterType(GCType *type); - -/* -** Register a root finder with the collector. The collector will call -** these functions to identify all of the roots before collection -** proceeds. "arg" is passed to the function when it is called. -*/ -PR_EXTERN(PRStatus) PR_RegisterRootFinder(GCRootFinder func, char *name, void *arg); - -/* -** Allocate some GC'able memory. The object must be at least bytes in -** size. The type index function for the object is specified. "flags" -** specifies some control flags. If PR_ALLOC_CLEAN is set then the memory -** is zero'd before being returned. If PR_ALLOC_DOUBLE is set then the -** allocated memory is double aligned. -** -** Any memory cell that you store a pointer to something allocated by -** this call must be findable by the GC. Use the PR_RegisterRootFinder to -** register new places where the GC will look for pointers into the heap. -** The GC already knows how to scan any NSPR threads or monitors. -*/ -PR_EXTERN(PRWord GCPTR *)PR_AllocMemory( - PRWord bytes, PRInt32 typeIndex, PRWord flags); -PR_EXTERN(PRWord GCPTR *)PR_AllocSimpleMemory( - PRWord bytes, PRInt32 typeIndex); - -/* -** This function can be used to cause PR_AllocMemory to always return -** NULL. This may be useful in low memory situations when we're trying to -** shutdown applets. -*/ -PR_EXTERN(void) PR_EnableAllocation(PRBool yesOrNo); - -/* flags bits */ -#define PR_ALLOC_CLEAN 0x1 -#define PR_ALLOC_DOUBLE 0x2 -#define PR_ALLOC_ZERO_HANDLE 0x4 /* XXX yes, it's a hack */ - -/* -** Force a garbage collection right now. Return when it completes. -*/ -PR_EXTERN(void) PR_GC(void); - -/* -** Force a finalization right now. Return when finalization has -** completed. Finalization completes when there are no more objects -** pending finalization. This does not mean there are no objects in the -** gc heap that will need finalization should a collection be done after -** this call. -*/ -PR_EXTERN(void) PR_ForceFinalize(void); - -/* -** Dump the GC heap out to the given file. This will stop the system dead -** in its tracks while it is occuring. -*/ -PR_EXTERN(void) PR_DumpGCHeap(FILE *out, PRBool detailed); - -/* -** Wrapper for PR_DumpGCHeap -*/ -PR_EXTERN(void) PR_DumpMemory(PRBool detailed); - -/* -** Dump summary of objects allocated. -*/ -PR_EXTERN(void) PR_DumpMemorySummary(void); - -/* -** Dump the application heaps. -*/ -PR_EXTERN(void) PR_DumpApplicationHeaps(void); - -/* -** Helper function used by dump routines to do the indentation in a -** consistent fashion. -*/ -PR_EXTERN(void) PR_DumpIndent(FILE *out, PRIntn indent); - -/* -** The GCInfo structure contains all of the GC state... -** -** busyMemory: -** The amount of GC heap memory that is busy at this instant. Busy -** doesn't mean alive, it just means that it has been -** allocated. Immediately after a collection busy means how much is -** alive. -** -** freeMemory: -** The amount of GC heap memory that is as yet unallocated. -** -** allocMemory: -** The sum of free and busy memory in the GC heap. -** -** maxMemory: -** The maximum size that the GC heap is allowed to grow. -** -** lowSeg: -** The lowest segment currently used in the GC heap. -** -** highSeg: -** The highest segment currently used in the GC heap. -** The lowSeg and highSeg members are used for a "quick test" of whether -** a pointer falls within the GC heap. [ see GC_IN_HEAP(...) ] -** -** lock: -** Monitor used for synchronization within the GC. -** -** finalizer: -** Thread in which the GC finalizer is running. -** -** liveBlock: -** Object scanning functions call through this function pointer to -** register a potential block of pointers with the collector. (This is -** currently not at all different than processRoot.) -** -** livePointer: -** Object scanning functions call through this function pointer to -** register a single pointer with the collector. -** -** processRootBlock: -** When a root finder identifies a root it should call through this -** function pointer so that the GC can process the root. The call takes -** a base address and count which the gc will examine for valid heap -** pointers. -** -** processRootPointer: -** When a root finder identifies a root it should call through this -** function pointer so that the GC can process the root. The call takes -** a single pointer value. -*/ -typedef struct GCInfoStr { - PRWord flags; /* trace flags (see below) */ - PRWord busyMemory; /* memory in use right now */ - PRWord freeMemory; /* memory free right now */ - PRWord allocMemory; /* sum of busy & free memory */ - PRWord maxMemory; /* max memory we are allowed to allocate */ - PRWord *lowSeg; /* lowest segment in the GC heap */ - PRWord *highSeg; /* highest segment in the GC heap */ - - PRMonitor *lock; - PRThread *finalizer; - - void (PR_CALLBACK *liveBlock)(void **base, PRInt32 count); - void (PR_CALLBACK *livePointer)(void *ptr); - void (PR_CALLBACK *processRootBlock)(void **base, PRInt32 count); - void (PR_CALLBACK *processRootPointer)(void *ptr); - FILE* dumpOutput; -#ifdef GCTIMINGHOOK - void (*gcTimingHook)(int32 gcTime); -#endif -} GCInfo; - -PR_EXTERN(GCInfo *) PR_GetGCInfo(void); -PR_EXTERN(PRBool) PR_GC_In_Heap(void GCPTR *object); - -/* -** Simple bounds check to see if a pointer is anywhere near the GC heap. -** Used to avoid calls to PR_ProcessRoot and GCInfo.livePointer by object -** scanning code. -*/ -#if !defined(XP_PC) || defined(_WIN32) -#define GC_IN_HEAP(_info, _p) (((PRWord*)(_p) >= (_info)->lowSeg) && \ - ((PRWord*)(_p) < (_info)->highSeg)) -#else -/* -** The simple bounds check, above, doesn't work in Win16, because we don't -** maintain: lowSeg == MIN(all segments) and highSeg == MAX(all segments). -** So we have to do a little better. -*/ -#define GC_IN_HEAP(_info, _p) PR_GC_In_Heap(_p) -#endif - -PR_EXTERN(PRWord) PR_GetObjectHeader(void *ptr); - -PR_EXTERN(PRWord) PR_SetObjectHeader(void *ptr, PRWord newUserBits); - -/************************************************************************/ - -/* Trace flags (passed to PR_InitGC or in environment GCLOG) */ -#define GC_TRACE 0x0001 -#define GC_ROOTS 0x0002 -#define GC_LIVE 0x0004 -#define GC_ALLOC 0x0008 -#define GC_MARK 0x0010 -#define GC_SWEEP 0x0020 -#define GC_DEBUG 0x0040 -#define GC_FINAL 0x0080 - -#if defined(DEBUG_kipp) || defined(DEBUG_warren) -#define GC_CHECK 0x0100 -#endif - -#ifdef DEBUG -#define GCTRACE(x, y) if (PR_GetGCInfo()->flags & x) GCTrace y -PR_EXTERN(void) GCTrace(char *fmt, ...); -#else -#define GCTRACE(x, y) -#endif - -PR_END_EXTERN_C - -#endif /* prgc_h___ */
deleted file mode 100644 --- a/nsprpub/lib/msgc/src/.cvsignore +++ /dev/null @@ -1,1 +0,0 @@ -Makefile
deleted file mode 100644 --- a/nsprpub/lib/msgc/src/Makefile.in +++ /dev/null @@ -1,93 +0,0 @@ -# -# ***** BEGIN LICENSE BLOCK ***** -# 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 the Netscape Portable Runtime (NSPR). -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998-2000 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either 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. -# -# ***** END LICENSE BLOCK ***** - -#! gmake - -MOD_DEPTH = ../../.. -topsrcdir = @top_srcdir@ -srcdir = @srcdir@ -VPATH = @srcdir@ - -include $(MOD_DEPTH)/config/autoconf.mk - -include $(topsrcdir)/config/config.mk - -INCLUDES = -I$(dist_includedir) -I../include - -CSRCS = prgcapi.c prmsgc.c - -ifeq ($(OS_ARCH),WINNT) -CSRCS += win32gc.c -else -ifeq ($(OS_ARCH),OS2) -CSRCS += os2gc.c -else -CSRCS += unixgc.c -endif -endif - -NSPR_VERSION = $(MOD_MAJOR_VERSION) - -EXTRA_LIBS = $(LIBNSPR) - -ifdef RESOLVE_LINK_SYMBOLS -EXTRA_LIBS += $(OS_LIBS) -endif - -ifeq ($(OS_ARCH), WINNT) -#RES=$(OBJDIR)/ds.res -#RESNAME=$(MOD_DEPTH)/pr/src/nspr.rc -#OS_LIBS = user32.lib -endif # WINNT - -LIBRARY_NAME = msgc -LIBRARY_VERSION = $(MOD_MAJOR_VERSION) - -RELEASE_LIBS = $(TARGETS) - -include $(topsrcdir)/config/rules.mk - -# -# The Client build wants the shared libraries in $(dist_bindir), -# so we also install them there. -# - -export:: $(TARGETS) - $(INSTALL) -m 444 $(TARGETS) $(dist_libdir) -ifdef SHARED_LIBRARY - $(INSTALL) -m 444 $(SHARED_LIBRARY) $(dist_bindir) -endif
deleted file mode 100644 --- a/nsprpub/lib/msgc/src/os2gc.c +++ /dev/null @@ -1,83 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * 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 the Netscape Portable Runtime (NSPR). - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either 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. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * GC related routines - * - */ -#include "prlog.h" - -#include <stdlib.h> - -/* Leave a bit of room for any malloc header bytes... */ -#define MAX_SEGMENT_SIZE (65536L - 4096L) - -/************************************************************************/ -/* -** Machine dependent GC Heap management routines: -** _MD_GrowGCHeap -*/ -/************************************************************************/ -void _MD_InitGC() {} - -void *_MD_GrowGCHeap(PRUint32 *sizep) -{ - void *addr; - - if ( *sizep > MAX_SEGMENT_SIZE ) - { - *sizep = MAX_SEGMENT_SIZE; - } - - addr = malloc((size_t)*sizep); - return addr; -} - - -PRBool _MD_ExtendGCHeap(char *base, PRInt32 oldSize, PRInt32 newSize) { - /* Not sure about this. Todd? */ - return PR_FALSE; -} - - -void _MD_FreeGCSegment(void *base, PRInt32 len) -{ - if (base) - { - free(base); - } -}
deleted file mode 100644 --- a/nsprpub/lib/msgc/src/prgcapi.c +++ /dev/null @@ -1,330 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * 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 the Netscape Portable Runtime (NSPR). - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either 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. - * - * ***** END LICENSE BLOCK ***** */ - -#include <stdarg.h> -#include <string.h> -#include <stdio.h> -#include "prenv.h" -#include "prmem.h" -#include "prmon.h" -#include "prlog.h" -#include "prthread.h" -#include "private/pprthred.h" -#include "gcint.h" - -/* -** Generic GC implementation independent code for the NSPR GC -*/ - -RootFinder *_pr_rootFinders; - -CollectorType *_pr_collectorTypes; - -/* GC State information */ -GCInfo _pr_gcData; - -GCBeginGCHook *_pr_beginGCHook; -void *_pr_beginGCHookArg; -GCBeginGCHook *_pr_endGCHook; -void *_pr_endGCHookArg; - -GCBeginFinalizeHook *_pr_beginFinalizeHook; -void *_pr_beginFinalizeHookArg; -GCBeginFinalizeHook *_pr_endFinalizeHook; -void *_pr_endFinalizeHookArg; - -FILE *_pr_dump_file; -int _pr_do_a_dump; -GCLockHook *_pr_GCLockHook; - -extern PRLogModuleInfo *_pr_msgc_lm; - -/************************************************************************/ - -static PRStatus PR_CALLBACK -pr_ScanOneThread(PRThread* t, void** addr, PRUword count, void* closure) -{ - _pr_gcData.processRootBlock(addr, count); - return PR_SUCCESS; -} - -/* -** Scan all of the threads C stack's and registers, looking for "root" -** pointers into the GC heap. These are the objects that the GC cannot -** move and are considered "live" by the GC. Caller has stopped all of -** the threads from running. -*/ -static void PR_CALLBACK ScanThreads(void *arg) -{ - PR_ScanStackPointers(pr_ScanOneThread, arg); -} - -/************************************************************************/ - -PR_IMPLEMENT(GCInfo *) PR_GetGCInfo(void) -{ - return &_pr_gcData; -} - - -PR_IMPLEMENT(PRInt32) PR_RegisterType(GCType *t) -{ - CollectorType *ct, *ect; - int rv = -1; - - LOCK_GC(); - ct = &_pr_collectorTypes[0]; - ect = &_pr_collectorTypes[FREE_MEMORY_TYPEIX]; - for (; ct < ect; ct++) { - if (ct->flags == 0) { - ct->gctype = *t; - ct->flags = _GC_TYPE_BUSY; - if (0 != ct->gctype.finalize) { - ct->flags |= _GC_TYPE_FINAL; - } - if (0 != ct->gctype.getWeakLinkOffset) { - ct->flags |= _GC_TYPE_WEAK; - } - rv = ct - &_pr_collectorTypes[0]; - break; - } - } - UNLOCK_GC(); - return rv; -} - -PR_IMPLEMENT(PRStatus) PR_RegisterRootFinder( - GCRootFinder f, char *name, void *arg) -{ - RootFinder *rf = PR_NEWZAP(RootFinder); - if (rf) { - rf->func = f; - rf->name = name; - rf->arg = arg; - - LOCK_GC(); - rf->next = _pr_rootFinders; - _pr_rootFinders = rf; - UNLOCK_GC(); - return PR_SUCCESS; - } - return PR_FAILURE; -} - - -PR_IMPLEMENT(int) PR_RegisterGCLockHook(GCLockHookFunc* f, void *arg) -{ - - GCLockHook *rf = 0; - - rf = (GCLockHook*) calloc(1, sizeof(GCLockHook)); - if (rf) { - rf->func = f; - rf->arg = arg; - - LOCK_GC(); - /* first dummy node */ - if (! _pr_GCLockHook) { - _pr_GCLockHook = (GCLockHook*) calloc(1, sizeof(GCLockHook)); - _pr_GCLockHook->next = _pr_GCLockHook; - _pr_GCLockHook->prev = _pr_GCLockHook; - } - - rf->next = _pr_GCLockHook; - rf->prev = _pr_GCLockHook->prev; - _pr_GCLockHook->prev->next = rf; - _pr_GCLockHook->prev = rf; - UNLOCK_GC(); - return 0; - } - return -1; -} - -/* -PR_IMPLEMENT(void) PR_SetGCLockHook(GCLockHook *hook, void *arg) -{ - LOCK_GC(); - _pr_GCLockHook = hook; - _pr_GCLockHookArg2 = arg; - UNLOCK_GC(); -} - -PR_IMPLEMENT(void) PR_GetGCLockHook(GCLockHook **hook, void **arg) -{ - LOCK_GC(); - *hook = _pr_GCLockHook; - *arg = _pr_GCLockHookArg2; - UNLOCK_GC(); -} -*/ - - -PR_IMPLEMENT(void) PR_SetBeginGCHook(GCBeginGCHook *hook, void *arg) -{ - LOCK_GC(); - _pr_beginGCHook = hook; - _pr_beginGCHookArg = arg; - UNLOCK_GC(); -} - -PR_IMPLEMENT(void) PR_GetBeginGCHook(GCBeginGCHook **hook, void **arg) -{ - LOCK_GC(); - *hook = _pr_beginGCHook; - *arg = _pr_beginGCHookArg; - UNLOCK_GC(); -} - -PR_IMPLEMENT(void) PR_SetEndGCHook(GCEndGCHook *hook, void *arg) -{ - LOCK_GC(); - _pr_endGCHook = hook; - _pr_endGCHookArg = arg; - UNLOCK_GC(); -} - -PR_IMPLEMENT(void) PR_GetEndGCHook(GCEndGCHook **hook, void **arg) -{ - LOCK_GC(); - *hook = _pr_endGCHook; - *arg = _pr_endGCHookArg; - UNLOCK_GC(); -} - -PR_IMPLEMENT(void) PR_SetBeginFinalizeHook(GCBeginFinalizeHook *hook, void *arg) -{ - LOCK_GC(); - _pr_beginFinalizeHook = hook; - _pr_beginFinalizeHookArg = arg; - UNLOCK_GC(); -} - -PR_IMPLEMENT(void) PR_GetBeginFinalizeHook(GCBeginFinalizeHook **hook, - void **arg) -{ - LOCK_GC(); - *hook = _pr_beginFinalizeHook; - *arg = _pr_beginFinalizeHookArg; - UNLOCK_GC(); -} - -PR_IMPLEMENT(void) PR_SetEndFinalizeHook(GCEndFinalizeHook *hook, void *arg) -{ - LOCK_GC(); - _pr_endFinalizeHook = hook; - _pr_endFinalizeHookArg = arg; - UNLOCK_GC(); -} - -PR_IMPLEMENT(void) PR_GetEndFinalizeHook(GCEndFinalizeHook **hook, void **arg) -{ - LOCK_GC(); - *hook = _pr_endFinalizeHook; - *arg = _pr_endFinalizeHookArg; - UNLOCK_GC(); -} - -#ifdef DEBUG -#include "prprf.h" - -PR_IMPLEMENT(void) GCTrace(char *fmt, ...) -{ - va_list ap; - char buf[400]; - - va_start(ap, fmt); - PR_vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - PR_LOG(_pr_msgc_lm, PR_LOG_ALWAYS, ("%s", buf)); -} -#endif - -void _PR_InitGC(PRWord flags) -{ - static char firstTime = 1; - - if (!firstTime) return; - firstTime = 0; - - _MD_InitGC(); - - if (flags == 0) { - char *ev = PR_GetEnv("GCLOG"); - if (ev && ev[0]) { - flags = atoi(ev); - } - } - _pr_gcData.flags = flags; - - _pr_gcData.lock = PR_NewMonitor(); - - _pr_collectorTypes = (CollectorType*) PR_CALLOC(256 * sizeof(CollectorType)); - - PR_RegisterRootFinder(ScanThreads, "scan threads", 0); - PR_RegisterRootFinder(_PR_ScanFinalQueue, "scan final queue", 0); -} - -extern void pr_FinalizeOnExit(void); - -#ifdef DEBUG -#ifdef GC_STATS -PR_PUBLIC_API(void) PR_PrintGCAllocStats(void); -#endif -#endif - -PR_IMPLEMENT(void) -PR_ShutdownGC(PRBool finalizeOnExit) -{ - /* first finalize all the objects in the heap */ - if (finalizeOnExit) { - pr_FinalizeOnExit(); - } - -#ifdef DEBUG -#ifdef GC_STATS - PR_PrintGCAllocStats(); -#endif /* GC_STATS */ -#endif /* DEBUG */ - - /* then the chance for any future allocations */ - - /* finally delete the gc heap */ - - /* write me */ -} - -/******************************************************************************/
deleted file mode 100644 --- a/nsprpub/lib/msgc/src/prmsgc.c +++ /dev/null @@ -1,3320 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * 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 the Netscape Portable Runtime (NSPR). - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either 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. - * - * ***** END LICENSE BLOCK ***** */ - -#include <string.h> -#include <stddef.h> -#include <stdarg.h> -#include <time.h> - -#ifdef WIN32 -#include <windef.h> -#include <winbase.h> -#endif - -#include "prclist.h" -#include "prbit.h" - -#include "prtypes.h" -#include "prenv.h" -#include "prgc.h" -#include "prthread.h" -#include "prlog.h" -#include "prlong.h" -#include "prinrval.h" -#include "prprf.h" -#include "gcint.h" - -#include "private/pprthred.h" - -typedef void (*PRFileDumper)(FILE *out, PRBool detailed); - -PR_EXTERN(void) -PR_DumpToFile(char* filename, char* msg, PRFileDumper dump, PRBool detailed); - -/* -** Mark&sweep garbage collector. Supports objects that require -** finalization, objects that can have a single weak link, and special -** objects that require care during sweeping. -*/ - -PRLogModuleInfo *_pr_msgc_lm; -PRLogModuleInfo* GC; - -static PRInt32 _pr_pageShift; -static PRInt32 _pr_pageSize; - -#ifdef DEBUG -#define GCMETER -#endif -#ifdef DEBUG_jwz -# undef GCMETER -#endif /* 1 */ - -#ifdef GCMETER -#define METER(x) x -#else -#define METER(x) -#endif - -/* -** Make this constant bigger to reduce the amount of recursion during -** garbage collection. -*/ -#define MAX_SCAN_Q 100L - -#if defined(XP_PC) && !defined(WIN32) -#define MAX_SEGS 400L -#define MAX_SEGMENT_SIZE (65536L - 4096L) -#define SEGMENT_SIZE (65536L - 4096L) -#define MAX_ALLOC_SIZE (65536L - 4096L) -#else -#define MAX_SEGS 400L -#define MAX_SEGMENT_SIZE (2L * 256L * 1024L) -#define SEGMENT_SIZE (1L * 256L * 1024L) -#define MAX_ALLOC_SIZE (4L * 1024L * 1024L) -#endif - -/* - * The highest value that can fit into a signed integer. This - * is used to prevent overflow of allocation size in alloc routines. - */ - -#define MAX_INT ((1UL << (PR_BITS_PER_INT - 1)) - 1) - -/* - * On 32-bit machines, only 22 bits are used in the cibx integer to - * store size since 8 bits of the integer are used to store type, and - * of the remainder, 2 are user defined. Max allocation size = 2^22 -1 - */ - -#define MAX_ALLOC ( (1L << (PR_BYTES_PER_WORD_LOG2 + WORDS_BITS )) -1) - -/* The minimum percentage of free heap space after a collection. If - the amount of free space doesn't meet this criteria then we will - attempt to grow the heap */ -#define MIN_FREE_THRESHOLD_AFTER_GC 20L - -static PRInt32 segmentSize = SEGMENT_SIZE; - -static PRInt32 collectorCleanupNeeded; - -#ifdef GCMETER -PRUint32 _pr_gcMeter; - -#define _GC_METER_STATS 0x01L -#define _GC_METER_GROWTH 0x02L -#define _GC_METER_FREE_LIST 0x04L -#endif - -/************************************************************************/ - -#define LINEAR_BIN_EXPONENT 5 -#define NUM_LINEAR_BINS ((PRUint32)1 << LINEAR_BIN_EXPONENT) -#define FIRST_LOG_BIN (NUM_LINEAR_BINS - LINEAR_BIN_EXPONENT) - -/* Each free list bin holds a chunk of memory sized from - 2^n to (2^(n+1))-1 inclusive. */ -#define NUM_BINS (FIRST_LOG_BIN + 32) - -/* - * Find the bin number for a given size (in bytes). This does not round up as - * values from 2^n to (2^(n+1))-1 share the same bin. - */ -#define InlineBinNumber(_bin,_bytes) \ -{ \ - PRUint32 _t, _n = (PRUint32) _bytes / 4; \ - if (_n < NUM_LINEAR_BINS) { \ - _bin = _n; \ - } else { \ - _bin = FIRST_LOG_BIN; \ - if ((_t = (_n >> 16)) != 0) { _bin += 16; _n = _t; } \ - if ((_t = (_n >> 8)) != 0) { _bin += 8; _n = _t; } \ - if ((_t = (_n >> 4)) != 0) { _bin += 4; _n = _t; } \ - if ((_t = (_n >> 2)) != 0) { _bin += 2; _n = _t; } \ - if ((_n >> 1) != 0) _bin++; \ - } \ -} - -#define BIG_ALLOC 16384L - -#define MIN_FREE_CHUNK_BYTES ((PRInt32)sizeof(GCFreeChunk)) - -/* Note: fix code in PR_AllocMemory if you change the size of GCFreeChunk - so that it zeros the right number of words */ -typedef struct GCFreeChunk { - struct GCFreeChunk *next; - struct GCSeg *segment; - PRInt32 chunkSize; -} GCFreeChunk; - -typedef struct GCSegInfo { - struct GCSegInfo *next; - char *base; - char *limit; - PRWord *hbits; - int fromMalloc; -} GCSegInfo; - -typedef struct GCSeg { - char *base; - char *limit; - PRWord *hbits; - GCSegInfo *info; -} GCSeg; - -#ifdef GCMETER -typedef struct GCMeter { - PRInt32 allocBytes; - PRInt32 wastedBytes; - PRInt32 numFreeChunks; - PRInt32 skippedFreeChunks; -} GCMeter; -static GCMeter meter; -#endif - -/* -** There is one of these for each segment of GC'able memory. -*/ -static GCSeg segs[MAX_SEGS]; -static GCSegInfo *freeSegs; -static GCSeg* lastInHeap; -static int nsegs; - -static GCFreeChunk *bins[NUM_BINS]; -static PRInt32 minBin; -static PRInt32 maxBin; - -/* -** Scan Q used to avoid deep recursion when scanning live objects for -** heap pointers -*/ -typedef struct GCScanQStr { - PRWord *q[MAX_SCAN_Q]; - int queued; -} GCScanQ; - -static GCScanQ *pScanQ; - -#ifdef GCMETER -PRInt32 _pr_maxScanDepth; -PRInt32 _pr_scanDepth; -#endif - -/* -** Keeps track of the number of bytes allocated via the BigAlloc() -** allocator. When the number of bytes allocated, exceeds the -** BIG_ALLOC_GC_SIZE, then a GC will occur before the next allocation -** is done... -*/ -#define BIG_ALLOC_GC_SIZE (4*SEGMENT_SIZE) -static PRWord bigAllocBytes = 0; - -/* -** There is one GC header word in front of each GC allocated object. We -** use it to contain information about the object (what TYPEIX to use for -** scanning it, how big it is, it's mark status, and if it's a root). -*/ -#define TYPEIX_BITS 8L -#define WORDS_BITS 20L -#define MAX_CBS (1L << GC_TYPEIX_BITS) -#define MAX_WORDS (1L << GC_WORDS_BITS) -#define TYPEIX_SHIFT 24L -#define MAX_TYPEIX ((1L << TYPEIX_BITS) - 1L) -#define TYPEIX_MASK PR_BITMASK(TYPEIX_BITS) -#define WORDS_SHIFT 2L -#define WORDS_MASK PR_BITMASK(WORDS_BITS) -#define MARK_BIT 1L -#define FINAL_BIT 2L - -/* Two bits per object header are reserved for the user of the memory - system to store information into. */ -#define GC_USER_BITS_SHIFT 22L -#define GC_USER_BITS 0x00c00000L - -#define MAKE_HEADER(_cbix,_words) \ - ((PRWord) (((unsigned long)(_cbix) << TYPEIX_SHIFT) \ - | ((unsigned long)(_words) << WORDS_SHIFT))) - -#define GET_TYPEIX(_h) \ - (((PRUword)(_h) >> TYPEIX_SHIFT) & 0xff) - -#define MARK(_sp,_p) \ - (((PRWord *)(_p))[0] |= MARK_BIT) -#define IS_MARKED(_sp,_p) \ - (((PRWord *)(_p))[0] & MARK_BIT) -#define OBJ_BYTES(_h) \ - (((PRInt32) (_h) & 0x003ffffcL) << (PR_BYTES_PER_WORD_LOG2-2L)) - -#define GC_GET_USER_BITS(_h) (((_h) & GC_USER_BITS) >> GC_USER_BITS_SHIFT) - -/************************************************************************/ - -/* -** Mark the start of an object in a segment. Note that we mark the header -** word (which we always have), not the data word (which we may not have -** for empty objects). -** XXX tune: put subtract of _sp->base into _sp->hbits pointer? -*/ -#define SET_HBIT(_sp,_ph) \ - SET_BIT((_sp)->hbits, (((PRWord*)(_ph)) - ((PRWord*) (_sp)->base))) - -#define CLEAR_HBIT(_sp,_ph) \ - CLEAR_BIT((_sp)->hbits, (((PRWord*)(_ph)) - ((PRWord*) (_sp)->base))) - -#define IS_HBIT(_sp,_ph) \ - TEST_BIT((_sp)->hbits, (((PRWord*)(_ph)) - ((PRWord*) (_sp)->base))) - -/* -** Given a pointer into this segment, back it up until we are at the -** start of the object the pointer points into. Each heap segment has a -** bitmap that has one bit for each word of the objects it contains. The -** bit's are set for the firstword of an object, and clear for it's other -** words. -*/ -static PRWord *FindObject(GCSeg *sp, PRWord *p) -{ - PRWord *base; - - /* Align p to it's proper boundary before we start fiddling with it */ - p = (PRWord*) ((PRWord)p & ~(PR_BYTES_PER_WORD-1L)); - - base = (PRWord *) sp->base; - do { - if (IS_HBIT(sp, p)) { - return (p); - } - p--; - } while ( p >= base ); - - /* Heap is corrupted! */ - _GCTRACE(GC_TRACE, ("ERROR: The heap is corrupted!!! aborting now!")); - abort(); - return NULL; -} - -/************************************************************************/ -#if !defined(XP_PC) || defined(XP_OS2) -#define OutputDebugString(msg) -#endif - -#define IN_SEGMENT(_sp, _p) \ - ((((char *)(_p)) >= (_sp)->base) && \ - (((char *)(_p)) < (_sp)->limit)) - -static GCSeg *InHeap(void *p) -{ - GCSeg *sp, *esp; - - if (lastInHeap && IN_SEGMENT(lastInHeap, p)) { - return lastInHeap; - } - - sp = segs; - esp = segs + nsegs; - for (; sp < esp; sp++) { - if (IN_SEGMENT(sp, p)) { - lastInHeap = sp; - return sp; - } - } - return 0; -} - -/* -** Grow the heap by allocating another segment. Fudge the requestedSize -** value to try to pre-account for the HBITS. -*/ -static GCSeg* DoGrowHeap(PRInt32 requestedSize, PRBool exactly) -{ - GCSeg *sp; - GCSegInfo *segInfo; - GCFreeChunk *cp; - char *base; - PRWord *hbits; - PRInt32 nhbytes, nhbits; - PRUint32 allocSize; - - if (nsegs == MAX_SEGS) { - /* No room for more segments */ - return 0; - } - - segInfo = (GCSegInfo*) PR_MALLOC(sizeof(GCSegInfo)); -#ifdef DEBUG - { - char str[256]; - sprintf(str, "[1] Allocated %ld bytes at %p\n", - (long) sizeof(GCSegInfo), segInfo); - OutputDebugString(str); - } -#endif - if (!segInfo) { - return 0; - } - - /* Get more memory from the OS */ - if (exactly) { - allocSize = requestedSize; - base = (char *) PR_MALLOC(requestedSize); - } else { - allocSize = requestedSize; - allocSize = (allocSize + _pr_pageSize - 1L) >> _pr_pageShift; - allocSize <<= _pr_pageShift; - base = (char*)_MD_GrowGCHeap(&allocSize); - } - if (!base) { - PR_DELETE(segInfo); - return 0; - } - - nhbits = (PRInt32)( - (allocSize + PR_BYTES_PER_WORD - 1L) >> PR_BYTES_PER_WORD_LOG2); - nhbytes = ((nhbits + PR_BITS_PER_WORD - 1L) >> PR_BITS_PER_WORD_LOG2) - * sizeof(PRWord); - - /* Get bitmap memory from malloc heap */ - hbits = (PRWord *) PR_CALLOC((PRUint32)nhbytes); - if (!hbits) { - /* Loser! */ - PR_DELETE(segInfo); - if (exactly) { - PR_DELETE(base); - } else { - /* XXX do something about this */ - /* _MD_FreeGCSegment(base, allocSize); */ - } - return 0; - } - - /* - ** Setup new segment. - */ - sp = &segs[nsegs++]; - segInfo->base = sp->base = base; - segInfo->limit = sp->limit = base + allocSize; - segInfo->hbits = sp->hbits = hbits; - sp->info = segInfo; - segInfo->fromMalloc = exactly; - memset(base, 0, allocSize); - -#ifdef GCMETER - if (_pr_gcMeter & _GC_METER_GROWTH) { - fprintf(stderr, "[GC: new segment base=%p size=%ld]\n", - sp->base, (long) allocSize); - } -#endif - - _pr_gcData.allocMemory += allocSize; - _pr_gcData.freeMemory += allocSize; - - if (!exactly) { - PRInt32 bin; - - /* Put free memory into a freelist bin */ - cp = (GCFreeChunk *) base; - cp->segment = sp; - cp->chunkSize = allocSize; - InlineBinNumber(bin, allocSize) - cp->next = bins[bin]; - bins[bin] = cp; - if (bin < minBin) minBin = bin; - if (bin > maxBin) maxBin = bin; - } else { - /* - ** When exactly allocating the entire segment is given over to a - ** single object to prevent fragmentation - */ - } - - if (!_pr_gcData.lowSeg) { - _pr_gcData.lowSeg = (PRWord*) sp->base; - _pr_gcData.highSeg = (PRWord*) sp->limit; - } else { - if ((PRWord*)sp->base < _pr_gcData.lowSeg) { - _pr_gcData.lowSeg = (PRWord*) sp->base; - } - if ((PRWord*)sp->limit > _pr_gcData.highSeg) { - _pr_gcData.highSeg = (PRWord*) sp->limit; - } - } - - /* - ** Get rid of the GC pointer in case it shows up in some uninitialized - ** local stack variable later (while scanning the C stack looking for - ** roots). - */ - memset(&base, 0, sizeof(base)); /* optimizers beware */ - - PR_LOG(_pr_msgc_lm, PR_LOG_WARNING, ("grow heap: total gc memory now %d", - _pr_gcData.allocMemory)); - - return sp; -} - -#ifdef USE_EXTEND_HEAP -static PRBool ExtendHeap(PRInt32 requestedSize) { - GCSeg* sp; - PRUint32 allocSize; - PRInt32 oldSize, newSize; - PRInt32 newHBits, newHBytes; - PRInt32 oldHBits, oldHBytes; - PRWord* hbits; - GCFreeChunk* cp; - PRInt32 bin; - - /* Can't extend nothing */ - if (nsegs == 0) return PR_FALSE; - - /* Round up requested size to the size of a page */ - allocSize = (PRUint32) requestedSize; - allocSize = (allocSize + _pr_pageSize - 1L) >> _pr_pageShift; - allocSize <<= _pr_pageShift; - - /* Malloc some memory for the new hbits array */ - sp = segs; - oldSize = sp->limit - sp->base; - newSize = oldSize + allocSize; - newHBits = (newSize + PR_BYTES_PER_WORD - 1L) >> PR_BYTES_PER_WORD_LOG2; - newHBytes = ((newHBits + PR_BITS_PER_WORD - 1L) >> PR_BITS_PER_WORD_LOG2) - * sizeof(PRWord); - hbits = (PRWord*) PR_MALLOC(newHBytes); - if (0 == hbits) return PR_FALSE; - - /* Attempt to extend the last segment by the desired amount */ - if (_MD_ExtendGCHeap(sp->base, oldSize, newSize)) { - oldHBits = (oldSize + PR_BYTES_PER_WORD - 1L) >> PR_BYTES_PER_WORD_LOG2; - oldHBytes = ((oldHBits + PR_BITS_PER_WORD - 1L) >> PR_BITS_PER_WORD_LOG2) - * sizeof(PRWord); - - /* Copy hbits from old memory into new memory */ - memset(hbits, 0, newHBytes); - memcpy(hbits, sp->hbits, oldHBytes); - PR_DELETE(sp->hbits); - memset(sp->base + oldSize, 0, allocSize); - - /* Adjust segment state */ - sp->limit += allocSize; - sp->hbits = hbits; - sp->info->limit = sp->limit; - sp->info->hbits = hbits; - - /* Put free memory into a freelist bin */ - cp = (GCFreeChunk *) (sp->base + oldSize); - cp->segment = sp; - cp->chunkSize = allocSize; - InlineBinNumber(bin, allocSize) - cp->next = bins[bin]; - bins[bin] = cp; - if (bin < minBin) minBin = bin; - if (bin > maxBin) maxBin = bin; - - /* Prevent a pointer that points to the free memory from showing - up on the call stack later on */ - memset(&cp, 0, sizeof(cp)); - - /* Update heap brackets and counters */ - if ((PRWord*)sp->limit > _pr_gcData.highSeg) { - _pr_gcData.highSeg = (PRWord*) sp->limit; - } - _pr_gcData.allocMemory += allocSize; - _pr_gcData.freeMemory += allocSize; - - return PR_TRUE; - } - PR_DELETE(hbits); - return PR_FALSE; -} -#endif /* USE_EXTEND_HEAP */ - -static GCSeg *GrowHeapExactly(PRInt32 requestedSize) -{ - GCSeg *sp = DoGrowHeap(requestedSize, PR_TRUE); - return sp; -} - -static PRBool GrowHeap(PRInt32 requestedSize) -{ - void *p; -#ifdef USE_EXTEND_HEAP - if (ExtendHeap(requestedSize)) { - return PR_TRUE; - } -#endif - p = DoGrowHeap(requestedSize, PR_FALSE); - return (p != NULL ? PR_TRUE : PR_FALSE); -} - -/* -** Release a segment when it is entirely free. -*/ -static void ShrinkGCHeap(GCSeg *sp) -{ -#ifdef GCMETER - if (_pr_gcMeter & _GC_METER_GROWTH) { - fprintf(stderr, "[GC: free segment base=%p size=%ld]\n", - sp->base, (long) (sp->limit - sp->base)); - } -#endif - - /* - * Put segment onto free seginfo list (we can't call free right now - * because we have the GC lock and all of the other threads are - * suspended; if one of them has the malloc lock we would deadlock) - */ - sp->info->next = freeSegs; - freeSegs = sp->info; - collectorCleanupNeeded = 1; - _pr_gcData.allocMemory -= sp->limit - sp->base; - if (sp == lastInHeap) lastInHeap = 0; - - /* Squish out disappearing segment from segment table */ - --nsegs; - if ((sp - segs) != nsegs) { - *sp = segs[nsegs]; - } else { - sp->base = 0; - sp->limit = 0; - sp->hbits = 0; - sp->info = 0; - } - - /* Recalculate the lowSeg and highSeg values */ - _pr_gcData.lowSeg = (PRWord*) segs[0].base; - _pr_gcData.highSeg = (PRWord*) segs[0].limit; - for (sp = segs; sp < &segs[nsegs]; sp++) { - if ((PRWord*)sp->base < _pr_gcData.lowSeg) { - _pr_gcData.lowSeg = (PRWord*) sp->base; - } - if ((PRWord*)sp->limit > _pr_gcData.highSeg) { - _pr_gcData.highSeg = (PRWord*) sp->limit; - } - } -} - -static void FreeSegments(void) -{ - GCSegInfo *si; - - while (0 != freeSegs) { - LOCK_GC(); - si = freeSegs; - if (si) { - freeSegs = si->next; - } - UNLOCK_GC(); - - if (!si) { - break; - } - PR_DELETE(si->base); - PR_DELETE(si->hbits); - PR_DELETE(si); - } -} - -/************************************************************************/ - -void ScanScanQ(GCScanQ *iscan) -{ - PRWord *p; - PRWord **pp; - PRWord **epp; - GCScanQ nextQ, *scan, *next, *temp; - CollectorType *ct; - - if (!iscan->queued) return; - - _GCTRACE(GC_MARK, ("begin scanQ @ 0x%x (%d)", iscan, iscan->queued)); - scan = iscan; - next = &nextQ; - while (scan->queued) { - _GCTRACE(GC_MARK, ("continue scanQ @ 0x%x (%d)", scan, scan->queued)); - /* - * Set pointer to current scanQ so that _pr_gcData.livePointer - * can find it. - */ - pScanQ = next; - next->queued = 0; - - /* Now scan the scan Q */ - pp = scan->q; - epp = &scan->q[scan->queued]; - scan->queued = 0; - while (pp < epp) { - p = *pp++; - ct = &_pr_collectorTypes[GET_TYPEIX(p[0])]; - PR_ASSERT(0 != ct->gctype.scan); - /* Scan object ... */ - (*ct->gctype.scan)(p + 1); - } - - /* Exchange pointers so that we scan next */ - temp = scan; - scan = next; - next = temp; - } - - pScanQ = iscan; - PR_ASSERT(nextQ.queued == 0); - PR_ASSERT(iscan->queued == 0); -} - -/* -** Called during root finding step to identify "root" pointers into the -** GC heap. First validate if it is a real heap pointer and then mark the -** object being pointed to and add it to the scan Q for eventual -** scanning. -*/ -static void PR_CALLBACK ProcessRootBlock(void **base, PRInt32 count) -{ - GCSeg *sp; - PRWord *p0, *p, h, tix, *low, *high, *segBase; - CollectorType *ct; -#ifdef DEBUG - void **base0 = base; -#endif - - low = _pr_gcData.lowSeg; - high = _pr_gcData.highSeg; - while (--count >= 0) { - p0 = (PRWord*) *base++; - if (p0 < low) continue; /* below gc heap */ - if (p0 >= high) continue; /* above gc heap */ - /* NOTE: inline expansion of InHeap */ - /* Find segment */ - sp = lastInHeap; - if (!sp || !IN_SEGMENT(sp,p0)) { - GCSeg *esp; - sp = segs; - esp = segs + nsegs; - for (; sp < esp; sp++) { - if (IN_SEGMENT(sp, p0)) { - lastInHeap = sp; - goto find_object; - } - } - continue; - } - - find_object: - /* NOTE: Inline expansion of FindObject */ - /* Align p to it's proper boundary before we start fiddling with it */ - p = (PRWord*) ((PRWord)p0 & ~(PR_BYTES_PER_WORD-1L)); - segBase = (PRWord *) sp->base; - do { - if (IS_HBIT(sp, p)) { - goto winner; - } - p--; - } while (p >= segBase); - - /* - ** We have a pointer into the heap, but it has no header - ** bit. This means that somehow the very first object in the heap - ** doesn't have a header. This is impossible so when debugging - ** lets abort. - */ -#ifdef DEBUG - PR_Abort(); -#endif - - winner: - h = p[0]; - if ((h & MARK_BIT) == 0) { -#ifdef DEBUG - _GCTRACE(GC_ROOTS, - ("root 0x%p (%d) base0=%p off=%d", - p, OBJ_BYTES(h), base0, (base-1) - base0)); -#endif - - /* Mark the root we just found */ - p[0] = h | MARK_BIT; - - /* - * See if object we just found needs scanning. It must - * have a scan function to be placed on the scanQ. - */ - tix = (PRWord)GET_TYPEIX(h); - ct = &_pr_collectorTypes[tix]; - if (0 == ct->gctype.scan) { - continue; - } - - /* - ** Put a pointer onto the scan Q. We use the scan Q to avoid - ** deep recursion on the C call stack. Objects are added to - ** the scan Q until the scan Q fills up. At that point we - ** make a call to ScanScanQ which proceeds to scan each of - ** the objects in the Q. This limits the recursion level by a - ** large amount though the stack frames get larger to hold - ** the GCScanQ's. - */ - pScanQ->q[pScanQ->queued++] = p; - if (pScanQ->queued == MAX_SCAN_Q) { - METER(_pr_scanDepth++); - ScanScanQ(pScanQ); - } - } - } -} - -static void PR_CALLBACK ProcessRootPointer(void *ptr) -{ - PRWord *p0, *p, h, tix, *segBase; - GCSeg* sp; - CollectorType *ct; - - p0 = (PRWord*) ptr; - - if (p0 < _pr_gcData.lowSeg) return; /* below gc heap */ - if (p0 >= _pr_gcData.highSeg) return; /* above gc heap */ - - /* NOTE: inline expansion of InHeap */ - /* Find segment */ - sp = lastInHeap; - if (!sp || !IN_SEGMENT(sp,p0)) { - GCSeg *esp; - sp = segs; - esp = segs + nsegs; - for (; sp < esp; sp++) { - if (IN_SEGMENT(sp, p0)) { - lastInHeap = sp; - goto find_object; - } - } - return; - } - - find_object: - /* NOTE: Inline expansion of FindObject */ - /* Align p to it's proper boundary before we start fiddling with it */ - p = (PRWord*) ((PRWord)p0 & ~(BYTES_PER_WORD-1L)); - segBase = (PRWord *) sp->base; - do { - if (IS_HBIT(sp, p)) { - goto winner; - } - p--; - } while (p >= segBase); - - /* - ** We have a pointer into the heap, but it has no header - ** bit. This means that somehow the very first object in the heap - ** doesn't have a header. This is impossible so when debugging - ** lets abort. - */ -#ifdef DEBUG - PR_Abort(); -#endif - - winner: - h = p[0]; - if ((h & MARK_BIT) == 0) { -#ifdef DEBUG - _GCTRACE(GC_ROOTS, ("root 0x%p (%d)", p, OBJ_BYTES(h))); -#endif - - /* Mark the root we just found */ - p[0] = h | MARK_BIT; - - /* - * See if object we just found needs scanning. It must - * have a scan function to be placed on the scanQ. - */ - tix = (PRWord)GET_TYPEIX(h); - ct = &_pr_collectorTypes[tix]; - if (0 == ct->gctype.scan) { - return; - } - - /* - ** Put a pointer onto the scan Q. We use the scan Q to avoid - ** deep recursion on the C call stack. Objects are added to - ** the scan Q until the scan Q fills up. At that point we - ** make a call to ScanScanQ which proceeds to scan each of - ** the objects in the Q. This limits the recursion level by a - ** large amount though the stack frames get larger to hold - ** the GCScanQ's. - */ - pScanQ->q[pScanQ->queued++] = p; - if (pScanQ->queued == MAX_SCAN_Q) { - METER(_pr_scanDepth++); - ScanScanQ(pScanQ); - } - } -} - -/************************************************************************/ - -/* -** Empty the freelist for each segment. This is done to make sure that -** the root finding step works properly (otherwise, if we had a pointer -** into a free section, we might not find its header word and abort in -** FindObject) -*/ -static void EmptyFreelists(void) -{ - GCFreeChunk *cp; - GCFreeChunk *next; - GCSeg *sp; - PRWord *p; - PRInt32 chunkSize; - PRInt32 bin; - - /* - ** Run over the freelist and make all of the free chunks look like - ** object debris. - */ - for (bin = 0; bin <= NUM_BINS-1; bin++) { - cp = bins[bin]; - while (cp) { - next = cp->next; - sp = cp->segment; - chunkSize = cp->chunkSize >> BYTES_PER_WORD_LOG2; - p = (PRWord*) cp; - PR_ASSERT(chunkSize != 0); - p[0] = MAKE_HEADER(FREE_MEMORY_TYPEIX, chunkSize); - SET_HBIT(sp, p); - cp = next; - } - bins[bin] = 0; - } - minBin = NUM_BINS - 1; - maxBin = 0; -} - -typedef struct GCBlockEnd { - PRInt32 check; -#ifdef GC_CHECK - PRInt32 requestedBytes; -#endif -#ifdef GC_STATS - PRInt32 bin; - PRInt64 allocTime; -#endif -#ifdef GC_TRACEROOTS - PRInt32 traceGeneration; -#endif -} GCBlockEnd; - -#define PR_BLOCK_END 0xDEADBEEF - -/************************************************************************/ - -#ifdef GC_STATS - -typedef struct GCStat { - PRInt32 nallocs; - double allocTime; - double allocTimeVariance; - PRInt32 nfrees; - double lifetime; - double lifetimeVariance; -} GCStat; - -#define GCSTAT_BINS NUM_BINS - -GCStat gcstats[GCSTAT_BINS]; - -#define GCLTFREQ_BINS NUM_BINS - -PRInt32 gcltfreq[GCSTAT_BINS][GCLTFREQ_BINS]; - -#include <math.h> - -static char* -pr_GetSizeString(PRUint32 size) -{ - char* sizeStr; - if (size < 1024) - sizeStr = PR_smprintf("<= %ld", size); - else if (size < 1024 * 1024) - sizeStr = PR_smprintf("<= %ldk", size / 1024); - else - sizeStr = PR_smprintf("<= %ldM", size / (1024 * 1024)); - return sizeStr; -} - -static void -pr_FreeSizeString(char *sizestr) -{ - PR_smprintf_free(sizestr); -} - - -static void -pr_PrintGCAllocStats(FILE* out) -{ - PRInt32 i, j; - _PR_DebugPrint(out, "\n--Allocation-Stats-----------------------------------------------------------"); - _PR_DebugPrint(out, "\n--Obj-Size----Count-----Avg-Alloc-Time-----------Avg-Lifetime---------%%Freed-\n"); - for (i = 0; i < GCSTAT_BINS; i++) { - GCStat stat = gcstats[i]; - double allocTimeMean = 0.0, allocTimeVariance = 0.0, lifetimeMean = 0.0, lifetimeVariance = 0.0; - PRUint32 maxSize = (1 << i); - char* sizeStr; - if (stat.nallocs != 0.0) { - allocTimeMean = stat.allocTime / stat.nallocs; - allocTimeVariance = fabs(stat.allocTimeVariance / stat.nallocs - allocTimeMean * allocTimeMean); - } - if (stat.nfrees != 0.0) { - lifetimeMean = stat.lifetime / stat.nfrees; - lifetimeVariance = fabs(stat.lifetimeVariance / stat.nfrees - lifetimeMean * lifetimeMean); - } - sizeStr = pr_GetSizeString(maxSize); - _PR_DebugPrint(out, "%10s %8lu %10.3f +- %10.3f %10.3f +- %10.3f (%2ld%%)\n", - sizeStr, stat.nallocs, - allocTimeMean, sqrt(allocTimeVariance), - lifetimeMean, sqrt(lifetimeVariance), - (stat.nallocs ? (stat.nfrees * 100 / stat.nallocs) : 0)); - pr_FreeSizeString(sizeStr); - } - _PR_DebugPrint(out, "--Lifetime-Frequency-Counts----------------------------------------------------\n"); - _PR_DebugPrint(out, "size\\cnt"); - for (j = 0; j < GCLTFREQ_BINS; j++) { - _PR_DebugPrint(out, "\t%lu", j); - } - _PR_DebugPrint(out, "\n"); - for (i = 0; i < GCSTAT_BINS; i++) { - PRInt32* freqs = gcltfreq[i]; - _PR_DebugPrint(out, "%lu", (1 << i)); - for (j = 0; j < GCLTFREQ_BINS; j++) { - _PR_DebugPrint(out, "\t%lu", freqs[j]); - } - _PR_DebugPrint(out, "\n"); - } - _PR_DebugPrint(out, "-------------------------------------------------------------------------------\n"); -} - -PR_PUBLIC_API(void) -PR_PrintGCAllocStats(void) -{ - pr_PrintGCAllocStats(stderr); -} - -#endif /* GC_STATS */ - -/************************************************************************/ - -/* -** Sweep a segment, cleaning up all of the debris. Coallese the debris -** into GCFreeChunk's which are added to the freelist bins. -*/ -static PRBool SweepSegment(GCSeg *sp) -{ - PRWord h, tix; - PRWord *p; - PRWord *np; - PRWord *limit; - GCFreeChunk *cp; - PRInt32 bytes, chunkSize, segmentSize, totalFree; - CollectorType *ct; - PRInt32 bin; - - /* - ** Now scan over the segment's memory in memory order, coallescing - ** all of the debris into a FreeChunk list. - */ - totalFree = 0; - segmentSize = sp->limit - sp->base; - p = (PRWord *) sp->base; - limit = (PRWord *) sp->limit; - PR_ASSERT(segmentSize > 0); - while (p < limit) { - chunkSize = 0; - cp = (GCFreeChunk *) p; - - /* Attempt to coallesce any neighboring free objects */ - for (;;) { - PR_ASSERT(IS_HBIT(sp, p) != 0); - h = p[0]; - bytes = OBJ_BYTES(h); - PR_ASSERT(bytes != 0); - np = (PRWord *) ((char *)p + bytes); - tix = (PRWord)GET_TYPEIX(h); - if ((h & MARK_BIT) && (tix != FREE_MEMORY_TYPEIX)) { -#ifdef DEBUG - if (tix != FREE_MEMORY_TYPEIX) { - PR_ASSERT(_pr_collectorTypes[tix].flags != 0); - } -#endif - p[0] = h & ~(MARK_BIT|FINAL_BIT); - _GCTRACE(GC_SWEEP, ("busy 0x%x (%d)", p, bytes)); - break; - } - _GCTRACE(GC_SWEEP, ("free 0x%x (%d)", p, bytes)); - - /* Found a free object */ -#ifdef GC_STATS - { - PRInt32 userSize = bytes - sizeof(GCBlockEnd); - GCBlockEnd* end = (GCBlockEnd*)((char*)p + userSize); - if (userSize >= 0 && end->check == PR_BLOCK_END) { - PRInt64 now = PR_Now(); - double nowd, delta; - PRInt32 freq; - LL_L2D(nowd, now); - delta = nowd - end->allocTime; - gcstats[end->bin].nfrees++; - gcstats[end->bin].lifetime += delta; - gcstats[end->bin].lifetimeVariance += delta * delta; - - InlineBinNumber(freq, delta); - gcltfreq[end->bin][freq]++; - - end->check = 0; - } - } -#endif - CLEAR_HBIT(sp, p); - ct = &_pr_collectorTypes[tix]; - if (0 != ct->gctype.free) { - (*ct->gctype.free)(p + 1); - } - chunkSize = chunkSize + bytes; - if (np == limit) { - /* Found the end of heap */ - break; - } - PR_ASSERT(np < limit); - p = np; - } - - if (chunkSize) { - _GCTRACE(GC_SWEEP, ("free chunk 0x%p to 0x%p (%d)", - cp, (char*)cp + chunkSize - 1, chunkSize)); - if (chunkSize < MIN_FREE_CHUNK_BYTES) { - /* Lost a tiny fragment until (maybe) next time */ - METER(meter.wastedBytes += chunkSize); - p = (PRWord *) cp; - chunkSize >>= BYTES_PER_WORD_LOG2; - PR_ASSERT(chunkSize != 0); - p[0] = MAKE_HEADER(FREE_MEMORY_TYPEIX, chunkSize); - SET_HBIT(sp, p); - } else { - /* See if the chunk constitutes the entire segment */ - if (chunkSize == segmentSize) { - /* Free up the segment right now */ - if (sp->info->fromMalloc) { - ShrinkGCHeap(sp); - return PR_TRUE; - } - } - - /* Put free chunk into the appropriate bin */ - cp->segment = sp; - cp->chunkSize = chunkSize; - InlineBinNumber(bin, chunkSize) - cp->next = bins[bin]; - bins[bin] = cp; - if (bin < minBin) minBin = bin; - if (bin > maxBin) maxBin = bin; - - /* Zero swept memory now */ - memset(cp+1, 0, chunkSize - sizeof(*cp)); - METER(meter.numFreeChunks++); - totalFree += chunkSize; - } - } - - /* Advance to next object */ - p = np; - } - - PR_ASSERT(totalFree <= segmentSize); - - _pr_gcData.freeMemory += totalFree; - _pr_gcData.busyMemory += (sp->limit - sp->base) - totalFree; - return PR_FALSE; -} - -/************************************************************************/ - -/* This is a list of all the objects that are finalizable. This is not - the list of objects that are awaiting finalization because they - have been collected. */ -PRCList _pr_finalizeableObjects; - -/* This is the list of objects that are awaiting finalization because - they have been collected. */ -PRCList _pr_finalQueue; - -/* Each object that requires finalization has one of these objects - allocated as well. The GCFinal objects are put on the - _pr_finalizeableObjects list until the object is collected at which - point the GCFinal object is moved to the _pr_finalQueue */ -typedef struct GCFinalStr { - PRCList links; - PRWord *object; -} GCFinal; - -/* Find pointer to GCFinal struct from the list linkaged embedded in it */ -#define FinalPtr(_qp) \ - ((GCFinal*) ((char*) (_qp) - offsetof(GCFinal,links))) - -static GCFinal *AllocFinalNode(void) -{ - return PR_NEWZAP(GCFinal); -} - -static void FreeFinalNode(GCFinal *node) -{ - PR_DELETE(node); -} - -/* -** Prepare for finalization. At this point in the GC cycle we have -** identified all of the live objects. For each object on the -** _pr_finalizeableObjects list see if the object is alive or dead. If -** it's dead, resurrect it and move it from the _pr_finalizeableObjects -** list to the _pr_finalQueue (object's only get finalized once). -** -** Once _pr_finalizeableObjects has been processed we can finish the -** GC and free up memory and release the threading lock. After that we -** can invoke the finalization procs for each object that is on the -** _pr_finalQueue. -*/ -static void PrepareFinalize(void) -{ - PRCList *qp; - GCFinal *fp; - PRWord h; - PRWord *p; - void (PR_CALLBACK *livePointer)(void *ptr); -#ifdef DEBUG - CollectorType *ct; -#endif - - /* This must be done under the same lock that the finalizer uses */ - PR_ASSERT( GC_IS_LOCKED() ); - - /* cache this ptr */ - livePointer = _pr_gcData.livePointer; - - /* - * Pass #1: Identify objects that are to be finalized, set their - * FINAL_BIT. - */ - qp = _pr_finalizeableObjects.next; - while (qp != &_pr_finalizeableObjects) { - fp = FinalPtr(qp); - qp = qp->next; - h = fp->object[0]; /* Grab header word */ - if (h & MARK_BIT) { - /* Object is already alive */ - continue; - } - -#ifdef DEBUG - ct = &_pr_collectorTypes[GET_TYPEIX(h)]; - PR_ASSERT((0 != ct->flags) && (0 != ct->gctype.finalize)); -#endif - fp->object[0] |= FINAL_BIT; - _GCTRACE(GC_FINAL, ("moving %p (%d) to finalQueue", - fp->object, OBJ_BYTES(h))); - } - - /* - * Pass #2: For each object that is going to be finalized, move it to - * the finalization queue and resurrect it - */ - qp = _pr_finalizeableObjects.next; - while (qp != &_pr_finalizeableObjects) { - fp = FinalPtr(qp); - qp = qp->next; - h = fp->object[0]; /* Grab header word */ - if ((h & FINAL_BIT) == 0) { - continue; - } - - /* Resurrect the object and any objects it refers to */ - p = &fp->object[1]; - (*livePointer)(p); - PR_REMOVE_LINK(&fp->links); - PR_APPEND_LINK(&fp->links, &_pr_finalQueue); - } -} - -/* -** Scan the finalQ, marking each and every object on it live. This is -** necessary because we might do a GC before objects that are on the -** final queue get finalized. Since there are no other references -** (otherwise they would be on the final queue), we have to scan them. -** This really only does work if we call the GC before the finalizer -** has a chance to do its job. -*/ -extern void PR_CALLBACK _PR_ScanFinalQueue(void *notused) -{ - PRCList *qp; - GCFinal *fp; - PRWord *p; - void ( PR_CALLBACK *livePointer)(void *ptr); - - livePointer = _pr_gcData.livePointer; - qp = _pr_finalQueue.next; - while (qp != &_pr_finalQueue) { - fp = FinalPtr(qp); - _GCTRACE(GC_FINAL, ("marking 0x%x (on final queue)", fp->object)); - p = &fp->object[1]; - (*livePointer)(p); - qp = qp->next; - } -} - -void PR_CALLBACK FinalizerLoop(void* unused) -{ - GCFinal *fp; - PRWord *p; - PRWord h, tix; - CollectorType *ct; - - LOCK_GC(); - for (;;) { - p = 0; h = 0; /* don't let the gc find these pointers */ - while (PR_CLIST_IS_EMPTY(&_pr_finalQueue)) - PR_Wait(_pr_gcData.lock, PR_INTERVAL_NO_TIMEOUT); - - _GCTRACE(GC_FINAL, ("begin finalization")); - while (_pr_finalQueue.next != &_pr_finalQueue) { - fp = FinalPtr(_pr_finalQueue.next); - PR_REMOVE_LINK(&fp->links); - p = fp->object; - - h = p[0]; /* Grab header word */ - tix = (PRWord)GET_TYPEIX(h); - ct = &_pr_collectorTypes[tix]; - _GCTRACE(GC_FINAL, ("finalize 0x%x (%d)", p, OBJ_BYTES(h))); - - /* - ** Give up the GC lock so that other threads can allocate memory - ** while this finalization method is running. Get it back - ** afterwards so that the list remains thread safe. - */ - UNLOCK_GC(); - FreeFinalNode(fp); - PR_ASSERT(ct->gctype.finalize != 0); - (*ct->gctype.finalize)(p + 1); - LOCK_GC(); - } - _GCTRACE(GC_FINAL, ("end finalization")); - PR_Notify(_pr_gcData.lock); - } -} - -static void NotifyFinalizer(void) -{ - if (!PR_CLIST_IS_EMPTY(&_pr_finalQueue)) { - PR_ASSERT( GC_IS_LOCKED() ); - PR_Notify(_pr_gcData.lock); - } -} - -void _PR_CreateFinalizer(PRThreadScope scope) -{ - if (!_pr_gcData.finalizer) { - _pr_gcData.finalizer = PR_CreateThreadGCAble(PR_SYSTEM_THREAD, - FinalizerLoop, 0, - PR_PRIORITY_LOW, scope, - PR_UNJOINABLE_THREAD, 0); - - if (_pr_gcData.finalizer == NULL) - /* We are doomed if we can't start the finalizer */ - PR_Abort(); - - } -} - -void pr_FinalizeOnExit(void) -{ -#ifdef DEBUG_warren - OutputDebugString("### Doing finalize-on-exit pass\n"); -#endif - PR_ForceFinalize(); -#ifdef DEBUG_warren - OutputDebugString("### Finalize-on-exit complete. Dumping object left to memory.out\n"); - PR_DumpMemorySummary(); - PR_DumpMemory(PR_TRUE); -#endif -} - -PR_IMPLEMENT(void) PR_ForceFinalize() -{ - LOCK_GC(); - NotifyFinalizer(); - while (!PR_CLIST_IS_EMPTY(&_pr_finalQueue)) { - PR_ASSERT( GC_IS_LOCKED() ); - (void) PR_Wait(_pr_gcData.lock, PR_INTERVAL_NO_TIMEOUT); - } - UNLOCK_GC(); - - /* XXX I don't know how to make it wait (yet) */ -} - -/************************************************************************/ - -typedef struct GCWeakStr { - PRCList links; - PRWord *object; -} GCWeak; - -/* -** Find pointer to GCWeak struct from the list linkaged embedded in it -*/ -#define WeakPtr(_qp) \ - ((GCWeak*) ((char*) (_qp) - offsetof(GCWeak,links))) - -PRCList _pr_weakLinks = PR_INIT_STATIC_CLIST(&_pr_weakLinks); -PRCList _pr_freeWeakLinks = PR_INIT_STATIC_CLIST(&_pr_freeWeakLinks); - -#define WEAK_FREELIST_ISEMPTY() (_pr_freeWeakLinks.next == &_pr_freeWeakLinks) - -/* - * Keep objects referred to by weak free list alive until they can be - * freed - */ -static void PR_CALLBACK ScanWeakFreeList(void *notused) { - PRCList *qp = _pr_freeWeakLinks.next; - while (qp != &_pr_freeWeakLinks) { - GCWeak *wp = WeakPtr(qp); - qp = qp->next; - ProcessRootPointer(wp->object); - } -} - -/* - * Empty the list of weak objects. Note that we can't call malloc/free - * under the cover of the GC's lock (we might deadlock), so transfer the - * list of free objects to a local list under the cover of the lock, then - * release the lock and free up the memory. - */ -static void EmptyWeakFreeList(void) { - if (!WEAK_FREELIST_ISEMPTY()) { - PRCList *qp, freeLinks; - - PR_INIT_CLIST(&freeLinks); - - /* - * Transfer list of free weak links from the global list to a - * local list. - */ - LOCK_GC(); - qp = _pr_freeWeakLinks.next; - while (qp != &_pr_freeWeakLinks) { - GCWeak *wp = WeakPtr(qp); - qp = qp->next; - PR_REMOVE_LINK(&wp->links); - PR_APPEND_LINK(&wp->links, &freeLinks); - } - UNLOCK_GC(); - - /* Free up storage now */ - qp = freeLinks.next; - while (qp != &freeLinks) { - GCWeak *wp = WeakPtr(qp); - qp = qp->next; - PR_DELETE(wp); - } - } -} - -/* - * Allocate a new weak node in the weak objects list - */ -static GCWeak *AllocWeakNode(void) -{ - EmptyWeakFreeList(); - return PR_NEWZAP(GCWeak); -} - -static void FreeWeakNode(GCWeak *node) -{ - PR_DELETE(node); -} - -/* - * Check the weak links for validity. Note that the list of weak links is - * itself weak (otherwise we would keep the objects with weak links in - * them alive forever). As we scan the list check the weak link object - * itself and if it's not marked then remove it from the weak link list - */ -static void CheckWeakLinks(void) { - PRCList *qp; - GCWeak *wp; - PRWord *p, h, tix, **weakPtrAddress; - CollectorType *ct; - PRUint32 offset; - - qp = _pr_weakLinks.next; - while (qp != &_pr_weakLinks) { - wp = WeakPtr(qp); - qp = qp->next; - if ((p = wp->object) != 0) { - h = p[0]; /* Grab header word */ - if ((h & MARK_BIT) == 0) { - /* - * The object that has a weak link is no longer being - * referenced; remove it from the chain and let it get - * swept away by the GC. Transfer it to the list of - * free weak links for later freeing. - */ - PR_REMOVE_LINK(&wp->links); - PR_APPEND_LINK(&wp->links, &_pr_freeWeakLinks); - collectorCleanupNeeded = 1; - continue; - } - - /* Examine a live object that contains weak links */ - tix = GET_TYPEIX(h); - ct = &_pr_collectorTypes[tix]; - PR_ASSERT((ct->flags != 0) && (ct->gctype.getWeakLinkOffset != 0)); - if (0 == ct->gctype.getWeakLinkOffset) { - /* Heap is probably corrupted */ - continue; - } - - /* Get offset into the object of where the weak pointer is */ - offset = (*ct->gctype.getWeakLinkOffset)(p + 1); - - /* Check the weak pointer */ - weakPtrAddress = (PRWord**)((char*)(p + 1) + offset); - p = *weakPtrAddress; - if (p != 0) { - h = p[-1]; /* Grab header word for pointed to object */ - if (h & MARK_BIT) { - /* Object can't be dead */ - continue; - } - /* Break weak link to an object that is about to be swept */ - *weakPtrAddress = 0; - } - } - } -} - -/************************************************************************/ - -/* -** Perform a complete garbage collection -*/ - -extern GCLockHook *_pr_GCLockHook; - -static void dogc(void) -{ - RootFinder *rf; - GCLockHook* lhook; - - GCScanQ scanQ; - GCSeg *sp, *esp; - PRInt64 start, end, diff; - -#if defined(GCMETER) || defined(GCTIMINGHOOK) - start = PR_Now(); -#endif - - /* - ** Stop all of the other threads. This also promises to capture the - ** register state of each and every thread - */ - - /* - ** Get all the locks that will be need during GC after SuspendAll. We - ** cannot make any locking/library calls after SuspendAll. - */ - if (_pr_GCLockHook) { - for (lhook = _pr_GCLockHook->next; lhook != _pr_GCLockHook; - lhook = lhook->next) { - (*lhook->func)(PR_GCBEGIN, lhook->arg); - } - } - - PR_SuspendAll(); - -#ifdef GCMETER - /* Reset meter info */ - if (_pr_gcMeter & _GC_METER_STATS) { - fprintf(stderr, - "[GCSTATS: busy:%ld skipped:%ld, alloced:%ld+wasted:%ld+free:%ld = total:%ld]\n", - (long) _pr_gcData.busyMemory, - (long) meter.skippedFreeChunks, - (long) meter.allocBytes, - (long) meter.wastedBytes, - (long) _pr_gcData.freeMemory, - (long) _pr_gcData.allocMemory); - } - memset(&meter, 0, sizeof(meter)); -#endif - - PR_LOG(_pr_msgc_lm, PR_LOG_ALWAYS, ("begin mark phase; busy=%d free=%d total=%d", - _pr_gcData.busyMemory, _pr_gcData.freeMemory, - _pr_gcData.allocMemory)); - - if (_pr_beginGCHook) { - (*_pr_beginGCHook)(_pr_beginGCHookArg); - } - - /* - ** Initialize scanQ to all zero's so that root finder doesn't walk - ** over it... - */ - memset(&scanQ, 0, sizeof(scanQ)); - pScanQ = &scanQ; - - /******************************************/ - /* MARK PHASE */ - - EmptyFreelists(); - - /* Find root's */ - PR_LOG(_pr_msgc_lm, PR_LOG_WARNING, - ("begin mark phase; busy=%d free=%d total=%d", - _pr_gcData.busyMemory, _pr_gcData.freeMemory, - _pr_gcData.allocMemory)); - METER(_pr_scanDepth = 0); - rf = _pr_rootFinders; - while (rf) { - _GCTRACE(GC_ROOTS, ("finding roots in %s", rf->name)); - (*rf->func)(rf->arg); - rf = rf->next; - } - _GCTRACE(GC_ROOTS, ("done finding roots")); - - /* Scan remaining object's that need scanning */ - ScanScanQ(&scanQ); - PR_ASSERT(pScanQ == &scanQ); - PR_ASSERT(scanQ.queued == 0); - METER({ - if (_pr_scanDepth > _pr_maxScanDepth) { - _pr_maxScanDepth = _pr_scanDepth; - } - }); - - /******************************************/ - /* FINALIZATION PHASE */ - - METER(_pr_scanDepth = 0); - PrepareFinalize(); - - /* Scan any resurrected objects found during finalization */ - ScanScanQ(&scanQ); - PR_ASSERT(pScanQ == &scanQ); - PR_ASSERT(scanQ.queued == 0); - METER({ - if (_pr_scanDepth > _pr_maxScanDepth) { - _pr_maxScanDepth = _pr_scanDepth; - } - }); - pScanQ = 0; - - /******************************************/ - /* SWEEP PHASE */ - - /* - ** Sweep each segment clean. While we are at it, figure out which - ** segment has the most free space and make that the current segment. - */ - CheckWeakLinks(); - _GCTRACE(GC_SWEEP, ("begin sweep phase")); - _pr_gcData.freeMemory = 0; - _pr_gcData.busyMemory = 0; - sp = segs; - esp = sp + nsegs; - while (sp < esp) { - if (SweepSegment(sp)) { - /* - ** Segment is now free and has been replaced with a different - ** segment object. - */ - esp--; - continue; - } - sp++; - } - -#if defined(GCMETER) || defined(GCTIMINGHOOK) - end = PR_Now(); -#endif -#ifdef GCMETER - LL_SUB(diff, end, start); - PR_LOG(GC, PR_LOG_ALWAYS, - ("done; busy=%d free=%d chunks=%d total=%d time=%lldms", - _pr_gcData.busyMemory, _pr_gcData.freeMemory, - meter.numFreeChunks, _pr_gcData.allocMemory, diff)); - if (_pr_gcMeter & _GC_METER_FREE_LIST) { - PRIntn bin; - fprintf(stderr, "Freelist bins:\n"); - for (bin = 0; bin < NUM_BINS; bin++) { - GCFreeChunk *cp = bins[bin]; - while (cp != NULL) { - fprintf(stderr, "%3d: %p %8ld\n", - bin, cp, (long) cp->chunkSize); - cp = cp->next; - } - } - } -#endif - - if (_pr_endGCHook) { - (*_pr_endGCHook)(_pr_endGCHookArg); - } - - /* clear the running total of the bytes allocated via BigAlloc() */ - bigAllocBytes = 0; - - /* And resume multi-threading */ - PR_ResumeAll(); - - if (_pr_GCLockHook) { - for (lhook = _pr_GCLockHook->prev; lhook != _pr_GCLockHook; - lhook = lhook->prev) { - (*lhook->func)(PR_GCEND, lhook->arg); - } - } - - /* Kick finalizer */ - NotifyFinalizer(); -#ifdef GCTIMINGHOOK - if (_pr_gcData.gcTimingHook) { - PRInt32 time; - LL_SUB(diff, end, start); - LL_L2I(time, diff); - _pr_gcData.gcTimingHook(time); - } -#endif -} - -PR_IMPLEMENT(void) PR_GC(void) -{ - LOCK_GC(); - dogc(); - UNLOCK_GC(); - - EmptyWeakFreeList(); -} - -/******************************************************************************* - * Heap Walker - ******************************************************************************/ - -/* -** This is yet another disgusting copy of the body of ProcessRootPointer -** (the other being ProcessRootBlock), but we're not leveraging a single -** function in their cases in interest of performance (avoiding the function -** call). -*/ -static PRInt32 PR_CALLBACK -pr_ConservativeWalkPointer(void* ptr, PRWalkFun walkRootPointer, void* data) -{ - PRWord *p0, *p, *segBase; - GCSeg* sp; - - p0 = (PRWord*) ptr; - - if (p0 < _pr_gcData.lowSeg) return 0; /* below gc heap */ - if (p0 >= _pr_gcData.highSeg) return 0; /* above gc heap */ - - /* NOTE: inline expansion of InHeap */ - /* Find segment */ - sp = lastInHeap; - if (!sp || !IN_SEGMENT(sp,p0)) { - GCSeg *esp; - sp = segs; - esp = segs + nsegs; - for (; sp < esp; sp++) { - if (IN_SEGMENT(sp, p0)) { - lastInHeap = sp; - goto find_object; - } - } - return 0; - } - - find_object: - /* NOTE: Inline expansion of FindObject */ - /* Align p to it's proper boundary before we start fiddling with it */ - p = (PRWord*) ((PRWord)p0 & ~(BYTES_PER_WORD-1L)); - segBase = (PRWord *) sp->base; - do { - if (IS_HBIT(sp, p)) { - goto winner; - } - p--; - } while (p >= segBase); - - /* - ** We have a pointer into the heap, but it has no header - ** bit. This means that somehow the very first object in the heap - ** doesn't have a header. This is impossible so when debugging - ** lets abort. - */ -#ifdef DEBUG - PR_Abort(); -#endif - return 0; - - winner: - return walkRootPointer(p, data); -} - -static PRInt32 PR_CALLBACK -pr_ConservativeWalkBlock(void **base, PRInt32 count, - PRWalkFun walkRootPointer, void* data) -{ - PRWord *p0; - while (--count >= 0) { - PRInt32 status; - p0 = (PRWord*) *base++; - status = pr_ConservativeWalkPointer(p0, walkRootPointer, data); - if (status) return status; - } - return 0; -} - -/******************************************************************************/ - -typedef void (*WalkObject_t)(FILE *out, GCType* tp, PRWord *obj, - size_t bytes, PRBool detailed); -typedef void (*WalkUnknown_t)(FILE *out, GCType* tp, PRWord tix, PRWord *p, - size_t bytes, PRBool detailed); -typedef void (*WalkFree_t)(FILE *out, PRWord *p, size_t size, PRBool detailed); -typedef void (*WalkSegment_t)(FILE *out, GCSeg* sp, PRBool detailed); - -static void -pr_WalkSegment(FILE* out, GCSeg* sp, PRBool detailed, - char* enterMsg, char* exitMsg, - WalkObject_t walkObject, WalkUnknown_t walkUnknown, WalkFree_t walkFree) -{ - PRWord *p, *limit; - - p = (PRWord *) sp->base; - limit = (PRWord *) sp->limit; - if (enterMsg) - fprintf(out, enterMsg, p); - while (p < limit) - { - if (IS_HBIT(sp, p)) /* Is this an object header? */ - { - PRWord h = p[0]; - PRWord tix = GET_TYPEIX(h); - size_t bytes = OBJ_BYTES(h); - PRWord* np = (PRWord*) ((char*)p + bytes); - - GCType* tp = &_pr_collectorTypes[tix].gctype; - if ((0 != tp) && walkObject) - walkObject(out, tp, p, bytes, detailed); - else if (walkUnknown) - walkUnknown(out, tp, tix, p, bytes, detailed); - p = np; - } - else - { - /* Must be a freelist item */ - size_t size = ((GCFreeChunk*)p)->chunkSize; - if (walkFree) - walkFree(out, p, size, detailed); - p = (PRWord*)((char*)p + size); - } - } - if (p != limit) - fprintf(out, "SEGMENT OVERRUN (end should be at 0x%p)\n", limit); - if (exitMsg) - fprintf(out, exitMsg, p); -} - -static void -pr_WalkSegments(FILE *out, WalkSegment_t walkSegment, PRBool detailed) -{ - GCSeg *sp = segs; - GCSeg *esp; - - LOCK_GC(); - esp = sp + nsegs; - while (sp < esp) - { - walkSegment(out, sp, detailed); - sp++; - } - fprintf(out, "End of heap\n"); - UNLOCK_GC(); -} - -/******************************************************************************* - * Heap Dumper - ******************************************************************************/ - -PR_IMPLEMENT(void) -PR_DumpIndent(FILE *out, int indent) -{ - while (--indent >= 0) - fprintf(out, " "); -} - -static void -PR_DumpHexWords(FILE *out, PRWord *p, int nWords, - int indent, int nWordsPerLine) -{ - while (nWords > 0) - { - int i; - - PR_DumpIndent(out, indent); - i = nWordsPerLine; - if (i > nWords) - i = nWords; - nWords -= i; - while (i--) - { - fprintf(out, "0x%.8lX", (long) *p++); - if (i) - fputc(' ', out); - } - fputc('\n', out); - } -} - -static void PR_CALLBACK -pr_DumpObject(FILE *out, GCType* tp, PRWord *p, - size_t bytes, PRBool detailed) -{ - char kindChar = tp->kindChar; - fprintf(out, "0x%p: 0x%.6lX %c ", - p, (long) bytes, kindChar ? kindChar : '?'); - if (tp->dump) - (*tp->dump)(out, (void*) (p + 1), detailed, 0); - if (detailed) - PR_DumpHexWords(out, p, bytes>>2, 22, 4); -} - -static void PR_CALLBACK -pr_DumpUnknown(FILE *out, GCType* tp, PRWord tix, PRWord *p, - size_t bytes, PRBool detailed) -{ - char kindChar = tp->kindChar; - fprintf(out, "0x%p: 0x%.6lX %c ", - p, (long) bytes, kindChar ? kindChar : '?'); - fprintf(out, "UNKNOWN KIND %ld\n", (long) tix); - if (detailed) - PR_DumpHexWords(out, p, bytes>>2, 22, 4); -} - -static void PR_CALLBACK -pr_DumpFree(FILE *out, PRWord *p, size_t size, PRBool detailed) -{ - fprintf(out, "0x%p: 0x%.6lX - FREE\n", p, (long) size); -} - -static void PR_CALLBACK -pr_DumpSegment(FILE* out, GCSeg* sp, PRBool detailed) -{ - pr_WalkSegment(out, sp, detailed, - "\n Address: Length\n0x%p: Beginning of segment\n", - "0x%p: End of segment\n\n", - pr_DumpObject, pr_DumpUnknown, pr_DumpFree); -} - -static void pr_DumpRoots(FILE *out); - -/* -** Dump out the GC heap. -*/ -PR_IMPLEMENT(void) -PR_DumpGCHeap(FILE *out, PRBool detailed) -{ - fprintf(out, "\n" - "The kinds are:\n" - " U unscanned block\n" - " W weak link block\n" - " S scanned block\n" - " F scanned and final block\n" - " C class record\n" - " X context record\n" - " - free list item\n" - " ? other\n"); - LOCK_GC(); - pr_WalkSegments(out, pr_DumpSegment, detailed); - if (detailed) - pr_DumpRoots(out); - UNLOCK_GC(); -} - -PR_IMPLEMENT(void) -PR_DumpMemory(PRBool detailed) -{ - PR_DumpToFile("memory.out", "Dumping memory", PR_DumpGCHeap, detailed); -} - -/******************************************************************************/ - -static PRInt32 PR_CALLBACK -pr_DumpRootPointer(PRWord* p, void* data) -{ - PRWord h = p[0]; - PRWord tix = GET_TYPEIX(h); - size_t bytes = OBJ_BYTES(h); - - GCType* tp = &_pr_collectorTypes[tix].gctype; - if (0 != tp) - pr_DumpObject(_pr_gcData.dumpOutput, tp, p, bytes, PR_FALSE); - else - pr_DumpUnknown(_pr_gcData.dumpOutput, tp, tix, p, bytes, PR_FALSE); - return 0; -} - -static void PR_CALLBACK -pr_ConservativeDumpRootPointer(void* ptr) -{ - (void)pr_ConservativeWalkPointer(ptr, (PRWalkFun) pr_DumpRootPointer, NULL); -} - -static void PR_CALLBACK -pr_ConservativeDumpRootBlock(void **base, PRInt32 count) -{ - (void)pr_ConservativeWalkBlock(base, count, (PRWalkFun) pr_DumpRootPointer, NULL); -} - -extern int -DumpThreadRoots(PRThread *t, int i, void *notused); - -static void -pr_DumpRoots(FILE *out) -{ - RootFinder *rf; - void (*liveBlock)(void **base, PRInt32 count); - void (*livePointer)(void *ptr); - void (*processRootBlock)(void **base, PRInt32 count); - void (*processRootPointer)(void *ptr); - - LOCK_GC(); - - liveBlock = _pr_gcData.liveBlock; - livePointer = _pr_gcData.livePointer; - processRootBlock = _pr_gcData.processRootBlock; - processRootPointer = _pr_gcData.processRootPointer; - - _pr_gcData.liveBlock = pr_ConservativeDumpRootBlock; - _pr_gcData.livePointer = pr_ConservativeDumpRootPointer; - _pr_gcData.processRootBlock = pr_ConservativeDumpRootBlock; - _pr_gcData.processRootPointer = pr_ConservativeDumpRootPointer; - _pr_gcData.dumpOutput = out; - - rf = _pr_rootFinders; - while (rf) { - fprintf(out, "\n===== Roots for %s\n", rf->name); - (*rf->func)(rf->arg); - rf = rf->next; - } - - _pr_gcData.liveBlock = liveBlock; - _pr_gcData.livePointer = livePointer; - _pr_gcData.processRootBlock = processRootBlock; - _pr_gcData.processRootPointer = processRootPointer; - _pr_gcData.dumpOutput = NULL; - - UNLOCK_GC(); -} - -/******************************************************************************* - * Heap Summary Dumper - ******************************************************************************/ - -PRSummaryPrinter summaryPrinter = NULL; -void* summaryPrinterClosure = NULL; - -PR_IMPLEMENT(void) -PR_RegisterSummaryPrinter(PRSummaryPrinter fun, void* closure) -{ - summaryPrinter = fun; - summaryPrinterClosure = closure; -} - -static void PR_CALLBACK -pr_SummarizeObject(FILE *out, GCType* tp, PRWord *p, - size_t bytes, PRBool detailed) -{ - if (tp->summarize) - (*tp->summarize)((void GCPTR*)(p + 1), bytes); -} - -static void PR_CALLBACK -pr_DumpSummary(FILE* out, GCSeg* sp, PRBool detailed) -{ - pr_WalkSegment(out, sp, detailed, NULL, NULL, - pr_SummarizeObject, NULL, NULL); -} - -PR_IMPLEMENT(void) -PR_DumpGCSummary(FILE *out, PRBool detailed) -{ - if (summaryPrinter) { - pr_WalkSegments(out, pr_DumpSummary, detailed); - summaryPrinter(out, summaryPrinterClosure); - } -#if 0 - fprintf(out, "\nFinalizable objects:\n"); - { - PRCList *qp; - qp = _pr_pendingFinalQueue.next; - while (qp != &_pr_pendingFinalQueue) { - GCFinal* fp = FinalPtr(qp); - PRWord h = fp->object[0]; /* Grab header word */ - PRWord tix = GET_TYPEIX(h); - GCType* tp = _pr_gcTypes[tix]; - size_t bytes = OBJ_BYTES(h); - pr_DumpObject(out, tp, fp->object, bytes, PR_FALSE); - qp = qp->next; - } - } -#endif -} - -PR_IMPLEMENT(void) -PR_DumpMemorySummary(void) -{ - PR_DumpToFile("memory.out", "Memory Summary", PR_DumpGCSummary, PR_FALSE); -} - -/******************************************************************************* - * End Of Heap Walker - ******************************************************************************/ - -#ifdef GC_TRACEROOTS - -PRInt32 pr_traceGen = 0; - -static PRBool -pr_IsMarked(PRWord* p) -{ - GCBlockEnd* end = (GCBlockEnd*)((char*)p + OBJ_BYTES(p[0]) - sizeof(GCBlockEnd)); - PR_ASSERT(end->check == PR_BLOCK_END); - return end->traceGeneration == pr_traceGen; -} - -static void -pr_Mark(PRWord* p) -{ - GCBlockEnd* end = (GCBlockEnd*)((char*)p + OBJ_BYTES(p[0]) - sizeof(GCBlockEnd)); - PR_ASSERT(end->check == PR_BLOCK_END); - end->traceGeneration = pr_traceGen; -} - -PRWord* pr_traceObj; /* set this in the debugger, then execute PR_TraceRoot() */ - -static PRInt32 PR_CALLBACK -pr_TraceRootObject(void* obj, void* data); - -static PRInt32 PR_CALLBACK -pr_TraceRootPointer(PRWord *p, void* data) -{ - PRInt32 printTrace = 0; - PRWord h = p[0]; - PRWord tix = GET_TYPEIX(h); - GCType* tp = &_pr_collectorTypes[tix].gctype; - FILE* out = _pr_gcData.dumpOutput; - - PR_ASSERT(tp); - if (pr_IsMarked(p)) - return printTrace; - - pr_Mark(p); - if (p == pr_traceObj) { - fprintf(out, "\n### Found path to:\n"); - printTrace = 1; - } - else { - if (PR_StackSpaceLeft(PR_GetCurrentThread()) < 512) { - fprintf(out, "\n### Path too deep (giving up):\n"); - printTrace = 1; - } - else if (tp->walk) { - printTrace = tp->walk((void*)(p + 1), pr_TraceRootObject, data); - } - /* else there's no way to walk this object, so we - haven't found what we're looking for */ - } - - if (printTrace == 1) { - PR_ASSERT(tp->dump); - fprintf(out, "0x%p: ", p); - tp->dump(out, (void*)(p + 1), PR_FALSE, 1); - } - return printTrace; -} - -static PRInt32 PR_CALLBACK -pr_TraceRootObject(void* obj, void* data) -{ - /* This version of pr_TraceRootPointer takes object - pointers, instead of gc header pointers. */ - return pr_TraceRootPointer((PRWord*)obj - 1, data); -} - -static void PR_CALLBACK -pr_ConservativeTraceRootPointer(PRWord *p) -{ - PRInt32 status; - ++pr_traceGen; - status = pr_ConservativeWalkPointer(p, pr_TraceRootPointer, NULL); - if (status) { - FILE* out = _pr_gcData.dumpOutput; - fprintf(out, "### from root at 0x%p\n\n", p); - } -} - -static void PR_CALLBACK -pr_ConservativeTraceRootBlock(void **base, PRInt32 count) -{ - PRInt32 status; - ++pr_traceGen; - status = pr_ConservativeWalkBlock(base, count, pr_TraceRootPointer, NULL); - if (status) { - FILE* out = _pr_gcData.dumpOutput; - fprintf(out, "### from root in range 0x%p + 0x%lx\n\n", - base, (long) count); - } -} - -static void -PR_TraceRoot1(FILE* out, PRBool detailed) -{ - RootFinder *rf; - void (*liveBlock)(void **base, PRInt32 count); - void (*livePointer)(void *ptr); - void (*processRootBlock)(void **base, PRInt32 count); - void (*processRootPointer)(void *ptr); - - LOCK_GC(); - - liveBlock = _pr_gcData.liveBlock; - livePointer = _pr_gcData.livePointer; - processRootBlock = _pr_gcData.processRootBlock; - processRootPointer = _pr_gcData.processRootPointer; - - _pr_gcData.liveBlock = pr_ConservativeTraceRootBlock; - _pr_gcData.livePointer = pr_ConservativeTraceRootPointer; - _pr_gcData.processRootBlock = pr_ConservativeTraceRootBlock; - _pr_gcData.processRootPointer = pr_ConservativeTraceRootPointer; - _pr_gcData.dumpOutput = out; - - fprintf(out, "### Looking for paths to 0x%p\n\n", pr_traceObj); - - rf = _pr_rootFinders; - while (rf) { - fprintf(out, "\n===== Roots for %s\n", rf->name); - (*rf->func)(rf->arg); - rf = rf->next; - } - - _pr_gcData.liveBlock = liveBlock; - _pr_gcData.livePointer = livePointer; - _pr_gcData.processRootBlock = processRootBlock; - _pr_gcData.processRootPointer = processRootPointer; - _pr_gcData.dumpOutput = NULL; - - UNLOCK_GC(); -} - -PR_PUBLIC_API(void) -PR_TraceRoot() -{ - /* - ** How this works: - ** Once you find the object you want to trace the roots of, set the - ** global variable pr_traceObj to point to it (the header, not the - ** java handle), and then call this routine (on Windows, you can set - ** a breakpoint at the end of a function that returns void (e.g. dogc) - ** and then do a "set next statement" to point to this routine and go. - ** This will dump a list of the paths from the roots to the object in - ** question to your memory.out file. - */ - PR_DumpToFile("memory.out", "Tracing Roots", PR_TraceRoot1, PR_FALSE); -} - -#endif /* GC_TRACEROOTS */ - -/******************************************************************************/ - -#if defined(DEBUG) && defined(WIN32) -static void DumpApplicationHeap(FILE *out, HANDLE heap) -{ - PROCESS_HEAP_ENTRY entry; - DWORD err; - - if (!HeapLock(heap)) - OutputDebugString("Can't lock the heap.\n"); - entry.lpData = 0; - fprintf(out, " address: size ovhd region\n"); - while (HeapWalk(heap, &entry)) - { - WORD flags = entry.wFlags; - - fprintf(out, "0x%.8X: 0x%.8X 0x%.2X 0x%.2X ", entry.lpData, entry.cbData, - entry.cbOverhead, entry.iRegionIndex); - if (flags & PROCESS_HEAP_REGION) - fprintf(out, "REGION committedSize=0x%.8X uncommittedSize=0x%.8X firstBlock=0x%.8X lastBlock=0x%.8X", - entry.Region.dwCommittedSize, entry.Region.dwUnCommittedSize, - entry.Region.lpFirstBlock, entry.Region.lpLastBlock); - else if (flags & PROCESS_HEAP_UNCOMMITTED_RANGE) - fprintf(out, "UNCOMMITTED"); - else if (flags & PROCESS_HEAP_ENTRY_BUSY) - { - if (flags & PROCESS_HEAP_ENTRY_DDESHARE) - fprintf(out, "DDEShare "); - if (flags & PROCESS_HEAP_ENTRY_MOVEABLE) - fprintf(out, "Moveable Block handle=0x%.8X", entry.Block.hMem); - else - fprintf(out, "Block"); - } - fprintf(out, "\n"); - } - if ((err = GetLastError()) != ERROR_NO_MORE_ITEMS) - fprintf(out, "ERROR %d iterating through the heap\n", err); - if (!HeapUnlock(heap)) - OutputDebugString("Can't unlock the heap.\n"); -} -#endif - -#if defined(DEBUG) && defined(WIN32) -static void DumpApplicationHeaps(FILE *out) -{ - HANDLE mainHeap; - HANDLE heaps[100]; - DWORD nHeaps; - PRInt32 i; - - mainHeap = GetProcessHeap(); - nHeaps = GetProcessHeaps(100, heaps); - if (nHeaps > 100) - nHeaps = 0; - fprintf(out, "%ld heaps:\n", (long) nHeaps); - for (i = 0; i<nHeaps; i++) - { - HANDLE heap = heaps[i]; - - fprintf(out, "Heap at 0x%.8lX", (long) heap); - if (heap == mainHeap) - fprintf(out, " (main)"); - fprintf(out, ":\n"); - DumpApplicationHeap(out, heap); - fprintf(out, "\n"); - } - fprintf(out, "End of heap dump\n\n"); -} -#endif - -#if defined(DEBUG) && defined(WIN32) -PR_IMPLEMENT(void) PR_DumpApplicationHeaps(void) -{ - FILE *out; - - OutputDebugString("Dumping heaps..."); - out = fopen("heaps.out", "a"); - if (!out) - OutputDebugString("Can't open \"heaps.out\"\n"); - else - { - struct tm *newtime; - time_t aclock; - - time(&aclock); - newtime = localtime(&aclock); - fprintf(out, "Heap dump on %s\n", asctime(newtime)); /* Print current time */ - DumpApplicationHeaps(out); - fprintf(out, "\n\n"); - fclose(out); - } - OutputDebugString(" done\n"); -} -#else - -PR_IMPLEMENT(void) PR_DumpApplicationHeaps(void) -{ - fprintf(stderr, "Native heap dumping is currently implemented only for Windows32.\n"); -} -#endif - -/************************************************************************/ - -/* -** Scan the freelist bins looking for a big enough chunk of memory to -** hold "bytes" worth of allocation. "bytes" already has the -** per-allocation header added to it. Return a pointer to the object with -** its per-allocation header already prepared. -*/ -static PRWord *BinAlloc(int cbix, PRInt32 bytes, int dub) -{ - GCFreeChunk **cpp, *cp, *cpNext; - GCSeg *sp; - PRInt32 chunkSize, remainder; - PRWord *p, *np; - PRInt32 bin, newbin; - - /* Compute bin that allocation belongs in */ - InlineBinNumber(bin,bytes) - if (bin < minBin) { - bin = minBin; /* Start at first filled bin */ - } - - /* Search in the bin, and larger bins, for a big enough piece */ - for (; bin <= NUM_BINS-1; bin++) { - cpp = &bins[bin]; - while ((cp = *cpp) != 0) { - chunkSize = cp->chunkSize; - if (chunkSize < bytes) { - /* Too small; skip it */ - METER(meter.skippedFreeChunks++); - cpp = &cp->next; - continue; - } - - /* We have found a hunk of memory large enough to use */ - p = (PRWord*) cp; - sp = cp->segment; - cpNext = cp->next; -#ifndef IS_64 - if (dub && (((PRWord)p & (PR_BYTES_PER_DWORD-1)) == 0)) { - /* - * We are double aligning the memory and the current free - * chunk is aligned on an even boundary. Because header - * words are one word long we need to discard the first - * word of memory. - */ - p[0] = MAKE_HEADER(FREE_MEMORY_TYPEIX, 1); - SET_HBIT(sp, p); - p++; - chunkSize -= PR_BYTES_PER_WORD; - bytes -= PR_BYTES_PER_WORD; - PR_ASSERT(((PRWord)p & (PR_BYTES_PER_DWORD-1)) != 0); - _pr_gcData.freeMemory -= PR_BYTES_PER_WORD; - _pr_gcData.busyMemory += PR_BYTES_PER_WORD; - } -#endif - np = (PRWord*) ((char*) p + bytes); - remainder = chunkSize - bytes; - if (remainder >= MIN_FREE_CHUNK_BYTES) { - /* The left over memory is large enough to be freed. */ - cp = (GCFreeChunk*) np; - cp->segment = sp; - cp->chunkSize = remainder; - InlineBinNumber(newbin, remainder) - if (newbin != bin) { - *cpp = (GCFreeChunk*) cpNext; /* remove */ - cp->next = bins[newbin]; /* insert */ - bins[newbin] = cp; - if (newbin < minBin) minBin = newbin; - if (newbin > maxBin) maxBin = newbin; - } else { - /* Leave it on the same list */ - cp->next = cpNext; - *cpp = (GCFreeChunk*) np; - } - } else { - /* - * The left over memory is too small to be released. Just - * leave it attached to the chunk of memory being - * returned. - */ - *cpp = cpNext; - bytes = chunkSize; - } - p[0] = MAKE_HEADER(cbix, (bytes >> PR_BYTES_PER_WORD_LOG2)); - SET_HBIT(sp, p); - _pr_gcData.freeMemory -= bytes; - _pr_gcData.busyMemory += bytes; - return p; - } - } - return 0; -} - -/* -** Allocate a piece of memory that is "big" in it's own segment. Make -** the object consume the entire segment to avoid fragmentation. When -** the object is no longer referenced, the segment is freed. -*/ -static PRWord *BigAlloc(int cbix, PRInt32 bytes, int dub) -{ - GCSeg *sp; - PRWord *p, h; - PRInt32 chunkSize; - - /* - ** If the number of bytes allocated via BigAlloc() since the last GC - ** exceeds BIG_ALLOC_GC_SIZE then do a GC Now... - */ - if (bigAllocBytes >= BIG_ALLOC_GC_SIZE) { - dogc(); - } - bigAllocBytes += bytes; - - /* Get a segment to hold this allocation */ - sp = GrowHeapExactly(bytes); - - if (sp) { - p = (PRWord*) sp->base; - chunkSize = sp->limit - sp->base; - - /* All memory is double aligned on 64 bit machines... */ -#ifndef IS_64 - if (dub && (((PRWord)p & (PR_BYTES_PER_DWORD-1)) == 0)) { - /* - ** Consume the first word of the chunk with a dummy - ** unreferenced object. - */ - p[0] = MAKE_HEADER(FREE_MEMORY_TYPEIX, 1); - SET_HBIT(sp, p); - p++; - chunkSize -= PR_BYTES_PER_WORD; - _pr_gcData.freeMemory -= PR_BYTES_PER_WORD; - _pr_gcData.busyMemory += PR_BYTES_PER_WORD; - PR_ASSERT(((PRWord)p & (PR_BYTES_PER_DWORD-1)) != 0); - } -#endif - - /* Consume the *entire* segment with a single allocation */ - h = MAKE_HEADER(cbix, (chunkSize >> PR_BYTES_PER_WORD_LOG2)); - p[0] = h; - SET_HBIT(sp, p); - _pr_gcData.freeMemory -= chunkSize; - _pr_gcData.busyMemory += chunkSize; - return p; - } - return 0; -} - -/* we disable gc allocation during low memory conditions */ -static PRBool allocationEnabled = PR_TRUE; - -PR_IMPLEMENT(void) PR_EnableAllocation(PRBool yesOrNo) -{ - allocationEnabled = yesOrNo; -} - -static void CollectorCleanup(void) { - while (collectorCleanupNeeded) { - LOCK_GC(); - collectorCleanupNeeded = 0; - UNLOCK_GC(); - if (freeSegs) { - FreeSegments(); - } - if (!WEAK_FREELIST_ISEMPTY()) { - EmptyWeakFreeList(); - } - } -} - -/******************************************************************************/ - -#ifdef GC_CHECK -static PRInt32 allocationCount; - -static void EarthShatteringKaBoom(PRInt32 whichOne) { - long* p = 0; - *p = 0; -} - -/* Check a segment of heap memory. Verify that the object memory - hasn't been overwritten (past the end at least) */ -static void CheckSegment(GCSeg* sp) { - PRWord h, tix; - PRWord *p, *lastp, *np, *limit; - - lastp = p = (PRWord *) sp->base; - limit = (PRWord *) sp->limit; - while (p < limit) { - if (IS_HBIT(sp, p)) { - char *cp, i; - GCBlockEnd* end; - PRWord bytes, requestedBytes; - - h = p[0]; - tix = GET_TYPEIX(h); - bytes = OBJ_BYTES(h); - np = (PRWord *) ((char *)p + bytes); - if (tix != FREE_MEMORY_TYPEIX) { - PRInt32 test; /* msdev get's fooled without this local */ - /* A live object is here. The last word in the object will - contain the objects requestedSize */ - end = (GCBlockEnd*)((char*)(p) + bytes - sizeof(GCBlockEnd)); - test = end->check; - if (test != PR_BLOCK_END) { - PR_ASSERT(test == PR_BLOCK_END); - } - requestedBytes = end->requestedBytes; - if (requestedBytes >= bytes) EarthShatteringKaBoom(0); - cp = (char*)(p + 1) + requestedBytes; - i = (char) 0xff; - while (cp < (char*)end) { - if (*cp != i) EarthShatteringKaBoom(1); - cp++; - i--; - } - } - lastp = p; - p = np; - } else { - /* Must be a freelist item */ - GCFreeChunk *cp = (GCFreeChunk*) p; - if ((PRInt32)cp->chunkSize < (PRInt32)sizeof(GCFreeChunk)) { - EarthShatteringKaBoom(3); - } - lastp = p; - p = (PRWord*) ((char*)p + cp->chunkSize); - } - } -} - -static void CheckHeap(void) { - GCSeg *sp = segs; - GCSeg *esp = sp + nsegs; - while (sp < esp) { - CheckSegment(sp); - sp++; - } -} - -#endif /* GC_CHECK */ - -/******************************************************************************/ - -#ifdef DEBUG -long gc_thrash = -1L; -#endif - -/* -** Allocate memory from the GC Heap. Performs garbage collections if -** memory gets tight and grows the heap as needed. May return NULL if -** memory cannot be found. -*/ -PR_IMPLEMENT(PRWord GCPTR *)PR_AllocMemory( - PRWord requestedBytes, PRInt32 tix, PRWord flags) -{ - PRWord *p; - CollectorType *ct; - PRInt32 bytes; - GCFinal *final = 0; - GCWeak *weak = 0; - int dub = flags & PR_ALLOC_DOUBLE; - PRInt32 objBytes; -#ifdef GC_STATS - PRInt64 allocTime, ldelta; -#endif - - if (!allocationEnabled) return NULL; - - PR_ASSERT(requestedBytes >= 0); - PR_ASSERT(_pr_collectorTypes[tix].flags != 0); - -#ifdef DEBUG - if (_pr_do_a_dump) { - /* - ** Collect, pause for a second (lets finalizer run), and then GC - ** again. - */ - PR_GC(); - PR_Sleep(PR_MicrosecondsToInterval(1000000L)); - PR_GC(); - PR_DumpGCHeap(_pr_dump_file, PR_TRUE); - _pr_do_a_dump = 0; - } -#endif - -#ifdef GC_STATS - allocTime = PR_Now(); -#endif - bytes = (PRInt32) requestedBytes; - - /* - ** Align bytes to a multiple of a PRWord, then add in enough space - ** to hold the header word. - ** - ** MSVC 1.52 crashed on the ff. code because of the "complex" shifting :-( - */ - /* Check for possible overflow of bytes before performing add */ - if ((MAX_INT - PR_BYTES_PER_WORD) < bytes ) return NULL; - bytes = (bytes + PR_BYTES_PER_WORD - 1) >> PR_BYTES_PER_WORD_LOG2; - bytes <<= PR_BYTES_PER_WORD_LOG2; - /* Check for possible overflow of bytes before performing add */ - if ((MAX_INT - sizeof(PRWord)) < bytes ) return NULL; - bytes += sizeof(PRWord); - /* - * Add in an extra word of memory for double-aligned memory. Some - * percentage of the time this will waste a word of memory (too - * bad). Howver, it makes the allocation logic much simpler and - * faster. - */ -#ifndef IS_64 - if (dub) { - /* Check for possible overflow of bytes before performing add */ - if ((MAX_INT - PR_BYTES_PER_WORD) < bytes ) return NULL; - bytes += PR_BYTES_PER_WORD; - } -#endif - -#ifdef GC_CHECK - if (_pr_gcData.flags & GC_CHECK) { - /* Bloat the allocation a bit so that we can lay down - a check pattern that we will validate */ - /* Check for possible overflow of bytes before performing add */ - if ((MAX_INT - PR_BYTES_PER_WORD * 3) < bytes ) return NULL; - bytes += PR_BYTES_PER_WORD * 3; - } -#endif - -#if defined(GC_CHECK) || defined(GC_STATS) || defined(GC_TRACEROOTS) - if ((MAX_INT - sizeof(GCBlockEnd)) < bytes ) return NULL; - bytes += sizeof(GCBlockEnd); -#endif - - PR_ASSERT( bytes < MAX_ALLOC_SIZE ); - /* - ** Java can ask for objects bigger than MAX_ALLOC_SIZE, - ** but it won't get them. - */ - if (bytes >= MAX_ALLOC_SIZE) return NULL; - -#ifdef DEBUG - if (gc_thrash == -1L ? (gc_thrash = (long)PR_GetEnv("GC_THRASH")):gc_thrash) PR_GC(); -#endif - - ct = &_pr_collectorTypes[tix]; - if (ct->flags & (_GC_TYPE_FINAL|_GC_TYPE_WEAK)) { - if (0 != ct->gctype.finalize) { - /* - ** Allocate a GCFinal struct for this object in advance. Don't put - ** it on the pending list until we have allocated the object - */ - final = AllocFinalNode(); - if (!final) { - /* XXX THIS IS NOT ACCEPTABLE*/ - PR_ASSERT(0); - return 0; - } - } - if (0 != ct->gctype.getWeakLinkOffset) { - /* - ** Allocate a GCWeak struct for this object in advance. Don't put - ** it on the weak links list until we have allocated the object - */ - weak = AllocWeakNode(); - if (!weak) { - /* XXX THIS IS NOT ACCEPTABLE*/ - if (0 != final) { - FreeFinalNode(final); - } - PR_ASSERT(0); - return 0; - } - } - } - - LOCK_GC(); -#ifdef GC_CHECK - if (_pr_gcData.flags & GC_CHECK) CheckHeap(); - allocationCount++; -#endif - - /* Check for overflow of maximum size we can handle */ - if (bytes > MAX_ALLOC) goto lost; - - /* Try default allocation */ - p = ((bytes >= BIG_ALLOC) && (nsegs < MAX_SEGS)) ? - BigAlloc(tix, bytes, dub) : BinAlloc(tix, bytes, dub); - if (0 == p) { -#ifdef GC_STATS - LL_SUB(ldelta, PR_Now(), allocTime); -#endif - /* Collect some memory */ - _GCTRACE(GC_ALLOC, ("force GC: want %d", bytes)); - dogc(); - PR_ASSERT( GC_IS_LOCKED() ); - - /* After a collection we check and see if we should grow the - ** heap. We grow the heap when the amount of memory free is less - ** than a certain percentage of the heap size. We don't check to - ** see if the grow succeeded because our fallback strategy in - ** either case is to try one more time to allocate. */ - if ((_pr_gcData.allocMemory < _pr_gcData.maxMemory) - && ((_pr_gcData.freeMemory < - ((_pr_gcData.allocMemory * MIN_FREE_THRESHOLD_AFTER_GC) / 100L)) - || (_pr_gcData.freeMemory < bytes))) { - GrowHeap(PR_MAX(bytes, segmentSize)); - } -#ifdef GC_STATS - LL_ADD(allocTime, PR_Now(), ldelta); -#endif - - /* Try again */ - p = ((bytes >= BIG_ALLOC) && (nsegs < MAX_SEGS)) ? - BigAlloc(tix, bytes, dub) : BinAlloc(tix, bytes, dub); - if (0 == p) { - /* Well that lost big time. Memory must be pretty well fragmented */ - if (!GrowHeap(PR_MAX(bytes, segmentSize))) goto lost; - p = BinAlloc(tix, bytes, dub); - if (0 == p) goto lost; - } - } - - /* Zero out the portion of the object memory that was used by - the GCFreeChunk structure (skip the first word because it - was already overwritten by the gc header word) */ - objBytes = OBJ_BYTES(p[0]); - if (objBytes > sizeof(PRWord)) p[1] = 0; - if (objBytes > sizeof(PRWord)*2) p[2] = 0; - - if (final) { - _GCTRACE(GC_ALLOC, ("alloc 0x%x (%d) final=0x%x", - p, bytes, final)); - final->object = p; - PR_APPEND_LINK(&final->links, &_pr_finalizeableObjects); - } else { - _GCTRACE(GC_ALLOC, ("alloc 0x%x (%d)", p, bytes)); - } - if (weak) { - weak->object = p; - PR_APPEND_LINK(&weak->links, &_pr_weakLinks); - } - METER(meter.allocBytes += bytes); - METER(meter.wastedBytes += (bytes - requestedBytes)); - UNLOCK_GC(); - - if (collectorCleanupNeeded) { - CollectorCleanup(); - } - -#if defined(GC_CHECK) || defined(GC_STATS) || defined(GC_TRACEROOTS) - { - GCBlockEnd* end = (GCBlockEnd*)((char*)p + OBJ_BYTES(p[0]) - sizeof(GCBlockEnd)); - end->check = PR_BLOCK_END; - } -#endif -#ifdef GC_STATS - { - PRInt64 now = PR_Now(); - double delta; - PRInt32 bin; - GCBlockEnd* end = (GCBlockEnd*)((char*)p + OBJ_BYTES(p[0]) - sizeof(GCBlockEnd)); - - end->allocTime = allocTime; - LL_SUB(ldelta, now, allocTime); - LL_L2D(delta, ldelta); - InlineBinNumber(bin, requestedBytes); - end->bin = bin; - gcstats[bin].nallocs++; - gcstats[bin].allocTime += delta; - gcstats[bin].allocTimeVariance += delta * delta; - } -#endif -#ifdef GC_CHECK - if (_pr_gcData.flags & GC_CHECK) { - /* Place a pattern in the memory that was allocated that was not - requested. We will check the pattern later. */ - char* cp = (char*)(p + 1) + requestedBytes; - GCBlockEnd* end = (GCBlockEnd*)((char*)p + OBJ_BYTES(p[0]) - sizeof(GCBlockEnd)); - char i = (char) 0xff; - while (cp < (char*)end) { - *cp++ = i--; - } - end->requestedBytes = requestedBytes; - CheckHeap(); - } -#endif - return p + 1; - - lost: - /* Out of memory */ - UNLOCK_GC(); - if (final) { - FreeFinalNode(final); - } - if (weak) { - FreeWeakNode(weak); - } - if (collectorCleanupNeeded) { - CollectorCleanup(); - } - return 0; -} - -/* Shortcut allocator for objects that do not require finalization or - are weak objects */ -PR_IMPLEMENT(PRWord GCPTR *) -PR_AllocSimpleMemory(PRWord requestedBytes, PRInt32 tix) -{ - PRWord *p; - PRInt32 bytes; - PRInt32 objBytes; -#ifdef GC_STATS - PRInt64 allocTime, ldelta; -#endif - - if (!allocationEnabled) return NULL; - - PR_ASSERT(requestedBytes >= 0); - PR_ASSERT(_pr_collectorTypes[tix].flags != 0); - -#ifdef DEBUG - if (_pr_do_a_dump) { - /* - ** Collect, pause for a second (lets finalizer run), and then GC - ** again. - */ - PR_GC(); - PR_Sleep(PR_MicrosecondsToInterval(1000000L)); - PR_GC(); - PR_DumpGCHeap(_pr_dump_file, PR_TRUE); - _pr_do_a_dump = 0; - } -#endif - -#ifdef GC_STATS - allocTime = PR_NowMS(); -#endif - bytes = (PRInt32) requestedBytes; - - /* - ** Align bytes to a multiple of a PRWord, then add in enough space - ** to hold the header word. - ** - ** MSVC 1.52 crashed on the ff. code because of the "complex" shifting :-( - */ - bytes = (bytes + PR_BYTES_PER_WORD - 1) >> PR_BYTES_PER_WORD_LOG2; - bytes <<= PR_BYTES_PER_WORD_LOG2; - bytes += sizeof(PRWord); - - /* - * Add in an extra word of memory for double-aligned memory. Some - * percentage of the time this will waste a word of memory (too - * bad). Howver, it makes the allocation logic much simpler and - * faster. - */ -#ifndef IS_64 - bytes += PR_BYTES_PER_WORD; -#endif - -#ifdef GC_CHECK - if (_pr_gcData.flags & GC_CHECK) { - /* Bloat the allocation a bit so that we can lay down - a check pattern that we will validate */ - bytes += PR_BYTES_PER_WORD * 2; - } -#endif - -#if defined(GC_CHECK) || defined(GC_STATS) || defined(GC_TRACEROOTS) - bytes += sizeof(GCBlockEnd); -#endif - - /* Java can ask for objects bigger than 4M, but it won't get them */ - /* - * This check was added because there is a fundamental limit of - * the size field maintained by the gc code. Going over the 4M - * limit caused some bits to roll over into another bit field, - * violating the max segment size and causing a bug. - */ - if (bytes >= MAX_ALLOC_SIZE) { - return NULL; - } -#ifdef DEBUG - if (gc_thrash == -1L - ? (gc_thrash = (long)PR_GetEnv("GC_THRASH")) - : gc_thrash) { - PR_GC(); - } -#endif - - LOCK_GC(); -#ifdef GC_CHECK - if (_pr_gcData.flags & GC_CHECK) { - CheckHeap(); - } - allocationCount++; -#endif - - /* Try default allocation */ - if ((bytes >= BIG_ALLOC) && (nsegs < MAX_SEGS)) { - p = BigAlloc(tix, bytes, 1); - } else { - p = BinAlloc(tix, bytes, 1); - } - if (0 == p) { -#ifdef GC_STATS - LL_SUB(ldelta, PR_Now(), allocTime); -#endif - /* Collect some memory */ - _GCTRACE(GC_ALLOC, ("force GC: want %d", bytes)); - dogc(); - PR_ASSERT( GC_IS_LOCKED() ); - - /* After a collection we check and see if we should grow the - heap. We grow the heap when the amount of memory free is less - than a certain percentage of the heap size. We don't check to - see if the grow succeeded because our fallback strategy in - either case is to try one more time to allocate. */ - if ((_pr_gcData.allocMemory < _pr_gcData.maxMemory) && - (_pr_gcData.freeMemory < - ((_pr_gcData.allocMemory * MIN_FREE_THRESHOLD_AFTER_GC) / 100L))) { - GrowHeap(PR_MAX(bytes, segmentSize)); - } -#ifdef GC_STATS - LL_ADD(allocTime, PR_Now(), ldelta); -#endif - - /* Try one last time */ - if ((bytes >= BIG_ALLOC) && (nsegs < MAX_SEGS)) { - p = BigAlloc(tix, bytes, 1); - } else { - p = BinAlloc(tix, bytes, 1); - } - if (0 == p) { - /* Well that lost big time. Memory must be pretty well fragmented */ - if (!GrowHeap(PR_MAX(bytes, segmentSize))) { - goto lost; - } - p = BinAlloc(tix, bytes, 1); - if (0 == p) goto lost; - } - } - - /* Zero out the portion of the object memory that was used by - the GCFreeChunk structure (skip the first word because it - was already overwritten by the gc header word) */ - objBytes = OBJ_BYTES(p[0]); - if (objBytes > sizeof(PRWord)) p[1] = 0; - if (objBytes > sizeof(PRWord)*2) p[2] = 0; - - METER(meter.allocBytes += bytes); - METER(meter.wastedBytes += (bytes - requestedBytes)); - UNLOCK_GC(); - - if (collectorCleanupNeeded) { - CollectorCleanup(); - } - -#if defined(GC_CHECK) || defined(GC_STATS) || defined(GC_TRACEROOTS) - { - GCBlockEnd* end = (GCBlockEnd*)((char*)p + OBJ_BYTES(p[0]) - sizeof(GCBlockEnd)); - end->check = PR_BLOCK_END; - } -#endif -#ifdef GC_STATS - { - PRInt64 now = PR_Now(); - double delta; - PRInt32 bin; - GCBlockEnd* end = (GCBlockEnd*)((char*)p + OBJ_BYTES(p[0]) - sizeof(GCBlockEnd)); - - end->allocTime = allocTime; - LL_SUB(ldelta, now, allocTime); - LL_L2D(delta, ldelta); - InlineBinNumber(bin, requestedBytes); - end->bin = bin; - gcstats[bin].nallocs++; - gcstats[bin].allocTime += delta; - gcstats[bin].allocTimeVariance += delta * delta; - } -#endif -#ifdef GC_CHECK - if (_pr_gcData.flags & GC_CHECK) { - /* Place a pattern in the memory that was allocated that was not - requested. We will check the pattern later. */ - char* cp = (char*)(p + 1) + requestedBytes; - GCBlockEnd* end = (GCBlockEnd*)((char*)p + OBJ_BYTES(p[0]) - sizeof(GCBlockEnd)); - char i = (char) 0xff; - while (cp < (char*)end) { - *cp++ = i--; - } - end->requestedBytes = requestedBytes; - CheckHeap(); - } -#endif - return p + 1; - - lost: - /* Out of memory */ - UNLOCK_GC(); - if (collectorCleanupNeeded) { - CollectorCleanup(); - } - return 0; -} - -/************************************************************************/ - -PR_IMPLEMENT(PRWord) PR_GetObjectHeader(void *ptr) { - GCSeg *sp; - PRWord *h; - - if (ptr == 0) return 0; - sp = InHeap(ptr); - if (sp == 0) return 0; - h = (PRWord*)FindObject(sp, (PRWord*)ptr); - return GC_GET_USER_BITS(h[0]); -} - -PR_IMPLEMENT(PRWord) PR_SetObjectHeader(void *ptr, PRWord newUserBits) { - GCSeg *sp; - PRWord *h, rv; - - if (ptr == 0) return 0; - sp = InHeap(ptr); - if (sp == 0) return 0; - h = (PRWord*)FindObject(sp, (PRWord*)ptr); - rv = GC_GET_USER_BITS(h[0]); - h[0] = (h[0] & ~GC_USER_BITS) | - ((newUserBits << GC_USER_BITS_SHIFT) & GC_USER_BITS); - return rv; -} - -PR_IMPLEMENT(void) PR_InitGC( - PRWord flags, PRInt32 initialHeapSize, PRInt32 segSize, PRThreadScope scope) -{ - static char firstTime = 1; - - if (!firstTime) return; - firstTime = 0; - - _pr_msgc_lm = PR_NewLogModule("msgc"); - _pr_pageShift = PR_GetPageShift(); - _pr_pageSize = PR_GetPageSize(); - - /* Setup initial heap size and initial segment size */ - if (0 != segSize) segmentSize = segSize; -#ifdef DEBUG - GC = PR_NewLogModule("GC"); - { - char *ev = PR_GetEnv("GC_SEGMENT_SIZE"); - if (ev && ev[0]) { - PRInt32 newSegmentSize = atoi(ev); - if (0 != newSegmentSize) segmentSize = newSegmentSize; - } - ev = PR_GetEnv("GC_INITIAL_HEAP_SIZE"); - if (ev && ev[0]) { - PRInt32 newInitialHeapSize = atoi(ev); - if (0 != newInitialHeapSize) initialHeapSize = newInitialHeapSize; - } - ev = PR_GetEnv("GC_FLAGS"); - if (ev && ev[0]) { - flags |= atoi(ev); - } -#ifdef GCMETER - ev = PR_GetEnv("GC_METER"); - if (ev && ev[0]) { - _pr_gcMeter = atoi(ev); - } -#endif - } -#endif - if (0 == initialHeapSize) initialHeapSize = segmentSize; - if (initialHeapSize < segmentSize) initialHeapSize = segmentSize; - - _pr_gcData.maxMemory = MAX_SEGS * segmentSize; - _pr_gcData.liveBlock = ProcessRootBlock; - _pr_gcData.livePointer = ProcessRootPointer; - _pr_gcData.processRootBlock = ProcessRootBlock; - _pr_gcData.processRootPointer = ProcessRootPointer; - _pr_gcData.dumpOutput = NULL; - - PR_INIT_CLIST(&_pr_finalizeableObjects); - PR_INIT_CLIST(&_pr_finalQueue); - _PR_InitGC(flags); - - /* Create finalizer thread */ - _PR_CreateFinalizer(scope); - - /* Allocate the initial segment for the heap */ - minBin = 31; - maxBin = 0; - GrowHeap(initialHeapSize); - PR_RegisterRootFinder(ScanWeakFreeList, "scan weak free list", 0); -} - -/** Added by Vishy for sanity checking a few GC structures **/ -/** Can use SanityCheckGC to debug corrupted GC Heap situations **/ - -#ifdef DEBUG - -static int SegmentOverlaps(int i, int j) -{ - return - (((segs[i].limit > segs[j].base) && (segs[i].base < segs[j].base)) || - ((segs[j].limit > segs[i].base) && (segs[j].base < segs[i].base))); -} - -static void NoSegmentOverlaps(void) -{ - int i,j; - - for (i = 0; i < nsegs; i++) - for (j = i+1 ; j < nsegs ; j++) - PR_ASSERT(!SegmentOverlaps(i,j)); -} - -static void SegInfoCheck(void) -{ - int i; - for (i = 0 ; i < nsegs ; i++) - PR_ASSERT((segs[i].info->hbits) && - (segs[i].info->hbits == segs[i].hbits) && - (segs[i].info->base == segs[i].base) && - (segs[i].info->limit == segs[i].limit)); -} - -static void SanityCheckGC() -{ - NoSegmentOverlaps(); - SegInfoCheck(); -} - -#endif - -#if defined(DEBUG) && defined(WIN32) - -extern void *baseaddr; -extern void *lastaddr; - -PR_IMPLEMENT(void) -PR_PrintGCStats(void) -{ - long reportedSegSpace = _pr_gcData.busyMemory + _pr_gcData.freeMemory; - char* msg; - long largeCount = 0, largeSize = 0; - long segCount = 0, segSize = 0; - long freeCount = 0, freeSize = 0; - GCSeg *sp, *esp; - GCSegInfo* si; - - LOCK_GC(); - - sp = segs; - esp = sp + nsegs; - while (sp < esp) { - long size = sp->info->limit - sp->info->base; - segCount++; - segSize += size; - if (sp->info->fromMalloc) { - largeCount++; - largeSize += size; - } - sp++; - } - - si = freeSegs; - while (si != NULL) { - long size = si->limit - si->base; - freeCount++; - freeSize += size; - si = si->next; - } - - msg = PR_smprintf("\ -# GC Stats:\n\ -# vm space:\n\ -# range: %ld - %ld\n\ -# size: %ld\n\ -# segments:\n\ -# range: %ld - %ld\n\ -# count: %ld (reported: %ld)\n\ -# size: %ld (reported: %ld)\n\ -# free count: %ld\n\ -# free size: %ld\n\ -# busy objs: %ld (%ld%%)\n\ -# free objs: %ld (%ld%%)\n\ -# large blocks:\n\ -# count: %ld\n\ -# total size: %ld (%ld%%)\n\ -# avg size: %ld\n\ -", - /* vm space */ - (long)baseaddr, (long)lastaddr, - (long)lastaddr - (long)baseaddr, - /* segments */ - _pr_gcData.lowSeg, _pr_gcData.highSeg, - segCount, nsegs, - segSize, reportedSegSpace, - freeCount, - freeSize, - _pr_gcData.busyMemory, - (_pr_gcData.busyMemory * 100 / reportedSegSpace), - _pr_gcData.freeMemory, - (_pr_gcData.freeMemory * 100 / reportedSegSpace), - /* large blocks */ - largeCount, - largeSize, (largeSize * 100 / reportedSegSpace), - (largeCount ? largeSize / largeCount : 0) - ); - UNLOCK_GC(); - fprintf(stderr, msg); - OutputDebugString(msg); - PR_smprintf_free(msg); -#ifdef GC_STATS - PR_PrintGCAllocStats(); -#endif -} -#endif - -PR_IMPLEMENT(void) -PR_DumpToFile(char* filename, char* msg, PRFileDumper dump, PRBool detailed) -{ - FILE *out; - OutputDebugString(msg); - out = fopen(filename, "a"); - if (!out) { - char buf[64]; - PR_ASSERT(strlen(filename) < sizeof(buf) - 16); - PR_snprintf(buf, sizeof(buf), "Can't open \"%s\"\n", - filename); - OutputDebugString(buf); - } - else - { - struct tm *newtime; - time_t aclock; - int i; - - time(&aclock); - newtime = localtime(&aclock); - fprintf(out, "%s on %s\n", msg, asctime(newtime)); /* Print current time */ - dump(out, detailed); - fprintf(out, "\n\n"); - for (i = 0; i < 80; i++) - fprintf(out, "="); - fprintf(out, "\n\n"); - fclose(out); - } - OutputDebugString(" done\n"); -} -
deleted file mode 100644 --- a/nsprpub/lib/msgc/src/unixgc.c +++ /dev/null @@ -1,155 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * 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 the Netscape Portable Runtime (NSPR). - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either 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. - * - * ***** END LICENSE BLOCK ***** */ - -#include "prlock.h" -#include "prlog.h" -#include "prmem.h" -#include "gcint.h" - -#include <stdio.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <sys/mman.h> - -#define _PR_GC_VMBASE 0x40000000 - -#if defined(SOLARIS) -#define _MD_MMAP_FLAGS MAP_SHARED -#elif defined(RELIANTUNIX) -#define _MD_MMAP_FLAGS MAP_PRIVATE|MAP_FIXED -#else -#define _MD_MMAP_FLAGS MAP_PRIVATE -#endif - -static PRInt32 zero_fd = -1; -static PRLock *zero_fd_lock = NULL; - -void _MD_InitGC(void) -{ -#ifdef DEBUG - /* - * Disable using mmap(2) if NSPR_NO_MMAP is set - */ - if (getenv("NSPR_NO_MMAP")) { - zero_fd = -2; - return; - } -#endif - zero_fd = open("/dev/zero",O_RDWR , 0); - zero_fd_lock = PR_NewLock(); -} - -/* This static variable is used by _MD_GrowGCHeap and _MD_ExtendGCHeap */ -static void *lastaddr = (void*) _PR_GC_VMBASE; - -void *_MD_GrowGCHeap(PRUint32 *sizep) -{ - void *addr; - PRUint32 size; - - size = *sizep; - - PR_Lock(zero_fd_lock); - if (zero_fd < 0) { - goto mmap_loses; - } - - /* Extend the mapping */ - addr = mmap(lastaddr, size, PROT_READ|PROT_WRITE|PROT_EXEC, - _MD_MMAP_FLAGS, - zero_fd, 0); - if (addr == (void*)-1) { - zero_fd = -1; - goto mmap_loses; - } - lastaddr = ((char*)addr + size); -#ifdef DEBUG - PR_LOG(_pr_msgc_lm, PR_LOG_WARNING, - ("GC: heap extends from %08x to %08x\n", - _PR_GC_VMBASE, - _PR_GC_VMBASE + (char*)lastaddr - (char*)_PR_GC_VMBASE)); -#endif - PR_Unlock(zero_fd_lock); - return addr; - -mmap_loses: - PR_Unlock(zero_fd_lock); - return PR_MALLOC(size); -} - -/* XXX - This is disabled. MAP_FIXED just does not work. */ -#if 0 -PRBool _MD_ExtendGCHeap(char *base, PRInt32 oldSize, PRInt32 newSize) { - PRBool rv = PR_FALSE; - void* addr; - PRInt32 allocSize = newSize - oldSize; - - PR_Lock(zero_fd_lock); - addr = mmap(base + oldSize, allocSize, PROT_READ|PROT_WRITE|PROT_EXEC, - _MD_MMAP_FLAGS | MAP_FIXED, zero_fd, 0); - if (addr == (void*)-1) { - goto loser; - } - if (addr != (void*) (base + oldSize)) { - munmap(base + oldSize, allocSize); - goto loser; - } - lastaddr = ((char*)base + newSize); - PR_LOG(_pr_msgc_lm, PR_LOG_ALWAYS, - ("GC: heap now extends from %p to %p", - base, base + newSize)); - rv = PR_TRUE; - -loser: - PR_Unlock(zero_fd_lock); - return rv; -} -#else -PRBool _MD_ExtendGCHeap(char *base, PRInt32 oldSize, PRInt32 newSize) { - return PR_FALSE; -} -#endif - -void _MD_FreeGCSegment(void *base, PRInt32 len) -{ - if (zero_fd < 0) { - PR_DELETE(base); - } else { - (void) munmap(base, len); - } -}
deleted file mode 100644 --- a/nsprpub/lib/msgc/src/win32gc.c +++ /dev/null @@ -1,129 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * 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 the Netscape Portable Runtime (NSPR). - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either 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. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * GC related routines - * - */ -#include <windows.h> -#include "prlog.h" - -extern PRLogModuleInfo* _pr_msgc_lm; - -#define GC_VMBASE 0x40000000 -#define GC_VMLIMIT 0x00FFFFFF - -/************************************************************************/ -/* -** Machine dependent GC Heap management routines: -** _MD_GrowGCHeap -*/ -/************************************************************************/ - -void *baseaddr = (void*) GC_VMBASE; -void *lastaddr = (void*) GC_VMBASE; - -void _MD_InitGC() {} - -void *_MD_GrowGCHeap(PRUint32 *sizep) -{ - void *addr; - size_t size; - - /* Reserve a block of memory for the GC */ - if( lastaddr == baseaddr ) { - addr = VirtualAlloc( (void *)GC_VMBASE, GC_VMLIMIT, MEM_RESERVE, PAGE_READWRITE ); - - /* - ** If the GC_VMBASE address is already mapped, then let the OS choose a - ** base address that is available... - */ - if (addr == NULL) { - addr = VirtualAlloc( NULL, GC_VMLIMIT, MEM_RESERVE, PAGE_READWRITE ); - - baseaddr = lastaddr = addr; - if (addr == NULL) { - PR_LOG(_pr_msgc_lm, PR_LOG_ALWAYS, ("GC: unable to allocate heap: LastError=%ld", - GetLastError())); - return 0; - } - } - } - size = *sizep; - - /* Extend the mapping */ - addr = VirtualAlloc( lastaddr, size, MEM_COMMIT, PAGE_READWRITE ); - if (addr == NULL) { - return 0; - } - - lastaddr = ((char*)addr + size); - PR_LOG(_pr_msgc_lm, PR_LOG_ALWAYS, - ("GC: heap extends from %08x to %08x", - baseaddr, (long)baseaddr + (char*)lastaddr - (char*)baseaddr)); - - return addr; -} - -PRBool _MD_ExtendGCHeap(char *base, PRInt32 oldSize, PRInt32 newSize) { - void* addr; - - addr = VirtualAlloc( base + oldSize, newSize - oldSize, - MEM_COMMIT, PAGE_READWRITE ); - if (NULL == addr) { - PR_LOG(_pr_msgc_lm, PR_LOG_ALWAYS, ("GC: unable to extend heap: LastError=%ld", - GetLastError())); - return PR_FALSE; - } - if (base + oldSize != (char*)addr) { - PR_LOG(_pr_msgc_lm, PR_LOG_ALWAYS, ("GC: segment extension returned %x instead of %x", - addr, base + oldSize)); - VirtualFree(addr, newSize - oldSize, MEM_DECOMMIT); - return PR_FALSE; - } - lastaddr = base + newSize; - PR_LOG(_pr_msgc_lm, PR_LOG_ALWAYS, - ("GC: heap now extends from %p to %p", - base, base + newSize)); - return PR_TRUE; -} - - -void _MD_FreeGCSegment(void *base, PRInt32 len) -{ - (void)VirtualFree(base, 0, MEM_RELEASE); -}
deleted file mode 100644 --- a/nsprpub/lib/msgc/tests/.cvsignore +++ /dev/null @@ -1,1 +0,0 @@ -Makefile
deleted file mode 100644 --- a/nsprpub/lib/msgc/tests/Makefile.in +++ /dev/null @@ -1,270 +0,0 @@ -# -# ***** BEGIN LICENSE BLOCK ***** -# 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 the Netscape Portable Runtime (NSPR). -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998-2000 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either 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. -# -# ***** END LICENSE BLOCK ***** - -#! gmake - -MOD_DEPTH = ../../.. -topsrcdir = @top_srcdir@ -srcdir = @srcdir@ -VPATH = @srcdir@ - -include $(MOD_DEPTH)/config/autoconf.mk - -include $(topsrcdir)/config/config.mk - -ifeq ($(OS_TARGET), OS2) -OS_CFLAGS = $(OS_EXE_CFLAGS) -endif - -CSRCS = gc1.c thrashgc.c - -ifeq (,$(filter-out WINNT OS2,$(OS_ARCH))) -PROG_SUFFIX = .exe -else -PROG_SUFFIX = -endif - -PROGS = $(addprefix $(OBJDIR)/, $(CSRCS:.c=$(PROG_SUFFIX))) - -TARGETS = $(PROGS) $(OBJS) - -INCLUDES = -I$(dist_includedir) - -# Setting the variables LDOPTS and LIBPR. We first initialize -# them to the default values, then adjust them for some platforms. -LDOPTS = -L$(dist_libdir) -NSPR_VERSION = $(MOD_MAJOR_VERSION) -GC_VERSION = $(MOD_MAJOR_VERSION) -LIBPR = -lnspr$(NSPR_VERSION) -LIBPLC = -lplc$(NSPR_VERSION) -LIBGC = -lmsgc$(GC_VERSION) - -ifeq ($(OS_ARCH), WINNT) - LDOPTS = -NOLOGO -DEBUG -INCREMENTAL:NO - LIBPR = $(dist_libdir)/libnspr$(NSPR_VERSION).$(LIB_SUFFIX) - LIBPLC = $(dist_libdir)/libplc$(NSPR_VERSION).$(LIB_SUFFIX) - LIBGC= $(dist_libdir)/libmsgc$(GC_VERSION).$(LIB_SUFFIX) -endif - -ifeq ($(OS_ARCH),OS2) - LDOPTS += -Zomf -Zlinker /PM:VIO -endif - -ifneq ($(OS_ARCH), WINNT) -PWD = $(shell pwd) -endif - -ifeq ($(OS_ARCH), IRIX) -LDOPTS += -rpath $(PWD)/$(dist_libdir) -rdata_shared - -# For 6.x machines, include this flag -ifeq ($(basename $(OS_RELEASE)),6) -ifeq ($(USE_N32),1) -LDOPTS += -n32 -else -LDOPTS += -32 -endif -endif - -endif - -ifeq ($(OS_ARCH), OSF1) -# I haven't figured out how to pass -rpath to cc on OSF1 V3.2, so -# we do static linking. -ifeq ($(OS_RELEASE), V3.2) - LIBPR = $(dist_libdir)/libnspr$(NSPR_VERSION).a - LIBPLC = $(dist_libdir)/libplc$(NSPR_VERSION).a - LIBGC = $(dist_libdir)/libmsgc$(GC_VERSION).a - EXTRA_LIBS = -lc_r -else - LDOPTS += -rpath $(PWD)/$(dist_libdir) -endif -endif - -ifeq ($(OS_ARCH), HP-UX) -LDOPTS += -z -Wl,+s,+b,$(PWD)/$(dist_libdir) -endif - -# AIX -ifeq ($(OS_ARCH),AIX) -LDOPTS += -blibpath:$(PWD)/$(dist_libdir):/usr/lib:/lib -ifeq ($(OS_ARCH)$(OS_RELEASE),AIX4.1) -LIBPR = -lnspr$(NSPR_VERSION)_shr -LIBPLC = -lplc$(NSPR_VERSION)_shr -LIBGC = -lmsgc$(GC_VERSION)_shr -else -LDOPTS += -brtl -EXTRA_LIBS = -ldl -endif -endif - -# Solaris -ifeq ($(OS_ARCH), SunOS) -ifneq ($(OS_RELEASE), 4.1.3_U1) -ifdef NS_USE_GCC -LDOPTS += -Xlinker -R -Xlinker $(PWD)/$(dist_libdir) -else -LDOPTS += -R $(PWD)/$(dist_libdir) -endif -endif - -# SunOS 5.5 needs to link with -lpthread, even though we already -# linked with this system library when we built libnspr.so. -ifeq ($(OS_RELEASE), 5.5) -ifdef USE_PTHREADS -EXTRA_LIBS = -lpthread -endif -endif -endif # SunOS - -ifeq ($(OS_ARCH),NEC) -EXTRA_LIBS = $(OS_LIBS) -# This hardcodes in the executable programs the directory to find -# libnspr.so etc. at program startup. Equivalent to the -R or -rpath -# option for ld on other platforms. -export LD_RUN_PATH = $(PWD)/$(dist_libdir) -endif - -ifeq ($(OS_ARCH), NCR) -# XXX: We see some strange problems when we link with libnspr.so. -# So for now we use static libraries on NCR. The shared library -# stuff below is commented out. -LIBPR = $(dist_libdir)/libnspr$(NSPR_VERSION).a -LIBPLC = $(dist_libdir)/libplc$(NSPR_VERSION).a -LIBGC = $(dist_libdir)/libmsgc$(GC_VERSION).a -EXTRA_LIBS = -lsocket -lnsl -ldl - -# NCR needs to link against -lsocket -lnsl (and -lc, which is linked -# implicitly by $(CC)) again even though we already linked with these -# system libraries when we built libnspr.so. -#EXTRA_LIBS = -lsocket -lnsl -# This hardcodes in the executable programs the directory to find -# libnspr.so etc. at program startup. Equivalent to the -R or -rpath -# option for ld on other platforms. -#export LD_RUN_PATH = $(PWD)/$(dist_libdir) -endif - -ifeq ($(OS_ARCH), Linux) -ifeq ($(OS_RELEASE), 1.2) -EXTRA_LIBS = -ldl -endif -endif - -ifeq ($(OS_ARCH), SCOOS) -# SCO Unix needs to link against -lsocket again even though we -# already linked with these system libraries when we built libnspr.so. -EXTRA_LIBS = -lsocket -# This hardcodes in the executable programs the directory to find -# libnspr.so etc. at program startup. Equivalent to the -R or -rpath -# option for ld on other platforms. -export LD_RUN_PATH = $(PWD)/$(dist_libdir) -endif - -ifeq ($(OS_ARCH),SINIX) -EXTRA_LIBS = -lsocket -lnsl -lresolv -ldl -# This hardcodes in the executable programs the directory to find -# libnspr.so etc. at program startup. Equivalent to the -R or -rpath -# option for ld on other platforms. -export LD_RUN_PATH = $(PWD)/$(dist_libdir) -endif - -ifeq ($(OS_ARCH), UNIXWARE) -export LD_RUN_PATH = $(PWD)/$(dist_libdir) -endif - -ifeq ($(OS_ARCH),BSD_OS) -EXTRA_LIBS = -ldl -endif - -ifeq ($(OS_ARCH),DGUX) -EXTRA_LIBS = -lsocket -lnsl -ldl -endif - -##################################################### -# -# The rules -# -##################################################### - -include $(topsrcdir)/config/rules.mk - -AIX_PRE_4_2 = 0 -ifeq ($(OS_ARCH),AIX) -ifneq ($(OS_RELEASE),4.2) -ifneq ($(USE_PTHREADS), 1) -#AIX_PRE_4_2 = 1 -endif -endif -endif - -ifeq ($(AIX_PRE_4_2),1) - -# AIX releases prior to 4.2 need a special two-step linking hack -# in order to both override the system select() and be able to -# get at the original system select(). -# -# We use a pattern rule in ns/nspr20/config/rules.mk to generate -# the .$(OBJ_SUFFIX) file from the .c source file, then do the -# two-step linking hack below. - -$(OBJDIR)/%: $(OBJDIR)/%.$(OBJ_SUFFIX) - @$(MAKE_OBJDIR) - rm -f $@ $(AIX_TMP) - $(CC) $(AIX_LINK_OPTS) -o $(AIX_TMP) $< $(dist_libdir)/libnspr$(NSPR_VERSION).a - $(CC) -o $@ $(AIX_TMP) $(AIX_WRAP) - rm -f $(AIX_TMP) - -else - -# All platforms that are not AIX pre-4.2. - -$(OBJDIR)/%$(PROG_SUFFIX): $(OBJDIR)/%.$(OBJ_SUFFIX) - @$(MAKE_OBJDIR) -ifeq ($(OS_ARCH), WINNT) - link $(LDOPTS) $< $(LIBGC) $(LIBPLC) $(LIBPR) wsock32.lib -out:$@ -else -ifeq ($(OS_ARCH),OS2) - $(LINK) $(LDOPTS) $< $(LIBGC) $(LIBPLC) $(LIBPR) $(OS_LIBS) $(EXTRA_LIBS) -o $@ -else - $(CC) $(XCFLAGS) $< $(LDOPTS) $(LIBGC) $(LIBPLC) $(LIBPR) $(EXTRA_LIBS) -o $@ -endif -endif -endif - -export:: $(TARGETS) -clean:: - rm -f $(TARGETS)
deleted file mode 100644 --- a/nsprpub/lib/msgc/tests/gc1.c +++ /dev/null @@ -1,242 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * 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 the Netscape Portable Runtime (NSPR). - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either 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. - * - * ***** END LICENSE BLOCK ***** */ - -/*********************************************************************** -** Includes -***********************************************************************/ -/* Used to get the command line option */ -#include "plgetopt.h" - -#include "prgc.h" -#include "prinit.h" -#include "prmon.h" -#include "prinrval.h" -#include "private/pprthred.h" - -#include <stdio.h> -#include <stdlib.h> - -static PRMonitor *mon; -static PRInt32 threads, waiting, iterations; -static PRInt32 scanCount, finalizeCount, freeCount; - -PRIntn failed_already=0; -PRIntn debug_mode; - - -typedef struct Array { - PRUintn size; - void *body[1]; -} Array; - -int arrayTypeIndex; - -static void PR_CALLBACK ScanArray(void *a) -{ -/* printf ("In ScanArray a = %X size = %d \n", a, a->size); */ - scanCount++; -} - -static void PR_CALLBACK FinalizeArray(void *a) -{ -/* printf ("In FinalizeArray a = %X size = %d \n", a, a->size); */ - finalizeCount++; -} - -static void PR_CALLBACK FreeArray(void *a) -{ -/* printf ("In FreeArray\n"); */ - freeCount++; -} - -static Array *NewArray(PRUintn size) -{ - Array *a; - - a = (Array *)PR_AllocMemory(sizeof(Array) + size*sizeof(void*) - 1*sizeof(void*), - arrayTypeIndex, PR_ALLOC_CLEAN); - -/* printf ("In NewArray a = %X \n", a); */ - - if (a) - a->size = size; - return a; -} - -GCType arrayType = { - ScanArray, - FinalizeArray, - 0, - 0, - FreeArray, - 0 -}; - -static void Initialize(void) -{ - PR_InitGC(0, 0, 0, PR_GLOBAL_THREAD); - arrayTypeIndex = PR_RegisterType(&arrayType); -} - -static void PR_CALLBACK AllocateLikeMad(void *arg) -{ - Array *prev; - PRInt32 i; - PRInt32 count; - - count = (PRInt32)arg; - prev = 0; - for (i = 0; i < count; i++) { - Array *leak = NewArray(i & 511); - if ((i & 1023) == 0) { - prev = 0; /* forget */ - } else { - if (i & 1) { - prev = leak; /* remember */ - } - } - } - PR_EnterMonitor(mon); - waiting++; - PR_Notify(mon); - PR_ExitMonitor(mon); -} - -int main(int argc, char **argv) -{ - PRIntervalTime start, stop, usec; - double d; - PRIntn i, totalIterations; - /* The command line argument: -d is used to determine if the test is being run - in debug mode. The regress tool requires only one line output:PASS or FAIL. - All of the printfs associated with this test has been handled with a if (debug_mode) - test. - Usage: test_name -d - */ - PLOptStatus os; - PLOptState *opt = PL_CreateOptState(argc, argv, "dt:c:"); - - threads = 10; - iterations = 100; - - while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) - { - if (PL_OPT_BAD == os) { - fprintf(stderr, "Invalid command-line option\n"); - exit(1); - } - switch (opt->option) - { - case 'd': /* debug mode */ - debug_mode = 1; - break; - case 't': /* number of threads */ - threads = atoi(opt->value); - break; - case 'c': /* iteration count */ - iterations = atoi(opt->value); - break; - default: - break; - } - } - PL_DestroyOptState(opt); - - fprintf(stderr, "t is %ld, i is %ld\n", (long) threads, (long) iterations); - /* main test */ - - PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 5); - PR_STDIO_INIT(); - Initialize(); - - /* Spin all of the allocator threads and then wait for them to exit */ - start = PR_IntervalNow(); - mon = PR_NewMonitor(); - PR_EnterMonitor(mon); - waiting = 0; - for (i = 0; i < threads; i++) { - (void) PR_CreateThreadGCAble(PR_USER_THREAD, - AllocateLikeMad, (void*)iterations, - PR_PRIORITY_NORMAL, - PR_LOCAL_THREAD, - PR_UNJOINABLE_THREAD, - 0); - } - while (waiting != threads) { - PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT); - } - PR_ExitMonitor(mon); - - PR_GC(); - PR_ForceFinalize(); - - totalIterations = iterations * threads; -/* - if (scanCount != totalIterations) - printf ("scanCount discrepancy scanCount = %d totalIterations = %d \n", - scanCount, totalIterations); - if (freeCount != totalIterations) - printf ("freeCount discrepancy freeCount = %d totalIterations = %d \n", - freeCount, totalIterations); - if ((finalizeCount != totalIterations) && (finalizeCount != (totalIterations-1))) - printf ("finalizeCount discrepancy finalizeCount = %d totalIterations = %d \n", - finalizeCount,totalIterations); -*/ - - stop = PR_IntervalNow(); - - usec = stop = stop - start; - d = (double)usec; - - if (debug_mode) printf("%40s: %6.2f usec\n", "GC allocation", d / (iterations * threads)); - else { - if (d == 0.0) failed_already = PR_TRUE; - - } - - PR_Cleanup(); - if(failed_already) - { - printf("FAIL\n"); - return 1; - } - else - { - printf("PASS\n"); - return 0; - } -}
deleted file mode 100644 --- a/nsprpub/lib/msgc/tests/thrashgc.c +++ /dev/null @@ -1,242 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * 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 the Netscape Portable Runtime (NSPR). - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either 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. - * - * ***** END LICENSE BLOCK ***** */ - -/*********************************************************************** -** Name: thrashgc -** -** Description: test garbace collection functions. -** -** Modification History: -** 19-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. -** The debug mode will print all of the printfs associated with this test. -** The regress mode will be the default mode. Since the regress tool limits -** the output to a one line status:PASS or FAIL,all of the printf statements -** have been handled with an if (debug_mode) statement. -** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to -** recognize the return code from tha main program. -***********************************************************************/ -/*********************************************************************** -** Includes -***********************************************************************/ -#include "prthread.h" -#include "prgc.h" -#include "prprf.h" -#include "prinrval.h" -#include "prlock.h" -#include "prinit.h" -#include "prcvar.h" - -#include "private/pprthred.h" - -#include <stdio.h> -#include <memory.h> -#include <string.h> - - -PRIntn failed_already=0; -PRIntn debug_mode; - -static char* progname; -static PRInt32 loops = 1000; -static int tix1, tix2, tix3; -static GCInfo* gcInfo; -static PRLock* stderrLock; - -typedef struct Type1 Type1; -typedef struct Type2 Type2; - -struct Type1 { - Type2* atwo; - Type1* next; -}; - -struct Type2 { - void* buf; -}; - -static void PR_CALLBACK ScanType1(void *obj) { - gcInfo->livePointer(((Type1 *)obj)->atwo); - gcInfo->livePointer(((Type1 *)obj)->next); -} - -static void PR_CALLBACK ScanType2(void *obj) { - gcInfo->livePointer(((Type2 *)obj)->buf); -} - -static GCType type1 = { - ScanType1 -}; - -static GCType type2 = { - ScanType2 -/* (void (*)(void*)) ScanType2 */ -}; - -static GCType type3 = { - 0 -}; - -Type1* NewType1(void) { - Type1* p = (Type1*) PR_AllocMemory(sizeof(Type1), tix1, PR_ALLOC_DOUBLE); - PR_ASSERT(p != NULL); - return p; -} - -Type2* NewType2(void) { - Type2* p = (Type2*) PR_AllocMemory(sizeof(Type2), tix2, PR_ALLOC_DOUBLE); - PR_ASSERT(p != NULL); - return p; -} - -void* NewBuffer(PRInt32 size) { - void* p = PR_AllocMemory(size, tix3, PR_ALLOC_DOUBLE); - PR_ASSERT(p != NULL); - return p; -} - -/* Allocate alot of garbage */ -static void PR_CALLBACK AllocStuff(void *unused) { - PRInt32 i; - void* danglingRefs[50]; - PRIntervalTime start, end; - char msg[100]; - - start = PR_IntervalNow(); - for (i = 0; i < loops; i++) { - void* p; - if (i & 1) { - Type1* t1 = NewType1(); - t1->atwo = NewType2(); - t1->next = NewType1(); - t1->atwo->buf = NewBuffer(100); - p = t1; - } else { - Type2* t2 = NewType2(); - t2->buf = NewBuffer(i & 16383); - p = t2; - } - if ((i % 10) == 0) { - memmove(&danglingRefs[0], &danglingRefs[1], 49*sizeof(void*)); - danglingRefs[49] = p; - } - } - end = PR_IntervalNow(); - if (debug_mode) PR_snprintf(msg, sizeof(msg), "Thread %p: %ld allocations took %ld ms", - PR_GetCurrentThread(), loops, - PR_IntervalToMilliseconds((PRIntervalTime) (end - start))); - PR_Lock(stderrLock); - fprintf(stderr, "%s\n", msg); - PR_Unlock(stderrLock); - } - -static void usage(char *progname) { - fprintf(stderr, "Usage: %s [-t threads] [-l loops]\n", progname); - exit(-1); -} - -static int realMain(int argc, char **argv, char *notused) { - int i; - int threads = 0; - - progname = strrchr(argv[0], '/'); - if (progname == 0) progname = argv[0]; - for (i = 1; i < argc; i++) { - if (strcmp(argv[i], "-t") == 0) { - if (i == argc - 1) { - usage(progname); - } - threads = atoi(argv[++i]); - if (threads < 0) threads = 0; - if (threads > 10000) threads = 10000; - continue; - } - if (strcmp(argv[i], "-l") == 0) { - if (i == argc - 1) { - usage(progname); - } - loops = atoi(argv[++i]); - continue; - } - usage(progname); - } - - for (i = 0; i < threads; i++) { - PRThread* thread; - - /* XXXXX */ - thread = PR_CreateThreadGCAble(PR_USER_THREAD, /* thread type */ - AllocStuff, /* start function */ - NULL, /* arg */ - PR_PRIORITY_NORMAL, /* priority */ - PR_LOCAL_THREAD, /* thread scope */ - PR_UNJOINABLE_THREAD, /* thread state */ - 0); /* stack size */ - if (thread == 0) { - fprintf(stderr, "%s: no more threads (only %d were created)\n", - progname, i); - break; - } - } - AllocStuff(NULL); - return 0; -} - -static int padMain(int argc, char **argv) { - char pad[512]; - return realMain(argc, argv, pad); -} - -int main(int argc, char **argv) { - int rv; - - debug_mode = 1; - - PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); - PR_SetThreadGCAble(); - - PR_InitGC(0, 0, 0, PR_GLOBAL_THREAD); - PR_STDIO_INIT(); - stderrLock = PR_NewLock(); - tix1 = PR_RegisterType(&type1); - tix2 = PR_RegisterType(&type2); - tix3 = PR_RegisterType(&type3); - gcInfo = PR_GetGCInfo(); - rv = padMain(argc, argv); - printf("PASS\n"); - PR_Cleanup(); - return rv; -}
--- a/nsprpub/pr/include/md/_darwin.h +++ b/nsprpub/pr/include/md/_darwin.h @@ -37,39 +37,42 @@ #ifndef nspr_darwin_defs_h___ #define nspr_darwin_defs_h___ #include "prthread.h" #include <sys/syscall.h> -#ifdef XP_MACOSX +#ifdef __APPLE__ #include <AvailabilityMacros.h> +#include <TargetConditionals.h> #endif #define PR_LINKER_ARCH "darwin" #define _PR_SI_SYSNAME "DARWIN" #ifdef __i386__ #define _PR_SI_ARCHITECTURE "x86" #elif defined(__x86_64__) #define _PR_SI_ARCHITECTURE "x86-64" #elif defined(__ppc__) #define _PR_SI_ARCHITECTURE "ppc" +#elif defined(__arm__) +#define _PR_SI_ARCHITECTURE "arm" #endif #define PR_DLL_SUFFIX ".dylib" #define _PR_VMBASE 0x30000000 #define _PR_STACK_VMBASE 0x50000000 #define _MD_DEFAULT_STACK_SIZE 65536L #define _MD_MMAP_FLAGS MAP_PRIVATE #undef HAVE_STACK_GROWING_UP #define HAVE_DLL -#ifdef __x86_64__ +#if defined(__x86_64__) || TARGET_OS_IPHONE #define USE_DLFCN #else #define USE_MACH_DYLD #endif #define _PR_HAVE_SOCKADDR_LEN #define _PR_STAT_HAS_ST_ATIMESPEC #define _PR_HAVE_LARGE_OFF_T #define _PR_HAVE_SYSV_SEMAPHORES
--- a/nsprpub/pr/include/prinit.h +++ b/nsprpub/pr/include/prinit.h @@ -58,21 +58,21 @@ PR_BEGIN_EXTERN_C /* ** NSPR's version is used to determine the likelihood that the version you ** used to build your component is anywhere close to being compatible with ** what is in the underlying library. ** ** The format of the version string is ** "<major version>.<minor version>[.<patch level>] [<Beta>]" */ -#define PR_VERSION "4.8.9" +#define PR_VERSION "4.9 Beta" #define PR_VMAJOR 4 -#define PR_VMINOR 8 -#define PR_VPATCH 9 -#define PR_BETA PR_FALSE +#define PR_VMINOR 9 +#define PR_VPATCH 0 +#define PR_BETA PR_TRUE /* ** PRVersionCheck ** ** The basic signature of the function that is called to provide version ** checking. The result will be a boolean that indicates the likelihood ** that the underling library will perform as the caller expects. **
--- a/nsprpub/pr/include/prtypes.h +++ b/nsprpub/pr/include/prtypes.h @@ -338,33 +338,50 @@ typedef long PRInt32; ** TYPES: PRUint64 ** PRInt64 ** DESCRIPTION: ** The int64 types are known to be 64 bits each. Care must be used when ** declaring variables of type PRUint64 or PRInt64. Different hardware ** architectures and even different compilers have varying support for ** 64 bit values. The only guaranteed portability requires the use of ** the LL_ macros (see prlong.h). +** +** MACROS: PR_INT64 +** PR_UINT64 +** DESCRIPTION: +** The PR_INT64 and PR_UINT64 macros provide a portable way for +** specifying 64-bit integer constants. They can only be used if +** PRInt64 and PRUint64 are defined as compiler-supported 64-bit +** integer types (i.e., if HAVE_LONG_LONG is defined, which is true +** for all the supported compilers topday). If PRInt64 and PRUint64 +** are defined as structs, the LL_INIT macro defined in prlong.h has +** to be used. ************************************************************************/ #ifdef HAVE_LONG_LONG /* Keep this in sync with prlong.h. */ /* * On 64-bit Mac OS X, uint64 needs to be defined as unsigned long long to * match uint64_t, otherwise our uint64 typedef conflicts with the uint64 * typedef in cssmconfig.h, which CoreServices.h includes indirectly. */ #if PR_BYTES_PER_LONG == 8 && !defined(__APPLE__) typedef long PRInt64; typedef unsigned long PRUint64; +#define PR_INT64(x) x ## L +#define PR_UINT64(x) x ## UL #elif defined(WIN32) && !defined(__GNUC__) typedef __int64 PRInt64; typedef unsigned __int64 PRUint64; +#define PR_INT64(x) x ## i64 +#define PR_UINT64(x) x ## ui64 #else typedef long long PRInt64; typedef unsigned long long PRUint64; +#define PR_INT64(x) x ## LL +#define PR_UINT64(x) x ## ULL #endif /* PR_BYTES_PER_LONG == 8 */ #else /* !HAVE_LONG_LONG */ typedef struct { #ifdef IS_LITTLE_ENDIAN PRUint32 lo, hi; #else PRUint32 hi, lo; #endif
--- a/nsprpub/pr/src/md/unix/uxproces.c +++ b/nsprpub/pr/src/md/unix/uxproces.c @@ -43,17 +43,19 @@ #include <signal.h> #include <sys/wait.h> #include <string.h> #if defined(AIX) #include <dlfcn.h> /* For dlopen, dlsym, dlclose */ #endif #if defined(DARWIN) +#if defined(HAVE_CRT_EXTERNS_H) #include <crt_externs.h> +#endif #else PR_IMPORT_DATA(char **) environ; #endif /* * HP-UX 9 doesn't have the SA_RESTART flag. */ #ifndef SA_RESTART @@ -180,21 +182,28 @@ ForkAndExec( } childEnvp = envp; if (attr && attr->fdInheritBuffer) { PRBool found = PR_FALSE; if (NULL == childEnvp) { #ifdef DARWIN +#ifdef HAVE_CRT_EXTERNS_H childEnvp = *(_NSGetEnviron()); #else + PR_DELETE(process); + PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); + return NULL; +#endif +#else childEnvp = environ; #endif } + for (nEnv = 0; childEnvp[nEnv]; nEnv++) { } newEnvp = (char **) PR_MALLOC((nEnv + 2) * sizeof(char *)); if (NULL == newEnvp) { PR_DELETE(process); PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return NULL; }
--- a/nsprpub/pr/tests/vercheck.c +++ b/nsprpub/pr/tests/vercheck.c @@ -47,47 +47,47 @@ */ #include "prinit.h" #include <stdio.h> #include <stdlib.h> /* - * This release (4.8.9) is backward compatible with the + * This release (4.9) is backward compatible with the * 4.0.x, 4.1.x, 4.2.x, 4.3.x, 4.4.x, 4.5.x, 4.6.x, 4.7.x, - * 4.8, 4.8.1, 4.8.2, 4.8.3, 4.8.4, 4.8.5, 4.8.6, 4.8.7, and - * 4.8.8 releases. It, of course, is compatible with itself. + * and 4.8.x releases. It, of course, is compatible with itself. */ static char *compatible_version[] = { "4.0", "4.0.1", "4.1", "4.1.1", "4.1.2", "4.1.3", "4.2", "4.2.1", "4.2.2", "4.3", "4.4", "4.4.1", "4.5", "4.5.1", "4.6", "4.6.1", "4.6.2", "4.6.3", "4.6.4", "4.6.5", "4.6.6", "4.6.7", "4.6.8", "4.7", "4.7.1", "4.7.2", "4.7.3", "4.7.4", "4.7.5", "4.7.6", "4.8", "4.8.1", "4.8.2", "4.8.3", "4.8.4", "4.8.5", - "4.8.6", "4.8.7", "4.8.8", PR_VERSION + "4.8.6", "4.8.7", "4.8.8", "4.8.9", + PR_VERSION }; /* * This release is not backward compatible with the old * NSPR 2.1 and 3.x releases. * * Any release is incompatible with future releases and * patches. */ static char *incompatible_version[] = { "2.1 19980529", "3.0", "3.0.1", "3.1", "3.1.1", "3.1.2", "3.1.3", "3.5", "3.5.1", - "4.8.10", - "4.9", "4.9.1", + "4.9.1", + "4.10", "4.10.1", "10.0", "11.1", "12.14.20" }; int main(int argc, char **argv) { int idx; int num_compatible = sizeof(compatible_version) / sizeof(char *); int num_incompatible = sizeof(incompatible_version) / sizeof(char *);