Title: [283095] trunk
Revision
283095
Author
ysuz...@apple.com
Date
2021-09-26 21:14:23 -0700 (Sun, 26 Sep 2021)

Log Message

[JSC] Optimize PutByVal with for-in
https://bugs.webkit.org/show_bug.cgi?id=230801

Reviewed by Saam Barati.

JSTests:

* stress/for-in-sentinel.js: Added.
(shouldBe):
(test):

Source/_javascript_Core:

We found that some of Speedometer2 subtests are heavily using for-in with PutByVal or the other DFG nodes.
And we also found that we are using polluted non-good type for the property names from for-in: String | Other.
The reason is that we are returning null when op_enumerator_next finishes instead of string. And this design
forces DFG and FTL to return null from EnumeratorNextUpdatePropertyName at the end of iteration. This pollutes
the type of property names as String | Other instead of String, and leading to suboptimal DFG nodes.

In this patch, we add special sentinel string in vm.smallString.sentinelString(). We know that this string cell
pointer will be never returned from EnumeratorNextUpdatePropertyName in the normal for-in iteration. This is easy
since we are always allocating a JSString when creating JSPropertyNameEnumerator. So this string cell (not the content)
is always different from pre-allocated vm.smallString.sentinelString(). So, we use this special string pointer
as a sentinel instead of null so that we can avoid polluting return type of EnumeratorNextUpdatePropertyName.

To check the sentinel in LLInt / Baseline, this patch adds jeq_ptr, which performs cell pointer comparison and do
not check string content equality. We do not need to have an implementation in DFG since we already have CompareEqPtr
for existing jneq_ptr bytecode.

We also clean up DFG operation related to PutByVal.

----------------------------------------------------------------------------------------------------------------------------------
|               subtest                |     ms      |     ms      |  b / a   | pValue (significance using False Discovery Rate) |
----------------------------------------------------------------------------------------------------------------------------------
| Elm-TodoMVC                          |116.010000   |112.701667   |0.971482  | 0.000000 (significant)                           |
| VueJS-TodoMVC                        |22.995000    |23.023333    |1.001232  | 0.907086                                         |
| EmberJS-TodoMVC                      |125.498333   |125.525000   |1.000212  | 0.932546                                         |
| BackboneJS-TodoMVC                   |45.700000    |45.975000    |1.006018  | 0.084799                                         |
| Preact-TodoMVC                       |16.681667    |16.610000    |0.995704  | 0.722758                                         |
| AngularJS-TodoMVC                    |123.753333   |123.740000   |0.999892  | 0.971431                                         |
| Vanilla-ES2015-TodoMVC               |61.255000    |61.380000    |1.002041  | 0.300654                                         |
| Inferno-TodoMVC                      |58.646667    |58.948333    |1.005144  | 0.267611                                         |
| Flight-TodoMVC                       |73.283333    |72.801667    |0.993427  | 0.207389                                         |
| Angular2-TypeScript-TodoMVC          |39.746667    |40.015000    |1.006751  | 0.449821                                         |
| VanillaJS-TodoMVC                    |50.096667    |49.823333    |0.994544  | 0.162020                                         |
| jQuery-TodoMVC                       |212.870000   |213.196667   |1.001535  | 0.371944                                         |
| EmberJS-Debug-TodoMVC                |331.878333   |332.710000   |1.002506  | 0.094499                                         |
| React-TodoMVC                        |83.078333    |82.726667    |0.995767  | 0.076143                                         |
| React-Redux-TodoMVC                  |136.018333   |133.935000   |0.984683  | 0.000000 (significant)                           |
| Vanilla-ES2015-Babel-Webpack-TodoMVC |59.743333    |59.643333    |0.998326  | 0.393671                                         |
----------------------------------------------------------------------------------------------------------------------------------
a mean = 271.75873
b mean = 272.45804
pValue = 0.0263030803
(Bigger means are better.)
1.003 times better
Results ARE significant

* builtins/BuiltinNames.h:
* bytecode/BytecodeList.rb:
* bytecode/BytecodeUseDef.cpp:
(JSC::computeUsesForBytecodeIndexImpl):
(JSC::computeDefsForBytecodeIndexImpl):
* bytecode/LinkTimeConstant.h:
* bytecode/Opcode.h:
(JSC::isBranch):
* bytecode/PreciseJumpTargetsInlines.h:
* bytecompiler/BytecodeGenerator.cpp:
(JSC::GenericLabel<JSGeneratorTraits>::setLocation):
(JSC::BytecodeGenerator::emitJumpIfSentinelString):
* bytecompiler/BytecodeGenerator.h:
* bytecompiler/NodesCodegen.cpp:
(JSC::ForInNode::emitBytecode):
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCapabilities.cpp:
(JSC::DFG::capabilityLevel):
* dfg/DFGOperations.cpp:
(JSC::DFG::putByVal):
(JSC::DFG::putByValInternal):
(JSC::DFG::putByValCellInternal):
(JSC::DFG::JSC_DEFINE_JIT_OPERATION):
* dfg/DFGOperations.h:
* dfg/DFGPredictionPropagationPhase.cpp:
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileEnumeratorNextUpdatePropertyName):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileCompareStrictEq):
* jit/JIT.cpp:
(JSC::JIT::privateCompileMainPass):
* jit/JIT.h:
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_jeq_ptr):
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emit_op_jeq_ptr):
* jit/JITPropertyAccess.cpp:
(JSC::JIT::emit_op_enumerator_next):
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:
* runtime/CommonSlowPaths.cpp:
(JSC::JSC_DEFINE_COMMON_SLOW_PATH):
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
* runtime/SmallStrings.cpp:
(JSC::SmallStrings::initializeCommonStrings):
(JSC::SmallStrings::visitStrongReferences):
* runtime/SmallStrings.h:
(JSC::SmallStrings::sentinelString const):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (283094 => 283095)


