Bug 1445272: Implement text-to-binary support for anyref; r=luke
authorBenjamin Bouvier <benj@benj.me>
Wed, 21 Mar 2018 14:49:24 +0100
changeset 413258 670d462e97cbd93bf7856ee6793ecd530394c928
parent 413257 f8b79c586af6e9ee3cdd5b56fd8f84f8ce2d9900
child 413259 f8a4c128ffd4989884dac54155430cffb04b947a
push id33840
push userapavel@mozilla.com
push dateFri, 13 Apr 2018 21:56:54 +0000
treeherdermozilla-central@6547c27303bc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs1445272
milestone61.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1445272: Implement text-to-binary support for anyref; r=luke
js/src/wasm/WasmAST.h
js/src/wasm/WasmTextToBinary.cpp
--- a/js/src/wasm/WasmAST.h
+++ b/js/src/wasm/WasmAST.h
@@ -204,16 +204,17 @@ enum class AstExprKind
     First,
     GetGlobal,
     GetLocal,
     GrowMemory,
     If,
     Load,
     Nop,
     Pop,
+    RefNull,
     Return,
     SetGlobal,
     SetLocal,
     TeeLocal,
     Store,
     TernaryOperator,
     UnaryOperator,
     Unreachable,
@@ -1158,16 +1159,29 @@ class AstExtraConversionOperator final :
         op_(op), operand_(operand)
     {}
 
     NumericOp op() const { return op_; }
     AstExpr* operand() const { return operand_; }
 };
 #endif
 
