js/src/jit/x64/CodeGenerator-x64.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
michael@0 2 * vim: set ts=8 sts=4 et sw=4 tw=99:
michael@0 3 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #include "jit/x64/CodeGenerator-x64.h"
michael@0 8
michael@0 9 #include "jit/IonCaches.h"
michael@0 10 #include "jit/MIR.h"
michael@0 11
michael@0 12 #include "jsscriptinlines.h"
michael@0 13
michael@0 14 #include "jit/shared/CodeGenerator-shared-inl.h"
michael@0 15
michael@0 16 using namespace js;
michael@0 17 using namespace js::jit;
michael@0 18
michael@0 19 CodeGeneratorX64::CodeGeneratorX64(MIRGenerator *gen, LIRGraph *graph, MacroAssembler *masm)
michael@0 20 : CodeGeneratorX86Shared(gen, graph, masm)
michael@0 21 {
michael@0 22 }
michael@0 23
michael@0 24 ValueOperand
michael@0 25 CodeGeneratorX64::ToValue(LInstruction *ins, size_t pos)
michael@0 26 {
michael@0 27 return ValueOperand(ToRegister(ins->getOperand(pos)));
michael@0 28 }
michael@0 29
michael@0 30 ValueOperand
michael@0 31 CodeGeneratorX64::ToOutValue(LInstruction *ins)
michael@0 32 {
michael@0 33 return ValueOperand(ToRegister(ins->getDef(0)));
michael@0 34 }
michael@0 35
michael@0 36 ValueOperand
michael@0 37 CodeGeneratorX64::ToTempValue(LInstruction *ins, size_t pos)
michael@0 38 {
michael@0 39 return ValueOperand(ToRegister(ins->getTemp(pos)));
michael@0 40 }
michael@0 41
michael@0 42 FrameSizeClass
michael@0 43 FrameSizeClass::FromDepth(uint32_t frameDepth)
michael@0 44 {
michael@0 45 return FrameSizeClass::None();
michael@0 46 }
michael@0 47
michael@0 48 FrameSizeClass
michael@0 49 FrameSizeClass::ClassLimit()
michael@0 50 {
michael@0 51 return FrameSizeClass(0);
michael@0 52 }
michael@0 53
michael@0 54 uint32_t
michael@0 55 FrameSizeClass::frameSize() const
michael@0 56 {
michael@0 57 MOZ_ASSUME_UNREACHABLE("x64 does not use frame size classes");
michael@0 58 }
michael@0 59
michael@0 60 bool
michael@0 61 CodeGeneratorX64::visitValue(LValue *value)
michael@0 62 {
michael@0 63 LDefinition *reg = value->getDef(0);
michael@0 64 masm.moveValue(value->value(), ToRegister(reg));
michael@0 65 return true;
michael@0 66 }
michael@0 67
michael@0 68 bool
michael@0 69 CodeGeneratorX64::visitBox(LBox *box)
michael@0 70 {
michael@0 71 const LAllocation *in = box->getOperand(0);
michael@0 72 const LDefinition *result = box->getDef(0);
michael@0 73
michael@0 74 if (IsFloatingPointType(box->type())) {
michael@0 75 FloatRegister reg = ToFloatRegister(in);
michael@0 76 if (box->type() == MIRType_Float32) {
michael@0 77 masm.convertFloat32ToDouble(reg, ScratchFloatReg);
michael@0 78 reg = ScratchFloatReg;
michael@0 79 }
michael@0 80 masm.movq(reg, ToRegister(result));
michael@0 81 } else {
michael@0 82 masm.boxValue(ValueTypeFromMIRType(box->type()), ToRegister(in), ToRegister(result));
michael@0 83 }
michael@0 84 return true;
michael@0 85 }
michael@0 86
michael@0 87 bool
michael@0 88 CodeGeneratorX64::visitUnbox(LUnbox *unbox)
michael@0 89 {
michael@0 90 const ValueOperand value = ToValue(unbox, LUnbox::Input);
michael@0 91 const LDefinition *result = unbox->output();
michael@0 92 MUnbox *mir = unbox->mir();
michael@0 93
michael@0 94 if (mir->fallible()) {
michael@0 95 Assembler::Condition cond;
michael@0 96 switch (mir->type()) {
michael@0 97 case MIRType_Int32:
michael@0 98 cond = masm.testInt32(Assembler::NotEqual, value);
michael@0 99 break;
michael@0 100 case MIRType_Boolean:
michael@0 101 cond = masm.testBoolean(Assembler::NotEqual, value);
michael@0 102 break;
michael@0 103 case MIRType_Object:
michael@0 104 cond = masm.testObject(Assembler::NotEqual, value);
michael@0 105 break;
michael@0 106 case MIRType_String:
michael@0 107 cond = masm.testString(Assembler::NotEqual, value);
michael@0 108 break;
michael@0 109 default:
michael@0 110 MOZ_ASSUME_UNREACHABLE("Given MIRType cannot be unboxed.");
michael@0 111 }
michael@0 112 if (!bailoutIf(cond, unbox->snapshot()))
michael@0 113 return false;
michael@0 114 }
michael@0 115
michael@0 116 switch (mir->type()) {
michael@0 117 case MIRType_Int32:
michael@0 118 masm.unboxInt32(value, ToRegister(result));
michael@0 119 break;
michael@0 120 case MIRType_Boolean:
michael@0 121 masm.unboxBoolean(value, ToRegister(result));
michael@0 122 break;
michael@0 123 case MIRType_Object:
michael@0 124 masm.unboxObject(value, ToRegister(result));
michael@0 125 break;
michael@0 126 case MIRType_String:
michael@0 127 masm.unboxString(value, ToRegister(result));
michael@0 128 break;
michael@0 129 default:
michael@0 130 MOZ_ASSUME_UNREACHABLE("Given MIRType cannot be unboxed.");
michael@0 131 }
michael@0 132
michael@0 133 return true;
michael@0 134 }
michael@0 135
michael@0 136 bool
michael@0 137 CodeGeneratorX64::visitLoadSlotV(LLoadSlotV *load)
michael@0 138 {
michael@0 139 ValueOperand dest = ToOutValue(load);
michael@0 140 Register base = ToRegister(load->input());
michael@0 141 int32_t offset = load->mir()->slot() * sizeof(js::Value);
michael@0 142
michael@0 143 masm.loadValue(Address(base, offset), dest);
michael@0 144 return true;
michael@0 145 }
michael@0 146
michael@0 147 void
michael@0 148 CodeGeneratorX64::loadUnboxedValue(Operand source, MIRType type, const LDefinition *dest)
michael@0 149 {
michael@0 150 switch (type) {
michael@0 151 case MIRType_Double:
michael@0 152 masm.loadInt32OrDouble(source, ToFloatRegister(dest));
michael@0 153 break;
michael@0 154
michael@0 155 case MIRType_Object:
michael@0 156 case MIRType_String:
michael@0 157 masm.unboxObject(source, ToRegister(dest));
michael@0 158 break;
michael@0 159
michael@0 160 case MIRType_Int32:
michael@0 161 case MIRType_Boolean:
michael@0 162 masm.movl(source, ToRegister(dest));
michael@0 163 break;
michael@0 164
michael@0 165 default:
michael@0 166 MOZ_ASSUME_UNREACHABLE("unexpected type");
michael@0 167 }
michael@0 168 }
michael@0 169
michael@0 170 bool
michael@0 171 CodeGeneratorX64::visitLoadSlotT(LLoadSlotT *load)
michael@0 172 {
michael@0 173 Register base = ToRegister(load->input());
michael@0 174 int32_t offset = load->mir()->slot() * sizeof(js::Value);
michael@0 175
michael@0 176 loadUnboxedValue(Operand(base, offset), load->mir()->type(), load->output());
michael@0 177
michael@0 178 return true;
michael@0 179 }
michael@0 180
michael@0 181 void
michael@0 182 CodeGeneratorX64::storeUnboxedValue(const LAllocation *value, MIRType valueType,
michael@0 183 Operand dest, MIRType slotType)
michael@0 184 {
michael@0 185 if (valueType == MIRType_Double) {
michael@0 186 masm.storeDouble(ToFloatRegister(value), dest);
michael@0 187 return;
michael@0 188 }
michael@0 189
michael@0 190 // For known integers and booleans, we can just store the unboxed value if
michael@0 191 // the slot has the same type.
michael@0 192 if ((valueType == MIRType_Int32 || valueType == MIRType_Boolean) && slotType == valueType) {
michael@0 193 if (value->isConstant()) {
michael@0 194 Value val = *value->toConstant();
michael@0 195 if (valueType == MIRType_Int32)
michael@0 196 masm.movl(Imm32(val.toInt32()), dest);
michael@0 197 else
michael@0 198 masm.movl(Imm32(val.toBoolean() ? 1 : 0), dest);
michael@0 199 } else {
michael@0 200 masm.movl(ToRegister(value), dest);
michael@0 201 }
michael@0 202 return;
michael@0 203 }
michael@0 204
michael@0 205 if (value->isConstant()) {
michael@0 206 masm.moveValue(*value->toConstant(), ScratchReg);
michael@0 207 masm.movq(ScratchReg, dest);
michael@0 208 } else {
michael@0 209 masm.storeValue(ValueTypeFromMIRType(valueType), ToRegister(value), dest);
michael@0 210 }
michael@0 211 }
michael@0 212
michael@0 213 bool
michael@0 214 CodeGeneratorX64::visitStoreSlotT(LStoreSlotT *store)
michael@0 215 {
michael@0 216 Register base = ToRegister(store->slots());
michael@0 217 int32_t offset = store->mir()->slot() * sizeof(js::Value);
michael@0 218
michael@0 219 const LAllocation *value = store->value();
michael@0 220 MIRType valueType = store->mir()->value()->type();
michael@0 221 MIRType slotType = store->mir()->slotType();
michael@0 222
michael@0 223 if (store->mir()->needsBarrier())
michael@0 224 emitPreBarrier(Address(base, offset), slotType);
michael@0 225
michael@0 226 storeUnboxedValue(value, valueType, Operand(base, offset), slotType);
michael@0 227 return true;
michael@0 228 }
michael@0 229
michael@0 230 bool
michael@0 231 CodeGeneratorX64::visitLoadElementT(LLoadElementT *load)
michael@0 232 {
michael@0 233 Operand source = createArrayElementOperand(ToRegister(load->elements()), load->index());
michael@0 234
michael@0 235 if (load->mir()->loadDoubles()) {
michael@0 236 FloatRegister fpreg = ToFloatRegister(load->output());
michael@0 237 if (source.kind() == Operand::MEM_REG_DISP)
michael@0 238 masm.loadDouble(source.toAddress(), fpreg);
michael@0 239 else
michael@0 240 masm.loadDouble(source.toBaseIndex(), fpreg);
michael@0 241 } else {
michael@0 242 loadUnboxedValue(source, load->mir()->type(), load->output());
michael@0 243 }
michael@0 244
michael@0 245 JS_ASSERT(!load->mir()->needsHoleCheck());
michael@0 246 return true;
michael@0 247 }
michael@0 248
michael@0 249
michael@0 250 void
michael@0 251 CodeGeneratorX64::storeElementTyped(const LAllocation *value, MIRType valueType, MIRType elementType,
michael@0 252 const Register &elements, const LAllocation *index)
michael@0 253 {
michael@0 254 Operand dest = createArrayElementOperand(elements, index);
michael@0 255 storeUnboxedValue(value, valueType, dest, elementType);
michael@0 256 }
michael@0 257
michael@0 258 bool
michael@0 259 CodeGeneratorX64::visitImplicitThis(LImplicitThis *lir)
michael@0 260 {
michael@0 261 Register callee = ToRegister(lir->callee());
michael@0 262
michael@0 263 // The implicit |this| is always |undefined| if the function's environment
michael@0 264 // is the current global.
michael@0 265 GlobalObject *global = &gen->info().script()->global();
michael@0 266 masm.cmpPtr(Operand(callee, JSFunction::offsetOfEnvironment()), ImmGCPtr(global));
michael@0 267
michael@0 268 // TODO: OOL stub path.
michael@0 269 if (!bailoutIf(Assembler::NotEqual, lir->snapshot()))
michael@0 270 return false;
michael@0 271
michael@0 272 masm.moveValue(UndefinedValue(), ToOutValue(lir));
michael@0 273 return true;
michael@0 274 }
michael@0 275
michael@0 276 bool
michael@0 277 CodeGeneratorX64::visitInterruptCheck(LInterruptCheck *lir)
michael@0 278 {
michael@0 279 OutOfLineCode *ool = oolCallVM(InterruptCheckInfo, lir, (ArgList()), StoreNothing());
michael@0 280 if (!ool)
michael@0 281 return false;
michael@0 282
michael@0 283 masm.branch32(Assembler::NotEqual,
michael@0 284 AbsoluteAddress(GetIonContext()->runtime->addressOfInterrupt()), Imm32(0),
michael@0 285 ool->entry());
michael@0 286 masm.bind(ool->rejoin());
michael@0 287 return true;
michael@0 288 }
michael@0 289
michael@0 290 bool
michael@0 291 CodeGeneratorX64::visitCompareB(LCompareB *lir)
michael@0 292 {
michael@0 293 MCompare *mir = lir->mir();
michael@0 294
michael@0 295 const ValueOperand lhs = ToValue(lir, LCompareB::Lhs);
michael@0 296 const LAllocation *rhs = lir->rhs();
michael@0 297 const Register output = ToRegister(lir->output());
michael@0 298
michael@0 299 JS_ASSERT(mir->jsop() == JSOP_STRICTEQ || mir->jsop() == JSOP_STRICTNE);
michael@0 300
michael@0 301 // Load boxed boolean in ScratchReg.
michael@0 302 if (rhs->isConstant())
michael@0 303 masm.moveValue(*rhs->toConstant(), ScratchReg);
michael@0 304 else
michael@0 305 masm.boxValue(JSVAL_TYPE_BOOLEAN, ToRegister(rhs), ScratchReg);
michael@0 306
michael@0 307 // Perform the comparison.
michael@0 308 masm.cmpq(lhs.valueReg(), ScratchReg);
michael@0 309 masm.emitSet(JSOpToCondition(mir->compareType(), mir->jsop()), output);
michael@0 310 return true;
michael@0 311 }
michael@0 312
michael@0 313 bool
michael@0 314 CodeGeneratorX64::visitCompareBAndBranch(LCompareBAndBranch *lir)
michael@0 315 {
michael@0 316 MCompare *mir = lir->cmpMir();
michael@0 317
michael@0 318 const ValueOperand lhs = ToValue(lir, LCompareBAndBranch::Lhs);
michael@0 319 const LAllocation *rhs = lir->rhs();
michael@0 320
michael@0 321 JS_ASSERT(mir->jsop() == JSOP_STRICTEQ || mir->jsop() == JSOP_STRICTNE);
michael@0 322
michael@0 323 // Load boxed boolean in ScratchReg.
michael@0 324 if (rhs->isConstant())
michael@0 325 masm.moveValue(*rhs->toConstant(), ScratchReg);
michael@0 326 else
michael@0 327 masm.boxValue(JSVAL_TYPE_BOOLEAN, ToRegister(rhs), ScratchReg);
michael@0 328
michael@0 329 // Perform the comparison.
michael@0 330 masm.cmpq(lhs.valueReg(), ScratchReg);
michael@0 331 emitBranch(JSOpToCondition(mir->compareType(), mir->jsop()), lir->ifTrue(), lir->ifFalse());
michael@0 332 return true;
michael@0 333 }
michael@0 334 bool
michael@0 335 CodeGeneratorX64::visitCompareV(LCompareV *lir)
michael@0 336 {
michael@0 337 MCompare *mir = lir->mir();
michael@0 338 const ValueOperand lhs = ToValue(lir, LCompareV::LhsInput);
michael@0 339 const ValueOperand rhs = ToValue(lir, LCompareV::RhsInput);
michael@0 340 const Register output = ToRegister(lir->output());
michael@0 341
michael@0 342 JS_ASSERT(IsEqualityOp(mir->jsop()));
michael@0 343
michael@0 344 masm.cmpq(lhs.valueReg(), rhs.valueReg());
michael@0 345 masm.emitSet(JSOpToCondition(mir->compareType(), mir->jsop()), output);
michael@0 346 return true;
michael@0 347 }
michael@0 348
michael@0 349 bool
michael@0 350 CodeGeneratorX64::visitCompareVAndBranch(LCompareVAndBranch *lir)
michael@0 351 {
michael@0 352 MCompare *mir = lir->cmpMir();
michael@0 353
michael@0 354 const ValueOperand lhs = ToValue(lir, LCompareVAndBranch::LhsInput);
michael@0 355 const ValueOperand rhs = ToValue(lir, LCompareVAndBranch::RhsInput);
michael@0 356
michael@0 357 JS_ASSERT(mir->jsop() == JSOP_EQ || mir->jsop() == JSOP_STRICTEQ ||
michael@0 358 mir->jsop() == JSOP_NE || mir->jsop() == JSOP_STRICTNE);
michael@0 359
michael@0 360 masm.cmpq(lhs.valueReg(), rhs.valueReg());
michael@0 361 emitBranch(JSOpToCondition(mir->compareType(), mir->jsop()), lir->ifTrue(), lir->ifFalse());
michael@0 362 return true;
michael@0 363 }
michael@0 364
michael@0 365 bool
michael@0 366 CodeGeneratorX64::visitAsmJSUInt32ToDouble(LAsmJSUInt32ToDouble *lir)
michael@0 367 {
michael@0 368 masm.convertUInt32ToDouble(ToRegister(lir->input()), ToFloatRegister(lir->output()));
michael@0 369 return true;
michael@0 370 }
michael@0 371
michael@0 372 bool
michael@0 373 CodeGeneratorX64::visitAsmJSUInt32ToFloat32(LAsmJSUInt32ToFloat32 *lir)
michael@0 374 {
michael@0 375 masm.convertUInt32ToFloat32(ToRegister(lir->input()), ToFloatRegister(lir->output()));
michael@0 376 return true;
michael@0 377 }
michael@0 378
michael@0 379 bool
michael@0 380 CodeGeneratorX64::visitLoadTypedArrayElementStatic(LLoadTypedArrayElementStatic *ins)
michael@0 381 {
michael@0 382 MOZ_ASSUME_UNREACHABLE("NYI");
michael@0 383 }
michael@0 384
michael@0 385 bool
michael@0 386 CodeGeneratorX64::visitStoreTypedArrayElementStatic(LStoreTypedArrayElementStatic *ins)
michael@0 387 {
michael@0 388 MOZ_ASSUME_UNREACHABLE("NYI");
michael@0 389 }
michael@0 390
michael@0 391 bool
michael@0 392 CodeGeneratorX64::visitAsmJSLoadHeap(LAsmJSLoadHeap *ins)
michael@0 393 {
michael@0 394 MAsmJSLoadHeap *mir = ins->mir();
michael@0 395 ArrayBufferView::ViewType vt = mir->viewType();
michael@0 396 const LAllocation *ptr = ins->ptr();
michael@0 397
michael@0 398 // No need to note the access if it will never fault.
michael@0 399 bool skipNote = mir->skipBoundsCheck();
michael@0 400 Operand srcAddr(HeapReg);
michael@0 401
michael@0 402 if (ptr->isConstant()) {
michael@0 403 int32_t ptrImm = ptr->toConstant()->toInt32();
michael@0 404 // Note only a positive index is accepted here because a negative offset would
michael@0 405 // not wrap back into the protected area reserved for the heap.
michael@0 406 JS_ASSERT(ptrImm >= 0);
michael@0 407 srcAddr = Operand(HeapReg, ptrImm);
michael@0 408 } else {
michael@0 409 srcAddr = Operand(HeapReg, ToRegister(ptr), TimesOne);
michael@0 410 }
michael@0 411
michael@0 412 uint32_t before = masm.size();
michael@0 413 switch (vt) {
michael@0 414 case ArrayBufferView::TYPE_INT8: masm.movsbl(srcAddr, ToRegister(ins->output())); break;
michael@0 415 case ArrayBufferView::TYPE_UINT8: masm.movzbl(srcAddr, ToRegister(ins->output())); break;
michael@0 416 case ArrayBufferView::TYPE_INT16: masm.movswl(srcAddr, ToRegister(ins->output())); break;
michael@0 417 case ArrayBufferView::TYPE_UINT16: masm.movzwl(srcAddr, ToRegister(ins->output())); break;
michael@0 418 case ArrayBufferView::TYPE_INT32:
michael@0 419 case ArrayBufferView::TYPE_UINT32: masm.movl(srcAddr, ToRegister(ins->output())); break;
michael@0 420 case ArrayBufferView::TYPE_FLOAT32: masm.loadFloat32(srcAddr, ToFloatRegister(ins->output())); break;
michael@0 421 case ArrayBufferView::TYPE_FLOAT64: masm.loadDouble(srcAddr, ToFloatRegister(ins->output())); break;
michael@0 422 default: MOZ_ASSUME_UNREACHABLE("unexpected array type");
michael@0 423 }
michael@0 424 uint32_t after = masm.size();
michael@0 425 return skipNote || masm.append(AsmJSHeapAccess(before, after, vt, ToAnyRegister(ins->output())));
michael@0 426 }
michael@0 427
michael@0 428 bool
michael@0 429 CodeGeneratorX64::visitAsmJSStoreHeap(LAsmJSStoreHeap *ins)
michael@0 430 {
michael@0 431 MAsmJSStoreHeap *mir = ins->mir();
michael@0 432 ArrayBufferView::ViewType vt = mir->viewType();
michael@0 433 const LAllocation *ptr = ins->ptr();
michael@0 434 // No need to note the access if it will never fault.
michael@0 435 bool skipNote = mir->skipBoundsCheck();
michael@0 436 Operand dstAddr(HeapReg);
michael@0 437
michael@0 438 if (ptr->isConstant()) {
michael@0 439 int32_t ptrImm = ptr->toConstant()->toInt32();
michael@0 440 // Note only a positive index is accepted here because a negative offset would
michael@0 441 // not wrap back into the protected area reserved for the heap.
michael@0 442 JS_ASSERT(ptrImm >= 0);
michael@0 443 dstAddr = Operand(HeapReg, ptrImm);
michael@0 444 } else {
michael@0 445 dstAddr = Operand(HeapReg, ToRegister(ins->ptr()), TimesOne);
michael@0 446 }
michael@0 447
michael@0 448 uint32_t before = masm.size();
michael@0 449 if (ins->value()->isConstant()) {
michael@0 450 switch (vt) {
michael@0 451 case ArrayBufferView::TYPE_INT8:
michael@0 452 case ArrayBufferView::TYPE_UINT8: masm.movb(Imm32(ToInt32(ins->value())), dstAddr); break;
michael@0 453 case ArrayBufferView::TYPE_INT16:
michael@0 454 case ArrayBufferView::TYPE_UINT16: masm.movw(Imm32(ToInt32(ins->value())), dstAddr); break;
michael@0 455 case ArrayBufferView::TYPE_INT32:
michael@0 456 case ArrayBufferView::TYPE_UINT32: masm.movl(Imm32(ToInt32(ins->value())), dstAddr); break;
michael@0 457 default: MOZ_ASSUME_UNREACHABLE("unexpected array type");
michael@0 458 }
michael@0 459 } else {
michael@0 460 switch (vt) {
michael@0 461 case ArrayBufferView::TYPE_INT8:
michael@0 462 case ArrayBufferView::TYPE_UINT8: masm.movb(ToRegister(ins->value()), dstAddr); break;
michael@0 463 case ArrayBufferView::TYPE_INT16:
michael@0 464 case ArrayBufferView::TYPE_UINT16: masm.movw(ToRegister(ins->value()), dstAddr); break;
michael@0 465 case ArrayBufferView::TYPE_INT32:
michael@0 466 case ArrayBufferView::TYPE_UINT32: masm.movl(ToRegister(ins->value()), dstAddr); break;
michael@0 467 case ArrayBufferView::TYPE_FLOAT32: masm.storeFloat32(ToFloatRegister(ins->value()), dstAddr); break;
michael@0 468 case ArrayBufferView::TYPE_FLOAT64: masm.storeDouble(ToFloatRegister(ins->value()), dstAddr); break;
michael@0 469 default: MOZ_ASSUME_UNREACHABLE("unexpected array type");
michael@0 470 }
michael@0 471 }
michael@0 472 uint32_t after = masm.size();
michael@0 473 return skipNote || masm.append(AsmJSHeapAccess(before, after));
michael@0 474 }
michael@0 475
michael@0 476 bool
michael@0 477 CodeGeneratorX64::visitAsmJSLoadGlobalVar(LAsmJSLoadGlobalVar *ins)
michael@0 478 {
michael@0 479 MAsmJSLoadGlobalVar *mir = ins->mir();
michael@0 480
michael@0 481 CodeOffsetLabel label;
michael@0 482 if (mir->type() == MIRType_Int32)
michael@0 483 label = masm.loadRipRelativeInt32(ToRegister(ins->output()));
michael@0 484 else
michael@0 485 label = masm.loadRipRelativeDouble(ToFloatRegister(ins->output()));
michael@0 486
michael@0 487 return masm.append(AsmJSGlobalAccess(label.offset(), mir->globalDataOffset()));
michael@0 488 }
michael@0 489
michael@0 490 bool
michael@0 491 CodeGeneratorX64::visitAsmJSStoreGlobalVar(LAsmJSStoreGlobalVar *ins)
michael@0 492 {
michael@0 493 MAsmJSStoreGlobalVar *mir = ins->mir();
michael@0 494
michael@0 495 MIRType type = mir->value()->type();
michael@0 496 JS_ASSERT(IsNumberType(type));
michael@0 497
michael@0 498 CodeOffsetLabel label;
michael@0 499 if (type == MIRType_Int32)
michael@0 500 label = masm.storeRipRelativeInt32(ToRegister(ins->value()));
michael@0 501 else
michael@0 502 label = masm.storeRipRelativeDouble(ToFloatRegister(ins->value()));
michael@0 503
michael@0 504 return masm.append(AsmJSGlobalAccess(label.offset(), mir->globalDataOffset()));
michael@0 505 }
michael@0 506
michael@0 507 bool
michael@0 508 CodeGeneratorX64::visitAsmJSLoadFuncPtr(LAsmJSLoadFuncPtr *ins)
michael@0 509 {
michael@0 510 MAsmJSLoadFuncPtr *mir = ins->mir();
michael@0 511
michael@0 512 Register index = ToRegister(ins->index());
michael@0 513 Register tmp = ToRegister(ins->temp());
michael@0 514 Register out = ToRegister(ins->output());
michael@0 515
michael@0 516 CodeOffsetLabel label = masm.leaRipRelative(tmp);
michael@0 517 masm.loadPtr(Operand(tmp, index, TimesEight, 0), out);
michael@0 518
michael@0 519 return masm.append(AsmJSGlobalAccess(label.offset(), mir->globalDataOffset()));
michael@0 520 }
michael@0 521
michael@0 522 bool
michael@0 523 CodeGeneratorX64::visitAsmJSLoadFFIFunc(LAsmJSLoadFFIFunc *ins)
michael@0 524 {
michael@0 525 MAsmJSLoadFFIFunc *mir = ins->mir();
michael@0 526
michael@0 527 CodeOffsetLabel label = masm.loadRipRelativeInt64(ToRegister(ins->output()));
michael@0 528
michael@0 529 return masm.append(AsmJSGlobalAccess(label.offset(), mir->globalDataOffset()));
michael@0 530 }
michael@0 531
michael@0 532 void
michael@0 533 DispatchIonCache::initializeAddCacheState(LInstruction *ins, AddCacheState *addState)
michael@0 534 {
michael@0 535 // Can always use the scratch register on x64.
michael@0 536 addState->dispatchScratch = ScratchReg;
michael@0 537 }
michael@0 538
michael@0 539 bool
michael@0 540 CodeGeneratorX64::visitTruncateDToInt32(LTruncateDToInt32 *ins)
michael@0 541 {
michael@0 542 FloatRegister input = ToFloatRegister(ins->input());
michael@0 543 Register output = ToRegister(ins->output());
michael@0 544
michael@0 545 // On x64, branchTruncateDouble uses cvttsd2sq. Unlike the x86
michael@0 546 // implementation, this should handle most doubles and we can just
michael@0 547 // call a stub if it fails.
michael@0 548 return emitTruncateDouble(input, output);
michael@0 549 }
michael@0 550
michael@0 551 bool
michael@0 552 CodeGeneratorX64::visitTruncateFToInt32(LTruncateFToInt32 *ins)
michael@0 553 {
michael@0 554 FloatRegister input = ToFloatRegister(ins->input());
michael@0 555 Register output = ToRegister(ins->output());
michael@0 556
michael@0 557 // On x64, branchTruncateFloat32 uses cvttss2sq. Unlike the x86
michael@0 558 // implementation, this should handle most floats and we can just
michael@0 559 // call a stub if it fails.
michael@0 560 return emitTruncateFloat32(input, output);
michael@0 561 }

mercurial