Upgrade V8 to 5.1.281.57  DO NOT MERGE

FPIIM-449

Change-Id: Id981b686b4d587ac31697662eb98bb34be42ad90
(cherry picked from commit 3b9bc31999c9787eb726ecdbfd5796bfdec32a18)
diff --git a/src/parsing/pattern-rewriter.cc b/src/parsing/pattern-rewriter.cc
index 768a948..e699255 100644
--- a/src/parsing/pattern-rewriter.cc
+++ b/src/parsing/pattern-rewriter.cc
@@ -17,6 +17,8 @@
     ZoneList<const AstRawString*>* names, bool* ok) {
   PatternRewriter rewriter;
 
+  DCHECK(block->ignore_completion_value());
+
   rewriter.scope_ = declaration_descriptor->scope;
   rewriter.parser_ = declaration_descriptor->parser;
   rewriter.context_ = BINDING;
@@ -234,22 +236,20 @@
 
     if (IsImmutableVariableMode(descriptor_->mode)) {
       arguments->Add(value, zone());
-      value = NULL;  // zap the value to avoid the unnecessary assignment
-
       // Construct the call to Runtime_InitializeConstGlobal
       // and add it to the initialization statement block.
       // Note that the function does different things depending on
       // the number of arguments (1 or 2).
-      initialize =
-          factory()->NewCallRuntime(Runtime::kInitializeConstGlobal, arguments,
-                                    descriptor_->initialization_pos);
+      initialize = factory()->NewCallRuntime(Runtime::kInitializeConstGlobal,
+                                             arguments, value->position());
+      value = NULL;  // zap the value to avoid the unnecessary assignment
     } else {
       // Add language mode.
       // We may want to pass singleton to avoid Literal allocations.
       LanguageMode language_mode = initialization_scope->language_mode();
-      arguments->Add(factory()->NewNumberLiteral(language_mode,
-                                                 descriptor_->declaration_pos),
-                     zone());
+      arguments->Add(
+          factory()->NewNumberLiteral(language_mode, RelocInfo::kNoPosition),
+          zone());
 
       // Be careful not to assign a value to the global variable if
       // we're in a with. The initialization value should not
@@ -257,12 +257,11 @@
       // which is why we need to generate a separate assignment node.
       if (value != NULL && !descriptor_->scope->inside_with()) {
         arguments->Add(value, zone());
-        value = NULL;  // zap the value to avoid the unnecessary assignment
         // Construct the call to Runtime_InitializeVarGlobal
         // and add it to the initialization statement block.
-        initialize =
-            factory()->NewCallRuntime(Runtime::kInitializeVarGlobal, arguments,
-                                      descriptor_->declaration_pos);
+        initialize = factory()->NewCallRuntime(Runtime::kInitializeVarGlobal,
+                                               arguments, value->position());
+        value = NULL;  // zap the value to avoid the unnecessary assignment
       } else {
         initialize = NULL;
       }
@@ -270,7 +269,7 @@
 
     if (initialize != NULL) {
       block_->statements()->Add(
-          factory()->NewExpressionStatement(initialize, RelocInfo::kNoPosition),
+          factory()->NewExpressionStatement(initialize, initialize->position()),
           zone());
     }
   } else if (value != nullptr && (descriptor_->mode == CONST_LEGACY ||
@@ -286,7 +285,7 @@
     DCHECK_NOT_NULL(proxy->var());
     DCHECK_NOT_NULL(value);
     // Add break location for destructured sub-pattern.
-    int pos = IsSubPattern() ? pattern->position() : RelocInfo::kNoPosition;
+    int pos = IsSubPattern() ? pattern->position() : value->position();
     Assignment* assignment =
         factory()->NewAssignment(Token::INIT, proxy, value, pos);
     block_->statements()->Add(
@@ -303,7 +302,7 @@
     // property).
     VariableProxy* proxy = initialization_scope->NewUnresolved(factory(), name);
     // Add break location for destructured sub-pattern.
-    int pos = IsSubPattern() ? pattern->position() : RelocInfo::kNoPosition;
+    int pos = IsSubPattern() ? pattern->position() : value->position();
     Assignment* assignment =
         factory()->NewAssignment(Token::INIT, proxy, value, pos);
     block_->statements()->Add(
@@ -365,7 +364,7 @@
   PatternContext old_context = SetAssignmentContextIfNeeded(initializer);
   int pos = assign->position();
   Block* old_block = block_;
-  block_ = factory()->NewBlock(nullptr, 8, false, pos);
+  block_ = factory()->NewBlock(nullptr, 8, true, pos);
   Variable* temp = nullptr;
   Expression* pattern = assign->target();
   Expression* old_value = current_value_;
@@ -414,16 +413,27 @@
 
 void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node,
                                                 Variable** temp_var) {
+  DCHECK(block_->ignore_completion_value());
+
   auto temp = *temp_var = CreateTempVar(current_value_);
-
-  block_->statements()->Add(parser_->BuildAssertIsCoercible(temp), zone());
-
   auto iterator = CreateTempVar(parser_->GetIterator(
       factory()->NewVariableProxy(temp), factory(), RelocInfo::kNoPosition));
   auto done = CreateTempVar(
       factory()->NewBooleanLiteral(false, RelocInfo::kNoPosition));
   auto result = CreateTempVar();
   auto v = CreateTempVar();
+  auto completion = CreateTempVar();
+  auto nopos = RelocInfo::kNoPosition;
+
+  // For the purpose of iterator finalization, we temporarily set block_ to a
+  // new block.  In the main body of this function, we write to block_ (both
+  // explicitly and implicitly via recursion).  At the end of the function, we
+  // wrap this new block in a try-finally statement, restore block_ to its
+  // original value, and add the try-finally statement to block_.
+  auto target = block_;
+  if (FLAG_harmony_iterator_close) {
+    block_ = factory()->NewBlock(nullptr, 8, true, nopos);
+  }
 
   Spread* spread = nullptr;
   for (Expression* value : *node->values()) {
@@ -433,88 +443,201 @@
     }
 
     PatternContext context = SetInitializerContextIfNeeded(value);
+
     // if (!done) {
+    //   done = true;  // If .next, .done or .value throws, don't close.
     //   result = IteratorNext(iterator);
-    //   v = (done = result.done) ? undefined : result.value;
+    //   if (result.done) {
+    //     v = undefined;
+    //   } else {
+    //     v = result.value;
+    //     done = false;
+    //   }
     // }
-    auto next_block =
-        factory()->NewBlock(nullptr, 2, true, RelocInfo::kNoPosition);
-    next_block->statements()->Add(factory()->NewExpressionStatement(
-                                      parser_->BuildIteratorNextResult(
-                                          factory()->NewVariableProxy(iterator),
-                                          result, RelocInfo::kNoPosition),
+    Statement* if_not_done;
+    {
+      auto result_done = factory()->NewProperty(
+          factory()->NewVariableProxy(result),
+          factory()->NewStringLiteral(ast_value_factory()->done_string(),
                                       RelocInfo::kNoPosition),
-                                  zone());
+          RelocInfo::kNoPosition);
 
-    auto assign_to_done = factory()->NewAssignment(
-        Token::ASSIGN, factory()->NewVariableProxy(done),
-        factory()->NewProperty(
-            factory()->NewVariableProxy(result),
-            factory()->NewStringLiteral(ast_value_factory()->done_string(),
-                                        RelocInfo::kNoPosition),
-            RelocInfo::kNoPosition),
-        RelocInfo::kNoPosition);
-    auto next_value = factory()->NewConditional(
-        assign_to_done, factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
-        factory()->NewProperty(
-            factory()->NewVariableProxy(result),
-            factory()->NewStringLiteral(ast_value_factory()->value_string(),
-                                        RelocInfo::kNoPosition),
-            RelocInfo::kNoPosition),
-        RelocInfo::kNoPosition);
-    next_block->statements()->Add(
-        factory()->NewExpressionStatement(
-            factory()->NewAssignment(Token::ASSIGN,
-                                     factory()->NewVariableProxy(v), next_value,
-                                     RelocInfo::kNoPosition),
-            RelocInfo::kNoPosition),
-        zone());
+      auto assign_undefined = factory()->NewAssignment(
+          Token::ASSIGN, factory()->NewVariableProxy(v),
+          factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
+          RelocInfo::kNoPosition);
 
-    auto if_statement = factory()->NewIfStatement(
-        factory()->NewUnaryOperation(Token::NOT,
-                                     factory()->NewVariableProxy(done),
-                                     RelocInfo::kNoPosition),
-        next_block, factory()->NewEmptyStatement(RelocInfo::kNoPosition),
-        RelocInfo::kNoPosition);
-    block_->statements()->Add(if_statement, zone());
+      auto assign_value = factory()->NewAssignment(
+          Token::ASSIGN, factory()->NewVariableProxy(v),
+          factory()->NewProperty(
+              factory()->NewVariableProxy(result),
+              factory()->NewStringLiteral(ast_value_factory()->value_string(),
+                                          RelocInfo::kNoPosition),
+              RelocInfo::kNoPosition),
+          RelocInfo::kNoPosition);
+
+      auto unset_done = factory()->NewAssignment(
+          Token::ASSIGN, factory()->NewVariableProxy(done),
+          factory()->NewBooleanLiteral(false, RelocInfo::kNoPosition),
+          RelocInfo::kNoPosition);
+
+      auto inner_else =
+          factory()->NewBlock(nullptr, 2, true, RelocInfo::kNoPosition);
+      inner_else->statements()->Add(
+          factory()->NewExpressionStatement(assign_value, nopos), zone());
+      inner_else->statements()->Add(
+          factory()->NewExpressionStatement(unset_done, nopos), zone());
+
+      auto inner_if = factory()->NewIfStatement(
+          result_done,
+          factory()->NewExpressionStatement(assign_undefined, nopos),
+          inner_else, nopos);
+
+      auto next_block =
+          factory()->NewBlock(nullptr, 3, true, RelocInfo::kNoPosition);
+      next_block->statements()->Add(
+          factory()->NewExpressionStatement(
+              factory()->NewAssignment(
+                  Token::ASSIGN, factory()->NewVariableProxy(done),
+                  factory()->NewBooleanLiteral(true, nopos), nopos),
+              nopos),
+          zone());
+      next_block->statements()->Add(
+          factory()->NewExpressionStatement(
+              parser_->BuildIteratorNextResult(
+                  factory()->NewVariableProxy(iterator), result,
+                  RelocInfo::kNoPosition),
+              RelocInfo::kNoPosition),
+          zone());
+      next_block->statements()->Add(inner_if, zone());
+
+      if_not_done = factory()->NewIfStatement(
+          factory()->NewUnaryOperation(Token::NOT,
+                                       factory()->NewVariableProxy(done),
+                                       RelocInfo::kNoPosition),
+          next_block, factory()->NewEmptyStatement(RelocInfo::kNoPosition),
+          RelocInfo::kNoPosition);
+    }
+    block_->statements()->Add(if_not_done, zone());
 
     if (!(value->IsLiteral() && value->AsLiteral()->raw_value()->IsTheHole())) {
+      if (FLAG_harmony_iterator_close) {
+        // completion = kAbruptCompletion;
+        Expression* proxy = factory()->NewVariableProxy(completion);
+        Expression* assignment = factory()->NewAssignment(
+            Token::ASSIGN, proxy,
+            factory()->NewSmiLiteral(kAbruptCompletion, nopos), nopos);
+        block_->statements()->Add(
+            factory()->NewExpressionStatement(assignment, nopos), zone());
+      }
+
       RecurseIntoSubpattern(value, factory()->NewVariableProxy(v));
+
+      if (FLAG_harmony_iterator_close) {
+        // completion = kNormalCompletion;
+        Expression* proxy = factory()->NewVariableProxy(completion);
+        Expression* assignment = factory()->NewAssignment(
+            Token::ASSIGN, proxy,
+            factory()->NewSmiLiteral(kNormalCompletion, nopos), nopos);
+        block_->statements()->Add(
+            factory()->NewExpressionStatement(assignment, nopos), zone());
+      }
     }
     set_context(context);
   }
 
   if (spread != nullptr) {
-    // array = [];
-    // if (!done) %concat_iterable_to_array(array, iterator);
-    auto empty_exprs = new (zone()) ZoneList<Expression*>(0, zone());
-    auto array = CreateTempVar(factory()->NewArrayLiteral(
-        empty_exprs,
-        // Reuse pattern's literal index - it is unused since there is no
-        // actual literal allocated.
-        node->literal_index(), is_strong(scope()->language_mode()),
-        RelocInfo::kNoPosition));
+    // A spread can only occur as the last component.  It is not handled by
+    // RecurseIntoSubpattern above.
 
-    auto arguments = new (zone()) ZoneList<Expression*>(2, zone());
-    arguments->Add(factory()->NewVariableProxy(array), zone());
-    arguments->Add(factory()->NewVariableProxy(iterator), zone());
-    auto spread_into_array_call =
-        factory()->NewCallRuntime(Context::CONCAT_ITERABLE_TO_ARRAY_INDEX,
-                                  arguments, RelocInfo::kNoPosition);
+    // let array = [];
+    // while (!done) {
+    //   result = IteratorNext(iterator);
+    //   if (result.done) {
+    //     done = true;
+    //   } else {
+    //     %AppendElement(array, result.value);
+    //   }
+    // }
 
-    auto if_statement = factory()->NewIfStatement(
-        factory()->NewUnaryOperation(Token::NOT,
-                                     factory()->NewVariableProxy(done),
-                                     RelocInfo::kNoPosition),
-        factory()->NewExpressionStatement(spread_into_array_call,
-                                          RelocInfo::kNoPosition),
-        factory()->NewEmptyStatement(RelocInfo::kNoPosition),
-        RelocInfo::kNoPosition);
-    block_->statements()->Add(if_statement, zone());
+    // let array = [];
+    Variable* array;
+    {
+      auto empty_exprs = new (zone()) ZoneList<Expression*>(0, zone());
+      array = CreateTempVar(factory()->NewArrayLiteral(
+          empty_exprs,
+          // Reuse pattern's literal index - it is unused since there is no
+          // actual literal allocated.
+          node->literal_index(), RelocInfo::kNoPosition));
+    }
 
+    // result = IteratorNext(iterator);
+    Statement* get_next = factory()->NewExpressionStatement(
+        parser_->BuildIteratorNextResult(factory()->NewVariableProxy(iterator),
+                                         result, nopos),
+        nopos);
+
+    // done = true;
+    Statement* set_done = factory()->NewExpressionStatement(
+        factory()->NewAssignment(
+            Token::ASSIGN, factory()->NewVariableProxy(done),
+            factory()->NewBooleanLiteral(true, nopos), nopos),
+        nopos);
+
+    // %AppendElement(array, result.value);
+    Statement* append_element;
+    {
+      auto args = new (zone()) ZoneList<Expression*>(2, zone());
+      args->Add(factory()->NewVariableProxy(array), zone());
+      args->Add(factory()->NewProperty(
+                    factory()->NewVariableProxy(result),
+                    factory()->NewStringLiteral(
+                        ast_value_factory()->value_string(), nopos),
+                    nopos),
+                zone());
+      append_element = factory()->NewExpressionStatement(
+          factory()->NewCallRuntime(Runtime::kAppendElement, args, nopos),
+          nopos);
+    }
+
+    // if (result.done) { #set_done } else { #append_element }
+    Statement* set_done_or_append;
+    {
+      Expression* result_done =
+          factory()->NewProperty(factory()->NewVariableProxy(result),
+                                 factory()->NewStringLiteral(
+                                     ast_value_factory()->done_string(), nopos),
+                                 nopos);
+      set_done_or_append = factory()->NewIfStatement(result_done, set_done,
+                                                     append_element, nopos);
+    }
+
+    // while (!done) {
+    //   #get_next;
+    //   #set_done_or_append;
+    // }
+    WhileStatement* loop = factory()->NewWhileStatement(nullptr, nopos);
+    {
+      Expression* condition = factory()->NewUnaryOperation(
+          Token::NOT, factory()->NewVariableProxy(done), nopos);
+      Block* body = factory()->NewBlock(nullptr, 2, true, nopos);
+      body->statements()->Add(get_next, zone());
+      body->statements()->Add(set_done_or_append, zone());
+      loop->Initialize(condition, body);
+    }
+
+    block_->statements()->Add(loop, zone());
     RecurseIntoSubpattern(spread->expression(),
                           factory()->NewVariableProxy(array));
   }
+
+  if (FLAG_harmony_iterator_close) {
+    Expression* closing_condition = factory()->NewUnaryOperation(
+        Token::NOT, factory()->NewVariableProxy(done), nopos);
+    parser_->FinalizeIteratorUse(completion, closing_condition, iterator,
+                                 block_, target);
+    block_ = target;
+  }
 }