Merge mozilla-inbound to mozilla-central. a=merge
authorDaniel Varga <dvarga@mozilla.com>
Thu, 25 Oct 2018 12:53:20 +0300
changeset 442938 3cc04ee79005058d817daf66da7963dfac3f0a3a
parent 442932 cb7bc3337f392abcfe442330d4b7350134150864 (current diff)
parent 442937 ca965ec1bc91eb004ab8f5d89dc783e62ba04cf2 (diff)
child 442943 d4b2fecf181c6c89a205eaf0058bbf129f780faa
child 442963 feb8571f288e22049912d64e3daa133578c8d55b
push id34930
push userdvarga@mozilla.com
push dateThu, 25 Oct 2018 09:54:00 +0000
treeherdermozilla-central@3cc04ee79005 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone65.0a1
first release with
nightly linux32
3cc04ee79005 / 65.0a1 / 20181025100246 / files
nightly linux64
3cc04ee79005 / 65.0a1 / 20181025100246 / files
nightly mac
3cc04ee79005 / 65.0a1 / 20181025100246 / files
nightly win32
3cc04ee79005 / 65.0a1 / 20181025100246 / files
nightly win64
3cc04ee79005 / 65.0a1 / 20181025100246 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-inbound to mozilla-central. a=merge
--- a/js/src/jit/BaselineCacheIRCompiler.cpp
+++ b/js/src/jit/BaselineCacheIRCompiler.cpp
@@ -1893,16 +1893,37 @@ BaselineCacheIRCompiler::emitCallAddOrUp
 
     if (!callVM(masm, AddOrUpdateSparseElementHelperInfo)) {
         return false;
     }
     stubFrame.leave(masm);
     return true;
 }
 
+bool
+BaselineCacheIRCompiler::emitCallGetSparseElementResult()
+{
+    Register obj = allocator.useRegister(masm, reader.objOperandId());
+    Register id = allocator.useRegister(masm, reader.int32OperandId());
+    AutoScratchRegister scratch(allocator, masm);
+
+    allocator.discardStack(masm);
+
+    AutoStubFrame stubFrame(*this);
+    stubFrame.enter(masm, scratch);
+
+    masm.Push(id);
+    masm.Push(obj);
+
+    if (!callVM(masm, GetSparseElementHelperInfo)) {
+        return false;
+    }
+    stubFrame.leave(masm);
+    return true;
+}
 
 bool
 BaselineCacheIRCompiler::emitMegamorphicSetElement()
 {
     Register obj = allocator.useRegister(masm, reader.objOperandId());
     ValueOperand idVal = allocator.useValueRegister(masm, reader.valOperandId());
     ValueOperand val = allocator.useValueRegister(masm, reader.valOperandId());
     bool strict = reader.readBool();
--- a/js/src/jit/CacheIR.cpp
+++ b/js/src/jit/CacheIR.cpp
@@ -279,16 +279,19 @@ GetPropIRGenerator::tryAttachStub()
                 return true;
             }
             if (tryAttachDenseElement(obj, objId, index, indexId)) {
                 return true;
             }
             if (tryAttachDenseElementHole(obj, objId, index, indexId)) {
                 return true;
             }
+            if (tryAttachSparseElement(obj, objId, index, indexId)) {
+                return true;
+            }
             if (tryAttachUnboxedElementHole(obj, objId, index, indexId)) {
                 return true;
             }
             if (tryAttachArgumentsObjectArg(obj, objId, indexId)) {
                 return true;
             }
             if (tryAttachGenericElement(obj, objId, index, indexId)) {
                 return true;
@@ -2208,16 +2211,80 @@ GetPropIRGenerator::tryAttachDenseElemen
     GeneratePrototypeHoleGuards(writer, nobj, objId);
     writer.loadDenseElementHoleResult(objId, indexId);
     writer.typeMonitorResult();
 
     trackAttached("DenseElementHole");
     return true;
 }
 
