"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",
"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",
--- /dev/null
+// 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
--- /dev/null
+// 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_
--- /dev/null
+// 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
--- /dev/null
+// 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_
'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',
'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',
'test-transitions.cc',
'test-typedarrays.cc',
'test-types.cc',
+ 'test-typing-reset.cc',
'test-unbound-queue.cc',
'test-unboxed-doubles.cc',
'test-unique.cc',
--- /dev/null
+// 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_
--- /dev/null
+// 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);
+}
+}
+}
--- /dev/null
+// 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_
--- /dev/null
+// 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
+}
--- /dev/null
+// 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);
+}
'../../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',
'../../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',