bool CodeGeneratorX64::visitAsmJSLoadHeap(LAsmJSLoadHeap *ins) { MAsmJSLoadHeap *mir = ins->mir(); Scalar::Type 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(); JS_ASSERT(ptrImm >= 0); srcAddr = Operand(HeapReg, ptrImm); } else { srcAddr = Operand(HeapReg, ToRegister(ptr), TimesOne); } OutOfLineLoadTypedArrayOutOfBounds *ool = nullptr; uint32_t maybeCmpOffset = AsmJSHeapAccess::NoLengthCheck; if (!mir->skipBoundsCheck()) { bool isFloat32Load = vt == Scalar::Float32; ool = new(alloc()) OutOfLineLoadTypedArrayOutOfBounds(ToAnyRegister(out), isFloat32Load); 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 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; default: MOZ_CRASH("unexpected array type"); } uint32_t after = masm.size(); if (ool) masm.bind(ool->rejoin()); masm.append(AsmJSHeapAccess(before, after, vt, ToAnyRegister(out), maybeCmpOffset)); return true; }
bool CodeGeneratorX64::visitAsmJSLoadHeap(LAsmJSLoadHeap *ins) { MAsmJSLoadHeap *mir = ins->mir(); ArrayBufferView::ViewType vt = mir->viewType(); const LAllocation *ptr = ins->ptr(); // No need to note the access if it will never fault. bool skipNote = mir->skipBoundsCheck(); Operand srcAddr(HeapReg); if (ptr->isConstant()) { int32_t ptrImm = ptr->toConstant()->toInt32(); // Note only a positive index is accepted here because a negative offset would // not wrap back into the protected area reserved for the heap. JS_ASSERT(ptrImm >= 0); srcAddr = Operand(HeapReg, ptrImm); } else { srcAddr = Operand(HeapReg, ToRegister(ptr), TimesOne); } if (vt == ArrayBufferView::TYPE_FLOAT32) { FloatRegister dest = ToFloatRegister(ins->output()); uint32_t before = masm.size(); masm.movss(srcAddr, dest); uint32_t after = masm.size(); masm.cvtss2sd(dest, dest); return skipNote || gen->noteHeapAccess(AsmJSHeapAccess(before, after, vt, ToAnyRegister(ins->output()))); } uint32_t before = masm.size(); switch (vt) { case ArrayBufferView::TYPE_INT8: masm.movsbl(srcAddr, ToRegister(ins->output())); break; case ArrayBufferView::TYPE_UINT8: masm.movzbl(srcAddr, ToRegister(ins->output())); break; case ArrayBufferView::TYPE_INT16: masm.movswl(srcAddr, ToRegister(ins->output())); break; case ArrayBufferView::TYPE_UINT16: masm.movzwl(srcAddr, ToRegister(ins->output())); break; case ArrayBufferView::TYPE_INT32: case ArrayBufferView::TYPE_UINT32: masm.movl(srcAddr, ToRegister(ins->output())); break; case ArrayBufferView::TYPE_FLOAT64: masm.movsd(srcAddr, ToFloatRegister(ins->output())); break; default: MOZ_ASSUME_UNREACHABLE("unexpected array type"); } uint32_t after = masm.size(); return skipNote || gen->noteHeapAccess(AsmJSHeapAccess(before, after, vt, ToAnyRegister(ins->output()))); }