From 149c050c0399629efad21ff43da4df27f97d7917 Mon Sep 17 00:00:00 2001
From: Jon Coppeard <jcoppeard@mozilla.com>
Date: Tue, 13 Apr 2021 15:51:45 +0000
Subject: [PATCH] Bug 1704576 - Make the CacheIR plain object op handle failure
 by calling into the VM rather than failing the stub r=jandem

Differential Revision: https://phabricator.services.mozilla.com/D111687
---
 js/src/jit/CacheIRCompiler.cpp  | 31 ++++++++++++++++++++++---------
 js/src/jit/VMFunctionList-inl.h |  1 +
 js/src/vm/Interpreter.cpp       |  8 ++++++++
 js/src/vm/Interpreter.h         |  4 ++++
 js/src/vm/JSContext.h           |  2 +-
 5 files changed, 36 insertions(+), 10 deletions(-)

diff --git a/js/src/jit/CacheIRCompiler.cpp b/js/src/jit/CacheIRCompiler.cpp
index 4726787326ae8..ba53d7574f1b2 100644
--- a/js/src/jit/CacheIRCompiler.cpp
+++ b/js/src/jit/CacheIRCompiler.cpp
@@ -6106,24 +6106,37 @@ bool CacheIRCompiler::emitNewPlainObjectResult(uint32_t numFixedSlots,
                                                gc::AllocKind allocKind,
                                                uint32_t shapeOffset) {
   JitSpew(JitSpew_Codegen, "%s", __FUNCTION__);
-  AutoOutputRegister output(*this);
+  AutoCallVM callvm(masm, this, allocator);
   AutoScratchRegister obj(allocator, masm);
   AutoScratchRegister scratch(allocator, masm);
-  AutoScratchRegisterMaybeOutput shape(allocator, masm, output);
+  AutoScratchRegisterMaybeOutput shape(allocator, masm, callvm.output());
 
   StubFieldOffset shapeSlot(shapeOffset, StubField::Type::Shape);
 
-  FailurePath* failure;
-  if (!addFailurePath(&failure)) {
-    return false;
-  }
+  Label success;
+  Label fail;
 
   emitLoadStubField(shapeSlot, shape);
   masm.createPlainGCObject(obj, shape, scratch, shape, numFixedSlots,
-                           numDynamicSlots, allocKind, gc::DefaultHeap,
-                           failure->label());
+                           numDynamicSlots, allocKind, gc::DefaultHeap, &fail);
+  masm.tagValue(JSVAL_TYPE_OBJECT, obj, callvm.output().valueReg());
+  masm.jump(&success);
 
-  masm.tagValue(JSVAL_TYPE_OBJECT, obj, output.valueReg());
+  masm.bind(&fail);
+
+  // We get here if the nursery is full (unlikely) but also if the current arena
+  // is full and we need to allocate a new one (fairly common).
+
+  callvm.prepare();
+  masm.Push(Imm32(gc::DefaultHeap));
+  masm.Push(Imm32(int32_t(allocKind)));
+  masm.Push(shape);
+
+  using Fn =
+      JSObject* (*)(JSContext*, HandleShape, gc::AllocKind, gc::InitialHeap);
+  callvm.call<Fn, NewPlainObject>();
+
+  masm.bind(&success);
   return true;
 }
 
diff --git a/js/src/jit/VMFunctionList-inl.h b/js/src/jit/VMFunctionList-inl.h
index f63afca394097..9a0ecb82c038a 100644
--- a/js/src/jit/VMFunctionList-inl.h
+++ b/js/src/jit/VMFunctionList-inl.h
@@ -192,6 +192,7 @@ namespace jit {
   _(NewCallObject, js::jit::NewCallObject)                                     \
   _(NewObjectOperation, js::NewObjectOperation)                                \
   _(NewObjectOperationWithTemplate, js::NewObjectOperationWithTemplate)        \
+  _(NewPlainObject, js::NewPlainObject)                                        \
   _(NewRegExpStringIterator, js::NewRegExpStringIterator)                      \
   _(NewStringIterator, js::NewStringIterator)                                  \
   _(NewStringObject, js::jit::NewStringObject)                                 \
diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp
index c7eceb3aa3130..dcfd9e33a190f 100644
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -5051,6 +5051,14 @@ JSObject* js::NewObjectOperationWithTemplate(JSContext* cx,
   return CopyTemplateObject(cx, templateObject.as<PlainObject>(), newKind);
 }
 
+JSObject* js::NewPlainObject(JSContext* cx, HandleShape shape,
+                             gc::AllocKind allocKind,
+                             gc::InitialHeap initialHeap) {
+  MOZ_ASSERT(shape->getObjectClass() == &PlainObject::class_);
+  auto r = NativeObject::create(cx, allocKind, initialHeap, shape);
+  return cx->resultToPtr(r);
+}
+
 JSObject* js::CreateThisWithTemplate(JSContext* cx,
                                      HandleObject templateObject) {
   mozilla::Maybe<AutoRealm> ar;
diff --git a/js/src/vm/Interpreter.h b/js/src/vm/Interpreter.h
index c6d3f2fd58d95..98e655646f894 100644
--- a/js/src/vm/Interpreter.h
+++ b/js/src/vm/Interpreter.h
@@ -620,6 +620,10 @@ JSObject* NewObjectOperation(JSContext* cx, HandleScript script, jsbytecode* pc,
 
 JSObject* NewObjectOperationWithTemplate(JSContext* cx,
                                          HandleObject templateObject);
+
+JSObject* NewPlainObject(JSContext* cx, HandleShape shape,
+                         gc::AllocKind allocKind, gc::InitialHeap initialHeap);
+
 JSObject* CreateThisWithTemplate(JSContext* cx, HandleObject templateObject);
 
 ArrayObject* NewArrayOperation(JSContext* cx, uint32_t length,
diff --git a/js/src/vm/JSContext.h b/js/src/vm/JSContext.h
index 873d8a860ad56..5f0d0b346c8e9 100644
--- a/js/src/vm/JSContext.h
+++ b/js/src/vm/JSContext.h
@@ -422,7 +422,7 @@ struct JS_PUBLIC_API JSContext : public JS::RootingContext,
   }
 
   template <typename V, typename E>
-  V* resultToPtr(const JS::Result<V*, E>& result) {
+  V* resultToPtr(JS::Result<V*, E>& result) {
     return result.isOk() ? result.unwrap() : nullptr;
   }
 
-- 
GitLab