Changeset 190649 in webkit


Ignore:
Timestamp:
Oct 6, 2015 3:29:27 PM (8 years ago)
Author:
mark.lam@apple.com
Message:

Factoring out op_sub baseline code generation into JITSubGenerator.
https://bugs.webkit.org/show_bug.cgi?id=149600

Reviewed by Geoffrey Garen.

We're going to factor out baseline code generation into snippet generators so
that we can later use them in the DFG and FTL to emit code for to perform the
JS operations where the operand types are predicted to be polymorphic.
We are starting in this patch with the implementation of op_sub.

What was done in this patch:

  1. Created JITSubGenerator based on the baseline implementation of op_sub as expressed in compileBinaryArithOp() and compileBinaryArithOpSlowCase(). I did not attempt to do write a more optimal version of op_sub. I'll leave that to a later patch.
  1. Convert the 32-bit op_sub baseline implementation to use the same JITSubGenerator which was based on the 64-bit implementation. The pre-existing 32-bit baseline op_sub had handling for more optimization cases. However, a benchmark run shows that simply going with the 64-bit version (foregoing those extra optimizations) did not change the performance.

Also, previously, the 32-bit version was able to move double results directly
into the result location on the stack directly. By using JITSubGenerator,
we now always move that result into a pair of GPRs before storing it into
the stack location.

  1. Add some needed emitters to AssemblyHelpers that play nice with JSValueRegs.

(JSC::AssemblyHelpers::boxDouble):
(JSC::AssemblyHelpers::unboxDouble):
(JSC::AssemblyHelpers::boxBooleanPayload):

  • jit/JIT.h:

(JSC::JIT::linkDummySlowCase):

  • jit/JITArithmetic.cpp:

(JSC::JIT::compileBinaryArithOp):
(JSC::JIT::compileBinaryArithOpSlowCase):
(JSC::JIT::emitSlow_op_div):
(JSC::JIT::emit_op_sub):
(JSC::JIT::emitSlow_op_sub):

  • jit/JITArithmetic32_64.cpp:

(JSC::JIT::emitBinaryDoubleOp):
(JSC::JIT::emit_op_sub): Deleted.
(JSC::JIT::emitSub32Constant): Deleted.
(JSC::JIT::emitSlow_op_sub): Deleted.

  • jit/JITInlines.h:

(JSC::JIT::linkSlowCaseIfNotJSCell):
(JSC::JIT::linkAllSlowCasesForBytecodeOffset):
(JSC::JIT::addSlowCase):
(JSC::JIT::emitLoad):
(JSC::JIT::emitGetVirtualRegister):
(JSC::JIT::emitPutVirtualRegister):

  • jit/JITSubGenerator.h: Added.

(JSC::JITSubGenerator::JITSubGenerator):
(JSC::JITSubGenerator::generateFastPath):
(JSC::JITSubGenerator::slowPathJumpList):

