ab1bbfecfbb773e9165b31fbfee3e18fdc619742
[WebKit-https.git] / JavaScriptCore / VM / CodeGenerator.cpp
1 /*
2  * Copyright (C) 2008 Apple Inc. All rights reserved.
3  * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1.  Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer.
11  * 2.  Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15  *     its contributors may be used to endorse or promote products derived
16  *     from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include "config.h"
31 #include "CodeGenerator.h"
32
33 #include "BatchedTransitionOptimizer.h"
34 #include "JSFunction.h"
35 #include "Machine.h"
36 #include "ustring.h"
37
38 using namespace std;
39
40 namespace JSC {
41
42 /*
43     The layout of a register frame looks like this:
44
45     For
46
47     function f(x, y) {
48         var v1;
49         function g() { }
50         var v2;
51         return (x) * (y);
52     }
53
54     assuming (x) and (y) generated temporaries t1 and t2, you would have
55
56     ------------------------------------
57     |  x |  y |  g | v2 | v1 | t1 | t2 | <-- value held
58     ------------------------------------
59     | -5 | -4 | -3 | -2 | -1 | +0 | +1 | <-- register index
60     ------------------------------------
61     | params->|<-locals      | temps->
62
63     Because temporary registers are allocated in a stack-like fashion, we
64     can reclaim them with a simple popping algorithm. The same goes for labels.
65     (We never reclaim parameter or local registers, because parameters and
66     locals are DontDelete.)
67
68     The register layout before a function call looks like this:
69
70     For
71
72     function f(x, y)
73     {
74     }
75
76     f(1);
77
78     >                        <------------------------------
79     <                        >  reserved: call frame  |  1 | <-- value held
80     >         >snip<         <------------------------------
81     <                        > +0 | +1 | +2 | +3 | +4 | +5 | <-- register index
82     >                        <------------------------------
83     | params->|<-locals      | temps->
84
85     The call instruction fills in the "call frame" registers. It also pads
86     missing arguments at the end of the call:
87
88     >                        <-----------------------------------
89     <                        >  reserved: call frame  |  1 |  ? | <-- value held ("?" stands for "undefined")
90     >         >snip<         <-----------------------------------
91     <                        > +0 | +1 | +2 | +3 | +4 | +5 | +6 | <-- register index
92     >                        <-----------------------------------
93     | params->|<-locals      | temps->
94
95     After filling in missing arguments, the call instruction sets up the new
96     stack frame to overlap the end of the old stack frame:
97
98                              |---------------------------------->                        <
99                              |  reserved: call frame  |  1 |  ? <                        > <-- value held ("?" stands for "undefined")
100                              |---------------------------------->         >snip<         <
101                              | -7 | -6 | -5 | -4 | -3 | -2 | -1 <                        > <-- register index
102                              |---------------------------------->                        <
103                              |                        | params->|<-locals       | temps->
104
105     That way, arguments are "copied" into the callee's stack frame for free.
106
107     If the caller supplies too many arguments, this trick doesn't work. The
108     extra arguments protrude into space reserved for locals and temporaries.
109     In that case, the call instruction makes a real copy of the call frame header,
110     along with just the arguments expected by the callee, leaving the original
111     call frame header and arguments behind. (The call instruction can't just discard
112     extra arguments, because the "arguments" object may access them later.)
113     This copying strategy ensures that all named values will be at the indices
114     expected by the callee.
115 */
116
117 #ifndef NDEBUG
118 bool CodeGenerator::s_dumpsGeneratedCode = false;
119 #endif
120
121 void CodeGenerator::setDumpsGeneratedCode(bool dumpsGeneratedCode)
122 {
123 #ifndef NDEBUG
124     s_dumpsGeneratedCode = dumpsGeneratedCode;
125 #else
126     UNUSED_PARAM(dumpsGeneratedCode);
127 #endif
128 }
129
130 void CodeGenerator::generate()
131 {
132     m_codeBlock->numLocals = m_codeBlock->numVars + m_codeBlock->numParameters;
133     m_codeBlock->thisRegister = m_thisRegister.index();
134     if (m_shouldEmitDebugHooks)
135         m_codeBlock->needsFullScopeChain = true;
136
137     m_scopeNode->emitCode(*this);
138
139 #ifndef NDEBUG
140     if (s_dumpsGeneratedCode) {
141         JSGlobalObject* globalObject = m_scopeChain->globalObject();
142         m_codeBlock->dump(globalObject->globalExec());
143     }
144 #endif
145
146     m_scopeNode->children().shrinkCapacity(0);
147     if (m_codeType != EvalCode) { // eval code needs to hang on to its declaration stacks to keep declaration info alive until Machine::execute time.
148         m_scopeNode->varStack().shrinkCapacity(0);
149         m_scopeNode->functionStack().shrinkCapacity(0);
150     }
151 }
152
153 bool CodeGenerator::addVar(const Identifier& ident, bool isConstant, RegisterID*& r0)
154 {
155     int index = m_nextVar;
156     SymbolTableEntry newEntry(index, isConstant ? ReadOnly : 0);
157     pair<SymbolTable::iterator, bool> result = symbolTable().add(ident.ustring().rep(), newEntry);
158
159     if (!result.second)
160         index = result.first->second.getIndex();
161     else {
162         --m_nextVar;
163         ++m_codeBlock->numVars;
164
165         m_locals.append(index);
166     }
167
168     r0 = &m_locals[localsIndex(index)];
169     return result.second;
170 }
171
172 bool CodeGenerator::addGlobalVar(const Identifier& ident, bool isConstant, RegisterID*& r0)
173 {
174     int index = m_nextVar;
175     SymbolTableEntry newEntry(index, isConstant ? ReadOnly : 0);
176     pair<SymbolTable::iterator, bool> result = symbolTable().add(ident.ustring().rep(), newEntry);
177
178     if (!result.second)
179         index = result.first->second.getIndex();
180     else {
181         --m_nextVar;
182         m_locals.append(index + m_globalVarStorageOffset);
183     }
184
185     r0 = &m_locals[localsIndex(index)];
186     return result.second;
187 }
188
189 CodeGenerator::CodeGenerator(ProgramNode* programNode, const Debugger* debugger, const ScopeChain& scopeChain, SymbolTable* symbolTable, CodeBlock* codeBlock, VarStack& varStack, FunctionStack& functionStack)
190     : m_shouldEmitDebugHooks(!!debugger)
191     , m_scopeChain(&scopeChain)
192     , m_symbolTable(symbolTable)
193     , m_scopeNode(programNode)
194     , m_codeBlock(codeBlock)
195     , m_thisRegister(RegisterFile::ProgramCodeThisRegister)
196     , m_finallyDepth(0)
197     , m_dynamicScopeDepth(0)
198     , m_codeType(GlobalCode)
199     , m_continueDepth(0)
200     , m_nextVar(-1)
201     , m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
202     , m_lastOpcodeID(op_end)
203 {
204     codeBlock->globalData = m_globalData;
205
206     // FIXME: Move code that modifies the global object to Machine::execute.
207     
208     m_codeBlock->numConstants = programNode->neededConstants();
209     m_codeBlock->numVars = 1; // Allocate space for "this"
210
211     JSGlobalObject* globalObject = scopeChain.globalObject();
212     ExecState* exec = globalObject->globalExec();
213     RegisterFile* registerFile = &exec->globalData().machine->registerFile();
214     
215     // Shift register indexes in generated code to elide registers allocated by intermediate stack frames.
216     m_globalVarStorageOffset = -1 - RegisterFile::CallFrameHeaderSize - registerFile->size();
217
218     // Add previously defined symbols to bookkeeping.
219     m_locals.resize(symbolTable->size());
220     SymbolTable::iterator end = symbolTable->end();
221     for (SymbolTable::iterator it = symbolTable->begin(); it != end; ++it)
222         m_locals[localsIndex(it->second.getIndex())].setIndex(it->second.getIndex() + m_globalVarStorageOffset);
223         
224     BatchedTransitionOptimizer optimizer(globalObject);
225
226     bool canOptimizeNewGlobals = symbolTable->size() + functionStack.size() + varStack.size() < registerFile->maxGlobals();
227     if (canOptimizeNewGlobals) {
228         // Shift new symbols so they get stored prior to existing symbols.
229         m_nextVar -= symbolTable->size();
230
231         for (size_t i = 0; i < functionStack.size(); ++i) {
232             FuncDeclNode* funcDecl = functionStack[i].get();
233             globalObject->removeDirect(funcDecl->m_ident); // Make sure our new function is not shadowed by an old property.
234             emitNewFunction(addGlobalVar(funcDecl->m_ident, false), funcDecl);
235         }
236
237         for (size_t i = 0; i < varStack.size(); ++i) {
238             if (!globalObject->hasProperty(exec, varStack[i].first))
239                 emitLoad(addGlobalVar(varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant), jsUndefined());
240         }
241     } else {
242         for (size_t i = 0; i < functionStack.size(); ++i) {
243             FuncDeclNode* funcDecl = functionStack[i].get();
244             globalObject->putWithAttributes(exec, funcDecl->m_ident, funcDecl->makeFunction(exec, scopeChain.node()), DontDelete);
245         }
246         for (size_t i = 0; i < varStack.size(); ++i) {
247             if (globalObject->hasProperty(exec, varStack[i].first))
248                 continue;
249             int attributes = DontDelete;
250             if (varStack[i].second & DeclarationStacks::IsConstant)
251                 attributes |= ReadOnly;
252             globalObject->putWithAttributes(exec, varStack[i].first, jsUndefined(), attributes);
253         }
254     }
255 }
256
257 CodeGenerator::CodeGenerator(FunctionBodyNode* functionBody, const Debugger* debugger, const ScopeChain& scopeChain, SymbolTable* symbolTable, CodeBlock* codeBlock)
258     : m_shouldEmitDebugHooks(!!debugger)
259     , m_scopeChain(&scopeChain)
260     , m_symbolTable(symbolTable)
261     , m_scopeNode(functionBody)
262     , m_codeBlock(codeBlock)
263     , m_finallyDepth(0)
264     , m_dynamicScopeDepth(0)
265     , m_codeType(FunctionCode)
266     , m_continueDepth(0)
267     , m_nextVar(-1)
268     , m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
269     , m_lastOpcodeID(op_end)
270 {
271     codeBlock->globalData = m_globalData;
272
273     m_codeBlock->numConstants = functionBody->neededConstants();
274
275     const Node::FunctionStack& functionStack = functionBody->functionStack();
276     for (size_t i = 0; i < functionStack.size(); ++i) {
277         FuncDeclNode* funcDecl = functionStack[i].get();
278         const Identifier& ident = funcDecl->m_ident;
279
280         m_functions.add(ident.ustring().rep());
281         emitNewFunction(addVar(ident, false), funcDecl);
282     }
283
284     const Node::VarStack& varStack = functionBody->varStack();
285     for (size_t i = 0; i < varStack.size(); ++i) {
286         const Identifier& ident = varStack[i].first;
287         if (ident == propertyNames().arguments)
288             continue;
289         addVar(ident, varStack[i].second & DeclarationStacks::IsConstant);
290     }
291
292     Vector<Identifier>& parameters = functionBody->parameters();
293     m_nextParameter = m_nextVar - parameters.size(); // parameters are allocated prior to vars
294     m_locals.resize(localsIndex(m_nextParameter) + 1); // localsIndex of 0 => m_locals size of 1
295
296     // Add "this" as a parameter
297     m_thisRegister.setIndex(m_nextParameter);
298     ++m_nextParameter;
299     ++m_codeBlock->numParameters;
300     
301     for (size_t i = 0; i < parameters.size(); ++i)
302         addParameter(parameters[i]);
303 }
304
305 CodeGenerator::CodeGenerator(EvalNode* evalNode, const Debugger* debugger, const ScopeChain& scopeChain, SymbolTable* symbolTable, EvalCodeBlock* codeBlock)
306     : m_shouldEmitDebugHooks(!!debugger)
307     , m_scopeChain(&scopeChain)
308     , m_symbolTable(symbolTable)
309     , m_scopeNode(evalNode)
310     , m_codeBlock(codeBlock)
311     , m_thisRegister(RegisterFile::ProgramCodeThisRegister)
312     , m_finallyDepth(0)
313     , m_dynamicScopeDepth(0)
314     , m_codeType(EvalCode)
315     , m_continueDepth(0)
316     , m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
317     , m_lastOpcodeID(op_end)
318 {
319     codeBlock->globalData = m_globalData;
320
321     m_codeBlock->numConstants = evalNode->neededConstants();
322     m_codeBlock->numVars = 1; // Allocate space for "this"
323 }
324
325 CodeGenerator::~CodeGenerator()
326 {
327 }
328
329 RegisterID* CodeGenerator::addParameter(const Identifier& ident)
330 {
331     // Parameters overwrite var declarations, but not function declarations,
332     // in the symbol table.
333     RegisterID* result = 0;
334     UString::Rep* rep = ident.ustring().rep();
335     if (!m_functions.contains(rep)) {
336         symbolTable().set(rep, m_nextParameter);
337         m_locals[localsIndex(m_nextParameter)].setIndex(m_nextParameter);
338         result = &(m_locals[localsIndex(m_nextParameter)]);
339     }
340
341     // To maintain the calling convention, we have to allocate unique space for
342     // each parameter, even if the parameter doesn't make it into the symbol table.
343     ++m_nextParameter;
344     ++m_codeBlock->numParameters;
345     return result;
346 }
347
348 RegisterID* CodeGenerator::registerForLocal(const Identifier& ident)
349 {
350     if (m_codeType == FunctionCode && ident == propertyNames().arguments)
351         m_codeBlock->needsFullScopeChain = true;
352
353     if (ident == propertyNames().thisIdentifier)
354         return &m_thisRegister;
355
356     if (!shouldOptimizeLocals())
357         return 0;
358
359     SymbolTableEntry entry = symbolTable().get(ident.ustring().rep());
360     if (entry.isNull())
361         return 0;
362
363     return &m_locals[localsIndex(entry.getIndex())];
364 }
365
366 RegisterID* CodeGenerator::registerForLocalConstInit(const Identifier& ident)
367 {
368     if (m_codeType == EvalCode)
369         return 0;
370
371     SymbolTableEntry entry = symbolTable().get(ident.ustring().rep());
372     ASSERT(!entry.isNull());
373
374     return &m_locals[localsIndex(entry.getIndex())];
375 }
376
377 bool CodeGenerator::isLocal(const Identifier& ident)
378 {
379     if (ident == propertyNames().thisIdentifier)
380         return true;
381     
382     return shouldOptimizeLocals() && symbolTable().contains(ident.ustring().rep());
383 }
384
385 bool CodeGenerator::isLocalConstant(const Identifier& ident)
386 {
387     return symbolTable().get(ident.ustring().rep()).isReadOnly();
388 }
389
390 RegisterID* CodeGenerator::newTemporary()
391 {
392     // Reclaim free register IDs.
393     while (m_temporaries.size() && !m_temporaries.last().refCount())
394         m_temporaries.removeLast();
395
396     // Allocate new register ID.
397     m_temporaries.append(m_temporaries.size() + m_codeBlock->numConstants);
398     m_codeBlock->numTemporaries = max<int>(m_codeBlock->numTemporaries, m_temporaries.size());
399     return &m_temporaries.last();
400 }
401
402 RegisterID* CodeGenerator::highestUsedRegister()
403 {
404     while (m_temporaries.size() < static_cast<unsigned>(m_codeBlock->numTemporaries))
405         m_temporaries.append(m_temporaries.size());
406     return &m_temporaries.last();
407 }
408
409 PassRefPtr<LabelID> CodeGenerator::newLabel()
410 {
411     // Reclaim free label IDs.
412     while (m_labels.size() && !m_labels.last().refCount())
413         m_labels.removeLast();
414
415     // Allocate new label ID.
416     m_labels.append(m_codeBlock);
417     return &m_labels.last();
418 }
419
420 PassRefPtr<LabelID> CodeGenerator::emitLabel(LabelID* l0)
421 {
422     l0->setLocation(instructions().size());
423     
424     // This disables peephole optimizations when an instruction is a jump target
425     m_lastOpcodeID = op_end;
426     
427     return l0;
428 }
429
430 void CodeGenerator::emitOpcode(OpcodeID opcodeID)
431 {
432     instructions().append(globalData()->machine->getOpcode(opcodeID));
433     m_lastOpcodeID = opcodeID;
434 }
435
436 void CodeGenerator::retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index)
437 {
438     ASSERT(instructions().size() >= 4);
439     size_t size = instructions().size();
440     dstIndex = instructions().at(size - 3).u.operand;
441     src1Index = instructions().at(size - 2).u.operand;
442     src2Index = instructions().at(size - 1).u.operand;
443 }
444
445 void CodeGenerator::retrieveLastUnaryOp(int& dstIndex, int& srcIndex)
446 {
447     ASSERT(instructions().size() >= 3);
448     size_t size = instructions().size();
449     dstIndex = instructions().at(size - 2).u.operand;
450     srcIndex = instructions().at(size - 1).u.operand;
451 }
452
453 void ALWAYS_INLINE CodeGenerator::rewindBinaryOp()
454 {
455     ASSERT(instructions().size() >= 4);
456     instructions().shrink(instructions().size() - 4);
457 }
458
459 void ALWAYS_INLINE CodeGenerator::rewindUnaryOp()
460 {
461     ASSERT(instructions().size() >= 3);
462     instructions().shrink(instructions().size() - 3);
463 }
464
465 PassRefPtr<LabelID> CodeGenerator::emitJump(LabelID* target)
466 {
467     emitOpcode(target->isForwardLabel() ? op_jmp : op_loop);
468     instructions().append(target->offsetFrom(instructions().size()));
469     return target;
470 }
471
472 PassRefPtr<LabelID> CodeGenerator::emitJumpIfTrue(RegisterID* cond, LabelID* target)
473 {
474     if (m_lastOpcodeID == op_less && !target->isForwardLabel()) {
475         int dstIndex;
476         int src1Index;
477         int src2Index;
478
479         retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
480
481         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
482             rewindBinaryOp();
483             emitOpcode(op_loop_if_less);
484             instructions().append(src1Index);
485             instructions().append(src2Index);
486             instructions().append(target->offsetFrom(instructions().size()));
487             return target;
488         }
489     } else if (m_lastOpcodeID == op_lesseq && !target->isForwardLabel()) {
490         int dstIndex;
491         int src1Index;
492         int src2Index;
493
494         retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
495
496         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
497             rewindBinaryOp();
498             emitOpcode(op_loop_if_lesseq);
499             instructions().append(src1Index);
500             instructions().append(src2Index);
501             instructions().append(target->offsetFrom(instructions().size()));
502             return target;
503         }
504     }
505
506     emitOpcode(target->isForwardLabel() ? op_jtrue : op_loop_if_true);
507     instructions().append(cond->index());
508     instructions().append(target->offsetFrom(instructions().size()));
509     return target;
510 }
511
512 PassRefPtr<LabelID> CodeGenerator::emitJumpIfFalse(RegisterID* cond, LabelID* target)
513 {
514     ASSERT(target->isForwardLabel());
515
516     if (m_lastOpcodeID == op_less) {
517         int dstIndex;
518         int src1Index;
519         int src2Index;
520
521         retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
522
523         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
524             rewindBinaryOp();
525             emitOpcode(op_jnless);
526             instructions().append(src1Index);
527             instructions().append(src2Index);
528             instructions().append(target->offsetFrom(instructions().size()));
529             return target;
530         }
531     } else if (m_lastOpcodeID == op_not) {
532         int dstIndex;
533         int srcIndex;
534
535         retrieveLastUnaryOp(dstIndex, srcIndex);
536
537         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
538             rewindUnaryOp();
539             emitOpcode(target->isForwardLabel() ? op_jtrue : op_loop_if_true);
540             instructions().append(srcIndex);
541             instructions().append(target->offsetFrom(instructions().size()));
542             return target;
543         }        
544     }
545
546     emitOpcode(op_jfalse);
547     instructions().append(cond->index());
548     instructions().append(target->offsetFrom(instructions().size()));
549     return target;
550 }
551
552 unsigned CodeGenerator::addConstant(FuncDeclNode* n)
553 {
554     // No need to explicitly unique function body nodes -- they're unique already.
555     int index = m_codeBlock->functions.size();
556     m_codeBlock->functions.append(n);
557     return index;
558 }
559
560 unsigned CodeGenerator::addConstant(FuncExprNode* n)
561 {
562     // No need to explicitly unique function expression nodes -- they're unique already.
563     int index = m_codeBlock->functionExpressions.size();
564     m_codeBlock->functionExpressions.append(n);
565     return index;
566 }
567
568 unsigned CodeGenerator::addConstant(const Identifier& ident)
569 {
570     UString::Rep* rep = ident.ustring().rep();
571     pair<IdentifierMap::iterator, bool> result = m_identifierMap.add(rep, m_codeBlock->identifiers.size());
572     if (result.second) // new entry
573         m_codeBlock->identifiers.append(Identifier(m_globalData, rep));
574
575     return result.first->second;
576 }
577
578 RegisterID* CodeGenerator::addConstant(JSValue* v)
579 {
580     pair<JSValueMap::iterator, bool> result = m_jsValueMap.add(v, m_codeBlock->constantRegisters.size());
581     if (result.second) {
582         m_constants.append(m_codeBlock->constantRegisters.size());
583         m_constants.last().makeConstant();
584         m_codeBlock->constantRegisters.append(v);
585         ASSERT(m_codeBlock->constantRegisters.size() <= (unsigned) m_codeBlock->numConstants);
586         return &m_constants.last();
587     }
588
589     return &m_constants[result.first->second];
590 }
591
592 unsigned CodeGenerator::addUnexpectedConstant(JSValue* v)
593 {
594     int index = m_codeBlock->unexpectedConstants.size();
595     m_codeBlock->unexpectedConstants.append(v);
596     return index;
597 }
598
599 unsigned CodeGenerator::addRegExp(RegExp* r)
600 {
601     int index = m_codeBlock->regexps.size();
602     m_codeBlock->regexps.append(r);
603     return index;
604 }
605
606 RegisterID* CodeGenerator::emitMove(RegisterID* dst, RegisterID* src)
607 {
608     emitOpcode(op_mov);
609     instructions().append(dst->index());
610     instructions().append(src->index());
611     return dst;
612 }
613
614 RegisterID* CodeGenerator::emitUnaryOp(OpcodeID opcode, RegisterID* dst, RegisterID* src)
615 {
616     emitOpcode(opcode);
617     instructions().append(dst->index());
618     instructions().append(src->index());
619     return dst;
620 }
621
622 RegisterID* CodeGenerator::emitPreInc(RegisterID* srcDst)
623 {
624     emitOpcode(op_pre_inc);
625     instructions().append(srcDst->index());
626     return srcDst;
627 }
628
629 RegisterID* CodeGenerator::emitPreDec(RegisterID* srcDst)
630 {
631     emitOpcode(op_pre_dec);
632     instructions().append(srcDst->index());
633     return srcDst;
634 }
635
636 RegisterID* CodeGenerator::emitPostInc(RegisterID* dst, RegisterID* srcDst)
637 {
638     emitOpcode(op_post_inc);
639     instructions().append(dst->index());
640     instructions().append(srcDst->index());
641     return dst;
642 }
643
644 RegisterID* CodeGenerator::emitPostDec(RegisterID* dst, RegisterID* srcDst)
645 {
646     emitOpcode(op_post_dec);
647     instructions().append(dst->index());
648     instructions().append(srcDst->index());
649     return dst;
650 }
651
652 RegisterID* CodeGenerator::emitBinaryOp(OpcodeID opcode, RegisterID* dst, RegisterID* src1, RegisterID* src2)
653 {
654     emitOpcode(opcode);
655     instructions().append(dst->index());
656     instructions().append(src1->index());
657     instructions().append(src2->index());
658     return dst;
659 }
660
661 RegisterID* CodeGenerator::emitEqualityOp(OpcodeID opcode, RegisterID* dst, RegisterID* src1, RegisterID* src2)
662 {
663     if (m_lastOpcodeID == op_typeof) {
664         int dstIndex;
665         int srcIndex;
666
667         retrieveLastUnaryOp(dstIndex, srcIndex);
668
669         if (src1->index() == dstIndex
670             && src1->isTemporary()
671             && static_cast<unsigned>(src2->index()) < m_codeBlock->constantRegisters.size()
672             && m_codeBlock->constantRegisters[src2->index()].jsValue(globalExec())->isString()) {
673             const UString& value = static_cast<JSString*>(m_codeBlock->constantRegisters[src2->index()].jsValue(globalExec()))->value();
674             if (value == "undefined") {
675                 rewindUnaryOp();
676                 emitOpcode(op_is_undefined);
677                 instructions().append(dst->index());
678                 instructions().append(srcIndex);
679                 return dst;
680             }
681             if (value == "boolean") {
682                 rewindUnaryOp();
683                 emitOpcode(op_is_boolean);
684                 instructions().append(dst->index());
685                 instructions().append(srcIndex);
686                 return dst;
687             }
688             if (value == "number") {
689                 rewindUnaryOp();
690                 emitOpcode(op_is_number);
691                 instructions().append(dst->index());
692                 instructions().append(srcIndex);
693                 return dst;
694             }
695             if (value == "string") {
696                 rewindUnaryOp();
697                 emitOpcode(op_is_string);
698                 instructions().append(dst->index());
699                 instructions().append(srcIndex);
700                 return dst;
701             }
702             if (value == "object") {
703                 rewindUnaryOp();
704                 emitOpcode(op_is_object);
705                 instructions().append(dst->index());
706                 instructions().append(srcIndex);
707                 return dst;
708             }
709             if (value == "function") {
710                 rewindUnaryOp();
711                 emitOpcode(op_is_function);
712                 instructions().append(dst->index());
713                 instructions().append(srcIndex);
714                 return dst;
715             }
716         }
717     }
718
719     emitOpcode(opcode);
720     instructions().append(dst->index());
721     instructions().append(src1->index());
722     instructions().append(src2->index());
723     return dst;
724 }
725
726 RegisterID* CodeGenerator::emitLoad(RegisterID* dst, bool b)
727 {
728     return emitLoad(dst, jsBoolean(b));
729 }
730
731 RegisterID* CodeGenerator::emitLoad(RegisterID* dst, double d)
732 {
733     return emitLoad(dst, jsNumber(globalExec(), d));
734 }
735
736 RegisterID* CodeGenerator::emitLoad(RegisterID* dst, JSValue* v)
737 {
738     RegisterID* constantID = addConstant(v);
739     if (dst)
740         return emitMove(dst, constantID);
741     return constantID;
742 }
743
744 RegisterID* CodeGenerator::emitUnexpectedLoad(RegisterID* dst, bool b)
745 {
746     emitOpcode(op_unexpected_load);
747     instructions().append(dst->index());
748     instructions().append(addUnexpectedConstant(jsBoolean(b)));
749     return dst;
750 }
751
752 RegisterID* CodeGenerator::emitUnexpectedLoad(RegisterID* dst, double d)
753 {
754     emitOpcode(op_unexpected_load);
755     instructions().append(dst->index());
756     instructions().append(addUnexpectedConstant(jsNumber(globalExec(), d)));
757     return dst;
758 }
759
760 bool CodeGenerator::findScopedProperty(const Identifier& property, int& index, size_t& stackDepth, bool forWriting, JSValue*& globalObject)
761 {
762     // Cases where we cannot statically optimise the lookup
763     if (property == propertyNames().arguments || !canOptimizeNonLocals()) {
764         stackDepth = 0;
765         index = missingSymbolMarker();
766
767         if (shouldOptimizeLocals() && m_codeType == GlobalCode) {
768             ScopeChainIterator iter = m_scopeChain->begin();
769             globalObject = *iter;
770             ASSERT((++iter) == m_scopeChain->end());
771         }
772         return false;
773     }
774
775     size_t depth = 0;
776     
777     ScopeChainIterator iter = m_scopeChain->begin();
778     ScopeChainIterator end = m_scopeChain->end();
779     for (; iter != end; ++iter, ++depth) {
780         JSObject* currentScope = *iter;
781         if (!currentScope->isVariableObject())
782             break;
783         JSVariableObject* currentVariableObject = static_cast<JSVariableObject*>(currentScope);
784         SymbolTableEntry entry = currentVariableObject->symbolTable().get(property.ustring().rep());
785
786         // Found the property
787         if (!entry.isNull()) {
788             if (entry.isReadOnly() && forWriting) {
789                 stackDepth = 0;
790                 index = missingSymbolMarker();
791                 if (++iter == end)
792                     globalObject = currentVariableObject;
793                 return false;
794             }
795             stackDepth = depth;
796             index = entry.getIndex();
797             if (++iter == end)
798                 globalObject = currentVariableObject;
799             return true;
800         }
801         if (currentVariableObject->isDynamicScope())
802             break;
803     }
804
805     // Can't locate the property but we're able to avoid a few lookups
806     stackDepth = depth;
807     index = missingSymbolMarker();
808     JSObject* scope = *iter;
809     if (++iter == end)
810         globalObject = scope;
811     return true;
812 }
813
814 RegisterID* CodeGenerator::emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* base, RegisterID* basePrototype)
815
816     emitOpcode(op_instanceof);
817     instructions().append(dst->index());
818     instructions().append(value->index());
819     instructions().append(base->index());
820     instructions().append(basePrototype->index());
821     return dst;
822 }
823
824 RegisterID* CodeGenerator::emitResolve(RegisterID* dst, const Identifier& property)
825 {
826     size_t depth = 0;
827     int index = 0;
828     JSValue* globalObject = 0;
829     if (!findScopedProperty(property, index, depth, false, globalObject) && !globalObject) {
830         // We can't optimise at all :-(
831         emitOpcode(op_resolve);
832         instructions().append(dst->index());
833         instructions().append(addConstant(property));
834         return dst;
835     }
836
837     if (index != missingSymbolMarker()) {
838         // Directly index the property lookup across multiple scopes.  Yay!
839         return emitGetScopedVar(dst, depth, index, globalObject);
840     }
841
842     if (globalObject) {
843         m_codeBlock->structureIDInstructions.append(instructions().size());
844         emitOpcode(op_resolve_global);
845         instructions().append(dst->index());
846         instructions().append(static_cast<JSCell*>(globalObject));
847         instructions().append(addConstant(property));
848         instructions().append(0);
849         instructions().append(0);
850         return dst;
851     }
852
853     // In this case we are at least able to drop a few scope chains from the
854     // lookup chain, although we still need to hash from then on.
855     emitOpcode(op_resolve_skip);
856     instructions().append(dst->index());
857     instructions().append(addConstant(property));
858     instructions().append(depth);
859     return dst;
860 }
861
862 RegisterID* CodeGenerator::emitGetScopedVar(RegisterID* dst, size_t depth, int index, JSValue* globalObject)
863 {
864     if (globalObject) {
865         emitOpcode(op_get_global_var);
866         instructions().append(dst->index());
867         instructions().append(static_cast<JSCell*>(globalObject));
868         instructions().append(index);
869         return dst;
870     }
871
872     emitOpcode(op_get_scoped_var);
873     instructions().append(dst->index());
874     instructions().append(index);
875     instructions().append(depth);
876     return dst;
877 }
878
879 RegisterID* CodeGenerator::emitPutScopedVar(size_t depth, int index, RegisterID* value, JSValue* globalObject)
880 {
881     if (globalObject) {
882         emitOpcode(op_put_global_var);
883         instructions().append(static_cast<JSCell*>(globalObject));
884         instructions().append(index);
885         instructions().append(value->index());
886         return value;
887     }
888     emitOpcode(op_put_scoped_var);
889     instructions().append(index);
890     instructions().append(depth);
891     instructions().append(value->index());
892     return value;
893 }
894
895 RegisterID* CodeGenerator::emitResolveBase(RegisterID* dst, const Identifier& property)
896 {
897     emitOpcode(op_resolve_base);
898     instructions().append(dst->index());
899     instructions().append(addConstant(property));
900     return dst;
901 }
902
903 RegisterID* CodeGenerator::emitResolveWithBase(RegisterID* baseDst, RegisterID* propDst, const Identifier& property)
904 {
905     emitOpcode(op_resolve_with_base);
906     instructions().append(baseDst->index());
907     instructions().append(propDst->index());
908     instructions().append(addConstant(property));
909     return baseDst;
910 }
911
912 RegisterID* CodeGenerator::emitResolveFunction(RegisterID* baseDst, RegisterID* funcDst, const Identifier& property)
913 {
914     emitOpcode(op_resolve_func);
915     instructions().append(baseDst->index());
916     instructions().append(funcDst->index());
917     instructions().append(addConstant(property));
918     return baseDst;
919 }
920
921 RegisterID* CodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property)
922 {
923     m_codeBlock->structureIDInstructions.append(instructions().size());
924
925     emitOpcode(op_get_by_id);
926     instructions().append(dst->index());
927     instructions().append(base->index());
928     instructions().append(addConstant(property));
929     instructions().append(0);
930     instructions().append(0);
931     instructions().append(0);
932     instructions().append(0);
933     return dst;
934 }
935
936 RegisterID* CodeGenerator::emitPutById(RegisterID* base, const Identifier& property, RegisterID* value)
937 {
938     m_codeBlock->structureIDInstructions.append(instructions().size());
939
940     emitOpcode(op_put_by_id);
941     instructions().append(base->index());
942     instructions().append(addConstant(property));
943     instructions().append(value->index());
944     instructions().append(0);
945     instructions().append(0);
946     instructions().append(0);
947     instructions().append(0);
948     return value;
949 }
950
951 RegisterID* CodeGenerator::emitPutGetter(RegisterID* base, const Identifier& property, RegisterID* value)
952 {
953     emitOpcode(op_put_getter);
954     instructions().append(base->index());
955     instructions().append(addConstant(property));
956     instructions().append(value->index());
957     return value;
958 }
959
960 RegisterID* CodeGenerator::emitPutSetter(RegisterID* base, const Identifier& property, RegisterID* value)
961 {
962     emitOpcode(op_put_setter);
963     instructions().append(base->index());
964     instructions().append(addConstant(property));
965     instructions().append(value->index());
966     return value;
967 }
968
969 RegisterID* CodeGenerator::emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier& property)
970 {
971     emitOpcode(op_del_by_id);
972     instructions().append(dst->index());
973     instructions().append(base->index());
974     instructions().append(addConstant(property));
975     return dst;
976 }
977
978 RegisterID* CodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
979 {
980     emitOpcode(op_get_by_val);
981     instructions().append(dst->index());
982     instructions().append(base->index());
983     instructions().append(property->index());
984     return dst;
985 }
986
987 RegisterID* CodeGenerator::emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value)
988 {
989     emitOpcode(op_put_by_val);
990     instructions().append(base->index());
991     instructions().append(property->index());
992     instructions().append(value->index());
993     return value;
994 }
995
996 RegisterID* CodeGenerator::emitDeleteByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
997 {
998     emitOpcode(op_del_by_val);
999     instructions().append(dst->index());
1000     instructions().append(base->index());
1001     instructions().append(property->index());
1002     return dst;
1003 }
1004
1005 RegisterID* CodeGenerator::emitPutByIndex(RegisterID* base, unsigned index, RegisterID* value)
1006 {
1007     emitOpcode(op_put_by_index);
1008     instructions().append(base->index());
1009     instructions().append(index);
1010     instructions().append(value->index());
1011     return value;
1012 }
1013
1014 RegisterID* CodeGenerator::emitNewObject(RegisterID* dst)
1015 {
1016     emitOpcode(op_new_object);
1017     instructions().append(dst->index());
1018     return dst;
1019 }
1020
1021 RegisterID* CodeGenerator::emitNewArray(RegisterID* dst, ElementNode* elements)
1022 {
1023     Vector<RefPtr<RegisterID>, 16> argv;
1024     for (ElementNode* n = elements; n; n = n->next()) {
1025         if (n->elision())
1026             break;
1027         argv.append(newTemporary());
1028         emitNode(argv.last().get(), n->value());
1029     }
1030     emitOpcode(op_new_array);
1031     instructions().append(dst->index());
1032     instructions().append(argv.size() ? argv[0]->index() : 0); // argv
1033     instructions().append(argv.size()); // argc
1034     return dst;
1035 }
1036
1037 RegisterID* CodeGenerator::emitNewFunction(RegisterID* dst, FuncDeclNode* n)
1038 {
1039     emitOpcode(op_new_func);
1040     instructions().append(dst->index());
1041     instructions().append(addConstant(n));
1042     return dst;
1043 }
1044
1045 RegisterID* CodeGenerator::emitNewRegExp(RegisterID* dst, RegExp* regExp)
1046 {
1047     emitOpcode(op_new_regexp);
1048     instructions().append(dst->index());
1049     instructions().append(addRegExp(regExp));
1050     return dst;
1051 }
1052
1053
1054 RegisterID* CodeGenerator::emitNewFunctionExpression(RegisterID* r0, FuncExprNode* n)
1055 {
1056     emitOpcode(op_new_func_exp);
1057     instructions().append(r0->index());
1058     instructions().append(addConstant(n));
1059     return r0;
1060 }
1061
1062 RegisterID* CodeGenerator::emitCall(RegisterID* dst, RegisterID* func, RegisterID* base, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)
1063 {
1064     return emitCall(op_call, dst, func, base, argumentsNode, divot, startOffset, endOffset);
1065 }
1066
1067 RegisterID* CodeGenerator::emitCallEval(RegisterID* dst, RegisterID* func, RegisterID* base, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)
1068 {
1069     return emitCall(op_call_eval, dst, func, base, argumentsNode, divot, startOffset, endOffset);
1070 }
1071
1072 RegisterID* CodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, RegisterID* func, RegisterID* base, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)
1073 {
1074     ASSERT(opcodeID == op_call || opcodeID == op_call_eval);
1075     
1076     // Ordinarily, we might ref "func" and "base", to avoid allocating new
1077     // temporaries in the same registers. In this case, though, we actually
1078     // want the call frame we allocate to overlap "func" and "base", if they're
1079     // not otherwise referenced. op_call will read "func" and "base" before
1080     // writing out the call frame, so this is safe.
1081
1082     // Reserve space for call frame.
1083     Vector<RefPtr<RegisterID>, RegisterFile::CallFrameHeaderSize> callFrame;
1084     for (int i = 0; i < RegisterFile::CallFrameHeaderSize; ++i)
1085         callFrame.append(newTemporary());
1086
1087     // Generate code for arguments.
1088     Vector<RefPtr<RegisterID>, 16> argv;
1089     argv.append(newTemporary()); // reserve space for "this"
1090     for (ArgumentListNode* n = argumentsNode->m_listNode.get(); n; n = n->m_next.get()) {
1091         argv.append(newTemporary());
1092         emitNode(argv.last().get(), n);
1093     }
1094
1095     emitExpressionInfo(divot, startOffset, endOffset);
1096     emitOpcode(opcodeID);
1097     instructions().append(dst->index());
1098     instructions().append(func->index());
1099     instructions().append(base ? base->index() : missingThisObjectMarker()); // We encode the "this" value in the instruction stream, to avoid an explicit instruction for copying or loading it.
1100     instructions().append(argv[0]->index()); // argv
1101     instructions().append(argv.size()); // argc
1102     return dst;
1103 }
1104
1105 RegisterID* CodeGenerator::emitUnaryNoDstOp(OpcodeID opcode, RegisterID* src)
1106 {
1107     emitOpcode(opcode);
1108     instructions().append(src->index());
1109     return src;
1110 }
1111
1112 RegisterID* CodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)
1113 {
1114     ASSERT(func->refCount());
1115
1116     // Reserve space for prototype
1117     RefPtr<RegisterID> funcProto = newTemporary();
1118
1119     // Reserve space for call frame.
1120     Vector<RefPtr<RegisterID>, RegisterFile::CallFrameHeaderSize> callFrame;
1121     for (int i = 0; i < RegisterFile::CallFrameHeaderSize; ++i)
1122         callFrame.append(newTemporary());
1123
1124     // Generate code for arguments.
1125     Vector<RefPtr<RegisterID>, 16> argv;
1126     argv.append(newTemporary()); // reserve space for "this"
1127     for (ArgumentListNode* n = argumentsNode ? argumentsNode->m_listNode.get() : 0; n; n = n->m_next.get()) {
1128         argv.append(newTemporary());
1129         emitNode(argv.last().get(), n);
1130     }
1131
1132     emitExpressionInfo(divot, startOffset, endOffset);
1133     emitGetById(funcProto.get(), func, globalExec()->propertyNames().prototype);
1134
1135     emitExpressionInfo(divot, startOffset, endOffset);
1136     emitOpcode(op_construct);
1137     instructions().append(dst->index());
1138     instructions().append(func->index());
1139     instructions().append(funcProto->index());
1140     instructions().append(argv[0]->index()); // argv
1141     instructions().append(argv.size()); // argc
1142     
1143     emitOpcode(op_construct_verify);
1144     instructions().append(dst->index());
1145     instructions().append(argv[0]->index());
1146
1147     return dst;
1148 }
1149
1150 RegisterID* CodeGenerator::emitPushScope(RegisterID* scope)
1151 {
1152     m_codeBlock->needsFullScopeChain = true;
1153     ControlFlowContext context;
1154     context.isFinallyBlock = false;
1155     m_scopeContextStack.append(context);
1156     m_dynamicScopeDepth++;
1157
1158     return emitUnaryNoDstOp(op_push_scope, scope);
1159 }
1160
1161 void CodeGenerator::emitPopScope()
1162 {
1163     ASSERT(m_scopeContextStack.size());
1164     ASSERT(!m_scopeContextStack.last().isFinallyBlock);
1165
1166     emitOpcode(op_pop_scope);
1167
1168     m_scopeContextStack.removeLast();
1169     m_dynamicScopeDepth--;
1170 }
1171
1172 void CodeGenerator::emitDebugHook(DebugHookID debugHookID, int firstLine, int lastLine)
1173 {
1174     if (!m_shouldEmitDebugHooks)
1175         return;
1176     emitOpcode(op_debug);
1177     instructions().append(debugHookID);
1178     instructions().append(firstLine);
1179     instructions().append(lastLine);
1180 }
1181
1182 void CodeGenerator::pushFinallyContext(LabelID* target, RegisterID* retAddrDst)
1183 {
1184     ControlFlowContext scope;
1185     scope.isFinallyBlock = true;
1186     FinallyContext context = { target, retAddrDst };
1187     scope.finallyContext = context;
1188     m_scopeContextStack.append(scope);
1189     m_finallyDepth++;
1190 }
1191
1192 void CodeGenerator::popFinallyContext()
1193 {
1194     ASSERT(m_scopeContextStack.size());
1195     ASSERT(m_scopeContextStack.last().isFinallyBlock);
1196     ASSERT(m_finallyDepth > 0);
1197     m_scopeContextStack.removeLast();
1198     m_finallyDepth--;
1199 }
1200
1201 void CodeGenerator::pushJumpContext(LabelStack* labels, LabelID* continueTarget, LabelID* breakTarget, bool isValidUnlabeledBreakTarget)
1202 {
1203     JumpContext context = { labels, continueTarget, breakTarget, scopeDepth(), isValidUnlabeledBreakTarget };
1204     m_jumpContextStack.append(context);
1205     if (continueTarget)
1206         m_continueDepth++;
1207 }
1208
1209 void CodeGenerator::popJumpContext()
1210 {
1211     ASSERT(m_jumpContextStack.size());
1212     if (m_jumpContextStack.last().continueTarget)
1213         m_continueDepth--;
1214     m_jumpContextStack.removeLast();
1215 }
1216
1217 JumpContext* CodeGenerator::jumpContextForContinue(const Identifier& label)
1218 {
1219     if(!m_jumpContextStack.size())
1220         return 0;
1221
1222     if (label.isEmpty()) {
1223         for (int i = m_jumpContextStack.size() - 1; i >= 0; i--) {
1224             JumpContext* scope = &m_jumpContextStack[i];
1225             if (scope->continueTarget)
1226                 return scope;
1227         }
1228         return 0;
1229     }
1230
1231     for (int i = m_jumpContextStack.size() - 1; i >= 0; i--) {
1232         JumpContext* scope = &m_jumpContextStack[i];
1233         if (scope->labels->contains(label))
1234             return scope;
1235     }
1236     return 0;
1237 }
1238
1239 JumpContext* CodeGenerator::jumpContextForBreak(const Identifier& label)
1240 {
1241     if(!m_jumpContextStack.size())
1242         return 0;
1243
1244     if (label.isEmpty()) {
1245         for (int i = m_jumpContextStack.size() - 1; i >= 0; i--) {
1246             JumpContext* scope = &m_jumpContextStack[i];
1247             if (scope->isValidUnlabeledBreakTarget)
1248                 return scope;
1249         }
1250         return 0;
1251     }
1252
1253     for (int i = m_jumpContextStack.size() - 1; i >= 0; i--) {
1254         JumpContext* scope = &m_jumpContextStack[i];
1255         if (scope->labels->contains(label))
1256             return scope;
1257     }
1258     return 0;
1259 }
1260
1261 PassRefPtr<LabelID> CodeGenerator::emitComplexJumpScopes(LabelID* target, ControlFlowContext* topScope, ControlFlowContext* bottomScope)
1262 {
1263     while (topScope > bottomScope) {
1264         // First we count the number of dynamic scopes we need to remove to get
1265         // to a finally block.
1266         int nNormalScopes = 0;
1267         while (topScope > bottomScope) {
1268             if (topScope->isFinallyBlock)
1269                 break;
1270             ++nNormalScopes;
1271             --topScope;
1272         }
1273
1274         if (nNormalScopes) {
1275             // We need to remove a number of dynamic scopes to get to the next
1276             // finally block
1277             emitOpcode(op_jmp_scopes);
1278             instructions().append(nNormalScopes);
1279
1280             // If topScope == bottomScope then there isn't actually a finally block
1281             // left to emit, so make the jmp_scopes jump directly to the target label
1282             if (topScope == bottomScope) {
1283                 instructions().append(target->offsetFrom(instructions().size()));
1284                 return target;
1285             }
1286
1287             // Otherwise we just use jmp_scopes to pop a group of scopes and go
1288             // to the next instruction
1289             RefPtr<LabelID> nextInsn = newLabel();
1290             instructions().append(nextInsn->offsetFrom(instructions().size()));
1291             emitLabel(nextInsn.get());
1292         }
1293
1294         // To get here there must be at least one finally block present
1295         do {
1296             ASSERT(topScope->isFinallyBlock);
1297             emitJumpSubroutine(topScope->finallyContext.retAddrDst, topScope->finallyContext.finallyAddr);
1298             --topScope;
1299             if (!topScope->isFinallyBlock)
1300                 break;
1301         } while (topScope > bottomScope);
1302     }
1303     return emitJump(target);
1304 }
1305
1306 PassRefPtr<LabelID> CodeGenerator::emitJumpScopes(LabelID* target, int targetScopeDepth)
1307 {
1308     ASSERT(scopeDepth() - targetScopeDepth >= 0);
1309     ASSERT(target->isForwardLabel());
1310
1311     size_t scopeDelta = scopeDepth() - targetScopeDepth;
1312     ASSERT(scopeDelta <= m_scopeContextStack.size());
1313     if (!scopeDelta)
1314         return emitJump(target);
1315
1316     if (m_finallyDepth)
1317         return emitComplexJumpScopes(target, &m_scopeContextStack.last(), &m_scopeContextStack.last() - scopeDelta);
1318
1319     emitOpcode(op_jmp_scopes);
1320     instructions().append(scopeDelta);
1321     instructions().append(target->offsetFrom(instructions().size()));
1322     return target;
1323 }
1324
1325 RegisterID* CodeGenerator::emitNextPropertyName(RegisterID* dst, RegisterID* iter, LabelID* target)
1326 {
1327     emitOpcode(op_next_pname);
1328     instructions().append(dst->index());
1329     instructions().append(iter->index());
1330     instructions().append(target->offsetFrom(instructions().size()));
1331     return dst;
1332 }
1333
1334 RegisterID* CodeGenerator::emitCatch(RegisterID* targetRegister, LabelID* start, LabelID* end)
1335 {
1336     HandlerInfo info = { start->offsetFrom(0), end->offsetFrom(0), instructions().size(), m_dynamicScopeDepth, 0 };
1337     exceptionHandlers().append(info);
1338     emitOpcode(op_catch);
1339     instructions().append(targetRegister->index());
1340     return targetRegister;
1341 }
1342
1343 RegisterID* CodeGenerator::emitNewError(RegisterID* dst, ErrorType type, JSValue* message)
1344 {
1345     emitOpcode(op_new_error);
1346     instructions().append(dst->index());
1347     instructions().append(static_cast<int>(type));
1348     instructions().append(addUnexpectedConstant(message));
1349     return dst;
1350 }
1351
1352 PassRefPtr<LabelID> CodeGenerator::emitJumpSubroutine(RegisterID* retAddrDst, LabelID* finally)
1353 {
1354     emitOpcode(op_jsr);
1355     instructions().append(retAddrDst->index());
1356     instructions().append(finally->offsetFrom(instructions().size()));
1357     return finally;
1358 }
1359
1360 void CodeGenerator::emitSubroutineReturn(RegisterID* retAddrSrc)
1361 {
1362     emitOpcode(op_sret);
1363     instructions().append(retAddrSrc->index());
1364 }
1365
1366 void CodeGenerator::emitPushNewScope(RegisterID* dst, Identifier& property, RegisterID* value)
1367 {
1368     m_codeBlock->needsFullScopeChain = true;
1369     ControlFlowContext context;
1370     context.isFinallyBlock = false;
1371     m_scopeContextStack.append(context);
1372     m_dynamicScopeDepth++;
1373     
1374     emitOpcode(op_push_new_scope);
1375     instructions().append(dst->index());
1376     instructions().append(addConstant(property));
1377     instructions().append(value->index());
1378 }
1379
1380 void CodeGenerator::beginSwitch(RegisterID* scrutineeRegister, SwitchInfo::SwitchType type)
1381 {
1382     SwitchInfo info = { instructions().size(), type };
1383     switch (type) {
1384         case SwitchInfo::SwitchImmediate:
1385             emitOpcode(op_switch_imm);
1386             break;
1387         case SwitchInfo::SwitchCharacter:
1388             emitOpcode(op_switch_char);
1389             break;
1390         case SwitchInfo::SwitchString:
1391             emitOpcode(op_switch_string);
1392             break;
1393         default:
1394             ASSERT_NOT_REACHED();
1395     }
1396
1397     instructions().append(0); // place holder for table index
1398     instructions().append(0); // place holder for default target    
1399     instructions().append(scrutineeRegister->index());
1400     m_switchContextStack.append(info);
1401 }
1402
1403 static int32_t keyForImmediateSwitch(ExpressionNode* node, int32_t min, int32_t max)
1404 {
1405     UNUSED_PARAM(max);
1406     ASSERT(node->isNumber());
1407     double value = static_cast<NumberNode*>(node)->value();
1408     ASSERT(JSImmediate::from(value));
1409     int32_t key = static_cast<int32_t>(value);
1410     ASSERT(key == value);
1411     ASSERT(key >= min);
1412     ASSERT(key <= max);
1413     return key - min;
1414 }
1415
1416 static void prepareJumpTableForImmediateSwitch(SimpleJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<LabelID>* labels, ExpressionNode** nodes, int32_t min, int32_t max)
1417 {
1418     jumpTable.min = min;
1419     jumpTable.branchOffsets.resize(max - min + 1);
1420     jumpTable.branchOffsets.fill(0);
1421     for (uint32_t i = 0; i < clauseCount; ++i) {
1422         // We're emitting this after the clause labels should have been fixed, so 
1423         // the labels should not be "forward" references
1424         ASSERT(!labels[i]->isForwardLabel());
1425         jumpTable.add(keyForImmediateSwitch(nodes[i], min, max), labels[i]->offsetFrom(switchAddress)); 
1426     }
1427 }
1428
1429 static int32_t keyForCharacterSwitch(ExpressionNode* node, int32_t min, int32_t max)
1430 {
1431     UNUSED_PARAM(max);
1432     ASSERT(node->isString());
1433     UString::Rep* clause = static_cast<StringNode*>(node)->value().ustring().rep();
1434     ASSERT(clause->size() == 1);
1435     
1436     int32_t key = clause->data()[0];
1437     ASSERT(key >= min);
1438     ASSERT(key <= max);
1439     return key - min;
1440 }
1441
1442 static void prepareJumpTableForCharacterSwitch(SimpleJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<LabelID>* labels, ExpressionNode** nodes, int32_t min, int32_t max)
1443 {
1444     jumpTable.min = min;
1445     jumpTable.branchOffsets.resize(max - min + 1);
1446     jumpTable.branchOffsets.fill(0);
1447     for (uint32_t i = 0; i < clauseCount; ++i) {
1448         // We're emitting this after the clause labels should have been fixed, so 
1449         // the labels should not be "forward" references
1450         ASSERT(!labels[i]->isForwardLabel());
1451         jumpTable.add(keyForCharacterSwitch(nodes[i], min, max), labels[i]->offsetFrom(switchAddress)); 
1452     }
1453 }
1454
1455 static void prepareJumpTableForStringSwitch(StringJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<LabelID>* labels, ExpressionNode** nodes)
1456 {
1457     for (uint32_t i = 0; i < clauseCount; ++i) {
1458         // We're emitting this after the clause labels should have been fixed, so 
1459         // the labels should not be "forward" references
1460         ASSERT(!labels[i]->isForwardLabel());
1461         
1462         ASSERT(nodes[i]->isString());
1463         UString::Rep* clause = static_cast<StringNode*>(nodes[i])->value().ustring().rep();
1464         OffsetLocation location;
1465         location.branchOffset = labels[i]->offsetFrom(switchAddress);
1466 #if ENABLE(CTI)
1467         location.ctiOffset = 0;
1468 #endif
1469         jumpTable.offsetTable.add(clause, location);
1470     }
1471 }
1472
1473 void CodeGenerator::endSwitch(uint32_t clauseCount, RefPtr<LabelID>* labels, ExpressionNode** nodes, LabelID* defaultLabel, int32_t min, int32_t max)
1474 {
1475     SwitchInfo switchInfo = m_switchContextStack.last();
1476     m_switchContextStack.removeLast();
1477     if (switchInfo.switchType == SwitchInfo::SwitchImmediate) {
1478         instructions()[switchInfo.opcodeOffset + 1] = m_codeBlock->immediateSwitchJumpTables.size();
1479         instructions()[switchInfo.opcodeOffset + 2] = defaultLabel->offsetFrom(switchInfo.opcodeOffset + 3);
1480
1481         m_codeBlock->immediateSwitchJumpTables.append(SimpleJumpTable());
1482         SimpleJumpTable& jumpTable = m_codeBlock->immediateSwitchJumpTables.last();
1483
1484         prepareJumpTableForImmediateSwitch(jumpTable, switchInfo.opcodeOffset + 3, clauseCount, labels, nodes, min, max);
1485     } else if (switchInfo.switchType == SwitchInfo::SwitchCharacter) {
1486         instructions()[switchInfo.opcodeOffset + 1] = m_codeBlock->characterSwitchJumpTables.size();
1487         instructions()[switchInfo.opcodeOffset + 2] = defaultLabel->offsetFrom(switchInfo.opcodeOffset + 3);
1488         
1489         m_codeBlock->characterSwitchJumpTables.append(SimpleJumpTable());
1490         SimpleJumpTable& jumpTable = m_codeBlock->characterSwitchJumpTables.last();
1491
1492         prepareJumpTableForCharacterSwitch(jumpTable, switchInfo.opcodeOffset + 3, clauseCount, labels, nodes, min, max);
1493     } else {
1494         ASSERT(switchInfo.switchType == SwitchInfo::SwitchString);
1495         instructions()[switchInfo.opcodeOffset + 1] = m_codeBlock->stringSwitchJumpTables.size();
1496         instructions()[switchInfo.opcodeOffset + 2] = defaultLabel->offsetFrom(switchInfo.opcodeOffset + 3);
1497
1498         m_codeBlock->stringSwitchJumpTables.append(StringJumpTable());
1499         StringJumpTable& jumpTable = m_codeBlock->stringSwitchJumpTables.last();
1500
1501         prepareJumpTableForStringSwitch(jumpTable, switchInfo.opcodeOffset + 3, clauseCount, labels, nodes);
1502     }
1503 }
1504
1505 } // namespace JSC