--- a/js/src/asmjs/WasmBinaryToExperimentalText.cpp
+++ b/js/src/asmjs/WasmBinaryToExperimentalText.cpp
@@ -54,74 +54,16 @@ enum PrintOperatorPrecedence
NegatePrecedence = 12,
EqzPrecedence = 12,
OperatorPrecedence = 15,
LoadOperatorPrecedence = 15,
CallPrecedence = 15,
GroupPrecedence = 16,
};
-// StringBuffer wrapper to track the position (line and column) within the generated
-// source.
-class WasmPrintBuffer
-{
- StringBuffer& stringBuffer_;
- uint32_t lineno_;
- uint32_t column_;
-
- public:
- explicit WasmPrintBuffer(StringBuffer& stringBuffer) : stringBuffer_(stringBuffer), lineno_(1), column_(1) {}
- inline char processChar(char ch) {
- if (ch == '\n') {
- lineno_++; column_ = 1;
- } else
- column_++;
- return ch;
- }
- inline char16_t processChar(char16_t ch) {
- if (ch == '\n') {
- lineno_++; column_ = 1;
- } else
- column_++;
- return ch;
- }
- bool append(const char ch) {
- return stringBuffer_.append(processChar(ch));
- }
- bool append(const char16_t ch) {
- return stringBuffer_.append(processChar(ch));
- }
- bool append(const char* str, size_t length) {
- for (size_t i = 0; i < length; i++)
- processChar(str[i]);
- return stringBuffer_.append(str, length);
- }
- bool append(const char16_t* begin, const char16_t* end) {
- for (const char16_t* p = begin; p != end; p++)
- processChar(*p);
- return stringBuffer_.append(begin, end);
- }
- bool append(const char16_t* str, size_t length) {
- return append(str, str + length);
- }
- template <size_t ArrayLength>
- bool append(const char (&array)[ArrayLength]) {
- return append(array, ArrayLength - 1);
- }
- char16_t getChar(size_t index) {
- return stringBuffer_.getChar(index);
- }
- size_t length() {
- return stringBuffer_.length();
- }
- StringBuffer& stringBuffer() { return stringBuffer_; }
- uint32_t lineno() { return lineno_; }
- uint32_t column() { return column_; }
-};
-
struct WasmPrintContext
{
JSContext* cx;
AstModule* module;
WasmPrintBuffer& buffer;
const ExperimentalTextFormatting& f;
GeneratedSourceMap* maybeSourceMap;
uint32_t indent;
--- a/js/src/asmjs/WasmBinaryToExperimentalText.h
+++ b/js/src/asmjs/WasmBinaryToExperimentalText.h
@@ -14,20 +14,19 @@
* 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_binary_to_experimental_text_h
#define wasm_binary_to_experimental_text_h
-#include "mozilla/Vector.h"
-
#include "NamespaceImports.h"
+#include "asmjs/WasmGeneratedSourceMap.h"
#include "gc/Rooting.h"
#include "js/Class.h"
namespace js {
class StringBuffer;
namespace wasm {
@@ -40,69 +39,16 @@ struct ExperimentalTextFormatting
ExperimentalTextFormatting()
: allowAsciiOperators(true),
reduceParens(true),
groupBlocks(true)
{}
};
-// 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 mozilla::Vector<ExprLoc, 0, TempAllocPolicy> ExprLocVector;
-
-// The generated source WebAssembly function lines and expressions ranges.
-struct FunctionLoc
-{
- size_t startExprsIndex;
- size_t endExprsIndex;
- uint32_t startLineno;
- uint32_t endLineno;
- FunctionLoc(size_t startExprsIndex_, size_t endExprsIndex_, uint32_t startLineno_, uint32_t endLineno_)
- : startExprsIndex(startExprsIndex_),
- endExprsIndex(endExprsIndex_),
- startLineno(startLineno_),
- endLineno(endLineno_)
- {}
-};
-
-typedef mozilla::Vector<FunctionLoc, 0, TempAllocPolicy> FunctionLocVector;
-
-// The generated source map for WebAssembly binary file. This map is generated during
-// building the text buffer (see BinaryToExperimentalText).
-class GeneratedSourceMap
-{
- ExprLocVector exprlocs_;
- FunctionLocVector functionlocs_;
- uint32_t totalLines_;
-
- public:
- explicit GeneratedSourceMap(JSContext* cx)
- : exprlocs_(cx),
- functionlocs_(cx),
- totalLines_(0)
- {}
- ExprLocVector& exprlocs() { return exprlocs_; }
- FunctionLocVector& functionlocs() { return functionlocs_; }
-
- uint32_t totalLines() { return totalLines_; }
- void setTotalLines(uint32_t val) { totalLines_ = val; }
-};
-
-typedef UniquePtr<GeneratedSourceMap> UniqueGeneratedSourceMap;
-
// Translate the given binary representation of a wasm module into the module's textual
// representation.
MOZ_MUST_USE bool
BinaryToExperimentalText(JSContext* cx, const uint8_t* bytes, size_t length, StringBuffer& buffer,
const ExperimentalTextFormatting& formatting = ExperimentalTextFormatting(),
GeneratedSourceMap* sourceMap = nullptr);
--- a/js/src/asmjs/WasmBinaryToText.cpp
+++ b/js/src/asmjs/WasmBinaryToText.cpp
@@ -34,24 +34,27 @@ using namespace js::wasm;
using mozilla::IsInfinite;
using mozilla::IsNaN;
using mozilla::IsNegativeZero;
struct WasmRenderContext
{
JSContext* cx;
AstModule* module;
- StringBuffer& buffer;
+ WasmPrintBuffer& buffer;
+ GeneratedSourceMap* maybeSourceMap;
uint32_t indent;
uint32_t currentFuncIndex;
- WasmRenderContext(JSContext* cx, AstModule* module, StringBuffer& buffer)
- : cx(cx), module(module), buffer(buffer), indent(0), currentFuncIndex(0)
+ WasmRenderContext(JSContext* cx, AstModule* module, WasmPrintBuffer& buffer, GeneratedSourceMap* sourceMap)
+ : cx(cx), module(module), buffer(buffer), maybeSourceMap(sourceMap), indent(0), currentFuncIndex(0)
{}
+
+ StringBuffer& sb() { return buffer.stringBuffer(); }
};
/*****************************************************************************/
// utilities
static bool
RenderIndent(WasmRenderContext& c)
{
@@ -60,51 +63,51 @@ RenderIndent(WasmRenderContext& c)
return false;
}
return true;
}
static bool
RenderInt32(WasmRenderContext& c, int32_t num)
{
- return NumberValueToStringBuffer(c.cx, Int32Value(num), c.buffer);
+ return NumberValueToStringBuffer(c.cx, Int32Value(num), c.sb());
}
static bool
RenderInt64(WasmRenderContext& c, int64_t num)
{
if (num < 0 && !c.buffer.append("-"))
return false;
if (!num)
return c.buffer.append("0");
- return RenderInBase<10>(c.buffer, mozilla::Abs(num));
+ return RenderInBase<10>(c.sb(), mozilla::Abs(num));
}
static bool
RenderDouble(WasmRenderContext& c, RawF64 num)
{
double d = num.fp();
if (IsNaN(d))
- return RenderNaN(c.buffer, num);
+ return RenderNaN(c.sb(), num);
if (IsNegativeZero(d))
return c.buffer.append("-0");
if (IsInfinite(d)) {
if (d > 0)
return c.buffer.append("infinity");
return c.buffer.append("-infinity");
}
- return NumberValueToStringBuffer(c.cx, DoubleValue(d), c.buffer);
+ return NumberValueToStringBuffer(c.cx, DoubleValue(d), c.sb());
}
static bool
RenderFloat32(WasmRenderContext& c, RawF32 num)
{
float f = num.fp();
if (IsNaN(f))
- return RenderNaN(c.buffer, num);
+ return RenderNaN(c.sb(), num);
return RenderDouble(c, RawF64(double(f)));
}
static bool
RenderEscapedString(WasmRenderContext& c, const AstName& s)
{
size_t length = s.length();
const char16_t* p = s.begin();
@@ -218,45 +221,56 @@ RenderBlockNameAndSignature(WasmRenderCo
}
return true;
}
static bool
RenderExpr(WasmRenderContext& c, AstExpr& expr);
+#define MAP_AST_EXPR(c, expr) \
+ if (c.maybeSourceMap) { \
+ uint32_t lineno = c.buffer.lineno(); \
+ uint32_t column = c.buffer.column(); \
+ if (!c.maybeSourceMap->exprlocs().emplaceBack(lineno, column, expr.offset())) \
+ return false; \
+ }
+
/*****************************************************************************/
// binary format parsing and rendering
static bool
-RenderNop(WasmRenderContext& c)
+RenderNop(WasmRenderContext& c, AstNop& nop)
{
if (!RenderIndent(c))
return false;
+ MAP_AST_EXPR(c, nop);
return c.buffer.append("nop\n");
}
static bool
RenderDrop(WasmRenderContext& c, AstDrop& drop)
{
if (!RenderExpr(c, drop.value()))
return false;
if (!RenderIndent(c))
return false;
+ MAP_AST_EXPR(c, drop);
if (!c.buffer.append("drop\n"))
return false;
return true;
}
static bool
-RenderUnreachable(WasmRenderContext& c)
+RenderUnreachable(WasmRenderContext& c, AstUnreachable& unreachable)
{
if (!RenderIndent(c))
return false;
+ MAP_AST_EXPR(c, unreachable);
return c.buffer.append("unreachable\n");
}
static bool
RenderCallArgs(WasmRenderContext& c, const AstExprVector& args)
{
for (uint32_t i = 0; i < args.length(); i++) {
if (!RenderExpr(c, *args[i]))
@@ -270,16 +284,17 @@ static bool
RenderCall(WasmRenderContext& c, AstCall& call)
{
if (!RenderCallArgs(c, call.args()))
return false;
if (!RenderIndent(c))
return false;
+ MAP_AST_EXPR(c, call);
if (call.expr() == Expr::Call) {
if (!c.buffer.append("call "))
return false;
} else if (call.expr() == Expr::CallImport) {
if (!c.buffer.append("call_import "))
return false;
} else {
return false;
@@ -301,16 +316,17 @@ RenderCallIndirect(WasmRenderContext& c,
return false;
if (!RenderExpr(c, *call.index()))
return false;
if (!RenderIndent(c))
return false;
+ MAP_AST_EXPR(c, call);
if (!c.buffer.append("call_indirect "))
return false;
if (!RenderRef(c, call.sig()))
return false;
if (!c.buffer.append('\n'))
return false;
@@ -318,16 +334,17 @@ RenderCallIndirect(WasmRenderContext& c,
}
static bool
RenderConst(WasmRenderContext& c, AstConst& cst)
{
if (!RenderIndent(c))
return false;
+ MAP_AST_EXPR(c, cst);
if (!RenderValType(c, cst.val().type()))
return false;
if (!c.buffer.append(".const "))
return false;
switch (ToExprType(cst.val().type())) {
case ExprType::I32:
if (!RenderInt32(c, (uint32_t)cst.val().i32()))
@@ -355,16 +372,17 @@ RenderConst(WasmRenderContext& c, AstCon
}
static bool
RenderGetLocal(WasmRenderContext& c, AstGetLocal& gl)
{
if (!RenderIndent(c))
return false;
+ MAP_AST_EXPR(c, gl);
if (!c.buffer.append("get_local "))
return false;
if (!RenderRef(c, gl.local()))
return false;
if (!c.buffer.append('\n'))
return false;
return true;
}
@@ -373,16 +391,17 @@ static bool
RenderSetLocal(WasmRenderContext& c, AstSetLocal& sl)
{
if (!RenderExpr(c, sl.value()))
return false;
if (!RenderIndent(c))
return false;
+ MAP_AST_EXPR(c, sl);
if (!c.buffer.append("set_local "))
return false;
if (!RenderRef(c, sl.local()))
return false;
if (!c.buffer.append('\n'))
return false;
return true;
@@ -392,16 +411,17 @@ static bool
RenderTeeLocal(WasmRenderContext& c, AstTeeLocal& tl)
{
if (!RenderExpr(c, tl.value()))
return false;
if (!RenderIndent(c))
return false;
+ MAP_AST_EXPR(c, tl);
if (!c.buffer.append("tee_local "))
return false;
if (!RenderRef(c, tl.local()))
return false;
if (!c.buffer.append('\n'))
return false;
return true;
@@ -418,16 +438,17 @@ RenderExprList(WasmRenderContext& c, con
}
static bool
RenderBlock(WasmRenderContext& c, AstBlock& block)
{
if (!RenderIndent(c))
return false;
+ MAP_AST_EXPR(c, block);
if (block.expr() == Expr::Block) {
if (!c.buffer.append("block"))
return false;
} else if (block.expr() == Expr::Loop) {
if (!c.buffer.append("loop"))
return false;
} else
return false;
@@ -480,16 +501,17 @@ static bool
RenderUnaryOperator(WasmRenderContext& c, AstUnaryOperator& op)
{
if (!RenderExpr(c, *op.op()))
return false;
if (!RenderIndent(c))
return false;
+ MAP_AST_EXPR(c, op);
const char* opStr;
switch (op.expr()) {
case Expr::I32Eqz: opStr = "i32.eqz"; break;
case Expr::I32Clz: opStr = "i32.clz"; break;
case Expr::I32Ctz: opStr = "i32.ctz"; break;
case Expr::I32Popcnt: opStr = "i32.popcnt"; break;
case Expr::I64Clz: opStr = "i64.clz"; break;
case Expr::I64Ctz: opStr = "i64.ctz"; break;
@@ -521,16 +543,17 @@ RenderBinaryOperator(WasmRenderContext&
if (!RenderExpr(c, *op.lhs()))
return false;
if (!RenderExpr(c, *op.rhs()))
return false;
if (!RenderIndent(c))
return false;
+ MAP_AST_EXPR(c, op);
const char* opStr;
switch (op.expr()) {
case Expr::I32Add: opStr = "i32.add"; break;
case Expr::I32Sub: opStr = "i32.sub"; break;
case Expr::I32Mul: opStr = "i32.mul"; break;
case Expr::I32DivS: opStr = "i32.div_s"; break;
case Expr::I32DivU: opStr = "i32.div_u"; break;
case Expr::I32RemS: opStr = "i32.rem_s"; break;
@@ -586,16 +609,17 @@ RenderTernaryOperator(WasmRenderContext&
if (!RenderExpr(c, *op.op1()))
return false;
if (!RenderExpr(c, *op.op2()))
return false;
if (!RenderIndent(c))
return false;
+ MAP_AST_EXPR(c, op);
const char* opStr;
switch (op.expr()) {
case Expr::Select: opStr = "select"; break;
default: return false;
}
if (!c.buffer.append(opStr, strlen(opStr)))
return false;
@@ -611,16 +635,17 @@ RenderComparisonOperator(WasmRenderConte
if (!RenderExpr(c, *op.lhs()))
return false;
if (!RenderExpr(c, *op.rhs()))
return false;
if (!RenderIndent(c))
return false;
+ MAP_AST_EXPR(c, op);
const char* opStr;
switch (op.expr()) {
case Expr::I32Eq: opStr = "i32.eq"; break;
case Expr::I32Ne: opStr = "i32.ne"; break;
case Expr::I32LtS: opStr = "i32.lt_s"; break;
case Expr::I32LtU: opStr = "i32.lt_u"; break;
case Expr::I32LeS: opStr = "i32.le_s"; break;
case Expr::I32LeU: opStr = "i32.le_u"; break;
@@ -665,16 +690,17 @@ static bool
RenderConversionOperator(WasmRenderContext& c, AstConversionOperator& op)
{
if (!RenderExpr(c, *op.op()))
return false;
if (!RenderIndent(c))
return false;
+ MAP_AST_EXPR(c, op);
const char* opStr;
switch (op.expr()) {
case Expr::I32WrapI64: opStr = "i32.wrap/i64"; break;
case Expr::I32TruncSF32: opStr = "i32.trunc_s/f32"; break;
case Expr::I32TruncUF32: opStr = "i32.trunc_u/f32"; break;
case Expr::I32ReinterpretF32: opStr = "i32.reinterpret/f32"; break;
case Expr::I32TruncSF64: opStr = "i32.trunc_s/f64"; break;
case Expr::I32TruncUF64: opStr = "i32.trunc_u/f64"; break;
@@ -711,16 +737,17 @@ static bool
RenderIf(WasmRenderContext& c, AstIf& if_)
{
if (!RenderExpr(c, if_.cond()))
return false;
if (!RenderIndent(c))
return false;
+ MAP_AST_EXPR(c, if_);
if (!c.buffer.append("if"))
return false;
if (!RenderBlockNameAndSignature(c, if_.name(), if_.type()))
return false;
if (!if_.name().empty()) {
if (!c.buffer.append(' '))
@@ -791,16 +818,17 @@ static bool
RenderLoad(WasmRenderContext& c, AstLoad& load)
{
if (!RenderLoadStoreBase(c, load.address()))
return false;
if (!RenderIndent(c))
return false;
+ MAP_AST_EXPR(c, load);
uint32_t defaultAlignLog2;
switch (load.expr()) {
case Expr::I32Load8S:
if (!c.buffer.append("i32.load8_s"))
return false;
defaultAlignLog2 = 0;
break;
case Expr::I64Load8S:
@@ -885,16 +913,17 @@ RenderStore(WasmRenderContext& c, AstSto
return false;
if (!RenderExpr(c, store.value()))
return false;
if (!RenderIndent(c))
return false;
+ MAP_AST_EXPR(c, store);
uint32_t defaultAlignLog2;
switch (store.expr()) {
case Expr::I32Store8:
if (!c.buffer.append("i32.store8"))
return false;
defaultAlignLog2 = 0;
break;
case Expr::I64Store8:
@@ -961,16 +990,17 @@ RenderBranch(WasmRenderContext& c, AstBr
if (branch.maybeValue()) {
if (!RenderExpr(c, *(branch.maybeValue())))
return false;
}
if (!RenderIndent(c))
return false;
+ MAP_AST_EXPR(c, branch);
if (expr == Expr::BrIf ? !c.buffer.append("br_if ") : !c.buffer.append("br "))
return false;
if (!RenderRef(c, branch.target()))
return false;
return c.buffer.append('\n');
}
@@ -985,16 +1015,17 @@ RenderBrTable(WasmRenderContext& c, AstB
// Index
if (!RenderExpr(c, table.index()))
return false;
if (!RenderIndent(c))
return false;
+ MAP_AST_EXPR(c, table);
if (!c.buffer.append("br_table "))
return false;
uint32_t tableLength = table.table().length();
for (uint32_t i = 0; i < tableLength; i++) {
if (!RenderRef(c, table.table()[i]))
return false;
@@ -1014,32 +1045,33 @@ RenderReturn(WasmRenderContext& c, AstRe
if (ret.maybeExpr()) {
if (!RenderExpr(c, *(ret.maybeExpr())))
return false;
}
if (!RenderIndent(c))
return false;
+ MAP_AST_EXPR(c, ret);
if (!c.buffer.append("return"))
return false;
return c.buffer.append('\n');
}
static bool
RenderExpr(WasmRenderContext& c, AstExpr& expr)
{
switch (expr.kind()) {
case AstExprKind::Drop:
return RenderDrop(c, expr.as<AstDrop>());
case AstExprKind::Nop:
- return RenderNop(c);
+ return RenderNop(c, expr.as<AstNop>());
case AstExprKind::Unreachable:
- return RenderUnreachable(c);
+ return RenderUnreachable(c, expr.as<AstUnreachable>());
case AstExprKind::Call:
return RenderCall(c, expr.as<AstCall>());
case AstExprKind::CallIndirect:
return RenderCallIndirect(c, expr.as<AstCallIndirect>());
case AstExprKind::Const:
return RenderConst(c, expr.as<AstConst>());
case AstExprKind::GetLocal:
return RenderGetLocal(c, expr.as<AstGetLocal>());
@@ -1292,16 +1324,19 @@ RenderExportSection(WasmRenderContext& c
return true;
}
static bool
RenderFunctionBody(WasmRenderContext& c, AstFunc& func, const AstModule::SigVector& sigs)
{
const AstSig* sig = sigs[func.sig().index()];
+ size_t startExprIndex = c.maybeSourceMap ? c.maybeSourceMap->exprlocs().length() : 0;
+ uint32_t startLineno = c.buffer.lineno();
+
uint32_t argsNum = sig->args().length();
uint32_t localsNum = func.vars().length();
if (localsNum > 0) {
if (!RenderIndent(c))
return false;
for (uint32_t i = 0; i < localsNum; i++) {
if (!c.buffer.append("(local "))
return false;
@@ -1324,16 +1359,24 @@ RenderFunctionBody(WasmRenderContext& c,
uint32_t exprsNum = func.body().length();
for (uint32_t i = 0; i < exprsNum; i++) {
if (!RenderExpr(c, *func.body()[i]))
return false;
}
+ size_t endExprIndex = c.maybeSourceMap ? c.maybeSourceMap->exprlocs().length() : 0;
+ uint32_t endLineno = c.buffer.lineno();
+
+ if (c.maybeSourceMap) {
+ if (!c.maybeSourceMap->functionlocs().emplaceBack(startExprIndex, endExprIndex, startLineno, endLineno))
+ return false;
+ }
+
return true;
}
static bool
RenderCodeSection(WasmRenderContext& c, const AstModule::FuncVector& funcs, const AstModule::SigVector& sigs)
{
uint32_t numFuncBodies = funcs.length();
for (uint32_t funcIndex = 0; funcIndex < numFuncBodies; funcIndex++) {
@@ -1456,30 +1499,33 @@ RenderModule(WasmRenderContext& c, AstMo
c.indent--;
if (!c.buffer.append(")"))
return false;
return true;
}
+#undef MAP_AST_EXPR
+
/*****************************************************************************/
// Top-level functions
bool
-wasm::BinaryToText(JSContext* cx, const uint8_t* bytes, size_t length, StringBuffer& buffer)
+wasm::BinaryToText(JSContext* cx, const uint8_t* bytes, size_t length, StringBuffer& buffer, GeneratedSourceMap* sourceMap)
{
LifoAlloc lifo(AST_LIFO_DEFAULT_CHUNK_SIZE);
AstModule* module;
if (!BinaryToAst(cx, bytes, length, lifo, &module))
return false;
- WasmRenderContext c(cx, module, buffer);
+ WasmPrintBuffer buf(buffer);
+ WasmRenderContext c(cx, module, buf, sourceMap);
if (!RenderModule(c, *module)) {
if (!cx->isExceptionPending())
ReportOutOfMemory(cx);
return false;
}
return true;
--- a/js/src/asmjs/WasmBinaryToText.h
+++ b/js/src/asmjs/WasmBinaryToText.h
@@ -16,28 +16,30 @@
* limitations under the License.
*/
#ifndef wasm_binary_to_text_h
#define wasm_binary_to_text_h
#include "NamespaceImports.h"
+#include "asmjs/WasmGeneratedSourceMap.h"
#include "gc/Rooting.h"
#include "js/Class.h"
namespace js {
class StringBuffer;
namespace wasm {
// Translate the given binary representation of a wasm module into the module's textual
// representation.
MOZ_MUST_USE bool
-BinaryToText(JSContext* cx, const uint8_t* bytes, size_t length, StringBuffer& buffer);
+BinaryToText(JSContext* cx, const uint8_t* bytes, size_t length, StringBuffer& buffer,
+ GeneratedSourceMap* sourceMap = nullptr);
} // namespace wasm
} // namespace js
#endif // namespace wasm_binary_to_text_h
--- a/js/src/asmjs/WasmCode.cpp
+++ b/js/src/asmjs/WasmCode.cpp
@@ -19,16 +19,17 @@
#include "asmjs/WasmCode.h"
#include "mozilla/Atomics.h"
#include "mozilla/BinarySearch.h"
#include "mozilla/EnumeratedRange.h"
#include "jsprf.h"
+#include "asmjs/WasmBinaryToText.h"
#include "asmjs/WasmModule.h"
#include "asmjs/WasmSerialize.h"
#include "jit/ExecutableAllocator.h"
#include "jit/MacroAssembler.h"
#ifdef JS_ION_PERF
# include "jit/PerfSpewer.h"
#endif
#include "vm/StringBuffer.h"
@@ -709,20 +710,18 @@ Code::createText(JSContext* cx)
const Bytes& bytes = maybeBytecode_->bytes;
if (!buffer.append(experimentalWarning))
return nullptr;
maybeSourceMap_.reset(cx->runtime()->new_<GeneratedSourceMap>(cx));
if (!maybeSourceMap_)
return nullptr;
- if (!BinaryToExperimentalText(cx, bytes.begin(), bytes.length(), buffer,
- ExperimentalTextFormatting(), maybeSourceMap_.get())) {
+ if (!BinaryToText(cx, bytes.begin(), bytes.length(), buffer, maybeSourceMap_.get()))
return nullptr;
- }
#if DEBUG
// Checking source map invariant: expression and function locations must be sorted
// by line number.
uint32_t lastLineno = 0;
for (const ExprLoc& loc : maybeSourceMap_->exprlocs()) {
MOZ_ASSERT(lastLineno <= loc.lineno);
lastLineno = loc.lineno;
--- a/js/src/asmjs/WasmCode.h
+++ b/js/src/asmjs/WasmCode.h
@@ -14,17 +14,17 @@
* 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_code_h
#define wasm_code_h
-#include "asmjs/WasmBinaryToExperimentalText.h"
+#include "asmjs/WasmGeneratedSourceMap.h"
#include "asmjs/WasmTypes.h"
namespace js {
struct AsmJSMetadata;
namespace wasm {
new file mode 100644
--- /dev/null
+++ b/js/src/asmjs/WasmGeneratedSourceMap.h
@@ -0,0 +1,145 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ *
+ * 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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_generated_source_map_h
+#define wasm_generated_source_map_h
+
+#include "mozilla/Vector.h"
+
+#include "vm/StringBuffer.h"
+
+namespace js {
+
+namespace wasm {
+
+// 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 mozilla::Vector<ExprLoc, 0, TempAllocPolicy> ExprLocVector;
+
+// The generated source WebAssembly function lines and expressions ranges.
+struct FunctionLoc
+{
+ size_t startExprsIndex;
+ size_t endExprsIndex;
+ uint32_t startLineno;
+ uint32_t endLineno;
+ FunctionLoc(size_t startExprsIndex_, size_t endExprsIndex_, uint32_t startLineno_, uint32_t endLineno_)
+ : startExprsIndex(startExprsIndex_),
+ endExprsIndex(endExprsIndex_),
+ startLineno(startLineno_),
+ endLineno(endLineno_)
+ {}
+};
+
+typedef mozilla::Vector<FunctionLoc, 0, TempAllocPolicy> FunctionLocVector;
+
+// The generated source map for WebAssembly binary file. This map is generated during
+// building the text buffer (see BinaryToExperimentalText).
+class GeneratedSourceMap
+{
+ ExprLocVector exprlocs_;
+ FunctionLocVector functionlocs_;
+ uint32_t totalLines_;
+
+ public:
+ explicit GeneratedSourceMap(JSContext* cx)
+ : exprlocs_(cx),
+ functionlocs_(cx),
+ totalLines_(0)
+ {}
+ ExprLocVector& exprlocs() { return exprlocs_; }
+ FunctionLocVector& functionlocs() { return functionlocs_; }
+
+ uint32_t totalLines() { return totalLines_; }
+ void setTotalLines(uint32_t val) { totalLines_ = val; }
+};
+
+typedef UniquePtr<GeneratedSourceMap> UniqueGeneratedSourceMap;
+
+// Helper class, StringBuffer wrapper, to track the position (line and column)
+// within the generated source.
+class WasmPrintBuffer
+{
+ StringBuffer& stringBuffer_;
+ uint32_t lineno_;
+ uint32_t column_;
+
+ public:
+ explicit WasmPrintBuffer(StringBuffer& stringBuffer) : stringBuffer_(stringBuffer), lineno_(1), column_(1) {}
+ inline char processChar(char ch) {
+ if (ch == '\n') {
+ lineno_++; column_ = 1;
+ } else
+ column_++;
+ return ch;
+ }
+ inline char16_t processChar(char16_t ch) {
+ if (ch == '\n') {
+ lineno_++; column_ = 1;
+ } else
+ column_++;
+ return ch;
+ }
+ bool append(const char ch) {
+ return stringBuffer_.append(processChar(ch));
+ }
+ bool append(const char16_t ch) {
+ return stringBuffer_.append(processChar(ch));
+ }
+ bool append(const char* str, size_t length) {
+ for (size_t i = 0; i < length; i++)
+ processChar(str[i]);
+ return stringBuffer_.append(str, length);
+ }
+ bool append(const char16_t* begin, const char16_t* end) {
+ for (const char16_t* p = begin; p != end; p++)
+ processChar(*p);
+ return stringBuffer_.append(begin, end);
+ }
+ bool append(const char16_t* str, size_t length) {
+ return append(str, str + length);
+ }
+ template <size_t ArrayLength>
+ bool append(const char (&array)[ArrayLength]) {
+ return append(array, ArrayLength - 1);
+ }
+ char16_t getChar(size_t index) {
+ return stringBuffer_.getChar(index);
+ }
+ size_t length() {
+ return stringBuffer_.length();
+ }
+ StringBuffer& stringBuffer() { return stringBuffer_; }
+ uint32_t lineno() { return lineno_; }
+ uint32_t column() { return column_; }
+};
+
+} // namespace wasm
+
+} // namespace js
+
+#endif // namespace wasm_generated_source_map_h
--- a/js/src/jit-test/tests/debug/wasm-05.js
+++ b/js/src/jit-test/tests/debug/wasm-05.js
@@ -28,22 +28,11 @@ var result1 = getAllOffsets('(module \
)');
var nopLine = result1.filter(i => i.str.indexOf('nop') >= 0);
assertEq(nopLine.length, 1);
// The nopLine shall have single offset.
assertEq(nopLine[0].offsets.length, 1);
assertEq(nopLine[0].offsets[0] > 0, true);
-var sqrtLine = result1.filter(i => i.str.indexOf('sqrt') >= 0);
-assertEq(sqrtLine.length, 1);
-// The sqrtLine shall have 5 offsets but they were produced from AST postorder decoding:
-// drop(f32.sqrt(1.0 + 2.0)) ~~> 88,87,86,76,81
-assertEq(sqrtLine[0].offsets.length, 5);
-assertEq(sqrtLine[0].offsets[3] > 0, true);
-assertEq(sqrtLine[0].offsets[3] < sqrtLine[0].offsets[4], true);
-assertEq(sqrtLine[0].offsets[2] > sqrtLine[0].offsets[3], true);
-assertEq(sqrtLine[0].offsets[1] > sqrtLine[0].offsets[2], true);
-assertEq(sqrtLine[0].offsets[0] > sqrtLine[0].offsets[1], true);
-
-var noOffsetLines = result1.filter(i => i.str.indexOf('nop') < 0 && i.str.indexOf('sqrt') < 0);
-// Other lines will not have offsets.
-assertEq(noOffsetLines.every(i => i.offsets.length == 0), true);
+var singleOffsetLines = result1.filter(i => i.offsets.length === 1);
+// There shall be total 6 lines with single offset.
+assertEq(singleOffsetLines.length === 6, true);