Commit 935340a4 authored by klaasb's avatar klaasb Committed by Commit bot

[interpreter] VisitForTest for bytecode generator

Adds TestResultScope and uses it to directly jump/fall through to the
correct branch in expressions used as branch conditions.
Should enable nicer TurboFan-graphs for easier control-flow
transformations in the future.

BUG=v8:4280
LOG=n

Review-Url: https://codereview.chromium.org/2242463002
Cr-Commit-Position: refs/heads/master@{#38634}
parent 160d0a18
......@@ -1381,6 +1381,7 @@ v8_source_set("v8_base") {
"src/interpreter/bytecode-flags.h",
"src/interpreter/bytecode-generator.cc",
"src/interpreter/bytecode-generator.h",
"src/interpreter/bytecode-label.cc",
"src/interpreter/bytecode-label.h",
"src/interpreter/bytecode-peephole-optimizer.cc",
"src/interpreter/bytecode-peephole-optimizer.h",
......
This diff is collapsed.
......@@ -48,6 +48,9 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
class GlobalDeclarationsBuilder;
class RegisterResultScope;
class RegisterAllocationScope;
class TestResultScope;
enum class TestFallthrough { kThen, kElse, kNone };
void GenerateBytecode();
void GenerateBytecodeBody();
......@@ -162,6 +165,8 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
MUST_USE_RESULT Register VisitForRegisterValue(Expression* expr);
void VisitForRegisterValue(Expression* expr, Register destination);
void VisitForEffect(Expression* expr);
void VisitForTest(Expression* expr, BytecodeLabels* then_labels,
BytecodeLabels* else_labels, TestFallthrough fallthrough);
// Methods for tracking and remapping register.
void RecordStoreToRegister(Register reg);
......
// Copyright 2016 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.
#include "src/interpreter/bytecode-label.h"
#include "src/interpreter/bytecode-array-builder.h"
namespace v8 {
namespace internal {
namespace interpreter {
BytecodeLabel* BytecodeLabels::New() {
labels_.push_back(BytecodeLabel());
return &labels_.back();
}
void BytecodeLabels::Bind(BytecodeArrayBuilder* builder) {
for (auto label : labels_) {
builder->Bind(&label);
}
}
} // namespace interpreter
} // namespace internal
} // namespace v8
......@@ -5,10 +5,14 @@
#ifndef V8_INTERPRETER_BYTECODE_LABEL_H_
#define V8_INTERPRETER_BYTECODE_LABEL_H_
#include "src/zone-containers.h"
namespace v8 {
namespace internal {
namespace interpreter {
class BytecodeArrayBuilder;
// A label representing a branch target in a bytecode array. When a
// label is bound, it represents a known position in the bytecode
// array. For labels that are forward references there can be at most
......@@ -49,6 +53,21 @@ class BytecodeLabel final {
friend class BytecodeArrayWriter;
};
// Class representing a branch target of multiple jumps.
class BytecodeLabels {
public:
explicit BytecodeLabels(Zone* zone) : labels_(zone) {}
BytecodeLabel* New();
void Bind(BytecodeArrayBuilder* builder);
private:
ZoneVector<BytecodeLabel> labels_;
DISALLOW_COPY_AND_ASSIGN(BytecodeLabels);
};
} // namespace interpreter
} // namespace internal
} // namespace v8
......
......@@ -985,6 +985,7 @@
'interpreter/bytecode-flags.h',
'interpreter/bytecode-generator.cc',
'interpreter/bytecode-generator.h',
'interpreter/bytecode-label.cc',
'interpreter/bytecode-label.h',
'interpreter/bytecode-peephole-optimizer.cc',
'interpreter/bytecode-peephole-optimizer.h',
......
......@@ -18,10 +18,10 @@ bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), U8(1),
B(Star), R(0),
/* 45 S> */ B(JumpIfToBooleanTrue), U8(5),
/* 45 S> */ B(JumpIfToBooleanTrue), U8(7),
B(LdaZero),
/* 56 E> */ B(TestLessThan), R(0),
B(JumpIfToBooleanFalse), U8(5),
B(JumpIfFalse), U8(5),
/* 63 S> */ B(LdaSmi), U8(1),
/* 75 S> */ B(Return),
B(LdaUndefined),
......@@ -43,10 +43,10 @@ bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), U8(1),
B(Star), R(0),
/* 45 S> */ B(JumpIfToBooleanFalse), U8(5),
/* 45 S> */ B(JumpIfToBooleanFalse), U8(10),
B(LdaZero),
/* 56 E> */ B(TestLessThan), R(0),
B(JumpIfToBooleanFalse), U8(5),
B(JumpIfFalse), U8(5),
/* 63 S> */ B(LdaSmi), U8(1),
/* 75 S> */ B(Return),
B(LdaUndefined),
......@@ -68,10 +68,10 @@ bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), U8(1),
B(Star), R(0),
/* 45 S> */ B(JumpIfToBooleanTrue), U8(5),
/* 45 S> */ B(JumpIfToBooleanTrue), U8(7),
B(LdaZero),
/* 57 E> */ B(TestLessThan), R(0),
B(JumpIfToBooleanFalse), U8(6),
B(JumpIfFalse), U8(6),
B(LdaSmi), U8(2),
B(Jump), U8(4),
B(LdaSmi), U8(3),
......
......@@ -13,14 +13,10 @@ snippet: "
"
frame size: 0
parameter count: 1
bytecode array length: 12
bytecode array length: 4
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 34 S> */ B(LdaSmi), U8(1),
B(JumpIfToBooleanFalse), U8(6),
B(LdaSmi), U8(2),
B(Jump), U8(4),
B(LdaSmi), U8(3),
/* 34 S> */ B(LdaSmi), U8(2),
/* 52 S> */ B(Return),
]
constant pool: [
......@@ -34,19 +30,58 @@ snippet: "
"
frame size: 0
parameter count: 1
bytecode array length: 20
bytecode array length: 4
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 34 S> */ B(LdaSmi), U8(1),
B(JumpIfToBooleanFalse), U8(14),
/* 34 S> */ B(LdaSmi), U8(3),
/* 60 S> */ B(Return),
]
constant pool: [
]
handlers: [
]
---
snippet: "
return 0 < 1 ? 2 : 3;
"
frame size: 1
parameter count: 1
bytecode array length: 17
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 34 S> */ B(LdaZero),
B(Star), R(0),
B(LdaSmi), U8(1),
/* 43 E> */ B(TestLessThan), R(0),
B(JumpIfFalse), U8(6),
B(LdaSmi), U8(2),
B(JumpIfToBooleanFalse), U8(6),
B(LdaSmi), U8(3),
B(Jump), U8(4),
B(LdaSmi), U8(4),
B(LdaSmi), U8(3),
/* 56 S> */ B(Return),
]
constant pool: [
]
handlers: [
]
---
snippet: "
var x = 0;
return x ? 2 : 3;
"
frame size: 1
parameter count: 1
bytecode array length: 13
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaZero),
B(Star), R(0),
/* 45 S> */ B(JumpIfToBooleanFalse), U8(6),
B(LdaSmi), U8(2),
B(Jump), U8(4),
B(LdaSmi), U8(5),
/* 60 S> */ B(Return),
B(LdaSmi), U8(3),
/* 63 S> */ B(Return),
]
constant pool: [
]
......
......@@ -13,7 +13,7 @@ snippet: "
"
frame size: 16
parameter count: 1
bytecode array length: 283
bytecode array length: 282
bytecodes: [
/* 30 E> */ B(StackCheck),
B(LdaZero),
......@@ -70,11 +70,10 @@ bytecodes: [
B(Star), R(11),
B(LdaZero),
B(TestEqualStrict), R(3),
B(JumpIfTrue), U8(5),
B(JumpIfTrue), U8(123),
B(LdaUndefined),
B(TestEqualStrict), R(1),
B(ToBooleanLogicalNot),
B(JumpIfFalse), U8(118),
B(JumpIfTrue), U8(118),
B(LdrNamedProperty), R(1), U8(6), U8(13), R(5),
B(LdaNull),
B(TestEqual), R(5),
......@@ -144,7 +143,7 @@ constant pool: [
handlers: [
[7, 121, 127],
[10, 80, 82],
[200, 210, 212],
[199, 209, 211],
]
---
......@@ -154,7 +153,7 @@ snippet: "
"
frame size: 17
parameter count: 1
bytecode array length: 296
bytecode array length: 295
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaConstant), U8(0),
......@@ -213,11 +212,10 @@ bytecodes: [
B(Star), R(12),
B(LdaZero),
B(TestEqualStrict), R(3),
B(JumpIfTrue), U8(5),
B(JumpIfTrue), U8(123),
B(LdaUndefined),
B(TestEqualStrict), R(1),
B(ToBooleanLogicalNot),
B(JumpIfFalse), U8(118),
B(JumpIfTrue), U8(118),
B(LdrNamedProperty), R(1), U8(6), U8(13), R(5),
B(LdaNull),
B(TestEqual), R(5),
......@@ -292,7 +290,7 @@ constant pool: [
handlers: [
[11, 124, 130],
[14, 83, 85],
[204, 214, 216],
[203, 213, 215],
]
---
......@@ -304,7 +302,7 @@ snippet: "
"
frame size: 16
parameter count: 1
bytecode array length: 299
bytecode array length: 298
bytecodes: [
/* 30 E> */ B(StackCheck),
B(LdaZero),
......@@ -369,11 +367,10 @@ bytecodes: [
B(Star), R(11),
B(LdaZero),
B(TestEqualStrict), R(3),
B(JumpIfTrue), U8(5),
B(JumpIfTrue), U8(123),
B(LdaUndefined),
B(TestEqualStrict), R(1),
B(ToBooleanLogicalNot),
B(JumpIfFalse), U8(118),
B(JumpIfTrue), U8(118),
B(LdrNamedProperty), R(1), U8(6), U8(13), R(5),
B(LdaNull),
B(TestEqual), R(5),
......@@ -443,7 +440,7 @@ constant pool: [
handlers: [
[7, 137, 143],
[10, 96, 98],
[216, 226, 228],
[215, 225, 227],
]
---
......@@ -453,7 +450,7 @@ snippet: "
"
frame size: 15
parameter count: 1
bytecode array length: 309
bytecode array length: 308
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1), R(8),
......@@ -515,11 +512,10 @@ bytecodes: [
B(Star), R(10),
B(LdaZero),
B(TestEqualStrict), R(2),
B(JumpIfTrue), U8(5),
B(JumpIfTrue), U8(123),
B(LdaUndefined),
B(TestEqualStrict), R(0),
B(ToBooleanLogicalNot),
B(JumpIfFalse), U8(118),
B(JumpIfTrue), U8(118),
B(LdrNamedProperty), R(0), U8(8), U8(17), R(4),
B(LdaNull),
B(TestEqual), R(4),
......@@ -596,6 +592,6 @@ constant pool: [
handlers: [
[15, 137, 143],
[18, 96, 98],
[217, 227, 229],
[216, 226, 228],
]
......@@ -264,7 +264,7 @@ snippet: "
"
frame size: 18
parameter count: 1
bytecode array length: 769
bytecode array length: 768
bytecodes: [
B(Ldar), R(new_target),
B(JumpIfUndefined), U8(26),
......@@ -316,7 +316,7 @@ bytecodes: [
B(Star), R(6),
B(LdaZero),
B(Star), R(5),
B(JumpConstant), U8(16),
B(JumpConstant), U8(17),
B(Ldar), R(10),
/* 11 E> */ B(Throw),
B(LdaConstant), U8(0),
......@@ -452,12 +452,11 @@ bytecodes: [
B(LdrContextSlot), R(1), U8(9), R(11),
B(LdaZero),
B(TestEqualStrict), R(11),
B(JumpIfTrue), U8(9),
B(JumpIfTrueConstant), U8(15),
B(LdrContextSlot), R(1), U8(7), R(11),
B(LdaUndefined),
B(TestEqualStrict), R(11),
B(ToBooleanLogicalNot),
B(JumpIfFalseConstant), U8(15),
B(JumpIfTrueConstant), U8(16),
B(LdrContextSlot), R(1), U8(7), R(11),
B(LdaNamedProperty), R(11), U8(12), U8(13),
B(StaContextSlot), R(1), U8(11),
......@@ -596,11 +595,12 @@ constant pool: [
InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
kInstanceTypeDontCare,
kInstanceTypeDontCare,
kInstanceTypeDontCare,
]
handlers: [
[41, 688, 694],
[41, 687, 693],
[147, 442, 448],
[150, 396, 398],
[545, 557, 559],
[544, 556, 558],
]
......@@ -737,3 +737,47 @@ constant pool: [
handlers: [
]
---
snippet: "
function f(a, b) {
if (a == b || a < 0) {
return 1;
} else if (a > 0 && b > 0) {
return 0;
} else {
return -1;
}
};
f(-1, 1);
"
frame size: 0
parameter count: 3
bytecode array length: 32
bytecodes: [
/* 10 E> */ B(StackCheck),
/* 21 S> */ B(Ldar), R(arg1),
/* 27 E> */ B(TestEqual), R(arg0),
B(JumpIfTrue), U8(7),
B(LdaZero),
/* 37 E> */ B(TestLessThan), R(arg0),
B(JumpIfFalse), U8(5),
/* 48 S> */ B(LdaSmi), U8(1),
/* 133 S> */ B(Return),
/* 67 S> */ B(LdaZero),
/* 73 E> */ B(TestGreaterThan), R(arg0),
B(JumpIfFalse), U8(9),
B(LdaZero),
/* 82 E> */ B(TestGreaterThan), R(arg1),
B(JumpIfFalse), U8(4),
/* 93 S> */ B(LdaZero),
/* 133 S> */ B(Return),
/* 118 S> */ B(LdaSmi), U8(-1),
/* 133 S> */ B(Return),
B(LdaUndefined),
/* 133 S> */ B(Return),
]
constant pool: [
]
handlers: [
]
......@@ -705,6 +705,17 @@ TEST(IfConditions) {
" }\n"
"};\n"
"f();\n",
"function f(a, b) {\n"
" if (a == b || a < 0) {\n"
" return 1;\n"
" } else if (a > 0 && b > 0) {\n"
" return 0;\n"
" } else {\n"
" return -1;\n"
" }\n"
"};\n"
"f(-1, 1);\n",
};
CHECK(CompareTexts(BuildActual(printer, snippets),
......@@ -1615,6 +1626,11 @@ TEST(Conditional) {
"return 1 ? 2 : 3;\n",
"return 1 ? 2 ? 3 : 4 : 5;\n",
"return 0 < 1 ? 2 : 3;\n",
"var x = 0;\n"
"return x ? 2 : 3;\n",
};
CHECK(CompareTexts(BuildActual(printer, snippets),
......
......@@ -287,7 +287,8 @@ TEST(MultipleFuncsConditional) {
v8::HandleScope scope(CcTest::isolate());
v8::Local<v8::Script> script = Compile(CcTest::isolate(),
"fun1 = 0 ?\n"
"var x = 0;\n"
"fun1 = x ?\n"
" function() { return 1; } :\n"
" function() { return 2; }");
CheckFunctionName(script, "return 1", "fun1");
......@@ -301,9 +302,10 @@ TEST(MultipleFuncsInLiteral) {
v8::Local<v8::Script> script =
Compile(CcTest::isolate(),
"var x = 0;\n"
"function MyClass() {}\n"
"MyClass.prototype = {\n"
" method1: 0 ? function() { return 1; } :\n"
" method1: x ? function() { return 1; } :\n"
" function() { return 2; } }");
CheckFunctionName(script, "return 1", "MyClass.method1");
CheckFunctionName(script, "return 2", "MyClass.method1");
......
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