--- trunk/JSTests/ChangeLog	2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/JSTests/ChangeLog	2021-09-27 04:14:23 UTC (rev 283095)
@@ -1,3 +1,14 @@
+2021-09-26  Yusuke Suzuki  <ysuz...@apple.com>
+
+        [JSC] Optimize PutByVal with for-in
+        https://bugs.webkit.org/show_bug.cgi?id=230801
+
+        Reviewed by Saam Barati.
+
+        * stress/for-in-sentinel.js: Added.
+        (shouldBe):
+        (test):
+
 2021-09-24 Rick Waldron <waldron.r...@gmail.com>
 
         [JSC] Add checkScriptSyntax function to jsc host environment

Added: trunk/JSTests/stress/for-in-sentinel.js (0 => 283095)


--- trunk/JSTests/stress/for-in-sentinel.js	                        (rev 0)
+++ trunk/JSTests/stress/for-in-sentinel.js	2021-09-27 04:14:23 UTC (rev 283095)
@@ -0,0 +1,22 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+var object = {
+    $: 32,
+    test: 33,
+    hey: 34,
+};
+
+function test(object) {
+    var count = 0;
+    for (var i in object) {
+        ++count;
+    }
+    return count;
+}
+noInline(test);
+
+for (var i = 0; i < 1e6; ++i)
+    shouldBe(test(object), 3);

Modified: trunk/Source/_javascript_Core/ChangeLog (283094 => 283095)


