Revision: 13282
Author:   [email protected]
Date:     Thu Dec 27 07:57:11 2012
Log:      Version 3.16.1

Fixed x64 MathMinMax for negative untagged int32 arguments. (Chromium issue 164442)

Fixed FloatingPointHelper::CheckSSE2OperandIsInt32. (issue 2458)

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

Added:
 /trunk/test/mjsunit/regress/regress-164442.js
Deleted:
 /trunk/test/mjsunit/stack-traces-gc.js
Modified:
 /trunk/ChangeLog
 /trunk/src/api.cc
 /trunk/src/deoptimizer.cc
 /trunk/src/handles.cc
 /trunk/src/heap-inl.h
 /trunk/src/heap.cc
 /trunk/src/heap.h
 /trunk/src/ia32/assembler-ia32.cc
 /trunk/src/ia32/assembler-ia32.h
 /trunk/src/ia32/code-stubs-ia32.cc
 /trunk/src/ia32/disasm-ia32.cc
 /trunk/src/ia32/lithium-gap-resolver-ia32.cc
 /trunk/src/isolate.cc
 /trunk/src/list-inl.h
 /trunk/src/list.h
 /trunk/src/mark-compact.cc
 /trunk/src/messages.js
 /trunk/src/runtime.cc
 /trunk/src/runtime.h
 /trunk/src/version.cc
 /trunk/src/x64/assembler-x64.cc
 /trunk/src/x64/assembler-x64.h
 /trunk/src/x64/disasm-x64.cc
 /trunk/src/x64/lithium-codegen-x64.cc
 /trunk/test/cctest/test-decls.cc
 /trunk/test/cctest/test-heap.cc
 /trunk/test/cctest/test-object-observe.cc
 /trunk/test/message/overwritten-builtins.out
 /trunk/test/mjsunit/eval-stack-trace.js
 /trunk/test/mjsunit/stack-traces.js

=======================================
--- /dev/null
+++ /trunk/test/mjsunit/regress/regress-164442.js       Thu Dec 27 07:57:11 2012
@@ -0,0 +1,45 @@
+// 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.
+
+// Flags: --allow-natives-syntax
+
+// Should not take a very long time (n^2 algorithms are bad)
+
+
+function ensureNotNegative(x) {
+  return Math.max(0, x | 0);
+}
+
+
+ensureNotNegative(1);
+ensureNotNegative(2);
+
+%OptimizeFunctionOnNextCall(ensureNotNegative);
+
+var r = ensureNotNegative(-1);
+
+assertEquals(0, r);
=======================================
--- /trunk/test/mjsunit/stack-traces-gc.js      Fri Dec 21 04:35:02 2012
+++ /dev/null
@@ -1,119 +0,0 @@
-// 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.
-
-// Flags: --expose-gc --allow-natives-syntax
-
-var fired = [];
-for (var i = 0; i < 100; i++) fired[i] = false;
-
-function getter_function(i) {
-  return %MarkOneShotGetter( function() { fired[i] = true; } );
-}
-
-// Error objects that die young.
-for (var i = 0; i < 100; i++) {
-  var error = new Error();
-  // Replace the getter to observe whether it has been fired,
-  // and disguise it as original getter.
-  var getter = getter_function(i);
-  error.__defineGetter__("stack", getter);
-
-  error = undefined;
-}
-
-gc();
-for (var i = 0; i < 100; i++) {
-  assertFalse(fired[i]);
-}
-
-// Error objects that are kept alive.
-var array = [];
-for (var i = 0; i < 100; i++) {
-  var error = new Error();
-  var getter = getter_function(i);
-  // Replace the getter to observe whether it has been fired,
-  // and disguise it as original getter.
-  error.__defineGetter__("stack", getter);
-
-  array.push(error);
-  error = undefined;
-}
-
-gc();
-// We don't expect all stack traces to be formatted after only one GC.
-assertTrue(fired[0]);
-
-for (var i = 0; i < 10; i++) gc();
-for (var i = 0; i < 100; i++) assertTrue(fired[i]);
-
-// Error objects with custom stack getter.
-var custom_error = new Error();
-var custom_getter_fired = false;
-custom_error.__defineGetter__("stack",
-                              function() { custom_getter_fired = true; });
-gc();
-assertFalse(custom_getter_fired);
-
-// Check that formatting caused by GC is not somehow observable.
-var error;
-
-var obj = { foo: function foo() { throw new Error(); } };
-
-try {
-  obj.foo();
-} catch (e) {
-  delete obj.foo;
-  Object.defineProperty(obj, 'foo', {
-    get: function() { assertUnreachable(); }
-  });
-  error = e;
-}
-
-gc();
-
-Object.defineProperty(Array.prototype, '0', {
-  get: function() { assertUnreachable(); }
-});
-
-try {
-  throw new Error();
-} catch (e) {
-  error = e;
-}
-
-gc();
-
-String.prototype.indexOf = function() { assertUnreachable(); };
-String.prototype.lastIndexOf = function() { assertUnreachable(); };
-var obj = { method: function() { throw Error(); } };
-try {
-  obj.method();
-} catch (e) {
-  error = e;
-}
-
-gc();
=======================================
--- /trunk/ChangeLog    Fri Dec 21 05:47:00 2012
+++ /trunk/ChangeLog    Thu Dec 27 07:57:11 2012
@@ -1,3 +1,14 @@
+2012-12-27: Version 3.16.1
+
+        Fixed x64 MathMinMax for negative untagged int32 arguments.
+        (Chromium issue 164442)
+
+        Fixed FloatingPointHelper::CheckSSE2OperandIsInt32.
+        (issue 2458)
+
+        Performance and stability improvements on all platforms.
+
+
 2012-12-21: Version 3.16.0

         V8_Fatal now prints C++ stack trace in debug mode.
=======================================
--- /trunk/src/api.cc   Fri Dec 21 04:35:02 2012
+++ /trunk/src/api.cc   Thu Dec 27 07:57:11 2012
@@ -1851,7 +1851,8 @@
     if (!raw_obj->IsJSObject()) return v8::Local<Value>();
     i::HandleScope scope(isolate_);
     i::Handle<i::JSObject> obj(i::JSObject::cast(raw_obj), isolate_);
