Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[v18.x] deps: patch V8 to 10.2.154.19 #45229

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion deps/v8/include/v8-version.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#define V8_MAJOR_VERSION 10
#define V8_MINOR_VERSION 2
#define V8_BUILD_NUMBER 154
#define V8_PATCH_LEVEL 15
#define V8_PATCH_LEVEL 19

// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
Expand Down
12 changes: 9 additions & 3 deletions deps/v8/src/compiler/access-info.cc
Original file line number Diff line number Diff line change
Expand Up @@ -454,9 +454,15 @@ PropertyAccessInfo AccessInfoFactory::ComputeDataFieldAccessInfo(
map, descriptor, details_representation));
} else if (details_representation.IsHeapObject()) {
if (descriptors_field_type->IsNone()) {
// Store is not safe if the field type was cleared.
if (access_mode == AccessMode::kStore) {
return Invalid();
switch (access_mode) {
case AccessMode::kStore:
case AccessMode::kStoreInLiteral:
case AccessMode::kDefine:
// Store is not safe if the field type was cleared.
return Invalid();
case AccessMode::kLoad:
case AccessMode::kHas:
break;
}

// The field type was cleared by the GC, so we don't know anything
Expand Down
45 changes: 44 additions & 1 deletion deps/v8/src/compiler/compilation-dependencies.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ namespace compiler {
V(Protector) \
V(PrototypeProperty) \
V(StableMap) \
V(Transition)
V(Transition) \
V(ObjectSlotValue)

CompilationDependencies::CompilationDependencies(JSHeapBroker* broker,
Zone* zone)
Expand Down Expand Up @@ -863,6 +864,42 @@ class ProtectorDependency final : public CompilationDependency {
const PropertyCellRef cell_;
};

// Check that an object slot will not change during compilation.
class ObjectSlotValueDependency final : public CompilationDependency {
public:
explicit ObjectSlotValueDependency(const HeapObjectRef& object, int offset,
const ObjectRef& value)
: CompilationDependency(kObjectSlotValue),
object_(object.object()),
offset_(offset),
value_(value.object()) {}

bool IsValid() const override {
PtrComprCageBase cage_base = GetPtrComprCageBase(*object_);
Object current_value =
offset_ == HeapObject::kMapOffset
? object_->map()
: TaggedField<Object>::Relaxed_Load(cage_base, *object_, offset_);
return *value_ == current_value;
}
void Install(PendingDependencies* deps) const override {}

private:
size_t Hash() const override {
return base::hash_combine(object_.address(), offset_, value_.address());
}

bool Equals(const CompilationDependency* that) const override {
const ObjectSlotValueDependency* const zat = that->AsObjectSlotValue();
return object_->address() == zat->object_->address() &&
offset_ == zat->offset_ && value_.address() == zat->value_.address();
}

Handle<HeapObject> object_;
int offset_;
Handle<Object> value_;
};

class ElementsKindDependency final : public CompilationDependency {
public:
ElementsKindDependency(const AllocationSiteRef& site, ElementsKind kind)
Expand Down Expand Up @@ -1110,6 +1147,12 @@ void CompilationDependencies::DependOnElementsKind(
}
}

void CompilationDependencies::DependOnObjectSlotValue(
const HeapObjectRef& object, int offset, const ObjectRef& value) {
RecordDependency(
zone_->New<ObjectSlotValueDependency>(object, offset, value));
}

void CompilationDependencies::DependOnOwnConstantElement(
const JSObjectRef& holder, uint32_t index, const ObjectRef& element) {
RecordDependency(
Expand Down
4 changes: 4 additions & 0 deletions deps/v8/src/compiler/compilation-dependencies.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ class V8_EXPORT_PRIVATE CompilationDependencies : public ZoneObject {
// Record the assumption that {site}'s {ElementsKind} doesn't change.
void DependOnElementsKind(const AllocationSiteRef& site);

// Check that an object slot will not change during compilation.
void DependOnObjectSlotValue(const HeapObjectRef& object, int offset,
const ObjectRef& value);

void DependOnOwnConstantElement(const JSObjectRef& holder, uint32_t index,
const ObjectRef& element);

Expand Down
12 changes: 12 additions & 0 deletions deps/v8/src/compiler/js-create-lowering.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1677,6 +1677,10 @@ base::Optional<Node*> JSCreateLowering::TryAllocateFastLiteral(

// Now that we hold the migration lock, get the current map.
MapRef boilerplate_map = boilerplate.map();
// Protect against concurrent changes to the boilerplate object by checking
// for an identical value at the end of the compilation.
dependencies()->DependOnObjectSlotValue(boilerplate, HeapObject::kMapOffset,
boilerplate_map);
{
base::Optional<MapRef> current_boilerplate_map =
boilerplate.map_direct_read();
Expand Down Expand Up @@ -1841,10 +1845,18 @@ base::Optional<Node*> JSCreateLowering::TryAllocateFastLiteralElements(
boilerplate.elements(kRelaxedLoad);
if (!maybe_boilerplate_elements.has_value()) return {};
FixedArrayBaseRef boilerplate_elements = maybe_boilerplate_elements.value();
// Protect against concurrent changes to the boilerplate object by checking
// for an identical value at the end of the compilation.
dependencies()->DependOnObjectSlotValue(
boilerplate, JSObject::kElementsOffset, boilerplate_elements);

// Empty or copy-on-write elements just store a constant.
int const elements_length = boilerplate_elements.length();
MapRef elements_map = boilerplate_elements.map();
// Protect against concurrent changes to the boilerplate object by checking
// for an identical value at the end of the compilation.
dependencies()->DependOnObjectSlotValue(boilerplate_elements,
HeapObject::kMapOffset, elements_map);
if (boilerplate_elements.length() == 0 || elements_map.IsFixedCowArrayMap()) {
if (allocation == AllocationType::kOld &&
!boilerplate.IsElementsTenured(boilerplate_elements)) {
Expand Down
54 changes: 50 additions & 4 deletions deps/v8/src/objects/value-serializer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,17 @@ static const uint32_t kLatestVersion = 15;
static_assert(kLatestVersion == v8::CurrentValueSerializerFormatVersion(),
"Exported format version must match latest version.");

namespace {
// For serializing JSArrayBufferView flags. Instead of serializing /
// deserializing the flags directly, we serialize them bit by bit. This is for
// ensuring backwards compatilibity in the case where the representation
// changes. Note that the ValueSerializer data can be stored on disk.
using JSArrayBufferViewIsLengthTracking = base::BitField<bool, 0, 1>;
using JSArrayBufferViewIsBackedByRab =
JSArrayBufferViewIsLengthTracking::Next<bool, 1>;

} // namespace

template <typename T>
static size_t BytesNeededForVarint(T value) {
static_assert(std::is_integral<T>::value && std::is_unsigned<T>::value,
Expand Down Expand Up @@ -922,6 +933,8 @@ Maybe<bool> ValueSerializer::WriteJSArrayBuffer(
if (byte_length > std::numeric_limits<uint32_t>::max()) {
return ThrowDataCloneError(MessageTemplate::kDataCloneError, array_buffer);
}
// TODO(v8:11111): Support RAB / GSAB. The wire version will need to be
// bumped.
WriteTag(SerializationTag::kArrayBuffer);
WriteVarint<uint32_t>(byte_length);
WriteRawBytes(array_buffer->backing_store(), byte_length);
Expand Down Expand Up @@ -950,7 +963,10 @@ Maybe<bool> ValueSerializer::WriteJSArrayBufferView(JSArrayBufferView view) {
WriteVarint(static_cast<uint8_t>(tag));
WriteVarint(static_cast<uint32_t>(view.byte_offset()));
WriteVarint(static_cast<uint32_t>(view.byte_length()));
WriteVarint(static_cast<uint32_t>(view.bit_field()));
uint32_t flags =
JSArrayBufferViewIsLengthTracking::encode(view.is_length_tracking()) |
JSArrayBufferViewIsBackedByRab::encode(view.is_backed_by_rab());
WriteVarint(flags);
return ThrowIfOutOfMemory();
}

Expand Down Expand Up @@ -1979,7 +1995,7 @@ MaybeHandle<JSArrayBuffer> ValueDeserializer::ReadTransferredJSArrayBuffer() {

MaybeHandle<JSArrayBufferView> ValueDeserializer::ReadJSArrayBufferView(
Handle<JSArrayBuffer> buffer) {
uint32_t buffer_byte_length = static_cast<uint32_t>(buffer->byte_length());
uint32_t buffer_byte_length = static_cast<uint32_t>(buffer->GetByteLength());
uint8_t tag = 0;
uint32_t byte_offset = 0;
uint32_t byte_length = 0;
Expand All @@ -2004,7 +2020,9 @@ MaybeHandle<JSArrayBufferView> ValueDeserializer::ReadJSArrayBufferView(
Handle<JSDataView> data_view =
isolate_->factory()->NewJSDataView(buffer, byte_offset, byte_length);
AddObjectWithID(id, data_view);
data_view->set_bit_field(flags);
if (!ValidateAndSetJSArrayBufferViewFlags(*data_view, *buffer, flags)) {
return MaybeHandle<JSArrayBufferView>();
}
return data_view;
}
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
Expand All @@ -2021,11 +2039,39 @@ MaybeHandle<JSArrayBufferView> ValueDeserializer::ReadJSArrayBufferView(
}
Handle<JSTypedArray> typed_array = isolate_->factory()->NewJSTypedArray(
external_array_type, buffer, byte_offset, byte_length / element_size);
typed_array->set_bit_field(flags);
if (!ValidateAndSetJSArrayBufferViewFlags(*typed_array, *buffer, flags)) {
return MaybeHandle<JSArrayBufferView>();
}
AddObjectWithID(id, typed_array);
return typed_array;
}

bool ValueDeserializer::ValidateAndSetJSArrayBufferViewFlags(
JSArrayBufferView view, JSArrayBuffer buffer, uint32_t serialized_flags) {
bool is_length_tracking =
JSArrayBufferViewIsLengthTracking::decode(serialized_flags);
bool is_backed_by_rab =
JSArrayBufferViewIsBackedByRab::decode(serialized_flags);

// TODO(marja): When the version number is bumped the next time, check that
// serialized_flags doesn't contain spurious 1-bits.

if (is_backed_by_rab || is_length_tracking) {
if (!FLAG_harmony_rab_gsab) {
return false;
}
if (!buffer.is_resizable()) {
return false;
}
if (is_backed_by_rab && buffer.is_shared()) {
return false;
}
}
view.set_is_length_tracking(is_length_tracking);
view.set_is_backed_by_rab(is_backed_by_rab);
return true;
}

MaybeHandle<Object> ValueDeserializer::ReadJSError() {
uint32_t id = next_id_++;

Expand Down
3 changes: 3 additions & 0 deletions deps/v8/src/objects/value-serializer.h
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,9 @@ class ValueDeserializer {
V8_WARN_UNUSED_RESULT;
MaybeHandle<JSArrayBufferView> ReadJSArrayBufferView(
Handle<JSArrayBuffer> buffer) V8_WARN_UNUSED_RESULT;
bool ValidateAndSetJSArrayBufferViewFlags(
JSArrayBufferView view, JSArrayBuffer buffer,
uint32_t serialized_flags) V8_WARN_UNUSED_RESULT;
MaybeHandle<Object> ReadJSError() V8_WARN_UNUSED_RESULT;
#if V8_ENABLE_WEBASSEMBLY
MaybeHandle<JSObject> ReadWasmModuleTransfer() V8_WARN_UNUSED_RESULT;
Expand Down
12 changes: 8 additions & 4 deletions deps/v8/src/wasm/baseline/liftoff-compiler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1417,9 +1417,11 @@ class LiftoffCompiler {
__ MergeFullStackWith(c->label_state, *__ cache_state());
__ emit_jump(c->label.get());
}
// Merge the else state into the end state.
// Merge the else state into the end state. Set this state as the current
// state first so helper functions know which registers are in use.
__ bind(c->else_state->label.get());
__ MergeFullStackWith(c->label_state, c->else_state->state);
__ cache_state()->Steal(c->else_state->state);
__ MergeFullStackWith(c->label_state, *__ cache_state());
__ cache_state()->Steal(c->label_state);
} else if (c->reachable()) {
// No merge yet at the end of the if, but we need to create a merge for
Expand All @@ -1431,9 +1433,11 @@ class LiftoffCompiler {
c->stack_depth + c->num_exceptions);
__ MergeFullStackWith(c->label_state, *__ cache_state());
__ emit_jump(c->label.get());
// Merge the else state into the end state.
// Merge the else state into the end state. Set this state as the current
// state first so helper functions know which registers are in use.
__ bind(c->else_state->label.get());
__ MergeFullStackWith(c->label_state, c->else_state->state);
__ cache_state()->Steal(c->else_state->state);
__ MergeFullStackWith(c->label_state, *__ cache_state());
__ cache_state()->Steal(c->label_state);
} else {
// No merge needed, just continue with the else state.
Expand Down
17 changes: 17 additions & 0 deletions deps/v8/test/mjsunit/rab-gsab-valueserializer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2022 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: --harmony-rab-gsab

"use strict";

(function FlagMismatch() {
// Length tracking TA, buffer not resizable.
const data1 = new Uint8Array([255, 15, 66, 4, 3, 5, 7, 11, 86, 66, 1, 2, 1]);
assertThrows(() => { d8.serializer.deserialize(data1.buffer); });

// RAB backed TA, buffer not resizable.
const data2 = new Uint8Array([255, 15, 66, 4, 3, 5, 7, 11, 86, 66, 1, 2, 2]);
assertThrows(() => { d8.serializer.deserialize(data2.buffer); });
})();