--- trunk/Source/_javascript_Core/ChangeLog	2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/ChangeLog	2021-09-27 04:14:23 UTC (rev 283095)
@@ -1,3 +1,108 @@
+2021-09-26  Yusuke Suzuki  <ysuz...@apple.com>
+
+        [JSC] Optimize PutByVal with for-in
+        https://bugs.webkit.org/show_bug.cgi?id=230801
+
+        Reviewed by Saam Barati.
+
+        We found that some of Speedometer2 subtests are heavily using for-in with PutByVal or the other DFG nodes.
+        And we also found that we are using polluted non-good type for the property names from for-in: String | Other.
+        The reason is that we are returning null when op_enumerator_next finishes instead of string. And this design
+        forces DFG and FTL to return null from EnumeratorNextUpdatePropertyName at the end of iteration. This pollutes
+        the type of property names as String | Other instead of String, and leading to suboptimal DFG nodes.
+
+        In this patch, we add special sentinel string in vm.smallString.sentinelString(). We know that this string cell
+        pointer will be never returned from EnumeratorNextUpdatePropertyName in the normal for-in iteration. This is easy
+        since we are always allocating a JSString when creating JSPropertyNameEnumerator. So this string cell (not the content)
+        is always different from pre-allocated vm.smallString.sentinelString(). So, we use this special string pointer
+        as a sentinel instead of null so that we can avoid polluting return type of EnumeratorNextUpdatePropertyName.
+
+        To check the sentinel in LLInt / Baseline, this patch adds jeq_ptr, which performs cell pointer comparison and do
+        not check string content equality. We do not need to have an implementation in DFG since we already have CompareEqPtr
+        for existing jneq_ptr bytecode.
+
+        We also clean up DFG operation related to PutByVal.
+
+        ----------------------------------------------------------------------------------------------------------------------------------
+        |               subtest                |     ms      |     ms      |  b / a   | pValue (significance using False Discovery Rate) |
+        ----------------------------------------------------------------------------------------------------------------------------------
+        | Elm-TodoMVC                          |116.010000   |112.701667   |0.971482  | 0.000000 (significant)                           |
+        | VueJS-TodoMVC                        |22.995000    |23.023333    |1.001232  | 0.907086                                         |
+        | EmberJS-TodoMVC                      |125.498333   |125.525000   |1.000212  | 0.932546                                         |
+        | BackboneJS-TodoMVC                   |45.700000    |45.975000    |1.006018  | 0.084799                                         |
+        | Preact-TodoMVC                       |16.681667    |16.610000    |0.995704  | 0.722758                                         |
+        | AngularJS-TodoMVC                    |123.753333   |123.740000   |0.999892  | 0.971431                                         |
+        | Vanilla-ES2015-TodoMVC               |61.255000    |61.380000    |1.002041  | 0.300654                                         |
+        | Inferno-TodoMVC                      |58.646667    |58.948333    |1.005144  | 0.267611                                         |
+        | Flight-TodoMVC                       |73.283333    |72.801667    |0.993427  | 0.207389                                         |
+        | Angular2-TypeScript-TodoMVC          |39.746667    |40.015000    |1.006751  | 0.449821                                         |
+        | VanillaJS-TodoMVC                    |50.096667    |49.823333    |0.994544  | 0.162020                                         |
+        | jQuery-TodoMVC                       |212.870000   |213.196667   |1.001535  | 0.371944                                         |
+        | EmberJS-Debug-TodoMVC                |331.878333   |332.710000   |1.002506  | 0.094499                                         |
+        | React-TodoMVC                        |83.078333    |82.726667    |0.995767  | 0.076143                                         |
+        | React-Redux-TodoMVC                  |136.018333   |133.935000   |0.984683  | 0.000000 (significant)                           |
+        | Vanilla-ES2015-Babel-Webpack-TodoMVC |59.743333    |59.643333    |0.998326  | 0.393671                                         |
+        ----------------------------------------------------------------------------------------------------------------------------------
+        a mean = 271.75873
+        b mean = 272.45804
+        pValue = 0.0263030803
+        (Bigger means are better.)
+        1.003 times better
+        Results ARE significant
+
+        * builtins/BuiltinNames.h:
+        * bytecode/BytecodeList.rb:
+        * bytecode/BytecodeUseDef.cpp:
+        (JSC::computeUsesForBytecodeIndexImpl):
+        (JSC::computeDefsForBytecodeIndexImpl):
+        * bytecode/LinkTimeConstant.h:
+        * bytecode/Opcode.h:
+        (JSC::isBranch):
+        * bytecode/PreciseJumpTargetsInlines.h:
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::GenericLabel<JSGeneratorTraits>::setLocation):
+        (JSC::BytecodeGenerator::emitJumpIfSentinelString):
+        * bytecompiler/BytecodeGenerator.h:
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::ForInNode::emitBytecode):
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGCapabilities.cpp:
+        (JSC::DFG::capabilityLevel):
+        * dfg/DFGOperations.cpp:
+        (JSC::DFG::putByVal):
+        (JSC::DFG::putByValInternal):
+        (JSC::DFG::putByValCellInternal):
+        (JSC::DFG::JSC_DEFINE_JIT_OPERATION):
+        * dfg/DFGOperations.h:
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileEnumeratorNextUpdatePropertyName):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileCompareStrictEq):
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompileMainPass):
+        * jit/JIT.h:
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_jeq_ptr):
+        * jit/JITOpcodes32_64.cpp:
+        (JSC::JIT::emit_op_jeq_ptr):
+        * jit/JITPropertyAccess.cpp:
+        (JSC::JIT::emit_op_enumerator_next):
+        * llint/LowLevelInterpreter32_64.asm:
+        * llint/LowLevelInterpreter64.asm:
+        * runtime/CommonSlowPaths.cpp:
+        (JSC::JSC_DEFINE_COMMON_SLOW_PATH):
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::init):
+        * runtime/SmallStrings.cpp:
+        (JSC::SmallStrings::initializeCommonStrings):
+        (JSC::SmallStrings::visitStrongReferences):
+        * runtime/SmallStrings.h:
+        (JSC::SmallStrings::sentinelString const):
+
 2021-09-26  Commit Queue  <commit-qu...@webkit.org>
 
         Unreviewed, reverting r283083 and r283088.

Modified: trunk/Source/_javascript_Core/builtins/BuiltinNames.h (283094 => 283095)


--- trunk/Source/_javascript_Core/builtins/BuiltinNames.h	2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/builtins/BuiltinNames.h	2021-09-27 04:14:23 UTC (rev 283095)
@@ -182,7 +182,7 @@
     macro(createPrivateSymbol) \
     macro(entries) \
     macro(outOfLineReactionCounts) \
-    macro(emptyPropertyNameEnumerator)
+    macro(emptyPropertyNameEnumerator) \
 
 
 namespace Symbols {

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeList.rb (283094 => 283095)


--- trunk/Source/_javascript_Core/bytecode/BytecodeList.rb	2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeList.rb	2021-09-27 04:14:23 UTC (rev 283095)
@@ -762,6 +762,13 @@
         targetLabel: BoundLabel,
     }
 
