Changeset 33552 in webkit


Ignore:
Timestamp:
May 17, 2008 4:00:56 AM (16 years ago)
Author:
cwzwarich@webkit.org
Message:

2008-05-17 Cameron Zwarich <cwzwarich@uwaterloo.ca>

Reviewed by Oliver.

Bug 18991: SquirrelFish: Major codegen issue in a.b=expr, a[b]=expr
<https://bugs.webkit.org/show_bug.cgi?id=18991>

Ensure that the code generated for assignments uses temporaries whenever
necessary. This patch covers the vast majority of situations, but there
are still a few left.

This patch also adds some missing cases to CodeBlock::dump().

JavaScriptCore:

  • VM/CodeBlock.cpp: (KJS::CodeBlock::dump):
  • VM/CodeGenerator.h: (KJS::CodeGenerator::destinationForAssignResult): (KJS::CodeGenerator::leftHandSideNeedsCopy): (KJS::CodeGenerator::emitNodeForLeftHandSide):
  • kjs/NodeInfo.h:
  • kjs/grammar.y:
  • kjs/nodes.cpp: (KJS::AssignDotNode::emitCode): (KJS::ReadModifyDotNode::emitCode): (KJS::AssignBracketNode::emitCode): (KJS::ReadModifyBracketNode::emitCode): (KJS::ForInNode::ForInNode):
  • kjs/nodes.h: (KJS::ReadModifyResolveNode::): (KJS::AssignResolveNode::): (KJS::ReadModifyBracketNode::): (KJS::AssignBracketNode::): (KJS::AssignDotNode::): (KJS::ReadModifyDotNode::):

LayoutTests:

  • fast/js/codegen-temporaries-expected.txt:
  • fast/js/resources/codegen-temporaries.js:
Location:
branches/squirrelfish
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • branches/squirrelfish/JavaScriptCore/ChangeLog

    r33550 r33552  
     12008-05-17  Cameron Zwarich  <cwzwarich@uwaterloo.ca>
     2
     3        Reviewed by Oliver.
     4
     5        Partial fix for:
     6
     7        Bug 18991: SquirrelFish: Major codegen issue in a.b=expr, a[b]=expr
     8        <https://bugs.webkit.org/show_bug.cgi?id=18991>
     9
     10        Ensure that the code generated for assignments uses temporaries whenever
     11        necessary. This patch covers the vast majority of situations, but there
     12        are still a few left.
     13
     14        This patch also adds some missing cases to CodeBlock::dump().
     15
     16        * VM/CodeBlock.cpp:
     17        (KJS::CodeBlock::dump):
     18        * VM/CodeGenerator.h:
     19        (KJS::CodeGenerator::destinationForAssignResult):
     20        (KJS::CodeGenerator::leftHandSideNeedsCopy):
     21        (KJS::CodeGenerator::emitNodeForLeftHandSide):
     22        * kjs/NodeInfo.h:
     23        * kjs/grammar.y:
     24        * kjs/nodes.cpp:
     25        (KJS::AssignDotNode::emitCode):
     26        (KJS::ReadModifyDotNode::emitCode):
     27        (KJS::AssignBracketNode::emitCode):
     28        (KJS::ReadModifyBracketNode::emitCode):
     29        (KJS::ForInNode::ForInNode):
     30        * kjs/nodes.h:
     31        (KJS::ReadModifyResolveNode::):
     32        (KJS::AssignResolveNode::):
     33        (KJS::ReadModifyBracketNode::):
     34        (KJS::AssignBracketNode::):
     35        (KJS::AssignDotNode::):
     36        (KJS::ReadModifyDotNode::):
     37
    1382008-05-17  Oliver Hunt  <oliver@apple.com>
    239
  • branches/squirrelfish/JavaScriptCore/VM/CodeBlock.cpp

    r33484 r33552  
    383383            break;
    384384        }
     385        case op_put_getter: {
     386            int r0 = (++it)->u.operand;
     387            int id0 = (++it)->u.operand;
     388            int r1 = (++it)->u.operand;
     389            printf("[%4d] put_getter\t %s, %s, %s\n", location, registerName(r0).c_str(), idName(id0, identifiers[id0]).c_str(), registerName(r1).c_str());
     390            break;
     391        }
     392        case op_put_setter: {
     393            int r0 = (++it)->u.operand;
     394            int id0 = (++it)->u.operand;
     395            int r1 = (++it)->u.operand;
     396            printf("[%4d] put_setter\t %s, %s, %s\n", location, registerName(r0).c_str(), idName(id0, identifiers[id0]).c_str(), registerName(r1).c_str());
     397            break;
     398        }
    385399        case op_del_by_id: {
    386400            int r0 = (++it)->u.operand;
  • branches/squirrelfish/JavaScriptCore/VM/CodeGenerator.h

    r33541 r33552  
    127127            return newTemporary();
    128128        }
     129       
     130        RegisterID* destinationForAssignResult(RegisterID* dst) {
     131            if (dst && m_codeBlock->needsFullScopeChain)
     132                return dst->isTemporary() ? dst : newTemporary();
     133            return 0;
     134        }
    129135
    130136        // moves src to dst if dst is not null and is different from src, otherwise just returns src
     
    149155        {
    150156            return emitNode(0, n);
     157        }
     158
     159        ALWAYS_INLINE bool leftHandSideNeedsCopy(bool rightHasAssignments)
     160        {
     161            return m_codeBlock->needsFullScopeChain || rightHasAssignments;
     162        }
     163
     164        ALWAYS_INLINE PassRefPtr<RegisterID> emitNodeForLeftHandSide(ExpressionNode* n, bool rightHasAssignments)
     165        {
     166            if (leftHandSideNeedsCopy(rightHasAssignments)) {
     167                PassRefPtr<RegisterID> dst = newTemporary();
     168                emitNode(dst.get(), n);
     169                return dst;
     170            }
     171           
     172            return PassRefPtr<RegisterID>(emitNode(n));
    151173        }
    152174
  • branches/squirrelfish/JavaScriptCore/kjs/NodeInfo.h

    r31072 r33552  
    3131    const FeatureInfo EvalFeature = 1 << 0;
    3232    const FeatureInfo ClosureFeature = 1 << 1;
     33    const FeatureInfo AssignFeature = 1 << 2;
    3334
    3435    template <typename T> struct NodeFeatureInfo {
  • branches/squirrelfish/JavaScriptCore/kjs/grammar.y

    r33386 r33552  
    6464static AddNode* makeAddNode(ExpressionNode*, ExpressionNode*);
    6565static LessNode* makeLessNode(ExpressionNode*, ExpressionNode*);
    66 static ExpressionNode* makeAssignNode(ExpressionNode* loc, Operator, ExpressionNode* expr);
     66static ExpressionNode* makeAssignNode(ExpressionNode* loc, Operator, ExpressionNode* expr, bool locHasAssignments, bool exprHasAssignments);
    6767static ExpressionNode* makePrefixNode(ExpressionNode* expr, Operator);
    6868static ExpressionNode* makePostfixNode(ExpressionNode* expr, Operator);
     
    9898                                                                       FeatureInfo info)
    9999{
    100     ASSERT((info & ~(EvalFeature | ClosureFeature)) == 0);
     100    ASSERT((info & ~(EvalFeature | ClosureFeature | AssignFeature)) == 0);
    101101    NodeDeclarationInfo<T> result = {node, varDecls, funcDecls, info};
    102102    return result;
     
    105105template <typename T> NodeFeatureInfo<T> createNodeFeatureInfo(T node, FeatureInfo info)
    106106{
    107     ASSERT((info & ~(EvalFeature | ClosureFeature)) == 0);
     107    ASSERT((info & ~(EvalFeature | ClosureFeature | AssignFeature)) == 0);
    108108    NodeFeatureInfo<T> result = {node, info};
    109109    return result;
     
    438438  | VOIDTOKEN UnaryExpr                 { $$ = createNodeFeatureInfo<ExpressionNode*>(new VoidNode($2.m_node), $2.m_featureInfo); }
    439439  | TYPEOF UnaryExpr                    { $$ = createNodeFeatureInfo<ExpressionNode*>(makeTypeOfNode($2.m_node), $2.m_featureInfo); }
    440   | PLUSPLUS UnaryExpr                  { $$ = createNodeFeatureInfo<ExpressionNode*>(makePrefixNode($2.m_node, OpPlusPlus), $2.m_featureInfo); }
    441   | AUTOPLUSPLUS UnaryExpr              { $$ = createNodeFeatureInfo<ExpressionNode*>(makePrefixNode($2.m_node, OpPlusPlus), $2.m_featureInfo); }
    442   | MINUSMINUS UnaryExpr                { $$ = createNodeFeatureInfo<ExpressionNode*>(makePrefixNode($2.m_node, OpMinusMinus), $2.m_featureInfo); }
    443   | AUTOMINUSMINUS UnaryExpr            { $$ = createNodeFeatureInfo<ExpressionNode*>(makePrefixNode($2.m_node, OpMinusMinus), $2.m_featureInfo); }
     440  | PLUSPLUS UnaryExpr                  { $$ = createNodeFeatureInfo<ExpressionNode*>(makePrefixNode($2.m_node, OpPlusPlus), $2.m_featureInfo | AssignFeature); }
     441  | AUTOPLUSPLUS UnaryExpr              { $$ = createNodeFeatureInfo<ExpressionNode*>(makePrefixNode($2.m_node, OpPlusPlus), $2.m_featureInfo | AssignFeature); }
     442  | MINUSMINUS UnaryExpr                { $$ = createNodeFeatureInfo<ExpressionNode*>(makePrefixNode($2.m_node, OpMinusMinus), $2.m_featureInfo | AssignFeature); }
     443  | AUTOMINUSMINUS UnaryExpr            { $$ = createNodeFeatureInfo<ExpressionNode*>(makePrefixNode($2.m_node, OpMinusMinus), $2.m_featureInfo | AssignFeature); }
    444444  | '+' UnaryExpr                       { $$ = createNodeFeatureInfo<ExpressionNode*>(new UnaryPlusNode($2.m_node), $2.m_featureInfo); }
    445445  | '-' UnaryExpr                       { $$ = createNodeFeatureInfo<ExpressionNode*>(makeNegateNode($2.m_node), $2.m_featureInfo); }
     
    668668    ConditionalExpr
    669669  | LeftHandSideExpr AssignmentOperator AssignmentExpr
    670                                         { $$ = createNodeFeatureInfo<ExpressionNode*>(makeAssignNode($1.m_node, $2, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
     670                                        { $$ = createNodeFeatureInfo<ExpressionNode*>(makeAssignNode($1.m_node, $2, $3.m_node, $1.m_featureInfo & AssignFeature, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo | AssignFeature); }
    671671;
    672672
     
    674674    ConditionalExprNoIn
    675675  | LeftHandSideExpr AssignmentOperator AssignmentExprNoIn
    676                                         { $$ = createNodeFeatureInfo<ExpressionNode*>(makeAssignNode($1.m_node, $2, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
     676                                        { $$ = createNodeFeatureInfo<ExpressionNode*>(makeAssignNode($1.m_node, $2, $3.m_node, $1.m_featureInfo & AssignFeature, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo | AssignFeature); }
    677677;
    678678
     
    680680    ConditionalExprNoBF
    681681  | LeftHandSideExprNoBF AssignmentOperator AssignmentExpr
    682                                         { $$ = createNodeFeatureInfo<ExpressionNode*>(makeAssignNode($1.m_node, $2, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
     682                                        { $$ = createNodeFeatureInfo<ExpressionNode*>(makeAssignNode($1.m_node, $2, $3.m_node, $1.m_featureInfo & AssignFeature, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo | AssignFeature); }
    683683;
    684684
     
    754754                                          $$.m_featureInfo = 0;
    755755                                        }
    756   | IDENT Initializer                   { $$.m_node = new AssignResolveNode(*$1, $2.m_node);
     756  | IDENT Initializer                   { $$.m_node = new AssignResolveNode(*$1, $2.m_node, $2.m_featureInfo & AssignFeature);
    757757                                          $$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>;
    758758                                          appendToVarDeclarationList($$.m_varDeclarations, *$1, DeclarationStacks::HasInitializer);
     
    768768                                        }
    769769  | VariableDeclarationList ',' IDENT Initializer
    770                                         { $$.m_node = combineVarInitializers($1.m_node, new AssignResolveNode(*$3, $4.m_node));
     770                                        { $$.m_node = combineVarInitializers($1.m_node, new AssignResolveNode(*$3, $4.m_node, $4.m_featureInfo & AssignFeature));
    771771                                          $$.m_varDeclarations = $1.m_varDeclarations;
    772772                                          appendToVarDeclarationList($$.m_varDeclarations, *$3, DeclarationStacks::HasInitializer);
     
    783783                                          $$.m_featureInfo = 0;
    784784                                        }
    785   | IDENT InitializerNoIn               { $$.m_node = new AssignResolveNode(*$1, $2.m_node);
     785  | IDENT InitializerNoIn               { $$.m_node = new AssignResolveNode(*$1, $2.m_node, $2.m_featureInfo & AssignFeature);
    786786                                          $$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>;
    787787                                          appendToVarDeclarationList($$.m_varDeclarations, *$1, DeclarationStacks::HasInitializer);
     
    797797                                        }
    798798  | VariableDeclarationListNoIn ',' IDENT InitializerNoIn
    799                                         { $$.m_node = combineVarInitializers($1.m_node, new AssignResolveNode(*$3, $4.m_node));
     799                                        { $$.m_node = combineVarInitializers($1.m_node, new AssignResolveNode(*$3, $4.m_node, $4.m_featureInfo & AssignFeature));
    800800                                          $$.m_varDeclarations = $1.m_varDeclarations;
    801801                                          appendToVarDeclarationList($$.m_varDeclarations, *$3, DeclarationStacks::HasInitializer);
     
    11261126}
    11271127
    1128 static ExpressionNode* makeAssignNode(ExpressionNode* loc, Operator op, ExpressionNode* expr)
     1128static ExpressionNode* makeAssignNode(ExpressionNode* loc, Operator op, ExpressionNode* expr, bool locHasAssignments, bool exprHasAssignments)
    11291129{
    11301130    if (!loc->isLocation())
     
    11341134        ResolveNode* resolve = static_cast<ResolveNode*>(loc);
    11351135        if (op == OpEqual)
    1136             return new AssignResolveNode(resolve->identifier(), expr);
     1136            return new AssignResolveNode(resolve->identifier(), expr, exprHasAssignments);
    11371137        else
    1138             return new ReadModifyResolveNode(resolve->identifier(), op, expr);
     1138            return new ReadModifyResolveNode(resolve->identifier(), op, expr, exprHasAssignments);
    11391139    }
    11401140    if (loc->isBracketAccessorNode()) {
    11411141        BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(loc);
    11421142        if (op == OpEqual)
    1143             return new AssignBracketNode(bracket->base(), bracket->subscript(), expr);
     1143            return new AssignBracketNode(bracket->base(), bracket->subscript(), expr, locHasAssignments, exprHasAssignments);
    11441144        else
    1145             return new ReadModifyBracketNode(bracket->base(), bracket->subscript(), op, expr);
     1145            return new ReadModifyBracketNode(bracket->base(), bracket->subscript(), op, expr, locHasAssignments, exprHasAssignments);
    11461146    }
    11471147    ASSERT(loc->isDotAccessorNode());
    11481148    DotAccessorNode* dot = static_cast<DotAccessorNode*>(loc);
    11491149    if (op == OpEqual)
    1150         return new AssignDotNode(dot->base(), dot->identifier(), expr);
    1151     return new ReadModifyDotNode(dot->base(), dot->identifier(), op, expr);
     1150        return new AssignDotNode(dot->base(), dot->identifier(), expr, exprHasAssignments);
     1151    return new ReadModifyDotNode(dot->base(), dot->identifier(), op, expr, exprHasAssignments);
    11521152}
    11531153
  • branches/squirrelfish/JavaScriptCore/kjs/nodes.cpp

    r33541 r33552  
    43424342RegisterID* AssignDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
    43434343{
    4344     RefPtr<RegisterID> base = generator.emitNode(m_base.get());
    4345     RegisterID* value = generator.emitNode(dst, m_right.get());
    4346     return generator.emitPutById(base.get(), m_ident, value);
     4344    RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments);
     4345    RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
     4346    RegisterID* result = generator.emitNode(value.get(), m_right.get());
     4347    generator.emitPutById(base.get(), m_ident, result);
     4348    return generator.moveToDestinationIfNeeded(dst, result);
    43474349}
    43484350
     
    43694371RegisterID* ReadModifyDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
    43704372{
    4371     RefPtr<RegisterID> base = generator.emitNode(m_base.get());
    4372 
    4373     // FIXME: should not write temp value to dst if dst is a local!
     4373    RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments);
    43744374    RefPtr<RegisterID> value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
    43754375    RegisterID* change = generator.emitNode(m_right.get());
     
    44224422RegisterID* AssignBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
    44234423{
    4424     RefPtr<RegisterID> base = generator.emitNode(m_base.get());
    4425     RefPtr<RegisterID> property = generator.emitNode(m_subscript.get());
    4426     RegisterID* value = generator.emitNode(dst, m_right.get());
    4427     return generator.emitPutByVal(base.get(), property.get(), value);
     4424    RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments);
     4425    RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments);
     4426    RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
     4427    RegisterID* result = generator.emitNode(value.get(), m_right.get());
     4428    generator.emitPutByVal(base.get(), property.get(), result);
     4429    return generator.moveToDestinationIfNeeded(dst, result);
    44284430}
    44294431
     
    44634465RegisterID* ReadModifyBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
    44644466{
    4465     RefPtr<RegisterID> base = generator.emitNode(m_base.get());
    4466     RefPtr<RegisterID> property = generator.emitNode(m_subscript.get());
     4467    RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments);
     4468    RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments);
    44674469
    44684470    RefPtr<RegisterID> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
     
    50965098{
    50975099    if (in)
    5098         m_init = new AssignResolveNode(ident, in);
     5100        m_init = new AssignResolveNode(ident, in, true);
    50995101    // for( var foo = bar in baz )
    51005102}
  • branches/squirrelfish/JavaScriptCore/kjs/nodes.h

    r33434 r33552  
    23012301    class ReadModifyResolveNode : public ExpressionNode {
    23022302    public:
    2303         ReadModifyResolveNode(const Identifier& ident, Operator oper, ExpressionNode*  right) KJS_FAST_CALL
     2303        ReadModifyResolveNode(const Identifier& ident, Operator oper, ExpressionNode*  right, bool rightHasAssignments) KJS_FAST_CALL
    23042304            : m_ident(ident)
     2305            , m_right(right)
    23052306            , m_operator(oper)
    2306             , m_right(right)
     2307            , m_rightHasAssignments(rightHasAssignments)
    23072308        {
    23082309        }
     
    23122313            , m_ident(PlacementNewAdopt)
    23132314            , m_right(PlacementNewAdopt)
     2315            , m_rightHasAssignments(true)
    23142316        {
    23152317        }
     
    23242326    protected:
    23252327        Identifier m_ident;
    2326         Operator m_operator;
    23272328        RefPtr<ExpressionNode> m_right;
    23282329        size_t m_index; // Used by ReadModifyLocalVarNode.
     2330        Operator m_operator : 31;
     2331        bool m_rightHasAssignments : 1;
    23292332    };
    23302333
     
    23552358    class AssignResolveNode : public ExpressionNode {
    23562359    public:
    2357         AssignResolveNode(const Identifier& ident, ExpressionNode* right) KJS_FAST_CALL
     2360        AssignResolveNode(const Identifier& ident, ExpressionNode* right, bool rightHasAssignments) KJS_FAST_CALL
    23582361            : m_ident(ident)
    23592362            , m_right(right)
     2363            , m_rightHasAssignments(rightHasAssignments)
    23602364        {
    23612365        }
     
    23792383        RefPtr<ExpressionNode> m_right;
    23802384        size_t m_index; // Used by ReadModifyLocalVarNode.
     2385        bool m_rightHasAssignments;
    23812386    };
    23822387
     
    24052410    class ReadModifyBracketNode : public ExpressionNode {
    24062411    public:
    2407         ReadModifyBracketNode(ExpressionNode* base, ExpressionNode* subscript, Operator oper, ExpressionNode* right) KJS_FAST_CALL
    2408             : m_base(base)
    2409             , m_subscript(subscript)
    2410             , m_operator(oper)
    2411             , m_right(right)
    2412         {
    2413         }
    2414 
    2415         virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
    2416 
    2417         virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
    2418         virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
    2419         virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
    2420         virtual Precedence precedence() const { return PrecAssignment; }
    2421 
    2422     protected:
    2423         RefPtr<ExpressionNode> m_base;
    2424         RefPtr<ExpressionNode> m_subscript;
    2425         Operator m_operator;
    2426         RefPtr<ExpressionNode> m_right;
    2427     };
    2428 
    2429     class AssignBracketNode : public ExpressionNode {
    2430     public:
    2431         AssignBracketNode(ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right) KJS_FAST_CALL
     2412        ReadModifyBracketNode(ExpressionNode* base, ExpressionNode* subscript, Operator oper, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments) KJS_FAST_CALL
    24322413            : m_base(base)
    24332414            , m_subscript(subscript)
    24342415            , m_right(right)
     2416            , m_operator(oper)
     2417            , m_subscriptHasAssignments(subscriptHasAssignments)
     2418            , m_rightHasAssignments(rightHasAssignments)
    24352419        {
    24362420        }
     
    24472431        RefPtr<ExpressionNode> m_subscript;
    24482432        RefPtr<ExpressionNode> m_right;
     2433        Operator m_operator : 30;
     2434        bool m_subscriptHasAssignments : 1;
     2435        bool m_rightHasAssignments : 1;
     2436    };
     2437
     2438    class AssignBracketNode : public ExpressionNode {
     2439    public:
     2440        AssignBracketNode(ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments) KJS_FAST_CALL
     2441            : m_base(base)
     2442            , m_subscript(subscript)
     2443            , m_right(right)
     2444            , m_subscriptHasAssignments(subscriptHasAssignments)
     2445            , m_rightHasAssignments(rightHasAssignments)
     2446        {
     2447        }
     2448
     2449        virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
     2450
     2451        virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
     2452        virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
     2453        virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
     2454        virtual Precedence precedence() const { return PrecAssignment; }
     2455
     2456    protected:
     2457        RefPtr<ExpressionNode> m_base;
     2458        RefPtr<ExpressionNode> m_subscript;
     2459        RefPtr<ExpressionNode> m_right;
     2460        bool m_subscriptHasAssignments : 1;
     2461        bool m_rightHasAssignments : 1;
    24492462    };
    24502463
    24512464    class AssignDotNode : public ExpressionNode {
    24522465    public:
    2453         AssignDotNode(ExpressionNode* base, const Identifier& ident, ExpressionNode* right) KJS_FAST_CALL
     2466        AssignDotNode(ExpressionNode* base, const Identifier& ident, ExpressionNode* right, bool rightHasAssignments) KJS_FAST_CALL
    24542467            : m_base(base)
    24552468            , m_ident(ident)
    24562469            , m_right(right)
     2470            , m_rightHasAssignments(rightHasAssignments)
    24572471        {
    24582472        }
     
    24682482        Identifier m_ident;
    24692483        RefPtr<ExpressionNode> m_right;
     2484        bool m_rightHasAssignments;
    24702485    };
    24712486
    24722487    class ReadModifyDotNode : public ExpressionNode {
    24732488    public:
    2474         ReadModifyDotNode(ExpressionNode* base, const Identifier& ident, Operator oper, ExpressionNode* right) KJS_FAST_CALL
     2489        ReadModifyDotNode(ExpressionNode* base, const Identifier& ident, Operator oper, ExpressionNode* right, bool rightHasAssignments) KJS_FAST_CALL
    24752490            : m_base(base)
    24762491            , m_ident(ident)
     2492            , m_right(right)
    24772493            , m_operator(oper)
    2478             , m_right(right)
     2494            , m_rightHasAssignments(rightHasAssignments)
    24792495        {
    24802496        }
     
    24902506        RefPtr<ExpressionNode> m_base;
    24912507        Identifier m_ident;
    2492         Operator m_operator;
    24932508        RefPtr<ExpressionNode> m_right;
     2509        Operator m_operator : 31;
     2510        bool m_rightHasAssignments : 1;
    24942511    };
    24952512
  • branches/squirrelfish/LayoutTests/ChangeLog

    r33551 r33552  
     12008-05-17  Cameron Zwarich  <cwzwarich@uwaterloo.ca>
     2
     3        Reviewed by Oliver.
     4
     5        Add tests for:
     6
     7        Bug 18991: SquirrelFish: Major codegen issue in a.b=expr, a[b]=expr
     8        <https://bugs.webkit.org/show_bug.cgi?id=18991>
     9
     10        * fast/js/codegen-temporaries-expected.txt:
     11        * fast/js/resources/codegen-temporaries.js:
     12
    1132008-05-17  Oliver Hunt  <oliver@apple.com>
    214
  • branches/squirrelfish/LayoutTests/fast/js/codegen-temporaries-expected.txt

    r33369 r33552  
    66PASS a is true
    77PASS b is false
     8PASS assign_test1() is 'PASS'
     9PASS assign_test2() is 'PASS'
     10PASS assign_test3() is 'PASS'
     11PASS testObject4.test is 'PASS'
     12PASS testObject5.test is 'PASS'
     13PASS assign_test6() is 'PASS'
     14PASS assign_test7() is 'PASS'
     15PASS assign_test8() is 'PASS'
     16PASS assign_test9() is 'PASS'
     17PASS testObject10.test is 'PASS'
     18PASS assign_test11() is 'PASS'
     19PASS assign_test12() is 'PASS'
     20PASS assign_test13() is 'PASS'
     21PASS assign_test14() is 'PASS'
     22PASS assign_test15() is 'PASS'
     23PASS assign_test16() is 2
    824PASS successfullyParsed is true
    925
  • branches/squirrelfish/LayoutTests/fast/js/resources/codegen-temporaries.js

    r33369 r33552  
    1111shouldBeFalse("b");
    1212
     13function TestObject() {
     14    this.toString = function() { return this.test; }
     15    this.test = "FAIL";
     16    return this;
     17}
     18
     19function assign_test1()
     20{
     21    var testObject = new TestObject;
     22    var a = testObject;
     23    a.test = "PASS";
     24    return testObject.test;
     25}
     26
     27shouldBe("assign_test1()", "'PASS'");
     28
     29function assign_test2()
     30{
     31    var testObject = new TestObject;
     32    var a = testObject;
     33    a = a.test = "PASS";
     34    return testObject.test;
     35}
     36
     37shouldBe("assign_test2()", "'PASS'");
     38
     39function assign_test3()
     40{
     41    var testObject = new TestObject;
     42    var a = testObject;
     43    a.test = a = "PASS";
     44    return testObject.test;
     45}
     46
     47shouldBe("assign_test3()", "'PASS'");
     48
     49var testObject4 = new TestObject;
     50var a4 = testObject4;
     51a4.test = this.a4 = "PASS";
     52
     53shouldBe("testObject4.test", "'PASS'");
     54
     55var testObject5 = new TestObject;
     56var a5 = testObject5;
     57a5 = this.a5.test = "PASS";
     58
     59shouldBe("testObject5.test", "'PASS'");
     60
     61function assign_test6()
     62{
     63    var testObject = new TestObject;
     64    var a = testObject;
     65    a["test"] = "PASS";
     66    return testObject.test;
     67}
     68
     69shouldBe("assign_test6()", "'PASS'");
     70
     71function assign_test7()
     72{
     73    var testObject = new TestObject;
     74    var a = testObject;
     75    a = a["test"] = "PASS";
     76    return testObject.test;
     77}
     78
     79shouldBe("assign_test7()", "'PASS'");
     80
     81function assign_test8()
     82{
     83    var testObject = new TestObject;
     84    var a = testObject;
     85    a["test"] = a = "PASS";
     86    return testObject.test;
     87}
     88
     89shouldBe("assign_test8()", "'PASS'");
     90
     91function assign_test9()
     92{
     93    var testObject = new TestObject;
     94    var a = testObject;
     95    a["test"] = this.a = "PASS";
     96    return testObject.test;
     97}
     98
     99shouldBe("assign_test9()", "'PASS'");
     100
     101var testObject10 = new TestObject;
     102var a10 = testObject10;
     103a10 = this.a10["test"] = "PASS";
     104
     105shouldBe("testObject10.test", "'PASS'");
     106
     107function assign_test11()
     108{
     109    var testObject = new TestObject;
     110    var a = testObject;
     111    a[a = "test"] = "PASS";
     112    return testObject.test;
     113}
     114
     115shouldBe("assign_test11()", "'PASS'");
     116
     117function assign_test12()
     118{
     119    var test = "test";
     120    var testObject = new TestObject;
     121    var a = testObject;
     122    a[test] = "PASS";
     123    return testObject.test;
     124}
     125
     126shouldBe("assign_test12()", "'PASS'");
     127
     128function assign_test13()
     129{
     130    var testObject = new TestObject;
     131    var a = testObject;
     132    a.test = (a = "FAIL", "PASS");
     133    return testObject.test;
     134}
     135
     136shouldBe("assign_test13()", "'PASS'");
     137
     138function assign_test14()
     139{
     140    var testObject = new TestObject;
     141    var a = testObject;
     142    a["test"] = (a = "FAIL", "PASS");
     143    return testObject.test;
     144}
     145
     146shouldBe("assign_test14()", "'PASS'");
     147
     148function assign_test15()
     149{
     150    var test = "test";
     151    var testObject = new TestObject;
     152    var a = testObject;
     153    a[test] = (test = "FAIL", "PASS");
     154    return testObject.test;
     155}
     156
     157shouldBe("assign_test15()", "'PASS'");
     158
     159function assign_test16()
     160{
     161    var a = 1;
     162    a = (a = 2);
     163    return a;
     164}
     165
     166shouldBe("assign_test16()", "2");
     167
    13168successfullyParsed = true;
Note: See TracChangeset for help on using the changeset viewer.