LinkBuffer::CodeRef LinkBuffer::finalizeCodeWithDisassembly(const char* format, ...) { CodeRef result = finalizeCodeWithoutDisassembly(); if (m_alreadyDisassembled) return result; StringPrintStream out; out.printf("Generated JIT code for "); va_list argList; va_start(argList, format); out.vprintf(format, argList); va_end(argList); out.printf(":\n"); out.printf(" Code at [%p, %p):\n", result.code().executableAddress(), static_cast<char*>(result.code().executableAddress()) + result.size()); CString header = out.toCString(); if (Options::asyncDisassembly()) { disassembleAsynchronously(header, result, m_size, " "); return result; } dataLog(header); disassemble(result.code(), m_size, " ", WTF::dataFile()); return result; }
LinkBuffer::CodeRef LinkBuffer::finalizeCodeWithDisassembly(const char* format, ...) { ASSERT(Options::showDisassembly() || Options::showDFGDisassembly()); CodeRef result = finalizeCodeWithoutDisassembly(); dataLogF("Generated JIT code for "); va_list argList; va_start(argList, format); WTF::dataLogFV(format, argList); va_end(argList); dataLogF(":\n"); dataLogF(" Code at [%p, %p):\n", result.code().executableAddress(), static_cast<char*>(result.code().executableAddress()) + result.size()); disassemble(result.code(), m_size, " ", WTF::dataFile()); return result; }
void Timers::deleteTimer (TimerKey const mt_nonnull timer_key) { Timer * const timer = timer_key; if (timer->del_sbn) { CodeRef const code_ref = timer->timer_cb.getWeakCodeRef(); if (!code_ref) { // doDeleteTimer() will be called by subscriberDeletionCallback, // which is likely just about to be called. return; } code_ref->removeDeletionCallback (timer->del_sbn); } doDeleteTimer (timer); }
LinkBuffer::CodeRef LinkBuffer::finalizeCodeWithDisassembly(const char* format, ...) { CodeRef result = finalizeCodeWithoutDisassembly(); #if ENABLE(DISASSEMBLER) dataLogF("Generated JIT code for "); va_list argList; va_start(argList, format); WTF::dataLogFV(format, argList); va_end(argList); dataLogF(":\n"); dataLogF(" Code at [%p, %p):\n", result.code().executableAddress(), static_cast<char*>(result.code().executableAddress()) + result.size()); disassemble(result.code(), m_size, " ", WTF::dataFile()); #else UNUSED_PARAM(format); #endif // ENABLE(DISASSEMBLER) return result; }
void Timers::processTimers () { Time const cur_time = getTimeMicroseconds (); mutex.lock (); TimerChain *chain = expiration_tree_leftmost; if (chain == NULL) { mutex.unlock (); return; } while (!chain->timer_list.isEmpty () && chain->nearest_time <= cur_time) { Time const cur_nearest_time = chain->nearest_time; logD (timers, _func, "cur_nearest_time: ", cur_nearest_time, ", cur_time: ", cur_time); Timer * const timer = chain->timer_list.getFirst (); assert (timer->active); chain->timer_list.remove (timer); bool delete_timer = false; if (timer->periodical) { timer->due_time += chain->interval_microseconds; if (timer->due_time < chain->interval_microseconds) { logW_ (_func, "Expiration time overflow"); timer->due_time = (Time) -1; } chain->timer_list.append (timer); } else { timer->active = false; if (timer->delete_after_tick) { if (timer->del_sbn) { // TODO We create CodeRef twice: here and in call_unlocks_mutex_(). // Should do this only once for efficiency. CodeRef const code_ref = timer->timer_cb.getWeakCodeRef(); // If 'code_ref' is null, then doDeleteTimer() will be called // by subscriberDeletionCallback(), which is likely just about // to be called. if (code_ref) { code_ref->removeDeletionCallback (timer->del_sbn); delete_timer = true; } } else { delete_timer = true; } } } bool delete_chain; if (chain->timer_list.isEmpty ()) { expiration_tree.remove (chain); expiration_tree_leftmost = expiration_tree.getLeftmost(); interval_tree.remove (chain); delete_chain = true; } else { if (cur_nearest_time != chain->timer_list.getFirst ()->due_time) { expiration_tree.remove (chain); chain->nearest_time = chain->timer_list.getFirst ()->due_time; expiration_tree.add (chain); expiration_tree_leftmost = expiration_tree.getLeftmost(); } delete_chain = false; } timer->timer_cb.call_unlocks_mutex_ (mutex); // 'timer' might have been deleted by the user and should not be used // directly anymore. // // We can't delete the timer ourselves here for a similar reason: its // lifetime is controlled by the user, so we can't tie it to callback's // weak_obj. if (delete_timer) delete timer; if (delete_chain) delete chain; mutex.lock (); // 'chain' might have been deleted due to user's actions in 'timer_cb' callback. chain = expiration_tree_leftmost; if (chain == NULL) { mutex.unlock (); return; } } mutex.unlock (); }