[Interpreter] Add conditional expressions.
Adds support and tests for conditional (ternary) expressions. BUG=v8:4280 LOG=N Review URL: https://codereview.chromium.org/1417053004 Cr-Commit-Position: refs/heads/master@{#31575}
This commit is contained in:
parent
cf050cc2d2
commit
2781ff6834
@ -656,7 +656,26 @@ void BytecodeGenerator::VisitDoExpression(DoExpression* expr) {
|
||||
}
|
||||
|
||||
|
||||
void BytecodeGenerator::VisitConditional(Conditional* expr) { UNIMPLEMENTED(); }
|
||||
void BytecodeGenerator::VisitConditional(Conditional* expr) {
|
||||
// TODO(rmcilroy): Spot easy cases where there code would not need to
|
||||
// emit the then block or the else block, e.g. condition is
|
||||
// obviously true/1/false/0.
|
||||
|
||||
BytecodeLabel else_label, end_label;
|
||||
|
||||
VisitForAccumulatorValue(expr->condition());
|
||||
builder()->CastAccumulatorToBoolean();
|
||||
builder()->JumpIfFalse(&else_label);
|
||||
|
||||
VisitForAccumulatorValue(expr->then_expression());
|
||||
builder()->Jump(&end_label);
|
||||
|
||||
builder()->Bind(&else_label);
|
||||
VisitForAccumulatorValue(expr->else_expression());
|
||||
builder()->Bind(&end_label);
|
||||
|
||||
execution_result()->SetResultInAccumulator();
|
||||
}
|
||||
|
||||
|
||||
void BytecodeGenerator::VisitLiteral(Literal* expr) {
|
||||
|
@ -3493,6 +3493,52 @@ TEST(IllegalRedeclaration) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST(Conditional) {
|
||||
InitializedHandleScope handle_scope;
|
||||
BytecodeGeneratorHelper helper;
|
||||
|
||||
ExpectedSnippet<int> snippets[] = {
|
||||
{"return 1 ? 2 : 3;",
|
||||
0,
|
||||
1,
|
||||
12,
|
||||
{
|
||||
B(LdaSmi8), U8(1), //
|
||||
B(ToBoolean), //
|
||||
B(JumpIfFalse), U8(6), //
|
||||
B(LdaSmi8), U8(2), //
|
||||
B(Jump), U8(4), //
|
||||
B(LdaSmi8), U8(3), //
|
||||
B(Return), //
|
||||
}},
|
||||
{"return 1 ? 2 ? 3 : 4 : 5;",
|
||||
0,
|
||||
1,
|
||||
21,
|
||||
{
|
||||
B(LdaSmi8), U8(1), //
|
||||
B(ToBoolean), //
|
||||
B(JumpIfFalse), U8(15), //
|
||||
B(LdaSmi8), U8(2), //
|
||||
B(ToBoolean), //
|
||||
B(JumpIfFalse), U8(6), //
|
||||
B(LdaSmi8), U8(3), //
|
||||
B(Jump), U8(4), //
|
||||
B(LdaSmi8), U8(4), //
|
||||
B(Jump), U8(4), //
|
||||
B(LdaSmi8), U8(5), //
|
||||
B(Return), //
|
||||
}},
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < arraysize(snippets); i++) {
|
||||
Handle<BytecodeArray> bytecode_array =
|
||||
helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
|
||||
CheckBytecodeArrayEqual(snippets[i], bytecode_array);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace interpreter
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -2264,3 +2264,37 @@ TEST(InterpreterCreateArguments) {
|
||||
CHECK(return_val->SameValue(*args[create_args[i].second]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST(InterpreterConditional) {
|
||||
HandleAndZoneScope handles;
|
||||
i::Isolate* isolate = handles.main_isolate();
|
||||
|
||||
std::pair<const char*, Handle<Object>> conditional[8] = {
|
||||
std::make_pair("return true ? 2 : 3;",
|
||||
handle(Smi::FromInt(2), isolate)),
|
||||
std::make_pair("return false ? 2 : 3;",
|
||||
handle(Smi::FromInt(3), isolate)),
|
||||
std::make_pair("var a = 1; return a ? 20 : 30;",
|
||||
handle(Smi::FromInt(20), isolate)),
|
||||
std::make_pair("var a = 1; return a ? 20 : 30;",
|
||||
handle(Smi::FromInt(20), isolate)),
|
||||
std::make_pair("var a = 'string'; return a ? 20 : 30;",
|
||||
handle(Smi::FromInt(20), isolate)),
|
||||
std::make_pair("var a = undefined; return a ? 20 : 30;",
|
||||
handle(Smi::FromInt(30), isolate)),
|
||||
std::make_pair("return 1 ? 2 ? 3 : 4 : 5;",
|
||||
handle(Smi::FromInt(3), isolate)),
|
||||
std::make_pair("return 0 ? 2 ? 3 : 4 : 5;",
|
||||
handle(Smi::FromInt(5), isolate)),
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < arraysize(conditional); i++) {
|
||||
std::string source(InterpreterTester::SourceForBody(conditional[i].first));
|
||||
InterpreterTester tester(handles.main_isolate(), source.c_str());
|
||||
auto callable = tester.GetCallable<>();
|
||||
|
||||
Handle<i::Object> return_value = callable().ToHandleChecked();
|
||||
CHECK(return_value->SameValue(*conditional[i].second));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user