bool CodeGeneratorX64::visitAsmJSLoadFFIFunc(LAsmJSLoadFFIFunc *ins) { MAsmJSLoadFFIFunc *mir = ins->mir(); CodeOffsetLabel label = masm.loadRipRelativeInt64(ToRegister(ins->output())); return gen->noteGlobalAccess(label.offset(), mir->globalDataOffset()); }
bool CodeGeneratorX86::visitAsmJSLoadFFIFunc(LAsmJSLoadFFIFunc *ins) { MAsmJSLoadFFIFunc *mir = ins->mir(); Register out = ToRegister(ins->output()); CodeOffsetLabel label = masm.movlWithPatch(NULL, out); return gen->noteGlobalAccess(label.offset(), mir->globalDataOffset()); }
void CodeGeneratorX64::visitAsmJSLoadHeap(LAsmJSLoadHeap *ins) { MAsmJSLoadHeap *mir = ins->mir(); Scalar::Type vt = mir->accessType(); const LAllocation *ptr = ins->ptr(); const LDefinition *out = ins->output(); Operand srcAddr(HeapReg); if (Scalar::isSimdType(vt)) return emitSimdLoad(ins); if (ptr->isConstant()) { int32_t ptrImm = ptr->toConstant()->toInt32(); MOZ_ASSERT(ptrImm >= 0); srcAddr = Operand(HeapReg, ptrImm); } else { srcAddr = Operand(HeapReg, ToRegister(ptr), TimesOne); } memoryBarrier(ins->mir()->barrierBefore()); OutOfLineLoadTypedArrayOutOfBounds *ool = nullptr; uint32_t maybeCmpOffset = AsmJSHeapAccess::NoLengthCheck; if (mir->needsBoundsCheck()) { CodeOffsetLabel cmp = masm.cmp32WithPatch(ToRegister(ptr), Imm32(0)); ool = new(alloc()) OutOfLineLoadTypedArrayOutOfBounds(ToAnyRegister(out), vt); addOutOfLineCode(ool, ins->mir()); masm.j(Assembler::AboveOrEqual, ool->entry()); maybeCmpOffset = cmp.offset(); } uint32_t before = masm.size(); switch (vt) { case Scalar::Int8: masm.movsbl(srcAddr, ToRegister(out)); break; case Scalar::Uint8: masm.movzbl(srcAddr, ToRegister(out)); break; case Scalar::Int16: masm.movswl(srcAddr, ToRegister(out)); break; case Scalar::Uint16: masm.movzwl(srcAddr, ToRegister(out)); break; case Scalar::Int32: case Scalar::Uint32: masm.movl(srcAddr, ToRegister(out)); break; case Scalar::Float32: masm.loadFloat32(srcAddr, ToFloatRegister(out)); break; case Scalar::Float64: masm.loadDouble(srcAddr, ToFloatRegister(out)); break; case Scalar::Float32x4: case Scalar::Int32x4: MOZ_CRASH("SIMD loads should be handled in emitSimdLoad"); case Scalar::Uint8Clamped: case Scalar::MaxTypedArrayViewType: MOZ_CRASH("unexpected array type"); } uint32_t after = masm.size(); verifyHeapAccessDisassembly(before, after, /*isLoad=*/true, vt, srcAddr, *out->output()); if (ool) masm.bind(ool->rejoin()); memoryBarrier(ins->mir()->barrierAfter()); masm.append(AsmJSHeapAccess(before, after, vt, ToAnyRegister(out), maybeCmpOffset)); }
bool CodeGeneratorX64::visitAsmJSStoreHeap(LAsmJSStoreHeap *ins) { MAsmJSStoreHeap *mir = ins->mir(); Scalar::Type vt = mir->viewType(); const LAllocation *ptr = ins->ptr(); Operand dstAddr(HeapReg); if (ptr->isConstant()) { int32_t ptrImm = ptr->toConstant()->toInt32(); JS_ASSERT(ptrImm >= 0); dstAddr = Operand(HeapReg, ptrImm); } else { dstAddr = Operand(HeapReg, ToRegister(ptr), TimesOne); } Label rejoin; uint32_t maybeCmpOffset = AsmJSHeapAccess::NoLengthCheck; if (!mir->skipBoundsCheck()) { CodeOffsetLabel cmp = masm.cmplWithPatch(ToRegister(ptr), Imm32(0)); masm.j(Assembler::AboveOrEqual, &rejoin); maybeCmpOffset = cmp.offset(); } uint32_t before = masm.size(); if (ins->value()->isConstant()) { switch (vt) { case Scalar::Int8: case Scalar::Uint8: masm.movb(Imm32(ToInt32(ins->value())), dstAddr); break; case Scalar::Int16: case Scalar::Uint16: masm.movw(Imm32(ToInt32(ins->value())), dstAddr); break; case Scalar::Int32: case Scalar::Uint32: masm.movl(Imm32(ToInt32(ins->value())), dstAddr); break; default: MOZ_CRASH("unexpected array type"); } } else { switch (vt) { case Scalar::Int8: case Scalar::Uint8: masm.movb(ToRegister(ins->value()), dstAddr); break; case Scalar::Int16: case Scalar::Uint16: masm.movw(ToRegister(ins->value()), dstAddr); break; case Scalar::Int32: case Scalar::Uint32: masm.movl(ToRegister(ins->value()), dstAddr); break; case Scalar::Float32: masm.storeFloat32(ToFloatRegister(ins->value()), dstAddr); break; case Scalar::Float64: masm.storeDouble(ToFloatRegister(ins->value()), dstAddr); break; default: MOZ_CRASH("unexpected array type"); } } uint32_t after = masm.size(); if (rejoin.used()) masm.bind(&rejoin); masm.append(AsmJSHeapAccess(before, after, maybeCmpOffset)); return true; }
bool CodeGeneratorX86::visitAsmJSLoadHeap(LAsmJSLoadHeap *ins) { const MAsmJSLoadHeap *mir = ins->mir(); ArrayBufferView::ViewType vt = mir->viewType(); Register ptr = ToRegister(ins->ptr()); const LDefinition *out = ins->output(); OutOfLineAsmJSLoadHeapOutOfBounds *ool = new OutOfLineAsmJSLoadHeapOutOfBounds(ToAnyRegister(out)); if (!addOutOfLineCode(ool)) return false; CodeOffsetLabel cmp = masm.cmplWithPatch(ptr, Imm32(0)); masm.j(Assembler::AboveOrEqual, ool->entry()); Address srcAddr(ptr, 0); if (vt == ArrayBufferView::TYPE_FLOAT32) { FloatRegister dest = ToFloatRegister(out); uint32_t before = masm.size(); masm.movssWithPatch(srcAddr, dest); uint32_t after = masm.size(); masm.cvtss2sd(dest, dest); masm.bind(ool->rejoin()); return gen->noteHeapAccess(AsmJSHeapAccess(cmp.offset(), before, after, vt, AnyRegister(dest))); } uint32_t before = masm.size(); switch (vt) { case ArrayBufferView::TYPE_INT8: masm.movxblWithPatch(srcAddr, ToRegister(out)); break; case ArrayBufferView::TYPE_UINT8: masm.movzblWithPatch(srcAddr, ToRegister(out)); break; case ArrayBufferView::TYPE_INT16: masm.movxwlWithPatch(srcAddr, ToRegister(out)); break; case ArrayBufferView::TYPE_UINT16: masm.movzwlWithPatch(srcAddr, ToRegister(out)); break; case ArrayBufferView::TYPE_INT32: masm.movlWithPatch(srcAddr, ToRegister(out)); break; case ArrayBufferView::TYPE_UINT32: masm.movlWithPatch(srcAddr, ToRegister(out)); break; case ArrayBufferView::TYPE_FLOAT64: masm.movsdWithPatch(srcAddr, ToFloatRegister(out)); break; default: JS_NOT_REACHED("unexpected array type"); } uint32_t after = masm.size(); masm.bind(ool->rejoin()); return gen->noteHeapAccess(AsmJSHeapAccess(cmp.offset(), before, after, vt, ToAnyRegister(out))); }
bool CodeGeneratorX64::visitAsmJSLoadGlobalVar(LAsmJSLoadGlobalVar *ins) { MAsmJSLoadGlobalVar *mir = ins->mir(); CodeOffsetLabel label; if (mir->type() == MIRType_Int32) label = masm.loadRipRelativeInt32(ToRegister(ins->output())); else label = masm.loadRipRelativeDouble(ToFloatRegister(ins->output())); return gen->noteGlobalAccess(label.offset(), mir->globalDataOffset()); }
bool CodeGeneratorX86::visitAsmJSLoadGlobalVar(LAsmJSLoadGlobalVar *ins) { MAsmJSLoadGlobalVar *mir = ins->mir(); CodeOffsetLabel label; if (mir->type() == MIRType_Int32) label = masm.movlWithPatch(NULL, ToRegister(ins->output())); else label = masm.movsdWithPatch(NULL, ToFloatRegister(ins->output())); return gen->noteGlobalAccess(label.offset(), mir->globalDataOffset()); }
bool CodeGeneratorX64::visitAsmJSLoadHeap(LAsmJSLoadHeap *ins) { MAsmJSLoadHeap *mir = ins->mir(); AsmJSHeapAccess::ViewType vt = mir->viewType(); const LAllocation *ptr = ins->ptr(); const LDefinition *out = ins->output(); Operand srcAddr(HeapReg); if (ptr->isConstant()) { int32_t ptrImm = ptr->toConstant()->toInt32(); MOZ_ASSERT(ptrImm >= 0); srcAddr = Operand(HeapReg, ptrImm); } else { srcAddr = Operand(HeapReg, ToRegister(ptr), TimesOne); } memoryBarrier(ins->mir()->barrierBefore()); OutOfLineLoadTypedArrayOutOfBounds *ool = nullptr; uint32_t maybeCmpOffset = AsmJSHeapAccess::NoLengthCheck; if (mir->needsBoundsCheck()) { ool = new(alloc()) OutOfLineLoadTypedArrayOutOfBounds(ToAnyRegister(out), vt); if (!addOutOfLineCode(ool, ins->mir())) return false; CodeOffsetLabel cmp = masm.cmplWithPatch(ToRegister(ptr), Imm32(0)); masm.j(Assembler::AboveOrEqual, ool->entry()); maybeCmpOffset = cmp.offset(); } uint32_t before = masm.size(); switch (vt) { case AsmJSHeapAccess::Int8: masm.movsbl(srcAddr, ToRegister(out)); break; case AsmJSHeapAccess::Uint8: masm.movzbl(srcAddr, ToRegister(out)); break; case AsmJSHeapAccess::Int16: masm.movswl(srcAddr, ToRegister(out)); break; case AsmJSHeapAccess::Uint16: masm.movzwl(srcAddr, ToRegister(out)); break; case AsmJSHeapAccess::Int32: case AsmJSHeapAccess::Uint32: masm.movl(srcAddr, ToRegister(out)); break; case AsmJSHeapAccess::Float32: masm.loadFloat32(srcAddr, ToFloatRegister(out)); break; case AsmJSHeapAccess::Float64: masm.loadDouble(srcAddr, ToFloatRegister(out)); break; case AsmJSHeapAccess::Float32x4: masm.loadUnalignedFloat32x4(srcAddr, ToFloatRegister(out)); break; case AsmJSHeapAccess::Int32x4: masm.loadUnalignedInt32x4(srcAddr, ToFloatRegister(out)); break; case AsmJSHeapAccess::Uint8Clamped: MOZ_CRASH("unexpected array type"); } uint32_t after = masm.size(); if (ool) masm.bind(ool->rejoin()); memoryBarrier(ins->mir()->barrierAfter()); masm.append(AsmJSHeapAccess(before, after, vt, ToAnyRegister(out), maybeCmpOffset)); return true; }
bool CodeGeneratorX64::visitAsmJSLoadFuncPtr(LAsmJSLoadFuncPtr *ins) { MAsmJSLoadFuncPtr *mir = ins->mir(); Register index = ToRegister(ins->index()); Register tmp = ToRegister(ins->temp()); Register out = ToRegister(ins->output()); CodeOffsetLabel label = masm.leaRipRelative(tmp); masm.loadPtr(Operand(tmp, index, TimesEight, 0), out); return gen->noteGlobalAccess(label.offset(), mir->globalDataOffset()); }
bool CodeGeneratorX86::visitAsmJSStoreHeap(LAsmJSStoreHeap *ins) { MAsmJSStoreHeap *mir = ins->mir(); ArrayBufferView::ViewType vt = mir->viewType(); Register ptr = ToRegister(ins->ptr()); const LAllocation *value = ins->value(); CodeOffsetLabel cmp = masm.cmplWithPatch(ptr, Imm32(0)); Label rejoin; masm.j(Assembler::AboveOrEqual, &rejoin); Address dstAddr(ptr, 0); if (vt == ArrayBufferView::TYPE_FLOAT32) { masm.convertDoubleToFloat(ToFloatRegister(value), ScratchFloatReg); uint32_t before = masm.size(); masm.movssWithPatch(ScratchFloatReg, dstAddr); uint32_t after = masm.size(); masm.bind(&rejoin); return gen->noteHeapAccess(AsmJSHeapAccess(cmp.offset(), before, after)); } uint32_t before = masm.size(); switch (vt) { case ArrayBufferView::TYPE_INT8: masm.movbWithPatch(ToRegister(value), dstAddr); break; case ArrayBufferView::TYPE_UINT8: masm.movbWithPatch(ToRegister(value), dstAddr); break; case ArrayBufferView::TYPE_INT16: masm.movwWithPatch(ToRegister(value), dstAddr); break; case ArrayBufferView::TYPE_UINT16: masm.movwWithPatch(ToRegister(value), dstAddr); break; case ArrayBufferView::TYPE_INT32: masm.movlWithPatch(ToRegister(value), dstAddr); break; case ArrayBufferView::TYPE_UINT32: masm.movlWithPatch(ToRegister(value), dstAddr); break; case ArrayBufferView::TYPE_FLOAT64: masm.movsdWithPatch(ToFloatRegister(value), dstAddr); break; default: JS_NOT_REACHED("unexpected array type"); } uint32_t after = masm.size(); masm.bind(&rejoin); return gen->noteHeapAccess(AsmJSHeapAccess(cmp.offset(), before, after)); }
bool CodeGeneratorX64::visitAsmJSStoreGlobalVar(LAsmJSStoreGlobalVar *ins) { MAsmJSStoreGlobalVar *mir = ins->mir(); MIRType type = mir->value()->type(); JS_ASSERT(type == MIRType_Int32 || type == MIRType_Double); CodeOffsetLabel label; if (type == MIRType_Int32) label = masm.storeRipRelativeInt32(ToRegister(ins->value())); else label = masm.storeRipRelativeDouble(ToFloatRegister(ins->value())); return gen->noteGlobalAccess(label.offset(), mir->globalDataOffset()); }
void CodeGeneratorX64::visitAsmJSStoreHeap(LAsmJSStoreHeap *ins) { MAsmJSStoreHeap *mir = ins->mir(); Scalar::Type vt = mir->accessType(); const LAllocation *ptr = ins->ptr(); Operand dstAddr(HeapReg); if (Scalar::isSimdType(vt)) return emitSimdStore(ins); if (ptr->isConstant()) { int32_t ptrImm = ptr->toConstant()->toInt32(); MOZ_ASSERT(ptrImm >= 0); dstAddr = Operand(HeapReg, ptrImm); } else { dstAddr = Operand(HeapReg, ToRegister(ptr), TimesOne); } memoryBarrier(ins->mir()->barrierBefore()); Label rejoin; uint32_t maybeCmpOffset = AsmJSHeapAccess::NoLengthCheck; if (mir->needsBoundsCheck()) { CodeOffsetLabel cmp = masm.cmp32WithPatch(ToRegister(ptr), Imm32(0)); masm.j(Assembler::AboveOrEqual, &rejoin); maybeCmpOffset = cmp.offset(); } uint32_t before = masm.size(); if (ins->value()->isConstant()) { switch (vt) { case Scalar::Int8: case Scalar::Uint8: masm.movb(Imm32(ToInt32(ins->value())), dstAddr); break; case Scalar::Int16: case Scalar::Uint16: masm.movw(Imm32(ToInt32(ins->value())), dstAddr); break; case Scalar::Int32: case Scalar::Uint32: masm.movl(Imm32(ToInt32(ins->value())), dstAddr); break; case Scalar::Float32: case Scalar::Float64: case Scalar::Float32x4: case Scalar::Int32x4: case Scalar::Uint8Clamped: case Scalar::MaxTypedArrayViewType: MOZ_CRASH("unexpected array type"); } } else { switch (vt) { case Scalar::Int8: case Scalar::Uint8: masm.movb(ToRegister(ins->value()), dstAddr); break; case Scalar::Int16: case Scalar::Uint16: masm.movw(ToRegister(ins->value()), dstAddr); break; case Scalar::Int32: case Scalar::Uint32: masm.movl(ToRegister(ins->value()), dstAddr); break; case Scalar::Float32: masm.storeFloat32(ToFloatRegister(ins->value()), dstAddr); break; case Scalar::Float64: masm.storeDouble(ToFloatRegister(ins->value()), dstAddr); break; case Scalar::Float32x4: case Scalar::Int32x4: MOZ_CRASH("SIMD stores must be handled in emitSimdStore"); case Scalar::Uint8Clamped: case Scalar::MaxTypedArrayViewType: MOZ_CRASH("unexpected array type"); } } uint32_t after = masm.size(); verifyHeapAccessDisassembly(before, after, /*isLoad=*/false, vt, dstAddr, *ins->value()); if (rejoin.used()) masm.bind(&rejoin); memoryBarrier(ins->mir()->barrierAfter()); masm.append(AsmJSHeapAccess(before, after, vt, maybeCmpOffset)); }