Bug 930625 - Fix some exact rooting hazards in spidermonkey; r=sfink
authorTerrence Cole <terrence@mozilla.com>
Thu, 24 Oct 2013 10:01:38 -0700
changeset 166776 be2e01347abd82173cba282492170c194f9a7119
parent 166775 541750e89771444d80f70a2f47e10f4db1ef417b
child 166777 5775bf2165d2caef104734dbd722b089e9e70b69
push id428
push userbbajaj@mozilla.com
push dateTue, 28 Jan 2014 00:16:25 +0000
treeherdermozilla-release@cd72a7ff3a75 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssfink
bugs930625
milestone27.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 930625 - Fix some exact rooting hazards in spidermonkey; r=sfink
js/src/jit/CodeGenerator.cpp
js/src/jit/IonAnalysis.cpp
js/src/jit/IonAnalysis.h
js/src/jsapi-tests/testNullRoot.cpp
js/src/jsarray.cpp
js/src/jsinfer.cpp
js/src/jsinfer.h
js/src/vm/StructuredClone.cpp
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -5693,17 +5693,17 @@ CodeGenerator::generate()
         return false;
 
     return !masm.oom();
 }
 
 bool
 CodeGenerator::link(JSContext *cx, types::CompilerConstraintList *constraints)
 {
-    JSScript *script = gen->info().script();
+    RootedScript script(cx, gen->info().script());
     ExecutionMode executionMode = gen->info().executionMode();
     JS_ASSERT(!HasIonScript(script, executionMode));
 
     // Check to make sure we didn't have a mid-build invalidation. If so, we
     // will trickle to jit::Compile() and return Method_Skipped.
     types::RecompileInfo recompileInfo;
     if (!types::FinishCompilation(cx, script, executionMode, constraints, &recompileInfo))
         return true;
--- a/js/src/jit/IonAnalysis.cpp
+++ b/js/src/jit/IonAnalysis.cpp
@@ -2053,17 +2053,17 @@ AnalyzePoppedThis(JSContext *cx, types::
 static int
 CmpInstructions(const void *a, const void *b)
 {
     return (*static_cast<MInstruction * const *>(a))->id() -
            (*static_cast<MInstruction * const *>(b))->id();
 }
 
 bool
-jit::AnalyzeNewScriptProperties(JSContext *cx, JSFunction *fun,
+jit::AnalyzeNewScriptProperties(JSContext *cx, HandleFunction fun,
                                 types::TypeObject *type, HandleObject baseobj,
                                 Vector<types::TypeNewScript::Initializer> *initializerList)
 {
     // When invoking 'new' on the specified script, try to find some properties
     // which will definitely be added to the created object before it has a
     // chance to escape and be accessed elsewhere.
 
     if (fun->isInterpretedLazy() && !fun->getOrCreateScript(cx))
--- a/js/src/jit/IonAnalysis.h
+++ b/js/src/jit/IonAnalysis.h
@@ -121,16 +121,16 @@ class LinearSum
     void dump(FILE *) const;
 
   private:
     Vector<LinearTerm, 2, IonAllocPolicy> terms_;
     int32_t constant_;
 };
 
 bool
-AnalyzeNewScriptProperties(JSContext *cx, JSFunction *fun,
+AnalyzeNewScriptProperties(JSContext *cx, HandleFunction fun,
                            types::TypeObject *type, HandleObject baseobj,
                            Vector<types::TypeNewScript::Initializer> *initializerList);
 
 } // namespace jit
 } // namespace js
 
 #endif /* jit_IonAnalysis_h */
--- a/js/src/jsapi-tests/testNullRoot.cpp
+++ b/js/src/jsapi-tests/testNullRoot.cpp
@@ -4,26 +4,26 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "jsapi-tests/tests.h"
 
 BEGIN_TEST(testNullRoot)
 {
-    JSObject *obj = nullptr;
-    CHECK(JS_AddObjectRoot(cx, &obj));
+    JS::RootedObject obj(cx);
+    CHECK(JS_AddObjectRoot(cx, obj.address()));
 
-    JSString *str = nullptr;
-    CHECK(JS_AddStringRoot(cx, &str));
+    JS::RootedString str(cx);
+    CHECK(JS_AddStringRoot(cx, str.address()));
 
-    JSScript *scr = nullptr;
-    CHECK(JS_AddNamedScriptRoot(cx, &scr, "testNullRoot's scr"));
+    JS::RootedScript script(cx);
+    CHECK(JS_AddNamedScriptRoot(cx, script.address(), "testNullRoot's script"));
 
     // This used to crash because obj was nullptr.
     JS_GC(cx->runtime());
 
-    JS_RemoveObjectRoot(cx, &obj);
-    JS_RemoveStringRoot(cx, &str);
-    JS_RemoveScriptRoot(cx, &scr);
+    JS_RemoveObjectRoot(cx, obj.address());
+    JS_RemoveStringRoot(cx, str.address());
+    JS_RemoveScriptRoot(cx, script.address());
     return true;
 }
 END_TEST(testNullRoot)
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -1081,24 +1081,22 @@ ArrayJoin(JSContext *cx, CallArgs &args)
 
     // Steps 2 and 3
     uint32_t length;
     if (!GetLengthProperty(cx, obj, &length))
         return false;
 
     // Steps 4 and 5
     RootedString sepstr(cx, nullptr);
-    JS::Anchor<JSString *> anchor(nullptr);
     const jschar *sepchars;
     size_t seplen;
     if (!Locale && args.hasDefined(0)) {
         sepstr = ToString<CanGC>(cx, args[0]);
         if (!sepstr)
             return false;
-        anchor = sepstr;
         sepchars = sepstr->getChars(cx);
         if (!sepchars)
             return false;
         seplen = sepstr->length();
     } else {
         static const jschar comma = ',';
         sepchars = &comma;
         seplen = 1;
@@ -1123,16 +1121,19 @@ ArrayJoin(JSContext *cx, CallArgs &args)
         if (!ArrayJoinKernel<Locale>(cx, op, obj, length, sb))
             return false;
     } else {
         StringSeparatorOp op(sepchars, seplen);
         if (!ArrayJoinKernel<Locale>(cx, op, obj, length, sb))
             return false;
     }
 
+    // Ensure that sepstr stays alive longer than sepchars.
+    JS_AnchorPtr(sepstr);
+
     // Step 11
     JSString *str = sb.finishString();
     if (!str)
         return false;
     args.rval().setString(str);
     return true;
 }
 
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -921,17 +921,17 @@ class TypeConstraintFreezeStack : public
          */
         cx->compartment()->types.addPendingRecompile(cx, script_);
     }
 };
 
 } /* anonymous namespace */
 
 bool
