diff --git a/src/ast/ast.h b/src/ast/ast.h index c44129b7b2..3872819f8e 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -2238,8 +2238,10 @@ class FunctionLiteral final : public Expression { return function_type() == kAnonymousExpression; } - void mark_as_iife() { bit_field_ = IIFEBit::update(bit_field_, true); } - bool is_iife() const { return IIFEBit::decode(bit_field_); } + void mark_as_oneshot_iife() { + bit_field_ = OneshotIIFEBit::update(bit_field_, true); + } + bool is_oneshot_iife() const { return OneshotIIFEBit::decode(bit_field_); } bool is_toplevel() const { return function_literal_id() == FunctionLiteral::kIdTypeTopLevel; } @@ -2370,13 +2372,13 @@ class FunctionLiteral final : public Expression { body_(0, nullptr), raw_inferred_name_(ast_value_factory->empty_cons_string()), produced_preparse_data_(produced_preparse_data) { - bit_field_ |= FunctionTypeBits::encode(function_type) | - Pretenure::encode(false) | - HasDuplicateParameters::encode(has_duplicate_parameters == - kHasDuplicateParameters) | - DontOptimizeReasonField::encode(BailoutReason::kNoReason) | - RequiresInstanceMembersInitializer::encode(false) | - HasBracesField::encode(has_braces) | IIFEBit::encode(false); + bit_field_ |= + FunctionTypeBits::encode(function_type) | Pretenure::encode(false) | + HasDuplicateParameters::encode(has_duplicate_parameters == + kHasDuplicateParameters) | + DontOptimizeReasonField::encode(BailoutReason::kNoReason) | + RequiresInstanceMembersInitializer::encode(false) | + HasBracesField::encode(has_braces) | OneshotIIFEBit::encode(false); if (eager_compile_hint == kShouldEagerCompile) SetShouldEagerCompile(); body.CopyTo(&body_, zone); } @@ -2391,7 +2393,7 @@ class FunctionLiteral final : public Expression { : public BitField {}; class HasBracesField : public BitField {}; - class IIFEBit : public BitField {}; + class OneshotIIFEBit : public BitField {}; int expected_property_count_; int parameter_count_; diff --git a/src/compiler.cc b/src/compiler.cc index 3f333d2429..6e2f9d3590 100644 --- a/src/compiler.cc +++ b/src/compiler.cc @@ -406,7 +406,7 @@ void SetSharedFunctionFlagsFromLiteral(FunctionLiteral* literal, } shared_info->set_has_duplicate_parameters( literal->has_duplicate_parameters()); - shared_info->set_is_iife(literal->is_iife()); + shared_info->set_is_oneshot_iife(literal->is_oneshot_iife()); shared_info->SetExpectedNofPropertiesFromEstimate(literal); if (literal->dont_optimize_reason() != BailoutReason::kNoReason) { shared_info->DisableOptimization(literal->dont_optimize_reason()); diff --git a/src/interpreter/bytecode-generator.cc b/src/interpreter/bytecode-generator.cc index f6d97d0e66..0115ba80db 100644 --- a/src/interpreter/bytecode-generator.cc +++ b/src/interpreter/bytecode-generator.cc @@ -1907,11 +1907,8 @@ bool BytecodeGenerator::ShouldOptimizeAsOneShot() const { if (loop_depth_ > 0) return false; - // A non-top-level iife is likely to be executed multiple times and so - // shouldn`t be optimized as one-shot. - bool is_toplevel_iife = info()->literal()->is_iife() && - current_scope()->outer_scope()->is_script_scope(); - return info()->literal()->is_toplevel() || is_toplevel_iife; + return info()->literal()->is_toplevel() || + info()->literal()->is_oneshot_iife(); } void BytecodeGenerator::BuildClassLiteral(ClassLiteral* expr, Register name) { diff --git a/src/objects/shared-function-info-inl.h b/src/objects/shared-function-info-inl.h index c57920aa65..5484441030 100644 --- a/src/objects/shared-function-info-inl.h +++ b/src/objects/shared-function-info-inl.h @@ -222,8 +222,8 @@ BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, is_named_expression, SharedFunctionInfo::IsNamedExpressionBit) BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, is_toplevel, SharedFunctionInfo::IsTopLevelBit) -BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, is_iife, - SharedFunctionInfo::IsIIFEBit) +BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, is_oneshot_iife, + SharedFunctionInfo::IsOneshotIIFEBit) bool SharedFunctionInfo::optimization_disabled() const { return disable_optimization_reason() != BailoutReason::kNoReason; diff --git a/src/objects/shared-function-info.h b/src/objects/shared-function-info.h index 583edd8285..baaacd538c 100644 --- a/src/objects/shared-function-info.h +++ b/src/objects/shared-function-info.h @@ -489,8 +489,9 @@ class SharedFunctionInfo : public HeapObject { DECL_BOOLEAN_ACCESSORS(is_anonymous_expression) // Indicates that the function represented by the shared function info was - // classed as an immediately invoked function execution (IIFE) function. - DECL_BOOLEAN_ACCESSORS(is_iife) + // classed as an immediately invoked function execution (IIFE) function and + // is only executed once. + DECL_BOOLEAN_ACCESSORS(is_oneshot_iife) // Indicates that the function has been reported for binary code coverage. DECL_BOOLEAN_ACCESSORS(has_reported_binary_coverage) @@ -700,7 +701,7 @@ class SharedFunctionInfo : public HeapObject { V(HasReportedBinaryCoverageBit, bool, 1, _) \ V(IsNamedExpressionBit, bool, 1, _) \ V(IsTopLevelBit, bool, 1, _) \ - V(IsIIFEBit, bool, 1, _) + V(IsOneshotIIFEBit, bool, 1, _) DEFINE_BIT_FIELDS(FLAGS_BIT_FIELDS) #undef FLAGS_BIT_FIELDS diff --git a/src/parsing/parse-info.cc b/src/parsing/parse-info.cc index 5e7ce6a8bf..3050e01b48 100644 --- a/src/parsing/parse-info.cc +++ b/src/parsing/parse-info.cc @@ -80,7 +80,7 @@ void ParseInfo::SetFunctionInfo(T function) { set_requires_instance_members_initializer( function->requires_instance_members_initializer()); set_toplevel(function->is_toplevel()); - set_is_iife(function->is_iife()); + set_is_oneshot_iife(function->is_oneshot_iife()); set_wrapped_as_function(function->is_wrapped()); } diff --git a/src/parsing/parse-info.h b/src/parsing/parse-info.h index 8b2d66dc60..7ab236c82d 100644 --- a/src/parsing/parse-info.h +++ b/src/parsing/parse-info.h @@ -114,7 +114,7 @@ class V8_EXPORT_PRIVATE ParseInfo { set_allow_harmony_private_fields); FLAG_ACCESSOR(kAllowHarmonyPrivateMethods, allow_harmony_private_methods, set_allow_harmony_private_methods); - FLAG_ACCESSOR(kIsIIFE, is_iife, set_is_iife); + FLAG_ACCESSOR(kIsOneshotIIFE, is_oneshot_iife, set_is_oneshot_iife); #undef FLAG_ACCESSOR void set_parse_restriction(ParseRestriction restriction) { @@ -311,7 +311,7 @@ class V8_EXPORT_PRIVATE ParseInfo { kAllowHarmonyNumericSeparator = 1 << 26, kAllowHarmonyPrivateFields = 1 << 27, kAllowHarmonyPrivateMethods = 1 << 28, - kIsIIFE = 1 << 29 + kIsOneshotIIFE = 1 << 29 }; //------------- Inputs to parsing and scope analysis ----------------------- diff --git a/src/parsing/parser-base.h b/src/parsing/parser-base.h index e6d639cd1d..b8039d0ec9 100644 --- a/src/parsing/parser-base.h +++ b/src/parsing/parser-base.h @@ -3061,7 +3061,11 @@ ParserBase::ParseLeftHandSideContinuation(ExpressionT result) { // function literal eagerly, we can also compile it eagerly. if (result->IsFunctionLiteral()) { result->AsFunctionLiteral()->SetShouldEagerCompile(); - result->AsFunctionLiteral()->mark_as_iife(); + if (scope()->is_script_scope()) { + // A non-top-level iife is likely to be executed multiple times + // and so shouldn`t be optimized as one-shot. + result->AsFunctionLiteral()->mark_as_oneshot_iife(); + } } } bool has_spread; diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc index 0a3033c531..ba244ad298 100644 --- a/src/parsing/parser.cc +++ b/src/parsing/parser.cc @@ -859,8 +859,8 @@ FunctionLiteral* Parser::DoParseFunction(Isolate* isolate, ParseInfo* info, if (has_error()) return nullptr; result->set_requires_instance_members_initializer( info->requires_instance_members_initializer()); - if (info->is_iife()) { - result->mark_as_iife(); + if (info->is_oneshot_iife()) { + result->mark_as_oneshot_iife(); } } diff --git a/src/parsing/preparser.h b/src/parsing/preparser.h index d3de3a4edb..aa218c7ee3 100644 --- a/src/parsing/preparser.h +++ b/src/parsing/preparser.h @@ -310,7 +310,7 @@ class PreParserExpression { // More dummy implementations of things PreParser doesn't need to track: void SetShouldEagerCompile() {} - void mark_as_iife() {} + void mark_as_oneshot_iife() {} int position() const { return kNoSourcePosition; } void set_function_token_position(int position) {} diff --git a/test/cctest/interpreter/bytecode_expectations/IIFEWithOneshotOpt.golden b/test/cctest/interpreter/bytecode_expectations/IIFEWithOneshotOpt.golden index 124711e73c..9bffe3bf79 100644 --- a/test/cctest/interpreter/bytecode_expectations/IIFEWithOneshotOpt.golden +++ b/test/cctest/interpreter/bytecode_expectations/IIFEWithOneshotOpt.golden @@ -565,9 +565,9 @@ snippet: " } " -frame size: 3 +frame size: 2 parameter count: 1 -bytecode array length: 46 +bytecode array length: 43 bytecodes: [ B(CreateMappedArguments), B(Star), R(0), @@ -577,17 +577,15 @@ bytecodes: [ /* 111 S> */ B(LdaGlobal), U8(0), U8(2), B(Star), R(1), B(LdaSmi), I8(3), - /* 115 E> */ B(StaNamedPropertyNoFeedback), R(1), U8(1), U8(0), + /* 115 E> */ B(StaNamedProperty), R(1), U8(1), U8(4), /* 130 S> */ B(LdaGlobal), U8(0), U8(2), B(Star), R(1), B(LdaSmi), I8(4), - /* 134 E> */ B(StaNamedPropertyNoFeedback), R(1), U8(2), U8(0), - /* 149 S> */ B(LdaUndefined), - B(Star), R(2), - B(LdaGlobal), U8(3), U8(4), + /* 134 E> */ B(StaNamedProperty), R(1), U8(2), U8(6), + /* 149 S> */ B(LdaGlobal), U8(3), U8(8), B(Star), R(1), - /* 149 E> */ B(CallNoFeedback), R(1), R(2), U8(1), - /* 182 S> */ B(LdaNamedPropertyNoFeedback), R(0), U8(4), + /* 149 E> */ B(CallUndefinedReceiver0), R(1), U8(10), + /* 182 S> */ B(LdaNamedProperty), R(0), U8(4), U8(12), /* 189 S> */ B(Return), ] constant pool: [ diff --git a/test/cctest/interpreter/test-bytecode-generator.cc b/test/cctest/interpreter/test-bytecode-generator.cc index 4664d1e3df..4519cd9a5a 100644 --- a/test/cctest/interpreter/test-bytecode-generator.cc +++ b/test/cctest/interpreter/test-bytecode-generator.cc @@ -664,6 +664,7 @@ TEST(IIFEWithOneshotOpt) { return arguments.callee; })(); )", + // TODO(rmcilroy): Make this function produce one-shot code. R"( var t = 0; function f2() {};