Changeset 283098 in webkit


Ignore:
Timestamp:
Sep 26, 2021 10:02:37 PM (10 months ago)
Author:
ysuzuki@apple.com
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/JavaScriptCore:

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):

Location:
trunk
Files:
2 added
30 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r283096 r283098  
     12021-09-26  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        [JSC] Optimize PutByVal with for-in
     4        https://bugs.webkit.org/show_bug.cgi?id=230801
     5
     6        Reviewed by Saam Barati.
     7
     8        * stress/for-in-sentinel.js: Added.
     9        (shouldBe):
     10        (test):
     11
    1122021-09-26  Commit Queue  <commit-queue@webkit.org>
    213
  • trunk/Source/JavaScriptCore/ChangeLog

    r283096 r283098  
     12021-09-26  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        [JSC] Optimize PutByVal with for-in
     4        https://bugs.webkit.org/show_bug.cgi?id=230801
     5
     6        Reviewed by Saam Barati.
     7
     8        We found that some of Speedometer2 subtests are heavily using for-in with PutByVal or the other DFG nodes.
     9        And we also found that we are using polluted non-good type for the property names from for-in: String | Other.
     10        The reason is that we are returning null when op_enumerator_next finishes instead of string. And this design
     11        forces DFG and FTL to return null from EnumeratorNextUpdatePropertyName at the end of iteration. This pollutes
     12        the type of property names as String | Other instead of String, and leading to suboptimal DFG nodes.
     13
     14        In this patch, we add special sentinel string in vm.smallString.sentinelString(). We know that this string cell
     15        pointer will be never returned from EnumeratorNextUpdatePropertyName in the normal for-in iteration. This is easy
     16        since we are always allocating a JSString when creating JSPropertyNameEnumerator. So this string cell (not the content)
     17        is always different from pre-allocated vm.smallString.sentinelString(). So, we use this special string pointer
     18        as a sentinel instead of null so that we can avoid polluting return type of EnumeratorNextUpdatePropertyName.
     19
     20        To check the sentinel in LLInt / Baseline, this patch adds jeq_ptr, which performs cell pointer comparison and do
     21        not check string content equality. We do not need to have an implementation in DFG since we already have CompareEqPtr
     22        for existing jneq_ptr bytecode.
     23
     24        We also clean up DFG operation related to PutByVal.
     25
     26        ----------------------------------------------------------------------------------------------------------------------------------
     27        |               subtest                |     ms      |     ms      |  b / a   | pValue (significance using False Discovery Rate) |
     28        ----------------------------------------------------------------------------------------------------------------------------------
     29        | Elm-TodoMVC                          |116.010000   |112.701667   |0.971482  | 0.000000 (significant)                           |
     30        | VueJS-TodoMVC                        |22.995000    |23.023333    |1.001232  | 0.907086                                         |
     31        | EmberJS-TodoMVC                      |125.498333   |125.525000   |1.000212  | 0.932546                                         |
     32        | BackboneJS-TodoMVC                   |45.700000    |45.975000    |1.006018  | 0.084799                                         |
     33        | Preact-TodoMVC                       |16.681667    |16.610000    |0.995704  | 0.722758                                         |
     34        | AngularJS-TodoMVC                    |123.753333   |123.740000   |0.999892  | 0.971431                                         |
     35        | Vanilla-ES2015-TodoMVC               |61.255000    |61.380000    |1.002041  | 0.300654                                         |
     36        | Inferno-TodoMVC                      |58.646667    |58.948333    |1.005144  | 0.267611                                         |
     37        | Flight-TodoMVC                       |73.283333    |72.801667    |0.993427  | 0.207389                                         |
     38        | Angular2-TypeScript-TodoMVC          |39.746667    |40.015000    |1.006751  | 0.449821                                         |
     39        | VanillaJS-TodoMVC                    |50.096667    |49.823333    |0.994544  | 0.162020                                         |
     40        | jQuery-TodoMVC                       |212.870000   |213.196667   |1.001535  | 0.371944                                         |
     41        | EmberJS-Debug-TodoMVC                |331.878333   |332.710000   |1.002506  | 0.094499                                         |
     42        | React-TodoMVC                        |83.078333    |82.726667    |0.995767  | 0.076143                                         |
     43        | React-Redux-TodoMVC                  |136.018333   |133.935000   |0.984683  | 0.000000 (significant)                           |
     44        | Vanilla-ES2015-Babel-Webpack-TodoMVC |59.743333    |59.643333    |0.998326  | 0.393671                                         |
     45        ----------------------------------------------------------------------------------------------------------------------------------
     46        a mean = 271.75873
     47        b mean = 272.45804
     48        pValue = 0.0263030803
     49        (Bigger means are better.)
     50        1.003 times better
     51        Results ARE significant
     52
     53        * builtins/BuiltinNames.h:
     54        * bytecode/BytecodeList.rb:
     55        * bytecode/BytecodeUseDef.cpp:
     56        (JSC::computeUsesForBytecodeIndexImpl):
     57        (JSC::computeDefsForBytecodeIndexImpl):
     58        * bytecode/LinkTimeConstant.h:
     59        * bytecode/Opcode.h:
     60        (JSC::isBranch):
     61        * bytecode/PreciseJumpTargetsInlines.h:
     62        * bytecompiler/BytecodeGenerator.cpp:
     63        (JSC::GenericLabel<JSGeneratorTraits>::setLocation):
     64        (JSC::BytecodeGenerator::emitJumpIfSentinelString):
     65        * bytecompiler/BytecodeGenerator.h:
     66        * bytecompiler/NodesCodegen.cpp:
     67        (JSC::ForInNode::emitBytecode):
     68        * dfg/DFGAbstractInterpreterInlines.h:
     69        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
     70        * dfg/DFGByteCodeParser.cpp:
     71        (JSC::DFG::ByteCodeParser::parseBlock):
     72        * dfg/DFGCapabilities.cpp:
     73        (JSC::DFG::capabilityLevel):
     74        * dfg/DFGOperations.cpp:
     75        (JSC::DFG::putByVal):
     76        (JSC::DFG::putByValInternal):
     77        (JSC::DFG::putByValCellInternal):
     78        (JSC::DFG::JSC_DEFINE_JIT_OPERATION):
     79        * dfg/DFGOperations.h:
     80        * dfg/DFGPredictionPropagationPhase.cpp:
     81        * dfg/DFGSpeculativeJIT.cpp:
     82        (JSC::DFG::SpeculativeJIT::compileEnumeratorNextUpdatePropertyName):
     83        * ftl/FTLLowerDFGToB3.cpp:
     84        (JSC::FTL::DFG::LowerDFGToB3::compileCompareStrictEq):
     85        * jit/JIT.cpp:
     86        (JSC::JIT::privateCompileMainPass):
     87        * jit/JIT.h:
     88        * jit/JITOpcodes.cpp:
     89        (JSC::JIT::emit_op_jeq_ptr):
     90        * jit/JITOpcodes32_64.cpp:
     91        (JSC::JIT::emit_op_jeq_ptr):
     92        * jit/JITPropertyAccess.cpp:
     93        (JSC::JIT::emit_op_enumerator_next):
     94        * llint/LowLevelInterpreter32_64.asm:
     95        * llint/LowLevelInterpreter64.asm:
     96        * runtime/CommonSlowPaths.cpp:
     97        (JSC::JSC_DEFINE_COMMON_SLOW_PATH):
     98        * runtime/JSGlobalObject.cpp:
     99        (JSC::JSGlobalObject::init):
     100        * runtime/SmallStrings.cpp:
     101        (JSC::SmallStrings::initializeCommonStrings):
     102        (JSC::SmallStrings::visitStrongReferences):
     103        * runtime/SmallStrings.h:
     104        (JSC::SmallStrings::sentinelString const):
     105
    11062021-09-26  Commit Queue  <commit-queue@webkit.org>
    2107
  • trunk/Source/JavaScriptCore/builtins/BuiltinNames.h

    r283096 r283098  
    183183    macro(entries) \
    184184    macro(outOfLineReactionCounts) \
    185     macro(emptyPropertyNameEnumerator)
     185    macro(emptyPropertyNameEnumerator) \
     186    macro(sentinelString) \
    186187
    187188
  • trunk/Source/JavaScriptCore/bytecode/BytecodeList.rb

    r283096 r283098  
    760760    args: {
    761761        value: VirtualRegister,
     762        targetLabel: BoundLabel,
     763    }
     764
     765op :jeq_ptr,
     766    args: {
     767        value: VirtualRegister,
     768        specialPointer: VirtualRegister,
    762769        targetLabel: BoundLabel,
    763770    }
  • trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.cpp

    r283096 r283098  
    8181    case op_new_regexp:
    8282    case op_debug:
    83     case op_jneq_ptr:
    8483    case op_loop_hint:
    8584    case op_jmp:
     
    136135    USES(OpJbelow, lhs, rhs)
    137136    USES(OpJbeloweq, lhs, rhs)
     137    USES(OpJeqPtr, value, specialPointer)
     138    USES(OpJneqPtr, value, specialPointer)
     139
    138140    USES(OpSetFunctionName, function, name)
    139141    USES(OpLogShadowChickenTail, thisValue, scope)
     
    366368    case op_jundefined_or_null:
    367369    case op_jnundefined_or_null:
     370    case op_jeq_ptr:
    368371    case op_jneq_ptr:
    369372    case op_jless:
  • trunk/Source/JavaScriptCore/bytecode/LinkTimeConstant.h

    r280760 r283098  
    113113    v(createPrivateSymbol, nullptr) \
    114114    v(emptyPropertyNameEnumerator, nullptr) \
     115    v(sentinelString, nullptr) \
    115116
    116117
  • trunk/Source/JavaScriptCore/bytecode/Opcode.h

    r283096 r283098  
    200200    case op_jundefined_or_null:
    201201    case op_jnundefined_or_null:
     202    case op_jeq_ptr:
    202203    case op_jneq_ptr:
    203204    case op_jless:
  • trunk/Source/JavaScriptCore/bytecode/PreciseJumpTargetsInlines.h

    r283096 r283098  
    4444    CASE_OP(OpJundefinedOrNull) \
    4545    CASE_OP(OpJnundefinedOrNull) \
     46    CASE_OP(OpJeqPtr) \
    4647    CASE_OP(OpJneqPtr) \
    4748    \
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r283096 r283098  
    106106        CASE(OpJstricteq)
    107107        CASE(OpJneq)
     108        CASE(OpJeqPtr)
    108109        CASE(OpJneqPtr)
    109110        CASE(OpJnstricteq)
     
    14961497{
    14971498    OpJneqPtr::emit(this, cond, moveLinkTimeConstant(nullptr, LinkTimeConstant::applyFunction), target.bind(this));
     1499}
     1500
     1501void BytecodeGenerator::emitJumpIfSentinelString(RegisterID* cond, Label& target)
     1502{
     1503    OpJeqPtr::emit(this, cond, moveLinkTimeConstant(nullptr, LinkTimeConstant::sentinelString), target.bind(this));
    14981504}
    14991505
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r283096 r283098  
    859859        void emitJumpIfNotFunctionCall(RegisterID* cond, Label& target);
    860860        void emitJumpIfNotFunctionApply(RegisterID* cond, Label& target);
     861        void emitJumpIfSentinelString(RegisterID* cond, Label& target);
    861862        unsigned emitWideJumpIfNotFunctionHasOwnProperty(RegisterID* cond, Label& target);
    862863        void recordHasOwnPropertyInForInLoop(ForInContext&, unsigned branchOffset, Label& genericPath);
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r283096 r283098  
    42284228        // 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.
    42294229        generator.emitEnumeratorNext(propertyName.get(), mode.get(), index.get(), base.get(), enumerator.get());
    4230 
    4231         // Note, choosing undefined or null helps please DFG's Abstract Interpreter as it doesn't distinguish null and undefined as types (via SpecOther).
    4232         generator.emitJumpIfTrue(generator.emitIsUndefinedOrNull(generator.newTemporary(), propertyName.get()), scope->breakTarget());
     4230        generator.emitJumpIfSentinelString(propertyName.get(), scope->breakTarget());
    42334231
    42344232        this->emitLoopHeader(generator, propertyName.get());
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

    r283096 r283098  
    43244324
    43254325    case EnumeratorNextUpdatePropertyName: {
    4326         setTypeForNode(node, SpecString | SpecOther);
     4326        setTypeForNode(node, SpecStringIdent);
    43274327        break;
    43284328    }
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r283096 r283098  
    76317631
    76327632            NEXT_OPCODE(op_iterator_next);
     7633        }
     7634
     7635        case op_jeq_ptr: {
     7636            auto bytecode = currentInstruction->as<OpJeqPtr>();
     7637            JSValue constant = m_inlineStackTop->m_codeBlock->getConstant(bytecode.m_specialPointer);
     7638            FrozenValue* frozenPointer = m_graph.freezeStrong(constant);
     7639            ASSERT(frozenPointer->cell() == constant);
     7640            unsigned relativeOffset = jumpTarget(bytecode.m_targetLabel);
     7641            Node* child = get(bytecode.m_value);
     7642            Node* condition = addToGraph(CompareEqPtr, OpInfo(frozenPointer), child);
     7643            addToGraph(Branch, OpInfo(branchData(m_currentIndex.offset() + relativeOffset, m_currentIndex.offset() + currentInstruction->size())), condition);
     7644            LAST_OPCODE(op_jeq_ptr);
    76337645        }
    76347646
  • trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp

    r283096 r283098  
    241241    case op_put_to_arguments:
    242242    case op_get_argument:
     243    case op_jeq_ptr:
    243244    case op_jneq_ptr:
    244245    case op_typeof:
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r283096 r283098  
    8787
    8888template<bool strict, bool direct>
    89 static inline void putByVal(JSGlobalObject* globalObject, VM& vm, JSValue baseValue, uint32_t index, JSValue value)
     89static ALWAYS_INLINE void putByVal(JSGlobalObject* globalObject, VM& vm, JSValue baseValue, uint32_t index, JSValue value)
    9090{
    9191    ASSERT(isIndex(index));
    92     if (direct) {
     92    if constexpr (direct) {
    9393        RELEASE_ASSERT(baseValue.isObject());
    9494        asObject(baseValue)->putDirectIndex(globalObject, index, value, 0, strict ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
     
    129129
    130130    PutPropertySlot slot(baseValue, strict);
    131     if (direct) {
     131    if constexpr (direct) {
    132132        RELEASE_ASSERT(baseValue.isObject());
    133133        JSObject* baseObject = asObject(baseValue);
     
    149149{
    150150    PutPropertySlot slot(base, strict);
    151     if (direct) {
     151    if constexpr (direct) {
    152152        RELEASE_ASSERT(base->isObject());
    153153        JSObject* baseObject = asObject(base);
     
    24872487}
    24882488
    2489 JSC_DEFINE_JIT_OPERATION(operationEnumeratorNextUpdatePropertyName, EncodedJSValue, (JSGlobalObject* globalObject, uint32_t index, int32_t modeNumber, JSPropertyNameEnumerator* enumerator))
     2489JSC_DEFINE_JIT_OPERATION(operationEnumeratorNextUpdatePropertyName, JSString*, (JSGlobalObject* globalObject, uint32_t index, int32_t modeNumber, JSPropertyNameEnumerator* enumerator))
    24902490{
    24912491    VM& vm = globalObject->vm();
     
    24952495    if (modeNumber == JSPropertyNameEnumerator::IndexedMode) {
    24962496        if (index < enumerator->indexedLength())
    2497             return JSValue::encode(jsString(vm, Identifier::from(vm, index).string()));
    2498         return JSValue::encode(jsNull());
     2497            return jsString(vm, Identifier::from(vm, index).string());
     2498        return vm.smallStrings.sentinelString();
    24992499    }
    25002500
    25012501    JSString* result = enumerator->propertyNameAtIndex(index);
    25022502    if (!result)
    2503         return JSValue::encode(jsNull());
    2504 
    2505     return JSValue::encode(result);
     2503        return vm.smallStrings.sentinelString();
     2504
     2505    return result;
    25062506}
    25072507
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.h

    r283096 r283098  
    109109JSC_DECLARE_JIT_OPERATION(operationGetPropertyEnumeratorCell, JSCell*, (JSGlobalObject*, JSCell*));
    110110JSC_DECLARE_JIT_OPERATION(operationEnumeratorNextUpdateIndexAndMode, EncodedJSValue, (JSGlobalObject*, EncodedJSValue, uint32_t, int32_t, JSPropertyNameEnumerator*));
    111 JSC_DECLARE_JIT_OPERATION(operationEnumeratorNextUpdatePropertyName, EncodedJSValue, (JSGlobalObject*, uint32_t, int32_t, JSPropertyNameEnumerator*));
     111JSC_DECLARE_JIT_OPERATION(operationEnumeratorNextUpdatePropertyName, JSString*, (JSGlobalObject*, uint32_t, int32_t, JSPropertyNameEnumerator*));
    112112JSC_DECLARE_JIT_OPERATION(operationEnumeratorInByVal, EncodedJSValue, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, uint32_t, int32_t));
    113113JSC_DECLARE_JIT_OPERATION(operationEnumeratorHasOwnProperty, EncodedJSValue, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, uint32_t, int32_t));
  • trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp

    r283096 r283098  
    12341234
    12351235        case EnumeratorNextUpdatePropertyName: {
    1236             setPrediction(SpecString | SpecOther);
     1236            setPrediction(SpecStringIdent);
    12371237            break;
    12381238        }
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r283096 r283098  
    1364713647    SpeculateStrictInt32Operand modeOperand(this, node->child2());
    1364813648    SpeculateCellOperand enumeratorOperand(this, node->child3());
    13649     JSValueRegsTemporary resultTemp(this);
     13649    GPRTemporary result(this);
    1365013650
    1365113651    GPRReg index = indexOperand.gpr();
    1365213652    GPRReg mode = modeOperand.gpr();
    1365313653    GPRReg enumerator = enumeratorOperand.gpr();
    13654     JSValueRegs resultRegs = resultTemp.regs();
     13654    GPRReg resultGPR = result.gpr();
    1365513655
    1365613656    OptionSet seenModes = node->enumeratorMetadata();
     
    1366813668        auto outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, index, MacroAssembler::Address(enumerator, JSPropertyNameEnumerator::endGenericPropertyIndexOffset()));
    1366913669
    13670         m_jit.loadPtr(MacroAssembler::Address(enumerator, JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset()), resultRegs.payloadGPR());
    13671         m_jit.loadPtr(MacroAssembler::BaseIndex(resultRegs.payloadGPR(), index, MacroAssembler::ScalePtr), resultRegs.payloadGPR());
    13672 #if USE(JSVALUE32_64)
    13673         m_jit.move(TrustedImm32(JSValue::CellTag), resultRegs.tagGPR());
    13674 #endif
     13670        m_jit.loadPtr(MacroAssembler::Address(enumerator, JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset()), resultGPR);
     13671        m_jit.loadPtr(MacroAssembler::BaseIndex(resultGPR, index, MacroAssembler::ScalePtr), resultGPR);
    1367513672        doneCases.append(m_jit.jump());
    1367613673
    1367713674        outOfBounds.link(&m_jit);
    13678         m_jit.moveTrustedValue(jsNull(), resultRegs);
     13675        m_jit.move(TrustedImmPtr::weakPointer(m_graph, vm().smallStrings.sentinelString()), resultGPR);
    1367913676        doneCases.append(m_jit.jump());
    1368013677        operationCall.link(&m_jit);
    1368113678    }
    1368213679
    13683     callOperation(operationEnumeratorNextUpdatePropertyName, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), index, mode, enumerator);
     13680    callOperation(operationEnumeratorNextUpdatePropertyName, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), index, mode, enumerator);
    1368413681    m_jit.exceptionCheck();
    1368513682
    1368613683    doneCases.link(&m_jit);
    13687     jsValueResult(resultRegs, node);
     13684    cellResult(resultGPR, node);
    1368813685}
    1368913686
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

    r283096 r283098  
    1352713527            {
    1352813528                m_out.appendTo(outOfBoundsBlock);
    13529                 results.append(m_out.anchor(m_out.constInt64(JSValue::encode(jsNull()))));
     13529                results.append(m_out.anchor(weakPointer(vm().smallStrings.sentinelString())));
    1353013530                m_out.jump(continuation);
    1353113531            }
     
    1353413534                m_out.appendTo(loadPropertyNameBlock);
    1353513535                LValue namesVector = m_out.loadPtr(enumerator, m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVector);
    13536                 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)))));
     13536                results.append(m_out.anchor(m_out.loadPtr(m_out.baseIndex(m_heaps.WriteBarrierBuffer_bufferContents.atAnyIndex(), namesVector, m_out.zeroExt(index, Int64), ScalePtr))));
    1353713537                m_out.jump(continuation);
    1353813538            }
     
    1354213542            m_out.appendTo(operationBlock);
    1354313543        // Note: We can't omit the operation because we have no guarantee that the mode will match what we profiled.
    13544         results.append(m_out.anchor(vmCall(Int64, operationEnumeratorNextUpdatePropertyName, weakPointer(globalObject), index, mode, enumerator)));
     13544        results.append(m_out.anchor(vmCall(pointerType(), operationEnumeratorNextUpdatePropertyName, weakPointer(globalObject), index, mode, enumerator)));
    1354513545        if (continuation) {
    1354613546            m_out.jump(continuation);
     
    1354913549
    1355013550        ASSERT(results.size());
    13551         LValue result = m_out.phi(Int64, results);
     13551        LValue result = m_out.phi(pointerType(), results);
    1355213552        setJSValue(result);
    1355313553    }
  • trunk/Source/JavaScriptCore/jit/JIT.cpp

    r283096 r283098  
    388388        DEFINE_OP(op_jundefined_or_null)
    389389        DEFINE_OP(op_jnundefined_or_null)
     390        DEFINE_OP(op_jeq_ptr)
    390391        DEFINE_OP(op_jneq_ptr)
    391392        DEFINE_OP(op_jless)
  • trunk/Source/JavaScriptCore/jit/JIT.h

    r283096 r283098  
    462462        void emit_op_jundefined_or_null(const Instruction*);
    463463        void emit_op_jnundefined_or_null(const Instruction*);
     464        void emit_op_jeq_ptr(const Instruction*);
    464465        void emit_op_jneq_ptr(const Instruction*);
    465466        void emit_op_jless(const Instruction*);
  • trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp

    r283096 r283098  
    580580}
    581581
     582void JIT::emit_op_jeq_ptr(const Instruction* currentInstruction)
     583{
     584    auto bytecode = currentInstruction->as<OpJeqPtr>();
     585    VirtualRegister src = bytecode.m_value;
     586    JSValue specialPointer = getConstantOperand(bytecode.m_specialPointer);
     587    ASSERT(specialPointer.isCell());
     588    unsigned target = jumpTarget(currentInstruction, bytecode.m_targetLabel);
     589
     590    emitGetVirtualRegister(src, regT0);
     591    addJump(branchPtr(Equal, regT0, TrustedImmPtr(specialPointer.asCell())), target);
     592}
     593
    582594void JIT::emit_op_jneq_ptr(const Instruction* currentInstruction)
    583595{
  • trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp

    r283096 r283098  
    502502}
    503503
     504void JIT::emit_op_jeq_ptr(const Instruction* currentInstruction)
     505{
     506    auto bytecode = currentInstruction->as<OpJeqPtr>();
     507    auto& metadata = bytecode.metadata(m_profiledCodeBlock);
     508    VirtualRegister src = bytecode.m_value;
     509    JSValue specialPointer = getConstantOperand(bytecode.m_specialPointer);
     510    ASSERT(specialPointer.isCell());
     511    unsigned target = jumpTarget(currentInstruction, bytecode.m_targetLabel);
     512
     513    emitLoad(src, regT1, regT0);
     514    Jump notCell = branchIfNotCell(regT1);
     515    addJump(branchPtr(Equal, regT0, TrustedImmPtr(specialPointer.asCell())), target);
     516    notCell.link(this);
     517}
     518
    504519void JIT::emit_op_jneq_ptr(const Instruction* currentInstruction)
    505520{
  • trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp

    r283096 r283098  
    28672867
    28682868        outOfBounds.link(this);
    2869         storeTrustedValue(jsNull(), addressFor(propertyName));
     2869        storeTrustedValue(vm().smallStrings.sentinelString(), addressFor(propertyName));
    28702870        done.append(jump());
    28712871    }
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm

    r283096 r283098  
    19451945    macro (value, target) bineq value, NullTag, target end)
    19461946
     1947llintOpWithReturn(op_jeq_ptr, OpJeqPtr, macro (size, get, dispatch, return)
     1948    get(m_value, t0)
     1949    get(m_specialPointer, t1)
     1950    loadConstant(size, t1, t3, t2)
     1951    bineq TagOffset[cfr, t0, 8], CellTag, .opJeqPtrFallThrough
     1952    bpneq PayloadOffset[cfr, t0, 8], t2, .opJeqPtrFallThrough
     1953.opJeqPtrBranch:
     1954    get(m_targetLabel, t0)
     1955    jumpImpl(dispatchIndirect, t0)
     1956.opJeqPtrFallThrough:
     1957    dispatch()
     1958end)
     1959
     1960
    19471961llintOpWithMetadata(op_jneq_ptr, OpJneqPtr, macro (size, get, dispatch, metadata, return)
    19481962    get(m_value, t0)
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm

    r283096 r283098  
    20722072undefinedOrNullJumpOp(jnundefined_or_null, OpJnundefinedOrNull,
    20732073    macro (value, target) bqneq value, ValueNull, target end)
     2074
     2075llintOpWithReturn(op_jeq_ptr, OpJeqPtr, macro (size, get, dispatch, return)
     2076    get(m_value, t0)
     2077    get(m_specialPointer, t1)
     2078    loadConstant(size, t1, t2)
     2079    bpeq t2, [cfr, t0, 8], .opJeqPtrTarget
     2080    dispatch()
     2081
     2082.opJeqPtrTarget:
     2083    get(m_targetLabel, t0)
     2084    jumpImpl(dispatchIndirect, t0)
     2085end)
     2086
    20742087
    20752088llintOpWithMetadata(op_jneq_ptr, OpJneqPtr, macro (size, get, dispatch, metadata, return)
  • trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp

    r283096 r283098  
    10021002    modeRegister = jsNumber(static_cast<uint8_t>(mode));
    10031003    indexRegister = jsNumber(index);
    1004     nameRegister = name ? name : jsNull();
     1004    nameRegister = name ? name : vm.smallStrings.sentinelString();
    10051005    END();
    10061006}
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp

    r282125 r283098  
    982982    m_setIteratorStructure.set(vm, this, JSSetIterator::createStructure(vm, this, setIteratorPrototype));
    983983
     984    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::sentinelString)].set(vm, this, vm.smallStrings.sentinelString());
     985
    984986    JSFunction* defaultPromiseThen = JSFunction::create(vm, promisePrototypeThenCodeGenerator(vm), this);
    985987    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::defaultPromiseThen)].set(vm, this, defaultPromiseThen);
  • trunk/Source/JavaScriptCore/runtime/SmallStrings.cpp

    r283096 r283098  
    6363    initialize(&vm, m_timedOutString, "timed-out");
    6464    initialize(&vm, m_okString, "ok");
     65    initialize(&vm, m_sentinelString, "$");
    6566
    6667    setIsInitialized(true);
     
    8485    visitor.appendUnbarriered(m_timedOutString);
    8586    visitor.appendUnbarriered(m_okString);
     87    visitor.appendUnbarriered(m_sentinelString);
    8688}
    8789
  • trunk/Source/JavaScriptCore/runtime/SmallStrings.h

    r283096 r283098  
    120120    JSString* timedOutString() const { return m_timedOutString; }
    121121    JSString* okString() const { return m_okString; }
     122    JSString* sentinelString() const { return m_sentinelString; }
    122123
    123124    bool needsToBeVisited(CollectionScope scope) const
     
    144145    JSString* m_timedOutString { nullptr };
    145146    JSString* m_okString { nullptr };
     147    JSString* m_sentinelString { nullptr };
    146148    JSString* m_singleCharacterStrings[singleCharacterStringCount] { nullptr };
    147149    bool m_needsToBeVisited { true };
Note: See TracChangeset for help on using the changeset viewer.