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