Push version 1.3.10 to trunk.

Fixed profiler on Mac in 64-bit mode.

Optimized creation of objects from simple constructor functions on ARM.

Fixed a number of debugger issues.

Reduced the amount of memory consumed by V8.




git-svn-id: http://v8.googlecode.com/svn/trunk@2866 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/test/cctest/cctest.status b/test/cctest/cctest.status
index 67e9d8a..68aabb5 100644
--- a/test/cctest/cctest.status
+++ b/test/cctest/cctest.status
@@ -50,10 +50,6 @@
 test-api/OutOfMemory: SKIP
 test-api/OutOfMemoryNested: SKIP
 
-# BUG(432): Fail on ARM hardware.
-test-regexp/MacroAssemblerNativeSimple: PASS || FAIL
-test-regexp/MacroAssemblerNativeSimpleUC16: PASS || FAIL
-
 # BUG(355): Test crashes on ARM.
 test-log/ProfLazyMode: SKIP
 
diff --git a/test/cctest/test-assembler-arm.cc b/test/cctest/test-assembler-arm.cc
index 34f1639..f6e4d04 100644
--- a/test/cctest/test-assembler-arm.cc
+++ b/test/cctest/test-assembler-arm.cc
@@ -37,9 +37,9 @@
 
 
 // Define these function prototypes to match JSEntryFunction in execution.cc.
-typedef int (*F1)(int x, int p1, int p2, int p3, int p4);
-typedef int (*F2)(int x, int y, int p2, int p3, int p4);
-typedef int (*F3)(void* p, int p1, int p2, int p3, int p4);
+typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4);
+typedef Object* (*F2)(int x, int y, int p2, int p3, int p4);
+typedef Object* (*F3)(void* p, int p1, int p2, int p3, int p4);
 
 
 static v8::Persistent<v8::Context> env;
diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc
index bd09d0d..0cae26c 100644
--- a/test/cctest/test-debug.cc
+++ b/test/cctest/test-debug.cc
@@ -4503,14 +4503,16 @@
 
 
 TEST(DebuggerAgent) {
-  // Make sure this port is not used by other tests to allow tests to run in
+  // Make sure these ports is not used by other tests to allow tests to run in
   // parallel.
-  const int kPort = 5858;
+  const int kPort1 = 5858;
+  const int kPort2 = 5857;
+  const int kPort3 = 5856;
 
-  // Make a string with the port number.
+  // Make a string with the port2 number.
   const int kPortBufferLen = 6;
-  char port_str[kPortBufferLen];
-  OS::SNPrintF(i::Vector<char>(port_str, kPortBufferLen), "%d", kPort);
+  char port2_str[kPortBufferLen];
+  OS::SNPrintF(i::Vector<char>(port2_str, kPortBufferLen), "%d", kPort2);
 
   bool ok;
 
@@ -4518,15 +4520,15 @@
   i::Socket::Setup();
 
   // Test starting and stopping the agent without any client connection.
-  i::Debugger::StartAgent("test", kPort);
+  i::Debugger::StartAgent("test", kPort1);
   i::Debugger::StopAgent();
 
   // Test starting the agent, connecting a client and shutting down the agent
   // with the client connected.
-  ok = i::Debugger::StartAgent("test", kPort);
+  ok = i::Debugger::StartAgent("test", kPort2);
   CHECK(ok);
   i::Socket* client = i::OS::CreateSocket();
-  ok = client->Connect("localhost", port_str);
+  ok = client->Connect("localhost", port2_str);
   CHECK(ok);
   i::Debugger::StopAgent();
   delete client;
@@ -4534,9 +4536,9 @@
   // Test starting and stopping the agent with the required port already
   // occoupied.
   i::Socket* server = i::OS::CreateSocket();
-  server->Bind(kPort);
+  server->Bind(kPort3);
 
-  i::Debugger::StartAgent("test", kPort);
+  i::Debugger::StartAgent("test", kPort3);
   i::Debugger::StopAgent();
 
   delete server;
diff --git a/test/cctest/test-log.cc b/test/cctest/test-log.cc
index 5884a41..dafd3aa 100644
--- a/test/cctest/test-log.cc
+++ b/test/cctest/test-log.cc
@@ -5,12 +5,15 @@
 #ifdef ENABLE_LOGGING_AND_PROFILING
 
 #ifdef __linux__
+#include <math.h>
+#include <pthread.h>
 #include <signal.h>
 #include <unistd.h>
-#endif
+#endif  // __linux__
 
 #include "v8.h"
 #include "log.h"
+#include "v8threads.h"
 #include "cctest.h"
 
 using v8::internal::Address;
@@ -155,9 +158,10 @@
 #ifdef __linux__
 
 struct sigaction old_sigprof_handler;
+pthread_t our_thread;
 
 static void SigProfSignalHandler(int signal, siginfo_t* info, void* context) {
-  if (signal != SIGPROF) return;
+  if (signal != SIGPROF || !pthread_equal(pthread_self(), our_thread)) return;
   was_sigprof_received = true;
   old_sigprof_handler.sa_sigaction(signal, info, context);
 }
@@ -185,6 +189,7 @@
   // Intercept SIGPROF handler to make sure that the test process
   // had received it. Under load, system can defer it causing test failure.
   // It is important to execute this after 'ResumeProfiler'.
+  our_thread = pthread_self();
   was_sigprof_received = false;
   struct sigaction sa;
   sa.sa_sigaction = SigProfSignalHandler;
@@ -280,6 +285,158 @@
 }
 
 
+// Profiling multiple threads that use V8 is currently only available on Linux.
+#ifdef __linux__
+
+namespace {
+
+class LoopingThread : public v8::internal::Thread {
+ public:
+  LoopingThread()
+      : v8::internal::Thread(),
+        semaphore_(v8::internal::OS::CreateSemaphore(0)),
+        run_(true) {
+  }
+
+  virtual ~LoopingThread() { delete semaphore_; }
+
+  void Run() {
+    self_ = pthread_self();
+    RunLoop();
+  }
+
+  void SendSigProf() { pthread_kill(self_, SIGPROF); }
+
+  void Stop() { run_ = false; }
+
+  bool WaitForRunning() { return semaphore_->Wait(1000000); }
+
+ protected:
+  bool IsRunning() { return run_; }
+
+  virtual void RunLoop() = 0;
+
+  void SetV8ThreadId() {
+    v8_thread_id_ = v8::V8::GetCurrentThreadId();
+  }
+
+  void SignalRunning() { semaphore_->Signal(); }
+
+ private:
+  v8::internal::Semaphore* semaphore_;
+  bool run_;
+  pthread_t self_;
+  int v8_thread_id_;
+};
+
+
+class LoopingJsThread : public LoopingThread {
+ public:
+  void RunLoop() {
+    {
+      v8::Locker locker;
+      CHECK(v8::internal::ThreadManager::HasId());
+      SetV8ThreadId();
+    }
+    while (IsRunning()) {
+      v8::Locker locker;
+      v8::HandleScope scope;
+      v8::Persistent<v8::Context> context = v8::Context::New();
+      v8::Context::Scope context_scope(context);
+      SignalRunning();
+      CompileAndRunScript(
+          "var j; for (var i=0; i<10000; ++i) { j = Math.sin(i); }");
+      context.Dispose();
+      i::OS::Sleep(1);
+    }
+  }
+};
+
+
+class LoopingNonJsThread : public LoopingThread {
+ public:
+  void RunLoop() {
+    v8::Locker locker;
+    v8::Unlocker unlocker;
+    // Now thread has V8's id, but will not run VM code.
+    CHECK(v8::internal::ThreadManager::HasId());
+    double i = 10;
+    SignalRunning();
+    while (IsRunning()) {
+      i = sin(i);
+      i::OS::Sleep(1);
+    }
+  }
+};
+
+
+class TestSampler : public v8::internal::Sampler {
+ public:
+  TestSampler()
+      : Sampler(0, true),
+        semaphore_(v8::internal::OS::CreateSemaphore(0)),
+        was_sample_stack_called_(false) {
+  }
+
+  ~TestSampler() { delete semaphore_; }
+
+  void SampleStack(v8::internal::TickSample*) {
+    was_sample_stack_called_ = true;
+  }
+
+  void Tick(v8::internal::TickSample*) { semaphore_->Signal(); }
+
+  bool WaitForTick() { return semaphore_->Wait(1000000); }
+
+  void Reset() { was_sample_stack_called_ = false; }
+
+  bool WasSampleStackCalled() { return was_sample_stack_called_; }
+
+ private:
+  v8::internal::Semaphore* semaphore_;
+  bool was_sample_stack_called_;
+};
+
+
+}  // namespace
+
+TEST(ProfMultipleThreads) {
+  // V8 needs to be initialized before the first Locker
+  // instantiation. Otherwise, Top::Initialize will reset
+  // thread_id_ in ThreadTopLocal.
+  v8::HandleScope scope;
+  v8::Handle<v8::Context> env = v8::Context::New();
+  env->Enter();
+
+  LoopingJsThread jsThread;
+  jsThread.Start();
+  LoopingNonJsThread nonJsThread;
+  nonJsThread.Start();
+
+  TestSampler sampler;
+  sampler.Start();
+  CHECK(!sampler.WasSampleStackCalled());
+  jsThread.WaitForRunning();
+  jsThread.SendSigProf();
+  CHECK(sampler.WaitForTick());
+  CHECK(sampler.WasSampleStackCalled());
+  sampler.Reset();
+  CHECK(!sampler.WasSampleStackCalled());
+  nonJsThread.WaitForRunning();
+  nonJsThread.SendSigProf();
+  CHECK(sampler.WaitForTick());
+  CHECK(!sampler.WasSampleStackCalled());
+  sampler.Stop();
+
+  jsThread.Stop();
+  nonJsThread.Stop();
+  jsThread.Join();
+  nonJsThread.Join();
+}
+
+#endif  // __linux__
+
+
 static inline bool IsStringEqualTo(const char* r, const char* s) {
   return strncmp(r, s, strlen(r)) == 0;
 }