+op :jeq_ptr,
+    args: {
+        value: VirtualRegister,
+        specialPointer: VirtualRegister,
+        targetLabel: BoundLabel,
+    }
+
 op :jneq_ptr,
     args: {
         value: VirtualRegister,

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.cpp (283094 => 283095)


--- trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.cpp	2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.cpp	2021-09-27 04:14:23 UTC (rev 283095)
@@ -80,7 +80,6 @@
     // No uses.
     case op_new_regexp:
     case op_debug:
-    case op_jneq_ptr:
     case op_loop_hint:
     case op_jmp:
     case op_new_object:
@@ -135,6 +134,9 @@
     USES(OpJnstricteq, lhs, rhs)
     USES(OpJbelow, lhs, rhs)
     USES(OpJbeloweq, lhs, rhs)
+    USES(OpJeqPtr, value, specialPointer)
+    USES(OpJneqPtr, value, specialPointer)
+
     USES(OpSetFunctionName, function, name)
     USES(OpLogShadowChickenTail, thisValue, scope)
 
@@ -365,6 +367,7 @@
     case op_jneq_null:
     case op_jundefined_or_null:
     case op_jnundefined_or_null:
+    case op_jeq_ptr:
     case op_jneq_ptr:
     case op_jless:
     case op_jlesseq:

Modified: trunk/Source/_javascript_Core/bytecode/Opcode.h (283094 => 283095)


--- trunk/Source/_javascript_Core/bytecode/Opcode.h	2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/bytecode/Opcode.h	2021-09-27 04:14:23 UTC (rev 283095)
@@ -199,6 +199,7 @@
     case op_jneq_null:
     case op_jundefined_or_null:
     case op_jnundefined_or_null:
+    case op_jeq_ptr:
     case op_jneq_ptr:
     case op_jless:
     case op_jlesseq:

Modified: trunk/Source/_javascript_Core/bytecode/PreciseJumpTargetsInlines.h (283094 => 283095)


--- trunk/Source/_javascript_Core/bytecode/PreciseJumpTargetsInlines.h	2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/bytecode/PreciseJumpTargetsInlines.h	2021-09-27 04:14:23 UTC (rev 283095)
@@ -43,6 +43,7 @@
     CASE_OP(OpJneqNull) \
     CASE_OP(OpJundefinedOrNull) \
     CASE_OP(OpJnundefinedOrNull) \
+    CASE_OP(OpJeqPtr) \
     CASE_OP(OpJneqPtr) \
     \
     CASE_OP(OpJless) \

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (283094 => 283095)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2021-09-27 04:14:23 UTC (rev 283095)
@@ -105,6 +105,7 @@
         CASE(OpJeq)
         CASE(OpJstricteq)
         CASE(OpJneq)
+        CASE(OpJeqPtr)
         CASE(OpJneqPtr)
         CASE(OpJnstricteq)
         CASE(OpJless)
@@ -1497,6 +1498,11 @@
     OpJneqPtr::emit(this, cond, moveLinkTimeConstant(nullptr, LinkTimeConstant::applyFunction), target.bind(this));
 }
 
+void BytecodeGenerator::emitJumpIfSentinelString(RegisterID* cond, Label& target)
+{
+    OpJeqPtr::emit(this, cond, emitLoad(nullptr, JSValue(vm().smallStrings.sentinelString())), target.bind(this));
+}
+
 unsigned BytecodeGenerator::emitWideJumpIfNotFunctionHasOwnProperty(RegisterID* cond, Label& target)
 {
     OpJneqPtr::emit<OpcodeSize::Wide32>(this, cond, moveLinkTimeConstant(nullptr, LinkTimeConstant::hasOwnPropertyFunction), target.bind(this));

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (283094 => 283095)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2021-09-27 04:14:23 UTC (rev 283095)
@@ -858,6 +858,7 @@
         void emitJumpIfFalse(RegisterID* cond, Label& target);
         void emitJumpIfNotFunctionCall(RegisterID* cond, Label& target);
         void emitJumpIfNotFunctionApply(RegisterID* cond, Label& target);
+        void emitJumpIfSentinelString(RegisterID* cond, Label& target);
         unsigned emitWideJumpIfNotFunctionHasOwnProperty(RegisterID* cond, Label& target);
         void recordHasOwnPropertyInForInLoop(ForInContext&, unsigned branchOffset, Label& genericPath);
 

Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (283094 => 283095)


--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2021-09-27 04:14:23 UTC (rev 283095)
@@ -4227,10 +4227,8 @@
 
         // FIXME: We should have a way to see if anyone is actually using the propertyName for something other than a get_by_val. If not, we could eliminate the toString in this opcode.
         generator.emitEnumeratorNext(propertyName.get(), mode.get(), index.get(), base.get(), enumerator.get());
+        generator.emitJumpIfSentinelString(propertyName.get(), scope->breakTarget());
 
-        // Note, choosing undefined or null helps please DFG's Abstract Interpreter as it doesn't distinguish null and undefined as types (via SpecOther).
-        generator.emitJumpIfTrue(generator.emitIsUndefinedOrNull(generator.newTemporary(), propertyName.get()), scope->breakTarget());
-
         this->emitLoopHeader(generator, propertyName.get());
 
         generator.emitProfileControlFlow(profilerStartOffset);

Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (283094 => 283095)


--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2021-09-27 04:14:23 UTC (rev 283095)
@@ -4323,7 +4323,7 @@
     }
 
     case EnumeratorNextUpdatePropertyName: {
-        setTypeForNode(node, SpecString | SpecOther);
+        setTypeForNode(node, SpecStringIdent);
         break;
     }
 

Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (283094 => 283095)


