diff --git a/deps/v8/include/v8-version.h b/deps/v8/include/v8-version.h index 85a2ced31e74b6..54fd822efe41ed 100644 --- a/deps/v8/include/v8-version.h +++ b/deps/v8/include/v8-version.h @@ -11,7 +11,7 @@ #define V8_MAJOR_VERSION 4 #define V8_MINOR_VERSION 6 #define V8_BUILD_NUMBER 85 -#define V8_PATCH_LEVEL 23 +#define V8_PATCH_LEVEL 25 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.) diff --git a/deps/v8/src/ast.h b/deps/v8/src/ast.h index 1366041387215b..10dbdb910960fa 100644 --- a/deps/v8/src/ast.h +++ b/deps/v8/src/ast.h @@ -3271,14 +3271,15 @@ class AstVisitor BASE_EMBEDDED { class AstNodeFactory final BASE_EMBEDDED { public: explicit AstNodeFactory(AstValueFactory* ast_value_factory) - : zone_(ast_value_factory->zone()), + : local_zone_(ast_value_factory->zone()), + parser_zone_(ast_value_factory->zone()), ast_value_factory_(ast_value_factory) {} VariableDeclaration* NewVariableDeclaration( VariableProxy* proxy, VariableMode mode, Scope* scope, int pos, bool is_class_declaration = false, int declaration_group_start = -1) { - return new (zone_) - VariableDeclaration(zone_, proxy, mode, scope, pos, + return new (parser_zone_) + VariableDeclaration(parser_zone_, proxy, mode, scope, pos, is_class_declaration, declaration_group_start); } @@ -3287,32 +3288,34 @@ class AstNodeFactory final BASE_EMBEDDED { FunctionLiteral* fun, Scope* scope, int pos) { - return new (zone_) FunctionDeclaration(zone_, proxy, mode, fun, scope, pos); + return new (parser_zone_) + FunctionDeclaration(parser_zone_, proxy, mode, fun, scope, pos); } ImportDeclaration* NewImportDeclaration(VariableProxy* proxy, const AstRawString* import_name, const AstRawString* module_specifier, Scope* scope, int pos) { - return new (zone_) ImportDeclaration(zone_, proxy, import_name, - module_specifier, scope, pos); + return new (parser_zone_) ImportDeclaration( + parser_zone_, proxy, import_name, module_specifier, scope, pos); } ExportDeclaration* NewExportDeclaration(VariableProxy* proxy, Scope* scope, int pos) { - return new (zone_) ExportDeclaration(zone_, proxy, scope, pos); + return new (parser_zone_) + ExportDeclaration(parser_zone_, proxy, scope, pos); } Block* NewBlock(ZoneList* labels, int capacity, bool ignore_completion_value, int pos) { - return new (zone_) - Block(zone_, labels, capacity, ignore_completion_value, pos); + return new (local_zone_) + Block(local_zone_, labels, capacity, ignore_completion_value, pos); } #define STATEMENT_WITH_LABELS(NodeType) \ NodeType* New##NodeType(ZoneList* labels, int pos) { \ - return new (zone_) NodeType(zone_, labels, pos); \ + return new (local_zone_) NodeType(local_zone_, labels, pos); \ } STATEMENT_WITH_LABELS(DoWhileStatement) STATEMENT_WITH_LABELS(WhileStatement) @@ -3325,10 +3328,10 @@ class AstNodeFactory final BASE_EMBEDDED { int pos) { switch (visit_mode) { case ForEachStatement::ENUMERATE: { - return new (zone_) ForInStatement(zone_, labels, pos); + return new (local_zone_) ForInStatement(local_zone_, labels, pos); } case ForEachStatement::ITERATE: { - return new (zone_) ForOfStatement(zone_, labels, pos); + return new (local_zone_) ForOfStatement(local_zone_, labels, pos); } } UNREACHABLE(); @@ -3336,95 +3339,102 @@ class AstNodeFactory final BASE_EMBEDDED { } ExpressionStatement* NewExpressionStatement(Expression* expression, int pos) { - return new (zone_) ExpressionStatement(zone_, expression, pos); + return new (local_zone_) ExpressionStatement(local_zone_, expression, pos); } ContinueStatement* NewContinueStatement(IterationStatement* target, int pos) { - return new (zone_) ContinueStatement(zone_, target, pos); + return new (local_zone_) ContinueStatement(local_zone_, target, pos); } BreakStatement* NewBreakStatement(BreakableStatement* target, int pos) { - return new (zone_) BreakStatement(zone_, target, pos); + return new (local_zone_) BreakStatement(local_zone_, target, pos); } ReturnStatement* NewReturnStatement(Expression* expression, int pos) { - return new (zone_) ReturnStatement(zone_, expression, pos); + return new (local_zone_) ReturnStatement(local_zone_, expression, pos); } WithStatement* NewWithStatement(Scope* scope, Expression* expression, Statement* statement, int pos) { - return new (zone_) WithStatement(zone_, scope, expression, statement, pos); + return new (local_zone_) + WithStatement(local_zone_, scope, expression, statement, pos); } IfStatement* NewIfStatement(Expression* condition, Statement* then_statement, Statement* else_statement, int pos) { - return new (zone_) - IfStatement(zone_, condition, then_statement, else_statement, pos); + return new (local_zone_) IfStatement(local_zone_, condition, then_statement, + else_statement, pos); } TryCatchStatement* NewTryCatchStatement(Block* try_block, Scope* scope, Variable* variable, Block* catch_block, int pos) { - return new (zone_) - TryCatchStatement(zone_, try_block, scope, variable, catch_block, pos); + return new (local_zone_) TryCatchStatement(local_zone_, try_block, scope, + variable, catch_block, pos); } TryFinallyStatement* NewTryFinallyStatement(Block* try_block, Block* finally_block, int pos) { - return new (zone_) - TryFinallyStatement(zone_, try_block, finally_block, pos); + return new (local_zone_) + TryFinallyStatement(local_zone_, try_block, finally_block, pos); } DebuggerStatement* NewDebuggerStatement(int pos) { - return new (zone_) DebuggerStatement(zone_, pos); + return new (local_zone_) DebuggerStatement(local_zone_, pos); } EmptyStatement* NewEmptyStatement(int pos) { - return new(zone_) EmptyStatement(zone_, pos); + return new (local_zone_) EmptyStatement(local_zone_, pos); } CaseClause* NewCaseClause( Expression* label, ZoneList* statements, int pos) { - return new (zone_) CaseClause(zone_, label, statements, pos); + return new (local_zone_) CaseClause(local_zone_, label, statements, pos); } Literal* NewStringLiteral(const AstRawString* string, int pos) { - return new (zone_) - Literal(zone_, ast_value_factory_->NewString(string), pos); + return new (local_zone_) + Literal(local_zone_, ast_value_factory_->NewString(string), pos); } // A JavaScript symbol (ECMA-262 edition 6). Literal* NewSymbolLiteral(const char* name, int pos) { - return new (zone_) Literal(zone_, ast_value_factory_->NewSymbol(name), pos); + return new (local_zone_) + Literal(local_zone_, ast_value_factory_->NewSymbol(name), pos); } Literal* NewNumberLiteral(double number, int pos, bool with_dot = false) { - return new (zone_) - Literal(zone_, ast_value_factory_->NewNumber(number, with_dot), pos); + return new (local_zone_) Literal( + local_zone_, ast_value_factory_->NewNumber(number, with_dot), pos); } Literal* NewSmiLiteral(int number, int pos) { - return new (zone_) Literal(zone_, ast_value_factory_->NewSmi(number), pos); + return new (local_zone_) + Literal(local_zone_, ast_value_factory_->NewSmi(number), pos); } Literal* NewBooleanLiteral(bool b, int pos) { - return new (zone_) Literal(zone_, ast_value_factory_->NewBoolean(b), pos); + return new (local_zone_) + Literal(local_zone_, ast_value_factory_->NewBoolean(b), pos); } Literal* NewNullLiteral(int pos) { - return new (zone_) Literal(zone_, ast_value_factory_->NewNull(), pos); + return new (local_zone_) + Literal(local_zone_, ast_value_factory_->NewNull(), pos); } Literal* NewUndefinedLiteral(int pos) { - return new (zone_) Literal(zone_, ast_value_factory_->NewUndefined(), pos); + return new (local_zone_) + Literal(local_zone_, ast_value_factory_->NewUndefined(), pos); } Literal* NewTheHoleLiteral(int pos) { - return new (zone_) Literal(zone_, ast_value_factory_->NewTheHole(), pos); + return new (local_zone_) + Literal(local_zone_, ast_value_factory_->NewTheHole(), pos); } ObjectLiteral* NewObjectLiteral( @@ -3434,15 +3444,15 @@ class AstNodeFactory final BASE_EMBEDDED { bool has_function, bool is_strong, int pos) { - return new (zone_) ObjectLiteral(zone_, properties, literal_index, - boilerplate_properties, has_function, - is_strong, pos); + return new (local_zone_) + ObjectLiteral(local_zone_, properties, literal_index, + boilerplate_properties, has_function, is_strong, pos); } ObjectLiteral::Property* NewObjectLiteralProperty( Expression* key, Expression* value, ObjectLiteralProperty::Kind kind, bool is_static, bool is_computed_name) { - return new (zone_) + return new (local_zone_) ObjectLiteral::Property(key, value, kind, is_static, is_computed_name); } @@ -3450,8 +3460,8 @@ class AstNodeFactory final BASE_EMBEDDED { Expression* value, bool is_static, bool is_computed_name) { - return new (zone_) ObjectLiteral::Property(ast_value_factory_, key, value, - is_static, is_computed_name); + return new (local_zone_) ObjectLiteral::Property( + ast_value_factory_, key, value, is_static, is_computed_name); } RegExpLiteral* NewRegExpLiteral(const AstRawString* pattern, @@ -3459,29 +3469,30 @@ class AstNodeFactory final BASE_EMBEDDED { int literal_index, bool is_strong, int pos) { - return new (zone_) RegExpLiteral(zone_, pattern, flags, literal_index, - is_strong, pos); + return new (local_zone_) RegExpLiteral(local_zone_, pattern, flags, + literal_index, is_strong, pos); } ArrayLiteral* NewArrayLiteral(ZoneList* values, int literal_index, bool is_strong, int pos) { - return new (zone_) - ArrayLiteral(zone_, values, -1, literal_index, is_strong, pos); + return new (local_zone_) + ArrayLiteral(local_zone_, values, -1, literal_index, is_strong, pos); } ArrayLiteral* NewArrayLiteral(ZoneList* values, int first_spread_index, int literal_index, bool is_strong, int pos) { - return new (zone_) ArrayLiteral(zone_, values, first_spread_index, - literal_index, is_strong, pos); + return new (local_zone_) ArrayLiteral( + local_zone_, values, first_spread_index, literal_index, is_strong, pos); } VariableProxy* NewVariableProxy(Variable* var, int start_position = RelocInfo::kNoPosition, int end_position = RelocInfo::kNoPosition) { - return new (zone_) VariableProxy(zone_, var, start_position, end_position); + return new (parser_zone_) + VariableProxy(parser_zone_, var, start_position, end_position); } VariableProxy* NewVariableProxy(const AstRawString* name, @@ -3489,70 +3500,73 @@ class AstNodeFactory final BASE_EMBEDDED { int start_position = RelocInfo::kNoPosition, int end_position = RelocInfo::kNoPosition) { DCHECK_NOT_NULL(name); - return new (zone_) - VariableProxy(zone_, name, variable_kind, start_position, end_position); + return new (parser_zone_) VariableProxy(parser_zone_, name, variable_kind, + start_position, end_position); } Property* NewProperty(Expression* obj, Expression* key, int pos) { - return new (zone_) Property(zone_, obj, key, pos); + return new (local_zone_) Property(local_zone_, obj, key, pos); } Call* NewCall(Expression* expression, ZoneList* arguments, int pos) { - return new (zone_) Call(zone_, expression, arguments, pos); + return new (local_zone_) Call(local_zone_, expression, arguments, pos); } CallNew* NewCallNew(Expression* expression, ZoneList* arguments, int pos) { - return new (zone_) CallNew(zone_, expression, arguments, pos); + return new (local_zone_) CallNew(local_zone_, expression, arguments, pos); } CallRuntime* NewCallRuntime(const AstRawString* name, const Runtime::Function* function, ZoneList* arguments, int pos) { - return new (zone_) CallRuntime(zone_, name, function, arguments, pos); + return new (local_zone_) + CallRuntime(local_zone_, name, function, arguments, pos); } UnaryOperation* NewUnaryOperation(Token::Value op, Expression* expression, int pos) { - return new (zone_) UnaryOperation(zone_, op, expression, pos); + return new (local_zone_) UnaryOperation(local_zone_, op, expression, pos); } BinaryOperation* NewBinaryOperation(Token::Value op, Expression* left, Expression* right, int pos) { - return new (zone_) BinaryOperation(zone_, op, left, right, pos); + return new (local_zone_) BinaryOperation(local_zone_, op, left, right, pos); } CountOperation* NewCountOperation(Token::Value op, bool is_prefix, Expression* expr, int pos) { - return new (zone_) CountOperation(zone_, op, is_prefix, expr, pos); + return new (local_zone_) + CountOperation(local_zone_, op, is_prefix, expr, pos); } CompareOperation* NewCompareOperation(Token::Value op, Expression* left, Expression* right, int pos) { - return new (zone_) CompareOperation(zone_, op, left, right, pos); + return new (local_zone_) + CompareOperation(local_zone_, op, left, right, pos); } Spread* NewSpread(Expression* expression, int pos) { - return new (zone_) Spread(zone_, expression, pos); + return new (local_zone_) Spread(local_zone_, expression, pos); } Conditional* NewConditional(Expression* condition, Expression* then_expression, Expression* else_expression, int position) { - return new (zone_) Conditional(zone_, condition, then_expression, - else_expression, position); + return new (local_zone_) Conditional( + local_zone_, condition, then_expression, else_expression, position); } Assignment* NewAssignment(Token::Value op, @@ -3560,7 +3574,8 @@ class AstNodeFactory final BASE_EMBEDDED { Expression* value, int pos) { DCHECK(Token::IsAssignmentOp(op)); - Assignment* assign = new (zone_) Assignment(zone_, op, target, value, pos); + Assignment* assign = + new (local_zone_) Assignment(local_zone_, op, target, value, pos); if (assign->is_compound()) { DCHECK(Token::IsAssignmentOp(op)); assign->binary_operation_ = @@ -3574,12 +3589,12 @@ class AstNodeFactory final BASE_EMBEDDED { Yield::Kind yield_kind, int pos) { if (!expression) expression = NewUndefinedLiteral(pos); - return new (zone_) - Yield(zone_, generator_object, expression, yield_kind, pos); + return new (local_zone_) + Yield(local_zone_, generator_object, expression, yield_kind, pos); } Throw* NewThrow(Expression* exception, int pos) { - return new (zone_) Throw(zone_, exception, pos); + return new (local_zone_) Throw(local_zone_, exception, pos); } FunctionLiteral* NewFunctionLiteral( @@ -3591,11 +3606,11 @@ class AstNodeFactory final BASE_EMBEDDED { FunctionLiteral::IsFunctionFlag is_function, FunctionLiteral::EagerCompileHint eager_compile_hint, FunctionKind kind, int position) { - return new (zone_) FunctionLiteral( - zone_, name, ast_value_factory, scope, body, materialized_literal_count, - expected_property_count, parameter_count, function_type, - has_duplicate_parameters, is_function, eager_compile_hint, kind, - position); + return new (parser_zone_) FunctionLiteral( + parser_zone_, name, ast_value_factory, scope, body, + materialized_literal_count, expected_property_count, parameter_count, + function_type, has_duplicate_parameters, is_function, + eager_compile_hint, kind, position); } ClassLiteral* NewClassLiteral(const AstRawString* name, Scope* scope, @@ -3603,38 +3618,65 @@ class AstNodeFactory final BASE_EMBEDDED { FunctionLiteral* constructor, ZoneList* properties, int start_position, int end_position) { - return new (zone_) - ClassLiteral(zone_, name, scope, proxy, extends, constructor, + return new (parser_zone_) + ClassLiteral(parser_zone_, name, scope, proxy, extends, constructor, properties, start_position, end_position); } NativeFunctionLiteral* NewNativeFunctionLiteral(const AstRawString* name, v8::Extension* extension, int pos) { - return new (zone_) NativeFunctionLiteral(zone_, name, extension, pos); + return new (parser_zone_) + NativeFunctionLiteral(parser_zone_, name, extension, pos); } ThisFunction* NewThisFunction(int pos) { - return new (zone_) ThisFunction(zone_, pos); + return new (local_zone_) ThisFunction(local_zone_, pos); } SuperPropertyReference* NewSuperPropertyReference(VariableProxy* this_var, Expression* home_object, int pos) { - return new (zone_) - SuperPropertyReference(zone_, this_var, home_object, pos); + return new (parser_zone_) + SuperPropertyReference(parser_zone_, this_var, home_object, pos); } SuperCallReference* NewSuperCallReference(VariableProxy* this_var, VariableProxy* new_target_var, VariableProxy* this_function_var, int pos) { - return new (zone_) SuperCallReference(zone_, this_var, new_target_var, - this_function_var, pos); + return new (parser_zone_) SuperCallReference( + parser_zone_, this_var, new_target_var, this_function_var, pos); } + Zone* zone() const { return local_zone_; } + + // Handles use of temporary zones when parsing inner function bodies. + class BodyScope { + public: + BodyScope(AstNodeFactory* factory, Zone* temp_zone, bool use_temp_zone) + : factory_(factory), prev_zone_(factory->local_zone_) { + if (use_temp_zone) { + factory->local_zone_ = temp_zone; + } + } + + ~BodyScope() { factory_->local_zone_ = prev_zone_; } + + private: + AstNodeFactory* factory_; + Zone* prev_zone_; + }; + private: - Zone* zone_; + // This zone may be deallocated upon returning from parsing a function body + // which we can guarantee is not going to be compiled or have its AST + // inspected. + // See ParseFunctionLiteral in parser.cc for preconditions. + Zone* local_zone_; + // ZoneObjects which need to persist until scope analysis must be allocated in + // the parser-level zone. + Zone* parser_zone_; AstValueFactory* ast_value_factory_; }; diff --git a/deps/v8/src/parser.cc b/deps/v8/src/parser.cc index ecc65301350c9e..2b6467ba3d2a0c 100644 --- a/deps/v8/src/parser.cc +++ b/deps/v8/src/parser.cc @@ -4135,10 +4135,44 @@ FunctionLiteral* Parser::ParseFunctionLiteral( } } if (!is_lazily_parsed) { - body = ParseEagerFunctionBody(function_name, pos, formals, kind, - function_type, CHECK_OK); + // Determine whether the function body can be discarded after parsing. + // The preconditions are: + // - Lazy compilation has to be enabled. + // - Neither V8 natives nor native function declarations can be allowed, + // since parsing one would retroactively force the function to be + // eagerly compiled. + // - The invoker of this parser can't depend on the AST being eagerly + // built (either because the function is about to be compiled, or + // because the AST is going to be inspected for some reason). + // - Because of the above, we can't be attempting to parse a + // FunctionExpression; even without enclosing parentheses it might be + // immediately invoked. + // - The function literal shouldn't be hinted to eagerly compile. + bool use_temp_zone = + FLAG_lazy && !allow_natives() && extension_ == NULL && allow_lazy() && + function_type == FunctionLiteral::DECLARATION && + eager_compile_hint != FunctionLiteral::kShouldEagerCompile; + // Open a new BodyScope, which sets our AstNodeFactory to allocate in the + // new temporary zone if the preconditions are satisfied, and ensures that + // the previous zone is always restored after parsing the body. + // For the purpose of scope analysis, some ZoneObjects allocated by the + // factory must persist after the function body is thrown away and + // temp_zone is deallocated. These objects are instead allocated in a + // parser-persistent zone (see parser_zone_ in AstNodeFactory). + { + Zone temp_zone; + AstNodeFactory::BodyScope inner(factory(), &temp_zone, use_temp_zone); + + body = ParseEagerFunctionBody(function_name, pos, formals, kind, + function_type, CHECK_OK); + } materialized_literal_count = function_state.materialized_literal_count(); expected_property_count = function_state.expected_property_count(); + if (use_temp_zone) { + // If the preconditions are correct the function body should never be + // accessed, but do this anyway for better behaviour if they're wrong. + body = NULL; + } } // Parsing the body may change the language mode in our scope. diff --git a/deps/v8/test/cctest/test-parsing.cc b/deps/v8/test/cctest/test-parsing.cc index 23a3d2621a8fa7..94605c6a36cb18 100644 --- a/deps/v8/test/cctest/test-parsing.cc +++ b/deps/v8/test/cctest/test-parsing.cc @@ -1388,6 +1388,68 @@ TEST(ScopePositions) { } +TEST(DiscardFunctionBody) { + // Test that inner function bodies are discarded if possible. + // See comments in ParseFunctionLiteral in parser.cc. + const char* discard_sources[] = { + "(function f() { function g() { var a; } })();", + /* TODO(conradw): In future it may be possible to apply this optimisation + * to these productions. + "(function f() { 0, function g() { var a; } })();", + "(function f() { 0, { g() { var a; } } })();", + "(function f() { 0, class c { g() { var a; } } })();", */ + NULL + }; + + i::Isolate* isolate = CcTest::i_isolate(); + i::Factory* factory = isolate->factory(); + v8::HandleScope handles(CcTest::isolate()); + i::FunctionLiteral* function; + + for (int i = 0; discard_sources[i]; i++) { + const char* source = discard_sources[i]; + i::Handle source_code = + factory->NewStringFromUtf8(i::CStrVector(source)).ToHandleChecked(); + i::Handle script = factory->NewScript(source_code); + i::Zone zone; + i::ParseInfo info(&zone, script); + info.set_allow_lazy_parsing(); + i::Parser parser(&info); + parser.set_allow_harmony_sloppy(true); + parser.Parse(&info); + function = info.literal(); + CHECK_NOT_NULL(function); + CHECK_NOT_NULL(function->body()); + CHECK_EQ(1, function->body()->length()); + i::FunctionLiteral* inner = + function->body()->first()->AsExpressionStatement()->expression()-> + AsCall()->expression()->AsFunctionLiteral(); + i::Scope* inner_scope = inner->scope(); + i::FunctionLiteral* fun = nullptr; + if (inner_scope->declarations()->length() > 1) { + fun = inner_scope->declarations()->at(1)->AsFunctionDeclaration()->fun(); + } else { + // TODO(conradw): This path won't be hit until the other test cases can be + // uncommented. + CHECK_NOT_NULL(inner->body()); + CHECK_GE(2, inner->body()->length()); + i::Expression* exp = inner->body()->at(1)->AsExpressionStatement()-> + expression()->AsBinaryOperation()->right(); + if (exp->IsFunctionLiteral()) { + fun = exp->AsFunctionLiteral(); + } else if (exp->IsObjectLiteral()) { + fun = exp->AsObjectLiteral()->properties()->at(0)->value()-> + AsFunctionLiteral(); + } else { + fun = exp->AsClassLiteral()->properties()->at(0)->value()-> + AsFunctionLiteral(); + } + } + CHECK_NULL(fun->body()); + } +} + + const char* ReadString(unsigned* start) { int length = start[0]; char* result = i::NewArray(length + 1); diff --git a/deps/v8/test/mjsunit/compiler/lazy-iife-no-parens.js b/deps/v8/test/mjsunit/compiler/lazy-iife-no-parens.js new file mode 100644 index 00000000000000..cbad4da4a6454f --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/lazy-iife-no-parens.js @@ -0,0 +1,43 @@ +// 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. + +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation + +// Test that IIFEs are compilable even under lazy conditions where the enclosing +// parentheses heuristic has not been triggered. + +function f() { + return function(){ return 0; }(); +} + +function g() { + function h() { + return function(){ return 0; }(); + } + return h(); +} + +f(); + +g(); + +0, function(){}(); + +(function(){ 0, function(){}(); })(); + +0, function(){ (function(){ 0, function(){}(); })(); }(); diff --git a/deps/v8/tools/run-tests.py b/deps/v8/tools/run-tests.py index 9c6f30a3657591..971843cc678c44 100755 --- a/deps/v8/tools/run-tests.py +++ b/deps/v8/tools/run-tests.py @@ -52,13 +52,6 @@ ARCH_GUESS = utils.DefaultArch() -DEFAULT_TESTS = [ - "mjsunit", - "unittests", - "cctest", - "message", - "preparser", -] # Map of test name synonyms to lists of test suites. Should be ordered by # expected runtimes (suites with slow test cases first). These groups are @@ -69,11 +62,14 @@ "cctest", "message", "preparser", + "intl", + "unittests", ], "optimize_for_size": [ "mjsunit", "cctest", "webkit", + "intl", ], "unittests": [ "unittests", @@ -146,6 +142,7 @@ "x87", "mips", "mipsel", + "mips64", "mips64el", "nacl_ia32", "nacl_x64", @@ -162,6 +159,7 @@ "arm", "mips", "mipsel", + "mips64", "mips64el", "nacl_ia32", "nacl_x64", @@ -171,9 +169,11 @@ def BuildOptions(): result = optparse.OptionParser() + result.usage = '%prog [options] [tests]' + result.description = """TESTS: %s""" % (TEST_MAP["default"]) result.add_option("--arch", help=("The architecture to run tests for, " - "'auto' or 'native' for auto-detect"), + "'auto' or 'native' for auto-detect: %s" % SUPPORTED_ARCHS), default="ia32,x64,arm") result.add_option("--arch-and-mode", help="Architecture and mode in the format 'arch.mode'", @@ -220,7 +220,8 @@ def BuildOptions(): result.add_option("-j", help="The number of parallel tasks to run", default=0, type="int") result.add_option("-m", "--mode", - help="The test modes in which to run (comma-separated)", + help="The test modes in which to run (comma-separated," + " uppercase for ninja and buildbot builds): %s" % MODES.keys(), default="release,debug") result.add_option("--no-harness", "--noharness", help="Run without test harness of a given suite", @@ -248,7 +249,7 @@ def BuildOptions(): help="Don't run any testing variants", default=False, dest="no_variants", action="store_true") result.add_option("--variants", - help="Comma-separated list of testing variants") + help="Comma-separated list of testing variants: %s" % VARIANTS) result.add_option("--outdir", help="Base directory with compile output", default="out") result.add_option("--predictable", @@ -452,8 +453,8 @@ def CheckTestMode(name, option): return False if not CheckTestMode("pass|fail test", options.pass_fail_tests): return False - if not options.no_i18n: - DEFAULT_TESTS.append("intl") + if options.no_i18n: + TEST_MAP["default"].remove("intl") return True @@ -489,6 +490,10 @@ def Main(): suite_paths = utils.GetSuitePaths(join(workspace, "test")) + # Use default tests if no test configuration was provided at the cmd line. + if len(args) == 0: + args = ["default"] + # Expand arguments with grouped tests. The args should reflect the list of # suites as otherwise filters would break. def ExpandTestGroups(name): @@ -500,13 +505,10 @@ def ExpandTestGroups(name): [ExpandTestGroups(arg) for arg in args], []) - if len(args) == 0: - suite_paths = [ s for s in DEFAULT_TESTS if s in suite_paths ] - else: - args_suites = OrderedDict() # Used as set - for arg in args: - args_suites[arg.split('/')[0]] = True - suite_paths = [ s for s in args_suites if s in suite_paths ] + args_suites = OrderedDict() # Used as set + for arg in args: + args_suites[arg.split('/')[0]] = True + suite_paths = [ s for s in args_suites if s in suite_paths ] suites = [] for root in suite_paths: @@ -548,6 +550,8 @@ def Execute(arch, mode, args, options, suites, workspace): "%s.%s" % (arch, MODES[mode]["output_folder"]), ) shell_dir = os.path.relpath(shell_dir) + if not os.path.exists(shell_dir): + raise Exception('Could not find shell_dir: "%s"' % shell_dir) # Populate context object. mode_flags = MODES[mode]["flags"] @@ -586,7 +590,7 @@ def Execute(arch, mode, args, options, suites, workspace): # TODO(all): Combine "simulator" and "simulator_run". simulator_run = not options.dont_skip_simulator_slow_tests and \ - arch in ['arm64', 'arm', 'mipsel', 'mips', 'mips64el', \ + arch in ['arm64', 'arm', 'mipsel', 'mips', 'mips64', 'mips64el', \ 'ppc', 'ppc64'] and \ ARCH_GUESS and arch != ARCH_GUESS # Find available test suites and read test cases from them. @@ -606,6 +610,7 @@ def Execute(arch, mode, args, options, suites, workspace): "msan": options.msan, "dcheck_always_on": options.dcheck_always_on, "novfp3": options.novfp3, + "predictable": options.predictable, "byteorder": sys.byteorder, } all_tests = []