Changeset 194087 in webkit


Ignore:
Timestamp:
Dec 14, 2015 7:51:42 PM (8 years ago)
Author:
Yusuke Suzuki
Message:

Math.random should have an intrinsic thunk and it should be later handled as a DFG Node
https://bugs.webkit.org/show_bug.cgi?id=152133

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

In this patch, we implement new RandomIntrinsic. It emits a machine code to generate random numbers efficiently.
And later it will be recognized by DFG and converted to ArithRandom node.
It provides type information SpecDoubleReal since Math.random only generates a number within [0, 1.0).

Currently, only 64bit version is supported. On 32bit environment, ArithRandom will be converted to callOperation.
While it emits a function call, ArithRandom node on 32bit still represents SpecDoubleReal as a result type.

  • dfg/DFGAbstractHeap.h:
  • dfg/DFGAbstractInterpreterInlines.h:

(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::handleIntrinsicCall):

  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):

  • dfg/DFGDoesGC.cpp:

(JSC::DFG::doesGC):

  • dfg/DFGFixupPhase.cpp:

(JSC::DFG::FixupPhase::fixupNode):

  • dfg/DFGNodeType.h:
  • dfg/DFGOperations.cpp:
  • dfg/DFGOperations.h:
  • dfg/DFGPredictionPropagationPhase.cpp:

(JSC::DFG::PredictionPropagationPhase::propagate):

  • dfg/DFGSafeToExecute.h:

(JSC::DFG::safeToExecute):

  • dfg/DFGSpeculativeJIT.h:

(JSC::DFG::SpeculativeJIT::callOperation):

  • dfg/DFGSpeculativeJIT32_64.cpp:

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

  • dfg/DFGSpeculativeJIT64.cpp:

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

  • ftl/FTLCapabilities.cpp:

(JSC::FTL::canCompile):

  • ftl/FTLLowerDFGToLLVM.cpp:

(JSC::FTL::DFG::LowerDFGToLLVM::compileNode):
(JSC::FTL::DFG::LowerDFGToLLVM::compileArithRandom):

  • jit/AssemblyHelpers.cpp:

(JSC::emitRandomThunkImpl):
(JSC::AssemblyHelpers::emitRandomThunk):

  • jit/AssemblyHelpers.h:
  • jit/JITOperations.h:
  • jit/ThunkGenerators.cpp:

(JSC::randomThunkGenerator):

  • jit/ThunkGenerators.h:
  • runtime/Intrinsic.h:
  • runtime/JSGlobalObject.h:

(JSC::JSGlobalObject::weakRandomOffset):

  • runtime/MathObject.cpp:

(JSC::MathObject::finishCreation):

  • runtime/VM.cpp:

(JSC::thunkGeneratorForIntrinsic):

  • tests/stress/random-53bit.js: Added.

(test):

  • tests/stress/random-in-range.js: Added.

(test):

Source/WTF:

Change 64bit random to double logic to convert efficiently.

  • wtf/WeakRandom.h:

(WTF::WeakRandom::get):
(WTF::WeakRandom::lowOffset):
(WTF::WeakRandom::highOffset):

LayoutTests:

Add new regression test.

  • js/regress/math-random-expected.txt: Added.
  • js/regress/math-random.html: Added.
  • js/regress/script-tests/math-random.js: Added.

(test):

