Ignore:
Timestamp:
Sep 8, 2016, 4:19:38 PM (9 years ago)
Author:
[email protected]
Message:

We should inline operationConvertJSValueToBoolean into JIT code
https://bugs.webkit.org/show_bug.cgi?id=161729

Reviewed by Filip Pizlo.

JSTests:

  • stress/value-to-boolean.js: Added.

(assert):
(test1):
(test2):
(test3):

Source/JavaScriptCore:

This patch introduces an AssemblyHelpers emitter function
that replaces operationConvertJSValueToBoolean. This operation
was showing up when I was doing performance analysis for the
speedometer benchmark. I saw that it was spending about 1% of
its time in this function. Hopefully this patch can help us speedup
up speedometer by a little bit.

  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::compileLogicalNot):
(JSC::DFG::SpeculativeJIT::emitBranch):

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::compileLogicalNot):
(JSC::DFG::SpeculativeJIT::emitBranch):

  • jit/AssemblyHelpers.cpp:

(JSC::AssemblyHelpers::emitConvertValueToBoolean):

  • jit/AssemblyHelpers.h:

(JSC::AssemblyHelpers::emitAllocateDestructibleObject): Deleted.

  • jit/JIT.cpp:

(JSC::JIT::privateCompileSlowCases):

  • jit/JIT.h:
  • jit/JITOpcodes.cpp:

(JSC::JIT::emit_op_jfalse):
(JSC::JIT::emit_op_jtrue):
(JSC::JIT::emitSlow_op_jfalse): Deleted.
(JSC::JIT::emitSlow_op_jtrue): Deleted.

  • jit/JITOpcodes32_64.cpp:

(JSC::JIT::emit_op_jfalse):
(JSC::JIT::emit_op_jtrue):
(JSC::JIT::emitSlow_op_jfalse): Deleted.
(JSC::JIT::emitSlow_op_jtrue): Deleted.

  • jit/JITOperations.cpp:
  • jit/JITOperations.h:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp

    r205520 r205675  
    673673#endif // USE(JSVALUE64)
    674674
     675void AssemblyHelpers::emitConvertValueToBoolean(JSValueRegs value, GPRReg result, GPRReg scratch, FPRReg valueAsFPR, FPRReg tempFPR, bool shouldCheckMasqueradesAsUndefined, JSGlobalObject* globalObject, bool negateResult)
     676{
     677    // Implements the following control flow structure:
     678    // if (value is boolean) {
     679    //     result = value === true
     680    // } else if (value is integer) {
     681    //     result = value !== 0
     682    // } else if (value is double) {
     683    //     result = value !== 0.0 && !isNaN(value);
     684    // } else if (value is cell) {
     685    //     if (value is string) {
     686    //          result = value.length() !== 0;
     687    //     } else {
     688    //          do crazy things for masquerades as undefined
     689    //     }
     690    // } else {
     691    //     result = false;
     692    // }
     693    //
     694    // if (negateResult)
     695    //     result = !result;
     696
     697    JumpList done;
     698    auto notBoolean = branchIfNotBoolean(value, result);
     699#if USE(JSVALUE64)
     700    compare32(negateResult ? NotEqual : Equal, value.gpr(), TrustedImm32(ValueTrue), result);
     701#else
     702    compare32(negateResult ? Equal : NotEqual, value.payloadGPR(), TrustedImm32(0), result);
     703#endif
     704    done.append(jump());
     705
     706    notBoolean.link(this);
     707#if USE(JSVALUE64)
     708    auto isNotNumber = branchIfNotNumber(value.gpr());
     709#else
     710    ASSERT(scratch != InvalidGPRReg);
     711    auto isNotNumber = branchIfNotNumber(value, scratch);
     712#endif
     713    auto isDouble = branchIfNotInt32(value);
     714
     715    // It's an int32.
     716    compare32(negateResult ? Equal : NotEqual, value.payloadGPR(), TrustedImm32(0), result);
     717    done.append(jump());
     718
     719    isDouble.link(this);
     720#if USE(JSVALUE64)
     721    unboxDouble(value.gpr(), result, valueAsFPR);
     722#else
     723    unboxDouble(value, valueAsFPR, tempFPR);
     724#endif
     725    auto isZeroOrNaN = branchDoubleZeroOrNaN(valueAsFPR, tempFPR);
     726    move(negateResult ? TrustedImm32(0) : TrustedImm32(1), result);
     727    done.append(jump());
     728    isZeroOrNaN.link(this);
     729    move(negateResult ? TrustedImm32(1) : TrustedImm32(0), result);
     730    done.append(jump());
     731
     732    isNotNumber.link(this);
     733    auto isNotCellAndIsNotNumberAndIsNotBoolean = branchIfNotCell(value);
     734    auto isCellButNotString = branch8(NotEqual,
     735        Address(value.payloadGPR(), JSCell::typeInfoTypeOffset()), TrustedImm32(StringType));
     736    load32(Address(value.payloadGPR(), JSString::offsetOfLength()), result);
     737    compare32(negateResult ? Equal : NotEqual, result, TrustedImm32(0), result);
     738    done.append(jump());
     739
     740    isCellButNotString.link(this);
     741    if (shouldCheckMasqueradesAsUndefined) {
     742        ASSERT(scratch != InvalidGPRReg);
     743        JumpList isNotMasqueradesAsUndefined;
     744        isNotMasqueradesAsUndefined.append(branchTest8(Zero, Address(value.payloadGPR(), JSCell::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined)));
     745        emitLoadStructure(value.payloadGPR(), result, scratch);
     746        move(TrustedImmPtr(globalObject), scratch);
     747        isNotMasqueradesAsUndefined.append(branchPtr(NotEqual, Address(result, Structure::globalObjectOffset()), scratch));
     748        // We act like we are "undefined" here.
     749        move(negateResult ? TrustedImm32(1) : TrustedImm32(0), result);
     750        done.append(jump());
     751        isNotMasqueradesAsUndefined.link(this);
     752    }
     753    move(negateResult ? TrustedImm32(0) : TrustedImm32(1), result);
     754    done.append(jump());
     755
     756    // null or undefined.
     757    isNotCellAndIsNotNumberAndIsNotBoolean.link(this);
     758    move(negateResult ? TrustedImm32(1) : TrustedImm32(0), result);
     759
     760    done.link(this);
     761}
     762
    675763} // namespace JSC
    676764
Note: See TracChangeset for help on using the changeset viewer.