Merge remote-tracking branch 'origin/tracking' into custom

This commit is contained in:
roytam1 2023-05-01 06:55:51 +08:00
commit 0a4a1d8a63
32 changed files with 299 additions and 188 deletions

View file

@ -194,6 +194,7 @@ def old_configure_options(*options):
'--enable-ion',
'--enable-ios-target',
'--enable-jitspew',
'--enable-js-lto',
'--enable-libjpeg-turbo',
'--enable-libproxy',
'--enable-llvm-hacks',

View file

@ -128,3 +128,9 @@ else:
'/js/src/ctypes/libffi/src/%s/%s' % (CONFIG['FFI_TARGET_DIR'], s)
for s in sorted(ffi_srcs)
]
# Explicitly enable WPO and LTCG in MSVC if we're doing LTO.
if CONFIG['JS_LTO']:
if CONFIG['_MSC_VER'] and not CONFIG['CLANG_CL']:
CFLAGS += [ '-GL' ]
CXXFLAGS += [ '-GL' ]

View file

@ -484,7 +484,7 @@ FT2FontEntry::ReadCMAP(FontInfoData *aFontInfoData)
// check to see if the cmap includes complex script codepoints
if (charmap->TestRange(sr->rangeStart, sr->rangeEnd)) {
// We check for GSUB here, as GPOS alone would not be ok.
if (hasGSUB && SupportsScriptInGSUB(sr->tags)) {
if (hasGSUB && SupportsScriptInGSUB(sr->tags, sr->numTags)) {
continue;
}
charmap->ClearRange(sr->rangeStart, sr->rangeEnd);

View file

@ -1171,12 +1171,14 @@ gfxFont::CheckForFeaturesInvolvingSpace()
sScriptTagToCode->Put(HB_TAG('D','F','L','T'), Script::COMMON);
for (Script s = Script::ARABIC; s < Script::NUM_SCRIPT_CODES;
s = Script(static_cast<int>(s) + 1)) {
hb_script_t scriptTag = hb_script_t(GetScriptTagForCode(s));
hb_tag_t s1, s2;
hb_ot_tags_from_script(scriptTag, &s1, &s2);
sScriptTagToCode->Put(s1, s);
if (s2 != HB_OT_TAG_DEFAULT_SCRIPT) {
sScriptTagToCode->Put(s2, s);
hb_script_t script = hb_script_t(GetScriptTagForCode(s));
unsigned int scriptCount = 4;
hb_tag_t scriptTags[4];
hb_ot_tags_from_script_and_language(script, HB_LANGUAGE_INVALID,
&scriptCount, scriptTags, nullptr,
nullptr);
for (unsigned int i = 0; i < scriptCount; i++) {
sScriptTagToCode->Put(scriptTags[i], s);
}
}

View file

@ -233,7 +233,9 @@ uint16_t gfxFontEntry::GetUVSGlyph(uint32_t aCh, uint32_t aVS)
return 0;
}
bool gfxFontEntry::SupportsScriptInGSUB(const hb_tag_t* aScriptTags)
bool
gfxFontEntry::SupportsScriptInGSUB(const hb_tag_t* aScriptTags,
uint32_t aNumTags)
{
hb_face_t *face = GetHBFace();
if (!face) {
@ -242,9 +244,9 @@ bool gfxFontEntry::SupportsScriptInGSUB(const hb_tag_t* aScriptTags)
unsigned int index;
hb_tag_t chosenScript;
bool found =
hb_ot_layout_table_choose_script(face, TRUETYPE_TAG('G','S','U','B'),
aScriptTags, &index, &chosenScript);
bool found = hb_ot_layout_table_select_script(
face, TRUETYPE_TAG('G', 'S', 'U', 'B'), aNumTags, aScriptTags, &index,
&chosenScript);
hb_face_destroy(face);
return found && chosenScript != TRUETYPE_TAG('D','F','L','T');
@ -819,27 +821,22 @@ gfxFontEntry::SupportsOpenTypeFeature(Script aScript, uint32_t aFeatureTag)
gfxHarfBuzzShaper::GetHBScriptUsedForShaping(aScript);
// Get the OpenType tag(s) that match this script code
hb_tag_t scriptTags[4] = {
HB_TAG_NONE,
HB_TAG_NONE,
HB_TAG_NONE,
HB_TAG_NONE
};
hb_ot_tags_from_script(hbScript, &scriptTags[0], &scriptTags[1]);
unsigned int scriptCount = 4;
hb_tag_t scriptTags[4];
hb_ot_tags_from_script_and_language(hbScript, HB_LANGUAGE_INVALID,
&scriptCount, scriptTags, nullptr,
nullptr);
// Replace the first remaining NONE with DEFAULT
hb_tag_t* scriptTag = &scriptTags[0];
while (*scriptTag != HB_TAG_NONE) {
++scriptTag;
// Append DEFAULT to the returned tags, if room
if (scriptCount < 4) {
scriptTags[scriptCount++] = HB_OT_TAG_DEFAULT_SCRIPT;
}
*scriptTag = HB_OT_TAG_DEFAULT_SCRIPT;
// Now check for 'smcp' under the first of those scripts that is present
const hb_tag_t kGSUB = HB_TAG('G','S','U','B');
scriptTag = &scriptTags[0];
while (*scriptTag != HB_TAG_NONE) {
for (unsigned int i = 0; i < scriptCount; i++) {
unsigned int scriptIndex;
if (hb_ot_layout_table_find_script(face, kGSUB, *scriptTag,
if (hb_ot_layout_table_find_script(face, kGSUB, scriptTags[i],
&scriptIndex)) {
if (hb_ot_layout_language_find_feature(face, kGSUB,
scriptIndex,
@ -849,7 +846,6 @@ gfxFontEntry::SupportsOpenTypeFeature(Script aScript, uint32_t aFeatureTag)
}
break;
}
++scriptTag;
}
}
@ -886,20 +882,17 @@ gfxFontEntry::InputsForOpenTypeFeature(Script aScript, uint32_t aFeatureTag)
gfxHarfBuzzShaper::GetHBScriptUsedForShaping(aScript);
// Get the OpenType tag(s) that match this script code
hb_tag_t scriptTags[4] = {
HB_TAG_NONE,
HB_TAG_NONE,
HB_TAG_NONE,
HB_TAG_NONE
};
hb_ot_tags_from_script(hbScript, &scriptTags[0], &scriptTags[1]);
unsigned int scriptCount = 4;
hb_tag_t scriptTags[5]; // space for null terminator
hb_ot_tags_from_script_and_language(hbScript, HB_LANGUAGE_INVALID,
&scriptCount, scriptTags, nullptr,
nullptr);
// Replace the first remaining NONE with DEFAULT
hb_tag_t* scriptTag = &scriptTags[0];
while (*scriptTag != HB_TAG_NONE) {
++scriptTag;
// Append DEFAULT to the returned tags, if room
if (scriptCount < 4) {
scriptTags[scriptCount++] = HB_OT_TAG_DEFAULT_SCRIPT;
}
*scriptTag = HB_OT_TAG_DEFAULT_SCRIPT;
scriptTags[scriptCount++] = 0;
const hb_tag_t kGSUB = HB_TAG('G','S','U','B');
hb_tag_t features[2] = { aFeatureTag, HB_TAG_NONE };

View file

@ -320,11 +320,11 @@ public:
struct ScriptRange {
uint32_t rangeStart;
uint32_t rangeEnd;
hb_tag_t tags[3]; // one or two OpenType script tags to check,
// plus a NULL terminator
uint32_t numTags; // number of entries in the tags[] array
hb_tag_t tags[3]; // up to three OpenType script tags to check
};
bool SupportsScriptInGSUB(const hb_tag_t* aScriptTags);
bool SupportsScriptInGSUB(const hb_tag_t* aScriptTags, uint32_t aNumTags);
nsString mName;
nsString mFamilyName;

View file

@ -204,7 +204,7 @@ MacOSFontEntry::ReadCMAP(FontInfoData *aFontInfoData)
}
// We check for GSUB here, as GPOS alone would not be ok.
if (hasGSUB && SupportsScriptInGSUB(sr->tags)) {
if (hasGSUB && SupportsScriptInGSUB(sr->tags, sr->numTags)) {
continue;
}

View file

@ -52,39 +52,39 @@ const gfxFontEntry::ScriptRange gfxPlatformFontList::sComplexScriptRanges[] = {
// want to mask the basic Arabic block here?
// This affects the arabic-fallback-*.html reftests, which rely on
// loading a font that *doesn't* have any GSUB table.
{ 0x0600, 0x06FF, { TRUETYPE_TAG('a','r','a','b'), 0, 0 } },
{ 0x0700, 0x074F, { TRUETYPE_TAG('s','y','r','c'), 0, 0 } },
{ 0x0750, 0x077F, { TRUETYPE_TAG('a','r','a','b'), 0, 0 } },
{ 0x08A0, 0x08FF, { TRUETYPE_TAG('a','r','a','b'), 0, 0 } },
{ 0x0900, 0x097F, { TRUETYPE_TAG('d','e','v','2'),
TRUETYPE_TAG('d','e','v','a'), 0 } },
{ 0x0980, 0x09FF, { TRUETYPE_TAG('b','n','g','2'),
TRUETYPE_TAG('b','e','n','g'), 0 } },
{ 0x0A00, 0x0A7F, { TRUETYPE_TAG('g','u','r','2'),
TRUETYPE_TAG('g','u','r','u'), 0 } },
{ 0x0A80, 0x0AFF, { TRUETYPE_TAG('g','j','r','2'),
TRUETYPE_TAG('g','u','j','r'), 0 } },
{ 0x0B00, 0x0B7F, { TRUETYPE_TAG('o','r','y','2'),
TRUETYPE_TAG('o','r','y','a'), 0 } },
{ 0x0B80, 0x0BFF, { TRUETYPE_TAG('t','m','l','2'),
TRUETYPE_TAG('t','a','m','l'), 0 } },
{ 0x0C00, 0x0C7F, { TRUETYPE_TAG('t','e','l','2'),
TRUETYPE_TAG('t','e','l','u'), 0 } },
{ 0x0C80, 0x0CFF, { TRUETYPE_TAG('k','n','d','2'),
TRUETYPE_TAG('k','n','d','a'), 0 } },
{ 0x0D00, 0x0D7F, { TRUETYPE_TAG('m','l','m','2'),
TRUETYPE_TAG('m','l','y','m'), 0 } },
{ 0x0D80, 0x0DFF, { TRUETYPE_TAG('s','i','n','h'), 0, 0 } },
{ 0x0E80, 0x0EFF, { TRUETYPE_TAG('l','a','o',' '), 0, 0 } },
{ 0x0F00, 0x0FFF, { TRUETYPE_TAG('t','i','b','t'), 0, 0 } },
{ 0x1000, 0x109f, { TRUETYPE_TAG('m','y','m','r'),
TRUETYPE_TAG('m','y','m','2'), 0 } },
{ 0x1780, 0x17ff, { TRUETYPE_TAG('k','h','m','r'), 0, 0 } },
{0x0600, 0x06FF, 1, {TRUETYPE_TAG('a', 'r', 'a', 'b'), 0, 0}},
{0x0700, 0x074F, 1, {TRUETYPE_TAG('s', 'y', 'r', 'c'), 0, 0}},
{0x0750, 0x077F, 1, {TRUETYPE_TAG('a', 'r', 'a', 'b'), 0, 0}},
{0x08A0, 0x08FF, 1, {TRUETYPE_TAG('a', 'r', 'a', 'b'), 0, 0}},
{ 0x0900, 0x097F, 2, { TRUETYPE_TAG('d','e','v','2'),
TRUETYPE_TAG('d','e','v','a'), 0 } },
{ 0x0980, 0x09FF, 2, { TRUETYPE_TAG('b','n','g','2'),
TRUETYPE_TAG('b','e','n','g'), 0 } },
{ 0x0A00, 0x0A7F, 2, { TRUETYPE_TAG('g','u','r','2'),
TRUETYPE_TAG('g','u','r','u'), 0 } },
{ 0x0A80, 0x0AFF, 2, { TRUETYPE_TAG('g','j','r','2'),
TRUETYPE_TAG('g','u','j','r'), 0 } },
{ 0x0B00, 0x0B7F, 2, { TRUETYPE_TAG('o','r','y','2'),
TRUETYPE_TAG('o','r','y','a'), 0 } },
{ 0x0B80, 0x0BFF, 2, { TRUETYPE_TAG('t','m','l','2'),
TRUETYPE_TAG('t','a','m','l'), 0 } },
{ 0x0C00, 0x0C7F, 2, { TRUETYPE_TAG('t','e','l','2'),
TRUETYPE_TAG('t','e','l','u'), 0 } },
{ 0x0C80, 0x0CFF, 2, { TRUETYPE_TAG('k','n','d','2'),
TRUETYPE_TAG('k','n','d','a'), 0 } },
{ 0x0D00, 0x0D7F, 2, { TRUETYPE_TAG('m','l','m','2'),
TRUETYPE_TAG('m','l','y','m'), 0 } },
{0x0D80, 0x0DFF, 1, {TRUETYPE_TAG('s', 'i', 'n', 'h'), 0, 0}},
{0x0E80, 0x0EFF, 1, {TRUETYPE_TAG('l', 'a', 'o', ' '), 0, 0}},
{0x0F00, 0x0FFF, 1, {TRUETYPE_TAG('t', 'i', 'b', 't'), 0, 0}},
{ 0x1000, 0x109f, 2, { TRUETYPE_TAG('m','y','m','r'),
TRUETYPE_TAG('m','y','m','2'), 0 } },
{ 0x1780, 0x17ff, 1, { TRUETYPE_TAG('k','h','m','r'), 0, 0 } },
// Khmer Symbols (19e0..19ff) don't seem to need any special shaping
{ 0xaa60, 0xaa7f, { TRUETYPE_TAG('m','y','m','r'),
TRUETYPE_TAG('m','y','m','2'), 0 } },
{ 0xaa60, 0xaa7f, 2, { TRUETYPE_TAG('m','y','m','r'),
TRUETYPE_TAG('m','y','m','2'), 0 } },
// Thai seems to be "renderable" without AAT morphing tables
{ 0, 0, { 0, 0, 0 } } // terminator
{0, 0, 0, {0, 0, 0}} // terminator
};
// prefs for the font info loader

View file

@ -11,6 +11,7 @@
#include "frontend/SharedContext.h"
#include "gc/Policy.h"
#include "gc/Tracer.h"
#include "vm/SelfHosting.h"
#include "jsobjinlines.h"
#include "jsscriptinlines.h"

View file

@ -3162,7 +3162,7 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
case PNK_OPTDOT:
case PNK_DOT:
{
PropertyAccess* prop = &pn->as<PropertyAccess>();
PropertyAccessBase* prop = &pn->as<PropertyAccessBase>();
MOZ_ASSERT(prop->pn_pos.encloses(prop->expression().pn_pos));
RootedValue expr(cx);

View file

@ -245,7 +245,7 @@ BytecodeEmitter::locationOfNameBoundInFunctionScope(JSAtom* name, EmitterScope*
}
bool
BytecodeEmitter::emitCheck(ptrdiff_t delta, ptrdiff_t* offset)
BytecodeEmitter::emitCheck(JSOp op, ptrdiff_t delta, ptrdiff_t* offset)
{
size_t oldLength = code().length();
*offset = ptrdiff_t(oldLength);
@ -260,6 +260,13 @@ BytecodeEmitter::emitCheck(ptrdiff_t delta, ptrdiff_t* offset)
ReportOutOfMemory(cx);
return false;
}
// If op is JOF_TYPESET (see the type barriers comment in TypeInference.h),
// reserve a type set to store its result.
if (CodeSpec[op].format & JOF_TYPESET) {
if (typesetCount < UINT16_MAX)
typesetCount++;
}
return true;
}
@ -297,7 +304,7 @@ BytecodeEmitter::emit1(JSOp op)
MOZ_ASSERT(checkStrictOrSloppy(op));
ptrdiff_t offset;
if (!emitCheck(1, &offset))
if (!emitCheck(op, 1, &offset))
return false;
jsbytecode* code = this->code(offset);
@ -312,7 +319,7 @@ BytecodeEmitter::emit2(JSOp op, uint8_t op1)
MOZ_ASSERT(checkStrictOrSloppy(op));
ptrdiff_t offset;
if (!emitCheck(2, &offset))
if (!emitCheck(op, 2, &offset))
return false;
jsbytecode* code = this->code(offset);
@ -332,7 +339,7 @@ BytecodeEmitter::emit3(JSOp op, jsbytecode op1, jsbytecode op2)
MOZ_ASSERT(!IsLocalOp(op));
ptrdiff_t offset;
if (!emitCheck(3, &offset))
if (!emitCheck(op, 3, &offset))
return false;
jsbytecode* code = this->code(offset);
@ -350,7 +357,7 @@ BytecodeEmitter::emitN(JSOp op, size_t extra, ptrdiff_t* offset)
ptrdiff_t length = 1 + ptrdiff_t(extra);
ptrdiff_t off;
if (!emitCheck(length, &off))
if (!emitCheck(op, length, &off))
return false;
jsbytecode* code = this->code(off);
@ -391,7 +398,7 @@ bool
BytecodeEmitter::emitJumpNoFallthrough(JSOp op, JumpList* jump)
{
ptrdiff_t offset;
if (!emitCheck(5, &offset))
if (!emitCheck(op, 5, &offset))
return false;
jsbytecode* code = this->code(offset);
@ -634,22 +641,12 @@ BytecodeEmitter::emitLoopEntry(ParseNode* nextpn, JumpList entryJump)
return emit2(JSOP_LOOPENTRY, loopDepthAndFlags);
}
void
BytecodeEmitter::checkTypeSet(JSOp op)
{
if (CodeSpec[op].format & JOF_TYPESET) {
if (typesetCount < UINT16_MAX)
typesetCount++;
}
}
bool
BytecodeEmitter::emitUint16Operand(JSOp op, uint32_t operand)
{
MOZ_ASSERT(operand <= UINT16_MAX);
if (!emit3(op, UINT16_HI(operand), UINT16_LO(operand)))
return false;
checkTypeSet(op);
return true;
}
@ -660,7 +657,6 @@ BytecodeEmitter::emitUint32Operand(JSOp op, uint32_t operand)
if (!emitN(op, 4, &off))
return false;
SET_UINT32(code(off), operand);
checkTypeSet(op);
return true;
}
@ -881,13 +877,12 @@ BytecodeEmitter::emitIndex32(JSOp op, uint32_t index)
MOZ_ASSERT(len == size_t(CodeSpec[op].length));
ptrdiff_t offset;
if (!emitCheck(len, &offset))
if (!emitCheck(op, len, &offset))
return false;
jsbytecode* code = this->code(offset);
code[0] = jsbytecode(op);
SET_UINT32_INDEX(code, index);
checkTypeSet(op);
updateDepth(offset);
return true;
}
@ -901,13 +896,12 @@ BytecodeEmitter::emitIndexOp(JSOp op, uint32_t index)
MOZ_ASSERT(len >= 1 + UINT32_INDEX_LEN);
ptrdiff_t offset;
if (!emitCheck(len, &offset))
if (!emitCheck(op, len, &offset))
return false;
jsbytecode* code = this->code(offset);
code[0] = jsbytecode(op);
SET_UINT32_INDEX(code, index);
checkTypeSet(op);
updateDepth(offset);
return true;
}
@ -1023,7 +1017,6 @@ BytecodeEmitter::emitEnvCoordOp(JSOp op, EnvironmentCoordinate ec)
pc += ENVCOORD_HOPS_LEN;
SET_ENVCOORD_SLOT(pc, ec.slot());
pc += ENVCOORD_SLOT_LEN;
checkTypeSet(op);
return true;
}
@ -1713,7 +1706,7 @@ BytecodeEmitter::emitNewInit(JSProtoKey key)
{
const size_t len = 1 + UINT32_INDEX_LEN;
ptrdiff_t offset;
if (!emitCheck(len, &offset))
if (!emitCheck(JSOP_NEWINIT, len, &offset))
return false;
jsbytecode* code = this->code(offset);
@ -1722,7 +1715,6 @@ BytecodeEmitter::emitNewInit(JSProtoKey key)
code[2] = 0;
code[3] = 0;
code[4] = 0;
checkTypeSet(JSOP_NEWINIT);
updateDepth(offset);
return true;
}
@ -1953,7 +1945,6 @@ BytecodeEmitter::emitElemOpBase(JSOp op)
if (!emit1(op))
return false;
checkTypeSet(op);
return true;
}
@ -2770,7 +2761,6 @@ BytecodeEmitter::emitIteratorNext(ParseNode* pn, IteratorKind iterKind /* = Iter
if (!emitCheckIsObj(CheckIsObjectKind::IteratorNext)) // ... RESULT
return false;
checkTypeSet(JSOP_CALL);
return true;
}
@ -2860,7 +2850,6 @@ BytecodeEmitter::emitIteratorCloseInScope(EmitterScope& currentScope,
if (!emitCall(JSOP_CALL, 0)) // ... ... RESULT
return false;
checkTypeSet(JSOP_CALL);
if (iterKind == IteratorKind::Async) {
if (completionKind != CompletionKind::Throw) {
@ -4496,7 +4485,6 @@ BytecodeEmitter::emitRequireObjectCoercible()
return false;
if (!emitCall(JSOP_CALL_IGNORES_RV, 1))// VAL IGNORED
return false;
checkTypeSet(JSOP_CALL_IGNORES_RV);
if (!emit1(JSOP_POP)) // VAL
return false;
@ -4543,7 +4531,6 @@ BytecodeEmitter::emitCopyDataProperties(CopyOption option)
}
if (!emitCall(JSOP_CALL_IGNORES_RV, argc)) // IGNORED
return false;
checkTypeSet(JSOP_CALL_IGNORES_RV);
if (!emit1(JSOP_POP)) // -
return false;
@ -4566,7 +4553,6 @@ BytecodeEmitter::emitIterator()
return false;
if (!emitCall(JSOP_CALLITER, 0)) // ITER
return false;
checkTypeSet(JSOP_CALLITER);
if (!emitCheckIsObj(CheckIsObjectKind::GetIterator)) // ITER
return false;
return true;
@ -4605,7 +4591,6 @@ BytecodeEmitter::emitAsyncIterator()
return false;
if (!emitCall(JSOP_CALLITER, 0)) // ITER
return false;
checkTypeSet(JSOP_CALLITER);
if (!emitCheckIsObj(CheckIsObjectKind::GetIterator)) // ITER
return false;
@ -4619,7 +4604,6 @@ BytecodeEmitter::emitAsyncIterator()
return false;
if (!emitCall(JSOP_CALLITER, 0)) // ITER
return false;
checkTypeSet(JSOP_CALLITER);
if (!emitCheckIsObj(CheckIsObjectKind::GetIterator)) // ITER
return false;
@ -6425,7 +6409,6 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter)
return false;
if (!emitCall(JSOP_CALL, 1, iter)) // ITER OLDRESULT RESULT
return false;
checkTypeSet(JSOP_CALL);
if (isAsyncGenerator) {
if (!emitAwaitInInnermostScope()) // NEXT ITER OLDRESULT RESULT
@ -6496,7 +6479,6 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter)
return false;
if (!emitCall(JSOP_CALL, 1)) // ITER OLDRESULT FTYPE FVALUE RESULT
return false;
checkTypeSet(JSOP_CALL);
if (iterKind == IteratorKind::Async) {
if (!emitAwaitInInnermostScope()) // ... FTYPE FVALUE RESULT
@ -6577,7 +6559,6 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter)
return false;
if (!emitCall(JSOP_CALL, 1, iter)) // ITER RESULT
return false;
checkTypeSet(JSOP_CALL);
if (isAsyncGenerator) {
if (!emitAwaitInInnermostScope()) // NEXT ITER RESULT RESULT
@ -7039,7 +7020,6 @@ BytecodeEmitter::emitSelfHostedCallFunction(BinaryNode* callNode)
if (!emitCall(callOp, argc))
return false;
checkTypeSet(callOp);
return true;
}
@ -8329,7 +8309,6 @@ BytecodeEmitter::emitFunctionFormalParameters(ListNode* paramsBody)
} else if (isRest) {
if (!emit1(JSOP_REST))
return false;
checkTypeSet(JSOP_REST);
}
// Initialize the parameter name.

View file

@ -418,17 +418,13 @@ struct MOZ_STACK_CLASS BytecodeEmitter
// Emit function code for the tree rooted at body.
MOZ_MUST_USE bool emitFunctionScript(FunctionNode* funNode);
// If op is JOF_TYPESET (see the type barriers comment in TypeInference.h),
// reserve a type set to store its result.
void checkTypeSet(JSOp op);
void updateDepth(ptrdiff_t target);
MOZ_MUST_USE bool updateLineNumberNotes(uint32_t offset);
MOZ_MUST_USE bool updateSourceCoordNotes(uint32_t offset);
JSOp strictifySetNameOp(JSOp op);
MOZ_MUST_USE bool emitCheck(ptrdiff_t delta, ptrdiff_t* offset);
MOZ_MUST_USE bool emitCheck(JSOp op, ptrdiff_t delta, ptrdiff_t* offset);
// Emit one bytecode.
MOZ_MUST_USE bool emit1(JSOp op);

View file

@ -305,7 +305,6 @@ CallOrNewEmitter::emitEnd(uint32_t argc, const Maybe<uint32_t>& beginPos)
return false;
}
}
bce_->checkTypeSet(op_);
if (isEval() && beginPos) {
uint32_t lineNum = bce_->parser->tokenStream.srcCoords.lineNum(*beginPos);

View file

@ -345,8 +345,10 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
return new_<ListNode>(PNK_ARGUMENTS, JSOP_NOP, pos);
}
BinaryNodeType newSuperCall(Node callee, Node args) {
return new_<BinaryNode>(PNK_SUPERCALL, JSOP_SUPERCALL, callee, args);
BinaryNodeType newSuperCall(Node callee, Node args, bool isSpread) {
JSOp op = isSpread ? JSOP_SPREADSUPERCALL : JSOP_SUPERCALL;
TokenPos pos(callee->pn_pos.begin, args->pn_pos.end);
return new_<BinaryNode>(PNK_SUPERCALL, op, pos, callee, args);
}
BinaryNodeType newTaggedTemplate(Node tag, Node args) {

View file

@ -6,6 +6,8 @@
#ifndef frontend_ParseNode_h
#define frontend_ParseNode_h
#include <functional>
#include "mozilla/Attributes.h"
#include "builtin/ModuleObject.h"
@ -1420,6 +1422,8 @@ class ListNode : public ParseNode
}
};
typedef std::function<bool(ParseNode*)> predicate_fun;
#ifdef DEBUG
MOZ_MUST_USE bool contains(ParseNode* target) const {
MOZ_ASSERT(target);
@ -1460,6 +1464,24 @@ class ListNode : public ParseNode
MOZ_ASSERT_IF(end, contains(end));
return range(head(), end);
}
// Predicate functions, like their counterparts in C++17
size_t count_if(predicate_fun predicate) const {
size_t count = 0;
for (ParseNode* node = head(); node; node = node->pn_next) {
if (predicate(node))
count++;
}
return count;
}
bool any_of(predicate_fun predicate) const {
for (ParseNode* node = head(); node; node = node->pn_next) {
if (predicate(node))
return true;
}
return false;
}
};
inline bool

View file

@ -785,7 +785,7 @@ ParserBase::ParserBase(ExclusiveContext* cx, LifoAlloc& alloc,
#endif
abortedSyntaxParse(false),
isUnexpectedEOF_(false),
awaitIsKeyword_(false),
awaitHandling_(AwaitIsName),
parseGoal_(uint8_t(parseGoal))
{
cx->perThreadData->frontendCollectionPool.addActiveCompilation();
@ -846,18 +846,18 @@ Parser<ParseHandler>::~Parser()
template <>
void
Parser<SyntaxParseHandler>::setAwaitIsKeyword(bool isKeyword)
Parser<SyntaxParseHandler>::setAwaitHandling(AwaitHandling awaitHandling)
{
awaitIsKeyword_ = isKeyword;
awaitHandling_ = awaitHandling;
}
template <>
void
Parser<FullParseHandler>::setAwaitIsKeyword(bool isKeyword)
Parser<FullParseHandler>::setAwaitHandling(AwaitHandling awaitHandling)
{
awaitIsKeyword_ = isKeyword;
awaitHandling_ = awaitHandling;
if (Parser<SyntaxParseHandler>* parser = handler.syntaxParser)
parser->setAwaitIsKeyword(isKeyword);
parser->setAwaitHandling(awaitHandling);
}
template <typename ParseHandler>
@ -2219,7 +2219,7 @@ Parser<FullParseHandler>::moduleBody(ModuleSharedContext* modulesc)
if (!moduleNode)
return null();
AutoAwaitIsKeyword<FullParseHandler> awaitIsKeyword(this, true);
AutoAwaitIsKeyword<FullParseHandler> awaitIsKeyword(this, AwaitIsModuleKeyword);
ListNode* stmtList = statementList(YieldIsName);
if (!stmtList) {
return null();
@ -2492,6 +2492,14 @@ GetYieldHandling(GeneratorKind generatorKind)
return YieldIsKeyword;
}
static AwaitHandling
GetAwaitHandling(FunctionAsyncKind asyncKind)
{
if (asyncKind == SyncFunction)
return AwaitIsName;
return AwaitIsKeyword;
}
template <>
FunctionNode*
Parser<FullParseHandler>::standaloneFunction(HandleFunction fun,
@ -2551,7 +2559,8 @@ Parser<FullParseHandler>::standaloneFunction(HandleFunction fun,
funpc.setIsStandaloneFunctionBody();
YieldHandling yieldHandling = GetYieldHandling(generatorKind);
AutoAwaitIsKeyword<FullParseHandler> awaitIsKeyword(this, asyncKind == AsyncFunction);
AwaitHandling awaitHandling = GetAwaitHandling(asyncKind);
AutoAwaitIsKeyword<FullParseHandler> awaitIsKeyword(this, awaitHandling);
if (!functionFormalParametersAndBody(InAllowed, yieldHandling, funNode, FunctionSyntaxKind::Statement,
parameterListEnd, /* isStandaloneFunction = */ true))
{
@ -3643,9 +3652,11 @@ Parser<ParseHandler>::functionFormalParametersAndBody(InHandling inHandling,
// See below for an explanation why arrow function parameters and arrow
// function bodies are parsed with different yield/await settings.
{
bool asyncOrArrowInAsync = funbox->isAsync() ||
(kind == FunctionSyntaxKind::Arrow && awaitIsKeyword());
AutoAwaitIsKeyword<ParseHandler> awaitIsKeyword(this, asyncOrArrowInAsync);
AwaitHandling awaitHandling = funbox->isAsync() ||
(kind == FunctionSyntaxKind::Arrow && awaitIsKeyword())
? AwaitIsKeyword
: AwaitIsName;
AutoAwaitIsKeyword<ParseHandler> awaitIsKeyword(this, awaitHandling);
if (!functionArguments(yieldHandling, kind, funNode))
return false;
}
@ -3715,9 +3726,10 @@ Parser<ParseHandler>::functionFormalParametersAndBody(InHandling inHandling,
// Whereas the |yield| in the function body is always parsed as a name.
// The same goes when parsing |await| in arrow functions.
YieldHandling bodyYieldHandling = GetYieldHandling(pc->generatorKind());
AwaitHandling bodyAwaitHandling = GetAwaitHandling(pc->asyncKind());
LexicalScopeNodeType body;
{
AutoAwaitIsKeyword<ParseHandler> awaitIsKeyword(this, funbox->isAsync());
AutoAwaitIsKeyword<ParseHandler> awaitIsKeyword(this, bodyAwaitHandling);
body = functionBody(inHandling, bodyYieldHandling, kind, bodyType);
if (!body)
return false;
@ -3875,7 +3887,7 @@ Parser<ParseHandler>::functionExpr(uint32_t toStringStart, InvokedPrediction inv
{
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_FUNCTION));
AutoAwaitIsKeyword<ParseHandler> awaitIsKeyword(this, asyncKind == AsyncFunction);
AutoAwaitIsKeyword<ParseHandler> awaitIsKeyword(this, GetAwaitHandling(asyncKind));
GeneratorKind generatorKind = NotGenerator;
TokenKind tt;
if (!tokenStream.getToken(&tt))
@ -9450,13 +9462,10 @@ Parser<ParseHandler>::memberExpr(YieldHandling yieldHandling, TripledotHandling
if (!args)
return null();
nextMember = handler.newSuperCall(lhs, args);
nextMember = handler.newSuperCall(lhs, args, isSpread);
if (!nextMember)
return null();
if (isSpread)
handler.setOp(nextMember, JSOP_SPREADSUPERCALL);
NameNodeType thisName = newThisName();
if (!thisName)
return null();
@ -10626,7 +10635,7 @@ Parser<ParseHandler>::importExpr(YieldHandling yieldHandling, bool allowCallSynt
return handler.newCallImport(importHolder, arg);
} else {
error(JSMSG_UNEXPECTED_TOKEN, TokenKindToDesc(next));
error(JSMSG_UNEXPECTED_TOKEN_NO_EXPECT, TokenKindToDesc(next));
return null();
}
}

View file

@ -591,6 +591,7 @@ enum class PropertyType {
// we're in a function box -- easier and simpler than passing an extra
// parameter everywhere.
enum YieldHandling { YieldIsName, YieldIsKeyword };
enum AwaitHandling : uint8_t { AwaitIsName, AwaitIsKeyword, AwaitIsModuleKeyword };
enum InHandling { InAllowed, InProhibited };
enum DefaultHandling { NameRequired, AllowDefaultName };
enum TripledotHandling { TripledotAllowed, TripledotProhibited };
@ -800,13 +801,13 @@ class ParserBase : public StrictModeGetter
/* Unexpected end of input, i.e. TOK_EOF not at top-level. */
bool isUnexpectedEOF_:1;
bool awaitIsKeyword_:1;
/* AwaitHandling */ uint8_t awaitHandling_:2;
uint8_t parseGoal_:1;
public:
bool awaitIsKeyword() const {
return awaitIsKeyword_;
return awaitHandling_ != AwaitIsName;
}
ParseGoal parseGoal() const {
@ -1058,7 +1059,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
~Parser();
friend class AutoAwaitIsKeyword<ParseHandler>;
void setAwaitIsKeyword(bool isKeyword);
void setAwaitHandling(AwaitHandling awaitHandling);
bool checkOptions();
@ -1643,17 +1644,21 @@ class MOZ_STACK_CLASS AutoAwaitIsKeyword
{
private:
Parser<ParseHandler>* parser_;
bool oldAwaitIsKeyword_;
AwaitHandling oldAwaitHandling_;
public:
AutoAwaitIsKeyword(Parser<ParseHandler>* parser, bool awaitIsKeyword) {
AutoAwaitIsKeyword(Parser<ParseHandler>* parser, AwaitHandling awaitHandling) {
parser_ = parser;
oldAwaitIsKeyword_ = parser_->awaitIsKeyword_;
parser_->setAwaitIsKeyword(awaitIsKeyword);
oldAwaitHandling_ = static_cast<AwaitHandling>(parser_->awaitHandling_);
// 'await' is always a keyword in module contexts, so we don't modify
// the state when the original handling is AwaitIsModuleKeyword.
if (oldAwaitHandling_ != AwaitIsModuleKeyword)
parser_->setAwaitHandling(awaitHandling);
}
~AutoAwaitIsKeyword() {
parser_->setAwaitIsKeyword(oldAwaitIsKeyword_);
parser_->setAwaitHandling(oldAwaitHandling_);
}
};

View file

@ -307,7 +307,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
BinaryNodeType newCall(Node callee, Node args) { return NodeFunctionCall; }
BinaryNodeType newOptionalCall(Node callee, Node args) { return NodeOptionalFunctionCall; }
ListNodeType newArguments(const TokenPos& pos) { return NodeGeneric; }
BinaryNodeType newSuperCall(Node callee, Node args) { return NodeGeneric; }
BinaryNodeType newSuperCall(Node callee, Node args, bool isSpread) { return NodeGeneric; }
BinaryNodeType newTaggedTemplate(Node callee, Node args) { return NodeGeneric; }
Node newGenExp(Node callee, Node args) { return NodeGeneric; }

View file

@ -4584,7 +4584,7 @@ DoSetPropFallback(JSContext* cx, BaselineFrame* frame, ICSetProp_Fallback* stub_
op == JSOP_INITLOCKEDPROP ||
op == JSOP_INITHIDDENPROP)
{
if (!InitPropertyOperation(cx, op, obj, id, rhs))
if (!InitPropertyOperation(cx, op, obj, name, rhs))
return false;
} else if (op == JSOP_SETNAME ||
op == JSOP_STRICTSETNAME ||

View file

@ -4443,7 +4443,7 @@ IonBuilder::jsop_logical(JSOp op)
MIsNullOrUndefined* isNullOrUndefined =
MIsNullOrUndefined::New(alloc(), lhs);
current->add(isNullOrUndefined);
test = newTest(isNullOrUndefined, evalLhs, evalRhs);
test = newTest(isNullOrUndefined, evalRhs, evalLhs);
break;
}

View file

@ -232,8 +232,7 @@ bool
InitProp(JSContext* cx, HandleObject obj, HandlePropertyName name, HandleValue value,
jsbytecode* pc)
{
RootedId id(cx, NameToId(name));
return InitPropertyOperation(cx, JSOp(*pc), obj, id, value);
return InitPropertyOperation(cx, JSOp(*pc), obj, name, value);
}
template<bool Equal>

View file

@ -339,6 +339,7 @@ MSG_DEF(JSMSG_TOO_MANY_LOCALS, 0, JSEXN_SYNTAXERR, "too many local varia
MSG_DEF(JSMSG_TOO_MANY_YIELDS, 0, JSEXN_SYNTAXERR, "too many yield expressions")
MSG_DEF(JSMSG_TOUGH_BREAK, 0, JSEXN_SYNTAXERR, "unlabeled break must be inside loop or switch")
MSG_DEF(JSMSG_UNEXPECTED_TOKEN, 2, JSEXN_SYNTAXERR, "expected {0}, got {1}")
MSG_DEF(JSMSG_UNEXPECTED_TOKEN_NO_EXPECT, 1, JSEXN_SYNTAXERR, "unexpected token: {0}")
MSG_DEF(JSMSG_UNEXPECTED_PARAMLIST_END,0, JSEXN_SYNTAXERR, "unexpected end of function parameter list")
MSG_DEF(JSMSG_UNNAMED_CLASS_STMT, 0, JSEXN_SYNTAXERR, "class statement requires a name")
MSG_DEF(JSMSG_UNNAMED_FUNCTION_STMT, 0, JSEXN_SYNTAXERR, "function statement requires a name")

View file

@ -7,8 +7,6 @@ include('js-config.mozbuild')
include('js-cxxflags.mozbuild')
include('js-testing.mozbuild')
FILES_PER_UNIFIED_FILE = 6
if CONFIG['JS_BUNDLED_EDITLINE']:
DIRS += ['editline']
@ -111,7 +109,7 @@ EXPORTS.js += [
'../public/WeakMapPtr.h',
]
UNIFIED_SOURCES += [
main_deunified_sources = [
'builtin/AtomicsObject.cpp',
'builtin/Eval.cpp',
'builtin/intl/Collator.cpp',
@ -388,7 +386,7 @@ SOURCES += [
]
if CONFIG['JS_POSIX_NSPR']:
UNIFIED_SOURCES += [
posix_nspr_deunified_sources = [
'vm/PosixNSPR.cpp',
]
@ -405,26 +403,24 @@ if CONFIG['ENABLE_TRACE_LOGGING']:
]
if not CONFIG['ENABLE_ION']:
UNIFIED_SOURCES += [
jit_ioncheck1_deunified_sources = [
'jit/none/Trampoline-none.cpp'
]
elif CONFIG['JS_CODEGEN_X86'] or CONFIG['JS_CODEGEN_X64']:
UNIFIED_SOURCES += [
jit_ioncheck1_deunified_sources = [
'jit/x86-shared/Architecture-x86-shared.cpp',
'jit/x86-shared/Assembler-x86-shared.cpp',
'jit/x86-shared/AssemblerBuffer-x86-shared.cpp',
'jit/x86-shared/BaselineCompiler-x86-shared.cpp',
'jit/x86-shared/BaselineIC-x86-shared.cpp',
'jit/x86-shared/CodeGenerator-x86-shared.cpp',
'jit/x86-shared/Disassembler-x86-shared.cpp', # using namespace js::jit::X86Encoding;
'jit/x86-shared/Lowering-x86-shared.cpp',
'jit/x86-shared/MacroAssembler-x86-shared.cpp',
'jit/x86-shared/MoveEmitter-x86-shared.cpp',
]
UNIFIED_SOURCES += [
'jit/x86-shared/Disassembler-x86-shared.cpp', # using namespace js::jit::X86Encoding;
]
if CONFIG['JS_CODEGEN_X64']:
UNIFIED_SOURCES += [
jit_ioncheck2_deunified_sources = [
'jit/x64/Assembler-x64.cpp',
'jit/x64/Bailouts-x64.cpp',
'jit/x64/BaselineCompiler-x64.cpp',
@ -436,7 +432,7 @@ elif CONFIG['JS_CODEGEN_X86'] or CONFIG['JS_CODEGEN_X64']:
'jit/x64/Trampoline-x64.cpp',
]
else:
UNIFIED_SOURCES += [
jit_ioncheck2_deunified_sources = [
'jit/x86/Assembler-x86.cpp',
'jit/x86/Bailouts-x86.cpp',
'jit/x86/BaselineCompiler-x86.cpp',
@ -448,7 +444,7 @@ elif CONFIG['JS_CODEGEN_X86'] or CONFIG['JS_CODEGEN_X64']:
'jit/x86/Trampoline-x86.cpp',
]
elif CONFIG['JS_CODEGEN_ARM']:
UNIFIED_SOURCES += [
jit_ioncheck1_deunified_sources = [
'jit/arm/Architecture-arm.cpp',
'jit/arm/Assembler-arm.cpp',
'jit/arm/Bailouts-arm.cpp',
@ -464,16 +460,16 @@ elif CONFIG['JS_CODEGEN_ARM']:
'jit/arm/Trampoline-arm.cpp',
]
if CONFIG['JS_SIMULATOR_ARM']:
UNIFIED_SOURCES += [
jit_ioncheck2_deunified_sources = [
'jit/arm/Simulator-arm.cpp'
]
elif CONFIG['OS_ARCH'] == 'Darwin':
UNIFIED_SOURCES += [
jit_ioncheck2_deunified_sources = [
'jit/arm/llvm-compiler-rt/arm/aeabi_idivmod.S',
'jit/arm/llvm-compiler-rt/arm/aeabi_uidivmod.S',
]
elif CONFIG['JS_CODEGEN_ARM64']:
UNIFIED_SOURCES += [
jit_ioncheck1_deunified_sources = [
'jit/arm64/Architecture-arm64.cpp',
'jit/arm64/Assembler-arm64.cpp',
'jit/arm64/Bailouts-arm64.cpp',
@ -496,14 +492,14 @@ elif CONFIG['JS_CODEGEN_ARM64']:
'jit/arm64/vixl/Utils-vixl.cpp'
]
if CONFIG['JS_SIMULATOR_ARM64']:
UNIFIED_SOURCES += [
jit_ioncheck2_deunified_sources = [
'jit/arm64/vixl/Debugger-vixl.cpp',
'jit/arm64/vixl/Logic-vixl.cpp',
'jit/arm64/vixl/MozSimulator-vixl.cpp',
'jit/arm64/vixl/Simulator-vixl.cpp'
]
elif CONFIG['JS_CODEGEN_MIPS32'] or CONFIG['JS_CODEGEN_MIPS64']:
UNIFIED_SOURCES += [
jit_ioncheck1_deunified_sources = [
'jit/mips-shared/Architecture-mips-shared.cpp',
'jit/mips-shared/Assembler-mips-shared.cpp',
'jit/mips-shared/Bailouts-mips-shared.cpp',
@ -515,7 +511,7 @@ elif CONFIG['JS_CODEGEN_MIPS32'] or CONFIG['JS_CODEGEN_MIPS64']:
'jit/mips-shared/MoveEmitter-mips-shared.cpp',
]
if CONFIG['JS_CODEGEN_MIPS32']:
UNIFIED_SOURCES += [
jit_ioncheck2_deunified_sources = [
'jit/mips32/Architecture-mips32.cpp',
'jit/mips32/Assembler-mips32.cpp',
'jit/mips32/Bailouts-mips32.cpp',
@ -529,11 +525,11 @@ elif CONFIG['JS_CODEGEN_MIPS32'] or CONFIG['JS_CODEGEN_MIPS64']:
'jit/mips32/Trampoline-mips32.cpp',
]
if CONFIG['JS_SIMULATOR_MIPS32']:
UNIFIED_SOURCES += [
jit_ioncheck3_deunified_sources = [
'jit/mips32/Simulator-mips32.cpp'
]
elif CONFIG['JS_CODEGEN_MIPS64']:
UNIFIED_SOURCES += [
jit_ioncheck2_deunified_sources = [
'jit/mips64/Architecture-mips64.cpp',
'jit/mips64/Assembler-mips64.cpp',
'jit/mips64/Bailouts-mips64.cpp',
@ -547,7 +543,7 @@ elif CONFIG['JS_CODEGEN_MIPS32'] or CONFIG['JS_CODEGEN_MIPS64']:
'jit/mips64/Trampoline-mips64.cpp',
]
if CONFIG['JS_SIMULATOR_MIPS64']:
UNIFIED_SOURCES += [
jit_ioncheck3_deunified_sources = [
'jit/mips64/Simulator-mips64.cpp'
]
@ -627,6 +623,33 @@ else:
'icuuc',
]
# Explicitly enable WPO and LTCG in MSVC, and deunify sources if
# we're doing LTO
if CONFIG['JS_LTO']:
if CONFIG['_MSC_VER'] and not CONFIG['CLANG_CL']:
CFLAGS += [ '-GL' ]
CXXFLAGS += [ '-GL' ]
if CONFIG['JS_SHARED_LIBRARY']:
LDFLAGS += [ '/LTCG' ]
SOURCES += main_deunified_sources
if CONFIG['JS_POSIX_NSPR']:
SOURCES += posix_nspr_deunified_sources
SOURCES += jit_ioncheck1_deunified_sources
if CONFIG['ENABLE_ION']:
SOURCES += jit_ioncheck2_deunified_sources
if CONFIG['JS_CODEGEN_MIPS32'] or CONFIG['JS_CODEGEN_MIPS64']:
SOURCES += jit_ioncheck3_deunified_sources
else:
FILES_PER_UNIFIED_FILE = 6
UNIFIED_SOURCES += main_deunified_sources
if CONFIG['JS_POSIX_NSPR']:
UNIFIED_SOURCES += posix_nspr_deunified_sources
UNIFIED_SOURCES += jit_ioncheck1_deunified_sources
if CONFIG['ENABLE_ION']:
UNIFIED_SOURCES += jit_ioncheck2_deunified_sources
if CONFIG['JS_CODEGEN_MIPS32'] or CONFIG['JS_CODEGEN_MIPS64']:
UNIFIED_SOURCES += jit_ioncheck3_deunified_sources
USE_LIBS += [
'nspr',
'zlib',

View file

@ -584,6 +584,26 @@ esac
MOZ_DOING_LTO(lto_is_enabled)
dnl ========================================================
dnl Spidermonkey link-time optimization support
dnl ========================================================
# We want LTO enabled by default in Spidermonkey if we're building it shared.
if test -n "$JS_SHARED_LIBRARY"; then
JS_LTO=1
fi
MOZ_ARG_DISABLE_BOOL(js-lto,
[ --disable-js-lto Disable link-time optimization for the Spidermonkey library],
JS_LTO=,
JS_LTO=1)
if test -n "$JS_LTO"; then
AC_DEFINE(JS_LTO)
fi
AC_SUBST(JS_LTO)
dnl ========================================================
dnl System overrides of the defaults for target
dnl ========================================================

View file

@ -179,6 +179,8 @@ GeneratorObject::resume(JSContext* cx, InterpreterActivation& activation,
{
Rooted<GeneratorObject*> genObj(cx, &obj->as<GeneratorObject>());
MOZ_ASSERT(genObj->isSuspended());
// See comment in InterpreterStack::resumeGeneratorCallFrame
MOZ_ASSERT_IF(genObj->isConstructing(), genObj->is<LegacyGeneratorObject>());
RootedFunction callee(cx, &genObj->callee());
RootedValue newTarget(cx, genObj->newTarget());

View file

@ -340,12 +340,15 @@ InitGlobalLexicalOperation(JSContext* cx, LexicalEnvironmentObject* lexicalEnvAr
}
inline bool
InitPropertyOperation(JSContext* cx, JSOp op, HandleObject obj, HandleId id, HandleValue rhs)
InitPropertyOperation(JSContext* cx, JSOp op, HandleObject obj, HandlePropertyName name, HandleValue rhs)
{
if (obj->is<PlainObject>() || obj->is<JSFunction>()) {
RootedId id(cx, NameToId(name));
// {Goanna} DefineProperty works on almost any JSObject, but there's no good way to check what works
// So instead, check what we don't handle explicitly.
if (!obj->is<UnboxedPlainObject>()) {
unsigned propAttrs = GetInitDataPropAttrs(op);
return NativeDefineProperty(cx, obj.as<NativeObject>(), id, rhs, nullptr, nullptr,
propAttrs);
return DefineProperty(cx, obj, id, rhs, nullptr, nullptr, propAttrs);
}
MOZ_ASSERT(obj->as<UnboxedPlainObject>().layout().lookup(id));

View file

@ -3744,12 +3744,9 @@ CASE(JSOP_INITHIDDENPROP)
/* Load the object being initialized into lval/obj. */
ReservedRooted<JSObject*> obj(&rootObject0, &REGS.sp[-2].toObject());
PropertyName* name = script->getName(REGS.pc);
ReservedRooted<PropertyName*> name(&rootName0, script->getName(REGS.pc));
RootedId& id = rootId0;
id = NameToId(name);
if (!InitPropertyOperation(cx, JSOp(*REGS.pc), obj, id, rval))
if (!InitPropertyOperation(cx, JSOp(*REGS.pc), obj, name, rval))
goto error;
REGS.sp--;

View file

@ -994,11 +994,33 @@ RegExpShared::initializeNamedCaptures(JSContext* cx, HandleRegExpShared re,
irregexp::CharacterVectorVector* names,
irregexp::IntegerVector* indices)
{
MOZ_ASSERT(!re->groupsTemplate_);
MOZ_ASSERT(names);
MOZ_ASSERT(indices);
MOZ_ASSERT(names->length() == indices->length());
if (re->getGroupsTemplate()) {
// If initializeNamedCaptures was previously called for a different CompilationMode/Latin1Chars combination,
// the template object is already created and correct.
#ifdef DEBUG
// In debug builds, verify that.
MOZ_ASSERT(re->getGroupsTemplate()->propertyCount() == names->length());
RootedId id(cx);
RootedNativeObject groupsTemplate(cx, re->getGroupsTemplate());
Rooted<PropertyDescriptor> desc(cx);
for (uint32_t i = 0; i < names->length(); i++) {
irregexp::CharacterVector* cv = (*names)[i];
JSAtom* atom = AtomizeChars(cx, cv->begin(), cv->length());
MOZ_ASSERT(atom);
id = NameToId(atom->asPropertyName());
MOZ_ASSERT(NativeGetOwnPropertyDescriptor(cx, groupsTemplate, id, &desc));
int32_t idx;
MOZ_ASSERT(ToInt32(cx, desc.value(), &idx));
MOZ_ASSERT(idx == (*indices)[i]);
}
#endif
return true;
}
// The irregexp parser returns named capture information in the form
// of two arrays. We create a template object with a property for each
// capture name, and store the capture index as Integer in the corresponding value.
@ -1025,7 +1047,7 @@ RegExpShared::initializeNamedCaptures(JSContext* cx, HandleRegExpShared re,
// Need to explicitly create an Atom (not a String) or it won't get added to the atom table
JSAtom* atom = AtomizeChars(cx, cv->begin(), cv->length());
if (!atom) {
return false;
return false;
}
id = NameToId(atom->asPropertyName());
RootedValue idx(cx, Int32Value((*indices)[i]));

View file

@ -351,7 +351,10 @@ InterpreterStack::resumeGeneratorCallFrame(JSContext* cx, InterpreterRegs& regs,
constructing = MaybeConstruct(newTarget.isObject());
MOZ_ASSERT_IF(constructing, callee->isConstructor());
} else {
MOZ_ASSERT(!callee->isConstructor());
// We should really be doing MOZ_ASSERT(!callee->isConstructor()) here.
// However, the GeneratorObject only stores the callee as-is, which in the case of a lambda generator
// (i.e. a |new GeneratorFunction(...)| or derieved generator class) is still flagged as a constructor.
// Instead, we check for the correct state in GeneratorObject::resume.
}
// Include callee, |this|, and maybe |new.target|

View file

@ -640,9 +640,9 @@ hb_ot_layout_language_get_feature_tags
hb_ot_layout_language_get_required_feature_index
hb_ot_layout_lookup_collect_glyphs
hb_ot_layout_script_get_language_tags
hb_ot_layout_table_choose_script
hb_ot_layout_table_find_script
hb_ot_layout_table_get_script_tags
hb_ot_layout_table_select_script
hb_ot_math_get_constant
hb_ot_math_get_glyph_assembly
hb_ot_math_get_glyph_italics_correction
@ -650,7 +650,7 @@ hb_ot_math_get_glyph_variants
hb_ot_math_has_data
hb_ot_tag_to_language
hb_ot_tag_to_script
hb_ot_tags_from_script
hb_ot_tags_from_script_and_language
hb_set_add
hb_set_clear
hb_set_create

View file

@ -38,6 +38,12 @@ if CONFIG['CC_TYPE'] == 'clang-cl':
'-Wno-sign-compare', # signed/unsigned mismatch
]
# Explicitly enable WPO and LTCG in MSVC if we're doing LTO.
if CONFIG['JS_LTO']:
if CONFIG['_MSC_VER'] and not CONFIG['CLANG_CL']:
CFLAGS += [ '-GL' ]
CXXFLAGS += [ '-GL' ]
SOURCES += [
'e_acos.cpp',
'e_acosh.cpp',

View file

@ -768,6 +768,26 @@ AC_SUBST(MOZILLA_UAVERSION_U)
MOZ_DOING_LTO(lto_is_enabled)
dnl ========================================================
dnl Spidermonkey link-time optimization support
dnl ========================================================
# We want LTO enabled by default in Spidermonkey if we're building it shared.
if test -n "$JS_SHARED_LIBRARY"; then
JS_LTO=1
fi
MOZ_ARG_DISABLE_BOOL(js-lto,
[ --disable-js-lto Disable link-time optimization for the Spidermonkey library],
JS_LTO=,
JS_LTO=1)
if test -n "$JS_LTO"; then
AC_DEFINE(JS_LTO)
fi
AC_SUBST(JS_LTO)
dnl ========================================================
dnl System overrides of the defaults for target
dnl ========================================================