Revision: 10621
Author:   [email protected]
Date:     Tue Feb  7 04:07:34 2012
Log:      Version 3.9.3

When rethrowing an exception, print the stack trace of its original site instead of rethrow site (Chromium issue 60240).

Increased size of small stacks from 32k to 64k to avoid hitting limits in Chromium (Chromium issue 112843).
http://code.google.com/p/v8/source/detail?r=10621

Added:
 /trunk/tools/bash-completion.sh
Modified:
 /trunk/ChangeLog
 /trunk/include/v8-profiler.h
 /trunk/src/cpu-profiler.cc
 /trunk/src/d8.cc
 /trunk/src/flag-definitions.h
 /trunk/src/handles.cc
 /trunk/src/heap.h
 /trunk/src/incremental-marking.cc
 /trunk/src/isolate.cc
 /trunk/src/isolate.h
 /trunk/src/list-inl.h
 /trunk/src/mark-compact.cc
 /trunk/src/mark-compact.h
 /trunk/src/messages.js
 /trunk/src/objects.cc
 /trunk/src/objects.h
 /trunk/src/platform-freebsd.cc
 /trunk/src/platform-linux.cc
 /trunk/src/platform-macos.cc
 /trunk/src/platform-openbsd.cc
 /trunk/src/platform-solaris.cc
 /trunk/src/platform-win32.cc
 /trunk/src/profile-generator.cc
 /trunk/src/profile-generator.h
 /trunk/src/property-details.h
 /trunk/src/property.h
 /trunk/src/runtime.cc
 /trunk/src/runtime.h
 /trunk/src/version.cc
 /trunk/src/x64/lithium-codegen-x64.cc
 /trunk/test/cctest/test-api.cc
 /trunk/test/cctest/test-heap-profiler.cc
 /trunk/test/cctest/test-mark-compact.cc
 /trunk/test/mjsunit/array-join.js
 /trunk/test/mjsunit/string-replace-one-char.js

=======================================
--- /dev/null
+++ /trunk/tools/bash-completion.sh     Tue Feb  7 04:07:34 2012
@@ -0,0 +1,55 @@
+#!/bin/bash
+# Copyright 2012 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.
+
+# Inspired by and based on:
+# http://src.chromium.org/viewvc/chrome/trunk/src/tools/bash-completion
+
+# Flag completion rule for bash.
+# To load in your shell, "source path/to/this/file".
+
+v8_source=$(readlink -f $(dirname $BASH_SOURCE)/..)
+
+_v8_flag() {
+  local cur defines targets
+  cur="${COMP_WORDS[COMP_CWORD]}"
+  defines=$(cat src/flag-definitions.h \
+    | grep "^DEFINE" \
+    | grep -v "DEFINE_implication" \
+    | sed -e 's/_/-/g')
+  targets=$(echo "$defines" \
+    | sed -ne 's/^DEFINE-[^(]*(\([^,]*\).*/--\1/p'; \
+    echo "$defines" \
+    | sed -ne 's/^DEFINE-bool(\([^,]*\).*/--no\1/p'; \
+    cat src/d8.cc \
+    | grep "strcmp(argv\[i\]" \
+    | sed -ne 's/^[^"]*"--\([^"]*\)".*/--\1/p')
+  COMPREPLY=($(compgen -W "$targets" -- "$cur"))
+  return 0
+}
+
+complete -F _v8_flag d8
=======================================
--- /trunk/ChangeLog    Mon Feb  6 02:12:55 2012
+++ /trunk/ChangeLog    Tue Feb  7 04:07:34 2012
@@ -1,3 +1,12 @@
+2012-02-07: Version 3.9.3
+
+        When rethrowing an exception, print the stack trace of its original
+        site instead of rethrow site (Chromium issue 60240).
+
+ Increased size of small stacks from 32k to 64k to avoid hitting limits
+        in Chromium (Chromium issue 112843).
+
+
 2012-02-06: Version 3.9.2

         Add timestamp to --trace-gc output. (issue 1932)
=======================================
--- /trunk/include/v8-profiler.h        Wed Feb  1 02:48:36 2012
+++ /trunk/include/v8-profiler.h        Tue Feb  7 04:07:34 2012
@@ -255,7 +255,9 @@
     kClosure = 5,     // Function closure.
     kRegExp = 6,      // RegExp.
     kHeapNumber = 7,  // Number stored in the heap.
-    kNative = 8       // Native object (not from V8 heap).
+    kNative = 8,      // Native object (not from V8 heap).
+    kSynthetic = 9    // Synthetic object, usualy used for grouping
+                      // snapshot items together.
   };

   /** Returns node type (see HeapGraphNode::Type). */
=======================================
--- /trunk/src/cpu-profiler.cc  Wed Jan 25 23:37:54 2012
+++ /trunk/src/cpu-profiler.cc  Tue Feb  7 04:07:34 2012
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2012 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:
@@ -42,7 +42,7 @@
 static const int kEventsBufferSize = 256 * KB;
 static const int kTickSamplesBufferChunkSize = 64 * KB;
 static const int kTickSamplesBufferChunksCount = 16;
-static const int kProfilerStackSize = 32 * KB;
+static const int kProfilerStackSize = 64 * KB;


ProfilerEventsProcessor::ProfilerEventsProcessor(ProfileGenerator* generator)
=======================================
--- /trunk/src/d8.cc    Thu Feb  2 08:21:15 2012
+++ /trunk/src/d8.cc    Tue Feb  7 04:07:34 2012
@@ -1288,7 +1288,7 @@
       options.use_preemption = true;
       argv[i] = NULL;
 #endif  // V8_SHARED
-    } else if (strcmp(argv[i], "--no-preemption") == 0) {
+    } else if (strcmp(argv[i], "--nopreemption") == 0) {
 #ifdef V8_SHARED
       printf("D8 with shared library does not support multi-threading\n");
       return false;
=======================================
--- /trunk/src/flag-definitions.h       Mon Feb  6 02:12:55 2012
+++ /trunk/src/flag-definitions.h       Tue Feb  7 04:07:34 2012
@@ -307,7 +307,8 @@
             "Flush code caches in maps during mark compact cycle.")
 DEFINE_bool(never_compact, false,
             "Never perform compaction on full GC - testing only")
-DEFINE_bool(compact_code_space, false, "Compact code space")
+DEFINE_bool(compact_code_space, false,
+            "Compact code space on full non-incremental collections")
 DEFINE_bool(cleanup_code_caches_at_gc, true,
             "Flush inline caches prior to mark compact collection and "
             "flush code caches in maps during mark compact cycle.")