diff --git a/test/cctest/testcfg.py b/test/cctest/testcfg.py
index 75377db..c2427c8 100644
--- a/test/cctest/testcfg.py
+++ b/test/cctest/testcfg.py
@@ -31,7 +31,7 @@
 import platform
 import utils
 
-DEBUG_FLAGS = ['--enable-slow-asserts', '--debug-code', '--verify-heap']
+CCTEST_DEBUG_FLAGS = ['--enable-slow-asserts', '--debug-code', '--verify-heap']
 
 
 class CcTestCase(test.TestCase):
@@ -55,7 +55,7 @@
     serialization_option = '--testing_serialization_file=' + serialization_file
     result = [ self.executable, name, serialization_option ]
     if self.mode == 'debug':
-      result += DEBUG_FLAGS
+      result += CCTEST_DEBUG_FLAGS
     return result
 
   def GetCommand(self):
diff --git a/test/mjsunit/debug-scopes.js b/test/mjsunit/debug-scopes.js
index 7b477e1..e87cbb7 100644
--- a/test/mjsunit/debug-scopes.js
+++ b/test/mjsunit/debug-scopes.js
@@ -140,6 +140,11 @@
   if (!scope.scopeObject().property('arguments').isUndefined()) {
     scope_size--;
   }
+  // Also ignore synthetic variable from catch block.
+  if (!scope.scopeObject().property('.catch-var').isUndefined()) {
+    scope_size--;
+  }
+
   if (count != scope_size) {
     print('Names found in scope:');
     var names = scope.scopeObject().propertyNames();
@@ -656,5 +661,101 @@
 debugger;
 EndTest();
 
+
+BeginTest("Catch block 1");
+function catch_block_1() {
+  try {
+    throw 'Exception';
+  } catch (e) {
+    debugger;
+  }
+};
+
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Catch,
+                   debug.ScopeType.Local,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({e:'Exception'}, 0, exec_state);
+}
+catch_block_1()
+EndTest();
+
+
+BeginTest("Catch block 2");
+function catch_block_2() {
+  try {
+    throw 'Exception';
+  } catch (e) {
+    with({n:10}) {
+      debugger;
+    }
+  }
+};
+
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.With,
+                   debug.ScopeType.Catch,
+                   debug.ScopeType.Local,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({n:10}, 0, exec_state);
+  CheckScopeContent({e:'Exception'}, 1, exec_state);
+}
+catch_block_2()
+EndTest();
+
+
+BeginTest("Catch block 3");
+function catch_block_1() {
+  // Do eval to dynamically declare a local variable so that the context's
+  // extension slot is initialized with JSContextExtensionObject.
+  eval("var y = 78;");
+  try {
+    throw 'Exception';
+  } catch (e) {
+    debugger;
+  }
+};
+
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Catch,
+                   debug.ScopeType.Local,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({e:'Exception'}, 0, exec_state);
+  CheckScopeContent({y:78}, 1, exec_state);
+}
+catch_block_1()
+EndTest();
+
+
+BeginTest("Catch block 4");
+function catch_block_2() {
+  // Do eval to dynamically declare a local variable so that the context's
+  // extension slot is initialized with JSContextExtensionObject.
+  eval("var y = 98;");
+  try {
+    throw 'Exception';
+  } catch (e) {
+    with({n:10}) {
+      debugger;
+    }
+  }
+};
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.With,
+                   debug.ScopeType.Catch,
+                   debug.ScopeType.Local,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({n:10}, 0, exec_state);
+  CheckScopeContent({e:'Exception'}, 1, exec_state);
+  CheckScopeContent({y:98}, 2, exec_state);
+}
+catch_block_2()
+EndTest();
+
+
 assertEquals(begin_test_count, break_count, 'one or more tests did not enter the debugger');
 assertEquals(begin_test_count, end_test_count, 'one or more tests did not have its result checked');
