Bug 637572 - Implement ScriptSourceObject; r=jimb
authorEddy Bruel <ejpbruel@mozilla.com>
Wed, 22 May 2013 16:06:54 -0700
changeset 132703 b048b14ab01016516489f1e6c590571d662ce7b3
parent 132702 b5812c4bef740c0a3c2574d1ffbf624b5f1d3aa5
child 132704 88016f09b0f4be66698780ec36d2b4e5ba7f0f8a
push id24712
push useremorley@mozilla.com
push dateThu, 23 May 2013 11:43:28 +0000
treeherdermozilla-central@8eebe35aae63 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjimb
bugs637572
milestone24.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 637572 - Implement ScriptSourceObject; r=jimb
js/public/RootingAPI.h
js/src/jsobj.h
js/src/jsobjinlines.h
js/src/jsscript.cpp
js/src/jsscript.h
--- a/js/public/RootingAPI.h
+++ b/js/public/RootingAPI.h
@@ -94,16 +94,17 @@
  *     (via &)
  *
  * All of these types have an implicit conversion to raw pointers.
  */
 
 namespace js {
 
 class Module;
+class ScriptSourceObject;
 
 template <typename T>
 struct RootMethods {};
 
 template <typename T>
 class RootedBase {};
 
 template <typename T>
@@ -242,23 +243,24 @@ class MOZ_STACK_CLASS Handle : public js
     Handle() {}
 
     const T *ptr;
 
     template <typename S>
     void operator=(S v) MOZ_DELETE;
 };
 
