Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/deps
diff options
context:
space:
mode:
authorMichaël Zasso <targos@protonmail.com>2021-04-17 17:28:47 +0300
committerMichaël Zasso <targos@protonmail.com>2021-04-30 13:54:09 +0300
commit5dc82469d5cb87e4451336f31483d8d69dd16dff (patch)
treef14bd3228f9d680603d92a9d731f98f49bd9b392 /deps
parent77b7a3b7100960fdd59a2f7b5785e56c42398961 (diff)
deps: V8: cherry-pick 254c7945eea2
Original commit message: Merged: [deoptimizer] Fix bug in OptimizedFrame::Summarize Revision: 3353a7d0b017146d543434be4036a81aaf7d25ae BUG=chromium:1182647 NOTRY=true NOPRESUBMIT=true NOTREECHECKS=true R=​bmeurer@chromium.org (cherry picked from commit c0c96b768a7d3463b11403874549e6496529740d) Change-Id: I86abd6a3f34169be5f99aa9f54bb7bb3706fa85a Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2780300 Reviewed-by: Georg Neis <neis@chromium.org> Reviewed-by: Benedikt Meurer <bmeurer@chromium.org> Commit-Queue: Georg Neis <neis@chromium.org> Cr-Original-Commit-Position: refs/branch-heads/8.9@{#49} Cr-Original-Branched-From: 16b9bbbd581c25391981aa03180b76aa60463a3e-refs/heads/8.9.255@{#1} Cr-Original-Branched-From: d16a2a688498bd1c3e6a49edb25d8c4ca56232dc-refs/heads/master@{#72039} Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2794427 Reviewed-by: Victor-Gabriel Savu <vsavu@google.com> Commit-Queue: Artem Sumaneev <asumaneev@google.com> Cr-Commit-Position: refs/branch-heads/8.6@{#72} Cr-Branched-From: a64aed2333abf49e494d2a5ce24bbd14fff19f60-refs/heads/8.6.395@{#1} Cr-Branched-From: a626bc036236c9bf92ac7b87dc40c9e538b087e3-refs/heads/master@{#69472} Refs: https://github.com/v8/v8/commit/254c7945eea2ee85e2bab98dd802b9d940fc1f4b PR-URL: https://github.com/nodejs/node/pull/38275 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Jiawen Geng <technicalcute@gmail.com> Reviewed-By: Shelley Vohr <codebytere@gmail.com>
Diffstat (limited to 'deps')
-rw-r--r--deps/v8/src/deoptimizer/deoptimizer.cc58
-rw-r--r--deps/v8/src/deoptimizer/deoptimizer.h19
-rw-r--r--deps/v8/test/mjsunit/compiler/regress-1182647.js25
3 files changed, 92 insertions, 10 deletions
diff --git a/deps/v8/src/deoptimizer/deoptimizer.cc b/deps/v8/src/deoptimizer/deoptimizer.cc
index 05cd675bedc..970723839ca 100644
--- a/deps/v8/src/deoptimizer/deoptimizer.cc
+++ b/deps/v8/src/deoptimizer/deoptimizer.cc
@@ -3266,7 +3266,8 @@ Address TranslatedState::DecompressIfNeeded(intptr_t value) {
}
}
-TranslatedState::TranslatedState(const JavaScriptFrame* frame) {
+TranslatedState::TranslatedState(const JavaScriptFrame* frame)
+ : purpose_(kFrameInspection) {
int deopt_index = Safepoint::kNoDeoptimizationIndex;
DeoptimizationData data =
static_cast<const OptimizedFrame*>(frame)->GetDeoptimizationData(
@@ -3641,25 +3642,63 @@ void TranslatedState::EnsureCapturedObjectAllocatedAt(
}
default:
- CHECK(map->IsJSObjectMap());
EnsureJSObjectAllocated(slot, map);
- TranslatedValue* properties_slot = &(frame->values_[value_index]);
- value_index++;
+ int remaining_children_count = slot->GetChildrenCount() - 1;
+
+ TranslatedValue* properties_slot = frame->ValueAt(value_index);
+ value_index++, remaining_children_count--;
if (properties_slot->kind() == TranslatedValue::kCapturedObject) {
- // If we are materializing the property array, make sure we put
- // the mutable heap numbers at the right places.
+ // We are materializing the property array, so make sure we put the
+ // mutable heap numbers at the right places.
EnsurePropertiesAllocatedAndMarked(properties_slot, map);
EnsureChildrenAllocated(properties_slot->GetChildrenCount(), frame,
&value_index, worklist);
+ } else {
+ CHECK_EQ(properties_slot->kind(), TranslatedValue::kTagged);
}
- // Make sure all the remaining children (after the map and properties) are
- // allocated.
- return EnsureChildrenAllocated(slot->GetChildrenCount() - 2, frame,
+
+ TranslatedValue* elements_slot = frame->ValueAt(value_index);
+ value_index++, remaining_children_count--;
+ if (elements_slot->kind() == TranslatedValue::kCapturedObject ||
+ !map->IsJSArrayMap()) {
+ // Handle this case with the other remaining children below.
+ value_index--, remaining_children_count++;
+ } else {
+ CHECK_EQ(elements_slot->kind(), TranslatedValue::kTagged);
+ elements_slot->GetValue();
+ if (purpose_ == kFrameInspection) {
+ // We are materializing a JSArray for the purpose of frame inspection.
+ // If we were to construct it with the above elements value then an
+ // actual deopt later on might create another JSArray instance with
+ // the same elements store. That would violate the key assumption
+ // behind left-trimming.
+ elements_slot->ReplaceElementsArrayWithCopy();
+ }
+ }
+
+ // Make sure all the remaining children (after the map, properties store,
+ // and possibly elements store) are allocated.
+ return EnsureChildrenAllocated(remaining_children_count, frame,
&value_index, worklist);
}
UNREACHABLE();
}
+void TranslatedValue::ReplaceElementsArrayWithCopy() {
+ DCHECK_EQ(kind(), TranslatedValue::kTagged);
+ DCHECK_EQ(materialization_state(), TranslatedValue::kFinished);
+ auto elements = Handle<FixedArrayBase>::cast(GetValue());
+ DCHECK(elements->IsFixedArray() || elements->IsFixedDoubleArray());
+ if (elements->IsFixedDoubleArray()) {
+ DCHECK(!elements->IsCowArray());
+ set_storage(isolate()->factory()->CopyFixedDoubleArray(
+ Handle<FixedDoubleArray>::cast(elements)));
+ } else if (!elements->IsCowArray()) {
+ set_storage(isolate()->factory()->CopyFixedArray(
+ Handle<FixedArray>::cast(elements)));
+ }
+}
+
void TranslatedState::EnsureChildrenAllocated(int count, TranslatedFrame* frame,
int* value_index,
std::stack<int>* worklist) {
@@ -3724,6 +3763,7 @@ Handle<ByteArray> TranslatedState::AllocateStorageFor(TranslatedValue* slot) {
void TranslatedState::EnsureJSObjectAllocated(TranslatedValue* slot,
Handle<Map> map) {
+ CHECK(map->IsJSObjectMap());
CHECK_EQ(map->instance_size(), slot->GetChildrenCount() * kTaggedSize);
Handle<ByteArray> object_storage = AllocateStorageFor(slot);
diff --git a/deps/v8/src/deoptimizer/deoptimizer.h b/deps/v8/src/deoptimizer/deoptimizer.h
index ee6978e6292..eaf0578878d 100644
--- a/deps/v8/src/deoptimizer/deoptimizer.h
+++ b/deps/v8/src/deoptimizer/deoptimizer.h
@@ -117,6 +117,8 @@ class TranslatedValue {
return storage_;
}
+ void ReplaceElementsArrayWithCopy();
+
Kind kind_;
MaterializationState materialization_state_ = kUninitialized;
TranslatedState* container_; // This is only needed for materialization of
@@ -313,7 +315,15 @@ class TranslatedFrame {
class TranslatedState {
public:
- TranslatedState() = default;
+ // There are two constructors, each for a different purpose:
+
+ // The default constructor is for the purpose of deoptimizing an optimized
+ // frame (replacing it with one or several unoptimized frames). It is used by
+ // the Deoptimizer.
+ TranslatedState() : purpose_(kDeoptimization) {}
+
+ // This constructor is for the purpose of merely inspecting an optimized
+ // frame. It is used by stack trace generation and various debugging features.
explicit TranslatedState(const JavaScriptFrame* frame);
void Prepare(Address stack_frame_pointer);
@@ -347,6 +357,12 @@ class TranslatedState {
private:
friend TranslatedValue;
+ // See the description of the constructors for an explanation of the two
+ // purposes. The only actual difference is that in the kFrameInspection case
+ // extra work is needed to not violate assumptions made by left-trimming. For
+ // details, see the code around ReplaceElementsArrayWithCopy.
+ enum Purpose { kDeoptimization, kFrameInspection };
+
TranslatedFrame CreateNextTranslatedFrame(TranslationIterator* iterator,
FixedArray literal_array,
Address fp, FILE* trace_file);
@@ -404,6 +420,7 @@ class TranslatedState {
static Float32 GetFloatSlot(Address fp, int slot_index);
static Float64 GetDoubleSlot(Address fp, int slot_index);
+ Purpose const purpose_;
std::vector<TranslatedFrame> frames_;
Isolate* isolate_ = nullptr;
Address stack_frame_pointer_ = kNullAddress;
diff --git a/deps/v8/test/mjsunit/compiler/regress-1182647.js b/deps/v8/test/mjsunit/compiler/regress-1182647.js
new file mode 100644
index 00000000000..e0582f7cbfb
--- /dev/null
+++ b/deps/v8/test/mjsunit/compiler/regress-1182647.js
@@ -0,0 +1,25 @@
+// Copyright 2021 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --verify-heap
+
+function foo() {
+ const arr = Array(1000);
+
+ function bar() {
+ try { ({a: p4nda, b: arr.length}); } catch(e) {}
+ }
+
+ for (var i = 0; i < 25; i++) bar();
+
+ /p4nda/.test({}); // Deopt here.
+
+ arr.shift();
+}
+
+%PrepareFunctionForOptimization(foo);
+foo();
+foo();
+%OptimizeFunctionOnNextCall(foo);
+foo();