From 16e41aaea6e6be65dec66629d471c86fc0cc6976 Mon Sep 17 00:00:00 2001 From: Iain Ireland Date: Wed, 12 Oct 2022 17:27:17 +0000 Subject: [PATCH] Bug 1792228: Use LoadObject instead of LoadProto for proto shape guards r=jandem We noticed this while looking at the CacheIR generated for an add-slot stub. The depth threshold of 4 was picked by browsing around on the web and dumping the observed depth. 4 is enough to cover 95%+ of the cases I saw. There are a couple of other places where we use LoadProto: the no-teleporting case in `GeneratePrototypeGuards`, and `ShapeGuardPrototypeChainForCrossCompartmentHolder`. They didn't show up in my experiments, so I left them alone for now. Differential Revision: https://phabricator.services.mozilla.com/D158037 --- js/src/jit/CacheIR.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/js/src/jit/CacheIR.cpp b/js/src/jit/CacheIR.cpp index 0d80154061e7..dc2954816c82 100644 --- a/js/src/jit/CacheIR.cpp +++ b/js/src/jit/CacheIR.cpp @@ -762,6 +762,9 @@ static void TestMatchingHolder(CacheIRWriter& writer, NativeObject* obj, // Note: this relies on shape implying proto. static void ShapeGuardProtoChain(CacheIRWriter& writer, NativeObject* obj, ObjOperandId objId) { + uint32_t depth = 0; + static const uint32_t MAX_CACHED_LOADS = 4; + while (true) { JSObject* proto = obj->staticPrototype(); if (!proto) { @@ -769,7 +772,18 @@ static void ShapeGuardProtoChain(CacheIRWriter& writer, NativeObject* obj, } obj = &proto->as(); - objId = writer.loadProto(objId); + + // After guarding the shape of an object, we can safely bake that + // object's proto into the stub data. Compared to LoadProto, this + // takes one load instead of three (object -> shape -> baseshape + // -> proto). We cap the depth to avoid bloating the size of the + // stub data. + if (depth < MAX_CACHED_LOADS) { + objId = writer.loadObject(obj); + } else { + objId = writer.loadProto(objId); + } + depth++; writer.guardShape(objId, obj->shape()); }