diff --git a/test/mjsunit/debug-step-stub-callfunction.js b/test/mjsunit/debug-step-stub-callfunction.js
index fbb8078..50d095b 100644
--- a/test/mjsunit/debug-step-stub-callfunction.js
+++ b/test/mjsunit/debug-step-stub-callfunction.js
@@ -54,7 +54,7 @@
 
 break_break_point_hit_count = 0;
 f();
-assertEquals(5, break_break_point_hit_count);
+assertEquals(6, break_break_point_hit_count);
 
 // Use an inner function to ensure that the function call is through CodeStub
 // CallFunction see Ia32CodeGenerator::VisitCall and
@@ -67,7 +67,21 @@
 
 break_break_point_hit_count = 0;
 g();
-assertEquals(4, break_break_point_hit_count);
+assertEquals(5, break_break_point_hit_count);
+
+
+// Use an inner function to ensure that the function call is through CodeStub
+// CallFunction.
+function testCallInExpreesion() {
+  function h() {}
+  debugger;
+  var x = 's' + h(10, 20);
+};
+
+break_break_point_hit_count = 0;
+testCallInExpreesion();
+assertEquals(5, break_break_point_hit_count);
+
 
 // Get rid of the debug event listener.
 Debug.setListener(null);
diff --git a/test/mjsunit/debug-stepin-call-function-stub.js b/test/mjsunit/debug-stepin-call-function-stub.js
new file mode 100644
index 0000000..12f5142
--- /dev/null
+++ b/test/mjsunit/debug-stepin-call-function-stub.js
@@ -0,0 +1,115 @@
+// Copyright 2009 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-debug-as debug

+// Get the Debug object exposed from the debug context global object.

+Debug = debug.Debug

+

+var exception = null;

+var state = 0;

+var expected_function_name = null;

+var expected_source_line_text = null;

+var expected_caller_source_line = null;

+var step_in_count = 2;

+

+// Simple debug event handler which first time will cause 'step in' action

+// to get into g.call and than check that execution is pauesed inside

+// function 'g'.

+function listener(event, exec_state, event_data, data) {

+  try {

+    if (event == Debug.DebugEvent.Break) {

+      if (state == 0) {

+        // Step into f().

+        exec_state.prepareStep(Debug.StepAction.StepIn, step_in_count);

+        state = 2;

+      } else if (state == 2) {

+        assertEquals(expected_source_line_text,

+                     event_data.sourceLineText());

+        assertEquals(expected_function_name, event_data.func().name());

+        state = 3;

+      }

+    }

+  } catch(e) {

+    exception = e;

+  }

+};

+

+// Add the debug event listener.

+Debug.setListener(listener);

+

+

+function g() { 

+   return "s";  // expected line

+}

+

+function testFunction() {

+  var f = g;

+  var s = 1 +f(10);

+}

+

+function g2() { 

+   return "s2";  // expected line

+}

+

+function testFunction2() {

+  var f = g2;

+  var s = 1 +f(10, 20);

+}

+

+// Run three times. First time the function will be compiled lazily,

+// second time cached version will be used.

+for (var i = 0; i < 3; i++) {

+  state = 0;

+  expected_function_name = 'g';

+  expected_source_line_text = '   return "s";  // expected line';

+  step_in_count = 2;

+  // Set a break point and call to invoke the debug event listener.

+  Debug.setBreakPoint(testFunction, 1, 0);

+  testFunction();

+  assertNull(exception);

+  assertEquals(3, state);

+}

+

+// Test stepping into function call when a breakpoint is set at the place

+// of call. Use different pair of functions so that g2 is compiled lazily.

+// Run twice: first time function will be compiled lazily, second time

+// cached version will be used.

