Chromium Code Reviews| Index: test/cctest/test-ast-expression-visitor.cc |
| diff --git a/test/cctest/test-ast-expression-visitor.cc b/test/cctest/test-ast-expression-visitor.cc |
| index 291f64fd95f61739aba3cda301514e3e6cfef927..5df8253afa756df4e89899b1f2195031776fe744 100644 |
| --- a/test/cctest/test-ast-expression-visitor.cc |
| +++ b/test/cctest/test-ast-expression-visitor.cc |
| @@ -3,6 +3,7 @@ |
| // found in the LICENSE file. |
| #include <stdlib.h> |
| +#include <map> |
| #include "src/v8.h" |
| @@ -19,38 +20,25 @@ using namespace v8::internal; |
| namespace { |
| -static void CollectTypes(HandleAndZoneScope* handles, const char* source, |
| - ZoneVector<ExpressionTypeEntry>* dst) { |
| - i::Isolate* isolate = CcTest::i_isolate(); |
| - i::Factory* factory = isolate->factory(); |
| - |
| - i::Handle<i::String> source_code = |
| - factory->NewStringFromUtf8(i::CStrVector(source)).ToHandleChecked(); |
| +class NodeTypeCounter : public AstExpressionVisitor { |
| + public: |
| + typedef std::map<AstNode::NodeType, int> Counters; |
| - i::Handle<i::Script> script = factory->NewScript(source_code); |
| - |
| - i::ParseInfo info(handles->main_zone(), script); |
| - i::Parser parser(&info); |
| - info.set_global(); |
| - info.set_lazy(false); |
| - info.set_allow_lazy_parsing(false); |
| - info.set_toplevel(true); |
| + NodeTypeCounter(Isolate* isolate, Expression* expr, Counters* counts) |
| + : AstExpressionVisitor(isolate, expr), counts_(counts) {} |
| - CHECK(i::Compiler::ParseAndAnalyze(&info)); |
| + protected: |
| + void VisitExpression(Expression* expr) override { |
| + (*counts_)[expr->node_type()]++; |
| + } |
| - ExpressionTypeCollector( |
| - isolate, |
| - info.scope()->declarations()->at(0)->AsFunctionDeclaration()->fun(), dst) |
| - .Run(); |
| -} |
| + private: |
| + Counters* counts_; |
| +}; |
| } // namespace |
| - |
| -TEST(VisitExpressions) { |
| - v8::V8::Initialize(); |
| - HandleAndZoneScope handles; |
| - ZoneVector<ExpressionTypeEntry> types(handles.main_zone()); |
| +TEST(VisitExpression) { |
| const char test_function[] = |
| "function GeometricMean(stdlib, foreign, buffer) {\n" |
| " \"use asm\";\n" |
| @@ -84,342 +72,31 @@ TEST(VisitExpressions) { |
| " return { geometricMean: geometricMean };\n" |
| "}\n"; |
| - CollectTypes(&handles, test_function, &types); |
| - CHECK_TYPES_BEGIN { |
| - // function logSum |
| - CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) { |
| - CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) { |
| - CHECK_EXPR(Assignment, Bounds::Unbounded()) { |
| - CHECK_VAR(start, Bounds::Unbounded()); |
| - CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) { |
| - CHECK_VAR(start, Bounds::Unbounded()); |
| - CHECK_EXPR(Literal, Bounds::Unbounded()); |
| - } |
| - } |
| - CHECK_EXPR(Assignment, Bounds::Unbounded()) { |
| - CHECK_VAR(end, Bounds::Unbounded()); |
| - CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) { |
| - CHECK_VAR(end, Bounds::Unbounded()); |
| - CHECK_EXPR(Literal, Bounds::Unbounded()); |
| - } |
| - } |
| - CHECK_EXPR(Assignment, Bounds::Unbounded()) { |
| - CHECK_VAR(sum, Bounds::Unbounded()); |
| - CHECK_EXPR(Literal, Bounds::Unbounded()); |
| - } |
| - CHECK_EXPR(Assignment, Bounds::Unbounded()) { |
| - CHECK_VAR(p, Bounds::Unbounded()); |
| - CHECK_EXPR(Literal, Bounds::Unbounded()); |
| - } |
| - CHECK_EXPR(Assignment, Bounds::Unbounded()) { |
| - CHECK_VAR(q, Bounds::Unbounded()); |
| - CHECK_EXPR(Literal, Bounds::Unbounded()); |
| - } |
| - // for (p = start << 3, q = end << 3; |
| - CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) { |
| - CHECK_EXPR(Assignment, Bounds::Unbounded()) { |
| - CHECK_VAR(p, Bounds::Unbounded()); |
| - CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) { |
| - CHECK_VAR(start, Bounds::Unbounded()); |
| - CHECK_EXPR(Literal, Bounds::Unbounded()); |
| - } |
| - } |
| - CHECK_EXPR(Assignment, Bounds::Unbounded()) { |
| - CHECK_VAR(q, Bounds::Unbounded()); |
| - CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) { |
| - CHECK_VAR(end, Bounds::Unbounded()); |
| - CHECK_EXPR(Literal, Bounds::Unbounded()); |
| - } |
| - } |
| - } |
| - // (p|0) < (q|0); |
| - CHECK_EXPR(CompareOperation, Bounds::Unbounded()) { |
| - CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) { |
| - CHECK_VAR(p, Bounds::Unbounded()); |
| - CHECK_EXPR(Literal, Bounds::Unbounded()); |
| - } |
| - CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) { |
| - CHECK_VAR(q, Bounds::Unbounded()); |
| - CHECK_EXPR(Literal, Bounds::Unbounded()); |
| - } |
| - } |
| - // p = (p + 8)|0) {\n" |
| - CHECK_EXPR(Assignment, Bounds::Unbounded()) { |
| - CHECK_VAR(p, Bounds::Unbounded()); |
| - CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) { |
| - CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) { |
| - CHECK_VAR(p, Bounds::Unbounded()); |
| - CHECK_EXPR(Literal, Bounds::Unbounded()); |
| - } |
| - CHECK_EXPR(Literal, Bounds::Unbounded()); |
| - } |
| - } |
| - // sum = sum + +log(values[p>>3]); |
| - CHECK_EXPR(Assignment, Bounds::Unbounded()) { |
| - CHECK_VAR(sum, Bounds::Unbounded()); |
| - CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) { |
| - CHECK_VAR(sum, Bounds::Unbounded()); |
| - CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) { |
| - CHECK_EXPR(Call, Bounds::Unbounded()) { |
| - CHECK_VAR(log, Bounds::Unbounded()); |
| - CHECK_EXPR(Property, Bounds::Unbounded()) { |
| - CHECK_VAR(values, Bounds::Unbounded()); |
| - CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) { |
| - CHECK_VAR(p, Bounds::Unbounded()); |
| - CHECK_EXPR(Literal, Bounds::Unbounded()); |
| - } |
| - } |
| - } |
| - CHECK_EXPR(Literal, Bounds::Unbounded()); |
| - } |
| - } |
| - } |
| - // return +sum; |
| - CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) { |
| - CHECK_VAR(sum, Bounds::Unbounded()); |
| - CHECK_EXPR(Literal, Bounds::Unbounded()); |
| - } |
| - } |
| - // function geometricMean |
| - CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) { |
| - CHECK_EXPR(Assignment, Bounds::Unbounded()) { |
| - CHECK_VAR(start, Bounds::Unbounded()); |
| - CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) { |
| - CHECK_VAR(start, Bounds::Unbounded()); |
| - CHECK_EXPR(Literal, Bounds::Unbounded()); |
| - } |
| - } |
| - CHECK_EXPR(Assignment, Bounds::Unbounded()) { |
| - CHECK_VAR(end, Bounds::Unbounded()); |
| - CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) { |
| - CHECK_VAR(end, Bounds::Unbounded()); |
| - CHECK_EXPR(Literal, Bounds::Unbounded()); |
| - } |
| - } |
| - // return +exp(+logSum(start, end) / +((end - start)|0)); |
| - CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) { |
| - CHECK_EXPR(Call, Bounds::Unbounded()) { |
| - CHECK_VAR(exp, Bounds::Unbounded()); |
| - CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) { |
| - CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) { |
| - CHECK_EXPR(Call, Bounds::Unbounded()) { |
| - CHECK_VAR(logSum, Bounds::Unbounded()); |
| - CHECK_VAR(start, Bounds::Unbounded()); |
| - CHECK_VAR(end, Bounds::Unbounded()); |
| - } |
| - CHECK_EXPR(Literal, Bounds::Unbounded()); |
| - } |
| - CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) { |
| - CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) { |
| - CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) { |
| - CHECK_VAR(end, Bounds::Unbounded()); |
| - CHECK_VAR(start, Bounds::Unbounded()); |
| - } |
| - CHECK_EXPR(Literal, Bounds::Unbounded()); |
| - } |
| - CHECK_EXPR(Literal, Bounds::Unbounded()); |
| - } |
| - } |
| - } |
| - CHECK_EXPR(Literal, Bounds::Unbounded()); |
| - } |
| - } |
| - // "use asm"; |
| - CHECK_EXPR(Literal, Bounds::Unbounded()); |
| - // var exp = stdlib.Math.exp; |
| - CHECK_EXPR(Assignment, Bounds::Unbounded()) { |
| - CHECK_VAR(exp, Bounds::Unbounded()); |
| - CHECK_EXPR(Property, Bounds::Unbounded()) { |
| - CHECK_EXPR(Property, Bounds::Unbounded()) { |
| - CHECK_VAR(stdlib, Bounds::Unbounded()); |
| - CHECK_EXPR(Literal, Bounds::Unbounded()); |
| - } |
| - CHECK_EXPR(Literal, Bounds::Unbounded()); |
| - } |
| - } |
| - // var log = stdlib.Math.log; |
| - CHECK_EXPR(Assignment, Bounds::Unbounded()) { |
| - CHECK_VAR(log, Bounds::Unbounded()); |
| - CHECK_EXPR(Property, Bounds::Unbounded()) { |
| - CHECK_EXPR(Property, Bounds::Unbounded()) { |
| - CHECK_VAR(stdlib, Bounds::Unbounded()); |
| - CHECK_EXPR(Literal, Bounds::Unbounded()); |
| - } |
| - CHECK_EXPR(Literal, Bounds::Unbounded()); |
| - } |
| - } |
| - // var values = new stdlib.Float64Array(buffer); |
| - CHECK_EXPR(Assignment, Bounds::Unbounded()) { |
| - CHECK_VAR(values, Bounds::Unbounded()); |
| - CHECK_EXPR(CallNew, Bounds::Unbounded()) { |
| - CHECK_EXPR(Property, Bounds::Unbounded()) { |
| - CHECK_VAR(stdlib, Bounds::Unbounded()); |
| - CHECK_EXPR(Literal, Bounds::Unbounded()); |
| - } |
| - CHECK_VAR(buffer, Bounds::Unbounded()); |
| - } |
| - } |
| - // return { geometricMean: geometricMean }; |
| - CHECK_EXPR(ObjectLiteral, Bounds::Unbounded()) { |
| - CHECK_VAR(geometricMean, Bounds::Unbounded()); |
| - } |
| - } |
| - } |
| - CHECK_TYPES_END |
| -} |
| - |
| - |
| -TEST(VisitConditional) { |
| - v8::V8::Initialize(); |
| - HandleAndZoneScope handles; |
| - ZoneVector<ExpressionTypeEntry> types(handles.main_zone()); |
| - // Check that traversing the ternary operator works. |
| - const char test_function[] = |
| - "function foo() {\n" |
| - " var a, b, c;\n" |
| - " var x = a ? b : c;\n" |
| - "}\n"; |
| - CollectTypes(&handles, test_function, &types); |
| - CHECK_TYPES_BEGIN { |
| - CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) { |
| - CHECK_EXPR(Assignment, Bounds::Unbounded()) { |
| - CHECK_VAR(x, Bounds::Unbounded()); |
| - CHECK_EXPR(Conditional, Bounds::Unbounded()) { |
| - CHECK_VAR(a, Bounds::Unbounded()); |
| - CHECK_VAR(b, Bounds::Unbounded()); |
| - CHECK_VAR(c, Bounds::Unbounded()); |
| - } |
| - } |
| - } |
| - } |
| - CHECK_TYPES_END |
| -} |
| - |
| - |
| -TEST(VisitEmptyForStatment) { |
| - v8::V8::Initialize(); |
| - HandleAndZoneScope handles; |
| - ZoneVector<ExpressionTypeEntry> types(handles.main_zone()); |
| - // Check that traversing an empty for statement works. |
| - const char test_function[] = |
| - "function foo() {\n" |
| - " for (;;) {}\n" |
| - "}\n"; |
| - CollectTypes(&handles, test_function, &types); |
| - CHECK_TYPES_BEGIN { |
| - CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) {} |
| - } |
| - CHECK_TYPES_END |
| -} |
| - |
| - |
| -TEST(VisitSwitchStatment) { |
| - v8::V8::Initialize(); |
| - HandleAndZoneScope handles; |
| - ZoneVector<ExpressionTypeEntry> types(handles.main_zone()); |
| - // Check that traversing a switch with a default works. |
| - const char test_function[] = |
| - "function foo() {\n" |
| - " switch (0) { case 1: break; default: break; }\n" |
| - "}\n"; |
| - CollectTypes(&handles, test_function, &types); |
| - CHECK_TYPES_BEGIN { |
| - CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) { |
| - CHECK_EXPR(Assignment, Bounds::Unbounded()) { |
| - CHECK_VAR(.switch_tag, Bounds::Unbounded()); |
| - CHECK_EXPR(Literal, Bounds::Unbounded()); |
| - } |
| - CHECK_EXPR(Literal, Bounds::Unbounded()); |
| - CHECK_VAR(.switch_tag, Bounds::Unbounded()); |
| - CHECK_EXPR(Literal, Bounds::Unbounded()); |
| - } |
| - } |
| - CHECK_TYPES_END |
| -} |
| - |
| - |
| -TEST(VisitThrow) { |
| - v8::V8::Initialize(); |
| - HandleAndZoneScope handles; |
| - ZoneVector<ExpressionTypeEntry> types(handles.main_zone()); |
| - const char test_function[] = |
| - "function foo() {\n" |
| - " throw 123;\n" |
| - "}\n"; |
| - CollectTypes(&handles, test_function, &types); |
| - CHECK_TYPES_BEGIN { |
| - CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) { |
| - CHECK_EXPR(Throw, Bounds::Unbounded()) { |
| - CHECK_EXPR(Literal, Bounds::Unbounded()); |
| - } |
| - } |
| - } |
| - CHECK_TYPES_END |
| -} |
| - |
| - |
| -TEST(VisitYield) { |
| + // Parse + compile test_function, and extract the AST node for it. |
| v8::V8::Initialize(); |
| HandleAndZoneScope handles; |
| - ZoneVector<ExpressionTypeEntry> types(handles.main_zone()); |
| - const char test_function[] = |
| - "function* foo() {\n" |
| - " yield 123;\n" |
| - "}\n"; |
| - CollectTypes(&handles, test_function, &types); |
| - CHECK_TYPES_BEGIN { |
| - CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) { |
| - // Implicit initial yield |
| - CHECK_EXPR(Yield, Bounds::Unbounded()) { |
| - CHECK_VAR(.generator_object, Bounds::Unbounded()); |
| - CHECK_EXPR(Assignment, Bounds::Unbounded()) { |
| - CHECK_VAR(.generator_object, Bounds::Unbounded()); |
| - CHECK_EXPR(CallRuntime, Bounds::Unbounded()) { |
| - CHECK_EXPR(ThisFunction, Bounds::Unbounded()); |
| - CHECK_EXPR(VariableProxy, Bounds::Unbounded()); |
| - } |
| - } |
| - } |
| - // Explicit yield (argument wrapped with CreateIterResultObject) |
| - CHECK_EXPR(Yield, Bounds::Unbounded()) { |
| - CHECK_VAR(.generator_object, Bounds::Unbounded()); |
| - CHECK_EXPR(CallRuntime, Bounds::Unbounded()) { |
| - CHECK_EXPR(Literal, Bounds::Unbounded()); |
| - CHECK_EXPR(Literal, Bounds::Unbounded()); |
| - } |
| - } |
| - // Argument to implicit final return |
| - CHECK_EXPR(CallRuntime, Bounds::Unbounded()) { // CreateIterResultObject |
| - CHECK_EXPR(Literal, Bounds::Unbounded()); |
| - CHECK_EXPR(Literal, Bounds::Unbounded()); |
| - } |
| - // Implicit finally clause |
| - CHECK_EXPR(CallRuntime, Bounds::Unbounded()) { |
| - CHECK_VAR(.generator_object, Bounds::Unbounded()); |
| - } |
| - } |
| - } |
| - CHECK_TYPES_END |
| -} |
| - |
| - |
| -TEST(VisitSkipping) { |
| - v8::V8::Initialize(); |
| - HandleAndZoneScope handles; |
| - ZoneVector<ExpressionTypeEntry> types(handles.main_zone()); |
| - const char test_function[] = |
| - "function foo(x) {\n" |
| - " return (x + x) + 1;\n" |
| - "}\n"; |
| - CollectTypes(&handles, test_function, &types); |
| - CHECK_TYPES_BEGIN { |
| - CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) { |
| - CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) { |
| - // Skip x + x |
| - CHECK_SKIP(); |
| - CHECK_EXPR(Literal, Bounds::Unbounded()); |
| - } |
| - } |
| - } |
| - CHECK_TYPES_END |
| + i::Isolate* isolate = CcTest::i_isolate(); |
| + i::Handle<i::String> source_code = |
| + isolate->factory() |
| + ->NewStringFromUtf8(i::CStrVector(test_function)) |
| + .ToHandleChecked(); |
| + i::Handle<i::Script> script = isolate->factory()->NewScript(source_code); |
| + i::ParseInfo info(handles.main_zone(), script); |
| + i::Parser parser(&info); |
| + info.set_global(); |
| + info.set_lazy(false); |
| + info.set_allow_lazy_parsing(false); |
| + info.set_toplevel(true); |
| + CHECK(i::Compiler::ParseAndAnalyze(&info)); |
| + Expression* test_function_expr = |
| + info.scope()->declarations()->at(0)->AsFunctionDeclaration()->fun(); |
| + |
| + // Run NodeTypeCounter and sanity check counts for 3 expression types, |
| + // and for overall # of types found. |
|
bradnelson
2016/05/12 15:43:45
Yeah that's better, this was overkill at the time.
|
| + NodeTypeCounter::Counters counts; |
| + NodeTypeCounter(isolate, test_function_expr, &counts).Run(); |
| + CHECK_EQ(21, counts[AstNode::kBinaryOperation]); |
| + CHECK_EQ(26, counts[AstNode::kLiteral]); |
| + CHECK_EQ(3, counts[AstNode::kFunctionLiteral]); |
| + CHECK_EQ(10, counts.size()); |
| } |