Reland "Reland "[compiler] Don't collect source positions for the top frame""
This is a reland of f2e652264d
Nothing has changed but
https://chromium-review.googlesource.com/c/v8/v8/+/1585269 has been rolled
back due to v8:9234.
Original change's description:
> Reland "[compiler] Don't collect source positions for the top frame"
>
> Fixed crashes by adding missing call to EnsureSourcePositionsAvailable,
> which requires clearing and restoring the pending exception.
>
> > While most source positions were not collected even throwing exceptions,
> > the top frame still was always collected as it was used to initialize
> > the JSMessageObject. This skips even that frame, by storing the
> > SharedFunctionInfo and bytecode offset in the JSMessageObject allowing
> > it to lazily evaluate the actual source position.
> >
> > Also adds tests to test-api.cc that test each of the source position
> > functions in isolation to ensure that they don't rely on previous
> > invocations to call the source collection function.
> >
> > Since no source positions are now collected at the point when an
> > exception is thrown, the mjsunit/stack-traces-overflow now passes again
> > with the flag enabled. (cctest/test-cpu-profiler/Inlining2 is now the
> > only failure).
>
> Bug: v8:8510
> Change-Id: Ifa5fe31d3db34a6c6d6a9cef3d646ad620dabd81
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1601270
> Commit-Queue: Dan Elphick <delphick@chromium.org>
> Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
> Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#61372}
TBR=ulan@chromium.org
Bug: v8:8510
Change-Id: Iaa9e376f90d10c0f25d1bcc352808363e4ea8b4d
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1605946
Reviewed-by: Dan Elphick <delphick@chromium.org>
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
Commit-Queue: Dan Elphick <delphick@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61418}
This commit is contained in:
parent
a814f29f67
commit
bf9e3e4de8
32
src/api.cc
32
src/api.cc
@ -2857,20 +2857,28 @@ Maybe<int> Message::GetLineNumber(Local<Context> context) const {
|
||||
i::Isolate* isolate = self->GetIsolate();
|
||||
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
|
||||
EscapableHandleScope handle_scope(reinterpret_cast<Isolate*>(isolate));
|
||||
auto msg = i::Handle<i::JSMessageObject>::cast(self);
|
||||
return Just(msg->GetLineNumber());
|
||||
i::JSMessageObject::EnsureSourcePositionsAvailable(isolate, self);
|
||||
return Just(self->GetLineNumber());
|
||||
}
|
||||
|
||||
|
||||
int Message::GetStartPosition() const {
|
||||
auto self = Utils::OpenHandle(this);
|
||||
return self->start_position();
|
||||
i::Isolate* isolate = self->GetIsolate();
|
||||
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
|
||||
EscapableHandleScope handle_scope(reinterpret_cast<Isolate*>(isolate));
|
||||
i::JSMessageObject::EnsureSourcePositionsAvailable(isolate, self);
|
||||
return self->GetStartPosition();
|
||||
}
|
||||
|
||||
|
||||
int Message::GetEndPosition() const {
|
||||
auto self = Utils::OpenHandle(this);
|
||||
return self->end_position();
|
||||
i::Isolate* isolate = self->GetIsolate();
|
||||
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
|
||||
EscapableHandleScope handle_scope(reinterpret_cast<Isolate*>(isolate));
|
||||
i::JSMessageObject::EnsureSourcePositionsAvailable(isolate, self);
|
||||
return self->GetEndPosition();
|
||||
}
|
||||
|
||||
int Message::ErrorLevel() const {
|
||||
@ -2883,8 +2891,8 @@ int Message::GetStartColumn() const {
|
||||
i::Isolate* isolate = self->GetIsolate();
|
||||
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
|
||||
EscapableHandleScope handle_scope(reinterpret_cast<Isolate*>(isolate));
|
||||
auto msg = i::Handle<i::JSMessageObject>::cast(self);
|
||||
return msg->GetColumnNumber();
|
||||
i::JSMessageObject::EnsureSourcePositionsAvailable(isolate, self);
|
||||
return self->GetColumnNumber();
|
||||
}
|
||||
|
||||
Maybe<int> Message::GetStartColumn(Local<Context> context) const {
|
||||
@ -2896,11 +2904,11 @@ int Message::GetEndColumn() const {
|
||||
i::Isolate* isolate = self->GetIsolate();
|
||||
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
|
||||
EscapableHandleScope handle_scope(reinterpret_cast<Isolate*>(isolate));
|
||||
auto msg = i::Handle<i::JSMessageObject>::cast(self);
|
||||
const int column_number = msg->GetColumnNumber();
|
||||
i::JSMessageObject::EnsureSourcePositionsAvailable(isolate, self);
|
||||
const int column_number = self->GetColumnNumber();
|
||||
if (column_number == -1) return -1;
|
||||
const int start = self->start_position();
|
||||
const int end = self->end_position();
|
||||
const int start = self->GetStartPosition();
|
||||
const int end = self->GetEndPosition();
|
||||
return column_number + (end - start);
|
||||
}
|
||||
|
||||
@ -2930,8 +2938,8 @@ MaybeLocal<String> Message::GetSourceLine(Local<Context> context) const {
|
||||
i::Isolate* isolate = self->GetIsolate();
|
||||
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
|
||||
EscapableHandleScope handle_scope(reinterpret_cast<Isolate*>(isolate));
|
||||
auto msg = i::Handle<i::JSMessageObject>::cast(self);
|
||||
RETURN_ESCAPED(Utils::ToLocal(msg->GetSourceLine()));
|
||||
i::JSMessageObject::EnsureSourcePositionsAvailable(isolate, self);
|
||||
RETURN_ESCAPED(Utils::ToLocal(self->GetSourceLine()));
|
||||
}
|
||||
|
||||
|
||||
|
@ -321,8 +321,11 @@ extern class JSMessageObject extends JSObject {
|
||||
arguments: Object;
|
||||
script: Script;
|
||||
stack_frames: Object;
|
||||
shared_info: SharedFunctionInfo | Undefined;
|
||||
|
||||
// Raw data fields.
|
||||
// TODO(ishell): store as int32 instead of Smi.
|
||||
bytecode_offset: Smi;
|
||||
start_position: Smi;
|
||||
end_position: Smi;
|
||||
error_level: Smi;
|
||||
|
@ -1338,11 +1338,23 @@ void FrameSummary::EnsureSourcePositionsAvailable() {
|
||||
}
|
||||
}
|
||||
|
||||
bool FrameSummary::AreSourcePositionsAvailable() const {
|
||||
if (IsJavaScript()) {
|
||||
return java_script_summary_.AreSourcePositionsAvailable();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void FrameSummary::JavaScriptFrameSummary::EnsureSourcePositionsAvailable() {
|
||||
Handle<SharedFunctionInfo> shared(function()->shared(), isolate());
|
||||
SharedFunctionInfo::EnsureSourcePositionsAvailable(isolate(), shared);
|
||||
}
|
||||
|
||||
bool FrameSummary::JavaScriptFrameSummary::AreSourcePositionsAvailable() const {
|
||||
return !FLAG_enable_lazy_source_positions ||
|
||||
function()->shared()->GetBytecodeArray()->HasSourcePositionTable();
|
||||
}
|
||||
|
||||
bool FrameSummary::JavaScriptFrameSummary::is_subject_to_debugging() const {
|
||||
return function()->shared()->IsSubjectToDebugging();
|
||||
}
|
||||
|
@ -483,6 +483,7 @@ class V8_EXPORT_PRIVATE FrameSummary {
|
||||
FixedArray parameters);
|
||||
|
||||
void EnsureSourcePositionsAvailable();
|
||||
bool AreSourcePositionsAvailable() const;
|
||||
|
||||
Handle<Object> receiver() const { return receiver_; }
|
||||
Handle<JSFunction> function() const { return function_; }
|
||||
@ -572,6 +573,7 @@ class V8_EXPORT_PRIVATE FrameSummary {
|
||||
static FrameSummary Get(const StandardFrame* frame, int index);
|
||||
|
||||
void EnsureSourcePositionsAvailable();
|
||||
bool AreSourcePositionsAvailable() const;
|
||||
|
||||
// Dispatched accessors.
|
||||
Handle<Object> receiver() const;
|
||||
|
@ -3468,7 +3468,8 @@ Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfoForLiteral(
|
||||
|
||||
Handle<JSMessageObject> Factory::NewJSMessageObject(
|
||||
MessageTemplate message, Handle<Object> argument, int start_position,
|
||||
int end_position, Handle<Script> script, Handle<Object> stack_frames) {
|
||||
int end_position, Handle<SharedFunctionInfo> shared_info,
|
||||
int bytecode_offset, Handle<Script> script, Handle<Object> stack_frames) {
|
||||
Handle<Map> map = message_object_map();
|
||||
Handle<JSMessageObject> message_obj(
|
||||
JSMessageObject::cast(New(map, AllocationType::kYoung)), isolate());
|
||||
@ -3481,6 +3482,23 @@ Handle<JSMessageObject> Factory::NewJSMessageObject(
|
||||
message_obj->set_start_position(start_position);
|
||||
message_obj->set_end_position(end_position);
|
||||
message_obj->set_script(*script);
|
||||
if (start_position >= 0) {
|
||||
// If there's a start_position, then there's no need to store the
|
||||
// SharedFunctionInfo as it will never be necessary to regenerate the
|
||||
// position.
|
||||
message_obj->set_shared_info(*undefined_value());
|
||||
message_obj->set_bytecode_offset(Smi::FromInt(0));
|
||||
} else {
|
||||
message_obj->set_bytecode_offset(Smi::FromInt(bytecode_offset));
|
||||
if (shared_info.is_null()) {
|
||||
message_obj->set_shared_info(*undefined_value());
|
||||
DCHECK_EQ(bytecode_offset, -1);
|
||||
} else {
|
||||
message_obj->set_shared_info(*shared_info);
|
||||
DCHECK_GE(bytecode_offset, 0);
|
||||
}
|
||||
}
|
||||
|
||||
message_obj->set_stack_frames(*stack_frames);
|
||||
message_obj->set_error_level(v8::Isolate::kMessageError);
|
||||
return message_obj;
|
||||
|
@ -885,7 +885,8 @@ class V8_EXPORT_PRIVATE Factory {
|
||||
// Allocates a new JSMessageObject object.
|
||||
Handle<JSMessageObject> NewJSMessageObject(
|
||||
MessageTemplate message, Handle<Object> argument, int start_position,
|
||||
int end_position, Handle<Script> script, Handle<Object> stack_frames);
|
||||
int end_position, Handle<SharedFunctionInfo> shared_info,
|
||||
int bytecode_offset, Handle<Script> script, Handle<Object> stack_frames);
|
||||
|
||||
Handle<ClassPositions> NewClassPositions(int start, int end);
|
||||
Handle<DebugInfo> NewDebugInfo(Handle<SharedFunctionInfo> shared);
|
||||
|
@ -2069,8 +2069,6 @@ bool Isolate::ComputeLocation(MessageLocation* target) {
|
||||
wasm::WasmCodeRefScope code_ref_scope;
|
||||
frame->Summarize(&frames);
|
||||
FrameSummary& summary = frames.back();
|
||||
summary.EnsureSourcePositionsAvailable();
|
||||
int pos = summary.SourcePosition();
|
||||
Handle<SharedFunctionInfo> shared;
|
||||
Handle<Object> script = summary.script();
|
||||
if (!script->IsScript() ||
|
||||
@ -2081,7 +2079,14 @@ bool Isolate::ComputeLocation(MessageLocation* target) {
|
||||
if (summary.IsJavaScript()) {
|
||||
shared = handle(summary.AsJavaScript().function()->shared(), this);
|
||||
}
|
||||
*target = MessageLocation(Handle<Script>::cast(script), pos, pos + 1, shared);
|
||||
if (summary.AreSourcePositionsAvailable()) {
|
||||
int pos = summary.SourcePosition();
|
||||
*target =
|
||||
MessageLocation(Handle<Script>::cast(script), pos, pos + 1, shared);
|
||||
} else {
|
||||
*target = MessageLocation(Handle<Script>::cast(script), shared,
|
||||
summary.code_offset());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2156,13 +2161,18 @@ bool Isolate::ComputeLocationFromStackTrace(MessageLocation* target,
|
||||
if (script->IsScript() &&
|
||||
!(Script::cast(script)->source()->IsUndefined(this))) {
|
||||
Handle<SharedFunctionInfo> shared = handle(fun->shared(), this);
|
||||
SharedFunctionInfo::EnsureSourcePositionsAvailable(this, shared);
|
||||
|
||||
AbstractCode abstract_code = elements->Code(i);
|
||||
const int code_offset = elements->Offset(i)->value();
|
||||
const int pos = abstract_code->SourcePosition(code_offset);
|
||||
|
||||
Handle<Script> casted_script(Script::cast(script), this);
|
||||
*target = MessageLocation(casted_script, pos, pos + 1);
|
||||
if (shared->HasBytecodeArray() &&
|
||||
shared->GetBytecodeArray()->HasSourcePositionTable()) {
|
||||
int pos = abstract_code->SourcePosition(code_offset);
|
||||
*target = MessageLocation(casted_script, pos, pos + 1, shared);
|
||||
} else {
|
||||
*target = MessageLocation(casted_script, shared, code_offset);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -2278,8 +2288,13 @@ void Isolate::ReportPendingMessagesImpl(bool report_externally) {
|
||||
HandleScope scope(this);
|
||||
Handle<JSMessageObject> message(JSMessageObject::cast(message_obj), this);
|
||||
Handle<Script> script(message->script(), this);
|
||||
int start_pos = message->start_position();
|
||||
int end_pos = message->end_position();
|
||||
// Clear the exception and restore it afterwards, otherwise
|
||||
// CollectSourcePositions will abort.
|
||||
clear_pending_exception();
|
||||
JSMessageObject::EnsureSourcePositionsAvailable(this, message);
|
||||
set_pending_exception(exception);
|
||||
int start_pos = message->GetStartPosition();
|
||||
int end_pos = message->GetEndPosition();
|
||||
MessageLocation location(script, start_pos, end_pos);
|
||||
MessageHandler::ReportMessage(this, &location, message);
|
||||
}
|
||||
|
@ -24,14 +24,30 @@ namespace internal {
|
||||
|
||||
MessageLocation::MessageLocation(Handle<Script> script, int start_pos,
|
||||
int end_pos)
|
||||
: script_(script), start_pos_(start_pos), end_pos_(end_pos) {}
|
||||
: script_(script),
|
||||
start_pos_(start_pos),
|
||||
end_pos_(end_pos),
|
||||
bytecode_offset_(-1) {}
|
||||
|
||||
MessageLocation::MessageLocation(Handle<Script> script, int start_pos,
|
||||
int end_pos, Handle<SharedFunctionInfo> shared)
|
||||
: script_(script),
|
||||
start_pos_(start_pos),
|
||||
end_pos_(end_pos),
|
||||
bytecode_offset_(-1),
|
||||
shared_(shared) {}
|
||||
MessageLocation::MessageLocation() : start_pos_(-1), end_pos_(-1) {}
|
||||
|
||||
MessageLocation::MessageLocation(Handle<Script> script,
|
||||
Handle<SharedFunctionInfo> shared,
|
||||
int bytecode_offset)
|
||||
: script_(script),
|
||||
start_pos_(-1),
|
||||
end_pos_(-1),
|
||||
bytecode_offset_(bytecode_offset),
|
||||
shared_(shared) {}
|
||||
|
||||
MessageLocation::MessageLocation()
|
||||
: start_pos_(-1), end_pos_(-1), bytecode_offset_(-1) {}
|
||||
|
||||
// If no message listeners have been registered this one is called
|
||||
// by default.
|
||||
@ -59,11 +75,15 @@ Handle<JSMessageObject> MessageHandler::MakeMessageObject(
|
||||
|
||||
int start = -1;
|
||||
int end = -1;
|
||||
int bytecode_offset = -1;
|
||||
Handle<Script> script_handle = isolate->factory()->empty_script();
|
||||
Handle<SharedFunctionInfo> shared_info;
|
||||
if (location != nullptr) {
|
||||
start = location->start_pos();
|
||||
end = location->end_pos();
|
||||
script_handle = location->script();
|
||||
bytecode_offset = location->bytecode_offset();
|
||||
shared_info = location->shared();
|
||||
}
|
||||
|
||||
Handle<Object> stack_frames_handle = stack_frames.is_null()
|
||||
@ -71,7 +91,8 @@ Handle<JSMessageObject> MessageHandler::MakeMessageObject(
|
||||
: Handle<Object>::cast(stack_frames);
|
||||
|
||||
Handle<JSMessageObject> message_obj = factory->NewJSMessageObject(
|
||||
message, argument, start, end, script_handle, stack_frames_handle);
|
||||
message, argument, start, end, shared_info, bytecode_offset,
|
||||
script_handle, stack_frames_handle);
|
||||
|
||||
return message_obj;
|
||||
}
|
||||
|
@ -33,20 +33,29 @@ class WasmInstanceObject;
|
||||
|
||||
class V8_EXPORT_PRIVATE MessageLocation {
|
||||
public:
|
||||
// Constructors for when source positions are already known.
|
||||
// TODO(delphick): Collapse to a single constructor with a default parameter
|
||||
// when we stop using the GCC that requires this separation.
|
||||
MessageLocation(Handle<Script> script, int start_pos, int end_pos);
|
||||
MessageLocation(Handle<Script> script, int start_pos, int end_pos,
|
||||
Handle<SharedFunctionInfo> shared);
|
||||
// Constructor for when source positions were not collected but which can be
|
||||
// reconstructed from the SharedFuncitonInfo and bytecode offset.
|
||||
MessageLocation(Handle<Script> script, Handle<SharedFunctionInfo> shared,
|
||||
int bytecode_offset);
|
||||
MessageLocation();
|
||||
|
||||
Handle<Script> script() const { return script_; }
|
||||
int start_pos() const { return start_pos_; }
|
||||
int end_pos() const { return end_pos_; }
|
||||
int bytecode_offset() const { return bytecode_offset_; }
|
||||
Handle<SharedFunctionInfo> shared() const { return shared_; }
|
||||
|
||||
private:
|
||||
Handle<Script> script_;
|
||||
int start_pos_;
|
||||
int end_pos_;
|
||||
int bytecode_offset_;
|
||||
Handle<SharedFunctionInfo> shared_;
|
||||
};
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "src/ast/ast.h"
|
||||
#include "src/ast/scopes.h"
|
||||
#include "src/base/bits.h"
|
||||
#include "src/base/debug/stack_trace.h"
|
||||
#include "src/base/overflowing-math.h"
|
||||
#include "src/base/utils/random-number-generator.h"
|
||||
#include "src/bootstrapper.h"
|
||||
@ -5571,6 +5572,13 @@ void SharedFunctionInfo::SetPosition(int start_position, int end_position) {
|
||||
}
|
||||
}
|
||||
|
||||
bool SharedFunctionInfo::AreSourcePositionsAvailable() const {
|
||||
if (FLAG_enable_lazy_source_positions) {
|
||||
return !HasBytecodeArray() || GetBytecodeArray()->HasSourcePositionTable();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
void SharedFunctionInfo::EnsureSourcePositionsAvailable(
|
||||
Isolate* isolate, Handle<SharedFunctionInfo> shared_info) {
|
||||
|
@ -717,16 +717,34 @@ ACCESSORS(JSDate, hour, Object, kHourOffset)
|
||||
ACCESSORS(JSDate, min, Object, kMinOffset)
|
||||
ACCESSORS(JSDate, sec, Object, kSecOffset)
|
||||
|
||||
bool JSMessageObject::DidEnsureSourcePositionsAvailable() const {
|
||||
return shared_info()->IsUndefined();
|
||||
}
|
||||
|
||||
int JSMessageObject::GetStartPosition() const {
|
||||
DCHECK(DidEnsureSourcePositionsAvailable());
|
||||
return start_position();
|
||||
}
|
||||
|
||||
int JSMessageObject::GetEndPosition() const {
|
||||
DCHECK(DidEnsureSourcePositionsAvailable());
|
||||
return end_position();
|
||||
}
|
||||
|
||||
MessageTemplate JSMessageObject::type() const {
|
||||
Object value = READ_FIELD(*this, kMessageTypeOffset);
|
||||
return MessageTemplateFromInt(Smi::ToInt(value));
|
||||
}
|
||||
|
||||
void JSMessageObject::set_type(MessageTemplate value) {
|
||||
WRITE_FIELD(*this, kMessageTypeOffset, Smi::FromInt(static_cast<int>(value)));
|
||||
}
|
||||
|
||||
ACCESSORS(JSMessageObject, argument, Object, kArgumentsOffset)
|
||||
ACCESSORS(JSMessageObject, script, Script, kScriptOffset)
|
||||
ACCESSORS(JSMessageObject, stack_frames, Object, kStackFramesOffset)
|
||||
ACCESSORS(JSMessageObject, shared_info, HeapObject, kSharedInfoOffset)
|
||||
ACCESSORS(JSMessageObject, bytecode_offset, Smi, kBytecodeOffsetOffset)
|
||||
SMI_ACCESSORS(JSMessageObject, start_position, kStartPositionOffset)
|
||||
SMI_ACCESSORS(JSMessageObject, end_position, kEndPositionOffset)
|
||||
SMI_ACCESSORS(JSMessageObject, error_level, kErrorLevelOffset)
|
||||
|
@ -5786,7 +5786,27 @@ void JSDate::SetCachedFields(int64_t local_time_ms, DateCache* date_cache) {
|
||||
set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
|
||||
}
|
||||
|
||||
// static
|
||||
void JSMessageObject::EnsureSourcePositionsAvailable(
|
||||
Isolate* isolate, Handle<JSMessageObject> message) {
|
||||
if (!message->DidEnsureSourcePositionsAvailable()) {
|
||||
DCHECK_EQ(message->start_position(), -1);
|
||||
DCHECK_GE(message->bytecode_offset()->value(), 0);
|
||||
Handle<SharedFunctionInfo> shared_info(
|
||||
SharedFunctionInfo::cast(message->shared_info()), isolate);
|
||||
SharedFunctionInfo::EnsureSourcePositionsAvailable(isolate, shared_info);
|
||||
DCHECK(shared_info->HasBytecodeArray());
|
||||
int position = shared_info->abstract_code()->SourcePosition(
|
||||
message->bytecode_offset()->value());
|
||||
DCHECK_GE(position, 0);
|
||||
message->set_start_position(position);
|
||||
message->set_end_position(position + 1);
|
||||
message->set_shared_info(ReadOnlyRoots(isolate).undefined_value());
|
||||
}
|
||||
}
|
||||
|
||||
int JSMessageObject::GetLineNumber() const {
|
||||
DCHECK(DidEnsureSourcePositionsAvailable());
|
||||
if (start_position() == -1) return Message::kNoLineNumberInfo;
|
||||
|
||||
Handle<Script> the_script(script(), GetIsolate());
|
||||
@ -5802,6 +5822,7 @@ int JSMessageObject::GetLineNumber() const {
|
||||
}
|
||||
|
||||
int JSMessageObject::GetColumnNumber() const {
|
||||
DCHECK(DidEnsureSourcePositionsAvailable());
|
||||
if (start_position() == -1) return -1;
|
||||
|
||||
Handle<Script> the_script(script(), GetIsolate());
|
||||
@ -5826,6 +5847,7 @@ Handle<String> JSMessageObject::GetSourceLine() const {
|
||||
|
||||
Script::PositionInfo info;
|
||||
const Script::OffsetFlag offset_flag = Script::WITH_OFFSET;
|
||||
DCHECK(DidEnsureSourcePositionsAvailable());
|
||||
if (!Script::GetPositionInfo(the_script, start_position(), &info,
|
||||
offset_flag)) {
|
||||
return isolate->factory()->empty_string();
|
||||
|
@ -1342,23 +1342,30 @@ class JSMessageObject : public JSObject {
|
||||
// [stack_frames]: an array of stack frames for this error object.
|
||||
DECL_ACCESSORS(stack_frames, Object)
|
||||
|
||||
// [start_position]: the start position in the script for the error message.
|
||||
inline int start_position() const;
|
||||
inline void set_start_position(int value);
|
||||
// Initializes the source positions in the object if possible. Does nothing if
|
||||
// called more than once. If called when stack space is exhausted, then the
|
||||
// source positions will be not be set and calling it again when there is more
|
||||
// stack space will not have any effect.
|
||||
static void EnsureSourcePositionsAvailable(Isolate* isolate,
|
||||
Handle<JSMessageObject> message);
|
||||
|
||||
// [end_position]: the end position in the script for the error message.
|
||||
inline int end_position() const;
|
||||
inline void set_end_position(int value);
|
||||
// Gets the start and end positions for the message.
|
||||
// EnsureSourcePositionsAvailable must have been called before calling these.
|
||||
inline int GetStartPosition() const;
|
||||
inline int GetEndPosition() const;
|
||||
|
||||
// Returns the line number for the error message (1-based), or
|
||||
// Message::kNoLineNumberInfo if the line cannot be determined.
|
||||
// EnsureSourcePositionsAvailable must have been called before calling this.
|
||||
V8_EXPORT_PRIVATE int GetLineNumber() const;
|
||||
|
||||
// Returns the offset of the given position within the containing line.
|
||||
// EnsureSourcePositionsAvailable must have been called before calling this.
|
||||
V8_EXPORT_PRIVATE int GetColumnNumber() const;
|
||||
|
||||
// Returns the source code line containing the given source
|
||||
// position, or the empty string if the position is invalid.
|
||||
// EnsureSourcePositionsAvailable must have been called before calling this.
|
||||
Handle<String> GetSourceLine() const;
|
||||
|
||||
inline int error_level() const;
|
||||
@ -1379,6 +1386,27 @@ class JSMessageObject : public JSObject {
|
||||
kPointerFieldsEndOffset, kSize>;
|
||||
|
||||
OBJECT_CONSTRUCTORS(JSMessageObject, JSObject);
|
||||
|
||||
private:
|
||||
friend class Factory;
|
||||
|
||||
inline bool DidEnsureSourcePositionsAvailable() const;
|
||||
|
||||
// [shared]: optional SharedFunctionInfo that can be used to reconstruct the
|
||||
// source position if not available when the message was generated.
|
||||
DECL_ACCESSORS(shared_info, HeapObject)
|
||||
|
||||
// [bytecode_offset]: optional offset using along with |shared| to generation
|
||||
// source positions.
|
||||
DECL_ACCESSORS(bytecode_offset, Smi)
|
||||
|
||||
// [start_position]: the start position in the script for the error message.
|
||||
inline int start_position() const;
|
||||
inline void set_start_position(int value);
|
||||
|
||||
// [end_position]: the end position in the script for the error message.
|
||||
inline int end_position() const;
|
||||
inline void set_end_position(int value);
|
||||
};
|
||||
|
||||
// The [Async-from-Sync Iterator] object
|
||||
|
@ -590,6 +590,8 @@ class SharedFunctionInfo : public HeapObject {
|
||||
static void EnsureSourcePositionsAvailable(
|
||||
Isolate* isolate, Handle<SharedFunctionInfo> shared_info);
|
||||
|
||||
bool AreSourcePositionsAvailable() const;
|
||||
|
||||
// Hash based on function literal id and script id.
|
||||
V8_EXPORT_PRIVATE uint32_t Hash();
|
||||
|
||||
|
@ -5131,9 +5131,7 @@ TEST(InterpreterCollectSourcePositions_StackOverflow) {
|
||||
CHECK_GT(source_position_table->length(), 0);
|
||||
}
|
||||
|
||||
// TODO(v8:8510): When an exception is thrown, the top frame still has its
|
||||
// source positions collected. Re-enable this test when that is fixed.
|
||||
DISABLED_TEST(InterpreterCollectSourcePositions_ThrowFrom1stFrame) {
|
||||
TEST(InterpreterCollectSourcePositions_ThrowFrom1stFrame) {
|
||||
FLAG_enable_lazy_source_positions = true;
|
||||
HandleAndZoneScope handles;
|
||||
Isolate* isolate = handles.main_isolate();
|
||||
|
@ -5048,6 +5048,81 @@ TEST(MessageHandler5) {
|
||||
isolate->RemoveMessageListeners(check_message_5b);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// Verifies that after throwing an exception the message object is set up in
|
||||
// some particular way by calling the supplied |tester| function. The tests that
|
||||
// use this purposely test only a single getter as the getter updates the cached
|
||||
// state of the object which could affect the results of other functions.
|
||||
void CheckMessageAttributes(std::function<void(v8::Local<v8::Context> context,
|
||||
v8::Local<v8::Message> message)>
|
||||
tester) {
|
||||
LocalContext context;
|
||||
v8::HandleScope scope(context->GetIsolate());
|
||||
|
||||
TryCatch try_catch(context->GetIsolate());
|
||||
CompileRun(
|
||||
R"javascript(
|
||||
(function() {
|
||||
throw new Error();
|
||||
})();
|
||||
)javascript");
|
||||
CHECK(try_catch.HasCaught());
|
||||
|
||||
v8::Local<v8::Value> error = try_catch.Exception();
|
||||
v8::Local<v8::Message> message =
|
||||
v8::Exception::CreateMessage(context->GetIsolate(), error);
|
||||
CHECK(!message.IsEmpty());
|
||||
|
||||
tester(context.local(), message);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(MessageGetLineNumber) {
|
||||
CheckMessageAttributes(
|
||||
[](v8::Local<v8::Context> context, v8::Local<v8::Message> message) {
|
||||
CHECK_EQ(3, message->GetLineNumber(context).FromJust());
|
||||
});
|
||||
}
|
||||
|
||||
TEST(MessageGetStartColumn) {
|
||||
CheckMessageAttributes(
|
||||
[](v8::Local<v8::Context> context, v8::Local<v8::Message> message) {
|
||||
CHECK_EQ(14, message->GetStartColumn(context).FromJust());
|
||||
});
|
||||
}
|
||||
|
||||
TEST(MessageGetEndColumn) {
|
||||
CheckMessageAttributes(
|
||||
[](v8::Local<v8::Context> context, v8::Local<v8::Message> message) {
|
||||
CHECK_EQ(15, message->GetEndColumn(context).FromJust());
|
||||
});
|
||||
}
|
||||
|
||||
TEST(MessageGetStartPosition) {
|
||||
CheckMessageAttributes(
|
||||
[](v8::Local<v8::Context> context, v8::Local<v8::Message> message) {
|
||||
CHECK_EQ(35, message->GetStartPosition());
|
||||
});
|
||||
}
|
||||
|
||||
TEST(MessageGetEndPosition) {
|
||||
CheckMessageAttributes(
|
||||
[](v8::Local<v8::Context> context, v8::Local<v8::Message> message) {
|
||||
CHECK_EQ(36, message->GetEndPosition());
|
||||
});
|
||||
}
|
||||
|
||||
TEST(MessageGetSourceLine) {
|
||||
CheckMessageAttributes(
|
||||
[](v8::Local<v8::Context> context, v8::Local<v8::Message> message) {
|
||||
std::string result(*v8::String::Utf8Value(
|
||||
context->GetIsolate(),
|
||||
message->GetSourceLine(context).ToLocalChecked()));
|
||||
CHECK_EQ(" throw new Error();", result);
|
||||
});
|
||||
}
|
||||
|
||||
THREADED_TEST(GetSetProperty) {
|
||||
LocalContext context;
|
||||
|
@ -86,10 +86,10 @@ void CheckComputeLocation(v8::internal::Isolate* i_isolate, Handle<Object> exc,
|
||||
printf("loc start: %d, end: %d\n", loc.start_pos(), loc.end_pos());
|
||||
Handle<JSMessageObject> message = i_isolate->CreateMessage(exc, nullptr);
|
||||
printf("msg start: %d, end: %d, line: %d, col: %d\n",
|
||||
message->start_position(), message->end_position(),
|
||||
message->GetStartPosition(), message->GetEndPosition(),
|
||||
message->GetLineNumber(), message->GetColumnNumber());
|
||||
CHECK_EQ(loc.start_pos(), message->start_position());
|
||||
CHECK_EQ(loc.end_pos(), message->end_position());
|
||||
CHECK_EQ(loc.start_pos(), message->GetStartPosition());
|
||||
CHECK_EQ(loc.end_pos(), message->GetEndPosition());
|
||||
// In the message, the line is 1-based, but the column is 0-based.
|
||||
CHECK_EQ(topLocation.line_nr, message->GetLineNumber());
|
||||
CHECK_LE(1, topLocation.column);
|
||||
|
@ -400,12 +400,6 @@
|
||||
'regress/regress-crbug-319860': [PASS, ['pointer_compression', SLOW]],
|
||||
}], # 'lite_mode or variant == jitless'
|
||||
|
||||
##############################################################################
|
||||
['lite_mode', {
|
||||
# TODO(v8:8510): Tests that currently fail with lazy source positions.
|
||||
'stack-traces-overflow': [SKIP],
|
||||
}], # lite_mode
|
||||
|
||||
##############################################################################
|
||||
['is_full_debug', {
|
||||
# Tests too slow in non-optimized debug mode.
|
||||
|
Loading…
Reference in New Issue
Block a user