1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/jit/x86/MacroAssembler-x86.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1134 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99: 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef jit_x86_MacroAssembler_x86_h 1.11 +#define jit_x86_MacroAssembler_x86_h 1.12 + 1.13 +#include "jscompartment.h" 1.14 + 1.15 +#include "jit/IonFrames.h" 1.16 +#include "jit/MoveResolver.h" 1.17 +#include "jit/shared/MacroAssembler-x86-shared.h" 1.18 + 1.19 +namespace js { 1.20 +namespace jit { 1.21 + 1.22 +class MacroAssemblerX86 : public MacroAssemblerX86Shared 1.23 +{ 1.24 + // Number of bytes the stack is adjusted inside a call to C. Calls to C may 1.25 + // not be nested. 1.26 + bool inCall_; 1.27 + uint32_t args_; 1.28 + uint32_t passedArgs_; 1.29 + uint32_t stackForCall_; 1.30 + bool dynamicAlignment_; 1.31 + bool enoughMemory_; 1.32 + 1.33 + struct Double { 1.34 + double value; 1.35 + AbsoluteLabel uses; 1.36 + Double(double value) : value(value) {} 1.37 + }; 1.38 + Vector<Double, 0, SystemAllocPolicy> doubles_; 1.39 + struct Float { 1.40 + float value; 1.41 + AbsoluteLabel uses; 1.42 + Float(float value) : value(value) {} 1.43 + }; 1.44 + Vector<Float, 0, SystemAllocPolicy> floats_; 1.45 + 1.46 + typedef HashMap<double, size_t, DefaultHasher<double>, SystemAllocPolicy> DoubleMap; 1.47 + DoubleMap doubleMap_; 1.48 + typedef HashMap<float, size_t, DefaultHasher<float>, SystemAllocPolicy> FloatMap; 1.49 + FloatMap floatMap_; 1.50 + 1.51 + Double *getDouble(double d); 1.52 + Float *getFloat(float f); 1.53 + 1.54 + protected: 1.55 + MoveResolver moveResolver_; 1.56 + 1.57 + private: 1.58 + Operand payloadOf(const Address &address) { 1.59 + return Operand(address.base, address.offset); 1.60 + } 1.61 + Operand tagOf(const Address &address) { 1.62 + return Operand(address.base, address.offset + 4); 1.63 + } 1.64 + Operand tagOf(const BaseIndex &address) { 1.65 + return Operand(address.base, address.index, address.scale, address.offset + 4); 1.66 + } 1.67 + 1.68 + void setupABICall(uint32_t args); 1.69 + 1.70 + public: 1.71 + using MacroAssemblerX86Shared::Push; 1.72 + using MacroAssemblerX86Shared::Pop; 1.73 + using MacroAssemblerX86Shared::callWithExitFrame; 1.74 + using MacroAssemblerX86Shared::branch32; 1.75 + using MacroAssemblerX86Shared::load32; 1.76 + using MacroAssemblerX86Shared::store32; 1.77 + using MacroAssemblerX86Shared::call; 1.78 + 1.79 + MacroAssemblerX86() 1.80 + : inCall_(false), 1.81 + enoughMemory_(true) 1.82 + { 1.83 + } 1.84 + 1.85 + // The buffer is about to be linked, make sure any constant pools or excess 1.86 + // bookkeeping has been flushed to the instruction stream. 1.87 + void finish(); 1.88 + 1.89 + bool oom() const { 1.90 + return MacroAssemblerX86Shared::oom() || !enoughMemory_; 1.91 + } 1.92 + 1.93 + ///////////////////////////////////////////////////////////////// 1.94 + // X86-specific interface. 1.95 + ///////////////////////////////////////////////////////////////// 1.96 + 1.97 + Operand ToPayload(Operand base) { 1.98 + return base; 1.99 + } 1.100 + Address ToPayload(Address base) { 1.101 + return base; 1.102 + } 1.103 + Operand ToType(Operand base) { 1.104 + switch (base.kind()) { 1.105 + case Operand::MEM_REG_DISP: 1.106 + return Operand(Register::FromCode(base.base()), base.disp() + sizeof(void *)); 1.107 + 1.108 + case Operand::MEM_SCALE: 1.109 + return Operand(Register::FromCode(base.base()), Register::FromCode(base.index()), 1.110 + base.scale(), base.disp() + sizeof(void *)); 1.111 + 1.112 + default: 1.113 + MOZ_ASSUME_UNREACHABLE("unexpected operand kind"); 1.114 + } 1.115 + } 1.116 + Address ToType(Address base) { 1.117 + return ToType(Operand(base)).toAddress(); 1.118 + } 1.119 + void moveValue(const Value &val, Register type, Register data) { 1.120 + jsval_layout jv = JSVAL_TO_IMPL(val); 1.121 + movl(Imm32(jv.s.tag), type); 1.122 + if (val.isMarkable()) 1.123 + movl(ImmGCPtr(reinterpret_cast<gc::Cell *>(val.toGCThing())), data); 1.124 + else 1.125 + movl(Imm32(jv.s.payload.i32), data); 1.126 + } 1.127 + void moveValue(const Value &val, const ValueOperand &dest) { 1.128 + moveValue(val, dest.typeReg(), dest.payloadReg()); 1.129 + } 1.130 + void moveValue(const ValueOperand &src, const ValueOperand &dest) { 1.131 + Register s0 = src.typeReg(), d0 = dest.typeReg(), 1.132 + s1 = src.payloadReg(), d1 = dest.payloadReg(); 1.133 + 1.134 + // Either one or both of the source registers could be the same as a 1.135 + // destination register. 1.136 + if (s1 == d0) { 1.137 + if (s0 == d1) { 1.138 + // If both are, this is just a swap of two registers. 1.139 + xchgl(d0, d1); 1.140 + return; 1.141 + } 1.142 + // If only one is, copy that source first. 1.143 + mozilla::Swap(s0, s1); 1.144 + mozilla::Swap(d0, d1); 1.145 + } 1.146 + 1.147 + if (s0 != d0) 1.148 + movl(s0, d0); 1.149 + if (s1 != d1) 1.150 + movl(s1, d1); 1.151 + } 1.152 + 1.153 + ///////////////////////////////////////////////////////////////// 1.154 + // X86/X64-common interface. 1.155 + ///////////////////////////////////////////////////////////////// 1.156 + void storeValue(ValueOperand val, Operand dest) { 1.157 + movl(val.payloadReg(), ToPayload(dest)); 1.158 + movl(val.typeReg(), ToType(dest)); 1.159 + } 1.160 + void storeValue(ValueOperand val, const Address &dest) { 1.161 + storeValue(val, Operand(dest)); 1.162 + } 1.163 + template <typename T> 1.164 + void storeValue(JSValueType type, Register reg, const T &dest) { 1.165 + storeTypeTag(ImmTag(JSVAL_TYPE_TO_TAG(type)), Operand(dest)); 1.166 + storePayload(reg, Operand(dest)); 1.167 + } 1.168 + template <typename T> 1.169 + void storeValue(const Value &val, const T &dest) { 1.170 + jsval_layout jv = JSVAL_TO_IMPL(val); 1.171 + storeTypeTag(ImmTag(jv.s.tag), Operand(dest)); 1.172 + storePayload(val, Operand(dest)); 1.173 + } 1.174 + void storeValue(ValueOperand val, BaseIndex dest) { 1.175 + storeValue(val, Operand(dest)); 1.176 + } 1.177 + void loadValue(Operand src, ValueOperand val) { 1.178 + Operand payload = ToPayload(src); 1.179 + Operand type = ToType(src); 1.180 + 1.181 + // Ensure that loading the payload does not erase the pointer to the 1.182 + // Value in memory or the index. 1.183 + Register baseReg = Register::FromCode(src.base()); 1.184 + Register indexReg = (src.kind() == Operand::MEM_SCALE) ? Register::FromCode(src.index()) : InvalidReg; 1.185 + 1.186 + if (baseReg == val.payloadReg() || indexReg == val.payloadReg()) { 1.187 + JS_ASSERT(baseReg != val.typeReg()); 1.188 + JS_ASSERT(indexReg != val.typeReg()); 1.189 + 1.190 + movl(type, val.typeReg()); 1.191 + movl(payload, val.payloadReg()); 1.192 + } else { 1.193 + JS_ASSERT(baseReg != val.payloadReg()); 1.194 + JS_ASSERT(indexReg != val.payloadReg()); 1.195 + 1.196 + movl(payload, val.payloadReg()); 1.197 + movl(type, val.typeReg()); 1.198 + } 1.199 + } 1.200 + void loadValue(Address src, ValueOperand val) { 1.201 + loadValue(Operand(src), val); 1.202 + } 1.203 + void loadValue(const BaseIndex &src, ValueOperand val) { 1.204 + loadValue(Operand(src), val); 1.205 + } 1.206 + void tagValue(JSValueType type, Register payload, ValueOperand dest) { 1.207 + JS_ASSERT(dest.typeReg() != dest.payloadReg()); 1.208 + if (payload != dest.payloadReg()) 1.209 + movl(payload, dest.payloadReg()); 1.210 + movl(ImmType(type), dest.typeReg()); 1.211 + } 1.212 + void pushValue(ValueOperand val) { 1.213 + push(val.typeReg()); 1.214 + push(val.payloadReg()); 1.215 + } 1.216 + void popValue(ValueOperand val) { 1.217 + pop(val.payloadReg()); 1.218 + pop(val.typeReg()); 1.219 + } 1.220 + void pushValue(const Value &val) { 1.221 + jsval_layout jv = JSVAL_TO_IMPL(val); 1.222 + push(Imm32(jv.s.tag)); 1.223 + if (val.isMarkable()) 1.224 + push(ImmGCPtr(reinterpret_cast<gc::Cell *>(val.toGCThing()))); 1.225 + else 1.226 + push(Imm32(jv.s.payload.i32)); 1.227 + } 1.228 + void pushValue(JSValueType type, Register reg) { 1.229 + push(ImmTag(JSVAL_TYPE_TO_TAG(type))); 1.230 + push(reg); 1.231 + } 1.232 + void pushValue(const Address &addr) { 1.233 + push(tagOf(addr)); 1.234 + push(payloadOf(addr)); 1.235 + } 1.236 + void Push(const ValueOperand &val) { 1.237 + pushValue(val); 1.238 + framePushed_ += sizeof(Value); 1.239 + } 1.240 + void Pop(const ValueOperand &val) { 1.241 + popValue(val); 1.242 + framePushed_ -= sizeof(Value); 1.243 + } 1.244 + void storePayload(const Value &val, Operand dest) { 1.245 + jsval_layout jv = JSVAL_TO_IMPL(val); 1.246 + if (val.isMarkable()) 1.247 + movl(ImmGCPtr((gc::Cell *)jv.s.payload.ptr), ToPayload(dest)); 1.248 + else 1.249 + movl(Imm32(jv.s.payload.i32), ToPayload(dest)); 1.250 + } 1.251 + void storePayload(Register src, Operand dest) { 1.252 + movl(src, ToPayload(dest)); 1.253 + } 1.254 + void storeTypeTag(ImmTag tag, Operand dest) { 1.255 + movl(tag, ToType(dest)); 1.256 + } 1.257 + 1.258 + void movePtr(const Register &src, const Register &dest) { 1.259 + movl(src, dest); 1.260 + } 1.261 + void movePtr(const Register &src, const Operand &dest) { 1.262 + movl(src, dest); 1.263 + } 1.264 + 1.265 + // Returns the register containing the type tag. 1.266 + Register splitTagForTest(const ValueOperand &value) { 1.267 + return value.typeReg(); 1.268 + } 1.269 + 1.270 + Condition testUndefined(Condition cond, const Register &tag) { 1.271 + JS_ASSERT(cond == Equal || cond == NotEqual); 1.272 + cmpl(tag, ImmTag(JSVAL_TAG_UNDEFINED)); 1.273 + return cond; 1.274 + } 1.275 + Condition testBoolean(Condition cond, const Register &tag) { 1.276 + JS_ASSERT(cond == Equal || cond == NotEqual); 1.277 + cmpl(tag, ImmTag(JSVAL_TAG_BOOLEAN)); 1.278 + return cond; 1.279 + } 1.280 + Condition testInt32(Condition cond, const Register &tag) { 1.281 + JS_ASSERT(cond == Equal || cond == NotEqual); 1.282 + cmpl(tag, ImmTag(JSVAL_TAG_INT32)); 1.283 + return cond; 1.284 + } 1.285 + Condition testDouble(Condition cond, const Register &tag) { 1.286 + JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual); 1.287 + Condition actual = (cond == Equal) ? Below : AboveOrEqual; 1.288 + cmpl(tag, ImmTag(JSVAL_TAG_CLEAR)); 1.289 + return actual; 1.290 + } 1.291 + Condition testNull(Condition cond, const Register &tag) { 1.292 + JS_ASSERT(cond == Equal || cond == NotEqual); 1.293 + cmpl(tag, ImmTag(JSVAL_TAG_NULL)); 1.294 + return cond; 1.295 + } 1.296 + Condition testString(Condition cond, const Register &tag) { 1.297 + JS_ASSERT(cond == Equal || cond == NotEqual); 1.298 + cmpl(tag, ImmTag(JSVAL_TAG_STRING)); 1.299 + return cond; 1.300 + } 1.301 + Condition testObject(Condition cond, const Register &tag) { 1.302 + JS_ASSERT(cond == Equal || cond == NotEqual); 1.303 + cmpl(tag, ImmTag(JSVAL_TAG_OBJECT)); 1.304 + return cond; 1.305 + } 1.306 + Condition testNumber(Condition cond, const Register &tag) { 1.307 + JS_ASSERT(cond == Equal || cond == NotEqual); 1.308 + cmpl(tag, ImmTag(JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET)); 1.309 + return cond == Equal ? BelowOrEqual : Above; 1.310 + } 1.311 + Condition testGCThing(Condition cond, const Register &tag) { 1.312 + JS_ASSERT(cond == Equal || cond == NotEqual); 1.313 + cmpl(tag, ImmTag(JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET)); 1.314 + return cond == Equal ? AboveOrEqual : Below; 1.315 + } 1.316 + Condition testGCThing(Condition cond, const Address &address) { 1.317 + JS_ASSERT(cond == Equal || cond == NotEqual); 1.318 + cmpl(tagOf(address), ImmTag(JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET)); 1.319 + return cond == Equal ? AboveOrEqual : Below; 1.320 + } 1.321 + Condition testMagic(Condition cond, const Address &address) { 1.322 + JS_ASSERT(cond == Equal || cond == NotEqual); 1.323 + cmpl(tagOf(address), ImmTag(JSVAL_TAG_MAGIC)); 1.324 + return cond; 1.325 + } 1.326 + Condition testMagic(Condition cond, const Register &tag) { 1.327 + JS_ASSERT(cond == Equal || cond == NotEqual); 1.328 + cmpl(tag, ImmTag(JSVAL_TAG_MAGIC)); 1.329 + return cond; 1.330 + } 1.331 + Condition testMagic(Condition cond, const Operand &operand) { 1.332 + JS_ASSERT(cond == Equal || cond == NotEqual); 1.333 + cmpl(ToType(operand), ImmTag(JSVAL_TAG_MAGIC)); 1.334 + return cond; 1.335 + } 1.336 + Condition testPrimitive(Condition cond, const Register &tag) { 1.337 + JS_ASSERT(cond == Equal || cond == NotEqual); 1.338 + cmpl(tag, ImmTag(JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET)); 1.339 + return cond == Equal ? Below : AboveOrEqual; 1.340 + } 1.341 + Condition testError(Condition cond, const Register &tag) { 1.342 + return testMagic(cond, tag); 1.343 + } 1.344 + Condition testInt32(Condition cond, const Operand &operand) { 1.345 + JS_ASSERT(cond == Equal || cond == NotEqual); 1.346 + cmpl(ToType(operand), ImmTag(JSVAL_TAG_INT32)); 1.347 + return cond; 1.348 + } 1.349 + Condition testInt32(Condition cond, const Address &address) { 1.350 + JS_ASSERT(cond == Equal || cond == NotEqual); 1.351 + return testInt32(cond, Operand(address)); 1.352 + } 1.353 + Condition testDouble(Condition cond, const Operand &operand) { 1.354 + JS_ASSERT(cond == Equal || cond == NotEqual); 1.355 + Condition actual = (cond == Equal) ? Below : AboveOrEqual; 1.356 + cmpl(ToType(operand), ImmTag(JSVAL_TAG_CLEAR)); 1.357 + return actual; 1.358 + } 1.359 + Condition testDouble(Condition cond, const Address &address) { 1.360 + JS_ASSERT(cond == Equal || cond == NotEqual); 1.361 + return testDouble(cond, Operand(address)); 1.362 + } 1.363 + 1.364 + 1.365 + Condition testUndefined(Condition cond, const Operand &operand) { 1.366 + JS_ASSERT(cond == Equal || cond == NotEqual); 1.367 + cmpl(ToType(operand), ImmTag(JSVAL_TAG_UNDEFINED)); 1.368 + return cond; 1.369 + } 1.370 + Condition testUndefined(Condition cond, const Address &addr) { 1.371 + return testUndefined(cond, Operand(addr)); 1.372 + } 1.373 + 1.374 + 1.375 + Condition testUndefined(Condition cond, const ValueOperand &value) { 1.376 + return testUndefined(cond, value.typeReg()); 1.377 + } 1.378 + Condition testBoolean(Condition cond, const ValueOperand &value) { 1.379 + return testBoolean(cond, value.typeReg()); 1.380 + } 1.381 + Condition testInt32(Condition cond, const ValueOperand &value) { 1.382 + return testInt32(cond, value.typeReg()); 1.383 + } 1.384 + Condition testDouble(Condition cond, const ValueOperand &value) { 1.385 + return testDouble(cond, value.typeReg()); 1.386 + } 1.387 + Condition testNull(Condition cond, const ValueOperand &value) { 1.388 + return testNull(cond, value.typeReg()); 1.389 + } 1.390 + Condition testString(Condition cond, const ValueOperand &value) { 1.391 + return testString(cond, value.typeReg()); 1.392 + } 1.393 + Condition testObject(Condition cond, const ValueOperand &value) { 1.394 + return testObject(cond, value.typeReg()); 1.395 + } 1.396 + Condition testMagic(Condition cond, const ValueOperand &value) { 1.397 + return testMagic(cond, value.typeReg()); 1.398 + } 1.399 + Condition testError(Condition cond, const ValueOperand &value) { 1.400 + return testMagic(cond, value); 1.401 + } 1.402 + Condition testNumber(Condition cond, const ValueOperand &value) { 1.403 + return testNumber(cond, value.typeReg()); 1.404 + } 1.405 + Condition testGCThing(Condition cond, const ValueOperand &value) { 1.406 + return testGCThing(cond, value.typeReg()); 1.407 + } 1.408 + Condition testPrimitive(Condition cond, const ValueOperand &value) { 1.409 + return testPrimitive(cond, value.typeReg()); 1.410 + } 1.411 + 1.412 + 1.413 + Condition testUndefined(Condition cond, const BaseIndex &address) { 1.414 + JS_ASSERT(cond == Equal || cond == NotEqual); 1.415 + cmpl(tagOf(address), ImmTag(JSVAL_TAG_UNDEFINED)); 1.416 + return cond; 1.417 + } 1.418 + Condition testNull(Condition cond, const BaseIndex &address) { 1.419 + JS_ASSERT(cond == Equal || cond == NotEqual); 1.420 + cmpl(tagOf(address), ImmTag(JSVAL_TAG_NULL)); 1.421 + return cond; 1.422 + } 1.423 + Condition testBoolean(Condition cond, const BaseIndex &address) { 1.424 + JS_ASSERT(cond == Equal || cond == NotEqual); 1.425 + cmpl(tagOf(address), ImmTag(JSVAL_TAG_BOOLEAN)); 1.426 + return cond; 1.427 + } 1.428 + Condition testString(Condition cond, const BaseIndex &address) { 1.429 + JS_ASSERT(cond == Equal || cond == NotEqual); 1.430 + cmpl(tagOf(address), ImmTag(JSVAL_TAG_STRING)); 1.431 + return cond; 1.432 + } 1.433 + Condition testInt32(Condition cond, const BaseIndex &address) { 1.434 + JS_ASSERT(cond == Equal || cond == NotEqual); 1.435 + cmpl(tagOf(address), ImmTag(JSVAL_TAG_INT32)); 1.436 + return cond; 1.437 + } 1.438 + Condition testObject(Condition cond, const BaseIndex &address) { 1.439 + JS_ASSERT(cond == Equal || cond == NotEqual); 1.440 + cmpl(tagOf(address), ImmTag(JSVAL_TAG_OBJECT)); 1.441 + return cond; 1.442 + } 1.443 + Condition testDouble(Condition cond, const BaseIndex &address) { 1.444 + JS_ASSERT(cond == Equal || cond == NotEqual); 1.445 + Condition actual = (cond == Equal) ? Below : AboveOrEqual; 1.446 + cmpl(tagOf(address), ImmTag(JSVAL_TAG_CLEAR)); 1.447 + return actual; 1.448 + } 1.449 + Condition testMagic(Condition cond, const BaseIndex &address) { 1.450 + JS_ASSERT(cond == Equal || cond == NotEqual); 1.451 + cmpl(tagOf(address), ImmTag(JSVAL_TAG_MAGIC)); 1.452 + return cond; 1.453 + } 1.454 + Condition testGCThing(Condition cond, const BaseIndex &address) { 1.455 + JS_ASSERT(cond == Equal || cond == NotEqual); 1.456 + cmpl(tagOf(address), ImmTag(JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET)); 1.457 + return cond == Equal ? AboveOrEqual : Below; 1.458 + } 1.459 + 1.460 + 1.461 + 1.462 + void branchTestValue(Condition cond, const ValueOperand &value, const Value &v, Label *label); 1.463 + void branchTestValue(Condition cond, const Address &valaddr, const ValueOperand &value, 1.464 + Label *label) 1.465 + { 1.466 + JS_ASSERT(cond == Equal || cond == NotEqual); 1.467 + // Check payload before tag, since payload is more likely to differ. 1.468 + if (cond == NotEqual) { 1.469 + branchPtr(NotEqual, payloadOf(valaddr), value.payloadReg(), label); 1.470 + branchPtr(NotEqual, tagOf(valaddr), value.typeReg(), label); 1.471 + 1.472 + } else { 1.473 + Label fallthrough; 1.474 + branchPtr(NotEqual, payloadOf(valaddr), value.payloadReg(), &fallthrough); 1.475 + branchPtr(Equal, tagOf(valaddr), value.typeReg(), label); 1.476 + bind(&fallthrough); 1.477 + } 1.478 + } 1.479 + 1.480 + void testNullSet(Condition cond, const ValueOperand &value, Register dest) { 1.481 + cond = testNull(cond, value); 1.482 + emitSet(cond, dest); 1.483 + } 1.484 + void testUndefinedSet(Condition cond, const ValueOperand &value, Register dest) { 1.485 + cond = testUndefined(cond, value); 1.486 + emitSet(cond, dest); 1.487 + } 1.488 + 1.489 + void cmpPtr(Register lhs, const ImmWord rhs) { 1.490 + cmpl(lhs, Imm32(rhs.value)); 1.491 + } 1.492 + void cmpPtr(Register lhs, const ImmPtr imm) { 1.493 + cmpPtr(lhs, ImmWord(uintptr_t(imm.value))); 1.494 + } 1.495 + void cmpPtr(Register lhs, const ImmGCPtr rhs) { 1.496 + cmpl(lhs, rhs); 1.497 + } 1.498 + void cmpPtr(Register lhs, const Imm32 rhs) { 1.499 + cmpl(lhs, rhs); 1.500 + } 1.501 + void cmpPtr(const Operand &lhs, const ImmWord rhs) { 1.502 + cmpl(lhs, rhs); 1.503 + } 1.504 + void cmpPtr(const Operand &lhs, const ImmPtr imm) { 1.505 + cmpPtr(lhs, ImmWord(uintptr_t(imm.value))); 1.506 + } 1.507 + void cmpPtr(const Operand &lhs, const ImmGCPtr rhs) { 1.508 + cmpl(lhs, rhs); 1.509 + } 1.510 + void cmpPtr(const Operand &lhs, const Imm32 rhs) { 1.511 + cmpl(lhs, rhs); 1.512 + } 1.513 + void cmpPtr(const Address &lhs, Register rhs) { 1.514 + cmpl(Operand(lhs), rhs); 1.515 + } 1.516 + void cmpPtr(const Address &lhs, const ImmWord rhs) { 1.517 + cmpl(Operand(lhs), rhs); 1.518 + } 1.519 + void cmpPtr(const Address &lhs, const ImmPtr rhs) { 1.520 + cmpPtr(lhs, ImmWord(uintptr_t(rhs.value))); 1.521 + } 1.522 + void cmpPtr(Register lhs, Register rhs) { 1.523 + cmpl(lhs, rhs); 1.524 + } 1.525 + void testPtr(Register lhs, Register rhs) { 1.526 + testl(lhs, rhs); 1.527 + } 1.528 + 1.529 + template <typename T1, typename T2> 1.530 + void cmpPtrSet(Assembler::Condition cond, T1 lhs, T2 rhs, const Register &dest) 1.531 + { 1.532 + cmpPtr(lhs, rhs); 1.533 + emitSet(cond, dest); 1.534 + } 1.535 + 1.536 + ///////////////////////////////////////////////////////////////// 1.537 + // Common interface. 1.538 + ///////////////////////////////////////////////////////////////// 1.539 + void reserveStack(uint32_t amount) { 1.540 + if (amount) 1.541 + subl(Imm32(amount), StackPointer); 1.542 + framePushed_ += amount; 1.543 + } 1.544 + void freeStack(uint32_t amount) { 1.545 + JS_ASSERT(amount <= framePushed_); 1.546 + if (amount) 1.547 + addl(Imm32(amount), StackPointer); 1.548 + framePushed_ -= amount; 1.549 + } 1.550 + void freeStack(Register amount) { 1.551 + addl(amount, StackPointer); 1.552 + } 1.553 + 1.554 + void addPtr(const Register &src, const Register &dest) { 1.555 + addl(src, dest); 1.556 + } 1.557 + void addPtr(Imm32 imm, const Register &dest) { 1.558 + addl(imm, dest); 1.559 + } 1.560 + void addPtr(ImmWord imm, const Register &dest) { 1.561 + addl(Imm32(imm.value), dest); 1.562 + } 1.563 + void addPtr(ImmPtr imm, const Register &dest) { 1.564 + addPtr(ImmWord(uintptr_t(imm.value)), dest); 1.565 + } 1.566 + void addPtr(Imm32 imm, const Address &dest) { 1.567 + addl(imm, Operand(dest)); 1.568 + } 1.569 + void addPtr(Imm32 imm, const Operand &dest) { 1.570 + addl(imm, dest); 1.571 + } 1.572 + void addPtr(const Address &src, const Register &dest) { 1.573 + addl(Operand(src), dest); 1.574 + } 1.575 + void subPtr(Imm32 imm, const Register &dest) { 1.576 + subl(imm, dest); 1.577 + } 1.578 + void subPtr(const Register &src, const Register &dest) { 1.579 + subl(src, dest); 1.580 + } 1.581 + void subPtr(const Address &addr, const Register &dest) { 1.582 + subl(Operand(addr), dest); 1.583 + } 1.584 + void subPtr(const Register &src, const Address &dest) { 1.585 + subl(src, Operand(dest)); 1.586 + } 1.587 + 1.588 + void branch32(Condition cond, const AbsoluteAddress &lhs, Imm32 rhs, Label *label) { 1.589 + cmpl(Operand(lhs), rhs); 1.590 + j(cond, label); 1.591 + } 1.592 + void branch32(Condition cond, const AbsoluteAddress &lhs, Register rhs, Label *label) { 1.593 + cmpl(Operand(lhs), rhs); 1.594 + j(cond, label); 1.595 + } 1.596 + 1.597 + // Specialization for AsmJSAbsoluteAddress. 1.598 + void branchPtr(Condition cond, AsmJSAbsoluteAddress lhs, Register ptr, Label *label) { 1.599 + cmpl(lhs, ptr); 1.600 + j(cond, label); 1.601 + } 1.602 + 1.603 + template <typename T, typename S> 1.604 + void branchPtr(Condition cond, T lhs, S ptr, Label *label) { 1.605 + cmpl(Operand(lhs), ptr); 1.606 + j(cond, label); 1.607 + } 1.608 + 1.609 + void branchPrivatePtr(Condition cond, const Address &lhs, ImmPtr ptr, Label *label) { 1.610 + branchPtr(cond, lhs, ptr, label); 1.611 + } 1.612 + 1.613 + void branchPrivatePtr(Condition cond, const Address &lhs, Register ptr, Label *label) { 1.614 + branchPtr(cond, lhs, ptr, label); 1.615 + } 1.616 + 1.617 + template <typename T, typename S> 1.618 + void branchPtr(Condition cond, T lhs, S ptr, RepatchLabel *label) { 1.619 + cmpl(Operand(lhs), ptr); 1.620 + j(cond, label); 1.621 + } 1.622 + 1.623 + CodeOffsetJump jumpWithPatch(RepatchLabel *label) { 1.624 + jump(label); 1.625 + return CodeOffsetJump(size()); 1.626 + } 1.627 + 1.628 + CodeOffsetJump jumpWithPatch(RepatchLabel *label, Assembler::Condition cond) { 1.629 + j(cond, label); 1.630 + return CodeOffsetJump(size()); 1.631 + } 1.632 + 1.633 + template <typename S, typename T> 1.634 + CodeOffsetJump branchPtrWithPatch(Condition cond, S lhs, T ptr, RepatchLabel *label) { 1.635 + branchPtr(cond, lhs, ptr, label); 1.636 + return CodeOffsetJump(size()); 1.637 + } 1.638 + void branchPtr(Condition cond, Register lhs, Register rhs, RepatchLabel *label) { 1.639 + cmpl(lhs, rhs); 1.640 + j(cond, label); 1.641 + } 1.642 + void branchPtr(Condition cond, Register lhs, Register rhs, Label *label) { 1.643 + cmpl(lhs, rhs); 1.644 + j(cond, label); 1.645 + } 1.646 + void branchTestPtr(Condition cond, Register lhs, Register rhs, Label *label) { 1.647 + testl(lhs, rhs); 1.648 + j(cond, label); 1.649 + } 1.650 + void branchTestPtr(Condition cond, Register lhs, Imm32 imm, Label *label) { 1.651 + testl(lhs, imm); 1.652 + j(cond, label); 1.653 + } 1.654 + void branchTestPtr(Condition cond, const Address &lhs, Imm32 imm, Label *label) { 1.655 + testl(Operand(lhs), imm); 1.656 + j(cond, label); 1.657 + } 1.658 + void decBranchPtr(Condition cond, const Register &lhs, Imm32 imm, Label *label) { 1.659 + subPtr(imm, lhs); 1.660 + j(cond, label); 1.661 + } 1.662 + 1.663 + void movePtr(ImmWord imm, Register dest) { 1.664 + movl(Imm32(imm.value), dest); 1.665 + } 1.666 + void movePtr(ImmPtr imm, Register dest) { 1.667 + movl(imm, dest); 1.668 + } 1.669 + void movePtr(AsmJSImmPtr imm, Register dest) { 1.670 + mov(imm, dest); 1.671 + } 1.672 + void movePtr(ImmGCPtr imm, Register dest) { 1.673 + movl(imm, dest); 1.674 + } 1.675 + void loadPtr(const Address &address, Register dest) { 1.676 + movl(Operand(address), dest); 1.677 + } 1.678 + void loadPtr(const Operand &src, Register dest) { 1.679 + movl(src, dest); 1.680 + } 1.681 + void loadPtr(const BaseIndex &src, Register dest) { 1.682 + movl(Operand(src), dest); 1.683 + } 1.684 + void loadPtr(const AbsoluteAddress &address, Register dest) { 1.685 + movl(Operand(address), dest); 1.686 + } 1.687 + void loadPrivate(const Address &src, Register dest) { 1.688 + movl(payloadOf(src), dest); 1.689 + } 1.690 + void load32(const AbsoluteAddress &address, Register dest) { 1.691 + movl(Operand(address), dest); 1.692 + } 1.693 + void storePtr(ImmWord imm, const Address &address) { 1.694 + movl(Imm32(imm.value), Operand(address)); 1.695 + } 1.696 + void storePtr(ImmPtr imm, const Address &address) { 1.697 + storePtr(ImmWord(uintptr_t(imm.value)), address); 1.698 + } 1.699 + void storePtr(ImmGCPtr imm, const Address &address) { 1.700 + movl(imm, Operand(address)); 1.701 + } 1.702 + void storePtr(Register src, const Address &address) { 1.703 + movl(src, Operand(address)); 1.704 + } 1.705 + void storePtr(Register src, const Operand &dest) { 1.706 + movl(src, dest); 1.707 + } 1.708 + void storePtr(Register src, const AbsoluteAddress &address) { 1.709 + movl(src, Operand(address)); 1.710 + } 1.711 + void store32(Register src, const AbsoluteAddress &address) { 1.712 + movl(src, Operand(address)); 1.713 + } 1.714 + 1.715 + void setStackArg(const Register ®, uint32_t arg) { 1.716 + movl(reg, Operand(esp, arg * sizeof(intptr_t))); 1.717 + } 1.718 + 1.719 + // Type testing instructions can take a tag in a register or a 1.720 + // ValueOperand. 1.721 + template <typename T> 1.722 + void branchTestUndefined(Condition cond, const T &t, Label *label) { 1.723 + cond = testUndefined(cond, t); 1.724 + j(cond, label); 1.725 + } 1.726 + template <typename T> 1.727 + void branchTestInt32(Condition cond, const T &t, Label *label) { 1.728 + cond = testInt32(cond, t); 1.729 + j(cond, label); 1.730 + } 1.731 + template <typename T> 1.732 + void branchTestBoolean(Condition cond, const T &t, Label *label) { 1.733 + cond = testBoolean(cond, t); 1.734 + j(cond, label); 1.735 + } 1.736 + template <typename T> 1.737 + void branchTestDouble(Condition cond, const T &t, Label *label) { 1.738 + cond = testDouble(cond, t); 1.739 + j(cond, label); 1.740 + } 1.741 + template <typename T> 1.742 + void branchTestNull(Condition cond, const T &t, Label *label) { 1.743 + cond = testNull(cond, t); 1.744 + j(cond, label); 1.745 + } 1.746 + template <typename T> 1.747 + void branchTestString(Condition cond, const T &t, Label *label) { 1.748 + cond = testString(cond, t); 1.749 + j(cond, label); 1.750 + } 1.751 + template <typename T> 1.752 + void branchTestObject(Condition cond, const T &t, Label *label) { 1.753 + cond = testObject(cond, t); 1.754 + j(cond, label); 1.755 + } 1.756 + template <typename T> 1.757 + void branchTestNumber(Condition cond, const T &t, Label *label) { 1.758 + cond = testNumber(cond, t); 1.759 + j(cond, label); 1.760 + } 1.761 + template <typename T> 1.762 + void branchTestGCThing(Condition cond, const T &t, Label *label) { 1.763 + cond = testGCThing(cond, t); 1.764 + j(cond, label); 1.765 + } 1.766 + template <typename T> 1.767 + void branchTestPrimitive(Condition cond, const T &t, Label *label) { 1.768 + cond = testPrimitive(cond, t); 1.769 + j(cond, label); 1.770 + } 1.771 + template <typename T> 1.772 + void branchTestMagic(Condition cond, const T &t, Label *label) { 1.773 + cond = testMagic(cond, t); 1.774 + j(cond, label); 1.775 + } 1.776 + void branchTestMagicValue(Condition cond, const ValueOperand &val, JSWhyMagic why, 1.777 + Label *label) 1.778 + { 1.779 + JS_ASSERT(cond == Equal || cond == NotEqual); 1.780 + if (cond == Equal) { 1.781 + // Test for magic 1.782 + Label notmagic; 1.783 + Condition testCond = testMagic(Equal, val); 1.784 + j(InvertCondition(testCond), ¬magic); 1.785 + // Test magic value 1.786 + branch32(Equal, val.payloadReg(), Imm32(static_cast<int32_t>(why)), label); 1.787 + bind(¬magic); 1.788 + } else { 1.789 + Condition testCond = testMagic(NotEqual, val); 1.790 + j(testCond, label); 1.791 + branch32(NotEqual, val.payloadReg(), Imm32(static_cast<int32_t>(why)), label); 1.792 + } 1.793 + } 1.794 + 1.795 + // Note: this function clobbers the source register. 1.796 + void boxDouble(const FloatRegister &src, const ValueOperand &dest) { 1.797 + movd(src, dest.payloadReg()); 1.798 + psrldq(Imm32(4), src); 1.799 + movd(src, dest.typeReg()); 1.800 + } 1.801 + void boxNonDouble(JSValueType type, const Register &src, const ValueOperand &dest) { 1.802 + if (src != dest.payloadReg()) 1.803 + movl(src, dest.payloadReg()); 1.804 + movl(ImmType(type), dest.typeReg()); 1.805 + } 1.806 + void unboxInt32(const ValueOperand &src, const Register &dest) { 1.807 + movl(src.payloadReg(), dest); 1.808 + } 1.809 + void unboxInt32(const Address &src, const Register &dest) { 1.810 + movl(payloadOf(src), dest); 1.811 + } 1.812 + void unboxDouble(const Address &src, const FloatRegister &dest) { 1.813 + loadDouble(Operand(src), dest); 1.814 + } 1.815 + void unboxBoolean(const ValueOperand &src, const Register &dest) { 1.816 + movl(src.payloadReg(), dest); 1.817 + } 1.818 + void unboxBoolean(const Address &src, const Register &dest) { 1.819 + movl(payloadOf(src), dest); 1.820 + } 1.821 + void unboxObject(const ValueOperand &src, const Register &dest) { 1.822 + if (src.payloadReg() != dest) 1.823 + movl(src.payloadReg(), dest); 1.824 + } 1.825 + void unboxDouble(const ValueOperand &src, const FloatRegister &dest) { 1.826 + JS_ASSERT(dest != ScratchFloatReg); 1.827 + if (Assembler::HasSSE41()) { 1.828 + movd(src.payloadReg(), dest); 1.829 + pinsrd(src.typeReg(), dest); 1.830 + } else { 1.831 + movd(src.payloadReg(), dest); 1.832 + movd(src.typeReg(), ScratchFloatReg); 1.833 + unpcklps(ScratchFloatReg, dest); 1.834 + } 1.835 + } 1.836 + void unboxDouble(const Operand &payload, const Operand &type, 1.837 + const Register &scratch, const FloatRegister &dest) { 1.838 + JS_ASSERT(dest != ScratchFloatReg); 1.839 + if (Assembler::HasSSE41()) { 1.840 + movl(payload, scratch); 1.841 + movd(scratch, dest); 1.842 + movl(type, scratch); 1.843 + pinsrd(scratch, dest); 1.844 + } else { 1.845 + movl(payload, scratch); 1.846 + movd(scratch, dest); 1.847 + movl(type, scratch); 1.848 + movd(scratch, ScratchFloatReg); 1.849 + unpcklps(ScratchFloatReg, dest); 1.850 + } 1.851 + } 1.852 + void unboxString(const ValueOperand &src, const Register &dest) { 1.853 + movl(src.payloadReg(), dest); 1.854 + } 1.855 + void unboxString(const Address &src, const Register &dest) { 1.856 + movl(payloadOf(src), dest); 1.857 + } 1.858 + void unboxValue(const ValueOperand &src, AnyRegister dest) { 1.859 + if (dest.isFloat()) { 1.860 + Label notInt32, end; 1.861 + branchTestInt32(Assembler::NotEqual, src, ¬Int32); 1.862 + convertInt32ToDouble(src.payloadReg(), dest.fpu()); 1.863 + jump(&end); 1.864 + bind(¬Int32); 1.865 + unboxDouble(src, dest.fpu()); 1.866 + bind(&end); 1.867 + } else { 1.868 + if (src.payloadReg() != dest.gpr()) 1.869 + movl(src.payloadReg(), dest.gpr()); 1.870 + } 1.871 + } 1.872 + void unboxPrivate(const ValueOperand &src, Register dest) { 1.873 + if (src.payloadReg() != dest) 1.874 + movl(src.payloadReg(), dest); 1.875 + } 1.876 + 1.877 + void notBoolean(const ValueOperand &val) { 1.878 + xorl(Imm32(1), val.payloadReg()); 1.879 + } 1.880 + 1.881 + // Extended unboxing API. If the payload is already in a register, returns 1.882 + // that register. Otherwise, provides a move to the given scratch register, 1.883 + // and returns that. 1.884 + Register extractObject(const Address &address, Register scratch) { 1.885 + movl(payloadOf(address), scratch); 1.886 + return scratch; 1.887 + } 1.888 + Register extractObject(const ValueOperand &value, Register scratch) { 1.889 + return value.payloadReg(); 1.890 + } 1.891 + Register extractInt32(const ValueOperand &value, Register scratch) { 1.892 + return value.payloadReg(); 1.893 + } 1.894 + Register extractBoolean(const ValueOperand &value, Register scratch) { 1.895 + return value.payloadReg(); 1.896 + } 1.897 + Register extractTag(const Address &address, Register scratch) { 1.898 + movl(tagOf(address), scratch); 1.899 + return scratch; 1.900 + } 1.901 + Register extractTag(const ValueOperand &value, Register scratch) { 1.902 + return value.typeReg(); 1.903 + } 1.904 + 1.905 + void boolValueToDouble(const ValueOperand &operand, const FloatRegister &dest) { 1.906 + convertInt32ToDouble(operand.payloadReg(), dest); 1.907 + } 1.908 + void boolValueToFloat32(const ValueOperand &operand, const FloatRegister &dest) { 1.909 + convertInt32ToFloat32(operand.payloadReg(), dest); 1.910 + } 1.911 + void int32ValueToDouble(const ValueOperand &operand, const FloatRegister &dest) { 1.912 + convertInt32ToDouble(operand.payloadReg(), dest); 1.913 + } 1.914 + void int32ValueToFloat32(const ValueOperand &operand, const FloatRegister &dest) { 1.915 + convertInt32ToFloat32(operand.payloadReg(), dest); 1.916 + } 1.917 + 1.918 + void loadConstantDouble(double d, const FloatRegister &dest); 1.919 + void addConstantDouble(double d, const FloatRegister &dest); 1.920 + void loadConstantFloat32(float f, const FloatRegister &dest); 1.921 + void addConstantFloat32(float f, const FloatRegister &dest); 1.922 + 1.923 + void branchTruncateDouble(const FloatRegister &src, const Register &dest, Label *fail) { 1.924 + cvttsd2si(src, dest); 1.925 + 1.926 + // cvttsd2si returns 0x80000000 on failure. Test for it by 1.927 + // subtracting 1 and testing overflow (this permits the use of a 1.928 + // smaller immediate field). 1.929 + cmpl(dest, Imm32(1)); 1.930 + j(Assembler::Overflow, fail); 1.931 + } 1.932 + void branchTruncateFloat32(const FloatRegister &src, const Register &dest, Label *fail) { 1.933 + cvttss2si(src, dest); 1.934 + 1.935 + // cvttss2si returns 0x80000000 on failure. Test for it by 1.936 + // subtracting 1 and testing overflow (this permits the use of a 1.937 + // smaller immediate field). 1.938 + cmpl(dest, Imm32(1)); 1.939 + j(Assembler::Overflow, fail); 1.940 + } 1.941 + 1.942 + Condition testInt32Truthy(bool truthy, const ValueOperand &operand) { 1.943 + testl(operand.payloadReg(), operand.payloadReg()); 1.944 + return truthy ? NonZero : Zero; 1.945 + } 1.946 + void branchTestInt32Truthy(bool truthy, const ValueOperand &operand, Label *label) { 1.947 + Condition cond = testInt32Truthy(truthy, operand); 1.948 + j(cond, label); 1.949 + } 1.950 + void branchTestBooleanTruthy(bool truthy, const ValueOperand &operand, Label *label) { 1.951 + testl(operand.payloadReg(), operand.payloadReg()); 1.952 + j(truthy ? NonZero : Zero, label); 1.953 + } 1.954 + Condition testStringTruthy(bool truthy, const ValueOperand &value) { 1.955 + Register string = value.payloadReg(); 1.956 + Operand lengthAndFlags(string, JSString::offsetOfLengthAndFlags()); 1.957 + 1.958 + size_t mask = (0xFFFFFFFF << JSString::LENGTH_SHIFT); 1.959 + testl(lengthAndFlags, Imm32(mask)); 1.960 + return truthy ? Assembler::NonZero : Assembler::Zero; 1.961 + } 1.962 + void branchTestStringTruthy(bool truthy, const ValueOperand &value, Label *label) { 1.963 + Condition cond = testStringTruthy(truthy, value); 1.964 + j(cond, label); 1.965 + } 1.966 + 1.967 + void loadInt32OrDouble(const Operand &operand, const FloatRegister &dest) { 1.968 + Label notInt32, end; 1.969 + branchTestInt32(Assembler::NotEqual, operand, ¬Int32); 1.970 + convertInt32ToDouble(ToPayload(operand), dest); 1.971 + jump(&end); 1.972 + bind(¬Int32); 1.973 + loadDouble(operand, dest); 1.974 + bind(&end); 1.975 + } 1.976 + 1.977 + template <typename T> 1.978 + void loadUnboxedValue(const T &src, MIRType type, AnyRegister dest) { 1.979 + if (dest.isFloat()) 1.980 + loadInt32OrDouble(Operand(src), dest.fpu()); 1.981 + else 1.982 + movl(Operand(src), dest.gpr()); 1.983 + } 1.984 + 1.985 + void rshiftPtr(Imm32 imm, Register dest) { 1.986 + shrl(imm, dest); 1.987 + } 1.988 + void lshiftPtr(Imm32 imm, Register dest) { 1.989 + shll(imm, dest); 1.990 + } 1.991 + void xorPtr(Imm32 imm, Register dest) { 1.992 + xorl(imm, dest); 1.993 + } 1.994 + void xorPtr(Register src, Register dest) { 1.995 + xorl(src, dest); 1.996 + } 1.997 + void orPtr(Imm32 imm, Register dest) { 1.998 + orl(imm, dest); 1.999 + } 1.1000 + void orPtr(Register src, Register dest) { 1.1001 + orl(src, dest); 1.1002 + } 1.1003 + void andPtr(Imm32 imm, Register dest) { 1.1004 + andl(imm, dest); 1.1005 + } 1.1006 + void andPtr(Register src, Register dest) { 1.1007 + andl(src, dest); 1.1008 + } 1.1009 + 1.1010 + void loadInstructionPointerAfterCall(const Register &dest) { 1.1011 + movl(Operand(StackPointer, 0x0), dest); 1.1012 + } 1.1013 + 1.1014 + // Note: this function clobbers the source register. 1.1015 + void convertUInt32ToDouble(const Register &src, const FloatRegister &dest) { 1.1016 + // src is [0, 2^32-1] 1.1017 + subl(Imm32(0x80000000), src); 1.1018 + 1.1019 + // Now src is [-2^31, 2^31-1] - int range, but not the same value. 1.1020 + convertInt32ToDouble(src, dest); 1.1021 + 1.1022 + // dest is now a double with the int range. 1.1023 + // correct the double value by adding 0x80000000. 1.1024 + addConstantDouble(2147483648.0, dest); 1.1025 + } 1.1026 + 1.1027 + // Note: this function clobbers the source register. 1.1028 + void convertUInt32ToFloat32(const Register &src, const FloatRegister &dest) { 1.1029 + convertUInt32ToDouble(src, dest); 1.1030 + convertDoubleToFloat32(dest, dest); 1.1031 + } 1.1032 + 1.1033 + void inc64(AbsoluteAddress dest) { 1.1034 + addl(Imm32(1), Operand(dest)); 1.1035 + Label noOverflow; 1.1036 + j(NonZero, &noOverflow); 1.1037 + addl(Imm32(1), Operand(dest.offset(4))); 1.1038 + bind(&noOverflow); 1.1039 + } 1.1040 + 1.1041 + 1.1042 + // If source is a double, load it into dest. If source is int32, 1.1043 + // convert it to double. Else, branch to failure. 1.1044 + void ensureDouble(const ValueOperand &source, FloatRegister dest, Label *failure) { 1.1045 + Label isDouble, done; 1.1046 + branchTestDouble(Assembler::Equal, source.typeReg(), &isDouble); 1.1047 + branchTestInt32(Assembler::NotEqual, source.typeReg(), failure); 1.1048 + 1.1049 + convertInt32ToDouble(source.payloadReg(), dest); 1.1050 + jump(&done); 1.1051 + 1.1052 + bind(&isDouble); 1.1053 + unboxDouble(source, dest); 1.1054 + 1.1055 + bind(&done); 1.1056 + } 1.1057 + 1.1058 + // Setup a call to C/C++ code, given the number of general arguments it 1.1059 + // takes. Note that this only supports cdecl. 1.1060 + // 1.1061 + // In order for alignment to work correctly, the MacroAssembler must have a 1.1062 + // consistent view of the stack displacement. It is okay to call "push" 1.1063 + // manually, however, if the stack alignment were to change, the macro 1.1064 + // assembler should be notified before starting a call. 1.1065 + void setupAlignedABICall(uint32_t args); 1.1066 + 1.1067 + // Sets up an ABI call for when the alignment is not known. This may need a 1.1068 + // scratch register. 1.1069 + void setupUnalignedABICall(uint32_t args, const Register &scratch); 1.1070 + 1.1071 + // Arguments must be assigned to a C/C++ call in order. They are moved 1.1072 + // in parallel immediately before performing the call. This process may 1.1073 + // temporarily use more stack, in which case esp-relative addresses will be 1.1074 + // automatically adjusted. It is extremely important that esp-relative 1.1075 + // addresses are computed *after* setupABICall(). Furthermore, no 1.1076 + // operations should be emitted while setting arguments. 1.1077 + void passABIArg(const MoveOperand &from, MoveOp::Type type); 1.1078 + void passABIArg(const Register ®); 1.1079 + void passABIArg(const FloatRegister ®, MoveOp::Type type); 1.1080 + 1.1081 + private: 1.1082 + void callWithABIPre(uint32_t *stackAdjust); 1.1083 + void callWithABIPost(uint32_t stackAdjust, MoveOp::Type result); 1.1084 + 1.1085 + public: 1.1086 + // Emits a call to a C/C++ function, resolving all argument moves. 1.1087 + void callWithABI(void *fun, MoveOp::Type result = MoveOp::GENERAL); 1.1088 + void callWithABI(AsmJSImmPtr fun, MoveOp::Type result = MoveOp::GENERAL); 1.1089 + void callWithABI(const Address &fun, MoveOp::Type result = MoveOp::GENERAL); 1.1090 + 1.1091 + // Used from within an Exit frame to handle a pending exception. 1.1092 + void handleFailureWithHandler(void *handler); 1.1093 + void handleFailureWithHandlerTail(); 1.1094 + 1.1095 + void makeFrameDescriptor(Register frameSizeReg, FrameType type) { 1.1096 + shll(Imm32(FRAMESIZE_SHIFT), frameSizeReg); 1.1097 + orl(Imm32(type), frameSizeReg); 1.1098 + } 1.1099 + 1.1100 + // Save an exit frame (which must be aligned to the stack pointer) to 1.1101 + // ThreadData::ionTop of the main thread. 1.1102 + void linkExitFrame() { 1.1103 + movl(StackPointer, Operand(AbsoluteAddress(GetIonContext()->runtime->addressOfIonTop()))); 1.1104 + } 1.1105 + 1.1106 + void callWithExitFrame(JitCode *target, Register dynStack) { 1.1107 + addPtr(Imm32(framePushed()), dynStack); 1.1108 + makeFrameDescriptor(dynStack, JitFrame_IonJS); 1.1109 + Push(dynStack); 1.1110 + call(target); 1.1111 + } 1.1112 + void call(const CallSiteDesc &desc, AsmJSImmPtr target) { 1.1113 + call(target); 1.1114 + appendCallSite(desc); 1.1115 + } 1.1116 + void callExit(AsmJSImmPtr target, uint32_t stackArgBytes) { 1.1117 + call(CallSiteDesc::Exit(), target); 1.1118 + } 1.1119 + 1.1120 + // Save an exit frame to the thread data of the current thread, given a 1.1121 + // register that holds a PerThreadData *. 1.1122 + void linkParallelExitFrame(const Register &pt) { 1.1123 + movl(StackPointer, Operand(pt, offsetof(PerThreadData, ionTop))); 1.1124 + } 1.1125 + 1.1126 +#ifdef JSGC_GENERATIONAL 1.1127 + void branchPtrInNurseryRange(Register ptr, Register temp, Label *label); 1.1128 + void branchValueIsNurseryObject(ValueOperand value, Register temp, Label *label); 1.1129 +#endif 1.1130 +}; 1.1131 + 1.1132 +typedef MacroAssemblerX86 MacroAssemblerSpecific; 1.1133 + 1.1134 +} // namespace jit 1.1135 +} // namespace js 1.1136 + 1.1137 +#endif /* jit_x86_MacroAssembler_x86_h */