Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion common.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@

# Reset this number to 0 on major V8 upgrades.
# Increment by one for each non-official patch applied to deps/v8.
'v8_embedder_string': '-node.10',
'v8_embedder_string': '-node.11',

##### V8 defaults for Node.js #####

Expand Down
11 changes: 10 additions & 1 deletion deps/v8/src/codegen/compiler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2024,6 +2024,9 @@ void BackgroundCompileTask::Run(
parser.ParseOnBackground(isolate, &info, script_, start_position_,
end_position_, function_literal_id_);
parser.UpdateStatistics(script_, &use_counts_, &total_preparse_skipped_);
if (toplevel_script_compilation) {
debug_magic_comment_locations_ = parser.debug_magic_comment_locations();
}

TRACE_EVENT(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.CompileCodeBackground");
Expand Down Expand Up @@ -2767,8 +2770,14 @@ MaybeHandle<SharedFunctionInfo> BackgroundCompileTask::FinalizeScript(
{
DisallowGarbageCollection no_gc;
SetScriptFieldsFromDetails(isolate, *script, script_details, &no_gc);
LOG(isolate, ScriptDetails(*script));
}
// After SetScriptFieldsFromDetails, so that a source map URL provided
// through the API takes precedence. The locations come from the streamed
// source; the embedder is expected to pass the same source here, but an
// out-of-bounds location is ignored.
Parser::SetDebugMagicCommentFields(isolate, script, source,
debug_magic_comment_locations_);
LOG(isolate, ScriptDetails(*script));
}

ReportStatistics(isolate);
Expand Down
4 changes: 4 additions & 0 deletions deps/v8/src/codegen/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "src/objects/debug-objects.h"
#include "src/parsing/parse-info.h"
#include "src/parsing/pending-compilation-error-handler.h"
#include "src/parsing/scanner.h" // For Scanner::DebugMagicCommentLocations.
#include "src/snapshot/code-serializer.h"
#include "src/utils/allocation.h"
#include "src/zone/zone.h"
Expand Down Expand Up @@ -649,6 +650,9 @@ class V8_EXPORT_PRIVATE BackgroundCompileTask {
DeferredFinalizationJobDataList jobs_to_retry_finalization_on_main_thread_;
base::SmallVector<v8::Isolate::UseCounterFeature, 8> use_counts_;
int total_preparse_skipped_ = 0;
// The source is not available on the background thread, so the debug magic
// comment values are created from these locations when finalizing.
Scanner::DebugMagicCommentLocations debug_magic_comment_locations_;

// Single function data for top-level function compilation.
MaybeIndirectHandle<SharedFunctionInfo> input_shared_info_;
Expand Down
18 changes: 0 additions & 18 deletions deps/v8/src/parsing/literal-buffer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,11 @@
#include "src/parsing/literal-buffer.h"

#include "src/base/strings.h"
#include "src/execution/isolate.h"
#include "src/execution/local-isolate.h"
#include "src/heap/factory.h"
#include "src/objects/objects.h"
#include "src/objects/string.h"
#include "src/utils/memcopy.h"

namespace v8 {
namespace internal {

template <typename IsolateT>
DirectHandle<String> LiteralBuffer::Internalize(IsolateT* isolate) const {
if (is_one_byte()) {
return isolate->factory()->InternalizeString(one_byte_literal());
}
return isolate->factory()->InternalizeString(two_byte_literal());
}

template DirectHandle<String> LiteralBuffer::Internalize(
Isolate* isolate) const;
template DirectHandle<String> LiteralBuffer::Internalize(
LocalIsolate* isolate) const;

size_t LiteralBuffer::NewCapacity(size_t min_capacity) {
return min_capacity < (kMaxGrowth / (kGrowthFactor - 1))
? min_capacity * kGrowthFactor
Expand Down
3 changes: 0 additions & 3 deletions deps/v8/src/parsing/literal-buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,6 @@ class LiteralBuffer final {
is_one_byte_ = true;
}

template <typename IsolateT>
DirectHandle<String> Internalize(IsolateT* isolate) const;

private:
static constexpr size_t kInitialCapacity = 256;
static constexpr size_t kGrowthFactor = 4;
Expand Down
52 changes: 34 additions & 18 deletions deps/v8/src/parsing/parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "src/common/message-template.h"
#include "src/common/scoped-modification.h"
#include "src/compiler-dispatcher/lazy-compile-dispatcher.h"
#include "src/heap/factory-inl.h"
#include "src/heap/local-heap-inl.h"
#include "src/heap/parked-scope.h"
#include "src/logging/counters.h"
Expand Down Expand Up @@ -3572,32 +3573,50 @@ void Parser::InsertSloppyBlockFunctionVarBindings(DeclarationScope* scope) {
// ----------------------------------------------------------------------------
// Parser support

template <typename IsolateT>
void Parser::HandleDebugMagicComments(IsolateT* isolate,
void Parser::HandleDebugMagicComments(Isolate* isolate,
DirectHandle<Script> script) {
DirectHandle<String> source_url = scanner_.SourceUrl(isolate);
if (!source_url.is_null()) {
// On the main thread, the scanned source is the script source.
DirectHandle<String> source(Cast<String>(script->source()), isolate);
SetDebugMagicCommentFields(isolate, script, source,
scanner_.debug_magic_comment_locations());
}

// static
void Parser::SetDebugMagicCommentFields(
Isolate* isolate, DirectHandle<Script> script, DirectHandle<String> source,
const Scanner::DebugMagicCommentLocations& locations) {
source = String::Flatten(isolate, source);
auto is_valid = [&](Scanner::Location location) {
return location.IsValid() && location.length() != 0 &&
static_cast<uint32_t>(location.end_pos) <= source->length();
};
if (is_valid(locations.source_url)) {
// The source URL is used as the script name (e.g. in stack traces,
// profiles and heap snapshots), so it is a sequential copy rather than a
// substring of the source.
DirectHandle<String> source_url = isolate->factory()->NewCopiedSubstring(
source, locations.source_url.beg_pos, locations.source_url.length());
script->set_source_url(*source_url);
}
DirectHandle<String> source_mapping_url = scanner_.SourceMappingUrl(isolate);
// The API can provide a source map URL and the API should take precedence.
// Let's make sure we do not override the API with the magic comment.
if (!source_mapping_url.is_null() &&
IsUndefined(script->source_mapping_url())) {
if (IsUndefined(script->source_mapping_url()) &&
is_valid(locations.source_mapping_url)) {
// The source map URL can be arbitrarily large (e.g. an inline source map),
// so it is a substring of the source rather than a copy.
DirectHandle<String> source_mapping_url = isolate->factory()->NewSubString(
source, locations.source_mapping_url.beg_pos,
locations.source_mapping_url.end_pos);
script->set_source_mapping_url(*source_mapping_url);
}

DirectHandle<String> debug_id = scanner_.DebugId(isolate);
if (!debug_id.is_null()) {
if (is_valid(locations.debug_id)) {
// Debug IDs are short, so they are copied like the source URL.
DirectHandle<String> debug_id = isolate->factory()->NewCopiedSubstring(
source, locations.debug_id.beg_pos, locations.debug_id.length());
script->set_debug_id(*debug_id);
}
}

template void Parser::HandleDebugMagicComments(Isolate* isolate,
DirectHandle<Script> script);
template void Parser::HandleDebugMagicComments(LocalIsolate* isolate,
DirectHandle<Script> script);

void Parser::UpdateStatistics(Isolate* isolate, DirectHandle<Script> script) {
CHECK_NOT_NULL(isolate);

Expand Down Expand Up @@ -3700,9 +3719,6 @@ void Parser::ParseOnBackground(LocalIsolate* isolate, ParseInfo* info,
MaybeProcessSourceRanges(info, result, stack_limit_);
});
// We need to unpark by now though, to be able to internalize.
if (flags().is_toplevel()) {
HandleDebugMagicComments(isolate, script);
}
if (result == nullptr) return;
PostProcessParseResult(isolate, info, result);
}
Expand Down
15 changes: 13 additions & 2 deletions deps/v8/src/parsing/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,19 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
DirectHandle<Script> script,
base::SmallVector<v8::Isolate::UseCounterFeature, 8>* use_counters,
int* preparse_skipped);
template <typename IsolateT>
void HandleDebugMagicComments(IsolateT* isolate, DirectHandle<Script> script);
void HandleDebugMagicComments(Isolate* isolate, DirectHandle<Script> script);
const Scanner::DebugMagicCommentLocations& debug_magic_comment_locations()
const {
return scanner_.debug_magic_comment_locations();
}
// Sets the debug magic comment fields of {script} to the values in {source}
// at the given locations: the source map URL is a substring of {source}, the
// source URL and debug ID are sequential copies. Locations that are empty,
// invalid or out of bounds are ignored.
static void SetDebugMagicCommentFields(
Isolate* isolate, DirectHandle<Script> script,
DirectHandle<String> source,
const Scanner::DebugMagicCommentLocations& locations);

private:
friend class ParserBase<Parser>;
Expand Down
116 changes: 45 additions & 71 deletions deps/v8/src/parsing/scanner.cc
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,27 @@ void ProcessPerFunctionCompileHints(const base::Vector<const uint8_t>& data,

} // namespace

template <typename CharCallback>
Scanner::Location Scanner::ScanMagicCommentValue(CharCallback on_char) {
DCHECK_EQ(c0_, '=');
Advance();
while (IsWhiteSpace(c0_)) {
Advance();
}
int value_beg_pos = source_pos();
while (c0_ != kEndOfInput && !IsWhiteSpaceOrLineTerminator(c0_)) {
on_char(c0_);
Advance();
}
Location value_location(value_beg_pos, source_pos());
// Allow whitespace at the end.
while (c0_ != kEndOfInput && !unibrow::IsLineTerminator(c0_)) {
if (!IsWhiteSpace(c0_)) return Location::invalid();
Advance();
}
return value_location;
}

void Scanner::TryToParseMagicComment(base::uc32 hash_or_at_sign) {
// Magic comments are of the form: //[#@]\s<name>=\s*<value>\s*.* and this
// function will just return if it cannot parse a magic comment.
Expand All @@ -293,12 +314,14 @@ void Scanner::TryToParseMagicComment(base::uc32 hash_or_at_sign) {
}
if (!name.is_one_byte()) return;
base::Vector<const uint8_t> name_literal = name.one_byte_literal();
LiteralBuffer* value;
LiteralBuffer per_function_compile_hints_value;
// The debug magic comment values are recorded as source locations, so that
// they can be created as substrings of the source instead of being copied.
Location* value_location = nullptr;
bool is_compile_hints = false;
if (name_literal == base::StaticOneByteVector("sourceURL")) {
value = &source_url_;
value_location = &debug_magic_comment_locations_.source_url;
} else if (name_literal == base::StaticOneByteVector("sourceMappingURL")) {
value = &source_mapping_url_;
value_location = &debug_magic_comment_locations_.source_mapping_url;
DCHECK(hash_or_at_sign == '#' || hash_or_at_sign == '@');
saw_source_mapping_url_magic_comment_at_sign_ = hash_or_at_sign == '@';
} else if (!saw_non_comment_ &&
Expand All @@ -309,45 +332,33 @@ void Scanner::TryToParseMagicComment(base::uc32 hash_or_at_sign) {
} else if (name_literal ==
base::StaticOneByteVector("functionsCalledOnLoad") &&
hash_or_at_sign == '#') {
value = &per_function_compile_hints_value;
is_compile_hints = true;
} else if (name_literal == base::StaticOneByteVector("debugId") &&
hash_or_at_sign == '#') {
value = &debug_id_;
value_location = &debug_magic_comment_locations_.debug_id;
} else {
return;
}
if (c0_ != '=') {
return;
}
value->Start();
Advance();
while (IsWhiteSpace(c0_)) {
Advance();
}
while (c0_ != kEndOfInput && !unibrow::IsLineTerminator(c0_)) {
if (IsWhiteSpace(c0_)) {
break;
}
value->AddChar(c0_);
Advance();
}
// Allow whitespace at the end.
while (c0_ != kEndOfInput && !unibrow::IsLineTerminator(c0_)) {
if (!IsWhiteSpace(c0_)) {
value->Start();
break;
}
Advance();
}
if (value == &per_function_compile_hints_value &&
per_function_compile_hints_value.is_one_byte()) {
base::Vector<const uint8_t> value_literal =
per_function_compile_hints_value.one_byte_literal();
per_function_compile_hint_positions_.clear();
per_function_compile_hint_positions_idx_ = 0;
ProcessPerFunctionCompileHints(value_literal, source_pos(),
per_function_compile_hint_positions_);
if (!is_compile_hints) {
DCHECK_NOT_NULL(value_location);
*value_location = ScanMagicCommentValue([](base::uc32) {});
return;
}
LiteralBuffer value;
value.Start();
Location value_location_in_source =
ScanMagicCommentValue([&value](base::uc32 c) { value.AddChar(c); });
// A value followed by trailing garbage is treated as empty, which clears
// the previously recorded compile hints.
if (!value_location_in_source.IsValid()) value.Start();
if (!value.is_one_byte()) return;
per_function_compile_hint_positions_.clear();
per_function_compile_hint_positions_idx_ = 0;
ProcessPerFunctionCompileHints(value.one_byte_literal(), source_pos(),
per_function_compile_hint_positions_);
}

bool Scanner::HasPerFunctionCompileHint(int position) {
Expand Down Expand Up @@ -689,43 +700,6 @@ Token::Value Scanner::ScanTemplateSpan() {
return result;
}

template <typename IsolateT>
DirectHandle<String> Scanner::SourceUrl(IsolateT* isolate) const {
DirectHandle<String> tmp;
if (source_url_.length() > 0) {
tmp = source_url_.Internalize(isolate);
}
return tmp;
}

template DirectHandle<String> Scanner::SourceUrl(Isolate* isolate) const;
template DirectHandle<String> Scanner::SourceUrl(LocalIsolate* isolate) const;

template <typename IsolateT>
DirectHandle<String> Scanner::SourceMappingUrl(IsolateT* isolate) const {
DirectHandle<String> tmp;
if (source_mapping_url_.length() > 0) {
tmp = source_mapping_url_.Internalize(isolate);
}
return tmp;
}

template DirectHandle<String> Scanner::SourceMappingUrl(Isolate* isolate) const;
template DirectHandle<String> Scanner::SourceMappingUrl(
LocalIsolate* isolate) const;

template <typename IsolateT>
DirectHandle<String> Scanner::DebugId(IsolateT* isolate) const {
DirectHandle<String> tmp;
if (debug_id_.length() > 0) {
tmp = debug_id_.Internalize(isolate);
}
return tmp;
}

template DirectHandle<String> Scanner::DebugId(Isolate* isolate) const;
template DirectHandle<String> Scanner::DebugId(LocalIsolate* isolate) const;

bool Scanner::ScanDigitsWithNumericSeparators(bool (*predicate)(base::uc32 ch),
bool is_check_first_digit) {
// we must have at least one digit after 'x'/'b'/'o'
Expand Down
Loading
Loading