Changeset 27589 in webkit


Ignore:
Timestamp:
Nov 7, 2007 11:58:15 PM (16 years ago)
Author:
eric@webkit.org
Message:

2007-11-07 Eric Seidel <eric@webkit.org>

Reviewed by Darin and Oliver.


Add evaluateToNumber parallel evaluation tree to speed up number operations.
Make ImmediateNumberNode a subclass of NumberNode.
Share evaluate logic between evaluate and evaluateToNumber using inline functions
There is still a lot of improvement to be made here.


SunSpider claims this is a 1.0% speedup overall (nbody 7.9%), base64 slowing 2.0%
Given the huge win that this prepares us for with simple type inferencing I see the small
regression in base64 being worth the substantial overall improvement.

  • kjs/grammar.y:
  • kjs/nodes.cpp: (KJS::Node::evaluateToNumber): (KJS::NumberNode::evaluate): (KJS::NumberNode::evaluateToNumber): (KJS::StringNode::evaluateToNumber): (KJS::LocalVarAccessNode::inlineEvaluate): (KJS::LocalVarAccessNode::evaluate): (KJS::LocalVarAccessNode::evaluateToNumber): (KJS::BracketAccessorNode::inlineEvaluate): (KJS::BracketAccessorNode::evaluate): (KJS::BracketAccessorNode::evaluateToNumber): (KJS::NegateNode::evaluate): (KJS::NegateNode::evaluateToNumber): (KJS::MultNode::inlineEvaluateToNumber): (KJS::MultNode::evaluate): (KJS::MultNode::evaluateToNumber): (KJS::DivNode::inlineEvaluateToNumber): (KJS::DivNode::evaluate): (KJS::DivNode::evaluateToNumber): (KJS::ModNode::inlineEvaluateToNumber): (KJS::ModNode::evaluate): (KJS::ModNode::evaluateToNumber): (KJS::throwOutOfMemoryErrorToNumber): (KJS::addSlowCaseToNumber): (KJS::add): (KJS::addToNumber): (KJS::AddNode::evaluateToNumber): (KJS::SubNode::inlineEvaluateToNumber): (KJS::SubNode::evaluate): (KJS::SubNode::evaluateToNumber): (KJS::valueForReadModifyAssignment): (KJS::ReadModifyLocalVarNode::evaluate): (KJS::ReadModifyResolveNode::evaluate): (KJS::ReadModifyDotNode::evaluate): (KJS::ReadModifyBracketNode::evaluate):
  • kjs/nodes.h: (KJS::Node::): (KJS::NumberNode::): (KJS::ImmediateNumberNode::): (KJS::AddNode::precedence):
  • kjs/nodes2string.cpp: (KJS::NumberNode::streamTo):