+class AstRefNull final : public AstExpr
+{
+    ValType refType_;
+  public:
+    static const AstExprKind Kind = AstExprKind::RefNull;
+    explicit AstRefNull(ValType refType)
+      : AstExpr(Kind, ExprType::Limit), refType_(refType)
+    {}
+    ValType refType() const {
+        return refType_;
+    }
+};
+
 // This is an artificial AST node which can fill operand slots in an AST
 // constructed from parsing or decoding stack-machine code that doesn't have
 // an inherent AST structure.
 class AstPop final : public AstExpr
 {
   public:
     static const AstExprKind Kind = AstExprKind::Pop;
     AstPop()
--- a/js/src/wasm/WasmTextToBinary.cpp
+++ b/js/src/wasm/WasmTextToBinary.cpp
@@ -110,16 +110,17 @@ class WasmToken
         Loop,
         Module,
         Mutable,
         Name,
         Nop,
         Offset,
         OpenParen,
         Param,
+        RefNull,
         Result,
         Return,
         SetGlobal,
         SetLocal,
         Shared,
         SignedInteger,
         Start,
         Store,
@@ -326,16 +327,17 @@ class WasmToken
           case Drop:
           case GetGlobal:
           case GetLocal:
           case GrowMemory:
           case If:
           case Load:
           case Loop:
           case Nop:
+          case RefNull:
           case Return:
           case SetGlobal:
           case SetLocal:
           case Store:
           case TeeLocal:
           case TernaryOpcode:
           case UnaryOpcode:
           case Unreachable:
@@ -883,16 +885,18 @@ WasmTokenStream::next()
       case '5': case '6': case '7': case '8': case '9':
         return literal(begin);
 
       case 'a':
         if (consume(u"align"))
             return WasmToken(WasmToken::Align, begin, cur_);
         if (consume(u"anyfunc"))
             return WasmToken(WasmToken::AnyFunc, begin, cur_);
+        if (consume(u"anyref"))
+            return WasmToken(WasmToken::ValueType, ValType::AnyRef, begin, cur_);
 #ifdef ENABLE_WASM_THREAD_OPS
         if (consume(u"atomic.wake"))
             return WasmToken(WasmToken::Wake, ThreadOp::Wake, begin, cur_);
 #endif
         break;
 
       case 'b':
         if (consume(u"block"))
@@ -1660,16 +1664,23 @@ WasmTokenStream::next()
             return WasmToken(WasmToken::Param, begin, cur_);
         break;
 
       case 'r':
         if (consume(u"result"))
             return WasmToken(WasmToken::Result, begin, cur_);
         if (consume(u"return"))
             return WasmToken(WasmToken::Return, begin, cur_);
+        if (consume(u"ref.")) {
+            if (consume(u"null"))
+                return WasmToken(WasmToken::RefNull, begin, cur_);
+            if (consume(u"is_null"))
+                return WasmToken(WasmToken::UnaryOpcode, Op::RefIsNull, begin, cur_);
+            break;
+        }
         break;
 
       case 's':
         if (consume(u"select"))
             return WasmToken(WasmToken::TernaryOpcode, Op::Select, begin, cur_);
         if (consume(u"set_global"))
             return WasmToken(WasmToken::SetGlobal, begin, cur_);
         if (consume(u"set_local"))
@@ -2928,16 +2939,29 @@ ParseGrowMemory(WasmParseContext& c, boo
     AstExpr* operand = ParseExpr(c, inParens);
     if (!operand)
         return nullptr;
 
     return new(c.lifo) AstGrowMemory(operand);
 }
 
 static AstExpr*
+ParseRefNull(WasmParseContext& c)
+{
+    WasmToken token;
+    if (!c.ts.match(WasmToken::ValueType, &token, c.error))
+        return nullptr;
+    if (token.valueType() != ValType::AnyRef) {
+        c.ts.generateError(token, "only anyref is supported for nullref", c.error);
+        return nullptr;
+    }
+    return new(c.lifo) AstRefNull(ValType::AnyRef);
+}
+
+static AstExpr*
 ParseExprBody(WasmParseContext& c, WasmToken token, bool inParens)
 {
     if (!CheckRecursionLimitDontReport(c.stackLimit))
         return nullptr;
     switch (token.kind()) {
       case WasmToken::Unreachable:
         return new(c.lifo) AstUnreachable;
       case WasmToken::AtomicCmpXchg:
@@ -3003,16 +3027,18 @@ ParseExprBody(WasmParseContext& c, WasmT
       case WasmToken::UnaryOpcode:
         return ParseUnaryOperator(c, token.op(), inParens);
       case WasmToken::Nop:
         return new(c.lifo) AstNop();
       case WasmToken::CurrentMemory:
         return new(c.lifo) AstCurrentMemory();
       case WasmToken::GrowMemory:
         return ParseGrowMemory(c, inParens);
+      case WasmToken::RefNull:
+        return ParseRefNull(c);
       default:
         c.ts.generateError(token, c.error);
         return nullptr;
     }
 }
 
 static AstExpr*
 ParseExprInsideParens(WasmParseContext& c)
@@ -4320,16 +4346,17 @@ ResolveWake(Resolver& r, AstWake& s)
 static bool
 ResolveExpr(Resolver& r, AstExpr& expr)
 {
     switch (expr.kind()) {
       case AstExprKind::Nop:
       case AstExprKind::Pop:
       case AstExprKind::Unreachable:
       case AstExprKind::CurrentMemory:
+      case AstExprKind::RefNull:
         return true;
       case AstExprKind::Drop:
         return ResolveDropOperator(r, expr.as<AstDrop>());
       case AstExprKind::BinaryOperator:
         return ResolveBinaryOperator(r, expr.as<AstBinaryOperator>());
       case AstExprKind::Block:
         return ResolveBlock(r, expr.as<AstBlock>());
       case AstExprKind::Branch:
@@ -4925,25 +4952,34 @@ EncodeWake(Encoder& e, AstWake& s)
 {
     return EncodeLoadStoreAddress(e, s.address()) &&
            EncodeExpr(e, s.count()) &&
            e.writeOp(ThreadOp::Wake) &&
            EncodeLoadStoreFlags(e, s.address());
 }
 
 static bool
+EncodeRefNull(Encoder& e, AstRefNull& s)
+{
+    return e.writeOp(Op::RefNull) &&
+           e.writeValType(s.refType());
+}
+
+static bool
 EncodeExpr(Encoder& e, AstExpr& expr)
 {
     switch (expr.kind()) {
       case AstExprKind::Pop:
         return true;
       case AstExprKind::Nop:
         return e.writeOp(Op::Nop);
       case AstExprKind::Unreachable:
         return e.writeOp(Op::Unreachable);
+      case AstExprKind::RefNull:
+        return EncodeRefNull(e, expr.as<AstRefNull>());
       case AstExprKind::BinaryOperator:
         return EncodeBinaryOperator(e, expr.as<AstBinaryOperator>());
       case AstExprKind::Block:
         return EncodeBlock(e, expr.as<AstBlock>());
       case AstExprKind::Branch:
         return EncodeBranch(e, expr.as<AstBranch>());
       case AstExprKind::Call:
         return EncodeCall(e, expr.as<AstCall>());