Revision: 5005
Author: [email protected]
Date: Thu Jul  1 15:12:37 2010
Log: [Isolates] Statics 7: ExternalReference*/Simulator/dtoa

- Fix up ExternalReference{Table|Encoder|Decoder} for multiple isolates.
- Define MULTIPLE_THREADS for dtoa.
- Fix up the simulator for multiple isolates.

Review URL: http://codereview.chromium.org/2864032
http://code.google.com/p/v8/source/detail?r=5005

Modified:
 /branches/experimental/isolates/src/arm/cpu-arm.cc
 /branches/experimental/isolates/src/arm/simulator-arm.cc
 /branches/experimental/isolates/src/arm/simulator-arm.h
 /branches/experimental/isolates/src/conversions.cc
 /branches/experimental/isolates/src/dtoa-config.c
 /branches/experimental/isolates/src/isolate.cc
 /branches/experimental/isolates/src/isolate.h
 /branches/experimental/isolates/src/serialize.cc
 /branches/experimental/isolates/src/serialize.h

=======================================
--- /branches/experimental/isolates/src/arm/cpu-arm.cc Wed Jun 16 09:30:02 2010 +++ /branches/experimental/isolates/src/arm/cpu-arm.cc Thu Jul 1 15:12:37 2010
@@ -56,7 +56,8 @@
   // that the Icache was flushed.
   // None of this code ends up in the snapshot so there are no issues
   // around whether or not to generate the code when building snapshots.
-  assembler::arm::Simulator::FlushICache(start, size);
+  assembler::arm::Simulator::FlushICache(
+      Isolate::Current()->simulator_i_cache(), start, size);
 #else
   // Ideally, we would call
   //   syscall(__ARM_NR_cacheflush, start,
=======================================
--- /branches/experimental/isolates/src/arm/simulator-arm.cc Fri Jun 25 15:53:25 2010 +++ /branches/experimental/isolates/src/arm/simulator-arm.cc Thu Jul 1 15:12:37 2010
@@ -47,6 +47,7 @@
 using ::v8::internal::OS;
 using ::v8::internal::ReadLine;
 using ::v8::internal::DeleteArray;
+using ::v8::internal::Isolate;

 // This macro provides a platform independent use of sscanf. The reason for
 // SScanF not being implemented in a platform independent way through
@@ -495,7 +496,9 @@
 }


