Changeset 10621 in webkit for trunk/JavaScriptCore/kjs/nodes.cpp


Ignore:
Timestamp:
Sep 24, 2005, 3:34:15 PM (20 years ago)
Author:
mjs
Message:

Reviewed by Darin.

<rdar://problem/4260479> Finish deploying PropertySlot in the interpreter
http://bugzilla.opendarwin.org/show_bug.cgi?id=5112

Convert postfix, prefix, delete, prefix, and for..in expressions to use
PropertySlot-based lookup instead of evaluateReference.

3% speedup on JS iBench.

Fixed two of the JS tests:

  • tests/mozilla/expected.html:
  • kjs/grammar.y:
  • kjs/nodes.cpp: (PostfixResolveNode::evaluate): (PostfixBracketNode::evaluate): (PostfixDotNode::evaluate): (DeleteResolveNode::evaluate): (DeleteBracketNode::evaluate): (DeleteDotNode::evaluate): (DeleteValueNode::evaluate): (typeStringForValue): (TypeOfResolveNode::evaluate): (TypeOfValueNode::evaluate): (PrefixResolveNode::evaluate): (PrefixBracketNode::evaluate): (PrefixDotNode::evaluate): (ForInNode::execute):
  • kjs/nodes.h: (KJS::PostfixResolveNode::PostfixResolveNode): (KJS::PostfixBracketNode::PostfixBracketNode): (KJS::PostfixDotNode::PostfixDotNode): (KJS::DeleteResolveNode::DeleteResolveNode): (KJS::DeleteBracketNode::DeleteBracketNode): (KJS::DeleteDotNode::DeleteDotNode): (KJS::DeleteValueNode::DeleteValueNode): (KJS::TypeOfResolveNode::TypeOfResolveNode): (KJS::TypeOfValueNode::TypeOfValueNode): (KJS::PrefixResolveNode::PrefixResolveNode): (KJS::PrefixBracketNode::PrefixBracketNode): (KJS::PrefixDotNode::PrefixDotNode):
  • kjs/nodes2string.cpp: (PostfixResolveNode::streamTo): (PostfixBracketNode::streamTo): (PostfixDotNode::streamTo): (DeleteResolveNode::streamTo): (DeleteBracketNode::streamTo): (DeleteDotNode::streamTo): (DeleteValueNode::streamTo): (TypeOfValueNode::streamTo): (TypeOfResolveNode::streamTo): (PrefixResolveNode::streamTo): (PrefixBracketNode::streamTo): (PrefixDotNode::streamTo):
  • kjs/reference.cpp: (KJS::Reference::Reference): (KJS::Reference::getPropertyName): (KJS::Reference::getValue): (KJS::Reference::deleteValue):
  • kjs/reference.h:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/kjs/nodes.cpp

    r10496 r10621  
    7373    return Undefined(); // will be picked up by KJS_CHECKEXCEPTION
    7474
    75 #define KJS_CHECKEXCEPTIONREFERENCE \
    76   if (exec->hadException()) { \
    77     setExceptionDetailsIfNeeded(exec); \
    78     return Reference::makeValueReference(Undefined()); \
    79   } \
    80   if (Collector::outOfMemory()) \
    81     return Reference::makeValueReference(Undefined()); // will be picked up by KJS_CHECKEXCEPTION
    82 
    8375#define KJS_CHECKEXCEPTIONLIST \
    8476  if (exec->hadException()) { \
     
    10597Node::~Node()
    10698{
    107 }
    108 
    109 Reference Node::evaluateReference(ExecState *exec)
    110 {
    111   ValueImp *v = evaluate(exec);
    112   KJS_CHECKEXCEPTIONREFERENCE
    113   return Reference::makeValueReference(v);
    11499}
    115100
     
    307292}
    308293
    309 Reference ResolveNode::evaluateReference(ExecState *exec)
    310 {
    311   const ScopeChain& chain = exec->context().imp()->scopeChain();
    312   ScopeChainIterator iter = chain.begin();
    313   ScopeChainIterator end = chain.end();
    314  
    315   // we must always have something in the scope chain
    316   assert(iter != end);
    317 
    318   PropertySlot slot;
    319   do {
    320     ObjectImp *o = *iter;
    321     if (o->getPropertySlot(exec, ident, slot))
    322       return Reference(o, ident);
    323    
    324     ++iter;
    325   } while (iter != end);
    326 
    327   return Reference(ident);
    328 }
    329 
    330294// ------------------------------ GroupNode ------------------------------------
    331295
     
    334298{
    335299  return group->evaluate(exec);
    336 }
    337 
    338 Reference GroupNode::evaluateReference(ExecState *exec)
    339 {
    340   return group->evaluateReference(exec);
    341300}
    342301
     
    443402}
    444403
    445 Reference BracketAccessorNode::evaluateReference(ExecState *exec)
    446 {
    447   ValueImp *v1 = expr1->evaluate(exec);
    448   KJS_CHECKEXCEPTIONREFERENCE
    449   ValueImp *v2 = expr2->evaluate(exec);
    450   KJS_CHECKEXCEPTIONREFERENCE
    451   ObjectImp *o = v1->toObject(exec);
    452   uint32_t i;
    453   if (v2->getUInt32(i))
    454     return Reference(o, i);
    455   return Reference(o, Identifier(v2->toString(exec)));
    456 }
    457 
    458404// ------------------------------ DotAccessorNode --------------------------------
    459405
     
    465411  return v->toObject(exec)->get(exec, ident);
    466412
    467 }
    468 
    469 Reference DotAccessorNode::evaluateReference(ExecState *exec)
    470 {
    471   ValueImp *v = expr->evaluate(exec);
    472   KJS_CHECKEXCEPTIONREFERENCE
    473   ObjectImp *o = v->toObject(exec);
    474   return Reference(o, ident);
    475413}
    476414
     
    702640}
    703641
    704 // ------------------------------ PostfixNode ----------------------------------
    705 
    706642// ECMA 11.3
    707 ValueImp *PostfixNode::evaluate(ExecState *exec)
    708 {
    709   Reference ref = expr->evaluateReference(exec);
    710   KJS_CHECKEXCEPTIONVALUE
    711   ValueImp *v = ref.getValue(exec);
     643
     644// ------------------------------ PostfixResolveNode ----------------------------------
     645
     646ValueImp *PostfixResolveNode::evaluate(ExecState *exec)
     647{
     648  const ScopeChain& chain = exec->context().imp()->scopeChain();
     649  ScopeChainIterator iter = chain.begin();
     650  ScopeChainIterator end = chain.end();
     651 
     652  // we must always have something in the scope chain
     653  assert(iter != end);
     654
     655  PropertySlot slot;
     656  ObjectImp *base;
     657  do {
     658    base = *iter;
     659    if (base->getPropertySlot(exec, m_ident, slot)) {
     660        ValueImp *v = slot.getValue(exec, m_ident);
     661
     662        bool knownToBeInteger;
     663        double n = v->toNumber(exec, knownToBeInteger);
     664       
     665        double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
     666        base->put(exec, m_ident, jsNumber(newValue, knownToBeInteger));
     667       
     668        return jsNumber(n, knownToBeInteger);
     669    }
     670
     671    ++iter;
     672  } while (iter != end);
     673
     674  return undefinedVariableError(exec, m_ident);
     675}
     676
     677// ------------------------------ PostfixBracketNode ----------------------------------
     678
     679ValueImp *PostfixBracketNode::evaluate(ExecState *exec)
     680{
     681  ValueImp *baseValue = m_base->evaluate(exec);
     682  KJS_CHECKEXCEPTIONVALUE
     683  ValueImp *subscript = m_subscript->evaluate(exec);
     684  KJS_CHECKEXCEPTIONVALUE
     685
     686  ObjectImp *base = baseValue->toObject(exec);
     687
     688  uint32_t propertyIndex;
     689  if (subscript->getUInt32(propertyIndex)) {
     690    PropertySlot slot;
     691    ValueImp *v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, propertyIndex) : Undefined();
     692    KJS_CHECKEXCEPTIONVALUE
     693
     694    bool knownToBeInteger;
     695    double n = v->toNumber(exec, knownToBeInteger);
     696
     697    double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
     698    base->put(exec, propertyIndex, jsNumber(newValue, knownToBeInteger));
     699       
     700    return jsNumber(n, knownToBeInteger);
     701  }
     702
     703  Identifier propertyName(subscript->toString(exec));
     704  PropertySlot slot;
     705  ValueImp *v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, propertyName) : Undefined();
     706  KJS_CHECKEXCEPTIONVALUE
    712707
    713708  bool knownToBeInteger;
    714709  double n = v->toNumber(exec, knownToBeInteger);
    715 
    716   double newValue = (oper == OpPlusPlus) ? n + 1 : n - 1;
    717   ref.putValue(exec, jsNumber(newValue, knownToBeInteger));
    718 
     710 
     711  double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
     712  base->put(exec, propertyName, jsNumber(newValue, knownToBeInteger));
     713       
    719714  return jsNumber(n, knownToBeInteger);
    720715}
    721716
    722 // ------------------------------ DeleteNode -----------------------------------
     717// ------------------------------ PostfixDotNode ----------------------------------
     718
     719ValueImp *PostfixDotNode::evaluate(ExecState *exec)
     720{
     721  ValueImp *baseValue = m_base->evaluate(exec);
     722  KJS_CHECKEXCEPTIONVALUE
     723  ObjectImp *base = baseValue->toObject(exec);
     724
     725  PropertySlot slot;
     726  ValueImp *v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, m_ident) : Undefined();
     727  KJS_CHECKEXCEPTIONVALUE
     728
     729  bool knownToBeInteger;
     730  double n = v->toNumber(exec, knownToBeInteger);
     731 
     732  double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
     733  base->put(exec, m_ident, jsNumber(newValue, knownToBeInteger));
     734       
     735  return jsNumber(n, knownToBeInteger);
     736}
    723737
    724738// ECMA 11.4.1
    725 ValueImp *DeleteNode::evaluate(ExecState *exec)
    726 {
    727   Reference ref = expr->evaluateReference(exec);
    728   KJS_CHECKEXCEPTIONVALUE
    729   return jsBoolean(ref.deleteValue(exec));
     739
     740// ------------------------------ DeleteResolveNode -----------------------------------
     741ValueImp *DeleteResolveNode::evaluate(ExecState *exec)
     742{
     743  const ScopeChain& chain = exec->context().imp()->scopeChain();
     744  ScopeChainIterator iter = chain.begin();
     745  ScopeChainIterator end = chain.end();
     746 
     747  // we must always have something in the scope chain
     748  assert(iter != end);
     749
     750  PropertySlot slot;
     751  ObjectImp *base;
     752  do {
     753    base = *iter;
     754    if (base->getPropertySlot(exec, m_ident, slot)) {
     755        return jsBoolean(base->deleteProperty(exec, m_ident));
     756    }
     757
     758    ++iter;
     759  } while (iter != end);
     760
     761  return jsBoolean(true);
     762}
     763
     764// ------------------------------ DeleteBracketNode -----------------------------------
     765ValueImp *DeleteBracketNode::evaluate(ExecState *exec)
     766{
     767  ValueImp *baseValue = m_base->evaluate(exec);
     768  KJS_CHECKEXCEPTIONVALUE
     769  ValueImp *subscript = m_subscript->evaluate(exec);
     770  KJS_CHECKEXCEPTIONVALUE
     771
     772  ObjectImp *base = baseValue->toObject(exec);
     773
     774  uint32_t propertyIndex;
     775  if (subscript->getUInt32(propertyIndex))
     776      return jsBoolean(base->deleteProperty(exec, propertyIndex));
     777
     778  Identifier propertyName(subscript->toString(exec));
     779  return jsBoolean(base->deleteProperty(exec, propertyName));
     780}
     781
     782// ------------------------------ DeleteDotNode -----------------------------------
     783ValueImp *DeleteDotNode::evaluate(ExecState *exec)
     784{
     785  ValueImp *baseValue = m_base->evaluate(exec);
     786  ObjectImp *base = baseValue->toObject(exec);
     787  KJS_CHECKEXCEPTIONVALUE
     788
     789  return jsBoolean(base->deleteProperty(exec, m_ident));
     790}
     791
     792// ------------------------------ DeleteValueNode -----------------------------------
     793ValueImp *DeleteValueNode::evaluate(ExecState *exec)
     794{
     795  m_expr->evaluate(exec);
     796  KJS_CHECKEXCEPTIONVALUE
     797
     798  // delete on a non-location expression ignores the value and returns true
     799  return jsBoolean(true);
    730800}
    731801
     
    741811}
    742812
    743 // ------------------------------ TypeOfNode -----------------------------------
    744 
    745813// ECMA 11.4.3
    746 ValueImp *TypeOfNode::evaluate(ExecState *exec)
    747 {
    748   const char *s = 0L;
    749   Reference ref = expr->evaluateReference(exec);
    750   KJS_CHECKEXCEPTIONVALUE
    751   ValueImp *b = ref.baseIfMutable();
    752   if (b && b->isNull())
    753     return jsString("undefined");
    754   ValueImp *v = ref.getValue(exec);
    755   switch (v->type())
    756     {
     814
     815// ------------------------------ TypeOfValueNode -----------------------------------
     816
     817static ValueImp *typeStringForValue(ValueImp *v)
     818{
     819    switch (v->type()) {
    757820    case UndefinedType:
    758       s = "undefined";
    759       break;
     821        return jsString("undefined");
    760822    case NullType:
    761       s = "object";
    762       break;
     823        return jsString("object");
    763824    case BooleanType:
    764       s = "boolean";
    765       break;
     825        return jsString("boolean");
    766826    case NumberType:
    767       s = "number";
    768       break;
     827        return jsString("number");
    769828    case StringType:
    770       s = "string";
    771       break;
     829        return jsString("string");
    772830    default:
    773       if (v->isObject() && static_cast<ObjectImp*>(v)->implementsCall())
    774         s = "function";
    775       else
    776         s = "object";
    777       break;
     831        if (v->isObject() && static_cast<ObjectImp*>(v)->implementsCall())
     832            return jsString("function");
     833        else
     834            return jsString("object");
    778835    }
    779 
    780   return jsString(s);
    781 }
    782 
    783 // ------------------------------ PrefixNode -----------------------------------
     836}
     837
     838ValueImp *TypeOfResolveNode::evaluate(ExecState *exec)
     839{
     840  const ScopeChain& chain = exec->context().imp()->scopeChain();
     841  ScopeChainIterator iter = chain.begin();
     842  ScopeChainIterator end = chain.end();
     843 
     844  // we must always have something in the scope chain
     845  assert(iter != end);
     846
     847  PropertySlot slot;
     848  ObjectImp *base;
     849  do {
     850    base = *iter;
     851    if (base->getPropertySlot(exec, m_ident, slot)) {
     852        ValueImp *v = slot.getValue(exec, m_ident);
     853        return typeStringForValue(v);
     854    }
     855
     856    ++iter;
     857  } while (iter != end);
     858
     859  return jsString("undefined");
     860}
     861
     862// ------------------------------ TypeOfValueNode -----------------------------------
     863
     864ValueImp *TypeOfValueNode::evaluate(ExecState *exec)
     865{
     866  ValueImp *v = m_expr->evaluate(exec);
     867  KJS_CHECKEXCEPTIONVALUE
     868
     869  return typeStringForValue(v);
     870}
    784871
    785872// ECMA 11.4.4 and 11.4.5
    786 ValueImp *PrefixNode::evaluate(ExecState *exec)
    787 {
    788   Reference ref = expr->evaluateReference(exec);
    789   KJS_CHECKEXCEPTIONVALUE
    790   ValueImp *v = ref.getValue(exec);
     873
     874// ------------------------------ PrefixResolveNode ----------------------------------
     875
     876ValueImp *PrefixResolveNode::evaluate(ExecState *exec)
     877{
     878  const ScopeChain& chain = exec->context().imp()->scopeChain();
     879  ScopeChainIterator iter = chain.begin();
     880  ScopeChainIterator end = chain.end();
     881 
     882  // we must always have something in the scope chain
     883  assert(iter != end);
     884
     885  PropertySlot slot;
     886  ObjectImp *base;
     887  do {
     888    base = *iter;
     889    if (base->getPropertySlot(exec, m_ident, slot)) {
     890        ValueImp *v = slot.getValue(exec, m_ident);
     891
     892        bool knownToBeInteger;
     893        double n = v->toNumber(exec, knownToBeInteger);
     894       
     895        double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
     896        ValueImp *n2 = jsNumber(newValue, knownToBeInteger);
     897        base->put(exec, m_ident, n2);
     898
     899        return n2;
     900    }
     901
     902    ++iter;
     903  } while (iter != end);
     904
     905  return undefinedVariableError(exec, m_ident);
     906}
     907
     908// ------------------------------ PrefixBracketNode ----------------------------------
     909
     910ValueImp *PrefixBracketNode::evaluate(ExecState *exec)
     911{
     912  ValueImp *baseValue = m_base->evaluate(exec);
     913  KJS_CHECKEXCEPTIONVALUE
     914  ValueImp *subscript = m_subscript->evaluate(exec);
     915  KJS_CHECKEXCEPTIONVALUE
     916
     917  ObjectImp *base = baseValue->toObject(exec);
     918
     919  uint32_t propertyIndex;
     920  if (subscript->getUInt32(propertyIndex)) {
     921    PropertySlot slot;
     922    ValueImp *v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, propertyIndex) : Undefined();
     923    KJS_CHECKEXCEPTIONVALUE
     924
     925    bool knownToBeInteger;
     926    double n = v->toNumber(exec, knownToBeInteger);
     927
     928    double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
     929    ValueImp *n2 = jsNumber(newValue, knownToBeInteger);
     930    base->put(exec, propertyIndex, n2);
     931
     932    return n2;
     933  }
     934
     935  Identifier propertyName(subscript->toString(exec));
     936  PropertySlot slot;
     937  ValueImp *v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, propertyName) : Undefined();
     938  KJS_CHECKEXCEPTIONVALUE
    791939
    792940  bool knownToBeInteger;
    793941  double n = v->toNumber(exec, knownToBeInteger);
    794 
    795   double newValue = (oper == OpPlusPlus) ? n + 1 : n - 1;
     942 
     943  double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
    796944  ValueImp *n2 = jsNumber(newValue, knownToBeInteger);
    797 
    798   ref.putValue(exec, n2);
     945  base->put(exec, propertyName, n2);
     946
     947  return n2;
     948}
     949
     950// ------------------------------ PrefixDotNode ----------------------------------
     951
     952ValueImp *PrefixDotNode::evaluate(ExecState *exec)
     953{
     954  ValueImp *baseValue = m_base->evaluate(exec);
     955  KJS_CHECKEXCEPTIONVALUE
     956  ObjectImp *base = baseValue->toObject(exec);
     957
     958  PropertySlot slot;
     959  ValueImp *v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, m_ident) : Undefined();
     960  KJS_CHECKEXCEPTIONVALUE
     961
     962  bool knownToBeInteger;
     963  double n = v->toNumber(exec, knownToBeInteger);
     964 
     965  double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
     966  ValueImp *n2 = jsNumber(newValue, knownToBeInteger);
     967  base->put(exec, m_ident, n2);
    799968
    800969  return n2;
     
    16231792  ReferenceList propList;
    16241793
    1625   if ( varDecl ) {
     1794  if (varDecl) {
    16261795    varDecl->evaluate(exec);
    16271796    KJS_CHECKEXCEPTION
     
    16461815  while (propIt != propList.end()) {
    16471816    Identifier name = propIt->getPropertyName(exec);
    1648     if (!v->hasProperty(exec,name)) {
     1817    if (!v->hasProperty(exec, name)) {
    16491818      propIt++;
    16501819      continue;
    16511820    }
    16521821
    1653     Reference ref = lexpr->evaluateReference(exec);
     1822    ValueImp *str = jsString(name.ustring());
     1823
     1824    if (lexpr->isResolveNode()) {
     1825        const Identifier &ident = static_cast<ResolveNode *>(lexpr.get())->identifier();
     1826
     1827        const ScopeChain& chain = exec->context().imp()->scopeChain();
     1828        ScopeChainIterator iter = chain.begin();
     1829        ScopeChainIterator end = chain.end();
     1830 
     1831        // we must always have something in the scope chain
     1832        assert(iter != end);
     1833
     1834        PropertySlot slot;
     1835        ObjectImp *o;
     1836        do {
     1837            o = *iter;
     1838            if (o->getPropertySlot(exec, ident, slot))
     1839                o->put(exec, ident, str);
     1840           
     1841            ++iter;
     1842        } while (iter != end);
     1843       
     1844        if (iter == end)
     1845            o->put(exec, ident, str);
     1846    } else if (lexpr->isDotAccessorNode()) {
     1847        const Identifier& ident = static_cast<DotAccessorNode *>(lexpr.get())->identifier();
     1848        ValueImp *v = static_cast<DotAccessorNode *>(lexpr.get())->base()->evaluate(exec);
     1849        KJS_CHECKEXCEPTION
     1850        ObjectImp *o = v->toObject(exec);
     1851
     1852        o->put(exec, ident, str);
     1853    } else {
     1854        assert(lexpr->isBracketAccessorNode());
     1855        ValueImp *v = static_cast<BracketAccessorNode *>(lexpr.get())->base()->evaluate(exec);
     1856        KJS_CHECKEXCEPTION
     1857        ValueImp *v2 = static_cast<BracketAccessorNode *>(lexpr.get())->subscript()->evaluate(exec);
     1858        KJS_CHECKEXCEPTION
     1859        ObjectImp *o = v->toObject(exec);
     1860
     1861        uint32_t i;
     1862        if (v2->getUInt32(i))
     1863            o->put(exec, i, str);
     1864        o->put(exec, Identifier(v2->toString(exec)), str);
     1865    }
     1866
    16541867    KJS_CHECKEXCEPTION
    1655     ref.putValue(exec, String(name.ustring()));
    16561868
    16571869    exec->context().imp()->seenLabels()->pushIteration();
Note: See TracChangeset for help on using the changeset viewer.