Bug 168842 - Introduce a VM Traps mechanism and refactor Watchdog to use it.
Summary: Introduce a VM Traps mechanism and refactor Watchdog to use it.
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: JavaScriptCore (show other bugs)
Version: WebKit Local Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Mark Lam
URL:
Keywords: InRadar
Depends on:
Blocks: 168920
  Show dependency treegraph
 
Reported: 2017-02-24 13:44 PST by Mark Lam
Modified: 2017-02-27 17:22 PST (History)
8 users (show)

See Also:


Attachments
proposed patch. (51.94 KB, patch)
2017-02-27 11:51 PST, Mark Lam
buildbot: commit-queue-
Details | Formatted Diff | Diff
Archive of layout-test-results from ews114 for mac-elcapitan (1.81 MB, application/zip)
2017-02-27 13:42 PST, Build Bot
no flags Details
proposed patch 2 (improved). (55.49 KB, patch)
2017-02-27 13:51 PST, Mark Lam
fpizlo: review+
Details | Formatted Diff | Diff
patch for landing. (65.00 KB, patch)
2017-02-27 16:33 PST, Mark Lam
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Mark Lam 2017-02-24 13:44:45 PST
This introduces the ability to fire asynchronous traps on the JS thread.  For now, we'll only be using this for the Watchdog mechanism, and asynchronous termination.  Later on, we can use this to add support for debugger breaks.
Comment 1 Mark Lam 2017-02-24 13:55:32 PST
Such a trapping mechanism requires polling of some flag from LLInt and baseline JITted code (assuming we don't want to implement something more exotic like an invalidation point for the baseline JIT).  We can implement this polling in 2 ways:

1. Add a new polling check into the bytecode stream.

   This is how the pre-existing Watchdog code work.

2. Overload stack checking (at the start of functions) and the JIT counter check (at loop hints) as a trigger for trap checks.

   This comes at a price of added complexity, but would ensure no loss of performance at the LLInt and baseline JIT tiers.

I did a jsc only benchmark run comparing a vm without op_watchdog vs a vm with op_watchdog emitted minus a hack to make the DFG and FTL layers emit no code for op_watchdog.  The DFG and FTL hack is necessary because our plan is to handle the trap check at the DFG and FTL tiers using invalidation points.  This configuration simulates what we would get in the final implementation of (1) above.

With that, I saw that performance was neutral.  Based on this, I will go with implementation (1) to keep things simple.  We can revisit changing to using (2) later if we end up observing a performance difference due to the extra polling of (1).
Comment 2 Radar WebKit Bug Importer 2017-02-24 13:56:23 PST
<rdar://problem/30703107>
Comment 3 Mark Lam 2017-02-27 11:51:33 PST
Created attachment 302859 [details]
proposed patch.

Let's get some EWS testing.
Comment 4 WebKit Commit Bot 2017-02-27 11:54:29 PST
Attachment 302859 [details] did not pass style-queue:


ERROR: Source/JavaScriptCore/dfg/DFGNodeType.h:394:  Weird number of spaces at line-start.  Are you using a 4-space indent?  [whitespace/indent] [3]
Total errors found: 1 in 36 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 5 Build Bot 2017-02-27 13:42:01 PST
Comment on attachment 302859 [details]
proposed patch.

Attachment 302859 [details] did not pass mac-debug-ews (mac):
Output: http://webkit-queues.webkit.org/results/3204222

New failing tests:
fast/dom/timer-throttling-hidden-page.html
Comment 6 Build Bot 2017-02-27 13:42:05 PST
Created attachment 302867 [details]
Archive of layout-test-results from ews114 for mac-elcapitan

The attached test failures were seen while running run-webkit-tests on the mac-debug-ews.
Bot: ews114  Port: mac-elcapitan  Platform: Mac OS X 10.11.6
Comment 7 Mark Lam 2017-02-27 13:51:01 PST
Created attachment 302869 [details]
proposed patch 2 (improved).
Comment 8 WebKit Commit Bot 2017-02-27 13:53:26 PST
Attachment 302869 [details] did not pass style-queue:


ERROR: Source/JavaScriptCore/dfg/DFGNodeType.h:394:  Weird number of spaces at line-start.  Are you using a 4-space indent?  [whitespace/indent] [3]
Total errors found: 1 in 37 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 9 Filip Pizlo 2017-02-27 15:03:18 PST
Comment on attachment 302869 [details]
proposed patch 2 (improved).

View in context: https://bugs.webkit.org/attachment.cgi?id=302869&action=review

> Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp:5554
> -        ASSERT(m_jit.vm()->watchdog());
> +    case CheckTraps: {
>          GPRTemporary unused(this);
>          GPRReg unusedGPR = unused.gpr();
>          
> -        JITCompiler::Jump timerDidFire = m_jit.branchTest8(JITCompiler::NonZero,
> -            JITCompiler::AbsoluteAddress(m_jit.vm()->watchdog()->timerDidFireAddress()));
> +        JITCompiler::Jump needTrapHandling = m_jit.branchTest8(JITCompiler::NonZero,
> +            JITCompiler::AbsoluteAddress(m_jit.vm()->needTrapHandlingAddress()));
>          
> -        addSlowPathGenerator(slowPathCall(timerDidFire, this, operationHandleWatchdogTimer, unusedGPR));
> +        addSlowPathGenerator(slowPathCall(needTrapHandling, this, operationHandleTraps, unusedGPR));
>          break;

Make common with 64-bit code.

Create a SpeculativeJIT::compileCheckTraps(Node*) and put it in SpeculativeJIT.cpp, and then call it here.

> Source/JavaScriptCore/runtime/VM.h:723
> +    class Traps {
> +    public:
> +        enum EventType {
> +            // Sorted in servicing priority order from highest to lowest.
> +            NeedTermination,
> +            NeedWatchdogCheck,
> +            NumberOfEventTypes, // This entry must be last in this list.
> +            Invalid
> +        };
> +
> +        bool needTrapHandling() { return m_needTrapHandling; }
> +        void* needTrapHandlingAddress() { return &m_needTrapHandling; }
> +
> +        JS_EXPORT_PRIVATE void fireTrap(EventType);
> +
> +        bool takeTrap(EventType);
> +        EventType takeTopPriorityTrap();
> +
> +    private:
> +        VM& vm() const;
> +
> +        bool hasTrapForEvent(Locker<Lock>&, EventType eventType)
> +        {
> +            ASSERT(eventType < NumberOfEventTypes);
> +            return (m_trapsBitField & (1 << eventType));
> +        }
> +        void setTrapForEvent(Locker<Lock>&, EventType eventType)
> +        {
> +            ASSERT(eventType < NumberOfEventTypes);
> +            m_trapsBitField |= (1 << eventType);
> +        }
> +        void clearTrapForEvent(Locker<Lock>&, EventType eventType)
> +        {
> +            ASSERT(eventType < NumberOfEventTypes);
> +            m_trapsBitField &= ~(1 << eventType);
> +        }
> +
> +        Lock m_lock;
> +        union {
> +            uint8_t m_needTrapHandling { false };
> +            uint8_t m_trapsBitField;
> +        };
> +
> +        friend class LLIntOffsetsExtractor;
> +    };

Make this not nested in VM.  Put it in a separate header/cpp file (even though you will include the header in VM.h)

> Source/JavaScriptCore/runtime/Watchdog.cpp:160
> +    // We need to ensure that the Watchdog outlives the timer.
> +    // The timer callback lambda below will deref later to match this ref.
> +    // For the same reason, the timer may also outlive the VM that the Watchdog operates on.
> +    // So, we always need to null check m_vm before using it. The VM will notify the Watchdog
> +    // via willDestroyVM() before it goes away.
> +    this->ref();

Say something like this instead:

RefPtr<Watchdog> protectedThis = this;

> Source/JavaScriptCore/runtime/Watchdog.cpp:163
>      m_timerQueue->dispatchAfter(std::chrono::nanoseconds(timeLimit), [this] {

Change [this] to [this, protectedThis]

Or even better:

[this, RefPtr<WatchDog> protectedThis = this]

> Source/JavaScriptCore/runtime/Watchdog.cpp:171
>          deref();

Don't need this
Comment 10 Mark Lam 2017-02-27 16:33:18 PST
Created attachment 302889 [details]
patch for landing.

Thanks for the review.  I've applied the requested changes.
Comment 11 WebKit Commit Bot 2017-02-27 16:36:50 PST
Attachment 302889 [details] did not pass style-queue:


ERROR: Source/JavaScriptCore/dfg/DFGNodeType.h:394:  Weird number of spaces at line-start.  Are you using a 4-space indent?  [whitespace/indent] [3]
Total errors found: 1 in 43 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 12 WebKit Commit Bot 2017-02-27 17:22:46 PST
Comment on attachment 302889 [details]
patch for landing.

Clearing flags on attachment: 302889

Committed r213107: <http://trac.webkit.org/changeset/213107>
Comment 13 WebKit Commit Bot 2017-02-27 17:22:51 PST
All reviewed patches have been landed.  Closing bug.