Commit a48fcd6d authored by Camillo Bruni's avatar Camillo Bruni Committed by Commit Bot

[api] Add module streaming support

- Add support for module streaming compilation
- Enable module streaming testing d8
- Update API tests to include basic module streaming

Bug: chromium:1061857
Change-Id: I3ac95f7d672c382406182fb6900b1095f15c63b3
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2536457Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Commit-Queue: Camillo Bruni <cbruni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71342}
parent 1df2f22f
......@@ -1948,12 +1948,15 @@ class V8_EXPORT ScriptCompiler {
* This API allows to start the streaming with as little data as possible, and
* the remaining data (for example, the ScriptOrigin) is passed to Compile.
*/
V8_DEPRECATED("Use ScriptCompiler::StartStreamingScript instead.")
V8_DEPRECATED("Use ScriptCompiler::StartStreaming instead.")
static ScriptStreamingTask* StartStreamingScript(
Isolate* isolate, StreamedSource* source,
CompileOptions options = kNoCompileOptions);
static ScriptStreamingTask* StartStreaming(Isolate* isolate,
StreamedSource* source);
// The same as ScriptCompiler::StartStreaming but for module scripts.
static ScriptStreamingTask* StartStreamingModule(Isolate* isolate,
StreamedSource* source);
/**
* Compiles a streamed script (bound to current context).
......@@ -1998,6 +2001,17 @@ class V8_EXPORT ScriptCompiler {
CompileOptions options = kNoCompileOptions,
NoCacheReason no_cache_reason = kNoCacheNoReason);
/**
* Compiles a streamed module script.
*
* This can only be called after the streaming has finished
* (ScriptStreamingTask has been run). V8 doesn't construct the source string
* during streaming, so the embedder needs to pass the full source here.
*/
static V8_WARN_UNUSED_RESULT MaybeLocal<Module> CompileModule(
Local<Context> context, StreamedSource* v8_source,
Local<String> full_source_string, const ScriptOrigin& origin);
/**
* Compile a function for a given context. This is equivalent to running
*
......
......@@ -85,6 +85,7 @@
#include "src/objects/property-details.h"
#include "src/objects/property.h"
#include "src/objects/prototype.h"
#include "src/objects/shared-function-info.h"
#include "src/objects/slots.h"
#include "src/objects/smi.h"
#include "src/objects/stack-frame-info-inl.h"
......@@ -2525,8 +2526,6 @@ MaybeLocal<Module> ScriptCompiler::CompileModule(
NoCacheReason no_cache_reason) {
CHECK(options == kNoCompileOptions || options == kConsumeCodeCache);
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
Utils::ApiCheck(source->GetResourceOptions().IsModule(),
"v8::ScriptCompiler::CompileModule",
"Invalid ScriptOrigin: is_module must be true");
......@@ -2536,6 +2535,7 @@ MaybeLocal<Module> ScriptCompiler::CompileModule(
if (!maybe.ToLocal(&unbound)) return MaybeLocal<Module>();
i::Handle<i::SharedFunctionInfo> shared = Utils::OpenHandle(*unbound);
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
return ToApiHandle<Module>(i_isolate->factory()->NewSourceTextModule(shared));
}
......@@ -2662,44 +2662,79 @@ ScriptCompiler::ScriptStreamingTask* ScriptCompiler::StartStreaming(
ASSERT_NO_SCRIPT_NO_EXCEPTION(isolate);
i::ScriptStreamingData* data = source->impl();
std::unique_ptr<i::BackgroundCompileTask> task =
std::make_unique<i::BackgroundCompileTask>(data, isolate);
std::make_unique<i::BackgroundCompileTask>(data, isolate,
i::ScriptType::kClassic);
data->task = std::move(task);
return new ScriptCompiler::ScriptStreamingTask(data);
}
MaybeLocal<Script> ScriptCompiler::Compile(Local<Context> context,
StreamedSource* v8_source,
Local<String> full_source_string,
const ScriptOrigin& origin) {
PREPARE_FOR_EXECUTION(context, ScriptCompiler, Compile, Script);
TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8", "V8.ScriptCompiler");
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.CompileStreamedScript");
ScriptCompiler::ScriptStreamingTask* ScriptCompiler::StartStreamingModule(
Isolate* v8_isolate, StreamedSource* source) {
if (!i::FLAG_script_streaming) return nullptr;
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
i::ScriptStreamingData* data = source->impl();
std::unique_ptr<i::BackgroundCompileTask> task =
std::make_unique<i::BackgroundCompileTask>(data, isolate,
i::ScriptType::kModule);
data->task = std::move(task);
return new ScriptCompiler::ScriptStreamingTask(data);
}
namespace {
i::MaybeHandle<i::SharedFunctionInfo> CompileStreamedSource(
i::Isolate* isolate, ScriptCompiler::StreamedSource* v8_source,
Local<String> full_source_string, const ScriptOrigin& origin) {
i::Handle<i::String> str = Utils::OpenHandle(*(full_source_string));
i::Compiler::ScriptDetails script_details = GetScriptDetails(
isolate, origin.ResourceName(), origin.ResourceLineOffset(),
origin.ResourceColumnOffset(), origin.SourceMapUrl(),
origin.HostDefinedOptions());
i::ScriptStreamingData* data = v8_source->impl();
return i::Compiler::GetSharedFunctionInfoForStreamedScript(
isolate, str, script_details, origin.Options(), data);
}
i::MaybeHandle<i::SharedFunctionInfo> maybe_function_info =
i::Compiler::GetSharedFunctionInfoForStreamedScript(
isolate, str, script_details, origin.Options(), data);
} // namespace
i::Handle<i::SharedFunctionInfo> result;
has_pending_exception = !maybe_function_info.ToHandle(&result);
MaybeLocal<Script> ScriptCompiler::Compile(Local<Context> context,
StreamedSource* v8_source,
Local<String> full_source_string,
const ScriptOrigin& origin) {
PREPARE_FOR_EXECUTION(context, ScriptCompiler, Compile, Script);
TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8", "V8.ScriptCompiler");
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.CompileStreamedScript");
i::Handle<i::SharedFunctionInfo> sfi;
i::MaybeHandle<i::SharedFunctionInfo> maybe_sfi =
CompileStreamedSource(isolate, v8_source, full_source_string, origin);
has_pending_exception = !maybe_sfi.ToHandle(&sfi);
if (has_pending_exception) isolate->ReportPendingMessages();
RETURN_ON_FAILED_EXECUTION(Script);
Local<UnboundScript> generic = ToApiHandle<UnboundScript>(result);
Local<UnboundScript> generic = ToApiHandle<UnboundScript>(sfi);
if (generic.IsEmpty()) return Local<Script>();
Local<Script> bound = generic->BindToCurrentContext();
if (bound.IsEmpty()) return Local<Script>();
RETURN_ESCAPED(bound);
}
MaybeLocal<Module> ScriptCompiler::CompileModule(
Local<Context> context, StreamedSource* v8_source,
Local<String> full_source_string, const ScriptOrigin& origin) {
PREPARE_FOR_EXECUTION(context, ScriptCompiler, Compile, Module);
TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8", "V8.ScriptCompiler");
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.CompileStreamedModule");
i::Handle<i::SharedFunctionInfo> sfi;
i::MaybeHandle<i::SharedFunctionInfo> maybe_sfi =
CompileStreamedSource(isolate, v8_source, full_source_string, origin);
has_pending_exception = !maybe_sfi.ToHandle(&sfi);
if (has_pending_exception) isolate->ReportPendingMessages();
RETURN_ON_FAILED_EXECUTION(Module);
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
RETURN_ESCAPED(
ToApiHandle<Module>(i_isolate->factory()->NewSourceTextModule(sfi)));
}
uint32_t ScriptCompiler::CachedDataVersionTag() {
return static_cast<uint32_t>(base::hash_combine(
internal::Version::Hash(), internal::FlagList::Hash(),
......
......@@ -1459,10 +1459,10 @@ DeferredFinalizationJobData::DeferredFinalizationJobData(
job_(std::move(job)) {}
BackgroundCompileTask::BackgroundCompileTask(ScriptStreamingData* streamed_data,
Isolate* isolate)
Isolate* isolate, ScriptType type)
: flags_(UnoptimizedCompileFlags::ForToplevelCompile(
isolate, true, construct_language_mode(FLAG_use_strict),
REPLMode::kNo)),
REPLMode::kNo, type)),
compile_state_(isolate),
info_(std::make_unique<ParseInfo>(isolate, flags_, &compile_state_)),
isolate_for_local_isolate_(isolate),
......@@ -1588,7 +1588,7 @@ void BackgroundCompileTask::Run() {
// Save the language mode.
language_mode_ = info_->language_mode();
if (!FLAG_finalize_streaming_on_background) {
if (!FLAG_finalize_streaming_on_background || info_->flags().is_module()) {
if (info_->literal() != nullptr) {
CompileOnBackgroundThread(info_.get(), compile_state_.allocator(),
&compilation_jobs_);
......@@ -1604,9 +1604,9 @@ void BackgroundCompileTask::Run() {
// We don't have the script source, origin, or details yet, so use default
// values for them. These will be fixed up during the main-thread merge.
Handle<Script> script =
info_->CreateScript(&isolate, isolate.factory()->empty_string(),
kNullMaybeHandle, ScriptOriginOptions());
Handle<Script> script = info_->CreateScript(
&isolate, isolate.factory()->empty_string(), kNullMaybeHandle,
ScriptOriginOptions(false, false, false, info_->flags().is_module()));
parser_->HandleSourceURLComments(&isolate, script);
......@@ -2017,12 +2017,12 @@ MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
UnoptimizedCompileFlags flags = UnoptimizedCompileFlags::ForToplevelCompile(
isolate, true, language_mode, REPLMode::kNo);
flags.set_is_eval(true);
DCHECK(!flags.is_module());
flags.set_parse_restriction(restriction);
UnoptimizedCompileState compile_state(isolate);
ParseInfo parse_info(isolate, flags, &compile_state);
parse_info.set_parameters_end_pos(parameters_end_pos);
DCHECK(!parse_info.flags().is_module());
MaybeHandle<ScopeInfo> maybe_outer_scope_info;
if (!context->IsNativeContext()) {
......@@ -2523,13 +2523,15 @@ MaybeHandle<SharedFunctionInfo> CompileScriptOnMainThread(
class StressBackgroundCompileThread : public base::Thread {
public:
StressBackgroundCompileThread(Isolate* isolate, Handle<String> source)
StressBackgroundCompileThread(Isolate* isolate, Handle<String> source,
ScriptType type)
: base::Thread(
base::Thread::Options("StressBackgroundCompileThread", 2 * i::MB)),
source_(source),
streamed_source_(std::make_unique<SourceStream>(source, isolate),
v8::ScriptCompiler::StreamedSource::UTF8) {
data()->task = std::make_unique<i::BackgroundCompileTask>(data(), isolate);
data()->task =
std::make_unique<i::BackgroundCompileTask>(data(), isolate, type);
}
void Run() override { data()->task->Run(); }
......@@ -2594,7 +2596,9 @@ MaybeHandle<SharedFunctionInfo> CompileScriptOnBothBackgroundAndMainThread(
ScriptOriginOptions origin_options, Isolate* isolate,
IsCompiledScope* is_compiled_scope) {
// Start a background thread compiling the script.
StressBackgroundCompileThread background_compile_thread(isolate, source);
StressBackgroundCompileThread background_compile_thread(
isolate, source,
origin_options.IsModule() ? ScriptType::kModule : ScriptType::kClassic);
UnoptimizedCompileFlags flags_copy =
background_compile_thread.data()->task->flags();
......@@ -2736,10 +2740,11 @@ MaybeHandle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript(
UnoptimizedCompileFlags flags =
UnoptimizedCompileFlags::ForToplevelCompile(
isolate, natives == NOT_NATIVES_CODE, language_mode,
script_details.repl_mode);
script_details.repl_mode,
origin_options.IsModule() ? ScriptType::kModule
: ScriptType::kClassic);
flags.set_is_eager(compile_options == ScriptCompiler::kEagerCompile);
flags.set_is_module(origin_options.IsModule());
maybe_result = CompileScriptOnMainThread(
flags, source, script_details, origin_options, natives, extension,
......@@ -2859,7 +2864,6 @@ Compiler::GetSharedFunctionInfoForStreamedScript(
Isolate* isolate, Handle<String> source,
const ScriptDetails& script_details, ScriptOriginOptions origin_options,
ScriptStreamingData* streaming_data) {
DCHECK(!origin_options.IsModule());
DCHECK(!origin_options.IsWasm());
ScriptCompileTimerScope compile_timer(
......@@ -2893,7 +2897,7 @@ Compiler::GetSharedFunctionInfoForStreamedScript(
// the isolate cache.
Handle<Script> script;
if (FLAG_finalize_streaming_on_background) {
if (FLAG_finalize_streaming_on_background && !origin_options.IsModule()) {
RuntimeCallTimerScope runtimeTimerScope(
isolate, RuntimeCallCounterId::kCompilePublishBackgroundFinalization);
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
......@@ -2922,6 +2926,7 @@ Compiler::GetSharedFunctionInfoForStreamedScript(
} else {
ParseInfo* parse_info = task->info();
DCHECK(parse_info->flags().is_toplevel());
DCHECK_EQ(parse_info->flags().is_module(), origin_options.IsModule());
script = parse_info->CreateScript(isolate, source, kNullMaybeHandle,
origin_options);
......
......@@ -459,7 +459,8 @@ class V8_EXPORT_PRIVATE BackgroundCompileTask {
// script associated with |data| and can be finalized with
// Compiler::GetSharedFunctionInfoForStreamedScript.
// Note: does not take ownership of |data|.
BackgroundCompileTask(ScriptStreamingData* data, Isolate* isolate);
BackgroundCompileTask(ScriptStreamingData* data, Isolate* isolate,
ScriptType type);
~BackgroundCompileTask();
// Creates a new task that when run will parse and compile the
......
......@@ -434,6 +434,8 @@ inline LanguageMode stricter_language_mode(LanguageMode mode1,
static_cast<int>(mode2));
}
enum class ScriptType { kClassic, kModule };
// A non-keyed store is of the form a.x = foo or a["x"] = foo whereas
// a keyed store is of the form a[expression] = foo.
enum class StoreOrigin { kMaybeKeyed, kNamed };
......
......@@ -13,6 +13,7 @@
#include <iterator>
#include <string>
#include <tuple>
#include <type_traits>
#include <unordered_map>
#include <utility>
#include <vector>
......@@ -539,10 +540,14 @@ class DummySourceStream : public v8::ScriptCompiler::ExternalSourceStream {
class StreamingCompileTask final : public v8::Task {
public:
StreamingCompileTask(Isolate* isolate,
v8::ScriptCompiler::StreamedSource* streamed_source)
v8::ScriptCompiler::StreamedSource* streamed_source,
i::ScriptType type)
: isolate_(isolate),
script_streaming_task_(
v8::ScriptCompiler::StartStreaming(isolate, streamed_source)) {
type == i::ScriptType::kClassic
? v8::ScriptCompiler::StartStreaming(isolate, streamed_source)
: v8::ScriptCompiler::StartStreamingModule(isolate,
streamed_source)) {
Shell::NotifyStartStreamingTask(isolate_);
}
......@@ -566,6 +571,80 @@ class StreamingCompileTask final : public v8::Task {
script_streaming_task_;
};
namespace {
template <class T>
MaybeLocal<T> CompileStreamed(Local<Context> context,
ScriptCompiler::StreamedSource* v8_source,
Local<String> full_source_string,
const ScriptOrigin& origin) {}
template <>
MaybeLocal<Script> CompileStreamed(Local<Context> context,
ScriptCompiler::StreamedSource* v8_source,
Local<String> full_source_string,
const ScriptOrigin& origin) {
return ScriptCompiler::Compile(context, v8_source, full_source_string,
origin);
}
template <>
MaybeLocal<Module> CompileStreamed(Local<Context> context,
ScriptCompiler::StreamedSource* v8_source,
Local<String> full_source_string,
const ScriptOrigin& origin) {
return ScriptCompiler::CompileModule(context, v8_source, full_source_string,
origin);
}
template <class T>
MaybeLocal<T> Compile(Local<Context> context, ScriptCompiler::Source* source,
ScriptCompiler::CompileOptions options) {}
template <>
MaybeLocal<Script> Compile(Local<Context> context,
ScriptCompiler::Source* source,
ScriptCompiler::CompileOptions options) {
return ScriptCompiler::Compile(context, source, options);
}
template <>
MaybeLocal<Module> Compile(Local<Context> context,
ScriptCompiler::Source* source,
ScriptCompiler::CompileOptions options) {
return ScriptCompiler::CompileModule(context->GetIsolate(), source, options);
}
} // namespace
template <class T>
MaybeLocal<T> Shell::CompileString(Isolate* isolate, Local<Context> context,
Local<String> source,
const ScriptOrigin& origin) {
if (options.streaming_compile) {
v8::ScriptCompiler::StreamedSource streamed_source(
std::make_unique<DummySourceStream>(source),
v8::ScriptCompiler::StreamedSource::UTF8);
PostBlockingBackgroundTask(std::make_unique<StreamingCompileTask>(
isolate, &streamed_source,
std::is_same<T, Module>::value ? i::ScriptType::kModule
: i::ScriptType::kClassic));
// Pump the loop until the streaming task completes.
Shell::CompleteMessageLoop(isolate);
return CompileStreamed<T>(context, &streamed_source, source, origin);
}
ScriptCompiler::CachedData* cached_code = nullptr;
if (options.compile_options == ScriptCompiler::kConsumeCodeCache) {
cached_code = LookupCodeCache(isolate, source);
}
ScriptCompiler::Source script_source(source, origin, cached_code);
MaybeLocal<T> result =
Compile<T>(context, &script_source,
cached_code ? ScriptCompiler::kConsumeCodeCache
: ScriptCompiler::kNoCompileOptions);
if (cached_code) CHECK(!cached_code->rejected);
return result;
}
// Executes a string within the current v8 context.
bool Shell::ExecuteString(Isolate* isolate, Local<String> source,
Local<Value> name, PrintResult print_result,
......@@ -619,40 +698,9 @@ bool Shell::ExecuteString(Isolate* isolate, Local<String> source,
Local<Context> context(isolate->GetCurrentContext());
ScriptOrigin origin(name);
if (options.compile_options == ScriptCompiler::kConsumeCodeCache) {
ScriptCompiler::CachedData* cached_code =
LookupCodeCache(isolate, source);
if (cached_code != nullptr) {
ScriptCompiler::Source script_source(source, origin, cached_code);
maybe_script = ScriptCompiler::Compile(context, &script_source,
options.compile_options);
CHECK(!cached_code->rejected);
} else {
ScriptCompiler::Source script_source(source, origin);
maybe_script = ScriptCompiler::Compile(
context, &script_source, ScriptCompiler::kNoCompileOptions);
}
} else if (options.streaming_compile) {
v8::ScriptCompiler::StreamedSource streamed_source(
std::make_unique<DummySourceStream>(source),
v8::ScriptCompiler::StreamedSource::UTF8);
PostBlockingBackgroundTask(
std::make_unique<StreamingCompileTask>(isolate, &streamed_source));
// Pump the loop until the streaming task completes.
Shell::CompleteMessageLoop(isolate);
maybe_script =
ScriptCompiler::Compile(context, &streamed_source, source, origin);
} else {
ScriptCompiler::Source script_source(source, origin);
maybe_script = ScriptCompiler::Compile(context, &script_source,
options.compile_options);
}
Local<Script> script;
if (!maybe_script.ToLocal(&script)) {
if (!CompileString<Script>(isolate, context, source, origin)
.ToLocal(&script)) {
return false;
}
......@@ -867,9 +915,10 @@ MaybeLocal<Module> Shell::FetchModuleTree(Local<Module> referrer,
String::NewFromUtf8(isolate, file_name.c_str()).ToLocalChecked(),
Local<Integer>(), Local<Integer>(), Local<Boolean>(), Local<Integer>(),
Local<Value>(), Local<Boolean>(), Local<Boolean>(), True(isolate));
ScriptCompiler::Source source(source_text, origin);
Local<Module> module;
if (!ScriptCompiler::CompileModule(isolate, &source).ToLocal(&module)) {
if (!CompileString<Module>(isolate, context, source_text, origin)
.ToLocal(&module)) {
return MaybeLocal<Module>();
}
......
......@@ -612,6 +612,12 @@ class Shell : public i::AllStatic {
static MaybeLocal<Module> FetchModuleTree(v8::Local<v8::Module> origin_module,
v8::Local<v8::Context> context,
const std::string& file_name);
template <class T>
static MaybeLocal<T> CompileString(Isolate* isolate, Local<Context> context,
Local<String> source,
const ScriptOrigin& origin);
static ScriptCompiler::CachedData* LookupCodeCache(Isolate* isolate,
Local<Value> name);
static void StoreInCodeCache(Isolate* isolate, Local<Value> name,
......
......@@ -257,6 +257,7 @@ void ScopeIterator::TryParseAndRetrieveScopes(ReparseStrategy strategy) {
// Retrieve it from shared function info.
flags.set_outer_language_mode(shared_info->language_mode());
} else if (scope_info->scope_type() == MODULE_SCOPE) {
DCHECK(script->origin_options().IsModule());
DCHECK(flags.is_module());
} else {
DCHECK(scope_info->scope_type() == SCRIPT_SCOPE ||
......
......@@ -7,6 +7,7 @@
#include "src/ast/ast-source-ranges.h"
#include "src/ast/ast-value-factory.h"
#include "src/ast/ast.h"
#include "src/base/logging.h"
#include "src/common/globals.h"
#include "src/compiler-dispatcher/compiler-dispatcher.h"
#include "src/heap/heap-inl.h"
......@@ -75,7 +76,9 @@ UnoptimizedCompileFlags UnoptimizedCompileFlags::ForScriptCompile(
flags.SetFlagsForFunctionFromScript(script);
flags.SetFlagsForToplevelCompile(
isolate->is_collecting_type_profile(), script.IsUserJavaScript(),
flags.outer_language_mode(), construct_repl_mode(script.is_repl_mode()));
flags.outer_language_mode(), construct_repl_mode(script.is_repl_mode()),
script.origin_options().IsModule() ? ScriptType::kModule
: ScriptType::kClassic);
if (script.is_wrapped()) {
flags.set_function_syntax_kind(FunctionSyntaxKind::kWrapped);
}
......@@ -86,11 +89,11 @@ UnoptimizedCompileFlags UnoptimizedCompileFlags::ForScriptCompile(
// static
UnoptimizedCompileFlags UnoptimizedCompileFlags::ForToplevelCompile(
Isolate* isolate, bool is_user_javascript, LanguageMode language_mode,
REPLMode repl_mode) {
REPLMode repl_mode, ScriptType type) {
UnoptimizedCompileFlags flags(isolate, isolate->GetNextScriptId());
flags.SetFlagsForToplevelCompile(isolate->is_collecting_type_profile(),
is_user_javascript, language_mode,
repl_mode);
is_user_javascript, language_mode, repl_mode,
type);
LOG(isolate,
ScriptEvent(Logger::ScriptEventType::kReserveId, flags.script_id()));
......@@ -132,13 +135,15 @@ void UnoptimizedCompileFlags::SetFlagsFromFunction(T function) {
void UnoptimizedCompileFlags::SetFlagsForToplevelCompile(
bool is_collecting_type_profile, bool is_user_javascript,
LanguageMode language_mode, REPLMode repl_mode) {
LanguageMode language_mode, REPLMode repl_mode, ScriptType type) {
set_allow_lazy_parsing(true);
set_is_toplevel(true);
set_collect_type_profile(is_user_javascript && is_collecting_type_profile);
set_outer_language_mode(
stricter_language_mode(outer_language_mode(), language_mode));
set_is_repl_mode((repl_mode == REPLMode::kYes));
set_is_module(type == ScriptType::kModule);
DCHECK_IMPLIES(is_eval(), !is_module());
set_block_coverage_enabled(block_coverage_enabled() && is_user_javascript);
}
......@@ -148,7 +153,7 @@ void UnoptimizedCompileFlags::SetFlagsForFunctionFromScript(Script script) {
set_is_eval(script.compilation_type() == Script::COMPILATION_TYPE_EVAL);
set_is_module(script.origin_options().IsModule());
DCHECK(!(is_eval() && is_module()));
DCHECK_IMPLIES(is_eval(), !is_module());
set_block_coverage_enabled(block_coverage_enabled() &&
script.IsUserJavaScript());
......
......@@ -69,10 +69,9 @@ class Zone;
class V8_EXPORT_PRIVATE UnoptimizedCompileFlags {
public:
// Set-up flags for a toplevel compilation.
static UnoptimizedCompileFlags ForToplevelCompile(Isolate* isolate,
bool is_user_javascript,
LanguageMode language_mode,
REPLMode repl_mode);
static UnoptimizedCompileFlags ForToplevelCompile(
Isolate* isolate, bool is_user_javascript, LanguageMode language_mode,
REPLMode repl_mode, ScriptType type = ScriptType::kClassic);
// Set-up flags for a compiling a particular function (either a lazy compile
// or a recompile).
......@@ -135,7 +134,7 @@ class V8_EXPORT_PRIVATE UnoptimizedCompileFlags {
void SetFlagsForToplevelCompile(bool is_collecting_type_profile,
bool is_user_javascript,
LanguageMode language_mode,
REPLMode repl_mode);
REPLMode repl_mode, ScriptType type);
void SetFlagsForFunctionFromScript(Script script);
uint32_t flags_;
......
......@@ -23544,7 +23544,7 @@ class TestSourceStream : public v8::ScriptCompiler::ExternalSourceStream {
// Helper function for running streaming tests.
void RunStreamingTest(const char** chunks,
void RunStreamingTest(const char** chunks, i::ScriptType type,
v8::ScriptCompiler::StreamedSource::Encoding encoding =
v8::ScriptCompiler::StreamedSource::ONE_BYTE,
bool expected_success = true,
......@@ -23558,7 +23558,9 @@ void RunStreamingTest(const char** chunks,
v8::ScriptCompiler::StreamedSource source(
std::make_unique<TestSourceStream>(chunks), encoding);
v8::ScriptCompiler::ScriptStreamingTask* task =
v8::ScriptCompiler::StartStreaming(isolate, &source);
type == i::ScriptType::kClassic
? v8::ScriptCompiler::StartStreaming(isolate, &source)
: v8::ScriptCompiler::StartStreamingModule(isolate, &source);
// TestSourceStream::GetMoreData won't block, so it's OK to just run the
// task here in the main thread.
......@@ -23568,25 +23570,65 @@ void RunStreamingTest(const char** chunks,
// Possible errors are only produced while compiling.
CHECK(!try_catch.HasCaught());
v8::ScriptOrigin origin(v8_str("http://foo.com"));
v8::ScriptOrigin origin(
v8_str("http://foo.com"), v8::Local<v8::Integer>(),
v8::Local<v8::Integer>(), v8::Local<v8::Boolean>(),
v8::Local<v8::Integer>(), v8::Local<v8::Value>(),
v8::Local<v8::Boolean>(), v8::Local<v8::Boolean>(),
type == i::ScriptType::kModule ? v8::True(isolate) : v8::False(isolate));
char* full_source = TestSourceStream::FullSourceString(chunks);
v8::MaybeLocal<Script> script = v8::ScriptCompiler::Compile(
env.local(), &source, v8_str(full_source), origin);
if (expected_success) {
CHECK(!script.IsEmpty());
v8::Local<Value> result(
script.ToLocalChecked()->Run(env.local()).ToLocalChecked());
// All scripts are supposed to return the fixed value 13 when ran.
CHECK_EQ(13, result->Int32Value(env.local()).FromJust());
CheckMagicComments(isolate, script.ToLocalChecked(), expected_source_url,
expected_source_mapping_url);
if (type == i::ScriptType::kClassic) {
v8::MaybeLocal<Script> script = v8::ScriptCompiler::Compile(
env.local(), &source, v8_str(full_source), origin);
if (expected_success) {
CHECK(!script.IsEmpty());
v8::Local<Value> result(
script.ToLocalChecked()->Run(env.local()).ToLocalChecked());
// All scripts are supposed to return the fixed value 13 when ran.
CHECK_EQ(13, result->Int32Value(env.local()).FromJust());
CheckMagicComments(isolate, script.ToLocalChecked(), expected_source_url,
expected_source_mapping_url);
} else {
CHECK(script.IsEmpty());
}
} else {
CHECK(script.IsEmpty());
CHECK(try_catch.HasCaught());
v8::MaybeLocal<Module> maybe_module = v8::ScriptCompiler::CompileModule(
env.local(), &source, v8_str(full_source), origin);
if (expected_success) {
v8::Local<v8::Module> module = maybe_module.ToLocalChecked();
CHECK(module->InstantiateModule(env.local(), nullptr).FromJust());
CHECK_EQ(Module::kInstantiated, module->GetStatus());
v8::Local<Value> result = module->Evaluate(env.local()).ToLocalChecked();
CHECK_EQ(Module::kEvaluated, module->GetStatus());
if (i::FLAG_harmony_top_level_await) {
v8::Local<v8::Promise> promise = result.As<v8::Promise>();
CHECK_EQ(promise->State(), v8::Promise::kFulfilled);
CHECK_EQ(13, promise->Result()->Int32Value(env.local()).FromJust());
} else {
CHECK(!result.IsEmpty());
CHECK_EQ(13, result->Int32Value(env.local()).FromJust());
}
} else {
CHECK(maybe_module.IsEmpty());
}
}
if (!expected_success) CHECK(try_catch.HasCaught());
delete[] full_source;
}
void RunStreamingTest(const char** chunks,
v8::ScriptCompiler::StreamedSource::Encoding encoding =
v8::ScriptCompiler::StreamedSource::ONE_BYTE,
bool expected_success = true,
const char* expected_source_url = nullptr,
const char* expected_source_mapping_url = nullptr) {
RunStreamingTest(chunks, i::ScriptType::kClassic, encoding, expected_success,
expected_source_url, expected_source_mapping_url);
RunStreamingTest(chunks, i::ScriptType::kModule, encoding, expected_success,
expected_source_url, expected_source_mapping_url);
}
TEST(StreamingSimpleScript) {
// This script is unrealistically small, since no one chunk is enough to fill
// the backing buffer of Scanner, let alone overflow it.
......@@ -23619,7 +23661,8 @@ TEST(StreamingScriptEvalShadowing) {
" })()\n"
"})()\n";
const char* chunks[] = {chunk1, nullptr};
RunStreamingTest(chunks);
// Only run the script version of this test.
RunStreamingTest(chunks, i::ScriptType::kClassic);
}
TEST(StreamingBiggerScript) {
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