Changeset 208238 in webkit
- Timestamp:
- Nov 1, 2016 1:40:40 PM (8 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 4 added
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/CMakeLists.txt
r208209 r208238 880 880 wasm/WasmB3IRGenerator.cpp 881 881 wasm/WasmCallingConvention.cpp 882 wasm/WasmFormat.cpp 882 883 wasm/WasmMemory.cpp 883 884 wasm/WasmModuleParser.cpp 884 885 wasm/WasmPlan.cpp 886 wasm/WasmValidate.cpp 885 887 886 888 wasm/js/JSWebAssemblyCompileError.cpp -
trunk/Source/JavaScriptCore/ChangeLog
r208235 r208238 1 2016-11-01 Keith Miller <keith_miller@apple.com> 2 3 Add a WASM function validator. 4 https://bugs.webkit.org/show_bug.cgi?id=161707 5 6 Reviewed by Saam Barati. 7 8 This is a new template specialization of the Wasm FunctionParser class. Instead of having 9 the FunctionParser track what B3 values each stack entry refers to the validator has each 10 entry refer to the type of the stack entry. Additionally, the control stack tracks what type 11 of block the object is and what the result type of the block is. The validation functions 12 for unary, binary, and memory operations are autogenerated by the 13 generateWasmValidateInlinesHeader.py script. 14 15 There are still a couple issue with validating that will be addressed in follow-up patches. 16 1) We need to handle result types from basic blocks. https://bugs.webkit.org/show_bug.cgi?id=164100 17 2) We need to handle popping things from stacks when they don't exist. https://bugs.webkit.org/show_bug.cgi?id=164275 18 19 * CMakeLists.txt: 20 * DerivedSources.make: 21 * JavaScriptCore.xcodeproj/project.pbxproj: 22 * testWasm.cpp: 23 (runWasmTests): 24 * wasm/WasmB3IRGenerator.cpp: 25 * wasm/WasmFormat.cpp: Added. 26 (JSC::Wasm::toString): 27 * wasm/WasmFormat.h: 28 * wasm/WasmFunctionParser.h: 29 (JSC::Wasm::FunctionParser<Context>::parseExpression): 30 (JSC::Wasm::FunctionParser<Context>::parseUnreachableExpression): 31 * wasm/WasmPlan.cpp: 32 (JSC::Wasm::Plan::Plan): 33 * wasm/WasmValidate.cpp: Added. 34 (JSC::Wasm::Validate::ControlData::ControlData): 35 (JSC::Wasm::Validate::ControlData::dump): 36 (JSC::Wasm::Validate::ControlData::type): 37 (JSC::Wasm::Validate::ControlData::signature): 38 (JSC::Wasm::Validate::addConstant): 39 (JSC::Wasm::Validate::isContinuationReachable): 40 (JSC::Wasm::Validate::errorMessage): 41 (JSC::Wasm::Validate::Validate): 42 (JSC::Wasm::Validate::addArguments): 43 (JSC::Wasm::Validate::addLocal): 44 (JSC::Wasm::Validate::getLocal): 45 (JSC::Wasm::Validate::setLocal): 46 (JSC::Wasm::Validate::addBlock): 47 (JSC::Wasm::Validate::addLoop): 48 (JSC::Wasm::Validate::addIf): 49 (JSC::Wasm::Validate::addElse): 50 (JSC::Wasm::Validate::addReturn): 51 (JSC::Wasm::Validate::addBranch): 52 (JSC::Wasm::Validate::endBlock): 53 (JSC::Wasm::Validate::addCall): 54 (JSC::Wasm::Validate::unify): 55 (JSC::Wasm::Validate::dump): 56 (JSC::Wasm::validateFunction): 57 * wasm/WasmValidate.h: Added. 58 * wasm/generateWasmValidateInlinesHeader.py: Added. 59 (cppType): 60 (toCpp): 61 (unaryMacro): 62 (binaryMacro): 63 (loadMacro): 64 (storeMacro): 65 1 66 2016-11-01 Saam Barati <sbarati@apple.com> 2 67 … … 1679 1744 Async functions generate bytecode equivalent to the following, which is 1680 1745 highly dependent on the Generator implementation: 1681 1746 1682 1747 ``` 1683 1748 // Before translation: … … 1701 1766 1702 1767 There are some caveats to be addressed later: 1703 1768 1704 1769 1) the `op_to_this` is always performed, whether it's used or not, like normal generators. (https://bugs.webkit.org/show_bug.cgi?id=151586) 1705 1770 1706 1771 2) for async arrow functions, the home object is always stored on the "body" function, regardless of whether it's needed or 1707 1772 not, for the same reason as #1 (and should also be fixed as part of https://bugs.webkit.org/show_bug.cgi?id=151586) … … 1811 1876 behavior that is different than the set of cacheable put operations above. 1812 1877 Hence, it should not claim that the property put is cacheable. 1813 1878 1814 1879 2. Cacheable puts are cached on the original structure of the object before the 1815 1880 put operation. … … 2069 2134 2070 2135 Reviewed by Geoffrey Garen. 2071 2136 2072 2137 I want to introduce another HeapTimer. Prior to this change, that would have meant writing 2073 2138 exact copies of that timer's logic for each platform that has a HeapTimer (CF, GLIB, and … … 2077 2142 to add insult to injury, the USE(CF) version of HeapTimer would have to have an extra case 2078 2143 for that new subclass since it doesn't use virtual methods effectively. 2079 2144 2080 2145 This changes HeapTimer on USE(CF) to know to get its runloop from Heap and to use virtual 2081 2146 methods effectively so that it doesn't have to know about all of its subclasses. 2082 2147 2083 2148 This also moves IncrementalSweeper's code for scheduling timers into HeapTimer. This means 2084 2149 that future subclasses of HeapTimer could simply use that logic. 2085 2150 2086 2151 This keeps changes to GCActivityCallback to a minimum. It still has a lot of 2087 2152 platform-specific code and I'm not sure that this code can be trivially deduplicated since … … 2712 2777 2713 2778 Reviewed by Keith Miller. 2714 2779 2715 2780 JSC often suffers from the inline cargo cult, and Heap is a prime example. This outlines a 2716 2781 bunch of Heap methods that are either already very big, or call out-of-line methods, or call 2717 2782 very big methods, or are not called often enough for inlining to matter. 2718 2783 2719 2784 This simplifies concurrent GC work because I'm so tired of recompiling the world when I touch 2720 2785 one of these methods. 2721 2786 2722 2787 This looks to be perf-neutral. 2723 2788 … … 3089 3154 3090 3155 Reviewed by Geoffrey Garen. 3091 3156 3092 3157 We need to know if we're currently in an allocation slow path, so that code can assert that 3093 3158 it's not being used from inside a destructor that runs during a sweep. We need to know if … … 3097 3162 full collection. If we are requesting a collection, we need to know if we're requesting an 3098 3163 eden collection, a full collection, or any kind of collection. 3099 3164 3100 3165 Prior to this change, you would reason about all of these things using the HeapOperation. It 3101 3166 had the following states: NoOperation, Allocation, FullCollection, EdenCollection, and … … 3105 3170 Eden, because we just needed a variable to tell us which generation we were talking about. 3106 3171 It was all very confusing. 3107 3172 3108 3173 Where it completely breaks down is the fact that a concurrent GC has two logical threads, the 3109 3174 mutator and the collector, which can change state independently. The mutator can be … … 3115 3180 collector not running, running eden, or running full. So, this change decouples mutator state 3116 3181 from collector state and uses two separate fields with two different types. 3117 3182 3118 3183 Mutator state is described using MutatorState, which can be either MutatorState::Running, 3119 3184 MutatorState::Allocating, or MutatorState::HelpingGC. 3120 3185 3121 3186 Collector state is described using Optional<CollectionScope>. CollectionScope describes how 3122 3187 big the scope of the collection is, and it can be either CollectionScope::Eden or … … 3127 3192 collection, which those methods take to mean that they can run any kind of collection (the 3128 3193 old AnyCollection). 3129 3194 3130 3195 Another use of HeapOperation was to answer questions about whether the caller is running as 3131 3196 part of the GC or as part of the mutator. Optional<CollectionScope> does not answer this, … … 3144 3209 by checking with mayBeGCThread, which returns Optional<GCThreadType>; if engaged, then run as 3145 3210 GC, else run as GC if MutatorState is HelpingGC, else run as mutator. 3146 3211 3147 3212 This doesn't change the way that the GC behaves, but it does change how the GC represents a 3148 3213 fundamental piece of state. So, it's a big change. It should be perf-neutral (still testing). … … 3704 3769 3705 3770 Reviewed by Geoffrey Garen. 3706 3771 3707 3772 Change the JITWorklist to use AutomaticThread, so that the Baseline JIT's concurrent 3708 3773 compiler thread shuts down automatically after inactivity. 3709 3774 3710 3775 With this change, all of JSC's threads shut down automatically. If you run splay for a few 3711 3776 seconds (which fires up all threads - compiler and GC) and then go to sleep for a second, … … 3750 3815 3751 3816 Reviewed by Mark Lam. 3752 3817 3753 3818 AutomaticThread is a new feature in WTF that allows you to easily create worker threads that 3754 3819 shut down automatically. This changes DFG::Worklist to use AutomaticThread, so that its 3755 3820 threads shut down automatically, too. This has the potential to save a lot of memory. 3756 3821 3757 3822 This required some improvements to AutomaticThread: Worklist likes to be able to keep state 3758 3823 around for the whole lifetime of a thread, and so it likes knowing when threads are born and 3759 3824 when they die. I added virtual methods for that. Also, Worklist uses notifyOne() so I added 3760 3825 that, too. 3761 3826 3762 3827 This looks to be perf-neutral. 3763 3828 … … 3923 3988 3924 3989 Reviewed by Andreas Kling. 3925 3990 3926 3991 Added a sleepSeconds() function, which made it easier for me to test this change. 3927 3992 3928 3993 The WTF changes in this patch change how the JSC GC manages threads: the GC threads will now 3929 3994 shut down automatically after 1 second of inactivity. Maybe this will save some memory. … … 3953 4018 3954 4019 Reviewed by Geoffrey Garen and Saam Barati. 3955 4020 3956 4021 This adds a new kind of call inline cache for when the DFG can prove what the callee 3957 4022 executable is. In those cases, we can skip some of the things that the traditional call IC 3958 4023 would do: 3959 4024 3960 4025 - No need to check who the callee is. 3961 4026 - No need to do arity checks. 3962 4027 3963 4028 This case isn't as simple as just emitting a call instruction since the callee may not be 3964 4029 compiled at the time that the caller is compiled. So, we need lazy resolution. Also, the … … 3967 4032 CallLinkInfo has. CallLinkInfo already knows about different kinds of calls. This patch 3968 4033 teaches it about new "Direct" call types. 3969 4034 3970 4035 The direct non-tail call IC looks like this: 3971 4036 3972 4037 set up arguments 3973 4038 FastPath: 3974 4039 call _SlowPath 3975 4040 lea -FrameSize(%rbp), %rsp 3976 4041 3977 4042 SlowPath: 3978 4043 pop … … 3980 4045 check exception 3981 4046 jmp FastPath 3982 4047 3983 4048 The job of operationLinkDirectCall is to link the fast path's call entrypoint of the callee. 3984 4049 This means that in steady state, a call is just that: a call. There are no extra branches or 3985 4050 checks. 3986 4051 3987 4052 The direct tail call IC is a bit more complicated because the act of setting up arguments 3988 4053 destroys our frame, which would prevent us from being able to throw an exception if we 3989 4054 failed to compile the callee. So, direct tail call ICs look like this: 3990 4055 3991 4056 jmp _SlowPath 3992 4057 FastPath: 3993 4058 set up arguments 3994 4059 jmp 0 // patch to jump to callee 3995 4060 3996 4061 SlowPath: 3997 4062 silent spill … … 4000 4065 check exception 4001 4066 jmp FastPath 4002 4067 4003 4068 The jmp to the slow path is patched to be a fall-through jmp when we link the call. 4004 4069 4005 4070 Direct calls mean less code at call sites, fewer checks on the steady state call fast path, 4006 4071 and no need for arity fixup. This looks like a slight speed-up (~0.8%) on both Octane and … … 4163 4228 MethodDefinitions which are not either class "constructor" methods or GeneratorMethods, AsyncFunctions, 4164 4229 and ArrowFunctions. 4165 4230 4166 4231 For details, see the following spec text, and the difference between GeneratorMethod evaluation and 4167 4232 the evaluation of other MethodDefinition forms. 4168 4233 4169 4234 - https://tc39.github.io/ecma262/#sec-method-definitions-runtime-semantics-propertydefinitionevaluation 4170 4235 - https://tc39.github.io/ecma262/#sec-arrow-function-definitions-runtime-semantics-evaluation 4171 4236 - https://tc39.github.io/ecmascript-asyncawait/#async-function-instances 4172 4237 - https://tc39.github.io/ecma262/#sec-generator-function-definitions-runtime-semantics-propertydefinitionevaluation 4173 4238 4174 4239 4175 4240 * runtime/Executable.h: … … 4317 4382 4318 4383 Reviewed by Geoffrey Garen. 4319 4384 4320 4385 Before r207408, IRC had a mode where it would silently assign the first assignable register (so 4321 4386 %rax, %xmm0, etc) to any tmp that was not colorable due to a pathological interference fencepost. … … 4328 4393 corruption. Also, this can only happen for floating point registers, so it's hard to get an 4329 4394 exciting crash. The worst case is that your numbers get all messed up. 4330 4395 4331 4396 This change fixes the issue: 4332 4397 4333 4398 - IRC will now crash if it can't color a tmp. 4334 4399 4335 4400 - IRC doesn't crash on our tests anymore because I added a padInterference() utility that works 4336 4401 around the interference problem by inserting Nops to pad between those instructions where 4337 4402 conflating their early and late actions into one interference fencepost could create an 4338 4403 uncolorable graph. 4339 4404 4340 4405 See https://bugs.webkit.org/show_bug.cgi?id=163548#c2 for a detailed discussion of how the 4341 4406 problem can arise. 4342 4407 4343 4408 This problem almost made me want to abandon our use of interference at instruction boundaries, 4344 4409 and introduce something more comprehensive, like interference at various stages of an … … 4354 4419 DCE, which includes eliminateDeadCode(), allocateStack(), and reportUsedRegisters(). In practice 4355 4420 allocateStack() kills them. 4356 4421 4357 4422 This also finally refactors our passing of RegisterSet to pass it by value, since it's small 4358 4423 enough that we're not gaining anything by using references. On x86, RegisterSet ought to be … … 4621 4686 4622 4687 Reviewed by Mark Lam. 4623 4688 4624 4689 The worklist building function in IRC skips temporaries that have no degree. This doesn't appear 4625 4690 to be necessary. This has been there since the original IRC commit. It hasn't caused bugs because … … 4627 4692 while working on bug 163371, I hit a crazy corner case where a temporary would have no 4628 4693 interference edges (i.e. no degree). Here's how it happens: 4629 4694 4630 4695 A spill tmp from a previous iteration of IRC may have no degree: imagine a tmp that is live 4631 4696 everywhere and interferes with everyone, but has one use like: … … 4647 4712 Then, we might coalesce %someOtherTmp with %newTmp. Once this happens, if we make the %newTmp be 4648 4713 the master, we're in deep trouble because %newTmp is not on any worklist. 4649 4714 4650 4715 I don't know how to reproduce this except through the patch in bug 163371. Removing the two lines 4651 4716 of code that skipped no-degree tmps causes no regressions, and resolves the problem I was having. … … 5031 5096 5032 5097 Reviewed by Mark Lam. 5033 5098 5034 5099 When I first added the concept of NewGrey/OldGrey, I had the SlotVisitor store the old cell 5035 5100 state in itself, so that it could use it to decide what to do for reportExtraMemoryVisited(). 5036 5101 5037 5102 Then I changed it in a recent commit, because I wanted the freedom to have SlotVisitor visit 5038 5103 multiple objects in tandem. But I never ended up using this capability. Still, I liked the … … 5040 5105 make the object's state reflect whether it was black for the first time or not. That seemed 5041 5106 convenient. 5042 5107 5043 5108 Unfortunately it's wrong. After we blacken the object, a concurrent barrier could instantly 5044 5109 grey it. Then we would forget that we are visiting this object for the first time. 5045 5110 Subsequent visits will think that they are not the first. So, we will fail to do the right 5046 5111 thing in reportExtraMemoryVisited(). 5047 5112 5048 5113 So, this reverts that change. This is a little more than just a revert, though. I've changed 5049 5114 the terminology a bit. For example, I got tired of reading Black and having to remind myself … … 5052 5117 currently being scanned. I'm going to adopt Siebert's term for this: Anthracite [1]. So, our 5053 5118 black CellState is now called AnthraciteOrBlack. 5054 5119 5055 5120 [1] https://pdfs.semanticscholar.org/7ae4/633265aead1f8835cf7966e179d02c2c8a4b.pdf 5056 5121 … … 5152 5217 5153 5218 Reviewed by Mark Lam. 5154 5219 5155 5220 It turns out that HeapSnapshot was not down with revisiting. The concurrent GC is going to be 5156 5221 built around the idea that we can revisit objects many times. This means that any action that 5157 5222 should only take place once per object must check the object's state. This fixes the snapshot 5158 5223 code to do this. 5159 5224 5160 5225 While writing this code, I realized that we're actually doing this check incorrectly, so I 5161 5226 filed bug 163343. That bug requires a race, so we aren't going to see it yet. … … 5188 5253 (InjectedScript.prototype._describe): 5189 5254 Provide a friendlier name, "Proxy" instead of "ProxyObject". 5190 5255 5191 5256 (InjectedScript.RemoteObject): 5192 5257 When generating a preview for a Proxy object, generate it from the final target … … 5227 5292 by the parser. This could get out of sync, or nodes could forget to 5228 5293 emit debug hooks expected by the parser. 5229 5294 5230 5295 With this change, we always check and emit a debug hook for any 5231 5296 node. The default behavior is for BytecodeGenerator::emitNode … … 5372 5437 5373 5438 Reviewed by Mark Lam. 5374 5439 5375 5440 I guess that the idea of JITWriteBarrier was to make sure that if you slap some heap pointer 5376 5441 bits into machine code, then you better execute a barrier on the code block. But it's a … … 5380 5445 stored in machine code must always be shadowed in the GC heap. I think that convention has 5381 5446 won by overwhelming majority, so we should finally remove JITWriteBarrier. 5382 5447 5383 5448 A practical outcome of this change is that it makes it easier to implement DirectCall ICs, 5384 5449 which will have to store the callee in the CallLinkInfo but not in the machine code. … … 5429 5494 5430 5495 Reviewed by Geoffrey Garen. 5431 5496 5432 5497 It used to be that we would forget which objects are live the moment we started collection. 5433 5498 That's because the flip at the beginning clears all mark bits. 5434 5499 5435 5500 But we already have a facility for tracking objects that are live-but-not-marked. It's called 5436 5501 newlyAllocated. So, instead of clearing mark bits, we want to just transfer them to 5437 5502 newlyAllocated. Then we want to clear all newlyAllocated after GC. 5438 5503 5439 5504 This implements such an approach, along with a versioning optimization for newlyAllocated. 5440 5505 Instead of walking the whole heap to clear newlyAllocated bits at the end of the GC, we bump 5441 5506 the newlyAllocatedVersion, which causes MarkedBlock to treat newlyAllocated as if it was 5442 5507 clear. 5443 5508 5444 5509 We could have even avoided allocating newlyAllocated in most cases, since empirically most 5445 5510 blocks are either completely empty or completely full. An earlier version of this patch did 5446 5511 this, but it was not better than this patch. In fact, it seemed to actually be worse for PLT 5447 5512 and membuster. 5448 5513 5449 5514 To validate this change, we now run the conservative scan after the beginMarking flip. And it 5450 5515 totally works! 5451 5516 5452 5517 This is a huge step towards concurrent GC. It means that we ought to be able to run the 5453 5518 allocator while marking. Since we already separately made it possible to run the barrier 5454 5519 while marking, this means that we're pretty much ready for some serious concurrency action. 5455 5520 5456 5521 This appears to be perf-neutral and space-neutral. 5457 5522 … … 5610 5675 5611 5676 Reviewed by Yusuke Suzuki. 5612 5677 5613 5678 We have a lot of defenses against emitting code that materializes huge contants. But if we do 5614 5679 end up with such code in the backend, it's better to convert those materializations into add … … 5625 5690 5626 5691 Reviewed by Mark Lam. 5627 5692 5628 5693 When writing the lea patch (r207039), I was very careful about how I convert a Shl into a 5629 5694 BaseIndex scale. But I forgot to check if the older code for creating BaseIndexes for 5630 5695 effectiveAddr() got this right. It turns out that the older code missed the <<32 corner 5631 5696 case. 5632 5697 5633 5698 It's sad that the two paths can't share all of their code, but it's somewhat inevitable due 5634 5699 to how matching an address and matching a lea have to do very different things. Matching a … … 5640 5705 more sane by adding a scaleForShl() helper that handles this weird case. It's based on the 5641 5706 new Shl handling from r207039, and exposes it as an API for effectiveAddr() to use. 5642 5707 5643 5708 The testLoadBaseIndexShift32() used to crash. I don't think that this case affects JS 5644 5709 content, since <<32 is such a bizarre outlier. I don't think we even have a path along … … 5691 5756 5692 5757 Reviewed by Saam Barati. 5693 5758 5694 5759 This adds comprehensive support for emitting lea on x86. 5695 5760 5696 5761 When adding this, I found that it was useful to also finally add more reassociation. That 5697 5762 reduces the amount of patterns that the instruction selector has to deal with. … … 5832 5897 5833 5898 Reviewed by Keith Miller. 5834 5899 5835 5900 You can now call Procedure::pinRegister(), or Code::pinRegister(), and it will make this 5836 5901 register behave as follows: 5837 5902 5838 5903 - B3 and Air will emit no code that modifies the value in this register, except if that 5839 5904 happens via a Patchpoint or stackmap constraint (i.e. the user explicitly asked for it). … … 5846 5911 to use them by (1) excluding them from any clobber set (easy, since they're callee save) 5847 5912 and (2) emitting ArgumentReg to grab their value. There's a test that does this. 5848 5849 This is accomplished by taking regsInPriorityOrder() and making it a method of Code. Air 5913 5914 This is accomplished by taking regsInPriorityOrder() and making it a method of Code. Air 5850 5915 already used this API when choosing registers in register allocation. Code now also vends a 5851 5916 mutableRegs() set, which is derived from regsInPriorityOrder(), that can quickly tell you if 5852 5917 a register can be mutated. Doing it this way means that most of this is a purely mechanical 5853 5918 change. The calls to mutableRegs() are the places where we had to change logic: 5854 5919 5855 5920 - The register allocators needs to know that coalescing with a precolored pinned tmp is free. 5856 5921 - The callee-save handler needs to know that we're not supposed to save/restore pinned 5857 5922 registers. 5858 5923 5859 5924 Note that in this scheme, pinned registers are simply registers that do not appear in 5860 5925 regsInPriorityOrder(). This means, for example, that we will now say that FP is pinned. So, … … 5911 5976 5912 5977 Reviewed by Keith Miller. 5913 5978 5914 5979 If we have mutable pinned registers then we need to know which operations mutate them. At 5915 5980 first I considered making this into a heap range thing, but I think that this would be very … … 6912 6977 Air::generate() to use labelIgnoringWatchpoints() to create pcToOriginMap 6913 6978 entries to eliminate unneccesary NOPs. 6914 6979 6915 6980 * b3/air/AirGenerate.cpp: 6916 6981 (JSC::B3::Air::generate): … … 6946 7011 6947 7012 Reviewed by Geoffrey Garen. 6948 7013 6949 7014 While writing some documentation, I found some small holes in the code. 6950 7015 … … 7045 7110 7046 7111 Reviewed by Dan Bernstein. 7047 7112 7048 7113 This function has become dead code. This change removes it. 7049 7114 … … 7100 7165 7101 7166 Reviewed by Geoffrey Garen. 7102 7167 7103 7168 This adds a traps flag to B3::Kind. It also makes B3::Kind work more like Air::Kind, in the 7104 7169 sense that it's a bag of distinct bits - it doesn't need to be a union unless we get enough 7105 7170 things that it would make a difference. 7106 7171 7107 7172 The only analysis that needs to know about traps is effects. It now knows that traps implies 7108 7173 sideExits, which means that this turns off DCE. The only optimization that needs to know 7109 7174 about traps is eliminateCommonSubexpressions(), which needs to pessimize its store 7110 7175 elimination if the store traps. 7111 7176 7112 7177 The hard part of this change is teaching the instruction selector to faithfully carry the 7113 7178 traps flag down to Air. I got this to work by making ArgPromise a non-copyable object that … … 7117 7182 correctly carry the trap bit: if any of the B3 loads or stores involved traps then you get 7118 7183 traps in Air. 7119 7184 7120 7185 This framework also sets us up to do bug 162688, since the ArgPromise::inst() hook is 7121 7186 powerful enough to allow wrapping the instruction with a Patch. 7122 7187 7123 7188 I added some tests to testb3 that verify that optimizations are appropriately inhibited and 7124 7189 that the traps flag survives until the bitter end of Air. … … 7191 7256 7192 7257 Reviewed by Saam Barati. 7193 7258 7194 7259 There are some interesting cases where we can reduce the number of constant materializations if 7195 7260 we teach moveConstants() how to edit code. The two examples that this patch supports are: 7196 7261 7197 7262 - Loads and stores from a constant pointer. Since loads and stores get an offset for free 7198 7263 and the instruction selector is really good at handling it, and since we can query Air to … … 7200 7265 is specific to the absolute address of that load and instead pick some other constant 7201 7266 that is within offset distance of ours. 7202 7267 7203 7268 - Add and Sub by a constant (x + c, x - c). Since x + c = x - -c and x - c = x + -c, we can 7204 7269 flip Add to Sub or vice versa if the negated constant is available. 7205 7270 7206 7271 This change makes moveConstants() pick the most dominant constant that works for an value. In 7207 7272 the case of memory accesses, it uses Air::Arg::isValidAddrForm() to work out what other … … 7210 7275 most dominant constant that works - so if an Add's constant is already most dominant then 7211 7276 nothing changes, but if the negated one is more dominant then it becomes a Sub. 7212 7277 7213 7278 This is a 0.5% speed-up on LongSpider and neutral elsewhere. It's a speed-up because the 7214 7279 absolute address thing reduces the number of address materializations that we have to do, while … … 7506 7571 resolve the breakpoint location before setting the 7507 7572 breakpoint. The different paths are: 7508 7573 7509 7574 - setBreakpoint(scriptId, location) 7510 7575 - Here we know the SourceProvider by its SourceID 7511 7576 - resolve and set 7512 7577 7513 7578 - setBreakpointByURL(url, location) 7514 7579 - Search for existing Scripts that match the URL … … 7516 7581 - When new Scripts are parsed that match the URL 7517 7582 - resolve and set 7518 7583 7519 7584 7520 7585 2016-09-30 Joseph Pecoraro <pecoraro@apple.com> … … 7655 7720 (JSC::Debugger::exception): 7656 7721 (JSC::Debugger::didReachBreakpoint): 7657 7722 7658 7723 Use new variable names, and clarify if we should attempt 7659 7724 to pause or not. … … 7667 7732 (JSC::Debugger::pauseIfNeeded): 7668 7733 Allow updateCallFrame to either attempt a pause or not. 7669 7734 7670 7735 (JSC::Debugger::atStatement): 7671 7736 Attempt pause and reset the at first expression flag. … … 7683 7748 If the user did a step-over and is leaving the 7684 7749 function, then behave like step-out. 7685 7750 7686 7751 (JSC::Debugger::unwindEvent): 7687 7752 Behave like return except don't change any … … 7702 7767 our state so we don't errantly pause on the next 7703 7768 JavaScript microtask that gets executed. 7704 7769 7705 7770 (JSC::Debugger::clearNextPauseState): 7706 7771 Helper to clear all of the pause states now that … … 7785 7850 7786 7851 Reviewed by Mark Lam. 7787 7852 7788 7853 This follows a similar change in B3 (r206595) and replaces Air::Opcode with Air::Kind, 7789 7854 which holds onto the opcode and some additional flags. Because Air is an orthogonal ISA … … 7792 7857 meant to be orthogonal to opcode. This allows us to say things like Add32<Trap>, which 7793 7858 makes sense if any of the operands to the Add32 are addresses. 7794 7859 7795 7860 To demonstrate the flags facility this partly adds a trap flag to Air. B3 doesn't use it 7796 7861 yet, but I made sure that Air respects it. Basically that means blocking DCE when the flag … … 7876 7941 7877 7942 Reviewed by Keith Miller. 7878 7943 7879 7944 The put_by_id-in-put_by_val optimization had the write barrier in the wrong place and 7880 7945 incorrectly filtered on value instead of base. 7881 7946 7882 7947 No reduced test case. You really need to run Dromaeo/jslib to catch it. I love Dromaeo's 7883 7948 ability to catch GC bugs. … … 7932 7997 actually did. This change replaces Opcode with Kind, which is a tuple of opcode and other 7933 7998 stuff. 7934 7999 7935 8000 Opcodes are great, and that's how most compilers work. But opcodes are one-dimensional. Here 7936 8001 is how this manifests. Say you have an opcode, like Load. You will be happy if your IR has … … 7938 8003 done in B3. B3 has one dimension of Load opcodes, which determines something like the C type 7939 8004 of the load. But in the very near future, we will want to add two more dimensions to Loads: 7940 8005 7941 8006 - A flag to say if the load traps. 7942 8007 - A flag to say if the load has acquire semantics. 7943 8008 7944 8009 Mapping these three dimensions (type, trap, acquire) onto the one-dimensional Opcode space 7945 8010 would create mayham: Load8S, Load8STrap, Load8SAcquire, Load8STrapAcquire, Load8Z, 7946 8011 Load8ZTrap, etc. 7947 8012 7948 8013 This happens in other parts of the IR. For example, we have a dimension of arithmetic 7949 8014 operations: add, sub, mul, div, mod, etc. Then we have the chill flag. But since opcodes … … 7951 8016 compiler that case on both Div and ChillDiv, or case on both Mod and ChillMod, since they 7952 8017 are only interested in the kind of arithmetic being done and not the chillness. 7953 8018 7954 8019 Though the examples all involve bits (chill or not, trapping or not, etc), I can imagine 7955 8020 other properties that behave more like small enums, like if we fill out more memory ordering 7956 8021 modes other than just "acquire? yes/no". There will eventually have to be something like a 7957 8022 std::memory_order associated with memory accesses. 7958 8023 7959 8024 One approach to this problem is to have a Value subclass that contains fields with the meta 7960 8025 data. I don't like this for two reasons: 7961 8026 7962 8027 - In bug 162688, I want to make trapping memory accesses have stackmaps. This means that a 7963 8028 trapping memory access would have a different Value subclass than a non-trapping memory 7964 8029 access. So, this meta-data needs to channel into ValueType::accepts(). Currently that 7965 8030 takes Opcode and nothing else. 7966 8031 7967 8032 - Compiler IRs are all about making common tasks easy. If it becomes commonplace for opcodes 7968 8033 to require a custom Value subclass just for a bit then that's not very easy. 7969 8034 7970 8035 This change addresses this problem by making the compiler pass around Kinds rather than 7971 8036 Opcodes. A Kind contains an Opcode as well as any number of opcode-specific bits. This … … 7976 8041 7977 8042 Int32 @38 = Div<Chill>(@36, @37, DFG:@24, ControlDependent) 7978 8043 7979 8044 Where "Div<Chill>" is how a Kind that hasExtraBits() dumps itself. If a Kind does not 7980 8045 hasExtraBits() (the normal case) then it dumps like a normal Opcode (without the "<>"). 7981 8046 7982 8047 I replaced many uses of Opcode with Kind. New code has to be mindful that Opcode may not be 7983 8048 the right way to summarize what a value does, and so in many cases it's better to carry … … 7987 8052 Opcode. But most opcodes don't get any extra Kind bits, and so the code that operates on 7988 8053 those opcodes is largely unchanged. 7989 8054 7990 8055 * CMakeLists.txt: 7991 8056 * JavaScriptCore.xcodeproj/project.pbxproj: … … 8114 8179 8115 8180 Reviewed by Geoffrey Garen. 8116 8181 8117 8182 This makes our write barrier behave correctly when it races with the collector. The 8118 8183 collector wants to do this when visiting: 8119 8184 8120 8185 object->cellState = black 8121 8186 visit(object) 8122 8187 8123 8188 The mutator wants to do this when storing: 8124 8189 8125 8190 object->property = newValue 8126 8191 if (object->cellState == black) 8127 8192 remember(object) 8128 8193 8129 8194 Prior to this change, this didn't work right because the compiler would sometimes place 8130 8195 barriers before the store to the property and because the mutator did not have adequate 8131 8196 fences. 8132 8197 8133 8198 Prior to this change, the DFG and FTL would emit this: 8134 8199 8135 8200 if (object->cellState == black) 8136 8201 remember(object) 8137 8202 object->property = newValue 8138 8203 8139 8204 Which is wrong, because the object could start being scanned just after the cellState 8140 8205 check, at which point the store would be lost. We need to confirm that the state was not … … 8147 8212 don't have any way to represent any of the GC's other state, which means that B3 does not 8148 8213 have to worry about aliasing with any of that). 8149 8214 8150 8215 The collector already uses a store-load fence on x86 just after setting the cellState and 8151 8216 before visiting the object. The mutator needs to do the same. But we cannot put a … … 8156 8221 would lift throughput-while-collecting from 0% of peak to 85% of peak. This changes the 8157 8222 barrier so that it looks like this: 8158 8223 8159 8224 if (object->cellState <= heap.sneakyBlackThreshold) 8160 8225 slowPath(object) 8161 8226 8162 8227 Where sneakyBlackThreshold is the normal blackThreshold when we're not collecting, or a 8163 8228 tautoligical threshold (that makes everything look black) when we are collecting. This … … 8167 8232 check if we are concurrently collecting; if so, it does a fence and rechecks if the object 8168 8233 really did need that barrier. 8169 8234 8170 8235 This also reintroduces elimination of redundant store barriers, which was lost in the last 8171 8236 store barrier change. We can only do it when there is no possibility of GC, exit, or … … 8177 8242 that it uses a constant black threshold rather than the sneaky one, thereby saving one 8178 8243 load. 8179 8244 8180 8245 Even with all of those optimizations, I still had problems with barrier cost. I found that one 8181 8246 of the benchmarks that was being hit particularly hard was JetStream/regexp-2010. Fortunately … … 8187 8252 to have a DeferralContext object that houses a boolean that is false by default, but the GC 8188 8253 writes true into it if it would have wanted to GC. You thread a pointer to the deferralContext 8189 through all of your allocations. This kind of mechanism has the overhead of a zero 8254 through all of your allocations. This kind of mechanism has the overhead of a zero 8190 8255 initialization on the stack on entry and a zero check on exit. This is probably even efficient 8191 8256 enough that we could start thinking about having the DFG use it, for example if we found a … … 8193 8258 wacky. This optimization took this patch from 0.68% JetStream regressed to neutral, according 8194 8259 to my latest data. 8195 8260 8196 8261 Finally, an earlier version of this change put the store-load fence in B3 IR, so I ended up 8197 8262 adding FTLOutput support for it and AbstractHeapRepository magic for decorating the heaps. … … 8569 8634 Make the subclass of CallSlowPathGenerator that takes arguments variadic 8570 8635 so it can take any number of arguments. Also updates the slowPathCall helper 8571 function to be variadic. I had to move the spill mode and exception check 8636 function to be variadic. I had to move the spill mode and exception check 8572 8637 requirement parameters to before the arguments since the variadic arguments 8573 8638 must be at the end. As a convenience, I added an overload of slowPathCall that -
trunk/Source/JavaScriptCore/DerivedSources.make
r208148 r208238 65 65 YarrCanonicalizeUnicode.cpp \ 66 66 WasmOps.h \ 67 WasmValidateInlines.h \ 67 68 # 68 69 … … 302 303 $(PYTHON) $(JavaScriptCore)/wasm/generateWasmOpsHeader.py $(JavaScriptCore)/wasm/wasm.json ./WasmOps.h 303 304 305 WasmValidateInlines.h: $(JavaScriptCore)/wasm/generateWasmValidateInlinesHeader.py $(JavaScriptCore)/wasm/generateWasm.py $(JavaScriptCore)/wasm/wasm.json 306 $(PYTHON) $(JavaScriptCore)/wasm/generateWasmValidateInlinesHeader.py $(JavaScriptCore)/wasm/wasm.json ./WasmValidateInlines.h 307 304 308 # Dynamically-defined targets are listed below. Static targets belong up top. 305 309 -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r208209 r208238 1231 1231 531374BD1D5CE67600AF7A0B /* WasmPlan.h in Headers */ = {isa = PBXBuildFile; fileRef = 531374BC1D5CE67600AF7A0B /* WasmPlan.h */; }; 1232 1232 531374BF1D5CE95000AF7A0B /* WasmPlan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 531374BE1D5CE95000AF7A0B /* WasmPlan.cpp */; }; 1233 533B15DF1DC7F463004D500A /* WasmOps.h in Headers */ = {isa = PBXBuildFile; fileRef = 533B15DE1DC7F463004D500A /* WasmOps.h */; }; 1233 1234 5341FC701DAC33E500E7E4D7 /* B3WasmBoundsCheckValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5341FC6F1DAC33E500E7E4D7 /* B3WasmBoundsCheckValue.cpp */; }; 1234 1235 5341FC721DAC343C00E7E4D7 /* B3WasmBoundsCheckValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 5341FC711DAC343C00E7E4D7 /* B3WasmBoundsCheckValue.h */; }; … … 1254 1255 53F40E8D1D5901F20099A1B6 /* WasmParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F40E8C1D5901F20099A1B6 /* WasmParser.h */; }; 1255 1256 53F40E8F1D5902820099A1B6 /* WasmB3IRGenerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53F40E8E1D5902820099A1B6 /* WasmB3IRGenerator.cpp */; }; 1256 53F40E911D5903020099A1B6 /* WasmOps.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F40E901D5903020099A1B6 /* WasmOps.h */; };1257 1257 53F40E931D5A4AB30099A1B6 /* WasmB3IRGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F40E921D5A4AB30099A1B6 /* WasmB3IRGenerator.h */; }; 1258 1258 53F40E951D5A7AEF0099A1B6 /* WasmModuleParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F40E941D5A7AEF0099A1B6 /* WasmModuleParser.h */; }; … … 1263 1263 53FD04D31D7AB277003287D3 /* WasmCallingConvention.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53FD04D11D7AB187003287D3 /* WasmCallingConvention.cpp */; }; 1264 1264 53FD04D41D7AB291003287D3 /* WasmCallingConvention.h in Headers */ = {isa = PBXBuildFile; fileRef = 53FD04D21D7AB187003287D3 /* WasmCallingConvention.h */; }; 1265 5C4E8E961DBEBE620036F1FC /* JSONParseTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5C4E8E941DBEBDA20036F1FC /* JSONParseTest.cpp */; }; 1265 53FF7F991DBFCD9000A26CCC /* WasmValidate.h in Headers */ = {isa = PBXBuildFile; fileRef = 53FF7F981DBFCD9000A26CCC /* WasmValidate.h */; }; 1266 53FF7F9B1DBFD2B900A26CCC /* WasmValidate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53FF7F9A1DBFD2B900A26CCC /* WasmValidate.cpp */; }; 1267 53FF7F9D1DC00DB100A26CCC /* WasmFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53FF7F9C1DC00DB100A26CCC /* WasmFormat.cpp */; }; 1266 1268 5B70CFDE1DB69E6600EC23F9 /* JSAsyncFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 5B70CFD81DB69E5C00EC23F9 /* JSAsyncFunction.h */; }; 1267 1269 5B70CFDF1DB69E6600EC23F9 /* JSAsyncFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5B70CFD91DB69E5C00EC23F9 /* JSAsyncFunction.cpp */; }; … … 1270 1272 5B70CFE21DB69E6600EC23F9 /* AsyncFunctionConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = 5B70CFDC1DB69E5C00EC23F9 /* AsyncFunctionConstructor.h */; }; 1271 1273 5B70CFE31DB69E6600EC23F9 /* AsyncFunctionConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5B70CFDD1DB69E5C00EC23F9 /* AsyncFunctionConstructor.cpp */; }; 1274 5C4E8E961DBEBE620036F1FC /* JSONParseTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5C4E8E941DBEBDA20036F1FC /* JSONParseTest.cpp */; }; 1272 1275 5D5D8AD10E0D0EBE00F9C692 /* libedit.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D5D8AD00E0D0EBE00F9C692 /* libedit.dylib */; }; 1273 1276 5DBB151B131D0B310056AD36 /* testapi.js in Copy Support Script */ = {isa = PBXBuildFile; fileRef = 14D857740A4696C80032146C /* testapi.js */; }; … … 3559 3562 531374BC1D5CE67600AF7A0B /* WasmPlan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmPlan.h; sourceTree = "<group>"; }; 3560 3563 531374BE1D5CE95000AF7A0B /* WasmPlan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmPlan.cpp; sourceTree = "<group>"; }; 3564 533B15DE1DC7F463004D500A /* WasmOps.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmOps.h; sourceTree = "<group>"; }; 3561 3565 5341FC6F1DAC33E500E7E4D7 /* B3WasmBoundsCheckValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3WasmBoundsCheckValue.cpp; path = b3/B3WasmBoundsCheckValue.cpp; sourceTree = "<group>"; }; 3562 3566 5341FC711DAC343C00E7E4D7 /* B3WasmBoundsCheckValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3WasmBoundsCheckValue.h; path = b3/B3WasmBoundsCheckValue.h; sourceTree = "<group>"; }; … … 3586 3590 53F40E8C1D5901F20099A1B6 /* WasmParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmParser.h; sourceTree = "<group>"; }; 3587 3591 53F40E8E1D5902820099A1B6 /* WasmB3IRGenerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmB3IRGenerator.cpp; sourceTree = "<group>"; }; 3588 53F40E901D5903020099A1B6 /* WasmOps.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmOps.h; sourceTree = "<group>"; };3589 3592 53F40E921D5A4AB30099A1B6 /* WasmB3IRGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmB3IRGenerator.h; sourceTree = "<group>"; }; 3590 3593 53F40E941D5A7AEF0099A1B6 /* WasmModuleParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmModuleParser.h; sourceTree = "<group>"; }; … … 3595 3598 53FD04D11D7AB187003287D3 /* WasmCallingConvention.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmCallingConvention.cpp; sourceTree = "<group>"; }; 3596 3599 53FD04D21D7AB187003287D3 /* WasmCallingConvention.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmCallingConvention.h; sourceTree = "<group>"; }; 3597 5C4E8E941DBEBDA20036F1FC /* JSONParseTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JSONParseTest.cpp; path = API/tests/JSONParseTest.cpp; sourceTree = "<group>"; }; 3598 5C4E8E951DBEBDA20036F1FC /* JSONParseTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSONParseTest.h; path = API/tests/JSONParseTest.h; sourceTree = "<group>"; }; 3600 53FF7F981DBFCD9000A26CCC /* WasmValidate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmValidate.h; sourceTree = "<group>"; }; 3601 53FF7F9A1DBFD2B900A26CCC /* WasmValidate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmValidate.cpp; sourceTree = "<group>"; }; 3602 53FF7F9C1DC00DB100A26CCC /* WasmFormat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmFormat.cpp; sourceTree = "<group>"; }; 3599 3603 5B70CFD81DB69E5C00EC23F9 /* JSAsyncFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSAsyncFunction.h; sourceTree = "<group>"; }; 3600 3604 5B70CFD91DB69E5C00EC23F9 /* JSAsyncFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSAsyncFunction.cpp; sourceTree = "<group>"; }; … … 3604 3608 5B70CFDD1DB69E5C00EC23F9 /* AsyncFunctionConstructor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AsyncFunctionConstructor.cpp; sourceTree = "<group>"; }; 3605 3609 5B8243041DB7AA4900EA6384 /* AsyncFunctionPrototype.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = AsyncFunctionPrototype.js; sourceTree = "<group>"; }; 3610 5C4E8E941DBEBDA20036F1FC /* JSONParseTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JSONParseTest.cpp; path = API/tests/JSONParseTest.cpp; sourceTree = "<group>"; }; 3611 5C4E8E951DBEBDA20036F1FC /* JSONParseTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSONParseTest.h; path = API/tests/JSONParseTest.h; sourceTree = "<group>"; }; 3606 3612 5D5D8AD00E0D0EBE00F9C692 /* libedit.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libedit.dylib; path = /usr/lib/libedit.dylib; sourceTree = "<absolute>"; }; 3607 3613 5DAFD6CB146B686300FBEFB4 /* JSC.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = JSC.xcconfig; sourceTree = "<group>"; }; … … 5846 5852 996B73141BD9FA2C00331B84 /* SymbolPrototype.lut.h */, 5847 5853 65A946141C8E9F6F00A7209A /* YarrCanonicalizeUnicode.cpp */, 5854 533B15DE1DC7F463004D500A /* WasmOps.h */, 5848 5855 ); 5849 5856 name = "Derived Sources"; … … 5882 5889 53FD04D11D7AB187003287D3 /* WasmCallingConvention.cpp */, 5883 5890 53FD04D21D7AB187003287D3 /* WasmCallingConvention.h */, 5884 53F 40E901D5903020099A1B6 /* WasmOps.h*/,5891 53FF7F9C1DC00DB100A26CCC /* WasmFormat.cpp */, 5885 5892 7BC547D21B69599B00959B58 /* WasmFormat.h */, 5886 5893 53F40E8A1D5901BB0099A1B6 /* WasmFunctionParser.h */, … … 5893 5900 53F40E8C1D5901F20099A1B6 /* WasmParser.h */, 5894 5901 53F40E841D58F9770099A1B6 /* WasmSections.h */, 5902 53FF7F9A1DBFD2B900A26CCC /* WasmValidate.cpp */, 5903 53FF7F981DBFCD9000A26CCC /* WasmValidate.h */, 5895 5904 ); 5896 5905 path = wasm; … … 7997 8006 0F2BDC4B1522809D00CD8910 /* DFGVariableEventStream.h in Headers */, 7998 8007 0FFFC96014EF90BD00C72532 /* DFGVirtualRegisterAllocationPhase.h in Headers */, 8008 53FF7F991DBFCD9000A26CCC /* WasmValidate.h in Headers */, 7999 8009 0FC97F4218202119002C9B26 /* DFGWatchpointCollectionPhase.h in Headers */, 8000 8010 0FDB2CE8174830A2007B3C1B /* DFGWorklist.h in Headers */, … … 8400 8410 FE1220271BE7F58C0039E6F2 /* JITAddGenerator.h in Headers */, 8401 8411 0F919D11157F332C004A4E7D /* JSSegmentedVariableObject.h in Headers */, 8402 53F40E911D5903020099A1B6 /* WasmOps.h in Headers */,8403 8412 A7299D9E17D12837005F5FF9 /* JSSet.h in Headers */, 8404 8413 A790DD70182F499700588807 /* JSSetIterator.h in Headers */, … … 8781 8790 14E84FA214EE1ACC00D6D5D4 /* WeakImpl.h in Headers */, 8782 8791 14BE7D3317135CF400D1807A /* WeakInlines.h in Headers */, 8792 533B15DF1DC7F463004D500A /* WasmOps.h in Headers */, 8783 8793 A7CA3AE417DA41AE006538AF /* WeakMapConstructor.h in Headers */, 8784 8794 A7CA3AEC17DA5168006538AF /* WeakMapData.h in Headers */, … … 9942 9952 A7E2EA6C0FB460CF00601F06 /* LiteralParser.cpp in Sources */, 9943 9953 A5A1A0951D8CB341004C2EB8 /* DebuggerParseData.cpp in Sources */, 9954 53FF7F9D1DC00DB100A26CCC /* WasmFormat.cpp in Sources */, 9944 9955 FE3913541B794F6E00EDAF71 /* LiveObjectList.cpp in Sources */, 9945 9956 FE20CE9D15F04A9500DF3430 /* LLIntCLoop.cpp in Sources */, … … 10100 10111 70EC0EC61AA0D7DA00B6AAFA /* StringIteratorPrototype.cpp in Sources */, 10101 10112 14469DEC107EC7E700650446 /* StringObject.cpp in Sources */, 10113 53FF7F9B1DBFD2B900A26CCC /* WasmValidate.cpp in Sources */, 10102 10114 14469DED107EC7E700650446 /* StringPrototype.cpp in Sources */, 10103 10115 9335F24D12E6765B002B5553 /* StringRecursionChecker.cpp in Sources */, -
trunk/Source/JavaScriptCore/testWasm.cpp
r207825 r208238 270 270 } 271 271 272 static void checkPlan(Plan& plan, unsigned expectedNumberOfFunctions) 273 { 274 if (plan.failed()) { 275 dataLogLn("Module failed to compile with error: ", plan.errorMessage()); 276 CRASH(); 277 } 278 279 if (plan.resultSize() != expectedNumberOfFunctions) { 280 dataLogLn("Incorrect number of functions"); 281 CRASH(); 282 } 283 284 for (unsigned i = 0; i < expectedNumberOfFunctions; ++i) { 285 if (!plan.result(i)) { 286 dataLogLn("Function at index, " , i, " failed to compile correctly"); 287 CRASH(); 288 } 289 } 290 291 } 292 272 293 // For now we inline the test files. 273 294 static void runWasmTests() … … 291 312 292 313 Plan plan(*vm, vector); 293 if (plan.failed() || plan.resultSize() != 2 || !plan.result(0) || !plan.result(1)) { 294 dataLogLn("Module failed to compile correctly."); 295 CRASH(); 296 } 314 checkPlan(plan, 2); 297 315 298 316 // Test this doesn't crash. … … 320 338 321 339 Plan plan(*vm, vector); 322 if (plan.failed() || plan.resultSize() != 2 || !plan.result(0) || !plan.result(1)) { 323 dataLogLn("Module failed to compile correctly."); 324 CRASH(); 325 } 340 checkPlan(plan, 2); 326 341 327 342 // Test this doesn't crash. … … 354 369 355 370 Plan plan(*vm, vector); 356 if (plan.failed() || plan.resultSize() != 2 || !plan.result(0) || !plan.result(1)) { 357 dataLogLn("Module failed to compile correctly."); 358 CRASH(); 359 } 371 checkPlan(plan, 2); 360 372 361 373 // Test this doesn't crash. … … 388 400 389 401 Plan plan(*vm, vector); 390 if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) { 391 dataLogLn("Module failed to compile correctly."); 392 CRASH(); 393 } 402 checkPlan(plan, 1); 394 403 395 404 // Test this doesn't crash. … … 448 457 449 458 Plan plan(*vm, vector); 450 if (plan.failed() || plan.resultSize() != 2 || !plan.result(0) || !plan.result(1)) { 451 dataLogLn("Module failed to compile correctly."); 452 CRASH(); 453 } 459 checkPlan(plan, 2); 454 460 455 461 // Test this doesn't crash. … … 464 470 { 465 471 // Generated from: 466 // (module467 // (memory 1)468 // (func (export "i32_load8_s") (param $i i32) (param $ptr i32) (result i32)469 // (i64.store (get_local $ptr) (get_local $i))470 // (return (i64.load (get_local $ptr)))471 // )472 // )472 // (module 473 // (memory 1) 474 // (func (export "i64") (param $i i64) (param $ptr i32) (result i64) 475 // (i64.store (get_local $ptr) (get_local $i)) 476 // (return (i64.load (get_local $ptr))) 477 // ) 478 // ) 473 479 Vector<uint8_t> vector = { 474 480 0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40, 475 481 0x02, 0x02, 0x01, 0x01, 0x02, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80, 476 0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0b, 0x69, 0x33, 477 0x32, 0x5f, 0x6c, 0x6f, 0x61, 0x64, 0x38, 0x5f, 0x73, 0x00, 0x00, 0x0a, 0x95, 0x80, 0x80, 0x80, 478 0x00, 0x01, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x01, 0x14, 0x00, 0x34, 0x03, 0x00, 0x14, 479 0x01, 0x2b, 0x03, 0x00, 0x09, 0x0f 480 }; 481 482 Plan plan(*vm, vector); 483 if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) { 484 dataLogLn("Module failed to compile correctly."); 485 CRASH(); 486 } 482 0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x03, 0x69, 0x36, 483 0x34, 0x00, 0x00, 0x0a, 0x95, 0x80, 0x80, 0x80, 0x00, 0x01, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x00, 484 0x14, 0x01, 0x14, 0x00, 0x34, 0x03, 0x00, 0x14, 0x01, 0x2b, 0x03, 0x00, 0x09, 0x0f 485 }; 486 487 Plan plan(*vm, vector); 488 checkPlan(plan, 1); 487 489 488 490 // Test this doesn't crash. … … 511 513 512 514 Plan plan(*vm, vector); 513 if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) { 514 dataLogLn("Module failed to compile correctly."); 515 CRASH(); 516 } 515 checkPlan(plan, 1); 517 516 518 517 // Test this doesn't crash. … … 551 550 552 551 Plan plan(*vm, vector); 553 if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) { 554 dataLogLn("Module failed to compile correctly."); 555 CRASH(); 556 } 552 checkPlan(plan, 1); 557 553 ASSERT(plan.memory()->size()); 558 554 … … 606 602 607 603 Plan plan(*vm, vector); 608 if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) { 609 dataLogLn("Module failed to compile correctly."); 610 CRASH(); 611 } 604 checkPlan(plan, 1); 612 605 ASSERT(plan.memory()->size()); 613 606 … … 650 643 651 644 Plan plan(*vm, vector); 652 if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) { 653 dataLogLn("Module failed to compile correctly."); 654 CRASH(); 655 } 645 checkPlan(plan, 1); 656 646 ASSERT(plan.memory()->size()); 657 647 … … 681 671 682 672 Plan plan(*vm, vector); 683 if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) { 684 dataLogLn("Module failed to compile correctly."); 685 CRASH(); 686 } 673 checkPlan(plan, 1); 687 674 688 675 // Test this doesn't crash. … … 711 698 712 699 Plan plan(*vm, vector); 713 if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) { 714 dataLogLn("Module failed to compile correctly."); 715 CRASH(); 716 } 700 checkPlan(plan, 1); 717 701 718 702 // Test this doesn't crash. … … 742 726 743 727 Plan plan(*vm, vector); 744 if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) { 745 dataLogLn("Module failed to compile correctly."); 746 CRASH(); 747 } 728 checkPlan(plan, 1); 748 729 749 730 // Test this doesn't crash. … … 782 763 783 764 Plan plan(*vm, vector); 784 if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) { 785 dataLogLn("Module failed to compile correctly."); 786 CRASH(); 787 } 765 checkPlan(plan, 1); 788 766 ASSERT(plan.memory()->size()); 789 767 … … 837 815 838 816 Plan plan(*vm, vector); 839 if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) { 840 dataLogLn("Module failed to compile correctly."); 841 CRASH(); 842 } 817 checkPlan(plan, 1); 843 818 ASSERT(plan.memory()->size()); 844 819 … … 881 856 882 857 Plan plan(*vm, vector); 883 if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) { 884 dataLogLn("Module failed to compile correctly."); 885 CRASH(); 886 } 858 checkPlan(plan, 1); 887 859 ASSERT(plan.memory()->size()); 888 860 … … 912 884 913 885 Plan plan(*vm, vector); 914 if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) { 915 dataLogLn("Module failed to compile correctly."); 916 CRASH(); 917 } 886 checkPlan(plan, 1); 918 887 919 888 // Test this doesn't crash. … … 942 911 943 912 Plan plan(*vm, vector); 944 if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) { 945 dataLogLn("Module failed to compile correctly."); 946 CRASH(); 947 } 913 checkPlan(plan, 1); 948 914 949 915 // Test this doesn't crash. … … 983 949 984 950 Plan plan(*vm, vector); 985 if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) { 986 dataLogLn("Module failed to compile correctly."); 987 CRASH(); 988 } 951 checkPlan(plan, 1); 989 952 990 953 // Test this doesn't crash. … … 1010 973 1011 974 Plan plan(*vm, vector); 1012 if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) { 1013 dataLogLn("Module failed to compile correctly."); 1014 CRASH(); 1015 } 975 checkPlan(plan, 1); 1016 976 1017 977 // Test this doesn't crash. … … 1031 991 1032 992 Plan plan(*vm, vector); 1033 if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) { 1034 dataLogLn("Module failed to compile correctly."); 1035 CRASH(); 1036 } 993 checkPlan(plan, 1); 1037 994 1038 995 // Test this doesn't crash. … … 1051 1008 1052 1009 Plan plan(*vm, vector); 1053 if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) { 1054 dataLogLn("Module failed to compile correctly."); 1055 CRASH(); 1056 } 1010 checkPlan(plan, 1); 1057 1011 1058 1012 // Test this doesn't crash. … … 1071 1025 1072 1026 Plan plan(*vm, vector); 1073 if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) { 1074 dataLogLn("Module failed to compile correctly."); 1075 CRASH(); 1076 } 1027 checkPlan(plan, 1); 1077 1028 1078 1029 // Test this doesn't crash. … … 1090 1041 1091 1042 Plan plan(*vm, vector); 1092 if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) { 1093 dataLogLn("Module failed to compile correctly."); 1094 CRASH(); 1095 } 1043 checkPlan(plan, 1); 1096 1044 1097 1045 // Test this doesn't crash. … … 1119 1067 1120 1068 Plan plan(*vm, vector); 1121 if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) { 1122 dataLogLn("Module failed to compile correctly."); 1123 CRASH(); 1124 } 1069 checkPlan(plan, 1); 1125 1070 1126 1071 // Test this doesn't crash. … … 1155 1100 1156 1101 Plan plan(*vm, vector); 1157 if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) { 1158 dataLogLn("Module failed to compile correctly."); 1159 CRASH(); 1160 } 1102 checkPlan(plan, 1); 1161 1103 1162 1104 // Test this doesn't crash. … … 1199 1141 1200 1142 Plan plan(*vm, vector); 1201 if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) { 1202 dataLogLn("Module failed to compile correctly."); 1203 CRASH(); 1204 } 1143 checkPlan(plan, 1); 1205 1144 1206 1145 // Test this doesn't crash. … … 1252 1191 1253 1192 Plan plan(*vm, vector); 1254 if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) { 1255 dataLogLn("Module failed to compile correctly."); 1256 CRASH(); 1257 } 1193 checkPlan(plan, 1); 1258 1194 1259 1195 // Test this doesn't crash. -
trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp
r207825 r208238 88 88 } 89 89 90 LazyBlock() 91 { 92 } 93 90 94 explicit operator bool() const { return !!m_block; } 91 95 … … 117 121 if (signature != Void) 118 122 result.append(proc.addVariable(toB3Type(signature))); 123 } 124 125 ControlData() 126 { 119 127 } 120 128 … … 173 181 B3IRGenerator(Memory*, Procedure&, Vector<UnlinkedCall>& unlinkedCalls); 174 182 175 voidaddArguments(const Vector<Type>&);176 voidaddLocal(Type, uint32_t);183 bool WARN_UNUSED_RETURN addArguments(const Vector<Type>&); 184 bool WARN_UNUSED_RETURN addLocal(Type, uint32_t); 177 185 ExpressionType addConstant(Type, uint64_t); 178 186 … … 192 200 ControlData WARN_UNUSED_RETURN addBlock(Type signature); 193 201 ControlData WARN_UNUSED_RETURN addLoop(Type signature); 194 ControlData WARN_UNUSED_RETURN addIf(ExpressionType condition, Type signature);195 bool WARN_UNUSED_RETURN addElse(ControlData& );202 bool WARN_UNUSED_RETURN addIf(ExpressionType condition, Type signature, ControlData& result); 203 bool WARN_UNUSED_RETURN addElse(ControlData&, const ExpressionList&); 196 204 197 205 bool WARN_UNUSED_RETURN addReturn(const ExpressionList& returnValues); … … 246 254 } 247 255 248 void B3IRGenerator::addLocal(Type type, uint32_t count) 249 { 250 m_locals.reserveCapacity(m_locals.size() + count); 256 bool B3IRGenerator::addLocal(Type type, uint32_t count) 257 { 258 if (!m_locals.tryReserveCapacity(m_locals.size() + count)) 259 return false; 260 251 261 for (uint32_t i = 0; i < count; ++i) 252 m_locals.append(m_proc.addVariable(toB3Type(type))); 253 } 254 255 void B3IRGenerator::addArguments(const Vector<Type>& types) 262 m_locals.uncheckedAppend(m_proc.addVariable(toB3Type(type))); 263 return true; 264 } 265 266 bool B3IRGenerator::addArguments(const Vector<Type>& types) 256 267 { 257 268 ASSERT(!m_locals.size()); 269 if (!m_locals.tryReserveCapacity(types.size())) 270 return false; 271 258 272 m_locals.grow(types.size()); 259 273 wasmCallingConvention().loadArguments(types, m_proc, m_currentBlock, Origin(), … … 263 277 m_currentBlock->appendNew<VariableValue>(m_proc, Set, Origin(), argumentVariable, argument); 264 278 }); 279 return true; 265 280 } 266 281 … … 494 509 } 495 510 496 B3IRGenerator::ControlData B3IRGenerator::addIf(ExpressionType condition, Type signature)511 bool B3IRGenerator::addIf(ExpressionType condition, Type signature, ControlType& result) 497 512 { 498 513 // FIXME: This needs to do some kind of stack passing. … … 508 523 509 524 m_currentBlock = taken; 510 return ControlData(m_proc, signature, notTaken, continuation); 511 } 512 513 bool B3IRGenerator::addElse(ControlData& data) 525 result = ControlData(m_proc, signature, notTaken, continuation); 526 return true; 527 } 528 529 bool B3IRGenerator::addElse(ControlData& data, const ExpressionList&) 514 530 { 515 531 ASSERT(data.continuation); -
trunk/Source/JavaScriptCore/wasm/WasmFormat.h
r207693 r208238 98 98 } 99 99 100 const char* toString(Type); 100 101 101 102 struct Signature { -
trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h
r207825 r208238 74 74 if (verbose) 75 75 dataLogLn("Parsing function starting at: ", (uintptr_t)functionStart, " of length: ", functionLength); 76 m_context.addArguments(m_signature->arguments);77 76 } 78 77 … … 80 79 bool FunctionParser<Context>::parse() 81 80 { 81 if (!m_context.addArguments(m_signature->arguments)) 82 return false; 83 82 84 uint32_t localCount; 83 85 if (!parseVarUInt32(localCount)) … … 93 95 return false; 94 96 95 m_context.addLocal(typeOfLocal, numberOfLocals); 97 if (!m_context.addLocal(typeOfLocal, numberOfLocals)) 98 return false; 96 99 } 97 100 … … 283 286 284 287 ExpressionType condition = m_expressionStack.takeLast(); 285 m_controlStack.append(m_context.addIf(condition, inlineSignature)); 288 ControlType control; 289 if (!m_context.addIf(condition, inlineSignature, control)) 290 return false; 291 292 m_controlStack.append(control); 286 293 return true; 287 294 } 288 295 289 296 case OpType::Else: { 290 return m_context.addElse(m_controlStack.last() );297 return m_context.addElse(m_controlStack.last(), m_expressionStack); 291 298 } 292 299 … … 350 357 ASSERT(data.type() == BlockType::If); 351 358 m_unreachableBlocks = 0; 352 return m_context.addElse(data );359 return m_context.addElse(data, m_expressionStack); 353 360 } 354 361 -
trunk/Source/JavaScriptCore/wasm/WasmPlan.cpp
r207825 r208238 33 33 #include "WasmCallingConvention.h" 34 34 #include "WasmModuleParser.h" 35 #include "WasmValidate.h" 35 36 #include <wtf/DataLog.h> 36 37 … … 64 65 size_t functionLength = info.end - info.start; 65 66 ASSERT(functionLength <= sourceLength); 67 68 String error = validateFunction(functionStart, functionLength, info.signature, moduleParser.functionInformation()); 69 if (!error.isNull()) { 70 m_errorMessage = error; 71 return; 72 } 73 66 74 m_result.append(parseAndCompile(vm, functionStart, functionLength, moduleParser.memory().get(), info.signature, moduleParser.functionInformation())); 67 75 }
Note: See TracChangeset
for help on using the changeset viewer.