--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2021-09-27 04:14:23 UTC (rev 283095)
@@ -7632,6 +7632,16 @@
             NEXT_OPCODE(op_iterator_next);
         }
 
+        case op_jeq_ptr: {
+            auto bytecode = currentInstruction->as<OpJeqPtr>();
+            FrozenValue* frozenPointer = m_graph.freezeStrong(m_inlineStackTop->m_codeBlock->getConstant(bytecode.m_specialPointer));
+            unsigned relativeOffset = jumpTarget(bytecode.m_targetLabel);
+            Node* child = get(bytecode.m_value);
+            Node* condition = addToGraph(CompareEqPtr, OpInfo(frozenPointer), child);
+            addToGraph(Branch, OpInfo(branchData(m_currentIndex.offset() + relativeOffset, m_currentIndex.offset() + currentInstruction->size())), condition);
+            LAST_OPCODE(op_jeq_ptr);
+        }
+
         case op_jneq_ptr: {
             auto bytecode = currentInstruction->as<OpJneqPtr>();
             FrozenValue* frozenPointer = m_graph.freezeStrong(m_inlineStackTop->m_codeBlock->getConstant(bytecode.m_specialPointer));

Modified: trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp (283094 => 283095)


--- trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp	2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp	2021-09-27 04:14:23 UTC (rev 283095)
@@ -240,6 +240,7 @@
     case op_get_from_arguments:
     case op_put_to_arguments:
     case op_get_argument:
+    case op_jeq_ptr:
     case op_jneq_ptr:
     case op_typeof:
     case op_to_number:

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (283094 => 283095)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2021-09-27 04:14:23 UTC (rev 283095)
@@ -86,10 +86,10 @@
 namespace JSC { namespace DFG {
 
 template<bool strict, bool direct>
-static inline void putByVal(JSGlobalObject* globalObject, VM& vm, JSValue baseValue, uint32_t index, JSValue value)
+static ALWAYS_INLINE void putByVal(JSGlobalObject* globalObject, VM& vm, JSValue baseValue, uint32_t index, JSValue value)
 {
     ASSERT(isIndex(index));
-    if (direct) {
+    if constexpr (direct) {
         RELEASE_ASSERT(baseValue.isObject());
         asObject(baseValue)->putDirectIndex(globalObject, index, value, 0, strict ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
         return;
@@ -128,7 +128,7 @@
     RETURN_IF_EXCEPTION(scope, void());
 
     PutPropertySlot slot(baseValue, strict);
-    if (direct) {
+    if constexpr (direct) {
         RELEASE_ASSERT(baseValue.isObject());
         JSObject* baseObject = asObject(baseValue);
         if (std::optional<uint32_t> index = parseIndex(propertyName)) {
@@ -148,7 +148,7 @@
 ALWAYS_INLINE static void putByValCellInternal(JSGlobalObject* globalObject, VM& vm, JSCell* base, PropertyName propertyName, JSValue value)
 {
     PutPropertySlot slot(base, strict);
-    if (direct) {
+    if constexpr (direct) {
         RELEASE_ASSERT(base->isObject());
         JSObject* baseObject = asObject(base);
         if (std::optional<uint32_t> index = parseIndex(propertyName)) {
@@ -2486,7 +2486,7 @@
     return JSValue::encode(result);
 }
 
-JSC_DEFINE_JIT_OPERATION(operationEnumeratorNextUpdatePropertyName, EncodedJSValue, (JSGlobalObject* globalObject, uint32_t index, int32_t modeNumber, JSPropertyNameEnumerator* enumerator))
+JSC_DEFINE_JIT_OPERATION(operationEnumeratorNextUpdatePropertyName, JSString*, (JSGlobalObject* globalObject, uint32_t index, int32_t modeNumber, JSPropertyNameEnumerator* enumerator))
 {
     VM& vm = globalObject->vm();
     CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
@@ -2494,15 +2494,15 @@
 
     if (modeNumber == JSPropertyNameEnumerator::IndexedMode) {
         if (index < enumerator->indexedLength())
-            return JSValue::encode(jsString(vm, Identifier::from(vm, index).string()));
-        return JSValue::encode(jsNull());
+            return jsString(vm, Identifier::from(vm, index).string());
+        return vm.smallStrings.sentinelString();
     }
 
     JSString* result = enumerator->propertyNameAtIndex(index);
     if (!result)
-        return JSValue::encode(jsNull());
+        return vm.smallStrings.sentinelString();
 
-    return JSValue::encode(result);
+    return result;
 }
 
 JSC_DEFINE_JIT_OPERATION(operationEnumeratorRecoverNameAndGetByVal, EncodedJSValue, (JSGlobalObject* globalObject, JSCell* base, uint32_t index, JSPropertyNameEnumerator* enumerator))

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.h (283094 => 283095)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.h	2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.h	2021-09-27 04:14:23 UTC (rev 283095)
@@ -108,7 +108,7 @@
 JSC_DECLARE_JIT_OPERATION(operationGetPropertyEnumerator, JSCell*, (JSGlobalObject*, EncodedJSValue));
 JSC_DECLARE_JIT_OPERATION(operationGetPropertyEnumeratorCell, JSCell*, (JSGlobalObject*, JSCell*));
 JSC_DECLARE_JIT_OPERATION(operationEnumeratorNextUpdateIndexAndMode, EncodedJSValue, (JSGlobalObject*, EncodedJSValue, uint32_t, int32_t, JSPropertyNameEnumerator*));
-JSC_DECLARE_JIT_OPERATION(operationEnumeratorNextUpdatePropertyName, EncodedJSValue, (JSGlobalObject*, uint32_t, int32_t, JSPropertyNameEnumerator*));
+JSC_DECLARE_JIT_OPERATION(operationEnumeratorNextUpdatePropertyName, JSString*, (JSGlobalObject*, uint32_t, int32_t, JSPropertyNameEnumerator*));
 JSC_DECLARE_JIT_OPERATION(operationEnumeratorInByVal, EncodedJSValue, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, uint32_t, int32_t));
 JSC_DECLARE_JIT_OPERATION(operationEnumeratorHasOwnProperty, EncodedJSValue, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, uint32_t, int32_t));
 JSC_DECLARE_JIT_OPERATION(operationEnumeratorRecoverNameAndGetByVal, EncodedJSValue, (JSGlobalObject*, JSCell*, uint32_t, JSPropertyNameEnumerator*));

Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (283094 => 283095)


--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2021-09-27 04:14:23 UTC (rev 283095)
@@ -1233,7 +1233,7 @@
         }
 
         case EnumeratorNextUpdatePropertyName: {
-            setPrediction(SpecString | SpecOther);
+            setPrediction(SpecStringIdent);
             break;
         }
 

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (283094 => 283095)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2021-09-27 04:14:23 UTC (rev 283095)
@@ -13646,12 +13646,12 @@
     SpeculateStrictInt32Operand indexOperand(this, node->child1());
     SpeculateStrictInt32Operand modeOperand(this, node->child2());
     SpeculateCellOperand enumeratorOperand(this, node->child3());
-    JSValueRegsTemporary resultTemp(this);
+    GPRTemporary result(this);
 
     GPRReg index = indexOperand.gpr();
     GPRReg mode = modeOperand.gpr();
     GPRReg enumerator = enumeratorOperand.gpr();
-    JSValueRegs resultRegs = resultTemp.regs();
+    GPRReg resultGPR = result.gpr();
 
     OptionSet seenModes = node->enumeratorMetadata();
 
@@ -13667,24 +13667,21 @@
 
         auto outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, index, MacroAssembler::Address(enumerator, JSPropertyNameEnumerator::endGenericPropertyIndexOffset()));
 
-        m_jit.loadPtr(MacroAssembler::Address(enumerator, JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset()), resultRegs.payloadGPR());
-        m_jit.loadPtr(MacroAssembler::BaseIndex(resultRegs.payloadGPR(), index, MacroAssembler::ScalePtr), resultRegs.payloadGPR());
-#if USE(JSVALUE32_64)
-        m_jit.move(TrustedImm32(JSValue::CellTag), resultRegs.tagGPR());
-#endif
+        m_jit.loadPtr(MacroAssembler::Address(enumerator, JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset()), resultGPR);
+        m_jit.loadPtr(MacroAssembler::BaseIndex(resultGPR, index, MacroAssembler::ScalePtr), resultGPR);
         doneCases.append(m_jit.jump());
 
         outOfBounds.link(&m_jit);
-        m_jit.moveTrustedValue(jsNull(), resultRegs);
+        m_jit.move(TrustedImmPtr::weakPointer(m_graph, vm().smallStrings.sentinelString()), resultGPR);
         doneCases.append(m_jit.jump());
         operationCall.link(&m_jit);
     }
 
-    callOperation(operationEnumeratorNextUpdatePropertyName, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), index, mode, enumerator);
+    callOperation(operationEnumeratorNextUpdatePropertyName, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), index, mode, enumerator);
     m_jit.exceptionCheck();
 
     doneCases.link(&m_jit);
-    jsValueResult(resultRegs, node);
+    cellResult(resultGPR, node);
 }
 
 template<typename SlowPathFunctionType>

Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (283094 => 283095)


--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2021-09-27 04:14:23 UTC (rev 283095)
@@ -13526,7 +13526,7 @@
 
             {
                 m_out.appendTo(outOfBoundsBlock);
-                results.append(m_out.anchor(m_out.constInt64(JSValue::encode(jsNull()))));
+                results.append(m_out.anchor(weakPointer(vm().smallStrings.sentinelString())));
                 m_out.jump(continuation);
             }
 
@@ -13533,7 +13533,7 @@
             {
                 m_out.appendTo(loadPropertyNameBlock);
                 LValue namesVector = m_out.loadPtr(enumerator, m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVector);
-                results.append(m_out.anchor(m_out.zeroExtPtr(m_out.loadPtr(m_out.baseIndex(m_heaps.WriteBarrierBuffer_bufferContents.atAnyIndex(), namesVector, m_out.zeroExt(index, Int64), ScalePtr)))));
+                results.append(m_out.anchor(m_out.loadPtr(m_out.baseIndex(m_heaps.WriteBarrierBuffer_bufferContents.atAnyIndex(), namesVector, m_out.zeroExt(index, Int64), ScalePtr))));
                 m_out.jump(continuation);
             }
         }
@@ -13541,7 +13541,7 @@
         if (operationBlock)
             m_out.appendTo(operationBlock);
         // Note: We can't omit the operation because we have no guarantee that the mode will match what we profiled.
-        results.append(m_out.anchor(vmCall(Int64, operationEnumeratorNextUpdatePropertyName, weakPointer(globalObject), index, mode, enumerator)));
+        results.append(m_out.anchor(vmCall(pointerType(), operationEnumeratorNextUpdatePropertyName, weakPointer(globalObject), index, mode, enumerator)));
         if (continuation) {
             m_out.jump(continuation);
             m_out.appendTo(continuation);
@@ -13548,7 +13548,7 @@
         }
 
         ASSERT(results.size());
-        LValue result = m_out.phi(Int64, results);
+        LValue result = m_out.phi(pointerType(), results);
         setJSValue(result);
     }
 

Modified: trunk/Source/_javascript_Core/jit/JIT.cpp (283094 => 283095)


--- trunk/Source/_javascript_Core/jit/JIT.cpp	2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/jit/JIT.cpp	2021-09-27 04:14:23 UTC (rev 283095)
@@ -387,6 +387,7 @@
         DEFINE_OP(op_jneq_null)
         DEFINE_OP(op_jundefined_or_null)
         DEFINE_OP(op_jnundefined_or_null)
+        DEFINE_OP(op_jeq_ptr)
         DEFINE_OP(op_jneq_ptr)
         DEFINE_OP(op_jless)
         DEFINE_OP(op_jlesseq)

Modified: trunk/Source/_javascript_Core/jit/JIT.h (283094 => 283095)


--- trunk/Source/_javascript_Core/jit/JIT.h	2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/jit/JIT.h	2021-09-27 04:14:23 UTC (rev 283095)
@@ -461,6 +461,7 @@
         void emit_op_jneq_null(const Instruction*);
         void emit_op_jundefined_or_null(const Instruction*);
         void emit_op_jnundefined_or_null(const Instruction*);
+        void emit_op_jeq_ptr(const Instruction*);
         void emit_op_jneq_ptr(const Instruction*);
         void emit_op_jless(const Instruction*);
         void emit_op_jlesseq(const Instruction*);

Modified: trunk/Source/_javascript_Core/jit/JITOpcodes.cpp (283094 => 283095)


--- trunk/Source/_javascript_Core/jit/JITOpcodes.cpp	2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes.cpp	2021-09-27 04:14:23 UTC (rev 283095)
@@ -579,6 +579,18 @@
     addJump(branch64(NotEqual, regT0, TrustedImm64(JSValue::encode(jsNull()))), target);
 }
 
+void JIT::emit_op_jeq_ptr(const Instruction* currentInstruction)
+{
+    auto bytecode = currentInstruction->as<OpJeqPtr>();
+    VirtualRegister src = ""
+    JSValue specialPointer = getConstantOperand(bytecode.m_specialPointer);
+    ASSERT(specialPointer.isCell());
+    unsigned target = jumpTarget(currentInstruction, bytecode.m_targetLabel);
+
+    emitGetVirtualRegister(src, regT0);
+    addJump(branchPtr(Equal, regT0, TrustedImmPtr(specialPointer.asCell())), target);
+}
+
 void JIT::emit_op_jneq_ptr(const Instruction* currentInstruction)
 {
     auto bytecode = currentInstruction->as<OpJneqPtr>();

Modified: trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp (283094 => 283095)


--- trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp	2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp	2021-09-27 04:14:23 UTC (rev 283095)
@@ -501,6 +501,21 @@
     addJump(branchIfNotNull(regT0), target);
 }
 
+void JIT::emit_op_jeq_ptr(const Instruction* currentInstruction)
+{
+    auto bytecode = currentInstruction->as<OpJeqPtr>();
+    auto& metadata = bytecode.metadata(m_profiledCodeBlock);
+    VirtualRegister src = ""
+    JSValue specialPointer = getConstantOperand(bytecode.m_specialPointer);
+    ASSERT(specialPointer.isCell());
+    unsigned target = jumpTarget(currentInstruction, bytecode.m_targetLabel);
+
+    emitLoad(src, regT1, regT0);
+    Jump notCell = branchIfNotCell(regT1);
+    addJump(branchPtr(Equal, regT0, TrustedImmPtr(specialPointer.asCell())), target);
+    notCell.link(this);
+}
+
 void JIT::emit_op_jneq_ptr(const Instruction* currentInstruction)
 {
     auto bytecode = currentInstruction->as<OpJneqPtr>();

Modified: trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp (283094 => 283095)


--- trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp	2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp	2021-09-27 04:14:23 UTC (rev 283095)
@@ -2866,7 +2866,7 @@
         done.append(jump());
 
         outOfBounds.link(this);
-        storeTrustedValue(jsNull(), addressFor(propertyName));
+        storeTrustedValue(vm().smallStrings.sentinelString(), addressFor(propertyName));
         done.append(jump());
     }
 

Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm (283094 => 283095)


--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm	2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm	2021-09-27 04:14:23 UTC (rev 283095)
@@ -1944,6 +1944,20 @@
 undefinedOrNullJumpOp(jnundefined_or_null, OpJnundefinedOrNull,
     macro (value, target) bineq value, NullTag, target end)
 
+llintOpWithReturn(op_jeq_ptr, OpJeqPtr, macro (size, get, dispatch, return)
+    get(m_value, t0)
+    get(m_specialPointer, t1)
+    loadConstant(size, t1, t3, t2)
+    bineq TagOffset[cfr, t0, 8], CellTag, .opJeqPtrFallThrough
+    bpneq PayloadOffset[cfr, t0, 8], t2, .opJeqPtrFallThrough
+.opJeqPtrBranch:
+    get(m_targetLabel, t0)
+    jumpImpl(dispatchIndirect, t0)
+.opJeqPtrFallThrough:
+    dispatch()
+end)
+
+
 llintOpWithMetadata(op_jneq_ptr, OpJneqPtr, macro (size, get, dispatch, metadata, return)
     get(m_value, t0)
     get(m_specialPointer, t1)

Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm (283094 => 283095)


--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm	2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm	2021-09-27 04:14:23 UTC (rev 283095)
@@ -2072,6 +2072,19 @@
 undefinedOrNullJumpOp(jnundefined_or_null, OpJnundefinedOrNull,
     macro (value, target) bqneq value, ValueNull, target end)
 
+llintOpWithReturn(op_jeq_ptr, OpJeqPtr, macro (size, get, dispatch, return)
+    get(m_value, t0)
+    get(m_specialPointer, t1)
+    loadConstant(size, t1, t2)
+    bpeq t2, [cfr, t0, 8], .opJeqPtrTarget
+    dispatch()
+
+.opJeqPtrTarget:
+    get(m_targetLabel, t0)
+    jumpImpl(dispatchIndirect, t0)
+end)
+
+
 llintOpWithMetadata(op_jneq_ptr, OpJneqPtr, macro (size, get, dispatch, metadata, return)
     get(m_value, t0)
     get(m_specialPointer, t1)

Modified: trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp (283094 => 283095)


--- trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp	2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp	2021-09-27 04:14:23 UTC (rev 283095)
@@ -1001,7 +1001,7 @@
     metadata.m_enumeratorMetadata |= static_cast<uint8_t>(mode);
     modeRegister = jsNumber(static_cast<uint8_t>(mode));
     indexRegister = jsNumber(index);
-    nameRegister = name ? name : jsNull();
+    nameRegister = name ? name : vm.smallStrings.sentinelString();
     END();
 }
 

Modified: trunk/Source/_javascript_Core/runtime/SmallStrings.cpp (283094 => 283095)


--- trunk/Source/_javascript_Core/runtime/SmallStrings.cpp	2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/runtime/SmallStrings.cpp	2021-09-27 04:14:23 UTC (rev 283095)
@@ -62,6 +62,7 @@
     initialize(&vm, m_notEqualString, "not-equal");
     initialize(&vm, m_timedOutString, "timed-out");
     initialize(&vm, m_okString, "ok");
+    initialize(&vm, m_sentinelString, "$");
 
     setIsInitialized(true);
 }
@@ -83,6 +84,7 @@
     visitor.appendUnbarriered(m_notEqualString);
     visitor.appendUnbarriered(m_timedOutString);
     visitor.appendUnbarriered(m_okString);
+    visitor.appendUnbarriered(m_sentinelString);
 }
 
 template void SmallStrings::visitStrongReferences(AbstractSlotVisitor&);

Modified: trunk/Source/_javascript_Core/runtime/SmallStrings.h (283094 => 283095)


--- trunk/Source/_javascript_Core/runtime/SmallStrings.h	2021-09-27 03:01:05 UTC (rev 283094)
+++ trunk/Source/_javascript_Core/runtime/SmallStrings.h	2021-09-27 04:14:23 UTC (rev 283095)
@@ -119,6 +119,7 @@
     JSString* notEqualString() const { return m_notEqualString; }
     JSString* timedOutString() const { return m_timedOutString; }
     JSString* okString() const { return m_okString; }
+    JSString* sentinelString() const { return m_sentinelString; }
 
     bool needsToBeVisited(CollectionScope scope) const
     {
@@ -143,6 +144,7 @@
     JSString* m_notEqualString { nullptr };
     JSString* m_timedOutString { nullptr };
     JSString* m_okString { nullptr };
+    JSString* m_sentinelString { nullptr };
     JSString* m_singleCharacterStrings[singleCharacterStringCount] { nullptr };
     bool m_needsToBeVisited { true };
     bool m_isInitialized { false };
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to