Location:
trunk/JavaScriptCore
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r27574 r27589  
     12007-11-07  Eric Seidel  <eric@webkit.org>
     2
     3        Reviewed by Darin and Oliver.
     4       
     5        Add evaluateToNumber parallel evaluation tree to speed up number operations.
     6        Make ImmediateNumberNode a subclass of NumberNode.
     7        Share evaluate logic between evaluate and evaluateToNumber using inline functions
     8        There is still a lot of improvement to be made here.
     9       
     10        SunSpider claims this is a 1.0% speedup overall (nbody 7.9%), base64 slowing 2.0%
     11        Given the huge win that this prepares us for with simple type inferencing I see the small
     12        regression in base64 being worth the substantial overall improvement.
     13
     14        * kjs/grammar.y:
     15        * kjs/nodes.cpp:
     16        (KJS::Node::evaluateToNumber):
     17        (KJS::NumberNode::evaluate):
     18        (KJS::NumberNode::evaluateToNumber):
     19        (KJS::StringNode::evaluateToNumber):
     20        (KJS::LocalVarAccessNode::inlineEvaluate):
     21        (KJS::LocalVarAccessNode::evaluate):
     22        (KJS::LocalVarAccessNode::evaluateToNumber):
     23        (KJS::BracketAccessorNode::inlineEvaluate):
     24        (KJS::BracketAccessorNode::evaluate):
     25        (KJS::BracketAccessorNode::evaluateToNumber):
     26        (KJS::NegateNode::evaluate):
     27        (KJS::NegateNode::evaluateToNumber):
     28        (KJS::MultNode::inlineEvaluateToNumber):
     29        (KJS::MultNode::evaluate):
     30        (KJS::MultNode::evaluateToNumber):
     31        (KJS::DivNode::inlineEvaluateToNumber):
     32        (KJS::DivNode::evaluate):
     33        (KJS::DivNode::evaluateToNumber):
     34        (KJS::ModNode::inlineEvaluateToNumber):
     35        (KJS::ModNode::evaluate):
     36        (KJS::ModNode::evaluateToNumber):
     37        (KJS::throwOutOfMemoryErrorToNumber):
     38        (KJS::addSlowCaseToNumber):
     39        (KJS::add):
     40        (KJS::addToNumber):
     41        (KJS::AddNode::evaluateToNumber):
     42        (KJS::SubNode::inlineEvaluateToNumber):
     43        (KJS::SubNode::evaluate):
     44        (KJS::SubNode::evaluateToNumber):
     45        (KJS::valueForReadModifyAssignment):
     46        (KJS::ReadModifyLocalVarNode::evaluate):
     47        (KJS::ReadModifyResolveNode::evaluate):
     48        (KJS::ReadModifyDotNode::evaluate):
     49        (KJS::ReadModifyBracketNode::evaluate):
     50        * kjs/nodes.h:
     51        (KJS::Node::):
     52        (KJS::NumberNode::):
     53        (KJS::ImmediateNumberNode::):
     54        (KJS::AddNode::precedence):
     55        * kjs/nodes2string.cpp:
     56        (KJS::NumberNode::streamTo):
     57
    1582007-11-07  Mark Rowe  <mrowe@apple.com>
    259
  • trunk/JavaScriptCore/kjs/grammar.y

    r27394 r27589  
    44 *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
    55 *  Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
     6 *  Copyright (C) 2007 Eric Seidel <eric@webkit.org>
    67 *
    78 *  This library is free software; you can redistribute it and/or
     
    10211022}
    10221023
    1023 static Node* makeNegateNode(Node *n)
     1024static Node* makeNegateNode(Node* n)
    10241025{
    10251026    if (n->isNumber()) {
     
    10301031            return number;
    10311032        }
    1032     } else if (n->isImmediateValue()) {
    1033         ImmediateNumberNode* number = static_cast<ImmediateNumberNode*>(n);
    1034         double value = number->value();
    1035         if (value > 0.0) {
    1036             number->setValue(-value);
    1037             return number;
    1038         }
    10391033    }
    10401034
     
    10461040    JSValue* value = JSImmediate::fromDouble(d);
    10471041    if (value)
    1048         return new ImmediateNumberNode(value);
     1042        return new ImmediateNumberNode(value, d);
    10491043    return new NumberNode(d);
    10501044}
  • trunk/JavaScriptCore/kjs/nodes.cpp

    r27501 r27589  
    55 *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
    66 *  Copyright (C) 2007 Maks Orlovich
     7 *  Copyright (C) 2007 Eric Seidel <eric@webkit.org>
    78 *
    89 *  This library is free software; you can redistribute it and/or
     
    5657  }
    5758
     59#define KJS_CHECKEXCEPTIONNUMBER \
     60  if (exec->hadException()) { \
     61    handleException(exec); \
     62    return 0.0; \
     63  }
     64
    5865#define KJS_CHECKEXCEPTIONLIST \
    5966  if (exec->hadException()) { \
     
    195202    delete newNodes;
    196203    newNodes = 0;
     204}
     205
     206double Node::evaluateToNumber(ExecState* exec)
     207{
     208    JSValue* value = evaluate(exec);
     209    KJS_CHECKEXCEPTIONNUMBER
     210    // No need to check exception after toNumber, caller will do so right after evaluateToNumber() call
     211    return value->toNumber(exec);
    197212}
    198213
     
    361376// ------------------------------ NumberNode -----------------------------------
    362377
    363 JSValue *NumberNode::evaluate(ExecState *)
     378JSValue* NumberNode::evaluate(ExecState*)
    364379{
    365380    // Number nodes are only created when the number can't fit in a JSImmediate, so no need to check again.
    366     return jsNumberCell(val);
     381    return jsNumberCell(m_double);
     382}
     383   
     384double NumberNode::evaluateToNumber(ExecState*)
     385{
     386    return m_double;
    367387}
    368388
     
    378398  return jsOwnedString(value);
    379399}
    380 
     400   
     401double StringNode::evaluateToNumber(ExecState*)
     402{
     403    return value.toDouble();
     404}
     405   
    381406// ------------------------------ RegExpNode -----------------------------------
    382407
     
    434459}
    435460
    436 JSValue* LocalVarAccessNode::evaluate(ExecState* exec)
     461JSValue* LocalVarAccessNode::inlineEvaluate(ExecState* exec)
    437462{
    438463    ASSERT(static_cast<ActivationImp*>(exec->variableObject())->isActivation());
    439464    ASSERT(static_cast<ActivationImp*>(exec->variableObject()) == exec->scopeChain().top());
    440465    return exec->localStorage()[index].value;
     466}
     467
     468JSValue* LocalVarAccessNode::evaluate(ExecState* exec)
     469{
     470    return inlineEvaluate(exec);
     471}
     472
     473double LocalVarAccessNode::evaluateToNumber(ExecState* exec)
     474{
     475    return inlineEvaluate(exec)->toNumber(exec);
    441476}
    442477
     
    572607
    573608// ECMA 11.2.1a
    574 JSValue *BracketAccessorNode::evaluate(ExecState *exec)
    575 {
    576   JSValue *v1 = expr1->evaluate(exec);
    577   KJS_CHECKEXCEPTIONVALUE
    578   JSValue *v2 = expr2->evaluate(exec);
    579   KJS_CHECKEXCEPTIONVALUE
    580   JSObject *o = v1->toObject(exec);
     609JSValue* BracketAccessorNode::inlineEvaluate(ExecState* exec)
     610{
     611  JSValue* v1 = expr1->evaluate(exec);
     612  KJS_CHECKEXCEPTIONVALUE
     613  JSValue* v2 = expr2->evaluate(exec);
     614  KJS_CHECKEXCEPTIONVALUE
     615  JSObject* o = v1->toObject(exec);
    581616  uint32_t i;
    582617  if (v2->getUInt32(i))
    583618    return o->get(exec, i);
    584619  return o->get(exec, Identifier(v2->toString(exec)));
     620}
     621
     622JSValue* BracketAccessorNode::evaluate(ExecState* exec)
     623{
     624    return inlineEvaluate(exec);
     625}
     626
     627double BracketAccessorNode::evaluateToNumber(ExecState* exec)
     628{
     629    return inlineEvaluate(exec)->toNumber(exec);
    585630}
    586631
     
    15801625JSValue *NegateNode::evaluate(ExecState *exec)
    15811626{
    1582   JSValue *v = expr->evaluate(exec);
    1583   KJS_CHECKEXCEPTIONVALUE
    1584 
    1585   double n = v->toNumber(exec);
    1586   return jsNumber(-n);
     1627    // No need to check exception, caller will do so right after evaluate()
     1628    return jsNumber(-expr->evaluateToNumber(exec));
     1629}
     1630
     1631double NegateNode::evaluateToNumber(ExecState* exec)
     1632{
     1633    // No need to check exception, caller will do so right after evaluateToNumber()
     1634    return -expr->evaluateToNumber(exec);
    15871635}
    15881636
     
    16261674
    16271675// ECMA 11.5.1
    1628 JSValue *MultNode::evaluate(ExecState *exec)
    1629 {
    1630     JSValue *v1 = term1->evaluate(exec);
    1631     KJS_CHECKEXCEPTIONVALUE
    1632        
    1633     JSValue *v2 = term2->evaluate(exec);
    1634     KJS_CHECKEXCEPTIONVALUE
    1635 
    1636     return jsNumber(v1->toNumber(exec) * v2->toNumber(exec));
     1676double MultNode::inlineEvaluateToNumber(ExecState* exec)
     1677{
     1678    double n1 = term1->evaluateToNumber(exec);
     1679    KJS_CHECKEXCEPTIONNUMBER
     1680   
     1681    double n2 = term2->evaluateToNumber(exec);
     1682    KJS_CHECKEXCEPTIONNUMBER
     1683   
     1684    return n1 * n2;
     1685}
     1686
     1687JSValue *MultNode::evaluate(ExecState* exec)
     1688{
     1689    return jsNumber(inlineEvaluateToNumber(exec));
     1690}
     1691   
     1692double MultNode::evaluateToNumber(ExecState* exec)
     1693{
     1694    return inlineEvaluateToNumber(exec);
    16371695}
    16381696
     
    16441702
    16451703// ECMA 11.5.2
    1646 JSValue *DivNode::evaluate(ExecState *exec)
    1647 {
    1648     JSValue *v1 = term1->evaluate(exec);
    1649     KJS_CHECKEXCEPTIONVALUE
    1650        
    1651     JSValue *v2 = term2->evaluate(exec);
    1652     KJS_CHECKEXCEPTIONVALUE
    1653 
    1654     return jsNumber(v1->toNumber(exec) / v2->toNumber(exec));
     1704double DivNode::inlineEvaluateToNumber(ExecState* exec)
     1705{
     1706    double n1 = term1->evaluateToNumber(exec);
     1707    KJS_CHECKEXCEPTIONNUMBER
     1708   
     1709    double n2 = term2->evaluateToNumber(exec);
     1710    KJS_CHECKEXCEPTIONNUMBER
     1711   
     1712    return n1 / n2;
     1713}
     1714
     1715JSValue* DivNode::evaluate(ExecState* exec)
     1716{
     1717    return jsNumber(inlineEvaluateToNumber(exec));
     1718}
     1719
     1720double DivNode::evaluateToNumber(ExecState* exec)
     1721{
     1722    return inlineEvaluateToNumber(exec);
    16551723}
    16561724
     
    16621730
    16631731// ECMA 11.5.3
    1664 JSValue *ModNode::evaluate(ExecState *exec)
    1665 {
    1666     JSValue *v1 = term1->evaluate(exec);
    1667     KJS_CHECKEXCEPTIONVALUE
    1668        
    1669     JSValue *v2 = term2->evaluate(exec);
    1670     KJS_CHECKEXCEPTIONVALUE
    1671 
    1672     return jsNumber(fmod(v1->toNumber(exec), v2->toNumber(exec)));
     1732double ModNode::inlineEvaluateToNumber(ExecState* exec)
     1733{
     1734    double n1 = term1->evaluateToNumber(exec);
     1735    KJS_CHECKEXCEPTIONNUMBER
     1736   
     1737    double n2 = term2->evaluateToNumber(exec);
     1738    KJS_CHECKEXCEPTIONNUMBER
     1739   
     1740    return fmod(n1, n2);
     1741}
     1742
     1743JSValue* ModNode::evaluate(ExecState* exec)
     1744{
     1745    return jsNumber(inlineEvaluateToNumber(exec));
     1746}
     1747
     1748double ModNode::evaluateToNumber(ExecState* exec)
     1749{
     1750    return inlineEvaluateToNumber(exec);
    16731751}
    16741752
     
    16811759    return error;
    16821760}
     1761
     1762static double throwOutOfMemoryErrorToNumber(ExecState* exec)
     1763{
     1764    JSObject* error = Error::create(exec, GeneralError, "Out of memory");
     1765    exec->setException(error);
     1766    return 0.0;
     1767}   
    16831768
    16841769// ECMA 11.6
     
    16971782   
    16981783    return jsNumber(p1->toNumber(exec) + p2->toNumber(exec));
     1784}
     1785
     1786static double addSlowCaseToNumber(ExecState* exec, JSValue* v1, JSValue* v2)
     1787{
     1788    // exception for the Date exception in defaultValue()
     1789    JSValue *p1 = v1->toPrimitive(exec, UnspecifiedType);
     1790    JSValue *p2 = v2->toPrimitive(exec, UnspecifiedType);
     1791   
     1792    if (p1->isString() || p2->isString()) {
     1793        UString value = p1->toString(exec) + p2->toString(exec);
     1794        if (value.isNull())
     1795            return throwOutOfMemoryErrorToNumber(exec);
     1796        return value.toDouble();
     1797    }
     1798   
     1799    return p1->toNumber(exec) + p2->toNumber(exec);
    16991800}
    17001801
     
    17171818    if (bothTypes == ((NumberType << 3) | NumberType))
    17181819        return jsNumber(v1->toNumber(exec) + v2->toNumber(exec));
    1719     else if (bothTypes == ((StringType << 3) | StringType)) {
     1820    if (bothTypes == ((StringType << 3) | StringType)) {
    17201821        UString value = static_cast<StringImp*>(v1)->value() + static_cast<StringImp*>(v2)->value();
    17211822        if (value.isNull())
     
    17281829}
    17291830
     1831static inline double addToNumber(ExecState* exec, JSValue* v1, JSValue *v2)
     1832{
     1833    JSType t1 = v1->type();
     1834    JSType t2 = v2->type();
     1835    const unsigned bothTypes = (t1 << 3) | t2;
     1836   
     1837    if (bothTypes == ((NumberType << 3) | NumberType))
     1838        return v1->toNumber(exec) + v2->toNumber(exec);
     1839    if (bothTypes == ((StringType << 3) | StringType)) {
     1840        UString value = static_cast<StringImp*>(v1)->value() + static_cast<StringImp*>(v2)->value();
     1841        if (value.isNull())
     1842            return throwOutOfMemoryErrorToNumber(exec);
     1843        return value.toDouble();
     1844    }
     1845   
     1846    // All other cases are pretty uncommon
     1847    return addSlowCaseToNumber(exec, v1, v2);
     1848}
     1849
    17301850void AddNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
    17311851{
     
    17461866}
    17471867
     1868double AddNode::evaluateToNumber(ExecState* exec)
     1869{
     1870    JSValue *v1 = term1->evaluate(exec);
     1871    KJS_CHECKEXCEPTIONNUMBER
     1872   
     1873    JSValue *v2 = term2->evaluate(exec);
     1874    KJS_CHECKEXCEPTIONNUMBER
     1875   
     1876    return addToNumber(exec, v1, v2);
     1877}
     1878
    17481879void SubNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
    17491880{
     
    17531884
    17541885// ECMA 11.6.2
    1755 JSValue *SubNode::evaluate(ExecState *exec)
    1756 {
    1757     JSValue *v1 = term1->evaluate(exec);
    1758     KJS_CHECKEXCEPTIONVALUE
    1759        
    1760     JSValue *v2 = term2->evaluate(exec);
    1761     KJS_CHECKEXCEPTIONVALUE
    1762        
    1763     return jsNumber(v1->toNumber(exec) - v2->toNumber(exec));
     1886double SubNode::inlineEvaluateToNumber(ExecState* exec)
     1887{
     1888    double n1 = term1->evaluateToNumber(exec);
     1889    KJS_CHECKEXCEPTIONNUMBER
     1890   
     1891    double n2 = term2->evaluateToNumber(exec);
     1892    KJS_CHECKEXCEPTIONNUMBER
     1893   
     1894    return n1 - n2;
     1895}
     1896
     1897JSValue* SubNode::evaluate(ExecState* exec)
     1898{
     1899    return jsNumber(inlineEvaluateToNumber(exec));
     1900}
     1901
     1902double SubNode::evaluateToNumber(ExecState* exec)
     1903{
     1904    return inlineEvaluateToNumber(exec);
    17641905}
    17651906
     
    21562297// ECMA 11.13
    21572298
    2158 static ALWAYS_INLINE JSValue *valueForReadModifyAssignment(ExecState * exec, JSValue *v1, JSValue *v2, Operator oper) KJS_FAST_CALL;
    2159 static ALWAYS_INLINE JSValue *valueForReadModifyAssignment(ExecState * exec, JSValue *v1, JSValue *v2, Operator oper)
     2299static ALWAYS_INLINE JSValue* valueForReadModifyAssignment(ExecState* exec, JSValue* current, Node* right, Operator oper) KJS_FAST_CALL;
     2300static ALWAYS_INLINE JSValue* valueForReadModifyAssignment(ExecState* exec, JSValue* current, Node* right, Operator oper)
    21602301{
    21612302  JSValue *v;
     
    21652306  switch (oper) {
    21662307  case OpMultEq:
    2167     v = jsNumber(v1->toNumber(exec) * v2->toNumber(exec));
     2308    v = jsNumber(current->toNumber(exec) * right->evaluateToNumber(exec));
    21682309    break;
    21692310  case OpDivEq:
    2170     v = jsNumber(v1->toNumber(exec) / v2->toNumber(exec));
     2311    v = jsNumber(current->toNumber(exec) / right->evaluateToNumber(exec));
    21712312    break;
    21722313  case OpPlusEq:
    2173     v = add(exec, v1, v2);
     2314    v = add(exec, current, right->evaluate(exec));
    21742315    break;
    21752316  case OpMinusEq:
    2176     v = jsNumber(v1->toNumber(exec) - v2->toNumber(exec));
     2317    v = jsNumber(current->toNumber(exec) - right->evaluateToNumber(exec));
    21772318    break;
    21782319  case OpLShift:
    2179     i1 = v1->toInt32(exec);
    2180     i2 = v2->toInt32(exec);
     2320    i1 = current->toInt32(exec);
     2321    i2 = right->evaluate(exec)->toInt32(exec);
    21812322    v = jsNumber(i1 << i2);
    21822323    break;
    21832324  case OpRShift:
    2184     i1 = v1->toInt32(exec);
    2185     i2 = v2->toInt32(exec);
     2325    i1 = current->toInt32(exec);
     2326    i2 = right->evaluate(exec)->toInt32(exec);
    21862327    v = jsNumber(i1 >> i2);
    21872328    break;
    21882329  case OpURShift:
    2189     ui = v1->toUInt32(exec);
    2190     i2 = v2->toInt32(exec);
     2330    ui = current->toUInt32(exec);
     2331    i2 = right->evaluate(exec)->toInt32(exec);
    21912332    v = jsNumber(ui >> i2);
    21922333    break;
    21932334  case OpAndEq:
    2194     i1 = v1->toInt32(exec);
    2195     i2 = v2->toInt32(exec);
     2335    i1 = current->toInt32(exec);
     2336    i2 = right->evaluate(exec)->toInt32(exec);
    21962337    v = jsNumber(i1 & i2);
    21972338    break;
    21982339  case OpXOrEq:
    2199     i1 = v1->toInt32(exec);
    2200     i2 = v2->toInt32(exec);
     2340    i1 = current->toInt32(exec);
     2341    i2 = right->evaluate(exec)->toInt32(exec);
    22012342    v = jsNumber(i1 ^ i2);
    22022343    break;
    22032344  case OpOrEq:
    2204     i1 = v1->toInt32(exec);
    2205     i2 = v2->toInt32(exec);
     2345    i1 = current->toInt32(exec);
     2346    i2 = right->evaluate(exec)->toInt32(exec);
    22062347    v = jsNumber(i1 | i2);
    22072348    break;
    22082349  case OpModEq: {
    2209     double d1 = v1->toNumber(exec);
    2210     double d2 = v2->toNumber(exec);
     2350    double d1 = current->toNumber(exec);
     2351    double d2 = right->evaluateToNumber(exec);
    22112352    v = jsNumber(fmod(d1, d2));
    22122353  }
    22132354    break;
    22142355  default:
    2215     ASSERT(0);
     2356    ASSERT_NOT_REACHED();
    22162357    v = jsUndefined();
    22172358  }
     
    22452386
    22462387    ASSERT(m_oper != OpEqual);
    2247     JSValue* v2 = m_right->evaluate(exec);
    2248     JSValue* v = valueForReadModifyAssignment(exec, *slot, v2, m_oper);
     2388    JSValue* v = valueForReadModifyAssignment(exec, *slot, m_right.get(), m_oper);
    22492389
    22502390    KJS_CHECKEXCEPTIONVALUE
     
    22962436  JSValue *v1 = slot.getValue(exec, base, m_ident);
    22972437  KJS_CHECKEXCEPTIONVALUE
    2298   JSValue *v2 = m_right->evaluate(exec);
    2299   v = valueForReadModifyAssignment(exec, v1, v2, m_oper);
     2438  v = valueForReadModifyAssignment(exec, v1, m_right.get(), m_oper);
    23002439
    23012440  KJS_CHECKEXCEPTIONVALUE
     
    23732512  JSValue *v1 = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
    23742513  KJS_CHECKEXCEPTIONVALUE
    2375   JSValue *v2 = m_right->evaluate(exec);
    2376   v = valueForReadModifyAssignment(exec, v1, v2, m_oper);
     2514  v = valueForReadModifyAssignment(exec, v1, m_right.get(), m_oper);
    23772515
    23782516  KJS_CHECKEXCEPTIONVALUE
     
    24482586    JSValue *v1 = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
    24492587    KJS_CHECKEXCEPTIONVALUE
    2450     JSValue *v2 = m_right->evaluate(exec);
    2451     v = valueForReadModifyAssignment(exec, v1, v2, m_oper);
     2588    v = valueForReadModifyAssignment(exec, v1, m_right.get(), m_oper);
    24522589
    24532590    KJS_CHECKEXCEPTIONVALUE
     
    24642601  JSValue *v1 = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
    24652602  KJS_CHECKEXCEPTIONVALUE
    2466   JSValue *v2 = m_right->evaluate(exec);
    2467   v = valueForReadModifyAssignment(exec, v1, v2, m_oper);
     2603  v = valueForReadModifyAssignment(exec, v1, m_right.get(), m_oper);
    24682604
    24692605  KJS_CHECKEXCEPTIONVALUE
  • trunk/JavaScriptCore/kjs/nodes.h

    r27501 r27589  
    66 *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
    77 *  Copyright (C) 2007 Maks Orlovich
     8 *  Copyright (C) 2007 Eric Seidel <eric@webkit.org>
    89 *
    910 *  This library is free software; you can redistribute it and/or
     
    117118    virtual ~Node();
    118119
    119     virtual JSValue *evaluate(ExecState *exec) KJS_FAST_CALL = 0;
     120    virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL = 0;
     121    virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
    120122    UString toString() const KJS_FAST_CALL;
    121123    int lineNo() const KJS_FAST_CALL { return m_line; }
     
    126128
    127129    virtual bool isNumber() const KJS_FAST_CALL { return false; }
    128     virtual bool isImmediateValue() const KJS_FAST_CALL { return false; }
    129130    virtual bool isLocation() const KJS_FAST_CALL { return false; }
    130131    virtual bool isResolveNode() const KJS_FAST_CALL { return false; }
     
    210211  class NumberNode : public Node {
    211212  public:
    212     NumberNode(double v) KJS_FAST_CALL : val(v) {}
    213     JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     213    NumberNode(double v) KJS_FAST_CALL : m_double(v) {}
     214    virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     215    virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
    214216    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
    215217    virtual Precedence precedence() const { return PrecPrimary; }
    216218
    217219    virtual bool isNumber() const KJS_FAST_CALL { return true; }
    218     double value() const KJS_FAST_CALL { return val; }
    219     void setValue(double v) KJS_FAST_CALL { val = v; }
    220   private:
    221     double val;
     220    double value() const KJS_FAST_CALL { return m_double; }
     221    virtual void setValue(double d) KJS_FAST_CALL { m_double = d; }
     222  protected:
     223    double m_double;
    222224  };
    223225 
    224   class ImmediateNumberNode : public Node {
    225   public:
    226       ImmediateNumberNode(JSValue* v) KJS_FAST_CALL : m_value(v) {}
    227       JSValue* evaluate(ExecState*) KJS_FAST_CALL;
    228       virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
    229       virtual Precedence precedence() const { return PrecPrimary; }
     226  class ImmediateNumberNode : public NumberNode {
     227  public:
     228      ImmediateNumberNode(JSValue* v, double d) KJS_FAST_CALL : NumberNode(d), m_value(v) { ASSERT(v == JSImmediate::fromDouble(d)); }
     229      virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
    230230     
    231       virtual bool isImmediateValue() const KJS_FAST_CALL { return true; }
    232       double value() const KJS_FAST_CALL { return JSImmediate::toDouble(m_value); }
    233       void setValue(double v) KJS_FAST_CALL { m_value = JSImmediate::fromDouble(v); ASSERT(m_value); }
     231      virtual void setValue(double d) KJS_FAST_CALL { m_double = d; m_value = JSImmediate::fromDouble(d); ASSERT(m_value); }
    234232  private:
    235233      JSValue* m_value;
     
    239237  public:
    240238    StringNode(const UString *v) KJS_FAST_CALL { value = *v; }
    241     JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     239    virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     240    virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
    242241    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
    243242    virtual Precedence precedence() const { return PrecPrimary; }
     
    304303    }
    305304    virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     305    virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
     306  private:
     307    ALWAYS_INLINE JSValue* inlineEvaluate(ExecState*);
    306308  };
    307309
     
    390392    BracketAccessorNode(Node *e1, Node *e2) KJS_FAST_CALL : expr1(e1), expr2(e2) {}
    391393    virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
    392     JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     394    virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     395    virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
    393396    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
    394397    virtual Precedence precedence() const { return PrecMember; }
     
    400403
    401404  private:
     405    ALWAYS_INLINE JSValue* inlineEvaluate(ExecState*);
    402406    RefPtr<Node> expr1;
    403407    RefPtr<Node> expr2;
     
    950954    NegateNode(Node *e) KJS_FAST_CALL : expr(e) {}
    951955    virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
    952     JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     956    virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     957    virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
    953958    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
    954959    virtual Precedence precedence() const { return PrecUnary; }
     
    983988      MultNode(Node *t1, Node *t2) KJS_FAST_CALL : term1(t1), term2(t2) {}
    984989      virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
    985       JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     990      virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     991      virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
    986992      virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
    987993      virtual Precedence precedence() const { return PrecMultiplicitave; }
    988994  private:
     995      ALWAYS_INLINE double inlineEvaluateToNumber(ExecState*);
    989996      RefPtr<Node> term1;
    990997      RefPtr<Node> term2;
     
    9951002      DivNode(Node *t1, Node *t2) KJS_FAST_CALL : term1(t1), term2(t2) {}
    9961003      virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
    997       JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     1004      virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     1005      virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
    9981006      virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
    9991007      virtual Precedence precedence() const { return PrecMultiplicitave; }
    10001008  private:
     1009      ALWAYS_INLINE double inlineEvaluateToNumber(ExecState*);
    10011010      RefPtr<Node> term1;
    10021011      RefPtr<Node> term2;
     
    10071016      ModNode(Node *t1, Node *t2) KJS_FAST_CALL : term1(t1), term2(t2) {}
    10081017      virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
    1009       JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     1018      virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     1019      virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
    10101020      virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
    10111021      virtual Precedence precedence() const { return PrecMultiplicitave; }
    10121022  private:
     1023      ALWAYS_INLINE double inlineEvaluateToNumber(ExecState*);
    10131024      RefPtr<Node> term1;
    10141025      RefPtr<Node> term2;
     
    10191030    AddNode(Node *t1, Node *t2) KJS_FAST_CALL : term1(t1), term2(t2) {}
    10201031    virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
    1021     JSValue* evaluate(ExecState*) KJS_FAST_CALL;
    1022     virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
    1023       virtual Precedence precedence() const { return PrecAdditive; }
     1032    virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     1033    virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
     1034    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
     1035    virtual Precedence precedence() const { return PrecAdditive; }
    10241036  private:
    10251037    RefPtr<Node> term1;
     
    10311043      SubNode(Node *t1, Node *t2) KJS_FAST_CALL : term1(t1), term2(t2) {}
    10321044      virtual void optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack&) KJS_FAST_CALL;
    1033       JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     1045      virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
     1046      virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
    10341047      virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
    10351048      virtual Precedence precedence() const { return PrecAdditive; }
    10361049  private:
     1050      ALWAYS_INLINE double inlineEvaluateToNumber(ExecState*);
    10371051      RefPtr<Node> term1;
    10381052      RefPtr<Node> term2;
  • trunk/JavaScriptCore/kjs/nodes2string.cpp

    r27410 r27589  
    22 *  Copyright (C) 2002 Harri Porten (porten@kde.org)
    33 *  Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
     4 *  Copyright (C) 2007 Eric Seidel <eric@webkit.org>
    45 *
    56 *  This library is free software; you can redistribute it and/or
     
    275276void NumberNode::streamTo(SourceStream& s) const
    276277{
    277     s << val;
    278 }
    279 
    280 void ImmediateNumberNode::streamTo(SourceStream& s) const
    281 {
    282278    s << value();
    283279}
Note: See TracChangeset for help on using the changeset viewer.