mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-08 00:38:39 +09:00
Issue #1240 - Part 4 - Implement parser support for BigInt literals. https://bugzilla.mozilla.org/show_bug.cgi?id=1505849 Partially based on https://bugzilla.mozilla.org/show_bug.cgi?id=1456568 Un-result-ified the BigInt XDR code, so we can enable it. https://bugzilla.mozilla.org/show_bug.cgi?id=1419094 Uninitialised memory read with BigInt right-shift https://bugzilla.mozilla.org/show_bug.cgi?id=1679003
This commit is contained in:
parent
07b6c03dc7
commit
dc23241afb
27 changed files with 394 additions and 80 deletions
|
|
@ -1047,7 +1047,6 @@ MaybeWrapValue(JSContext* cx, JS::MutableHandle<JS::Value> rval)
|
|||
if (rval.isBigInt()) {
|
||||
return JS_WrapValue(cx, rval);
|
||||
}
|
||||
MOZ_ASSERT(rval.isSymbol());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -667,7 +667,7 @@ class MOZ_NON_PARAM alignas(8) Value
|
|||
#if defined(JS_NUNBOX32)
|
||||
return data.s.payload.bi;
|
||||
#elif defined(JS_PUNBOX64)
|
||||
return reinterpret_cast<JS::BigInt*>(data.asBits & JSVAL_SHIFTED_TAG_BIGINT);
|
||||
return reinterpret_cast<JS::BigInt*>(data.asBits & JSVAL_PAYLOAD_MASK);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include "frontend/TokenStream.h"
|
||||
#include "js/CharacterEncoding.h"
|
||||
#include "vm/RegExpObject.h"
|
||||
#include "vm/BigIntType.h"
|
||||
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
|
|
@ -3434,6 +3435,7 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
|
|||
case PNK_STRING:
|
||||
case PNK_REGEXP:
|
||||
case PNK_NUMBER:
|
||||
case PNK_BIGINT:
|
||||
case PNK_TRUE:
|
||||
case PNK_FALSE:
|
||||
case PNK_NULL:
|
||||
|
|
@ -3604,7 +3606,7 @@ ASTSerializer::literal(ParseNode* pn, MutableHandleValue dst)
|
|||
|
||||
case PNK_REGEXP:
|
||||
{
|
||||
RootedObject re1(cx, pn->as<RegExpLiteral>().objbox()->object);
|
||||
RootedObject re1(cx, pn->as<RegExpLiteral>().objbox()->object());
|
||||
LOCAL_ASSERT(re1 && re1->is<RegExpObject>());
|
||||
|
||||
RootedObject re2(cx, CloneRegExpObject(cx, re1));
|
||||
|
|
@ -3619,6 +3621,13 @@ ASTSerializer::literal(ParseNode* pn, MutableHandleValue dst)
|
|||
val.setNumber(pn->as<NumericLiteral>().value());
|
||||
break;
|
||||
|
||||
case PNK_BIGINT:
|
||||
{
|
||||
BigInt* x = pn->as<BigIntLiteral>().box()->value();
|
||||
val.setBigInt(x);
|
||||
break;
|
||||
}
|
||||
|
||||
case PNK_NULL:
|
||||
val.setNull();
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1093,6 +1093,11 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
|
|||
*answer = false;
|
||||
return true;
|
||||
|
||||
case PNK_BIGINT:
|
||||
MOZ_ASSERT(pn->is<BigIntLiteral>());
|
||||
*answer = false;
|
||||
return true;
|
||||
|
||||
// |this| can throw in derived class constructors, including nested arrow
|
||||
// functions or eval.
|
||||
case PNK_THIS:
|
||||
|
|
@ -4225,6 +4230,9 @@ ParseNode::getConstantValue(ExclusiveContext* cx, AllowConstantObjects allowObje
|
|||
case PNK_NUMBER:
|
||||
vp.setNumber(as<NumericLiteral>().value());
|
||||
return true;
|
||||
case PNK_BIGINT:
|
||||
vp.setBigInt(as<BigIntLiteral>().box()->value());
|
||||
return true;
|
||||
case PNK_TEMPLATE_STRING:
|
||||
case PNK_STRING:
|
||||
vp.setString(as<NameNode>().atom());
|
||||
|
|
@ -4834,6 +4842,15 @@ BytecodeEmitter::emitCopyDataProperties(CopyOption option)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitBigIntOp(BigInt* bigint)
|
||||
{
|
||||
if (!constList.append(BigIntValue(bigint))) {
|
||||
return false;
|
||||
}
|
||||
return emitIndex32(JSOP_BIGINT, constList.length() - 1);
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitIterator()
|
||||
{
|
||||
|
|
@ -9579,6 +9596,12 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage::
|
|||
return false;
|
||||
break;
|
||||
|
||||
case PNK_BIGINT:
|
||||
if (!emitBigIntOp(pn->as<BigIntLiteral>().box()->value())) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case PNK_REGEXP:
|
||||
if (!emitRegExp(objectList.add(pn->as<RegExpLiteral>().objbox())))
|
||||
return false;
|
||||
|
|
@ -10317,7 +10340,7 @@ CGConstList::finish(ConstArray* array)
|
|||
MOZ_ASSERT(length() == array->length);
|
||||
|
||||
for (unsigned i = 0; i < length(); i++)
|
||||
array->vector[i] = list[i];
|
||||
array->vector[i] = vector[i];
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -10331,6 +10354,7 @@ CGConstList::finish(ConstArray* array)
|
|||
unsigned
|
||||
CGObjectList::add(ObjectBox* objbox)
|
||||
{
|
||||
MOZ_ASSERT(objbox->isObjectBox());
|
||||
MOZ_ASSERT(!objbox->emitLink);
|
||||
objbox->emitLink = lastbox;
|
||||
lastbox = objbox;
|
||||
|
|
@ -10342,7 +10366,7 @@ CGObjectList::indexOf(JSObject* obj)
|
|||
{
|
||||
MOZ_ASSERT(length > 0);
|
||||
unsigned index = length - 1;
|
||||
for (ObjectBox* box = lastbox; box->object != obj; box = box->emitLink)
|
||||
for (ObjectBox* box = lastbox; box->object() != obj; box = box->emitLink)
|
||||
index--;
|
||||
return index;
|
||||
}
|
||||
|
|
@ -10358,8 +10382,8 @@ CGObjectList::finish(ObjectArray* array)
|
|||
do {
|
||||
--cursor;
|
||||
MOZ_ASSERT(!*cursor);
|
||||
MOZ_ASSERT(objbox->object->isTenured());
|
||||
*cursor = objbox->object;
|
||||
MOZ_ASSERT(objbox->object()->isTenured());
|
||||
*cursor = objbox->object();
|
||||
} while ((objbox = objbox->emitLink) != nullptr);
|
||||
MOZ_ASSERT(cursor == array->vector);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,20 +35,21 @@ class SharedContext;
|
|||
class TokenStream;
|
||||
|
||||
class CGConstList {
|
||||
Vector<Value> list;
|
||||
Rooted<ValueVector> vector;
|
||||
public:
|
||||
explicit CGConstList(ExclusiveContext* cx) : list(cx) {}
|
||||
explicit CGConstList(ExclusiveContext* cx)
|
||||
: vector(cx, ValueVector(cx))
|
||||
{ }
|
||||
MOZ_MUST_USE bool append(const Value& v) {
|
||||
MOZ_ASSERT_IF(v.isString(), v.toString()->isAtom());
|
||||
return list.append(v);
|
||||
return vector.append(v);
|
||||
}
|
||||
size_t length() const { return list.length(); }
|
||||
size_t length() const { return vector.length(); }
|
||||
void finish(ConstArray* array);
|
||||
};
|
||||
|
||||
struct CGObjectList {
|
||||
uint32_t length; /* number of emitted so far objects */
|
||||
ObjectBox* lastbox; /* last emitted object */
|
||||
ObjectBox* lastbox; /* last emitted object */
|
||||
|
||||
CGObjectList() : length(0), lastbox(nullptr) {}
|
||||
|
||||
|
|
@ -198,7 +199,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
|||
return innermostEmitterScope_;
|
||||
}
|
||||
|
||||
CGConstList constList; /* constants to be included with the script */
|
||||
CGConstList constList; /* double and bigint values used by script */
|
||||
CGObjectList objectList; /* list of emitted objects */
|
||||
CGScopeList scopeList; /* list of emitted scopes */
|
||||
CGTryNoteList tryNoteList; /* list of emitted try notes */
|
||||
|
|
@ -478,6 +479,8 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
|||
|
||||
MOZ_MUST_USE bool emitNumberOp(double dval);
|
||||
|
||||
MOZ_MUST_USE bool emitBigIntOp(BigInt* bigint);
|
||||
|
||||
MOZ_MUST_USE bool emitThisLiteral(ThisLiteral* pn);
|
||||
MOZ_MUST_USE bool emitGetFunctionThis(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitGetFunctionThis(const mozilla::Maybe<uint32_t>& offset);
|
||||
|
|
|
|||
|
|
@ -395,6 +395,7 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result)
|
|||
case PNK_THIS:
|
||||
case PNK_ELISION:
|
||||
case PNK_NUMBER:
|
||||
case PNK_BIGINT:
|
||||
case PNK_NEW:
|
||||
case PNK_GENERATOR:
|
||||
case PNK_GENEXP:
|
||||
|
|
@ -485,6 +486,7 @@ IsEffectless(ParseNode* node)
|
|||
node->isKind(PNK_FALSE) ||
|
||||
node->isKind(PNK_STRING) ||
|
||||
node->isKind(PNK_TEMPLATE_STRING) ||
|
||||
node->isKind(PNK_BIGINT) ||
|
||||
node->isKind(PNK_NUMBER) ||
|
||||
node->isKind(PNK_NULL) ||
|
||||
node->isKind(PNK_RAW_UNDEFINED) ||
|
||||
|
|
@ -503,6 +505,9 @@ Boolish(ParseNode* pn, bool isNullish = false)
|
|||
return (isNullish || isNonZeroNumber) ? Truthy : Falsy;
|
||||
}
|
||||
|
||||
case PNK_BIGINT:
|
||||
return (pn->as<BigIntLiteral>().box()->value()->isZero()) ? Falsy : Truthy;
|
||||
|
||||
case PNK_STRING:
|
||||
case PNK_TEMPLATE_STRING: {
|
||||
bool isNonZeroLengthString = (pn->as<NameNode>().atom()->length() > 0);
|
||||
|
|
@ -591,6 +596,8 @@ FoldTypeOfExpr(ExclusiveContext* cx, UnaryNode* node, Parser<FullParseHandler>&
|
|||
result = cx->names().string;
|
||||
else if (expr->isKind(PNK_NUMBER))
|
||||
result = cx->names().number;
|
||||
else if (expr->isKind(PNK_BIGINT))
|
||||
result = cx->names().bigint;
|
||||
else if (expr->isKind(PNK_NULL))
|
||||
result = cx->names().object;
|
||||
else if (expr->isKind(PNK_TRUE) || expr->isKind(PNK_FALSE))
|
||||
|
|
@ -1699,6 +1706,10 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
|
|||
MOZ_ASSERT(pn->is<NumericLiteral>());
|
||||
return true;
|
||||
|
||||
case PNK_BIGINT:
|
||||
MOZ_ASSERT(pn->is<BigIntLiteral>());
|
||||
return true;
|
||||
|
||||
case PNK_SUPERBASE:
|
||||
case PNK_TYPEOFNAME: {
|
||||
#ifdef DEBUG
|
||||
|
|
|
|||
|
|
@ -151,6 +151,18 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
|
|||
return new_<NumericLiteral>(value, decimalPoint, pos);
|
||||
}
|
||||
|
||||
// The Boxer object here is any object that can allocate BigIntBoxes.
|
||||
// Specifically, a Boxer has a .newBigIntBox(T) method that accepts a
|
||||
// BigInt* argument and returns a BigIntBox*.
|
||||
template <class Boxer>
|
||||
BigIntLiteralType newBigInt(BigInt* bi, const TokenPos& pos, Boxer& boxer) {
|
||||
BigIntBox* box = boxer.newBigIntBox(bi);
|
||||
if (!box) {
|
||||
return null();
|
||||
}
|
||||
return new_<BigIntLiteral>(box, pos);
|
||||
}
|
||||
|
||||
BooleanLiteralType newBooleanLiteral(bool cond, const TokenPos& pos) {
|
||||
return new_<BooleanLiteral>(cond, pos);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -420,6 +420,9 @@ class NameResolver
|
|||
MOZ_ASSERT(cur->is<NumericLiteral>());
|
||||
break;
|
||||
|
||||
case PNK_BIGINT:
|
||||
MOZ_ASSERT(cur->is<BigIntLiteral>());
|
||||
break;
|
||||
|
||||
case PNK_TYPEOFNAME:
|
||||
case PNK_SUPERBASE:
|
||||
|
|
|
|||
|
|
@ -218,6 +218,10 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack)
|
|||
MOZ_ASSERT(pn->is<NumericLiteral>());
|
||||
return PushResult::Recyclable;
|
||||
|
||||
case PNK_BIGINT:
|
||||
MOZ_ASSERT(pn->is<BigIntLiteral>());
|
||||
return PushResult::Recyclable;
|
||||
|
||||
// Nodes with a single non-null child.
|
||||
case PNK_TYPEOFNAME:
|
||||
case PNK_TYPEOFEXPR:
|
||||
|
|
@ -716,6 +720,9 @@ ParseNode::dump(int indent)
|
|||
case PN_NUMBER:
|
||||
as<NumericLiteral>().dump(indent);
|
||||
return;
|
||||
case PN_BIGINT:
|
||||
as<BigIntLiteral>().dump(indent);
|
||||
return;
|
||||
case PN_REGEXP:
|
||||
as<RegExpLiteral>().dump(indent);
|
||||
return;
|
||||
|
|
@ -759,6 +766,12 @@ NumericLiteral::dump(int indent)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
BigIntLiteral::dump(int indent)
|
||||
{
|
||||
fprintf(stderr, "(%s)", parseNodeNames[size_t(getKind())]);
|
||||
}
|
||||
|
||||
void
|
||||
RegExpLiteral::dump(int indent)
|
||||
{
|
||||
|
|
@ -962,23 +975,45 @@ LexicalScopeNode::dump(int indent)
|
|||
}
|
||||
#endif
|
||||
|
||||
ObjectBox::ObjectBox(JSObject* object, ObjectBox* traceLink)
|
||||
: object(object),
|
||||
traceLink(traceLink),
|
||||
emitLink(nullptr)
|
||||
TraceListNode::TraceListNode(js::gc::Cell* gcThing, TraceListNode* traceLink)
|
||||
: gcThing(gcThing),
|
||||
traceLink(traceLink)
|
||||
{
|
||||
MOZ_ASSERT(!object->is<JSFunction>());
|
||||
MOZ_ASSERT(object->isTenured());
|
||||
MOZ_ASSERT(gcThing->isTenured());
|
||||
}
|
||||
|
||||
ObjectBox::ObjectBox(JSFunction* function, ObjectBox* traceLink)
|
||||
: object(function),
|
||||
traceLink(traceLink),
|
||||
BigIntBox*
|
||||
TraceListNode::asBigIntBox()
|
||||
{
|
||||
MOZ_ASSERT(isBigIntBox());
|
||||
return static_cast<BigIntBox*>(this);
|
||||
}
|
||||
|
||||
ObjectBox*
|
||||
TraceListNode::asObjectBox()
|
||||
{
|
||||
MOZ_ASSERT(isObjectBox());
|
||||
return static_cast<ObjectBox*>(this);
|
||||
}
|
||||
|
||||
BigIntBox::BigIntBox(BigInt* bi, TraceListNode* traceLink)
|
||||
: TraceListNode(bi, traceLink)
|
||||
{
|
||||
}
|
||||
|
||||
ObjectBox::ObjectBox(JSObject* obj, TraceListNode* traceLink)
|
||||
: TraceListNode(obj, traceLink),
|
||||
emitLink(nullptr)
|
||||
{
|
||||
MOZ_ASSERT(object->is<JSFunction>());
|
||||
MOZ_ASSERT(!object()->is<JSFunction>());
|
||||
}
|
||||
|
||||
ObjectBox::ObjectBox(JSFunction* function, TraceListNode* traceLink)
|
||||
: TraceListNode(function, traceLink),
|
||||
emitLink(nullptr)
|
||||
{
|
||||
MOZ_ASSERT(object()->is<JSFunction>());
|
||||
MOZ_ASSERT(asFunctionBox()->function() == function);
|
||||
MOZ_ASSERT(object->isTenured());
|
||||
}
|
||||
|
||||
FunctionBox*
|
||||
|
|
@ -989,16 +1024,17 @@ ObjectBox::asFunctionBox()
|
|||
}
|
||||
|
||||
/* static */ void
|
||||
ObjectBox::TraceList(JSTracer* trc, ObjectBox* listHead)
|
||||
TraceListNode::TraceList(JSTracer* trc, TraceListNode* listHead)
|
||||
{
|
||||
for (ObjectBox* box = listHead; box; box = box->traceLink)
|
||||
box->trace(trc);
|
||||
for (TraceListNode* node = listHead; node; node = node->traceLink) {
|
||||
node->trace(trc);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ObjectBox::trace(JSTracer* trc)
|
||||
TraceListNode::trace(JSTracer* trc)
|
||||
{
|
||||
TraceRoot(trc, &object, "parser.object");
|
||||
TraceGenericPointerRoot(trc, &gcThing, "parser.traceListNode");
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "builtin/ModuleObject.h"
|
||||
#include "frontend/TokenStream.h"
|
||||
#include "vm/BigIntType.h"
|
||||
|
||||
namespace js {
|
||||
namespace frontend {
|
||||
|
|
@ -20,6 +21,7 @@ class ParseContext;
|
|||
class FullParseHandler;
|
||||
class FunctionBox;
|
||||
class ObjectBox;
|
||||
class BigIntBox;
|
||||
|
||||
#define FOR_EACH_PARSE_NODE_KIND(F) \
|
||||
F(NOP) \
|
||||
|
|
@ -53,6 +55,7 @@ class ObjectBox;
|
|||
F(OBJECT_PROPERTY_NAME) \
|
||||
F(COMPUTED_NAME) \
|
||||
F(NUMBER) \
|
||||
F(BIGINT) \
|
||||
F(STRING) \
|
||||
F(TEMPLATE_STRING_LIST) \
|
||||
F(TEMPLATE_STRING) \
|
||||
|
|
@ -524,6 +527,8 @@ IsTypeofKind(ParseNodeKind kind)
|
|||
* regexp: RegExp model object
|
||||
* PNK_NUMBER (NumericLiteral)
|
||||
* value: double value of numeric literal
|
||||
* PNK_BIGINT (BigIntLiteral)
|
||||
* box: BigIntBox holding BigInt* value
|
||||
* PNK_TRUE, PNK_FALSE (BooleanLiteral)
|
||||
* pn_op: JSOp bytecode
|
||||
* PNK_NULL (NullLiteral)
|
||||
|
|
@ -571,6 +576,7 @@ enum ParseNodeArity
|
|||
PN_LIST, /* generic singly linked list */
|
||||
PN_NAME, /* name, label, string */
|
||||
PN_NUMBER, /* numeric literal */
|
||||
PN_BIGINT, /* BigInt literal */
|
||||
PN_REGEXP, /* regexp literal */
|
||||
PN_LOOP, /* loop control (break/continue) */
|
||||
PN_SCOPE /* lexical scope */
|
||||
|
|
@ -613,6 +619,7 @@ enum ParseNodeArity
|
|||
macro(RawUndefinedLiteral, RawUndefinedLiteralType, asRawUndefinedLiteral) \
|
||||
\
|
||||
macro(NumericLiteral, NumericLiteralType, asNumericLiteral) \
|
||||
macro(BigIntLiteral, BigIntLiteralType, asBigIntLiteral) \
|
||||
\
|
||||
macro(RegExpLiteral, RegExpLiteralType, asRegExpLiteral) \
|
||||
\
|
||||
|
|
@ -828,6 +835,11 @@ class ParseNode
|
|||
double value; /* aligned numeric literal value */
|
||||
DecimalPoint decimalPoint; /* Whether the number has a decimal point */
|
||||
} number;
|
||||
struct {
|
||||
private:
|
||||
friend class BigIntLiteral;
|
||||
BigIntBox* box;
|
||||
} bigint;
|
||||
class {
|
||||
private:
|
||||
friend class LoopControlStatement;
|
||||
|
|
@ -849,6 +861,7 @@ class ParseNode
|
|||
/* True if pn is a parsenode representing a literal constant. */
|
||||
bool isLiteral() const {
|
||||
return isKind(PNK_NUMBER) ||
|
||||
isKind(PNK_BIGINT) ||
|
||||
isKind(PNK_STRING) ||
|
||||
isKind(PNK_TRUE) ||
|
||||
isKind(PNK_FALSE) ||
|
||||
|
|
@ -1631,6 +1644,30 @@ class NumericLiteral : public ParseNode
|
|||
}
|
||||
};
|
||||
|
||||
class BigIntLiteral : public ParseNode
|
||||
{
|
||||
public:
|
||||
BigIntLiteral(BigIntBox* bibox, const TokenPos& pos)
|
||||
: ParseNode(PNK_BIGINT, JSOP_NOP, PN_BIGINT, pos)
|
||||
{
|
||||
pn_u.bigint.box = bibox;
|
||||
}
|
||||
|
||||
static bool test(const ParseNode& node) {
|
||||
bool match = node.isKind(PNK_BIGINT);
|
||||
MOZ_ASSERT_IF(match, node.isArity(PN_BIGINT));
|
||||
return match;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void dump(int indent);
|
||||
#endif
|
||||
|
||||
BigIntBox* box() const {
|
||||
return pn_u.bigint.box;
|
||||
}
|
||||
};
|
||||
|
||||
class LexicalScopeNode : public ParseNode
|
||||
{
|
||||
public:
|
||||
|
|
@ -2350,25 +2387,48 @@ ParseNode::isConstant()
|
|||
}
|
||||
}
|
||||
|
||||
class ObjectBox
|
||||
class TraceListNode
|
||||
{
|
||||
public:
|
||||
JSObject* object;
|
||||
protected:
|
||||
js::gc::Cell* gcThing;
|
||||
TraceListNode* traceLink;
|
||||
|
||||
TraceListNode(js::gc::Cell* gcThing, TraceListNode* traceLink);
|
||||
|
||||
bool isBigIntBox() const { return gcThing->is<BigInt>(); }
|
||||
bool isObjectBox() const { return gcThing->is<JSObject>(); }
|
||||
|
||||
BigIntBox* asBigIntBox();
|
||||
ObjectBox* asObjectBox();
|
||||
|
||||
ObjectBox(JSObject* object, ObjectBox* traceLink);
|
||||
bool isFunctionBox() { return object->is<JSFunction>(); }
|
||||
FunctionBox* asFunctionBox();
|
||||
virtual void trace(JSTracer* trc);
|
||||
|
||||
static void TraceList(JSTracer* trc, ObjectBox* listHead);
|
||||
public:
|
||||
static void TraceList(JSTracer* trc, TraceListNode* listHead);
|
||||
};
|
||||
|
||||
class BigIntBox : public TraceListNode
|
||||
{
|
||||
public:
|
||||
BigIntBox(BigInt* bi, TraceListNode* link);
|
||||
BigInt* value() const { return gcThing->as<BigInt>(); }
|
||||
};
|
||||
|
||||
class ObjectBox : public TraceListNode
|
||||
{
|
||||
protected:
|
||||
friend struct CGObjectList;
|
||||
|
||||
ObjectBox* traceLink;
|
||||
ObjectBox* emitLink;
|
||||
|
||||
ObjectBox(JSFunction* function, TraceListNode* link);
|
||||
|
||||
ObjectBox(JSFunction* function, ObjectBox* traceLink);
|
||||
public:
|
||||
ObjectBox(JSObject* obj, TraceListNode* link);
|
||||
|
||||
JSObject* object() const { return gcThing->as<JSObject>(); }
|
||||
|
||||
bool isFunctionBox() const { return object()->is<JSFunction>(); }
|
||||
FunctionBox* asFunctionBox();
|
||||
};
|
||||
|
||||
enum ParseReportKind
|
||||
|
|
|
|||
|
|
@ -438,7 +438,7 @@ UsedNameTracker::rewind(RewindToken token)
|
|||
r.front().value().resetToScope(token.scriptId, token.scopeId);
|
||||
}
|
||||
|
||||
FunctionBox::FunctionBox(ExclusiveContext* cx, LifoAlloc& alloc, ObjectBox* traceListHead,
|
||||
FunctionBox::FunctionBox(ExclusiveContext* cx, LifoAlloc& alloc, TraceListNode* traceListHead,
|
||||
JSFunction* fun, uint32_t toStringStart,
|
||||
Directives directives, bool extraWarnings,
|
||||
GeneratorKind generatorKind, FunctionAsyncKind asyncKind)
|
||||
|
|
@ -882,11 +882,11 @@ Parser<FullParseHandler>::setAwaitHandling(AwaitHandling awaitHandling)
|
|||
parser->setAwaitHandling(awaitHandling);
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
ObjectBox*
|
||||
Parser<ParseHandler>::newObjectBox(JSObject* obj)
|
||||
template <typename BoxT, typename ArgT>
|
||||
BoxT*
|
||||
ParserBase::newTraceListNode(ArgT* arg)
|
||||
{
|
||||
MOZ_ASSERT(obj);
|
||||
MOZ_ASSERT(arg);
|
||||
|
||||
/*
|
||||
* We use JSContext.tempLifoAlloc to allocate parsed objects and place them
|
||||
|
|
@ -896,15 +896,27 @@ Parser<ParseHandler>::newObjectBox(JSObject* obj)
|
|||
* function.
|
||||
*/
|
||||
|
||||
ObjectBox* objbox = alloc.new_<ObjectBox>(obj, traceListHead);
|
||||
if (!objbox) {
|
||||
BoxT* box = alloc.template new_<BoxT>(arg, traceListHead);
|
||||
if (!box) {
|
||||
ReportOutOfMemory(context);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
traceListHead = objbox;
|
||||
traceListHead = box;
|
||||
|
||||
return objbox;
|
||||
return box;
|
||||
}
|
||||
|
||||
ObjectBox*
|
||||
ParserBase::newObjectBox(JSObject* obj)
|
||||
{
|
||||
return newTraceListNode<ObjectBox, JSObject>(obj);
|
||||
}
|
||||
|
||||
BigIntBox*
|
||||
ParserBase::newBigIntBox(BigInt* val)
|
||||
{
|
||||
return newTraceListNode<BigIntBox, BigInt>(val);
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
|
|
@ -10579,6 +10591,37 @@ Parser<ParseHandler>::newRegExp()
|
|||
return handler.newRegExp(reobj, pos(), *this);
|
||||
}
|
||||
|
||||
template <>
|
||||
BigIntLiteral*
|
||||
Parser<FullParseHandler>::newBigInt()
|
||||
{
|
||||
// The token's charBuffer contains the DecimalIntegerLiteral or
|
||||
// NumericLiteralBase production, and as such does not include the
|
||||
// BigIntLiteralSuffix (the trailing "n"). Note that NumericLiteralBase
|
||||
// productions may start with 0[bBoOxX], indicating binary/octal/hex.
|
||||
const auto& chars = tokenStream.getTokenbuf();
|
||||
mozilla::Range<const char16_t> source(chars.begin(), chars.length());
|
||||
|
||||
BigInt* b = js::ParseBigIntLiteral(context, source);
|
||||
if (!b) {
|
||||
return null();
|
||||
}
|
||||
|
||||
// newBigInt immediately puts "b" in a BigIntBox, which is allocated using
|
||||
// tempLifoAlloc, avoiding any potential GC. Therefore it's OK to pass a
|
||||
// raw pointer.
|
||||
return handler.newBigInt(b, pos(), *this);
|
||||
}
|
||||
|
||||
template <>
|
||||
SyntaxParseHandler::BigIntLiteralType
|
||||
Parser<SyntaxParseHandler>::newBigInt()
|
||||
{
|
||||
// The tokenizer has already checked the syntax of the bigint.
|
||||
|
||||
return handler.newBigInt();
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
void
|
||||
Parser<ParseHandler>::checkDestructuringAssignmentTarget(Node expr, TokenPos exprPos,
|
||||
|
|
@ -11474,6 +11517,9 @@ Parser<ParseHandler>::primaryExpr(YieldHandling yieldHandling, TripledotHandling
|
|||
case TOK_NUMBER:
|
||||
return newNumber(tokenStream.currentToken());
|
||||
|
||||
case TOK_BIGINT:
|
||||
return newBigInt();
|
||||
|
||||
case TOK_TRUE:
|
||||
return handler.newBooleanLiteral(true, pos());
|
||||
case TOK_FALSE:
|
||||
|
|
|
|||
|
|
@ -779,8 +779,8 @@ class ParserBase : public StrictModeGetter
|
|||
TokenStream tokenStream;
|
||||
LifoAlloc::Mark tempPoolMark;
|
||||
|
||||
/* list of parsed objects for GC tracing */
|
||||
ObjectBox* traceListHead;
|
||||
/* list of parsed objects and BigInts for GC tracing */
|
||||
TraceListNode* traceListHead;
|
||||
|
||||
/* innermost parse context (stack-allocated) */
|
||||
ParseContext* pc;
|
||||
|
|
@ -915,6 +915,13 @@ class ParserBase : public StrictModeGetter
|
|||
bool warnOnceAboutExprClosure();
|
||||
bool warnOnceAboutForEach();
|
||||
|
||||
ObjectBox* newObjectBox(JSObject* obj);
|
||||
BigIntBox* newBigIntBox(BigInt* val);
|
||||
|
||||
private:
|
||||
template <typename BoxT, typename ArgT>
|
||||
BoxT* newTraceListNode(ArgT* arg);
|
||||
|
||||
protected:
|
||||
enum InvokedPrediction { PredictUninvoked = false, PredictInvoked = true };
|
||||
enum ForInitLocation { InForInit, NotInForInit };
|
||||
|
|
@ -1085,7 +1092,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
|
|||
{
|
||||
friend class Parser;
|
||||
LifoAlloc::Mark mark;
|
||||
ObjectBox* traceListHead;
|
||||
TraceListNode* traceListHead;
|
||||
};
|
||||
Mark mark() const {
|
||||
Mark m;
|
||||
|
|
@ -1174,7 +1181,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
|
|||
* Allocate a new parsed object or function container from
|
||||
* cx->tempLifoAlloc.
|
||||
*/
|
||||
ObjectBox* newObjectBox(JSObject* obj);
|
||||
public:
|
||||
FunctionBox* newFunctionBox(FunctionNodeType funNode, JSFunction* fun, uint32_t toStringStart,
|
||||
Directives directives,
|
||||
GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
|
||||
|
|
@ -1660,6 +1667,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
|
|||
const mozilla::Maybe<DeclarationKind>& maybeDecl, ListNodeType literal);
|
||||
ListNodeType arrayInitializer(YieldHandling yieldHandling, PossibleError* possibleError);
|
||||
RegExpLiteralType newRegExp();
|
||||
BigIntLiteralType newBigInt();
|
||||
|
||||
ListNodeType objectLiteral(YieldHandling yieldHandling, PossibleError* possibleError);
|
||||
|
||||
|
|
|
|||
|
|
@ -443,7 +443,7 @@ class FunctionBox : public ObjectBox, public SharedContext
|
|||
|
||||
FunctionContextFlags funCxFlags;
|
||||
|
||||
FunctionBox(ExclusiveContext* cx, LifoAlloc& alloc, ObjectBox* traceListHead, JSFunction* fun,
|
||||
FunctionBox(ExclusiveContext* cx, LifoAlloc& alloc, TraceListNode* traceListHead, JSFunction* fun,
|
||||
uint32_t toStringStart, Directives directives, bool extraWarnings,
|
||||
GeneratorKind generatorKind, FunctionAsyncKind asyncKind);
|
||||
|
||||
|
|
@ -467,7 +467,8 @@ class FunctionBox : public ObjectBox, public SharedContext
|
|||
void initWithEnclosingParseContext(ParseContext* enclosing, FunctionSyntaxKind kind);
|
||||
|
||||
ObjectBox* toObjectBox() override { return this; }
|
||||
JSFunction* function() const { return &object->as<JSFunction>(); }
|
||||
JSFunction* function() const { return &object()->as<JSFunction>(); }
|
||||
void clobberFunction(JSFunction* function) { gcThing = function; }
|
||||
|
||||
Scope* compilationEnclosingScope() const override {
|
||||
// This method is used to distinguish the outermost SharedContext. If
|
||||
|
|
|
|||
|
|
@ -224,6 +224,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
|
|||
}
|
||||
|
||||
NumericLiteralType newNumber(double value, DecimalPoint decimalPoint, const TokenPos& pos) { return NodeGeneric; }
|
||||
BigIntLiteralType newBigInt() { return NodeGeneric; }
|
||||
BooleanLiteralType newBooleanLiteral(bool cond, const TokenPos& pos) { return NodeGeneric; }
|
||||
|
||||
NameNodeType newStringLiteral(JSAtom* atom, const TokenPos& pos) {
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@
|
|||
macro(PRIVATE_NAME, "private identifier") \
|
||||
macro(NUMBER, "numeric literal") \
|
||||
macro(STRING, "string literal") \
|
||||
macro(BIGINT, "bigint literal") \
|
||||
\
|
||||
/* start of template literal with substitutions */ \
|
||||
macro(TEMPLATE_HEAD, "'${'") \
|
||||
|
|
|
|||
|
|
@ -1382,6 +1382,7 @@ TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier)
|
|||
const char16_t* identStart;
|
||||
NameVisibility identVisibility;
|
||||
bool hadUnicodeEscape;
|
||||
bool isBigInt = false;
|
||||
|
||||
// Check if in the middle of a template string. Have to get this out of
|
||||
// the way first.
|
||||
|
|
@ -1619,6 +1620,10 @@ TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier)
|
|||
}
|
||||
} while (true);
|
||||
}
|
||||
if (c == 'n') {
|
||||
isBigInt = true;
|
||||
c = getCharIgnoreEOL();
|
||||
}
|
||||
ungetCharIgnoreEOL(c);
|
||||
|
||||
if (c != EOF) {
|
||||
|
|
@ -1638,6 +1643,16 @@ TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier)
|
|||
}
|
||||
}
|
||||
|
||||
if (isBigInt) {
|
||||
size_t length = userbuf.addressOfNextRawChar() - numStart - 1;
|
||||
tokenbuf.clear();
|
||||
if(!tokenbuf.reserve(length))
|
||||
goto error;
|
||||
tokenbuf.infallibleAppend(numStart, length);
|
||||
tp->type = TOK_BIGINT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
// Unlike identifiers and strings, numbers cannot contain escaped
|
||||
// chars, so we don't need to use tokenbuf. Instead we can just
|
||||
// convert the char16_t characters in userbuf to the numeric value.
|
||||
|
|
@ -1777,6 +1792,10 @@ TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier)
|
|||
hasExp = false;
|
||||
goto decimal_rest;
|
||||
}
|
||||
if (c == 'n') {
|
||||
isBigInt = true;
|
||||
c = getCharIgnoreEOL();
|
||||
}
|
||||
ungetCharIgnoreEOL(c);
|
||||
|
||||
if (c != EOF) {
|
||||
|
|
@ -1796,6 +1815,16 @@ TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier)
|
|||
}
|
||||
}
|
||||
|
||||
if (isBigInt) {
|
||||
size_t length = userbuf.addressOfNextRawChar() - numStart - 1;
|
||||
tokenbuf.clear();
|
||||
if(!tokenbuf.reserve(length))
|
||||
goto error;
|
||||
tokenbuf.infallibleAppend(numStart, length);
|
||||
tp->type = TOK_BIGINT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
double dval;
|
||||
const char16_t* dummy;
|
||||
if (!GetPrefixInteger(cx, numStart, userbuf.addressOfNextRawChar(), radix,
|
||||
|
|
|
|||
|
|
@ -1620,6 +1620,13 @@ BaselineCompiler::emit_JSOP_DOUBLE()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BaselineCompiler::emit_JSOP_BIGINT()
|
||||
{
|
||||
frame.push(script->getConst(GET_UINT32_INDEX(pc)));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BaselineCompiler::emit_JSOP_STRING()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ namespace jit {
|
|||
_(JSOP_UINT16) \
|
||||
_(JSOP_UINT24) \
|
||||
_(JSOP_DOUBLE) \
|
||||
_(JSOP_BIGINT) \
|
||||
_(JSOP_STRING) \
|
||||
_(JSOP_SYMBOL) \
|
||||
_(JSOP_OBJECT) \
|
||||
|
|
|
|||
|
|
@ -1765,6 +1765,7 @@ IonBuilder::inspectOpcode(JSOp op)
|
|||
return jsop_compare(op);
|
||||
|
||||
case JSOP_DOUBLE:
|
||||
case JSOP_BIGINT:
|
||||
pushConstant(info().getConst(pc));
|
||||
return true;
|
||||
|
||||
|
|
|
|||
|
|
@ -1039,6 +1039,9 @@ js::Disassemble1(JSContext* cx, HandleScript script, jsbytecode* pc,
|
|||
break;
|
||||
}
|
||||
|
||||
case JOF_BIGINT:
|
||||
// Fallthrough.
|
||||
|
||||
case JOF_DOUBLE: {
|
||||
RootedValue v(cx, script->getConst(GET_UINT32_INDEX(pc)));
|
||||
JSAutoByteString bytes;
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ enum {
|
|||
JOF_ATOMOBJECT = 19, /* uint16_t constant index + object index */
|
||||
JOF_SCOPE = 20, /* unsigned 32-bit scope index */
|
||||
JOF_ENVCOORD = 21, /* embedded ScopeCoordinate immediate */
|
||||
JOF_BIGINT = 22, /* uint32_t index for BigInt value */
|
||||
JOF_TYPEMASK = 0x001f, /* mask for above immediate types */
|
||||
|
||||
JOF_NAME = 1 << 5, /* name operation */
|
||||
|
|
|
|||
|
|
@ -83,7 +83,8 @@ js::XDRScriptConst(XDRState<mode>* xdr, MutableHandleValue vp)
|
|||
SCRIPT_NULL,
|
||||
SCRIPT_OBJECT,
|
||||
SCRIPT_VOID,
|
||||
SCRIPT_HOLE
|
||||
SCRIPT_HOLE,
|
||||
SCRIPT_BIGINT
|
||||
};
|
||||
|
||||
ConstTag tag;
|
||||
|
|
@ -104,6 +105,8 @@ js::XDRScriptConst(XDRState<mode>* xdr, MutableHandleValue vp)
|
|||
tag = SCRIPT_OBJECT;
|
||||
} else if (vp.isMagic(JS_ELEMENTS_HOLE)) {
|
||||
tag = SCRIPT_HOLE;
|
||||
} else if (vp.isBigInt()) {
|
||||
tag = SCRIPT_BIGINT;
|
||||
} else {
|
||||
MOZ_ASSERT(vp.isUndefined());
|
||||
tag = SCRIPT_VOID;
|
||||
|
|
@ -176,6 +179,20 @@ js::XDRScriptConst(XDRState<mode>* xdr, MutableHandleValue vp)
|
|||
if (mode == XDR_DECODE)
|
||||
vp.setMagic(JS_ELEMENTS_HOLE);
|
||||
break;
|
||||
case SCRIPT_BIGINT: {
|
||||
RootedBigInt bi(cx);
|
||||
if (mode == XDR_ENCODE) {
|
||||
bi = vp.toBigInt();
|
||||
}
|
||||
|
||||
if(!XDRBigInt(xdr, &bi))
|
||||
return false;
|
||||
|
||||
if (mode == XDR_DECODE) {
|
||||
vp.setBigInt(bi);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// Fail in debug, but only soft-fail in release
|
||||
MOZ_ASSERT(false, "Bad XDR value kind");
|
||||
|
|
@ -3418,6 +3435,38 @@ js::detail::CopyScript(JSContext* cx, HandleScript src, HandleScript dst,
|
|||
}
|
||||
}
|
||||
|
||||
/* Constants */
|
||||
|
||||
AutoValueVector consts(cx);
|
||||
if (nconsts != 0) {
|
||||
GCPtrValue* vector = src->consts()->vector;
|
||||
RootedValue val(cx);
|
||||
RootedValue clone(cx);
|
||||
for (unsigned i = 0; i < nconsts; i++) {
|
||||
val = vector[i];
|
||||
if (val.isDouble()) {
|
||||
clone = val;
|
||||
} else if (val.isBigInt()) {
|
||||
if (cx->zone() == val.toBigInt()->zone()) {
|
||||
clone.setBigInt(val.toBigInt());
|
||||
} else {
|
||||
RootedBigInt b(cx, val.toBigInt());
|
||||
BigInt* copy = BigInt::copy(cx, b);
|
||||
if (!copy) {
|
||||
return false;
|
||||
}
|
||||
clone.setBigInt(copy);
|
||||
}
|
||||
} else {
|
||||
MOZ_ASSERT_UNREACHABLE("bad script consts() element");
|
||||
}
|
||||
|
||||
if (!consts.append(clone)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Objects */
|
||||
|
||||
AutoObjectVector objects(cx);
|
||||
|
|
@ -3508,7 +3557,7 @@ js::detail::CopyScript(JSContext* cx, HandleScript src, HandleScript dst,
|
|||
GCPtrValue* vector = Rebase<GCPtrValue>(dst, src, src->consts()->vector);
|
||||
dst->consts()->vector = vector;
|
||||
for (unsigned i = 0; i < nconsts; ++i)
|
||||
MOZ_ASSERT_IF(vector[i].isGCThing(), vector[i].toString()->isAtom());
|
||||
vector[i].init(consts[i]);
|
||||
}
|
||||
if (nobjects != 0) {
|
||||
GCPtrObject* vector = Rebase<GCPtrObject>(dst, src, src->objects()->vector);
|
||||
|
|
|
|||
|
|
@ -1987,6 +1987,8 @@ BigInt* BigInt::rshByAbsolute(ExclusiveContext* cx, HandleBigInt x, HandleBigInt
|
|||
return nullptr;
|
||||
}
|
||||
if (!bitsShift) {
|
||||
// If roundingCanOverflow, manually initialize the overflow digit.
|
||||
result->setDigit(resultLength - 1, 0);
|
||||
for (int i = digitShift; i < length; i++) {
|
||||
result->setDigit(i - digitShift, x->digit(i));
|
||||
}
|
||||
|
|
@ -3144,16 +3146,14 @@ JS::ubi::Node::Size JS::ubi::Concrete<BigInt>::size(
|
|||
return size;
|
||||
}
|
||||
|
||||
#if 0 // Future XDR support
|
||||
template <XDRMode mode>
|
||||
XDRResult js::XDRBigInt(XDRState<mode>* xdr, MutableHandleBigInt bi) {
|
||||
JSContext* cx = xdr->cx();
|
||||
bool js::XDRBigInt(XDRState<mode>* xdr, MutableHandleBigInt bi) {
|
||||
ExclusiveContext* cx = xdr->cx();
|
||||
|
||||
uint8_t sign;
|
||||
uint32_t length;
|
||||
|
||||
if (mode == XDR_ENCODE) {
|
||||
cx->check(bi);
|
||||
sign = static_cast<uint8_t>(bi->isNegative());
|
||||
uint64_t sz = bi->digitLength() * sizeof(BigInt::Digit);
|
||||
// As the maximum source code size is currently UINT32_MAX code units
|
||||
|
|
@ -3165,8 +3165,10 @@ XDRResult js::XDRBigInt(XDRState<mode>* xdr, MutableHandleBigInt bi) {
|
|||
length = static_cast<uint32_t>(sz);
|
||||
}
|
||||
|
||||
MOZ_TRY(xdr->codeUint8(&sign));
|
||||
MOZ_TRY(xdr->codeUint32(&length));
|
||||
if(!xdr->codeUint8(&sign))
|
||||
return false;
|
||||
if(!xdr->codeUint32(&length))
|
||||
return false;
|
||||
|
||||
MOZ_RELEASE_ASSERT(length % sizeof(BigInt::Digit) == 0);
|
||||
uint32_t digitLength = length / sizeof(BigInt::Digit);
|
||||
|
|
@ -3179,7 +3181,8 @@ XDRResult js::XDRBigInt(XDRState<mode>* xdr, MutableHandleBigInt bi) {
|
|||
std::uninitialized_copy_n(bi->digits().Elements(), digitLength, buf.get());
|
||||
}
|
||||
|
||||
MOZ_TRY(xdr->codeBytes(buf.get(), length));
|
||||
if(!xdr->codeBytes(buf.get(), length))
|
||||
return false;
|
||||
|
||||
if (mode == XDR_DECODE) {
|
||||
BigInt* res = BigInt::createUninitialized(cx, digitLength, sign);
|
||||
|
|
@ -3190,12 +3193,10 @@ XDRResult js::XDRBigInt(XDRState<mode>* xdr, MutableHandleBigInt bi) {
|
|||
bi.set(res);
|
||||
}
|
||||
|
||||
return Ok();
|
||||
return true;
|
||||
}
|
||||
|
||||
template XDRResult js::XDRBigInt(XDRState<XDR_ENCODE>* xdr,
|
||||
MutableHandleBigInt bi);
|
||||
template bool js::XDRBigInt(XDRState<XDR_ENCODE>* xdr, MutableHandleBigInt bi);
|
||||
|
||||
template bool js::XDRBigInt(XDRState<XDR_DECODE>* xdr, MutableHandleBigInt bi);
|
||||
|
||||
template XDRResult js::XDRBigInt(XDRState<XDR_DECODE>* xdr,
|
||||
MutableHandleBigInt bi);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@
|
|||
|
||||
namespace JS {
|
||||
|
||||
#if 0 // Future XDR support
|
||||
class BigInt;
|
||||
|
||||
} // namespace JS
|
||||
|
|
@ -34,12 +33,11 @@ class BigInt;
|
|||
namespace js {
|
||||
|
||||
template <XDRMode mode>
|
||||
XDRResult XDRBigInt(XDRState<mode>* xdr, MutableHandle<JS::BigInt*> bi);
|
||||
bool XDRBigInt(XDRState<mode>* xdr, MutableHandle<JS::BigInt*> bi);
|
||||
|
||||
} // namespace js
|
||||
|
||||
namespace JS {
|
||||
#endif
|
||||
|
||||
class BigInt final : public js::gc::TenuredCell {
|
||||
public:
|
||||
|
|
@ -332,11 +330,8 @@ class BigInt final : public js::gc::TenuredCell {
|
|||
|
||||
friend struct JSStructuredCloneReader;
|
||||
friend struct JSStructuredCloneWriter;
|
||||
#if 0 // Future XDR support
|
||||
template <js::XDRMode mode>
|
||||
friend js::XDRResult js::XDRBigInt(js::XDRState<mode>* xdr,
|
||||
MutableHandle<BigInt*> bi);
|
||||
#endif
|
||||
friend bool js::XDRBigInt(js::XDRState<mode>* xdr, MutableHandle<BigInt*> bi);
|
||||
|
||||
BigInt() = delete;
|
||||
BigInt(const BigInt& other) = delete;
|
||||
|
|
|
|||
|
|
@ -4125,6 +4125,13 @@ CASE(JSOP_IS_CONSTRUCTING)
|
|||
PUSH_MAGIC(JS_IS_CONSTRUCTING);
|
||||
END_CASE(JSOP_IS_CONSTRUCTING)
|
||||
|
||||
CASE(JSOP_BIGINT)
|
||||
{
|
||||
PUSH_COPY(script->getConst(GET_UINT32_INDEX(REGS.pc)));
|
||||
MOZ_ASSERT(REGS.sp[-1].isBigInt());
|
||||
}
|
||||
END_CASE(JSOP_BIGINT)
|
||||
|
||||
DEFAULT()
|
||||
{
|
||||
char numBuf[12];
|
||||
|
|
|
|||
|
|
@ -2357,14 +2357,20 @@
|
|||
* Operands:
|
||||
* Stack: arg => rval
|
||||
*/ \
|
||||
macro(JSOP_DYNAMIC_IMPORT, 234, "call-import", NULL, 1, 1, 1, JOF_BYTE)
|
||||
|
||||
macro(JSOP_DYNAMIC_IMPORT, 234, "call-import", NULL, 1, 1, 1, JOF_BYTE) \
|
||||
/*
|
||||
* Pushes a BigInt constant onto the stack.
|
||||
* Category: Literals
|
||||
* Type: Constants
|
||||
* Operands: uint32_t constIndex
|
||||
* Stack: => val
|
||||
*/ \
|
||||
macro(JSOP_BIGINT, 235, "bigint", NULL, 5, 0, 1, JOF_BIGINT)
|
||||
/*
|
||||
* In certain circumstances it may be useful to "pad out" the opcode space to
|
||||
* a power of two. Use this macro to do so.
|
||||
*/
|
||||
#define FOR_EACH_TRAILING_UNUSED_OPCODE(macro) \
|
||||
macro(235) \
|
||||
macro(236) \
|
||||
macro(237) \
|
||||
macro(238) \
|
||||
|
|
|
|||
|
|
@ -8709,7 +8709,7 @@ js::CompileAsmJS(ExclusiveContext* cx, AsmJSParser& parser, ParseNode* stmtList,
|
|||
// generating bytecode for asm.js functions, allowing this asm.js module
|
||||
// function to be the finished result.
|
||||
MOZ_ASSERT(funbox->function()->isInterpreted());
|
||||
funbox->object = moduleFun;
|
||||
funbox->clobberFunction(moduleFun);
|
||||
|
||||
// Success! Write to the console with a "warning" message.
|
||||
*validated = true;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue