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