Commit 0c0ab3dc authored by Leszek Swirski's avatar Leszek Swirski Committed by Commit Bot

[ignition/turbofan] Use Switch node for Switch bytecode

Uses CheckSmi to force the switch argument to be a Smi, so that it can
be used as an input into a Switch node.

Change-Id: Ibec6beaeebc2168a3f80b86512c70a99d52f2575
Reviewed-on: https://chromium-review.googlesource.com/505621
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#45397}
parent 9fd599ef
......@@ -2165,24 +2165,25 @@ void BytecodeGraphBuilder::VisitJumpIfNotUndefinedConstant() {
void BytecodeGraphBuilder::VisitJumpLoop() { BuildJump(); }
void BytecodeGraphBuilder::VisitSwitchOnSmiNoFeedback() {
PrepareEagerCheckpoint();
Node* acc = environment()->LookupAccumulator();
void BytecodeGraphBuilder::BuildSwitchOnSmi(Node* condition) {
interpreter::JumpTableTargetOffsets offsets =
bytecode_iterator().GetJumpTableTargetOffsets();
for (const auto& entry : bytecode_iterator().GetJumpTableTargetOffsets()) {
// TODO(leszeks): This should be a switch, but under OSR we fail to type the
// input correctly so we have to do a JS strict equal instead.
NewBranch(
NewNode(javascript()->StrictEqual(CompareOperationHint::kSignedSmall),
acc, jsgraph()->SmiConstant(entry.case_value)));
{
NewSwitch(condition, offsets.size() + 1);
for (const auto& entry : offsets) {
SubEnvironment sub_environment(this);
NewIfTrue();
NewIfValue(entry.case_value);
MergeIntoSuccessorEnvironment(entry.target_offset);
}
NewIfFalse();
}
NewIfDefault();
}
void BytecodeGraphBuilder::VisitSwitchOnSmiNoFeedback() {
PrepareEagerCheckpoint();
Node* acc = environment()->LookupAccumulator();
Node* acc_smi = NewNode(simplified()->CheckSmi(), acc);
BuildSwitchOnSmi(acc_smi);
}
void BytecodeGraphBuilder::VisitStackCheck() {
......
......@@ -91,11 +91,16 @@ class BytecodeGraphBuilder {
// Helpers to create new control nodes.
Node* NewIfTrue() { return NewNode(common()->IfTrue()); }
Node* NewIfFalse() { return NewNode(common()->IfFalse()); }
Node* NewIfValue(int32_t value) { return NewNode(common()->IfValue(value)); }
Node* NewIfDefault() { return NewNode(common()->IfDefault()); }
Node* NewMerge() { return NewNode(common()->Merge(1), true); }
Node* NewLoop() { return NewNode(common()->Loop(1), true); }
Node* NewBranch(Node* condition, BranchHint hint = BranchHint::kNone) {
return NewNode(common()->Branch(hint), condition);
}
Node* NewSwitch(Node* condition, int control_output_count) {
return NewNode(common()->Switch(control_output_count), condition);
}
// Creates a new Phi node having {count} input values.
Node* NewPhi(int count, Node* input, Node* control);
......@@ -222,6 +227,8 @@ class BytecodeGraphBuilder {
void BuildJumpIfNotHole();
void BuildJumpIfJSReceiver();
void BuildSwitchOnSmi(Node* condition);
// Simulates control flow by forward-propagating environments.
void MergeIntoSuccessorEnvironment(int target_offset);
void BuildLoopHeaderEnvironment(int current_offset);
......
......@@ -237,6 +237,15 @@ JumpTableTargetOffsets::iterator JumpTableTargetOffsets::end() const {
return iterator(case_value_base_ + table_size_, table_start_ + table_size_,
table_start_ + table_size_, accessor_);
}
int JumpTableTargetOffsets::size() const {
int ret = 0;
// TODO(leszeks): Is there a more efficient way of doing this than iterating?
for (const auto& entry : *this) {
USE(entry);
ret++;
}
return ret;
}
JumpTableTargetOffsets::iterator::iterator(
int case_value, int table_offset, int table_end,
......
......@@ -51,6 +51,8 @@ class V8_EXPORT_PRIVATE JumpTableTargetOffsets final {
iterator begin() const;
iterator end() const;
int size() const;
private:
const BytecodeArrayAccessor* accessor_;
int table_start_;
......
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