Unreviewed, rolling in r201436.
authorggaren@apple.com <ggaren@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 1 Jun 2016 22:22:04 +0000 (22:22 +0000)
committerggaren@apple.com <ggaren@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 1 Jun 2016 22:22:04 +0000 (22:22 +0000)
https://bugs.webkit.org/show_bug.cgi?id=158143

r201562 should haved fixed the Dromaeo DOM core regression.

Restored changeset:

"REGRESSION: JSBench spends a lot of time transitioning
to/from dictionary"
https://bugs.webkit.org/show_bug.cgi?id=158045
http://trac.webkit.org/changeset/201436

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

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bytecode/ObjectPropertyConditionSet.cpp
Source/JavaScriptCore/interpreter/Interpreter.cpp
Source/JavaScriptCore/runtime/BatchedTransitionOptimizer.h
Source/JavaScriptCore/runtime/JSGlobalObject.cpp
Source/JavaScriptCore/runtime/Operations.cpp
Source/JavaScriptCore/runtime/Operations.h

index 293ceb6..07d6976 100644 (file)
@@ -1,3 +1,18 @@
+2016-06-01  Geoffrey Garen  <ggaren@apple.com>
+
+        Unreviewed, rolling in r201436.
+        https://bugs.webkit.org/show_bug.cgi?id=158143
+
+        r201562 should haved fixed the Dromaeo DOM core regression.
+
+        Restored changeset:
+
+        "REGRESSION: JSBench spends a lot of time transitioning
+        to/from dictionary"
+        https://bugs.webkit.org/show_bug.cgi?id=158045
+        http://trac.webkit.org/changeset/201436
+
+
 2016-06-01  Commit Queue  <commit-queue@webkit.org>
 
         Unreviewed, rolling out r201488.
