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 { |