+bool
+GetPropIRGenerator::tryAttachSparseElement(HandleObject obj, ObjOperandId objId,
+                                           uint32_t index, Int32OperandId indexId)
+{
+    if (!obj->isNative()) {
+        return false;
+    }
+    NativeObject* nobj = &obj->as<NativeObject>();
+
+    // Stub doesn't handle negative indices.
+    if (index > INT_MAX) {
+        return false;
+    }
+
+    // We also need to be past the end of the dense capacity, to ensure sparse.
+    if (index < nobj->getDenseInitializedLength()) {
+        return false;
+    }
+
+    // Only handle Array objects in this stub.
+    if (!nobj->is<ArrayObject>()) {
+        return false;
+    }
+
+    // Here, we ensure that the prototype chain does not define any sparse
+    // indexed properties on the shape lineage. This allows us to guard on
+    // the shapes up the prototype chain to ensure that no indexed properties
+    // exist outside of the dense elements.
+    //
+    // The `GeneratePrototypeHoleGuards` call below will guard on the shapes,
+    // as well as ensure that no prototypes contain dense elements, allowing
+    // us to perform a pure shape-search for out-of-bounds integer-indexed
+    // properties on the recevier object.
+    if ((nobj->staticPrototype() != nullptr) &&
+        ObjectMayHaveExtraIndexedProperties(nobj->staticPrototype()))
+    {
+        return false;
+    }
+
+    // Ensure that obj is an Array.
+    writer.guardClass(objId, GuardClassKind::Array);
+
+    // The helper we are going to call only applies to non-dense elements.
+    writer.guardIndexGreaterThanDenseInitLength(objId, indexId);
+
+    // Ensures we are able to efficiently able to map to an integral jsid.
+    writer.guardIndexIsNonNegative(indexId);
+
+    // Shape guard the prototype chain to avoid shadowing indexes from appearing.
+    // The helper function also ensures that the index does not appear within the
+    // dense element set of the prototypes.
+    GeneratePrototypeHoleGuards(writer, nobj, objId);
+
+    // At this point, we are guaranteed that the indexed property will not
+    // be found on one of the prototypes. We are assured that we only have
+    // to check that the receiving object has the property.
+
+    writer.callGetSparseElementResult(objId, indexId);
+    writer.typeMonitorResult();
+
+    trackAttached("GetSparseElement");
+    return true;
+}
+
 static bool
 IsPrimitiveArrayTypedObject(JSObject* obj)
 {
     if (!obj->is<TypedObject>()) {
         return false;
     }
     TypeDescr& descr = obj->as<TypedObject>().typeDescr();
     return descr.is<ArrayTypeDescr>() &&
--- a/js/src/jit/CacheIR.h
+++ b/js/src/jit/CacheIR.h
@@ -277,16 +277,17 @@ extern const char* const CacheKindNames[
                                           \
     /* The *Result ops load a value into the cache's result register. */ \
     _(LoadFixedSlotResult)                \
     _(LoadDynamicSlotResult)              \
     _(LoadUnboxedPropertyResult)          \
     _(LoadTypedObjectResult)              \
     _(LoadDenseElementResult)             \
     _(LoadDenseElementHoleResult)         \
+    _(CallGetSparseElementResult)         \
     _(LoadDenseElementExistsResult)       \
     _(LoadTypedElementExistsResult)       \
     _(LoadDenseElementHoleExistsResult)   \
     _(LoadTypedElementResult)             \
     _(LoadInt32ArrayLengthResult)         \
     _(LoadArgumentsObjectArgResult)       \
     _(LoadArgumentsObjectLengthResult)    \
     _(LoadFunctionLengthResult)           \
@@ -1233,16 +1234,20 @@ class MOZ_RAII CacheIRWriter : public JS
     void loadDenseElementResult(ObjOperandId obj, Int32OperandId index) {
         writeOpWithOperandId(CacheOp::LoadDenseElementResult, obj);
         writeOperandId(index);
     }
     void loadDenseElementHoleResult(ObjOperandId obj, Int32OperandId index) {
         writeOpWithOperandId(CacheOp::LoadDenseElementHoleResult, obj);
         writeOperandId(index);
     }
+    void callGetSparseElementResult(ObjOperandId obj, Int32OperandId index) {
+        writeOpWithOperandId(CacheOp::CallGetSparseElementResult, obj);
+        writeOperandId(index);
+    }
     void loadDenseElementExistsResult(ObjOperandId obj, Int32OperandId index) {
         writeOpWithOperandId(CacheOp::LoadDenseElementExistsResult, obj);
         writeOperandId(index);
     }
     void loadTypedElementExistsResult(ObjOperandId obj, Int32OperandId index, TypedThingLayout layout) {
         writeOpWithOperandId(CacheOp::LoadTypedElementExistsResult, obj);
         writeOperandId(index);
         buffer_.writeByte(uint32_t(layout));
@@ -1595,16 +1600,18 @@ class MOZ_RAII GetPropIRGenerator : publ
     bool tryAttachMagicArgument(ValOperandId valId, ValOperandId indexId);
     bool tryAttachArgumentsObjectArg(HandleObject obj, ObjOperandId objId,
                                      Int32OperandId indexId);
 
     bool tryAttachDenseElement(HandleObject obj, ObjOperandId objId,
                                uint32_t index, Int32OperandId indexId);
     bool tryAttachDenseElementHole(HandleObject obj, ObjOperandId objId,
                                    uint32_t index, Int32OperandId indexId);
+    bool tryAttachSparseElement(HandleObject obj, ObjOperandId objId,
+                                uint32_t index, Int32OperandId indexId);
     bool tryAttachTypedElement(HandleObject obj, ObjOperandId objId,
                                uint32_t index, Int32OperandId indexId);
     bool tryAttachUnboxedElementHole(HandleObject obj, ObjOperandId objId,
                                      uint32_t index, Int32OperandId indexId);
 
     bool tryAttachGenericElement(HandleObject obj, ObjOperandId objId,
                                  uint32_t index, Int32OperandId indexId);
 
--- a/js/src/jit/IonCacheIRCompiler.cpp
+++ b/js/src/jit/IonCacheIRCompiler.cpp
@@ -2281,16 +2281,38 @@ IonCacheIRCompiler::emitCallAddOrUpdateS
     masm.Push(Imm32(strict));
     masm.Push(val);
     masm.Push(id);
     masm.Push(obj);
 
     return callVM(masm, AddOrUpdateSparseElementHelperInfo);
 }
 
+bool
+IonCacheIRCompiler::emitCallGetSparseElementResult()
+{
+    AutoSaveLiveRegisters save(*this);
+    AutoOutputRegister output(*this);
+
+    Register obj = allocator.useRegister(masm, reader.objOperandId());
+    Register id = allocator.useRegister(masm, reader.int32OperandId());
+
+    allocator.discardStack(masm);
+    prepareVMCall(masm, save);
+    masm.Push(id);
+    masm.Push(obj);
+
+    if (!callVM(masm, GetSparseElementHelperInfo)) {
+        return false;
+    }
+
+    masm.storeCallResultValue(output);
+    return true;
+}
+
 
 bool
 IonCacheIRCompiler::emitMegamorphicSetElement()
 {
     AutoSaveLiveRegisters save(*this);
 
     Register obj = allocator.useRegister(masm, reader.objOperandId());
     ConstantOrRegister idVal = allocator.useConstantOrRegister(masm, reader.valOperandId());
--- a/js/src/jit/VMFunctions.cpp
+++ b/js/src/jit/VMFunctions.cpp
@@ -2080,10 +2080,15 @@ typedef bool (*NativeGetElementFn)(JSCon
 const VMFunction NativeGetElementInfo =
     FunctionInfo<NativeGetElementFn>(NativeGetElement, "NativeGetProperty");
 
 typedef bool (*AddOrUpdateSparseElementHelperFn)(JSContext* cx, HandleArrayObject obj,
                                                  int32_t int_id, HandleValue v, bool strict);
 const VMFunction AddOrUpdateSparseElementHelperInfo =
     FunctionInfo<AddOrUpdateSparseElementHelperFn>(AddOrUpdateSparseElementHelper, "AddOrUpdateSparseElementHelper");
 
+typedef bool (*GetSparseElementHelperFn)(JSContext* cx, HandleArrayObject obj,
+                                         int32_t int_id, MutableHandleValue result);
+const VMFunction GetSparseElementHelperInfo =
+    FunctionInfo<GetSparseElementHelperFn>(GetSparseElementHelper, "getSparseElementHelper");
+
 } // namespace jit
 } // namespace js
--- a/js/src/jit/VMFunctions.h
+++ b/js/src/jit/VMFunctions.h
@@ -978,16 +978,17 @@ extern const VMFunction ProxyGetProperty
 extern const VMFunction ProxySetPropertyInfo;
 extern const VMFunction ProxySetPropertyByValueInfo;
 extern const VMFunction ProxyHasInfo;
 extern const VMFunction ProxyHasOwnInfo;
 
 extern const VMFunction NativeGetElementInfo;
 
 extern const VMFunction AddOrUpdateSparseElementHelperInfo;
+extern const VMFunction GetSparseElementHelperInfo;
 
 // TailCall VMFunctions
 extern const VMFunction DoConcatStringObjectInfo;
 
 } // namespace jit
 } // namespace js
 
 #endif /* jit_VMFunctions_h */