-typedef Handle<JSObject*>    HandleObject;
-typedef Handle<js::Module*>  HandleModule;
-typedef Handle<JSFunction*>  HandleFunction;
-typedef Handle<JSScript*>    HandleScript;
-typedef Handle<JSString*>    HandleString;
-typedef Handle<jsid>         HandleId;
-typedef Handle<Value>        HandleValue;
+typedef Handle<JSObject*>                   HandleObject;
+typedef Handle<js::Module*>                 HandleModule;
+typedef Handle<js::ScriptSourceObject *>    HandleScriptSource;
+typedef Handle<JSFunction*>                 HandleFunction;
+typedef Handle<JSScript*>                   HandleScript;
+typedef Handle<JSString*>                   HandleString;
+typedef Handle<jsid>                        HandleId;
+typedef Handle<Value>                       HandleValue;
 
 /*
  * Similar to a handle, but the underlying storage can be changed. This is
  * useful for outparams.
  *
  * If you want to add additional methods to MutableHandle for a specific
  * specialization, define a MutableHandleBase<T> specialization containing
  * them.
@@ -518,23 +520,24 @@ class MOZ_STACK_CLASS Rooted : public js
 };
 
 #if !(defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING))
 // Defined in vm/String.h.
 template <>
 class Rooted<JSStableString *>;
 #endif
 
-typedef Rooted<JSObject*>    RootedObject;
-typedef Rooted<js::Module*>  RootedModule;
-typedef Rooted<JSFunction*>  RootedFunction;
-typedef Rooted<JSScript*>    RootedScript;
-typedef Rooted<JSString*>    RootedString;
-typedef Rooted<jsid>         RootedId;
-typedef Rooted<JS::Value>    RootedValue;
+typedef Rooted<JSObject*>                   RootedObject;
+typedef Rooted<js::Module*>                 RootedModule;
+typedef Rooted<js::ScriptSourceObject *>    RootedScriptSource;
+typedef Rooted<JSFunction*>                 RootedFunction;
+typedef Rooted<JSScript*>                   RootedScript;
+typedef Rooted<JSString*>                   RootedString;
+typedef Rooted<jsid>                        RootedId;
+typedef Rooted<JS::Value>                   RootedValue;
 
 } /* namespace JS */
 
 namespace js {
 
 /*
  * Mark a stack location as a root for the rooting analysis, without actually
  * rooting it in release builds. This should only be used for stack locations
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -224,16 +224,17 @@ extern Class MathClass;
 extern Class ModuleClass;
 extern Class NumberClass;
 extern Class NormalArgumentsObjectClass;
 extern Class ObjectClass;
 extern Class ProxyClass;
 extern Class RegExpClass;
 extern Class RegExpStaticsClass;
 extern Class SetIteratorClass;
+extern Class ScriptSourceClass;
 extern Class StopIterationClass;
 extern Class StringClass;
 extern Class StrictArgumentsObjectClass;
 extern Class WeakMapClass;
 extern Class WithClass;
 
 class ArgumentsObject;
 class ArrayBufferObject;
@@ -974,16 +975,17 @@ class JSObject : public js::ObjectImpl
     inline bool isObject() const;
     inline bool isPrimitive() const;
     inline bool isPropertyIterator() const;
     using js::ObjectImpl::isProxy;
     inline bool isRegExp() const;
     inline bool isRegExpStatics() const;
     inline bool isScope() const;
     inline bool isScript() const;
+    inline bool isScriptSource() const;
     inline bool isSetIterator() const;
     inline bool isStopIteration() const;
     inline bool isTypedArray() const;
     inline bool isWeakMap() const;
 
     /* Subtypes of ScopeObject. */
     inline bool isBlock() const;
     inline bool isCall() const;
@@ -1026,16 +1028,17 @@ class JSObject : public js::ObjectImpl
     inline js::NormalArgumentsObject &asNormalArguments();
     inline js::NumberObject &asNumber();
     inline js::PropertyIteratorObject &asPropertyIterator();
     inline const js::PropertyIteratorObject &asPropertyIterator() const;
     inline js::RegExpObject &asRegExp();
     inline js::ScopeObject &asScope();
     inline js::SetObject &asSet();
     inline js::SetIteratorObject &asSetIterator();
+    inline js::ScriptSourceObject &asScriptSource();
     inline js::StrictArgumentsObject &asStrictArguments();
     inline js::StaticBlockObject &asStaticBlock();
     inline js::StringObject &asString();
     inline js::WithObject &asWith();
 
     static inline js::ThingRootKind rootKind() { return js::THING_ROOT_OBJECT; }
 
 #ifdef DEBUG
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -901,16 +901,17 @@ inline bool JSObject::isModule() const {
 inline bool JSObject::isNestedScope() const { return isBlock() || isWith(); }
 inline bool JSObject::isNormalArguments() const { return hasClass(&js::NormalArgumentsObjectClass); }
 inline bool JSObject::isNumber() const { return hasClass(&js::NumberClass); }
 inline bool JSObject::isObject() const { return hasClass(&js::ObjectClass); }
 inline bool JSObject::isPrimitive() const { return isNumber() || isString() || isBoolean(); }
 inline bool JSObject::isRegExp() const { return hasClass(&js::RegExpClass); }
 inline bool JSObject::isRegExpStatics() const { return hasClass(&js::RegExpStaticsClass); }
 inline bool JSObject::isScope() const { return isCall() || isDeclEnv() || isNestedScope(); }
+inline bool JSObject::isScriptSource() const { return hasClass(&js::ScriptSourceClass); }
 inline bool JSObject::isSetIterator() const { return hasClass(&js::SetIteratorClass); }
 inline bool JSObject::isStaticBlock() const { return isBlock() && !getProto(); }
 inline bool JSObject::isStopIteration() const { return hasClass(&js::StopIterationClass); }
 inline bool JSObject::isStrictArguments() const { return hasClass(&js::StrictArgumentsObjectClass); }
 inline bool JSObject::isString() const { return hasClass(&js::StringClass); }
 inline bool JSObject::isTypedArray() const { return IsTypedArrayClass(getClass()); }
 inline bool JSObject::isWeakMap() const { return hasClass(&js::WeakMapClass); }
 inline bool JSObject::isWith() const { return hasClass(&js::WithClass); }
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -888,16 +888,48 @@ void
 JSScript::destroyScriptCounts(FreeOp *fop)
 {
     if (hasScriptCounts) {
         ScriptCounts scriptCounts = releaseScriptCounts();
         scriptCounts.destroy(fop);
     }
 }
 
+void
+ScriptSourceObject::finalize(FreeOp *fop, JSObject *obj)
+{
+    // ScriptSource::setSource automatically takes care of the refcount
+    obj->asScriptSource().setSource(NULL);
+}
+
+Class js::ScriptSourceClass = {
+    "ScriptSource",
+    JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_IS_ANONYMOUS,
+    JS_PropertyStub,        /* addProperty */
+    JS_DeletePropertyStub,  /* delProperty */
+    JS_PropertyStub,        /* getProperty */
+    JS_StrictPropertyStub,  /* setProperty */
+    JS_EnumerateStub,
+    JS_ResolveStub,
+    JS_ConvertStub,
+    ScriptSourceObject::finalize
+};
+
+ScriptSourceObject *
+ScriptSourceObject::create(JSContext *cx, ScriptSource *source)
+{
+    RootedObject object(cx, NewObjectWithGivenProto(cx, &ScriptSourceClass, NULL, cx->global()));
+    if (!object)
+        return NULL;
+    JS::RootedScriptSource sourceObject(cx, &object->asScriptSource());
+    sourceObject->setSlot(SOURCE_SLOT, PrivateValue(source));
+    source->incref();
+    return sourceObject;
+}
+
 #ifdef JS_THREADSAFE
 void
 SourceCompressorThread::compressorThread(void *arg)
 {
     PR_SetCurrentThreadName("JS Source Compressing Thread");
     static_cast<SourceCompressorThread *>(arg)->threadLoop();
 }
 
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -1074,16 +1074,37 @@ class ScriptSourceHolder
         ss->incref();
     }
     ~ScriptSourceHolder()
     {
         ss->decref();
     }
 };
 
