Revision: 11276
Author: [email protected]
Date: Wed Apr 11 06:59:42 2012
Log: Merged r11194, r11198, r11201, r11214, r11225, r11233, r11240
into 3.9 branch.
Ensure that arguments object is materialized when deoptimizing from inlined
function.
Fix performance regressions due to lazy initialization.
Fix broken build on Windows due to r11198.
Properly support shrinking arrays in CopyDictionaryToObjectElements.
Ensure default isolate is present in Add/RemoveCallCompletedCallback.
Ensure default isolate is present in Context::New().
MIPS: Ensure proper alignment of LazyInstance objects.
BUG=v8:2045,chromium:121407,chromium:118686
[email protected]
Review URL: https://chromiumcodereview.appspot.com/10020040
http://code.google.com/p/v8/source/detail?r=11276
Added:
/branches/3.9/src/platform-posix.h
/branches/3.9/test/mjsunit/regress/regress-121407.js
/branches/3.9/test/mjsunit/regress/regress-2045.js
Modified:
/branches/3.9/src/api.cc
/branches/3.9/src/arm/lithium-arm.cc
/branches/3.9/src/elements.cc
/branches/3.9/src/hydrogen-instructions.h
/branches/3.9/src/hydrogen.cc
/branches/3.9/src/ia32/lithium-ia32.cc
/branches/3.9/src/isolate.cc
/branches/3.9/src/isolate.h
/branches/3.9/src/lazy-instance.h
/branches/3.9/src/mips/lithium-mips.cc
/branches/3.9/src/platform-cygwin.cc
/branches/3.9/src/platform-freebsd.cc
/branches/3.9/src/platform-linux.cc
/branches/3.9/src/platform-macos.cc
/branches/3.9/src/platform-nullos.cc
/branches/3.9/src/platform-openbsd.cc
/branches/3.9/src/platform-posix.cc
/branches/3.9/src/platform-solaris.cc
/branches/3.9/src/platform-win32.cc
/branches/3.9/src/platform.h
/branches/3.9/src/v8.cc
/branches/3.9/src/version.cc
/branches/3.9/src/x64/lithium-x64.cc
/branches/3.9/tools/check-static-initializers.sh
/branches/3.9/tools/gyp/v8.gyp
=======================================
--- /dev/null
+++ /branches/3.9/src/platform-posix.h Wed Apr 11 06:59:42 2012
@@ -0,0 +1,40 @@
+// Copyright 2012 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_PLATFORM_POSIX_H_
+#define V8_PLATFORM_POSIX_H_
+
+namespace v8 {
+namespace internal {
+
+// Used by platform implementation files during OS::PostSetUp() to
initialize
+// the math functions.
+void MathSetup();
+
+} } // namespace v8::internal
+
+#endif // V8_PLATFORM_POSIX_H_
=======================================
--- /dev/null
+++ /branches/3.9/test/mjsunit/regress/regress-121407.js Wed Apr 11
06:59:42 2012
@@ -0,0 +1,40 @@
+// Copyright 2012 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.
+
+var a = [0,1,2,3];
+a[2000000] = 2000000;
+a.length=2000;
+for (var i = 0; i <= 256; i++) {
+ a[i] = new Object();
+}
+
+a = [0.5,1.5,2.5,3.5,4.5,5.5];
+a[2000000] = 2000000;
+a.length=2000;
+for (var i = 0; i <= 256; i++) {
+ a[i] = new Object();
+}
=======================================
--- /dev/null
+++ /branches/3.9/test/mjsunit/regress/regress-2045.js Wed Apr 11 06:59:42
2012
@@ -0,0 +1,49 @@
+// Copyright 2012 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: --allow-natives-syntax
+
+function foo() {
+ assertEquals(2, arguments.length);
+}
+
+function bar() {
+ G.x;
+ return foo.apply(this, arguments);
+}
+
+function baz() {
+ return bar(1, 2);
+}
+
+G = {x: 0};
+baz();
+baz();
+%OptimizeFunctionOnNextCall(baz);
+baz();
+delete G.x;
+baz();
=======================================
--- /branches/3.9/src/api.cc Wed Mar 28 00:54:11 2012
+++ /branches/3.9/src/api.cc Wed Apr 11 06:59:42 2012
@@ -4170,7 +4170,7 @@
bool v8::V8::Initialize() {
- i::Isolate* isolate = i::Isolate::Current();
+ i::Isolate* isolate = i::Isolate::UncheckedCurrent();
if (isolate != NULL && isolate->IsInitialized()) {
return true;
}
@@ -4277,6 +4277,7 @@
v8::ExtensionConfiguration* extensions,
v8::Handle<ObjectTemplate> global_template,
v8::Handle<Value> global_object) {
+ i::Isolate::EnsureDefaultIsolate();
i::Isolate* isolate = i::Isolate::Current();
EnsureInitializedForIsolate(isolate, "v8::Context::New()");
LOG_API(isolate, "Context::New");
@@ -5063,7 +5064,7 @@
Local<Integer> v8::Integer::New(int32_t value) {
- i::Isolate* isolate = i::Isolate::Current();
+ i::Isolate* isolate = i::Isolate::UncheckedCurrent();
EnsureInitializedForIsolate(isolate, "v8::Integer::New()");
if (i::Smi::IsValid(value)) {
return
Utils::IntegerToLocal(i::Handle<i::Object>(i::Smi::FromInt(value),
@@ -5269,6 +5270,7 @@
void V8::AddCallCompletedCallback(CallCompletedCallback callback) {
if (callback == NULL) return;
+ i::Isolate::EnsureDefaultIsolate();
i::Isolate* isolate = i::Isolate::Current();
if (IsDeadCheck(isolate, "v8::V8::AddLeaveScriptCallback()")) return;
i::V8::AddCallCompletedCallback(callback);
@@ -5276,6 +5278,7 @@
void V8::RemoveCallCompletedCallback(CallCompletedCallback callback) {
+ i::Isolate::EnsureDefaultIsolate();
i::Isolate* isolate = i::Isolate::Current();
if (IsDeadCheck(isolate, "v8::V8::RemoveLeaveScriptCallback()")) return;
i::V8::RemoveCallCompletedCallback(callback);
@@ -5341,7 +5344,7 @@
Isolate* Isolate::GetCurrent() {
- i::Isolate* isolate = i::Isolate::Current();
+ i::Isolate* isolate = i::Isolate::UncheckedCurrent();
return reinterpret_cast<Isolate*>(isolate);
}
=======================================
--- /branches/3.9/src/arm/lithium-arm.cc Fri Mar 23 08:47:56 2012
+++ /branches/3.9/src/arm/lithium-arm.cc Wed Apr 11 06:59:42 2012
@@ -2271,6 +2271,9 @@
undefined,
instr->call_kind(),
instr->is_construct());
+ if (instr->arguments() != NULL) {
+ inner->Bind(instr->arguments(), graph()->GetArgumentsObject());
+ }
current_block_->UpdateEnvironment(inner);
chunk_->AddInlinedClosure(instr->closure());
return NULL;
=======================================
--- /branches/3.9/src/elements.cc Mon Mar 26 02:46:02 2012
+++ /branches/3.9/src/elements.cc Wed Apr 11 06:59:42 2012
@@ -199,10 +199,13 @@
}
#endif
}
- ASSERT((copy_size + static_cast<int>(to_start)) <= to->length());
ASSERT(to != from);
ASSERT(to_kind == FAST_ELEMENTS || to_kind == FAST_SMI_ONLY_ELEMENTS);
if (copy_size == 0) return;
+ uint32_t to_length = to->length();
+ if (to_start + copy_size > to_length) {
+ copy_size = to_length - to_start;
+ }
for (int i = 0; i < copy_size; i++) {
int entry = from->FindEntry(i + from_start);
if (entry != SeededNumberDictionary::kNotFound) {
@@ -356,8 +359,11 @@
}
}
}
- ASSERT(copy_size + static_cast<int>(to_start) <= to->length());
if (copy_size == 0) return;
+ uint32_t to_length = to->length();
+ if (to_start + copy_size > to_length) {
+ copy_size = to_length - to_start;
+ }
for (int i = 0; i < copy_size; i++) {
int entry = from->FindEntry(i + from_start);
if (entry != SeededNumberDictionary::kNotFound) {
=======================================
--- /branches/3.9/src/hydrogen-instructions.h Fri Mar 23 08:47:56 2012
+++ /branches/3.9/src/hydrogen-instructions.h Wed Apr 11 06:59:42 2012
@@ -1353,12 +1353,14 @@
int arguments_count,
FunctionLiteral* function,
CallKind call_kind,
- bool is_construct)
+ bool is_construct,
+ Variable* arguments)
: closure_(closure),
arguments_count_(arguments_count),
function_(function),
call_kind_(call_kind),
- is_construct_(is_construct) {
+ is_construct_(is_construct),
+ arguments_(arguments) {
}
virtual void PrintDataTo(StringStream* stream);
@@ -1372,6 +1374,8 @@
virtual Representation RequiredInputRepresentation(int index) {
return Representation::None();
}
+
+ Variable* arguments() { return arguments_; }
DECLARE_CONCRETE_INSTRUCTION(EnterInlined)
@@ -1381,6 +1385,7 @@
FunctionLiteral* function_;
CallKind call_kind_;
bool is_construct_;
+ Variable* arguments_;
};
=======================================
--- /branches/3.9/src/hydrogen.cc Wed Apr 11 02:35:05 2012
+++ /branches/3.9/src/hydrogen.cc Wed Apr 11 06:59:42 2012
@@ -5379,7 +5379,8 @@
arguments->length(),
function,
call_kind,
-
function_state()->is_construct()));
+
function_state()->is_construct(),
+
function->scope()->arguments()));
// If the function uses arguments object create and bind one.
if (function->scope()->arguments() != NULL) {
ASSERT(function->scope()->arguments()->IsStackAllocated());
=======================================
--- /branches/3.9/src/ia32/lithium-ia32.cc Fri Mar 23 08:47:56 2012
+++ /branches/3.9/src/ia32/lithium-ia32.cc Wed Apr 11 06:59:42 2012
@@ -2380,6 +2380,9 @@
undefined,
instr->call_kind(),
instr->is_construct());
+ if (instr->arguments() != NULL) {
+ inner->Bind(instr->arguments(), graph()->GetArgumentsObject());
+ }
current_block_->UpdateEnvironment(inner);
chunk_->AddInlinedClosure(instr->closure());
return NULL;
=======================================
--- /branches/3.9/src/isolate.cc Wed Mar 28 00:54:11 2012
+++ /branches/3.9/src/isolate.cc Wed Apr 11 06:59:42 2012
@@ -38,7 +38,6 @@
#include "heap-profiler.h"
#include "hydrogen.h"
#include "isolate.h"
-#include "lazy-instance.h"
#include "lithium-allocator.h"
#include "log.h"
#include "messages.h"
@@ -57,31 +56,6 @@
namespace v8 {
namespace internal {
-struct GlobalState {
- Thread::LocalStorageKey per_isolate_thread_data_key;
- Thread::LocalStorageKey isolate_key;
- Thread::LocalStorageKey thread_id_key;
- Isolate* default_isolate;
- Isolate::ThreadDataTable* thread_data_table;
- Mutex* mutex;
-};
-
-struct InitializeGlobalState {
- static void Construct(GlobalState* state) {
- state->isolate_key = Thread::CreateThreadLocalKey();
- state->thread_id_key = Thread::CreateThreadLocalKey();
- state->per_isolate_thread_data_key = Thread::CreateThreadLocalKey();
- state->thread_data_table = new Isolate::ThreadDataTable();
- state->default_isolate = new Isolate();
- state->mutex = OS::CreateMutex();
- // Can't use SetIsolateThreadLocals(default_isolate_, NULL) here
- // because a non-null thread data may be already set.
- Thread::SetThreadLocal(state->isolate_key, state->default_isolate);
- }
-};
-
-static LazyInstance<GlobalState, InitializeGlobalState>::type global_state;
-
Atomic32 ThreadId::highest_thread_id_ = 0;
int ThreadId::AllocateThreadId() {
@@ -91,11 +65,10 @@
int ThreadId::GetCurrentThreadId() {
- const GlobalState& global = global_state.Get();
- int thread_id = Thread::GetThreadLocalInt(global.thread_id_key);
+ int thread_id = Thread::GetThreadLocalInt(Isolate::thread_id_key_);
if (thread_id == 0) {
thread_id = AllocateThreadId();
- Thread::SetThreadLocalInt(global.thread_id_key, thread_id);
+ Thread::SetThreadLocalInt(Isolate::thread_id_key_, thread_id);
}
return thread_id;
}
@@ -338,17 +311,24 @@
storage->Unlink();
storage->LinkTo(&free_list_);
}
+
+Isolate* Isolate::default_isolate_ = NULL;
+Thread::LocalStorageKey Isolate::isolate_key_;
+Thread::LocalStorageKey Isolate::thread_id_key_;
+Thread::LocalStorageKey Isolate::per_isolate_thread_data_key_;
+Mutex* Isolate::process_wide_mutex_ = OS::CreateMutex();
+Isolate::ThreadDataTable* Isolate::thread_data_table_ = NULL;
+
Isolate::PerIsolateThreadData* Isolate::AllocatePerIsolateThreadData(
ThreadId thread_id) {
ASSERT(!thread_id.Equals(ThreadId::Invalid()));
PerIsolateThreadData* per_thread = new PerIsolateThreadData(this,
thread_id);
{
- GlobalState* const global = global_state.Pointer();
- ScopedLock lock(global->mutex);
- ASSERT(global->thread_data_table->Lookup(this, thread_id) == NULL);
- global->thread_data_table->Insert(per_thread);
- ASSERT(global->thread_data_table->Lookup(this, thread_id) ==
per_thread);
+ ScopedLock lock(process_wide_mutex_);
+ ASSERT(thread_data_table_->Lookup(this, thread_id) == NULL);
+ thread_data_table_->Insert(per_thread);
+ ASSERT(thread_data_table_->Lookup(this, thread_id) == per_thread);
}
return per_thread;
}
@@ -359,9 +339,8 @@
ThreadId thread_id = ThreadId::Current();
PerIsolateThreadData* per_thread = NULL;
{
- GlobalState* const global = global_state.Pointer();
- ScopedLock lock(global->mutex);
- per_thread = global->thread_data_table->Lookup(this, thread_id);
+ ScopedLock lock(process_wide_mutex_);
+ per_thread = thread_data_table_->Lookup(this, thread_id);
if (per_thread == NULL) {
per_thread = AllocatePerIsolateThreadData(thread_id);
}
@@ -374,74 +353,64 @@
ThreadId thread_id = ThreadId::Current();
PerIsolateThreadData* per_thread = NULL;
{
- GlobalState* const global = global_state.Pointer();
- ScopedLock lock(global->mutex);
- per_thread = global->thread_data_table->Lookup(this, thread_id);
+ ScopedLock lock(process_wide_mutex_);
+ per_thread = thread_data_table_->Lookup(this, thread_id);
}
return per_thread;
}
-
-
-bool Isolate::IsDefaultIsolate() const {
- return this == global_state.Get().default_isolate;
-}
void Isolate::EnsureDefaultIsolate() {
- GlobalState* const global = global_state.Pointer();
+ ScopedLock lock(process_wide_mutex_);
+ if (default_isolate_ == NULL) {
+ isolate_key_ = Thread::CreateThreadLocalKey();
+ thread_id_key_ = Thread::CreateThreadLocalKey();
+ per_isolate_thread_data_key_ = Thread::CreateThreadLocalKey();
+ thread_data_table_ = new Isolate::ThreadDataTable();
+ default_isolate_ = new Isolate();
+ }
// Can't use SetIsolateThreadLocals(default_isolate_, NULL) here
// because a non-null thread data may be already set.
- if (Thread::GetThreadLocal(global->isolate_key) == NULL) {
- Thread::SetThreadLocal(global->isolate_key, global->default_isolate);
+ if (Thread::GetThreadLocal(isolate_key_) == NULL) {
+ Thread::SetThreadLocal(isolate_key_, default_isolate_);
}
}
+struct StaticInitializer {
+ StaticInitializer() {
+ Isolate::EnsureDefaultIsolate();
+ }
+} static_initializer;
#ifdef ENABLE_DEBUGGER_SUPPORT
Debugger* Isolate::GetDefaultIsolateDebugger() {
EnsureDefaultIsolate();
- return global_state.Pointer()->default_isolate->debugger();
+ return default_isolate_->debugger();
}
#endif
StackGuard* Isolate::GetDefaultIsolateStackGuard() {
EnsureDefaultIsolate();
- return global_state.Pointer()->default_isolate->stack_guard();
-}
-
-
-Thread::LocalStorageKey Isolate::isolate_key() {
- return global_state.Get().isolate_key;
-}
-
-
-Thread::LocalStorageKey Isolate::thread_id_key() {
- return global_state.Get().thread_id_key;
-}
-
-
-Thread::LocalStorageKey Isolate::per_isolate_thread_data_key() {
- return global_state.Get().per_isolate_thread_data_key;
+ return default_isolate_->stack_guard();
}
void Isolate::EnterDefaultIsolate() {
EnsureDefaultIsolate();
- Isolate* const default_isolate = global_state.Pointer()->default_isolate;
- ASSERT(default_isolate != NULL);
+ ASSERT(default_isolate_ != NULL);
PerIsolateThreadData* data = CurrentPerIsolateThreadData();
// If not yet in default isolate - enter it.
- if (data == NULL || data->isolate() != default_isolate) {
- default_isolate->Enter();
+ if (data == NULL || data->isolate() != default_isolate_) {
+ default_isolate_->Enter();
}
}
Isolate* Isolate::GetDefaultIsolateForLocking() {
EnsureDefaultIsolate();
- return global_state.Pointer()->default_isolate;
+ return default_isolate_;
}
@@ -1564,8 +1533,8 @@
Deinit();
- { ScopedLock lock(global_state.Pointer()->mutex);
- global_state.Pointer()->thread_data_table->RemoveAllThreads(this);
+ { ScopedLock lock(process_wide_mutex_);
+ thread_data_table_->RemoveAllThreads(this);
}
if (!IsDefaultIsolate()) {
@@ -1618,9 +1587,8 @@
void Isolate::SetIsolateThreadLocals(Isolate* isolate,
PerIsolateThreadData* data) {
- const GlobalState& global = global_state.Get();
- Thread::SetThreadLocal(global.isolate_key, isolate);
- Thread::SetThreadLocal(global.per_isolate_thread_data_key, data);
+ Thread::SetThreadLocal(isolate_key_, isolate);
+ Thread::SetThreadLocal(per_isolate_thread_data_key_, data);
}
=======================================
--- /branches/3.9/src/isolate.h Wed Mar 28 00:54:11 2012
+++ /branches/3.9/src/isolate.h Wed Apr 11 06:59:42 2012
@@ -430,25 +430,19 @@
// not currently set).
static PerIsolateThreadData* CurrentPerIsolateThreadData() {
return reinterpret_cast<PerIsolateThreadData*>(
- Thread::GetThreadLocal(per_isolate_thread_data_key()));
+ Thread::GetThreadLocal(per_isolate_thread_data_key_));
}
// Returns the isolate inside which the current thread is running.
INLINE(static Isolate* Current()) {
- const Thread::LocalStorageKey key = isolate_key();
Isolate* isolate = reinterpret_cast<Isolate*>(
- Thread::GetExistingThreadLocal(key));
- if (!isolate) {
- EnsureDefaultIsolate();
- isolate = reinterpret_cast<Isolate*>(
- Thread::GetExistingThreadLocal(key));
- }
+ Thread::GetExistingThreadLocal(isolate_key_));
ASSERT(isolate != NULL);
return isolate;
}
INLINE(static Isolate* UncheckedCurrent()) {
- return
reinterpret_cast<Isolate*>(Thread::GetThreadLocal(isolate_key()));
+ return
reinterpret_cast<Isolate*>(Thread::GetThreadLocal(isolate_key_));
}
// Usually called by Init(), but can be called early e.g. to allow
@@ -470,7 +464,7 @@
// for legacy API reasons.
void TearDown();
- bool IsDefaultIsolate() const;
+ bool IsDefaultIsolate() const { return this == default_isolate_; }
// Ensures that process-wide resources and the default isolate have been
// allocated. It is only necessary to call this method in rare cases, for
@@ -495,10 +489,14 @@
// Returns the key used to store the pointer to the current isolate.
// Used internally for V8 threads that do not execute JavaScript but
still
// are part of the domain of an isolate (like the context switcher).
- static Thread::LocalStorageKey isolate_key();
+ static Thread::LocalStorageKey isolate_key() {
+ return isolate_key_;
+ }
// Returns the key used to store process-wide thread IDs.
- static Thread::LocalStorageKey thread_id_key();
+ static Thread::LocalStorageKey thread_id_key() {
+ return thread_id_key_;
+ }
static Thread::LocalStorageKey per_isolate_thread_data_key();
@@ -1082,6 +1080,16 @@
DISALLOW_COPY_AND_ASSIGN(EntryStackItem);
};
+ // This mutex protects highest_thread_id_, thread_data_table_ and
+ // default_isolate_.
+ static Mutex* process_wide_mutex_;
+
+ static Thread::LocalStorageKey per_isolate_thread_data_key_;
+ static Thread::LocalStorageKey isolate_key_;
+ static Thread::LocalStorageKey thread_id_key_;
+ static Isolate* default_isolate_;
+ static ThreadDataTable* thread_data_table_;
+
void Deinit();
static void SetIsolateThreadLocals(Isolate* isolate,
=======================================
--- /branches/3.9/src/lazy-instance.h Wed Mar 28 00:54:11 2012
+++ /branches/3.9/src/lazy-instance.h Wed Apr 11 06:59:42 2012
@@ -65,6 +65,9 @@
// static LazyInstance<MyClass, MyCreateTrait>::type my_instance =
// LAZY_INSTANCE_INITIALIZER;
//
+// WARNING: This implementation of LazyInstance is NOT thread-safe by
default.
+// See ThreadSafeInitOnceTrait declared below for that.
+//
// Notes for advanced users:
// LazyInstance can actually be used in two different ways:
//
@@ -104,9 +107,17 @@
// Traits that define how an instance is allocated and accessed.
+// TODO(kalmard): __alignof__ is only defined for GCC > 4.2. Fix alignment
issue
+// on MIPS with other compilers.
+#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__
2))
+#define LAZY_ALIGN(x) __attribute__((aligned(__alignof__(x))))
+#else
+#define LAZY_ALIGN(x)
+#endif
+
template <typename T>
struct StaticallyAllocatedInstanceTrait {
- typedef char StorageType[sizeof(T)];
+ typedef char StorageType[sizeof(T)] LAZY_ALIGN(T);
static T* MutableInstance(StorageType* storage) {
return reinterpret_cast<T*>(storage);
@@ -118,6 +129,8 @@
}
};
+#undef LAZY_ALIGN
+
template <typename T>
struct DynamicallyAllocatedInstanceTrait {
@@ -151,9 +164,29 @@
};
+struct ThreadSafeInitOnceTrait {
+ template <typename Function, typename Storage>
+ static void Init(OnceType* once, Function function, Storage storage) {
+ CallOnce(once, function, storage);
+ }
+};
+
+
+// Initialization trait for users who don't care about thread-safety.
+struct SingleThreadInitOnceTrait {
+ template <typename Function, typename Storage>
+ static void Init(OnceType* once, Function function, Storage storage) {
+ if (*once == ONCE_STATE_UNINITIALIZED) {
+ function(storage);
+ *once = ONCE_STATE_DONE;
+ }
+ }
+};
+
+
// TODO(pliard): Handle instances destruction (using global destructors).
template <typename T, typename AllocationTrait, typename CreateTrait,
- typename DestroyTrait /* not used yet. */ >
+ typename InitOnceTrait, typename DestroyTrait /* not used yet.
*/>
struct LazyInstanceImpl {
public:
typedef typename AllocationTrait::StorageType StorageType;
@@ -164,7 +197,12 @@
}
void Init() const {
- CallOnce(&once_, &InitInstance, &storage_);
+ InitOnceTrait::Init(
+ &once_,
+ // Casts to void* are needed here to avoid breaking strict aliasing
+ // rules.
+ reinterpret_cast<void(*)(void*)>(&InitInstance), // NOLINT
+ reinterpret_cast<void*>(&storage_));
}
public:
@@ -180,35 +218,40 @@
mutable OnceType once_;
// Note that the previous field, OnceType, is an AtomicWord which
guarantees
- // the correct alignment of the storage field below.
+ // 4-byte alignment of the storage field below. If compiling with GCC
(>4.2),
+ // the LAZY_ALIGN macro above will guarantee correctness for any
alignment.
mutable StorageType storage_;
};
template <typename T,
typename CreateTrait = DefaultConstructTrait<T>,
+ typename InitOnceTrait = SingleThreadInitOnceTrait,
typename DestroyTrait = LeakyInstanceTrait<T> >
struct LazyStaticInstance {
- typedef LazyInstanceImpl<T, StaticallyAllocatedInstanceTrait<T>,
CreateTrait,
- DestroyTrait> type;
+ typedef LazyInstanceImpl<T, StaticallyAllocatedInstanceTrait<T>,
+ CreateTrait, InitOnceTrait, DestroyTrait> type;
};
template <typename T,
typename CreateTrait = DefaultConstructTrait<T>,
+ typename InitOnceTrait = SingleThreadInitOnceTrait,
typename DestroyTrait = LeakyInstanceTrait<T> >
struct LazyInstance {
// A LazyInstance is a LazyStaticInstance.
- typedef typename LazyStaticInstance<T, CreateTrait, DestroyTrait>::type
type;
+ typedef typename LazyStaticInstance<T, CreateTrait, InitOnceTrait,
+ DestroyTrait>::type type;
};
template <typename T,
typename CreateTrait = DefaultConstructTrait<T>,
+ typename InitOnceTrait = SingleThreadInitOnceTrait,
typename DestroyTrait = LeakyInstanceTrait<T> >
struct LazyDynamicInstance {
- typedef LazyInstanceImpl<T, DynamicallyAllocatedInstanceTrait<T>,
CreateTrait,
- DestroyTrait> type;
+ typedef LazyInstanceImpl<T, DynamicallyAllocatedInstanceTrait<T>,
+ CreateTrait, InitOnceTrait, DestroyTrait> type;
};
} } // namespace v8::internal
=======================================
--- /branches/3.9/src/mips/lithium-mips.cc Fri Mar 23 08:47:56 2012
+++ /branches/3.9/src/mips/lithium-mips.cc Wed Apr 11 06:59:42 2012
@@ -2277,6 +2277,9 @@
undefined,
instr->call_kind(),
instr->is_construct());
+ if (instr->arguments() != NULL) {
+ inner->Bind(instr->arguments(), graph()->GetArgumentsObject());
+ }
current_block_->UpdateEnvironment(inner);
chunk_->AddInlinedClosure(instr->closure());
return NULL;
=======================================
--- /branches/3.9/src/platform-cygwin.cc Wed Mar 28 00:54:11 2012
+++ /branches/3.9/src/platform-cygwin.cc Wed Apr 11 06:59:42 2012
@@ -41,6 +41,7 @@
#include "v8.h"
+#include "platform-posix.h"
#include "platform.h"
#include "v8threads.h"
#include "vm-state-inl.h"
@@ -73,6 +74,12 @@
}
+void OS::PostSetUp() {
+ // Math functions depend on CPU features therefore they are initialized
after
+ // CPU.
+ MathSetup();
+}
+
uint64_t OS::CpuFeaturesImpliedByPlatform() {
return 0; // Nothing special about Cygwin.
}
=======================================
--- /branches/3.9/src/platform-freebsd.cc Wed Mar 28 00:54:11 2012
+++ /branches/3.9/src/platform-freebsd.cc Wed Apr 11 06:59:42 2012
@@ -54,6 +54,7 @@
#include "v8.h"
#include "v8threads.h"
+#include "platform-posix.h"
#include "platform.h"
#include "vm-state-inl.h"
@@ -89,6 +90,13 @@
srandom(static_cast<unsigned int>(seed));
limit_mutex = CreateMutex();
}
+
+
+void OS::PostSetUp() {
+ // Math functions depend on CPU features therefore they are initialized
after
+ // CPU.
+ MathSetup();
+}
void OS::ReleaseStore(volatile AtomicWord* ptr, AtomicWord value) {
=======================================
--- /branches/3.9/src/platform-linux.cc Wed Mar 28 00:54:11 2012
+++ /branches/3.9/src/platform-linux.cc Wed Apr 11 06:59:42 2012
@@ -57,6 +57,7 @@
#include "v8.h"
+#include "platform-posix.h"
#include "platform.h"
#include "v8threads.h"
#include "vm-state-inl.h"
@@ -103,6 +104,13 @@
}
#endif
}
+
+
+void OS::PostSetUp() {
+ // Math functions depend on CPU features therefore they are initialized
after
+ // CPU.
+ MathSetup();
+}
uint64_t OS::CpuFeaturesImpliedByPlatform() {
=======================================
--- /branches/3.9/src/platform-macos.cc Wed Mar 28 00:54:11 2012
+++ /branches/3.9/src/platform-macos.cc Wed Apr 11 06:59:42 2012
@@ -58,6 +58,7 @@
#include "v8.h"
+#include "platform-posix.h"
#include "platform.h"
#include "vm-state-inl.h"
@@ -99,6 +100,13 @@
srandom(static_cast<unsigned int>(seed));
limit_mutex = CreateMutex();
}
+
+
+void OS::PostSetUp() {
+ // Math functions depend on CPU features therefore they are initialized
after
+ // CPU.
+ MathSetup();
+}
// We keep the lowest and highest addresses mapped as a quick way of
=======================================
--- /branches/3.9/src/platform-nullos.cc Tue Mar 6 00:42:24 2012
+++ /branches/3.9/src/platform-nullos.cc Wed Apr 11 06:59:42 2012
@@ -84,6 +84,11 @@
// Seed the random number generator.
UNIMPLEMENTED();
}
+
+
+void OS::PostSetUp() {
+ UNIMPLEMENTED();
+}
// Returns the accumulated user time for thread.
=======================================
--- /branches/3.9/src/platform-openbsd.cc Wed Mar 28 00:54:11 2012
+++ /branches/3.9/src/platform-openbsd.cc Wed Apr 11 06:59:42 2012
@@ -51,6 +51,7 @@
#include "v8.h"
+#include "platform-posix.h"
#include "platform.h"
#include "v8threads.h"
#include "vm-state-inl.h"
@@ -105,6 +106,13 @@
srandom(static_cast<unsigned int>(seed));
limit_mutex = CreateMutex();
}
+
+
+void OS::PostSetUp() {
+ // Math functions depend on CPU features therefore they are initialized
after
+ // CPU.
+ MathSetup();
+}
uint64_t OS::CpuFeaturesImpliedByPlatform() {
=======================================
--- /branches/3.9/src/platform-posix.cc Wed Mar 28 00:54:11 2012
+++ /branches/3.9/src/platform-posix.cc Wed Apr 11 06:59:42 2012
@@ -29,6 +29,8 @@
// own but contains the parts which are the same across POSIX platforms
Linux,
// Mac OS, FreeBSD and OpenBSD.
+#include "platform-posix.h"
+
#include <unistd.h>
#include <errno.h>
#include <time.h>
@@ -129,13 +131,10 @@
#define UNARY_MATH_FUNCTION(name, generator) \
static UnaryMathFunction fast_##name##_function = NULL; \
-V8_DECLARE_ONCE(fast_##name##_init_once); \
void init_fast_##name##_function() { \
fast_##name##_function = generator; \
} \
double fast_##name(double x) { \
- CallOnce(&fast_##name##_init_once, \
- &init_fast_##name##_function); \
return (*fast_##name##_function)(x); \
}
@@ -148,6 +147,15 @@
#undef MATH_FUNCTION
+void MathSetup() {
+ init_fast_sin_function();
+ init_fast_cos_function();
+ init_fast_tan_function();
+ init_fast_log_function();
+ init_fast_sqrt_function();
+}
+
+
double OS::nan_value() {
// NAN from math.h is defined in C99 and not in POSIX.
return NAN;
=======================================
--- /branches/3.9/src/platform-solaris.cc Wed Mar 28 00:54:11 2012
+++ /branches/3.9/src/platform-solaris.cc Wed Apr 11 06:59:42 2012
@@ -52,6 +52,7 @@
#include "v8.h"
+#include "platform-posix.h"
#include "platform.h"
#include "v8threads.h"
#include "vm-state-inl.h"
@@ -100,6 +101,13 @@
srandom(static_cast<unsigned int>(seed));
limit_mutex = CreateMutex();
}
+
+
+void OS::PostSetUp() {
+ // Math functions depend on CPU features therefore they are initialized
after
+ // CPU.
+ MathSetup();
+}
uint64_t OS::CpuFeaturesImpliedByPlatform() {
=======================================
--- /branches/3.9/src/platform-win32.cc Wed Mar 28 00:54:11 2012
+++ /branches/3.9/src/platform-win32.cc Wed Apr 11 06:59:42 2012
@@ -175,7 +175,6 @@
#ifdef _WIN64
typedef double (*ModuloFunction)(double, double);
static ModuloFunction modulo_function = NULL;
-V8_DECLARE_ONCE(modulo_function_init_once);
// Defined in codegen-x64.cc.
ModuloFunction CreateModuloFunction();
@@ -184,7 +183,6 @@
}
double modulo(double x, double y) {
- CallOnce(&modulo_function_init_once, &init_modulo_function);
// Note: here we rely on dependent reads being ordered. This is true
// on all architectures we currently support.
return (*modulo_function)(x, y);
@@ -207,13 +205,10 @@
#define UNARY_MATH_FUNCTION(name, generator) \
static UnaryMathFunction fast_##name##_function = NULL; \
-V8_DECLARE_ONCE(fast_##name##_init_once); \
void init_fast_##name##_function() { \
fast_##name##_function = generator; \
} \
double fast_##name(double x) { \
- CallOnce(&fast_##name##_init_once, \
- &init_fast_##name##_function); \
return (*fast_##name##_function)(x); \
}
@@ -226,6 +221,18 @@
#undef MATH_FUNCTION
+void MathSetup() {
+#ifdef _WIN64
+ init_modulo_function();
+#endif
+ init_fast_sin_function();
+ init_fast_cos_function();
+ init_fast_tan_function();
+ init_fast_log_function();
+ init_fast_sqrt_function();
+}
+
+
//
----------------------------------------------------------------------------
// The Time class represents time on win32. A timestamp is represented as
// a 64-bit integer in 100 nanoseconds since January 1, 1601 (UTC).
JavaScript
@@ -568,6 +575,13 @@
srand(static_cast<unsigned int>(seed));
limit_mutex = CreateMutex();
}
+
+
+void OS::PostSetUp() {
+ // Math functions depend on CPU features therefore they are initialized
after
+ // CPU.
+ MathSetup();
+}
// Returns the accumulated user time for thread.
=======================================
--- /branches/3.9/src/platform.h Wed Mar 28 00:54:11 2012
+++ /branches/3.9/src/platform.h Wed Apr 11 06:59:42 2012
@@ -119,6 +119,10 @@
// Initializes the platform OS support. Called once at VM startup.
static void SetUp();
+ // Initializes the platform OS support that depend on CPU features. This
is
+ // called after CPU initialization.
+ static void PostSetUp();
+
// Returns the accumulated user time for thread. This routine
// can be used for profiling. The implementation should
// strive for high-precision timer resolution, preferable
@@ -545,7 +549,8 @@
// // Do something.
// }
//
-typedef LazyDynamicInstance<Mutex, CreateMutexTrait>::type LazyMutex;
+typedef LazyDynamicInstance<
+ Mutex, CreateMutexTrait, ThreadSafeInitOnceTrait>::type LazyMutex;
#define LAZY_MUTEX_INITIALIZER LAZY_DYNAMIC_INSTANCE_INITIALIZER
@@ -616,7 +621,8 @@
template <int InitialValue>
struct LazySemaphore {
typedef typename LazyDynamicInstance<
- Semaphore, CreateSemaphoreTrait<InitialValue> >::type type;
+ Semaphore, CreateSemaphoreTrait<InitialValue>,
+ ThreadSafeInitOnceTrait>::type type;
};
#define LAZY_SEMAPHORE_INITIALIZER LAZY_DYNAMIC_INSTANCE_INITIALIZER
=======================================
--- /branches/3.9/src/v8.cc Wed Mar 28 00:54:11 2012
+++ /branches/3.9/src/v8.cc Wed Apr 11 06:59:42 2012
@@ -253,6 +253,8 @@
if (!CPU::SupportsCrankshaft()) {
use_crankshaft_ = false;
}
+
+ OS::PostSetUp();
RuntimeProfiler::GlobalSetup();
=======================================
--- /branches/3.9/src/version.cc Wed Apr 11 02:35:05 2012
+++ /branches/3.9/src/version.cc Wed Apr 11 06:59:42 2012
@@ -35,7 +35,7 @@
#define MAJOR_VERSION 3
#define MINOR_VERSION 9
#define BUILD_NUMBER 24
-#define PATCH_LEVEL 10
+#define PATCH_LEVEL 11
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
#define IS_CANDIDATE_VERSION 0
=======================================
--- /branches/3.9/src/x64/lithium-x64.cc Fri Mar 23 08:47:56 2012
+++ /branches/3.9/src/x64/lithium-x64.cc Wed Apr 11 06:59:42 2012
@@ -2270,6 +2270,9 @@
undefined,
instr->call_kind(),
instr->is_construct());
+ if (instr->arguments() != NULL) {
+ inner->Bind(instr->arguments(), graph()->GetArgumentsObject());
+ }
current_block_->UpdateEnvironment(inner);
chunk_->AddInlinedClosure(instr->closure());
return NULL;
=======================================
--- /branches/3.9/tools/check-static-initializers.sh Wed Mar 28 00:54:11
2012
+++ /branches/3.9/tools/check-static-initializers.sh Wed Apr 11 06:59:42
2012
@@ -31,9 +31,10 @@
# Note that the project must be built with SCons before running this
script.
# Allow:
-# - _GLOBAL__I__ZN2v88internal32AtomicOps_Internalx86CPUFeaturesE
# - _GLOBAL__I__ZN2v810LineEditor6first_E
-expected_static_init_count=2
+# - _GLOBAL__I__ZN2v88internal32AtomicOps_Internalx86CPUFeaturesE
+# - _GLOBAL__I__ZN2v88internal8ThreadId18highest_thread_id_E
+expected_static_init_count=3
v8_root=$(readlink -f $(dirname $BASH_SOURCE)/../)
d8="${v8_root}/d8"
=======================================
--- /branches/3.9/tools/gyp/v8.gyp Wed Mar 28 00:54:11 2012
+++ /branches/3.9/tools/gyp/v8.gyp Wed Apr 11 06:59:42 2012
@@ -395,6 +395,7 @@
'../../src/once.h',
'../../src/parser.cc',
'../../src/parser.h',
+ '../../src/platform-posix.h',
'../../src/platform-tls-mac.h',
'../../src/platform-tls-win32.h',
'../../src/platform-tls.h',
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev