diff --git a/build/moz.configure/old.configure b/build/moz.configure/old.configure index fa08574833..40656f42dc 100644 --- a/build/moz.configure/old.configure +++ b/build/moz.configure/old.configure @@ -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', diff --git a/config/external/ffi/moz.build b/config/external/ffi/moz.build index 168f28c0bf..8710ebab7a 100644 --- a/config/external/ffi/moz.build +++ b/config/external/ffi/moz.build @@ -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' ] diff --git a/gfx/thebes/gfxFT2FontList.cpp b/gfx/thebes/gfxFT2FontList.cpp index b032be13dc..93603f5167 100644 --- a/gfx/thebes/gfxFT2FontList.cpp +++ b/gfx/thebes/gfxFT2FontList.cpp @@ -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); diff --git a/gfx/thebes/gfxFont.cpp b/gfx/thebes/gfxFont.cpp index 8ac64bc1b4..3857c4cd38 100644 --- a/gfx/thebes/gfxFont.cpp +++ b/gfx/thebes/gfxFont.cpp @@ -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(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); } } diff --git a/gfx/thebes/gfxFontEntry.cpp b/gfx/thebes/gfxFontEntry.cpp index 90c0bc8585..765332aef5 100644 --- a/gfx/thebes/gfxFontEntry.cpp +++ b/gfx/thebes/gfxFontEntry.cpp @@ -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 }; diff --git a/gfx/thebes/gfxFontEntry.h b/gfx/thebes/gfxFontEntry.h index 7f0e7215be..77346f3ea3 100644 --- a/gfx/thebes/gfxFontEntry.h +++ b/gfx/thebes/gfxFontEntry.h @@ -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; diff --git a/gfx/thebes/gfxMacPlatformFontList.mm b/gfx/thebes/gfxMacPlatformFontList.mm index 55263e7e6b..375d307230 100644 --- a/gfx/thebes/gfxMacPlatformFontList.mm +++ b/gfx/thebes/gfxMacPlatformFontList.mm @@ -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; } diff --git a/gfx/thebes/gfxPlatformFontList.cpp b/gfx/thebes/gfxPlatformFontList.cpp index 5f7bbb832f..1a4a72cb5a 100644 --- a/gfx/thebes/gfxPlatformFontList.cpp +++ b/gfx/thebes/gfxPlatformFontList.cpp @@ -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 diff --git a/js/src/builtin/ModuleObject.cpp b/js/src/builtin/ModuleObject.cpp index 8e01ea2ac8..194959cf31 100644 --- a/js/src/builtin/ModuleObject.cpp +++ b/js/src/builtin/ModuleObject.cpp @@ -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" diff --git a/js/src/builtin/ReflectParse.cpp b/js/src/builtin/ReflectParse.cpp index 91bef98884..4aa7f1640b 100644 --- a/js/src/builtin/ReflectParse.cpp +++ b/js/src/builtin/ReflectParse.cpp @@ -3162,7 +3162,7 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) case PNK_OPTDOT: case PNK_DOT: { - PropertyAccess* prop = &pn->as(); + PropertyAccessBase* prop = &pn->as(); MOZ_ASSERT(prop->pn_pos.encloses(prop->expression().pn_pos)); RootedValue expr(cx); diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index 78b134cf58..51ebd81969 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -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. diff --git a/js/src/frontend/BytecodeEmitter.h b/js/src/frontend/BytecodeEmitter.h index 7a59cf0825..9cbf6ee38b 100644 --- a/js/src/frontend/BytecodeEmitter.h +++ b/js/src/frontend/BytecodeEmitter.h @@ -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); diff --git a/js/src/frontend/CallOrNewEmitter.cpp b/js/src/frontend/CallOrNewEmitter.cpp index bd1e32ab02..81e1956c25 100644 --- a/js/src/frontend/CallOrNewEmitter.cpp +++ b/js/src/frontend/CallOrNewEmitter.cpp @@ -305,7 +305,6 @@ CallOrNewEmitter::emitEnd(uint32_t argc, const Maybe& beginPos) return false; } } - bce_->checkTypeSet(op_); if (isEval() && beginPos) { uint32_t lineNum = bce_->parser->tokenStream.srcCoords.lineNum(*beginPos); diff --git a/js/src/frontend/FullParseHandler.h b/js/src/frontend/FullParseHandler.h index 173ffcb8d7..a9f7c6de09 100644 --- a/js/src/frontend/FullParseHandler.h +++ b/js/src/frontend/FullParseHandler.h @@ -345,8 +345,10 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return new_(PNK_ARGUMENTS, JSOP_NOP, pos); } - BinaryNodeType newSuperCall(Node callee, Node args) { - return new_(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_(PNK_SUPERCALL, op, pos, callee, args); } BinaryNodeType newTaggedTemplate(Node tag, Node args) { diff --git a/js/src/frontend/ParseNode.h b/js/src/frontend/ParseNode.h index 54d2bef108..2f6311eace 100644 --- a/js/src/frontend/ParseNode.h +++ b/js/src/frontend/ParseNode.h @@ -6,6 +6,8 @@ #ifndef frontend_ParseNode_h #define frontend_ParseNode_h +#include + #include "mozilla/Attributes.h" #include "builtin/ModuleObject.h" @@ -1420,6 +1422,8 @@ class ListNode : public ParseNode } }; + typedef std::function 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 diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 97b11ae248..1120359705 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -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::~Parser() template <> void -Parser::setAwaitIsKeyword(bool isKeyword) +Parser::setAwaitHandling(AwaitHandling awaitHandling) { - awaitIsKeyword_ = isKeyword; + awaitHandling_ = awaitHandling; } template <> void -Parser::setAwaitIsKeyword(bool isKeyword) +Parser::setAwaitHandling(AwaitHandling awaitHandling) { - awaitIsKeyword_ = isKeyword; + awaitHandling_ = awaitHandling; if (Parser* parser = handler.syntaxParser) - parser->setAwaitIsKeyword(isKeyword); + parser->setAwaitHandling(awaitHandling); } template @@ -2219,7 +2219,7 @@ Parser::moduleBody(ModuleSharedContext* modulesc) if (!moduleNode) return null(); - AutoAwaitIsKeyword awaitIsKeyword(this, true); + AutoAwaitIsKeyword 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::standaloneFunction(HandleFunction fun, @@ -2551,7 +2559,8 @@ Parser::standaloneFunction(HandleFunction fun, funpc.setIsStandaloneFunctionBody(); YieldHandling yieldHandling = GetYieldHandling(generatorKind); - AutoAwaitIsKeyword awaitIsKeyword(this, asyncKind == AsyncFunction); + AwaitHandling awaitHandling = GetAwaitHandling(asyncKind); + AutoAwaitIsKeyword awaitIsKeyword(this, awaitHandling); if (!functionFormalParametersAndBody(InAllowed, yieldHandling, funNode, FunctionSyntaxKind::Statement, parameterListEnd, /* isStandaloneFunction = */ true)) { @@ -3643,9 +3652,11 @@ Parser::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 awaitIsKeyword(this, asyncOrArrowInAsync); + AwaitHandling awaitHandling = funbox->isAsync() || + (kind == FunctionSyntaxKind::Arrow && awaitIsKeyword()) + ? AwaitIsKeyword + : AwaitIsName; + AutoAwaitIsKeyword awaitIsKeyword(this, awaitHandling); if (!functionArguments(yieldHandling, kind, funNode)) return false; } @@ -3715,9 +3726,10 @@ Parser::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 awaitIsKeyword(this, funbox->isAsync()); + AutoAwaitIsKeyword awaitIsKeyword(this, bodyAwaitHandling); body = functionBody(inHandling, bodyYieldHandling, kind, bodyType); if (!body) return false; @@ -3875,7 +3887,7 @@ Parser::functionExpr(uint32_t toStringStart, InvokedPrediction inv { MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_FUNCTION)); - AutoAwaitIsKeyword awaitIsKeyword(this, asyncKind == AsyncFunction); + AutoAwaitIsKeyword awaitIsKeyword(this, GetAwaitHandling(asyncKind)); GeneratorKind generatorKind = NotGenerator; TokenKind tt; if (!tokenStream.getToken(&tt)) @@ -9450,13 +9462,10 @@ Parser::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::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(); } } diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h index fce6ead17d..4dd9f64178 100644 --- a/js/src/frontend/Parser.h +++ b/js/src/frontend/Parser.h @@ -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; - void setAwaitIsKeyword(bool isKeyword); + void setAwaitHandling(AwaitHandling awaitHandling); bool checkOptions(); @@ -1643,17 +1644,21 @@ class MOZ_STACK_CLASS AutoAwaitIsKeyword { private: Parser* parser_; - bool oldAwaitIsKeyword_; + AwaitHandling oldAwaitHandling_; public: - AutoAwaitIsKeyword(Parser* parser, bool awaitIsKeyword) { + AutoAwaitIsKeyword(Parser* parser, AwaitHandling awaitHandling) { parser_ = parser; - oldAwaitIsKeyword_ = parser_->awaitIsKeyword_; - parser_->setAwaitIsKeyword(awaitIsKeyword); + oldAwaitHandling_ = static_cast(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_); } }; diff --git a/js/src/frontend/SyntaxParseHandler.h b/js/src/frontend/SyntaxParseHandler.h index e364f9d680..d8bc3e4959 100644 --- a/js/src/frontend/SyntaxParseHandler.h +++ b/js/src/frontend/SyntaxParseHandler.h @@ -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; } diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp index 7dbe239a7e..61d77adc2e 100644 --- a/js/src/jit/BaselineIC.cpp +++ b/js/src/jit/BaselineIC.cpp @@ -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 || diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp index 7721ed99d5..a6dcdf001a 100644 --- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -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; } diff --git a/js/src/jit/VMFunctions.cpp b/js/src/jit/VMFunctions.cpp index 01a22482eb..f191ce7d6d 100644 --- a/js/src/jit/VMFunctions.cpp +++ b/js/src/jit/VMFunctions.cpp @@ -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 diff --git a/js/src/js.msg b/js/src/js.msg index b98e6d860b..413469b808 100644 --- a/js/src/js.msg +++ b/js/src/js.msg @@ -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") diff --git a/js/src/moz.build b/js/src/moz.build index 115747daaf..3553dc9bf1 100644 --- a/js/src/moz.build +++ b/js/src/moz.build @@ -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', diff --git a/js/src/old-configure.in b/js/src/old-configure.in index 987d348448..f8db1e9a55 100644 --- a/js/src/old-configure.in +++ b/js/src/old-configure.in @@ -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 ======================================================== diff --git a/js/src/vm/GeneratorObject.cpp b/js/src/vm/GeneratorObject.cpp index 082e382663..f0718c0f86 100644 --- a/js/src/vm/GeneratorObject.cpp +++ b/js/src/vm/GeneratorObject.cpp @@ -179,6 +179,8 @@ GeneratorObject::resume(JSContext* cx, InterpreterActivation& activation, { Rooted genObj(cx, &obj->as()); MOZ_ASSERT(genObj->isSuspended()); + // See comment in InterpreterStack::resumeGeneratorCallFrame + MOZ_ASSERT_IF(genObj->isConstructing(), genObj->is()); RootedFunction callee(cx, &genObj->callee()); RootedValue newTarget(cx, genObj->newTarget()); diff --git a/js/src/vm/Interpreter-inl.h b/js/src/vm/Interpreter-inl.h index 5c2320d3fb..79a4b90200 100644 --- a/js/src/vm/Interpreter-inl.h +++ b/js/src/vm/Interpreter-inl.h @@ -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() || obj->is()) { + 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()) { unsigned propAttrs = GetInitDataPropAttrs(op); - return NativeDefineProperty(cx, obj.as(), id, rhs, nullptr, nullptr, - propAttrs); + return DefineProperty(cx, obj, id, rhs, nullptr, nullptr, propAttrs); } MOZ_ASSERT(obj->as().layout().lookup(id)); diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index 5fccc00d54..b17c762eae 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -3744,12 +3744,9 @@ CASE(JSOP_INITHIDDENPROP) /* Load the object being initialized into lval/obj. */ ReservedRooted obj(&rootObject0, ®S.sp[-2].toObject()); - PropertyName* name = script->getName(REGS.pc); + ReservedRooted 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--; diff --git a/js/src/vm/RegExpObject.cpp b/js/src/vm/RegExpObject.cpp index f46f4b4510..1d88754084 100644 --- a/js/src/vm/RegExpObject.cpp +++ b/js/src/vm/RegExpObject.cpp @@ -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 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])); diff --git a/js/src/vm/Stack-inl.h b/js/src/vm/Stack-inl.h index 9114a6a79e..5f66159c2c 100644 --- a/js/src/vm/Stack-inl.h +++ b/js/src/vm/Stack-inl.h @@ -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| diff --git a/layout/media/symbols.def.in b/layout/media/symbols.def.in index 94866cc2ba..09df0df7ed 100644 --- a/layout/media/symbols.def.in +++ b/layout/media/symbols.def.in @@ -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 diff --git a/modules/fdlibm/src/moz.build b/modules/fdlibm/src/moz.build index 541f840399..d1feeb62f9 100644 --- a/modules/fdlibm/src/moz.build +++ b/modules/fdlibm/src/moz.build @@ -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', diff --git a/old-configure.in b/old-configure.in index 9c30ab53bd..034a6eb244 100644 --- a/old-configure.in +++ b/old-configure.in @@ -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 ========================================================