Skip to content
Open
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 15
#define V8_MINOR_VERSION 6
#define V8_BUILD_NUMBER 75
#define V8_PATCH_LEVEL 13
#define V8_PATCH_LEVEL 19

// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
Expand Down
9 changes: 7 additions & 2 deletions deps/v8/src/codegen/compiler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2852,8 +2852,8 @@ void BackgroundDeserializeTask::Run() {
LocalHandleScope handle_scope(&isolate);

DirectHandle<SharedFunctionInfo> inner_result;
off_thread_data_ =
CodeSerializer::StartDeserializeOffThread(&isolate, &cached_data_);
CodeSerializer::StartDeserializeOffThread(&isolate, &cached_data_,
&off_thread_data_);
if (v8_flags.enable_slow_asserts && off_thread_data_.HasResult()) {
#ifdef ENABLE_SLOW_DCHECKS
MergeAssumptionChecker checker(&isolate, false);
Expand All @@ -2866,6 +2866,11 @@ void BackgroundDeserializeTask::SourceTextAvailable(
Isolate* isolate, Handle<String> source_text,
const ScriptDetails& script_details) {
DCHECK_EQ(isolate, isolate_for_local_isolate_);
if (!CodeSerializer::NotifySourceTextAvailable(isolate, &off_thread_data_,
&cached_data_, source_text,
script_details)) {
return;
}
LanguageMode language_mode = construct_language_mode(v8_flags.use_strict);
background_merge_task_.SetUpOnMainThread(isolate, source_text, script_details,
language_mode);
Expand Down
2 changes: 1 addition & 1 deletion deps/v8/src/codegen/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -719,7 +719,7 @@ class V8_EXPORT_PRIVATE BackgroundDeserializeTask {
private:
Isolate* isolate_for_local_isolate_;
AlignedCachedData cached_data_;
CodeSerializer::OffThreadDeserializeData off_thread_data_;
OffThreadDeserializeData off_thread_data_;
BackgroundMergeTask background_merge_task_;
TimedHistogram* timer_;
int64_t background_time_in_microseconds_ = 0;
Expand Down
31 changes: 19 additions & 12 deletions deps/v8/src/ic/ic.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1760,17 +1760,6 @@ KeyedAccessLoadMode GetUpdatedLoadModeForMap(Isolate* isolate,
Handle<Object> KeyedLoadIC::LoadElementHandler(
DirectHandle<Map> receiver_map, KeyedAccessLoadMode new_load_mode,
MaybeDirectHandle<Map> maybe_transition_target) {
// Has a getter interceptor, or is any has and has a query interceptor.
if (receiver_map->has_indexed_interceptor() &&
(receiver_map->GetIndexedInterceptor()->has_getter() ||
(IsAnyHas() && receiver_map->GetIndexedInterceptor()->has_query())) &&
!receiver_map->GetIndexedInterceptor()->non_masking()) {
// TODO(jgruber): Update counter name.
TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_LoadIndexedInterceptorStub);
return IsAnyHas() ? BUILTIN_CODE(isolate(), HasIndexedInterceptorIC)
: BUILTIN_CODE(isolate(), LoadIndexedInterceptorIC);
}

InstanceType instance_type = receiver_map->instance_type();
if (instance_type < FIRST_NONSTRING_TYPE) {
TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_LoadIndexedStringDH);
Expand All @@ -1784,6 +1773,23 @@ Handle<Object> KeyedLoadIC::LoadElementHandler(
if (instance_type == JS_PROXY_TYPE) {
return LoadHandler::LoadProxy(isolate());
}
if (receiver_map->is_access_check_needed()) {
TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_SlowStub);
return LoadHandler::LoadSlow(isolate());
}

// Has a getter interceptor, or is any has and has a query interceptor.
if (receiver_map->has_indexed_interceptor() &&
(receiver_map->GetIndexedInterceptor()->has_getter() ||
(IsAnyHas() && receiver_map->GetIndexedInterceptor()->has_query())) &&
!receiver_map->GetIndexedInterceptor()->non_masking()) {
DCHECK(!receiver_map->is_access_check_needed());
// TODO(jgruber): Update counter name.
TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_LoadIndexedInterceptorStub);
return IsAnyHas() ? BUILTIN_CODE(isolate(), HasIndexedInterceptorIC)
: BUILTIN_CODE(isolate(), LoadIndexedInterceptorIC);
}

#if V8_ENABLE_WEBASSEMBLY
if (InstanceTypeChecker::IsWasmObject(instance_type)) {
// TODO(jgruber): Update counter name.
Expand Down Expand Up @@ -2870,7 +2876,8 @@ void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map,
Handle<Object> KeyedStoreIC::StoreElementHandler(
DirectHandle<Map> receiver_map, KeyedAccessStoreMode store_mode,
MaybeDirectHandle<UnionOf<Smi, Cell>> prev_validity_cell) {
if (!IsJSObjectMap(*receiver_map)) {
if (!IsJSObjectMap(*receiver_map) || receiver_map->is_access_check_needed() ||
receiver_map->IsMapInArrayPrototypeChain(isolate())) {
// DefineKeyedOwnIC, which is used to define computed fields in instances,
// should handled by the slow stub below instead of the proxy stub.
if (IsJSProxyMap(*receiver_map) && !IsDefineKeyedOwnIC()) {
Expand Down
15 changes: 10 additions & 5 deletions deps/v8/src/maglev/maglev-graph-builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9110,16 +9110,21 @@ MaglevGraphBuilder::BuildJSArrayBuiltinMapSwitchOnElementsKind(
sub_graph.GotoOrTrim(&*object_case);
sub_graph.Bind(&*object_case);
}
any_successful |= (!build_kind_specific(kind).IsDoneWithAbort());
ReduceResult result = build_kind_specific(kind);
if (IsSmiElementsKind(kind) && make_smi_fallthrough_to_object) {
// After building the SMI specific parts (see build_kind_specific call
// above), jump to the beginning of the case for the object elements
// kind.
DCHECK(object_case.has_value());
sub_graph.GotoOrTrim(&*object_case);

// Whether the Smi case is successful depends on whether the object case
// is successful, so don't update any_successful here.
} else {
DCHECK(do_return.has_value());
sub_graph.GotoOrTrim(&*do_return);

any_successful |= !result.IsDoneWithAbort();
}
sub_graph.Bind(&check_next_map);
} else {
Expand Down Expand Up @@ -16971,11 +16976,11 @@ void MaglevGraphBuilder::ProcessMergePointPredecessors(
ResetBuilderCachedState();

if (merge_state.is_loop()) {
DCHECK_EQ(merge_state.predecessors_so_far(),
merge_state.predecessor_count() - 1);
CHECK_EQ(merge_state.predecessors_so_far(),
merge_state.predecessor_count() - 1);
} else {
DCHECK_EQ(merge_state.predecessors_so_far(),
merge_state.predecessor_count());
CHECK_EQ(merge_state.predecessors_so_far(),
merge_state.predecessor_count());
}

if (merge_state.predecessor_count() == 1) {
Expand Down
54 changes: 38 additions & 16 deletions deps/v8/src/maglev/maglev-known-node-aspects.cc
Original file line number Diff line number Diff line change
Expand Up @@ -652,22 +652,22 @@ void KnownNodeAspects::ClearUnstableNodeAspectsForStoreMap(
StoreMap* node, bool is_tracing_enabled) {
if (!node->is_transitioning()) return;

if (NodeInfo* node_info = TryGetInfoFor(node->ValueInput().node())) {
if (node_info->possible_maps_are_known() && !node_info->maps_are_stale() &&
node_info->possible_maps().size() == 1) {
compiler::MapRef old_map = node_info->possible_maps().at(0);
auto MaybeAliases = [&](compiler::MapRef map) -> bool {
return map.equals(old_map);
};
// Mark aliasing maps as stale.
if (MarkMapsStaleIfAny(MaybeAliases)) {
if (V8_UNLIKELY(v8_flags.trace_maglev_kna && is_tracing_enabled)) {
std::cout << kRed << "[KNA] StoreMap: Invalidate alias "
<< Brief(*old_map.object()) << kReset << std::endl;
}
}
return;
}
if (MarkSingleMapAsStale(node->ValueInput().node(), is_tracing_enabled)) {
return;
}

// TODO(olivf): Only invalidate nodes with the same type.
OnSideEffect();
if (V8_UNLIKELY(v8_flags.trace_maglev_kna && is_tracing_enabled)) {
std::cout << kRed << "[KNA] StoreMap: Invalidate all unstable maps"
<< kReset << std::endl;
}
}

void KnownNodeAspects::ClearUnstableNodeAspectsForMigration(
Node* node, bool is_tracing_enabled) {
if (MarkSingleMapAsStale(node->input_node(0), is_tracing_enabled)) {
return;
}

// TODO(olivf): Only invalidate nodes with the same type.
Expand Down Expand Up @@ -1009,6 +1009,28 @@ KnownNodeAspects::ContextStoreResult KnownNodeAspects::RecordContextSlotStore(
return {ContextStoreResult::kSetNewValue, std::move(aliased_slots)};
}

bool KnownNodeAspects::MarkSingleMapAsStale(ValueNode* node,
bool is_tracing_enabled) {
if (NodeInfo* node_info = TryGetInfoFor(node)) {
if (node_info->possible_maps_are_known() && !node_info->maps_are_stale() &&
node_info->possible_maps().size() == 1) {
compiler::MapRef old_map = node_info->possible_maps().at(0);
auto MaybeAliases = [&](compiler::MapRef map) -> bool {
return map.equals(old_map);
};
// Mark aliasing maps as stale.
if (MarkMapsStaleIfAny(MaybeAliases)) {
if (V8_UNLIKELY(v8_flags.trace_maglev_kna && is_tracing_enabled)) {
std::cout << kRed << "[KNA]: MarkSingleMapAsStale: Invalidate alias "
<< Brief(*old_map.object()) << kReset << std::endl;
}
}
return true;
}
}
return false;
}

#ifdef DEBUG
bool IsStringRootIndex(RootIndex index) {
if (index > RootIndex::kLastReadOnlyRoot) return false;
Expand Down
7 changes: 5 additions & 2 deletions deps/v8/src/maglev/maglev-known-node-aspects.h
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,8 @@ class KnownNodeAspects {

void ClearUnstableNodeAspectsForStoreMap(StoreMap* node,
bool is_tracing_enabled);
void ClearUnstableNodeAspectsForMigration(Node* node,
bool is_tracing_enabled);
void ClearUnstableNodeAspectsForElementsTransition(
const ZoneVector<compiler::MapRef>& transition_sources,
bool is_tracing_enabled);
Expand Down Expand Up @@ -824,8 +826,7 @@ class KnownNodeAspects {
std::is_same_v<NodeT,
CheckMapsWithMigrationAndDeopt> ||
std::is_same_v<NodeT, MigrateMapIfNeeded>) {
// These instructions only migrate representations of values, not the
// values themselves, so cached values are still valid.
ClearUnstableNodeAspectsForMigration(node, is_tracing_enabled);
} else if constexpr (std::is_same_v<NodeT, StoreMap>) {
ClearUnstableNodeAspectsForStoreMap(node, is_tracing_enabled);
} else if constexpr (std::is_same_v<NodeT, TransitionElementsKind> ||
Expand Down Expand Up @@ -910,6 +911,8 @@ class KnownNodeAspects {
SmallZoneVector<LoadedContextSlotsKey, 8> ClearAliasedContextSlotsFor(
Graph* graph, ValueNode* context, int offset, ValueNode* value);

bool MarkSingleMapAsStale(ValueNode* node, bool is_tracing_enabled);

static constexpr uint32_t kEffectEpochForPureInstructions =
std::numeric_limits<uint32_t>::max();
static constexpr uint32_t kEffectEpochOverflow =
Expand Down
31 changes: 17 additions & 14 deletions deps/v8/src/maglev/maglev-phi-representation-selector.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1074,7 +1074,7 @@ ValueNode* MaglevPhiRepresentationSelector::GetReplacementForPhiInputConversion(
}

ProcessResult MaglevPhiRepresentationSelector::UpdateUntaggingOfPhi(
Phi* phi, ValueNode* old_untagging) {
Phi* phi, ValueNode* old_untagging, const ProcessingState* state) {
DCHECK_EQ(old_untagging->input_count(), 1);
DCHECK(old_untagging->input(0).node()->Is<Phi>());

Expand Down Expand Up @@ -1192,24 +1192,27 @@ ProcessResult MaglevPhiRepresentationSelector::UpdateUntaggingOfPhi(
if (old_untagging->Is<TruncateUnsafeNumberOrOddballToInt32>()) {
conversion_is_truncating_float64 = true;
} else if (old_untagging->Is<TruncateCheckedNumberOrOddballToInt32>()) {
if (from_repr == ValueRepresentation::kFloat64) {
// If {from_repr} is Float64, then the "CheckedNumber" part is
// guaranteed to pass and this operation just truncates its value to
// Int32.
conversion_is_truncating_float64 = true;
} else {
DCHECK_EQ(from_repr, ValueRepresentation::kHoleyFloat64);
if (from_repr == ValueRepresentation::kHoleyFloat64) {
const auto* truncate =
old_untagging->Cast<TruncateCheckedNumberOrOddballToInt32>();
// A HoleyFloat64 hole really means Undefined rather than the_hole:
// whenever it gets rematerialized, it will always be rematerialized as
// Undefined. So, we can use a truncating conversion as long as the
// original assumed input type was allowing truncating Undefined.
// Assumptions without Undefined need to deopt for Hole/Undefined
// ==> not truncating.
conversion_is_truncating_float64 = !NodeTypeIs(
truncate->assumed_input_type(), NodeType::kNumberOrBoolean);
// Undefined. Assumptions without Undefined need to deopt on
// Hole/Undefined before truncating the Float64 value to Int32.
if (!NodeTypeCanBe(truncate->assumed_input_type(),
NodeType::kUndefined)) {
eager_deopt_frame_ = &old_untagging->eager_deopt_info()->top_frame();
AddNewNodeNoInputConversion<CheckHoleyFloat64NotHoleOrUndefined>(
reducer_.current_block(),
BasicBlockPosition::At(state->node_index()), {phi});
#ifdef DEBUG
eager_deopt_frame_ = nullptr;
#endif // DEBUG
}
} else {
DCHECK_EQ(from_repr, ValueRepresentation::kFloat64);
}
conversion_is_truncating_float64 = true;
}

Opcode needed_conversion = GetOpcodeForConversion(
Expand Down
5 changes: 3 additions & 2 deletions deps/v8/src/maglev/maglev-phi-representation-selector.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ class MaglevPhiRepresentationSelector {
// removed altogether (or rather, replaced by an identity node).
return UpdateUntaggingOfPhi(
node->NodeBase::input(0).node()->template Cast<Phi>(),
node->template Cast<ValueNode>());
node->template Cast<ValueNode>(), state);
}
return ProcessResult::kContinue;
}
Expand Down Expand Up @@ -273,7 +273,8 @@ class MaglevPhiRepresentationSelector {

// Updates {old_untagging} to reflect that its Phi input has been untagged and
// that a different conversion is now needed.
ProcessResult UpdateUntaggingOfPhi(Phi* phi, ValueNode* old_untagging);
ProcessResult UpdateUntaggingOfPhi(Phi* phi, ValueNode* old_untagging,
const ProcessingState* state);

ProcessResult EmitUnconditionalDeopt(NodeBase* node, DeoptimizeReason reason);

Expand Down
29 changes: 29 additions & 0 deletions deps/v8/src/maglev/maglev-range-analysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,18 @@ class NodeRanges {
return *range;
}

void InitializeRangeIfMissing(BasicBlock* block, ValueNode* node,
Range range) {
DCHECK(ranges_initialized_.Contains(block->id()));
RangeMap& map = ranges_[block->id()];
if (!map.find(node)) {
map = map.insert(zone(), node, range);
TRACE_RANGE("Initializing in Block b" << block->id() << ": "
<< PrintNodeBrief(node) << ": "
<< range);
}
}

void UnionUpdate(BasicBlock* block, ValueNode* node, Range range) {
DCHECK(ranges_initialized_.Contains(block->id()));
RangeMap& map = ranges_[block->id()];
Expand Down Expand Up @@ -210,6 +222,15 @@ class RangeProcessor {
BlockProcessResult PreProcessBasicBlock(BasicBlock* block) {
current_block_ = block;
ranges_.EnsureMapExistsFor(block);
if (block->has_state() && block->state()->is_resumable_loop() &&
block->predecessor_count() == 1) {
// Resumable loop headers might not have a live forward predecessor: that
// part of the code might be dead even though the loop is still reachable
// via a resume point. Make sure we initialize phis in such case. If the
// loop has a live predecessor, ProcessPhis is called when processing that
// live predecessor, and this code is a no-op.
InitializeLoopPhisIfMissing(block);
}
return BlockProcessResult::kContinue;
}
BlockProcessResult PostProcessBasicBlock(BasicBlock* block) {
Expand Down Expand Up @@ -543,6 +564,14 @@ class RangeProcessor {
}
}

void InitializeLoopPhisIfMissing(BasicBlock* block) {
if (!block->has_phi()) return;
for (Phi* phi : *block->phis()) {
ranges_.InitializeRangeIfMissing(
block, phi, phi->is_int32() ? Range::Int32() : Range::All());
}
}

// Returns true if the loop reach a fixpoint.
bool ProcessLoopPhisBackedge(BasicBlock* block, BasicBlock* backedge_pred) {
if (!block->has_phi()) return true;
Expand Down
Loading
Loading