Location:
trunk
Files:
5 added
29 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r194083 r194087  
     12015-12-14  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        Math.random should have an intrinsic thunk and it should be later handled as a DFG Node
     4        https://bugs.webkit.org/show_bug.cgi?id=152133
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        Add new regression test.
     9
     10        * js/regress/math-random-expected.txt: Added.
     11        * js/regress/math-random.html: Added.
     12        * js/regress/script-tests/math-random.js: Added.
     13        (test):
     14
    1152015-12-14  Joseph Pecoraro  <pecoraro@apple.com>
    216
  • trunk/Source/JavaScriptCore/ChangeLog

    r194073 r194087  
     12015-12-14  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        Math.random should have an intrinsic thunk and it should be later handled as a DFG Node
     4        https://bugs.webkit.org/show_bug.cgi?id=152133
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        In this patch, we implement new RandomIntrinsic. It emits a machine code to generate random numbers efficiently.
     9        And later it will be recognized by DFG and converted to ArithRandom node.
     10        It provides type information SpecDoubleReal since Math.random only generates a number within [0, 1.0).
     11
     12        Currently, only 64bit version is supported. On 32bit environment, ArithRandom will be converted to callOperation.
     13        While it emits a function call, ArithRandom node on 32bit still represents SpecDoubleReal as a result type.
     14
     15        * dfg/DFGAbstractHeap.h:
     16        * dfg/DFGAbstractInterpreterInlines.h:
     17        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
     18        * dfg/DFGByteCodeParser.cpp:
     19        (JSC::DFG::ByteCodeParser::handleIntrinsicCall):
     20        * dfg/DFGClobberize.h:
     21        (JSC::DFG::clobberize):
     22        * dfg/DFGDoesGC.cpp:
     23        (JSC::DFG::doesGC):
     24        * dfg/DFGFixupPhase.cpp:
     25        (JSC::DFG::FixupPhase::fixupNode):
     26        * dfg/DFGNodeType.h:
     27        * dfg/DFGOperations.cpp:
     28        * dfg/DFGOperations.h:
     29        * dfg/DFGPredictionPropagationPhase.cpp:
     30        (JSC::DFG::PredictionPropagationPhase::propagate):
     31        * dfg/DFGSafeToExecute.h:
     32        (JSC::DFG::safeToExecute):
     33        * dfg/DFGSpeculativeJIT.h:
     34        (JSC::DFG::SpeculativeJIT::callOperation):
     35        * dfg/DFGSpeculativeJIT32_64.cpp:
     36        (JSC::DFG::SpeculativeJIT::compile):
     37        (JSC::DFG::SpeculativeJIT::compileArithRandom):
     38        * dfg/DFGSpeculativeJIT64.cpp:
     39        (JSC::DFG::SpeculativeJIT::compile):
     40        (JSC::DFG::SpeculativeJIT::compileArithRandom):
     41        * ftl/FTLCapabilities.cpp:
     42        (JSC::FTL::canCompile):
     43        * ftl/FTLLowerDFGToLLVM.cpp:
     44        (JSC::FTL::DFG::LowerDFGToLLVM::compileNode):
     45        (JSC::FTL::DFG::LowerDFGToLLVM::compileArithRandom):
     46        * jit/AssemblyHelpers.cpp:
     47        (JSC::emitRandomThunkImpl):
     48        (JSC::AssemblyHelpers::emitRandomThunk):
     49        * jit/AssemblyHelpers.h:
     50        * jit/JITOperations.h:
     51        * jit/ThunkGenerators.cpp:
     52        (JSC::randomThunkGenerator):
     53        * jit/ThunkGenerators.h:
     54        * runtime/Intrinsic.h:
     55        * runtime/JSGlobalObject.h:
     56        (JSC::JSGlobalObject::weakRandomOffset):
     57        * runtime/MathObject.cpp:
     58        (JSC::MathObject::finishCreation):
     59        * runtime/VM.cpp:
     60        (JSC::thunkGeneratorForIntrinsic):
     61        * tests/stress/random-53bit.js: Added.
     62        (test):
     63        * tests/stress/random-in-range.js: Added.
     64        (test):
     65
    1662015-12-14  Benjamin Poulain  <benjamin@webkit.org>
    267
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractHeap.h

    r188979 r194087  
    7070    macro(HeapObjectCount) /* Used to reflect the fact that some allocations reveal object identity */\
    7171    macro(RegExpState) \
     72    macro(MathDotRandomState) \
    7273    macro(InternalState) \
    7374    macro(Absolute) \
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

    r194036 r194087  
    820820        }
    821821        forNode(node).setType(typeOfDoublePow(forNode(node->child1()).m_type, forNode(node->child2()).m_type));
     822        break;
     823    }
     824
     825    case ArithRandom: {
     826        forNode(node).setType(m_graph, SpecDoubleReal);
    822827        break;
    823828    }
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r194036 r194087  
    22132213        Node* right = get(rightOperand);
    22142214        set(VirtualRegister(resultOperand), addToGraph(ArithIMul, left, right));
     2215        return true;
     2216    }
     2217
     2218    case RandomIntrinsic: {
     2219        if (argumentCountIncludingThis != 1)
     2220            return false;
     2221        insertChecks();
     2222        set(VirtualRegister(resultOperand), addToGraph(ArithRandom));
    22152223        return true;
    22162224    }
  • trunk/Source/JavaScriptCore/dfg/DFGClobberize.h

    r194036 r194087  
    164164        def(PureValue(node));
    165165        return;
     166
     167    case ArithRandom:
     168        read(MathDotRandomState);
     169        write(MathDotRandomState);
     170        return;
    166171       
    167172    case HasGenericProperty:
  • trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp

    r194036 r194087  
    8686    case ArithPow:
    8787    case ArithSqrt:
     88    case ArithRandom:
    8889    case ArithRound:
    8990    case ArithFRound:
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r194040 r194087  
    349349            fixDoubleOrBooleanEdge(node->child1());
    350350            fixDoubleOrBooleanEdge(node->child2());
     351            break;
     352        }
     353
     354        case ArithRandom: {
     355            node->setResult(NodeResultDouble);
    351356            break;
    352357        }
  • trunk/Source/JavaScriptCore/dfg/DFGNodeType.h

    r194036 r194087  
    153153    macro(ArithFRound, NodeResultNumber) \
    154154    macro(ArithPow, NodeResultNumber) \
     155    macro(ArithRandom, NodeResultDouble | NodeMustGenerate) \
    155156    macro(ArithRound, NodeResultNumber) \
    156157    macro(ArithSqrt, NodeResultNumber) \
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r193781 r194087  
    12291229}
    12301230
     1231#if USE(JSVALUE32_64)
     1232double JIT_OPERATION operationRandom(JSGlobalObject* globalObject)
     1233{
     1234    return globalObject->weakRandomNumber();
     1235}
     1236#endif
     1237
    12311238JSCell* JIT_OPERATION operationStringFromCharCode(ExecState* exec, int32_t op1)
    12321239{
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.h

    r193781 r194087  
    151151void JIT_OPERATION triggerReoptimizationNow(CodeBlock*, OSRExitBase*) WTF_INTERNAL;
    152152
     153#if USE(JSVALUE32_64)
     154double JIT_OPERATION operationRandom(JSGlobalObject*);
     155#endif
     156
    153157#if ENABLE(FTL_JIT)
    154158void JIT_OPERATION triggerTierUpNow(ExecState*) WTF_INTERNAL;
  • trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp

    r194036 r194087  
    375375        case ArithLog: {
    376376            changed |= setPrediction(SpecBytecodeDouble);
     377            break;
     378        }
     379
     380        case ArithRandom: {
     381            changed |= setPrediction(SpecDoubleReal);
    377382            break;
    378383        }
  • trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h

    r194036 r194087  
    178178    case ArithMax:
    179179    case ArithPow:
     180    case ArithRandom:
    180181    case ArithSqrt:
    181182    case ArithFRound:
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r194036 r194087  
    15511551#endif
    15521552
     1553    JITCompiler::Call callOperation(D_JITOperation_G operation, FPRReg result, JSGlobalObject* globalObject)
     1554    {
     1555        m_jit.setupArguments(TrustedImmPtr(globalObject));
     1556        return appendCallSetResult(operation, result);
     1557    }
    15531558    JITCompiler::Call callOperation(Z_JITOperation_D operation, GPRReg result, FPRReg arg1)
    15541559    {
     
    22262231    void compileArithPow(Node*);
    22272232    void compileArithRound(Node*);
     2233    void compileArithRandom(Node*);
    22282234    void compileArithSqrt(Node*);
    22292235    void compileArithLog(Node*);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r194036 r194087  
    22872287        break;
    22882288    }
     2289
     2290    case ArithRandom:
     2291        compileArithRandom(node);
     2292        break;
    22892293
    22902294    case ArithRound:
     
    48474851}
    48484852
     4853void SpeculativeJIT::compileArithRandom(Node* node)
     4854{
     4855    JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
     4856
     4857    flushRegisters();
     4858
     4859    FPRResult result(this);
     4860    callOperation(operationRandom, result.fpr(), globalObject);
     4861    // operationRandom does not raise any exception.
     4862    doubleResult(result.fpr(), node);
     4863}
     4864
    48494865#endif
    48504866
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r194036 r194087  
    24092409        break;
    24102410    }
     2411
     2412    case ArithRandom:
     2413        compileArithRandom(node);
     2414        break;
    24112415
    24122416    case ArithRound:
     
    49534957}
    49544958
     4959void SpeculativeJIT::compileArithRandom(Node* node)
     4960{
     4961    JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
     4962    GPRTemporary temp1(this);
     4963    GPRTemporary temp2(this);
     4964    GPRTemporary temp3(this);
     4965    FPRTemporary result(this);
     4966    m_jit.emitRandomThunk(globalObject, temp1.gpr(), temp2.gpr(), temp3.gpr(), result.fpr());
     4967    doubleResult(result.fpr(), node);
     4968}
     4969
    49554970#endif
    49564971
  • trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp

    r194036 r194087  
    9595    case ArithCos:
    9696    case ArithPow:
     97    case ArithRandom:
    9798    case ArithRound:
    9899    case ArithSqrt:
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp

    r194073 r194087  
    626626            compileArithPow();
    627627            break;
     628        case ArithRandom:
     629            compileArithRandom();
     630            break;
    628631        case ArithRound:
    629632            compileArithRound();
     
    21182121            setDouble(m_out.phi(m_out.doubleType, powDoubleIntResult, powResult, pureNan));
    21192122        }
     2123    }
     2124
     2125    void compileArithRandom()
     2126    {
     2127        JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
     2128
     2129        // Inlined WeakRandom::advance().
     2130        // uint64_t x = m_low;
     2131        void* lowAddress = reinterpret_cast<uint8_t*>(globalObject) + JSGlobalObject::weakRandomOffset() + WeakRandom::lowOffset();
     2132        LValue low = m_out.load64(m_out.absolute(lowAddress));
     2133        // uint64_t y = m_high;
     2134        void* highAddress = reinterpret_cast<uint8_t*>(globalObject) + JSGlobalObject::weakRandomOffset() + WeakRandom::highOffset();
     2135        LValue high = m_out.load64(m_out.absolute(highAddress));
     2136        // m_low = y;
     2137        m_out.store64(high, m_out.absolute(lowAddress));
     2138
     2139        // x ^= x << 23;
     2140        LValue phase1 = m_out.bitXor(m_out.shl(low, m_out.constInt64(23)), low);
     2141
     2142        // x ^= x >> 17;
     2143        LValue phase2 = m_out.bitXor(m_out.lShr(phase1, m_out.constInt64(17)), phase1);
     2144
     2145        // x ^= y ^ (y >> 26);
     2146        LValue phase3 = m_out.bitXor(m_out.bitXor(high, m_out.lShr(high, m_out.constInt64(26))), phase2);
     2147
     2148        // m_high = x;
     2149        m_out.store64(phase3, m_out.absolute(highAddress));
     2150
     2151        // return x + y;
     2152        LValue random64 = m_out.add(phase3, high);
     2153
     2154        // Extract random 53bit. [0, 53] bit is safe integer number ranges in double representation.
     2155        LValue random53 = m_out.bitAnd(random64, m_out.constInt64((1ULL << 53) - 1));
     2156
     2157        LValue double53Integer = m_out.intToDouble(random53);
     2158
     2159        // Convert `(53bit double integer value) / (1 << 53)` to `(53bit double integer value) * (1.0 / (1 << 53))`.
     2160        // In latter case, `1.0 / (1 << 53)` will become a double value represented as (mantissa = 0 & exp = 970, it means 1e-(2**54)).
     2161        static const double scale = 1.0 / (1ULL << 53);
     2162
     2163        // Multiplying 1e-(2**54) with the double integer does not change anything of the mantissa part of the double integer.
     2164        // It just reduces the exp part of the given 53bit double integer.
     2165        // (Except for 0.0. This is specially handled and in this case, exp just becomes 0.)
     2166        // Now we get 53bit precision random double value in [0, 1).
     2167        LValue result = m_out.doubleMul(double53Integer, m_out.constDouble(scale));
     2168
     2169        setDouble(result);
    21202170    }
    21212171
  • trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp

    r193424 r194087  
    421421}
    422422
     423#if USE(JSVALUE64)
     424template<typename LoadFromHigh, typename StoreToHigh, typename LoadFromLow, typename StoreToLow>
     425void emitRandomThunkImpl(AssemblyHelpers& jit, GPRReg scratch0, GPRReg scratch1, GPRReg scratch2, FPRReg result, const LoadFromHigh& loadFromHigh, const StoreToHigh& storeToHigh, const LoadFromLow& loadFromLow, const StoreToLow& storeToLow)
     426{
     427    // Inlined WeakRandom::advance().
     428    // uint64_t x = m_low;
     429    loadFromLow(scratch0);
     430    // uint64_t y = m_high;
     431    loadFromHigh(scratch1);
     432    // m_low = y;
     433    storeToLow(scratch1);
     434
     435    // x ^= x << 23;
     436    jit.move(scratch0, scratch2);
     437    jit.lshift64(AssemblyHelpers::TrustedImm32(23), scratch2);
     438    jit.xor64(scratch2, scratch0);
     439
     440    // x ^= x >> 17;
     441    jit.move(scratch0, scratch2);
     442    jit.rshift64(AssemblyHelpers::TrustedImm32(17), scratch2);
     443    jit.xor64(scratch2, scratch0);
     444
     445    // x ^= y ^ (y >> 26);
     446    jit.move(scratch1, scratch2);
     447    jit.rshift64(AssemblyHelpers::TrustedImm32(26), scratch2);
     448    jit.xor64(scratch1, scratch2);
     449    jit.xor64(scratch2, scratch0);
     450
     451    // m_high = x;
     452    storeToHigh(scratch0);
     453
     454    // return x + y;
     455    jit.add64(scratch1, scratch0);
     456
     457    // Extract random 53bit. [0, 53] bit is safe integer number ranges in double representation.
     458    jit.move(AssemblyHelpers::TrustedImm64((1ULL << 53) - 1), scratch1);
     459    jit.and64(scratch1, scratch0);
     460    // Now, scratch0 is always in range of int64_t. Safe to convert it to double with cvtsi2sdq.
     461    jit.convertInt64ToDouble(scratch0, result);
     462
     463    // Convert `(53bit double integer value) / (1 << 53)` to `(53bit double integer value) * (1.0 / (1 << 53))`.
     464    // In latter case, `1.0 / (1 << 53)` will become a double value represented as (mantissa = 0 & exp = 970, it means 1e-(2**54)).
     465    static const double scale = 1.0 / (1ULL << 53);
     466
     467    // Multiplying 1e-(2**54) with the double integer does not change anything of the mantissa part of the double integer.
     468    // It just reduces the exp part of the given 53bit double integer.
     469    // (Except for 0.0. This is specially handled and in this case, exp just becomes 0.)
     470    // Now we get 53bit precision random double value in [0, 1).
     471    jit.move(AssemblyHelpers::TrustedImmPtr(&scale), scratch1);
     472    jit.mulDouble(AssemblyHelpers::Address(scratch1), result);
     473}
     474
     475void AssemblyHelpers::emitRandomThunk(JSGlobalObject* globalObject, GPRReg scratch0, GPRReg scratch1, GPRReg scratch2, FPRReg result)
     476{
     477    void* lowAddress = reinterpret_cast<uint8_t*>(globalObject) + JSGlobalObject::weakRandomOffset() + WeakRandom::lowOffset();
     478    void* highAddress = reinterpret_cast<uint8_t*>(globalObject) + JSGlobalObject::weakRandomOffset() + WeakRandom::highOffset();
     479
     480    auto loadFromHigh = [&](GPRReg high) {
     481        load64(highAddress, high);
     482    };
     483    auto storeToHigh = [&](GPRReg high) {
     484        store64(high, highAddress);
     485    };
     486    auto loadFromLow = [&](GPRReg low) {
     487        load64(lowAddress, low);
     488    };
     489    auto storeToLow = [&](GPRReg low) {
     490        store64(low, lowAddress);
     491    };
     492
     493    emitRandomThunkImpl(*this, scratch0, scratch1, scratch2, result, loadFromHigh, storeToHigh, loadFromLow, storeToLow);
     494}
     495
     496void AssemblyHelpers::emitRandomThunk(GPRReg scratch0, GPRReg scratch1, GPRReg scratch2, GPRReg scratch3, FPRReg result)
     497{
     498    emitGetFromCallFrameHeaderPtr(JSStack::Callee, scratch3);
     499    emitLoadStructure(scratch3, scratch3, scratch0);
     500    loadPtr(Address(scratch3, Structure::globalObjectOffset()), scratch3);
     501    // Now, scratch3 holds JSGlobalObject*.
     502
     503    auto loadFromHigh = [&](GPRReg high) {
     504        load64(Address(scratch3, JSGlobalObject::weakRandomOffset() + WeakRandom::highOffset()), high);
     505    };
     506    auto storeToHigh = [&](GPRReg high) {
     507        store64(high, Address(scratch3, JSGlobalObject::weakRandomOffset() + WeakRandom::highOffset()));
     508    };
     509    auto loadFromLow = [&](GPRReg low) {
     510        load64(Address(scratch3, JSGlobalObject::weakRandomOffset() + WeakRandom::lowOffset()), low);
     511    };
     512    auto storeToLow = [&](GPRReg low) {
     513        store64(low, Address(scratch3, JSGlobalObject::weakRandomOffset() + WeakRandom::lowOffset()));
     514    };
     515
     516    emitRandomThunkImpl(*this, scratch0, scratch1, scratch2, result, loadFromHigh, storeToHigh, loadFromLow, storeToLow);
     517}
     518#endif
     519
    423520} // namespace JSC
    424521
  • trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h

    r193471 r194087  
    13721372            addPtr(TrustedImm32(stackOffset), stackPointerRegister);
    13731373    }
     1374
     1375#if USE(JSVALUE64)
     1376    void emitRandomThunk(JSGlobalObject*, GPRReg scratch0, GPRReg scratch1, GPRReg scratch2, FPRReg result);
     1377    void emitRandomThunk(GPRReg scratch0, GPRReg scratch1, GPRReg scratch2, GPRReg scratch3, FPRReg result);
     1378#endif
    13741379   
    13751380protected:
  • trunk/Source/JavaScriptCore/jit/JITOperations.h

    r194036 r194087  
    165165typedef JSCell* JIT_OPERATION (*C_JITOperation_EZ)(ExecState*, int32_t);
    166166typedef double JIT_OPERATION (*D_JITOperation_D)(double);
     167typedef double JIT_OPERATION (*D_JITOperation_G)(JSGlobalObject*);
    167168typedef double JIT_OPERATION (*D_JITOperation_DD)(double, double);
    168169typedef double JIT_OPERATION (*D_JITOperation_ZZ)(int32_t, int32_t);
  • trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp

    r194062 r194087  
    10051005}
    10061006
     1007MacroAssemblerCodeRef randomThunkGenerator(VM* vm)
     1008{
     1009    SpecializedThunkJIT jit(vm, 0);
     1010    if (!jit.supportsFloatingPoint())
     1011        return MacroAssemblerCodeRef::createSelfManagedCodeRef(vm->jitStubs->ctiNativeCall(vm));
     1012
     1013#if USE(JSVALUE64)
     1014    jit.emitRandomThunk(SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT1, SpecializedThunkJIT::regT2, SpecializedThunkJIT::regT3, SpecializedThunkJIT::fpRegT0);
     1015    jit.returnDouble(SpecializedThunkJIT::fpRegT0);
     1016
     1017    return jit.finalize(vm->jitStubs->ctiNativeTailCall(vm), "random");
     1018#else
     1019    return MacroAssemblerCodeRef::createSelfManagedCodeRef(vm->jitStubs->ctiNativeCall(vm));
     1020#endif
     1021}
     1022
    10071023}
    10081024
  • trunk/Source/JavaScriptCore/jit/ThunkGenerators.h

    r191937 r194087  
    6363MacroAssemblerCodeRef powThunkGenerator(VM*);
    6464MacroAssemblerCodeRef imulThunkGenerator(VM*);
     65MacroAssemblerCodeRef randomThunkGenerator(VM*);
    6566
    6667}
  • trunk/Source/JavaScriptCore/runtime/Intrinsic.h

    r191215 r194087  
    5454    StringPrototypeValueOfIntrinsic,
    5555    IMulIntrinsic,
     56    RandomIntrinsic,
    5657    FRoundIntrinsic,
    5758
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h

    r194036 r194087  
    666666    TemplateRegistry& templateRegistry() { return m_templateRegistry; }
    667667
     668    static ptrdiff_t weakRandomOffset() { return OBJECT_OFFSETOF(JSGlobalObject, m_weakRandom); }
    668669    double weakRandomNumber() { return m_weakRandom.get(); }
    669670    unsigned weakRandomInteger() { return m_weakRandom.getUint32(); }
  • trunk/Source/JavaScriptCore/runtime/MathObject.cpp

    r191864 r194087  
    122122    putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier::fromString(&vm, "min"), 2, mathProtoFuncMin, MinIntrinsic, DontEnum);
    123123    putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier::fromString(&vm, "pow"), 2, mathProtoFuncPow, PowIntrinsic, DontEnum);
    124     putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier::fromString(&vm, "random"), 0, mathProtoFuncRandom, NoIntrinsic, DontEnum);
     124    putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier::fromString(&vm, "random"), 0, mathProtoFuncRandom, RandomIntrinsic, DontEnum);
    125125    putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier::fromString(&vm, "round"), 1, mathProtoFuncRound, RoundIntrinsic, DontEnum);
    126126    putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier::fromString(&vm, "sign"), 1, mathProtoFuncSign, NoIntrinsic, DontEnum);
  • trunk/Source/JavaScriptCore/runtime/VM.cpp

    r193649 r194087  
    449449    case IMulIntrinsic:
    450450        return imulThunkGenerator;
     451    case RandomIntrinsic:
     452        return randomThunkGenerator;
    451453    default:
    452454        return 0;
  • trunk/Source/WTF/ChangeLog

    r194041 r194087  
     12015-12-14  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        Math.random should have an intrinsic thunk and it should be later handled as a DFG Node
     4        https://bugs.webkit.org/show_bug.cgi?id=152133
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        Change 64bit random to double logic to convert efficiently.
     9
     10        * wtf/WeakRandom.h:
     11        (WTF::WeakRandom::get):
     12        (WTF::WeakRandom::lowOffset):
     13        (WTF::WeakRandom::highOffset):
     14
    1152015-12-14  Sukolsak Sakshuwong  <sukolsak@gmail.com>
    216
  • trunk/Source/WTF/wtf/WeakRandom.h

    r192855 r194087  
    3838namespace WTF {
    3939
     40// The code used to generate random numbers are inlined manually in JIT code.
     41// So it needs to stay in sync with the JIT one.
    4042class WeakRandom {
    4143public:
     
    6163    double get()
    6264    {
    63         return advance() / (std::numeric_limits<uint64_t>::max() + 1.0);
     65        uint64_t value = advance() & ((1ULL << 53) - 1);
     66        return value * (1.0 / (1ULL << 53));
    6467    }
    6568
     
    8184        }
    8285    }
     86
     87    static unsigned lowOffset() { return OBJECT_OFFSETOF(WeakRandom, m_low); }
     88    static unsigned highOffset() { return OBJECT_OFFSETOF(WeakRandom, m_high); }
    8389
    8490private:
Note: See TracChangeset for help on using the changeset viewer.