Location:
trunk/Source/JavaScriptCore
Files:
1 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r190617 r190649  
     12015-10-06  Mark Lam  <mark.lam@apple.com>
     2
     3        Factoring out op_sub baseline code generation into JITSubGenerator.
     4        https://bugs.webkit.org/show_bug.cgi?id=149600
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        We're going to factor out baseline code generation into snippet generators so
     9        that we can later use them in the DFG and FTL to emit code for to perform the
     10        JS operations where the operand types are predicted to be polymorphic.
     11        We are starting in this patch with the implementation of op_sub.
     12
     13        What was done in this patch:
     14        1. Created JITSubGenerator based on the baseline implementation of op_sub as
     15           expressed in compileBinaryArithOp() and compileBinaryArithOpSlowCase().
     16           I did not attempt to do write a more optimal version of op_sub.  I'll
     17           leave that to a later patch.
     18
     19        2. Convert the 32-bit op_sub baseline implementation to use the same
     20           JITSubGenerator which was based on the 64-bit implementation.  The
     21           pre-existing 32-bit baseline op_sub had handling for more optimization cases.
     22           However, a benchmark run shows that simply going with the 64-bit version
     23           (foregoing those extra optimizations) did not change the performance.
     24
     25           Also, previously, the 32-bit version was able to move double results directly
     26           into the result location on the stack directly.  By using JITSubGenerator,
     27           we now always move that result into a pair of GPRs before storing it into
     28           the stack location.
     29
     30        3. Add some needed emitters to AssemblyHelpers that play nice with JSValueRegs.
     31
     32        * JavaScriptCore.xcodeproj/project.pbxproj:
     33        * jit/AssemblyHelpers.h:
     34        (JSC::AssemblyHelpers::boxDouble):
     35        (JSC::AssemblyHelpers::unboxDouble):
     36        (JSC::AssemblyHelpers::boxBooleanPayload):
     37        * jit/JIT.h:
     38        (JSC::JIT::linkDummySlowCase):
     39        * jit/JITArithmetic.cpp:
     40        (JSC::JIT::compileBinaryArithOp):
     41        (JSC::JIT::compileBinaryArithOpSlowCase):
     42        (JSC::JIT::emitSlow_op_div):
     43        (JSC::JIT::emit_op_sub):
     44        (JSC::JIT::emitSlow_op_sub):
     45        * jit/JITArithmetic32_64.cpp:
     46        (JSC::JIT::emitBinaryDoubleOp):
     47        (JSC::JIT::emit_op_sub): Deleted.
     48        (JSC::JIT::emitSub32Constant): Deleted.
     49        (JSC::JIT::emitSlow_op_sub): Deleted.
     50        * jit/JITInlines.h:
     51        (JSC::JIT::linkSlowCaseIfNotJSCell):
     52        (JSC::JIT::linkAllSlowCasesForBytecodeOffset):
     53        (JSC::JIT::addSlowCase):
     54        (JSC::JIT::emitLoad):
     55        (JSC::JIT::emitGetVirtualRegister):
     56        (JSC::JIT::emitPutVirtualRegister):
     57        * jit/JITSubGenerator.h: Added.
     58        (JSC::JITSubGenerator::JITSubGenerator):
     59        (JSC::JITSubGenerator::generateFastPath):
     60        (JSC::JITSubGenerator::slowPathJumpList):
     61
    1622015-10-06  Daniel Bates  <dbates@webkit.org>
    263
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r190569 r190649  
    37083708                FE7BA60E1A1A7CEC00F1F7B4 /* HeapVerifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeapVerifier.h; sourceTree = "<group>"; };
    37093709                FE90BB3A1B7CF64E006B3F03 /* VMInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VMInlines.h; sourceTree = "<group>"; };
     3710                FE98B5B61BB9AE110073E7A6 /* JITSubGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITSubGenerator.h; sourceTree = "<group>"; };
    37103711                FEA0861E182B7A0400F6D851 /* Breakpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Breakpoint.h; sourceTree = "<group>"; };
    37113712                FEA0861F182B7A0400F6D851 /* DebuggerPrimitives.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebuggerPrimitives.h; sourceTree = "<group>"; };
     
    41904191                                FEF6835C174343CC00A32E25 /* JITStubsX86_64.h */,
    41914192                                A7A4AE0C17973B4D005612B1 /* JITStubsX86Common.h */,
     4193                                FE98B5B61BB9AE110073E7A6 /* JITSubGenerator.h */,
    41924194                                0F5EF91B16878F78003E5C25 /* JITThunks.cpp */,
    41934195                                0F5EF91C16878F78003E5C25 /* JITThunks.h */,
  • trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h

    r190606 r190649  
    965965        boxDouble(fpr, regs.gpr());
    966966    }
    967    
     967    void unboxDouble(JSValueRegs regs, FPRReg destFPR, FPRReg)
     968    {
     969        unboxDouble(regs.payloadGPR(), destFPR);
     970    }
     971
    968972    // Here are possible arrangements of source, target, scratch:
    969973    // - source, target, scratch can all be separate registers.
     
    10021006    {
    10031007        boxDouble(fpr, regs.tagGPR(), regs.payloadGPR());
     1008    }
     1009    void unboxDouble(JSValueRegs regs, FPRReg fpr, FPRReg scratchFPR)
     1010    {
     1011        unboxDouble(regs.tagGPR(), regs.payloadGPR(), fpr, scratchFPR);
    10041012    }
    10051013#endif
  • trunk/Source/JavaScriptCore/jit/JIT.h

    r190561 r190649  
    400400
    401401        enum FinalObjectMode { MayBeFinal, KnownNotFinal };
     402
     403        void emitGetVirtualRegister(int src, JSValueRegs dst);
     404        void emitPutVirtualRegister(int dst, JSValueRegs src);
    402405
    403406#if USE(JSVALUE32_64)
     
    709712        }
    710713        void linkSlowCaseIfNotJSCell(Vector<SlowCaseEntry>::iterator&, int virtualRegisterIndex);
     714        void linkAllSlowCasesForBytecodeOffset(Vector<SlowCaseEntry>& slowCases,
     715            Vector<SlowCaseEntry>::iterator&, unsigned bytecodeOffset);
    711716
    712717        MacroAssembler::Call appendCallWithExceptionCheck(const FunctionPtr&);
  • trunk/Source/JavaScriptCore/jit/JITArithmetic.cpp

    r190435 r190649  
    11/*
    2  * Copyright (C) 2008 Apple Inc. All rights reserved.
     2 * Copyright (C) 2008, 2015 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3333#include "JITOperations.h"
    3434#include "JITStubs.h"
     35#include "JITSubGenerator.h"
    3536#include "JSArray.h"
    3637#include "JSFunction.h"
     
    669670    if (opcodeID == op_add)
    670671        addSlowCase(branchAdd32(Overflow, regT1, regT0));
    671     else if (opcodeID == op_sub)
    672         addSlowCase(branchSub32(Overflow, regT1, regT0));
    673672    else {
    674673        ASSERT(opcodeID == op_mul);
     
    722721    Label stubFunctionCall(this);
    723722
    724     JITSlowPathCall slowPathCall(this, currentInstruction, opcodeID == op_add ? slow_path_add : opcodeID == op_sub ? slow_path_sub : slow_path_mul);
     723    JITSlowPathCall slowPathCall(this, currentInstruction, opcodeID == op_add ? slow_path_add : slow_path_mul);
    725724    slowPathCall.call();
    726725    Jump end = jump();
     
    768767    if (opcodeID == op_add)
    769768        addDouble(fpRegT2, fpRegT1);
    770     else if (opcodeID == op_sub)
    771         subDouble(fpRegT2, fpRegT1);
    772769    else if (opcodeID == op_mul)
    773770        mulDouble(fpRegT2, fpRegT1);
     
    962959}
    963960
     961#endif // USE(JSVALUE64)
     962
    964963void JIT::emit_op_sub(Instruction* currentInstruction)
    965964{
     
    969968    OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
    970969
    971     compileBinaryArithOp(op_sub, result, op1, op2, types);
    972     emitPutVirtualRegister(result);
     970#if USE(JSVALUE64)
     971    JSValueRegs leftRegs = JSValueRegs(regT0);
     972    JSValueRegs rightRegs = JSValueRegs(regT1);
     973    JSValueRegs resultRegs = leftRegs;
     974    GPRReg scratchGPR = InvalidGPRReg;
     975    FPRReg scratchFPR = InvalidFPRReg;
     976#else
     977    JSValueRegs leftRegs = JSValueRegs(regT1, regT0);
     978    JSValueRegs rightRegs = JSValueRegs(regT3, regT2);
     979    JSValueRegs resultRegs = leftRegs;
     980    GPRReg scratchGPR = regT4;
     981    FPRReg scratchFPR = fpRegT2;
     982#endif
     983
     984    emitGetVirtualRegister(op1, leftRegs);
     985    emitGetVirtualRegister(op2, rightRegs);
     986
     987    JITSubGenerator gen(resultRegs, leftRegs, rightRegs, types.first(), types.second(),
     988        fpRegT0, fpRegT1, scratchGPR, scratchFPR);
     989
     990    gen.generateFastPath(*this);
     991    emitPutVirtualRegister(result, resultRegs);
     992
     993    addSlowCase(gen.slowPathJumpList());
    973994}
    974995
    975996void JIT::emitSlow_op_sub(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
    976997{
    977     int result = currentInstruction[1].u.operand;
    978     int op1 = currentInstruction[2].u.operand;
    979     int op2 = currentInstruction[3].u.operand;
    980     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
    981 
    982     compileBinaryArithOpSlowCase(currentInstruction, op_sub, iter, result, op1, op2, types, false, false);
     998    linkAllSlowCasesForBytecodeOffset(m_slowCases, iter, m_bytecodeOffset);
     999
     1000    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_sub);
     1001    slowPathCall.call();
    9831002}
    9841003
    9851004/* ------------------------------ END: OP_ADD, OP_SUB, OP_MUL ------------------------------ */
    9861005
    987 #endif // USE(JSVALUE64)
    988 
    9891006} // namespace JSC
    9901007
  • trunk/Source/JavaScriptCore/jit/JITArithmetic32_64.cpp

    r190230 r190649  
    11/*
    2 * Copyright (C) 2008 Apple Inc. All rights reserved.
     2* Copyright (C) 2008, 2015 Apple Inc. All rights reserved.
    33*
    44* Redistribution and use in source and binary forms, with or without
     
    595595// Subtraction (-)
    596596
    597 void JIT::emit_op_sub(Instruction* currentInstruction)
    598 {
    599     int dst = currentInstruction[1].u.operand;
    600     int op1 = currentInstruction[2].u.operand;
    601     int op2 = currentInstruction[3].u.operand;
    602     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
    603 
    604     JumpList notInt32Op1;
    605     JumpList notInt32Op2;
    606 
    607     if (isOperandConstantInt(op2)) {
    608         emitSub32Constant(dst, op1, getConstantOperand(op2).asInt32(), types.first());
    609         return;
    610     }
    611 
    612     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
    613     notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
    614     notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
    615 
    616     // Int32 case.
    617     addSlowCase(branchSub32(Overflow, regT2, regT0));
    618     emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
    619 
    620     if (!supportsFloatingPoint()) {
    621         addSlowCase(notInt32Op1);
    622         addSlowCase(notInt32Op2);
    623         return;
    624     }
    625     Jump end = jump();
    626 
    627     // Double case.
    628     emitBinaryDoubleOp(op_sub, dst, op1, op2, types, notInt32Op1, notInt32Op2);
    629     end.link(this);
    630 }
    631 
    632 void JIT::emitSub32Constant(int dst, int op, int32_t constant, ResultType opType)
    633 {
    634     // Int32 case.
    635     emitLoad(op, regT1, regT0);
    636     Jump notInt32 = branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag));
    637     addSlowCase(branchSub32(Overflow, regT0, Imm32(constant), regT2, regT3));   
    638     emitStoreInt32(dst, regT2, (op == dst));
    639 
    640     // Double case.
    641     if (!supportsFloatingPoint()) {
    642         addSlowCase(notInt32);
    643         return;
    644     }
    645     Jump end = jump();
    646 
    647     notInt32.link(this);
    648     if (!opType.definitelyIsNumber())
    649         addSlowCase(branch32(Above, regT1, TrustedImm32(JSValue::LowestTag)));
    650     move(Imm32(constant), regT2);
    651     convertInt32ToDouble(regT2, fpRegT0);
    652     emitLoadDouble(op, fpRegT1);
    653     subDouble(fpRegT0, fpRegT1);
    654     emitStoreDouble(dst, fpRegT1);
    655 
    656     end.link(this);
    657 }
    658 
    659 void JIT::emitSlow_op_sub(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
    660 {
    661     int op2 = currentInstruction[3].u.operand;
    662     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
    663 
    664     if (isOperandConstantInt(op2)) {
    665         linkSlowCase(iter); // overflow check
    666 
    667         if (!supportsFloatingPoint() || !types.first().definitelyIsNumber())
    668             linkSlowCase(iter); // int32 or double check
    669     } else {
    670         linkSlowCase(iter); // overflow check
    671 
    672         if (!supportsFloatingPoint()) {
    673             linkSlowCase(iter); // int32 check
    674             linkSlowCase(iter); // int32 check
    675         } else {
    676             if (!types.first().definitelyIsNumber())
    677                 linkSlowCase(iter); // double check
    678 
    679             if (!types.second().definitelyIsNumber()) {
    680                 linkSlowCase(iter); // int32 check
    681                 linkSlowCase(iter); // double check
    682             }
    683         }
    684     }
    685 
    686     JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_sub);
    687     slowPathCall.call();
    688 }
    689 
    690597void JIT::emitBinaryDoubleOp(OpcodeID opcodeID, int dst, int op1, int op2, OperandTypes types, JumpList& notInt32Op1, JumpList& notInt32Op2, bool op1IsInRegisters, bool op2IsInRegisters)
    691598{
     
    729636                addDouble(fpRegT2, fpRegT0);
    730637                emitStoreDouble(dst, fpRegT0);
    731                 break;
    732             case op_sub:
    733                 emitLoadDouble(op1, fpRegT1);
    734                 subDouble(fpRegT0, fpRegT1);
    735                 emitStoreDouble(dst, fpRegT1);
    736638                break;
    737639            case op_div: {
     
    829731                emitLoadDouble(op2, fpRegT2);
    830732                addDouble(fpRegT2, fpRegT0);
    831                 emitStoreDouble(dst, fpRegT0);
    832                 break;
    833             case op_sub:
    834                 emitLoadDouble(op2, fpRegT2);
    835                 subDouble(fpRegT2, fpRegT0);
    836733                emitStoreDouble(dst, fpRegT0);
    837734                break;
  • trunk/Source/JavaScriptCore/jit/JITInlines.h

    r190230 r190649  
    770770}
    771771
     772ALWAYS_INLINE void JIT::linkAllSlowCasesForBytecodeOffset(Vector<SlowCaseEntry>& slowCases, Vector<SlowCaseEntry>::iterator& iter, unsigned bytecodeOffset)
     773{
     774    while (iter != slowCases.end() && iter->to == bytecodeOffset) {
     775        iter->from.link(this);
     776        ++iter;
     777    }
     778}
     779
    772780ALWAYS_INLINE void JIT::addSlowCase(Jump jump)
    773781{
     
    9991007}
    10001008
     1009ALWAYS_INLINE void JIT::emitGetVirtualRegister(int src, JSValueRegs dst)
     1010{
     1011    emitLoad(src, dst.tagGPR(), dst.payloadGPR());
     1012}
     1013
     1014ALWAYS_INLINE void JIT::emitPutVirtualRegister(int dst, JSValueRegs from)
     1015{
     1016    emitStore(dst, from.tagGPR(), from.payloadGPR());
     1017}
     1018
    10011019inline void JIT::emitLoad(int index, RegisterID tag, RegisterID payload, RegisterID base)
    10021020{
     
    11571175}
    11581176
     1177ALWAYS_INLINE void JIT::emitGetVirtualRegister(int src, JSValueRegs dst)
     1178{
     1179    emitGetVirtualRegister(src, dst.payloadGPR());
     1180}
     1181
    11591182ALWAYS_INLINE void JIT::emitGetVirtualRegister(VirtualRegister src, RegisterID dst)
    11601183{
     
    11861209{
    11871210    store64(from, Address(callFrameRegister, dst * sizeof(Register)));
     1211}
     1212
     1213ALWAYS_INLINE void JIT::emitPutVirtualRegister(int dst, JSValueRegs from)
     1214{
     1215    emitPutVirtualRegister(dst, from.payloadGPR());
    11881216}
    11891217
Note: See TracChangeset for help on using the changeset viewer.