Bug 1618198 part 23 - Implement InitProp* and InitElem* ops. r=iain
authorJan de Mooij <jdemooij@mozilla.com>
Tue, 24 Mar 2020 07:04:44 +0000
changeset 520190 f9e0bd856b82937448f46fb137644f00218b9056
parent 520189 1f0b527ef54c4725dce4bcd3aa852f2b7c2133eb
child 520191 c447b127f99ef167c83888f53aed2cac7c850d9c
push id37245
push useropoprus@mozilla.com
push dateTue, 24 Mar 2020 21:46:41 +0000
treeherdermozilla-central@dbabf2e388fa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersiain
bugs1618198
milestone76.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 1618198 part 23 - Implement InitProp* and InitElem* ops. r=iain This adds buildInitPropOp instead of reusing buildSetPropOp because there are some subtle differences between Init and Set. Longer term we should consider splitting the MIR and CacheIR code as well so it becomes easier to reason about. Differential Revision: https://phabricator.services.mozilla.com/D67804
js/src/jit/WarpBuilder.cpp
js/src/jit/WarpBuilder.h
js/src/vm/BytecodeLocation.h
--- a/js/src/jit/WarpBuilder.cpp
+++ b/js/src/jit/WarpBuilder.cpp
@@ -2155,8 +2155,80 @@ bool WarpBuilder::build_GetPropSuper(Byt
 
 bool WarpBuilder::build_GetElemSuper(BytecodeLocation loc) {
   MDefinition* obj = current->pop();
   MDefinition* id = current->pop();
   MDefinition* receiver = current->pop();
 
   return buildGetPropSuperOp(loc, obj, receiver, id);
 }
+
+bool WarpBuilder::buildInitPropOp(BytecodeLocation loc, MDefinition* obj,
+                                  MDefinition* id, MDefinition* val) {
+  // We need a GC post barrier. We don't need a TI barrier. We pass true for
+  // guardHoles, although the prototype chain is ignored for InitProp/InitElem.
+  bool strict = false;
+  bool needsPostBarrier = true;
+  bool needsTypeBarrier = false;
+  bool guardHoles = true;
+  auto* ins =
+      MSetPropertyCache::New(alloc(), obj, id, val, strict, needsPostBarrier,
+                             needsTypeBarrier, guardHoles);
+  current->add(ins);
+  return resumeAfter(ins, loc);
+}
+
+bool WarpBuilder::build_InitProp(BytecodeLocation loc) {
+  MDefinition* val = current->pop();
+  MDefinition* obj = current->peek(-1);
+
+  PropertyName* name = loc.getPropertyName(script_);
+  MConstant* id = constant(StringValue(name));
+
+  return buildInitPropOp(loc, obj, id, val);
+}
+
+bool WarpBuilder::build_InitLockedProp(BytecodeLocation loc) {
+  return build_InitProp(loc);
+}
+
+bool WarpBuilder::build_InitHiddenProp(BytecodeLocation loc) {
+  return build_InitProp(loc);
+}
+
+bool WarpBuilder::build_InitElem(BytecodeLocation loc) {
+  MDefinition* val = current->pop();
+  MDefinition* id = current->pop();
+  MDefinition* obj = current->peek(-1);
+  return buildInitPropOp(loc, obj, id, val);
+}
+
+bool WarpBuilder::build_InitHiddenElem(BytecodeLocation loc) {
+  return build_InitElem(loc);
+}
+
+bool WarpBuilder::build_InitElemArray(BytecodeLocation loc) {
+  MDefinition* val = current->pop();
+  MDefinition* obj = current->peek(-1);
+
+  // Note: getInitElemArrayIndex asserts the index fits in int32_t.
+  uint32_t index = loc.getInitElemArrayIndex();
+  MConstant* indexConst = constant(Int32Value(index));
+
+  // TODO: we can probably just use MStoreElement like IonBuilder's fast path.
+  // Simpler than IonBuilder because we don't have to worry about maintaining TI
+  // invariants.
+  return buildInitPropOp(loc, obj, indexConst, val);
+}
+
+bool WarpBuilder::build_InitElemInc(BytecodeLocation loc) {
+  MDefinition* val = current->pop();
+  MDefinition* index = current->pop();
+  MDefinition* obj = current->peek(-1);
+
+  // Push index + 1.
+  MConstant* constOne = constant(Int32Value(1));
+  MAdd* nextIndex = MAdd::New(alloc(), index, constOne, MIRType::Int32);
+  current->add(nextIndex);
+  current->push(nextIndex);
+
+  return buildInitPropOp(loc, obj, index, val);
+}
--- a/js/src/jit/WarpBuilder.h
+++ b/js/src/jit/WarpBuilder.h
@@ -187,16 +187,23 @@ namespace jit {
   _(Instanceof)             \
   _(NewTarget)              \
   _(CheckIsObj)             \
   _(CheckIsCallable)        \
   _(CheckObjCoercible)      \
   _(GetImport)              \
   _(GetPropSuper)           \
   _(GetElemSuper)           \
+  _(InitProp)               \
+  _(InitLockedProp)         \
+  _(InitHiddenProp)         \
+  _(InitElem)               \
+  _(InitHiddenElem)         \
+  _(InitElemArray)          \
+  _(InitElemInc)            \
   _(SetRval)                \
   _(Return)                 \
   _(RetRval)
 
 class MIRGenerator;
 class MIRGraph;
 class WarpSnapshot;
 
@@ -283,16 +290,18 @@ class MOZ_STACK_CLASS WarpBuilder {
   MOZ_MUST_USE bool buildCallOp(BytecodeLocation loc);
 
   MOZ_MUST_USE bool buildGetNameOp(BytecodeLocation loc, MDefinition* env);
   MOZ_MUST_USE bool buildBindNameOp(BytecodeLocation loc, MDefinition* env);
   MOZ_MUST_USE bool buildGetPropOp(BytecodeLocation loc, MDefinition* val,
                                    MDefinition* id);
   MOZ_MUST_USE bool buildSetPropOp(BytecodeLocation loc, MDefinition* obj,
                                    MDefinition* id, MDefinition* val);
+  MOZ_MUST_USE bool buildInitPropOp(BytecodeLocation loc, MDefinition* obj,
+                                    MDefinition* id, MDefinition* val);
   MOZ_MUST_USE bool buildGetPropSuperOp(BytecodeLocation loc, MDefinition* obj,
                                         MDefinition* receiver, MDefinition* id);
 
   MOZ_MUST_USE bool buildInitPropGetterSetterOp(BytecodeLocation loc);
   MOZ_MUST_USE bool buildInitElemGetterSetterOp(BytecodeLocation loc);
 
   void buildCopyLexicalEnvOp(bool copySlots);
   void buildCheckLexicalOp(BytecodeLocation loc);
--- a/js/src/vm/BytecodeLocation.h
+++ b/js/src/vm/BytecodeLocation.h
@@ -244,16 +244,25 @@ class BytecodeLocation {
     return EnvironmentCoordinate(rawBytecode_);
   }
 
   uint32_t getCallArgc() const {
     MOZ_ASSERT(JOF_OPTYPE(getOp()) == JOF_ARGC);
     return GET_ARGC(rawBytecode_);
   }
 
+  uint32_t getInitElemArrayIndex() const {
+    MOZ_ASSERT(is(JSOp::InitElemArray));
+    uint32_t index = GET_UINT32(rawBytecode_);
+    MOZ_ASSERT(index <= INT32_MAX,
+               "the bytecode emitter must never generate JSOp::InitElemArray "
+               "with an index exceeding int32_t range");
+    return index;
+  }
+
   FunctionPrefixKind getFunctionPrefixKind() const {
     MOZ_ASSERT(is(JSOp::SetFunName));
     return FunctionPrefixKind(GET_UINT8(rawBytecode_));
   }
 
   CheckIsObjectKind getCheckIsObjectKind() const {
     MOZ_ASSERT(is(JSOp::CheckIsObj));
     return CheckIsObjectKind(GET_UINT8(rawBytecode_));