+for (var i = 0; i < 3; i++) {

+  state = 0;

+  expected_function_name = 'g2';

+  expected_source_line_text = '   return "s2";  // expected line';

+  step_in_count = 1;

+  // Set a break point and call to invoke the debug event listener.

+  Debug.setBreakPoint(testFunction2, 2, 0);

+  testFunction2();

+  assertNull(exception);

+  assertEquals(3, state);

+}

+

+

+// Get rid of the debug event listener.

+Debug.setListener(null);

diff --git a/test/mjsunit/debug-stepout-recursive-function.js b/test/mjsunit/debug-stepout-recursive-function.js
new file mode 100644
index 0000000..2f8780c
--- /dev/null
+++ b/test/mjsunit/debug-stepout-recursive-function.js
@@ -0,0 +1,106 @@
+// Copyright 2009 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-debug-as debug

+// Get the Debug object exposed from the debug context global object.

+Debug = debug.Debug

+

+var exception = null;

+var step_out_count = 1;

+

+// Simple debug event handler which counts the number of breaks hit and steps.

+var break_point_hit_count = 0;

+function listener(event, exec_state, event_data, data) {

+  try {

+    if (event == Debug.DebugEvent.Break) {

+      break_point_hit_count++;

+      // Continue stepping until returned to bottom frame.

+      if (exec_state.frameCount() > 1) {

+        exec_state.prepareStep(Debug.StepAction.StepOut, step_out_count);

+      }

+

+    }

+  } catch(e) {

+    exception = e;

+  }

+

+};

+

+function BeginTest(name) {

+  test_name = name;

+  break_point_hit_count = 0;

+  exception = null;

+}

+

+function EndTest(expected_break_point_hit_count) {

+  assertEquals(expected_break_point_hit_count, break_point_hit_count, test_name);

+  assertNull(exception, test_name);

+  test_name = null;

+}

+

+// Add the debug event listener.

+Debug.setListener(listener);

+

+

+var shouldBreak = null;

+function fact(x) {

+  if (shouldBreak(x)) {

+    debugger;

+  }

+  if (x < 2) {

+    return 1;

+  } else {

+    return x*fact(x-1);

+  }

+}

+

+BeginTest('Test 1');

+shouldBreak = function(x) { return x == 3; };

+step_out_count = 1;

+fact(3);

+EndTest(2);

+

+BeginTest('Test 2');

+shouldBreak = function(x) { return x == 2; };

+step_out_count = 1;

+fact(3);

+EndTest(3);

+

+BeginTest('Test 3');

+shouldBreak = function(x) { return x == 1; };

+step_out_count = 2;

+fact(3);

+EndTest(2);

+

+BeginTest('Test 4');

+shouldBreak = function(x) { print(x); return x == 1 || x == 3; };

+step_out_count = 2;

+fact(3);

+EndTest(3);

+

+// Get rid of the debug event listener.

+Debug.setListener(null);

diff --git a/test/mjsunit/debug-stepout-to-builtin.js b/test/mjsunit/debug-stepout-to-builtin.js
new file mode 100644
index 0000000..486eee0
--- /dev/null
+++ b/test/mjsunit/debug-stepout-to-builtin.js
@@ -0,0 +1,84 @@
+// Copyright 2009 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-debug-as debug

+

+// Get the Debug object exposed from the debug context global object.

+Debug = debug.Debug

+

+var exception = null;

+var state = 1;

+var expected_source_line_text = null;

+var expected_function_name = null;

+

+// Simple debug event handler which first time will cause 'step out' action

+// and than check that execution is paused inside function

+// expected_function_name.

+function listener(event, exec_state, event_data, data) {

+  try {

+    if (event == Debug.DebugEvent.Break) {

+      if (state == 1) {

+        exec_state.prepareStep(Debug.StepAction.StepOut, 2);

+        state = 2;

+      } else if (state == 2) {

+        assertEquals(expected_function_name, event_data.func().name());

+        assertEquals(expected_source_line_text,

+                     event_data.sourceLineText());

+        state = 3;

+      }

+    }

+  } catch(e) {

+    exception = e;

+  }

+};

+

+// Add the debug event listener.

+Debug.setListener(listener);

+

+var obj = {key:10};

+

+function replacer(key, value) {

+  if (key == 'key') {

+    debugger;

+  }

+  return value;

+}

+

+// Test step into function call from a function without local variables.

+function testStepOutToBuiltIn() {

+  expected_function_name = 'testStepOutToBuiltIn';

+  expected_source_line_text = '}  // expected line';

+  JSON.stringify(obj, replacer);

+}  // expected line

