Commit 37aaa410 authored by Leszek Swirski's avatar Leszek Swirski Committed by Commit Bot

[parser] Remove Handles from ParseInfo

Remove the wrapped arguments and outer scope info handles from
ParseInfo, and instead infer them from the SharedFunctionInfo or Script,
or in the case of eval pass it through to the parser as an argument.

Bug: v8:10314
Change-Id: Ia1d1dbab5b62252e10fa2055f7e91f914324efd4
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2106200
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: 's avatarSimon Zünd <szuend@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#66771}
parent ebd85d2c
......@@ -573,10 +573,11 @@ bool DeclarationScope::Analyze(ParseInfo* info) {
DeclarationScope* scope = info->literal()->scope();
base::Optional<AllowHandleDereference> allow_deref;
if (!info->maybe_outer_scope_info().is_null()) {
// Allow dereferences to the scope info if there is one.
#ifdef DEBUG
if (scope->outer_scope() && !scope->outer_scope()->scope_info_.is_null()) {
allow_deref.emplace();
}
#endif
if (scope->is_eval_scope() && is_sloppy(scope->language_mode())) {
AstNodeFactory factory(info->ast_value_factory(), info->zone());
......
......@@ -32,6 +32,7 @@
#include "src/execution/isolate.h"
#include "src/execution/runtime-profiler.h"
#include "src/execution/vm-state-inl.h"
#include "src/handles/maybe-handles.h"
#include "src/heap/heap-inl.h"
#include "src/heap/off-thread-factory-inl.h"
#include "src/init/bootstrapper.h"
......@@ -1075,7 +1076,8 @@ MaybeHandle<SharedFunctionInfo> FinalizeTopLevel(
}
MaybeHandle<SharedFunctionInfo> CompileToplevel(
ParseInfo* parse_info, Handle<Script> script, Isolate* isolate,
ParseInfo* parse_info, Handle<Script> script,
MaybeHandle<ScopeInfo> maybe_outer_scope_info, Isolate* isolate,
IsCompiledScope* is_compiled_scope) {
TimerEventScope<TimerEventCompileCode> top_level_timer(isolate);
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileCode");
......@@ -1088,7 +1090,8 @@ MaybeHandle<SharedFunctionInfo> CompileToplevel(
: RuntimeCallCounterId::kCompileScript);
VMState<BYTECODE_COMPILER> state(isolate);
if (parse_info->literal() == nullptr &&
!parsing::ParseProgram(parse_info, script, isolate)) {
!parsing::ParseProgram(parse_info, script, maybe_outer_scope_info,
isolate)) {
return MaybeHandle<SharedFunctionInfo>();
}
// Measure how long it takes to do the compilation; only take the
......@@ -1135,6 +1138,13 @@ std::unique_ptr<UnoptimizedCompilationJob> CompileOnBackgroundThread(
return outer_function_job;
}
MaybeHandle<SharedFunctionInfo> CompileToplevel(
ParseInfo* parse_info, Handle<Script> script, Isolate* isolate,
IsCompiledScope* is_compiled_scope) {
return CompileToplevel(parse_info, script, kNullMaybeHandle, isolate,
is_compiled_scope);
}
} // namespace
BackgroundCompileTask::BackgroundCompileTask(ScriptStreamingData* streamed_data,
......@@ -1709,10 +1719,12 @@ MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
parse_info.set_eval();
parse_info.set_parse_restriction(restriction);
parse_info.set_parameters_end_pos(parameters_end_pos);
DCHECK(!parse_info.is_module());
MaybeHandle<ScopeInfo> maybe_outer_scope_info;
if (!context->IsNativeContext()) {
parse_info.set_outer_scope_info(handle(context->scope_info(), isolate));
maybe_outer_scope_info = handle(context->scope_info(), isolate);
}
DCHECK(!parse_info.is_module());
script = parse_info.CreateScript(
isolate, source, OriginOptionsForEval(outer_info->script()));
......@@ -1734,7 +1746,8 @@ MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
}
script->set_eval_from_position(eval_position);
if (!CompileToplevel(&parse_info, script, isolate, &is_compiled_scope)
if (!CompileToplevel(&parse_info, script, maybe_outer_scope_info, isolate,
&is_compiled_scope)
.ToHandle(&shared_info)) {
return MaybeHandle<JSFunction>();
}
......@@ -2320,22 +2333,24 @@ MaybeHandle<JSFunction> Compiler::GetWrappedFunction(
parse_info.set_eval(); // Use an eval scope as declaration scope.
parse_info.set_function_syntax_kind(FunctionSyntaxKind::kWrapped);
parse_info.set_wrapped_arguments(arguments);
// TODO(delphick): Remove this and instead make the wrapped and wrapper
// functions fully non-lazy instead thus preventing source positions from
// being omitted.
parse_info.set_collect_source_positions(true);
// parse_info.set_eager(compile_options == ScriptCompiler::kEagerCompile);
MaybeHandle<ScopeInfo> maybe_outer_scope_info;
if (!context->IsNativeContext()) {
parse_info.set_outer_scope_info(handle(context->scope_info(), isolate));
maybe_outer_scope_info = handle(context->scope_info(), isolate);
}
script = NewScript(isolate, &parse_info, source, script_details,
origin_options, NOT_NATIVES_CODE);
script->set_wrapped_arguments(*arguments);
Handle<SharedFunctionInfo> top_level;
maybe_result =
CompileToplevel(&parse_info, script, isolate, &is_compiled_scope);
maybe_result = CompileToplevel(&parse_info, script, maybe_outer_scope_info,
isolate, &is_compiled_scope);
if (maybe_result.is_null()) isolate->ReportPendingMessages();
ASSIGN_RETURN_ON_EXCEPTION(isolate, top_level, maybe_result, JSFunction);
......
......@@ -35,6 +35,7 @@
#include "src/deoptimizer/deoptimizer.h"
#include "src/diagnostics/basic-block-profiler.h"
#include "src/execution/vm-state-inl.h"
#include "src/handles/maybe-handles.h"
#include "src/init/v8.h"
#include "src/interpreter/interpreter.h"
#include "src/logging/counters.h"
......@@ -549,7 +550,8 @@ bool Shell::ExecuteString(Isolate* isolate, Local<String> source,
i::Handle<i::Script> script =
parse_info.CreateScript(i_isolate, str, options.compile_options);
if (!i::parsing::ParseProgram(&parse_info, script, i_isolate)) {
if (!i::parsing::ParseProgram(&parse_info, script, i::kNullMaybeHandle,
i_isolate)) {
fprintf(stderr, "Failed parsing\n");
return false;
}
......
......@@ -244,10 +244,11 @@ void ScopeIterator::TryParseAndRetrieveScopes(ReparseStrategy strategy) {
info_->set_eager();
}
MaybeHandle<ScopeInfo> maybe_outer_scope;
if (scope_info->scope_type() == EVAL_SCOPE || script->is_wrapped()) {
info_->set_eval();
if (!context_->IsNativeContext()) {
info_->set_outer_scope_info(handle(context_->scope_info(), isolate_));
maybe_outer_scope = handle(context_->scope_info(), isolate_);
}
// Language mode may be inherited from the eval caller.
// Retrieve it from shared function info.
......@@ -259,8 +260,12 @@ void ScopeIterator::TryParseAndRetrieveScopes(ReparseStrategy strategy) {
scope_info->scope_type() == FUNCTION_SCOPE);
}
if (parsing::ParseAny(info_, shared_info, isolate_) &&
Rewriter::Rewrite(info_)) {
const bool parse_result =
info_->is_toplevel()
? parsing::ParseProgram(info_, script, maybe_outer_scope, isolate_)
: parsing::ParseFunction(info_, shared_info, isolate_);
if (parse_result && Rewriter::Rewrite(info_)) {
info_->ast_value_factory()->Internalize(isolate_);
DeclarationScope* literal_scope = info_->literal()->scope();
......
......@@ -12,6 +12,10 @@
namespace v8 {
namespace internal {
struct NullMaybeHandleType {};
constexpr NullMaybeHandleType kNullMaybeHandle;
// ----------------------------------------------------------------------------
// A Handle can be converted into a MaybeHandle. Converting a MaybeHandle
// into a Handle requires checking that it does not point to nullptr. This
......@@ -25,6 +29,8 @@ class MaybeHandle final {
public:
V8_INLINE MaybeHandle() = default;
V8_INLINE MaybeHandle(NullMaybeHandleType) {}
// Constructor for handling automatic up casting from Handle.
// Ex. Handle<JSArray> can be passed when MaybeHandle<Object> is expected.
template <typename S, typename = typename std::enable_if<
......
......@@ -107,14 +107,6 @@ ParseInfo::ParseInfo(Isolate* isolate, SharedFunctionInfo shared)
Script script = Script::cast(shared.script());
SetFlagsForFunctionFromScript(script);
if (shared.is_wrapped()) {
DCHECK(script.is_wrapped());
set_wrapped_arguments(handle(script.wrapped_arguments(), isolate));
}
if (shared.HasOuterScopeInfo()) {
set_outer_scope_info(handle(shared.GetOuterScopeInfo(), isolate));
}
set_repl_mode(shared.is_repl_mode());
......@@ -150,7 +142,6 @@ std::unique_ptr<ParseInfo> ParseInfo::FromParent(
DCHECK_EQ(outer_parse_info->parameters_end_pos(), kNoSourcePosition);
DCHECK_NULL(outer_parse_info->extension());
DCHECK(outer_parse_info->maybe_outer_scope_info().is_null());
// Clone the function_name AstRawString into the ParseInfo's own
// AstValueFactory.
......@@ -197,9 +188,7 @@ Handle<Script> ParseInfo::CreateScript(LocalIsolate* isolate,
}
script->set_origin_options(origin_options);
script->set_is_repl_mode(is_repl_mode());
if (is_wrapped_as_function()) {
script->set_wrapped_arguments(*wrapped_arguments());
} else if (is_eval()) {
if (is_eval() && !is_wrapped_as_function()) {
script->set_compilation_type(Script::COMPILATION_TYPE_EVAL);
}
......@@ -267,7 +256,6 @@ void ParseInfo::SetFlagsForToplevelCompileFromScript(
if (script.is_wrapped()) {
set_function_syntax_kind(FunctionSyntaxKind::kWrapped);
set_wrapped_arguments(handle(script.wrapped_arguments(), isolate));
}
}
......@@ -282,7 +270,6 @@ void ParseInfo::CheckFlagsForToplevelCompileFromScript(
if (script.is_wrapped()) {
DCHECK_EQ(function_syntax_kind(), FunctionSyntaxKind::kWrapped);
DCHECK_EQ(*wrapped_arguments(), script.wrapped_arguments());
}
}
......
......@@ -268,21 +268,6 @@ class V8_EXPORT_PRIVATE ParseInfo {
void CheckFlagsForFunctionFromScript(Script script);
//--------------------------------------------------------------------------
// TODO(titzer): these should not be part of ParseInfo.
//--------------------------------------------------------------------------
Handle<FixedArray> wrapped_arguments() const { return wrapped_arguments_; }
void set_wrapped_arguments(Handle<FixedArray> wrapped_arguments) {
wrapped_arguments_ = wrapped_arguments;
}
MaybeHandle<ScopeInfo> maybe_outer_scope_info() const {
return maybe_outer_scope_info_;
}
void set_outer_scope_info(Handle<ScopeInfo> outer_scope_info) {
maybe_outer_scope_info_ = outer_scope_info;
}
int script_id() const { return script_id_; }
//--------------------------------------------------------------------------
......@@ -365,10 +350,6 @@ class V8_EXPORT_PRIVATE ParseInfo {
int function_literal_id_;
int max_function_literal_id_;
// TODO(titzer): Move handles out of ParseInfo.
Handle<FixedArray> wrapped_arguments_;
MaybeHandle<ScopeInfo> maybe_outer_scope_info_;
//----------- Inputs+Outputs of parsing and scope analysis -----------------
std::unique_ptr<Utf16CharacterStream> character_stream_;
std::unique_ptr<ConsumedPreparseData> consumed_preparse_data_;
......
......@@ -515,8 +515,9 @@ void MaybeProcessSourceRanges(ParseInfo* parse_info, Expression* root,
} // namespace
FunctionLiteral* Parser::ParseProgram(Isolate* isolate, Handle<Script> script,
ParseInfo* info) {
FunctionLiteral* Parser::ParseProgram(
Isolate* isolate, Handle<Script> script, ParseInfo* info,
MaybeHandle<ScopeInfo> maybe_outer_scope_info) {
// TODO(bmeurer): We temporarily need to pass allow_nesting = true here,
// see comment for HistogramTimerScope class.
DCHECK_EQ(script->id(), script_id());
......@@ -533,9 +534,14 @@ FunctionLiteral* Parser::ParseProgram(Isolate* isolate, Handle<Script> script,
if (V8_UNLIKELY(FLAG_log_function_events)) timer.Start();
// Initialize parser state.
DeserializeScopeChain(isolate, info, info->maybe_outer_scope_info(),
DeserializeScopeChain(isolate, info, maybe_outer_scope_info,
Scope::DeserializationMode::kIncludingVariables);
DCHECK_EQ(script->is_wrapped(), info->is_wrapped_as_function());
if (script->is_wrapped()) {
maybe_wrapped_arguments_ = handle(script->wrapped_arguments(), isolate);
}
scanner_.Initialize();
FunctionLiteral* result = DoParseProgram(isolate, info);
MaybeResetCharacterStream(info, result);
......@@ -690,7 +696,7 @@ ZonePtrList<const AstRawString>* Parser::PrepareWrappedArguments(
Isolate* isolate, ParseInfo* info, Zone* zone) {
DCHECK(parsing_on_main_thread_);
DCHECK_NOT_NULL(isolate);
Handle<FixedArray> arguments = info->wrapped_arguments();
Handle<FixedArray> arguments = maybe_wrapped_arguments_.ToHandleChecked();
int arguments_length = arguments->length();
ZonePtrList<const AstRawString>* arguments_for_wrapped_function =
new (zone) ZonePtrList<const AstRawString>(arguments_length, zone);
......@@ -796,10 +802,19 @@ FunctionLiteral* Parser::ParseFunction(Isolate* isolate, ParseInfo* info,
base::ElapsedTimer timer;
if (V8_UNLIKELY(FLAG_log_function_events)) timer.Start();
DeserializeScopeChain(isolate, info, info->maybe_outer_scope_info(),
MaybeHandle<ScopeInfo> maybe_outer_scope_info;
if (shared_info->HasOuterScopeInfo()) {
maybe_outer_scope_info = handle(shared_info->GetOuterScopeInfo(), isolate);
}
DeserializeScopeChain(isolate, info, maybe_outer_scope_info,
Scope::DeserializationMode::kIncludingVariables);
DCHECK_EQ(factory()->zone(), info->zone());
if (shared_info->is_wrapped()) {
maybe_wrapped_arguments_ = handle(
Script::cast(shared_info->script()).wrapped_arguments(), isolate);
}
// Initialize parser state.
Handle<String> name(shared_info->Name(), isolate);
info->set_function_name(ast_value_factory()->GetString(name));
......@@ -3080,7 +3095,6 @@ void Parser::ParseOnBackground(ParseInfo* info) {
FunctionLiteral* result = nullptr;
scanner_.Initialize();
DCHECK(info->maybe_outer_scope_info().is_null());
DCHECK(original_scope_);
......
......@@ -166,8 +166,8 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
friend class i::ParameterDeclarationParsingScope<ParserTypes<Parser>>;
friend class i::ArrowHeadParsingScope<ParserTypes<Parser>>;
friend bool v8::internal::parsing::ParseProgram(
ParseInfo*, Handle<Script>, Isolate*,
parsing::ReportErrorsAndStatisticsMode stats_mode);
ParseInfo*, Handle<Script>, MaybeHandle<ScopeInfo> maybe_outer_scope_info,
Isolate*, parsing::ReportErrorsAndStatisticsMode stats_mode);
friend bool v8::internal::parsing::ParseFunction(
ParseInfo*, Handle<SharedFunctionInfo> shared_info, Isolate*,
parsing::ReportErrorsAndStatisticsMode stats_mode);
......@@ -209,7 +209,8 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
// Returns nullptr if parsing failed.
FunctionLiteral* ParseProgram(Isolate* isolate, Handle<Script> script,
ParseInfo* info);
ParseInfo* info,
MaybeHandle<ScopeInfo> maybe_outer_scope_info);
FunctionLiteral* ParseFunction(Isolate* isolate, ParseInfo* info,
Handle<SharedFunctionInfo> shared_info);
......@@ -1043,6 +1044,8 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
PreParser* reusable_preparser_;
Mode mode_;
MaybeHandle<FixedArray> maybe_wrapped_arguments_;
SourceRangeMap* source_range_map_ = nullptr;
friend class ParserTargetScope;
......
......@@ -8,6 +8,7 @@
#include "src/ast/ast.h"
#include "src/execution/vm-state-inl.h"
#include "src/handles/maybe-handles.h"
#include "src/objects/objects-inl.h"
#include "src/parsing/parse-info.h"
#include "src/parsing/parser.h"
......@@ -18,8 +19,9 @@ namespace v8 {
namespace internal {
namespace parsing {
bool ParseProgram(ParseInfo* info, Handle<Script> script, Isolate* isolate,
ReportErrorsAndStatisticsMode mode) {
bool ParseProgram(ParseInfo* info, Handle<Script> script,
MaybeHandle<ScopeInfo> maybe_outer_scope_info,
Isolate* isolate, ReportErrorsAndStatisticsMode mode) {
DCHECK(info->is_toplevel());
DCHECK_NULL(info->literal());
......@@ -38,7 +40,7 @@ bool ParseProgram(ParseInfo* info, Handle<Script> script, Isolate* isolate,
// Ok to use Isolate here; this function is only called in the main thread.
DCHECK(parser.parsing_on_main_thread_);
result = parser.ParseProgram(isolate, script, info);
result = parser.ParseProgram(isolate, script, info, maybe_outer_scope_info);
info->set_literal(result);
if (result) {
info->set_language_mode(info->literal()->language_mode());
......@@ -57,6 +59,11 @@ bool ParseProgram(ParseInfo* info, Handle<Script> script, Isolate* isolate,
return (result != nullptr);
}
bool ParseProgram(ParseInfo* info, Handle<Script> script, Isolate* isolate,
ReportErrorsAndStatisticsMode mode) {
return ParseProgram(info, script, kNullMaybeHandle, isolate, mode);
}
bool ParseFunction(ParseInfo* info, Handle<SharedFunctionInfo> shared_info,
Isolate* isolate, ReportErrorsAndStatisticsMode mode) {
DCHECK(!info->is_toplevel());
......@@ -102,11 +109,17 @@ bool ParseFunction(ParseInfo* info, Handle<SharedFunctionInfo> shared_info,
bool ParseAny(ParseInfo* info, Handle<SharedFunctionInfo> shared_info,
Isolate* isolate, ReportErrorsAndStatisticsMode mode) {
DCHECK(!shared_info.is_null());
return info->is_toplevel()
? ParseProgram(
info, handle(Script::cast(shared_info->script()), isolate),
isolate, mode)
: ParseFunction(info, shared_info, isolate, mode);
if (info->is_toplevel()) {
MaybeHandle<ScopeInfo> maybe_outer_scope_info;
if (shared_info->HasOuterScopeInfo()) {
maybe_outer_scope_info =
handle(shared_info->GetOuterScopeInfo(), isolate);
}
return ParseProgram(info,
handle(Script::cast(shared_info->script()), isolate),
maybe_outer_scope_info, isolate, mode);
}
return ParseFunction(info, shared_info, isolate, mode);
}
} // namespace parsing
......
......@@ -18,12 +18,21 @@ namespace parsing {
enum class ReportErrorsAndStatisticsMode { kYes, kNo };
// Parses the top-level source code represented by the parse info and sets its
// function literal. Returns false (and deallocates any allocated AST
// nodes) if parsing failed.
// function literal. Returns false (and deallocates any allocated AST nodes) if
// parsing failed.
V8_EXPORT_PRIVATE bool ParseProgram(
ParseInfo* info, Handle<Script> script, Isolate* isolate,
ReportErrorsAndStatisticsMode mode = ReportErrorsAndStatisticsMode::kYes);
// Parses the top-level source code represented by the parse info and sets its
// function literal. Allows passing an |outer_scope| for programs that exist in
// another scope (e.g. eval). Returns false (and deallocates any allocated AST
// nodes) if parsing failed.
V8_EXPORT_PRIVATE bool ParseProgram(
ParseInfo* info, Handle<Script> script, MaybeHandle<ScopeInfo> outer_scope,
Isolate* isolate,
ReportErrorsAndStatisticsMode mode = ReportErrorsAndStatisticsMode::kYes);
// Like ParseProgram but for an individual function which already has a
// allocated shared function info.
V8_EXPORT_PRIVATE bool ParseFunction(
......
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