@@ -2846,29 +2846,33 @@ Statement* Parser::DesugarLetBindingsInForStatement(
28462846 //
28472847 // We rewrite a for statement of the form
28482848 //
2849- // for (let x = i; cond; next) body
2849+ // labels: for (let x = i; cond; next) body
28502850 //
28512851 // into
28522852 //
28532853 // {
2854- // let x = i;
2855- // temp_x = x;
2856- // flag = 1;
2857- // for (;;) {
2858- // let x = temp_x;
2859- // if (flag == 1) {
2860- // flag = 0;
2861- // } else {
2862- // next;
2863- // }
2854+ // let x = i;
2855+ // temp_x = x;
2856+ // first = 1;
2857+ // outer: for (;;) {
2858+ // let x = temp_x;
2859+ // if (first == 1) {
2860+ // first = 0;
2861+ // } else {
2862+ // next;
2863+ // }
2864+ // flag = 1;
2865+ // labels: for (; flag == 1; flag = 0, temp_x = x) {
28642866 // if (cond) {
2865- // <empty>
2867+ // body
28662868 // } else {
2867- // break;
2869+ // break outer ;
28682870 // }
2869- // b
2870- // temp_x = x;
2871- // }
2871+ // }
2872+ // if (flag == 1) {
2873+ // break;
2874+ // }
2875+ // }
28722876 // }
28732877
28742878 DCHECK (names->length () > 0 );
@@ -2896,24 +2900,33 @@ Statement* Parser::DesugarLetBindingsInForStatement(
28962900 temps.Add (temp, zone ());
28972901 }
28982902
2899- Variable* flag = scope_->DeclarationScope ()->NewTemporary (temp_name);
2900- // Make statement: flag = 1.
2901- {
2902- VariableProxy* flag_proxy = factory ()->NewVariableProxy (flag);
2903+ Variable* first = NULL ;
2904+ // Make statement: first = 1.
2905+ if (next) {
2906+ first = scope_->DeclarationScope ()->NewTemporary (temp_name);
2907+ VariableProxy* first_proxy = factory ()->NewVariableProxy (first);
29032908 Expression* const1 = factory ()->NewSmiLiteral (1 , RelocInfo::kNoPosition );
29042909 Assignment* assignment = factory ()->NewAssignment (
2905- Token::ASSIGN, flag_proxy , const1, RelocInfo::kNoPosition );
2906- Statement* assignment_statement = factory ()-> NewExpressionStatement (
2907- assignment, RelocInfo::kNoPosition );
2910+ Token::ASSIGN, first_proxy , const1, RelocInfo::kNoPosition );
2911+ Statement* assignment_statement =
2912+ factory ()-> NewExpressionStatement ( assignment, RelocInfo::kNoPosition );
29082913 outer_block->AddStatement (assignment_statement, zone ());
29092914 }
29102915
2911- outer_block->AddStatement (loop, zone ());
2916+ // Make statement: outer: for (;;)
2917+ // Note that we don't actually create the label, or set this loop up as an
2918+ // explicit break target, instead handing it directly to those nodes that
2919+ // need to know about it. This should be safe because we don't run any code
2920+ // in this function that looks up break targets.
2921+ ForStatement* outer_loop =
2922+ factory ()->NewForStatement (NULL , RelocInfo::kNoPosition );
2923+ outer_block->AddStatement (outer_loop, zone ());
2924+
29122925 outer_block->set_scope (for_scope);
29132926 scope_ = inner_scope;
29142927
2915- Block* inner_block = factory ()->NewBlock (NULL , 2 * names->length () + 3 ,
2916- false , RelocInfo::kNoPosition );
2928+ Block* inner_block = factory ()->NewBlock (NULL , names->length () + 4 , false ,
2929+ RelocInfo::kNoPosition );
29172930 int pos = scanner ()->location ().beg_pos ;
29182931 ZoneList<Variable*> inner_vars (names->length (), zone ());
29192932
@@ -2935,61 +2948,118 @@ Statement* Parser::DesugarLetBindingsInForStatement(
29352948 inner_block->AddStatement (assignment_statement, zone ());
29362949 }
29372950
2938- // Make statement: if (flag == 1) { flag = 0; } else { next; }.
2951+ // Make statement: if (first == 1) { first = 0; } else { next; }
29392952 if (next) {
2953+ DCHECK (first);
29402954 Expression* compare = NULL ;
2941- // Make compare expresion: flag == 1.
2955+ // Make compare expression: first == 1.
29422956 {
29432957 Expression* const1 = factory ()->NewSmiLiteral (1 , RelocInfo::kNoPosition );
2944- VariableProxy* flag_proxy = factory ()->NewVariableProxy (flag );
2945- compare = factory ()-> NewCompareOperation (
2946- Token::EQ, flag_proxy , const1, pos);
2958+ VariableProxy* first_proxy = factory ()->NewVariableProxy (first );
2959+ compare =
2960+ factory ()-> NewCompareOperation ( Token::EQ, first_proxy , const1, pos);
29472961 }
2948- Statement* clear_flag = NULL ;
2949- // Make statement: flag = 0.
2962+ Statement* clear_first = NULL ;
2963+ // Make statement: first = 0.
29502964 {
2951- VariableProxy* flag_proxy = factory ()->NewVariableProxy (flag );
2965+ VariableProxy* first_proxy = factory ()->NewVariableProxy (first );
29522966 Expression* const0 = factory ()->NewSmiLiteral (0 , RelocInfo::kNoPosition );
29532967 Assignment* assignment = factory ()->NewAssignment (
2954- Token::ASSIGN, flag_proxy, const0, RelocInfo::kNoPosition );
2955- clear_flag = factory ()->NewExpressionStatement (assignment, pos);
2968+ Token::ASSIGN, first_proxy, const0, RelocInfo::kNoPosition );
2969+ clear_first =
2970+ factory ()->NewExpressionStatement (assignment, RelocInfo::kNoPosition );
29562971 }
2957- Statement* clear_flag_or_next = factory ()->NewIfStatement (
2958- compare, clear_flag , next, RelocInfo::kNoPosition );
2959- inner_block->AddStatement (clear_flag_or_next , zone ());
2972+ Statement* clear_first_or_next = factory ()->NewIfStatement (
2973+ compare, clear_first , next, RelocInfo::kNoPosition );
2974+ inner_block->AddStatement (clear_first_or_next , zone ());
29602975 }
29612976
2977+ Variable* flag = scope_->DeclarationScope ()->NewTemporary (temp_name);
2978+ // Make statement: flag = 1.
2979+ {
2980+ VariableProxy* flag_proxy = factory ()->NewVariableProxy (flag);
2981+ Expression* const1 = factory ()->NewSmiLiteral (1 , RelocInfo::kNoPosition );
2982+ Assignment* assignment = factory ()->NewAssignment (
2983+ Token::ASSIGN, flag_proxy, const1, RelocInfo::kNoPosition );
2984+ Statement* assignment_statement =
2985+ factory ()->NewExpressionStatement (assignment, RelocInfo::kNoPosition );
2986+ inner_block->AddStatement (assignment_statement, zone ());
2987+ }
2988+
2989+ // Make cond expression for main loop: flag == 1.
2990+ Expression* flag_cond = NULL ;
2991+ {
2992+ Expression* const1 = factory ()->NewSmiLiteral (1 , RelocInfo::kNoPosition );
2993+ VariableProxy* flag_proxy = factory ()->NewVariableProxy (flag);
2994+ flag_cond =
2995+ factory ()->NewCompareOperation (Token::EQ, flag_proxy, const1, pos);
2996+ }
29622997
2963- // Make statement: if (cond) { } else { break; }.
2998+ // Create chain of expressions "flag = 0, temp_x = x, ..."
2999+ Statement* compound_next_statement = NULL ;
3000+ {
3001+ Expression* compound_next = NULL ;
3002+ // Make expression: flag = 0.
3003+ {
3004+ VariableProxy* flag_proxy = factory ()->NewVariableProxy (flag);
3005+ Expression* const0 = factory ()->NewSmiLiteral (0 , RelocInfo::kNoPosition );
3006+ compound_next = factory ()->NewAssignment (Token::ASSIGN, flag_proxy,
3007+ const0, RelocInfo::kNoPosition );
3008+ }
3009+
3010+ // Make the comma-separated list of temp_x = x assignments.
3011+ for (int i = 0 ; i < names->length (); i++) {
3012+ VariableProxy* temp_proxy = factory ()->NewVariableProxy (temps.at (i));
3013+ VariableProxy* proxy = factory ()->NewVariableProxy (inner_vars.at (i), pos);
3014+ Assignment* assignment = factory ()->NewAssignment (
3015+ Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition );
3016+ compound_next = factory ()->NewBinaryOperation (
3017+ Token::COMMA, compound_next, assignment, RelocInfo::kNoPosition );
3018+ }
3019+
3020+ compound_next_statement = factory ()->NewExpressionStatement (
3021+ compound_next, RelocInfo::kNoPosition );
3022+ }
3023+
3024+ // Make statement: if (cond) { body; } else { break outer; }
3025+ Statement* body_or_stop = body;
29643026 if (cond) {
2965- Statement* empty = factory ()->NewEmptyStatement (RelocInfo::kNoPosition );
2966- BreakableStatement* t = LookupBreakTarget (NULL , CHECK_OK);
2967- Statement* stop = factory ()->NewBreakStatement (t, RelocInfo::kNoPosition );
2968- Statement* if_not_cond_break = factory ()->NewIfStatement (
2969- cond, empty, stop, cond->position ());
2970- inner_block->AddStatement (if_not_cond_break, zone ());
3027+ Statement* stop =
3028+ factory ()->NewBreakStatement (outer_loop, RelocInfo::kNoPosition );
3029+ body_or_stop =
3030+ factory ()->NewIfStatement (cond, body, stop, cond->position ());
29713031 }
29723032
2973- inner_block->AddStatement (body, zone ());
3033+ // Make statement: labels: for (; flag == 1; flag = 0, temp_x = x)
3034+ // Note that we re-use the original loop node, which retains it labels
3035+ // and ensures that any break or continue statements in body point to
3036+ // the right place.
3037+ loop->Initialize (NULL , flag_cond, compound_next_statement, body_or_stop);
3038+ inner_block->AddStatement (loop, zone ());
29743039
2975- // For each let variable x:
2976- // make statement: temp_x = x;
2977- for (int i = 0 ; i < names->length (); i++) {
2978- VariableProxy* temp_proxy = factory ()->NewVariableProxy (temps.at (i));
2979- int pos = scanner ()->location ().end_pos ;
2980- VariableProxy* proxy = factory ()->NewVariableProxy (inner_vars.at (i), pos);
2981- Assignment* assignment = factory ()->NewAssignment (
2982- Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition );
2983- Statement* assignment_statement = factory ()->NewExpressionStatement (
2984- assignment, RelocInfo::kNoPosition );
2985- inner_block->AddStatement (assignment_statement, zone ());
3040+ // Make statement: if (flag == 1) { break; }
3041+ {
3042+ Expression* compare = NULL ;
3043+ // Make compare expresion: flag == 1.
3044+ {
3045+ Expression* const1 = factory ()->NewSmiLiteral (1 , RelocInfo::kNoPosition );
3046+ VariableProxy* flag_proxy = factory ()->NewVariableProxy (flag);
3047+ compare =
3048+ factory ()->NewCompareOperation (Token::EQ, flag_proxy, const1, pos);
3049+ }
3050+ Statement* stop =
3051+ factory ()->NewBreakStatement (outer_loop, RelocInfo::kNoPosition );
3052+ Statement* empty = factory ()->NewEmptyStatement (RelocInfo::kNoPosition );
3053+ Statement* if_flag_break =
3054+ factory ()->NewIfStatement (compare, stop, empty, RelocInfo::kNoPosition );
3055+ inner_block->AddStatement (if_flag_break, zone ());
29863056 }
29873057
29883058 inner_scope->set_end_position (scanner ()->location ().end_pos );
29893059 inner_block->set_scope (inner_scope);
29903060 scope_ = for_scope;
29913061
2992- loop ->Initialize (NULL , NULL , NULL , inner_block);
3062+ outer_loop ->Initialize (NULL , NULL , NULL , inner_block);
29933063 return outer_block;
29943064}
29953065
0 commit comments