Commit d91679bf authored by Leszek Swirski's avatar Leszek Swirski Committed by Commit Bot

[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: 's avatarUlan Degenbaev <ulan@chromium.org>
Reviewed-by: 's avatarSimon Zünd <szuend@chromium.org>
Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#66782}
parent 2b1d9b0f
......@@ -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;
......
......@@ -1237,7 +1237,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());
......@@ -1295,7 +1296,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(),
......@@ -1370,7 +1372,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,56 +253,25 @@ 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(); }
bool allow_harmony_optional_chaining() const {
return scanner()->allow_harmony_optional_chaining();
}
void set_allow_harmony_optional_chaining(bool allow) {
scanner()->set_allow_harmony_optional_chaining(allow);
}
bool allow_harmony_nullish() const {
return scanner()->allow_harmony_nullish();
}
void set_allow_harmony_nullish(bool allow) {
scanner()->set_allow_harmony_nullish(allow);
}
uintptr_t stack_limit() const { return stack_limit_; }
void set_stack_limit(uintptr_t stack_limit) { stack_limit_ = stack_limit; }
......@@ -885,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(); }
......@@ -1077,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 {
......@@ -1534,7 +1502,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_;
......@@ -1549,8 +1516,8 @@ class ParserBase {
Scanner* scanner_;
const UnoptimizedCompileFlags flags_;
int function_literal_id_;
int script_id_;
FunctionLiteral::EagerCompileHint default_eager_compile_hint_;
......@@ -1589,11 +1556,6 @@ 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_;
};
......@@ -1644,7 +1606,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();
}
......@@ -1668,7 +1630,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();
}
......@@ -1879,7 +1841,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:
......@@ -1942,7 +1904,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;
......@@ -2188,7 +2150,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());
......@@ -2536,7 +2498,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();
}
......@@ -3456,8 +3418,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();
......@@ -3555,14 +3518,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();
......@@ -3572,7 +3535,7 @@ ParserBase<Impl>::ParseImportExpressions() {
}
if (V8_UNLIKELY(peek() != Token::LPAREN)) {
if (!parsing_module_) {
if (!flags().is_module) {
impl()->ReportMessageAt(scanner()->location(),
MessageTemplate::kImportOutsideModule);
} else {
......@@ -4493,8 +4456,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
......@@ -358,7 +356,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());
......
......@@ -366,11 +366,12 @@ V8_INLINE Token::Value Scanner::ScanSingleToken() {
case Token::CONDITIONAL:
// ? ?. ??
Advance();
if (V8_UNLIKELY(allow_harmony_optional_chaining() && c0_ == '.')) {
if (V8_UNLIKELY(flags_.allow_harmony_optional_chaining &&
c0_ == '.')) {
Advance();
if (!IsDecimalDigit(c0_)) return Token::QUESTION_PERIOD;
PushBack('.');
} else if (V8_UNLIKELY(allow_harmony_nullish() && c0_ == '?')) {
} else if (V8_UNLIKELY(flags_.allow_harmony_nullish && c0_ == '?')) {
return Select(Token::NULLISH);
}
return Token::CONDITIONAL;
......
......@@ -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,12 +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),
allow_harmony_optional_chaining_(false),
allow_harmony_nullish_(false),
is_module_(is_module),
octal_pos_(Location::invalid()),
octal_message_(MessageTemplate::kNone) {
DCHECK_NOT_NULL(source);
......@@ -190,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();
......@@ -410,18 +411,6 @@ class V8_EXPORT_PRIVATE Scanner {
bool FoundHtmlComment() const { return found_html_comment_; }
bool allow_harmony_optional_chaining() const {
return allow_harmony_optional_chaining_;
}
void set_allow_harmony_optional_chaining(bool allow) {
allow_harmony_optional_chaining_ = allow;
}
bool allow_harmony_nullish() const { return allow_harmony_nullish_; }
void set_allow_harmony_nullish(bool allow) { allow_harmony_nullish_ = allow; }
const Utf16CharacterStream* stream() const { return source_; }
private:
......@@ -715,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())
......@@ -730,12 +721,6 @@ class V8_EXPORT_PRIVATE Scanner {
// Whether this scanner encountered an HTML comment.
bool found_html_comment_;
// Harmony flags to allow ESNext features.
bool allow_harmony_optional_chaining_;
bool allow_harmony_nullish_;
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