--- a/js/src/vm/NativeObject.cpp
+++ b/js/src/vm/NativeObject.cpp
@@ -2529,16 +2529,42 @@ GeneralizedGetProperty(JSContext* cx, JS
         return false;
     }
     if (nameLookup) {
         return false;
     }
     return GetPropertyNoGC(cx, obj, receiver, id, vp.address());
 }
 
+bool
+js::GetSparseElementHelper(JSContext* cx, HandleArrayObject obj, int32_t int_id,
+                           MutableHandleValue result)
+{
+    // Callers should have ensured that this object has a static prototype.
+    MOZ_ASSERT(obj->hasStaticPrototype());
+
+    // Indexed properties can not exist on the prototype chain.
+    MOZ_ASSERT_IF(obj->staticPrototype() != nullptr,
+                  !ObjectMayHaveExtraIndexedProperties(obj->staticPrototype()));
+
+    MOZ_ASSERT(INT_FITS_IN_JSID(int_id));
+    RootedId id(cx, INT_TO_JSID(int_id));
+
+    Shape* rawShape = obj->lastProperty()->search(cx, id);
+    if (!rawShape) {
+        // Property not found, return directly.
+        result.setUndefined();
+        return true;
+    }
+
+    RootedValue receiver(cx, ObjectValue(*obj));
+    RootedShape shape(cx, rawShape);
+    return GetExistingProperty<CanGC>(cx, receiver, obj, shape, result);
+}
+
 template <AllowGC allowGC>
 static MOZ_ALWAYS_INLINE bool
 NativeGetPropertyInline(JSContext* cx,
                         typename MaybeRooted<NativeObject*, allowGC>::HandleType obj,
                         typename MaybeRooted<Value, allowGC>::HandleType receiver,
                         typename MaybeRooted<jsid, allowGC>::HandleType id,
                         IsNameLookup nameLookup,
                         typename MaybeRooted<Value, allowGC>::MutableHandleType vp)
