Object.getOwnPropertySymbols on large list takes very long
authorutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 24 Jul 2015 19:31:16 +0000 (19:31 +0000)
committerutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 24 Jul 2015 19:31:16 +0000 (19:31 +0000)
https://bugs.webkit.org/show_bug.cgi?id=146137

Reviewed by Mark Lam.

Source/JavaScriptCore:

Before this patch, Object.getOwnPropertySymbols collects all the names including strings.
And after it's done, filter the names to only retrieve the symbols.
But it's so time consuming if the given object is a large non-holed array since it has
many indexed properties and all the indexes have to be converted to uniqued_strings and
added to the collection of property names (though they may not be of the requested type
and will be filtered out later)

This patch introduces PropertyNameMode.
We leverage this mode in 2 places.

1. PropertyNameArray side
It is set in PropertyNameArray and it filters the incoming added identifiers based on the mode.
It ensures that PropertyNameArray doesn't become so large in the pathological case.
And it ensures that non-expected typed keys by the filter (Symbols or Strings) are never added
to the property name array collections.
However it does not solve the whole problem because the huge array still incurs the many
"indexed property to uniqued string" conversion and the large iteration before adding the keys
to the property name array.

2. getOwnPropertyNames side
So we can use the PropertyNameMode in the caller side (getOwnPropertyNames) as a **hint**.
When the large iteration may occur, the caller side can use the PropertyNameMode as a hint to
avoid the iteration.
But we cannot exclusively rely on these caller side checks because it would require that we
exhaustively add the checks to all custom implementations of getOwnPropertyNames as well.
This process requires manual inspection of many pieces of code, and is error prone. Instead,
we only apply the caller side check in a few strategic places where it is known to yield
performance benefits; and we rely on the filter in PropertyNameArray::add() to reject the wrong
types of properties for all other calls to PropertyNameArray::add().

In this patch, there's a concept in use that is not clear just from reading the code, and hence
should be documented here. When selecting the PropertyNameMode for the PropertyNameArray to be
instantiated, we apply the following logic:

1. Only JavaScriptCore code is aware of ES6 Symbols.
We can assume that pre-existing external code that interfaces JSC are only looking for string named properties. This includes:
    a. WebCore bindings
    b. Serializer bindings
    c. NPAPI bindings
    d. Objective C bindings
2. In JSC, code that compute object storage space needs to iterate both Symbol and String named properties. Hence, use PropertyNameMode::Both.
3. In JSC, ES6 APIs that work with Symbols should use PropertyNameMode::Symbols.
4. In JSC, ES6 APIs that work with String named properties should use PropertyNameMode::Strings.

* API/JSObjectRef.cpp:
(JSObjectCopyPropertyNames):
* bindings/ScriptValue.cpp:
(Deprecated::jsToInspectorValue):
* bytecode/ObjectAllocationProfile.h:
(JSC::ObjectAllocationProfile::possibleDefaultPropertyCount):
* runtime/EnumerationMode.h:
(JSC::EnumerationMode::EnumerationMode):
(JSC::EnumerationMode::includeSymbolProperties): Deleted.
* runtime/GenericArgumentsInlines.h:
(JSC::GenericArguments<Type>::getOwnPropertyNames):
* runtime/JSGenericTypedArrayViewInlines.h:
(JSC::JSGenericTypedArrayView<Adaptor>::getOwnPropertyNames):
* runtime/JSLexicalEnvironment.cpp:
(JSC::JSLexicalEnvironment::getOwnNonIndexPropertyNames):
* runtime/JSONObject.cpp:
(JSC::Stringifier::Stringifier):
(JSC::Stringifier::Holder::appendNextProperty):
(JSC::Walker::walk):
* runtime/JSObject.cpp:
(JSC::JSObject::getOwnPropertyNames):
* runtime/JSPropertyNameEnumerator.cpp:
(JSC::JSPropertyNameEnumerator::create):
* runtime/JSPropertyNameEnumerator.h:
(JSC::propertyNameEnumerator):
* runtime/JSSymbolTableObject.cpp:
(JSC::JSSymbolTableObject::getOwnNonIndexPropertyNames):
* runtime/ObjectConstructor.cpp:
(JSC::objectConstructorGetOwnPropertyNames):
(JSC::objectConstructorGetOwnPropertySymbols):
(JSC::objectConstructorKeys):
(JSC::defineProperties):
(JSC::objectConstructorSeal):
(JSC::objectConstructorFreeze):
(JSC::objectConstructorIsSealed):
(JSC::objectConstructorIsFrozen):
* runtime/PropertyNameArray.h:
(JSC::PropertyNameArray::PropertyNameArray):
(JSC::PropertyNameArray::mode):
(JSC::PropertyNameArray::addKnownUnique):
(JSC::PropertyNameArray::add):
(JSC::PropertyNameArray::isUidMatchedToTypeMode):
(JSC::PropertyNameArray::includeSymbolProperties):
(JSC::PropertyNameArray::includeStringProperties):
* runtime/StringObject.cpp:
(JSC::StringObject::getOwnPropertyNames):
* runtime/Structure.cpp:
(JSC::Structure::getPropertyNamesFromStructure):

Source/WebCore:

* bindings/js/Dictionary.cpp:
(WebCore::Dictionary::getOwnPropertiesAsStringHashMap):
(WebCore::Dictionary::getOwnPropertyNames):
* bindings/js/SerializedScriptValue.cpp:
(WebCore::CloneSerializer::serialize):
* bridge/NP_jsobject.cpp:
(_NPN_Enumerate):

Source/WebKit/mac:

* Plugins/Hosted/NetscapePluginInstanceProxy.mm:
(WebKit::NetscapePluginInstanceProxy::enumerate):

Source/WebKit2:

* WebProcess/Plugins/Netscape/NPJSObject.cpp:
(WebKit::NPJSObject::enumerate):

LayoutTests:

* js/regress/object-get-own-property-symbols-on-large-array-expected.txt: Added.
* js/regress/object-get-own-property-symbols-on-large-array.html: Added.
* js/regress/script-tests/object-get-own-property-symbols-on-large-array.js: Added.
(trial):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@187355 268f45cc-cd09-0410-ab3c-d52691b4dbfc

