diff options
Diffstat (limited to 'js/src/jit/IonBuilder.cpp')
-rw-r--r-- | js/src/jit/IonBuilder.cpp | 435 |
1 files changed, 98 insertions, 337 deletions
diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp index af85011be..2d053de5a 100644 --- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -466,7 +466,8 @@ IonBuilder::canInlineTarget(JSFunction* target, CallInfo& callInfo) // Allow constructing lazy scripts when performing the definite properties // analysis, as baseline has not been used to warm the caller up yet. if (target->isInterpreted() && info().analysisMode() == Analysis_DefiniteProperties) { - RootedScript script(analysisContext, target->getOrCreateScript(analysisContext)); + RootedFunction fun(analysisContext, target); + RootedScript script(analysisContext, JSFunction::getOrCreateScript(analysisContext, fun)); if (!script) return InliningDecision_Error; @@ -1938,6 +1939,7 @@ IonBuilder::inspectOpcode(JSOp op) return jsop_funapply(GET_ARGC(pc)); case JSOP_CALL: + case JSOP_CALL_IGNORES_RV: case JSOP_CALLITER: case JSOP_NEW: case JSOP_SUPERCALL: @@ -1945,7 +1947,8 @@ IonBuilder::inspectOpcode(JSOp op) if (!outermostBuilder()->iterators_.append(current->peek(-1))) return false; } - return jsop_call(GET_ARGC(pc), (JSOp)*pc == JSOP_NEW || (JSOp)*pc == JSOP_SUPERCALL); + return jsop_call(GET_ARGC(pc), (JSOp)*pc == JSOP_NEW || (JSOp)*pc == JSOP_SUPERCALL, + (JSOp)*pc == JSOP_CALL_IGNORES_RV); case JSOP_EVAL: case JSOP_STRICTEVAL: @@ -2218,6 +2221,8 @@ IonBuilder::inspectOpcode(JSOp op) // update that stale value. #endif default: + // Any unused opcodes and JSOP_LIMIT will end up here without having + // to explicitly specify break; } @@ -5871,7 +5876,7 @@ IonBuilder::inlineGenericFallback(JSFunction* target, CallInfo& callInfo, MBasic return false; // Create a new CallInfo to track modified state within this block. - CallInfo fallbackInfo(alloc(), callInfo.constructing()); + CallInfo fallbackInfo(alloc(), callInfo.constructing(), callInfo.ignoresReturnValue()); if (!fallbackInfo.init(callInfo)) return false; fallbackInfo.popFormals(fallbackBlock); @@ -5910,7 +5915,7 @@ IonBuilder::inlineObjectGroupFallback(CallInfo& callInfo, MBasicBlock* dispatchB MOZ_ASSERT(cache->idempotent()); // Create a new CallInfo to track modified state within the fallback path. - CallInfo fallbackInfo(alloc(), callInfo.constructing()); + CallInfo fallbackInfo(alloc(), callInfo.constructing(), callInfo.ignoresReturnValue()); if (!fallbackInfo.init(callInfo)) return false; @@ -6086,7 +6091,7 @@ IonBuilder::inlineCalls(CallInfo& callInfo, const ObjectVector& targets, BoolVec inlineBlock->rewriteSlot(funIndex, funcDef); // Create a new CallInfo to track modified state within the inline block. - CallInfo inlineInfo(alloc(), callInfo.constructing()); + CallInfo inlineInfo(alloc(), callInfo.constructing(), callInfo.ignoresReturnValue()); if (!inlineInfo.init(callInfo)) return false; inlineInfo.popFormals(inlineBlock); @@ -6535,7 +6540,8 @@ IonBuilder::jsop_funcall(uint32_t argc) TemporaryTypeSet* calleeTypes = current->peek(calleeDepth)->resultTypeSet(); JSFunction* native = getSingleCallTarget(calleeTypes); if (!native || !native->isNative() || native->native() != &fun_call) { - CallInfo callInfo(alloc(), false); + CallInfo callInfo(alloc(), /* constructing = */ false, + /* ignoresReturnValue = */ BytecodeIsPopped(pc)); if (!callInfo.init(current, argc)) return false; return makeCall(native, callInfo); @@ -6560,7 +6566,8 @@ IonBuilder::jsop_funcall(uint32_t argc) argc -= 1; } - CallInfo callInfo(alloc(), false); + CallInfo callInfo(alloc(), /* constructing = */ false, + /* ignoresReturnValue = */ BytecodeIsPopped(pc)); if (!callInfo.init(current, argc)) return false; @@ -6597,7 +6604,8 @@ IonBuilder::jsop_funapply(uint32_t argc) TemporaryTypeSet* calleeTypes = current->peek(calleeDepth)->resultTypeSet(); JSFunction* native = getSingleCallTarget(calleeTypes); if (argc != 2 || info().analysisMode() == Analysis_ArgumentsUsage) { - CallInfo callInfo(alloc(), false); + CallInfo callInfo(alloc(), /* constructing = */ false, + /* ignoresReturnValue = */ BytecodeIsPopped(pc)); if (!callInfo.init(current, argc)) return false; return makeCall(native, callInfo); @@ -6626,7 +6634,8 @@ IonBuilder::jsop_funapply(uint32_t argc) return jsop_funapplyarray(argc); } - CallInfo callInfo(alloc(), false); + CallInfo callInfo(alloc(), /* constructing = */ false, + /* ignoresReturnValue = */ BytecodeIsPopped(pc)); if (!callInfo.init(current, argc)) return false; return makeCall(native, callInfo); @@ -6735,7 +6744,8 @@ IonBuilder::jsop_funapplyarguments(uint32_t argc) // can inline the apply() target and don't care about the actual arguments // that were passed in. - CallInfo callInfo(alloc(), false); + CallInfo callInfo(alloc(), /* constructing = */ false, + /* ignoresReturnValue = */ BytecodeIsPopped(pc)); // Vp MDefinition* vp = current->pop(); @@ -6781,7 +6791,7 @@ IonBuilder::jsop_funapplyarguments(uint32_t argc) } bool -IonBuilder::jsop_call(uint32_t argc, bool constructing) +IonBuilder::jsop_call(uint32_t argc, bool constructing, bool ignoresReturnValue) { startTrackingOptimizations(); @@ -6807,7 +6817,7 @@ IonBuilder::jsop_call(uint32_t argc, bool constructing) if (calleeTypes && !getPolyCallTargets(calleeTypes, constructing, targets, 4)) return false; - CallInfo callInfo(alloc(), constructing); + CallInfo callInfo(alloc(), constructing, ignoresReturnValue); if (!callInfo.init(current, argc)) return false; @@ -6943,7 +6953,8 @@ IonBuilder::makeCallHelper(JSFunction* target, CallInfo& callInfo) } MCall* call = MCall::New(alloc(), target, targetArgs + 1 + callInfo.constructing(), - callInfo.argc(), callInfo.constructing(), isDOMCall); + callInfo.argc(), callInfo.constructing(), + callInfo.ignoresReturnValue(), isDOMCall); if (!call) return nullptr; @@ -7044,7 +7055,7 @@ IonBuilder::jsop_eval(uint32_t argc) // Emit a normal call if the eval has never executed. This keeps us from // disabling compilation for the script when testing with --ion-eager. if (calleeTypes && calleeTypes->empty()) - return jsop_call(argc, /* constructing = */ false); + return jsop_call(argc, /* constructing = */ false, false); JSFunction* singleton = getSingleCallTarget(calleeTypes); if (!singleton) @@ -7060,7 +7071,8 @@ IonBuilder::jsop_eval(uint32_t argc) if (info().funMaybeLazy()->isArrow()) return abort("Direct eval from arrow function"); - CallInfo callInfo(alloc(), /* constructing = */ false); + CallInfo callInfo(alloc(), /* constructing = */ false, + /* ignoresReturnValue = */ BytecodeIsPopped(pc)); if (!callInfo.init(current, argc)) return false; callInfo.setImplicitlyUsedUnchecked(); @@ -7099,7 +7111,8 @@ IonBuilder::jsop_eval(uint32_t argc) current->push(dynamicName); current->push(constant(UndefinedValue())); // thisv - CallInfo evalCallInfo(alloc(), /* constructing = */ false); + CallInfo evalCallInfo(alloc(), /* constructing = */ false, + /* ignoresReturnValue = */ BytecodeIsPopped(pc)); if (!evalCallInfo.init(current, /* argc = */ 0)) return false; @@ -7116,7 +7129,7 @@ IonBuilder::jsop_eval(uint32_t argc) return resumeAfter(ins) && pushTypeBarrier(ins, types, BarrierKind::TypeSet); } - return jsop_call(argc, /* constructing = */ false); + return jsop_call(argc, /* constructing = */ false, false); } bool @@ -7336,12 +7349,6 @@ IonBuilder::newArrayTryTemplateObject(bool* emitted, JSObject* templateObject, u if (!templateObject) return true; - if (templateObject->is<UnboxedArrayObject>()) { - MOZ_ASSERT(templateObject->as<UnboxedArrayObject>().capacity() >= length); - if (!templateObject->as<UnboxedArrayObject>().hasInlineElements()) - return true; - } - MOZ_ASSERT(length <= NativeObject::MAX_DENSE_ELEMENTS_COUNT); size_t arraySlots = @@ -7597,7 +7604,6 @@ IonBuilder::jsop_initelem_array() // intializer, and that arrays are marked as non-packed when writing holes // to them during initialization. bool needStub = false; - JSValueType unboxedType = JSVAL_TYPE_MAGIC; if (shouldAbortOnPreliminaryGroups(obj)) { needStub = true; } else if (!obj->resultTypeSet() || @@ -7608,12 +7614,6 @@ IonBuilder::jsop_initelem_array() } else { MOZ_ASSERT(obj->resultTypeSet()->getObjectCount() == 1); TypeSet::ObjectKey* initializer = obj->resultTypeSet()->getObject(0); - if (initializer->clasp() == &UnboxedArrayObject::class_) { - if (initializer->group()->unboxedLayout().nativeGroup()) - needStub = true; - else - unboxedType = initializer->group()->unboxedLayout().elementType(); - } if (value->type() == MIRType::MagicHole) { if (!initializer->hasFlags(constraints(), OBJECT_FLAG_NON_PACKED)) needStub = true; @@ -7633,60 +7633,46 @@ IonBuilder::jsop_initelem_array() return resumeAfter(store); } - return initializeArrayElement(obj, index, value, unboxedType, /* addResumePoint = */ true); + return initializeArrayElement(obj, index, value, /* addResumePoint = */ true); } bool IonBuilder::initializeArrayElement(MDefinition* obj, size_t index, MDefinition* value, - JSValueType unboxedType, bool addResumePointAndIncrementInitializedLength) { MConstant* id = MConstant::New(alloc(), Int32Value(index)); current->add(id); // Get the elements vector. - MElements* elements = MElements::New(alloc(), obj, unboxedType != JSVAL_TYPE_MAGIC); + MElements* elements = MElements::New(alloc(), obj); current->add(elements); - if (unboxedType != JSVAL_TYPE_MAGIC) { - // Note: storeUnboxedValue takes care of any post barriers on the value. - storeUnboxedValue(obj, elements, 0, id, unboxedType, value, /* preBarrier = */ false); - - if (addResumePointAndIncrementInitializedLength) { - MInstruction* increment = MIncrementUnboxedArrayInitializedLength::New(alloc(), obj); - current->add(increment); - - if (!resumeAfter(increment)) - return false; - } - } else { - if (NeedsPostBarrier(value)) - current->add(MPostWriteBarrier::New(alloc(), obj, value)); + if (NeedsPostBarrier(value)) + current->add(MPostWriteBarrier::New(alloc(), obj, value)); - if ((obj->isNewArray() && obj->toNewArray()->convertDoubleElements()) || - (obj->isNullarySharedStub() && - obj->resultTypeSet()->convertDoubleElements(constraints()) == TemporaryTypeSet::AlwaysConvertToDoubles)) - { - MInstruction* valueDouble = MToDouble::New(alloc(), value); - current->add(valueDouble); - value = valueDouble; - } + if ((obj->isNewArray() && obj->toNewArray()->convertDoubleElements()) || + (obj->isNullarySharedStub() && + obj->resultTypeSet()->convertDoubleElements(constraints()) == TemporaryTypeSet::AlwaysConvertToDoubles)) + { + MInstruction* valueDouble = MToDouble::New(alloc(), value); + current->add(valueDouble); + value = valueDouble; + } - // Store the value. - MStoreElement* store = MStoreElement::New(alloc(), elements, id, value, + // Store the value. + MStoreElement* store = MStoreElement::New(alloc(), elements, id, value, /* needsHoleCheck = */ false); - current->add(store); + current->add(store); - if (addResumePointAndIncrementInitializedLength) { - // Update the initialized length. (The template object for this - // array has the array's ultimate length, so the length field is - // already correct: no updating needed.) - MSetInitializedLength* initLength = MSetInitializedLength::New(alloc(), elements, id); - current->add(initLength); + if (addResumePointAndIncrementInitializedLength) { + // Update the initialized length. (The template object for this + // array has the array's ultimate length, so the length field is + // already correct: no updating needed.) + MSetInitializedLength* initLength = MSetInitializedLength::New(alloc(), elements, id); + current->add(initLength); - if (!resumeAfter(initLength)) - return false; - } + if (!resumeAfter(initLength)) + return false; } return true; @@ -8175,8 +8161,7 @@ IonBuilder::maybeMarkEmpty(MDefinition* ins) static bool ClassHasEffectlessLookup(const Class* clasp) { - return (clasp == &UnboxedArrayObject::class_) || - IsTypedObjectClass(clasp) || + return IsTypedObjectClass(clasp) || (clasp->isNative() && !clasp->getOpsLookupProperty()); } @@ -9452,12 +9437,9 @@ IonBuilder::getElemTryDense(bool* emitted, MDefinition* obj, MDefinition* index) { MOZ_ASSERT(*emitted == false); - JSValueType unboxedType = UnboxedArrayElementType(constraints(), obj, index); - if (unboxedType == JSVAL_TYPE_MAGIC) { - if (!ElementAccessIsDenseNative(constraints(), obj, index)) { - trackOptimizationOutcome(TrackedOutcome::AccessNotDense); - return true; - } + if (!ElementAccessIsDenseNative(constraints(), obj, index)) { + trackOptimizationOutcome(TrackedOutcome::AccessNotDense); + return true; } // Don't generate a fast path if there have been bounds check failures @@ -9474,7 +9456,7 @@ IonBuilder::getElemTryDense(bool* emitted, MDefinition* obj, MDefinition* index) return true; } - if (!jsop_getelem_dense(obj, index, unboxedType)) + if (!jsop_getelem_dense(obj, index)) return false; trackOptimizationSuccess(); @@ -9826,7 +9808,7 @@ IonBuilder::computeHeapType(const TemporaryTypeSet* objTypes, const jsid id) } bool -IonBuilder::jsop_getelem_dense(MDefinition* obj, MDefinition* index, JSValueType unboxedType) +IonBuilder::jsop_getelem_dense(MDefinition* obj, MDefinition* index) { TemporaryTypeSet* types = bytecodeTypes(pc); @@ -9850,7 +9832,7 @@ IonBuilder::jsop_getelem_dense(MDefinition* obj, MDefinition* index, JSValueType !ElementAccessHasExtraIndexedProperty(this, obj); MIRType knownType = MIRType::Value; - if (unboxedType == JSVAL_TYPE_MAGIC && barrier == BarrierKind::NoBarrier) + if (barrier == BarrierKind::NoBarrier) knownType = GetElemKnownType(needsHoleCheck, types); // Ensure index is an integer. @@ -9859,13 +9841,13 @@ IonBuilder::jsop_getelem_dense(MDefinition* obj, MDefinition* index, JSValueType index = idInt32; // Get the elements vector. - MInstruction* elements = MElements::New(alloc(), obj, unboxedType != JSVAL_TYPE_MAGIC); + MInstruction* elements = MElements::New(alloc(), obj); current->add(elements); // Note: to help GVN, use the original MElements instruction and not // MConvertElementsToDoubles as operand. This is fine because converting // elements to double does not change the initialized length. - MInstruction* initLength = initializedLength(obj, elements, unboxedType); + MInstruction* initLength = initializedLength(obj, elements); // If we can load the element as a definite double, make sure to check that // the array has been converted to homogenous doubles first. @@ -9881,7 +9863,6 @@ IonBuilder::jsop_getelem_dense(MDefinition* obj, MDefinition* index, JSValueType } bool loadDouble = - unboxedType == JSVAL_TYPE_MAGIC && barrier == BarrierKind::NoBarrier && loopDepth_ && inBounds && @@ -9900,18 +9881,13 @@ IonBuilder::jsop_getelem_dense(MDefinition* obj, MDefinition* index, JSValueType // hoisting. index = addBoundsCheck(index, initLength); - if (unboxedType != JSVAL_TYPE_MAGIC) { - load = loadUnboxedValue(elements, 0, index, unboxedType, barrier, types); - } else { - load = MLoadElement::New(alloc(), elements, index, needsHoleCheck, loadDouble); - current->add(load); - } + load = MLoadElement::New(alloc(), elements, index, needsHoleCheck, loadDouble); + current->add(load); } else { // This load may return undefined, so assume that we *can* read holes, // or that we can read out-of-bounds accesses. In this case, the bounds // check is part of the opcode. - load = MLoadElementHole::New(alloc(), elements, index, initLength, - unboxedType, needsHoleCheck); + load = MLoadElementHole::New(alloc(), elements, index, initLength, needsHoleCheck); current->add(load); // If maybeUndefined was true, the typeset must have undefined, and @@ -9921,8 +9897,7 @@ IonBuilder::jsop_getelem_dense(MDefinition* obj, MDefinition* index, JSValueType } if (knownType != MIRType::Value) { - if (unboxedType == JSVAL_TYPE_MAGIC) - load->setResultType(knownType); + load->setResultType(knownType); load->setResultTypeSet(types); } @@ -10369,12 +10344,9 @@ IonBuilder::setElemTryDense(bool* emitted, MDefinition* object, { MOZ_ASSERT(*emitted == false); - JSValueType unboxedType = UnboxedArrayElementType(constraints(), object, index); - if (unboxedType == JSVAL_TYPE_MAGIC) { - if (!ElementAccessIsDenseNative(constraints(), object, index)) { - trackOptimizationOutcome(TrackedOutcome::AccessNotDense); - return true; - } + if (!ElementAccessIsDenseNative(constraints(), object, index)) { + trackOptimizationOutcome(TrackedOutcome::AccessNotDense); + return true; } if (PropertyWriteNeedsTypeBarrier(alloc(), constraints(), current, @@ -10408,7 +10380,7 @@ IonBuilder::setElemTryDense(bool* emitted, MDefinition* object, } // Emit dense setelem variant. - if (!jsop_setelem_dense(conversion, object, index, value, unboxedType, writeHole, emitted)) + if (!jsop_setelem_dense(conversion, object, index, value, writeHole, emitted)) return false; if (!*emitted) { @@ -10498,13 +10470,11 @@ IonBuilder::setElemTryCache(bool* emitted, MDefinition* object, bool IonBuilder::jsop_setelem_dense(TemporaryTypeSet::DoubleConversion conversion, MDefinition* obj, MDefinition* id, MDefinition* value, - JSValueType unboxedType, bool writeHole, bool* emitted) + bool writeHole, bool* emitted) { MOZ_ASSERT(*emitted == false); - MIRType elementType = MIRType::None; - if (unboxedType == JSVAL_TYPE_MAGIC) - elementType = DenseNativeElementType(constraints(), obj); + MIRType elementType = DenseNativeElementType(constraints(), obj); bool packed = ElementAccessIsPacked(constraints(), obj); // Writes which are on holes in the object do not have to bail out if they @@ -10534,7 +10504,7 @@ IonBuilder::jsop_setelem_dense(TemporaryTypeSet::DoubleConversion conversion, obj = addMaybeCopyElementsForWrite(obj, /* checkNative = */ false); // Get the elements vector. - MElements* elements = MElements::New(alloc(), obj, unboxedType != JSVAL_TYPE_MAGIC); + MElements* elements = MElements::New(alloc(), obj); current->add(elements); // Ensure the value is a double, if double conversion might be needed. @@ -10571,7 +10541,7 @@ IonBuilder::jsop_setelem_dense(TemporaryTypeSet::DoubleConversion conversion, MInstruction* store; MStoreElementCommon* common = nullptr; if (writeHole && hasNoExtraIndexedProperty && !mayBeFrozen) { - MStoreElementHole* ins = MStoreElementHole::New(alloc(), obj, elements, id, newValue, unboxedType); + MStoreElementHole* ins = MStoreElementHole::New(alloc(), obj, elements, id, newValue); store = ins; common = ins; @@ -10583,27 +10553,23 @@ IonBuilder::jsop_setelem_dense(TemporaryTypeSet::DoubleConversion conversion, bool strict = IsStrictSetPC(pc); MFallibleStoreElement* ins = MFallibleStoreElement::New(alloc(), obj, elements, id, - newValue, unboxedType, strict); + newValue, strict); store = ins; common = ins; current->add(ins); current->push(value); } else { - MInstruction* initLength = initializedLength(obj, elements, unboxedType); + MInstruction* initLength = initializedLength(obj, elements); id = addBoundsCheck(id, initLength); bool needsHoleCheck = !packed && !hasNoExtraIndexedProperty; - if (unboxedType != JSVAL_TYPE_MAGIC) { - store = storeUnboxedValue(obj, elements, 0, id, unboxedType, newValue); - } else { - MStoreElement* ins = MStoreElement::New(alloc(), elements, id, newValue, needsHoleCheck); - store = ins; - common = ins; + MStoreElement* ins = MStoreElement::New(alloc(), elements, id, newValue, needsHoleCheck); + store = ins; + common = ins; - current->add(store); - } + current->add(store); current->push(value); } @@ -10721,18 +10687,6 @@ IonBuilder::jsop_length_fastPath() return true; } - // Compute the length for unboxed array objects. - if (UnboxedArrayElementType(constraints(), obj, nullptr) != JSVAL_TYPE_MAGIC && - !objTypes->hasObjectFlags(constraints(), OBJECT_FLAG_LENGTH_OVERFLOW)) - { - current->pop(); - - MUnboxedArrayLength* length = MUnboxedArrayLength::New(alloc(), obj); - current->add(length); - current->push(length); - return true; - } - // Compute the length for array typed objects. TypedObjectPrediction prediction = typedObjectPrediction(obj); if (!prediction.isUseless()) { @@ -10982,63 +10936,6 @@ IonBuilder::getDefiniteSlot(TemporaryTypeSet* types, PropertyName* name, uint32_ return slot; } -uint32_t -IonBuilder::getUnboxedOffset(TemporaryTypeSet* types, PropertyName* name, JSValueType* punboxedType) -{ - if (!types || types->unknownObject() || !types->objectOrSentinel()) { - trackOptimizationOutcome(TrackedOutcome::NoTypeInfo); - return UINT32_MAX; - } - - uint32_t offset = UINT32_MAX; - - for (size_t i = 0; i < types->getObjectCount(); i++) { - TypeSet::ObjectKey* key = types->getObject(i); - if (!key) - continue; - - if (key->unknownProperties()) { - trackOptimizationOutcome(TrackedOutcome::UnknownProperties); - return UINT32_MAX; - } - - if (key->isSingleton()) { - trackOptimizationOutcome(TrackedOutcome::Singleton); - return UINT32_MAX; - } - - UnboxedLayout* layout = key->group()->maybeUnboxedLayout(); - if (!layout) { - trackOptimizationOutcome(TrackedOutcome::NotUnboxed); - return UINT32_MAX; - } - - const UnboxedLayout::Property* property = layout->lookup(name); - if (!property) { - trackOptimizationOutcome(TrackedOutcome::StructNoField); - return UINT32_MAX; - } - - if (layout->nativeGroup()) { - trackOptimizationOutcome(TrackedOutcome::UnboxedConvertedToNative); - return UINT32_MAX; - } - - if (offset == UINT32_MAX) { - offset = property->offset; - *punboxedType = property->type; - } else if (offset != property->offset) { - trackOptimizationOutcome(TrackedOutcome::InconsistentFieldOffset); - return UINT32_MAX; - } else if (*punboxedType != property->type) { - trackOptimizationOutcome(TrackedOutcome::InconsistentFieldType); - return UINT32_MAX; - } - } - - return offset; -} - bool IonBuilder::jsop_runonce() { @@ -12005,72 +11902,6 @@ IonBuilder::getPropTryModuleNamespace(bool* emitted, MDefinition* obj, PropertyN return true; } -MInstruction* -IonBuilder::loadUnboxedProperty(MDefinition* obj, size_t offset, JSValueType unboxedType, - BarrierKind barrier, TemporaryTypeSet* types) -{ - // loadUnboxedValue is designed to load any value as if it were contained in - // an array. Thus a property offset is converted to an index, when the - // object is reinterpreted as an array of properties of the same size. - size_t index = offset / UnboxedTypeSize(unboxedType); - MInstruction* indexConstant = MConstant::New(alloc(), Int32Value(index)); - current->add(indexConstant); - - return loadUnboxedValue(obj, UnboxedPlainObject::offsetOfData(), - indexConstant, unboxedType, barrier, types); -} - -MInstruction* -IonBuilder::loadUnboxedValue(MDefinition* elements, size_t elementsOffset, - MDefinition* index, JSValueType unboxedType, - BarrierKind barrier, TemporaryTypeSet* types) -{ - MInstruction* load; - switch (unboxedType) { - case JSVAL_TYPE_BOOLEAN: - load = MLoadUnboxedScalar::New(alloc(), elements, index, Scalar::Uint8, - DoesNotRequireMemoryBarrier, elementsOffset); - load->setResultType(MIRType::Boolean); - break; - - case JSVAL_TYPE_INT32: - load = MLoadUnboxedScalar::New(alloc(), elements, index, Scalar::Int32, - DoesNotRequireMemoryBarrier, elementsOffset); - load->setResultType(MIRType::Int32); - break; - - case JSVAL_TYPE_DOUBLE: - load = MLoadUnboxedScalar::New(alloc(), elements, index, Scalar::Float64, - DoesNotRequireMemoryBarrier, elementsOffset, - /* canonicalizeDoubles = */ false); - load->setResultType(MIRType::Double); - break; - - case JSVAL_TYPE_STRING: - load = MLoadUnboxedString::New(alloc(), elements, index, elementsOffset); - break; - - case JSVAL_TYPE_OBJECT: { - MLoadUnboxedObjectOrNull::NullBehavior nullBehavior; - if (types->hasType(TypeSet::NullType())) - nullBehavior = MLoadUnboxedObjectOrNull::HandleNull; - else if (barrier != BarrierKind::NoBarrier) - nullBehavior = MLoadUnboxedObjectOrNull::BailOnNull; - else - nullBehavior = MLoadUnboxedObjectOrNull::NullNotPossible; - load = MLoadUnboxedObjectOrNull::New(alloc(), elements, index, nullBehavior, - elementsOffset); - break; - } - - default: - MOZ_CRASH(); - } - - current->add(load); - return load; -} - MDefinition* IonBuilder::addShapeGuardsForGetterSetter(MDefinition* obj, JSObject* holder, Shape* holderShape, const BaselineInspector::ReceiverVector& receivers, @@ -12180,7 +12011,8 @@ IonBuilder::getPropTryCommonGetter(bool* emitted, MDefinition* obj, PropertyName current->push(obj); - CallInfo callInfo(alloc(), false); + CallInfo callInfo(alloc(), /* constructing = */ false, + /* ignoresReturnValue = */ BytecodeIsPopped(pc)); if (!callInfo.init(current, 0)) return false; @@ -12675,7 +12507,8 @@ IonBuilder::setPropTryCommonSetter(bool* emitted, MDefinition* obj, // Call the setter. Note that we have to push the original value, not // the setter's return value. - CallInfo callInfo(alloc(), false); + CallInfo callInfo(alloc(), /* constructing = */ false, + /* ignoresReturnValue = */ BytecodeIsPopped(pc)); if (!callInfo.init(current, 1)) return false; @@ -12892,66 +12725,6 @@ IonBuilder::setPropTryDefiniteSlot(bool* emitted, MDefinition* obj, return true; } -MInstruction* -IonBuilder::storeUnboxedProperty(MDefinition* obj, size_t offset, JSValueType unboxedType, - MDefinition* value) -{ - size_t scaledOffsetConstant = offset / UnboxedTypeSize(unboxedType); - MInstruction* scaledOffset = MConstant::New(alloc(), Int32Value(scaledOffsetConstant)); - current->add(scaledOffset); - - return storeUnboxedValue(obj, obj, UnboxedPlainObject::offsetOfData(), - scaledOffset, unboxedType, value); -} - -MInstruction* -IonBuilder::storeUnboxedValue(MDefinition* obj, MDefinition* elements, int32_t elementsOffset, - MDefinition* scaledOffset, JSValueType unboxedType, - MDefinition* value, bool preBarrier /* = true */) -{ - MInstruction* store; - switch (unboxedType) { - case JSVAL_TYPE_BOOLEAN: - store = MStoreUnboxedScalar::New(alloc(), elements, scaledOffset, value, Scalar::Uint8, - MStoreUnboxedScalar::DontTruncateInput, - DoesNotRequireMemoryBarrier, elementsOffset); - break; - - case JSVAL_TYPE_INT32: - store = MStoreUnboxedScalar::New(alloc(), elements, scaledOffset, value, Scalar::Int32, - MStoreUnboxedScalar::DontTruncateInput, - DoesNotRequireMemoryBarrier, elementsOffset); - break; - - case JSVAL_TYPE_DOUBLE: - store = MStoreUnboxedScalar::New(alloc(), elements, scaledOffset, value, Scalar::Float64, - MStoreUnboxedScalar::DontTruncateInput, - DoesNotRequireMemoryBarrier, elementsOffset); - break; - - case JSVAL_TYPE_STRING: - store = MStoreUnboxedString::New(alloc(), elements, scaledOffset, value, - elementsOffset, preBarrier); - break; - - case JSVAL_TYPE_OBJECT: - MOZ_ASSERT(value->type() == MIRType::Object || - value->type() == MIRType::Null || - value->type() == MIRType::Value); - MOZ_ASSERT(!value->mightBeType(MIRType::Undefined), - "MToObjectOrNull slow path is invalid for unboxed objects"); - store = MStoreUnboxedObjectOrNull::New(alloc(), elements, scaledOffset, value, obj, - elementsOffset, preBarrier); - break; - - default: - MOZ_CRASH(); - } - - current->add(store); - return store; -} - bool IonBuilder::setPropTryInlineAccess(bool* emitted, MDefinition* obj, PropertyName* name, MDefinition* value, @@ -13687,11 +13460,8 @@ IonBuilder::inTryDense(bool* emitted, MDefinition* obj, MDefinition* id) if (shouldAbortOnPreliminaryGroups(obj)) return true; - JSValueType unboxedType = UnboxedArrayElementType(constraints(), obj, id); - if (unboxedType == JSVAL_TYPE_MAGIC) { - if (!ElementAccessIsDenseNative(constraints(), obj, id)) - return true; - } + if (!ElementAccessIsDenseNative(constraints(), obj, id)) + return true; if (ElementAccessHasExtraIndexedProperty(this, obj)) return true; @@ -13706,10 +13476,10 @@ IonBuilder::inTryDense(bool* emitted, MDefinition* obj, MDefinition* id) id = idInt32; // Get the elements vector. - MElements* elements = MElements::New(alloc(), obj, unboxedType != JSVAL_TYPE_MAGIC); + MElements* elements = MElements::New(alloc(), obj); current->add(elements); - MInstruction* initLength = initializedLength(obj, elements, unboxedType); + MInstruction* initLength = initializedLength(obj, elements); // If there are no holes, speculate the InArray check will not fail. if (!needsHoleCheck && !failedBoundsCheck_) { @@ -13719,8 +13489,7 @@ IonBuilder::inTryDense(bool* emitted, MDefinition* obj, MDefinition* id) } // Check if id < initLength and elem[id] not a hole. - MInArray* ins = MInArray::New(alloc(), elements, id, initLength, obj, needsHoleCheck, - unboxedType); + MInArray* ins = MInArray::New(alloc(), elements, id, initLength, obj, needsHoleCheck); current->add(ins); current->push(ins); @@ -14398,32 +14167,24 @@ IonBuilder::constantInt(int32_t i) } MInstruction* -IonBuilder::initializedLength(MDefinition* obj, MDefinition* elements, JSValueType unboxedType) +IonBuilder::initializedLength(MDefinition* obj, MDefinition* elements) { - MInstruction* res; - if (unboxedType != JSVAL_TYPE_MAGIC) - res = MUnboxedArrayInitializedLength::New(alloc(), obj); - else - res = MInitializedLength::New(alloc(), elements); + MInstruction* res = MInitializedLength::New(alloc(), elements); current->add(res); return res; } MInstruction* -IonBuilder::setInitializedLength(MDefinition* obj, JSValueType unboxedType, size_t count) +IonBuilder::setInitializedLength(MDefinition* obj, size_t count) { MOZ_ASSERT(count); - MInstruction* res; - if (unboxedType != JSVAL_TYPE_MAGIC) { - res = MSetUnboxedArrayInitializedLength::New(alloc(), obj, constant(Int32Value(count))); - } else { - // MSetInitializedLength takes the index of the last element, rather - // than the count itself. - MInstruction* elements = MElements::New(alloc(), obj, /* unboxed = */ false); - current->add(elements); - res = MSetInitializedLength::New(alloc(), elements, constant(Int32Value(count - 1))); - } + // MSetInitializedLength takes the index of the last element, rather + // than the count itself. + MInstruction* elements = MElements::New(alloc(), obj, /* unboxed = */ false); + current->add(elements); + MInstruction* res = + MSetInitializedLength::New(alloc(), elements, constant(Int32Value(count - 1))); current->add(res); return res; } |