Commit 313d4844 authored by Leszek Swirski's avatar Leszek Swirski Committed by Commit Bot

Reland^3 "[parser] Introduce UnoptimizedCompileFlags"

This is a reland of 0a59e0cb
which was a reland of 146f5375
which was a reland of d91679bf

Initializes the BackgroundCompileTasks's language_mode in the
constructor (previously only initialized after successful parse) in case
the parse failed. We still need to reset it after parse in case the
language mode changed (because we encountered "use strict").

Original change's description:
> [parser] Introduce UnoptimizedCompileFlags
>
> UnoptimizedCompileFlags defines the input flags shared between parse and
> compile (currently parse-only). It is set initially with some values, and
> is immutable after being passed to ParseInfo (ParseInfo still has getters
> for the fields, but no setters).
>
> Since a few of the existing flags were output flags, ParseInfo now has a
> new output_flags field, which will eventually migrate to a ParseOutputs
> structure.
>
> Bug: v8:10314
> Change-Id: If3890a5fad883bca80a97bf9dfe44d91797dc286
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2096580
> Commit-Queue: Leszek Swirski <leszeks@chromium.org>
> Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
> Reviewed-by: Simon Zünd <szuend@chromium.org>
> Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#66782}

TBR=ulan@chromium.org,szuend@chromium.org,rmcilroy@chromium.org