=======================================
--- /trunk/src/handles.cc       Mon Jan 16 03:42:08 2012
+++ /trunk/src/handles.cc       Tue Feb  7 04:07:34 2012
@@ -711,7 +711,7 @@
                                 isolate);
     }
     isolate->counters()->enum_cache_misses()->Increment();
-    int num_enum = object->NumberOfEnumProperties();
+    int num_enum = object->NumberOfLocalProperties(DONT_ENUM);
Handle<FixedArray> storage = isolate->factory()->NewFixedArray(num_enum); Handle<FixedArray> sort_array = isolate->factory()->NewFixedArray(num_enum);
     Handle<DescriptorArray> descs =
@@ -735,7 +735,7 @@
     ASSERT(storage->length() == index);
     return storage;
   } else {
-    int num_enum = object->NumberOfEnumProperties();
+    int num_enum = object->NumberOfLocalProperties(DONT_ENUM);
Handle<FixedArray> storage = isolate->factory()->NewFixedArray(num_enum); Handle<FixedArray> sort_array = isolate->factory()->NewFixedArray(num_enum);
     object->property_dictionary()->CopyEnumKeysTo(*storage, *sort_array);
=======================================
--- /trunk/src/heap.h   Mon Feb  6 02:12:55 2012
+++ /trunk/src/heap.h   Tue Feb  7 04:07:34 2012
@@ -241,9 +241,10 @@
   V(use_strict, "use strict")                                            \
   V(dot_symbol, ".")                                                     \
   V(anonymous_function_symbol, "(anonymous function)")                   \
-  V(compare_ic_symbol, ".compare_ic")                                   \
+  V(compare_ic_symbol, ".compare_ic")                                    \
   V(infinity_symbol, "Infinity")                                         \
-  V(minus_infinity_symbol, "-Infinity")
+  V(minus_infinity_symbol, "-Infinity")                                  \
+  V(hidden_stack_trace_symbol, "v8::hidden_stack_trace")

 // Forward declarations.
 class GCTracer;
=======================================
--- /trunk/src/incremental-marking.cc   Thu Jan 19 07:36:35 2012
+++ /trunk/src/incremental-marking.cc   Tue Feb  7 04:07:34 2012
@@ -505,7 +505,8 @@
   }

   is_compacting_ = !FLAG_never_compact && (flag == ALLOW_COMPACTION) &&
-      heap_->mark_compact_collector()->StartCompaction();
+      heap_->mark_compact_collector()->StartCompaction(
+          MarkCompactCollector::INCREMENTAL_COMPACTION);

   state_ = MARKING;

=======================================
--- /trunk/src/isolate.cc       Mon Feb  6 02:12:55 2012
+++ /trunk/src/isolate.cc       Tue Feb  7 04:07:34 2012
@@ -540,6 +540,18 @@
     return factory()->empty_symbol();
   }
 }
+
+
+void Isolate::CaptureAndSetCurrentStackTraceFor(Handle<JSObject> error_object) {
+  if (capture_stack_trace_for_uncaught_exceptions_) {
+    // Capture stack trace for a detailed exception message.
+    Handle<String> key = factory()->hidden_stack_trace_symbol();
+    Handle<JSArray> stack_trace = CaptureCurrentStackTrace(
+        stack_trace_for_uncaught_exceptions_frame_limit_,
+        stack_trace_for_uncaught_exceptions_options_);
+    JSObject::SetHiddenProperty(error_object, key, stack_trace);
+  }
+}


 Handle<JSArray> Isolate::CaptureCurrentStackTrace(
@@ -1037,22 +1049,39 @@
 }