29 files changed:
LayoutTests/ChangeLog
LayoutTests/js/regress/object-get-own-property-symbols-on-large-array-expected.txt [new file with mode: 0644]
LayoutTests/js/regress/object-get-own-property-symbols-on-large-array.html [new file with mode: 0644]
LayoutTests/js/regress/script-tests/object-get-own-property-symbols-on-large-array.js [new file with mode: 0644]
Source/JavaScriptCore/API/JSObjectRef.cpp
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bindings/ScriptValue.cpp
Source/JavaScriptCore/bytecode/ObjectAllocationProfile.h
Source/JavaScriptCore/runtime/EnumerationMode.h
Source/JavaScriptCore/runtime/GenericArgumentsInlines.h
Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h
Source/JavaScriptCore/runtime/JSLexicalEnvironment.cpp
Source/JavaScriptCore/runtime/JSONObject.cpp
Source/JavaScriptCore/runtime/JSObject.cpp
Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.cpp
Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.h
Source/JavaScriptCore/runtime/JSSymbolTableObject.cpp
Source/JavaScriptCore/runtime/ObjectConstructor.cpp
Source/JavaScriptCore/runtime/PropertyNameArray.h
Source/JavaScriptCore/runtime/StringObject.cpp
Source/JavaScriptCore/runtime/Structure.cpp
Source/WebCore/ChangeLog
Source/WebCore/bindings/js/Dictionary.cpp
Source/WebCore/bindings/js/SerializedScriptValue.cpp
Source/WebCore/bridge/NP_jsobject.cpp
Source/WebKit/mac/ChangeLog
Source/WebKit/mac/Plugins/Hosted/NetscapePluginInstanceProxy.mm
Source/WebKit2/ChangeLog
Source/WebKit2/WebProcess/Plugins/Netscape/NPJSObject.cpp

index efdbf0b..a3cebf6 100644 (file)
@@ -1,3 +1,15 @@
+2015-07-24  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        Object.getOwnPropertySymbols on large list takes very long
+        https://bugs.webkit.org/show_bug.cgi?id=146137
+
+        Reviewed by Mark Lam.
+
+        * js/regress/object-get-own-property-symbols-on-large-array-expected.txt: Added.
+        * js/regress/object-get-own-property-symbols-on-large-array.html: Added.
+        * js/regress/script-tests/object-get-own-property-symbols-on-large-array.js: Added.
+        (trial):
+
 2015-07-24  Devin Rousso  <drousso@apple.com>
 
         Web Inspector: Editing non-inspector-stylesheet rule selectors fails after the first change
diff --git a/LayoutTests/js/regress/object-get-own-property-symbols-on-large-array-expected.txt b/LayoutTests/js/regress/object-get-own-property-symbols-on-large-array-expected.txt
new file mode 100644 (file)
index 0000000..a3beb6f
--- /dev/null
@@ -0,0 +1,10 @@
+JSRegress/object-get-own-property-symbols-on-large-array
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/regress/object-get-own-property-symbols-on-large-array.html b/LayoutTests/js/regress/object-get-own-property-symbols-on-large-array.html
new file mode 100644 (file)
index 0000000..a9144e4
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="../../resources/regress-pre.js"></script>
+<script src="script-tests/object-get-own-property-symbols-on-large-array.js"></script>
+<script src="../../resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/regress/script-tests/object-get-own-property-symbols-on-large-array.js b/LayoutTests/js/regress/script-tests/object-get-own-property-symbols-on-large-array.js
new file mode 100644 (file)
index 0000000..faa4858
--- /dev/null
@@ -0,0 +1,13 @@
+function trial()
+{
+    var buffer = new ArrayBuffer(10000000);
+    var int8View = new Int8Array(buffer);
+    var start = Date.now();
+    var result = Object.getOwnPropertySymbols(int8View);
+    var delta = Date.now() - start;
+    if (delta > 1000)
+        throw new Error(`time consuming (${delta}ms)`);
+    return result;
+}
+
+trial();
index faf38ff..e05fbbb 100644 (file)
@@ -622,7 +622,7 @@ JSPropertyNameArrayRef JSObjectCopyPropertyNames(JSContextRef ctx, JSObjectRef o
 
     JSObject* jsObject = toJS(object);
     JSPropertyNameArrayRef propertyNames = new OpaqueJSPropertyNameArray(vm);
-    PropertyNameArray array(vm);
+    PropertyNameArray array(vm, PropertyNameMode::Strings);
     jsObject->methodTable()->getPropertyNames(jsObject, exec, array, EnumerationMode());
 
     size_t size = array.size();
index 37fba63..cf61cc6 100644 (file)
@@ -1,3 +1,103 @@
+2015-07-24  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        Object.getOwnPropertySymbols on large list takes very long
+        https://bugs.webkit.org/show_bug.cgi?id=146137
+
+        Reviewed by Mark Lam.
+
+        Before this patch, Object.getOwnPropertySymbols collects all the names including strings.
+        And after it's done, filter the names to only retrieve the symbols.
+        But it's so time consuming if the given object is a large non-holed array since it has
+        many indexed properties and all the indexes have to be converted to uniqued_strings and
+        added to the collection of property names (though they may not be of the requested type
+        and will be filtered out later)
+
+        This patch introduces PropertyNameMode.
+        We leverage this mode in 2 places.
+
+        1. PropertyNameArray side
+        It is set in PropertyNameArray and it filters the incoming added identifiers based on the mode.
+        It ensures that PropertyNameArray doesn't become so large in the pathological case.
+        And it ensures that non-expected typed keys by the filter (Symbols or Strings) are never added
+        to the property name array collections.
+        However it does not solve the whole problem because the huge array still incurs the many
+        "indexed property to uniqued string" conversion and the large iteration before adding the keys
+        to the property name array.
+
+        2. getOwnPropertyNames side
+        So we can use the PropertyNameMode in the caller side (getOwnPropertyNames) as a **hint**.
+        When the large iteration may occur, the caller side can use the PropertyNameMode as a hint to
+        avoid the iteration.
+        But we cannot exclusively rely on these caller side checks because it would require that we
+        exhaustively add the checks to all custom implementations of getOwnPropertyNames as well.
+        This process requires manual inspection of many pieces of code, and is error prone. Instead,
+        we only apply the caller side check in a few strategic places where it is known to yield
+        performance benefits; and we rely on the filter in PropertyNameArray::add() to reject the wrong
+        types of properties for all other calls to PropertyNameArray::add().
+
+        In this patch, there's a concept in use that is not clear just from reading the code, and hence
+        should be documented here. When selecting the PropertyNameMode for the PropertyNameArray to be
+        instantiated, we apply the following logic:
+
+        1. Only JavaScriptCore code is aware of ES6 Symbols.
+        We can assume that pre-existing external code that interfaces JSC are only looking for string named properties. This includes:
+            a. WebCore bindings
+            b. Serializer bindings
+            c. NPAPI bindings
+            d. Objective C bindings
+        2. In JSC, code that compute object storage space needs to iterate both Symbol and String named properties. Hence, use PropertyNameMode::Both.
+        3. In JSC, ES6 APIs that work with Symbols should use PropertyNameMode::Symbols.
+        4. In JSC, ES6 APIs that work with String named properties should use PropertyNameMode::Strings.
+
+        * API/JSObjectRef.cpp:
+        (JSObjectCopyPropertyNames):
+        * bindings/ScriptValue.cpp:
+        (Deprecated::jsToInspectorValue):
+        * bytecode/ObjectAllocationProfile.h:
+        (JSC::ObjectAllocationProfile::possibleDefaultPropertyCount):
+        * runtime/EnumerationMode.h:
+        (JSC::EnumerationMode::EnumerationMode):
+        (JSC::EnumerationMode::includeSymbolProperties): Deleted.
+        * runtime/GenericArgumentsInlines.h:
+        (JSC::GenericArguments<Type>::getOwnPropertyNames):
+        * runtime/JSGenericTypedArrayViewInlines.h:
+        (JSC::JSGenericTypedArrayView<Adaptor>::getOwnPropertyNames):
+        * runtime/JSLexicalEnvironment.cpp:
+        (JSC::JSLexicalEnvironment::getOwnNonIndexPropertyNames):
+        * runtime/JSONObject.cpp:
+        (JSC::Stringifier::Stringifier):
+        (JSC::Stringifier::Holder::appendNextProperty):
+        (JSC::Walker::walk):
+        * runtime/JSObject.cpp:
+        (JSC::JSObject::getOwnPropertyNames):
+        * runtime/JSPropertyNameEnumerator.cpp:
+        (JSC::JSPropertyNameEnumerator::create):
+        * runtime/JSPropertyNameEnumerator.h:
+        (JSC::propertyNameEnumerator):
+        * runtime/JSSymbolTableObject.cpp:
+        (JSC::JSSymbolTableObject::getOwnNonIndexPropertyNames):
+        * runtime/ObjectConstructor.cpp:
+        (JSC::objectConstructorGetOwnPropertyNames):
+        (JSC::objectConstructorGetOwnPropertySymbols):
+        (JSC::objectConstructorKeys):
+        (JSC::defineProperties):
+        (JSC::objectConstructorSeal):
+        (JSC::objectConstructorFreeze):
+        (JSC::objectConstructorIsSealed):
+        (JSC::objectConstructorIsFrozen):
+        * runtime/PropertyNameArray.h:
+        (JSC::PropertyNameArray::PropertyNameArray):
+        (JSC::PropertyNameArray::mode):
+        (JSC::PropertyNameArray::addKnownUnique):
+        (JSC::PropertyNameArray::add):
+        (JSC::PropertyNameArray::isUidMatchedToTypeMode):
+        (JSC::PropertyNameArray::includeSymbolProperties):
+        (JSC::PropertyNameArray::includeStringProperties):
+        * runtime/StringObject.cpp:
+        (JSC::StringObject::getOwnPropertyNames):
+        * runtime/Structure.cpp:
+        (JSC::Structure::getPropertyNamesFromStructure):
+
 2015-07-24  Saam barati  <saambarati1@gmail.com>
 
         [ES6] Add support for default parameters
index 153b033..02ef36e 100644 (file)
@@ -136,7 +136,7 @@ static RefPtr<InspectorValue> jsToInspectorValue(ExecState* scriptState, JSValue
         }
         Ref<InspectorObject> inspectorObject = InspectorObject::create();
         JSObject* object = value.getObject();
-        PropertyNameArray propertyNames(scriptState);
+        PropertyNameArray propertyNames(scriptState, PropertyNameMode::Strings);
         object->methodTable()->getOwnPropertyNames(object, scriptState, propertyNames, EnumerationMode());
         for (size_t i = 0; i < propertyNames.size(); i++) {
             const Identifier& name = propertyNames[i];
index cb4148e..c04194c 100644 (file)
@@ -127,7 +127,7 @@ private:
             return 0;
 
         size_t count = 0;
-        PropertyNameArray propertyNameArray(&vm);
+        PropertyNameArray propertyNameArray(&vm, PropertyNameMode::Both);
         prototype->structure()->getPropertyNamesFromStructure(vm, propertyNameArray, EnumerationMode());
         PropertyNameArrayData::PropertyNameVector& propertyNameVector = propertyNameArray.data()->propertyNameVector();
         for (size_t i = 0; i < propertyNameVector.size(); ++i) {
index 3e95ed3..83c0568 100644 (file)
 
 namespace JSC {
 
+enum class PropertyNameMode {
+    Symbols = 1 << 0,
+    Strings = 1 << 1,
+    Both = Symbols | Strings,
+};
+
 enum class DontEnumPropertiesMode {
     Include,
     Exclude
@@ -45,16 +51,14 @@ enum class JSObjectPropertiesMode {
 
 class EnumerationMode {
 public:
-    EnumerationMode(DontEnumPropertiesMode dontEnumPropertiesMode = DontEnumPropertiesMode::Exclude, SymbolPropertiesMode symbolPropertiesMode = SymbolPropertiesMode::Exclude, JSObjectPropertiesMode jsObjectPropertiesMode = JSObjectPropertiesMode::Include)
+    EnumerationMode(DontEnumPropertiesMode dontEnumPropertiesMode = DontEnumPropertiesMode::Exclude, JSObjectPropertiesMode jsObjectPropertiesMode = JSObjectPropertiesMode::Include)
         : m_dontEnumPropertiesMode(dontEnumPropertiesMode)
-        , m_symbolPropertiesMode(symbolPropertiesMode)
         , m_jsObjectPropertiesMode(jsObjectPropertiesMode)
     {
     }
 
     EnumerationMode(const EnumerationMode& mode, JSObjectPropertiesMode jsObjectPropertiesMode)
         : m_dontEnumPropertiesMode(mode.m_dontEnumPropertiesMode)
-        , m_symbolPropertiesMode(mode.m_symbolPropertiesMode)
         , m_jsObjectPropertiesMode(jsObjectPropertiesMode)
     {
     }
@@ -66,11 +70,6 @@ public:
         return m_dontEnumPropertiesMode == DontEnumPropertiesMode::Include;
     }
 
-    bool includeSymbolProperties()
-    {
-        return m_symbolPropertiesMode == SymbolPropertiesMode::Include;
-    }
-
     bool includeJSObjectProperties()
     {
         return m_jsObjectPropertiesMode == JSObjectPropertiesMode::Include;
@@ -78,7 +77,6 @@ public:
 
 private:
     DontEnumPropertiesMode m_dontEnumPropertiesMode;
-    SymbolPropertiesMode m_symbolPropertiesMode;
     JSObjectPropertiesMode m_jsObjectPropertiesMode;
 };
 
index 5f952c6..9b18001 100644 (file)
@@ -78,16 +78,19 @@ template<typename Type>
 void GenericArguments<Type>::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& array, EnumerationMode mode)
 {
     Type* thisObject = jsCast<Type*>(object);
-    
-    for (unsigned i = 0; i < thisObject->internalLength(); ++i) {
-        if (!thisObject->canAccessIndexQuickly(i))
-            continue;
-        array.add(Identifier::from(exec, i));
+
+    if (array.includeStringProperties()) {
+        for (unsigned i = 0; i < thisObject->internalLength(); ++i) {
+            if (!thisObject->canAccessIndexQuickly(i))
+                continue;
+            array.add(Identifier::from(exec, i));
+        }
     }
+
     if (mode.includeDontEnumProperties() && !thisObject->overrodeThings()) {
         array.add(exec->propertyNames().length);
         array.add(exec->propertyNames().callee);
-        if (mode.includeSymbolProperties())
+        if (array.includeSymbolProperties())
             array.add(exec->propertyNames().iteratorSymbol);
     }
     Base::getOwnPropertyNames(thisObject, exec, array, mode);
index ec653dc..e9ed1e9 100644 (file)
@@ -423,9 +423,11 @@ void JSGenericTypedArrayView<Adaptor>::getOwnPropertyNames(
     JSObject* object, ExecState* exec, PropertyNameArray& array, EnumerationMode mode)
 {
     JSGenericTypedArrayView* thisObject = jsCast<JSGenericTypedArrayView*>(object);
-    
-    for (unsigned i = 0; i < thisObject->m_length; ++i)
-        array.add(Identifier::from(exec, i));
+
+    if (array.includeStringProperties()) {
+        for (unsigned i = 0; i < thisObject->m_length; ++i)
+            array.add(Identifier::from(exec, i));
+    }
     
     return Base::getOwnPropertyNames(object, exec, array, mode);
 }
index 6076874..47a81b5 100644 (file)
@@ -99,7 +99,7 @@ void JSLexicalEnvironment::getOwnNonIndexPropertyNames(JSObject* object, ExecSta
                 continue;
             if (!thisObject->isValid(it->value.scopeOffset()))
                 continue;
-            if (it->key->isSymbol() && !mode.includeSymbolProperties())
+            if (it->key->isSymbol() && !propertyNames.includeSymbolProperties())
                 continue;
             propertyNames.add(Identifier::fromUid(exec, it->key.get()));
         }
index 61dc046..49d6b15 100644 (file)
@@ -205,7 +205,7 @@ Stringifier::Stringifier(ExecState* exec, const Local<Unknown>& replacer, const
     : m_exec(exec)
     , m_replacer(replacer)
     , m_usingArrayReplacer(false)
-    , m_arrayReplacerPropertyNames(exec)
+    , m_arrayReplacerPropertyNames(exec, PropertyNameMode::Strings)
     , m_replacerCallType(CallTypeNone)
     , m_gap(gap(exec, space.get()))
 {
@@ -427,7 +427,7 @@ bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, StringBui
             if (stringifier.m_usingArrayReplacer)
                 m_propertyNames = stringifier.m_arrayReplacerPropertyNames.data();
             else {
-                PropertyNameArray objectPropertyNames(exec);
+                PropertyNameArray objectPropertyNames(exec, PropertyNameMode::Strings);
                 m_object->methodTable()->getOwnPropertyNames(m_object.get(), exec, objectPropertyNames, EnumerationMode());
                 m_propertyNames = objectPropertyNames.releaseData();
             }
@@ -644,7 +644,7 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
                 JSObject* object = asObject(inValue);
                 objectStack.push(object);
                 indexStack.append(0);
-                propertyStack.append(PropertyNameArray(m_exec));
+                propertyStack.append(PropertyNameArray(m_exec, PropertyNameMode::Strings));
                 object->methodTable()->getOwnPropertyNames(object, m_exec, propertyStack.last(), EnumerationMode());
             }
             objectStartVisitMember:
index d20daa2..a54facb 100644 (file)
@@ -1502,67 +1502,69 @@ void JSObject::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNa
         return;
     }
 
-    // Add numeric properties first. That appears to be the accepted convention.
-    // FIXME: Filling PropertyNameArray with an identifier for every integer
-    // is incredibly inefficient for large arrays. We need a different approach,
-    // which almost certainly means a different structure for PropertyNameArray.
-    switch (object->indexingType()) {
-    case ALL_BLANK_INDEXING_TYPES:
-    case ALL_UNDECIDED_INDEXING_TYPES:
-        break;
-        
-    case ALL_INT32_INDEXING_TYPES:
-    case ALL_CONTIGUOUS_INDEXING_TYPES: {
-        Butterfly* butterfly = object->butterfly();
-        unsigned usedLength = butterfly->publicLength();
-        for (unsigned i = 0; i < usedLength; ++i) {
-            if (!butterfly->contiguous()[i])
-                continue;
-            propertyNames.add(i);
-        }
-        break;
-    }
-        
-    case ALL_DOUBLE_INDEXING_TYPES: {
-        Butterfly* butterfly = object->butterfly();
-        unsigned usedLength = butterfly->publicLength();
-        for (unsigned i = 0; i < usedLength; ++i) {
-            double value = butterfly->contiguousDouble()[i];
-            if (value != value)
-                continue;
-            propertyNames.add(i);
+    if (propertyNames.includeStringProperties()) {
+        // Add numeric properties first. That appears to be the accepted convention.
+        // FIXME: Filling PropertyNameArray with an identifier for every integer
+        // is incredibly inefficient for large arrays. We need a different approach,
+        // which almost certainly means a different structure for PropertyNameArray.
+        switch (object->indexingType()) {
+        case ALL_BLANK_INDEXING_TYPES:
+        case ALL_UNDECIDED_INDEXING_TYPES:
+            break;
+            
+        case ALL_INT32_INDEXING_TYPES:
+        case ALL_CONTIGUOUS_INDEXING_TYPES: {
+            Butterfly* butterfly = object->butterfly();
+            unsigned usedLength = butterfly->publicLength();
+            for (unsigned i = 0; i < usedLength; ++i) {
+                if (!butterfly->contiguous()[i])
+                    continue;
+                propertyNames.add(i);
+            }
+            break;
         }
-        break;
-    }
-        
-    case ALL_ARRAY_STORAGE_INDEXING_TYPES: {
-        ArrayStorage* storage = object->m_butterfly->arrayStorage();
-        
-        unsigned usedVectorLength = std::min(storage->length(), storage->vectorLength());
-        for (unsigned i = 0; i < usedVectorLength; ++i) {
-            if (storage->m_vector[i])
+            
+        case ALL_DOUBLE_INDEXING_TYPES: {
+            Butterfly* butterfly = object->butterfly();
+            unsigned usedLength = butterfly->publicLength();
+            for (unsigned i = 0; i < usedLength; ++i) {
+                double value = butterfly->contiguousDouble()[i];
+                if (value != value)
+                    continue;
                 propertyNames.add(i);
+            }
+            break;
         }
-        
-        if (SparseArrayValueMap* map = storage->m_sparseMap.get()) {
-            Vector<unsigned, 0, UnsafeVectorOverflow> keys;
-            keys.reserveInitialCapacity(map->size());
             
-            SparseArrayValueMap::const_iterator end = map->end();
-            for (SparseArrayValueMap::const_iterator it = map->begin(); it != end; ++it) {
-                if (mode.includeDontEnumProperties() || !(it->value.attributes & DontEnum))
-                    keys.uncheckedAppend(static_cast<unsigned>(it->key));
+        case ALL_ARRAY_STORAGE_INDEXING_TYPES: {
+            ArrayStorage* storage = object->m_butterfly->arrayStorage();
+            
+            unsigned usedVectorLength = std::min(storage->length(), storage->vectorLength());
+            for (unsigned i = 0; i < usedVectorLength; ++i) {
+                if (storage->m_vector[i])
+                    propertyNames.add(i);
             }
             
-            std::sort(keys.begin(), keys.end());
-            for (unsigned i = 0; i < keys.size(); ++i)
-                propertyNames.add(keys[i]);
+            if (SparseArrayValueMap* map = storage->m_sparseMap.get()) {
+                Vector<unsigned, 0, UnsafeVectorOverflow> keys;
+                keys.reserveInitialCapacity(map->size());
+                
+                SparseArrayValueMap::const_iterator end = map->end();
+                for (SparseArrayValueMap::const_iterator it = map->begin(); it != end; ++it) {
+                    if (mode.includeDontEnumProperties() || !(it->value.attributes & DontEnum))
+                        keys.uncheckedAppend(static_cast<unsigned>(it->key));
+                }
+                
+                std::sort(keys.begin(), keys.end());
+                for (unsigned i = 0; i < keys.size(); ++i)
+                    propertyNames.add(keys[i]);
+            }
+            break;
+        }
+            
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
         }
-        break;
-    }
-        
-    default:
-        RELEASE_ASSERT_NOT_REACHED();
     }
 
     object->methodTable(exec->vm())->getOwnNonIndexPropertyNames(object, exec, propertyNames, mode);
index 7e7d1ac..690920f 100644 (file)
@@ -36,7 +36,7 @@ const ClassInfo JSPropertyNameEnumerator::s_info = { "JSPropertyNameEnumerator",
 JSPropertyNameEnumerator* JSPropertyNameEnumerator::create(VM& vm)
 {
     if (!vm.emptyPropertyNameEnumerator.get()) {
-        PropertyNameArray propertyNames(&vm);
+        PropertyNameArray propertyNames(&vm, PropertyNameMode::Strings);
         vm.emptyPropertyNameEnumerator = Strong<JSCell>(vm, create(vm, 0, 0, 0, propertyNames));
     }
     return jsCast<JSPropertyNameEnumerator*>(vm.emptyPropertyNameEnumerator.get());
index 94b0343..c9ece11 100644 (file)
@@ -115,7 +115,7 @@ inline JSPropertyNameEnumerator* propertyNameEnumerator(ExecState* exec, JSObjec
 
     uint32_t numberStructureProperties = 0;
 
-    PropertyNameArray propertyNames(exec);
+    PropertyNameArray propertyNames(exec, PropertyNameMode::Strings);
 
     if (structure->canAccessPropertiesQuickly() && indexedLength == base->getArrayLength()) {
         base->methodTable(vm)->getStructurePropertyNames(base, exec, propertyNames, EnumerationMode());
index c08ff59..20b673a 100644 (file)
@@ -62,7 +62,7 @@ void JSSymbolTableObject::getOwnNonIndexPropertyNames(JSObject* object, ExecStat
         SymbolTable::Map::iterator end = thisObject->symbolTable()->end(locker);
         for (SymbolTable::Map::iterator it = thisObject->symbolTable()->begin(locker); it != end; ++it) {
             if (!(it->value.getAttributes() & DontEnum) || mode.includeDontEnumProperties()) {
-                if (it->key->isSymbol() && !mode.includeSymbolProperties())
+                if (it->key->isSymbol() && !propertyNames.includeSymbolProperties())
                     continue;
                 propertyNames.add(Identifier::fromUid(exec, it->key.get()));
             }
index 1a11e28..f2e1e5a 100644 (file)
@@ -253,7 +253,7 @@ EncodedJSValue JSC_HOST_CALL objectConstructorGetOwnPropertyNames(ExecState* exe
     JSObject* object = exec->argument(0).toObject(exec);
     if (exec->hadException())
         return JSValue::encode(jsNull());
-    PropertyNameArray properties(exec);
+    PropertyNameArray properties(exec, PropertyNameMode::Strings);
     object->methodTable(exec->vm())->getOwnPropertyNames(object, exec, properties, EnumerationMode(DontEnumPropertiesMode::Include));
     JSArray* names = constructEmptyArray(exec, 0);
     size_t numProperties = properties.size();
@@ -268,8 +268,8 @@ EncodedJSValue JSC_HOST_CALL objectConstructorGetOwnPropertySymbols(ExecState* e
     JSObject* object = exec->argument(0).toObject(exec);
     if (exec->hadException())
         return JSValue::encode(jsNull());
-    PropertyNameArray properties(exec);
-    object->methodTable(exec->vm())->getOwnPropertyNames(object, exec, properties, EnumerationMode(DontEnumPropertiesMode::Include, SymbolPropertiesMode::Include));
+    PropertyNameArray properties(exec, PropertyNameMode::Symbols);
+    object->methodTable(exec->vm())->getOwnPropertyNames(object, exec, properties, EnumerationMode(DontEnumPropertiesMode::Include));
     JSArray* names = constructEmptyArray(exec, 0);
     size_t numProperties = properties.size();
     for (size_t i = 0; i < numProperties; i++) {
@@ -286,7 +286,7 @@ EncodedJSValue JSC_HOST_CALL objectConstructorKeys(ExecState* exec)
     JSObject* object = exec->argument(0).toObject(exec);
     if (exec->hadException())
         return JSValue::encode(jsNull());
-    PropertyNameArray properties(exec);
+    PropertyNameArray properties(exec, PropertyNameMode::Strings);
     object->methodTable(exec->vm())->getOwnPropertyNames(object, exec, properties, EnumerationMode());
     JSArray* keys = constructEmptyArray(exec, 0);
     size_t numProperties = properties.size();
@@ -397,8 +397,8 @@ EncodedJSValue JSC_HOST_CALL objectConstructorDefineProperty(ExecState* exec)
 
 static JSValue defineProperties(ExecState* exec, JSObject* object, JSObject* properties)
 {
-    PropertyNameArray propertyNames(exec);
-    asObject(properties)->methodTable(exec->vm())->getOwnPropertyNames(asObject(properties), exec, propertyNames, EnumerationMode(DontEnumPropertiesMode::Exclude, SymbolPropertiesMode::Include));
+    PropertyNameArray propertyNames(exec, PropertyNameMode::Both);
+    asObject(properties)->methodTable(exec->vm())->getOwnPropertyNames(asObject(properties), exec, propertyNames, EnumerationMode(DontEnumPropertiesMode::Exclude));
     size_t numProperties = propertyNames.size();
     Vector<PropertyDescriptor> descriptors;
     MarkedArgumentBuffer markBuffer;
@@ -467,8 +467,8 @@ EncodedJSValue JSC_HOST_CALL objectConstructorSeal(ExecState* exec)
     }
 
     // 2. For each named own property name P of O,
-    PropertyNameArray properties(exec);
-    object->methodTable(exec->vm())->getOwnPropertyNames(object, exec, properties, EnumerationMode(DontEnumPropertiesMode::Include, SymbolPropertiesMode::Include));
+    PropertyNameArray properties(exec, PropertyNameMode::Both);
+    object->methodTable(exec->vm())->getOwnPropertyNames(object, exec, properties, EnumerationMode(DontEnumPropertiesMode::Include));
     PropertyNameArray::const_iterator end = properties.end();
     for (PropertyNameArray::const_iterator iter = properties.begin(); iter != end; ++iter) {
         Identifier propertyName = *iter;
@@ -501,8 +501,8 @@ JSObject* objectConstructorFreeze(ExecState* exec, JSObject* object)
     }
 
     // 2. For each named own property name P of O,
-    PropertyNameArray properties(exec);
-    object->methodTable(exec->vm())->getOwnPropertyNames(object, exec, properties, EnumerationMode(DontEnumPropertiesMode::Include, SymbolPropertiesMode::Include));
+    PropertyNameArray properties(exec, PropertyNameMode::Both);
+    object->methodTable(exec->vm())->getOwnPropertyNames(object, exec, properties, EnumerationMode(DontEnumPropertiesMode::Include));
     PropertyNameArray::const_iterator end = properties.end();
     for (PropertyNameArray::const_iterator iter = properties.begin(); iter != end; ++iter) {
         Identifier propertyName = *iter;
@@ -561,8 +561,8 @@ EncodedJSValue JSC_HOST_CALL objectConstructorIsSealed(ExecState* exec)
         return JSValue::encode(jsBoolean(object->isSealed(exec->vm())));
 
     // 2. For each named own property name P of O,
-    PropertyNameArray properties(exec);
-    object->methodTable(exec->vm())->getOwnPropertyNames(object, exec, properties, EnumerationMode(DontEnumPropertiesMode::Include, SymbolPropertiesMode::Include));
+    PropertyNameArray properties(exec, PropertyNameMode::Both);
+    object->methodTable(exec->vm())->getOwnPropertyNames(object, exec, properties, EnumerationMode(DontEnumPropertiesMode::Include));
     PropertyNameArray::const_iterator end = properties.end();
     for (PropertyNameArray::const_iterator iter = properties.begin(); iter != end; ++iter) {
         Identifier propertyName = *iter;
@@ -594,8 +594,8 @@ EncodedJSValue JSC_HOST_CALL objectConstructorIsFrozen(ExecState* exec)
         return JSValue::encode(jsBoolean(object->isFrozen(exec->vm())));
 
     // 2. For each named own property name P of O,
-    PropertyNameArray properties(exec);
-    object->methodTable(exec->vm())->getOwnPropertyNames(object, exec, properties, EnumerationMode(DontEnumPropertiesMode::Include, SymbolPropertiesMode::Include));
+    PropertyNameArray properties(exec, PropertyNameMode::Both);
+    object->methodTable(exec->vm())->getOwnPropertyNames(object, exec, properties, EnumerationMode(DontEnumPropertiesMode::Include));
     PropertyNameArray::const_iterator end = properties.end();
     for (PropertyNameArray::const_iterator iter = properties.begin(); iter != end; ++iter) {
         Identifier propertyName = *iter;
index c2f13d8..14f6f78 100644 (file)
@@ -48,15 +48,15 @@ private:
 // FIXME: Rename to PropertyNameArrayBuilder.
 class PropertyNameArray {
 public:
-    PropertyNameArray(VM* vm)
+    PropertyNameArray(VM* vm, PropertyNameMode mode)
         : m_data(PropertyNameArrayData::create())
         , m_vm(vm)
+        , m_mode(mode)
     {
     }
 
-    PropertyNameArray(ExecState* exec)
-        : m_data(PropertyNameArrayData::create())
-        , m_vm(&exec->vm())
+    PropertyNameArray(ExecState* exec, PropertyNameMode mode)
+        : PropertyNameArray(&exec->vm(), mode)
     {
     }
 
@@ -85,10 +85,17 @@ public:
     const_iterator begin() const { return m_data->propertyNameVector().begin(); }
     const_iterator end() const { return m_data->propertyNameVector().end(); }
 
+    PropertyNameMode mode() const { return m_mode; }
+    bool includeSymbolProperties() const;
+    bool includeStringProperties() const;
+
 private:
+    bool isUidMatchedToTypeMode(UniquedStringImpl* identifier);
+
     RefPtr<PropertyNameArrayData> m_data;
     HashSet<UniquedStringImpl*> m_set;
     VM* m_vm;
+    PropertyNameMode m_mode;
 };
 
 ALWAYS_INLINE void PropertyNameArray::add(const Identifier& identifier)
@@ -98,6 +105,8 @@ ALWAYS_INLINE void PropertyNameArray::add(const Identifier& identifier)
 
 ALWAYS_INLINE void PropertyNameArray::addKnownUnique(UniquedStringImpl* identifier)
 {
+    if (!isUidMatchedToTypeMode(identifier))
+        return;
     m_data->propertyNameVector().append(Identifier::fromUid(m_vm, identifier));
 }
 
@@ -107,6 +116,9 @@ ALWAYS_INLINE void PropertyNameArray::add(UniquedStringImpl* identifier)
 
     ASSERT(identifier);
 
+    if (!isUidMatchedToTypeMode(identifier))
+        return;
+
     if (size() < setThreshold) {
         if (m_data->propertyNameVector().contains(identifier))
             return;
@@ -122,6 +134,23 @@ ALWAYS_INLINE void PropertyNameArray::add(UniquedStringImpl* identifier)
     addKnownUnique(identifier);
 }
 
+ALWAYS_INLINE bool PropertyNameArray::isUidMatchedToTypeMode(UniquedStringImpl* identifier)
+{
+    if (identifier->isSymbol())
+        return includeSymbolProperties();
+    return includeStringProperties();
+}
+
+ALWAYS_INLINE bool PropertyNameArray::includeSymbolProperties() const
+{
+    return static_cast<std::underlying_type<PropertyNameMode>::type>(m_mode) & static_cast<std::underlying_type<PropertyNameMode>::type>(PropertyNameMode::Symbols);
+}
+
+ALWAYS_INLINE bool PropertyNameArray::includeStringProperties() const
+{
+    return static_cast<std::underlying_type<PropertyNameMode>::type>(m_mode) & static_cast<std::underlying_type<PropertyNameMode>::type>(PropertyNameMode::Strings);
+}
+
 } // namespace JSC
 
 #endif // PropertyNameArray_h
index eb7430e..b5aa3f7 100644 (file)
@@ -146,9 +146,11 @@ bool StringObject::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned
 void StringObject::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
 {
     StringObject* thisObject = jsCast<StringObject*>(object);
-    int size = thisObject->internalValue()->length();
-    for (int i = 0; i < size; ++i)
-        propertyNames.add(Identifier::from(exec, i));
+    if (propertyNames.includeStringProperties()) {
+        int size = thisObject->internalValue()->length();
+        for (int i = 0; i < size; ++i)
+            propertyNames.add(Identifier::from(exec, i));
+    }
     if (mode.includeDontEnumProperties())
         propertyNames.add(exec->propertyNames().length);
     return JSObject::getOwnPropertyNames(thisObject, exec, propertyNames, mode);
index ca097f7..98d3fc2 100644 (file)
@@ -947,7 +947,7 @@ void Structure::getPropertyNamesFromStructure(VM& vm, PropertyNameArray& propert
     for (PropertyTable::iterator iter = propertyTable()->begin(); iter != end; ++iter) {
         ASSERT(hasNonEnumerableProperties() || !(iter->attributes & DontEnum));
         if (!(iter->attributes & DontEnum) || mode.includeDontEnumProperties()) {
-            if (iter->key->isSymbol() && !mode.includeSymbolProperties())
+            if (iter->key->isSymbol() && !propertyNames.includeSymbolProperties())
                 continue;
             if (knownUnique)
                 propertyNames.addKnownUnique(iter->key);
index a8ef7c0..2e68137 100644 (file)
@@ -1,3 +1,18 @@
+2015-07-24  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        Object.getOwnPropertySymbols on large list takes very long
+        https://bugs.webkit.org/show_bug.cgi?id=146137
+
+        Reviewed by Mark Lam.
+
+        * bindings/js/Dictionary.cpp:
+        (WebCore::Dictionary::getOwnPropertiesAsStringHashMap):
+        (WebCore::Dictionary::getOwnPropertyNames):
+        * bindings/js/SerializedScriptValue.cpp:
+        (WebCore::CloneSerializer::serialize):
+        * bridge/NP_jsobject.cpp:
+        (_NPN_Enumerate):
+
 2015-07-24  David Kilzer  <ddkilzer@apple.com>
 
         REGRESSION (r187149): Build fails when CSS_SELECTORS_LEVEL4 is disabled
index 5c2436a..9390400 100644 (file)
@@ -62,7 +62,7 @@ bool Dictionary::getOwnPropertiesAsStringHashMap(HashMap<String, String>& map) c
     JSObject* object =  m_dictionary.initializerObject();
     ExecState* exec = m_dictionary.execState();
 
-    PropertyNameArray propertyNames(exec);
+    PropertyNameArray propertyNames(exec, PropertyNameMode::Strings);
     JSObject::getOwnPropertyNames(object, exec, propertyNames, EnumerationMode());
     for (PropertyNameArray::const_iterator it = propertyNames.begin(); it != propertyNames.end(); ++it) {
         String stringKey = it->string();
@@ -87,7 +87,7 @@ bool Dictionary::getOwnPropertyNames(Vector<String>& names) const
     JSObject* object =  m_dictionary.initializerObject();
     ExecState* exec = m_dictionary.execState();
 
-    PropertyNameArray propertyNames(exec);
+    PropertyNameArray propertyNames(exec, PropertyNameMode::Strings);
     JSObject::getOwnPropertyNames(object, exec, propertyNames, EnumerationMode());
     for (PropertyNameArray::const_iterator it = propertyNames.begin(); it != propertyNames.end(); ++it) {
         String stringKey = it->string();
index 6786119..de0c52b 100644 (file)
@@ -1254,7 +1254,7 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in)
                     indexStack.removeLast();
                     lengthStack.removeLast();
 
-                    propertyStack.append(PropertyNameArray(m_exec));
+                    propertyStack.append(PropertyNameArray(m_exec, PropertyNameMode::Strings));
                     array->methodTable()->getOwnNonIndexPropertyNames(array, m_exec, propertyStack.last(), EnumerationMode());
                     if (propertyStack.last().size()) {
                         write(NonIndexPropertiesTag);
@@ -1304,7 +1304,7 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in)
                     return DataCloneError;
                 inputObjectStack.append(inObject);
                 indexStack.append(0);
-                propertyStack.append(PropertyNameArray(m_exec));
+                propertyStack.append(PropertyNameArray(m_exec, PropertyNameMode::Strings));
                 inObject->methodTable()->getOwnPropertyNames(inObject, m_exec, propertyStack.last(), EnumerationMode());
             }
             objectStartVisitMember:
@@ -1372,7 +1372,7 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in)
                     mapIteratorStack.removeLast();
                     JSObject* object = inputObjectStack.last();
                     ASSERT(jsDynamicCast<JSMap*>(object));
-                    propertyStack.append(PropertyNameArray(m_exec));
+                    propertyStack.append(PropertyNameArray(m_exec, PropertyNameMode::Strings));
                     object->methodTable()->getOwnPropertyNames(object, m_exec, propertyStack.last(), EnumerationMode());
                     write(NonMapPropertiesTag);
                     indexStack.append(0);
@@ -1416,7 +1416,7 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in)
                     setIteratorStack.removeLast();
                     JSObject* object = inputObjectStack.last();
                     ASSERT(jsDynamicCast<JSSet*>(object));
-                    propertyStack.append(PropertyNameArray(m_exec));
+                    propertyStack.append(PropertyNameArray(m_exec, PropertyNameMode::Strings));
                     object->methodTable()->getOwnPropertyNames(object, m_exec, propertyStack.last(), EnumerationMode());
                     write(NonSetPropertiesTag);
                     indexStack.append(0);
index 094b1ae..59c9c74 100644 (file)
@@ -445,7 +445,7 @@ bool _NPN_Enumerate(NPP, NPObject* o, NPIdentifier** identifier, uint32_t* count
         
         ExecState* exec = rootObject->globalObject()->globalExec();
         JSLockHolder lock(exec);
-        PropertyNameArray propertyNames(exec);
+        PropertyNameArray propertyNames(exec, PropertyNameMode::Strings);
 
         obj->imp->methodTable()->getPropertyNames(obj->imp, exec, propertyNames, EnumerationMode());
         unsigned size = static_cast<unsigned>(propertyNames.size());
index 119b1f2..7e9f2f6 100644 (file)
@@ -1,3 +1,13 @@
+2015-07-24  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        Object.getOwnPropertySymbols on large list takes very long
+        https://bugs.webkit.org/show_bug.cgi?id=146137
+
+        Reviewed by Mark Lam.
+
+        * Plugins/Hosted/NetscapePluginInstanceProxy.mm:
+        (WebKit::NetscapePluginInstanceProxy::enumerate):
+
 2015-07-23  Alex Christensen  <achristensen@webkit.org>
 
         Remove compile and runtime flags for promises.
index abae781..76c4655 100644 (file)
@@ -1230,7 +1230,7 @@ bool NetscapePluginInstanceProxy::enumerate(uint32_t objectID, data_t& resultDat
     ExecState* exec = frame->script().globalObject(pluginWorld())->globalExec();
     JSLockHolder lock(exec);
  
-    PropertyNameArray propertyNames(exec);
+    PropertyNameArray propertyNames(exec, PropertyNameMode::Strings);
     object->methodTable()->getPropertyNames(object, exec, propertyNames, EnumerationMode());
 
     RetainPtr<NSMutableArray*> array = adoptNS([[NSMutableArray alloc] init]);
index 2e51545..8b0535f 100644 (file)
@@ -1,3 +1,13 @@
+2015-07-24  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        Object.getOwnPropertySymbols on large list takes very long
+        https://bugs.webkit.org/show_bug.cgi?id=146137
+
+        Reviewed by Mark Lam.
+
+        * WebProcess/Plugins/Netscape/NPJSObject.cpp:
+        (WebKit::NPJSObject::enumerate):
+
 2015-07-24  Simon Fraser  <simon.fraser@apple.com>
 
         Recode.net gets into a continual resize loop in split fullscreen
index 20dc4d8..ffc7793 100644 (file)
@@ -239,7 +239,7 @@ bool NPJSObject::enumerate(NPIdentifier** identifiers, uint32_t* identifierCount
     
     JSLockHolder lock(exec);
 
-    PropertyNameArray propertyNames(exec);
+    PropertyNameArray propertyNames(exec, PropertyNameMode::Strings);
     m_jsObject->methodTable()->getPropertyNames(m_jsObject.get(), exec, propertyNames, EnumerationMode());
 
     NPIdentifier* nameIdentifiers = npnMemNewArray<NPIdentifier>(propertyNames.size());