Commit 05611feb authored by Simon Zünd's avatar Simon Zünd Committed by Commit Bot

[stack-trace] Always return lazy wrapper objects from CaptureStackTrace

This CL is the starting point to convert all FrameArray users to
use StackTraceFrame objects instead.

Bug: v8:8742
Change-Id: I7bd0081dfd428e9914dedebd5065ac262aacec0b
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1627332Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Commit-Queue: Simon Zünd <szuend@chromium.org>
Cr-Commit-Position: refs/heads/master@{#62076}
parent ef2ba534
...@@ -737,15 +737,19 @@ class FrameArrayBuilder { ...@@ -737,15 +737,19 @@ class FrameArrayBuilder {
} }
// Creates a StackTraceFrame object for each frame in the FrameArray. // Creates a StackTraceFrame object for each frame in the FrameArray.
Handle<FixedArray> GetElementsAsStackTraceFrameArray() { Handle<FixedArray> GetElementsAsStackTraceFrameArray(
bool enable_frame_caching) {
elements_->ShrinkToFit(isolate_); elements_->ShrinkToFit(isolate_);
const int frame_count = elements_->FrameCount(); const int frame_count = elements_->FrameCount();
Handle<FixedArray> stack_trace = Handle<FixedArray> stack_trace =
isolate_->factory()->NewFixedArray(frame_count); isolate_->factory()->NewFixedArray(frame_count);
for (int i = 0; i < frame_count; ++i) { for (int i = 0; i < frame_count; ++i) {
// Caching stack frames only happens for non-Wasm frames. // Caching stack frames only happens for user JS frames.
if (!elements_->IsAnyWasmFrame(i)) { const bool cache_frame =
enable_frame_caching && !elements_->IsAnyWasmFrame(i) &&
elements_->Function(i).shared().IsUserJavaScript();
if (cache_frame) {
MaybeHandle<StackTraceFrame> maybe_frame = MaybeHandle<StackTraceFrame> maybe_frame =
StackFrameCacheHelper::LookupCachedFrame( StackFrameCacheHelper::LookupCachedFrame(
isolate_, handle(elements_->Code(i), isolate_), isolate_, handle(elements_->Code(i), isolate_),
...@@ -761,7 +765,7 @@ class FrameArrayBuilder { ...@@ -761,7 +765,7 @@ class FrameArrayBuilder {
isolate_->factory()->NewStackTraceFrame(elements_, i); isolate_->factory()->NewStackTraceFrame(elements_, i);
stack_trace->set(i, *frame); stack_trace->set(i, *frame);
if (!elements_->IsAnyWasmFrame(i)) { if (cache_frame) {
StackFrameCacheHelper::CacheFrameAndUpdateCache( StackFrameCacheHelper::CacheFrameAndUpdateCache(
isolate_, handle(elements_->Code(i), isolate_), isolate_, handle(elements_->Code(i), isolate_),
Smi::ToInt(elements_->Offset(i)), frame); Smi::ToInt(elements_->Offset(i)), frame);
...@@ -974,9 +978,7 @@ struct CaptureStackTraceOptions { ...@@ -974,9 +978,7 @@ struct CaptureStackTraceOptions {
bool capture_builtin_exit_frames; bool capture_builtin_exit_frames;
bool capture_only_frames_subject_to_debugging; bool capture_only_frames_subject_to_debugging;
bool async_stack_trace; bool async_stack_trace;
bool enable_frame_caching;
enum CaptureResult { RAW_FRAME_ARRAY, STACK_TRACE_FRAME_ARRAY };
CaptureResult capture_result;
}; };
Handle<Object> CaptureStackTrace(Isolate* isolate, Handle<Object> caller, Handle<Object> CaptureStackTrace(Isolate* isolate, Handle<Object> caller,
...@@ -1106,10 +1108,8 @@ Handle<Object> CaptureStackTrace(Isolate* isolate, Handle<Object> caller, ...@@ -1106,10 +1108,8 @@ Handle<Object> CaptureStackTrace(Isolate* isolate, Handle<Object> caller,
} }
// TODO(yangguo): Queue this structured stack trace for preprocessing on GC. // TODO(yangguo): Queue this structured stack trace for preprocessing on GC.
if (options.capture_result == CaptureStackTraceOptions::RAW_FRAME_ARRAY) { return builder.GetElementsAsStackTraceFrameArray(
return builder.GetElements(); options.enable_frame_caching);
}
return builder.GetElementsAsStackTraceFrameArray();
} }
} // namespace } // namespace
...@@ -1127,7 +1127,7 @@ Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSReceiver> error_object, ...@@ -1127,7 +1127,7 @@ Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSReceiver> error_object,
options.async_stack_trace = FLAG_async_stack_traces; options.async_stack_trace = FLAG_async_stack_traces;
options.filter_mode = FrameArrayBuilder::CURRENT_SECURITY_CONTEXT; options.filter_mode = FrameArrayBuilder::CURRENT_SECURITY_CONTEXT;
options.capture_only_frames_subject_to_debugging = false; options.capture_only_frames_subject_to_debugging = false;
options.capture_result = CaptureStackTraceOptions::RAW_FRAME_ARRAY; options.enable_frame_caching = false;
return CaptureStackTrace(this, caller, options); return CaptureStackTrace(this, caller, options);
} }
...@@ -1223,7 +1223,7 @@ Handle<FixedArray> Isolate::CaptureCurrentStackTrace( ...@@ -1223,7 +1223,7 @@ Handle<FixedArray> Isolate::CaptureCurrentStackTrace(
? FrameArrayBuilder::ALL ? FrameArrayBuilder::ALL
: FrameArrayBuilder::CURRENT_SECURITY_CONTEXT; : FrameArrayBuilder::CURRENT_SECURITY_CONTEXT;
options.capture_only_frames_subject_to_debugging = true; options.capture_only_frames_subject_to_debugging = true;
options.capture_result = CaptureStackTraceOptions::STACK_TRACE_FRAME_ARRAY; options.enable_frame_caching = true;
return Handle<FixedArray>::cast( return Handle<FixedArray>::cast(
CaptureStackTrace(this, factory()->undefined_value(), options)); CaptureStackTrace(this, factory()->undefined_value(), options));
...@@ -2114,7 +2114,8 @@ bool Isolate::ComputeLocationFromStackTrace(MessageLocation* target, ...@@ -2114,7 +2114,8 @@ bool Isolate::ComputeLocationFromStackTrace(MessageLocation* target,
JSReceiver::GetDataProperty(Handle<JSObject>::cast(exception), key); JSReceiver::GetDataProperty(Handle<JSObject>::cast(exception), key);
if (!property->IsFixedArray()) return false; if (!property->IsFixedArray()) return false;
Handle<FrameArray> elements = Handle<FrameArray>::cast(property); Handle<FrameArray> elements =
GetFrameArrayFromStackTrace(this, Handle<FixedArray>::cast(property));
const int frame_count = elements->FrameCount(); const int frame_count = elements->FrameCount();
for (int i = 0; i < frame_count; i++) { for (int i = 0; i < frame_count; i++) {
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "src/objects/frame-array-inl.h" #include "src/objects/frame-array-inl.h"
#include "src/objects/js-array-inl.h" #include "src/objects/js-array-inl.h"
#include "src/objects/keys.h" #include "src/objects/keys.h"
#include "src/objects/stack-frame-info-inl.h"
#include "src/objects/struct-inl.h" #include "src/objects/struct-inl.h"
#include "src/strings/string-builder-inl.h" #include "src/strings/string-builder-inl.h"
#include "src/wasm/wasm-code-manager.h" #include "src/wasm/wasm-code-manager.h"
...@@ -905,8 +906,7 @@ StackFrameBase* FrameArrayIterator::Frame() { ...@@ -905,8 +906,7 @@ StackFrameBase* FrameArrayIterator::Frame() {
namespace { namespace {
MaybeHandle<Object> ConstructCallSite(Isolate* isolate, MaybeHandle<Object> ConstructCallSite(Isolate* isolate,
Handle<FrameArray> frame_array, Handle<StackTraceFrame> frame) {
int frame_index) {
Handle<JSFunction> target = Handle<JSFunction> target =
handle(isolate->native_context()->callsite_function(), isolate); handle(isolate->native_context()->callsite_function(), isolate);
...@@ -915,6 +915,14 @@ MaybeHandle<Object> ConstructCallSite(Isolate* isolate, ...@@ -915,6 +915,14 @@ MaybeHandle<Object> ConstructCallSite(Isolate* isolate,
isolate, obj, isolate, obj,
JSObject::New(target, target, Handle<AllocationSite>::null()), Object); JSObject::New(target, target, Handle<AllocationSite>::null()), Object);
// TODO(szuend): Introduce a new symbol "call_site_frame_symbol" and set
// it to the StackTraceFrame. The CallSite API builtins can then
// be implemented using StackFrameInfo objects.
Handle<FrameArray> frame_array(FrameArray::cast(frame->frame_array()),
isolate);
int frame_index = frame->frame_index();
Handle<Symbol> key = isolate->factory()->call_site_frame_array_symbol(); Handle<Symbol> key = isolate->factory()->call_site_frame_array_symbol();
RETURN_ON_EXCEPTION(isolate, RETURN_ON_EXCEPTION(isolate,
JSObject::SetOwnPropertyIgnoreAttributes( JSObject::SetOwnPropertyIgnoreAttributes(
...@@ -934,14 +942,16 @@ MaybeHandle<Object> ConstructCallSite(Isolate* isolate, ...@@ -934,14 +942,16 @@ MaybeHandle<Object> ConstructCallSite(Isolate* isolate,
// Convert the raw frames as written by Isolate::CaptureSimpleStackTrace into // Convert the raw frames as written by Isolate::CaptureSimpleStackTrace into
// a JSArray of JSCallSite objects. // a JSArray of JSCallSite objects.
MaybeHandle<JSArray> GetStackFrames(Isolate* isolate, MaybeHandle<JSArray> GetStackFrames(Isolate* isolate,
Handle<FrameArray> elems) { Handle<FixedArray> elems) {
const int frame_count = elems->FrameCount(); const int frame_count = elems->length();
Handle<FixedArray> frames = isolate->factory()->NewFixedArray(frame_count); Handle<FixedArray> frames = isolate->factory()->NewFixedArray(frame_count);
for (int i = 0; i < frame_count; i++) { for (int i = 0; i < frame_count; i++) {
Handle<Object> site; Handle<Object> site;
ASSIGN_RETURN_ON_EXCEPTION(isolate, site, Handle<StackTraceFrame> frame(StackTraceFrame::cast(elems->get(i)),
ConstructCallSite(isolate, elems, i), JSArray); isolate);
ASSIGN_RETURN_ON_EXCEPTION(isolate, site, ConstructCallSite(isolate, frame),
JSArray);
frames->set(i, *site); frames->set(i, *site);
} }
...@@ -1004,7 +1014,7 @@ MaybeHandle<Object> ErrorUtils::FormatStackTrace(Isolate* isolate, ...@@ -1004,7 +1014,7 @@ MaybeHandle<Object> ErrorUtils::FormatStackTrace(Isolate* isolate,
Handle<JSObject> error, Handle<JSObject> error,
Handle<Object> raw_stack) { Handle<Object> raw_stack) {
DCHECK(raw_stack->IsFixedArray()); DCHECK(raw_stack->IsFixedArray());
Handle<FrameArray> elems = Handle<FrameArray>::cast(raw_stack); Handle<FixedArray> elems = Handle<FixedArray>::cast(raw_stack);
const bool in_recursion = isolate->formatting_stack_trace(); const bool in_recursion = isolate->formatting_stack_trace();
if (!in_recursion) { if (!in_recursion) {
...@@ -1071,7 +1081,9 @@ MaybeHandle<Object> ErrorUtils::FormatStackTrace(Isolate* isolate, ...@@ -1071,7 +1081,9 @@ MaybeHandle<Object> ErrorUtils::FormatStackTrace(Isolate* isolate,
wasm::WasmCodeRefScope wasm_code_ref_scope; wasm::WasmCodeRefScope wasm_code_ref_scope;
for (FrameArrayIterator it(isolate, elems); it.HasFrame(); it.Advance()) { Handle<FrameArray> frame_array = GetFrameArrayFromStackTrace(isolate, elems);
for (FrameArrayIterator it(isolate, frame_array); it.HasFrame();
it.Advance()) {
builder.AppendCString("\n at "); builder.AppendCString("\n at ");
StackFrameBase* frame = it.Frame(); StackFrameBase* frame = it.Frame();
......
...@@ -137,5 +137,20 @@ void StackTraceFrame::InitializeFrameInfo(Handle<StackTraceFrame> frame) { ...@@ -137,5 +137,20 @@ void StackTraceFrame::InitializeFrameInfo(Handle<StackTraceFrame> frame) {
frame->set_frame_index(-1); frame->set_frame_index(-1);
} }
Handle<FrameArray> GetFrameArrayFromStackTrace(Isolate* isolate,
Handle<FixedArray> stack_trace) {
// For the empty case, a empty FrameArray needs to be allocated so the rest
// of the code doesn't has to be special cased everywhere.
if (stack_trace->length() == 0) {
return isolate->factory()->NewFrameArray(0);
}
// Retrieve the FrameArray from the first StackTraceFrame.
DCHECK_GT(stack_trace->length(), 0);
Handle<StackTraceFrame> frame(StackTraceFrame::cast(stack_trace->get(0)),
isolate);
return handle(FrameArray::cast(frame->frame_array()), isolate);
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -113,6 +113,14 @@ class StackTraceFrame : public Struct { ...@@ -113,6 +113,14 @@ class StackTraceFrame : public Struct {
static void InitializeFrameInfo(Handle<StackTraceFrame> frame); static void InitializeFrameInfo(Handle<StackTraceFrame> frame);
}; };
// Small helper that retrieves the FrameArray from a stack-trace
// consisting of a FixedArray of StackTraceFrame objects.
// This helper is only temporary until all FrameArray use-sites have
// been converted to use StackTraceFrame and StackFrameInfo objects.
V8_EXPORT_PRIVATE
Handle<FrameArray> GetFrameArrayFromStackTrace(Isolate* isolate,
Handle<FixedArray> stack_trace);
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
......
...@@ -3444,10 +3444,10 @@ void DetailedErrorStackTraceTest(const char* src, ...@@ -3444,10 +3444,10 @@ void DetailedErrorStackTraceTest(const char* src,
Isolate* isolate = CcTest::i_isolate(); Isolate* isolate = CcTest::i_isolate();
Handle<Name> key = isolate->factory()->stack_trace_symbol(); Handle<Name> key = isolate->factory()->stack_trace_symbol();
Handle<FrameArray> stack_trace(Handle<FrameArray>::cast( Handle<FixedArray> stack_trace(Handle<FixedArray>::cast(
Object::GetProperty(isolate, exception, key).ToHandleChecked())); Object::GetProperty(isolate, exception, key).ToHandleChecked()));
test(stack_trace); test(GetFrameArrayFromStackTrace(isolate, stack_trace));
} }
// * Test interpreted function error // * Test interpreted function error
......
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