GeezerVison is showing github.com — deps: patch V8 to 8.4.371.23 · nodejs/node@6b115d7
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: deps/v8/include/v8-version.h +1-1Lines changed: 1 addition & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
| 11 | 11 | #define V8_MAJOR_VERSION 8 | 12 | 12 | #define V8_MINOR_VERSION 4 | 13 | 13 | #define V8_BUILD_NUMBER 371 | 14 | | -#define V8_PATCH_LEVEL 19 | | 14 | +#define V8_PATCH_LEVEL 23 | 15 | 15 |
| 16 | 16 | // Use 1 for candidates and 0 otherwise. | 17 | 17 | // (Boolean macro values are not supported by all preprocessors.) | |
Collapse file Copy file name to clipboardExpand all lines: deps/v8/src/builtins/promise-all-element-closure.tq +35-10Lines changed: 35 additions & 10 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -82,7 +82,8 @@ const kPropertyArrayHashFieldMax: constexpr int31 | 82 | 82 |
| 83 | 83 | transitioning macro PromiseAllResolveElementClosure<F: type>( | 84 | 84 | implicit context: Context)( | 85 | | - value: JSAny, function: JSFunction, wrapResultFunctor: F): JSAny { | | 85 | + value: JSAny, function: JSFunction, wrapResultFunctor: F, | | 86 | + hasResolveAndRejectClosures: constexpr bool): JSAny { | 86 | 87 | // We use the {function}s context as the marker to remember whether this | 87 | 88 | // resolve element closure was already called. It points to the resolve | 88 | 89 | // element context (which is a FunctionContext) until it was called the | @@ -98,10 +99,6 @@ transitioning macro PromiseAllResolveElementClosure<F: type>( | 98 | 99 | const nativeContext = LoadNativeContext(context); | 99 | 100 | function.context = nativeContext; | 100 | 101 |
| 101 | | - // Update the value depending on whether Promise.all or | 102 | | - // Promise.allSettled is called. | 103 | | - const updatedValue = wrapResultFunctor.Call(nativeContext, value); | 104 | | - | 105 | 102 | // Determine the index from the {function}. | 106 | 103 | assert(kPropertyArrayNoHashSentinel == 0); | 107 | 104 | const identityHash = | @@ -116,13 +113,41 @@ transitioning macro PromiseAllResolveElementClosure<F: type>( | 116 | 113 | const elements = UnsafeCast<FixedArray>(valuesArray.elements); | 117 | 114 | const valuesLength = Convert<intptr>(valuesArray.length); | 118 | 115 | if (index < valuesLength) { | 119 | | - // The {index} is in bounds of the {values_array}, | 120 | | - // just store the {value} and continue. | | 116 | + // The {index} is in bounds of the {values_array}, check if this element has | | 117 | + // already been resolved, and store the {value} if not. | | 118 | + // | | 119 | + // Promise.allSettled, for each input element, has both a resolve and a | | 120 | + // reject closure that share an [[AlreadyCalled]] boolean. That is, the | | 121 | + // input element can only be settled once: after resolve is called, reject | | 122 | + // returns early, and vice versa. Using {function}'s context as the marker | | 123 | + // only tracks per-closure instead of per-element. When the second | | 124 | + // resolve/reject closure is called on the same index, values.object[index] | | 125 | + // will already exist and will not be the hole value. In that case, return | | 126 | + // early. Everything up to this point is not yet observable to user code. | | 127 | + // This is not a problem for Promise.all since Promise.all has a single | | 128 | + // resolve closure (no reject) per element. | | 129 | + if (hasResolveAndRejectClosures) { | | 130 | + if (elements.objects[index] != TheHole) deferred { | | 131 | + return Undefined; | | 132 | + } | | 133 | + } | | 134 | + | | 135 | + // Update the value depending on whether Promise.all or | | 136 | + // Promise.allSettled is called. | | 137 | + const updatedValue = wrapResultFunctor.Call(nativeContext, value); | 121 | 138 | elements.objects[index] = updatedValue; | 122 | 139 | } else { | 123 | 140 | // Check if we need to grow the backing store. | | 141 | + // | | 142 | + // There's no need to check if this element has already been resolved for | | 143 | + // Promise.allSettled if {values_array} has not yet grown to the index. | 124 | 144 | const newLength = index + 1; | 125 | 145 | const elementsLength = elements.length_intptr; | | 146 | + | | 147 | + // Update the value depending on whether Promise.all or | | 148 | + // Promise.allSettled is called. | | 149 | + const updatedValue = wrapResultFunctor.Call(nativeContext, value); | | 150 | + | 126 | 151 | if (index < elementsLength) { | 127 | 152 | // The {index} is within bounds of the {elements} backing store, so | 128 | 153 | // just store the {value} and update the "length" of the {values_array}. | @@ -166,22 +191,22 @@ PromiseAllResolveElementClosure( | 166 | 191 | js-implicit context: Context, receiver: JSAny, | 167 | 192 | target: JSFunction)(value: JSAny): JSAny { | 168 | 193 | return PromiseAllResolveElementClosure( | 169 | | - value, target, PromiseAllWrapResultAsFulfilledFunctor{}); | | 194 | + value, target, PromiseAllWrapResultAsFulfilledFunctor{}, false); | 170 | 195 | } | 171 | 196 |
| 172 | 197 | transitioning javascript builtin | 173 | 198 | PromiseAllSettledResolveElementClosure( | 174 | 199 | js-implicit context: Context, receiver: JSAny, | 175 | 200 | target: JSFunction)(value: JSAny): JSAny { | 176 | 201 | return PromiseAllResolveElementClosure( | 177 | | - value, target, PromiseAllSettledWrapResultAsFulfilledFunctor{}); | | 202 | + value, target, PromiseAllSettledWrapResultAsFulfilledFunctor{}, true); | 178 | 203 | } | 179 | 204 |
| 180 | 205 | transitioning javascript builtin | 181 | 206 | PromiseAllSettledRejectElementClosure( | 182 | 207 | js-implicit context: Context, receiver: JSAny, | 183 | 208 | target: JSFunction)(value: JSAny): JSAny { | 184 | 209 | return PromiseAllResolveElementClosure( | 185 | | - value, target, PromiseAllSettledWrapResultAsRejectedFunctor{}); | | 210 | + value, target, PromiseAllSettledWrapResultAsRejectedFunctor{}, true); | 186 | 211 | } | 187 | 212 | } |
Collapse file Copy file name to clipboardExpand all lines: deps/v8/src/heap/mark-compact.cc +5Lines changed: 5 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -2531,6 +2531,11 @@ void MarkCompactCollector::ClearJSWeakRefs() { | 2531 | 2531 | matched_cell.set_unregister_token(undefined); | 2532 | 2532 | }, | 2533 | 2533 | gc_notify_updated_slot); | | 2534 | + // The following is necessary because in the case that weak_cell has | | 2535 | + // already been popped and removed from the FinalizationRegistry, the call | | 2536 | + // to JSFinalizationRegistry::RemoveUnregisterToken above will not find | | 2537 | + // weak_cell itself to clear its unregister token. | | 2538 | + weak_cell.set_unregister_token(undefined); | 2534 | 2539 | } else { | 2535 | 2540 | // The unregister_token is alive. | 2536 | 2541 | ObjectSlot slot = weak_cell.RawField(WeakCell::kUnregisterTokenOffset); | |
Collapse file Copy file name to clipboardExpand all lines: deps/v8/src/wasm/baseline/arm/liftoff-assembler-arm.h +8-3Lines changed: 8 additions & 3 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -122,11 +122,16 @@ template <void (Assembler::*op)(Register, Register, Register, SBit, Condition), | 122 | 122 | SBit, Condition)> | 123 | 123 | inline void I64Binop(LiftoffAssembler* assm, LiftoffRegister dst, | 124 | 124 | LiftoffRegister lhs, LiftoffRegister rhs) { | 125 | | - DCHECK_NE(dst.low_gp(), lhs.high_gp()); | 126 | | - DCHECK_NE(dst.low_gp(), rhs.high_gp()); | 127 | | - (assm->*op)(dst.low_gp(), lhs.low_gp(), rhs.low_gp(), SetCC, al); | | 125 | + Register dst_low = dst.low_gp(); | | 126 | + if (dst_low == lhs.high_gp() || dst_low == rhs.high_gp()) { | | 127 | + dst_low = assm->GetUnusedRegister( | | 128 | + kGpReg, LiftoffRegList::ForRegs(lhs, rhs, dst.high_gp())) | | 129 | + .gp(); | | 130 | + } | | 131 | + (assm->*op)(dst_low, lhs.low_gp(), rhs.low_gp(), SetCC, al); | 128 | 132 | (assm->*op_with_carry)(dst.high_gp(), lhs.high_gp(), Operand(rhs.high_gp()), | 129 | 133 | LeaveCC, al); | | 134 | + if (dst_low != dst.low_gp()) assm->mov(dst.low_gp(), dst_low); | 130 | 135 | } | 131 | 136 |
| 132 | 137 | template <void (Assembler::*op)(Register, Register, const Operand&, SBit, | |
Collapse file Copy file name to clipboardExpand all lines: deps/v8/src/wasm/baseline/liftoff-assembler.h -9Lines changed: 0 additions & 9 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -354,15 +354,6 @@ class LiftoffAssembler : public TurboAssembler { | 354 | 354 | LiftoffRegList candidates = kGpCacheRegList; | 355 | 355 | Register low = pinned.set(GetUnusedRegister(candidates, pinned)).gp(); | 356 | 356 | Register high = GetUnusedRegister(candidates, pinned).gp(); | 357 | | - if (low.code() > high.code()) { | 358 | | - // Establish the invariant that the register of the low word always has | 359 | | - // a lower code than the register of the high word. This guarantees that | 360 | | - // if a register pair of an input is reused for the result, the low | 361 | | - // word and high word registers are not swapped, i.e. the low word | 362 | | - // register of the result is not the high word register of the input, | 363 | | - // and vice versa. | 364 | | - std::swap(low, high); | 365 | | - } | 366 | 357 | return LiftoffRegister::ForPair(low, high); | 367 | 358 | } else if (kNeedS128RegPair && rc == kFpRegPair) { | 368 | 359 | // kFpRegPair specific logic here because we need adjacent registers, not | |
Collapse file Copy file name to clipboardExpand all lines: deps/v8/test/cctest/test-js-weak-refs.cc +47Lines changed: 47 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -968,5 +968,52 @@ TEST(JSWeakRefTenuredInWorklist) { | 968 | 968 | CHECK(weak_ref->target().IsUndefined(isolate)); | 969 | 969 | } | 970 | 970 |
| | 971 | +TEST(UnregisterTokenHeapVerifier) { | | 972 | + FLAG_harmony_weak_refs = true; | | 973 | + if (!FLAG_incremental_marking) return; | | 974 | + ManualGCScope manual_gc_scope; | | 975 | +#ifdef VERIFY_HEAP | | 976 | + FLAG_verify_heap = true; | | 977 | +#endif | | 978 | + | | 979 | + CcTest::InitializeVM(); | | 980 | + v8::Isolate* isolate = CcTest::isolate(); | | 981 | + Heap* heap = CcTest::heap(); | | 982 | + v8::HandleScope outer_scope(isolate); | | 983 | + | | 984 | + { | | 985 | + // Make a new FinalizationRegistry and register an object with an unregister | | 986 | + // token that's unreachable after the IIFE returns. | | 987 | + v8::HandleScope scope(isolate); | | 988 | + CompileRun( | | 989 | + "var token = {}; " | | 990 | + "var registry = new FinalizationRegistry(function () {}); " | | 991 | + "(function () { " | | 992 | + " let o = {}; " | | 993 | + " registry.register(o, {}, token); " | | 994 | + "})();"); | | 995 | + } | | 996 | + | | 997 | + // GC so the WeakCell corresponding to o is moved from the active_cells to | | 998 | + // cleared_cells. | | 999 | + CcTest::CollectAllGarbage(); | | 1000 | + CcTest::CollectAllGarbage(); | | 1001 | + | | 1002 | + { | | 1003 | + // Override the unregister token to make the original object collectible. | | 1004 | + v8::HandleScope scope(isolate); | | 1005 | + CompileRun("token = 0;"); | | 1006 | + } | | 1007 | + | | 1008 | + heap::SimulateIncrementalMarking(heap, true); | | 1009 | + | | 1010 | + // Pump message loop to run the finalizer task, then the incremental marking | | 1011 | + // task. The finalizer task will pop the WeakCell from the cleared list. This | | 1012 | + // should make the unregister_token slot undefined. That slot is iterated as a | | 1013 | + // custom weak pointer, so if it is not made undefined, the verifier as part | | 1014 | + // of the incremental marking task will crash. | | 1015 | + EmptyMessageQueues(isolate); | | 1016 | +} | | 1017 | + | 971 | 1018 | } // namespace internal | 972 | 1019 | } // namespace v8 |
Collapse file Copy file name to clipboard +29Lines changed: 29 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +// Copyright 2020 the V8 project authors. All rights reserved. | | 2 | +// Use of this source code is governed by a BSD-style license that can be | | 3 | +// found in the LICENSE file. | | 4 | + | | 5 | +load('test/mjsunit/wasm/wasm-module-builder.js'); | | 6 | + | | 7 | +const builder = new WasmModuleBuilder(); | | 8 | +builder.addType(makeSig( | | 9 | + [kWasmI64, kWasmI32, kWasmF64, kWasmI64, kWasmI64, kWasmI32, kWasmI64], | | 10 | + [])); | | 11 | +builder.addFunction(undefined, 0 /* sig */).addBody([ | | 12 | + kExprI32Const, 0, // i32.const | | 13 | + kExprIf, kWasmStmt, // if @3 | | 14 | + kExprI32Const, 1, // i32.const | | 15 | + kExprIf, kWasmStmt, // if @7 | | 16 | + kExprNop, // nop | | 17 | + kExprElse, // else @10 | | 18 | + kExprUnreachable, // unreachable | | 19 | + kExprEnd, // end @12 | | 20 | + kExprLocalGet, 0x06, // local.get | | 21 | + kExprLocalSet, 0x00, // local.set | | 22 | + kExprLocalGet, 0x03, // local.get | | 23 | + kExprLocalGet, 0x00, // local.get | | 24 | + kExprI64Sub, // i64.sub | | 25 | + kExprDrop, // drop | | 26 | + kExprUnreachable, // unreachable | | 27 | + kExprEnd // end @24 | | 28 | +]); | | 29 | +builder.toModule(); |
Collapse file Copy file name to clipboardExpand all lines: deps/v8/tools/whitespace.txt +1Lines changed: 1 addition & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -14,3 +14,4 @@ I'm starting to think that just adding trailing whitespaces might not be bad. | 14 | 14 | Because whitespaces are not that funny..... | 15 | 15 | Today's answer to life the universe and everything is 12950! | 16 | 16 | Today's answer to life the universe and everything is 6728! | | 17 | ++1 |
|