Remove "All rights reserved" line from license headers.
[profile/ivi/qtdeclarative.git] / src / declarative / qml / v4 / qv4instruction.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtDeclarative module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qv4instruction_p.h"
43 #include "qv4bindings_p.h"
44
45 #include <QtCore/qdebug.h>
46 #include <private/qdeclarativeglobal_p.h>
47
48 // Define this to do a test dump of all the instructions at startup.  This is 
49 // helpful to test that each instruction's Instr::dump() case uses the correct
50 // number of tabs etc and otherwise looks correct.
51 // #define DEBUG_INSTR_DUMP
52
53 QT_BEGIN_NAMESPACE
54
55 namespace QDeclarativeJS {
56
57 #ifdef DEBUG_INSTR_DUMP
58 static struct DumpInstrAtStartup {
59     DumpInstrAtStartup() {
60         Bytecode bc;
61 #define DUMP_INSTR_AT_STARTUP(I, FMT) { V4InstrData<V4Instr::I> i; bc.append(i); }
62         FOR_EACH_V4_INSTR(DUMP_INSTR_AT_STARTUP);
63 #undef DUMP_INSTR_AT_STARTUP
64         const char *start = bc.constData();
65         const char *end = start + bc.size();
66         bc.dump(start, end);
67     }
68 } dump_instr_at_startup;
69 #endif
70
71 int V4Instr::size(Type type)
72 {
73 #define V4_RETURN_INSTR_SIZE(I, FMT) case I: return QML_V4_INSTR_SIZE(I, FMT);
74     switch (type) {
75     FOR_EACH_V4_INSTR(V4_RETURN_INSTR_SIZE)
76     }
77 #undef V4_RETURN_INSTR_SIZE
78     return 0;
79 }
80
81 void Bytecode::dump(const V4Instr *i, int address) const
82 {
83     QByteArray leading;
84     if (address != -1) {
85         leading = QByteArray::number(address);
86         leading.prepend(QByteArray(8 - leading.count(), ' '));
87         leading.append("\t");
88     }
89
90 #define INSTR_DUMP qWarning().nospace() << leading.constData() 
91
92     switch (instructionType(i)) {
93     case V4Instr::Noop:
94         INSTR_DUMP << "\t" << "Noop";
95         break;
96     case V4Instr::BindingId:
97         INSTR_DUMP << i->id.line << ":" << i->id.column << ":";
98         break;
99     case V4Instr::Subscribe:
100         INSTR_DUMP << "\t" << "Subscribe" << "\t\t" << "Object_Reg(" << i->subscribeop.reg << ") Notify_Signal(" << i->subscribeop.index << ") -> Subscribe_Slot(" << i->subscribeop.offset << ")";
101         break;
102     case V4Instr::SubscribeId:
103         INSTR_DUMP << "\t" << "SubscribeId" << "\t\t" << "Id_Offset(" << i->subscribeop.index << ") -> Subscribe_Slot(" << i->subscribeop.offset << ")";
104         break;
105     case V4Instr::FetchAndSubscribe:
106         INSTR_DUMP << "\t" << "FetchAndSubscribe" << "\t" << "Object_Reg(" << i->fetchAndSubscribe.reg << ") Fast_Accessor(" << i->fetchAndSubscribe.property.accessors << ") -> Output_Reg(" << i->fetchAndSubscribe.reg << ") Subscription_Slot(" <<  i->fetchAndSubscribe.subscription << ")";
107         break;
108     case V4Instr::LoadId:
109         INSTR_DUMP << "\t" << "LoadId" << "\t\t\t" << "Id_Offset(" << i->load.index << ") -> Output_Reg(" << i->load.reg << ")";
110         break;
111     case V4Instr::LoadScope:
112         INSTR_DUMP << "\t" << "LoadScope" << "\t\t" << "-> Output_Reg(" << i->load.reg << ")";
113         break;
114     case V4Instr::LoadRoot:
115         INSTR_DUMP << "\t" << "LoadRoot" << "\t\t" << "-> Output_Reg(" << i->load.reg << ")";
116         break;
117     case V4Instr::LoadAttached:
118         INSTR_DUMP << "\t" << "LoadAttached" << "\t\t" << "Object_Reg(" << i->attached.reg << ") Attached_Index(" << i->attached.id << ") -> Output_Reg(" << i->attached.output << ")";
119         break;
120     case V4Instr::UnaryNot:
121         INSTR_DUMP << "\t" << "UnaryNot" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
122         break;
123     case V4Instr::UnaryMinusReal:
124         INSTR_DUMP << "\t" << "UnaryMinusReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
125         break;
126     case V4Instr::UnaryMinusInt:
127         INSTR_DUMP << "\t" << "UnaryMinusInt" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
128         break;
129     case V4Instr::UnaryPlusReal:
130         INSTR_DUMP << "\t" << "UnaryPlusReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
131         break;
132     case V4Instr::UnaryPlusInt:
133         INSTR_DUMP << "\t" << "UnaryPlusInt" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
134         break;
135     case V4Instr::ConvertBoolToInt:
136         INSTR_DUMP << "\t" << "ConvertBoolToInt" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
137         break;
138     case V4Instr::ConvertBoolToReal:
139         INSTR_DUMP << "\t" << "ConvertBoolToReal" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
140         break;
141     case V4Instr::ConvertBoolToString:
142         INSTR_DUMP << "\t" << "ConvertBoolToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
143         break;
144     case V4Instr::ConvertIntToBool:
145         INSTR_DUMP << "\t" << "ConvertIntToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
146         break;
147     case V4Instr::ConvertIntToReal:
148         INSTR_DUMP << "\t" << "ConvertIntToReal" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
149         break;
150     case V4Instr::ConvertIntToString:
151         INSTR_DUMP << "\t" << "ConvertIntToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
152         break;
153     case V4Instr::ConvertRealToBool:
154         INSTR_DUMP << "\t" << "ConvertRealToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
155         break;
156     case V4Instr::ConvertRealToInt:
157         INSTR_DUMP << "\t" << "ConvertRealToInt" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
158         break;
159     case V4Instr::ConvertRealToString:
160         INSTR_DUMP << "\t" << "ConvertRealToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
161         break;
162     case V4Instr::ConvertStringToBool:
163         INSTR_DUMP << "\t" << "ConvertStringToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
164         break;
165     case V4Instr::ConvertStringToInt:
166         INSTR_DUMP << "\t" << "ConvertStringToInt" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
167         break;
168     case V4Instr::ConvertStringToReal:
169         INSTR_DUMP << "\t" << "ConvertStringToReal" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
170         break;
171     case V4Instr::ConvertStringToUrl:
172         INSTR_DUMP << "\t" << "ConvertStringToUrl" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
173         break;
174     case V4Instr::ConvertUrlToBool:
175         INSTR_DUMP << "\t" << "ConvertUrlToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
176         break;
177     case V4Instr::ConvertUrlToString:
178         INSTR_DUMP << "\t" << "ConvertUrlToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
179         break;
180     case V4Instr::ResolveUrl:
181         INSTR_DUMP << "\t" << "ResolveUrl" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
182         break;
183     case V4Instr::MathSinReal:
184         INSTR_DUMP << "\t" << "MathSinReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
185         break;
186     case V4Instr::MathCosReal:
187         INSTR_DUMP << "\t" << "MathCosReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
188         break;
189     case V4Instr::MathRoundReal:
190         INSTR_DUMP << "\t" << "MathRoundReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
191         break;
192     case V4Instr::MathFloorReal:
193         INSTR_DUMP << "\t" << "MathFloorReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
194         break;
195     case V4Instr::MathPIReal:
196         INSTR_DUMP << "\t" << "MathPIReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
197         break;
198     case V4Instr::LoadReal:
199         INSTR_DUMP << "\t" << "LoadReal" << "\t\t" << "Constant(" << i->real_value.value << ") -> Output_Reg(" << i->real_value.reg << ")";
200         break;
201     case V4Instr::LoadInt:
202         INSTR_DUMP << "\t" << "LoadInt" << "\t\t\t" << "Constant(" << i->int_value.value << ") -> Output_Reg(" << i->int_value.reg << ")";
203         break;
204     case V4Instr::LoadBool:
205         INSTR_DUMP << "\t" << "LoadBool" << "\t\t" << "Constant(" << i->bool_value.value << ") -> Output_Reg(" << i->bool_value.reg << ")";
206         break;
207     case V4Instr::LoadString:
208         INSTR_DUMP << "\t" << "LoadString" << "\t\t" << "String_DataIndex(" << i->string_value.offset << ") String_Length(" << i->string_value.length << ") -> Output_Register(" << i->string_value.reg << ")";
209         break;
210     case V4Instr::EnableV4Test:
211         INSTR_DUMP << "\t" << "EnableV4Test" << "\t\t" << "String_DataIndex(" << i->string_value.offset << ") String_Length(" << i->string_value.length << ")";
212         break;
213     case V4Instr::TestV4Store:
214         INSTR_DUMP << "\t" << "TestV4Store" << "\t\t" << "Input_Reg(" << i->storetest.reg << ") Reg_Type(" << i->storetest.regType << ")";
215         break;
216     case V4Instr::BitAndInt:
217         INSTR_DUMP << "\t" << "BitAndInt" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
218         break;
219     case V4Instr::BitOrInt:
220         INSTR_DUMP << "\t" << "BitOrInt" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
221         break;
222     case V4Instr::BitXorInt:
223         INSTR_DUMP << "\t" << "BitXorInt" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
224         break;
225     case V4Instr::AddReal:
226         INSTR_DUMP << "\t" << "AddReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
227         break;
228     case V4Instr::AddString:
229         INSTR_DUMP << "\t" << "AddString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
230         break;
231     case V4Instr::SubReal:
232         INSTR_DUMP << "\t" << "SubReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
233         break;
234     case V4Instr::MulReal:
235         INSTR_DUMP << "\t" << "MulReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
236         break;
237     case V4Instr::DivReal:
238         INSTR_DUMP << "\t" << "DivReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
239         break;
240     case V4Instr::ModReal:
241         INSTR_DUMP << "\t" << "ModReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
242         break;
243     case V4Instr::LShiftInt:
244         INSTR_DUMP << "\t" << "LShiftInt" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
245         break;
246     case V4Instr::RShiftInt:
247         INSTR_DUMP << "\t" << "RShiftInt" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
248         break;
249     case V4Instr::URShiftInt:
250         INSTR_DUMP << "\t" << "URShiftInt" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
251         break;
252     case V4Instr::GtReal:
253         INSTR_DUMP << "\t" << "GtReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
254         break;
255     case V4Instr::LtReal:
256         INSTR_DUMP << "\t" << "LtReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
257         break;
258     case V4Instr::GeReal:
259         INSTR_DUMP << "\t" << "GeReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
260         break;
261     case V4Instr::LeReal:
262         INSTR_DUMP << "\t" << "LeReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
263         break;
264     case V4Instr::EqualReal:
265         INSTR_DUMP << "\t" << "EqualReal" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
266         break;
267     case V4Instr::NotEqualReal:
268         INSTR_DUMP << "\t" << "NotEqualReal" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
269         break;
270     case V4Instr::StrictEqualReal:
271         INSTR_DUMP << "\t" << "StrictEqualReal" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
272         break;
273     case V4Instr::StrictNotEqualReal:
274         INSTR_DUMP << "\t" << "StrictNotEqualReal" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
275         break;
276     case V4Instr::GtString:
277         INSTR_DUMP << "\t" << "GtString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
278         break;
279     case V4Instr::LtString:
280         INSTR_DUMP << "\t" << "LtString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
281         break;
282     case V4Instr::GeString:
283         INSTR_DUMP << "\t" << "GeString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
284         break;
285     case V4Instr::LeString:
286         INSTR_DUMP << "\t" << "LeString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
287         break;
288     case V4Instr::EqualString:
289         INSTR_DUMP << "\t" << "EqualString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
290         break;
291     case V4Instr::NotEqualString:
292         INSTR_DUMP << "\t" << "NotEqualString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
293         break;
294     case V4Instr::StrictEqualString:
295         INSTR_DUMP << "\t" << "StrictEqualString" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
296         break;
297     case V4Instr::StrictNotEqualString:
298         INSTR_DUMP << "\t" << "StrictNotEqualString" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
299         break;
300     case V4Instr::NewString:
301         INSTR_DUMP << "\t" << "NewString" << "\t\t" << "Register(" << i->construct.reg << ")";
302         break;
303     case V4Instr::NewUrl:
304         INSTR_DUMP << "\t" << "NewUrl" << "\t\t\t" << "Register(" << i->construct.reg << ")";
305         break;
306     case V4Instr::CleanupRegister:
307         INSTR_DUMP << "\t" << "CleanupRegister" << "\t\t" << "Register(" << i->cleanup.reg << ")";
308         break;
309     case V4Instr::Fetch:
310         INSTR_DUMP << "\t" << "Fetch" << "\t\t\t" << "Object_Reg(" << i->fetch.reg << ") Property_Index(" << i->fetch.index << ") -> Output_Reg(" << i->fetch.reg << ")";
311         break;
312     case V4Instr::Store:
313         INSTR_DUMP << "\t" << "Store" << "\t\t\t" << "Input_Reg(" << i->store.reg << ") -> Object_Reg(" << i->store.output << ") Property_Index(" << i->store.index << ")";
314         break;
315     case V4Instr::Copy:
316         INSTR_DUMP << "\t" << "Copy" << "\t\t\t" << "Input_Reg(" << i->copy.src << ") -> Output_Reg(" << i->copy.reg << ")";
317         break;
318     case V4Instr::Jump:
319         if (i->jump.reg != -1) {
320             INSTR_DUMP << "\t" << "Jump" << "\t\t\t" << "Address(" << (address + size() + i->jump.count) << ") [if false == Input_Reg(" << i->jump.reg << ")]";
321         } else {
322             INSTR_DUMP << "\t" << "Jump" << "\t\t\t" << "Address(" << (address + size() + i->jump.count) << ")";
323         }
324         break;
325     case V4Instr::BranchFalse:
326         INSTR_DUMP << "\t" << "BranchFalse" << "\t\t" << "Address(" << (address + size() + i->branchop.offset) << ") [if false == Input_Reg(" << i->branchop.reg << ")]";
327         break;
328     case V4Instr::BranchTrue:
329         INSTR_DUMP << "\t" << "BranchTrue" << "\t\t" << "Address(" << (address + size() + i->branchop.offset) << ") [if true == Input_Reg(" << i->branchop.reg << ")]";
330         break;
331     case V4Instr::Branch:
332         INSTR_DUMP << "\t" << "Branch" << "\t\t\t" << "Address(" << (address + size() + i->branchop.offset) << ")";
333         break;
334     case V4Instr::InitString:
335         INSTR_DUMP << "\t" << "InitString" << "\t\t" << "String_DataIndex(" << i->initstring.dataIdx << ") -> String_Slot(" << i->initstring.offset << ")";
336         break;
337     case V4Instr::Block:
338         INSTR_DUMP << "\t" << "Block" << "\t\t\t" << "Mask(" << QByteArray::number(i->blockop.block, 16).constData()  << ")";
339         break;
340     default:
341         INSTR_DUMP << "\t" << "Unknown";
342         break;
343     }
344 }
345
346 void Bytecode::dump(const char *start, const char *end) const
347 {
348     const char *code = start;
349     while (code < end) {
350         const V4Instr *instr = reinterpret_cast<const V4Instr *>(code);
351         dump(instr, code - start);
352         code += V4Instr::size(instructionType(instr));
353     }
354 }
355
356 Bytecode::Bytecode()
357 {
358 #ifdef QML_THREADED_INTERPRETER
359     decodeInstr = QV4Bindings::getDecodeInstrTable();
360 #endif
361 }
362
363 V4Instr::Type Bytecode::instructionType(const V4Instr *instr) const
364 {
365 #ifdef QML_THREADED_INTERPRETER
366     void *code = instr->common.code;
367
368 #  define CHECK_V4_INSTR_CODE(I, FMT) \
369     if (decodeInstr[static_cast<int>(V4Instr::I)] == code) \
370         return V4Instr::I;
371
372     FOR_EACH_V4_INSTR(CHECK_V4_INSTR_CODE)
373     Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid instruction address");
374     return static_cast<V4Instr::Type>(0);
375 #  undef CHECK_V4_INSTR_CODE
376 #else
377     return static_cast<V4Instr::Type>(instr->common.type);
378 #endif
379
380 }
381
382 void Bytecode::append(V4Instr::Type type, V4Instr &instr)
383 {
384 #ifdef QML_THREADED_INTERPRETER
385     instr.common.code = decodeInstr[static_cast<int>(type)];
386 #else
387     instr.common.type = type;
388 #endif
389     d.append(reinterpret_cast<const char *>(&instr), V4Instr::size(type));
390 }
391
392 int Bytecode::remove(int offset)
393 {
394     const V4Instr *instr = reinterpret_cast<const V4Instr *>(d.begin() + offset);
395     const int instrSize = V4Instr::size(instructionType(instr));
396     d.remove(offset, instrSize);
397     return instrSize;
398 }
399
400 const V4Instr &Bytecode::operator[](int offset) const
401 {
402     return *(reinterpret_cast<const V4Instr *>(d.begin() + offset));
403 }
404
405 V4Instr &Bytecode::operator[](int offset)
406 {
407     return *(reinterpret_cast<V4Instr *>(d.begin() + offset));
408 }
409
410 }
411
412 QT_END_NAMESPACE