Commit 957ac364 authored by Tobias Tebbi's avatar Tobias Tebbi Committed by Commit Bot

[turbofan] disable indirect jumps in Turbofan generated switches

Bug: 
Change-Id: I326bf518f895e7c030376210e7797f3dd4a9ae1f
Reviewed-on: https://chromium-review.googlesource.com/873643Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50984}
parent 630a992b
...@@ -1980,24 +1980,26 @@ void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) { ...@@ -1980,24 +1980,26 @@ void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) {
InstructionOperand value_operand = g.UseRegister(node->InputAt(0)); InstructionOperand value_operand = g.UseRegister(node->InputAt(0));
// Emit either ArchTableSwitch or ArchLookupSwitch. // Emit either ArchTableSwitch or ArchLookupSwitch.
static const size_t kMaxTableSwitchValueRange = 2 << 16; if (!FLAG_turbo_disable_switch_jump_table) {
size_t table_space_cost = 4 + sw.value_range; static const size_t kMaxTableSwitchValueRange = 2 << 16;
size_t table_time_cost = 3; size_t table_space_cost = 4 + sw.value_range;
size_t lookup_space_cost = 3 + 2 * sw.case_count; size_t table_time_cost = 3;
size_t lookup_time_cost = sw.case_count; size_t lookup_space_cost = 3 + 2 * sw.case_count;
if (sw.case_count > 0 && size_t lookup_time_cost = sw.case_count;
table_space_cost + 3 * table_time_cost <= if (sw.case_count > 0 &&
lookup_space_cost + 3 * lookup_time_cost && table_space_cost + 3 * table_time_cost <=
sw.min_value > std::numeric_limits<int32_t>::min() && lookup_space_cost + 3 * lookup_time_cost &&
sw.value_range <= kMaxTableSwitchValueRange) { sw.min_value > std::numeric_limits<int32_t>::min() &&
InstructionOperand index_operand = value_operand; sw.value_range <= kMaxTableSwitchValueRange) {
if (sw.min_value) { InstructionOperand index_operand = value_operand;
index_operand = g.TempRegister(); if (sw.min_value) {
Emit(kArmSub | AddressingModeField::encode(kMode_Operand2_I), index_operand = g.TempRegister();
index_operand, value_operand, g.TempImmediate(sw.min_value)); Emit(kArmSub | AddressingModeField::encode(kMode_Operand2_I),
index_operand, value_operand, g.TempImmediate(sw.min_value));
}
// Generate a table lookup.
return EmitTableSwitch(sw, index_operand);
} }
// Generate a table lookup.
return EmitTableSwitch(sw, index_operand);
} }
// Generate a sequence of conditional jumps. // Generate a sequence of conditional jumps.
......
...@@ -2361,24 +2361,26 @@ void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) { ...@@ -2361,24 +2361,26 @@ void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) {
InstructionOperand value_operand = g.UseRegister(node->InputAt(0)); InstructionOperand value_operand = g.UseRegister(node->InputAt(0));
// Emit either ArchTableSwitch or ArchLookupSwitch. // Emit either ArchTableSwitch or ArchLookupSwitch.
static const size_t kMaxTableSwitchValueRange = 2 << 16; if (!FLAG_turbo_disable_switch_jump_table) {
size_t table_space_cost = 4 + sw.value_range; static const size_t kMaxTableSwitchValueRange = 2 << 16;
size_t table_time_cost = 3; size_t table_space_cost = 4 + sw.value_range;
size_t lookup_space_cost = 3 + 2 * sw.case_count; size_t table_time_cost = 3;
size_t lookup_time_cost = sw.case_count; size_t lookup_space_cost = 3 + 2 * sw.case_count;
if (sw.case_count > 0 && size_t lookup_time_cost = sw.case_count;
table_space_cost + 3 * table_time_cost <= if (sw.case_count > 0 &&
lookup_space_cost + 3 * lookup_time_cost && table_space_cost + 3 * table_time_cost <=
sw.min_value > std::numeric_limits<int32_t>::min() && lookup_space_cost + 3 * lookup_time_cost &&
sw.value_range <= kMaxTableSwitchValueRange) { sw.min_value > std::numeric_limits<int32_t>::min() &&
InstructionOperand index_operand = value_operand; sw.value_range <= kMaxTableSwitchValueRange) {
if (sw.min_value) { InstructionOperand index_operand = value_operand;
index_operand = g.TempRegister(); if (sw.min_value) {
Emit(kArm64Sub32, index_operand, value_operand, index_operand = g.TempRegister();
g.TempImmediate(sw.min_value)); Emit(kArm64Sub32, index_operand, value_operand,
g.TempImmediate(sw.min_value));
}
// Generate a table lookup.
return EmitTableSwitch(sw, index_operand);
} }
// Generate a table lookup.
return EmitTableSwitch(sw, index_operand);
} }
// Generate a sequence of conditional jumps. // Generate a sequence of conditional jumps.
......
...@@ -1431,24 +1431,26 @@ void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) { ...@@ -1431,24 +1431,26 @@ void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) {
InstructionOperand value_operand = g.UseRegister(node->InputAt(0)); InstructionOperand value_operand = g.UseRegister(node->InputAt(0));
// Emit either ArchTableSwitch or ArchLookupSwitch. // Emit either ArchTableSwitch or ArchLookupSwitch.
static const size_t kMaxTableSwitchValueRange = 2 << 16; if (!FLAG_turbo_disable_switch_jump_table) {
size_t table_space_cost = 4 + sw.value_range; static const size_t kMaxTableSwitchValueRange = 2 << 16;
size_t table_time_cost = 3; size_t table_space_cost = 4 + sw.value_range;
size_t lookup_space_cost = 3 + 2 * sw.case_count; size_t table_time_cost = 3;
size_t lookup_time_cost = sw.case_count; size_t lookup_space_cost = 3 + 2 * sw.case_count;
if (sw.case_count > 4 && size_t lookup_time_cost = sw.case_count;
table_space_cost + 3 * table_time_cost <= if (sw.case_count > 4 &&
lookup_space_cost + 3 * lookup_time_cost && table_space_cost + 3 * table_time_cost <=
sw.min_value > std::numeric_limits<int32_t>::min() && lookup_space_cost + 3 * lookup_time_cost &&
sw.value_range <= kMaxTableSwitchValueRange) { sw.min_value > std::numeric_limits<int32_t>::min() &&
InstructionOperand index_operand = value_operand; sw.value_range <= kMaxTableSwitchValueRange) {
if (sw.min_value) { InstructionOperand index_operand = value_operand;
index_operand = g.TempRegister(); if (sw.min_value) {
Emit(kIA32Lea | AddressingModeField::encode(kMode_MRI), index_operand, index_operand = g.TempRegister();
value_operand, g.TempImmediate(-sw.min_value)); Emit(kIA32Lea | AddressingModeField::encode(kMode_MRI), index_operand,
value_operand, g.TempImmediate(-sw.min_value));
}
// Generate a table lookup.
return EmitTableSwitch(sw, index_operand);
} }
// Generate a table lookup.
return EmitTableSwitch(sw, index_operand);
} }
// Generate a sequence of conditional jumps. // Generate a sequence of conditional jumps.
......
...@@ -1608,24 +1608,26 @@ void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) { ...@@ -1608,24 +1608,26 @@ void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) {
InstructionOperand value_operand = g.UseRegister(node->InputAt(0)); InstructionOperand value_operand = g.UseRegister(node->InputAt(0));
// Emit either ArchTableSwitch or ArchLookupSwitch. // Emit either ArchTableSwitch or ArchLookupSwitch.
static const size_t kMaxTableSwitchValueRange = 2 << 16; if (!FLAG_turbo_disable_switch_jump_table) {
size_t table_space_cost = 9 + sw.value_range; static const size_t kMaxTableSwitchValueRange = 2 << 16;
size_t table_time_cost = 3; size_t table_space_cost = 9 + sw.value_range;
size_t lookup_space_cost = 2 + 2 * sw.case_count; size_t table_time_cost = 3;
size_t lookup_time_cost = sw.case_count; size_t lookup_space_cost = 2 + 2 * sw.case_count;
if (sw.case_count > 0 && size_t lookup_time_cost = sw.case_count;
table_space_cost + 3 * table_time_cost <= if (sw.case_count > 0 &&
lookup_space_cost + 3 * lookup_time_cost && table_space_cost + 3 * table_time_cost <=
sw.min_value > std::numeric_limits<int32_t>::min() && lookup_space_cost + 3 * lookup_time_cost &&
sw.value_range <= kMaxTableSwitchValueRange) { sw.min_value > std::numeric_limits<int32_t>::min() &&
InstructionOperand index_operand = value_operand; sw.value_range <= kMaxTableSwitchValueRange) {
if (sw.min_value) { InstructionOperand index_operand = value_operand;
index_operand = g.TempRegister(); if (sw.min_value) {
Emit(kMipsSub, index_operand, value_operand, index_operand = g.TempRegister();
g.TempImmediate(sw.min_value)); Emit(kMipsSub, index_operand, value_operand,
g.TempImmediate(sw.min_value));
}
// Generate a table lookup.
return EmitTableSwitch(sw, index_operand);
} }
// Generate a table lookup.
return EmitTableSwitch(sw, index_operand);
} }
// Generate a sequence of conditional jumps. // Generate a sequence of conditional jumps.
......
...@@ -2216,24 +2216,26 @@ void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) { ...@@ -2216,24 +2216,26 @@ void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) {
InstructionOperand value_operand = g.UseRegister(node->InputAt(0)); InstructionOperand value_operand = g.UseRegister(node->InputAt(0));
// Emit either ArchTableSwitch or ArchLookupSwitch. // Emit either ArchTableSwitch or ArchLookupSwitch.
static const size_t kMaxTableSwitchValueRange = 2 << 16; if (!FLAG_turbo_disable_switch_jump_table) {
size_t table_space_cost = 10 + 2 * sw.value_range; static const size_t kMaxTableSwitchValueRange = 2 << 16;
size_t table_time_cost = 3; size_t table_space_cost = 10 + 2 * sw.value_range;
size_t lookup_space_cost = 2 + 2 * sw.case_count; size_t table_time_cost = 3;
size_t lookup_time_cost = sw.case_count; size_t lookup_space_cost = 2 + 2 * sw.case_count;
if (sw.case_count > 0 && size_t lookup_time_cost = sw.case_count;
table_space_cost + 3 * table_time_cost <= if (sw.case_count > 0 &&
lookup_space_cost + 3 * lookup_time_cost && table_space_cost + 3 * table_time_cost <=
sw.min_value > std::numeric_limits<int32_t>::min() && lookup_space_cost + 3 * lookup_time_cost &&
sw.value_range <= kMaxTableSwitchValueRange) { sw.min_value > std::numeric_limits<int32_t>::min() &&
InstructionOperand index_operand = value_operand; sw.value_range <= kMaxTableSwitchValueRange) {
if (sw.min_value) { InstructionOperand index_operand = value_operand;
index_operand = g.TempRegister(); if (sw.min_value) {
Emit(kMips64Sub, index_operand, value_operand, index_operand = g.TempRegister();
g.TempImmediate(sw.min_value)); Emit(kMips64Sub, index_operand, value_operand,
g.TempImmediate(sw.min_value));
}
// Generate a table lookup.
return EmitTableSwitch(sw, index_operand);
} }
// Generate a table lookup.
return EmitTableSwitch(sw, index_operand);
} }
// Generate a sequence of conditional jumps. // Generate a sequence of conditional jumps.
......
...@@ -1762,24 +1762,26 @@ void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) { ...@@ -1762,24 +1762,26 @@ void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) {
InstructionOperand value_operand = g.UseRegister(node->InputAt(0)); InstructionOperand value_operand = g.UseRegister(node->InputAt(0));
// Emit either ArchTableSwitch or ArchLookupSwitch. // Emit either ArchTableSwitch or ArchLookupSwitch.
static const size_t kMaxTableSwitchValueRange = 2 << 16; if (!FLAG_turbo_disable_switch_jump_table) {
size_t table_space_cost = 4 + sw.value_range; static const size_t kMaxTableSwitchValueRange = 2 << 16;
size_t table_time_cost = 3; size_t table_space_cost = 4 + sw.value_range;
size_t lookup_space_cost = 3 + 2 * sw.case_count; size_t table_time_cost = 3;
size_t lookup_time_cost = sw.case_count; size_t lookup_space_cost = 3 + 2 * sw.case_count;
if (sw.case_count > 0 && size_t lookup_time_cost = sw.case_count;
table_space_cost + 3 * table_time_cost <= if (sw.case_count > 0 &&
lookup_space_cost + 3 * lookup_time_cost && table_space_cost + 3 * table_time_cost <=
sw.min_value > std::numeric_limits<int32_t>::min() && lookup_space_cost + 3 * lookup_time_cost &&
sw.value_range <= kMaxTableSwitchValueRange) { sw.min_value > std::numeric_limits<int32_t>::min() &&
InstructionOperand index_operand = value_operand; sw.value_range <= kMaxTableSwitchValueRange) {
if (sw.min_value) { InstructionOperand index_operand = value_operand;
index_operand = g.TempRegister(); if (sw.min_value) {
Emit(kPPC_Sub, index_operand, value_operand, index_operand = g.TempRegister();
g.TempImmediate(sw.min_value)); Emit(kPPC_Sub, index_operand, value_operand,
g.TempImmediate(sw.min_value));
}
// Generate a table lookup.
return EmitTableSwitch(sw, index_operand);
} }
// Generate a table lookup.
return EmitTableSwitch(sw, index_operand);
} }
// Generate a sequence of conditional jumps. // Generate a sequence of conditional jumps.
......
...@@ -2138,22 +2138,23 @@ void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) { ...@@ -2138,22 +2138,23 @@ void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) {
InstructionOperand value_operand = g.UseRegister(node->InputAt(0)); InstructionOperand value_operand = g.UseRegister(node->InputAt(0));
// Emit either ArchTableSwitch or ArchLookupSwitch. // Emit either ArchTableSwitch or ArchLookupSwitch.
static const size_t kMaxTableSwitchValueRange = 2 << 16; if (!FLAG_turbo_disable_switch_jump_table) {
size_t table_space_cost = 4 + sw.value_range; static const size_t kMaxTableSwitchValueRange = 2 << 16;
size_t table_time_cost = 3; size_t table_space_cost = 4 + sw.value_range;
size_t lookup_space_cost = 3 + 2 * sw.case_count; size_t table_time_cost = 3;
size_t lookup_time_cost = sw.case_count; size_t lookup_space_cost = 3 + 2 * sw.case_count;
if (sw.case_count > 0 && size_t lookup_time_cost = sw.case_count;
table_space_cost + 3 * table_time_cost <= if (sw.case_count > 0 &&
lookup_space_cost + 3 * lookup_time_cost && table_space_cost + 3 * table_time_cost <=
sw.min_value > std::numeric_limits<int32_t>::min() && lookup_space_cost + 3 * lookup_time_cost &&
sw.value_range <= kMaxTableSwitchValueRange) { sw.min_value > std::numeric_limits<int32_t>::min() &&
InstructionOperand index_operand = value_operand; sw.value_range <= kMaxTableSwitchValueRange) {
if (sw.min_value) { InstructionOperand index_operand = value_operand;
index_operand = g.TempRegister(); if (sw.min_value) {
Emit(kS390_Lay | AddressingModeField::encode(kMode_MRI), index_operand, index_operand = g.TempRegister();
value_operand, g.TempImmediate(-sw.min_value)); Emit(kS390_Lay | AddressingModeField::encode(kMode_MRI), index_operand,
} value_operand, g.TempImmediate(-sw.min_value));
}
#if V8_TARGET_ARCH_S390X #if V8_TARGET_ARCH_S390X
InstructionOperand index_operand_zero_ext = g.TempRegister(); InstructionOperand index_operand_zero_ext = g.TempRegister();
Emit(kS390_Uint32ToUint64, index_operand_zero_ext, index_operand); Emit(kS390_Uint32ToUint64, index_operand_zero_ext, index_operand);
...@@ -2162,6 +2163,7 @@ void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) { ...@@ -2162,6 +2163,7 @@ void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) {
// Generate a table lookup. // Generate a table lookup.
return EmitTableSwitch(sw, index_operand); return EmitTableSwitch(sw, index_operand);
} }
}
// Generate a sequence of conditional jumps. // Generate a sequence of conditional jumps.
return EmitLookupSwitch(sw, value_operand); return EmitLookupSwitch(sw, value_operand);
......
...@@ -1959,27 +1959,30 @@ void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) { ...@@ -1959,27 +1959,30 @@ void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) {
InstructionOperand value_operand = g.UseRegister(node->InputAt(0)); InstructionOperand value_operand = g.UseRegister(node->InputAt(0));
// Emit either ArchTableSwitch or ArchLookupSwitch. // Emit either ArchTableSwitch or ArchLookupSwitch.
static const size_t kMaxTableSwitchValueRange = 2 << 16; if (!FLAG_turbo_disable_switch_jump_table) {
size_t table_space_cost = 4 + sw.value_range; static const size_t kMaxTableSwitchValueRange = 2 << 16;
size_t table_time_cost = 3; size_t table_space_cost = 4 + sw.value_range;
size_t lookup_space_cost = 3 + 2 * sw.case_count; size_t table_time_cost = 3;
size_t lookup_time_cost = sw.case_count; size_t lookup_space_cost = 3 + 2 * sw.case_count;
if (sw.case_count > 4 && size_t lookup_time_cost = sw.case_count;
table_space_cost + 3 * table_time_cost <= if (sw.case_count > 4 &&
lookup_space_cost + 3 * lookup_time_cost && table_space_cost + 3 * table_time_cost <=
sw.min_value > std::numeric_limits<int32_t>::min() && lookup_space_cost + 3 * lookup_time_cost &&
sw.value_range <= kMaxTableSwitchValueRange) { sw.min_value > std::numeric_limits<int32_t>::min() &&
InstructionOperand index_operand = g.TempRegister(); sw.value_range <= kMaxTableSwitchValueRange) {
if (sw.min_value) { InstructionOperand index_operand = g.TempRegister();
// The leal automatically zero extends, so result is a valid 64-bit index. if (sw.min_value) {
Emit(kX64Lea32 | AddressingModeField::encode(kMode_MRI), index_operand, // The leal automatically zero extends, so result is a valid 64-bit
value_operand, g.TempImmediate(-sw.min_value)); // index.
} else { Emit(kX64Lea32 | AddressingModeField::encode(kMode_MRI), index_operand,
// Zero extend, because we use it as 64-bit index into the jump table. value_operand, g.TempImmediate(-sw.min_value));
Emit(kX64Movl, index_operand, value_operand); } else {
// Zero extend, because we use it as 64-bit index into the jump table.
Emit(kX64Movl, index_operand, value_operand);
}
// Generate a table lookup.
return EmitTableSwitch(sw, index_operand);
} }
// Generate a table lookup.
return EmitTableSwitch(sw, index_operand);
} }
// Generate a sequence of conditional jumps. // Generate a sequence of conditional jumps.
......
...@@ -490,6 +490,10 @@ DEFINE_BOOL(untrusted_code_mitigations, V8_DEFAULT_UNTRUSTED_CODE_MITIGATIONS, ...@@ -490,6 +490,10 @@ DEFINE_BOOL(untrusted_code_mitigations, V8_DEFAULT_UNTRUSTED_CODE_MITIGATIONS,
"Enable mitigations for executing untrusted code") "Enable mitigations for executing untrusted code")
#undef V8_DEFAULT_UNTRUSTED_CODE_MITIGATIONS #undef V8_DEFAULT_UNTRUSTED_CODE_MITIGATIONS
DEFINE_BOOL(turbo_disable_switch_jump_table, false,
"do not emit jump-tables in Turbofan")
DEFINE_IMPLICATION(untrusted_code_mitigations, turbo_disable_switch_jump_table)
// Flags to help platform porters // Flags to help platform porters
DEFINE_BOOL(minimal, false, DEFINE_BOOL(minimal, false,
"simplifies execution model to make porting " "simplifies execution model to make porting "
......
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