index d570040..43dc168 100644 (file)
@@ -251,12 +251,18 @@ ObjectPropertyConditionSet generateConditions(
         JSObject* object = jsCast<JSObject*>(value);
         structure = object->structure(vm);
         
-        // Since we're accessing a prototype repeatedly, it's a good bet that it should not be
-        // treated as a dictionary.
         if (structure->isDictionary()) {
-            if (concurrency == MainThread)
+            if (concurrency == MainThread) {
+                if (structure->hasBeenFlattenedBefore()) {
+                    if (verbose)
+                        dataLog("Dictionary has been flattened before, so invalid.\n");
+                    return ObjectPropertyConditionSet::invalid();
+                }
+
+                if (verbose)
+                    dataLog("Flattening ", pointerDump(structure));
                 structure->flattenDictionaryStructure(vm, object);
-            else {
+            else {
                 if (verbose)
                     dataLog("Cannot flatten dictionary when not on main thread, so invalid.\n");
                 return ObjectPropertyConditionSet::invalid();
index 2ed8898..a0ae2d6 100644 (file)
@@ -941,6 +941,9 @@ failedJSONP:
     if (UNLIKELY(vm.shouldTriggerTermination(callFrame)))
         return throwTerminatedExecutionException(callFrame);
 
+    if (scope->structure()->isUncacheableDictionary())
+        scope->flattenDictionaryObject(vm);
+
     ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
 
     ProtoCallFrame protoCallFrame;
@@ -1189,6 +1192,9 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue
         }
     }
 
+    if (variableObject->structure()->isUncacheableDictionary())
+        variableObject->flattenDictionaryObject(vm);
+
     if (numVariables || numFunctions) {
         BatchedTransitionOptimizer optimizer(vm, variableObject);
         if (variableObject->next())
@@ -1246,6 +1252,9 @@ JSValue Interpreter::execute(ModuleProgramExecutable* executable, CallFrame* cal
     if (UNLIKELY(vm.shouldTriggerTermination(callFrame)))
         return throwTerminatedExecutionException(callFrame);
 
+    if (scope->structure()->isUncacheableDictionary())
+        scope->flattenDictionaryObject(vm);
+
     ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
 
     // The |this| of the module is always `undefined`.
index 951a328..f955d75 100644 (file)
@@ -35,22 +35,10 @@ class BatchedTransitionOptimizer {
     WTF_MAKE_NONCOPYABLE(BatchedTransitionOptimizer);
 public:
     BatchedTransitionOptimizer(VM& vm, JSObject* object)
-        : m_vm(&vm)
-        , m_object(object)
     {
-        if (!m_object->structure(vm)->isDictionary())
-            m_object->convertToDictionary(vm);
+        if (!object->structure(vm)->isDictionary())
+            object->convertToDictionary(vm);
     }
-
-    ~BatchedTransitionOptimizer()
-    {
-        if (m_object->structure()->isDictionary())
-            m_object->flattenDictionaryObject(*m_vm);
-    }
-
-private:
-    VM* m_vm;
-    JSObject* m_object;
 };
 
 } // namespace JSC
index 7a5b05c..561e34d 100644 (file)
@@ -319,6 +319,8 @@ void JSGlobalObject::init(VM& vm)
 {
     ASSERT(vm.currentThreadIsHoldingAPILock());
 
+    Base::setStructure(vm, Structure::toCacheableDictionaryTransition(vm, structure()));
+
     JSGlobalObject::globalExec()->init(0, 0, CallFrame::noCaller(), 0, 0);
 
     m_debugger = 0;
index de893c1..01a33a1 100644 (file)
@@ -120,4 +120,27 @@ bool jsIsFunctionType(JSValue v)
     return false;
 }
 
+size_t normalizePrototypeChain(CallFrame* callFrame, Structure* structure)
+{
+    VM& vm = callFrame->vm();
+    size_t count = 0;
+    while (1) {
+        if (structure->isProxy())
+            return InvalidPrototypeChain;
+        JSValue v = structure->prototypeForLookup(callFrame);
+        if (v.isNull())
+            return count;
+
+        JSCell* base = v.asCell();
+        structure = base->structure(vm);
+        if (structure->isDictionary()) {
+            if (structure->hasBeenFlattenedBefore())
+                return InvalidPrototypeChain;
+            structure->flattenDictionaryStructure(vm, asObject(base));
+        }
+
+        ++count;
+    }
+}
+
 } // namespace JSC
index 057f594..45fbfc6 100644 (file)
 
 namespace JSC {
 
+#define InvalidPrototypeChain (std::numeric_limits<size_t>::max())
+
 NEVER_INLINE JSValue jsAddSlowCase(CallFrame*, JSValue, JSValue);
 JSValue jsTypeStringForValue(CallFrame*, JSValue);
 JSValue jsTypeStringForValue(VM&, JSGlobalObject*, JSValue);
 bool jsIsObjectTypeOrNull(CallFrame*, JSValue);
 bool jsIsFunctionType(JSValue);
+size_t normalizePrototypeChain(CallFrame*, Structure*);
 
 ALWAYS_INLINE JSValue jsString(ExecState* exec, JSString* s1, JSString* s2)
 {
@@ -192,30 +195,6 @@ ALWAYS_INLINE JSValue jsAdd(CallFrame* callFrame, JSValue v1, JSValue v2)
     return jsAddSlowCase(callFrame, v1, v2);
 }
 
-#define InvalidPrototypeChain (std::numeric_limits<size_t>::max())
-
-inline size_t normalizePrototypeChain(CallFrame* callFrame, Structure* structure)
-{
-    VM& vm = callFrame->vm();
-    size_t count = 0;
-    while (1) {
-        if (structure->isProxy())
-            return InvalidPrototypeChain;
-        JSValue v = structure->prototypeForLookup(callFrame);
-        if (v.isNull())
-            return count;
-
-        JSCell* base = v.asCell();
-        structure = base->structure(vm);
-        // Since we're accessing a prototype in a loop, it's a good bet that it
-        // should not be treated as a dictionary.
-        if (structure->isDictionary())
-            structure->flattenDictionaryStructure(vm, asObject(base));
-
-        ++count;
-    }
-}
-
 } // namespace JSC
 
 #endif // Operations_h