-void Isolate::DoThrow(MaybeObject* exception, MessageLocation* location) {
+bool Isolate::IsErrorObject(Handle<Object> obj) {
+  if (!obj->IsJSObject()) return false;
+
+  String* error_key = *(factory()->LookupAsciiSymbol("$Error"));
+  Object* error_constructor =
+      js_builtins_object()->GetPropertyNoExceptionThrown(error_key);
+
+  for (Object* prototype = *obj; !prototype->IsNull();
+       prototype = prototype->GetPrototype()) {
+    if (!prototype->IsJSObject()) return false;
+ if (JSObject::cast(prototype)->map()->constructor() == error_constructor) {
+      return true;
+    }
+  }
+  return false;
+}
+
+
+void Isolate::DoThrow(Object* exception, MessageLocation* location) {
   ASSERT(!has_pending_exception());

   HandleScope scope;
-  Object* exception_object = Smi::FromInt(0);
-  bool is_object = exception->ToObject(&exception_object);
-  Handle<Object> exception_handle(exception_object);
+  Handle<Object> exception_handle(exception);

   // Determine reporting and whether the exception is caught externally.
   bool catchable_by_javascript = is_catchable_by_javascript(exception);
-  // Only real objects can be caught by JS.
-  ASSERT(!catchable_by_javascript || is_object);
   bool can_be_caught_externally = false;
   bool should_report_exception =
ShouldReportException(&can_be_caught_externally, catchable_by_javascript); bool report_exception = catchable_by_javascript && should_report_exception;
+  bool try_catch_needs_message =
+      can_be_caught_externally && try_catch_handler()->capture_message_;
+  bool bootstrapping = bootstrapper()->IsActive();

 #ifdef ENABLE_DEBUGGER_SUPPORT
   // Notify debugger of exception.
@@ -1061,34 +1090,52 @@
   }
 #endif

-  // Generate the message.
-  Handle<Object> message_obj;
-  MessageLocation potential_computed_location;
-  bool try_catch_needs_message =
-      can_be_caught_externally &&
-      try_catch_handler()->capture_message_;
+  // Generate the message if required.
   if (report_exception || try_catch_needs_message) {
+    MessageLocation potential_computed_location;
     if (location == NULL) {
-      // If no location was specified we use a computed one instead
+      // If no location was specified we use a computed one instead.
       ComputeLocation(&potential_computed_location);
       location = &potential_computed_location;
     }
-    if (!bootstrapper()->IsActive()) {
-      // It's not safe to try to make message objects or collect stack
-      // traces while the bootstrapper is active since the infrastructure
-      // may not have been properly initialized.
+    // It's not safe to try to make message objects or collect stack traces
+ // while the bootstrapper is active since the infrastructure may not have
+    // been properly initialized.
+    if (!bootstrapping) {
       Handle<String> stack_trace;
       if (FLAG_trace_exception) stack_trace = StackTraceString();
       Handle<JSArray> stack_trace_object;
- if (report_exception && capture_stack_trace_for_uncaught_exceptions_) {
+      if (capture_stack_trace_for_uncaught_exceptions_) {
+        if (IsErrorObject(exception_handle)) {
+ // We fetch the stack trace that corresponds to this error object.
+          String* key = heap()->hidden_stack_trace_symbol();
+          Object* stack_property =
+              JSObject::cast(*exception_handle)->GetHiddenProperty(key);
+ // Property lookup may have failed. In this case it's probably not
+          // a valid Error object.
+          if (stack_property->IsJSArray()) {
+ stack_trace_object = Handle<JSArray>(JSArray::cast(stack_property));
+          }
+        }
+        if (stack_trace_object.is_null()) {
+          // Not an error object, we capture at throw site.
           stack_trace_object = CaptureCurrentStackTrace(
               stack_trace_for_uncaught_exceptions_frame_limit_,
               stack_trace_for_uncaught_exceptions_options_);
-      }
- ASSERT(is_object); // Can't use the handle unless there's a real object.
-      message_obj = MessageHandler::MakeMessageObject("uncaught_exception",
- location, HandleVector<Object>(&exception_handle, 1), stack_trace,
+        }
+      }
+      Handle<Object> message_obj = MessageHandler::MakeMessageObject(
+          "uncaught_exception",
+          location,
+          HandleVector<Object>(&exception_handle, 1),
+          stack_trace,
           stack_trace_object);
+      thread_local_top()->pending_message_obj_ = *message_obj;
+      if (location != NULL) {
+        thread_local_top()->pending_message_script_ = *location->script();
+ thread_local_top()->pending_message_start_pos_ = location->start_pos();
+        thread_local_top()->pending_message_end_pos_ = location->end_pos();
+      }
     } else if (location != NULL && !location->script().is_null()) {
       // We are bootstrapping and caught an error where the location is set
       // and we have a script for the location.
@@ -1104,30 +1151,13 @@

   // Save the message for reporting if the the exception remains uncaught.
   thread_local_top()->has_pending_message_ = report_exception;
-  if (!message_obj.is_null()) {
-    thread_local_top()->pending_message_obj_ = *message_obj;
-    if (location != NULL) {
-      thread_local_top()->pending_message_script_ = *location->script();
- thread_local_top()->pending_message_start_pos_ = location->start_pos();
-      thread_local_top()->pending_message_end_pos_ = location->end_pos();
-    }
-  }

   // Do not forget to clean catcher_ if currently thrown exception cannot
   // be caught.  If necessary, ReThrow will update the catcher.
   thread_local_top()->catcher_ = can_be_caught_externally ?
       try_catch_handler() : NULL;

-  // NOTE: Notifying the debugger or generating the message
-  // may have caused new exceptions. For now, we just ignore
-  // that and set the pending exception to the original one.
-  if (is_object) {
-    set_pending_exception(*exception_handle);
-  } else {
- // Failures are not on the heap so they neither need nor work with handles.
-    ASSERT(exception_handle->IsFailure());
-    set_pending_exception(exception);
-  }
+  set_pending_exception(*exception_handle);
 }


=======================================
--- /trunk/src/isolate.h        Mon Feb  6 02:12:55 2012
+++ /trunk/src/isolate.h        Tue Feb  7 04:07:34 2012
@@ -703,6 +703,8 @@
       int frame_limit,
       StackTrace::StackTraceOptions options);

+  void CaptureAndSetCurrentStackTraceFor(Handle<JSObject> error_object);
+
   // Returns if the top context may access the given global object. If
   // the result is false, the pending exception is guaranteed to be
   // set.
@@ -729,7 +731,7 @@

// Promote a scheduled exception to pending. Asserts has_scheduled_exception.
   Failure* PromoteScheduledException();
-  void DoThrow(MaybeObject* exception, MessageLocation* location);
+  void DoThrow(Object* exception, MessageLocation* location);
   // Checks if exception should be reported and finds out if it's
   // caught externally.
   bool ShouldReportException(bool* can_be_caught_externally,
@@ -1141,6 +1143,10 @@

   void InitializeDebugger();

+ // Traverse prototype chain to find out whether the object is derived from
+  // the Error object.
+  bool IsErrorObject(Handle<Object> obj);
+
   int stack_trace_nesting_level_;
   StringStream* incomplete_message_;
   // The preallocated memory thread singleton.
=======================================
--- /trunk/src/list-inl.h       Thu Oct 27 00:38:48 2011
+++ /trunk/src/list-inl.h       Tue Feb  7 04:07:34 2012
@@ -72,9 +72,9 @@
 template<typename T, class P>
 void List<T, P>::ResizeAddInternal(const T& element) {
   ASSERT(length_ >= capacity_);
-  // Grow the list capacity by 50%, but make sure to let it grow
+  // Grow the list capacity by 100%, but make sure to let it grow
   // even when the capacity is zero (possible initial case).
-  int new_capacity = 1 + capacity_ + (capacity_ >> 1);
+  int new_capacity = 1 + 2 * capacity_;
   // Since the element reference could be an element of the list, copy
   // it out of the old backing storage before resizing.
   T temp = element;
=======================================
--- /trunk/src/mark-compact.cc  Mon Feb  6 02:12:55 2012
+++ /trunk/src/mark-compact.cc  Tue Feb  7 04:07:34 2012
@@ -242,14 +242,14 @@
 }


-bool MarkCompactCollector::StartCompaction() {
+bool MarkCompactCollector::StartCompaction(CompactionMode mode) {
   if (!compacting_) {
     ASSERT(evacuation_candidates_.length() == 0);

     CollectEvacuationCandidates(heap()->old_pointer_space());
     CollectEvacuationCandidates(heap()->old_data_space());

-    if (FLAG_compact_code_space) {
+    if (FLAG_compact_code_space && mode == NON_INCREMENTAL_COMPACTION) {
       CollectEvacuationCandidates(heap()->code_space());
     } else if (FLAG_trace_fragmentation) {
       TraceFragmentation(heap()->code_space());
@@ -697,7 +697,7 @@
   // Don't start compaction if we are in the middle of incremental
   // marking cycle. We did not collect any slots.
   if (!FLAG_never_compact && !was_marked_incrementally_) {
-    StartCompaction();
+    StartCompaction(NON_INCREMENTAL_COMPACTION);
   }

   PagedSpaces spaces;
=======================================
--- /trunk/src/mark-compact.h   Mon Feb  6 02:12:55 2012
+++ /trunk/src/mark-compact.h   Tue Feb  7 04:07:34 2012
@@ -441,7 +441,12 @@
   // Performs a global garbage collection.
   void CollectGarbage();

-  bool StartCompaction();
+  enum CompactionMode {
+    INCREMENTAL_COMPACTION,
+    NON_INCREMENTAL_COMPACTION
+  };
+
+  bool StartCompaction(CompactionMode mode);

   void AbortCompaction();

=======================================
--- /trunk/src/messages.js      Tue Dec 13 00:07:27 2011
+++ /trunk/src/messages.js      Tue Feb  7 04:07:34 2012
@@ -1078,9 +1078,9 @@
   if (stackTraceLimit < 0 || stackTraceLimit > 10000) {
     stackTraceLimit = 10000;
   }
-  var raw_stack = %CollectStackTrace(cons_opt
-                                     ? cons_opt
-                                     : captureStackTrace, stackTraceLimit);
+  var raw_stack = %CollectStackTrace(obj,
+ cons_opt ? cons_opt : captureStackTrace,
+                                     stackTraceLimit);
   DefineOneShotAccessor(obj, 'stack', function (obj) {
     return FormatRawStackTrace(obj, raw_stack);
   });
=======================================
--- /trunk/src/objects.cc       Mon Feb  6 02:12:55 2012
+++ /trunk/src/objects.cc       Tue Feb  7 04:07:34 2012
@@ -3773,12 +3773,14 @@
     // code zero) it will always occupy the first entry if present.
     DescriptorArray* descriptors = this->map()->instance_descriptors();
     if ((descriptors->number_of_descriptors() > 0) &&
-        (descriptors->GetKey(0) == GetHeap()->hidden_symbol()) &&
-        descriptors->IsProperty(0)) {
-      ASSERT(descriptors->GetType(0) == FIELD);
-      Object* hidden_store =
-          this->FastPropertyAt(descriptors->GetFieldIndex(0));
-      return StringDictionary::cast(hidden_store);
+        (descriptors->GetKey(0) == GetHeap()->hidden_symbol())) {
+      if (descriptors->GetType(0) == FIELD) {
+        Object* hidden_store =
+            this->FastPropertyAt(descriptors->GetFieldIndex(0));
+        return StringDictionary::cast(hidden_store);
+      } else {
+        ASSERT(descriptors->GetType(0) == MAP_TRANSITION);
+      }
     }
   } else {
     PropertyAttributes attributes;
@@ -3819,11 +3821,13 @@
     // code zero) it will always occupy the first entry if present.
     DescriptorArray* descriptors = this->map()->instance_descriptors();
     if ((descriptors->number_of_descriptors() > 0) &&
-        (descriptors->GetKey(0) == GetHeap()->hidden_symbol()) &&
-        descriptors->IsProperty(0)) {
-      ASSERT(descriptors->GetType(0) == FIELD);
-      this->FastPropertyAtPut(descriptors->GetFieldIndex(0), dictionary);
-      return this;
+        (descriptors->GetKey(0) == GetHeap()->hidden_symbol())) {
+      if (descriptors->GetType(0) == FIELD) {
+        this->FastPropertyAtPut(descriptors->GetFieldIndex(0), dictionary);
+        return this;
+      } else {
+        ASSERT(descriptors->GetType(0) == MAP_TRANSITION);
+      }
     }
   }
   MaybeObject* store_result =
@@ -4247,11 +4251,14 @@
 }


-int Map::NumberOfDescribedProperties() {
+int Map::NumberOfDescribedProperties(PropertyAttributes filter) {
   int result = 0;
   DescriptorArray* descs = instance_descriptors();
   for (int i = 0; i < descs->number_of_descriptors(); i++) {
-    if (descs->IsProperty(i)) result++;
+    PropertyDetails details(descs->GetDetails(i));
+    if (descs->IsProperty(i) && (details.attributes() & filter) == 0) {
+      result++;
+    }
   }
   return result;
 }
@@ -5829,14 +5836,14 @@
   // not be allocated.

   // Compute the size of the map transition entries to be removed.
-  int num_removed = 0;
+  int new_number_of_descriptors = 0;
   for (int i = 0; i < number_of_descriptors(); i++) {
-    if (!IsProperty(i)) num_removed++;
+    if (IsProperty(i)) new_number_of_descriptors++;
   }

   // Allocate the new descriptor array.
   DescriptorArray* new_descriptors;
- { MaybeObject* maybe_result = Allocate(number_of_descriptors() - num_removed);
+  { MaybeObject* maybe_result = Allocate(new_number_of_descriptors);
     if (!maybe_result->To<DescriptorArray>(&new_descriptors)) {
       return maybe_result;
     }
@@ -10355,24 +10362,9 @@


 int JSObject::NumberOfLocalProperties(PropertyAttributes filter) {
-  if (HasFastProperties()) {
-    DescriptorArray* descs = map()->instance_descriptors();
-    int result = 0;
-    for (int i = 0; i < descs->number_of_descriptors(); i++) {
-      PropertyDetails details(descs->GetDetails(i));
-      if (details.IsProperty() && (details.attributes() & filter) == 0) {
-        result++;
-      }
-    }
-    return result;
-  } else {
-    return property_dictionary()->NumberOfElementsFilterAttributes(filter);
-  }
-}
-
-
-int JSObject::NumberOfEnumProperties() {
- return NumberOfLocalProperties(static_cast<PropertyAttributes>(DONT_ENUM));
+  return HasFastProperties() ?
+      map()->NumberOfDescribedProperties(filter) :
+      property_dictionary()->NumberOfElementsFilterAttributes(filter);
 }


@@ -10493,7 +10485,7 @@
// purpose of this function is to provide reflection information for the object
 // mirrors.
 void JSObject::GetLocalPropertyNames(FixedArray* storage, int index) {
-  ASSERT(storage->length() >= (NumberOfLocalProperties(NONE) - index));
+  ASSERT(storage->length() >= (NumberOfLocalProperties() - index));
   if (HasFastProperties()) {
     DescriptorArray* descs = map()->instance_descriptors();
     for (int i = 0; i < descs->number_of_descriptors(); i++) {
=======================================
--- /trunk/src/objects.h        Mon Feb  6 02:12:55 2012
+++ /trunk/src/objects.h        Tue Feb  7 04:07:34 2012
@@ -1638,7 +1638,7 @@
                                           Handle<String> key,
                                           Handle<Object> value);
   // Returns a failure if a GC is required.
-  MaybeObject* SetHiddenProperty(String* key, Object* value);
+ MUST_USE_RESULT MaybeObject* SetHiddenProperty(String* key, Object* value); // Gets the value of a hidden property with the given key. Returns undefined
   // if the property doesn't exist (or if called on a detached proxy),
   // otherwise returns the value set for the key.
@@ -1807,9 +1807,7 @@

// Returns the number of properties on this object filtering out properties
   // with the specified attributes (ignoring interceptors).
-  int NumberOfLocalProperties(PropertyAttributes filter);
-  // Returns the number of enumerable properties (ignoring interceptors).
-  int NumberOfEnumProperties();
+  int NumberOfLocalProperties(PropertyAttributes filter = NONE);
   // Fill in details for properties into storage starting at the specified
   // index.
   void GetLocalPropertyNames(FixedArray* storage, int index);
@@ -4638,8 +4636,9 @@
   // Returns the next free property index (only valid for FAST MODE).
   int NextFreePropertyIndex();

-  // Returns the number of properties described in instance_descriptors.
-  int NumberOfDescribedProperties();
+  // Returns the number of properties described in instance_descriptors
+  // filtering out properties with the specified attributes.
+  int NumberOfDescribedProperties(PropertyAttributes filter = NONE);

   // Casting.
   static inline Map* cast(Object* obj);
=======================================
--- /trunk/src/platform-freebsd.cc      Wed Jan 25 23:37:54 2012
+++ /trunk/src/platform-freebsd.cc      Tue Feb  7 04:07:34 2012
@@ -710,7 +710,7 @@
     FULL_INTERVAL
   };

-  static const int kSignalSenderStackSize = 32 * KB;
+  static const int kSignalSenderStackSize = 64 * KB;

   explicit SignalSender(int interval)
       : Thread(Thread::Options("SignalSender", kSignalSenderStackSize)),
=======================================
--- /trunk/src/platform-linux.cc        Wed Feb  1 02:48:36 2012
+++ /trunk/src/platform-linux.cc        Tue Feb  7 04:07:34 2012
@@ -1060,7 +1060,7 @@
     FULL_INTERVAL
   };

-  static const int kSignalSenderStackSize = 32 * KB;
+  static const int kSignalSenderStackSize = 64 * KB;

   explicit SignalSender(int interval)
       : Thread(Thread::Options("SignalSender", kSignalSenderStackSize)),
=======================================
--- /trunk/src/platform-macos.cc        Wed Jan 25 23:37:54 2012
+++ /trunk/src/platform-macos.cc        Tue Feb  7 04:07:34 2012
@@ -733,7 +733,7 @@

 class SamplerThread : public Thread {
  public:
-  static const int kSamplerThreadStackSize = 32 * KB;
+  static const int kSamplerThreadStackSize = 64 * KB;

   explicit SamplerThread(int interval)
       : Thread(Thread::Options("SamplerThread", kSamplerThreadStackSize)),
=======================================
--- /trunk/src/platform-openbsd.cc      Wed Jan 25 23:37:54 2012
+++ /trunk/src/platform-openbsd.cc      Tue Feb  7 04:07:34 2012
@@ -782,7 +782,7 @@
     FULL_INTERVAL
   };

-  static const int kSignalSenderStackSize = 32 * KB;
+  static const int kSignalSenderStackSize = 64 * KB;

   explicit SignalSender(int interval)
       : Thread(Thread::Options("SignalSender", kSignalSenderStackSize)),
=======================================
--- /trunk/src/platform-solaris.cc      Wed Jan 25 23:37:54 2012
+++ /trunk/src/platform-solaris.cc      Tue Feb  7 04:07:34 2012
@@ -704,7 +704,7 @@
     FULL_INTERVAL
   };

-  static const int kSignalSenderStackSize = 32 * KB;
+  static const int kSignalSenderStackSize = 64 * KB;

   explicit SignalSender(int interval)
       : Thread(Thread::Options("SignalSender", kSignalSenderStackSize)),
=======================================
--- /trunk/src/platform-win32.cc        Wed Jan 25 23:37:54 2012
+++ /trunk/src/platform-win32.cc        Tue Feb  7 04:07:34 2012
@@ -1894,7 +1894,7 @@

 class SamplerThread : public Thread {
  public:
-  static const int kSamplerThreadStackSize = 32 * KB;
+  static const int kSamplerThreadStackSize = 64 * KB;

   explicit SamplerThread(int interval)
       : Thread(Thread::Options("SamplerThread", kSamplerThreadStackSize)),
=======================================
--- /trunk/src/profile-generator.cc     Mon Feb  6 02:12:55 2012
+++ /trunk/src/profile-generator.cc     Tue Feb  7 04:07:34 2012
@@ -1131,6 +1131,7 @@
     case kRegExp: return "/regexp/";
     case kHeapNumber: return "/number/";
     case kNative: return "/native/";
+    case kSynthetic: return "/synthetic/";
     default: return "???";
   }
 }
@@ -2698,6 +2699,45 @@
   NativeObjectsExplorer* explorer_;
 };

+
+class BasicHeapEntriesAllocator : public HeapEntriesAllocator {
+ public:
+  BasicHeapEntriesAllocator(
+      HeapSnapshot* snapshot,
+      HeapEntry::Type entries_type)
+    : snapshot_(snapshot),
+      collection_(snapshot_->collection()),
+      entries_type_(entries_type) {
+  }
+  virtual HeapEntry* AllocateEntry(
+      HeapThing ptr, int children_count, int retainers_count);
+ private:
+  HeapSnapshot* snapshot_;
+  HeapSnapshotsCollection* collection_;
+  HeapEntry::Type entries_type_;
+};
+
+
+HeapEntry* BasicHeapEntriesAllocator::AllocateEntry(
+    HeapThing ptr, int children_count, int retainers_count) {
+ v8::RetainedObjectInfo* info = reinterpret_cast<v8::RetainedObjectInfo*>(ptr);
+  intptr_t elements = info->GetElementCount();
+  intptr_t size = info->GetSizeInBytes();
+  return snapshot_->AddEntry(
+      entries_type_,
+      elements != -1 ?
+          collection_->names()->GetFormatted(
+              "%s / %" V8_PTR_PREFIX "d entries",
+              info->GetLabel(),
+              info->GetElementCount()) :
+          collection_->names()->GetCopy(info->GetLabel()),
+      HeapObjectsMap::GenerateId(info),
+      size != -1 ? static_cast<int>(size) : 0,
+      children_count,
+      retainers_count);
+}
+
+
 NativeObjectsExplorer::NativeObjectsExplorer(
HeapSnapshot* snapshot, SnapshottingProgressReportingInterface* progress)
     : snapshot_(snapshot),
@@ -2707,6 +2747,10 @@
       objects_by_info_(RetainedInfosMatch),
       native_groups_(StringsMatch),
       filler_(NULL) {
+  synthetic_entries_allocator_ =
+      new BasicHeapEntriesAllocator(snapshot, HeapEntry::kSynthetic);
+  native_entries_allocator_ =
+      new BasicHeapEntriesAllocator(snapshot, HeapEntry::kNative);
 }


@@ -2728,27 +2772,8 @@
         reinterpret_cast<v8::RetainedObjectInfo*>(p->value);
     info->Dispose();
   }
-}
-
-
-HeapEntry* NativeObjectsExplorer::AllocateEntry(
-    HeapThing ptr, int children_count, int retainers_count) {
-  v8::RetainedObjectInfo* info =
-      reinterpret_cast<v8::RetainedObjectInfo*>(ptr);
-  intptr_t elements = info->GetElementCount();
-  intptr_t size = info->GetSizeInBytes();
-  return snapshot_->AddEntry(
-      HeapEntry::kNative,
-      elements != -1 ?
-          collection_->names()->GetFormatted(
-              "%s / %" V8_PTR_PREFIX "d entries",
-              info->GetLabel(),
-              info->GetElementCount()) :
-          collection_->names()->GetCopy(info->GetLabel()),
-      HeapObjectsMap::GenerateId(info),
-      size != -1 ? static_cast<int>(size) : 0,
-      children_count,
-      retainers_count);
+  delete synthetic_entries_allocator_;
+  delete native_entries_allocator_;
 }


@@ -2790,12 +2815,14 @@
   for (int i = 0; i < groups->length(); ++i) {
     ImplicitRefGroup* group = groups->at(i);
     HeapObject* parent = *group->parent_;
-    HeapEntry* parent_entry = filler_->FindOrAddEntry(parent, this);
+    HeapEntry* parent_entry =
+        filler_->FindOrAddEntry(parent, native_entries_allocator_);
     ASSERT(parent_entry != NULL);
     Object*** children = group->children_;
     for (size_t j = 0; j < group->length_; ++j) {
       Object* child = *children[j];
-      HeapEntry* child_entry = filler_->FindOrAddEntry(child, this);
+      HeapEntry* child_entry =
+          filler_->FindOrAddEntry(child, native_entries_allocator_);
       filler_->SetNamedReference(
           HeapGraphEdge::kInternal,
           parent, parent_entry,
@@ -2886,11 +2913,13 @@

 void NativeObjectsExplorer::SetNativeRootReference(
     v8::RetainedObjectInfo* info) {
-  HeapEntry* child_entry = filler_->FindOrAddEntry(info, this);
+  HeapEntry* child_entry =
+      filler_->FindOrAddEntry(info, native_entries_allocator_);
   ASSERT(child_entry != NULL);
   NativeGroupRetainedObjectInfo* group_info =
       FindOrAddGroupInfo(info->GetGroupLabel());
-  HeapEntry* group_entry = filler_->FindOrAddEntry(group_info, this);
+  HeapEntry* group_entry =
+      filler_->FindOrAddEntry(group_info, synthetic_entries_allocator_);
   filler_->SetNamedAutoIndexReference(
       HeapGraphEdge::kInternal,
       group_info, group_entry,
@@ -2902,7 +2931,8 @@
     HeapObject* wrapper, v8::RetainedObjectInfo* info) {
   HeapEntry* wrapper_entry = filler_->FindEntry(wrapper);
   ASSERT(wrapper_entry != NULL);
-  HeapEntry* info_entry = filler_->FindOrAddEntry(info, this);
+  HeapEntry* info_entry =
+      filler_->FindOrAddEntry(info, native_entries_allocator_);
   ASSERT(info_entry != NULL);
   filler_->SetNamedReference(HeapGraphEdge::kInternal,
                              wrapper, wrapper_entry,
@@ -2920,7 +2950,8 @@
        entry = native_groups_.Next(entry)) {
     NativeGroupRetainedObjectInfo* group_info =
         static_cast<NativeGroupRetainedObjectInfo*>(entry->value);
-    HeapEntry* group_entry = filler_->FindOrAddEntry(group_info, this);
+    HeapEntry* group_entry =
+        filler_->FindOrAddEntry(group_info, native_entries_allocator_);
     ASSERT(group_entry != NULL);
     filler_->SetIndexedAutoIndexReference(
         HeapGraphEdge::kElement,
@@ -3547,7 +3578,8 @@
             "," JSON_S("closure")
             "," JSON_S("regexp")
             "," JSON_S("number")
-            "," JSON_S("native"))
+            "," JSON_S("native")
+            "," JSON_S("synthetic"))
         "," JSON_S("string")
         "," JSON_S("number")
         "," JSON_S("number")
=======================================
--- /trunk/src/profile-generator.h      Mon Feb  6 02:12:55 2012
+++ /trunk/src/profile-generator.h      Tue Feb  7 04:07:34 2012
@@ -525,7 +525,8 @@
     kClosure = v8::HeapGraphNode::kClosure,
     kRegExp = v8::HeapGraphNode::kRegExp,
     kHeapNumber = v8::HeapGraphNode::kHeapNumber,
-    kNative = v8::HeapGraphNode::kNative
+    kNative = v8::HeapGraphNode::kNative,
+    kSynthetic = v8::HeapGraphNode::kSynthetic
   };

   HeapEntry() { }
@@ -1026,16 +1027,16 @@
   DISALLOW_COPY_AND_ASSIGN(V8HeapExplorer);
 };

+
 class NativeGroupRetainedObjectInfo;

+
 // An implementation of retained native objects extractor.
-class NativeObjectsExplorer : public HeapEntriesAllocator {
+class NativeObjectsExplorer {
  public:
   NativeObjectsExplorer(HeapSnapshot* snapshot,
                       SnapshottingProgressReportingInterface* progress);
   virtual ~NativeObjectsExplorer();
-  virtual HeapEntry* AllocateEntry(
-      HeapThing ptr, int children_count, int retainers_count);
   void AddRootEntries(SnapshotFillerInterface* filler);
   int EstimateObjectsCount();
   bool IterateAndExtractReferences(SnapshotFillerInterface* filler);
@@ -1074,6 +1075,8 @@
   // RetainedObjectInfo* -> List<HeapObject*>*
   HashMap objects_by_info_;
   HashMap native_groups_;
+  HeapEntriesAllocator* synthetic_entries_allocator_;
+  HeapEntriesAllocator* native_entries_allocator_;
   // Used during references extraction.
   SnapshotFillerInterface* filler_;

=======================================
--- /trunk/src/property-details.h       Mon Feb  6 02:12:55 2012
+++ /trunk/src/property-details.h       Tue Feb  7 04:07:34 2012
@@ -118,10 +118,6 @@
   inline Smi* AsSmi();

   PropertyType type() { return TypeField::decode(value_); }
-
-  bool IsProperty() {
-    return IsRealProperty(type());
-  }

PropertyAttributes attributes() { return AttributesField::decode(value_); }

=======================================
--- /trunk/src/property.h       Mon Feb  6 02:12:55 2012
+++ /trunk/src/property.h       Tue Feb  7 04:07:34 2012
@@ -264,7 +264,7 @@
   // Is the result is a property excluding transitions and the null
   // descriptor?
   bool IsProperty() {
-    return IsFound() && GetPropertyDetails().IsProperty();
+    return IsFound() && IsRealProperty(GetPropertyDetails().type());
   }

   bool IsCacheable() { return cacheable_; }
=======================================
--- /trunk/src/runtime.cc       Mon Feb  6 02:12:55 2012
+++ /trunk/src/runtime.cc       Tue Feb  7 04:07:34 2012
@@ -165,7 +165,7 @@
     }
   } else {
     { MaybeObject* maybe_result =
-          heap->AllocateFixedArray(copy->NumberOfLocalProperties(NONE));
+          heap->AllocateFixedArray(copy->NumberOfLocalProperties());
       if (!maybe_result->ToObject(&result)) return maybe_result;
     }
     FixedArray* names = FixedArray::cast(result);
@@ -5010,7 +5010,7 @@
       return *isolate->factory()->NewJSArray(0);
     }
     int n;
- n = jsproto->NumberOfLocalProperties(static_cast<PropertyAttributes>(NONE));
+    n = jsproto->NumberOfLocalProperties();
     local_property_count[i] = n;
     total_property_count += n;
     if (i < length - 1) {
@@ -13263,9 +13263,10 @@
 // element segments each containing a receiver, function, code and
 // native code offset.
 RUNTIME_FUNCTION(MaybeObject*, Runtime_CollectStackTrace) {
-  ASSERT_EQ(args.length(), 2);
-  Handle<Object> caller = args.at<Object>(0);
-  CONVERT_NUMBER_CHECKED(int32_t, limit, Int32, args[1]);
+  ASSERT_EQ(args.length(), 3);
+  CONVERT_ARG_CHECKED(JSObject, error_object, 0);
+  Handle<Object> caller = args.at<Object>(1);
+  CONVERT_NUMBER_CHECKED(int32_t, limit, Int32, args[2]);

   HandleScope scope(isolate);
   Factory* factory = isolate->factory();
@@ -13315,6 +13316,8 @@
     iter.Advance();
   }
   Handle<JSArray> result = factory->NewJSArrayWithElements(elements);
+  // Capture and attach a more detailed stack trace if necessary.
+  isolate->CaptureAndSetCurrentStackTraceFor(error_object);
   result->set_length(Smi::FromInt(cursor));
   return *result;
 }
=======================================
--- /trunk/src/runtime.h        Thu Jan 19 07:36:35 2012
+++ /trunk/src/runtime.h        Tue Feb  7 04:07:34 2012
@@ -229,7 +229,7 @@
   F(FunctionIsAPIFunction, 1, 1) \
   F(FunctionIsBuiltin, 1, 1) \
   F(GetScript, 1, 1) \
-  F(CollectStackTrace, 2, 1) \
+  F(CollectStackTrace, 3, 1) \
   F(GetV8Version, 0, 1) \
   \
   F(ClassOf, 1, 1) \
=======================================
--- /trunk/src/version.cc       Mon Feb  6 02:12:55 2012
+++ /trunk/src/version.cc       Tue Feb  7 04:07:34 2012
@@ -34,7 +34,7 @@
 // cannot be changed without changing the SCons build script.
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     9
-#define BUILD_NUMBER      2
+#define BUILD_NUMBER      3
 #define PATCH_LEVEL       0
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
=======================================
--- /trunk/src/x64/lithium-codegen-x64.cc       Wed Feb  1 02:48:36 2012
+++ /trunk/src/x64/lithium-codegen-x64.cc       Tue Feb  7 04:07:34 2012
@@ -993,11 +993,11 @@
         DeoptimizeIf(no_condition, instr->environment());
       }
     } else if (right->IsStackSlot()) {
-      __ or_(kScratchRegister, ToOperand(right));
+      __ orl(kScratchRegister, ToOperand(right));
       DeoptimizeIf(sign, instr->environment());
     } else {
       // Test the non-zero operand for negative sign.
-      __ or_(kScratchRegister, ToRegister(right));
+      __ orl(kScratchRegister, ToRegister(right));
       DeoptimizeIf(sign, instr->environment());
     }
     __ bind(&done);
=======================================
--- /trunk/test/cctest/test-api.cc      Thu Feb  2 08:21:15 2012
+++ /trunk/test/cctest/test-api.cc      Tue Feb  7 04:07:34 2012
@@ -13533,6 +13533,137 @@
   CompileRun("throw 'exception';");
   v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
 }
+
+
+static void RethrowStackTraceHandler(v8::Handle<v8::Message> message,
+                                     v8::Handle<v8::Value> data) {
+  // Use the frame where JavaScript is called from.
+  v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
+  CHECK(!stack_trace.IsEmpty());
+  int frame_count = stack_trace->GetFrameCount();
+  CHECK_EQ(3, frame_count);
+  int line_number[] = {1, 2, 5};
+  for (int i = 0; i < frame_count; i++) {
+    CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
+  }
+}
+
+
+// Test that we only return the stack trace at the site where the exception
+// is first thrown (not where it is rethrown).
+TEST(RethrowStackTrace) {
+  v8::HandleScope scope;
+  LocalContext env;
+  // We make sure that
+  // - the stack trace of the ReferenceError in g() is reported.
+  // - the stack trace is not overwritten when e1 is rethrown by t().
+  // - the stack trace of e2 does not overwrite that of e1.
+  const char* source =
+      "function g() { error; }          \n"
+      "function f() { g(); }            \n"
+      "function t(e) { throw e; }       \n"
+      "try {                            \n"
+      "  f();                           \n"
+      "} catch (e1) {                   \n"
+      "  try {                          \n"
+      "    error;                       \n"
+      "  } catch (e2) {                 \n"
+      "    t(e1);                       \n"
+      "  }                              \n"
+      "}                                \n";
+  v8::V8::AddMessageListener(RethrowStackTraceHandler);
+  v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
+  CompileRun(source);
+  v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
+  v8::V8::RemoveMessageListeners(RethrowStackTraceHandler);
+}
+
+
+static void RethrowPrimitiveStackTraceHandler(v8::Handle<v8::Message> message,
+                                              v8::Handle<v8::Value> data) {
+  v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
+  CHECK(!stack_trace.IsEmpty());
+  int frame_count = stack_trace->GetFrameCount();
+  CHECK_EQ(2, frame_count);
+  int line_number[] = {3, 7};
+  for (int i = 0; i < frame_count; i++) {
+    CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
+  }
+}
+
+
+// Test that we do not recognize identity for primitive exceptions.
+TEST(RethrowPrimitiveStackTrace) {
+  v8::HandleScope scope;
+  LocalContext env;
+  // We do not capture stack trace for non Error objects on creation time.
+  // Instead, we capture the stack trace on last throw.
+  const char* source =
+      "function g() { throw 404; }      \n"
+      "function f() { g(); }            \n"
+      "function t(e) { throw e; }       \n"
+      "try {                            \n"
+      "  f();                           \n"
+      "} catch (e1) {                   \n"
+      "  t(e1)                          \n"
+      "}                                \n";
+  v8::V8::AddMessageListener(RethrowPrimitiveStackTraceHandler);
+  v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
+  CompileRun(source);
+  v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
+  v8::V8::RemoveMessageListeners(RethrowPrimitiveStackTraceHandler);
+}
+
+
+static void RethrowExistingStackTraceHandler(v8::Handle<v8::Message> message,
+                                              v8::Handle<v8::Value> data) {
+  // Use the frame where JavaScript is called from.
+  v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
+  CHECK(!stack_trace.IsEmpty());
+  CHECK_EQ(1, stack_trace->GetFrameCount());
+  CHECK_EQ(1, stack_trace->GetFrame(0)->GetLineNumber());
+}
+
+
+// Test that the stack trace is captured when the error object is created and
+// not where it is thrown.
+TEST(RethrowExistingStackTrace) {
+  v8::HandleScope scope;
+  LocalContext env;
+  const char* source =
+      "var e = new Error();           \n"
+      "throw e;                       \n";
+  v8::V8::AddMessageListener(RethrowExistingStackTraceHandler);
+  v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
+  CompileRun(source);
+  v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
+  v8::V8::RemoveMessageListeners(RethrowExistingStackTraceHandler);
+}
+
+
+static void RethrowBogusErrorStackTraceHandler(v8::Handle<v8::Message> message, + v8::Handle<v8::Value> data) {
+  // Use the frame where JavaScript is called from.
+  v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
+  CHECK(!stack_trace.IsEmpty());
+  CHECK_EQ(1, stack_trace->GetFrameCount());
+  CHECK_EQ(2, stack_trace->GetFrame(0)->GetLineNumber());
+}
+
+
+// Test that the stack trace is captured where the bogus Error object is thrown.
+TEST(RethrowBogusErrorStackTrace) {
+  v8::HandleScope scope;
+  LocalContext env;
+  const char* source =
+      "var e = {__proto__: new Error()} \n"
+      "throw e;                         \n";
+  v8::V8::AddMessageListener(RethrowBogusErrorStackTraceHandler);
+  v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
+  CompileRun(source);
+  v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
+  v8::V8::RemoveMessageListeners(RethrowBogusErrorStackTraceHandler);
+}


v8::Handle<Value> AnalyzeStackOfEvalWithSourceURL(const v8::Arguments& args) {
=======================================
--- /trunk/test/cctest/test-heap-profiler.cc    Mon Feb  6 02:12:55 2012
+++ /trunk/test/cctest/test-heap-profiler.cc    Tue Feb  7 04:07:34 2012
@@ -774,7 +774,7 @@
   }

   const v8::HeapGraphNode* native_group_aaa = GetNode(
-      snapshot->GetRoot(), v8::HeapGraphNode::kNative, "aaa-group");
+      snapshot->GetRoot(), v8::HeapGraphNode::kSynthetic, "aaa-group");
   CHECK_NE(NULL, native_group_aaa);
   CHECK_EQ(1, native_group_aaa->GetChildrenCount());
   const v8::HeapGraphNode* aaa = GetNode(
@@ -783,7 +783,7 @@
   CHECK_EQ(2, aaa->GetChildrenCount());

   const v8::HeapGraphNode* native_group_ccc = GetNode(
-      snapshot->GetRoot(), v8::HeapGraphNode::kNative, "ccc-group");
+      snapshot->GetRoot(), v8::HeapGraphNode::kSynthetic, "ccc-group");
   const v8::HeapGraphNode* ccc = GetNode(
       native_group_ccc, v8::HeapGraphNode::kNative, "ccc");
   CHECK_NE(NULL, ccc);
=======================================
--- /trunk/test/cctest/test-mark-compact.cc     Wed Feb  1 02:48:36 2012
+++ /trunk/test/cctest/test-mark-compact.cc     Tue Feb  7 04:07:34 2012
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2012 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:
@@ -534,15 +534,15 @@
     intptr_t booted_memory = MemoryInUse();
     if (sizeof(initial_memory) == 8) {
       if (v8::internal::Snapshot::IsEnabled()) {
-        CHECK_LE(booted_memory - initial_memory, 6654 * 1024);  // 6444.
+        CHECK_LE(booted_memory - initial_memory, 6686 * 1024);  // 6476.
       } else {
-        CHECK_LE(booted_memory - initial_memory, 6777 * 1024);  // 6596.
+        CHECK_LE(booted_memory - initial_memory, 6809 * 1024);  // 6628.
       }
     } else {
       if (v8::internal::Snapshot::IsEnabled()) {
-        CHECK_LE(booted_memory - initial_memory, 6500 * 1024);  // 6356.
+        CHECK_LE(booted_memory - initial_memory, 6532 * 1024);  // 6388.
       } else {
-        CHECK_LE(booted_memory - initial_memory, 6654 * 1024);  // 6424
+        CHECK_LE(booted_memory - initial_memory, 6686 * 1024);  // 6456
       }
     }
   }
=======================================
--- /trunk/test/mjsunit/array-join.js   Mon May  2 07:30:53 2011
+++ /trunk/test/mjsunit/array-join.js   Tue Feb  7 04:07:34 2012
@@ -75,10 +75,10 @@
   Array.prototype.toString = oldToString;
 }

-var a = new Array(123123123);
-assertEquals(123123122, String(a).length);
-assertEquals(123123122, a.join(",").length);
-assertEquals(246246244, a.join("oo").length);
+var a = new Array(123123);
+assertEquals(123122, String(a).length);
+assertEquals(123122, a.join(",").length);
+assertEquals(246244, a.join("oo").length);

 a = new Array(Math.pow(2,32) - 1);  // Max length.
 assertEquals("", a.join(""));
=======================================
--- /trunk/test/mjsunit/string-replace-one-char.js      Thu Jan 19 07:36:35 2012
+++ /trunk/test/mjsunit/string-replace-one-char.js      Tue Feb  7 04:07:34 2012
@@ -71,13 +71,13 @@

 // Deep cons tree.
 var nested_1 = "";
-for (var i = 0; i < 1000000; i++) nested_1 += "y";
+for (var i = 0; i < 100000; i++) nested_1 += "y";
 var nested_1_result = prefix1024 + nested_1 + "aa";
 nested_1 = prefix1024 + nested_1 + "z";
 test_replace(nested_1, nested_1_result, "z", "aa");

 var nested_2 = "\u2244";
-for (var i = 0; i < 1000000; i++) nested_2 += "y";
+for (var i = 0; i < 100000; i++) nested_2 += "y";
 var nested_2_result = prefix1024 + nested_2 + "aa";
 nested_2 = prefix1024 + nested_2 + "\u2012";
 test_replace(nested_2, nested_2_result, "\u2012", "aa");

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to