Changeset 10621 in webkit for trunk/JavaScriptCore/kjs


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:
Location:
trunk/JavaScriptCore/kjs
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/kjs/grammar.y

    r10588 r10621  
    5050using namespace KJS;
    5151
     52static bool makeAssignNode(Node*& result, Node *loc, Operator op, Node *expr);
     53static bool makePrefixNode(Node*& result, Node *expr, Operator op);
     54static bool makePostfixNode(Node*& result, Node *expr, Operator op);
    5255static Node *makeFunctionCallNode(Node *func, ArgumentsNode *args);
     56static Node *makeTypeOfNode(Node *expr);
     57static Node *makeDeleteNode(Node *expr);
    5358
    5459%}
     
    166171%type <plist> PropertyNameAndValueList
    167172%type <pnode> PropertyName
    168 %type <ident> ParenthesizedIdent
    169173
    170174%%
     
    185189;
    186190
    187 ParenthesizedIdent:
    188     IDENT
    189   | '(' ParenthesizedIdent ')' { $$ = $2; }
    190 ;
    191 
    192191PrimaryExpr:
    193192    THIS                           { $$ = new ThisNode(); }
    194193  | Literal
    195194  | ArrayLiteral
    196   | ParenthesizedIdent             { $$ = new ResolveNode(*$1); }
    197   | '(' Expr ')'                   { $$ = new GroupNode($2); }
     195  | IDENT                          { $$ = new ResolveNode(*$1); }
     196  | '(' Expr ')'                   { if ($2->isResolveNode()) $$ = $2; else $$ = new GroupNode($2); }
    198197  | '{' '}'                        { $$ = new ObjectLiteralNode(); }
    199198  | '{' PropertyNameAndValueList '}'   { $$ = new ObjectLiteralNode($2); }
     
    271270PostfixExpr:    /* TODO: no line terminator here */
    272271    LeftHandSideExpr
    273   | LeftHandSideExpr PLUSPLUS      { $$ = new PostfixNode($1, OpPlusPlus); }
    274   | LeftHandSideExpr MINUSMINUS    { $$ = new PostfixNode($1, OpMinusMinus); }
     272  | LeftHandSideExpr PLUSPLUS      { if (!makePostfixNode($$, $1, OpPlusPlus)) YYABORT; }
     273  | LeftHandSideExpr MINUSMINUS    { if (!makePostfixNode($$, $1, OpMinusMinus)) YYABORT; }
    275274;
    276275
    277276UnaryExpr:
    278277    PostfixExpr
    279   | DELETE UnaryExpr               { $$ = new DeleteNode($2); }
     278  | DELETE UnaryExpr               { $$ = makeDeleteNode($2); }
    280279  | VOID UnaryExpr                 { $$ = new VoidNode($2); }
    281   | TYPEOF UnaryExpr               { $$ = new TypeOfNode($2); }
    282   | PLUSPLUS UnaryExpr             { $$ = new PrefixNode(OpPlusPlus, $2); }
    283   | AUTOPLUSPLUS UnaryExpr         { $$ = new PrefixNode(OpPlusPlus, $2); }
    284   | MINUSMINUS UnaryExpr           { $$ = new PrefixNode(OpMinusMinus, $2); }
    285   | AUTOMINUSMINUS UnaryExpr       { $$ = new PrefixNode(OpMinusMinus, $2); }
     280  | TYPEOF UnaryExpr               { $$ = makeTypeOfNode($2); }
     281  | PLUSPLUS UnaryExpr             { if (!makePrefixNode($$, $2, OpPlusPlus)) YYABORT; }
     282  | AUTOPLUSPLUS UnaryExpr         { if (!makePrefixNode($$, $2, OpPlusPlus)) YYABORT; }
     283  | MINUSMINUS UnaryExpr           { if (!makePrefixNode($$, $2, OpMinusMinus)) YYABORT; }
     284  | AUTOMINUSMINUS UnaryExpr       { if (!makePrefixNode($$, $2, OpMinusMinus)) YYABORT; }
    286285  | '+' UnaryExpr                  { $$ = new UnaryPlusNode($2); }
    287286  | '-' UnaryExpr                  { $$ = new NegateNode($2); }
     
    370369    ConditionalExpr
    371370  | LeftHandSideExpr AssignmentOperator AssignmentExpr
    372                            {
    373                                Node *n = $1;
    374                                bool paren = n->isGroupNode();
    375                                if (paren)
    376                                    n = static_cast<GroupNode *>(n)->nodeInsideAllParens();
    377 
    378                                if (!n->isLocation())
    379                                    YYABORT;
    380                                else if (n->isResolveNode()) {
    381                                    ResolveNode *resolve = static_cast<ResolveNode *>(n);
    382                                    $$ = new AssignResolveNode(resolve->identifier(), $2, $3);
    383                                } else if (n->isBracketAccessorNode()) {
    384                                    BracketAccessorNode *bracket = static_cast<BracketAccessorNode *>(n);
    385                                    $$ = new AssignBracketNode(bracket->base(), bracket->subscript(), $2, $3);
    386                                } else {
    387                                    assert(n->isDotAccessorNode());
    388                                    DotAccessorNode *dot = static_cast<DotAccessorNode *>(n);
    389                                    $$ = new AssignDotNode(dot->base(), dot->identifier(), $2, $3);
    390                                }
    391                            }
     371                           { if (!makeAssignNode($$, $1, $2, $3)) YYABORT; }
    392372;
    393373
     
    520500                                     DBG($$,@1,@9); }
    521501  | FOR '(' LeftHandSideExpr IN Expr ')'
    522             Statement              { $$ = new ForInNode($3, $5, $7);
    523                                      DBG($$,@1,@6); }
     502            Statement              {
     503                                     Node *n = $3;
     504                                     bool paren = n->isGroupNode();
     505                                     if (paren)
     506                                         n = static_cast<GroupNode *>(n)->nodeInsideAllParens();
     507                                     
     508                                     if (!n->isLocation())
     509                                         YYABORT;
     510
     511                                     $$ = new ForInNode(n, $5, $7);
     512                                     DBG($$,@1,@6);
     513                                   }
    524514  | FOR '(' VAR IDENT IN Expr ')'
    525515            Statement              { $$ = new ForInNode(*$4,0,$6,$8);
     
    685675
    686676%%
     677
     678static bool makeAssignNode(Node*& result, Node *loc, Operator op, Node *expr)
     679{
     680    Node *n = loc;
     681    bool paren = n->isGroupNode();
     682    if (paren)
     683        n = static_cast<GroupNode *>(n)->nodeInsideAllParens();
     684
     685    if (!n->isLocation())
     686        return false;
     687
     688    if (n->isResolveNode()) {
     689        ResolveNode *resolve = static_cast<ResolveNode *>(n);
     690        result = new AssignResolveNode(resolve->identifier(), op, expr);
     691    } else if (n->isBracketAccessorNode()) {
     692        BracketAccessorNode *bracket = static_cast<BracketAccessorNode *>(n);
     693        result = new AssignBracketNode(bracket->base(), bracket->subscript(), op, expr);
     694    } else {
     695        assert(n->isDotAccessorNode());
     696        DotAccessorNode *dot = static_cast<DotAccessorNode *>(n);
     697        result = new AssignDotNode(dot->base(), dot->identifier(), op, expr);
     698    }
     699
     700    return true;
     701}
     702
     703static bool makePrefixNode(Node*& result, Node *expr, Operator op)
     704{
     705    Node *n = expr;
     706    bool paren = n->isGroupNode();
     707    if (paren)
     708        n = static_cast<GroupNode *>(n)->nodeInsideAllParens();
     709
     710    if (!n->isLocation())
     711        return false;
     712   
     713    if (n->isResolveNode()) {
     714        ResolveNode *resolve = static_cast<ResolveNode *>(n);
     715        result = new PrefixResolveNode(resolve->identifier(), op);
     716    } else if (n->isBracketAccessorNode()) {
     717        BracketAccessorNode *bracket = static_cast<BracketAccessorNode *>(n);
     718        result = new PrefixBracketNode(bracket->base(), bracket->subscript(), op);
     719    } else {
     720        assert(n->isDotAccessorNode());
     721        DotAccessorNode *dot = static_cast<DotAccessorNode *>(n);
     722        result = new PrefixDotNode(dot->base(), dot->identifier(), op);
     723    }
     724
     725    return true;
     726}
     727
     728static bool makePostfixNode(Node*& result, Node *expr, Operator op)
     729{
     730    Node *n = expr;
     731    bool paren = n->isGroupNode();
     732    if (paren)
     733        n = static_cast<GroupNode *>(n)->nodeInsideAllParens();
     734
     735    if (!n->isLocation())
     736        return false;
     737   
     738    if (n->isResolveNode()) {
     739        ResolveNode *resolve = static_cast<ResolveNode *>(n);
     740        result = new PostfixResolveNode(resolve->identifier(), op);
     741    } else if (n->isBracketAccessorNode()) {
     742        BracketAccessorNode *bracket = static_cast<BracketAccessorNode *>(n);
     743        result = new PostfixBracketNode(bracket->base(), bracket->subscript(), op);
     744    } else {
     745        assert(n->isDotAccessorNode());
     746        DotAccessorNode *dot = static_cast<DotAccessorNode *>(n);
     747        result = new PostfixDotNode(dot->base(), dot->identifier(), op);
     748    }
     749
     750    return true;
     751}
    687752
    688753static Node *makeFunctionCallNode(Node *func, ArgumentsNode *args)
     
    714779}
    715780
     781static Node *makeTypeOfNode(Node *expr)
     782{
     783    Node *n = expr;
     784    bool paren = n->isGroupNode();
     785    if (paren)
     786        n = static_cast<GroupNode *>(n)->nodeInsideAllParens();
     787
     788    if (n->isResolveNode()) {
     789        ResolveNode *resolve = static_cast<ResolveNode *>(n);
     790        return new TypeOfResolveNode(resolve->identifier());
     791    } else
     792        return new TypeOfValueNode(n);
     793}
     794
     795static Node *makeDeleteNode(Node *expr)
     796{
     797    Node *n = expr;
     798    bool paren = n->isGroupNode();
     799    if (paren)
     800        n = static_cast<GroupNode *>(n)->nodeInsideAllParens();
     801   
     802    if (!n->isLocation())
     803        return new DeleteValueNode(expr);
     804    else if (n->isResolveNode()) {
     805        ResolveNode *resolve = static_cast<ResolveNode *>(n);
     806        return new DeleteResolveNode(resolve->identifier());
     807    } else if (n->isBracketAccessorNode()) {
     808        BracketAccessorNode *bracket = static_cast<BracketAccessorNode *>(n);
     809        return new DeleteBracketNode(bracket->base(), bracket->subscript());
     810    } else {
     811        assert(n->isDotAccessorNode());
     812        DotAccessorNode *dot = static_cast<DotAccessorNode *>(n);
     813        return new DeleteDotNode(dot->base(), dot->identifier());
     814    }
     815}
     816
    716817int yyerror (const char * /* s */)  /* Called by yyparse on error */
    717818{
  • 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();
  • trunk/JavaScriptCore/kjs/nodes.h

    r10588 r10621  
    8686
    8787    virtual ValueImp *evaluate(ExecState *exec) = 0;
    88     virtual Reference evaluateReference(ExecState *exec);
    8988    UString toString() const;
    9089    virtual void streamTo(SourceStream &s) const = 0;
     
    200199    ResolveNode(const Identifier &s) : ident(s) { }
    201200    ValueImp *evaluate(ExecState *exec);
    202     virtual Reference evaluateReference(ExecState *exec);
    203201    virtual void streamTo(SourceStream &s) const;
    204202
     
    215213    GroupNode(Node *g) : group(g) { }
    216214    virtual ValueImp *evaluate(ExecState *exec);
    217     virtual Reference evaluateReference(ExecState *exec);
    218215    virtual void streamTo(SourceStream &s) const;
    219216
     
    303300    BracketAccessorNode(Node *e1, Node *e2) : expr1(e1), expr2(e2) {}
    304301    ValueImp *evaluate(ExecState *exec);
    305     virtual Reference evaluateReference(ExecState *exec);
    306302    virtual void streamTo(SourceStream &s) const;
    307303
     
    320316    DotAccessorNode(Node *e, const Identifier &s) : expr(e), ident(s) { }
    321317    ValueImp *evaluate(ExecState *exec);
    322     virtual Reference evaluateReference(ExecState *exec);
    323318    virtual void streamTo(SourceStream &s) const;
    324319
     
    425420  };
    426421
    427   class PostfixNode : public Node {
    428   public:
    429     PostfixNode(Node *e, Operator o) : expr(e), oper(o) {}
    430     ValueImp *evaluate(ExecState *exec);
    431     virtual void streamTo(SourceStream &s) const;
    432   private:
    433     KXMLCore::SharedPtr<Node> expr;
    434     Operator oper;
    435   };
    436 
    437   class DeleteNode : public Node {
    438   public:
    439     DeleteNode(Node *e) : expr(e) {}
    440     ValueImp *evaluate(ExecState *exec);
    441     virtual void streamTo(SourceStream &s) const;
    442   private:
    443     KXMLCore::SharedPtr<Node> expr;
     422  class PostfixResolveNode : public Node {
     423  public:
     424    PostfixResolveNode(const Identifier& i, Operator o) : m_ident(i), m_oper(o) {}
     425    ValueImp *evaluate(ExecState *exec);
     426    virtual void streamTo(SourceStream &s) const;
     427  private:
     428    Identifier m_ident;
     429    Operator m_oper;
     430  };
     431
     432  class PostfixBracketNode : public Node {
     433  public:
     434    PostfixBracketNode(Node *b, Node *s, Operator o) : m_base(b), m_subscript(s), m_oper(o) {}
     435    ValueImp *evaluate(ExecState *exec);
     436    virtual void streamTo(SourceStream &s) const;
     437  private:
     438    KXMLCore::SharedPtr<Node> m_base;
     439    KXMLCore::SharedPtr<Node> m_subscript;
     440    Operator m_oper;
     441  };
     442
     443  class PostfixDotNode : public Node {
     444  public:
     445    PostfixDotNode(Node *b, const Identifier& i, Operator o) : m_base(b), m_ident(i), m_oper(o) {}
     446    ValueImp *evaluate(ExecState *exec);
     447    virtual void streamTo(SourceStream &s) const;
     448  private:
     449    KXMLCore::SharedPtr<Node> m_base;
     450    Identifier m_ident;
     451    Operator m_oper;
     452  };
     453
     454  class DeleteResolveNode : public Node {
     455  public:
     456    DeleteResolveNode(const Identifier& i) : m_ident(i) {}
     457    ValueImp *evaluate(ExecState *exec);
     458    virtual void streamTo(SourceStream &s) const;
     459  private:
     460    Identifier m_ident;
     461  };
     462
     463  class DeleteBracketNode : public Node {
     464  public:
     465    DeleteBracketNode(Node *base, Node *subscript) : m_base(base), m_subscript(subscript) {}
     466    ValueImp *evaluate(ExecState *exec);
     467    virtual void streamTo(SourceStream &s) const;
     468  private:
     469    KXMLCore::SharedPtr<Node> m_base;
     470    KXMLCore::SharedPtr<Node> m_subscript;
     471  };
     472
     473  class DeleteDotNode : public Node {
     474  public:
     475    DeleteDotNode(Node *base, const Identifier& i) : m_base(base), m_ident(i) {}
     476    ValueImp *evaluate(ExecState *exec);
     477    virtual void streamTo(SourceStream &s) const;
     478  private:
     479    KXMLCore::SharedPtr<Node> m_base;
     480    Identifier m_ident;
     481  };
     482
     483  class DeleteValueNode : public Node {
     484  public:
     485    DeleteValueNode(Node *e) : m_expr(e) {}
     486    ValueImp *evaluate(ExecState *exec);
     487    virtual void streamTo(SourceStream &s) const;
     488  private:
     489    KXMLCore::SharedPtr<Node> m_expr;
    444490  };
    445491
     
    453499  };
    454500
    455   class TypeOfNode : public Node {
    456   public:
    457     TypeOfNode(Node *e) : expr(e) {}
    458     ValueImp *evaluate(ExecState *exec);
    459     virtual void streamTo(SourceStream &s) const;
    460   private:
    461     KXMLCore::SharedPtr<Node> expr;
    462   };
    463 
    464   class PrefixNode : public Node {
    465   public:
    466     PrefixNode(Operator o, Node *e) : oper(o), expr(e) {}
    467     ValueImp *evaluate(ExecState *exec);
    468     virtual void streamTo(SourceStream &s) const;
    469   private:
    470     Operator oper;
    471     KXMLCore::SharedPtr<Node> expr;
     501  class TypeOfResolveNode : public Node {
     502  public:
     503    TypeOfResolveNode(const Identifier& i) : m_ident(i) {}
     504    ValueImp *evaluate(ExecState *exec);
     505    virtual void streamTo(SourceStream &s) const;
     506  private:
     507    Identifier m_ident;
     508  };
     509
     510  class TypeOfValueNode : public Node {
     511  public:
     512    TypeOfValueNode(Node *e) : m_expr(e) {}
     513    ValueImp *evaluate(ExecState *exec);
     514    virtual void streamTo(SourceStream &s) const;
     515  private:
     516    KXMLCore::SharedPtr<Node> m_expr;
     517  };
     518
     519  class PrefixResolveNode : public Node {
     520  public:
     521    PrefixResolveNode(const Identifier& i, Operator o) : m_ident(i), m_oper(o) {}
     522    ValueImp *evaluate(ExecState *exec);
     523    virtual void streamTo(SourceStream &s) const;
     524  private:
     525    Identifier m_ident;
     526    Operator m_oper;
     527  };
     528
     529  class PrefixBracketNode : public Node {
     530  public:
     531    PrefixBracketNode(Node *b, Node *s, Operator o) : m_base(b), m_subscript(s), m_oper(o) {}
     532    ValueImp *evaluate(ExecState *exec);
     533    virtual void streamTo(SourceStream &s) const;
     534  private:
     535    KXMLCore::SharedPtr<Node> m_base;
     536    KXMLCore::SharedPtr<Node> m_subscript;
     537    Operator m_oper;
     538  };
     539
     540  class PrefixDotNode : public Node {
     541  public:
     542    PrefixDotNode(Node *b, const Identifier& i, Operator o) : m_base(b), m_ident(i), m_oper(o) {}
     543    ValueImp *evaluate(ExecState *exec);
     544    virtual void streamTo(SourceStream &s) const;
     545  private:
     546    KXMLCore::SharedPtr<Node> m_base;
     547    Identifier m_ident;
     548    Operator m_oper;
    472549  };
    473550
  • trunk/JavaScriptCore/kjs/nodes2string.cpp

    r10399 r10621  
    229229}
    230230
    231 void PostfixNode::streamTo(SourceStream &s) const
    232 {
    233   s << expr;
    234   if (oper == OpPlusPlus)
     231void PostfixResolveNode::streamTo(SourceStream &s) const
     232{
     233  s << m_ident;
     234  if (m_oper == OpPlusPlus)
    235235    s << "++";
    236236  else
     
    238238}
    239239
    240 void DeleteNode::streamTo(SourceStream &s) const
    241 {
    242   s << "delete " << expr;
     240void PostfixBracketNode::streamTo(SourceStream &s) const
     241{
     242  s << m_base << "[" << m_subscript << "]";
     243  if (m_oper == OpPlusPlus)
     244    s << "++";
     245  else
     246    s << "--";
     247}
     248
     249void PostfixDotNode::streamTo(SourceStream &s) const
     250{
     251  s << m_base << "." << m_ident;
     252  if (m_oper == OpPlusPlus)
     253    s << "++";
     254  else
     255    s << "--";
     256}
     257
     258void DeleteResolveNode::streamTo(SourceStream &s) const
     259{
     260  s << "delete " << m_ident;
     261}
     262
     263void DeleteBracketNode::streamTo(SourceStream &s) const
     264{
     265  s << "delete " << m_base << "[" << m_subscript << "]";
     266}
     267
     268void DeleteDotNode::streamTo(SourceStream &s) const
     269{
     270  s << "delete " << m_base << "." << m_ident;
     271}
     272
     273void DeleteValueNode::streamTo(SourceStream &s) const
     274{
     275  s << "delete " << m_expr;
    243276}
    244277
     
    248281}
    249282
    250 void TypeOfNode::streamTo(SourceStream &s) const
    251 {
    252   s << "typeof " << expr;
    253 }
    254 
    255 void PrefixNode::streamTo(SourceStream &s) const
    256 {
    257   s << expr << (oper == OpPlusPlus ? "++" : "--");
     283void TypeOfValueNode::streamTo(SourceStream &s) const
     284{
     285  s << "typeof " << m_expr;
     286}
     287
     288void TypeOfResolveNode::streamTo(SourceStream &s) const
     289{
     290  s << "typeof " << m_ident;
     291}
     292
     293void PrefixResolveNode::streamTo(SourceStream &s) const
     294{
     295  if (m_oper == OpPlusPlus)
     296    s << "++";
     297  else
     298    s << "--";
     299  s << m_ident;
     300}
     301
     302void PrefixBracketNode::streamTo(SourceStream &s) const
     303{
     304  if (m_oper == OpPlusPlus)
     305    s << "++";
     306  else
     307    s << "--";
     308  s << m_base << "[" << m_subscript << "]";
     309}
     310
     311void PrefixDotNode::streamTo(SourceStream &s) const
     312{
     313  if (m_oper == OpPlusPlus)
     314    s << "++";
     315  else
     316    s << "--";
     317  s << m_base << "." << m_ident;
    258318}
    259319
  • trunk/JavaScriptCore/kjs/reference.cpp

    r10207 r10621  
    3030Reference::Reference(ObjectImp *b, const Identifier& p)
    3131  : base(b),
    32     baseIsValue(false),
    3332    propertyNameIsNumber(false),
    3433    prop(p)
     
    3938  : base(b),
    4039    propertyNameAsNumber(p),
    41     baseIsValue(false),
    4240    propertyNameIsNumber(true)
    4341{
    4442}
    4543
    46 Reference::Reference(const Identifier& p)
    47   : base(jsNull()),
    48     baseIsValue(false),
    49     propertyNameIsNumber(false),
    50     prop(p)
    51 {
    52 }
    53 
    54 Reference::Reference(unsigned p)
    55   : base(jsNull()),
    56     propertyNameAsNumber(p),
    57     baseIsValue(false),
    58     propertyNameIsNumber(true)
    59 {
    60 }
    61 
    62 Reference Reference::makeValueReference(ValueImp *v)
    63 {
    64   Reference valueRef;
    65   valueRef.base = v;
    66   valueRef.baseIsValue = true;
    67   return valueRef;
    68 }
    69 
    70 ValueImp *Reference::getBase(ExecState *exec) const
    71 {
    72   if (baseIsValue)
    73     return throwError(exec, ReferenceError, "Invalid reference base");
    74   return base;
    75 }
    76 
    7744Identifier Reference::getPropertyName(ExecState *exec) const
    7845{
    79   if (baseIsValue) {
    80     // the spec wants a runtime error here. But getValue() and putValue()
    81     // will catch this case on their own earlier. When returning a Null
    82     // string we should be on the safe side.
    83     return Identifier();
    84   }
    85 
    8646  if (propertyNameIsNumber && prop.isNull())
    8747    prop = Identifier::from(propertyNameAsNumber);
     
    9151ValueImp *Reference::getValue(ExecState *exec) const
    9252{
    93   if (baseIsValue)
    94     return base;
    95 
    9653  ValueImp *o = base;
    9754  if (!o || !o->isObject()) {
     
    10663}
    10764
    108 void Reference::putValue(ExecState *exec, ValueImp *w)
    109 {
    110   if (baseIsValue) {
    111     throwError(exec, ReferenceError);
    112     return;
    113   }
    114 
    115 #ifdef KJS_VERBOSE
    116   printInfo(exec,(UString("setting property ")+getPropertyName(exec).ustring()).cstring().c_str(),w);
    117 #endif
    118 
    119   ValueImp *o = base;
    120   Type t = o ? o->type() : NullType;
    121 
    122   if (t == NullType)
    123     o = exec->lexicalInterpreter()->globalObject();
    124 
    125   if (propertyNameIsNumber)
    126     return static_cast<ObjectImp*>(o)->put(exec, propertyNameAsNumber, w);
    127   return static_cast<ObjectImp*>(o)->put(exec, prop, w);
    128 }
    129 
    13065bool Reference::deleteValue(ExecState *exec)
    13166{
    132   if (baseIsValue) {
    133     throwError(exec, ReferenceError);
    134     return false;
    135   }
    136 
    13767  ValueImp *o = base;
    13868  Type t = o ? o->type() : NullType;
  • trunk/JavaScriptCore/kjs/reference.h

    r10563 r10621  
    3737    Reference(ObjectImp *b, const Identifier& p);
    3838    Reference(ObjectImp *b, unsigned p);
    39     Reference(const Identifier& p);
    40     Reference(unsigned p);
    41     static Reference makeValueReference(ValueImp *);
    4239   
    43     /**
    44      * Performs the GetBase type conversion operation on this value (ECMA 8.7)
    45      *
    46      * Since references are supposed to have an Object or null as their base,
    47      * this method is guaranteed to return either Null() or an Object value.
    48      */
    49     ValueImp *getBase(ExecState *exec) const;
    50 
    5140    /**
    5241     * Performs the GetPropertyName type conversion operation on this value
     
    6554     * (ECMA 8.7.1)
    6655     */
    67     void putValue(ExecState *exec, ValueImp *);
    6856    bool deleteValue(ExecState *exec);
    69 
    70     ValueImp *baseIfMutable() const { return baseIsValue ? 0 : base; }
    7157
    7258  protected:
     
    7763
    7864    unsigned propertyNameAsNumber;
    79     bool baseIsValue;
    8065    bool propertyNameIsNumber;
    8166    mutable Identifier prop;
Note: See TracChangeset for help on using the changeset viewer.