-    i::Handle<i::String> name = isolate_->factory()->stack_symbol();
+    i::Handle<i::String> name =
+ isolate_->factory()->LookupOneByteSymbol(STATIC_ASCII_VECTOR("stack"));
     if (!obj->HasProperty(*name)) return v8::Local<Value>();
     i::Handle<i::Object> value = i::GetProperty(obj, name);
     if (value.is_null()) return v8::Local<Value>();
=======================================
--- /trunk/src/deoptimizer.cc   Fri Dec 21 04:35:02 2012
+++ /trunk/src/deoptimizer.cc   Thu Dec 27 07:57:11 2012
@@ -502,7 +502,7 @@
       return "OSR";
   }
   UNREACHABLE();
-  return false;
+  return NULL;
 }


=======================================
--- /trunk/src/handles.cc       Fri Dec 21 04:35:02 2012
+++ /trunk/src/handles.cc       Thu Dec 27 07:57:11 2012
@@ -375,15 +375,6 @@
   Handle<JSFunction> constructor = isolate->script_function();
   Handle<JSValue> result =
       Handle<JSValue>::cast(isolate->factory()->NewJSObject(constructor));
-
-  // The allocation might have triggered a GC, which could have called this
- // function recursively, and a wrapper has already been created and cached.
-  // In that case, simply return the cached wrapper.
-  if (script->wrapper()->foreign_address() != NULL) {
-    return Handle<JSValue>(
-        reinterpret_cast<JSValue**>(script->wrapper()->foreign_address()));
-  }
-
   result->set_value(*script);

   // Create a new weak global handle and use it to cache the wrapper
=======================================
--- /trunk/src/heap-inl.h       Fri Dec 21 04:35:02 2012
+++ /trunk/src/heap-inl.h       Thu Dec 27 07:57:11 2012
@@ -664,19 +664,6 @@
   }
 #endif
 }
-
-
-void ErrorObjectList::Add(JSObject* object) {
-  list_.Add(object);
-}
-
-
-void ErrorObjectList::Iterate(ObjectVisitor* v) {
-  if (!list_.is_empty()) {
-    Object** start = &list_[0];
-    v->VisitPointers(start, start + list_.length());
-  }
-}


 void Heap::ClearInstanceofCache() {
=======================================
--- /trunk/src/heap.cc  Fri Dec 21 04:35:02 2012
+++ /trunk/src/heap.cc  Thu Dec 27 07:57:11 2012
@@ -550,8 +550,6 @@
 #ifdef ENABLE_DEBUGGER_SUPPORT
   isolate_->debug()->AfterGarbageCollection();
 #endif  // ENABLE_DEBUGGER_SUPPORT
-
-  error_object_list_.DeferredFormatStackTrace(isolate());
 }


@@ -1356,8 +1354,6 @@
   UpdateNewSpaceReferencesInExternalStringTable(
       &UpdateNewSpaceReferenceInExternalStringTableEntry);

-  error_object_list_.UpdateReferencesInNewSpace(this);
-
   promotion_queue_.Destroy();

   LiveObjectList::UpdateReferencesForScavengeGC();
@@ -2900,6 +2896,7 @@
   RootListIndex writable_roots[] = {
     kStoreBufferTopRootIndex,
     kStackLimitRootIndex,
+    kNumberStringCacheRootIndex,
     kInstanceofCacheFunctionRootIndex,
     kInstanceofCacheMapRootIndex,
     kInstanceofCacheAnswerRootIndex,
@@ -5936,7 +5933,6 @@
       mode != VISIT_ALL_IN_SWEEP_NEWSPACE) {
     // Scavenge collections have special processing for this.
     external_string_table_.Iterate(v);
-    error_object_list_.Iterate(v);
   }
   v->Synchronize(VisitorSynchronization::kExternalStringsTable);
 }
@@ -6310,8 +6306,6 @@

   external_string_table_.TearDown();

-  error_object_list_.TearDown();
-
   new_space_.TearDown();

   if (old_pointer_space_ != NULL) {
@@ -7218,8 +7212,6 @@
     }
   }
   new_space_strings_.Rewind(last);
-  new_space_strings_.Trim();
-
   last = 0;
   for (int i = 0; i < old_space_strings_.length(); ++i) {
     if (old_space_strings_[i] == heap_->the_hole_value()) {
@@ -7229,7 +7221,6 @@
     old_space_strings_[last++] = old_space_strings_[i];
   }
   old_space_strings_.Rewind(last);
-  old_space_strings_.Trim();
 #ifdef VERIFY_HEAP
   if (FLAG_verify_heap) {
     Verify();
@@ -7242,114 +7233,6 @@
   new_space_strings_.Free();
   old_space_strings_.Free();
 }
-
-
-// Update all references.
-void ErrorObjectList::UpdateReferences() {
-  for (int i = 0; i < list_.length(); i++) {
-    HeapObject* object = HeapObject::cast(list_[i]);
-    MapWord first_word = object->map_word();
-    if (first_word.IsForwardingAddress()) {
-      list_[i] = first_word.ToForwardingAddress();
-    }
-  }
-}
-
-
-// Unforwarded objects in new space are dead and removed from the list.
-void ErrorObjectList::UpdateReferencesInNewSpace(Heap* heap) {
-  if (!nested_) {
-    int write_index = 0;
-    for (int i = 0; i < list_.length(); i++) {
-      MapWord first_word = HeapObject::cast(list_[i])->map_word();
-      if (first_word.IsForwardingAddress()) {
-        list_[write_index++] = first_word.ToForwardingAddress();
-      }
-    }
-    list_.Rewind(write_index);
-  } else {
-    // If a GC is triggered during DeferredFormatStackTrace, we do not move
-    // objects in the list, just remove dead ones, as to not confuse the
-    // loop in DeferredFormatStackTrace.
-    for (int i = 0; i < list_.length(); i++) {
-      MapWord first_word = HeapObject::cast(list_[i])->map_word();
-      list_[i] = first_word.IsForwardingAddress()
-                     ? first_word.ToForwardingAddress()
-                     : heap->the_hole_value();
-    }
-  }
-}
-
-
-void ErrorObjectList::DeferredFormatStackTrace(Isolate* isolate) {
-  // If formatting the stack trace causes a GC, this method will be
-  // recursively called.  In that case, skip the recursive call, since
-  // the loop modifies the list while iterating over it.
-  if (nested_ || isolate->has_pending_exception()) return;
-  nested_ = true;
-  HandleScope scope(isolate);
-  Handle<String> stack_key = isolate->factory()->stack_symbol();
-  int write_index = 0;
-  int budget = kBudgetPerGC;
-  for (int i = 0; i < list_.length(); i++) {
-    Object* object = list_[i];
-    JSFunction* getter_fun;
-
-    { AssertNoAllocation assert;
-      // Skip possible holes in the list.
-      if (object->IsTheHole()) continue;
-      if (isolate->heap()->InNewSpace(object) || budget == 0) {
-        list_[write_index++] = object;
-        continue;
-      }
-
-      // Check whether the stack property is backed by the original getter.
-      LookupResult lookup(isolate);
- JSObject::cast(object)->LocalLookupRealNamedProperty(*stack_key, &lookup);
-      if (!lookup.IsFound() || lookup.type() != CALLBACKS) continue;
-      Object* callback = lookup.GetCallbackObject();
-      if (!callback->IsAccessorPair()) continue;
-      Object* getter_obj = AccessorPair::cast(callback)->getter();
-      if (!getter_obj->IsJSFunction()) continue;
-      getter_fun = JSFunction::cast(getter_obj);
-      String* key = isolate->heap()->hidden_stack_trace_symbol();
-      if (key != getter_fun->GetHiddenProperty(key)) continue;
-    }
-
-    budget--;
-    HandleScope scope(isolate);
-    bool has_exception = false;
-    Handle<Object> object_handle(object, isolate);
-    Handle<Object> getter_handle(getter_fun, isolate);
-    Execution::Call(getter_handle, object_handle, 0, NULL, &has_exception);
-    if (has_exception) {
-      // Hit an exception (most likely a stack overflow).
-      // Wrap up this pass and retry after another GC.
-      isolate->clear_pending_exception();
-      // We use the handle since calling the getter might have caused a GC.
-      list_[write_index++] = *object_handle;
-      budget = 0;
-    }
-  }
-  list_.Rewind(write_index);
-  list_.Trim();
-  nested_ = false;
-}
-
-
-void ErrorObjectList::RemoveUnmarked(Heap* heap) {
-  for (int i = 0; i < list_.length(); i++) {
-    HeapObject* object = HeapObject::cast(list_[i]);
-    if (!Marking::MarkBitFrom(object).Get()) {
-      list_[i] = heap->the_hole_value();
-    }
-  }
-}
-
-
-void ErrorObjectList::TearDown() {
-  list_.Free();
-}


 void Heap::QueueMemoryChunkForFree(MemoryChunk* chunk) {
=======================================
--- /trunk/src/heap.h   Fri Dec 21 04:35:02 2012
+++ /trunk/src/heap.h   Thu Dec 27 07:57:11 2012
@@ -209,7 +209,6 @@
   V(char_at_symbol, "CharAt")                                            \
   V(undefined_symbol, "undefined")                                       \
   V(value_of_symbol, "valueOf")                                          \
-  V(stack_symbol, "stack")                                               \
   V(InitializeVarGlobal_symbol, "InitializeVarGlobal")                   \
   V(InitializeConstGlobal_symbol, "InitializeConstGlobal")               \
   V(KeyedLoadElementMonomorphic_symbol,                                  \
@@ -428,41 +427,6 @@
 };


-// The stack property of an error object is implemented as a getter that
-// formats the attached raw stack trace into a string. This raw stack trace -// keeps code and function objects alive until the getter is called the first
-// time.  To release those objects, we call the getter after each GC for
-// newly tenured error objects that are kept in a list.
-class ErrorObjectList {
- public:
-  inline void Add(JSObject* object);
-
-  inline void Iterate(ObjectVisitor* v);
-
-  void TearDown();
-
-  void RemoveUnmarked(Heap* heap);
-
-  void DeferredFormatStackTrace(Isolate* isolate);
-
-  void UpdateReferences();
-
-  void UpdateReferencesInNewSpace(Heap* heap);
-
- private:
-  static const int kBudgetPerGC = 16;
-
-  ErrorObjectList() : nested_(false) { }
-
-  friend class Heap;
-
-  List<Object*> list_;
-  bool nested_;
-
-  DISALLOW_COPY_AND_ASSIGN(ErrorObjectList);
-};
-
-
 enum ArrayStorageAllocationMode {
   DONT_INITIALIZE_ARRAY_ELEMENTS,
   INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE
@@ -1612,10 +1576,6 @@
   ExternalStringTable* external_string_table() {
     return &external_string_table_;
   }
-
-  ErrorObjectList* error_object_list() {
-    return &error_object_list_;
-  }

   // Returns the current sweep generation.
   int sweep_generation() {
@@ -2193,8 +2153,6 @@

   ExternalStringTable external_string_table_;

-  ErrorObjectList error_object_list_;
-
   VisitorDispatchTable<ScavengingCallback> scavenging_visitors_table_;

   MemoryChunk* chunks_queued_for_free_;
=======================================
--- /trunk/src/ia32/assembler-ia32.cc   Fri Dec 21 04:35:02 2012
+++ /trunk/src/ia32/assembler-ia32.cc   Thu Dec 27 07:57:11 2012
@@ -2128,6 +2128,15 @@
   EMIT(0x50);
   emit_sse_operand(dst, src);
 }
+
+
+void Assembler::movmskps(Register dst, XMMRegister src) {
+  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  EnsureSpace ensure_space(this);
+  EMIT(0x0F);
+  EMIT(0x50);
+  emit_sse_operand(dst, src);
+}


 void Assembler::pcmpeqd(XMMRegister dst, XMMRegister src) {
=======================================
--- /trunk/src/ia32/assembler-ia32.h    Fri Dec 21 04:35:02 2012
+++ /trunk/src/ia32/assembler-ia32.h    Thu Dec 27 07:57:11 2012
@@ -1077,6 +1077,7 @@
   void roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode);

   void movmskpd(Register dst, XMMRegister src);
+  void movmskps(Register dst, XMMRegister src);

   void cmpltsd(XMMRegister dst, XMMRegister src);
   void pcmpeqd(XMMRegister dst, XMMRegister src);
=======================================
--- /trunk/src/ia32/code-stubs-ia32.cc  Fri Dec 21 04:35:02 2012
+++ /trunk/src/ia32/code-stubs-ia32.cc  Thu Dec 27 07:57:11 2012
@@ -2871,9 +2871,11 @@
   __ cvttsd2si(scratch, Operand(operand));
   __ cvtsi2sd(xmm_scratch, scratch);
   __ pcmpeqd(xmm_scratch, operand);
-  __ movmskpd(scratch, xmm_scratch);
-  __ test(scratch, Immediate(1));
-  __ j(zero, non_int32);
+  __ movmskps(scratch, xmm_scratch);
+  // Two least significant bits should be both set.
+  __ not_(scratch);
+  __ test(scratch, Immediate(3));
+  __ j(not_zero, non_int32);
 }


=======================================
--- /trunk/src/ia32/disasm-ia32.cc      Mon Nov 26 06:53:56 2012
+++ /trunk/src/ia32/disasm-ia32.cc      Thu Dec 27 07:57:11 2012
@@ -1040,6 +1040,14 @@
                            NameOfXMMRegister(regop),
                            NameOfXMMRegister(rm));
             data++;
+          } else if (f0byte == 0x50) {
+            data += 2;
+            int mod, regop, rm;
+            get_modrm(*data, &mod, &regop, &rm);
+            AppendToBuffer("movmskps %s,%s",
+                           NameOfCPURegister(regop),
+                           NameOfXMMRegister(rm));
+            data++;
           } else if ((f0byte & 0xF0) == 0x80) {
             data += JumpConditional(data, branch_hint);
           } else if (f0byte == 0xBE || f0byte == 0xBF || f0byte == 0xB6 ||
=======================================
--- /trunk/src/ia32/lithium-gap-resolver-ia32.cc        Fri Dec 21 04:35:02 2012
+++ /trunk/src/ia32/lithium-gap-resolver-ia32.cc        Thu Dec 27 07:57:11 2012
@@ -324,37 +324,29 @@
     }

   } else if (source->IsDoubleRegister()) {
-    if (CpuFeatures::IsSupported(SSE2)) {
-      CpuFeatures::Scope scope(SSE2);
-      XMMRegister src = cgen_->ToDoubleRegister(source);
-      if (destination->IsDoubleRegister()) {
-        XMMRegister dst = cgen_->ToDoubleRegister(destination);
-        __ movaps(dst, src);
-      } else {
-        ASSERT(destination->IsDoubleStackSlot());
-        Operand dst = cgen_->ToOperand(destination);
-        __ movdbl(dst, src);
-      }
+    CpuFeatures::Scope scope(SSE2);
+    XMMRegister src = cgen_->ToDoubleRegister(source);
+    if (destination->IsDoubleRegister()) {
+      XMMRegister dst = cgen_->ToDoubleRegister(destination);
+      __ movaps(dst, src);
     } else {
-      UNREACHABLE();
+      ASSERT(destination->IsDoubleStackSlot());
+      Operand dst = cgen_->ToOperand(destination);
+      __ movdbl(dst, src);
     }
   } else if (source->IsDoubleStackSlot()) {
-    if (CpuFeatures::IsSupported(SSE2)) {
-      CpuFeatures::Scope scope(SSE2);
-      ASSERT(destination->IsDoubleRegister() ||
-             destination->IsDoubleStackSlot());
-      Operand src = cgen_->ToOperand(source);
-      if (destination->IsDoubleRegister()) {
-        XMMRegister dst = cgen_->ToDoubleRegister(destination);
-        __ movdbl(dst, src);
-      } else {
-        // We rely on having xmm0 available as a fixed scratch register.
-        Operand dst = cgen_->ToOperand(destination);
-        __ movdbl(xmm0, src);
-        __ movdbl(dst, xmm0);
-      }
+    CpuFeatures::Scope scope(SSE2);
+    ASSERT(destination->IsDoubleRegister() ||
+           destination->IsDoubleStackSlot());
+    Operand src = cgen_->ToOperand(source);
+    if (destination->IsDoubleRegister()) {
+      XMMRegister dst = cgen_->ToDoubleRegister(destination);
+      __ movdbl(dst, src);
     } else {
-      UNREACHABLE();
+      // We rely on having xmm0 available as a fixed scratch register.
+      Operand dst = cgen_->ToOperand(destination);
+      __ movdbl(xmm0, src);
+      __ movdbl(dst, xmm0);
     }
   } else {
     UNREACHABLE();
@@ -429,6 +421,7 @@
     __ movaps(dst, xmm0);

} else if (source->IsDoubleRegister() || destination->IsDoubleRegister()) {
+    CpuFeatures::Scope scope(SSE2);
     // XMM register-memory swap.  We rely on having xmm0
     // available as a fixed scratch register.
ASSERT(source->IsDoubleStackSlot() || destination->IsDoubleStackSlot());
@@ -442,6 +435,7 @@
     __ movdbl(reg, Operand(xmm0));

} else if (source->IsDoubleStackSlot() && destination->IsDoubleStackSlot()) {
+    CpuFeatures::Scope scope(SSE2);
     // Double-width memory-to-memory.  Spill on demand to use a general
     // purpose temporary register and also rely on having xmm0 available as
     // a fixed scratch register.
=======================================
--- /trunk/src/isolate.cc       Fri Dec 21 04:35:02 2012
+++ /trunk/src/isolate.cc       Thu Dec 27 07:57:11 2012
@@ -634,7 +634,6 @@
   }
   Handle<JSArray> result = factory()->NewJSArrayWithElements(elements);
   result->set_length(Smi::FromInt(cursor));
-  heap()->error_object_list()->Add(*error_object);
   return result;
 }

=======================================
--- /trunk/src/list-inl.h       Fri Dec 21 04:35:02 2012
+++ /trunk/src/list-inl.h       Thu Dec 27 07:57:11 2012
@@ -85,9 +85,8 @@

 template<typename T, class P>
 void List<T, P>::Resize(int new_capacity, P alloc) {
-  ASSERT_LE(length_, new_capacity);
   T* new_data = NewData(new_capacity, alloc);
-  memcpy(new_data, data_, length_ * sizeof(T));
+  memcpy(new_data, data_, capacity_ * sizeof(T));
   List<T, P>::DeleteData(data_);
   data_ = new_data;
   capacity_ = new_capacity;
@@ -160,14 +159,6 @@
 void List<T, P>::Rewind(int pos) {
   length_ = pos;
 }
-
-
-template<typename T, class P>
-void List<T, P>::Trim(P alloc) {
-  if (length_ < capacity_ / 4) {
-    Resize(capacity_ / 2, alloc);
-  }
-}


 template<typename T, class P>
=======================================
--- /trunk/src/list.h   Fri Dec 21 04:35:02 2012
+++ /trunk/src/list.h   Thu Dec 27 07:57:11 2012
@@ -148,9 +148,6 @@

   // Drop the last 'count' elements from the list.
   INLINE(void RewindBy(int count)) { Rewind(length_ - count); }
-
-  // Halve the capacity if fill level is less than a quarter.
-  INLINE(void Trim(AllocationPolicy allocator = AllocationPolicy()));

   bool Contains(const T& elm) const;
   int CountOccurrences(const T& elm, int start, int end) const;
=======================================
--- /trunk/src/mark-compact.cc  Fri Dec 21 04:35:02 2012
+++ /trunk/src/mark-compact.cc  Thu Dec 27 07:57:11 2012
@@ -835,6 +835,8 @@
   // GC, because it relies on the new address of certain old space
   // objects (empty string, illegal builtin).
   heap()->isolate()->stub_cache()->Clear();
+
+  heap()->external_string_table_.CleanUp();
 }


@@ -2028,7 +2030,6 @@
   symbol_table->ElementsRemoved(v.PointersRemoved());
   heap()->external_string_table_.Iterate(&v);
   heap()->external_string_table_.CleanUp();
-  heap()->error_object_list_.RemoveUnmarked(heap());

   // Process the weak references.
   MarkCompactWeakObjectRetainer mark_compact_object_retainer;
@@ -3068,9 +3069,6 @@
   heap_->UpdateReferencesInExternalStringTable(
       &UpdateReferenceInExternalStringTableEntry);

-  // Update pointers in the new error object list.
-  heap_->error_object_list()->UpdateReferences();
-
   if (!FLAG_watch_ic_patching) {
     // Update JSFunction pointers from the runtime profiler.
     heap()->isolate()->runtime_profiler()->UpdateSamplesAfterCompact(
=======================================
--- /trunk/src/messages.js      Fri Dec 21 04:35:02 2012
+++ /trunk/src/messages.js      Thu Dec 27 07:57:11 2012
@@ -820,7 +820,7 @@
        %_CallFunction(this.receiver,
                       ownName,
                       ObjectLookupSetter) === this.fun ||
-       %GetDataProperty(this.receiver, ownName) === this.fun)) {
+       this.receiver[ownName] === this.fun)) {
     // To handle DontEnum properties we guess that the method has
     // the same name as the function.
     return ownName;
@@ -829,7 +829,8 @@
   for (var prop in this.receiver) {
if (%_CallFunction(this.receiver, prop, ObjectLookupGetter) === this.fun || %_CallFunction(this.receiver, prop, ObjectLookupSetter) === this.fun ||
-        %GetDataProperty(this.receiver, prop) === this.fun) {
+        (!%_CallFunction(this.receiver, prop, ObjectLookupGetter) &&
+         this.receiver[prop] === this.fun)) {
       // If we find more than one match bail out to avoid confusion.
       if (name) {
         return null;
@@ -932,14 +933,12 @@
     var typeName = GetTypeName(this, true);
     var methodName = this.getMethodName();
     if (functionName) {
-      if (typeName &&
-          %_CallFunction(functionName, typeName, StringIndexOf) != 0) {
+      if (typeName && functionName.indexOf(typeName) != 0) {
         line += typeName + ".";
       }
       line += functionName;
-      if (methodName &&
-          (%_CallFunction(functionName, "." + methodName, StringIndexOf) !=
-           functionName.length - methodName.length - 1)) {
+      if (methodName && functionName.lastIndexOf("." + methodName) !=
+          functionName.length - methodName.length - 1) {
         line += " [as " + methodName + "]";
       }
     } else {
@@ -1017,37 +1016,17 @@
   return eval_origin;
 }

-
-function FormatErrorString(error) {
+function FormatStackTrace(error, frames) {
+  var lines = [];
   try {
-    return %_CallFunction(error, ErrorToString);
+    lines.push(error.toString());
   } catch (e) {
     try {
-      return "<error: " + e + ">";
+      lines.push("<error: " + e + ">");
     } catch (ee) {
-      return "<error>";
+      lines.push("<error>");
     }
   }
-}
-
-
-function GetStackFrames(raw_stack) {
-  var frames = new InternalArray();
-  for (var i = 0; i < raw_stack.length; i += 4) {
-    var recv = raw_stack[i];
-    var fun = raw_stack[i + 1];
-    var code = raw_stack[i + 2];
-    var pc = raw_stack[i + 3];
-    var pos = %FunctionGetPositionForOffset(code, pc);
-    frames.push(new CallSite(recv, fun, pos));
-  }
-  return frames;
-}
-
-
-function FormatStackTrace(error_string, frames) {
-  var lines = new InternalArray();
-  lines.push(error_string);
   for (var i = 0; i < frames.length; i++) {
     var frame = frames[i];
     var line;
@@ -1063,9 +1042,25 @@
     }
     lines.push("    at " + line);
   }
-  return %_CallFunction(lines, "\n", ArrayJoin);
+  return lines.join("\n");
 }

+function FormatRawStackTrace(error, raw_stack) {
+  var frames = [ ];
+  for (var i = 0; i < raw_stack.length; i += 4) {
+    var recv = raw_stack[i];
+    var fun = raw_stack[i + 1];
+    var code = raw_stack[i + 2];
+    var pc = raw_stack[i + 3];
+    var pos = %FunctionGetPositionForOffset(code, pc);
+    frames.push(new CallSite(recv, fun, pos));
+  }
+  if (IS_FUNCTION($Error.prepareStackTrace)) {
+    return $Error.prepareStackTrace(error, frames);
+  } else {
+    return FormatStackTrace(error, frames);
+  }
+}

 function GetTypeName(obj, requireConstructor) {
   var constructor = obj.receiver.constructor;
@@ -1080,11 +1075,6 @@
   }
   return constructorName;
 }
-
-
-// Flag to prevent recursive call of Error.prepareStackTrace.
-var formatting_custom_stack_trace = false;
-

 function captureStackTrace(obj, cons_opt) {
   var stackTraceLimit = $Error.stackTraceLimit;
@@ -1092,40 +1082,17 @@
   if (stackTraceLimit < 0 || stackTraceLimit > 10000) {
     stackTraceLimit = 10000;
   }
-  var stack = %CollectStackTrace(obj,
-                                 cons_opt ? cons_opt : captureStackTrace,
-                                 stackTraceLimit);
-
-  // Don't be lazy if the error stack formatting is custom (observable).
- if (IS_FUNCTION($Error.prepareStackTrace) && !formatting_custom_stack_trace) {
-    var array = [];
-    %MoveArrayContents(GetStackFrames(stack), array);
-    formatting_custom_stack_trace = true;
-    try {
-      obj.stack = $Error.prepareStackTrace(obj, array);
-    } catch (e) {
-      throw e;  // The custom formatting function threw.  Rethrow.
-    } finally {
-      formatting_custom_stack_trace = false;
-    }
-    return;
-  }
-
-  var error_string = FormatErrorString(obj);
+  var raw_stack = %CollectStackTrace(obj,
+ cons_opt ? cons_opt : captureStackTrace,
+                                     stackTraceLimit);
   // Note that 'obj' and 'this' maybe different when called on objects that
// have the error object on its prototype chain. The getter replaces itself
   // with a data property as soon as the stack trace has been formatted.
- // The getter must not change the object layout as it may be called after GC.
   var getter = function() {
-    if (IS_STRING(stack)) return stack;
-    // Stack is still a raw array awaiting to be formatted.
-    stack = FormatStackTrace(error_string, GetStackFrames(stack));
-    // Release context value.
-    error_string = void 0;
-    return stack;
+    var value = FormatRawStackTrace(obj, raw_stack);
+    %DefineOrRedefineDataProperty(obj, 'stack', value, NONE);
+    return value;
   };
-  %MarkOneShotGetter(getter);
-
   // The 'stack' property of the receiver is set as data property.  If
   // the receiver is the same as holder, this accessor pair is replaced.
   var setter = function(v) {
@@ -1272,32 +1239,23 @@
   // error object copy, but can be found on the prototype chain of 'this'.
// When the stack trace is formatted, this accessor property is replaced by
   // a data property.
-  var error_string = boilerplate.name + ": " + boilerplate.message;
-
- // The getter must not change the object layout as it may be called after GC.
   function getter() {
     var holder = this;
     while (!IS_ERROR(holder)) {
       holder = %GetPrototype(holder);
       if (holder == null) return MakeSyntaxError('illegal_access', []);
     }
-    var stack = %GetOverflowedStackTrace(holder);
-    if (IS_STRING(stack)) return stack;
-    if (IS_ARRAY(stack)) {
-      var result = FormatStackTrace(error_string, GetStackFrames(stack));
-      %SetOverflowedStackTrace(holder, result);
-      return result;
-    }
-    return void 0;
+    var raw_stack = %GetOverflowedRawStackTrace(holder);
+ var result = IS_ARRAY(raw_stack) ? FormatRawStackTrace(holder, raw_stack)
+                                     : void 0;
+    %DefineOrRedefineDataProperty(holder, 'stack', result, NONE);
+    return result;
   }
-  %MarkOneShotGetter(getter);

   // The 'stack' property of the receiver is set as data property.  If
   // the receiver is the same as holder, this accessor pair is replaced.
   function setter(v) {
     %DefineOrRedefineDataProperty(this, 'stack', v, NONE);
- // Release the stack trace that is stored as hidden property, if exists.
-    %SetOverflowedStackTrace(this, void 0);
   }

   %DefineOrRedefineAccessorProperty(
=======================================
--- /trunk/src/runtime.cc       Fri Dec 21 04:35:02 2012
+++ /trunk/src/runtime.cc       Thu Dec 27 07:57:11 2012
@@ -13206,47 +13206,17 @@
 }


-// Mark a function to recognize when called after GC to format the stack trace.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_MarkOneShotGetter) {
-  ASSERT_EQ(args.length(), 1);
-  CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
-  HandleScope scope(isolate);
-  Handle<String> key = isolate->factory()->hidden_stack_trace_symbol();
-  JSObject::SetHiddenProperty(fun, key, key);
-  return *fun;
-}
-
-
-// Retrieve the stack trace.  This could be the raw stack trace collected
-// on stack overflow or the already formatted stack trace string.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOverflowedStackTrace) {
-  HandleScope scope(isolate);
+// Retrieve the raw stack trace collected on stack overflow and delete
+// it since it is used only once to avoid keeping it alive.
+RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOverflowedRawStackTrace) {
   ASSERT_EQ(args.length(), 1);
   CONVERT_ARG_CHECKED(JSObject, error_object, 0);
   String* key = isolate->heap()->hidden_stack_trace_symbol();
   Object* result = error_object->GetHiddenProperty(key);
-  RUNTIME_ASSERT(result->IsJSArray() ||
-                 result->IsString() ||
-                 result->IsUndefined());
+  RUNTIME_ASSERT(result->IsJSArray() || result->IsUndefined());
+  error_object->DeleteHiddenProperty(key);
   return result;
 }
-
-
-// Set or clear the stack trace attached to an stack overflow error object.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetOverflowedStackTrace) {
-  HandleScope scope(isolate);
-  ASSERT_EQ(args.length(), 2);
-  CONVERT_ARG_HANDLE_CHECKED(JSObject, error_object, 0);
-  CONVERT_ARG_HANDLE_CHECKED(HeapObject, value, 1);
-  Handle<String> key = isolate->factory()->hidden_stack_trace_symbol();
-  if (value->IsUndefined()) {
-    error_object->DeleteHiddenProperty(*key);
-  } else {
-    RUNTIME_ASSERT(value->IsString());
-    JSObject::SetHiddenProperty(error_object, key, value);
-  }
-  return *error_object;
-}


 // Returns V8 version as a string.
=======================================
--- /trunk/src/runtime.h        Fri Dec 21 04:35:02 2012
+++ /trunk/src/runtime.h        Thu Dec 27 07:57:11 2012
@@ -237,9 +237,7 @@
   F(FunctionIsBuiltin, 1, 1) \
   F(GetScript, 1, 1) \
   F(CollectStackTrace, 3, 1) \
-  F(MarkOneShotGetter, 1, 1) \
-  F(GetOverflowedStackTrace, 1, 1) \
-  F(SetOverflowedStackTrace, 2, 1) \
+  F(GetOverflowedRawStackTrace, 1, 1) \
   F(GetV8Version, 0, 1) \
   \
   F(ClassOf, 1, 1) \
=======================================
--- /trunk/src/version.cc       Fri Dec 21 05:47:00 2012
+++ /trunk/src/version.cc       Thu Dec 27 07:57:11 2012
@@ -34,7 +34,7 @@
 // cannot be changed without changing the SCons build script.
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     16
-#define BUILD_NUMBER      0
+#define BUILD_NUMBER      1
 #define PATCH_LEVEL       0
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
=======================================
--- /trunk/src/x64/assembler-x64.cc     Fri Dec 21 04:35:02 2012
+++ /trunk/src/x64/assembler-x64.cc     Thu Dec 27 07:57:11 2012
@@ -2950,6 +2950,15 @@
   emit(0x50);
   emit_sse_operand(dst, src);
 }
+
+
+void Assembler::movmskps(Register dst, XMMRegister src) {
+  EnsureSpace ensure_space(this);
+  emit_optional_rex_32(dst, src);
+  emit(0x0f);
+  emit(0x50);
+  emit_sse_operand(dst, src);
+}


 void Assembler::emit_sse_operand(XMMRegister reg, const Operand& adr) {
=======================================
--- /trunk/src/x64/assembler-x64.h      Fri Dec 21 04:35:02 2012
+++ /trunk/src/x64/assembler-x64.h      Thu Dec 27 07:57:11 2012
@@ -1394,6 +1394,7 @@
   void roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode);

   void movmskpd(Register dst, XMMRegister src);
+  void movmskps(Register dst, XMMRegister src);

// The first argument is the reg field, the second argument is the r/m field.
   void emit_sse_operand(XMMRegister dst, XMMRegister src);
=======================================
--- /trunk/src/x64/disasm-x64.cc        Thu Jun 21 04:16:20 2012
+++ /trunk/src/x64/disasm-x64.cc        Thu Dec 27 07:57:11 2012
@@ -1244,6 +1244,13 @@
     AppendToBuffer("xorps %s, ", NameOfXMMRegister(regop));
     current += PrintRightXMMOperand(current);

+  } else if (opcode == 0x50) {
+    // movmskps reg, xmm
+    int mod, regop, rm;
+    get_modrm(*current, &mod, &regop, &rm);
+    AppendToBuffer("movmskps %s, ", NameOfCPURegister(regop));
+    current += PrintRightXMMOperand(current);
+
   } else if ((opcode & 0xF0) == 0x80) {
     // Jcc: Conditional jump (branch).
     current = data + JumpConditional(data);
@@ -1724,6 +1731,11 @@
         data += F6F7Instruction(data);
         break;

+      case 0x3C:
+ AppendToBuffer("cmp al, 0x%x", *reinterpret_cast<int8_t*>(data + 1));
+        data +=2;
+        break;
+
       default:
         UnimplementedInstruction();
         data += 1;
=======================================
--- /trunk/src/x64/lithium-codegen-x64.cc       Fri Dec 21 04:35:02 2012
+++ /trunk/src/x64/lithium-codegen-x64.cc       Thu Dec 27 07:57:11 2012
@@ -1642,17 +1642,17 @@
     if (right->IsConstantOperand()) {
       Immediate right_imm =
           Immediate(ToInteger32(LConstantOperand::cast(right)));
-      __ cmpq(left_reg, right_imm);
+      __ cmpl(left_reg, right_imm);
       __ j(condition, &return_left, Label::kNear);
       __ movq(left_reg, right_imm);
     } else if (right->IsRegister()) {
       Register right_reg = ToRegister(right);
-      __ cmpq(left_reg, right_reg);
+      __ cmpl(left_reg, right_reg);
       __ j(condition, &return_left, Label::kNear);
       __ movq(left_reg, right_reg);
     } else {
       Operand right_op = ToOperand(right);
-      __ cmpq(left_reg, right_op);
+      __ cmpl(left_reg, right_op);
       __ j(condition, &return_left, Label::kNear);
       __ movq(left_reg, right_op);
     }
=======================================
--- /trunk/test/cctest/test-decls.cc    Fri Dec 21 04:35:02 2012
+++ /trunk/test/cctest/test-decls.cc    Thu Dec 27 07:57:11 2012
@@ -161,7 +161,6 @@
       CHECK_EQ(value, catcher.Exception());
     }
   }
-  HEAP->CollectAllAvailableGarbage();  // Clean slate for the next test.
 }


