Add new FrameArray type
A FrameArray encodes information about a set of stack frames into a fixed array. This commit is a pure refactoring to make the structure of fixed array-encoded frames explicit. BUG= Review-Url: https://codereview.chromium.org/2270783002 Cr-Commit-Position: refs/heads/master@{#38852}
This commit is contained in:
parent
2053d142e0
commit
19e8380261
@ -178,6 +178,14 @@ Handle<FixedArrayBase> Factory::NewFixedDoubleArrayWithHoles(
|
||||
return array;
|
||||
}
|
||||
|
||||
Handle<FrameArray> Factory::NewFrameArray(int number_of_frames,
|
||||
PretenureFlag pretenure) {
|
||||
DCHECK_LE(0, number_of_frames);
|
||||
Handle<FixedArray> result =
|
||||
NewFixedArrayWithHoles(FrameArray::LengthFor(number_of_frames));
|
||||
result->set(FrameArray::kFrameCountIndex, Smi::FromInt(0));
|
||||
return Handle<FrameArray>::cast(result);
|
||||
}
|
||||
|
||||
Handle<OrderedHashSet> Factory::NewOrderedHashSet() {
|
||||
return OrderedHashSet::Allocate(isolate(), OrderedHashSet::kMinCapacity);
|
||||
|
@ -52,6 +52,9 @@ class Factory final {
|
||||
int size,
|
||||
PretenureFlag pretenure = NOT_TENURED);
|
||||
|
||||
Handle<FrameArray> NewFrameArray(int number_of_frames,
|
||||
PretenureFlag pretenure = NOT_TENURED);
|
||||
|
||||
Handle<OrderedHashSet> NewOrderedHashSet();
|
||||
Handle<OrderedHashMap> NewOrderedHashMap();
|
||||
|
||||
|
@ -128,6 +128,7 @@
|
||||
V(sourceText_string, "sourceText") \
|
||||
V(source_url_string, "source_url") \
|
||||
V(stack_string, "stack") \
|
||||
V(stackTraceLimit_string, "stackTraceLimit") \
|
||||
V(strict_compare_ic_string, "===") \
|
||||
V(string_string, "string") \
|
||||
V(String_string, "String") \
|
||||
|
132
src/isolate.cc
132
src/isolate.cc
@ -315,21 +315,7 @@ void Isolate::PushStackTraceAndDie(unsigned int magic, void* ptr1, void* ptr2,
|
||||
base::OS::Abort();
|
||||
}
|
||||
|
||||
static Handle<FixedArray> MaybeGrow(Isolate* isolate,
|
||||
Handle<FixedArray> elements,
|
||||
int cur_position, int new_size) {
|
||||
if (new_size > elements->length()) {
|
||||
int new_capacity = JSObject::NewElementsCapacity(elements->length());
|
||||
Handle<FixedArray> new_elements =
|
||||
isolate->factory()->NewFixedArrayWithHoles(new_capacity);
|
||||
for (int i = 0; i < cur_position; i++) {
|
||||
new_elements->set(i, elements->get(i));
|
||||
}
|
||||
elements = new_elements;
|
||||
}
|
||||
DCHECK(new_size <= elements->length());
|
||||
return elements;
|
||||
}
|
||||
namespace {
|
||||
|
||||
class StackTraceHelper {
|
||||
public:
|
||||
@ -435,8 +421,6 @@ class StackTraceHelper {
|
||||
bool encountered_strict_function_;
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
// TODO(jgruber): Fix all cases in which frames give us a hole value (e.g. the
|
||||
// receiver in RegExp constructor frames.
|
||||
Handle<Object> TheHoleToUndefined(Isolate* isolate, Handle<Object> in) {
|
||||
@ -444,35 +428,36 @@ Handle<Object> TheHoleToUndefined(Isolate* isolate, Handle<Object> in) {
|
||||
? Handle<Object>::cast(isolate->factory()->undefined_value())
|
||||
: in;
|
||||
}
|
||||
|
||||
bool GetStackTraceLimit(Isolate* isolate, int* result) {
|
||||
Handle<JSObject> error = isolate->error_function();
|
||||
|
||||
Handle<String> key = isolate->factory()->stackTraceLimit_string();
|
||||
Handle<Object> stack_trace_limit = JSReceiver::GetDataProperty(error, key);
|
||||
if (!stack_trace_limit->IsNumber()) return false;
|
||||
|
||||
// Ensure that limit is not negative.
|
||||
*result = Max(FastD2IChecked(stack_trace_limit->Number()), 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSReceiver> error_object,
|
||||
FrameSkipMode mode,
|
||||
Handle<Object> caller) {
|
||||
DisallowJavascriptExecution no_js(this);
|
||||
|
||||
// Get stack trace limit.
|
||||
Handle<JSObject> error = error_function();
|
||||
Handle<String> stackTraceLimit =
|
||||
factory()->InternalizeUtf8String("stackTraceLimit");
|
||||
DCHECK(!stackTraceLimit.is_null());
|
||||
Handle<Object> stack_trace_limit =
|
||||
JSReceiver::GetDataProperty(error, stackTraceLimit);
|
||||
if (!stack_trace_limit->IsNumber()) return factory()->undefined_value();
|
||||
int limit = FastD2IChecked(stack_trace_limit->Number());
|
||||
limit = Max(limit, 0); // Ensure that limit is not negative.
|
||||
int limit;
|
||||
if (!GetStackTraceLimit(this, &limit)) return factory()->undefined_value();
|
||||
|
||||
int initial_size = Min(limit, 10);
|
||||
Handle<FixedArray> elements =
|
||||
factory()->NewFixedArrayWithHoles(initial_size * 4 + 1);
|
||||
const int initial_size = Min(limit, 10);
|
||||
Handle<FrameArray> elements = factory()->NewFrameArray(initial_size);
|
||||
|
||||
StackTraceHelper helper(this, mode, caller);
|
||||
|
||||
// First element is reserved to store the number of sloppy frames.
|
||||
int cursor = 1;
|
||||
int frames_seen = 0;
|
||||
for (StackFrameIterator iter(this); !iter.done() && frames_seen < limit;
|
||||
iter.Advance()) {
|
||||
for (StackFrameIterator iter(this);
|
||||
!iter.done() && elements->FrameCount() < limit; iter.Advance()) {
|
||||
StackFrame* frame = iter.frame();
|
||||
|
||||
switch (frame->type()) {
|
||||
@ -502,14 +487,11 @@ Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSReceiver> error_object,
|
||||
recv = handle(heap()->call_site_constructor_symbol(), this);
|
||||
}
|
||||
}
|
||||
Handle<Smi> offset(Smi::FromInt(frames[i].code_offset()), this);
|
||||
const int offset = frames[i].code_offset();
|
||||
|
||||
elements = MaybeGrow(this, elements, cursor, cursor + 4);
|
||||
elements->set(cursor++, *TheHoleToUndefined(this, recv));
|
||||
elements->set(cursor++, *fun);
|
||||
elements->set(cursor++, *abstract_code);
|
||||
elements->set(cursor++, *offset);
|
||||
frames_seen++;
|
||||
elements = FrameArray::AppendJSFrame(elements,
|
||||
TheHoleToUndefined(this, recv),
|
||||
fun, abstract_code, offset);
|
||||
}
|
||||
} break;
|
||||
|
||||
@ -534,39 +516,39 @@ Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSReceiver> error_object,
|
||||
recv = handle(exit_frame->receiver(), this);
|
||||
}
|
||||
|
||||
elements = MaybeGrow(this, elements, cursor, cursor + 4);
|
||||
elements->set(cursor++, *recv);
|
||||
elements->set(cursor++, *fun);
|
||||
elements->set(cursor++, *code);
|
||||
elements->set(cursor++, Smi::FromInt(offset));
|
||||
frames_seen++;
|
||||
elements = FrameArray::AppendJSFrame(
|
||||
elements, recv, fun, Handle<AbstractCode>::cast(code), offset);
|
||||
} break;
|
||||
|
||||
case StackFrame::WASM: {
|
||||
WasmFrame* wasm_frame = WasmFrame::cast(frame);
|
||||
Handle<Object> wasm_object = handle(wasm_frame->wasm_obj(), this);
|
||||
const int wasm_function_index = wasm_frame->function_index();
|
||||
Code* code = wasm_frame->unchecked_code();
|
||||
Handle<AbstractCode> abstract_code =
|
||||
Handle<AbstractCode>(AbstractCode::cast(code), this);
|
||||
int offset =
|
||||
const int offset =
|
||||
static_cast<int>(wasm_frame->pc() - code->instruction_start());
|
||||
elements = MaybeGrow(this, elements, cursor, cursor + 4);
|
||||
elements->set(cursor++, wasm_frame->wasm_obj());
|
||||
elements->set(cursor++, Smi::FromInt(wasm_frame->function_index()));
|
||||
elements->set(cursor++, *abstract_code);
|
||||
elements->set(cursor++, Smi::FromInt(offset));
|
||||
frames_seen++;
|
||||
|
||||
// TODO(wasm): The wasm object returned by the WasmFrame should always
|
||||
// be a wasm object.
|
||||
DCHECK(wasm::IsWasmObject(*wasm_object) ||
|
||||
wasm_object->IsUndefined(this));
|
||||
|
||||
elements = FrameArray::AppendWasmFrame(
|
||||
elements, wasm_object, wasm_function_index, abstract_code, offset);
|
||||
} break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
elements->set(0, Smi::FromInt(helper.sloppy_frames()));
|
||||
elements->Shrink(cursor);
|
||||
Handle<JSArray> result = factory()->NewJSArrayWithElements(elements);
|
||||
result->set_length(Smi::FromInt(cursor));
|
||||
|
||||
elements->SetSloppyFrameCount(helper.sloppy_frames());
|
||||
elements->ShrinkToFit();
|
||||
|
||||
// TODO(yangguo): Queue this structured stack trace for preprocessing on GC.
|
||||
return result;
|
||||
return factory()->NewJSArrayWithElements(elements);
|
||||
}
|
||||
|
||||
MaybeHandle<JSReceiver> Isolate::CaptureAndSetDetailedStackTrace(
|
||||
@ -773,19 +755,6 @@ class CaptureStackTraceHelper {
|
||||
Handle<String> constructor_key_;
|
||||
};
|
||||
|
||||
|
||||
int PositionFromStackTrace(Handle<FixedArray> elements, int index) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
Object* maybe_code = elements->get(index + 2);
|
||||
if (maybe_code->IsSmi()) {
|
||||
return Smi::cast(maybe_code)->value();
|
||||
} else {
|
||||
AbstractCode* abstract_code = AbstractCode::cast(maybe_code);
|
||||
int code_offset = Smi::cast(elements->get(index + 3))->value();
|
||||
return abstract_code->SourcePosition(code_offset);
|
||||
}
|
||||
}
|
||||
|
||||
Handle<JSArray> Isolate::CaptureCurrentStackTrace(
|
||||
int frame_limit, StackTrace::StackTraceOptions options) {
|
||||
DisallowJavascriptExecution no_js(this);
|
||||
@ -1531,22 +1500,25 @@ bool Isolate::ComputeLocationFromStackTrace(MessageLocation* target,
|
||||
if (!property->IsJSArray()) return false;
|
||||
Handle<JSArray> simple_stack_trace = Handle<JSArray>::cast(property);
|
||||
|
||||
Handle<FixedArray> elements(FixedArray::cast(simple_stack_trace->elements()));
|
||||
int elements_limit = Smi::cast(simple_stack_trace->length())->value();
|
||||
Handle<FrameArray> elements(FrameArray::cast(simple_stack_trace->elements()));
|
||||
|
||||
for (int i = 1; i < elements_limit; i += 4) {
|
||||
Handle<Object> fun_obj = handle(elements->get(i + 1), this);
|
||||
if (fun_obj->IsSmi()) {
|
||||
const int frame_count = elements->FrameCount();
|
||||
for (int i = 0; i < frame_count; i++) {
|
||||
if (elements->IsWasmFrame(i)) {
|
||||
// TODO(clemensh): handle wasm frames
|
||||
return false;
|
||||
}
|
||||
Handle<JSFunction> fun = Handle<JSFunction>::cast(fun_obj);
|
||||
|
||||
Handle<JSFunction> fun = handle(elements->Function(i), this);
|
||||
if (!fun->shared()->IsSubjectToDebugging()) continue;
|
||||
|
||||
Object* script = fun->shared()->script();
|
||||
if (script->IsScript() &&
|
||||
!(Script::cast(script)->source()->IsUndefined(this))) {
|
||||
int pos = PositionFromStackTrace(elements, i);
|
||||
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));
|
||||
*target = MessageLocation(casted_script, pos, pos + 1);
|
||||
return true;
|
||||
|
@ -495,44 +495,52 @@ MaybeHandle<FixedArray> GetStackFrames(Isolate* isolate,
|
||||
Handle<JSArray> raw_stack_array = Handle<JSArray>::cast(raw_stack);
|
||||
|
||||
DCHECK(raw_stack_array->elements()->IsFixedArray());
|
||||
Handle<FixedArray> raw_stack_elements =
|
||||
handle(FixedArray::cast(raw_stack_array->elements()), isolate);
|
||||
Handle<FrameArray> elems(FrameArray::cast(raw_stack_array->elements()));
|
||||
|
||||
const int raw_stack_len = raw_stack_elements->length();
|
||||
DCHECK(raw_stack_len % 4 == 1); // Multiples of 4 plus sloppy frames count.
|
||||
const int frame_count = (raw_stack_len - 1) / 4;
|
||||
const int frame_count = elems->FrameCount();
|
||||
|
||||
Handle<Object> sloppy_frames_obj =
|
||||
FixedArray::get(*raw_stack_elements, 0, isolate);
|
||||
int sloppy_frames = Handle<Smi>::cast(sloppy_frames_obj)->value();
|
||||
int sloppy_frames = elems->SloppyFrameCount();
|
||||
|
||||
int dst_ix = 0;
|
||||
Handle<FixedArray> frames = isolate->factory()->NewFixedArray(frame_count);
|
||||
for (int i = 1; i < raw_stack_len; i += 4) {
|
||||
Handle<Object> recv = FixedArray::get(*raw_stack_elements, i, isolate);
|
||||
Handle<Object> fun = FixedArray::get(*raw_stack_elements, i + 1, isolate);
|
||||
Handle<AbstractCode> code = Handle<AbstractCode>::cast(
|
||||
FixedArray::get(*raw_stack_elements, i + 2, isolate));
|
||||
Handle<Smi> pc =
|
||||
Handle<Smi>::cast(FixedArray::get(*raw_stack_elements, i + 3, isolate));
|
||||
|
||||
Handle<Object> pos =
|
||||
(fun->IsSmi() && pc->value() < 0)
|
||||
? handle(Smi::FromInt(-1 - pc->value()), isolate)
|
||||
: handle(Smi::FromInt(code->SourcePosition(pc->value())), isolate);
|
||||
for (int i = 0; i < frame_count; i++) {
|
||||
Handle<AbstractCode> code(elems->Code(i), isolate);
|
||||
Handle<Smi> pc(elems->Offset(i), isolate);
|
||||
|
||||
sloppy_frames--;
|
||||
Handle<Object> strict = isolate->factory()->ToBoolean(sloppy_frames < 0);
|
||||
|
||||
Handle<Object> callsite;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate, callsite,
|
||||
CallSiteUtils::Construct(isolate, recv, fun, pos, strict), FixedArray);
|
||||
if (elems->IsWasmFrame(i)) {
|
||||
Handle<Object> wasm_obj(elems->WasmObject(i), isolate);
|
||||
Handle<Smi> wasm_fun_ix(elems->WasmFunctionIndex(i), isolate);
|
||||
|
||||
frames->set(dst_ix++, *callsite);
|
||||
Handle<Object> pos((pc->value() < 0)
|
||||
? Smi::FromInt(-1 - pc->value())
|
||||
: Smi::FromInt(code->SourcePosition(pc->value())),
|
||||
isolate);
|
||||
|
||||
Handle<Object> callsite;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate, callsite,
|
||||
CallSiteUtils::Construct(isolate, wasm_obj, wasm_fun_ix, pos, strict),
|
||||
FixedArray);
|
||||
|
||||
frames->set(i, *callsite);
|
||||
} else {
|
||||
Handle<Object> recv(elems->Receiver(i), isolate);
|
||||
Handle<Object> fun(elems->Function(i), isolate);
|
||||
Handle<Object> pos(Smi::FromInt(code->SourcePosition(pc->value())),
|
||||
isolate);
|
||||
|
||||
Handle<Object> callsite;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate, callsite,
|
||||
CallSiteUtils::Construct(isolate, recv, fun, pos, strict),
|
||||
FixedArray);
|
||||
|
||||
frames->set(i, *callsite);
|
||||
}
|
||||
}
|
||||
|
||||
DCHECK_EQ(frame_count, dst_ix);
|
||||
return frames;
|
||||
}
|
||||
|
||||
|
@ -709,6 +709,8 @@ bool HeapObject::IsJSCollection() const { return IsJSMap() || IsJSSet(); }
|
||||
|
||||
bool HeapObject::IsDescriptorArray() const { return IsFixedArray(); }
|
||||
|
||||
bool HeapObject::IsFrameArray() const { return IsFixedArray(); }
|
||||
|
||||
bool HeapObject::IsArrayList() const { return IsFixedArray(); }
|
||||
|
||||
bool Object::IsLayoutDescriptor() const {
|
||||
@ -2610,6 +2612,38 @@ Object** FixedArray::RawFieldOfElementAt(int index) {
|
||||
return HeapObject::RawField(this, OffsetOfElementAt(index));
|
||||
}
|
||||
|
||||
#define DEFINE_FRAME_ARRAY_ACCESSORS(name, type) \
|
||||
type* FrameArray::name(int frame_ix) const { \
|
||||
Object* obj = \
|
||||
get(kFirstIndex + frame_ix * kElementsPerFrame + k##name##Offset); \
|
||||
return type::cast(obj); \
|
||||
} \
|
||||
\
|
||||
void FrameArray::Set##name(int frame_ix, type* value) { \
|
||||
set(kFirstIndex + frame_ix * kElementsPerFrame + k##name##Offset, value); \
|
||||
}
|
||||
FRAME_ARRAY_FIELD_LIST(DEFINE_FRAME_ARRAY_ACCESSORS)
|
||||
#undef DEFINE_FRAME_ARRAY_ACCESSORS
|
||||
|
||||
int FrameArray::SloppyFrameCount() const {
|
||||
return Smi::cast(get(kSloppyFramesIndex))->value();
|
||||
}
|
||||
|
||||
void FrameArray::SetSloppyFrameCount(int count) {
|
||||
return set(kSloppyFramesIndex, Smi::FromInt(count));
|
||||
}
|
||||
|
||||
bool FrameArray::IsWasmFrame(int frame_ix) const {
|
||||
Object* obj = get(kFirstIndex + frame_ix * kElementsPerFrame +
|
||||
kWasmFunctionIndexOffset);
|
||||
return obj->IsSmi();
|
||||
}
|
||||
|
||||
int FrameArray::FrameCount() const {
|
||||
const int frame_count = Smi::cast(get(kFrameCountIndex))->value();
|
||||
DCHECK_LE(0, frame_count);
|
||||
return frame_count;
|
||||
}
|
||||
|
||||
bool DescriptorArray::IsEmpty() {
|
||||
DCHECK(length() >= kFirstIndex ||
|
||||
@ -3223,6 +3257,7 @@ CAST_ACCESSOR(FixedDoubleArray)
|
||||
CAST_ACCESSOR(FixedTypedArrayBase)
|
||||
CAST_ACCESSOR(Float32x4)
|
||||
CAST_ACCESSOR(Foreign)
|
||||
CAST_ACCESSOR(FrameArray)
|
||||
CAST_ACCESSOR(GlobalDictionary)
|
||||
CAST_ACCESSOR(HandlerTable)
|
||||
CAST_ACCESSOR(HeapObject)
|
||||
|
@ -10177,22 +10177,74 @@ bool ArrayList::IsFull() {
|
||||
return kFirstIndex + Length() == capacity;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
Handle<ArrayList> ArrayList::EnsureSpace(Handle<ArrayList> array, int length) {
|
||||
Handle<FixedArray> EnsureSpaceInFixedArray(Handle<FixedArray> array,
|
||||
int length) {
|
||||
int capacity = array->length();
|
||||
bool empty = (capacity == 0);
|
||||
if (capacity < kFirstIndex + length) {
|
||||
if (capacity < length) {
|
||||
Isolate* isolate = array->GetIsolate();
|
||||
int new_capacity = kFirstIndex + length;
|
||||
int new_capacity = length;
|
||||
new_capacity = new_capacity + Max(new_capacity / 2, 2);
|
||||
int grow_by = new_capacity - capacity;
|
||||
array = Handle<ArrayList>::cast(
|
||||
isolate->factory()->CopyFixedArrayAndGrow(array, grow_by));
|
||||
if (empty) array->SetLength(0);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Handle<ArrayList> ArrayList::EnsureSpace(Handle<ArrayList> array, int length) {
|
||||
const bool empty = (array->length() == 0);
|
||||
auto ret = Handle<ArrayList>::cast(
|
||||
EnsureSpaceInFixedArray(array, kFirstIndex + length));
|
||||
if (empty) ret->SetLength(0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// static
|
||||
Handle<FrameArray> FrameArray::AppendJSFrame(Handle<FrameArray> in,
|
||||
Handle<Object> receiver,
|
||||
Handle<JSFunction> function,
|
||||
Handle<AbstractCode> code,
|
||||
int offset) {
|
||||
const int frame_count = in->FrameCount();
|
||||
const int new_length = LengthFor(frame_count + 1);
|
||||
Handle<FrameArray> array = EnsureSpace(in, new_length);
|
||||
array->SetReceiver(frame_count, *receiver);
|
||||
array->SetFunction(frame_count, *function);
|
||||
array->SetCode(frame_count, *code);
|
||||
array->SetOffset(frame_count, Smi::FromInt(offset));
|
||||
array->set(kFrameCountIndex, Smi::FromInt(frame_count + 1));
|
||||
return array;
|
||||
}
|
||||
|
||||
// static
|
||||
Handle<FrameArray> FrameArray::AppendWasmFrame(Handle<FrameArray> in,
|
||||
Handle<Object> wasm_object,
|
||||
int wasm_function_index,
|
||||
Handle<AbstractCode> code,
|
||||
int offset) {
|
||||
const int frame_count = in->FrameCount();
|
||||
const int new_length = LengthFor(frame_count + 1);
|
||||
Handle<FrameArray> array = EnsureSpace(in, new_length);
|
||||
array->SetWasmObject(frame_count, *wasm_object);
|
||||
array->SetWasmFunctionIndex(frame_count, Smi::FromInt(wasm_function_index));
|
||||
array->SetCode(frame_count, *code);
|
||||
array->SetOffset(frame_count, Smi::FromInt(offset));
|
||||
array->set(kFrameCountIndex, Smi::FromInt(frame_count + 1));
|
||||
return array;
|
||||
}
|
||||
|
||||
void FrameArray::ShrinkToFit() { Shrink(LengthFor(FrameCount())); }
|
||||
|
||||
// static
|
||||
Handle<FrameArray> FrameArray::EnsureSpace(Handle<FrameArray> array,
|
||||
int length) {
|
||||
return Handle<FrameArray>::cast(EnsureSpaceInFixedArray(array, length));
|
||||
}
|
||||
|
||||
Handle<DescriptorArray> DescriptorArray::Allocate(Isolate* isolate,
|
||||
int number_of_descriptors,
|
||||
int slack,
|
||||
|
@ -76,6 +76,7 @@
|
||||
// - BytecodeArray
|
||||
// - FixedArray
|
||||
// - DescriptorArray
|
||||
// - FrameArray
|
||||
// - LiteralsArray
|
||||
// - HashTable
|
||||
// - Dictionary
|
||||
@ -862,7 +863,7 @@ enum class ComparisonResult {
|
||||
INLINE(static type* cast(Object* object)); \
|
||||
INLINE(static const type* cast(const Object* object));
|
||||
|
||||
|
||||
class AbstractCode;
|
||||
class AccessorPair;
|
||||
class AllocationSite;
|
||||
class AllocationSiteCreationContext;
|
||||
@ -961,6 +962,7 @@ template <class C> inline bool Is(Object* obj);
|
||||
V(JSGeneratorObject) \
|
||||
V(Map) \
|
||||
V(DescriptorArray) \
|
||||
V(FrameArray) \
|
||||
V(TransitionArray) \
|
||||
V(LiteralsArray) \
|
||||
V(TypeFeedbackMetadata) \
|
||||
@ -2895,7 +2897,6 @@ class WeakFixedArray : public FixedArray {
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(WeakFixedArray);
|
||||
};
|
||||
|
||||
|
||||
// Generic array grows dynamically with O(1) amortized insertion.
|
||||
class ArrayList : public FixedArray {
|
||||
public:
|
||||
@ -2925,6 +2926,76 @@ class ArrayList : public FixedArray {
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(ArrayList);
|
||||
};
|
||||
|
||||
#define FRAME_ARRAY_FIELD_LIST(V) \
|
||||
V(WasmObject, Object) \
|
||||
V(WasmFunctionIndex, Smi) \
|
||||
V(Receiver, Object) \
|
||||
V(Function, JSFunction) \
|
||||
V(Code, AbstractCode) \
|
||||
V(Offset, Smi)
|
||||
|
||||
// Container object for data collected during simple stack trace captures.
|
||||
class FrameArray : public FixedArray {
|
||||
public:
|
||||
#define DECLARE_FRAME_ARRAY_ACCESSORS(name, type) \
|
||||
inline type* name(int frame_ix) const; \
|
||||
inline void Set##name(int frame_ix, type* value);
|
||||
FRAME_ARRAY_FIELD_LIST(DECLARE_FRAME_ARRAY_ACCESSORS)
|
||||
#undef DECLARE_FRAME_ARRAY_ACCESSORS
|
||||
|
||||
inline void SetSloppyFrameCount(int count);
|
||||
inline int SloppyFrameCount() const;
|
||||
|
||||
inline bool IsWasmFrame(int frame_ix) const;
|
||||
inline int FrameCount() const;
|
||||
|
||||
void ShrinkToFit();
|
||||
|
||||
static Handle<FrameArray> AppendJSFrame(Handle<FrameArray> in,
|
||||
Handle<Object> receiver,
|
||||
Handle<JSFunction> function,
|
||||
Handle<AbstractCode> code,
|
||||
int offset);
|
||||
static Handle<FrameArray> AppendWasmFrame(Handle<FrameArray> in,
|
||||
Handle<Object> wasm_object,
|
||||
int wasm_function_index,
|
||||
Handle<AbstractCode> code,
|
||||
int offset);
|
||||
|
||||
DECLARE_CAST(FrameArray)
|
||||
|
||||
private:
|
||||
// The underlying fixed array embodies a captured stack trace. The number of
|
||||
// sloppy frames is stored at array[kFirstIndex]. Frame i occupies indices
|
||||
// kFirstIndex + 1 + [i * kElementsPerFrame, (i + 1) * kElementsPerFrame[,
|
||||
// with internal offsets as below:
|
||||
|
||||
static const int kWasmObjectOffset = 0;
|
||||
static const int kWasmFunctionIndexOffset = 1;
|
||||
|
||||
static const int kReceiverOffset = 0;
|
||||
static const int kFunctionOffset = 1;
|
||||
|
||||
static const int kCodeOffset = 2;
|
||||
static const int kOffsetOffset = 3;
|
||||
|
||||
static const int kElementsPerFrame = 4;
|
||||
|
||||
// Array layout indices.
|
||||
|
||||
static const int kFrameCountIndex = 0;
|
||||
static const int kSloppyFramesIndex = 1;
|
||||
static const int kFirstIndex = 2;
|
||||
|
||||
static int LengthFor(int frame_count) {
|
||||
return kFirstIndex + frame_count * kElementsPerFrame;
|
||||
}
|
||||
|
||||
static Handle<FrameArray> EnsureSpace(Handle<FrameArray> array, int length);
|
||||
|
||||
friend class Factory;
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(FrameArray);
|
||||
};
|
||||
|
||||
// DescriptorArrays are fixed arrays used to hold instance descriptors.
|
||||
// The format of the these objects is:
|
||||
|
@ -120,18 +120,17 @@ RUNTIME_FUNCTION(Runtime_ThrowWasmError) {
|
||||
error, isolate->factory()->stack_trace_symbol());
|
||||
// Patch the stack trace (array of <receiver, function, code, position>).
|
||||
if (stack_trace_obj->IsJSArray()) {
|
||||
Handle<FixedArray> stack_elements(
|
||||
FixedArray::cast(JSArray::cast(*stack_trace_obj)->elements()));
|
||||
DCHECK_EQ(1, stack_elements->length() % 4);
|
||||
DCHECK(Code::cast(stack_elements->get(3))->kind() == Code::WASM_FUNCTION);
|
||||
DCHECK(stack_elements->get(4)->IsSmi() &&
|
||||
Smi::cast(stack_elements->get(4))->value() >= 0);
|
||||
stack_elements->set(4, Smi::FromInt(-1 - byte_offset));
|
||||
Handle<FrameArray> stack_elements(
|
||||
FrameArray::cast(JSArray::cast(*stack_trace_obj)->elements()));
|
||||
DCHECK(stack_elements->Code(0)->kind() == AbstractCode::WASM_FUNCTION);
|
||||
DCHECK(stack_elements->Offset(0)->value() >= 0);
|
||||
stack_elements->SetOffset(0, Smi::FromInt(-1 - byte_offset));
|
||||
}
|
||||
Handle<Object> detailed_stack_trace_obj = JSReceiver::GetDataProperty(
|
||||
error, isolate->factory()->detailed_stack_trace_symbol());
|
||||
|
||||
// Patch the detailed stack trace (array of JSObjects with various
|
||||
// properties).
|
||||
Handle<Object> detailed_stack_trace_obj = JSReceiver::GetDataProperty(
|
||||
error, isolate->factory()->detailed_stack_trace_symbol());
|
||||
if (detailed_stack_trace_obj->IsJSArray()) {
|
||||
Handle<FixedArray> stack_elements(
|
||||
FixedArray::cast(JSArray::cast(*detailed_stack_trace_obj)->elements()));
|
||||
|
Loading…
Reference in New Issue
Block a user