Commit 81700ddf authored by clemensh's avatar clemensh Committed by Commit bot

[wasm] Introduce WasmToInterpreterFrame

and rename WasmFrame to WasmCompiledFrame.
The WasmToInterpreterFrames are not used yet; this will follow in a
follow-up CL (see tracking bug for the overall picture).
Those frames will represent frames for WASM_TO_INTERPRETER stubs, which
call from wasm code to the wasm interpreter, implemented in C++.
They will support the Summarize method to inspect the stack frames in
the wasm interpreter.

R=yangguo@chromium.org, titzer@chromium.org
BUG=v8:5822

Review-Url: https://codereview.chromium.org/2623773004
Cr-Commit-Position: refs/heads/master@{#42213}
parent 7ef86f80
......@@ -2666,7 +2666,7 @@ void MacroAssembler::EnterFrame(StackFrame::Type type) {
// jssp[3] : fp
// jssp[1] : type
// jssp[0] : [code object]
} else if (type == StackFrame::WASM) {
} else if (type == StackFrame::WASM_COMPILED) {
DCHECK(csp.Is(StackPointer()));
Mov(type_reg, Smi::FromInt(type));
Push(xzr, lr);
......
......@@ -166,11 +166,13 @@ StackFrame::Type CompilationInfo::GetOutputStackFrameType() const {
#undef CASE_KIND
return StackFrame::STUB;
case Code::WASM_FUNCTION:
return StackFrame::WASM;
return StackFrame::WASM_COMPILED;
case Code::JS_TO_WASM_FUNCTION:
return StackFrame::JS_TO_WASM;
case Code::WASM_TO_JS_FUNCTION:
return StackFrame::WASM_TO_JS;
case Code::WASM_INTERPRETER_ENTRY:
return StackFrame::WASM_INTERPRETER_ENTRY;
default:
UNIMPLEMENTED();
return StackFrame::NONE;
......
......@@ -1713,7 +1713,7 @@ void CodeGenerator::AssembleArchTrap(Instruction* instr,
bool old_has_frame = __ has_frame();
if (frame_elided_) {
__ set_has_frame(true);
__ EnterFrame(StackFrame::WASM);
__ EnterFrame(StackFrame::WASM_COMPILED);
}
GenerateCallToTrap(trap_id);
if (frame_elided_) {
......
......@@ -1717,7 +1717,7 @@ void CodeGenerator::AssembleArchTrap(Instruction* instr,
bool old_has_frame = __ has_frame();
if (frame_elided_) {
__ set_has_frame(true);
__ EnterFrame(StackFrame::WASM);
__ EnterFrame(StackFrame::WASM_COMPILED);
}
GenerateCallToTrap(trap_id);
if (frame_elided_) {
......
......@@ -1693,7 +1693,7 @@ void CodeGenerator::AssembleArchTrap(Instruction* instr,
bool old_has_frame = __ has_frame();
if (frame_elided_) {
__ set_has_frame(true);
__ EnterFrame(StackFrame::WASM);
__ EnterFrame(StackFrame::WASM_COMPILED);
}
GenerateCallToTrap(trap_id);
if (frame_elided_) {
......
......@@ -285,7 +285,7 @@ class WasmOutOfLineTrap final : public OutOfLineCode {
gen_->AddProtectedInstruction(pc_, current_pc);
if (frame_elided_) {
__ EnterFrame(StackFrame::WASM);
__ EnterFrame(StackFrame::WASM_COMPILED);
}
wasm::TrapReason trap_id = wasm::kTrapMemOutOfBounds;
......@@ -2321,7 +2321,7 @@ void CodeGenerator::AssembleArchTrap(Instruction* instr,
bool old_has_frame = __ has_frame();
if (frame_elided_) {
__ set_has_frame(true);
__ EnterFrame(StackFrame::WASM);
__ EnterFrame(StackFrame::WASM_COMPILED);
}
GenerateCallToTrap(trap_id);
if (frame_elided_) {
......
......@@ -33,7 +33,9 @@ class FrameInspector {
return frame_->is_arguments_adaptor() ? ArgumentsAdaptorFrame::cast(frame_)
: JavaScriptFrame::cast(frame_);
}
inline WasmFrame* wasm_frame() { return WasmFrame::cast(frame_); }
inline WasmCompiledFrame* wasm_frame() {
return WasmCompiledFrame::cast(frame_);
}
JavaScriptFrame* GetArgumentsFrame() { return javascript_frame(); }
void SetArgumentsFrame(StandardFrame* frame);
......
......@@ -252,7 +252,11 @@ inline ArgumentsAdaptorFrame::ArgumentsAdaptorFrame(
inline BuiltinFrame::BuiltinFrame(StackFrameIteratorBase* iterator)
: JavaScriptFrame(iterator) {}
inline WasmFrame::WasmFrame(StackFrameIteratorBase* iterator)
inline WasmCompiledFrame::WasmCompiledFrame(StackFrameIteratorBase* iterator)
: StandardFrame(iterator) {}
inline WasmInterpreterEntryFrame::WasmInterpreterEntryFrame(
StackFrameIteratorBase* iterator)
: StandardFrame(iterator) {}
inline WasmToJsFrame::WasmToJsFrame(StackFrameIteratorBase* iterator)
......@@ -311,13 +315,11 @@ bool StackTraceFrameIterator::is_javascript() const {
bool StackTraceFrameIterator::is_wasm() const { return frame()->is_wasm(); }
JavaScriptFrame* StackTraceFrameIterator::javascript_frame() const {
DCHECK(is_javascript());
return static_cast<JavaScriptFrame*>(frame());
return JavaScriptFrame::cast(frame());
}
WasmFrame* StackTraceFrameIterator::wasm_frame() const {
DCHECK(is_wasm());
return static_cast<WasmFrame*>(frame());
WasmCompiledFrame* StackTraceFrameIterator::wasm_compiled_frame() const {
return WasmCompiledFrame::cast(frame());
}
inline StackFrame* SafeStackFrameIterator::frame() const {
......
......@@ -468,11 +468,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_INTERPRETER_ENTRY:
return WASM_INTERPRETER_ENTRY;
default:
// All other types should have an explicit marker
break;
......@@ -496,7 +498,7 @@ StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator,
case CONSTRUCT:
case ARGUMENTS_ADAPTOR:
case WASM_TO_JS:
case WASM:
case WASM_COMPILED:
return candidate;
case JS_TO_WASM:
case JAVA_SCRIPT:
......@@ -760,6 +762,12 @@ void StandardFrame::SetCallerFp(Address caller_fp) {
bool StandardFrame::IsConstructor() const { return false; }
void StandardFrame::Summarize(List<FrameSummary>* functions,
FrameSummary::Mode mode) const {
// This should only be called on frames which override this method.
UNREACHABLE();
}
void StandardFrame::IterateCompiledFrame(ObjectVisitor* v) const {
// Make sure that we're not doing "safe" stack frame iteration. We cannot
// possibly find pointers in optimized frames in that state.
......@@ -791,7 +799,8 @@ void StandardFrame::IterateCompiledFrame(ObjectVisitor* v) const {
case CONSTRUCT:
case JS_TO_WASM:
case WASM_TO_JS:
case WASM:
case WASM_COMPILED:
case WASM_INTERPRETER_ENTRY:
frame_header_size = TypedFrameConstants::kFixedFrameSizeFromFp;
break;
case JAVA_SCRIPT:
......@@ -973,10 +982,6 @@ JSFunction* JavaScriptFrame::function() const {
Object* JavaScriptFrame::receiver() const { return GetParameter(-1); }
Script* JavaScriptFrame::script() const {
return Script::cast(function()->shared()->script());
}
Object* JavaScriptFrame::context() const {
const int offset = StandardFrameConstants::kContextOffset;
Object* maybe_result = Memory::Object_at(fp() + offset);
......@@ -984,6 +989,10 @@ Object* JavaScriptFrame::context() const {
return maybe_result;
}
Script* JavaScriptFrame::script() const {
return Script::cast(function()->shared()->script());
}
int JavaScriptFrame::LookupExceptionHandlerInTable(
int* stack_depth, HandlerTable::CatchPrediction* prediction) {
DCHECK_EQ(0, LookupCode()->handler_table()->length());
......@@ -1134,7 +1143,7 @@ FrameSummary::FrameSummary(Object* receiver, JSFunction* function,
mode == kApproximateSummary);
}
FrameSummary FrameSummary::GetFirst(JavaScriptFrame* frame) {
FrameSummary FrameSummary::GetFirst(StandardFrame* frame) {
List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
frame->Summarize(&frames);
return frames.first();
......@@ -1522,8 +1531,8 @@ void StackFrame::PrintIndex(StringStream* accumulator,
accumulator->Add((mode == OVERVIEW) ? "%5d: " : "[%d]: ", index);
}
void WasmFrame::Print(StringStream* accumulator, PrintMode mode,
int index) const {
void WasmCompiledFrame::Print(StringStream* accumulator, PrintMode mode,
int index) const {
PrintIndex(accumulator, mode, index);
accumulator->Add("WASM [");
Script* script = this->script();
......@@ -1543,35 +1552,36 @@ void WasmFrame::Print(StringStream* accumulator, PrintMode mode,
if (mode != OVERVIEW) accumulator->Add("\n");
}
Code* WasmFrame::unchecked_code() const {
return static_cast<Code*>(isolate()->FindCodeObject(pc()));
Code* WasmCompiledFrame::unchecked_code() const {
return isolate()->FindCodeObject(pc());
}
void WasmFrame::Iterate(ObjectVisitor* v) const { IterateCompiledFrame(v); }
void WasmCompiledFrame::Iterate(ObjectVisitor* v) const {
IterateCompiledFrame(v);
}
Address WasmFrame::GetCallerStackPointer() const {
Address WasmCompiledFrame::GetCallerStackPointer() const {
return fp() + ExitFrameConstants::kCallerSPOffset;
}
WasmInstanceObject* WasmFrame::wasm_instance() const {
WasmInstanceObject* WasmCompiledFrame::wasm_instance() const {
WasmInstanceObject* obj = wasm::GetOwningWasmInstance(LookupCode());
// This is a live stack frame; it must have a live instance.
DCHECK_NOT_NULL(obj);
return obj;
}
uint32_t WasmFrame::function_index() const {
uint32_t WasmCompiledFrame::function_index() const {
FixedArray* deopt_data = LookupCode()->deoptimization_data();
DCHECK(deopt_data->length() == 2);
return Smi::cast(deopt_data->get(1))->value();
}
Script* WasmFrame::script() const {
Handle<JSObject> instance(JSObject::cast(wasm_instance()), isolate());
return *wasm::GetScript(instance);
Script* WasmCompiledFrame::script() const {
return wasm_instance()->compiled_module()->script();
}
int WasmFrame::position() const {
int WasmCompiledFrame::position() const {
int position = StandardFrame::position();
if (wasm_instance()->compiled_module()->is_asm_js()) {
Handle<WasmCompiledModule> compiled_module(
......@@ -1585,7 +1595,12 @@ int WasmFrame::position() const {
return position;
}
bool WasmFrame::at_to_number_conversion() const {
void WasmCompiledFrame::Summarize(List<FrameSummary>* functions,
FrameSummary::Mode mode) const {
// TODO(clemensh): Implement.
}
bool WasmCompiledFrame::at_to_number_conversion() const {
// Check whether our callee is a WASM_TO_JS frame, and this frame is at the
// ToNumber conversion call.
Address callee_pc = reinterpret_cast<Address>(this->callee_pc());
......@@ -1598,7 +1613,7 @@ bool WasmFrame::at_to_number_conversion() const {
return !!pos;
}
int WasmFrame::LookupExceptionHandlerInTable(int* stack_slots) {
int WasmCompiledFrame::LookupExceptionHandlerInTable(int* stack_slots) {
DCHECK_NOT_NULL(stack_slots);
Code* code = LookupCode();
HandlerTable* table = HandlerTable::cast(code->handler_table());
......@@ -1607,6 +1622,49 @@ int WasmFrame::LookupExceptionHandlerInTable(int* stack_slots) {
return table->LookupReturn(pc_offset);
}
void WasmInterpreterEntryFrame::Iterate(ObjectVisitor* v) const {
IterateCompiledFrame(v);
}
void WasmInterpreterEntryFrame::Print(StringStream* accumulator, PrintMode mode,
int index) const {
PrintIndex(accumulator, mode, index);
accumulator->Add("WASM TO INTERPRETER [");
Script* script = this->script();
accumulator->PrintName(script->name());
accumulator->Add("]");
if (mode != OVERVIEW) accumulator->Add("\n");
}
void WasmInterpreterEntryFrame::Summarize(List<FrameSummary>* functions,
FrameSummary::Mode mode) const {
// TODO(clemensh): Implement this.
}
Code* WasmInterpreterEntryFrame::unchecked_code() const {
return isolate()->FindCodeObject(pc());
}
WasmInstanceObject* WasmInterpreterEntryFrame::wasm_instance() const {
WasmInstanceObject* ret = wasm::GetOwningWasmInstance(LookupCode());
// This is a live stack frame, there must be a live wasm instance available.
DCHECK_NOT_NULL(ret);
return ret;
}
Script* WasmInterpreterEntryFrame::script() const {
return wasm_instance()->compiled_module()->script();
}
int WasmInterpreterEntryFrame::position() const {
// TODO(clemensh): Implement this.
return 0;
}
Address WasmInterpreterEntryFrame::GetCallerStackPointer() const {
return fp() + ExitFrameConstants::kCallerSPOffset;
}
namespace {
......
......@@ -97,9 +97,10 @@ class StackHandler BASE_EMBEDDED {
V(EXIT, ExitFrame) \
V(JAVA_SCRIPT, JavaScriptFrame) \
V(OPTIMIZED, OptimizedFrame) \
V(WASM, WasmFrame) \
V(WASM_COMPILED, WasmCompiledFrame) \
V(WASM_TO_JS, WasmToJsFrame) \
V(JS_TO_WASM, JsToWasmFrame) \
V(WASM_INTERPRETER_ENTRY, WasmInterpreterEntryFrame) \
V(INTERPRETED, InterpretedFrame) \
V(STUB, StubFrame) \
V(STUB_FAILURE_TRAMPOLINE, StubFailureTrampolineFrame) \
......@@ -463,9 +464,12 @@ class StackFrame BASE_EMBEDDED {
bool is_exit() const { return type() == EXIT; }
bool is_optimized() const { return type() == OPTIMIZED; }
bool is_interpreted() const { return type() == INTERPRETED; }
bool is_wasm() const { return type() == WASM; }
bool is_wasm_compiled() const { return type() == WASM_COMPILED; }
bool is_wasm_to_js() const { return type() == WASM_TO_JS; }
bool is_js_to_wasm() const { return type() == JS_TO_WASM; }
bool is_wasm_interpreter_entry() const {
return type() == WASM_INTERPRETER_ENTRY;
}
bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
bool is_builtin() const { return type() == BUILTIN; }
bool is_internal() const { return type() == INTERNAL; }
......@@ -481,6 +485,10 @@ class StackFrame BASE_EMBEDDED {
return (type == JAVA_SCRIPT) || (type == OPTIMIZED) ||
(type == INTERPRETED) || (type == BUILTIN);
}
bool is_wasm() const {
Type type = this->type();
return type == WASM_COMPILED || type == WASM_INTERPRETER_ENTRY;
}
// Accessors.
Address sp() const { return state_.sp; }
......@@ -729,7 +737,7 @@ class BuiltinExitFrame : public ExitFrame {
friend class StackFrameIteratorBase;
};
class JavaScriptFrame;
class StandardFrame;
class FrameSummary BASE_EMBEDDED {
public:
......@@ -744,7 +752,7 @@ class FrameSummary BASE_EMBEDDED {
AbstractCode* abstract_code, int code_offset,
bool is_constructor, Mode mode = kExactSummary);
static FrameSummary GetFirst(JavaScriptFrame* frame);
static FrameSummary GetFirst(StandardFrame* frame);
Handle<Object> receiver() const { return receiver_; }
Handle<JSFunction> function() const { return function_; }
......@@ -787,6 +795,11 @@ class StandardFrame : public StackFrame {
// Check if this frame is a constructor frame invoked through 'new'.
virtual bool IsConstructor() const;
// Build a list with summaries for this frame including all inlined frames.
virtual void Summarize(
List<FrameSummary>* frames,
FrameSummary::Mode mode = FrameSummary::kExactSummary) const;
static StandardFrame* cast(StackFrame* frame) {
DCHECK(frame->is_standard());
return static_cast<StandardFrame*>(frame);
......@@ -836,10 +849,9 @@ class JavaScriptFrame : public StandardFrame {
public:
Type type() const override { return JAVA_SCRIPT; }
// Build a list with summaries for this frame including all inlined frames.
virtual void Summarize(
void Summarize(
List<FrameSummary>* frames,
FrameSummary::Mode mode = FrameSummary::kExactSummary) const;
FrameSummary::Mode mode = FrameSummary::kExactSummary) const override;
// Accessors.
virtual JSFunction* function() const;
......@@ -1091,9 +1103,9 @@ class BuiltinFrame final : public JavaScriptFrame {
friend class StackFrameIteratorBase;
};
class WasmFrame : public StandardFrame {
class WasmCompiledFrame : public StandardFrame {
public:
Type type() const override { return WASM; }
Type type() const override { return WASM_COMPILED; }
// GC support.
void Iterate(ObjectVisitor* v) const override;
......@@ -1116,13 +1128,53 @@ class WasmFrame : public StandardFrame {
int position() const override;
bool at_to_number_conversion() const;
static WasmFrame* cast(StackFrame* frame) {
DCHECK(frame->is_wasm());
return static_cast<WasmFrame*>(frame);
void Summarize(List<FrameSummary>* frames,
FrameSummary::Mode mode) const override;
static WasmCompiledFrame* cast(StackFrame* frame) {
DCHECK(frame->is_wasm_compiled());
return static_cast<WasmCompiledFrame*>(frame);
}
protected:
inline explicit WasmCompiledFrame(StackFrameIteratorBase* iterator);
Address GetCallerStackPointer() const override;
private:
friend class StackFrameIteratorBase;
};
class WasmInterpreterEntryFrame : public StandardFrame {
public:
Type type() const override { return WASM_INTERPRETER_ENTRY; }
// GC support.
void Iterate(ObjectVisitor* v) const override;
// Printing support.
void Print(StringStream* accumulator, PrintMode mode,
int index) const override;
void Summarize(
List<FrameSummary>* frames,
FrameSummary::Mode mode = FrameSummary::kExactSummary) const override;
// Determine the code for the frame.
Code* unchecked_code() const override;
// Accessors.
WasmInstanceObject* wasm_instance() const;
Script* script() const override;
int position() const override;
static WasmInterpreterEntryFrame* cast(StackFrame* frame) {
DCHECK(frame->is_wasm_interpreter_entry());
return static_cast<WasmInterpreterEntryFrame*>(frame);
}
protected:
inline explicit WasmFrame(StackFrameIteratorBase* iterator);
inline explicit WasmInterpreterEntryFrame(StackFrameIteratorBase* iterator);
Address GetCallerStackPointer() const override;
......@@ -1313,7 +1365,9 @@ class StackTraceFrameIterator BASE_EMBEDDED {
inline bool is_javascript() const;
inline bool is_wasm() const;
inline JavaScriptFrame* javascript_frame() const;
inline WasmFrame* wasm_frame() const;
// TODO(clemensh): Remove / refactor this for general wasm frames
// (compiled/interpreted).
inline WasmCompiledFrame* wasm_compiled_frame() const;
// Advance to the frame holding the arguments for the current
// frame. This only affects the current frame if it is a javascript frame and
......
......@@ -510,8 +510,8 @@ Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSReceiver> error_object,
offset, flags);
} break;
case StackFrame::WASM: {
WasmFrame* wasm_frame = WasmFrame::cast(frame);
case StackFrame::WASM_COMPILED: {
WasmCompiledFrame* wasm_frame = WasmCompiledFrame::cast(frame);
Handle<WasmInstanceObject> instance(wasm_frame->wasm_instance(), this);
const int wasm_function_index = wasm_frame->function_index();
Code* code = wasm_frame->unchecked_code();
......@@ -534,6 +534,10 @@ Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSReceiver> error_object,
abstract_code, offset, flags);
} break;
case StackFrame::WASM_INTERPRETER_ENTRY:
// TODO(clemensh): Add frames.
break;
default:
break;
}
......@@ -699,7 +703,7 @@ class CaptureStackTraceHelper {
return stack_frame;
}
Handle<JSObject> NewStackFrameObject(WasmFrame* frame) {
Handle<JSObject> NewStackFrameObject(WasmCompiledFrame* frame) {
Handle<JSObject> stack_frame =
factory()->NewJSObject(isolate_->object_function());
......@@ -783,7 +787,7 @@ Handle<JSArray> Isolate::CaptureCurrentStackTrace(
}
} else {
DCHECK(frame->is_wasm());
WasmFrame* wasm_frame = WasmFrame::cast(frame);
WasmCompiledFrame* wasm_frame = WasmCompiledFrame::cast(frame);
Handle<JSObject> new_frame_obj = helper.NewStackFrameObject(wasm_frame);
stack_trace_elems->set(frames_seen, *new_frame_obj);
frames_seen++;
......@@ -1220,7 +1224,7 @@ Object* Isolate::UnwindAndFindHandler() {
if (FLAG_wasm_eh_prototype) {
if (frame->is_wasm() && is_catchable_by_wasm(exception)) {
int stack_slots = 0; // Will contain stack slot count of frame.
WasmFrame* wasm_frame = static_cast<WasmFrame*>(frame);
WasmCompiledFrame* wasm_frame = static_cast<WasmCompiledFrame*>(frame);
offset = wasm_frame->LookupExceptionHandlerInTable(&stack_slots);
if (offset >= 0) {
// Compute the stack pointer from the frame pointer. This ensures that
......@@ -1309,6 +1313,9 @@ Object* Isolate::UnwindAndFindHandler() {
CHECK_EQ(-1, offset);
}
// TODO(clemensh): Handle unwinding interpreted wasm frames (stored in the
// WasmInterpreter C++ object).
RemoveMaterializedObjectsOnUnwind(frame);
}
......
......@@ -1482,6 +1482,10 @@ void Logger::LogCodeObject(Object* object) {
description = "A Wasm to JavaScript adapter";
tag = CodeEventListener::STUB_TAG;
break;
case AbstractCode::WASM_INTERPRETER_ENTRY:
description = "A Wasm to Interpreter adapter";
tag = CodeEventListener::STUB_TAG;
break;
case AbstractCode::NUMBER_OF_KINDS:
UNIMPLEMENTED();
}
......
......@@ -5064,7 +5064,8 @@ class Code: public HeapObject {
V(REGEXP) \
V(WASM_FUNCTION) \
V(WASM_TO_JS_FUNCTION) \
V(JS_TO_WASM_FUNCTION)
V(JS_TO_WASM_FUNCTION) \
V(WASM_INTERPRETER_ENTRY)
#define IC_KIND_LIST(V) \
V(LOAD_IC) \
......
......@@ -526,8 +526,8 @@ RUNTIME_FUNCTION(Runtime_GetFrameDetails) {
// Add the function name.
Handle<WasmCompiledModule> compiled_module(
it.wasm_frame()->wasm_instance()->compiled_module(), isolate);
int func_index = it.wasm_frame()->function_index();
it.wasm_compiled_frame()->wasm_instance()->compiled_module(), isolate);
int func_index = it.wasm_compiled_frame()->function_index();
Handle<String> func_name = WasmCompiledModule::GetFunctionName(
isolate, compiled_module, func_index);
details->set(kFrameDetailsFunctionIndex, *func_name);
......
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