Bug 1574415 - Part 12: Remove StoreToTypedObject and instead use new guard ops for StoreTypedObjectScalarProperty. r=jandem
authorAndré Bargull <andre.bargull@gmail.com>
Mon, 07 Oct 2019 12:00:19 +0000
changeset 496564 218a81625331fa748ee2723114ed836a09e93694
parent 496563 1bd9ae4caa0ba3aa9b08743cbd899c0ce052567d
child 496565 3dc778bc0ce0ccb1abc83d46f55f202b95a7e771
push id97326
push userarchaeopteryx@coole-files.de
push dateMon, 07 Oct 2019 16:46:32 +0000
treeherderautoland@144ebbca6844 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1574415
milestone71.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1574415 - Part 12: Remove StoreToTypedObject and instead use new guard ops for StoreTypedObjectScalarProperty. r=jandem Differential Revision: https://phabricator.services.mozilla.com/D47760
js/src/jit/BaselineCacheIRCompiler.cpp
js/src/jit/BaselineIC.cpp
js/src/jit/BaselineIC.h
js/src/jit/CacheIR.cpp
js/src/jit/CacheIR.h
js/src/jit/IonCacheIRCompiler.cpp
--- a/js/src/jit/BaselineCacheIRCompiler.cpp
+++ b/js/src/jit/BaselineCacheIRCompiler.cpp
@@ -1082,31 +1082,60 @@ bool BaselineCacheIRCompiler::emitStoreT
 }
 
 bool BaselineCacheIRCompiler::emitStoreTypedObjectScalarProperty() {
   JitSpew(JitSpew_Codegen, __FUNCTION__);
   Register obj = allocator.useRegister(masm, reader.objOperandId());
   Address offsetAddr = stubAddress(reader.stubOffset());
   TypedThingLayout layout = reader.typedThingLayout();
   Scalar::Type type = reader.scalarType();
-  ValueOperand val = allocator.useValueRegister(masm, reader.valOperandId());
-  AutoScratchRegister scratch1(allocator, masm);
-  AutoScratchRegister scratch2(allocator, masm);
-
-  FailurePath* failure;
-  if (!addFailurePath(&failure)) {
-    return false;
+
+  Maybe<Register> valInt32;
+  switch (type) {
+    case Scalar::Int8:
+    case Scalar::Uint8:
+    case Scalar::Int16:
+    case Scalar::Uint16:
+    case Scalar::Int32:
+    case Scalar::Uint32:
+    case Scalar::Uint8Clamped:
+      valInt32.emplace(allocator.useRegister(masm, reader.int32OperandId()));
+      break;
+
+    case Scalar::Float32:
+    case Scalar::Float64:
+      // Float register must be preserved. The SetProp ICs use the fact that
+      // baseline has them available, as well as fixed temps on
+      // LSetPropertyCache.
+      allocator.ensureDoubleRegister(masm, reader.numberOperandId(), FloatReg0);
+      break;
+
+    case Scalar::BigInt64:
+    case Scalar::BigUint64:
+    case Scalar::MaxTypedArrayViewType:
+    case Scalar::Int64:
+      MOZ_CRASH("Unsupported TypedArray type");
   }
 
+  AutoScratchRegister scratch(allocator, masm);
+
   // Compute the address being written to.
-  LoadTypedThingData(masm, layout, obj, scratch1);
-  masm.addPtr(offsetAddr, scratch1);
-  Address dest(scratch1, 0);
-
-  StoreToTypedObject(cx_, masm, type, val, dest, scratch2, failure->label());
+  LoadTypedThingData(masm, layout, obj, scratch);
+  masm.addPtr(offsetAddr, scratch);
+  Address dest(scratch, 0);
+
+  if (type == Scalar::Float32) {
+    ScratchFloat32Scope fpscratch(masm);
+    masm.convertDoubleToFloat32(FloatReg0, fpscratch);
+    masm.storeToTypedFloatArray(type, fpscratch, dest);
+  } else if (type == Scalar::Float64) {
+    masm.storeToTypedFloatArray(type, FloatReg0, dest);
+  } else {
+    masm.storeToTypedIntArray(type, *valInt32, dest);
+  }
   return true;
 }
 
 bool BaselineCacheIRCompiler::emitStoreDenseElement() {
   JitSpew(JitSpew_Codegen, __FUNCTION__);
   ObjOperandId objId = reader.objOperandId();
   Int32OperandId indexId = reader.int32OperandId();
 
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -2244,76 +2244,16 @@ bool FallbackICCodeCompiler::emit_SetEle
   masm.push(ICStubReg);
   pushStubPayload(masm, R0.scratchReg());
 
   using Fn = bool (*)(JSContext*, BaselineFrame*, ICSetElem_Fallback*, Value*,
                       HandleValue, HandleValue, HandleValue);
   return tailCallVM<Fn, DoSetElemFallback>(masm);
 }
 
-void StoreToTypedObject(JSContext* cx, MacroAssembler& masm, Scalar::Type type,
-                        const ValueOperand& value, const Address& dest,
-                        Register scratch, Label* failure) {
-  // Float register must be preserved. The SetProp ICs use the fact that
-  // baseline has them available, as well as fixed temps on LSetPropertyCache.
-
-  Label done;
-
-  if (type == Scalar::Float32 || type == Scalar::Float64) {
-    masm.ensureDouble(value, FloatReg0, failure);
-    if (type == Scalar::Float32) {
-      ScratchFloat32Scope fpscratch(masm);
-      masm.convertDoubleToFloat32(FloatReg0, fpscratch);
-      masm.storeToTypedFloatArray(type, fpscratch, dest);
-    } else {
-      masm.storeToTypedFloatArray(type, FloatReg0, dest);
-    }
-  } else if (type == Scalar::Uint8Clamped) {
-    Label notInt32;
-    masm.branchTestInt32(Assembler::NotEqual, value, &notInt32);
-    masm.unboxInt32(value, scratch);
-    masm.clampIntToUint8(scratch);
-
-    Label clamped;
-    masm.bind(&clamped);
-    masm.storeToTypedIntArray(type, scratch, dest);
-    masm.jump(&done);
-
-    // If the value is a double, clamp to uint8 and jump back.
-    // Else, jump to failure.
-    masm.bind(&notInt32);
-    masm.branchTestDouble(Assembler::NotEqual, value, failure);
-    masm.unboxDouble(value, FloatReg0);
-    masm.clampDoubleToUint8(FloatReg0, scratch);
-    masm.jump(&clamped);
-  } else if (type == Scalar::BigInt64 || type == Scalar::BigUint64) {
-    // FIXME: https://bugzil.la/1536703
-    masm.jump(failure);
-  } else {
-    Label notInt32;
-    masm.branchTestInt32(Assembler::NotEqual, value, &notInt32);
-    masm.unboxInt32(value, scratch);
-
-    Label isInt32;
-    masm.bind(&isInt32);
-    masm.storeToTypedIntArray(type, scratch, dest);
-    masm.jump(&done);
-
-    // If the value is a double, truncate and jump back.
-    // Else, jump to failure.
-    masm.bind(&notInt32);
-    masm.branchTestDouble(Assembler::NotEqual, value, failure);
-    masm.unboxDouble(value, FloatReg0);
-    masm.branchTruncateDoubleMaybeModUint32(FloatReg0, scratch, failure);
-    masm.jump(&isInt32);
-  }
-
-  masm.bind(&done);
-}
-
 //
 // In_Fallback
 //
 
 bool DoInFallback(JSContext* cx, BaselineFrame* frame, ICIn_Fallback* stub,
                   HandleValue key, HandleValue objValue,
                   MutableHandleValue res) {
   stub->incrementEnteredCount();
--- a/js/src/jit/BaselineIC.h
+++ b/js/src/jit/BaselineIC.h
@@ -1828,23 +1828,16 @@ inline bool IsCacheableDOMProxy(JSObject
 
   // Some DOM proxies have dynamic prototypes.  We can't really cache those very
   // well.
   return obj->hasStaticPrototype();
 }
 
 struct IonOsrTempData;
 
-// Write an arbitrary value to a typed object address at dest.
-// If the value could not be converted to the appropriate format, jump to
-// failure.
-void StoreToTypedObject(JSContext* cx, MacroAssembler& masm, Scalar::Type type,
-                        const ValueOperand& value, const Address& dest,
-                        Register scratch, Label* failure);
-
 extern MOZ_MUST_USE bool TypeMonitorResult(JSContext* cx,
                                            ICMonitoredFallbackStub* stub,
                                            BaselineFrame* frame,
                                            HandleScript script, jsbytecode* pc,
                                            HandleValue val);
 
 extern bool DoTypeUpdateFallback(JSContext* cx, BaselineFrame* frame,
                                  ICCacheIR_Updated* stub, HandleValue objval,
--- a/js/src/jit/CacheIR.cpp
+++ b/js/src/jit/CacheIR.cpp
@@ -3406,18 +3406,49 @@ AttachDecision SetPropIRGenerator::tryAt
   writer.guardNoDetachedTypedObjects();
   writer.guardGroupForLayout(objId, obj->group());
 
   typeCheckInfo_.set(obj->group(), id);
 
   // Scalar types can always be stored without a type update stub.
   if (fieldDescr->is<ScalarTypeDescr>()) {
     Scalar::Type type = fieldDescr->as<ScalarTypeDescr>().type();
+
+    Maybe<OperandId> rhsValId;
+    switch (type) {
+      case Scalar::Int8:
+      case Scalar::Uint8:
+      case Scalar::Int16:
+      case Scalar::Uint16:
+      case Scalar::Int32:
+      case Scalar::Uint32:
+        rhsValId.emplace(writer.guardToInt32ModUint32(rhsId));
+        break;
+
+      case Scalar::Float32:
+      case Scalar::Float64:
+        rhsValId.emplace(writer.guardIsNumber(rhsId));
+        break;
+
+      case Scalar::Uint8Clamped:
+        rhsValId.emplace(writer.guardToUint8Clamped(rhsId));
+        break;
+
+      case Scalar::BigInt64:
+      case Scalar::BigUint64:
+        // FIXME: https://bugzil.la/1536703
+        return AttachDecision::NoAction;
+
+      case Scalar::MaxTypedArrayViewType:
+      case Scalar::Int64:
+        MOZ_CRASH("Unsupported TypedArray type");
+    }
+
     writer.storeTypedObjectScalarProperty(objId, fieldOffset, layout, type,
-                                          rhsId);
+                                          *rhsValId);
     writer.returnFromIC();
 
     trackAttached("TypedObject");
     return AttachDecision::Attach;
   }
 
   // For reference types, guard on the RHS type first, so that
   // StoreTypedObjectReferenceProperty is infallible.
--- a/js/src/jit/CacheIR.h
+++ b/js/src/jit/CacheIR.h
@@ -1330,17 +1330,17 @@ class MOZ_RAII CacheIRWriter : public JS
     addStubField(offset, StubField::Type::RawWord);
     buffer_.writeByte(uint32_t(layout));
     buffer_.writeByte(uint32_t(type));
     writeOperandId(rhs);
   }
 
   void storeTypedObjectScalarProperty(ObjOperandId obj, uint32_t offset,
                                       TypedThingLayout layout,
-                                      Scalar::Type type, ValOperandId rhs) {
+                                      Scalar::Type type, OperandId rhs) {
     writeOpWithOperandId(CacheOp::StoreTypedObjectScalarProperty, obj);
     addStubField(offset, StubField::Type::RawWord);
     buffer_.writeByte(uint32_t(layout));
     buffer_.writeByte(uint32_t(type));
     writeOperandId(rhs);
   }
 
   void storeDenseElement(ObjOperandId obj, Int32OperandId index,
--- a/js/src/jit/IonCacheIRCompiler.cpp
+++ b/js/src/jit/IonCacheIRCompiler.cpp
@@ -1568,30 +1568,59 @@ bool IonCacheIRCompiler::emitStoreTypedO
 }
 
 bool IonCacheIRCompiler::emitStoreTypedObjectScalarProperty() {
   JitSpew(JitSpew_Codegen, __FUNCTION__);
   Register obj = allocator.useRegister(masm, reader.objOperandId());
   int32_t offset = int32StubField(reader.stubOffset());
   TypedThingLayout layout = reader.typedThingLayout();
   Scalar::Type type = reader.scalarType();
-  ValueOperand val = allocator.useValueRegister(masm, reader.valOperandId());
-  AutoScratchRegister scratch1(allocator, masm);
-  AutoScratchRegister scratch2(allocator, masm);
-
-  FailurePath* failure;
-  if (!addFailurePath(&failure)) {
-    return false;
+
+  Maybe<Register> valInt32;
+  switch (type) {
+    case Scalar::Int8:
+    case Scalar::Uint8:
+    case Scalar::Int16:
+    case Scalar::Uint16:
+    case Scalar::Int32:
+    case Scalar::Uint32:
+    case Scalar::Uint8Clamped:
+      valInt32.emplace(allocator.useRegister(masm, reader.int32OperandId()));
+      break;
+
+    case Scalar::Float32:
+    case Scalar::Float64:
+      // Float register must be preserved. The SetProp ICs use the fact that
+      // baseline has them available, as well as fixed temps on
+      // LSetPropertyCache.
+      allocator.ensureDoubleRegister(masm, reader.numberOperandId(), FloatReg0);
+      break;
+
+    case Scalar::BigInt64:
+    case Scalar::BigUint64:
+    case Scalar::MaxTypedArrayViewType:
+    case Scalar::Int64:
+      MOZ_CRASH("Unsupported TypedArray type");
   }
 
+  AutoScratchRegister scratch(allocator, masm);
+
   // Compute the address being written to.
-  LoadTypedThingData(masm, layout, obj, scratch1);
-  Address dest(scratch1, offset);
-
-  StoreToTypedObject(cx_, masm, type, val, dest, scratch2, failure->label());
+  LoadTypedThingData(masm, layout, obj, scratch);
+  Address dest(scratch, offset);
+
+  if (type == Scalar::Float32) {
+    ScratchFloat32Scope fpscratch(masm);
+    masm.convertDoubleToFloat32(FloatReg0, fpscratch);
+    masm.storeToTypedFloatArray(type, fpscratch, dest);
+  } else if (type == Scalar::Float64) {
+    masm.storeToTypedFloatArray(type, FloatReg0, dest);
+  } else {
+    masm.storeToTypedIntArray(type, *valInt32, dest);
+  }
   return true;
 }
 
 static void EmitStoreDenseElement(MacroAssembler& masm,
                                   const ConstantOrRegister& value,
                                   Register elements,
                                   BaseObjectElementIndex target) {
   // If the ObjectElements::CONVERT_DOUBLE_ELEMENTS flag is set, int32 values