Changeset 28973
- Timestamp:
- 12/24/07 02:13:00 (11 months ago)
- Location:
- trunk/JavaScriptCore
- Files:
-
- 7 modified
-
ChangeLog (modified) (1 diff)
-
JavaScriptCore.exp (modified) (1 diff)
-
kjs/NodeInfo.h (modified) (1 diff)
-
kjs/grammar.y (modified) (14 diffs)
-
kjs/nodes.cpp (modified) (19 diffs)
-
kjs/nodes.h (modified) (12 diffs)
-
kjs/nodes2string.cpp (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/ChangeLog
r28950 r28973 1 2007-12-24 Maciej Stachowiak <mjs@apple.com> 2 3 Reviewed by Eric. 4 5 - Optimize variable declarations 6 http://bugs.webkit.org/show_bug.cgi?id=16585 7 8 3.5% speedup on SunSpider. 9 10 var statements now result in either assignments or empty statements. 11 12 This allows a couple of optimization opportunities: 13 - No need to branch at runtime to check if there is an initializer 14 - EmptyStatementNodes can be removed entirely (also done in this patch) 15 - Assignment expressions get properly optimized for local variables 16 17 This patch also includes some code cleanup: 18 - Most of the old VarStatement/VarDecl logic is now only used for const declarations, 19 thus it is renamed appropriately 20 - AssignExprNode is gone 21 22 * JavaScriptCore.exp: 23 * kjs/NodeInfo.h: 24 * kjs/grammar.y: 25 * kjs/nodes.cpp: 26 (KJS::SourceElements::append): 27 (KJS::ConstDeclNode::ConstDeclNode): 28 (KJS::ConstDeclNode::optimizeVariableAccess): 29 (KJS::ConstDeclNode::handleSlowCase): 30 (KJS::ConstDeclNode::evaluateSingle): 31 (KJS::ConstDeclNode::evaluate): 32 (KJS::ConstStatementNode::optimizeVariableAccess): 33 (KJS::ConstStatementNode::execute): 34 (KJS::VarStatementNode::optimizeVariableAccess): 35 (KJS::VarStatementNode::execute): 36 (KJS::ForInNode::ForInNode): 37 (KJS::ForInNode::optimizeVariableAccess): 38 (KJS::ForInNode::execute): 39 (KJS::FunctionBodyNode::initializeSymbolTable): 40 (KJS::ProgramNode::initializeSymbolTable): 41 (KJS::FunctionBodyNode::processDeclarations): 42 (KJS::ProgramNode::processDeclarations): 43 (KJS::EvalNode::processDeclarations): 44 * kjs/nodes.h: 45 (KJS::DeclarationStacks::): 46 (KJS::StatementNode::): 47 (KJS::ConstDeclNode::): 48 (KJS::ConstStatementNode::): 49 (KJS::EmptyStatementNode::): 50 (KJS::VarStatementNode::): 51 (KJS::ForNode::): 52 * kjs/nodes2string.cpp: 53 (KJS::ConstDeclNode::streamTo): 54 (KJS::ConstStatementNode::streamTo): 55 (KJS::ScopeNode::streamTo): 56 (KJS::VarStatementNode::streamTo): 57 (KJS::ForNode::streamTo): 58 (KJS::ForInNode::streamTo): 59 1 60 2007-12-21 Mark Rowe <mrowe@apple.com> 2 61 -
trunk/JavaScriptCore/JavaScriptCore.exp
r28950 r28973 121 121 __ZN3KJS11JSImmediate8toObjectEPKNS_7JSValueEPNS_9ExecStateE 122 122 __ZN3KJS11JSImmediate8toStringEPKNS_7JSValueE 123 __ZN3KJS11ProgramNodeC1EPNS_14SourceElementsEPN3WTF6VectorI PNS_11VarDeclNodeELm16EEEPNS4_IPNS_12FuncDeclNodeELm16EEE123 __ZN3KJS11ProgramNodeC1EPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm16EEEPNS4_IPNS_12FuncDeclNodeELm16EEE 124 124 __ZN3KJS11PropertyMap11getLocationERKNS_10IdentifierE 125 125 __ZN3KJS11PropertyMap5clearEv -
trunk/JavaScriptCore/kjs/NodeInfo.h
r28937 r28973 37 37 typedef NodeInfo<SourceElements*> SourceElementsInfo; 38 38 typedef NodeInfo<ClauseList> ClauseListInfo; 39 typedef NodeInfo<VarDeclList> VarDeclListInfo; 39 typedef NodeInfo<ExpressionNode*> VarDeclListInfo; 40 typedef NodeInfo<ConstDeclList> ConstDeclListInfo; 40 41 41 42 } // namespace KJS -
trunk/JavaScriptCore/kjs/grammar.y
r28937 r28973 71 71 static ExpressionNode* makeNegateNode(ExpressionNode*); 72 72 static NumberNode* makeNumberNode(double); 73 static StatementNode* makeVarStatementNode(ExpressionNode*); 74 static ExpressionNode* combineVarInitializers(ExpressionNode* list, AssignResolveNode* init); 75 73 76 74 77 #if COMPILER(MSVC) … … 112 115 } 113 116 114 static void appendToVarDeclarationList(ParserRefCountedData<DeclarationStacks::VarStack>*& varDecls, VarDeclNode* decl)117 static void appendToVarDeclarationList(ParserRefCountedData<DeclarationStacks::VarStack>*& varDecls, const Identifier& ident, unsigned attrs) 115 118 { 116 119 if (!varDecls) 117 120 varDecls = new ParserRefCountedData<DeclarationStacks::VarStack>; 118 varDecls->data.append(decl); 121 122 varDecls->data.append(make_pair(ident, attrs)); 123 124 } 125 126 static inline void appendToVarDeclarationList(ParserRefCountedData<DeclarationStacks::VarStack>*& varDecls, ConstDeclNode* decl) 127 { 128 unsigned attrs = DeclarationStacks::IsConstant; 129 if (decl->init) 130 attrs |= DeclarationStacks::HasInitializer; 131 appendToVarDeclarationList(varDecls, decl->ident, attrs); 119 132 } 120 133 … … 132 145 PropertyNode* propertyNode; 133 146 ArgumentsNode* argumentsNode; 134 VarDeclNode* varDeclNode;147 ConstDeclNode* constDeclNode; 135 148 CaseBlockNodeInfo caseBlockNode; 136 149 CaseClauseNodeInfo caseClauseNode; 137 150 FuncExprNode* funcExprNode; 138 AssignExprNode* assignExprNode;139 151 140 152 // statement nodes … … 147 159 ArgumentList argumentList; 148 160 VarDeclListInfo varDeclList; 161 ConstDeclListInfo constDeclList; 149 162 ClauseListInfo clauseList; 150 163 ElementList elementList; … … 229 242 %type <statementNode> SourceElement 230 243 231 %type < assignExprNode> Initializer InitializerNoIn244 %type <expressionNode> Initializer InitializerNoIn 232 245 %type <funcDeclNode> FunctionDeclaration 233 246 %type <funcExprNode> FunctionExpr … … 238 251 %type <argumentsNode> Arguments 239 252 %type <argumentList> ArgumentList 240 %type <varDeclList> VariableDeclarationList VariableDeclarationListNoIn ConstDeclarationList 241 %type <varDeclNode> VariableDeclaration VariableDeclarationNoIn ConstDeclaration 253 %type <varDeclList> VariableDeclarationList VariableDeclarationListNoIn 254 %type <constDeclList> ConstDeclarationList 255 %type <constDeclNode> ConstDeclaration 242 256 %type <caseBlockNode> CaseBlock 243 257 %type <caseClauseNode> CaseClause DefaultClause … … 704 718 705 719 VariableStatement: 706 VAR VariableDeclarationList ';' { $$ = createNodeInfo<StatementNode*>( new VarStatementNode($2.m_node.head), $2.m_varDeclarations, $2.m_funcDeclarations);720 VAR VariableDeclarationList ';' { $$ = createNodeInfo<StatementNode*>(makeVarStatementNode($2.m_node), $2.m_varDeclarations, $2.m_funcDeclarations); 707 721 DBG($$.m_node, @1, @3); } 708 | VAR VariableDeclarationList error { $$ = createNodeInfo<StatementNode*>( new VarStatementNode($2.m_node.head), $2.m_varDeclarations, $2.m_funcDeclarations);722 | VAR VariableDeclarationList error { $$ = createNodeInfo<StatementNode*>(makeVarStatementNode($2.m_node), $2.m_varDeclarations, $2.m_funcDeclarations); 709 723 DBG($$.m_node, @1, @2); 710 724 AUTO_SEMICOLON; } … … 712 726 713 727 VariableDeclarationList: 714 VariableDeclaration { $$.m_node.head = $1; 715 $$.m_node.tail = $$.m_node.head; 728 IDENT { $$.m_node = 0; 716 729 $$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>; 717 $$.m_varDeclarations->data.append($1);730 appendToVarDeclarationList($$.m_varDeclarations, *$1, 0); 718 731 $$.m_funcDeclarations = 0; 719 732 } 720 | VariableDeclarationList ',' VariableDeclaration 721 { $$.m_node.head = $1.m_node.head; 722 $1.m_node.tail->next = $3; 723 $$.m_node.tail = $3; 733 | IDENT Initializer { $$.m_node = new AssignResolveNode(*$1, $2); 734 $$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>; 735 appendToVarDeclarationList($$.m_varDeclarations, *$1, DeclarationStacks::HasInitializer); 736 $$.m_funcDeclarations = 0; 737 } 738 | VariableDeclarationList ',' IDENT 739 { $$.m_node = $1.m_node; 724 740 $$.m_varDeclarations = $1.m_varDeclarations; 725 $$.m_varDeclarations->data.append($3);741 appendToVarDeclarationList($$.m_varDeclarations, *$3, 0); 726 742 $$.m_funcDeclarations = 0; 727 743 } 744 | VariableDeclarationList ',' IDENT Initializer 745 { $$.m_node = combineVarInitializers($1.m_node, new AssignResolveNode(*$3, $4)); 746 $$.m_varDeclarations = $1.m_varDeclarations; 747 appendToVarDeclarationList($$.m_varDeclarations, *$3, DeclarationStacks::HasInitializer); 748 $$.m_funcDeclarations = 0; 749 } 728 750 ; 729 751 730 752 VariableDeclarationListNoIn: 731 VariableDeclarationNoIn { $$.m_node.head = $1; 732 $$.m_node.tail = $$.m_node.head; 753 IDENT { $$.m_node = 0; 733 754 $$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>; 734 $$.m_varDeclarations->data.append($1); 735 $$.m_funcDeclarations = 0; } 736 | VariableDeclarationListNoIn ',' VariableDeclarationNoIn 737 { $$.m_node.head = $1.m_node.head; 738 $1.m_node.tail->next = $3; 739 $$.m_node.tail = $3; 755 appendToVarDeclarationList($$.m_varDeclarations, *$1, 0); 756 $$.m_funcDeclarations = 0; 757 } 758 | IDENT InitializerNoIn { $$.m_node = new AssignResolveNode(*$1, $2); 759 $$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>; 760 appendToVarDeclarationList($$.m_varDeclarations, *$1, DeclarationStacks::HasInitializer); 761 $$.m_funcDeclarations = 0; 762 } 763 | VariableDeclarationListNoIn ',' IDENT 764 { $$.m_node = $1.m_node; 740 765 $$.m_varDeclarations = $1.m_varDeclarations; 741 $$.m_varDeclarations->data.append($3); 742 $$.m_funcDeclarations = 0; } 743 ; 744 745 VariableDeclaration: 746 IDENT { $$ = new VarDeclNode(*$1, 0, VarDeclNode::Variable); } 747 | IDENT Initializer { $$ = new VarDeclNode(*$1, $2, VarDeclNode::Variable); } 748 ; 749 750 VariableDeclarationNoIn: 751 IDENT { $$ = new VarDeclNode(*$1, 0, VarDeclNode::Variable); } 752 | IDENT InitializerNoIn { $$ = new VarDeclNode(*$1, $2, VarDeclNode::Variable); } 766 appendToVarDeclarationList($$.m_varDeclarations, *$3, 0); 767 $$.m_funcDeclarations = 0; 768 } 769 | VariableDeclarationListNoIn ',' IDENT InitializerNoIn 770 { $$.m_node = combineVarInitializers($1.m_node, new AssignResolveNode(*$3, $4)); 771 $$.m_varDeclarations = $1.m_varDeclarations; 772 appendToVarDeclarationList($$.m_varDeclarations, *$3, DeclarationStacks::HasInitializer); 773 $$.m_funcDeclarations = 0; 774 } 753 775 ; 754 776 755 777 ConstStatement: 756 CONSTTOKEN ConstDeclarationList ';' { $$ = createNodeInfo<StatementNode*>(new VarStatementNode($2.m_node.head), $2.m_varDeclarations, $2.m_funcDeclarations);778 CONSTTOKEN ConstDeclarationList ';' { $$ = createNodeInfo<StatementNode*>(new ConstStatementNode($2.m_node.head), $2.m_varDeclarations, $2.m_funcDeclarations); 757 779 DBG($$.m_node, @1, @3); } 758 780 | CONSTTOKEN ConstDeclarationList error 759 { $$ = createNodeInfo<StatementNode*>(new VarStatementNode($2.m_node.head), $2.m_varDeclarations, $2.m_funcDeclarations);781 { $$ = createNodeInfo<StatementNode*>(new ConstStatementNode($2.m_node.head), $2.m_varDeclarations, $2.m_funcDeclarations); 760 782 DBG($$.m_node, @1, @2); AUTO_SEMICOLON; } 761 783 ; … … 765 787 $$.m_node.tail = $$.m_node.head; 766 788 $$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>; 767 $$.m_varDeclarations->data.append($1);789 appendToVarDeclarationList($$.m_varDeclarations, $1); 768 790 $$.m_funcDeclarations = 0; } 769 791 | ConstDeclarationList ',' ConstDeclaration … … 772 794 $$.m_node.tail = $3; 773 795 $$.m_varDeclarations = $1.m_varDeclarations; 774 $$.m_varDeclarations->data.append($3);796 appendToVarDeclarationList($$.m_varDeclarations, $3); 775 797 $$.m_funcDeclarations = 0; } 776 798 ; 777 799 778 800 ConstDeclaration: 779 IDENT { $$ = new VarDeclNode(*$1, 0, VarDeclNode::Constant); }780 | IDENT Initializer { $$ = new VarDeclNode(*$1, $2, VarDeclNode::Constant); }801 IDENT { $$ = new ConstDeclNode(*$1, 0); } 802 | IDENT Initializer { $$ = new ConstDeclNode(*$1, $2); } 781 803 ; 782 804 783 805 Initializer: 784 '=' AssignmentExpr { $$ = new AssignExprNode($2); }806 '=' AssignmentExpr { $$ = $2; } 785 807 ; 786 808 787 809 InitializerNoIn: 788 '=' AssignmentExprNoIn { $$ = new AssignExprNode($2); }810 '=' AssignmentExprNoIn { $$ = $2; } 789 811 ; 790 812 … … 817 839 DBG($$.m_node, @1, @4); } 818 840 | FOR '(' ExprNoInOpt ';' ExprOpt ';' ExprOpt ')' Statement 819 { $$ = createNodeInfo<StatementNode*>(new ForNode($3, $5, $7, $9.m_node ), $9.m_varDeclarations, $9.m_funcDeclarations);841 { $$ = createNodeInfo<StatementNode*>(new ForNode($3, $5, $7, $9.m_node, false), $9.m_varDeclarations, $9.m_funcDeclarations); 820 842 DBG($$.m_node, @1, @8); 821 843 } 822 844 | FOR '(' VAR VariableDeclarationListNoIn ';' ExprOpt ';' ExprOpt ')' Statement 823 { $$ = createNodeInfo<StatementNode*>(new ForNode($4.m_node.head, $6, $8, $10.m_node),845 { $$ = createNodeInfo<StatementNode*>(new ForNode($4.m_node, $6, $8, $10.m_node, true), 824 846 mergeDeclarationLists($4.m_varDeclarations, $10.m_varDeclarations), 825 847 mergeDeclarationLists($4.m_funcDeclarations, $10.m_funcDeclarations)); … … 835 857 | FOR '(' VAR IDENT INTOKEN Expr ')' Statement 836 858 { ForInNode *forIn = new ForInNode(*$4, 0, $6, $8.m_node); 837 appendToVarDeclarationList($8.m_varDeclarations, forIn->getVarDecl());859 appendToVarDeclarationList($8.m_varDeclarations, *$4, DeclarationStacks::HasInitializer); 838 860 $$ = createNodeInfo<StatementNode*>(forIn, $8.m_varDeclarations, $8.m_funcDeclarations); 839 861 DBG($$.m_node, @1, @7); } 840 862 | FOR '(' VAR IDENT InitializerNoIn INTOKEN Expr ')' Statement 841 863 { ForInNode *forIn = new ForInNode(*$4, $5, $7, $9.m_node); 842 appendToVarDeclarationList($9.m_varDeclarations, forIn->getVarDecl());864 appendToVarDeclarationList($9.m_varDeclarations, *$4, DeclarationStacks::HasInitializer); 843 865 $$ = createNodeInfo<StatementNode*>(forIn, $9.m_varDeclarations, $9.m_funcDeclarations); 844 866 DBG($$.m_node, @1, @8); } … … 981 1003 /* not in spec */ { $$ = new FunctionBodyNode(0, 0, 0); } 982 1004 | SourceElements { $$ = new FunctionBodyNode($1.m_node, $1.m_varDeclarations ? &$1.m_varDeclarations->data : 0, 983 $1.m_funcDeclarations ? &$1.m_funcDeclarations->data : 0);1005 $1.m_funcDeclarations ? &$1.m_funcDeclarations->data : 0); 984 1006 // As in mergeDeclarationLists() we have to ref/deref to safely get rid of 985 1007 // the declaration lists. … … 1219 1241 return yychar == '}' || yychar == 0 || lexer().prevTerminator(); 1220 1242 } 1243 1244 static ExpressionNode* combineVarInitializers(ExpressionNode* list, AssignResolveNode* init) 1245 { 1246 if (!list) 1247 return init; 1248 return new CommaNode(list, init); 1249 } 1250 1251 // We turn variable declarations into either assignments or empty 1252 // statements (which later get stripped out), because the actual 1253 // declaration work is hoisted up to the start of the function body 1254 static StatementNode* makeVarStatementNode(ExpressionNode* expr) 1255 { 1256 if (!expr) 1257 return new EmptyStatementNode(); 1258 return new VarStatementNode(expr); 1259 } 1260 -
trunk/JavaScriptCore/kjs/nodes.cpp
r28937 r28973 381 381 void SourceElements::append(PassRefPtr<StatementNode> statement) 382 382 { 383 if (statement->isEmptyStatement()) 384 return; 385 383 386 if (Debugger::debuggersPresent) 384 387 m_statements.append(new BreakpointCheckStatement(statement)); … … 3420 3423 } 3421 3424 3422 // ------------------------------ AssignExprNode ------------------------------- 3423 3424 void AssignExprNode::optimizeVariableAccess(SymbolTable&, DeclarationStacks::NodeStack& nodeStack) 3425 { 3426 nodeStack.append(expr.get()); 3427 } 3428 3429 // ECMA 12.2 3430 JSValue* AssignExprNode::evaluate(ExecState* exec) 3431 { 3432 return expr->evaluate(exec); 3433 } 3434 3435 bool AssignExprNode::evaluateToBoolean(ExecState* exec) 3436 { 3437 return expr->evaluateToBoolean(exec); 3438 } 3439 3440 double AssignExprNode::evaluateToNumber(ExecState* exec) 3441 { 3442 return expr->evaluateToNumber(exec); 3443 } 3444 3445 int32_t AssignExprNode::evaluateToInt32(ExecState* exec) 3446 { 3447 return expr->evaluateToInt32(exec); 3448 } 3449 3450 uint32_t AssignExprNode::evaluateToUInt32(ExecState* exec) 3451 { 3452 return expr->evaluateToInt32(exec); 3453 } 3454 3455 // ------------------------------ VarDeclNode ---------------------------------- 3456 3457 VarDeclNode::VarDeclNode(const Identifier &id, AssignExprNode *in, Type t) 3458 : varType(t) 3459 , ident(id) 3425 // ------------------------------ ConstDeclNode ---------------------------------- 3426 3427 ConstDeclNode::ConstDeclNode(const Identifier& id, ExpressionNode* in) 3428 : ident(id) 3460 3429 , init(in) 3461 3430 { 3462 3431 } 3463 3432 3464 void VarDeclNode::optimizeVariableAccess(SymbolTable&, DeclarationStacks::NodeStack& nodeStack)3433 void ConstDeclNode::optimizeVariableAccess(SymbolTable&, DeclarationStacks::NodeStack& nodeStack) 3465 3434 { 3466 3435 if (next) … … 3470 3439 } 3471 3440 3472 void VarDeclNode::handleSlowCase(ExecState* exec, const ScopeChain& chain, JSValue* val)3441 void ConstDeclNode::handleSlowCase(ExecState* exec, const ScopeChain& chain, JSValue* val) 3473 3442 { 3474 3443 ScopeChainIterator iter = chain.begin(); … … 3491 3460 unsigned flags = 0; 3492 3461 base->getPropertyAttributes(ident, flags); 3493 if (varType == VarDeclNode::Constant) 3494 flags |= ReadOnly; 3462 flags |= ReadOnly; 3495 3463 3496 3464 base->put(exec, ident, val, flags); … … 3498 3466 3499 3467 // ECMA 12.2 3500 inline void VarDeclNode::evaluateSingle(ExecState* exec)3468 inline void ConstDeclNode::evaluateSingle(ExecState* exec) 3501 3469 { 3502 3470 ASSERT(exec->variableObject()->hasOwnProperty(exec, ident) || exec->codeType() == EvalCode); // Guaranteed by processDeclarations. … … 3514 3482 if (exec->codeType() != EvalCode) 3515 3483 flags |= DontDelete; 3516 if (varType == VarDeclNode::Constant) 3517 flags |= ReadOnly; 3484 flags |= ReadOnly; 3518 3485 variableObject->put(exec, ident, val, flags); 3519 3486 } else { … … 3529 3496 unsigned flags = 0; 3530 3497 variableObject->getPropertyAttributes(ident, flags); 3531 if (varType == VarDeclNode::Constant) 3532 flags |= ReadOnly; 3498 flags |= ReadOnly; 3533 3499 3534 3500 variableObject->put(exec, ident, val, flags); … … 3537 3503 } 3538 3504 3539 JSValue* VarDeclNode::evaluate(ExecState* exec)3505 JSValue* ConstDeclNode::evaluate(ExecState* exec) 3540 3506 { 3541 3507 evaluateSingle(exec); 3542 3508 3543 if ( VarDeclNode* n = next.get()) {3509 if (ConstDeclNode* n = next.get()) { 3544 3510 do { 3545 3511 n->evaluateSingle(exec); … … 3551 3517 } 3552 3518 3553 // ------------------------------ VarStatementNode -----------------------------3554 3555 void VarStatementNode::optimizeVariableAccess(SymbolTable&, DeclarationStacks::NodeStack& nodeStack)3519 // ------------------------------ ConstStatementNode ----------------------------- 3520 3521 void ConstStatementNode::optimizeVariableAccess(SymbolTable&, DeclarationStacks::NodeStack& nodeStack) 3556 3522 { 3557 3523 ASSERT(next); … … 3560 3526 3561 3527 // ECMA 12.2 3562 JSValue* VarStatementNode::execute(ExecState* exec)3528 JSValue* ConstStatementNode::execute(ExecState* exec) 3563 3529 { 3564 3530 next->evaluate(exec); … … 3655 3621 } 3656 3622 3623 // ------------------------------ VarStatementNode ---------------------------- 3624 3625 void VarStatementNode::optimizeVariableAccess(SymbolTable&, DeclarationStacks::NodeStack& nodeStack) 3626 { 3627 ASSERT(expr); 3628 nodeStack.append(expr.get()); 3629 } 3630 3631 JSValue* VarStatementNode::execute(ExecState* exec) 3632 { 3633 expr->evaluate(exec); 3634 KJS_CHECKEXCEPTION 3635 3636 return exec->setNormalCompletion(); 3637 } 3638 3657 3639 // ------------------------------ IfNode --------------------------------------- 3658 3640 … … 3827 3809 3828 3810 ForInNode::ForInNode(ExpressionNode* l, ExpressionNode* e, StatementNode* s) 3829 : init(0L), lexpr(l), expr(e), varDecl(0L), statement(s) 3830 { 3831 } 3832 3833 ForInNode::ForInNode(const Identifier& i, AssignExprNode* in, ExpressionNode* e, StatementNode* s) 3834 : ident(i), init(in), expr(e), statement(s) 3835 { 3811 : init(0L), lexpr(l), expr(e), statement(s), identIsVarDecl(false) 3812 { 3813 } 3814 3815 ForInNode::ForInNode(const Identifier& i, ExpressionNode* in, ExpressionNode* e, StatementNode* s) 3816 : ident(i), lexpr(new ResolveNode(i)), expr(e), statement(s), identIsVarDecl(true) 3817 { 3818 if (in) 3819 init = new AssignResolveNode(i, in); 3836 3820 // for( var foo = bar in baz ) 3837 varDecl = new VarDeclNode(ident, init.get(), VarDeclNode::Variable);3838 lexpr = new ResolveNode(ident);3839 3821 } 3840 3822 … … 3844 3826 nodeStack.append(expr.get()); 3845 3827 nodeStack.append(lexpr.get()); 3846 if ( varDecl)3847 nodeStack.append( varDecl.get());3828 if (init) 3829 nodeStack.append(init.get()); 3848 3830 } 3849 3831 … … 3853 3835 JSValue* value = 0; 3854 3836 3855 if ( varDecl) {3856 varDecl->evaluate(exec);3837 if (init) { 3838 init->evaluate(exec); 3857 3839 KJS_CHECKEXCEPTION 3858 3840 } … … 4268 4250 4269 4251 for (size_t i = 0, size = m_varStack.size(); i < size; ++i, ++localStorageIndex) { 4270 Identifier& ident = m_varStack[i] ->ident;4252 Identifier& ident = m_varStack[i].first; 4271 4253 if (ident == exec->propertyNames().arguments) 4272 4254 continue; … …