=======================================
--- /trunk/test/cctest/test-heap.cc     Fri Dec 21 04:35:02 2012
+++ /trunk/test/cctest/test-heap.cc     Thu Dec 27 07:57:11 2012
@@ -2429,7 +2429,11 @@
     CHECK(!resource->IsDisposed());
   }
   HEAP->CollectAllAvailableGarbage();
+  // External source is being retained by the stack trace.
+  CHECK(!resource->IsDisposed());

+  CompileRun("error.stack;");
+  HEAP->CollectAllAvailableGarbage();
   // External source has been released.
   CHECK(resource->IsDisposed());
   delete resource;
=======================================
--- /trunk/test/cctest/test-object-observe.cc   Fri Dec 21 04:35:02 2012
+++ /trunk/test/cctest/test-object-observe.cc   Thu Dec 27 07:57:11 2012
@@ -278,6 +278,7 @@
   }
   CHECK_EQ(3, CompileRun("records.length")->Int32Value());
 }
+

 struct RecordExpectation {
   Handle<Value> object;
@@ -309,6 +310,9 @@
     }
   }
 }
+
+#define EXPECT_RECORDS(records, expectations) \
+    ExpectRecords(records, expectations, ARRAY_SIZE(expectations))

 TEST(APITestBasicMutation) {
   HarmonyIsolate isolate;
@@ -348,7 +352,48 @@
     { obj, "deleted", "1", Number::New(5) },
     { obj, "deleted", "1.1", Number::New(6) }
   };