-types::FinishCompilation(JSContext *cx, JSScript *script, ExecutionMode executionMode,
+types::FinishCompilation(JSContext *cx, HandleScript script, ExecutionMode executionMode,
                          CompilerConstraintList *constraints, RecompileInfo *precompileInfo)
 {
     if (constraints->failed())
         return false;
 
     CompilerOutput co(script, executionMode);
 
     TypeCompartment &types = cx->compartment()->types;
@@ -1363,17 +1363,17 @@ ObjectStateChange(ExclusiveContext *cxAr
             }
         } else {
             JS_ASSERT(!types->constraintList);
         }
     }
 }
 
 static void
-CheckNewScriptProperties(JSContext *cx, TypeObject *type, JSFunction *fun);
+CheckNewScriptProperties(JSContext *cx, TypeObject *type, HandleFunction fun);
 
 namespace {
 
 class ConstraintDataFreezeConfiguredProperty
 {
   public:
     TypeObjectKey *object;
 
@@ -1397,17 +1397,18 @@ class ConstraintDataFreezeConfiguredProp
         // constraints in place which will mark those properties as configured
         // should the definite properties be invalidated.
         TypeObject *type = object->isSingleObject()
                            ? object->asSingleObject()->type()
                            : object->asTypeObject();
         if (type->flags & OBJECT_FLAG_NEW_SCRIPT_REGENERATE) {
             type->flags &= ~OBJECT_FLAG_NEW_SCRIPT_REGENERATE;
             if (type->hasNewScript()) {
-                CheckNewScriptProperties(cx, type, type->newScript()->fun);
+                RootedFunction fun(cx, type->newScript()->fun);
+                CheckNewScriptProperties(cx, type, fun);
             } else {
                 JS_ASSERT(type->flags & OBJECT_FLAG_ADDENDUM_CLEARED);
                 type->flags &= ~OBJECT_FLAG_NEW_SCRIPT_REGENERATE;
             }
         }
 
         return !property.maybeTypes()->configuredProperty();
     }
@@ -3206,17 +3207,17 @@ types::AddClearDefiniteFunctionUsesInScr
 }
 
 /*
  * Either make the newScript information for type when it is constructed
  * by the specified script, or regenerate the constraints for an existing
  * newScript on the type after they were cleared by a GC.
  */
 static void
-CheckNewScriptProperties(JSContext *cx, TypeObject *type, JSFunction *fun)
+CheckNewScriptProperties(JSContext *cx, TypeObject *type, HandleFunction fun)
 {
     JS_ASSERT(cx->compartment()->activeAnalysis);
 
 #ifdef JS_ION
     if (type->unknownProperties())
         return;
 
     /* Strawman object to add properties to and watch for duplicates. */
--- a/js/src/jsinfer.h
+++ b/js/src/jsinfer.h
@@ -1216,17 +1216,17 @@ class TypeScript
 };
 
 class RecompileInfo;
 
 // Allocate a CompilerOutput for a finished compilation and generate the type
 // constraints for the compilation. Returns whether the type constraints
 // still hold.
 bool
-FinishCompilation(JSContext *cx, JSScript *script, ExecutionMode executionMode,
+FinishCompilation(JSContext *cx, HandleScript script, ExecutionMode executionMode,
                   CompilerConstraintList *constraints, RecompileInfo *precompileInfo);
 
 struct ArrayTableKey;
 typedef HashMap<ArrayTableKey,ReadBarriered<TypeObject>,ArrayTableKey,SystemAllocPolicy> ArrayTypeTable;
 
 struct ObjectTableKey;
 struct ObjectTableEntry;
 typedef HashMap<ObjectTableKey,ObjectTableEntry,ObjectTableKey,SystemAllocPolicy> ObjectTypeTable;
--- a/js/src/vm/StructuredClone.cpp
+++ b/js/src/vm/StructuredClone.cpp
@@ -1489,17 +1489,17 @@ JSStructuredCloneReader::readTransferMap
         void *content;
         if (!in.readPtr(&content))
             return false;
 
         uint64_t userdata;
         if (!in.read(&userdata))
             return false;
 
-        JSObject *obj = JS_NewArrayBufferWithContents(context(), content);
+        RootedObject obj(context(), JS_NewArrayBufferWithContents(context(), content));
         if (!obj)
             return false;
 
         // Rewind to the SCTAG_TRANSFER_MAP_ENTRY and mark this entry as unowned by
         // the input buffer.
         uint64_t *next = in.tell();
         in.seek(pos);
         MOZ_ALWAYS_TRUE(in.replacePair(SCTAG_TRANSFER_MAP_ENTRY, SCTAG_TM_UNOWNED));