]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - runtime/GetterSetter.h
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / runtime / GetterSetter.h
index bc5cbe0afb1325f1d14f7af26fa9fc956e942ae4..b983f043dc03eb608bb7e0732e3c89361f2b779f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2014 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
 #include "JSCell.h"
 
 #include "CallFrame.h"
+#include "JSGlobalObject.h"
+#include "NullGetterFunction.h"
+#include "NullSetterFunction.h"
 #include "Structure.h"
 
 namespace JSC {
 
-    class JSObject;
-
-    // This is an internal value object which stores getter and setter functions
-    // for a property.
-    class GetterSetter : public JSCell {
-        friend class JIT;
-
-    private:        
-        GetterSetter(VM& vm)
-            : JSCell(vm, vm.getterSetterStructure.get())
-        {
-        }
-
-    public:
-        typedef JSCell Base;
-
-        static GetterSetter* create(VM& vm)
-        {
-            GetterSetter* getterSetter = new (NotNull, allocateCell<GetterSetter>(vm.heap)) GetterSetter(vm);
-            getterSetter->finishCreation(vm);
-            return getterSetter;
-        }
-
-        static void visitChildren(JSCell*, SlotVisitor&);
-
-        JSObject* getter() const { return m_getter.get(); }
-        void setGetter(VM& vm, JSObject* getter) { m_getter.setMayBeNull(vm, this, getter); }
-        JSObject* setter() const { return m_setter.get(); }
-        void setSetter(VM& vm, JSObject* setter) { m_setter.setMayBeNull(vm, this, setter); }
-        static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
-        {
-            return Structure::create(vm, globalObject, prototype, TypeInfo(GetterSetterType, OverridesVisitChildren), info());
-        }
-        
-        static ptrdiff_t offsetOfGetter()
-        {
-            return OBJECT_OFFSETOF(GetterSetter, m_getter);
-        }
-        
-        static ptrdiff_t offsetOfSetter()
-        {
-            return OBJECT_OFFSETOF(GetterSetter, m_setter);
-        }
-        
-        DECLARE_INFO;
-
-    private:
-        WriteBarrier<JSObject> m_getter;
-        WriteBarrier<JSObject> m_setter;  
-    };
-
-    GetterSetter* asGetterSetter(JSValue);
-
-    inline GetterSetter* asGetterSetter(JSValue value)
+class JSObject;
+
+// This is an internal value object which stores getter and setter functions
+// for a property. Instances of this class have the property that once a getter
+// or setter is set to a non-null value, then they cannot be changed. This means
+// that if a property holding a GetterSetter reference is constant-inferred and
+// that constant is observed to have a non-null setter (or getter) then we can
+// constant fold that setter (or getter).
+class GetterSetter final : public JSCell {
+    friend class JIT;
+
+private:
+    GetterSetter(VM& vm, JSGlobalObject* globalObject)
+        : JSCell(vm, vm.getterSetterStructure.get())
+    {
+        m_getter.set(vm, this, globalObject->nullGetterFunction());
+        m_setter.set(vm, this, globalObject->nullSetterFunction());
+    }
+
+public:
+    typedef JSCell Base;
+    static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
+
+    static GetterSetter* create(VM& vm, JSGlobalObject* globalObject)
+    {
+        GetterSetter* getterSetter = new (NotNull, allocateCell<GetterSetter>(vm.heap)) GetterSetter(vm, globalObject);
+        getterSetter->finishCreation(vm);
+        return getterSetter;
+    }
+
+    static void visitChildren(JSCell*, SlotVisitor&);
+
+    JSObject* getter() const { return m_getter.get(); }
+
+    JSObject* getterConcurrently() const
+    {
+        JSObject* result = getter();
+        WTF::loadLoadFence();
+        return result;
+    }
+
+    bool isGetterNull() const { return !!jsDynamicCast<NullGetterFunction*>(m_getter.get()); }
+    bool isSetterNull() const { return !!jsDynamicCast<NullSetterFunction*>(m_setter.get()); }
+
+    // Set the getter. It's only valid to call this if you've never set the getter on this
+    // object.
+    void setGetter(VM& vm, JSGlobalObject* globalObject, JSObject* getter)
+    {
+        if (!getter)
+            getter = jsCast<JSObject*>(globalObject->nullGetterFunction());
+
+        RELEASE_ASSERT(isGetterNull());
+        WTF::storeStoreFence();
+        m_getter.set(vm, this, getter);
+    }
+
+    JSObject* setter() const { return m_setter.get(); }
+
+    JSObject* setterConcurrently() const
+    {
+        JSObject* result = setter();
+        WTF::loadLoadFence();
+        return result;
+    }
+
+    // Set the setter. It's only valid to call this if you've never set the setter on this
+    // object.
+    void setSetter(VM& vm, JSGlobalObject* globalObject, JSObject* setter)
+    {
+        if (!setter)
+            setter = jsCast<JSObject*>(globalObject->nullSetterFunction());
+
+        RELEASE_ASSERT(isSetterNull());
+        WTF::storeStoreFence();
+        m_setter.set(vm, this, setter);
+    }
+
+    GetterSetter* withGetter(VM&, JSGlobalObject*, JSObject* getter);
+    GetterSetter* withSetter(VM&, JSGlobalObject*, JSObject* setter);
+
+    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
     {
-        ASSERT_WITH_SECURITY_IMPLICATION(value.asCell()->isGetterSetter());
-        return static_cast<GetterSetter*>(value.asCell());
+        return Structure::create(vm, globalObject, prototype, TypeInfo(GetterSetterType), info());
     }
 
-    JSValue callGetter(ExecState*, JSValue base, JSValue getterSetter);
-    void callSetter(ExecState*, JSValue base, JSValue getterSetter, JSValue value, ECMAMode);
+    static ptrdiff_t offsetOfGetter()
+    {
+        return OBJECT_OFFSETOF(GetterSetter, m_getter);
+    }
+
+    static ptrdiff_t offsetOfSetter()
+    {
+        return OBJECT_OFFSETOF(GetterSetter, m_setter);
+    }
+
+    DECLARE_INFO;
+
+private:
+    WriteBarrier<JSObject> m_getter;
+    WriteBarrier<JSObject> m_setter;  
+};
+
+GetterSetter* asGetterSetter(JSValue);
+
+inline GetterSetter* asGetterSetter(JSValue value)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(value.asCell()->isGetterSetter());
+    return static_cast<GetterSetter*>(value.asCell());
+}
+
+JSValue callGetter(ExecState*, JSValue base, JSValue getterSetter);
+void callSetter(ExecState*, JSValue base, JSValue getterSetter, JSValue, ECMAMode);
 
 } // namespace JSC