RESOLVED FIXED Bug 181599
PoisonedWriteBarrier
https://bugs.webkit.org/show_bug.cgi?id=181599
Summary PoisonedWriteBarrier
JF Bastien
Reported 2018-01-12 10:17:55 PST
Allow poisoning of WriteBarrier objects, and use this in a place where it should be perf-neutral first. If it indeed is perf-neutral, start using it in more risky places!
Attachments
patch (50.40 KB, patch)
2018-01-12 10:32 PST, JF Bastien
no flags
patch (52.11 KB, patch)
2018-01-12 11:24 PST, JF Bastien
mark.lam: review-
js benchmarks (86.26 KB, text/plain)
2018-01-12 13:36 PST, JF Bastien
no flags
patch (52.61 KB, patch)
2018-01-12 14:31 PST, JF Bastien
mark.lam: review+
patch (52.50 KB, patch)
2018-01-12 15:09 PST, JF Bastien
no flags
Radar WebKit Bug Importer
Comment 1 2018-01-12 10:20:42 PST
JF Bastien
Comment 2 2018-01-12 10:32:26 PST
EWS Watchlist
Comment 3 2018-01-12 10:33:54 PST
Attachment 331214 [details] did not pass style-queue: ERROR: Source/JavaScriptCore/runtime/WriteBarrier.h:33: Alphabetical sorting problem. [build/include_order] [4] Total errors found: 1 in 27 files If any of these errors are false positives, please file a bug against check-webkit-style.
Mark Lam
Comment 4 2018-01-12 10:52:49 PST
Comment on attachment 331214 [details] patch View in context: https://bugs.webkit.org/attachment.cgi?id=331214&action=review Please make sure the EWS bots are happy. I'll wait for you to rebase before continuing the review. It'll make it easier to do the review. Thanks. > Source/JavaScriptCore/ChangeLog:12 > + using it in more risky places! I suggest rephrasing /in more risky places!/in more potentially performance sensitive places./ > Source/JavaScriptCore/runtime/WriteBarrier.h:34 > +#include <type_traits> Please fix ordering. > Source/WTF/wtf/Poisoned.h:92 > +template<typename KeyType, KeyType Key, typename T, typename = std::enable_if_t<std::is_pointer<T>::value>> Why uppercase Key? Isn't our convention to use lowercase for variables / arguments, and uppercase for Types? I suggest reverting this here and below as well.
JF Bastien
Comment 5 2018-01-12 11:24:27 PST
Created attachment 331219 [details] patch Address comments. This should also fix the build (still going on my laptop...): code was indirectly doing WriteBarrier<>.set() on JSGlobalObject with only a forward declaration, so it didn't know that JSGlobalObject derives from JSCell. This is now a compilation error because I static_cast to JSCell*, instead of reinterpret_cast. This particular case was fine because the object layout didn't change, but in general static_cast might require a base adjustment. It's also good to check that there indeed is an inheritance hierarchy! I fixed the issue by moving Structure.h's uses of .set() to its Inlines.h file.
JF Bastien
Comment 6 2018-01-12 13:36:00 PST
Created attachment 331232 [details] js benchmarks In addition to WasmBench which I ran earlier, I also ran our JS benchmarks to confirm that the WriteBarrier changes had no effect. They're indeed totally neutral (results attached). WasmBench results (with 10 iterations) where: Compile score (as arithmetic mean of each compile iteration) 90.30 +- 1.45 ms Throughput score (as arithmetic mean of each throughput iteration) 3359.70 +- 22.63 ms Total score (as arithmetic mean of each score iteration) 550.76 +- 5.15 ms Compile score (as arithmetic mean of each compile iteration) 90.62 +- 1.23 ms Throughput score (as arithmetic mean of each throughput iteration) 3387.59 +- 16.70 ms Total score (as arithmetic mean of each score iteration) 554.03 +- 3.60 ms
Mark Lam
Comment 7 2018-01-12 13:36:18 PST
Comment on attachment 331219 [details] patch View in context: https://bugs.webkit.org/attachment.cgi?id=331219&action=review I think you have a bug. Please fix. > Source/JavaScriptCore/runtime/WriteBarrier.h:113 > + validateCell<T>(Traits::unwrap(cell)); > + return Traits::unwrap(cell); I suggest pre-caching the unwrapped pointer: T* resultCell = Traits::unwrap(cell); validateCell<T>(resultCell); return resultCell; > Source/JavaScriptCore/runtime/WriteBarrier.h:121 > + validateCell(Traits::unwrap(cell)); > + return Traits::unwrap(cell); Ditto. precache? > Source/JavaScriptCore/wasm/js/WasmToJS.cpp:482 > + jit.move(CCallHelpers::TrustedImm64(JSWebAssemblyInstance::PoisonedBarrier<WebAssemblyToJSCallee>::poison), importJSCellGPRReg); It is wrong to assume that importJSCellGPRReg (i.e. GPRInfo::regT0) !== GPRInfo::argumentGPR0. In fact, on ARM64 (and most other architectures), they are the same. You're just lucky that they aren't the same on x86_64 here. Please fix.
JF Bastien
Comment 8 2018-01-12 14:31:49 PST
Created attachment 331235 [details] patch > > Source/JavaScriptCore/runtime/WriteBarrier.h:113 > > + validateCell<T>(Traits::unwrap(cell)); > > + return Traits::unwrap(cell); > > I suggest pre-caching the unwrapped pointer: > T* resultCell = Traits::unwrap(cell); > validateCell<T>(resultCell); > return resultCell; > > > Source/JavaScriptCore/runtime/WriteBarrier.h:121 > > + validateCell(Traits::unwrap(cell)); > > + return Traits::unwrap(cell); > > Ditto. precache? Done x 2. > > Source/JavaScriptCore/wasm/js/WasmToJS.cpp:482 > > + jit.move(CCallHelpers::TrustedImm64(JSWebAssemblyInstance::PoisonedBarrier<WebAssemblyToJSCallee>::poison), importJSCellGPRReg); > > It is wrong to assume that importJSCellGPRReg (i.e. GPRInfo::regT0) !== > GPRInfo::argumentGPR0. In fact, on ARM64 (and most other architectures), > they are the same. You're just lucky that they aren't the same on x86_64 > here. Please fix. Nice, good catch! I hadn't looked at all the ISAs. Fixed now.
Mark Lam
Comment 9 2018-01-12 14:51:37 PST
Comment on attachment 331235 [details] patch View in context: https://bugs.webkit.org/attachment.cgi?id=331235&action=review r=me with suggestion. Please make sure the EWS bots are green before landing. Thanks. > Source/JavaScriptCore/wasm/js/WasmToJS.cpp:56 > -static void materializeImportJSCell(JIT& jit, unsigned importIndex, GPRReg result) > +static void materializeImportJSCell(JIT& jit, unsigned importIndex, GPRReg scratch, GPRReg result) > { > // We're calling out of the current WebAssembly.Instance. That Instance has a list of all its import functions. > - jit.loadWasmContextInstance(result); > - jit.loadPtr(JIT::Address(result, Instance::offsetOfImportFunction(importIndex)), result); > + jit.loadWasmContextInstance(scratch); > + jit.loadPtr(JIT::Address(scratch, Instance::offsetOfImportFunction(importIndex)), scratch); > + jit.move(CCallHelpers::TrustedImm64(JSWebAssemblyInstance::PoisonedBarrier<JSObject>::poison), result); > + jit.xor64(scratch, result); > } In both clients that calls materializeImportJSCell, they already loaded JSWebAssemblyInstance::PoisonedBarrier<JSObject>::poison into scratch. Can we simplify this as: static void materializeImportJSCell(JIT& jit, unsigned importIndex, GPRReg poison, GPRReg result) { // We're calling out of the current WebAssembly.Instance. That Instance has a list of all its import functions. jit.loadWasmContextInstance(result); jit.loadPtr(JIT::Address(result, Instance::offsetOfImportFunction(importIndex)), result); jit.xor64(poison, result); } > Source/JavaScriptCore/wasm/js/WasmToJS.cpp:295 > + jit.move(CCallHelpers::TrustedImm64(JSWebAssemblyInstance::PoisonedBarrier<WebAssemblyToJSCallee>::poison), GPRInfo::argumentGPR1); Jus move the poison into argumentGPR2 as a poisonScratch so that you can skip doing it in materializeImportJSCell below. > Source/JavaScriptCore/wasm/js/WasmToJS.cpp:299 > + materializeImportJSCell(jit, importIndex, GPRInfo::argumentGPR2, GPRInfo::argumentGPR1); Do you need to clear the poison after this as well before the call?
JF Bastien
Comment 10 2018-01-12 15:09:09 PST
Created attachment 331239 [details] patch Implement suggestions.
WebKit Commit Bot
Comment 11 2018-01-12 15:48:03 PST
Comment on attachment 331239 [details] patch Clearing flags on attachment: 331239 Committed r226920: <https://trac.webkit.org/changeset/226920>
WebKit Commit Bot
Comment 12 2018-01-12 15:48:05 PST
All reviewed patches have been landed. Closing bug.
Note You need to log in before you can comment on or make changes to this bug.