--- a/js/src/vm/NativeObject.h
+++ b/js/src/vm/NativeObject.h
@@ -1610,16 +1610,20 @@ NativeGetProperty(JSContext* cx, HandleN
     return NativeGetProperty(cx, obj, receiver, id, vp);
 }
 
 extern bool
 NativeGetElement(JSContext* cx, HandleNativeObject obj, HandleValue reciever, int32_t index,
                  MutableHandleValue vp);
 
 bool
+GetSparseElementHelper(JSContext* cx, HandleArrayObject obj, int32_t int_id,
+                       MutableHandleValue result);
+
+bool
 SetPropertyByDefining(JSContext* cx, HandleId id, HandleValue v, HandleValue receiver,
                       ObjectOpResult& result);
 
 bool
 SetPropertyOnProto(JSContext* cx, HandleObject obj, HandleId id, HandleValue v,
                    HandleValue receiver, ObjectOpResult& result);
 
 bool
--- a/js/src/wasm/WasmGenerator.cpp
+++ b/js/src/wasm/WasmGenerator.cpp
@@ -973,17 +973,17 @@ ModuleGenerator::finishCodeTier()
     UniqueModuleSegment segment = ModuleSegment::create(tier(), masm_, *linkData_);
     if (!segment) {
         return nullptr;
     }
 
     return js::MakeUnique<CodeTier>(std::move(metadataTier_), std::move(segment));
 }
 
