Title: [221783] trunk
Revision
221783
Author
[email protected]
Date
2017-09-08 08:36:05 -0700 (Fri, 08 Sep 2017)

Log Message

[DFG][FTL] GetByVal(ObjectUse with Array::Generic, StringUse/SymbolUse) should be supported
https://bugs.webkit.org/show_bug.cgi?id=176590

Reviewed by Saam Barati.

JSTests:

* microbenchmarks/object-iterate-symbols.js: Added.
(test):
* microbenchmarks/object-iterate.js: Added.
(test):
* stress/object-iterate-symbols.js: Added.
(shouldBe):
(test):
* stress/object-iterate.js: Added.
(shouldBe):
(test):

Source/_javascript_Core:

We add fixup edges for GetByVal(Array::Generic) to call faster operation instead of generic operationGetByVal.

                                 baseline                  patched

object-iterate                5.8531+-0.3029            5.7903+-0.2795          might be 1.0108x faster
object-iterate-symbols        7.4099+-0.3993     ^      5.8254+-0.2276        ^ definitely 1.2720x faster

* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGOperations.cpp:
(JSC::DFG::getByValObject):
* dfg/DFGOperations.h:
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileGetByValForObjectWithString):
(JSC::DFG::SpeculativeJIT::compileGetByValForObjectWithSymbol):
* dfg/DFGSpeculativeJIT.h:
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileGetByVal):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (221782 => 221783)


--- trunk/JSTests/ChangeLog	2017-09-08 10:57:35 UTC (rev 221782)
+++ trunk/JSTests/ChangeLog	2017-09-08 15:36:05 UTC (rev 221783)
@@ -1,3 +1,21 @@
+2017-09-08  Yusuke Suzuki  <[email protected]>
+
+        [DFG][FTL] GetByVal(ObjectUse with Array::Generic, StringUse/SymbolUse) should be supported
+        https://bugs.webkit.org/show_bug.cgi?id=176590
+
+        Reviewed by Saam Barati.
+
+        * microbenchmarks/object-iterate-symbols.js: Added.
+        (test):
+        * microbenchmarks/object-iterate.js: Added.
+        (test):
+        * stress/object-iterate-symbols.js: Added.
+        (shouldBe):
+        (test):
+        * stress/object-iterate.js: Added.
+        (shouldBe):
+        (test):
+
 2017-09-07  Per Arne Vollan  <[email protected]>
 
         [Win32] 10 JSC stress tests are failing.

Added: trunk/JSTests/microbenchmarks/object-iterate-symbols.js (0 => 221783)


--- trunk/JSTests/microbenchmarks/object-iterate-symbols.js	                        (rev 0)
+++ trunk/JSTests/microbenchmarks/object-iterate-symbols.js	2017-09-08 15:36:05 UTC (rev 221783)
@@ -0,0 +1,27 @@
+var a = Symbol("a");
+var b = Symbol("b");
+var c = Symbol("c");
+var d = Symbol("d");
+var e = Symbol("e");
+
+var obj = {
+    [a]: 1,
+    [b]: 2,
+    [c]: 3,
+    [d]: null,
+    [e]: 'e'
+};
+
+function test(src) {
+    var array = [];
+    var keys = Object.getOwnPropertySymbols(src);
+    for (var i = 0; i < keys.length; ++i) {
+        var key = keys[i];
+        array.push(src[key]);
+    }
+    return array;
+}
+noInline(test);
+
+for (var i = 0; i < 1e4; ++i)
+    test(obj);

Added: trunk/JSTests/microbenchmarks/object-iterate.js (0 => 221783)


--- trunk/JSTests/microbenchmarks/object-iterate.js	                        (rev 0)
+++ trunk/JSTests/microbenchmarks/object-iterate.js	2017-09-08 15:36:05 UTC (rev 221783)
@@ -0,0 +1,21 @@
+var obj = {
+    a: 1,
+    b: 2,
+    c: 3,
+    d: null,
+    e: 'e'
+};
+
+function test(src) {
+    var array = [];
+    var keys = Object.keys(src);
+    for (var i = 0; i < keys.length; ++i) {
+        var key = keys[i];
+        array.push(src[key]);
+    }
+    return array;
+}
+noInline(test);
+
+for (var i = 0; i < 1e4; ++i)
+    test(obj);

Added: trunk/JSTests/stress/object-iterate-symbols.js (0 => 221783)


