Source code

Revision control

Other Tools

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sts=2 et sw=2 tw=80:
*
* Copyright 2016 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef wasm_debug_h
#define wasm_debug_h
#include "js/HashTable.h"
#include "wasm/WasmModule.h"
#include "wasm/WasmTypes.h"
namespace js {
class Debugger;
class WasmBreakpointSite;
class WasmInstanceObject;
namespace wasm {
struct MetadataTier;
// The generated source location for the AST node/expression. The offset field
// refers an offset in an binary format file.
struct ExprLoc {
uint32_t lineno;
uint32_t column;
uint32_t offset;
ExprLoc() : lineno(0), column(0), offset(0) {}
ExprLoc(uint32_t lineno_, uint32_t column_, uint32_t offset_)
: lineno(lineno_), column(column_), offset(offset_) {}
};
typedef HashMap<uint32_t, uint32_t, DefaultHasher<uint32_t>, SystemAllocPolicy>
StepperCounters;
typedef HashMap<uint32_t, WasmBreakpointSite*, DefaultHasher<uint32_t>,
SystemAllocPolicy>
WasmBreakpointSiteMap;
class DebugState {
const SharedCode code_;
const SharedModule module_;
// State maintained when debugging is enabled. In this case, the Code is
// not actually shared, but is referenced uniquely by the instance that is
// being debugged.
bool enterFrameTrapsEnabled_;
uint32_t enterAndLeaveFrameTrapsCounter_;
WasmBreakpointSiteMap breakpointSites_;
StepperCounters stepperCounters_;
void toggleDebugTrap(uint32_t offset, bool enabled);
public:
DebugState(const Code& code, const Module& module);
void trace(JSTracer* trc);
void finalize(JSFreeOp* fop);
const Bytes& bytecode() const { return module_->debugBytecode(); }
MOZ_MUST_USE bool getLineOffsets(size_t lineno, Vector<uint32_t>* offsets);
MOZ_MUST_USE bool getAllColumnOffsets(Vector<ExprLoc>* offsets);
MOZ_MUST_USE bool getOffsetLocation(uint32_t offset, size_t* lineno,
size_t* column);
// The Code can track enter/leave frame events. Any such event triggers
// debug trap. The enter/leave frame events enabled or disabled across
// all functions.
void adjustEnterAndLeaveFrameTrapsState(JSContext* cx, bool enabled);
void ensureEnterFrameTrapsState(JSContext* cx, bool enabled);
bool enterFrameTrapsEnabled() const { return enterFrameTrapsEnabled_; }
// When the Code is debugEnabled, individual breakpoints can be enabled or
// disabled at instruction offsets.
bool hasBreakpointTrapAtOffset(uint32_t offset);
void toggleBreakpointTrap(JSRuntime* rt, uint32_t offset, bool enabled);
WasmBreakpointSite* getBreakpointSite(uint32_t offset) const;
WasmBreakpointSite* getOrCreateBreakpointSite(JSContext* cx,
Instance* instance,
uint32_t offset);
bool hasBreakpointSite(uint32_t offset);
void destroyBreakpointSite(JSFreeOp* fop, Instance* instance,
uint32_t offset);
void clearBreakpointsIn(JSFreeOp* fp, WasmInstanceObject* instance,
js::Debugger* dbg, JSObject* handler);
void clearAllBreakpoints(JSFreeOp* fp, WasmInstanceObject* instance);
// When the Code is debug-enabled, single-stepping mode can be toggled on
// the granularity of individual functions.
bool stepModeEnabled(uint32_t funcIndex) const;
MOZ_MUST_USE bool incrementStepperCount(JSContext* cx, uint32_t funcIndex);
void decrementStepperCount(JSFreeOp* fop, uint32_t funcIndex);
// Stack inspection helpers.
MOZ_MUST_USE bool debugGetLocalTypes(uint32_t funcIndex,
ValTypeVector* locals,
size_t* argsLength,
StackResults* stackResults);
// Invariant: the result of getDebugResultType can only be used as long as
// code_->metadata() is live. See MetaData::getFuncResultType for more
// information.
ResultType debugGetResultType(uint32_t funcIndex) const {
return metadata().getFuncResultType(funcIndex);
}
MOZ_MUST_USE bool getGlobal(Instance& instance, uint32_t globalIndex,
MutableHandleValue vp);
// Debug URL helpers.
MOZ_MUST_USE bool getSourceMappingURL(JSContext* cx,
MutableHandleString result) const;
// Accessors for commonly used elements of linked structures.
const MetadataTier& metadata(Tier t) const { return code_->metadata(t); }
const Metadata& metadata() const { return code_->metadata(); }
const CodeRangeVector& codeRanges(Tier t) const {
return metadata(t).codeRanges;
}
const CallSiteVector& callSites(Tier t) const {
return metadata(t).callSites;
}
uint32_t funcToCodeRangeIndex(uint32_t funcIndex) const {
return metadata(Tier::Debug).funcToCodeRange[funcIndex];
}
// about:memory reporting:
void addSizeOfMisc(MallocSizeOf mallocSizeOf, Metadata::SeenSet* seenMetadata,
Code::SeenSet* seenCode, size_t* code, size_t* data) const;
};
using UniqueDebugState = UniquePtr<DebugState>;
} // namespace wasm
} // namespace js
#endif // wasm_debug_h