WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
165834
WebAssembly: WasmB3IRGenerator should throw exceptions instead of crash
https://bugs.webkit.org/show_bug.cgi?id=165834
Summary
WebAssembly: WasmB3IRGenerator should throw exceptions instead of crash
Saam Barati
Reported
2016-12-13 17:37:41 PST
Should be an easy fix. My plan is to introduce a helper to WasmB3IRGenerator that just jumps to a particular location to throw an exception with some enum as an argument to the function call. The function call can switch on the enum to provide a nice error message.
Attachments
WIP
(9.71 KB, patch)
2016-12-14 12:27 PST
,
Saam Barati
no flags
Details
Formatted Diff
Diff
WIP RFC
(21.01 KB, patch)
2016-12-14 13:15 PST
,
Saam Barati
no flags
Details
Formatted Diff
Diff
patch
(38.55 KB, patch)
2016-12-15 17:41 PST
,
Saam Barati
no flags
Details
Formatted Diff
Diff
patch
(38.55 KB, patch)
2016-12-15 17:43 PST
,
Saam Barati
keith_miller
: review-
Details
Formatted Diff
Diff
patch
(43.70 KB, patch)
2016-12-15 23:29 PST
,
Saam Barati
no flags
Details
Formatted Diff
Diff
patch
(47.58 KB, patch)
2016-12-15 23:34 PST
,
Saam Barati
no flags
Details
Formatted Diff
Diff
Show Obsolete
(5)
View All
Add attachment
proposed patch, testcase, etc.
Saam Barati
Comment 1
2016-12-14 12:27:55 PST
Created
attachment 297110
[details]
WIP I just need to fill in the various exception checks now.
Saam Barati
Comment 2
2016-12-14 13:15:27 PST
Created
attachment 297118
[details]
WIP RFC
JF Bastien
Comment 3
2016-12-14 13:25:48 PST
Comment on
attachment 297118
[details]
WIP RFC View in context:
https://bugs.webkit.org/attachment.cgi?id=297118&action=review
Looks good.
> JSTests/wasm/function-tests/exceptions.js:20 > + .Function("foo", 0 /*['i32', 'i32'] => 'i32'*/)
Why not let these auto-populate in the Type section?
> JSTests/wasm/function-tests/exceptions.js:23 > + .CallIndirect(1, 0) // calling function of type ['i32'] => 'i32'
Can call indirect also take a type signature?
> JSTests/wasm/function-tests/exceptions.js:57 > + assert.throws(() => foo(1 + i, i), WebAssembly.RuntimeError, "Out of bounds call_indirect");
Check that negative also fails.
> Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp:282 > + // The thing that jumps here will move ExceptionType into the argumentGPR1 and jump here.
Can you use a named constant for that GPR so it's more obvious / can't go out of sync?
> Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp:297 > + switch (type) {
Can we just make these a static const char * array next to the enum?
> Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp:308 > + message = "Can't make a call_indirect to a null table entry";
I'd drop "can't make a " from the message: the issue is "call_indirect to a null table entry".
> Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp:311 > + message = "Tried to make a call_indirect to a signature that does not match";
Similar here: "call_indirect signature mismatch".
> Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp:859 > + // FIXME: is this even possible?
Do we need to zero-fill missing arguments, and drop extra ones?
Saam Barati
Comment 4
2016-12-15 14:24:38 PST
Comment on
attachment 297118
[details]
WIP RFC View in context:
https://bugs.webkit.org/attachment.cgi?id=297118&action=review
>> JSTests/wasm/function-tests/exceptions.js:23 >> + .CallIndirect(1, 0) // calling function of type ['i32'] => 'i32' > > Can call indirect also take a type signature?
We could make it do that but lets make that a separate patch
>> Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp:282 >> + // The thing that jumps here will move ExceptionType into the argumentGPR1 and jump here. > > Can you use a named constant for that GPR so it's more obvious / can't go out of sync?
That constant would only be used in one place. I don't think it's worth it.
>> Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp:297 >> + switch (type) { > > Can we just make these a static const char * array next to the enum?
I'm not a big fan of this. I could just make all exception types a macro?
>> Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp:308 >> + message = "Can't make a call_indirect to a null table entry"; > > I'd drop "can't make a " from the message: the issue is "call_indirect to a null table entry".
sounds good.
>> Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp:311 >> + message = "Tried to make a call_indirect to a signature that does not match"; > > Similar here: "call_indirect signature mismatch".
sounds good
>> Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp:859 >> + // FIXME: is this even possible? > > Do we need to zero-fill missing arguments, and drop extra ones?
No idea. I'll leave this for another patch.
Keith Miller
Comment 5
2016-12-15 14:35:39 PST
Comment on
attachment 297118
[details]
WIP RFC View in context:
https://bugs.webkit.org/attachment.cgi?id=297118&action=review
> Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp:747 > + check->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
Doesn't this copy the entire B3IRGenerator for each exception generator? Maybe this should just capture the address of m_exceptionHandler?
>>> Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp:859 >>> + // FIXME: is this even possible? >> >> Do we need to zero-fill missing arguments, and drop extra ones? > > No idea. I'll leave this for another patch.
I don't think this is possible anymore.
> Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp:923 > + return jsEntrypoint->codeRef();
Aren't you required to keep the byproducts alive along with the code ref?
Saam Barati
Comment 6
2016-12-15 17:41:57 PST
Created
attachment 297265
[details]
patch
Saam Barati
Comment 7
2016-12-15 17:43:46 PST
Created
attachment 297266
[details]
patch
WebKit Commit Bot
Comment 8
2016-12-15 17:44:52 PST
Attachment 297266
[details]
did not pass style-queue: ERROR: Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp:328: Non-label code inside switch statements should be indented. [whitespace/indent] [4] Total errors found: 1 in 12 files If any of these errors are false positives, please file a bug against check-webkit-style.
Keith Miller
Comment 9
2016-12-15 18:31:38 PST
Comment on
attachment 297266
[details]
patch View in context:
https://bugs.webkit.org/attachment.cgi?id=297266&action=review
It seems like emitExceptionHandler should only be called if it's actually needed. I think I would add a member, m_needsExceptionHandler that is set in emitExceptionCheck.
> Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp:296 > + jit.addLinkTask([=] (LinkBuffer& linkBuffer) {
It's a little weird that you capture the entire B3IRGenerator here.
Saam Barati
Comment 10
2016-12-15 18:37:37 PST
Comment on
attachment 297266
[details]
patch View in context:
https://bugs.webkit.org/attachment.cgi?id=297266&action=review
>> Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp:296 >> + jit.addLinkTask([=] (LinkBuffer& linkBuffer) { > > It's a little weird that you capture the entire B3IRGenerator here.
What do you propose instead?
Saam Barati
Comment 11
2016-12-15 18:38:15 PST
(In reply to
comment #9
)
> Comment on
attachment 297266
[details]
> patch > > View in context: >
https://bugs.webkit.org/attachment.cgi?id=297266&action=review
> > It seems like emitExceptionHandler should only be called if it's actually > needed. I think I would add a member, m_needsExceptionHandler that is set in > emitExceptionCheck.
Ok, sounds good.
Keith Miller
Comment 12
2016-12-15 18:40:21 PST
Comment on
attachment 297266
[details]
patch View in context:
https://bugs.webkit.org/attachment.cgi?id=297266&action=review
>>> Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp:296 >>> + jit.addLinkTask([=] (LinkBuffer& linkBuffer) { >> >> It's a little weird that you capture the entire B3IRGenerator here. > > What do you propose instead?
I would just capture m_exceptionHandler.
Oliver Hunt
Comment 13
2016-12-15 23:20:05 PST
Could you explain in more detail what your goal is here? My principle concern is that it seems like you're trying to continue executing despite having generated incorrect code. The correct course of action is to terminate, so there needs to be a very compelling reason not to. If it's for debugging or similar, i'd rather you replace "call a function with an enum" with jit.move($enumValue, regT0) hit.breakpoint() or similar.
Saam Barati
Comment 14
2016-12-15 23:28:34 PST
(In reply to
comment #13
)
> Could you explain in more detail what your goal is here? My principle > concern is that it seems like you're trying to continue executing despite > having generated incorrect code. > > The correct course of action is to terminate, so there needs to be a very > compelling reason not to. > > If it's for debugging or similar, i'd rather you replace "call a function > with an enum" with > > jit.move($enumValue, regT0) > hit.breakpoint() > > or similar.
This is not "trying to continue executing despite having generated incorrect code". There are operations in Wasm that *are* supposed to throw real JS exceptions. For example: - division by zero - out of bounds memory access - Trying to call an "imported" function with a signature mismatch. So these are things that need to be validated at runtime because they can't be validated at compile time. Therefore, we must validate such things and throw exceptions if the validation fails.
Saam Barati
Comment 15
2016-12-15 23:29:40 PST
Created
attachment 297302
[details]
patch All Wasm functions now share the exact same exception thrower thunk. This should reduce code size by at least 20 bytes per function.
Saam Barati
Comment 16
2016-12-15 23:31:28 PST
(In reply to
comment #14
)
> (In reply to
comment #13
) > > Could you explain in more detail what your goal is here? My principle > > concern is that it seems like you're trying to continue executing despite > > having generated incorrect code. > > > > The correct course of action is to terminate, so there needs to be a very > > compelling reason not to. > > > > If it's for debugging or similar, i'd rather you replace "call a function > > with an enum" with > > > > jit.move($enumValue, regT0) > > hit.breakpoint() > > > > or similar. > > This is not "trying to continue executing despite having generated incorrect > code". > There are operations in Wasm that *are* supposed to throw real JS exceptions. > For example: > - division by zero > - out of bounds memory access > - Trying to call an "imported" function with a signature mismatch. > > So these are things that need to be validated at runtime because they can't > be validated at compile time. Therefore, we must validate such things and > throw exceptions if the validation fails.
To elaborate a bit, when Keith began to implement Wasm, he didn't write the infrastructure needed to throw exceptions. I recently made our unwinder Wasm-aware, so we can now throw exceptions from (and through) Wasm code. Keith originally added breakpoints() for places that needed to throw exceptions. This patch just fills in some of the various breakpoints() with jumps to the thing that throws an exception.
Saam Barati
Comment 17
2016-12-15 23:34:55 PST
Created
attachment 297303
[details]
patch rebased
WebKit Commit Bot
Comment 18
2016-12-15 23:37:01 PST
Attachment 297303
[details]
did not pass style-queue: ERROR: Source/JavaScriptCore/wasm/WasmExceptionType.h:53: Non-label code inside switch statements should be indented. [whitespace/indent] [4] Total errors found: 1 in 15 files If any of these errors are false positives, please file a bug against check-webkit-style.
JF Bastien
Comment 19
2016-12-16 10:14:26 PST
Comment on
attachment 297303
[details]
patch Looks good.
Keith Miller
Comment 20
2016-12-16 10:53:42 PST
Comment on
attachment 297303
[details]
patch r=me.
WebKit Commit Bot
Comment 21
2016-12-16 11:24:44 PST
Comment on
attachment 297303
[details]
patch Clearing flags on attachment: 297303 Committed
r209928
: <
http://trac.webkit.org/changeset/209928
>
WebKit Commit Bot
Comment 22
2016-12-16 11:24:49 PST
All reviewed patches have been landed. Closing bug.
Oliver Hunt
Comment 23
2016-12-16 11:34:11 PST
> To elaborate a bit, when Keith began to implement Wasm, he didn't write the > infrastructure needed to throw exceptions. I recently made our unwinder > Wasm-aware, so we can now throw exceptions from (and through) Wasm code. > Keith originally added breakpoints() for places that needed to throw > exceptions. This patch just fills in some of the various breakpoints() with > jumps to the thing that throws an exception.
Ok, i understand now -- it was not clear to me that the existing breakpoints were (essentially) for unimplemented checks, so i interpreted the breakpoints as being the standard RELEASE_ASSERT of the jit work. That said i wonder if we could do something to make the existing jit asserts plant info into the crash trace (write error code to register or similar)
Saam Barati
Comment 24
2016-12-16 11:38:38 PST
(In reply to
comment #23
)
> > To elaborate a bit, when Keith began to implement Wasm, he didn't write the > > infrastructure needed to throw exceptions. I recently made our unwinder > > Wasm-aware, so we can now throw exceptions from (and through) Wasm code. > > Keith originally added breakpoints() for places that needed to throw > > exceptions. This patch just fills in some of the various breakpoints() with > > jumps to the thing that throws an exception. > > Ok, i understand now -- it was not clear to me that the existing breakpoints > were (essentially) for unimplemented checks, so i interpreted the > breakpoints as being the standard RELEASE_ASSERT of the jit work. > > That said i wonder if we could do something to make the existing jit asserts > plant info into the crash trace (write error code to register or similar)
Yeah for things that are really crashes, we should use the JIT assert mechanism that's already in place instead of the breakpoint().
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug