Commit 10f2c5c3 authored by bradnelson's avatar bradnelson Committed by Commit bot

Adding visitors to regurgitate expression types or reset them.

Adding an AstExpressionVisitor to touch each expression node in
an AST.

Adding TypingReseter to clear the slate after a failed asm.js
validation that has set partial typing information.

Adding a ExpressionTypeCollector to walk the expressions
in an AST and emit them as a string for testing.

Adding tests of the above.

LOG=N
BUG= https://code.google.com/p/v8/issues/detail?id=4203
TEST=test-typing-reset,test-ast-expression-visitor
R=rossberg@chromium.org,titzer@chromium.org

Review URL: https://codereview.chromium.org/1288773007

Cr-Commit-Position: refs/heads/master@{#30336}
parent f0e3d518
......@@ -643,6 +643,8 @@ source_set("v8_base") {
"src/assembler.h",
"src/assert-scope.h",
"src/assert-scope.cc",
"src/ast-expression-visitor.cc",
"src/ast-expression-visitor.h",
"src/ast-literal-reindexer.cc",
"src/ast-literal-reindexer.h",
"src/ast-numbering.cc",
......@@ -1209,6 +1211,8 @@ source_set("v8_base") {
"src/types-inl.h",
"src/types.cc",
"src/types.h",
"src/typing-reset.cc",
"src/typing-reset.h",
"src/typing.cc",
"src/typing.h",
"src/unbound-queue-inl.h",
......
// Copyright 2015 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/v8.h"
#include "src/ast-expression-visitor.h"
#include "src/ast.h"
#include "src/codegen.h"
#include "src/scopes.h"
namespace v8 {
namespace internal {
#define RECURSE(call) \
do { \
DCHECK(!HasStackOverflow()); \
call; \
if (HasStackOverflow()) return; \
} while (false)
#define RECURSE_EXPRESSION(call) \
do { \
DCHECK(!HasStackOverflow()); \
++depth_; \
call; \
--depth_; \
if (HasStackOverflow()) return; \
} while (false)
AstExpressionVisitor::AstExpressionVisitor(CompilationInfo* info)
: compilation_info_(info), depth_(0) {
InitializeAstVisitor(info->isolate(), info->zone());
}
void AstExpressionVisitor::Run() {
RECURSE(VisitFunctionLiteral(compilation_info_->literal()));
}
void AstExpressionVisitor::VisitVariableDeclaration(VariableDeclaration* decl) {
}
void AstExpressionVisitor::VisitFunctionDeclaration(FunctionDeclaration* decl) {
RECURSE(Visit(decl->fun()));
}
void AstExpressionVisitor::VisitImportDeclaration(ImportDeclaration* decl) {}
void AstExpressionVisitor::VisitExportDeclaration(ExportDeclaration* decl) {}
void AstExpressionVisitor::VisitStatements(ZoneList<Statement*>* stmts) {
for (int i = 0; i < stmts->length(); ++i) {
Statement* stmt = stmts->at(i);
RECURSE(Visit(stmt));
if (stmt->IsJump()) break;
}
}
void AstExpressionVisitor::VisitBlock(Block* stmt) {
RECURSE(VisitStatements(stmt->statements()));
}
void AstExpressionVisitor::VisitExpressionStatement(ExpressionStatement* stmt) {
RECURSE(Visit(stmt->expression()));
}
void AstExpressionVisitor::VisitEmptyStatement(EmptyStatement* stmt) {}
void AstExpressionVisitor::VisitIfStatement(IfStatement* stmt) {
RECURSE(Visit(stmt->condition()));
RECURSE(Visit(stmt->then_statement()));
RECURSE(Visit(stmt->else_statement()));
}
void AstExpressionVisitor::VisitContinueStatement(ContinueStatement* stmt) {}
void AstExpressionVisitor::VisitBreakStatement(BreakStatement* stmt) {}
void AstExpressionVisitor::VisitReturnStatement(ReturnStatement* stmt) {
RECURSE(Visit(stmt->expression()));
}
void AstExpressionVisitor::VisitWithStatement(WithStatement* stmt) {
RECURSE(stmt->expression());
RECURSE(stmt->statement());
}
void AstExpressionVisitor::VisitSwitchStatement(SwitchStatement* stmt) {
RECURSE(Visit(stmt->tag()));
ZoneList<CaseClause*>* clauses = stmt->cases();
for (int i = 0; i < clauses->length(); ++i) {
CaseClause* clause = clauses->at(i);
Expression* label = clause->label();
RECURSE(Visit(label));
ZoneList<Statement*>* stmts = clause->statements();
RECURSE(VisitStatements(stmts));
}
}
void AstExpressionVisitor::VisitCaseClause(CaseClause* clause) {
UNREACHABLE();
}
void AstExpressionVisitor::VisitDoWhileStatement(DoWhileStatement* stmt) {
RECURSE(Visit(stmt->body()));
RECURSE(Visit(stmt->cond()));
}
void AstExpressionVisitor::VisitWhileStatement(WhileStatement* stmt) {
RECURSE(Visit(stmt->cond()));
RECURSE(Visit(stmt->body()));
}
void AstExpressionVisitor::VisitForStatement(ForStatement* stmt) {
RECURSE(Visit(stmt->init()));
RECURSE(Visit(stmt->cond()));
RECURSE(Visit(stmt->next()));
RECURSE(Visit(stmt->body()));
}
void AstExpressionVisitor::VisitForInStatement(ForInStatement* stmt) {
RECURSE(Visit(stmt->enumerable()));
RECURSE(Visit(stmt->body()));
}
void AstExpressionVisitor::VisitForOfStatement(ForOfStatement* stmt) {
RECURSE(Visit(stmt->iterable()));
RECURSE(Visit(stmt->body()));
}
void AstExpressionVisitor::VisitTryCatchStatement(TryCatchStatement* stmt) {
RECURSE(Visit(stmt->try_block()));
RECURSE(Visit(stmt->catch_block()));
}
void AstExpressionVisitor::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
RECURSE(Visit(stmt->try_block()));
RECURSE(Visit(stmt->finally_block()));
}
void AstExpressionVisitor::VisitDebuggerStatement(DebuggerStatement* stmt) {}
void AstExpressionVisitor::VisitFunctionLiteral(FunctionLiteral* expr) {
Scope* scope = expr->scope();
VisitExpression(expr);
RECURSE_EXPRESSION(VisitDeclarations(scope->declarations()));
RECURSE_EXPRESSION(VisitStatements(expr->body()));
}
void AstExpressionVisitor::VisitNativeFunctionLiteral(
NativeFunctionLiteral* expr) {}
void AstExpressionVisitor::VisitConditional(Conditional* expr) {
RECURSE(Visit(expr->condition()));
RECURSE(Visit(expr->then_expression()));
RECURSE(Visit(expr->else_expression()));
}
void AstExpressionVisitor::VisitVariableProxy(VariableProxy* expr) {
VisitExpression(expr);
}
void AstExpressionVisitor::VisitLiteral(Literal* expr) {
VisitExpression(expr);
}
void AstExpressionVisitor::VisitRegExpLiteral(RegExpLiteral* expr) {
VisitExpression(expr);
}
void AstExpressionVisitor::VisitObjectLiteral(ObjectLiteral* expr) {
VisitExpression(expr);
ZoneList<ObjectLiteralProperty*>* props = expr->properties();
for (int i = 0; i < props->length(); ++i) {
ObjectLiteralProperty* prop = props->at(i);
RECURSE_EXPRESSION(Visit(prop->value()));
}
}
void AstExpressionVisitor::VisitArrayLiteral(ArrayLiteral* expr) {
VisitExpression(expr);
ZoneList<Expression*>* values = expr->values();
for (int i = 0; i < values->length(); ++i) {
Expression* value = values->at(i);
RECURSE_EXPRESSION(Visit(value));
}
}
void AstExpressionVisitor::VisitAssignment(Assignment* expr) {
VisitExpression(expr);
RECURSE_EXPRESSION(Visit(expr->target()));
RECURSE_EXPRESSION(Visit(expr->value()));
}
void AstExpressionVisitor::VisitYield(Yield* expr) {
RECURSE(Visit(expr->generator_object()));
RECURSE(Visit(expr->expression()));
}
void AstExpressionVisitor::VisitThrow(Throw* expr) {
RECURSE(Visit(expr->exception()));
}
void AstExpressionVisitor::VisitProperty(Property* expr) {
RECURSE(Visit(expr->obj()));
RECURSE(Visit(expr->key()));
}
void AstExpressionVisitor::VisitCall(Call* expr) {
VisitExpression(expr);
RECURSE_EXPRESSION(Visit(expr->expression()));
ZoneList<Expression*>* args = expr->arguments();
for (int i = 0; i < args->length(); ++i) {
Expression* arg = args->at(i);
RECURSE_EXPRESSION(Visit(arg));
}
}
void AstExpressionVisitor::VisitCallNew(CallNew* expr) {
VisitExpression(expr);
RECURSE_EXPRESSION(Visit(expr->expression()));
ZoneList<Expression*>* args = expr->arguments();
for (int i = 0; i < args->length(); ++i) {
Expression* arg = args->at(i);
RECURSE_EXPRESSION(Visit(arg));
}
}
void AstExpressionVisitor::VisitCallRuntime(CallRuntime* expr) {
VisitExpression(expr);
ZoneList<Expression*>* args = expr->arguments();
for (int i = 0; i < args->length(); ++i) {
Expression* arg = args->at(i);
RECURSE_EXPRESSION(Visit(arg));
}
}
void AstExpressionVisitor::VisitUnaryOperation(UnaryOperation* expr) {
VisitExpression(expr);
RECURSE_EXPRESSION(Visit(expr->expression()));
}
void AstExpressionVisitor::VisitCountOperation(CountOperation* expr) {
VisitExpression(expr);
RECURSE_EXPRESSION(Visit(expr->expression()));
}
void AstExpressionVisitor::VisitBinaryOperation(BinaryOperation* expr) {
VisitExpression(expr);
RECURSE_EXPRESSION(Visit(expr->left()));
RECURSE_EXPRESSION(Visit(expr->right()));
}
void AstExpressionVisitor::VisitCompareOperation(CompareOperation* expr) {
VisitExpression(expr);
RECURSE_EXPRESSION(Visit(expr->left()));
RECURSE_EXPRESSION(Visit(expr->right()));
}
void AstExpressionVisitor::VisitThisFunction(ThisFunction* expr) {
VisitExpression(expr);
}
void AstExpressionVisitor::VisitDeclarations(ZoneList<Declaration*>* decls) {
for (int i = 0; i < decls->length(); ++i) {
Declaration* decl = decls->at(i);
RECURSE(Visit(decl));
}
}
void AstExpressionVisitor::VisitClassLiteral(ClassLiteral* expr) {}
void AstExpressionVisitor::VisitSpread(Spread* expr) {}
void AstExpressionVisitor::VisitSuperPropertyReference(
SuperPropertyReference* expr) {}
void AstExpressionVisitor::VisitSuperCallReference(SuperCallReference* expr) {}
}
} // namespace v8::internal
// Copyright 2015 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.
#ifndef V8_AST_EXPRESSION_VISITOR_H_
#define V8_AST_EXPRESSION_VISITOR_H_
#include "src/allocation.h"
#include "src/ast.h"
#include "src/effects.h"
#include "src/scopes.h"
#include "src/type-info.h"
#include "src/types.h"
#include "src/zone.h"
namespace v8 {
namespace internal {
// A Visitor over a CompilationInfo's AST that invokes
// VisitExpression on each expression node.
class AstExpressionVisitor : public AstVisitor {
public:
explicit AstExpressionVisitor(CompilationInfo* info);
void Run();
protected:
virtual void VisitExpression(Expression* expression) = 0;
int depth() { return depth_; }
private:
void VisitDeclarations(ZoneList<Declaration*>* d) override;
void VisitStatements(ZoneList<Statement*>* s) override;
DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
#define DECLARE_VISIT(type) virtual void Visit##type(type* node) override;
AST_NODE_LIST(DECLARE_VISIT)
#undef DECLARE_VISIT
CompilationInfo* compilation_info_;
int depth_;
DISALLOW_COPY_AND_ASSIGN(AstExpressionVisitor);
};
}
} // namespace v8::internal
#endif // V8_AST_EXPRESSION_VISITOR_H_
// Copyright 2015 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/v8.h"
#include "src/typing-reset.h"
#include "src/ast.h"
#include "src/codegen.h"
#include "src/scopes.h"
namespace v8 {
namespace internal {
TypingReseter::TypingReseter(CompilationInfo* info)
: AstExpressionVisitor(info), info_(info) {}
void TypingReseter::VisitExpression(Expression* expression) {
expression->set_bounds(Bounds::Unbounded(info_->zone()));
}
}
} // namespace v8::internal
// Copyright 2015 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.
#ifndef V8_TYPING_RESET_H_
#define V8_TYPING_RESET_H_
#include "src/ast-expression-visitor.h"
namespace v8 {
namespace internal {
// A Visitor over a CompilationInfo's AST that resets
// typing bounds back to their default.
class TypingReseter : public AstExpressionVisitor {
public:
explicit TypingReseter(CompilationInfo* info);
protected:
void VisitExpression(Expression* expression) override;
private:
CompilationInfo* info_;
};
}
} // namespace v8::internal
#endif // V8_TYPING_RESET_H_
......@@ -83,6 +83,8 @@
'compiler/test-run-variables.cc',
'compiler/test-simplified-lowering.cc',
'cctest.cc',
'expression-type-collector.cc',
'expression-type-collector.h',
'interpreter/test-bytecode-generator.cc',
'interpreter/test-interpreter.cc',
'gay-fixed.cc',
......@@ -98,6 +100,7 @@
'test-api-interceptors.cc',
'test-array-list.cc',
'test-ast.cc',
'test-ast-expression-visitor.cc',
'test-atomicops.cc',
'test-bignum.cc',
'test-bignum-dtoa.cc',
......@@ -157,6 +160,7 @@
'test-transitions.cc',
'test-typedarrays.cc',
'test-types.cc',
'test-typing-reset.cc',
'test-unbound-queue.cc',
'test-unboxed-doubles.cc',
'test-unique.cc',
......
// Copyright 2015 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.
#ifndef V8_EXPRESSION_TYPE_COLLECTOR_MACROS_H_
#define V8_EXPRESSION_TYPE_COLLECTOR_MACROS_H_
#define CHECK_TYPES_BEGIN \
{ \
size_t index = 0; \
int depth = 0;
#define CHECK_TYPES_END \
CHECK_EQ(index, types.size()); \
}
#define DEFAULT_TYPE Bounds::Unbounded(handles.main_zone())
#define INT32_TYPE \
Bounds(Type::Signed32(handles.main_zone()), \
Type::Signed32(handles.main_zone()))
#define CHECK_EXPR(ekind, type) \
CHECK_LT(index, types.size()); \
CHECK(strcmp(#ekind, types[index].kind) == 0); \
CHECK_EQ(depth, types[index].depth); \
CHECK(type.lower->Is(types[index].bounds.lower)); \
CHECK(type.upper->Is(types[index].bounds.upper)); \
for (int j = (++depth, ++index, 0); j < 1 ? 1 : (--depth, 0); ++j)
#define CHECK_VAR(vname, type) \
CHECK_EXPR(VariableProxy, type); \
CHECK_EQ(#vname, std::string(types[index - 1].name->raw_data(), \
types[index - 1].name->raw_data() + \
types[index - 1].name->byte_length()));
#endif // V8_EXPRESSION_TYPE_COLLECTOR_MACROS_H_
// Copyright 2015 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/v8.h"
#include "test/cctest/expression-type-collector.h"
#include "src/ast.h"
#include "src/codegen.h"
#include "src/scopes.h"
namespace v8 {
namespace internal {
namespace {
struct {
AstNode::NodeType type;
const char* name;
} NodeTypeNameList[] = {
#define DECLARE_VISIT(type) \
{ AstNode::k##type, #type } \
,
AST_NODE_LIST(DECLARE_VISIT)
#undef DECLARE_VISIT
};
}
ExpressionTypeCollector::ExpressionTypeCollector(
CompilationInfo* info, ZoneVector<ExpressionTypeEntry>* dst)
: AstExpressionVisitor(info), result_(dst) {}
void ExpressionTypeCollector::Run() {
result_->clear();
AstExpressionVisitor::Run();
}
void ExpressionTypeCollector::VisitExpression(Expression* expression) {
ExpressionTypeEntry e;
e.depth = depth();
VariableProxy* proxy = expression->AsVariableProxy();
if (proxy) {
e.name = proxy->raw_name();
}
e.bounds = expression->bounds();
AstNode::NodeType type = expression->node_type();
e.kind = "unknown";
for (size_t i = 0; i < arraysize(NodeTypeNameList); ++i) {
if (NodeTypeNameList[i].type == type) {
e.kind = NodeTypeNameList[i].name;
break;
}
}
result_->push_back(e);
}
}
}
// Copyright 2015 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.
#ifndef V8_EXPRESSION_TYPE_COLLECTOR_H_
#define V8_EXPRESSION_TYPE_COLLECTOR_H_
#include "src/ast-expression-visitor.h"
namespace v8 {
namespace internal {
// A Visitor over a CompilationInfo's AST that collects
// a human readable string summarizing structure and types.
// Used for testing of the typing information attached to the
// expression nodes of an AST.
struct ExpressionTypeEntry {
int depth;
const char* kind;
const AstRawString* name;
Bounds bounds;
};
class ExpressionTypeCollector : public AstExpressionVisitor {
public:
ExpressionTypeCollector(CompilationInfo* info,
ZoneVector<ExpressionTypeEntry>* dst);
void Run();
protected:
void VisitExpression(Expression* expression);
private:
ZoneVector<ExpressionTypeEntry>* result_;
};
}
} // namespace v8::internal
#endif // V8_EXPRESSION_TYPE_COLLECTOR_H_
// Copyright 2015 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 <stdlib.h>
#include "src/v8.h"
#include "src/ast.h"
#include "src/ast-expression-visitor.h"
#include "src/parser.h"
#include "src/rewriter.h"
#include "src/scopes.h"
#include "test/cctest/cctest.h"
#include "test/cctest/expression-type-collector.h"
#include "test/cctest/expression-type-collector-macros.h"
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();
i::Handle<i::Script> script = factory->NewScript(source_code);
i::ParseInfo info(handles->main_zone(), script);
i::Parser parser(&info);
parser.set_allow_harmony_arrow_functions(true);
parser.set_allow_harmony_sloppy(true);
info.set_global();
info.set_lazy(false);
info.set_allow_lazy_parsing(false);
info.set_toplevel(true);
i::CompilationInfo compilation_info(&info);
CHECK(i::Compiler::ParseAndAnalyze(&info));
info.set_literal(
info.scope()->declarations()->at(0)->AsFunctionDeclaration()->fun());
ExpressionTypeCollector(&compilation_info, dst).Run();
}
}
TEST(VisitExpressions) {
v8::V8::Initialize();
HandleAndZoneScope handles;
ZoneVector<ExpressionTypeEntry> types(handles.main_zone());
const char test_function[] =
"function GeometricMean(stdlib, foreign, buffer) {\n"
" \"use asm\";\n"
"\n"
" var exp = stdlib.Math.exp;\n"
" var log = stdlib.Math.log;\n"
" var values = new stdlib.Float64Array(buffer);\n"
"\n"
" function logSum(start, end) {\n"
" start = start|0;\n"
" end = end|0;\n"
"\n"
" var sum = 0.0, p = 0, q = 0;\n"
"\n"
" // asm.js forces byte addressing of the heap by requiring shifting "
"by 3\n"
" for (p = start << 3, q = end << 3; (p|0) < (q|0); p = (p + 8)|0) {\n"
" sum = sum + +log(values[p>>3]);\n"
" }\n"
"\n"
" return +sum;\n"
" }\n"
"\n"
" function geometricMean(start, end) {\n"
" start = start|0;\n"
" end = end|0;\n"
"\n"
" return +exp(+logSum(start, end) / +((end - start)|0));\n"
" }\n"
"\n"
" return { geometricMean: geometricMean };\n"
"}\n";
CollectTypes(&handles, test_function, &types);
CHECK_TYPES_BEGIN {
// function logSum
CHECK_EXPR(FunctionLiteral, DEFAULT_TYPE) {
CHECK_EXPR(FunctionLiteral, DEFAULT_TYPE) {
CHECK_EXPR(Assignment, DEFAULT_TYPE) {
CHECK_VAR(start, DEFAULT_TYPE);
CHECK_EXPR(BinaryOperation, DEFAULT_TYPE) {
CHECK_VAR(start, DEFAULT_TYPE);
CHECK_EXPR(Literal, DEFAULT_TYPE);
}
}
CHECK_EXPR(Assignment, DEFAULT_TYPE) {
CHECK_VAR(end, DEFAULT_TYPE);
CHECK_EXPR(BinaryOperation, DEFAULT_TYPE) {
CHECK_VAR(end, DEFAULT_TYPE);
CHECK_EXPR(Literal, DEFAULT_TYPE);
}
}
CHECK_EXPR(Assignment, DEFAULT_TYPE) {
CHECK_VAR(sum, DEFAULT_TYPE);
CHECK_EXPR(Literal, DEFAULT_TYPE);
}
CHECK_EXPR(Assignment, DEFAULT_TYPE) {
CHECK_VAR(p, DEFAULT_TYPE);
CHECK_EXPR(Literal, DEFAULT_TYPE);
}
CHECK_EXPR(Assignment, DEFAULT_TYPE) {
CHECK_VAR(q, DEFAULT_TYPE);
CHECK_EXPR(Literal, DEFAULT_TYPE);
}
// for (p = start << 3, q = end << 3;
CHECK_EXPR(BinaryOperation, DEFAULT_TYPE) {
CHECK_EXPR(Assignment, DEFAULT_TYPE) {
CHECK_VAR(p, DEFAULT_TYPE);
CHECK_EXPR(BinaryOperation, DEFAULT_TYPE) {
CHECK_VAR(start, DEFAULT_TYPE);
CHECK_EXPR(Literal, DEFAULT_TYPE);
}
}
CHECK_EXPR(Assignment, DEFAULT_TYPE) {
CHECK_VAR(q, DEFAULT_TYPE);
CHECK_EXPR(BinaryOperation, DEFAULT_TYPE) {
CHECK_VAR(end, DEFAULT_TYPE);
CHECK_EXPR(Literal, DEFAULT_TYPE);
}
}
}
// (p|0) < (q|0);
CHECK_EXPR(CompareOperation, DEFAULT_TYPE) {
CHECK_EXPR(BinaryOperation, DEFAULT_TYPE) {
CHECK_VAR(p, DEFAULT_TYPE);
CHECK_EXPR(Literal, DEFAULT_TYPE);
}
CHECK_EXPR(BinaryOperation, DEFAULT_TYPE) {
CHECK_VAR(q, DEFAULT_TYPE);
CHECK_EXPR(Literal, DEFAULT_TYPE);
}
}
// p = (p + 8)|0) {\n"
CHECK_EXPR(Assignment, DEFAULT_TYPE) {
CHECK_VAR(p, DEFAULT_TYPE);
CHECK_EXPR(BinaryOperation, DEFAULT_TYPE) {
CHECK_EXPR(BinaryOperation, DEFAULT_TYPE) {
CHECK_VAR(p, DEFAULT_TYPE);
CHECK_EXPR(Literal, DEFAULT_TYPE);
}
CHECK_EXPR(Literal, DEFAULT_TYPE);
}
}
// sum = sum + +log(values[p>>3]);
CHECK_EXPR(Assignment, DEFAULT_TYPE) {
CHECK_VAR(sum, DEFAULT_TYPE);
CHECK_EXPR(BinaryOperation, DEFAULT_TYPE) {
CHECK_VAR(sum, DEFAULT_TYPE);
CHECK_EXPR(BinaryOperation, DEFAULT_TYPE) {
CHECK_EXPR(Call, DEFAULT_TYPE) {
CHECK_VAR(log, DEFAULT_TYPE);
CHECK_VAR(values, DEFAULT_TYPE);
CHECK_EXPR(BinaryOperation, DEFAULT_TYPE) {
CHECK_VAR(p, DEFAULT_TYPE);
CHECK_EXPR(Literal, DEFAULT_TYPE);
}
}
CHECK_EXPR(Literal, DEFAULT_TYPE);
}
}
}
// return +sum;
CHECK_EXPR(BinaryOperation, DEFAULT_TYPE) {
CHECK_VAR(sum, DEFAULT_TYPE);
CHECK_EXPR(Literal, DEFAULT_TYPE);
}
}
// function geometricMean
CHECK_EXPR(FunctionLiteral, DEFAULT_TYPE) {
CHECK_EXPR(Assignment, DEFAULT_TYPE) {
CHECK_VAR(start, DEFAULT_TYPE);
CHECK_EXPR(BinaryOperation, DEFAULT_TYPE) {
CHECK_VAR(start, DEFAULT_TYPE);
CHECK_EXPR(Literal, DEFAULT_TYPE);
}
}
CHECK_EXPR(Assignment, DEFAULT_TYPE) {
CHECK_VAR(end, DEFAULT_TYPE);
CHECK_EXPR(BinaryOperation, DEFAULT_TYPE) {
CHECK_VAR(end, DEFAULT_TYPE);
CHECK_EXPR(Literal, DEFAULT_TYPE);
}
}
// return +exp(+logSum(start, end) / +((end - start)|0));
CHECK_EXPR(BinaryOperation, DEFAULT_TYPE) {
CHECK_EXPR(Call, DEFAULT_TYPE) {
CHECK_VAR(exp, DEFAULT_TYPE);
CHECK_EXPR(BinaryOperation, DEFAULT_TYPE) {
CHECK_EXPR(BinaryOperation, DEFAULT_TYPE) {
CHECK_EXPR(Call, DEFAULT_TYPE) {
CHECK_VAR(logSum, DEFAULT_TYPE);
CHECK_VAR(start, DEFAULT_TYPE);
CHECK_VAR(end, DEFAULT_TYPE);
}
CHECK_EXPR(Literal, DEFAULT_TYPE);
}
CHECK_EXPR(BinaryOperation, DEFAULT_TYPE) {
CHECK_EXPR(BinaryOperation, DEFAULT_TYPE) {
CHECK_EXPR(BinaryOperation, DEFAULT_TYPE) {
CHECK_VAR(end, DEFAULT_TYPE);
CHECK_VAR(start, DEFAULT_TYPE);
}
CHECK_EXPR(Literal, DEFAULT_TYPE);
}
CHECK_EXPR(Literal, DEFAULT_TYPE);
}
}
}
CHECK_EXPR(Literal, DEFAULT_TYPE);
}
}
// "use asm";
CHECK_EXPR(Literal, DEFAULT_TYPE);
// var exp = stdlib.Math.exp;
CHECK_EXPR(Assignment, DEFAULT_TYPE) {
CHECK_VAR(exp, DEFAULT_TYPE);
CHECK_VAR(stdlib, DEFAULT_TYPE);
CHECK_EXPR(Literal, DEFAULT_TYPE);
CHECK_EXPR(Literal, DEFAULT_TYPE);
}
// var log = stdlib.Math.log;
CHECK_EXPR(Assignment, DEFAULT_TYPE) {
CHECK_VAR(log, DEFAULT_TYPE);
CHECK_VAR(stdlib, DEFAULT_TYPE);
CHECK_EXPR(Literal, DEFAULT_TYPE);
CHECK_EXPR(Literal, DEFAULT_TYPE);
}
// var values = new stdlib.Float64Array(buffer);
CHECK_EXPR(Assignment, DEFAULT_TYPE) {
CHECK_VAR(values, DEFAULT_TYPE);
CHECK_EXPR(CallNew, DEFAULT_TYPE) {
CHECK_VAR(stdlib, DEFAULT_TYPE);
CHECK_EXPR(Literal, DEFAULT_TYPE);
CHECK_VAR(buffer, DEFAULT_TYPE);
}
}
// return { geometricMean: geometricMean };
CHECK_EXPR(ObjectLiteral, DEFAULT_TYPE) {
CHECK_VAR(geometricMean, DEFAULT_TYPE);
}
}
}
CHECK_TYPES_END
}
// Copyright 2015 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 <stdlib.h>
#include "src/v8.h"
#include "src/ast.h"
#include "src/ast-expression-visitor.h"
#include "src/parser.h"
#include "src/rewriter.h"
#include "src/scopes.h"
#include "src/typing-reset.h"
#include "test/cctest/cctest.h"
#include "test/cctest/compiler/function-tester.h"
#include "test/cctest/expression-type-collector.h"
#include "test/cctest/expression-type-collector-macros.h"
using namespace v8::internal;
namespace {
class TypeSetter : public AstExpressionVisitor {
public:
explicit TypeSetter(CompilationInfo* info) : AstExpressionVisitor(info) {}
protected:
void VisitExpression(Expression* expression) {
expression->set_bounds(Bounds(Type::Integral32()));
}
};
void CheckAllSame(ZoneVector<ExpressionTypeEntry>& types,
Bounds expected_type) {
HandleAndZoneScope handles;
CHECK_TYPES_BEGIN {
// function logSum
CHECK_EXPR(FunctionLiteral, expected_type) {
CHECK_EXPR(FunctionLiteral, expected_type) {
CHECK_EXPR(Assignment, expected_type) {
CHECK_VAR(start, expected_type);
CHECK_EXPR(BinaryOperation, expected_type) {
CHECK_VAR(start, expected_type);
CHECK_EXPR(Literal, expected_type);
}
}
CHECK_EXPR(Assignment, expected_type) {
CHECK_VAR(end, expected_type);
CHECK_EXPR(BinaryOperation, expected_type) {
CHECK_VAR(end, expected_type);
CHECK_EXPR(Literal, expected_type);
}
}
CHECK_EXPR(Assignment, expected_type) {
CHECK_VAR(sum, expected_type);
CHECK_EXPR(Literal, expected_type);
}
CHECK_EXPR(Assignment, expected_type) {
CHECK_VAR(p, expected_type);
CHECK_EXPR(Literal, expected_type);
}
CHECK_EXPR(Assignment, expected_type) {
CHECK_VAR(q, expected_type);
CHECK_EXPR(Literal, expected_type);
}
// for (p = start << 3, q = end << 3;
CHECK_EXPR(BinaryOperation, expected_type) {
CHECK_EXPR(Assignment, expected_type) {
CHECK_VAR(p, expected_type);
CHECK_EXPR(BinaryOperation, expected_type) {
CHECK_VAR(start, expected_type);
CHECK_EXPR(Literal, expected_type);
}
}
CHECK_EXPR(Assignment, expected_type) {
CHECK_VAR(q, expected_type);
CHECK_EXPR(BinaryOperation, expected_type) {
CHECK_VAR(end, expected_type);
CHECK_EXPR(Literal, expected_type);
}
}
}
// (p|0) < (q|0);
CHECK_EXPR(CompareOperation, expected_type) {
CHECK_EXPR(BinaryOperation, expected_type) {
CHECK_VAR(p, expected_type);
CHECK_EXPR(Literal, expected_type);
}
CHECK_EXPR(BinaryOperation, expected_type) {
CHECK_VAR(q, expected_type);
CHECK_EXPR(Literal, expected_type);
}
}
// p = (p + 8)|0) {\n"
CHECK_EXPR(Assignment, expected_type) {
CHECK_VAR(p, expected_type);
CHECK_EXPR(BinaryOperation, expected_type) {
CHECK_EXPR(BinaryOperation, expected_type) {
CHECK_VAR(p, expected_type);
CHECK_EXPR(Literal, expected_type);
}
CHECK_EXPR(Literal, expected_type);
}
}
// sum = sum + +log(values[p>>3]);
CHECK_EXPR(Assignment, expected_type) {
CHECK_VAR(sum, expected_type);
CHECK_EXPR(BinaryOperation, expected_type) {
CHECK_VAR(sum, expected_type);
CHECK_EXPR(BinaryOperation, expected_type) {
CHECK_EXPR(Call, expected_type) {
CHECK_VAR(log, expected_type);
CHECK_VAR(values, expected_type);
CHECK_EXPR(BinaryOperation, expected_type) {
CHECK_VAR(p, expected_type);
CHECK_EXPR(Literal, expected_type);
}
}
CHECK_EXPR(Literal, expected_type);
}
}
}
// return +sum;
CHECK_EXPR(BinaryOperation, expected_type) {
CHECK_VAR(sum, expected_type);
CHECK_EXPR(Literal, expected_type);
}
}
// function geometricMean
CHECK_EXPR(FunctionLiteral, expected_type) {
CHECK_EXPR(Assignment, expected_type) {
CHECK_VAR(start, expected_type);
CHECK_EXPR(BinaryOperation, expected_type) {
CHECK_VAR(start, expected_type);
CHECK_EXPR(Literal, expected_type);
}
}
CHECK_EXPR(Assignment, expected_type) {
CHECK_VAR(end, expected_type);
CHECK_EXPR(BinaryOperation, expected_type) {
CHECK_VAR(end, expected_type);
CHECK_EXPR(Literal, expected_type);
}
}
// return +exp(+logSum(start, end) / +((end - start)|0));
CHECK_EXPR(BinaryOperation, expected_type) {
CHECK_EXPR(Call, expected_type) {
CHECK_VAR(exp, expected_type);
CHECK_EXPR(BinaryOperation, expected_type) {
CHECK_EXPR(BinaryOperation, expected_type) {
CHECK_EXPR(Call, expected_type) {
CHECK_VAR(logSum, expected_type);
CHECK_VAR(start, expected_type);
CHECK_VAR(end, expected_type);
}
CHECK_EXPR(Literal, expected_type);
}
CHECK_EXPR(BinaryOperation, expected_type) {
CHECK_EXPR(BinaryOperation, expected_type) {
CHECK_EXPR(BinaryOperation, expected_type) {
CHECK_VAR(end, expected_type);
CHECK_VAR(start, expected_type);
}
CHECK_EXPR(Literal, expected_type);
}
CHECK_EXPR(Literal, expected_type);
}
}
}
CHECK_EXPR(Literal, expected_type);
}
}
// "use asm";
CHECK_EXPR(Literal, expected_type);
// var exp = stdlib.Math.exp;
CHECK_EXPR(Assignment, expected_type) {
CHECK_VAR(exp, expected_type);
CHECK_VAR(stdlib, expected_type);
CHECK_EXPR(Literal, expected_type);
CHECK_EXPR(Literal, expected_type);
}
// var log = stdlib.Math.log;
CHECK_EXPR(Assignment, expected_type) {
CHECK_VAR(log, expected_type);
CHECK_VAR(stdlib, expected_type);
CHECK_EXPR(Literal, expected_type);
CHECK_EXPR(Literal, expected_type);
}
// var values = new stdlib.Float64Array(buffer);
CHECK_EXPR(Assignment, expected_type) {
CHECK_VAR(values, expected_type);
CHECK_EXPR(CallNew, expected_type) {
CHECK_VAR(stdlib, expected_type);
CHECK_EXPR(Literal, expected_type);
CHECK_VAR(buffer, expected_type);
}
}
// return { geometricMean: geometricMean };
CHECK_EXPR(ObjectLiteral, expected_type) {
CHECK_VAR(geometricMean, expected_type);
}
}
}
CHECK_TYPES_END
}
}
TEST(ResetTypingInfo) {
const char test_function[] =
"function GeometricMean(stdlib, foreign, buffer) {\n"
" \"use asm\";\n"
"\n"
" var exp = stdlib.Math.exp;\n"
" var log = stdlib.Math.log;\n"
" var values = new stdlib.Float64Array(buffer);\n"
"\n"
" function logSum(start, end) {\n"
" start = start|0;\n"
" end = end|0;\n"
"\n"
" var sum = 0.0, p = 0, q = 0;\n"
"\n"
" // asm.js forces byte addressing of the heap by requiring shifting "
"by 3\n"
" for (p = start << 3, q = end << 3; (p|0) < (q|0); p = (p + 8)|0) {\n"
" sum = sum + +log(values[p>>3]);\n"
" }\n"
"\n"
" return +sum;\n"
" }\n"
"\n"
" function geometricMean(start, end) {\n"
" start = start|0;\n"
" end = end|0;\n"
"\n"
" return +exp(+logSum(start, end) / +((end - start)|0));\n"
" }\n"
"\n"
" return { geometricMean: geometricMean };\n"
"}\n";
v8::V8::Initialize();
HandleAndZoneScope handles;
i::Isolate* isolate = CcTest::i_isolate();
i::Factory* factory = isolate->factory();
i::Handle<i::String> source_code =
factory->NewStringFromUtf8(i::CStrVector(test_function))
.ToHandleChecked();
i::Handle<i::Script> script = factory->NewScript(source_code);
i::ParseInfo info(handles.main_zone(), script);
i::Parser parser(&info);
parser.set_allow_harmony_arrow_functions(true);
parser.set_allow_harmony_sloppy(true);
info.set_global();
info.set_lazy(false);
info.set_allow_lazy_parsing(false);
info.set_toplevel(true);
i::CompilationInfo compilation_info(&info);
CHECK(i::Compiler::ParseAndAnalyze(&info));
info.set_literal(
info.scope()->declarations()->at(0)->AsFunctionDeclaration()->fun());
// Core of the test.
ZoneVector<ExpressionTypeEntry> types(handles.main_zone());
ExpressionTypeCollector(&compilation_info, &types).Run();
CheckAllSame(types, DEFAULT_TYPE);
TypeSetter(&compilation_info).Run();
ExpressionTypeCollector(&compilation_info, &types).Run();
CheckAllSame(types, INT32_TYPE);
TypingReseter(&compilation_info).Run();
ExpressionTypeCollector(&compilation_info, &types).Run();
CheckAllSame(types, DEFAULT_TYPE);
}
......@@ -400,12 +400,14 @@
'../../src/assembler.h',
'../../src/assert-scope.h',
'../../src/assert-scope.cc',
'../../src/ast-value-factory.cc',
'../../src/ast-value-factory.h',
'../../src/ast-expression-visitor.cc',
'../../src/ast-expression-visitor.h',
'../../src/ast-literal-reindexer.cc',
'../../src/ast-literal-reindexer.h',
'../../src/ast-numbering.cc',
'../../src/ast-numbering.h',
'../../src/ast-value-factory.cc',
'../../src/ast-value-factory.h',
'../../src/ast.cc',
'../../src/ast.h',
'../../src/background-parsing-task.cc',
......@@ -969,6 +971,8 @@
'../../src/types-inl.h',
'../../src/types.cc',
'../../src/types.h',
'../../src/typing-reset.cc',
'../../src/typing-reset.h',
'../../src/typing.cc',
'../../src/typing.h',
'../../src/unbound-queue-inl.h',
......
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