Upgrade to 3.29
Update V8 to 3.29.88.17 and update makefiles to support building on
all the relevant platforms.
Bug: 17370214
Change-Id: Ia3407c157fd8d72a93e23d8318ccaf6ecf77fa4e
diff --git a/src/v8threads.cc b/src/v8threads.cc
index fd8d536..a46b289 100644
--- a/src/v8threads.cc
+++ b/src/v8threads.cc
@@ -1,38 +1,15 @@
-// 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.
+// Copyright 2012 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
-#include "v8.h"
+#include "src/v8.h"
-#include "api.h"
-#include "bootstrapper.h"
-#include "debug.h"
-#include "execution.h"
-#include "v8threads.h"
-#include "regexp-stack.h"
+#include "src/api.h"
+#include "src/bootstrapper.h"
+#include "src/debug.h"
+#include "src/execution.h"
+#include "src/regexp-stack.h"
+#include "src/v8threads.h"
namespace v8 {
@@ -42,15 +19,13 @@
bool Locker::active_ = false;
-// Constructor for the Locker object. Once the Locker is constructed the
-// current thread will be guaranteed to have the lock for a given isolate.
-Locker::Locker(v8::Isolate* isolate)
- : has_lock_(false),
- top_level_(true),
- isolate_(reinterpret_cast<i::Isolate*>(isolate)) {
- if (isolate_ == NULL) {
- isolate_ = i::Isolate::GetDefaultIsolateForLocking();
- }
+// Once the Locker is initialized, the current thread will be guaranteed to have
+// the lock for a given isolate.
+void Locker::Initialize(v8::Isolate* isolate) {
+ DCHECK(isolate != NULL);
+ has_lock_= false;
+ top_level_ = true;
+ isolate_ = reinterpret_cast<i::Isolate*>(isolate);
// Record that the Locker has been used at least once.
active_ = true;
// Get the big lock if necessary.
@@ -76,20 +51,14 @@
isolate_->stack_guard()->ClearThread(access);
isolate_->stack_guard()->InitThread(access);
}
- if (isolate_->IsDefaultIsolate()) {
- // This only enters if not yet entered.
- internal::Isolate::EnterDefaultIsolate();
- }
}
- ASSERT(isolate_->thread_manager()->IsLockedByCurrentThread());
+ DCHECK(isolate_->thread_manager()->IsLockedByCurrentThread());
}
bool Locker::IsLocked(v8::Isolate* isolate) {
+ DCHECK(isolate != NULL);
i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
- if (internal_isolate == NULL) {
- internal_isolate = i::Isolate::GetDefaultIsolateForLocking();
- }
return internal_isolate->thread_manager()->IsLockedByCurrentThread();
}
@@ -100,11 +69,8 @@
Locker::~Locker() {
- ASSERT(isolate_->thread_manager()->IsLockedByCurrentThread());
+ DCHECK(isolate_->thread_manager()->IsLockedByCurrentThread());
if (has_lock_) {
- if (isolate_->IsDefaultIsolate()) {
- isolate_->Exit();
- }
if (top_level_) {
isolate_->thread_manager()->FreeThreadResources();
} else {
@@ -115,37 +81,19 @@
}
-Unlocker::Unlocker(v8::Isolate* isolate)
- : isolate_(reinterpret_cast<i::Isolate*>(isolate)) {
- if (isolate_ == NULL) {
- isolate_ = i::Isolate::GetDefaultIsolateForLocking();
- }
- ASSERT(isolate_->thread_manager()->IsLockedByCurrentThread());
- if (isolate_->IsDefaultIsolate()) {
- isolate_->Exit();
- }
+void Unlocker::Initialize(v8::Isolate* isolate) {
+ DCHECK(isolate != NULL);
+ isolate_ = reinterpret_cast<i::Isolate*>(isolate);
+ DCHECK(isolate_->thread_manager()->IsLockedByCurrentThread());
isolate_->thread_manager()->ArchiveThread();
isolate_->thread_manager()->Unlock();
}
Unlocker::~Unlocker() {
- ASSERT(!isolate_->thread_manager()->IsLockedByCurrentThread());
+ DCHECK(!isolate_->thread_manager()->IsLockedByCurrentThread());
isolate_->thread_manager()->Lock();
isolate_->thread_manager()->RestoreThread();
- if (isolate_->IsDefaultIsolate()) {
- isolate_->Enter();
- }
-}
-
-
-void Locker::StartPreemption(int every_n_ms) {
- v8::internal::ContextSwitcher::StartPreemption(every_n_ms);
-}
-
-
-void Locker::StopPreemption() {
- v8::internal::ContextSwitcher::StopPreemption();
}
@@ -153,7 +101,7 @@
bool ThreadManager::RestoreThread() {
- ASSERT(IsLockedByCurrentThread());
+ DCHECK(IsLockedByCurrentThread());
// First check whether the current thread has been 'lazily archived', i.e.
// not archived at all. If that is the case we put the state storage we
// had prepared back in the free list, since we didn't need it after all.
@@ -161,8 +109,8 @@
lazily_archived_thread_ = ThreadId::Invalid();
Isolate::PerIsolateThreadData* per_thread =
isolate_->FindPerThreadDataForThisThread();
- ASSERT(per_thread != NULL);
- ASSERT(per_thread->thread_state() == lazily_archived_thread_state_);
+ DCHECK(per_thread != NULL);
+ DCHECK(per_thread->thread_state() == lazily_archived_thread_state_);
lazily_archived_thread_state_->set_id(ThreadId::Invalid());
lazily_archived_thread_state_->LinkInto(ThreadState::FREE_LIST);
lazily_archived_thread_state_ = NULL;
@@ -191,15 +139,13 @@
from = isolate_->handle_scope_implementer()->RestoreThread(from);
from = isolate_->RestoreThread(from);
from = Relocatable::RestoreState(isolate_, from);
-#ifdef ENABLE_DEBUGGER_SUPPORT
from = isolate_->debug()->RestoreDebug(from);
-#endif
from = isolate_->stack_guard()->RestoreStackGuard(from);
from = isolate_->regexp_stack()->RestoreStack(from);
from = isolate_->bootstrapper()->RestoreState(from);
per_thread->set_thread_state(NULL);
if (state->terminate_on_restore()) {
- isolate_->stack_guard()->TerminateExecution();
+ isolate_->stack_guard()->RequestTerminateExecution();
state->set_terminate_on_restore(false);
}
state->set_id(ThreadId::Invalid());
@@ -210,24 +156,22 @@
void ThreadManager::Lock() {
- mutex_->Lock();
+ mutex_.Lock();
mutex_owner_ = ThreadId::Current();
- ASSERT(IsLockedByCurrentThread());
+ DCHECK(IsLockedByCurrentThread());
}
void ThreadManager::Unlock() {
mutex_owner_ = ThreadId::Invalid();
- mutex_->Unlock();
+ mutex_.Unlock();
}
static int ArchiveSpacePerThread() {
return HandleScopeImplementer::ArchiveSpacePerThread() +
Isolate::ArchiveSpacePerThread() +
-#ifdef ENABLE_DEBUGGER_SUPPORT
Debug::ArchiveSpacePerThread() +
-#endif
StackGuard::ArchiveSpacePerThread() +
RegExpStack::ArchiveSpacePerThread() +
Bootstrapper::ArchiveSpacePerThread() +
@@ -238,12 +182,18 @@
ThreadState::ThreadState(ThreadManager* thread_manager)
: id_(ThreadId::Invalid()),
terminate_on_restore_(false),
+ data_(NULL),
next_(this),
previous_(this),
thread_manager_(thread_manager) {
}
+ThreadState::~ThreadState() {
+ DeleteArray<char>(data_);
+}
+
+
void ThreadState::AllocateSpace() {
data_ = NewArray<char>(ArchiveSpacePerThread());
}
@@ -293,8 +243,7 @@
// be distinguished from not having a thread id at all (since NULL is
// defined as 0.)
ThreadManager::ThreadManager()
- : mutex_(OS::CreateMutex()),
- mutex_owner_(ThreadId::Invalid()),
+ : mutex_owner_(ThreadId::Invalid()),
lazily_archived_thread_(ThreadId::Invalid()),
lazily_archived_thread_state_(NULL),
free_anchor_(NULL),
@@ -305,16 +254,26 @@
ThreadManager::~ThreadManager() {
- delete mutex_;
- delete free_anchor_;
- delete in_use_anchor_;
+ DeleteThreadStateList(free_anchor_);
+ DeleteThreadStateList(in_use_anchor_);
+}
+
+
+void ThreadManager::DeleteThreadStateList(ThreadState* anchor) {
+ // The list starts and ends with the anchor.
+ for (ThreadState* current = anchor->next_; current != anchor;) {
+ ThreadState* next = current->next_;
+ delete current;
+ current = next;
+ }
+ delete anchor;
}
void ThreadManager::ArchiveThread() {
- ASSERT(lazily_archived_thread_.Equals(ThreadId::Invalid()));
- ASSERT(!IsArchived());
- ASSERT(IsLockedByCurrentThread());
+ DCHECK(lazily_archived_thread_.Equals(ThreadId::Invalid()));
+ DCHECK(!IsArchived());
+ DCHECK(IsLockedByCurrentThread());
ThreadState* state = GetFreeThreadState();
state->Unlink();
Isolate::PerIsolateThreadData* per_thread =
@@ -322,14 +281,14 @@
per_thread->set_thread_state(state);
lazily_archived_thread_ = ThreadId::Current();
lazily_archived_thread_state_ = state;
- ASSERT(state->id().Equals(ThreadId::Invalid()));
+ DCHECK(state->id().Equals(ThreadId::Invalid()));
state->set_id(CurrentId());
- ASSERT(!state->id().Equals(ThreadId::Invalid()));
+ DCHECK(!state->id().Equals(ThreadId::Invalid()));
}
void ThreadManager::EagerlyArchiveThread() {
- ASSERT(IsLockedByCurrentThread());
+ DCHECK(IsLockedByCurrentThread());
ThreadState* state = lazily_archived_thread_state_;
state->LinkInto(ThreadState::IN_USE_LIST);
char* to = state->data();
@@ -338,9 +297,7 @@
to = isolate_->handle_scope_implementer()->ArchiveThread(to);
to = isolate_->ArchiveThread(to);
to = Relocatable::ArchiveState(isolate_, to);
-#ifdef ENABLE_DEBUGGER_SUPPORT
to = isolate_->debug()->ArchiveDebug(to);
-#endif
to = isolate_->stack_guard()->ArchiveStackGuard(to);
to = isolate_->regexp_stack()->ArchiveStack(to);
to = isolate_->bootstrapper()->ArchiveState(to);
@@ -350,11 +307,12 @@
void ThreadManager::FreeThreadResources() {
+ DCHECK(!isolate_->has_pending_exception());
+ DCHECK(!isolate_->external_caught_exception());
+ DCHECK(isolate_->try_catch_handler() == NULL);
isolate_->handle_scope_implementer()->FreeThreadResources();
isolate_->FreeThreadResources();
-#ifdef ENABLE_DEBUGGER_SUPPORT
isolate_->debug()->FreeThreadResources();
-#endif
isolate_->stack_guard()->FreeThreadResources();
isolate_->regexp_stack()->FreeThreadResources();
isolate_->bootstrapper()->FreeThreadResources();
@@ -367,6 +325,7 @@
return data != NULL && data->thread_state() != NULL;
}
+
void ThreadManager::Iterate(ObjectVisitor* v) {
// Expecting no threads during serialization/deserialization
for (ThreadState* state = FirstThreadStateInUse();
@@ -407,66 +366,5 @@
}
-ContextSwitcher::ContextSwitcher(Isolate* isolate, int every_n_ms)
- : Thread("v8:CtxtSwitcher"),
- keep_going_(true),
- sleep_ms_(every_n_ms),
- isolate_(isolate) {
-}
-
-
-// Set the scheduling interval of V8 threads. This function starts the
-// ContextSwitcher thread if needed.
-void ContextSwitcher::StartPreemption(int every_n_ms) {
- Isolate* isolate = Isolate::Current();
- ASSERT(Locker::IsLocked(reinterpret_cast<v8::Isolate*>(isolate)));
- if (isolate->context_switcher() == NULL) {
- // If the ContextSwitcher thread is not running at the moment start it now.
- isolate->set_context_switcher(new ContextSwitcher(isolate, every_n_ms));
- isolate->context_switcher()->Start();
- } else {
- // ContextSwitcher thread is already running, so we just change the
- // scheduling interval.
- isolate->context_switcher()->sleep_ms_ = every_n_ms;
- }
-}
-
-
-// Disable preemption of V8 threads. If multiple threads want to use V8 they
-// must cooperatively schedule amongst them from this point on.
-void ContextSwitcher::StopPreemption() {
- Isolate* isolate = Isolate::Current();
- ASSERT(Locker::IsLocked(reinterpret_cast<v8::Isolate*>(isolate)));
- if (isolate->context_switcher() != NULL) {
- // The ContextSwitcher thread is running. We need to stop it and release
- // its resources.
- isolate->context_switcher()->keep_going_ = false;
- // Wait for the ContextSwitcher thread to exit.
- isolate->context_switcher()->Join();
- // Thread has exited, now we can delete it.
- delete(isolate->context_switcher());
- isolate->set_context_switcher(NULL);
- }
-}
-
-
-// Main loop of the ContextSwitcher thread: Preempt the currently running V8
-// thread at regular intervals.
-void ContextSwitcher::Run() {
- while (keep_going_) {
- OS::Sleep(sleep_ms_);
- isolate()->stack_guard()->Preempt();
- }
-}
-
-
-// Acknowledge the preemption by the receiving thread.
-void ContextSwitcher::PreemptionReceived() {
- ASSERT(Locker::IsLocked());
- // There is currently no accounting being done for this. But could be in the
- // future, which is why we leave this in.
-}
-
-
} // namespace internal
} // namespace v8