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