Merge cvs-trunk-mirror -> mozilla-central to pick up the 421274 backout especially
authorbenjamin@smedbergs.us
Thu, 13 Mar 2008 15:26:42 -0400
changeset 13024 5be6ee5eedaffe5c440670f908dd8d6a2f1b22ab
parent 13007 8f4b429275a5e05b3baa46a147237f53fe26b208 (current diff)
parent 13023 69342997f2acd1152abb6539d12fd0ee2ba81cf9 (diff)
child 13025 9df334adb143da61887e8ccbf56a090111e6efc4
push idunknown
push userunknown
push dateunknown
bugs421274
milestone2.0a1pre
Merge cvs-trunk-mirror -> mozilla-central to pick up the 421274 backout especially
configure.in
js/src/Makefile.in
js/src/js.cpp
js/src/jsapi.cpp
js/src/jscntxt.cpp
js/src/jsdbgapi.cpp
js/src/jsexn.cpp
js/src/jsfun.cpp
js/src/jsgc.cpp
js/src/jsinterp.cpp
js/src/jsiter.cpp
js/src/jsobj.cpp
js/src/jsopcode.cpp
js/src/jsstr.cpp
js/src/jsxml.cpp
--- a/accessible/src/atk/nsAccessibleWrap.cpp
+++ b/accessible/src/atk/nsAccessibleWrap.cpp
@@ -797,22 +797,16 @@ GetAttributeSet(nsIAccessible* aAccessib
         PRUint32 state;
         aAccessible->GetFinalState(&state, nsnull);
         if (state & nsIAccessibleStates::STATE_HASPOPUP) {
           // There is no ATK state for haspopup, must use object attribute to expose the same info
           nsAutoString oldValueUnused;
           attributes->SetStringProperty(NS_LITERAL_CSTRING("haspopup"), NS_LITERAL_STRING("true"),
                                         oldValueUnused);
         }
-        if (state & nsIAccessibleStates::STATE_CHECKABLE) {
-          // There is no ATK state for haspopup, must use object attribute to expose the same info
-          nsAutoString oldValueUnused;
-          attributes->SetStringProperty(NS_LITERAL_CSTRING("checkable"), NS_LITERAL_STRING("true"),
-                                        oldValueUnused);
-        }
 
         nsCOMPtr<nsISimpleEnumerator> propEnum;
         nsresult rv = attributes->Enumerate(getter_AddRefs(propEnum));
         NS_ENSURE_SUCCESS(rv, nsnull);
 
         PRBool hasMore;
         while (NS_SUCCEEDED(propEnum->HasMoreElements(&hasMore)) && hasMore) {
             nsCOMPtr<nsISupports> sup;
--- a/accessible/src/base/nsARIAMap.cpp
+++ b/accessible/src/base/nsARIAMap.cpp
@@ -91,23 +91,22 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] 
             {&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
             {&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
             {&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY}, kEndEntry},
   {"group", nsIAccessibleRole::ROLE_GROUPING, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
   {"heading", nsIAccessibleRole::ROLE_HEADING, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
   {"img", nsIAccessibleRole::ROLE_GRAPHIC, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
   {"label", nsIAccessibleRole::ROLE_LABEL, eNameOkFromChildren, eNoValue, kNoReqStates, kEndEntry},
   {"link", nsIAccessibleRole::ROLE_LINK, eNameOkFromChildren, eNoValue, nsIAccessibleStates::STATE_LINKED, kEndEntry},
-  {"list", nsIAccessibleRole::ROLE_LIST, eNameLabelOrTitle, eNoValue, kNoReqStates,
-            {&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
+  {"list", nsIAccessibleRole::ROLE_LIST, eNameLabelOrTitle, eNoValue, nsIAccessibleStates::STATE_READONLY,
             {&nsAccessibilityAtoms::aria_multiselectable, kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE}, kEndEntry},
   {"listbox", nsIAccessibleRole::ROLE_LISTBOX, eNameLabelOrTitle, eNoValue, kNoReqStates,
             {&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
             {&nsAccessibilityAtoms::aria_multiselectable, kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE}, kEndEntry},
-  {"listitem", nsIAccessibleRole::ROLE_LISTITEM, eNameOkFromChildren, eNoValue, kNoReqStates,
+  {"listitem", nsIAccessibleRole::ROLE_LISTITEM, eNameOkFromChildren, eNoValue, nsIAccessibleStates::STATE_READONLY,
             {&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
             {&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
             {&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED | nsIAccessibleStates::STATE_CHECKABLE},
             {&nsAccessibilityAtoms::aria_checked, "mixed", nsIAccessibleStates::STATE_MIXED | nsIAccessibleStates::STATE_CHECKABLE},
             {&nsAccessibilityAtoms::aria_checked, "false", nsIAccessibleStates::STATE_CHECKABLE}, kEndEntry},
   {"menu", nsIAccessibleRole::ROLE_MENUPOPUP, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
   {"menubar", nsIAccessibleRole::ROLE_MENUBAR, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
   {"menuitem", nsIAccessibleRole::ROLE_MENUITEM, eNameOkFromChildren, eNoValue, kNoReqStates,
--- a/accessible/src/base/nsAccessibilityAtomList.h
+++ b/accessible/src/base/nsAccessibilityAtomList.h
@@ -152,16 +152,17 @@ ACCESSIBILITY_ATOM(ul, "ul")
   // Alphabetical list of attributes
 ACCESSIBILITY_ATOM(acceltext, "acceltext")
 ACCESSIBILITY_ATOM(accesskey, "accesskey")
 ACCESSIBILITY_ATOM(alt, "alt")
 ACCESSIBILITY_ATOM(anonid, "anonid") // Used for ID's in XBL
 ACCESSIBILITY_ATOM(contenteditable, "contenteditable")
 ACCESSIBILITY_ATOM(control, "control")
 ACCESSIBILITY_ATOM(disabled, "disabled")
+ACCESSIBILITY_ATOM(_class, "class")
 ACCESSIBILITY_ATOM(cycles, "cycles") // used for XUL cycler attribute
 ACCESSIBILITY_ATOM(curpos, "curpos") // XUL
 ACCESSIBILITY_ATOM(data, "data")
 ACCESSIBILITY_ATOM(droppable, "droppable")   // XUL combo box
 ACCESSIBILITY_ATOM(editable, "editable")
 ACCESSIBILITY_ATOM(_for, "for")
 ACCESSIBILITY_ATOM(hidden, "hidden")   // XUL tree columns
 ACCESSIBILITY_ATOM(href, "href")
--- a/accessible/src/base/nsAccessibilityUtils.cpp
+++ b/accessible/src/base/nsAccessibilityUtils.cpp
@@ -902,8 +902,34 @@ nsAccUtils::GetRoleMapEntry(nsIDOMNode *
     }
   }
 
   // Always use some entry if there is a role string
   // To ensure an accessible object is created
   return &nsARIAMap::gLandmarkRoleMap;
 }
 
+PRBool
+nsAccUtils::IsARIAPropForObjectAttr(nsIAtom *aAtom)
+{
+  return aAtom != nsAccessibilityAtoms::aria_activedescendant &&
+         aAtom != nsAccessibilityAtoms::aria_checked &&
+         aAtom != nsAccessibilityAtoms::aria_controls &&
+         aAtom != nsAccessibilityAtoms::aria_describedby &&
+         aAtom != nsAccessibilityAtoms::aria_disabled &&
+         aAtom != nsAccessibilityAtoms::aria_expanded &&
+         aAtom != nsAccessibilityAtoms::aria_flowto &&
+         aAtom != nsAccessibilityAtoms::aria_invalid &&
+         aAtom != nsAccessibilityAtoms::aria_haspopup &&
+         aAtom != nsAccessibilityAtoms::aria_labelledby &&
+         aAtom != nsAccessibilityAtoms::aria_multiline &&
+         aAtom != nsAccessibilityAtoms::aria_multiselectable &&
+         aAtom != nsAccessibilityAtoms::aria_owns &&
+         aAtom != nsAccessibilityAtoms::aria_pressed &&
+         aAtom != nsAccessibilityAtoms::aria_readonly &&
+         aAtom != nsAccessibilityAtoms::aria_relevant &&
+         aAtom != nsAccessibilityAtoms::aria_required &&
+         aAtom != nsAccessibilityAtoms::aria_selected &&
+         aAtom != nsAccessibilityAtoms::aria_valuemax &&
+         aAtom != nsAccessibilityAtoms::aria_valuemin &&
+         aAtom != nsAccessibilityAtoms::aria_valuenow &&
+         aAtom != nsAccessibilityAtoms::aria_valuetext;
+}
--- a/accessible/src/base/nsAccessibilityUtils.h
+++ b/accessible/src/base/nsAccessibilityUtils.h
@@ -358,12 +358,15 @@ public:
 
   // Helper for FindDescendantPointingToID(), same args
   static nsIContent *FindDescendantPointingToIDImpl(nsCString& aIdWithSpaces,
                                                     nsIContent *aLookContent,
                                                     nsIAtom **aRelationAttrs,
                                                     PRUint32 aAttrNum = 1,
                                                     nsIContent *aExcludeContent = nsnull,
                                                     nsIAtom *aTagType = nsAccessibilityAtoms::label);
+  
+  // Return PR_TRUE if the ARIA property should always be exposed as an object attribute
+  static PRBool IsARIAPropForObjectAttr(nsIAtom *aAtom);
 };
 
 #endif
 
--- a/accessible/src/base/nsAccessible.cpp
+++ b/accessible/src/base/nsAccessible.cpp
@@ -82,16 +82,17 @@
 #include "nsIPrefService.h"
 #include "nsIPrefBranch.h"
 #include "nsIURI.h"
 #include "nsITimer.h"
 #include "nsIMutableArray.h"
 #include "nsIObserverService.h"
 #include "nsIServiceManager.h"
 #include "nsWhitespaceTokenizer.h"
+#include "nsAttrName.h"
 
 #ifdef NS_DEBUG
 #include "nsIFrameDebug.h"
 #include "nsIDOMCharacterData.h"
 #endif
 
 /**
  * nsAccessibleDOMStringList implementation
@@ -1961,21 +1962,27 @@ NS_IMETHODIMP nsAccessible::GetFinalRole
                                       nsAccessibilityAtoms::_true, eCaseMatters)) {
           // For button with aria-haspopup="true"
           *aRole = nsIAccessibleRole::ROLE_BUTTONMENU;
         }
       }
     }
     else if (*aRole == nsIAccessibleRole::ROLE_LISTBOX) {
       // A listbox inside of a combo box needs a special role because of ATK mapping to menu
-      nsCOMPtr<nsIAccessible> parent;
-      GetParent(getter_AddRefs(parent));
-      if (parent && Role(parent) == nsIAccessibleRole::ROLE_COMBOBOX) {
+      nsCOMPtr<nsIAccessible> possibleCombo;
+      GetParent(getter_AddRefs(possibleCombo));
+      if (possibleCombo && Role(possibleCombo) == nsIAccessibleRole::ROLE_COMBOBOX) {
         *aRole = nsIAccessibleRole::ROLE_COMBOBOX_LIST;
       }
+      else {   // Check to see if combo owns the listbox instead
+        GetAccessibleRelated(nsIAccessibleRelation::RELATION_NODE_CHILD_OF, getter_AddRefs(possibleCombo));
+        if (possibleCombo && Role(possibleCombo) == nsIAccessibleRole::ROLE_COMBOBOX) {
+          *aRole = nsIAccessibleRole::ROLE_COMBOBOX_LIST;
+        }
+      }
     }
     else if (*aRole == nsIAccessibleRole::ROLE_OPTION) {
       nsCOMPtr<nsIAccessible> parent;
       GetParent(getter_AddRefs(parent));
       if (parent && Role(parent) == nsIAccessibleRole::ROLE_COMBOBOX_LIST) {
         *aRole = nsIAccessibleRole::ROLE_COMBOBOX_OPTION;
       }
     }
@@ -2013,79 +2020,85 @@ nsAccessible::GetAttributes(nsIPersisten
   nsresult rv = GetAttributesInternal(attributes);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsAutoString id;
   nsAutoString oldValueUnused;
   if (nsAccUtils::GetID(content, id)) {
     attributes->SetStringProperty(NS_LITERAL_CSTRING("id"), id, oldValueUnused);
   }
+  
+  nsAutoString _class;
+  if (content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::_class, _class))
+    nsAccUtils::SetAccAttr(attributes, nsAccessibilityAtoms::_class, _class);
 
   nsAutoString xmlRoles;
   if (content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::role, xmlRoles)) {
     attributes->SetStringProperty(NS_LITERAL_CSTRING("xml-roles"),  xmlRoles, oldValueUnused);          
   }
 
-  // Make sure to keep these two arrays in sync
-  char *ariaPropertyString[] = { "live", "channel", "atomic", "relevant", "datatype", "level",
-                             "posinset", "setsize", "sort", "grab", "dropeffect"};
-  nsIAtom *ariaPropertyEnum[] = { nsAccessibilityAtoms::aria_live, nsAccessibilityAtoms::aria_channel, nsAccessibilityAtoms::aria_atomic, nsAccessibilityAtoms::aria_relevant,
-                                     nsAccessibilityAtoms::aria_datatype, nsAccessibilityAtoms::aria_level, nsAccessibilityAtoms::aria_posinset, nsAccessibilityAtoms::aria_setsize,
-                                     nsAccessibilityAtoms::aria_sort, nsAccessibilityAtoms::aria_grab, nsAccessibilityAtoms::aria_dropeffect};
-  NS_ASSERTION(NS_ARRAY_LENGTH(ariaPropertyString) == NS_ARRAY_LENGTH(ariaPropertyEnum),
-               "ARIA attributes and object property name arrays out of sync");
-  for (PRUint32 index = 0; index < NS_ARRAY_LENGTH(ariaPropertyString); index ++) {
-    nsAutoString value;
-    if (content->GetAttr(kNameSpaceID_None, ariaPropertyEnum[index], value)) {
-      ToLowerCase(value);
-      attributes->SetStringProperty(nsDependentCString(ariaPropertyString[index]), value, oldValueUnused);    
-    }
-  }
-
   nsCOMPtr<nsIAccessibleValue> supportsValue = do_QueryInterface(static_cast<nsIAccessible*>(this));
   if (supportsValue) {
     // We support values, so expose the string value as well, via the valuetext object attribute
     // We test for the value interface because we don't want to expose traditional get_accValue()
     // information such as URL's on links and documents, or text in an input
     nsAutoString valuetext;
     GetValue(valuetext);
     attributes->SetStringProperty(NS_LITERAL_CSTRING("valuetext"), valuetext, oldValueUnused);
   }
 
 
   // Get container-foo computed live region properties based on the closest container with
   // the live region attribute
   nsAutoString atomic, live, relevant, channel, busy;
-  while (content) {
+  nsIContent *ancestor = content;
+  while (ancestor) {
     if (relevant.IsEmpty() &&
-        content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_relevant, relevant))
+        ancestor->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_relevant, relevant))
       attributes->SetStringProperty(NS_LITERAL_CSTRING("container-relevant"), relevant, oldValueUnused);
     if (live.IsEmpty() &&
-        content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_live, live))
+        ancestor->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_live, live))
       attributes->SetStringProperty(NS_LITERAL_CSTRING("container-live"), live, oldValueUnused);
     if (channel.IsEmpty() &&
-        content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_channel, channel))
+        ancestor->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_channel, channel))
       attributes->SetStringProperty(NS_LITERAL_CSTRING("container-channel"), channel, oldValueUnused);
     if (atomic.IsEmpty() &&
-        content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_atomic, atomic))
+        ancestor->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_atomic, atomic))
       attributes->SetStringProperty(NS_LITERAL_CSTRING("container-atomic"), atomic, oldValueUnused);
     if (busy.IsEmpty() &&
-        content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_busy, busy))
+        ancestor->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_busy, busy))
       attributes->SetStringProperty(NS_LITERAL_CSTRING("container-busy"), busy, oldValueUnused);
-    content = content->GetParent();
+    ancestor = ancestor->GetParent();
   }
 
+  PRUint32 role = Role(this);
+  if (role == nsIAccessibleRole::ROLE_CHECKBUTTON ||
+      role == nsIAccessibleRole::ROLE_PUSHBUTTON ||
+      role == nsIAccessibleRole::ROLE_MENUITEM ||
+      role == nsIAccessibleRole::ROLE_LISTITEM ||
+      role == nsIAccessibleRole::ROLE_OUTLINEITEM ||
+      content->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_checked)) {
+    // Might be checkable -- checking role & ARIA attribute first is faster than getting state
+    PRUint32 state = 0;
+    GetFinalState(&state, nsnull);
+    if (state & nsIAccessibleStates::STATE_CHECKABLE) {
+      // No official state for checkable, so use object attribute to expose that
+      attributes->SetStringProperty(NS_LITERAL_CSTRING("checkable"), NS_LITERAL_STRING("true"),
+                                    oldValueUnused);
+    }
+  }
+
+  // Level/setsize/posinset
   if (!nsAccUtils::HasAccGroupAttrs(attributes)) {
     // The role of an accessible can be pointed by ARIA attribute but ARIA
     // posinset, level, setsize may be skipped. Therefore we calculate here
     // these properties to map them into description.
 
     // If accessible is invisible we don't want to calculate group ARIA
     // attributes for it.
-    PRUint32 role = Role(this);
     if ((role == nsIAccessibleRole::ROLE_LISTITEM ||
         role == nsIAccessibleRole::ROLE_MENUITEM ||
         role == nsIAccessibleRole::ROLE_RADIOBUTTON ||
         role == nsIAccessibleRole::ROLE_PAGETAB ||
         role == nsIAccessibleRole::ROLE_OUTLINEITEM) &&
         0 == (State(this) & nsIAccessibleStates::STATE_INVISIBLE)) {
       nsCOMPtr<nsIAccessible> parent = GetParent();
       NS_ENSURE_TRUE(parent, NS_ERROR_FAILURE);
@@ -2131,16 +2144,35 @@ nsAccessible::GetAttributes(nsIPersisten
         }
       }
 
       nsAccUtils::SetAccGroupAttrs(attributes, groupLevel, positionInGroup,
                                    setSize);
     }
   }
 
+  // Expose all ARIA attributes
+  PRUint32 numAttrs = content->GetAttrCount();
+  for (PRUint32 count = 0; count < numAttrs; count ++) {
+    const nsAttrName *attr = content->GetAttrNameAt(count);
+    if (attr && attr->NamespaceEquals(kNameSpaceID_None)) {
+      nsIAtom *attrAtom = attr->Atom();
+      const char *attrStr;
+      attrAtom->GetUTF8String(&attrStr);
+      if (PL_strncmp(attrStr, "aria-", 5)) 
+        continue; // Not ARIA
+      if (!nsAccUtils::IsARIAPropForObjectAttr(attrAtom))
+        continue; // No need to expose obj attribute -- will be exposed some other way
+      nsAutoString value;
+      if (content->GetAttr(kNameSpaceID_None, attrAtom, value)) {
+        attributes->SetStringProperty(nsDependentCString(attrStr + 5), value, oldValueUnused);
+      }
+    }
+  }
+
   attributes.swap(*aAttributes);
 
   return NS_OK;
 }
 
 nsresult
 nsAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
 {
@@ -2303,17 +2335,16 @@ nsAccessible::GetFinalState(PRUint32 *aS
     }
   }
 
   PRUint32 role;
   rv = GetFinalRole(&role);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (role == nsIAccessibleRole::ROLE_ENTRY ||
-      role == nsIAccessibleRole::ROLE_PASSWORD_TEXT ||
       role == nsIAccessibleRole::ROLE_COMBOBOX) {
 
     nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
     NS_ENSURE_STATE(content);
 
     nsAutoString autocomplete;
     if (content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_autocomplete, autocomplete) &&
         (autocomplete.EqualsIgnoreCase("inline") ||
@@ -2322,16 +2353,20 @@ nsAccessible::GetFinalState(PRUint32 *aS
       *aExtraState |= nsIAccessibleStates::EXT_STATE_SUPPORTS_AUTOCOMPLETION;
     }
 
     // XXX We can remove this hack once we support RDF-based role & state maps
     if (mRoleMapEntry && mRoleMapEntry->role == nsIAccessibleRole::ROLE_ENTRY) {
       PRBool isMultiLine = content->AttrValueIs(kNameSpaceID_None, nsAccessibilityAtoms::aria_multiline,
                                                 nsAccessibilityAtoms::_true, eCaseMatters);
       *aExtraState |= isMultiLine ? nsIAccessibleStates::EXT_STATE_MULTI_LINE : nsIAccessibleStates::EXT_STATE_SINGLE_LINE;
+      if (0 == (*aState & nsIAccessibleStates::STATE_READONLY))
+        *aExtraState |= nsIAccessibleStates::EXT_STATE_EDITABLE; // Not readonly
+      else  // We're readonly: make sure editable state wasn't set by impl class
+        *aExtraState &= ~nsIAccessibleStates::EXT_STATE_EDITABLE;
     }
   }
 
   // For some reasons DOM node may have not a frame. We tract such accessibles
   // as invisible.
   nsIFrame *frame = GetFrame();
   if (!frame)
     return NS_OK;
@@ -2383,23 +2418,16 @@ nsAccessible::GetARIAState()
       MappedAttrState(content, &ariaState, &mRoleMapEntry->attributeMap3) &&
       MappedAttrState(content, &ariaState, &mRoleMapEntry->attributeMap4) &&
       MappedAttrState(content, &ariaState, &mRoleMapEntry->attributeMap5) &&
       MappedAttrState(content, &ariaState, &mRoleMapEntry->attributeMap6) &&
       MappedAttrState(content, &ariaState, &mRoleMapEntry->attributeMap7)) {
     MappedAttrState(content, &ariaState, &mRoleMapEntry->attributeMap8);
   }
 
-  if (ariaState & nsIAccessibleStates::STATE_UNAVAILABLE) {
-    // Disabled elements are not selectable or focusable, even if disabled
-    // via DHTML accessibility disabled property
-    ariaState &= ~(nsIAccessibleStates::STATE_SELECTABLE |
-                   nsIAccessibleStates::STATE_FOCUSABLE);
-  }
-
   return ariaState;
 }
 
 // Not implemented by this class
 
 /* DOMString getValue (); */
 NS_IMETHODIMP nsAccessible::GetValue(nsAString& aValue)
 {
--- a/browser/components/build/Makefile.in
+++ b/browser/components/build/Makefile.in
@@ -8,18 +8,20 @@ include $(DEPTH)/config/autoconf.mk
 MODULE = browsercomps
 LIBRARY_NAME = browsercomps
 SHORT_LIBNAME = brwsrcmp
 IS_COMPONENT = 1
 MODULE_NAME = nsBrowserCompsModule
 FORCE_SHARED_LIB = 1
 
 # Because we are an application component, link against the CRT statically
-# (on Windows)
+# (on Windows, but only if we're not building our own CRT for jemalloc)
+ifndef MOZ_MEMORY
 USE_STATIC_LIBS = 1
+endif
 
 REQUIRES = \
 	xpcom \
 	string \
 	rdf \
 	uriloader \
 	intl \
 	necko \
--- a/browser/components/dirprovider/Makefile.in
+++ b/browser/components/dirprovider/Makefile.in
@@ -47,18 +47,20 @@ LIBRARY_NAME         = browserdirprovide
 ifneq ($(OS_ARCH),WINNT)
 SHORT_LIBNAME        = brwsrdir
 endif
 IS_COMPONENT         = 1
 MODULE_NAME          = BrowserDirProvider
 FORCE_SHARED_LIB     = 1
 
 # Because we are an application component, link against the CRT statically
-# (on Windows)
+# (on Windows, but only if we're not building our own CRT for jemalloc)
+ifndef MOZ_MEMORY
 USE_STATIC_LIBS      = 1
+endif
 
 REQUIRES = \
 	xpcom \
 	string \
 	pref \
 	xulapp \
 	$(NULL)
 
--- a/browser/components/feeds/src/Makefile.in
+++ b/browser/components/feeds/src/Makefile.in
@@ -40,17 +40,19 @@ srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE = browser_feeds
 LIBRARY_NAME = browser_feeds_s
 FORCE_STATIC_LIB = 1
 FORCE_USE_PIC = 1
+ifndef MOZ_MEMORY
 USE_STATIC_LIBS = 1
+endif
 
 DEFINES += \
 	-DMOZ_APP_NAME=$(MOZ_APP_NAME) \
 	-DMOZ_APP_DISPLAYNAME=$(MOZ_APP_DISPLAYNAME) \
 	$(NULL)
 
 EXTRA_PP_COMPONENTS = \
 	FeedConverter.js \
--- a/browser/components/migration/src/Makefile.in
+++ b/browser/components/migration/src/Makefile.in
@@ -40,17 +40,19 @@ srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= migration
 LIBRARY_NAME	= migration_s
 FORCE_STATIC_LIB = 1
 FORCE_USE_PIC = 1
+ifndef MOZ_MEMORY
 USE_STATIC_LIBS = 1
+endif
 
 REQUIRES	= \
 		  xpcom \
 		  string \
 		  necko \
 		  libreg \
 		  browsercomps \
 		  toolkitcomps \
--- a/browser/components/places/content/editBookmarkOverlay.js
+++ b/browser/components/places/content/editBookmarkOverlay.js
@@ -57,16 +57,18 @@ var gEditItemOverlay = {
    * Determines the initial data for the item edited or added by this dialog
    */
   _determineInfo: function EIO__determineInfo(aInfo) {
     // hidden rows
     if (aInfo && aInfo.hiddenRows)
       this._hiddenRows = aInfo.hiddenRows;
     else
       this._hiddenRows.splice(0);
+    // force-read-only
+    this._readOnly = aInfo && aInfo.forceReadOnly;
   },
 
   _showHideRows: function EIO__showHideRows() {
     var isBookmark = this._itemType == Ci.nsINavBookmarksService.TYPE_BOOKMARK;
 
     this._element("nameRow").collapsed = this._hiddenRows.indexOf("name") != -1;
     this._element("folderRow").collapsed =
       this._hiddenRows.indexOf("folderPicker") != -1;
@@ -84,34 +86,43 @@ var gEditItemOverlay = {
     this._element("feedLocationRow").collapsed = !this._isLivemark ||
       this._hiddenRows.indexOf("feedLocation") != -1;
     this._element("siteLocationRow").collapsed = !this._isLivemark ||
       this._hiddenRows.indexOf("siteLocation") != -1;
   },
 
   /**
    * Initialize the panel
+   * @param aItemId
+   *        a places-itemId of a bookmark, folder or a live bookmark.
+   * @param [optional] aInfo
+   *        JS object which stores additional info for the panel
+   *        initialization. The following properties may bet set:
+   *        * hiddenRows (Strings array): list of rows to be hidden regardless
+   *          of the item edited. Possible values: "title", "location",
+   *          "description", "keyword", "loadInSidebar", "feedLocation",
+   *          "siteLocation", folderPicker"
+   *        * forceReadOnly - set this flag to initialize the panel to its
+   *          read-only (view) mode even if the given item is editable.
    */
   initPanel: function EIO_initPanel(aItemId, aInfo) {
     const bms = PlacesUtils.bookmarks;
 
     this._folderMenuList = this._element("folderMenuList");
     this._folderTree = this._element("folderTree");
     this._itemId = aItemId;
     this._itemType = bms.getItemType(this._itemId);
     this._determineInfo(aInfo);
 
     var container = bms.getFolderIdForItem(this._itemId);
     if (this._itemType == Ci.nsINavBookmarksService.TYPE_BOOKMARK) {
       this._uri = bms.getBookmarkURI(this._itemId);
       this._isLivemark = false;
-      if (PlacesUtils.livemarks.isLivemark(container))
-        this._readOnly = true;
-      else
-        this._readOnly = false;
+      if (!this._readOnly) // If readOnly wasn't forced through aInfo
+        this._readOnly = PlacesUtils.livemarks.isLivemark(container);
 
       this._initTextField("locationField", this._uri.spec);
       this._initTextField("tagsField",
                            PlacesUtils.tagging
                                       .getTagsForURI(this._uri, {}).join(", "),
                           false);
 
       // tags selector
@@ -121,17 +132,18 @@ var gEditItemOverlay = {
                           bms.getKeywordForBookmark(this._itemId));
 
       // Load In Sidebar checkbox
       this._element("loadInSidebarCheckbox").checked =
         PlacesUtils.annotations.itemHasAnnotation(this._itemId,
                                                   LOAD_IN_SIDEBAR_ANNO);
     }
     else {
-      this._readOnly = false;
+      if (!this._readOnly) // If readOnly wasn't forced through aInfo
+        this._readOnly = false;
       this._isLivemark = PlacesUtils.livemarks.isLivemark(this._itemId);
       if (this._isLivemark) {
         var feedURI = PlacesUtils.livemarks.getFeedURI(this._itemId);
         var siteURI = PlacesUtils.livemarks.getSiteURI(this._itemId);
         this._initTextField("feedLocationField", feedURI.spec);
         this._initTextField("siteLocationField", siteURI ? siteURI.spec : "");
       }
       this._uri = null;
--- a/browser/components/places/content/places.js
+++ b/browser/components/places/content/places.js
@@ -536,18 +536,30 @@ var PlacesOrganizer = {
     if (selectedNode) {
       if (selectedNode.itemId != -1 &&
           !PlacesUtils.nodeIsSeparator(selectedNode)) {
         if (this._paneDisabled) {
           this._setDetailsFieldsDisabledState(false);
           this._paneDisabled = false;
         }
 
-        gEditItemOverlay.initPanel(selectedNode.itemId,
-                                   { hiddenRows: ["folderPicker"] });
+        // Using the concrete itemId is arguably wrong. The bookmarks API
+        // does allow setting properties for folder shortcuts as well, but since
+        // the UI does not distinct between the couple, we better just show
+        // the concrete item properties.
+        if (selectedNode.type ==
+            Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER_SHORTCUT) {
+          gEditItemOverlay.initPanel(asQuery(selectedNode).folderItemId,
+                                     { hiddenRows: ["folderPicker"],
+                                       forceReadOnly: true });
+        }
+        else {
+          gEditItemOverlay.initPanel(selectedNode.itemId,
+                                     { hiddenRows: ["folderPicker"] });
+        }
 
         this._detectAndSetDetailsPaneMinimalState(selectedNode);
         return;
       }
     }
     else {
       detailsDeck.selectedIndex = 0;
       var selectItemDesc = document.getElementById("selectItemDescription");
--- a/browser/components/places/src/Makefile.in
+++ b/browser/components/places/src/Makefile.in
@@ -43,17 +43,19 @@ srcdir = @srcdir@
 VPATH = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE = browserplaces
 LIBRARY_NAME  = browserplaces_s
 FORCE_STATIC_LIB = 1
 FORCE_USE_PIC = 1
+ifndef MOZ_MEMORY
 USE_STATIC_LIBS = 1
+endif
 
 REQUIRES	= \
 		  xpcom \
 		  string \
 		  necko \
 		  browsercomps \
 		  toolkitcomps \
 		  unicharutil \
--- a/browser/components/shell/src/Makefile.in
+++ b/browser/components/shell/src/Makefile.in
@@ -40,17 +40,19 @@ topsrcdir = @top_srcdir@
 srcdir    = @srcdir@
 VPATH   = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE = shellservice
 FORCE_STATIC_LIB = 1
 FORCE_USE_PIC = 1
+ifndef MOZ_MEMORY
 USE_STATIC_LIBS = 1
+endif
 
 REQUIRES	= \
 		  xpcom \
 		  string \
 		  uriloader \
 		  webbrowserpersist \
 		  dom \
 		  intl \
--- a/browser/themes/winstripe/browser/places/organizer.css
+++ b/browser/themes/winstripe/browser/places/organizer.css
@@ -1,32 +1,35 @@
 
 /* Toolbar */
 #placesToolbar {
   border: none;
 }
 
-/* back button */
+/* back & forward buttons */
+#back-button, #forward-button {
+  list-style-image: url("chrome://browser/skin/Toolbar.png");
+}
 
-#back-button {
-  list-style-image: url("chrome://browser/skin/Toolbar.png");
+#back-button,
+#forward-button[chromedir="rtl"] {  
   -moz-image-region: rect(0px, 24px, 24px, 0px);
 }
-#back-button[disabled="true"] {
- -moz-image-region: rect(48px, 24px, 72px, 0px) !important;
+#back-button[disabled="true"],
+#forward-button[chromedir="rtl"][disabled="true"] {
+ -moz-image-region: rect(48px, 24px, 72px, 0px);
 }
 
-/* forward button */
-
-#forward-button {
-  list-style-image: url("chrome://browser/skin/Toolbar.png");
+#forward-button,
+#back-button[chromedir="rtl"] {
   -moz-image-region: rect(0px, 48px, 24px, 24px);
 }
-#forward-button[disabled="true"] {
- -moz-image-region: rect(48px, 48px, 72px, 24px) !important;
+#forward-button[disabled="true"],
+#back-button[chromedir="rtl"][disabled="true"] {
+ -moz-image-region: rect(48px, 48px, 72px, 24px);
 }
 
 /* Menu */
 #placesMenu {
   -moz-appearance: none;
   border: none;
 }
 
--- a/configure.in
+++ b/configure.in
@@ -1270,18 +1270,18 @@ if test "$GNU_CC"; then
     # -Wall - turn on all warnings
     # -pedantic - make compiler warn about non-ANSI stuff, and
     #             be a little bit stricter
     # Warnings slamm took out for now (these were giving more noise than help):
     # -Wbad-function-cast - warns when casting a function to a new return type
     # -Wconversion - complained when char's or short's were used a function args
     # -Wshadow - removed because it generates more noise than help --pete
     _WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} -Wall -W -Wno-unused -Wpointer-arith"
-    if test "$CPU_ARCH" != "ia64"; then
-        # only use -Wcast-align for non-ia64, it's noisy on that platform
+    if test "$CPU_ARCH" != "ia64" && test "$CPU_ARCH" != "sparc"; then
+        # don't use -Wcast-align on ia64 or sparc, it's noisy on those platforms
         _WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} -Wcast-align"
     fi
 
     dnl Turn pedantic on but disable the warnings for long long
     _PEDANTIC=1
     _IGNORE_LONG_LONG_WARNINGS=1
 
     _DEFINES_CFLAGS='-include $(DEPTH)/mozilla-config.h -DMOZILLA_CLIENT'
@@ -1301,18 +1301,18 @@ else
     _DEFINES_CFLAGS='$(ACDEFINES) -D_MOZILLA_CONFIG_H_ -DMOZILLA_CLIENT'
 fi
 
 if test "$GNU_CXX"; then
     # FIXME: Let us build with strict aliasing. bug 414641.
     CXXFLAGS="$CXXFLAGS -fno-strict-aliasing"
     # Turn on GNU specific features
     _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wall -Wconversion -Wpointer-arith -Woverloaded-virtual -Wsynth -Wno-ctor-dtor-privacy -Wno-non-virtual-dtor"
-    if test "$CPU_ARCH" != "ia64"; then
-        # only use -Wcast-align for non-ia64, it's noisy on that platform
+    if test "$CPU_ARCH" != "ia64" && test "$CPU_ARCH" != "sparc"; then
+        # don't use -Wcast-align on ia64 or sparc, it's noisy on those platforms
         _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wcast-align"
     fi
 
     _DEFINES_CXXFLAGS='-DMOZILLA_CLIENT -include $(DEPTH)/mozilla-config.h'
     _USE_CPP_INCLUDE_FLAG=1
 else
     _DEFINES_CXXFLAGS='-DMOZILLA_CLIENT -D_MOZILLA_CONFIG_H_ $(ACDEFINES)'
 fi
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -1517,8 +1517,13 @@ GK_ATOM(usedPaddingProperty, "UsedPaddin
 GK_ATOM(viewProperty, "ViewProperty")                      
 
 // Languages for lang-specific transforms
 GK_ATOM(Japanese, "ja")
 GK_ATOM(Chinese, "zh-CN")
 GK_ATOM(Taiwanese, "zh-TW")
 GK_ATOM(HongKongChinese, "zh-HK")
 GK_ATOM(Unicode, "x-unicode")
+
+// Names for editor transactions
+GK_ATOM(TypingTxnName, "Typing")
+GK_ATOM(IMETxnName, "IME")
+GK_ATOM(DeleteTxnName, "Deleting")
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -601,31 +601,33 @@ nsXULElement::IsFocusable(PRInt32 *aTabI
   if (aTabIndex) {
     if (xulControl && HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex)) {
       // if either the aTabIndex argument or a specified tabindex is non-negative,
       // the element becomes focusable.
       PRInt32 tabIndex = 0;
       xulControl->GetTabIndex(&tabIndex);
       shouldFocus = *aTabIndex >= 0 || tabIndex >= 0;
       *aTabIndex = tabIndex;
+
+      if (shouldFocus && sTabFocusModelAppliesToXUL &&
+          !(sTabFocusModel & eTabFocus_formElementsMask)) {
+        // By default, the tab focus model doesn't apply to xul element on any system but OS X.
+        // on OS X we're following it for UI elements (XUL) as sTabFocusModel is based on
+        // "Full Keyboard Access" system setting (see mac/nsILookAndFeel).
+        // both textboxes and list elements (i.e. trees and list) should always be focusable
+        // (textboxes are handled as html:input)
+        // For compatibility, we only do this for controls, otherwise elements like <browser>
+        // cannot take this focus.
+        if (!mNodeInfo->Equals(nsGkAtoms::tree) && !mNodeInfo->Equals(nsGkAtoms::listbox))
+          *aTabIndex = -1;
+      }
     }
     else {
       shouldFocus = *aTabIndex >= 0;
     }
-
-    if (shouldFocus && sTabFocusModelAppliesToXUL &&
-        !(sTabFocusModel & eTabFocus_formElementsMask)) {
-      // By default, the tab focus model doesn't apply to xul element on any system but OS X.
-      // on OS X we're following it for UI elements (XUL) as sTabFocusModel is based on
-      // "Full Keyboard Access" system setting (see mac/nsILookAndFeel).
-      // both textboxes and list elements (i.e. trees and list) should always be focusable
-      // (textboxes are handled as html:input)
-      if (!mNodeInfo->Equals(nsGkAtoms::tree) && !mNodeInfo->Equals(nsGkAtoms::listbox))
-        *aTabIndex = -1; 
-    }
   }
 
   return shouldFocus;
 }
 
 void
 nsXULElement::PerformAccesskey(PRBool aKeyCausesActivation,
                                PRBool aIsTrustedEvent)
--- a/dom/src/base/nsDOMClassInfo.cpp
+++ b/dom/src/base/nsDOMClassInfo.cpp
@@ -6184,18 +6184,18 @@ nsWindowSH::NewResolve(nsIXPConnectWrapp
     // Something went wrong, or the property got resolved. Return.
     return rv;
   }
 
   // Make a fast expando if we're assigning to (not declaring or
   // binding a name) a new undefined property that's not already
   // defined on our prototype chain. This way we can access this
   // expando w/o ever getting back into XPConnect.
-  if ((flags & (JSRESOLVE_ASSIGNING)) && cx->fp->regs &&
-      (JSOp)*cx->fp->regs->pc != JSOP_BINDNAME && win->IsInnerWindow()) {
+  if ((flags & (JSRESOLVE_ASSIGNING)) && (JSOp)*cx->fp->pc != JSOP_BINDNAME &&
+      win->IsInnerWindow()) {
     JSObject *realObj;
     wrapper->GetJSObject(&realObj);
 
     if (obj == realObj) {
       JSObject *proto = STOBJ_GET_PROTO(obj);
       if (proto) {
         jsid interned_id;
         JSProperty *prop = nsnull;
--- a/editor/libeditor/base/Makefile.in
+++ b/editor/libeditor/base/Makefile.in
@@ -99,8 +99,11 @@ CPPSRCS		+=                          \
 		TransactionFactory.cpp      \
 		$(NULL)
 
 # don't want the shared lib; force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
 
+INCLUDES	+= \
+		-I$(topsrcdir)/content/base/src \
+		$(NULL)
--- a/editor/libeditor/base/PlaceholderTxn.cpp
+++ b/editor/libeditor/base/PlaceholderTxn.cpp
@@ -34,16 +34,17 @@
  * 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 "PlaceholderTxn.h"
 #include "nsEditor.h"
 #include "IMETextTxn.h"
+#include "nsGkAtoms.h"
 
 PlaceholderTxn::PlaceholderTxn() :  EditAggregateTxn(), 
                                     mAbsorb(PR_TRUE), 
                                     mForwarding(nsnull),
                                     mIMETextTxn(nsnull),
                                     mCommitted(PR_FALSE),
                                     mStartSel(nsnull),
                                     mEndSel(),
@@ -165,19 +166,19 @@ NS_IMETHODIMP PlaceholderTxn::Merge(nsIT
     *aDidMerge = PR_TRUE;
 //  RememberEndingSelection();
 //  efficiency hack: no need to remember selection here, as we haven't yet 
 //  finished the initial batch and we know we will be told when the batch ends.
 //  we can remeber the selection then.
   }
   else
   { // merge typing or IME or deletion transactions if the selection matches
-    if (((mName.get() == nsEditor::gTypingTxnName) ||
-         (mName.get() == nsEditor::gIMETxnName)    ||
-         (mName.get() == nsEditor::gDeleteTxnName)) 
+    if (((mName.get() == nsGkAtoms::TypingTxnName) ||
+         (mName.get() == nsGkAtoms::IMETxnName)    ||
+         (mName.get() == nsGkAtoms::DeleteTxnName)) 
          && !mCommitted ) 
     {
       nsCOMPtr<nsIAbsorbingTransaction> plcTxn;// = do_QueryInterface(editTxn);
       // can't do_QueryInterface() above due to our broken transaction interfaces.
       // instead have to brute it below. ugh. 
       editTxn->QueryInterface(NS_GET_IID(nsIAbsorbingTransaction), getter_AddRefs(plcTxn));
       if (plcTxn)
       {
--- a/editor/libeditor/base/nsEditor.cpp
+++ b/editor/libeditor/base/nsEditor.cpp
@@ -126,20 +126,16 @@ static PRBool gNoisy = PR_FALSE;
 extern nsIParserService *sParserService;
 
 //---------------------------------------------------------------------------
 //
 // nsEditor: base editor class implementation
 //
 //---------------------------------------------------------------------------
 
-nsIAtom *nsEditor::gTypingTxnName;
-nsIAtom *nsEditor::gIMETxnName;
-nsIAtom *nsEditor::gDeleteTxnName;
-
 nsEditor::nsEditor()
 :  mModCount(0)
 ,  mPresShellWeak(nsnull)
 ,  mViewManager(nsnull)
 ,  mUpdateCount(0)
 ,  mSpellcheckCheckboxState(eTriUnset)
 ,  mPlaceHolderTxn(nsnull)
 ,  mPlaceHolderName(nsnull)
@@ -156,66 +152,21 @@ nsEditor::nsEditor()
 ,  mIsIMEComposing(PR_FALSE)
 ,  mShouldTxnSetSelection(PR_TRUE)
 ,  mDidPreDestroy(PR_FALSE)
 ,  mDocDirtyState(-1)
 ,  mDocWeak(nsnull)
 ,  mPhonetic(nsnull)
 {
   //initialize member variables here
-  if (!gTypingTxnName)
-    gTypingTxnName = NS_NewAtom("Typing");
-  else
-    NS_ADDREF(gTypingTxnName);
-  if (!gIMETxnName)
-    gIMETxnName = NS_NewAtom("IME");
-  else
-    NS_ADDREF(gIMETxnName);
-  if (!gDeleteTxnName)
-    gDeleteTxnName = NS_NewAtom("Deleting");
-  else
-    NS_ADDREF(gDeleteTxnName);
 }
 
 nsEditor::~nsEditor()
 {
-  /* first, delete the transaction manager if there is one.
-     this will release any remaining transactions.
-     this is important because transactions can hold onto the atoms (gTypingTxnName, ...)
-     and to make the optimization (holding refcounted statics) work correctly, 
-     the editor instance needs to hold the last refcount.
-     If you get this wrong, expect to deref a garbage gTypingTxnName pointer if you bring up a second editor.
-  */
-  if (mTxnMgr) { 
-    mTxnMgr = 0;
-  }
-  nsrefcnt refCount=0;
-  if (gTypingTxnName)  // we addref'd in the constructor
-  { // want to release it without nulling out the pointer.
-    refCount = gTypingTxnName->Release();
-    if (0==refCount) {
-      gTypingTxnName = nsnull; 
-    }
-  }
-
-  if (gIMETxnName)  // we addref'd in the constructor
-  { // want to release it without nulling out the pointer.
-    refCount = gIMETxnName->Release();
-    if (0==refCount) {
-      gIMETxnName = nsnull;
-    }
-  }
-
-  if (gDeleteTxnName)  // we addref'd in the constructor
-  { // want to release it without nulling out the pointer.
-    refCount = gDeleteTxnName->Release();
-    if (0==refCount) {
-      gDeleteTxnName = nsnull;
-    }
-  }
+  mTxnMgr = nsnull;
 
   delete mPhonetic;
  
   NS_IF_RELEASE(mViewManager);
 }
 
 NS_IMPL_ISUPPORTS5(nsEditor, nsIEditor, nsIEditorIMESupport,
                    nsISupportsWeakReference, nsIPhonetic, nsIMutationObserver)
--- a/editor/libeditor/base/nsEditor.h
+++ b/editor/libeditor/base/nsEditor.h
@@ -576,23 +576,16 @@ public:
                                     nsIDOMNode *aEndNode,
                                     PRInt32 aEndOffset);
 
   already_AddRefed<nsPIDOMEventTarget> GetPIDOMEventTarget();
 
   // Fast non-refcounting editor root element accessor
   nsIDOMElement *GetRoot();
 
-public:
-  // Argh!  These transaction names are used by PlaceholderTxn and
-  // nsPlaintextEditor.  They should be localized to those classes.
-  static nsIAtom *gTypingTxnName;
-  static nsIAtom *gIMETxnName;
-  static nsIAtom *gDeleteTxnName;
-
 protected:
 
   PRUint32        mModCount;		// number of modifications (for undo/redo stack)
   PRUint32        mFlags;		// behavior flags. See nsIPlaintextEditor.idl for the flags we use.
   
   nsWeakPtr       mPresShellWeak;   // weak reference to the nsIPresShell
   nsWeakPtr       mSelConWeak;   // weak reference to the nsISelectionController
   nsIViewManager *mViewManager;
--- a/editor/libeditor/html/Makefile.in
+++ b/editor/libeditor/html/Makefile.in
@@ -97,9 +97,11 @@ DEFINES += -DENABLE_EDITOR_API_LOG
 endif
 
 # don't want the shared lib; force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
 
 INCLUDES        += -I$(topsrcdir)/editor/libeditor/base \
-                   -I$(topsrcdir)/editor/libeditor/text
+                   -I$(topsrcdir)/editor/libeditor/text \
+                   -I$(topsrcdir)/content/base/src \
+                   $(NULL)
--- a/editor/libeditor/html/nsHTMLEditor.cpp
+++ b/editor/libeditor/html/nsHTMLEditor.cpp
@@ -120,16 +120,17 @@
 // Transactionas
 #include "nsStyleSheetTxns.h"
 
 // Misc
 #include "TextEditorTest.h"
 #include "nsEditorUtils.h"
 #include "nsWSRunObject.h"
 #include "nsHTMLObjectResizer.h"
+#include "nsGkAtoms.h"
 
 #include "nsIFrame.h"
 #include "nsIView.h"
 #include "nsIWidget.h"
 #include "nsIParserService.h"
 #include "nsIEventStateManager.h"
 
 // Some utilities to handle annoying overloading of "A" tag for link and named anchor
@@ -1340,17 +1341,17 @@ NS_IMETHODIMP nsHTMLEditor::HandleKeyPre
    purposes.  Can't use HandleKeyPress() (above) for that since it takes
    a nsIDOMKeyEvent* parameter.  So instead we pass enough info through
    to TypedText() to determine what action to take, but without passing
    an event.
    */
 NS_IMETHODIMP nsHTMLEditor::TypedText(const nsAString& aString,
                                       PRInt32 aAction)
 {
-  nsAutoPlaceHolderBatch batch(this, gTypingTxnName);
+  nsAutoPlaceHolderBatch batch(this, nsGkAtoms::TypingTxnName);
 
   switch (aAction)
   {
     case eTypedText:
     case eTypedBreak:
       {
         return nsPlaintextEditor::TypedText(aString, aAction);
       }
--- a/editor/libeditor/text/Makefile.in
+++ b/editor/libeditor/text/Makefile.in
@@ -76,10 +76,12 @@ CPPSRCS		=                           \
 		nsTextEditRulesBidi.cpp \
 		$(NULL)
 
 # don't want the shared lib; force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
 
-INCLUDES        += -I$(topsrcdir)/editor/libeditor/base
-
+INCLUDES	+= \
+		-I$(topsrcdir)/editor/libeditor/base \
+		-I$(topsrcdir)/content/base/src \
+		$(NULL)
--- a/editor/libeditor/text/nsPlaintextEditor.cpp
+++ b/editor/libeditor/text/nsPlaintextEditor.cpp
@@ -74,16 +74,17 @@
 #include "nsEditorUtils.h"  // nsAutoEditBatch, nsAutoRules
 #include "nsIPrefBranch.h"
 #include "nsIPrefService.h"
 #include "nsUnicharUtils.h"
 #include "nsContentCID.h"
 #include "nsAOLCiter.h"
 #include "nsInternetCiter.h"
 #include "nsEventDispatcher.h"
+#include "nsGkAtoms.h"
 
 // Drag & Drop, Clipboard
 #include "nsIClipboard.h"
 #include "nsITransferable.h"
 #include "nsCopySupport.h"
 
 // prototype for rules creation shortcut
 nsresult NS_NewTextEditRules(nsIEditRules** aInstancePtrResult);
@@ -412,17 +413,17 @@ NS_IMETHODIMP nsPlaintextEditor::HandleK
    purposes.  Can't use HandleKeyPress() (above) for that since it takes
    a nsIDOMKeyEvent* parameter.  So instead we pass enough info through
    to TypedText() to determine what action to take, but without passing
    an event.
    */
 NS_IMETHODIMP nsPlaintextEditor::TypedText(const nsAString& aString,
                                       PRInt32 aAction)
 {
-  nsAutoPlaceHolderBatch batch(this, gTypingTxnName);
+  nsAutoPlaceHolderBatch batch(this, nsGkAtoms::TypingTxnName);
 
   switch (aAction)
   {
     case eTypedText:
       {
         return InsertText(aString);
       }
     case eTypedBreak:
@@ -638,17 +639,17 @@ nsPlaintextEditor::GetTextSelectionOffse
 
 NS_IMETHODIMP nsPlaintextEditor::DeleteSelection(nsIEditor::EDirection aAction)
 {
   if (!mRules) { return NS_ERROR_NOT_INITIALIZED; }
 
   nsresult result;
 
   // delete placeholder txns merge.
-  nsAutoPlaceHolderBatch batch(this, gDeleteTxnName);
+  nsAutoPlaceHolderBatch batch(this, nsGkAtoms::DeleteTxnName);
   nsAutoRules beginRulesSniffing(this, kOpDeleteSelection, aAction);
 
   // pre-process
   nsCOMPtr<nsISelection> selection;
   result = GetSelection(getter_AddRefs(selection));
   if (NS_FAILED(result)) return result;
   if (!selection) return NS_ERROR_NULL_POINTER;
 
@@ -1707,17 +1708,17 @@ nsPlaintextEditor::SetCompositionString(
     }
 
     // XXX_kin: END HACK! HACK! HACK!
 
     // we need the nsAutoPlaceHolderBatch destructor called before hitting
     // GetCaretCoordinates so the states in Frame system sync with content
     // therefore, we put the nsAutoPlaceHolderBatch into a inner block
     {
-      nsAutoPlaceHolderBatch batch(this, gIMETxnName);
+      nsAutoPlaceHolderBatch batch(this, nsGkAtoms::IMETxnName);
 
       SetIsIMEComposing(); // We set mIsIMEComposing properly.
 
       result = InsertText(aCompositionString);
 
       mIMEBufferLength = aCompositionString.Length();
 
       if (caretP)
new file mode 100644
--- /dev/null
+++ b/intl/strres/tests/397093.properties
@@ -0,0 +1,4 @@
+# Property file for test_bug397093.js 
+asciiProperty=Foo
+utf8Property=Fòò
+latin1Property=F
--- a/intl/strres/tests/Makefile.in
+++ b/intl/strres/tests/Makefile.in
@@ -43,16 +43,17 @@ VPATH		= @srcdir@
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		 = test_intl_strres
 
 XPCSHELL_TESTS	 = unit
 
 EXPORT_RESOURCE	= \
 		$(srcdir)/strres.properties \
+		$(srcdir)/397093.properties \
 		$(NULL)
 
 include $(topsrcdir)/config/rules.mk
 
 libs::
 	$(INSTALL) $(EXPORT_RESOURCE) $(DIST)/bin/res
 
 install::
new file mode 100644
--- /dev/null
+++ b/intl/strres/tests/unit/test_bug397093.js
@@ -0,0 +1,40 @@
+/* Tests getting properties from string bundles with incorrect encoding.
+ * The string bundle contains one ascii property, one UTF-8 and one Latin-1.
+ * Expected behaviour is that the whole string bundle should be rejected and
+ * all GetStringFromName calls should fail.
+ */
+
+const name_ascii = "asciiProperty";
+const value_ascii = "";
+
+const name_utf8 = "utf8Property";
+const value_utf8 = "";
+
+const name_latin1 = "latin1";
+const value_latin1 = "";
+
+
+function run_test() {
+    var StringBundle = 
+	Components.classes["@mozilla.org/intl/stringbundle;1"]
+	 .getService(Components.interfaces.nsIStringBundleService);
+
+    var bundle = StringBundle.createBundle("resource://gre/res/397093.properties");
+    
+    var bundle_ascii="", bundle_utf8="", bundle_latin1="";
+    try {
+	bundle_ascii = bundle.GetStringFromName(name_ascii);
+    } catch(e) {}
+    do_check_eq(bundle_ascii, value_ascii);
+
+    try {
+	bundle_utf8 = bundle.GetStringFromName(name_utf8);
+    } catch(e) {}
+    do_check_eq(bundle_utf8, value_utf8);
+
+    try {
+	bundle_latin1 = bundle.GetStringFromName(name_latin1);
+    } catch(e) {}
+    do_check_eq(bundle_latin1, value_latin1);
+}
+    
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -45,16 +45,18 @@ VPATH		= @srcdir@
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= js
 LIBRARY_NAME	= mozjs
 GRE_MODULE	= 1
 
 ifdef GNU_CC
 MODULE_OPTIMIZE_FLAGS = -Os -fstrict-aliasing
+# Special optimization flags for jsinterp.c
+INTERP_OPTIMIZER = -O3 -fstrict-aliasing
 else
 ifeq ($(OS_ARCH),SunOS)
 MODULE_OPTIMIZE_FLAGS = -O
 endif
 ifeq ($(OS_ARCH),WINNT)
 MODULE_OPTIMIZE_FLAGS = -O2 -GL
 endif
 endif
@@ -332,16 +334,21 @@ endif # JS_ULTRASPARC_OPTS
 endif
 ifeq ($(OS_RELEASE),4.1)
 LDFLAGS		+= -ldl -lnsl
 else
 LDFLAGS		+= -lposix4 -ldl -lnsl -lsocket
 endif
 endif
 
+# Allow building jsinterp.c with special optimization flags
+ifdef INTERP_OPTIMIZER
+jsinterp.$(OBJ_SUFFIX): MODULE_OPTIMIZE_FLAGS=$(INTERP_OPTIMIZER)
+endif
+
 ifeq ($(OS_ARCH),IRIX)
 ifndef GNU_CC
 _COMPILE_CFLAGS  = $(patsubst -O%,-O1,$(COMPILE_CFLAGS))
 jsapi.o jsxdrapi.o jsarena.o jsarray.o jsatom.o jsemit.o jsfun.o jsinterp.o jsregexp.o jsparse.o jsopcode.o jsscript.o: %.o: %.cpp Makefile.in
 	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CXX)
 	$(CXX) -o $@ -c $(_COMPILE_CFLAGS) $<
 endif
--- a/js/src/js.cpp
+++ b/js/src/js.cpp
@@ -2475,18 +2475,17 @@ EvalInContext(JSContext *cx, JSObject *o
         *rval = OBJECT_TO_JSVAL(sobj);
         ok = JS_TRUE;
     } else {
         fp = JS_GetScriptedCaller(cx, NULL);
         JS_SetGlobalObject(scx, sobj);
         JS_ToggleOptions(scx, JSOPTION_DONT_REPORT_UNCAUGHT);
         ok = JS_EvaluateUCScript(scx, sobj, src, srclen,
                                  fp->script->filename,
-                                 JS_PCToLineNumber(cx, fp->script,
-                                                   fp->regs->pc),
+                                 JS_PCToLineNumber(cx, fp->script, fp->pc),
                                  rval);
         if (!ok) {
             if (JS_GetPendingException(scx, &v))
                 JS_SetPendingException(cx, v);
             else
                 JS_ReportOutOfMemory(cx);
         }
     }
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -5113,22 +5113,23 @@ JS_IsConstructing(JSContext *cx)
 {
     return cx->fp && (cx->fp->flags & JSFRAME_CONSTRUCTING);
 }
 
 JS_FRIEND_API(JSBool)
 JS_IsAssigning(JSContext *cx)
 {
     JSStackFrame *fp;
+    jsbytecode *pc;
 
     for (fp = cx->fp; fp && !fp->script; fp = fp->down)
         continue;
-    if (!fp || !fp->regs)
+    if (!fp || !(pc = fp->pc))
         return JS_FALSE;
-    return (js_CodeSpec[*fp->regs->pc].format & JOF_ASSIGNING) != 0;
+    return (js_CodeSpec[*pc].format & JOF_ASSIGNING) != 0;
 }
 
 JS_PUBLIC_API(void)
 JS_SetCallReturnValue2(JSContext *cx, jsval v)
 {
 #if JS_HAS_LVALUE_RETURN
     cx->rval2 = v;
     cx->rval2set = JS_TRUE;
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -885,19 +885,19 @@ js_ReportOutOfMemory(JSContext *cx)
     report.flags = JSREPORT_ERROR;
     report.errorNumber = JSMSG_OUT_OF_MEMORY;
 
     /*
      * Walk stack until we find a frame that is associated with some script
      * rather than a native frame.
      */
     for (fp = cx->fp; fp; fp = fp->down) {
-        if (fp->regs) {
+        if (fp->script && fp->pc) {
             report.filename = fp->script->filename;
-            report.lineno = js_PCToLineNumber(cx, fp->script, fp->regs->pc);
+            report.lineno = js_PCToLineNumber(cx, fp->script, fp->pc);
             break;
         }
     }
 
     /*
      * If debugErrorHook is present then we give it a chance to veto sending
      * the error on to the regular ErrorReporter. We also clear a pending
      * exception if any now so the hooks can replace the out-of-memory error
@@ -955,19 +955,19 @@ js_ReportErrorVA(JSContext *cx, uintN fl
 
     memset(&report, 0, sizeof (struct JSErrorReport));
     report.flags = flags;
     report.errorNumber = JSMSG_USER_DEFINED_ERROR;
     report.ucmessage = ucmessage = js_InflateString(cx, message, &messagelen);
 
     /* Find the top-most active script frame, for best line number blame. */
     for (fp = cx->fp; fp; fp = fp->down) {
-        if (fp->regs) {
+        if (fp->script && fp->pc) {
             report.filename = fp->script->filename;
-            report.lineno = js_PCToLineNumber(cx, fp->script, fp->regs->pc);
+            report.lineno = js_PCToLineNumber(cx, fp->script, fp->pc);
             break;
         }
     }
 
     warning = JSREPORT_IS_WARNING(report.flags);
     if (warning && JS_HAS_WERROR_OPTION(cx)) {
         report.flags &= ~JSREPORT_WARNING;
         warning = JS_FALSE;
@@ -1167,19 +1167,19 @@ js_ReportErrorNumberVA(JSContext *cx, ui
     report.flags = flags;
     report.errorNumber = errorNumber;
 
     /*
      * If we can't find out where the error was based on the current frame,
      * see if the next frame has a script/pc combo we can use.
      */
     for (fp = cx->fp; fp; fp = fp->down) {
-        if (fp->regs) {
+        if (fp->script && fp->pc) {
             report.filename = fp->script->filename;
-            report.lineno = js_PCToLineNumber(cx, fp->script, fp->regs->pc);
+            report.lineno = js_PCToLineNumber(cx, fp->script, fp->pc);
             break;
         }
     }
 
     if (!js_ExpandErrorArguments(cx, callback, userRef, errorNumber,
                                  &message, &report, &warning, charArgs, ap)) {
         return JS_FALSE;
     }
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -553,17 +553,16 @@ js_watch_set(JSContext *cx, JSObject *ob
                 JSClass *clasp;
                 JSFunction *fun;
                 JSScript *script;
                 JSBool injectFrame;
                 uintN nslots;
                 jsval smallv[5];
                 jsval *argv;
                 JSStackFrame frame;
-                JSFrameRegs regs;
 
                 closure = (JSObject *) wp->closure;
                 clasp = OBJ_GET_CLASS(cx, closure);
                 if (clasp == &js_FunctionClass) {
                     fun = GET_FUNCTION_PRIVATE(cx, closure);
                     script = FUN_SCRIPT(fun);
                 } else if (clasp == &js_ScriptClass) {
                     fun = NULL;
@@ -596,23 +595,20 @@ js_watch_set(JSContext *cx, JSObject *ob
                     }
 
                     argv[0] = OBJECT_TO_JSVAL(closure);
                     argv[1] = JSVAL_NULL;
                     memset(argv + 2, 0, (nslots - 2) * sizeof(jsval));
 
                     memset(&frame, 0, sizeof(frame));
                     frame.script = script;
-                    frame.regs = NULL;
                     if (script) {
                         JS_ASSERT(script->length >= JSOP_STOP_LENGTH);
-                        regs.pc = script->code + script->length
-                                  - JSOP_STOP_LENGTH;
-                        regs.sp = NULL;
-                        frame.regs = &regs;
+                        frame.pc = script->code + script->length
+                                   - JSOP_STOP_LENGTH;
                     }
                     frame.callee = closure;
                     frame.fun = fun;
                     frame.argv = argv + 2;
                     frame.down = cx->fp;
                     frame.scopeChain = OBJ_GET_PARENT(cx, closure);
 
                     cx->fp = &frame;
@@ -955,17 +951,17 @@ JS_PUBLIC_API(JSScript *)
 JS_GetFrameScript(JSContext *cx, JSStackFrame *fp)
 {
     return fp->script;
 }
 
 JS_PUBLIC_API(jsbytecode *)
 JS_GetFramePC(JSContext *cx, JSStackFrame *fp)
 {
-    return fp->regs ? fp->regs->pc : NULL;
+    return fp->pc;
 }
 
 JS_PUBLIC_API(JSStackFrame *)
 JS_GetScriptedCaller(JSContext *cx, JSStackFrame *fp)
 {
     if (!fp)
         fp = cx->fp;
     while (fp) {
--- a/js/src/jsdtracef.c
+++ b/js/src/jsdtracef.c
@@ -69,18 +69,18 @@ jsdtrace_filename(JSStackFrame *fp)
            : dempty;
 }
 
 int
 jsdtrace_linenumber(JSContext *cx, JSStackFrame *fp)
 {
     while (fp && fp->script == NULL)
         fp = fp->down;
-    return (fp && fp->regs)
-           ? js_PCToLineNumber(cx, fp->script, fp->regs->pc)
+    return (fp && fp->script && fp->pc)
+           ? js_PCToLineNumber(cx, fp->script, fp->pc)
            : -1;
 }
 
 /*
  * This function is used to convert function arguments and return value (jsval)
  * into the following based on each value's type tag:
  *
  *      jsval      returned
@@ -126,41 +126,39 @@ jsdtrace_jsvaltovoid(JSContext *cx, jsva
     /* NOTREACHED */
 }
 
 char *
 jsdtrace_function_name(JSContext *cx, JSStackFrame *fp, JSFunction *fun)
 {
     JSAtom *atom;
     JSScript *script;
-    JSFrameRegs *regs;
     jsbytecode *pc;
     char *name;
 
     atom = fun->atom;
     if (!atom) {
         if (fp->fun != fun || !fp->down)
             return dempty;
 
         script = fp->down->script;
-        regs = fp->down->regs;
-        if (!regs)
+        pc = fp->down->pc;
+        if (!script || !pc)
             return dempty;
 
         /*
          * An anonymous function called from an active script or interpreted
          * function: try to fetch the variable or property name by which the
          * anonymous function was invoked. First handle call ops by recovering
          * the generating pc for the callee expression at argv[-2].
          */
-        pc = regs->pc;
         switch ((JSOp) *pc) {
           case JSOP_CALL:
           case JSOP_EVAL:
-            JS_ASSERT(fp->argv == fp->down->regs->sp - (int)GET_ARGC(pc));
+            JS_ASSERT(fp->argv == fp->down->sp - (int)GET_ARGC(pc));
 
             pc = (jsbytecode *) fp->argv[-2 - (int)script->depth];
 
             /*
              * Be paranoid about bugs to-do with generating pc storage when
              * attempting to descend into the operand stack basement.
              */
             if ((uintptr_t)(pc - script->code) >= script->length)
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -327,18 +327,18 @@ InitExnPrivate(JSContext *cx, JSObject *
             elem->argc = fp->argc;
             memcpy(values, fp->argv, fp->argc * sizeof(jsval));
             values += fp->argc;
         }
         elem->ulineno = 0;
         elem->filename = NULL;
         if (fp->script) {
             elem->filename = fp->script->filename;
-            if (fp->regs)
-                elem->ulineno = js_PCToLineNumber(cx, fp->script, fp->regs->pc);
+            if (fp->pc)
+                elem->ulineno = js_PCToLineNumber(cx, fp->script, fp->pc);
         }
         ++elem;
     }
     JS_ASSERT(priv->stackElems + stackDepth == elem);
     JS_ASSERT(GetStackTraceValueBuffer(priv) + valueCount == values);
 
     STOBJ_SET_SLOT(exnObject, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(priv));
 
@@ -794,19 +794,17 @@ Exception(JSContext *cx, JSObject *obj, 
     /* Set the 'lineNumber' property. */
     if (argc > 2) {
         lineno = js_ValueToECMAUint32(cx, &argv[2]);
         if (JSVAL_IS_NULL(argv[2]))
             return JS_FALSE;
     } else {
         if (!fp)
             fp = JS_GetScriptedCaller(cx, NULL);
-        lineno = (fp && fp->regs)
-                 ? js_PCToLineNumber(cx, fp->script, fp->regs->pc)
-                 : 0;
+        lineno = (fp && fp->pc) ? js_PCToLineNumber(cx, fp->script, fp->pc) : 0;
     }
 
     return (OBJ_GET_CLASS(cx, obj) != &js_ErrorClass) ||
             InitExnPrivate(cx, obj, message, filename, lineno, NULL);
 }
 
 /*
  * Convert to string.
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -2196,36 +2196,35 @@ js_ValueToCallableObject(JSContext *cx, 
 
 void
 js_ReportIsNotFunction(JSContext *cx, jsval *vp, uintN flags)
 {
     JSStackFrame *fp;
     uintN error;
     const char *name, *source;
 
-    for (fp = cx->fp; fp && !fp->regs; fp = fp->down)
+    for (fp = cx->fp; fp && !fp->spbase; fp = fp->down)
         continue;
     name = NULL;
     source = NULL;
     if (flags & JSV2F_ITERATOR) {
         error = JSMSG_BAD_ITERATOR;
         name = js_iterator_str;
         source = js_ValueToPrintableSource(cx, *vp);
         if (!source)
             return;
     } else if (flags & JSV2F_CONSTRUCT) {
         error = JSMSG_NOT_CONSTRUCTOR;
     } else {
         error = JSMSG_NOT_FUNCTION;
     }
 
     js_ReportValueError3(cx, error,
-                         (fp && fp->regs &&
-                          fp->spbase <= vp && vp < fp->regs->sp)
-                         ? vp - fp->regs->sp
+                         (fp && fp->spbase <= vp && vp < fp->sp)
+                         ? vp - fp->sp
                          : (flags & JSV2F_SEARCH_STACK)
                          ? JSDVG_SEARCH_STACK
                          : JSDVG_IGNORE_STACK,
                          *vp, NULL,
                          name, source);
 }
 
 /*
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -2655,21 +2655,19 @@ js_TraceStackFrame(JSTracer *trc, JSStac
     if (fp->varobj)
         JS_CALL_OBJECT_TRACER(trc, fp->varobj, "variables");
     if (fp->script) {
         js_TraceScript(trc, fp->script);
         /*
          * Don't mark what has not been pushed yet, or what has been
          * popped already.
          */
-        if (fp->regs) {
-            nslots = (uintN) (fp->regs->sp - fp->spbase);
-            JS_ASSERT(nslots <= fp->script->depth);
-            TRACE_JSVALS(trc, nslots, fp->spbase, "operand");
-        }
+        nslots = (uintN) (fp->sp - fp->spbase);
+        JS_ASSERT(nslots <= fp->script->depth);
+        TRACE_JSVALS(trc, nslots, fp->spbase, "operand");
     }
 
     /* Allow for primitive this parameter due to JSFUN_THISP_* flags. */
     JS_ASSERT(JSVAL_IS_OBJECT((jsval)fp->thisp) ||
               (fp->fun && JSFUN_THISP_FLAGS(fp->fun->flags)));
     JS_CALL_VALUE_TRACER(trc, (jsval)fp->thisp, "this");
 
     if (fp->callee)
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -112,17 +112,17 @@ js_FillPropertyCache(JSContext *cx, JSOb
     const JSCodeSpec *cs;
     jsuword vword;
     ptrdiff_t pcoff;
     jsuword khash;
     JSAtom *atom;
     JSPropCacheEntry *entry;
 
     cache = &JS_PROPERTY_CACHE(cx);
-    pc = cx->fp->regs->pc;
+    pc = cx->fp->pc;
     if (cache->disabled) {
         PCMETER(cache->disfills++);
         *entryp = NULL;
         return;
     }
 
     /*
      * Check for fill from js_SetPropertyHelper where the setter removed sprop
@@ -1208,17 +1208,17 @@ have_fun:
         /* Push void to initialize local variables. */
         i = nvars;
         do {
             *sp++ = JSVAL_VOID;
         } while (--i != 0);
     }
 
     /*
-     * Initialize the frame.
+     * Initialize the frame, except for sp (set by SAVE_SP later).
      *
      * To set thisp we use an explicit cast and not JSVAL_TO_OBJECT, as vp[1]
      * can be a primitive value here for those native functions specified with
      * JSFUN_THISP_(NUMBER|STRING|BOOLEAN) flags.
      */
     frame.thisp = (JSObject *)vp[1];
     frame.varobj = NULL;
     frame.callobj = frame.argsobj = NULL;
@@ -1230,17 +1230,18 @@ have_fun:
 
     /* Default return value for a constructor is the new object. */
     frame.rval = (flags & JSINVOKE_CONSTRUCT) ? vp[1] : JSVAL_VOID;
     frame.nvars = nvars;
     frame.vars = sp - nvars;
     frame.down = cx->fp;
     frame.annotation = NULL;
     frame.scopeChain = NULL;    /* set below for real, after cx->fp is set */
-    frame.regs = NULL;
+    frame.pc = NULL;
+    frame.sp = NULL;
     frame.spbase = NULL;
     frame.sharpDepth = 0;
     frame.sharpArray = NULL;
     frame.flags = flags | rootedArgsFlag;
     frame.dormantNext = NULL;
     frame.xmlNamespace = NULL;
     frame.blockChain = NULL;
 
@@ -1479,17 +1480,18 @@ js_Execute(JSContext *cx, JSObject *chai
             frame.vars = NULL;
         }
         frame.annotation = NULL;
         frame.sharpArray = NULL;
     }
     frame.rval = JSVAL_VOID;
     frame.down = down;
     frame.scopeChain = chain;
-    frame.regs = NULL;
+    frame.pc = NULL;
+    frame.sp = NULL;
     frame.spbase = NULL;
     frame.sharpDepth = 0;
     frame.flags = flags;
     frame.dormantNext = NULL;
     frame.xmlNamespace = NULL;
     frame.blockChain = NULL;
 
     /*
@@ -1896,17 +1898,17 @@ js_InternNonIntElementId(JSContext *cx, 
 JSBool
 js_EnterWith(JSContext *cx, jsint stackIndex)
 {
     JSStackFrame *fp;
     jsval *sp;
     JSObject *obj, *parent, *withobj;
 
     fp = cx->fp;
-    sp = fp->regs->sp;
+    sp = fp->sp;
     JS_ASSERT(stackIndex < 0);
     JS_ASSERT(fp->spbase <= sp + stackIndex);
 
     if (!JSVAL_IS_PRIMITIVE(sp[-1])) {
         obj = JSVAL_TO_OBJECT(sp[-1]);
     } else {
         obj = js_ValueToNonNullObject(cx, sp[-1]);
         if (!obj)
@@ -1984,17 +1986,17 @@ js_CountWithBlocks(JSContext *cx, JSStac
 JSBool
 js_UnwindScope(JSContext *cx, JSStackFrame *fp, jsint stackDepth,
                JSBool normalUnwind)
 {
     JSObject *obj;
     JSClass *clasp;
 
     JS_ASSERT(stackDepth >= 0);
-    JS_ASSERT(fp->spbase + stackDepth <= fp->regs->sp);
+    JS_ASSERT(fp->spbase + stackDepth <= fp->sp);
 
     for (obj = fp->blockChain; obj; obj = OBJ_GET_PARENT(cx, obj)) {
         JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_BlockClass);
         if (OBJ_BLOCK_DEPTH(cx, obj) < stackDepth)
             break;
     }
     fp->blockChain = obj;
 
@@ -2006,17 +2008,17 @@ js_UnwindScope(JSContext *cx, JSStackFra
         if (clasp == &js_BlockClass) {
             /* Don't fail until after we've updated all stacks. */
             normalUnwind &= js_PutBlockObject(cx, normalUnwind);
         } else {
             js_LeaveWith(cx);
         }
     }
 
-    fp->regs->sp = fp->spbase + stackDepth;
+    fp->sp = fp->spbase + stackDepth;
     return normalUnwind;
 }
 
 JSBool
 js_DoIncDec(JSContext *cx, const JSCodeSpec *cs, jsval *vp, jsval *vp2)
 {
     jsval v;
     jsdouble d;
@@ -2186,52 +2188,83 @@ js_DumpOpMeters()
     }
     fclose(fp);
 }
 
 #endif /* JS_OPSMETER */
 
 #else /* !defined js_invoke_c__ */
 
-#define PUSH(v)         (*regs.sp++ = (v))
+/*
+ * Stack macros and functions.  These all use a local variable, jsval *sp, to
+ * point to the next free stack slot.  SAVE_SP must be called before any call
+ * to a function that may invoke the interpreter.  RESTORE_SP must be called
+ * only after return from js_Invoke, because only js_Invoke changes fp->sp.
+ */
+#define SAVE_SP(fp)                                                           \
+    (JS_ASSERT((fp)->script || !(fp)->spbase || (sp) == (fp)->spbase),        \
+     (fp)->sp = sp)
+#define RESTORE_SP(fp)  (sp = (fp)->sp)
+
+/*
+ * SAVE_SP_AND_PC commits deferred stores of interpreter registers to their
+ * homes in fp, when calling out of the interpreter loop or threaded code.
+ * RESTORE_SP_AND_PC copies the other way, to update registers after a call
+ * to a subroutine that interprets a piece of the current script.
+ * ASSERT_SAVED_SP_AND_PC checks that SAVE_SP_AND_PC was called.
+ */
+#define SAVE_SP_AND_PC(fp)      (SAVE_SP(fp), (fp)->pc = pc)
+#define RESTORE_SP_AND_PC(fp)   (RESTORE_SP(fp), pc = (fp)->pc)
+#define ASSERT_SAVED_SP_AND_PC(fp) JS_ASSERT((fp)->sp == sp && (fp)->pc == pc);
+
+#define PUSH(v)         (*sp++ = (v))
 #define PUSH_OPND(v)    PUSH(v)
-#define STORE_OPND(n,v) (regs.sp[n] = (v))
-#define POP()           (*--regs.sp)
+#define STORE_OPND(n,v) (sp[n] = (v))
+#define POP()           (*--sp)
 #define POP_OPND()      POP()
-#define FETCH_OPND(n)   (regs.sp[n])
+#define FETCH_OPND(n)   (sp[n])
 
 /*
  * Push the jsdouble d using sp from the lexical environment. Try to convert d
  * to a jsint that fits in a jsval, otherwise GC-alloc space for it and push a
  * reference.
  */
 #define STORE_NUMBER(cx, n, d)                                                \
     JS_BEGIN_MACRO                                                            \
         jsint i_;                                                             \
                                                                               \
-        if (JSDOUBLE_IS_INT(d, i_) && INT_FITS_IN_JSVAL(i_))                  \
-            regs.sp[n] = INT_TO_JSVAL(i_);                                    \
-        else if (!js_NewDoubleInRootedValue(cx, d, &regs.sp[n]))              \
-            goto error;                                                       \
+        if (JSDOUBLE_IS_INT(d, i_) && INT_FITS_IN_JSVAL(i_)) {                \
+            sp[n] = INT_TO_JSVAL(i_);                                         \
+        } else {                                                              \
+            SAVE_SP_AND_PC(fp);                                               \
+            if (!js_NewDoubleInRootedValue(cx, d, &sp[n]))                    \
+                goto error;                                                   \
+        }                                                                     \
     JS_END_MACRO
 
 #define STORE_INT(cx, n, i)                                                   \
     JS_BEGIN_MACRO                                                            \
-        if (INT_FITS_IN_JSVAL(i))                                             \
-            regs.sp[n] = INT_TO_JSVAL(i);                                     \
-        else if (!js_NewDoubleInRootedValue(cx, (jsdouble) (i), &regs.sp[n])) \
-            goto error;                                                       \
+        if (INT_FITS_IN_JSVAL(i)) {                                           \
+            sp[n] = INT_TO_JSVAL(i);                                          \
+        } else {                                                              \
+            SAVE_SP_AND_PC(fp);                                               \
+            if (!js_NewDoubleInRootedValue(cx, (jsdouble)(i), &sp[n]))        \
+                goto error;                                                   \
+        }                                                                     \
     JS_END_MACRO
 
 #define STORE_UINT(cx, n, u)                                                  \
     JS_BEGIN_MACRO                                                            \
-        if ((u) <= JSVAL_INT_MAX)                                             \
-            regs.sp[n] = INT_TO_JSVAL(u);                                     \
-        else if (!js_NewDoubleInRootedValue(cx, (jsdouble) (u), &regs.sp[n])) \
-            goto error;                                                       \
+        if ((u) <= JSVAL_INT_MAX) {                                           \
+            sp[n] = INT_TO_JSVAL(u);                                          \
+        } else {                                                              \
+            SAVE_SP_AND_PC(fp);                                               \
+            if (!js_NewDoubleInRootedValue(cx, (jsdouble)(u), &sp[n]))        \
+                goto error;                                                   \
+        }                                                                     \
     JS_END_MACRO
 
 #define FETCH_NUMBER(cx, n, d)                                                \
     JS_BEGIN_MACRO                                                            \
         jsval v_;                                                             \
                                                                               \
         v_ = FETCH_OPND(n);                                                   \
         VALUE_TO_NUMBER(cx, n, v_, d);                                        \
@@ -2240,94 +2273,100 @@ js_DumpOpMeters()
 #define FETCH_INT(cx, n, i)                                                   \
     JS_BEGIN_MACRO                                                            \
         jsval v_;                                                             \
                                                                               \
         v_= FETCH_OPND(n);                                                    \
         if (JSVAL_IS_INT(v_)) {                                               \
             i = JSVAL_TO_INT(v_);                                             \
         } else {                                                              \
-            i = js_ValueToECMAInt32(cx, &regs.sp[n]);                         \
-            if (JSVAL_IS_NULL(regs.sp[n]))                                    \
+            SAVE_SP_AND_PC(fp);                                               \
+            i = js_ValueToECMAInt32(cx, &sp[n]);                              \
+            if (JSVAL_IS_NULL(sp[n]))                                         \
                 goto error;                                                   \
         }                                                                     \
     JS_END_MACRO
 
 #define FETCH_UINT(cx, n, ui)                                                 \
     JS_BEGIN_MACRO                                                            \
         jsval v_;                                                             \
                                                                               \
         v_= FETCH_OPND(n);                                                    \
         if (JSVAL_IS_INT(v_)) {                                               \
             ui = (uint32) JSVAL_TO_INT(v_);                                   \
         } else {                                                              \
-            ui = js_ValueToECMAUint32(cx, &regs.sp[n]);                       \
-            if (JSVAL_IS_NULL(regs.sp[n]))                                    \
+            SAVE_SP_AND_PC(fp);                                               \
+            ui = js_ValueToECMAUint32(cx, &sp[n]);                            \
+            if (JSVAL_IS_NULL(sp[n]))                                         \
                 goto error;                                                   \
         }                                                                     \
     JS_END_MACRO
 
 /*
  * Optimized conversion macros that test for the desired type in v before
  * homing sp and calling a conversion function.
  */
 #define VALUE_TO_NUMBER(cx, n, v, d)                                          \
     JS_BEGIN_MACRO                                                            \
-        JS_ASSERT(v == regs.sp[n]);                                           \
+        JS_ASSERT(v == sp[n]);                                                \
         if (JSVAL_IS_INT(v)) {                                                \
             d = (jsdouble)JSVAL_TO_INT(v);                                    \
         } else if (JSVAL_IS_DOUBLE(v)) {                                      \
             d = *JSVAL_TO_DOUBLE(v);                                          \
         } else {                                                              \
-            d = js_ValueToNumber(cx, &regs.sp[n]);                            \
-            if (JSVAL_IS_NULL(regs.sp[n]))                                    \
+            SAVE_SP_AND_PC(fp);                                               \
+            d = js_ValueToNumber(cx, &sp[n]);                                 \
+            if (JSVAL_IS_NULL(sp[n]))                                         \
                 goto error;                                                   \
-            JS_ASSERT(JSVAL_IS_NUMBER(regs.sp[n]) ||                          \
-                      regs.sp[n] == JSVAL_TRUE);                              \
+            JS_ASSERT(JSVAL_IS_NUMBER(sp[n]) || sp[n] == JSVAL_TRUE);         \
         }                                                                     \
     JS_END_MACRO
 
 #define POP_BOOLEAN(cx, v, b)                                                 \
     JS_BEGIN_MACRO                                                            \
         v = FETCH_OPND(-1);                                                   \
         if (v == JSVAL_NULL) {                                                \
             b = JS_FALSE;                                                     \
         } else if (JSVAL_IS_BOOLEAN(v)) {                                     \
             b = JSVAL_TO_BOOLEAN(v);                                          \
         } else {                                                              \
             b = js_ValueToBoolean(v);                                         \
         }                                                                     \
-        regs.sp--;                                                            \
+        sp--;                                                                 \
     JS_END_MACRO
 
 #define VALUE_TO_OBJECT(cx, n, v, obj)                                        \
     JS_BEGIN_MACRO                                                            \
         if (!JSVAL_IS_PRIMITIVE(v)) {                                         \
             obj = JSVAL_TO_OBJECT(v);                                         \
         } else {                                                              \
+            SAVE_SP_AND_PC(fp);                                               \
             obj = js_ValueToNonNullObject(cx, v);                             \
             if (!obj)                                                         \
                 goto error;                                                   \
             STORE_OPND(n, OBJECT_TO_JSVAL(obj));                              \
         }                                                                     \
     JS_END_MACRO
 
+/* SAVE_SP_AND_PC must be already called. */
 #define FETCH_OBJECT(cx, n, v, obj)                                           \
     JS_BEGIN_MACRO                                                            \
+        ASSERT_SAVED_SP_AND_PC(fp);                                           \
         v = FETCH_OPND(n);                                                    \
         VALUE_TO_OBJECT(cx, n, v, obj);                                       \
     JS_END_MACRO
 
 #define DEFAULT_VALUE(cx, n, hint, v)                                         \
     JS_BEGIN_MACRO                                                            \
         JS_ASSERT(!JSVAL_IS_PRIMITIVE(v));                                    \
-        JS_ASSERT(v == regs.sp[n]);                                           \
-        if (!OBJ_DEFAULT_VALUE(cx, JSVAL_TO_OBJECT(v), hint, &regs.sp[n]))    \
+        JS_ASSERT(v == sp[n]);                                                \
+        SAVE_SP_AND_PC(fp);                                                   \
+        if (!OBJ_DEFAULT_VALUE(cx, JSVAL_TO_OBJECT(v), hint, &sp[n]))         \
             goto error;                                                       \
-        v = regs.sp[n];                                                       \
+        v = sp[n];                                                            \
     JS_END_MACRO
 
 /*
  * Quickly test if v is an int from the [-2**29, 2**29) range, that is, when
  * the lowest bit of v is 1 and the bits 30 and 31 are both either 0 or 1. For
  * such v we can do increment or decrement via adding or subtracting two
  * without checking that the result overflows JSVAL_INT_MIN or JSVAL_INT_MAX.
  */
@@ -2427,17 +2466,18 @@ js_Interpret(JSContext *cx)
 {
     JSRuntime *rt;
     JSStackFrame *fp;
     JSScript *script;
     uintN inlineCallCount;
     JSAtom **atoms;
     JSVersion currentVersion, originalVersion;
     void *mark;
-    JSFrameRegs regs;
+    jsval *sp;
+    jsbytecode *pc;
     JSObject *obj, *obj2, *parent;
     JSBool ok, cond;
     JSTrapHandler interruptHandler;
     jsint len;
     jsbytecode *endpc, *pc2;
     JSOp op, op2;
     jsatomid index;
     JSAtom *atom;
@@ -2489,23 +2529,23 @@ js_Interpret(JSContext *cx)
 # undef OPDEF
     };
 
     register void **jumpTable = normalJumpTable;
 
     METER_OP_INIT(op);      /* to nullify first METER_OP_PAIR */
 
 # define DO_OP()            JS_EXTENSION_(goto *jumpTable[op])
-# define DO_NEXT_OP(n)      do { METER_OP_PAIR(op, regs.pc[n]);               \
-                                 op = (JSOp) *(regs.pc += (n));               \
+# define DO_NEXT_OP(n)      do { METER_OP_PAIR(op, pc[n]);                    \
+                                 op = (JSOp) *(pc += (n));                    \
                                  DO_OP(); } while (0)
 # define BEGIN_CASE(OP)     L_##OP:
 # define END_CASE(OP)       DO_NEXT_OP(OP##_LENGTH);
 # define END_VARLEN_CASE    DO_NEXT_OP(len);
-# define EMPTY_CASE(OP)     BEGIN_CASE(OP) op = (JSOp) *++regs.pc; DO_OP();
+# define EMPTY_CASE(OP)     BEGIN_CASE(OP) op = (JSOp) *++pc; DO_OP();
 #else
 # define DO_OP()            goto do_op
 # define DO_NEXT_OP(n)      goto advance_pc
 # define BEGIN_CASE(OP)     case OP:
 # define END_CASE(OP)       break;
 # define END_VARLEN_CASE    break;
 # define EMPTY_CASE(OP)     BEGIN_CASE(OP) END_CASE(OP)
 #endif
@@ -2530,23 +2570,22 @@ js_Interpret(JSContext *cx)
      * access. For less frequent object and regexp loads we have to recover
      * the segment from atoms pointer first.
      */
     atoms = script->atomMap.vector;
 
 #define LOAD_ATOM(PCOFF)                                                      \
     JS_BEGIN_MACRO                                                            \
         JS_ASSERT((size_t)(atoms - script->atomMap.vector) <                  \
-                  (size_t)(script->atomMap.length -                           \
-                           GET_INDEX(regs.pc + PCOFF)));                      \
-        atom = atoms[GET_INDEX(regs.pc + PCOFF)];                             \
+                  (size_t)(script->atomMap.length - GET_INDEX(pc + PCOFF)));  \
+        atom = atoms[GET_INDEX(pc + PCOFF)];                                  \
     JS_END_MACRO
 
 #define GET_FULL_INDEX(PCOFF)                                                 \
-    (atoms - script->atomMap.vector + GET_INDEX(regs.pc + PCOFF))
+    (atoms - script->atomMap.vector + GET_INDEX(pc + PCOFF))
 
 #define LOAD_OBJECT(PCOFF)                                                    \
     JS_GET_SCRIPT_OBJECT(script, GET_FULL_INDEX(PCOFF), obj)
 
 #define LOAD_FUNCTION(PCOFF)                                                  \
     JS_BEGIN_MACRO                                                            \
         LOAD_OBJECT(PCOFF);                                                   \
         JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_FunctionClass);               \
@@ -2554,16 +2593,17 @@ js_Interpret(JSContext *cx)
 
     /*
      * Prepare to call a user-supplied branch handler, and abort the script
      * if it returns false.
      */
 #define CHECK_BRANCH(len)                                                     \
     JS_BEGIN_MACRO                                                            \
         if (len <= 0 && (cx->operationCount -= JSOW_SCRIPT_JUMP) <= 0) {      \
+            SAVE_SP_AND_PC(fp);                                               \
             if (!js_ResetOperationCount(cx))                                  \
                 goto error;                                                   \
         }                                                                     \
     JS_END_MACRO
 
     /*
      * Optimized Get and SetVersion for proper script language versioning.
      *
@@ -2579,17 +2619,17 @@ js_Interpret(JSContext *cx)
         js_SetVersion(cx, currentVersion);
 
     ++cx->interpLevel;
 #ifdef DEBUG
     fp->pcDisabledSave = JS_PROPERTY_CACHE(cx).disabled;
 #endif
 
     /*
-     * From this point control must flow through the label exit2.
+     * From this point the control must flow through the label exit.
      *
      * Load the debugger's interrupt hook here and after calling out to native
      * functions (but not to getters, setters, or other native hooks), so we do
      * not have to reload it each time through the interpreter loop -- we hope
      * the compiler can keep it in a register when it is non-null.
      */
 #if JS_THREADED_INTERP
 # define LOAD_JUMP_TABLE()                                                    \
@@ -2607,37 +2647,35 @@ js_Interpret(JSContext *cx)
     LOAD_INTERRUPT_HANDLER(cx);
 
      /*
      * Initialize the pc register and allocate operand stack slots for the
      * script's worst-case depth, unless we're resuming a generator.
      */
     if (JS_LIKELY(!fp->spbase)) {
         ASSERT_NOT_THROWING(cx);
-        JS_ASSERT(!fp->regs);
+        JS_ASSERT(!fp->pc);
+        JS_ASSERT(!fp->sp);
+        JS_ASSERT(!fp->spbase);
         fp->spbase = js_AllocRawStack(cx, script->depth, &mark);
         if (!fp->spbase) {
+            mark = NULL;
             ok = JS_FALSE;
-            goto exit2;
+            goto exit;
         }
         JS_ASSERT(mark);
-        regs.pc = script->code;
-        regs.sp = fp->spbase;
-        fp->regs = &regs;
+        fp->pc = script->code;
+        fp->sp = fp->spbase;
+        RESTORE_SP_AND_PC(fp);
     } else {
-        JSGenerator *gen;
-
         JS_ASSERT(fp->flags & JSFRAME_GENERATOR);
         mark = NULL;
-        gen = FRAME_TO_GENERATOR(fp);
-        JS_ASSERT(fp->regs == &gen->savedRegs);
-        regs = gen->savedRegs;
-        fp->regs = &regs;
-        JS_ASSERT((size_t) (regs.pc - script->code) <= script->length);
-        JS_ASSERT((size_t) (regs.sp - fp->spbase) <= script->depth);
+        RESTORE_SP_AND_PC(fp);
+        JS_ASSERT((size_t) (pc - script->code) <= script->length);
+        JS_ASSERT((size_t) (sp - fp->spbase) <= script->depth);
         JS_ASSERT(JS_PROPERTY_CACHE(cx).disabled >= 0);
         JS_PROPERTY_CACHE(cx).disabled += js_CountWithBlocks(cx, fp);
 
         /*
          * To support generator_throw and to catch ignored exceptions,
          * fail if cx->throwing is set.
          */
         if (cx->throwing) {
@@ -2660,20 +2698,21 @@ js_Interpret(JSContext *cx)
      * The trick is LOAD_INTERRUPT_HANDLER setting jumpTable appropriately.
      *
      * It is important that "op" be initialized before the interrupt label
      * because it is possible for "op" to be specially assigned during the
      * normally processing of an opcode while looping (in particular, this
      * happens in JSOP_TRAP while debugging).  We rely on DO_NEXT_OP to
      * correctly manage "op" in all other cases.
      */
-    op = (JSOp) *regs.pc;
+    op = (JSOp) *pc;
     if (interruptHandler) {
 interrupt:
-        switch (interruptHandler(cx, script, regs.pc, &rval,
+        SAVE_SP_AND_PC(fp);
+        switch (interruptHandler(cx, script, pc, &rval,
                                  cx->debugHooks->interruptHandlerData)) {
           case JSTRAP_ERROR:
             goto error;
           case JSTRAP_CONTINUE:
             break;
           case JSTRAP_RETURN:
             fp->rval = rval;
             ok = JS_TRUE;
@@ -2688,48 +2727,50 @@ interrupt:
     }
 
     JS_ASSERT((uintN)op < (uintN)JSOP_LIMIT);
     JS_EXTENSION_(goto *normalJumpTable[op]);
 
 #else  /* !JS_THREADED_INTERP */
 
     for (;;) {
-        op = (JSOp) *regs.pc;
+        op = (JSOp) *pc;
       do_op:
         len = js_CodeSpec[op].length;
 
 #ifdef DEBUG
         tracefp = (FILE *) cx->tracefp;
         if (tracefp) {
             intN nuses, n;
 
-            fprintf(tracefp, "%4u: ", js_PCToLineNumber(cx, script, regs.pc));
-            js_Disassemble1(cx, script, regs.pc,
-                            PTRDIFF(regs.pc, script->code, jsbytecode),
-                            JS_FALSE, tracefp);
+            fprintf(tracefp, "%4u: ", js_PCToLineNumber(cx, script, pc));
+            js_Disassemble1(cx, script, pc,
+                            PTRDIFF(pc, script->code, jsbytecode), JS_FALSE,
+                            tracefp);
             nuses = js_CodeSpec[op].nuses;
             if (nuses) {
+                SAVE_SP_AND_PC(fp);
                 for (n = -nuses; n < 0; n++) {
-                    char *bytes = js_DecompileValueGenerator(cx, n, regs.sp[n],
+                    char *bytes = js_DecompileValueGenerator(cx, n, sp[n],
                                                              NULL);
                     if (bytes) {
                         fprintf(tracefp, "%s %s",
                                 (n == -nuses) ? "  inputs:" : ",",
                                 bytes);
                         JS_free(cx, bytes);
                     }
                 }
-                fprintf(tracefp, " @ %d\n", regs.sp - fp->spbase);
+                fprintf(tracefp, " @ %d\n", sp - fp->spbase);
             }
         }
 #endif /* DEBUG */
 
         if (interruptHandler) {
-            switch (interruptHandler(cx, script, regs.pc, &rval,
+            SAVE_SP_AND_PC(fp);
+            switch (interruptHandler(cx, script, pc, &rval,
                                      cx->debugHooks->interruptHandlerData)) {
               case JSTRAP_ERROR:
                 goto error;
               case JSTRAP_CONTINUE:
                 break;
               case JSTRAP_RETURN:
                 fp->rval = rval;
                 ok = JS_TRUE;
@@ -2751,89 +2792,92 @@ interrupt:
 
           EMPTY_CASE(JSOP_GROUP)
 
           BEGIN_CASE(JSOP_PUSH)
             PUSH_OPND(JSVAL_VOID);
           END_CASE(JSOP_PUSH)
 
           BEGIN_CASE(JSOP_POP)
-            regs.sp--;
+            sp--;
           END_CASE(JSOP_POP)
 
           BEGIN_CASE(JSOP_POPN)
-            regs.sp -= GET_UINT16(regs.pc);
+            sp -= GET_UINT16(pc);
 #ifdef DEBUG
-            JS_ASSERT(fp->spbase <= regs.sp);
+            JS_ASSERT(fp->spbase <= sp);
             obj = fp->blockChain;
-            JS_ASSERT_IF(obj,
-                         OBJ_BLOCK_DEPTH(cx, obj) + OBJ_BLOCK_COUNT(cx, obj)
-                         <= (size_t) (regs.sp - fp->spbase));
+            JS_ASSERT(!obj ||
+                      fp->spbase + OBJ_BLOCK_DEPTH(cx, obj)
+                                 + OBJ_BLOCK_COUNT(cx, obj)
+                      <= sp);
             for (obj = fp->scopeChain; obj; obj = OBJ_GET_PARENT(cx, obj)) {
                 clasp = OBJ_GET_CLASS(cx, obj);
                 if (clasp != &js_BlockClass && clasp != &js_WithClass)
                     continue;
                 if (OBJ_GET_PRIVATE(cx, obj) != fp)
                     break;
                 JS_ASSERT(fp->spbase + OBJ_BLOCK_DEPTH(cx, obj)
                                      + ((clasp == &js_BlockClass)
-                                        ? OBJ_BLOCK_COUNT(cx, obj)
-                                        : 1)
-                          <= regs.sp);
+                                         ? OBJ_BLOCK_COUNT(cx, obj)
+                                         : 1)
+                          <= sp);
             }
 #endif
           END_CASE(JSOP_POPN)
 
           BEGIN_CASE(JSOP_SWAP)
-            rtmp = regs.sp[-1];
-            regs.sp[-1] = regs.sp[-2];
-            regs.sp[-2] = rtmp;
+            rtmp = sp[-1];
+            sp[-1] = sp[-2];
+            sp[-2] = rtmp;
           END_CASE(JSOP_SWAP)
 
           BEGIN_CASE(JSOP_SETRVAL)
           BEGIN_CASE(JSOP_POPV)
             ASSERT_NOT_THROWING(cx);
             fp->rval = POP_OPND();
           END_CASE(JSOP_POPV)
 
           BEGIN_CASE(JSOP_ENTERWITH)
+            SAVE_SP_AND_PC(fp);
             if (!js_EnterWith(cx, -1))
                 goto error;
 
             /*
              * We must ensure that different "with" blocks have different
              * stack depth associated with them. This allows the try handler
              * search to properly recover the scope chain. Thus we must keep
              * the stack at least at the current level.
              *
              * We set sp[-1] to the current "with" object to help asserting
              * the enter/leave balance in [leavewith].
              */
-            regs.sp[-1] = OBJECT_TO_JSVAL(fp->scopeChain);
+            sp[-1] = OBJECT_TO_JSVAL(fp->scopeChain);
           END_CASE(JSOP_ENTERWITH)
 
           BEGIN_CASE(JSOP_LEAVEWITH)
-            JS_ASSERT(regs.sp[-1] == OBJECT_TO_JSVAL(fp->scopeChain));
-            regs.sp--;
+            JS_ASSERT(sp[-1] == OBJECT_TO_JSVAL(fp->scopeChain));
+            sp--;
+            SAVE_SP_AND_PC(fp);
             js_LeaveWith(cx);
           END_CASE(JSOP_LEAVEWITH)
 
           BEGIN_CASE(JSOP_RETURN)
             CHECK_BRANCH(-1);
             fp->rval = POP_OPND();
             /* FALL THROUGH */
 
           BEGIN_CASE(JSOP_RETRVAL)    /* fp->rval already set */
           BEGIN_CASE(JSOP_STOP)
             /*
              * When the inlined frame exits with an exception or an error, ok
              * will be false after the inline_return label.
              */
             ASSERT_NOT_THROWING(cx);
-            JS_ASSERT(regs.sp == fp->spbase);
+            JS_ASSERT(sp == fp->spbase);
             ok = JS_TRUE;
             if (inlineCallCount)
           inline_return:
             {
                 JSInlineFrame *ifp = (JSInlineFrame *) fp;
                 void *hookData = ifp->hookData;
 
                 JS_ASSERT(JS_PROPERTY_CACHE(cx).disabled == fp->pcDisabledSave);
@@ -2845,34 +2889,39 @@ interrupt:
                     JSBool status;
 
                     hook = cx->debugHooks->callHook;
                     if (hook) {
                         /*
                          * Do not pass &ok directly as exposing the address
                          * inhibits optimizations and uninitialised warnings.
                          */
+                        SAVE_SP_AND_PC(fp);
                         status = ok;
                         hook(cx, fp, JS_FALSE, &status, hookData);
                         ok = status;
                         LOAD_INTERRUPT_HANDLER(cx);
                     }
                 }
 
                 /*
                  * If fp has a call object, sync values and clear the back-
                  * pointer. This can happen for a lightweight function if it
                  * calls eval unexpectedly (in a way that is hidden from the
                  * compiler). See bug 325540.
                  */
-                if (fp->callobj)
+                if (fp->callobj) {
+                    SAVE_SP_AND_PC(fp);
                     ok &= js_PutCallObject(cx, fp);
-
-                if (fp->argsobj)
+                }
+
+                if (fp->argsobj) {
+                    SAVE_SP_AND_PC(fp);
                     ok &= js_PutArgsObject(cx, fp);
+                }
 
 #ifdef INCLUDE_MOZILLA_DTRACE
                 /* DTrace function return, inlines */
                 if (JAVASCRIPT_FUNCTION_RVAL_ENABLED())
                     jsdtrace_function_rval(cx, fp, fp->fun);
                 if (JAVASCRIPT_FUNCTION_RETURN_ENABLED())
                     jsdtrace_function_return(cx, fp, fp->fun);
 #endif
@@ -2880,158 +2929,163 @@ interrupt:
                 /* Restore context version only if callee hasn't set version. */
                 if (JS_LIKELY(cx->version == currentVersion)) {
                     currentVersion = ifp->callerVersion;
                     if (currentVersion != cx->version)
                         js_SetVersion(cx, currentVersion);
                 }
 
                 /* Store the return value in the caller's operand frame. */
-                regs = ifp->callerRegs;
-                regs.sp += 1 - 2 - ifp->frame.argc;
-                regs.sp[-1] = fp->rval;
+                vp = ifp->rvp;
+                *vp = fp->rval;
 
                 /* Restore cx->fp and release the inline frame's space. */
                 cx->fp = fp = fp->down;
-                JS_ASSERT(fp->regs == &ifp->callerRegs);
-                fp->regs = &regs;
                 JS_ARENA_RELEASE(&cx->stackPool, ifp->mark);
 
+                /* Restore sp to point just above the return value. */
+                fp->sp = vp + 1;
+                RESTORE_SP(fp);
+
                 /* Restore the calling script's interpreter registers. */
                 script = fp->script;
                 atoms = script->atomMap.vector;
+                pc = fp->pc;
 
                 /* Resume execution in the calling frame. */
                 inlineCallCount--;
                 if (JS_LIKELY(ok)) {
-                    JS_ASSERT(js_CodeSpec[*regs.pc].length == JSOP_CALL_LENGTH);
+                    JS_ASSERT(js_CodeSpec[*pc].length == JSOP_CALL_LENGTH);
                     len = JSOP_CALL_LENGTH;
                     DO_NEXT_OP(len);
                 }
                 goto error;
             }
             goto exit;
 
           BEGIN_CASE(JSOP_DEFAULT)
             (void) POP();
             /* FALL THROUGH */
           BEGIN_CASE(JSOP_GOTO)
-            len = GET_JUMP_OFFSET(regs.pc);
+            len = GET_JUMP_OFFSET(pc);
             CHECK_BRANCH(len);
           END_VARLEN_CASE
 
           BEGIN_CASE(JSOP_IFEQ)
             POP_BOOLEAN(cx, rval, cond);
             if (cond == JS_FALSE) {
-                len = GET_JUMP_OFFSET(regs.pc);
+                len = GET_JUMP_OFFSET(pc);
                 CHECK_BRANCH(len);
                 DO_NEXT_OP(len);
             }
           END_CASE(JSOP_IFEQ)
 
           BEGIN_CASE(JSOP_IFNE)
             POP_BOOLEAN(cx, rval, cond);
             if (cond != JS_FALSE) {
-                len = GET_JUMP_OFFSET(regs.pc);
+                len = GET_JUMP_OFFSET(pc);
                 CHECK_BRANCH(len);
                 DO_NEXT_OP(len);
             }
           END_CASE(JSOP_IFNE)
 
           BEGIN_CASE(JSOP_OR)
             POP_BOOLEAN(cx, rval, cond);
             if (cond == JS_TRUE) {
-                len = GET_JUMP_OFFSET(regs.pc);
+                len = GET_JUMP_OFFSET(pc);
                 PUSH_OPND(rval);
                 DO_NEXT_OP(len);
             }
           END_CASE(JSOP_OR)
 
           BEGIN_CASE(JSOP_AND)
             POP_BOOLEAN(cx, rval, cond);
             if (cond == JS_FALSE) {
-                len = GET_JUMP_OFFSET(regs.pc);
+                len = GET_JUMP_OFFSET(pc);
                 PUSH_OPND(rval);
                 DO_NEXT_OP(len);
             }
           END_CASE(JSOP_AND)
 
           BEGIN_CASE(JSOP_DEFAULTX)
             (void) POP();
             /* FALL THROUGH */
           BEGIN_CASE(JSOP_GOTOX)
-            len = GET_JUMPX_OFFSET(regs.pc);
+            len = GET_JUMPX_OFFSET(pc);
             CHECK_BRANCH(len);
           END_VARLEN_CASE
 
           BEGIN_CASE(JSOP_IFEQX)
             POP_BOOLEAN(cx, rval, cond);
             if (cond == JS_FALSE) {
-                len = GET_JUMPX_OFFSET(regs.pc);
+                len = GET_JUMPX_OFFSET(pc);
                 CHECK_BRANCH(len);
                 DO_NEXT_OP(len);
             }
           END_CASE(JSOP_IFEQX)
 
           BEGIN_CASE(JSOP_IFNEX)
             POP_BOOLEAN(cx, rval, cond);
             if (cond != JS_FALSE) {
-                len = GET_JUMPX_OFFSET(regs.pc);
+                len = GET_JUMPX_OFFSET(pc);
                 CHECK_BRANCH(len);
                 DO_NEXT_OP(len);
             }
           END_CASE(JSOP_IFNEX)
 
           BEGIN_CASE(JSOP_ORX)
             POP_BOOLEAN(cx, rval, cond);
             if (cond == JS_TRUE) {
-                len = GET_JUMPX_OFFSET(regs.pc);
+                len = GET_JUMPX_OFFSET(pc);
                 PUSH_OPND(rval);
                 DO_NEXT_OP(len);
             }
           END_CASE(JSOP_ORX)
 
           BEGIN_CASE(JSOP_ANDX)
             POP_BOOLEAN(cx, rval, cond);
             if (cond == JS_FALSE) {
-                len = GET_JUMPX_OFFSET(regs.pc);
+                len = GET_JUMPX_OFFSET(pc);
                 PUSH_OPND(rval);
                 DO_NEXT_OP(len);
             }
           END_CASE(JSOP_ANDX)
 
 /*
  * If the index value at sp[n] is not an int that fits in a jsval, it could
  * be an object (an XML QName, AttributeName, or AnyName), but only if we are
  * compiling with JS_HAS_XML_SUPPORT.  Otherwise convert the index value to a
  * string atom id.
+ *
+ * SAVE_SP_AND_PC must be already called.
  */
 #define FETCH_ELEMENT_ID(obj, n, id)                                          \
     JS_BEGIN_MACRO                                                            \
         jsval idval_ = FETCH_OPND(n);                                         \
         if (JSVAL_IS_INT(idval_)) {                                           \
             id = INT_JSVAL_TO_JSID(idval_);                                   \
         } else {                                                              \
             if (!js_InternNonIntElementId(cx, obj, idval_, &id))              \
                 goto error;                                                   \
-            regs.sp[n] = ID_TO_VALUE(id);                                     \
+            sp[n] = ID_TO_VALUE(id);                                          \
         }                                                                     \
     JS_END_MACRO
 
           BEGIN_CASE(JSOP_IN)
             rval = FETCH_OPND(-1);
+            SAVE_SP_AND_PC(fp);
             if (JSVAL_IS_PRIMITIVE(rval)) {
                 js_ReportValueError(cx, JSMSG_IN_NOT_OBJECT, -1, rval, NULL);
                 goto error;
             }
             obj = JSVAL_TO_OBJECT(rval);
             FETCH_ELEMENT_ID(obj, -2, id);
             if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop))
                 goto error;
-            regs.sp--;
+            sp--;
             STORE_OPND(-1, BOOLEAN_TO_JSVAL(prop != NULL));
             if (prop)
                 OBJ_DROP_PROPERTY(cx, obj2, prop);
           END_CASE(JSOP_IN)
 
           BEGIN_CASE(JSOP_FOREACH)
             flags = JSITER_ENUMERATE | JSITER_FOREACH;
             goto value_to_iter;
@@ -3047,20 +3101,21 @@ interrupt:
              * Set JSITER_ENUMERATE to indicate that for-in loop should use
              * the enumeration protocol's iterator for compatibility if an
              * explicit iterator is not given via the optional __iterator__
              * method.
              */
             flags = JSITER_ENUMERATE;
 
           value_to_iter:
-            JS_ASSERT(regs.sp > fp->spbase);
-            if (!js_ValueToIterator(cx, flags, &regs.sp[-1]))
+            JS_ASSERT(sp > fp->spbase);
+            SAVE_SP_AND_PC(fp);
+            if (!js_ValueToIterator(cx, flags, &sp[-1]))
                 goto error;
-            JS_ASSERT(!JSVAL_IS_PRIMITIVE(regs.sp[-1]));
+            JS_ASSERT(!JSVAL_IS_PRIMITIVE(sp[-1]));
             JS_ASSERT(JSOP_FORIN_LENGTH == js_CodeSpec[op].length);
           END_CASE(JSOP_FORIN)
 
           BEGIN_CASE(JSOP_FORPROP)
             /*
              * Handle JSOP_FORPROP first, so the cost of the goto do_forinloop
              * is not paid for the more common cases.
              */
@@ -3095,45 +3150,46 @@ interrupt:
              */
             i = -1;
 
           do_forinloop:
             /*
              * Reach under the top of stack to find our property iterator, a
              * JSObject that contains the iteration state.
              */
-            JS_ASSERT(!JSVAL_IS_PRIMITIVE(regs.sp[i]));
-            iterobj = JSVAL_TO_OBJECT(regs.sp[i]);
-
+            JS_ASSERT(!JSVAL_IS_PRIMITIVE(sp[i]));
+            iterobj = JSVAL_TO_OBJECT(sp[i]);
+
+            SAVE_SP_AND_PC(fp);
             if (!js_CallIteratorNext(cx, iterobj, &rval))
                 goto error;
             if (rval == JSVAL_HOLE) {
                 rval = JSVAL_FALSE;
                 goto end_forinloop;
             }
 
             switch (op) {
               case JSOP_FORARG:
-                slot = GET_ARGNO(regs.pc);
+                slot = GET_ARGNO(pc);
                 JS_ASSERT(slot < fp->fun->nargs);
                 fp->argv[slot] = rval;
                 break;
 
               case JSOP_FORVAR:
-                slot = GET_VARNO(regs.pc);
+                slot = GET_VARNO(pc);
                 JS_ASSERT(slot < fp->fun->u.i.nvars);
                 fp->vars[slot] = rval;
                 break;
 
               case JSOP_FORCONST:
                 /* Don't update the const slot. */
                 break;
 
               case JSOP_FORLOCAL:
-                slot = GET_UINT16(regs.pc);
+                slot = GET_UINT16(pc);
                 JS_ASSERT(slot < script->depth);
                 vp = &fp->spbase[slot];
                 GC_POKE(cx, *vp);
                 *vp = rval;
                 break;
 
               case JSOP_FORELEM:
                 /* FORELEM is not a SET operation, it's more like BINDNAME. */
@@ -3141,16 +3197,17 @@ interrupt:
                 break;
 
               case JSOP_FORPROP:
                 /*
                  * We fetch object here to ensure that the iterator is called
                  * even if lval is null or undefined that throws in
                  * FETCH_OBJECT. See bug 372331.
                  */
+                SAVE_SP_AND_PC(fp);
                 FETCH_OBJECT(cx, -1, lval, obj);
                 goto set_for_property;
 
               default:
                 JS_ASSERT(op == JSOP_FORNAME);
 
                 /*
                  * We find property here after the iterator call to ensure
@@ -3172,48 +3229,50 @@ interrupt:
                     goto error;
                 break;
             }
 
             /* Push true to keep looping through properties. */
             rval = JSVAL_TRUE;
 
           end_forinloop:
-            regs.sp += i + 1;
+            sp += i + 1;
             PUSH_OPND(rval);
             len = js_CodeSpec[op].length;
             DO_NEXT_OP(len);
 
           BEGIN_CASE(JSOP_DUP)
-            JS_ASSERT(regs.sp > fp->spbase);
+            JS_ASSERT(sp > fp->spbase);
             rval = FETCH_OPND(-1);
             PUSH(rval);
           END_CASE(JSOP_DUP)
 
           BEGIN_CASE(JSOP_DUP2)
-            JS_ASSERT(regs.sp - 2 >= fp->spbase);
+            JS_ASSERT(sp - 2 >= fp->spbase);
             lval = FETCH_OPND(-2);
             rval = FETCH_OPND(-1);
             PUSH(lval);
             PUSH(rval);
           END_CASE(JSOP_DUP2)
 
 #define PROPERTY_OP(n, call)                                                  \
     JS_BEGIN_MACRO                                                            \
         /* Fetch the left part and resolve it to a non-null object. */        \
+        SAVE_SP_AND_PC(fp);                                                   \
         FETCH_OBJECT(cx, n, lval, obj);                                       \
                                                                               \
         /* Get or set the property. */                                        \
         if (!call)                                                            \
             goto error;                                                       \
     JS_END_MACRO
 
 #define ELEMENT_OP(n, call)                                                   \
     JS_BEGIN_MACRO                                                            \
         /* Fetch the left part and resolve it to a non-null object. */        \
+        SAVE_SP_AND_PC(fp);                                                   \
         FETCH_OBJECT(cx, n - 1, lval, obj);                                   \
                                                                               \
         /* Fetch index and convert it to id suitable for use with obj. */     \
         FETCH_ELEMENT_ID(obj, n, id);                                         \
                                                                               \
         /* Get or set the element. */                                         \
         if (!call)                                                            \
             goto error;                                                       \
@@ -3224,28 +3283,30 @@ interrupt:
         if (SPROP_HAS_STUB_GETTER(sprop)) {                                   \
             /* Fast path for Object instance properties. */                   \
             JS_ASSERT((sprop)->slot != SPROP_INVALID_SLOT ||                  \
                       !SPROP_HAS_STUB_SETTER(sprop));                         \
             *vp = ((sprop)->slot != SPROP_INVALID_SLOT)                       \
                   ? LOCKED_OBJ_GET_SLOT(pobj, (sprop)->slot)                  \
                   : JSVAL_VOID;                                               \
         } else {                                                              \
+            SAVE_SP_AND_PC(fp);                                               \
             if (!js_NativeGet(cx, obj, pobj, sprop, vp))                      \
                 goto error;                                                   \
         }                                                                     \
     JS_END_MACRO
 
 #define NATIVE_SET(cx,obj,sprop,vp)                                           \
     JS_BEGIN_MACRO                                                            \
         if (SPROP_HAS_STUB_SETTER(sprop) &&                                   \
             (sprop)->slot != SPROP_INVALID_SLOT) {                            \
             /* Fast path for, e.g., Object instance properties. */            \
             LOCKED_OBJ_WRITE_BARRIER(cx, obj, (sprop)->slot, *vp);            \
         } else {                                                              \
+            SAVE_SP_AND_PC(fp);                                               \
             if (!js_NativeSet(cx, obj, sprop, vp))                            \
                 goto error;                                                   \
         }                                                                     \
     JS_END_MACRO
 
 /*
  * Deadlocks or else bad races are likely if JS_THREADSAFE, so we must rely on
  * single-thread DEBUG js shell testing to verify property cache hits.
@@ -3253,21 +3314,22 @@ interrupt:
 #if defined DEBUG && !defined JS_THREADSAFE
 # define ASSERT_VALID_PROPERTY_CACHE_HIT(pcoff,obj,pobj,entry)                \
     do {                                                                      \
         JSAtom *atom_;                                                        \
         JSObject *obj_, *pobj_;                                               \
         JSProperty *prop_;                                                    \
         JSScopeProperty *sprop_;                                              \
         uint32 sample_ = rt->gcNumber;                                        \
+        SAVE_SP_AND_PC(fp);                                                   \
         if (pcoff >= 0)                                                       \
-            GET_ATOM_FROM_BYTECODE(script, regs.pc, pcoff, atom_);            \
+            GET_ATOM_FROM_BYTECODE(script, pc, pcoff, atom_);                 \
         else                                                                  \
             atom_ = rt->atomState.lengthAtom;                                 \
-        if (JOF_OPMODE(*regs.pc) == JOF_NAME) {                               \
+        if (JOF_OPMODE(*pc) == JOF_NAME) {                                    \
             ok = js_FindProperty(cx, ATOM_TO_JSID(atom_), &obj_, &pobj_,      \
                                  &prop_);                                     \
         } else {                                                              \
             obj_ = obj;                                                       \
             ok = js_LookupProperty(cx, obj, ATOM_TO_JSID(atom_), &pobj_,      \
                                    &prop_);                                   \
         }                                                                     \
         if (!ok)                                                              \
@@ -3297,72 +3359,75 @@ interrupt:
 #else
 # define ASSERT_VALID_PROPERTY_CACHE_HIT(pcoff,obj,pobj,entry) ((void) 0)
 #endif
 
           BEGIN_CASE(JSOP_SETCONST)
             LOAD_ATOM(0);
             obj = fp->varobj;
             rval = FETCH_OPND(-1);
+            SAVE_SP_AND_PC(fp);
             if (!OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), rval,
                                      JS_PropertyStub, JS_PropertyStub,
                                      JSPROP_ENUMERATE | JSPROP_PERMANENT |
                                      JSPROP_READONLY,
                                      NULL)) {
                 goto error;
             }
             STORE_OPND(-1, rval);
           END_CASE(JSOP_SETCONST)
 
 #if JS_HAS_DESTRUCTURING
           BEGIN_CASE(JSOP_ENUMCONSTELEM)
             rval = FETCH_OPND(-3);
+            SAVE_SP_AND_PC(fp);
             FETCH_OBJECT(cx, -2, lval, obj);
             FETCH_ELEMENT_ID(obj, -1, id);
             if (!OBJ_DEFINE_PROPERTY(cx, obj, id, rval,
                                      JS_PropertyStub, JS_PropertyStub,
                                      JSPROP_ENUMERATE | JSPROP_PERMANENT |
                                      JSPROP_READONLY,
                                      NULL)) {
                 goto error;
             }
-            regs.sp -= 3;
+            sp -= 3;
           END_CASE(JSOP_ENUMCONSTELEM)
 #endif
 
           BEGIN_CASE(JSOP_BINDNAME)
             do {
                 JSPropCacheEntry *entry;
 
                 obj = fp->scopeChain;
                 if (JS_LIKELY(OBJ_IS_NATIVE(obj))) {
-                    PROPERTY_CACHE_TEST(cx, regs.pc, obj, obj2, entry, atom);
+                    PROPERTY_CACHE_TEST(cx, pc, obj, obj2, entry, atom);
                     if (!atom) {
                         ASSERT_VALID_PROPERTY_CACHE_HIT(0, obj, obj2, entry);
                         JS_UNLOCK_OBJ(cx, obj2);
                         break;
                     }
                 } else {
                     entry = NULL;
                     LOAD_ATOM(0);
                 }
                 id = ATOM_TO_JSID(atom);
+                SAVE_SP_AND_PC(fp);
                 obj = js_FindIdentifierBase(cx, id, entry);
                 if (!obj)
                     goto error;
             } while (0);
             PUSH_OPND(OBJECT_TO_JSVAL(obj));
           END_CASE(JSOP_BINDNAME)
 
 #define BITWISE_OP(OP)                                                        \
     JS_BEGIN_MACRO                                                            \
         FETCH_INT(cx, -2, i);                                                 \
         FETCH_INT(cx, -1, j);                                                 \
         i = i OP j;                                                           \
-        regs.sp--;                                                            \
+        sp--;                                                                 \
         STORE_INT(cx, -1, i);                                                 \
     JS_END_MACRO
 
           BEGIN_CASE(JSOP_BITOR)
             BITWISE_OP(|);
           END_CASE(JSOP_BITOR)
 
           BEGIN_CASE(JSOP_BITXOR)
@@ -3398,17 +3463,17 @@ interrupt:
                 str2 = JSVAL_TO_STRING(rval);                                 \
                 cond = js_CompareStrings(str, str2) OP 0;                     \
             } else {                                                          \
                 VALUE_TO_NUMBER(cx, -2, lval, d);                             \
                 VALUE_TO_NUMBER(cx, -1, rval, d2);                            \
                 cond = JSDOUBLE_COMPARE(d, OP, d2, JS_FALSE);                 \
             }                                                                 \
         }                                                                     \
-        regs.sp--;                                                            \
+        sp--;                                                                 \
         STORE_OPND(-1, BOOLEAN_TO_JSVAL(cond));                               \
     JS_END_MACRO
 
 /*
  * NB: These macros can't use JS_BEGIN_MACRO/JS_END_MACRO around their bodies
  * because they begin if/else chains, so callers must not put semicolons after
  * the call expressions!
  */
@@ -3420,28 +3485,30 @@ interrupt:
         (rtmp == JSVAL_OBJECT &&                                              \
          (obj2 = JSVAL_TO_OBJECT(rval)) &&                                    \
          OBJECT_IS_XML(cx, obj2))) {                                          \
         JSXMLObjectOps *ops;                                                  \
                                                                               \
         ops = (JSXMLObjectOps *) obj2->map->ops;                              \
         if (obj2 == JSVAL_TO_OBJECT(rval))                                    \
             rval = lval;                                                      \
+        SAVE_SP_AND_PC(fp);                                                   \
         if (!ops->equality(cx, obj2, rval, &cond))                            \
             goto error;                                                       \
         cond = cond OP JS_TRUE;                                               \
     } else
 
 #define EXTENDED_EQUALITY_OP(OP)                                              \
     if (ltmp == JSVAL_OBJECT &&                                               \
         (obj2 = JSVAL_TO_OBJECT(lval)) &&                                     \
         ((clasp = OBJ_GET_CLASS(cx, obj2))->flags & JSCLASS_IS_EXTENDED)) {   \
         JSExtendedClass *xclasp;                                              \
                                                                               \
         xclasp = (JSExtendedClass *) clasp;                                   \
+        SAVE_SP_AND_PC(fp);                                                   \
         if (!xclasp->equality(cx, obj2, rval, &cond))                         \
             goto error;                                                       \
         cond = cond OP JS_TRUE;                                               \
     } else
 #else
 #define XML_EQUALITY_OP(OP)             /* nothing */
 #define EXTENDED_EQUALITY_OP(OP)        /* nothing */
 #endif
@@ -3486,61 +3553,61 @@ interrupt:
                     cond = js_EqualStrings(str, str2) OP JS_TRUE;             \
                 } else {                                                      \
                     VALUE_TO_NUMBER(cx, -2, lval, d);                         \
                     VALUE_TO_NUMBER(cx, -1, rval, d2);                        \
                     cond = JSDOUBLE_COMPARE(d, OP, d2, IFNAN);                \
                 }                                                             \
             }                                                                 \
         }                                                                     \
-        regs.sp--;                                                            \
+        sp--;                                                                 \
         STORE_OPND(-1, BOOLEAN_TO_JSVAL(cond));                               \
     JS_END_MACRO
 
           BEGIN_CASE(JSOP_EQ)
             EQUALITY_OP(==, JS_FALSE);
           END_CASE(JSOP_EQ)
 
           BEGIN_CASE(JSOP_NE)
             EQUALITY_OP(!=, JS_TRUE);
           END_CASE(JSOP_NE)
 
 #define STRICT_EQUALITY_OP(OP)                                                \
     JS_BEGIN_MACRO                                                            \
         rval = FETCH_OPND(-1);                                                \
         lval = FETCH_OPND(-2);                                                \
         cond = js_StrictlyEqual(cx, lval, rval) OP JS_TRUE;                   \
-        regs.sp--;                                                            \
+        sp--;                                                                 \
         STORE_OPND(-1, BOOLEAN_TO_JSVAL(cond));                               \
     JS_END_MACRO
 
           BEGIN_CASE(JSOP_STRICTEQ)
             STRICT_EQUALITY_OP(==);
           END_CASE(JSOP_STRICTEQ)
 
           BEGIN_CASE(JSOP_STRICTNE)
             STRICT_EQUALITY_OP(!=);
           END_CASE(JSOP_STRICTNE)
 
           BEGIN_CASE(JSOP_CASE)
             STRICT_EQUALITY_OP(==);
             (void) POP();
             if (cond) {
-                len = GET_JUMP_OFFSET(regs.pc);
+                len = GET_JUMP_OFFSET(pc);
                 CHECK_BRANCH(len);
                 DO_NEXT_OP(len);
             }
             PUSH(lval);
           END_CASE(JSOP_CASE)
 
           BEGIN_CASE(JSOP_CASEX)
             STRICT_EQUALITY_OP(==);
             (void) POP();
             if (cond) {
-                len = GET_JUMPX_OFFSET(regs.pc);
+                len = GET_JUMPX_OFFSET(pc);
                 CHECK_BRANCH(len);
                 DO_NEXT_OP(len);
             }
             PUSH(lval);
           END_CASE(JSOP_CASEX)
 
           BEGIN_CASE(JSOP_LT)
             RELATIONAL_OP(<);
@@ -3569,29 +3636,30 @@ interrupt:
 #define FETCH_SHIFT(shift)                                                    \
     JS_BEGIN_MACRO                                                            \
         jsval v_;                                                             \
                                                                               \
         v_ = FETCH_OPND(-1);                                                  \
         if (v_ & JSVAL_INT) {                                                 \
             shift = JSVAL_TO_INT(v_);                                         \
         } else {                                                              \
-            shift = js_ValueToECMAInt32(cx, &regs.sp[-1]);                    \
-            if (JSVAL_IS_NULL(regs.sp[-1]))                                   \
+            SAVE_SP_AND_PC(fp);                                               \
+            shift = js_ValueToECMAInt32(cx, &sp[-1]);                         \
+            if (JSVAL_IS_NULL(sp[-1]))                                        \
                 goto error;                                                   \
         }                                                                     \
         shift &= 31;                                                          \
     JS_END_MACRO
 
 #define SIGNED_SHIFT_OP(OP)                                                   \
     JS_BEGIN_MACRO                                                            \
         FETCH_INT(cx, -2, i);                                                 \
         FETCH_SHIFT(j);                                                       \
         i = i OP j;                                                           \
-        regs.sp--;                                                            \
+        sp--;                                                                 \
         STORE_INT(cx, -1, i);                                                 \
     JS_END_MACRO
 
           BEGIN_CASE(JSOP_LSH)
             SIGNED_SHIFT_OP(<<);
           END_CASE(JSOP_LSH)
 
           BEGIN_CASE(JSOP_RSH)
@@ -3600,17 +3668,17 @@ interrupt:
 
           BEGIN_CASE(JSOP_URSH)
           {
             uint32 u;
 
             FETCH_UINT(cx, -2, u);
             FETCH_SHIFT(j);
             u >>= j;
-            regs.sp--;
+            sp--;
             STORE_UINT(cx, -1, u);
           }
           END_CASE(JSOP_URSH)
 
 #undef BITWISE_OP
 #undef SIGNED_SHIFT_OP
 
           BEGIN_CASE(JSOP_ADD)
@@ -3618,77 +3686,79 @@ interrupt:
             lval = FETCH_OPND(-2);
 #if JS_HAS_XML_SUPPORT
             if (!JSVAL_IS_PRIMITIVE(lval) &&
                 (obj2 = JSVAL_TO_OBJECT(lval), OBJECT_IS_XML(cx, obj2)) &&
                 VALUE_IS_XML(cx, rval)) {
                 JSXMLObjectOps *ops;
 
                 ops = (JSXMLObjectOps *) obj2->map->ops;
+                SAVE_SP_AND_PC(fp);
                 if (!ops->concatenate(cx, obj2, rval, &rval))
                     goto error;
-                regs.sp--;
+                sp--;
                 STORE_OPND(-1, rval);
             } else
 #endif
             {
                 if (!JSVAL_IS_PRIMITIVE(lval))
                     DEFAULT_VALUE(cx, -2, JSTYPE_VOID, lval);
                 if (!JSVAL_IS_PRIMITIVE(rval))
                     DEFAULT_VALUE(cx, -1, JSTYPE_VOID, rval);
                 if ((cond = JSVAL_IS_STRING(lval)) || JSVAL_IS_STRING(rval)) {
+                    SAVE_SP_AND_PC(fp);
                     if (cond) {
                         str = JSVAL_TO_STRING(lval);
                         str2 = js_ValueToString(cx, rval);
                         if (!str2)
                             goto error;
-                        regs.sp[-1] = STRING_TO_JSVAL(str2);
+                        sp[-1] = STRING_TO_JSVAL(str2);
                     } else {
                         str2 = JSVAL_TO_STRING(rval);
                         str = js_ValueToString(cx, lval);
                         if (!str)
                             goto error;
-                        regs.sp[-2] = STRING_TO_JSVAL(str);
+                        sp[-2] = STRING_TO_JSVAL(str);
                     }
                     str = js_ConcatStrings(cx, str, str2);
                     if (!str)
                         goto error;
-                    regs.sp--;
+                    sp--;
                     STORE_OPND(-1, STRING_TO_JSVAL(str));
                 } else {
                     VALUE_TO_NUMBER(cx, -2, lval, d);
                     VALUE_TO_NUMBER(cx, -1, rval, d2);
                     d += d2;
-                    regs.sp--;
+                    sp--;
                     STORE_NUMBER(cx, -1, d);
                 }
             }
           END_CASE(JSOP_ADD)
 
 #define BINARY_OP(OP)                                                         \
     JS_BEGIN_MACRO                                                            \
         FETCH_NUMBER(cx, -1, d2);                                             \
         FETCH_NUMBER(cx, -2, d);                                              \
         d = d OP d2;                                                          \
-        regs.sp--;                                                                 \
+        sp--;                                                                 \
         STORE_NUMBER(cx, -1, d);                                              \
     JS_END_MACRO
 
           BEGIN_CASE(JSOP_SUB)
             BINARY_OP(-);
           END_CASE(JSOP_SUB)
 
           BEGIN_CASE(JSOP_MUL)
             BINARY_OP(*);
           END_CASE(JSOP_MUL)
 
           BEGIN_CASE(JSOP_DIV)
             FETCH_NUMBER(cx, -1, d2);
             FETCH_NUMBER(cx, -2, d);
-            regs.sp--;
+            sp--;
             if (d2 == 0) {
 #ifdef XP_WIN
                 /* XXX MSVC miscompiles such that (NaN == 0) */
                 if (JSDOUBLE_IS_NaN(d2))
                     rval = DOUBLE_TO_JSVAL(rt->jsNaN);
                 else
 #endif
                 if (d == 0 || JSDOUBLE_IS_NaN(d))
@@ -3702,17 +3772,17 @@ interrupt:
                 d /= d2;
                 STORE_NUMBER(cx, -1, d);
             }
           END_CASE(JSOP_DIV)
 
           BEGIN_CASE(JSOP_MOD)
             FETCH_NUMBER(cx, -1, d2);
             FETCH_NUMBER(cx, -2, d);
-            regs.sp--;
+            sp--;
             if (d2 == 0) {
                 STORE_OPND(-1, DOUBLE_TO_JSVAL(rt->jsNaN));
             } else {
 #ifdef XP_WIN
               /* Workaround MS fmod bug where 42 % (1/0) => NaN, not 42. */
               if (!(JSDOUBLE_IS_FINITE(d) && JSDOUBLE_IS_INFINITE(d2)))
 #endif
                 d = fmod(d, d2);
@@ -3736,101 +3806,107 @@ interrupt:
              * Optimize the case of an int-tagged operand by noting that
              * INT_FITS_IN_JSVAL(i) => INT_FITS_IN_JSVAL(-i) unless i is 0
              * when -i is the negative zero which is jsdouble.
              */
             rval = FETCH_OPND(-1);
             if (JSVAL_IS_INT(rval) && (i = JSVAL_TO_INT(rval)) != 0) {
                 i = -i;
                 JS_ASSERT(INT_FITS_IN_JSVAL(i));
-                regs.sp[-1] = INT_TO_JSVAL(i);
+                sp[-1] = INT_TO_JSVAL(i);
             } else {
+                SAVE_SP_AND_PC(fp);
                 if (JSVAL_IS_DOUBLE(rval)) {
                     d = *JSVAL_TO_DOUBLE(rval);
                 } else {
-                    d = js_ValueToNumber(cx, &regs.sp[-1]);
-                    if (JSVAL_IS_NULL(regs.sp[-1]))
+                    d = js_ValueToNumber(cx, &sp[-1]);
+                    if (JSVAL_IS_NULL(sp[-1]))
                         goto error;
-                    JS_ASSERT(JSVAL_IS_NUMBER(regs.sp[-1]) ||
-                              regs.sp[-1] == JSVAL_TRUE);
+                    JS_ASSERT(JSVAL_IS_NUMBER(sp[-1]) || sp[-1] == JSVAL_TRUE);
                 }
 #ifdef HPUX
                 /*
                  * Negation of a zero doesn't produce a negative
                  * zero on HPUX. Perform the operation by bit
                  * twiddling.
                  */
                 JSDOUBLE_HI32(d) ^= JSDOUBLE_HI32_SIGNBIT;
 #else
                 d = -d;
 #endif
-                if (!js_NewNumberInRootedValue(cx, d, &regs.sp[-1]))
+                if (!js_NewNumberInRootedValue(cx, d, &sp[-1]))
                     goto error;
             }
           END_CASE(JSOP_NEG)
 
           BEGIN_CASE(JSOP_POS)
             rval = FETCH_OPND(-1);
             if (!JSVAL_IS_NUMBER(rval)) {
-                d = js_ValueToNumber(cx, &regs.sp[-1]);
-                rval = regs.sp[-1];
+                SAVE_SP_AND_PC(fp);
+                d = js_ValueToNumber(cx, &sp[-1]);
+                rval = sp[-1];
                 if (JSVAL_IS_NULL(rval))
                     goto error;
                 if (rval == JSVAL_TRUE) {
-                    if (!js_NewNumberInRootedValue(cx, d, &regs.sp[-1]))
+                    if (!js_NewNumberInRootedValue(cx, d, &sp[-1]))
                         goto error;
                 } else {
                     JS_ASSERT(JSVAL_IS_NUMBER(rval));
                 }
             }
           END_CASE(JSOP_POS)
 
           BEGIN_CASE(JSOP_NEW)
             /* Get immediate argc and find the constructor function. */
-            argc = GET_ARGC(regs.pc);
-            vp = regs.sp - (2 + argc);
+            argc = GET_ARGC(pc);
+            SAVE_SP_AND_PC(fp);
+            vp = sp - (2 + argc);
             JS_ASSERT(vp >= fp->spbase);
 
             if (!js_InvokeConstructor(cx, vp, argc))
                 goto error;
-            regs.sp = vp + 1;
+            sp = vp + 1;
             LOAD_INTERRUPT_HANDLER(cx);
           END_CASE(JSOP_NEW)
 
           BEGIN_CASE(JSOP_DELNAME)
             LOAD_ATOM(0);
             id = ATOM_TO_JSID(atom);
+
+            SAVE_SP_AND_PC(fp);
             if (!js_FindProperty(cx, id, &obj, &obj2, &prop))
                 goto error;
 
             /* ECMA says to return true if name is undefined or inherited. */
-            PUSH_OPND(JSVAL_TRUE);
+            rval = JSVAL_TRUE;
             if (prop) {
                 OBJ_DROP_PROPERTY(cx, obj2, prop);
-                if (!OBJ_DELETE_PROPERTY(cx, obj, id, &regs.sp[-1]))
+                if (!OBJ_DELETE_PROPERTY(cx, obj, id, &rval))
                     goto error;
             }
+            PUSH_OPND(rval);
           END_CASE(JSOP_DELNAME)
 
           BEGIN_CASE(JSOP_DELPROP)
             LOAD_ATOM(0);
             id = ATOM_TO_JSID(atom);
             PROPERTY_OP(-1, OBJ_DELETE_PROPERTY(cx, obj, id, &rval));
             STORE_OPND(-1, rval);
           END_CASE(JSOP_DELPROP)
 
           BEGIN_CASE(JSOP_DELELEM)
             ELEMENT_OP(-1, OBJ_DELETE_PROPERTY(cx, obj, id, &rval));
-            regs.sp--;
+            sp--;
             STORE_OPND(-1, rval);
           END_CASE(JSOP_DELELEM)
 
           BEGIN_CASE(JSOP_TYPEOFEXPR)
           BEGIN_CASE(JSOP_TYPEOF)
             rval = FETCH_OPND(-1);
+            SAVE_SP_AND_PC(fp);
             type = JS_TypeOfValue(cx, rval);
             atom = rt->atomState.typeAtoms[type];
             STORE_OPND(-1, ATOM_KEY(atom));
           END_CASE(JSOP_TYPEOF)
 
           BEGIN_CASE(JSOP_VOID)
             STORE_OPND(-1, JSVAL_VOID);
           END_CASE(JSOP_VOID)
@@ -3851,90 +3927,95 @@ interrupt:
           BEGIN_CASE(JSOP_DECPROP)
           BEGIN_CASE(JSOP_PROPINC)
           BEGIN_CASE(JSOP_PROPDEC)
             LOAD_ATOM(0);
             id = ATOM_TO_JSID(atom);
             i = -1;
 
           fetch_incop_obj:
+            SAVE_SP_AND_PC(fp);
             FETCH_OBJECT(cx, i, lval, obj);
             if (id == 0)
                 FETCH_ELEMENT_ID(obj, -1, id);
             goto do_incop;
 
           BEGIN_CASE(JSOP_INCNAME)
           BEGIN_CASE(JSOP_DECNAME)
           BEGIN_CASE(JSOP_NAMEINC)
           BEGIN_CASE(JSOP_NAMEDEC)
             LOAD_ATOM(0);
             id = ATOM_TO_JSID(atom);
+
+            SAVE_SP_AND_PC(fp);
             if (!js_FindProperty(cx, id, &obj, &obj2, &prop))
                 goto error;
             if (!prop)
                 goto atom_not_defined;
             OBJ_DROP_PROPERTY(cx, obj2, prop);
 
           do_incop:
           {
             const JSCodeSpec *cs;
             jsval v;
 
             /*
              * We need a root to store the value to leave on the stack until
              * we have done with OBJ_SET_PROPERTY.
              */
             PUSH_OPND(JSVAL_NULL);
-            if (!OBJ_GET_PROPERTY(cx, obj, id, &regs.sp[-1]))
+            SAVE_SP(fp);
+            if (!OBJ_GET_PROPERTY(cx, obj, id, &sp[-1]))
                 goto error;
 
             cs = &js_CodeSpec[op];
             JS_ASSERT(cs->ndefs == 1);
             JS_ASSERT((cs->format & JOF_TMPSLOT_MASK) == JOF_TMPSLOT2);
-            v = regs.sp[-1];
+            v = sp[-1];
             if (JS_LIKELY(CAN_DO_FAST_INC_DEC(v))) {
                 jsval incr;
 
                 incr = (cs->format & JOF_INC) ? 2 : -2;
                 if (cs->format & JOF_POST) {
-                    regs.sp[-1] = v + incr;
+                    sp[-1] = v + incr;
                 } else {
                     v += incr;
-                    regs.sp[-1] = v;
+                    sp[-1] = v;
                 }
                 fp->flags |= JSFRAME_ASSIGNING;
-                ok = OBJ_SET_PROPERTY(cx, obj, id, &regs.sp[-1]);
+                ok = OBJ_SET_PROPERTY(cx, obj, id, &sp[-1]);
                 fp->flags &= ~JSFRAME_ASSIGNING;
                 if (!ok)
                     goto error;
 
                 /*
-                 * We must set regs.sp[-1] to v for both post and pre increments
-                 * as the setter overwrites regs.sp[-1].
+                 * We must set sp[-1] to v for both post and pre increments
+                 * as the setter overwrites sp[-1].
                  */
-                regs.sp[-1] = v;
+                sp[-1] = v;
             } else {
                 /* We need an extra root for the result. */
                 PUSH_OPND(JSVAL_NULL);
-                if (!js_DoIncDec(cx, cs, &regs.sp[-2], &regs.sp[-1]))
+                SAVE_SP(fp);
+                if (!js_DoIncDec(cx, cs, &sp[-2], &sp[-1]))
                     goto error;
                 fp->flags |= JSFRAME_ASSIGNING;
-                ok = OBJ_SET_PROPERTY(cx, obj, id, &regs.sp[-1]);
+                ok = OBJ_SET_PROPERTY(cx, obj, id, &sp[-1]);
                 fp->flags &= ~JSFRAME_ASSIGNING;
                 if (!ok)
                     goto error;
-                regs.sp--;
+                sp--;
             }
 
             if (cs->nuses == 0) {
-                /* regs.sp[-1] already contains the result of name increment. */
+                /* sp[-1] already contains the result of name increment. */
             } else {
-                rtmp = regs.sp[-1];
-                regs.sp -= cs->nuses;
-                regs.sp[-1] = rtmp;
+                rtmp = sp[-1];
+                sp -= cs->nuses;
+                sp[-1] = rtmp;
             }
             len = cs->length;
             DO_NEXT_OP(len);
           }
 
           {
             jsval incr, incr2;
 
@@ -3944,33 +4025,33 @@ interrupt:
           BEGIN_CASE(JSOP_ARGDEC)
             incr = -2; incr2 =  0; goto do_arg_incop;
           BEGIN_CASE(JSOP_INCARG)
             incr =  2; incr2 =  2; goto do_arg_incop;
           BEGIN_CASE(JSOP_ARGINC)
             incr =  2; incr2 =  0;
 
           do_arg_incop:
-            slot = GET_ARGNO(regs.pc);
+            slot = GET_ARGNO(pc);
             JS_ASSERT(slot < fp->fun->nargs);
             METER_SLOT_OP(op, slot);
             vp = fp->argv + slot;
             goto do_int_fast_incop;
 
           BEGIN_CASE(JSOP_DECLOCAL)
             incr = -2; incr2 = -2; goto do_local_incop;
           BEGIN_CASE(JSOP_LOCALDEC)
             incr = -2; incr2 =  0; goto do_local_incop;
           BEGIN_CASE(JSOP_INCLOCAL)
             incr =  2; incr2 =  2; goto do_local_incop;
           BEGIN_CASE(JSOP_LOCALINC)
             incr =  2; incr2 =  0;
 
           do_local_incop:
-            slot = GET_UINT16(regs.pc);
+            slot = GET_UINT16(pc);
             JS_ASSERT(slot < script->depth);
             vp = fp->spbase + slot;
             goto do_int_fast_incop;
 
           BEGIN_CASE(JSOP_DECVAR)
             incr = -2; incr2 = -2; goto do_var_incop;
           BEGIN_CASE(JSOP_VARDEC)
             incr = -2; incr2 =  0; goto do_var_incop;
@@ -3980,29 +4061,30 @@ interrupt:
             incr =  2; incr2 =  0;
 
           /*
            * do_var_incop comes right before do_int_fast_incop as we want to
            * avoid an extra jump for variable cases as var++ is more frequent
            * than arg++ or local++;
            */
           do_var_incop:
-            slot = GET_VARNO(regs.pc);
+            slot = GET_VARNO(pc);
             JS_ASSERT(slot < fp->fun->u.i.nvars);
             METER_SLOT_OP(op, slot);
             vp = fp->vars + slot;
 
           do_int_fast_incop:
             rval = *vp;
             if (JS_LIKELY(CAN_DO_FAST_INC_DEC(rval))) {
                 *vp = rval + incr;
                 PUSH_OPND(rval + incr2);
             } else {
                 PUSH_OPND(rval);
-                if (!js_DoIncDec(cx, &js_CodeSpec[op], &regs.sp[-1], vp))
+                SAVE_SP_AND_PC(fp);
+                if (!js_DoIncDec(cx, &js_CodeSpec[op], &sp[-1], vp))
                     goto error;
             }
             len = JSOP_INCARG_LENGTH;
             JS_ASSERT(len == js_CodeSpec[op].length);
             DO_NEXT_OP(len);
           }
 
 /* NB: This macro doesn't use JS_BEGIN_MACRO/JS_END_MACRO around its body. */
@@ -4024,36 +4106,37 @@ interrupt:
           BEGIN_CASE(JSOP_GVARINC)
             FAST_GLOBAL_INCREMENT_OP(JSOP_NAMEINC,  2,  0);
 
 #undef FAST_GLOBAL_INCREMENT_OP
 
           do_global_incop:
             JS_ASSERT((js_CodeSpec[op].format & JOF_TMPSLOT_MASK) ==
                       JOF_TMPSLOT2);
-            slot = GET_VARNO(regs.pc);
+            slot = GET_VARNO(pc);
             JS_ASSERT(slot < fp->nvars);
             METER_SLOT_OP(op, slot);
             lval = fp->vars[slot];
             if (JSVAL_IS_NULL(lval)) {
                 op = op2;
                 DO_OP();
             }
             slot = JSVAL_TO_INT(lval);
             rval = OBJ_GET_SLOT(cx, fp->varobj, slot);
             if (JS_LIKELY(CAN_DO_FAST_INC_DEC(rval))) {
                 PUSH_OPND(rval + incr2);
                 rval += incr;
             } else {
                 PUSH_OPND(rval);
                 PUSH_OPND(JSVAL_NULL);  /* Extra root */
-                if (!js_DoIncDec(cx, &js_CodeSpec[op], &regs.sp[-2], &regs.sp[-1]))
+                SAVE_SP_AND_PC(fp);
+                if (!js_DoIncDec(cx, &js_CodeSpec[op], &sp[-2], &sp[-1]))
                     goto error;
-                rval = regs.sp[-1];
-                --regs.sp;
+                rval = sp[-1];
+                --sp;
             }
             OBJ_SET_SLOT(cx, fp->varobj, slot, rval);
             len = JSOP_INCGVAR_LENGTH;  /* all gvar incops are same length */
             JS_ASSERT(len == js_CodeSpec[op].length);
             DO_NEXT_OP(len);
           }
 
 #define COMPUTE_THIS(cx, fp, obj)                                             \
@@ -4080,33 +4163,33 @@ interrupt:
             PUSH(JSVAL_NULL);
             len = JSOP_GETTHISPROP_LENGTH;
             goto do_getprop_with_obj;
 
 #undef COMPUTE_THIS
 
           BEGIN_CASE(JSOP_GETARGPROP)
             i = ARGNO_LEN;
-            slot = GET_ARGNO(regs.pc);
+            slot = GET_ARGNO(pc);
             JS_ASSERT(slot < fp->fun->nargs);
             PUSH_OPND(fp->argv[slot]);
             len = JSOP_GETARGPROP_LENGTH;
             goto do_getprop_body;
 
           BEGIN_CASE(JSOP_GETVARPROP)
             i = VARNO_LEN;
-            slot = GET_VARNO(regs.pc);
+            slot = GET_VARNO(pc);
             JS_ASSERT(slot < fp->fun->u.i.nvars);
             PUSH_OPND(fp->vars[slot]);
             len = JSOP_GETVARPROP_LENGTH;
             goto do_getprop_body;
 
           BEGIN_CASE(JSOP_GETLOCALPROP)
             i = UINT16_LEN;
-            slot = GET_UINT16(regs.pc);
+            slot = GET_UINT16(pc);
             JS_ASSERT(slot < script->depth);
             PUSH_OPND(fp->spbase[slot]);
             len = JSOP_GETLOCALPROP_LENGTH;
             goto do_getprop_body;
 
           BEGIN_CASE(JSOP_GETPROP)
           BEGIN_CASE(JSOP_GETXPROP)
             i = 0;
@@ -4118,71 +4201,75 @@ interrupt:
           do_getprop_with_lval:
             VALUE_TO_OBJECT(cx, -1, lval, obj);
 
           do_getprop_with_obj:
             do {
                 JSPropCacheEntry *entry;
 
                 if (JS_LIKELY(obj->map->ops->getProperty == js_GetProperty)) {
-                    PROPERTY_CACHE_TEST(cx, regs.pc, obj, obj2, entry, atom);
+                    PROPERTY_CACHE_TEST(cx, pc, obj, obj2, entry, atom);
                     if (!atom) {
                         ASSERT_VALID_PROPERTY_CACHE_HIT(i, obj, obj2, entry);
                         if (PCVAL_IS_OBJECT(entry->vword)) {
                             rval = PCVAL_OBJECT_TO_JSVAL(entry->vword);
                         } else if (PCVAL_IS_SLOT(entry->vword)) {
                             slot = PCVAL_TO_SLOT(entry->vword);
                             JS_ASSERT(slot < obj2->map->freeslot);
                             rval = LOCKED_OBJ_GET_SLOT(obj2, slot);
                         } else {
                             JS_ASSERT(PCVAL_IS_SPROP(entry->vword));
                             sprop = PCVAL_TO_SPROP(entry->vword);
+                            SAVE_SP_AND_PC(fp);
                             NATIVE_GET(cx, obj, obj2, sprop, &rval);
                         }
                         JS_UNLOCK_OBJ(cx, obj2);
                         break;
                     }
                 } else {
                     entry = NULL;
                     if (i < 0)
                         atom = rt->atomState.lengthAtom;
                     else
                         LOAD_ATOM(i);
                 }
                 id = ATOM_TO_JSID(atom);
+                SAVE_SP_AND_PC(fp);
                 if (entry
                     ? !js_GetPropertyHelper(cx, obj, id, &rval, &entry)
                     : !OBJ_GET_PROPERTY(cx, obj, id, &rval)) {
                     goto error;
                 }
             } while (0);
 
             STORE_OPND(-1, rval);
           END_VARLEN_CASE
 
           BEGIN_CASE(JSOP_LENGTH)
             lval = FETCH_OPND(-1);
             if (JSVAL_IS_STRING(lval)) {
                 str = JSVAL_TO_STRING(lval);
-                regs.sp[-1] = INT_TO_JSVAL(JSSTRING_LENGTH(str));
+                sp[-1] = INT_TO_JSVAL(JSSTRING_LENGTH(str));
             } else if (!JSVAL_IS_PRIMITIVE(lval) &&
                        (obj = JSVAL_TO_OBJECT(lval), OBJ_IS_ARRAY(cx, obj))) {
                 jsuint length;
 
                 /*
                  * We know that the array is created with only its 'length'
                  * private data in a fixed slot at JSSLOT_ARRAY_LENGTH. See
                  * also JSOP_ARRAYPUSH, far below.
                  */
                 length = obj->fslots[JSSLOT_ARRAY_LENGTH];
                 if (length <= JSVAL_INT_MAX) {
-                    regs.sp[-1] = INT_TO_JSVAL(length);
-                } else if (!js_NewDoubleInRootedValue(cx, (jsdouble) length,
-                                                      &regs.sp[-1])) {
-                    goto error;
+                    sp[-1] = INT_TO_JSVAL(length);
+                } else {
+                    SAVE_SP_AND_PC(fp);
+                    if (!js_NewDoubleInRootedValue(cx, (jsdouble) length,
+                                                   &sp[-1]))
+                        goto error;
                 }
             } else {
                 i = -1;
                 len = JSOP_LENGTH_LENGTH;
                 goto do_getprop_with_lval;
             }
           END_CASE(JSOP_LENGTH)
 
@@ -4190,16 +4277,18 @@ interrupt:
           {
             JSObject *aobj;
             JSPropCacheEntry *entry;
 
             lval = FETCH_OPND(-1);
             if (!JSVAL_IS_PRIMITIVE(lval)) {
                 obj = JSVAL_TO_OBJECT(lval);
             } else {
+                SAVE_SP_AND_PC(fp);
+
                 if (JSVAL_IS_STRING(lval)) {
                     i = JSProto_String;
                 } else if (JSVAL_IS_NUMBER(lval)) {
                     i = JSProto_Number;
                 } else if (JSVAL_IS_BOOLEAN(lval)) {
                     i = JSProto_Boolean;
                 } else {
                     JS_ASSERT(JSVAL_IS_NULL(lval) || JSVAL_IS_VOID(lval));
@@ -4208,17 +4297,17 @@ interrupt:
                 }
 
                 if (!js_GetClassPrototype(cx, NULL, INT_TO_JSID(i), &obj))
                     goto error;
             }
 
             aobj = OBJ_IS_DENSE_ARRAY(cx, obj) ? OBJ_GET_PROTO(cx, obj) : obj;
             if (JS_LIKELY(aobj->map->ops->getProperty == js_GetProperty)) {
-                PROPERTY_CACHE_TEST(cx, regs.pc, aobj, obj2, entry, atom);
+                PROPERTY_CACHE_TEST(cx, pc, aobj, obj2, entry, atom);
                 if (!atom) {
                     ASSERT_VALID_PROPERTY_CACHE_HIT(0, aobj, obj2, entry);
                     if (PCVAL_IS_OBJECT(entry->vword)) {
                         rval = PCVAL_OBJECT_TO_JSVAL(entry->vword);
                     } else if (PCVAL_IS_SLOT(entry->vword)) {
                         slot = PCVAL_TO_SLOT(entry->vword);
                         JS_ASSERT(slot < obj2->map->freeslot);
                         rval = LOCKED_OBJ_GET_SLOT(obj2, slot);
@@ -4238,16 +4327,17 @@ interrupt:
             }
 
             /*
              * Cache miss: use the immediate atom that was loaded for us under
              * PROPERTY_CACHE_TEST.
              */
             id = ATOM_TO_JSID(atom);
             PUSH(JSVAL_NULL);
+            SAVE_SP_AND_PC(fp);
             if (!JSVAL_IS_PRIMITIVE(lval)) {
 #if JS_HAS_XML_SUPPORT
                 /* Special-case XML object method lookup, per ECMA-357. */
                 if (OBJECT_IS_XML(cx, obj)) {
                     JSXMLObjectOps *ops;
 
                     ops = (JSXMLObjectOps *) obj->map->ops;
                     obj = ops->getMethod(cx, obj, id, &rval);
@@ -4273,25 +4363,26 @@ interrupt:
           end_callprop:
             /* Wrap primitive lval in object clothing if necessary. */
             if (JSVAL_IS_PRIMITIVE(lval)) {
                 /* FIXME: https://bugzilla.mozilla.org/show_bug.cgi?id=412571 */
                 if (!VALUE_IS_FUNCTION(cx, rval) ||
                     (obj = JSVAL_TO_OBJECT(rval),
                      fun = GET_FUNCTION_PRIVATE(cx, obj),
                      !PRIMITIVE_THIS_TEST(fun, lval))) {
-                    if (!js_PrimitiveToObject(cx, &regs.sp[-1]))
+                    if (!js_PrimitiveToObject(cx, &sp[-1]))
                         goto error;
                 }
             }
 #if JS_HAS_NO_SUCH_METHOD
             if (JS_UNLIKELY(rval == JSVAL_VOID)) {
                 LOAD_ATOM(0);
-                regs.sp[-2] = ATOM_KEY(atom);
-                if (!js_OnUnknownMethod(cx, regs.sp - 2))
+                sp[-2] = ATOM_KEY(atom);
+                SAVE_SP_AND_PC(fp);
+                if (!js_OnUnknownMethod(cx, sp - 2))
                     goto error;
             }
 #endif
           }
           END_CASE(JSOP_CALLPROP)
 
           BEGIN_CASE(JSOP_SETNAME)
           BEGIN_CASE(JSOP_SETPROP)
@@ -4323,21 +4414,20 @@ interrupt:
                      * of property additions. And second:
                      *
                      *   o.p = x;
                      *
                      * in a frequently executed method or loop body, where p
                      * will (possibly after the first iteration) always exist
                      * in native object o.
                      */
-                    entry = &cache->table[PROPERTY_CACHE_HASH_PC(regs.pc,
-                                                                 kshape)];
+                    entry = &cache->table[PROPERTY_CACHE_HASH_PC(pc, kshape)];
                     PCMETER(cache->tests++);
                     PCMETER(cache->settests++);
-                    if (entry->kpc == regs.pc && entry->kshape == kshape) {
+                    if (entry->kpc == pc && entry->kshape == kshape) {
                         JSScope *scope;
 
                         JS_LOCK_OBJ(cx, obj);
                         scope = OBJ_SCOPE(obj);
                         if (scope->shape == kshape) {
                             JS_ASSERT(PCVAL_IS_SPROP(entry->vword));
                             sprop = PCVAL_TO_SPROP(entry->vword);
                             JS_ASSERT(!(sprop->attrs & JSPROP_READONLY));
@@ -4451,17 +4541,17 @@ interrupt:
 
                             PCMETER(cache->setpcmisses++);
                             atom = NULL;
                         }
 
                         JS_UNLOCK_OBJ(cx, obj);
                     }
 
-                    atom = js_FullTestPropertyCache(cx, regs.pc, &obj, &obj2,
+                    atom = js_FullTestPropertyCache(cx, pc, &obj, &obj2,
                                                     &entry);
                     if (atom) {
                         PCMETER(cache->misses++);
                         PCMETER(cache->setmisses++);
                     } else {
                         ASSERT_VALID_PROPERTY_CACHE_HIT(0, obj, obj2, entry);
                         if (obj == obj2) {
                             if (PCVAL_IS_SLOT(entry->vword)) {
@@ -4479,29 +4569,31 @@ interrupt:
                         if (obj == obj2 && !PCVAL_IS_OBJECT(entry->vword))
                             break;
                     }
                 }
 
                 if (!atom)
                     LOAD_ATOM(0);
                 id = ATOM_TO_JSID(atom);
+                SAVE_SP_AND_PC(fp);
                 if (entry
                     ? !js_SetPropertyHelper(cx, obj, id, &rval, &entry)
                     : !OBJ_SET_PROPERTY(cx, obj, id, &rval)) {
                     goto error;
                 }
             } while (0);
 
-            regs.sp--;
+            sp--;
             STORE_OPND(-1, rval);
           END_CASE(JSOP_SETPROP)
 
           BEGIN_CASE(JSOP_GETELEM)
             /* Open-coded ELEMENT_OP optimized for strings and dense arrays. */
+            SAVE_SP_AND_PC(fp);
             lval = FETCH_OPND(-2);
             rval = FETCH_OPND(-1);
             if (JSVAL_IS_STRING(lval) && JSVAL_IS_INT(rval)) {
                 str = JSVAL_TO_STRING(lval);
                 i = JSVAL_TO_INT(rval);
                 if ((size_t)i < JSSTRING_LENGTH(str)) {
                     str = js_GetUnitString(cx, str, (size_t)i);
                     if (!str)
@@ -4529,42 +4621,44 @@ interrupt:
             } else {
                 if (!js_InternNonIntElementId(cx, obj, rval, &id))
                     goto error;
             }
 
             if (!OBJ_GET_PROPERTY(cx, obj, id, &rval))
                 goto error;
           end_getelem:
-            regs.sp--;
+            sp--;
             STORE_OPND(-1, rval);
           END_CASE(JSOP_GETELEM)
 
           BEGIN_CASE(JSOP_CALLELEM)
             /*
              * FIXME: JSOP_CALLELEM should call getMethod on XML objects as
              * CALLPROP does. See bug 362910.
              */
             ELEMENT_OP(-1, OBJ_GET_PROPERTY(cx, obj, id, &rval));
 #if JS_HAS_NO_SUCH_METHOD
             if (JS_UNLIKELY(rval == JSVAL_VOID)) {
-                regs.sp[-2] = regs.sp[-1];
-                regs.sp[-1] = OBJECT_TO_JSVAL(obj);
-                if (!js_OnUnknownMethod(cx, regs.sp - 2))
+                sp[-2] = sp[-1];
+                sp[-1] = OBJECT_TO_JSVAL(obj);
+                SAVE_SP_AND_PC(fp);
+                if (!js_OnUnknownMethod(cx, sp - 2))
                     goto error;
             } else
 #endif
             {
                 STORE_OPND(-2, rval);
                 STORE_OPND(-1, OBJECT_TO_JSVAL(obj));
             }
           END_CASE(JSOP_CALLELEM)
 
           BEGIN_CASE(JSOP_SETELEM)
             rval = FETCH_OPND(-1);
+            SAVE_SP_AND_PC(fp);
             FETCH_OBJECT(cx, -3, lval, obj);
             FETCH_ELEMENT_ID(obj, -2, id);
             if (OBJ_IS_DENSE_ARRAY(cx, obj) && JSID_IS_INT(id)) {
                 jsuint length;
 
                 length = ARRAY_DENSE_LENGTH(obj);
                 i = JSID_TO_INT(id);
                 if ((jsuint)i < length) {
@@ -4575,103 +4669,106 @@ interrupt:
                     }
                     obj->dslots[i] = rval;
                     goto end_setelem;
                 }
             }
             if (!OBJ_SET_PROPERTY(cx, obj, id, &rval))
                 goto error;
         end_setelem:
-            regs.sp -= 2;
+            sp -= 2;
             STORE_OPND(-1, rval);
           END_CASE(JSOP_SETELEM)
 
           BEGIN_CASE(JSOP_ENUMELEM)
             /* Funky: the value to set is under the [obj, id] pair. */
             rval = FETCH_OPND(-3);
+            SAVE_SP_AND_PC(fp);
             FETCH_OBJECT(cx, -2, lval, obj);
             FETCH_ELEMENT_ID(obj, -1, id);
             if (!OBJ_SET_PROPERTY(cx, obj, id, &rval))
                 goto error;
-            regs.sp -= 3;
+            sp -= 3;
           END_CASE(JSOP_ENUMELEM)
 
           BEGIN_CASE(JSOP_CALL)
           BEGIN_CASE(JSOP_EVAL)
-            argc = GET_ARGC(regs.pc);
-            vp = regs.sp - (argc + 2);
+            argc = GET_ARGC(pc);
+            vp = sp - (argc + 2);
             lval = *vp;
+            SAVE_SP_AND_PC(fp);
             if (VALUE_IS_FUNCTION(cx, lval)) {
                 obj = JSVAL_TO_OBJECT(lval);
                 fun = GET_FUNCTION_PRIVATE(cx, obj);
 
                 if (FUN_INTERPRETED(fun)) {
-                    uintN nframeslots, nvars, missing;
+                    uintN nframeslots, nvars, nslots, missing;
                     JSArena *a;
-                    jsuword nbytes;
+                    jsuword avail, nbytes;
                     void *newmark;
-                    jsval *newsp;
+                    jsval *newsp, *rvp;
+                    JSBool overflow;
                     JSInlineFrame *newifp;
                     JSInterpreterHook hook;
 
                     /* Compute the total number of stack slots needed by fun. */
                     nframeslots = JS_HOWMANY(sizeof(JSInlineFrame),
                                              sizeof(jsval));
                     nvars = fun->u.i.nvars;
                     script = fun->u.i.script;
                     atoms = script->atomMap.vector;
-                    nbytes = (nframeslots + nvars + script->depth) *
-                             sizeof(jsval);
+                    nslots = nframeslots + nvars + script->depth;
 
                     /* Allocate missing expected args adjacent to actuals. */
+                    missing = (fun->nargs > argc) ? fun->nargs - argc : 0;
                     a = cx->stackPool.current;
-                    newmark = (void *) a->avail;
-                    if (fun->nargs <= argc) {
-                        missing = 0;
-                    } else {
-                        newsp = vp + 2 + fun->nargs;
-                        JS_ASSERT(newsp > regs.sp);
-                        if ((jsuword) newsp <= a->limit) {
-                            if ((jsuword) newsp > a->avail)
-                                a->avail = (jsuword) newsp;
-                            do {
-                                *--newsp = JSVAL_VOID;
-                            } while (newsp != regs.sp);
-                            missing = 0;
-                        } else {
-                            missing = fun->nargs - argc;
-                            nbytes += (2 + fun->nargs) * sizeof(jsval);
-                        }
+                    avail = a->avail;
+                    newmark = (void *) avail;
+                    if (missing) {
+                        newsp = sp + missing;
+                        overflow = (jsuword) newsp > a->limit;
+                        if (overflow)
+                            nslots += 2 + argc + missing;
+                        else if ((jsuword) newsp > avail)
+                            avail = a->avail = (jsuword) newsp;
                     }
+#ifdef __GNUC__
+                    else overflow = JS_FALSE; /* suppress bogus gcc warnings */
+#endif
 
                     /* Allocate the inline frame with its vars and operands. */
-                    if (a->avail + nbytes <= a->limit) {
-                        newsp = (jsval *) a->avail;
-                        a->avail += nbytes;
-                        JS_ASSERT(missing == 0);
+                    newsp = (jsval *) avail;
+                    nbytes = nslots * sizeof(jsval);
+                    avail += nbytes;
+                    if (avail <= a->limit) {
+                        a->avail = avail;
                     } else {
                         JS_ARENA_ALLOCATE_CAST(newsp, jsval *, &cx->stackPool,
                                                nbytes);
                         if (!newsp) {
                             js_ReportOutOfScriptQuota(cx);
                             goto bad_inline_call;
                         }
-
-                        /*
-                         * Move args if missing overflow arena a, then push
-                         * any missing args.
-                         */
-                        if (missing) {
+                    }
+
+                    /*
+                     * Move args if missing overflow arena a, then push any
+                     * missing args.
+                     */
+                    rvp = vp;
+                    if (missing) {
+                        if (overflow) {
                             memcpy(newsp, vp, (2 + argc) * sizeof(jsval));
                             vp = newsp;
-                            newsp = vp + 2 + argc;
-                            do {
-                                *newsp++ = JSVAL_VOID;
-                            } while (--missing != 0);
+                            sp = vp + 2 + argc;
+                            newsp = sp + missing;
                         }
+                        do {
+                            PUSH(JSVAL_VOID);
+                        } while (--missing != 0);
                     }
 
                     /* Claim space for the stack frame and initialize it. */
                     newifp = (JSInlineFrame *) newsp;
                     newsp += nframeslots;
                     newifp->frame.callobj = NULL;
                     newifp->frame.argsobj = NULL;
                     newifp->frame.varobj = NULL;
@@ -4691,33 +4788,35 @@ interrupt:
                     newifp->frame.flags = 0;
                     newifp->frame.dormantNext = NULL;
                     newifp->frame.xmlNamespace = NULL;
                     newifp->frame.blockChain = NULL;
 #ifdef DEBUG
                     newifp->frame.pcDisabledSave =
                         JS_PROPERTY_CACHE(cx).disabled;
 #endif
+                    newifp->rvp = rvp;
                     newifp->mark = newmark;
 
                     /* Compute the 'this' parameter now that argv is set. */
                     JS_ASSERT(!JSFUN_BOUND_METHOD_TEST(fun->flags));
                     JS_ASSERT(JSVAL_IS_OBJECT(vp[1]));
                     newifp->frame.thisp = (JSObject *)vp[1];
 
                     /* Push void to initialize local variables. */
+                    sp = newsp;
                     while (nvars--)
-                        *newsp++ = JSVAL_VOID;
-
-                    newifp->frame.regs = NULL;
-                    newifp->frame.spbase = NULL;
+                        PUSH(JSVAL_VOID);
+                    newifp->frame.spbase = sp;
+                    SAVE_SP(&newifp->frame);
 
                     /* Call the debugger hook if present. */
                     hook = cx->debugHooks->callHook;
                     if (hook) {
+                        newifp->frame.pc = NULL;
                         newifp->hookData = hook(cx, &newifp->frame, JS_TRUE, 0,
                                                 cx->debugHooks->callHookData);
                         LOAD_INTERRUPT_HANDLER(cx);
                     } else {
                         newifp->hookData = NULL;
                     }
 
                     /* Scope with a call object parented by callee's parent. */
@@ -4730,42 +4829,38 @@ interrupt:
                     newifp->callerVersion = (JSVersion) cx->version;
                     if (JS_LIKELY(cx->version == currentVersion)) {
                         currentVersion = (JSVersion) script->version;
                         if (currentVersion != cx->version)
                             js_SetVersion(cx, currentVersion);
                     }
 
                     /* Push the frame and set interpreter registers. */
-                    newifp->callerRegs = regs;
-                    fp->regs = &newifp->callerRegs;
-                    regs.sp = newifp->frame.spbase = newsp;
-                    regs.pc = script->code;
-                    newifp->frame.regs = &regs;
                     cx->fp = fp = &newifp->frame;
-
+                    pc = script->code;
                     inlineCallCount++;
                     JS_RUNTIME_METER(rt, inlineCalls);
 
 #ifdef INCLUDE_MOZILLA_DTRACE
                     /* DTrace function entry, inlines */
                     if (JAVASCRIPT_FUNCTION_ENTRY_ENABLED())
                         jsdtrace_function_entry(cx, fp, fun);
                     if (JAVASCRIPT_FUNCTION_INFO_ENABLED())
                         jsdtrace_function_info(cx, fp, fp->down, fun);
                     if (JAVASCRIPT_FUNCTION_ARGS_ENABLED())
                         jsdtrace_function_args(cx, fp, fun);
 #endif
 
                     /* Load first op and dispatch it (safe since JSOP_STOP). */
-                    op = (JSOp) *regs.pc;
+                    op = (JSOp) *pc;
                     DO_OP();
 
                   bad_inline_call:
-                    JS_ASSERT(fp->regs == &regs);
+                    RESTORE_SP(fp);
+                    JS_ASSERT(fp->pc == pc);
                     script = fp->script;
                     atoms = script->atomMap.vector;
                     js_FreeRawStack(cx, newmark);
                     goto error;
                 }
 
 #ifdef INCLUDE_MOZILLA_DTRACE
                 /* DTrace function entry, non-inlines */
@@ -4784,54 +4879,55 @@ interrupt:
                     if (argc < fun->u.n.minargs) {
                         uintN nargs;
 
                         /*
                          * If we can't fit missing args and local roots in
                          * this frame's operand stack, take the slow path.
                          */
                         nargs = fun->u.n.minargs - argc;
-                        if (regs.sp + nargs > fp->spbase + script->depth)
+                        if (sp + nargs > fp->spbase + script->depth)
                             goto do_invoke;
                         do {
                             PUSH(JSVAL_VOID);
                         } while (--nargs != 0);
+                        SAVE_SP(fp);
                     }
 
                     JS_ASSERT(JSVAL_IS_OBJECT(vp[1]) ||
                               PRIMITIVE_THIS_TEST(fun, vp[1]));
 
                     ok = ((JSFastNative) fun->u.n.native)(cx, argc, vp);
 #ifdef INCLUDE_MOZILLA_DTRACE
                     if (VALUE_IS_FUNCTION(cx, lval)) {
                         if (JAVASCRIPT_FUNCTION_RVAL_ENABLED())
                             jsdtrace_function_rval(cx, fp, fun);
                         if (JAVASCRIPT_FUNCTION_RETURN_ENABLED())
                             jsdtrace_function_return(cx, fp, fun);
                     }
 #endif
                     if (!ok)
                         goto error;
-                    regs.sp = vp + 1;
+                    sp = vp + 1;
                     goto end_call;
                 }
             }
 
           do_invoke:
             ok = js_Invoke(cx, argc, vp, 0);
 #ifdef INCLUDE_MOZILLA_DTRACE
             /* DTrace function return, non-inlines */
             if (VALUE_IS_FUNCTION(cx, lval)) {
                 if (JAVASCRIPT_FUNCTION_RVAL_ENABLED())
                     jsdtrace_function_rval(cx, fp, fun);
                 if (JAVASCRIPT_FUNCTION_RETURN_ENABLED())
                     jsdtrace_function_return(cx, fp, fun);
             }
 #endif
-            regs.sp = vp + 1;
+            sp = vp + 1;
             LOAD_INTERRUPT_HANDLER(cx);
             if (!ok)
                 goto error;
             JS_RUNTIME_METER(rt, nonInlineCalls);
 
           end_call:
 #if JS_HAS_LVALUE_RETURN
             if (cx->rval2set) {
@@ -4847,29 +4943,30 @@ interrupt:
                  * ECMA "reference type", which can be used on the right- or
                  * left-hand side of assignment ops.  Note well: only native
                  * methods can return reference types.  See JSOP_SETCALL just
                  * below for the left-hand-side case.
                  */
                 PUSH_OPND(cx->rval2);
                 ELEMENT_OP(-1, OBJ_GET_PROPERTY(cx, obj, id, &rval));
 
-                regs.sp--;
+                sp--;
                 STORE_OPND(-1, rval);
                 cx->rval2set = JS_FALSE;
             }
 #endif /* JS_HAS_LVALUE_RETURN */
           END_CASE(JSOP_CALL)
 
 #if JS_HAS_LVALUE_RETURN
           BEGIN_CASE(JSOP_SETCALL)
-            argc = GET_ARGC(regs.pc);
-            vp = regs.sp - argc - 2;
+            argc = GET_ARGC(pc);
+            SAVE_SP_AND_PC(fp);
+            vp = sp - argc - 2;
             ok = js_Invoke(cx, argc, vp, 0);
-            regs.sp = vp + 1;
+            sp = vp + 1;
             LOAD_INTERRUPT_HANDLER(cx);
             if (!ok)
                 goto error;
             if (!cx->rval2set) {
                 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                                      JSMSG_BAD_LEFTSIDE_OF_ASS);
                 goto error;
             }
@@ -4880,17 +4977,17 @@ interrupt:
 
           BEGIN_CASE(JSOP_NAME)
           BEGIN_CASE(JSOP_CALLNAME)
           {
             JSPropCacheEntry *entry;
 
             obj = fp->scopeChain;
             if (JS_LIKELY(OBJ_IS_NATIVE(obj))) {
-                PROPERTY_CACHE_TEST(cx, regs.pc, obj, obj2, entry, atom);
+                PROPERTY_CACHE_TEST(cx, pc, obj, obj2, entry, atom);
                 if (!atom) {
                     ASSERT_VALID_PROPERTY_CACHE_HIT(0, obj, obj2, entry);
                     if (PCVAL_IS_OBJECT(entry->vword)) {
                         rval = PCVAL_OBJECT_TO_JSVAL(entry->vword);
                         JS_UNLOCK_OBJ(cx, obj2);
                         goto do_push_rval;
                     }
 
@@ -4907,23 +5004,24 @@ interrupt:
                     goto do_native_get;
                 }
             } else {
                 entry = NULL;
                 LOAD_ATOM(0);
             }
 
             id = ATOM_TO_JSID(atom);
+            SAVE_SP_AND_PC(fp);
             if (js_FindPropertyHelper(cx, id, &obj, &obj2, &prop, &entry) < 0)
                 goto error;
             if (!prop) {
                 /* Kludge to allow (typeof foo == "undefined") tests. */
                 len = JSOP_NAME_LENGTH;
                 endpc = script->code + script->length;
-                for (pc2 = regs.pc + len; pc2 < endpc; pc2++) {
+                for (pc2 = pc + len; pc2 < endpc; pc2++) {
                     op2 = (JSOp)*pc2;
                     if (op2 == JSOP_TYPEOF) {
                         PUSH_OPND(JSVAL_VOID);
                         DO_NEXT_OP(len);
                     }
                     if (op2 != JSOP_GROUP)
                         break;
                 }
@@ -4946,45 +5044,45 @@ interrupt:
           do_push_rval:
             PUSH_OPND(rval);
             if (op == JSOP_CALLNAME)
                 PUSH_OPND(OBJECT_TO_JSVAL(obj));
           }
           END_CASE(JSOP_NAME)
 
           BEGIN_CASE(JSOP_UINT16)
-            i = (jsint) GET_UINT16(regs.pc);
+            i = (jsint) GET_UINT16(pc);
             rval = INT_TO_JSVAL(i);
             PUSH_OPND(rval);
           END_CASE(JSOP_UINT16)
 
           BEGIN_CASE(JSOP_UINT24)
-            i = (jsint) GET_UINT24(regs.pc);
+            i = (jsint) GET_UINT24(pc);
             rval = INT_TO_JSVAL(i);
             PUSH_OPND(rval);
           END_CASE(JSOP_UINT24)
 
           BEGIN_CASE(JSOP_INT8)
-            i = GET_INT8(regs.pc);
+            i = GET_INT8(pc);
             rval = INT_TO_JSVAL(i);
             PUSH_OPND(rval);
           END_CASE(JSOP_INT8)
 
           BEGIN_CASE(JSOP_INT32)
-            i = GET_INT32(regs.pc);
+            i = GET_INT32(pc);
             rval = INT_TO_JSVAL(i);
             PUSH_OPND(rval);
           END_CASE(JSOP_INT32)
 
           BEGIN_CASE(JSOP_INDEXBASE)
             /*
              * Here atoms can exceed script->atomMap.length as we use atoms
              * as a segment register for object literals as well.
              */
-            atoms += GET_INDEXBASE(regs.pc);
+            atoms += GET_INDEXBASE(pc);
           END_CASE(JSOP_INDEXBASE)
 
           BEGIN_CASE(JSOP_INDEXBASE1)
           BEGIN_CASE(JSOP_INDEXBASE2)
           BEGIN_CASE(JSOP_INDEXBASE3)
             atoms += (op - JSOP_INDEXBASE1 + 1) << 16;
           END_CASE(JSOP_INDEXBASE3)
 
@@ -5065,16 +5163,25 @@ interrupt:
 
             if (JSVAL_IS_NULL(rval)) {
                 /* Compute the current global object in obj2. */
                 obj2 = fp->scopeChain;
                 while ((parent = OBJ_GET_PARENT(cx, obj2)) != NULL)
                     obj2 = parent;
 
                 /*
+                 * We must home sp here, because either js_CloneRegExpObject
+                 * or JS_SetReservedSlot could nest a last-ditch GC.  We home
+                 * pc as well, in case js_CloneRegExpObject has to lookup the
+                 * "RegExp" class in the global object, which could entail a
+                 * JSNewResolveOp call.
+                 */
+                SAVE_SP_AND_PC(fp);
+
+                /*
                  * If obj's parent is not obj2, we must clone obj so that it
                  * has the right parent, and therefore, the right prototype.
                  *
                  * Yes, this means we assume that the correct RegExp.prototype
                  * to which regexp instances (including literals) delegate can
                  * be distinguished solely by the instance's parent, which was
                  * set to the parent of the RegExp constructor function object
                  * when the instance was created.  In other words,
@@ -5130,17 +5237,17 @@ interrupt:
             PUSH_OPND(JSVAL_FALSE);
           END_CASE(JSOP_FALSE)
 
           BEGIN_CASE(JSOP_TRUE)
             PUSH_OPND(JSVAL_TRUE);
           END_CASE(JSOP_TRUE)
 
           BEGIN_CASE(JSOP_TABLESWITCH)
-            pc2 = regs.pc;
+            pc2 = pc;
             len = GET_JUMP_OFFSET(pc2);
 
             /*
              * ECMAv2+ forbids conversion of discriminant, so we will skip to
              * the default case if the discriminant isn't already an int jsval.
              * (This opcode is emitted only for dense jsint-domain switches.)
              */
             rval = POP_OPND();
@@ -5158,17 +5265,17 @@ interrupt:
                 pc2 += JUMP_OFFSET_LEN + JUMP_OFFSET_LEN * i;
                 off = (jsint) GET_JUMP_OFFSET(pc2);
                 if (off)
                     len = off;
             }
           END_VARLEN_CASE
 
           BEGIN_CASE(JSOP_TABLESWITCHX)
-            pc2 = regs.pc;
+            pc2 = pc;
             len = GET_JUMPX_OFFSET(pc2);
 
             /*
              * ECMAv2+ forbids conversion of discriminant, so we will skip to
              * the default case if the discriminant isn't already an int jsval.
              * (This opcode is emitted only for dense jsint-domain switches.)
              */
             rval = POP_OPND();
@@ -5198,17 +5305,17 @@ interrupt:
             off = JUMP_OFFSET_LEN;
 
           do_lookup_switch:
             /*
              * JSOP_LOOKUPSWITCH and JSOP_LOOKUPSWITCHX are never used if
              * any atom index in it would exceed 64K limit.
              */
             JS_ASSERT(atoms == script->atomMap.vector);
-            pc2 = regs.pc;
+            pc2 = pc;
             lval = POP_OPND();
 
             if (!JSVAL_IS_NUMBER(lval) &&
                 !JSVAL_IS_STRING(lval) &&
                 !JSVAL_IS_BOOLEAN(lval)) {
                 goto end_lookup_switch;
             }
 
@@ -5223,17 +5330,17 @@ interrupt:
         atom = atoms[GET_INDEX(pc2)];                                         \
         rval = ATOM_KEY(atom);                                                \
         MATCH_CODE                                                            \
         pc2 += INDEX_LEN;                                                     \
         if (match)                                                            \
             break;                                                            \
         pc2 += off;                                                           \
         if (--npairs == 0) {                                                  \
-            pc2 = regs.pc;                                                    \
+            pc2 = pc;                                                         \
             break;                                                            \
         }                                                                     \
     }
             if (JSVAL_IS_STRING(lval)) {
                 str = JSVAL_TO_STRING(lval);
                 SEARCH_PAIRS(
                     match = (JSVAL_IS_STRING(rval) &&
                              ((str2 = JSVAL_TO_STRING(rval)) == str ||
@@ -5258,16 +5365,17 @@ interrupt:
                   : GET_JUMPX_OFFSET(pc2);
           END_VARLEN_CASE
 
           EMPTY_CASE(JSOP_CONDSWITCH)
 
 #if JS_HAS_EXPORT_IMPORT
           BEGIN_CASE(JSOP_EXPORTALL)
             obj = fp->varobj;
+            SAVE_SP_AND_PC(fp);
             ida = JS_Enumerate(cx, obj);
             if (!ida)
                 goto error;
             ok = JS_TRUE;
             for (i = 0; i != ida->length; i++) {
                 id = ida->vector[i];
                 ok = OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop);
                 if (!ok)
@@ -5288,16 +5396,17 @@ interrupt:
             if (!ok)
                 goto error;
           END_CASE(JSOP_EXPORTALL)
 
           BEGIN_CASE(JSOP_EXPORTNAME)
             LOAD_ATOM(0);
             id = ATOM_TO_JSID(atom);
             obj = fp->varobj;
+            SAVE_SP_AND_PC(fp);
             if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop))
                 goto error;
             if (!prop) {
                 if (!OBJ_DEFINE_PROPERTY(cx, obj, id, JSVAL_VOID,
                                          JS_PropertyStub, JS_PropertyStub,
                                          JSPROP_EXPORTED, NULL)) {
                     goto error;
                 }
@@ -5311,35 +5420,36 @@ interrupt:
                 if (!ok)
                     goto error;
             }
           END_CASE(JSOP_EXPORTNAME)
 
           BEGIN_CASE(JSOP_IMPORTALL)
             id = (jsid) JSVAL_VOID;
             PROPERTY_OP(-1, js_ImportProperty(cx, obj, id));
-            regs.sp--;
+            sp--;
           END_CASE(JSOP_IMPORTALL)
 
           BEGIN_CASE(JSOP_IMPORTPROP)
             /* Get an immediate atom naming the property. */
             LOAD_ATOM(0);
             id = ATOM_TO_JSID(atom);
             PROPERTY_OP(-1, js_ImportProperty(cx, obj, id));
-            regs.sp--;
+            sp--;
           END_CASE(JSOP_IMPORTPROP)
 
           BEGIN_CASE(JSOP_IMPORTELEM)
             ELEMENT_OP(-1, js_ImportProperty(cx, obj, id));
-            regs.sp -= 2;
+            sp -= 2;
           END_CASE(JSOP_IMPORTELEM)
 #endif /* JS_HAS_EXPORT_IMPORT */
 
           BEGIN_CASE(JSOP_TRAP)
-            switch (JS_HandleTrap(cx, script, regs.pc, &rval)) {
+            SAVE_SP_AND_PC(fp);
+            switch (JS_HandleTrap(cx, script, pc, &rval)) {
               case JSTRAP_ERROR:
                 goto error;
               case JSTRAP_CONTINUE:
                 JS_ASSERT(JSVAL_IS_INT(rval));
                 op = (JSOp) JSVAL_TO_INT(rval);
                 JS_ASSERT((uintN)op < (uintN)JSOP_LIMIT);
                 LOAD_INTERRUPT_HANDLER(cx);
                 DO_OP();
@@ -5352,136 +5462,141 @@ interrupt:
                 cx->exception = rval;
                 goto error;
               default:;
             }
             LOAD_INTERRUPT_HANDLER(cx);
           END_CASE(JSOP_TRAP)
 
           BEGIN_CASE(JSOP_ARGUMENTS)
+            SAVE_SP_AND_PC(fp);
             if (!js_GetArgsValue(cx, fp, &rval))
                 goto error;
             PUSH_OPND(rval);
           END_CASE(JSOP_ARGUMENTS)
 
           BEGIN_CASE(JSOP_ARGSUB)
-            id = INT_TO_JSID(GET_ARGNO(regs.pc));
+            id = INT_TO_JSID(GET_ARGNO(pc));
+            SAVE_SP_AND_PC(fp);
             if (!js_GetArgsProperty(cx, fp, id, &rval))
                 goto error;
             PUSH_OPND(rval);
           END_CASE(JSOP_ARGSUB)
 
           BEGIN_CASE(JSOP_ARGCNT)
             id = ATOM_TO_JSID(rt->atomState.lengthAtom);
+            SAVE_SP_AND_PC(fp);
             if (!js_GetArgsProperty(cx, fp, id, &rval))
                 goto error;
             PUSH_OPND(rval);
           END_CASE(JSOP_ARGCNT)
 
           BEGIN_CASE(JSOP_GETARG)
           BEGIN_CASE(JSOP_CALLARG)
-            slot = GET_ARGNO(regs.pc);
+            slot = GET_ARGNO(pc);
             JS_ASSERT(slot < fp->fun->nargs);
             METER_SLOT_OP(op, slot);
             PUSH_OPND(fp->argv[slot]);
             if (op == JSOP_CALLARG)
                 PUSH_OPND(JSVAL_NULL);
           END_CASE(JSOP_GETARG)
 
           BEGIN_CASE(JSOP_SETARG)
-            slot = GET_ARGNO(regs.pc);
+            slot = GET_ARGNO(pc);
             JS_ASSERT(slot < fp->fun->nargs);
             METER_SLOT_OP(op, slot);
             vp = &fp->argv[slot];
             GC_POKE(cx, *vp);
             *vp = FETCH_OPND(-1);
           END_CASE(JSOP_SETARG)
 
           BEGIN_CASE(JSOP_GETVAR)
           BEGIN_CASE(JSOP_CALLVAR)
-            slot = GET_VARNO(regs.pc);
+            slot = GET_VARNO(pc);
             JS_ASSERT(slot < fp->fun->u.i.nvars);
             METER_SLOT_OP(op, slot);
             PUSH_OPND(fp->vars[slot]);
             if (op == JSOP_CALLVAR)
                 PUSH_OPND(JSVAL_NULL);
           END_CASE(JSOP_GETVAR)
 
           BEGIN_CASE(JSOP_SETVAR)
-            slot = GET_VARNO(regs.pc);
+            slot = GET_VARNO(pc);
             JS_ASSERT(slot < fp->fun->u.i.nvars);
             METER_SLOT_OP(op, slot);
             vp = &fp->vars[slot];
             GC_POKE(cx, *vp);
             *vp = FETCH_OPND(-1);
           END_CASE(JSOP_SETVAR)
 
           BEGIN_CASE(JSOP_GETGVAR)
           BEGIN_CASE(JSOP_CALLGVAR)
-            slot = GET_VARNO(regs.pc);
+            slot = GET_VARNO(pc);
             JS_ASSERT(slot < fp->nvars);
             METER_SLOT_OP(op, slot);
             lval = fp->vars[slot];
             if (JSVAL_IS_NULL(lval)) {
                 op = (op == JSOP_GETGVAR) ? JSOP_NAME : JSOP_CALLNAME;
                 DO_OP();
             }
             slot = JSVAL_TO_INT(lval);
             obj = fp->varobj;
             rval = OBJ_GET_SLOT(cx, obj, slot);
             PUSH_OPND(rval);
             if (op == JSOP_CALLGVAR)
                 PUSH_OPND(OBJECT_TO_JSVAL(obj));
           END_CASE(JSOP_GETGVAR)
 
           BEGIN_CASE(JSOP_SETGVAR)
-            slot = GET_VARNO(regs.pc);
+            slot = GET_VARNO(pc);
             JS_ASSERT(slot < fp->nvars);
             METER_SLOT_OP(op, slot);
             rval = FETCH_OPND(-1);
             lval = fp->vars[slot];
             obj = fp->varobj;
             if (JSVAL_IS_NULL(lval)) {
                 /*
                  * Inline-clone and deoptimize JSOP_SETNAME code here because
                  * JSOP_SETGVAR has arity 1: [rval], not arity 2: [obj, rval]
                  * as JSOP_SETNAME does, where [obj] is due to JSOP_BINDNAME.
                  */
                 LOAD_ATOM(0);
                 id = ATOM_TO_JSID(atom);
+                SAVE_SP_AND_PC(fp);
                 if (!OBJ_SET_PROPERTY(cx, obj, id, &rval))
                     goto error;
                 STORE_OPND(-1, rval);
             } else {
                 slot = JSVAL_TO_INT(lval);
                 JS_LOCK_OBJ(cx, obj);
                 LOCKED_OBJ_WRITE_BARRIER(cx, obj, slot, rval);
                 JS_UNLOCK_OBJ(cx, obj);
             }
           END_CASE(JSOP_SETGVAR)
 
           BEGIN_CASE(JSOP_DEFCONST)
           BEGIN_CASE(JSOP_DEFVAR)
-            index = GET_INDEX(regs.pc);
+            index = GET_INDEX(pc);
             atom = atoms[index];
 
             /*
              * index is relative to atoms at this point but for global var
              * code below we need the absolute value.
              */
             index += atoms - script->atomMap.vector;
             obj = fp->varobj;
             attrs = JSPROP_ENUMERATE;
             if (!(fp->flags & JSFRAME_EVAL))
                 attrs |= JSPROP_PERMANENT;
             if (op == JSOP_DEFCONST)
                 attrs |= JSPROP_READONLY;
 
             /* Lookup id in order to check for redeclaration problems. */
             id = ATOM_TO_JSID(atom);
+            SAVE_SP_AND_PC(fp);
             if (!js_CheckRedeclaration(cx, obj, id, attrs, &obj2, &prop))
                 goto error;
 
             /* Bind a variable only if it's not yet defined. */
             if (!prop) {
                 if (!OBJ_DEFINE_PROPERTY(cx, obj, id, JSVAL_VOID,
                                          JS_PropertyStub, JS_PropertyStub,
                                          attrs, &prop)) {
@@ -5551,21 +5666,23 @@ interrupt:
             JS_ASSERT(fp->scopeChain == fp->varobj);
             obj2 = fp->scopeChain;
 
             /*
              * ECMA requires functions defined when entering Global code to be
              * permanent.
              */
             attrs = JSPROP_ENUMERATE | JSPROP_PERMANENT;
+            SAVE_SP_AND_PC(fp);
 
           do_deffun:
+            /* The common code for JSOP_DEFFUN and JSOP_CLOSURE. */
+            ASSERT_SAVED_SP_AND_PC(fp);
+
             /*
-             * The common code for JSOP_DEFFUN and JSOP_CLOSURE.
-             *
              * Clone the function object with the current scope chain as the
              * clone's parent.  The original function object is the prototype
              * of the clone.  Do this only if re-parenting; the compiler may
              * have seen the right parent already and created a sufficiently
              * well-scoped function object.
              */
             if (OBJ_GET_PARENT(cx, obj) != obj2) {
                 obj = js_CloneFunctionObject(cx, obj, obj2);
@@ -5640,34 +5757,36 @@ interrupt:
 
             /*
              * Define a local function (i.e., one nested at the top level of
              * another function), parented by the current scope chain, and
              * stored in a local variable slot that the compiler allocated.
              * This is an optimization over JSOP_DEFFUN that avoids requiring
              * a call object for the outer function's activation.
              */
-            slot = GET_VARNO(regs.pc);
+            slot = GET_VARNO(pc);
 
             parent = js_GetScopeChain(cx, fp);
             if (!parent)
                 goto error;
 
+            SAVE_SP_AND_PC(fp);
             obj = js_CloneFunctionObject(cx, obj, parent);
             if (!obj)
                 goto error;
 
             fp->vars[slot] = OBJECT_TO_JSVAL(obj);
           END_CASE(JSOP_DEFLOCALFUN)
 
           BEGIN_CASE(JSOP_ANONFUNOBJ)
             /* Load the specified function object literal. */
             LOAD_FUNCTION(0);
 
             /* If re-parenting, push a clone of the function object. */
+            SAVE_SP_AND_PC(fp);
             parent = js_GetScopeChain(cx, fp);
             if (!parent)
                 goto error;
             if (OBJ_GET_PARENT(cx, obj) != parent) {
                 obj = js_CloneFunctionObject(cx, obj, parent);
                 if (!obj)
                     goto error;
             }
@@ -5682,16 +5801,17 @@ interrupt:
             /*
              * 1. Create a new object as if by the expression new Object().
              * 2. Add Result(1) to the front of the scope chain.
              *
              * Step 2 is achieved by making the new object's parent be the
              * current scope chain, and then making the new object the parent
              * of the Function object clone.
              */
+            SAVE_SP_AND_PC(fp);
             obj2 = js_GetScopeChain(cx, fp);
             if (!obj2)
                 goto error;
             parent = js_NewObject(cx, &js_ObjectClass, NULL, obj2);
             if (!parent)
                 goto error;
 
             /*
@@ -5768,16 +5888,17 @@ interrupt:
             LOAD_FUNCTION(0);
 
             /*
              * Clone the function object with the current scope chain as the
              * clone's parent. Do this only if re-parenting; the compiler may
              * have seen the right parent already and created a sufficiently
              * well-scoped function object.
              */
+            SAVE_SP_AND_PC(fp);
             obj2 = js_GetScopeChain(cx, fp);
             if (!obj2)
                 goto error;
 
             /*
              * ECMA requires that functions defined when entering Eval code to
              * be impermanent.
              */
@@ -5786,21 +5907,21 @@ interrupt:
                 attrs |= JSPROP_PERMANENT;
 
             goto do_deffun;
 
 #if JS_HAS_GETTER_SETTER
           BEGIN_CASE(JSOP_GETTER)
           BEGIN_CASE(JSOP_SETTER)
           do_getter_setter:
-            op2 = (JSOp) *++regs.pc;
+            op2 = (JSOp) *++pc;
             switch (op2) {
               case JSOP_INDEXBASE:
-                atoms += GET_INDEXBASE(regs.pc);
-                regs.pc += JSOP_INDEXBASE_LENGTH - 1;
+                atoms += GET_INDEXBASE(pc);
+                pc += JSOP_INDEXBASE_LENGTH - 1;
                 goto do_getter_setter;
               case JSOP_INDEXBASE1:
               case JSOP_INDEXBASE2:
               case JSOP_INDEXBASE3:
                 atoms += (op2 - JSOP_INDEXBASE1 + 1) << 16;
                 goto do_getter_setter;
 
               case JSOP_SETNAME:
@@ -5811,38 +5932,40 @@ interrupt:
                 i = -1;
                 goto gs_pop_lval;
 
               case JSOP_SETELEM:
                 rval = FETCH_OPND(-1);
                 id = 0;
                 i = -2;
               gs_pop_lval:
+                SAVE_SP_AND_PC(fp);
                 FETCH_OBJECT(cx, i - 1, lval, obj);
                 break;
 
               case JSOP_INITPROP:
-                JS_ASSERT(regs.sp - fp->spbase >= 2);
+                JS_ASSERT(sp - fp->spbase >= 2);
                 rval = FETCH_OPND(-1);
                 i = -1;
                 LOAD_ATOM(0);
                 id = ATOM_TO_JSID(atom);
                 goto gs_get_lval;
 
               default:
                 JS_ASSERT(op2 == JSOP_INITELEM);
 
-                JS_ASSERT(regs.sp - fp->spbase >= 3);
+                JS_ASSERT(sp - fp->spbase >= 3);
                 rval = FETCH_OPND(-1);
                 id = 0;
                 i = -2;
               gs_get_lval:
                 lval = FETCH_OPND(i-1);
                 JS_ASSERT(JSVAL_IS_OBJECT(lval));
                 obj = JSVAL_TO_OBJECT(lval);
+                SAVE_SP_AND_PC(fp);
                 break;
             }
 
             /* Ensure that id has a type suitable for use with obj. */
             if (id == 0)
                 FETCH_ELEMENT_ID(obj, i, id);
 
             if (JS_TypeOfValue(cx, rval) != JSTYPE_FUNCTION) {
@@ -5876,50 +5999,51 @@ interrupt:
             if (!js_CheckRedeclaration(cx, obj, id, attrs, NULL, NULL))
                 goto error;
 
             if (!OBJ_DEFINE_PROPERTY(cx, obj, id, JSVAL_VOID, getter, setter,
                                      attrs, NULL)) {
                 goto error;
             }
 
-            regs.sp += i;
+            sp += i;
             if (js_CodeSpec[op2].ndefs)
                 STORE_OPND(-1, rval);
             len = js_CodeSpec[op2].length;
             DO_NEXT_OP(len);
 #endif /* JS_HAS_GETTER_SETTER */
 
           BEGIN_CASE(JSOP_NEWINIT)
-            i = GET_INT8(regs.pc);
+            i = GET_INT8(pc);
             JS_ASSERT(i == JSProto_Array || i == JSProto_Object);
+            SAVE_SP_AND_PC(fp);
             obj = (i == JSProto_Array)
                   ? js_NewArrayObject(cx, 0, NULL)
                   : js_NewObject(cx, &js_ObjectClass, NULL, NULL);
             if (!obj)
                 goto error;
             PUSH_OPND(OBJECT_TO_JSVAL(obj));
             fp->sharpDepth++;
             LOAD_INTERRUPT_HANDLER(cx);
           END_CASE(JSOP_NEWINIT)
 
           BEGIN_CASE(JSOP_ENDINIT)
             if (--fp->sharpDepth == 0)
                 fp->sharpArray = NULL;
 
             /* Re-set the newborn root to the top of this object tree. */
-            JS_ASSERT(regs.sp - fp->spbase >= 1);
+            JS_ASSERT(sp - fp->spbase >= 1);
             lval = FETCH_OPND(-1);
             JS_ASSERT(JSVAL_IS_OBJECT(lval));
             cx->weakRoots.newborn[GCX_OBJECT] = JSVAL_TO_GCTHING(lval);
           END_CASE(JSOP_ENDINIT)
 
           BEGIN_CASE(JSOP_INITPROP)
             /* Load the property's initial value into rval. */
-            JS_ASSERT(regs.sp - fp->spbase >= 2);
+            JS_ASSERT(sp - fp->spbase >= 2);
             rval = FETCH_OPND(-1);
 
             /* Load the object being initialized into lval/obj. */
             lval = FETCH_OPND(-2);
             obj = JSVAL_TO_OBJECT(lval);
             JS_ASSERT(OBJ_IS_NATIVE(obj));
             JS_ASSERT(!OBJ_GET_CLASS(cx, obj)->reserveSlots);
             JS_ASSERT(!(LOCKED_OBJ_GET_CLASS(obj)->flags &
@@ -5931,21 +6055,21 @@ interrupt:
                 JSPropertyCache *cache;
                 JSPropCacheEntry *entry;
 
                 JS_LOCK_OBJ(cx, obj);
                 scope = OBJ_SCOPE(obj);
                 JS_ASSERT(!SCOPE_IS_SEALED(scope));
                 kshape = scope->shape;
                 cache = &JS_PROPERTY_CACHE(cx);
-                entry = &cache->table[PROPERTY_CACHE_HASH_PC(regs.pc, kshape)];
+                entry = &cache->table[PROPERTY_CACHE_HASH_PC(pc, kshape)];
                 PCMETER(cache->tests++);
                 PCMETER(cache->initests++);
 
-                if (entry->kpc == regs.pc && entry->kshape == kshape) {
+                if (entry->kpc == pc && entry->kshape == kshape) {
                     PCMETER(cache->pchits++);
                     PCMETER(cache->inipchits++);
 
                     JS_ASSERT(PCVAL_IS_SPROP(entry->vword));
                     sprop = PCVAL_TO_SPROP(entry->vword);
                     JS_ASSERT(!(sprop->attrs & JSPROP_READONLY));
 
                     /*
@@ -6025,111 +6149,116 @@ interrupt:
 
               do_initprop_miss:
                 PCMETER(cache->inipcmisses++);
                 JS_UNLOCK_SCOPE(cx, scope);
 
                 /* Get the immediate property name into id. */
                 LOAD_ATOM(0);
                 id = ATOM_TO_JSID(atom);
+                SAVE_SP_AND_PC(fp);
 
                 /* Set the property named by obj[id] to rval. */
                 if (!js_CheckRedeclaration(cx, obj, id, JSPROP_INITIALIZER,
                                            NULL, NULL)) {
                     goto error;
                 }
                 if (!js_SetPropertyHelper(cx, obj, id, &rval, &entry))
                     goto error;
             } while (0);
 
             /* Common tail for property cache hit and miss cases. */
-            regs.sp--;
+            sp--;
           END_CASE(JSOP_INITPROP);
 
           BEGIN_CASE(JSOP_INITELEM)
             /* Pop the element's value into rval. */
-            JS_ASSERT(regs.sp - fp->spbase >= 3);
+            JS_ASSERT(sp - fp->spbase >= 3);
             rval = FETCH_OPND(-1);
+            SAVE_SP_AND_PC(fp);
             FETCH_ELEMENT_ID(obj, -2, id);
 
             /* Find the object being initialized at top of stack. */
             lval = FETCH_OPND(-3);
             JS_ASSERT(!JSVAL_IS_PRIMITIVE(lval));
             obj = JSVAL_TO_OBJECT(lval);
 
             /* Set the property named by obj[id] to rval. */
             if (!js_CheckRedeclaration(cx, obj, id, JSPROP_INITIALIZER, NULL,
                                        NULL)) {
                 goto error;
             }
             if (!OBJ_SET_PROPERTY(cx, obj, id, &rval))
                 goto error;
-            regs.sp -= 2;
+            sp -= 2;
           END_CASE(JSOP_INITELEM);
 
 #if JS_HAS_SHARP_VARS
           BEGIN_CASE(JSOP_DEFSHARP)
+            SAVE_SP_AND_PC(fp);
             obj = fp->sharpArray;
             if (!obj) {
                 obj = js_NewArrayObject(cx, 0, NULL);
                 if (!obj)
                     goto error;
                 fp->sharpArray = obj;
             }
-            i = (jsint) GET_UINT16(regs.pc);
+            i = (jsint) GET_UINT16(pc);
             id = INT_TO_JSID(i);
             rval = FETCH_OPND(-1);
             if (JSVAL_IS_PRIMITIVE(rval)) {
                 char numBuf[12];
                 JS_snprintf(numBuf, sizeof numBuf, "%u", (unsigned) i);
                 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                                      JSMSG_BAD_SHARP_DEF, numBuf);
                 goto error;
             }
             if (!OBJ_SET_PROPERTY(cx, obj, id, &rval))
                 goto error;
           END_CASE(JSOP_DEFSHARP)
 
           BEGIN_CASE(JSOP_USESHARP)
-            i = (jsint) GET_UINT16(regs.pc);
+            i = (jsint) GET_UINT16(pc);
             id = INT_TO_JSID(i);
             obj = fp->sharpArray;
             if (!obj) {
                 rval = JSVAL_VOID;
             } else {
+                SAVE_SP_AND_PC(fp);
                 if (!OBJ_GET_PROPERTY(cx, obj, id, &rval))
                     goto error;
             }
             if (!JSVAL_IS_OBJECT(rval)) {
                 char numBuf[12];
-
                 JS_snprintf(numBuf, sizeof numBuf, "%u", (unsigned) i);
+
+                SAVE_SP_AND_PC(fp);
                 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                                      JSMSG_BAD_SHARP_USE, numBuf);
                 goto error;
             }
             PUSH_OPND(rval);
           END_CASE(JSOP_USESHARP)
 #endif /* JS_HAS_SHARP_VARS */
 
           /* No-ops for ease of decompilation and jit'ing. */
           EMPTY_CASE(JSOP_TRY)
           EMPTY_CASE(JSOP_FINALLY)
 
           BEGIN_CASE(JSOP_GOSUB)
             PUSH(JSVAL_FALSE);
-            i = PTRDIFF(regs.pc, script->main, jsbytecode) + JSOP_GOSUB_LENGTH;
-            len = GET_JUMP_OFFSET(regs.pc);
+            i = PTRDIFF(pc, script->main, jsbytecode) + JSOP_GOSUB_LENGTH;
+            len = GET_JUMP_OFFSET(pc);
             PUSH(INT_TO_JSVAL(i));
           END_VARLEN_CASE
 
           BEGIN_CASE(JSOP_GOSUBX)
             PUSH(JSVAL_FALSE);
-            i = PTRDIFF(regs.pc, script->main, jsbytecode) + JSOP_GOSUBX_LENGTH;
-            len = GET_JUMPX_OFFSET(regs.pc);
+            i = PTRDIFF(pc, script->main, jsbytecode) + JSOP_GOSUBX_LENGTH;
+            len = GET_JUMPX_OFFSET(pc);
             PUSH(INT_TO_JSVAL(i));
           END_VARLEN_CASE
 
           BEGIN_CASE(JSOP_RETSUB)
             rval = POP();
             lval = POP();
             JS_ASSERT(JSVAL_IS_BOOLEAN(lval));
             if (JSVAL_TO_BOOLEAN(lval)) {
@@ -6140,17 +6269,17 @@ interrupt:
                  * it points out a FIXME: 350509, due to Igor Bukanov.
                  */
                 cx->throwing = JS_TRUE;
                 cx->exception = rval;
                 goto error;
             }
             JS_ASSERT(JSVAL_IS_INT(rval));
             len = JSVAL_TO_INT(rval);
-            regs.pc = script->main;
+            pc = script->main;
           END_VARLEN_CASE
 
           BEGIN_CASE(JSOP_EXCEPTION)
             JS_ASSERT(cx->throwing);
             PUSH(cx->exception);
             cx->throwing = JS_FALSE;
           END_CASE(JSOP_EXCEPTION)
 
@@ -6167,44 +6296,46 @@ interrupt:
             /* let the code at error try to catch the exception. */
             goto error;
 
           BEGIN_CASE(JSOP_SETLOCALPOP)
             /*
              * The stack must have a block with at least one local slot below
              * the exception object.
              */
-            JS_ASSERT(regs.sp - fp->spbase >= 2);
-            slot = GET_UINT16(regs.pc);
+            JS_ASSERT(sp - fp->spbase >= 2);
+            slot = GET_UINT16(pc);
             JS_ASSERT(slot + 1 < script->depth);
             fp->spbase[slot] = POP_OPND();
           END_CASE(JSOP_SETLOCALPOP)
 
           BEGIN_CASE(JSOP_INSTANCEOF)
+            SAVE_SP_AND_PC(fp);
             rval = FETCH_OPND(-1);
             if (JSVAL_IS_PRIMITIVE(rval) ||
                 !(obj = JSVAL_TO_OBJECT(rval))->map->ops->hasInstance) {
                 js_ReportValueError(cx, JSMSG_BAD_INSTANCEOF_RHS,
                                     -1, rval, NULL);
                 goto error;
             }
             lval = FETCH_OPND(-2);
             cond = JS_FALSE;
             if (!obj->map->ops->hasInstance(cx, obj, lval, &cond))
                 goto error;
-            regs.sp--;
+            sp--;
             STORE_OPND(-1, BOOLEAN_TO_JSVAL(cond));
           END_CASE(JSOP_INSTANCEOF)
 
 #if JS_HAS_DEBUGGER_KEYWORD
           BEGIN_CASE(JSOP_DEBUGGER)
           {
             JSTrapHandler handler = cx->debugHooks->debuggerHandler;
             if (handler) {
-                switch (handler(cx, script, regs.pc, &rval,
+                SAVE_SP_AND_PC(fp);
+                switch (handler(cx, script, pc, &rval,
                                 cx->debugHooks->debuggerHandlerData)) {
                   case JSTRAP_ERROR:
                     goto error;
                   case JSTRAP_CONTINUE:
                     break;
                   case JSTRAP_RETURN:
                     fp->rval = rval;
                     ok = JS_TRUE;
@@ -6219,207 +6350,224 @@ interrupt:
             }
           }
           END_CASE(JSOP_DEBUGGER)
 #endif /* JS_HAS_DEBUGGER_KEYWORD */
 
 #if JS_HAS_XML_SUPPORT
           BEGIN_CASE(JSOP_DEFXMLNS)
             rval = POP();
+            SAVE_SP_AND_PC(fp);
             if (!js_SetDefaultXMLNamespace(cx, rval))
                 goto error;
           END_CASE(JSOP_DEFXMLNS)
 
           BEGIN_CASE(JSOP_ANYNAME)
+            SAVE_SP_AND_PC(fp);
             if (!js_GetAnyName(cx, &rval))
                 goto error;
             PUSH_OPND(rval);
           END_CASE(JSOP_ANYNAME)
 
           BEGIN_CASE(JSOP_QNAMEPART)
             LOAD_ATOM(0);
             PUSH_OPND(ATOM_KEY(atom));
           END_CASE(JSOP_QNAMEPART)
 
           BEGIN_CASE(JSOP_QNAMECONST)
             LOAD_ATOM(0);
             rval = ATOM_KEY(atom);
             lval = FETCH_OPND(-1);
+            SAVE_SP_AND_PC(fp);
             obj = js_ConstructXMLQNameObject(cx, lval, rval);
             if (!obj)
                 goto error;
             STORE_OPND(-1, OBJECT_TO_JSVAL(obj));
           END_CASE(JSOP_QNAMECONST)
 
           BEGIN_CASE(JSOP_QNAME)
             rval = FETCH_OPND(-1);
             lval = FETCH_OPND(-2);
+            SAVE_SP_AND_PC(fp);
             obj = js_ConstructXMLQNameObject(cx, lval, rval);
             if (!obj)
                 goto error;
-            regs.sp--;
+            sp--;
             STORE_OPND(-1, OBJECT_TO_JSVAL(obj));
           END_CASE(JSOP_QNAME)
 
           BEGIN_CASE(JSOP_TOATTRNAME)
             rval = FETCH_OPND(-1);
+            SAVE_SP_AND_PC(fp);
             if (!js_ToAttributeName(cx, &rval))
                 goto error;
             STORE_OPND(-1, rval);
           END_CASE(JSOP_TOATTRNAME)
 
           BEGIN_CASE(JSOP_TOATTRVAL)
             rval = FETCH_OPND(-1);
             JS_ASSERT(JSVAL_IS_STRING(rval));
+            SAVE_SP_AND_PC(fp);
             str = js_EscapeAttributeValue(cx, JSVAL_TO_STRING(rval), JS_FALSE);
             if (!str)
                 goto error;
             STORE_OPND(-1, STRING_TO_JSVAL(str));
           END_CASE(JSOP_TOATTRVAL)
 
           BEGIN_CASE(JSOP_ADDATTRNAME)
           BEGIN_CASE(JSOP_ADDATTRVAL)
             rval = FETCH_OPND(-1);
             lval = FETCH_OPND(-2);
             str = JSVAL_TO_STRING(lval);
             str2 = JSVAL_TO_STRING(rval);
+            SAVE_SP_AND_PC(fp);
             str = js_AddAttributePart(cx, op == JSOP_ADDATTRNAME, str, str2);
             if (!str)
                 goto error;
-            regs.sp--;
+            sp--;
             STORE_OPND(-1, STRING_TO_JSVAL(str));
           END_CASE(JSOP_ADDATTRNAME)
 
           BEGIN_CASE(JSOP_BINDXMLNAME)
             lval = FETCH_OPND(-1);
+            SAVE_SP_AND_PC(fp);
             if (!js_FindXMLProperty(cx, lval, &obj, &id))
                 goto error;
             STORE_OPND(-1, OBJECT_TO_JSVAL(obj));
             PUSH_OPND(ID_TO_VALUE(id));
           END_CASE(JSOP_BINDXMLNAME)
 
           BEGIN_CASE(JSOP_SETXMLNAME)
             obj = JSVAL_TO_OBJECT(FETCH_OPND(-3));
             rval = FETCH_OPND(-1);
+            SAVE_SP_AND_PC(fp);
             FETCH_ELEMENT_ID(obj, -2, id);
             if (!OBJ_SET_PROPERTY(cx, obj, id, &rval))
                 goto error;
-            regs.sp -= 2;
+            sp -= 2;
             STORE_OPND(-1, rval);
           END_CASE(JSOP_SETXMLNAME)
 
           BEGIN_CASE(JSOP_CALLXMLNAME)
           BEGIN_CASE(JSOP_XMLNAME)
             lval = FETCH_OPND(-1);
+            SAVE_SP_AND_PC(fp);
             if (!js_FindXMLProperty(cx, lval, &obj, &id))
                 goto error;
             if (!OBJ_GET_PROPERTY(cx, obj, id, &rval))
                 goto error;
             STORE_OPND(-1, rval);
             if (op == JSOP_CALLXMLNAME)
                 PUSH_OPND(OBJECT_TO_JSVAL(obj));
           END_CASE(JSOP_XMLNAME)
 
           BEGIN_CASE(JSOP_DESCENDANTS)
           BEGIN_CASE(JSOP_DELDESC)
+            SAVE_SP_AND_PC(fp);
             FETCH_OBJECT(cx, -2, lval, obj);
             rval = FETCH_OPND(-1);
             if (!js_GetXMLDescendants(cx, obj, rval, &rval))
                 goto error;
 
             if (op == JSOP_DELDESC) {
-                regs.sp[-1] = rval;          /* set local root */
+                sp[-1] = rval;          /* set local root */
                 if (!js_DeleteXMLListElements(cx, JSVAL_TO_OBJECT(rval)))
                     goto error;
                 rval = JSVAL_TRUE;      /* always succeed */
             }
 
-            regs.sp--;
+            sp--;
             STORE_OPND(-1, rval);
           END_CASE(JSOP_DESCENDANTS)
 
           BEGIN_CASE(JSOP_FILTER)
             /*
              * We push the hole value before jumping to [enditer] so we can
              * detect the first iteration and direct js_StepXMLListFilter to
              * initialize filter's state.
              */
             PUSH_OPND(JSVAL_HOLE);
-            len = GET_JUMP_OFFSET(regs.pc);
+            len = GET_JUMP_OFFSET(pc);
             JS_ASSERT(len > 0);
           END_VARLEN_CASE
 
           BEGIN_CASE(JSOP_ENDFILTER)
-            cond = (regs.sp[-1] != JSVAL_HOLE);
+            SAVE_SP_AND_PC(fp);
+            cond = (sp[-1] != JSVAL_HOLE);
             if (cond) {
                 /* Exit the "with" block left from the previous iteration. */
                 js_LeaveWith(cx);
             }
             if (!js_StepXMLListFilter(cx, cond))
                 goto error;
-            if (regs.sp[-1] != JSVAL_NULL) {
+            if (sp[-1] != JSVAL_NULL) {
                 /*
                  * Decrease sp after EnterWith returns as we use sp[-1] there
                  * to root temporaries.
                  */
-                JS_ASSERT(VALUE_IS_XML(cx, regs.sp[-1]));
+                JS_ASSERT(VALUE_IS_XML(cx, sp[-1]));
                 if (!js_EnterWith(cx, -2))
                     goto error;
-                regs.sp--;
-                len = GET_JUMP_OFFSET(regs.pc);
+                sp--;
+                len = GET_JUMP_OFFSET(pc);
                 JS_ASSERT(len < 0);
                 CHECK_BRANCH(len);
                 DO_NEXT_OP(len);
             }
-            regs.sp--;
+            sp--;
           END_CASE(JSOP_ENDFILTER);
 
           EMPTY_CASE(JSOP_STARTXML)
           EMPTY_CASE(JSOP_STARTXMLEXPR)
 
           BEGIN_CASE(JSOP_TOXML)
             rval = FETCH_OPND(-1);
+            SAVE_SP_AND_PC(fp);
             obj = js_ValueToXMLObject(cx, rval);
             if (!obj)
                 goto error;
             STORE_OPND(-1, OBJECT_TO_JSVAL(obj));
           END_CASE(JSOP_TOXML)
 
           BEGIN_CASE(JSOP_TOXMLLIST)
             rval = FETCH_OPND(-1);
+            SAVE_SP_AND_PC(fp);
             obj = js_ValueToXMLListObject(cx, rval);
             if (!obj)
                 goto error;
             STORE_OPND(-1, OBJECT_TO_JSVAL(obj));
           END_CASE(JSOP_TOXMLLIST)
 
           BEGIN_CASE(JSOP_XMLTAGEXPR)
             rval = FETCH_OPND(-1);
+            SAVE_SP_AND_PC(fp);
             str = js_ValueToString(cx, rval);
             if (!str)
                 goto error;
             STORE_OPND(-1, STRING_TO_JSVAL(str));
           END_CASE(JSOP_XMLTAGEXPR)
 
           BEGIN_CASE(JSOP_XMLELTEXPR)
             rval = FETCH_OPND(-1);
+            SAVE_SP_AND_PC(fp);
             if (VALUE_IS_XML(cx, rval)) {
                 str = js_ValueToXMLString(cx, rval);
             } else {
                 str = js_ValueToString(cx, rval);
                 if (str)
                     str = js_EscapeElementValue(cx, str);
             }
             if (!str)
                 goto error;
             STORE_OPND(-1, STRING_TO_JSVAL(str));
           END_CASE(JSOP_XMLELTEXPR)
 
           BEGIN_CASE(JSOP_XMLOBJECT)
             LOAD_OBJECT(0);
+            SAVE_SP_AND_PC(fp);
             obj = js_CloneXMLObject(cx, obj);
             if (!obj)
                 goto error;
             PUSH_OPND(OBJECT_TO_JSVAL(obj));
           END_CASE(JSOP_XMLOBJECT)
 
           BEGIN_CASE(JSOP_XMLCDATA)
             LOAD_ATOM(0);
@@ -6439,39 +6587,41 @@ interrupt:
             PUSH_OPND(OBJECT_TO_JSVAL(obj));
           END_CASE(JSOP_XMLCOMMENT)
 
           BEGIN_CASE(JSOP_XMLPI)
             LOAD_ATOM(0);
             str = ATOM_TO_STRING(atom);
             rval = FETCH_OPND(-1);
             str2 = JSVAL_TO_STRING(rval);
+            SAVE_SP_AND_PC(fp);
             obj = js_NewXMLSpecialObject(cx,
                                          JSXML_CLASS_PROCESSING_INSTRUCTION,
                                          str, str2);
             if (!obj)
                 goto error;
             STORE_OPND(-1, OBJECT_TO_JSVAL(obj));
           END_CASE(JSOP_XMLPI)
 
           BEGIN_CASE(JSOP_GETFUNNS)
+            SAVE_SP_AND_PC(fp);
             if (!js_GetFunctionNamespace(cx, &rval))
                 goto error;
             PUSH_OPND(rval);
           END_CASE(JSOP_GETFUNNS)
 #endif /* JS_HAS_XML_SUPPORT */
 
           BEGIN_CASE(JSOP_ENTERBLOCK)
             LOAD_OBJECT(0);
-            JS_ASSERT(fp->spbase + OBJ_BLOCK_DEPTH(cx, obj) == regs.sp);
-            vp = regs.sp + OBJ_BLOCK_COUNT(cx, obj);
+            JS_ASSERT(fp->spbase + OBJ_BLOCK_DEPTH(cx, obj) == sp);
+            vp = sp + OBJ_BLOCK_COUNT(cx, obj);
             JS_ASSERT(vp <= fp->spbase + script->depth);
-            while (regs.sp < vp) {
+            while (sp < vp) {
                 STORE_OPND(0, JSVAL_VOID);
-                regs.sp++;
+                sp++;
             }
 
             /*
              * If this frame had to reflect the compile-time block chain into
              * the runtime scope chain, we can't optimize block scopes out of
              * runtime any longer, because an outer block that parents obj has
              * been cloned onto the scope chain.  To avoid re-cloning such a
              * parent and accumulating redundant clones via js_GetScopeChain,
@@ -6505,93 +6655,100 @@ interrupt:
             if (fp->blockChain) {
                 JS_ASSERT(OBJ_GET_CLASS(cx, fp->blockChain) == &js_BlockClass);
                 fp->blockChain = OBJ_GET_PARENT(cx, fp->blockChain);
             } else {
                 /*
                  * This block was cloned into fp->scopeChain, so clear its
                  * private data and sync its locals to their property slots.
                  */
+                SAVE_SP_AND_PC(fp);
                 if (!js_PutBlockObject(cx, JS_TRUE))
                     goto error;
             }
 
             /*
              * We will move the result of the expression to the new topmost
              * stack slot.
              */
             if (op == JSOP_LEAVEBLOCKEXPR)
                 rval = FETCH_OPND(-1);
-            regs.sp -= GET_UINT16(regs.pc);
+            sp -= GET_UINT16(pc);
             if (op == JSOP_LEAVEBLOCKEXPR) {
-                JS_ASSERT(blocksp == regs.sp - 1);
+                JS_ASSERT(blocksp == sp - 1);
                 STORE_OPND(-1, rval);
             } else {
-                JS_ASSERT(blocksp == regs.sp);
+                JS_ASSERT(blocksp == sp);
             }
           }
           END_CASE(JSOP_LEAVEBLOCK)
 
           BEGIN_CASE(JSOP_GETLOCAL)
           BEGIN_CASE(JSOP_CALLLOCAL)
-            slot = GET_UINT16(regs.pc);
+            slot = GET_UINT16(pc);
             JS_ASSERT(slot < script->depth);
             PUSH_OPND(fp->spbase[slot]);
             if (op == JSOP_CALLLOCAL)
                 PUSH_OPND(JSVAL_NULL);
           END_CASE(JSOP_GETLOCAL)
 
           BEGIN_CASE(JSOP_SETLOCAL)
-            slot = GET_UINT16(regs.pc);
+            slot = GET_UINT16(pc);
             JS_ASSERT(slot < script->depth);
             vp = &fp->spbase[slot];
             GC_POKE(cx, *vp);
             *vp = FETCH_OPND(-1);
           END_CASE(JSOP_SETLOCAL)
 
           BEGIN_CASE(JSOP_ENDITER)
             /*
              * Decrease the stack pointer even when !ok, see comments in the
              * exception capturing code for details.
              */
-            ok = js_CloseIterator(cx, regs.sp[-1]);
-            regs.sp--;
+            SAVE_SP_AND_PC(fp);
+            ok = js_CloseIterator(cx, sp[-1]);
+            sp--;
             if (!ok)
                 goto error;
           END_CASE(JSOP_ENDITER)
 
 #if JS_HAS_GENERATORS
           BEGIN_CASE(JSOP_GENERATOR)
             ASSERT_NOT_THROWING(cx);
-            regs.pc += JSOP_GENERATOR_LENGTH;
+            pc += JSOP_GENERATOR_LENGTH;
+            SAVE_SP_AND_PC(fp);
             obj = js_NewGenerator(cx, fp);
             if (!obj)
                 goto error;
             JS_ASSERT(!fp->callobj && !fp->argsobj);
             fp->rval = OBJECT_TO_JSVAL(obj);
             ok = JS_TRUE;
             if (inlineCallCount != 0)
                 goto inline_return;
             goto exit;
 
           BEGIN_CASE(JSOP_YIELD)
             ASSERT_NOT_THROWING(cx);
             if (FRAME_TO_GENERATOR(fp)->state == JSGEN_CLOSING) {
+                SAVE_SP_AND_PC(fp);
                 js_ReportValueError(cx, JSMSG_BAD_GENERATOR_YIELD,
                                     JSDVG_SEARCH_STACK, fp->argv[-2], NULL);
                 goto error;
             }
             fp->rval = FETCH_OPND(-1);
             fp->flags |= JSFRAME_YIELDING;
-            regs.pc += JSOP_YIELD_LENGTH;
+            pc += JSOP_YIELD_LENGTH;
+            SAVE_SP_AND_PC(fp);
+            JS_PROPERTY_CACHE(cx).disabled -= js_CountWithBlocks(cx, fp);
+            JS_ASSERT(JS_PROPERTY_CACHE(cx).disabled >= 0);
             ok = JS_TRUE;
             goto exit;
 
           BEGIN_CASE(JSOP_ARRAYPUSH)
-            slot = GET_UINT16(regs.pc);
+            slot = GET_UINT16(pc);
             JS_ASSERT(slot < script->depth);
             lval = fp->spbase[slot];
             obj  = JSVAL_TO_OBJECT(lval);
             JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_ArrayClass);
             rval = FETCH_OPND(-1);
 
             /*
              * We know that the array is created with only a 'length' private
@@ -6603,17 +6760,17 @@ interrupt:
             if (i == ARRAY_INIT_LIMIT) {
                 JS_ReportErrorNumberUC(cx, js_GetErrorMessage, NULL,
                                        JSMSG_ARRAY_INIT_TOO_BIG);
                 goto error;
             }
             id = INT_TO_JSID(i);
             if (!OBJ_SET_PROPERTY(cx, obj, id, &rval))
                 goto error;
-            regs.sp--;
+            sp--;
           END_CASE(JSOP_ARRAYPUSH)
 #endif /* JS_HAS_GENERATORS */
 
 #if JS_THREADED_INTERP
           L_JSOP_BACKPATCH:
           L_JSOP_BACKPATCH_POP:
 
 # if !JS_HAS_GENERATORS
@@ -6671,73 +6828,75 @@ interrupt:
             goto error;
           }
 
 #if !JS_THREADED_INTERP
 
         } /* switch (op) */
 
     advance_pc:
-        regs.pc += len;
+        pc += len;
 
 #ifdef DEBUG
         if (tracefp) {
             intN ndefs, n;
             jsval *siter;
 
             /*
              * op may be invalid here when a catch or finally handler jumps to
              * advance_pc.
              */
-            op = (JSOp) regs.pc[-len];
+            op = (JSOp) pc[-len];
             ndefs = js_CodeSpec[op].ndefs;
             if (ndefs) {
-                if (op == JSOP_FORELEM && regs.sp[-1] == JSVAL_FALSE)
+                SAVE_SP_AND_PC(fp);
+                if (op == JSOP_FORELEM && sp[-1] == JSVAL_FALSE)
                     --ndefs;
                 for (n = -ndefs; n < 0; n++) {
-                    char *bytes = js_DecompileValueGenerator(cx, n, regs.sp[n],
+                    char *bytes = js_DecompileValueGenerator(cx, n, sp[n],
                                                              NULL);
                     if (bytes) {
                         fprintf(tracefp, "%s %s",
                                 (n == -ndefs) ? "  output:" : ",",
                                 bytes);
                         JS_free(cx, bytes);
                     }
                 }
-                fprintf(tracefp, " @ %d\n", regs.sp - fp->spbase);
+                fprintf(tracefp, " @ %d\n", sp - fp->spbase);
             }
             fprintf(tracefp, "  stack: ");
-            for (siter = fp->spbase; siter < regs.sp; siter++) {
+            for (siter = fp->spbase; siter < sp; siter++) {
                 str = js_ValueToString(cx, *siter);
                 if (!str)
                     fputs("<null>", tracefp);
                 else
                     js_FileEscapedString(tracefp, str, 0);
                 fputc(' ', tracefp);
             }
             fputc('\n', tracefp);
         }
 #endif /* DEBUG */
     }
 #endif /* !JS_THREADED_INTERP */
 
   error:
-    JS_ASSERT((size_t)(regs.pc - script->code) < script->length);
+    JS_ASSERT((size_t)(pc - script->code) < script->length);
     if (!cx->throwing) {
         /* This is an error, not a catchable exception, quit the frame ASAP. */
         ok = JS_FALSE;
     } else {
         JSTrapHandler handler;
         JSTryNote *tn, *tnlimit;
         uint32 offset;
 
         /* Call debugger throw hook if set. */
         handler = cx->debugHooks->throwHook;
         if (handler) {
-            switch (handler(cx, script, regs.pc, &rval,
+            SAVE_SP_AND_PC(fp);
+            switch (handler(cx, script, pc, &rval,
                             cx->debugHooks->throwHookData)) {
               case JSTRAP_ERROR:
                 cx->throwing = JS_FALSE;
                 goto error;
               case JSTRAP_RETURN:
                 cx->throwing = JS_FALSE;
                 fp->rval = rval;
                 ok = JS_TRUE;
@@ -6751,17 +6910,17 @@ interrupt:
         }
 
         /*
          * Look for a try block in script that can catch this exception.
          */
         if (script->trynotesOffset == 0)
             goto no_catch;
 
-        offset = (uint32)(regs.pc - script->main);
+        offset = (uint32)(pc - script->main);
         tn = JS_SCRIPT_TRYNOTES(script)->vector;
         tnlimit = tn + JS_SCRIPT_TRYNOTES(script)->length;
         do {
             if (offset - tn->start >= tn->length)
                 continue;
 
             /*
              * We have a note that covers the exception pc but we must check
@@ -6777,39 +6936,41 @@ interrupt:
              * corresponding iterators and invoked the finally blocks.
              *
              * To address this, we make [enditer] always decrease the stack
              * even when its implementation throws an exception. Thus already
              * executed [enditer] and [gosub] opcodes will have try notes
              * with the stack depth exceeding the current one and this
              * condition is what we use to filter them out.
              */
-            if (tn->stackDepth > regs.sp - fp->spbase)
+            if (tn->stackDepth > sp - fp->spbase)
                 continue;
 
             /*
              * Set pc to the first bytecode after the the try note to point
              * to the beginning of catch or finally or to [enditer] closing
              * the for-in loop.
              */
-            regs.pc = (script)->main + tn->start + tn->length;
-
+            pc = (script)->main + tn->start + tn->length;
+
+            SAVE_SP_AND_PC(fp);
             ok = js_UnwindScope(cx, fp, tn->stackDepth, JS_TRUE);
-            JS_ASSERT(fp->regs->sp == fp->spbase + tn->stackDepth);
+            JS_ASSERT(fp->sp == fp->spbase + tn->stackDepth);
+            RESTORE_SP(fp);
             if (!ok) {
                 /*
                  * Restart the handler search with updated pc and stack depth
                  * to properly notify the debugger.
                  */
                 goto error;
             }
 
             switch (tn->kind) {
               case JSTN_CATCH:
-                JS_ASSERT(*regs.pc == JSOP_ENTERBLOCK);
+                JS_ASSERT(*pc == JSOP_ENTERBLOCK);
 
 #if JS_HAS_GENERATORS
                 /* Catch cannot intercept the closing of a generator. */
                 if (JS_UNLIKELY(cx->exception == JSVAL_ARETURN))
                     break;
 #endif
 
                 /*
@@ -6832,25 +6993,26 @@ interrupt:
                 DO_NEXT_OP(len);
 
               case JSTN_ITER:
                 /*
                  * This is similar to JSOP_ENDITER in the interpreter loop
                  * except the code now uses a reserved stack slot to save and
                  * restore the exception.
                  */
-                JS_ASSERT(*regs.pc == JSOP_ENDITER);
+                JS_ASSERT(*pc == JSOP_ENDITER);
                 PUSH(cx->exception);
                 cx->throwing = JS_FALSE;
-                ok = js_CloseIterator(cx, regs.sp[-2]);
-                regs.sp -= 2;
+                SAVE_SP_AND_PC(fp);
+                ok = js_CloseIterator(cx, sp[-2]);
+                sp -= 2;
                 if (!ok)
                     goto error;
                 cx->throwing = JS_TRUE;
-                cx->exception = regs.sp[1];
+                cx->exception = sp[1];
             }
         } while (++tn != tnlimit);
 
       no_catch:
         /*
          * Propagate the exception or error to the caller unless the exception
          * is an asynchronous return from a generator.
          */
@@ -6867,18 +7029,20 @@ interrupt:
   forced_return:
     /*
      * Unwind the scope making sure that ok stays false even when UnwindScope
      * returns true.
      *
      * When a trap handler returns JSTRAP_RETURN, we jump here with ok set to
      * true bypassing any finally blocks.
      */
+    SAVE_SP_AND_PC(fp);
     ok &= js_UnwindScope(cx, fp, 0, ok || cx->throwing);
-    JS_ASSERT(regs.sp == fp->spbase);
+    JS_ASSERT(fp->sp == fp->spbase);
+    RESTORE_SP(fp);
 
     if (inlineCallCount)
         goto inline_return;
 
   exit:
     /*
      * At this point we are inevitably leaving an interpreted function or a
      * top-level script, and returning to one of:
@@ -6886,53 +7050,38 @@ interrupt:
      * (b) a js_Execute activation;
      * (c) a generator (SendToGenerator, jsiter.c).
      *
      * We must not be in an inline frame. The check above ensures that for the
      * error case and for a normal return, the code jumps directly to parent's
      * frame pc.
      */
     JS_ASSERT(inlineCallCount == 0);
-
-    JS_ASSERT(fp->spbase);
-    JS_ASSERT(fp->regs == &regs);
+    JS_ASSERT(JS_PROPERTY_CACHE(cx).disabled == fp->pcDisabledSave);
+
     if (JS_LIKELY(mark != NULL)) {
         JS_ASSERT(!fp->blockChain);
         JS_ASSERT(!js_IsActiveWithOrBlock(cx, fp->scopeChain, 0));
         JS_ASSERT(!(fp->flags & JSFRAME_GENERATOR));
-        fp->spbase = NULL;
-        fp->regs = NULL;
+        JS_ASSERT(fp->spbase);
+        JS_ASSERT(fp->spbase <= fp->sp);
+        fp->sp = fp->spbase = NULL;
         js_FreeRawStack(cx, mark);
-    } else {
-        JS_ASSERT(fp->flags & JSFRAME_GENERATOR);
-        if (fp->flags & JSFRAME_YIELDING) {
-            JSGenerator *gen;
-
-            gen = FRAME_TO_GENERATOR(fp);
-            gen->savedRegs = regs;
-            gen->frame.regs = &gen->savedRegs;
-            JS_PROPERTY_CACHE(cx).disabled -= js_CountWithBlocks(cx, fp);
-            JS_ASSERT(JS_PROPERTY_CACHE(cx).disabled >= 0);
-        } else {
-            fp->regs = NULL;
-            fp->spbase = NULL;
-        }
     }
 
-  exit2:
-    JS_ASSERT(JS_PROPERTY_CACHE(cx).disabled == fp->pcDisabledSave);
     if (cx->version == currentVersion && currentVersion != originalVersion)
         js_SetVersion(cx, originalVersion);
     cx->interpLevel--;
     return ok;
 
   atom_not_defined:
     {
         const char *printable;
 
+        ASSERT_SAVED_SP_AND_PC(fp);
         printable = js_AtomToPrintableString(cx, atom);
         if (printable)
             js_ReportIsNotDefined(cx, printable);
         goto error;
     }
 }
 
 #endif /* !defined js_invoke_c__ */
--- a/js/src/jsinterp.h
+++ b/js/src/jsinterp.h
@@ -44,33 +44,29 @@
  * JS interpreter interface.
  */
 #include "jsprvtd.h"
 #include "jspubtd.h"
 #include "jsopcode.h"
 
 JS_BEGIN_EXTERN_C
 
-typedef struct JSFrameRegs {
-    jsbytecode      *pc;            /* program counter */
-    jsval           *sp;            /* stack pointer */
-} JSFrameRegs;
-
 /*
  * JS stack frame, may be allocated on the C stack by native callers.  Always
  * allocated on cx->stackPool for calls from the interpreter to an interpreted
  * function.
  *
  * NB: This struct is manually initialized in jsinterp.c and jsiter.c.  If you
  * add new members, update both files.  But first, try to remove members.  The
  * sharp* and xml* members should be moved onto the stack as local variables
  * with well-known slots, if possible.
  */
 struct JSStackFrame {
-    JSFrameRegs     *regs;
+    jsval           *sp;            /* stack pointer */
+    jsbytecode      *pc;            /* program counter */
     jsval           *spbase;        /* operand stack base */
     JSObject        *callobj;       /* lazily created Call object */
     JSObject        *argsobj;       /* lazily created arguments object */
     JSObject        *varobj;        /* variables object, where vars go */
     JSObject        *callee;        /* function or script object */
     JSScript        *script;        /* script being interpreted */
     JSFunction      *fun;           /* function being called or null */
     JSObject        *thisp;         /* "this" pointer if in method */
@@ -90,17 +86,17 @@ struct JSStackFrame {
     JSObject        *blockChain;    /* active compile-time block scopes */
 #ifdef DEBUG
     jsrefcount      pcDisabledSave; /* for balanced property cache control */
 #endif
 };
 
 typedef struct JSInlineFrame {
     JSStackFrame    frame;          /* base struct */
-    JSFrameRegs     callerRegs;     /* parent's frame registers */
+    jsval           *rvp;           /* ptr to caller's return value slot */
     void            *mark;          /* mark before inline frame */
     void            *hookData;      /* debugger call hook data */
     JSVersion       callerVersion;  /* dynamic version of calling script */
 } JSInlineFrame;
 
 /* JS stack frame flags. */
 #define JSFRAME_CONSTRUCTING   0x01 /* frame is for a constructor invocation */
 #define JSFRAME_INTERNAL       0x02 /* internal call, not invoked by a script */
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -786,22 +786,20 @@ js_NewGenerator(JSContext *cx, JSStackFr
     COPY_STACK_ARRAY(vars, nvars, nvars);
 
 #undef COPY_STACK_ARRAY
 
     /* Initialize or copy virtual machine state. */
     gen->frame.down = NULL;
     gen->frame.annotation = NULL;
     gen->frame.scopeChain = fp->scopeChain;
+    gen->frame.pc = fp->pc;
 
-    gen->frame.spbase = newsp;
-    JS_ASSERT(fp->spbase == fp->regs->sp);
-    gen->savedRegs.sp = newsp;
-    gen->savedRegs.pc = fp->regs->pc;
-    gen->frame.regs = &gen->savedRegs;
+    /* Allocate generating pc and operand stack space. */
+    gen->frame.spbase = gen->frame.sp = newsp;
 
     /* Copy remaining state (XXX sharp* and xml* should be local vars). */
     gen->frame.sharpDepth = 0;
     gen->frame.sharpArray = NULL;
     gen->frame.flags = (fp->flags & ~JSFRAME_ROOTED_ARGV) | JSFRAME_GENERATOR;
     gen->frame.dormantNext = NULL;
     gen->frame.xmlNamespace = NULL;
     gen->frame.blockChain = NULL;
@@ -850,17 +848,17 @@ SendToGenerator(JSContext *cx, JSGenerat
     switch (op) {
       case JSGENOP_NEXT:
       case JSGENOP_SEND:
         if (gen->state == JSGEN_OPEN) {
             /*
              * Store the argument to send as the result of the yield
              * expression.
              */
-            gen->savedRegs.sp[-1] = arg;
+            gen->frame.sp[-1] = arg;
         }
         gen->state = JSGEN_RUNNING;
         break;
 
       case JSGENOP_THROW:
         JS_SetPendingException(cx, arg);
         gen->state = JSGEN_RUNNING;
         break;
--- a/js/src/jsiter.h
+++ b/js/src/jsiter.h
@@ -92,17 +92,16 @@ typedef enum JSGeneratorState {
     JSGEN_CLOSING,  /* close method is doing asynchronous return */
     JSGEN_CLOSED    /* closed, cannot be started or closed again */
 } JSGeneratorState;
 
 struct JSGenerator {
     JSObject            *obj;
     JSGeneratorState    state;
     JSStackFrame        frame;
-    JSFrameRegs         savedRegs;
     JSArena             arena;
     jsval               stack[1];
 };
 
 #define FRAME_TO_GENERATOR(fp) \
     ((JSGenerator *) ((uint8 *)(fp) - offsetof(JSGenerator, frame)))
 
 extern JSObject *
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -1141,18 +1141,17 @@ js_ComputeFilename(JSContext *cx, JSStac
 
     flags = JS_GetScriptFilenameFlags(caller->script);
     if ((flags & JSFILENAME_PROTECTED) &&
         strcmp(principals->codebase, "[System Principal]")) {
         *linenop = 0;
         return principals->codebase;
     }
 
-    *linenop = js_PCToLineNumber(cx, caller->script,
-                                 caller->regs ? caller->regs->pc : NULL);
+    *linenop = js_PCToLineNumber(cx, caller->script, caller->pc);
     return caller->script->filename;
 }
 
 static JSBool
 obj_eval(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 {
     JSStackFrame *fp, *caller;
     JSBool indirectCall;
@@ -1166,18 +1165,18 @@ obj_eval(JSContext *cx, JSObject *obj, u
 #if JS_HAS_EVAL_THIS_SCOPE
     JSObject *callerScopeChain = NULL, *callerVarObj = NULL;
     JSObject *setCallerScopeChain = NULL;
     JSBool setCallerVarObj = JS_FALSE;
 #endif
 
     fp = cx->fp;
     caller = JS_GetScriptedCaller(cx, fp);
-    JS_ASSERT(!caller || caller->regs);
-    indirectCall = (caller && *caller->regs->pc != JSOP_EVAL);
+    JS_ASSERT(!caller || caller->pc);
+    indirectCall = (caller && *caller->pc != JSOP_EVAL);
 
     /*
      * Ban all indirect uses of eval (global.foo = eval; global.foo(...)) and
      * calls that attempt to use a non-global object as the "with" object in
      * the former indirect case.
      */
     scopeobj = OBJ_GET_PARENT(cx, obj);
     if (scopeobj) {
@@ -1955,27 +1954,27 @@ js_PutBlockObject(JSContext *cx, JSBool 
 
     fp = cx->fp;
     obj = fp->scopeChain;
     JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_BlockClass);
     JS_ASSERT(OBJ_GET_PRIVATE(cx, obj) == cx->fp);
 
     /* Block and its locals must be on the current stack for GC safety. */
     JS_ASSERT((size_t) OBJ_BLOCK_DEPTH(cx, obj) <=
-              (size_t) (fp->regs->sp - fp->spbase));
+              (size_t) (fp->sp - fp->spbase));
 
     if (normalUnwind) {
         depth = OBJ_BLOCK_DEPTH(cx, obj);
         for (sprop = OBJ_SCOPE(obj)->lastProp; sprop; sprop = sprop->parent) {
             if (sprop->getter != js_BlockClass.getProperty)
                 continue;
             if (!(sprop->flags & SPROP_HAS_SHORTID))
                 continue;
             slot = depth + (uintN) sprop->shortid;
-            JS_ASSERT(slot < (size_t) (fp->regs->sp - fp->spbase));
+            JS_ASSERT(slot < (size_t) (fp->sp - fp->spbase));
             if (!js_DefineNativeProperty(cx, obj, sprop->id,
                                          fp->spbase[slot], NULL, NULL,
                                          JSPROP_ENUMERATE | JSPROP_PERMANENT,
                                          SPROP_HAS_SHORTID, sprop->shortid,
                                          NULL)) {
                 /*
                  * Stop adding properties if we failed due to out-of-memory or
                  * other quit-asap errors.
@@ -3265,18 +3264,18 @@ js_LookupPropertyWithFlags(JSContext *cx
                 generation = cx->resolvingTable->generation;
 
                 /* Null *propp here so we can test it at cleanup: safely. */
                 *propp = NULL;
 
                 if (clasp->flags & JSCLASS_NEW_RESOLVE) {
                     newresolve = (JSNewResolveOp)resolve;
                     if (!(flags & JSRESOLVE_CLASSNAME) &&
-                        cx->fp && cx->fp->regs) {
-                        pc = cx->fp->regs->pc;
+                        cx->fp &&
+                        (pc = cx->fp->pc)) {
                         cs = &js_CodeSpec[*pc];
                         format = cs->format;
                         if (JOF_MODE(format) != JOF_NAME)
                             flags |= JSRESOLVE_QUALIFIED;
                         if ((format & JOF_ASSIGNING) ||
                             (cx->fp->flags & JSFRAME_ASSIGNING)) {
                             flags |= JSRESOLVE_ASSIGNING;
                         } else {
@@ -3463,20 +3462,20 @@ js_FindIdentifierBase(JSContext *cx, jsi
      * Look for id's property along the "with" statement chain and the
      * statically-linked scope chain.
      */
     if (js_FindPropertyHelper(cx, id, &obj, &pobj, &prop, &entry) < 0)
         return NULL;
     if (prop) {
         OBJ_DROP_PROPERTY(cx, pobj, prop);
 
-        JS_ASSERT_IF(entry,
-                     entry->kpc == ((PCVCAP_TAG(entry->vcap) > 1)
-                                    ? (jsbytecode *) JSID_TO_ATOM(id)
-                                    : cx->fp->regs->pc));
+        JS_ASSERT(!entry ||
+                  entry->kpc == ((PCVCAP_TAG(entry->vcap) > 1)
+                                 ? (jsbytecode *) JSID_TO_ATOM(id)
+                                 : cx->fp->pc));
         return obj;
     }
 
     /*
      * Use the top-level scope from the scope chain, which won't end in the
      * same scope as cx->globalObject for cross-context function calls.
      */
     JS_ASSERT(obj);
@@ -3625,21 +3624,20 @@ js_GetPropertyHelper(JSContext *cx, JSOb
             PCMETER(JS_PROPERTY_CACHE(cx).nofills++);
             *entryp = NULL;
         }
 
         /*
          * Give a strict warning if foo.bar is evaluated by a script for an
          * object foo with no property named 'bar'.
          */
-        if (JSVAL_IS_VOID(*vp) && cx->fp && cx->fp->regs) {
+        if (JSVAL_IS_VOID(*vp) && cx->fp && (pc = cx->fp->pc)) {
             JSOp op;
             uintN flags;
 
-            pc = cx->fp->regs->pc;
             op = (JSOp) *pc;
             if (op == JSOP_GETXPROP) {
                 flags = JSREPORT_ERROR;
             } else {
                 if (!JS_HAS_STRICT_OPTION(cx) ||
                     (op != JSOP_GETPROP && op != JSOP_GETELEM)) {
                     return JS_TRUE;
                 }
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -1782,17 +1782,17 @@ Decompile(SprintStack *ss, jsbytecode *p
             /*
              * Rewrite non-get ops to their "get" format if the error is in
              * the bytecode at pc, so we don't decompile more than the error
              * expression.
              */
             for (fp = cx->fp; fp && !fp->script; fp = fp->down)
                 continue;
             format = cs->format;
-            if (((fp && fp->regs && pc == fp->regs->pc) ||
+            if (((fp && pc == fp->pc) ||
                  (pc == startpc && cs->nuses != 0)) &&
                 format & (JOF_SET|JOF_DEL|JOF_INCDEC|JOF_IMPORT|JOF_FOR|
                           JOF_VARPROP)) {
                 mode = JOF_MODE(format);
                 if (mode == JOF_NAME) {
                     /*
                      * JOF_NAME does not imply JOF_ATOM, so we must check for
                      * the QARG and QVAR format types, and translate those to
@@ -4780,81 +4780,81 @@ js_DecompileFunction(JSPrinter *jp)
 
 char *
 js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v,
                            JSString *fallback)
 {
     JSStackFrame *fp;
     jsbytecode *pc;
     JSScript *script;
-    JSFrameRegs *regs;
     intN pcdepth;
     jsval *sp;
     char *name;
 
     JS_ASSERT(spindex < 0 ||
               spindex == JSDVG_IGNORE_STACK ||
               spindex == JSDVG_SEARCH_STACK);
 
     for (fp = cx->fp; fp && !fp->script; fp = fp->down)
         continue;
-    if (!fp || !fp->regs)
+    if (!fp)
         goto do_fallback;
 
+    pc = fp->pc;
+    if (!pc)
+        goto do_fallback;
     script = fp->script;
-    regs = fp->regs;
-    pc = regs->pc;
     if (pc < script->main || script->code + script->length <= pc) {
         JS_NOT_REACHED("bug");
         goto do_fallback;
     }
 
     if (spindex != JSDVG_IGNORE_STACK) {
         jsbytecode **pcstack;
 
         /*
          * Prepare computing pcstack containing pointers to opcodes that
          * populated interpreter's stack with its current content.
          */
         pcstack = (jsbytecode **)
                   JS_malloc(cx, script->depth * sizeof *pcstack);
         if (!pcstack)
             return NULL;
-        pcdepth = ReconstructPCStack(cx, script, regs->pc, pcstack);
+        pcdepth = ReconstructPCStack(cx, script, fp->pc, pcstack);
         if (pcdepth < 0)
             goto release_pcstack;
 
         if (spindex != JSDVG_SEARCH_STACK) {
             JS_ASSERT(spindex < 0);
             pcdepth += spindex;
             if (pcdepth < 0)
                 goto release_pcstack;
             pc = pcstack[pcdepth];
         } else {
             /*
              * We search from fp->sp to base to find the most recently
              * calculated value matching v under assumption that it is
              * it that caused exception, see bug 328664.
              */
-            JS_ASSERT((size_t) (regs->sp - fp->spbase) <= script->depth);
-            sp = regs->sp;
+            JS_ASSERT((size_t) (fp->sp - fp->spbase) <= fp->script->depth);
+            sp = fp->sp;
             do {
                 if (sp == fp->spbase) {
                     pcdepth = -1;
                     goto release_pcstack;
                 }
             } while (*--sp != v);
 
             if (sp >= fp->spbase + pcdepth) {
                 /*
                  * This happens when the value comes from a temporary slot
                  * that the interpreter uses for GC roots. Assume that it is
                  * fp->pc that caused the exception.
                  */
-                pc = regs->pc;
+                pc = fp->pc;
             } else {
                 pc = pcstack[sp - fp->spbase];
             }
         }
 
       release_pcstack:
         JS_free(cx, pcstack);
         if (pcdepth < 0)
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -1206,26 +1206,25 @@ match_or_replace(JSContext *cx,
              * MODE_MATCH implies str_match is being called from a script or a
              * scripted function.  If the caller cares only about testing null
              * vs. non-null return value, optimize away the array object that
              * would normally be returned in *vp.
              */
             JSStackFrame *fp;
 
             /* Skip Function.prototype.call and .apply frames. */
-            for (fp = cx->fp; fp && !fp->regs; fp = fp->down)
+            for (fp = cx->fp; fp && !fp->pc; fp = fp->down)
                 JS_ASSERT(!fp->script);
 
             /* Assume a full array result is required, then prove otherwise. */
             test = JS_FALSE;
             if (fp) {
-                JS_ASSERT(*fp->regs->pc == JSOP_CALL ||
-                          *fp->regs->pc == JSOP_NEW);
-                JS_ASSERT(js_CodeSpec[*fp->regs->pc].length == 3);
-                switch (fp->regs->pc[3]) {
+                JS_ASSERT(*fp->pc == JSOP_CALL || *fp->pc == JSOP_NEW);
+                JS_ASSERT(js_CodeSpec[*fp->pc].length == 3);
+                switch (fp->pc[3]) {
                   case JSOP_POP:
                   case JSOP_IFEQ:
                   case JSOP_IFNE:
                   case JSOP_IFEQX:
                   case JSOP_IFNEX:
                     test = JS_TRUE;
                     break;
                   default:;
--- a/js/src/jsxml.cpp
+++ b/js/src/jsxml.cpp
@@ -1997,25 +1997,25 @@ ParseXMLSource(JSContext *cx, JSString *
     js_strncpy(chars + offset, srcp, srclen);
     offset += srclen;
     dstlen = length - offset + 1;
     js_InflateStringToBuffer(cx, suffix, constrlen(suffix), chars + offset,
                              &dstlen);
     chars [offset + dstlen] = 0;
 
     xml = NULL;
-    for (fp = cx->fp; fp && !fp->regs; fp = fp->down)
+    for (fp = cx->fp; fp && !fp->pc; fp = fp->down)
         JS_ASSERT(!fp->script);
     filename = NULL;
     lineno = 1;
     if (fp) {
-        op = (JSOp) *fp->regs->pc;
+        op = (JSOp) *fp->pc;
         if (op == JSOP_TOXML || op == JSOP_TOXMLLIST) {
             filename = fp->script->filename;
-            lineno = js_PCToLineNumber(cx, fp->script, fp->regs->pc);
+            lineno = js_PCToLineNumber(cx, fp->script, fp->pc);
             for (endp = srcp + srclen; srcp < endp; srcp++) {
                 if (*srcp == '\n')
                     --lineno;
             }
         }
     }
 
     if (!js_InitParseContext(cx, &pc, NULL, chars, length, NULL,
@@ -8276,17 +8276,17 @@ js_InitXMLFilterClass(JSContext *cx, JSO
 JSBool
 js_StepXMLListFilter(JSContext *cx, JSBool initialized)
 {
     jsval *sp;
     JSObject *obj, *filterobj, *resobj, *kidobj;
     JSXML *xml, *list;
     JSXMLFilter *filter;
 
-    sp = cx->fp->regs->sp;
+    sp = cx->fp->sp;
     if (!initialized) {
         /*
          * We haven't iterated yet, so initialize the filter based on the
          * value stored in sp[-2].
          */
         if (!VALUE_IS_XML(cx, sp[-2])) {
             js_ReportValueError(cx, JSMSG_NON_XML_FILTER, -2, sp[-2], NULL);
             return JS_FALSE;
--- a/js/src/liveconnect/nsCLiveconnect.cpp
+++ b/js/src/liveconnect/nsCLiveconnect.cpp
@@ -182,16 +182,17 @@ AutoPushJSContext::AutoPushJSContext(nsI
                                                               jsprinc, "anonymous", 0, nsnull,
                                                               "", 0, "", 1);
             JSPRINCIPALS_DROP(cx, jsprinc);
 
             if (fun)
             {
                 mFrame.fun = fun;
                 mFrame.script = JS_GetFunctionScript(cx, fun);
+                mFrame.pc = mFrame.script->code;
                 mFrame.callee = JS_GetFunctionObject(fun);
                 mFrame.scopeChain = JS_GetParent(cx, mFrame.callee);
                 mFrame.down = cx->fp;
                 cx->fp = &mFrame;
             }
             else
                 mPushResult = NS_ERROR_OUT_OF_MEMORY;
         }
--- a/js/tests/js1_5/Array/regress-157652.js
+++ b/js/tests/js1_5/Array/regress-157652.js
@@ -118,28 +118,38 @@ var gTestfile = 'regress-157652.js';
 var BUGNUMBER = 157652;
 var summary = "Testing that Array.sort() doesn't crash on very large arrays";
 var expect = 'No Crash';
 var actual = 'No Crash';
 
 printBugNumber(BUGNUMBER);
 printStatus(summary);
 
+expectExitCode(0);
 expectExitCode(5);
 
 var IN_RHINO = inRhino();
 
-if (!IN_RHINO)
+try
 {
-  var a1=Array(0xFFFFFFFF);
-  a1.sort();
-  a1 = null;
+  if (!IN_RHINO)
+  {
+    var a1=Array(0xFFFFFFFF);
+    a1.sort();
+    a1 = null;
+  }
+
+  var a2 = Array(0x40000000);
+  a2.sort();
+  a2=null;
+
+  var a3=Array(0x10000000/4);
+  a3.sort();
+  a3=null;
+}
+catch(ex)
+{
+  // handle changed 1.9 branch behavior. see bug 422348
+  expect = 'InternalError: allocation size overflow';
+  actual = ex + '';
 }
 
-var a2 = Array(0x40000000);
-a2.sort();
-a2=null;
-
-var a3=Array(0x10000000/4);
-a3.sort();
-a3=null;
-
 reportCompare(expect, actual, summary);
--- a/js/tests/js1_5/Function/regress-338001.js
+++ b/js/tests/js1_5/Function/regress-338001.js
@@ -45,22 +45,31 @@ var expect = 'No Crash';
 printBugNumber(BUGNUMBER);
 printStatus (summary);
 
 expectExitCode(0);
 expectExitCode(5);
 
 var fe="f";
 
-for (i=0; i<25; i++)
-  fe += fe;
+try
+{
+  for (i=0; i<25; i++)
+    fe += fe;
 
-var fu=new Function(
-  fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe,
-  fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe,
-  fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe,
-  fe, fe, fe, fe, fe, fe, fe, fe, fe, fe,
-  "done"
-  );
+  var fu=new Function(
+    fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe,
+    fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe,
+    fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe,
+    fe, fe, fe, fe, fe, fe, fe, fe, fe, fe,
+    "done"
+    );
+}
+catch(ex)
+{
+  // handle changed 1.9 branch behavior. see bug 422348
+  expect = 'InternalError: allocation size overflow';
+  actual = ex + '';
+}
  
 print('Done');
 
 reportCompare(expect, actual, summary);
--- a/js/tests/js1_5/Regress/regress-303213.js
+++ b/js/tests/js1_5/Regress/regress-303213.js
@@ -41,38 +41,48 @@ var BUGNUMBER = 303213;
 var summary = 'integer overflow in js';
 var actual = 'No Crash';
 var expect = 'No Crash';
 
 printBugNumber(BUGNUMBER);
 printStatus (summary);
 printStatus('This bug passes if no crash occurs');
 
+expectExitCode(0);
 expectExitCode(5);
 
-var s=String.fromCharCode(257);
-
-var ki="";
-var me="";
-for (i = 0; i < 1024; i++)
+try
 {
-  ki = ki + s;
-}
+  var s=String.fromCharCode(257);
+
+  var ki="";
+  var me="";
+  for (i = 0; i < 1024; i++)
+  {
+    ki = ki + s;
+  }
 
-for (i = 0; i < 1024; i++)
-{
-  me = me + ki;
+  for (i = 0; i < 1024; i++)
+  {
+    me = me + ki;
+  }
+
+  var ov = s;
+
+  for (i = 0; i < 28; i++)
+    ov += ov;
+
+  for (i = 0; i < 88; i++)
+    ov += me;
+
+  printStatus("done generating");
+  var eov = escape(ov);
+  printStatus("done escape");
+  printStatus(eov);
 }
-
-var ov = s;
-
-for (i = 0; i < 28; i++)
-  ov += ov;
-
-for (i = 0; i < 88; i++)
-  ov += me;
-
-printStatus("done generating");
-var eov = escape(ov);
-printStatus("done escape");
-printStatus(eov);
+catch(ex)
+{
+  // handle changed 1.9 branch behavior. see bug 422348
+  expect = 'InternalError: allocation size overflow';
+  actual = ex + '';
+}
  
 reportCompare(expect, actual, summary);
--- a/js/tests/public-failures.txt
+++ b/js/tests/public-failures.txt
@@ -129,20 +129,19 @@ TEST_ID=ecma_3/RegExp/regress-375715-04.
 TEST_ID=ecma_3/extensions/regress-274152.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=(browser|shell), TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=Do not ignore unicode format-control characters: `[`0`-`2`]` expected: SyntaxError: illegal character actual:  reason: Expected value 'SyntaxError: illegal character', Actual value ''
 TEST_ID=ecma_3/extensions/regress-368516.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=(browser|shell), TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=Ignore unicode BOM characters: `[`0`-`1`]` expected: No Error actual: SyntaxError: illegal character reason: Expected value 'No Error', Actual value 'SyntaxError: illegal character'
 TEST_ID=js1_2/function/regexparg-1.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=(browser|shell), TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=typeof f(/abc/) expected: object actual: function reason: wrong value
 TEST_ID=js1_2/function/regexparg-1.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=(browser|shell), TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=typeof new f(/abc/) expected: object actual: function reason: wrong value
 TEST_ID=js1_5/Array/11.1.4.js, TEST_BRANCH=(1.8.1|1.9.0), TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=(browser|shell), TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=Elisons in Array literals should not be enumed Section 1 of test -  [,1]  expected: 1 actual: 01 reason: Expected value '1', Actual value '01'
 TEST_ID=js1_5/Array/11.1.4.js, TEST_BRANCH=(1.8.1|1.9.0), TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=(browser|shell), TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=Elisons in Array literals should not be enumed Section 2 of test -  [,,1]  expected: 2 actual: 012 reason: Expected value '2', Actual value '012'
 TEST_ID=js1_5/Array/11.1.4.js, TEST_BRANCH=(1.8.1|1.9.0), TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=(browser|shell), TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=Elisons in Array literals should not be enumed Section 4 of test -  [1,,]  expected: 0 actual: 01 reason: Expected value '0', Actual value '01'
 TEST_ID=js1_5/Array/regress-101964.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=(browser|shell), TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=Section 1 of test -  expected: Truncation took less than `[`0`-`9`]``+` ms actual: Truncation took `[`0`-`9`]``+` ms reason: Expected value 'Truncation took less than `[`0`-`9`]``+` ms', Actual value 'Truncation took `[`0`-`9`]``+` ms'
-TEST_ID=js1_5/Array/regress-157652.js, TEST_BRANCH=(1.8.1|1.9.0), TEST_RESULT=FAILED, TEST_BUILDTYPE=debug, TEST_TYPE=browser, TEST_OS=(linux|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`.``*`/js1_5/Array/regress-157652.js:`.``*`: out of memory
-TEST_ID=js1_5/Array/regress-157652.js, TEST_BRANCH=(1.8.1|1.9.0), TEST_RESULT=FAILED, TEST_BUILDTYPE=opt, TEST_TYPE=browser, TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=BUGNUMBER: 157652; STATUS: Testing that Array.sort() doesn't crash on very large arrays; --- NOTE: IN THIS TESTCASE, WE EXPECT EXIT CODE 5 ---
+TEST_ID=js1_5/Array/regress-157652.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=debug, TEST_TYPE=browser, TEST_OS=(linux|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`.``*`/js1_5/Array/regress-157652.js:`.``*`: out of memory
 TEST_ID=js1_5/Array/regress-157652.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=debug, TEST_TYPE=browser, TEST_OS=mac, TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`.``*`/Array/regress-157652.js:`.``*`: out of memory
-TEST_ID=js1_5/Array/regress-157652.js, TEST_BRANCH=1.9.0, TEST_RESULT=FAILED, TEST_BUILDTYPE=debug, TEST_TYPE=browser, TEST_OS=(mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`.``*`/js1_5/Array/regress-157652.js:`.``*`: out of memory
+TEST_ID=js1_5/Array/regress-157652.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=opt, TEST_TYPE=browser, TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=BUGNUMBER: 157652; STATUS: Testing that Array.sort() doesn't crash on very large arrays; --- NOTE: IN THIS TESTCASE, WE EXPECT EXIT CODE 0 ---; --- NOTE: IN THIS TESTCASE, WE EXPECT EXIT CODE 5 ---
 TEST_ID=js1_5/Array/regress-330812.js, TEST_BRANCH=(1.8.1|1.9.0), TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=shell, TEST_OS=win32, TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=EXIT STATUS: CRASHED `.``*`/js1_5/Array/regress-330812.js:`.``*`: out of memory
 TEST_ID=js1_5/Array/regress-330812.js, TEST_BRANCH=(1.8.1|1.9.0), TEST_RESULT=FAILED, TEST_BUILDTYPE=debug, TEST_TYPE=browser, TEST_OS=(mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`.``*`/js1_5/Array/regress-330812.js:`.``*`: out of memory
 TEST_ID=js1_5/Array/regress-330812.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=shell, TEST_OS=mac, TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=EXIT STATUS: TIMED OUT
 TEST_ID=js1_5/Array/regress-330812.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=debug, TEST_TYPE=(browser|shell), TEST_OS=linux, TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`(`EXIT STATUS: TIMED OUT`|``.``*`/js1_5/Array/regress-330812.js:`.``*`: out of memory`)`
 TEST_ID=js1_5/Array/regress-330812.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=opt, TEST_TYPE=browser, TEST_OS=(mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=BUGNUMBER: 330812; STATUS: Making Array(1<<29).sort() less problematic; --- NOTE: IN THIS TESTCASE, WE EXPECT EXIT CODE 0 ---; --- NOTE: IN THIS TESTCASE, WE EXPECT EXIT CODE 3 ---; STATUS: This test passes if the browser does not hang or crash; STATUS: This test expects exit code 0 or 3 to indicate out of memory
 TEST_ID=js1_5/Array/regress-330812.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=opt, TEST_TYPE=browser, TEST_OS=linux, TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`(`EXIT STATUS: TIMED OUT`|``.``*`/js1_5/Array/regress-330812.js:`.``*`: out of memory`|`BUGNUMBER: 330812; STATUS: Making Array(1<<29).sort() less problematic; --- NOTE: IN THIS TESTCASE, WE EXPECT EXIT CODE 0 ---; --- NOTE: IN THIS TESTCASE, WE EXPECT EXIT CODE 3 ---; STATUS: This test passes if the browser does not hang or crash; STATUS: This test expects exit code 0 or 3 to indicate out of memory`)`
 TEST_ID=js1_5/Array/regress-330812.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=opt, TEST_TYPE=shell, TEST_OS=linux, TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`(`EXIT STATUS: TIMED OUT`|``.``*`/js1_5/Array/regress-330812.js:`.``*`: out of memory`)`
 TEST_ID=js1_5/Array/regress-330812.js, TEST_BRANCH=1.9.0, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=shell, TEST_OS=mac, TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`.``*`/js1_5/Array/regress-330812.js:`.``*`: out of memory
@@ -150,20 +149,18 @@ TEST_ID=js1_5/Array/regress-330812.js, T
 TEST_ID=js1_5/Array/regress-330812.js, TEST_BRANCH=1.9.0, TEST_RESULT=FAILED, TEST_BUILDTYPE=debug, TEST_TYPE=browser, TEST_OS=win32, TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`.``*`/js1_5/Array/regress-330812.js:`.``*`: out of memory
 TEST_ID=js1_5/Array/regress-330812.js, TEST_BRANCH=1.9.0, TEST_RESULT=FAILED, TEST_BUILDTYPE=opt, TEST_TYPE=browser, TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=BUGNUMBER: 330812; STATUS: Making Array(1<<29).sort() less problematic; --- NOTE: IN THIS TESTCASE, WE EXPECT EXIT CODE 0 ---; --- NOTE: IN THIS TESTCASE, WE EXPECT EXIT CODE 3 ---; STATUS: This test passes if the browser does not hang or crash; STATUS: This test expects exit code 0 or 3 to indicate out of memory
 TEST_ID=js1_5/Array/regress-330812.js, TEST_BRANCH=1.9.0, TEST_RESULT=FAILED, TEST_BUILDTYPE=opt, TEST_TYPE=shell, TEST_OS=linux, TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=EXIT STATUS: CRASHED 5 `.``*`/js1_5/Array/regress-330812.js:`.``*`: out of memory
 TEST_ID=js1_5/Array/regress-350256-03.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=(browser|shell), TEST_OS=win32, TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=EXIT STATUS: TIMED OUT
 TEST_ID=js1_5/Array/regress-350256-03.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=debug, TEST_TYPE=(browser|shell), TEST_OS=mac, TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=EXIT STATUS: TIMED OUT
 TEST_ID=js1_5/Array/regress-350256-03.js, TEST_BRANCH=1.9.0, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=(browser|shell), TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`.``*`/js1_5/Array/regress-350256-03.js:`.``*`: `(`InternalError: `)``?`script stack space quota is exhausted
 TEST_ID=js1_5/Error/regress-354246.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=(browser|shell), TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`.``*`reason: `.``*`/js1_5/Error/regress-354246.js:`.``*`: x is not defined
 TEST_ID=js1_5/Expressions/regress-394673.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=(browser|shell), TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`.``*``(`InternalError:`|`reason:`)``?` too much recursion
-TEST_ID=js1_5/Function/regress-338001.js, TEST_BRANCH=(1.8.1|1.9.0), TEST_RESULT=FAILED, TEST_BUILDTYPE=debug, TEST_TYPE=browser, TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`.``*`/js1_5/Function/regress-338001.js:`.``*`: out of memory
-TEST_ID=js1_5/Function/regress-338001.js, TEST_BRANCH=(1.8.1|1.9.0), TEST_RESULT=FAILED, TEST_BUILDTYPE=opt, TEST_TYPE=browser, TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=BUGNUMBER: 338001; STATUS: integer overflow in jsfun.c:Function; --- NOTE: IN THIS TESTCASE, WE EXPECT EXIT CODE 0 ---; --- NOTE: IN THIS TESTCASE, WE EXPECT EXIT CODE 5 ---
-TEST_ID=js1_5/Function/regress-338001.js, TEST_BRANCH=1.9.0, TEST_RESULT=FAILED, TEST_BUILDTYPE=debug, TEST_TYPE=browser, TEST_OS=win32, TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`.``*`/js1_5/Function/regress-338001.js:`.``*`: out of memory
-TEST_ID=js1_5/Function/regress-338001.js, TEST_BRANCH=1.9.0, TEST_RESULT=FAILED, TEST_BUILDTYPE=opt, TEST_TYPE=browser, TEST_OS=win32, TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=BUGNUMBER: 338001; STATUS: integer overflow in jsfun.c:Function; --- NOTE: IN THIS TESTCASE, WE EXPECT EXIT CODE 0 ---; --- NOTE: IN THIS TESTCASE, WE EXPECT EXIT CODE 5 ---
+TEST_ID=js1_5/Function/regress-338001.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=debug, TEST_TYPE=browser, TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`.``*`/js1_5/Function/regress-338001.js:`.``*`: out of memory
+TEST_ID=js1_5/Function/regress-338001.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=opt, TEST_TYPE=browser, TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=BUGNUMBER: 338001; STATUS: integer overflow in jsfun.c:Function; --- NOTE: IN THIS TESTCASE, WE EXPECT EXIT CODE 0 ---; --- NOTE: IN THIS TESTCASE, WE EXPECT EXIT CODE 5 ---
 TEST_ID=js1_5/Function/regress-338121-01.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=shell, TEST_OS=(mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=EXIT STATUS: CRASHED `.``*`/js1_5/Function/regress-338121-01.js:`.``*`: out of memory
 TEST_ID=js1_5/Function/regress-338121-01.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=debug, TEST_TYPE=browser, TEST_OS=(mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`.``*`/js1_5/Function/regress-338121-01.js:`.``*`: out of memory
 TEST_ID=js1_5/Function/regress-338121-01.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=debug, TEST_TYPE=browser, TEST_OS=linux, TEST_MACHINE=.*, TEST_PROCESSORTYPE=i686, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`(`EXIT STATUS: TIMED OUT`|`BUGNUMBER: 338121; STATUS: Issues with JS_ARENA_ALLOCATE_CAST`)`
 TEST_ID=js1_5/Function/regress-338121-01.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=debug, TEST_TYPE=shell, TEST_OS=linux, TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`(`EXIT STATUS: TIMED OUT`|`/js1_5/Function/regress-338121-01.js:`.``*`: InternalError: script stack space quota is exhausted`)`
 TEST_ID=js1_5/Function/regress-338121-01.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=opt, TEST_TYPE=browser, TEST_OS=(mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=BUGNUMBER: 338121; STATUS: Issues with JS_ARENA_ALLOCATE_CAST
 TEST_ID=js1_5/Function/regress-338121-01.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=opt, TEST_TYPE=browser, TEST_OS=mac, TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=BUGNUMBER: 338121; STATUS: Issues with JS_ARENA_ALLOCATE_CAST; firefox-bin`.``*` malloc: *** vm_allocate`.``*` failed (error code=3); firefox-bin`.``*` malloc: *** error: can't allocate region; firefox-bin`.``*` malloc: *** set a breakpoint in szone_error to debug
 TEST_ID=js1_5/Function/regress-338121-01.js, TEST_BRANCH=1.9.0, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=browser, TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`.``*`/js1_5/Function/regress-338121-01.js:`.``*`: `(`InternalError: `)``?`script stack space quota is exhausted
 TEST_ID=js1_5/Function/regress-338121-01.js, TEST_BRANCH=1.9.0, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=shell, TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`.``*`/js1_5/Function/regress-338121-01.js:`.``*`: InternalError: script stack space quota is exhausted
@@ -190,20 +187,19 @@ TEST_ID=js1_5/GC/regress-348532.js, TEST
 TEST_ID=js1_5/GC/regress-348532.js, TEST_BRANCH=(1.8.1|1.9.0), TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=shell, TEST_OS=win32, TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=EXIT STATUS: TIMED OUT
 TEST_ID=js1_5/GC/regress-348532.js, TEST_BRANCH=1.9.0, TEST_RESULT=FAILED, TEST_BUILDTYPE=debug, TEST_TYPE=browser, TEST_OS=linux, TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=EXIT STATUS: TIMED OUT
 TEST_ID=js1_5/GC/regress-383269-01.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=shell, TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`.``*`reason: `.``*`uncaught exception: generate_big_object_graph() leaked
 TEST_ID=js1_5/GC/regress-383269-02.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=shell, TEST_OS=(linux|mac), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`.``*`reason: uncaught exception: generate_big_object_graph() leaked
 TEST_ID=js1_5/GC/regress-383269-02.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=shell, TEST_OS=linux, TEST_MACHINE=.*, TEST_PROCESSORTYPE=athlon, TEST_KERNEL=2.6.18.*el5, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`.``*`reason: `.``*`uncaught exception: generate_big_object_graph() leaked
 TEST_ID=js1_5/GC/regress-383269-02.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=shell, TEST_OS=win32, TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`.``*`reason: `.``*`uncaught exception: generate_big_object_graph() leaked
 TEST_ID=js1_5/Regress/regress-271716-n.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=(browser|shell), TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`(`EXIT STATUS: TIMED OUT`|``.``*`/js1_5/Regress/regress-271716-n.js:`.``*`: out of memory`)`
 TEST_ID=js1_5/Regress/regress-271716-n.js, TEST_BRANCH=1.9.0, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=(browser|shell), TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`(`EXIT STATUS: CRASHED`|`EXIT STATUS: TIMED OUT`|``.``*`/js1_5/Regress/regress-271716-n.js:`.``*`: out of memory`)`
-TEST_ID=js1_5/Regress/regress-303213.js, TEST_BRANCH=(1.8.1|1.9.0), TEST_RESULT=FAILED, TEST_BUILDTYPE=debug, TEST_TYPE=browser, TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`(`EXIT STATUS: TIMED OUT`|``.``*`/js1_5/Regress/regress-303213.js:`.``*`: out of memory`)`
-TEST_ID=js1_5/Regress/regress-303213.js, TEST_BRANCH=(1.8.1|1.9.0), TEST_RESULT=FAILED, TEST_BUILDTYPE=opt, TEST_TYPE=browser, TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=BUGNUMBER: 303213; STATUS: integer overflow in js; STATUS: This bug passes if no crash occurs; --- NOTE: IN THIS TESTCASE, WE EXPECT EXIT CODE 5 ---
-TEST_ID=js1_5/Regress/regress-303213.js, TEST_BRANCH=1.9.0, TEST_RESULT=FAILED, TEST_BUILDTYPE=debug, TEST_TYPE=browser, TEST_OS=linux, TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=EXIT STATUS: TIMED OUT
-TEST_ID=js1_5/Regress/regress-303213.js, TEST_BRANCH=1.9.0, TEST_RESULT=FAILED, TEST_BUILDTYPE=opt, TEST_TYPE=browser, TEST_OS=mac, TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=BUGNUMBER: 303213; STATUS: integer overflow in js; STATUS: This bug passes if no crash occurs; --- NOTE: IN THIS TESTCASE, WE EXPECT EXIT CODE 5 ---; STATUS: done generating
+TEST_ID=js1_5/Regress/regress-303213.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=debug, TEST_TYPE=browser, TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`(`EXIT STATUS: TIMED OUT`|``.``*`/js1_5/Regress/regress-303213.js:`.``*`: out of memory`)`
+TEST_ID=js1_5/Regress/regress-303213.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=opt, TEST_TYPE=browser, TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=BUGNUMBER: 303213; STATUS: integer overflow in js; STATUS: This bug passes if no crash occurs; --- NOTE: IN THIS TESTCASE, WE EXPECT EXIT CODE 0 ---; --- NOTE: IN THIS TESTCASE, WE EXPECT EXIT CODE 5 ---
+TEST_ID=js1_5/Regress/regress-303213.js, TEST_BRANCH=1.9.0, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=browser, TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=EXIT STATUS: TIMED OUT
 TEST_ID=js1_5/Regress/regress-312588.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=(browser|shell), TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`(`EXIT STATUS: CRASHED`|`EXIT STATUS: TIMED OUT`|``.``*`/js1_5/Regress/regress-312588.js:`.``*`: out of memory`)`
 TEST_ID=js1_5/Regress/regress-319384.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=browser, TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`.``*`reason: `.``*`/js1_5/Regress/regress-319384.js:`.``*`: can't convert "foo" to an integer
 TEST_ID=js1_5/Regress/regress-320119.js, TEST_BRANCH=1.9.0, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=(browser|shell), TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=delegating objects and arguments, arity, caller, name: arguments no longer shared expected: false actual: true reason: Expected value 'false', Actual value 'true'
 TEST_ID=js1_5/Regress/regress-320119.js, TEST_BRANCH=1.9.0, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=(browser|shell), TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=delegating objects and arguments, arity, caller, name: arity no longer shared expected: false actual: true reason: Expected value 'false', Actual value 'true'
 TEST_ID=js1_5/Regress/regress-320119.js, TEST_BRANCH=1.9.0, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=(browser|shell), TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=delegating objects and arguments, arity, caller, name: caller no longer shared expected: false actual: true reason: Expected value 'false', Actual value 'true'
 TEST_ID=js1_5/Regress/regress-320119.js, TEST_BRANCH=1.9.0, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=(browser|shell), TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=delegating objects and arguments, arity, caller, name: name no longer shared expected: false actual: true reason: Expected value 'false', Actual value 'true'
 TEST_ID=js1_5/Regress/regress-328897.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=browser, TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`.``*`reason: :0: uncaught exception: Permission denied to get property UnnamedClass.classes
 TEST_ID=js1_5/Regress/regress-328897.js, TEST_BRANCH=1.9.0, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=browser, TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=JS_ReportPendingException should expected: Error actual: No Error reason: Expected value 'Error', Actual value 'No Error'
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -1037,24 +1037,19 @@ nsBlockFrame::Reflow(nsPresContext*     
     }
   }
 
   if (NS_FRAME_IS_NOT_COMPLETE(state.mReflowStatus)) {
     if (GetOverflowLines()) {
       state.mReflowStatus |= NS_FRAME_REFLOW_NEXTINFLOW;
     }
 
-    if (NS_STYLE_OVERFLOW_CLIP == aReflowState.mStyleDisplay->mOverflowX) {
-      state.mReflowStatus = NS_FRAME_COMPLETE;
-    }
-    else {
 #ifdef DEBUG_kipp
-      ListTag(stdout); printf(": block is not complete\n");
+    ListTag(stdout); printf(": block is not complete\n");
 #endif
-    }
   }
 
   CheckFloats(state);
 
   // Place the "marker" (bullet) frame if it is placed next to a block
   // child.
   //
   // According to the CSS2 spec, section 12.6.1, the "marker" box
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -505,18 +505,18 @@ var gCSSProperties = {
 		other_values: [ "fixed" ],
 		invalid_values: []
 	},
 	"background-color": {
 		domProp: "backgroundColor",
 		inherited: false,
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ "transparent", "rgba(255, 127, 15, 0)", "hsla(240, 97%, 50%, 0.0)", "rgba(0, 0, 0, 0)", "rgba(255,255,255,-3.7)" ],
-		other_values: [ "green", "rgb(255, 0, 128)", "rgb(255.0,0.387,3489)", "#fc2", "#96ed2a", "black", "rgba(255,255,0,3)" ],
-		invalid_values: [ "#0", "#00", "#0000", "#00000", "#0000000", "#00000000", "#000000000" ]
+		other_values: [ "green", "rgb(255, 0, 128)", "#fc2", "#96ed2a", "black", "rgba(255,255,0,3)" ],
+		invalid_values: [ "#0", "#00", "#0000", "#00000", "#0000000", "#00000000", "#000000000", "rgb(255.0,0.387,3489)" ]
 	},
 	"background-image": {
 		domProp: "backgroundImage",
 		inherited: false,
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ "none" ],
 		other_values: [ "url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==)", "url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==')", 'url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==")', ],
 		invalid_values: []
--- a/layout/style/test/test_value_computation.html
+++ b/layout/style/test/test_value_computation.html
@@ -33,17 +33,16 @@
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 /** Test for computation of values in property database **/
 
 var gNotAccepted = {
   "-moz-column-width": [ "50%" ],
   "-moz-user-select": [ "auto" ],
-  "background-color": [ "rgb(255.0,0.387,3489)" ],
   "list-style": [ "none disc outside" ],
 };
 
 var gBadComputed = {
   // NS_STYLE_COLUMN_COUNT_AUTO is 0
   "-moz-column-count": [ "0" ],
 
   "clip": [ "rect(auto,auto,auto,auto)" ],
--- a/layout/style/test/test_value_storage.html
+++ b/layout/style/test/test_value_storage.html
@@ -55,17 +55,16 @@ var gShorthandsWithoutCondensingSerializ
   "list-style": true,
   "outline": true,
   "pause": true,
 };
 
 var gNotAccepted = {
   "-moz-column-width": [ "50%" ],
   "-moz-user-select": [ "auto" ],
-  "background-color": [ "rgb(255.0,0.387,3489)" ],
   "list-style": [ "none disc outside" ],
 };
 
 var gSystemFont = {
   "caption": true,
   "icon": true,
   "menu": true,
   "message-box": true,
--- a/tools/release/configs/fx-moz19-staging-bootstrap.cfg
+++ b/tools/release/configs/fx-moz19-staging-bootstrap.cfg
@@ -1,21 +1,21 @@
-version         = 3.0b3
-milestone       = 1.9b3
+version         = 3.0b5
+milestone       = 1.9b5
 # _RCn and _RELEASE will be appended as-needed
-productTag      = FIREFOX_3_0b3
+productTag      = FIREFOX_3_0b5
 # Branch name and pull dates to use for base tag
 branchTag       = HEAD
 #RelbranchOverride = GECKO190_20071207_RELBRANCH
-pullDate        = 2008-01-07 09:00 PST
-l10n_pullDate   = 2008-01-07 09:00 PST
+pullDate        = 2008-03-03 09:00 PST
+l10n_pullDate   = 2008-03-13 09:00 PST
 rc              = 1
 # oldVersion and oldRc refer to the previous release
 oldVersion      = 3.0b4
-oldRc           = 3
+oldRc           = 1
 appName         = browser
 product         = firefox
 # Absolute path to tinderbox build directory
 # The win32 ones are kept short because of a long path issue detailed in
 # bug# 400846
 linux_buildDir       = /builds/tinderbox/Fx-Mozilla1.9-Release
 macosx_buildDir      = /builds/tinderbox/Fx-Mozilla1.9-Release
 win32_buildDir       = /e/fx19rel
--- a/tools/update-packaging/Makefile.in
+++ b/tools/update-packaging/Makefile.in
@@ -46,17 +46,21 @@ include $(DEPTH)/config/autoconf.mk
 
 include $(topsrcdir)/toolkit/mozapps/installer/package-name.mk
 
 # Default output location for update archive
 STAGE_DIR	= $(DIST)/update
 
 ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
 ifdef UNIVERSAL_BINARY
+ifneq (,$(filter %/l10n-stage,$(DIST)))
+PACKAGE_DIR	= $(DIST)/$(MOZ_PKG_APPNAME)/$(MOZ_APP_DISPLAYNAME).app
+else
 PACKAGE_DIR	= $(DIST)/universal/$(MOZ_PKG_APPNAME)/$(MOZ_APP_DISPLAYNAME).app
+endif
 else
 PACKAGE_DIR	= $(DIST)/$(MOZ_PKG_APPNAME)/$(MOZ_APP_DISPLAYNAME).app
 endif
 else
 PACKAGE_DIR	= $(DIST)/$(MOZ_PKG_APPNAME)
 endif
 
 MAR_BIN	= $(DIST)/host/bin/mar$(HOST_BIN_SUFFIX)
--- a/xpcom/io/nsUnicharInputStream.cpp
+++ b/xpcom/io/nsUnicharInputStream.cpp
@@ -219,21 +219,22 @@ nsresult UTF8InputStream::Read(PRUnichar
                                PRUint32 aCount,
                                PRUint32 *aReadCount)
 {
   NS_ASSERTION(mUnicharDataLength >= mUnicharDataOffset, "unsigned madness");
   PRUint32 readCount = mUnicharDataLength - mUnicharDataOffset;
   nsresult errorCode;
   if (0 == readCount) {
     // Fill the unichar buffer
-    readCount = Fill(&errorCode);
-    if (readCount <= 0) {
+    PRInt32 bytesRead = Fill(&errorCode);
+    if (bytesRead <= 0) {
       *aReadCount = 0;
       return errorCode;
     }
+    readCount = bytesRead;
   }
   if (readCount > aCount) {
     readCount = aCount;
   }
   memcpy(aBuf, mUnicharData->GetBuffer() + mUnicharDataOffset,
          readCount * sizeof(PRUnichar));
   mUnicharDataOffset += readCount;
   *aReadCount = readCount;
@@ -245,21 +246,22 @@ UTF8InputStream::ReadSegments(nsWriteUni
                               void* aClosure,
                               PRUint32 aCount, PRUint32 *aReadCount)
 {
   NS_ASSERTION(mUnicharDataLength >= mUnicharDataOffset, "unsigned madness");
   PRUint32 bytesToWrite = mUnicharDataLength - mUnicharDataOffset;
   nsresult rv = NS_OK;
   if (0 == bytesToWrite) {
     // Fill the unichar buffer
-    bytesToWrite = Fill(&rv);
-    if (bytesToWrite <= 0) {
+    PRInt32 bytesRead = Fill(&rv);
+    if (bytesRead <= 0) {
       *aReadCount = 0;
       return rv;
     }
+    bytesToWrite = bytesRead;
   }
   
   if (bytesToWrite > aCount)
     bytesToWrite = aCount;
   
   PRUint32 bytesWritten;
   PRUint32 totalBytesWritten = 0;
 
@@ -287,21 +289,22 @@ NS_IMETHODIMP
 UTF8InputStream::ReadString(PRUint32 aCount, nsAString& aString,
                             PRUint32* aReadCount)
 {
   NS_ASSERTION(mUnicharDataLength >= mUnicharDataOffset, "unsigned madness");
   PRUint32 readCount = mUnicharDataLength - mUnicharDataOffset;
   nsresult errorCode;
   if (0 == readCount) {
     // Fill the unichar buffer
-    readCount = Fill(&errorCode);
-    if (readCount <= 0) {
+    PRInt32 bytesRead = Fill(&errorCode);
+    if (bytesRead <= 0) {
       *aReadCount = 0;
       return errorCode;
     }
+    readCount = bytesRead;
   }
   if (readCount > aCount) {
     readCount = aCount;
   }
   const PRUnichar* buf = reinterpret_cast<const PRUnichar*>(mUnicharData->GetBuffer() +
                                              mUnicharDataOffset);
   aString.Assign(buf, readCount);
 
@@ -345,17 +348,20 @@ PRInt32 UTF8InputStream::Fill(nsresult *
   if (PRInt32(dstLen) > mUnicharData->GetBufferSize()) return 0;
   
   ConvertUTF8toUTF16 converter(mUnicharData->GetBuffer());
   
   nsASingleFragmentCString::const_char_iterator start = mByteData->GetBuffer();
   nsASingleFragmentCString::const_char_iterator end = mByteData->GetBuffer() + srcLen;
             
   copy_string(start, end, converter);
-  NS_ASSERTION(converter.Length() == dstLen, "length mismatch");
+  if (converter.Length() != dstLen) {
+    *aErrorCode = NS_BASE_STREAM_BAD_CONVERSION;
+    return -1;
+  }
                
   mUnicharDataOffset = 0;
   mUnicharDataLength = dstLen;
   mByteDataOffset = srcLen;
   
   return dstLen;
 }