1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/jit/shared/Lowering-shared.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,203 @@ 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 +#include "jit/shared/Lowering-shared-inl.h" 1.11 + 1.12 +#include "jit/LIR.h" 1.13 +#include "jit/MIR.h" 1.14 + 1.15 +using namespace js; 1.16 +using namespace jit; 1.17 + 1.18 +bool 1.19 +LIRGeneratorShared::visitConstant(MConstant *ins) 1.20 +{ 1.21 + const Value &v = ins->value(); 1.22 + switch (ins->type()) { 1.23 + case MIRType_Boolean: 1.24 + return define(new(alloc()) LInteger(v.toBoolean()), ins); 1.25 + case MIRType_Int32: 1.26 + return define(new(alloc()) LInteger(v.toInt32()), ins); 1.27 + case MIRType_String: 1.28 + return define(new(alloc()) LPointer(v.toString()), ins); 1.29 + case MIRType_Object: 1.30 + return define(new(alloc()) LPointer(&v.toObject()), ins); 1.31 + default: 1.32 + // Constants of special types (undefined, null) should never flow into 1.33 + // here directly. Operations blindly consuming them require a Box. 1.34 + JS_ASSERT(!"unexpected constant type"); 1.35 + return false; 1.36 + } 1.37 +} 1.38 + 1.39 +bool 1.40 +LIRGeneratorShared::defineTypedPhi(MPhi *phi, size_t lirIndex) 1.41 +{ 1.42 + LPhi *lir = current->getPhi(lirIndex); 1.43 + 1.44 + uint32_t vreg = getVirtualRegister(); 1.45 + if (vreg >= MAX_VIRTUAL_REGISTERS) 1.46 + return false; 1.47 + 1.48 + phi->setVirtualRegister(vreg); 1.49 + lir->setDef(0, LDefinition(vreg, LDefinition::TypeFrom(phi->type()))); 1.50 + annotate(lir); 1.51 + return true; 1.52 +} 1.53 + 1.54 +void 1.55 +LIRGeneratorShared::lowerTypedPhiInput(MPhi *phi, uint32_t inputPosition, LBlock *block, size_t lirIndex) 1.56 +{ 1.57 + MDefinition *operand = phi->getOperand(inputPosition); 1.58 + LPhi *lir = block->getPhi(lirIndex); 1.59 + lir->setOperand(inputPosition, LUse(operand->virtualRegister(), LUse::ANY)); 1.60 +} 1.61 + 1.62 +LRecoverInfo * 1.63 +LIRGeneratorShared::getRecoverInfo(MResumePoint *rp) 1.64 +{ 1.65 + if (cachedRecoverInfo_ && cachedRecoverInfo_->mir() == rp) 1.66 + return cachedRecoverInfo_; 1.67 + 1.68 + LRecoverInfo *recoverInfo = LRecoverInfo::New(gen, rp); 1.69 + if (!recoverInfo) 1.70 + return nullptr; 1.71 + 1.72 + cachedRecoverInfo_ = recoverInfo; 1.73 + return recoverInfo; 1.74 +} 1.75 + 1.76 +#ifdef JS_NUNBOX32 1.77 +LSnapshot * 1.78 +LIRGeneratorShared::buildSnapshot(LInstruction *ins, MResumePoint *rp, BailoutKind kind) 1.79 +{ 1.80 + LRecoverInfo *recover = getRecoverInfo(rp); 1.81 + if (!recover) 1.82 + return nullptr; 1.83 + 1.84 + LSnapshot *snapshot = LSnapshot::New(gen, recover, kind); 1.85 + if (!snapshot) 1.86 + return nullptr; 1.87 + 1.88 + size_t i = 0; 1.89 + for (MResumePoint **it = recover->begin(), **end = recover->end(); it != end; ++it) { 1.90 + MResumePoint *mir = *it; 1.91 + for (size_t j = 0, e = mir->numOperands(); j < e; ++i, ++j) { 1.92 + MDefinition *ins = mir->getOperand(j); 1.93 + 1.94 + LAllocation *type = snapshot->typeOfSlot(i); 1.95 + LAllocation *payload = snapshot->payloadOfSlot(i); 1.96 + 1.97 + if (ins->isBox()) 1.98 + ins = ins->toBox()->getOperand(0); 1.99 + 1.100 + // Guards should never be eliminated. 1.101 + JS_ASSERT_IF(ins->isUnused(), !ins->isGuard()); 1.102 + 1.103 + // Snapshot operands other than constants should never be 1.104 + // emitted-at-uses. Try-catch support depends on there being no 1.105 + // code between an instruction and the LOsiPoint that follows it. 1.106 + JS_ASSERT_IF(!ins->isConstant(), !ins->isEmittedAtUses()); 1.107 + 1.108 + // The register allocation will fill these fields in with actual 1.109 + // register/stack assignments. During code generation, we can restore 1.110 + // interpreter state with the given information. Note that for 1.111 + // constants, including known types, we record a dummy placeholder, 1.112 + // since we can recover the same information, much cleaner, from MIR. 1.113 + if (ins->isConstant() || ins->isUnused()) { 1.114 + *type = LConstantIndex::Bogus(); 1.115 + *payload = LConstantIndex::Bogus(); 1.116 + } else if (ins->type() != MIRType_Value) { 1.117 + *type = LConstantIndex::Bogus(); 1.118 + *payload = use(ins, LUse::KEEPALIVE); 1.119 + } else { 1.120 + *type = useType(ins, LUse::KEEPALIVE); 1.121 + *payload = usePayload(ins, LUse::KEEPALIVE); 1.122 + } 1.123 + } 1.124 + } 1.125 + 1.126 + return snapshot; 1.127 +} 1.128 + 1.129 +#elif JS_PUNBOX64 1.130 + 1.131 +LSnapshot * 1.132 +LIRGeneratorShared::buildSnapshot(LInstruction *ins, MResumePoint *rp, BailoutKind kind) 1.133 +{ 1.134 + LRecoverInfo *recover = getRecoverInfo(rp); 1.135 + if (!recover) 1.136 + return nullptr; 1.137 + 1.138 + LSnapshot *snapshot = LSnapshot::New(gen, recover, kind); 1.139 + if (!snapshot) 1.140 + return nullptr; 1.141 + 1.142 + size_t i = 0; 1.143 + for (MResumePoint **it = recover->begin(), **end = recover->end(); it != end; ++it) { 1.144 + MResumePoint *mir = *it; 1.145 + for (size_t j = 0, e = mir->numOperands(); j < e; ++i, ++j) { 1.146 + MDefinition *def = mir->getOperand(j); 1.147 + 1.148 + if (def->isBox()) 1.149 + def = def->toBox()->getOperand(0); 1.150 + 1.151 + // Guards should never be eliminated. 1.152 + JS_ASSERT_IF(def->isUnused(), !def->isGuard()); 1.153 + 1.154 + // Snapshot operands other than constants should never be 1.155 + // emitted-at-uses. Try-catch support depends on there being no 1.156 + // code between an instruction and the LOsiPoint that follows it. 1.157 + JS_ASSERT_IF(!def->isConstant(), !def->isEmittedAtUses()); 1.158 + 1.159 + LAllocation *a = snapshot->getEntry(i); 1.160 + 1.161 + if (def->isUnused()) { 1.162 + *a = LConstantIndex::Bogus(); 1.163 + continue; 1.164 + } 1.165 + 1.166 + *a = useKeepaliveOrConstant(def); 1.167 + } 1.168 + } 1.169 + 1.170 + return snapshot; 1.171 +} 1.172 +#endif 1.173 + 1.174 +bool 1.175 +LIRGeneratorShared::assignSnapshot(LInstruction *ins, BailoutKind kind) 1.176 +{ 1.177 + // assignSnapshot must be called before define/add, since 1.178 + // it may add new instructions for emitted-at-use operands. 1.179 + JS_ASSERT(ins->id() == 0); 1.180 + 1.181 + LSnapshot *snapshot = buildSnapshot(ins, lastResumePoint_, kind); 1.182 + if (!snapshot) 1.183 + return false; 1.184 + 1.185 + ins->assignSnapshot(snapshot); 1.186 + return true; 1.187 +} 1.188 + 1.189 +bool 1.190 +LIRGeneratorShared::assignSafepoint(LInstruction *ins, MInstruction *mir) 1.191 +{ 1.192 + JS_ASSERT(!osiPoint_); 1.193 + JS_ASSERT(!ins->safepoint()); 1.194 + 1.195 + ins->initSafepoint(alloc()); 1.196 + 1.197 + MResumePoint *mrp = mir->resumePoint() ? mir->resumePoint() : lastResumePoint_; 1.198 + LSnapshot *postSnapshot = buildSnapshot(ins, mrp, Bailout_Normal); 1.199 + if (!postSnapshot) 1.200 + return false; 1.201 + 1.202 + osiPoint_ = new(alloc()) LOsiPoint(ins->safepoint(), postSnapshot); 1.203 + 1.204 + return lirGraph_.noteNeedsSafepoint(ins); 1.205 +} 1.206 +