--- trunk/JSTests/stress/object-iterate-symbols.js	                        (rev 0)
+++ trunk/JSTests/stress/object-iterate-symbols.js	2017-09-08 15:36:05 UTC (rev 221783)
@@ -0,0 +1,32 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+var a = Symbol("a");
+var b = Symbol("b");
+var c = Symbol("c");
+var d = Symbol("d");
+var e = Symbol("e");
+
+var obj = {
+    [a]: 1,
+    [b]: 2,
+    [c]: 3,
+    [d]: null,
+    [e]: 'e'
+};
+
+function test(src) {
+    var array = [];
+    var keys = Object.getOwnPropertySymbols(src);
+    for (var i = 0; i < keys.length; ++i) {
+        var key = keys[i];
+        array.push(src[key]);
+    }
+    return array;
+}
+noInline(test);
+
+for (var i = 0; i < 1e4; ++i)
+    shouldBe(JSON.stringify(test(obj)), `[1,2,3,null,"e"]`);

Added: trunk/JSTests/stress/object-iterate.js (0 => 221783)


--- trunk/JSTests/stress/object-iterate.js	                        (rev 0)
+++ trunk/JSTests/stress/object-iterate.js	2017-09-08 15:36:05 UTC (rev 221783)
@@ -0,0 +1,26 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+var obj = {
+    a: 1,
+    b: 2,
+    c: 3,
+    d: null,
+    e: 'e'
+};
+
+function test(src) {
+    var array = [];
+    var keys = Object.keys(src);
+    for (var i = 0; i < keys.length; ++i) {
+      var key = keys[i];
+      array.push(src[key]);
+    }
+    return array;
+}
+noInline(test);
+
+for (var i = 0; i < 1e4; ++i)
+    shouldBe(JSON.stringify(test(obj)), `[1,2,3,null,"e"]`);

Modified: trunk/Source/_javascript_Core/ChangeLog (221782 => 221783)


--- trunk/Source/_javascript_Core/ChangeLog	2017-09-08 10:57:35 UTC (rev 221782)
+++ trunk/Source/_javascript_Core/ChangeLog	2017-09-08 15:36:05 UTC (rev 221783)
@@ -1,3 +1,33 @@
+2017-09-08  Yusuke Suzuki  <[email protected]>
+
+        [DFG][FTL] GetByVal(ObjectUse with Array::Generic, StringUse/SymbolUse) should be supported
+        https://bugs.webkit.org/show_bug.cgi?id=176590
+
+        Reviewed by Saam Barati.
+
+        We add fixup edges for GetByVal(Array::Generic) to call faster operation instead of generic operationGetByVal.
+
+                                         baseline                  patched
+
+        object-iterate                5.8531+-0.3029            5.7903+-0.2795          might be 1.0108x faster
+        object-iterate-symbols        7.4099+-0.3993     ^      5.8254+-0.2276        ^ definitely 1.2720x faster
+
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * dfg/DFGOperations.cpp:
+        (JSC::DFG::getByValObject):
+        * dfg/DFGOperations.h:
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileGetByValForObjectWithString):
+        (JSC::DFG::SpeculativeJIT::compileGetByValForObjectWithSymbol):
+        * dfg/DFGSpeculativeJIT.h:
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileGetByVal):
+
 2017-09-07  Mark Lam  <[email protected]>
 
         Use JIT probes for DFG OSR exit.

Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (221782 => 221783)


--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2017-09-08 10:57:35 UTC (rev 221782)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2017-09-08 15:36:05 UTC (rev 221783)
@@ -788,6 +788,19 @@
                 RELEASE_ASSERT_NOT_REACHED();
                 break;
             case Array::Generic:
+                if (node->child1()->shouldSpeculateObject()) {
+                    if (node->child2()->shouldSpeculateString()) {
+                        fixEdge<ObjectUse>(node->child1());
+                        fixEdge<StringUse>(node->child2());
+                        break;
+                    }
+
+                    if (node->child2()->shouldSpeculateSymbol()) {
+                        fixEdge<ObjectUse>(node->child1());
+                        fixEdge<SymbolUse>(node->child2());
+                        break;
+                    }
+                }
 #if USE(JSVALUE32_64)
                 fixEdge<CellUse>(node->child1()); // Speculating cell due to register pressure on 32-bit.
 #endif

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (221782 => 221783)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2017-09-08 10:57:35 UTC (rev 221782)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2017-09-08 15:36:05 UTC (rev 221783)
@@ -184,6 +184,16 @@
     return JSValue::encode(jsNumber(input));
 }
 
