File indexing completed on 2024-05-12 15:43:16
0001 /* 0002 * This file is part of the KDE libraries 0003 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) 0004 * Copyright (C) 2001 Peter Kelly (pmk@post.com) 0005 * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc. 0006 * Copyright (C) 2007, 2008 Maksim Orlovich (maksim@kde.org) 0007 * 0008 * This library is free software; you can redistribute it and/or 0009 * modify it under the terms of the GNU Library General Public 0010 * License as published by the Free Software Foundation; either 0011 * version 2 of the License, or (at your option) any later version. 0012 * 0013 * This library is distributed in the hope that it will be useful, 0014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0016 * Library General Public License for more details. 0017 * 0018 * You should have received a copy of the GNU Library General Public License 0019 * along with this library; see the file COPYING.LIB. If not, write to 0020 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0021 * Boston, MA 02110-1301, USA. 0022 * 0023 */ 0024 #include "CompileState.h" 0025 #include "nodes.h" 0026 0027 #include <wtf/Vector.h> 0028 0029 namespace KJS 0030 { 0031 0032 CompileState::~CompileState() 0033 { 0034 deleteAllValues(locals); 0035 deleteAllValues(freeMarkTemps); 0036 deleteAllValues(freeNonMarkTemps); 0037 } 0038 0039 CodeBlock &CompileState::codeBlock() 0040 { 0041 return fbody->code(); 0042 } 0043 0044 void CompileState::requestTemporary(OpType type, OpValue *value, OpValue *reference) 0045 { 0046 ASSERT(type == OpType_value || type == OpType_bool || type == OpType_int32 || type == OpType_number); 0047 0048 value->type = type; 0049 value->immediate = false; 0050 0051 reference->type = OpType_reg; 0052 reference->immediate = true; 0053 0054 RegDescriptor *temp = nullptr; 0055 0056 bool markable = (type == OpType_value); 0057 0058 if (markable && !freeMarkTemps.isEmpty()) { 0059 temp = freeMarkTemps.last(); 0060 freeMarkTemps.removeLast(); 0061 } else if (!markable && !freeNonMarkTemps.isEmpty()) { 0062 temp = freeNonMarkTemps.last(); 0063 freeNonMarkTemps.removeLast(); 0064 } 0065 0066 if (!temp) { 0067 Register id = maxTemp; 0068 fbody->reserveSlot(id, markable); 0069 temp = new RegDescriptor(this, id, markable); 0070 ++maxTemp; 0071 } 0072 0073 value->ownedReg = temp; 0074 0075 reference->ownedReg = temp; 0076 reference->value.narrow.regVal = temp->reg(); 0077 } 0078 0079 OpValue CompileState::localReadVal(Register regNum) 0080 { 0081 OpValue val; 0082 val.immediate = false; 0083 val.type = OpType_value; 0084 0085 RegDescriptor *desc = locals[regNum]; 0086 if (!desc) { 0087 desc = new RegDescriptor(this, regNum, true, false /*not a temp!*/); 0088 locals[regNum] = desc; 0089 } 0090 0091 val.ownedReg = desc; 0092 return val; 0093 } 0094 0095 void CompileState::localFlushAll(CodeBlock &block) 0096 { 0097 for (Register r = 0; r < initialMaxTemp; ++r) { 0098 if (locals[r] && locals[r]->live()) { 0099 flushLocal(block, r); 0100 } 0101 } 0102 } 0103 0104 void CompileState::flushLocal(CodeBlock & /*block*/, Register regNum) 0105 { 0106 if (locals[regNum] && locals[regNum]->live()) { 0107 OpValue localVal; 0108 localVal.immediate = false; 0109 localVal.type = OpType_value; 0110 localVal.ownedReg = locals[regNum]; 0111 0112 OpValue out, outReg; 0113 requestTemporary(OpType_value, &out, &outReg); 0114 0115 CodeGen::emitOp(this, Op_RegPutValue, nullptr, &outReg, &localVal); 0116 0117 // Now, patch up the descriptor to point to the same place as the temporary, and to 0118 // take ownership of it, and remove it from local descriptors list. 0119 locals[regNum]->adopt(out.ownedReg.get()); 0120 locals[regNum] = nullptr; 0121 } 0122 } 0123 0124 OpValue CompileState::localWriteRef(CodeBlock &block, Register regNum) 0125 { 0126 // Detach any live value copies. 0127 flushLocal(block, regNum); 0128 0129 OpValue rval; 0130 rval.immediate = true; 0131 rval.type = OpType_reg; 0132 rval.value.narrow.regVal = regNum; 0133 return rval; 0134 } 0135 0136 bool CompileState::pushLabel(const Identifier &label) 0137 { 0138 if (!seenLabels.add(label).second) { 0139 return false; // Dupe! 0140 } 0141 0142 seenLabelsStack.append(label); 0143 pendingLabels.append(label); 0144 0145 return true; 0146 } 0147 0148 void CompileState::popLabel() 0149 { 0150 Identifier name = seenLabelsStack.last(); 0151 0152 seenLabelsStack.removeLast(); 0153 seenLabels.remove(name); 0154 labelTargets.remove(name); 0155 ASSERT(pendingLabels.isEmpty()); 0156 } 0157 0158 void CompileState::bindLabels(Node *node) 0159 { 0160 for (size_t l = 0; l < pendingLabels.size(); ++l) { 0161 labelTargets.set(pendingLabels[l], node); 0162 } 0163 pendingLabels.clear(); 0164 } 0165 0166 Node *CompileState::resolveBreakLabel(Identifier label) 0167 { 0168 if (label.isEmpty()) { 0169 if (defaultBreakTargets.isEmpty()) { 0170 return nullptr; 0171 } else { 0172 return defaultBreakTargets.last(); 0173 } 0174 } else { 0175 return labelTargets.get(label); 0176 } 0177 } 0178 0179 Node *CompileState::resolveContinueLabel(Identifier label) 0180 { 0181 if (label.isEmpty()) { 0182 if (defaultContinueTargets.isEmpty()) { 0183 return nullptr; 0184 } else { 0185 return defaultContinueTargets.last(); 0186 } 0187 } else { 0188 return labelTargets.get(label); 0189 } 0190 } 0191 0192 void CompileState::pushNest(NestType type, Node *node) 0193 { 0194 if (type == Scope) { 0195 ++scopeDepth; 0196 } else if (type == TryFinally) { 0197 ++finallyDepth; 0198 } 0199 0200 NestInfo inf; 0201 inf.type = type; 0202 inf.node = node; 0203 nests.append(inf); 0204 0205 assert(!(type == ContBreakTarget && !node)); 0206 } 0207 0208 void CompileState::popNest() 0209 { 0210 if (nests.last().type == Scope) { 0211 --scopeDepth; 0212 } else if (nests.last().type == TryFinally) { 0213 --finallyDepth; 0214 } 0215 0216 nests.removeLast(); 0217 } 0218 0219 void CompileState::pushDefaultBreak(Node *node) 0220 { 0221 defaultBreakTargets.append(node); 0222 } 0223 0224 void CompileState::pushDefaultContinue(Node *node) 0225 { 0226 defaultContinueTargets.append(node); 0227 } 0228 0229 void CompileState::popDefaultBreak() 0230 { 0231 defaultBreakTargets.removeLast(); 0232 } 0233 0234 void CompileState::popDefaultContinue() 0235 { 0236 defaultContinueTargets.removeLast(); 0237 } 0238 0239 void CompileState::addPendingBreak(Node *node, Addr addr) 0240 { 0241 if (!pendingBreaks.contains(node)) { 0242 pendingBreaks.set(node, new WTF::Vector<Addr>()); 0243 } 0244 pendingBreaks.get(node)->append(addr); 0245 } 0246 0247 void CompileState::addPendingContinue(Node *node, Addr addr) 0248 { 0249 if (!pendingContinues.contains(node)) { 0250 pendingContinues.set(node, new WTF::Vector<Addr>()); 0251 } 0252 pendingContinues.get(node)->append(addr); 0253 } 0254 0255 void CompileState::resolvePendingBreaks(Node *node, Addr dest) 0256 { 0257 const WTF::Vector<Addr> *stats = pendingBreaks.get(node); 0258 if (!stats) { 0259 return; 0260 } 0261 0262 CodeBlock &block = codeBlock(); 0263 OpValue newDest = OpValue::immAddr(dest); 0264 for (size_t c = 0; c < stats->size(); ++c) { 0265 CodeGen::patchOpArgument(block, (*stats)[c], 0, newDest); 0266 } 0267 0268 pendingBreaks.remove(node); 0269 delete stats; 0270 } 0271 0272 void CompileState::resolvePendingContinues(Node *node, Addr dest) 0273 { 0274 const WTF::Vector<Addr> *stats = pendingContinues.get(node); 0275 if (!stats) { 0276 return; 0277 } 0278 0279 CodeBlock &block = codeBlock(); 0280 OpValue newDest = OpValue::immAddr(dest); 0281 for (size_t c = 0; c < stats->size(); ++c) { 0282 CodeGen::patchOpArgument(block, (*stats)[c], 0, newDest); 0283 } 0284 0285 pendingContinues.remove(node); 0286 delete stats; 0287 } 0288 0289 static OpValue *addrDummy; 0290 0291 OpValue *OpValue::dummyAddr() 0292 { 0293 if (!addrDummy) { 0294 addrDummy = new OpValue; 0295 *addrDummy = OpValue::immAddr(0); 0296 } 0297 return addrDummy; 0298 } 0299 0300 } //namespace KJS 0301