Optimize FrameState for large linear scripts (bug 591836, r=dmandelin).
[mozilla-central.git] / js / src / methodjit / FrameState-inl.h
blob234463399161c6558236671910e81013642a7492
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=4 sw=4 et tw=99:
4 * ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
15 * License.
17 * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
18 * May 28, 2008.
20 * The Initial Developer of the Original Code is
21 * Brendan Eich <brendan@mozilla.org>
23 * Contributor(s):
24 * David Anderson <danderson@mozilla.com>
26 * Alternatively, the contents of this file may be used under the terms of
27 * either of the GNU General Public License Version 2 or later (the "GPL"),
28 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 #if !defined jsjaeger_framestate_inl_h__ && defined JS_METHODJIT
41 #define jsjaeger_framestate_inl_h__
43 namespace js {
44 namespace mjit {
46 inline void
47 FrameState::addToTracker(FrameEntry *fe)
49 JS_ASSERT(!fe->isTracked());
50 fe->track(tracker.nentries);
51 tracker.add(fe);
52 JS_ASSERT(tracker.nentries <= script->nslots);
55 inline FrameEntry *
56 FrameState::peek(int32 depth)
58 JS_ASSERT(depth < 0);
59 JS_ASSERT(sp + depth >= spBase);
60 FrameEntry *fe = &sp[depth];
61 if (!fe->isTracked()) {
62 addToTracker(fe);
63 fe->resetSynced();
65 return fe;
68 inline void
69 FrameState::popn(uint32 n)
71 for (uint32 i = 0; i < n; i++)
72 pop();
75 inline bool
76 FrameState::haveSameBacking(FrameEntry *lhs, FrameEntry *rhs)
78 if (lhs->isCopy())
79 lhs = lhs->copyOf();
80 if (rhs->isCopy())
81 rhs = rhs->copyOf();
82 return lhs == rhs;
85 inline JSC::MacroAssembler::RegisterID
86 FrameState::allocReg()
88 RegisterID reg;
89 if (!freeRegs.empty()) {
90 reg = freeRegs.takeAnyReg();
91 } else {
92 reg = evictSomeReg();
93 regstate[reg].forget();
96 return reg;
99 inline JSC::MacroAssembler::RegisterID
100 FrameState::allocReg(uint32 mask)
102 RegisterID reg;
103 if (freeRegs.hasRegInMask(mask)) {
104 reg = freeRegs.takeRegInMask(mask);
105 } else {
106 reg = evictSomeReg(mask);
107 regstate[reg].forget();
110 return reg;
113 inline JSC::MacroAssembler::RegisterID
114 FrameState::allocReg(FrameEntry *fe, RematInfo::RematType type)
116 RegisterID reg;
117 if (!freeRegs.empty()) {
118 reg = freeRegs.takeAnyReg();
119 } else {
120 reg = evictSomeReg();
121 regstate[reg].forget();
124 regstate[reg].associate(fe, type);
126 return reg;
129 inline void
130 FrameState::emitLoadTypeTag(FrameEntry *fe, RegisterID reg) const
132 emitLoadTypeTag(this->masm, fe, reg);
135 inline void
136 FrameState::emitLoadTypeTag(Assembler &masm, FrameEntry *fe, RegisterID reg) const
138 if (fe->isCopy())
139 fe = fe->copyOf();
140 masm.loadTypeTag(addressOf(fe), reg);
143 inline void
144 FrameState::convertInt32ToDouble(Assembler &masm, FrameEntry *fe, FPRegisterID fpreg) const
146 JS_ASSERT(!fe->isConstant());
148 if (fe->isCopy())
149 fe = fe->copyOf();
151 if (fe->data.inRegister())
152 masm.convertInt32ToDouble(fe->data.reg(), fpreg);
153 else
154 masm.convertInt32ToDouble(addressOf(fe), fpreg);
157 inline bool
158 FrameState::peekTypeInRegister(FrameEntry *fe) const
160 if (fe->isCopy())
161 fe = fe->copyOf();
162 return fe->type.inRegister();
165 inline void
166 FrameState::pop()
168 JS_ASSERT(sp > spBase);
170 FrameEntry *fe = --sp;
171 if (!fe->isTracked())
172 return;
174 forgetAllRegs(fe);
177 inline void
178 FrameState::freeReg(RegisterID reg)
180 JS_ASSERT(!regstate[reg].usedBy());
182 freeRegs.putReg(reg);
185 inline void
186 FrameState::forgetReg(RegisterID reg)
189 * Important: Do not touch the fe here. We can peephole optimize away
190 * loads and stores by re-using the contents of old FEs.
192 JS_ASSERT_IF(regstate[reg].fe(), !regstate[reg].fe()->isCopy());
194 if (!regstate[reg].isPinned()) {
195 regstate[reg].forget();
196 freeRegs.putReg(reg);
200 inline void
201 FrameState::syncAndForgetEverything(uint32 newStackDepth)
203 syncAndForgetEverything();
204 sp = spBase + newStackDepth;
207 inline FrameEntry *
208 FrameState::rawPush()
210 JS_ASSERT(unsigned(sp - entries) < nargs + script->nslots);
212 if (!sp->isTracked())
213 addToTracker(sp);
215 return sp++;
218 inline void
219 FrameState::push(const Value &v)
221 FrameEntry *fe = rawPush();
222 fe->setConstant(Jsvalify(v));
225 inline void
226 FrameState::pushSynced()
228 if (sp->isTracked())
229 sp->resetSynced();
230 sp++;
233 inline void
234 FrameState::pushSyncedType(JSValueType type)
236 FrameEntry *fe = rawPush();
238 fe->resetSynced();
239 fe->setType(type);
242 inline void
243 FrameState::pushSynced(JSValueType type, RegisterID reg)
245 FrameEntry *fe = rawPush();
247 fe->resetUnsynced();
248 fe->type.sync();
249 fe->data.sync();
250 fe->setType(type);
251 fe->data.setRegister(reg);
252 regstate[reg].associate(fe, RematInfo::DATA);
255 inline void
256 FrameState::push(Address address)
258 FrameEntry *fe = rawPush();
260 /* :XXX: X64 */
261 fe->resetUnsynced();
263 /* Prevent us from clobbering this reg. */
264 bool free = freeRegs.hasReg(address.base);
265 if (free)
266 freeRegs.takeReg(address.base);
268 RegisterID dreg = allocReg(fe, RematInfo::DATA);
269 masm.loadPayload(address, dreg);
270 fe->data.setRegister(dreg);
272 /* Now it's safe to grab this register again. */
273 if (free)
274 freeRegs.putReg(address.base);
276 RegisterID treg = allocReg(fe, RematInfo::TYPE);
277 masm.loadTypeTag(address, treg);
278 fe->type.setRegister(treg);
281 inline void
282 FrameState::pushRegs(RegisterID type, RegisterID data)
284 JS_ASSERT(!freeRegs.hasReg(type) && !freeRegs.hasReg(data));
286 FrameEntry *fe = rawPush();
288 fe->resetUnsynced();
289 fe->type.setRegister(type);
290 fe->data.setRegister(data);
291 regstate[type].associate(fe, RematInfo::TYPE);
292 regstate[data].associate(fe, RematInfo::DATA);
295 inline void
296 FrameState::pushTypedPayload(JSValueType type, RegisterID payload)
298 JS_ASSERT(!freeRegs.hasReg(payload));
300 FrameEntry *fe = rawPush();
302 fe->resetUnsynced();
303 fe->setType(type);
304 fe->data.setRegister(payload);
305 regstate[payload].associate(fe, RematInfo::DATA);
308 inline void
309 FrameState::pushNumber(MaybeRegisterID payload, bool asInt32)
311 JS_ASSERT_IF(payload.isSet(), !freeRegs.hasReg(payload.reg()));
313 FrameEntry *fe = rawPush();
314 fe->clear();
316 JS_ASSERT(!fe->isNumber);
318 if (asInt32) {
319 if (!fe->type.synced())
320 masm.storeTypeTag(ImmType(JSVAL_TYPE_INT32), addressOf(fe));
321 fe->type.setMemory();
322 } else {
323 fe->type.setMemory();
326 fe->isNumber = true;
327 if (payload.isSet()) {
328 fe->data.unsync();
329 fe->data.setRegister(payload.reg());
330 regstate[payload.reg()].associate(fe, RematInfo::DATA);
331 } else {
332 fe->data.setMemory();
336 inline void
337 FrameState::pushInt32(RegisterID payload)
339 FrameEntry *fe = rawPush();
340 fe->clear();
341 JS_ASSERT(!fe->isNumber);
343 masm.storeTypeTag(ImmType(JSVAL_TYPE_INT32), addressOf(fe));
344 fe->type.setMemory();
346 fe->isNumber = true;
347 fe->data.unsync();
348 fe->data.setRegister(payload);
349 regstate[payload].associate(fe, RematInfo::DATA);
352 inline void
353 FrameState::pushUntypedPayload(JSValueType type, RegisterID payload)
355 JS_ASSERT(!freeRegs.hasReg(payload));
357 FrameEntry *fe = rawPush();
359 fe->clear();
361 masm.storeTypeTag(ImmType(type), addressOf(fe));
363 /* The forceful type sync will assert otherwise. */
364 #ifdef DEBUG
365 fe->type.unsync();
366 #endif
367 fe->type.setMemory();
368 fe->data.unsync();
369 fe->setNotCopied();
370 fe->setCopyOf(NULL);
371 fe->data.setRegister(payload);
372 regstate[payload].associate(fe, RematInfo::DATA);
375 inline JSC::MacroAssembler::RegisterID
376 FrameState::tempRegForType(FrameEntry *fe, RegisterID fallback)
378 JS_ASSERT(!regstate[fallback].fe());
379 if (fe->isCopy())
380 fe = fe->copyOf();
382 JS_ASSERT(!fe->type.isConstant());
384 if (fe->type.inRegister())
385 return fe->type.reg();
387 /* :XXX: X86 */
389 masm.loadTypeTag(addressOf(fe), fallback);
390 return fallback;
394 inline JSC::MacroAssembler::RegisterID
395 FrameState::tempRegForType(FrameEntry *fe)
397 if (fe->isCopy())
398 fe = fe->copyOf();
400 JS_ASSERT(!fe->type.isConstant());
402 if (fe->type.inRegister())
403 return fe->type.reg();
405 /* :XXX: X86 */
407 RegisterID reg = allocReg(fe, RematInfo::TYPE);
408 masm.loadTypeTag(addressOf(fe), reg);
409 fe->type.setRegister(reg);
410 return reg;
413 inline JSC::MacroAssembler::RegisterID
414 FrameState::tempRegForData(FrameEntry *fe)
416 JS_ASSERT(!fe->data.isConstant());
418 if (fe->isCopy())
419 fe = fe->copyOf();
421 if (fe->data.inRegister())
422 return fe->data.reg();
424 RegisterID reg = allocReg(fe, RematInfo::DATA);
425 masm.loadPayload(addressOf(fe), reg);
426 fe->data.setRegister(reg);
427 return reg;
430 inline JSC::MacroAssembler::RegisterID
431 FrameState::tempRegInMaskForData(FrameEntry *fe, uint32 mask)
433 JS_ASSERT(!fe->data.isConstant());
435 if (fe->isCopy())
436 fe = fe->copyOf();
438 RegisterID reg;
439 if (fe->data.inRegister()) {
440 RegisterID old = fe->data.reg();
441 if (Registers::maskReg(old) & mask)
442 return old;
444 /* Keep the old register pinned. */
445 regstate[old].forget();
446 reg = allocReg(mask);
447 masm.move(old, reg);
448 freeReg(old);
449 } else {
450 reg = allocReg(mask);
451 masm.loadPayload(addressOf(fe), reg);
453 regstate[reg].associate(fe, RematInfo::DATA);
454 fe->data.setRegister(reg);
455 return reg;
458 inline JSC::MacroAssembler::RegisterID
459 FrameState::tempRegForData(FrameEntry *fe, RegisterID reg, Assembler &masm) const
461 JS_ASSERT(!fe->data.isConstant());
463 if (fe->isCopy())
464 fe = fe->copyOf();
466 if (fe->data.inRegister()) {
467 JS_ASSERT(fe->data.reg() != reg);
468 return fe->data.reg();
469 } else {
470 masm.loadPayload(addressOf(fe), reg);
471 return reg;
475 inline bool
476 FrameState::shouldAvoidTypeRemat(FrameEntry *fe)
478 return fe->type.inMemory();
481 inline bool
482 FrameState::shouldAvoidDataRemat(FrameEntry *fe)
484 return fe->data.inMemory();
487 inline void
488 FrameState::syncType(const FrameEntry *fe, Address to, Assembler &masm) const
490 JS_ASSERT_IF(fe->type.synced(),
491 fe->isCopied() && addressOf(fe).offset != to.offset);
492 JS_ASSERT(fe->type.inRegister() || fe->type.isConstant());
494 if (fe->type.isConstant()) {
495 JS_ASSERT(fe->isTypeKnown());
496 masm.storeTypeTag(ImmType(fe->getKnownType()), to);
497 } else {
498 masm.storeTypeTag(fe->type.reg(), to);
502 inline void
503 FrameState::syncData(const FrameEntry *fe, Address to, Assembler &masm) const
505 JS_ASSERT_IF(addressOf(fe).base == to.base &&
506 addressOf(fe).offset == to.offset,
507 !fe->data.synced());
508 JS_ASSERT(fe->data.inRegister() || fe->data.isConstant());
510 if (fe->data.isConstant()) {
511 if (!fe->type.synced())
512 masm.storeValue(fe->getValue(), to);
513 else
514 #if defined JS_NUNBOX32
515 masm.storePayload(Imm32(fe->getPayload32()), to);
516 #elif defined JS_PUNBOX64
517 masm.storePayload(Imm64(fe->getPayload64()), to);
518 #endif
519 } else {
520 masm.storePayload(fe->data.reg(), to);
524 inline void
525 FrameState::forgetType(FrameEntry *fe)
527 JS_ASSERT(fe->isTypeKnown() && !fe->type.synced());
528 syncType(fe, addressOf(fe), masm);
529 fe->type.setMemory();
532 inline void
533 FrameState::learnType(FrameEntry *fe, JSValueType type)
535 if (fe->type.inRegister())
536 forgetReg(fe->type.reg());
537 #ifdef DEBUG
538 fe->isNumber = false;
539 #endif
540 fe->setType(type);
543 inline JSC::MacroAssembler::Address
544 FrameState::addressOf(const FrameEntry *fe) const
546 uint32 index = (fe - entries);
547 JS_ASSERT(index >= nargs);
548 index -= nargs;
549 return Address(JSFrameReg, sizeof(JSStackFrame) + sizeof(Value) * index);
552 inline JSC::MacroAssembler::Address
553 FrameState::addressForDataRemat(const FrameEntry *fe) const
555 if (fe->isCopy() && !fe->data.synced())
556 fe = fe->copyOf();
557 JS_ASSERT(fe->data.synced());
558 return addressOf(fe);
561 inline JSC::MacroAssembler::Jump
562 FrameState::testNull(Assembler::Condition cond, FrameEntry *fe)
564 JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
565 if (shouldAvoidTypeRemat(fe))
566 return masm.testNull(cond, addressOf(fe));
567 return masm.testNull(cond, tempRegForType(fe));
570 inline JSC::MacroAssembler::Jump
571 FrameState::testInt32(Assembler::Condition cond, FrameEntry *fe)
573 JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
574 if (shouldAvoidTypeRemat(fe))
575 return masm.testInt32(cond, addressOf(fe));
576 return masm.testInt32(cond, tempRegForType(fe));
579 inline JSC::MacroAssembler::Jump
580 FrameState::testPrimitive(Assembler::Condition cond, FrameEntry *fe)
582 JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
583 if (shouldAvoidTypeRemat(fe))
584 return masm.testPrimitive(cond, addressOf(fe));
585 return masm.testPrimitive(cond, tempRegForType(fe));
588 inline JSC::MacroAssembler::Jump
589 FrameState::testObject(Assembler::Condition cond, FrameEntry *fe)
591 JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
592 if (shouldAvoidTypeRemat(fe))
593 return masm.testObject(cond, addressOf(fe));
594 return masm.testObject(cond, tempRegForType(fe));
597 inline JSC::MacroAssembler::Jump
598 FrameState::testDouble(Assembler::Condition cond, FrameEntry *fe)
600 JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
601 if (shouldAvoidTypeRemat(fe))
602 return masm.testDouble(cond, addressOf(fe));
603 return masm.testDouble(cond, tempRegForType(fe));
606 inline JSC::MacroAssembler::Jump
607 FrameState::testBoolean(Assembler::Condition cond, FrameEntry *fe)
609 JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
610 if (shouldAvoidTypeRemat(fe))
611 return masm.testBoolean(cond, addressOf(fe));
612 return masm.testBoolean(cond, tempRegForType(fe));
615 inline JSC::MacroAssembler::Jump
616 FrameState::testString(Assembler::Condition cond, FrameEntry *fe)
618 JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
619 if (shouldAvoidTypeRemat(fe))
620 return masm.testString(cond, addressOf(fe));
621 return masm.testString(cond, tempRegForType(fe));
624 inline FrameEntry *
625 FrameState::getLocal(uint32 slot)
627 uint32 index = nargs + slot;
628 FrameEntry *fe = &entries[index];
629 if (!fe->isTracked()) {
630 addToTracker(fe);
631 fe->resetSynced();
633 return fe;
636 inline void
637 FrameState::pinReg(RegisterID reg)
639 regstate[reg].pin();
642 inline void
643 FrameState::unpinReg(RegisterID reg)
645 regstate[reg].unpin();
648 inline void
649 FrameState::unpinKilledReg(RegisterID reg)
651 regstate[reg].unpinUnsafe();
652 freeRegs.putReg(reg);
655 inline void
656 FrameState::forgetAllRegs(FrameEntry *fe)
658 if (fe->type.inRegister())
659 forgetReg(fe->type.reg());
660 if (fe->data.inRegister())
661 forgetReg(fe->data.reg());
664 inline void
665 FrameState::swapInTracker(FrameEntry *lhs, FrameEntry *rhs)
667 uint32 li = lhs->trackerIndex();
668 uint32 ri = rhs->trackerIndex();
669 JS_ASSERT(tracker[li] == lhs);
670 JS_ASSERT(tracker[ri] == rhs);
671 tracker.entries[ri] = lhs;
672 tracker.entries[li] = rhs;
673 lhs->index_ = ri;
674 rhs->index_ = li;
677 inline uint32
678 FrameState::localIndex(uint32 n)
680 return nargs + n;
683 inline void
684 FrameState::dup()
686 dupAt(-1);
689 inline void
690 FrameState::dup2()
692 FrameEntry *lhs = peek(-2);
693 FrameEntry *rhs = peek(-1);
694 pushCopyOf(indexOfFe(lhs));
695 pushCopyOf(indexOfFe(rhs));
698 inline void
699 FrameState::dupAt(int32 n)
701 JS_ASSERT(n < 0);
702 FrameEntry *fe = peek(n);
703 pushCopyOf(indexOfFe(fe));
706 inline void
707 FrameState::pushLocal(uint32 n)
709 if (!eval && !escaping[n]) {
710 pushCopyOf(indexOfFe(getLocal(n)));
711 } else {
712 #ifdef DEBUG
714 * We really want to assert on local variables, but in the presence of
715 * SETLOCAL equivocation of stack slots, and let expressions, just
716 * weakly assert on the fixed local vars.
718 FrameEntry *fe = &locals[n];
719 if (fe->isTracked() && n < script->nfixed) {
720 JS_ASSERT(fe->type.inMemory());
721 JS_ASSERT(fe->data.inMemory());
723 #endif
724 push(Address(JSFrameReg, sizeof(JSStackFrame) + n * sizeof(Value)));
728 inline void
729 FrameState::leaveBlock(uint32 n)
731 popn(n);
734 inline void
735 FrameState::enterBlock(uint32 n)
737 /* expect that tracker has 0 entries, for now. */
738 JS_ASSERT(!tracker.nentries);
739 JS_ASSERT(uint32(sp + n - locals) <= script->nslots);
741 sp += n;
744 inline void
745 FrameState::eviscerate(FrameEntry *fe)
747 forgetAllRegs(fe);
748 fe->type.invalidate();
749 fe->data.invalidate();
750 fe->setNotCopied();
751 fe->setCopyOf(NULL);
754 inline bool
755 FrameState::addEscaping(uint32 local)
757 if (!eval) {
758 uint32 already = escaping[local];
759 escaping[local] = 1;
760 return !already;
762 return false;
765 inline StateRemat
766 FrameState::dataRematInfo(const FrameEntry *fe) const
768 if (fe->isCopy())
769 fe = fe->copyOf();
770 StateRemat remat;
771 if (fe->data.inRegister()) {
772 remat.reg = fe->data.reg();
773 remat.inReg = true;
774 } else {
775 JS_ASSERT(fe->data.synced());
776 remat.offset = addressOf(fe).offset;
777 remat.inReg = false;
779 return remat;
782 inline void
783 FrameState::giveOwnRegs(FrameEntry *fe)
785 JS_ASSERT(!fe->isConstant());
786 JS_ASSERT(fe == peek(-1));
788 if (!fe->isCopy())
789 return;
791 RegisterID data = copyDataIntoReg(fe);
792 if (fe->isTypeKnown()) {
793 JSValueType type = fe->getKnownType();
794 pop();
795 pushTypedPayload(type, data);
796 } else {
797 RegisterID type = copyTypeIntoReg(fe);
798 pop();
799 pushRegs(type, data);
803 inline void
804 FrameState::loadDouble(RegisterID t, RegisterID d, FrameEntry *fe, FPRegisterID fpReg,
805 Assembler &masm) const
807 #ifdef JS_CPU_X86
808 masm.fastLoadDouble(d, t, fpReg);
809 #else
810 loadDouble(fe, fpReg, masm);
811 #endif
814 inline bool
815 FrameState::tryFastDoubleLoad(FrameEntry *fe, FPRegisterID fpReg, Assembler &masm) const
817 #ifdef JS_CPU_X86
818 if (fe->type.inRegister() && fe->data.inRegister()) {
819 masm.fastLoadDouble(fe->data.reg(), fe->type.reg(), fpReg);
820 return true;
822 #endif
823 return false;
826 inline void
827 FrameState::loadDouble(FrameEntry *fe, FPRegisterID fpReg, Assembler &masm) const
829 if (fe->isCopy()) {
830 FrameEntry *backing = fe->copyOf();
831 if (tryFastDoubleLoad(fe, fpReg, masm))
832 return;
833 if (backing->isCachedNumber() || (backing->type.synced() && backing->data.synced())) {
834 masm.loadDouble(addressOf(backing), fpReg);
835 return;
837 fe = backing;
840 if (tryFastDoubleLoad(fe, fpReg, masm))
841 return;
843 if ((fe->type.synced() && fe->data.synced()) || fe->isCachedNumber()) {
844 masm.loadDouble(addressOf(fe), fpReg);
845 return;
848 Address address = addressOf(fe);
849 do {
850 if (!fe->data.synced()) {
851 syncData(fe, address, masm);
852 if (fe->isConstant())
853 break;
855 if (!fe->type.synced())
856 syncType(fe, address, masm);
857 } while (0);
859 masm.loadDouble(address, fpReg);
862 } /* namspace mjit */
863 } /* namspace js */
865 #endif /* include */