void StackFrame::CookFramesForThread(ThreadLocalTop* thread) {
- // Only cooking frames when the collector is compacting and thus moving code
- // around.
- ASSERT(MarkCompactCollector::IsCompacting());
ASSERT(!thread->stack_is_cooked());
for (StackFrameIterator it(thread); !it.done(); it.Advance()) {
it.frame()->Cook();
void StackFrame::UncookFramesForThread(ThreadLocalTop* thread) {
- // Only uncooking frames when the collector is compacting and thus moving code
- // around.
- ASSERT(MarkCompactCollector::HasCompacted());
ASSERT(thread->stack_is_cooked());
for (StackFrameIterator it(thread); !it.done(); it.Advance()) {
it.frame()->Uncook();
ZoneList<RelocInfo> reloc_infos_;
};
+
+class FrameCookingThreadVisitor : public ThreadVisitor {
+ public:
+ void VisitThread(ThreadLocalTop* top) {
+ StackFrame::CookFramesForThread(top);
+ }
+};
+
+class FrameUncookingThreadVisitor : public ThreadVisitor {
+ public:
+ void VisitThread(ThreadLocalTop* top) {
+ StackFrame::UncookFramesForThread(top);
+ }
+};
+
+static void IterateAllThreads(ThreadVisitor* visitor) {
+ Top::IterateThread(visitor);
+ ThreadManager::IterateThreads(visitor);
+}
+
// Finds all references to original and replaces them with substitution.
static void ReplaceCodeObject(Code* original, Code* substitution) {
ASSERT(!Heap::InNewSpace(substitution));
// Iterate over all roots. Stack frames may have pointer into original code,
// so temporary replace the pointers with offset numbers
// in prologue/epilogue.
- ThreadManager::MarkCompactPrologue(true);
- Heap::IterateStrongRoots(&visitor, VISIT_ALL);
- ThreadManager::MarkCompactEpilogue(true);
+ {
+ FrameCookingThreadVisitor cooking_visitor;
+ IterateAllThreads(&cooking_visitor);
+
+ Heap::IterateStrongRoots(&visitor, VISIT_ALL);
+
+ FrameUncookingThreadVisitor uncooking_visitor;
+ IterateAllThreads(&uncooking_visitor);
+ }
// Now iterate over all pointers of all objects, including code_target
// implicit pointers.
}
+void Top::IterateThread(ThreadVisitor* v) {
+ v->VisitThread(&thread_local_);
+}
+
+
+void Top::IterateThread(ThreadVisitor* v, char* t) {
+ ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(t);
+ v->VisitThread(thread);
+}
+
+
void Top::Iterate(ObjectVisitor* v, ThreadLocalTop* thread) {
v->VisitPointer(&(thread->pending_exception_));
v->VisitPointer(&(thread->pending_message_obj_));
// Top has static variables used for JavaScript execution.
class SaveContext; // Forward declaration.
+class ThreadVisitor; // Defined in v8threads.h
class ThreadLocalTop BASE_EMBEDDED {
public:
static void Iterate(ObjectVisitor* v);
static void Iterate(ObjectVisitor* v, ThreadLocalTop* t);
static char* Iterate(ObjectVisitor* v, char* t);
+ static void IterateThread(ThreadVisitor* v);
+ static void IterateThread(ThreadVisitor* v, char* t);
// Returns the global object of the current context. It could be
// a builtin object, or a js global object.
}
+void ThreadManager::IterateThreads(ThreadVisitor* v) {
+ for (ThreadState* state = ThreadState::FirstInUse();
+ state != NULL;
+ state = state->Next()) {
+ char* data = state->data();
+ data += HandleScopeImplementer::ArchiveSpacePerThread();
+ Top::IterateThread(v, data);
+ }
+}
+
+
void ThreadManager::MarkCompactPrologue(bool is_compacting) {
for (ThreadState* state = ThreadState::FirstInUse();
state != NULL;
};
+// Defined in top.h
+class ThreadLocalTop;
+
+
+class ThreadVisitor {
+ public:
+ // ThreadLocalTop may be only available during this call.
+ virtual void VisitThread(ThreadLocalTop* top) = 0;
+
+ protected:
+ virtual ~ThreadVisitor() {}
+};
+
+
class ThreadManager : public AllStatic {
public:
static void Lock();
static bool IsArchived();
static void Iterate(ObjectVisitor* v);
+ static void IterateThreads(ThreadVisitor* v);
static void MarkCompactPrologue(bool is_compacting);
static void MarkCompactEpilogue(bool is_compacting);
static bool IsLockedByCurrentThread() { return mutex_owner_.IsSelf(); }