Push version 1.3.10 to trunk.

Fixed profiler on Mac in 64-bit mode.

Optimized creation of objects from simple constructor functions on ARM.

Fixed a number of debugger issues.

Reduced the amount of memory consumed by V8.




git-svn-id: http://v8.googlecode.com/svn/trunk@2866 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/platform-linux.cc b/src/platform-linux.cc
index 6ec5070..fe4c31f 100644
--- a/src/platform-linux.cc
+++ b/src/platform-linux.cc
@@ -56,6 +56,8 @@
 #include "v8.h"
 
 #include "platform.h"
+#include "top.h"
+#include "v8threads.h"
 
 
 namespace v8 {
@@ -145,7 +147,9 @@
 
 void OS::Free(void* address, const size_t size) {
   // TODO(1240712): munmap has a return value which is ignored here.
-  munmap(address, size);
+  int result = munmap(address, size);
+  USE(result);
+  ASSERT(result == 0);
 }
 
 
@@ -360,7 +364,7 @@
 
 bool VirtualMemory::Uncommit(void* address, size_t size) {
   return mmap(address, size, PROT_NONE,
-              MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
+              MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_FIXED,
               kMmapFd, kMmapFdOffset) != MAP_FAILED;
 }
 
@@ -580,6 +584,7 @@
 #ifdef ENABLE_LOGGING_AND_PROFILING
 
 static Sampler* active_sampler_ = NULL;
+static pthread_t vm_thread_ = 0;
 
 
 #if !defined(__GLIBC__) && (defined(__arm__) || defined(__thumb__))
@@ -608,6 +613,30 @@
 #endif
 
 
+// A function that determines if a signal handler is called in the context
+// of a VM thread.
+//
+// The problem is that SIGPROF signal can be delivered to an arbitrary thread
+// (see http://code.google.com/p/google-perftools/issues/detail?id=106#c2)
+// So, if the signal is being handled in the context of a non-VM thread,
+// it means that the VM thread is running, and trying to sample its stack can
+// cause a crash.
+static inline bool IsVmThread() {
+  // In the case of a single VM thread, this check is enough.
+  if (pthread_equal(pthread_self(), vm_thread_)) return true;
+  // If there are multiple threads that use VM, they must have a thread id
+  // stored in TLS. To verify that the thread is really executing VM,
+  // we check Top's data. Having that ThreadManager::RestoreThread first
+  // restores ThreadLocalTop from TLS, and only then erases the TLS value,
+  // reading Top::thread_id() should not be affected by races.
+  if (ThreadManager::HasId() && !ThreadManager::IsArchived() &&
+      ThreadManager::CurrentId() == Top::thread_id()) {
+    return true;
+  }
+  return false;
+}
+
+
 static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
   USE(info);
   if (signal != SIGPROF) return;
@@ -640,7 +669,8 @@
     sample.fp = mcontext.arm_fp;
 #endif
 #endif
-    active_sampler_->SampleStack(&sample);
+    if (IsVmThread())
+      active_sampler_->SampleStack(&sample);
   }
 
   // We always sample the VM state.
@@ -678,6 +708,8 @@
   // platforms.
   if (active_sampler_ != NULL) return;
 
+  vm_thread_ = pthread_self();
+
   // Request profiling signals.
   struct sigaction sa;
   sa.sa_sigaction = ProfilerSignalHandler;
@@ -713,6 +745,7 @@
   active_ = false;
 }
 
+
 #endif  // ENABLE_LOGGING_AND_PROFILING
 
 } }  // namespace v8::internal