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
17 * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
20 * The Initial Developer of the Original Code is
21 * Brendan Eich <brendan@mozilla.org>
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__
47 FrameState::addToTracker(FrameEntry *fe)
49 JS_ASSERT(!fe->isTracked());
50 fe->track(tracker.nentries);
52 JS_ASSERT(tracker.nentries <= feLimit());
56 FrameState::peek(int32 depth)
59 JS_ASSERT(sp + depth >= spBase);
60 FrameEntry *fe = &sp[depth];
61 if (!fe->isTracked()) {
69 FrameState::popn(uint32 n)
71 for (uint32 i = 0; i < n; i++)
76 FrameState::haveSameBacking(FrameEntry *lhs, FrameEntry *rhs)
85 inline JSC::MacroAssembler::RegisterID
86 FrameState::allocReg()
89 if (!freeRegs.empty()) {
90 reg = freeRegs.takeAnyReg();
93 regstate[reg].forget();
99 inline JSC::MacroAssembler::RegisterID
100 FrameState::allocReg(uint32 mask)
103 if (freeRegs.hasRegInMask(mask)) {
104 reg = freeRegs.takeRegInMask(mask);
106 reg = evictSomeReg(mask);
107 regstate[reg].forget();
113 inline JSC::MacroAssembler::RegisterID
114 FrameState::allocReg(FrameEntry *fe, RematInfo::RematType type)
117 if (!freeRegs.empty()) {
118 reg = freeRegs.takeAnyReg();
120 reg = evictSomeReg();
121 regstate[reg].forget();
124 regstate[reg].associate(fe, type);
130 FrameState::convertInt32ToDouble(Assembler &masm, FrameEntry *fe, FPRegisterID fpreg) const
132 JS_ASSERT(!fe->isConstant());
137 if (fe->data.inRegister())
138 masm.convertInt32ToDouble(fe->data.reg(), fpreg);
140 masm.convertInt32ToDouble(addressOf(fe), fpreg);
144 FrameState::peekTypeInRegister(FrameEntry *fe) const
148 return fe->type.inRegister();
154 JS_ASSERT(sp > spBase);
156 FrameEntry *fe = --sp;
157 if (!fe->isTracked())
164 FrameState::freeReg(RegisterID reg)
166 JS_ASSERT(!regstate[reg].usedBy());
168 freeRegs.putReg(reg);
172 FrameState::forgetReg(RegisterID reg)
175 * Important: Do not touch the fe here. We can peephole optimize away
176 * loads and stores by re-using the contents of old FEs.
178 JS_ASSERT_IF(regstate[reg].fe(), !regstate[reg].fe()->isCopy());
180 if (!regstate[reg].isPinned()) {
181 regstate[reg].forget();
182 freeRegs.putReg(reg);
187 FrameState::syncAndForgetEverything(uint32 newStackDepth)
189 syncAndForgetEverything();
190 sp = spBase + newStackDepth;
194 FrameState::rawPush()
196 JS_ASSERT(unsigned(sp - entries) < feLimit());
198 if (!sp->isTracked())
205 FrameState::push(const Value &v)
207 FrameEntry *fe = rawPush();
208 fe->setConstant(Jsvalify(v));
212 FrameState::pushSynced()
220 FrameState::pushSyncedType(JSValueType type)
222 FrameEntry *fe = rawPush();
229 FrameState::pushSynced(JSValueType type, RegisterID reg)
231 FrameEntry *fe = rawPush();
237 fe->data.setRegister(reg);
238 regstate[reg].associate(fe, RematInfo::DATA);
242 FrameState::push(Address address)
245 // It's okay if either of these clobbers address.base, since we guarantee
246 // eviction will not physically clobber. It's also safe, on x64, for
247 // loadValueAsComponents() to take either type or data regs as address.base.
248 RegisterID typeReg = allocReg();
249 RegisterID dataReg = allocReg();
250 masm.loadValueAsComponents(address, typeReg, dataReg);
252 // Prevent us from clobbering this reg.
253 bool free = freeRegs.hasReg(address.base);
255 freeRegs.takeReg(address.base);
257 RegisterID typeReg = allocReg();
259 masm.loadTypeTag(address, typeReg);
261 // Allow re-use of the base register. This could avoid a spill, and
262 // is safe because the following allocReg() won't actually emit any
263 // writes to the register.
265 freeRegs.putReg(address.base);
267 RegisterID dataReg = allocReg();
268 masm.loadPayload(address, dataReg);
271 pushRegs(typeReg, dataReg);
275 FrameState::pushRegs(RegisterID type, RegisterID data)
277 JS_ASSERT(!freeRegs.hasReg(type) && !freeRegs.hasReg(data));
279 FrameEntry *fe = rawPush();
282 fe->type.setRegister(type);
283 fe->data.setRegister(data);
284 regstate[type].associate(fe, RematInfo::TYPE);
285 regstate[data].associate(fe, RematInfo::DATA);
289 FrameState::pushTypedPayload(JSValueType type, RegisterID payload)
291 JS_ASSERT(!freeRegs.hasReg(payload));
293 FrameEntry *fe = rawPush();
297 fe->data.setRegister(payload);
298 regstate[payload].associate(fe, RematInfo::DATA);
302 FrameState::pushNumber(MaybeRegisterID payload, bool asInt32)
304 JS_ASSERT_IF(payload.isSet(), !freeRegs.hasReg(payload.reg()));
306 FrameEntry *fe = rawPush();
309 JS_ASSERT(!fe->isNumber);
312 if (!fe->type.synced())
313 masm.storeTypeTag(ImmType(JSVAL_TYPE_INT32), addressOf(fe));
314 fe->type.setMemory();
316 fe->type.setMemory();
320 if (payload.isSet()) {
322 fe->data.setRegister(payload.reg());
323 regstate[payload.reg()].associate(fe, RematInfo::DATA);
325 fe->data.setMemory();
330 FrameState::pushInt32(RegisterID payload)
332 FrameEntry *fe = rawPush();
334 JS_ASSERT(!fe->isNumber);
336 masm.storeTypeTag(ImmType(JSVAL_TYPE_INT32), addressOf(fe));
337 fe->type.setMemory();
341 fe->data.setRegister(payload);
342 regstate[payload].associate(fe, RematInfo::DATA);
346 FrameState::pushInitializerObject(RegisterID payload, bool array, JSObject *baseobj)
348 pushTypedPayload(JSVAL_TYPE_OBJECT, payload);
350 FrameEntry *fe = peek(-1);
351 fe->initArray = array;
352 fe->initObject = baseobj;
356 FrameState::pushUntypedPayload(JSValueType type, RegisterID payload)
358 JS_ASSERT(!freeRegs.hasReg(payload));
360 FrameEntry *fe = rawPush();
364 masm.storeTypeTag(ImmType(type), addressOf(fe));
366 /* The forceful type sync will assert otherwise. */
370 fe->type.setMemory();
374 fe->data.setRegister(payload);
375 regstate[payload].associate(fe, RematInfo::DATA);
379 FrameState::pushUntypedValue(const Value &v)
381 FrameEntry *fe = rawPush();
385 masm.storeValue(v, addressOf(fe));
387 /* The forceful type sync will assert otherwise. */
391 fe->type.setMemory();
393 fe->data.setMemory();
398 inline JSC::MacroAssembler::RegisterID
399 FrameState::tempRegForType(FrameEntry *fe, RegisterID fallback)
401 JS_ASSERT(!regstate[fallback].fe());
405 JS_ASSERT(!fe->type.isConstant());
407 if (fe->type.inRegister())
408 return fe->type.reg();
412 masm.loadTypeTag(addressOf(fe), fallback);
417 inline JSC::MacroAssembler::RegisterID
418 FrameState::tempRegForType(FrameEntry *fe)
423 JS_ASSERT(!fe->type.isConstant());
425 if (fe->type.inRegister())
426 return fe->type.reg();
430 RegisterID reg = allocReg(fe, RematInfo::TYPE);
431 masm.loadTypeTag(addressOf(fe), reg);
432 fe->type.setRegister(reg);
436 inline JSC::MacroAssembler::RegisterID
437 FrameState::tempRegForData(FrameEntry *fe)
439 JS_ASSERT(!fe->data.isConstant());
444 if (fe->data.inRegister())
445 return fe->data.reg();
447 RegisterID reg = allocReg(fe, RematInfo::DATA);
448 masm.loadPayload(addressOf(fe), reg);
449 fe->data.setRegister(reg);
453 inline JSC::MacroAssembler::RegisterID
454 FrameState::tempRegInMaskForData(FrameEntry *fe, uint32 mask)
456 JS_ASSERT(!fe->data.isConstant());
462 if (fe->data.inRegister()) {
463 RegisterID old = fe->data.reg();
464 if (Registers::maskReg(old) & mask)
467 /* Keep the old register pinned. */
468 regstate[old].forget();
469 reg = allocReg(mask);
473 reg = allocReg(mask);
474 masm.loadPayload(addressOf(fe), reg);
476 regstate[reg].associate(fe, RematInfo::DATA);
477 fe->data.setRegister(reg);
481 inline JSC::MacroAssembler::RegisterID
482 FrameState::tempRegForData(FrameEntry *fe, RegisterID reg, Assembler &masm) const
484 JS_ASSERT(!fe->data.isConstant());
489 if (fe->data.inRegister()) {
490 JS_ASSERT(fe->data.reg() != reg);
491 return fe->data.reg();
493 masm.loadPayload(addressOf(fe), reg);
499 FrameState::shouldAvoidTypeRemat(FrameEntry *fe)
501 return fe->type.inMemory();
505 FrameState::shouldAvoidDataRemat(FrameEntry *fe)
507 return fe->data.inMemory();
511 FrameState::ensureFeSynced(const FrameEntry *fe, Assembler &masm) const
513 #if defined JS_PUNBOX64
514 Address to = addressOf(fe);
515 const FrameEntry *backing = fe;
517 backing = fe->copyOf();
519 /* If we can, sync the type and data in one go. */
520 if (!fe->data.synced() && !fe->type.synced()) {
521 if (backing->isConstant())
522 masm.storeValue(backing->getValue(), to);
523 else if (backing->isTypeKnown())
524 masm.storeValueFromComponents(ImmType(backing->getKnownType()), backing->data.reg(), to);
526 masm.storeValueFromComponents(backing->type.reg(), backing->data.reg(), to);
532 * On x86_64, only one of the following two calls will have output,
533 * and a load will only occur if necessary.
535 ensureDataSynced(fe, masm);
536 ensureTypeSynced(fe, masm);
540 FrameState::ensureTypeSynced(const FrameEntry *fe, Assembler &masm) const
542 if (fe->type.synced())
545 Address to = addressOf(fe);
546 const FrameEntry *backing = fe;
548 backing = fe->copyOf();
550 #if defined JS_PUNBOX64
551 /* Attempt to store the entire Value, to prevent a load. */
552 if (backing->isConstant()) {
553 masm.storeValue(backing->getValue(), to);
557 if (backing->data.inRegister()) {
558 RegisterID dreg = backing->data.reg();
559 if (backing->isTypeKnown())
560 masm.storeValueFromComponents(ImmType(backing->getKnownType()), dreg, to);
562 masm.storeValueFromComponents(backing->type.reg(), dreg, to);
567 /* Store a double's type bits, even though !isTypeKnown(). */
568 if (backing->isConstant())
569 masm.storeTypeTag(ImmTag(backing->getKnownTag()), to);
570 else if (backing->isTypeKnown())
571 masm.storeTypeTag(ImmType(backing->getKnownType()), to);
573 masm.storeTypeTag(backing->type.reg(), to);
577 FrameState::ensureDataSynced(const FrameEntry *fe, Assembler &masm) const
579 if (fe->data.synced())
582 Address to = addressOf(fe);
583 const FrameEntry *backing = fe;
585 backing = fe->copyOf();
587 #if defined JS_PUNBOX64
588 if (backing->isConstant())
589 masm.storeValue(backing->getValue(), to);
590 else if (backing->isTypeKnown())
591 masm.storeValueFromComponents(ImmType(backing->getKnownType()), backing->data.reg(), to);
592 else if (backing->type.inRegister())
593 masm.storeValueFromComponents(backing->type.reg(), backing->data.reg(), to);
595 masm.storePayload(backing->data.reg(), to);
596 #elif defined JS_NUNBOX32
597 if (backing->isConstant())
598 masm.storePayload(ImmPayload(backing->getPayload()), to);
600 masm.storePayload(backing->data.reg(), to);
605 FrameState::syncFe(FrameEntry *fe)
607 FrameEntry *backing = fe;
609 backing = fe->copyOf();
611 bool needTypeReg = !fe->type.synced() && backing->type.inMemory();
612 bool needDataReg = !fe->data.synced() && backing->data.inMemory();
614 #if defined JS_NUNBOX32
615 /* Determine an ordering that won't spill known regs. */
616 if (needTypeReg && !needDataReg) {
623 #elif defined JS_PUNBOX64
624 if (JS_UNLIKELY(needTypeReg && needDataReg)) {
625 /* Memory-to-memory moves can only occur for copies backed by memory. */
626 JS_ASSERT(backing != fe);
628 /* Use ValueReg to do a whole-Value mem-to-mem move. */
629 masm.loadValue(addressOf(backing), Registers::ValueReg);
630 masm.storeValue(Registers::ValueReg, addressOf(fe));
632 /* Store in case unpinning is necessary. */
633 MaybeRegisterID pairReg;
635 /* Get a register if necessary, without clobbering its pair. */
637 if (backing->data.inRegister() && !regstate[backing->data.reg()].isPinned()) {
638 pairReg = backing->data.reg();
639 pinReg(backing->data.reg());
641 tempRegForType(backing);
642 } else if (needDataReg) {
643 if (backing->type.inRegister() && !regstate[backing->type.reg()].isPinned()) {
644 pairReg = backing->type.reg();
645 pinReg(backing->type.reg());
647 tempRegForData(backing);
650 ensureFeSynced(fe, masm);
653 unpinReg(pairReg.reg());
656 if (!fe->type.synced())
658 if (!fe->data.synced())
664 FrameState::syncType(FrameEntry *fe)
666 FrameEntry *backing = fe;
668 backing = fe->copyOf();
670 if (!fe->type.synced() && backing->type.inMemory())
671 tempRegForType(backing);
673 ensureTypeSynced(fe, masm);
675 if (!fe->type.synced())
680 FrameState::syncData(FrameEntry *fe)
682 FrameEntry *backing = fe;
684 backing = fe->copyOf();
686 if (!fe->data.synced() && backing->data.inMemory())
687 tempRegForData(backing);
689 ensureDataSynced(fe, masm);
691 if (!fe->data.synced())
696 FrameState::forgetType(FrameEntry *fe)
699 * The type may have been forgotten with an intervening storeLocal in the
700 * presence of eval or closed variables. For defense in depth and to make
701 * callers' lives simpler, bail out if the type is not known.
703 if (!fe->isTypeKnown())
707 * Likewise, storeLocal() may have set this FE, with a known type,
708 * to be a copy of another FE, which has an unknown type.
709 * Just forget the type, since the backing is used in all cases.
712 fe->type.invalidate();
716 ensureTypeSynced(fe, masm);
717 fe->type.setMemory();
721 FrameState::learnType(FrameEntry *fe, JSValueType type)
723 if (fe->type.inRegister())
724 forgetReg(fe->type.reg());
726 fe->isNumber = false;
731 inline JSC::MacroAssembler::Address
732 FrameState::addressOf(const FrameEntry *fe) const
734 int32 frameOffset = 0;
736 frameOffset = JSStackFrame::offsetOfFixed(uint32(fe - locals));
738 frameOffset = JSStackFrame::offsetOfFormalArg(fun, uint32(fe - args));
739 else if (fe == this_)
740 frameOffset = JSStackFrame::offsetOfThis(fun);
741 else if (fe == callee_)
742 frameOffset = JSStackFrame::offsetOfCallee(fun);
743 JS_ASSERT(frameOffset);
744 return Address(JSFrameReg, frameOffset);
747 inline JSC::MacroAssembler::Address
748 FrameState::addressForDataRemat(const FrameEntry *fe) const
750 if (fe->isCopy() && !fe->data.synced())
752 JS_ASSERT(fe->data.synced());
753 return addressOf(fe);
756 inline JSC::MacroAssembler::Jump
757 FrameState::testNull(Assembler::Condition cond, FrameEntry *fe)
759 JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
760 if (shouldAvoidTypeRemat(fe))
761 return masm.testNull(cond, addressOf(fe));
762 return masm.testNull(cond, tempRegForType(fe));
765 inline JSC::MacroAssembler::Jump
766 FrameState::testUndefined(Assembler::Condition cond, FrameEntry *fe)
768 JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
769 if (shouldAvoidTypeRemat(fe))
770 return masm.testUndefined(cond, addressOf(fe));
771 return masm.testUndefined(cond, tempRegForType(fe));
774 inline JSC::MacroAssembler::Jump
775 FrameState::testInt32(Assembler::Condition cond, FrameEntry *fe)
777 JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
778 if (shouldAvoidTypeRemat(fe))
779 return masm.testInt32(cond, addressOf(fe));
780 return masm.testInt32(cond, tempRegForType(fe));
783 inline JSC::MacroAssembler::Jump
784 FrameState::testPrimitive(Assembler::Condition cond, FrameEntry *fe)
786 JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
787 if (shouldAvoidTypeRemat(fe))
788 return masm.testPrimitive(cond, addressOf(fe));
789 return masm.testPrimitive(cond, tempRegForType(fe));
792 inline JSC::MacroAssembler::Jump
793 FrameState::testObject(Assembler::Condition cond, FrameEntry *fe)
795 JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
796 if (shouldAvoidTypeRemat(fe))
797 return masm.testObject(cond, addressOf(fe));
798 return masm.testObject(cond, tempRegForType(fe));
801 inline JSC::MacroAssembler::Jump
802 FrameState::testDouble(Assembler::Condition cond, FrameEntry *fe)
804 JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
805 if (shouldAvoidTypeRemat(fe))
806 return masm.testDouble(cond, addressOf(fe));
807 return masm.testDouble(cond, tempRegForType(fe));
810 inline JSC::MacroAssembler::Jump
811 FrameState::testBoolean(Assembler::Condition cond, FrameEntry *fe)
813 JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
814 if (shouldAvoidTypeRemat(fe))
815 return masm.testBoolean(cond, addressOf(fe));
816 return masm.testBoolean(cond, tempRegForType(fe));
819 inline JSC::MacroAssembler::Jump
820 FrameState::testString(Assembler::Condition cond, FrameEntry *fe)
822 JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
823 if (shouldAvoidTypeRemat(fe))
824 return masm.testString(cond, addressOf(fe));
825 return masm.testString(cond, tempRegForType(fe));
829 FrameState::getOrTrack(uint32 index)
831 FrameEntry *fe = &entries[index];
832 if (!fe->isTracked()) {
840 FrameState::getLocal(uint32 slot)
842 JS_ASSERT(slot < script->nslots);
843 return getOrTrack(uint32(&locals[slot] - entries));
847 FrameState::getArg(uint32 slot)
849 JS_ASSERT(slot < nargs);
850 return getOrTrack(uint32(&args[slot] - entries));
854 FrameState::getThis()
856 return getOrTrack(uint32(this_ - entries));
860 FrameState::getCallee()
862 // Callee can only be used in function code, and it's always an object.
864 if (!callee_->isTracked()) {
865 addToTracker(callee_);
866 callee_->resetSynced();
867 callee_->setType(JSVAL_TYPE_OBJECT);
873 FrameState::pinReg(RegisterID reg)
879 FrameState::unpinReg(RegisterID reg)
881 regstate[reg].unpin();
885 FrameState::unpinKilledReg(RegisterID reg)
887 regstate[reg].unpinUnsafe();
888 freeRegs.putReg(reg);
892 FrameState::forgetAllRegs(FrameEntry *fe)
894 if (fe->type.inRegister())
895 forgetReg(fe->type.reg());
896 if (fe->data.inRegister())
897 forgetReg(fe->data.reg());
901 FrameState::swapInTracker(FrameEntry *lhs, FrameEntry *rhs)
903 uint32 li = lhs->trackerIndex();
904 uint32 ri = rhs->trackerIndex();
905 JS_ASSERT(tracker[li] == lhs);
906 JS_ASSERT(tracker[ri] == rhs);
907 tracker.entries[ri] = lhs;
908 tracker.entries[li] = rhs;
922 FrameEntry *lhs = peek(-2);
923 FrameEntry *rhs = peek(-1);
924 pushCopyOf(indexOfFe(lhs));
925 pushCopyOf(indexOfFe(rhs));
929 FrameState::dupAt(int32 n)
932 FrameEntry *fe = peek(n);
933 pushCopyOf(indexOfFe(fe));
937 FrameState::pushLocal(uint32 n)
939 FrameEntry *fe = getLocal(n);
940 if (!isClosedVar(n)) {
941 pushCopyOf(indexOfFe(fe));
945 * We really want to assert on local variables, but in the presence of
946 * SETLOCAL equivocation of stack slots, and let expressions, just
947 * weakly assert on the fixed local vars.
949 FrameEntry *fe = &locals[n];
950 if (fe->isTracked() && n < script->nfixed) {
951 JS_ASSERT(fe->type.inMemory());
952 JS_ASSERT(fe->data.inMemory());
960 FrameState::pushArg(uint32 n)
962 FrameEntry *fe = getArg(n);
963 if (!isClosedArg(n)) {
964 pushCopyOf(indexOfFe(fe));
967 FrameEntry *fe = &args[n];
968 if (fe->isTracked()) {
969 JS_ASSERT(fe->type.inMemory());
970 JS_ASSERT(fe->data.inMemory());
978 FrameState::pushCallee()
980 FrameEntry *fe = getCallee();
981 pushCopyOf(indexOfFe(fe));
985 FrameState::pushThis()
987 FrameEntry *fe = getThis();
988 pushCopyOf(indexOfFe(fe));
992 FrameState::learnThisIsObject()
994 // This is safe, albeit hacky. This is only called from the compiler,
995 // and only on the first use of |this| inside a basic block. Thus,
996 // there are no copies of |this| anywhere.
997 learnType(this_, JSVAL_TYPE_OBJECT);
1001 FrameState::leaveBlock(uint32 n)
1007 FrameState::enterBlock(uint32 n)
1009 /* expect that tracker has 0 entries, for now. */
1010 JS_ASSERT(!tracker.nentries);
1011 JS_ASSERT(uint32(sp + n - locals) <= script->nslots);
1014 memset(&closedVars[uint32(sp - locals)], 0, n * sizeof(*closedVars));
1019 FrameState::eviscerate(FrameEntry *fe)
1022 fe->type.invalidate();
1023 fe->data.invalidate();
1025 fe->setCopyOf(NULL);
1029 FrameState::setClosedVar(uint32 slot)
1032 closedVars[slot] = true;
1036 FrameState::setClosedArg(uint32 slot)
1038 if (!eval && !usesArguments)
1039 closedArgs[slot] = true;
1043 FrameState::dataRematInfo(const FrameEntry *fe) const
1048 if (fe->data.inRegister())
1049 return StateRemat::FromRegister(fe->data.reg());
1051 JS_ASSERT(fe->data.synced());
1052 return StateRemat::FromAddress(addressOf(fe));
1056 FrameState::giveOwnRegs(FrameEntry *fe)
1058 JS_ASSERT(!fe->isConstant());
1059 JS_ASSERT(fe == peek(-1));
1064 RegisterID data = copyDataIntoReg(fe);
1065 if (fe->isTypeKnown()) {
1066 JSValueType type = fe->getKnownType();
1068 pushTypedPayload(type, data);
1070 RegisterID type = copyTypeIntoReg(fe);
1072 pushRegs(type, data);
1077 FrameState::loadDouble(RegisterID t, RegisterID d, FrameEntry *fe, FPRegisterID fpReg,
1078 Assembler &masm) const
1081 masm.fastLoadDouble(d, t, fpReg);
1083 loadDouble(fe, fpReg, masm);
1088 FrameState::tryFastDoubleLoad(FrameEntry *fe, FPRegisterID fpReg, Assembler &masm) const
1091 if (fe->type.inRegister() && fe->data.inRegister()) {
1092 masm.fastLoadDouble(fe->data.reg(), fe->type.reg(), fpReg);
1100 FrameState::loadDouble(FrameEntry *fe, FPRegisterID fpReg, Assembler &masm) const
1103 FrameEntry *backing = fe->copyOf();
1104 if (tryFastDoubleLoad(fe, fpReg, masm))
1106 if (backing->isCachedNumber() || (backing->type.synced() && backing->data.synced())) {
1107 masm.loadDouble(addressOf(backing), fpReg);
1113 if (tryFastDoubleLoad(fe, fpReg, masm))
1116 if ((fe->type.synced() && fe->data.synced()) || fe->isCachedNumber()) {
1117 masm.loadDouble(addressOf(fe), fpReg);
1121 ensureFeSynced(fe, masm);
1122 masm.loadDouble(addressOf(fe), fpReg);
1126 FrameState::isClosedVar(uint32 slot)
1128 return eval || closedVars[slot];
1132 FrameState::isClosedArg(uint32 slot)
1134 return eval || usesArguments || closedArgs[slot];
1137 class PinRegAcrossSyncAndKill
1139 typedef JSC::MacroAssembler::RegisterID RegisterID;
1141 MaybeRegisterID maybeReg;
1143 PinRegAcrossSyncAndKill(FrameState &frame, RegisterID reg)
1144 : frame(frame), maybeReg(reg)
1148 PinRegAcrossSyncAndKill(FrameState &frame, MaybeRegisterID maybeReg)
1149 : frame(frame), maybeReg(maybeReg)
1151 if (maybeReg.isSet())
1152 frame.pinReg(maybeReg.reg());
1154 ~PinRegAcrossSyncAndKill() {
1155 if (maybeReg.isSet())
1156 frame.unpinKilledReg(maybeReg.reg());
1160 } /* namespace mjit */
1161 } /* namespace js */
1163 #endif /* include */