-bool
+SharedMetadata
 ModuleGenerator::finishMetadata(const Bytes& bytecode)
 {
     // Finish initialization of Metadata, which is only needed for constructing
     // the initial Module, not for tier-2 compilation.
     MOZ_ASSERT(mode() != CompileMode::Tier2);
 
     // Copy over data from the ModuleEnvironment.
 
@@ -1000,38 +1000,43 @@ ModuleGenerator::finishMetadata(const By
 
     // Copy over additional debug information.
 
     if (env_->debugEnabled()) {
         metadata_->debugEnabled = true;
 
         const size_t numFuncTypes = env_->funcTypes.length();
         if (!metadata_->debugFuncArgTypes.resize(numFuncTypes)) {
-            return false;
+            return nullptr;
         }
         if (!metadata_->debugFuncReturnTypes.resize(numFuncTypes)) {
-            return false;
+            return nullptr;
         }
         for (size_t i = 0; i < numFuncTypes; i++) {
             if (!metadata_->debugFuncArgTypes[i].appendAll(env_->funcTypes[i]->args())) {
-                return false;
+                return nullptr;
             }
             metadata_->debugFuncReturnTypes[i] = env_->funcTypes[i]->ret();
         }
 
         static_assert(sizeof(ModuleHash) <= sizeof(mozilla::SHA1Sum::Hash),
                       "The ModuleHash size shall not exceed the SHA1 hash size.");
         mozilla::SHA1Sum::Hash hash;
         mozilla::SHA1Sum sha1Sum;
         sha1Sum.update(bytecode.begin(), bytecode.length());
         sha1Sum.finish(hash);
         memcpy(metadata_->debugHash, hash, sizeof(ModuleHash));
     }
 
-    return true;
+    MOZ_ASSERT_IF(env_->nameCustomSectionIndex, !!metadata_->namePayload);
+
+    // Metadata shouldn't be mutably modified after finishMetadata().
+    SharedMetadata metadata = metadata_;
+    metadata_ = nullptr;
+    return metadata;
 }
 
 SharedModule
 ModuleGenerator::finishModule(const ShareableBytes& bytecode,
                               JS::OptimizedEncodingListener* maybeTier2Listener,
                               UniqueLinkData* maybeLinkDataOut)
 {
     MOZ_ASSERT(mode() == CompileMode::Once || mode() == CompileMode::Tier1);
@@ -1041,33 +1046,16 @@ ModuleGenerator::finishModule(const Shar
         return nullptr;
     }
 
     JumpTables jumpTables;
     if (!jumpTables.init(mode(), codeTier->segment(), codeTier->metadata().codeRanges)) {
         return nullptr;
     }
 
-    if (!finishMetadata(bytecode.bytes)) {
-        return nullptr;
-    }
-
-    StructTypeVector structTypes;
-    for (TypeDef& td : env_->types) {
-        if (td.isStructType() && !structTypes.append(std::move(td.structType()))) {
-            return nullptr;
-        }
-    }
-
-    MutableCode code = js_new<Code>(std::move(codeTier), *metadata_, std::move(jumpTables),
-                                    std::move(structTypes));
-    if (!code || !code->initialize(*linkData_)) {
-        return nullptr;
-    }
-
     // Copy over data from the Bytecode, which is going away at the end of
     // compilation.
 
     DataSegmentVector dataSegments;
     if (!dataSegments.reserve(env_->dataSegments.length())) {
         return nullptr;
     }
     for (const DataSegmentEnv& srcSeg : env_->dataSegments) {
@@ -1100,16 +1088,34 @@ ModuleGenerator::finishModule(const Shar
         sec.payload = std::move(payload);
         customSections.infallibleAppend(std::move(sec));
     }
 
     if (env_->nameCustomSectionIndex) {
         metadata_->namePayload = customSections[*env_->nameCustomSectionIndex].payload;
     }
 
+    SharedMetadata metadata = finishMetadata(bytecode.bytes);
+    if (!metadata) {
+        return nullptr;
+    }
+
+    StructTypeVector structTypes;
+    for (TypeDef& td : env_->types) {
+        if (td.isStructType() && !structTypes.append(std::move(td.structType()))) {
+            return nullptr;
+        }
+    }
+
+    MutableCode code = js_new<Code>(std::move(codeTier), *metadata, std::move(jumpTables),
+                                    std::move(structTypes));
+    if (!code || !code->initialize(*linkData_)) {
+        return nullptr;
+    }
+
     // See Module debugCodeClaimed_ comments for why we need to make a separate
     // debug copy.
 
     UniqueBytes debugUnlinkedCode;
     UniqueLinkData debugLinkData;
     const ShareableBytes* debugBytecode = nullptr;
     if (env_->debugEnabled()) {
         MOZ_ASSERT(mode() == CompileMode::Once);
--- a/js/src/wasm/WasmGenerator.h
+++ b/js/src/wasm/WasmGenerator.h
@@ -197,17 +197,17 @@ class MOZ_STACK_CLASS ModuleGenerator
     void noteCodeRange(uint32_t codeRangeIndex, const CodeRange& codeRange);
     bool linkCompiledCode(const CompiledCode& code);
     bool finishTask(CompileTask* task);
     bool launchBatchCompile();
     bool finishOutstandingTask();
     bool finishCodegen();
     bool finishMetadataTier();
     UniqueCodeTier finishCodeTier();
-    bool finishMetadata(const Bytes& bytecode);
+    SharedMetadata finishMetadata(const Bytes& bytecode);
 
     bool isAsmJS() const { return env_->isAsmJS(); }
     Tier tier() const { return env_->tier(); }
     CompileMode mode() const { return env_->mode(); }
     bool debugEnabled() const { return env_->debugEnabled(); }
 
   public:
     ModuleGenerator(const CompileArgs& args, ModuleEnvironment* env,
--- a/mobile/android/config/mozconfigs/android-aarch64/nightly
+++ b/mobile/android/config/mozconfigs/android-aarch64/nightly
@@ -1,13 +1,19 @@
 . "$topsrcdir/mobile/android/config/mozconfigs/common"
 
 # Android
 ac_add_options --with-android-min-sdk=21
 ac_add_options --target=aarch64-linux-android
 
 ac_add_options --with-branding=mobile/android/branding/nightly
 
+export AR="$topsrcdir/clang/bin/llvm-ar"
+export NM="$topsrcdir/clang/bin/llvm-nm"
+export RANLIB="$topsrcdir/clang/bin/llvm-ranlib"
+
+ac_add_options --enable-lto
+
 export MOZILLA_OFFICIAL=1
 export MOZ_TELEMETRY_REPORTING=1
 export MOZ_ANDROID_POCKET=1
 
 . "$topsrcdir/mobile/android/config/mozconfigs/common.override"
--- a/mobile/android/config/mozconfigs/android-api-16/nightly
+++ b/mobile/android/config/mozconfigs/android-api-16/nightly
@@ -11,9 +11,15 @@ ac_add_options --target=arm-linux-androi
 
 ac_add_options --with-branding=mobile/android/branding/nightly
 
 export MOZILLA_OFFICIAL=1
 export MOZ_TELEMETRY_REPORTING=1
 export MOZ_ANDROID_MMA=1
 export MOZ_ANDROID_POCKET=1
 
+export AR="$topsrcdir/clang/bin/llvm-ar"
+export NM="$topsrcdir/clang/bin/llvm-nm"
+export RANLIB="$topsrcdir/clang/bin/llvm-ranlib"
+
+ac_add_options --enable-lto
+
 . "$topsrcdir/mobile/android/config/mozconfigs/common.override"
--- a/mobile/android/config/mozconfigs/android-x86/nightly
+++ b/mobile/android/config/mozconfigs/android-x86/nightly
@@ -9,9 +9,15 @@ ac_add_options --target=i686-linux-andro
 ac_add_options --with-android-min-sdk=16
 
 ac_add_options --with-branding=mobile/android/branding/nightly
 
 export MOZILLA_OFFICIAL=1
 export MOZ_TELEMETRY_REPORTING=1
 export MOZ_ANDROID_POCKET=1
 
+export AR="$topsrcdir/clang/bin/llvm-ar"
+export NM="$topsrcdir/clang/bin/llvm-nm"
+export RANLIB="$topsrcdir/clang/bin/llvm-ranlib"
+
+ac_add_options --enable-lto
+
 . "$topsrcdir/mobile/android/config/mozconfigs/common.override"