Fixed a bunch of memory leaks in tests, including:
- String traversal test data (now in a zone) - Debug message thread (now joined on exit) - Threading test threads (now joined on exit) - Changed message tests framework to cope with valgrind Also, fixed a bug where we'd try to delete stack-allocated objects when tearing down v8. Good times. git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1622 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
d970e04e04
commit
9142c42df2
11
include/v8.h
11
include/v8.h
@ -2033,6 +2033,17 @@ class V8EXPORT V8 {
|
|||||||
*/
|
*/
|
||||||
static void ResumeProfiler();
|
static void ResumeProfiler();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Releases any resources used by v8 and stops any utility threads
|
||||||
|
* that may be running. Note that disposing v8 is permanent, it
|
||||||
|
* cannot be reinitialized.
|
||||||
|
*
|
||||||
|
* It should generally not be necessary to dispose v8 before exiting
|
||||||
|
* a process, this should happen automatically. It is only necessary
|
||||||
|
* to use if the process needs the resources taken up by v8.
|
||||||
|
*/
|
||||||
|
static bool Dispose();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
V8();
|
V8();
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ v8::Handle<v8::String> ReadFile(const char* name);
|
|||||||
void ReportException(v8::TryCatch* handler);
|
void ReportException(v8::TryCatch* handler);
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int RunMain(int argc, char* argv[]) {
|
||||||
v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
|
v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
|
||||||
v8::HandleScope handle_scope;
|
v8::HandleScope handle_scope;
|
||||||
// Create a template for the global object.
|
// Create a template for the global object.
|
||||||
@ -95,11 +95,17 @@ int main(int argc, char* argv[]) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (run_shell) RunShell(context);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
int result = RunMain(argc, argv);
|
||||||
|
v8::V8::Dispose();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Extracts a C string from a V8 Utf8Value.
|
// Extracts a C string from a V8 Utf8Value.
|
||||||
const char* ToCString(const v8::String::Utf8Value& value) {
|
const char* ToCString(const v8::String::Utf8Value& value) {
|
||||||
return *value ? *value : "<string conversion failed>";
|
return *value ? *value : "<string conversion failed>";
|
||||||
|
@ -2272,6 +2272,12 @@ bool v8::V8::Initialize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool v8::V8::Dispose() {
|
||||||
|
i::V8::TearDown();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const char* v8::V8::GetVersion() {
|
const char* v8::V8::GetVersion() {
|
||||||
return "1.1.4 (candidate)";
|
return "1.1.4 (candidate)";
|
||||||
}
|
}
|
||||||
|
24
src/debug.cc
24
src/debug.cc
@ -1737,6 +1737,15 @@ void Debugger::SetEventListener(Handle<Object> callback,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Debugger::TearDown() {
|
||||||
|
if (message_thread_ != NULL) {
|
||||||
|
message_thread_->Stop();
|
||||||
|
delete message_thread_;
|
||||||
|
message_thread_ = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Debugger::SetMessageHandler(v8::DebugMessageHandler handler, void* data) {
|
void Debugger::SetMessageHandler(v8::DebugMessageHandler handler, void* data) {
|
||||||
message_handler_ = handler;
|
message_handler_ = handler;
|
||||||
message_handler_data_ = data;
|
message_handler_data_ = data;
|
||||||
@ -1852,16 +1861,23 @@ void Debugger::StopAgent() {
|
|||||||
DebugMessageThread::DebugMessageThread()
|
DebugMessageThread::DebugMessageThread()
|
||||||
: host_running_(true),
|
: host_running_(true),
|
||||||
command_queue_(kQueueInitialSize),
|
command_queue_(kQueueInitialSize),
|
||||||
message_queue_(kQueueInitialSize) {
|
message_queue_(kQueueInitialSize),
|
||||||
|
keep_running_(true) {
|
||||||
command_received_ = OS::CreateSemaphore(0);
|
command_received_ = OS::CreateSemaphore(0);
|
||||||
message_received_ = OS::CreateSemaphore(0);
|
message_received_ = OS::CreateSemaphore(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Does not free resources held by DebugMessageThread
|
// Should only be done after the thread is done running.
|
||||||
// because this cannot be done thread-safely.
|
|
||||||
DebugMessageThread::~DebugMessageThread() {
|
DebugMessageThread::~DebugMessageThread() {
|
||||||
|
delete command_received_;
|
||||||
|
delete message_received_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DebugMessageThread::Stop() {
|
||||||
|
keep_running_ = false;
|
||||||
|
SendMessage(Vector<uint16_t>(NULL, 0));
|
||||||
|
Join();
|
||||||
|
}
|
||||||
|
|
||||||
// Puts an event coming from V8 on the queue. Creates
|
// Puts an event coming from V8 on the queue. Creates
|
||||||
// a copy of the JSON formatted event string managed by the V8.
|
// a copy of the JSON formatted event string managed by the V8.
|
||||||
@ -1909,7 +1925,7 @@ bool DebugMessageThread::SetEventJSONFromEvent(Handle<Object> event_data) {
|
|||||||
|
|
||||||
void DebugMessageThread::Run() {
|
void DebugMessageThread::Run() {
|
||||||
// Sends debug events to an installed debugger message callback.
|
// Sends debug events to an installed debugger message callback.
|
||||||
while (true) {
|
while (keep_running_) {
|
||||||
// Wait and Get are paired so that semaphore count equals queue length.
|
// Wait and Get are paired so that semaphore count equals queue length.
|
||||||
message_received_->Wait();
|
message_received_->Wait();
|
||||||
Logger::DebugTag("Get message from event message_queue.");
|
Logger::DebugTag("Get message from event message_queue.");
|
||||||
|
@ -429,6 +429,7 @@ class Debugger {
|
|||||||
bool auto_continue);
|
bool auto_continue);
|
||||||
static void SetEventListener(Handle<Object> callback, Handle<Object> data);
|
static void SetEventListener(Handle<Object> callback, Handle<Object> data);
|
||||||
static void SetMessageHandler(v8::DebugMessageHandler handler, void* data);
|
static void SetMessageHandler(v8::DebugMessageHandler handler, void* data);
|
||||||
|
static void TearDown();
|
||||||
static void SetHostDispatchHandler(v8::DebugHostDispatchHandler handler,
|
static void SetHostDispatchHandler(v8::DebugHostDispatchHandler handler,
|
||||||
void* data);
|
void* data);
|
||||||
static void SendMessage(Vector<uint16_t> message);
|
static void SendMessage(Vector<uint16_t> message);
|
||||||
@ -527,7 +528,7 @@ class LockingMessageQueue BASE_EMBEDDED {
|
|||||||
class DebugMessageThread: public Thread {
|
class DebugMessageThread: public Thread {
|
||||||
public:
|
public:
|
||||||
DebugMessageThread(); // Called from API thread.
|
DebugMessageThread(); // Called from API thread.
|
||||||
virtual ~DebugMessageThread(); // Never called.
|
virtual ~DebugMessageThread();
|
||||||
// Called by V8 thread. Reports events from V8 VM.
|
// Called by V8 thread. Reports events from V8 VM.
|
||||||
// Also handles command processing in stopped state of V8,
|
// Also handles command processing in stopped state of V8,
|
||||||
// when host_running_ is false.
|
// when host_running_ is false.
|
||||||
@ -554,6 +555,7 @@ class DebugMessageThread: public Thread {
|
|||||||
|
|
||||||
// Check whether there are commands in the queue.
|
// Check whether there are commands in the queue.
|
||||||
bool HasCommands() { return !command_queue_.IsEmpty(); }
|
bool HasCommands() { return !command_queue_.IsEmpty(); }
|
||||||
|
void Stop();
|
||||||
|
|
||||||
bool host_running_; // Is the debugging host running or stopped?
|
bool host_running_; // Is the debugging host running or stopped?
|
||||||
Semaphore* command_received_; // Non-zero when command queue is non-empty.
|
Semaphore* command_received_; // Non-zero when command queue is non-empty.
|
||||||
@ -564,6 +566,7 @@ class DebugMessageThread: public Thread {
|
|||||||
static const int kQueueInitialSize = 4;
|
static const int kQueueInitialSize = 4;
|
||||||
LockingMessageQueue command_queue_;
|
LockingMessageQueue command_queue_;
|
||||||
LockingMessageQueue message_queue_;
|
LockingMessageQueue message_queue_;
|
||||||
|
bool keep_running_;
|
||||||
DISALLOW_COPY_AND_ASSIGN(DebugMessageThread);
|
DISALLOW_COPY_AND_ASSIGN(DebugMessageThread);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@
|
|||||||
// printing / etc in the flag parser code. We only do this for writable flags.
|
// printing / etc in the flag parser code. We only do this for writable flags.
|
||||||
#elif defined(FLAG_MODE_META)
|
#elif defined(FLAG_MODE_META)
|
||||||
#define FLAG_FULL(ftype, ctype, nam, def, cmt) \
|
#define FLAG_FULL(ftype, ctype, nam, def, cmt) \
|
||||||
{ Flag::TYPE_##ftype, #nam, &FLAG_##nam, &FLAGDEFAULT_##nam, cmt },
|
{ Flag::TYPE_##ftype, #nam, &FLAG_##nam, &FLAGDEFAULT_##nam, cmt, false },
|
||||||
#define FLAG_READONLY(ftype, ctype, nam, def, cmt)
|
#define FLAG_READONLY(ftype, ctype, nam, def, cmt)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
31
src/flags.cc
31
src/flags.cc
@ -58,6 +58,7 @@ struct Flag {
|
|||||||
void* valptr_; // Pointer to the global flag variable.
|
void* valptr_; // Pointer to the global flag variable.
|
||||||
const void* defptr_; // Pointer to the default value.
|
const void* defptr_; // Pointer to the default value.
|
||||||
const char* cmt_; // A comment about the flags purpose.
|
const char* cmt_; // A comment about the flags purpose.
|
||||||
|
bool owns_ptr_; // Does the flag own its string value?
|
||||||
|
|
||||||
FlagType type() const { return type_; }
|
FlagType type() const { return type_; }
|
||||||
|
|
||||||
@ -80,9 +81,17 @@ struct Flag {
|
|||||||
return reinterpret_cast<double*>(valptr_);
|
return reinterpret_cast<double*>(valptr_);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char** string_variable() const {
|
const char* string_value() const {
|
||||||
ASSERT(type_ == TYPE_STRING);
|
ASSERT(type_ == TYPE_STRING);
|
||||||
return reinterpret_cast<const char**>(valptr_);
|
return *reinterpret_cast<const char**>(valptr_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_string_value(const char *value, bool owns_ptr) {
|
||||||
|
ASSERT(type_ == TYPE_STRING);
|
||||||
|
const char **ptr = reinterpret_cast<const char **>(valptr_);
|
||||||
|
if (owns_ptr_ && *ptr != NULL) DeleteArray(*ptr);
|
||||||
|
*ptr = value;
|
||||||
|
owns_ptr_ = owns_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSArguments* args_variable() const {
|
JSArguments* args_variable() const {
|
||||||
@ -125,7 +134,7 @@ struct Flag {
|
|||||||
case TYPE_FLOAT:
|
case TYPE_FLOAT:
|
||||||
return *float_variable() == float_default();
|
return *float_variable() == float_default();
|
||||||
case TYPE_STRING: {
|
case TYPE_STRING: {
|
||||||
const char* str1 = *string_variable();
|
const char* str1 = string_value();
|
||||||
const char* str2 = string_default();
|
const char* str2 = string_default();
|
||||||
if (str2 == NULL) return str1 == NULL;
|
if (str2 == NULL) return str1 == NULL;
|
||||||
if (str1 == NULL) return str2 == NULL;
|
if (str1 == NULL) return str2 == NULL;
|
||||||
@ -151,7 +160,7 @@ struct Flag {
|
|||||||
*float_variable() = float_default();
|
*float_variable() = float_default();
|
||||||
break;
|
break;
|
||||||
case TYPE_STRING:
|
case TYPE_STRING:
|
||||||
*string_variable() = string_default();
|
set_string_value(string_default(), false);
|
||||||
break;
|
break;
|
||||||
case TYPE_ARGS:
|
case TYPE_ARGS:
|
||||||
*args_variable() = args_default();
|
*args_variable() = args_default();
|
||||||
@ -197,7 +206,7 @@ static SmartPointer<const char> ToString(Flag* flag) {
|
|||||||
buffer.Add("%f", FmtElm(*flag->float_variable()));
|
buffer.Add("%f", FmtElm(*flag->float_variable()));
|
||||||
break;
|
break;
|
||||||
case Flag::TYPE_STRING: {
|
case Flag::TYPE_STRING: {
|
||||||
const char* str = *flag->string_variable();
|
const char* str = flag->string_value();
|
||||||
buffer.Add("%s", str ? str : "NULL");
|
buffer.Add("%s", str ? str : "NULL");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -389,17 +398,17 @@ int FlagList::SetFlagsFromCommandLine(int* argc,
|
|||||||
*flag->float_variable() = strtod(value, &endp);
|
*flag->float_variable() = strtod(value, &endp);
|
||||||
break;
|
break;
|
||||||
case Flag::TYPE_STRING:
|
case Flag::TYPE_STRING:
|
||||||
*flag->string_variable() = value;
|
flag->set_string_value(value ? StrDup(value) : NULL, true);
|
||||||
break;
|
break;
|
||||||
case Flag::TYPE_ARGS: {
|
case Flag::TYPE_ARGS: {
|
||||||
int start_pos = (value == NULL) ? i : i - 1;
|
int start_pos = (value == NULL) ? i : i - 1;
|
||||||
int js_argc = *argc - start_pos;
|
int js_argc = *argc - start_pos;
|
||||||
const char** js_argv = NewArray<const char*>(js_argc);
|
const char** js_argv = NewArray<const char*>(js_argc);
|
||||||
if (value != NULL) {
|
if (value != NULL) {
|
||||||
js_argv[0] = value;
|
js_argv[0] = StrDup(value);
|
||||||
}
|
}
|
||||||
for (int k = i; k < *argc; k++) {
|
for (int k = i; k < *argc; k++) {
|
||||||
js_argv[k - start_pos] = argv[k];
|
js_argv[k - start_pos] = StrDup(argv[k]);
|
||||||
}
|
}
|
||||||
*flag->args_variable() = JSArguments(js_argc, js_argv);
|
*flag->args_variable() = JSArguments(js_argc, js_argv);
|
||||||
i = *argc; // Consume all arguments
|
i = *argc; // Consume all arguments
|
||||||
@ -491,11 +500,7 @@ int FlagList::SetFlagsFromString(const char* str, int len) {
|
|||||||
|
|
||||||
// cleanup
|
// cleanup
|
||||||
DeleteArray(argv);
|
DeleteArray(argv);
|
||||||
// don't delete copy0 since the substrings
|
DeleteArray(copy0);
|
||||||
// may be pointed to by FLAG variables!
|
|
||||||
// (this is a memory leak, but it's minor since this
|
|
||||||
// code is only used for debugging, or perhaps once
|
|
||||||
// during initialization).
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -407,6 +407,7 @@ FILE* Logger::logfile_ = NULL;
|
|||||||
Profiler* Logger::profiler_ = NULL;
|
Profiler* Logger::profiler_ = NULL;
|
||||||
Mutex* Logger::mutex_ = NULL;
|
Mutex* Logger::mutex_ = NULL;
|
||||||
VMState* Logger::current_state_ = NULL;
|
VMState* Logger::current_state_ = NULL;
|
||||||
|
VMState Logger::bottom_state_(OTHER);
|
||||||
SlidingStateWindow* Logger::sliding_state_window_ = NULL;
|
SlidingStateWindow* Logger::sliding_state_window_ = NULL;
|
||||||
|
|
||||||
#endif // ENABLE_LOGGING_AND_PROFILING
|
#endif // ENABLE_LOGGING_AND_PROFILING
|
||||||
@ -1017,7 +1018,7 @@ bool Logger::Setup() {
|
|||||||
mutex_ = OS::CreateMutex();
|
mutex_ = OS::CreateMutex();
|
||||||
}
|
}
|
||||||
|
|
||||||
current_state_ = new VMState(OTHER);
|
current_state_ = &bottom_state_;
|
||||||
|
|
||||||
// as log is initialized early with V8, we can assume that JS execution
|
// as log is initialized early with V8, we can assume that JS execution
|
||||||
// frames can never reach this point on stack
|
// frames can never reach this point on stack
|
||||||
@ -1052,8 +1053,6 @@ void Logger::TearDown() {
|
|||||||
profiler_ = NULL;
|
profiler_ = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deleting the current_state_ has the side effect of assigning to it(!).
|
|
||||||
while (current_state_) delete current_state_;
|
|
||||||
delete sliding_state_window_;
|
delete sliding_state_window_;
|
||||||
|
|
||||||
delete ticker_;
|
delete ticker_;
|
||||||
|
@ -83,7 +83,7 @@ class LogMessageBuilder;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
class VMState {
|
class VMState BASE_EMBEDDED {
|
||||||
#ifdef ENABLE_LOGGING_AND_PROFILING
|
#ifdef ENABLE_LOGGING_AND_PROFILING
|
||||||
public:
|
public:
|
||||||
explicit VMState(StateTag state);
|
explicit VMState(StateTag state);
|
||||||
@ -252,6 +252,9 @@ class Logger {
|
|||||||
// A stack of VM states.
|
// A stack of VM states.
|
||||||
static VMState* current_state_;
|
static VMState* current_state_;
|
||||||
|
|
||||||
|
// Singleton bottom or default vm state.
|
||||||
|
static VMState bottom_state_;
|
||||||
|
|
||||||
// SlidingStateWindow instance keeping a sliding window of the most
|
// SlidingStateWindow instance keeping a sliding window of the most
|
||||||
// recent VM states.
|
// recent VM states.
|
||||||
static SlidingStateWindow* sliding_state_window_;
|
static SlidingStateWindow* sliding_state_window_;
|
||||||
|
@ -417,6 +417,7 @@ class ThreadHandle::PlatformData : public Malloced {
|
|||||||
case ThreadHandle::INVALID: thread_ = kNoThread; break;
|
case ThreadHandle::INVALID: thread_ = kNoThread; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_t thread_; // Thread handle for pthread.
|
pthread_t thread_; // Thread handle for pthread.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -111,6 +111,8 @@ void V8::TearDown() {
|
|||||||
Heap::TearDown();
|
Heap::TearDown();
|
||||||
Logger::TearDown();
|
Logger::TearDown();
|
||||||
|
|
||||||
|
Debugger::TearDown();
|
||||||
|
|
||||||
has_been_setup_ = false;
|
has_been_setup_ = false;
|
||||||
has_been_disposed_ = true;
|
has_been_disposed_ = true;
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,12 @@ inline void* Zone::New(int size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T* Zone::NewArray(int length) {
|
||||||
|
return static_cast<T*>(Zone::New(length * sizeof(T)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Zone::excess_allocation() {
|
bool Zone::excess_allocation() {
|
||||||
return segment_bytes_allocated_ > zone_excess_limit_;
|
return segment_bytes_allocated_ > zone_excess_limit_;
|
||||||
}
|
}
|
||||||
|
@ -58,6 +58,9 @@ class Zone {
|
|||||||
// allocating new segments of memory on demand using malloc().
|
// allocating new segments of memory on demand using malloc().
|
||||||
static inline void* New(int size);
|
static inline void* New(int size);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static inline T* NewArray(int length);
|
||||||
|
|
||||||
// Delete all objects and free all memory allocated in the Zone.
|
// Delete all objects and free all memory allocated in the Zone.
|
||||||
static void DeleteAll();
|
static void DeleteAll();
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include "cctest.h"
|
#include "cctest.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
|
||||||
CcTest* CcTest::last_ = NULL;
|
CcTest* CcTest::last_ = NULL;
|
||||||
@ -120,5 +121,6 @@ int main(int argc, char* argv[]) {
|
|||||||
}
|
}
|
||||||
if (print_run_count && tests_run != 1)
|
if (print_run_count && tests_run != 1)
|
||||||
printf("Ran %i tests.\n", tests_run);
|
printf("Ran %i tests.\n", tests_run);
|
||||||
|
v8::V8::Dispose();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -154,7 +154,7 @@ class ApiTestFuzzer: public v8::internal::Thread {
|
|||||||
class RegisterThreadedTest {
|
class RegisterThreadedTest {
|
||||||
public:
|
public:
|
||||||
explicit RegisterThreadedTest(CcTest::TestFunction* callback)
|
explicit RegisterThreadedTest(CcTest::TestFunction* callback)
|
||||||
: callback_(callback) {
|
: fuzzer_(NULL), callback_(callback) {
|
||||||
prev_ = first_;
|
prev_ = first_;
|
||||||
first_ = this;
|
first_ = this;
|
||||||
count_++;
|
count_++;
|
||||||
@ -5098,6 +5098,10 @@ void ApiTestFuzzer::ContextSwitch() {
|
|||||||
|
|
||||||
void ApiTestFuzzer::TearDown() {
|
void ApiTestFuzzer::TearDown() {
|
||||||
fuzzing_ = false;
|
fuzzing_ = false;
|
||||||
|
for (int i = 0; i < RegisterThreadedTest::count(); i++) {
|
||||||
|
ApiTestFuzzer *fuzzer = RegisterThreadedTest::nth(i)->fuzzer_;
|
||||||
|
if (fuzzer != NULL) fuzzer->Join();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include "factory.h"
|
#include "factory.h"
|
||||||
#include "cctest.h"
|
#include "cctest.h"
|
||||||
|
#include "zone-inl.h"
|
||||||
|
|
||||||
unsigned int seed = 123;
|
unsigned int seed = 123;
|
||||||
|
|
||||||
@ -48,6 +49,8 @@ static const int SUPER_DEEP_DEPTH = 80 * 1024;
|
|||||||
|
|
||||||
static void InitializeBuildingBlocks(
|
static void InitializeBuildingBlocks(
|
||||||
Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS]) {
|
Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS]) {
|
||||||
|
// A list of pointers that we don't have any interest in cleaning up.
|
||||||
|
// If they are reachable from a root then leak detection won't complain.
|
||||||
for (int i = 0; i < NUMBER_OF_BUILDING_BLOCKS; i++) {
|
for (int i = 0; i < NUMBER_OF_BUILDING_BLOCKS; i++) {
|
||||||
int len = gen() % 16;
|
int len = gen() % 16;
|
||||||
if (len > 14) {
|
if (len > 14) {
|
||||||
@ -80,7 +83,7 @@ static void InitializeBuildingBlocks(
|
|||||||
}
|
}
|
||||||
case 2: {
|
case 2: {
|
||||||
class Resource: public v8::String::ExternalStringResource,
|
class Resource: public v8::String::ExternalStringResource,
|
||||||
public Malloced {
|
public ZoneObject {
|
||||||
public:
|
public:
|
||||||
explicit Resource(Vector<const uc16> string): data_(string.start()) {
|
explicit Resource(Vector<const uc16> string): data_(string.start()) {
|
||||||
length_ = string.length();
|
length_ = string.length();
|
||||||
@ -92,7 +95,7 @@ static void InitializeBuildingBlocks(
|
|||||||
const uc16* data_;
|
const uc16* data_;
|
||||||
size_t length_;
|
size_t length_;
|
||||||
};
|
};
|
||||||
uc16* buf = NewArray<uc16>(len);
|
uc16* buf = Zone::NewArray<uc16>(len);
|
||||||
for (int j = 0; j < len; j++) {
|
for (int j = 0; j < len; j++) {
|
||||||
buf[j] = gen() % 65536;
|
buf[j] = gen() % 65536;
|
||||||
}
|
}
|
||||||
@ -212,6 +215,7 @@ TEST(Traverse) {
|
|||||||
InitializeVM();
|
InitializeVM();
|
||||||
v8::HandleScope scope;
|
v8::HandleScope scope;
|
||||||
Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS];
|
Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS];
|
||||||
|
ZoneScope zone(DELETE_ON_EXIT);
|
||||||
InitializeBuildingBlocks(building_blocks);
|
InitializeBuildingBlocks(building_blocks);
|
||||||
Handle<String> flat = ConstructBalanced(building_blocks);
|
Handle<String> flat = ConstructBalanced(building_blocks);
|
||||||
FlattenString(flat);
|
FlattenString(flat);
|
||||||
@ -303,6 +307,7 @@ TEST(Slice) {
|
|||||||
InitializeVM();
|
InitializeVM();
|
||||||
v8::HandleScope scope;
|
v8::HandleScope scope;
|
||||||
Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS];
|
Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS];
|
||||||
|
ZoneScope zone(DELETE_ON_EXIT);
|
||||||
InitializeBuildingBlocks(building_blocks);
|
InitializeBuildingBlocks(building_blocks);
|
||||||
|
|
||||||
seed = 42;
|
seed = 42;
|
||||||
|
@ -41,6 +41,11 @@ class MessageTestCase(test.TestCase):
|
|||||||
self.config = config
|
self.config = config
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
|
|
||||||
|
def IgnoreLine(self, str):
|
||||||
|
"""Ignore empty lines and valgrind output."""
|
||||||
|
if not str: return True
|
||||||
|
else: return str.startswith('==') or str.startswith('**')
|
||||||
|
|
||||||
def IsFailureOutput(self, output):
|
def IsFailureOutput(self, output):
|
||||||
f = file(self.expected)
|
f = file(self.expected)
|
||||||
# Skip initial '#' comment and spaces
|
# Skip initial '#' comment and spaces
|
||||||
@ -58,7 +63,8 @@ class MessageTestCase(test.TestCase):
|
|||||||
pattern = '^%s$' % pattern
|
pattern = '^%s$' % pattern
|
||||||
patterns.append(pattern)
|
patterns.append(pattern)
|
||||||
# Compare actual output with the expected
|
# Compare actual output with the expected
|
||||||
outlines = [ s for s in output.stdout.split('\n') if s ]
|
raw_lines = output.stdout.split('\n')
|
||||||
|
outlines = [ s for s in raw_lines if not self.IgnoreLine(s) ]
|
||||||
if len(outlines) != len(patterns):
|
if len(outlines) != len(patterns):
|
||||||
return True
|
return True
|
||||||
for i in xrange(len(patterns)):
|
for i in xrange(len(patterns)):
|
||||||
|
Loading…
Reference in New Issue
Block a user