bool LMoveGroup::add(LAllocation from, LAllocation to, LDefinition::Type type) { #ifdef DEBUG MOZ_ASSERT(from != to); for (size_t i = 0; i < moves_.length(); i++) MOZ_ASSERT(to != moves_[i].to()); // Check that SIMD moves are aligned according to ABI requirements. if (LDefinition(type).isSimdType()) { MOZ_ASSERT(from.isMemory() || from.isFloatReg()); if (from.isMemory()) { if (from.isArgument()) MOZ_ASSERT(from.toArgument()->index() % SimdMemoryAlignment == 0); else MOZ_ASSERT(from.toStackSlot()->slot() % SimdMemoryAlignment == 0); } MOZ_ASSERT(to.isMemory() || to.isFloatReg()); if (to.isMemory()) { if (to.isArgument()) MOZ_ASSERT(to.toArgument()->index() % SimdMemoryAlignment == 0); else MOZ_ASSERT(to.toStackSlot()->slot() % SimdMemoryAlignment == 0); } } #endif return moves_.append(LMove(from, to, type)); }
bool AllocationIntegrityState::checkSafepointAllocation(LInstruction* ins, uint32_t vreg, LAllocation alloc, bool populateSafepoints) { LSafepoint* safepoint = ins->safepoint(); MOZ_ASSERT(safepoint); if (ins->isCall() && alloc.isRegister()) return true; if (alloc.isRegister()) { AnyRegister reg = alloc.toRegister(); if (populateSafepoints) safepoint->addLiveRegister(reg); MOZ_ASSERT(safepoint->liveRegs().has(reg)); } // The |this| argument slot is implicitly included in all safepoints. if (alloc.isArgument() && alloc.toArgument()->index() < THIS_FRAME_ARGSLOT + sizeof(Value)) return true; LDefinition::Type type = virtualRegisters[vreg] ? virtualRegisters[vreg]->type() : LDefinition::GENERAL; switch (type) { case LDefinition::OBJECT: if (populateSafepoints) { JitSpew(JitSpew_RegAlloc, "Safepoint object v%u i%u %s", vreg, ins->id(), alloc.toString()); if (!safepoint->addGcPointer(alloc)) return false; } MOZ_ASSERT(safepoint->hasGcPointer(alloc)); break; case LDefinition::SLOTS: if (populateSafepoints) { JitSpew(JitSpew_RegAlloc, "Safepoint slots v%u i%u %s", vreg, ins->id(), alloc.toString()); if (!safepoint->addSlotsOrElementsPointer(alloc)) return false; } MOZ_ASSERT(safepoint->hasSlotsOrElementsPointer(alloc)); break; #ifdef JS_NUNBOX32 // Do not assert that safepoint information for nunbox types is complete, // as if a vreg for a value's components are copied in multiple places // then the safepoint information may not reflect all copies. All copies // of payloads must be reflected, however, for generational GC. case LDefinition::TYPE: if (populateSafepoints) { JitSpew(JitSpew_RegAlloc, "Safepoint type v%u i%u %s", vreg, ins->id(), alloc.toString()); if (!safepoint->addNunboxType(vreg, alloc)) return false; } break; case LDefinition::PAYLOAD: if (populateSafepoints) { JitSpew(JitSpew_RegAlloc, "Safepoint payload v%u i%u %s", vreg, ins->id(), alloc.toString()); if (!safepoint->addNunboxPayload(vreg, alloc)) return false; } MOZ_ASSERT(safepoint->hasNunboxPayload(alloc)); break; #else case LDefinition::BOX: if (populateSafepoints) { JitSpew(JitSpew_RegAlloc, "Safepoint boxed value v%u i%u %s", vreg, ins->id(), alloc.toString()); if (!safepoint->addBoxedValue(alloc)) return false; } MOZ_ASSERT(safepoint->hasBoxedValue(alloc)); break; #endif default: break; } return true; }