Bug: v8:10314
Change-Id: Ieee0bbfade4fe0b56de03bff47a7364959608d6a
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2157367Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67265}
parent b3a8c113
......@@ -2725,7 +2725,7 @@ bool ClassScope::ResolvePrivateNames(ParseInfo* info) {
if (var == nullptr) {
// It's only possible to fail to resolve private names here if
// this is at the top level or the private name is accessed through eval.
DCHECK(info->is_eval() || outer_scope_->is_script_scope());
DCHECK(info->flags().is_eval || outer_scope_->is_script_scope());
Scanner::Location loc = proxy->location();
info->pending_error_handler()->ReportMessageAt(
loc.beg_pos, loc.end_pos,
......
This diff is collapsed.
......@@ -14,6 +14,7 @@
#include "src/execution/isolate.h"
#include "src/logging/code-events.h"
#include "src/objects/contexts.h"
#include "src/parsing/parse-info.h"
#include "src/utils/allocation.h"
#include "src/zone/zone.h"
......@@ -399,6 +400,7 @@ class V8_EXPORT_PRIVATE BackgroundCompileTask {
// Data needed for parsing, and data needed to to be passed between thread
// between parsing and compilation. These need to be initialized before the
// compilation starts.
UnoptimizedCompileFlags flags_;
std::unique_ptr<ParseInfo> info_;
std::unique_ptr<Parser> parser_;
......@@ -414,6 +416,11 @@ class V8_EXPORT_PRIVATE BackgroundCompileTask {
// This is a raw pointer to the off-thread allocated SharedFunctionInfo.
SharedFunctionInfo outer_function_sfi_;
// Single function data for top-level function compilation.
int start_position_;
int end_position_;
int function_literal_id_;
int stack_size_;
WorkerThreadRuntimeCallStats* worker_thread_runtime_call_stats_;
AccountingAllocator* allocator_;
......
......@@ -18,7 +18,7 @@ namespace internal {
UnoptimizedCompilationInfo::UnoptimizedCompilationInfo(Zone* zone,
ParseInfo* parse_info,
FunctionLiteral* literal)
: flags_(0), zone_(zone), feedback_vector_spec_(zone) {
: flags_(parse_info->flags()), zone_(zone), feedback_vector_spec_(zone) {
// NOTE: The parse_info passed here represents the global information gathered
// during parsing, but does not represent specific details of the actual
// function literal being compiled for this OptimizedCompilationInfo. As such,
......@@ -28,13 +28,6 @@ UnoptimizedCompilationInfo::UnoptimizedCompilationInfo(Zone* zone,
DCHECK_NOT_NULL(literal);
literal_ = literal;
source_range_map_ = parse_info->source_range_map();
if (parse_info->is_eval()) MarkAsEval();
if (parse_info->collect_type_profile()) MarkAsCollectTypeProfile();
if (parse_info->might_always_opt()) MarkAsMightAlwaysOpt();
if (parse_info->collect_source_positions()) {
MarkAsForceCollectSourcePositions();
}
}
DeclarationScope* UnoptimizedCompilationInfo::scope() const {
......@@ -52,7 +45,7 @@ int UnoptimizedCompilationInfo::num_parameters_including_this() const {
SourcePositionTableBuilder::RecordingMode
UnoptimizedCompilationInfo::SourcePositionRecordingMode() const {
if (collect_source_positions()) {
if (flags().collect_source_positions) {
return SourcePositionTableBuilder::RECORD_SOURCE_POSITIONS;
}
......
......@@ -12,6 +12,7 @@
#include "src/handles/handles.h"
#include "src/objects/feedback-vector.h"
#include "src/objects/objects.h"
#include "src/parsing/parse-info.h"
#include "src/utils/utils.h"
namespace v8 {
......@@ -35,21 +36,7 @@ class V8_EXPORT_PRIVATE UnoptimizedCompilationInfo final {
Zone* zone() { return zone_; }
// Compilation flag accessors.
void MarkAsEval() { SetFlag(kIsEval); }
bool is_eval() const { return GetFlag(kIsEval); }
void MarkAsCollectTypeProfile() { SetFlag(kCollectTypeProfile); }
bool collect_type_profile() const { return GetFlag(kCollectTypeProfile); }
void MarkAsForceCollectSourcePositions() { SetFlag(kCollectSourcePositions); }
bool collect_source_positions() const {
return GetFlag(kCollectSourcePositions);
}
void MarkAsMightAlwaysOpt() { SetFlag(kMightAlwaysOpt); }
bool might_always_opt() const { return GetFlag(kMightAlwaysOpt); }
const UnoptimizedCompileFlags& flags() const { return flags_; }
// Accessors for the input data of the function being compiled.
......@@ -97,20 +84,8 @@ class V8_EXPORT_PRIVATE UnoptimizedCompilationInfo final {
FeedbackVectorSpec* feedback_vector_spec() { return &feedback_vector_spec_; }
private:
// Various configuration flags for a compilation, as well as some properties
// of the compiled code produced by a compilation.
enum Flag {
kIsEval = 1 << 0,
kCollectTypeProfile = 1 << 1,
kMightAlwaysOpt = 1 << 2,
kCollectSourcePositions = 1 << 3,
};
void SetFlag(Flag flag) { flags_ |= flag; }
bool GetFlag(Flag flag) const { return (flags_ & flag) != 0; }
// Compilation flags.
unsigned flags_;
const UnoptimizedCompileFlags flags_;
// The zone from which the compilation pipeline working on this
// OptimizedCompilationInfo allocates.
......
......@@ -837,7 +837,7 @@ enum NativesFlag { NOT_NATIVES_CODE, EXTENSION_CODE, INSPECTOR_CODE };
// ParseRestriction is used to restrict the set of valid statements in a
// unit of compilation. Restriction violations cause a syntax error.
enum ParseRestriction {
enum ParseRestriction : bool {
NO_PARSE_RESTRICTION, // All expressions are allowed.
ONLY_SINGLE_FUNCTION_LITERAL // Only a single FunctionLiteral expression.
};
......
......@@ -544,16 +544,16 @@ bool Shell::ExecuteString(Isolate* isolate, Local<String> source,
i::Handle<i::String> str = Utils::OpenHandle(*(source));
// Set up ParseInfo.
i::ParseInfo parse_info(i_isolate);
parse_info.set_toplevel();
parse_info.set_allow_lazy_parsing();
parse_info.set_language_mode(
i::construct_language_mode(i::FLAG_use_strict));
i::Handle<i::Script> script =
parse_info.CreateScript(i_isolate, str, options.compile_options);
if (!i::parsing::ParseProgram(&parse_info, script, i::kNullMaybeHandle,
i_isolate)) {
i::UnoptimizedCompileFlags flags =
i::UnoptimizedCompileFlags::ForToplevelCompile(
i_isolate, true, i::construct_language_mode(i::FLAG_use_strict),
i::REPLMode::kNo);
i::ParseInfo parse_info(i_isolate, flags);
i::Handle<i::Script> script = parse_info.CreateScript(
i_isolate, str, i::kNullMaybeHandle, options.compile_options);
if (!i::parsing::ParseProgram(&parse_info, script, i_isolate)) {
fprintf(stderr, "Failed parsing\n");
return false;
}
......
......@@ -40,7 +40,7 @@ ScopeIterator::ScopeIterator(Isolate* isolate, FrameInspector* frame_inspector,
TryParseAndRetrieveScopes(strategy);
}
ScopeIterator::~ScopeIterator() { delete info_; }
ScopeIterator::~ScopeIterator() = default;
Handle<Object> ScopeIterator::GetFunctionDebugName() const {
if (!function_.is_null()) return JSFunction::GetDebugName(function_);
......@@ -236,36 +236,41 @@ void ScopeIterator::TryParseAndRetrieveScopes(ReparseStrategy strategy) {
// Depending on the choosen strategy, the whole script or just
// the closure is re-parsed for function scopes.
Handle<Script> script(Script::cast(shared_info->script()), isolate_);
UnoptimizedCompileFlags flags;
if (scope_info->scope_type() == FUNCTION_SCOPE &&
strategy == ReparseStrategy::kFunctionLiteral) {
info_ = new ParseInfo(isolate_, *shared_info);
flags = UnoptimizedCompileFlags::ForFunctionCompile(isolate_, *shared_info);
} else {
info_ = new ParseInfo(isolate_, *script);
info_->set_eager();
flags = UnoptimizedCompileFlags::ForScriptCompile(isolate_, *script);
flags.is_eager = true;
}
MaybeHandle<ScopeInfo> maybe_outer_scope;
if (scope_info->scope_type() == EVAL_SCOPE || script->is_wrapped()) {
info_->set_eval();
flags.is_eval = true;
if (!context_->IsNativeContext()) {
maybe_outer_scope = handle(context_->scope_info(), isolate_);
}
// Language mode may be inherited from the eval caller.
// Retrieve it from shared function info.
info_->set_language_mode(shared_info->language_mode());
flags.outer_language_mode = shared_info->language_mode();
} else if (scope_info->scope_type() == MODULE_SCOPE) {
DCHECK(info_->is_module());
DCHECK(flags.is_module);
} else {
DCHECK(scope_info->scope_type() == SCRIPT_SCOPE ||
scope_info->scope_type() == FUNCTION_SCOPE);
}
info_ = std::make_unique<ParseInfo>(isolate_, flags);
const bool parse_result =
info_->is_toplevel()
? parsing::ParseProgram(info_, script, maybe_outer_scope, isolate_)
: parsing::ParseFunction(info_, shared_info, isolate_);
flags.is_toplevel
? parsing::ParseProgram(info_.get(), script, maybe_outer_scope,
isolate_)
: parsing::ParseFunction(info_.get(), shared_info, isolate_);
if (parse_result && Rewriter::Rewrite(info_)) {
if (parse_result && Rewriter::Rewrite(info_.get())) {
info_->ast_value_factory()->Internalize(isolate_);
DeclarationScope* literal_scope = info_->literal()->scope();
......@@ -280,7 +285,7 @@ void ScopeIterator::TryParseAndRetrieveScopes(ReparseStrategy strategy) {
? scope_chain_retriever.ClosureScope()
: literal_scope;
CHECK(DeclarationScope::Analyze(info_));
CHECK(DeclarationScope::Analyze(info_.get()));
if (ignore_nested_scopes) {
current_scope_ = closure_scope_;
start_scope_ = current_scope_;
......
......@@ -109,7 +109,7 @@ class ScopeIterator {
private:
Isolate* isolate_;
ParseInfo* info_ = nullptr;
std::unique_ptr<ParseInfo> info_;
FrameInspector* const frame_inspector_ = nullptr;
Handle<JSGeneratorObject> generator_;
Handle<JSFunction> function_;
......
......@@ -750,7 +750,6 @@ class CollectFunctionLiterals final
bool ParseScript(Isolate* isolate, Handle<Script> script, ParseInfo* parse_info,
bool compile_as_well, std::vector<FunctionLiteral*>* literals,
debug::LiveEditResult* result) {
parse_info->set_eager();
v8::TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
Handle<SharedFunctionInfo> shared;
bool success = false;
......@@ -1058,15 +1057,21 @@ void LiveEdit::PatchScript(Isolate* isolate, Handle<Script> script,
return;
}
ParseInfo parse_info(isolate, *script);
UnoptimizedCompileFlags flags =
UnoptimizedCompileFlags::ForScriptCompile(isolate, *script);
flags.is_eager = true;
ParseInfo parse_info(isolate, flags);
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);
UnoptimizedCompileFlags new_flags =
UnoptimizedCompileFlags::ForScriptCompile(isolate, *new_script);
new_flags.is_eager = true;
ParseInfo new_parse_info(isolate, new_flags);
std::vector<FunctionLiteral*> new_literals;
ParseInfo new_parse_info(isolate, *new_script);
if (!ParseScript(isolate, new_script, &new_parse_info, true, &new_literals,
result)) {
return;
......
......@@ -1252,7 +1252,8 @@ Handle<String> RenderCallSite(Isolate* isolate, Handle<Object> object,
MessageLocation* location,
CallPrinter::ErrorHint* hint) {
if (ComputeLocation(isolate, location)) {
ParseInfo info(isolate, *location->shared());
ParseInfo info(isolate, i::UnoptimizedCompileFlags::ForFunctionCompile(
isolate, *location->shared()));
if (parsing::ParseAny(&info, location->shared(), isolate)) {
info.ast_value_factory()->Internalize(isolate);
CallPrinter printer(isolate, location->shared()->IsUserJavaScript());
......@@ -1310,7 +1311,8 @@ Object ErrorUtils::ThrowSpreadArgIsNullOrUndefinedError(Isolate* isolate,
MessageLocation location;
Handle<String> callsite;
if (ComputeLocation(isolate, &location)) {
ParseInfo info(isolate, *location.shared());
ParseInfo info(isolate, i::UnoptimizedCompileFlags::ForFunctionCompile(
isolate, *location.shared()));
if (parsing::ParseAny(&info, location.shared(), isolate)) {
info.ast_value_factory()->Internalize(isolate);
CallPrinter printer(isolate, location.shared()->IsUserJavaScript(),
......@@ -1385,7 +1387,8 @@ Object ErrorUtils::ThrowLoadFromNullOrUndefined(Isolate* isolate,
if (ComputeLocation(isolate, &location)) {
location_computed = true;
ParseInfo info(isolate, *location.shared());
ParseInfo info(isolate, i::UnoptimizedCompileFlags::ForFunctionCompile(
isolate, *location.shared()));
if (parsing::ParseAny(&info, location.shared(), isolate)) {
info.ast_value_factory()->Internalize(isolate);
CallPrinter printer(isolate, location.shared()->IsUserJavaScript());
......
......@@ -1332,7 +1332,7 @@ void BytecodeGenerator::GenerateBytecodeBody() {
if (FLAG_trace) builder()->CallRuntime(Runtime::kTraceEnter);
// Emit type profile call.
if (info()->collect_type_profile()) {
if (info()->flags().collect_type_profile) {
feedback_spec()->AddTypeProfileSlot();
int num_parameters = closure_scope()->num_parameters();
for (int i = 0; i < num_parameters; i++) {
......@@ -2134,7 +2134,7 @@ void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
DCHECK(expr->scope()->outer_scope() == current_scope());
uint8_t flags = CreateClosureFlags::Encode(
expr->pretenure(), closure_scope()->is_function_scope(),
info()->might_always_opt());
info()->flags().might_always_opt);
size_t entry = builder()->AllocateDeferredConstantPoolEntry();
builder()->CreateClosure(entry, GetCachedCreateClosureSlot(expr), flags);
function_literals_.push_back(std::make_pair(expr, entry));
......@@ -3197,7 +3197,7 @@ void BytecodeGenerator::BuildReturn(int source_position) {
builder()->StoreAccumulatorInRegister(result).CallRuntime(
Runtime::kTraceExit, result);
}
if (info()->collect_type_profile()) {
if (info()->flags().collect_type_profile) {
builder()->CollectTypeProfile(info()->literal()->return_position());
}
builder()->SetReturnPosition(source_position, info()->literal());
......
......@@ -191,17 +191,18 @@ void InterpreterCompilationJob::CheckAndPrintBytecodeMismatch(
std::cerr << "Bytecode mismatch";
#ifdef OBJECT_PRINT
std::cerr << " found for function: ";
Handle<String> name = parse_info()->function_name()->string();
if (name->length() == 0) {
std::cerr << "anonymous";
} else {
MaybeHandle<String> maybe_name = parse_info()->literal()->GetName(isolate);
Handle<String> name;
if (maybe_name.ToHandle(&name) && name->length() != 0) {
name->StringPrint(std::cerr);
} else {
std::cerr << "anonymous";
}
Object script_name = script->GetNameOrSourceURL();
if (script_name.IsString()) {
std::cerr << " ";
String::cast(script_name).StringPrint(std::cerr);
std::cerr << ":" << parse_info()->start_position();
std::cerr << ":" << parse_info()->literal()->start_position();
}
#endif
std::cerr << "\nOriginal bytecode:\n";
......
......@@ -6,6 +6,7 @@
#define V8_OBJECTS_FUNCTION_KIND_H_
#include "src/base/bounds.h"
#include "src/base/macros.h"
namespace v8 {
namespace internal {
......@@ -56,6 +57,9 @@ enum FunctionKind : uint8_t {
kLastFunctionKind = kClassMembersInitializerFunction,
};
constexpr int kFunctionKindBitSize = 5;
STATIC_ASSERT(kLastFunctionKind < (1 << kFunctionKindBitSize));
inline bool IsArrowFunction(FunctionKind kind) {
return base::IsInRange(kind, FunctionKind::kArrowFunction,
FunctionKind::kAsyncArrowFunction);
......
......@@ -5,6 +5,7 @@
#ifndef V8_OBJECTS_SHARED_FUNCTION_INFO_INL_H_
#define V8_OBJECTS_SHARED_FUNCTION_INFO_INL_H_
#include "src/base/macros.h"
#include "src/objects/shared-function-info.h"
#include "src/handles/handles-inl.h"
......@@ -250,6 +251,7 @@ void SharedFunctionInfo::set_language_mode(LanguageMode language_mode) {
}
FunctionKind SharedFunctionInfo::kind() const {
STATIC_ASSERT(FunctionKindBits::kSize == kFunctionKindBitSize);
return FunctionKindBits::decode(flags());
}
......
This diff is collapsed.
This diff is collapsed.
......@@ -23,6 +23,7 @@
#include "src/objects/function-kind.h"
#include "src/parsing/expression-scope.h"
#include "src/parsing/func-name-inferrer.h"
#include "src/parsing/parse-info.h"
#include "src/parsing/scanner.h"
#include "src/parsing/token.h"
#include "src/utils/pointer-with-payload.h"
......@@ -241,7 +242,7 @@ class ParserBase {
v8::Extension* extension, AstValueFactory* ast_value_factory,
PendingCompilationErrorHandler* pending_error_handler,
RuntimeCallStats* runtime_call_stats, Logger* logger,
int script_id, bool parsing_module, bool parsing_on_main_thread)
UnoptimizedCompileFlags flags, bool parsing_on_main_thread)
: scope_(nullptr),
original_scope_(nullptr),
function_state_(nullptr),
......@@ -252,37 +253,22 @@ class ParserBase {
runtime_call_stats_(runtime_call_stats),
logger_(logger),
parsing_on_main_thread_(parsing_on_main_thread),
parsing_module_(parsing_module),
stack_limit_(stack_limit),
pending_error_handler_(pending_error_handler),
zone_(zone),
expression_scope_(nullptr),
scanner_(scanner),
flags_(flags),
function_literal_id_(0),
script_id_(script_id),
default_eager_compile_hint_(FunctionLiteral::kShouldLazyCompile),
allow_natives_(false),
allow_harmony_dynamic_import_(false),
allow_harmony_import_meta_(false),
allow_harmony_private_methods_(false),
allow_harmony_top_level_await_(false),
allow_eval_cache_(true) {
default_eager_compile_hint_(FunctionLiteral::kShouldLazyCompile) {
pointer_buffer_.reserve(32);
variable_buffer_.reserve(32);
}
#define ALLOW_ACCESSORS(name) \
bool allow_##name() const { return allow_##name##_; } \
void set_allow_##name(bool allow) { allow_##name##_ = allow; }
const UnoptimizedCompileFlags& flags() const { return flags_; }
ALLOW_ACCESSORS(natives)
ALLOW_ACCESSORS(harmony_dynamic_import)
ALLOW_ACCESSORS(harmony_import_meta)
ALLOW_ACCESSORS(harmony_private_methods)
ALLOW_ACCESSORS(harmony_top_level_await)
ALLOW_ACCESSORS(eval_cache)
#undef ALLOW_ACCESSORS
bool allow_eval_cache() const { return allow_eval_cache_; }
void set_allow_eval_cache(bool allow) { allow_eval_cache_ = allow; }
V8_INLINE bool has_error() const { return scanner()->has_parser_error(); }
......@@ -869,8 +855,6 @@ class ParserBase {
// Any further calls to Next or peek will return the illegal token.
if (GetCurrentStackPosition() < stack_limit_) set_stack_overflow();
}
int script_id() { return script_id_; }
void set_script_id(int id) { script_id_ = id; }
V8_INLINE Token::Value peek() { return scanner()->peek(); }
......@@ -1061,7 +1045,7 @@ class ParserBase {
return IsResumableFunction(function_state_->kind());
}
bool is_await_allowed() const {
return is_async_function() || (allow_harmony_top_level_await() &&
return is_async_function() || (flags().allow_harmony_top_level_await &&
IsModule(function_state_->kind()));
}
const PendingCompilationErrorHandler* pending_error_handler() const {
......@@ -1516,7 +1500,6 @@ class ParserBase {
RuntimeCallStats* runtime_call_stats_;
internal::Logger* logger_;
bool parsing_on_main_thread_;
const bool parsing_module_;
uintptr_t stack_limit_;
PendingCompilationErrorHandler* pending_error_handler_;
......@@ -1531,8 +1514,8 @@ class ParserBase {
Scanner* scanner_;
const UnoptimizedCompileFlags flags_;
int function_literal_id_;
int script_id_;
FunctionLiteral::EagerCompileHint default_eager_compile_hint_;
......@@ -1571,12 +1554,7 @@ class ParserBase {
bool accept_IN_ = true;
bool allow_natives_;
bool allow_harmony_dynamic_import_;
bool allow_harmony_import_meta_;
bool allow_harmony_private_methods_;
bool allow_harmony_top_level_await_;
bool allow_eval_cache_;
bool allow_eval_cache_ = true;
};
template <typename Impl>
......@@ -1626,7 +1604,7 @@ ParserBase<Impl>::ParseAndClassifyIdentifier(Token::Value next) {
}
if (!Token::IsValidIdentifier(next, language_mode(), is_generator(),
parsing_module_ || is_async_function())) {
flags().is_module || is_async_function())) {
ReportUnexpectedToken(next);
return impl()->EmptyIdentifierString();
}
......@@ -1650,7 +1628,7 @@ typename ParserBase<Impl>::IdentifierT ParserBase<Impl>::ParseIdentifier(
if (!Token::IsValidIdentifier(
next, language_mode(), IsGeneratorFunction(function_kind),
parsing_module_ || IsAsyncFunction(function_kind))) {
flags().is_module || IsAsyncFunction(function_kind))) {
ReportUnexpectedToken(next);
return impl()->EmptyIdentifierString();
}
......@@ -1861,7 +1839,7 @@ ParserBase<Impl>::ParsePrimaryExpression() {
return ParseSuperExpression(is_new);
}
case Token::IMPORT:
if (!allow_harmony_dynamic_import()) break;
if (!flags().allow_harmony_dynamic_import) break;
return ParseImportExpressions();
case Token::LBRACK:
......@@ -1924,7 +1902,7 @@ ParserBase<Impl>::ParsePrimaryExpression() {
return ParseTemplateLiteral(impl()->NullExpression(), beg_pos, false);
case Token::MOD:
if (allow_natives() || extension_ != nullptr) {
if (flags().allow_natives_syntax || extension_ != nullptr) {
return ParseV8Intrinsic();
}
break;
......@@ -2170,7 +2148,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseProperty(
prop_info->kind = ParsePropertyKind::kNotSet;
return impl()->FailureExpression();
}
if (V8_UNLIKELY(!allow_harmony_private_methods() &&
if (V8_UNLIKELY(!flags().allow_harmony_private_methods &&
(IsAccessor(prop_info->kind) ||
prop_info->kind == ParsePropertyKind::kMethod))) {
ReportUnexpectedToken(Next());
......@@ -2518,7 +2496,7 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ParsePropertyInfo* prop_info,
DCHECK_EQ(function_flags, ParseFunctionFlag::kIsNormal);
if (!Token::IsValidIdentifier(name_token, language_mode(), is_generator(),
parsing_module_ || is_async_function())) {
flags().is_module || is_async_function())) {
ReportUnexpectedToken(Next());
return impl()->NullLiteralProperty();
}
......@@ -3432,8 +3410,9 @@ ParserBase<Impl>::ParseMemberWithPresentNewPrefixesExpression() {
if (peek() == Token::SUPER) {
const bool is_new = true;
result = ParseSuperExpression(is_new);
} else if (allow_harmony_dynamic_import() && peek() == Token::IMPORT &&
(!allow_harmony_import_meta() || PeekAhead() == Token::LPAREN)) {
} else if (flags().allow_harmony_dynamic_import && peek() == Token::IMPORT &&
(!flags().allow_harmony_import_meta ||
PeekAhead() == Token::LPAREN)) {
impl()->ReportMessageAt(scanner()->peek_location(),
MessageTemplate::kImportCallNotNewExpression);
return impl()->FailureExpression();
......@@ -3531,14 +3510,14 @@ ParserBase<Impl>::ParseMemberExpression() {
template <typename Impl>
typename ParserBase<Impl>::ExpressionT
ParserBase<Impl>::ParseImportExpressions() {
DCHECK(allow_harmony_dynamic_import());
DCHECK(flags().allow_harmony_dynamic_import);
Consume(Token::IMPORT);
int pos = position();
if (allow_harmony_import_meta() && Check(Token::PERIOD)) {
if (flags().allow_harmony_import_meta && Check(Token::PERIOD)) {
ExpectContextualKeyword(ast_value_factory()->meta_string(), "import.meta",
pos);
if (!parsing_module_) {
if (!flags().is_module) {
impl()->ReportMessageAt(scanner()->location(),
MessageTemplate::kImportMetaOutsideModule);
return impl()->FailureExpression();
......@@ -3548,7 +3527,7 @@ ParserBase<Impl>::ParseImportExpressions() {
}
if (V8_UNLIKELY(peek() != Token::LPAREN)) {
if (!parsing_module_) {
if (!flags().is_module) {
impl()->ReportMessageAt(scanner()->location(),
MessageTemplate::kImportOutsideModule);
} else {
......@@ -4470,8 +4449,9 @@ ParserBase<Impl>::ParseArrowFunctionLiteral(
const char* event_name =
is_lazy_top_level_function ? "preparse-no-resolution" : "parse";
const char* name = "arrow function";
logger_->FunctionEvent(event_name, script_id(), ms, scope->start_position(),
scope->end_position(), name, strlen(name));
logger_->FunctionEvent(event_name, flags().script_id, ms,
scope->start_position(), scope->end_position(), name,
strlen(name));
}
return function_literal;
......
This diff is collapsed.
......@@ -14,6 +14,7 @@
#include "src/base/compiler-specific.h"
#include "src/base/threaded-list.h"
#include "src/common/globals.h"
#include "src/parsing/parse-info.h"
#include "src/parsing/parser-base.h"
#include "src/parsing/parsing.h"
#include "src/parsing/preparser.h"
......@@ -134,7 +135,8 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
static bool IsPreParser() { return false; }
void ParseOnBackground(ParseInfo* info);
void ParseOnBackground(ParseInfo* info, int start_position, int end_position,
int function_literal_id);
// Initializes an empty scope chain for top-level scripts, or scopes which
// consist of only the native context.
......@@ -215,6 +217,8 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
FunctionLiteral* ParseFunction(Isolate* isolate, ParseInfo* info,
Handle<SharedFunctionInfo> shared_info);
FunctionLiteral* DoParseFunction(Isolate* isolate, ParseInfo* info,
int start_position, int end_position,
int function_literal_id,
const AstRawString* raw_name);
// Called by ParseProgram after setting up the scanner.
......@@ -239,15 +243,9 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
if (reusable_preparser_ == nullptr) {
reusable_preparser_ = new PreParser(
&preparser_zone_, &scanner_, stack_limit_, ast_value_factory(),
pending_error_handler(), runtime_call_stats_, logger_, -1,
parsing_module_, parsing_on_main_thread_);
#define SET_ALLOW(name) reusable_preparser_->set_allow_##name(allow_##name());
SET_ALLOW(natives);
SET_ALLOW(harmony_dynamic_import);
SET_ALLOW(harmony_import_meta);
SET_ALLOW(harmony_private_methods);
SET_ALLOW(eval_cache);
#undef SET_ALLOW
pending_error_handler(), runtime_call_stats_, logger_, flags(),
parsing_on_main_thread_);
reusable_preparser_->set_allow_eval_cache(allow_eval_cache());
preparse_data_buffer_.reserve(128);
}
return reusable_preparser_;
......
......@@ -22,7 +22,7 @@ namespace parsing {
bool ParseProgram(ParseInfo* info, Handle<Script> script,
MaybeHandle<ScopeInfo> maybe_outer_scope_info,
Isolate* isolate, ReportErrorsAndStatisticsMode mode) {
DCHECK(info->is_toplevel());
DCHECK(info->flags().is_toplevel);
DCHECK_NULL(info->literal());
VMState<PARSER> state(isolate);
......@@ -44,7 +44,7 @@ bool ParseProgram(ParseInfo* info, Handle<Script> script,
info->set_literal(result);
if (result) {
info->set_language_mode(info->literal()->language_mode());
if (info->is_eval()) {
if (info->flags().is_eval) {
info->set_allow_eval_cache(parser.allow_eval_cache());
}
}
......@@ -66,7 +66,7 @@ bool ParseProgram(ParseInfo* info, Handle<Script> script, Isolate* isolate,
bool ParseFunction(ParseInfo* info, Handle<SharedFunctionInfo> shared_info,
Isolate* isolate, ReportErrorsAndStatisticsMode mode) {
DCHECK(!info->is_toplevel());
DCHECK(!info->flags().is_toplevel);
DCHECK(!shared_info.is_null());
DCHECK_NULL(info->literal());
......@@ -91,7 +91,7 @@ bool ParseFunction(ParseInfo* info, Handle<SharedFunctionInfo> shared_info,
info->set_literal(result);
if (result) {
info->ast_value_factory()->Internalize(isolate);
if (info->is_eval()) {
if (info->flags().is_eval) {
info->set_allow_eval_cache(parser.allow_eval_cache());
}
}
......@@ -109,7 +109,7 @@ 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());
if (info->is_toplevel()) {
if (info->flags().is_toplevel) {
MaybeHandle<ScopeInfo> maybe_outer_scope_info;
if (shared_info->HasOuterScopeInfo()) {
maybe_outer_scope_info =
......
......@@ -78,7 +78,7 @@ PreParser::PreParseResult PreParser::PreParseProgram() {
// ModuleDeclarationInstantiation for Source Text Module Records creates a
// new Module Environment Record whose outer lexical environment record is
// the global scope.
if (parsing_module_) scope = NewModuleScope(scope);
if (flags().is_module) scope = NewModuleScope(scope);
FunctionState top_scope(&function_state_, &scope_, scope);
original_scope_ = scope_;
......@@ -105,11 +105,9 @@ void PreParserFormalParameters::ValidateStrictMode(PreParser* preparser) const {
PreParser::PreParseResult PreParser::PreParseFunction(
const AstRawString* function_name, FunctionKind kind,
FunctionSyntaxKind function_syntax_kind, DeclarationScope* function_scope,
int* use_counts, ProducedPreparseData** produced_preparse_data,
int script_id) {
int* use_counts, ProducedPreparseData** produced_preparse_data) {
DCHECK_EQ(FUNCTION_SCOPE, function_scope->scope_type());
use_counts_ = use_counts;
set_script_id(script_id);
#ifdef DEBUG
function_scope->set_is_being_lazily_parsed(true);
#endif
......@@ -359,7 +357,7 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
name_byte_length = string->byte_length();
}
logger_->FunctionEvent(
event_name, script_id(), ms, function_scope->start_position(),
event_name, flags().script_id, ms, function_scope->start_position(),
function_scope->end_position(), name, name_byte_length);
}
......
......@@ -8,6 +8,7 @@
#include "src/ast/ast-value-factory.h"
#include "src/ast/ast.h"
#include "src/ast/scopes.h"
#include "src/parsing/parse-info.h"
#include "src/parsing/parser-base.h"
#include "src/parsing/pending-compilation-error-handler.h"
#include "src/parsing/preparser-logger.h"
......@@ -921,12 +922,11 @@ class PreParser : public ParserBase<PreParser> {
AstValueFactory* ast_value_factory,
PendingCompilationErrorHandler* pending_error_handler,
RuntimeCallStats* runtime_call_stats, Logger* logger,
int script_id = -1, bool parsing_module = false,
bool parsing_on_main_thread = true)
UnoptimizedCompileFlags flags, bool parsing_on_main_thread = true)
: ParserBase<PreParser>(zone, scanner, stack_limit, nullptr,
ast_value_factory, pending_error_handler,
runtime_call_stats, logger, script_id,
parsing_module, parsing_on_main_thread),
runtime_call_stats, logger, flags,
parsing_on_main_thread),
use_counts_(nullptr),
preparse_data_builder_(nullptr),
preparse_data_builder_buffer_() {
......@@ -954,8 +954,7 @@ class PreParser : public ParserBase<PreParser> {
PreParseResult PreParseFunction(
const AstRawString* function_name, FunctionKind kind,
FunctionSyntaxKind function_syntax_kind, DeclarationScope* function_scope,
int* use_counts, ProducedPreparseData** produced_preparser_scope_data,
int script_id);
int* use_counts, ProducedPreparseData** produced_preparser_scope_data);
PreparseDataBuilder* preparse_data_builder() const {
return preparse_data_builder_;
......
......@@ -400,7 +400,7 @@ base::Optional<VariableProxy*> Rewriter::RewriteBody(
int pos = kNoSourcePosition;
VariableProxy* result_value =
processor.factory()->NewVariableProxy(result, pos);
if (!info->is_repl_mode()) {
if (!info->flags().is_repl_mode) {
Statement* result_statement =
processor.factory()->NewReturnStatement(result_value, pos);
body->Add(result_statement, info->zone());
......
......@@ -13,6 +13,7 @@
#include "src/ast/ast-value-factory.h"
#include "src/numbers/conversions-inl.h"
#include "src/objects/bigint.h"
#include "src/parsing/parse-info.h"
#include "src/parsing/scanner-inl.h"
#include "src/zone/zone.h"
......@@ -89,10 +90,10 @@ bool Scanner::BookmarkScope::HasBeenApplied() const {
// ----------------------------------------------------------------------------
// Scanner
Scanner::Scanner(Utf16CharacterStream* source, bool is_module)
: source_(source),
Scanner::Scanner(Utf16CharacterStream* source, UnoptimizedCompileFlags flags)
: flags_(flags),
source_(source),
found_html_comment_(false),
is_module_(is_module),
octal_pos_(Location::invalid()),
octal_message_(MessageTemplate::kNone) {
DCHECK_NOT_NULL(source);
......@@ -188,7 +189,7 @@ Token::Value Scanner::PeekAhead() {
}
Token::Value Scanner::SkipSingleHTMLComment() {
if (is_module_) {
if (flags_.is_module) {
ReportScannerError(source_pos(), MessageTemplate::kHtmlCommentInModule);
return Token::ILLEGAL;
}
......
......@@ -15,6 +15,7 @@
#include "src/common/globals.h"
#include "src/common/message-template.h"
#include "src/parsing/literal-buffer.h"
#include "src/parsing/parse-info.h"
#include "src/parsing/token.h"
#include "src/strings/char-predicates.h"
#include "src/strings/unicode.h"
......@@ -269,7 +270,7 @@ class V8_EXPORT_PRIVATE Scanner {
static const int kNoOctalLocation = -1;
static const uc32 kEndOfInput = Utf16CharacterStream::kEndOfInput;
explicit Scanner(Utf16CharacterStream* source, bool is_module);
explicit Scanner(Utf16CharacterStream* source, UnoptimizedCompileFlags flags);
void Initialize();
......@@ -703,6 +704,8 @@ class V8_EXPORT_PRIVATE Scanner {
const TokenDesc& next() const { return *next_; }
const TokenDesc& next_next() const { return *next_next_; }
UnoptimizedCompileFlags flags_;
TokenDesc* current_; // desc for current token (as returned by Next())
TokenDesc* next_; // desc for next token (one token look-ahead)
TokenDesc* next_next_; // desc for the token after next (after PeakAhead())
......@@ -718,8 +721,6 @@ class V8_EXPORT_PRIVATE Scanner {
// Whether this scanner encountered an HTML comment.
bool found_html_comment_;
const bool is_module_;
// Values parsed from magic comments.
LiteralBuffer source_url_;
LiteralBuffer source_mapping_url_;
......
......@@ -707,9 +707,12 @@ TEST(PreParserScopeAnalysis) {
shared->uncompiled_data_with_preparse_data().preparse_data(),
isolate);
i::UnoptimizedCompileFlags flags =
i::UnoptimizedCompileFlags::ForFunctionCompile(isolate, *shared);
flags.is_lazy_compile = true;
// Parse the lazy function using the scope data.
i::ParseInfo using_scope_data(isolate, *shared);
using_scope_data.set_lazy_compile();
i::ParseInfo using_scope_data(isolate, flags);
using_scope_data.set_consumed_preparse_data(
i::ConsumedPreparseData::For(isolate, produced_data_on_heap));
CHECK(i::parsing::ParseFunction(&using_scope_data, shared, isolate));
......@@ -724,8 +727,7 @@ TEST(PreParserScopeAnalysis) {
CHECK(i::DeclarationScope::Analyze(&using_scope_data));
// Parse the lazy function again eagerly to produce baseline data.
i::ParseInfo not_using_scope_data(isolate, *shared);
not_using_scope_data.set_lazy_compile();
i::ParseInfo not_using_scope_data(isolate, flags);
CHECK(i::parsing::ParseFunction(&not_using_scope_data, shared, isolate));
// Verify that we didn't skip anything (there's no preparsed scope data,
......@@ -759,7 +761,9 @@ 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::ParseInfo info(isolate, *script);
i::UnoptimizedCompileFlags flags =
i::UnoptimizedCompileFlags::ForScriptCompile(isolate, *script);
i::ParseInfo info(isolate, flags);
// 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.
......
......@@ -7,6 +7,7 @@
#include "src/handles/handles-inl.h"
#include "src/objects/objects-inl.h"
#include "src/parsing/parse-info.h"
#include "src/parsing/scanner-character-streams.h"
#include "src/parsing/scanner.h"
#include "test/cctest/cctest.h"
......@@ -34,8 +35,9 @@ struct ScannerTestHelper {
ScannerTestHelper make_scanner(const char* src) {
ScannerTestHelper helper;
helper.stream = ScannerStream::ForTesting(src);
helper.scanner =
std::unique_ptr<Scanner>(new Scanner(helper.stream.get(), false));
helper.scanner = std::unique_ptr<Scanner>(
new Scanner(helper.stream.get(),
UnoptimizedCompileFlags::ForTest(CcTest::i_isolate())));
helper.scanner->Initialize();
return helper;
}
......
This diff is collapsed.
......@@ -80,7 +80,10 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
v8::internal::Handle<v8::internal::Script> script =
factory->NewScript(source.ToHandleChecked());
v8::internal::ParseInfo info(i_isolate, *script);
v8::internal::UnoptimizedCompileFlags flags =
v8::internal::UnoptimizedCompileFlags::ForScriptCompile(i_isolate,
*script);
v8::internal::ParseInfo info(i_isolate, flags);
if (!v8::internal::parsing::ParseProgram(&info, script, i_isolate)) {
i_isolate->OptionalRescheduleException(true);
}
......
......@@ -15,6 +15,7 @@
#include "src/execution/off-thread-isolate.h"
#include "src/handles/handles-inl.h"
#include "src/handles/handles.h"
#include "src/handles/maybe-handles.h"
#include "src/heap/off-thread-factory-inl.h"
#include "src/objects/fixed-array.h"
#include "src/objects/script.h"
......@@ -55,7 +56,10 @@ class OffThreadFactoryTest : public TestWithIsolateAndZone {
public:
OffThreadFactoryTest()
: TestWithIsolateAndZone(),
parse_info_(isolate()),
parse_info_(isolate(), UnoptimizedCompileFlags::ForToplevelCompile(
isolate(), true,
construct_language_mode(FLAG_use_strict),
REPLMode::kNo)),
off_thread_isolate_(isolate(), parse_info_.zone()) {}
FunctionLiteral* ParseProgram(const char* source) {
......@@ -68,8 +72,6 @@ class OffThreadFactoryTest : public TestWithIsolateAndZone {
parse_info_.set_character_stream(
ScannerStream::ForTesting(utf16_source.data(), utf16_source.size()));
parse_info_.set_toplevel();
parse_info_.set_allow_lazy_parsing();
{
DisallowHeapAllocation no_allocation;
......@@ -78,7 +80,7 @@ class OffThreadFactoryTest : public TestWithIsolateAndZone {
Parser parser(parse_info());
parser.InitializeEmptyScopeChain(parse_info());
parser.ParseOnBackground(parse_info());
parser.ParseOnBackground(parse_info(), 0, 0, kFunctionLiteralIdTopLevel);
CHECK(DeclarationScope::Analyze(parse_info()));
}
......@@ -88,7 +90,7 @@ class OffThreadFactoryTest : public TestWithIsolateAndZone {
script_ = parse_info_.CreateScript(off_thread_isolate(),
off_thread_factory()->empty_string(),
ScriptOriginOptions());
kNullMaybeHandle, ScriptOriginOptions());
// Create the SFI list on the script so that SFI SetScript works.
Handle<WeakFixedArray> infos = off_thread_factory()->NewWeakFixedArray(
......
......@@ -56,8 +56,8 @@ Handle<SharedFunctionInfo> CreateSharedFunctionInfo(
std::unique_ptr<ParseInfo> OuterParseInfoForShared(
Isolate* isolate, Handle<SharedFunctionInfo> shared) {
Script script = Script::cast(shared->script());
std::unique_ptr<ParseInfo> result =
std::make_unique<ParseInfo>(isolate, script);
std::unique_ptr<ParseInfo> result = std::make_unique<ParseInfo>(
isolate, i::UnoptimizedCompileFlags::ForScriptCompile(isolate, script));
// Create a character stream to simulate the parser having done so for the
// to-level ParseProgram.
......
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