Changeset 35639 in webkit for trunk/JavaScriptCore/VM/Machine.cpp


Ignore:
Timestamp:
Aug 8, 2008, 2:48:10 AM (17 years ago)
Author:
[email protected]
Message:

Improve performance of arithmetic operators

Reviewed by Cameron Zwarich

Added a fast (non-virtual) mechanism to determine if a non-immediate JSValue*
is a JSNumberCell. We then use this to allow improved specialisation in many
arithmetic operators. SunSpider reports a 2.5% progression overall, with greater
than 10% progressions on a number of arithmetic heavy tests.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/VM/Machine.cpp

    r35594 r35639  
    9797}
    9898
     99static bool fastIsNumber(JSValue* value, double& arg) {
     100    if (JSImmediate::isNumber(value))
     101        arg = JSImmediate::getTruncatedInt32(value);
     102    else if (Heap::fastIsNumber(static_cast<JSCell*>(value)))
     103        arg = static_cast<JSNumberCell*>(value)->value();
     104    else
     105        return false;
     106    return true;
     107}
     108
     109static bool fastToInt32(JSValue* value, int32_t& arg) {
     110    if (JSImmediate::isNumber(value))
     111        arg = JSImmediate::getTruncatedInt32(value);
     112    else if (Heap::fastIsNumber(static_cast<JSCell*>(value)))
     113        arg = static_cast<JSNumberCell*>(value)->fastToInt32();
     114    else
     115        return false;
     116    return true;
     117}
     118
     119static ALWAYS_INLINE bool fastToUInt32(JSValue* value, uint32_t& arg) {
     120    if (JSImmediate::isNumber(value)) {
     121        if (JSImmediate::getTruncatedUInt32(value, arg))
     122            return true;
     123        bool scratch;
     124        arg = JSValue::toUInt32SlowCase(JSImmediate::getTruncatedInt32(value), scratch);
     125        return true;
     126    } else if (Heap::fastIsNumber(static_cast<JSCell*>(value)))
     127        arg = static_cast<JSNumberCell*>(value)->fastToUInt32();
     128    else
     129        return false;
     130    return true;
     131}
     132
    99133static inline bool jsLess(ExecState* exec, JSValue* v1, JSValue* v2)
    100134{
     
    104138    double n1;
    105139    double n2;
     140    if (fastIsNumber(v1, n1) && fastIsNumber(v2, n2))
     141        return n1 < n2;
     142
    106143    JSValue* p1;
    107144    JSValue* p2;
     
    122159    double n1;
    123160    double n2;
     161    if (fastIsNumber(v1, n1) && fastIsNumber(v2, n2))
     162        return n1 <= n2;
     163
    124164    JSValue* p1;
    125165    JSValue* p2;
     
    160200static inline JSValue* jsAdd(ExecState* exec, JSValue* v1, JSValue* v2)
    161201{
     202    double left;
     203    double right;
     204   
     205    if (fastIsNumber(v1, left) && fastIsNumber(v2, right))
     206        return jsNumber(exec, left + right);
     207   
    162208    JSType t1 = v1->type();
    163209    JSType t2 = v2->type();
    164210    const unsigned bothTypes = (t1 << 3) | t2;
    165 
    166     if (bothTypes == ((NumberType << 3) | NumberType))
    167         return jsNumber(exec, v1->uncheckedGetNumber() + v2->uncheckedGetNumber());
     211    ASSERT(bothTypes != ((NumberType << 3) | NumberType));
    168212    if (bothTypes == ((StringType << 3) | StringType)) {
    169213        UString value = static_cast<JSString*>(v1)->value() + static_cast<JSString*>(v2)->value();
     
    13591403        */
    13601404        int dst = (++vPC)->u.operand;
    1361         int src = (++vPC)->u.operand;
    1362         JSValue* result = jsNumber(exec, -r[src].jsValue(exec)->toNumber(exec));
    1363         VM_CHECK_EXCEPTION();
    1364         r[dst] = result;
     1405        JSValue* src = r[(++vPC)->u.operand].jsValue(exec);
     1406        double v;
     1407        if (fastIsNumber(src, v))
     1408            r[dst] = jsNumber(exec, -v);
     1409        else {
     1410            JSValue* result = jsNumber(exec, -src->toNumber(exec));
     1411            VM_CHECK_EXCEPTION();
     1412            r[dst] = result;
     1413        }
    13651414
    13661415        ++vPC;
     
    13961445        JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
    13971446        JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
    1398         JSValue* result = jsNumber(exec, src1->toNumber(exec) * src2->toNumber(exec));
    1399         VM_CHECK_EXCEPTION();
    1400         r[dst] = result;
     1447        double left;
     1448        double right;
     1449        if (fastIsNumber(src1, left) && fastIsNumber(src2, right))
     1450            r[dst] = jsNumber(exec, left * right);
     1451        else {
     1452            JSValue* result = jsNumber(exec, src1->toNumber(exec) * src2->toNumber(exec));
     1453            VM_CHECK_EXCEPTION();
     1454            r[dst] = result;
     1455        }
    14011456
    14021457        ++vPC;
     
    14111466        */
    14121467        int dst = (++vPC)->u.operand;
    1413         int dividend = (++vPC)->u.operand;
    1414         int divisor = (++vPC)->u.operand;
    1415         JSValue* result = jsNumber(exec, r[dividend].jsValue(exec)->toNumber(exec) / r[divisor].jsValue(exec)->toNumber(exec));
    1416         VM_CHECK_EXCEPTION();
    1417         r[dst] = result;
     1468        JSValue* dividend = r[(++vPC)->u.operand].jsValue(exec);
     1469        JSValue* divisor = r[(++vPC)->u.operand].jsValue(exec);
     1470        double left;
     1471        double right;
     1472        if (fastIsNumber(dividend, left) && fastIsNumber(divisor, right))
     1473            r[dst] = jsNumber(exec, left / right);
     1474        else {
     1475            JSValue* result = jsNumber(exec, dividend->toNumber(exec) / divisor->toNumber(exec));
     1476            VM_CHECK_EXCEPTION();
     1477            r[dst] = result;
     1478        }
    14181479        ++vPC;
    14191480        NEXT_OPCODE;
     
    14561517        JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
    14571518        JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
     1519        double left;
     1520        double right;
    14581521        if (JSImmediate::canDoFastAdditiveOperations(src1) && JSImmediate::canDoFastAdditiveOperations(src2))
    14591522            r[dst] = JSImmediate::subImmediateNumbers(src1, src2);
     1523        else if (fastIsNumber(src1, left) && fastIsNumber(src2, right))
     1524            r[dst] = jsNumber(exec, left - right);
    14601525        else {
    14611526            JSValue* result = jsNumber(exec, src1->toNumber(exec) - src2->toNumber(exec));
     
    14761541        JSValue* val = r[(++vPC)->u.operand].jsValue(exec);
    14771542        JSValue* shift = r[(++vPC)->u.operand].jsValue(exec);
     1543        int32_t left;
     1544        uint32_t right;
    14781545        if (JSImmediate::areBothImmediateNumbers(val, shift))
    14791546            r[dst] = jsNumber(exec, JSImmediate::getTruncatedInt32(val) << (JSImmediate::toTruncatedUInt32(shift) & 0x1f));
     1547        else if (fastToInt32(val, left) && fastToUInt32(shift, right))
     1548            r[dst] = jsNumber(exec, left << (right & 0x1f));
    14801549        else {
    14811550            JSValue* result = jsNumber(exec, (val->toInt32(exec)) << (shift->toUInt32(exec) & 0x1f));
     
    14971566        JSValue* val = r[(++vPC)->u.operand].jsValue(exec);
    14981567        JSValue* shift = r[(++vPC)->u.operand].jsValue(exec);
     1568        int32_t left;
     1569        uint32_t right;
    14991570        if (JSImmediate::areBothImmediateNumbers(val, shift))
    15001571            r[dst] = JSImmediate::rightShiftImmediateNumbers(val, shift);
     1572        else if (fastToInt32(val, left) && fastToUInt32(shift, right))
     1573            r[dst] = jsNumber(exec, left >> (right & 0x1f));
    15011574        else {
    15021575            JSValue* result = jsNumber(exec, (val->toInt32(exec)) >> (shift->toUInt32(exec) & 0x1f));
     
    15391612        JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
    15401613        JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
     1614        int32_t left;
     1615        int32_t right;
    15411616        if (JSImmediate::areBothImmediateNumbers(src1, src2))
    15421617            r[dst] = JSImmediate::andImmediateNumbers(src1, src2);
     1618        else if (fastToInt32(src1, left) && fastToInt32(src2, right))
     1619            r[dst] = jsNumber(exec, left & right);
    15431620        else {
    15441621            JSValue* result = jsNumber(exec, src1->toInt32(exec) & src2->toInt32(exec));
     
    15601637        JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
    15611638        JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
     1639        int32_t left;
     1640        int32_t right;
    15621641        if (JSImmediate::areBothImmediateNumbers(src1, src2))
    15631642            r[dst] = JSImmediate::xorImmediateNumbers(src1, src2);
     1643        else if (fastToInt32(src1, left) && fastToInt32(src2, right))
     1644            r[dst] = jsNumber(exec, left ^ right);
    15641645        else {
    15651646            JSValue* result = jsNumber(exec, src1->toInt32(exec) ^ src2->toInt32(exec));
     
    15811662        JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
    15821663        JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
     1664        int32_t left;
     1665        int32_t right;
    15831666        if (JSImmediate::areBothImmediateNumbers(src1, src2))
    15841667            r[dst] = JSImmediate::orImmediateNumbers(src1, src2);
     1668        else if (fastToInt32(src1, left) && fastToInt32(src2, right))
     1669            r[dst] = jsNumber(exec, left | right);
    15851670        else {
    15861671            JSValue* result = jsNumber(exec, src1->toInt32(exec) | src2->toInt32(exec));
     
    15991684        */
    16001685        int dst = (++vPC)->u.operand;
    1601         int src = (++vPC)->u.operand;
    1602         JSValue* result = jsNumber(exec, ~r[src].jsValue(exec)->toInt32(exec));
    1603         VM_CHECK_EXCEPTION();
    1604         r[dst] = result;
    1605 
     1686        JSValue* src = r[(++vPC)->u.operand].jsValue(exec);
     1687        int32_t value;
     1688        if (fastToInt32(src, value))
     1689            r[dst] = jsNumber(exec, ~value);
     1690        else {
     1691            JSValue* result = jsNumber(exec, ~src->toInt32(exec));
     1692            VM_CHECK_EXCEPTION();
     1693            r[dst] = result;
     1694        }
    16061695        ++vPC;
    16071696        NEXT_OPCODE;
Note: See TracChangeset for help on using the changeset viewer.