+ALWAYS_INLINE static JSValue getByValObject(ExecState* exec, VM& vm, JSObject* base, PropertyName propertyName)
+{
+    Structure& structure = *base->structure(vm);
+    if (JSCell::canUseFastGetOwnProperty(structure)) {
+        if (JSValue result = base->fastGetOwnProperty(vm, structure, propertyName))
+            return result;
+    }
+    return base->get(exec, propertyName);
+}
+
 extern "C" {
 
 EncodedJSValue JIT_OPERATION operationToThis(ExecState* exec, EncodedJSValue encodedOp)
@@ -584,6 +594,28 @@
     return getByValCellInt(exec, base, index);
 }
 
+EncodedJSValue JIT_OPERATION operationGetByValObjectString(ExecState* exec, JSCell* base, JSCell* string)
+{
+    VM& vm = exec->vm();
+    NativeCallFrameTracer tracer(&vm, exec);
+
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    auto propertyName = asString(string)->toIdentifier(exec);
+    RETURN_IF_EXCEPTION(scope, encodedJSValue());
+
+    scope.release();
+    return JSValue::encode(getByValObject(exec, vm, asObject(base), propertyName));
+}
+
+EncodedJSValue JIT_OPERATION operationGetByValObjectSymbol(ExecState* exec, JSCell* base, JSCell* symbol)
+{
+    VM& vm = exec->vm();
+    NativeCallFrameTracer tracer(&vm, exec);
+
+    return JSValue::encode(getByValObject(exec, vm, asObject(base), asSymbol(symbol)->privateName()));
+}
+
 void JIT_OPERATION operationPutByValStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
 {
     VM* vm = &exec->vm();

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.h (221782 => 221783)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.h	2017-09-08 10:57:35 UTC (rev 221782)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.h	2017-09-08 15:36:05 UTC (rev 221783)
@@ -71,6 +71,8 @@
 EncodedJSValue JIT_OPERATION operationGetByValCell(ExecState*, JSCell*, EncodedJSValue encodedProperty) WTF_INTERNAL;
 EncodedJSValue JIT_OPERATION operationGetByValObjectInt(ExecState*, JSObject*, int32_t) WTF_INTERNAL;
 EncodedJSValue JIT_OPERATION operationGetByValStringInt(ExecState*, JSString*, int32_t) WTF_INTERNAL;
+EncodedJSValue JIT_OPERATION operationGetByValObjectString(ExecState*, JSCell*, JSCell* string) WTF_INTERNAL;
+EncodedJSValue JIT_OPERATION operationGetByValObjectSymbol(ExecState*, JSCell*, JSCell* symbol) WTF_INTERNAL;
 EncodedJSValue JIT_OPERATION operationToPrimitive(ExecState*, EncodedJSValue) WTF_INTERNAL;
 EncodedJSValue JIT_OPERATION operationToNumber(ExecState*, EncodedJSValue) WTF_INTERNAL;
 EncodedJSValue JIT_OPERATION operationGetByIdWithThis(ExecState*, EncodedJSValue, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (221782 => 221783)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2017-09-08 10:57:35 UTC (rev 221782)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2017-09-08 15:36:05 UTC (rev 221783)
@@ -3144,6 +3144,62 @@
     noResult(node);
 }
 
+void SpeculativeJIT::compileGetByValForObjectWithString(Node* node)
+{
+    SpeculateCellOperand arg1(this, node->child1());
+    SpeculateCellOperand arg2(this, node->child2());
+
+    GPRReg arg1GPR = arg1.gpr();
+    GPRReg arg2GPR = arg2.gpr();
+
+    speculateObject(node->child1(), arg1GPR);
+    speculateString(node->child2(), arg2GPR);
+
+    GPRFlushedCallResult resultPayload(this);
+    GPRReg resultPayloadGPR = resultPayload.gpr();
+#if USE(JSVALUE64)
+    JSValueRegs resultRegs(resultPayloadGPR);
+#else
+    GPRFlushedCallResult2 resultTag(this);
+    GPRReg resultTagGPR = resultTag.gpr();
+    JSValueRegs resultRegs(resultTagGPR, resultPayloadGPR);
+#endif
+
+    flushRegisters();
+    callOperation(operationGetByValObjectString, extractResult(resultRegs), arg1GPR, arg2GPR);
+    m_jit.exceptionCheck();
+
+    jsValueResult(resultRegs, node);
+}
+
+void SpeculativeJIT::compileGetByValForObjectWithSymbol(Node* node)
+{
+    SpeculateCellOperand arg1(this, node->child1());
+    SpeculateCellOperand arg2(this, node->child2());
+
+    GPRReg arg1GPR = arg1.gpr();
+    GPRReg arg2GPR = arg2.gpr();
+
+    speculateObject(node->child1(), arg1GPR);
+    speculateSymbol(node->child2(), arg2GPR);
+
+    GPRFlushedCallResult resultPayload(this);
+    GPRReg resultPayloadGPR = resultPayload.gpr();
+#if USE(JSVALUE64)
+    JSValueRegs resultRegs(resultPayloadGPR);
+#else
+    GPRFlushedCallResult2 resultTag(this);
+    GPRReg resultTagGPR = resultTag.gpr();
+    JSValueRegs resultRegs(resultTagGPR, resultPayloadGPR);
+#endif
+
+    flushRegisters();
+    callOperation(operationGetByValObjectSymbol, extractResult(resultRegs), arg1GPR, arg2GPR);
+    m_jit.exceptionCheck();
+
+    jsValueResult(resultRegs, node);
+}
+
 void SpeculativeJIT::compileInstanceOfForObject(Node*, GPRReg valueReg, GPRReg prototypeReg, GPRReg scratchReg, GPRReg scratch2Reg)
 {
     // Check that prototype is an object.

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (221782 => 221783)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h	2017-09-08 10:57:35 UTC (rev 221782)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h	2017-09-08 15:36:05 UTC (rev 221783)
@@ -2873,6 +2873,8 @@
     void compilePutByValForIntTypedArray(GPRReg base, GPRReg property, Node*, TypedArrayType);
     void compileGetByValOnFloatTypedArray(Node*, TypedArrayType);
     void compilePutByValForFloatTypedArray(GPRReg base, GPRReg property, Node*, TypedArrayType);
+    void compileGetByValForObjectWithString(Node*);
+    void compileGetByValForObjectWithSymbol(Node*);
     // If this returns false it means that we terminated speculative execution.
     bool getIntTypedArrayStoreOperand(
         GPRTemporary& value,

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (221782 => 221783)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2017-09-08 10:57:35 UTC (rev 221782)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2017-09-08 15:36:05 UTC (rev 221783)
@@ -2593,6 +2593,18 @@
             break;
         }
         case Array::Generic: {
+            if (node->child1().useKind() == ObjectUse) {
+                if (node->child2().useKind() == StringUse) {
+                    compileGetByValForObjectWithString(node);
+                    break;
+                }
+
+                if (node->child2().useKind() == SymbolUse) {
+                    compileGetByValForObjectWithSymbol(node);
+                    break;
+                }
+            }
+
             SpeculateCellOperand base(this, node->child1()); // Save a register, speculate cell. We'll probably be right.
             JSValueOperand property(this, node->child2());
             GPRReg baseGPR = base.gpr();

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (221782 => 221783)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2017-09-08 10:57:35 UTC (rev 221782)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2017-09-08 15:36:05 UTC (rev 221783)
@@ -2729,6 +2729,17 @@
             break;
         }
         case Array::Generic: {
+            if (node->child1().useKind() == ObjectUse) {
+                if (node->child2().useKind() == StringUse) {
+                    compileGetByValForObjectWithString(node);
+                    break;
+                }
+
+                if (node->child2().useKind() == SymbolUse) {
+                    compileGetByValForObjectWithSymbol(node);
+                    break;
+                }
+            }
             JSValueOperand base(this, node->child1());
             JSValueOperand property(this, node->child2());
             GPRReg baseGPR = base.gpr();

Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (221782 => 221783)


--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2017-09-08 10:57:35 UTC (rev 221782)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2017-09-08 15:36:05 UTC (rev 221783)
@@ -3673,6 +3673,21 @@
         }
             
         case Array::Generic: {
+            if (m_node->child1().useKind() == ObjectUse) {
+                if (m_node->child2().useKind() == StringUse) {
+                    setJSValue(vmCall(
+                        Int64, m_out.operation(operationGetByValObjectString), m_callFrame,
+                        lowObject(m_node->child1()), lowString(m_node->child2())));
+                    return;
+                }
+
+                if (m_node->child2().useKind() == SymbolUse) {
+                    setJSValue(vmCall(
+                        Int64, m_out.operation(operationGetByValObjectSymbol), m_callFrame,
+                        lowObject(m_node->child1()), lowSymbol(m_node->child2())));
+                    return;
+                }
+            }
             setJSValue(vmCall(
                 Int64, m_out.operation(operationGetByVal), m_callFrame,
                 lowJSValue(m_node->child1()), lowJSValue(m_node->child2())));
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to