-  ExpectRecords(CompileRun("records"),
-                expected_records,
-                ARRAY_SIZE(expected_records));
+  EXPECT_RECORDS(CompileRun("records"), expected_records);
+}
+
+TEST(HiddenPrototypeObservation) {
+  HarmonyIsolate isolate;
+  HandleScope scope;
+  LocalContext context;
+  Handle<FunctionTemplate> tmpl = FunctionTemplate::New();
+  tmpl->SetHiddenPrototype(true);
+  tmpl->InstanceTemplate()->Set(String::New("foo"), Number::New(75));
+  Handle<Object> proto = tmpl->GetFunction()->NewInstance();
+  Handle<Object> obj = Object::New();
+  obj->SetPrototype(proto);
+  context->Global()->Set(String::New("obj"), obj);
+  context->Global()->Set(String::New("proto"), proto);
+  CompileRun(
+      "var records;"
+      "function observer(r) { records = r; };"
+      "Object.observe(obj, observer);"
+      "obj.foo = 41;"  // triggers a notification
+      "proto.foo = 42;");  // does not trigger a notification
+  const RecordExpectation expected_records[] = {
+    { obj, "updated", "foo", Number::New(75) }
+  };
+  EXPECT_RECORDS(CompileRun("records"), expected_records);
+  obj->SetPrototype(Null());
+  CompileRun("obj.foo = 43");
+  const RecordExpectation expected_records2[] = {
+    { obj, "new", "foo", Handle<Value>() }
+  };
+  EXPECT_RECORDS(CompileRun("records"), expected_records2);
+  obj->SetPrototype(proto);
+  CompileRun(
+      "Object.observe(proto, observer);"
+      "proto.bar = 1;"
+      "Object.unobserve(obj, observer);"
+      "obj.foo = 44;");
+  const RecordExpectation expected_records3[] = {
+    { proto, "new", "bar", Handle<Value>() }
+ // TODO(adamk): The below record should be emitted since proto is observed
+    // and has been modified. Not clear if this happens in practice.
+    // { proto, "updated", "foo", Number::New(43) }
+  };
+  EXPECT_RECORDS(CompileRun("records"), expected_records3);
 }
=======================================
--- /trunk/test/message/overwritten-builtins.out        Fri Dec 21 04:35:02 2012
+++ /trunk/test/message/overwritten-builtins.out        Thu Dec 27 07:57:11 2012
@@ -28,6 +28,3 @@
 *%(basename)s:31: TypeError: Cannot read property 'x' of undefined
 undefined.x
          ^
-TypeError: Cannot read property 'x' of undefined
-    at *%(basename)s:31:10
-
=======================================
--- /trunk/test/mjsunit/eval-stack-trace.js     Fri Dec 21 04:35:02 2012
+++ /trunk/test/mjsunit/eval-stack-trace.js     Thu Dec 27 07:57:11 2012
@@ -26,13 +26,12 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

 // Return the stack frames of an Error object.
-
-Error.prepareStackTrace = function(error, frames) {
-  return frames;
-}
-
 Error.prototype.getFrames = function() {
+  Error.prepareStackTrace = function(error, frames) {
+    return frames;
+  }
   var frames = this.stack;
+  Error.prepareStackTrace = undefined;
   return frames;
 }

=======================================
--- /trunk/test/mjsunit/stack-traces.js Fri Dec 21 04:35:02 2012
+++ /trunk/test/mjsunit/stack-traces.js Thu Dec 27 07:57:11 2012
@@ -289,41 +289,3 @@

 // Omitted because ADD from runtime.js is non-native builtin.
 testOmittedBuiltin(function(){ thrower + 2; }, "ADD");
-
-var error = new Error();
-error.toString = function() { assertUnreachable(); };
-error.stack;
-
-error = new Error();
-error.name = { toString: function() { assertUnreachable(); }};
-error.message = { toString: function() {  assertUnreachable(); }};
-error.stack;
-
-error = new Error();
-Array.prototype.push = function(x) { assertUnreachable(); };
-Array.prototype.join = function(x) { assertUnreachable(); };
-error.stack;
-
-var fired = false;
-error = new Error({ toString: function() { fired = true; } });
-assertTrue(fired);
-error.stack;
-assertTrue(fired);
-
-// Check that throwing exception in a custom stack trace formatting function
-// does not lead to recursion.
-Error.prepareStackTrace = function() { throw new Error("abc"); };
-var message;
-try {
-  throw new Error();
-} catch (e) {
-  message = e.message;
-}
-
-assertEquals("abc", message);
-
-// Test that modifying Error.prepareStackTrace by itself works.
-Error.prepareStackTrace = function() { Error.prepareStackTrace = "custom"; };
-new Error();
-
-assertEquals("custom", Error.prepareStackTrace);

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

Reply via email to