deps: V8: backport 3e010af
Original commit message:
[CloneObjectIC] clone MutableHeapNumbers only if !FLAG_unbox_double_fields
Change the macros added in bf84766a2cd3e09070adcd6228a3a487c8dc4bbd to
only do the hard work if FLAG_unbox_double_fields is unset (otherwise,
they will attempt to dereference raw float64s, which is bad!)
Also adds a write barrier in CopyPropertyArrayValues for each store if
it's possible that a MutableHeapNumber is cloned.
BUG=chromium:901301, chromium:902965, chromium:903070, v8:7611
R=cbruni@chromium.org, jkummerow@chromium.org, ishell@chromium.org
Change-Id: I224d3c4e7b0a887684bff68985b4d97021ba4cfb
Reviewed-on: https://chromium-review.googlesource.com/c/1323911
Commit-Queue: Caitlin Potter <caitp@igalia.com>
Reviewed-by: Camillo Bruni <cbruni@chromium.org>
Reviewed-by: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57368}
PR-URL: https://github.com/nodejs/node/pull/25101
Refs: 3e010af274
Fixes: https://github.com/nodejs/node/issues/25089
Reviewed-By: Richard Lau <riclau@uk.ibm.com>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Ali Ijaz Sheikh <ofrobots@google.com>
Reviewed-By: Yang Guo <yangguo@chromium.org>
This commit is contained in:
parent
b5784fe5d5
commit
4884ca6428
@ -38,7 +38,7 @@
|
|||||||
|
|
||||||
# Reset this number to 0 on major V8 upgrades.
|
# Reset this number to 0 on major V8 upgrades.
|
||||||
# Increment by one for each non-official patch applied to deps/v8.
|
# Increment by one for each non-official patch applied to deps/v8.
|
||||||
'v8_embedder_string': '-node.6',
|
'v8_embedder_string': '-node.7',
|
||||||
|
|
||||||
##### V8 defaults for Node.js #####
|
##### V8 defaults for Node.js #####
|
||||||
|
|
||||||
|
@ -534,8 +534,7 @@ Node* ConstructorBuiltinsAssembler::EmitCreateShallowObjectLiteral(
|
|||||||
VARIABLE(offset, MachineType::PointerRepresentation(),
|
VARIABLE(offset, MachineType::PointerRepresentation(),
|
||||||
IntPtrConstant(JSObject::kHeaderSize));
|
IntPtrConstant(JSObject::kHeaderSize));
|
||||||
// Mutable heap numbers only occur on 32-bit platforms.
|
// Mutable heap numbers only occur on 32-bit platforms.
|
||||||
bool may_use_mutable_heap_numbers =
|
bool may_use_mutable_heap_numbers = !FLAG_unbox_double_fields;
|
||||||
FLAG_track_double_fields && !FLAG_unbox_double_fields;
|
|
||||||
{
|
{
|
||||||
Comment("Copy in-object properties fast");
|
Comment("Copy in-object properties fast");
|
||||||
Label continue_fast(this, &offset);
|
Label continue_fast(this, &offset);
|
||||||
|
7
deps/v8/src/code-stub-assembler.cc
vendored
7
deps/v8/src/code-stub-assembler.cc
vendored
@ -4931,6 +4931,13 @@ void CodeStubAssembler::CopyPropertyArrayValues(Node* from_array,
|
|||||||
Comment("[ CopyPropertyArrayValues");
|
Comment("[ CopyPropertyArrayValues");
|
||||||
|
|
||||||
bool needs_write_barrier = barrier_mode == UPDATE_WRITE_BARRIER;
|
bool needs_write_barrier = barrier_mode == UPDATE_WRITE_BARRIER;
|
||||||
|
|
||||||
|
if (destroy_source == DestroySource::kNo) {
|
||||||
|
// PropertyArray may contain MutableHeapNumbers, which will be cloned on the
|
||||||
|
// heap, requiring a write barrier.
|
||||||
|
needs_write_barrier = true;
|
||||||
|
}
|
||||||
|
|
||||||
Node* start = IntPtrOrSmiConstant(0, mode);
|
Node* start = IntPtrOrSmiConstant(0, mode);
|
||||||
ElementsKind kind = PACKED_ELEMENTS;
|
ElementsKind kind = PACKED_ELEMENTS;
|
||||||
BuildFastFixedArrayForEach(
|
BuildFastFixedArrayForEach(
|
||||||
|
60
deps/v8/src/ic/accessor-assembler.cc
vendored
60
deps/v8/src/ic/accessor-assembler.cc
vendored
@ -3566,7 +3566,7 @@ void AccessorAssembler::GenerateCloneObjectIC_Slow() {
|
|||||||
|
|
||||||
void AccessorAssembler::GenerateCloneObjectIC() {
|
void AccessorAssembler::GenerateCloneObjectIC() {
|
||||||
typedef CloneObjectWithVectorDescriptor Descriptor;
|
typedef CloneObjectWithVectorDescriptor Descriptor;
|
||||||
Node* source = Parameter(Descriptor::kSource);
|
TNode<HeapObject> source = CAST(Parameter(Descriptor::kSource));
|
||||||
Node* flags = Parameter(Descriptor::kFlags);
|
Node* flags = Parameter(Descriptor::kFlags);
|
||||||
Node* slot = Parameter(Descriptor::kSlot);
|
Node* slot = Parameter(Descriptor::kSlot);
|
||||||
Node* vector = Parameter(Descriptor::kVector);
|
Node* vector = Parameter(Descriptor::kVector);
|
||||||
@ -3576,8 +3576,7 @@ void AccessorAssembler::GenerateCloneObjectIC() {
|
|||||||
Label miss(this, Label::kDeferred), try_polymorphic(this, Label::kDeferred),
|
Label miss(this, Label::kDeferred), try_polymorphic(this, Label::kDeferred),
|
||||||
try_megamorphic(this, Label::kDeferred);
|
try_megamorphic(this, Label::kDeferred);
|
||||||
|
|
||||||
CSA_SLOW_ASSERT(this, TaggedIsNotSmi(source));
|
TNode<Map> source_map = LoadMap(UncheckedCast<HeapObject>(source));
|
||||||
Node* source_map = LoadMap(UncheckedCast<HeapObject>(source));
|
|
||||||
GotoIf(IsDeprecatedMap(source_map), &miss);
|
GotoIf(IsDeprecatedMap(source_map), &miss);
|
||||||
TNode<MaybeObject> feedback = TryMonomorphicCase(
|
TNode<MaybeObject> feedback = TryMonomorphicCase(
|
||||||
slot, vector, source_map, &if_handler, &var_handler, &try_polymorphic);
|
slot, vector, source_map, &if_handler, &var_handler, &try_polymorphic);
|
||||||
@ -3598,7 +3597,7 @@ void AccessorAssembler::GenerateCloneObjectIC() {
|
|||||||
|
|
||||||
// The IC fast case should only be taken if the result map a compatible
|
// The IC fast case should only be taken if the result map a compatible
|
||||||
// elements kind with the source object.
|
// elements kind with the source object.
|
||||||
TNode<FixedArrayBase> source_elements = LoadElements(source);
|
TNode<FixedArrayBase> source_elements = LoadElements(CAST(source));
|
||||||
|
|
||||||
auto flags = ExtractFixedArrayFlag::kAllFixedArraysDontCopyCOW;
|
auto flags = ExtractFixedArrayFlag::kAllFixedArraysDontCopyCOW;
|
||||||
var_elements = CAST(CloneFixedArray(source_elements, flags));
|
var_elements = CAST(CloneFixedArray(source_elements, flags));
|
||||||
@ -3633,22 +3632,45 @@ void AccessorAssembler::GenerateCloneObjectIC() {
|
|||||||
// Lastly, clone any in-object properties.
|
// Lastly, clone any in-object properties.
|
||||||
// Determine the inobject property capacity of both objects, and copy the
|
// Determine the inobject property capacity of both objects, and copy the
|
||||||
// smaller number into the resulting object.
|
// smaller number into the resulting object.
|
||||||
Node* source_start = LoadMapInobjectPropertiesStartInWords(source_map);
|
TNode<IntPtrT> source_start =
|
||||||
Node* source_size = LoadMapInstanceSizeInWords(source_map);
|
LoadMapInobjectPropertiesStartInWords(source_map);
|
||||||
Node* result_start = LoadMapInobjectPropertiesStartInWords(result_map);
|
TNode<IntPtrT> source_size = LoadMapInstanceSizeInWords(source_map);
|
||||||
Node* field_offset_difference =
|
TNode<IntPtrT> result_start =
|
||||||
|
LoadMapInobjectPropertiesStartInWords(result_map);
|
||||||
|
TNode<IntPtrT> field_offset_difference =
|
||||||
TimesPointerSize(IntPtrSub(result_start, source_start));
|
TimesPointerSize(IntPtrSub(result_start, source_start));
|
||||||
BuildFastLoop(source_start, source_size,
|
|
||||||
[=](Node* field_index) {
|
// If MutableHeapNumbers may be present in-object, allocations may occur
|
||||||
Node* field_offset = TimesPointerSize(field_index);
|
// within this loop, thus the write barrier is required.
|
||||||
TNode<Object> field = LoadObjectField(source, field_offset);
|
//
|
||||||
field = CloneIfMutablePrimitive(field);
|
// TODO(caitp): skip the write barrier until the first MutableHeapNumber
|
||||||
Node* result_offset =
|
// field is found
|
||||||
IntPtrAdd(field_offset, field_offset_difference);
|
const bool may_use_mutable_heap_numbers = !FLAG_unbox_double_fields;
|
||||||
StoreObjectFieldNoWriteBarrier(object, result_offset,
|
|
||||||
field);
|
BuildFastLoop(
|
||||||
},
|
source_start, source_size,
|
||||||
1, INTPTR_PARAMETERS, IndexAdvanceMode::kPost);
|
[=](Node* field_index) {
|
||||||
|
TNode<IntPtrT> field_offset =
|
||||||
|
TimesPointerSize(UncheckedCast<IntPtrT>(field_index));
|
||||||
|
|
||||||
|
if (may_use_mutable_heap_numbers) {
|
||||||
|
TNode<Object> field = LoadObjectField(source, field_offset);
|
||||||
|
field = CloneIfMutablePrimitive(field);
|
||||||
|
TNode<IntPtrT> result_offset =
|
||||||
|
IntPtrAdd(field_offset, field_offset_difference);
|
||||||
|
StoreObjectField(object, result_offset, field);
|
||||||
|
} else {
|
||||||
|
// Copy fields as raw data.
|
||||||
|
TNode<IntPtrT> field = UncheckedCast<IntPtrT>(
|
||||||
|
LoadObjectField(source, field_offset, MachineType::IntPtr()));
|
||||||
|
TNode<IntPtrT> result_offset =
|
||||||
|
IntPtrAdd(field_offset, field_offset_difference);
|
||||||
|
StoreObjectFieldNoWriteBarrier(
|
||||||
|
object, result_offset, field,
|
||||||
|
MachineType::IntPtr().representation());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
1, INTPTR_PARAMETERS, IndexAdvanceMode::kPost);
|
||||||
Return(object);
|
Return(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
12
deps/v8/test/mjsunit/es9/regress/regress-902965.js
vendored
Normal file
12
deps/v8/test/mjsunit/es9/regress/regress-902965.js
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// Copyright 2018 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.
|
||||||
|
|
||||||
|
// Previously, spreading in-object properties would always treat double fields
|
||||||
|
// as tagged, potentially dereferencing a Float64.
|
||||||
|
function inobjectDouble() {
|
||||||
|
"use strict";
|
||||||
|
this.x = -3.9;
|
||||||
|
}
|
||||||
|
const instance = new inobjectDouble();
|
||||||
|
const clone = { ...instance, };
|
15
deps/v8/test/mjsunit/es9/regress/regress-903070.js
vendored
Normal file
15
deps/v8/test/mjsunit/es9/regress/regress-903070.js
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// Copyright 2018 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.
|
||||||
|
|
||||||
|
function clone(src) {
|
||||||
|
return { ...src };
|
||||||
|
}
|
||||||
|
|
||||||
|
function inobjectDoubles() {
|
||||||
|
"use strict";
|
||||||
|
this.p0 = -6400510997704731;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that unboxed double is not treated as tagged
|
||||||
|
assertEquals({ p0: -6400510997704731 }, clone(new inobjectDoubles()));
|
Loading…
x
Reference in New Issue
Block a user