+

+state = 1;

+testStepOutToBuiltIn();

+assertNull(exception);

+assertEquals(3, state);

+

+// Get rid of the debug event listener.

+Debug.setListener(null);

diff --git a/test/mjsunit/function-prototype.js b/test/mjsunit/function-prototype.js
index 371311e..c5a5487 100644
--- a/test/mjsunit/function-prototype.js
+++ b/test/mjsunit/function-prototype.js
@@ -90,8 +90,9 @@
 // in GetPrototypeOf and go to a monomorphic IC load instead.
 assertEquals(87, GetPrototypeOf({prototype:87}));
 
-// Check the prototype is enumerable as specified in ECMA262, 15.3.5.2
+// Check the prototype is not enumerable, for compatibility with
+// safari.  This is deliberately incompatible with ECMA262, 15.3.5.2.
 var foo = new Function("return x");
 var result  = ""
 for (var n in foo) result += n;
-assertEquals(result, "prototype");
+assertEquals(result, "");
diff --git a/test/mjsunit/mjsunit.status b/test/mjsunit/mjsunit.status
index 6ac4938..3b89154 100644
--- a/test/mjsunit/mjsunit.status
+++ b/test/mjsunit/mjsunit.status
@@ -60,8 +60,11 @@
 debug-step-stub-callfunction: SKIP
 debug-stepin-accessor: CRASH || FAIL
 debug-stepin-builtin: CRASH || FAIL
+debug-stepin-call-function-stub: CRASH || FAIL
 debug-stepin-constructor: CRASH, FAIL
 debug-stepin-function-call: CRASH || FAIL
+debug-stepout-recursive-function: CRASH || FAIL
+debug-stepout-to-builtin: CRASH || FAIL
 debug-step: SKIP
 debug-breakpoints: PASS || FAIL
 debug-handle: CRASH || FAIL || PASS
diff --git a/test/mjsunit/regress/regress-246.js b/test/mjsunit/regress/regress-246.js
old mode 100755
new mode 100644
diff --git a/test/mjsunit/regress/regress-254.js b/test/mjsunit/regress/regress-254.js
old mode 100755
new mode 100644
diff --git a/test/mjsunit/regress/regress-crbug-18639.js b/test/mjsunit/regress/regress-crbug-18639.js
new file mode 100644
index 0000000..23e225a
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-18639.js
@@ -0,0 +1,34 @@
+// Copyright 2009 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.
+
+// See http://crbug.com/18639
+
+toString = toString;
+__defineGetter__("z", (0).toLocaleString);
+z;
+z;
+((0).toLocaleString)();
diff --git a/test/mjsunit/testcfg.py b/test/mjsunit/testcfg.py
index 96840f5..97924c8 100644
--- a/test/mjsunit/testcfg.py
+++ b/test/mjsunit/testcfg.py
@@ -31,7 +31,7 @@
 import re
 import tempfile
 
-
+MJSUNIT_DEBUG_FLAGS = ['--enable-slow-asserts', '--debug-code', '--verify-heap']
 FLAGS_PATTERN = re.compile(r"//\s+Flags:(.*)")
 FILES_PATTERN = re.compile(r"//\s+Files:(.*)")
 SELF_SCRIPT_PATTERN = re.compile(r"//\s+Env: TEST_FILE_NAME")
@@ -58,6 +58,8 @@
     flags_match = FLAGS_PATTERN.search(source)
     if flags_match:
       result += flags_match.group(1).strip().split()
+    if self.mode == 'debug':
+      result += MJSUNIT_DEBUG_FLAGS
     additional_files = []
     files_match = FILES_PATTERN.search(source);
     # Accept several lines of 'Files:'
diff --git a/test/mozilla/mozilla.status b/test/mozilla/mozilla.status
index 41395b3..9793dc8 100644
--- a/test/mozilla/mozilla.status
+++ b/test/mozilla/mozilla.status
@@ -124,6 +124,10 @@
 ecma/Array/15.4.4.5-3: PASS || ($ARM && FAIL)
 ecma/Date/15.9.5.22-2: PASS || ($ARM && FAIL)
 
+# Flaky test that fails due to what appears to be a bug in the test.
+# Occurs depending on current time
+ecma/Date/15.9.5.8: PASS || FAIL
+
 # Severely brain-damaged test. Access to local variables must not
 # be more than 2.5 times faster than access to global variables? WTF?
 js1_5/Regress/regress-169559: PASS || FAIL