+class ScriptSourceObject : public JSObject {
+  public:
+    static void finalize(FreeOp *fop, JSObject *obj);
+    static ScriptSourceObject *create(JSContext *cx, ScriptSource *source);
+
+    ScriptSource *source() {
+        return static_cast<ScriptSource *>(getReservedSlot(SOURCE_SLOT).toPrivate());
+    }
+
+    void setSource(ScriptSource *source) {
+        if (source)
+            source->incref();
+        if (this->source())
+            this->source()->decref();
+        setReservedSlot(SOURCE_SLOT, PrivateValue(source));
+    }
+
+  private:
+    static const uint32_t SOURCE_SLOT = 0;
+};
+
 #ifdef JS_THREADSAFE
 /*
  * Background thread to compress JS source code. This happens only while parsing
  * and bytecode generation is happening in the main thread. If needed, the
  * compiler waits for compression to complete before returning.
  *
  * To use it, you have to have a SourceCompressionToken, tok, with tok.ss and
  * tok.chars set to the proper values. When the SourceCompressionToken is
@@ -1245,16 +1266,23 @@ struct ScriptAndCounts
 
     ion::IonScriptCounts *getIonCounts() const {
         return scriptCounts.ionCounts;
     }
 };
 
 } /* namespace js */
 
+inline js::ScriptSourceObject &
+JSObject::asScriptSource()
+{
+    JS_ASSERT(isScriptSource());
+    return *static_cast<js::ScriptSourceObject *>(this);
+}
+
 extern jssrcnote *
 js_GetSrcNote(JSContext *cx, JSScript *script, jsbytecode *pc);
 
 extern jsbytecode *
 js_LineNumberToPC(JSScript *script, unsigned lineno);
 
 extern JS_FRIEND_API(unsigned)
 js_GetScriptLineExtent(JSScript *script);