-void Simulator::FlushICache(void* start_addr, size_t size) {
+void Simulator::FlushICache(v8::internal::HashMap* i_cache,
+                            void* start_addr,
+                            size_t size) {
   intptr_t start = reinterpret_cast<intptr_t>(start_addr);
   int intra_line = (start & CachePage::kLineMask);
   start -= intra_line;
@@ -504,22 +507,22 @@
   int offset = (start & CachePage::kPageMask);
   while (!AllOnOnePage(start, size - 1)) {
     int bytes_to_flush = CachePage::kPageSize - offset;
-    FlushOnePage(start, bytes_to_flush);
+    FlushOnePage(i_cache, start, bytes_to_flush);
     start += bytes_to_flush;
     size -= bytes_to_flush;
     ASSERT_EQ(0, start & CachePage::kPageMask);
     offset = 0;
   }
   if (size != 0) {
-    FlushOnePage(start, size);
+    FlushOnePage(i_cache, start, size);
   }
 }


-CachePage* Simulator::GetCachePage(void* page) {
-  v8::internal::HashMap::Entry* entry = i_cache_->Lookup(page,
-                                                         ICacheHash(page),
-                                                         true);
+CachePage* Simulator::GetCachePage(v8::internal::HashMap* i_cache, void* page) {
+  v8::internal::HashMap::Entry* entry = i_cache->Lookup(page,
+                                                        ICacheHash(page),
+                                                        true);
   if (entry->value == NULL) {
     CachePage* new_page = new CachePage();
     entry->value = new_page;
@@ -529,25 +532,27 @@


 // Flush from start up to and not including start + size.
-void Simulator::FlushOnePage(intptr_t start, int size) {
+void Simulator::FlushOnePage(v8::internal::HashMap* i_cache,
+                             intptr_t start,
+                             int size) {
   ASSERT(size <= CachePage::kPageSize);
   ASSERT(AllOnOnePage(start, size - 1));
   ASSERT((start & CachePage::kLineMask) == 0);
   ASSERT((size & CachePage::kLineMask) == 0);
   void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask));
   int offset = (start & CachePage::kPageMask);
-  CachePage* cache_page = GetCachePage(page);
+  CachePage* cache_page = GetCachePage(i_cache, page);
   char* valid_bytemap = cache_page->ValidityByte(offset);
memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
 }


-void Simulator::CheckICache(Instr* instr) {
+void Simulator::CheckICache(v8::internal::HashMap* i_cache, Instr* instr) {
   intptr_t address = reinterpret_cast<intptr_t>(instr);
   void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
   void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
   int offset = (address & CachePage::kPageMask);
-  CachePage* cache_page = GetCachePage(page);
+  CachePage* cache_page = GetCachePage(i_cache, page);
   char* cache_valid_byte = cache_page->ValidityByte(offset);
   bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask);
@@ -562,29 +567,20 @@
     *cache_valid_byte = CachePage::LINE_VALID;
   }
 }
-
-
-// Create one simulator per thread and keep it in thread local storage.
-static v8::internal::Thread::LocalStorageKey simulator_key;
-
-
-bool Simulator::initialized_ = false;


 void Simulator::Initialize() {
-  if (initialized_) return;
-  simulator_key = v8::internal::Thread::CreateThreadLocalKey();
-  initialized_ = true;
+  if (Isolate::Current()->simulator_initialized()) return;
+  Isolate::Current()->set_simulator_initialized(true);
   
::v8::internal::ExternalReference::set_redirector(&RedirectExternalReference);
 }


-v8::internal::HashMap* Simulator::i_cache_ = NULL;
-
-
-Simulator::Simulator() {
+Simulator::Simulator() : isolate_(Isolate::Current()) {
+  i_cache_ = isolate_->simulator_i_cache();
   if (i_cache_ == NULL) {
     i_cache_ = new v8::internal::HashMap(&ICacheMatch);
+    isolate_->set_simulator_i_cache(i_cache_);
   }
   Initialize();
   // Setup simulator support first. Some of this information is needed to
@@ -649,11 +645,13 @@
       : external_function_(external_function),
         swi_instruction_((AL << 28) | (0xf << 24) | call_rt_redirected),
         fp_return_(fp_return),
-        next_(list_) {
-    Simulator::current()->
-        FlushICache(reinterpret_cast<void*>(&swi_instruction_),
-                      Instr::kInstrSize);
-    list_ = this;
+        next_(NULL) {
+    v8::internal::Isolate* isolate = Isolate::Current();
+    next_ = isolate->simulator_redirection();
+    Simulator::FlushICache(isolate->simulator_i_cache(),
+                           reinterpret_cast<void*>(&swi_instruction_),
+                           Instr::kInstrSize);
+    isolate->set_simulator_redirection(this);
   }

   void* address_of_swi_instruction() {
@@ -664,8 +662,9 @@
   bool fp_return() { return fp_return_; }

   static Redirection* Get(void* external_function, bool fp_return) {
-    Redirection* current;
-    for (current = list_; current != NULL; current = current->next_) {
+    Isolate* isolate = Isolate::Current();
+    Redirection* current = isolate->simulator_redirection();
+    for (; current != NULL; current = current->next_) {
       if (current->external_function_ == external_function) return current;
     }
     return new Redirection(external_function, fp_return);
@@ -683,13 +682,9 @@
   uint32_t swi_instruction_;
   bool fp_return_;
   Redirection* next_;
-  static Redirection* list_;
 };


-Redirection* Redirection::list_ = NULL;
-
-
 void* Simulator::RedirectExternalReference(void* external_function,
                                            bool fp_return) {
Redirection* redirection = Redirection::Get(external_function, fp_return);
@@ -698,14 +693,16 @@


 // Get the active Simulator for the current thread.
-Simulator* Simulator::current() {
+Simulator* Simulator::current(Isolate* isolate) {
+  v8::internal::Thread::LocalStorageKey* simulator_key =
+      Isolate::Current()->simulator_key();
   Initialize();
   Simulator* sim = reinterpret_cast<Simulator*>(
-      v8::internal::Thread::GetThreadLocal(simulator_key));
+      v8::internal::Thread::GetThreadLocal(*simulator_key));
   if (sim == NULL) {
     // TODO(146): delete the simulator object when a thread goes away.
     sim = new Simulator();
-    v8::internal::Thread::SetThreadLocal(simulator_key, sim);
+    v8::internal::Thread::SetThreadLocal(*simulator_key, sim);
   }
   return sim;
 }
@@ -2568,7 +2565,7 @@
 // Executes the current instruction.
 void Simulator::InstructionDecode(Instr* instr) {
   if (v8::internal::FLAG_check_icache) {
-    CheckICache(instr);
+    CheckICache(isolate_->simulator_i_cache(), instr);
   }
   pc_modified_ = false;
   if (::v8::internal::FLAG_trace_sim) {
=======================================
--- /branches/experimental/isolates/src/arm/simulator-arm.h Fri May 7 13:02:57 2010 +++ /branches/experimental/isolates/src/arm/simulator-arm.h Thu Jul 1 15:12:37 2010
@@ -74,17 +74,17 @@

// When running with the simulator transition into simulated execution at this
 // point.
-#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
-  reinterpret_cast<Object*>( \
-      assembler::arm::Simulator::current()->Call(FUNCTION_ADDR(entry), 5, \
-                                                 p0, p1, p2, p3, p4))
-
-#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6) \
-  assembler::arm::Simulator::current()->Call( \
+#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \ + reinterpret_cast<Object*>( \ + assembler::arm::Simulator::current(Isolate::Current())-> \
+          Call(FUNCTION_ADDR(entry), 5, p0, p1, p2, p3, p4))
+
+#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6) \ + assembler::arm::Simulator::current(Isolate::Current())->Call( \
     FUNCTION_ADDR(entry), 7, p0, p1, p2, p3, p4, p5, p6)

-#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
-  try_catch_address == NULL ? \
+#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \ + try_catch_address == NULL ? \
       NULL : *(reinterpret_cast<TryCatch**>(try_catch_address))


@@ -152,7 +152,7 @@

// The currently executing Simulator instance. Potentially there can be one
   // for each native thread.
-  static Simulator* current();
+  static Simulator* current(v8::internal::Isolate* isolate);

   // Accessors for register state. Reading the pc value adheres to the ARM
// architecture specification and is off by a 8 from the currently executing
@@ -196,7 +196,8 @@
   uintptr_t PopAddress();

   // ICache checking.
-  static void FlushICache(void* start, size_t size);
+  static void FlushICache(v8::internal::HashMap* i_cache, void* start,
+                          size_t size);

  private:
   enum special_values {
@@ -279,9 +280,10 @@
   void InstructionDecode(Instr* instr);

   // ICache.
-  static void CheckICache(Instr* instr);
-  static void FlushOnePage(intptr_t start, int size);
-  static CachePage* GetCachePage(void* page);
+  static void CheckICache(v8::internal::HashMap* i_cache, Instr* instr);
+  static void FlushOnePage(v8::internal::HashMap* i_cache, intptr_t start,
+                           int size);
+ static CachePage* GetCachePage(v8::internal::HashMap* i_cache, void* page);

   // Runtime call support.
   static void* RedirectExternalReference(void* external_function,
@@ -318,14 +320,15 @@
   char* stack_;
   bool pc_modified_;
   int icount_;
-  static bool initialized_;

   // Icache simulation
-  static v8::internal::HashMap* i_cache_;
+  v8::internal::HashMap* i_cache_;

   // Registered breakpoints.
   Instr* break_pc_;
   instr_t break_instr_;
+
+  v8::internal::Isolate* isolate_;
 };

 } }  // namespace assembler::arm
@@ -339,16 +342,19 @@
 class SimulatorStack : public v8::internal::AllStatic {
  public:
   static inline uintptr_t JsLimitFromCLimit(uintptr_t c_limit) {
-    return assembler::arm::Simulator::current()->StackLimit();
+    return assembler::arm::Simulator::current(
+        v8::internal::Isolate::Current())->StackLimit();
   }

   static inline uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) {
-    assembler::arm::Simulator* sim = assembler::arm::Simulator::current();
+    assembler::arm::Simulator* sim =
+ assembler::arm::Simulator::current(v8::internal::Isolate::Current());
     return sim->PushAddress(try_catch_address);
   }

   static inline void UnregisterCTryCatch() {
-    assembler::arm::Simulator::current()->PopAddress();
+    assembler::arm::Simulator::current(v8::internal::Isolate::Current())->
+        PopAddress();
   }
 };

=======================================
--- /branches/experimental/isolates/src/conversions.cc Thu Jun 17 06:14:39 2010 +++ /branches/experimental/isolates/src/conversions.cc Thu Jul 1 15:12:37 2010
@@ -1152,6 +1152,25 @@
   builder.AddSubstring(decimal_buffer, decimal_pos);
   return builder.Finalize();
 }
+
+
+static Mutex* dtoa_lock_one = OS::CreateMutex();
+static Mutex* dtoa_lock_zero = OS::CreateMutex();


 } }  // namespace v8::internal
+
+
+extern "C" {
+void ACQUIRE_DTOA_LOCK(int n) {
+  ASSERT(n == 0 || n == 1);
+ (n == 0 ? v8::internal::dtoa_lock_zero : v8::internal::dtoa_lock_one)->Lock();
+}
+
+
+void FREE_DTOA_LOCK(int n) {
+  ASSERT(n == 0 || n == 1);
+  (n == 0 ? v8::internal::dtoa_lock_zero : v8::internal::dtoa_lock_one)->
+      Unlock();
+}
+}
=======================================
--- /branches/experimental/isolates/src/dtoa-config.c Mon Jan 25 04:37:31 2010 +++ /branches/experimental/isolates/src/dtoa-config.c Thu Jul 1 15:12:37 2010
@@ -85,6 +85,10 @@
 #define Long int
 #endif /* V8_TARGET_ARCH_X64 */

+/* Definitions for dtoa's ACQUIRE_DTOA_LOCK and FREE_DTOA_LOCK are in
+ * conversions.cc. */
+#define MULTIPLE_THREADS
+
 /* Make sure we use the David M. Gay version of strtod(). On Linux, we
  * cannot use the same name (maybe the function does not have weak
  * linkage?). */
=======================================
--- /branches/experimental/isolates/src/isolate.cc      Thu Jul  1 14:55:46 2010
+++ /branches/experimental/isolates/src/isolate.cc      Thu Jul  1 15:12:37 2010
@@ -266,6 +266,13 @@
   zone_.isolate_ = this;
   stack_guard_.isolate_ = this;

+#if defined(V8_TARGET_ARCH_ARM) && !defined(__arm__)
+  simulator_initialized_ = false;
+  simulator_i_cache_ = NULL;
+  simulator_key_ = Thread::CreateThreadLocalKey();
+  simulator_redirection_ = NULL;
+#endif
+
 #ifdef DEBUG
   // heap_histograms_ initializes itself.
   memset(&js_spill_information_, 0, sizeof(js_spill_information_));
@@ -399,6 +406,10 @@
   debug_ = NULL;
 #endif

+#if defined(V8_TARGET_ARCH_ARM) && !defined(__arm__)
+  Thread::DeleteThreadLocalKey(simulator_key_);
+#endif
+
   if (state_ == INITIALIZED) --number_of_isolates_;
 }

=======================================
--- /branches/experimental/isolates/src/isolate.h       Thu Jul  1 14:55:46 2010
+++ /branches/experimental/isolates/src/isolate.h       Thu Jul  1 15:12:37 2010
@@ -45,6 +45,16 @@
 #include "zone.h"
 #include "../include/v8-debug.h"

+
+#if !defined(__arm__) && defined(V8_TARGET_ARCH_ARM)
+namespace assembler {
+namespace arm {
+class Redirection;
+}
+}
+#endif
+
+
 namespace v8 {
 namespace internal {

@@ -60,6 +70,7 @@
 class CpuProfiler;
 class Deserializer;
 class EmptyStatement;
+class ExternalReferenceTable;
 class FunctionInfoListener;
 class HandleScopeImplementer;
 class HeapProfiler;
@@ -197,6 +208,10 @@
/* VirtualFrame::SpilledScope state */ \
   V(bool, is_virtual_frame_in_spilled_scope, false)

+#if !defined(__arm__)
+class HashMap;
+#endif
+
 #else

 #define ISOLATE_PLATFORM_INIT_LIST(V)
@@ -276,6 +291,8 @@
V(Object*, string_stream_current_security_token, NULL) \ /* TODO(isolates): Release this on destruction? */ \ V(int*, irregexp_interpreter_backtrack_stack_cache, NULL) \ + /* Serializer state. */ \ + V(ExternalReferenceTable*, external_reference_table, NULL) \ ISOLATE_PLATFORM_INIT_LIST(V) \ ISOLATE_LOGGING_INIT_LIST(V) \
   ISOLATE_DEBUGGER_INIT_LIST(V)
@@ -704,6 +721,29 @@
   int* code_kind_statistics() { return code_kind_statistics_; }
 #endif

+#if defined(V8_TARGET_ARCH_ARM) && !defined(__arm__)
+  v8::internal::Thread::LocalStorageKey* simulator_key() {
+    return &simulator_key_;
+  }
+
+  bool simulator_initialized() { return simulator_initialized_; }
+  void set_simulator_initialized(bool initialized) {
+    simulator_initialized_ = initialized;
+  }
+
+  HashMap* simulator_i_cache() { return simulator_i_cache_; }
+  void set_simulator_i_cache(HashMap* hash_map) {
+    simulator_i_cache_ = hash_map;
+  }
+
+  assembler::arm::Redirection* simulator_redirection() {
+    return simulator_redirection_;
+  }
+ void set_simulator_redirection(assembler::arm::Redirection* redirection) {
+    simulator_redirection_ = redirection;
+  }
+#endif
+
   bool IsDefaultIsolate() { return this == global_isolate_; }

   // SerializerDeserializer state.
@@ -808,6 +848,13 @@
   ZoneObjectList frame_element_constant_list_;
   ZoneObjectList result_constant_list_;

+#if defined(V8_TARGET_ARCH_ARM) && !defined(__arm__)
+  // Create one simulator per thread and keep it in thread local storage.
+  v8::internal::Thread::LocalStorageKey simulator_key_;
+  bool simulator_initialized_;
+  HashMap* simulator_i_cache_;
+  assembler::arm::Redirection* simulator_redirection_;
+#endif

 #ifdef DEBUG
   // A static array of histogram info for each type.
=======================================
--- /branches/experimental/isolates/src/serialize.cc Thu Jul 1 11:02:03 2010 +++ /branches/experimental/isolates/src/serialize.cc Thu Jul 1 15:12:37 2010
@@ -67,9 +67,14 @@
 // hashmaps in ExternalReferenceEncoder and ExternalReferenceDecoder.
 class ExternalReferenceTable {
  public:
-  static ExternalReferenceTable* instance() {
-    if (!instance_) instance_ = new ExternalReferenceTable();
-    return instance_;
+  static ExternalReferenceTable* instance(Isolate* isolate) {
+    ExternalReferenceTable* external_reference_table =
+        isolate->external_reference_table();
+    if (external_reference_table == NULL) {
+      external_reference_table = new ExternalReferenceTable(isolate);
+      isolate->set_external_reference_table(external_reference_table);
+    }
+    return external_reference_table;
   }

   int size() const { return refs_.length(); }
@@ -83,9 +88,9 @@
   int max_id(int code) { return max_id_[code]; }

  private:
-  static ExternalReferenceTable* instance_;
-
-  ExternalReferenceTable() : refs_(64) { PopulateTable(); }
+  explicit ExternalReferenceTable(Isolate* isolate) : refs_(64) {
+      PopulateTable(isolate);
+  }
   ~ExternalReferenceTable() { }

   struct ExternalReferenceEntry {
@@ -94,7 +99,7 @@
     const char* name;
   };

-  void PopulateTable();
+  void PopulateTable(Isolate* isolate);

   // For a few types of references, we can get their address from their id.
   void AddFromId(TypeCode type, uint16_t id, const char* name);
@@ -107,9 +112,6 @@
 };


-ExternalReferenceTable* ExternalReferenceTable::instance_ = NULL;
-
-
 void ExternalReferenceTable::AddFromId(TypeCode type,
                                        uint16_t id,
                                        const char* name) {
@@ -158,9 +160,7 @@
 }


-void ExternalReferenceTable::PopulateTable() {
-  Isolate* isolate = Isolate::Current();
-
+void ExternalReferenceTable::PopulateTable(Isolate* isolate) {
   for (int type_code = 0; type_code < kTypeCodeCount; type_code++) {
     max_id_[type_code] = 0;
   }
@@ -469,9 +469,10 @@


 ExternalReferenceEncoder::ExternalReferenceEncoder()
-    : encodings_(Match) {
+    : encodings_(Match),
+      isolate_(Isolate::Current()) {
   ExternalReferenceTable* external_references =
-      ExternalReferenceTable::instance();
+      ExternalReferenceTable::instance(isolate_);
   for (int i = 0; i < external_references->size(); ++i) {
     Put(external_references->address(i), i);
   }
@@ -480,20 +481,22 @@

 uint32_t ExternalReferenceEncoder::Encode(Address key) const {
   int index = IndexOf(key);
-  return index >=0 ? ExternalReferenceTable::instance()->code(index) : 0;
+  return index >= 0 ?
+      ExternalReferenceTable::instance(isolate_)->code(index) : 0;
 }


 const char* ExternalReferenceEncoder::NameOfAddress(Address key) const {
   int index = IndexOf(key);
- return index >=0 ? ExternalReferenceTable::instance()->name(index) : NULL;
+  return index >= 0 ?
+      ExternalReferenceTable::instance(isolate_)->name(index) : NULL;
 }


 int ExternalReferenceEncoder::IndexOf(Address key) const {
   if (key == NULL) return -1;
   HashMap::Entry* entry =
-      const_cast<HashMap &>(encodings_).Lookup(key, Hash(key), false);
+      const_cast<HashMap&>(encodings_).Lookup(key, Hash(key), false);
   return entry == NULL
       ? -1
       : static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
@@ -507,9 +510,10 @@


 ExternalReferenceDecoder::ExternalReferenceDecoder()
-  : encodings_(NewArray<Address*>(kTypeCodeCount)) {
+  : encodings_(NewArray<Address*>(kTypeCodeCount)),
+    isolate_(Isolate::Current()) {
   ExternalReferenceTable* external_references =
-      ExternalReferenceTable::instance();
+      ExternalReferenceTable::instance(isolate_);
   for (int type = kFirstTypeCode; type < kTypeCodeCount; ++type) {
     int max = external_references->max_id(type) + 1;
     encodings_[type] = NewArray<Address>(max + 1);
=======================================
--- /branches/experimental/isolates/src/serialize.h     Tue Jun  8 10:29:06 2010
+++ /branches/experimental/isolates/src/serialize.h     Thu Jul  1 15:12:37 2010
@@ -79,6 +79,8 @@
   static bool Match(void* key1, void* key2) { return key1 == key2; }

   void Put(Address key, int index);
+
+  Isolate* isolate_;
 };


@@ -105,6 +107,8 @@
   void Put(uint32_t key, Address value) {
     *Lookup(key) = value;
   }
+
+  Isolate* isolate_;
 };


--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to