JavaScriptCore:

2008-09-01  Geoffrey Garen  <ggaren@apple.com>

        Reviewed by Darin Adler.

        First cut at inline caching for access to vanilla JavaScript properties.
        
        SunSpider says 4% faster. Tests heavy on dictionary-like access have
        regressed a bit -- we have a lot of room to improve in this area,
        but this patch is over-ripe as-is.
        
        JSCells now have a StructureID that uniquely identifies their layout,
        and holds their prototype.
        
        JSValue::put takes a PropertySlot& argument, so it can fill in details
        about where it put a value, for the sake of caching.

        * VM/CodeGenerator.cpp:
        (KJS::CodeGenerator::CodeGenerator): Avoid calling removeDirect if we
        can, since it disables inline caching in the global object. This can
        probably improve in the future.

        * kjs/JSGlobalObject.cpp: Nixed reset(), since it complicates caching, and
        wasn't really necessary.

        * kjs/JSObject.cpp: Tweaked getter / setter behavior not to rely on the
        IsGetterSetter flag, since the flag was buggy. This is necessary in order
        to avoid accidentally accessing a getter / setter as a normal property.
        
        Also changed getter / setter creation to honor ReadOnly, matching Mozilla.
        
        * kjs/PropertyMap.cpp: Nixed clear(), since it complicates caching and
        isn't necessary.

        * kjs/Shell.cpp: Moved SamplingTool dumping outside the loop. This allows
        you to aggregate sampling of multiple files (or the same file repeatedly),
        which helped me track down regressions.

        * kjs/ustring.h: Moved IdentifierRepHash here to share it.

WebCore:

2008-09-01  Geoffrey Garen  <ggaren@apple.com>

        Reviewed by Darin Adler.

        First cut at inline caching for access to vanilla JavaScript properties.

        Updated for JavaScriptCore changes. Mostly mechanical addition of StructureIDs
        to WebCore classes, and PutPropertySlot& arguments to put functions.

        (WebCore::JSCSSStyleDeclaration::customPut): Be sure to play nice with
        inline caching for global properties, so global assignment can be optimized.

        * ForwardingHeaders/kjs/StructureID.h: Added.
        * bindings/js/JSDOMBinding.h:
        (WebCore::DOMObject::DOMObject):
        * bindings/js/JSDOMWindowBase.cpp:
        (WebCore::JSDOMWindowBase::put):
        * bindings/js/JSDOMWindowBase.h:
        * bindings/js/JSDOMWindowCustom.h:
        (WebCore::JSDOMWindow::customPut):
        * bindings/js/JSDOMWindowShell.cpp:
        (WebCore::JSDOMWindowShell::JSDOMWindowShell):
        (WebCore::JSDOMWindowShell::put):
        * bindings/js/JSDOMWindowShell.h:
        * bindings/js/JSEventTargetBase.h:
        (WebCore::JSEventTargetBase::put):
        * bindings/js/JSEventTargetNode.h:
        (WebCore::JSEventTargetNode::put):
        * bindings/js/JSHTMLAppletElementCustom.cpp:
        (WebCore::JSHTMLAppletElement::customPut):
        * bindings/js/JSHTMLEmbedElementCustom.cpp:
        (WebCore::JSHTMLEmbedElement::customPut):
        * bindings/js/JSHTMLInputElementBase.cpp:
        (WebCore::JSHTMLInputElementBase::put):
        * bindings/js/JSHTMLInputElementBase.h:
        * bindings/js/JSHTMLObjectElementCustom.cpp:
        (WebCore::JSHTMLObjectElement::customPut):
        * bindings/js/JSHistoryCustom.cpp:
        (WebCore::JSHistory::customPut):
        * bindings/js/JSInspectedObjectWrapper.cpp:
        (WebCore::JSInspectedObjectWrapper::wrap):
        (WebCore::JSInspectedObjectWrapper::JSInspectedObjectWrapper):
        * bindings/js/JSInspectedObjectWrapper.h:
        * bindings/js/JSInspectorCallbackWrapper.cpp:
        (WebCore::JSInspectorCallbackWrapper::wrap):
        (WebCore::JSInspectorCallbackWrapper::JSInspectorCallbackWrapper):
        * bindings/js/JSInspectorCallbackWrapper.h:
        * bindings/js/JSLocationCustom.cpp:
        (WebCore::JSLocation::customPut):
        * bindings/js/JSPluginElementFunctions.cpp:
        (WebCore::runtimeObjectCustomPut):
        * bindings/js/JSPluginElementFunctions.h:
        * bindings/js/JSQuarantinedObjectWrapper.cpp:
        (WebCore::JSQuarantinedObjectWrapper::JSQuarantinedObjectWrapper):
        (WebCore::JSQuarantinedObjectWrapper::put):
        * bindings/js/JSQuarantinedObjectWrapper.h:
        * bindings/js/JSStorageCustom.cpp:
        (WebCore::JSStorage::customPut):
        * bindings/objc/WebScriptObject.mm:
        (-[WebScriptObject setValue:forKey:]):
        * bindings/scripts/CodeGeneratorJS.pm:
        * bridge/NP_jsobject.cpp:
        (_NPN_SetProperty):
        * bridge/jni/jni_jsobject.mm:
        (JavaJSObject::setMember):
        * bridge/objc/objc_class.mm:
        (KJS::Bindings::ObjcClass::fallbackObject):
        * bridge/objc/objc_runtime.h:
        * bridge/objc/objc_runtime.mm:
        (ObjcFallbackObjectImp::ObjcFallbackObjectImp):
        (ObjcFallbackObjectImp::put):
        * bridge/runtime.cpp:
        (KJS::Bindings::Instance::createRuntimeObject):
        * bridge/runtime_array.cpp:
        (RuntimeArray::put):
        * bridge/runtime_array.h:
        * bridge/runtime_object.cpp:
        (RuntimeObjectImp::RuntimeObjectImp):
        (RuntimeObjectImp::put):
        * bridge/runtime_object.h:

