Commit fe757702 authored by Jaroslav Sevcik's avatar Jaroslav Sevcik Committed by Commit Bot

[turbofan] Only poison loads and branches participating in property access

This cuts down the perf cost on Octane from 18% to 13%. The baseline is the no mitigation
Octane score, the array access mitigation cost was about 4%. This means we would be
getting a bit more than 1/3 of the poisoning regression back.

Bug: chromium:856973, chromium:887213
Change-Id: Ibd99f66ae832c6080f2c2e5b33a1a7610907466f
Reviewed-on: https://chromium-review.googlesource.com/c/1251401Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Commit-Queue: Jaroslav Sevcik <jarin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#56409}
parent 6cf351e8
...@@ -67,20 +67,20 @@ FieldAccess AccessBuilder::ForBigIntBitfield() { ...@@ -67,20 +67,20 @@ FieldAccess AccessBuilder::ForBigIntBitfield() {
// static // static
FieldAccess AccessBuilder::ForJSObjectPropertiesOrHash() { FieldAccess AccessBuilder::ForJSObjectPropertiesOrHash() {
FieldAccess access = {kTaggedBase, JSObject::kPropertiesOrHashOffset, FieldAccess access = {kTaggedBase, JSObject::kPropertiesOrHashOffset,
MaybeHandle<Name>(), MaybeHandle<Map>(), MaybeHandle<Name>(), MaybeHandle<Map>(),
Type::Any(), MachineType::AnyTagged(), Type::Any(), MachineType::AnyTagged(),
kPointerWriteBarrier}; kPointerWriteBarrier, LoadSensitivity::kCritical};
return access; return access;
} }
// static // static
FieldAccess AccessBuilder::ForJSObjectElements() { FieldAccess AccessBuilder::ForJSObjectElements() {
FieldAccess access = {kTaggedBase, JSObject::kElementsOffset, FieldAccess access = {kTaggedBase, JSObject::kElementsOffset,
MaybeHandle<Name>(), MaybeHandle<Map>(), MaybeHandle<Name>(), MaybeHandle<Map>(),
Type::Internal(), MachineType::TaggedPointer(), Type::Internal(), MachineType::TaggedPointer(),
kPointerWriteBarrier}; kPointerWriteBarrier, LoadSensitivity::kCritical};
return access; return access;
} }
...@@ -494,7 +494,7 @@ FieldAccess AccessBuilder::ForFixedTypedArrayBaseBasePointer() { ...@@ -494,7 +494,7 @@ FieldAccess AccessBuilder::ForFixedTypedArrayBaseBasePointer() {
kTaggedBase, FixedTypedArrayBase::kBasePointerOffset, kTaggedBase, FixedTypedArrayBase::kBasePointerOffset,
MaybeHandle<Name>(), MaybeHandle<Map>(), MaybeHandle<Name>(), MaybeHandle<Map>(),
Type::OtherInternal(), MachineType::AnyTagged(), Type::OtherInternal(), MachineType::AnyTagged(),
kPointerWriteBarrier}; kPointerWriteBarrier, LoadSensitivity::kCritical};
return access; return access;
} }
...@@ -506,7 +506,8 @@ FieldAccess AccessBuilder::ForFixedTypedArrayBaseExternalPointer() { ...@@ -506,7 +506,8 @@ FieldAccess AccessBuilder::ForFixedTypedArrayBaseExternalPointer() {
MaybeHandle<Map>(), MaybeHandle<Map>(),
Type::ExternalPointer(), Type::ExternalPointer(),
MachineType::Pointer(), MachineType::Pointer(),
kNoWriteBarrier}; kNoWriteBarrier,
LoadSensitivity::kCritical};
return access; return access;
} }
...@@ -835,10 +836,10 @@ FieldAccess AccessBuilder::ForFixedArraySlot( ...@@ -835,10 +836,10 @@ FieldAccess AccessBuilder::ForFixedArraySlot(
// static // static
FieldAccess AccessBuilder::ForCellValue() { FieldAccess AccessBuilder::ForCellValue() {
FieldAccess access = {kTaggedBase, Cell::kValueOffset, FieldAccess access = {kTaggedBase, Cell::kValueOffset,
Handle<Name>(), MaybeHandle<Map>(), Handle<Name>(), MaybeHandle<Map>(),
Type::Any(), MachineType::AnyTagged(), Type::Any(), MachineType::AnyTagged(),
kFullWriteBarrier}; kFullWriteBarrier, LoadSensitivity::kCritical};
return access; return access;
} }
......
...@@ -1462,10 +1462,11 @@ void EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) { ...@@ -1462,10 +1462,11 @@ void EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) {
Node* map = __ HeapConstant(maps[i]); Node* map = __ HeapConstant(maps[i]);
Node* check = __ WordEqual(value_map, map); Node* check = __ WordEqual(value_map, map);
if (i == map_count - 1) { if (i == map_count - 1) {
__ GotoIfNot(check, &migrate); __ Branch(check, &done, &migrate, IsSafetyCheck::kCriticalSafetyCheck);
__ Goto(&done);
} else { } else {
__ GotoIf(check, &done); auto next_map = __ MakeLabel();
__ Branch(check, &done, &next_map, IsSafetyCheck::kCriticalSafetyCheck);
__ Bind(&next_map);
} }
} }
...@@ -1480,7 +1481,8 @@ void EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) { ...@@ -1480,7 +1481,8 @@ void EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) {
__ Int32Constant(Map::IsDeprecatedBit::kMask)), __ Int32Constant(Map::IsDeprecatedBit::kMask)),
__ Int32Constant(0)); __ Int32Constant(0));
__ DeoptimizeIf(DeoptimizeReason::kWrongMap, p.feedback(), __ DeoptimizeIf(DeoptimizeReason::kWrongMap, p.feedback(),
if_not_deprecated, frame_state); if_not_deprecated, frame_state,
IsSafetyCheck::kCriticalSafetyCheck);
Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow; Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow;
Runtime::FunctionId id = Runtime::kTryMigrateInstance; Runtime::FunctionId id = Runtime::kTryMigrateInstance;
...@@ -1491,7 +1493,7 @@ void EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) { ...@@ -1491,7 +1493,7 @@ void EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) {
__ Int32Constant(1), __ NoContextConstant()); __ Int32Constant(1), __ NoContextConstant());
Node* check = ObjectIsSmi(result); Node* check = ObjectIsSmi(result);
__ DeoptimizeIf(DeoptimizeReason::kInstanceMigrationFailed, p.feedback(), __ DeoptimizeIf(DeoptimizeReason::kInstanceMigrationFailed, p.feedback(),
check, frame_state); check, frame_state, IsSafetyCheck::kCriticalSafetyCheck);
} }
// Reload the current map of the {value}. // Reload the current map of the {value}.
...@@ -1503,9 +1505,11 @@ void EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) { ...@@ -1503,9 +1505,11 @@ void EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) {
Node* check = __ WordEqual(value_map, map); Node* check = __ WordEqual(value_map, map);
if (i == map_count - 1) { if (i == map_count - 1) {
__ DeoptimizeIfNot(DeoptimizeReason::kWrongMap, p.feedback(), check, __ DeoptimizeIfNot(DeoptimizeReason::kWrongMap, p.feedback(), check,
frame_state); frame_state, IsSafetyCheck::kCriticalSafetyCheck);
} else { } else {
__ GotoIf(check, &done); auto next_map = __ MakeLabel();
__ Branch(check, &done, &next_map, IsSafetyCheck::kCriticalSafetyCheck);
__ Bind(&next_map);
} }
} }
...@@ -1522,9 +1526,11 @@ void EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) { ...@@ -1522,9 +1526,11 @@ void EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) {
Node* check = __ WordEqual(value_map, map); Node* check = __ WordEqual(value_map, map);
if (i == map_count - 1) { if (i == map_count - 1) {
__ DeoptimizeIfNot(DeoptimizeReason::kWrongMap, p.feedback(), check, __ DeoptimizeIfNot(DeoptimizeReason::kWrongMap, p.feedback(), check,
frame_state); frame_state, IsSafetyCheck::kCriticalSafetyCheck);
} else { } else {
__ GotoIf(check, &done); auto next_map = __ MakeLabel();
__ Branch(check, &done, &next_map, IsSafetyCheck::kCriticalSafetyCheck);
__ Bind(&next_map);
} }
} }
__ Goto(&done); __ Goto(&done);
...@@ -1545,7 +1551,14 @@ Node* EffectControlLinearizer::LowerCompareMaps(Node* node) { ...@@ -1545,7 +1551,14 @@ Node* EffectControlLinearizer::LowerCompareMaps(Node* node) {
for (size_t i = 0; i < map_count; ++i) { for (size_t i = 0; i < map_count; ++i) {
Node* map = __ HeapConstant(maps[i]); Node* map = __ HeapConstant(maps[i]);
Node* check = __ WordEqual(value_map, map); Node* check = __ WordEqual(value_map, map);
__ GotoIf(check, &done, __ Int32Constant(1)); auto next_map = __ MakeLabel();
auto passed = __ MakeLabel();
__ Branch(check, &passed, &next_map, IsSafetyCheck::kCriticalSafetyCheck);
__ Bind(&passed);
__ Goto(&done, __ Int32Constant(1));
__ Bind(&next_map);
} }
__ Goto(&done, __ Int32Constant(0)); __ Goto(&done, __ Int32Constant(0));
......
...@@ -214,9 +214,11 @@ Node* GraphAssembler::Word32PoisonOnSpeculation(Node* value) { ...@@ -214,9 +214,11 @@ Node* GraphAssembler::Word32PoisonOnSpeculation(Node* value) {
Node* GraphAssembler::DeoptimizeIf(DeoptimizeReason reason, Node* GraphAssembler::DeoptimizeIf(DeoptimizeReason reason,
VectorSlotPair const& feedback, VectorSlotPair const& feedback,
Node* condition, Node* frame_state) { Node* condition, Node* frame_state,
IsSafetyCheck is_safety_check) {
return current_control_ = current_effect_ = graph()->NewNode( return current_control_ = current_effect_ = graph()->NewNode(
common()->DeoptimizeIf(DeoptimizeKind::kEager, reason, feedback), common()->DeoptimizeIf(DeoptimizeKind::kEager, reason, feedback,
is_safety_check),
condition, frame_state, current_effect_, current_control_); condition, frame_state, current_effect_, current_control_);
} }
...@@ -231,7 +233,8 @@ Node* GraphAssembler::DeoptimizeIfNot(DeoptimizeReason reason, ...@@ -231,7 +233,8 @@ Node* GraphAssembler::DeoptimizeIfNot(DeoptimizeReason reason,
} }
void GraphAssembler::Branch(Node* condition, GraphAssemblerLabel<0u>* if_true, void GraphAssembler::Branch(Node* condition, GraphAssemblerLabel<0u>* if_true,
GraphAssemblerLabel<0u>* if_false) { GraphAssemblerLabel<0u>* if_false,
IsSafetyCheck is_safety_check) {
DCHECK_NOT_NULL(current_control_); DCHECK_NOT_NULL(current_control_);
BranchHint hint = BranchHint::kNone; BranchHint hint = BranchHint::kNone;
...@@ -239,8 +242,8 @@ void GraphAssembler::Branch(Node* condition, GraphAssemblerLabel<0u>* if_true, ...@@ -239,8 +242,8 @@ void GraphAssembler::Branch(Node* condition, GraphAssemblerLabel<0u>* if_true,
hint = if_false->IsDeferred() ? BranchHint::kTrue : BranchHint::kFalse; hint = if_false->IsDeferred() ? BranchHint::kTrue : BranchHint::kFalse;
} }
Node* branch = Node* branch = graph()->NewNode(common()->Branch(hint, is_safety_check),
graph()->NewNode(common()->Branch(hint), condition, current_control_); condition, current_control_);
current_control_ = graph()->NewNode(common()->IfTrue(), branch); current_control_ = graph()->NewNode(common()->IfTrue(), branch);
MergeState(if_true); MergeState(if_true);
......
...@@ -234,8 +234,10 @@ class GraphAssembler { ...@@ -234,8 +234,10 @@ class GraphAssembler {
Node* Word32PoisonOnSpeculation(Node* value); Node* Word32PoisonOnSpeculation(Node* value);
Node* DeoptimizeIf(DeoptimizeReason reason, VectorSlotPair const& feedback, Node* DeoptimizeIf(
Node* condition, Node* frame_state); DeoptimizeReason reason, VectorSlotPair const& feedback, Node* condition,
Node* frame_state,
IsSafetyCheck is_safety_check = IsSafetyCheck::kSafetyCheck);
Node* DeoptimizeIfNot( Node* DeoptimizeIfNot(
DeoptimizeReason reason, VectorSlotPair const& feedback, Node* condition, DeoptimizeReason reason, VectorSlotPair const& feedback, Node* condition,
Node* frame_state, Node* frame_state,
...@@ -253,7 +255,8 @@ class GraphAssembler { ...@@ -253,7 +255,8 @@ class GraphAssembler {
void Goto(GraphAssemblerLabel<sizeof...(Vars)>* label, Vars...); void Goto(GraphAssemblerLabel<sizeof...(Vars)>* label, Vars...);
void Branch(Node* condition, GraphAssemblerLabel<0u>* if_true, void Branch(Node* condition, GraphAssemblerLabel<0u>* if_true,
GraphAssemblerLabel<0u>* if_false); GraphAssemblerLabel<0u>* if_false,
IsSafetyCheck is_safety_check = IsSafetyCheck::kNoSafetyCheck);
// Control helpers. // Control helpers.
// {GotoIf(c, l)} is equivalent to {Branch(c, l, templ);Bind(templ)}. // {GotoIf(c, l)} is equivalent to {Branch(c, l, templ);Bind(templ)}.
......
...@@ -916,9 +916,9 @@ PipelineCompilationJob::Status PipelineCompilationJob::PrepareJobImpl( ...@@ -916,9 +916,9 @@ PipelineCompilationJob::Status PipelineCompilationJob::PrepareJobImpl(
PoisoningMitigationLevel load_poisoning = PoisoningMitigationLevel load_poisoning =
PoisoningMitigationLevel::kDontPoison; PoisoningMitigationLevel::kDontPoison;
if (FLAG_untrusted_code_mitigations) { if (FLAG_untrusted_code_mitigations) {
// For partial mitigations, this can be changed to // For full mitigations, this can be changed to
// PoisoningMitigationLevel::kPoisonCriticalOnly. // PoisoningMitigationLevel::kPoisonAll.
load_poisoning = PoisoningMitigationLevel::kPoisonAll; load_poisoning = PoisoningMitigationLevel::kPoisonCriticalOnly;
} }
compilation_info()->SetPoisoningMitigationLevel(load_poisoning); compilation_info()->SetPoisoningMitigationLevel(load_poisoning);
......
...@@ -246,7 +246,8 @@ Node* PropertyAccessBuilder::BuildLoadDataField( ...@@ -246,7 +246,8 @@ Node* PropertyAccessBuilder::BuildLoadDataField(
MaybeHandle<Map>(), MaybeHandle<Map>(),
field_type, field_type,
MachineType::TypeForRepresentation(field_representation), MachineType::TypeForRepresentation(field_representation),
kFullWriteBarrier}; kFullWriteBarrier,
LoadSensitivity::kCritical};
if (field_representation == MachineRepresentation::kFloat64) { if (field_representation == MachineRepresentation::kFloat64) {
if (!field_index.is_inobject() || field_index.is_hidden_field() || if (!field_index.is_inobject() || field_index.is_hidden_field() ||
!FLAG_unbox_double_fields) { !FLAG_unbox_double_fields) {
...@@ -256,7 +257,8 @@ Node* PropertyAccessBuilder::BuildLoadDataField( ...@@ -256,7 +257,8 @@ Node* PropertyAccessBuilder::BuildLoadDataField(
MaybeHandle<Map>(), MaybeHandle<Map>(),
Type::OtherInternal(), Type::OtherInternal(),
MachineType::TaggedPointer(), MachineType::TaggedPointer(),
kPointerWriteBarrier}; kPointerWriteBarrier,
LoadSensitivity::kCritical};
storage = *effect = graph()->NewNode( storage = *effect = graph()->NewNode(
simplified()->LoadField(storage_access), storage, *effect, *control); simplified()->LoadField(storage_access), storage, *effect, *control);
field_access.offset = HeapNumber::kValueOffset; field_access.offset = HeapNumber::kValueOffset;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment