Commit 43253f7a authored by Shu-yu Guo's avatar Shu-yu Guo Committed by V8 LUCI CQ

Revert "[off-thread] Allow off-thread top-level IIFE finalization"

This reverts commit 35a6eeec.

Reason for revert: TSAN failures like https://ci.chromium.org/ui/p/v8/builders/ci/V8%20Linux64%20TSAN/39084/overview

Original change's description:
> [off-thread] Allow off-thread top-level IIFE finalization
>
> Allow off-thread finalization for parallel compile tasks (i.e. for top-
> level IIFEs).
>
> This allows us to merge the code paths in BackgroundCompileTask, and
> re-enable the compiler dispatcher tests under the off-thread
> finalization flag. Indeed, we can simplify further and get rid of that
> flag entirely (it has been on-by-default for several releases now).
>
> Change-Id: I54f361997d651667fa813ec09790a6aab4d26774
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3226780
> Reviewed-by: Toon Verwaest <verwaest@chromium.org>
> Commit-Queue: Leszek Swirski <leszeks@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#77615}

Change-Id: I6752470eebd594bad92c7cf4e58dbe5bac53598c
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3255667Reviewed-by: 's avatarShu-yu Guo <syg@chromium.org>
Commit-Queue: Shu-yu Guo <syg@chromium.org>
Owners-Override: Shu-yu Guo <syg@chromium.org>
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Cr-Commit-Position: refs/heads/main@{#77631}
parent 9acf61bc
This diff is collapsed.
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
#include <forward_list> #include <forward_list>
#include <memory> #include <memory>
#include "src/ast/ast-value-factory.h"
#include "src/base/platform/elapsed-timer.h" #include "src/base/platform/elapsed-timer.h"
#include "src/codegen/bailout-reason.h" #include "src/codegen/bailout-reason.h"
#include "src/common/globals.h" #include "src/common/globals.h"
...@@ -496,7 +495,8 @@ using DeferredFinalizationJobDataList = ...@@ -496,7 +495,8 @@ using DeferredFinalizationJobDataList =
class V8_EXPORT_PRIVATE BackgroundCompileTask { class V8_EXPORT_PRIVATE BackgroundCompileTask {
public: public:
// Creates a new task that when run will parse and compile the streamed // Creates a new task that when run will parse and compile the streamed
// script associated with |data| and can be finalized with FinalizeScript. // script associated with |data| and can be finalized with
// Compiler::GetSharedFunctionInfoForStreamedScript.
// Note: does not take ownership of |data|. // Note: does not take ownership of |data|.
BackgroundCompileTask(ScriptStreamingData* data, Isolate* isolate, BackgroundCompileTask(ScriptStreamingData* data, Isolate* isolate,
v8::ScriptType type); v8::ScriptType type);
...@@ -505,44 +505,68 @@ class V8_EXPORT_PRIVATE BackgroundCompileTask { ...@@ -505,44 +505,68 @@ class V8_EXPORT_PRIVATE BackgroundCompileTask {
~BackgroundCompileTask(); ~BackgroundCompileTask();
// Creates a new task that when run will parse and compile the // Creates a new task that when run will parse and compile the
// |function_literal| and can be finalized with FinalizeFunction // |function_literal| and can be finalized with
// Compiler::FinalizeBackgroundCompileTask. // Compiler::FinalizeBackgroundCompileTask.
BackgroundCompileTask( BackgroundCompileTask(
Isolate* isolate, const ParseInfo* outer_parse_info, const ParseInfo* outer_parse_info, const AstRawString* function_name,
const AstRawString* function_name,
const FunctionLiteral* function_literal, const FunctionLiteral* function_literal,
WorkerThreadRuntimeCallStats* worker_thread_runtime_stats, WorkerThreadRuntimeCallStats* worker_thread_runtime_stats,
TimedHistogram* timer, int max_stack_size); TimedHistogram* timer, int max_stack_size);
void Run(); void Run();
MaybeHandle<SharedFunctionInfo> FinalizeScript( ParseInfo* info() {
Isolate* isolate, Handle<String> source, DCHECK_NOT_NULL(info_);
const ScriptDetails& script_details); return info_.get();
}
Parser* parser() { return parser_.get(); }
UnoptimizedCompilationJobList* compilation_jobs() {
return &compilation_jobs_;
}
UnoptimizedCompileFlags flags() const { return flags_; }
UnoptimizedCompileState* compile_state() { return &compile_state_; }
LanguageMode language_mode() { return language_mode_; }
FinalizeUnoptimizedCompilationDataList*
finalize_unoptimized_compilation_data() {
return &finalize_unoptimized_compilation_data_;
}
bool FinalizeFunction(Isolate* isolate, int use_count(v8::Isolate::UseCounterFeature feature) const {
Handle<SharedFunctionInfo> shared_info, return use_counts_[static_cast<int>(feature)];
Compiler::ClearExceptionFlag flag); }
int total_preparse_skipped() const { return total_preparse_skipped_; }
UnoptimizedCompileFlags flags() const { return flags_; } // Jobs which could not be finalized in the background task, and need to be
LanguageMode language_mode() const { return language_mode_; } // finalized on the main thread.
DeferredFinalizationJobDataList* jobs_to_retry_finalization_on_main_thread() {
return &jobs_to_retry_finalization_on_main_thread_;
}
private: // Getters for the off-thread finalization results, that create main-thread
void ReportStatistics(Isolate* isolate); // handles to the objects.
MaybeHandle<SharedFunctionInfo> GetOuterFunctionSfi(Isolate* isolate);
Handle<Script> GetScript(Isolate* isolate);
// Data needed for parsing and compilation. These need to be initialized private:
// before the compilation starts. // Data needed for parsing, and data needed to to be passed between thread
Isolate* isolate_for_local_isolate_; // between parsing and compilation. These need to be initialized before the
// compilation starts.
UnoptimizedCompileFlags flags_; UnoptimizedCompileFlags flags_;
UnoptimizedCompileState compile_state_; UnoptimizedCompileState compile_state_;
std::unique_ptr<ParseInfo> info_; std::unique_ptr<ParseInfo> info_;
int stack_size_; std::unique_ptr<Parser> parser_;
WorkerThreadRuntimeCallStats* worker_thread_runtime_call_stats_;
TimedHistogram* timer_;
// Data needed for merging onto the main thread. // Data needed for finalizing compilation after background compilation.
UnoptimizedCompilationJobList compilation_jobs_;
// Data needed for merging onto the main thread after background finalization.
// TODO(leszeks): When these are available, the above fields are not. We
// should add some stricter type-safety or DCHECKs to ensure that the user of
// the task knows this.
Isolate* isolate_for_local_isolate_;
std::unique_ptr<PersistentHandles> persistent_handles_; std::unique_ptr<PersistentHandles> persistent_handles_;
MaybeHandle<SharedFunctionInfo> outer_function_sfi_; MaybeHandle<SharedFunctionInfo> outer_function_sfi_;
Handle<Script> script_;
IsCompiledScope is_compiled_scope_; IsCompiledScope is_compiled_scope_;
FinalizeUnoptimizedCompilationDataList finalize_unoptimized_compilation_data_; FinalizeUnoptimizedCompilationDataList finalize_unoptimized_compilation_data_;
DeferredFinalizationJobDataList jobs_to_retry_finalization_on_main_thread_; DeferredFinalizationJobDataList jobs_to_retry_finalization_on_main_thread_;
...@@ -550,11 +574,13 @@ class V8_EXPORT_PRIVATE BackgroundCompileTask { ...@@ -550,11 +574,13 @@ class V8_EXPORT_PRIVATE BackgroundCompileTask {
int total_preparse_skipped_ = 0; int total_preparse_skipped_ = 0;
// Single function data for top-level function compilation. // Single function data for top-level function compilation.
Handle<Script> script_;
int start_position_; int start_position_;
int end_position_; int end_position_;
int function_literal_id_; int function_literal_id_;
int stack_size_;
WorkerThreadRuntimeCallStats* worker_thread_runtime_call_stats_;
TimedHistogram* timer_;
LanguageMode language_mode_; LanguageMode language_mode_;
}; };
......
...@@ -86,7 +86,7 @@ base::Optional<LazyCompileDispatcher::JobId> LazyCompileDispatcher::Enqueue( ...@@ -86,7 +86,7 @@ base::Optional<LazyCompileDispatcher::JobId> LazyCompileDispatcher::Enqueue(
RCS_SCOPE(isolate_, RuntimeCallCounterId::kCompileEnqueueOnDispatcher); RCS_SCOPE(isolate_, RuntimeCallCounterId::kCompileEnqueueOnDispatcher);
std::unique_ptr<Job> job = std::make_unique<Job>(new BackgroundCompileTask( std::unique_ptr<Job> job = std::make_unique<Job>(new BackgroundCompileTask(
isolate_, outer_parse_info, function_name, function_literal, outer_parse_info, function_name, function_literal,
worker_thread_runtime_call_stats_, background_compile_timer_, worker_thread_runtime_call_stats_, background_compile_timer_,
static_cast<int>(max_stack_size_))); static_cast<int>(max_stack_size_)));
JobMap::const_iterator it = InsertJob(std::move(job)); JobMap::const_iterator it = InsertJob(std::move(job));
......
...@@ -668,9 +668,8 @@ bool Shell::ExecuteString(Isolate* isolate, Local<String> source, ...@@ -668,9 +668,8 @@ bool Shell::ExecuteString(Isolate* isolate, Local<String> source,
i::ParseInfo parse_info(i_isolate, flags, &compile_state); i::ParseInfo parse_info(i_isolate, flags, &compile_state);
parse_info.InitializeScript(i_isolate, str, i::kNullMaybeHandle, i::Handle<i::Script> script = parse_info.CreateScript(
ScriptOriginOptions()); i_isolate, str, i::kNullMaybeHandle, ScriptOriginOptions());
i::Handle<i::Script> script = parse_info.script();
if (!i::parsing::ParseProgram(&parse_info, script, i_isolate, if (!i::parsing::ParseProgram(&parse_info, script, i_isolate,
i::parsing::ReportStatisticsMode::kYes)) { i::parsing::ReportStatisticsMode::kYes)) {
parse_info.pending_error_handler()->PrepareErrors( parse_info.pending_error_handler()->PrepareErrors(
......
...@@ -445,8 +445,8 @@ DEFINE_NEG_IMPLICATION(enable_third_party_heap, allocation_site_pretenuring) ...@@ -445,8 +445,8 @@ DEFINE_NEG_IMPLICATION(enable_third_party_heap, allocation_site_pretenuring)
DEFINE_NEG_IMPLICATION(enable_third_party_heap, turbo_allocation_folding) DEFINE_NEG_IMPLICATION(enable_third_party_heap, turbo_allocation_folding)
DEFINE_NEG_IMPLICATION(enable_third_party_heap, concurrent_recompilation) DEFINE_NEG_IMPLICATION(enable_third_party_heap, concurrent_recompilation)
DEFINE_NEG_IMPLICATION(enable_third_party_heap, concurrent_inlining) DEFINE_NEG_IMPLICATION(enable_third_party_heap, concurrent_inlining)
DEFINE_NEG_IMPLICATION(enable_third_party_heap, script_streaming) DEFINE_NEG_IMPLICATION(enable_third_party_heap,
DEFINE_NEG_IMPLICATION(enable_third_party_heap, parallel_compile_tasks) finalize_streaming_on_background)
DEFINE_NEG_IMPLICATION(enable_third_party_heap, use_marking_progress_bar) DEFINE_NEG_IMPLICATION(enable_third_party_heap, use_marking_progress_bar)
DEFINE_NEG_IMPLICATION(enable_third_party_heap, move_object_start) DEFINE_NEG_IMPLICATION(enable_third_party_heap, move_object_start)
DEFINE_NEG_IMPLICATION(enable_third_party_heap, concurrent_marking) DEFINE_NEG_IMPLICATION(enable_third_party_heap, concurrent_marking)
...@@ -1479,8 +1479,14 @@ DEFINE_BOOL(enable_regexp_unaligned_accesses, true, ...@@ -1479,8 +1479,14 @@ DEFINE_BOOL(enable_regexp_unaligned_accesses, true,
DEFINE_BOOL(script_streaming, true, "enable parsing on background") DEFINE_BOOL(script_streaming, true, "enable parsing on background")
DEFINE_BOOL(stress_background_compile, false, DEFINE_BOOL(stress_background_compile, false,
"stress test parsing on background") "stress test parsing on background")
DEFINE_BOOL(
finalize_streaming_on_background, true,
"perform the script streaming finalization on the background thread")
DEFINE_BOOL(concurrent_cache_deserialization, true, DEFINE_BOOL(concurrent_cache_deserialization, true,
"enable deserializing code caches on background") "enable deserializing code caches on background")
// TODO(leszeks): Parallel compile tasks currently don't support off-thread
// finalization.
DEFINE_NEG_IMPLICATION(parallel_compile_tasks, finalize_streaming_on_background)
DEFINE_BOOL(disable_old_api_accessors, false, DEFINE_BOOL(disable_old_api_accessors, false,
"Disable old-style API accessors whose setters trigger through the " "Disable old-style API accessors whose setters trigger through the "
"prototype chain") "prototype chain")
......
...@@ -305,24 +305,6 @@ Handle<SharedFunctionInfo> FactoryBase<Impl>::NewSharedFunctionInfoForLiteral( ...@@ -305,24 +305,6 @@ Handle<SharedFunctionInfo> FactoryBase<Impl>::NewSharedFunctionInfoForLiteral(
return shared; return shared;
} }
template <typename Impl>
Handle<SharedFunctionInfo>
FactoryBase<Impl>::NewPlaceholderSharedFunctionInfoForLazyLiteral(
FunctionLiteral* literal, Handle<Script> script) {
FunctionKind kind = literal->kind();
Handle<SharedFunctionInfo> shared =
NewSharedFunctionInfo(literal->GetName(isolate()), MaybeHandle<Code>(),
Builtin::kCompileLazy, kind);
// Don't fully initialise the SFI from the function literal, since we e.g.
// might not have the scope info, but initialise just enough to work for
// compilation/finalization.
shared->set_function_literal_id(literal->function_literal_id());
// Set the script on the SFI, but don't make the script's SFI list point back
// to this SFI.
shared->set_script(*script);
return shared;
}
template <typename Impl> template <typename Impl>
Handle<PreparseData> FactoryBase<Impl>::NewPreparseData(int data_length, Handle<PreparseData> FactoryBase<Impl>::NewPreparseData(int data_length,
int children_length) { int children_length) {
......
...@@ -162,9 +162,6 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) FactoryBase ...@@ -162,9 +162,6 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) FactoryBase
Handle<SharedFunctionInfo> NewSharedFunctionInfoForLiteral( Handle<SharedFunctionInfo> NewSharedFunctionInfoForLiteral(
FunctionLiteral* literal, Handle<Script> script, bool is_toplevel); FunctionLiteral* literal, Handle<Script> script, bool is_toplevel);
Handle<SharedFunctionInfo> NewPlaceholderSharedFunctionInfoForLazyLiteral(
FunctionLiteral* literal, Handle<Script> script);
Handle<PreparseData> NewPreparseData(int data_length, int children_length); Handle<PreparseData> NewPreparseData(int data_length, int children_length);
Handle<UncompiledDataWithoutPreparseData> Handle<UncompiledDataWithoutPreparseData>
......
...@@ -240,7 +240,7 @@ ParseInfo::~ParseInfo() = default; ...@@ -240,7 +240,7 @@ ParseInfo::~ParseInfo() = default;
DeclarationScope* ParseInfo::scope() const { return literal()->scope(); } DeclarationScope* ParseInfo::scope() const { return literal()->scope(); }
template <typename IsolateT> template <typename IsolateT>
void ParseInfo::InitializeScript( Handle<Script> ParseInfo::CreateScript(
IsolateT* isolate, Handle<String> source, IsolateT* isolate, Handle<String> source,
MaybeHandle<FixedArray> maybe_wrapped_arguments, MaybeHandle<FixedArray> maybe_wrapped_arguments,
ScriptOriginOptions origin_options, NativesFlag natives) { ScriptOriginOptions origin_options, NativesFlag natives) {
...@@ -271,18 +271,19 @@ void ParseInfo::InitializeScript( ...@@ -271,18 +271,19 @@ void ParseInfo::InitializeScript(
CheckFlagsForToplevelCompileFromScript(*script, CheckFlagsForToplevelCompileFromScript(*script,
isolate->is_collecting_type_profile()); isolate->is_collecting_type_profile());
return script;
script_ = script;
} }
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) void ParseInfo:: template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
InitializeScript(Isolate* isolate, Handle<String> source, Handle<Script> ParseInfo::CreateScript(
MaybeHandle<FixedArray> maybe_wrapped_arguments, Isolate* isolate, Handle<String> source,
ScriptOriginOptions origin_options, NativesFlag natives); MaybeHandle<FixedArray> maybe_wrapped_arguments,
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) void ParseInfo:: ScriptOriginOptions origin_options, NativesFlag natives);
InitializeScript(LocalIsolate* isolate, Handle<String> source, template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
MaybeHandle<FixedArray> maybe_wrapped_arguments, Handle<Script> ParseInfo::CreateScript(
ScriptOriginOptions origin_options, NativesFlag natives); LocalIsolate* isolate, Handle<String> source,
MaybeHandle<FixedArray> maybe_wrapped_arguments,
ScriptOriginOptions origin_options, NativesFlag natives);
AstValueFactory* ParseInfo::GetOrCreateAstValueFactory() { AstValueFactory* ParseInfo::GetOrCreateAstValueFactory() {
if (!ast_value_factory_.get()) { if (!ast_value_factory_.get()) {
......
...@@ -225,10 +225,10 @@ class V8_EXPORT_PRIVATE ParseInfo { ...@@ -225,10 +225,10 @@ class V8_EXPORT_PRIVATE ParseInfo {
template <typename IsolateT> template <typename IsolateT>
EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
void InitializeScript(IsolateT* isolate, Handle<String> source, Handle<Script> CreateScript(IsolateT* isolate, Handle<String> source,
MaybeHandle<FixedArray> maybe_wrapped_arguments, MaybeHandle<FixedArray> maybe_wrapped_arguments,
ScriptOriginOptions origin_options, ScriptOriginOptions origin_options,
NativesFlag natives = NOT_NATIVES_CODE); NativesFlag natives = NOT_NATIVES_CODE);
// Either returns the ast-value-factory associcated with this ParseInfo, or // Either returns the ast-value-factory associcated with this ParseInfo, or
// creates and returns a new factory if none exists. // creates and returns a new factory if none exists.
...@@ -274,9 +274,6 @@ class V8_EXPORT_PRIVATE ParseInfo { ...@@ -274,9 +274,6 @@ class V8_EXPORT_PRIVATE ParseInfo {
LanguageMode language_mode() const { return language_mode_; } LanguageMode language_mode() const { return language_mode_; }
void set_language_mode(LanguageMode value) { language_mode_ = value; } void set_language_mode(LanguageMode value) { language_mode_ = value; }
Handle<Script> script() const { return script_; }
void set_script(Handle<Script> script) { script_ = script; }
Utf16CharacterStream* character_stream() const { Utf16CharacterStream* character_stream() const {
return character_stream_.get(); return character_stream_.get();
} }
...@@ -355,7 +352,6 @@ class V8_EXPORT_PRIVATE ParseInfo { ...@@ -355,7 +352,6 @@ class V8_EXPORT_PRIVATE ParseInfo {
int max_function_literal_id_; int max_function_literal_id_;
//----------- Inputs+Outputs of parsing and scope analysis ----------------- //----------- Inputs+Outputs of parsing and scope analysis -----------------
Handle<Script> script_;
std::unique_ptr<Utf16CharacterStream> character_stream_; std::unique_ptr<Utf16CharacterStream> character_stream_;
std::unique_ptr<ConsumedPreparseData> consumed_preparse_data_; std::unique_ptr<ConsumedPreparseData> consumed_preparse_data_;
std::unique_ptr<AstValueFactory> ast_value_factory_; std::unique_ptr<AstValueFactory> ast_value_factory_;
......
...@@ -39,6 +39,7 @@ class LazyCompilerDispatcherTestFlags { ...@@ -39,6 +39,7 @@ class LazyCompilerDispatcherTestFlags {
FLAG_single_threaded = true; FLAG_single_threaded = true;
FlagList::EnforceFlagImplications(); FlagList::EnforceFlagImplications();
FLAG_lazy_compile_dispatcher = true; FLAG_lazy_compile_dispatcher = true;
FLAG_finalize_streaming_on_background = false;
} }
static void RestoreFlags() { static void RestoreFlags() {
...@@ -106,6 +107,15 @@ class LazyCompilerDispatcherTest : public TestWithNativeContext { ...@@ -106,6 +107,15 @@ class LazyCompilerDispatcherTest : public TestWithNativeContext {
return dispatcher->Enqueue(outer_parse_info.get(), function_name, return dispatcher->Enqueue(outer_parse_info.get(), function_name,
function_literal); function_literal);
} }
protected:
void SetUp() override {
// TODO(leszeks): Support background finalization in compiler dispatcher.
if (FLAG_finalize_streaming_on_background) {
GTEST_SKIP_(
"Parallel compile tasks don't yet support background finalization");
}
}
}; };
namespace { namespace {
......
...@@ -88,10 +88,9 @@ class LocalFactoryTest : public TestWithIsolateAndZone { ...@@ -88,10 +88,9 @@ class LocalFactoryTest : public TestWithIsolateAndZone {
parse_info()->ast_value_factory()->Internalize(local_isolate()); parse_info()->ast_value_factory()->Internalize(local_isolate());
DeclarationScope::AllocateScopeInfos(parse_info(), local_isolate()); DeclarationScope::AllocateScopeInfos(parse_info(), local_isolate());
parse_info_.InitializeScript(local_isolate(), script_ = parse_info_.CreateScript(local_isolate(),
local_factory()->empty_string(), local_factory()->empty_string(),
kNullMaybeHandle, ScriptOriginOptions()); kNullMaybeHandle, ScriptOriginOptions());
script_ = parse_info_.script();
// Create the SFI list on the script so that SFI SetScript works. // Create the SFI list on the script so that SFI SetScript works.
Handle<WeakFixedArray> infos = local_factory()->NewWeakFixedArray( Handle<WeakFixedArray> infos = local_factory()->NewWeakFixedArray(
......
...@@ -80,11 +80,20 @@ class BackgroundCompileTaskTest : public TestWithNativeContext { ...@@ -80,11 +80,20 @@ class BackgroundCompileTaskTest : public TestWithNativeContext {
shared->function_literal_id(), nullptr); shared->function_literal_id(), nullptr);
return new BackgroundCompileTask( return new BackgroundCompileTask(
isolate, outer_parse_info.get(), function_name, function_literal, outer_parse_info.get(), function_name, function_literal,
isolate->counters()->worker_thread_runtime_call_stats(), isolate->counters()->worker_thread_runtime_call_stats(),
isolate->counters()->compile_function_on_background(), FLAG_stack_size); isolate->counters()->compile_function_on_background(), FLAG_stack_size);
} }
protected:
void SetUp() override {
// TODO(leszeks): Support background finalization in compiler dispatcher.
if (FLAG_finalize_streaming_on_background) {
GTEST_SKIP_(
"Parallel compile tasks don't yet support background finalization");
}
}
private: private:
AccountingAllocator* allocator_; AccountingAllocator* allocator_;
static SaveFlags* save_flags_; static SaveFlags* save_flags_;
......
...@@ -67,8 +67,6 @@ std::unique_ptr<ParseInfo> OuterParseInfoForShared( ...@@ -67,8 +67,6 @@ std::unique_ptr<ParseInfo> OuterParseInfoForShared(
ScannerStream::For(isolate, source)); ScannerStream::For(isolate, source));
result->set_character_stream(std::move(stream)); result->set_character_stream(std::move(stream));
result->set_script(handle(script, isolate));
return result; return result;
} }
......
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