Revision: 19215
Author:   [email protected]
Date:     Mon Feb 10 09:01:23 2014 UTC
Log:      Version 3.24.35 (based on bleeding_edge revision r19214)

Fix inconsistencies wrt whitespaces (issue 3109).

Performance and stability improvements on all platforms.
http://code.google.com/p/v8/source/detail?r=19215

Added:
 /trunk/src/zone-allocator.h
 /trunk/src/zone-containers.h
Modified:
 /trunk/ChangeLog
 /trunk/include/v8.h
 /trunk/src/heap-inl.h
 /trunk/src/heap.cc
 /trunk/src/heap.h
 /trunk/src/hydrogen-gvn.cc
 /trunk/src/hydrogen-gvn.h
 /trunk/src/list.h
 /trunk/src/parser.cc
 /trunk/src/parser.h
 /trunk/src/preparser.cc
 /trunk/src/preparser.h
 /trunk/src/utils.h
 /trunk/src/version.cc
 /trunk/src/x64/codegen-x64.cc
 /trunk/src/x64/lithium-codegen-x64.cc
 /trunk/src/x64/macro-assembler-x64.h
 /trunk/test/cctest/test-api.cc
 /trunk/test/cctest/test-parsing.cc

=======================================
--- /dev/null
+++ /trunk/src/zone-allocator.h Mon Feb 10 09:01:23 2014 UTC
@@ -0,0 +1,80 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_ZONE_ALLOCATOR_H_
+#define V8_ZONE_ALLOCATOR_H_
+
+#include "zone.h"
+
+namespace v8 {
+namespace internal {
+
+template<typename T>
+class zone_allocator {
+ public:
+  typedef T* pointer;
+  typedef const T* const_pointer;
+  typedef T& reference;
+  typedef const T& const_reference;
+  typedef T value_type;
+  typedef size_t size_type;
+  typedef ptrdiff_t difference_type;
+  template<class O> struct rebind {
+    typedef zone_allocator<O> other;
+  };
+
+  explicit zone_allocator(Zone* zone) throw() : zone_(zone) {}
+  explicit zone_allocator(const zone_allocator& other) throw()
+      : zone_(other.zone_) {}
+  template<typename U> zone_allocator(const zone_allocator<U>&) throw() {}
+
+  pointer address(reference x) const {return &x;}
+  const_pointer address(const_reference x) const {return &x;}
+
+  pointer allocate(size_type count, const void* hint = 0) {
+    size_t size = count * sizeof(value_type);
+    size = RoundUp(size, kPointerSize);
+    return static_cast<pointer>(zone_->New(size));
+  }
+  void deallocate(pointer p, size_type) { /* noop for Zones */ }
+
+  size_type max_size() const throw() {
+    size_type max = static_cast<size_type>(-1) / sizeof(T);
+    return (max > 0 ? max : 1);
+  }
+  void construct(pointer p, const T& val) {
+    new(static_cast<void*>(p)) T(val);
+  }
+  void destroy(pointer p) { (static_cast<T*>(p))->~T(); }
+
+ private:
+  Zone* zone_;
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_ZONE_ALLOCATOR_H_
=======================================
--- /dev/null
+++ /trunk/src/zone-containers.h        Mon Feb 10 09:01:23 2014 UTC
@@ -0,0 +1,46 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_ZONE_CONTAINERS_H_
+#define V8_ZONE_CONTAINERS_H_
+
+#include <vector>
+#include <set>
+
+#include "zone.h"
+
+namespace v8 {
+namespace internal {
+
+typedef zone_allocator<int> ZoneIntAllocator;
+typedef std::vector<int, ZoneIntAllocator> IntVector;
+typedef IntVector::iterator IntVectorIter;
+typedef IntVector::reverse_iterator IntVectorRIter;
+
+} }  // namespace v8::internal
+
+#endif  // V8_ZONE_CONTAINERS_H_
=======================================
--- /trunk/ChangeLog    Fri Feb  7 09:11:16 2014 UTC
+++ /trunk/ChangeLog    Mon Feb 10 09:01:23 2014 UTC
@@ -1,3 +1,10 @@
+2014-02-10: Version 3.24.35
+
+        Fix inconsistencies wrt whitespaces (issue 3109).
+
+        Performance and stability improvements on all platforms.
+
+
 2014-02-07: Version 3.24.34

         Performance and stability improvements on all platforms.
=======================================
--- /trunk/include/v8.h Fri Jan 31 14:01:53 2014 UTC
+++ /trunk/include/v8.h Mon Feb 10 09:01:23 2014 UTC
@@ -5398,7 +5398,7 @@
   static const int kNullValueRootIndex = 7;
   static const int kTrueValueRootIndex = 8;
   static const int kFalseValueRootIndex = 9;
-  static const int kEmptyStringRootIndex = 146;
+  static const int kEmptyStringRootIndex = 147;

   static const int kNodeClassIdOffset = 1 * kApiPointerSize;
   static const int kNodeFlagsOffset = 1 * kApiPointerSize + 3;
=======================================
--- /trunk/src/heap-inl.h       Thu Feb  6 01:06:18 2014 UTC
+++ /trunk/src/heap-inl.h       Mon Feb 10 09:01:23 2014 UTC
@@ -517,12 +517,8 @@
   AllocationMemento* memento = AllocationMemento::cast(candidate);
   if (!memento->IsValid()) return;

-  if (memento->GetAllocationSite()->IncrementMementoFoundCount() &&
-      heap->allocation_sites_scratchpad_length <
-      kAllocationSiteScratchpadSize) {
-    heap->allocation_sites_scratchpad[
-        heap->allocation_sites_scratchpad_length++] =
-        memento->GetAllocationSite();
+  if (memento->GetAllocationSite()->IncrementMementoFoundCount()) {
+    heap->AddAllocationSiteToScratchpad(memento->GetAllocationSite());
   }
 }

=======================================
--- /trunk/src/heap.cc  Fri Feb  7 09:11:16 2014 UTC
+++ /trunk/src/heap.cc  Mon Feb 10 09:01:23 2014 UTC
@@ -150,7 +150,7 @@
 #ifdef VERIFY_HEAP
       no_weak_object_verification_scope_depth_(0),
 #endif
-      allocation_sites_scratchpad_length(0),
+      allocation_sites_scratchpad_length_(0),
       promotion_queue_(this),
       configured_(false),
       external_string_table_(this),
@@ -516,16 +516,17 @@
     // If the scratchpad overflowed, we have to iterate over the allocation
     // sites list.
     bool use_scratchpad =
-        allocation_sites_scratchpad_length < kAllocationSiteScratchpadSize;
+ allocation_sites_scratchpad_length_ < kAllocationSiteScratchpadSize;

     int i = 0;
     Object* list_element = allocation_sites_list();
     bool trigger_deoptimization = false;
     while (use_scratchpad ?
-              i < allocation_sites_scratchpad_length :
+              i < allocation_sites_scratchpad_length_ :
               list_element->IsAllocationSite()) {
       AllocationSite* site = use_scratchpad ?
- allocation_sites_scratchpad[i] : AllocationSite::cast(list_element);
+          AllocationSite::cast(allocation_sites_scratchpad()->get(i)) :
+          AllocationSite::cast(list_element);
       allocation_mementos_found += site->memento_found_count();
       if (site->memento_found_count() > 0) {
         active_allocation_sites++;
@@ -546,7 +547,7 @@

     if (trigger_deoptimization) isolate_->stack_guard()->DeoptMarkedCode();

-    allocation_sites_scratchpad_length = 0;
+    FlushAllocationSitesScratchpad();

     if (FLAG_trace_pretenuring_statistics &&
         (allocation_mementos_found > 0 ||
@@ -3300,6 +3301,12 @@
   // Handling of script id generation is in Factory::NewScript.
   set_last_script_id(Smi::FromInt(v8::Script::kNoScriptId));

+  { MaybeObject* maybe_obj = AllocateAllocationSitesScratchpad();
+    if (!maybe_obj->ToObject(&obj)) return false;
+  }
+  set_allocation_sites_scratchpad(FixedArray::cast(obj));
+  InitializeAllocationSitesScratchpad();
+
   // Initialize keyed lookup cache.
   isolate_->keyed_lookup_cache()->Clear();

@@ -3587,6 +3594,39 @@
   if (!maybe->To<Object>(&number)) return maybe;
   return NumberToString(number, check_number_string_cache);
 }
+
+
+MaybeObject* Heap::AllocateAllocationSitesScratchpad() {
+  MaybeObject* maybe_obj =
+      AllocateFixedArray(kAllocationSiteScratchpadSize, TENURED);
+  return maybe_obj;
+}
+
+
+void Heap::FlushAllocationSitesScratchpad() {
+  for (int i = 0; i < allocation_sites_scratchpad_length_; i++) {
+    allocation_sites_scratchpad()->set_undefined(i);
+  }
+  allocation_sites_scratchpad_length_ = 0;
+}
+
+
+void Heap::InitializeAllocationSitesScratchpad() {
+  ASSERT(allocation_sites_scratchpad()->length() ==
+         kAllocationSiteScratchpadSize);
+  for (int i = 0; i < kAllocationSiteScratchpadSize; i++) {
+    allocation_sites_scratchpad()->set_undefined(i);
+  }
+}
+
+
+void Heap::AddAllocationSiteToScratchpad(AllocationSite* site) {
+ if (allocation_sites_scratchpad_length_ < kAllocationSiteScratchpadSize) {
+    allocation_sites_scratchpad()->set(
+        allocation_sites_scratchpad_length_, site);
+    allocation_sites_scratchpad_length_++;
+  }
+}


 Map* Heap::MapForExternalArrayType(ExternalArrayType array_type) {
=======================================
--- /trunk/src/heap.h   Wed Feb  5 03:04:56 2014 UTC
+++ /trunk/src/heap.h   Mon Feb 10 09:01:23 2014 UTC
@@ -202,7 +202,8 @@
V(SeededNumberDictionary, empty_slow_element_dictionary, \ EmptySlowElementDictionary) \ V(Symbol, observed_symbol, ObservedSymbol) \
-  V(FixedArray, materialized_objects, MaterializedObjects)
+ V(FixedArray, materialized_objects, MaterializedObjects) \
+  V(FixedArray, allocation_sites_scratchpad, AllocationSitesScratchpad)

 #define ROOT_LIST(V)                                  \
   STRONG_ROOT_LIST(V)                                 \
@@ -2285,6 +2286,18 @@
   // Flush the number to string cache.
   void FlushNumberStringCache();

+  // Allocates a fixed-size allocation sites scratchpad.
+  MUST_USE_RESULT MaybeObject* AllocateAllocationSitesScratchpad();
+
+  // Sets used allocation sites entries to undefined.
+  void FlushAllocationSitesScratchpad();
+
+  // Initializes the allocation sites scratchpad with undefined values.
+  void InitializeAllocationSitesScratchpad();
+
+  // Adds an allocation site to the scratchpad if there is space left.
+  void AddAllocationSiteToScratchpad(AllocationSite* site);
+
   void UpdateSurvivalRateTrend(int start_new_space_size);

   enum SurvivalRateTrend { INCREASING, STABLE, DECREASING, FLUCTUATING };
@@ -2457,10 +2470,8 @@
   int no_weak_object_verification_scope_depth_;
 #endif

-
   static const int kAllocationSiteScratchpadSize = 256;
-  int allocation_sites_scratchpad_length;
- AllocationSite* allocation_sites_scratchpad[kAllocationSiteScratchpadSize];
+  int allocation_sites_scratchpad_length_;

   static const int kMaxMarkSweepsInIdleRound = 7;
   static const int kIdleScavengeThreshold = 5;
=======================================
--- /trunk/src/hydrogen-gvn.cc  Fri Feb  7 09:11:16 2014 UTC
+++ /trunk/src/hydrogen-gvn.cc  Mon Feb 10 09:01:23 2014 UTC
@@ -535,13 +535,9 @@
                   block->block_id(),
                   GetGVNFlagsString(side_effects).get());

-      GVNFlagSet accumulated_first_time_depends;
-      GVNFlagSet accumulated_first_time_changes;
       HBasicBlock* last = block->loop_information()->GetLastBackEdge();
       for (int j = block->block_id(); j <= last->block_id(); ++j) {
-        ProcessLoopBlock(graph()->blocks()->at(j), block, side_effects,
-                         &accumulated_first_time_depends,
-                         &accumulated_first_time_changes);
+        ProcessLoopBlock(graph()->blocks()->at(j), block, side_effects);
       }
     }
   }
@@ -551,9 +547,7 @@
 void HGlobalValueNumberingPhase::ProcessLoopBlock(
     HBasicBlock* block,
     HBasicBlock* loop_header,
-    GVNFlagSet loop_kills,
-    GVNFlagSet* first_time_depends,
-    GVNFlagSet* first_time_changes) {
+    GVNFlagSet loop_kills) {
   HBasicBlock* pre_header = loop_header->predecessors()->at(0);
GVNFlagSet depends_flags = HValue::ConvertChangesToDependsFlags(loop_kills);
   TRACE_GVN_2("Loop invariant motion for B%d %s\n",
@@ -562,7 +556,6 @@
   HInstruction* instr = block->first();
   while (instr != NULL) {
     HInstruction* next = instr->next();
-    bool hoisted = false;
     if (instr->CheckFlag(HValue::kUseGVN)) {
       TRACE_GVN_4("Checking instruction %d (%s) %s. Loop %s\n",
                   instr->id(),
@@ -589,26 +582,9 @@
           instr->Unlink();
           instr->InsertBefore(pre_header->end());
           if (instr->HasSideEffects()) removed_side_effects_ = true;
-          hoisted = true;
         }
       }
     }
-    if (!hoisted) {
-      // If an instruction is not hoisted, we have to account for its side
-      // effects when hoisting later HTransitionElementsKind instructions.
-      GVNFlagSet previous_depends = *first_time_depends;
-      GVNFlagSet previous_changes = *first_time_changes;
-      first_time_depends->Add(instr->DependsOnFlags());
-      first_time_changes->Add(instr->ChangesFlags());
-      if (!(previous_depends == *first_time_depends)) {
-        TRACE_GVN_1("Updated first-time accumulated %s\n",
-                    GetGVNFlagsString(*first_time_depends).get());
-      }
-      if (!(previous_changes == *first_time_changes)) {
-        TRACE_GVN_1("Updated first-time accumulated %s\n",
-                    GetGVNFlagsString(*first_time_changes).get());
-      }
-    }
     instr = next;
   }
 }
=======================================
--- /trunk/src/hydrogen-gvn.h   Fri Feb  7 09:11:16 2014 UTC
+++ /trunk/src/hydrogen-gvn.h   Mon Feb 10 09:01:23 2014 UTC
@@ -52,9 +52,7 @@
   void LoopInvariantCodeMotion();
   void ProcessLoopBlock(HBasicBlock* block,
                         HBasicBlock* before_loop,
-                        GVNFlagSet loop_kills,
-                        GVNFlagSet* accumulated_first_time_depends,
-                        GVNFlagSet* accumulated_first_time_changes);
+                        GVNFlagSet loop_kills);
   bool AllowCodeMotion();
   bool ShouldMove(HInstruction* instr, HBasicBlock* loop_header);

=======================================
--- /trunk/src/list.h   Wed Jan 22 10:50:56 2014 UTC
+++ /trunk/src/list.h   Mon Feb 10 09:01:23 2014 UTC
@@ -90,6 +90,10 @@
   inline T& at(int i) const { return operator[](i); }
   inline T& last() const { return at(length_ - 1); }
   inline T& first() const { return at(0); }
+
+  typedef T* iterator;
+  inline iterator begin() const { return &data_[0]; }
+  inline iterator end() const { return &data_[length_]; }

   INLINE(bool is_empty() const) { return length_ == 0; }
   INLINE(int length() const) { return length_; }
=======================================
--- /trunk/src/parser.cc        Fri Feb  7 09:11:16 2014 UTC
+++ /trunk/src/parser.cc        Mon Feb 10 09:01:23 2014 UTC
@@ -2486,23 +2486,21 @@

     Expect(Token::RPAREN, CHECK_OK);

-    if (peek() == Token::LBRACE) {
-      Target target(&this->target_stack_, &catch_collector);
-      VariableMode mode = is_extended_mode() ? LET : VAR;
-      catch_variable =
-          catch_scope->DeclareLocal(name, mode, kCreatedInitialized);
+    Target target(&this->target_stack_, &catch_collector);
+    VariableMode mode = is_extended_mode() ? LET : VAR;
+    catch_variable =
+        catch_scope->DeclareLocal(name, mode, kCreatedInitialized);

-      BlockState block_state(this, catch_scope);
-      catch_block = ParseBlock(NULL, CHECK_OK);
-    } else {
-      Expect(Token::LBRACE, CHECK_OK);
-    }
+    BlockState block_state(this, catch_scope);
+    catch_block = ParseBlock(NULL, CHECK_OK);
+
     catch_scope->set_end_position(scanner().location().end_pos);
     tok = peek();
   }

   Block* finally_block = NULL;
-  if (tok == Token::FINALLY || catch_block == NULL) {
+  ASSERT(tok == Token::FINALLY || catch_block != NULL);
+  if (tok == Token::FINALLY) {
     Consume(Token::FINALLY);
     finally_block = ParseBlock(NULL, CHECK_OK);
   }
@@ -3388,7 +3386,7 @@
   // Parse the initial primary or function expression.
   Expression* result = NULL;
   if (peek() == Token::FUNCTION) {
-    Expect(Token::FUNCTION, CHECK_OK);
+    Consume(Token::FUNCTION);
     int function_token_position = position();
     bool is_generator = allow_generators() && Check(Token::MUL);
     Handle<String> name;
@@ -4068,8 +4066,12 @@
     //    '(' (Identifier)*[','] ')'
     Expect(Token::LPAREN, CHECK_OK);
     scope->set_start_position(scanner().location().beg_pos);
-    Scanner::Location name_loc = Scanner::Location::invalid();
-    Scanner::Location dupe_loc = Scanner::Location::invalid();
+
+    // We don't yet know if the function will be strict, so we cannot yet
+ // produce errors for parameter names or duplicates. However, we remember + // the locations of these errors if they occur and produce the errors later.
+    Scanner::Location eval_args_error_log = Scanner::Location::invalid();
+    Scanner::Location dupe_error_loc = Scanner::Location::invalid();
     Scanner::Location reserved_loc = Scanner::Location::invalid();

     bool done = (peek() == Token::RPAREN);
@@ -4079,16 +4081,16 @@
ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);

       // Store locations for possible future error reports.
-      if (!name_loc.IsValid() && IsEvalOrArguments(param_name)) {
-        name_loc = scanner().location();
-      }
-      if (!dupe_loc.IsValid() && top_scope_->IsDeclared(param_name)) {
-        duplicate_parameters = FunctionLiteral::kHasDuplicateParameters;
-        dupe_loc = scanner().location();
+ if (!eval_args_error_log.IsValid() && IsEvalOrArguments(param_name)) {
+        eval_args_error_log = scanner().location();
       }
       if (!reserved_loc.IsValid() && is_strict_reserved) {
         reserved_loc = scanner().location();
       }
+ if (!dupe_error_loc.IsValid() && top_scope_->IsDeclared(param_name)) {
+        duplicate_parameters = FunctionLiteral::kHasDuplicateParameters;
+        dupe_error_loc = scanner().location();
+      }

       top_scope_->DeclareParameter(param_name, VAR);
       num_parameters++;
@@ -4256,7 +4258,8 @@
       scope->set_end_position(scanner().location().end_pos);
     }

-    // Validate strict mode.
+ // Validate strict mode. We can do this only after parsing the function,
+    // since the function can declare itself strict.
     if (!top_scope_->is_classic_mode()) {
       if (IsEvalOrArguments(function_name)) {
         ReportMessageAt(function_name_location,
@@ -4265,20 +4268,20 @@
         *ok = false;
         return NULL;
       }
-      if (name_loc.IsValid()) {
-        ReportMessageAt(name_loc, "strict_eval_arguments",
+      if (name_is_strict_reserved) {
+ ReportMessageAt(function_name_location, "unexpected_strict_reserved",
                         Vector<const char*>::empty());
         *ok = false;
         return NULL;
       }
-      if (dupe_loc.IsValid()) {
-        ReportMessageAt(dupe_loc, "strict_param_dupe",
+      if (eval_args_error_log.IsValid()) {
+        ReportMessageAt(eval_args_error_log, "strict_eval_arguments",
                         Vector<const char*>::empty());
         *ok = false;
         return NULL;
       }
-      if (name_is_strict_reserved) {
- ReportMessageAt(function_name_location, "unexpected_strict_reserved",
+      if (dupe_error_loc.IsValid()) {
+        ReportMessageAt(dupe_error_loc, "strict_param_dupe",
                         Vector<const char*>::empty());
         *ok = false;
         return NULL;
=======================================
--- /trunk/src/parser.h Fri Feb  7 09:11:16 2014 UTC
+++ /trunk/src/parser.h Mon Feb 10 09:01:23 2014 UTC
@@ -649,9 +649,9 @@

   ZoneList<Expression*>* ParseArguments(bool* ok);
   FunctionLiteral* ParseFunctionLiteral(
-      Handle<String> var_name,
+      Handle<String> name,
       Scanner::Location function_name_location,
-      bool name_is_reserved,
+      bool name_is_strict_reserved,
       bool is_generator,
       int function_token_position,
       FunctionLiteral::FunctionType type,
=======================================
--- /trunk/src/preparser.cc     Fri Feb  7 09:11:16 2014 UTC
+++ /trunk/src/preparser.cc     Mon Feb 10 09:01:23 2014 UTC
@@ -75,9 +75,6 @@
     if (!scope_->is_classic_mode()) {
       int end_pos = scanner()->location().end_pos;
       CheckOctalLiteral(start_position, end_pos, &ok);
-      if (ok) {
-        CheckDelayedStrictModeViolation(start_position, end_pos, &ok);
-      }
     }
   }
   return kPreParseSuccess;
@@ -265,25 +262,14 @@
   Expect(Token::FUNCTION, CHECK_OK);

   bool is_generator = allow_generators() && Check(Token::MUL);
- Identifier identifier = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
-  Scanner::Location location = scanner()->location();
-
-  Expression function_value = ParseFunctionLiteral(is_generator, CHECK_OK);
-
- // If we're in strict mode, ParseIdentifier will catch using eval, arguments - // or a strict reserved word as function name. However, if only the function
-  // is strict, we need to do an extra check.
-  if (function_value.IsStrictFunction() &&
-      !identifier.IsValidStrictVariable()) {
-    // Strict mode violation, using either reserved word or eval/arguments
-    // as name of strict function.
-    const char* type = "strict_eval_arguments";
-    if (identifier.IsFutureStrictReserved() || identifier.IsYield()) {
-      type = "unexpected_strict_reserved";
-    }
-    ReportMessageAt(location, type, NULL);
-    *ok = false;
-  }
+  bool is_strict_reserved = false;
+  Identifier name = ParseIdentifierOrStrictReservedWord(
+      &is_strict_reserved, CHECK_OK);
+  ParseFunctionLiteral(name,
+                       scanner()->location(),
+                       is_strict_reserved,
+                       is_generator,
+                       CHECK_OK);
   return Statement::FunctionDeclaration();
 }

@@ -713,15 +699,17 @@
   // Finally ::
   //   'finally' Block

- // In preparsing, allow any number of catch/finally blocks, including zero
-  // of both.
-
   Expect(Token::TRY, CHECK_OK);

   ParseBlock(CHECK_OK);

-  bool catch_or_finally_seen = false;
-  if (peek() == Token::CATCH) {
+  Token::Value tok = peek();
+  if (tok != Token::CATCH && tok != Token::FINALLY) {
+    ReportMessageAt(scanner()->location(), "no_catch_or_finally", NULL);
+    *ok = false;
+    return Statement::Default();
+  }
+  if (tok == Token::CATCH) {
     Consume(Token::CATCH);
     Expect(Token::LPAREN, CHECK_OK);
     ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
@@ -729,15 +717,11 @@
     { Scope::InsideWith iw(scope_);
       ParseBlock(CHECK_OK);
     }
-    catch_or_finally_seen = true;
+    tok = peek();
   }
-  if (peek() == Token::FINALLY) {
+  if (tok == Token::FINALLY) {
     Consume(Token::FINALLY);
     ParseBlock(CHECK_OK);
-    catch_or_finally_seen = true;
-  }
-  if (!catch_or_finally_seen) {
-    *ok = false;
   }
   return Statement::Default();
 }
@@ -1021,20 +1005,19 @@
     Consume(Token::FUNCTION);

     bool is_generator = allow_generators() && Check(Token::MUL);
-    Identifier identifier = Identifier::Default();
+    Identifier name = Identifier::Default();
+    bool is_strict_reserved_name = false;
+ Scanner::Location function_name_location = Scanner::Location::invalid();
     if (peek_any_identifier()) {
-      identifier = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
+      name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name,
+                                                 CHECK_OK);
+      function_name_location = scanner()->location();
     }
-    result = ParseFunctionLiteral(is_generator, CHECK_OK);
- // If we're in strict mode, ParseIdentifier will catch using eval, arguments - // or a strict reserved word as function name. However, if only the function
-    // is strict, we need to do an extra check.
-    if (result.IsStrictFunction() && !identifier.IsValidStrictVariable()) {
-      StrictModeIdentifierViolation(scanner()->location(),
-                                    identifier,
-                                    ok);
-      return Expression::Default();
-    }
+    result = ParseFunctionLiteral(name,
+                                  function_name_location,
+                                  is_strict_reserved_name,
+                                  is_generator,
+                                  CHECK_OK);
   } else {
     result = ParsePrimaryExpression(CHECK_OK);
   }
@@ -1216,7 +1199,11 @@
             }
PropertyKind type = is_getter ? kGetterProperty : kSetterProperty;
             checker.CheckProperty(name, type, CHECK_OK);
-            ParseFunctionLiteral(false, CHECK_OK);
+            ParseFunctionLiteral(Identifier::Default(),
+                                 scanner()->location(),
+                                 false,  // reserved words are allowed here
+                                 false,  // not a generator
+                                 CHECK_OK);
             if (peek() != Token::RBRACE) {
               Expect(Token::COMMA, CHECK_OK);
             }
@@ -1302,9 +1289,12 @@
   return argc;
 }

-
-PreParser::Expression PreParser::ParseFunctionLiteral(bool is_generator,
-                                                      bool* ok) {
+PreParser::Expression PreParser::ParseFunctionLiteral(
+    Identifier function_name,
+    Scanner::Location function_name_location,
+    bool name_is_strict_reserved,
+    bool is_generator,
+    bool* ok) {
   // Function ::
   //   '(' FormalParameterList? ')' '{' FunctionBody '}'

@@ -1319,8 +1309,23 @@
   int start_position = position();
   bool done = (peek() == Token::RPAREN);
   DuplicateFinder duplicate_finder(scanner()->unicode_cache());
+ // We don't yet know if the function will be strict, so we cannot yet produce
+  // errors for parameter names or duplicates. However, we remember the
+  // locations of these errors if they occur and produce the errors later.
+  Scanner::Location eval_args_error_loc = Scanner::Location::invalid();
+  Scanner::Location dupe_error_loc = Scanner::Location::invalid();
+  Scanner::Location reserved_error_loc = Scanner::Location::invalid();
   while (!done) {
-    ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
+    bool is_strict_reserved = false;
+    Identifier param_name =
+        ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
+    if (!eval_args_error_loc.IsValid() && param_name.IsEvalOrArguments()) {
+      eval_args_error_loc = scanner()->location();
+    }
+    if (!reserved_error_loc.IsValid() && is_strict_reserved) {
+      reserved_error_loc = scanner()->location();
+    }
+
     int prev_value;
     if (scanner()->is_literal_ascii()) {
       prev_value =
@@ -1330,11 +1335,10 @@
duplicate_finder.AddUtf16Symbol(scanner()->literal_utf16_string(), 1);
     }

-    if (prev_value != 0) {
-      SetStrictModeViolation(scanner()->location(),
-                             "strict_param_dupe",
-                             CHECK_OK);
+    if (!dupe_error_loc.IsValid() && prev_value != 0) {
+      dupe_error_loc = scanner()->location();
     }
+
     done = (peek() == Token::RPAREN);
     if (!done) {
       Expect(Token::COMMA, CHECK_OK);
@@ -1358,10 +1362,41 @@
   }
   Expect(Token::RBRACE, CHECK_OK);

+  // Validate strict mode. We can do this only after parsing the function,
+  // since the function can declare itself strict.
   if (!scope_->is_classic_mode()) {
+    if (function_name.IsEvalOrArguments()) {
+ ReportMessageAt(function_name_location, "strict_eval_arguments", NULL);
+      *ok = false;
+      return Expression::Default();
+    }
+    if (name_is_strict_reserved) {
+      ReportMessageAt(
+          function_name_location, "unexpected_strict_reserved", NULL);
+      *ok = false;
+      return Expression::Default();
+    }
+    if (eval_args_error_loc.IsValid()) {
+      ReportMessageAt(eval_args_error_loc, "strict_eval_arguments",
+                      Vector<const char*>::empty());
+      *ok = false;
+      return Expression::Default();
+    }
+    if (dupe_error_loc.IsValid()) {
+      ReportMessageAt(dupe_error_loc, "strict_param_dupe",
+                      Vector<const char*>::empty());
+      *ok = false;
+      return Expression::Default();
+    }
+    if (reserved_error_loc.IsValid()) {
+      ReportMessageAt(reserved_error_loc, "unexpected_strict_reserved",
+                      Vector<const char*>::empty());
+      *ok = false;
+      return Expression::Default();
+    }
+
     int end_position = scanner()->location().end_pos;
     CheckOctalLiteral(start_position, end_position, CHECK_OK);
- CheckDelayedStrictModeViolation(start_position, end_position, CHECK_OK);
     return Expression::StrictFunction();
   }

@@ -1467,7 +1502,8 @@
     PreParser::Identifier name = GetIdentifierSymbol();
     if (allow_eval_or_arguments == kDontAllowEvalOrArguments &&
         !scope_->is_classic_mode() && name.IsEvalOrArguments()) {
-      StrictModeIdentifierViolation(scanner()->location(), name, ok);
+ ReportMessageAt(scanner()->location(), "strict_eval_arguments", NULL);
+      *ok = false;
     }
     return name;
   } else if (scope_->is_classic_mode() &&
@@ -1482,55 +1518,22 @@
 }


-void PreParser::SetStrictModeViolation(Scanner::Location location,
-                                       const char* type,
-                                       bool* ok) {
-  if (!scope_->is_classic_mode()) {
-    ReportMessageAt(location, type, NULL);
-    *ok = false;
-    return;
-  }
-  // Delay report in case this later turns out to be strict code
-  // (i.e., for function names and parameters prior to a "use strict"
-  // directive).
-  // It's safe to overwrite an existing violation.
-  // It's either from a function that turned out to be non-strict,
-  // or it's in the current function (and we just need to report
-  // one error), or it's in a unclosed nesting function that wasn't
-  // strict (otherwise we would already be in strict mode).
-  strict_mode_violation_location_ = location;
-  strict_mode_violation_type_ = type;
-}
-
-
-void PreParser::CheckDelayedStrictModeViolation(int beg_pos,
-                                                int end_pos,
-                                                bool* ok) {
-  Scanner::Location location = strict_mode_violation_location_;
-  if (location.IsValid() &&
-      location.beg_pos > beg_pos && location.end_pos < end_pos) {
-    ReportMessageAt(location, strict_mode_violation_type_, NULL);
-    *ok = false;
-  }
-}
-
-
-void PreParser::StrictModeIdentifierViolation(Scanner::Location location,
-                                              Identifier identifier,
-                                              bool* ok) {
-  const char* type = "strict_eval_arguments";
-  if (identifier.IsFutureReserved()) {
-    type = "unexpected_reserved";
-  } else if (identifier.IsFutureStrictReserved() || identifier.IsYield()) {
-    type = "unexpected_strict_reserved";
-  }
-  if (!scope_->is_classic_mode()) {
-    ReportMessageAt(location, type, NULL);
+// Parses and identifier or a strict mode future reserved word, and indicate
+// whether it is strict mode future reserved.
+PreParser::Identifier PreParser::ParseIdentifierOrStrictReservedWord(
+    bool* is_strict_reserved, bool* ok) {
+  Token::Value next = Next();
+  if (next == Token::IDENTIFIER) {
+    *is_strict_reserved = false;
+  } else if (next == Token::FUTURE_STRICT_RESERVED_WORD ||
+             (next == Token::YIELD && !scope_->is_generator())) {
+    *is_strict_reserved = true;
+  } else {
+    ReportUnexpectedToken(next);
     *ok = false;
-    return;
+    return Identifier::Default();
   }
-  strict_mode_violation_location_ = location;
-  strict_mode_violation_type_ = type;
+  return GetIdentifierSymbol();
 }


=======================================
--- /trunk/src/preparser.h      Fri Feb  7 09:11:16 2014 UTC
+++ /trunk/src/preparser.h      Mon Feb 10 09:01:23 2014 UTC
@@ -243,8 +243,6 @@
       : ParserBase(scanner, stack_limit),
         log_(log),
         scope_(NULL),
-        strict_mode_violation_location_(Scanner::Location::invalid()),
-        strict_mode_violation_type_(NULL),
         parenthesized_function_(false) { }

   ~PreParser() {}
@@ -616,10 +614,17 @@
   Expression ParseV8Intrinsic(bool* ok);

   Arguments ParseArguments(bool* ok);
-  Expression ParseFunctionLiteral(bool is_generator, bool* ok);
+  Expression ParseFunctionLiteral(
+      Identifier name,
+      Scanner::Location function_name_location,
+      bool name_is_strict_reserved,
+      bool is_generator,
+      bool* ok);
   void ParseLazyFunctionLiteralBody(bool* ok);

   Identifier ParseIdentifier(AllowEvalOrArgumentsAsIdentifier, bool* ok);
+  Identifier ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved,
+                                                 bool* ok);
   Identifier ParseIdentifierName(bool* ok);
   Identifier ParseIdentifierNameOrGetOrSet(bool* is_get,
                                            bool* is_set,
@@ -648,20 +653,8 @@

   bool CheckInOrOf(bool accept_OF);

-  void SetStrictModeViolation(Scanner::Location,
-                              const char* type,
-                              bool* ok);
-
-  void CheckDelayedStrictModeViolation(int beg_pos, int end_pos, bool* ok);
-
-  void StrictModeIdentifierViolation(Scanner::Location,
-                                     Identifier identifier,
-                                     bool* ok);
-
   ParserRecorder* log_;
   Scope* scope_;
-  Scanner::Location strict_mode_violation_location_;
-  const char* strict_mode_violation_type_;
   bool parenthesized_function_;
 };

=======================================
--- /trunk/src/utils.h  Wed Jan 15 10:29:52 2014 UTC
+++ /trunk/src/utils.h  Mon Feb 10 09:01:23 2014 UTC
@@ -1140,6 +1140,21 @@
   int id_;
 };

+
+template <class C>
+class ContainerPointerWrapper {
+ public:
+  typedef typename C::iterator iterator;
+  typedef typename C::reverse_iterator reverse_iterator;
+  explicit ContainerPointerWrapper(C* container) : container_(container) {}
+  iterator begin() { return container_->begin(); }
+  iterator end() { return container_->end(); }
+  reverse_iterator rbegin() { return container_->rbegin(); }
+  reverse_iterator rend() { return container_->rend(); }
+ private:
+  C* container_;
+};
+
 } }  // namespace v8::internal

 #endif  // V8_UTILS_H_
=======================================
--- /trunk/src/version.cc       Fri Feb  7 09:11:16 2014 UTC
+++ /trunk/src/version.cc       Mon Feb 10 09:01:23 2014 UTC
@@ -34,7 +34,7 @@
 // system so their names cannot be changed without changing the scripts.
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     24
-#define BUILD_NUMBER      34
+#define BUILD_NUMBER      35
 #define PATCH_LEVEL       0
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
=======================================
--- /trunk/src/x64/codegen-x64.cc       Mon Jan 27 01:05:32 2014 UTC
+++ /trunk/src/x64/codegen-x64.cc       Mon Feb 10 09:01:23 2014 UTC
@@ -422,7 +422,7 @@
   // Non-hole double, copy value into a heap number.
   __ AllocateHeapNumber(rax, r15, &gc_required);
   // rax: new heap number
-  __ MoveDouble(FieldOperand(rax, HeapNumber::kValueOffset), r14);
+  __ movq(FieldOperand(rax, HeapNumber::kValueOffset), r14);
   __ movp(FieldOperand(r11,
                        r9,
                        times_pointer_size,
=======================================
--- /trunk/src/x64/lithium-codegen-x64.cc       Sat Feb  1 08:54:43 2014 UTC
+++ /trunk/src/x64/lithium-codegen-x64.cc       Mon Feb 10 09:01:23 2014 UTC
@@ -3417,10 +3417,10 @@
   __ LoadFromSafepointRegisterSlot(input_reg, input_reg);

   __ bind(&allocated);
-  __ MoveDouble(tmp2, FieldOperand(input_reg, HeapNumber::kValueOffset));
+  __ movq(tmp2, FieldOperand(input_reg, HeapNumber::kValueOffset));
   __ shl(tmp2, Immediate(1));
   __ shr(tmp2, Immediate(1));
-  __ MoveDouble(FieldOperand(tmp, HeapNumber::kValueOffset), tmp2);
+  __ movq(FieldOperand(tmp, HeapNumber::kValueOffset), tmp2);
   __ StoreToSafepointRegisterSlot(input_reg, tmp);

   __ bind(&done);
=======================================
--- /trunk/src/x64/macro-assembler-x64.h        Tue Jan 28 07:51:38 2014 UTC
+++ /trunk/src/x64/macro-assembler-x64.h        Mon Feb 10 09:01:23 2014 UTC
@@ -841,9 +841,6 @@
   void Pop(Register dst) { pop(dst); }
   void PushReturnAddressFrom(Register src) { push(src); }
   void PopReturnAddressTo(Register dst) { pop(dst); }
-  void MoveDouble(Register dst, const Operand& src) { movq(dst, src); }
-  void MoveDouble(const Operand& dst, Register src) { movq(dst, src); }
-
   void Move(Register dst, ExternalReference ext) {
     movp(dst, reinterpret_cast<Address>(ext.address()),
          RelocInfo::EXTERNAL_REFERENCE);
=======================================
--- /trunk/test/cctest/test-api.cc      Fri Feb  7 09:11:16 2014 UTC
+++ /trunk/test/cctest/test-api.cc      Mon Feb 10 09:01:23 2014 UTC
@@ -7044,28 +7044,6 @@
   CHECK(context.IsEmpty());
   CHECK_NE(last_location, NULL);
 }
-
-
-static const char* js_code_causing_huge_string_flattening =
-    "var str = 'X';"
-    "for (var i = 0; i < 30; i++) {"
-    "  str = str + str;"
-    "}"
-    "str.match(/X/);";
-
-
-TEST(RegexpOutOfMemory) {
-  // Execute a script that causes out of memory when flattening a string.
-  v8::HandleScope scope(CcTest::isolate());
-  v8::V8::SetFatalErrorHandler(OOMCallback);
-  LocalContext context;
-  Local<Script> script = Script::Compile(String::NewFromUtf8(
-      CcTest::isolate(), js_code_causing_huge_string_flattening));
-  last_location = NULL;
-  script->Run();
-
-  CHECK(false);  // Should not return.
-}


static void MissingScriptInfoMessageListener(v8::Handle<v8::Message> message,
@@ -7084,93 +7062,6 @@
   Script::Compile(v8_str("throw Error()"))->Run();
   v8::V8::RemoveMessageListeners(MissingScriptInfoMessageListener);
 }
-
-
-int global_index = 0;
-
-template<typename T>
-class Snorkel {
- public:
-  explicit Snorkel(v8::Persistent<T>* handle) : handle_(handle) {
-    index_ = global_index++;
-  }
-  v8::Persistent<T>* handle_;
-  int index_;
-};
-
-class Whammy {
- public:
-  explicit Whammy(v8::Isolate* isolate) : cursor_(0), isolate_(isolate) { }
-  ~Whammy() { script_.Reset(); }
-  v8::Handle<Script> getScript() {
- if (script_.IsEmpty()) script_.Reset(isolate_, v8_compile("({}).blammo"));
-    return Local<Script>::New(isolate_, script_);
-  }
-
- public:
-  static const int kObjectCount = 256;
-  int cursor_;
-  v8::Isolate* isolate_;
-  v8::Persistent<v8::Object> objects_[kObjectCount];
-  v8::Persistent<Script> script_;
-};
-
-static void HandleWeakReference(
-    const v8::WeakCallbackData<v8::Value, Snorkel<v8::Value> >& data) {
-  data.GetParameter()->handle_->ClearWeak();
-  delete data.GetParameter();
-}
-
-void WhammyPropertyGetter(Local<String> name,
- const v8::PropertyCallbackInfo<v8::Value>& info) {
-  Whammy* whammy =
- static_cast<Whammy*>(v8::Handle<v8::External>::Cast(info.Data())->Value());
-
-  v8::Persistent<v8::Object>& prev = whammy->objects_[whammy->cursor_];
-
-  v8::Handle<v8::Object> obj = v8::Object::New(info.GetIsolate());
-  if (!prev.IsEmpty()) {
-    v8::Local<v8::Object>::New(info.GetIsolate(), prev)
-        ->Set(v8_str("next"), obj);
- prev.SetWeak<Value, Snorkel<Value> >(new Snorkel<Value>(&prev.As<Value>()),
-                                         &HandleWeakReference);
-  }
-  whammy->objects_[whammy->cursor_].Reset(info.GetIsolate(), obj);
-  whammy->cursor_ = (whammy->cursor_ + 1) % Whammy::kObjectCount;
-  info.GetReturnValue().Set(whammy->getScript()->Run());
-}
-
-
-TEST(WeakReference) {
-  i::FLAG_expose_gc = true;
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope handle_scope(isolate);
-  v8::Handle<v8::ObjectTemplate> templ= v8::ObjectTemplate::New(isolate);
-  Whammy* whammy = new Whammy(CcTest::isolate());
-  templ->SetNamedPropertyHandler(WhammyPropertyGetter,
-                                 0, 0, 0, 0,
- v8::External::New(CcTest::isolate(), whammy));
-  const char* extension_list[] = { "v8/gc" };
-  v8::ExtensionConfiguration extensions(1, extension_list);
-  v8::Handle<Context> context =
-      Context::New(CcTest::isolate(), &extensions);
-  Context::Scope context_scope(context);
-
-  v8::Handle<v8::Object> interceptor = templ->NewInstance();
-  context->Global()->Set(v8_str("whammy"), interceptor);
-  const char* code =
-      "var last;"
-      "for (var i = 0; i < 10000; i++) {"
-      "  var obj = whammy.length;"
-      "  if (last) last.next = obj;"
-      "  last = obj;"
-      "}"
-      "gc();"
-      "4";
-  v8::Handle<Value> result = CompileRun(code);
-  CHECK_EQ(4.0, result->NumberValue());
-  delete whammy;
-}


 struct FlagAndPersistent {
@@ -14934,6 +14825,7 @@

   delete sd;
   delete deserialized_sd;
+  i::DeleteArray(serialized_data);
 }


@@ -14982,6 +14874,7 @@
            *exception_value);

   try_catch.Reset();
+  delete sd;

   // Overwrite function bar's start position with 200.  The function entry
   // will not be found when searching for it by position and we should fall
@@ -15298,6 +15191,7 @@
   timeout_thread.Join();

   regexp_interruption_data.string.Reset();
+  i::DeleteArray(uc16_content);
 }

 #endif  // V8_INTERPRETED_REGEXP
@@ -19156,18 +19050,20 @@

 UNINITIALIZED_TEST(DisposeIsolateWhenInUse) {
   v8::Isolate* isolate = v8::Isolate::New();
-  CHECK(isolate);
-  isolate->Enter();
-  v8::HandleScope scope(isolate);
-  LocalContext context(isolate);
-  // Run something in this isolate.
-  ExpectTrue("true");
-  v8::V8::SetFatalErrorHandler(StoringErrorCallback);
-  last_location = last_message = NULL;
-  // Still entered, should fail.
+  {
+    v8::Isolate::Scope i_scope(isolate);
+    v8::HandleScope scope(isolate);
+    LocalContext context(isolate);
+    // Run something in this isolate.
+    ExpectTrue("true");
+    v8::V8::SetFatalErrorHandler(StoringErrorCallback);
+    last_location = last_message = NULL;
+    // Still entered, should fail.
+    isolate->Dispose();
+    CHECK_NE(last_location, NULL);
+    CHECK_NE(last_message, NULL);
+  }
   isolate->Dispose();
-  CHECK_NE(last_location, NULL);
-  CHECK_NE(last_message, NULL);
 }


@@ -19382,6 +19278,7 @@
     CHECK(v->IsNumber());
     CHECK_EQ(22, static_cast<int>(v->NumberValue()));
   }
+  isolate->Dispose();
 }

 class InitDefaultIsolateThread : public v8::internal::Thread {
=======================================
--- /trunk/test/cctest/test-parsing.cc  Fri Feb  7 09:11:16 2014 UTC
+++ /trunk/test/cctest/test-parsing.cc  Mon Feb 10 09:01:23 2014 UTC
@@ -1874,3 +1874,142 @@

   RunParserSyncTest(context_data, statement_data, kSuccess);
 }
+
+
+TEST(DontRegressPreParserDataSizes) {
+ // These tests make sure that PreParser doesn't start producing less data.
+
+  v8::V8::Initialize();
+
+  int marker;
+  CcTest::i_isolate()->stack_guard()->SetStackLimit(
+      reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
+
+  struct TestCase {
+    const char* program;
+    int symbols;
+    int functions;
+  } test_cases[] = {
+    // Labels, variables and functions are recorded as symbols.
+    {"{label: 42}", 1, 0}, {"{label: 42; label2: 43}", 2, 0},
+    {"var x = 42;", 1, 0}, {"var x = 42, y = 43;", 2, 0},
+ {"function foo() {}", 1, 1}, {"function foo() {} function bar() {}", 2, 2}, + // Labels, variables and functions insize lazy functions are not recorded.
+    {"function lazy() { var a, b, c; }", 1, 1},
+    {"function lazy() { a: 1; b: 2; c: 3; }", 1, 1},
+ {"function lazy() { function a() {} function b() {} function c() {} }", 1,
+     1},
+    {NULL, 0, 0}
+  };
+  // Each function adds 5 elements to the preparse function data.
+  const int kDataPerFunction = 5;
+
+ uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
+  for (int i = 0; test_cases[i].program; i++) {
+    const char* program = test_cases[i].program;
+    i::Utf8ToUtf16CharacterStream stream(
+        reinterpret_cast<const i::byte*>(program),
+        static_cast<unsigned>(strlen(program)));
+    i::CompleteParserRecorder log;
+    i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
+    scanner.Initialize(&stream);
+
+    i::PreParser preparser(&scanner, &log, stack_limit);
+    preparser.set_allow_lazy(true);
+    preparser.set_allow_natives_syntax(true);
+    i::PreParser::PreParseResult result = preparser.PreParseProgram();
+    CHECK_EQ(i::PreParser::kPreParseSuccess, result);
+    if (log.symbol_ids() != test_cases[i].symbols) {
+      i::OS::Print(
+          "Expected preparse data for program:\n"
+          "\t%s\n"
+          "to contain %d symbols, however, received %d symbols.\n",
+          program, test_cases[i].symbols, log.symbol_ids());
+      CHECK(false);
+    }
+ if (log.function_position() != test_cases[i].functions * kDataPerFunction) {
+      i::OS::Print(
+          "Expected preparse data for program:\n"
+          "\t%s\n"
+          "to contain %d functions, however, received %d functions.\n",
+          program, test_cases[i].functions,
+          log.function_position() / kDataPerFunction);
+      CHECK(false);
+    }
+    i::ScriptDataImpl data(log.ExtractData());
+    CHECK(!data.has_error());
+  }
+}
+
+
+TEST(FunctionDeclaresItselfStrict) {
+ // Tests that we produce the right kinds of errors when a function declares
+  // itself strict (we cannot produce there errors as soon as we see the
+  // offending identifiers, because we don't know at that point whether the
+  // function is strict or not).
+  const char* context_data[][2] = {
+    {"function eval() {", "}"},
+    {"function arguments() {", "}"},
+    {"function yield() {", "}"},
+    {"function interface() {", "}"},
+    {"function foo(eval) {", "}"},
+    {"function foo(arguments) {", "}"},
+    {"function foo(yield) {", "}"},
+    {"function foo(interface) {", "}"},
+    {"function foo(bar, eval) {", "}"},
+    {"function foo(bar, arguments) {", "}"},
+    {"function foo(bar, yield) {", "}"},
+    {"function foo(bar, interface) {", "}"},
+    {"function foo(bar, bar) {", "}"},
+    { NULL, NULL }
+  };
+
+  const char* strict_statement_data[] = {
+    "\"use strict\";",
+    NULL
+  };
+
+  const char* non_strict_statement_data[] = {
+    ";",
+    NULL
+  };
+
+  RunParserSyncTest(context_data, strict_statement_data, kError);
+  RunParserSyncTest(context_data, non_strict_statement_data, kSuccess);
+}
+
+
+TEST(ErrorsTryWithoutCatchOrFinally) {
+  const char* context_data[][2] = {
+    {"", ""},
+    { NULL, NULL }
+  };
+
+  const char* statement_data[] = {
+    "try { }",
+    "try { } foo();",
+    "try { } catch (e) foo();",
+    "try { } catch { }",
+    "try { } finally foo();",
+    NULL
+  };
+
+  RunParserSyncTest(context_data, statement_data, kError);
+}
+
+
+TEST(NoErrorsTryCatchFinally) {
+  const char* context_data[][2] = {
+    {"", ""},
+    { NULL, NULL }
+  };
+
+  const char* statement_data[] = {
+    "try { } catch (e) { }",
+    "try { } catch (e) { } finally { }",
+    "try { } finally { }",
+    NULL
+  };
+
+  RunParserSyncTest(context_data, statement_data, kSuccess);
+}

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to