Changeset 95399 in webkit


Ignore:
Timestamp:
Sep 18, 2011, 3:29:41 PM (14 years ago)
Author:
fpizlo@apple.com
Message:

DFG JIT should inline Math.min, Math.max, and Math.sqrt
https://bugs.webkit.org/show_bug.cgi?id=68318

Reviewed by Gavin Barraclough.

Adds Math.min, Math.max, and Math.sqrt intrinsics. Adds support for
a function to have an intrinsic but not a thunk generator. This is
a 7% speed-up on access-nbody, and neutral elsewhere, mainly because
we're still not DFG compiling the bulk of the hot code in Kraken audio
benchmarks.

  • create_hash_table:
  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::handleMinMax):
(JSC::DFG::ByteCodeParser::handleIntrinsic):

  • dfg/DFGIntrinsic.h:
  • dfg/DFGNode.h:
  • dfg/DFGPropagator.cpp:

(JSC::DFG::Propagator::propagateNode):
(JSC::DFG::Propagator::fixupNode):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • jit/JITStubs.cpp:

(JSC::JITThunks::hostFunctionStub):

  • runtime/Lookup.cpp:

(JSC::setUpStaticFunctionSlot):

Location:
trunk/Source/JavaScriptCore
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r95398 r95399  
     12011-09-17  Filip Pizlo  <fpizlo@apple.com>
     2
     3        DFG JIT should inline Math.min, Math.max, and Math.sqrt
     4        https://bugs.webkit.org/show_bug.cgi?id=68318
     5
     6        Reviewed by Gavin Barraclough.
     7       
     8        Adds Math.min, Math.max, and Math.sqrt intrinsics. Adds support for
     9        a function to have an intrinsic but not a thunk generator. This is
     10        a 7% speed-up on access-nbody, and neutral elsewhere, mainly because
     11        we're still not DFG compiling the bulk of the hot code in Kraken audio
     12        benchmarks.
     13
     14        * create_hash_table:
     15        * dfg/DFGByteCodeParser.cpp:
     16        (JSC::DFG::ByteCodeParser::handleMinMax):
     17        (JSC::DFG::ByteCodeParser::handleIntrinsic):
     18        * dfg/DFGIntrinsic.h:
     19        * dfg/DFGNode.h:
     20        * dfg/DFGPropagator.cpp:
     21        (JSC::DFG::Propagator::propagateNode):
     22        (JSC::DFG::Propagator::fixupNode):
     23        * dfg/DFGSpeculativeJIT.cpp:
     24        (JSC::DFG::SpeculativeJIT::compile):
     25        * jit/JITStubs.cpp:
     26        (JSC::JITThunks::hostFunctionStub):
     27        * runtime/Lookup.cpp:
     28        (JSC::setUpStaticFunctionSlot):
     29
    1302011-09-18  Nico Weber  <thakis@chromium.org>
    231
  • trunk/Source/JavaScriptCore/create_hash_table

    r95310 r95399  
    289289        }
    290290        if ($name eq "mathTable") {
     291            if ($key eq "min") {
     292                $intrinsic = "DFG::MinIntrinsic";
     293            }
     294            if ($key eq "max") {
     295                $intrinsic = "DFG::MaxIntrinsic";
     296            }
    291297            if ($key eq "sqrt") {
    292298                $thunkGenerator = "sqrtThunkGenerator";
     299                $intrinsic = "DFG::SqrtIntrinsic";
    293300            }
    294301            if ($key eq "pow") {
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r95389 r95399  
    6565
    6666private:
     67    // Helper for min and max.
     68    bool handleMinMax(bool usesResult, int resultOperand, NodeType op, int firstArg, int lastArg);
     69   
    6770    // Handle intrinsic functions.
    6871    bool handleIntrinsic(bool usesResult, int resultOperand, Intrinsic, int firstArg, int lastArg);
     
    601604    return !m_parseFailed
    602605
     606bool ByteCodeParser::handleMinMax(bool usesResult, int resultOperand, NodeType op, int firstArg, int lastArg)
     607{
     608    if (!usesResult)
     609        return true;
     610
     611    if (lastArg == firstArg) {
     612        set(resultOperand, constantNaN());
     613        return true;
     614    }
     615     
     616    if (lastArg == firstArg + 1) {
     617        set(resultOperand, getToNumber(firstArg + 1));
     618        return true;
     619    }
     620   
     621    if (lastArg == firstArg + 2) {
     622        set(resultOperand, addToGraph(op, getToNumber(firstArg + 1), getToNumber(firstArg + 2)));
     623        return true;
     624    }
     625   
     626    // Don't handle >=3 arguments for now.
     627    return false;
     628}
     629
    603630bool ByteCodeParser::handleIntrinsic(bool usesResult, int resultOperand, Intrinsic intrinsic, int firstArg, int lastArg)
    604631{
     
    618645        else
    619646            set(resultOperand, addToGraph(ArithAbs, getToNumber(absArg)));
     647        return true;
     648    }
     649       
     650    case MinIntrinsic:
     651        return handleMinMax(usesResult, resultOperand, ArithMin, firstArg, lastArg);
     652       
     653    case MaxIntrinsic:
     654        return handleMinMax(usesResult, resultOperand, ArithMax, firstArg, lastArg);
     655       
     656    case SqrtIntrinsic: {
     657        if (!usesResult)
     658            return true;
     659       
     660        if (firstArg == lastArg) {
     661            set(resultOperand, constantNaN());
     662            return true;
     663        }
     664       
     665        set(resultOperand, addToGraph(ArithSqrt, getToNumber(firstArg + 1)));
    620666        return true;
    621667    }
  • trunk/Source/JavaScriptCore/dfg/DFGIntrinsic.h

    r95310 r95399  
    3131enum Intrinsic {
    3232    NoIntrinsic,
    33     AbsIntrinsic
     33    AbsIntrinsic,
     34    MinIntrinsic,
     35    MaxIntrinsic,
     36    SqrtIntrinsic
    3437};
    3538
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r95389 r95399  
    156156    macro(ArithMod, NodeResultNumber) \
    157157    macro(ArithAbs, NodeResultNumber) \
     158    macro(ArithMin, NodeResultNumber) \
     159    macro(ArithMax, NodeResultNumber) \
     160    macro(ArithSqrt, NodeResultNumber) \
    158161    /* Arithmetic operators call ToNumber on their operands. */\
    159162    macro(ValueToNumber, NodeResultNumber | NodeMustGenerate) \
  • trunk/Source/JavaScriptCore/dfg/DFGPropagator.cpp

    r95389 r95399  
    226226        case ArithAdd:
    227227        case ArithSub:
    228         case ArithMul: {
     228        case ArithMul:
     229        case ArithMin:
     230        case ArithMax: {
    229231            PredictedType left = m_predictions[node.child1()];
    230232            PredictedType right = m_predictions[node.child2()];
     
    239241        }
    240242           
    241         case ArithDiv: {
     243        case ArithDiv:
     244        case ArithSqrt: {
    242245            changed |= setPrediction(makePrediction(PredictDouble, StrongPrediction));
    243246            break;
     
    406409        case ArithAdd:
    407410        case ArithSub:
    408         case ArithMul: {
     411        case ArithMul:
     412        case ArithMin:
     413        case ArithMax: {
    409414            PredictedType left = m_predictions[node.child1()];
    410415            PredictedType right = m_predictions[node.child2()];
     
    422427            toDouble(node.child1());
    423428            toDouble(node.child2());
     429            break;
     430        }
     431           
     432        case ArithAbs: {
     433            PredictedType prediction = m_predictions[node.child1()];
     434            if (isStrongPrediction(prediction) && (prediction & PredictDouble))
     435                toDouble(node.child1());
     436            break;
     437        }
     438           
     439        case ArithSqrt: {
     440            toDouble(node.child1());
    424441            break;
    425442        }
     
    731748        case ArithDiv:
    732749        case ArithAbs:
     750        case ArithMin:
     751        case ArithMax:
     752        case ArithSqrt:
    733753            setReplacement(pureCSE(node));
    734754            break;
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r95389 r95399  
    10841084        break;
    10851085    }
     1086       
     1087    case ArithMin:
     1088    case ArithMax: {
     1089        if (shouldSpeculateInteger(node.child1(), node.child2())) {
     1090            SpeculateIntegerOperand op1(this, node.child1());
     1091            SpeculateIntegerOperand op2(this, node.child2());
     1092            GPRTemporary result(this, op1);
     1093           
     1094            MacroAssembler::Jump op1Less = m_jit.branch32(op == ArithMin ? MacroAssembler::LessThan : MacroAssembler::GreaterThan, op1.gpr(), op2.gpr());
     1095            m_jit.move(op2.gpr(), result.gpr());
     1096            if (op1.gpr() != result.gpr()) {
     1097                MacroAssembler::Jump done = m_jit.jump();
     1098                op1Less.link(&m_jit);
     1099                m_jit.move(op1.gpr(), result.gpr());
     1100                done.link(&m_jit);
     1101            } else
     1102                op1Less.link(&m_jit);
     1103           
     1104            integerResult(result.gpr(), m_compileIndex);
     1105            break;
     1106        }
     1107       
     1108        SpeculateDoubleOperand op1(this, node.child1());
     1109        SpeculateDoubleOperand op2(this, node.child2());
     1110        FPRTemporary result(this, op1);
     1111       
     1112        MacroAssembler::JumpList done;
     1113       
     1114        MacroAssembler::Jump op1Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleLessThan : MacroAssembler::DoubleGreaterThan, op1.fpr(), op2.fpr());
     1115       
     1116        // op2 is eather the lesser one or one of then is NaN
     1117        MacroAssembler::Jump op2Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleGreaterThan : MacroAssembler::DoubleLessThan, op1.fpr(), op2.fpr());
     1118       
     1119        // Unordered case. We don't know which of op1, op2 is NaN. Manufacture NaN by adding
     1120        // op1 + op2 and putting it into result.
     1121        m_jit.addDouble(op1.fpr(), op2.fpr(), result.fpr());
     1122        done.append(m_jit.jump());
     1123       
     1124        op2Less.link(&m_jit);
     1125        m_jit.moveDouble(op2.fpr(), result.fpr());
     1126       
     1127        if (op1.fpr() != result.fpr()) {
     1128            done.append(m_jit.jump());
     1129           
     1130            op1Less.link(&m_jit);
     1131            m_jit.moveDouble(op1.fpr(), result.fpr());
     1132        } else
     1133            op1Less.link(&m_jit);
     1134       
     1135        done.link(&m_jit);
     1136       
     1137        doubleResult(result.fpr(), m_compileIndex);
     1138        break;
     1139    }
     1140       
     1141    case ArithSqrt: {
     1142        SpeculateDoubleOperand op1(this, node.child1());
     1143        FPRTemporary result(this, op1);
     1144       
     1145        m_jit.sqrtDouble(op1.fpr(), result.fpr());
     1146       
     1147        doubleResult(result.fpr(), m_compileIndex);
     1148        break;
     1149    }
    10861150
    10871151    case LogicalNot: {
  • trunk/Source/JavaScriptCore/jit/JITStubs.cpp

    r95388 r95399  
    37843784    std::pair<HostFunctionStubMap::iterator, bool> entry = m_hostFunctionStubMap->add(function, Weak<NativeExecutable>());
    37853785    if (!*entry.first->second) {
    3786         MacroAssemblerCodeRef code = globalData->canUseJIT() ? generator(globalData) : MacroAssemblerCodeRef();
     3786        MacroAssemblerCodeRef code;
     3787        if (generator) {
     3788            if (globalData->canUseJIT())
     3789                code = generator(globalData);
     3790            else
     3791                code = MacroAssemblerCodeRef();
     3792        } else
     3793            code = JIT::compileCTINativeCall(globalData, function);
    37873794        entry.first->second.set(*globalData, NativeExecutable::create(*globalData, code, function, MacroAssemblerCodeRef::createSelfManagedCodeRef(ctiNativeConstruct()), callHostFunctionAsConstructor, intrinsic));
    37883795    }
  • trunk/Source/JavaScriptCore/runtime/Lookup.cpp

    r95318 r95399  
    8282        JSGlobalObject* globalObject = thisObj->globalObject();
    8383#if ENABLE(JIT)
    84         if (entry->generator())
     84        if (entry->generator() || entry->intrinsic() != DFG::NoIntrinsic)
    8585            function = JSFunction::create(exec, globalObject, globalObject->functionStructure(), entry->functionLength(), propertyName, exec->globalData().getHostFunction(entry->function(), entry->generator(), entry->intrinsic()));
    8686        else
Note: See TracChangeset for help on using the changeset viewer.