| Index: src/frames.cc
|
| diff --git a/src/frames.cc b/src/frames.cc
|
| index 0e3851d16a23b791699368be3a43596fad030c19..bf181427f2a7dd2a1d28dfe60cf7d08cf7e2b604 100644
|
| --- a/src/frames.cc
|
| +++ b/src/frames.cc
|
| @@ -474,11 +474,13 @@ StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator,
|
| case Code::OPTIMIZED_FUNCTION:
|
| return OPTIMIZED;
|
| case Code::WASM_FUNCTION:
|
| - return WASM;
|
| + return WASM_COMPILED;
|
| case Code::WASM_TO_JS_FUNCTION:
|
| return WASM_TO_JS;
|
| case Code::JS_TO_WASM_FUNCTION:
|
| return JS_TO_WASM;
|
| + case Code::WASM_TO_INTERPRETER:
|
| + return WASM_INTERPRETED;
|
| default:
|
| // All other types should have an explicit marker
|
| break;
|
| @@ -501,7 +503,8 @@ StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator,
|
| case CONSTRUCT:
|
| case ARGUMENTS_ADAPTOR:
|
| case WASM_TO_JS:
|
| - case WASM:
|
| + case WASM_COMPILED:
|
| + case WASM_INTERPRETED:
|
| return candidate;
|
| case JS_TO_WASM:
|
| case JAVA_SCRIPT:
|
| @@ -656,6 +659,12 @@ Object* StandardFrame::context() const {
|
| return isolate()->heap()->undefined_value();
|
| }
|
|
|
| +Object* StandardFrame::debug_info(bool create) const {
|
| + // This should only be called on frames which override this method.
|
| + DCHECK(false);
|
| + return nullptr;
|
| +}
|
| +
|
| int StandardFrame::ComputeExpressionsCount() const {
|
| Address base = GetExpressionAddress(0);
|
| Address limit = sp() - kPointerSize;
|
| @@ -672,6 +681,11 @@ Object* StandardFrame::GetParameter(int index) const {
|
|
|
| int StandardFrame::ComputeParametersCount() const { return 0; }
|
|
|
| +void StandardFrame::Summarize(List<FrameSummary>* frames,
|
| + FrameSummary::Mode mode) const {
|
| + // Default implementation: no frames.
|
| +}
|
| +
|
| void StandardFrame::ComputeCallerState(State* state) const {
|
| state->sp = caller_sp();
|
| state->fp = caller_fp();
|
| @@ -719,7 +733,8 @@ void StandardFrame::IterateCompiledFrame(ObjectVisitor* v) const {
|
| case CONSTRUCT:
|
| case JS_TO_WASM:
|
| case WASM_TO_JS:
|
| - case WASM:
|
| + case WASM_COMPILED:
|
| + case WASM_INTERPRETED:
|
| frame_header_size = TypedFrameConstants::kFixedFrameSizeFromFp;
|
| break;
|
| case JAVA_SCRIPT:
|
| @@ -913,6 +928,16 @@ Object* JavaScriptFrame::context() const {
|
| return maybe_result;
|
| }
|
|
|
| +Object* JavaScriptFrame::debug_info(bool create) const {
|
| + Handle<JSFunction> fun(function(), isolate());
|
| + Handle<SharedFunctionInfo> shared(fun->shared(), isolate());
|
| + if (!create && !shared->HasDebugInfo()) {
|
| + return *isolate()->factory()->undefined_value();
|
| + }
|
| + if (create) isolate()->debug()->EnsureDebugInfo(shared, fun);
|
| + return shared->GetDebugInfo();
|
| +}
|
| +
|
| int JavaScriptFrame::LookupExceptionHandlerInTable(
|
| int* stack_depth, HandlerTable::CatchPrediction* prediction) {
|
| Code* code = LookupCode();
|
| @@ -1013,39 +1038,84 @@ FrameSummary::FrameSummary(Object* receiver, JSFunction* function,
|
| AbstractCode* abstract_code, int code_offset,
|
| bool is_constructor, Mode mode)
|
| : receiver_(receiver, function->GetIsolate()),
|
| - function_(function),
|
| + function_(function, function->GetIsolate()),
|
| abstract_code_(abstract_code),
|
| code_offset_(code_offset),
|
| - is_constructor_(is_constructor) {
|
| + flags(is_constructor ? kIsConstructor : kNone) {
|
| DCHECK(abstract_code->IsBytecodeArray() ||
|
| Code::cast(abstract_code)->kind() != Code::OPTIMIZED_FUNCTION ||
|
| CannotDeoptFromAsmCode(Code::cast(abstract_code), function) ||
|
| mode == kApproximateSummary);
|
| }
|
|
|
| -FrameSummary FrameSummary::GetFirst(JavaScriptFrame* frame) {
|
| +FrameSummary::FrameSummary(Object* wasm_object, int func_index,
|
| + AbstractCode* abstract_code, int code_offset,
|
| + Mode mode)
|
| + : receiver_(wasm_object, abstract_code->GetIsolate()),
|
| + function_(Smi::FromInt(func_index), abstract_code->GetIsolate()),
|
| + abstract_code_(abstract_code),
|
| + code_offset_(code_offset),
|
| + flags(kIsWasm) {
|
| + DCHECK(abstract_code->IsCode() &&
|
| + abstract_code->GetCode()->kind() == Code::WASM_FUNCTION);
|
| +}
|
| +
|
| +FrameSummary FrameSummary::GetFirst(StandardFrame* frame) {
|
| List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
|
| frame->Summarize(&frames);
|
| return frames.first();
|
| }
|
|
|
| +FrameSummary FrameSummary::GetLast(StandardFrame* frame) {
|
| + List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
|
| + frame->Summarize(&frames);
|
| + return frames.last();
|
| +}
|
| +
|
| +Script* FrameSummary::script() {
|
| + if (is_javascript()) return Script::cast(function()->shared()->script());
|
| + // In testing, we sometimes don't have a wasm object.
|
| + if (!wasm_object()->IsJSObject()) return nullptr;
|
| + Handle<wasm::WasmDebugInfo> debug_info(
|
| + wasm::GetDebugInfo(Handle<JSObject>::cast(wasm_object())));
|
| + return wasm::WasmDebugInfo::GetFunctionScript(debug_info,
|
| + wasm_function_index());
|
| +}
|
| +
|
| void FrameSummary::Print() {
|
| - PrintF("receiver: ");
|
| - receiver_->ShortPrint();
|
| - PrintF("\nfunction: ");
|
| - function_->shared()->DebugName()->ShortPrint();
|
| + if (is_javascript()) {
|
| + PrintF("receiver: ");
|
| + receiver()->ShortPrint();
|
| + PrintF("\nfunction: ");
|
| + function()->shared()->DebugName()->ShortPrint();
|
| + } else {
|
| + DCHECK(is_wasm());
|
| + PrintF("wasm object: ");
|
| + wasm_object()->ShortPrint();
|
| + PrintF("\nfunction index: %d", wasm_function_index());
|
| + }
|
| PrintF("\ncode: ");
|
| abstract_code_->ShortPrint();
|
| if (abstract_code_->IsCode()) {
|
| Code* code = abstract_code_->GetCode();
|
| - if (code->kind() == Code::FUNCTION) PrintF(" UNOPT ");
|
| - if (code->kind() == Code::OPTIMIZED_FUNCTION) {
|
| - if (function()->shared()->asm_function()) {
|
| - DCHECK(CannotDeoptFromAsmCode(code, *function()));
|
| - PrintF(" ASM ");
|
| - } else {
|
| - PrintF(" OPT (approximate)");
|
| - }
|
| + switch (code->kind()) {
|
| + case Code::FUNCTION:
|
| + PrintF(" UNOPT ");
|
| + break;
|
| + case Code::OPTIMIZED_FUNCTION:
|
| + if (function()->shared()->asm_function()) {
|
| + DCHECK(CannotDeoptFromAsmCode(code, *function()));
|
| + PrintF(" ASM ");
|
| + } else {
|
| + PrintF(" OPT (approximate)");
|
| + }
|
| + break;
|
| + case Code::WASM_FUNCTION:
|
| + PrintF(" WASM ");
|
| + break;
|
| + default:
|
| + PrintF("UNKNOWN");
|
| + break;
|
| }
|
| } else {
|
| PrintF(" BYTECODE ");
|
| @@ -1396,24 +1466,74 @@ Address WasmFrame::GetCallerStackPointer() const {
|
| return fp() + ExitFrameConstants::kCallerSPOffset;
|
| }
|
|
|
| -Object* WasmFrame::wasm_obj() const {
|
| +Object* WasmCompiledFrame::wasm_obj() const {
|
| FixedArray* deopt_data = LookupCode()->deoptimization_data();
|
| - DCHECK(deopt_data->length() == 2);
|
| + DCHECK_EQ(2, deopt_data->length());
|
| return deopt_data->get(0);
|
| }
|
|
|
| -uint32_t WasmFrame::function_index() const {
|
| +uint32_t WasmCompiledFrame::function_index() const {
|
| FixedArray* deopt_data = LookupCode()->deoptimization_data();
|
| - DCHECK(deopt_data->length() == 2);
|
| + DCHECK_EQ(2, deopt_data->length());
|
| return Smi::cast(deopt_data->get(1))->value();
|
| }
|
|
|
| -Script* WasmFrame::script() const {
|
| - JSObject* wasm = JSObject::cast(wasm_obj());
|
| +Script* WasmCompiledFrame::script() const {
|
| + Handle<JSObject> wasm(JSObject::cast(wasm_obj()), isolate());
|
| Handle<wasm::WasmDebugInfo> debug_info(wasm::GetDebugInfo(wasm), isolate());
|
| return wasm::WasmDebugInfo::GetFunctionScript(debug_info, function_index());
|
| }
|
|
|
| +Object* WasmCompiledFrame::debug_info(bool create) const {
|
| + Handle<JSObject> wasm(JSObject::cast(wasm_obj()), isolate());
|
| + Handle<wasm::WasmDebugInfo> debug_info(wasm::GetDebugInfo(wasm), isolate());
|
| + return wasm::WasmDebugInfo::GetDebugInfo(debug_info, function_index());
|
| +}
|
| +
|
| +void WasmCompiledFrame::Summarize(List<FrameSummary>* frames,
|
| + FrameSummary::Mode mode) const {
|
| + Code* code = LookupCode();
|
| + int offset = static_cast<int>(pc() - code->instruction_start());
|
| + // Check that we don't call this from testing, where we have no wasm object.
|
| + FrameSummary summary(wasm_obj(), function_index(), AbstractCode::cast(code),
|
| + offset, mode);
|
| + frames->Add(summary);
|
| +}
|
| +
|
| +Object* WasmInterpretedFrame::wasm_obj() const {
|
| + FixedArray* deopt_data = LookupCode()->deoptimization_data();
|
| + DCHECK_EQ(1, deopt_data->length());
|
| + return deopt_data->get(0);
|
| +}
|
| +
|
| +Object* WasmInterpretedFrame::debug_info(bool /* create */) const {
|
| + Handle<JSObject> wasm(JSObject::cast(wasm_obj()), isolate());
|
| + Handle<wasm::WasmDebugInfo> wasm_debug(wasm::GetDebugInfo(wasm), isolate());
|
| + // Get the top-most function index.
|
| + auto it = wasm_debug->GetInterpreterFrameIterator();
|
| + while (it.Remaining() > 0) it.Next();
|
| + int func_index = it.GetFrameInfo().func_index();
|
| + return wasm_debug->GetDebugInfo(wasm_debug, func_index);
|
| +}
|
| +
|
| +void WasmInterpretedFrame::Summarize(List<FrameSummary>* frames,
|
| + FrameSummary::Mode mode) const {
|
| + Handle<JSObject> wasm(JSObject::cast(wasm_obj()), isolate());
|
| + Handle<wasm::WasmDebugInfo> debug_info(wasm::GetDebugInfo(wasm), isolate());
|
| + wasm::InterpreterFrameIterator frame_it =
|
| + debug_info->GetInterpreterFrameIterator();
|
| +
|
| + while (!frame_it.Done()) {
|
| + wasm::InterpreterFrameInfo frame_info = frame_it.GetFrameInfo();
|
| + AbstractCode* code = AbstractCode::cast(
|
| + wasm::GetWasmFunctionCode(*wasm, frame_info.func_index()));
|
| + FrameSummary summ(*wasm, frame_info.func_index(), code,
|
| + frame_info.pc_offset());
|
| + frames->Add(summ);
|
| + frame_it.Next();
|
| + }
|
| +}
|
| +
|
| namespace {
|
|
|
|
|
|
|