[compiler] Don't collect source positions for the top frame
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: Ic5382bdbab65cd8838f0c84b544fabb1a9109d13 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1587385 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@{#61271}
This commit is contained in:
parent
eef7b8d675
commit
758700a708
32
src/api.cc
32
src/api.cc
@ -2859,20 +2859,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 {
|
||||
@ -2885,8 +2893,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 {
|
||||
@ -2898,11 +2906,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);
|
||||
}
|
||||
|
||||
@ -2932,8 +2940,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;
|
||||
|
@ -1336,11 +1336,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;
|
||||
|
@ -3505,7 +3505,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());
|
||||
@ -3518,6 +3519,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;
|
||||
|
@ -881,7 +881,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,8 @@ 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();
|
||||
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"
|
||||
@ -5615,6 +5616,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) {
|
||||
|
@ -718,16 +718,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)
|
||||
|
@ -5773,7 +5773,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());
|
||||
@ -5789,6 +5809,7 @@ int JSMessageObject::GetLineNumber() const {
|
||||
}
|
||||
|
||||
int JSMessageObject::GetColumnNumber() const {
|
||||
DCHECK(DidEnsureSourcePositionsAvailable());
|
||||
if (start_position() == -1) return -1;
|
||||
|
||||
Handle<Script> the_script(script(), GetIsolate());
|
||||
@ -5813,6 +5834,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
|
||||
|
@ -581,6 +581,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);
|
||||
|
@ -399,12 +399,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
|
||||
|
||||
##############################################################################
|
||||
['byteorder == big', {
|
||||
# Emscripten requires little-endian, skip all tests on big endian platforms.
|
||||
|
Loading…
Reference in New Issue
Block a user