+++ /dev/null
-// Copyright 2010 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.
-
-#ifndef V8_ALLOCATION_INL_H_
-#define V8_ALLOCATION_INL_H_
-
-#include "allocation.h"
-
-namespace v8 {
-namespace internal {
-
-
-void* PreallocatedStorageAllocationPolicy::New(size_t size) {
- return Isolate::Current()->PreallocatedStorageNew(size);
-}
-
-
-void PreallocatedStorageAllocationPolicy::Delete(void* p) {
- return Isolate::Current()->PreallocatedStorageDelete(p);
-}
-
-
-} } // namespace v8::internal
-
-#endif // V8_ALLOCATION_INL_H_
return result;
}
-
-void PreallocatedStorage::LinkTo(PreallocatedStorage* other) {
- next_ = other->next_;
- other->next_->previous_ = this;
- previous_ = other;
- other->next_ = this;
-}
-
-
-void PreallocatedStorage::Unlink() {
- next_->previous_ = previous_;
- previous_->next_ = next_;
-}
-
-
-PreallocatedStorage::PreallocatedStorage(size_t size)
- : size_(size) {
- previous_ = next_ = this;
-}
-
} } // namespace v8::internal
};
-// Allocation policy for allocating in preallocated space.
-// Used as an allocation policy for ScopeInfo when generating
-// stack traces.
-class PreallocatedStorage {
- public:
- explicit PreallocatedStorage(size_t size);
- size_t size() { return size_; }
-
- private:
- size_t size_;
- PreallocatedStorage* previous_;
- PreallocatedStorage* next_;
-
- void LinkTo(PreallocatedStorage* other);
- void Unlink();
-
- friend class Isolate;
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(PreallocatedStorage);
-};
-
-
-struct PreallocatedStorageAllocationPolicy {
- INLINE(void* New(size_t size));
- INLINE(static void Delete(void* ptr));
-};
-
-
} } // namespace v8::internal
#endif // V8_ALLOCATION_H_
"abort program (dump core) when an uncaught exception is thrown")
DEFINE_bool(trace_exception, false,
"print stack trace when throwing exceptions")
-DEFINE_bool(preallocate_message_memory, false,
- "preallocate some memory to build stack traces.")
DEFINE_bool(randomize_hashes, true,
"randomize hashes to avoid predictable hash collisions "
"(with snapshots this option cannot override the baked-in seed)")
#include "string-stream.h"
#include "vm-state-inl.h"
-#include "allocation-inl.h"
-
namespace v8 {
namespace internal {
#include "v8.h"
-#include "allocation-inl.h"
#include "ast.h"
#include "bootstrapper.h"
#include "codegen.h"
}
-// Create a dummy thread that will wait forever on a semaphore. The only
-// purpose for this thread is to have some stack area to save essential data
-// into for use by a stacks only core dump (aka minidump).
-class PreallocatedMemoryThread: public Thread {
- public:
- char* data() {
- if (data_ready_semaphore_ != NULL) {
- // Initial access is guarded until the data has been published.
- data_ready_semaphore_->Wait();
- delete data_ready_semaphore_;
- data_ready_semaphore_ = NULL;
- }
- return data_;
- }
-
- unsigned length() {
- if (data_ready_semaphore_ != NULL) {
- // Initial access is guarded until the data has been published.
- data_ready_semaphore_->Wait();
- delete data_ready_semaphore_;
- data_ready_semaphore_ = NULL;
- }
- return length_;
- }
-
- // Stop the PreallocatedMemoryThread and release its resources.
- void StopThread() {
- keep_running_ = false;
- wait_for_ever_semaphore_->Signal();
-
- // Wait for the thread to terminate.
- Join();
-
- if (data_ready_semaphore_ != NULL) {
- delete data_ready_semaphore_;
- data_ready_semaphore_ = NULL;
- }
-
- delete wait_for_ever_semaphore_;
- wait_for_ever_semaphore_ = NULL;
- }
-
- protected:
- // When the thread starts running it will allocate a fixed number of bytes
- // on the stack and publish the location of this memory for others to use.
- void Run() {
- EmbeddedVector<char, 15 * 1024> local_buffer;
-
- // Initialize the buffer with a known good value.
- OS::StrNCpy(local_buffer, "Trace data was not generated.\n",
- local_buffer.length());
-
- // Publish the local buffer and signal its availability.
- data_ = local_buffer.start();
- length_ = local_buffer.length();
- data_ready_semaphore_->Signal();
-
- while (keep_running_) {
- // This thread will wait here until the end of time.
- wait_for_ever_semaphore_->Wait();
- }
-
- // Make sure we access the buffer after the wait to remove all possibility
- // of it being optimized away.
- OS::StrNCpy(local_buffer, "PreallocatedMemoryThread shutting down.\n",
- local_buffer.length());
- }
-
-
- private:
- PreallocatedMemoryThread()
- : Thread("v8:PreallocMem"),
- keep_running_(true),
- wait_for_ever_semaphore_(new Semaphore(0)),
- data_ready_semaphore_(new Semaphore(0)),
- data_(NULL),
- length_(0) {
- }
-
- // Used to make sure that the thread keeps looping even for spurious wakeups.
- bool keep_running_;
-
- // This semaphore is used by the PreallocatedMemoryThread to wait for ever.
- Semaphore* wait_for_ever_semaphore_;
- // Semaphore to signal that the data has been initialized.
- Semaphore* data_ready_semaphore_;
-
- // Location and size of the preallocated memory block.
- char* data_;
- unsigned length_;
-
- friend class Isolate;
-
- DISALLOW_COPY_AND_ASSIGN(PreallocatedMemoryThread);
-};
-
-
-void Isolate::PreallocatedMemoryThreadStart() {
- if (preallocated_memory_thread_ != NULL) return;
- preallocated_memory_thread_ = new PreallocatedMemoryThread();
- preallocated_memory_thread_->Start();
-}
-
-
-void Isolate::PreallocatedMemoryThreadStop() {
- if (preallocated_memory_thread_ == NULL) return;
- preallocated_memory_thread_->StopThread();
- // Done with the thread entirely.
- delete preallocated_memory_thread_;
- preallocated_memory_thread_ = NULL;
-}
-
-
-void Isolate::PreallocatedStorageInit(size_t size) {
- ASSERT(free_list_.next_ == &free_list_);
- ASSERT(free_list_.previous_ == &free_list_);
- PreallocatedStorage* free_chunk =
- reinterpret_cast<PreallocatedStorage*>(new char[size]);
- free_list_.next_ = free_list_.previous_ = free_chunk;
- free_chunk->next_ = free_chunk->previous_ = &free_list_;
- free_chunk->size_ = size - sizeof(PreallocatedStorage);
- preallocated_storage_preallocated_ = true;
-}
-
-
-void* Isolate::PreallocatedStorageNew(size_t size) {
- if (!preallocated_storage_preallocated_) {
- return FreeStoreAllocationPolicy().New(size);
- }
- ASSERT(free_list_.next_ != &free_list_);
- ASSERT(free_list_.previous_ != &free_list_);
-
- size = (size + kPointerSize - 1) & ~(kPointerSize - 1);
- // Search for exact fit.
- for (PreallocatedStorage* storage = free_list_.next_;
- storage != &free_list_;
- storage = storage->next_) {
- if (storage->size_ == size) {
- storage->Unlink();
- storage->LinkTo(&in_use_list_);
- return reinterpret_cast<void*>(storage + 1);
- }
- }
- // Search for first fit.
- for (PreallocatedStorage* storage = free_list_.next_;
- storage != &free_list_;
- storage = storage->next_) {
- if (storage->size_ >= size + sizeof(PreallocatedStorage)) {
- storage->Unlink();
- storage->LinkTo(&in_use_list_);
- PreallocatedStorage* left_over =
- reinterpret_cast<PreallocatedStorage*>(
- reinterpret_cast<char*>(storage + 1) + size);
- left_over->size_ = storage->size_ - size - sizeof(PreallocatedStorage);
- ASSERT(size + left_over->size_ + sizeof(PreallocatedStorage) ==
- storage->size_);
- storage->size_ = size;
- left_over->LinkTo(&free_list_);
- return reinterpret_cast<void*>(storage + 1);
- }
- }
- // Allocation failure.
- ASSERT(false);
- return NULL;
-}
-
-
-// We don't attempt to coalesce.
-void Isolate::PreallocatedStorageDelete(void* p) {
- if (p == NULL) {
- return;
- }
- if (!preallocated_storage_preallocated_) {
- FreeStoreAllocationPolicy::Delete(p);
- return;
- }
- PreallocatedStorage* storage = reinterpret_cast<PreallocatedStorage*>(p) - 1;
- ASSERT(storage->next_->previous_ == storage);
- ASSERT(storage->previous_->next_ == storage);
- storage->Unlink();
- storage->LinkTo(&free_list_);
-}
-
Isolate* Isolate::default_isolate_ = NULL;
Thread::LocalStorageKey Isolate::isolate_key_;
Thread::LocalStorageKey Isolate::thread_id_key_;
void Isolate::PrintStack(FILE* out) {
if (stack_trace_nesting_level_ == 0) {
stack_trace_nesting_level_++;
-
- StringAllocator* allocator;
- if (preallocated_message_space_ == NULL) {
- allocator = new HeapStringAllocator();
- } else {
- allocator = preallocated_message_space_;
- }
-
StringStream::ClearMentionedObjectCache(this);
- StringStream accumulator(allocator);
+ HeapStringAllocator allocator;
+ StringStream accumulator(&allocator);
incomplete_message_ = &accumulator;
PrintStack(&accumulator);
accumulator.OutputToFile(out);
accumulator.Log(this);
incomplete_message_ = NULL;
stack_trace_nesting_level_ = 0;
- if (preallocated_message_space_ == NULL) {
- // Remove the HeapStringAllocator created above.
- delete allocator;
- }
} else if (stack_trace_nesting_level_ == 1) {
stack_trace_nesting_level_++;
OS::PrintError(
entry_stack_(NULL),
stack_trace_nesting_level_(0),
incomplete_message_(NULL),
- preallocated_memory_thread_(NULL),
- preallocated_message_space_(NULL),
bootstrapper_(NULL),
runtime_profiler_(NULL),
compilation_cache_(NULL),
handle_scope_implementer_(NULL),
unicode_cache_(NULL),
runtime_zone_(this),
- in_use_list_(0),
- free_list_(0),
- preallocated_storage_preallocated_(false),
inner_pointer_to_code_cache_(NULL),
write_iterator_(NULL),
global_handles_(NULL),
builtins_.TearDown();
bootstrapper_->TearDown();
- // Remove the external reference to the preallocated stack memory.
- delete preallocated_message_space_;
- preallocated_message_space_ = NULL;
- PreallocatedMemoryThreadStop();
-
if (runtime_profiler_ != NULL) {
runtime_profiler_->TearDown();
delete runtime_profiler_;
}
}
- // Only preallocate on the first initialization.
- if (FLAG_preallocate_message_memory && preallocated_message_space_ == NULL) {
- // Start the thread which will set aside some memory.
- PreallocatedMemoryThreadStart();
- preallocated_message_space_ =
- new NoAllocationStringAllocator(
- preallocated_memory_thread_->data(),
- preallocated_memory_thread_->length());
- PreallocatedStorageInit(preallocated_memory_thread_->length() / 4);
- }
-
if (FLAG_preemption) {
v8::Locker locker(reinterpret_cast<v8::Isolate*>(this));
v8::Locker::StartPreemption(reinterpret_cast<v8::Isolate*>(this), 100);
class InlineRuntimeFunctionsTable;
class NoAllocationStringAllocator;
class InnerPointerToCodeCache;
-class PreallocatedMemoryThread;
class RandomNumberGenerator;
class RegExpStack;
class SaveContext;
V(uint32_t, private_random_seed, 2) \
ISOLATE_INIT_DEBUG_ARRAY_LIST(V)
-typedef List<HeapObject*, PreallocatedStorageAllocationPolicy> DebugObjectCache;
+typedef List<HeapObject*> DebugObjectCache;
#define ISOLATE_INIT_LIST(V) \
/* SerializerDeserializer state. */ \
return &interp_canonicalize_mapping_;
}
- void* PreallocatedStorageNew(size_t size);
- void PreallocatedStorageDelete(void* p);
- void PreallocatedStorageInit(size_t size);
-
inline bool IsCodePreAgingActive();
#ifdef ENABLE_DEBUGGER_SUPPORT
// at the same time, this should be prevented using external locking.
void Exit();
- void PreallocatedMemoryThreadStart();
- void PreallocatedMemoryThreadStop();
void InitializeThreadLocal();
void PrintStackTrace(FILE* out, ThreadLocalTop* thread);
EntryStackItem* entry_stack_;
int stack_trace_nesting_level_;
StringStream* incomplete_message_;
- // The preallocated memory thread singleton.
- PreallocatedMemoryThread* preallocated_memory_thread_;
Address isolate_addresses_[kIsolateAddressCount + 1]; // NOLINT
- NoAllocationStringAllocator* preallocated_message_space_;
Bootstrapper* bootstrapper_;
RuntimeProfiler* runtime_profiler_;
CompilationCache* compilation_cache_;
HandleScopeImplementer* handle_scope_implementer_;
UnicodeCache* unicode_cache_;
Zone runtime_zone_;
- PreallocatedStorage in_use_list_;
- PreallocatedStorage free_list_;
- bool preallocated_storage_preallocated_;
InnerPointerToCodeCache* inner_pointer_to_code_cache_;
ConsStringIteratorOp* write_iterator_;
GlobalHandles* global_handles_;
#include "scopeinfo.h"
#include "scopes.h"
-#include "allocation-inl.h"
-
namespace v8 {
namespace internal {
#include "messages.h"
#include "scopeinfo.h"
-#include "allocation-inl.h"
-
namespace v8 {
namespace internal {
#include "factory.h"
#include "string-stream.h"
-#include "allocation-inl.h"
-
namespace v8 {
namespace internal {
void StringStream::ClearMentionedObjectCache(Isolate* isolate) {
isolate->set_string_stream_current_security_token(NULL);
if (isolate->string_stream_debug_object_cache() == NULL) {
- isolate->set_string_stream_debug_object_cache(
- new List<HeapObject*, PreallocatedStorageAllocationPolicy>(0));
+ isolate->set_string_stream_debug_object_cache(new DebugObjectCache(0));
}
isolate->string_stream_debug_object_cache()->Clear();
}
+++ /dev/null
-// Copyright 2008 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.
-
-// The flags below are to test the trace-calls functionality and the
-// preallocated meessage memory.
-// Flags: --trace-calls --preallocate-message-memory
-
-/**
- * @fileoverview Check that various regexp constructs work as intended.
- * Particularly those regexps that use ^ and $.
- */
-
-assertTrue(/^bar/.test("bar"));
-assertTrue(/^bar/.test("bar\nfoo"));
-assertFalse(/^bar/.test("foo\nbar"));
-assertTrue(/^bar/m.test("bar"));
-assertTrue(/^bar/m.test("bar\nfoo"));
-assertTrue(/^bar/m.test("foo\nbar"));
-
-assertTrue(/bar$/.test("bar"));
-assertFalse(/bar$/.test("bar\nfoo"));
-assertTrue(/bar$/.test("foo\nbar"));
-assertTrue(/bar$/m.test("bar"));
-assertTrue(/bar$/m.test("bar\nfoo"));
-assertTrue(/bar$/m.test("foo\nbar"));
-
-assertFalse(/^bxr/.test("bar"));
-assertFalse(/^bxr/.test("bar\nfoo"));
-assertFalse(/^bxr/m.test("bar"));
-assertFalse(/^bxr/m.test("bar\nfoo"));
-assertFalse(/^bxr/m.test("foo\nbar"));
-
-assertFalse(/bxr$/.test("bar"));
-assertFalse(/bxr$/.test("foo\nbar"));
-assertFalse(/bxr$/m.test("bar"));
-assertFalse(/bxr$/m.test("bar\nfoo"));
-assertFalse(/bxr$/m.test("foo\nbar"));
-
-
-assertTrue(/^.*$/.test(""));
-assertTrue(/^.*$/.test("foo"));
-assertFalse(/^.*$/.test("\n"));
-assertTrue(/^.*$/m.test("\n"));
-
-assertTrue(/^[\s]*$/.test(" "));
-assertTrue(/^[\s]*$/.test("\n"));
-
-assertTrue(/^[^]*$/.test(""));
-assertTrue(/^[^]*$/.test("foo"));
-assertTrue(/^[^]*$/.test("\n"));
-
-assertTrue(/^([()\s]|.)*$/.test("()\n()"));
-assertTrue(/^([()\n]|.)*$/.test("()\n()"));
-assertFalse(/^([()]|.)*$/.test("()\n()"));
-assertTrue(/^([()]|.)*$/m.test("()\n()"));
-assertTrue(/^([()]|.)*$/m.test("()\n"));
-assertTrue(/^[()]*$/m.test("()\n."));
-
-assertTrue(/^[\].]*$/.test("...]..."));
-
-
-function check_case(lc, uc) {
- var a = new RegExp("^" + lc + "$");
- assertFalse(a.test(uc));
- a = new RegExp("^" + lc + "$", "i");
- assertTrue(a.test(uc));
-
- var A = new RegExp("^" + uc + "$");
- assertFalse(A.test(lc));
- A = new RegExp("^" + uc + "$", "i");
- assertTrue(A.test(lc));
-
- a = new RegExp("^[" + lc + "]$");
- assertFalse(a.test(uc));
- a = new RegExp("^[" + lc + "]$", "i");
- assertTrue(a.test(uc));
-
- A = new RegExp("^[" + uc + "]$");
- assertFalse(A.test(lc));
- A = new RegExp("^[" + uc + "]$", "i");
- assertTrue(A.test(lc));
-}
-
-
-check_case("a", "A");
-// Aring
-check_case(String.fromCharCode(229), String.fromCharCode(197));
-// Russian G
-check_case(String.fromCharCode(0x413), String.fromCharCode(0x433));
-
-
-assertThrows("a = new RegExp('[z-a]');");