Commit b3e1eb0c authored by Leszek Swirski's avatar Leszek Swirski Committed by V8 LUCI CQ

[compiler] Introduce ReusableUnoptimizedCompileState

Introduce a ReusableUnoptimizedCompileState class, passed to ParseInfo,
which stores a couple of pointers and most importantly the Zone and
AstValueFactory of the parse. This allows the Zone and AstValueFactory
to be reused across multiple parses, rather than re-initialising
per-Parse.

With this, we can amend the LazyCompileDispatcher to initialise one
LocalIsolate, Zone and AstValueFactory per background thread loop,
rather than one per compile task, which allows us to reduce per-task
costs and re-use the AstValueFactory's string table and previous String
internalizations.

Change-Id: Ia0e29c4e31fbe29af57674ebb10916865d38b2ce
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3313106Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/main@{#78289}
parent 4ae67baf
......@@ -367,8 +367,6 @@ AstConsString* AstValueFactory::NewConsString(const AstRawString* str1,
template <typename IsolateT>
void AstValueFactory::Internalize(IsolateT* isolate) {
if (!zone_) return;
// Strings need to be internalized before values, because values refer to
// strings.
for (AstRawString* current = strings_; current != nullptr;) {
......@@ -378,7 +376,6 @@ void AstValueFactory::Internalize(IsolateT* isolate) {
}
ResetStrings();
zone_ = nullptr;
}
template EXPORT_TEMPLATE_DEFINE(
V8_EXPORT_PRIVATE) void AstValueFactory::Internalize(Isolate* isolate);
......
This diff is collapsed.
......@@ -511,12 +511,13 @@ class V8_EXPORT_PRIVATE BackgroundCompileTask {
// Compiler::FinalizeBackgroundCompileTask.
BackgroundCompileTask(
Isolate* isolate, Handle<SharedFunctionInfo> shared_info,
const UnoptimizedCompileState* compile_state,
std::unique_ptr<Utf16CharacterStream> character_stream,
WorkerThreadRuntimeCallStats* worker_thread_runtime_stats,
TimedHistogram* timer, int max_stack_size);
void Run();
void Run(LocalIsolate* isolate,
ReusableUnoptimizedCompileState* reusable_state);
MaybeHandle<SharedFunctionInfo> FinalizeScript(
Isolate* isolate, Handle<String> source,
......
......@@ -19,7 +19,7 @@ UnoptimizedCompilationInfo::UnoptimizedCompilationInfo(Zone* zone,
ParseInfo* parse_info,
FunctionLiteral* literal)
: flags_(parse_info->flags()),
state_(parse_info->state()),
dispatcher_(parse_info->dispatcher()),
character_stream_(parse_info->character_stream()),
feedback_vector_spec_(zone) {
// NOTE: The parse_info passed here represents the global information gathered
......
......@@ -35,7 +35,7 @@ class V8_EXPORT_PRIVATE UnoptimizedCompilationInfo final {
FunctionLiteral* literal);
const UnoptimizedCompileFlags& flags() const { return flags_; }
const UnoptimizedCompileState* state() const { return state_; }
LazyCompileDispatcher* dispatcher() { return dispatcher_; }
const Utf16CharacterStream* character_stream() const {
return character_stream_;
}
......@@ -90,8 +90,8 @@ class V8_EXPORT_PRIVATE UnoptimizedCompilationInfo final {
// Compilation flags.
const UnoptimizedCompileFlags flags_;
// Compilation state.
const UnoptimizedCompileState* state_;
// For dispatching eager compilation of lazily compiled functions.
LazyCompileDispatcher* dispatcher_;
const Utf16CharacterStream* character_stream_;
// The root AST node of the function literal being compiled.
......
......@@ -13,11 +13,14 @@
#include "src/codegen/compiler.h"
#include "src/flags/flags.h"
#include "src/handles/global-handles-inl.h"
#include "src/heap/parked-scope.h"
#include "src/logging/counters.h"
#include "src/logging/runtime-call-stats-scope.h"
#include "src/numbers/hash-seed-inl.h"
#include "src/objects/objects-inl.h"
#include "src/parsing/parse-info.h"
#include "src/parsing/parser.h"
#include "src/roots/roots.h"
#include "src/tasks/cancelable-task.h"
#include "src/tasks/task-utils.h"
#include "src/zone/zone-list-inl.h" // crbug.com/v8/8816
......@@ -86,7 +89,6 @@ LazyCompileDispatcher::~LazyCompileDispatcher() {
void LazyCompileDispatcher::Enqueue(
LocalIsolate* isolate, Handle<SharedFunctionInfo> shared_info,
const UnoptimizedCompileState* compile_state,
std::unique_ptr<Utf16CharacterStream> character_stream) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.LazyCompilerDispatcherEnqueue");
......@@ -94,7 +96,7 @@ void LazyCompileDispatcher::Enqueue(
std::unique_ptr<Job> job =
std::make_unique<Job>(std::make_unique<BackgroundCompileTask>(
isolate_, shared_info, compile_state, std::move(character_stream),
isolate_, shared_info, std::move(character_stream),
worker_thread_runtime_call_stats_, background_compile_timer_,
static_cast<int>(max_stack_size_)));
......@@ -259,6 +261,17 @@ void LazyCompileDispatcher::ScheduleIdleTaskFromAnyThread(
void LazyCompileDispatcher::DoBackgroundWork(JobDelegate* delegate) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.LazyCompileDispatcherDoBackgroundWork");
WorkerThreadRuntimeCallStatsScope worker_thread_scope(
worker_thread_runtime_call_stats_);
LocalIsolate isolate(isolate_, ThreadKind::kBackground,
worker_thread_scope.Get());
UnparkedScope unparked_scope(&isolate);
LocalHandleScope handle_scope(&isolate);
ReusableUnoptimizedCompileState reusable_state(&isolate);
while (!delegate->ShouldYield()) {
Job* job = nullptr;
{
......@@ -281,7 +294,7 @@ void LazyCompileDispatcher::DoBackgroundWork(JobDelegate* delegate) {
PrintF("LazyCompileDispatcher: doing background work\n");
}
job->task->Run();
job->task->Run(&isolate, &reusable_state);
{
base::MutexGuard lock(&mutex_);
......
......@@ -85,7 +85,6 @@ class V8_EXPORT_PRIVATE LazyCompileDispatcher {
~LazyCompileDispatcher();
void Enqueue(LocalIsolate* isolate, Handle<SharedFunctionInfo> shared_info,
const UnoptimizedCompileState* compile_state,
std::unique_ptr<Utf16CharacterStream> character_stream);
// Returns true if there is a pending job registered for the given function.
......
......@@ -687,7 +687,8 @@ bool Shell::ExecuteString(Isolate* isolate, Local<String> source,
i::Handle<i::String> str = Utils::OpenHandle(*(source));
// Set up ParseInfo.
i::UnoptimizedCompileState compile_state(i_isolate);
i::UnoptimizedCompileState compile_state;
i::ReusableUnoptimizedCompileState reusable_state(i_isolate);
i::UnoptimizedCompileFlags flags =
i::UnoptimizedCompileFlags::ForToplevelCompile(
......@@ -698,7 +699,7 @@ bool Shell::ExecuteString(Isolate* isolate, Local<String> source,
flags.set_is_eager(true);
}
i::ParseInfo parse_info(i_isolate, flags, &compile_state);
i::ParseInfo parse_info(i_isolate, flags, &compile_state, &reusable_state);
i::Handle<i::Script> script = parse_info.CreateScript(
i_isolate, str, i::kNullMaybeHandle, ScriptOriginOptions());
......
......@@ -272,9 +272,12 @@ void ScopeIterator::TryParseAndRetrieveScopes(ReparseStrategy strategy) {
scope_info->scope_type() == FUNCTION_SCOPE);
}
UnoptimizedCompileState compile_state(isolate_);
UnoptimizedCompileState compile_state;
info_ = std::make_unique<ParseInfo>(isolate_, flags, &compile_state);
reusable_compile_state_ =
std::make_unique<ReusableUnoptimizedCompileState>(isolate_);
info_ = std::make_unique<ParseInfo>(isolate_, flags, &compile_state,
reusable_compile_state_.get());
const bool parse_result =
flags.is_toplevel()
......
......@@ -8,6 +8,7 @@
#include <vector>
#include "src/debug/debug-frames.h"
#include "src/parsing/parse-info.h"
namespace v8 {
namespace internal {
......@@ -110,6 +111,7 @@ class ScopeIterator {
private:
Isolate* isolate_;
std::unique_ptr<ReusableUnoptimizedCompileState> reusable_compile_state_;
std::unique_ptr<ParseInfo> info_;
FrameInspector* const frame_inspector_ = nullptr;
Handle<JSGeneratorObject> generator_;
......
......@@ -1545,10 +1545,11 @@ void FindBreakablePositions(Handle<DebugInfo> debug_info, int start_position,
}
bool CompileTopLevel(Isolate* isolate, Handle<Script> script) {
UnoptimizedCompileState compile_state(isolate);
UnoptimizedCompileState compile_state;
ReusableUnoptimizedCompileState reusable_state(isolate);
UnoptimizedCompileFlags flags =
UnoptimizedCompileFlags::ForScriptCompile(isolate, *script);
ParseInfo parse_info(isolate, flags, &compile_state);
ParseInfo parse_info(isolate, flags, &compile_state, &reusable_state);
IsCompiledScope is_compiled_scope;
const MaybeHandle<SharedFunctionInfo> maybe_result =
Compiler::CompileToplevel(&parse_info, script, isolate,
......
......@@ -984,22 +984,25 @@ void LiveEdit::PatchScript(Isolate* isolate, Handle<Script> script,
return;
}
UnoptimizedCompileState compile_state(isolate);
ReusableUnoptimizedCompileState reusable_state(isolate);
UnoptimizedCompileState compile_state;
UnoptimizedCompileFlags flags =
UnoptimizedCompileFlags::ForScriptCompile(isolate, *script);
flags.set_is_eager(true);
ParseInfo parse_info(isolate, flags, &compile_state);
ParseInfo parse_info(isolate, flags, &compile_state, &reusable_state);
std::vector<FunctionLiteral*> literals;
if (!ParseScript(isolate, script, &parse_info, false, &literals, result))
return;
Handle<Script> new_script = isolate->factory()->CloneScript(script);
new_script->set_source(*new_source);
UnoptimizedCompileState new_compile_state(isolate);
UnoptimizedCompileState new_compile_state;
UnoptimizedCompileFlags new_flags =
UnoptimizedCompileFlags::ForScriptCompile(isolate, *new_script);
new_flags.set_is_eager(true);
ParseInfo new_parse_info(isolate, new_flags, &new_compile_state);
ParseInfo new_parse_info(isolate, new_flags, &new_compile_state,
&reusable_state);
std::vector<FunctionLiteral*> new_literals;
if (!ParseScript(isolate, new_script, &new_parse_info, true, &new_literals,
result)) {
......
......@@ -67,6 +67,17 @@ class V8_EXPORT_PRIVATE LocalIsolate final : private HiddenLocalFactory {
base::SharedMutex* internalized_string_access() {
return isolate_->internalized_string_access();
}
const AstStringConstants* ast_string_constants() {
return isolate_->ast_string_constants();
}
LazyCompileDispatcher* lazy_compile_dispatcher() {
return isolate_->lazy_compile_dispatcher();
}
Logger* main_thread_logger() {
// TODO(leszeks): This is needed for logging in ParseInfo. Figure out a way
// to use the LocalLogger for this instead.
return isolate_->logger();
}
v8::internal::LocalFactory* factory() {
// Upcast to the privately inherited base-class using c-style casts to avoid
......
......@@ -779,8 +779,9 @@ Handle<String> RenderCallSite(Isolate* isolate, Handle<Object> object,
if (ComputeLocation(isolate, location)) {
UnoptimizedCompileFlags flags = UnoptimizedCompileFlags::ForFunctionCompile(
isolate, *location->shared());
UnoptimizedCompileState compile_state(isolate);
ParseInfo info(isolate, flags, &compile_state);
UnoptimizedCompileState compile_state;
ReusableUnoptimizedCompileState reusable_state(isolate);
ParseInfo info(isolate, flags, &compile_state, &reusable_state);
if (parsing::ParseAny(&info, location->shared(), isolate,
parsing::ReportStatisticsMode::kNo)) {
info.ast_value_factory()->Internalize(isolate);
......@@ -838,8 +839,9 @@ Object ErrorUtils::ThrowSpreadArgError(Isolate* isolate, MessageTemplate id,
if (ComputeLocation(isolate, &location)) {
UnoptimizedCompileFlags flags = UnoptimizedCompileFlags::ForFunctionCompile(
isolate, *location.shared());
UnoptimizedCompileState compile_state(isolate);
ParseInfo info(isolate, flags, &compile_state);
UnoptimizedCompileState compile_state;
ReusableUnoptimizedCompileState reusable_state(isolate);
ParseInfo info(isolate, flags, &compile_state, &reusable_state);
if (parsing::ParseAny(&info, location.shared(), isolate,
parsing::ReportStatisticsMode::kNo)) {
info.ast_value_factory()->Internalize(isolate);
......@@ -914,8 +916,9 @@ Object ErrorUtils::ThrowLoadFromNullOrUndefined(Isolate* isolate,
UnoptimizedCompileFlags flags = UnoptimizedCompileFlags::ForFunctionCompile(
isolate, *location.shared());
UnoptimizedCompileState compile_state(isolate);
ParseInfo info(isolate, flags, &compile_state);
UnoptimizedCompileState compile_state;
ReusableUnoptimizedCompileState reusable_state(isolate);
ParseInfo info(isolate, flags, &compile_state, &reusable_state);
if (parsing::ParseAny(&info, location.shared(), isolate,
parsing::ReportStatisticsMode::kNo)) {
info.ast_value_factory()->Internalize(isolate);
......
......@@ -2528,7 +2528,7 @@ void BytecodeGenerator::AddToEagerLiteralsIfEager(FunctionLiteral* literal) {
literal->ShouldEagerCompile(),
info()->flags().post_parallel_compile_tasks_for_eager_toplevel());
// There exists a lazy compile dispatcher.
DCHECK(info()->state()->dispatcher());
DCHECK(info()->dispatcher());
// There exists a cloneable character stream.
DCHECK(info()->character_stream()->can_be_cloned_for_parallel_access());
......@@ -2542,9 +2542,8 @@ void BytecodeGenerator::AddToEagerLiteralsIfEager(FunctionLiteral* literal) {
.ToHandle(&shared_info)) {
shared_info =
Compiler::GetSharedFunctionInfo(literal, script_, local_isolate_);
info()->state()->dispatcher()->Enqueue(
local_isolate_, shared_info, info()->state(),
info()->character_stream()->Clone());
info()->dispatcher()->Enqueue(local_isolate_, shared_info,
info()->character_stream()->Clone());
}
} else if (eager_inner_literals_ && literal->ShouldEagerCompile()) {
DCHECK(!IsInEagerLiterals(literal, *eager_inner_literals_));
......
......@@ -17,9 +17,11 @@ namespace v8 {
namespace internal {
class Isolate;
class LocalIsolate;
class ReadOnlyRoots;
inline uint64_t HashSeed(Isolate* isolate);
inline uint64_t HashSeed(LocalIsolate* isolate);
inline uint64_t HashSeed(ReadOnlyRoots roots);
} // namespace internal
......@@ -36,6 +38,10 @@ inline uint64_t HashSeed(Isolate* isolate) {
return HashSeed(ReadOnlyRoots(isolate));
}
inline uint64_t HashSeed(LocalIsolate* isolate) {
return HashSeed(ReadOnlyRoots(isolate));
}
inline uint64_t HashSeed(ReadOnlyRoots roots) {
uint64_t seed;
roots.hash_seed().copy_out(0, reinterpret_cast<byte*>(&seed), kInt64Size);
......
......@@ -169,34 +169,44 @@ void UnoptimizedCompileFlags::SetFlagsForFunctionFromScript(Script script) {
script.IsUserJavaScript());
}
UnoptimizedCompileState::UnoptimizedCompileState(Isolate* isolate)
ReusableUnoptimizedCompileState::ReusableUnoptimizedCompileState(
Isolate* isolate)
: hash_seed_(HashSeed(isolate)),
allocator_(isolate->allocator()),
ast_string_constants_(isolate->ast_string_constants()),
logger_(isolate->logger()),
dispatcher_(isolate->lazy_compile_dispatcher()) {}
dispatcher_(isolate->lazy_compile_dispatcher()),
ast_string_constants_(isolate->ast_string_constants()),
zone_(allocator_, "unoptimized-compile-zone"),
ast_value_factory_(
new AstValueFactory(zone(), ast_string_constants(), hash_seed())) {}
UnoptimizedCompileState::UnoptimizedCompileState(
const UnoptimizedCompileState& other) V8_NOEXCEPT
: hash_seed_(other.hash_seed()),
allocator_(other.allocator()),
ast_string_constants_(other.ast_string_constants()),
logger_(other.logger()),
dispatcher_(other.dispatcher()) {}
ReusableUnoptimizedCompileState::ReusableUnoptimizedCompileState(
LocalIsolate* isolate)
: hash_seed_(HashSeed(isolate)),
allocator_(isolate->allocator()),
logger_(isolate->main_thread_logger()),
dispatcher_(isolate->lazy_compile_dispatcher()),
ast_string_constants_(isolate->ast_string_constants()),
zone_(allocator_, "unoptimized-compile-zone"),
ast_value_factory_(
new AstValueFactory(zone(), ast_string_constants(), hash_seed())) {}
ReusableUnoptimizedCompileState::~ReusableUnoptimizedCompileState() = default;
ParseInfo::ParseInfo(const UnoptimizedCompileFlags flags,
UnoptimizedCompileState* state, uintptr_t stack_limit,
UnoptimizedCompileState* state,
ReusableUnoptimizedCompileState* reusable_state,
uintptr_t stack_limit,
RuntimeCallStats* runtime_call_stats)
: flags_(flags),
state_(state),
zone_(std::make_unique<Zone>(state->allocator(), "parser-zone")),
reusable_state_(reusable_state),
extension_(nullptr),
script_scope_(nullptr),
stack_limit_(stack_limit),
parameters_end_pos_(kNoSourcePosition),
max_function_literal_id_(kFunctionLiteralIdInvalid),
character_stream_(nullptr),
ast_value_factory_(nullptr),
function_name_(nullptr),
runtime_call_stats_(runtime_call_stats),
source_range_map_(nullptr),
......@@ -212,13 +222,18 @@ ParseInfo::ParseInfo(const UnoptimizedCompileFlags flags,
}
ParseInfo::ParseInfo(Isolate* isolate, const UnoptimizedCompileFlags flags,
UnoptimizedCompileState* state)
: ParseInfo(flags, state, isolate->stack_guard()->real_climit(),
UnoptimizedCompileState* state,
ReusableUnoptimizedCompileState* reusable_state)
: ParseInfo(flags, state, reusable_state,
isolate->stack_guard()->real_climit(),
isolate->counters()->runtime_call_stats()) {}
ParseInfo::ParseInfo(LocalIsolate* isolate, const UnoptimizedCompileFlags flags,
UnoptimizedCompileState* state, uintptr_t stack_limit)
: ParseInfo(flags, state, stack_limit, isolate->runtime_call_stats()) {}
UnoptimizedCompileState* state,
ReusableUnoptimizedCompileState* reusable_state,
uintptr_t stack_limit)
: ParseInfo(flags, state, reusable_state, stack_limit,
isolate->runtime_call_stats()) {}
ParseInfo::~ParseInfo() = default;
......@@ -270,14 +285,6 @@ template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
MaybeHandle<FixedArray> maybe_wrapped_arguments,
ScriptOriginOptions origin_options, NativesFlag natives);
AstValueFactory* ParseInfo::GetOrCreateAstValueFactory() {
if (!ast_value_factory_.get()) {
ast_value_factory_.reset(
new AstValueFactory(zone(), ast_string_constants(), hash_seed()));
}
return ast_value_factory();
}
void ParseInfo::AllocateSourceRangeMap() {
DCHECK(flags().block_coverage_enabled());
DCHECK_NULL(source_range_map());
......
......@@ -161,39 +161,61 @@ class ParseInfo;
// The mutable state for a parse + unoptimized compile operation.
class V8_EXPORT_PRIVATE UnoptimizedCompileState {
public:
explicit UnoptimizedCompileState(Isolate*);
UnoptimizedCompileState(const UnoptimizedCompileState& other) V8_NOEXCEPT;
const PendingCompilationErrorHandler* pending_error_handler() const {
return &pending_error_handler_;
}
PendingCompilationErrorHandler* pending_error_handler() {
return &pending_error_handler_;
}
private:
PendingCompilationErrorHandler pending_error_handler_;
};
// A container for ParseInfo fields that are reusable across multiple parses and
// unoptimized compiles.
//
// Note that this is different from UnoptimizedCompileState, which has mutable
// state for a single compilation that is not reusable across multiple
// compilations.
class V8_EXPORT_PRIVATE ReusableUnoptimizedCompileState {
public:
explicit ReusableUnoptimizedCompileState(Isolate* isolate);
explicit ReusableUnoptimizedCompileState(LocalIsolate* isolate);
~ReusableUnoptimizedCompileState();
Zone* zone() { return &zone_; }
AstValueFactory* ast_value_factory() const {
return ast_value_factory_.get();
}
uint64_t hash_seed() const { return hash_seed_; }
AccountingAllocator* allocator() const { return allocator_; }
const AstStringConstants* ast_string_constants() const {
return ast_string_constants_;
}
Logger* logger() const { return logger_; }
PendingCompilationErrorHandler* pending_error_handler() {
return &pending_error_handler_;
}
const PendingCompilationErrorHandler* pending_error_handler() const {
return &pending_error_handler_;
}
LazyCompileDispatcher* dispatcher() const { return dispatcher_; }
private:
uint64_t hash_seed_;
AccountingAllocator* allocator_;
const AstStringConstants* ast_string_constants_;
PendingCompilationErrorHandler pending_error_handler_;
Logger* logger_;
LazyCompileDispatcher* dispatcher_;
const AstStringConstants* ast_string_constants_;
Zone zone_;
std::unique_ptr<AstValueFactory> ast_value_factory_;
};
// A container for the inputs, configuration options, and outputs of parsing.
class V8_EXPORT_PRIVATE ParseInfo {
public:
ParseInfo(Isolate* isolate, const UnoptimizedCompileFlags flags,
UnoptimizedCompileState* state);
UnoptimizedCompileState* state,
ReusableUnoptimizedCompileState* reusable_state);
ParseInfo(LocalIsolate* isolate, const UnoptimizedCompileFlags flags,
UnoptimizedCompileState* state, uintptr_t stack_limit);
UnoptimizedCompileState* state,
ReusableUnoptimizedCompileState* reusable_state,
uintptr_t stack_limit);
~ParseInfo();
......@@ -204,26 +226,28 @@ class V8_EXPORT_PRIVATE ParseInfo {
ScriptOriginOptions origin_options,
NativesFlag natives = NOT_NATIVES_CODE);
// Either returns the ast-value-factory associcated with this ParseInfo, or
// creates and returns a new factory if none exists.
AstValueFactory* GetOrCreateAstValueFactory();
Zone* zone() const { return zone_.get(); }
Zone* zone() const { return reusable_state_->zone(); }
const UnoptimizedCompileFlags& flags() const { return flags_; }
// Getters for state.
uint64_t hash_seed() const { return state_->hash_seed(); }
AccountingAllocator* allocator() const { return state_->allocator(); }
// Getters for reusable state.
uint64_t hash_seed() const { return reusable_state_->hash_seed(); }
AccountingAllocator* allocator() const {
return reusable_state_->allocator();
}
const AstStringConstants* ast_string_constants() const {
return state_->ast_string_constants();
return reusable_state_->ast_string_constants();
}
Logger* logger() const { return reusable_state_->logger(); }
LazyCompileDispatcher* dispatcher() const {
return reusable_state_->dispatcher();
}
Logger* logger() const { return state_->logger(); }
const UnoptimizedCompileState* state() const { return state_; }
// Getters for state.
PendingCompilationErrorHandler* pending_error_handler() {
return state_->pending_error_handler();
}
LazyCompileDispatcher* dispatcher() const { return state_->dispatcher(); }
const UnoptimizedCompileState* state() const { return state_; }
// Accessors for per-thread state.
uintptr_t stack_limit() const { return stack_limit_; }
......@@ -264,8 +288,7 @@ class V8_EXPORT_PRIVATE ParseInfo {
}
AstValueFactory* ast_value_factory() const {
DCHECK(ast_value_factory_.get());
return ast_value_factory_.get();
return reusable_state_->ast_value_factory();
}
const AstRawString* function_name() const { return function_name_; }
......@@ -302,6 +325,7 @@ class V8_EXPORT_PRIVATE ParseInfo {
private:
ParseInfo(const UnoptimizedCompileFlags flags, UnoptimizedCompileState* state,
ReusableUnoptimizedCompileState* reusable_state,
uintptr_t stack_limit, RuntimeCallStats* runtime_call_stats);
void CheckFlagsForToplevelCompileFromScript(Script script,
......@@ -310,8 +334,8 @@ class V8_EXPORT_PRIVATE ParseInfo {
//------------- Inputs to parsing and scope analysis -----------------------
const UnoptimizedCompileFlags flags_;
UnoptimizedCompileState* state_;
ReusableUnoptimizedCompileState* reusable_state_;
std::unique_ptr<Zone> zone_;
v8::Extension* extension_;
DeclarationScope* script_scope_;
uintptr_t stack_limit_;
......@@ -321,7 +345,6 @@ class V8_EXPORT_PRIVATE ParseInfo {
//----------- Inputs+Outputs of parsing and scope analysis -----------------
std::unique_ptr<Utf16CharacterStream> character_stream_;
std::unique_ptr<ConsumedPreparseData> consumed_preparse_data_;
std::unique_ptr<AstValueFactory> ast_value_factory_;
const AstRawString* function_name_;
RuntimeCallStats* runtime_call_stats_;
SourceRangeMap* source_range_map_; // Used when block coverage is enabled.
......
......@@ -424,7 +424,7 @@ Parser::Parser(LocalIsolate* local_isolate, ParseInfo* info,
Handle<Script> script)
: ParserBase<Parser>(
info->zone(), &scanner_, info->stack_limit(),
info->GetOrCreateAstValueFactory(), info->pending_error_handler(),
info->ast_value_factory(), info->pending_error_handler(),
info->runtime_call_stats(), info->logger(), info->flags(), true),
local_isolate_(local_isolate),
info_(info),
......
......@@ -685,6 +685,7 @@ TEST(PreParserScopeAnalysis) {
v8::base::SNPrintF(program, code, inner.params, inner.source);
i::HandleScope scope(isolate);
i::ReusableUnoptimizedCompileState reusable_state(isolate);
i::Handle<i::String> source =
factory->InternalizeUtf8String(program.begin());
......@@ -713,8 +714,9 @@ TEST(PreParserScopeAnalysis) {
flags.set_is_lazy_compile(true);
// Parse the lazy function using the scope data.
i::UnoptimizedCompileState using_scope_state(isolate);
i::ParseInfo using_scope_data(isolate, flags, &using_scope_state);
i::UnoptimizedCompileState using_scope_state;
i::ParseInfo using_scope_data(isolate, flags, &using_scope_state,
&reusable_state);
using_scope_data.set_consumed_preparse_data(
i::ConsumedPreparseData::For(isolate, produced_data_on_heap));
CHECK(i::parsing::ParseFunction(&using_scope_data, shared, isolate,
......@@ -727,8 +729,9 @@ TEST(PreParserScopeAnalysis) {
scope_with_skipped_functions));
// Parse the lazy function again eagerly to produce baseline data.
i::UnoptimizedCompileState not_using_scope_state(isolate);
i::ParseInfo not_using_scope_data(isolate, flags, &not_using_scope_state);
i::UnoptimizedCompileState not_using_scope_state;
i::ParseInfo not_using_scope_data(isolate, flags, &not_using_scope_state,
&reusable_state);
CHECK(i::parsing::ParseFunction(&not_using_scope_data, shared, isolate,
i::parsing::ReportStatisticsMode::kYes));
......@@ -760,10 +763,11 @@ TEST(Regress753896) {
i::Handle<i::String> source = factory->InternalizeUtf8String(
"function lazy() { let v = 0; if (true) { var v = 0; } }");
i::Handle<i::Script> script = factory->NewScript(source);
i::UnoptimizedCompileState state(isolate);
i::UnoptimizedCompileState state;
i::ReusableUnoptimizedCompileState reusable_state(isolate);
i::UnoptimizedCompileFlags flags =
i::UnoptimizedCompileFlags::ForScriptCompile(isolate, *script);
i::ParseInfo info(isolate, flags, &state);
i::ParseInfo info(isolate, flags, &state, &reusable_state);
// We don't assert that parsing succeeded or that it failed; currently the
// error is not detected inside lazy functions, but it might be in the future.
......
This diff is collapsed.
......@@ -83,11 +83,12 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
v8::internal::Handle<v8::internal::Script> script =
factory->NewScript(source.ToHandleChecked());
v8::internal::UnoptimizedCompileState state(i_isolate);
v8::internal::UnoptimizedCompileState state;
v8::internal::ReusableUnoptimizedCompileState reusable_state(i_isolate);
v8::internal::UnoptimizedCompileFlags flags =
v8::internal::UnoptimizedCompileFlags::ForScriptCompile(i_isolate,
*script);
v8::internal::ParseInfo info(i_isolate, flags, &state);
v8::internal::ParseInfo info(i_isolate, flags, &state, &reusable_state);
if (!v8::internal::parsing::ParseProgram(
&info, script, i_isolate, i::parsing::ReportStatisticsMode::kYes)) {
info.pending_error_handler()->PrepareErrors(i_isolate,
......
......@@ -19,6 +19,7 @@
#include "src/objects/objects-inl.h"
#include "src/parsing/parse-info.h"
#include "src/parsing/parsing.h"
#include "src/parsing/scanner-character-streams.h"
#include "src/zone/zone-list-inl.h"
#include "test/unittests/test-helpers.h"
#include "test/unittests/test-utils.h"
......@@ -74,13 +75,9 @@ class LazyCompileDispatcherTest : public TestWithNativeContext {
static void EnqueueUnoptimizedCompileJob(LazyCompileDispatcher* dispatcher,
Isolate* isolate,
Handle<SharedFunctionInfo> shared) {
UnoptimizedCompileState state(isolate);
std::unique_ptr<ParseInfo> outer_parse_info =
test::OuterParseInfoForShared(isolate, shared, &state);
if (dispatcher->IsEnqueued(shared)) return;
dispatcher->Enqueue(isolate->main_thread_local_isolate(), shared,
outer_parse_info->state(),
outer_parse_info->character_stream()->Clone());
test::SourceCharacterStreamForShared(isolate, shared));
}
};
......
......@@ -55,13 +55,13 @@ class LocalFactoryTest : public TestWithIsolateAndZone {
public:
LocalFactoryTest()
: TestWithIsolateAndZone(),
state_(isolate()),
reusable_state_(isolate()),
parse_info_(
isolate(),
UnoptimizedCompileFlags::ForToplevelCompile(
isolate(), true, construct_language_mode(FLAG_use_strict),
REPLMode::kNo, ScriptType::kClassic, FLAG_lazy),
&state_),
&state_, &reusable_state_),
local_isolate_(isolate()->main_thread_local_isolate()) {}
FunctionLiteral* ParseProgram(const char* source) {
......@@ -105,6 +105,7 @@ class LocalFactoryTest : public TestWithIsolateAndZone {
private:
SaveFlags save_flags_;
UnoptimizedCompileState state_;
ReusableUnoptimizedCompileState reusable_state_;
ParseInfo parse_info_;
LocalIsolate* local_isolate_;
Handle<String> source_string_;
......
......@@ -51,17 +51,8 @@ class BackgroundCompileTaskTest : public TestWithNativeContext {
BackgroundCompileTask* NewBackgroundCompileTask(
Isolate* isolate, Handle<SharedFunctionInfo> shared,
size_t stack_size = FLAG_stack_size) {
UnoptimizedCompileState state(isolate);
std::unique_ptr<ParseInfo> outer_parse_info =
test::OuterParseInfoForShared(isolate, shared, &state);
AstValueFactory* ast_value_factory =
outer_parse_info->GetOrCreateAstValueFactory();
AstNodeFactory ast_node_factory(ast_value_factory,
outer_parse_info->zone());
return new BackgroundCompileTask(
isolate, shared, outer_parse_info->state(),
outer_parse_info->character_stream()->Clone(),
isolate, shared, test::SourceCharacterStreamForShared(isolate, shared),
isolate->counters()->worker_thread_runtime_call_stats(),
isolate->counters()->compile_function_on_background(), FLAG_stack_size);
}
......
......@@ -52,22 +52,15 @@ Handle<SharedFunctionInfo> CreateSharedFunctionInfo(
return scope.CloseAndEscape(shared);
}
std::unique_ptr<ParseInfo> OuterParseInfoForShared(
Isolate* isolate, Handle<SharedFunctionInfo> shared,
UnoptimizedCompileState* state) {
Script script = Script::cast(shared->script());
std::unique_ptr<ParseInfo> result = std::make_unique<ParseInfo>(
isolate, i::UnoptimizedCompileFlags::ForScriptCompile(isolate, script),
state);
std::unique_ptr<Utf16CharacterStream> SourceCharacterStreamForShared(
Isolate* isolate, Handle<SharedFunctionInfo> shared) {
// Create a character stream to simulate the parser having done so for the
// top-level ParseProgram.
Script script = Script::cast(shared->script());
Handle<String> source(String::cast(script.source()), isolate);
std::unique_ptr<Utf16CharacterStream> stream(
ScannerStream::For(isolate, source));
result->set_character_stream(std::move(stream));
return result;
return stream;
}
} // namespace test
......
......@@ -8,7 +8,6 @@
#include <memory>
#include "include/v8-primitive.h"
#include "src/parsing/parse-info.h"
namespace v8 {
......@@ -20,6 +19,9 @@ class Object;
template <typename T>
class Handle;
class Isolate;
class SharedFunctionInfo;
class String;
class Utf16CharacterStream;
namespace test {
......@@ -45,9 +47,8 @@ Handle<String> CreateSource(
Handle<SharedFunctionInfo> CreateSharedFunctionInfo(
Isolate* isolate,
v8::String::ExternalOneByteStringResource* maybe_resource);
std::unique_ptr<ParseInfo> OuterParseInfoForShared(
Isolate* isolate, Handle<SharedFunctionInfo> shared,
UnoptimizedCompileState* state);
std::unique_ptr<Utf16CharacterStream> SourceCharacterStreamForShared(
Isolate* isolate, Handle<SharedFunctionInfo> shared);
} // namespace test
} // namespace internal
......
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