LayoutTests:

2008-09-01  Geoffrey Garen  <ggaren@apple.com>

        Reviewed by Darin Adler.

        First cut at inline caching for access to vanilla JavaScript properties.
        
        Tests for things I broke along the way.
        
        * fast/dom/getter-on-window-object2-expected.txt:
        * fast/js/pic: Added.
        * fast/js/pic/cached-deleted-properties-expected.txt: Added.
        * fast/js/pic/cached-deleted-properties.html: Added.
        * fast/js/pic/cached-getter-dictionary-and-proto-expected.txt: Added.
        * fast/js/pic/cached-getter-dictionary-and-proto.html: Added.
        * fast/js/pic/cached-getter-setter-expected.txt: Added.
        * fast/js/pic/cached-getter-setter.html: Added.
        * fast/js/pic/cached-prototype-setter-expected.txt: Added.
        * fast/js/pic/cached-prototype-setter.html: Added.
        * fast/js/pic/cached-single-entry-transition-expected.txt: Added.
        * fast/js/pic/cached-single-entry-transition.html: Added.
        * fast/js/pic/get-empty-string-expected.txt: Added.
        * fast/js/pic/get-empty-string.html: Added.
        * fast/js/pic/get-set-proxy-object-expected.txt: Added.
        * fast/js/pic/get-set-proxy-object.html: Added.
        * fast/js/pic/rehash-poisons-structure-expected.txt: Added.
        * fast/js/pic/rehash-poisons-structure.html: Added.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@36016 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/JavaScriptCore/kjs/StructureID.h b/JavaScriptCore/kjs/StructureID.h
new file mode 100644
index 0000000..44bc60f
--- /dev/null
+++ b/JavaScriptCore/kjs/StructureID.h
@@ -0,0 +1,102 @@
+// -*- mode: c++; c-basic-offset: 4 -*-
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef StructureID_h
+#define StructureID_h
+
+#include <wtf/OwnArrayPtr.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include "JSValue.h"
+#include "ustring.h"
+
+namespace KJS {
+
+    class JSValue;
+    class StructureIDChain;
+
+    class StructureID : public RefCounted<StructureID> {
+    public:
+        static PassRefPtr<StructureID> create(JSValue* prototype)
+        {
+            return adoptRef(new StructureID(prototype));
+        }
+        
+        static PassRefPtr<StructureID> changePrototypeTransition(StructureID*, JSValue* prototype);
+        static PassRefPtr<StructureID> addPropertyTransition(StructureID*, const Identifier& name);
+        static PassRefPtr<StructureID> getterSetterTransition(StructureID*);
+        static PassRefPtr<StructureID> dictionaryTransition(StructureID*);
+
+        ~StructureID();
+
+        void mark()
+        {
+            if (!m_prototype->marked())
+                m_prototype->mark();
+        }
+
+        bool isDictionary() const { return m_isDictionary; }
+
+        JSValue* prototype() const { return m_prototype; }
+        
+        void setCachedPrototypeChain(PassRefPtr<StructureIDChain> cachedPrototypeChain) { m_cachedPrototypeChain = cachedPrototypeChain; }
+        StructureIDChain* cachedPrototypeChain() const { return m_cachedPrototypeChain.get(); }
+
+    private:
+        typedef HashMap<RefPtr<UString::Rep>, StructureID*, WTF::IdentifierRepHash, HashTraits<RefPtr<UString::Rep> > > TransitionTable;
+        
+        StructureID(JSValue* prototype);
+        
+        static const size_t s_maxTransitionLength = 64;
+
+        bool m_isDictionary;
+
+        JSValue* m_prototype;
+        RefPtr<StructureIDChain> m_cachedPrototypeChain;
+
+        RefPtr<StructureID> m_previous;
+        UString::Rep* m_nameInPrevious;
+
+        size_t m_transitionCount;
+        TransitionTable m_transitionTable;
+    };
+
+    class StructureIDChain : public RefCounted<StructureIDChain> {
+    public:
+        static PassRefPtr<StructureIDChain> create(StructureID* structureID) { return adoptRef(new StructureIDChain(structureID)); }
+
+        RefPtr<StructureID>* head() { return m_vector.get(); }
+
+    private:
+        StructureIDChain(StructureID* structureID);
+
+        size_t m_size;
+        OwnArrayPtr<RefPtr<StructureID> > m_vector;
+    };
+
+} // namespace KJS
+
+#endif // StructureID_h